pax_global_header00006660000000000000000000000064147611535710014524gustar00rootroot0000000000000052 comment=99b5dfc04d55d5dd0faf82a2d6ce6741ea1232b7 fheroes2-1.1.6+dfsg/000077500000000000000000000000001476115357100141655ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/.clang-format000066400000000000000000000044441476115357100165460ustar00rootroot00000000000000--- AccessModifierOffset: -4 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: Enabled: false AlignConsecutiveDeclarations: Enabled: false AlignEscapedNewlinesLeft: Right AlignOperands: true AlignTrailingComments: false AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: Empty AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: true BinPackArguments: true BinPackParameters: true BreakAfterJavaFieldAnnotations: true BreakBeforeBraces: Custom BraceWrapping: AfterClass: true AfterControlStatement: false AfterEnum: true AfterFunction: true AfterNamespace: true AfterStruct: true AfterUnion: true BeforeCatch: true BeforeElse: true SplitEmptyFunction: false SplitEmptyRecord: false SplitEmptyNamespace: false BreakBeforeBinaryOperators: All BreakBeforeTernaryOperators: true BreakConstructorInitializers: BeforeComma BreakStringLiterals: false ColumnLimit: 170 ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false FixNamespaceComments: false IncludeBlocks: Regroup IncludeCategories: - Regex: '^$' Priority: 1 - Regex: '^<' Priority: 2 - Regex: '^"' Priority: 4 IndentCaseLabels: false IndentWidth: 4 IndentWrappedFunctionNames: true JavaImportGroups: - 'java' - 'android' - 'androidx' - 'org.apache' - 'org.libsdl' - 'com.github.stephenc' KeepEmptyLinesAtTheStartOfBlocks: false MaxEmptyLinesToKeep: 1 NamespaceIndentation: All PenaltyBreakBeforeFirstCallParameter: 19937 PenaltyReturnTypeOnItsOwnLine: 19937 PointerAlignment: Middle ReflowComments: true SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInCStyleCastParentheses: false SpacesInParentheses: true SpacesInSquareBrackets: false Standard: c++17 TabWidth: 4 UseTab: Never --- Language: Cpp --- Language: Java fheroes2-1.1.6+dfsg/.clang-tidy000066400000000000000000000026061476115357100162250ustar00rootroot00000000000000Checks: >- -*, bugprone-*, -bugprone-easily-swappable-parameters, cppcoreguidelines-*, -cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-avoid-non-const-global-variables, -cppcoreguidelines-init-variables, -cppcoreguidelines-non-private-member-variables-in-classes, -cppcoreguidelines-owning-memory, -cppcoreguidelines-pro-bounds-array-to-pointer-decay, -cppcoreguidelines-pro-bounds-constant-array-index, -cppcoreguidelines-pro-bounds-pointer-arithmetic, -cppcoreguidelines-pro-type-reinterpret-cast, -cppcoreguidelines-pro-type-union-access, google-explicit-constructor, misc-*, -misc-include-cleaner, -misc-non-private-member-variables-in-classes, modernize-*, -modernize-use-auto, -modernize-use-nodiscard, -modernize-use-trailing-return-type, performance-*, -performance-avoid-endl, -performance-enum-size, readability-*, -readability-avoid-const-params-in-decls, -readability-braces-around-statements, -readability-function-cognitive-complexity, -readability-identifier-length, -readability-implicit-bool-conversion, -readability-magic-numbers CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctionsWhenCopyIsDeleted value: true - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: true - key: readability-redundant-member-init.IgnoreBaseInCopyConstructors value: true fheroes2-1.1.6+dfsg/.codechecker-ignore000066400000000000000000000003061476115357100177050ustar00rootroot00000000000000# LLVM header # cetintrin.h:49:10: 1st function call argument is an uninitialized value [core.CallAndMessage] # return __builtin_ia32_rdsspd(t); -/usr/lib/llvm-18/lib/clang/18/include/cetintrin.h fheroes2-1.1.6+dfsg/.gitignore000066400000000000000000000024421476115357100161570ustar00rootroot00000000000000# Prerequisites *.d # Compiled Object files *.slo *.lo *.o *.obj # Precompiled Headers *.gch *.pch # Compiled Dynamic libraries *.so *.dylib *.dll # Compiled Static libraries *.lai *.la *.a *.lib # Executables *.exe *.out *.app # GNU gettext *.pot *.pot~ *.po~ *.po.tmp *.po.tmp~ *.mo ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. *.suo *.sln *.vcxproj.filters *.user *.log *.ilk *.pdb *.tlog *.idb *.iobj *.ipdb *.obj *.pch *.tmp # visual studio directory .vs .vscode # Ignore Heroes of Might & Magic II game files *.agg *.mp2 *.mx2 *.h2c *.hxc *.hs *.smk *.ogg DATA/NETLODR.DAT # build directory build # fheroes2 related files files/save # Never put 'fheroes2' in this list. It breaks SonarQube analysis fheroes2.cfg # demo directory script/demo/demo /demo # Installed packages for Visual Studio VisualStudio/packages # Third-party packages for Android Studio android/app/jni/SDL2/ android/app/jni/SDL2_mixer/ android/sdl2/ # Android Studio files specific to the developer's local configuration android/local.properties android/.idea android/.gradle # Automatically created Android assets android/app/src/main/assets/ # Mac magic folders .DS_Store # Web build artifacts fheroes2.data fheroes2.js fheroes2.wasm fheroes2.wasm.map fheroes2-1.1.6+dfsg/.markdownlint-cli2.jsonc000066400000000000000000000020631476115357100206420ustar00rootroot00000000000000{ "config": { "default": true, "heading-style": { "style": "atx" }, "ul-style": { "style": "asterisk" }, "no-trailing-spaces": { "strict": true }, "line-length": { "code_block_line_length": 170, "heading_line_length": 170, "line_length": 170 }, "no-inline-html": { "allowed_elements": [ "a", "details", "img", "p", "summary" ] }, "code-block-style": { "style": "fenced" }, "code-fence-style": { "style": "backtick" }, "emphasis-style": { "style": "underscore" }, "strong-style": { "style": "asterisk" }, "table-pipe-style": { "style": "leading_and_trailing" } }, "globs": [ "**/*.md" ], "ignores": [ "cmake/README_findsdl2.md" ] } fheroes2-1.1.6+dfsg/CMakeLists.txt000066400000000000000000000151101476115357100167230ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### cmake_minimum_required(VERSION 3.24) cmake_policy(SET CMP0074 NEW) file(STRINGS ${CMAKE_SOURCE_DIR}/version.txt FHEROES2_VERSION LIMIT_COUNT 1 REGEX "^[0-9]+\.[0-9]+\.[0-9]+$") project(fheroes2 VERSION ${FHEROES2_VERSION} LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 17) include(CMakeDependentOption) include(GNUInstallDirs) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) # # Compile-time options # option(ENABLE_IMAGE "Enable the use of SDL_image (requires libpng)" OFF) option(ENABLE_TOOLS "Enable the build of additional tools" OFF) # Available only on macOS cmake_dependent_option(MACOS_APP_BUNDLE "Create a Mac app bundle" OFF "APPLE" OFF) # Should not be available if we are creating a Mac app bundle cmake_dependent_option(GET_HOMM2_DEMO "Fetch and install the HoMM II demo data" OFF "NOT MACOS_APP_BUNDLE" OFF) set(USE_SDL_VERSION SDL2 CACHE STRING "Version of the SDL library used") set(FHEROES2_DATA ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME} CACHE STRING "Path to the fheroes2 data directory (relative to CMAKE_INSTALL_PREFIX)") # For ComboBox in CMake GUI set_property(CACHE USE_SDL_VERSION PROPERTY STRINGS SDL2) # # Library & feature detection # find_package(${USE_SDL_VERSION} REQUIRED) find_package(${USE_SDL_VERSION}_mixer REQUIRED) find_package(ZLIB REQUIRED) find_package(Threads) if(ENABLE_IMAGE) find_package(${USE_SDL_VERSION}_image REQUIRED) find_package(PNG REQUIRED) endif(ENABLE_IMAGE) # # Source files # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) add_subdirectory(src) # # Translation files # if(NOT WIN32) find_program(MAKE_EXECUTABLE make) add_custom_target( translations ALL COMMAND ${MAKE_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/files/lang ) endif(NOT WIN32) # # macOS app bundle # if(MACOS_APP_BUNDLE) add_custom_target( app_bundle_h2d_files ALL COMMAND mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/Resources/h2d COMMAND cp *.h2d ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/Resources/h2d DEPENDS fheroes2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/files/data ) add_custom_target( app_bundle_translations ALL COMMAND mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/Resources/translations COMMAND cp *.mo ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/Resources/translations DEPENDS translations WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/files/lang ) add_custom_target( run_dylibbundler ALL COMMAND dylibbundler -od -b -x ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/MacOS/${PROJECT_NAME} -d ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/libs DEPENDS fheroes2 app_bundle_h2d_files app_bundle_translations WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) endif(MACOS_APP_BUNDLE) # # Installation of auxiliary files # if(NOT MACOS_APP_BUNDLE) install( DIRECTORY files/data/ DESTINATION ${FHEROES2_DATA}/files/data FILES_MATCHING PATTERN *.h2d ) install( FILES docs/README.txt LICENSE changelog.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} ) if(GET_HOMM2_DEMO) include(FetchContent) set(FETCHCONTENT_QUIET OFF) FetchContent_Declare( demodata URL https://archive.org/download/HeroesofMightandMagicIITheSuccessionWars_1020/h2demo.zip URL_HASH SHA256=12048c8b03875c81e69534a3813aaf6340975e77b762dc1b79a4ff5514240e3c ) FetchContent_MakeAvailable(demodata) file(COPY ${demodata_SOURCE_DIR}/DATA/ DESTINATION data PATTERN *.*) file(COPY ${demodata_SOURCE_DIR}/MAPS/ DESTINATION maps PATTERN *.*) install( DIRECTORY ${demodata_SOURCE_DIR}/DATA/ DESTINATION ${FHEROES2_DATA}/data FILES_MATCHING PATTERN *.* ) install( DIRECTORY ${demodata_SOURCE_DIR}/MAPS/ DESTINATION ${FHEROES2_DATA}/maps FILES_MATCHING PATTERN *.* ) endif(GET_HOMM2_DEMO) if(WIN32) install( FILES script/demo/download_demo_version.bat script/demo/download_demo_version.ps1 DESTINATION ${CMAKE_INSTALL_DOCDIR}/demo ) install( FILES script/homm2/extract_homm2_resources.bat script/homm2/extract_homm2_resources.ps1 DESTINATION ${CMAKE_INSTALL_DOCDIR}/homm2 ) install( FILES script/homm2/resource_extraction_toolset.bat script/homm2/resource_extraction_toolset.ps1 DESTINATION ${CMAKE_INSTALL_DOCDIR}/homm2 ) else(WIN32) install( DIRECTORY files/lang/ DESTINATION ${FHEROES2_DATA}/files/lang FILES_MATCHING PATTERN *.mo ) install( FILES script/demo/download_demo_version.sh PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION ${CMAKE_INSTALL_DOCDIR}/demo ) install( FILES script/homm2/extract_homm2_resources.sh PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ DESTINATION ${CMAKE_INSTALL_DOCDIR}/homm2 ) install( FILES script/packaging/common/fheroes2.metainfo.xml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo ) install( FILES src/resources/fheroes2.png DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps ) install( FILES script/packaging/common/fheroes2.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications ) endif(WIN32) endif(NOT MACOS_APP_BUNDLE) fheroes2-1.1.6+dfsg/CONTRIBUTING.md000066400000000000000000000022251476115357100164170ustar00rootroot00000000000000# Contribution and Development This repository is a place for everyone. If you want to contribute, please read more [**here**](https://github.com/ihhub/fheroes2/wiki/F.A.Q.#q-how-can-i-contribute-to-the-project). To build the project from source, please follow [**this guide**](docs/DEVELOPMENT.md). [![Build Status](https://github.com/ihhub/fheroes2/actions/workflows/push.yml/badge.svg)](https://github.com/ihhub/fheroes2/actions) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=bugs)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=code_smells)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) To assist with the graphical asset efforts of the project, please look at our [**graphical artist guide**](docs/GRAPHICAL_ASSETS.md). If you would like to help translating the project, please read the [**translation guide**](docs/TRANSLATION.md). fheroes2-1.1.6+dfsg/LICENSE000066400000000000000000000432541476115357100152020ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. fheroes2-1.1.6+dfsg/Makefile000066400000000000000000000066341476115357100156360ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Options: # # FHEROES2_STRICT_COMPILATION: build in strict compilation mode (turns warnings into errors) # FHEROES2_WITH_DEBUG: build in debug mode # FHEROES2_WITH_ASAN: build with UB Sanitizer and Address Sanitizer (small runtime overhead, incompatible with FHEROES2_WITH_TSAN) # FHEROES2_WITH_TSAN: build with UB Sanitizer and Thread Sanitizer (large runtime overhead, incompatible with FHEROES2_WITH_ASAN) # FHEROES2_WITH_IMAGE: build with SDL_image (requires libpng) # FHEROES2_WITH_SYSTEM_SMACKER: build with an external libsmacker instead of the bundled one # FHEROES2_WITH_TOOLS: build additional tools # FHEROES2_MACOS_APP_BUNDLE: create a Mac app bundle (only valid when building on macOS) # FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2) PROJECT_NAME := fheroes2 PROJECT_VERSION := $(file < version.txt) .PHONY: all clean all: $(MAKE) -C src/dist $(MAKE) -C files/lang ifdef FHEROES2_MACOS_APP_BUNDLE mkdir -p fheroes2.app/Contents/Resources/translations mkdir -p fheroes2.app/Contents/Resources/h2d mkdir -p fheroes2.app/Contents/MacOS cp src/resources/fheroes2.icns fheroes2.app/Contents/Resources cp files/lang/*.mo fheroes2.app/Contents/Resources/translations cp files/data/*.h2d fheroes2.app/Contents/Resources/h2d sed -e "s/\$${MACOSX_BUNDLE_BUNDLE_NAME}/$(PROJECT_NAME)/" \ -e "s/\$${MACOSX_BUNDLE_BUNDLE_VERSION}/$(PROJECT_VERSION)/" \ -e "s/\$${MACOSX_BUNDLE_EXECUTABLE_NAME}/fheroes2/" \ -e "s/\$${MACOSX_BUNDLE_GUI_IDENTIFIER}/org.fheroes2.$(PROJECT_NAME)/" \ -e "s/\$${MACOSX_BUNDLE_ICON_FILE}/fheroes2.icns/" \ -e "s/\$${MACOSX_BUNDLE_SHORT_VERSION_STRING}/$(PROJECT_VERSION)/" src/resources/Info.plist.in > fheroes2.app/Contents/Info.plist cp src/dist/fheroes2/fheroes2 fheroes2.app/Contents/MacOS dylibbundler -od -b -x fheroes2.app/Contents/MacOS/fheroes2 -d fheroes2.app/Contents/libs else cp src/dist/fheroes2/fheroes2 . endif clean: $(MAKE) -C src/dist clean $(MAKE) -C files/lang clean -rm -rf fheroes2 fheroes2.app fheroes2-1.1.6+dfsg/Makefile.emscripten000066400000000000000000000042251476115357100200000ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Options: # # FHEROES2_STRICT_COMPILATION: build in strict compilation mode (turns warnings into errors) # FHEROES2_WITH_DEBUG: build in debug mode # FHEROES2_WITH_THREADS: build with multithreading support # FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2) .PHONY: all clean translations all: fheroes2.js fheroes2.js: translations $(MAKE) -C src/dist PLATFORM=emscripten cp src/dist/fheroes2/fheroes2.data . cp src/dist/fheroes2/fheroes2.js . # The fheroes2.wasm.map file can also be generated in debug mode cp src/dist/fheroes2/fheroes2.wasm* . translations: $(MAKE) -C files/lang clean: $(MAKE) -C src/dist clean $(MAKE) -C files/lang clean -rm -f fheroes2.data fheroes2.js fheroes2.wasm* fheroes2-1.1.6+dfsg/Makefile.switch000066400000000000000000000043321476115357100171270ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Options: # # FHEROES2_STRICT_COMPILATION: build in strict compilation mode (turns warnings into errors) # FHEROES2_WITH_DEBUG: build in debug mode # FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2) PROJECT_TITLE := fheroes2 PROJECT_AUTHOR := fheroes2 resurrection team PROJECT_VERSION := $(file < version.txt) PATH := $(PATH):/opt/devkitpro/portlibs/switch/bin/:/opt/devkitpro/tools/bin/ .PHONY: all clean all: $(MAKE) -C src/dist PLATFORM=switch cp src/dist/fheroes2/fheroes2 fheroes2.elf nacptool --create "$(PROJECT_TITLE)" "$(PROJECT_AUTHOR)" "$(PROJECT_VERSION)" fheroes2.nacp elf2nro fheroes2.elf fheroes2.nro --icon=files/images/platform/switch/icon.jpg --nacp=fheroes2.nacp clean: $(MAKE) -C src/dist clean -rm -f fheroes2.elf fheroes2.nacp fheroes2.nro fheroes2-1.1.6+dfsg/Makefile.vita000066400000000000000000000063761476115357100166030ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Options: # # FHEROES2_STRICT_COMPILATION: build in strict compilation mode (turns warnings into errors) # FHEROES2_WITH_DEBUG: build in debug mode # FHEROES2_DATA: set the built-in path to the fheroes2 data directory (e.g. /usr/share/fheroes2) PROJECT_TITLE := fheroes2 PROJECT_TITLEID := FHOMM0002 # Version should be in XX.YY format PROJECT_VERSION := $(strip $(shell printf %02d.%02d "$$(cat version.txt | cut -s -f1 -d.)" "$$(cat version.txt | cut -s -f2 -d.)") \ $(and $(filter-out 0,$(.SHELLSTATUS)),$(error Invalid version syntax))) .PHONY: all clean fheroes2.vpk param.sfo fheroes2.elf translations all: fheroes2.vpk fheroes2.vpk: eboot.bin param.sfo translations vita-pack-vpk -s param.sfo -b eboot.bin \ --add files/images/platform/psv/sce_sys/icon0.png=sce_sys/icon0.png \ --add files/images/platform/psv/sce_sys/livearea/contents/bg.png=sce_sys/livearea/contents/bg.png \ --add files/images/platform/psv/sce_sys/livearea/contents/startup.png=sce_sys/livearea/contents/startup.png \ --add files/images/platform/psv/sce_sys/livearea/contents/template.xml=sce_sys/livearea/contents/template.xml \ --add files/data=files/data \ --add files/lang/vita_temp=files/lang \ fheroes2.vpk rm -rf files/lang/vita_temp translations: fheroes2.elf $(MAKE) -C files/lang mkdir -p files/lang/vita_temp cp files/lang/*.mo files/lang/vita_temp eboot.bin: fheroes2.velf vita-make-fself fheroes2.velf eboot.bin param.sfo: vita-mksfoex -s TITLE_ID="$(PROJECT_TITLEID)" -s APP_VER="$(PROJECT_VERSION)" "$(PROJECT_TITLE)" param.sfo fheroes2.velf: fheroes2.elf arm-vita-eabi-strip -g $< vita-elf-create $< $@ fheroes2.elf: $(MAKE) -C src/dist PLATFORM=vita cp src/dist/fheroes2/fheroes2 fheroes2.elf clean: $(MAKE) -C src/dist clean $(MAKE) -C files/lang clean -rm -f fheroes2.velf fheroes2.elf fheroes2.vpk eboot.bin param.sfo fheroes2-1.1.6+dfsg/README.md000066400000000000000000000107531476115357100154520ustar00rootroot00000000000000# fheroes2 **fheroes2** is a recreation of the Heroes of Might and Magic II game engine. This open source multiplatform project, written from scratch, is designed to reproduce the original game with significant improvements in gameplay, graphics and logic (including support for high-resolution graphics, improved AI, numerous fixes and user interface improvements), breathing new life into one of the most addictive turn-based strategy games. You can find a complete list of all of our changes and enhancements in [**its own wiki page**](https://github.com/ihhub/fheroes2/wiki/Features-and-enhancements-of-the-project).

Screenshot of the world map

Screenshot of the battle screen Screenshot of the castle screen

## Download and install Please follow the [**installation guide**](docs/INSTALL.md) to download and install fheroes2. [![Github Downloads](https://img.shields.io/github/downloads/ihhub/fheroes2/total.svg)](https://github.com/ihhub/fheroes2/releases) ## Copyright All rights for the original game and its resources belong to former The 3DO Company. These rights were transferred to Ubisoft. We do not encourage and do not support any form of illegal usage of the original game. We strongly advise to purchase the original game on [**GOG**](https://www.gog.com) or [**Ubisoft Store**](https://store.ubi.com) platforms. Alternatively, you can download a free demo version of the game. Please refer to the [**installation guide**](docs/INSTALL.md) for more information. ## License This project is licensed under the [**GNU General Public License v2.0**](https://github.com/ihhub/fheroes2/blob/master/LICENSE). Initially, the project was developed on [**sourceforge**](https://sourceforge.net/projects/fheroes2/). ## Contribution and Development This repository is a place for everyone. If you want to contribute, please read more [**here**](https://github.com/ihhub/fheroes2/wiki/F.A.Q.#q-how-can-i-contribute-to-the-project). To build the project from source, please follow [**this guide**](docs/DEVELOPMENT.md). [![Build Status](https://github.com/ihhub/fheroes2/actions/workflows/push.yml/badge.svg)](https://github.com/ihhub/fheroes2/actions) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=bugs)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=code_smells)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) To assist with the graphical asset efforts of the project, please look at our [**graphical artist guide**](docs/GRAPHICAL_ASSETS.md). If you would like to help translating the project, please read the [**translation guide**](docs/TRANSLATION.md). ## Donation We accept donations via [**Patreon**](https://www.patreon.com/fheroes2), [**PayPal**](https://www.paypal.com/paypalme/fheroes2) or [**Boosty**](https://boosty.to/fheroes2). All donations will be used only for the future project development as we do not consider this project as a source of income by any means. [![Donate](https://img.shields.io/badge/Donate-Patreon-green.svg)](https://www.patreon.com/fheroes2) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/paypalme/fheroes2) [![Donate](https://img.shields.io/badge/Donate-Boosty-green.svg)](https://boosty.to/fheroes2) ## Contacts Follow us on social networks: [**Facebook**](https://www.facebook.com/groups/fheroes2) or [**VK**](https://vk.com/fheroes2). We also have a [**Discord**](https://discord.gg/xF85vbZ) server to discuss the development of the project. [![Facebook](https://img.shields.io/badge/Facebook-blue.svg)](https://www.facebook.com/groups/fheroes2) [![VK](https://img.shields.io/badge/VK-blue.svg)](https://vk.com/fheroes2) [![Discord](https://img.shields.io/discord/733093692860137523.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/xF85vbZ) ## FAQ You can find answers to the most commonly asked questions on our [**F.A.Q. page**](https://github.com/ihhub/fheroes2/wiki/F.A.Q.). fheroes2-1.1.6+dfsg/changelog.txt000066400000000000000000004552671476115357100167000ustar00rootroot00000000000000version 1.1.6 (16 February 2025) - fix Ultimate Artifact being erased for any action done on a map - fix Editor buttons not being translated - fix an assertion regarding maximum spell points - update the French translation - update the Czech translation - add return to the Main Menu and Play Map buttons to the Editor - replace "max" text with MIN and MAX buttons for integer input dialog - check Loss conditions before Victory conditions - expand the functionality of the Adventure map event - update the Swedish translation - show a proper icon for music and audio settings when they are off - rework rendering of experience indicator - increase the maximum allowed map name length from the original 17 characters to 50 - show a range of available values in the input dialog - fix the interface not being updated in time in the Editor - show the total obelisk number while clicking on the Adventure Map object - update the Spanish translation - add a script to extract resources from CD images - fix rendering of text for several checkboxes - display monster count for the Monster object for the Editor - update the Hungarian translation - add more game options for the Editor - use a single button to switch between castle and town in the Editor dialog - make the "Week of Monster" deterministic - fix text rendering for the level-up dialog - display the chosen resource amount in the right-click popup info in the Editor - fix the Main Menu rendering after calling the Settings dialog - add a dialog pop-up when pressing standing horse - add button shine to engine-generated buttons - shorten hero name if name plus level is too long - add Undo and Redo icons in the Editor - show the Artifact description window when clicking on it in the Editor - add info about 50% retaliation damage to the Blind spell description - update Hero Movement button - fix Mine flag rendering on the Adventure Map - fix a crash in the View World mode for the Editor - add dialog to choose between Auto Combat and Quick Combat - fix the project version not being properly displayed in the PSV port of the engine - fix overlap of the FPS info and popup message in the Editor - fix selected Ore mine resetting in the Mine placement dialog - fix the Hideous Mask behavior causing neutral units to never flee - fix issues with pressed button states on the battle screen - improve morale UI for the undead army - update the background image for the PSV port of the engine - display spell name in the dialog for spell casting error - remove additional passability marks on the bottom part of tiles - improve side tile passability logic - modify Button layout to be similar to the original game - Android: gracefully handle errors when the system chooser does not start for some reason - add swap army and swap artifacts to the heroes meeting screen - expand Text Support mode for New Map selection dialogs version 1.1.5 (30 December 2024) - add 3 new variants of the Observation Tower object - show Monster and Artifact names in the popup dialog of the Editor - show the minus sign for the numeric keypad only if a range allows the use of negative values - fix Spell Scroll artifact horizontal position on the Adventure Map - update the Portuguese translation - update the Swedish translation - fix the spell cost displayed in the quick info window when a hero has an artifact that reduces this cost - add the ability to set Secondary Skills in Witch's Hut inside the Editor - fix the mouse interaction in the Editor's spell selection and castle properties windows - fix cursor positioning with non-English characters and improve positioning at the end of the line - display a description of the mechanics of right-clicking on devices with touch input - fix assertion while loading different maps in the Editor - add the ability to edit spells in Pyramid inside the Editor - add the ability to set the amount in the Resource object in the Editor - add the ability to set spells in Shrine in the Editor - add a new variant of Stone Liths object - update the Russian translation - show a warning dialog upon map file loading failure - fix spell randomization logic for Artifacts and the Adventure Map objects - fix text input cursor setting for multi-line text input with many spaces at the line end - fix scrollbars being shifted while changing resolution on the Adventure Map - reset the damage info popup when spellcasting is cancelled - fix a bug when picking up an object whose type does not match its sprite on the map - update the Hungarian translation - add range values for default experience within the Editor - add missing CP1254 button letters - fix French and German ultimate staff sprite with PoL assets - updated the Czech translation - update the Turkish translation - improve the castle reinforcement logic for AI - synchronize the maximum allowed number of characters for input and the Virtual Keyboard - fix PS Vita touchpad usage - add file support for non-quite-POSIX-compliant filesystems (such as Amiga FS) - put several dialog box headers in order - enable the number input dialog for the recruitment window - use the platform-dependent byte order for the SDL audio format version 1.1.4 (27 November 2024) - add Virtual Numpad support for integer inputs - add new Lean-To object variant - update the Czech translation - add Belarusian language support for the Virtual Keyboard - improve & speed up the translation-related logic - update the German translation related to the Price of Loyalty Campaign - update the Swedish translation - update initial passability logic - fix the attack value estimation for a Hypnotized unit with the ALL_ADJACENT_CELL_MELEE_ATTACK ability - improve the retreat logic for archers - update the Portuguese Translation - fix overlapping text in the High Scores dialog - add support of Evil interface for the Scenario Information dialog - fix the penalty calculation for enemy units that can evade the engagement during battle - fix passability for several objects on maps made the original Editor - center Magic Book artifact on the Adventure Map - speed up ICN image decoding - do not download the wing32.dll for HoMM2 demo version - add u with two dots to buttons and translate and improve German buttons version 1.1.3 (23 October 2024) - fix invalid behavior and crash during interaction with whirlpools by heroes on boats - fix French small font i with circumflex - add Czech Virtual Keyboard support - fix rendering of overlapped UI elements - shorten map title when too long in several places - add missing popup dialogs to buttons within View World mode - update the Hungarian translation - speed up language switching I/O operations - update the Swedish translation - fix Sorceress Statue construction fade-in animation - fix map titles not being cleared when changing map - add language support for fh2m map format - update the Portuguese translation - use an original image to draw hexagons on the battlefield - improve Dismiss button for French and Spanish languages - fix event handling for dialogs in No Interface mode - improve error handling for I/O operations - increase most of object selection windows in the Editor by 50 pixels - update army information after battle before showing any dialogs - add missing sand animation for hourglass while waiting for a turn - speed up AI calculations on the Adventure Map - improve AI decision making while using Dimension Door spell - ease object requirements while erasing them in the Editor - split long phrases into two lines for battle log - fix blinking arrow cursor during scrolling in Editor - properly show damage info pop-up dialog for 2-hex monsters during battle - make default knowledge value for random hero 1 - fix inability to erase monsters on the map under certain conditions within the Editor - fix the triggering of invalid drag events for the game area when casting certain spells - fix out of mini-map mouse dragging behavior in the Editor - update the Russian translation - add vertical gradient fonts - add a popup dialog to the list of resolutions - allow to resize vertical buttons for translations - fix issues with non-English path detection on Windows - center sprites and text in adventure map treasure chest dialog - do not discard area selection while moving mouse out of the map in the Editor - fix a crash while trying to distribute an army with 1 unit version 1.1.2 (15 September 2024) - preserve the order of artifacts when adding the Spell Book to the artifacts bag - update the Portuguese translation - speed up MIDI file processing - update the German translation - update visited status for Tree of Knowledge object - update New Secondary Skill dialog - add an extra check to verify the game resources not being corrupted - update the Hungarian translation - limit the use of the Summon Boat by AI for the original maps - do not create an undo action in the Editor if nothing was changed for an object - allow to undo any castle modifications in the Editor - improve AI castle protection logic on the Adventure Map - render mirrored troop in dialog properly - update resources before showing construction animation inside castle dialog - update the Swedish translation - fix the audio playback and distance calculation in the 3D Audio mode - fix Cliff Nest glowing pixel - update Earthquake spell animation and improve its logic to allow bridge and nearby towers demolition - disable mouse popup for empty space in map selection window - fix AI heroes ignoring patrol limit - AI should determine best skill when leveling up heroes - update hero spell points indicator after the battle and before performing defeated opponent fade animation - fix creature and header overlap in recruit window - fix map special conditions render after drop list is closed - implement alliances in the Editor - fix original maps bottom layer (hacky) placed resources and artifacts - add Backslash character to normal and small fonts - add missed Small Cliff (Dirt terrain) to the Landscape Miscellaneous objects in the Editor - add Ukrainian language virtual keyboard - fix inability to save maps within the Editor for some installations - add monster statistics popup window inside the Editor monster information dialog - Android Toolset: add Russian translation for FH2M file manager - fix Anti-Magic spell description - update the Polish translation - fix mini-map updates while picking up certain objects on the Adventure Map - fix invalid animation while picking up an artifact hidden by another object on the Adventure Map - remove scouting & movement bonuses for AI-controlled players - fix rendering issues in mine selection dialog for the Editor - allow to input "/", "*", "-", "+" and "." from the keypad - add new River Deltas objects - add Slovak virtual keyboard support - update the Russian translation - fix lagging input controls on some devices - AI: properly evaluate the enemy heroes defending the castles version 1.1.1 (13 July 2024) - update the Russian translation - properly set tile information upon placing a new object - update the Hungarian translation - implement special victory and loss conditions for heroes and towns - add Evil theme for ADD, EDIT and DELETE buttons in the Editor - fix object UID restoration after Redo operation in the Editor - add support for double click within Sphinx, Daily Events and Rumors lists - show date description for daily events - allow to disable any building in castles and towns in the Editor - add Find Artifact victory condition in Editor - add popup messages for right clicking on special map conditions - restrict obelisk placement to 48 objects - update logic related to human player selection for maps - fix crash when entering an empty line in text boxes - fix town placement over action objects - allow normal victory for "Accumulate gold" condition - fix the display of identical artifacts captured in battle - Magic Book window: show the maximum number of spell points - add "Out of Time" and "Accumulate Gold" map conditions within the Editor - add support of editing daily events within the Editor - show pressed monster button on Editor panel while clicking on it - add hotkey for passability within the Editor - add color names to Traveller's Tent and Barrier objects within object selection window - reduce castle area for mouse right clicking inside Editor's castle selection window - update map type popup message by right clicking to include Resurrection maps - add a new variation of Cave object on the Adventure Map - change hero selection dialog in the Editor - add an ability in the Editor to edit Rumors for maps - bring the logic of the Summon Boat spell for the human player in line with its logic of operation in the case of AI - AI: fix the assertion failure when visiting an object that is impossible to stand on - fix castle and hero radar rendering in the Editor - fix Magic Garden being shown without animation within the Editor - speed up save file loading and saving operations - add '?' symbol to Virtual Keyboard - properly check the Price of Loyalty resources in order to enable the Editor - move an existing object in front while trying to place an exact one on the same tile in the Editor - generate a random hero portrait for the Editor - fix crash when a hero is killed defending a castle - differentiate Random Castle and Town names in the Editor - update the Swedish translation - fix invalid logic for setting random artifacts - put the Graveyard object to the correct category, "hide" the alternative versions of Graveyard sprites - remove the AI unit growth bonuses and tune the income bonuses for different difficulty levels - limit the minimum slider length to 15 pixels - update the Portuguese translation - fix hero editing assertion - update the Ukrainian translation - fix random artifact types - implement the file manager for FH2M maps in Android - force use the non-typeable hotkeys for text input dialog and allow starting a new line in multiline texts - fix Editor instruments' buttons rendering - AI: properly handle the Spell Book artifacts on the Adventure Map - add missing checks for Miscellaneous objects in the Editor - add missing Sphinx part - fix text editing crash - fix crash when using quick switch to hero when castle is current object - fix the evaluation of the DOUBLE_SHOOTING and DOUBLE_MELEE_ATTACK abilities version 1.1.0 (22 May 2024) - properly connect Streams and Deltas while placing Streams - do not allow placing Ultimate Artifact on non-diggable terrain in Editor - use golden color to highlight cells that are sometimes possible to edit - set the last edited map file as default for the new Standard game - allow picking-up the Magic Book artifact from the Adventure Map - show a warning message for no modification of normal artifacts - show a warning message that streams and roads cannot be placed on water - fix Editor interface items positions when Hide Interface mode is enabled in the engine - speed up object erasure in the Editor - allow only English to be used for text input within the Editor - add a general text for action objects with no metadata - display object coordinates in the right mouse click popup window - implement Event details window in the Editor - add generated buttons for map file dialog - make Editor panel buttons change good/evil interface - fix std::string serialization - implement base functions of Map Specifications dialog for the Editor - update the Swedish translation - add UI window to edit Sphinx properties - change a message while trying to get another Magic Book - fix the flickering of the map filter buttons in the map selection dialog - add an extra space between UI elements in the monster separation window - implement simple Save Map dialog for the Editor - properly handle objects while changing terrain in the Editor - properly connect roads and castles in the Editor - add a multi-line text editing feature to edit Sign and Bottle texts in the Editor - fix software cursor show delay - allow Events to be placed on Water within the Editor - remove Editor's beta flag - add Editor icon to the Main Menu - add a window to enter Random Ultimate Artifact radius - describe all Adventure Map objects used in the game - add relaxed requirements for object placement in the Editor - add a shortcut to go to the Main Menu from the Editor - allow river deltas to be placed anywhere in the Editor - implement Castle/Town details dialog in the Editor - add logic to handle victory and loss conditions for maps made by the Editor - fix typo in Hot Seat maximum players value - update the Russian translation - update the Portuguese translation - add a window to change Monster properties in the Editor - add the jailed hero details dialog in the Editor - implement hero details dialog in the Editor - do not add scaled resolutions for PS Vita - avoid extra I/O operations while changing game's settings - change the text in the monster separation window - introduce new object types: Swampy Lake and Frozen Lake - fix wrong name for Neutral race troops - update the Romanian translation - update the Ukrainian translation - use the AI pathfinder to assess the threat of enemy heroes instead of relying on the region database - update the Hungarian translation - fix hero battle info text X offset - make the default left and right hotkeys select skills in the level up dialog - add Editor related options - update the Spanish translation version 1.0.13 (16 March 2024) - fix Sphinx title offset - add a window telling about demo version being used - add possibility to "draw" the attack angle between two hexes on touch screens - fix double daily resources award - fix rendering flaws of battle journal when using scroll bar - update the French translation - fix delayed cursor in campaign briefing dialog - add convenient list scrolling for touch screens - fix army split dialog text overflowing the dialog and add troops name - fix multiple objects and add missing ones in the Editor - fix a crash with AI hero animation - fix the troops carry over mechanics for campaign - update the Ukrainian translation - update the Swedish translation - update the Danish translation - kingdom Overview screen: automatically update status of castle dwellings that have just been built or upgraded - update the Vietnamese Translation - fix the mechanics of Genie special ability - add multiline stats in hero info window in battle - update the Hungarian translation - update the Spanish translation - fix many typos and improve English strings - add info about ranged penalty elimination to archery skill description - update combat disabling dialog text - adjust the difficulties of campaign scenarios that were hard-coded in the original game - update the resource panel immediately after a purchase in a castle - speed up application loading - add a feature to align the text non-uniformly - make several buttons text adapted and fix okay button redraw - add quick hero switch feature to the adventure map interface - cursor update code improvements - fix accidental map scrolling after exiting castle/hero screen - auto combat toggling improvements version 1.0.12 (07 February 2024) - update the Russian translation - update the Spanish translation - correct icons alignment on the hero meeting screen - update the Polish translation - fix the retaliation of archers attacked by an ally under the influence of Berserker or Hypnotize spells, improve the AI usage of Hypnotize spell in general - fix incorrect Artesian Spring evaluation by the AI - make rules for AI surrender and retreat more unified - fix Oasis object passability - always offer one native hero at the beginning of a new week - puzzle and View World dialogs rendering improvements - implement Landscape Miscellaneous (non-action) objects placing in Editor - fix OKAY button translation for Interface Settings dialog after any setting change - make the AI not to know what objects contain - fix issue when Blind or Paralyze has been applied to a hypnotized unit during its turn - implement Adventure (action) Miscellaneous objects placing in Editor - tune the AI performance at different difficulty levels - add surrender cost to battle result dialog - improve overall image processing performance - update spell points, formations and artifacts descriptions - add infos on the cost of surrender - allow AI units covering an archer with the AREA_SHOT capability to attack neighboring units on their own - use proper name for PoL campaign in High Scores - use CP1257 code page for Lithaunian - offer the Wisdom skill to the heroes of "magic" classes on a mandatory basis at least once every three level-ups - implement Mountains, Rocks and Trees placing in the Editor - make the AI attack human heroes that have a greater chance to win than the AI heroes - implement Power-ups object placement in the Editor - allow AI units that ignore retaliatory strikes to attack neighboring enemy units while covering archers - avoid visiting Oasis and Watering Hole objects by AI heroes if they bring no benefit - make AI hero behavior depend on the time spent on the map - improve fog discovery by the AI heroes - adjust text in the skill popup dialog - implement Mines placing in the Editor - improve AI hero interaction with Witch's Hut object - allow the AI-controlled hero to surrender if his kingdom has sufficient gold reserves - add text width-adapted CANCEL button, change to StandardWindow for Resolution, Language, Adventure, File and Scenario Info dialogs - update Hungarian translation - add dwellings into the Editor - fix rare fog of war rendering issues - allow AI heroes to surrender if the conditions of retreat have been met, but it is impossible to retreat - implement the AI logic to transfer the slowest troops to the garrison at the end of the turn to try to get a movement bonus on the next turn - mark fheroes2 as DPI-aware on Windows - speed up image loading - speed up file loading and reduce memory usage on the Adventure Map - improve the AI logic for pay-to-hire dwellings on the Adventure Map - improve the AI heuristics of covering shooters when using defensive tactics - update buttons and add popup windows for them in Battle Only mode - use the "cautious offensive" tactics for AI only against melee-only armies without the distant attack potential (including damage spells) - update the Swedish translation - fix heroes with no names - add base code to load new map format files - use singular Mine form for the corresponding object - fix inaccurate Jail object removal - add missing rules for the plural in Hungarian language - restrict secondary skill name and level to the UI area - fix too wide text in quick hero info dialog - hide swap army/artifact buttons in the Battle Only mode - update several text descriptions - add Campfire object in the Editor - take into account SHIFT and CAPS LOCK being used at the same time - make radar rendering optimization - fix the AI spell damage estimation logic for units immune to the given spell - rework editor instrument groups: add new buttons, rework instrument panel, add evil interface - fix multiple spellbook-related issues in the Battle Only mode - update French translation - show an error when it is not possible to save a game on a hard disk version 1.0.11 (23 December 2023) - improve the logic of AI defensive tactics - add Tree of Knowledge claimed and cost info to quick info dialog - add a different object popup window logic for the Editor - implement town and castle placing in the Editor - update the Spanish translation - update the French translation and add missing offset for an A with accent - update Bulgarian translation - increase width and height of the Campaign Difficulty selection dialog - make speed of fade-in & fade-out animations for AI-controlled heroes dependent on the AI speed setting - speed up battle pathfinder logic - update Spanish translation - add Spanish and Portuguese button font letters - fix invalid focus update after AI hero battle - update Danish translation - speed up the original map format reading - fix a crash with castle overlapping inside a map - add basic logic to load and save maps through Editor UI - add text rendering within a given ROI - do not show quick info for hidden buttons inside castle building info dialog - add missing AI team alliance to Evil campaign's 6th scenario - update Swedish translation - update Hungarian translation - update Vietnamese Translation - fix update of the morale/luck indicator when changing the hero in the Battle Only mode - add base map file format for the Editor - add Hotkeys categories for the future UI improvements - fix scroll location on file deletion - rework Battle Only mode - add cell selection in Details mode for the Editor - speed up map loading for New Game - allow application closure by close button if no resources available - fix multi-font text offset calculation - properly evaluate potential attack positions for wide units - correctly manage touch device events - add ability to place Ocean Objects within the Editor version 1.0.10 (18 November 2023) - update Russian translation - rework Town Portal dialog - add artifact placement in the Editor - make Oracle dialog use selected interface mode (Good/Evil) - add treasure placement in the Editor - update hero status after digging on the Adventure Map - fix player names overlapping in Oracle and Thieves' Guild dialogs - fix dialog frames not being consistent for the same size windows - speed up monochrome cursors loading - fix rendering issue in Kingdom Overview dialog while dismissing a hero - fix castle and hero lists' updates after dismissing a hero in Kingdom Overview dialog - fix invalid attack positions from moat during battle - add support for right SHIFT, CTRL and ALT hotkeys - AI takes into account the spell immunity when calculating the effectiveness of mass damage spells - update Hungarian translation - fix incorrect AI estimation for moves during battle when a battlefield contains objects - update Vietnamese translation - fix several issues with loading ICN resources - add support for the future new heroes - fix the logic of purchasing a boat in a shipyard - increase the priority of those enemy units that have not yet got their turn, for proper AI decision making - add hero action button image - fix spelling in campaign text - display 0 shots during battle for archers with no shots left - fix random generator in normal and auto-combat modes - fix castle dialog rendering issues - adjust welcome window text at the first game launch - teach AI to use the marketplace to accelerate the development of their castles - update German translation - implement erase tool in the Editor - fix recruit dialog's MIN/MAX buttons when switching between creature upgrades - update Swedish translation - show proper Quick Info window for a hero during battle - fix troops' sprites overlapping in quick info - prioritize hiring those heroes whose portraits are not used by scenario specific heroes version 1.0.9 (11 October 2023) - add "tent visited" info to barrier quick info dialog - update Vietnamese translation - rework Hot-Keys dialog - fix combat victory window creature position - Town Gate and Town Portal spells: use depersonalized wording - add an ability to place heroes in the Editor - add an ability to place Random Monsters in the Editor - fix rendering of very long scenario names in the campaign briefing dialog - disable the not implemented Random Map option in the Editor - update German translation - make a long press on the "continue movement" button to reset a hero's path - use the "continue movement" button to interact with an object a hero is standing on - make Grass the default terrain for new maps in the Editor - restrict heroes' meetings and army merging on Easy difficulty - AI should avoid splitting troops on Easy difficulty - add functionality to place monsters in the Editor - add a mirror image check during spell evaluation - teach battle AI to use shield spells - implement streams' placing in the Editor - adjust AI combat spell heuristics - fix rendering of long text in the Hero screen status bar - update Ukrainian translation - implement roads' placing in the Editor - fix the AI first strike logic - update Hungarian translation - fix battle AI protecting paralyzed archers - properly display player's name in the New Game window - fix memorizing the position in the map list when changing the map size filter - adjust the position of luck and morale icons in the hero info window - update the followers window to support text mode - fix the logic of ALWAYS_RETALIATE regarding paralyzed units - add historical changes support for the Editor - add the ability to confirm actions in battle for touch devices - update Russian translation - fix Editor Main Menu hotkeys - update Swedish translation - speed up overall rendering for cycling animation - do not render text beyond the info and status bars during battles - rework game settings on the Adventure Map - remove double spaces in translatable texts - update Bulgarian translation - update Slovak translation - update Czech translations - update Danish translation - use Home and End hotkeys to navigate among items within a list - always use the nearest cell to attack the nearby unit if a monster is under the Berserker spell - fix an assertion when a hero starts moving and a player immediately mouse left clicks on the Adventure Map - improve path calculations by AIWorldPathfinder in planning mode - Wand of Negation should grant immunity against the Mass Dispel spell version 1.0.8 (11 September 2023) - fix number placeholders not being replaced in campaign spell bonus texts - fix spell rendering issues when words are divided in the middle - fix ? symbols appearing in single-line texts - generate vertical high scores buttons - display missing resource dialog for at least 5 seconds - show only skills that the hero does not already have in battle only skill selection list - show highscores after multiplayer game - improve the logic of kiting enemies with archers - update Vietnamese translation - update Hungarian Translation - adjust the description of the Eagle Eye skill - fix an empty gap in between lines in buttons font - update Russian translation - translate disabled buttons and reset them when changing languages - make vertical buttons translatable - implement terrain transitions in Editor - rework the Save/Load game dialog to allow variable dialog size and support Evil interface - change Army Order to Turn Order - Add Czech to original resource exception - do not close File options menu on cancelling load game dialog - fix foreign pixels on snow battlefield objects - do not try to scout the area if the hero is in jail and gets an artifact assigned using the map editor - update Slovak translation - cancel Hut of Magi reveal area animation when a player clicks any button - show the "You have been eliminated from the game" message in the multiplayer game - add small skill icons for Xanadu visit dialog - fix invalid logic for some objects on water - update Polish translation - speed up map, translation and save files loading - fix missing hero and town name in dialogs for non-English languages - fix Load/Save file title position and color - change Shipyard construction message - expand clickable area for settings in the Main Menu - shift text in Surrender window - show ... in Load/Save File dialog for long names - fix monster name position in monster info dialog - speed up rendering for specific buttons - fix multiple rendering issues in the Kingdom Overview dialog - adjust text for Quick Info dialogs - improve fading animation using Redmean color distance calculation - limit Dimension Door spell usage for AI heroes on lower difficulties - center text in hero battle info window - add A and O with diaereses to CP1252 button font - fix size of the button letter Æ - improve Mage guild status message for learnt spells - add "New Month!" title for new month - add "Victory!" title to victory dialog - update Danish translation - update Ukrainian translation - allow early exit from puzzle map during reveal animation - remember map filter selection until you quit the game - improve the distance estimation when an AI-controlled hero passes through objects on the map - update Swedish translation - AI heroes should decline battles if passing by - implement basic terrain draw in Map Editor version 1.0.7 (15 August 2023) - properly update uncovered fog with all hero actions - fix an issue when AI hero "jumps back" during the fog discovery - AI heroes should not know what exactly a Treasure or Sea Chest contains - do not play simultaneous walk/fly sounds for battle speed 9 and 10 - do not handle an event on the map twice - fix AI estimation of the castle garrison strength for priority tasks - rework "select from list" dialogs and also make all elements within dialogs right clickable - battle AI should switch to offense mode instead of passing turns - update Russian translation - add the ability to export and import save files in Android Toolset application - make many in-game buttons translatable - fix Army info button in level up dialog - update Ukrainian translation - update German translation - add Summon Boat spell support for AI - rephrase various game dialogs - add a dialog to confirm auto combat - add "Quit" title to quit dialog - fix Zounds grammar - update Norwegian Translation - the Shield spell should not affect the damage of the castle towers - apply AI growth bonus only on first AI player turn - show "cast down" animation for heroes on the battlefield - apply Cure & Mass Cure spells only if the target unit is either damaged or has negative magical effects - fix hero last frame delay after the spell casting animation - speed up several spell animations during battle - fix missing first animation frame of heroes on the battlefield - change heroes animation speed on the battlefield - fix puzzle screen exit button theme - reduce CPU usage while rendering castle's Well dialog - fix campaign buttons' rendering issues - make campaign buttons translatable - update Slovak translation - update Danish translation - update Swedish translation - disable Campaign button if no campaign resources are present - improve AI pathfinding logic regarding protected and guarded tiles - avoid engine execution with corrupted video files - add ability to select instrument brush and brush size in Editor UI - make thieves guild adapt background to chosen interface - fix a possible crash in Android toolset application version 1.0.6 (15 July 2023) - allow to lower the campaign difficulty during playthrough - update Russian translation - reduce CPU usage while rendering High Score dialog - add some missing horizontal buttons to translations - fix missing redraw in Battle Only dialog after cancelling hero selection - fix last hotkey not showing up in the hotkey dialog - add Dismiss hotkey to hero screen - create basic Map Editor GUI - update Polish translation - add checks for object reachability when calculating their value for AI heroes - fix AI logic for visiting Shrines and Arena - correct spell value estimation for AI heroes - fix a case when a dead AI hero was trying to reinforce army in a castle - update priorities for AI heroes based on battle outcome and fog uncover events - rework the spell generation in castles' Mage Guilds - update Spanish translation - speed up Armageddon spell rendering - fix invalid pixels in multiple images from the original resources - speed up resource loading - update Slovak translation - do Main Menu fade-in before showing first game run - fix the fade effect on the "View World" screen - properly restore environment sounds and terrain music after opening a castle dialog from the Kingdom Overview screen - fix cases when false symbols appear after the blinking cursor in text input dialog - rework game credits to keep aspect ratio - add extra windows and greying out conditions for Summon Boat spell - fix several button text placements and button press rendering version 1.0.5 (14 June 2023) - improve AI castle defensive strategy on Adventure Map - fix rating in campaign congratulations text in win video - update Danish translation - adjust battlefield Idle and Flag animation speed and avoid setting 0 animation delay for battlefield actions - show the currently selected bonus in the campaign scenario UI if the campaign scenario is already in progress - update Polish translation - add shadows for the Virtual Keyboard buttons - fix okay button not being redrawn in battle options dialog - improve army distribution in castles for AI players - make the text input cursor blink and add the ability to set the cursor position anywhere in the edited string - move jobless AI heroes into castles on a last day of a week - fix monster upgrade logic when AI was wasting resources for nothing - do not check whether a hero can cast a spell if spellcasting is prohibited in principle - fix AI heroes behavior ignoring empty castles with commanders - speed up AI decision making on Adventure Map - fix Magellan's Maps visit by AI heroes when discovered objects were not being added for exploration - fix missing logic for AI heroes to meet each other in the middle of a turn - reduce unit growth bonus for AI - do not play the same kill/wince sounds simultaneously - allow AI heroes to retreat when the kingdom has full house of heroes and when there are enough resources on the next turn - fix a crash when AI heroes capture a dwelling protected by monsters - add Editor Main Menu (only for development builds) - fix the Skeleton passability - fix the logic for defeated heroes in campaign scenarios - fix the logic of recognizing objects guarded by neighboring monsters - update hero's path after inspecting a castle - add Evil interface version of Monster recruitment dialog - update Bulgarian translation - add screen fade effect for transiting between game sections - add a check to avoid a crash for corrupted game resources - fix the rendering of the number of units during the castle siege - update Russian translation - speed up battlefield rendering - fix incorrect spell efficiency display for resurrection spells - set music type to MIDI if no MUSIC directory exist - fix cases with dropping audio volume when MUSIC directory is not present - fix crashes for Android devices due to using a buggy third-party package - fix cases when AI ignores some objects during path evaluation - use 22050 sound sample rate for PS Vita to fix high CPU load - add diacritic signs to CP-1250 button font - update Slovak translation - update Ukrainian translation - fix Android version for Android 7 or lower devices - do not reset castle or heroes scrollbars when hero moves version 1.0.4 (13 May 2023) - add Polish and Russian languages support for Virtual Keyboard - fix absence of delay after animating creature wince and before making next move - make haunt, set elemental guardian, identify hero and visions spells gray out when cannot be used - do not stop hero's movement after the first Dimension Door jump - do not show that enemy town or castle has no garrison if kingdom has no Thieves' Guilds - fix idle animation lag while casting any spell - fix creature idle animation freeze during Blind / Paralyze spell casting - fix an issue that caused an AI-controlled hero standing next to Stone Liths to block the path of another AI-controlled hero standing on these Stone Liths - add checks to detect corrupted data resources - improve the resource value estimation algorithm for AI - fix logic and reward of Daemon Cave object for AI - add an ability to cancel waiting for the end of the pre-battle sound - update Polish translation - create small and large obstacles on the battlefield at the same time - do not make an empty text line at the end of phrase and fix text rendering in a wider area than given maximum width - fix Battlefield animations freeze while waiting for Good Luck sound to end - add popup windows for monster dialog buttons - fill main menu with background when we do not stretch the main menu main image - update Russian translation - fix not returning to load menu while switching between campaign scenarios - fix Shipwreck Survivor bonuses - fix AI pathfinding when Spell Scroll was considered as an artifact which requires to defeat an army - rework logic for all Adventure Map objects' metadata - fix adventure map fog reveal on campaign scenario restart and when loading a Hot Seat save made in the first game day - adjust spell info message when hero has zero (0) mana - fix calculation of castle towers strength for AI - improve dialog titles related to losing the game - update Bulgarian translation - strategic AI economy update - AI should check for castles and funds before retreat - fix software cursor freezes during certain fading animations - rework the search algorithm for available scaled resolutions - show map ratings in victory video, add subtitles and color fading animation - add extra checks to prevent loading renamed MX2 maps on demo version - add "End Turn" title to dialog when heroes can move and you are ending your turn - catapult and castle towers should still act, even if there are no troops in the respective armies capable of taking any action - update Vietnamese translation - fix the behavior of Berserk and Hypnotize spells - add language support for highscores - expand wide screen support - properly handle absolute and relative paths in the CDDrive registry key for Windows scripts - update Danish translation - update Swedish translation - reset battlefield grid cursor position after using the spell book - fix a crash on deleting last save file - update Czech translation - update Slovak translation - update Ukrainian translation - fix recurring global events - redraw the status window after the amount of kingdom resources has changed at the beginning of the day - do not render hero/boat over the bottom map border - add "New week!" title to dialog showing start of a new week version 1.0.3 (11 April 2023) - update German translation - update Norwegian translation - preparations for Google Play Market release - add missing frame for hero information dialog when it is opened from hero meeting dialog - improve the destination indication for Teleport spell - translate more UI buttons within the game - fix endless jumping AI hero behavior while using Dimension Door spell - add Virtual Keyboard open button to Save Game and Player Name dialogs - add values to Morale and Luck stats within artifact description - show approximate information about the mine guardians to a non-owner player - adjust number of resources subtracted in event messages - fix projectile render position when hitting the target creature - reduce AI obsession with Wells - optimize object priority logic for AI heroes to prioritize more important locations - remove path icon after a hero/boat makes a turn, not before - show mirrored monster image in army order - make hotkey names translatable - improve AI fog discovery logic - fix a case when a hero has the same secondary skill but different levels of it set by an author of a map - add gold missing in Statue and Dungeon building description - add Vietnamese translation - fix the number of regenerated spell points with the Mysticism skill - focus on the AI hero before he disappears due to boarding a boat or using a Dimension Door or Town Portal spell - add legacy game detection on Windows x64 - fix clicks in Android MIDI music - speed up Adventure Map rendering - fix AI hero animation being interrupted while moving inside a fog for the current player - fix Alchemist Lab flag and Ghosts from Abandoned Mine rendering while rest of the object is not visible on the screen - fix boat's shadow being rendered over a boat while sailing diagonally - adjust recruitment window position on castle well and kingdom overview - apply the commanding hero/captain bonuses to the castle towers - fix the number of raised skeletons by Necromancy after battle - update Polish translation - fix incorrect number of Ghosts present in Abandoned and Haunted Mines - add Slovak translation - properly handle the situation when wandering monsters and an AI hero eliminate each other - update battle log with special abilities of Vampire Lords and Ghosts - update Belarusian translation - add numeric speed of monsters in information window - fix quick info for non-action objects when their action tile is under fog - block Chain Lightning if first target unit resists the spell - fix cases when Road sprite is drawn over a hero - fix Hero shadow rendering on Adventure Map - update Russian translation - show Spell Points for spells in Magic Book popup dialogs - fix necromancy and calculation of casualties with mirrors - properly track the Mirror Image spell duration - update documentation about Android - update Czech translation - update Swedish translation version 1.0.2 (12 March 2023) - fix display of Haunted Mines on mini-map and in View World - update the Norwegian translation - allow resurrected units to act on the current turn if they have not yet had their turn - add missing part of Captain's Quarter in Sorceress Town - allow to resurrect Elementals - fix the battle casualty report when non-true Resurrect spell was used during battle - redraw hero icons to display movement bar change before action dialog box is shown - fight the guardians on dwellings on Adventure Map only once per game - change the logic of reinforcement of the guest hero's army during the castle defence - do not show Dragon City on mini-map - summon boat spell will only summon friendly boats - allow the player to refuse to level up in the Tree of Knowledge even if this level up is for free - add virtual keyboard support for touch devices - grey out Summon Boat, Town Gate and Town Portal spells if they cannot be used - clean up AI priority tasks if attacker was killed - update sounds used while visiting dwellings on Adventure Map - add logic of AI heroes using town portal - add missing symbols to button font - update Polish translation - fix high CPU usage during battle while using highest animation speeds - fix battle AI tactics estimation - fix pathfinding not being updated after revealing the fog on visiting Magellan's Map - animate lighthouse in lighthouse dialog - fix the experience calculation for AI-controlled heroes while visiting Tree of Knowledge - add a frame for a hero portrait on the quick info dialog - add missing experience being displayed in the Tree of Knowledge window - fix music effects while visiting an empty object on Adventure Map - display the world date for save files - rework AI hero task priority logic - fix invalid popup window being displayed while clicking on an empty hero list area within Adventure Map - add Graphics option icon - fix corner cases of fog rendering - fix invalid calculation of AI path leading to a crash - show sleeping hero icon for hero's portrait within castle dialog - speed up rendering on Adventure Map - properly restore the screen after closing the hero dialog during combat - render background between HEROES and TOWNS/CASTLES buttons in Kingdom Overview window - fix possible random crashes during the gameplay - fix Iron and Steel Golems animation issues - show kingdom income when gold per day income is clicked within Kingdom Overview window - fix a crash while visiting a castle after an ally captured it - speed up file searching on Windows - fix the spell id calculation for a spell scroll while loading a map - fix puzzle map window position - fix View World default adventure map position - memorize zoom level of the View World screen - fix inability to move monsters after Good Morale event - fix unintended ability to upgrade troops during battle - fix huge CPU usage in hero window during battle - redevelop standard window generation logic - update Bulgarian translation - fix volcano sounds - update Russian translation (main menu and dialog buttons) - fix issue with the puzzle rendering - fix musical effects for various objects - fix stereo audio playing in SMK files - add letter "Ў" and "’" sign to Cyrillic (cp1251) button font - add lighthouse information popup in kingdom overview - fix an invalid option for scenario 1 of Roland Campaign - optimize mini-map rendering - update Czech translation - add proper hotkeys option icon - fix title in German translation - optimize View World rendering - add tooltip damage info for single target attack spells during battle version 1.0.1 (08 February 2023) - add the ambient sound for Abandoned Mine - add support for scaled resolutions - instantly update status bar in battle for hero's dialog options - fix invalid Kingdom income calculation - fix incorrect status bar update call - update Czech translation - add German and Russian translations of Android Toolset - Android Save File Manager: implement filtering of save files by type - fix scroll bar bottom position when dragging and fix high FPS rate when dragging scroll bar by mouse - make a narrower button font for cp-1251 (Cyrillic) characters - fix Druid projectile start position for shooting up - add PS Vita fixes and gamepad mapping improvements - add Danish translation - fix shooters projectile position during battle - fix high CPU load on Adventure map when Hero speed is set to Jump - Android toolset: add the ability to browse & delete save files - fix loss of the first frame in the after attack unit animation - update spell points for campaign heroes at the start of a scenario - uncover the fog during the hero's instantaneous movement only if the hero is actually moving - do not allow to dig for Ultimate Artifact second time - show spell effect animation so as not to cover the front troops - fix screen restoration after closing monster info dialog - fix the AI resurrect spell logic - fix the Dimension Door shadow on resolutions 640+x480 & 640x480+, temporarily hide auxiliary panels in "no interface" mode - rework pathfinding algorithm during battle to fix non-optimal paths for monsters - add Mossy Rock object which appears only on Swamp terrain while in the original game this object has no name - optimize Adventure Map rendering - do not do redundant redraws when dragging Adventure Map with the mouse - fix walking animations of certain monsters - fix the bridge operation when a wide friendly unit steps on it from the moat - fix creature wince animation for low morale and Lich cloud cases during battle - optimize Holy Shout spell effect rendering during battle - allow wide units to take a step back during battle - fix certain Peasant Huts being displayed as Thatched Huts with no ambient sounds on Adventure Map - update Polish translation - avoid excessing CPU usage for multiple windows in the game - set audio frequency to 44100 on Windows to avoid cracking sounds during playback - add fh2 toolset application on Android to help with setting up the main application - update French translation - reduce CPU usage in Select Language dialog - fix a case when external music was not being played on Ubuntu - fix incorrect logic for monster placement on Adventure Map - update German translation - do not lowercase creature name (or other string) when it is put first in phrase - fix forced Idle animation after switching to Static animation - fix screen flickering in SDL2 - optimize Death Wave spell effect rendering during battle - automatically assemble artifacts sets if their parts were captured in the battle - fix controller support for PS Vita - add a full stop, A and E characters with accents for CP1252 button font version 1.0.0 (21 December 2022) - add Ubuntu ARM support - update Polish translation - update the French translation - fix incorrect resource placements on certain maps - adjust "Battlefield Casualties" vertical position - fix bridge logic after morale event - enable the instant battle by default - optimize rendering in multiple places - update the Norwegian translation - add global hotkey to toggle the text support mode - make the regular small buttons translatable - make Trade button in Marketplace window disabled by default - add popup windows for monster recruit dialog - fix animation of slowed flying creatures - fix multiple hero related awards for campaigns - fix Death Wave, Holy Shout and Holy Word spell animations - do not mirror corpses of defeated troops during battle - fix rendering an extra empty line for specific texts - fix monster idling animation during battle - use logarithmic scale of sound volume - enable touch support for all devices - make separate hotkeys to cast battle & adventure spells - add the "Quit game" hotkey - handle hotkeys in the Adventure Map's File dialog - optimize defensive strategy for AI castles - fix black area not being rendering during video playback - reduce priority for bottles in sea for AI - make File Dialog and Adventure Dialog buttons translatable - do not stop object animation during AI turn - update Russian translation - fix text rendering for game option's names of certain translations - fix incorrect battlefield image restoration in the place of the previous damage popup - adjust several button font characters - rework the hotkeys concerning the hero movement - make the Main Menu's dialog buttons translatable for specific languages - display the amount of gold in the diplomacy dialog - show object animation during Hut of Magi visit - fix Dwarves death animation - fix very slow hero movement animation when moving a cursor with software cursor rendering - fix translated Cancel button in monster recruit dialog being switched to English - fix animation of bridge destruction during battle - fix the smoke animation when demolishing a castle building during battle - improve Adventure Map rendering performance - fix multiline word splitting for short phrases with a long first word - fix position of left barbarian's captain quarters part - reset the cursor position at the start of 'human turn' - add an option to toggle screen scaling type - recreate the original rainbow animation during battle - fix Scenario Info window elements - improve hexagon shading during battle - add Danish language option and font - improve rendering speed with software cursor rendering - fix French and Italian characters not being shown with their assets - set the minimum supported version to Android 5.1 - introduce AI Scout role - fix fullscreen mode with DPI higher than 100% on Windows - fix multi-monitor fullscreen support on Windows - update Bulgarian Translation - add Android installation and usage documentation - fix the scenario info dialog position - generate resizable buttons for both interfaces - fix inability to toggle V-Sync option dynamically - do not show resolution dialog on handheld devices on the first startup - add mouse right click simulation on touchscreen devices - fix cursor being too small for certain resolutions - disable Adventure Map scrolling for handheld devices by default - change battlefield hexagon generation to match the original - make fullscreen mode as a default state for Android devices - implement all troops transfer between armies within castle dialog - scroll Adventure Map with mouse left button pressed - use parabolic catapult projectile flight trajectory - update credits page - always show the Ultimate Artifact behind one of the last four central pieces of the puzzle - update captain's mana on map load and when building the Captain's Quarters - remove and integrate the rest of experimental options - always center text when a maximum width is provided - fix UI elements for the unhired hero popup window - update Ballista and Turrets damage information when they are destroyed - correctly reflect the change of fullscreen mode in the graphics settings dialog when it was toggled using a hotkey version 0.9.21 (12 November 2022) - fix audio playback issues on Windows OSes - do not show any hero status for AI heroes - add hotkeys for moving armies between heroes - update the Norwegian translation - fix monster upgrade cost formula - reset AI hero meeting flag every time if hero's strength has changed - add missing alliance conditions for the Succession Wars campaign last scenarios - add small optimizations for the pathfinding algorithm - fix incorrect evaluation of army strength where hero's abilities should not be taken into account - fix handicap income calculation - add right click quick info in more dialogs for hero and castle captain - fix possible assertion hit for campaign scenario info dialog - Luck / Morale related objects are now reset after meeting / battle for AI heroes - add a separate graphics options window - make more contrast for player objects on the minimap - do not override hero or castle selection focus on a game load - change language selection window to support many languages - improve the combat log's use of plural forms - draw the correct arrows for the paths on the adventure map - rework the troops arrangement mechanics for the castle defense - fix catapult's boulder animation - update position for text in difficulty selection dialog - add CP1252 French quotation marks - clear the kingdom's visited objects according to their lifetime, even if this kingdom has already been vanquished - update AI logic for monster distribution and recruitment - do not increase the number of upgraded creatures on Week Of/Month Of basic creatures - generate new MAX/MIN buttons for other languages - add Czech language option in game and add fonts - fix the troop splitting logic - include project's resource files into Android packages - translate language names in native language - add proper CP1250 font - update French translation - do not waste time to get useless monsters for an AI army - add audio support for Android devices - take Magic Book into account while visiting a castle by an AI hero - avoid using armies with 1 monster for AI heroes - lock the screen orientation to landscape for Android devices - fix campaign score sorting issue - fix an issue when kingdom overview scrollbar does not not remember last position - fix terrain colors on the minimap - memorize selected Scenario in Scenario Selection dialog - do not overwrite default platform's soundfonts if none is included into the package - update Hungarian translation - add Hungarian language option and font replacements - fix the shade used for mountains and trees - fix UI elements position in Select Scenario dialog - fix hero's fight cursor offset - fix heroes position on battle screen - add Android compilation - update Russian translation - redraw the castle's resource panel when a hero purchases the spellbook - add Dutch font and language option - update language dependent resources while changing language - update Bulgarian Translation - fix the Week Of / Month Of logic - update Belarusian translation - fix button font generation for original buttons version 0.9.20 (10 October 2022) - add Russian and French button translations - update the Norwegian translation - recalculate the hero's path when the hero was selected with the mouse - fix stopped music in events of quickly closing dialogs with internal music - add proper logic for artifact exchange between AI heroes - add Dutch translation - do not let the archers perform a double attack if they are out of ammo - add Hotkey support for restarting Campaign's Scenario - AI heroes now use spells from scrolls - fix neutral town unit growth - display detailed information about the composition of alliances in the scenario info window - add date to logging for the future bug fixing - add turkish translation - make sure that there is a place for the Ultimate Artifact in the artifact bag before trying to dig it out - do not ask player's name if the score is too low for High score board - add Romanian translation - hide console window for Windows OSes and add log file for this platform - add Romanian font and language option - update Polish translation - add Turkish language option and CP1254 font - add proper icons for Petrification spell - speed up Adventure Map rendering - take into consideration a case with full artifact bag while checking AI hero's path - generate button fonts for different code pages - apply usual rules for unit growth in neutral towns/castles with custom troops - decrease monster growth bonus for AI - fix incorrect usage of Dimension Door by AI heroes - make logging for monster movement in battle more user-friendly - add UI improvements of the Settings dialog - fix logic of processing cells containing units available for possible AI unit attack - fix incorrect object evaluation for AI heroes on boats - add a feature to give human player control to AI (debug build only) - make creature names lowercased for certain dialogs - generate new Gift button - generate full button English alphabet and new Battle Only button - fix switching of terrain music in case of hero loss - update Bulgarian translation - add Handicap feature for single and multiplayer games - fix a case when a hidden scrollbar during battle is visible for one frame - fix sound volume for objects while using external music type - include rating calculation for Campaign's high score - fix incorrectly rendered monochrome cursor for campaign selection window - update French translation version 0.9.19 (11 September 2022) - add popup dialogs for Well's buttons - generate MIN button based on newly added font - fix constantly moving AI heroes when they have nothing to do - update Polish translation - implement some improvements when exchanging an army between heroes - show intro videos like in the original game - fix messages displayed for captains during battle - update Bulgarian translation - correct start resources for AI players - add a popup dialog for Days spent info within campaign dialog - make Artifact evaluation for AI more granular - add Difficulty selection for Campaigns - add popup dialogs for mage guild and scenario info windows - fix rendering of Mine Guardians - do not show monsters and campfires on Puzzle screen - fix moving AI hero rendering - implement instant finishing of battles - update Norwegian translation - fix incorrect rendering of some icons in The Price of Loyalty campaign windows - make "Show terrain penalty" option the default - fix double income from captured objects - fix the distribution of Mutant Zombies in the Graveyard - fix the battle order after bad morale events - always use the current color of a unit when toggling auto battle (take the Hypnotize spell into account) - speed up file search on case-insensitive file systems - optimize Mini-map rendering - do not show boats on puzzle image - fix a possible crash in UI window - fix castle rendering on Mini-map - fix Ultimate Artifact placement conditions - fix rendering of towns for View Towns spell - fix tall object rendering version 0.9.18 (10 August 2022) - speed up rendering of Mini Map area - fix missing shadows from path arrows when they are on the edge of screen - render correct digging holes for terrains - add monster fading animation when both wandering monsters and hero are dying after a battle - fix incorrect boat fading animation - do not show digging holes on Puzzle Map - fix out of view rendering of boats and heroes - fix Ultimate Artifact digging conditions - fix the logic of joining monsters for free and for money - do not draw objects over the map edge if they are in fog - fix cases of boats being shifted when a hero boards it - fix wrong rendering priority of Hero and Jail - do not render shadow of a tall monster over another monster nearby - properly render trees and Sawmill - fix Fountain being displayed over a moving hero, not under - fix certain shadows of objects being too dark - fix cases when hero's flag was not being displayed properly when a hero stands near a tall object - fix cases when some parts of heroes being displayed over other objects - fix monsters being displayed over mountains - draw a flag over Magic Garden object - draw Adventure Map decors in the same way as in the original game - fix flag rendering priority from Windmill - fix incorrect moving boat rendering in relation to other boats - fix boat being cut near Magellan Maps object - fix incorrect boat rendering priority - fix wasteland terrain object displayed over hero's sprite - fix Mine's flag being displayed over a hero - fix cases when a moving hero being drawn over other heroes - fix cases when some parts of a ship can be seen through terrain objects - fix cases when hero overlaps ship while passing nearby - hero does not step on route arrows anymore - fix the pre-battle arrangement of neutral troops - add separate sound font for SDL 2 builds - fix paused music being played with old music volume while restarting it - fix hero starting experience values - fix amount of experience from Tree of Knowledge - fix missing retaliation delay after last animation frame - fix music being too quiet while fast switching between music types (Windows OS) - fix crashes on Windows 8 using MIDI music - fix external audio not always returning to on after turning volume to zero (Windows OS) - fix horse's steps being faded while crossing terrain border using MIDI sound (Windows OS) - fix sound volume being lower during combat (Windows OS) - fix no sounds situation when music is off even when sounds are not (Windows OS) - show correct hero's level and experience on level up - fix incorrect castle's area leading to wrong castle's info - add missing window frame for hero's dialog during level up - fix number of ghosts and splitting for Shipwreck, Haunt and Abandoned Mine cases - update Bulgarian Translation - update treasure chest AI decision logic - fix a case when a hero got 2 Magic Books - update Russian and Hungarian translations - add support for loading of MIDI sound fonts - show upgraded monster images in Adventure Map objects upon a successful upgrade - fix redrawing of the status window in cases when the hero's army or the castle garrison change without changing focus - make best AI fighter as a champion - update Polish translation version 0.9.17 (11 July 2022) - fix possible crashes during sound playback - always ask about rewriting an existing save file - allow to remap Hotkeys within the game - fix distance evaluation during Scouting - fix invalid logic when neutral monsters whose number was set in the Editor did not grow at all - add The Price of Loyalty team to credits - show a window stating about missing video files for campaigns - fix the class of a hero named Joseph - fix extra shadow being drawn for Hero Screen dialog on high resolutions - align File Options dialog position - fix Campaign Window button flickering - fix missing column of pixels in Map Scenario Info window - update French translation - allow different translations of "Red Tower" - implement AI courier hero role for better logistics - fix situation when MIDI music still continues to play during fast switching between music types - fix case when Adventure Map sounds are still being played while opening Main Menu - AI should keep some creatures in reserve for castle defence - update Ukrainian translation - update Norwegian translation - increase Genie special ability to 20% like it is done in the original game and correct log messages during battle - remember the last open page in Spell Book during battle - fix possible synchronization issues for audio playback - enhance AI logic towards defending its castles - improve usage of spell on Adventure Map by AI - fix displaying of negative resources in dialog - fix situations when AI was hiring too many heroes - respect the Ultimate Artifact's radius specified by the map creator - update Polish translation - fix the castle's well build logic for AI - align hero's button in level-up dialog - fix scenarios when ambient sounds from Adventure Map objects are still played while opening a castle's window - fix cases when Random Monsters appear from a different level due to invalid format of an object on the map - update Mine's sprite properly after defeating Ghosts in Abandoned Mine - fix multiple issues related to hero's info popup window and updating his position on a mini-map - update sounds and music before a hero making an action - add an environmental sound for Freeman's Foundry - add initial implementation of true "Evil" interface in the game - add missing Ultimate Artifact successful digging sound - do not play pre-battle sound if sounds are off - fix potential thread-access issues for Nintendo Switch - fix possible inter-thread race for Adventure Map Status window - fix a delay in game while crossing a terrain and playing MIDI music version 0.9.16 (12 June 2022) - add Flatpak support - add Belarusian translation - swap spell icons for Death Wave and Death Ripple - make the "no interface" mode more usable - add music resume ability for MP3, OGG and FLAC formats - update translation guide - replace "C with cedilla" with "latin C" in the French translation - do not auto-save at the end of a turn if the player has been vanquished on that turn - fix Puzzle window exit button rendering - add sound for rocks in water with seagulls - fix Sorceress captain purchase building rendering - fix issues with Romanian translation - properly deal with human-only colors in single player mode - fix the invalid behavior of "no interface" mode - introduce 3D audio option - change adventure map environment sounds for every step hero moves - fix boats being considered as free tiles - if attacker is able to attack multiple targets at once and has a built-in spell, then this spell should be applied to any (but only one) of the targets - fix some typos in translation texts - take into account AI hero's role during meeting - fix false highscore entry while cancelling to continue a campaign - highlight latest highscore after completion scenario/campaign - show evil resolution icon for Evil interface - add truncated shadow to Scenario Information window - generate missing parts of Red Tower sprite - fix incorrect tiles being marked as road - fix multiple cases while using Mirror Image and Summon Elemental spells - fix the victory/defeat verification logic - update error message if hero tries to open a spell book and does not have one - improve status text if only one troop is selected - fix inability to add new entries with similar high scores - add Campaign high scores - fix dwelling popup window on adventure map - make AI to be aware about map conditions - fix incorrect hero icon in adventure interface - do not show languages with empty translations - add Swedish language option and font support - update Ukrainian translation - well MAX buy: add condition for not enough room, make recruitment happen in guest hero's army too, more text flexibility - add Portuguese language option and initial font generation - speed up AI turn - impose a limit of turns for an attacking AI-controlled hero - cache AI hero's and neutral monsters' strength during AI turn - add initial Spanish language support - make castle's flags for Knight and Wizard factions appear in a correct color - add window header for campaign awards and bonuses - update German translation - fix plural forms translation for some languages - fix character filtering when generating the save file name - update Polish translation - fix Red Tower rendering with Rainbow - expand Hotkey usage on adventure map - fix German font support version 0.9.15 (07 May 2022) - add HotKey window and expand the list of system options - do not allow higher-level Mage Guilds to be built if the previous-level Mage Guild has not been built yet - Battle Only mode: always assign a random spell to the Spell Scroll - add initial support for Romanian language - add more conditions to define a blocking AI hero - fix incorrect video playback on Descendants campaign, scenario 5 - change some descriptions of campaign awards and bonuses - do not auto save after the completion of the last scenario in a campaign - add images and full description of bonuses and awards by right mouse click - fix some incorrect campaign bonuses - display None if no awards available for the current scenario - add hot keys to select bonuses - fix rendering of campaign UI window as it was very slow on response on changing bonuses - fix missing kingdom income value for scenarios with additional bonus resources - game type interface for campaign window must be unique and should not depend on overall game interface - allow already selected scenario to appear in ALL scenarios list - improved Week of the creature window - changed town portal's text and condition to be similar to town gate - update Russian translation - properly extract animations from the GOG distribution of HoMM2 for Windows - update French translation - improve search for video files - add text truncation method to be used in campaign's choices and awards - encourage AI to explore more - redesign Hot Key event file handling - add double-lined headers to adventure map options - add Belarusian, Bulgarian and Ukrainian languages support - populate resolution list based till the lowest resolution - fix 1000 and 100000 short values display - update hero quick info popup dialog - disable Town Portal dialog OK button by default - changed AI's turn to be repeated multiple times for heroes - generate French 'MIN' button - generate French 'GIFT' button - add Translation Context for Secondary Skill Campaign Bonuses - add Ogre Alliance and Dwarfbane full strings for translation - fix the positioning of the damage info popup - update Norwegian translation - fix calculation of morale & luck modifiers for in-castle army without a commander - properly calculate the number of travel days to the destination tile for a hero - AI should replenish lost spell points more frequently - do not allow a hero to have multiple spell books in the "Battle Only" mode - fix rendering of the Arm of the Martyr's shadow - AI uses View All spell to scout fog - hero should have at least 69MP to cast Dimension Door, Town Gate and Town Portal spells - fix spacing of player squares in Select Recipients window and properly center resource icons for "Your Funds" and "Planned Gift" horizontally - fix French small font Cedilla c rendering - update Polish translation - reserve half of AI spell points for Dimension Door spell - hero should be able to cast spells that consume movement points if he is able to move from his current tile - fix MP3 support in Windows SDL1 packages - reset the mixer volume before playing video soundtracks - expand Test Support mode to cover all campaign related actions - add Black-White cursor support - add music control options to the configuration dialog - fix failing music file search - properly work with guardians on the objects that can be captured - fix call to get secondary skill name leading to a crash - fix multiple issues related to the interface settings - allow to change the auto battle settings if player's army doesn't have a commander - fix a crash when a hero tries to get a second magic book - always grab the mouse in fullscreen mode to properly support devices with notch version 0.9.14 (09 April 2022) - generate Italian "Battle Only" button - fix line breaking in welcome message for various languages - update and improve Italian translation - generate Polish "Battle Only" button - fix switching fullscreen mode in Mac OS for certain resolutions - generate French "Battle Only" button - fix a crash due to an assertion failure when the shooter hits back at a unit under Berserk spell - fix scrolling in full-screen mode in case of an aspect ratio mismatch - fix rare cases for incorrect letters being generated while switching languages - add Norwegian language option and font generation - update French translation - add initial implementation of Dimension Door spell usage for AI - fix Gold Watch artifact invalid bonus - rework artifact logic with proper separation and calculations of artifact's bonuses and curses - play only one sound while getting ar artifact within an event - speed up castle and hero icons on adventure map - add "Battle Only" button generation for German version of the game - fix Mage Guild bottom status bar rendering - fix incorrect artifact discovery description - add in-game Italian language option and diacritics - fix army order option related crash - fix High Score Music after winning scenario - adjust AI spell estimates - fix rendering of bottom bar in Well dialog - update Polish translation - remove unnecessary call to play VICTORY music during Campaign intro - fix the calculation of the cost of surrender - fix Town Gate spell logic - prioritize AI castles further from enemy territory - take the weekly growth into account when calculating monthly population growth bonuses and fines - update minimap colors - optimize AI fighter hero priorities - add native macOS application generation - build player influence map to inform AI kingdom development decisions - speed up data reading from AGG files - update Norwegian translation - add a popup window for battle log - add a mandatory requirement of h2d file being present - fix incorrect logic for palette application function - fix position of armies for quick info window for both castle and enemy hero - set the direction for attacking and defending units in battle in a more OG-like way - fix incorrect popup monster window in Well - greatly speedup heavy video loading - do not render extra frame while playing an audio only video file - properly center the first sentence in the battle surrender dialog - dynamically update Game Language dialog - fix translation and UI in Tavern dialog - add MP3 file support - increase the number of sound channels to 32 - allow a hero to surrender to the captain during the siege - fix rare case of Shipwreck having no battle - display experience amount for Tree of Knowledge - fix Witch's Hut message body - for Anduran assembly window show artifact name as a title - for hero level up window with one secondary skill make the skill right clickable - for hero level up window with no secondary skill display the primary skill icon - add search for FLAC files if OGG files aren't found - add popup dialogs for Arena's skill choices version 0.9.13 (07 March 2022) - show captain quick info dialog in Kingdom Overview - add popup windows for campaign awards and bonuses - remove Map loading screen - add popup windows for campaign scenario dialog buttons - remember map size selection in New Game dialog - allow selecting options while restarting a campaign scenario - display the correct size of player-owned objects on mini-map - add base support for text mode - fix Sirens logic, AI interaction and UI - show missing last frame of wince animation - add dynamic generation of scrollbar slider - fix Sirens action dialogs - add missing artifact discovery event description - fix some French translations - fix directory and file detection on Windows - Kingdom Income window was changed to have Kingdom Income title and Kingdom Income per day to be more obvious for a player - events on land and sea now show artifact and resources in one window - most of objects related dialogs contain right mouse clickable icons - Pyramid visit outcome shows the correct horizontal position of icons and all icons are right mouse clickable - fix Artifact frame drawings - fix text if translation for a specific language was not found - update AI hero recruitment logic - allow a short name for all campaign bonus artifacts and spells - AI should save current unit if retreating - add Czech language support - fix monster strength heuristic regression - make AI more aggressive in losing situation - fix the logic of protecting tiles by neutral monsters - change music and surrounding sounds while jumping through Stone Liths - fix possible AI pathfinding issues while loading another scenario - fix battle grid and ballista info area - add popup dialogs for right mouse click in resolution dialog - fix hero name not being updated while switching languages - fix possible errors for translation related code - force to use only the original palette from the game - fix lowercase conversion of translations - AI archers should not ignore blinded units during battle - add missing take-off and landing sounds for Vampire and Vampire Lord - reset environment sounds and music theme at the beginning and at the end of the human turn only - fix player's allies configuration for 'Defeat the other side' victory condition - fix sounds of Lean-To and Skeleton objects - rename "Lean To" -> "Lean-To" - allow AI fog discovery only for teleport endpoints with reachability information - fix missing sounds for some objects on map - do not play castle's music if a terrain does not have its own music - fix missing sound of player's turn in Hot Seat mode - adjust monthly monster spawn - fix neutral monster growth formula - fix necromancer build order in castles for AI - allow a boat to move near the coast above the center of a town version 0.9.12 (07 February 2022) - add a confirmation window for restarting a campaign scenario - fix wrong scenario order in "Voyage Home" campaign - add Betrayal missing for Roland and Archibald campaigns - fix logic for switching on and off Auto battle option - fix normal and retaliation attack of monsters with multi-cell attack abilities - fix missing logging during certain spell casts in battle - implement a heuristic for hiring heroes that does not allow to offer the same heroes for hire in several kingdoms at the same time, if there are enough free heroes - use 'r' key instead of Escape to Retreat during battle - fix Hydra behavior under Berserk or Hypnotize spell effect - add highlighting of cells attacked by a unit capable of attacking all neighboring cells - fix a penetrating attack made by a wide unit from the tail cell - fix attack cursor display during battle - fix cases when no monsters were spawned at the beginning of a month - display ? symbol instead of empty space for unrecognized symbols - fix crashes while rendering non-English text - fix rare cases of a screen being black on a startup of the application - make language area and campaign choice selection to cover text too - fix campaign text translation - modify army order setting - add German font generation - fix multiple issues related the hero recruitment process - update Russian translation - show monster info on right click in castle's well - fix cases when the last AI hero was blocking an entrance to Stone Liths - fix small font positioning for Polish GoG version - fix most of existing cases with passabilities - fix the display of properties for maps from the list in scenario selection dialog - update German translation - fix translation of saved default player names - improve the AI fog discovery logic - AI properly uses Whirlpools for path calculation - fix cases when a hero was able to create a path over another hero - display dead monster information during battle - fix Mass Dispel usage during battle - update Polish translation - fix Russian small k per in both fonts - AI heroes properly calculate paths through water - add translation context for color and syntax flexibility to Traveller's Tent and Barrier - fix Knowledge spite rendering for Arena - fix sounds after battle cases - fix missing Russian letters on Switch - changed captain's name spelling - adds missing "pourcent" in description of Golden Bow - fix cases when a hero was able to walk on water - update French translation - show in-game only players for Gift marketplace option - fix glowing red pixel in Warlock's Red Tower - improve AI behavior during castle defence - fix CPU player icon's extra color column - show proper language name for mismatched by language save files - add a spell title when no enough SP window appears - fix a possible crash in French letters generation - fix usage of plural/singular translations for map's objects - update the logic of re-calculating the paths of heroes on the adventure map - add support of Buka version of Anim2 directory for video playback - always enable autosave - generate proper Russian E with 2 dots on top - allow translation of "Cost per troop:" text - update UI elements in marketplace window - fix a crash during AI turn when AI army has an invalid monster slot version 0.9.11 (23 December 2021) - add popup dialog for map information - fix hero's path not being updated properly after new monster month event - show available game languages in vertical order rather than horizontal - fix handling of national symbols in the paths to music files on Windows - improve AI behavior during castle defence - fix pressed buttons' background - fix incorrect output on console window for Windows users with non-English system language - add support of Russian language by default - update Polish translation - generate correct letters for French language - update Settings description to cover all actions - fix heroes meeting swap arrows - update PS Vita controls - fix crash for some systems after changing game resolution - add hotkey for settings in Main Menu - do not reset the hero's path in Sleeper mode, reset the Sleeper mode only with the beginning of the hero's movement - fix River being considered as a Road - allow to select player class using mouse wheel - add additional spell info for spells owned by a hero - fix button rendering artifacts after changing resolution - fix crash on Windows for some Archibald scenarios - always mark the entrance to the castle/town as a road, do not automatically mark the tile south of the entrance as a road version 0.9.10 (05 December 2021) - update background music on the fly while changing it within settings - fix horizontal position of town name and town icon in town construction dialog - improve marketplace gift button placement - fix vertical text position in skill icon - fix Summon Boat logic - add video playback in the Price of Loyalty campaign selection window - play sound for visiting Observation Tower - fix vertical position of building construction name - add missing button shadows in dialogs - add popup window to OK button in game settings - play campaign music in campaign scenario selection screen - fix Enter button pressed state being passed from gift dialog - show credits at the end of campaign - fix passability for Dimension Door spell - add V-Sync option for SDL2 - update troops split logic change - properly draw battle grid - use the OK button instead of YES button for the Tavern window - add Champion image for Stables object - play sounds from closest surrounding objects first - make consistent campaign info dialog - add default castle's name if none is specified by editor - show heroes on minimap - update Norwegian translation - show available creature count for the Price of Loyalty monster objects - fix Witch's Hut name - add Italian translation - properly handle the day-week-month routine - add titles for most of dialogs from map's objects - always mark Artesian Spring as visited, even if the hero was not able to drink from it - fix movement penalty calculation algorithm - implement last move logic for hero movement on the map - update hero movement points UI upon visiting multiple objects on the map - fix rendering for difficulty text in scenario info dialog - fix AI obsession with whirlpools and being always in sea - load palette from AGG file - fix monster recruit window position for multiple places - fix logic for Slow and Haste spell AI usage during battle - add random sign messages - fix maximum music and sound volume - use correct message in marketplace for first exchange when not enough resources - speed up for multiple image readings and for unit rendering during battle - allow to change Battle Speed using mouse wheel - update UI elements in Well's dialog - if a hero on the map has the custom empty army (OG editor bug/feature), give him a minimum army (one unit of level 1) - add translations for Battle Only mode texts - set correct starting army in Archibald 7 scenario - fix cases when AI creature doesn't move during battle - fix sound effects when receiving artifacts from world map - add hotkey to Okay button in Campaign select window - fix results on instant battle when Resurrect spell was being used - fix cases when opposing heroes still exist on the map after defeat - improve AI usage of Disrupting Ray spell during battle - add runtime language generation - fix terrain music being played during battle - fix water object passabilities - allow to use mouse wheel to change system options - set correct building requirements for Upgraded Jousting Arena and Upgraded Cathedral - update messages during battle - shorten artifacts names to be fit for campaign UI - always highlight the cell under the cursor in combat if the Shadow Cursor is enabled, even if this cell is not reachable by the current unit version 0.9.9 (05 November 2021) - do not leak the hotkey state from the experimental settings dialog to the scenario info dialog - fix Stonehenge gold cost - fix Stonehenge building requirements - add buttons in castle construction window - fix rendering of Captain's Quarters in Warlock castle - fix Marketplace messaging - fix MIDI Expansion music option being always reset upon restarting the game - fix incorrect sounds while playing MIDI music in certain platforms - add credits to the original HoMM2 team - correct original Waterfall images to remove Cave - use original alignment for Rating, Map Size in gameinfo window - fix interaction passability with water objects - change Shipwreck, Graveyard and Derelict Ship messages - add the Resources Settings page to the Windows installer - fix passability for Reefs - fix invalid Stonelithts after Barrier removal - fix passabilities for diagonal moves - clear fog for allies upon visiting Magellan's maps - fix Archibald scenario 7 description - fix bad pixels on multiple images - verify Victory/Loss conditions after a static hero action - modify Magellan's maps logic and UI - fix monster count in Dragon City for Archibald scenario 7 - update Victory message for Archibald scenario 7 - fix possible crash for Russian version of the game - fix incorrect map description length - fix spell points in Battle Only mode - apply Bane and Alliance condition only for Human heroes - add extra empty line in New Month window - disable bonus choice for campaign scenario info window during scenario play - add Norwegian Translation - fix the position of campaign days spent text - close certain dialogs containing only one Exit button with Enter key - add Barbarian Captain Quarter's missing part - add hotkeys for selection of SW/PoL campaign - generate the default High Score values - fix "show damage" feature for blessed/cursed troops - fix high scores word - fix AI lust for Magellan Maps object - hide the OKAY button in campaign info window - handle default exit hotkey in Campaign scenario select / info - add Sphinx handling by AI - remove incorrect status message for hero portrait in hero screen - fix map size button states on hotkey press - restore environment music & ambient sounds after exiting from the campaign info screen to the adventure map - do not allow to use lower than original resolutions - freed from Jail AI hero starts movement at the same turn - add AI interaction with Alchemist Tower - fix incorrect visiting status of Magic Well, Stables, Artesian Spring and Bad Luck objects for AI - fix invalid assessment of Monster upgrade objects for AI - fix cases when AI hero ignores some objects while defeating an army just on the way to them - fix losing hero artifacts upon flee or surrender - enable a pressed state for View Intro button post-launch in Campaign screen - fix bonus artifact names in campaign screen - return to the Main Menu after cancelling campaign scenario - fix AI heroes being stuck on teleports - fix button rendering in Restart battle dialog - update Portuguese translation - fix inability to dig on a tile where monster was located - fix inability to apply Hypnotize spell on Dwarves - fix shooting penalty detection - add extra popup windows for UI elements in castle dialog - fix passability with shadow sprites - AI to use Hydra ability in battle - reinforce a AI hero standing in a castle at the start of turn - update status bar in castle screen dialog even during construction animation - fix incorrect active area of certain buildings in castle screen dialog due to invalid Z levels - hide cursor while opening a dwelling info in castle screen dialog by right mouse click - add Italian language support - update Polish translation - properly show the attack cursor when the attack square is located at the top of the castle sprite - fix infinite loop for AI trying to use Stoneliths version 0.9.8 (05 October 2021) - fix a case when a hero loses his artifacts after retreat in multiplayer mode - fix monster position on World Map - correct resource position in castle window - new week status is not changed while reloading the same save file - add headers for all Daemon Cave dialogs - fix rewards in the Daemon Cave - fix Waterwheel incorrect visited status - fix spell points reduction while visiting a well with more than maximum spell points - add confirmation message in Alchemist Tower - add cell highlighting for monsters with double cell attack ability - add correct evaluation of an AI hero recruitment and meeting - fix artifact selection area - add a title to all artifact related windows - grey out experimental disabled option - show map type icons in New Map lists - do not place wandering troops on coast tile if there are no other coast tiles nearby - develop a castle during AI hero purchase - fix Altars' passabilities - fix AI hero being stuck on Stoneliths - fix passabilities of action objects - add Windows scripts to automatically copy & extract all necessary assets from original HoMM2 distributions - fix unresponsive application during AI turn while attacking an object with guards - fix active building area in castle construction window - AI can now visit Pyramids - fix scrollbar rendering in select lists - replace scrollbar in Experimental Settings dialog - unselect initial town in the Town Portal spell list - fix troop position in the Pyramid - fix bridge animation during battle - fix deterministic battle outcome - fix an empty list of heroes in the Kingdom Overview after the dismissal or loss of a hero - fix passability for tall objects - fix Roland campaign awards after ending scenarios 7 and 8 - set 15 character limit when inputting player name in High Scores - correct battle speed change for monsters - fix incorrect level of Lightning Rod artifact - correct castle building' active area - fix passabilities related to cracks - align UI elements on artifact combat outcome dialog - add Spell description window in monster info dialog - fix scrollbar position after dismissing a hero - add logic for ENTER and SPACE keys for a hero on World Map - add hotkey for View World dialog - fix some cases with Tree passabilities - update Polish translation - fix post battle crash - fix incorrect rendering for game settings window with evil interface - fix appearance of sounds of the sea when a hero stands close to map's edge - display a message about Ultimate Artifact after the battle - fix adventure border rendering on higher resolutions - fix incrementing days spent value after reloading a campaign save - lock mouse within the window in multi-monitor setup - fix passability of mines - fix an ability to attack a monster through a barrier - allow hero to traverse Stone Liths and Whirlpools even if he has no movement points left - fix black edges in View World - fix passability for tiles with shadows only version 0.9.7 (05 September 2021) - add popup dialogs for buttons in High Scores and save files manipulation windows - fix Faerie Ring passability - boat boarding animation speed doesn't depend on hero speed - add base support of German translation - fix medium size hero portraits - fix incorrect object info when a hero stands on it - remove flags from most of the captured objects for a lost player - fix alignment of scenario info window - fix boat froth drawing conditions - fix Battle Garb of Anduran missing assembly for The Price of Loyalty campaign - add monsters into High Score dialog - add short save file description window by right clicking - add base roles for AI heroes - restart of the battle should lead to the same results - fix logic in moral indicator - AI can capture Haunted mines - fix scrollbar position in Kingdom Overview dialog - allow guardian heroes upgrade their troops - add object count for weekly object income message - open game settings window while clicking on the main menu door - fix object passability nearby Hut of Magi - modify Necromancer Captain Quarters look - fix Radar appearance while right clicking on hero/castle - do not show file options window upon file saving - save Kingdom Overview UI selection in save files - add missing hotkey for Kingdom Overview - fix missing mine being drawn in View Mines - fix incorrect fading of some objects on World Map - fix AI behaviour during siege - fix cases of incorrect monster stack splitting logic - handle Escape/Enter keys in various settings dialogs - use distinct image for the "Swap heroes" button - properly restore captain's spell points after quick battle - remember UI position in Kingdom Overview dialog - add strict ordering of save files ignoring capitalization of letters - add popup dialogs in Kingdom Overview UI dialog - fix missing game resolutions on some machines - fix incorrect rendering on specific fog tile - display same name maps in the list of available maps - improve pathfinding algorithm for AI - place Ultimate artifact not always in the center of puzzle image - fix max ballista shots during battle - update French translation - add missing Farm sprite in Knight castle - update every scrollbar logic in the game - fix a crash while shooting from castle's tower during castle siege - fix Holy Shout being applied on Dwarves - properly handle cross-moat attacks during castle siege - do not let the player get a random artifact that allows him to win the game - allow player to immediately edit save file name without clicking on the input field - add few performance optimization in music and audio - update Polish translation - not visited obelisk remains not visited after the Ultimate Artifact has been found - fix polish translation encoding - game settings dialog: reset current language to English if game resources do not support other languages version 0.9.6 (06 August 2021) - update status window if troops have fallen overboard - add direct preview of changes in system options dialog - update Polish translation - display the position of a hero or a castle on radar while right clicking on them - add titles to some dialogs - add translation support for missing places - fix monster joining logic with and without diplomacy - add Nintendo Switch build - make captured object event messages to contain yellow titles - fix a crash while AI uses Summon Elemental spell during battle - fix incorrect Alliance conditions for certain maps - fix a case when a hero in castle's tavern always changes after reloading a save file - fix incorrect icons for scenario information dialog - update skill order for new heroes - add normal Game settings dialog - fix inability to attack during battle - do not play ambient sounds during AI turn - add monster names, abilities and hero skills to translations - fix AI archer avoiding hand battle logic - fix UI defects in Kingdom castle view dialog - properly update resource and artifact sprites on World map - fix infinite loop after chain lightning spell - do not draw flags for puzzle image - highlight cells from where a monster will attack - restore background music after playing short-term music effects - add language selection window - fix Town's fog area unveiling - implement regular win/loss conditions for multiplayer mode - update View World while resizing the application - fix English phrasing and punctuation - fix simultaneous activation of buttons in hero meeting screen - add Town Screen and Well hotkeys - fix incorrect logic nearby castles when an attacking hero was actually defending the castle - improve win/loss checks of scenarios - make AI to use Lich's ability properly - update Russian and French translations - make fog discovery by AI more efficient - fix missing monster spell casting during battles - center fast separation buttons in Monster separation dialog - remove required spell points from scrolls in Mage Guilds - fix Next Hero selection logic - fix Wizards campaign scenario 3 with custom Ultimate Artifact - add 500 experience for conquering a town regardless of defending hero existence - change battlefield pathfinding algorithm to more stable version avoiding AI skipping some moves - align text evenly inside secondary skill window - display translated text in campaign dialog - fix a crash during Summon Boat spell usage - if the hero's army does not have any of the original troops left alive at the end of the battle, then the hero should lose - fix typo in Fizbin Medal - fix small font for Russian localization - fix town/castle passability for some cases - fix incorrect mouse cursor appearance during AI turn after a battle with Necromancy outcome - fix attacking monster sprite on World map - AI should check if an object is guarded while unveiling fog - add Alchemist Tower to the list of objects to be avoided by AI - fix a case when AI heroes did not ever capture empty castles version 0.9.5 (04 July 2021) - do not hire AI heroes if no tasks exist for them - make AI be more aggressive if no tasks exist for them - all scrollbars support continuous scrolling - fix placement of creatures during Month of Monster event - add an option to restart Campaign scenario - do not show x marker for fully built castle icon - fix boat summoning logic in relation to some objects on a world map - do not show other types of save files on while saving or loading a save file on Windows - improve Sorceress castle building logic for AI - make AI to visit Lighthouse - fix displayed object info in popup dialogs - fix places where a hero could teleport for Dimension Door spell - fix passabilities of objects on World Map - fix multiple issues with castle music - fix disembarkation on coast during diagonal move - indicate the number of Ghost guarding Haunted and Abandoned Mines - add extra conditions for object visiting by AI - make AI to use Hut of Magi and Jail objects - AI heroes do not block way for other heroes anymore - use spacebar only for activating object - fix missing UI update in hero meeting dialog while moving artifacts within internal hero's dialog - speed up campaign game menu opening time - fix incorrect object rendering order on World Map - after loading a map and starting a new game the same map will be selected in the list of maps - improve AI logic to capture defendless castles - fix black screen for loading a campaign map without files - allow AI hero to revisit a castle more than once - fix a case of splitting monster stack for 2 monsters in stack - add monster descriptions - allow to visit Artesian Spring once a week - allow right click on captured artifact after battle - fix summoning boat logic in relation to AI - improve fog revealing algorithm for AI - fix Stables movement bonus - fix AI heroes interaction between each other (reset meeting flag if a hero updates an army) - AI heroes do not visit signs anymore - AI do not visit shrines for useless spells - fix AI spellcasting and army estimates - do not remove Sphere of Negation artifact while visiting Alchemist's Tower - fix the status of visited objects for a play with ally - make proper rendering of some of disabled buttons - fix AI behavior to visit Magellan Maps only once - center quickinfo dialog under mouse cursor - add more gamepad key mapping for PlayStation Vita - fix the displayed text in the army bar while splitting monster stack - do not let nearby monsters automatically attack hero if he moved to this location using Stone Lith, Whirlpool or Dimension Door - fix incorrect text position insertion while creating a save file - fix title background for recruit dialog - fix hero's mobility indicator for small number of move points - in scenario with random players random opponents are generated so that all races are present and different when possible - add new UI text rendering classes - fix issue when abandoned mine becomes OBJ_ZERO when captured by AI-controlled hero - fix missing road identification on broken by editor maps - make per-user config file as default option - allow attacking another hero located on a Temple - fix attacking monster sprite behavior - fix number of choices when splitting a troop into multiple troops - fix incorrect trading rate during battle - fix missing shadow removal of objects under a boat - show Dwarf's resistance message in the log only after spell completion - correct campaign bonuses' names - fix case when boat could be positioned over another boat over whirlpool - fix case of triggering Genie's special ability for a stack of 1 monster - fix the Price of Loyalty campaign missing rendering version 0.9.4 (04 June 2021) - add Windows executable installers - use user profile directories to store files to allow multi-user access to the game - fix incorrect text splitting in some rare cases - fix crash in Roland campaign, scenario 10 - add missing popup dialogs for system options and buttons - fix inaccurate object sorting by distance - fix multiple issues with AI and spell logic using distance evaluation - read campaign files in non-case sensitive manner - make fog uncovering task for AI more efficient - fix AI obsession over Observation Towers - fix missing path drawing while a hero moving through Whirlpool - mark resource generator objects as visited for allies - fix incorrect game ending during time loss condition - show extended shadow for 2-hex monsters in battle - do not show gray flag over Haunted mine - add configuration option for first game run - support PoL heroes and artifacts in "battle only" mode - fix inaccessible beach tiles - add hiding and showing cursor logic for SDL2 - fix shadows for random resources and artifacts - draw correct castle icon in popup window - fix incorrect hero position facing left - remove unneeded AI hero animation under fog - do not clear morale modifiers too early for Tavern case - highlight the door in Main Menu for mouse over event - speed up and fix many places with cursor rendering - recruit an AI hero if none exists - fix cheating AI behavior for dwellings with defenders - add an option to replay Intro video for campaign - force display rendering on app activation - fix Stables, Alchemist's Tower and Water Wheel passabilities - fix puzzle drawings - avoid using useless spell during battle for AI - return to load screen after cancelling loaded campaign scenario - play hero's vanishing sound after AI vs human battle - make Ultimate Crown as artifact for campaign scenarios - fix incorrect hero receiving a bonus spell for campaign scenario - fix monster recruitment logic when a hero present in a castle - fix well's max button hiring logic - add an option to open Hero Screen within battle - fix move points and spell points replenishment logic for heroes from hero pool - set proper difficulty level for campaign scenarios - directly show next campaign scenario for end of scenario save - modernize and secure demo version installation scripts - add video playback for campaign scenarios - do not reset hero mana points to maximum in the beginning of a new week if they are above maximum - fix Roland, chapter 9 map conditions - fix Tower shooting logic during castle's siege - build Mage Guild before Special building for AI - do not count monsters under fog for Visions spell - mute sound by setting music and effects volume to zero instead of pausing them - speed up AI hero movement - add an option to hide AI movements - do not draw objects under the fog if they are far from a revealed area - add base code for the Price of Loyalty campaign support - add dismiss and upgrade hotkeys in unit dialog info - add shadow for Spell Book - unveil the fog at the start of hero's movement - fix extra place with hero's double shadow at adventure world - add extended cursor icons from 4+ to 7+ - fix UI defect of selected creature appearing after closing meeting dialog - fix incorrect rendering of View World image - add Lose Sorceress Village Condition for The Succession Wars campaign - fix flags in Oracle/Thieves' Guild dialog - fix sound mute in background on MacOS with SDL1 - add Home and End button support for save naming - fix elements layout for Oracle/Thieves dialogs - generate obstacles on battlefield based on the battle tile index - use non-plural name for 1 creature while viewing with Crystal Ball - add correct support of The Price of Loyalty add-on maps - fix double clicking between dialog in castle's window - speed up MIDI loading - fix bug with mouse cursor not visible after left-clicking on hero's secondary skill in Kingdom Overview - fix the "world: use unique artifacts for resource affecting" option - reduce CPU usage for video playback and puzzle revealing - fix Mix-up in Roland's Campaign Scenarios - fix issue when troop info window was not showing after moving a single unit between army bars using drag & drop method - simulate level-ups for campaign-specific heroes that start at a higher level - reset current music from the previous turn in the beginning of a new human turn - upgrade Rendering engine - fix broken behavior of scrollbars - do not offer to exchange artifact with spell book - disable controllers on non-console platforms version 0.9.3 (04 May 2021) - add additional info to oracle dialog - check that unit is (im)movable after each unit action - save completed Campaign scenario to file - drop support of saves older than 0.9 version - remove incorrect battle background for Graveyard - fix catapult miss animation: show this animation near the actual target object - fix magic book behavior in inventory - fix spell indicator for hero's icon - add special Victory conditions for campaign scenarios - add initial support for Campaign Awards - allow switching heroes in hero dialog if it was opened from meeting dialog - fix issues with battles logs and sounds while Dwarves resist spell - fix inability to Teleport monster in battle for certain cases - add missing "Not enough gold (xxxx)" text in joining window with Diplomacy - do not generate Puzzle image on map loading - do not take Mage Guild level into account when calculating count of archers in castle towers - fix shadows for all monster mini sprites - allow the hero to retreat if, while in the castle, he attacks the hero outside the castle - show Mage Guild building always in center - add titles to Arena, Alchemist Tower and Stables dialogs - add World animation during Dimension door spell - show correct message for hero's option dialog buttons - fix bridge operation for flying units in instant battle - add letters for World View and View spells - properly handle filenames with dots - fix Main Menu UI redraw - do not run animation of lowering the bridge on bridge destruction if bridge is already lowered - fix the display of the army in the castle quick info window - display correct message when capturing abandoned mine - align columns and flags at oracle dialog - fix cursor during video playback - do not allow the player to scroll world map while hero is moving - add initial support of other languages: German, Polish, French and Russian - fix information displayed in castle quick info window - fix sphinx riddle dialogs - add swap buttons in hero meeting dialog - correct spells order in Magic Book - enable triggering of positive morale event after soft wait - fix saving scroll speed in the game config file - fix Artesian Springs logic - fix inability to use Stone Liths - fix incorrect heroes for surrender conditions - fix gold and experience dialog for the demon cave - remove exclamation mark in Hero info window for "Blood" morale - fix double shadow from heroes - preserve the order of catapult shots - highlight Lich's shot area - implement correct post-battle necromancy window - rename Coast to Beach - fix large object coverage in battles - add message when visiting Oracle - update hero's path while selecting next hero by an option button - fix Dragon City guardians - load correct video files to be played - implement the "faster monster of opposite army goes first" logic in the battle mode - fix excessive FPS issue in dialog of joining the army - fix game score calculation - reset the spell on tile when AI-controlled hero has successfully captured an object - immediately hide hero's path before executing the animation of the Dimension Door spell - fix Necromancy incorrect percentage output - fix ultimate artifact digging logic - speed up images loading from resource files - fix fading animation synchronization - fix a case of inability to confirm end turn while cursor is over options buttons version 0.9.2 (04 April 2021) - fix full artifact bag message - add missing dot to sentences in few windows - display Lighthouse count in Kingdom Overview - add proper large obstacle generation for battlefields - fast AI units should try to get the first strike - fix Sphinx missing rewards - reset paralyze state when receiving spell damage - randomize attack position of AI monsters - fix missing hero paths after loading a save - fix incorrect window resolution in fullscreen mode for SDL 2 - fix Choose Your Lord video sound - improve castle garrison estimation for AI - remove the mobility index sprite info from the hero Quick Info dialog - prohibit the guardian hero from casting adventure spells - fix merging of the castle guardian army - fix AI defensive unit behavior - add AI estimation of hero spell strength - force units into empty slots first during merge - do not always offer recruitment of heroes from the player's initial class, make recruitment more random - allow player to control the hero during the turn of a hypnotized enemy unit - archers should not lose shots when attacking in melee - check that the hero is able to move before focusing him and starting his movement - respect initial order of units (from top to bottom) when determining the order of unit moves in battle - add PlayStation Vita support - fix creature recruit window UI - fix rendering of Arm of the Martyr - fix blind spell logic - do not give additional 500 experience to the hero who won the battle if the opposing hero surrenders or flees - fix hypnotize spell behavior and the spell description - update positions of monster sprites and numbers on army status panel - fix possibly incorrect arrow direction from shooters - fix scrollbar position in multiple places - standartize icon position in town's dialog - fix Max/Min button position in monster recruit dialog - show the surrender dialog even if there is not enough gold to surrender - do not apply morale penalty to a hero if he wins a battle in a Graveyard, Shipwreck or Derelict Ship - add cross army drag split - reset player focus if focused hero or castle was removed - allow to switch players for multiplayer map selection - allow to use mouse wheel anywhere for split troop dialog - fix logic of placing monsters for a New Month - fix Kingdom Overview selection drawings - fix boat drawing issues - do not hide mouse cursor if the Skill Info dialog called from the Level Up dialog contains OK button - fix incorrect drawings for battle OKAY button - fix rendering of the Castle Captain's spell points bar - fix missing sounds within System dialog - fix interaction with the castle bridge for flying units - use rule of 9 for Ultimate Artifact placement - fix last focus option - fix incorrect cursor icon over ally's castle - add initial implementation of View spells - show normal monster names in Visions spell - show full 1-pixel black border for Show Interface option - show more detailed morale and luck description - AI predicts double cell attacks in combat - reset blind spell upon taking any damage - allow to place units in moat in front of the bridge - align spells in the magic book - add manual replay of battle if instant battle outcome is negative - sounds off when minimizing game window - fix playing background music during video playback on SDL1 - change damage description log message for some mass spells - add executable file description and icon on Windows - fix pathfinding backwards move and penalty in battle - fix City of the dead incorrect monster info - update no data error message - do not allow to manage monsters in unhired hero dialog - AI supports additional harmful combat spells - do not open the hero screen in readonly mode if it was opened from the meeting screen, just disable the DISMISS button instead - do not show external music option with an absent folder - wait for user input at the end of winning video - fix double exit dialog appearance - fix missing cursor in Army Bar for SDL 1 - ranged AI troops should move when blocked by a strong unit - if the unit attacks twice, apply the second attack to the same cell as the first attack - fix double hex attack target for AI troops - show the build window with the OKAY button disabled if there is not enough resources to build this building - AI uses mass damage spells in combat - improvements for AI wide unit pathfinding - fix the pathfinding near monsters: do not allow the hero to pass through the monster - fix MIN and MAX button drawings - do not give an extra day of life to a player without castles - preserve unit direction in battle if it moves strictly vertically - do not allow the visiting hero to learn Library spells if the Library hasn't been built yet - fix inability to reorganize troops in Kingdom View dialog version 0.9.1 (04 March 2021) - add "Artifacts" category in Oracle Screen - add barrier fading animation - improve AI retreat condition - fix Split-related issues and implement some new techniques - disable retreat for auto battle mode - fix object's visited info and grammar - fix issues with path finding during combat to avoid being stopped by moat - fix incorrect names of Ballista and Turret during battle - add missing shadow for arrow cursor on SDL2 - fix ACCEPT button font for Good Interface - fix AI wide units pathfinding and moat logic - allow to modify a hero during level up - fix summon boat logic - fix monster movement nearby moat - AI does not chase faster units during battle - fix hero shadow drawing on world map - fix missing animation frame for wince - fix object fading animation on world map - fix missing last lost hero condition reset - fix simultaneous animation of boat while during another building construction - change logic in monster hiring window - fix save loading crash for broken saves - add middle resolution status support - do not show waiting cursor for an exhausted hero - fix post Daemon Cave missing music - fix well's max button drawing - fix incorrect castle focus while visiting by a hero - fix fog drawings - reduce income window area in towns - fix autosave option logic - fix overlapped battleground objects - remember scenario difficulty while restarting or choosing a new scenario - fix multiple game freezes with MIDI music playback - add resizable window support on SDL2 - make deterministic bonus for hero level-up - fix wrong controller pointer speed option name and touch coordinates translation - add auto battle resolve mode to the game - add logic to support video frame rescaling - optimize screen resolution logic - fix garrison strength estimation by AI - fix magic gardens priority if object capture is enabled - optimize AI's troop placement before the battle - use same colour for all battlegrounds - change text in map size hint, to be displayed in more pleasant manner - load game button from UI should lead to common load game logic - initial implementation of "View World" - fix application crash for drawings - change building status message for Dwellings - fix crash when entering ally castle - add Campaign continuation initial support - speed up rendering of World Map - fix spell book status on hovering - save fullscreen mode in configuration file while switching between modes - AI should avoid spellcasting if has advantage in battle - fix rendering with mouse emulation - fix extensive memory usage by dialog windows version 0.9.0 (04 February 2021) - make AI to buy magic books in castles - fix infinite AI turns - optimize AI hero movements - do not visit useless objects by AI heroes - fix AI castle defence mechanics - restore cursor theme after HeroDialog or CastleDialog - do not show marketplace icon for joining creature dialog is no markets exist - allow to retreat for a hero with no castles - add more logic for AI jumping into whirlpools - do not block shooters with overpowered AI army - fix overlapped flag in Knight's castle - disable actions while buying a hero or during construction - change the text for the number of secondary skills in level up window - play music after showing New Week/Month dialog - reset hero direction when recruiting - align dates by left in the load file dialog - cap Necromancy bonus to 100% instead of 90% - fix multiple bugs in Kingdom View - fix Transcribe Spell Description Text - cancel spell selection with ESC button in combat - add a separate option for displaying terrain penalty - fix missing music for Load Game option - fix Scouting skill bugs and make crystal ball work - do not play dwarves' resist sound during mass spells - fix Berserk spell logic - fix Chain lightning spell logic - fix castle flag drawing for nearby hero - add empty line for visited info - allow Anti-magic spell on mirror-master creature - do not draw wall for destroyed bridge - fix pathfinding issues and missing path display - fix Kingdom overview crash - do no freeze building animation during construction or hero's hiring - show Spade of Necromancy artifact bonus in Necromancy Skill window - display troop counter only for static animations - show pointer cursor most of the time during combat - fix castle's object positions - display correct text when right-clicking on map tile - fix path selection for AI hero in patrol - fix town portal buttons in Good interface - add new standard window with shadow - fix events when AI was choosing to disembark on empty tiles - change highlighted cursor area for spells during battle - implement Alt hotkey to unite stacks of same type - implement CTRL split even with selected troop - add touchpad support - fix joining creature logic with the lack of gold - quick Info dialogs have fixed position when clicked from right bar - add a check for special objects that you can't move through - after AI loses to either castle or other player, center the view on them - fix animation order of creatures during combat - do not close File Save window while cancelling file overriding - fix marketplace button drawings in Surrender window - fix castle's battlefield drawings - hide Marketplace button for Surrender window - always draw troop counter at the top of monster sprites - fix a log message when a tower kills one creature - display battle grid for whole battlefield - fix object drawings on battlefield - Bone Dragon morale malus shows in battle and in dialog window - add PNG image saving support for SDL2 - add palette support for SDL2 - fix morale and luck sprites positioning in meeting screen - fix mouse cursor switching while navigating on hero or castle panel - always display the correct monster combat speed - fix Player Rankings message bar - add game controller support - add Gold version support for video playback - fix Earthquake spell animation - fix enemy castle capture action - speed up interface drawings for World map - fix Hydra's movement during battle - set correct size for spell point and experience point zone in hero window - fix income info clickable area at castle options window - add spells into Hero's book at the start of a map - add initial Nintendo Switch support - fix Battle Only mode UI - fix logic in mouse button press - make interface itemsbar adjustment while fixing some split logic - add FPS display support - fix clickable area for Heroes and Castles in their lists - differentiate save files based on game type - fix a crash while trying to get settings path on SDL 2 - fix path calculation for 2-hex creatures in battle - add software emulation support for cursor version 0.8.4 (23 December 2020) - speed up sprites allocation and deallocation (noticeable for low-profile devices) - add extra info in first game message about F4 key - fix moral and luck indicator messages - fix elements' layout at monster info dialog - disable monster attack using Dimension Door - remove click area around "exit" button in castle dialog - make elements gray for inactive game settings - fix cursor disappearance during resource collection on SDL 1 - fix Summon Boat animation - fix Summon boat logic - fix popup message for Abandoned Mine - fix Select button movement in Scenario window - fix position of monsters in battle - modify monster upgrade window for 3 monsters - make proper calculation of movement points - fix Hide interface reset issue - show correct artifact transfer dialog after battle - fix impassable barrier - fix meeting hero update after exiting hero's dialog - adjust troop separation dialog position - fix incorrect hero values for Kingdom Overview screen - fix a crash in multiplayer game selection - fix Transcribing spell scrolls logic and UI - change info bar text at bottom of screen when mouse cursor positioned under spell book - fix starting unit values - implement smooth slider - add an option to reveal secondary skill info by right click - implement Stack split hotkeys (Ctrl and Shift) - fix Resurrect logic - ignore fog for dimension door - disable gift button for a single player - fix empty castle capture behavior - fix interaction with skeleton on map - persist random race for new games - fix road penalty text - fix incorrect town frames for evil town portal UI - speed up generation of few images - fix UI defect after closing hero meeting dialog - fix UI defect after using town portal spell - modify a message of joining 1 creature due to diplomacy - do not show income popup window for exit button in castle screen - change Tavern dialog caption color to yellow - fix rendering and mouse behavior for SDL2 - fix elements layout for surrendering dialog - fix shadow under battle summary dialog - fix surrendering cost calculation - fix Wagon sounds - fix castle and hero interaction with mouse in Kingdom Overview - play sound only after a battle with a monster to grab an artifact - change window title font color to yellow - fix Pyramid bad luck position - correct few sprites of mini-monsters - add a popup message for View Hero button - remove spaces for Level messages - clear message log for retreat case - add missing Info word for artifact status bar - add popup messages for next/previous pages in spell book - use keypad Enter as a normal one - add magic book image to popup window for no gold case - add evil UI elements for "Town portal" spell window - show proper information about enemy based on Thieves Guild count - fix layout for campaign selection window - fix wrong title and wrong text for Freeman's Foundry window - fix battle log text layout - use Delete key to erase a part of save filename - fix post game conditions - do not reset army while moving a hero to castle - start battle instantly if sounds are off - add captain portraits in Kingdom Overview - correctly reduce hero army after whirlpool - fix Mine info dialog near hero - reset Adventure Options buttons when cursor move out - draw shadow for empty boat - do not show army formation with no captain - fix stack overflow when using spells - fix disappearing hero while attacking monsters standing on a barrier - select a hero with move points when the focus is on a castle - increase Meteor Shower spell animation - fix spell order in magic book - change Artesian spring logic - fix Alchemist Tower artifact manipulation logic - assemble Battle Garb of Anduran artifact for hero meeting - place a hero into castle at the start of game - change map size popup window text - fix primary skill frame color in hero meeting dialog - add a title for joining army dialog - fix battle false hex shadow - fix drawings for meeting hero dialog - fix map loading message typo - update hero availability pool after hero purchase - show hero's name in magic book related windows - fix scenario selection stuck condition - fix portraits/hero information display in battle only mode - fix normal moral icon image - fix enemy army threat check for AI - fix changing boat direction by AI at boarding - fix Sorceress castle background image - fix missing spell point digits version 0.8.3 (04 November 2020) - protect higher value (based on buildings built) AI castles first - recruit AI heroes in castles other than the first one in the list - improve castle build order for AI (priority on gold income buildings) - improve castle monster recruitment - fix slowed flying creature movement - remember boat direction when a hero boarding it - update Town Portal dialog - fix "jump" flying animation when unit has to turn for attack - make one rumour per week in Taverns - fix a case of second attack on blinded creature - fix Monster Info dialog in evil interface - fix few castle icon sprites - speed up video loading - play sound on shipwreck pickup - fix Freeman Foundry UI - fix War Troll's stone sprite - fix Cavalry sprite - fix mage guild dialog message - change troop logic exchange during hero meeting - fix boat summoning animation - AI heroes are able to exchange armies and artifacts - add road connection drawings for Barbarian castle - fix castle defense trigger condition - do not show teleport animation in some AI cases - center Good and Evil interface windows - teach AI units to block enemy archers - show boat froth sprite when stationary - fix mine guardians sprites - fix battle only mode - improve army merge logic - fix lighthouse missing movement bonus - fix boat and hero positions - speed up drawings for World Map - fix pass image position on the world map - give at least 1 skeleton via necromancy after victory - fix Hero screen status bar message position - fix Hero meeting screen title position - change Pyramid Bad Luck message - fix Hero's portrait position in hiring window - fix town population status text position - fix boat animation and castle building rendering - fix troop counter window position - fix adjacent monsters when removing one - add after play animation - fix redraw order for unit count - use hero spell power when applying Earthquake - fix Lighthouse fog clearance - change Hut of the Magi behavior - add game resolution popup window - fix spelling in castle dialog - always show building requirements even if the building is already built - fix Knowledge message in Arena - five every magic guild a guaranteed damage and non-damage spell - fix OK button in joining army window - adjust few elements in resolution window - fix battle option text overlapping - adjust post battle shadowing - change main menu popup window descriptions - add a support of hero AI patrol mode set in scenario - make autosave with capital letters - disable spell animation after mine was cleared - save boat direction when disembarking - set parts of wide objects as visited - allow AI player to start it's move with action - use original difficulty bonuses for the game - check armies for validity before starting the battle - remove mud pool from cover object list - fix non-necro undead units decreasing morale in an all-undead army - remember Ghost number after the battle - AI is able to collect/capture multiple objects on the same move - adjust heuristics to make sure AI doesn't miss important objects - fix a bug where AI was able to buy boats in a castle without shipyard - fix the artifact spell damage modifiers - display a proper message for Sea Bottle - make AI more aggressive when dealing with archers during battle - replace "Ship Wreck" word with "Shipwreck" - set random starting experience for starting heroes - play flotsam disappearing sound after closing the UI window - fix income window drawings - when retreating, give the hero its default army instead of 1 T1 unit - stop battle after AI kills the last creature - use word 'one' instead of '1' in battle log - fix Thieves Guild background - fix visibility of AI hero moving close to fog - limit Player name text within given input box - show skip turn message during AI turns - allow to cast a spell with no move points - fix incorrect resurrected troops after battle - honor player count for Hot Seat mode - fix system options UI dialog - remove scrollbars from interface in battle only mode - add fading animation for defeated AI hero - fix time loss conditions in Info window - fix displaying of remaining move points - fix multiple text issues - modify messages for splitting army window - fix the clipped boat sprite version 0.8.2 (04 October 2020) - make correct spawn of neutral monsters and their growth - display correct window while right clicking on a monster in Kingdom Overview - add a transition while boarding and off-boarding boats - make hero animation movement smooth - fix price of loyalty artifact selection - fix tents/barriers from Price of Loyalty - fix monster placement at the beginning of months - fix missing dialog box in some rare cases - do not show journal scrollbar when it's not open - fix second attack for blinded creatures - fix typo in description of "Knowledge" skill at hero screen - replace the original project AI with an enhanced version of AI (making it not that stupid) - save neutral army monsters after battle - always reduce moral for visited Graveyard and Ship Wreck - allow heroes to move last step with remaining move points - update village's shadow after a castle was built - fix drawing castle's shadows under roads - fix missing objects on puzzle map - fix empty puzzle map - fix Ultimate image on puzzle map - fix puzzle map color scheme - fix treasure location map doesn't update after visiting obelisk - fix amount of creatures position in monster information dialog - fix object and shadow drawings on the World Map - fix few hero's names - draw all dead troops on the battlefield - allow to open hero's dialog during heroes meeting - fix dialog frame generation - fix bookmark positions in Spell Book - fix text position in creature recruit window - add Information window by right click on buttons in File dialog - add the word "Skill" for "Attack Skill" and "Defense Skill" in monster window - fix font generation and its position - fix popup windows for Spell Book - fix cursor for Adandoned mine protected by monsters - fix scrollbar in Settings window - extend campaign support - add proper AI base code for battle - change hero's description in tavern - use single OKAY button for Config window - don't shift High Score background for high resolutions - shift second hero's portrait in town - change unit movement speed in battle under spells - add dynamic color for item selection - add a popup window for clicking on Income in castle construction screen - remember move points of surrendered/retreated hero - fix bottom-to-top scrolling issue by keyboard key - reset dismissed hero's army - focus on a new hired hero in a castle - check magic resistance against Chain Lighting spell - fix multiple UI issues in Hero's Screen - add proper credits - center Hero's Options dialog - display spell points in magic book from bottom to top - display Liches for the City of the Dead - fix hero button position for joining window - fix a crash for Mirror image creature - reset music after exiting a castle - fix Daemon Cave incorrect window - fix Blind spell name - fix victory message in battle - fix File Options window position - fix text color for joining window - fix monster info shadow position - remove extra wince animation for cold ray spell - fix some icon positions in hero's dialog - center spell point text in hero's dialog - add word 'player' for defeated player window - fix creature shadow contour issue - add button choice support for campaign - fix cycling colors for mirrored Genie - add external music support by default - fix "battle: show damage info" option - fix Bloodlust animation - speed up calculations for path finding algorithm - fix caption issue with map's objects - fix missing resolutions and black screen for SDL 1 - add a dot at the end of multiple messages - fix few Phoenix frames - make scrollbar more user friendly in battle log - fix game info buttons - disable Next Hero button if none of heroes can move - fix multiplayer player count window position - fix graphical issues in big text font - fix creature animation going out of window - fix few scenario information window UI issues - optimize video playback - fix map size button state selection - fix New Game window UI elements - fix a crash while downgrading resolution in 8-bit mode - remove "castle: allow recruits special/expansion heroes" option - fix sky view status - fix generated window position - make Exit button disabled for popup windows in castle - fix Resurrection animation frame and moving dead units version 0.8.1 (04 September 2020) - play video intro at the opening - set focus on a hero while opening spell book - set minimum Spell Power to be always 1 - fix castle mini status icon - fix drawings of Mage Guilds in castles - remove multiple redundant / useless configuration settings - fix message dialog shadow - add proper support of configuration file - fix shift after opening and closing system options dialog - fix Gift button for evil interface - fix drawings of letters - fix Resurrect spell animation - add a support of disabled buttons - fix Air elemental drawings - remove "Manage creatures" button's shadow - add missing glowing effects of units in UI - fix screen dimming effects - change missing file message - fix Armageddon animation - update interface after exiting hero dialog - fix incorrect map extension crash - show diplomacy window always and fix marketplace button - add dot at the end of player's turn text - always center scenario window position - fix map difficulty text and its position - use proper config background window image - reset interface while changing its type - add game scenario dialog shadow - do not refocus after exiting castle's window - make Disabled Campaign button in High Score board - disable Campaign button if no files present - fix abandoned mine cursor - fix Sphinx message - modify Graveyard robber message - polish "battle only" button - show upgrade button if there's not enough money - fix lighthouse spelling - fix Dismiss button position in Hero's dialog - add missing title for graveyard message - fix graveyard message - fix marketplace text - show a dialog if a hero has no space for Spell Book - don't display artifact dialog for unknown artifact - fix an ability to skip button state by using a keyboard - apply Chain Lightning damage on allies as well - skip turn of resurrected troop - fix EXIT button position in creature window - fix AI turn crash - remove black background over army counter - don't show start and end position for monster log movement - add logic to handle inability to buy monsters in well - don't draw tent images in the castle window avoiding weird animation during castle construction - remove move penalty for visiting whirlpool/teleport - fix descriptions for Thief's Guild and for Pathfinding skill - fix logic of Town Gate spell - fix wrong OKAY button in System Options for Evil interface - skip heroes who do not have move points for move or sleep version 0.8 (26 July 2020) - add in-game option to change resolution - add fade-in / fade-out animation for AI heroes - fix logic when all stone liths were connected to each other even with different types - fix logic for stone liths in regard to allies - fix flickering of status bar in castle - fix attack cursor while pointing a monster - fix wolf's low attack animation - fix monster attack and fade animation on the World Map - add boat building animation - adjust hero battle dialog to align text - display boat froth sprite only if away from the coast - use correct sprite for castle's exit button - do not play sounds in castle's window when restoring the application - fix cursor for empty enemy castle - fix incorrect popping window in tavern - fix delayed mouse click on a cell during battle - fix hero's level up window with single secondary skill - fix system menu OKAY button - add SMK video file support - reset sound only if battle is shown - add support for ogg music from GOG version - fix castle drawings on the World Map - add Holy Shout spell blur effect - fix pathfinding calculations - increase the amount of sound channels to 16 - add death wave/ripple spell effect animation - fix Hypnotize and Berserk spell behaviors - correct battle hero animation - update elemental storm spell - "Summon boat" spell should not be used on a board - do not focus screen on a hero after adjusting scroll speed - fix Shipwreck empty battle - use only screen supported resolutions for the game - update focus logic for AI moving out of the fog - change mass spell icons - add frame border to highscore screen - reuse SDL2 texture for drawing speedup - adjust arena object dialog - set monster to static state after receiving a hit - fix mage guild window background - fix hero's status bar item locations - fix going out the battle window animation - shift battle log window by 1 pixel up - add a partial drawing support for disabled buttons - add Chain Lightning spell animation - add color cycling for active monster aura - fix incorrect hero's interaction with objects during movement - adjust flags animation with battle speed - make hero's movement smoother - show a proper status window message depending on resolution - fix last unit being hit 1 frame missing animation - remove Skill word from level up window text - add full animation in castles - update cursor while pointing over empty interface area - make "Next hero" button disable when no heroes exist - fix extra shifting upon landing for flying monsters - adjust music fade in effect and better sound selection - add monster animation on the World Map - fix fullscreen behavior in SDL 2 - fix World Map drawings and screen jumping during hero movement - fix display drawing during mouse movement in SDL 2 - fix ship shifting upon boarding it - add keyboard support for navigation in spell book - display different message in Mage Guild if no hero is in castle - fix text positioning in status bar - add lightning spell animation - do not run idle monster animation at every human's turn - fix marketplace window UI issues - fix creature contour drawing - add keyboard support for navigating between castles and heroes - add hero's flag animation in a world map - draw post attack animation in parallel so that battle animation does not look slow - add a flag to castle's captain - fix cursor offsets so that the cursor does not jump while changing its type - fix incorrect drawings for many interactive dialogs - make yellow frame for not available building info - fix hero hiring animation position - fix incorrect mouse cursor type during hero's movement by keyboard - add magic resist sound - add missing Skill word for Attack and Defense - fix fog drawings - multiple tweaks for AI - fix Spell Power naming in its icon and description - add animation of many objects on World Map - fix Mirror Image clone placement - add smooth screen scrolling during hero's movement - fix screen shifting when a hero initiates movement without movement points - complete hero's movement cell if an user clicks by mouse during hero's movement - add Stunning animation - fix Resurrect spell animation and logic - fix Armageddon and Earthquake animations - show gray text for spells which need more than current hero spell amount - set correct yellow and white font - fix BloodLust spell animation - fix incorrect stunning state rendering - add mirror image effect - fix puzzle view on high resolutions - remove Visual Studio 2015 Redistributable package dependency for 64-bit application on Windows - add F4 fullscreen hotkey support - set correct animation for Holy Word and Holy Shout spells - fix join/flee condition - fix castle siege logic - add an improved battle obstacle selection - fix multiple places with shadows while using alpha blending in SDL 1 - hide World Map for next turn in hot seat mode - add an ability to use scroll by mouse in SDL 2 - fix transparency on World Map and during Battle - fix message content and scrollbar for Town Portal spell - fix a crash during hero's dismiss - fix retaliation condition logic - fix a crash while checking hero with focused castle - change monster value heuristics for battle and strategic decisions - fix Mutant Zombie HP value - add color cycling for glowing effects on monsters during battle - show adventure map quick info by right click for dimension door spell - make hero's path visible after using a portal - add a log message for flying monsters - fix teleport and luck animation - fix ripple effect for disrupting ray and cold ray - update focus after hero's dismiss - add a condition to check down bridge for unit defense calculation - set World Map border size depending on resolution - add flag animation of neutral captain in a castle/town - do not move to current hero after closing hero's stats window - make interface background more uniform on high resolutions - add exit button during Dimension Door spell - update sounds and music upon teleport spell usage - add bad luck animation - fix blurred buttons in Adventure Panel - fix teleport delay in animation - sort spell icons by their duration in monster statistics window - fix defense formula for monster during battle - fix application exiting behavior (add support for Alt+F4 in Windows for SDL 2) - ignore bad spell status for Archmage attack - set correct post battle video sequence - fix hero fading animation - add min and max buttons for troop separation dialog - speed up rendering - fix hero's flag position in battle - fix inability to cast another spell upon cancellation teleport spell - play resource collection and sound after reading a dialog - fix monster frame jumps from multiple spells - fix medusa's stunning effect icon - fix Lich animation - fix monster count window position during battle - fix Archmage dispel post attack effect - fix Tower and Magic Arrow animation - fix the logic for Summon Boat spell - fix Identify Hero spell behavior - fix 0 monster count for Visions spell - add correct battle speed adjustment formula - show disable Dismiss button for a hero in a castle - fix idling condition check - add correct attacks and timing for monster animation during battle - give a control to an opponent over hypnotized monster - do not shift application window while loading a map for SDL 2 - fix Haunt spell incorrect behavior - add shadows to most of dialogs - play animation of treasure chest after the collection - fix incorrect position of a stunned monster - remove red cross over town's icon - fix new dwelling building animation - fix an ability to continue movement after Town portal spell - fix quick info window position at world map - show reflected monster animation in a dialog for right-side monsters - do not auto disable dimension door spell nearby world map edges - remove tiny ship icon from hero's status - do not move a hero over a portal above another hero - add hero movement interruption by left click - use shadowing for end movement cell during battle - fix inability to move artifacts - show a message if not enough points for digging - fix monster attack at the start of a new game - add fading animation after battle - limit Dimension Door spell range - fix invisible hero's path after Dimension Door spell - fix landing from a ship event to attack a monster after landing - fix incorrectly mixed spells for hero's book - fix Mass Cure spell icon - fix spell icon size and position for monster's info - fix cursor behavior beyond world edge - set correct position of monster in dwelling info - fix minimap colors - add an option to switch music type in settings - fix incorrect map object naming - fix hero, castle and status army info - add support for swapping palettes - fix hero movement at low speeds - fix display info of resources with scouting - fix spell sorting crash and mage guild positioning - add an optional aspect ratio correction in full-screen mode - fix a crash for unhired hero - fix alignment of text in monster info dialog - fix shifted monster position in recruit window - fix negative resources in kingdom possession - rework of midi music and sounds - fix current unit animation freezing state during battle - draw main menu as a background for High Score window - fix a case when not destroyed castle gate remains opened after a troop from a castle crossed the bridge during battle - fix Phoenixes naming - fix EXIT button position in castle options - set a correct position for buttons in Configuration dialog - fix Genie special ability - fix surrender action during battle - fix UI value input selectors - fix hero animation in battle - fix hero position in battle - add monster animation in army's info dialog - add monster movement animation in Well - use BIN file information for correct monster animation - fix unit damage formula - fix morale and luck events - add *nix case insensitive file access - make Army Order window during battle optional - fix flying monster animation offset - fix a crash for hot seat game start - add quit dialog popup window and change File Options dialog behavior - fix incorrect position of recruit Creature Info window in higher than default resolutions - add scalable Sprites support - do not show text for hidden Dismiss button - fix multiple memory leaks - add double quotes to surrender dialog version 0.7 (18 April 2020) - add an edge of the World Map - complete hero movement cell if a player stops it by any keyboard button - add hotkey 'N' to start a new game within the World Map like in the original game - fix crashes in multiple maps during map loading or during AI turns - fix game freezes during animation of resources collection - make human turn always first - do not show file save loading dialog if no saves exist - fix 'Adventure Options' button is being blurred after pressing it once on MacOS - cancel a dialog by pressing close window button - do not allow to move artifacts for not hired heroes in a castle - allow file selection by double-clicking on a list entry - fix MAX button state for monster change in recruitment window - update a cursor while stopping hero's movement - add monster animation in castle's well - set correct animation speed - fix scrolling behavior and add diagonal scrolling - display recruit monster window even for 0 creatures within castle's well - fix castle well UI elements - show hero movement arrow icons with proper colors - fix resizing of mini-map in fixed interface mode - do not show Necromancy window for 0 obtained skeletons - show an empty area instead of tavern building in Necromancer castle - fix a state of no information displayed in Signs - fix a crash after loading a save and starting any new game after - fix a crash during loading empty or newly saved configuration file - add initial campaign support (very early beta) - fix crystal resource position - fix hero path cursor display - add missing option's titles in Battle Option dialog - fix a popup messages for different types of resources at the World Map - fix application title disappearing after loading any map on SDL 2 - fix disabled black surrender button in hero's options in SDL 2 mode - move creature window info to the top of the castle screen - make "Buy from well" as a default option - remove speed 0 for battle and the World Map - fix spell book is being displayed in semi transparent way - hero path is recalculated each time when an user chooses the hero - show creature information in recruitment building - fix incorrectly displayed shadows on the World Map for SDL 2 - change AI behaviour for castle building strategy - fix positions of labels in in-game settings - remove 'Dismiss' button for a hero who is not hired yet in a castle - fix incorrectly shown message of found resources in the World Map bottom-right window - fix battle grid - add missing text in battle options dialog - fix World Map UI is being drawn inside castle options - fix shadow display in a battle - disable Spell button for castles - change font color for a creature's name - fix observation tower coverage area - hide dismiss button for monsters if a hero has only one stack of them - fix incorrect message for Shipyard by right click - fix missing battle hexagonal net was not appearing if enabled until next battle - display a warning message about missing files from the original game - disable Continue Movement button for a hero which does not have chosen path - required building names are displayed on a separate line each - fix no building image for already built building for right mouse click - fix incorrect image for Captains Quarters - renamed 'Free Heroes II' to 'fheroes2' - show disabled "Continue Movement" button for castle - fix number of monsters being displayed in a black box - add a script to download a demo version of the original game - set default display size to 640x480 pixels - add Windows build 30th August 2019 - move the repository to https://github.com/ihhub/fheroes2 fheroes2-1.1.6+dfsg/docs/000077500000000000000000000000001476115357100151155ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/docs/DEVELOPMENT.md000066400000000000000000000064661476115357100172350ustar00rootroot00000000000000# [**fheroes2**](README.md) build and contribution guide ## Build Please follow the instructions below to be able to build the project from source: **Note:** You will need to clone the `fheroes2` project before following the instructions below. ### Windows * Go to the directory `script/windows` and run the file `install_packages.bat`. This script will install all the required packages to build the project using Microsoft Visual Studio. * If you have the original game, then copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` (some of them may be missing depending on the version of the original game) to the project root directory. * Alternatively, go to the directory `script/demo` and run the file `download_demo_version.bat`. This script will download a demo version of the original game, which is the minimum required for development. * Open the file `fheroes2-vs2019.vcxproj` (targeted for Visual Studio 2019) and build the project. * Visual Studio will automatically copy game files in the root directory to the build directory. ### macOS and Linux * Depending on your OS, run the following scripts to install the dependencies required for the build: * macOS: go to the directory `script/macos` and run the file `install_sdl2.sh`. * Linux: go to the directory `script/linux` and run the file `install_sdl2_dev.sh`. * If you have the original game, then copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` (some of them may be missing depending on the version of the original game) to the project root directory. * Alternatively, go to the directory `script/demo` and run the file `download_demo_version.sh`. This script will download a demo version of the original game, which is the minimum required for development. * Run the `make` command in the root directory of the project to build it. ### Android * Go to the directory `script/android` and run the file `install_packages.bat` if your development platform is Windows or `install_packages.sh` if your development platform is macOS or Linux. This script will install all the required packages to build the project using Android Studio. * Launch Android Studio, open the project in the `android` directory and run the build. ### PlayStation Vita If you would like to build and run this project on PlayStation Vita please follow the instructions on [**this page**](README_PSV.md). ### Nintendo Switch If you would like to build and run this project on Nintendo Switch please follow the instructions on [**this page**](README_switch.md). ### Emscripten (Wasm) If you would like to run this project in a web browser please follow the instructions on [**this page**](README_emscripten.md). ### Build with CMake If you would like to build the project using CMake please follow the instructions on [**this page**](README_cmake.md). ## Contribution We welcome and appreciate any help, even if it is a tiny text or code change. Please read our [**contribution guide**](https://github.com/ihhub/fheroes2/blob/master/CONTRIBUTING.md) before starting work on a pull request. Not sure what to start with? Feel free to refer to [**good first issue**](https://github.com/ihhub/fheroes2/issues?q=is%3Aissue%20is%3Aopen%20label%3A%22good%20first%20issue%22) or [**help wanted**](https://github.com/ihhub/fheroes2/issues?q=is%3Aissue%20is%3Aopen%20label%3A%22help%20wanted%22) tags. fheroes2-1.1.6+dfsg/docs/GRAPHICAL_ASSETS.md000066400000000000000000000105021476115357100200110ustar00rootroot00000000000000# [**fheroes2**](README.md) graphical artist guide The original game has its graphical assets stored in the `HEROES2.agg` file and potentially the `HEROES2X.agg` file if the expansion pack The Price of Loyalty is present. These two AGG files are located in the `DATA` folder of the original Heroes 2 installation. For convenience's sake the fheroes2 project provides a set of tools and a script that artists can use to easily extract and convert the original graphical assets into viewable PNG files. New assets that the fheroes2 project adds to the game are included in the `files/data/resurrection.h2d` data file. This guide is designed for Linux, MacOS and Windows users. The source files to these tools are available in the project's repository. ## Where to get the tools You can download the precompiled tools for your operating system (OS) of choice here: [Windows 32-bit](https://github.com/ihhub/fheroes2/releases/download/fheroes2-windows-x86-SDL2/fheroes2_tools_windows_x86_SDL2.zip) [Windows 64-bit](https://github.com/ihhub/fheroes2/releases/download/fheroes2-windows-x64-SDL2/fheroes2_tools_windows_x64_SDL2.zip) [MacOS](https://github.com/ihhub/fheroes2/releases/download/fheroes2-osx-sdl2_dev/fheroes2_tools_macos_x86-64_SDL2.zip) [Linux Ubuntu 64-bit](https://github.com/ihhub/fheroes2/releases/download/fheroes2-linux-sdl2_dev/fheroes2_tools_ubuntu_x86-64_SDL2.zip) [Linux Ubuntu ARM 64-bit](https://github.com/ihhub/fheroes2/releases/download/fheroes2-linux-arm-sdl2_dev/fheroes2_tools_ubuntu_arm64_SDL2.zip) Here is a list and short description of the various graphical artist tools: * extractor This tool extracts all the contents of the AGG files mentioned above. Among the extracted files are the ICNs which hold the graphical assets. * icn2img This tool converts the various graphical assets contained within the ICNs into PNG or BMP files. * pal2img This tool generates a PNG or BMP file from the palette file `KB.PAL`. It displays it as 16x16 tiles of 16 pixels each. Some colors in the game are used for the cycling animation. They are marked in the generated image by a black area in the top-left corner on a tile. Use these colors only if the animation is a requirement: * 214, 215, 216, 217 * 218, 219, 220, 221 * 231, 232, 233, 234, 235 * 238, 239, 240, 241 ## How to use the tools to extract the images Place the `HEROES2.agg` and optionally the `HEROES2X.agg` files in the same folder as you extracted the tools to. Then run the script called `extract_agg`. This will create two folders: `agg` and `icn`. Both of them have a subdirectory named `HEROES2`, and potentially a `HEROES2X` one, reflecting what AGG file the contents come from. In addition running the script will generate a PNG file of the palette of the game with the name `palette.png` in the same directory as the folders `agg` and `icn`. The folder named `agg` contains the untouched contents of the AGG files. Meanwhile, the folder named `icn` contains the PNG-converted graphical assets. These assets will be stored within folders named according to what ICN they were stored in, e.g. the folder `apanel` came from the ICN `apanel.icn`. The `icn` folder is in other words the most relevant one for graphical artists. ## Where is help needed We have labelled and tracked some issues that need help from graphical artists. Issues that require changes of the original art can be found [here](https://github.com/ihhub/fheroes2/issues?q=is%3Aopen+is%3Aissue+label%3A"original+assets"). New art tasks can be found [here](https://github.com/ihhub/fheroes2/issues?q=is%3Aopen+is%3Aissue+label%3A"new+assets"). NOTE! Before starting to work on an issue make sure to check if someone isn't already assigned to it by looking at the relevant place within the issue. Also notify the fheroes2 team that you wish to work on the issue. This is to avoid duplicate work. ## The work process 1. Choose the item you are going to work on and notify the fheroes2 team to avoid duplicate work. 2. Present a prototype / complete enough work in your opinion of your work. 3. 1-2 members of the team will give their feedback. 4. Address the given feedback if any. 5. Repeat steps 3-4 until approval. 6. Expand the review team to 3-4 members and steps 3-4 are repeated. 7. Once everyone approves we will add this file into the `resurrection.h2d` data file and change the code in the fheroes2 source code to use it. fheroes2-1.1.6+dfsg/docs/INSTALL.md000066400000000000000000000417171476115357100165570ustar00rootroot00000000000000# [**fheroes2**](README.md) installation guide ## Requirements You will need to have a demo version or the full version of **Heroes of Might and Magic II** game to be able to play. We strongly advise to purchase the original game on [**GOG**](https://www.gog.com) or [**Ubisoft Store**](https://store.ubi.com) platforms. Alternatively, you can **download a free demo version of the game (in English only) using the bundled script**. See detailed instructions below. ## Installation Precompiled binaries of the release version are currently available for the following platforms and operating systems: * [**Windows**](#windows) * [**Windows installer**](#windows-installer) * [**Windows ZIP archive**](#windows-zip-archive) * [**macOS**](#macos) * [**Homebrew**](#homebrew-on-macos) * [**MacPorts**](#macports) * [**macOS ZIP archive**](#macos-zip-archive) * [**macOS native app**](#macos-native-app) * [**Linux**](#linux) * [**Flatpak**](#flatpak) * [**Gentoo**](#gentoo-package) * [**Homebrew**](#homebrew-on-linux) * [**AUR package**](#aur-package) * [**Debian and Ubuntu**](#debian-and-ubuntu) * [**Linux ZIP archive**](#linux-zip-archive) * [**Android**](#android) * [**PlayStation Vita**](#playstation-vita) * [**Nintendo Switch**](#nintendo-switch) Alternatively, you can download the precompiled binaries of the latest commit (snapshot) [**here**](#snapshots-latest-builds). ## Windows ### Windows installer * Download one of the following Windows installer packages: [**Windows x64 (64-bit)**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_windows_x64_SDL2_installer.exe) or [**Windows x86 (32-bit)**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_windows_x86_SDL2_installer.exe) * After downloading the installer, launch it and follow the instructions. * During the installation process, you will be prompted to extract game resources from the original game (select this option if you already have a legally purchased copy of the original game installed), or download the demo version of the original game and extract game resources from it (you can also do this later by clicking the appropriate shortcut in the program's group in the Windows Start menu). * If you purchased a copy of the original game only after installing fheroes2, you can run the `Extract game resources from the original distribution of HoMM2` shortcut in the program's group in the Windows Start menu. This script will try to perform an automatic search for an existing installation of the original game and extract all the necessary resource files. If it can't find an existing installation, you will be prompted to enter the location of the original game manually. * As an alternative to the previous step, you can manually copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` (some of them may be missing depending on the version of the original game) from the original game directory to the fheroes2 installation directory. ### Windows ZIP archive * Download one of the following Windows ZIP archives: [**Windows x64 (64-bit)**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_windows_x64_SDL2.zip) or [**Windows x86 (32-bit)**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_windows_x86_SDL2.zip) * After downloading the ZIP archive, extract it to a suitable directory of your choice. * If you have a legally purchased copy of the original game, run the `extract_homm2_resources.bat` script supplied in the ZIP archive. This script will try to perform an automatic search for an existing installation of the original game and extract all the necessary resource files. If it can't find an existing installation, you will be prompted to enter the location of the original game manually. * As an alternative to the previous step, you can manually copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` (some of them may be missing depending on the version of the original game) from the original game directory to the fheroes2 installation directory. * If you don't have a legally purchased copy of the original game, you can download and install the demo version of the original game by running the `download_demo_version.bat` script supplied in the ZIP archive. If you see complaints about missing DLLs when running fheroes2, then you may need to install the Microsoft Visual C++ redistributable package. You can download it using the following URLs: [**https://aka.ms/vs/17/release/vc_redist.x64.exe**](https://aka.ms/vs/17/release/vc_redist.x64.exe) - for 64-bit x64 fheroes2 builds; [**https://aka.ms/vs/17/release/vc_redist.x86.exe**](https://aka.ms/vs/17/release/vc_redist.x86.exe) - for 32-bit x86 fheroes2 builds. ## macOS ### Homebrew on macOS If you are using [**Homebrew**](https://brew.sh/), you can install the game by running the following command: ```sh brew install fheroes2 ``` Follow the [**instructions below**](#gathering-game-resources) to gather resources necessary for fheroes2 to function as expected. ### MacPorts If you are using [**MacPorts**](https://www.macports.org/), you can install the game by running the following command: ```sh port install fheroes2 ``` Then follow the instructions on the screen. Follow the [**instructions below**](#gathering-game-resources) to gather resources necessary for fheroes2 to function as expected. ### macOS ZIP archive * Download the [**macOS ZIP archive**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_macos_x86-64_SDL2.zip). Currently only x86-64 binaries are provided. If you use a machine with an Apple Silicon chip, you should choose another installation method (using [**MacPorts**](#macports) or [**Homebrew**](#homebrew-on-macos)), or [**build the project from source**](DEVELOPMENT.md#macos-and-linux). * After downloading the ZIP archive, extract it to a suitable directory of your choice and then run the script `install_sdl2.sh` from the `script/macos` subdirectory. This will install the SDL libraries required to run the game. Follow the [**instructions below**](#gathering-game-resources) to gather resources necessary for fheroes2 to function as expected. ### macOS native app * Download the source and compile with the `-DMACOS_APP_BUNDLE=ON` option (if using CMake) or using the following command (with make): ```sh make FHEROES2_MACOS_APP_BUNDLE=ON ``` Follow the [**instructions below**](#gathering-game-resources) to gather resources necessary for fheroes2 to function as expected. ### Gathering game resources Once you obtain the fheroes2 executable using any of the options above, you should follow these steps to load in the correct resources: * If you have a legally purchased copy of the original game in a self-extracting Windows executable (such as from GOG), you can utilize [`innoextract`](https://constexpr.org/innoextract/#use) to extract files out of the exe without having to use Wine/Windows emulation software on your *UNIX-based machine. * If you have a legally purchased copy of the original game, run the extract resources script which will prompt you to enter the location of the original game, and will extract all the necessary resource files. The script can be run from the following paths depending on how you installed fheroes2: * `fheroes2-extract-resources` if you used a package manager (MacPorts or Homebrew); * `script/homm2/extract_homm2_resources_for_app_bundle.sh` if you built from source using the [**macOS native app**](#macos-native-app) method; * `script/homm2/extract_homm2_resources.sh` for all other cases. * As an alternative to the previous step, you can manually copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` (some of them may be missing depending on the version of the original game) from the original game directory to * `~/Library/Application Support/fheroes2` if you built from source using the [**macOS native app**](#macos-native-app) method; * `~/.fheroes2` for all other cases. * If you don't have a legally purchased copy of the original game, you can download and install the demo version of the original game by running the download demo script. The script can be run from the following paths depending on how you installed fheroes2: * `fheroes2-install-demo` if you used a package manager (MacPorts or Homebrew); * `script/demo/download_demo_version_for_app_bundle.sh` if you built from source using the [**macOS native app**](#macos-native-app) method; * `script/demo/download_demo_version.sh` for all other cases. ## Linux ### Flatpak If you are using [**Flatpak**](https://flatpak.org) and [**Flathub**](https://flathub.org), you can install the game by running the following command: ```sh flatpak install flathub io.github.ihhub.Fheroes2 ``` And launch from the start menu or the console: ```sh flatpak run io.github.ihhub.Fheroes2 ``` Alternatively, you can use an application manager like Discover, which is also available on Steam Deck. After the first start you will be asked for the original files. There are three possibilities: 1. Install GOG version (recommended) 2. Manual install 3. Install demo The recommended option requires the Heroes of Might and Magic II installer file (*.exe) from GOG. This will extract the appropriate resources by itself. For the manual installation you have to copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` from the original game or demo directory to the `~/.var/app/io.github.ihhub.Fheroes2/data/fheroes2` directory. The destination folder will be opened when this option is selected. ### Gentoo package If you are using [**Gentoo**](https://gentoo.org), you can install the game using package manager. There are several options: #### GOG version If you purchased the game from GOG, add `games-strategy/homm2-gold-gog GOG-EULA` line to your `/etc/portage/package.license`, then use the following command: ```sh sudo emerge -av games-strategy/homm2-gold-gog ``` It will ask you to put the .exe installer of the game and optionally the zip file with FLAC music to your distfiles directory, and if it's there, it will unpack everything to the correct places and pull `games-engines/fheroes2` as a dependency. USE-flag `flac` determines whether the game will use FLAC music or OGG music. #### Demo version You can install the demo version for free by adding `games-strategy/homm2-demo HoMM2-Demo` line to your `/etc/portage/package.license`, then using the following command: ```sh sudo emerge -av games-strategy/homm2-demo ``` #### Another legal installation If you installed the game from original CD, use the following commands: ```sh sudo emerge -av games-engines/fheroes2 /usr/share/fheroes2/extract_homm2_resources.sh ``` The second command (Note: run it without root) will ask you where your data files are. ### Homebrew on Linux If you are using [**Homebrew**](https://brew.sh/), you can install the game by running the following command: ```sh brew install fheroes2 ``` If you have a legally purchased copy of the original game, copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` (some of them may be missing depending on the version of the original game) from the original game directory to the `$XDG_DATA_HOME/fheroes2` (usually `~/.local/share/fheroes2`) directory. Otherwise, you can download and install the demo version of the original game by running the `/usr/share/fheroes2/download_demo_version.sh` script. ### AUR package If you are using Arch Linux or compatible distribution, you can install [**fheroes2 package**](https://aur.archlinux.org/packages/fheroes2) from AUR (Arch User Repository). #### Install using AUR helper If you use one of AUR helpers, e.g. `yay`, you can install the game by running the following command: ```sh yay -S aur/fheroes2 ``` #### Install using the official guide Follow the [**official guide**](https://wiki.archlinux.org/title/Arch_User_Repository#Installing_and_upgrading_packages). One of possible command sets: ```sh git clone https://aur.archlinux.org/fheroes2.git cd fheroes2 makepkg -si ``` ### Debian and Ubuntu fheroes2 is available from `contrib` repositories for Debian (since 13) and Ubuntu (since 24.04). You can install it by running: ```sh apt install fheroes2 ``` These distributions may not provide the latest version of the game due to their release cycle. #### Game resources To play the game you need the original game resources. You can install them to per-user paths (`man fheroes2` for more info, or you can install them to the system-wide path (`/usr/share/games/fheroes2`) with `game-data-packager` program (since v70). To make the resource package: ```sh game-data-packager heroes2 apt install ./homm2-data__all.deb ``` You can get more info about resource packaging by running `game-data-packager heroes2 --help` ### Linux ZIP archive * Download one of the following Linux ZIP archives: [**Linux x86-64**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_ubuntu_x86-64_SDL2.zip) or [**Linux ARM64**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_ubuntu_arm64_SDL2.zip) * After downloading the ZIP archive, extract it to a suitable directory of your choice. Then you will need to install the SDL libraries required to run the game. The installation procedure depends on the Linux distribution you are using: * **Debian-based**: run the script `install_sdl2.sh` from the `script/linux` subdirectory. * **Pacman-based (e.g. Arch Linux)**: run the following command: `sudo pacman -S sdl2 sdl2_mixer`. * **RedHat-based**: for RPM-based distributions (such as Fedora or RedHat) use the commands `sudo yum install SDL*` or `sudo dnf install SDL*`. * **openSUSE**: openSUSE supports the One-Click-Install using the `SDL_mixer.ymp` file from the `script/linux` subdirectory. * **Gentoo**: run the following command: `emerge --ask media-libs/sdl2-mixer`. * After all dependencies are installed, run the `extract_homm2_resources.sh` script supplied in the ZIP archive if you have a legally purchased copy of the original game. You will be prompted to enter the location of the original game, and the script will extract all the necessary resource files. * As an alternative to the previous step, you can manually copy the subdirectories `ANIM`, `DATA`, `MAPS` and `MUSIC` (some of them may be missing depending on the version of the original game) from the original game directory to the fheroes2 installation directory. * If you don't have a legally purchased copy of the original game, you can download and install the demo version of the original game by running the `download_demo_version.sh` script supplied in the ZIP archive. ## Android * Install the fheroes2 app from [**Google Play**](https://play.google.com/store/apps/details?id=org.fheroes2) or download the [**Android ZIP archive**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_android.zip). * Follow the [**instructions**](README_android.md). ## PlayStation Vita **Please note**: you need to be running custom firmware for it to work. * Download the [**PlayStation Vita ZIP archive**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_psv.zip). * Follow the [**instructions**](README_PSV.md). ## Nintendo Switch **Please note**: you need to be running custom firmware for it to work. * Download the [**Nintendo Switch ZIP archive**](https://github.com/ihhub/fheroes2/releases/latest/download/fheroes2_switch.zip). * Follow the [**instructions**](README_switch.md). ## Snapshots (latest builds) You can download the precompiled binaries of the latest commit (snapshot) for **Windows** ( [**x64 SDL2**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-windows-x64-SDL2) and [**x86 SDL2**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-windows-x86-SDL2) ), **macOS x86-64** ( [**SDL2**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-osx-sdl2_dev) ), **Ubuntu** ( [**x86-64 SDL2**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-linux-sdl2_dev) and [**ARM64 SDL2**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-linux-arm-sdl2_dev) ), [**Android**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-android), [**PlayStation Vita**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-psv-sdl2_dev) and [**Nintendo Switch**](https://github.com/ihhub/fheroes2/releases/tag/fheroes2-switch-sdl2_dev). **These binaries incorporate all the latest changes, but also all the latest bugs, and are mainly intended for developers.** **DON'T EXPECT THEM TO WORK PROPERLY.** fheroes2-1.1.6+dfsg/docs/Makefile000066400000000000000000000040211476115357100165520ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### LIN_DATA := $$HOME/.local/share/fheroes2 LIN_CONF := $$HOME/.config/fheroes2 UNIX_DATA := $$HOME/.fheroes2 SEDEX := /^\#_SG/,/^\#_EG/ d ifneq ($(FHEROES2_DATA),) SEDEX := /^\#_SG/,/^\#_EG/ { /^\#_[SE]G/d; s:@FHEROES2_DATA@:$(FHEROES2_DATA):} endif ifeq ($(shell uname), Linux) SEDEX := $(SEDEX); s:@data@:$(LIN_DATA):; s:@config@:$(LIN_CONF): else SEDEX := $(SEDEX); /@data@/,/^This path/ {s:@data@:$(UNIX_DATA):; /^This path/d} SEDEX := $(SEDEX); /@config@/,/^This path/ {s:@config@:$(UNIX_DATA):; /^This path/d} endif .PHONY: all clean all: sed -e '$(SEDEX)' fheroes2.6.in > fheroes2.6 clean: -rm -f fheroes2.6 fheroes2-1.1.6+dfsg/docs/PRIVACY_POLICY.md000066400000000000000000000017331476115357100176370ustar00rootroot00000000000000# [**fheroes2**](README.md) privacy policy **fheroes2** is provided at no cost and is intended for use as is. This document is used to inform regarding our policies with the collection, use, and disclosure of Personal Information if anyone decided to use fheroes2. If you choose to use fheroes2, then you agree to this policy. ## General **fheroes2** is an open source project and it does not collect any personal information in any of its official GitHub and Google Play Store releases. The project does not contain any library or programming module from third-party suppliers which collects sensitive personal information from its users. ## Contact information If you have any questions or concerns about any of the matters in relation to this Privacy Policy then there are several ways of contacting us: * via email to * via Discord at by contacting any of the collaborators This Privacy Policy was last updated 04th April 2023. fheroes2-1.1.6+dfsg/docs/README.md000066400000000000000000000107031476115357100163750ustar00rootroot00000000000000# fheroes2 **fheroes2** is a recreation of the Heroes of Might and Magic II game engine. This open source multiplatform project, written from scratch, is designed to reproduce the original game with significant improvements in gameplay, graphics and logic (including support for high-resolution graphics, improved AI, numerous fixes and user interface improvements), breathing new life into one of the most addictive turn-based strategy games. You can find a complete list of all of our changes and enhancements in [**its own wiki page**](https://github.com/ihhub/fheroes2/wiki/Features-and-enhancements-of-the-project).

Screenshot of the world map

Screenshot of the battle screen Screenshot of the castle screen

## Download and install Please follow the [**installation guide**](INSTALL.md) to download and install fheroes2. [![Github Downloads](https://img.shields.io/github/downloads/ihhub/fheroes2/total.svg)](https://github.com/ihhub/fheroes2/releases) ## Copyright All rights for the original game and its resources belong to former The 3DO Company. These rights were transferred to Ubisoft. We do not encourage and do not support any form of illegal usage of the original game. We strongly advise to purchase the original game on [**GOG**](https://www.gog.com) or [**Ubisoft Store**](https://store.ubi.com) platforms. Alternatively, you can download a free demo version of the game. Please refer to the [**installation guide**](INSTALL.md) for more information. ## License This project is licensed under the [**GNU General Public License v2.0**](https://github.com/ihhub/fheroes2/blob/master/LICENSE). Initially, the project was developed on [**sourceforge**](https://sourceforge.net/projects/fheroes2/). ## Contribution and Development This repository is a place for everyone. If you want to contribute, please read more [**here**](https://github.com/ihhub/fheroes2/wiki/F.A.Q.#q-how-can-i-contribute-to-the-project). To build the project from source, please follow [**this guide**](DEVELOPMENT.md). [![Build Status](https://github.com/ihhub/fheroes2/actions/workflows/push.yml/badge.svg)](https://github.com/ihhub/fheroes2/actions) [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=bugs)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=code_smells)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) [![Duplicated Lines (%)](https://sonarcloud.io/api/project_badges/measure?project=ihhub_fheroes2&metric=duplicated_lines_density)](https://sonarcloud.io/dashboard?id=ihhub_fheroes2) To assist with the graphical asset efforts of the project, please look at our [**graphical artist guide**](GRAPHICAL_ASSETS.md). If you would like to help translating the project, please read the [**translation guide**](TRANSLATION.md). ## Donation We accept donations via [**Patreon**](https://www.patreon.com/fheroes2), [**PayPal**](https://www.paypal.com/paypalme/fheroes2) or [**Boosty**](https://boosty.to/fheroes2). All donations will be used only for the future project development as we do not consider this project as a source of income by any means. [![Donate](https://img.shields.io/badge/Donate-Patreon-green.svg)](https://www.patreon.com/fheroes2) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/paypalme/fheroes2) [![Donate](https://img.shields.io/badge/Donate-Boosty-green.svg)](https://boosty.to/fheroes2) ## Contacts Follow us on social networks: [**Facebook**](https://www.facebook.com/groups/fheroes2) or [**VK**](https://vk.com/fheroes2). We also have a [**Discord**](https://discord.gg/xF85vbZ) server to discuss the development of the project. [![Facebook](https://img.shields.io/badge/Facebook-blue.svg)](https://www.facebook.com/groups/fheroes2) [![VK](https://img.shields.io/badge/VK-blue.svg)](https://vk.com/fheroes2) [![Discord](https://img.shields.io/discord/733093692860137523.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/xF85vbZ) ## FAQ You can find answers to the most commonly asked questions on our [**F.A.Q. page**](https://github.com/ihhub/fheroes2/wiki/F.A.Q.). fheroes2-1.1.6+dfsg/docs/README.txt000066400000000000000000000044151476115357100166170ustar00rootroot00000000000000--- Copyright --- All rights for the original game and its resources belong to former The 3DO Company. These rights were transferred to Ubisoft. We do not encourage and do not support any form of illegal usage of the original game. We strongly advise to purchase the original game on GOG or Ubisoft Store platforms. Alternatively, you can download a free demo version of the game (in English only) using one of the bundled scripts. --- Installation and Requirements --- You will need to have a demo version or the full version of Heroes of Might and Magic II game to be able to play. If you do not have the original Heroes of Might and Magic II game, run the 'download_demo_version.bat' file for Windows or 'download_demo_version.sh' for Linux OS and macOS. This script will download and install all the necessary files from the demo version of the original Heroes of Might and Magic II game. If you have a legally purchased copy of the original game, run the 'extract_homm2_resources.bat' file for Windows or 'extract_homm2_resources.sh' for Linux OS and macOS. This script will extract all the necessary resource files. As an alternative to the previous step, you can manually copy the subdirectories 'ANIM', 'DATA', 'MAPS' and 'MUSIC' (some of them may be missing depending on the version of the original game) from the original game directory to the fheroes2 installation directory. If you are running fheroes2 on Windows and see complaints about missing DLLs, then you may need to install the Microsoft Visual C++ redistributable package. You can download it using the following URLs: https://aka.ms/vs/17/release/vc_redist.x86.exe - for 32-bit x86 fheroes2 builds; https://aka.ms/vs/17/release/vc_redist.x64.exe - for 64-bit x64 fheroes2 builds. Or you can install the game using the installer, in this case, this package will be installed automatically. --- License --- This project is under GNU General Public License v2.0. Refer to file LICENSE for more details. --- Donation --- Currently we accept donations via Patreon at https://www.patreon.com/fheroes2, via PayPal at https://www.paypal.com/paypalme/fheroes2 and via Boosty at https://boosty.to/fheroes2. All donations will be used only for the future project development as we do not consider this project as a source of income by any means. fheroes2-1.1.6+dfsg/docs/README_PSV.md000066400000000000000000000037521476115357100171330ustar00rootroot00000000000000# PlayStation Vita port of [**fheroes2**](README.md) project ## Install Install fheroes2.vpk to your Vita. fheroes2 requires data files from the original Heroes of Might and Magic II. Copy HEROES2.AGG and HEROES2X.AGG (if you own Price of Loyalty expansion) from the original games "DATA" folder into "ux0:data/fheroes2/data" and everything from "MAPS" folder into "ux0:data/fheroes2/maps". Music files in OGG format (from GoG release of the game) should be placed into the "ux0:data/fheroes2/music/" folder. fheroes2 supports ingame cinematics. To play into and/or other videos, make sure that all of "*.SMK" files are placed inside "ux0:data/fheroes2/heroes2/anim/" folder. [rePatch reDux0](https://github.com/dots-tb/rePatch-reDux0) OR [FdFix](https://github.com/TheOfficialFloW/FdFix) plugin is required for proper suspend/resume support (only use one at a time). ## Building ### Prerequisites * VitaSDK * libSDL2 * libSDL2-mixer To build the game just run ```sh make -f Makefile.vita ``` ## Controls * Left analog stick - Pointer movement * Right analog stick - Map scrolling * × - Left mouse button * ○ - Right mouse button * □ - End turn * △ - Open spellbook * D-Pad left - Next hero * D-Pad right - Next castle * D-Pad down - Re-visit the object that hero stands on * R1 - Cursor acceleration * SELECT - System menu * START - Enter Text input is done with D-Pad. * Left - Remove character * Right - Add new character * Down - Next character (alphabetically) * Up - Previous character * R1, L1 - Switch current character between uppercase/lowercase ## Vita specific options Pointer movement speed can be changed with 'gamepad_pointer_speed' parameter in "ux0:data/fheroes2/fheroes2.cfg". Use "fullscreen = on" option to scale game area to native Vita resolution or "fullscreen = off" to keep the game area at the center of the screen. Native resolution is supported (set "videomode = 960x544" option in config file or just click on the left door in main menu and select resolution manually). fheroes2-1.1.6+dfsg/docs/README_android.md000066400000000000000000000060751476115357100201040ustar00rootroot00000000000000# Android port of [**fheroes2**](README.md) project ## Installation Install the fheroes2.apk to your device running Android. You need to have set the necessary permissions on your device to do this. fheroes2 requires the data files from the original Heroes of Might and Magic II. If you do not have the original game you can download a demo version of the game from If you already have a legally purchased copy of the original game, then put the directories "ANIM", "DATA", "MAPS" and "MUSIC" from your original Heroes of Might and Magic II installation into a ZIP archive and copy this archive to your Android device. Run the "fh2 Toolset" app, press the "Extract HoMM2 assets" button and select either the ZIP archive of the demo version or the ZIP archive created by you in the previous step to extract the assets of the original game to the proper place. Depending on your version of Heroes 2, the music files that need to be placed in the "MUSIC" directory can either be on your original CD or in the installation folder (GOG and Ubisoft). Ingame cinematics are supported by fheroes2 and for these to be supported it is necessary to have them in the "ANIM" folder. Depending on your original version of Heroes 2 they can either be found on your CD, disc image or in a folder named "anim" in your Heroes 2 installation directory. ## Controls To simulate a right-click to get info on various items, you need to first touch and keep touching on the item of interest and then touch anywhere else on the screen. While holding the second finger, you can remove the first one from the screen and keep viewing the information on the item. By default normal adventure map scrolling on the borders of the screen is disabled. To pane the viewing area around you need to press anywhere on the adventure map and slide around to change where you are viewing. During combat, actions (such as moving, attacking, or casting a spell) performed using the touchpad/touchscreen must be confirmed. The first touch event just places the cursor at the touch point, displaying information about the action being performed (the cell/cells to be moved to, the angle of attack and the cells subject to attack, the spell and the cells affected by this spell, potential damage, and so on). The second touch event is confirmatory, and performs the corresponding action if and only if this action exactly corresponds to the action that the first touch demonstrates. To make it easier to select the angle of attack on touchscreens, you can "draw" the angle by swiping your finger from the cell you intend to attack from, to the cell occupied by the enemy unit. Next, you should remove your finger from the screen, double-check your planned attack, and then confirm the action by touching the target cell with your finger again. ## Android specific notes Fullscreen is enabled by default. To have the info bar with the clock visible you can disable fullscreen mode within the main menu settings under "Graphics". The minimum supported Android version is 5.1. fheroes2-1.1.6+dfsg/docs/README_cmake.md000066400000000000000000000041211476115357100175320ustar00rootroot00000000000000# Building with CMake ## Linux and macOS [**fheroes2**](README.md) can be built with CMake buildsystem. First, you need to install dependencies. For Linux and macOS follow to instructions as described above. Next, you can configure the project with following commands: ```shell cmake -B build ``` After configuration let's build the project: ```shell cmake --build build ``` After building, executable can be found in `build` directory. ## Windows / Visual Studio For Windows you'll need Visual Studio 2019 with C++ support and [vcpkg package manager](https://vcpkg.readthedocs.io/en/latest/) for dependency management. Here quick and short instruction for deployment: ```shell # Clone vcpkg repository. For convenient, let's place it in C:\vcpkg directory, but it can be anywhere. git clone https://github.com/microsoft/vcpkg.git # Now initialize manager .\vcpkg\bootstrap-vcpkg.bat ``` Your vcpkg is ready to install external libraries. Assuming that you use x64 system, let's install all needed dependencies: ```shell .\vcpkg\vcpkg --triplet x64-windows install sdl2 sdl2-image sdl2-mixer zlib ``` If you planning to develop fheroes2 with Visual Studio, you may want to integrate vcpkg with it (requires elevated admin privileges). After following command Visual Studio automagically will find all required dependencies: ```shell .\vcpkg\vcpkg integrate install ``` Now you are ready to configure the project. cd to fheroes2 directory and run `cmake` command (note for `-DCMAKE_TOOLCHAIN_FILE` and `-DVCPKG_TARGET_TRIPLET` options): ```shell cmake -B build -DCMAKE_TOOLCHAIN_FILE="C:\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET=x64-windows ``` After configuration let's build the project: ```shell cmake --build build --config Release ``` After building, executable can be found in `build\Release` directory. ## Using Demo data CMake project allows to download and install original HoMM II Demo files which used by fheroes2 project. To do this please add `-DGET_HOMM2_DEMO=ON` to configuration options. For example: ```shell cmake -B build -DGET_HOMM2_DEMO=ON ``` fheroes2-1.1.6+dfsg/docs/README_emscripten.md000066400000000000000000000043531476115357100206320ustar00rootroot00000000000000# Emscripten (Wasm) port of [**fheroes2**](README.md) project ## Current status of this port Please note that this port is currently still **experimental**. You may experience various problems, crashes, or it not even working at all in particular browsers. ## Building ### Prerequisites * emsdk 4.0 or later * GNU gettext ### Building using Docker To save time, you can use a ready-made Docker image: ```sh docker run --rm -v "$(pwd):/src" emscripten/emsdk:latest sh -c "apt-get -y update; apt-get -y install gettext; emmake make -f Makefile.emscripten" ``` ### Building without Docker If you do not want to use Docker, then you will need to install all the prerequisites manually using your platform's package manager, and then run the following command: ```sh emmake make -f Makefile.emscripten ``` ### Building with additional parameters If you want to specify some additional ad hoc build parameters, you can use the appropriate environment variables for this. For example, the following command: ```sh FHEROES2_WITH_THREADS=ON LDFLAGS="-sMODULARIZE -sEXPORTED_RUNTIME_METHODS=run -sEXPORT_NAME=fheroes2" emmake make -f Makefile.emscripten ``` will build a WebAssembly binary with multithreading support, as well as with additional parameters for creating a module. ## Running the Wasm port on a web server ### Configuring the web server Emscripten uses web workers along with `SharedArrayBuffer` to support multithreading. `SharedArrayBuffer` usage is usually protected by Cross Origin Opener Policy (COOP) and Cross Origin Embedder Policy (COEP) HTTP headers, and the web server should send these headers as part of its response to a request for resources related to the Wasm build: ```text Cross-Origin-Opener-Policy: same-origin Cross-Origin-Embedder-Policy: require-corp ``` Please see the following link for details: ### Copying necessary files After the build is completed, copy the following files to the appropriate directory on your website: ```text fheroes2.data fheroes2.js fheroes2.wasm fheroes2.wasm.map (if fheroes2 has been built in debug mode) ``` If you want to use the stock launcher (pretty basic at the moment), then you will also need to copy all the files from `files/emscripten` to the same directory. fheroes2-1.1.6+dfsg/docs/README_switch.md000066400000000000000000000037471476115357100177700ustar00rootroot00000000000000# Nintendo Switch port of [**fheroes2**](README.md) project It's a homebrew app, so you need to be running custom firmware for it to work. ## BUILDING You will need to install the [devkitPro](https://devkitpro.org/) toolchain. Make sure to include the following package: ```text libnx switch-sdl2_mixer ``` After installation run `make -f Makefile.switch -j 2` command to build the package. ## SETUP You will need a copy of the official game to run this port. fheroes2 root directory is hardcoded as `/switch/fheroes2`. Put the game files there (specifically `ANIM`, `DATA`, `MAPS` and `MUSIC` folders), then copy over the `files` directory, as well as `fheroes2.nro`. If you have a Russian version from Buka Enternainment, you'll likely have `Anim2` folder instead. Rename it to `ANIM` if you wish use the Buka game data with this port. At the end you should have the following directory tree on your SD card: ```text switch | +-- ... +-- fheroes2 <--- this is the game directory | +--- anim <--- HoMM2 game data +--- data <--- HoMM2 game data +--- files <--- Part of fheroes2 release +--- maps <--- HoMM2 game data +--- music <--- HoMM2 game data +--- fheroes2.nro <--- Part of fheroes2 release ``` Generally, you will need game resources from the localized version of HoMM2 in order to use translations in fheroes2. During the first run, the game should auto-detect the game data you have and offer to choose a language you'd like to use. English is always available. ## RUNNING This build of fheroes2 was tested on 12.0.3|AMS M.19.4|S (FAT32). exFAT is not recommended. USB mice and keyboards connected via an OTG adapter are supported. Working controls are: * Touchscreen - emulates mouse, including dragging * L-stick - move mouse cursor * R-stick/D-pad - scroll * A - left mouse click * B - Right mouse click * X - Escape * Y - Enter * (+) - Cast spell * (-) - End turn * R - Cycle through towns * L - Cycle through heroes fheroes2-1.1.6+dfsg/docs/TRANSLATION.md000066400000000000000000000224531476115357100172430ustar00rootroot00000000000000# [**fheroes2**](README.md) translation guide This project uses portable object (PO) files to handle localization in various languages. The PO files are located in the `files/lang` subdirectory of the project source tree. The current instruction is designed for Linux, MacOS and Windows users. ## Current status ![Belarusian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_be.json) ![Bulgarian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_bg.json) ![Czech](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_cs.json) ![German](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_de.json) ![Danish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_dk.json) ![Spanish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_es.json) ![French](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_fr.json) ![Hungarian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_hu.json) ![Italian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_it.json) ![Lithuanian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_lt.json) ![Norwegian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_nb.json) ![Dutch](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_nl.json) ![Polish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_pl.json) ![Brazilian Portuguese](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_pt.json) ![Romanian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_ro.json) ![Russian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_ru.json) ![Slovak](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_sk.json) ![Swedish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_sv.json) ![Turkish](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_tr.json) ![Ukrainian](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_uk.json) ![Vietnamese](https://img.shields.io/endpoint?url=https://ihhub.github.io/fheroes2/json/lang_vi.json) ## Adding new translations/localizations If you want to add a new localization, you will first need to add it to the `SupportedLanguage` list/enumeration in the source code. Afterwards, a new PO file for it will need to be added. It will have to be named according to the ISO standard's two-character language abbreviations. Then to have font support, you will have to specify what font encoding/charset is compatible by adding the language to the font generation code found in `src/fheroes2/gui/ui_font.cpp`. If a compatible font encoding has not currently been implemented, then code for that will need to be written. ## Editing translations - Before you start Before starting, you will have to set up the necessary environment: fork the fheroes2 repository and install an application used for translating. When you have your own fork of fheroes2 you should create a branch. At this point you can start translating. After you finish your work, and you are ready to share it, you will have to prepare a pull request. ### Forking the fheroes2 repository A fork is your copy of the fheroes2 repository. It gives you a safe environment to prepare and test your changes. You can read here how to [**create a fork**](https://docs.github.com/en/get-started/quickstart/fork-a-repo). ### Translation editing software We encourage you to use [**poedit**](https://poedit.net/) or [**gtranslator**](https://wiki.gnome.org/Apps/Gtranslator) to edit translations. Currently all implemented languages adhere to a standardized font encoding/charset. ## Editing translations - For the first time or again ### Syncing your fork Before you start working on the first or next translation, make sure that your fork has all the recent changes from the fheroes2 repo. To do this, [**sync your fork**](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork). ### Creating a branch Next you will set up an environment for working on your translation, in addition to testing and sharing your changes. Read more [**about branches**](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches). To create a branch, please follow GitHub's instructions on [**creating a branch within your repo**](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository). ### Submitting translations Finally you will use your translation software of choice to make changes to the translation. All original translatable strings are located in the source code of the project. If you need to clarify where this string is being used you can search for it. The string below, for example, can be translated in PO files: ```cpp _( "Are you sure you want to quit?" ) ``` ### Testing your changes Once the translation files have been modified, for Linux/MacOS run the `make` command below in the `files/lang` subdirectory to create machine object (MO) binary files which can be used by the fheroes2 engine. For example, for the German PO file, `de.po`, the following would be the command: ```bash make de.mo ``` To make the engine use this MO, the file should be placed in the `files/lang` folder used by the fheroes2 executable. The exact location of this folder depends on the operating system. On Windows, it is usually located in the app installation directory. On Linux, it is usually located in the `/usr/share/fheroes2` or `/usr/local/share/fheroes2`. Currently for MacOS users this location is dependent on what third-party package manager is used to install fheroes2. The Flatpak version of the fheroes2 installation from Flathub is located in the `usr/.var/app/io.github.ihhub.Fheroes2` directory. For Windows users who use POEdit or a similar application, it is possible to compile the MO file using said program. However, note that the program will need to be set to compile the MO file in the font encoding/charset that the language that you are translating to has been set to. For example, for German you will have to set font encoding to CP1252, while for Russian this would be CP1251. Later when submitting a pull request with your changes, you will have to save the PO file in UTF-8 encoding because this is what Github supports. ### Sharing your translation work When you are satisfied with your work, you can proceed with sharing it. The first step is to commit your work into the branch you made of your own fheroes2 fork. Then, create a pull request that proposes to introduce your changes into the fheroes2 repository. How to [**commit**](https://github.com/git-guides/git-commit). How to [**create a pull request from your fork**](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). The pull request title has to be something human-understandable. This allows the team to quickly identify the purpose of your work, I.E. "Update the Slovak translation".
Pull request restrictions - Please read The fheroes2 team has set a maximum of 400 total modified lines for any pull request for translations. For contributors wanting to add translated lines to a new language this has a maximum of 30 total modified lines for that first pull request. These limitations have been set because every pull request needs to be reviewed by our team, and so changing too many lines at once will only slow this process down. In addition, GitHub becomes increasingly difficult to navigate once too many changes, comments and so on are present within the same pull request page, further slowing down the process of reviewing it. Furthermore, we have decided on a minimum amount of 15 changed strings for a translation pull request. For languages that have translations that are more or less complete, less than this amount can be accepted. Preferably a pull request should contain a small amount of changes, about 100 lines, all focused on translating a specific part of the game - for example creature names or castle buildings.
## Updating PO templates and translatable strings in PO files Currently all PO files are automatically updated with new strings after each commit that brings changes to the ingame text. If for whatever reason you still need to update strings locally, this can be achieved by running the command below in `src/dist/fheroes2` to generate a new portable object template (POT) file. Windows users will need to set up an environment that lets them run `make`, like Windows Subsystem for Linux (WSL) or [**Cygwin**](https://www.cygwin.com/)/[**MSYS2**](https://www.msys2.org/). ```bash make pot ``` Once the POT file has been created, go to the `files/lang` folder and run the command below to update translatable strings in the PO files. ```bash make merge ``` If you are using programs mentioned above like POEdit, then they have options to merge new strings from a POT file. fheroes2-1.1.6+dfsg/docs/_config.yml000066400000000000000000000000331476115357100172400ustar00rootroot00000000000000theme: jekyll-theme-merlot fheroes2-1.1.6+dfsg/docs/fheroes2.6.in000066400000000000000000000042431476115357100173310ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .\" (C) Copyright 2022 fheroes2 team .\" .TH fheroes2 6 "May 2022" .\" Please adjust this date whenever revising the manpage. .SH NAME fheroes2 \- free remake of Heroes of Might and Magic II game engine .SH SYNOPSIS .B fheroes2 .SH DESCRIPTION \fBfheroes2\fR is a free implementation of Heroes of Might and Magic II game engine, a classic turn-based strategy, with significant improvements in the gameplay, graphics and logic (including support for high-resolution graphics, improved AI, numerous fixes and UI improvements). .PP To play the game, original resources from a demo or full version are needed. .SH GAME DATA PATHS The following directories are searched as data root: #_SG .TP .B @FHEROES2_DATA@ The system-wide location that can be accessed by all users. #_EG .TP .B FHEROES2_DATA This environment variable can contain a path to a directory with game files. .TP .B Current working directory .TP .B @data@ Per-user data directory. This path can be overridden by XDG_DATA_HOME environment variable. .PP The game resources which searched in these directories: .TP .B data/*.agg Original assets (required). .TP .B files/data/*.h2d Additional non-original assets from fheroes2 project. .TP .B files/lang/*.mo Translations from fheroes2 project. .TP .B files/soundfonts/* Additional SoundFont files for MIDI synthesizer. sf2 and sf3 formats are supported. .TP .B maps/* .br Single scenarios and campaigns (h2c, hxc, mp2, mx2 files). .TP .B music/* CD audio music tracks which are ripped in mp3, ogg or flac formats. The tracks should be named as "homm2_XX.ext" or "TrackXX.ext" where XX is a track number and ext is an extension. Numeration starts from "01" for the "homm2_" prefix and from "02" for the "Track" prefix. .TP \fBanim/*.smk\fP or \fBanim2/*.smk\fP or \fBheroes2/anim/*.smk\fP Video files. .SH ENVIRONMENT .TP .B FHEROES2_DATA See the section \fBGAME DATA PATHS\fR above. .SH FILES .TP .B @config@ This directory contains per-user configuration files. \fBfheroes2.cfg\fR is for game options and \fBfheroes2.key\fR is for hotkeys. This path can be overridden by the XDG_CONFIG_HOME environment variable. fheroes2-1.1.6+dfsg/docs/images/000077500000000000000000000000001476115357100163625ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/docs/images/screenshots/000077500000000000000000000000001476115357100207225ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/docs/images/screenshots/screenshot_battle.png000066400000000000000000004362611476115357100251540ustar00rootroot00000000000000‰PNG  IHDR€à,ÖPLTEüüüðððèèèÜÜÜÔÔÔÈÈÈÀÀÀ´´´¬¬¬¤¤¤˜˜˜„„„|||ppphhh\\\TTTHHH@@@888,,,$$$üìÜðÜÈèиàĨظ˜Ð¨ˆÈ xÀ”l¸ˆ`¬|T¤pHœh<”`4ŒT,„L |Dt<h4`0 X(P$H<4,$ ÀÌü¬¸ð˜¨èˆ˜àxˆØhxÐXhÄLX¼@L´4@¬(4¤ 0˜($ˆ € xpd\T L D¬àœœÔŒÌ€€Àpt¸dh°\\¤PPœDH<<ˆ04|(,t$$l d\T L@80( üôÐøè¬ôàŒðÜlìÔPèÌ4äÈàÄØ¼ аÈ ¼˜´Œ¨|œp”d ˆX |LtDh<`0T(L äÌøØ¼ìȨäÀœØ´ŒÐ¨|Äœp¼d´„X¨xL pD”d8Œ\0€P(xH l@d8\,P D8,´ôü¨èð àè”ØàˆÌÔ€ÄÌx¸Äp°¼d¨°\œ¨X” PŒ”H€Œ@t€8ht0`l(T` LX@L8@,8 $,$üääôÐÐð¼¼è¬¬äœœÜŒŒØ||ÐllÌ\\ÄPPÀDD¼88¸,,´$$¨ œ„ xl`THüäœøØŒôÐ|ðÄpì¸`è¬Pä Dà8à„,Ìt ¸d¤X”H€<l0\(üX Ü4À¤üüüÌÀŒŒH¤Ð”¼„¬xœhŒ\xLh@X4H(xÐhÄH´8¬ T¼8¬@´„àü˜üP䤌Œ¼ppœTT|<<\Vî¬ IDATxœÌ½kw\×u-ˆÏ ’ßxÇ”l‘¢^¤DÉfn“"(&ã‘û-£ò‰$€:g?Î9UÙâ0Ý£ƒoq;±õ¶q“ØîtÇù?½æœk ‡'¹éÜ"Q Uç±÷Úë1×\kÏ=ûù±0û§Ç©û§Ç³gó§NÍŸ*ûßðÌþΟNéw>ósögÇ?-ð§EûþlñÙ⩯>ðyžG:…ÿúEÕküÓ³y>Ÿ¸ÌòÀÕÛéX|9Æ©S~ ?Ö¿÷Pþ>ï«øúcîÿ÷3þ‹‹˜ÅEŒ K–Më©" ±\ü²xzq~aiáäpSÐødX<ñŽAÁk‹‹K‹‹öI;ÕâbùœpaqÁEOÒ3;ì)®^ü‚ެÏâϾú(×üeQþw{ü~Bwü8õìß!|õñ¯ÀùÅùg‹_yéÄó_}ÿo{œš_üÊqæO~xiiiñÙüÂÂ<SŠgiÏÌ/êyÞesÞe+ÿÙ‹ó/\=5ÿ-{y 6ÐnÉŽÌ÷Ù˜ô½ðOuÕÞsõ[\9ÏÜ%<–$ønÏ0‘ §!‹²„ö³œ¸¡I) JÖÖÌ2~–:åÓ)j,JòøŒ‘°lT‹)Æàe¾ÙæÄ„f ÏöÍG@ùê·N]µ Á¼Ìcý\ýÖUü¿Z®B>¦É/%Ý$O¶\JÝÖÂÂ)»$êââŠâÿ‚ìÆ‚Ô/bæòU.*ºª‰yLç·l*ìR_\|ñ*¦‘êðôÒ—FçäEa9È­ÀtŸZ\Âûñ8m7ºP4™= B¾e󺀧°À^|áªMî‹W¯ÎQȯڗvñª~ÿÚÏþûUüNéûåp‘êêÂì=óåʪŽ]þTއ÷,Q¿=ƒ|ÙçqQ¸¤\²çç_àÃNwõ[úA½ª)ûÊ‘\ÀÄ™óÆù;mÍð¬ù×Ûô‹ÿû¢›ßÏEW(<‹îÐAùQ0íì&ú¶¤Ÿ™-Á™¼ºÈ×¹ÖñΫ˜x».üïZ:-5`S÷‚  Íº? €›£y”<ªy»§ø ÏŠC¼øŒ®¦nÉ$q .ÆÚ^³WNË<ƒ€š,-.”pSs%è8×ñO˜b;ó‹X¸,ÜP¹c”‹š?uÚËÂ3n»;Ž>ÎuzîjÑS¼,ÑÙmÚT_Õ^Ã-á³>vKz.¯ÿõKãAxmz,,ê—ï=y”¯}þ™=½`ú•FåÛ–4ô¸¶¥ÓöX*Ç+üN¹Ã²’¡*¶!·ÉµŸ©Kÿ-Ò§áE>—ìÊ0Wtaüvb$¯Úy!²(§¿4nþêÒ½ã™ÞwZ—ZFàÔo<´ ¯âw=^´yYZ´‹^x‘ª73ÿUOïÄ}m&ÏöÄ…/Ö•sä}ôÿ ø/|}64§¿á¢ žN}ëø±0›¹ÅÙ;–ôîô«>àé3g¾clêæàÉÓË4þð8cÿü·µÝM¬ëúéèéãÇÿÑõïö°ûÖ¡i‚=l ùîÿÌôeýs¸tæÌsׯçqMÚèÉþþ7}æ;óRJéz¶·6ý?øÆwý>0ð/ŒšÃzT×a?4£—›ÑÁ“ýÇOþÇÿƒ3gNÿ·ýQ=jF8ÇáȆ«±oûÿ]®ÿ_ôÀuÔ‡&t6k!Rþð”ìL¿üû—Îþ!…‡ v&;vQþ² à’ÉÞËmnÛ>Im ÕööÑèéÁ—¡½1]K9ç®k³iÊÐÄ1¶üþ´‹)åïüÝßý-ê`j¬Æ9mÄ¿ñ­&xg_úû”rÙ{G±9¨í;d/„ÃÈŸsÓ<Ýò¯¸Ø?8ó°oZ¦ ÈZ#ZÛÜףѨކýßn9t}Á$õñÓÅ2†¿ì6Ò„ÕEÙÃ8%Jcch³ó/ÿþÚ‰)ÿ·>0!šhÿÞÕ\vi!æ4îǹ5õuÍ®iîÙ™³&{/ç¾›ô&S6˜6[8Aƒ ×ýŒF~ ÓÖ„´5éëަ÷6Œ:üý̶)Û³×ìó˜¾ß1æ‹|û;/]¿ž2w„348Sѵ9x/¦öº­ ÓËœ–ç‚ÑàÚöG‡0ć¦íãÁ¾?yüø÷SÝðvìŒcÖ¸S ‘-ºšÆÎÖž R 8 ’‚æpô BxæìÙkmצ„‹Ù7EüäñþÓ§Oÿb8ìI÷MjJ¾EžTs†ùlfÛT I`l»Üå|ý¿ƒb9×0ñ1æ¶¿|ퟗB[³5?´rC6êÇ“®5)œëM»¾ïúÜÆŒ».Q?ánx¶Ô÷öß>h‚ÚwÐ~;8‹‘ ²DùÀD|³vÒÃÔÙÙÿüÒµ,ûíúàËùKˆèŸ}çÚK×ÿ>F»È„1NÍlI=DpTÿÙ™?»vÝDÏÑ$•«ÊÉ-RƒUT›š²¿Àµ5™¬9W!ŽŸþn!¤ì]³+èL®)É”~|~dñš0º œ‰o€=¶ó !VÇË=îÙ.èËjø© êáÓ§¿k žxPþö°¤B˜ÍfäÉ5A§¿BþøÆ„Ui& Bhºðì¿Ö$<=Õ<žŒg6Ahûë¿Kârµ,"´ žðá!ƒ}—çLŸÙ£k»˜8€(—B»½Èõ“ÉžÉm×™´ŽÛ.5a&y!ÊëõObTl¿>¯ˆo®Á&ØùlPBó•G}àfñôŸ}ç¥kX¸7;i¢˜#ŽH6¦œìú#o̸®oí}f`)©)Ö¸êÊÆ¬#ôø¡Ù¾¦Þ‡ÜÔºx|ÜLæ×'ë„‚—`Ï£‰vJ>$TõÔü#-ÏQ=Ø`™Â!ŒõAãjªÉîÂÔMŽ]+̉ͣ½ÍôØþþáÓƒýšßþ9ÓñtØpæäâ%O/anc’Ëg"QÇè² ; ÷_Qç·aÊf½úö—ÿRU8:„Ÿ+ÙÃ?×Rv;™rñòµo>àHþMElŠR£‹`ók28nçÌîBŒmŒMa7æF7gB(Kl÷`šÒ © DY‡üòà«<é-fíóoö»ïÆãúä·= R™k‚¦£ÃÌ% ÛˆŠÏ¤°†à’à Œû6Û¨Ú dºfÌQ-!¨)…v#ÞÓè ™è&ýÑVã!¬˜ÍÚß}ÇÕ‚i¼³ùÚuJœÍZjõ-w‰×äÊŒZ•KºÑ›p‡C®•†4ä%COH–íÐõ>äϾš§fžÌ­<<4q„Nü¦Y¤Å­Mþj©þ ÅçIìŠ)É 9ü!Qäm¶1ÅQ»!ûÍ÷µßSÚeb½»‚)ZÇÕMÄ”fê‰lÝ—¡-vͺV:¬FŒbEÍf+Û®h®ƒC×ÒÉ MŽ~*†EºkÁ ¶ÉEÝQZ¢ÜÓóö†©` “/T?]¦’#nÿ[„'i9å¾ha‚uœÄ…móÌÔ&Ži‹7b˜ñ';?.–Á`i!¦bÖf”#K-ñ¡þÆsMi¦²ÂÕórl©ý¤ºì"QϦ€¾2â(Â@Ó. ‹OmÜ@Œ°fì(&Ä´âøgF˜ÚÒ>v`ѳ=L©ËH l,“=ÜèHÑÆÆ2®³Ÿ9U ]+P@kÍœ=s5á¶ t²´–ìµïœ=}úw=M –›¹" v¨ Ì6ŽaÒ YZ™3f3"g%ú„Ä„ÐÊê@&„íœÙa 9ƒYa.©Æ?åwBW ”Á×PbOÃŒ9F›sPÖ ÌQj²Ùh¸Âúºæ“NcpÆ¢1 †¬_˜¹ð°¥K!€ÎA†pò›x˜ÜÕpÕË3ÕQC»uâ¼C!Ö^ÛÂå4‰Ã*ÀmÀ2¤–ÂCã`DŒ³ÁðˆÎ «ǰ¥¦`˜˜ë¢Çè ,›}bt8Q0›/ *í@¦·œ†»CÒÀxAõÉ- Yb‘ä ¹xÔî›§F¢jOÐÃV‹žÍØË×ùø&“ìž}M3îAD®¸\nðìÈ}+cÑ!B„ÈÅŠÿuôÀÈ]Ç‹™›šC—ÆIÑ,¢å¦èã\ü‰p¬Üy~Ýo ©ƒ¨9,Léå)BeÎŒô^Ã0Hg…©ÂàqlŽ=Ñ9„rÄò45™:³¾4Àí徊E=CTÛAôEbr6âÛáê22ªý÷ÈÈ)ø#dÊëÑÞ%a÷›IY„¯Mh—|55WI1Ô ¬MSKá»ôéö•Ó“Ž CžŸ\zÔuE·0àÇôqd ùmì Z鉋E2U¯II<6¤_áXM4Å+j%ÏŒ<3œ›L<Ãæ­ÓÏv¦cI,I 9äZá;?†ÛVZµïÔ$ûà–söÌ«‰å‚ü¸&€T#\³Ñ»Ô_ ƒi`Ãl¸UnäÑÄ|áÆ&¦®,à‡þê⺾€jx=EBÈ1jT˜´¸Ðˆ­Ì2üR‹ºés°çpìn&½‰ãfu"ê2‚\ÓAJºOZ⚎üÙ¾Zº&ÓË@OÕ°à°}^RN½"2=äÙøÇè¶&º#¬Öe°djŸ4&0‰žS¢­²×R1lÁAF×Ίp¸»7p=`YCÛ'ØôædÀëfQ²è땳–fC¦“€>v\P¸Eº¾–§ƒ;•[”©Ï|9ClŽ_8¶Ç¯!¬(ŽKÉàúÀž0áEàŠRžy–ÔÙs“1g¼MþNEw楥ÔÀ5dl}cª‰š q<~€¢ë‰%ŽÇcÁqã¶whËèÒ‘tšé%èžœ¤1RTdÐS ¯K üh~…š¦F2~Ç ‹­ç.ô”PÈÇ©=¼•VZz‹a3q$L_bêqk¹¨•âèS§Á®ÝÂÈçMðÊèìŠá\vÃÞ°sïû÷Þ½?<Øyמ)º#‡Ìðgà/ ?PWðÞÜŒGz…2AqGP0¬‹if…Œq²150ÓZã^K Š0çßGèf¢G¯H­;ÂZqe"ÜÈ]/w˜/èØÿC07žšþ²[êÓ ;/mI#G¡›@¤¶©²‘NiÒ¦± Bn\ÁZ„ gI°âø´]ceÇÇrMÐ>éR¼1¦î±ÀaxúŽ@ûo¦±UdŠ I¯¢= ÐNé$>ô%é£|Q²‚Ǹ›AÆ,ѺœpHË“Ä>]° ä+!(³M®Z)}3útÌ]è%Á,q†4öô%èŽYP:F†˜Ø0^‡«)k²‚äg¡qFpR’Ce‰0)‰€,¯-‡Io’n~Œ,¾ìʺñ$3ØhKô» 4!VO‚d%Ï0\n N 0dÛÐ31„ù¢:„¢&G…a ÷ð’†1Œ —‚•Œž¼;k'üôbƒ Ô%W°IöÕÃú;Ãýáûß4 ?|pß~üÓû÷†âAâÃOîÿk)ûŒc[:p™^S«è¨ßJ\|Üãhm.¾§›ó•aÒÆ'¤¬  ‘Þ“ùökR8ÓR¢ÿH :²Dá•C)%þõñ™]Pº–ÜÍ0A8tò¶ho”Š…ˆ_l! ø¥'„ 3˸£C#Ag™"í‘è.é °G9»«ÅpAj‡¨´¢›LO‹hcF„Àï÷R£“êI?…×Y'DǦ©i3:B"€ÂháF£$ˆM”‡Ž˜btË3Í­¹IiÒèÈIãàŒtbÞ§&2B6 ý|òð `-_;Î`f¦=”+O&kP!&ôáRV”àŽ€Iݽw‡Ýa¸sïî ³†ø%‰ „ ™$8C½‹eÑzTþÇpDHÂL‰.‹™¸cÆÒ¦ é¬u­;Ù Š*ðº§B 43d’ä‰,Ððšj»­üZf#ó˜È–ÒC:ñ˜!F©ÍÊÅÓ€ïÃÎAŒÚq¯P§4_ À "Ø3l's†šÑ(ÍA‹øc‚ÄD> ¢c˜9Š• Ø”7–å"˜ ØŸFrΛ$¬Ú$Fevs Lܦô,£`Rz+f“ÇY¸uÒ|§YPty“¨ æ¿„À80ªgGgljˆ—Åcô—f,5¢4ˆE$ÔjDD¥†d ê)OþÏ3»EÙÓOɃäi=E‹Åƒ$¶Ù ÷˜ú»¿7¬¯¼»9üpçÝ¡L±ùw2È¿õuJÍä (äœÞ€sIÜ -ÌõyBWÁíìz{ Âȶ‹@dò¸x Y$€µÒM`2x–­e¦kÜÍ|>Ïûå—Ä‹±ø:‰­AÔ“E*z5– ” qDÁðíÇFâ¤jŽÛŸ!^bÍ8DGù#1pLùƒŠ4ž0)o§oA\Ìì%¢dswWEW£ûb¯+yéôðw&<.5F c"c¶ËS€1„ºÍ¨›Ì!C›ÖøÈ„ü#0L·K¤‹£l—üµ&ÎÁت¹“‡‰$BùMã£^+JᢗRf:é ,‹%¡ >dVxJÏÎdy÷Þ°cðÊå•••Mûa戧ᑩCGÉÓÜÔd¤Ú¤ ܉(˜€ÌÌ”Ÿ#Òš uxó°ä)Ë(¸yA–ô"Š,ZG¾A;™Ðµ“ÁÉ4ˆ ¹#VqÌ…׈ôTö!òdŸ­i榓©É׸w¢‹L/}»¾£“ €”ù Úß\þ®´¶ à´›BïMÆï“FÐ3pš…÷Û¡EZÃ#ÀäuÁ»`Ð`¥Öa³ò8&·xÄžù>1a{&.iŠÄƒkqá•Jê"öÍ ‰_‘HÇÓÌ{ 'ÀC¸‹Ô©[ÊF<òZÜ6]«tBR‚Â%p&‚Q"¨¿Ž\fB„Š“QúÃÁâ•KÏŸYÙ8W•¤½}nv”aI×`98ïJ°£2‚ðˆœ(”}Õ±­ G'ÑaŠg§lpA`„òÀKú–²@,±€‡Ì^¡ókÇGƒ”P®™AvÕ™ É®ûx“tÝé–Å  òÇÈ0¥â½»d:o–/9{aëÂüfÁsRvw°$êz @íêÏÂ$_r\DɹN™¶”ë¼d›g¶$:»ï”a´Ê¡gì*MQÇkdÌ‚¹îªZì‰CÐÉÊR˜M™:¨¸_°å˜t±cڙĹ„J„PPè t¶i®Ÿ‚-ûÐ3ÜÈBö:G‡MîZB•¸târ“gûfWèo‡ÑÆg!,È¥‡ÅÁù!_’4Ë¢4¦.ƒ{-‰Î/S¾XÔ¼xÓ¸ŠDòA€Ãð)©‰À®‚øÂ[y炨çœÆÑILÐ3ÅyåÅ0y `py4cžf"Oƒ4/-ü‘bm.¦&ÜkÕ &K¸ yjÀ3‰' ç* ç­V/]º¸½üܹ3›R_9 ¸3(¯3üð‡Ïi:qù9æ¿Ecó8N|+÷AetÊ9\3S· kS8&k”d«#J&è`3wœ=ê8Ñu¬ähéÒí+!UT`Koƒis~:épž Ó¢“å€~ F´ h¸œxx´»cx«€#”RzzÝ$î2|Ç<ÿŠ©4ˆÇ¤›Lq4`xÔ¨À«THÔri€U ©IëR„Þ’ƒ-ò`6©Ý²chc’‡èbÀsKÄÐ$i1]¸ên¡Ê öRR.‘NÕ b}Ê”Ô$Ù›o0"•_¾aãäA²_)˜3T¼A±J’&楨… ë”X Ÿ„çfšý¶½µ²Zm\ÞØÜª¶8íø $Úoï ìy¥©¨^xvËBê5áê`·ÆZÔÁ0h‰0 ÌA)øtîF’Ÿ„h‘íT¬c«D¬çâq.¾Æ¨?{jÄ^ƒšCšB ẽÄR.Ä\G³K<Ïl+ÔÙö¶§6·„`rꮞRYò*LNAâÆÓV‘ÉXAó÷„Ž4…!9¥š¸\qA­U:£4g6‡=)>ˆÂ;‘m$ÈÁ§ëfAÀõiIÏyyAqÜ„í63LPæv4Ia¦M •УՅ^®#»H$Fgd ©©P£+¨D˜»V agvµQq­[tOµ¾|¡ú?«êÆRÄ_ðÇaog÷á°sÿÞá)æ15%,ËSóΠŒ% ’¢•!쨪•è—‹«…–BI"ŸD¢Aþ"l(æ%l÷8í‰~ÐL’€, |(4÷t‚8Òe…à4_]ò–¸Œ9×ʲ1™A"€I‰ÑxbòÖ„k'x¥G@@d*/+#ÀÆ>61iœ !¿Käò‡Ì~Õî|»ÂI¬WâÒшKxh ûWil#U?pð©$׫Ѕ€'|1™GØûâù¤8c5†¢!ªG IDATùf4)G/faÀ¨¸ Ã&=ÚëüjL‡î±8/ƒHŸäÕ"eì©Pz¨ʆ u©°•8T]á°ÕÚ¥óçªKϯonloÃ)îݤ »ïÞ°ó`¸÷ÝA%æZ v^O¥(×Eš—1–?˜Ži}¤>ð2baÕ6*ZâáfRW” qÎ&K(| „ié;™K¦¯0Óô—r3 ¿IG޾¸«¾îR#è+‹Ÿ6‚ f^$xÍÈ}týûÐ|@A ÿrÔ1A;–®#+›½N¤R´лé4èÎ cXD\ M 9ùY¡wNç ¡q¡av€QUX‚{Š„9 ³§fáIÞ"E>1nä›…¦LÏQý9Ô¢ÀdñxÌê^NÊ1ÈAŒ¢¡QþLΛQœ©™x8ŠHqÛ²ŽæFAv¿iÊ:³)3÷Ë’É^çtÑ3.¡ª¶Ö®œß\¹|fiáùMØÝ‡JÈ þøûwïÝ·hdçÞm•’'IR 76QËe:1.Î0`a–ôT˜ÑüJLFÕäÅ$~i4Þ Û`²;€Ê∗±(áÂn]ë”q¦¦¥¤[ú×ÁF "C쇵÷àÖqNÁ-@=“·‰sÆ&‚æÚ?SŒˆ¿'À›;R¡:id–¶dR»{oOH›Ÿ"]xY–xzý¶TCÃÁâ(t é:yø«¢L`þd8 †Pàìlùä °)À&» ·˜ˆ’»Å¹äe}®K®•¿(~ `d®^*áRz–T}N´»ñ\9¢)†OÑ 5y…( ÑyÎT‰\Ç"}Yôþö¤‰óØg»ZÛÜÚZ[©–/]X¯Ì'v÷† †áî÷¿¿óhçþΆ;·íTß nÚJ1‹(=\}†T ÂH ):"gÄž?‹'`?™%exƒR7È 0¥F«=#Þ óTJÌŽUFTïÒ¤ $aãREštŽjë™dÚìâæHó£ÂbÊ œ¾Éx2!óÙ¾Ûÿ) =.a=¨0TΔ(eñÓw®P™µQ¼“ăËf‚‚{o!>Y©b.‚!YÊjˆÄk±û¶€ód¨²u˜Dš`4NBÄLê€Xa““›Ï¢!K森= „Ió˜Ý¹|Máë™Ì4,^[»=ÃvšŒ½ªÄÞ}HBužp9ò¦Z§¼1äpgØ}ÿj{ãJµzy­Úؾp¶2wÓäÏTØjÑpçáðh÷½;w^7¼sÛÝûÆ9·` ¥  %³ƒÊ1ÃaŸ´¤¥´¬/`v C0âMÒõ*'¸J 6Å-_H91àè$4q#ÆŠ(# PTÆ$»-ˆš\¦îÐ<‘‰0®‰sy¥Ìh˜M[ý’„AŠmbï$O!cöK+sǸjÜ“ -Õ‘¿×«Ð“x± ÆHºŠ Œ€͹‰™K¸”‰j™I¯& ¦´1Ö5$^–™ƒw™ƒØ0Áƒkž(¨¡‡ÈDO«€•؈â¿;­H£ïa3’o*ëß?dÑ_3seâ&þ”³Ãud/•õb¤”mïU%.æZÕÖêvµzqóù‹&…ÛÛ[M†»v S ª wn¾zíö;7oÎ\wºÐÌcÖn˜C(P?‰–1ÂW3ÅBˆ<{â[ot?¤‘3¨FÏM¢¥m¤Ì{õ]ÉÓûNci=9+*^U¶Í RíPwàÌ4¥|Ñm@šï³e\Á\ËR›Ëè÷}XÕÉîÝøý)X*=ë6zé˾WI\žmÏXdŒãA`Zá‹\Kò~蔤‰F­(1˜0ˆ2Î!¤·'yÜ. ©d(xáЭo³×'¦¢èBPtS"ž¦tõˆÞÀÇ¡À0ƒÐ-RQ«íJ]²*QÔ •¥qè€j Ö)•åH¦ž™·(Þ^"›<½.Þ]™îjkkkyµº|aãìókÕÊÊfefwgoàUØ Ãæ¥‡î¼ùío¿9¼ùÆõÛ Ð¬ÔÉJÑÔ(·)HÉþØsR;¡ª•Æ0«¬"6æHŒÀQG•uð,òv †ÝcøÑ÷¦Çœr¤H·¬êè Ò+ÄÍ6©0¶q5…Èΰº4̉Í2-‚6F¶m'GS9Óˆ|Rç‘j gŽ(˜‚DŒAxÚóºÆøÀXy³¾“è…ZÐ[-¤l`L6 6±<áìÆŠ‹¼*Ì 3ÍT4²@cfÀÙƒá%6bJpäjOYax>ˆ@^ˆ©°µä·9”ÇE×Ħä1R¡R ƒåXR¿ôis,J“}Bd÷é¼…¾Ñ -z±ïY0K^‚êèS4ó»\]>¿ýüÙíµÕj»Ú¢ü%…å&~Ãæ¹½»w^yáµ7‡[¯ßæ56MÉ`¦cŠ…Ü×&K6Ya`!ËÞΞ‚xî𚡈Qx_˜y³jsÚ¥,.åN bRóÏúLH®]¸ŽYfÐrª`*Üt`©qœCQ3#aÞ’BsÚÏ<…)ÍÈÁޏ˜©àDd* •8*LÅ!ìX 2fqPGâ4hg²Híz¦“±»ãæFŒäo0Oj¢“)h±q50Pðœ£r­t,.i®ý”ü|xâœ1ç“‘¢€/K',gH/a 䳼Qî]œAµ>çdDáIJ¢C¤¬¬l¼—ŽË<½øÓd¤(!›Á4#ÀÅÚc‚ÌÞI¹-], +¦Z­ÖÏŸ¯.œÙº²µ]mn®^¡üщiØ^©†á¡EĆG{1ð7ÕÝÇÝ> Rv•˜ÄópÄ (­ªÅH’ ìˆk ;J¨|¼ f¯e*sUgQÏŒfN &Dˆ!,’¤ï)&« @ýÌ–GJB…ˆ ! ÔŘ0ÎɆ2¤¡K …"!bâvÔá°¤L¡Ï 6÷`æ¶“óoø¨Ôe+>-e¦ÏBìÎ˺pÓðäE#x9¹mòä`I¢<1KåDðR1#Œ¹µ³(.®ÌD.D¦F¸Ä‚xhòwXϸ1b§8Ë—ÄO ”rÈšäõò©TÎ5$¥3S24Ï4A-èwÒØžŠéì™6UWÎm¬ÉÄ|]‹<ÂaK­¢+­®I;Ž’ïÌàÌæV±hðòAyQ<Ð|‚˜"£ìi§ ('nF‚¡P&¥P<5z‚ŸGêD”D;a 9«\°&lÓ¨qelJ¯MLZZ´Åò[ÕÆÙ¡ªí+‹Û«ÏŸÝ|®Z>ÿÜåò÷(0> C5lo_>;ôª™îÞŽQõP K×E™2ªu»Þ/Ó¸Qµ­žJÔEׯBÝ)ÐÐløðSë5O­ØÜ=£Mx{Ó‰ì^ßyž.w¢ìA‘Ž©vQòKõÌÍ-ž@khárǬ׸?ê@ý#’œAFQ Ó’M5¡zÒ$‹ .»8“~a0¬ÙDp„2M‚ˆ%^g95ø ñk²S;˜G(ÒHVÁ§"(å‚U´˜##™ž ñ'RŽÉüÆMÔÝ( Q¨ŠDºR9ˆŽœC1-MA«™RFøXÈ8³IÈ¥Ü{¹ÌßyÚ*Jƒe—Aú©‹¼#ŒçIceTšœå¦¬©¨nqk½ªNŸÝ¼xesíòóçMÆìš’¿+ðr~xûÑw_½ùæ/ƒ4íü;©ÞYdŸÃŒ|P²+¥‰ ®:gy2D€Ø1a–j+¢w2 gõ,Ùù¬;gŒÖij;‡Á²Ãí'DƒêÜ~¬7ÀXWO›J@q>¾m€PÊ–”ô»9ÄÝ9$(òËÈgiÉÓþG}7‰ÉH=š’í×µS¢àä§¶pM-µ~wXf´Îä L[EL*ø„6kÂ!eMͯðjBÔ‚ÅÜmÛdzu‚sæÐ…¢Ñ“‰Ê¨Ðç0h¶ŽZ•σžP €ã;Ñ£R‰£›—‚>+ÿäi¹Â@¥=”[5ÍŠ›F,V5¨}oiçKw…èÑ5š±!ì"%…¡‹¨ ]—½% õ»=WkÏ]®6Ÿ[[ßX_¡üíí €Ñ0 ÕúÅ3g†¥¡Ù†W^©Ö¡Uø<£5y$z;è¨ÐFBÕGñ¾†¾Dh€Ith"ɳqŸ…ϳ UfV‡0ñ@= ìÄÏ‚Ì*‘ (á$Ñ:µB 4_èm¢H  ÑSê@¾¢v16OSsö³ùyÓ)mè˜áÄO;1©C|"Uen DmÒGÔ'A`ÈìÅ©Ÿî °éN¥X•ˆ#M®“¡E¯ ÑíQf˜HU2!²’ß+™‰lÅCk˜…4¥?ARÍ'Í'ò¤k©±$õ%´%­€„âz6êDš…ÒMà¢,*[°yyH B‰ ©’gEgM©¤³È…r -«I[m\XxþÊfu¥ÚX[uý·¹I¢^5TkçÏž]n£-ÑðjµuãáÃ!È}õÐ3­åaƒR31j8‹¥ D#Ë*: p+7¼ªZ:–4‡S‹PêÙûR`…«9Ÿ?Ñ>Ǥ†Â#$HãÒa÷Xí?­ŠÎgãŽ6ôÊ‹9£ŠTwÍY<‰!o€®0n²15×NŽÞÏ´ÈcÖgå›/T(¤Fsæ¼½ WȘ2ë}Aµz§E/1I¢î½q@±P¡;{ô¨%î3‹î0™¢õ‘ÝÚ”¬RM2ªBöˆv¨n$eXø™X5R ^È„ó©9öäYÆtܦÈ5Œ KŠ_j„®Ðh=Üè &ÕYT{sQ·”{v¯ªqú6˜J½ð¿ªÖ.=wnãÒjµ±¹9Ü3ùÛªK+{ó°½:l^:wîÜðÎÓ;ë×o î>¬UeSlm)‡t ¯èÛ+´B­®¸Zd ZdõAʱ$¥ æìaIR âÄ$F‰):•6û´0Û0¦àŽcÈÉÖõ(]SõIËÍ›0[#Ï"'¶éš£‚-©:a4wcDˆGÞ7…Èh~2VöY™uVð–ê¥Vˆ &Œ6bWòè°ŸdÃï»S¿)§¶dF•²óÈT§N7ì§¼yæ¢ÅÁ)©µd¤eÔHí³È”?X]M¯µ&µ–…‰jÂÈå ÇmŠØÅÒI "ïÀ=ñð–ü„„ÞÃì@™Jz®‹s<Ïž BÀ]›ÔÞf#©0磺T­^Þ\¾Xmn@ÿí™þ[­ªÍ*š¸ué‚y€+ÃÛ·¿÷ú0ì<Þúö ³lŽ˜¼†Vd‹¥YM_H³‹(Æ»¿v\èÛz¹X£|ú—h7\ì䓸ƒ1.+ÕHÅ::"=f,²0Y)ÌTö[…‡±9«j擳NÁX³#É"‚……Luˆå Ègò~?9*3ÉS&Ûw,kÉ*ð#'?«pJuÓâr!@g§ºæ`4ŠSöCEòA«¯•h³W`ŽHD—"‰s&[6ÁÕ ÙQyYôŒ­¢·-^ÉLÜ™ë=R’……$ž¬WòìH.¥+eb«çNÁ8zð=I­R)U­Áoê²WZ¡ÃÍH^åÿ oÕ±Ž*RÝh@c¹¥±@ûØ=‘LÕx¦‡ó‚’!ñUëò·ÈL”Öhè{fn–{ú*If!‡ìÆ:ó„7bar–XଠlôJ‡bËÊ8?T[ëçÏœ½€ìÇÂþšü]±¨¸º`òXU+—Ÿ_¾ûÝ×nUwÞ~ûÊ–Lî ¥ádò4œ’"Y¹Õà|,u#Pâ`›-6'wÞë¸qUÊO©pØbñ™‘ˆ&¶I̾W3&¾€KCCŒ)‘ ÷S0ñûð“O?û›/>«lBí¾Ø cÆÕR³Í`Œ%<³š ‡Ðá.j´ð9@'ÉSǵbÓfÒgG0c[m\Ú¸bø“ÿtoÇ ðòêFuþùåKƒ… ›Ë熷߹uãµïAo†»ö¦Á;&ÄRFî'JavÜØÀÁÕ˜Êã› `¶WA|¥Õ…XZ¾vÏØëŒÓ, «²Ru㬔´`U5»S¨©©Wð’Nª¾úÙGŸ˜~ò‘Ißçó¹‰`—Z‘>ée²‰Zk>`+z»T°"ù¬Xê8ô¤KÌkŒ[f&L”ÇS¶ÉISaßBYe%ÙZˆÌ}¡æê£ËÎ&±¥ßŒ‡KÐoazê@&òÅq§zd¸ˆyµìŠ¢&å`+4¢®"w[60H-™,ðÅ^Ô-Ñ‘ƒÂu'j…áþ’BSÊfÉx-¥$õA]|/Pa†yf¶~û=‹Tcp2_S[è{qµ:·x¥ª†Ÿüá»&€ë«›Õóðÿô“ª{¤h …˜è’Ï$Vd¹û·´ÞÉOÌDø9=#òžá ™ë{öi¢Ä‚Wæ¼™,a'!µ¶"ŒÃ–N„måÛ¥RfŠâ“že& j½$t&©„•¢pMý±¥:#EuwD†‡: gP''òÃÜ®ñÎy€yP':Q¯[QÇ…|5Ή¿¤Ð*Ò…­®=Â뉢ˆ†ëÙÕ‰tqãmôKJÎÉ¢up|MÜjÅQµ±Q]|nþìòpwø£?¼;lml-“ÃÖÄlÓŒððÎí×^~õöwßþži›>Ø^y©Šî^¤`üfB,µ"ÒmĨXÒ,jz*Óç¶±(I_,µ*gí7ôD/#+Ñ”µŽ9"Æ2¹+SFÅô '-Ûû˜v}õÁ'&xŸüôƒ?úôóŸb ±ªä«›¿‡8[èéº`DK4Ι(—YÎã鄉˜1:¡YÖX>õ‘R1Ï“§lÙ[²gÊ2S:°§=v ²RÙ(bLþ©ô¾šçÈ” ²,¹WC¸ìûœ ¸éF`1üåÚhc¥ÖW81BßAÑ2dªøœD–h|I!iqªDMðšÌFÍŠÚäx0üÑO†íå‹›C?ŠãakusnßzíÆkï¼õÎ;UC÷xxôù_½T5ÊQ(ìwœRWä{†D5Cò¦ÌpYUÞRGG‘ɺkÕ’ÃÑY<7ÇÄÙYO¥¤ÖCnLXh<¡ÿ×÷GGIˤhç-3Á}ôÉçŸþÉÏ~úiÀÊ~­h™$ô¹¡ö2Üx±n[4:ý€Æ %M)í¡0,VŠyÒù®ŒH¾DÊg"Ü1Qâ¤TLJ¹@|¹SÕ êÀò3èF¶$鳺öŠÀ…x ÿhä´$ĺ°Šo‰ò+<÷ÁOtÚÆ$•áã­©®8þ’BÓx¼cSJ=¼y1Üÿ(ïΔ;–TÖ‡¥~"Õ`¬6V.Ÿ[[>¿ŽdïúêÖöåå :0 Ë—7‡Û7oÜxãö[·Ë ©ÞùðÃooê¶¼v`–suKK*J8‰‹$ë±ÆaóÖ©÷E§ ŸEZóxL1s„_cÖÒã)›ÒxƒÖHp}Ü1ï$P) 3Æ!üiU}öé~üÙç•9½Uòì*ûÍ`;§Œjb•^tÖ6\žÞ *ŸJ¬©gF©G«È~È3’DÅ6¯€n˜{™Fò x bUD¨= ™=mô˜†n¨¢ÞÖßÄV¾½R~ìÄE’?ÛA0n¶Ð"ü¨öä’çE[¸>dbiaá†P|˜Y¡rðŒ‚¦ðH ܼD0™W™„YVÅH£‘of#úW*&ñDÂ3Åp\µUU[ÊX„O-Þ\¹pöÔÆ`Áðúóg«êò•aèÒ°vn¸ýúë¯Ü|ãí·ª0oï¼õÚK/VŽßª«Òìb\V)¥™À·IJ7OgYš'z7ùøeh4z¢&ÒÚú7 %~¥Ý<ŽYÚŽªžTPœ ©¬>û裫jTäе`‚¤C.8:ɧюQ]¯=O]©*"\ÇÔC¶g¶ËiPÑrovÏ@ÐLÊê””1T,K¶#°ÙDËžŽÌ¶ƒÇ¯|‰hæ`BÎ:»Løo[L]OhÁ¬“ËßQSœeiÊ…-¡ ÛiÛ# KrM♓à`ø*I!0Ø%áæYå¦$MUQRGÅ"9—£Ì4°Oå¬ŒÈædkk«Ò‰~œÆUµvùâé3w¶··¶·ÖWÎ]Ú^våîÐTâí7߀ު†§iÕí[×7•¥Nj]"7Ÿ3zj«R—®8Xíÿ³j‰º¶T¹åèId¹æÙ¹Þžˆ‹…4"Œ-I%ˆ%Ò:é;r»4O‹@£ÈX™dÌhÓ 9ÔbÀZ§k×ws6%ß5# wL‰É¡*GÖýÙ{º>´}ì[ïÔ e!~¬agíß@Yéò‘÷RL.½Þ⦀3=f|'–©ôy–žONÅ÷ö3:. ¤¶Šå*d¦“rÓ+Ä Ï†µ©¸a°¯[Gdrö*¥9«p2Š÷]G…¯’œZåä詃P{OéJ|‘|Ùô2‰ @´œá‹Ó ›°µµ ¬ Ÿ?ž¾ßÕÆåç/ÎßÙÞ´xóüêæ² àÝGí~7 ß{ëÍ7nÝzó­¡}:$¼ò-Ôü8ÈŽ ylÇ–”=$G1”~Œ¬_eq•R¨š»gá\ø8˜­C‹MQª…ÔØ©£¥¢ÃNÜ-ú<Þ¯ªŸ¡&€1WbK58Q˜}Y”ª #Tlý2þÉxó`­k˜e¹M)vãÄf½LI° ¦°K¦6°ÆÐçŒ&ãV^k«¶I]É$£‹ŒjŽEîæ$/ª´g¨ÚöBr¸ĘLŸÖ[Ä{W¬Ž%›*ÎaêÕÑ=u&ÔbVö‹?3ÇRTUöhŠ%1@·íI ¶:ù¢-X^éŽe³Î½Ø½'‰$#™ëãöÄD =Èð{¿ý±i»jýÒóËw¶6ÖÖÖ6ª•‹kðûîÞ^Ód¯HO:oI‰Å¢jÃÌ‘PÚ/«qVQ\øŸ×!±¡WƒZ9Uó؇EQíyi]fSYjP9‡dY^ÀD¢¹±edg³Å­ÀrißaâR¥™ã;³E¬“Ö”dC}ÍÅY ªÁG\Õ˜’Z&Û2(N¨\µ[BvÙ½Z¤5ƽ“½™šºá¨É¼Z90LB2a?a¶®Dådμªüz•a¢†‡1ÉÓ)z÷²3eC)íð©Å•wƒëe˜^`šÇ3Hô©4 œ)©ÂtüFRPr­añ‰º¢;™]TA 7µ×‘Q;hO&<§x€&€››”¿µõµ¡òp÷Á£¡:¿z§2¼¸|i­Ú&ï?ÚÙ»»»[§'ü÷8ìƒÃÚŠxrjKDáÝ €¡…O&ñ QM¾Ø¨6Ž‘“ÉG/­Õ/*BT—òJiïFÊ¡àΙ÷­¶±*~YÁ#ƒÜi­{j›¦Òð º $VbÕ7·Mâ¶’mœ#Ù8UžöFÝ¿R|Ók‰ÞâîwØ2%Ù_½ÍÈwIsdY¹¥jF§Fä-tã)ÀK@ÊLðux#B¬F¤l[OØü#uÉ· Ó¬ ·ãØ™wÈŽE™më³øµvqKÞõJpà1N«ÈË™°Ù[îxQ Y@hpÇnFRð^©Žé¦ k¯}`tIW …çSN<+]w¶>¢ÞM à°vùÒ•asîîí “;wîlolo¯_¾°xæâðãµf}M÷¦5ÿN†·*åÇŠ©Ïº Æ‹La°/A­ºß™OìÚ e"¼ÕyW´Bk[ï’”ÊtdJtBB©˜TöëvËð¶WŸžN~!‚b¦ÙaJBæa Lp©O±ÉC i…2¬™sÚgǹÚO²=Ì¢²‚øP‰¦\Ó,Qf“¶ìiAòFÓ¼N‘Ÿn-Ïð±¡af>ÃÑrê¿> ‚Fßwúb†,Š IDATd1»=äBù‹H®2Ûc¦ºÕË…:I{f4ÞA¢d1KÁ ÆDfwÏ=‚ÀZ¸†}ŽÚxLRˆ!|‰¤Ðh{Uvˆ©·7…+"|# [L `ã‘d‰©£7LÛÞ^[ÛÞ¶V.œáêîÎ0L~êðÅŒuG}D^Íd<å¶”9ttC¸™¶qd4Ã2Á`‚u’Ö^éaYuÜ}J-èÜq)°f~E1ÈA¡Hzïz')x…QNn¿ IA|A!ÚT½ÂäŽÜËnT›R¯NñÎPj”m/lo®®n¦ìž_6Lþv‡ýØ$p°×/¯n¯^¼xe«¦‡Ãêú½½»î=|ëÖÍ›@I®fM-ü­]Å:¶èwÀTÃ6X³”gw^«a<°¶¤ Ä‹ÉIïSj.:ìétÁ >;×DþzD±à›•ŠJt‰ß­KËm±U„ô ?3ׄPÀ#R¤oªÍ>3—b¡Æ>9 t(L)‚W‚‹u‹Bî„ÈT G  ‰[Âd¢³3Ð ä8Yª»!Èæ Ñaa:>Bç¨ó„õ*I›]S¤3Ú1ôV§ô¥a&ÃŽÈ­Ñ“¨AIÝÚFz15ÙrÂIÍÍhK±¥èÂÅŒa£“¯‘f°‰lšºürçM&I(M)䙿É- «ŸÃÇ0´RXaÖ¨4¡ ÂÖúú– à¥Óf€ÿè?½;tÓ£lC6 ›«—.UÛÕöÙ¥¡?4 xeØ8 Ü»ûèÛo!"oè›c˜³‚¸è‰8U{kº$ñì^Ë¡n‡ÝhY¸CÎ@¯m5H1ŠÔ5I ÁU\Ðj'Ú'RÖiLú}×z”LíŒo¸Àç£Ñ‡Ÿ}8†‚ž'O£‚Kç­+QG:W9pø´óß/ Q 99\ô¹É v“…‰p÷J»±ŠáÐEÈ™N<˜BûÙs“©I ©äž;yt:õIÝçÈ“ÅG³³Ó éÊ‚æWàÔŽ¨…©·´³YBÀY[ÖÆóiäF8¢_H ±ðŒó1IAN–"úLë·3’TÏpMr£$VSâ:ý§ŽŽ‚llQþΜ6öîþd˜NÛéQô>´àöò¥KçÏžšzØÞÖÏÏÏÏ£n÷î£[oWT¨A᪟'ÄÉZ{2„|4­¡Æ[FÏôD±¹½CZºGÀröƺ”f­ç>ý¢[.>1qJ`ß²g¤ÀBNMë;ÓVèr8Œ>5-8lVÚUÐ,¶ú»šS?qO“*š7Ñ©E[?-8v¤o=+§µ­ƒ#;ÿ(3Pnª³c‡^=¥»#íº0îzÔ›€^ÓRÇe_r:QÚèÙDZj”žRçCáJ1µËà üÂ+¥ˆ©àÁ>iÍh$l=8?ß"(›…í¨·H I·æ®½v³Co„=7âzÊàœ  úÈæDŒX~Û™x†¾cóîxI¦CO5Èì5Ó›¾Ó¢™0O8!g>ö¢I“%vÙT+y.´)JйWzÔ(Í£rÖDæù¨Âér_2[o¥V0sg1x"CØ**I´y–'I Ñéƒr¥jÄREmf ÓÊ/ÞÕ½Sƒ"|UŠ«?~«L®Ãá;ÿݾաêŽòûÛ§Ó!Y]»ÝØ ÛÃêÅç €ëÏ?2؇ƒöVä½äÖ±d%s*»’§‘Cáážkú¡™¿C¦Òg‡=ùƒm‰òËþ üÍ3Xj~6ÉL LÛYÎc¬ zvÁŽ¥c âÁÎ+7‡×_~cãÝ?݆ª`Õf"žlTMù\v«ýæÑïV™(µÖ²à—;»yQªÈŽ,Äì2(îÙ7kÂ}jÆêŽÊV@]:-Ó`Ùë”L §ýûP“Y5 tܱؔûåÖ¡¢=pN7cn 9nK²Réð–qHîÁœ"Œ’”‡mT³:úÞ.ôm¨B EêH'I _E¢qC«è´úÚ}AUÛk’ý´tu(#ψѭªóª-(Àamù¼… [ë€üd¼ßæv ?uíÂÅ¡ì]kÏ/>=¬˜!~¸ÛŽÂà¶°-Ôœbya¤¨-J½h¸´pSD$ì8:˜´êƒKÊRKb³@µ¶à:ÅmŽžœçŽÎÌôN™¿+ &ÓXjí°(PUÌë;¯¿õÒëo½ùêÆÎv,»<ŠIÐ:[˜ÍaJ/À­¯YðL=o[ÐdRŒ[ö; dÀ‡¶îoÄx³uôµê½Xúh0Cw÷hÂî[¦ÔLÒM} í­ônë[©‰Þ"º>´^û> ÓSö㘎Uš™àï9#â´RrÐ d§Sè’{µÑ·$jJG04Fl $SšÌÌH Ò$±%Yk¨þ–ÝÎk’)Ù˜Zû`¨¸Á+?šÐ8Q‘`wµôöúÖöú°uaX6¯œ3ó ƒÛÕ“œ&GJãL‹HªµaX¾xΜ§‹ç–LÝûC’/Fm[{Äc%QD³|>a¢£à?y³t­ Gáýµ¹ìФ÷J"wHâìúi‚CRË+&ùŒ?³aä¤{ÓÜzÀìHŒÖ±:qÌm]¿ÿêµoo½üjµ³¥Ž j’¶ÌV\çÄ: òIoC•KùöP£Ò/3«-ÝøÌ¯ŠÁŽ.‘å*ÊCI9éVæúM³lOÙAh†ô"`´^lÀýSZߊ•³¸ø(:s‹‹¶D}©VÇêv‡¾Twç‘§X‚¤õ°‘?Ð@©ü€Í~[±à¾FRà:U*ŽØ|E…›è4x‹Ù9šP`h5Jð@Oz{cÓ´Þ¥ÅSÃÆÅçÏœÖ/Ÿ¿x‘ɶ6N†­µ•õÍ‹•yìk•… ÕamíÌp?\† èbË©›Að(Þ«]…Í4êóBfs©AbÛÆÃÔЈµ¢vjm«nR­¶b)¦)Y2‰ešÈ5М‚ˆÚMÞdYˆzx·Ø¶”=ºh#ª×îûÆ·^»výÕj}¯B#›& ¦Å.Ü>À.~ŽÕû¡¥W’ ™$$ ‰™úøô2;œ²¹9\ ‹€R7IÔêŠÎÕ¼Z¬Tð$°\°±iHÑwÀV¨¤°B*GRÑyÉVä(Ž¶ÖŽÆìut4öÚþr‘ YÕEF­?PŽ­aÛ<Þ®ƒ÷Bs÷œR•cð4›È‘Gø*IAÝG½4®VFW læågzkQ Ôˆ8+g¯4)(x®¶×!€ç—†•+gOŸ–/œ½páû>»öIS)ÌÆ•mÔÚÛí-oC€º*ßß®ª×^¿ùÊë·ï¯WR‘·À£&m°Ñ©c.9òE)”ýPÍq “öj5Ø"ˆ¦˜êÚ0íA‰U–èû'o1ŽÜÙûêZƒU5ÕŽÄ܇â%Y{Ó~Ýl ¨Ñ¡ê4æ¦a ÔðÃÛJ°Õ:ûK;K¢ø(IƒœR¢¿»e%ÖÌ—¢aKÐÄWY± Yê—9lýÓyoGwgnDr-¡Ûbþ‚g}µ$JëHøÎ]gÓ³m¸»»³k_{»»vîn˜J´ÇPmë+—.þ¼Ç÷lollnn[Û»lfvÐeÏzdE–¢;Ýbàîdg0ÛZ kÒ‰˜Š©Ô{MoÏLǸóíÈÙëOõÜR lI-€&ßøÆîzýü¥íímÀK¶aæ{Àªú__¹þò7ªû?\¯"VÆì½v à®R íÙrã©(Þ•+nG Ö´‚Îâ[mÅ`Þ¡[!·ß‘„8vÜ®€0¶0„(޹qUªDMÝÈ;y^ˆFoÜPíC{äPèB²#:n}Ðàq{ÒVDÜ–!DñkcØ4f_”TŠpœ¢õä”tkJ.U½Qƒoî!È4’U.ªp˜?kÔ¢C 6Æ¡u·,²vâdyô_â~Hë[C³û`_{{»öÃÎîÞCŠ[µ±mŠîpØÝÛk™€Ö»»wMòìOí½ƒbŠC×}AA˜:ì©ap[j`\CêUœNT& ! 5÷ñµjJÛ8€Ôol9ëc2‚Ñ9¶F'Š‚i³ Ѳ66hã"p{“ßmú«d ë¾öí—®¿ñà‡Xc4_¯‰"ÖÃÝ6EFˆÎPP`)r5ÀÈF}@¡ÖÚêÒéåÊÁÿãÍàü ývÝß%>Ö2`k² t@û3x²+{Ûä…§Ð…ý+7¸ÓKî_cs†Ì½‘i¡Lk‹.r©Ð¡ ®¦ådnmœ‰›Û˜´AÜtîõæ­bÂŒ%âL<޽´ä +H’ñÖ­"¬¦èe&ÇÁK± ä ÛWžì‰Ýâ{‡€¨m­¯'öL š$B$«juˆOüÕä²yˆ/üR’ØÇy_ ŸwÜks*E¨±t‰‹3ªg!›3óÀ ŽàEqÑiÁƒ¦OÞ[§R{ߊÃÛMuÔ“páM€ „™*¤ruÅÔßövµù_í‡íÆ&€Ãçþâ‹×þ|§Ú«†>DÚò†¾ ž$4yéæX¶½q¡Ü«Ò¸0ËF1¡_U—+òÒÀfDè›™–ÄÔÚ4­c{3fó2IíR-ŵgo\7Å S‹’&ã·_y• ÊÙ3Ë6âàÔÁ¶ñörÜ+ÆYnF;{©÷2"“M6qœ(²Åf*…O]V )7®&•òVh®Q0 Á¡"ÆSôL1T~íIc. 0FoÉÊ‹œLäh"ÜÂw¦ÃwÍ#®Úݓ¸] ÃŽFC×ívqÿ0L%£ÄÃý'ƒPEÇ„¼aËÒ,BVP•Ëúø©¸‹Á˜·‰ ¦ð|·t)±ñ 3¦¾;%2J/…Üw¥ýÁ˜ÐiÍÔ ˜¤vÄjyÓÑÆö_­° pøâ‹¿øóÿÉB‘_ ÿõÇ‘®5K›Z%J¡¿çØ]¥rJŽ‚'œÒ=ئêyûGÛÚã=uÚÛ¥QðÁhGµ²ÍR(Yú&³F°‘WŸ¹k31 W€­öOýäÖ+¯`L•Ù‹ìr¤m13ãÃÌu-ÚŸõÉcH` »œÅH!©²-6_æœæþ¸‚zOæ–‘tiµ¨QFrGŸ{$Ë™!#Ûæž›Ãi%ˇiÕMY‰Ù©õjè›`ÜÚìNÚpØ´»ýè-ÉÛæ( “î°ÛmSóôiØíL­<~šŽž>È—›¹Š»£ç‡³Ÿ0r9‘˜œüÈ>èºáÕIQ ;8™•bÄ­—s§&PÞ²§÷¸¸-ÛŽ%•Ü!‹w®ö0÷À‰ñÙg¿øÅ¯¹òÓÍÍÊtàv†O?ý_þì/¾Ø1ùk>ø«>¼¯‡÷GìUkAHë4n5CWZ^¼èÆyƪ:]U5÷b À©IPÍÚºi ™¾_#ôÚM…j5Ë>=F烬mFMÙñúWn˜›qëú«I­Ûˆˆªñ/·¥@?V–æ:hë ¥@“Ü2/5Õ–0Ñ·ÓÌm1Yìpo*Pº>ÌðÚ¶€kµk–¤%û4ë¾¼C²ÈEù¿Ñõ’ĉ:2W§Êj*lö·£aÙzâÓƒn¯ëŸ> »}Þb‚Öx<ب<ëéê¾Ö3Ä ýw¥Ã—Àdø€­PÁ:ù¦YJ¶Q Ñ\0ªžuÇ`.i[ʾ÷]g€r×/’Œ»V&KZ=±à4ÇêãÇuül}ýW·¹½eò·]ÅáƒO~ñŸþüóÏ¿>¨ú³Ÿ šQï&0¢Eoñcs+¡Vr¿a÷G‘„‰µ®UÌxRsæ£à¸‚d ¸užÆ)_¬±§-£õ,õÕȯÊR[ý¯¾òê+/_{ùÕW_½ö*7c%7Jë„%Á¸x¬[\•îT kÜ”6â¡Bç¤Â–¼2n‡JÛ¶¢fø^û[¼¹ÒQ£¤ñµïeôðO5Š4ïÒ@IVŒEð,Õ¶B*mYêV½Us…&šÆ!>9lŽóáãƒñž àãý¼×Ö&€?ÕÓýau­ ÓÝqk‚×<œô&ˆOº!Õ°V¢j΋øÓSp&hûA.nçE¨ƒ\‹ÎŸB±R¾³&åÙB®¯}þùÉO5ò* ’š²oãÂDžzÍ *¶[®®üb?übõòå+W~¹Fù«†O~úñÏþó?ýì‹áÓ¿Š?K¥.yc*O¸Xܪ¢®8Ì8’ŸÕ)‰-ꘪN,¬LB‘5l%Ĥº¨a+ÒNÌ Ö e–—ÎbÙÉ5›EL^íÕ×nÝ~ûW®_{éåWYeróäë¾E¢ªa?zꓘ›šŠú¢ à¨BˆK X‡¹ÌŽ©BÞ‘º€•èÄ1jÆ—ÚÀX<ÚU¦ gÁJ,Ü}§mÒ‚4âÌÈñ.ÎÒXm£}hž¶{]~úøpòp’Ÿ>Ùoõã8ü(Ž'q¸øÜåjº;íÃþ“øÈ^=yr‡6>bÉdË÷ó°Qî_©caLèȬnœú˜»óAQQsà&óâÎOÛÕ*Öe+îC‰°w‚F>l?pbkÉŠæfVýT=ÿÙ/.Ÿ]:weeõ×+› oh óé‡?ûøç_ Ÿ|ü×ùƒ!³_.ñ[ÁŒ,/ž£gú©QãÞ¬ºmUåÕÕ~ðÞƒÂ)몸#^íºžôíȮȉŽdOZØ2ˆè|~1ï4õ©Ñö ÞA=÷ã›oÞº9¿ùæ­×_¦ nMÉØ·Ñ@Æ§ãÆ£r¸ëR¤ 0‘ä„ìÝ!qlV7±Ò =æ’díã›ëY}Tœ½®M§ÕØ'ù>î6±®„0;œh·I/…¥þ¸nÖÞxW8ü9ž„A$°¶’í4CÜã½.í?÷ÆÝÓýÚ rÜOÝ0ùñÁ°yéôùjow’ö§Ž£¹€£ü¨OûƒËI%[tv5bPb#ßyZ’ï[È>a2H¢GG–܊Я•a. ö‘öMv¢|/¢²1–æ8]«Ã’[O>rí#)›·ÏÿæW+ÏW›++¿\ÙØ23<|öÑ'Ÿ|ôчŸ|úÅ0úøg?ýdÕÎ[Ó·ïºF4OÙƒpx*¸_JÕîŸü`÷ÁÎÝhð‘U]È-›Ñ†•n#Ó ÀA…δÂÚáÿÕ¬^B¨›ÒwŽ ¯á‹ù>3H>tÜOÉB°7ß|ãú˯ÞÈ­}»¦†\`a° U?»aºP(’«¶¨´˜Äå±dµ´ä43–Í HÙ³–ý3´¹ˆ+3Õ½É}j‚F‚“Qq[‚§”«…Úc©…OPË>ÇhÕ„ÊÄIš8v“âž4»»}{pÐܽ;n÷G{»»ùÀ†hòPmØÞ½{¯}z0½ûpooüøé“<ÜŽžµ¥eFðþ*rqix íy/ ú à.ùâÚ˱–+^+ͦÝÓFžDÁŽ=Íaí|êÕV¥ ÑÍÒKV+ÇD#·¸ù›_¯]XÙª.\úÇ_­¯¯oWÖñùÏ?E‹¶_˜ø³-+éݙ鲷îÜ,4!:äÒ×VÕ{?xÏdðÞŽ àν?®À±ZÝve_Ø\€r`2=‘Î €–g%TË$3 bêm‘õ¸Á1—Ãrs6n¾a:ð•öæÍ7®ÛǸ(ºÄôrõ¸ñQ"„ƈB »î¨–ºRg¶~mµ/“(uB'ˆ¹רÎTIÀ!¼%VI#Ÿg˜ $VTô0F&#¸×϶T^³OòÍN\ĦFOLðÞ}7$ûv7T¬Õ}Ó‡èØ<©˜Ú:•Þ„Š”¦æØxá5ÿ¨9H¾5 âF´ÃÀÔ¸]Èjð% 5R“J)`›å³•$“÷õ›_/_Ù¸rñâòÿó«Íµ$å†á‹/>C›è_ ~?l ÃȽ/{`~ÙAÆ)Ä¿ªjçÁ{²wÿþý{÷߃V9Tâ@‚WNxœh—ˆm#ÕW+h?:L&D1¡êÕ De´£vTÑôwÌÚÊ úéÍ7^yõzºyó:¨öìÑ©Q° ¤\ß6éT z&H¦‘ôÓ‡žÍŠZî¾ÎÙ¢Bd&Ú=*Ï%QOz:})hÐTaëaˆºb`ÛµºDoÄ"2¶z4RŒâ_©ÖÝc[5Óù»[v¢>Ìw!iû)Ú·>­½áÞ½ww'? wßå+c;V§¬®¸W^Ь…¥&ãìM}x½#e;óv’÷ël<†òZ¾Úýº`ÅŒ—MÅ1–Ez¼ý³ØHÞepë}eåòÅ —–¹±¹²Œ&8ÕGçóÙ'?ÿøÓüÑ 6ŒÊÙ½ý@›¹OH_šèbKñ»÷Ç;{ï=¸w÷û´c‚¸ó}ó_*må'jcrëÕñQ^öè´Aëú<«•Ï'Ý€;dR vt3¸)WOÔõò n½ùúë7^¹ñòË7®µìyi÷DÏÔžæR‚If•ñ% Êĉ–t_hˆŽÒC²7ʓŊƒ¦fÁ÷sŒ IDAT1Aw ïHHíq ì¡&6ûC1`»u}×®¿ûðìðÏjÏM¾'»%ßFé7û«åÕÕååÕÿûW[kW–7`ƒ?>ÿüo¾øÂð§?ýéÏ>TEî‰fÖ@œ“£ŽŒeO\Ý»WU¦¿ÿG¼óÞ{ïíØ¯©âr»¢‚zlÖ½ðg…ïA[âÚìT-9DË’fw«¤ÉDa.·ëÆ·Þ|ãW_}ùåk×^zéz.4°Nœh® ’àÍe±pémDº7kúÔ‹ÎJ]«íj‚82¢ 2å(½ æt¾†êZóÍî8©óÄ6/ΘVçDꢹKµÓµkîõP)P·ÕÛo›Ü‚ªðÓíj<ÆÖàÓÉäh2}r4æ ‡¾zû;wО¼b%!y½^øN?©‹Šf™ôqx)8ØÇ›¾(õí(tãÖ™¡qŒ¥€ÝAxµ¡eU¹bZyæÇO`“š3+¢ÁÂÿͯÿÛßþúâúúÚ¯ÿ~e{ýÊ¥åõí­íês3Â_Øúàƒþê§ ÿ$;æÅPú÷sH0=hª¡˜ ˜sõÞîý»ß°[Uîß· „X‡X%t YBÿ^[¦jrÌÁ£¯Š*¹‹bïƒXОUHê°$¥ ~.þ£Î²Ÿ¾yû¶Åů¾öÊõ—L¯u$ìB˜ä}$×UŒ3º8(S—•N¤çá=§ê¿¤R‰P0'­ú¬]` ³à-(u#­Þ:ëØƒDâ<•Ž ÞÓ(kžd®ÒÿAâƒé½ÛwÞ¾Sq5Nªï~ïíÛ &“)v¨Ÿ²Ö,`SÚ± àÛß­ÞyçÍŠ$d6Õ™°%±b¬Æ;I£5ÇD™FíËstd&©.•}‰„7Ȉµ¤2‘– ‰õ|'ˆ¡uPñ—¢°áZ¯‡–9ªüÍ?üïÿöV¶ÿáWkÕÆÚ•‹WVö›;w†Ñ_ÿõÿõ_?úÙ ÿôOÞlÕ»_°4¼Ÿóª Z†qYckz°ºïÞnÕnuk’ƒ÷BnÅ çÕ#ìãØHbG’äЮ {ž–*Î%ß–2OáTì1¶øö[ï¼úÚë&‚/·ÎH¡ŸÓÂcæ$ºK®lê+ëk½ƒ?KÉ’'ûL€šÒ-¨)}aQxê[¬‘1㬭8žàt\šåQrt´dGTXŸÝCÇm×ÑãTj~æ5ío}Rçê-VÄdR½uëíÛo›v›Âôšòc½(@&sÕíwÞ~{ë»7ߨȌ4-8Åw5X!žÅ®¤Äl%-Nžªíò]å×®çl,Fùt¡Jê·BÛ[k?¯úd¥™Pz^É;Ï•tWÖ8Wž»ðÿþíÇá[[«ëk—.^^Eò›_½òíï õüì¯>þdø‡4 l…Cs·í£<Ç¢;¶lã®Ô¹Õ¶8;mrdc§-˜IåLŽFEM*A3EZ«ûãD jXôCî)Û³&l~Þù&7¾sˆçáÔÉ||ëæÍ7o½öòµï\»þ25 ZAÔ”n:3H¹ ¤ÂçÚX€<%®=‚rh¢ méé¬x1ÍDHû@hÄ›²GºÞ*)@Q¿*i<ùî Ó™´D&“(2^½õöÍ·ªÈ–'ãêö-ûªï舎 × [(Vï¼~ûí­·^y¥š4ï§Ò©ïÑ©¬ öÿ%!Þÿ[oÖ%Çy] â«mk 1ªrølY³d‰ˆé¥ïr/-«%™Nw[º" ° o TF|CDdfÏ·}oË—+dIE€ÄŒz³HSÄPj-KW¤(»õ ÓßÞû| ­¾]$A …¬¬ˆç;gŸ½÷AK8žFáµ> òV®W4Rœš 9— ‚)Æ(rC³‚9>“n“W»?bÓ é*~Tœ«`3eÊ¡µp©ô— (ã«ØL$FÉt؃—˜HàÂxºápظÛÛæÛôå/|áKŸçûA‹³‰%'e‘U"1|{œzÞØ-6lûA´<“!ßc«â K±oY¤1'ja•RæõX™¬Ç/ÙX²ìåÀYݹÝX”R•¾¼d%rQˆPƒçüJNjàˆÏçîô3Ïü•CòcÚ›Qdúwì«u|ô̾˜?¹Õè%jôfEЗ)µ²"=Í9à›ˆ€a§ƒ9[k–ìžÕSRö—0[üꉹ] þ$ú¦èõž"ë8þô§žÚwøÈƒ°ûï+û¬¬î?xhuüá¯~÷Ù/}5`ýþ/ï}ÐÿÇ¿ÿö£ßÿþæmçÆ‰ReéÑîaag´FèÀ|–TUb^N78ljZßPšuÂjaʤág- ­¬±ä‹óîáÌj„GÒùeŽ\§óa7:!sQå?{ö™g¿òÅ/&[Å…b&hàd*ú—Ž‘Ñ¶¸¿±ò匈¼º\·ÀºÜlÎõ~Ôyl§Q>ß)îç´²dÒÍžƒ!Ö¨1’eMõÛfEÉB*«“½Q-™A`pÿŠë$íž¹ã_ÿšëu§¤Æƒ‚Bõª{ö+_;6:ú¥Ï#Z»ZYG\a5þè7¿ýío?üõ¯>üñÇ»øxüèñîƒû>È}ðÿþæ[w†#3¡Â)¼•¬(úQl&ØÈ5RO:HW:‚ƒöŽÁ&FŽÝÞ‹&´‡î‘!uÔuËCÁ!ØŽ8jx+TDzóFFÎÖFzTÆäÀêV­#@;}±Šâ^F«:ku@ué(¶úIfL<½áýiùö½0=Ñ»*ã*™Y˜èŒ&`³½`ÕL B¤igÆ1*à’ÄÚ\¾›qwè,à_:%¼Üm¬æ‹áf¤Úƒ‘ÇÄX«_øì3£¿úÂgþ|u6ïD†°Ü»·üPn®›µµÀ„ìIkêÖR £P³g^ßU£jk‡óS<­©<µç ¡Væó:Óe’ÈÆ¥å¦؃µßýþnè>þøênNÇñ1ðèûv€o\½~Û Çh6Á Ä(.M­*c‹(WIòXtºð®Ôè‚ åÑ €»ú¢öSÄR¢ ö3 àˆÎÌ_dP›õ‹F(Ì­¢nW¶$ñ²œº‹K†¢'kQô+Z]W´VÐj5k¾ˆOmLc ˆò>¡š)HÕÜœnG;ô[Ò/úe“äY+XßGUüd:éŒV’¬ºÌï8Ÿ¶øëóÅlÞ¬~õséh-@¿³Õ¯þùŸÿÅh˜ûÛ|BçÿæôÍÉ¡:_ýrÎ~ŸÿÊgÿò3£álîé ÷_ð±÷ÿþ/{õCþ`e“ddAÈ©ÅRëDÅé¾.d§ÂäƒÍ3˜B¶UU­‚¤¶^Xî¤U0J­—Ð7l.<¬=ðÉxðÇõÕÃGެ ×r$ºýñõ] Ú‡÷óüÁ£ÇûoÿÍOߺzãÎx<¶©H‹Y0O¡d4|­ÀåÊ,¢œƒchN¨/‰VâÓÓaf=.‰ñ”ÎEBƒ*4¢ÐãTø‚Ô¢÷Ô†ÈÞ™–_Iä$a Iã^в£y`mªPc¶‹†°[“S˜H«ÁøÜÈäå4µ4µþYágá7-ØJ4^•UNŒ«`-Q0âÇ$Ö/âŒââ^Æøâù˜jóåèf«_ýË?ÿÌj§”—ÏÞÕ¯ŽGûö;…-ËDxç¹ú¥Ïýùg\N—«ùg9˜6fÀæ÷þp/þ 85J#'Q<°x(¤Z‚‚æ¬Éõ}À®3´"¤§’·Þ Z½£y VØÑóh¨Xž3o϶!!ÊÁ®€+‡VVW×ðÏðãnßx¾ß¹ÿ O÷<|üàþÃþ;ßüæÏ¯ß¸=¹¤E‚ÍlOŠÒ ‘'¨utH;uòduúÂéW¿˜k¸Æ·gSwlj\ cáH†`ktõžER¥›«ãË]÷±6J¡¹ÛñÑÕñV‰·êiýŽ{ìT<]Ìc)ÚD%"žj_ B{Kv¶âU`ôÁ¶‡è1]ï”ÖŸ/£ ,gg…gâmª"û¦$ò‘ji'—ŸÚ]©Ù¨I¦JH²S„èf]ç([ýs^M dîv18øä~ÌÜFC¸Â9¿®O<Ì?ΕVãëü¯ÿøÿø_÷îýÇÿ¾wï^þÜpdÔûD•S’aÕSëékKÞÛè@ŽÚQg\¶êÄ;Ex@Û#&óM{Ášb) +ùÎX19 ×8#puueåã_tëÆßõ|p¿OéÞ#ðQÿÍoþìÊÕ[ãÑ(%sÙ£Á­¬ä“UBãžk»0m§þ4Ÿ2ÇsŽƒFŠ:‚£ -+U>ÊéïñýGý·¾õÍËWoÞÌz!B–éeS*:yƒ݉gžsîôsÇœ#Híb,V*Ál`+Õ ,!0Ï'vˆ’9¦ŠüAãpQ> '-Z X˱ŸÙ|)?ãX=Nmššü”ª1ÂÉIàÙ:zá©§ûîuNÄ›i«ÓXÍȆ_•|äÔs‡åi’67 R9U˜é툥Šp‚ñ]™ŠKn”2ë“Q*Í8§aê˜FmsñÝbQr^þ 8…á™Ý°°Û,lØš•OÄë ü!>öþ°ßÛãü¢ù†Bðt{âC>•QÃk Zÿ#bU“L¬¦"Ñ"ws ߆¥zßW¾hxÙ*“jE’0ÿáÊÚÊÁ§ö`þú7]»óöÕþÞ/Þ»×ûêa>…‚šðwß|ãêÍÛ£¡í lZ­kõ¥´ÔþéœîÔÑS,GÇ»=Çœ‘jùw("4¢®˜õAäJÖg(-óNé@KT0kK‘\¦¼ŽOqp½MÂeg@0Äk¸Ëó™¶§ìíª¤}Çêp’Æø²>É —Ê%>©×¦[Uh°én†Rò‰S¥ˆ7@å§fñÕýfñ>˜òù·p<©©®šNikgŒFN­çŽe%ö-jMKÀ~Ëy2c;h6Æ%Ù‹b”Y7·OœÏçI)èŸ~øO?ì¸wï?õÿ´wïñ«š'‚oxòèÖy:?¦Í©æÜxÄ7Ë*^:a×ALA®+2…µµ¶e{§Sõ›^½¨ÊpœÀS|ÉÄü(NÃï~}hõPÀœü·ÿñÛ[o_»õóþþ{¿øà^?Þ¿ŸàãÝþ[ßyãÊÛnd⸶Û ‹7BÎ 0s'O=ãÜÿpî×î¸C:%hÔgá¢f höðv ûIr+óiV­2F ÆvÄoLÙDÖ¯ð›)€q”ÆÈî]m4½HŒþ̯auEÅQ”5-ø8îK:ÌdDÇC].9¿ U)c(¶‰Å Ú ~¢¦¹†§Ô±2Áœ”"bƒ$qWUgr8¦3XO°M‡tÒÁC‘bEî…—{ì¼ä<ÓmÔµYÍšžòNþ¯|¢6pALôßñÑ÷å‡üa|¬(—=y˜1›‰`ÁCÇ”T&FŸŒQG'›Y£gd< )ä¥Ô=TíÁëi4^ TVS£Èãåïüî7ÿ–CoßþCk++¿úð£ß^¿üóÛ—¿Ý¿÷ÞûÀ‡ÜÛÉøï¼y9w!ã @¢.8Òñ‡ÅP"y=ÇéãÏŠ3:†$9{r¨lžÊý[ƒÚdUåÄ5‰sHŸX‚µjê1 Tðë†%ÅÜëjWžÃ…,–ÚºšZL÷´¯ª^&y¸ÔFxMžÝuË”¦d Jžì ¬(2‹F’ãr«Í2n,îÄø˜EƒÎi_f‘#j=^¡Z–¤x@¾㰭àµh)t~ÓÐBdOOøfk1›i< výúð¢3}öYäÒ k ÿà,“âç8‡½eµ»h:®x%oÍĵ·‰'QY‘¦ªƒ­'N¶ÍæÎö‡ÿ6\]Ù—Ûà_ýê·|ëÎOÞ¼ñæ·ûÞ{?§ÀÍúÑÎ΃ǻM?™üäÆÍ;á0pÉǦJ–h•-@ŒwêÔ×á§ãFî˜Ãp¤‚ÖK& ¾ø&kU•ö“ÞƒñÄT-Ö Áº /Ž£@Nʵµ-DyV$ÐÈ(—ÛÉkÚœ±„ÁÉSžt :k2–Ò´†F±>XHJ˜ZÒ¿Å+-´R£M?+!`êyp#ÝJj­ Ú³bÂÌŠìÚB WÇÔêÆ¹“ÇŸB3–Á±õ,Ýä®`a”ûxÎk>¥Ò¨ÖelfQ]_ÔR´yçfñRE•4,†ôtĶ!ݤl÷U“hkö|,iЄ/ ÛÆÊ›¨[ ›ž! =ÃÍÛ}ô«_=x°û›_ÿÛ‡o_{ûæõŸÞøÙwúûï¾ûË€Õîî£Ý0ËøÆµ|Möˆ‡1C¥ËÄå/Á:öL®A¯ Ü3.ríŒýH¹¯–ÉŠ7 x’ 7òQÞ”¹{°U$í«L[Õp â‚6ÁÊðÚÏls¨~2º‰Ç~Ö&šƒ0‘>|R9U’éˆÖ!P ‹¾-³šò9>¹ÇQâ!,ª}3üÌz3zV9ô46”P¥PTä4,I†7s#‰EÎTKsäDKb·x;íÕ®hä#K`Sséž"—lh5¨7öèÒ3«…e›•/sêì8)(SÍ¥egH Ah°äEAH†¬ÂC,‰C[¼1¯Ygù£*E£—‰¤7sþf÷ü«~÷£?¼½ýæ›oÝüÉöÏ·û_¼ûÞ¿îô›~w÷ñÅÐÿÝäïþùgWÞÁÌ^ƒû‚ƒÍÁ4 ’çža|<çn±SæxäÂp4æ‹LDâ&ˆ›Q‰D£ŠU~¢ *©ŒÅN´%Qº¤ý‰".[v¬¬^ã3K+Ü.mô¦° iEûÒ…§ÌSUM¢ÃîE©1Ú1mB2žE´Õ­Œ ¯•Aì L6[i/€Ñæ…è¤q’&#qÈŸ@>¹•V\JÊ!¨q×6€BòA¤bf~é×íoBˆX„^œD½óº1ä+X%£R{LkæÐ •¨$fBéøø*RÍ Tc,ú§töá9΂&ÜÈSÛš9~G›2±õ”™H”4žÕÍ·oÝúèîùóñÁG^»yûŸ]¹ùÓío»ÿ_Þ}÷n¿rVMÿwÏ¿ñÓ›··GN˜hP)üŒÃR#¸æÁ>uôä1wduøì)‡/èòõ÷£Á`4\ŽCÕG5¢oNñ“¦‚ X¸p † 3ŸGUšL=hSâµÑ¼h¸7Y¶ù6½uf¦(Êë8šg™`·©7+ƒÚ¦¤Ð˜"œÞ‚éF$gE· ;ø¢‡ÔÉkŸ‚mR^ÇÛt±6SX@ˆÜ¦niÛ@b!g¿Qyåu҆؞¬~· ½p*p½ø3¾Ìùñ¼È’&å&عӧOsÃã'ÑÇäÚZOîÖãºïAH࢞/òì­è™¬ÝK’ ”P½^×¶Y#7…’|3‰Ð‰Sy¤2v• ·z B2¯G&˜ˆ9¢  Bk&Cùµ÷µe»‹¿dx©À?u \øŠüœ:.<6ÐTúQ†ù8Meân X‹-mwí‡äßá\@8,@/•7íOc‹Kw%ŒÃ—²„/­6u‚2ÐÔîЮÃ\Œ³å¡¨ŠÐ,yfcÊí¿D±y6Ç¢œ/òo5šä‘«Š>ªû½ÕˆÚj^Oƒ¿j‚ U0‘abæÌ…ì•·o¾óæÍõîÍ;×|ùú]¹óæ7ú|÷½wßÿåý>»ï··o߸qõíkã‘Êçä÷°ÜÁ`OY-¯;qêô)çŽ:–ÛàÓÇsÝh0÷k}ÀœóO„F&Å„# BA<‘ +Í„õL8ɉ´Ya5aÔ"t©D´^wêôÉã9ž ‰ÑÚÈõ¬¦Ñø¢HÚÕT„QyÝœgÕT²cßH·†›r X=RZ[•¹¦»QM¢KGÛ3–Œ¬AFàV 4ù(­‚­ñe .—3&,ìdlEl÷êCÔâD®½ûÑŒ-ŽÔqÇQˆ 8ª1ظ#ꥰj[ÒVð2%‰Ö¶ZmV*n5Ä’tÄ)Z¡´×)6™–£¤~cTʆ7ÈП(B:KÇ+$”X›k6KÑJ¬F6¡À¤Åº|¥Þ3*•ÜUmç>Á*mm-vF”H³a’ìUì[ÛWtùÖ?zëÚíŸüøg×ï¼ukûÛ·®Ý¼“‹À_|p·}»ïïܺqýÚµwrŽá7]«ª‘D±ßø¹<<Ã“Õ ^¢nϧÎËp8_&ѲM«­ÿ'¼hÇºÜ 4 ,ÚȨɷ×ô"*& ” VRHuß5(ŒØP§êÁu%“Ÿ<üºa/™¯*Âø¢&ÜÁhS§`9Š5‘]EƒO‚Ø–oݾþæ;·ú£·nܺüƵ›Û—/ߺùÎÛW¯ß¼ ‘ùVÀÛ7sxõ+WÞ¹6O†ÀžM¯j»ÌfîäÑc9æ<ùìqŒä޹ñxèúñxwǹñ`4¬ö6B°A•);4ªÐkoiÐ ùãfÔÀÝnµÖ^ Gk QKWñ8UsW ÕhÀ_Àª ì¸#’ƆW‹â9ŽðBŽ–9Ô|y†žî¤6ÿpów ¤Iû°ìhÛÄpµ´‰wÂ:<'ûúT6f$Ü´Ö°/âçŠiUüÔEXî2P_ÊS…Í™­„àR*(Qé$­£Ù‹ÞPU6‘ˆ`l …´kÎèžj,Wq &¾ŽÑoL=+<©xi"Ï OÔ‘y‰¦×FÒLÊòW­ ¬éÒŽàšú ØP±âõŸÝ¸þέŸ¾yùV>hoýä§·o_¿våʵ›·n¿þú,¥Ùk¯ç¼öε܅\¿u{„m",ªögrqñrý[wâøsÇ¿~—ðÙ£Gs<íŽ.ŸÀîñØ­­ŽÜÚç†ý&Vr¨£õÆ.æÙÅ©l-þ»£D„zJÔ×|Ï‘¦MŒ FöpJ²N “?ù#ð¾—Ò©Ž}Ê«Fj>6Øl2RÇVSNìOÄÎŒ=)[ª\Ìn+ÞiÉа±MŠbé•Û$†F0Ù= îø!`“lFÃoI1Àűì_Y–)zL•죦iZé$Zn‘MÙÆé 3%pš4­ÉFÿ‹*AÕö¥3±„궃a…üFÞWþ¦ߤŒ[’üY7È“T"¯Héum˜¾q`¨1Ýsƒ—! Po>†Ë7®¾õÖí·r¼|e;‡ÚÕw®_½vóõyN í¥×¯½~'‡æö·Þzëmxg±ãÁ¦$3×a1gôl4¾Ï?‘[÷ìÉ羞ðD>sü ws3"ŽÌxÐ'—}š»Rh¿&*€©x4þ œ‘*˜¿ð6h}ƒ AÙë7æQ‰gB†Q+ËX>¢êBqytØhKˆOÑ ˆ:Qe‚- HœqðY]²vóD·½-&- egé ‡O<ÿc+ïnØ7  /¢€˜Pn xBPÒ@›f‰á¨Å›E“"ZÑ“_etŠªœ5š «R%(%Kù栆 Ô&!¡˜¾È¶câ ÇvÓ‚áŠäìÒ5•÷r“ƒ`)¤9¿džx•´Ž€E!‡¯?ýàG?úÙ?ùñ•í;·ooß¼yûÎí×gùmÍ_{ýõ×sômßxû­ášŽÜÈ‘-›_qÆ_VNè€w'Ÿ;qô¹“ˆCwì¨;yʇ\k6Úþá—ƒQŽ¿ÁÃÜ`T’ЧBÖãqŽK /¢àV~‰ ³GÃå¢oÕ¨òR© ¦Ææ‚iMY9‘?/ì{Ùv(Iò Of;̧02—¶Z¸©•(KKØh}±Bk€A4 KZƆ¦]žÜU@…ã<*Ë9÷-”^­éD¥Â e·Ukëu(#aíŸjjJSÎÕ|™µMM ܺ­,”v3íY­>ƒ–ÛÑÈßlVŒJ]‰™^Ú-í‘YµÎêI‚ ÏÙiA½§Œ%BÓ+?$÷ºdË””—ñ¶T‘ø—z7\Åz»ÜຟÿøŸÿô­w®å˜{8xo¾óóÑh”ÿ|-Ç2µ]Ô€è6*wòøÉ¯çÞ÷ôÉc¹É 1¦È€#÷p4úÃv‡c7øC­¢/’ÄŒ%zí«€8cƒÖƒzRƒž:Lš2œµ>uR‰‡›_‹µl.2(®Õ¥ªû0é|ä²3Ú÷ÇŠûklèìËU  ö|Ñ–ü;³V;›i›(‹$ž¿/Jyˆì¡†.r,Ñ›hŽšJ~IO!ÙÙVy PQÌb3ׯ* ÈÚ¸²œ¹ÚQdyKÕ¦*Söi¨ÌgÏk}ޤT¡3²®=NƦÝå(åwDÝ"¿|ƒZ1P€K”§âªHvÆØÑB NËCÌo_n~R¯)máFÍ:7:²ººšÓÛÌ ƒÕáptûÊÏzåò•«oß¼qíÖÕÑïµµ–ŠŸ— Î=¤P”ôàçŽ=ûì±Iþÿ‰ãÇŽ»Ñˆëær˜Ïàá`gm”Odª“@Õ£·°èø•/Êlîƒ+ l€]“Ìxºƒât«Öl÷9*4€1d(@D^ØøZß‘J…—ì÷6!ã_ ×|/}רÚ­(G¥¶´Âá?Š­@ÉRscÛ›WÑùd{æ)ž±1ƒ¦Êì[ZP¥8ã3Þa¤ÜŠúQ E´ d.pÓ3ó†Œy¡Ÿè#î¡:Lкˆ† ð¡:L~:K"Y4òB0†GB$å¦27‚ ÁH­Ÿ+¢R5P9¼„_‰`Ì–¨Rq¾Ø@F¦Ùf¬æ)«¦ ¾w3wðÐþ#7›»ÁÊ¡+ù ìfó–Ö^ãÁh8ç$;¬AÒIix¸ ªI£0œŸ{ö¹ÉdurâÄñÓ'Žç²oŒdÔ݃Ã!p³¢*©É>H_, QÔ5n(~EmN^Ή´`0FsòSVd]h!€ý«ÓÒ?ya㫾àbK <Åéü ’FÍbÑÔ1áq)” > çà(ÃÐ[ÎèèÌ•*s‹x¤; &¬¯‘ÐTC4Á\tŠÒ²e¥`vò¢nsŽP3uä ÜÚJ ‚8¨ìà`Ϙ ¬×xØÑÛÒŠÉTæ^m\dȪ’À+EPPÙ3’NÊ{ã óZêhÔ{N…AÅOËig$Ã*ŠÎ¡âÏË¡ÓÛ¨-ÖÑÎñ<£F©Æ*f—Ò-æ;´ß¡knpxÿÓ‡s· ;n»wùpAÕáÝ‘•ñÐÁߊdî\ªÓ7³'2Ü©S'NLVVVV'ùãäh8®±ìG£Ç¹19š®j 8¦Žþ"O91ø¦µŒ¢ØXܱCvº:aå“h=«ÖØaÀJ¯TONCªìÌŽ:*’]‰Ô(ì,FŒ76XÁ”MªüÔ­Ú¨%ñï¥U®y„ É0—A’“Opz—hjƒ|µ±€ÄFñhà5sÐNIrd`™X¼Fi¦ä"ÇG2è©ÃCRÛ)lzÈ21Õ‚º¹|Ìl¾.Ÿ?i¼ªßTk È Z¼nÒ4’è–=…x¼œi(üìš²·cŸnR˜q>„ZªZZÔñlÁaÅ3‡‹™kitdze—®ç| 8kÜá}O^ÓdÑu‹Ö­®å„q·vhÍM¹kƒ¦~{´èÔpÄ= ybÚ2©J»‚ùQ…•h›ªŸãs¶‚h/SËM|½ºTɺ*ÎUŽÍæk³¢÷¢™iJ ~Ãa—g¶ F¹òœÉÆPUÁ$Jr°qmÔZ7­Zm„h¾¾ÚDðĬz¹šÙ1Á&M£kr+Ì ø²ü„QB3vS/¦#arÁO2&ÅGª†áëîH»5×µ3·²ÿéŠó.åóKˆÝáÃkC‡ÕÏîÈÁÃ/ÈA`0ÒU­6º"~¹íÜéÉÚ‘•ƒûLx¼³Ã­ÞL|}?¾w×í>¸ûË{ª²é•Xâ$•&Ø,‰Q¶¡öQGt€ÙÀš¦¦!¹g(PœÌV"ÔŒ>l%T`˜fˆÕ6\vƒÑìh:‘U¹*»Â£6˜ñ…U ÷ê“Ì7¢f G>:9[6èq(HŠŽÁ8ŒRƒ¸Â{i[a&±L\“š}®ÔBGå¿­LIhKÅíb’ÜÜG¿4Îe„vG¸Ž5QÚrB©›åX&œ€ðW3é¢â’?ˆÂÏ#¾JE(`>7AüYþö®nmÿS‡(üÜê§óÏd°žïÄÜå’Ðá„™»ÃåHô”‘×XתMFµÊÍû~{×v“|ê®^:tdg÷ƒp8@òÃ<îáx8\[{ÈN¦ (©©  #!ðʼnãTSÚüt´©ê„àa=ƒLŸ{µ¢¦N rŒ#°eûÑêTbrYš]qaôf~ɺ­µ…L̰I¸ŠdШóP._‹øpìj .—s/"ß:ršÑ«Ón Qƒ #–Uái©3*2ŠämÅþ±¶§¯0[TÈÙaëÍiØbi¡­´y„ÝmÙ“°"n¯ÿ1×éëpÉ‘iå5"ÏŸ1¥ª“r"ɪ…ÉjžfwœF$B š_ OCk>q)=i|MË#èœ>î Â.W}ntpßá!~FÏäjþeÓ…|Nï;èòèÀóÍÁ³‡%§HN™n´½ûÈÎ0·ÔkÃQn¨'»÷ò„îÇ óŒ^{ÕE¨¢,%%ŸÌà¦J"¹¾Íµ„Ac€4á†&{¸Íœ,â-ü·ÆF]ךh±bÕk+ìØ›Ëo¬ ÐãìåD-oÐÆMöùîb³Ò·¹l•{ñZÁFÓà²ø׆q-.áJ.´&%†Ç0›œhãUC-¼<õ­R73h‘Ahµ\¬ÄŒÆ‰ KÀÃO>´c<€Y”µ²Ò•‹¹ÚðhãPZfEZ+0­" ,Q(ÆCFd]/U”øR ˆnÅ̯$ŠŠêËûRRÖšï®sžÎ]0Þèé§¹ ?×ÍÌ8¼êòuÎ-IÒý°}m¦ÃìÑ(™ßëhœão´½óØ>qz¢\þMN?züKžÀ˜€` ØhÀ6„½·W‹ú6Zg7ÕIÐï³ë€÷HùHóؾ!¦áÉ…ÓlªvµÅZº(jR$±ÈCá|fÖCZ«¸&8jÿ0—?´`.‘yJœB‡è_Y6É%ÊM×*W¼ª£y¨·¤‹k#ÍRˆx‡0™Œ„* ß- ´hKÁhUr•áHÜÀoU“ŒP›œU¡èuÌzÓºÛx—ÀÆÕz[‚xØýŠ®@-i²ž›Î ‚‡ÝÊëÿùœ~BÍ>;üJúFãñöî.ø€§N>}ò4â6«÷îçÎÃðîãñðÝÎ( J•ÈÝ’ îÉÛSs‹«ZµÆ 5Ùµ ¢ Ó¶Aíj×ñ˜¸´];!8ǪRdÀV"ÏNYËc hEm¢eÓÌÜðbm&#Îb¯‹Æ§ÕXÀ ¾Öð_L•Å,&y¶er”Ùoh,é,–ã1z~Aq¸H¼6“ÚH2¨ä¦S™˜Ûöh5:g ÄùO©˜ê¤¸‘•ê5êåw*õQäØlÚÜ&k }™âxœ6ä„Ô›S уâ!„¯É6Xrã°t€1c”«“úR")¼º‡Æ4xuûŸ>2„Áz3ÏUöxÿ¾œáBœ ÅCOd2l[{Ä Å†\ä1?"süÔ1hBN»Snwûáã÷ÇÜC<þ×û÷ï»Ññôl<‰*EcsYŸhFå[ ÖñÝq]º?°¥Íw[EaÒ‹ŸPF:̽ ÖûœÁ!Cµ8SØÙ*íqpfà1O¥Ô²ÆÄ½ét>6Ñn<^©i[Q¡5äHìH ÃT}$Çj4ùç8ë¯&xs˜¬£šøŠ KQ„ ’L_WÜb³ ë'´€£6kšX0fI lâÛ{ÒáKżoAI=iJÒ‚x±ŸiSž¼¡£Osn‹$Ãl^Ìàt3J®R·1*r¿ñ¼ÐjŸÖ8SitßòW3Ó…éçCm¼°Úçæw°‚s7_Fwhÿšƒëf3Gß±ÿ€“ùpƒ xØq#±€Ü„ÈÃƒçŒøsÛ3O=zìYwòÄ çn»ÇþòÞ{wß»{÷i—O`´sVwDV«buŒB—¼QüŽ=OO:¸ à`%B‹ùhîÒ!š†#bUwËÙ®Š8‚ý8Ù:R0!ÜÔ3à›ˆê«“¼Ôãrlžž¨C:£Ü·jHØ}t:›ÛŽp å–ÌŸ"(qlË‚=þ<5¾dpÅ!¨iI•·¹®„IS£Qy-`VŽ“¢c™G´ ,ÔKb¾(óµÑ ‹ôœNé l±Z22|±ÀävPAÝæ‚kQ‘¶@¹>‡ØÇyG#¢52zEÞÞÑf¥îÜÚßPx"R+³œæ¼eí¶ºb!ïÁ9¬eÖÕnõà^ØÜqâDìÐ49sæ“Ùº=”„ÚXæÈÚ~üKÊN|öÄ3îäñ£GO¸ÇÛnwÔ>~ôëÇŽå#xw)PtÔ€"IIãFøÙtSÄCùìÒ³¾=ŒÃ¤ ©1ƒIEs¬‘¸Ø}¢TGÈa!&Aâ&•ªB‰RXÅ'LJ£¿`Ó°7þ±ÅFlSâ/~0ºsRœµVø‰² &¡–Ú¹üMØq¬Ó=æ‡C‘®:ß0øÿÞ†l¬Ç ðâí´ f†E¹:íSE9µÅ–¶(FsƒzU ‚®¼Ël¢gdiµ »hYØ5ó\á8ÚÌ-‹WÎ7ÓÓ`tu¹kyÁ(T`;Y•]]’n2!&úíFªRÀú%#¡ªÝÁv‹™G(¢ï…—{Š ™Né¹»\6sHÈÄêØ#Ä8f ‚¼ÿøîî£îÔɧN{æ÷ðáöãH<ˆA›§_¬§µ±‡¬š‰šeþÑà:÷"­gBï™drJë< :B/ŒS–Š¡“¤- lU8Pƒ‹¶µâFyVnFQ`— Ñ'뢠B·¨ rç#AM0q@¼*+È…LÉ¡&O5í¸özý†¶u¢>“¹¯I¬ÚV‹‰š6?°©cÉäã“f#˜»Y­½’j,Ö´ÍZŒþešQK³´’Ù¼‡d³žßÄîîÄ_Ìñ·[Û–¼š¥š!Kü‡z¢é&ì¤!¹žN«D# ~íÊ–Lªþ¬ ˆCB’æüV%‘Qg £®£ªŠ ©‰Ûÿ4Â.ÿÂ|únµãôÂî*wàHþµ¿ X¼æ,˜žœÜJÞ}üxçþî®;q T˜cÏÏ%àýÝ_>ãáÚ£>ÞNû²$a¹`„Jš®$ §óC£MY úYÔ6i๵áh†ciƒ¢Z¡yìKIÜC\,U@ªŒêì±ä9*<†G>)¹r=-{i+EÆfŠ…Rçp×qs…Äꦦ‘R öƺžTüfÔ‡0+XmÄ‹:ɲ…¹Ñ™ìÈŒ"mÕI¢µ@ÞàÍI0†Òް•© ®ƒ˜ÉVìN¦¯nMªÝÝ@2šž”¾Ù±_!„«h^'µ)X¦¶üJîÌ6#ˆÀ陋 FÿÊ7IQ)~t-]mêÖíjÕ-À¾Î?[q ªWê{Ñ}úÀ‘‘ ň+¿½=âhŒaü‚î>Ú¹·ûø‘;9®®qò`ûÞx÷îƒ$?ä@ Ñ“‘¹AwlÔQ8¥®Z.½áˆÝ,ò®y°"eÕ­äfAKš‡LÑÎ;ü´¡j(÷ï1–š.ÙbɇL\²¢ÙpK²©V¥mEö"Í%Ò4ç}Ä#!v$Ôª3k2^哊ϑÕ_ILD¿ð»Žòðñ¬0£RëŠlÞ$~ôäÁ$"nAz8æZô•âðŠòI–r(]Ú`ÑÆí È¥Þî¤y¥m滿˃X|=|݆ 'A®¯t~«*À¶4mž˜J&Çl$RPBP›¡<Š3X3ßå£*‹õFSyr¶èžÞ¿ê€‰ ¸zùF™-bØzÓÎ÷ü÷Èß!ŸÀ# ÀуG»vÜw“Á`0§‹•¶å×ßÃïsÞ’Gîîcì˜{4Y GGšlß½›óÞî½ûwYºÜïyÒL§ZH·È º—Yó‚1l¤®$ý«ŠeˆJ?R„³éƒÆ¸jM¾FÄŽ´ ,¢±d»aÃH:4SÆ IDAT£sÀì#g¹_!ÓfVÓÎ:é°¯(u*y+>ƒz U@Vï·šv ¡^®Û%`¹ª=¦…ù#hT+÷8äPßYÌj =k-e‰ û*«`ÛG*^N£ Y#ÅÝïM~à_ˆ¿zqi"‹[ ±ŒA%ö"h:ýOí é:ÄB²P³ñ„gȃ‚½é&Y¿¯év°]áIØ›ü“ÜÓ‡öIc"§0¦HÂF±šfز•Ô‰¿‡Âxø¤Ì!vïÁÎ΃Hêk+‡W'Û÷@?ÞyÿѽñÈÝÛù×G}¥ž”M-)ĉ&–ÆDÞ9¦aúÀÄ“{ %Glˆ / %I¬$¹OÓ”ècÃÀˆ¨ß¸*œFñx…¢TÌü·é™! ¾·î_gŽ©fÇ^w&²Y¤ÁU%z~¿刖Yù'­ÁÝ– I¬h•¬-†ÌE$bJ²M=÷ýšƒ¶Hö^†<Ö£ˆ]µÔÁ°ey÷óIb,«¡~÷?Oú¾ÙDümͺ­Kù ]…ƒKæ_S ¦0á ´â#zj#é ú…Ä. T)™o-o3‚*{ì Óøp““ÅÍ*˜¢sÃù&ÝË\–s‘Þv´¼È6KÖêFIÜC< Ëp€#{ã þËC#=xðËÝïÝ8ìiÛE·3­6YQO}yLHˆ,,䃛äÇÚݳüFnTQN ‚¡労ˆ×p‚ÑY&l£È£zBµä“q•´ðSI Ø£ ¬ë, qù K• €º¨Ó F7¢J&’lœß*í4bà‹vÐI›·„fùÆk1Õe ˜Dq×õ€X¥§±²ªB=Ugu‘ÄnQ9#’²vN xk숎ùì¾Ô¯Oˆ?ܦ .L'²qМ@!D‘QÐÊ&ìù‹›ê†*«ì&E›£F:¢ͻӥÚ %¸ƒ„¨ÍÌò<2îÀá5,5'Þí;GÒ¢K-Md%Úåü‹W؈FA>’¦Wë˜×8kyîR-NÎIÑò…Púe–¢aF£ÙŒkž¦“ÐìØkýÌ“c©ñZ{ú¿?3ì_8{®?óÒn.\˜Lf3 ûq™éx“ÉÈ+_|ØHÈk÷¦Êº4¶0q"­íšdà…\ͤ„ŽPBo\}AB1_ì­ÁÅ[ÏÉ0÷«•ùÕÔt›¦‰za"c/Ã$štÉv“RéÖ<¿¢Í¹“²Ð\½+dr,y×e¡0àÇŽç@>QŸ‚ÉœnhbÍæƒ yX³/Ñ@iÿÆh¼öÿ À¨B˜#éñAþaˆ È‹žh 6Œáâƒ¡Ò QÖû¢ÍJ&èåFÅaD2‡½Fèäž ùý‰üSG9 ÷uôC#e¾_ ?¥3´ËìÎ’6BÏ,%4¥ïбéÕJ.P#D;òòeÊ/ÆÂ Iˆ§î^B §»«ð_øÕóM½ uÉÁb*1ä÷¥™m][âÝ—{kZ¤ü)Ï.É‚&¼öFöæsÒ÷ƒ³/ã¶ìîvçϧnk’+þW7ó}žá¬n´‹î‹h=Èôzʱ Wÿð`7[|ƒäS Á(rü6»·$ÉiþUY(\ºÌJ†ØÃB~üpŒÄ/§ÔŽj ¹‡O”[:òñ@dÀáÚêƒm±`l<æxœ@U­G‡Œ3•8ž ŃÂZg.\Ò\ y 5ׄŽÔé`úͰJÐ Žª[(4b-§â Ñ“hÀ¤Œ6áÒR˜|¨Qc£–„œ0F©C ‚1hrƒ5tÀË(‡kƒ]0±¸1$“îç_ãÖÞI¸@lÔÈŽ@OÕTæ±Fp°U)êhø-È!RN2˜ð$Ÿ™ñVÓXœL.l]Û ݉jÄQœ‰žù€¹½]ÊâY%S¢9“ §‘‚]Õ—È{lu4_e‡~@š{ò&=ƒmC'C‚y·h0$$B`Ö[2­Ü¢µ›ÊY …BgÅOlÁcN›¸kùaçÍL»FúïïžwÝ`ä^Ãßig“±ËµÄâµÉk 30IꊂH.ÑNÃʘÙùºÎó®œÑ‰ÆÚ @3ôò& V¹š·¥w»ñ"RÉJ8ØiZpó©Aݘ=³%VE+“Aü¸'Îx àh\°Äß`´òÁ½m´Èä* ÉÝ—¤J4ÌJüÜx¯®iÒgS2Í&B£5õmšå ðA2øh"‚fuXCPkä.ì-Úub¶E2ª ©UðÓá|¾•EcSFkLRÄùÈ!LVÍ53õß-ÑfU €¥TbÔªBÈÌÒ;ÛÏ ä)Lí! ÉÎIg¯ÝywQa’舣ãY\U{µù0QT¤!kTO­¹A#ÊtîÁgüè:ûDK¦þÅá”ëÃ{åçÏçO›LF¯¼zñb5™oÍ’(ýu×¢³ÓJ¬ünºü.XSm6&éÏ4z UZ™¿;ž£d•&“¶üÙ­Ûà¨QÏOe Z.•¾µHŽ. ÏÄ#8…áp4BgËs6YOÚßd8ÚÝy÷ƒÝ푱sŽF÷û^ÈÈÜžÀ…KD=µ,Ϋ»ZåkË«yÓ@šÍÆ8Ãø?_R˜­j áF{¹<ç@!×µ±X™i‘f:}-CùÆ|¡5KÅí<×,ÐÒZ·5”!åw¢²±‘I4b•Ç^]Ü_¹KÉ@˜{Æyˆ~•® 9„¸äüˆ›$g›Ù\`¶œE´lSV¤ÔÐïß(ÿ,:›ãóºÜZÌò¿óüÃ\‡cþvúþ¥s£s룗7Æù\k^ùÁ…‹'2àl¶˜õßß¾ðâËg{HV5C²C {T~G‹Ï;¬ËÎiPˆ•ð¯ ô†úYâùp?'Âd”Ect-» ÐlTÞ6ÙWSºKA^&>qYOä#ØDñ'ÍdôøáÝÁp0™üq>)½NÔé!霊6Vª£ˆ’ÑŒ?8ëÐÈ”¨|”zò,Àxö∲üeµ+p¤6Ÿ¤@/œÊY+"S âƒõVЪ%Lâ(à.-«;´dÉy®“äÐÒF¡õFztÙü 0j€°¦"дÎTž ¦°Ã #•˜³¥œ1ÜùóΛw…¬ÎU§‡2d‹e/—÷¶3ÞËꛇ¯ÒB”{ÎÉx¹TFì1;t\¡O¡ÿîË£³Ã³£õsc7=16‹­ÉdâÆÍ|>YÌçý gGß?óý3gòmòµ‘c7†/Ž {Ϊó^x±X̽€h§’CàYÆššäB¸Rå‹>*ÔS9IÛæ]XThêCcHîaâZ’*pQ“î2dÆB‹Þü[Œ;Æß’£r“Ç;;Ã#‡BêÜè]²†ýr»$zÔÂËåœHÇõÆYOwR2îò¿s¿]2"²èU®@"o H“a4kšCø…qÌ6Ev‚AÖ1õO n²#¥Ã|OKÕ/¬ÍsüÈJÑHùÑ2Ž *S˜My¥ö¥1*Ôs SrÜD´ŸæïŸh3[¶”67i âMI¤q²¥H(¬=í¾rtK†º¨sBdÛ‡Þ÷/®»³g†ëƒñhØÖáütvi2{y+ŒÉ|Ö¿<~á?¯Ÿ¼°ñ2‘‹l4wËa ¥P˪­vŽÓ}žÃ0Ú¨@ö5ðƒ7Ï>^G¶ ¢5ª‘yYØ¢ñnéþÒÄÒ,”ÂÒ3_owÞŸw·џÛ8›c°yµ\š\˜œ&´m.çýwÝᯥ ÃÁzŽ@”´/¯s? ¾Aôu‹.€³y»ÈgqŽõ…úlAÁ)ñ3‘OÕÀ²´àòGNØF(Ô·H9Ùê»Ó|³¦É:9¼ûN#üœrLfýkh†XBdöÝö6J„Æ‹¤+„pèžp9×%Sei‘Žà`HòØuç9ü句” ó …«£¨=¨âzø&çf¼´¤ê\9Qx´‚ìÙS-÷‚Žõëh{µÓÒ$µ^>Œni«¸ÛM®S6Žc£FĦ ´ ³áÂ@jã ¸ó³‹]´ÂI±·ü‰èוi‡ šql¤Æ%h;œ¦0ØhxPæàX0sÌäúngšK¿ÿ£_Õ“üÅ'?h&ó×&›“áx88ëb;ŸäÀêÝwûñ‹ùˆ¬r¢+ö›ßê´\ÂÌg[9nm-h\rHÎEI®¦­µÚ–=;»±G*Õ&OòZôdV¥Ý‚£iY‘‚ÅOãÄŒ†~]-«\í=Z–ˆ9ˆRð˜=ó~þžc_¤H Â3€i²H~j¡œN!¹Ú4Æy-ÂzÍÖ#ŠþÉs–R_Èo[ù<‘ì¹ðCÒ–ÙfAggž”„]ä†JjLìZã÷I££³ÑÖ÷¨ÙXÕ°¥ *þ ­Xÿ4aEÀ=†œÙ$CX’J"Ëý(0[Å:ª?­Æáâ^™O]!æ'rÌÖƒEŠ7ïi±Û“$˜T.Œ.}3Nã†4•bæð[ä_¢a˜måì¶îŸôgÏ RŽÀÙ<ÇÞb¶1™l —½rñât‚¾¢Ÿ÷gÖÈã³½ô9š9Óœ#þp¼/n±V~Íÿ×[éÏóù˜šû4—óMty¦ ½}He©z2ž…‘_¦¬Ô33ï嘩ÔB/Q×JFÎEd:ŸæBCÈ÷•D©5sÞ›!Çù –æªY8–™Š"OäÖô®ãÄ¿‘ý ½øZ),mE%‚|’vÁ„¿´*Ò§"M@J”x€¼‰Ó]¸Üwrµl‘ÆSjÊ‚®–Ä]ö Ržóakã„ú¢ ¸ÐhˆNÀ’H‹AAg#¼H´ZÞI$»ÊW¸ôžã2wáâ<9 ☠V)•¨æ³˜)#j¿%JþÍðÈw3œ¿ˆ‘gfþXÌæXìwΜëÏl¼2kÐðÎúÉk‹Ùp8À"çšnk²Åšq6Î"¢«âËM&Ȩø9J‘ópÄÏ`¯›¿N“ï÷|Œ˜ mà"M3!¥ñf'óI,_Õ›Äd•É3I~¡É/ïJöþ¢»’íe1/XsD® ÎÝ=i~ÄDÍ‘ßjǼ‡ÃyÎÐÌ‘˜¿GÞj“‡7 úïz)E@Ë#¯YšÐk±ï³Áª¢Ç`þyjl`—–„'ŸÊƆûy…dnpàŽ¶3+vm{5uÓÈˬ4*Ál “¥´Ö2VЩC"¾–+™m?;Q=<ÔQ‘ÈD¬’…§éîÕI§8náÁ¯…2Äsäˆsf˜¤¥÷KXƦÇ/ʾ6‹ùrè‚éTÎú^î×Çc³üYýVjîÜKë¹z?3F³AÍQšÃrýÌ G`5í˜öÌrEߢίŒðe^]4 …;óaaMQ‹<˜kr`¯…Í]^vxÂ;®4\`õ·$¿Ðb_ÔnÏôGl££õ#+²:£*.ÈQ³Ç>ÖÜýÏ€°vÓ‡å½üþð' ÀÄÍ ¤¸0Ó°Ò25¾—Ñ!©t¸™b7¶&Ї©Z£ÉËmé7TS%¢ŒD6ÉØZPW‹§æ*¦›b )Ú”no”õðÆ1k+©ß#wÍè„eТ®Q½*.N5¦pªS*^¾³Q»_7¿O«ùÌQ"Åà<ø¥/ÊöIO§7€–€`Ð.ÍÚü^Ûuäg¥ÜGcoD‰n"ˆn¡ëûŤ©&“ íy®­Óìå3ÃÁöõù‹žPtn0ì l ÎöøÖfp+Ä š^œ¸9›Î™Qd¶Ì…íbÑiß;ؤÍÅ>–³Ž<1=}Xð"- J¯B~‘HWåqmVÄšÆKŸÁ1 xȰè "nåÒ'pî” çðÙbÉʰ˘«[üÉ0Á3!÷ɦÞúäÝÃQÏÔ¤0®×ˆË†¬ÄEhŒ KG㬣ƒ8²Y§–#Ú'i2I,*,¹‰®WljfdR‰L”/ Á³12€®^ŒNó¾²'NÁ%•2eו‡”­¥Ó2¿‹3cî$÷×ßú›oþoßú¶cm¿+:l8WÏ£ÔÌÔvà _.d@*§Å1@ YQ,Y¥OËùëmÙ‡Gœ¡øÆ3º…VmÆŠ ‡*Šr´…9wM¦9’.Lò‘”Û‰Åk£|Ôn`ŒÐζ&޽í<ê™õ³ÃœùYŸà¿iþ1¿`n@fz9uÙ‹® Þfkß5k2,äûGéMV¡ôÄÙ·™/`ecfH­~ 6“¯§7Ù"’ÐîA?WyP)0êíYr =“®…`~³ØÌ\Ì´Àë´$•ÛÊÌE)ýNkÆ/¡Èr)þÁ×îÈCՊ膨ÕE¦!W¥¹ÚlN‹SEØ5’(ÇÊ„òèÒ¬µÔZ+¶¼Yw›ž&4±À„h¼ºÆ†u‰ºÑD £’‘2“(ú…7“¿ ûÆ7Ÿþùoý¯ßrÜKQ Ì ð¼B ¬ùAíûüaæÇ:XG)æ¤õ•ôF¡ÖÁÌÆ!g@ö½Èƒ¹]`Úë áDdãu1ÉÁÔ׋Í0_ñ¥\Ž^tm3Ÿ8$JÔý 92ë9}¾\('ó]Ί¿9K¹ÎãüË­ÂÔ&ÄÚ(:A^Z•í×"›^§3(QîÃæ*íGW0ÛJü†5¦Hl­+å÷÷žñž€ÀžZ€}èBZ¤ç¶Iaˆ_/€Bz ,‹µF ¨$3òt†‰ ¯Ð¥^f"£ê7ÍnCl "5F!P D¥²D•î¹\œÀ¡rk˦™Y)Ìé,ÉoNx±5o¨©Ž“™ÚStìµL6蔪¥ÂÊ+˜´Ú8ò/ºo|ûùç'Šý½tetÜqççµÛ÷‰½ŸØwwlõ‹öÙÃe9µ¼¢Ž™ó“.j«—êgžÄ‘Ý/ŽÜ™Æ@ Áè¬$"½@Ÿ›ìÉdÖÇܸ¶çùÆ:¡zóbS j»þÌÙÁúh ˜= “ÙäÂb‚“Gü%XndÁ”¨5YY@åÅœ—VD. 1ã ®¸ƒj9h ÌxI~¡ïÚä(š…­£ÏóœSÇF39¬ià›z4(vŒE6Á0ÙGÞ[ËGp{ ãºQ?ãê„Î6:²¨ÍE– ÔÆA&SªhòpâÉÂN0MkMÑ&¶J+¯\Ú&C‚c1 Ñ苊F)3‰VKJÞiT†J hg£\ÉfˆxBT!¨@6–¿ÿ¹6‰½«ºÞ&Yú,Åd²² ˆûÖ7rü=ïòåÚrsp²;>ŸÀO?ý'òÔ•ÁpøWOî +äù…¢Í*Û‡¯Å¶&¸´’k8òȱ`µ ÔR¸„êT "YmÍgù³óQ‹ÃhkqæÅ3tPns2pÐÍÖ<ŸÁg×s<ØmœËwoâ›ÉäÕù4‡Ë-ÚÌ•}ð‚éP¨eÁWNT.œ±ïš·Z[IMGoûº0k¯%‹PÅG=Z¾LXÑmçfÁÈôM®Q€9àf­¥Àsô¾#$ÀüÆ{Ö‰3ΩdÒâéÊ󗽪® aƒMœ‰œp±y’Ë$à$á1*ñP)â°.5É»…Õb°ÅlÁº\R÷ÜüÛ8©À¤#%Ù•FE¡…Q/v³Ô±i§A[¢ã²È{ÚÖÞH²Ç¿Rc<¿÷ç¿ý¿u ?­º¹óê‚a õJŽ¿§>ù©O=uàÈê³ÇV?ù…/¬%m4þgå±.37!4¬™*_õ¸U(ȘòÀ—šÍŽâò¡4붘·æì¶æs|n×§4 Íèܹ¨gǹÍއɬë‡9sôË)p¸¾Ñ·“nºõZ΀€Ñ[#Þð“n®T3ç¿ÞLÈeÝ&èÙp¢ÍeBP\È/Ìë¤*R¹†¬’@dŠØé°‘W6̹'çC”‹’Uè8fsÞ²$į0‹D\0váÉ2•à2š““|x…GÖâ>Eˆ8/!¸4d×·T©‘W"v àöNu™¬€’¬:ð(2²ßœ®ÚŠŸExNç-ÓVSÌĉ·ÑZÔé*Ó(›ñFC £L]Qn6vd( J©¤ŽÄ¹¿þæßüÍߺK]õÊ…ª[8ó¸ðJ€G>ñ¿üéÓ‡W8ôÅ/\#FQû>™ë”Ìî}1v¯É›¬keJÒQæ„Crçè¯5(š?ððñî ÊËc±è/ÌòµØ8»¾¾1†p6“\-¹ü·ûsƒsH£Ü ¯Üz?Ÿl]X¼öj‡ ¨ÊokÆ)CºáÑž£"MŽEÉkÃW”3¹Œ´í%©Á8Ûµ¬/Ñ`HuYúò ÝaIŠÔã| ±˜ÚÐ&פsL‘è€þ± FA8Zë ÞçŒ)°ÏŠ@ †YMðöZÚF.2A7ø<­j.,qƒš£% JÃáÂà–ƒÜ±hR‘ã©3ÖNâD.©O%Y50}c«Qi:’q°’<ÆòJЦÊ<ƒãµÀ’ÑPgžÞFÁ†‡z Œ­Àþ÷ßøÖ·ò¼è¼uÚ9ïj\¬ºó[É­Œ}â“O:|è+¾t`Å'¥;…7§&ÒXJè;5?IOfÖá0õΙ’B_:Î-:æ'&*BÈsžÈ9#Íú”‹÷­KƒÑ9Èf‡Ãq›&À)Fn«?·1ç6d0­Ÿ=3^ÎøêìµW[ÐQò°^ ÿà Ï(G‡“Ô-ä2%‹«l¼OYk¥PÌjÄ~1 ÆË|¸ùEúÉìi J!i_f`iÚÔQ!`0dOä¹ã÷ŠÌ•€"`ÛÊ2¯ð¨„g‘›YkFusŠTæd§šQ¡¸šÿÐŽ’€oת. uë5)L:$qFªÛhaòê¹¥T.ª"9Óê IDATrù´ü´ð\Yz“†§¢‹¼I¦VrŸeÎ¥ˆùR42Í”"~&‹.ˆéòéûí¿þëoOžÏ HL+9nÁàsð§{ÿìàê‘ûÇ#O÷'-àæV8zµ)ÒŠ½2f»).%$- ç€ù‘9Ž ŽBØüÎÔÏÐ=´É÷ýV®†f[ç66@F83†Õc¿±1È¿÷Âúúú¹an„‡£~6ùAóÚÅnÒNŒeMFB~eÀ2ȉèçÕÀâÌO‰ñ²È–¡A1 š±™7j(li.€"žAas3L%%ŽÉxÀÌåd™öÐ[ÜÛEnv×úÀïB?rk}æêIÀÒBÝÀdù×ÆÆ úm%’”©^Üã&)%ëåáÛåg²c|vl‹Õ w!΄úÍÔ.KÝA&0$œ‚6è×Rk¿–v ñµAš— Åí4†S(ÛÕ‹¢´³ä¢…º ÆµµíðŒm'¶>ó+»< 9ží39Ôð‹ü³ sÚÚÓ96îéÑh´ïÀÚ!øß±Î¤B¬9ÞD–‹&PWÌÕҨײpÒÈ$‘ý'p¬åÙÌf Þn©<œõ}ß-êØ÷±Ù -¸÷ç¸B2wˆm;Aø½|f#Ÿ¼ÃQÿÂú ÷ÁÃ3à%ô“WÒ¥Ì.M&À1Ÿò\Ï·ÀMGµ9óbÂÑ[%ƒÄ¥âE*@Åky>®I§ÊVi&Â4iÓ¼eª%²±nò•·Þ0q³ ³8ï)· ,çU?—öØ)Â#dŠ)YA¢Ä£œ m¾•gCe•ŒâYääɮ̋ ƒ_‡æA8`RYÎ~'pâfÔÊ*Qç©Ê¡ý_`MESN“çœKkJ'9käbi£? 7' Ò’Bµ\F:Äd¯¬ÿ6²¿1!bâ$æt^­ó(Ýa÷ê+9~âÈÚÚêèÈš±â¡2‰Ôz ¼Ü,LÛ£u ÄbUmµèl‘êæBŸÛ\ åÇuÁ³·ÛZ°bËÅÒwûK±©¯ÒVßξ<<çÀ%‘äÅ3ùÌ=7^ºþÌúYGÖ‡ÃáF?©º×~оVM:õäúë‹å¶H`.¾ eGÆl6Ɉæ P[ï«ipcr÷x‘Ù<>a"“cr,§ŸY¯•-€ %8— 7 ÷°l±ó­ö ÷Íä_\탃 ˜ d @{ ±•p€UE†# –‡q%™™<Ï#ú6mP‡Û"Ût ùÄç»í ø´, ™1ëîs”ÔÙj"¯À¯š_,÷"Íñ½Õt=b“`ŽFЬbCe5.gIvÞPØÑŸW«ålË+àr‹¹»ðÊÅÎ]tÓúÈê>w!W€º÷éý+k+++ƒžuÖ#QŽAýG0^‰,‘q§^ì•Y‹nÍE`¶êÉ™=óV°Yÿý~û³}lûÑYwî…áÙs.7Â/¯o¼|æEœºëëƒ lµ:svðòp}p‰°Ÿ]zµ¹Tù %Īç3q±:‚8ûD¬ËÃ…Ê`t)cU­è1 g¢ø<ªÿˆ‰`æÃA>"(ˆZÞCxK¥Rðƒê¹‡§àó>W¯½"'òx48Ôçc¾`Oœ‹Þ® áèÍŒ˜’…)q?jcþ«W14AïÛŠI7½£ð¼“‰$b¨n휖۽XòhåÉWæã$¯«VãâŽ/ù[¬›Š"=.e¥!–°§q2.<½h §,-@­¶8XøtwéÒÂM/L»­© ƒOïuί5îð#+«Gr¸2æƒdM8'¥ÒnJíWkl€/Wiͼ¹“ŠóÆOó®Y /1ŠÅG _Ž¿Áf‘à¢ë×Ç/¾8<ûâ†sãsç^~ñÅ3/¾¼1Œ^X?ƒº9_ȿܜäðì—^m_›¢ ÑŽð ŸÖȯù__.¹ 1QU+¢Í4 —biŽ)0ëÍZ2ª'L„E›ôA Aw[ ±Ná“mPK\Tƒj¥K¹ñ^í Ty¬Íä6t%=÷Ò„€švqèJúS­ŸÆ\Æ`úësÉס̋V‚Ùê6«H « þk¹>ÎFdQxu I•–Û°ÅÀK‡¥öˆ}uÇ9ª?¦jä+dûýL8¢%LÒG%ÌóÙ “&ÎÉæËÂè¤AwîÒbËUS?[$78üÔ~‡ø;xèàSŸÞ¿²ïS+ã6ÈÙ©,7Ĩ<©ÿˆ¥Ï–ÐË'ÚcØ&"B޽¹zŽœ—üý &lýÙú—úпøâÆð%0aF9ÿ 6ΞyéìÆèÜàÌË/œ}9—PÀœûò¼þBî“×ûW·.U‹Ùdƶ—P7Zœ…°žY“¿Zª%{GKµñ`P{ª]²„•ÐRqJð²dö¶Lö !Vl°$tÑ6+jÂ8Üoâ l˜YN„{é›Ôüôc7<ÔGñ2jNóaˆJtÎ\Ȥ¸i5IÒaú¤r@Û”J{ ̱!H×jÊZ"ö&2}‰´)ý>òiiÎD­1bá†zónâùÍ6µ3±ñiúaµ¦—£µ¢F0éHêLæô©M DŠ¥·û7yÃû}îoÝV.ÉÀÓÜ jŸ»X¯ÍÜ'ÿìO?yxÿÓŸŽ[íšEI–êhqˆ937Ó ­C2;· "[DÄ-Œ ÈÍB~ F.·Èg¿‹è{i£OýÆ?|o}ýÅÁ¹ñp0çxñwöÜ‹g_ ÓÜ.^XÏ'ð`ýÌú87º­Í­É€z·?_€¦•‹Ì$Xy»’בײÉ‹9rðEÝ®îi3&ÿÇ6²~“[‚pYÚ;¢o`[Ù&óþD@ìÑeà`H9OP@©©*-óûb;B¯ª ˜¶d†$ëXÔl$7ÐS%»´µ¡ e}‡¬NÉË¢u YPˆDö'QŽS®,à:hYdmÆT‘Ëo*½ [šÎ¦ÃM4Z™Û3–è3môiŒ×ˆ“ZoJÊKæ“Êÿ#a—oLþö¯ÝVw±›¹îÛÿ)ßc¿–ܧöï]9¼/ÿ¢öXWʱɲ`JF¶QrÔQS5/MòAÅ{4N I¹ ž7j…93¿ë_z©?»>ìÛþ»¹Ð{ñ…së5·±±ñòFn6^Ê!¸A3 ààÜFÁ³¹9×_ºÐ.&ì©y/ý5$DÔ¬&P­ÝÔÞ4J¢Øê9®ÉxÆýAÆ7U¤oHuÂíž‘Œ@}öhОMg>¦KņfãÂñ‡U¨v|L{ å[àhjØlIcCh’jOÍk%*o–òÖ~§ "‡–»ìP½ÍÙU¡Tȸ…©HZ•é{e"nzãFFkÌÛH°Im±’JÖrPäQTƒ†›7ÂMªÄY P^Õbæ¯îrÔÑý§ &qõE$ð[ßþ›ÎM§kû“}ƒ}îsƒœ¸93h!|]SX·7b¶K§V]kZ€™÷Þ(€LÈR³V!ƒßFŠX)§ÀqÿZ?ø‡ï½°±‘k½s熣Aޏs/mä¦c°®µ¦#ì꿇x0xq#gÈþµ‹óKq gœªÕfA¨™ÈÂøÂJ[¦@óòêÔŠÝaàjÃ|³7Ÿã–L„P,p-[Žós1åQP‰z·Ü…¶‡­«VC¨t‘[«Ô–’¦„~DKJävÊÑ`hCŠ••¬eqÐÕºw5Ùø†Õ%É×:ó"` ØÌÌ–^1–Ñ…D$màE›¤[æÀ *ÍŒM`;õ{àe‰™ÕvJy,üZ~剒խÎßV–,üŽëÄöLš^éä¨iFáÓ^г þÿeëݞ㺷ó@>krâ$Ή`hûaæe*UG¢DÉF\5S>¥‡²çèBݽw_Ð$¢{ÿ.ûÖ~vìñqR{昷ys%“ÄINŽ$ÄñýØN@ài2v¢¿cÖú¾µ¡£ÄD„K÷êuý.Ƀ'ÿ‹¦À“¥4‚?L>nöR€á­··þ‡½¾|úkû m’]'¹ÇNÜ/½_ma`É’ÌjØ`Ýk­ •Æ™˜4^Ú ÒA«ïK~6Hb¥JæIGÃ=)¿ƒt´—ªŒ€LʼnÖåö ™A$’EÒöl½:\ SÙ"ÎAï_š¨/h "Gj½Zi³sÄp7´7÷sĸï"–T^+ôA¬é7eL H¦Hò¶ŒQZ¡}f …ÞÅ´bDÞ `_J2L$‹îÂ8gÒ5˜B`ÑPíu;Œ; 8Ù"(é±ìTü¨6 ³kErøø4q@>«JVfùÑiöå·SøÙiÊ¥õ9‡%œ© Іz mQVÍÈÅ×±­³=— “‡øñƒ¤®–¯ëõ:ùûIòZpëú{ hl¨ „ðÒf-tŒåŽM†lÂßxñ],\GÊ$A K)¿í¨MÚ¢M¿øì‹/Ž$ü2=ïKý•hìÓÒ¯¿O„¾tÚÊ ¼—HÜbéõÎ4- -®îÁánlã¡-¥è\qËÒùŒ?tÈU}¡H©f*éVªq=Í=^ž‹öoÌS%,A§Â—ã°a—mÀ ¯Òs:ߊ m|»ìi:è=ï×:¦B%-§øÏÍ\Œ¯‰ nŸù|çyžüý_IäÇÔãl’äKI€M¹ä·Ô§…5Ðr×´I¼¡r(m“ãfK£ Ë—#â6»+¬ŠµMYa2`¹nÛ] < Á~Û>ýüéHÇÝÝtIÐõ5çíJî&{’¥g*¼¬Pªôè961‡¤™TE ®ªÆV=MY—¹êUu,FãN9H¼Ò›&zB®HoÆAñŒªoü°ÜÄÚ¸“9­8ô¹«¼‘3ÊP#,uî¿…£8 &mA£(¸‹ä<Ì´ "ŽÊ1²¬z*üpvEK¯uÜ Š$ÑæX›„Pt£pDÖ-aKSM( =/IŒa]¡X>‚®¬1‹è£ÙQàp8.¹”©¡¶¡¼Ð:./ÒÅ« %Î!Tòh˜ií×L„×q‚– øøÑc½¡žŸ+áôô¤X,\ä;«Da±Þœò²‚&7f¹M» Ǧ¬‡åK—BüÒp2ðõÅ*Ù¯&,„¦ŒCéòvÛþó¶í÷³Ïžf»™J6î·»{’SÉ}}M}i¶›Ê’1wû»ÃAw_’'þo°ˆÑ$ËaGBpUv-A®ŒRÚJHàQlÄ-h¸àBÏN §N1$;»ïˆµ9^Øá­¡É:Q`èúÀuô-£áäHÁÛ±Ò± 6+"p«V÷tu •f#i/AÎoe6kBzÆ‘ã]x“–Ô§½4€>Vu )EÇßáúL²(ÆóŒ¶gz¢iHa˜e[ÈÜ{Éwâ)„ß°……á #ZV%CÁ G,Š‹ †ì Iƒ†S,àãŸ<9lÖͪv§''‹JP2áÎZÒ Yn¦CèϹ³]šJ ‰³œ‰#^ïÝèH,1'8Kme¼t5Ù- šÅÃmû)@·}öT!Ï»ÒÚIX¥™Ê‹JîííK\JêÛígû£ªgG€º£Iöõ‚j :ЭviÖ\«'‘PX$-!2â)zÍŸ€‡Kmõ{=ß[΀DÈ5ƒ{*ž/¿+Ö–›0…ö4GVw©€}ªôq‹ü »ßÞ’màéæa»ŠàŠ„f†ÙGéŸx Ö«ß2(ôqó³-dáy’S XI³ŸH¤V`TÒ‘ ÇʪáÖA1¾IS[œ·,MxÈdfÏ€Ÿ“+A\Xª(\ÓOàðk…U²?Ãp•É£!glHæDbè›äñÇ>yx˜4MÔøsk Š$îè,ì Ìâ ’ŽÀ[¢%_býg Áêq„³nGK°ÚIþ ±54´9*HÄ”ThÃXµ-h•m¿ý€Yzô¼/so"µUÁýTâLº>@)ÓY¶/©)P~#å÷™äIÍ€]6+Œ8= çh]gkâÀâ]²Û3ªwwî¸íÒˆq RõnŸubmØIS‹\¡L¨DZV*²wxÿÒÇù·d¼5á–æèCgìg)F—vœÃJõ¤æú§¢°} ¸¡Ý|;¾²ŠhÄ@Í®ãzºTç_}”üðÑãd--ZòR²`8üŸÿ¾4¹òﺿeÇ ´<@Ábθ‡?¦= ûp-n€',ÊÆ„Êê/’š1øU‚0@ moøìh”êze7Ñ‚+sÈÞ@B.ë÷ww³þ¾Þ^÷8 ÏçòKÖ6¼,c­ÃõN æÆâŽyn& 8.eO2¦¾°²-Ÿ÷z·{;½*Ÿf~:uSßY9ÙNúça Z]‰aá84v+n±`q¥“S¡ `*J('ZŸl,r6rݪÙS/åkÉuàX’¶‰"Õ- Y IQh ¥¨0“‘ÚNqzãõž‰Óx‡ƒÐÔ u¡@a”ß®!Lµ8ó|0„jǃg)ØE‡äš/L ¿’ÃDÆß•„ÛùùºZ%ù&Iâáÿú«‡Ò5›dÂ~œÿó…f€p¦þÚ¬¬5GEÒ @#DÓ±Ã× 2sïäèþV<Ýj^+'³®×!(*«}ž¦»IoÔÒf²¿·;PýèVÞÙSªH?ÝÏöÛ‘^‚÷†*Ÿ ‡>cWŠiʲ¡V &Ü%‡"Ä¢/r×}ƒžD8%^míôvvvü4›N*ŸËÔ[óØýÝ Âœ&(j§¾6¿ÇàÑ[Ý¥”$Ð@o »¬ùoçalyÈ…wvš¼Ð¼Xy®9Rœ«õŽÀLĦ޺3½ÌŠUc7„LˆlDÅ« LÂ&z5HÚ8Á©5¶¶?´¢~œ|¡bE&JDq׋¸ã×£¤é›ž®#˜‚ÀkqÙé¢x @i½BžlÖ’(’:Y¯ÕÊQÞk†˜ß¾_DØbz`†¼Äwšâ<–è?MÄÇÚ ½ˆUdƒÔFÊÔ0¡>Öz­—³º‘V[±ùé³çƒLÚ»öœ‹@‰ ö%÷û»{’÷²T~mv5öÒ¡æÁ–ÐSÒë  Ha Ø’·4RÐ1{î]|çþäÜ´·µu§ÚÙÉFà4MÇ“tD`£û¯TËQP/u7up.c@Б¡ø?oÇ[Õ6‹]ãX‚IõM…#wÌ6ºáGE ýÎd:ì:ªçÁ£¤ žY9O€Å/+KSš"«ì,wU6:hÓ¤6\×”d¥S¡­0\—ÖÔ@>‚ÖfÓu!d¹°u~ªÄ8:MQÔöZõ al¢PI¬S«º_s*ÐL¥À‚ð²ÜtȈЯ]žHæHdRL$ –'q•'pGÂ3£«³×:æÜÉ,]'ÞT‚#ËuZЄâs:Át\„I ºÁ†Xä‘ D²Öš„‘•‘ø|ût¦i?ÙOû€=C¤£¯`|i%¢'íÞs™UöFÑŠüT¶é¦$Gi¨ÀZ Iº‰Ì­—‡v³~%’€Îò|ê§!{kçí»’³Ì>Êò£{i–eºRß„¹ˆÑDú‘„×ý'€‚&Åî–¿‰ÀÈS+}Û} ®€ä¨¬¡“c 2Æ3æ‰ê§”º»œ6@w OŽF¦n¹M gâËÃGbà«T°Z儦°‹hÕC3NkTÒ è¢0hƒ@…Ò8æM ‰;õ`(wêãkÇÄ rŸ3|MA,Â-ÁûuR,¹b‰¿—/]R½~­h–Í(Á P]±€y!'‡O ViðíàÌæhðÀã•+q‡éee‹BU´5[ñb¦>"Žä[“1äù³Áp$)ï°jÎW)Àûý~ãݶML?ËdIÚ#iwQƒû­ÎÑšfñ7yqkI°Úµ{ ­ôÁ¡‡¶È›\Ëm˜NS©¼;Û¾× “4OCö‘ŸÈ·0U'¤å⻃pg§M¾§%dv¨IÒä-ný Kfð€îše¬Iõé]¶Êy² $‹§¹´Ü¤Ã&H ù\ Cyâs¢{¬r2F†Îö€TÃ0©TŒ° ST+#B"lÏuƒ#!DLy$ãR#˜ÜhÅÑ [¦’D: .lµG;êÂDz}Å ~.™›.ئ½p=*’“óýuR/N_¾vµª‰¿zñ:H å g7p Kª¶• ¾5ö˜|9Ú1Ęrw¢Óåæ$S %mSsf]᫼ÚÕ<{ö,Žöö“Ýåáú¼nÎ÷v÷åo5|ÙMöÚL‡TÚÄ~–È’*ë(ÙK¤\kä”®­å ‘Ž‹ v›e —¶‡F_.²¬(³tÚŒ';îí;áöV:”ˆžN?Œ“÷?L'YîÌb­gå.3–û< Wpœ×¶zº8%•ßnoÈÉÝ~L¢°*ô|—ÔëÂFƒË[}‚óh—&ZTê÷Ïý‹Frá8 –v#@ûhlƱO¶†.PDK^MÍ£0tsÙÓ{KŸÚ"§KRAØ ê,@lt6É"á´B}äý fT¤ä @sM9\æRƒíœ–àýóUO_¾P>œDÅþ‰K öÑŠ ò4 A„-¬§DH°è€œM€Ñçõ-paåRÝŠ¢´5.¨µ1|¨¢šâž Þ¥ƒáîð¹t|»ÒØžqµ‘ADêq›””´2„¤í¡k%Cê"%9㼂ìÞÊ4pu ÁÉ_zhUÙ(N;±%m %³2N'ÏGÅx–?¸'%˜ùw?ªîÝÏ| g_¸‚e¹ÏnXr UÐä‘úÛ•Õª[¶‹³œb$Ögd†@œ5d"¶~ælvñÏ1³Ú IDATD¡:”z‰èñ@µ…–\¦±*°”¿VÂlœ nÊ Î¢k¸e2²ÝcpÇe,):¶èÜ-8ÇŒM¿-–|]±YÕ©À Åttñ”U‹Jâïñ“'ûçIqzúâå"ÙÔU<Ù—^°^';INª‡ï¤‡LyœB…ß>¶ŽL'Œ…d®aЕý *ùDqá¢D5UŒÚ=ìí°?ØUj{xªfÕfÕ¤Zm¥-¤ŠÑoe6Yº¼M÷ÚöùHšC VÓ¶4šçÊä•îá©@iLÌÇóx¾„â˜:þH ÌÒz<žL«òÝ>Ì3/åßý½ìÃìÝûwîŽKøåÒM¥XçÙ´cÉq;‹¦M‡Ic¹ JÊÎ,ó¡öáxr¢-ÍŒtÖgxÄdØö6áÐQÒßC£IŠÚ’ÆmޱÎÕ®ð°ÁFµá¶$Þ¤kÓ°M)CM±,‰9óCI¿â𨠸‘Ü^G¹ËˆÑ% |‰Í9hÈ\1ÊRySkl¸Ú X,—Ô¤ŒŽÂDÞ,(x7‘Ï¡øøðq’ÔªúU$›¦zý"&Éj½IvT\4vÚ.Ì ‡D[èËÁ‘£É¿n8ÐÓ@‚LIçZK¬‹`Uܵ(êà WôÆ=oÙh0’Pk%ÈëÍz#ÿ㹄ãîîó£T*­”f½ß—‡‡mÚ†öéQo” ööû­«ˆƒA%®õ5±Ô€,¨‘ÄB0(7Š—ü”ãI9§1›úòCÉ€Ùh<šfùî½ûòx8 X\ɆR}'S]·•‰P§ò ]hq/½,oq>EpÈ×™Ÿ`y=ÏôQ:›/$!ʳµXŒ¸§Ô‡pÔ‰à¨EÚYF*Ãõ°ñTgÆ.“@M¦‡#Ý¡ùˆv!á%OõY¼£–†‘2yŽÑ‘ò×äü¡W‰7REîKZz0‹)H]­vb&Ë›¡™¦ù‚~ÄA+ðÈRžÃ´L¯É_¼pºšVO½ÄÛÂø>GÖ¯txÓŽ$£R1N¿@nÜLýZÕŠÇŽîì[k·Aå#\æT¼q—nŸ?ýbÐ>¶GÙ^zÔú¶,šóMB½‘I¸e–ÊSW çú\õCZ©Ž­´2ë9¸•¬Û” (ð+t¨Æ ×¾šJmMû Z@j‰H@†ÙÑ8Í¢ä¶÷î»<ËÞ_æ’ïÝ»_.ÿZ¸Q:OG™|Ü´cÉy;{ê¿+SÝ2·lIWð6ÏãÙñ±÷ÓT‡á\>.0g3¬kÇî-c©Yg³ã N¨kO¡Ý#oPpÛgÆ’Xž€ŽÜ…=¨G]Ÿ®§aéIu¯’ Æcã±®$·49à¤+µ 0˜Ã‰Ä$¤aê½Ã`ƒÄœàeÍâGª Ä RÕƒ­v°JÉ bbòäÉc™ƒ×ëÕù¹<ÙÉyø«êóDÿ\TX:w(üHäÒ…‰h–œƒûJ’¹XøV˜qA¿„T84É´ bŠZ•ðr»™cÚO³£´}:h5ùí}ÚºeR­‹rSDÕ3Ú´ý£Q_©‰Œ#‰ ‡Ä&µÏw³Ýd4LUY@C —Ëo™_H?n(Ò»K©|xíGŸ¼è¦’eÜ•˜+ßÿྯ²ðÁ‡…ûàƒû÷õ™.b¦Ùdt4M?x_²¤±äx€¤R)„p— ê•·L¡]Ê|þ:•_&òôOFÓ“àf“É„ÂÔ‰ú‚äa<žN}B)G:ÍQàK¹´¦çY‰º˜éh´­Û(ÊffÂ÷‚1ØM R“HÉf6À ÄÎŒÁñLí‘Èsc[Bû§Ä© ~ä® ”ÿ³ª¼m{‰z)ب@áZŽèí^X!ðѓǺŠnÜò\Þ’×§Aê± ’‰”愇ŒÛÌ¯áø‹òÈÔi"Ô‹ö„¡á.XUê+Ñ«‚g2Ón fÅùϳImýô¨}~Ô†¼måÛn%¢b}¾ÒÁmÓ>}úôh Z]š®å'¨‚íÓLb/MÊ/ƒޝ±X¨M­|E”`­W*À¬Lç6V¦eöƒîϦ2uèX첃"Üûð>ˆàzÓщßé|rï¨Ì>I’4–œ™ûa!]A~á”%§Ð!ÀEM²XŒÇÅét:P@Q:›ù±ä;¯‘¨Ül>—`œÄU§þt ÃhÂèùˆ¬‚=oÓV$“×X}®hWr*Å€NyTJ§Vfh¸*Võž‘QdÑÖé%ÆyÜäÌhO-P«Xãè?Z«»7š‘Ö¢2& «1XpS”{ËQP»AW'øñ#ÉtµtLçÕê|k˜dýúõZS`‚3=çô%SsiR`P:ô˜®€ôawPVUzÅv¬lЦ“„Ñ긂•7ÐÊù0æ­÷çiëóVd Ȳì\K_È÷6:Òt?ŽÇc l‹D©¼’ýñ,]H;êÒ´ë°õ e”“ÒìW‹PC‡£¢&B a77ŸvDÄik@iˆ‚œ7›Š¦fr€à†dàTs¯) .U8¼ë(žó«ƒ'2²7U.eF•7R­vŸ¹H òS$‘ˆ³5Ø’šAÉ“‡?J44Ö«Õ²9|ð+‡ñµKN_äçÉ#‰L=­Ñc9g.o»Mèã ±qË"ßÐ1@p’W0g­©Ò a|€l§÷Š&/ƒ¥ŒÊY[úv/%ûª"µY—E›>{ªüÝ]L!ÉéYîuEÔ>IÌúùXg$½Î¦r õÚœ\¡KjÀDÝÊo:{^Ifï¾÷a|ÿ¾ïõzÎmßîmÝÙáåרúnÚd÷ïùÞõ™àfãÏ((C·9·d"ñ·f¨–›éZin«b3›Ç2•KÈÈ6p£€HÔÞݽRðÃ( “QæVãÈ~M«+¯ {b†©êY^ÌG*|Á>:¨ËÙg]\¾äˆŠô•£ÐRuamÈ\'3ÜÁk H‘w"÷ôA¬,— @Õ¨¨0õxUc•2lüH Pñæxç jdÉ3@òødÀäü¼©NOÜêüðð°^¾Ì%"×uòðÑ“Dï…Þ¡róìä °à i:o&5¨‹vÕiThµ’^_fà­ÑI nl ZÙ5Ô 'IpÐòZ/©0ëïí&íùFÅíÓg}uGÚÝWºp+­Âù!&E׎T7+Ù$­ã‰Z\&C3:­ý«õ€ABÈÈ«Æ9ö1ò5Ë>üèÞ‡ÀÜmݹ}w«îåËÞwYr‹"Ü7û0û{1 ól)íÏ÷úž‘8F,j)_·¦ò"Ü4“9a*a&CÎ86ãqŠŒ/=_(kyJ&¾NH6a2ž…ÉÌ4i)Iþ9¢‹G ^0ÌKsá ›¿AÐ ×#Ä£Òμ↊úTU ƒè_Ab)WPÅ0д‚³ÞfÙ>ÝÝí'é kÉæ’_:Š:̃@¢Í8DšSú†èv¢*x B°öïÞÿƒz[þ»·ïÜÙVPL^]Æ‚²î¿?pÙt$É*æçvÏíÜéNn%71’n5ëºÜ,'ǶŠÙHü É€Cmå¤>7 ‘‰e9“Gr"Uq: iŠÐ¾ s¸LÛ9-ð–WN7$_oÊ I@¥ñÛhÍÐñÓ 2: «ÀÏ„jÑY_—íFŽàlïL°¬>ÞÐæhòàqzQo„þ¿’[‘Bï(v’3Œ5›E’³’G?~òà‰LËÓ“\uíNN¶€O=|œ°¤qckB!SènCBr„÷!Ȩf˜Ä½È/D¢®`¤¥‘;Amí š›øîb ˆéÕP2^ª¬_Å¿4›fÕ†ý=xƒÈ¢ðôu¾ÅéwPUÊdb.\¾{ª¿&)ðÝ{¿bÏ[½JaÑÒÞñ2"KÈ©âþ½{fÓéûïË ,õ‹Ñ€nlH4Uݪ›Ùé\m^šxýìõì´i²4Óæ\zÍ:V…&BDÇtü¢˜O¥ŽM§2.k™Æm-VQ3ˆ°äðk§   HH–~\4|øæc# Ò%T·¬ÉÁ嬴ª^`µÃîªD½$[¡Œ7xÔH¦=V`nL`57œÂV:¥7r'4ˆÁûÄçÉÿÅ£zòè‡Ož×EpAI& ^€ËÓ(àRÑ7FÞ‹| ÇàiaÓ.ÕøóÁ`8Žv%çí·›bÝ}z”î õ·ý >§UuHÆ“ŽÁý~Òµh!·§_ÍÊp5Äe'ϺjÖ:SΓ¢¾÷˺TÛ¹}ûÎííí^okkkg;þ¼}œ~þû÷?øÀû% éóÀ~1Ú>‚æó’+n•›c‰¿ã¶¨ŸÃ㘦/õE[û€"ëC=¯u‘U-§™<^ǯói%a[ä3ýw/<ƒÈ£^›ÿ ý?˜ ¸‘ <š•MÁ*pÔ•§­Êàêß+°Þ!Ã…>“®Õ CX’™É¢/"?W¿Ü«àó2€™žðšKŠ Æ°´hð’‚ÀÉáÃ>~ü€spé^/ ]I'›êô¥“|ðàQbàR´ÕÀÕ"¼K²@‰ÈÅ‘ëÕÚcÁ´hhLͲ0åg5SÌÆØ»JÉ;G*Úxc`ë…«Íž®Îè*-¿îk –`”øSÓ†¬ÝÉ\z(%µƒ#•ÐJGmN—y‚M…uõª¡? °¸Å•fJ¢¿ø0œêœ~ðKQÑÐùÎNo§¿³³uûnèe äâ.Hîxo2—éÖ? _ =)ÝT>À6Wzí[ÅTâo>›[o/Útëñ$näC6~Üaì*ç¥òúq*Ñ5—‡s2©ÆÇ•&çrÉûËhÑA˜È*)ÈÓ¤D%瑞ÆpôQ/‹oé¼úÔœäÐQS([ Ô#@\c´Ž+wÑ4¸ÃÜO1hìþƒ­±¯ÐÔ±¥Bðc H“2,ñ ¼Þ¹©–<ùä“Ç$ JVáôäåYpíNå½G|¢Œ«7 ®‚àŸhãá…PF)\ª&xSS¿ì +C§T AàÌQ¢0TúÃ.Uè-o?}ÖÏTZW.¤lŸö4MöÕ»U©rR™ON‡$Ú¶ÏúûRœÓ–—1]…4fVÓ’¹ʽ¦!Í´ØôCqïÂýäÿÞ ~GKð;[wwvv·3ð[ô ¾Êè”ßÞ¿?õÙ=‘{[±ë%vㆅ[›àü?Ï»›Ay<ž5“™´}“qqœž¦àôòËt0YÒÒ}2Î4.)‰;ÿ_%hÒ&3IÌ\=Æ º E·£ Õž†›ET¯\á$h¢ŒÕj# ìôP¨/HК”"…äè *¹Ž°®œxß¡‘[vÚúXMFÓïg seÐ%Láƒôè㇇Ÿ¨IœÌ½ùÉ‹—¯“'Éùº^œžÊ{øÉƒ‡ÉkàÀóÜîÙàii)óEŽ«¤B À÷7v} ‡ *—"¤_"Kê„Uæ$3=#-«m¬ôYšB PXŠ>H£lÔ%û}AvÕ?îüâsA7éîÞ°¥T{¤Gå ì;½€N­`ÓK¤Í ë•V| 0 3ÈåÕ¹ì…w¶Ý»½íÝ|{61W„ܘÖbÉ Ùt<˜L§y/w[=ßõ‹ØŠÌ§ÏÖ­Qª p2ŸW)h›Í´HÓ¢9ž³É<•"[IŸ:7›æ~r<Ìã A#ŸÞ;o áÂw‚¬‘ ±sY°™„×9V“çå'q+ÅC| äTõ|EQpˆÀiÃà%ôù ¸0E-È¥¹rXÅ;™#›)R¬ŸÈá[GåT£9›©‰TàÃøøÑ¡´}Ë/$ìž$›u¡SÈ“‡|ü(1–'·.-^+Kð˜{±Bå§å±<{:`®€B(Ì¢q§Q¸B>ÒVPŸþ˜ÿ5oN£·õý§ƒÁ Ý5!¬¤­êö³Ïž¥’èúIÖîõw‡‰óõ!áñí ¿;R™J“þ³]$¿îŽq .Ã1eDÿ´¢H•YŽªV½ü­wîö\o»Óë5VXèæaš¾Ÿ 'ÞËòÝ~‘mŒý­Íðx¾B’ÎëyÇÙæäxþ_F›M|’ôo8•þ/“œ½ŸAh(OÇøÜÞÇ·äþ¶BoÏ ‹ŠÃ-˜ÒÝ<Û¼’¼‚jØ–¥ç²Åu¡¢¨¯M`¥é 2feeÒ šÉR_pêgÑŸ­v,ÎÁ˜•|Mï™ %°Í)Лؒq´¨£$/³eÔ|ò«?|ôèp¿ ‹S̾ªÀ—Ô1høñÃÄ›u6 Ëe¨Ácåϧƒ½E‚w$,Ðös/\ =JãÕÒ¨!ëÕÊçÿè¿yËq/nO%â†{g»L€*¡:H³þH‰è€ªÌñJj0AÚ£lئØ ¤¯è”„ÛóŠ÷n7-#øx )“Îä^A°÷*OäÞýè£ÌËœáIðË#!˹˜¹Ñx˜ŽÎÂbg§ü¶_Œ½L‚øš½5ÓðûfžÁÌÐûm6­ç“êxþÍàól2™ž$Iïnoúád’I’ðlV)Áq4ÈUD©)×S‘DØ0ƒ?‚ïYx°ÖP£7m„À•3¶üOè×yèE0Kc¢»¾Ju¼*DE<†Û@-.®W 3 2$ o}i\ÔP/dÙlõW€®„å¸-¿Ñ±!R—7‹m‚ ©!”“èkQµù•HBùUóê —?NÁeEºº‚¦×dWFw$3ÉA”K°{÷É…îvÐŒ`¦„õIz8>’vÇÅŸï{E´n)†[:Ï¿8šÏá+W’&&ãñFfãoþê³l“)¢×»=›8ù„1ŽGÙËéTOj>}žN)¾æ$IéºÒDƒ¬0Ü¡šVÛ¡jT­·†ÈŠž¥…@íLí!p|ÌËt—†ðföÐ%xAb¤@$6l:hÆÅñ^èñfé ¥_@q€{Ð>/’ïI4#¬+éï‰û“Î þª྄]"ExYK ¸/øø«ep‡UY¯Ï#ç.Ìï¥5z•QèÈ&X?)z¿Á ÉÃ/†ßˆøWEOK…hùü×ñö[oýÖoýº½){Cзg2€@õWmÕÒ]UˆQy¶v7é÷‡Iˆõ¡4d‡¯[É­úÛ€jª„ Š¡#ÐéQÉ‘ƒ n˜*ÒäÉL§pd2(V•÷îÇRaµ Ï* \š®DSi³i6 Ù`·^õÎöýbÜÖ"Lt;nÁ’GƒlαD1/Š(9ü'ÃçIòö÷ÿîßùÛãñ$L&>§q&ÿVîÉ…k”¢ša lî"!ѤÞ®âÆ—W@Ë`š@²ÂF§ S2âBH÷>P@{ f¦'Òë\ô”€×BÌ;å‚ W4a2š¶–é$Ç[M,È$‰äA0½¬ ÄAŸÈœ+Cðà~â^Ÿ.*©À›ýu-Áš¡cUT Þ‰ç5p¡ qpކƒ[A6ºn‡µdÖûñ· ð©ráÚªm³=…à“ä–ª­†ÍQú\}ºÖêó¼·ìÜáúU«(%˜B…2*T¨¹MGÀC3(I¸´s᩺2ê½·n–Œayß»OŠh5}{ mÏÔ&Q è0%(‹ªW¢_ ½íÈ×{M'"çéÓã9%'‘³éêx2˜‡Óñ(ùÅ·¿ß»{{:ݞͦ>Œ³E9›•㱋³ ¨Ñª®•5×0p#ˆu±¦Ê’n3¾¢QŽ-É kÀEBõŠ0Oçè× =ÉÐu È0‘-ãSA›ºk­g­ŠÔ·þ‰€¬Â$ uQ¨ƒäñ­. âãv³v[†àG?ùá'2„HØI<]6ÉFÁÑÒŸIz|ôñƒÇ Ív»CpqcT N+“E`ªˆfå 8vÔhúh[®“@ICÕcÀ2ÿßüßøßüíßþíß|ë7ø¾rÀ¤ë¨%%ᥩ”àõ!Xíß+öÔ>3I[•)×Ut¹>ô‡¯›M;8Ò ˜Y°Y·òä¡/Þ¦aêY½ªÖ®R=²³—  ï݇\O/)¿;^B¬·ìõòñp4O³ét¨‹£ž$Ê·ïÞíUu/àID{áoaË$¢—_>jyoŽÇÓùàxÓñIoçû·“ÉäÃE–J4dŒK'Ùk}®²1í8©5£,ˆ½‘×–"ÒHD2Ut<ާŽM8kt’¨%PY(ÝÑä+•­­–™ðƒÂn­Á]WÑ(ŸÆ¤ÑQ5{BbMª˜orGØÐQ‚Ch!¨8V¢Äq}Q @®¼.—“Ÿ *!Q^ˆô€›s‰Fž'’Û···wn¿“¦µOeðåN‘1ò9稴ª³aaR˜ð)×^ÄcBŸk1­ŒKvW—5rå™vÅ·˜ãóeŠYHƒuÉeJÀS\v‹”@4+ ,F}'êŽðØïv›>B )ÿ¢-`/j .Š¥O?üøñ£O>ù¡àºÉs ÁÕâµ È>y¨›h½Øº‹î»&@×?‹n=·óSä’<¦xyú“ *®zÅ)>uUóJ"_òÇ|{ëÇí[ön^”ô“¡ü¤ »µFàªÅ.°¯\ÌÃýdOaY±99<Û4{í® æT˜lW1™€µé„öQu³¤±+Ù !ézVR‚ ò`$Ç)B+ô¶¶nû»;Ûq>É>J‹_z¯Ì2è”Ú/}ˆ<Î Ú*Ýâä¯$þÂÙL÷k2€Gé|ú—óãÙf3×ÖîÝ­·oçÊqš*ß P˜Ž%åVp!¦”½,=ŸuÛkƒ÷M'2àØ83}ãT2RÆYG ä!zéã‡D¦_j£„äGáó.`©€Iuk’˽­¡Ž‘Âø•ríRñEÓ©÷¢¯R–®q<ÆDom<üøÁ©¹åéË—2–È{ÕâåKÅÂ<øD’`B=QÏ`a:Àƒ±`,G]ç%GžÿËocO>Sí‚›µÂ`a$!˜ç¿ýcý«•&ïýöó•ôjm[û£/¤÷÷ü)|X[-ËRhww“|qÈ\¼Z/6¯ÖÉ E†ÎÇ7d"¯1ø`**×J}Q G-µ¤.ð5¥—êLP²íÛ½ÅÖÎÝí­Åf’¹ì£÷>x¯Ê ÜnŠR‚ÕUžW8T‚¨Gã[ØÎe‘§f:•Gk¬Ëèù||ôÍlRÅ4Súþí·“ñ8ËŽÁJL&0Ê0˜Ïçê“ü§+tì» £ûpcB± È<¦O¶j h[á€Œá˜Ø-ìÂmžT5C¨;Ô(«öågu” IDATiúŒæÈ?t4ô^Ðøœ]Ëȉ| "(H"0ª:áTK~Æ¿¹´€<–ü6ëDO"áôåirøøáƒµC'GZ×WZeë”õ’ÆŽº|‰v×Ô‘¸6jª¯¡æ*3S ñJû }Á5Ëäù?æ[Ûþãî-‡¦æJmS…¤Ê¬{Øð€'½Þ§Ãýô¤>ÜK÷“ç{ɪ^VKù˜½#‰ÏN©K¡æÖí!ë÷c=he¸ÄuµÆ4Ò@¢ÜpdÁY.„ž“jqL½$¦ÞÎRþéÝ–þo¹ÕóÓã<ûè£wk<õ¹*èÊÀRvêò3®YÁ!$eò+‰±˜ű„d:OÓôeQwl—¥]ï ¤Œ €4Oj‚ )áì0y”žQ ¸—Ó|ôè“Ç À*"ïI6áåi.ï=|(ãÉ£„@_Ðáš(ŒNí¡ð}‚Ï<¿)-ôÐ|Æ ’¥ LÒ >ÚJq ñª*wj@D´' Îæò4Ûx;ˆ¿éd\KFD†‡N&ûcw|,__˰’«ýœTÉÀ53mhb·ƒ1~ˆ­| r8·|‡b0°¦QceCX‹L÷úçÜwf74BR/‡PÙj:Òm¡ i/±ÝMÄøÎ„°kd‚B:çÔE…ìB,ÌÖÛtqt_’<~üèp-…÷Ÿ®‹ ï=zøÉ¯>z”€mþ×¼Êã5Pqµ„³¥ÏKŸÙVª[]š\iÙCˆ2ãkß)ÃåÛüΫö(û¬ÝµY[šže%%8ö÷öN7Õz·Ÿ%Ï÷Õ;óyÚßka@RÒS"xÂÿk»¼@†f$Ä+ϯÍà;„ν#˜ÐÉ·`A–aY?ÍDµgòäôQ¯ËJSe° Їˆõ4ã¢ñÆË­‘8XÂÁ¡Õûòf‚.œmÐôªHçÏbF´bQ^ !`D…«R‡Ž޾ˆz&ÒÐA!†:覺ê4„3ú³ŸP¯ Jœ…ª-ÂO45ï¾Ì€|;”ØK™VþkN¶X8v¸?˜šŽš•éŸVØ=7&(´µkH“&Ôu²+$>-åV©J×>o?;ÊÚÝ/Z³˜C øô׎Òaªz1q³éïî'ûÏ÷Ÿ+Dº]Ñ€„Ÿªpˆ9ÌÀ ~¬$ ¯ ‚n7ê#Õ0qEߨq—wB}ú9À2oŒä]Ê»oïl½z½Í_fÒ¢Íï¿§{ç'*¦S.¤Õ›…p2M0„|3ŸÎç€zN¤ÈO7ŠÄŸOfÏ'µBž‹r1‚ZFœLÆ<œ Ï3mhB‰ cu¬±€.ctaI„hP^æù¿¢¥$¹ Hp Íî-P<¥04 µ®"ÓÕÅñ¯Ò¥k.¬¨èo°ˆ\À”l¿X5È)AJç:c,¡/hKiCHbªv¥õ’.‰´€‡>~ˆ¼'‰,yô%ZK(ȯº0¼9ÙêÕÖó?»‚[£Ât+Ës\_ @¯P€ërát³ÕhÑ"–ÃrÚS þ˜B–Z5<emû£–†[š·Víógé Ÿ©2LµiÎw“}éU.a*QUùžqì³»[ƒËÊHJµáajZŠ8ˆY•WXG£ºá*=pü(óé2¸^¯Ü–VÐM§§Çéxºr“©Ë±* NãNþ¿ñ8ÌféBžÞ|”y­U^#+¦Ñ0™(äYC`œ¡âž9úß/.JÞ/Hd$ÁW?Öö€6?à¶uq}}¡ÏÎDͼ±ìÈž ‰´ÞÀP&¿À5`iJøúÉ  @Ô«ã´lŒR\ÐúpwÉCéõ>¾äß óWM’à9r X±<Ó¾õÖ¯¿õ[¿þO¶|mRv™LU~HãnÈ¿@²‘¹yUµþ³ÖÜF9WíÄʸüÔ”„íàïÛ#©½ígíçí³4ݕѶms]hÛ£OŸ·£4“hk¥iØ$û»i’ªyWÛDÐ=èØÊ/°ƒhàÒÞQ@¬3Àߪ ‡›`MYCÏ=z¼‘v•?û.8ݺî¼]îlÏÆ³É`¼r³L¢Î)××â.ÆWìõäá~: ³[ó™ŒÀ2•ǰñµÌÅÙ7ÉŒ ÇxÚ&D©¸³iŠm|¸|®‰ ¹¼xê°òG!HüqI’¡ñgy”æ‹ Z8I”Òh”غ(Ç]ÝŠ˜Ä`¼à‰º$”õâzs-RÈÿRԬƒXI…`*@<µÙª£½"°áÊÖ¾*¾#ç}Hb?§Z°S §µÄYòàcEä7È{U²Ù(“L¾ùZBPJ&™ì¼Øþø­¿õ~̘sâB©(èõÄ‘G¾z£;_ ·†CpmÞ4Ê$lͪ¢âQjŠŠsƒÚöù…"û>m?´¿öôiö4ÍÔy¡‘¿W.hNŽÚçi;WJy›Çudi¶Ÿî©KR CøÅ*Á‘,0jâolŽé62 üCT••|BYyÇ£oBê²û÷âGïà«Rd8š¤éø(Ê`{œÇùÜ‹;y̤°ÇŠf:…pk>M%«X*S…;óq6;Ç“qF$FÝ£JÌ)vˆˆ|‰“™ñ htYQ•Â,S B Œ~TÎaASÑ…Dú½òâúüúúëX~u½¹(¨m õ1÷¼|Ä ¶ñ”Í•h•Ô°Ô_+pBÊ‚zÔ(Ã2º”Ñô£Y3‘—à€wáõÿ•[£”œX ÷P@ÃX‘äãÇ?—÷ôWÅÅë×Ë !(ò’lßúíß|ë­·ìdÙsÆh¢%] €cÕJEo*4|òW³* Ÿ–zeÊXÐþ ¹99ëP™KÉý4k”¥ýìh0jåƒ[TÛçÃöó´¦ísͺF”2\œïíîígý}ÀeW9s=ȽÕ^fÝeó¼·.Áh;Ä¥§:#ÕÌ £$¸NGÃ2+?üàÝJú¸ñêi6š8 º©Þm%õTˆ;-XE5ÔE<‘pŒNp¨5UmžG©|ÖIœ§éñàLê,›ÖÇÇ:’DÊ`ùôhv †|Ȧéx4È^EúyâêÆyä9¨M`™R¦ºB,°±ðC)ýú+Í’Óί¯.âÅ•„VpÝÚX5<ób ¬¾äª¯®¯Ï5™•Ô-}'s¬Õã$Ì%äMbpж!NÛ¨¡€ò•ŽtXDsÈ-&‘!ºýù¼'= Ú¢/—Ëp.Ip©¢l7÷ÚòOìh››ÄÂ2 öO¥Ó¾®>DJ’nCt—€txÅU&¦OœFãÒµßy£ÁpígPÍúlÔ†°­·mËõF…{[Åþ—´–ô O.uön,ÖAƒZS¤reÆqMçÖáuO§Ý96@ì÷ß«>(ŒœeÖ•ŒÆ“l¦#ƒ$1Tí`Âc¹ö„Úh¥ãq¼5?Ïçõ¬’WÅh!i³™ÏfÙ?ÈÆµ¤Î&žÊטó–KšT¿ôQãgªZ„ÁÛåÒî \+ã9cG:Ɔ›Ç××›õõõWòGŠ€W?‘¼’Ø*¾&’ÅRp±¾¾ˆ¶Nùêújƒ,X‰Õ|—¬cB°M^ í“ÁtaÀDØOµ‹dI9œdäP_xÝ%Žrô_å=ÚªjNIšv}<Ó¶o}{´E v`?ä”6†‡àc«Š‹èæœÜH¥¿Â<ºþìÆ2½¢—+¬¯,u…Öµ^ÿ6V=Õ”‚ÔäöÓQû£´ý4m±öê9æz 0z GzrBÝwò¢ê[ÚÞÆy8ß4KœÃ—(K)‹‚Á (%v1 ½45+6†NuàaîÐïßó@yJ•ìò?ðY¨îð~™H½}&Xä;»î­»;T—„6¾âÖÔI žÿÕ|s6Sˆ 6=óÙ|6gòŽŽÒi6Å…Â)FŸ8P ǃ‰™ºš›—)\!ÇÆÂFÔÀñ•·[ðŽÛ1yûúzµÙ¬¯¾üZ"îzsõæÍï¾Yo®®¿þúê\Šnaæ 4ËÅ×WWoV«õ•Ôîë«sÌ"A—…©_„o³w0¡ƒØD‹v«¦kÍ…dIÄ^Žu¤y“†¢1žö<ÊÓ$%Xrà·y¯2UW…³“mûsG[ QµHN¢SEcQ™"%NÁuÁ36|…¼S„­™kG¿%tmgðaRÛhjÒÃ@G ù§už‰±5·bJÛ˜ª3ÇX‡o¢ÿ­Á-J xÃF#Jøž¸e » Ïd¡ì;¿òþ‡÷J§`ée&™ÎîÏç¿6Ïݼ/ÁÑÛùžG›>§¯i1Qι¼ÿ2MoÉÄ;—¢=•Iy¦g}½üš4‹a$¡FŸ§µ@>fҕߥ³‘­F±`ñBî‰<”Ñr•ïï·ðDRæýõõúüüÍ›7_þä¼÷æÍ¿””Løµ¶‚PåÔ`¸øéõù•®\—~oÖÒ§\]w•˜Ûå Ëjl³y†“G‰§aÄ%Qy›‹åÂE»ÐDZ0¢fËS…[]”øóo5-f|N%7îGþÛ“-HÆ8ÄÁøó݃KB†‹`б"K¨·5µEš§Ë FÏ%í)o¹0§›"Ÿ2OB±ýs{ÓÀ<ÀÈ÷Ø÷Æ>-ï|”Ù"uÃ}ªÙDX‹[J.•ÀloïߟÆì2õý¼;-ùxüÅD‘z»>4wîÊ3¾m§)“qÜÈ·¸ñéÓáü8@R§àçé7Ÿ*ù/n¢b¯ »­â†~<£±"?#ÏÃ} Ïs0?^ÒΩJ[PuÜ€(¨Ü%tä¡QQJÕÝ›7?yó¦^K$¾YI@^}%Áuý•…ò_/¤ê^}- ìßJø©€èêÍÕµä¿ó ·1šÁt{\™Ân`øà)ÆM„ÞÖ&ÆjG$#`)Áƒ&‚žî`žê—9}að° ç- Lài‹æü͵*šà¬d&¡…ä q ’.唕VSM*‡b$®­ D¼4È_l;»%Rñ Ñi8k Ö¦¨dv1ÄËwpfý =µ†ªƒ0` ˜>VeŠXç@PWÆ_ÑoªÎ ¢“A V»ÉÞÎÝw¶wv$ß¾ó¾ÏéÝLfÔÇïm¿sG>xGZG ñ$=ãɬ–¸‹·¦Gó¹ÂŠñXo»’¾ËC9›Í³Ík,0ªh{˜£éEz—ñƾ!ǘûå?ØØüƒ€I]¢H^ Ũ„€ºêÔГÖG~-Vë7g[˜|åSJüU뫯¾üê+ùsUÙmÞ\ÉÛJr§~HTi¯¾èpîKð÷1MXdQž£dd•®Š9L¬]ïFU¹ìׇÀ,5í0Miý‰—ŽØ$ü{;OÛ ´åÎж´»¢ép¡© W º<ìž¼‡¨s›NŨ7Z $?zâ0l¹,ÚPÒ9¬ïn 9©Ö÷-–yïÌ]\\,|qЮ9ÐTâi¡Ž‰Nˆ ¢OÕŠÖ« ’X¥†bä8nöFŸH­Ù;w¶z··ÕƵç»ãw§™ætLJÛýíXìì„b“D+K:ŸdãÙq¨¥ëÅÎ`…âKçß Çç‡ÏžeÇ‘¤ÖOMóœªò.—ü 7¢œöVĤDSl)Î$˜e—áQÀ!ÓmøúêNZzòÓʯ¡ÒD¸ÒB¬›ùTWò€hÈIŒªüAÍøkÖš©á±,Uüó”²³G_РUÀ‰n=%Ïê”J°.·¤hN.B ®“ò4. ƒ•¿Ô©ì™B4׉\JÁSÛ®à&¬‹”xmöë• ]®›5ÌÖëó0ï²@Å[TBzÚâ³®êê@—C™Aa†ØÝa6ÅÇ6œʼ3ãî¿ÉÝÁi88ÛÄ‹ÿûÿ¼@”&E“`…„®£ÆŠ&꼉˜cD…|Ûp­v6ÁÑà4Á$CK|/Êß[woßÙ7³wï£ìƒ|œæ€öjî„¿¹Óûžà‡·ûIâcº‰£ÿ2?>ÙdcLÁTBU‹‰ÆÑ(,6“Ù ûô‹¡;&ͨ¿3@ÉfÝ•[³Á'_—(žÞQŒ—ÆÜ Ý•†Š WM*H÷æ/4ëµ”Ù R.ü…¤½B“â›Ë¸<9-"Ò¥<[26±ÏÂWƒÒLrˆÔ‡’¹OáØ e ³Ë½! ³©ƒnAîu<}™ÜÀ=v‡hº;¿-Ê›ÁŒO-Ä›#“Y?¥\O:ž†´Zþ— _¯*SàÕ~1¢â¤õªS¨ZS¢TÝU‡œ’àT·T?vȹ9öa6;o°sÅ9ðoÆŸü_§•ÄÝÁÅÿñ]œgM}PÍAU£­j¬æ¢ÔÕŒ^C°µh@\⋤ò6,%j0T÷zåÎÎö;·ï¾ã¶z¡Üzÿ~6™ #oÞœy­ÄE%àÕÅõêúâ«7ò\JøÉkþdéb%ï+›vu~õo¿ñ\¢LïEc*˜žn Ž5° BN°C0M rF¾RH4ÕªT2¤Ë0Õ1uäÊGó&I›³ä;rƒÎ ŽUz»É«¹šTСª¸Ù9—÷5VeŒZ’¹‚q¹¤,Ý´±ÐC<¢ÄmŽ)dÙ (¬æ1F}s®MJBH¡bÀaôÁùOVåAõå¿üòK—Wh›ƒUäÒ‹ø°”9ŸÏÿêSê—¬T<@‡z6ÓæCFlèàêž»pcùèAsÔ­tUÂþ7òBRAuÍ9éèàFKÆe,ëË7õ›…¼Ž%J!¾’I£9ÿêÍ¥+ß\^^úåâ…<{Õ¥<¼ªn»ºúÉO®/xРœŒJ•¬˜'„waQaN ½ôïÊFd -Áš’ý±ÔG¤0A…: Ä&è°~÷Ü€Dƒ"¯“€€.-G/è°ÏÄòTråZŸÈµ´uCõ§!¸ŠuC_$GàžSÁ«µ*±#,![T7º…ÁÖiÛåóÒö¬¥Uå(×ÀðÓgïà­ƒÂK,|,WÕä?MMQ¡³0¯:%&)PDVÈZQLá ,3°Âs¢ÛÞÙRêööí;·oïäÅ­_Ö–{8Á„·½½îܽSlo7ÛwÇûïüÝï¿$χ@q…î%|$ÎñMúk£ÁÀ)Ñc>ýâ?MÙ¢ëúvãéw«Yn:ÅÀáÐ*E8L†™ùµrH´¬$Ï<šìÖZ’¾¦d‰Ÿ¾y£g©ËKýq/—ҘȨQœ¿‘ŒÕ———‹E!ñ·\¼|!Oååe¡><¥ "ÿú'×ç8 #üjRñ؆¦_R˜W@$D†™M„Ï%Å>h¦\`º"zË˜Íøn2ž”;Œ„èZuɉ*FSR‘é:yõ'aá5uO+Ѥõk6*¾r.½•v1š¸tô8/%Ç$B0Ö•½©ØéWòÀI¨ b³8_0út~)¡£n:ÓÍ yسhë¿ÞâIZ¿Õ_UÁ×z‚‘ÿAG[O‘Ý=jzÅZ6êÔ2T’"ÒL1ð„^/¿{{kg§¿ÓƒLõ½-°˜²Ypã±Ìñ{½»¯;ÓÛw{ßû“Ñx(ðx"õáÖü?Í%èfz>st4Ùl‚‡fÛ`4‰¶<žrÎBîÕ vœ £›òÅ,ä”ZàÀŒ 1ùêÜÏÄ›·Â_(=Q0œ.Cqyy¹”±ûM™»æòÍUYKü½>ñ—úë‹^ïȗg'Aªôï^]ã ÒIDÓ˜F&#®y `4Û·`±GÇD³@âCX-ÕLÝ„>îE©Ô` üŽII ­Vé¹££ð ÞÈ J#äO_ýº4ÁNCk³Öü§Žç}çTæ“߮Υ¸­Ô7×Sl,Kÿ†J¢X Vºœ.¡_©§9x²YvvDz¥”Ÿ'¬µ90;Žg’¡CT¸õê ä¥dÁþpM ÿÐãÐŽYÊ«;p„vªœ 7ÝH-t=åBo{wgçîÖ;Z‚wŠz§¸Û òm¾Î&©"`îÞÝ’äïô¾'ÿš,n§w2NC ?L§€TÅ"`Å"ÈøyÂ(u Iýf2›o4›ãÉnʰ×MP LW°üL¾ó©YúÁ¨Sy׆~çóȶsñå—!h¾~™—>?)$%ÎâI.­^yqqyùêԇ˓—/_¼r——ò´Ÿ¼|±(u\–A˜˜„‚ò[;’(¢¶ Žà&JA×áÆ.b¹ª¬Ö’j»Sæ\Ò(2‹wCxÅ•F;Ô¹æ*F«fÎÔiêè¸Ô[~¥,–Ž@ñi ”àÒçvU(ßqmh»ºÜ”š6ëU‘©„jJ''SÒÚ —Ⲥ…©n£©Œ¯èëQ7*¿3{ôû]a5ˆ¾ÿçwÿíÁJþ çõAÙèg$Y_,Rlâ4µÙ W¼FRÇÓzY#¤o»ÝíÞÝ;aûØŒv¶²*öâÇ㻷˰ó·îÞ¹S­îÜyçöÎööv’ %8㙑 Ä.Å2Öβqy±(?ýÏs?Gìÿr¼¡Dpt2‚ãÒLúYÌ'”z`p´«§ŠÍh¸Œ.èTØ\­ÓñÅõõ—_J^ºg!^.^ºË³WNBñ•äÂ7_^ËÛ«üúú嫯__^æ‹…äÁWK_kø]­7ç××ç« 7ŒåŒcÎÆM[”Hbþ™¾Á”(Ù°0㘯¡êŠî¢d1‰sæBë+s³|¡c<F‰tjc#²ÚÇKþãg-)dã׆…”$ù ;VŒT-Uÿ¤ÍHr†WÌm%Ï 9ñ{”w¡½…¦ —Œ2úzwuçRüÓöÏþ…Ä_Üœ8é+™C}Ý—­»I•Ž qÒÝ'yêpQZ1Ñ” [ðížëÝ}g뺧lª¸£ø©0ž¢ÿzçL"Ê—Ûþ›·ßÞº«LùÁfìU†mêÜ­ÙtŠú;ŸÎf“tJ­ããÙlúüÿ›£*ðè‹éä$Ö(îl¤®hß§µX~7›-l¯lQ]à˜ L¶ KÂ’¬ÝÏꘫû½Ëøâd/ó¹ÔÚ¥¼sâÊ˯®®ÿü/®O¯ÿâúÅ‹i_ŸJø½\ìl®äyY_saóÇueð‡Œ(޲z—ëdúq³=yi/‡]õ¤ÑÓDÈ›ñû’! 0C„°„-ÁG“©¹×ô©W¶/ Øè l­ì¶ )>(’ƒÂ«›.×*„†÷%íˆ IDAT›3)˜f1wVÔpVà hÃz)®p!6%Օ嬊/ÌÄò«¦>‰Ôæ@~JAk|q ŠxÖÒˆ ÊD«sye©wã`¬ÚP ÜΔóˆz§qd#úÌ{åK8fNC › ‰f²ýŽÙ‰<þÇÙ_êJb ’ø'\ÅﯲÁhœN3®)|ƒÀI±äž®2ˆWªbHj9½ ¯^žäÁË2sœIüòêúOö××ö×/O._¼~õR²ß"V•®±¸R04¶ §]:ÔI1xR9K¾.ÝyLëŠÿ•]Aä ýB¦=ÀÁ\…)¢è­U˜òM´^—WˆºÅnýD´ ìÈð:H.À Aˆ#«èQas^ë=Xcæ‹ÞŠõs2Ã%# Í&SÓ©êÅHÞÈd|ü4{6ØlRo ÁŒ]ɾƒÔúql J$0(`Ÿk¸3åmÞƒF_’—¶àÙÂûëëÅ©àÙå믯¯¿þòâò÷þÝHþ»ßÿ£Ÿ]ý‡ë¯^¼:UÙŒK¼é"p=àÿÏÖ›>·uŸk‚üÌX"ÅMÜ7œšê¾Iœh±lËÎéºsû&í¾K’›Ø±-‰$€³Q\€³/NO»Þ`)øºº¦j¦&¶6îKbI”HI~êîXÒß1ïò©;°,R\@ðœ÷÷®Ïû<Ló 9ÅåsæŸä•õŸ à ´vØâxU‰˜­ÉoòR“ϲ'¼€ˆB$êà±£X$ D"º9Ø‹!6'S/.|lp{†}BE»~•lIô`°µ\«ž„^ÂÃCŒziÉ÷¹{L=hj¢‚y•æ襂„ßAýJšS}îïþÀY¹±¼t= ×Å¥iõ5IúúÞÆînybêÀ;2Ä\pd’èÇd䙡—6ãá·†×ÃØ|ÚÔä­Í$í°èS'L° ö°ì’î!GðºwáøÍd*x+L5-6ͯHÎÌÌŒ¢ª+‘˜A±òƒ¾×õ«`SW¿³_ä ÅÖho aèš¹¢a]5?XÐÕÁ qºPæTP×óƒ1<¦j h,ÃD<"M'ƒí æõcE¯N S\°Ýl.—Ýãg`‚è÷ÛǻۻûhgÿøàáÁ“öÑ·Ç‹7Ê%¿yb}ÈáXÅͤà,Ë{È DL k 1[ÃM¹o×Ñp`ÑŒ:o_DZA€’ÒND(N¨}ƒ\^ mˆwd¥ ”d¦V¼I`§ÆfrNÄ4W’‹Ÿ£×«²UÓ*#øANòº¨r"€¹W@.ÌK=Ö’KSª‚ ý—`ôE*§òÒß|懸.íoi…€§Òðð̘~,<¢r@u"×°HÁ•º×ðëSfÀÔ0ôÊhM“vF˜1ÒÐF.¾Sv‘O÷þŸzç/¾óføæÔ›a§9ù‰¸–¹ `Vìú1˜ ]áº]†nA h¿,š/ì ¬/C0Œ‰}A PQÔ«š¯**V:~‰d‰©øvŠŠp¤Þ÷.• í8¦­^!2=„Í¢%xòw®.¹ØqnßXÝk··6·v!ÿñO´Zà+hy¥²+ö À%ìÒRo¼Ìø–} Äy'Ó´@Pæv脜÷ÖÁ:MÈ ª]CÎ&»!öY¢öGM—ÁýûF¡íˆ6fÛš>ŸWlã•]PM†îÂ7CbfH¼_ŸR«&µ½3t-©DÌY¡ÑC5NäMÅ ‹©'-äȵ…üÇÿ§†ò­ú6WãEœjXæH4<˜©ˆ ×$ÀSQØà p?üIÕ9LJ‡{­æÎÖÚööú&áßüéÑQ»}„ã`4¾%¸ÈñVµŽw|ÁY)VžbÊ]b;÷Är<#„££µufØEpyŽêãjiD®”Ž"®‰Y¸„—:\ŽÔ¨cAìÕ<¨hh×>Ì+¨Šqõ£¢‘eÜ%µGÜ]¢$D·R©Òà{‚Œ äÖ4IV<ÜÔMV':i9SýÁ”NgšÀ~À.0ý»ýäÀ…äïÑââ–k‹˜ÞX\„»È|–VrÃö]d—Æ#EeyÅ…ú$‘äCâ> \<îy"“j7ÿÐSV¿5¬hnø¼óìà­7ýóৃ SxÉô¼Fu.ˆHˆÙ5mÕwÞôEfÃ,@Éai¶¥ºXP÷ZªmÌ릻úKõJÑÌtÓÅ„<±”%ÌÃiCÏ]&f”’Ç\E”#]yÛ©ÐÂŽUUD;_H*ìûì¸]¯?>Ükï¬­í®¯oîƒ üæá“VëÙÁc—P‰6 ;{Hm$zÆÄ’ÏhDB&Ltî±IG”‡Wó‘%šx˜›2çá_ˆå™ÉÒC1ç DMì ]v|S&Vž7SR@ <ß\Òuþãk³Sccð%oð$iµÆÜ8Þ­VÙ誂Šk¤‚Á!(7!²ròË·ÅB®!¥u]4ˆha «ßÛ‡ÎêÒJùуìÀÀY½Ž"È%—›V¤Þ‘™éd€I‚ã·œÈqêb¸1‹Æç­Fi~Mñʱ‡ÖHi`\áÖ$Ekt͸¢‚=$ù~çÒS¾Éù×/ž §&°˜¨9Ì;FËkH§ælhÌÂG|#oÎCÙ[ÄTÐ.İlÏ[`wzAÑUÕS(pÍ0\±»b 'r´çCOC5ˆ ŠáE}÷I¡XíÅp•ô…£™­ AÝû¬^oמìo®­¯­mî·w |Ðl=xøä°} — ä½Z„d0V‡_ˆÌHU‰lEäâžbxö"ÁSÀ…Q(¨8a4?6nbn4Í9‘YÔX„kZÀ/WË|¥ÎÍ£æßÿÐ$m´ ²ÌWs‰­«j-­U*bËB´WЉ¨©¡ã87〒2ªª¢L›D03 fÊ;‡åGKå•ÕòÁêÒâÒâ%¨ƒÁ.>BÄi1˜üfðó¤É!¨C*¡Gã?Nå eCdüI”ç!ÓýHÚ‹K+QÌu7bSÁäŵPÊ=¤ið±Þ„|+zóé»IrŸK§ÎUb7M‹%D ø–óM ¡–\¯¬±†:—i]vÑ´t»0?I4[›W RnÈcYw5_ÌkЧ©Ú’oê`½ îzbÖI<.¨]nla޶/Yñü§¾˜ÛBX!³ A ®{íúÑãÇ»ÇíÍûë;›ëPˆ4›þøàÉ“vûùsxeeeµT*¯”J¥¯)­eFÜÛ!´ÿ t¹ÕÁ¸#Dtä$î ¶'ɬ8<ãæax Ÿ÷™…åyø÷üê‰Ô&#Œ2ÊËÐÕ>V骩WÞ×Èš³ ð»÷ Îé:N'ZbØÊEf…³}«ŽK­^°E„@žˆ‚$&Cµ .¶¯JÛ÷ï”]ï‰ûÈ-“ \‚Ö"‹¤U!ºã„%I¥žay¹æÈU”2ˆ¼5Õ¡.’¹ñ—ÖÅŒ2™LÃ<…\c»†Æ‚¼=3/2Â2ïøéÅ$ºxîâÏ&§ÎOÇSA¬jQìzÌ3f“ò®Y„‚tÕ,€§WÐ/¹˜Zf¡·òùb±(›š­Fºm@ 2§ØúÕ•+iFÙÖ¡ÔÓ]¤é½|9¦2šŠ )a9y.=àý *{BÆïó^dB³|ˆåaá ´mïÕën»…\RGûíÖú½{›÷6vÚà>xÒl>Å$PAì>Šv/wPÀý­¸+`›-HÛ»­æúú½ÍÍíÝÍ­ãæ£Gž`ºwãFieµyR‚P ¸Ïh˜ë•`ñÙò®rGo3ä™ çX¯„Œ¦: èñ"Ƽº)H¶õ"úF5p‰ç+´u{!oø~fëJQ/À9um[Éê5Ýrf ÊEG0׺dq•(3ašŽÐƒèé™@~DM@„«$Ï )Aa{,Ïõ¯´³yÿèÐ=¼{çþýÇeçÁ£GK=€ÇÒ7Kdð|N*{àß"Œ±3}R&Ÿ’¤;[»I&GÒØ¤äÉU9¬Õd=T ¬ÜWæþ7žðz©Á4²ÈE¸øéáíwËØ‹ ¼wÀ/\8?ynúÜ´(gð{®I+B6ÑHê:š…V4=|:ƒ]Šš/^Í_ù¸øÒšƒªÃ4Ñ$W¶¢Ì›®‘E*ÔÆ–)elj«"’þæRBŒ™¬ÇæyÃ?ú‰GøtÚ:Æ­`jc õ5†‰@# yF@+õ•¥òš`ˇÜz…ðÆúÆÆúÚÆV{{1­#ð€ÇX€Ðž´wŠ`Þ-XÀˆ;oØ—Ií1ŠÊÈ;|Ñ^È€=Ið)Lªî»Ü 9O`¦„à{4Mx‚æ7Ë \˜s:+[[PíbÁB<‚¦XJÁ Ü…•/˜ :ÁT©îE£Íï*n'áz#`ªÌI_QE‚ˆ…Ô9 £Œ!`$XœÑj8þÝÞ8 î>½swíîcgùჇårùà€üßAÙ»+­ÊU7€ý%UY†ðÌ ÎG Ik²42<&I!„ã X# Tª‘VX¸†Šv.~Òt"£µi$$A‡_‚ÉgÞyóõsçí‹çÞ¹xqb .?r܇¾¹ê±"8â³L›7«‰g(¥.KS¡™¿ú¡6§š^X˜ÏmÍ,^ËÛV¾h¬êºçDZä-kùàòåÃÃÇ¿ù\ äàÒ¹÷¿Mã‰ð™CÄ›úáS€1×·/¨ñcâ¤\¨ƒÎxÂïÒ* È¶ÁŸïc% -¨ƒ›ü㟞<=^Z†Ìº´ºtcµ„M*¬€;bq ¾÷˜ )²˜HNYlޤ4]#uk&êè„î€M3$qFüñ°¸ƒÒ¢r‰2‘¿boÙ»Ë#·l`[¦fúwf‚³ûꕆÀÈÌÿÅTt\dð€@éý]›I†›ðûô¨zˆd¥hd*ÇÖ¯TbaI‡»jUÚݸxoíþÆÆýÇ¥7€'òAA¼ô¨\~|Ü[•‘…œ`EÁÛ%™4<=-eUiR^áùˆ,@%C™àª¼ñ‘VÐ 'ÇúÞ”5ø0Ô»q¤ëd®6Ï{ë-ó'—Þ:nzúÜTÄëÙ.R¬y'(ÜV"¿ øe\¯Ô¥þE›»vuanaA3Lµ¸ðѼfʺ¡\{e›3ÀÐtÃ̃ýÁãÉ“Gß^†|NzûÂO/N õv÷"VgòÇ=ÿ~Œ‡ø¤‹Á¬"­`¦†d¿Bõ@ÔWîܽçîHñÐ>i>kï·Ûë›[Û;{íýæƒOŽŽ¯/./Q+zñúbÙK²,#rT±‘ÄxæÛ Ä(iä Œx$À1¬¢E—%¤& Fc‚²„ÑöHÆšåô|F± #dÞ_d‰´n‰çËÖ h0@Ò–y,Ó4Ã2”W*=ö‚ƒò\°ƒƒòQ°ÀÐ8i“k¸})õõôK‰Ô70(˹(«f¹é©ñ±œÈI…´"¿qJ¬ù,OôýÆŠE\tUÈ8ù'ä`.”Áî…·Ìsß¾ôú/þí~ù¤ âúb¥’6€1*Cfb2¤ K+äÕB~~¾¨êªiä¯}TÐ4S1Tå YkºêU¼©RµÂåËß~ûíÁ£Ç=¿ ?5–Þ¹4vvpðÔ©áñé™™óƒó£q_ `ž€ðnšáwÀ›¼'8!þþ?ÿWãæÍ$yË¥R»Þ||Ø~º •ðÆýûë`ƒûÍ„^Ã'×J¯J IDAT&I3ªd‚¼MØžPóx9ŽA7­äѹd_(R¸°ãã"fK ÄL8Ú^á ì^ˆÏ²ø"Qxøbµ ×ÖÑÇG€A؆™Ÿ_0ýÑÖ+ÓÔ‘ÏÎR¯©yGµZ­ŠÿU…³Cž• |¬ã ÉqkÓ+CÉÄ!” "m*>÷'6ÕbšÿîmÜ[[ßÚÛZ geõàÉá8uáîÑ4(BÄŠ*<&£±H&é-é¹Á.Dúå JqAÕPU©ð~þjÞzÿ@ ¯À15ŒÔjÅqMå2Zàóg‡‡ß^Æp,½538p¦¯o`xbòÒ[“g~ô£© OS¡ûåÙƒ€5‰¹—Å\1×W¾þ¿%ÉÝl~Ýl]G”_ýñQë"kk÷îoìîc+ð!vaN€0ˆäÌÚmœ‚p€AxÏ2räcJ ;Ëñ^(è«<†8Ÿt£Ù> “åq×:¢´­,+b³àQE‡–6È";o+„Ú(¯šYdÁ¿®wMÏÂÌ0ÍXP3b†©VjÈŠP¡†4ü_cpj„Ìi1Y[—]äêàK6HoÒ„™RžÄÆÂ· ønmoÝ;ò–VÀüž>½<~üØyÉÈÑ&ø?9ܼ³¹Yja39ˤ‰é\n¬wljb" _Ìr½CÓ’Ÿ† QNÅ€&@azÚIO‘¦F0U&„©ÔÄ—É$é_±Aõ¾óo€NÍLOÑ96À¸¼"’”D»Î1¤…>*⺠ÝеâTº ®þnájþÅ‚‘‡RØ6³²(W,Ýs=ÿWˆˆÌÉщþÁ‰Þ×NŽþøõ‘©C|±„ýZr…a‡œï¬K¡—›%h‚õ?ÜiHÒò×kÍ{[mˆ­uÄ¡µö›Ç[pi÷÷!ÿéOЗVWËŽC`|ðˆ{ûb°Šñš˜RD^G˜†¡Ž%)àä û‘ž°:^agü3uo<Ñ(§‡B6„þŒÂ'v3ß6M„ÝÓ÷Û¶^àªó&b‹úµ"Dø™ˆ±Tt0aN…Í®VKÁ  ÿ"†4ÆÎÌ<á°:‚­¼öFH©ˆÅ; ëÒ˜ßîÞöZ¸Ðþî^ù‰÷äÎáÑÝÍi5ج1 Q"l€F(958*õœ „´Ï¯$ruvbªø¢ZU&ZrÌà ŠtÒÑêâí¼„Î\)RP"+“‰¨³„Sï”Ló¢¦ÿéìôù)aAH¶áD£Í:ƒAŒÊ Åyøù.MÑ-CËk†¢*Åù+¼u¾h«syÓ^ÒñGº«êú y>¼ü lðùÑÑåËN49>|vèã¹ÑÞ3£c£?~}x<"5>UCáSZp«À¼3Îðe‡†‚¡^nlß½óÕõÖífk©YßÚÙm=m=ƒ:dkksggw¯ùð1¢Ÿ`tc‚@vÁ~Ä1±Ã¿€=´ë8"ŒÆU7`âçŽV' jJZ+Ñ÷mËq‘vÖ £N¿HÌGàûlS5¬r@Ïì2Õ0 µ`BD6ŠP¶ézõâÕ<ª=’.š\ ã0úÁj™Î1)$¢,$‹áñ0DeÏwRFÓNd%ažè˜Xu`›€iC‚±½~ÿöSïðéÚöÖú³£§‡GîѳµµM\ÊDF„S’N2­É5ibJʤ±IéÌ™3g'$(8äJE™†²X†¼,©ªÕ¹ ©>ï{P%LE¯X‘q5!^k¢Œ…p\“K(óÃÿlê'SÑ*›™×*'ë¦ãØØzF©8ï-ñµ¢¯k×í.L¥™ÉÙÙœ©\ÍÏxåꇅ}÷ rý‚DÖázjp)MÃU\tàK cxÂå[ѧÅÒX?øïîÞ‰©©ÉY8a³~**¥m"»$µ_‘M'Ó¿ƒ…n,‚6z³õuêàÖ T![„[Û¸ö¶…€+…´Ú‹\Ʊ(ѰÏ*Ü(v™\Hä\yRFÆH  âF3·"yÜaÆH3=²9Þä<H>›ŠöKÝ6æ 7ãφˆ?(ÌAh lÝ0ͦif¡¯és ¨öÈê܈¦BÌ µF°ýR¥˜Œ6X©ñÒR%õ¼€o2ÖŸ)«#”™0HÖ-Fþ*TÁ[÷owî­omo£ý=»("t˜/¢ú!£¡ÑNrc3“ÒÀ™\Ï©ž¡ÉI©X›ž™•¼Z&Wˆ.烕 ΂ ûÏõ†(:DúÉiÚVÂW$Èú=¦¤‚+®åõs?œ<n¦›ºV !ÏS‹(‡]a0p"óùØ#¡8ðŠf—ˆÔÜì ÔCf±¨À‡,M)¯l°58¾ŽbK )Nˆ¢rož˜z­»{x\àÙñ©ñññééÂG±DJ¨(ÃD‹ÞÍa;y¢¢XBïgc¬ß…R¤y·ùõý½•¥ãúÖú~ÂðæÚýµíý6º>(‹¯/"Ì÷ÆrÉ…“É 6h;&˜Ì!+J¾™á‹¶éuè@hwøDÌP(ó0™FtB™]ÐnptfWKôpÍü•,#q9ßC35E³|(HL’þ6#ÏX¸VÔ pÌÑ–á `…KÛ“`iÕ¬óÀÎ ”ǵ,©ÕÈ«HŠ{¬RÇ…–/0ð…q¥J3 ¶¿Ý­õ{wî¯oïnoßž=]__ßÞÞÂÏ ¢€tGRÄXÑÊ\*Icm!j ŽMn˜¾Ñœ$ã¾.)ÑP†¶ES8f¼èÞáˆã½©Î †§1x@„¢ :abWÌ¢|þÇo¼1•ø%ˆ^€T¦à°< 0Ÿ(¦*^'ÂF— ùŸmÎN¿-a–,[Ö‹êeÕŒdÇQÓÔtz:aPHeº¿{`xtxdrlxb|rbìÌÌx.kE¶#ìALJ¦Ñ[G«K¸ ±‚Ÿh4Öo·Z_·îo´·›­úúnsÿ¸¹µ½¶µ¹µEð£Ã§ÇàQ‹ TRÚ¡ê†YBÏiÁC°`bl§ r£ú‚ÇOE´GTÙˆ"^B~—¦¸À‰Ø†C¦¸â-bø DY[™#>wÄ¢ÚÖœmæ?6LœÈY`€† &m\›ÓòïSF}P7!Yå‚ÕÞTÉ!ŠŠ¤LpBbÑ‘_KHÐÏ[Ò¸€Îö·¹vgmgko{ûé³µ­ÁÈØæ Sж!°9i°¯/×7˜›œ‘ËN,§`ãÓ3±—ÕhI MjE"*ÛwSÞ½LD÷ "F‡EbSžbŸ$D\Þ r £*ß~ó'ÓÓ3I¨—´Õâ "ú×5#F]S$¹Gœ¥¥ª¢ÆË抉ˆh¨gÞ—s‡Qä»BáÚµ…b±7ÎÐQPÑò\£©h~ñôØÀÙÑÙÙ©±‘Ñ‘þ³ãC}ã9¢Ö åu˜|;¯èkxoóL$lн3êh7ÿÐ>¾³¹³Ò>®ïî‚绿µ·³½·×<88zÖþ«°-@Êx™© dHÕ½¾  r#1ˆ—äÈò: “¿ðø˜§½³†B \0dÉ/‹|p°¦$ÛZ0uṎŒeÍ E»8ocFÅzÄôÂ,Ó *ª=ÒØ‡¥(­'*T¢Á‘)f´«”‘eVS–’q™”# £Hpc8QôB©§d÷înnïînon¬­oîlo£õ­²™vÀ{‚F ®ñìp_ÏäÈéžÑIY./ûrzUÈ +¸%g²`A¥E ÏK¾ç¦‰÷¹ø*Ž½Ô™DF"‡‹`VQ“­†33ïü gä42f¥.cÕˆ#Æ+ãåÕ!ñ‚qQñ­‚ߥØv!_Ƚ{q\Æ8lZHT4ÿÑ•ßÍtµ®S’uÂ@…§±¬xf´oh2—“&†Ïôœ>3vv°w&Ón¬É·Ù ÄØÊ£ÞÑ=fa‰|ÞË }Átá׿j·nßi¶6ÚKÍúÎ^«½~ Û€Çhv8‡[.Q0­´Ú{¾É"33mãS@ Åu$TŒ¸Â•xbê¢M)Ñ„Z£ÜÑ¡Ïü€ÄúBëìøQÖáŠ%¤çù%BÐì–bX”º‚$UK×,L5Â&²¡ Õ½ŒøÃCV2ÂÆ½Ô ¬‘Í¡;+¬a$&ÒÖ ^"Œi뉈‘©H~…AìoÍRÀ]r~¢©ý9Á¸@ü ±S.KãcÒø DßUùº'{~ A¨¸„ÔD¼+@ˆÜaDê/(W¢˜×1©ôa ,«ãÈ$!Å#ȸÊÏ6qå:e\Âé4ö’ Ÿ·4]gļ¢Ny3öcÍÏü8CvHëº2ˆ*37=~AÂ8lY×òE%_˜»zíjÑ(Ì•m?ÂrÛ‹Q¾Õw—øؙ¿}g»Çdž$)ÇXˆ—PÆÆaì¦ËÔho‘ù¢ú$"ªŽ¾e ¤]|·~ü‡æñW÷Û÷¶–J­ú~³µµµ±¾½C«™‡èÿ–WVWJ+^ˆS}H7‚2©bÈÆ<IP¢Æ$º„‡íˆsñ~¼ tfšÝ_¾Ú²P¦š¥3ÜãÈ5wÔ}û•¦.¨Ôÿq°ˆö;3 lE·_(†™y%£h¢Ú£XÕ"¸5¶G©CÕ:@&¥D7HÖHwÜ—£ÅÓ„‘¨Dvñø ¢†µK—¢0ä}»L†µJÈiÚk#Ì^Ä€ú¤†³Zi°çôô™QY.:ö4è–ÊYÊÄ1•½UÊT‹C …¼ÂûšxD&­ƒ/¨Ðhû‘„{ü²_&Õ8ⓞ×uUGÒd¯¬ç?06˜‡ìeI±\Íô=S75ËíZˆÀÍ契ñã0¤ÕêUuA™›»ò;#ïš(ÒâI.;$ßê…9xÈÒèèÈ©¡é!éo¦)¯ÄÓ·iâ숽FT éLù‚’>mc£‰%¾·þÕíVû«»Çw¶ZNi︹vogok"ðŸ¾98:þã"­‡ˆ©!/4c+ˆÞ Czä3 !CcЖPÍ«VóI°#üû²W,I>ê$±^,zÚ.5‰,]·ÍÜdˆaØÖ Š:_(.Á 4¾Ð aïª*4$öì“FF{¦g%„ýS=é2-‚÷WøB깈¦ƒø‚+ÂLÍÁ˼!éÞ$vSo¶o·ï¬µÚ÷×7Úííõ À¯6›K‹K«+`b¨ž´/tùD|sÆx¡é0ƒ<…Q/äYICtiBVŠ7Ó;+ê>ÓŒó¢Ú,÷JëTi 6²G¼dª)ÛVÈäÄ>Cþò‘ _ˆ¥Z/LßP´¹WØhÅÁSFJ¢¼õY.—‰/:é ßžU#ßZËjiƸhø+«¢&’{pÙ¢8ˆšš8àÿ JÛ,”`~iEÁ¿3JF,SbÎècv†v.õ÷÷LÉËYB脸"»H‰†òõ"1`Œ, |«Üñ«RA’àÖmàQ šÿk›•”4g)%fš0— [ÞFçøB1V5”y‚+‹jQóuÔOGþqðiouÑ:e—–ÄHoç¦b ö Õ¯¢ sʼ’À ÍU‡s #)ǹéÉÉ1(á%éßK±¦pŠ%†A‡­…Ù_pŸ,`2íér‹ J¯Lµ2!·×!ò¯·×Ö[­{w· °kïƒ<|v¼´ &H_¥µã]¢÷:GâaQ›ÁOpº‡Íg¼¾P¶¥uš¢ |4wY¥'d¼*¯¦0ÕÑó -_4^¸CD:øÚÑüt+̈]ÆFô•2o¢-B2h)yT_AµGÏ7æ¯\)Ò š~q´ö¸tªHÀ|bۯѠ˜D”jIC¨Æo@{)Sùýíìí²í­¦U&ô#X¼"L™e2Fí—¤ÒH_Ït¯mV=9–Èÿ<$©¤T…P‘Øg²¤¸–².q WôÁ|êL“ øÀ-ËsHú6`ýceCßUŠ(ùXÀûàé¦P×}pç ß!ÐðºÔB R!ä& ÇDû7W(ªóÏå‹FƒåRkÂsÅXq½xvvfv6 #7§ Ða‰x’Í,æj섲<ÒmE›syu=`†Œ˜µ]ÚèCñ¯úñWÍãÛ­ûwšÍæöÝû›û»8yøBnsiÉqÁ!=‚»BJꬾ!dQé"x„ñJ9LF\ý CýÇCÀ¸ ËXÛzTº ‚?xO“æo¨R0¡‰éy¹¬UïÓ¥2 X서_°Õ<ä5Ó\Ðôbþ­k×òïT ‚ }S$^ š F[’¬ÁšÇƒÒªÂpÁšèH£ &DÔr14IâÀÅùz?Lú˜+ˆ©È‘Ï/°CäAØ+¤GŸKÁ«LŒM½6t²ŒT•+9ªÊ!„`L©3Ìôk´ƒN-éŠà'Jȱ0@>Ý14êrqÑN’Ãâx‚£Š„\KELÆTdDðMÇšùñ$í)ù2£zX%êʧ åÒ¶4õfnR•tS/óç>†lYF¤á,™>–åÇŽÏš ØvÑ<Ó& >Ÿ¿bR‰pQ?@äˆS2Êç©~Ä×YtªžS¿Ûúú^ûx}½Ùjîo­C ððñãÃöõåæòr ¾Ŭ‰’Rˆ‡SN@jbý.âÒ”°©êð™b=á2 ¥,¸O•Ï:„ï Dß\@ÓAºD^I½[µµkEƒËÀ`!Ù\\ÃP抿+êd‚êÕâû¤öˆ˜V•¼Há’f#´2P¥ ]MÀò«ûc¬*ÑNÑtî*ØŸHûh·=aÊ–„×4(3#ŸÆD†Qáý¥8†<=>1 p}3ENÔ BÁ#lð{¬ó€ ã(õ«0H‘¢ŽV’€gædwlŠÄÇB /¿£×îrväêõÔ§màïL¤6ðÒD‚‚Îâ?ÔèÊÃBû{!MAd]•TM)ççòª!‘ˆWböCËs™ ~ž¥ÙºEÀçõ«P´’s.¦¬Ç $6 äeÕ¹ûðµ;´ÐŒ/Úqê÷Ú·[_ßon´ÖÚÍí­­Ý]äExö¬½tj`2·¸ÕÞÝó¹_ÌJ‘.ËA¸¼… IŸ±|^giŽˆºÂKòxø¢Tâð\™Š#ŸI4CšËgÑ­P,³CÔ͛ꋗ&} ñ„ˆÆÝ8 › Å9ýwWTøÙ®YÌkß½¯²Ž7òèd¢?-ãt„,±B=t‡ 5ªùX ÔXL“+/Æûº*Ò¾Hpò’ì x$¬?G¿i£ š§tºg¦w`|á1·oßƒÒ ÑYÊ3ÈD¥— ¡tÚ„Ãâ»Zv˜0!ÄJ vTi,. ½ÔË%yË[$’pØà4º„y¸Y3tÚSòƒ<‹°2‘q—fVtÛ~eÛŠ4‘›ˆeÃ2%E]Ð óŠ!…‚‰×aN,Õ ’¨Œ%^LÝÖÝUêw`ž2‡ÅˆQx„ebÂAÑ‘abi'oVo}Ý>¾»ÑjßC@Vs§Ýl<|Bxµì4[´Í}¼/v¹Öí<ß§t›áP¿ Y45[F¼Â]çÛñ„mf ]OÚ8çü”šE¨Vø”Ó¯ÁºïAf-H‘q×>гËV`p5”^-|PD>ËÀT͹÷ÿ§A­‚ÍfLÈ…µ\Àœ>ö‘(ÿÃpIƒaÅÐÖ&Ñy€7ô¸¼Œ#ê·;¤øËÜõLãÛáfýB¡É£ ibzº¿÷Tÿø´$}UvCY–†FÁc9ªÉdªvލrKǬ¨“ JÄ1©)S´ÃC‹é&Ï^DÒ,<#[Zþçªb¬ÖóðEª¥ª¨n„W_U1˜ÇpÖe€w¤¬J3…c²ÁÙYœφ‰WF&^̲< Á¶Çªõ¨hê;ºfš•ݺG‚~ëµz¼zæU•0›©`Kb:Ÿ{I&ÍÖÆÆqsc jÝæ.í¤?{z|c¹Y†?lÑÀ "0)¿œøA_@ŸÙ9Áä6#ks‘~mpð à„i }1'"‚43èÀ±¸cãSvMPFjŸ“اeÚ†fb4Â6Œi¾Òþ§EÝó•RP_ÍwÔu½xeN Xé&° –›#À,ÖŠ6^*YÆÁ‰ñ’ía+´¼ª´±T©%Uøâ˜àña…{vbK¿†é‡XÓí…VÛyjKŠ"‰Ôß75ÑúÌÀ¸ì 8kL˜ž–’DNeÙñYâ‹Ö X(‚}©ØHN;¤\q,x§ƒ…‹ÐYqEч7‚ê`Ç/Ùà£lØ{‹ \X]/hª$œÂbÀs)|Æ.„¥ÛKu p pöÝéIif2bÛ|^L4]×FXµ¡¢s-xþª‰ðše>¬jJ8ÎH,”yLFEô¨ltúÑ„ËLgÄÖƒ.ðÞfëv»uç˜ß½íæqóàÑA»ýüøú1ä‡Q«…»˜Î‰Û ˜ž~*!‰•:þûÊËêÈ5Iؽ„ôªÀ™óXšS•ëk0ißâÙaþ)ÒÊ ™âDØžKÃ/ˆEÆ"›n²ªAõf™–ª(Øø… ©Ó>ŽGRƒàm›Zªº:+M¼ý¦œ{{zfV2p¢‚?S×ó¤6ŽÞ×FéG¢Ipò Eö IDAT`æ*ŽF8%.†PÒEMgC?ƒ_ô>f€ õ°Õ€Á½¾Þ¼ûõqûöÆÖññænk—Cžc^¼^šàÿ*íí½}„í=qÀ‘#¬Õ~ûxÔDf‰ÔŽøsñ'Å)6P7ÐÜ”…²]±(0L²^\^i®–Ê!TÀÆ_Ä]ˆŽèú}¿öÛßþÓ?þÃ{¿úMìŸÀ:„&ˆ‰w+b®”£=–öyÈFämèšy•9 w c¢1O !0Õ ‘A™/f™¨‚5]+êVfë$Ϩöȵ¥C!÷ÁÿRªeHíñ{È5AÒ<Äà B±ô_Fù_BtúÕ„—8ÓFã“Ï>û¼þûïÄ‘µ$¬bÃkjB˜ËpÃX:“4l’8wzlxêÌé¡ñÉžþñ³R?®§CX­Ê©ë„™B¥Í˜‡‰ª™•.ø[WßÛ Â_°Ðb‰2ŸUõ¤×%m‚ Ì¾k–]Û„ï5tMױХ`Iãù¡.¸r1u±LMQ§ßyç]y|ü­™˜ÙW1ä¹ð-˜µA.æAå¡|Eaˆ‡ªzäȈ¼2f¡Rã1Š‹€eO,‚0Ô“™ë;›ò¾ËÄnž__¿}¼Öº»y¼v¯µ±†˜ˆ¹‹«NL6!.ü‘"dÖC?¨ýöW¿þÕ¿üú—ÿøÞojµ°“¨Ì~Œ-#¢ƒá1Y‘4ËçÎt™J¯x”XCNDëˆd†EÌ+(ht¯ŒÂK­1 lËБñ8°UH‡‘UÛÅ«ù–®Î+sBцÕYšD ¼°ýÌ‘—± 5¯Á·¼4ÌjˆÁh~Ÿ~qóÖï VñJh-i}‘pK‘* ÄÄèë` BÆHZÃq®gôtÿÄÐø@ßD_ÿ¸4Ù3<<)A)’Ê/: ëv´å˜+Š%)9I ) '‘±Ððê@&7ˆ?®Ïîl‚ĨM1Út]î•mÃUS_b@ŒèÌQ¨ÓëvÊCu]QgåKÒ…ñwsÆJÌd V5÷"vGÉ»4ž·ê*ÙÞÏ„Õ5^§ù1CG(˜Ø"…<¸•î $º³ú=ðàùö÷Ž›[;Íý6d‚ÍÅe¿…SðöÎþîÎþ>Îí*AðïÃï¯ÞûÅÏÿ3uXq¦Ol1Kwáicäž;HAxŽ s¹ÂHøEu #ÁT3†Eg}þ*(}_aÈ«-ˆ†Y¾mâZ—¦ÛYÖgB\T?RÞ/FØ£ÕY˲M4|$mÃô† à Ù r×쑘³ÒƧŸ}ñÙh~`€ óUHÑ#ej5=á°Bè…,¬D”FGÇOœžêy­oüì”ÔÓ3=1*yr¥&Ë8…©ÒxCì3-!Ô#R÷¨$˜Ø «”-9DŠ‹ÊäTî2Àˆˆg‰â3³`lŽ™žnšT9x™b¬Z6†n—܇'ìr ;e T_(/¥·.Cüµ¬ˆÕz‰øÿ:é§)®ãŒXÑ´•€ÜI$h È<u!µq7¢!ñÿˆâ„Háp_›94X$>­úÚVû>Øà6$~P ·¶ö[Çû-”Poa–tŒ“¹Ö~çAáâïoõŸßûÅ?Hg'ú'Á}6ô ­e"!bBô¢«BYoÐùŒPõÂlŒ/XXL‚±65r™ëKz\‹2ª7L‹¦:tpQTŶà jÃÓÚcQͨ¼¯àfºP{Ä‚¤ša±€5nÊó72Fš3ú§ÄUi|öEýóÏ¿¼u«ÑÀµ8ôlHZ*°Q$¡” )/ ¥7a"æ/Hr=#€‡ÆÎô æ&Çû{†pkàÕ~ãŽ|kÊóL`’X:ë•x˜…“˜ôà¨âP„â¬Çtà¾I½´8-FÎ 5B ä/­eÁ²‰&Ë D§]E˔뒦Þ}WN -ñPöÕFgJ:€û`¨¦€)›že†ÒHþx"¦í1Úã˜~þD@ 5^R8!éMÍÁqë›Ç÷¶vŽ×¶öZÛ{Ç[[ûíýv+tcŒ¿.¯$1Pã‹ø/ÿðóŸ¿7=:490Õ76HÁ¼V<ìºJàp;’j`Ì™.•Ã%8ÜÁÍv?‰y2Gž‹i—ŃÎ&¶…²fx¢0u±4Eà ÄB^EDõGãÚ;Hàz¤ö%äg#–]e@4f~è1¤\a kœÊVŸÕoÞ¼ùùÍú—7ßÀ=%Š ED¬ntvÖ0XÂfkdÿlÏ™3“ƒS=?8390söÔp²O0,T%Z8« u6¥åÁá(’ºsA°É }’uÐcPºD+Häè|´p÷WhÕ:¸†S–M úÕÕæ0RâÀ ð…!Ï´…ª’(&Í.O˜ß Sy©so¿}ùÝ·c5 âNa&ˆÔT4˜1䓊g@vWMÇÒÊÈ¿âøü[Б'ÖÖ(èÐ^ ) T2Â/9ø ñ9'IëàÿŽ››Èˆ°ßlíîol¡ p”´wÁâ–o\¿ðÛ‡Ùñ>¼ð€¿þû¿ÿŬ4455>6:}VªÑÌÎBP“²Þ ­Fú….›@$ê[ÞRæY0s = páÅŠ…ÊïS¡Ï(ʰF<à+ÃÄí3Äá»iæ‹æïŠ -Ãõ¹€Õ p+~– ¸“D-?¬DPÌS¿´šÔ’25>©Ÿêî»õ%!·¤§J¨äˆc*5®~©Žeù°ŽÆœÖÍ÷ O}­ûµÉ©Áž¾!É‘“HÎh ,#"5M "ñ$Ñ’¹zA¥á©q‰‚oñÓóôÈõxâÆMXÌM׿â寒w òØJˆµÁ.ò¦C•¦£ªÚ+ÛÓ žð‹¾àzBw׺ʶà,îÕü‚¦ô™ñÚ»—gL; „C… NÙ"Z½c"IsÁŒd;÷Tœ'¹ìïçÒ2®Ç0L¡“ Ÿãûõo~óIrþ̓LÓúöNóvk¿½u|ÜÚ[lïì€%‚½ïì4]·¼|}iÙ‰Ò.ÆAŽøÞßÿÝÏgǦ'†úûÏNRˆÈa)‹^EÈŒ1‚þŽŠŸ„€zãx:Ë ,(F0ëy´\!ïÉ8ÇM‡¢fãfÿ ©9Ðê6Fâïp84LsA1¯¯!¾‰Ôyý“‘á]\š{$Ôx® ´†NO`¥qxœ&œÊ²[?èî«Ø`X¶cÖ2$Å¥˜ä¿y ýå'O÷OLôžêéŸêžc”ä2¹=dé…7•ˆø;|ø#/9è¹,–¥>)êÐ" <6Møh “LÐxhSõæ¼Ô¹b˜E?Ïà¶ ìåI›¢%ÅÏt žPý^‹À-š]pˆܯ~ùaÑÐUMN€#©õʈÙ¥ oÕ„ŸL#`TDв=ijûbÁƒ+ሠKps$Qˆ£éŸÿéW¿~ï¿øOÿ(IŸüxD˜ó3©ï·îmµ×wÀ nÂûÇ»Ô>Þ«¯\_n6‘×%j "¦>ií_þá½ÿøsi|hrh ·§§çì¬Tc,½‡DHi‘(˜3w[áÈŽÝð [9ï(±}R yÈËGaä4jÄn1üï¶>¯Zd”˜¹è†nG|eŒ+¨öFj5ãš27o€gÍ|R{dí:¸<u="m«®" Äà)Ä2˜?ÑèýýŸÿÜhüùÖ­×n‚ý5„f ÁC+Œ%ü`Íùäß<tf3tÇú†&ú'»_{mjPŠÁÊ"Y®aÌ•«‘3ƒL¸Œ@A™ÒiXBsç!Bp†ö\H¨ˆàÄ`E¿8õFq>ïæ‹Ø ñy _Y4ŠÆ+ÓΔØŒî zjzÈ#Ô)à †a}N±4UÍÍŒ¿]dd)fÖïï476ÁÛ{uwyùFIìÆµÛû$º›Ö~ûË_þó?Iã`}p={ÁRˆ÷á\iÄ£€ÊĸCf„äkLØÁÜÌ‚ ¤*ï h!~‰Ã‹T‚­ˆž iˆæ3Cè,[Å¡ì÷æxI’áxÝ:Ÿ¥™»YúÅßýIõèþâ_»ÿN»BIpRÀ]p{`v‘[íÍÝæî~s¿î¬..–Y°kaêRÕ ¦ÿžjx°wL¾tñ¼Ü+Õ¦ $²I²œ ÚOPLè>ò}¢0çÞ3WJhs®Àr;@0~˜Ð62œ¯ˆ–á^-3•}q­ ý}g½¸¢(6%–¾¡ªnŽÕœ†Ú8$áêxÕŠfˆ~–T2’(¯">Ûè¾ÕxöüÏ~^<‹.0¦]%VN'–sÞgƒ®ä¿vwÑýÅü¾ƒ¶š›í=ýZÏàØdïTÏÀU¤„Nd'F}$·CB¬IRÚ ¹ ÆÌOz ]`Ú!DH÷#ÿ‡FÈݘ|NOÉ_½¦î\Ñ›ÿØô ' ?½€½Ð€Ê-ÚšjÃ×b¿ÙDðÊ£ÃÑõ.×¶(,jÈäU†à}0g§* ¤ƒsÕC~|Óô41v½—É ;š“œðÑ®dijj Méÿ`)—Î_¸ôÖ;o½qá’Tÿä“ú÷G•Ûª××·ÁävÀ6·¶š­cÓóV¯¯À >IJc`I:ÛæÝ S=¹×§ÀY3ty¹œàÈè ctˆôLÆH,ªóƨ üåQ0ÿâS(°ßƒR>éÀVÁŒ  y …0‚-»ðá|®š7_^S_ØÜ'jD›ª¦¸YMj¬kC>7 îZ/­Æ8ôàÝÎûª´xE”mðn£»qðäÑ“£o³î[_~ùÅ— .JyHÆ’™ ëx°¬×»ëÝ'³ÅÙþñ±Þž×ú†§ú{§FFr¾\…Ò7”Ë¡¼êcü_˜e¸#BN(»NX‘©‘-I“R…9ªQ“íI`ð¥â¦Lû<äôŠóW}Í3á÷- Ï)-’6•‡P>(|Áa¾„ëc{sy›‰ËTÈúPìÈ4»"×H±PÄÒî¨< ?o®¬\µ¨(ÞBA!zòËZQ½A#`xâ|ž jD`»gÂk’!Ä-Bët2¬A<éâ…ïýß§ŸugŸ~öé§Ÿ~æp?«CH—¦õúþÞ>Äõö½íÖÚvûxkŒr@”ãóQ)©Ý¦u,ü¼št¶wæârþÂë?¤Kh>ÛƒÏ!”,ŠYã#uL©ñ™Ëˆ 8 CsÍ0djClf–,BXŽ€$åp:’%¶õÒÄkéãý£ùù¼e½TŒWªzÕÂ/Œ_šzѸ6_°Ú#:fZ  YÆ Ìõ æÈ°á‡5p%JªLVC\ntKo~sp”ý ÷Ó/¾ø¼Ñˆ"¯ÐîdËÌrøR~ÙýåÍ/?íæËŠ3–™Sƒã“ý}gG¦ûN÷NN¢N°d7–—!Üz1y½L–KÄXI‰!Y 43’“ÄmÁÛ0?a‰|Ðýh®˜ŸÿØ*ä•‚©+EäfË+:U·1·[ÑÜ\¨„3Õ.Bzü±Y@Y)ÍÔ}±¿dÛ]¸‚h•~À©ÍÊ—.˳±aТ¨¦™iìéÉÁÁýá P×iw†VtO(hùWˆ‹Gâ~âg$0¿ØÿóӣǾÕýù­[Y÷çøpH=œEéY­R¯×¡ÞÙolía[z³ ¸‚9 ·¼²¼¸Sk»Ø‹Ü;{é‡?|ýüŒU0íq`̹'ѳ¢÷ HQ˜*\χçP¤%:_jÂt< `u YÝ }ÂNý%3€ De~¶b]YÈÏ›vÁœ7ô…¼I?Ä2t3ÿþ•p|¬ö°üÏ4¬ˆat‰x¼F~Œ˜ap¦Á’êXWài Jo¿}|ô¼v«÷“ÏoÞlÄa ×j’1{š CWòó[Ý¿à²Æ`€Rïhÿàôtnvr°·g¨°\"çõR H½U–ª«²—É8yQ8’º¥!)!C"éÅqƒÛ‘+wy"Gé?:=° Óv‹ª6©˜˜›gó  ñ§H˜»ê¹ša[ZÁš·pbd"A× èùf…©ö«ïìïtý*CtÝt‰sÀG%æ"ó“#;¹š/ªàxR%yGÌÇLlŠ4Á§ÕÙˆQ'!–!±ï¥O¿yùðrbE= Q©î ÛRÚá¾á}ˆÆ|bgo¿qŒCá]ŒÁ¥•Õår³ /zÕõB’êÊ û“FÁÏ¿þú^Ç>`À˜Ø°V#¶J P»롘¼à nƒg½Q(d<ƒoR ÃhÊc#!rH@/´X»h›Ê)‹…«yeÞ°óŠa!êB’hê¼qíý<áPíÑÏÙ¥ÏS˜0ÚŒ0Ë¡ŸÖhHeLîg¤ÆãGGGϳ[½ŸÕ%dsªÐ,˜Xh‡—ºÐ‡®d.+üÅ—>'õŽ÷öôžž“ΜŸER˜þÔäT¡æ­ &&•«’ ¥HEÊȦèÁü¦$!“ˆ…7ÉÿñF"­­’,´ë¡)(ªñWWuKÓ,ø¬Y„4hIVr>$œLËq Ëp³åwE‰™q+ú%³}Ò0$·X'™`¤hšŠä¼ˆ|UÃñJà”ŠAáïÙYòy,`5UžÒÅ4_x7,¥Ù³Ãî~üd7õîHJ¿¬Yw‚Š`]ÂZ„5ëÛÍ6]ÒFk—Kâfy圤f$QÕ¸@È'¥id¤oöÇç.Í "A üôÚ/Y É)z?ÖsE°&uòÄPP†âÃt‚Ä.q<_ÀÊèŠÒwS6gë†áXÛ öµDYÛ´æ¯Ù8é`î†Awტš¬öÈ€.’c¨œÛ* ÔU õžk©ØÔL €MÁÆ`ãOGÏÐÝû¯ŸK_~ Øá«â¶]90/ä—uº¬Ýü>õ¥éñþÓ½gFƇûá ÎHlQDM\ É•€Td)‘KQB\ q*õÍNH„hÈ5v”â&‹²yb9êŠÉIp|¦k*ã3Óhlžá;&éà—’”R6g5Ó°SK#³¢WÁ@Þ…†‚îÏ~ññ¸G†!Ä37ý%M3òÄOþü²“û4ß§©eÏs6xŠz^Ä‘Ï§Š“àŠQ¸½ì_ŽÊµGµ£'Ÿ<ú„“†äd7ááøAÂK T ©Ic«½¿s Vç†íæÎ~k¿¾Ül:‹‹¥€{1”ƒû›•FáÒöõÎüô‡?:G˜Hj¿ìþeñx…%‚/Øå—FÝ=¿#a‡Ý·ÏRž4,ƂڄÑÜ]Ào %%-†nÏ|¡œÈ.X–Á†©CRôá¼ê±ÚcçEà4’­òApµJ"–0IBC/OâR¢PˆRã‹là_?¯ß¬ßºu“*a®@ª c÷ÐBr“ ¼¬üîM¡6ÒðÄtïÀÈøÔpoOßÈ´ä—©íÉI‚ã·j a©`•xBð)˜d w•¶$±J;õ=áûØj\žá;¾‡5ˆfšh¹qiÆUá7GÖÀ‚|LKi#ßò•¨``¦aaž¥äønöómḎ2¶^è& C´­@n˜âwÚHýüè2ŠÃé–…dD®Ž³\ì yv&‘¥ˆÄM$ZæðÞWûûQ9Èž<{zxðP¦V½:5|ËÔK,—AVp#ÏÚ[ÍF³ìgí7VK«X…,^‡çDYXœ–FsoIÒ»/œ»€9 ìÉþüˆ!ã¡ 9aé‡_+NFj 뚂𜈷€C!è D!ñÚ&3D¿°LC)¾ 8‘5×׆¬Å(ªú•÷¯êBí1` ¯¥´Õ~«U^¿EÚÞ*¯Â¥´œŠ•¤´Ñ'eRß` ¿¿õû[7ÿ{2@B2èŠe<¢ÿ¿Ia\¥qäÁ—¦ûû!”±I"' P€8P†@–S©šfR þ&h‚àSgå`6—¦¬a ? /èmÖãE (|¨˜ ®˜Ÿšš™ÊOKÓnÙ7J&¸=º\‘I.° !XÆÄ¤¢BÈË@ˆ?òÜ.7Ž ÁßÙ¸éo˜Ô‰YÈà r‘ 7¶tȹM&‡Æ±¯gi ª®Ã@E{Ìy;(…+50¸Í‹ay}çöÚ;ð’*ÕçGOn¯ïЧ¤ÿê’j.‘#2ªƒŽ?üÕ«{¸µÝ¯WnxyMgµGr?¬/X…Á‡T/3G[q Þ¬Š‘;!©6n ŽJ½ŸßºyëÖï7?ÿü‹›ã ÊR°9ÇËØDL}…ðÇr0†Tpù pb §·oh*7Ð?4˜“|¹ zQ…L3Bæs‘ùQHKJÌØMAhxµõÕþæ9…ò³öôÛ£ÇvpÄ"ý•’[»×Ð'vâ*ŒÀ' ù={Ühì·Z>:Àǰx+؈ƶ2¤sà4¤™Ñi¼¿·wPê—ÞxãwÞ…ƒ3MÀ@²??f®TrƒÝzꀛ.?½?A6HvòÄ‚Œ8ýCˆ'Ö!³‡Å&8÷1†¸HózÑÔæt]/èÊ•ç5V{ŒBJäkƒïÑ6Aƺ d~¬(ŒI`ÂÅDçFýËÑîOnÞ¬×o6nÕ?ýì‹ÏG&ÌXA(BL‚ )îi# / â屩Àè>izx¨¯o` 9¼!KÈŒàË«åçq)Ù’¤B(‘¤Š/Ç¥•¨Ђž°0"Bw•öØx¡ŒÒØð½hü‹ÓSÒ d†Z6CÃïiöwW Ë–|I²Ž—vç˜ZÜh—k7U‰Žÿ…Š fŽ;1Jìï>æ…:õ\ÓØ®ã‚9ûvņ8¯û<„åÕ/‚A ¾Û0ܺ½ŸePŠÜHß|ûmÅ{Òñ¼RFˆ€Šï'Uf &ú³Gh~i²¡¶ñàêJÐ ½åë%0ÁˆöÇ ¸ŒJ}g¤Ñ¾Sg†¤^éÍ·ß•FgG'Õ‡ Ù¤û±Ç+Ê\Q‘áaF6G¹Xž´^˜™rúÖÍ:¤€·êŸ|òÙg½Ýc„‰HÚ æí]²ŽÐPŸÉŸ‡Ó#Ãýý£ÓSgF$I—0C{Ñ¥”= $C·âÁ`c’ <`%&‰cL‘Àë`·`xÁc©LMŒ¾1:;;;íyª®éˆµÀ¬#W$Â׿íÿŽ<7;;9#!óR™IdÀqu¡²ú>[7^Í+74H*s܉Á™6·¬%šf®–œÃ¶‰ݶ=¤òL—’IH†ð W3 †oGÙÏœ «9«ËÏÞ‰$òåÒ ürÅ $Ö|üxöðñ³Fƒ¤÷Ú葳ä!CÛÊõë^@Eø?i¸Oè•&Gúz΂JRÿìèðLãaÈñ—7ÒÙ²¢Î0½œ˜çt\Ã[㉠IDATSc˜ (Îýð¤4Æ_ 0ìì—R–K$\[Èc›ýê¦bE¨wu8¯†®hº~íý+ªš/„ ¡Œ(²™·É¥F4ŽBÈvÈŠ*UNq?¸Qÿì‹î¾zýóÏë_ÞºùÙç½§ºG  !ÎÈXlðÆÌaJ™!r‡Ãm¥*9H™Q k_°¯é‘¾³P²a'zÕ‡B[e°Ç*Ú,d1ãR5‘ÃUTP÷1 c†Ý!ˆƒ·,Èë YäVÁä¿\&r,Ï‹’ÉÉ‘ñÜÌÓSP•馃=°Rd†šŽU+ŽààÛʳïNÏHÄyT&BvÍiVÁ†­Íït×д9:1Zì£ÒC€,[¸í…HJA9pÕ]ˆÍ.Näh±Í£Ì(ä8L¥zØî"Œ²•pÉ•«a){|Ùý/Oú¯`ÉK)3¦@¥ñÍã§Ÿ>zJ懧»RÙm7>k´Z·Šåo®.®R R“ÆF¤¾Ó³½ãÓ33³Rÿèif|¢á»hZÈùvEsO€žÁì\Ž®’™–ƒ|cØYá :2ÖÌ߯ŕÀ¤RuÂÃN^‹3ló/Ú_>Ôç S…[ÇyT{E#ÿá+MEµÇH´fS Y%î*Wˆ¦Vekˆ©¦qH¥ ðgŸœþäË/ÀoÝéëí¹ybp× M!#bUKŠ1’y84õ!Qx“åÆFGÎŽNMBÄÉå2t‚q$û5š‰È9l%`3KªeQ†ÒJr&×20[R&~4l>ëP‡]b±Y¾)Ìå†Ç&.MÍäfJšÆë˜XÿÞð«øR·ƒ ¬Dšž™Í¹ qÖ™ëtåá6 ZÖ l˜f˜7©“Ú\^7”Õ'V#¦B†Ž&ï÷ø‚>”;j‚„Ñ0œoÁ­KËY–\Ë™ÿô0 -ù`HsLùS°¿Æãçž?FóÃ:„Ý!8@ÔˆóVø¾Ð¹¾˜°öõKgzFÆáÂMMNN`î7;Û¸ì€ý ý¶Q‹¾€Y±ÿéì,ãxŽ£©(QxÛƒP08dÔëz‚ÙRØ%¨âÛ~a›WLõªrÍ´4œêR,Å90@i‰Á3q LňW©1ò§žcLñ”æ•`€Ýýàë_|Ñ&&G¾ø´þåàX#í̃+„àH‘¿QäÑ5¦‰¶~I0¤éÑ¡áÑØEn`pð,ÖÙZ&Çú¾¤*ÏÌNÏJ9úqS– #Ä™œ4>+±40Ë4Ðþ,íP0ä0 × ttNÍH³ïŒ¿ OgL!xÚ hŠp"_Zª›ùoOÏBüõÅ~üqJ]y=B4–e+àü ß+éy-¤N Ä Å,–£DU<ãòB2¼,?P‡2Q¢Ž`h‚7…ŠtĹv($®é7¿úU–,–ß[yúŸÜ’|¨AÂÿ—­7mŽã:ÓDñ™²%.â¨1wl‘ÄB$Hˆ 6¤¸€Ý·m‹PKV•-.¨ÌsNž¬*€Ñ1ã17Tý Ûr»Ým[ôuÇØŸnLH­_0?àž÷yÞ„<†MŠ$€BUå›ïy—g±f»g E½2‰¶‚ò{_ß§Ã?ÿÏP v½Áô%’&4Áá|>|ptèСQùÔÑ#ÇNŽ”GNös‰¿{çGw¹õBx{5 V6¯Ãe`Bk^ @ò ]NuðÐt ´Ð$å«FH“^iVÄÀ+]^,'ðƒŸ|û]ÂpÉO1K-°Ï²‚ë’ 6æ®°1Cüýú×ÿú2ê¿zõá±~è?^¿‰Âo¯^¾Ü;r`¨ULã îZ~ìÒ‰„ƒ–Â^X–Ò G¥ry¬42 ‰IÍácƒ¥1)Ö ³<:Z Ý+Èy2Qxt8~£(|ý3è½I»ÃÐ*Àp#Œ®8AtêõÿææKQIzo7 #æµ-¬R†æFE8A$D¤]é­ðÍRJo×¾%‹°HBÃXª@R··ÂÝUó§²U›#á(¨±!÷ƒ 4ZŸØÜê. HÀõÌ1mtçæµ;=×¾ýèzûfdÓè ›Ì4­ë÷BäõåBý¦ÿ›ß3þ±ÿ—¿|Õýç?ÿÏðfüÕN'ÈH¸ÏF 5Né衃‡>>128Ô¿(ñwûþÄ|H™ZqqóE°½ð£þîwý¯Â¿ýóŸÿ,Fé_}õÿü9ü©³#„‘£Ñè±Ñè©£²ï<>4Xêß>p"Äß¿=ùS·HiDFú‚ŒëI#…œ<ÛŽR =–ˆˆ …s;Neu›eu³#f7,X ±WÛ ¿ªºàæfmó'?ݬJí-*ä®°øL]Úí)ÖÕ*Æ!ºD;è×ÿòâ™à^ôõï¿þ×åÈ©ãG~÷®¯¸h¦öz"ö¾#GbºˆûåÔûcd—†GdLWŽ†ŽŸv|pìäÉÁñSÃ¥ñá~Q¡ …øñØÇ£ƒRÊ?tø@r ËµN„Žé±Ã <5&S,ÝC¯‘‹V\E9”™mQèCëY«òS45T·<}±NIâ«`…kØlå /2ª€¥Êà+Ô~YÞlÊ›(?8±„"Š´¤‚ú‰½!hè8ÁrªSÉÜN€+KW×ÖC¼ñxu-òÿ(éµçÐ ArÜôq ,¸Ûß‘t(o¡œÈ2°ýç¿üewç/_uz_ý³ì@vCcwdäØH8+ʃG>úð£C'FJ㌿ӿy2Ñß•93Ú˜{kÜ÷Êä$+ÈYtŽñ%io M:IØ”‘ª2'›^'‡N´¡ëÍïêq­ºYm†ß…›¾õí?Ä[¶Ötâ¨~µx”\ýÂã ÿ¼«Jl„ t!RÈèÝWý×€¿þÍoC\~;ôjooïíëw{¯ú…ŒÊgt‰#ø¼Ó!f“»´ÃÈÊÃåñryp°¯<>tR Ö$úöÃ_¨ükW bhƒ;.m ø‚¨Fõ) hJ4Å’´Yµ, Áñ±òH©j©`™Fó‘]ȇ†#0"-w¸i#°¢%“v'Ôá·zîÇCu*üÅF£Õ5µ¦°*ð]ÔGG‡8™ÄrÅI^í!! @ÝúðÉ(š›{´¼|óÖíõl¯­.ßòqxVtChf:FIZÙ˜Ã`1\Ÿü«¿€nǯÂw£òááƒÃ'JãC£CÇ<$¥Mˆ¿C·ïß·¿}bå¦þdÑš[nÑÈXVÓ:Xçx˜¼ºb£hª©#Ã=H¦ÈŠB1Ú‘N‚}H³ÙŒëq¨ÿÖ«Ææ?l~ûwp{´4ŠÀœ#¡œ»d!Õö@)“¦™²ÿ aVÞëEïwú¯_|µ½ÿão×?qðåÇÏfõâÅË·R$wB'Üëe )å*ÓÚè+Î7g&@ÊQT‡îx©<Æ@£8>àY²û}4ªB ÌGzÐ&",Z/¤lãýpc¢þ",ÁzšâÁËeˆº·Zã‘k-å§F"ø ÜþÔ®ÆÉ@£%KÒ\Е¹OL(¬b&’‡«#ñ›W ± 1tP¡XôQ ÐÑ)Õ©Ó Å9††B|¹…¯?÷èÖÝ[7VîºöÚÒõH8’b¹†&I´›q!±ÛÉ\SÙNÈÏúX;u•’îÃ[òÏ_íF'†ž>:¢PâïhÈ÷×nß~ìû»jzr¦MÅcÊü"Ù‰$…c¹JßGï.P` ô¨!9=Û÷ääPµ"«çÚÖÖ·•oãFMÀÁ›µÆæƒï*u8óp®z38¼a£Úôè™÷„™Ô!Äy‡8äþÛ7‡‡Þî½ÿ/|´w Ä_ˆ> @„ }Ûà¤%¦ê.¶«9Ü$èzª‘…™³jØmR]Z.({Ûsnåa’­êЙ¯‡Ç…”­ÌœQ'¦7q ¼€Û6i6=TØš2\ €ÓÆF;õjºàòÒ¸œ¢0¯C×Ý@ *÷^:bÕlƒ'¦`7ľVnyöBöwÛÊÌŠÑFŠïk£·$„;S,|ýïÿòï_¯¯ß¾±¼|½Ó¾u/ Ÿ G”•®:!ß%Î$Ç2ÐZÅ•ÒÐv–­AH”»ÑÉS‡O+ŸÅOsJñJ^JŠ%È@^¥gÏ’“ÜŽ†ZèÆ=€aär@Š’¥æ©ì2’4% móÓ¶ðµµñhl´úž¸õìÙè¨íV·ò|x¼‘u:ÒLSæ£nêõt )´ÎJ‰gZ{›Šû˜‚AÊ4ÕÆç/‰wKö!bÆ1€»œu7FÖEöO¿ÿí¿†ø»Îàµ;ݺ U¯ûÌÂ[‚*7ðøÒÌ`0½#±Ýz„# ’¿äkC:’!ýáôØRBÔ¢Ï×¾y$WÌ$ öÂëî¡—ÔÏÂŒl'„¢ïªù S¤ƒàú·3 „ÄJÃX™ŸVK¤ÂB”T„ 0þ¶5:::îó­…“³¥(ó[^•mê×hÄf€ç¥ÿD¤Å˜ý¢o †ár@Q¨-«”v‚&Ä’$™~g>v›òMß™y9ÿí÷ÿïú½;·ïܹsïY;úC÷e/åz¤(#S—*ê‘áGt5PΪAŒC–¡ß-õ_? xçþý벋 ^£d7IiзñhÙ•²™jªúôéþ÷0€¦”“+TŒŠœ ls«µùàï7ãŸV«ßÄßVBܨþäguÑî(6(FQ6¸2‘Í6 VÃH‚¨pM0íW¢þW_•Ë})|£á“åcGCF앺+²¥Ôÿ£¢©Œâ\wSNƒuÌ})“CQÕwˆáï!ŽÐ3{¹„ñfDš‚x.¦Aà½z]ò€­-¬DuöŸ$ê:&réb‰†ÔkÕPÛôikK,?¢ÑùºlY2[}º0{N0«nJ¹^¯··«•¥q’凜bzPàâ4…Mˆ³‰š‹h‚'‰"´õ|Ô áKEB£XtùÈ.¼ÿ79€ïܽ{ûÖÍ»ëÝ?¼EwYÕ‚ÃÚ35 MRd)¨çʘÄR¹œÍ92ààHôÃÇNF å1ö¿#÷ûÿuíþïß¿-nÚ^J󎢌—×}þ#çVžé‚Lõ,=mEÙsx£`tÒV.‰£w&É#njß„wTH!Õõ­‡[âa©[Æ +§Š@ÌŒŽ¦©¹l IPFËê0ßH44XzwdøË/¿ 1øô`ýGdM©mBV+õy¥ q—(ÙŠÐé­‡øÁhEª=ÀiÂ'`'rÅBÅ|æ$@¡=t¸qÌ™bfO‘@i?Úi}£&‘P‰ŸÖjiÜˆÇÆK~'mw‰ŠËÂÌùᨓÕj‚¹Â¥®TÂ×Wø¡Hì!¦$%I–Á•É‚ w›šà´"Iiõ&_ e)´Ÿ1ä"FÔr‘kB’‰Ú ø÷ßþþ?B ¼¹zãî½èOVׯ¯¯GÐçì]®bÎTò<¸<¤¾%Û ŒïÆîX9:|´42]\X@ü]œ»ØÿbíþŸòß~vë>Ð#൑½b I©ÊçЈé¼ètý戡7…Ž¡°WZ|Ð5t, Es­úM5>V½VÝü¼ñ`3tă)<Ì©Š²RœÕ) ã4Žÿv¹›“7×uûç>øøÃƒå¨<Ö?5‰À/ßõCõVHÛK ,A[PÒÏÒªÆóxFÕÖaðjGÊY™uu3ˆ¿Ûd™òa”ȹ"ì Áv4HŽYPžÑ$B¹N.sRK¤ýpf«ŠVõ`½"§S¯[FÇÆ"“å çK£Qèzª›(î° ©ÇÕ8p<«¾,L³0¤Ã|˜ö™Ú¥ $á–Mx44Iø§Äøä"g\ˆß…÷øÝ¹Ç+ ³ÓÓ3Òvþ'³¼¾¾¼²N….I§0ކࡠGŒâR ¯-Œí(­BGac9qìT©ë: !þÎwÃûõúûù/’»!¡s`Д†QÖ•õ)Nª¬b[+³Ö4û«,Ç=\(t9ÌÄXÚc„—œˆÛcMp0ÍfܨnnƵz³°”E#Î^s©Wi(஋Kj‹§,\ÙÐÃî|õÕÈÈ©¯¾ú²Eýò;'ôûÄ<ÅD2†ÝûzΛÌiÞÚ¶½¡zt.F3â—ºÕ-¨`]Êžwé:jJÝ-†û¬‰u±¸bêä¢ý…ÑöÃmmÓl< .ÔƒõjC‡=å1AB-\˜™/7§®Z©êó:+‘æ€Æ›jɸMÔ‚TÀÙGÌá°‡I(Ò ñ²Ý–ŠÔ*¶F.¬ÚÀ&|&J: ÿñþÜÓkË+w&Ïüxûbå+ë+¡]P_«¯¶cÞXô1ÜO çxË ÆQúøÐ‡Ï.tž.Ü^8ßížïÿ—õpÎ'O~ž÷wi#êß"[`«Cq[4 ­Ê±ÒVÛtÜö™®ÐôÀç.Ï!j©K†‰ŽM áä¬)ÔÕXZÀF£ò°Q}תãϱ(%Žl¢Ñ×µÿoäZ4ÁH8]´ý×CÇ÷¡ûöÝ—}ÜËJ-H .(¶õ¼úvqî‚<ˆþé,&y,õóÑ÷:PØ—ï$ê­KVèðâH¶—G­Þþ*‘"©IÚ•D÷*<›‡)§6ÂŽÞ©Ý®¬“x|¬|ana¬NÜ_XL(œVk›õú`¬ž­tý ø4ŽEê­ÉÓô aˆ3 ‹¦iS>0„‘‡‘BfX^,Ã=ÙŽ_¸ÞX^º²²|ga.ÜÝrk¬¬®DNÍžÐÉí …·æ­FÌxJÜ;ªî³ _³;uäàGƒ#ƒ/ü‘›(r!»g ÙÚÚÕë×?]Z]¸{o=2&Z_‹ ‹WÎ\ò {—Zó—ýB› ŒðÝîXtâã“#ÇY蘅ÒÈH¹ÿ›[÷o^¿wÿÎ=ÁÂ8çô °Ô"ó±ÔðŠLj5¸îÂôÓÙbàXàŠ=ÉΔJø•¤0\51qm6[õï*ßUëqs£¹!6·Ž×'M)EíÚÏôiAŠ·9 ë´9jÉ–¼ÿúøG_ï½xõúÕ›wBÉ„¹¯Œœ;€ˆ™Z‚ Ò1‰,åu%X{]f „Ÿi ’ç…á\\wéQr O¢e2Å(ÓK¬ÂòDâ:‹K—‘öÚpJdÕj5áEWêikxñâ…óç£f³ÖÈêN*7³ò(¤Ãj3mÎyu.sÂ{Ñ&N*õüLË@'óbN`ä;%ê±.€ˆ Ótб¶±’n8§Ebmùêõ+k ëwîEé¶sQšò^"愎–¨ï`÷ûÚ}YW$û,1ÌP|ÚFXé#Ç•xêã÷dáÔàHÿ7×ï_Ÿ\¿÷Ù]A¤fÂ×K¹æP“,f>d’^X BŸ*ëúÏÎî³6¡ è–Miô„û'5XxÊü]£Ui„Sø»j „7EýÐ)™ÊçÈ„Euehåˆq3]•½LäË£?z¹÷âåÞ˽7”É/$#åø5b©ª«Ûfp©’Ù0¡WÈlÂȧu¯«û9‰9Š‚aËêœöHЫ¥g7Š×B÷ÙÒNý¹dÿÃ0ü"€jNrSB¼ßªTÝèh©„*p|üÂÅÝ¡Ññ­­8¯TBÞ ‘ú¤U‘ Nêx×Håx qú\„–à>CKØF'’ä@jµH˜÷ÄÒOHEØFÓÎÚÎD>D›Ý]X¿»°v}ieáÞí·Cûëv%ÑHí ½ÑíÖ÷¸x:+©Š!§Â£¢²‚$ _"ÄÌÇžü`ha§½0xl¤ÿxíþéûëwÖd-³7‘'f7Á×ø}æSÀ•ŒÎ$¯†Þİn•OíN ½,î‰ífkË·ŠM4î oÕCäIŒ7ÍgÚv`¨ªs,µfÂcMÉ€kàÎÃÐô¸“Pè¿8tøÃ{/ž¿}ùš)°S¸)„Ñ"Gá‹Ã«ãׇï̸ÎÐ]® £ïPPßÑeëK=t©;Øøö ¸ f †ÅNMT›Ðš:ÿ˜e&<¥¿ÛÚæ.W^]£ië_m5FËCƒ§†ËáëøóCуôAÅÖªµG©P}ãŠ8¦‰ÅÅ€œ&WmqY⊆ŒüpC1/M9øI $Lo¤W‘”ˆãšT;1̰TЦ²NûIhT××ïÞ¹´ºòß­ËQxyÏÐB& A…œl opÈÏT±LJA’ñqÿ’Hv£áòBtdøÐÉS;Î,?>„\¿½&È‘2ÕÎ*ðû̇#g¬ïdâð%N¡±1€G¦W5¡Ì)£)NKK³4î"¥ )ð»füp³Vû®^k6Âÿ²Jä9Á! …NŽ ‰Y‘M²]„„é¿8x䃯B¾xùæK`§§>„âv¢û58 vDƒÎêÂ餅ƒÊXаFšwŠ 3Å…¸>ùu^í¾ä,{¢”O©ÑÑ0þ–`›Y‡eh?DW.bÝ´¬‰›êõ(ÄßÉ•¡©±ht¾Ó;`}»ûVøŠ–°;êõøQ¸œÕZu€ LÅŽ\òÁ…i‹A•ËYW£ÒÚb#à Õ)L!å8Ʊf5ÔoÅå‰:é“¶õ wîܺ³~éÒíµÛ·B÷ÑNzx¡¢‰Þ®ºÒ<ÓE|&Ë5šÓ:`)iWÄÉK.tMtääèÂN²0|ôxÈ€S÷¾ø‘¿þÙz—¤ßTVÙ…c˜Ž¥J‡XêgurD”¨ÙS¸\Ï–¢EãPˆ|I:õV³„¡…2`³¶Y©ÕïPÆ ‡ã{äÉkÏtÉrÒ*+™u©‡DWx81!ÔYrÀ£¼xýòù»"sµ¨ñ¥NW\=jž,9;;;¹à ÃûŒŠ?ø IDATÍF8‡A6ïŠØ9ÆÖÝ.:‘\qÝžzmñ Z:Ò8úSëìWfgPÙLi9T¯‚¥Òàái5¢áA·ô¿‡q]>?2T%íz-ôf©©¥ãVïàÓ¸2ày÷Þ™F2^ ©1i5vͦÛõ- tTH©–pâ ¿ê&AÖ(r¬¶Qó¤ð,H,iupmtÁ`o‚iŽlóŒ*ÉÉsN\Ô~ü‹í¬»Û¹sçæúÝÛ·×VWoÞ\ ÿH7Å\KÓ,®du_áT$ bƒ–JÍdz Ò#«5*/‹ŽŸ:>6ÞO³[韸^×+¢Þ²Éœ@1ËB 3=¶Ú$Ò5x+¸"«µ˜¡ßXA"6¦œ„»C j«YÙ y°Ò(6Óm¾î„I%1°Èv…†«øœ9q˜’¡CNU™¦¼{þÑóÿþË7¯^ì½~ñúËwoû}“yGº¢Ê¡~ÕœªxÙîb·,é³áWÏâžWt?¸îÈw$ýe=–€TK²ìrËí»£ˆ Ð3ÎÏM—Ax Ù+³z%Ç[¹ffF†g‡GÐ×76ª§õz'ÉkYþ¸¶^}§R{ämnBÊ9"•UÈ}(Ã+3å§ð9BÁ—5¶€Ì´éù›*ž4¥ù/ÆHá5´E±?²‘yÜé=[ð!tïÞ¹³¶vÓ<~´ð c740 'Sæüûëâ9Ëh¼JæšGb s`¾•G95Z>6t</gÿþ™}ò›'îâ.ÏRìà A¦>St¬³EbD*—©%—·F RjŽǵ((žBìTü,Þ†$$1n ío³ÙˆkÕz½enêTDE‰î™¶õÜQ+>•-}yF2 tµz÷«Ÿÿò¿¿}õ<à«wïÞ„ ØíS˜.ö¼^VôF²æF (!P=`]‚€(ÇIz¤´C>Ä!‰—ð§–†ÅQù %HD§8{ ×dèOCý—ìg ($!Œ•o>°¦QϦ¦¦g"Ÿ JºWí$õ8îfµ´76œ ŲËåB†&$eõ–nŸ3IIâIŽ'(ùâì%¥Ø²&M1-–g+Ôe‘\HÚ!®à¿+ 0(zºûl×-\ºtÉ›/=N/]Zð»`F9¾Ê¤üê4¾ vO_\ÃÙ`‘Œpw£ñÁò¡ò¡ÑáèøØh48:ûxýO~cs4Áâåˆ Ó1Ùq¸Gâ©™Òø¨€‡§‡ºçV˜0yÑ9/'·Å*ãáÉIÏé¤Ûï¬n‡2Yua'5âpØØÐÛt²NŠ£Ë{©J/+Sé‹l!©óxÑ\ÔÂÃòݯ>ÿåÛ{ýüÕÞËWoßî½ëw‹ñ^H`árÞ·ƒ¶¤›+š/+<.w€îïBßÅ Fm‡@¡Úõl|¡Èvš3XnÜ1¤¦ A8zyŽÅ ·²€ƒÉT¾þ^Ù°i£VNèÖšÍGYÖ u_5T]æa%vµM ê ,XjµÚ@8tŸJÈ·qµÄ‘U1/â”)m0"‹PȪbÄÒ…ß¶%v‹,Q%@)†oÄá ÈlHÛþYfÖ×ï]ÂÇúúB0ôÏä–b[`ö—.%ïBè*l%Á—ÔKGˇFŽ|ÿàÕó_þpïÕ˽7r¿ ]ˆ B† Þéž= 2YÖë#ܺ¼Gp`x ñg焦'š¾™×£Ó˜^ünχÏuØç‚,qæSE¤"aS ¡ØGR3ËU6Â1\ ïS%Þoà̼µ•éÆC™\T6ærgª!âXšßG¨´mÖh‡V·-ÆÑÛ²R¦)¬±rÚJ¬)LD3œ“m¯>X)Ï^[ SʃЈ­ÄEÝ…»ílýæÊ¥{·n/HŒs\Ír£ÇÆÒ xÌ}MS¯1(¾´Íò8Šmˆ¿áã'KÃGC÷1rrøÄÇ'K»ý,ëC*_®¶7‰îZ1Üñ8F “w^ù&еòpÆz˜M Y)@bA^žËDº4›/<`Oä:2g X{X?ÿæAí»¸AxWÎI #{;„râWÇò„B;å=ŽÞ½{uà¸]Òè¨×}÷òƒ·Ïuàù«—¯ßî‰uú»þ3;‡ÓÖ$™–o¹ºíõ ­JöJƒ,[eZ…·Û3IR×)0@l‡q~KËH¨cèfû6³: sÀÅ1¦»a™A©ÌQ z†ÚVC€©á¢Æ›vÖNOÍÛxºöó¬ÊyÛ }škµb]ó.; Õ<‘B3r±ËñrÂVÂ*`"­ùo`¢Kl!¿À:±"9DZ,Šåðì,æ¶ÑÂÓ^¿ycáÞí[ ,%ÈP^)t«YAB¿=ãÔ múEç@4Œ“³s7佡S§Ž>t¬4>Z:þñ±Òîn_ €@/c‰aTj{ ¹=@Y^†½§‡ñÌOÀ"ª§+›’x3U{“!†háÖ÷â/.v8ŒÃü ÞŒ?ÿ»õJ,ë¹ÀžGWº5?0YRM™ËQ´—FGbrÔïFG!$Þ½ øâÀá½W¡¿Bì‹bW᪫|¤$@ß# •¹ÌdD½ç{‚=w9«Á}*ÐX]c¨ŽÊÙ»¤ îRѼm[ §¥ n×9©á`¥F\5µ ;—ª™ÏMÍךÓÓUð_«sÞvê¡ä­ &‡«üûPíT8Yµ(íÓÐú¹xÜÒ@>1ÙyCè;N]«TaíhŠÓ9DåÂ]o×oÜZ¸}[Ñà'†+YCv£”Ù‚“¥k®òÎìsÃÔ.^h‚O>rüÈáLJƆ‡N=íú]%{²ÂÀã²xT}6(¶!ÅXT²gTjV¸y—hj(Bf9iËчc »Ôγ¸Ñz؈kÿ¿jý›—_š¢CÌæÝL ˆì°jnæm¨ŒŽÔä( ŒŽBXô÷~øîW/~ùƒ=IP*—µwÔ€iª„ó\™çäZR¿¼§¾ hHz¡Á¤É¡ÇŠ˜€J%`é'ߘËÍâ• qäx‰;O‡´#ì²w XE þ¡ii\‰çG’’ª3sµê̼©Ÿ;åÜÅ·ÇiÚŽ`5ô@D9;À¤p¯LÛBüÝFNLÈI’F‹Ÿ§á{Úr<`ˆÒ4£T[ <=¸§N±%ö~'Ö×]¾¾¶¾°¾~6PfU†TCø(²‘\1¢5s,Ðx\¢D”ͧ‡”úˆÝhxhðTùä‘ÃÇKQT¤]«<ãNoø8ÉÚÂÙƒãã ;B¶Æ— ]ÕöoUÚÔO€U(iR‹Ê‰ S7ïÂ8®=ø»¸þÓÆ3ºùöÈ=ÂæLKI•ÉċӢ@”=ésÔW·#…€é¿ùèÝóp‹LùÛ7¯C#Ì5«®PˆrŠ¿Ð¾UÚ\pås*óëAf“ ‰½ö(ø2/ ß"“:E¥¡Såñ±²¨EÓi#<Ž;[.)vJ^ç}‹ÔA7VožiÓ±|ôÅAéØdªòÆá±³ä=Ò©Hö]¾p{üü›zü Ñå,”SNªüNAÅ£6 ‚beM:òßÜ„tž=ë÷?zûòWÏCk"éoïµ ¿×NCT6fG™nÄ›bÀ‡v¸Ú5\h@/ ÈHœà˜{Z ¢Ì÷íhÀ‡4Nûy,„k–Yέ·ž8“˜EŠP³Öª7eiÌÌôt}cêÌü/æfM[Êí…9BH³,©Õ¬{ÜQ@ä€M0ûp+Çýs‚>5!Š)qÙ~ aèÌè8¡gI~<±ŒN;‘‚èFó²†;w:š9;uÚ¨´bdáÙÛ‘OH4vFOIÕ÷ÆÌNxÃÀÓ4ߨÐH$J8#ÇOD»ôŸ”{{ŸFäÔÞ(Sž NWÖšžh›vaR‡€ç,²Ø¨èµåfNNcÑ%I)\>j´5ÿóáO*µzµA\‰PÏĘ)5J;ÖþÀšBv$tÁÔ«Æš;¼k…:pÿà›W¿zþË$CÊ*„¸ÎáP!ú´¹;PñjHÿ.˜¿ÐîÝÉ!ÓAˆ ZŠ<[ž…3Wà8” á êúJ*þHJ ]’D[^ RdøL56¶Ùã°&ûÛz«ž>•¥„9wz²²1}f¾636íÒ’IçgçQMùΖøMgJy5m.Ð8~Vò/Ö½r÷4Å-Š,¨¿-Zým¸ÎqŽÍ3· ™íIñ—„÷4š>7’ßd47É}.mþ·î|O],àÑ;8@¨¶–sšy—ßÙN<>8Œ9Ñ`CüsÿÖ;5ŽƒupN‹à)_-– &zXm‡€ê¸Š;Ípæ!«¸}ß5¾ý澩ÕkqC®»¤ Ñ)–Ôà ©…Oy=i+Œh铿ߗfþOî½|þËoß½y-^5o÷Ï`Ñ,…Äiqá[2ªªe6aSŒ`8³•ƒvhF„“Ù½‡8%Éé ÷}@tž)0ÐXÊQÔDòzÎGqUúÝz«•™XÇ2y½ÖùNà¶3§'ê[S¿›¯ÏÎλ¼TJç熴üí<L‚Uáöm ±Z••‘ |mŒeèí :_‘ßÈ EÉ¡·4.¥!!ánI¨ L! rв0(<¢‰³§ÏNNFó¦"-=:kJñ–L˰{ý3HeìËŒø 1>1 ?"p§·++ëÙÓ"‘£á —q@0ùeTb1tãÖ ˜äA°)5`¸ÐÏ$ã?ûÙF¼ñmÜèqµÅõ•tøŠIÜGd4/T¤£ËY`áµ‘Žƒ±“÷püíËÏ·.a¨¿{×ça›’ßU`)'â].…1îˆî4f.2þ²“d·œHÁô)Û‘" {X+&«g <ª5š°¹¼HÀ=ªÕ–šÍ8~l+µð†Ôcá÷wÌÓF­fÜcoҹɳg•©Éùüâì¬éÌŽ™€iŽ{:¯Vå¾!`¥:Fœ®nƆ@¨Ê¦mi˜e°H~@›¨æ„ $'Ð|:á-!œlÔ!á}‰æçÎ…ìwiú“(ï¤NŒ}]8Àß$Npsí‘yJla–Q½O(‘ ÆÐ»"•?xdäãC'Jc¥¡cdž#1Ü$¸ÙžÿÀN—¾$[f:ôl®‰F$_-…íŽÛ—LUãå{¹Õs!¶\ΞèË6ª[߈Gæ7q3@à'ÁøK=×.ÓV˜U ú)ç8ûÙé $Ÿ:}ØyÿÃ#o_¿|þÑGoà÷îKÑjËTžkc–3—’ÂÏZ/L™"† Ùõr"spÐ?{¢Ú]¶ÀXç‰FaÞ˜¥à¥ 3$…Ä$‡¡Gšn‡vôÁVÚ¨oÔŒmTëVŒ¥mZ•ÓU.ûüÄÙ³ÊäÄôüÜìHêf'Kçg‡žZ Acâ8íBj¾›s¹*{U<:ØÒ…)* €JÕÕÑ+ßÍ®ïûc«álŸÜ¤òm¨IlGè¨ã¸YûÙOªõ†äò†ÉþeiK a¦5à¾{õ^çN¨ŠT;É©rßÞË—/?8òöÝÛ½7¡On01§Ýpôäó¬lB”«.™ygGÒaOÀ«) ƒºxëôÂ%ˆ¢Õ•ÕåÅk¡¯\qiÚ‘M2-hIcŒÁ9ì:ØW9*£b¼‡ÿ>¬šmÓhÊDþ¹NW)OæÞO„žx"t!ó336-MŽŸf­g+•ø ¼ä@‚Hä¥ô½B_RݾÈ:c°‘ÆÇéÜ6’ É—'\(Àfé>+éSÞ*pPtqæô™™èÜÔé(êSVì@<ßÓ<%'%Ž(C×Î¥½ ½Ö ç ÝÍ…&äÔÈà©áhüÔØÈø©┹Ò â›d¯º·/a¡Çýƒ(RB‚pß»H!®ð³ÉT> Œx§2pV1Aä ”R» ¦8M‰6ÇÿÚ¨Õ$zÐô â´EwE`-öêôšF (3ψ1 lCXõ÷Þ~Rß«WÇ>8’Ÿ€äƒ~Á=ѹê{Â.~G'ë)‰ EÙMDŠÚœæÒöuº‘´!7–—¯|z9êqQœYƬræòÁC¥ªæ©}TÛª[ ¿U·j±xrÉGµŠéÍܹÉ)Ó¨O„3xîâÌŒ1ÓcS¥g›Mâz!$>ÎT+æÆÜºÉaœaâ-gí¶Ãäå©”—ÀÄ;Ë;y*s˜ŒbÃ-;hPxíÚŒËîhanâ“ó¡™üäLÉÏOuúæÀ‹·oÞ¼8€¨îk3Ø­s\ç÷XÜ™¥è¹0ÓG‡G†J²;q<:v|1ØÃ¿9øå‹b¹ŠÔ–±ÖGæ¾™ÑFþ?ÊNlëxî[Pã­v,Ì$!`&~.à¨õÚw?ÙܪT `€IR–”œépä¨# 9ï6jšM ¸ãý¿zóÑB¾~sð‡Ç  (#!e¶"•½.¥°((ÓËK=ªt;*¸‘© _*Ö®!ëEkË‹W¯..^½rùrµT4#~‡I™Û°­é¨JËþÍzÍšªX-|×Dë%H\ÅÁ07*¿8žœœ˜º4;;“šÙ³S3%»M€¸F¸¡àÝ€SDz „†p&‘$ذYdhRÚà¶•µ'woÒ&b‘G,±|}ø4·àÌ%áE_šžþd2ŠæfC3|&B‡ƒè«\…rê÷[`ÿWX:L¥=ªŠP7bÙ:\ŠŽ}tx<І£ÁOF§NF»|`Ý«òÑ_%ޤrn† °ÚgÀ gIq¯ähpœ’'g÷]¾¼'p–ºþTˆ‘ÐÍZÍV³QÙú&tÁqë–ŠJR_}8å¢óÁ2¯|ÞbðO6"Ìñƒ½W¯ßþ ¾oß9pœÞy'KCÇÃC¦ o ö¿Ø÷ˆ6!Jv¾¾C§Ub]Â塸=§…y´E7—¯… gðÕ+Ъ]*UË^Á¦ŠÇ‚*•d’%ôh…4$« ªã IDAT fc£c³Z½ÓËn…è릶;7n§¹éó3&­™™ofjÚ¤³“Ãå­ª¡¨Z~…H‡Ùõ 0]v80mG Ažfd IzØ–Ðl:˜bÇ Ûa>*†éýC?úòÔ±992täðP_l¬\¯£Âjª=¬ £±×ð€XÛ²Fdãþ-Z¹v%üºâ0ZZºv9êêX3KÜ3yq¢ŒvÀ‹Sºº¼þj¥ޏê“^šnÄup¶9ÿ~nÞ™ù÷fC|œž˜˜š?7^ÙÐÙR™š&Æ4›-‡ÓA&OÄ1sýTé­Èõ]§t@ÈDʶC}ޑݦŠ í6ç„(‘2)q ‡â03ÑüŹ©³“§'αû8l=ßôÃY~é”JJ„&e·°[Eù/ê(Ö·81xêèÉèØÁcѱCG´­Û M 8V¬ß?°¢5ËIªüõÇ•sD:¦W{£;KY–à/$Ãà‰3 —†.¸ÇÕø'Õf½Ùê·–ª~˜ÕóœÛ½ì{NR:Ö”¹×LŠèäN·ÿÑÑSG§áF¤‚â ¤ (k Õ„¢M”³0Ô€ÕF­ñ³føC'A½b ü’ŸhÃùˆø"ÔL¤Ar=ìCcÑ ÕZ <„ÙÁŽK¸=x|pðБeÄÞ³]¨;‡7UY˜ÅÅö ¡|Õ@þÃ…á*Q„÷g‘YYŒ®Êé>>”ØÉ­5DͰOUí L;Hб*8‡Ý¿«…NhcËøíJpùÇêü×ó3!×\œ ïLÀé³3ÓS3֖ΖGÿ‚–À¥„[t3>pÔˆ¾!#7.e¶A”K¶·Û€l±ˆ—\ö áú$ÍÊñ(:ªypNH^‹ÌxLúW&=XX„ü…EÑ€fE¹¦FDOyQsK%þ»=…{þÍåjBñl:2dÀIÐg}ŸRîm1{¡gˆÁ.PÆ%`Ä”³R«Je¶U·ÇðKŒý(Ø)Å x¡´)‰Õ¡7‚ßê¡,¨@Ïe¦±rîÛ"ñ&AÓ/>èQ(m¯öÂBÊ UhÂc‚ÏêR}Ã+¹³Â.×Ñ#{seqéÚµkKQt-¢˜‡T“4P±d+B[’Ú²ï™zÂw`$hµºñµÐúÞ“fk~föýÜŹÁËLOžžœžŸ˜qiéôðXEfxÛ ­ ‡rÕßmÝÆ¡¼¸Á6¶¸2ósO“투?@‘¾yÄ¥L•:ŒL¦å}ƨ&¥¦ƒã˜dr( @bIF†8Ç ‡´†-8tÕÓ'¢]N²x¦; ÙÃý€á†ßý?> ¶­ÊgHµ!OPÀ³YjUÓ`ÇþCPù€äQÔôú .5\;Ca¦°~‡3Äeº¡"´8lƒCøå®°Œ(‘ *„<•N‚ž[øÍðU‘^.M·-k|h ©c‚¶·JFR“Bps¹*­#{ÈzXàaˆ}ˆà:Öª„Wjs°úd½ûh7ÄÞê•ËW®.^»,)ÍÎÜow)(ý©Š<`IÅ[×qÜÕ¥>Tq‚Ovr ÌgZ-“ÏÏ{aa6¼øxjêÌééKŸÌ¤iéÌ䨶òôå ‚Ì½«:?@X2ÉH¡¦n6`ÛA:å-¿ ¯. ÛNCúº ¡ÃóþG‚Iaè˜È„D^4|…Z¨1Ú£h(›ï)…Ëq¢²\‹ŠÃJêM½|ùÚâ5){]CQÀ]ˆ }(–œÇ‰f$•¸zT«Õl‡·$n™Ÿ×âðÕ6o…˜Ÿ}rफT&'Îþîtyb:Ác5[bä’çëiÕUÈoc~¥¦Å²6•¯ˆ]M¨ý‡q’ bzˆ›á˘Il˜múšŠªEÆÂ™luÈ1érøv£Àã ÷UÁZCÏ[,+T»QžˆÇ\ ïÚ:ÄR½Í@`Ò@~€tOÜRF·ûŒ\]‡Q3+Öœûà†÷û.4ÔT€ë‰ü$(‡B¡ Šeäíj¸z+HÝxã,¸öè_xl{5‰€&¯†¾Ix>(ö :6!üy_‘£““vUS*Ð6íoUaÑ* U,Yñ©‚ ¢îö¢+ËKË«+K!ÞŒ"¾Ê4 e1š¸ŸÈr íÊ­ß|T„±Z6nµòV3¸ƒÐkC©wz¹áDeWŒEZ?ÜÆ¢p$…ËÀ¹GµÀ^®Ê¨8ÚáÍý€ñðÞI-ØóÑõÕ••¥Åkׯ^:é«6ƒ8·bÙ-wª†{aöý|…Y³–Öë‚D O¥"»¸:uíÜû÷Ó³ÖÆ¡ 9;}îÒäHÀÉÐ —JÚmTÓj5üÚÚÚP@«Ñ»ØQTL^ßv’ŠÎKÊI^ÌvšµC©‚m £7(Fª†E<`Ö „]¬\Dˆ–˜mR®Ô©Pz"Áæ Ázlò½‚7q®A&º´à®;=¬àµî(…dÕ3ƒå§òŠèׄ“YVÚä‚8»¿Ø8¯ §{)0SF'g4ÔR°à2gÚE3z.ðH‰^¢B‰ÉÛTïxŸíï‘¥¢ Ctls<µ¼U„VN §\Í‹r"²)KÈóŽ ¦‡!JW‹9á K:Ïr*y_…úËÈ;ŠBò[¾±²xåêu‰z×.ôùFYV,Ÿ&TζA¹”»|V~@UTï%$ÛõJø®Øãc禿~?q&±SÓg'/ž=S2C2‰.•äk«©aŽúf5Ý£QÙÐÓôÈpY bùòƒB0Oä%·›¤p:LÆ3gsKIQÓq*ðñ^È ‰S‚iq§„‡ý•lsô„ð¢­@MÊ ÙV¦›#Y\D𠺇DF ±9¿ŸõXí)…pë†oñ¨r$(Á©pqjúäU0ÕR©-AA¥2&EýœÓR…”’f9s,î¯VÙB×"ö†Ÿ–5C§åÔÇÏwf¾¯5zTåÈê ›•®·¢âØ-X røª¹%ßì” èƒëKWW¯-ݺ¾xåÚÕO£ˆWBë¡Ì°G%@ðEô’Š…­-ú“¦«*iÓÍfÝ9‘æŒÃß/̼Ÿ:}Öš‰É‰ééÓÓ“Ó¥ÉGÇ&KòùP7Vã4©ÆÕͪHôZ8q´Õ­”zUµHÀ´.a°}Cç'ýKhh¶Ù¼r2ž£lçžò;r£§P”Ë)Uì™ÙBD?#4WÕ+0#™ïYÆD`š4¬ËÅS¡²‡ºïþ¢³9'<[ 4)FW^Ž;Lš-djÿH ‡!ÈÀ¦Pbí©2€B ,áªÚÞ[‚$˦ÍQ»†‹N _0ù˜J¡ÁèTAÚ2.y^5SŠZ¢cnÌR¤¦†+c 'íÕ@Ïv`-Óœ—yL ìø<Æ…Ø»¾º¼|íÚÊêµ+W×nÝX -È2ÈÅŠA@•eIñS«ÀõèÀ¾šÚZ%IU c36I\ Y)ÏëÂÂg'Ïœnœžž9=3?=61Q°j¬xt…þ9ü¾57Y÷Hë\£còÉ!™ú 0¾¾‰ò¥8ô±·R]¡Ë‘ûÄ*ÒC20os¢Ø³FÀ–•é©Y†Ë.jX”ª‡¨)WWÔËÈT¿E•õØêÔ‚!ëá{X¦palP¾zªÊ¸T4‘ƒ…8?žåžº˜”>‚%‡2&ÓæB¢âghbGq­6ÉX©å¦(VÕú'ÚÆ³&ÄÚ¦…\8ä,@ù¦Q~BK¤;¬¨-4›qÿªJ‹UǾ2˜° ¾‡²¡» l9pÆ¢W‰>èÒâÕ+Káô½ríÊâòg’———£Èj1Ã=°Hˆ…ß"Ù€Ä"©^ߨØbŒ§‚Lµ6ü“‹ÃO›Ÿ½059qƵ&&§Ï àädi«RèL»8å"[ÈRJ7b >@HÀO·%‹B XBmü¶âþR*r…v¯gïB<‰l™rNK}жÓ=ãEïÍaÆbžÕJ-t¥ Á”Õ„QãV8Ÿ»l*å­r„8‘à]Â&0>ÓãÉ‘³sšÏxsÕ¡ðÀLõÕ&ùÃé ÓíÏž­~­–vªŸO]ÊQ]–ŠúQ½ y6‘±<ÖR˜rMÂTèÞÈÞ,”Ô± ðô‰ÞׂO‚.)Ë Áôs✠˜±à)mCã±´´týæÊòêÚÒÒÕˆ‹+Ÿ-‰k•`®E”´XãL'¬*<4ÉÀ0êÃ|TÞñ¸ò b˜ò!6¬®×z#¼óg¿ž9sڹɩ©©³“å‘òD©<4Q.Uë[ãÊÜlhABøÍÇñ…G=PI°èÄœÀÛI¢è|a¸Iã¡ L‚”Cm¶®ŸBö† <Y‡ÈnR׺Z[£ ª†2QD;¡çÈÀä¾€ž:½Í¬ÒÓ­j+©âJ1œ²¼ì$qdÅîŽî4ŽK_Øþ`=¦Óň6êU£Ó?X¡dT~pF‹UΪ_ÈX¡¢z?Õ­’¥Ò?g@)¯ù•À|‘)òü&>× ÁbCCIe!Û¸”´IÂ4©XºïYŶ<-¬L9@`:­,]»zåÚòêg7¯ßº±z}õÆâÕÏB+,5áòâÕËW£‚ÁJï ãX_§*c`“d› m‹Û¬:Y!VL½nê5ñvóó3_Ÿ:cÃ<÷»É‘K¥)$Àjµ2óÐVç·B`~:ž€!ZXIØr:¤ÐB‘ä>öSîNRŠÃ¥h õÉå™ [:(^d®¥ûÏI6+ÊD$B'lNAÜ~dL:6%$ åoxng•äˆØª#ê A÷JÉ–p¬=¸ƒSa4äf/zޏï3$³2–>…Œ–Ó°'2ëlQtЉ£ÛÏ‘#]6!|u>Ó?y<Ñ|û)æ'ŽT)ôû9nªDWÕòäsKL„áÇ©N$ûÎTëA•­/¶*4bƒÝªåÄÔ9A |úi8v×®¯† ðÓËWVשּׁ®Ý¸¾¶¶¼¼©.U“¥Ëj0‚[zÇkçŽÜÿžˆ˜ÆF8ZåÍÏÏ~}úÌ„™œ™>=1;?==6=9\ ]Ke«žÌWM%©Ômµj/HÝ•rŒœ::mC˜ˆ#@eUz¿m8‚vØ*ËF˜Å47j„&Ï2gŒDV슧BM;a°û"¬tq\ZŒý¸.eíäPˆQ_^m’,)¤¤\RXU&;¤Íɧ𻅻qÕÌBìж8èîzå»"êˆÈ†JÆyNò«“§7áÌÅ îTD£?÷WJÔ:ÉVRpf¸idšm§„:rÄ3£#SL!fãh…×F3oG¹úTÑ*,­(8XMu‘k þ‡T;´¾Àk+·îF+ׯ…peåÆòµÅ¥•p8‡Sx)ÂSòi+?ˆ-‰ææî3LÌBrr@l=©Ö+,’Cò«›Ju[þ»N‹ù¹Ð„œ¶“3s“¿›˜.MO—'&K¡l¬\˜­§âx³RݬÌ͸ó²Å$ƒ ¤§ƒìѱp϶)bN´jÈ~ÛT,*v &¥ p"ÏÍͽŸ<}æìÌÜÜä鉑òTyrb¨d+¾z~&œ¼®Š •àÌ€'z2£œQ½AuK ‘–>Ab·OÛPŒNUˆÁƒ• 1bCÒ™œ{”W”ÝbŽsx[lQ1^/v j ’Q¤DLkµIÕj C:§ÌÐòܽY-%aHýj¶È¬ªT“ÒÒPgÁŦؠõ,@6ûaX¸xð€o8€‡†’¶µÌÑ^ä”TixÜr¬R ÿ5-#Z=@8YÖ¥Ž0½=µèÃy.oÊ|MªS7—ש˜¥ã1Å|X?5º1~Oe½Ñq!C«!(èÕèê„W¯-ß^ ÅßÊZ´“'OwŸ` Þ‘23³Ý~ú„y×Í{²R-&2Ë„{'Æ\¥žH5æf&çÞÿáôĹ™ó—&NOL—'K¥ð~–²óÓÕ Õ³®²µé«Ù…¹é¬&Û„ÿµe×Ëý´9¨â Ä'A?—>XÝ‚±àVù!y{Ð ð4ò† £Ü$€z R„ÚpÌëˆ L^8б¶p5·û¸y¯« „r&¸ˆu’¿SžZ„"ÕØ¢Æ·šŒ”éÐé&˜ýw! ¬ cÇ'Ž“ßPŒC)2ÁûÖøvšÂQŒÐè'&yÖ§Höz爼´§ÏP&ÊÜ™ÙBÕ¦*Ž0ˆ)!DÐÑÓÙ(–³?–€ìÎäï!é-  ©nñJ´tõʧW–>[¼rùêâÐñó/’ûŒsÊ3§TO­P(REW¯-®ÞX‹\§ã«'dŒ˜ôTk5Œ)ò©¹¹é¯ÏLœ›>?;söô¥sÓÓ“S%kK¥$;ÎÌ™j¼UÛ»à  ¼Ï ¼j” u]{» }|8)ȧq¡ÞÆ TÏdl‹åmÅ;gµžC©Å ÇXb¸ï—ÃÞª÷Õ­“-’š+Öl²@BÍ”Ž\3dØŽ¸èT~­ð›õ‘Wìx%‘÷«5ÕÝ$Ï)ÌJ½»ô/¡uZ ž)Ñî`R•׳b™:–$S)õŒÅ,wìl ¢{¦[DÝ) c£ûb5-HOx±\‚£0Oî0Oˆ:Ä Û¼juj‰Aâ¼U ð¸£++ËËëëvÛø(Z^ ‘tùÓÅë”áP¾{ëÆõ[Ù}:ïèœê•fåžîŽ7ÑÕ«Ë+²¾» ÆV½ ÷l®Ôm½¾Y«z@g.^˜~?11u~æâÔé3—¦g¦¦‡K®ÚüüÌÌ…jÏÎV«>?nSu\—$Ývm ëÏB|«Å~Az!`îEN_” åCP#9Îk@¥ 3 9FœSó,X>°Î ·T×…`w§µ˜Î-:l‘µÇÄa³ e\?Î2¤„µ w¡¼JC‹Sž æÑü#s~°˜ÏaJÎIµ/¦v–Ɇ«Ø êÉÎAŸF‹ßÇê0\ªã¿âiëçL¨ C“Ì><ÖªLú…:ÜÔz–h ¬@@± éA@¹¥T°¥”·Úlq…Up¢@ ÿݾ±º¼nÿüñ“è²À°$Ãá‹ÕÜhmyiq-â&Çjn UÁSr›á£¥Ø_ˆÂµkÉÅt¹lÅ‘&|$®“†rlú⥹©ÉÉ©‰Ó>ùd¢<3snº””†GKÞtΟŸ›3 s®šççç8„H½%3ÉH‡³òÃ!°ÖQ"-°Ü<¤†R[še Ëf„ |ps©p4‰¼Ušël.•Ê¿íÈ2 ‘ç²ÚòÊ;rFËŠá4‡2ìÁØ¿ê™çIFÓ¨xÃø…*p¥Z²è•¯Ë‹å-îø»³äëä\’en?Ú9oáð8Ãp +)ªb¹ãÑ3Óë<ÝyPÉgÖݪUËÅñŸ8ó1ÄeÐ…B%3™8¹ÈãpËG"wèƒr÷™8²È½ƒÔBàÓ)…ͱU³d ÀÏn­g_üâ‹»ÑåËr®¬®ÈúêµO/‡|&£ÀÅÚŽ¸èFA ,)}³ù“ŸnV*QhW"«b‡-IJVÿYˆP߬V*x¥çfçg¾þzbjjrêôé‰ùÙÉ©¹±ÒððpÉ„ú÷ü…›-T“jhHÏÈY ( RŽ¥ØNÓíí”C˜ð‰mÑ ÝDpoµ) (/—‚Û_P„@ÊS1^lÄPäîY@‹Æ<Çpµp¤ÿÕÕÐß7¿øÅýhuíÖÚ­ÕÈ~/øŒœ âPÔªmÖ¶*›õ­Ï·Z8E©›Ö°Y½Ñ°¡ôÓÉ+ñS¢¶ó|~zjnêýܹ©¹yG=Û IDATO~|v¢4YG°¬B1c]µ³UÛ¬lá>ðÔÑ ¹M¸¾`]äK$B/Rr9Ès)|©o'D‰ˆq°0\¤‡(Ó¡—–kŽ8÷LÈ@A”Â’P‚A¶6G¡%“ç<+Ò‡ót×Už@103ê³ãŠËœé‘›Á憙3 ì‘9œ!ÍDÄø7ƒIuNÞ‰Ë ÉB‹kø,Sr(qº©q ŽÈ”àÑ¢}=iÏ^$K­j‹°áθÚΊÝ|yNR½ìo«-£‡E«zW)ž7eN…ÜWm ˜ŽN±j°#W˜oݹ¾rõòåËW—Bù'ƒékW®-Ý·éúÅÅ¥¥å¥Õ(-ôQ-œb·•]E­Ö³¸¶ÕRù,PÕj®ÑØf½’ãVˆFºƒgnöýìì×fÏÍ…&øô¹òØXyâLIÞÚjUŒã*ç7kÓ­ªqV§åÔÛu)U01peTq IïžÊ͵Í!¥3í„Ø–¶s ­K!ÄR ÅRÑ_#u^‘*áyK›I ›la2ŒR§[7¶œ,Ù40DÙ:¦œX×ÄÕI,¦ZÄÓ=ls5aàÁYÄNÆ•-¾Փΰ-¹zª˜PŒy¼.„yÌÃèAp¸^Œ~E­:£öÜg{•…óB­5ìÐ !vrá¼Hœ¢N® AH[+«8]‰p*Ñ-á¬ämñÅ.Ó݉>»¾xåÓu+ÑjÈ…WB,.®®¯ßZxêòÒrTiöA]á[#÷¬~•#ÿ,j¦éþôá‹j¨ +q•îqÍÆÃJ±1wn~fnîýù¹s“§tæ“éKåÒÄ™¡’x{ûJ( íª[!š]ö+ŒJ#%جò6ÙñE꩜ ÒÌ05„CkJ¥ÜÉØ§òî”oAx2N ¦€t5ŠŽÓÆ‚ ¥ÉÙn莌 œÖÁ.ƪf½nuÖAÞ*!]Ÿ£ãh~3 *Î? “_ŸïÏðTŸÙèèš*xR;HÊ4©)J9î^SÌš½r) ôáYRð4·4ÊѤ"«§8%‡£ô¥úˆ×®[Åž)h…§a)îwÀÄZ×H_Uî-,Q¹øO†Ö×éPZû£h-ºµríÊU!¤¯.…øûôò•Å•èÆêÒâÕð§¥¥ˆ"»Ôè*$¤…g߉0 yà¸ELHŸ×dÐ ëºüaÅOÚuæ/ÎüáýÜìÙO~ôã3çÆf&NO ‡3°ÞØÚÚªVëõÍÊæfž›à·a°`ºG~}Šþ— ‡LðÎŽà­#(R•§4õBnÐÙ¦ QR¾$OœÌ¹âÄÌ|J‘§O8ÒŠŠÕ*=Òû\'"¶qû €Dš×¢!E3šŒ8d^÷ÁX:;ô:åàÁù¦Îôh& “<©9àcæË3¢Þ±ÅxHæØQœódºÕæs«d£ŒŠ—5e*Qí‹–›¯Û£ðwˆpBRq€û…da Í--Ù„è¤Regrn‘P´¼¨$cKg8B\›‚ ¼ºx}%Ĝ̣—£×€—Ã1i:–ûZ‡úvÁítLu¶%×åc¿úÙhÈ&8¼æž1U+·¥4¼Á~áÜÌ.ÌLœýñÿu¶<âo²·jÕ×6·â¸WcAåÛpÃ~ͨHð"ê S†pöâhvÿ{oÚÇye âsr1H‘¢¨ÒBRI$"K"I€ žjo’Êši>>Œ«l-–(J†Üj13â]"2Aësµ»Fn?üý3êé×x\Õ®¿ÁåÌ{Ï9odr³EÊS6§$€\"#"#nÜõÜsË¡çL`A¬–c[…¦G›îIß#j:¹5‹#œJäD¥o«ðÍ`ÌPHµÒQ]¶jUV´9LKƒ:N çeÈ+«\—J~HŽ?|ÐØ÷œS…/a áÂñ·ˆ—–Ïl.1{{ 8%u¡R *ÊË»œ¼0¶uMCNzgè"¡Ïl…Ë> Ëð‚ ^¥7Ç´Ã5lg|ZkH¾Å·^ì³vh;¤à Q¦ÓöÚWÿæÍö›ßûÎw¾ýïó×ßNñï[?x“ šI/ÊþùÝ]§|¦w;6u¹·÷ÇíWÚ;o^¼]©5Þ]ÿ#Ô¿Ó¾ÆÎÕ“4F’îïœ?¿uùâÚêòÊæ¥Í^ŠDN×ãxíúÞÇÉ‘||ñ¼û¸û8ÿ}h6ÕˆLÐ %kS‚KÓ…Öh57c‡F$f%¾z)Ö€'pœ Ãæ+ùøLÕÁ‘®™ ÆÚÞÉîØu­HFY3‹k×ÑŒ=áT¤hµrMœºæ¬ ЋFÆI€{J ¼êÆ14‹S›aƒV¨Í¡Mœ˜¶¬™E€ŽXç`½è•³Öd¢H£ŠÛ¨B.‡ß±J‰j4|N¢£ÍQx$Ô,Êw@ê'êFƒ+B½DœŠ÷ §(°UŽW§À;ÕïYkg¦Ô~ Ôþ›äç½ñýï}7EßIàø¾•áþ··R8œž»Íº]R>»¿‡&%äp닪šüâ‹ú‹9¯^½ýÙÛoÎÌŸ|ˆÛÃØj>*(ì•Mݬª­K;—×WÏ­¼2ØX_ét’ÊëŸ\ï]¿véCwy`áp:°9fL-÷3Â`V#ò¤ßPeH2Yc:a/ ÀòlL–5t£¤$ÂT8Ž]–5ë¨^Þ7úœ1]@W¶©Åqa®ŸÅ½“ÈIÏ>3+¤„ô3è6¤A˜´ Ü/r&’˜ÿ½8×hÇÐÜ®Ò /¡®ª]E•ï•È´tQ°œ¢d4Ú&"[•Èuy›`4"Î@zeÔ²+á#ü”¥\ 왹£Ž°˜Êþ0É™ÑõL˜EÉ!ý=¯þ~ï› %ò‘ÆÑ¤û ¢„Û×oÿÍëÉæ¾ùºcRÜñíï¶ß|ó͘|ãûß5H´gßåîïwÙþ‰½»­Éõ/&íSwÆoV½ÍtOº>ÂRfòÉÏü$í¿¶A“æâì¤e}u¥køÒ«§­e4}èúµúÚ¥Á–  ™Û¹`?ÇŒ³ ê”A„^‚ c>fÉAíì™7‚+ÄÌf €¤²l ¸’زÀN/dš£±q•`!OÑJV¼t«ðÄÛôÔ¨YJŸ!µÏ¾HŠˆ—ÚåEÖ‡yèªâ4ó (FÓ,&èx2v¨;ÃyãÇŒUiWŽ[Ìþ¨Åù(c!½TèãÄ­º6¦«M ËŠÄ"^.í{P…E(ôÕ¡ˆÁG%)á’U¶xê£.g ‰E¥›(Ä”ãˆ4T.œ¼m$H¶„ætM†‚öIý}û{íXå÷ÛÆP™ž~÷·®Š³Q‰vÿ›]N D`ú…ûõÍêòË/¾²Ó»üöÛ,µ˜A¹ö‘´L²Æ“=Þ–ÖgéÀ”´sigc½»>8?ØxõôI__'¼´™Ö¼f~®b®ohÒ4b⥔WXÚ×¢`×aˆÑ™s  G0¯ÝN~ök€KÁçÞ\Á€‚µÙZ£I0ü‚/j8=e–ÅÈØBð;fUÈ&i%EëR1NXÁ¼B> •zqâ•Â&/.B“*&#›B8·uf4l.3ä6·¢R^~]…5`•Ë%šÃ $EÀíâ(wðÓÐÓ´ï¨@<ý³y“]QÚvì‰#0÷ÃæN7'@41òpá”ûð5Üt›Mj¬Ó øÆýºu¨ÿ‡ï&èÔñAJQï(€Èñ$)yuç‹/¾¸PM=÷W;;Ïï HÂûúu‹R ª÷öxÕŒ¼‹sÇ;ÛƒÞö`û•WO%Œ¼ÐÐÉãñöyõô¹¹²ˆ»{펊#Ç0ÊZQÐWŽÒâÈÌ…C$ 3[cF`°Ý€ÐŠW®ÄD_–…]Åš·ùL]æ4¥)pÖXŽ˜§ µ}Âr B+Z)Áá õ±™6„`'ANè.Cri"I•ÆQ«ˆó•”ôé¡9~Œ¶£5/¨NXLjdOô:`Ôb.~ÆËQMí”kÞGH QéÇ”~#ë'ìº ¢=/™$q Ž Ú 86ш'„Š-ÖÞ«wÄâËöøÆëo˜˜¼Á¼‘’ï'/ÐD˜ k´% I•ÿ>=ìäIzîÅÕ‹íöÅ«/~ï“O<ËBéûìAï¦ÐÍH˜Â¹³}auõô©S§Îœ&ÏÊ\eÒìò›kð&jÖ=´‹Õ…G¬xÈ;!(¥7#È¡mÄôˆEÊãªÈUuƒ$¡gæåÆ&o¤BZÛé$E¨0cddpÓ#õ!Q†[Î *KÑ ‘#…HÜ3séЫ">žBdù˜úp!cª8‹Xgö'£úB]ˆpƒÕqØ“‘øYQ£ Jl ¾léOÄ%, cŠYlϵÔo¥sqðÇSmUjíRIÄÕ¹säSp<³#u€4M°wâ¦pBÊàmøÑ(¿Á/a]…ò{¯]ûþ0I`Z^ûßÿæûßÿþo¼Õfß ûALwÿ×Uÿ›]2ù•§žûÖ §nºxøÈɤÿÚíOöÄßkûÜÛÛ –>²­ïÝ µÂMsG×Îöéó§·O1°Wt¿Mgn”LĸV‹2€«µF7Tä̳3ó WЉsdsØ¢žv3bŸ±æyš ôª§"2“4Ús7,ðÆ %¬øWÓå+ØTMÓ 9á›Ù¹Ô€KÙ”YUô#5o“)Au`ò^ö š˜¸ox µ’¢çHÒ¬ä¹méÒ1}E›1RPO9»“îÝ»{÷N»=1â«Ï>Õ2òí;÷n—N¬¸¶™Ýß]M7tRiÓí—ÛÇŸ»49tê•Å$ïýäoßùðgNÍU\» ¶û¢B§ r*7œ>•ñEh¸FSƒ»œC&½Æ›·e…7ëL¶ù ¤aŸ©e-èµY†`9'`‘/<^†HøìݤÓH7}sN´y(“Xr0ÍqEO›9øl 3 ùzB)Cź>Âß°Ù’FF4ºõÊ„3‰‹£Ç8šΠT 4eÖDr#‘ZÐØÔi®–‘aKå4*ê{%š¤Q6äkṴ™EãîŠå$İ·Z?Ô$-Gð›Ãw¦½ºt¼lœ:‡Ð*©]ˆˆÛ60€VkÒAZßäïî$‚–Þøôç?¿1ríöí»·ï܆‚‘¹û_Mú»&'íö‹íÃ[›G^ÚYmŸj¿ów?úñ;;•£pÂæ˜l´Š,žj—KzBhƒÍå[fŽE°šf¶0wäG»þ,¡>D´/”ˆ/3%û¢ýˆÓ¨j'^¢°òm˜™JR ™S“oø«Z@BפËbž´( @½â# èŠÐäD& ìvÏ<Qjì~ ÷eÄT ¸<Æfp)µQÅnn5a|£RWº³ ;FSI‹™ÁDâe¸«±¼R1Lÿ!a^¢5+dä–±„¡ˆçéâk9!D Jœ÷ƒI¿wæy‰XÙn¨B^šUhb¡kâö´Ü¾=;] }Ô^º-*yÛèî?™úÿa^`û•ö«)`i/î\<ÕnÿøG?úñ?¢+ÚôáТ>Dtà}̰%¹E–|“„ÎaÈ Mo¸©…¤Ê÷Âߣû<]s{ Xh-xÌA¸ŒôZN¿¤ÐÐN|ÍÚRÅ‚‚aVHUÀþZ»¸µ†UÕ‚)ÕQ¤É¨‘˜÷‚äƒIô0˜¦Á*(q³¾'+Kú f#b›ÔäOÿ1`„´ö¹a’àdÄk2VúºˆmÍ‘¡^¡=;å]Û©FxÙH{¯òv ߤWJ׊ý,Ï2¢ŽºoËÐ8éû”€³%ŽM¹bCå}؛ĎM˜2\ßôñ±Äps'Ä|FŸä/éÀ»÷nkxß¹mÿ˜Ôf™ R ìü^»}²}h|hg5Éß©ößýíßþäÇ×c!Ïaêv‚#$D^Äû‚á¡—ëg> áÆ MA— nc.ð²az¬€cg¡SÕD´: ¯ÞªH96æáÞb U!ãØ+éèûwѤµ‰v´•ÀñU&s³dó—®„¸É< „¯:FŒ%c½†|¿$ «”¨‚0P¸¨ljVaWE2Y°{&sHÇØ£©ü™H B ìî?_2úîú½$/Z¼ôbûùdÿöݽ_~²çÙ:™[ ÕÅ)‡·¡ æ>Ÿ[Ö¤¼59byÀxcyÀ4™iõQ°ŠØŸe^‡øW0-ÌjºV1ÁÌ›‘ GéœÚø —`jÇ…±ÏÔ¢¶ò6>¹ò,ÀÕ1S«PØZ|Ò™²´‰­ Ñ8DÁq¦¡gŸcWD5zÁø”n‰®PÑPÙDk›o³Õ0¬ƒÔcžóa裦h#(A3=XP ìUÅ&ÁÜ@%/ä qð'gмQÞΪÒm•Ìè}Ö›Õ‘6Ìô5üÓ€Á—Œ¾¡‚lm>Cf¸´ë oŸ-Å{ô!É\’:0 •^F9IὂEæ ¾ÞýýUÙÿcwgût’À•“íc¯%Mø£†í]ÚQ&:“!#¢ºt˜­ BxØw+äÆfE¦aØùd´˜dá-­ô# ¿‚)"΢± ž#Ç‘!0=nDvfÝJp9S¡”N¬Ÿ6dd”î{ ¹íòŽYip„’˜7Â93ødOª…¨ž‹Ü<…•*M•!“R’‰FX¿ ü2(¦(Ä™§šnjÇpb(¤d쀉NÌ•ûÏÛ±R%’Í…Ã. ¿®+z$N2"Ô ´«Jå%\LQˆ0+Å1y#ç)M£‚·”klÈN‘†Esjp™ÆE±S tq@ýØp„uÂÛÐzIç݆¼šR½w/i@NßÖ°„ÝMh¾Øÿµ»=N6Ø* /œ1 ø|ðÉÞÖdÛKZ™‰Å`UßCvZdZ ’Ø`XF’99 Á@gµóqD5 ·|„V^h¤ÒY0qCg môÈ1q)6„™3b‡–üµ³!íø$NªºÉEõÑB¥::ŽÀ`ÓR!2¬Õm‹ jCŒÃ?CÒ§¬ª€2\¡Ì²É²b3úyzhó „yV †«y¶aà - 4Vñ¸ªmG0)PZ+qüa{ÌMÇÌsd¯ð6ˆAiO&#[[Ì;±N~Ç;EÑp1L Nã4ψez²cq€J‘#<+Üæû%çïî=e®aͤI”|' üý¿^EL°º;>ݶ ð íg^¶:ÈV:²ñŽ¢o%)]ƒÿmšûÑwc‹‰wæË¤¿sA3ùFhü°²ˆ±XRNˆ[1²"Lº-ÏÍãÊy•èôÒ)öÐ’ÚÇ®P‘ÏÌu¨G5§B­ÀòOQ±Ðni— g}äÈÑFˆ!‹±„,¡ëØŠÅ YYÅåÉQ)È ®-À–…ŒÆ´R¥ìºÊ¤“J«:TþX;AÞ?qÒ0Mg444I2M¶¡]âå Ba8\ò¿‚xÁi /A9éºÉb2àsã»$·†™á¡%«ã«‘Ñ#Ü0±4ÓB {œâƒ8°¦dÅQÌ)ã Ì˽"Z ö¥ð2‹4Áò;Î×4~ä [_˦‰;g;é§Ê‹  ¾TŒˆÃ™ñÁôyæ`¢27Ð= "©ƒíÚj×dÆÖežrÏdjW<,VÌ=&sw^ '[¤ „d¦µ˜wä˜@å[ Þ3ÄÁx6Ê•’˜’rhâ‘¥äP÷€‰`õ¶­Ç¾#Û³1M>Òž,Z¹ »z’TàÅ+·Ž¼uåÊ™ö/ì»N.í¸&ÄûmyL6'¢  .Nîc%ýˆh Õâ‡*’ÝçVýE}ø†SjÀIÎΔä0Å–b¶Ç‘]Âëì74œ*ªsI¦ÍágâVƒÐâ»Ê0]¡¬MýUl[Šðf":ˆT7@Û0ܱd÷I`Ý#tå1=.gš¼Ë1‰9ºŠ‘0çÇ9IY ®Êâ*`yTÄ!àì@ffU/0¥BJ‚‹y®ËˆWO_cÌCñRƒBšzfYs·»K&Ñçô¡PQ½•.f¯©Tä$Æ|Ê]† ¨LR ‰¤shúðn“ÙѰ|)óç²ÀÝ»w;4õf~Q{/ `ṳ̂ÞÞØÝª>¯’üç×ÎÌŸhëÉ/vv<+Ç>÷Qæø÷ oÉÀî(ÊdŽÁ°EòhÝj8—1>ø†‡ÉZÜ•ô›eXÈF˜¾‹t1z—¦w%ÃT8‹tUcÎ#YŠç_PGú–•[ò{—¼ØÊÉ0h…vTv ,¿žðÏ{•YªAÎ×2^#Ð0 À-%©‘(„€XŒho}Æ?‡Æ T)ޤ©ù}ÇÆ W×LB>žÊ@ß+Éü"ÒW2íè´ê™Ãg^8=™lì¶ÝŸ_¸õÛ3ß:sìäKí_\Ü!ÆÉРZU`"sÙñþØÑ8•E®+Q" ƒ‹1Ö¥« _ª¾m$E£‘MS‡Ýð˜+=G†˜Û™b*ŠŽ šu!Wè^°ÍU ‘`0ÂIÄžéÒšµ’Òs8Þ·‡ã)œV¼fΡWJ–®õT´0-è8ÔžŠ ]£fr IDAT8½€Q§›bbùW‘0)]xgãÀ¦^ȸÉsEóÖuÎr¶š1ƒ]eËŸDfÄȾF5¹çPEZÓŠä ˜ Ëæ8£4Ý^0F•â³ u„Í⃎­$%<3¶L·eø€+å‘B«DðLSÃø1Ç-–Œ@èÚxÁªË!¥ãhŸ8ùÊéלñ’§ø÷Tûè‹Ç^l·Ïœ’óB%í³8ˆ„ß•™óH—Aõh’nÌ9ÚóÑ\A@¹[ Šo‹+HÍ¡{͘sÔ3ÍnL;Ö]›Ã¡±M 1ÝVÞ!¬s¨ 1Í|‚jR¢.áÄ÷bؓڰ«5¥d’FîSzed5ÀloÅ$q$~Ï«¥Hâ*+Ë[‘XјóiùŠáuPSmy?ßPde«N^CF¹@"šô'µ’Bó½ªò.CmÏIN] ¬­±>DÝHÌ‹T˜s‡­ïZ¢òBs9¡ýJ¢3g²0,e}$Uʬ$sIJ ²&‹[÷6½>Ññݽw[½vt, ª'âkN¿ÂNÍ$g^Nxúô«¿¿uªM-|N« žd²l`±p}ãÇD û ,Ù^äË9ÜÛ¬t€‹¦L/:``iÕ \’ˆxÂbÈF1k”±ØehÓ ‡¬ëF•Èèv°ä¹ZEY«qútR˜¦b‚2¶^&««ÐÃ>s4‚W)Ï ásÑ•]Nl¿ˆ| IL-Ù+‰¬1bŽø¿ ˜'Ž‹;t)ãW `E‡MkÞßmà|Pk²—Ä(D‚¤´aÉœb£ºæ­Â¸·P/BßGÖÙí*WÁ+övˆŠ‘ód6UÜ ú!)·³ P`§{·á:KÝš6¼ÂáÀ УTiL·ÿõªí¡ýJûä©$·~÷»¹Õ>•ù±pXûQÆ(Gar²ÉÑÄicÕ€ÇçÀ7åý¹‚Ú=X¦ÕÌ/jÔ]B=b›¦ãXß3fŽ ’ )-h°ñLҤÑ9"#Ã;,Âc>=zߨw %ÌMëRGX™‹ÂA5.¨ެF^YÞ æ¬³Ð øË£ù Mà/Z8 `ðÒ|9C*MbKÅBU¶Ý°8„k Šê$å'½c©ÏSßÎa;–W)„a·w¤ô`3 u¡ª“˜p‡¨¤5U"³+B¥ÈH5%P¼^mÏÂâ{ ݆ì¢GŒ°ÈìÿãÐÓ‘“7Ç ˆo—R'ž}O4ØØÉî¿^M/·O'ù{øO¿M*ð–÷™6„ÉPßT_|NI骘w¸”ÁJ¾}¬ïÕZŽ µcs /nú/9Ãaî=1'ã†S1ÑÐhòop¤k‰>vs‡žv7,9X‰!`Ø9t:2HãDè¶X#¬g%Ë (vn+Á¢qsUéüKÂ]J¤ÿ|¾¿Uê2ǤLW%o H ç Û2/¢§à•0Mz MÉ´éPú]ìN2G xi¯Äî– >Q%ÁŒê‰å *~ ׄ,f‘dœƒÝ$|D„½ŸšSÏ6Lzˆ¹ø “ì³Ü©‚!¸4Æxyžhº"XÔÐXN1ˆb`XS)½ì'ªýÙýýÿºêÍ·ŸOøR’Àßü6Ù`DðYƒˆž7ßÁ(¢†-f.ÃÐlÌN™b*á6Ð(L´[Jsht–©DÙd:Ú®?xdpªàì ¯ §&ˆ‹¬¦LSmje4ÆØ ô¼Š(E‘„ùTRi;õSÐŒ’'C>üp–+©'2Ædš5ÉyŽ(8²ß^Uꜜ¶“ÈVšNf|Xü R¤17š"TƒÕ5ÈT"'‚½ˆ|MS„î©ÙB-r½E¨ÿ˜ibEæœÉš»(ÊÈÈËP¨R¦ÚVP¸ÈêGV˜)8S£ârÝD*Ë´žB‚ä Þ£¨Mà ¸“%yÒGv÷ÿ\õ)yþÔ‹§þ øO&€Ê`;'”M-31A®Iù”e§£Â%”§˜ã}eÌ~ÄB J£0nK¥Ã¾R·3ø5`Aòý,d…Ü27Œ9#š›¢Ï¨® ;óuîsA“ÚlÆk­^o/K„­Ú0`ª£žnÇRYI,TüÙb&”æl"dp‹’ %ªàA_Ï{–z¥ç7†.¥7ZåT%­±c¯(Fв‰Cô°{‚þbñy:þ¸ÓšŠqàþM<£¸}‰*ƒ^À99cI·OÓ ê²7ÉÂ@ „ê{ KX%ït‰–ü0suˆææïÞ»ƒÍsò.1ë¶$BJ¯íþvãjûµ“§N¤/zqïå[·vÚ™"”žž|½è²3ˆ})3Ïñ²èê Ê4ѲÎyÎá2q,<@p¨ö|tÃVq£å\l'±Ò%fÊ¥¨ÃØ|ù¹E+UœaÉók¬iÖW9u{$aJR—´¡M6Í8µEÉa6ÚáÕf&½4~—Ü㎙5ÎŽÉëSìÚ¤¿Våè„Æ:2ìõ ” ˆìG¤ Ù¢€Ýi0é+O õ04#:£¨"b¦£úYLó²ðHu©[³"i§\ÌŠËŸR}šBx:Ö Xì`žŒƒ%9›V’ÄÛ—y–Úå¨v"ctñ嘹ÇJˆŸLÒÇî“;Aä%Ù ¨åÂîÖ ýRõÒ‰—O¼4zÉ¿\}òWí ô¿²[øR%‡…œõqr"¼’óV¯ün%ê¬%73^–ªâ¬Šx‰ˆBFHñ!h.ˆz* cQõñ1;#Tæ,N¥oTc%Jù†9I9‚3£ »2,²©\,:V&U8³dÏr‰¤&eUQƒŒˆö¤ÀfMb Q²°›†=pà‘² mXb_‚s¥…ÏXæúD…ie*©‹\ȤG„-â=Àaš…[4fP*<•{¡õK&×ä`%ÀA*K¶—Ì‚³)-8´ÅíOî˜Þ™Œëý$€‚¯€œôÁÅò€ï}øÑÞõŸ¾óî{~òI;ßì<#)—CYå™GH 8ôu¹KO³ ’-æ"Ü¢d]ß®aaE_ )©=%Ë>?B¢ô{ÆsÃD!€=1 ‚Z¥/å=ç6JâZ¤ü¼seÓg¢¦® P£˜wd™Rˆ[~Út¸¦ÐÕæˆEa„ByD€=n¤x3ÏD­ŽT Lˆñn°î«æ>Ê‹7Å`ruEñ%D¹vœ‚ü"·æ8üÐ"C¹TÇ[5u·•DŒyͦn—óã¨ÈÑ êRæ™xuf}Õõæ„qÊf°ž‰»á µJ–¤î Áê ~\ß¾s×8ÔL3Ⱥø/-¦Û|ðÑÞÇï½ûλïô³vNF²ÁŒx%Kàå!ÁdXIÇ׌O^*Ï ) ØpK­ môÇ#ƒðBD„ÐxüJH0»‚# ðð$¶Qº!|aôòì‚í,Ô™^ ó§­UI^EN¨g{Zlø1È€ÈT²JŽnÖòƒÌ4ñ>ìÕ àÀìß œÊTóoh“Rš¨‚oXúìB€!ÅÈa3’®äF¡4VxæuôóKBxÔßé™¶¯^Ùë…=ôd!¸!ä!1hÞ¡™ˆ\ìàäx3LN½F¥S%üf3°EA :hõ‚ðTMä’§Š0deéq2žX%äÞ~’ºýqŠEŒBm<Þ¯Ó3®–°Õ²_À´©½Ÿ¾wíã½÷ßyç÷?Ükåk‚@VR~Np]!`£A#ˆ¤`Ù@H/h¥Åb”L°gîÙèFrpq€ÚruLŒq%[$“/B%qAA$›è@¬l ïì€áq2‰äž’ÿÆÁ‘@¶—b—¤!Bc8Ñr—^Mdö´D“Xî § ›åðÜü£V—^MIž=œl¦£ Å¨áÓËWrÚíc¦žÙO’‡Ù p6#a5G$¯±ua¤µ=72D¢°Q¢0÷Þg˜=½ü)ÿ5©Åà¦9¯uaVŒt±¢ª(ìïqsÿÞÝÛV‰[’4á~ò'û&~û“$•ÅßciýŸßúûV w|ïÃ÷Þû¸ýÓŸ¼ó“÷>¸Þ&tNÙ¯  ó 0—=A…¬‘4'àÎ¥ÏÊ.Ó04@*’–Ûóê»I†p÷ÂÖ:BJèÜqVÊ(cœöq·E€·Ì)¼áˆê v¹¦(U13…™YPã 5-’cJ Wù‡1ŒCÈöžA& ¥ÜXâðMâš0ݤz ˆÒò™Eú\{Ùõîs7SÅ9ƒJMúœ˜ö¬£X’÷ôöÙ‘œab–WAo³°D:òÆe@P>²BÆÍyŒ6d´_Ö4žiTPþYC†J›¡ÊaL’Õýýý›“{wîìï«—B`09sÙO&Ô€_¦ÿ­/¿”LÇ·wý½÷®¥ ä'ï¾ûÁGí´!Õ;ÈÙIÈ^>›TŽŒòq1å×sŽXÐM5GD«e½‘‹V ²8×úEFnxò0Y8—Åhh¡É bÔl<²õvYº%ˆÍpÄQÈv˜½gN˜…µcÌ[E¹Š¦+çhÉAëÉóåè÷³9¬¿8V÷q  Xåz«Æs¦ Å2ÉÐÙaŸ«Êçj/?Bs]eÓ͵¹ Ž¢Èâ‡ÉPj(ÏœÜ S'²€Ç!(o_ˆ¬8º›”fdLuèÃÖ±q½Üõ˜›ž½¦b暯 ·ÓVJ€[J ¥‚iBf¼œFŸ,ðÍÉÛ·“Ö»mÝÁß4&礹¿ü¯¿üeúiµþë/ÕÂãä:MÚÿôýk{דþôÃ$€ L;g¹ÅpBì ÔÀ6•@djŒª–áòÏ7 SÒCëŠþu@³o& ·F˜Êݯ2çÇûùY»VgµXÖÜ’ž«Âòj‚PI‚)¤¿ÃB²ˆü_.Û¤(P`èŸ$²ÙÔœAŸƒ#¶BR¤/*§2fÞ_DEÎp„žI&‡ð ‘·q!ïãª6ŸD=³LÐôc7f:U=¼„Tugg*ˆ‘1ü;{£ã%ì¬å‰£V3pvBÒZº‰Å4öŒìÇ»yše¬íÄšëU›h¨þ褑²Šx¢Xs®U¹@/²~tö°Ð§‚ð9%XÌ<hc.Ç´Ü|,IáIlÛht•ü£-ÖÞè–rrŽkÊng½è™L—åîɾ<@ƒì§àÈîe(~õeúwëW­VúݲÇ_‹lï}tízûúOßÿà£öÚ“ AJ’8u Kï†R=Up!jÉ|¢`7ø‚1#Œl W P:Žs¢~(¨½«$rvŸ}Q ŒÙTŒ‘¼68—¨e%ag£ÙmºËAy?ê1fäcÕr¦`Ûði‡ñ¹è wYô‚ú¾G`·€bÈ2±UŒL €_V}Eî‘Ëä±Á!•ü*FBÌ8Qª`!ÄW ¡«‘ôÀ¦!²[y¥W$ V'J‡Ñi´’R†îÏÀ_ zÜE‘¦Ñ«ÀOÏxF¹qHŸºN°AÁL‹óì;BPåa[j‹<êýÉÝ{û7SH²_Ãöî›(Úv‹ÿ†åÖ-ûÅÇEò÷Û{Ünï}ðþ‡Àýýiö…)ÜReT4L¯ž:2°LD·‰)Øp¨v’Ä”GJN ‡Ã€KžRŒ8›Ý rùê›ÆzÃŒêm ôEŒÖÀ‚i¥º,'EèF¡æY€‚7`tä…Ï¡¼ú=õcNÐ|1V”ôû€láHê Ûʱ­1‡äb-h/î5"ªÌ«ÒS:Ÿ+¢±”¨ @jùin'¾q˜ZÃS“d:ãȹñVª³¢¤+ ³X|Á2GKK ̆vÔôIè=B+ÅŒïsüQ’K5âFU•U¬9…³*QçœÅ·]HAHò¡þö-c® máQ•´V¦RÝ»víg×?i' d Å•árît,¼›¾BŽ“¦Ði¡&wscˆ¯éÔ<†d%R$¨aÉ“ç«$YÄq³ñvŒD ß5dÙ Ö”)û;V%IAðdbÕÃf]Ÿ<Ûh{»½³=¸` 1;—M /›(±Ê…ØœÍ °­„âà»8 X%7”­izoQ/½6ODZ"£ «OÇ\ÜAV§(%cô µ:ª¡³T&ù©õ3zW½Ã`\¤¥IÀákÓåàŽ5–Ë1¿ n’`R€4lR´ÙHéª!f!÷›™f°˜A$1»:²9ÞPÌ«E­¹-8ƒCI•å2JžŸ ü[O²‡^8+Á‚Óƒß?Jó¹›û“0¶BI{{µ¿Õ¾ra}£¿y~°±¹ÓÞŸP›D4Ñ (òãûˆu¤L7 ”ãB…‘ís‘e¶h ÍðŠ,¥DæOí•@ÞÖž®0e¬@AК¤–±²1S„–j1·äôµq>•ù¤téÆLÁP´‡ò÷`–2æ€n™ò‚LdÅ+ë|Î47´T%Ù-\ÎI•Mb&q5ýB¯aè’M&7¢ohJ™®Q3yÕ”T¶£3ôªWË1óèâç¡«`s (YïÌà% Ùd¯0ÍÙ´3 Ë8¿€l%éó|®«þIG+HVÉ\ÀyâJÀ^'á»=߻ǢJ²ÀI’Lí<ª|sŸIo&x'Iᥠ뫫ÛWÚíИߠ~VÉ"-A¹AÏ\[I$ÈÆ±ŠÉtô’¨„oTÞ(‰¨' ' @EÙ(uÊø)L(Q …YµPÁ³ûn94„‰«8fA£áâqÖóâæ¡ÈYæà9Ì%²ÑǰzD…ÔRt,3ÑΜ®'lTÕ$gJOÄsFK”ʼnäĘ8—óÐLz½)Ú¢¤;¨¥UíɶÀìD Ÿe—{å‚z4›É8§ˆÊanÑ{±` Ìò<âÀú™ˆ2Á=ï™øŒŒŽ5—†å]ÖèÊÎÑÝåI¥‚IMk²)¤@ÄÒ/uú]OögA­V#€&6É6{û½ßÞjï¼Ön_¼r´ú¡?yt%|Æ0S«³oZ(to‚e«1p±¶L3´Y;›\Œ‹ˆ% ‚ý*LÓ¨¹3¼F¤ò°U¬=$¢7®ðC#ŒÍÇÐîüÊØ°LÖ`@ lÔb“èNy„œMˆ°Ï>Z—}pcG=á”>©èßÖÔòJò¬ä÷•­ÔÄÉ!S2‚ŒãGб ¹Å/Òò2€.¥¢jε¶ÏHÓjtç*àa•2>Ž~­åãÉÆˆ‰Õ Pë54µ¦)=QN==)0t„Ì,à›ø¶ô>笌\–ñlÕ‘ß¶ç·÷ÇÖ–iª/}Îô›ŒƒjÀ,s)ØiåoÞ¼¹ŸðÒ—¶/··¶·/_iOÅ.Ÿ•Z³×òÍšÅT^¬—wš1ùð½ç€×ÖÀ²O– ´NKëŽK‡6Ä…dlA_4$}¼ "q„™®”CkÙA^­Ö€y¶A =À…dGÉŒ¦Íą̃X€;‰òf#¹tkÎÝ(‘Nö¹-?Ë o–Ð* ¼ˆh2:` ~e ÎtØ`'œtP6šI—ƒë|^ž7ºÈpivˆRö¼„¤Ë»¤œB“!#¨»4UÚÔ,eÖ…ú0 xm˜s¹¬t “HÙ¤«Þoæ&åü›mûömCN˜ŒÜß¿)µ* øeë¿|ÙjL0½5×n—“ööÖÅ×lžpÿ|Ü–°¹“äMJÿ‰ï¨[…Ó­ þ"*!®ÖdæU«@ÏFxà ²Víp¥“ »ió¬‡íp#¨X;s#xŒ3 žAfvb£‘HÍ–AÒdÀÈøÛ@«\‹ø*Ÿ…Œ*y‘a¬DSúPQåò.#V¹X £©’8bSªŸIgÎ)$ Ò@9ŸÂIJĈI,ê+±Ä‘øj„þƒõ¦–ùíŠ U™y²Å†(øº5íƒ)`²¯b%|\# /`!¢vç4B׿Žx}$r·9¦F0–‘3!dlVð·ïÞÛ¿sÛhlݤ{ƤZXþÕ/[­Ö/ù¸PRÛíl¶w¶.´··¯¼va;Œâù+í8@|Ö}J ª¹iFI{¶`*wâ)¡D[¦õGo°2ƒÔÃç `Ä*™+I_„¸Æ\Á‚ô±„—¨nëÆ m`QÜ"تĪüÖ㚆ש²P’þ»äœH3a5¡î´Z`)7øŒÍ¢rcÇ8Â~gA_=»…J+9Æ¨ÒÆ„hÈ͈ …S`€ýp( IDATàü%>›¢ÜɆñ9WsãXØAÏ»‚n«òAxèá˜ÓÃQãaÕšâ˜SßHzt‚T—e¢&g*]¹a™[䘔ø!ð( ¥sÒDôË’ï—|À»–w³b†˜Tþ‡_ÿZ`«Ó‚‡6ß^»½Ù[ï_¸p%¹^Ÿ¤f Ã4|”ƒJ˜*áÙ²¼(â«t„Ïéç1\­ qÜeÖIüO™ †¬')ú¥œpé(Tþ²©[ XàïìïV{}°±¶9ØÞN¶øB›91 °ñG Öè ›#f%”ôá¼Ï|Œàç,j(‡èIG¹Ð\Øý Ê~3›ìbaZm4Dá=vHá÷–Fl„—ÒnFŒ£=c¨ÁÜçbY%G.Ô ~ë*s2–l"Öu±A¿fm(¥­Ã%ž?JŠ Ã—Ã&Âk±8-&[Ûå°†ys j#¦N&«Ã•GUY¡óêQš¡p{µç0U ©i ©Pj¬,27LUQ)ì®J'v;(G'AÉÐgô©e÷“¨»2›L¤¶IGÉžˆÀ‚ˆS9U)¦eèŠC‚Ýøîíz¿–§¢1½fÖ€¿¼õe«ÅG¿‚bÙŸ s~°Ö[퟿x¡mq€ŠÑ¹ <ú\ñ"qaæO¾yZ5ðaø­éF#0þG«ø®G,d”œ›T†¡Ùb°]‰¾¨@õÎaN A0Ái¦º5-n Ñ4g_Óh ì{É$Ø¥èÉcæ «̲ 6ŠEŒ™¨O·ã’¨†µŠeÕPÅLxåØBxšŽÌ2Ò&óNÊ–Ì%AÌ„‹£úRå`"Ä Hˆ¸ÅÜ ªö@Àgšk®’e¦Tg&Üjû`´Hô´«4¨N(ñ \nDT©¨C {Ž‹hºhàX ¦¡WœÛ§ª"‘(AZ2f-gkrË’hÿm¦¬0ÏtƒážnèAms(Ül‘':“¹à¶)dèY”ªæÁèæH> 挖jõ`C[=Hý jD¿üCNÓ,F#Œ·Æ°uEs’«àÇÕÙM'«žX=\M˜ÖuGèƒ@ù´€xÀ¨–˜Ìà2Ö8K Ú¥.‘èܬ7>æb«æš>|R[P©"”u• pˆ(È•Fˆ ÅN FöPU1ÇUh´©ôíèD¡*t´–Sªrïy˜¹ú¹eœ™$§¹1ÒZô¯¼üªÝñò6b3È+[æ"Šõ6úìwy…¿"èË.Ô´²” ÇäKÎXÎT'©0. 9¦6Õ+ªÑ@?“ª_ªTa?è^$ hY— X¥¶o‡ö…¶‚¸{«‹ €AÑÃ‘Ç º™Aœi£b}ÖOpG€ó¬lBƒiòß’‰TÅ!¹†k¬ŸÃM·Uˆaèñ5€´MÈo¡m9Êrdyïé85ˆ§2Ô¼­s—$­_¦07 `¨Qe’kú™™k¼24BŠª,«˜q5Hs›÷i¾zDKV#/Ì!µù¶¼nI4)qœÕD¡>fÈĬ¾3(!]0*4Z4çÅ—Ïø… ,š¼ Öv\ü¨žBË|C®r'LŽZal8_Üԣ̨ÙT_&ð!³8(†b’ŸÏN!?K"Ïæ‚לâÑ Ídfâ4™4nTðR+šÃ'5i7a!èS|ãð¹ÁÒzCåélç“äPXúwb=Dœ%NNF•+Y¡®øUL ‘sX+ôsò>$ìÆ6 mŪH‹LzeÀ˜Dc‡j,Q›¯”â 4'(ÁS8[SfÍìv¥ð£¶ÑÙt¹ÂF™¬˜p.€:«2Ø‹íBÈà“Á”0ÚP;ñ>8…Ã!³\•tó(1ltsðµ¤`˜ƒqä{Ašdß ëZMV9§u‚ ¼ËˇÂU¨rœì”PVåG®›>Žœ†„7÷+g#_ß.¨skº}#ÛD¤ˆqþ¼(ýý\2ê½¥¯º,§p|øÍòÍòØå‰Å) àÚÒ—³gí¿ýmMÿž]à“–=m-õÚÃΧß,ß,\:Ã,NIt <# ÔYI•=Kÿ; &Nsí͵¯,±Kg—函µõõô}­×ív{«kxüÍÏ¿‡Ÿ‡^Z[…ä·{Ã$NçÓrÖþ=,@‹|Ooš8Ím7xv‰Ê³×ëéw Ÿõ²®&™KKwy±³°°¸Ü]ûfùw»$!XXèd!X]&q:—¥•D¥õ-Ö²ÿ->ºO[[ý•ôgkkK¿·¸ôðlk£ÇO$\][][YêœÅÒ9·¶ú'úwâèÁ´<í§[­ãoÑ6xðÄÚ*MÓ.f×HúÚÇ}òpZœÔÞŽ>í7š9~6ŽGý'û×jÍ?ý§~é\–¥¬°µÔy¬í,5¢y¿lmöLÖZ­ü»ù¿´ÕJÞŸI }b´jËÊ"MzgáìÂÊj/½ò5Ž·l™?~|¾Õzä:{}ú3ßzè5Û`Úb/mÝþίÚNî[g¾õµ];YmvÂ×ïûF_e;ÓãOŸšoi£ó­¯w|÷·ã8GOðóÀ +éâwèÛ-®@,FÀ¯( àÖ¹­µ•NÇ$¿[[ü½´ÕëtÒ§¶zÙ§/w,`Y^>—\ÎÅdŸW¿îÎùüæ`s3£G­s|~þnƒ|àµVÚž½>ßJé÷ =›YÇ^ûºÇ¾©mc'3Û×7ÚüŠû˜=þ–Žu³÷Àñ>ÅÏìy{Ô9úê?½ÌïÒ¹åe“„Î2Tðñò±Ëˬv6{gÏ™ìABôô›/à™à¶§.öš$oµ»xv!KwÅ–ô·÷”?-;9››ýtÁùþã^ŸþàäÞÿ·—¶ ì§ßýôpvôÚÓ³öÛ·¿ÚÉÌö[öØößßüjÛiŽóx‹ÇºÙ{ðxŸøç¾ó¶ùˆsôÕò\j{¼pv±»jrhº¨kzé†|À?°,Ì>œÀ$_½Þ}¨ß|È?¦o˜²]Y²vûýþÚòÙN „V;IMvµôžøoçÜž÷ûöüø!³_Ç»égúɚͼþü<ÿæÏÏ·ÇçáuÐë›ø Ù°-ÛoüÒ~ù¡n÷ùCÒò|z=}Ÿ×Fò½î‰y˜ÓVZ;B>þ>÷ßåñ7Ûç7 ýôœ_äÐÑéΦßmöøñžm&™à¼½£øFóûýâOôºœ¸CGyÞ´ºÝoæü¡ëñÇ®U·› dgq%=èœ]^K"Ð5YX‚Xüq\¼O§ØYCÀ‘b‹?&€Ÿ/¯I{ýn5½Ø]Yfº¢øT?ýîJ:9ÍóãxœÎ½Åãû5}=ÿÕúóvºí5øNóve´-œø ûìŒò=}¨Û=x¤Ë­äÝiŸöÆ >;oÎ\«•£;s¬Ú¿Ž¿ÙþÆ}û²íÃ&ÏlsºŸéñçÏö!1ÍöðÝÓ>÷ýmëøÚØÞÈûÃñæcîçWŸî:u)vðþ—WºéÒ¯&è-J×–?ÿãð>c<À$^çÎÁÏkY´‘Ämc*€Æ ˆì^2,\Yí.,®®¬,]XK¢¸°dú™æø ÿn¬$)±8ñG“Ðl¤³µ‘^<Þ·w6ðv~=]ùôzþüsö²]œûH_[ÂváÊóûÜ dKó¡þ†-ö:vÇýÚó ½±2»]MßäOÇ?ÝþFwæmlmÍo¤Þ°íà ÛÏqîwzüù¸ÓËým/½×š_Iÿ÷ým+&a¶BÏšýÙfmuÛ^þ~ðz<ö=ûÕKW~iu-ýZYY]\è®®HÍ/ýç'ÀÙ4L²¾½í°Å»=“?`¯ƒ˜¯˜~Öé!9›4_À¥åÞ¹•Šôú¦ ;Ý•sOû/üM§gý("ÈÖÑ•õt.×íõÙ×7^<~ ÓüÙùÖºÖjé>³Ïž[Áïé{Ø2¶ KØjñ𚶦7ô)¾–aæÈÓU]Ï[žÙ÷ì7:·q¤µž¶0³Íéw[yð¨·ð^³ {Ï„üqßzÜÍÑ5ûÃ7äêÓõžê áWR€Iíõ{IVÎõ–—’&MxAH¯óÙÓ à²üiÙ³ Øe{Úá xå,ÐTàJÇ2€éHÒC»/Ï®ö×’>±æ›þ•º;zàù¤±ì>rp¥»qäßn^7Ítü°éû|zÿùôRZ‹šiª[TaÒ€ÓuñzË^·Ýͬ§7Vf¶ËC0ÝÒ¿i•Ö€ù86îß/4m Çc;K0sü:-l¬›5à Ôã|÷qß_û6Ím+t¡ùšï ó¡Õ±¾vôT0]ø¥µþj2ödÕ$À²s—¦h1K¯ùË'½™?x45ÁvÓ,éOg‰Oø|i‰/ðÓ€ÿ©Óéš LŽÀRrå¬%ot}1ÇSú€é§"¹Ñ'Ì™înœ˜?x¢ß?z°ÛÿÖáä=wè8®Rózÿà‘ ¼ÏöIŸ<œ>ÞO·MœÐ6Å7°é£¦uíCð³¦:r Ÿ~t¤k3¿ÂUÒ¯™7úô-Ô°CØHﮤµxÜG[/¼ðÂs‡úÓè;Í|£nÿða¾ÖlsúݦǯÏ`ÀÅõ{®5_2…gÏšìv:ÿI¸¥ÒþJ½mÍüá»9y‚bðR¯ýóÎÂbw-…!лý&:¬¥h¨³ò#¨?ø·ßGIáðÉÃÝÍþÉùôhþd÷ðáv!Ÿ;ܵw§¯Ÿ„!{žïož“Þ8Ö;zô­ÒO¿§o@f<Ÿ´U¿9„´û9îDÇlú½ú›Í7êÎëy¼>Ýæô»M_ŸãÇðEú/:ÔíÙ¶íû<úûwÝïM.ïëiõN‚ýSEÁIºkƒæÅ>½±•ÕµîâBççÀ­J¦¹,ª@@ÑÊ%Ž–ÞÀ'XÚíO;g;‹çÖ»ç’빘$°¿ñÙgŸ~º>€U^Zý:ù´ÍœÜÜÌù3äÐ67‘Úy}ó¾üš>ןnã¾<àôõ¼­™÷°™õz3ûÜ|pI›u›üÚƒÛ¹/÷Ð~7ñݦû`Íæs}ƒG~äg_ß¼ï{Þwôý¾bnòá<àêìí`ýÓO?û,iáÞ²ÉÁ¹îú¹Å$Ÿ²¢ÒENm.qtôîTŸdiCÏ„`š7EßýWߺzõ³u“¿ÅÞzïé3íVµ¤“ˆ …=¶¿=fðWù8¿ÞËs†ŸUƒfÓJÇ&>;]?­wß{öïñ‡ëæ}òxì9,b2‰ÚצީÙ>sÿ¾{ͺ›y›ùµz³ûÙ|`¼­ÙczÜ÷O&ûàÌë÷íozÞšc¾o_OX Y·˜·³²þÙÕtÙoô‘Ká¨ÎJ‘7¡—‡0v‹ —™|ž-[9ø$‹õ¤üœy N'ýï,¯¬ßxó{W¯¶®~š$0Iã×­«þÅþ£Iü³Ç#’•=ùo±û•d.Éß§é’_ýÞ›7ÖW–;æNl|À$mÂ±Ì  ¼A àAX“  Ø,ËIþ¾ûׯ'xõ³ä–öÿt¸¿¬ƒóü÷ç>ŽÇÝ¿Á~ô§ŸBΤÿ®¾õú_7IàòŒ8H"j…—Çb.%pF*¨• -ôj«Å¢†Wg¶Õp¬B¤;¨È¬ßüÎ_ç{oÝ€üÿsö±œÇòç>ŠÇ-ÿ¦G xã­ï¥Ëþæp5ØÎ}09zÙËëAKY;¥©> =MÕÜ¿´†¡¸Ò% 'éÀ×_‡ü-,,õþü¨Ý§ý9qŒ¼G½—Ìéó)XïqÛJkäõ Î÷ˆulƒßùiÑ)vX€¾þºY`Àòº+ò•†¡˜bŽ8L¦ß|¬—¦¸=+€9U˜s5JàY àÂâ¹~AÇro0Xo|nQp:²åõtŒÏÞÏ vïà#Þ·j^ó| ÖÛ˜oµµ½Ö|k^ÓZÜŸ½üð½Ÿè‡–¬î;XÿüÆp¸> î¬tûç’(J³¨¤_g©ÉNÓ@º‡=é–7 àç¤öúƒî"ò€ƒ¼ ,´8ó³´´æ·’ÐØ·GøåþW[ö'8 æü#6¶ÕÚ:ÒzÔ'³Ágiô- Ÿõ—ò_üžyœ©ÀV+ƒ ·¶–·@à“ïT lôño€JHЕüʳõ¯µµ„jÛþ=êý–åqõxëxKën®µà6ÏÒöŽ´Èß¶×™n ¶Ó¶ÿìßúIÿÙ¯ÁêâÐ0g×Òe74Ì*pq%©ÄåÅâO'€[ÀsýÁºAò“´ h®hÇð€ skƒ'ª¬ü¥,7/µÇXðÔ`t/nμÉ5’<^Äšéõ‹¶æñôhë¸>xñH~È5þØŸe\¼Ãv,ü4<`’Ã.¯Rò'À¹ÛÚº?cŸ(—Öƒ5ƒ@›’ÝMû^³˜xaq9½²ùlþ»„. <b/="ŒnsäeºæñVZ÷â%[¯_:Òº8HÏ/e,^ZßïâGL¯sƒ³{{†þñ×ê²e^:Iã­/Ÿ5Y0\XX6©X*ÿ$PÑ0"âûÓ1¦ËsIãm ))Ý8ŠôÂÚÊòòÒ¹îà™]’H·¿I`ÒÿÁ¥–ýJ‹ÁèìÍéš­ãÍS<ÈÏ.=ð¼}ÆiI¿Ÿ;À7ÿÈŸ±¥{niy9Éß`º'™?4%%opýÜ×ÀKÇ­-´·o{ 쮟O1÷ÂÙ¤×ÖÖ’Sšlðù$‚)0Ê«gðßeËJxùÈKéçÀù—¹tùÒуçÓωÁA®yéàÑ´–I2wùðamaþà‰K—í½K)êHkzŸLk]N?.vøØyÁèøÒI­xòð}ÏÏëù¼bñΟ?|øØ‰Ã‡æ¥_8tèlðÙ[x©ÈIŸ[^5B/½Òïº|LspçqéKJ¶–¶:úGs¼4õ MýÚæc FEnÁêÈIþ.<óÿ®\Ö¿‡¿€¿ZóþÇøäý[Èëè“Óg—/4kèÝgë߃/ Ö%I{kI6×üTC 3#  Ô`¯‘Àž´â¬†õÍ . V €ˆôúà—-ý\x&ÿ^Á²s£®l¥{´cÒƒ+ÍúxGŸKës…-}ëá/V»°ÅÍ`½+Ø××vÿ¾÷Ã÷ÞC+ Ö%‹çVM6×C#€‘¿û8‹®Sï³ÀÓ†,½vÜl]ØÚô»K……N²¿[öü›Ÿ?¾¬°ÉÀR·!lFØŸûêKï) ù1íl;í?ù¢½•nòFQÁÚbë¾Çßü}6ÿ>î½G¬„ »Ò3!°çƒ~À'’§öS@ò“  ü‰Õß,ÿ¿[f…Àð‰ä©Ý~2Hþ–Aòm®&Ë9 ˜#!½{äk-ìýo–¿è¥,óé|³,w|õ$Òqú§^]¬Ó4òîIEND®B`‚fheroes2-1.1.6+dfsg/docs/images/screenshots/screenshot_castle.png000066400000000000000000004745441476115357100251620ustar00rootroot00000000000000‰PNG  IHDR€à,ÖPLTEüüüðððèèèÜÜÜÔÔÔÈÈÈÀÀÀ´´´¬¬¬¤¤¤˜˜˜„„„|||ppphhh\\\TTTHHH@@@888,,,$$$üìÜðÜÈèиàĨظ˜Ð¨ˆÈ xÀ”l¸ˆ`¬|T¤pHœh<”`4ŒT,„L |Dt<h4`0 X(P$H<4,$ ÀÌü¬¸ð˜¨èˆ˜àxˆØhxÐXhÄLX¼@L´4@¬(4¤ 0˜($ˆ € xpd\T L D¬àœœÔŒÌ€€Àpt¸dh°\\¤PPœDH<<ˆ04|(,t$$l d\T L@80( üôÐøè¬ôàŒðÜlìÔPèÌ4äÈàÄØ¼ аÈ ¼˜´Œ¨|œp”d ˆX |LtDh<`0T(L äÌøØ¼ìȨäÀœØ´ŒÐ¨|Äœp¼d´„X¨xL pD”d8Œ\0€P(xH l@d8\,P D8,´ôü¨èð àè”ØàˆÌÔ€ÄÌx¸Äp°¼d¨°\œ¨X” PŒ”H€Œ@t€8ht0`l(T` LX@L8@,8 $,$üääôÐÐð¼¼è¬¬äœœÜŒŒØ||ÐllÌ\\ÄPPÀDD¼88¸,,´$$¨ œ„ xl`THüäœøØŒôÐ|ðÄpì¸`è¬Pä Dà8à„,Ìt ¸d¤X”H€<l0\(üX Ü4À¤üüüÌÀŒŒH¤Ð”¼„¬xœhŒ\xLh@X4H(xÐhÄH´8¬ T¼8¬@´„àü˜üP䤌Œ¼ppœTT|<<\Vî¬ IDATxœÄ½ksÛVº.èÏ’x¿âÊ’H eÙŽ;q‹R$[‘-ßâtœN§{ÏLÕÔ©I©¤vúÔTÍ|Ù}lõœª¶#ëâJ"J¾H&öÙ»{ÿYR.î/çœ:ýHàû<ïZ E_ú²{_¤H€Hxð¼Ïó®w-iM´6ñ—˜l½2%&´ >ŸˆMD+QLãÑHt<Ò;Ñ+¼Å•è»mÄ*¸Ñ}‚nñ |Nï§·ÿìíON‡ _»R»³àuKi#ôkbØ üâp8Ô3 ÷üý™i¸sg>!ì?ÉårMü­+ª$JŠªª²Š—9UT0©² Öh=š4ý‰¦±p(§ÝG·È8íZºßŒDi_÷›Âãaº‡{8^Œw>$z“Úñ•lŽ} >íf$øØ¿æü Èxx¼ûݯ ‡^™^óV°½Øâ×Mýýì7̲éÈáQÚüµð‡ÇMš‰ød|r‚CiãÖß4¶…•H°™‘J3ÑhØê–6°û§jb‚Á8øà-öÈ¿Ž½à[­)þ#¦[÷ƒ·»+àá>ŸjO=hcÍûô„zÿþT‹Íò‰^ÑÞ˜bÿ†oKÐ6°“ˆC`Œ¼x8_?…{¦»‡;oF[m¥çÖ]ÅqÐ[w$öž&K2aRÌÆè E¢­ÝÕ¦¦®©šœÓ¦cN‡¾Âï•›ô +´kÇîÆ%U<Ð=³GZgœvÛºñ!;,ãQ†Ýp%2N3t˜*QöÇïÑàVWÂá >*À:Ç NŠñq6?ΦpÏ-Äïãô;°Æ_·^à€ëc·à©¯¯ïHçà¶&­ÖOF¾nµâ-`¦5‘ˆ'ª1vì*‹Å¢·bÑÃ_O¨»µÁX/¿…í¾X€RƇK´¤:ÛXF—bKUþº:¯N,±gš›ˆ3Ðo‚o«{Z 7E¿”à÷`ŠXަÿ_šg¯9܈%·°áïÿ=I›Ã¾x"ÛÀ‹°ã£ Hd£‰C¡{vE7‚ã…©JÁ‘‹9Zc=§­ë MUyLñÝœæ®çšëÍõ5IRW%q4›z’ª%jÄ”ºÚ\Wñš"ÊR:†ƒz³÷;6*õÑ7*Ä?²Ã;à|ˆðIk†9Ê7|#Lx ¸ €"DèªD#nŒDnvÃaËÃúø§u˜9Òyb3aöwËÀ8Ή_ýÐÇ8ØÇ°ÇǦ~ ;>Õ8À6Só±ÝÉa?O±j”Â(?z± 𢣥x®Ä¢116"Çè\ÂÙÄ£26 w:ž´a7é]:À¡à@ÓaDøß¾ðÍ0ö¾/>±Ùåäû-°SmBì±[­žu1U_}› ã*N~ÖÜŒ¼8ìñ›7Ø v-Ûvj±3 ·¢´­´¥ØTöH§U¥âQ ½ÙÌ5Ý5­±®+cYI^ÏÝÓñfNsî)š Pà¸àä4Ÿ`NÑ›òºÞ¼§ ¢$eS±è %·(~D :1Ø™< Ä^ô«‚pH`d|ÇC/Q‡g@” [?ÿøgl/r¸6êþUø—ÐfE¾½É09ΰNXïìƒÿLãÃt’v˜OúÆ™´øSÁ¶ÃxÄ}ý]Èõ@¿ÇC0—hñÁÅgfa$ÎdY4z«ÂDXöÖ…m.ËbVjdh_V˜¾aSœ=L2×å³´±„ïä@ŽìnÔEÜwsœä_ŒðZùø—Ÿüü㣈Þd’–9Ep ±»…oyÌb“EáÚ‘  8ð8˜ÌƒÐ{oAxe!¶WÙJ¼?E‡ÐÌ”áÒ7U–.QÿÏâ¢i, ì >˜¢¨7õB€#½ÈÓÌMòß-.š y+Oq®Âη0tø¤°zggÓè†:3Ý &²@x“„(ÇŸüQ îO³hÜ~8Õáý©HÎû°ÑS\[í­6_…£o‹³ÍÜî†t¶}S/näËxMÑw'&ã­9ˆÕz*ä×hhÀß:PVäøÛõ'ÀYs­±ÖPê²âkk9_‘$SD|dM]Óõ†­8R£¡Ü²ž ¬+Ù©¼Áûµ ü‰à˜äy¨p–c`¦iœbàzBË@ Èðvø“OÀ_~ÈS)‰­ÂöYú|ía6q³^@û±/᩽ÕÉöœSèm!l­)zEe©î'ÝïÌó/ÜD\uÖ×uM#ú[oÜkÞÝiŽ¢È€$Œ†¾ž[suWqT_’}ÅW}_ÎŽJX,"ö: x\)«u)£dÕY–8ZhrˆÔPÂg"ÎH¬ ƒMÜB¯þ,E3þø‹_~ü´ûÃçסÀ¹Ž‡C|5[þë>èׯ~8Çyä(¾ëfTúú^ÁŽë}=ò:¬vr,Ú i<³¬RÙÜÿ`²ohcÒ)ĉM–‚•Yä€.ß`8g÷ò»…|a¡P½™ÈÒXy“ %,Ñq¿.óÉr“ü"yæ©Hæ ]ßt¶à+ð\e0Δ3¯R6ßE[вŸ@·!;ÉôEY±ÅÞKÜʶt²5Ù³´õâ<)ØUuLúAÓÝ£ûºëâ-*¯¡Í&$ßš£4Ô5¼¡)`@¹áø yÝUï©«´Ô^“JŽ ’*§I›Ò®ž’åtÇþb¶ƒ6;Ü`áq¾`ÁYgfà—¿$ üÅ'vâ#‹ÁÂ?9õ÷xV™¾Nžî/QÛK¦¢›çëà?÷µ,dà+rîÅ]kÑ²ÊæÞ³âÑ“oäc¤RÈ~‘$¯ ¿BùJgÄØ'!zWY:­Š‡ æÒHœD78;jGo²¡,Wþ6ÈpÅÞ±«L½ó$Oé½lº ×<åÂülÄ·l½ Egé°+Æú{ÝÁËa±G±ý+&N]Ô˜þ³Øëê‘t¸À!PrÂ3s·hVÉØ7¬hn–%½…CÂò`<;Fi ¼÷X:,‹)zÙ,ÂÂa‘ªAª b—™°›ì`Zzœ>6J;<µcBŸ2Õd…Èj³üeÀ6XŽu<Ê“‹ ,€Ý· §L°U7Ip¼§ÁÁz:<‡óJs€Ž= tZ^PQœq9è£á[Œh‰Ñï1o«Q\cUÊú }]×›ZAØWeY»Þl®ºª"4wSÊÏÀÛµ[[—Q’3¾”î°.)ÝÉÖæDÐîÉÒäüŒì¹ýêx ; qþ~ñË_üÝGý/pÓ¿dõª/0Ý@ç¬øó°{Mt?"ŒŽ¦Sɘ–Ó’IË€—Øûh(ÜÁæi(â1ÖÌüÅú*Á{Äoš–.î»Ec߲̅b$h³ ò1Lüñ\e3nr%Ì>\H(œ`~„èf Qˆio|0Bh…²Ù<5L²Š1²…•È·aîÁIG³ÕqÚ/Z„:yXîaH²à=ð 7ú4Þ° .M$–xQr:·®Rì¥Ðë®­çî=iäô{ZsUa=|¸\k45">1Ö_Õr‹Š¼â¬ª+ÍwU…En6V+êúЬú¢(gÄc^‹D8©ëÄdŒK¦o°›‚¦‡Næ7`¿ `> @xÈcý}Ÿ°éŸüüg¾Xÿ&l×»ìFÛþ?GlÁ¯zMõ!›Í”s¹ÜQ]{C•Þ䱓Šüɉ“J§ý“R–t@ª±[Ê=ƒ¿ª¬]•NÔÊYü§tü¸$”þ·“þØ)Q,ŒG·ÙˆSmŒ³„.…bZ²Á3TDQ8´o9n€&ÞyçT''ã0ÀtÕÉMæ ™Æ§º3±LœÏ¬jh< Á> uéaîg€¿¤T`‡Ì‰êE輎>;åþ×}lú TÂkbo¯v=2¦°I:.YIËJY ËLXÉïS懿OYûI#i&¬dÚ,}˜†CI•Ò©ƒ”i&Ìý„iE£˜H˜EÌ&ÌÃ0cûñسoTݳœ\0 ߌE7˜‘ :¿ÞdÇ9Âv„Iž›<ófà«°ÉEYb#QOR}A‚ÖaVa'¸âdÎ •<ÕÅt7*Ý|åkjü7þÜØñ2͆¢5H?]kæAàz.çærOš¹&ìªã: §á‚]x·ÑôUj§»×DÄFÔ^qV9U]Ót}ÍVtխƈ¢(ùb&ÛBX@4Ài·g'6ÉÞæ< š)˜#ÒOëòa!yÊñI@?ÿÅG=h:LÐñüÝ¿–ÿJŒþuFæˆ ÓÐà™îïèúÛ§Ÿ`ætã-];ý–«ÎáÖ8sºyútãèz[?­ë¹·u¼‰¹·ô·›šþ¶vlpæ'g4Þ¤ Ó%þáI•›QVrD`ÄC…%™ô£†gß&ki‰OlDYê;Î+ºZTPŸè8Õ­Ö V5¼M)¥Í .XYÙNåæCøaCao}Ñ—ŒL<¾‚Pº…Ÿ~©Aï­R0ÍÜZS¢¯»Orz.\£ttcm}–Xk:Šþ P×5WWõ†*–5µϲ&75ÀqeEVêŽìû‚%¡,ÐÞ= ñ^Qफ9«îûkë@\rsM¦4McýIóž¶JÍÀõœã6µ÷×›Úºßð›ÊzS‚‘}Ñ—EÐ àfPƒÙ…à$8¿ú›j+q+ÆöEæj'ûUá)*ÝãE Ð>…ä¨KÄÂ#ž•)&ÌX_¢//„ú»Æ #ٺ陾®3鶬ušÔº«¼ØŒû¯F^ç#±ÝD %ªg?M[EË2£Â±±±ì±L9[†IΞÌO³Â˜ åÕ±QQüäSâñ“¸gÞ8¥œRߢ)ñXl!’§ôEt#”ÔÑq¼ÅŠŽ˜c˜:Tv[Š1¥W¥,ð$kƒâ‘èÕâlY»ÛFÁá6E oT󇹩fœŒS[ ¯ÚÃàÑ6ïýDuÂN=«KUjynMV[Õ Vª8ÿÍdr’5Ž{÷P[ž£AU€9‡æ°\®©ªÚU„Ú¦®ë×ÁsW5ÕiB+6¢ñZNkh×õëŽÞ\]×W¯õ†¼âÊÌ¢èK¢ÜI9Bf°°K¥q¬yªŠ=DÅLT*·‚mºÉKMI²D@h<^0 £xÒ°~W,†Ž% óFÚ,Œ$Béž0˜ƒž¬s{8„ÈðtDÌd øÎà™L&•JDM³ß•~ZJÅ-Ã,hX%ëXù؇e3aÄÍÁAéC kX–ÌrÉ´þg¦tüããdzƒgåÂX*a&7''á&É,À%йÇ.ŽSžu‰•ë“‘f¢fƒùè[ŒóhŸOÀö’ÃÝľ‡,„ýÝ|ŠS÷ÚÚ‡mo÷©-ŽÑ`›ód2dˆ¢#C}„;änYN˜²Ûß2¨Æ+A• Ë—Ó¡OS8ýØÖõFC¿¦¯!¨æš{:äž ð¹zÎEð]S4fpµµ¦ÛÐycp㺶ö¾s½¡ª+È'àÂu‡¤âuw}]º+”eßWýLVÚK”R`•Ød²XAóè+DàûŠŠyñU8ôM§6/ÄmI*‰CS Ë ©I«” ùÄÓH&Ús¬™ Ügµë?,UîZã¯Ðû§(ñw(7$•¬b±„ù`ïÙ³biÑøìÙb|ѰvMÓü`aqwa~waT_x¶k,,š»Æbqw¡°·[€ûýÈz{ðTZ°’bì°lmý=Š­õJ©M˜˜`Lø›MÞw£²DÉø¤„“›“] ¾[/wÙ î‡ßSåMq“ìV¥ú+רª‘§=&x‰7¯‰g®à·IÉÄ£uçýÆZ³ùaîc­Ñt1‹çÆÕ5USס¯kZ³±æ8 MC(Öu˜bhA}]?¦j™5]Ó¶¯iººÖÔÙñÉ…Œ ~6%‰­*ï²àü?‘ Âá•Ov±r–NW‘J§TЍ}džËËf5< YqL=)fg…rFìë$†_<Þ„­Þ´\O«ÄŸÏÑü{P’†t΀ˆ®érÑLŽF c·¸ž+šFiqwÏ´>Àcqaq´Îî..<3öJ{¥Ýg Ï Åââþî®aâ´OK‰t¼OMú÷y§ V¡Ò©¥b½©S÷YI);~ã;žÊõ@}ñD§/ SÝ·x2ˆh¥Za)ÛÖË`»@só…'¦£âÐQñ‰M×âKUª}ŒS£ÿ–*á{3^MÐ×aÁæd%&Y{3³à“­µÆ5ðƒnj ÷ºûþ“5ÀLwž4MÕ\õý{šÖS8WwׯçGwÖ4—\‰ººÖ¼î6êPsV|¦ùú²ò¾"ˆþj=ëeDAHS¤_¯Üú?°^¬ì­Ò©”"΃…ªŒóZ¿q^?˪VŠ…b*ŸÌD†F Å|~!?-&FúóI!!$;¬v˜9>L÷÷÷d¶_,•ÿšŽ—€=07¤½3;;–.'÷Íâî"µ°`™¦a}hîŒg ùPàéùüÞîî¾i–Ì=co×(.îæA’†ö©ž.ÆÅFºDÅûMmñRê.4µÕæ˜éV;áXÇ6+d¨¾«r‹7×i–˜!Ýä}2b¬:‹Ò}¬Tp+ 8f|É.NÄ+8jTŽÈêÎ)Æ\Šò~ølâÔJ<€7ï°GÈœ\b%Pý‰Íåç$Ax¢µí®pkˆ«kÎ=ÊêÔ—s@ejîÞ]wÕµ{¹Õ'O`z¯»:@zmµîÒm¬+×®­çΊ‚ˆÜTÖ$ 8ê;~ÙñEèìŒ ´[KÔðë½ÅãLËŽwËóùí0CÇèŸ,#lŒ ˆTÒY627ŒBq ?œ¢CÜu ÜlôzÐþþÿ´½Ù{nl‚ì„`}HO[åäh–Œý…}óàƒÝÅݬû–ù ”ˆ ecoo7¿g–,kß4>Û]Y,|`<“ϼ“Ç>.Æ^­#i½Õº†58¼›Ü+ÜŒU‡)àp§ÃÆø 2Ô0|3(Wª6`—U‘,UƒÞ+x¨l²ÜYå®%uÑnçÑ Ã(z[¼ÏÞ$ÿÉ›/HÉÉÍV}ÕÖ×®ëîbé:Eãµ5ǧ´³®ÓìjãÞšûá>ÑêpÀÞu(Âë÷+êêº Ãr½Žì¨J3çJÊš+¯ú’—ñ}qØË ˜•Å,‘rµÕ†ZÀ †?vZ0>Œ±¦¹p¤“z zcS:e&’fÒ°¬ØpæwÅxÌc)#܆~úÿƒ±xeêïîžÆCî| ¼!bÀA=WΔ‡ 1a±¸X4?[ØÛÛßßñl,îî« N2 µhîöñIXølwW9«AA€µ¸úºOa¶5}˜£ë­RÞlU'6©˜ÈŽíÝ ¤tÜ?ÝyLaäã•[ö-kžàmÀã¼^0ʳ8d©áAu1Ç™âÞdéÆNµ;¸´ºT]Ú¨Tx+ ÙêK:™˜ ª²H–Qa^¢}ݹ§;Ík°õ{®K×ÌiîÕ\C]´Ö5ÿZã‰ë^_m4®¯][«»z½~Ouš0.Oœk ŠÚ×Võµºü¾ÚTW\ßWšu_<ÑK ¾Ô𠥬)g¶ÚmÏö½VŒZzX'üÂjl’1at¼ÂöEè›NQLƒ¿KZF 1(nX…7E³ð»,‰‘, ÷‡}óÃ]ˆð§õú«×<"JžýT3…Œ1Z6Ͱ¹{ÀÖî æáLLb»Ý¢´ ~4ͅϬŸí¦±»øÌ/..Ì¿­é©df4VØê–Æs¯ð §òýþ þ£×ân&XFU VƒNPhÔÈFU[¼ï6F•T7y¶äÆ1u«²±Ä+ämw„Ç ²8™›ôyñN“2•>$˜ÝälJ„®õÕ[Ô>K¹¶ UC8]×€½•k°ÍúŠÛtXõk~C«¯6TlYW_Õ®­º«¬I®÷ñRpÕlªÚ“õ†¢^óݺïÔ|yT=Áо°êûeAv¯^óë«;ìt ªñ¸—5òÉl»Sðºþؘ ”³ÇôrVR´ÁœXÎjg4¥œ9–N‹‰D ¯ï%×1ÐS(ø‚.ìï1$ÿëÀ@Jd•rì’Ÿúo¯3~€’È$ e£õ7S¢5:VÂe˜Ÿí›{–Y×}d˜ˆÂ–¬}pøÌø Ü·,ô¾Ü3ɘì.ŒÌÏŸTO%­rÁŠN½âr; ¼­©€·z|êf§»z+9ÑbÞ€µˆBëQw›(¯)¼ÅÛæ!û­)ãªé0ËooÜŠm,m,U'».|«Ó~äòX€Mv ×?ËöuÖ·sR€GñSnUÉ{ _sï¹õëà·Æ—ÚÝ.7®6Vïkuþ„ Ÿ€÷ZN_¿æ6VÕëMç @{ÏÕœuõ:¼ñšö¾ó [2 IDAT$GýçVVäë¶ï×}¿¶LF؆ÄšdûY`¬_«×²ÉNú‰Gï×k™t*›êvÁ ºÖ °Íg¥hä …ßL …üBhx$´ÐŸþÇÈB!?œìKË–”:¬x€û;ÝÙþ Ì PÆH$DÆå•Ø §|ª¸ÐdYÆi%D£I)•L¦c|q$g…Œ‹½ÀQ¡Ã€¹ÜI3meF¢ý°ÞÞbñƒÏxö÷J%D`ó`oÁÚ'äý—äw–™þÒ2–àŠó‹‹Ÿêï¤âÙh¹ÈóÄAìÝ⩘© [åýÞΓ¼Ñ,å‡wq²æá ó;]Q_U*åŠ|$ÛÑ(w:òR ëC²9±‘Øìa×*“qÌkƒñ‚ÚÃà©J]¨¹ÊìÿXåx‹X4±I5ñíkõëÍUuõºÖ¨7ê¾ë®ªW\§±vÝ­¯¹M AYSךõ'T ÓPzëõúZƒÚáœkTŒPoø× ëš~ïzC—jñ©1˜pç{²'”/+ƒ ˜Bf´4y´Õúг ŽlÇXOIÞi2 Ãq†Ãx¬XHFò§ +SNP&Ð(Œ d Äàø@_r8OÉèCÜ™x•çÛßz ¼§þP,íÕl_%O2Y!ý™…Si6îƒJ±$9»˜N¤RIIeU†Ôm·©ñ[Ê$2Édèé@˜u<"Œ ˜ã-!øå µo>[ŒÀûZ?5÷M«|äH¼¿w|~ÑÚ3J)kÏ*ŸYû‹ÏvA{{{Ú©hš…|’ ŸÑâhë¶Pô yœGh}o˜ûÇç-Ùúh4Ë¢±±h€,‹¦öΩ¸YÀx öR€~«Œ÷»Î ¸S8 €GSÍóq4¡íí¤bŒÐ¢L Ropj þ$Ud†xìÅi‹+½ ãFœF°¡ÿf-ö|`ìÁ¨çwàmÀØÐ7Yk51-Ukwâ}_¦·ûZojˆíªëÞm®]]V/»õåë&(lXº{ x媿ÒpWõÕ¦v˜Ã kîû`Ë{¶¦«ðÈ ¹éø^Íψžì_ömÛKA âpÖ¼Œ-f¼Ú]Ú}’ 4ºöe¿nׯ^Å;@j;ÙJD_U€FÑ0cÅSq#ccr" V,D²F̰ò}‰ˆ˜%þ‚%x%ö¾”7éë{šôlÍWEß–\;•D!Áh2Òò ú¨·Œ¢jŽíÜõ%©”Nzªç¬EQ¥îYª¯H5_Ê&“Iø|’”UŽˆTŽ5Ä}0µ„ŠÅHÉ‚ü>¾a)Ó²g}fYf ˆûÞøÄ*í/0Æf©„wŠû‹Åg ÍÒ)]³äb,Qf»ËK§R@˜¨z”J FdxI©mL<¬7pn/Û5:5D¡C¡\C‚zèˆ7*‚‡Ã%ðtI§*¡Ú¢Ag6bAðÍ(v‡WººÕ8A%%|3€Hê?lxúrïÁ¨}uµùGc\±/Ãû"×ÝeǹÒp|sáUW[S­Ñ¼®]uVüËT¸î6W\m½Þ\Ã2÷jÝU¯4.MYÑeÛ“lÁöë—ëõ+¾Ie2äEê6í P G/ëË5o™øï®]¿b{‚-¦ÅLÖ‹¿ ÀB±ðO‰¢Œ¨/㎀'ÃHä5ËŠѾÄS53/ ¼vý4ª^¸ƒTF T tš‚©¾þX[ñU{Ù¡4“ˆ­ª:VÃ*Y!Kò:ØSµ•Ñÿ îD ÊÙÎB_bÅàÑÁAÞRÈ[ÅLißZ\x† k,>4 ÷‰5Dàg{¤Í¥Eò0o•ÊV©¤¿£¥2Ð Cþe;Qô286L%\ÑX5Î;=$6³Ùòêˉø €@‚žÿØóÁì5¯3%#Á¸O\óuFk¢¾Â¬÷&e'‚!·X¶˜çÿ*Ô­›{´Ÿ˜¬²òjÆç}T}äËýµx}_W‰ª¾ˆw¥®×/¯¸~£q¥~×m\…ÌsVUíʪ¯5´•ÕÆ²¿ê»«.ø¯Ùl¼¿Q×µ†ãÀ~\ñ¯6Vz†Ä^öÜæ²ÖX•ë¶RÏf½¬ïþl NÈiqûJ„á¬]·3BínÝGìõñ¶»\Çáô²™´°l{íÐ ¤¥ãYõÌQí'‚x,­å>Äl9«ªgÕcb:$å¨"‹Ö¿~à£Ë |Š_SaŸ²8@3Ùl6•¶±@S +º**$1!.›>Ÿ/ÉŠ²,+’/‹¸yét*ݶÕ#’t”Sà k )ŽÅÊùÒ¹X˜_Øÿ©ñ™±8¿hüt1ö{Ëú²8´oì픂¶¾/R‚3¶Ì½Ÿš¥ƒ’þé©h6 é;k¯Ì®,ûAdͦÓà¾/ѪN0‡ù»µN 9âÀ‚žCëã¯ÆÞ|ìµÄÁ™U^XåcTQÃG˜èŽ_euø¬±žeúx7*–F#T.U6»u1•`´©Né«ãêôw ÉùŽ‚¤V.×]çrC«/7œË®s±qÕ^uGv¯úuG]ó]ÿª«º—¨§9D敚áVì†æ^nèþJ½~·uˆò&<âÕe‰‰úòåúÝ+öln&ƒWxwEûò²ëÛ—ë—íå:1!Í1‚±s„d´‡ÐR%±XŒ‹‰‘‘‘á°68˜¶ŒbÁLo$’¦12Ü|gx>ú·S`8ýQS†s’d@êÀ“—%ø¥t?ˆdÜ]½.…kD CØMVk©¬Êt´Â/œ‰®¯`Á*ÉÂL625èEÿˆ(qd-!Åø‚ýlÑ´Š‹# Ôø;¿»°g|·g~W*ý_C°ÇÖÇ¥©ƒË¥¥ƒ}s¿”)•²Š•Œâöà%’Ë ´{³ø½8ÕSñh"Ùö—ësõegÿcv$H~SðÁê6c2Ͳ&[ÝDN0Và»ÔnQÅ0¬R3~œJX+7©ŒÛä W Ôÿ4ÀÖËp㯿é É¯è« à3çúÎÕúåÆ\}µ â_u ô®Ösî üÈ]˜’ëõëNcµáÂÇ^Qº+ê 5ÿ^wœÆU¢£6ÝúŠöÄÉ]µå:¶0ãyîeçªë,;¶#é±ÝFg$bólýòc{Ù­ÏÖX ¾Œóú"4Û£íXß@<ö´¯/d¤2Y3“)¥Ì”UûCC’i˜FQ)YHX…áùùÿô$ü·œ‡þ"{¡h题õ¥Ç’äùí lD†È@Wìt]_ƒÔ)V{þ²Ûá²zI_ÓWq÷¨@pg:›öd[–H"KÃP†ZBŠÉ¢5¡úwçwŸ-î’Å0‹–õÝ>dß¾_ú ÷¾·ŒréKÃ,}Ïbsé#‹•c¥‹¥¼íÏÝÅ©ìÛ 9ŸAD í6Ú.˜ô²{‰6:tÍÚ³Ø_——¿Yœˆu Ë6"r}–¤ŠM»tg6íK¯JÆŠùßgM«ôQɺñû%£_P‡†T+U-§“ÉRÂJñaa°0|#ôôoß@‹"(œ+¯¬ùăn}OòႲ³„@ð‹²ªæ‚átD‡° kå‹Úcÿ1ÕªQˆ^U›@¢ëŠÔ™Íb£dŸBðBðÑ¡!j IÅÑrÊúõÙBÑXÜ]Ã}°k<³Jæa½1o•¬`„à= Öä`aßXX|V2M*ÇÊ–RbayÖž»(m¸Òi–ïÔ$}Í ÅÇš«8ÀhÝ›•6a"z+¶Qác…Üä9Ö_4 »ÜX®w¼}g@á_°‰màÀX©»õKŠ|Éuæü9Õoø¾s͹àRôUÝYßt]Ÿ/Iu ¼ZWÁ ÇVî\C¿ª:6‰ Ïwç,=âTáBhy <ÓLýŽ X»¼<ë³l~…]ämc—Ö¼6ó‘…´Y0GY+™N†#’>4¤eâ¥Lê†a¦2V!Ö? õ Ïÿ ø‹z„7Ù× PW€?àÊ‘ù›~M¼ƒ°FèÕ€;Ÿ©=MÃRWWa²‚,I@žFѧ4ç+U_Å;"Ð*§ÛYA“å@ ´„ä `mÑ„ß0ö̽ݽÝ}Ãü~´ôѾõF ÞAx±ˆ¼Øí—F@“æÞ+ÇJ¥źsáòl}Æ›­mcoÞñ.,¸3[³Ë«í‹t\¿š³ç.9—æjØ£Û€VþÃß~~{›Ó ƒ¡à%)8 ÷  Æé‰„£Á`b‘p…Hˆ éŽlÌFW¤ÎÈa6â¬cƒº WâK›¬ßÃ^—‰kŽŒ‡[€Ó¬ý¨Lv.ú¶ÿÕe{NÅüEß_ñí 8+¢6ÖÔ9˜„k¢lÇ->®ò~mÖ¿zA"Ò¼¬5TçªêªÒ¬—Îìxö,ЯE ¯“Þ£¤ vƒ]¿ƒS˜Ø”X#ÆiËÎÉÇuZÐuj~=]ΔҥH!iF"õŽ£h&4àgš–‘îËGÏÆòý}ÛlwŠyÌ;h„?Êïu’Š-ÄEÕ_¶%x©;¤èÚˆ¯€™îûú¬¢ök GæÙ‡7qŸM‡N´5Wƒ³ HàЯ춄„ûäm÷ÿx àÁ=ëû¢1j.¾7ÌÏŠZx´Š¦Y>#ïïš…½EËì”cågmûB}öâ…YÕW³~í+ßkog3©Œ7c³ æ\¼s¹~i{øR}¦ÎÅ•ç ›~êøyp{ØÚ Á_–&ºíÔ`ÌjZ6‚a¬²Ñ¾‘¹ Ö'³Â2z²p%Àl€×ÚPv0š¹2Q¥ü6KMP“r…ç±Ç· ë e†Ã ~½N°€²¸@¯}Äû‚ZWVœ•+`Á¯TöyÎ&T9̽?‡7±Ó⪰z¨»)KÕöÜ9ŠÁŽs‡»±¶‡/ƒ6Ä×Ú°«lhèìY¾?ê³¾‡ØñÈhwf=[ÌŽùÙÓGsŠr,“S’i^Y˪öý´šM%4îRΈ‰)þ”´“eM•= éäÃä* Œ˜õ€OQD\DÈsTuEWTjßö(ÿ쉂î8Çš®ù4T¾¦S&gE±OÎfå,Q*c@^øNN52¥r<-™ûÖ‡PyϯÅg ‹»Åkï ô!Ã[yߨ·öá +÷¦™Ü-ŒZåÒ~PŽe&=ÿâÅYoöòÜì{ ÏßÙi·…ÛÞyÏ›µ/ÎÔç.Ù3¶ƒâo‡>Úyþ×þóï9d"1b›íóm¯§8ûMè›0o =ýõ@(tØE^c ;dJÐÈÞm+èZ‹§‡æ‚ z‡Íӽ〲B°Èf»€dÎù³~„ Ê2 0{ñŽ Æ¨­þ• úÒ%œâ`@šÖǼoÏ}…hs|”N·½mìUûÒì%û¢}áÂÜ*B‘°¹}û?~÷«/øòùÞ6ÏÉÎ1*$¨WÎ\Ý×fU00Z›þ„jõò%÷H̹¤Ø¾sÏ.Ñ K|I¥MÏØ—á/º8ÍX ØnoŸÃÍ÷Îys…iήπoã”E„!zØ‚v;iY©ðÏ«Šg5 cXhVÒLèÃB_²opð? }OSÿ² œªùš„àË<œ•¢jø#9èÛ€¢¢9we…óEŽ„Ôᆗk*kÞöj€˜èI8÷`S€=hC„ã­?-‰Y/#K1 uI‡t].Ç,œ•¹· å~üÕó?”óÆ¢¹w`}W2;x3~ºWÜ[0„\¹<4ô¶–/Ü0ÿ>(ÇJçüúÅÇ„;ïÍ.{Zv¦·AÞÃ4àlìÑK—.xq²Ûç½ó€gºýü»ƒ¾/¾øáàùù6x+€;ÓXÖn…^ª£}i” ¤ÞÞ }½§¼PçÖ;¬Do¶ÚÀÀÄ6DÂì ~#ÂNÈýdü·ü 2xÙçû–RèsîWõK¶ºâ;øg†PCø»ˆ|Éqf=…+AÈ?f® ÕeHE"x0š÷عOV·±Kl¢@ =³S÷ê3µ™íŠ$IÁoîöÀG'öŽ7ó(mÄ­R:r*Y4ãá|XÑŽÕð)iÓ4FQ4SÅÂ@2t,7x"6ŸüòŸ²"+à9€H¡]w|E'Jé!+T_ R,¶%E¢Ú„,¸){Ë`J_&÷!ƒ0—ë4F„ÒÔ›9Ue *$(imY¦F=¦yKÜЙ³eÓ,IÆP¡xPþà¹ð¼üåwÏÿxŒ‰ƒ¢y uñ¶¸·¸°`XòÑâ;ø?ml×úÎàåX Á÷j³µ _Ùx:_;ïù3ì¼nogzÓm€ ;ðÑLíÈ¢ÆÀÓÎ9ðAûyû‡ƒÝ¾¾/¾88øÕóG·w­q\v¦³möO­È¿aoÿ@ìá¹oPàeÏxÞo?'Ù6öú{ÞœïC´—.P½À¢«s`m%Û;@ CîÆáªsÅs Àä „bÝg‚¨U½Yö©ÞLðêÎÞn{ôaçHŒ<ò.Øì'#\kwæj61à¬}»iÓ?Û¶X„݈˜²™(ü¾ðßci-7˜;Š%½B²`©ã¦™4C}ÉäÑ£ƒÅh6ëK¥R²]¸?œJÄ¢?e-µN®‘5Gòÿ="–Œ´Q(…ò…þ¼”4,_°\²0(¡ùD¡7-ý4AÔ§Ú‚„mßì©T^@ÙøV…€H^DUtG£ö…FÞ”0©aƒ4¢à‹jɤÁ†b¦!q—Îf}8•†„u´Uj‰Ó”2&ª$ÙË’îÊtáž Èð¬ W.>„ ùñ­/¿~üâGýya¿TÊ”zñV.}´ŸÒ†R7ŠÙVŽe%³åt)J?ªÁ¿wñÒW;ömoúÑÃiêŒ8üèá¹íéTû>íˆÁ;`À÷vfk ºö?'~¾ëýjß;7ݾ`ŸØ~8óà!þéÜÃÖƒv{êÑtõß±Y"Y€Ä³w(ëâ± Çõ—GøªyêŒ^^]¾è!ÏÁ,pÆ”8ªM™›ÇØM¦Ë#@"þvÒ(³„MÆ„¾”j_°ç·íÝñèŸy‹Ð¬ÇB-84…‚$œ¥Úá†bá‚Q,œ,ĬB&>1ÄD܈¥à6Ù¡°2†Q¬,2¨$9•6ËE€.ÔI ÉFb8ß_èædúC8w(–" zfž$z¬zŽ×†ÙU Á²£;ª®*¬ÜYå-!°ÂÀ#\\®‡øÛ–Dp t (7C@ö*ì ¢/ º‚0ì!òÊË®4j'TQÃ7°b„¡@ž€sOâÄÊÀGýˆ€¸ûI²¾(•JÿÅìÅÛÿ4= ò­ÎoY+Dz£CÐX?~tçýEûÂöWÞô¹6]ZaúÁÃsçB ¶L¥$[ÛJúüÎù¥vîáù?üâþåÌ_òë/ý?â¡Ôp<ÜÉ8EÛ,£,*¾è+ör͵¨)„/ Fñ5M¦RSÊùBÊ´øš£Ù„K™À¨P$•2¾çeR©tF ¤ A1“N#–SùI@LB¹+*IÀ‡JŠ:FªRæmÁ¼uHò #R,™?ýüÇý>⣾/žüjÑ*Ö‹7á³½}ëÍÁd¶”.ZQ#6oZ¬+SMŽ £Ð£é’Ù>»ûÞìÌöù°"ÐsïAjO?x0ÝúoˆÈì҈Љ¹‘¯· ‡á~ñůžŸûüG¬”ËÇv§§ïŸ»n. Øš~8=“M¶Zñè­p'­ê 3D76l^Ðo'¸’åŸÒºAéUÌn´ IDATèi*¤}¿C‘@4C9¶ú €92„1†?éT<–l·3Ì!x„:‘v=‘R½}žTzñ¨M85Â#Er&.•P^Åó²—EaØ©Í9LnÎ06}Dµ³Tˆ±ÃPITúˆðG¤ŽeÓæ±Œa¨à%‘.èF"]JŽ„5õm†À\šäOY3e § ùcÉ´iEò ÛHòèñB²8Ÿ õ±‹…´©µ¡aQ¢Œ Ñ e˜UB†¦J4ø5eT”UVÊj«¨Ã$@3 ¿tBFÊÒh¯Œú8S™TV°5j¦‚,—ú*ÑàMQÔ¥“Ù1Pê„`b@]ûHЉTú`ÏzóÇd‰²ƒb_|a•JŸq¼åÞF‹9£¤ Rûžš£ ËzG׊f*5” ‚Å–•jŸŸ½ðxæü¹sÀݦIN·¶§Cº4âvŽÏÍœoÿáù?>Ÿ¾¿µõck²5¨ÐUë6Ój±å[ÓYoû\í½‡Ó©½‡ÆÏ݈ޜؘhUo}{“ ­[aåö„½Ê8oŒûf<üÍxä[Å,ô5!ðëÐø@xü›_‡&¼9²êL\i@mVF,4ÇB$7  ,P@Lq~{  o³ô€<ÍͲä$%>°>à ݆(Ÿ…ò Ô{|‡šÈé[¨}A`ƒÜ#‡Kf»}[ ÆèvègÁø´ÛñXûA ;ò‘yã÷*d ™L• Ë‘#ý1`@%™LZIK6Íÿl (Ÿ- ¿/'æó©ÈÈ ÿQ)"¥åÈxè¾Ç ­|†<™Fé‚<£ø«Ùäw_*-ÐtVb@FÖYa55f8tPÅv èèB}BŠÅTªï1#œÎzšÃ>Rm¬j+ëzN'yâ„$ª§yT8.vðÓÁ!ákíŒXΘCê×éô¾õ÷JîGÀo÷óa‡´¾3M%GÍÉ#_ÞÊx¶ÊoÖß|ãä©“ÇËÇÊŸ=;««fwîÁô¹ééíV²õpkú!]í]QçH¤¡V²ŠPd¼£C§³ìªu[­-¾¼ýð|tj:5ý ME‚““Àá+œÞlmNl°Ay©U˜.Õô-n•ð·ìo•H­x’Àþ¾êÎÜc{–jœÈ‘z)J±lß!å?C¢ß#èÍòt°Çà“Á:ém ¶wê²èc]»[¼#xAï‘„©!ÊÍŠ|ŽÝ!Ñiƒ£Àÿ…ÝEö/¹“¥¢µí ¥·³má‘ÐN&R;·ëLR¥˜•µRf¢l’ÖGù'I#YJD´·U@â¯1äÂï’©´a$ ÓLž6“ÉŸí&É“’rô ‚ß|r a>ð(ÍL™<_–æ5U¬Í ÞC¢˜ Ÿ R™Fõöê +Ì׉dAȃ==ê±¹´±ìP+XMf­Æê\WωQUTO‡c’v²ÿ{„ÄÏÿP–\ n å“À­V%FKÆ Ã2 ê£T²Ì½³geÁ42Ѹ0J„e,hZ–Ù~?<ý …蛜º?ÝÞš‚ä—F|\ ‘Qp¼©(©Üƒ«ÖMË)rCNÓE¦ w[ü²†T«ºÁêª( ¿¦¶ôënÛ0Eß°æqY¶Cî K´ \¿>5àÖ©ík¶î׉è{‚V º?fbŒ SXÕ,EL"Ýiް$ÒÁJ䨃'diÚ,O” |žŽ5ÐC†=R7Ë'ZÆÊêHXÞ©yeQÔ´œö¦(hâqI¥ãª Ž Ù¢–ËqÔŽáWŒ‰Ù±¬X©NLŽA£¥¤äh*6ú4–ïHôÇ"ÌHøòcæ?èÊÔcReõ̪ƒ° Z¤v[þˆWt¯“D5ð*©@U£ð-┈AE¢“,ËŠž©þ$#RÄF<}V•uý„vBVO¨~})}R.ËŠ¤atÆ3¹”8dÐ !pŸÅDso¡ôãüÂÁ÷{e³”c«dùs¹ülß2wËÔQs17¨ž0RceÖ›MQ83ÊÊ…L³”zx~f{zº•š¾?ÕzØJÝŸžf—F|»{ÄÓ²&+&÷bÅâ‚úD®Z§^@ø»?èNMo½»Es¬£û& u¾T­DÃãt%YvÙçoh‹o+áqªü&4>\z”ª¬B_·f«kC÷QkÃÛLàµÉ‘ 8k,}¡Þ%7 ¶òÊè:4çÑø4ÒÆ²ÈŽñƒ!—Cœé åe;"kCð‚Ù`1¢gO¶šÇ‘ëy3ŸÏ"Å‘‘âcÉB~Ž8_ FúÚÂñ hJ–q#þà#‘¬eÆ-È dºTÊ,„ò™áPìžB‘áh‚‘ß㯈ú(úú¬àŠLµ`ÈT£Ê*KŸø>•P<Ñxq»9D–A…òc‘’Ð>u¸ôd9»LélXál*Eç–£á)¤|öIE, å¬x¢”=%©'ÄQ64G®s¡Vs¨Tf3ª"ˆ àŸ•„Tâ®$¼´=¢âe¨Ç0öUV¤>#Š:˜Ôt1)cê)`xê„òGEyû¸pRâ Øá™!±Tâ„3Lgr¹Ónî´¦•K¥\°Z®KKÏ>Ø]ü°H}GÏžÕSFI-Åig3)@Z`K¥$Xoì´dr«}?Å.¨÷\ q¨[Q¨ ªÁUëÎô,GìÆÿMÓU<·îO?¸¸‹€ :ÜŒÓøZ7éêßáptó݉ê- áoœ0ô5+7% 8&ùÆò}uÈ8÷³Ïm模×Ç¡ñeÆ` óñÍòø#º"—ðé‘bC åÑrƒ‹q¤(vßí¬áupG¨»ÝƒÁÎ{™>³ÙB!bFcq螘V° Ö솑ú(mŒ S%<‹À8Û“f:ce fª”WnX©ÒGéìhé£b~>=í:Ÿ€OÒœýt™µ¨ù’Ïz]Úd~eàQ!:º ëàK©êû¦64™y_êøF•öô!2ën.`—Ñ.ÉÒ¨×˴ᾜDðUs9I=…P=Fn9{L=®Ž)êÙêq²/Ò عPëÐP©C8ÿ ;U>!—¢±b¾‹FÌïºÊ^×µ°·¸»¸»ûlqa!÷éñt±”MA€IÁr–ìˆe%M£D±9“NNƒÇØ¥õ.ˆ_¥BåÀ~Ânã´s/,§NîïBýmÞŸš~К·Þ-¶ZÕ‰ØøÍ–NRÝýVkjs"ürw7¦ïŸcƒåðf(—Ìš>y;œí°L¦>ÿÌFp†#ãÔǬ…Èz‘s$r4zŒäªˆ÷²Œî‚˜J„hŒƒƒ.ð#gLÎ}‚x›Ÿ² ìà.pd±9-Ä ¥ôh:—S¦`¥­b+å¡‚$ÌÐN’˺‘)eÒ7J‘Ÿ$­Œ!Ü€NÅçûý¡£:5'%ûúÃTéâãGÈ”ÈSUJû©äS%Ù¥–8V¾LÁ3§;ô¬Ù¼NfÙ@ÞÕñÈžN6ÑWÛæ¶¨U6á ŸDD?)ŽŽ•JceëqbP;£iÇô#¾rt(à™¡wJ‡„£kgôwr'R&Õ¸˜©tÜÊ«åzh©`íÅö‹»óïèRI(ˆE#Q“‚â(©Á2ÎLÓJýÞ*e³xœ¢KñÜéIé“Ò''e]{[—Õ?ÊÒ1AQ“NHØ4öTŠ(LS&-µª±Éjts¢5ñ.¢ðºÀà$øú-±a‰&z±ÇK«¬elƒ5µÍ1™wçq‰:j—‰CâV¢÷I6Æ`ÙZ¢@ÏËÜŠÜfPL§Ëé4 ØA³Ž;tlX,æu#·9~ƒ‰¨¯ØowY`—ãa+’0Sf:Y`ìÒFÚˆ— †YˆCo«, Ó“XQÇ 4ùwVéF𻑱Êó}…ùt¤0<¨–C}}j"•Lô¨ÚTb‰ªv¡| kè ÂŸZÐV@}ú*ÑXƒÁIѨ „9ꢂó$…¶Ybä‡]Ÿ,K"V$ŒQÞE<®IÚ˜t2cÏŒâ€×rЖ9NX<X‘ý¡!Î3ƒƒšÙC8gÕSzNK–Ëb𣨡£iÉÒ1…Îû…Q²^8cAÀËŽfYi“4Ydcj‰†9J¿P8&XÖË×hzí˜ØPo$«K4N%‰ÞªT[1G÷>qfj‹º£“; }Ý5Á­v+Ùò<r!ïfüÙǾW§1jÒ2Eœv"' ª'‰IYÙCX»—(ì6 ¸ lžà@©*“ò>å2ÝG3¢ñ4½H$ Ö8ßµ¸Œ9ÒçÑgwM -bÊ;Fì F,BC’¥3©7VºXLÒ+Aög5õmž…1 BÆL[Xè'o¤J7þ9˜Ê Ô„$=;¨$²}}‰¾(Õ$K~`‡É¬²$ ÀHdmêÊAö#çª@"M­û¬=Žš€  *âñ죌Ä2 ÇØ™Ôý†ÁlL{Sʪ’4 úË £07JqûTœxüÄ)Äz„`u°;:–~Z1ž~³ñŽ>ø©~vP?K\øo:úOÔ·ÿÓÚ›êOrjnðMU}K=­©?ùß¹h ŒìvÇØgI ÂápŒcä ¹Óü}I`»Ÿ6Qç£Â½îM¯¹Óýéíé-¦´w)ýîæ»“Õx$nnÆnU[ïnRßÍÍÖÖdu‰Æz_¾ ËLM¸µ yäcHÔÉ•®ÓAƒ´Pn{N¤¬˜•@\À „ã/¤Aâ„_ä ½-Þ–XºAïˆË¤—!ä‰ xËiAaë.VÂ[´ñ™ 7Ø@Úo¥³¿ÅfñN†ÜgÌèvL8­ál-gŲp\>‘ÞҤ옚QÎæxI§&މ´D†õœ*…²(?–F(öÆ3ù>j N„°µ2»¬6ˆR–™dÞ]Ä L ç@û9‚dDïÉ ¡‹z"PÓÓÁ’Ï‚õ¡IÖ©c0þCÃ.•5ùÔ˜˜Qމ£ÇàªæjeJYéÄñ?jê HG‡û䟺ZÜŸ½2Ü{ » …|gŒý‚0F{•I@‘Ë"6KÌR2ÉR™PIC"år âQ!s¬<:*W”»×hz͘Ê÷©õdkkÏS[°ÁˆÃ›­Ö»·bt)õwA{ˆ4®¿ŽÈÃöyïΣ‡ÓÞ,ÂíŽÇûÉËä$öçIË`?ò‚ꪺFo$Å ììX™w„X%Z¢qÄGY€ 莅hQZØ™ÏÚïÕU–– ƒ ËDoª¿B@ôŽa‡`dþ9‰—G¤\Y‡ñ'þV輛홄l©1>ŠŠyÇ(˜…ðB>ç †RŒ/ óøxÞr¬˜òÇŠÃ0òlä›P¤næCü|½[sdWz%VÏ äõÜ÷¹ìsN&2ÏeŸkf%P2=ÝVYÅnQRŒÆ1RõâíEÈ1v„Ý-²21êVOKj6€º±ŠÅÖüÅš²Âò³c"LüùîõíšMr]‰%Š#EÅY7Ž¢XïÂO'­µÛ.‘hª£a£ñ( ]>jPqo´Nù™Íµ©°þѲ©·ã¾Ëeú—liõ÷ðHO)øc—ðW”1h`Ç.ô\ì'× )]&µGPóû¢•²Šhßdö»U2Ç­cx°e×ܹåxý°¿íóM‡û_>-î¿z2ÉÙÙþhÿfÆ~B,½’¤2¿Ê7†c (ÀÒÍ~-nƒùÀ›ºþÄ™:ØU°E?ÜY²)®üdéùÓMŽ;|‡û×C&ø‹ïÊ=:^†Î—“gawºpÄ?ÿÎWÖû’Š;¿ü»UtåWÖ•ŒxAÈ´€Å‘ÈŠt¯ß_ºöÊÚµÅËy°äy å0–÷hš)>Ê=¶¼º1?¨89¢è,]FîÞ_ed°LÒ*˜³a.-SÏÙså“\3¿4Ì•&;ü ƒ÷½1@ …u­wV@ym€IÜÓbKdQš*8e’´½LÑ™H›ÝéM1LÒëv¥«ÃAEj"ÔD1’áІˆ•µQ²ÑÞÛS»}Þi¶×UzaÔÙ±ÊpÈ»”æ_óc*5ù[â`”˽ZZŽ,e¡oÀJm »ÐÌ!ïJ2Ò½~ esíUðØ9èA™>›0Î'¾“;lì8Þö7v.ÙçÓÀÛñœ[örPKç+$’æÁ,âÃîÚ¡O¾ Lží%ûû73ö)A¬ÿ+¿º&ƒtË3ÊŒ<Ë 0ÿžË?…Ûâc“$/ ¡ã3»°ˆ²:îøÊ½mWqV¤óÅw»ÿâ»ßéþ‹ÞwÈ÷J¥üîwþýw¿ø÷ð½ßívÿ×Þ_üÝ¿üò{¿ü15´AÙ~ôž´4xçjùXŸó«%…Háy®n^Ÿ½¤ é!YÉ„QVI§U¥Y‹ïsê»ñÁ¿ayRd7ïOø°>¶2ê†V•i|0Í)šŠGdq m1£(põ‹Ÿýœ²?ûâ;óÝοSÈû~è0Fßû[ˆã¿“9³Õ¸Ç¥¤ÃàiIe€í}D݃d܆ŒÄIRGûœÆ›z‡ÔbMA Ë”Œ†q޼ïÐu$,V¡–+&9ä’6™wŒ”çeÒÅ"Ø£Séìøn*£;•¢¼+›LL#>YÀ‰PvWÀâjr#?– T;™ªâ^:Šò=ÜÖ4m ¬4Ô†²fE¸²ÜÞ»OÄNš CuË>‘Â@Ž"cÐKîœìõWC ©_¯Êg¼c|ÆH[T1H‡º˜5šcJà¸&|fªÓ³¯,†òtËCŽ¿ÐŒ§K:ÈáT–‹(R¦P á‚dzÔ7VÁè…eh@ˆå:,º–,á:Ù|£Þ~|-DVb P$]!|;þÁ¿*÷5™'z¦‚Ϭ3ÎePßIcñ´«ÜóUt 3Õ„®Ç*ãt´K´¦>ÚSl-ÿ×aßµ¥á4ë_’öW#Õ°ï{²Ç¨v*™‰ÁµBÖb)bM F¤rrÀ\. #‡ ŒIúþð­­ü’^Û³Mã*acÇ­axSâMYáÁ:ܳÆXØk $ãss]`‰Š)Ì{ÌÈ@cSM`í2Æid´N31;3Ö“ó(IûÉbt3Y&–fè²ÁJ ák´¾â‚y¦ ÝøŽ¿Ë<5ªŒföy½©–DJš)I[‡ÞÁc±mÈÓTþÅï¬ûå—”xd^æg+[¿§÷è}EBÕ’Ù"¬éÈ“9‚ð0)dpŸß?=åd&§”´ÙËZSÊëëJHÆtHF7•ÂŒU‹R§2ä çÎé{àÇ )}¾<:­â:yt¹w"åà}Ií±ëò,·jC+*óìí¹nP|‘Vê··=jº£6d\\2©•Ê2° ­òmnW…'§¢¾m³Ú4øœ¯ª—D.KÓ ¶€1åUéÛµ‘”óp‡¢ây76ZñÜÍÆÍ+ÚÐHCHúGE÷”¦ÈŒ³„=R ¡Iàô–òXÁàüÚ±ÿë è;Æ[„É@/P4H ·®/í’u>.-'„ÕáVƒWÖÀÀ1³K³ÖÍÜ4©åV–$ô |:V-Yæiž‰˜‹5Ë,ª¯×2C,«rS­¹TNÚ­ZgçožÅ‹ô`t3Yft vågVI„ÕæÆ*’¾öÎÆÀ•m.ܯõ$wD‘3]L`§q¬$ØÛ‰0 CÀ;{n‘|mÆþ—_þ¶G@ÄØ{ÖòÌ^Œ$;ƒ ËЖçݧú^B'"–"®÷eM% ÊÞ݇aþµMÒ@ŠN°ähd³`ˆ²–?qDâøˆFÛùž ƒy®’åÁÿ¼gSꊒô@8<Á1=…/ÙÞ!@P2ø#ß;<†¼‘èæ” }•ihŠfipÁƳ\®Â)CmY¿±`w´F5­Í§TP^¯ÀPrÁQ·ÅCºE‘GYv4ІO¢ÑhØîAǬ\° Œ[Ãáúz³ÝZ}ÙÞˆÚ£a{ØlnÈ$ðúúŸÎþxÔXk´ñu›á |D¥.DódÓc£õ€Ê¤íz”)ö–ÇÄÏ<Çþ’—â î ?u×§¢lpüe—öøí|b¼=fÞŽ;'¥0q&våB{p^¸™¾Ã&ÆÄñjŸ—süv!ƒ•»ìøÛ^iÆÂܲ03/@ëŒÊÈôTÏpƒð~¶0@åÌý.8Þß¿™,“`Ѫ߆lÉôªk1"ž„„à‚Ì\oêÏv¸+2žˆ‰gfj7•TËôD«;ªú…öÅú—÷V<&cŸ–=¨SA«® IDAT>K^$òw-iؾ-{X%aÆß÷m9 Í¡]ýàSfýHŽÌ¡™Æ'K*zƒ ©4&È~cÙ.µ/œ.Ö„g³Òʵ\¥ßéHô;9òù ˆßOž!ÇOI|Ht—÷ñµ¬rr©D“Š•Àb`W•™c”ä) >Ó­OžCqVn‘þÍŠ³0ÉÁx¨–-n>·Úi«=jµÕ4ÖE-aeo=K£^¢ŠQ1ñËëZ„4Iå¡Rkpډ͘*†…ª\Pñ %n c0ÈR#×áƒE‚e‚cLsa±2¸EP¸Ì^zþFüâ`q/vçN&'ˬ¢€…"5•ô»«à “üPšç æP.Ü3s›Áܲ:…Á„š)U+ V;F,ÙÞ U¢QÉö `—ìÃwòw‹‹ä"’ç“a“Ø8ñNù!lƒ2¬BâÔF‘EIá kÜü•` šçaíkP*‹˜ò²,ù‡4P‘{GžË´Ÿ8ðKÓs]1áZÉØÈx)3ìK;¦1Œà©eÙ Euè&+Z ( ¤3òOò¬Ea}ª¢c™²Âü$=æé²™‹Vhe}×|C4#: ©ÓyšF†–‰gz¢v±@÷ Gkn¯ì %=E¤¢ÑÉ…ë£e‚kÖ½[U_$¢Ñ6;ÃÆh=˜þëV„^»’µ¢Ëå±Ü'rÑý‡XƒÃ+׸ÂBa§ºt¾­&ñÛå Uð;tÍq„ž†¡?…ˆð~8ϧÖÜŸóIàOØNÀwÐÀ->¶k™oÇ"»³;¼vËKà8 ÅˆòÙ;»îÀÅZ ®¨eÑ@OSlX½Òդǚ;„U¥¨¢^9…z–½H³ƒälq X-Ñ {$ƒ/¦,Ë¿F@2?sU!XÜÔiY×*˜OÍÔš‚½Z…£jÂs½º1µ)c1Á¬2*ÅqÞ»®eÒ§1YÄ‚g_‚üe™-Α#) ,âPÚÖ 1@@^ÇľÎvÞ—umRwPÇô}™·<:œõÞs]³†,uœ#Ymé­I‰ÇpL/š¨èéy¡J/O y" ™ªF`‡$fðd÷)ˆv_6Î’ï•b„‚½¼—«9-Â'Ï¡@L³ð¿y^†N—š,RY†ˆ8·»­O"5Õè*=ñ€pZ¥Æ0¶$ÖÞ2Ú{Æu1ÖÀS„PÒ¼-4r¤&©:‰DŒžEtœkÔhÆ{F»±¶ru¯±×°)/AeWË›†s_ÆÒIRø«US0A×ñ>r>¢jèãc÷×Äÿ>ÂÊÐüû€ŽêüñÁ$˜lQ Õ€óyLÜwudvcoì~îLªYmL.§s×ÎsÛÏ-ÛñÃ?àt\+8à<¤¥Þb–0A‹ `fæ¼p/ö²4Š8ã,c¶–R¤4Ëj[¦é™±x#=¿ž,£嘄ÀULN›sS€dÉ5LðZÓä»ÊY¦:”¶5±3X›p|xµf¡ØW+û#ü“V(ðŠ-íÁ¼ü,¿¸XÀm8`îÁ1žùÒ½.Áý@"e…LN%TÑÇë”Ò‘O$Ž…â”µµW³Ü=|xÕý‚£Á£Z…–3-×AU+(éCY>‚?G@½CÙ8FÎKFv(ôrè¾G³+€ÆOé5ü´1 ÝÐs°èŠÚóÌzžþUf¡}’=ùiê(,é ¢‚,P‹z*Œ‡:Î)Íñûa\½^¬ÞKT#mEúM"Î-TE¤A¥æ=ý(V¢4é¥ ]»¨ý¨¹·¡Cüªa?t¨¡½5¥õ÷Òú¸¬³¢zâ„`€ÁÉS(vlûü>‹‚/´3±±8pì#Æmÿõ2ZòUñË.,2˜ÀÙµ3vA°¦Î,w×…àŸ_Ú˘”‚XžQÃíÌa¬sâb¶W4f ÈLl0±8ÑÀkE®A dX¼Ü†ë %iºX¤wÓó M–É*5«x–LÎïÆñð¯bÖ¦CëPIXº>a™9¶á™(è•…é䔌ƒ,–·Ü`UNy0òH?âý„ÉDÈOm{i-¼¸øs‘Åçñé_ØœÊØÊÒ‘©ýŒb1ïÓy‡X£…‡Ò‹Ê¦™\"?$_©ëRbÈ"¥9`M‡à•Tžm×LKXR™–ÐÓ^Á¨ƒ–¬—2qx24)Náh96^^Ð%­7Õ0Xfi:fñü¹QšEñ‰YÂêŒâxd=§¼HN{77¥ú°ª› :’„†+ЩšEÌ3î=ƒÖ‹a–Bª?渖ìHÊ"5‹Sf0Åp'±i'Áu‹%ëA€¨®ªè§y»!µ)-ÅwWMçKþk²¤ûôq{,)²ß±”žY’'Á²~´üHÖíSp 0àc7„ÞR5_8åá;»l‹$pÈÝ Ÿpw|ÉAo¼jÇ)\§rKÓ5ÇoQ„g‡\0¤þ—ív¡ëNÑ;(‚ï‘b„2@k æX7Ye³­Ó;,£5xõc³zÛf]hõ'²Ð%ŽSZ4¾b°e/ïOðÎ’Q0P(öF¯Ñ\ë(56Ì8 Ò‘³‰ ƒ©ÁÍ¥°³Oš‚zÙN° ïƒàʤ•X—¹'ž,¡9^ÊùDW”üõ ˜Á’CIX +C>öé%þS(hruSîÖÄûlÙXZ…;aS¤<-8{‡ï†Ü™»Ë 8Zžåè:´‡j€“éºkµ „Ì«šrÅ"ÍEònrv ƒ±‘VfKÔ[åAd(plS ü< Å=]{Lö8ØñˆwÂó۠€5U>Y¼²ì©7qmRÚ¹ë㧪ÂLŒÿ»:âp„K’P[éŸ@â—//–2üÆå*ñc¶9f¿)ÆDd„Næ5IÝå†A¯²™ä~8ŠEÛœ†—Pïÿ1%BO}`¤wx•3S‡OL3(¤ÊJ4°àÜbðõd¤NÀO¸{zr´ràKrÐK™q¨$ŸÎÏ"öaj$0žË‚b·x‹EA5Ôª®î4­O-£0+ì7÷}oÔ…¨xÎ2'míSÜoÔ¢!㎧ÄQk4êí,ÛºL$hPêhm}3z¦B«Q7n[£æÈ~ šïÜPuFÑz´ño|½±fЈuÃàrÚ%‰ha?4,ù)%½mïÔ9¦Sâîß ¢½*`LàÇœù4Ø%‡L½±]ß§,+–{̧Œûe@‚©]ê—>žÔZQŽséN‚[–9k ˆ~e‚1*Í ‘9™—$*xŸ'´šAgà"´—ÆܸͭUîÐãÍñÓûxß²øÀãrÖÕ”…çÝfîÅ܉láYSйxþÀïÆ—Öà77ýÃ6œ)(+]B@ÌÆ)(ìO(;9® ËeàÆ™«ó,ѩݘ Ê’%Šå”eÁJ³;IZÄwÅ"¡³ƒ±n!è¼ ê ¨Ø5¡¢Ô5Láƒë &_±]Üï Öñºü]Š5®ìd O Ó®lð§*2Ó™L+‡ÊÙ“ìÆçâšÛÒú¨¬vöužeÉg‹Åÿ“Ç9ÅMÈ¥‘«€ý.ee°¿Êkª}[R÷ÿ¡Kc™@âËX<±¤Ø?¶ÉUºn@¦ËåPwj¶ŽVVf@¿\ÊT*¾Ϋ§1<•šäÈ?‘™;oi[×9J2ƒR.Ìç‚W¶lt³Lée Kš[&‘ÌŽL•~ÔóŽ(”ÙîˆHôÊt V÷–P™ôŠ^¯×™Ð’H;=~=—ãa é ©¨Žl]ÄGFW)«rbƘóÒ&\#nÎJÇs+R(¹iV•k¤å(,Г’#)uÙàѦSëil¼ BBÄ=à°¤"­*¥fÕª åº8æç­ÊJnê4É9Œžx'w ­øºµ)/ezåÏAù؈„ e“Ó•…Èd¶ì úaU¥âàû¯ÀVÍüìÔ[ù`È6?õ]Ã,þ WÛ–Aq²H9â‰S„ÄŸdi]Éʱ£ò“Žhãlç4†‡( , ¨-P«‚ZÀ1¤:‚Eæ”–e ¤²O¨t`râIJé.© Úv° ƒjÓxnªV©“ ,mìWujd!«¤œ\:~MÎÅðÙ°“@Û*n¢'Š!Ò(U2Mô’NúGBWE¦í7tH9Ù’äws‰ˆu}ÓHÕæw£^ çÛmO(½žŒ­Æ£ýõFÓ†»ÙZS¥p´¢š«J,àÛz²¬”~Òö˜¬cËÊq)Þ£>ÖGÑjîIJ*‚Á1sÇöçMa‚ó0˜;»€5ÆÇÎ̸cžAï8[—NiS“æ˜9“[[5$Χ”áÀ…H3£²+ì|'WA~€x¶Ë*ÊÄ ¡³øhŒ§`‰ÉPžÚu‘ Ä;¡G¶jä¬?.Mš ¿¹Ñ¾^UÚïœs3Ë¿nm L*ÓYñnÉ\¼Ö®õ›¯„‡½úòc_Í‚­,óÙb”Do€ö¯¯éÆ Ãø$Q fÈT#•í1•9ó¹—ÄUn—ÔÿAHÔžÀ¥»x1J…̃Þ_äL¼Êç_ÊejnÙ… í@Ýø&Üû)Ów(zNèØÜ÷\j)±=[ö®S«i¿'ù)%‹ò²t~LjB†¤Ès™)—Í=ž¬Áĵö[Ý(‰•^úQ*D”i–ž¾•é=Ñ{fi÷@ "Xr@žÄË‹^®Š#…bÑÓn*´èWjŠÿÕF{£95i{ÁÃжUÅöà‡×-P;XØ~âs*Á ‡rײ"LÖ$Ò¤“¹O½“0 Oi,ZÈkçÄž€0U¦G3‡lˆaÇsxìº}?;; WºvýræË-0VUcàÔîŸÁÛùX;ÍA.˜‚Â7·2Q¸E–9l ’©i5%ûK”BÍ *  lŠR§ûgÉE’ 2±Ì(WE¤rå¼"~G×vÇïèÈÉsT“§åb0ßX{a@ñ–"³¿²6 ]EÊ|^,Ò¤¬ ׊W¥„«Zx*z!ÄW>ô{¡.jw³RXQëï_\Øú\'uImvزdÅ„iÜÈSÏ”! „x@®™Y°4IöQqHŠGB£ì &Šö©UéÐÄB¡ ᦕv]=9“ráó|*à’EÅô¤ä*`[MµÖ ‘¸¶ÎÍÕ¨fÖdrä ÉeçÀþ*IL’¸§fÊ„2ºÚ½L蚀*% ª§ð·×pà‰ª&𽉛Áø¢nB:qÒ†º± 0b£ÑÞ‹¢ÖÞžrC4ZJ£±ÑPýå) Ú“ÈIçs²?ÝÀ’=ô)fJoëØ;:¥Ô‡{âzϳrÊe¼¢òì×ë‡=HÜŠùóËz¶Å2ˆÝj\1‘åã]7/·ŒÒ(ÇnõöÔÛsWÈ ðܳJ¡¹$WÇ'nf—” ¥89åT0¡Ë&qVP0!OÄÁ»ûç™m¤ÐÍ]X†S.kÒ»H <2eSb.ÝLiš”Pfu1ÑÝቀEQÕ_Y[½ŠÕ°ÿ/ Ê÷3^¸U«Â¥§PE½š<°‡aÛ< ñ$6ßš–F~·ÐGÑuuÝ Æ€±LÏeFöJ¬Ô¥RÏ{o°›ï/#Í1NT)D‚ÁeFôç$1zý„Ñf’SeR¯ Þ‡ÎÀQ4•5y‘vê´Ìs¯å‘w|"û˨ªóÚ}€ƒò•Rþ‘¬œÈ(}iI‘æÐ ÃìÚ7±{[¦ª? pH»Õi«Q*–@=¾W‰2F§ÃÏõb¾NŠ`+{T£ ¤î3Ë8ë)ÀB¡Re´P磸«‰(z¤(Î_2[iFó@k…=ׂ9ö¿  ké2ÙHg`¬ŽÒØ39têñ§lÕ ˆŸªÿw‰´6ŵ]ï>±vìÕŠåž–ÉóCRKÏÿÀ¦’ÔÒâµíSfÝf[Vî’ÞñxùÇWo×W¬úûꩬdFÐè^€¶rS6×X,p7-<ÜP „7ìäo8ç…aZkkÍõ+*‡~à/]*Bਗ਼–B3·ÿXfE©4ㄇ ä¼òhs²1‚«ÍT·j;³¿ßgãiÙ–•í¿3yÇwÌ1hÏÝqq9¿]צ€î/³Œƒ•Üâr:Û*(¼‰­Ÿ«Áå…ÉYÙ?€®ŒÁ­Û”›Ì$U %W³Ç††ÑùžŠæ 8Ü·ÈâJÀ¶å¨ü©&ÀpH£ÄŠÃ^Xå~Õ^‚îúïxáP‡¿kmŒB7c'ØÞY¤ƒ-/-ŒÚLhÄHàO½m¯¹çÛ:6¸àWU¥™ ë•Õue]ÿÆ Ë)‚§[쪺"K“s%*V…7ÒØüRr†úÈp ÿd9¤q79ˆÙOmƒh!ø„AJ–¬Aûñ[9m¦U ].Û‹¬UÚO˜d–²]Û•›”ô0ÙšÄÀ%ÇJRÌ‚B£ð)– Qƒˆò‚€<9ow åÀ݆x”8JÜîÄû-¸×(nG£a3…ùM%ªY/u†Ãæ“v<u¢Q{hGI/zµ6Fí7šÍæ¨Ù\­mh{ë{kjÏ{­t]o¬í5:KYPÿ€{ÁÄ«¨`c)aÐv*¶xèË-Ѓ0|ˆ— ‰ HòXžïXÉ*aÜò¦;á¬ïóK¦¸l§UÎÆA¶;›Ø¥kÛ¦×VéXlBŽxË™® p&ƒÂþm,eý- ´ùh_X–[ýz!‹ü`YÉþ‹ƒ‹ó4þ ¤RB‰™1äÚÉ«¼, ²u6Vð;|àÏ©» B¸ ê²ãÓY6úukãlʦ®5 ?_Tƒp§87 3™¸S?1uÝTvÏ55øÁí ‹;Ò5Åp”‘lïµæ¿ cªö©Ié‡çÅ3lIèf?–hÄçÙªÀrß'[Á‡þ¸€–L“v¶H °òü×U#ÓÐáDr]§Rz:lŠ1ŠÏ S72ö©lD¨ì›Û5³”¡ û}È|‘Ë/¨X6¤2N S¹”}¥0€øó‚cÙ$ÞnEè^øRø^¥¹pKIQ¡Fjuö#éF(Ÿƒ Bk¾7lª¨5j»OT'*X PcÑÚH{MHµ½ÖÚzàFÿ¯C¯™ø…î*C;‚èúrEâ]¶<þðAè?8 ‚£ûGÂþޏãÖp‰…×ziæ–enÝËíþ.Ы§†ÈÒh4zyÁœšÿ‰­BêŽgÞ¥O€9™šÐì_MÈçƒ@…ç<Ëóo.è`FÙs©Lk) ì\œö_¼8OöfÒŽ½ÛÚt7Ý`óvŠOU”®&“£ä…w`ˆÁî߾ߧ ìÊþºµ!sëâdP\”ƒÿ<1ìHd,N¡5¦þJíŽL(¸qz'¬ VÆTË•Z¦>”á·ðk0FqS§ôƒõ4±`I ÏÁmó@tÆa|)»å²;Î>·Ó,‹ãƒ3a_ä†C£9LBA½!z°C]¥†gSÖW4€z™%+ÎDRº’™2BÁ‰º÷eGòȶ\÷¾çüVíx«’O‚@5 RRŸ¬É(”zAÐi·Fi¢èILÁ¼h8¼-T °€]ÝK4EPJ¤©Qà ð £€„?…¹Æq”&iÔ¢Ì0~8…aRÌ&ít½5e¯µßØè‡v+Š{ê^SQ©`W¢ôªpˆ©L ‘:"^â?`T"}„׿Mü‰]ƒö™žaçeVŽK~ CÛzèÏa¼®ôI ÍÇéA<Ü…}OÝ©Ï(¬Pyþ¦lš>ýÜó[œÙ« ð¶ Q| èÜÜÀý&‘”Tø¸ÞR,ØPË…~p~ppv°¿¿HýÝw²ØHªœ»®? Ã>¥7ß›:ÓT™íTUEõ^N3¬A8ƒšs«ª¿nm.]B£ æúbs0Ø1ϵñ0Q  xö¼P55M^$j;Qš|—ê£ÕPuÃHÒ8§aa߀±ì™xI2ÍÔh:ƒ»¤¢"mØšÁžé«ÊÛ9Þ n]™Ù^¼¿o–U©Ñ ;ÐdšæXüG{•^›µ¬\]£1©”÷Æ: +Që#~W[+'¼šÕTH-Ý*‚UÒþîv•vûÑSU‰»ñÇzb€~2yàiàåeœÊAî}žkÆs÷}š€b[v€ý$äUGô(B[˜¥³FsQÆøcUƒÒRbm?ó§õM|%ÉÇvsM‘¡yWž=îýŽýÑ¥‘ŸÁV‹f‡6Š®‹ä‰ÍÙˆŠEª #‹r=r¾!”ôžè LµäñºA©³Õ!º¤Øl IDAT™Zþ–ª ìT8‹$Ú˜Æ Qq õzI¯M¹=umoo­ÝïsGmh­ÆFCÁË“…ö…¬8·(/µª~sìÛ®,êu|Zü I6M&ö¸¦H¬(ÃÂÎ*wÌ·ÂÛ úóê:õÆ Dû§DëÜŸº»|§Õâô(QÇWpöKü€ÎC;$XÂo¿“f ÞìÄ(ĪŸ ¸¿»C\›Ò ¹E…[iªc‘`Ë:%‰æìp‡ï†}ê÷ýÍ‘A*Á±úëÖd¢ðip’¸0ë$¦>‘8IÈ$5S¨LŒ¼ŠP'Dp®š»µHY”YýíoÀÕ¨'jÜ«1pn ‘ŸÇíÇ­õö£fÔzE ­°8ZFUQY–ÞsaÒ:å­a;–Ó¤Yó~¦ºéPzÍX·å0Jê °ÒÑp´ŸD&y`«ú”zœT_T¤<†kð‰w/Ò4¹xó"Y$éÂiq \èK?|¾·¦Âæôg~ùÇIÔé$4l¦ ˆÔˆû™Hl;šy¬k÷r히"¸˜U&κÃÓ‰â×ÁO§”˜³£g©Š÷.”Hž7„ýµcXUuûÔ45šC’`.»Íj#ÛÊIˆæ ±1\8oU•Kç±÷a¡Ì,Pc¥ãï5Š O!6ÙçÞ˜z3CªMýmê-˼TS³Â¬=/¼¤xO=¥´IiÃdøÖ-oRPØÙšfpÁߺÊu¦\vJÔÌX.êÿùA™VÖ4ÒIà¦zaPÙjF½äfž9 j—Ñ¡Š”¬ñ·œÍÓ0Ø&³ÛÝ}è?œ‡ý]JäL±ýuóáÜÊí¯[¬ZÊ‹Š*żBTð­ØHªÈ)CHÇQ ´ÔrW“¹™)”,w˜¦Žz±–} ÆšQ,tKãxD¢?ñz›·ép>ÁRÕ!.w;è´F½èã8ù8yòTמ=0¾€Û–AqÉu*Õ9˜”²¡cGCɸ “« öò"£FÔ[«: ümSŒ‚ Àõ V¼¶/¼ W¢–gí¿Y¤ï¦‹E²¸Hñ!}‘¼»xÑ1t" Ú3í™HZÝQ»ÓŠ; "3“‘á«ØÕtH"àI°ºÞb§¬æ“›ú½LoQ÷!DqôÑ{Ñíe𾔉†¢èk46̬jÔh´€‰ëÚªúû}×6ñc‰•Ë&²äy^ËJ^*O i|å[`€ã±W‚ã¦àT¬L™b^îÔ°¿Ë]<,Ø|•zSJHJ²‚áåVaàEþŒ•¯&—µçWeP8ÀeÙ·€NžÚcÇ ¦á"Ý„Zç«v‹¬.c$%d÷§Ž'«± ‚m¾}¼ÍwüÙñ,¤!3½®;QRyÓ"qm‡•g_·6›ez1ñç?¸x›îš²3àa-‹œ“Q»ƒßÞð;‚A¿6áƒÁH‡¬ci¶ÿ ‹ÏQŸŒâ¨Ù¶¢«Â™(™äy–ùñ:îj5ׇ£f³x@³E|ò2r4²ÚšÑëuÛmÞíO4¿Øc1t‹7ô›Yâ!Ät툸1Š,ÊD»Ò½®µßzÖæEb8Þ®·³Mìä5ödJG½P~¢zêäõze寋`i6If•WpUpçG} ï}^1ëí’Q¨¦z€_Ëh¶aɵ¨©ßÐ&dUöÛ•`lzý©·m”T kÒ°nsª?R÷öšk­¨íó™ºG“*Ú¶´?IôeP˜‡®ý·€.>g€Ð*¦|±*ÕjiY,·ÎŒFQƒ~úXðïP.˜ÒÄÁmv@»ºžÁê„ÐhÌ‹ùŒ/è3ÝÌC¿*²¯[Ûö¦»~߸ ŽÑÁ?·ÌÑWVçnS¡îæÉv¸í¸Ì„×4EO³2£c+ã1›¶J‘ÒâB¿í© ~-X˜¦š¨ÇžsºQ÷ÉhmÙ;š¢ÿºþ{ÓáˆuM£“G *ReùÐÏàÅ”"nüXÓ:OZ£V\Ç1Ó™AwÐŒ°¤p’Õ~^ÇûZ)TŸð°&úZ‹¸Þ:û|„©¬Ëéââ?f¯.^ŠìåË|L%÷zM/È_½¬A…Eƒ}µQÒ½ñqËšÚxÕñˆ¨k7Úâ΋XÛ£nuG¦fA„ ï%âYòxãÖh}ÚÓÅúˆöÏãQ»=jFøì_)Øií=ec¯í­ mþÖÞkkk$Éé0£û4ã…œU@ntÞô³žQE*)dŸO¼ w­ÊqôÊ)KW8¥ñ9«°æõÔ,=÷6'+Ç[ã-&¶V©·¢šz;n56³¬]905†Lœ­wjøŽ[!à*(ìoÎúÐY;/vîÕ?™×ä*I­†=ÎÎåD8jŒç3¶û`ðçÜU¸) »ÔqµªÒrðFÈDt» Øf¦B—rtãÖ–›ØuÛ?Ì6ݵ9IKW›ñ™¬8ÞÜ*î¥é"îú}–M;ì-é)ÝåÐtxrÃr°¬…Öˆ^Èq¥ÉÇ@-Q-:UÜ ’á„×[Í®nÿÊü;“˜%Ãì¾CI%Rª5°Ú†FóCø[Fh`ú”Ž3-k™+¸u:³W]LÒÛ¡ÍæÁ¤J’8gB¶é·ã šã‹Hàf0Ÿ÷ïÜùÑæ§ùÅâÕÎõ-{ùü³pɼVkZæ~"C8òÓŒD[Õ(!ê‰{ZÞjE2û›Þ‹LÕ€ NßêIJæf2V¢F"RÓvTP&@¿—R˜ZIÔæhx˜D‰+ë{j£9Zßh4‹µùð)æF›^¯<Ëc5ƒ*O—A gÊr:Š(+ K6ÁùþÔg¹[UŽ[ÛcU-Ó’Ù©kv ebUc?=è‡Ü“©·-™zƒbÞésý Ë’—6ìûþÌ« gK†aüA ƒÂa@U,ß:©……áFùàZ¬B­\€ekÉn0¸Ñßñ˜®ê4Ø  ”° ¢~Ešnª0(U1LMF •—AYE®™šñi ~ðuk+„ Å3O’]{Óa·¡ê³ìÝn5;ÛÛßß"Y­Úƒ  %{n:ÛËWC¦ìʤz$í_õâõ¨%Þ2 }­´ºÃîÃ;†ïoy9â£õ'qäoA Gw#=Sͤ3ŒcÎ{½x? Dõ:xõúåË—¯éãKQýSðòõËTÑRÕóæý­Às¨WFp=Õ¨ÒÓøÅùËŒ¿ÚëÏû›9ùËW¯òžêå‹lº úÛÜæš^üf:IdD‡ÎøÑFâªDFnW°6è^MtÕ$ôQ Ë4“Ñ6 ?=…ö`{ pbHU3xUÐiQ¬Š§õ…(k·Õ¤«Šø­µVc¾  õqÂý{æ^Ôóû±%b‡ö?„ù‘RL:Í ë.„Ȩa““#ä¸B LßÉsÊMš–«×Ÿ{S›m—ä_ú°À€;%ßrÇ[—SˆßÚŸMiÈã„ê ¨)ksÉa€»Þå-Û̈A”ûwd/ï7nbOÛsañí@h»øŸ‹ƒ±í°¡£+й"‹©8£(á[5dþ~¦SdJTÆ6¶+Ê”™Ft¤pðÄ€›™WfìÖfÄß™ò®-o?­Eùgi¾8XŠ ‘DgggY¥‹*µ¾ËŒ,îÊŽxƒíé4† å†ÇL?6‡­ápcCw°¹kÃJFÍQs¨Ò4Ï;zÖÓº­!8à£æãGÝÇÃ'£Çþ>i==i?qŸŒà¨Û^ß¼ážö“öÓ^sÂÕšSµ(O{öª¯'~ó™ø,½¸ ¿éÅf‹+J™.kMš¦ç¿3ï4½ª¼=š¤ÄàdéþHíuÒ®ˆ”òiOèI L£?EhQäEª–õÒLmF6žhW.œPR¡%qÚZ/"êN4ȉ¤§¨‰×~™IŒç­µ”~¶×úžC·eT(ðf|Þÿ‹-2AÊTQY>ë¬0á4c˜¾gËWÎÆ†“œ9nA plb×þ¹MGôû™+žÚ“­-ŸS°Àèâé}îæI„%Èø<˜]úsgæÝ*ð|ƒ¾ ‡^Y8Õ·€Ž¦‡ÁmÃó¯£%ƒù8K·2ö5Y`ÓÉJZjT°+j )¬eJšv3Y†F¼¼pYžƒ8x¶A‘ïšÑùS¨ÇoX›QX:ã± a<ø_¶ÞÈ­¬&ìKߟe"] ÏâJ¼Q¼9ìÔtZ÷E’1‹,•P¥Ža)¬¼àÁÖ)Íä`ÿøpÛ0ò!9Ö‡ sA¹÷¨–ô1ܪJv±ëè €rl$‘;Ó ÌÕxxÚYZ–xdףᆢi½l–‚H³N¯5zÜ)¦•(S)U‘j¦.g_¯?ËJÁêlœç ãÿgUÿO¯€Ÿ/?{™Š—éKåËnŸýY–{Ñè>£ª_(}Koucx6R<‘Qe_ÚëDê=?{ÜšQ)Ú[Í®9½‹`ë÷ªJÒR‚8ÖÒ(Ž„Þ{Q*ºJꈲ9ÑÛ¤{;ëÖ7´µÀßìšàLdy»þl۹̷îÜÞÜ À@™ûå²  Jizs²*  ŒÙÔ¯Y•̪˚Ž>²wêËàaH£ç‰eÔÞñwùpÏO‚`—6öò û(Ù}/ØygÎë[Ôü}æ $Õ·€Lѳå„ùu´d0óÇû%ì.¶kF§8h‰åËJs]#£+X!Rj£S¡i¡Ò‹ÉÛVõûý¯¤ÄàN0삹+²òÖÈŠ ¿õ‡Ò+÷ûžW$ùân²ÀVÌ’w_¤‹û£3–œ`àUM+Õ ØcÝa eD>140¿Ôt¬0˜Ž:Ñ~sƒõC[oµ××7º”nOº€5jðª}Ïwmkiû›r㪉ÅÛ\’Z3åñÙÅ)]“~F¥Þ,~’h³‹È¢áÇFlQüˆt>Ž£N¢$±‰m³}µp&î~ãÖñ¥,§æœªÈóR†ü«·ª*þ±Ú‚ȰR`KE}é-¥CÑ{l!ê,7°¼iÜ@¡XTªMïÑMM[¼´UWÁª…ˆ4¨ÛëÆâiÆ"™©Ñ”zU¸tšO´6jÄë¦>ðwå¼ÛÐsÆ›Soîo÷ççÛÿÄfÿ|~TªÊÀŸ@28'á JWUŸ^gõÄrªH²íËÉì ßŸ;V<ö¿ºÊ<ô'ÜÉ V*§æe–vN)Ä(ƒx˜ómß»•¬Ádç}pÒqûÐÕ¶;¦®-üÌ*Z2è{ãý¬*óÌ·²ÊŠŽ`9%; ™RÓvˆAÿß®½ß1ºªr'Þï_ò óR{¿6˜û¹(¿am&5óyIåþTq}žZ/3±ÈDþŸÁG’ÅÁþÙþ™u¶?ªîÖƒ`•d4@®r˜º_èÏôàYfh†17ô­(ry'âµëMcéMzÑú£®¢åCdEK;£ž Ëò¢ngÔîÅݸÛîDqÀ 5[í'Í ÿ?)ɳQŽÃ6ùö©cøÿ©Õv«äž:ÿ‹4-ÏžÅÑp'Æ3Ò¿YØggñ½ ¿/Ò{ù¸—²)õuMI¾n;|ó=^½ŠY“—c>tŠf·•ª=ñqo¢é >‰ ”þ¡:T°½{ÊFç"WØ€ñÝKÁ }׈õ"Qï}EøÉÔT„§VWÄÕ«RÜEí…ÛüÎd2±o;ÿl»|Öзëͪ&‹Ú þ¯Û›Ð"¤Ù¤?– Š“ÐóMzùý¬¨¡÷¦ž7½ô\{: ¾yÑRy| • á`àãË¢v…ýVQŠx!Xñvf·t¯Êh€ Û÷!«o»C@<õ&~x-¡pÉþ‚ÙM:±‡Ñá 'V^Ò9y¥3ùAùGúøw¬Î‚¾œ.A:«ež¼•.Îã$;ÈÌúvÿóoX[N SzßÛA8 NÌ¢—e/4±RäìÅùÙ ±wv¦EËxJ¦&µ-•.‹`yÁðÿ Ñ*Ÿ(–øvì‡Kü»±×üÍ+u£õIJl×·]g­E”¯gt@óð Í”sXF™j¨à ÿu¢Ž¼'°ÕN µ­ûŽÿZ³´n×q6O–^’e4LŒ,}¦=!5¢fÊS«XÔqôF"î¾{‘¾™‰·òÜ}ýò• ÜKSq³„q&b{ò:Žöiœ¼EIæNï U@ÒÝ˹ª¦4žŽ ¬1Ùô™©‰{™¢öìÂ\®rž‚ê žÊE/«TÕˆ{I¤F‰ sr(pM% =kïºÍ½íÉ`PƒÐÍÉô¶ÿ©²ÿ©ªg·w–[Ð#ÿw¸3Ýô?V Q~â‡TšZ}>©¶Æ3¸ ¯²9äò-ïÒí‚,Mcx¾LÒ¯"_L $ÜÛ °Öçùè,νþîŸRc:4®56âDIç.5]~èj6¥±¬Ð@Á<[}c°9ÎïUl”8®.@ÿg3{»ºv°2*0!1q¶œÚ.Õ¤goˆEÇo^œŸ§ÚâàîÙ pB[› ,›sÐQ¾kO‹Dµ8HRP=q 0@˜¡8ÿ·ƒm›¦™ÑÔ3Ó6˜š›ò0c ÐŽE(·¨ýÍëÉ»s‡í¦ÊýY·ÉÝpb;ÑšæÎi5=wÓµ±å¼rŒt£i•¯7-;än/z<ŠZkk¹Ã_çL^1R¯¦Ž“Q§î°eêÝ( žÒ¬œÏÞ>}–¦/Ÿ]¼Â[å¯_¾~ýÒ>/îeo¦/Þ¸›&o¤ù²WÑþë}ï3YùjØÕ•]¾}•›¶—Ë~*Ó¡ÚRp/6eT)ûÌñ†Ý³¼ëžLÿú¬ ÉgûpÆ06X_¦Ckr¤¯2WŒyÎ7Çõmwº=ÉœÒéwüÊ®q‰ùóvæƒp°iK¼е­p¶Lg¸Ö> ùÜ)ƒÚ¯`1¢¥^|^QUBµ;Þu©¤ ‡dÎ)r“ùƒŽü:IF¿Â­>+!j`¤Q\ø>îÞyçƒL“jeq·(Ø·€Wd×…–výþM¸n°ÅŹÅ~ðäwìÛõÄ.'4]þËË{o¤ož/Ò»Qš¼X$½·.βóø Pô—g&d ÷$üšµQg&M¬ 0Vbï³Â€†<;xÈÈÅArð†üÖYr°Á6M02+³zŽ¢ë«ÃŒ5VlÐ’‡lÓ;«»ŸZž¥jAßg½QܪP`¾ï€ŽZí^{}¨?Ž=~Ô„.Þe‘1|Ô®+ê£a÷Ùå+Û ‚<ð]ߟ[Íîå+îM„EocÄpmR|<6›x[*Dü ò5~µ`‹‹ êÛJ^¼±Ÿ¾í½z½;Ø­_Ùiúêâ³ÅËôÍÏ.ùÎâõðõ`ÏjèŠÕîÚ£vÚi:tðÂh4ê¾q,b%¢ã?:TŠÿGo@Ìÿ¶%.`5õ””Ƙ’Ç-›ÎȘX¾í£›4&]ÎÙî,øçºög$q·‰ìÕãzŽ]7qjæýÈsÀÞú؃UÙ®Ypg+ø~¤ßvt'„Ô¥iè\ý‡ «ž÷9x­Á© Žê2ú6ò —\Ž ¹Ô#77‚RîÕn™§‹Í?§¤ÞÊ´¼Ð-‘WþDžü  óÆ4aüx;¼ × 6qQËzÀ°§'Û'ÎØyÛúôì JÎÓÈõâ@ÄâͶOܽ8Hßã?–G4¹ÖµAœR’Jƒ fÙ:"!c¥–¿8_Ä/.uáŸS6?]$ggåàO(˜é«¬•~|s˜1“ѱ€ÿ«ö·›»›MPÓÐS“vŒÍëÌ\oØ\µ’¸ÛYo5µv³IùƒfsÝØhn4×›=>nú¯GVOµÕ\ƒWr\u迆«õCWÓ`# ¶ÈGxxdF1MdIž&í狉/_ÆÙK`]v·ð.ƒ ðÞþ‹4»HgÃ7'‹WûƒÁþUª[ª¢ÅØ:z¬«¦!î1ý“,eQ©eùQpžœfµEªÀ‡–qy-‚=A±uFMˆ®ö°M‡) ×Ìá d·Ù|5¬Õõ`{k^T*ŸNh2ÐÜ»=æ6·æúØ’S§™^뜅»|>ÆÖ/ùKj5à¦kobíšÂË;Õ<ó¯bhÉ33‰zÙ@îÌ߸þ©«VàÂ÷wœ[`UÔ —š•éÀ¿³É·€Î¢„{ 1‡y®xÓï׊m•;±]øÀ®‡ÍÅâà®È~ð2IÎΣ»éE~Ü]Äïî'go¾X€öÄÉÅ‹$~ó<Ë-¸àþ,Ãþsì^Q&0k‚íKÕv„‘—®MÝd²Ô±8??Ûÿ,ù³ä M0ô…€ EªçzA9K¾:Ì8SŸ>5mð ~þÕݹ=°ía¼·6¬ò¿´á¶†–××syŠ¥eé¡Q ¿¥ôb£Ïr:6Ö2¬\WgOâ¤5ZoGÆ–?«Ø,sõ^ÞpL\ùؘ;½Nc†7ÛV“nR|fÞ‹)n=ð_Ä?°_Öt4X`š%éÝ—Y¼ˆî ž½ úûöKCUT½Õ튄F22=Ë¢g÷4:w|ut\¦Šïgúï&— ÁK"XZ §j)‚ÓLèl5](¿˜³pwezòšõñ‡Üáîl^×5hÙtk"çË£ª‚ЙL(Hi:»xäv16u½;õÎÆÙø—Te9Ë? Šmæý[gÌœÒö.¹»ãm¶N™¦9Ì©ÐÅ,ø ó#Éä²±"Ô8ÚßÏ2Óݽ¥¦£†Ÿ´Ê,NÜû6ÐQ½®ãÕÎ~®lyû)+àS«»Æ÷¡@Š?OÞÌÀÉè u7ÏÓý³L|ÿüÅ›/Îî&oœ'p˜é›ÉÈÁ9äý?ô yç¡#Ô"£ù¼–ëQA÷ÉäŒ.Àr*(BVÛzGã;8O¨o]€b,$!ÄŽ~f&4Ä>©À]”¯3þ"ÖÛO,oNío¿sÆñÞÀqMÝàVÈ¿¬ci]æÈ>¾µšGämÒ™,ó¦ŒF;`ÍÝÙE@•÷¹®t[ðÈŒÿåìb´Þˆ?¬í3>í _öt[ ’ð"Ê}Üv„#&ÌBem‹} ‰~@ ¸Ÿ÷MT[î‹ B!óùž÷y¾ï]Lfä§®^dºÆÕCÛðÁp؇À›g<:¦ªz"°Ý¢,\ïÀqŸƒ­ÙEWo¿QØŽíB©ƒþcBþËÜÀûsøÔ!*p]p¼Ö/" nB0¨K!§Z!ÌÄ쌿 :ÃNº“¶íøé¹cj´ûç§i[8Ív^ 9—æèêè‹ŒÎÆ›Óñ,Þ9¿Ódt~nJQð5v£Íèüx<†•ûâ<ŒÇ› '=ܰ\3àzŠ:#ÙÒD&Ôò ÐHe žÑL"«™.¦M ¼iÑVL¦s6gä«xƦyà %*P`þÙü÷ÃŒAP)^]þög3ŽMicùÔ¢bšÍ_žÙh*ºn>¬Ì&¸ØÅpYYh-/ÄËgßo(à—ÃÖ™_„­(–Ö­5©H£›ƒ¹& àIöP5ô3§#Õm[ñig-ìÐÇdµ)íV„žÂùlÞÚ¬¢èÅwÅnv Zâü´Švv!p¬Þk –á78-6eþ"—”ziX—×Ô4®(²¦‹ :оè #kíé¬jÒhR¼GÈh#ôýgÒë¸oQ€=(Ü^àw빨Gn~?÷§$º°u­½kƒ¾]CÎu»Xs°­iF†µ–kk‰axžÀZÌ›oæúA‘ZjПƒØNy„gmØ6§Ui_ÇŸeEèMPñà ¢Ö&²â–]¦+O¿«Wÿ’èÚÉrЀöê³ýâà]¶.x,W›F¬mÒDO¸@á|=Œh³hcMéæø\E/°óÓâ&žŸññ|M㤙Ž|Ç¢ v[À‘Nš®kâ¨TÕœ¨¢”€u,]!I,Øæ´šW`±’j,ø¬³É(•mj½-µLf$Šþl˜±ü±daùÛ×f‡Ëgõì;rk é•h/ü/gÏ.Ÿ^0%pŽÑÂR3¶Y3mž—–AR½ :»­haAq@¶ê`·u>Ó1ôÓË¡äØª£.Ÿ‰Á¤ØáÏOµN3¹n) ÉNîìD{ÕÎÞtó\ĀъWVuãez.ª¦óhºW‹Û•h­Ÿ]_á:ÑO7"'`™ Êqš'ö'øQì×b­’LÆ ®<›ÒÕ¤˜N—pžµã>Ÿ½¢çŒ®?°ÛféÚf×óŽo,~0`žΰ4‰•kYC‡­AÔtº2h¿”gÞÐ>¡ž–Æ$Àaí,qm×(,"9¨LÞ IDAT/„ª.Y{%o[¥Ý‡ŸS’”Õ;ëuç&â~MûYG,"Ph¦@€bžxœGÞZ RMü%Ñixr¢›‰{óÙ~1Ï5L´%¦3¹ˆ„Où9 ¸ˆŸß­ø¶[À~ã8W@<Óñùi|­ìy€Áx½ÃŠB‚ï”8XË p¿Xå¤t>â8nX€ÞáZfbɽIhsŠŸs>ç#Î&Õ ¸^l  —”¤«XûgÃŒ™{XþöµÇ.ùŠ£(§Î,Z¾a:d‘]>)9 ¦µùGª*5e¥©ù²¤’{gRű“Sa ¢#BP#6_:c'–ý‘ÞZ?6,Ý–‰†åÕ#„ 8ÅR®çŸ÷ÈÉõÙ|ÞÚmMç±x7I¾ÃãjÎ^<=ÛœïíÌ÷¢j§S±VªÌÐåP2Y¹í2•-ÍTt") 2£nÇŸH2ü÷•™¤hŠªL!pñì5!6¥Ê1DžÀýÌ+ô>€ê0C+-í¢´³~÷Z¼Á÷ëÛØw:̇k¥§cc2bà ðšg¤é1Íx§üéáVÇÍ,Oµ@;®Ùmk:eÍzb÷m«ÀlœHº ø&Ž?ð$Ào‰ð4™â`…MIÙ Ë*µ5p+îÐwLŽ}Å¿NtfÛ° ÚN½_<¯7ŒyÄÙt¦êÓâì<œZxl ü7ÞØÜœ2Êêa›q<³i4;W¡{é¤Z'ïÞh4ú"½˜ÀÃ':Dz¾ÈBOð¼^Šcª,•ȸ¹1³¹Ì¯‚Çš ù.Ãj°×, |p0$Må{Q“¨°V:ÆŠùýÎ÷r§—²=Vf¹¸(è«É^iÿ»YÇ­ÅÖö)¬h±uòLl{õ¶¡\ªfš†ŸjF¹…ý¼Lܪ¿«,œY~¡Å#Ä0ð»ÇíðLØTáâþ¼Õ2mÏ»ÓeªÅ¿?^Šw«|=>ÞîkÅë;1߉áÂU³8^ §ÑnȯÎÖãø`/‹Ö7[Æ.ÑÏ4Bªcû8»&âŒM—TÈMíܤ‘Á4JŽs_%Űk“ëÙü§ð|S,#^ o3ÉïwúÈWµ0ú#Çl›Zá†cfN@홿–ƒ{­6$…^h²Ý‡ ©·GO!ãuÓ§ìqLØò\ÏΣ0GDwÐþØé¥m‚êt =MÀM…"¨ö5üy¶SZuNA nLQÅäDšrÍ(Œž(žJäÚ_%#ÃÎ|¥]ï;¸a ËA•ÁV†/ d à›D³ bÊ#\5 §àÎïp:=7ÝO7#0 c6Ÿ£{| לÊÙ{‚áåá7G‰Â“Kß< ؘM ëä¹Lo+‚a—¥Eœ…‘¢¨ˆx¸·f‰g7²!RSzAöÝÒí»þ Ã(¿ì•¤li†W–¶caÊÞ° ¡öX'˜bð%$ËÒ ñSÝ Màš£qc˜[¦‹?Ê6SÛÄ^”mwè¸kv¶f»¥UZý´m&\$œâÐÎ9ù:zÄrÖÌDDþ€¢ —'h¼ËÓüÕg§ä/‰N'"ÉÑé]Ót{Xê‘“$#¨(âõÝé B,??¡ã,êθZŸVà:!úFÓ„çéÎz<›3¶»> Á8ë_ÀÏ F£×ŽeâñãÇ^gÀß`;X¸J™ŽØÌéò8† ô9Œ±„_Ý©âx³Úà‚3<¡„MÎ%]]"ÅJ©·õÂðÜÁ­>x9‡»¼m› 6±\¸CÁN®&-,þ|ñT£u^–±E$©8»(q‡›8 r‰ÛVË<ÔÞjJ¦­ªlš¶¯Ÿ eSµ—~ÞzaY¥¶ÜÚüER=ޙŸÝwrùÜñÎsÕªè¹]:Û­?¤ˆÌnµ»ÙÚX×¹ÒjÛFݘ·®Ë%šb˜X$k`Õ•ÛªLd³Ùh4p–IZË-ѽåmß´ôWȇDÓÍ'fgK7‚a9\-WJ·ìŽJg`Ø¥†=r Ãê8À|îg˜ÿ‡yœÇ[Íõöqƒ…`à=}')î?¶í~?ÇrË¡I¦ :ä pϱõ:çèÍJd©á+W$:ŽÓ? çÝ>D–TAôJü1ëÜO–¿b<;•Às±¯6’q;Ø.°Ãîà‰EGWé¿PQ]¨vÆÓqWlÀO!ª:‰à'l®O^œ¬Wët4šN«6™¾1Τ»\؟೯=|ýáÁ+û/=9.•(X*k¬©Q‰i¨ ˆÐ ÛˆÙ[œÆp#ÙÄ_<™‹Ç›¼‘ÅI’Yd™¶½g~0\Å1>hÐpBØ=7÷°¥Ì§°_ŽÃ°«I[úEܲŒ-Ï“–Àþ.~üË_Ö ˜²ñ‹(¬OàïÆÏ»‰‘z–}ª%30Ц:Ø… ë¸¶ž\V3_=s&ù üÄÓ'_8£*‹`Â’ìil·ûf'Ï3 ÁðÌ`¥VÕò¹g.Ÿ[ýô“h³µÙƤOLFÀ¢ ò‰¡]& vDR–âÛÍF`ø‹[º¾5c<µÖ3Vi×Êç§Ê_h{ª’0kŸ$æñù#"‰h2' ïÆp^Ì9e|‚ÄÇ(\føä¾xqt~6ªj¼^żz‹Q%y±°öÃÑþþ£‡F—®^zeÿ`ÿu™¿ª“0V⥧•9š,r=ñFâi^íÑÉ|ŒâÕÉ Ñøn &„%ðäÈ"Uo¸ßÅôF¿žÇ^w›µW€Üá·éeYæÚƒ[¬Þ·5íä)Í0åÅÖ/MÈK¿\jµ–‹á™Ó`{Ï,,Ÿ]>µ à‹ZðF­ÁîÙ%EnÍ3±Äå¶av uy%5œ¸õ‚ÄûÍh91R#n-Å ¡1 ‚|i‡Å»Ñæüîù§;Ï;t7šO)«?Œç;ç™]½Ó:3Þ€€ Ô§)x¦“º©¦&ãlÓO4Òh45bÖåë%¤EYa`Åq|s›w ]}Y¼BÀÊ_ªÝDà}æbLó°ôµ_ô;?Xívº««8½£.#vË¡Z¤Ðmè ‚üß0…–gÖ¨ˆÝú€ß³ÿˆ91¾çš–JÛs¬a€gÐŽÝ(¶ì†‘çfþ‘<¾19Ë´À#]M76feº}¢¢83+€;ƒ§@$ð€x2ûœè„!L£žä¦X¶ÀY7F.e@8ˆ„ 4z¡qü7;ƒ?Åý˜ ›þ“€×FçF÷G/½tñÒÃѨΩâóÙŒyßèöûáþãÑ¿hÿµ?yõÒ+½ÆMø7Y'9 ˜­Ù `;8ŸØgÕœÏ<ÐÕ0ʪ–aK%¾¤¤KHÒÞî›–6ø=×U9. #ÑSí¡^¨8±Ç¹Fí©Ó§N5É™S/¨¶ÔˆÏàaë  ;ƒè[@6„¼8 á™ÅErË3—~½‡œ|@å…% ü»†é¬¹&KGvª UÆvó††) ¿ªÝ™VÑn÷Õ;Ïál ˆx¬?Qr÷ü{óOÃÍõV±@jÒCTuC$¿ÂQ'2‚m38]± f/ª¸Q#½1r»È} ’‹‚x~õè¢î?ôî¯úu…ª,+p8x«ÂÕÕÀÒ+-I™ñz>¦HcÆqJvné‚WàtSPa TÌ›ÿ]»>•à]}2kZψí¥. %³­›%<#1À¶²¤I;§±ù"Ý«@¨APá»çÙ‹B¥ }.=z Ãìão}3ÝߟóÑ(½ ¾C_åBX½íQð^öî£KhGFFr&ñE&+àXʺ™q!aWžóì*,>žƒÉš°9 |6Ý|ñ0°‰š¤Dµ(¡D½5Ðë{CÜõïÓeÚbF…1¥3vüOa®*//,,œ‰Îœ²–~¹xæ4üx)ïBô±ÒhÈÊq$®ùïr0ÿÅ‚4VÃðãE¢æJ¾wT÷5:ª›biê!n™Y&VìÁ²ÝÓéú<Ú¬·ûpç¹5CÜÕÛÏøá<Ä÷z¿º·¶Ö‹»2îGÖÓµÍ#øV–®q¢+”/ëƒB¹ù%öp<Ò¨žŠÄE%mû=S×5ùCà@ø˜üTSƒþgÎg¼‚² b¤è÷˜&:´Ør0t»»Úë­A¨p0Tx+™mÿt7GfÞªó´ÛÒ‡oËüšqr°šµ½aŠ)÷xÐëÔ#j\LþA‚ÎÔKu!yjck€e€ÝÍp—ÇÅv–<žÑ*¢s‘­0ˆw5 `× *c^™"2rìG+JÂIjàT‰XÏž˜Ø°C*SÁl`?¶9Û1ãUÅÄÎúœSž§IþòËV_­ýŕѣo_z´å×Þóñø‚=²ón_©£ïÛÄv/’ÑÀypåʃ—1ËGÑ •ÂS°42U%\¼À€cÙÛ3ÆÂñÞÎÎUQµ±¼CÕ`µn^¯ *ZÚòÖÞóíÕËö`¼ÕÕì4æNiÂÿißÇ´Õ9uæ{a1^Pe,;–Ö¹nŸ¥hØMM,³L+uvWqŒÕ± »x[¦³‹Õ°è_pÈëÑq,U7q0§3: ¹·G6ç{U½Ý‡;ÏU Åc<>ÿÐùôWã0»»õd ÎS÷Ñ\’šäKÙ”5IÂè+É™ a¬·ÍsžÚjRäß´ló⫦Q7i¸HT_ç»…k¦Žù' ¬CË+ è+§v·O·–?ƒØ ñy­ ¤è½õ30šŠÛw‚Ñ vœ_³cfvF„ ÈáZ:r‡ea¢¶ÀJNæ1Ãe-@½Ó62ÓéVJÓxXßäÕÇ€pÍ.Ö6]xà„bÆÈœ™iÅßâ¹,žJ`ý•À–ƒ¥î*`XBãÀ€à¯õÔ7Á–ñ8NŽ æ–]Vs:ÅŠ¡:ŸñÀ0¾¹ÿÚÅoí¿tñÉ«ß|mÿ¥·=ܧc®¥ ÿl×í‡û›é«ûîýáãGßxtåÊç/C S¸Æ$•å&+æ¸Ãsàp€ßæñ"ñΰ5N4"¬YE«ž„Γb@@ˆ”8B/Xµo(ª¼‘‘©µ§;F1e*‚•[Zrú `¢Ôí§µ£DýDŽá6*B…{‰xqd´¬Ë¦|—¬fٖݶs[Q ×5á3G¤ö«ò‘rˆx3ððð¸o’¢¦ïVdížÕ±®}¾·3«¡X¿Á‘ùƒ»I¥ Ë2ŸÍ¹µ`!à C¸×ð| ºƒ†°GKVG'1ä.Á-»äfÿÙæK{XdVjƒ2å £:0 9@f[ß#LaÖ¨nk…6Æ;>{ W§°¬<3(7é¯nS…YØnòÑ ,w ®aš€+A$>2O%RNU®€ž©QD³E•°¿Ü%ªÊ\90 IIÂd`Ç–4¦|ΫÉ„ßxŽ:U7=güÖ•ý+W®<„×} ´¶GlOÇ»†eÝŽFþã'û¿‘“'æÃ‡ÞÁk¯îï_¹_, ¡b‰œ›2w« ¦.3â ӄU›ÓqVêìæÅÀmËœê ¦4PP°Eû‰Ó-Ÿ`ºOÏîB0o¥AÄ÷Ìé,S°Î%¡z[–Z>F¸Õ „ŸÆ>‘UYU—¤ÛØj÷ëû–ÐþصàÙ¤¤È%ÛLd£þ(E=”5§×AVt³î¤…Ð%ú‰~·".3piçbÜyŽj(Öo¾BfÉE+¹[Ô¬›Té8K7ÕTIV{JÂÅ‘a˱ài[/ËN[·4ò*Hr¬3à"i‚éŒ0–[¾S¬^6Ê-ˆéû7ï™à'Až™ù ö¿éf— îœãÝhèö³gxtº$/³Rq@•‰ìl¬yqä ñ‹mÛ UÖ†¶àgðï08ÎFv×àÉd¹m 4Ÿ)Ç&Rò]´!úŒ!ªQgÍ6x’%¹åžÀ÷$; °žÓ%RB¢e–U&¬®BJ ÛVJ  gàh)i5+ð½ç#º>Ý2çvi•8¯õ]ëà[O®¸û9àÉ~øðÊ¥W¼4J/ŽF/] ‰sÅyõ xôÍ¿z4º$±FG¯¯`Ý:!mZn4Ij2g;¾¹ïÌf`Afáx<ðtcº©`!ê£À[Ô4‹'kv»}`w hÀ/Íéâ ñ‡Ï¦ü€`ÖR„ÅLÚ' °hDÃ~j,7µN‹þ·nˆƒŠ Bl¦¨zޓ圪Ä×Ö,«ƒÃåãé9@A‡8øG`Tÿ;GÄ Å ˜þy|U– PœC±~ó2ËÝO3º‚Uq u¾[·ê!g¨YTU™Fºa*Td·¬‚‹äy˜’Gp—cÅq¢Š³Æ ÇxÿÚQ0ê+]O±MÔ€^ï ×[uJƒü©ó½¿ÅÂ]·p2#K5y0ÌoxXBÙ ÖÖ2%[ŠÒa0È,†K<Ì<ï2P DaÏë¬"5FÞq§Ñ!ÄNÓÂC%Xþ™©†'usȺE½ƒáû¿xu?rø°Û¶ê63ôDÏ)Ë;A]®n¤2•D#ã\)na½\3 ®âfa¸Ïc­ä ¶2ð›ˆxgÎ*ZíLÇq…HVw'â"Hì}÷G¯"ÿÙé+Ï=z÷‹Ñh $ì7<íãõÑ£QºÿêË/™`†S^¸¢aó' 0BZš¡%’8_ WŽ}âªOãñx /jÐ#ØÂ0¶æ ƒíbdkHŽá¥!QÒž*G ‹ìø°Îö2Y¨Ç)ÚmôXuÈ'j­•ã)Ÿä¶¤ÔÆÀˆj,5%®ÊFÈ çªawpʺ¬šú!О~ŒÔãæ¼ÿ4 ÕÙ2+ùÿU–Y¶ùܪ¸º½0vù5GÄ(ºÔT@ê¬)¼Ñ“·-ë#MUj`@°_ c7qÜêû[×ÞÿòÚïûnÙw ¸Q£¬®•õË{`ƒ×z«èÑ:dz@Œ6vBì—Z}«ï`67¥îЃ”Š Èî–ë½1üIôÄJe°Á1Äà4I›\¢²š›:•’¶››²!4‘),šd Ff4®Æ³›ï1ž©v%]®YÃÑ›ß~„Ñ÷ÊþŸþùE~å‘wðÆèüts,;];õ'W̃×^û|4ÚOG£wJà£+ûçνÄ1æ%" 8¼‹d22ëü`Ò·(澊ª#?‹ÒÀÆ;![ÁÆ¥bÉ*pY»mØmw€' 8Ù¤;èõíÎüø°Îî‚ÞÀ*eœ¾ à( L8ÖœASäŒz.bÝ_’( ÎrSt­ÙEÒÌ· ½ÝptÛVQâ‹Y#Û9bŽžFçŒ[Ë2 ãu¢¯mx×ßËÿ£²LÑ­«âôº²y<`”²áFb•c†aç{¶ãvöìÙ0b¶ü!ö¿qýý摺e~ðÓ÷¿üòK±ƒ,$i ;õžè0X½_ðsuˆÅ’V» fÇÅÍ‚áp˜•Fé´5;è«)8ot‚5ç<F’ [ÜZ5[ÇiVàg}ת4Q€l¨Sfg•ã(HœˆíŽ`)çGD/ŽÌUÓ6Ž¿Õ³rk`ØE¶qbþÝäf7èãép˜ ™kÜ,J¸ð<Šb-¡Š@ÊBÖ€s•0=•c1eïÆàtÆjrÏßv¡¥kðüÞ°¿õðÕWö|±?zp08=à#:Û$mb;£ÁèµñÁ{´ÿÒhôØþÂÜß_qƒë\Õ• &¤8ÕØ.goÓ¨ÚÝ´º€i1|<‰ÎÑJ zÀZí# D‚^ÌôÂ|RêVþ¤ l;[nž_·ÎÖµÕ©%(¥ÂÉ ù¥„õoê!ðž«ѸݔÉmù6@SnS£"¥EŸ‘HÝο–]Ó:îíÜÔ4œmí&m³n¹ìÝŲLz7ÂÖwY"cÉ©ž¿ª=Ñ‹­òu£¸–š+¯YkŸ>­Š3‰jÔJ‰Q÷LÕU¹IrMË;–-8Ž Cóm…-ÖˆÎ"ݼqóèúáû‡7ÍÃßÿ§æO?P wÕj{¤ÄÔŽï ¶17Áë%Px¥Õ1í¬£ûõ9Eá ne  £˜ß †m° ^X”o{µí}*öà;,M;Ô$ ¬}‹÷a•‚j®'1Â3‡ÿÂáÈ|‰k€BXÓ&ÜP(¸õ½b ”wÛ8Á„¼›n8ºN„<A •Ï’D•c‰ ­ ŽV`n–PÀ è [ž«Ñd†u³¥(ïR€yÙɲέƒÑ4!OFß=úüµÑ7÷÷÷GÀum3·£ÑÈ=x5ˆ»Ðû£‡{#wôÅ•Ç#P€ŸŸÿxIÈ7 ­•x€Æ8¹]Ûã¢Øìy š bpDϧgb³Ä$(êi‹úRíƒÒ¶õîÐw-G9MÏ$_·Îk2Ù¨‘ºF=Ô(¶}I»ŒãØÃUp'¤¤\”ѱ9NÀk‘P6tj¤Í<ïü+NuÖQ,Žê³qxõ gËúŸX–3:=¹³Ãñ>f³»8WàźRø¸,óàYUÜñÌ0÷kÑmº¢[à*;¸ùa³( —Ïže¶U¸–g߸°ûððƒÞ?üðèÃßÿèƒ÷¿|ÿƒÀ[écwO€ º'Ï?Ë;«««€Àº³[²aYع…)À€nfI ë>pUÌê‹"ì]Bá†ÁÐÉÁI¬ÝúÆó?ì¬ ~M;üòKl ô1¦´2ÃN놚`œÔD®[²ã¬7ÝàˆHSáL‚ãQ#¦q‚sQ‰ìÁ½ÆM.@ìH"±àZ 4 ¢&qSŠ¥DÏ¥€ÿáСŠÔ„žŽwé,žUl³1{kžgl·|r`%¸­ü­o=úÆÃ/ÆþêáÃÏ?ãò£½À 3Cë?0²Ñ¨¬8J•Ñèá•G°GWÀæÉ\ÊŽ )E¥3%1‹è^?z>\Ï.›¼Òs<Žg;$°IBÚ–9 b -„p€)z¯w° –Îî4¥…Xýºuv²áMS.¡Ì»¹ê\ºdÆç Æ¿gÉ;ÿù?ý¯ÿéåKuŸdUWÑV`¬zê‚ÜIøÊŠY4YãÌz¤:nü¾ìG5Z†EpÿÐIªWf;ë{œ~<Õºóé'Œ³½=Ü«z^–—Ϫâ,„2Ðî½èjÛÀÈsÓ*ÄJÇÀ–* ÏBðñÌ÷чG[ÖÖ‡€À÷ßÿð££?¨ÿª‡þ`Åê–« ‚±ª3öX”4ü ø¬Ó±ßóûŸy풀à _}R¤|)MË` ÷BhB¨MSÁÕöZ0쥺~É6V·q[/T͹ IÅðÑlBÀÀ®' È,Àæ@I­žáUVêFw1–n[‰¥X9:7‚MèdU’€ó B°7t}'`¶$œŽ¤c· [“i3i‚Å&’p î–Š˜' Ž¢îl'Ž';3’|Î㬠B¥Ø—ñú«_ì<ø@5]þüñçï\¾|ùÊÄL’µQ™¦kÃ#ýÁÈ|P Vef8Þ| =Pö[¹Eo£¥ZÂYXÅo3vA¼K笮Ng/îV@,!`©ÝÜ2Òl†áÄ~ zÐä]7pýžs+‰èÆ»_·Î®Lšêm¿” w<:õÈ„V¸=1Bï^ýOæï~ÍÄVo6ã.‹‘cŸ@¢4 ¬Þy¶˜& …™š‚“>ÑüÂU¶žöµÅ9d{¤Âv6à:è”Æw9±fq ´÷¬,3œÒçUqȳ>Í ElÍœZyÖÉpÈ_=ËÒ¯ Èì-çæQqóã®}ô!°ßÑáµCÀàGÆGº”}»ÃnÇ*¿¿:Ç»ºÚí®®Þï® ‡5„ÀËí\Ç!ƒ:Xgèd¹Â#&›Ó H±•øù IDAT%ÁÐd˜šéXü£x²{~>«ªYµ³>×§Q´îNªhIC"|:â·PÄh@Û¸…*Ã~ ð«‡@OhÎtí­Û¶ÏÏ`lL¹±à.,u ô‡m AúsEæ".x"µMp÷OµamÀãX–€/ÏÆ;t+áV£Ì's“ž‡Kå»#1j_yppåÁãÇÞ忾üèÑåËÕþ_pàÄî@}rxŤTŸ33¹òæ÷ÞüÎú@æDE'1Süàçrð a5è1_e{xÔ‚}m)??ßL‡Ç& @¤-eÚiãÑ¥t³zq;«Íl¨_³ÎžAª®aÿò<Ïdî{¾Mé&óQ®Úùíßýö×—Ž[í’§cKqÊ0,ÍTQÔ‚%ÀÔY[:‰UXD_ˆš€OÐA–~<§±°Ü»X–¹w0²LÝÖSéæÓl˜“ËçžWÅAô…{ø#øy?ªq]vÁvè¶~¨9u‡‹ ðcG7›×¯]¿yýȾ´íkGG¶sí¸+ÿ–i@ˆö†ýú,ôž;Ä >wè®®vV»?è‚^±š]ÚæQÕûÉ%GD9n?s‘°Äê£Ó7ÿo+¬Ïw€gÆãu„`¸3Ãù㨚Wëq®Ûõ<2ÌdÇI(™±›$¦ü‰Z È Ôb=.{ºkF]?+êoäó½´(L¯±’<—š ®g8y)¡q$K8D}iYoMr—2#ÕK;Ó)‚j XLª KM5¥év¯Äƒ+o}óÍ'FÃËŸ?úüóËUEGútÂæÝ¶k ûe ýVFVÏßÕ©¼y%±®à 9€Ÿ©sŽóqz¶Íñü—½Å÷fó9«ønÄg˜[oª‚3ì ˜€Žl²‘»Á03ÐyÒÇA$†ºH¢ä­4}j«Ú:{¤¹‰G ØJW±û3gØ®uéxÓ$ÔKœ+¿ûõíßÝAâÃ" c_úC«îc©Ã¯®™Š&ñU9)2pꎥܖ1[ E¥idzim÷W–ežÜ¥+Åݽ{I’ชôÓöÓ²LÌÓz^—½Lx=/»mÊEá¡êí†mþx—éĹ~ãšsýÇ×®ßÿ±u˾yëæÑ-×UMÝ´ 4•[NпowVÀ4ôÀr ‹ÁWY)C`¿!¬·•M0Á±êIYÞ0O!Ðdqx¥p¬vŽåºÞ…½ XP:ߦÓp®Ão† ¤áßú½1»h…;ëQ;Á³(å~ÜU•k|« ÙnL³ª›s¹nj¬ÕM} 9ÄRiG«Xµ>4eMÀõTT¡åØd3Ã~ïr’41bƒ'ÁÅœ,Ù@‚•pãø-6ÆŽ3|2ž+¢=¯JÏŸÉ·F —ßüÛQòp0p_¹ü.D`ˆœói5Fßõæ`Á¡ëÈŸs=ÁCä n{ƒ¡×ÁdšŒó Á†¨\™X”DWœ^€·ñls"î&žœª¥2}äõ61[(ÞÓ*‘Ó„V§Ö¹Bëì™$Ä©ÐÀ~8ûö׿ö†<ðÝ51 Ukà Ç^¡W³¿ øCÜŒùoÇ{Îõ˜b#?”8ï$ºI©´SšH𩆇Êà°C*nÄ&uYæ,–ufüíNÖ])ÊvÞÎsñ›ã²Ì:OëyUnåà a RKÏ û5üZ­³gOE! ™imÝ<ºñ?®_»xóG·nlÝò\W„Ù­o`»Z÷uÛyÝwM·£·WÀk`‹)ß¿S³õ¾Âa¿ãÞ/ÿx/s°C.8=Íb•[Ûà_Øq:Ö{Nàlôˆÿ!ð«t¬ü8Ë+í€,~ˆnz•– ¯÷ö®Raã;ÕœéYýNH«~_dÈ\ØU5‰*5iCÂa;ª ÐLš5•J-ÄüÄ|§š«y'ðû®·Íˆ‘^L5×êÚ LŽWÔÜT1hÌTÓàŠNrú VÌ$šÀW³‰à»ã0G±xKí?ñl‹¸¾}ÓZµ¯¤“oÍéåêmÜ>¹¦öJÖé¹þ °±±”Úþ®ÐRÁ$œê¥ÊT! ¾TBYˆånDWð<–¾ Šê­Í)ŸŸíTízì‚Q(¸3"Ò¦ô¢²ÎzÛ A]c/3éLzl«çÖy¼ŠRX%.öDvÿêéÒ¥ÿò]Ã~ù;9\¶žã9L{ç·÷îý3•õ# ·f£> ©7ŒÁ–Ȭ‹ƒ4ÂÓªåfR³))Š"Åð¸X¬èºú?ïåë ”ø”Ó½G>‚ÃÌ£_Âi4™Lêl˜çUqGúÿ°­#×  mÀ¨>,IAü="‚Ô¶þþðïo±p¹0®ý„Eÿ2]מtÇZj8ŽíùoØ]à­®•šÕñ‡fßÿýÚ ´€ÿï–çà³áäavê|¸ ÿA:@ºŽÎDw”Saà·íÁ¿u>ÍgEí¦÷ØxÝñŒâ¨žÂ 0\B7¹,IŽÐÊõÌh“"ÍM[U8öú O6ß½tÜÑ2m Py ×M‰¡8*¾IeÕi‹‰ÈLÀ­ÈbØÂEs¬ñØ›§à0ù˜ÀT3Í ÈôÄÙêŪý=`@›Ò˘?8Ÿqžv:æ¼pÝ[ã;öP¨¹¿+'8CȰP$ž$1“à]<]h饞,ˆ«8T¨ââ­9£ó®:‰܈NjÂ;“\7£¹oÁH·à®Ðã0=¶ÎYõÔ:{zÖÀá¿R XÓß#>àï¿Xž7t{ ¼ÝKÎ%çžà'l¸Ã‰Õ˜¾@~(íH×$ 7`Õ˜õ´Üƒ˜k€Tp41¶xØÂ™j“=,Ë„¸¿÷ΞîìÌvûοø¿ÿ—àn¶3áߟLªsñóª8ì l…n—k»W^¤>Ó1cm92·~¼õÓ­æ¶ Ÿu¶þm‹°Öòr¤É¹ÁÂñ©V+Jƒd€Ù®(Ãæµ^àÿ©ïcèíÝ »¿ ýÀíkK³Œ:aâñŽ…cNAn×ËÝg@ÜöDuͶû:ÜòóúзïÝã÷þÐù¾¥iuÛd…¨Š’ÐÛ PRDXŠEѶ-·Ë@¼²1Hžë’wÜ0N(óÙ¤ÙîC× l¦±XÎÐQ 0&`§—'&vƒ1 "lY fjx¶J0C>©›ÑjΫ=+ Àao*À-šãtÚ+í=߯š4ˆƒñ_Kóì?ïyÃ.ÎöFiRú÷)H¾$Ó¸J2‰«:Ó&ÃÏÇãx9×y3Ÿýeõ64ÂÑq¥í€½g5™ð.à”Áñ3Pq 󆱾æ»o8K„6²Ú:ƒÒÊõ¼BëL±W,'‰C©°øâVß¿d®¸Û¥‹U‹~qïw¿»WÜ+ŠâžfÛõaîCáN£ ãé°Š#°E¾$-DйJb§¶â>î1ÀÓ–eNÃè.r¶í£ÃÃ#7jEÿðOÿÄÚíHgaëÔ&Dh=×݄خk­–^Ýk$¸W›ÞïAÂç>óVW»kk†1p}×_síÿ  g.Ô9ÏÞ6æ>#’Þ.×s“‰¹+¾_–ŸÖT}O{Ú6™r ä!´FCÐèÌ—ú ÓÅJNifš¥"Õ?’/û£Yæ'h5«ÞÕjtê©D€ÛÕ8>MŽÁëÅ2n0f˜0—ð¦¡QÄ!ªbQÅßÙÙ¥@€»ñ|¾Ís#°ôMÕ žØŽœiß³ÚBø&&>é îô‹ß9«î­$éû÷%tÁd á‰­5£($Ë ³ð*°{ÅÞá{œ¿=Ñ9‰ÉN¹Ðj w]oEïz¨«;@þäê²Ct-l݇JÙû×µU4t¾JDz³X0¡zöPpÝímDà6üÁøŒ ø¬]2ÄÒáÝíãä„?|Õ6y îsÌÎ,„§OµbÉÄÙµŠ«d¸ÀR[ ~§6ÂÚ6NÌ';•–÷‚Ápä$A"%™šé,(mðå2²‘À"T™œá1q®2%ÑòBfL™aÚ½9ElPúÖNl”A®76eX5 ße[+³ëïJì*fB'PwäÙÁšø÷U-W9¬ã¹.âàÞ🕃ˆÕs=‡Ug˜ìoÚºïûÕ4Ž.}lh D°$ ‘çÐsæ6ÎÅa$^÷ÄÉVʪ§ÖÖ_µaø®îê!'\¹ÓÛüE†ShRbpÓ —oã?u² &‰ãb àA‚‡*ëÏGbªÊ¢Äàó61ƒÊr¬`k,ŸhF{„îнhÆÙîc}:¹ó;¿Þ‰ >ý—éIïMüÆÉ“Kþ¤®ŠS-C?ô×ú¦;èw»@?¾—'l9·3ð¼Ä8Úº¶åüôH:ºµ}“ýôÇÒR~´ÑúYdýS›±¶ž$ájÃXHðâ !wƒÌ*VAßÝ÷< ¾ ¸/ ݮ癥W ®úÞðy:–]¦œ¦‰X5ÜJ뽞ÝéÔ¡ ;¼àY»d:ÏÀ½=೶ɋӧééÓ§£¸ÕˆK\…KU˜„Ŷ²ŠÓÀëDåªÐN nûNqŒ@~Û-ÖÌ4ˆyBK¨À31•ƒp‚É€ðŠÇ+L1@¬ ¬˜c @,u5:ø‹«” 3Ð͆¢×½ í&ån—ùö}Æ?b8pNˆUÏëX ååÂõï+wYÁY¸à|¥zÖ GŠ6ŽðDxLÙžxK168S‘ˆ¤“¹vnMsLÉWpˆ4¤bÁñyÔqá²úZèù›nÞhÄZgÀ¢QÅéáÌËÖÒâéV¤Ý†5ðâ›0Ú©ZÑÇrFæœ5p9$¸5$0±MS I«7` ÈÂgtLõÐâE¹ÑŒõv¯×ullÕúK Bã0Ñ)Ø\z.Wú·§“§»0¿ ÒöúÉ“í|âË‹§€5—K?’éH¥û˜3市eº›V膽µm€Ý-ölËÑùÍq¢$ÿͨgv[ÇYñ™iä¶c¸CÛÁö$V´y–ïÙwîxå  @/ Øq†¶]ä¶åÖ.8pR%SÌ`´V4HnÐÆæζ[ç³v{v×ô¼mp#ÏÚ%‹ÕýÃÓô¬{ÏÛ&?kƒ;0©š¨$o²æm†û£¹h˜&“ %ÅQË'ø<sÜ„»â•¹"Àò%Z¦ Xw7p¿§•£@ËHÊÁÝ`{*ÀbGêdïm:Àm Ü9/ß ˆmn]¦€-lŠnê»÷w÷({§Úâ­Jðw¸1ò­À±mpÊYϧLË„Ê8,à[ ­Éœ2ÛN•/UÜ4üb2´ÏôçbÐ1¦‡A·_¢&—Z±©‘忉i–¶ï'Šë—7†‡”DßÑ™&G8¿#ÒÍ6Yl6—–áÃŨÑÀ(™,+œ®Wë`Ö£…FØ a´Jf©‘HXÃU¡‰-R ^?XSFâ‹Ôm4M#Ј;êu\œ X?³°ŠãjªÛÓ§Û0¿Z‰ÏLö^žø’_ú“$Œd3 ?ÊË2˳Ìu¾}ä™mæ`"¨ ªðùq“EË'€'££\£Í PûM˱Ûİá&bB@²í:I§À¤+6‚®ï‚ý}ox7¢½Ô€CkèÕ}@J·n~0ìƒL''Ü`ÍJ¥˜Å)„`ö¶Sç úh€ë¸<¤u»d^eî½§äÏÛ&0çpè¹}¯o;vÞVêzfªâ.‚Ä5\ºCT†G›B:QMªyVZA¿N•ÖÕ@f8„=1…j&!Øb-‘—À•R×@n9ðIÅ"vɘŒÁ€<ÇçÕw¬ÀL>_üÝÝN&íP=÷]“îî1ãó„rí]ºNgYàÁ#*`—#U€ÆmãLÁa×rü£Ž©5Ä™Žð;½‰Ód–6i5Â3K‹­0¤ÿFÕÛ¸¶L¡w‘N z†­Ex¦$ÑXR±EMVŸ¦ã+.æ†rœÈ ËXnJ “Eѱ·UKR–¤†ÂêqÈ1gÑr%¾Àfqø¸Síþþ×Ã;¿¢loF³8Kp'Æïø“–¢˜¦ic:V¡w ×#`~Aèn[¶f™IN1Ún5Y 𠬣âÙ©å“'[cþŠý8T‹˜F“y<Ïâ˜e™¬:Ž3´Ì£¯:EöîØ½5LMv½5'ÏuR:uA·ŸŠfÛÜhLÈ¢†3Ž„œSÞ:`}hA/ —š›ö¦‰ËŸðÏÛ&›£k9kkN§Ì2LÝ8Tp`ƒI’‚§­Øƒ.¸¢°|¢ªØ)Às<×JdÊAª ON£Ð……‰°[ŸsxLs€(#³Ô2x4ŸÏÆ&)ï^}Ïæ`eˆë¥n\ן  ²`æo ¾—¼Ã0±àû^¯‹ã#ìa’¢ ‘™n Â%À9Ð-h~]§K[=œ±Ó`…'1»òÝÎÆuCÍÎO5lÑKáùá6L$“¥–Tg8˼ф_¼i; ŒbЯ‹Q¸¼ÙŠÂcÿ+g-l‚&V”.z%Š?PíüF„£'¶µÂE7²ãL,¬^OÌ›1¬ãÛM sÒq648ä8jªª>B$k`S4¦*|ZĦàúÕÕÝgìï¦ÕfÑbe2éM›’b[Ž¡[÷ß[µqZ¯ïçNÙÄ`<Å~>-öãæÑu÷Ì™¨/"ؾ ü†Ýnp@?‘-ϲ]o{õ)×pë4“—lÎÖ±]2¾ü<çyÛdaY\ÀJ(YžÃ…‡åybŽÉ‘@ªr¢¸<ÒáåÄñZy|*¡‚JxÂAྡQr,∠€°Œ]Š©’áž öŒ&¬Åâ èµI":¡Ü&¡ã=MxÎðtéҦƷýÝ,yK°=Êߦ ȹwÝ`õ‰mšŠÉ Ï›áÉá\oÎÀó$rQ…ÆþýɈ>@:PèUDûSxÀËWÓ -Ø®“ì˜ou"Kuœ…«Ùø¸+Š—ÂE‘ä8J,ŠÃÖéåF‡!Î+V–Â0ZoË·¹D1ç¶ÁÂ(fêÍ×¶Žþþ&–eþ¤ábEqSÒ’º1ßð1„¦Üü8j*ä!vŒÔ@DJQ‘õÀø[vûb*f¢Æ°H"§"- l§PU ú‡p¡‡þÝN<{‡'½À⫨XØÆê[®Ý»Å¶GúÀS¡U‰`›mÚÜþñÖ™£íŸlå:Í©@ì¸nŽYŽÓ“QÛìù‘ÉVæ>Võ–^Kô`„ÜuKÔt®k{v~duoÖô8tÖr5åZfÙ¾µ°Æ$ÉŸ{ltý^½! ¨E2C,Ûœ¦îwžðÓçm“)M¬ájAàj2V޼ׄ¶´³ ·"¨‚\x‚Rú¶ØzíøTB3ˆ$z*§ ]TFÀ7À|¨nP=w•õLÏ´ÜÑi XOðxH›üïæ0HøÂñsòk'à[ÒX] nWÓ=ö6ãs~Q® ëÓnû÷ *œ„¤*nbÔ£·Ày¦ øXQ-:¡{1$ì>Ä®ùù6Æ\ `"aÊv¢†L7ÂÖ¼4"…7£(V[¢ `0.ÕuT‰Ãÿ°Q{,׳pK:Žá¿áRÅ­…FLS²uóÿ¼v sž®ýo1<‹) &2ÈU‰ñ8“ÍÞJ]‚‡a'aŠe¬à07 ~PÊð“m6—¤4qbÞÑ­UËéÙîÝÎWËq±~D¯£°n8æÚÚÀvúpÓUÃ÷n©7 v*t†…‘‚¸šù­­Ÿ2¶%ÝòÜí6"Pƒ×rÿA$Ói´y!ÊM$Û‚¸eùY&S+G IDAT#\‰KØR0Þv=»ßµÝ6 p °Ù‘¦V]>t“454„¥!q™©*•TtÁ`} ç)ûxn†-@ðOǪûé3ò¼mrÒ4 ʉcª$ [:@¸d€›H`Jsê!4ª10üÄîœRQ®â©„?*ò”7.5Ü$Ú68z®¡¶ä𯄂.0‡»¯›¥Îg;³Íu@!ØàIt.Å~äà8÷u~RÜh`3«3›Ç¸¹±6cº7^ÈàÍ•šKx®(ã zŒÿ[ïþÝÈu öïr7  Þ§ªNUªN½P…ƒ ‰•¬5V·{®s—b÷“ê–®?ä&ØŠFŠdÙrÿ6k&¹Î8Ž×º™DV7ðmu“ºãLâñZ^³@$Ev«ý«nlYýˆÀï³w‘­ÈÊ ›ï€ÚçÛßwÎÞßNoŒsÜ“ˆäl¤ñ9ÛáwþDßè­þxÒýÉúúúO¾üã1ŽªqÞã1ˆªd6[ô»ß©Ô’êw¿+ùbDd1k7Lj Jë:F–Š×ÜÅ'ŽÙÓ³›ŠõYsn¢©úý‹Ðë ‚`ňJ€÷WkÀÿff+žp-N’DAö–!ÛÆ&ü—¼Ér/ûŽá/4´;]£B" ƒý>„h†Ñ¼¥ÑÆzbšÚ\ "ñ‡›–—žRØÕ´ªž(ëÔ0TYp•Jøà¡¡ º ]ÒŠ€6­8g ÛOM÷›éi$eoà³ö«ðÒ'fðD„|j›Ì¼8£XméŠûç„!=àïÆÍ¬´{3}Áë‡Vôgþbä¢5܆iAúWËnPÐ0À"äÚ P#$qìXñx.ã! PhF°Z² {^eƒ%vÕuO©»íÊtSïM­Ðw]š×Aƒxîÿá¾q`Þjè…<‡Ç –úÃ Í ûsrYôä]‰M/õww!f†öK‰@Q…Ðåw0z ¦lvÉîÛ»6$#»Ô¶sÞ´ φ›Ž@ç} {÷–ÃEå:® Áiã`Q€|í¸™È”viÚóÆâ×à6Y™¬¬vWÇÏNb`XÊïˆ;@ZÍ$iÕ¿ã¿õúwyž bK;ÐÞ­F ´Úº¦á?|æ»lŸ9YÇ-N1ô²8S#ê+‘ЉK²¡‘Û·AjIDb%Jê T’7×5Ïm2QIŽ&†Å+íÒS‹üÚÏT=.ƒ"fŠiǼ8£¡¸i¨Q$ã0‰„D!ÎÝ™X ¦®Ôl¦‡¢¡«jýHcMÆ™’, ¤«kÀ'®bo9V_ÀLÁ[49EÀæV¦i÷/íÛh—ÌbóÈ¢IÍ?<:j=±MÎq^6`™Ê¼Q<¢ÃxWNc0mŸÖê#‰‘å8 àmO©é¸mbôHq@%= …Іk'ºœëséÔsàÔœ Y«è×ܴ!%¹ë…5£ ØÜ§ñ—:ÒQõã¶#ùGÞËþÞžëî±Ð^2TØ2#ij{pWt\ˆÅþç LÑhE“*(ƃ)1@•¢&ŠEå N1'æù~&‚Þp§Xvâ ½u‹pAF}8]Dw¸ó>'À"ôrˆy!—˜ím–õAÎ2LØ¥éé"\X_íM~„½¶“ÎùÞ…µžtÒ¾)^¨XµÚÜïµ£pß{=y­rôÆÑÚ*DðTNQCßFg#s ;¡ .»tÖn6•‰Y·šŠX–úypY ä‘–:¨ªe uJG½E½t­žCŸV{“êžÝ.Ù>,qû ýÅŠõ6 × ˆœPá›jE%$ªêõj,GžDê*¤-m~‹*¾g‹¦Ù¶iÕÊZ91¶š†Ëg<EâOÆÎ‰¤­§@Kõ@„Œº£~Š€3[iiLÁè÷Ý>:º(fpž#˜ÉÛd/ÇIü2`°Èžä30Óp˜6‰ÀŸˆ$XyaÚŒ 8rý¨–¶eyÂ\ 5„ é–y °$(ŽP•à"IåÛÓEOS¿ÔÏ}ÿ¶û:Hã‚©¸Ÿ @ §ã˜TðJJþÑÚ“Cü¹¯Ž†î^°iÍœ7ZX:ûÈ壀”eJ̺ۃ·ºiJÊ5Á†€ás¸¥¹ƒ-ò8²ž]æ!ÑÛ%-;•%Ûi;¥bÛigЊ€ÇyjB €FÁ¢Fž¹ÛN ˆ¡KÊqvú%×Á”[\„KËPLÕs¦œRƶ3>Ñë[[k“µN÷ü…îd2§!CøìXRò•¹ú›Ãï…£äåaùêG#,žÅ 6`†@ µ £H™7L1ÙÔ%ÂM¹›šö2LÌäìö”$žˆBŽ68±€1ÎNH=!U­Ð˜WUÇwj <ËL}¢…¶gçVî.+^±øTbèO=õ÷3'°º–é—Ÿzjäè¨ .¡EBQUƒD¢î— âDµZ×^`1g3®®IR‹¶ ‘R…}ÆûxÏ+¨¾PÒU¬yÑÄT°–ÿ4·RÉ¥¾»;æ_ÆÀÛ2­ö‚’(Ol“eÐ :êBuk¦šD°Îƒ8Ñ È²ƒU8‡ÀOàÓB${Bü7A=@¬ß¢*AW(TÅ× "ÕÎy‚ Š4âCUÃÑHÀ3‘/`¿‰&¸%ܼ JEQlÞ9|á³7JŒ–:t‚üwAZ¼6dû¯cÿ« ýf -ó–EC/o>âU&!„[Ƚf¢ ’h¤ÐHÕ*òH´;zǹ8¶ؼߟj/ÙKöG¿d»¼ƒi´T´Kð£‘Ë{œä!X5$?›a¥ÅLVÀz!{×ÙuÚ¬ â¢ãO`å{L”œeA%@—¾¶¶2é,ßív{cìjXS‰ YK¥³V’¯ÇGÉþðÏݽ½×†GGöÊI«°ï¿öúÑQtºK­Ô…6Z†e§§…¦ÔlhssIêi$bé….‰’AŒ<\kE5jFKk6Í9ê³›gÏ::n™y€¿Èwë.v{ÉàHK¢ßþSÖ›žŠ”dX´5-Ð|Eƒô,ᣠÆ N (°¼8™Öär]"h ­H:[à(2ïgÜœªëB …M °ŒóÓ ñFM:(]êûþ€i¤†v±Ô“>k›,â™-¥eZŸ3æšu¯ 2$ÔT XO‰UODÁCvIáÑM匷ïÝ–'*(R<ïѽÐ/`!|yXö#×ÍznZ¨(ò@Àá'qpñUx ‡G»ÞkžìùU³ ûíÏÌ'A_XJ©Üvø|üHð€m¦mÃÁУ,Ì0ó-*yX}±&ª—å .Ç4†ö“Õˆ:Ï¡ºXœÞ†µŠ¤‡ÝK7pΕJÈžÚTSMhè`_5ÜÏãæÚ˜s™+ÿ‚t±ZÙV”Ljv†>ÐÓmtâ…ïÑóÀ{|¸„º®O6ÆNço–»ÎJO›|™ÃÉ5ÕIU!N±5Gç#åÁpÿµ~¯üòÁþhxðâ?7§Í„äÑBêë Äq¦¥2ðçì4ÀŒí#˜VR UEVBÐvân¦Ù4æ¶N'7®;D IÍ2)H×>묭ç×=gÕZÖ§¦R¤ŸI Nº‡0@y¬kDÇîÜâ¿¢+¶x«ˆaCIà~Õ%j­{¢‘760Éšq(–ËÀí‰T!ðË:6…rž¸Y°ê3Z͘¥æ Vš›[†×ï;h—œÚ&Ãuò>k› YÊu¹D¯4fæMZǽd,ÜKá0Ñöûd²©()êo´ïç… E[QxQÐI¤„š…‚€{/Rɱ«ØÔHR‚Hšêgû Ç"áÛ«û Ñÿ üé­[€¸Î¥¼±çaYýÐÛaIð8ßx1­Ân…B~îJ%­B€@RVå2üMàHO4%—›ÁZœFe‘cçNmãfó"p!·_,Á›]Ô±(fº|èâH¤”ž$Y®ŠÖJ–æ4–¸s¯XЄè]Q92d:ˆÇ3#Ü©¯áì^ªAèy~hk{€5–Ð'Á•rúÈ@§ ˜ÍÞ#/ÖÇhº=JK•iÒÊg3°&^ÔHÐØýÑžïí9ìª÷ G<ÒŒ¨‘Ÿ•”JEÓIÅTCÀ½gÒëý…ŸÁ٠ȼK÷KØæXÕ.âA<–Š»ðO>Ú8H!ÝU†×øƒOA„ÙS¥RDõõ ºIgCß0¶,4³‡ ˆ„§$¼ )z~ÊêzgµÓýß»Ë4ü= UêÃÃ)^|‰Lµ^‹çƒ7¢²çE/^f}¯xp#ðzçÂu¬Ð|!®™µÖ|ÔtG{ß àRîùK‡‡?l=®Wò~0 ‡Ãò%rYÙÃR™L.‰tMIÛG,ñRW}‹ðC™Ò¨ZkÎÒºY—åœ"ÚW^Tå@Áj•ü¼AÓ/ÆòòfnêÜ'Öʤ–·ÏXM‡2¨Ö1ÖÂÄèPœl†‘¤ÉP)ª?†õèq©o2zZ†çŒëý„i7øUHjèÓZm–Î$åXÃr9FßE%-éÀF2‘ÏŒ‚‘PP¤…<ʼnéó b S=D ŠÍ‘¦žJØEâ~]¤ør™Ä\é’7øC6¼:òÔoh…û,š³H_u5²Ý|þ‘p¹»´tÙ¿ÐZL sÅMÖA„äós{> ct( €œ`߇´šåíLÖÎ9‚Ä–÷@QðŽÍã•ìÅv±½¸¹8e~¶Ý‡H„‡ ŒošeD•®ÁªÞÊ[?5úÕµ ¥½åãeeÒYèÝe}emPC‡«ßÊoýtmm}}mµÛÕ» :–•nœ6¨<®Äxœ—(©ª³õ$þ¨ROÑÑ^|p©ÿ½~ß}½ì׿ƒï—£xðÆí¿ð†£@ºAbßÇCêÆ= )ƒ7Q›É "VüOW]¥@‰Ä²X£ùÀßà|qAÀ†FMEgfËYQ–&»ñOÿ4¯l=5YÕò—ê=U´~Ÿ+ßT*$\Ð'@_ªXIN#Ê ˆc \éô :TŒ%=ÊD¤™¸âD’CœŠ©å¹Ú F]#‚ §Ž2 = þ°Ú@lZ¶3pÐ.ùÄ69ùœm²ç#"yôh"Aú7!Êu¹¬„e™ ?…Dü3A gñTBÓ£€¹ÀGÂHÄR~‚Sºð@NÇÑ+A¨x°¼"/š08ô=4M°aT/èZ›/ ÛÒé6LZ¦%mÀV®R{•[ÑÈ[µ°ÚÈMt3 ù„Ò‰ˆ¢?uoºôsx°+ëäPK䘈Eµ‚€Ç» tqó¸”ÞÎbæÅw‘⺳϶m[Â7ž]_ßüñúÆ:5××AÐj“Õµî^ÕWV7Æ]Òëvî÷: 4ÆËø¿·º²²Ò½+-ß¹»<^Y‰xæä š} g;¼Ï$ ÍÙ´D›#•Y3©¹æÌaP èðµAù( úÁáÐÛÛwYÒ¨ÇÉþ³·ä ØÀ-ã‘Ï ðHr'Ák®fü•V 5ï§í…©VÄ«†—£z ëX›åu¬ep˜Â{þ4 T¦‚#^œ·ÿ¶óÔ?uŸzª7ÅQ4N=,'ž 4CÑ”ç'á¼B_•H»¨4-VÕ8ÙŽÔXOwiàÊR´¸Ñ$i<Ñ´±< ü}Iâ„@P”Ä÷ÉÇžQÔ¶N¦0¤•ùX–ˆ´íbcNÍEÛäøs¶ÉR[¤§Èe—’Zèùå"°iTä8ÖRYзX‡]8gö¼kûѺžfúùÙšŒÝv”pB]+ãöè´2¬&tªBf‰›®‘(k_aƒîÐî»U+hb;‡} Ö“‘Éx§ý9 î±Ë¾˜É‚À».vÖÂ:‡¸›Ëk „÷…Ÿ>[Ê•ŠÓ ¦¶·ùû\ ¢po‡ßÆ“lžMcqJ¿tu/0»E"üýá'J‹íŧG56Wz+«äo:wem®M:ڸ׽ÛS—×V{“4Ôºk“qçBÞ%ò_#Ý“Že±Ù·KH·ý¯%¸¥wá—3Hq÷=IÖ* *%VUMB?y3Økü~˜øk^íJ¿;VGrßœùþL@^v›Aììzû./f³ÇX²Ê ^Z*ƒñ!eD¸ qZÄÍUž‰•8®Íb ]„«+( ˆ$výÏlõ…EìkRwõ2|¶ÃŸšâ„©º¡â(Y=òB7«Pï k)Ö®éúº¿¨¼øXUb5–q{˜du‚—µ¾¤O°‹^֥㱨b©æd¢¥Þ†úŒ·ºãÚ,ô‹Akgl ÔT=e …r% iY(£t ½œBgIpÛÜÞeΨ´{BÍÈ £–#àL§yØ•ª†y³ñ(5ht]@"Q”=ߊwæ§Þù'þxŠÿäîr+ V7tÏÊr¼úpj*ŽÛÐõÉ‹Z¤>NÀSûD›(d©¦‹ûØDýòpÄœ>„Ì’Ãή=ÂÍSœ¡ ⺟á|ɇ¼K›5ç1 #Z[Zûª3t}ˆ·Ô6YþŒm2šºKL„ —¨qȤP BUkT«ÕZ-iÔXE33uZ×÷Ö(~¤¯ã¦p‹d?P}U¹«Ç$V51Tqf+ê#¬”Å” J&ðUB‚sýÛ% ž—ݾ=¬$êHÓq%Š@ÌE墯 ó @Iç-ºÙw¤´Yñ=î¾eļ,šy£É/ù¾“å„û yvïúÜ+aÑ Ð=ÀÀ ˆw‰ýûͯn~©·±e®÷~blüÝúFïbï'_]ùòxLºº»½ñ…î¤Óíïuþ¦Óí^„°ÃxÄâ‚^çBw|¾»|÷Â…•Îz½‹ÝÕ Äßx­Ûé£-£KP¿ÓŠƒÙ`ß{ýpïè裘+oUˆÐ×÷éÚhïÕ²Ûß»íô—ühèGV~¦DÍ%×»m¸auÔÔ´(uéF Bê=Yx’:·éjc¶FkZ"yÓ9U'u5Œ´ZÌ`ÙqÂs"çqÁ»¾ ,x²-ÃC÷ì)ÛvéöŽ—ÿaü?þÇ»ÿ8Îöþøø“•ñ ÎXåx#Ô nm☈Ǒ+H¶ªŠ¼þ 2$Ñ¨æº ¿ÝÌÀ—г¡ß¤>(ïnC8.e‡·´ 5^yÏu¯z,à•xÜœmBŠ4 ÝRcÎqÑ.yÈ^˜¼á`}Ú¿¦M·î½K»ö®ƒ¹â]­Õð>H’ø$Qëm=Ô1 ¤àaðªÔ¬ŸœJ õZˆ¡S¿P IDATWÅ–YôFÓiŒx «€j ­ðø31ö ÓšPrvÛ—wÛKKíþ@^-h‚d‚삜,ª±ñ’iÂç ú£G¸ÏW—c!€‡­ðKC€•GŠs‰$ÈÄ.žçÞ³{ÀÁ·½½¿+a¶Uhåà\–WØç¶$¹w~ܹ1s~¥³BÆhWð%¬Î—.¢’èö:ÏtàŽØ-ƒÚ½ûÎÿv x·s÷î;Âå»wA„œïÃ'îßíõ”Þ2¸ƒ¢Ìs’Œåx80Ñt_¶ò{4Ç1aGrAŸpgÜ-.:™mÇÙæîgîïi\T’i•šæ–¡LÖV&+J¯Ó¹8¹¸ú£ Ò=?~¦£½Ž$Ž­u%ˆ8ˆ®åÎñ;ï\8¾süfÛÎùãgîÞ9ÿÅÎùÎy@À/B*þb7ÞÛá‡Lðêz-”üm†½’’lTÓŠƒï6÷îžT삆–3•¿h!„ÚkkïIˆæq… —5ó5Óú«ä1ÝÐÆ­#~©Hˆ€"GóWÑÂ,/Aø…‰ МµZL0!õÄu¹ïEÑ "0f{¾¸ÀDçyåªx­$%`76ÓýíÿöÉñÛŸ,ÿlúm c~<ßÝ06 Y§fºÚ#jô±¹ á§âØ JBO—h´‹6èõÒÙ{ÃÁmy—J—qú&À–;ŠÚ¶Í]*áåígúýKŸYÓK»¹ôS¼3À ‚»öÒ»Šõ½ÌÁúòËÛðÆ8ƒK¶= špi°ä祻hM¥a£Ü44f$/ô•3ØXî7µ‚…>Ô« ‰@CYÑâ RÛ(Šä bx$‰úþF z7Ã×#–é/‘p’Ú™JX}À·—5½ªÖ)‰%ž¨I+?Ç›ùæ£=FÀ1ïdyˆ8G« oæEiçr dï»E§„/x¼‘¹Gi«u2Tï-µ¹¹µiRбkßU;x;s V/|éBç—@P@Âg€Þ½{ŒÀqø3Àå À »Ë“nš”; @;wÂÐs‘“n&2o >WŽ% -õ™øIÅÁÁpïµÙÃÓŠƒ¼:_€5ùkÝ¢[zè9{\~8 “ƒº¼ƒ)(Ûrc»Yv  pÄúýsýöT¿_šê·Ûg—†¦·mg0Ävtø1ôp…¸ƒWî\ÁKàÄ8î¸Ó¥ÛKödŸõÝ\ÎcnhaDI£©†ÏŸqÜK#©^/˜j¶´Ô”-”<ÙKB%" -Ò” äqxGB¿ŽD É:0Í}°‘`y<ïg9-1ÈûZÇHjóÛycO¹ õ‚fÀñRIšV5ê4ÿè@(åÇc8Ò¾W\|·øîÓ‹pç‹ï*Fº±ÝjµÀèƒdCé’HZøaåbïé`^¸yHÞ]Œ@8ÌÆç±”T$àå¿Y¾srí;wß9þü;ã»AfX'ê¤uѼS\A"¢¤&ÔÐ?­8^Œ¼Ê¡ŸV´Ôùjád[B·ò›Íz¯U›Û ?¬G—<Ï èüƒf³y¿.( ã:Ί°`åPxO¶€5l^ œhèu\o&èlÃß EvóÆàÚuÛɲÏ] ”›Ä%<êde½¾iI[éüã1Ÿ[îÞÿìxÌǽÎJg²…§khë¯ÝļI­]¬—ÑÇšŽ#d:'c¢žšüYè˜`š".¦®;=í8SOÏ)ž[:Û/µáÝsçìïŸ,CšWþNøòÑsoFQå£çÂðZôÜAà ä.ÝvöàÒ.°È24ðoúѾdï— qÜÖˆ(AXÑfŒf³ªü™¥ÑȾ–ÌМ^*ƒðOUŠp“SS\7¥k pؤ~Eæ=Y‹Aªð®*«œ¼‡ÛèaÓ_quŲŽ;Ku]“c–¥–·¼GФÀ“ \•yÌá=´.Á/ˆá®Sâsð>„6Ìøa±ˆeyéAT¡Ú²’,ñÜ¡QmJv©œ?8æ`½†X‚Ž ²°³Š9Ÿ÷eËe}âÆšW#]u9Zì/,ÈlA*‹‘¼ ”Jria¡„oì’6Ú˜il®¯‘^G[9¾{§{÷“n°À|<îë”<§(/è=‚Ҹ鷋Ó"àÊMJ`P?5ù;Bú•Â¥"<þ60µÏ¹ì #*î¾ß>ç?Hw!\OnðÖ˜›ŸŸ¿5?W£?¤ l}ñýÁÒðÏåÀ·d/A :·xÃ8ìB(:—¥¥K»h Ê8¦—uÜs¬ýÌÒïJ™þebƒ†ž„B¤iå=B…ÒD ø«´XM=H”²*xH¬±SŒ“!¥x\7»Åd_†LZ•<®×RP¤8!óyXjyëÑ­ª$Á±^ Û8LD³iX¡?8·¸¸Èqâýþ½¬Møw äfËÄÔ;W/´êV+±€•µ*Qg¥»"Cþ]Y]×W»x¬Ñí-w/,/÷.¨?ZU;«Iôß1 •È•n÷Kˈ0öº? õu)ë ±Þ´SÊ@ü ZP›˜yõIÅÁaxø—Û®{8z9­8˜7 Ö&ð)X÷\…Öa-©È<û¬oÖ LŸ;ü੺S¥ ud#Óq›¢€gz.Ïû"ÚìH‚Ÿcs•Z%‰µ˜SH‹¥ß-À톿pc!¾É®.ð%Æþ ™æs0/áÙ<(À¾Ûø¥%FÌ4Kð@(*7› †ëõ3, $uR˜Ë[y:k(¡¢IU%‘ ’GÕq@ä ¢«O£b@E­`u²6|ú,fQ},:DUrYp§íl&ËãD9UÉV5Ÿßó”$x©bò`OKL•ÖÜTî\»¸ÈæZË:9~ÿîA!o´*­¹¸ÐªnE&dá‚õ‘dùâÅîsñ¸7yfù<\ŠåÞÝÉòä/'ËÞdm­«#ö:½qO °lb./»ÿÔÂV€ œ.¦Õ¨™R&Sâ}ɯâxN}vî3ûÆûF4Œ¿ÃØ+€Â7xã­Â¡ <(Þ—[|XUYÊ¡ÆC…ÌUÿõ(›ã"óHÞã…U®ò;2ö֡ј¤ÈãsèÒMHƒD’R¯24v\#tSy^(ÙׯÁµvù ÊÕ{l85Æd‚ú}ùîÒ9¶‹;»8Ÿkƒ=‚­v šLƒäÕ¿µë¥gz:ºNUþ‰B€ZæZVœá×]ʼWÕÊLËÈ÷n²Y©ónÛ%JúNRàÁéXÕ*V¥aÔt¸P§¶Ñù–arY*---í‚^@0:)úõ‡˜ŒÀ¥)à’öÔ.føËÎ%ÈÜ»ªªñ=wh5`€sf â+ #ò‚À߃´«ÄºªR˜¢Õ´DCÇ\)RÃFu@=^­.“@†„ À&x¾—“E>=íå%Ì Ž(¢¿C¾=ŠàWÆŠšÔ-©Š>Câ2¹ídÏ•îÒmÒúo¬b° •@àÃBá¡i=,´´ÌÈxO.h0@6 z+|;X¾@¸Ò»<¨àX°8unÇqEßá},²ü2  ‚0p±¤Ô/-fÜŒ#°¬“ s¾^ÕÔIü¹Šƒ½ƒ—ËGÍ ~Rq 3äÚ#Á‡Ãsaœ¡â\Ä ~7E_ŒE¼TŽ…fhÞ|ôˆ€¼QÕxB”Xæ%?â<)è/þ¼¸x¶„8ú=_?¡|y«u  ?„´[hÕ,+.˜ƒzÁ*‡ ‚{½Iouµs|Tí…q÷üøí Ëãåó½cØx”ã²¶“Ë0ÞÞæË xæØ÷V´:hVÀÚ‹Å{XUxÚâ»TKH¬®â@;_>ˆkWÂáIÅBë"äÚLý Pxå47+à‹ Ý«(ÍÈ(GnY­ RÆ6Âm3n•›'x.àmÞÇf;t뤜TÚòHÃ.’ :%ò¢knÉ ñêMIJŠ*é*Ä‹¡©«k'Á¶<ñØ/ð‰ñÐatM—è'4˜‚5s )œ Ô”‰2FcëIê9iš…­­´\Ó²°ÆÅp=OkXZý¤É íØÔ—Jß@¬¸B&úÇÆ·¨! ‹jc•ߎº†¶ò§©Ü0hM) NiÚ¹ô$ä@>ÿû 7oúÀ)0ÃûA¬7ý3ب­aIþ-Ó2k$Cèqà‡¡a§*Hab¤³Úe²UB•Ütn›Ÿ¾ç¹%û—Ë x6ã¤yàDYÊäXÍ¡*‰‡Go”æiMP¡,EÓÇ!?Nª•PšÚu¬4ø`Iþ;åƒâ*º¼Õ ÖƒV¡b ¿‡‡ñšf¬ª+'«kk{¡‡§¹çAóÞyæø¯%ÑdÙ¥q²…)Ö.ÓÚåöeâû!Äc2°Í³œgÓ\ ‹Nÿ âÀ’•Ûlÿ ¬8¤Šñž‡‘"¼xxt½uèeÝŠà€ –›ZN¢ï¿xt$©uÑ>wvjŠ9.ó}[ AöbÅ,Ç|œr#8B6IÔ$¡Ò zÉrîŠ/^•‹Wäk WYIŽé†v}m² q‡‘—¢^:’ñqGÓu8]S1OAúÕÓ™±ß¶á#}’J`@?¬‚šÀ{t5ŒÀ´¼ ¶ZL×»¢6S7ËP[Õ>¶w´½þîÒÀõüJ­×N œnát—B¡öxsÖ˜Û,À¯0@¿ž¤ò|kv¶`ÜJäsŽör¯8WÎ¥ÆE©šéÇ)§ôkY TªäÌÀöù¸a SÕ¼eÐ2\ƒˆ”kÑoÔZµA*„÷(àd €î!²:ͦíé)ŽçÏ9Ù¬ É‚—œ[b ø¡8À ­ÌUãJûxw<¢å›š¯”Ü{@ý™PFf–qƒñùƒTˆ­Ö‰Ú°*-ãSÊW€¼{0—ÏÃJ«[$<ø¾·0q–Ï£ Yž\ìþDïñùîžyûÎÝwîÈ ƒáìdЂ¨XÄŠ܊ʾ’á˜3s@édJY,œvœElã´Ó-ÀœË¶!2B½‰Fû\ÅÁȱxü{ÅY§xrËãëzœä€Ìz ªà*Q) Vj¡dÏ9Ó%û+:èxâtÌ<ˆt¾äºî#µZ\¥bÄlÑ_0*®|“»f§©¼¹ehD’ÔNzÀ ¯zcÜVß]¢!Cv;òÿž¦âA›Šx2©XÿÖ ÍÄX*#OTe<&„DC4-4Mjnm¡ß𑾯öŽÔq—¦…WæáÒÉhïþÒ.ú`‘ïǵÊ´;ÆÚ¼ÑÜœ‡þwJ™§OÔµ©W÷rßóýp¸‘÷þûf#O"iš¿*0HØØW>#R Å›8Â.ßÒÕR²65%Èq9QPHh`ð?f@úƒ¨ÅÌ:\N¸îÝû|ÎósçÈ2Ï󘥕ë͈¬$j„ È—¶]Á•¼®¡ÃB­[ ç2Jå°,ËJõÑ#]OÁoÃì¡e|Jù°H±Y ÈÍ‚` ZÑ𣕂üíaÕDoÉ>—õs;׮ݸ‘=¬!ÔDô׸¦œN¡ÆÔÛ[éNV&ˆ„Ç€rà@Ä­rS}^Soè†~rÓˆ®›9_¨éèkIc²Š'%8 .e/f£Æ÷ÎÁötÜ…4ÐëýA:Ú»a„…~€ZGkÕ4£çMÈÁÈ· kë4££D4SUS°ŒQ¤bä½_;™i£‚ra·£(*§3ëP±²W ¥Ú™¯Üºúo×$tÃI`/I|Öã9– rŽwPG;9#険¹‚|š&Aq>+äüt(6ú’Ê>Ïqhà#‚щ^…GÙ>¯és6ÚVÁÿ§&œv[&]‡•ãjõû¸xjµï# ÖÙO)¦Û–UŒFÚGϤe}áÇ®éÝ ãå/þ]1¬!ËJ¥ûÓÄ`гØon·Ï¶~ý«ôöËáÞáá+{{«=î¹²´Îá@™‚wygaVµäsžV,D–‰ÑÈ0ó†**RönßöZG)T ´Ó™òdTù /z|Ñ̈·}XhðT ËDŸ—-‹ EuÑ×Åc¨Ï¹í+9þÜÂõìÿyÝ)g¯l~€JÓô@á¯.§€|+ŒGXqQ×d¬BEw7H­$‹89‰As7•¾  å1|ƒª¯SýÒ‹Âeœ=í5o¤GÖ¶wø^d¾_5š33³¦ÇÒÑÞ‹£%o$ø/ ´ÄîlÝ´j'³_¿¯fââ4£§ƒ¶ ›ð0±ŸT0ò’µD»vxµ8òo³Ý’ÝNgÖk˜6T¿g>üý­Ë·nÝú-xœfP Ù,ïH—q4Ú@þeQšúlè8.Çš¦Š%– )¢tŠCƒís¾Ïá¨òàñ0>æBÒ±b ã¯ýóö"*§´ØF:@XŽ4àè¥U¯ µrJùNÓm¡vd˜F½ !µ–µâP“$9ètåÎr÷üùåÎ… r÷‚‹§Ø·øï·â¯ñ/¿úÕ¿¼÷‹áÞƒZÃá+ÛüYPïÞ+Û9¾$:>Ïp,0$›ÿŸŠíº·e`}ˆËÈ ðºõÒ¿U^øÚ‡~¸°ãÄmÚ0t„ÕŒ´TÍ?!˜'}Ft·/ µÎx5 )/’ÿ‰÷p+Ãñ¢KÀƼ´[ Ï:0ÓÝÛqv]§ß‡$ùnûiì`ºøôÓOS4H"ÕȧÇnV«^Ã-¡Ï¦ÛðÀIJzëd«¦6kÁ‡ù£ƒòÉ…ã;äŸEŠâARŬۆWç°V¿],Maç\˱­Œµs¿tïþýÝÖî/i·€\ß³ï÷ýËáþю˳@ô™øJÎ c´b ÿ¡â Ü3u5†…ÁZG¶½ $ Dá’ñ!sã1=÷ô4Ä–“=æ§žzÊNMµÑ[]‡E¸¢ï©üˆÝfC®ë Ä0cüy×EáìëŒËè’¬ÿëBžÞ·:¯.¯tƽñxy²Ú½Û™t$žŒ(„Á®ºÀ "!žxÀ>” Uk::œäÇ IDAT‚ýœjWßÀÞJOÞÔ”öaÑ•ªŒ,:P FÆ ÿ""ŸA×uã$S09EÀ¦‰Ce SÇöw$™Iã€ïØÞÑrFµ¨V‹o³¹'¨Æº9Œr«°•?ýu'x < X2öÜú¾?½þÀ;í99Á4°‡!0"dÕμôÒK¿ƒ—_ú: –ýl%…%®*8-Ýq`an©èb™î˜€Ñ é–9êâ“–)‘¼îà~¯ë”pdXé^ñç?/¾ûóRÑ)– â” ™Ñ)¦2"R’í…r\3±"¿^Èß² ߯ÕZ8¿ç$ݬ˜´®·Œ–Y˜mÐÚ[õ¨üZ+šWîòb,è.ÎÒ],a_&–Oï‘[lû¢(·8fI–Ãmoo·Üþ×ÓU¸»;½qô¾ÏÆA :|B¢‰ ø*†’¸Ñb…ƒAIÂzðŠ& Ñc…¹ÓÎJ¹0àY.nÔ!¯z6ÄYé©âÙâ9 !<Ÿ %+çGY—“ÂwÅq"2–ñ>y?¼.)ªm_~I©²>Y»“ª•Õ1Æ]Š€½qWíê›* [ºÑX&]¢“çq¼fÚ›™Þ°AÓ°J• Çx {I×tãEúØÂ7ÝH·íNТ-kÐj‹b{Û Í÷“™z½Ñ4}!íT¾u0+ä­2£Ym~þtªk¥Q™Ã郧€zЧxÆ—7) A@/°{=À ”Â`ØW°FÈwáÙ›9óÒï~G!ãÍ—>þ:’Y¼›è¼m˜rW7ó wq^ŽÕ…¼›7Í4W¦„éŠð“-BQ)žÊ£¼(þnñ]H{Š Uî¥m¶XPtýÔÒ*½Á܃ämÍåáÉXëæOŽDj-Hsiºd4’ nkfÙ:lUŽºùòáæAU©x¾zv‹«Š_mfç¦Û¼¯T2¡Ü’K´Jm¨­ø¿ÿßÿò/¿üg ¾_ÿúÿe-öG»£`ïÁÑû£‘wtµ–JÿCÅ{ßÔrò`­¼SN°á0 ã°\.ƒè-»„aB\!RLpœÝÒY§ÈÇÅÙ’ïç“Ú&Q©IµHÒÎe—¹+ÞUþºt­Œ[«k›+“µ †ÛdeoB‘¯Óëâ'‰Æâ Ä6º‘4:ÁA*žƒLô “ :O£ ùÖ.GRXÄÓáõÇ÷M­ÖÌÇVš3gNU0D#* :d¯yΘ~u¦^Móð`oè¹}×»bšG#?©Õ¢ ê,,ÍúIö¶ê*öùâ@ÃOðO±Î´nCêxyÀó°ƒØsÚ¥]dž|2³>ßqÝœ§Ÿ¹Q¦ˆÏô-óCú¸¬›ÀNœXÑ5"¢yÝÀ6g Œ(O @=1RMÒBkßò†ûÔð&…ä94*&}75>sú̵ï¹Xýé§gð¥°.s±“öòÚ,,'p¿7¼öì³ëk½àl Ù îY=l¡ò°ªæ!W6fgLýpfŽT÷“Ãü¢5t¯â:,“I7þ‹È Ê›„Iœ*ÆÂ=ÿöºÓrZ|®uߺ׶½]H­û\k¸;ö_Bt¹ÓýA+Bæú\ÅqØüa#ïµJxЇþ !©Ö€ÕIRÜ@$§Øf¨}y>ÀÚv×Å~æ¬Í84GÆ-;ç‹õp¦V&bÕCûr–¹ 2wE¸.IW¯3Í…µµÉÆ€àoþÿ×ÈÆ+XÛU(:¾"KÏ£ò}þk:dVPQUôœVOÒ°®«ubÚ#ê߯‹hȵt´·w›A¼8Fë,Ÿ>š›ÕSlPaÂz¨'xjádˤ©qÑkî`i´wû¶<Ç F”nßtPYϱøÌÿøÿöáK˜‡?úÆ·oµôÙVJÿp7i²-,ðJŸÚOe"°¡‡%ƒÛÑNC‚w€"-€8Å©žš²yõiP{ß-½[*wïOã¹*T«¨8 -âHÀÜ)-¿…`mkþ§k:]›Ð?ýÊúÊêÚŸ¬ ó+ ÄŒñðV T 妆VÎGñœÿVrt°÷ nQóP'¾ïdeÛÀÛ€¼}ŸWMEI¬JkáÅŒoüöÃ[¥c­Òcælßßfl§å±–CwáÖ:-X­’›¨Šn!Í¢•?¨80ÂJÜ(ù£Ý 8û4zœF~†yYV.+‰S\| Øn–q8VÀƒ0Ín3¬9ÀŒÀ<ÇKšú1‰³Ï…2àâϽfso_wùçTºE)ÂÜÊd%E¾•UAˆ>ø 76Gq·7_z loÂ{é† =ɾ(=(Åc8bñVndîj*¡Ôð¯úx¼f|ã'Yø~¹Â“m˜×]¸žíýD38òß?8uÜÝÅÑÞì0„uÔµßW«-mN¥5 @ˆÊ$`c–?ÔO·Pñ@HOzNØÀ ¼Ý2ŒãÞvtf}ˆÝú.Ÿãjg~{ëÃûí‡7žÿÝ×é·Œç?ƇA-|LS–áqc­§›tb š7·p#æ_«…þ…´pw•òªÌçᙦ!0õ»g UÍç£ O‘ª¬ O[}¦©74µºfl<Ͳ±ñ§­¯|õO¿ú•g¿ò§«2éफþ—µ”j¶@åýÍB¡,7f’z¥öªµ_)öÄ–y8£ãlÙ(pp/pçÃw:òßzñ.~ãþ^ÿmëiU¯‘ãÐÁ-[ßrE‡Ñ!&Ž€pY²¢Y&`‰ñð*€%3+Dý¾Ns‹OŸ-…Ó! 5žXI)“ê"üå/œcH6Ùå·ya{ûùúäð¡Ül&•ø÷•œç.¤öR×Îµí²«~Û‚êaIÙ8M½½UÄÁUFÀ½ÞÅ¢z,øC’@$Ÿ,㸫'Ê Úm?囿wÃèèËñÃï†o–1[uk®‰ÑüPSî Ëðq¯›ºÙ/c!j¨ \ðG-T=—SG­µÔ~b2­ê©=¤¤FYX«D¨àQEþAõd¯ò©5¨ËѬµ'ÿ)ãàáÌÖÛ0{Z¹çóâX)Bh¼/œ1x¾§Õ‡ëÍOø¿ãû”(ÿ [¡G~”u‹,MZDq"]6d% ƒ4ê—°½}çÎÉ{§ì÷ ø RðEøÅ#ª«Ë" WUõŠNVWÕæ´H¦XSçµÛ«c4Ö×.ŒëЏæÅëo]°(I¸¿]Ϩ߭Ghú`®]<ÃÖ4àí›!ÐQöNeüÃ+ºG4.Jµß=ÛªÊj<`Uû”ÁLøH)ËæÓ{ Ñ{–­Õ‹¨˜Ð‹¿GM<¢º‰»MÓEžRíÌÚÚkׯÿžªæÕo¬Õ³{ðj8ˆ©xØ¬×Ø.¾WOht3VŒtB;GÖ³.l–©µM:]¤QK´IMéaÚ³zÖ]•šÄí¼øõ'Ø|qs~{ãä/Ý>¹õåÛ·oþ½ÇŸ¼÷Þ{'·nïlîìl½|g«_`=\>Nákïû¾gfUÚ·™ÛM-»ø‰ý¿”±O6µ~ÂôôñOXžæš1Z®“ïhˆ€ÈÍå†ZeT]%—{ÖJQõºêO+oÝãkõK_º\eBõà—¯ÿÛ¯«`‰y¸ļo_ìý§Œƒ8éËí°=S•ý/|!Lò0wCÏt–†vŸÍ•áJâ×y0H­ÑTö!Dµ9K¤¸Šá´ŒA³@ý\¸¤ªz¤+âkШ¬¸ƒà»EñÂo¾IR:Ìç›'[šYÛ\ƪªœPµ6hRΟ:¯‹ŽðÍÜP¨î ¨jæ®YMË0õK7nÄf¹S·=e¦¥S:´}šZ2 NgP[Z'7=hàÚ«7…—”›7_íª¢ ‡mvGeŽ÷ñx¥_YF½"è1kå^ÛÜ¥\=ÜÓ÷HpÆo±!ÕÔè”óǺ7 £Gqì—† Øm^£ Ÿ–g>~cíÒ§]zå§Ÿ`É0ÊeTº¶TWˆ%Y9=^Ù%à_s㮤SOWpb̓8Ã!Yˆu¿Ör|Q;¶Ø²Šùßo|eccþÂæ­Ó®-øûù{€àÆÆ­“÷ðÍ{Ô¦jç½Ï·ïe¯—„~ga½~ŽNÓ:“IÇ[É%£ÝÅ«6cÕ«™™ÅÚÊhÚO¿WuGzö8wÊ0RÕŸYfBmTƒD ¹ Ñq®[©¶®&z¡8Z­ï)Â뫯ÿõå/UŠ÷ÿJÒ¿ÿößTü ‚šD”—§Ü«ìï9Î8È¡—M«âR÷œç'\šÇa Ÿ¸ ®ÃΆRÇþaˆ—•sé äâ„–'Q¬PUî•Å$ŒBIQAËcàUѲw“90ßQc¸1߯û\Ói›¥Nª—IÿiŠrEA<¡Ýh¢>ŠYsÚ†ÑNTj÷W—2ª ŽOÏŸ_}íif]gÆU-5Ìy…÷N;]Ѽӳ j÷¢Õ í»xß™ì7/?ÜÔÝ#„à٣ü›—ÚÈ\ÑÆ£²> aï°r³ÑÞ=ÍŸ¶ÿ ç:ÛÆÖã?rÞáÁå<ö¹á+ûßÂØëÔ¸Z ý$éŸùÆÇkŸ|òÙ§Ÿ~úÉÓo¬­)ð¸¶J ó©Í zšF> l8ÿ\ì]h;I4fÈ¢.kõNRE§‡Ä•eW¢Øàí¯rœa‹’hv_T6nÝÙÜ “ô¯¨_Ù¼}[<¹õ¥[·¿|û+·o‚_záKŸ,åA/ŽéÄ”M5¡m=Ja°VåÙØ²M#uFÝQ6ëîZ£CÃ…Æñа§½j:(#JÈ(Là|\s¾ñ~¬F+÷F#kE¯ºzæ¢_ò¥ÿI©V«Z:øÛê·¿ýUùmÁ¿ÿ /zðí(*T«2†Ý?g³²Ô‹HÐ:ÈB0ô8¤ʼnïŸuG#}0”†7\ß‹"߇q#jKÑ:ˆ“Æ’i&yyìØ¨'^Õg«æj«6›ßÙÙ æ#Ñ7ú`; 776!bÞÀ x©I¢°¾ÙU ¨m(`E•r~uS¯µ‘ pH¬p¢)æ ±ôrpþüÕ·Þ0/ºzI¸d@›±² tìZõGÚ@‚ðY¿ÅŽ<ª¦ß9«éþ¾Dªâ'PmG‡e™¿¯Ffß\9[ÃŽÌÒ²ÆtLø#$8×FÀ†«dFݸèàà[Q¸÷Åɤ èAŒ|+|\{¢ÉŠ.'~˜YàÓË^ühmíkíMÍ!¤¼ìº‘ˆ¨Ú–)ÛªÈTüϲ,ˆ¦Âá DZ â4”œ¤È´QÂ*ò$ŒRÂÚ&+Å,`Z«¥Ê-·¦hë›/ª/¾8ßxqcã+ ?xûüäóÏo‰·n¿wëöÆç·ß”^ñ«Ø ý¥%Ìx½…%ŸÖm;'…ù#+ƒêt~lÿ81íØ™>nì)Kì£\g³ “K anG[ä­ ¡+r6„.IpãŸ(Éj­ªŒ³P”®ÚÓi­Pþ¹]Uû{ëqû‚ð@+ê<¢T^Š"zª¨épˆj¡&yžÃwä]pÑs”lAÇÝ­/¸F# ¹ŽÎ‡‹¼KÝÁî#¬.z-ŸÆy¥Š\B®i`È…Ft1ÉéµìµWx´öímÝùÉÓwøŽM¨ÁÍ ukCe¦|IKV/%ªü/¬RQÑØU tìKÒO7”š+ñز¿ˆ4Ô§fÿíágWWùüÅK;u³¼ÓFT B T‹Á0º±ã Ø1V  ¬>’÷ጃÇmòn™kkæH›z-÷ØÌЭ‘iŒ ~LØ¥Î)V5µ¯øß à qxóQ$?Œü½›¡ÿèñÃØûr"Æ‚Çljy棵+ߺrùÃ?|úá7Þ¼r\'ýÇhX1P‡k§ª NQåEÛi ª rŽ!×ÓJÛÔšA+”j9hÓøU³²i§\×Áy¥ž{ÈÐÃÒnŸl|åÖüö&TàÉ%÷¾xû…ÛÔ¦å¯67¿òÂæ–œwSч²_‡ &Ðõ$:³ÛS³–•í™Ýe3{4s²C«l·#¦™#6Ë­èeš”Šª©Ð÷aä%T¹LÝù cnäи•5v ×{zº\éø¨–}»úöþº¨Tûf¼ìßþíƒç>øà—0JB"rÎû>a£uCJü 4åç~±¿WÏ…Pžl»PŠøÝ2 ‹Kˆ¯ð M—SÄ É ˆS³Û-ä®YMèÓeˆÆ¢( ¯]|•fîì€îhÛeë ‚xWéW¹¬È«ò³&[W u uC5ë\?ÄG5—u>eŠŠ\;É‹V[ïúÓ§—’4¹xñ¼G Y¥Zèãºé3‘×é@¤þ­)›YS€Mm¯…«¹¯ìûá#ÿ»`ÀøûpyÙßG¬Y8`üô)îÖéX€W8§pfôìØFPÆy0¡ëÅõˆ¼t웵yR¢˜g`‚×Ö>üðë}üégW¯\ìL]ïQŠæXšöã$W•ÈÑhh8Ú 7^ð"[³H®Óñs½%HM¡MÃîçL6ØÅ]y±mË ¿Ô y«PoS Û›2ÕvÝ‚þòí/ßú\Hñž"æä;¥NÈ|ÈþF<,£»–š Ëþ‚“¶Ív:ÖÎã¼LÙ¡Ùflšçq…ÑKe&+T‚žòI2 I y–5ÔT$½+¥j¦Vª\J=iY—*/ƒó‡³ãÇÙ¿}ðöÜ¿ýë{îY¡Ó9¾ß™¼ïù­ Ïò\¦> ñ9w²»ÝäÝ!ßtƒ–2XŽK gyŸfà,R‡AŸrÒ¢ -{EWU-‹—Ã`$ÈW’ðµ‹ÂÞ^÷’éX;w¶á4 „à;sÚ|Þ¤6Âwî̱ð/+U ËÔ™PQ.ŸnAS ÆQVÕÚœÖëó`hB˜‰2Ÿ v5­â[¶õôÓìâê…‹G“K;ýºf¸¸«Wu§ƒ+³î~ªTìøØÆ‡ÙÍÄf3­šÂ½M÷üGA›¥_þ°«è#sÜû§<îCóYiáŽH†¶A~V”ø›“à¼oß £C/<ønP{ŸÂ‹9öÁ€kì“+kôöé'kkoSÏM*ÁwÈÎ8˜¡ˆ-žSŒ²éh’H}îÚÀü†eÐ6l¼¸†Þ¦4¶]­Ñ¼¡µa1Ïy \ÔP*=püp¹!ƒú6nÝþ’F ‚n¿·A©¾·Õ¢HZ/,¸ÉúÒº/…™’*BäÓPË÷ív5c¬ÊÙ÷+–Wí©=3ØK'yœ›‡¬´«ƒ!‹ÜNÜ‚°øC™ÆÂÎÐÂ:"^NTC xIW[üg*PK¶cªr¡¤]»L{Y/„û•%y7f³Ùå)hÂÙ~ ÇÑð& ^ÃÛ£Ò&:Íp)ç–R;i ÏûGišv.‡Ë‰{¶ãò\,ùÍ`Ћc/ãþÑÈïã¸6/&2Í1n½òÚ£½H×MšFgllÛÀÞÿAÑ—è&xóή)kÊÅK`>Y¢¸zR É¿úìMÕæôLæ4ʇ²°t#½ÁÏ µ†B\]Þ1«ëoÒôò¯¨¯®žçÓb^—‰ ®1‡ÎàvOË2•ƒ€±è¸M2)lꬳã=š„h=¦t¬ÒViÒL=C 8ìÞ³1°FÉPu*a±ãp ŒâSÎó‚}ßu~Ó?ðh°­}ó•=ÿ¦Ð_ñŠžvæC ¸—”µ±õÑõë­^1l›tÚŽ¡| M¶dS£‰ê ;ËÉÖåŒlC‘tSmE°~AùTO?t„– ‚ÔòÆ:X Æ™J i:5ƒú_ ¢VðÖæíaŒoÁç4Ì.¼‰·´à®/¹¢Š:¡ÊQqn»r¦uNÓ²cfϬĜRÝ**û€•æ¿F¿c³Îû/Ã&qÞ72‰Faj¦¨ýÜ0þ~È….ÅT OÃ(¥"é)¶F ¨è¡WíÏŽ¾ýKJ”ù7õy¿9©<*X]/×½Ž˜RrŸ×¤l3ßÕ¸çD~£µ¬‹Ïó¦&üK 6)Ψõ§„9ñqoXôjYð‹Â1ý"î’SõeK¿¢ëÿÈ4Z¬ó¼çº“†¿:¦ ‚DI‘n+Ôí¾®·„äSôz’˜Vc 8$ìÑ }B•ðÃu'£çåëo_ûìrv¥ÿwû¯^ˆBøF­ØV˹föåmµrê${·­!{‡rKŒÍn2"Ã㯚Æm†'ÔÕ¯ýGe=„YzÒîe×à»PÒÓ1ócª§;›øÇ5‰Úç=ü¦ç>:¨7Ûë“ý=ßS5Yö3.×ô3oHW?dŸ©úÉëŸ\¿þßWUæÉyŽñ¬§5‘®»C ‘8°M]’d­å3+Ve1¨iË2¥ ²1qqÝÍêÅV©K´f:¦¢4cAh5Ø*ˆSðÒnRS|8ÁûWŠ,N“0|à­Có­w|Ñ ~…8*e©ªàs&ÿÒiWÔƒÚïÙ?`íöSM‡cèŽQuÈÌ8²r{Öpë^æa^„A¯,3y õT97˜U~*ù¾Ê-6Ü_Ü…:× ÊÔªÈôTO~îU Z¿Âûþ£@Ԅ燊pTMÐÙk,¹~(PšãõY¼œöÜÙªþÍêþ:Åê*bVÆq’H^d©Ì ±f-›ºf¦EºøjÓ½f\jcZL¢Î4îâdýì’æs‹tN¼°è-.Q#>áîæÿ‰—^EÚ,C —u½%%Ê_*ÐB ÍERÌ9U»©  Iýtep—ªÜFÔ¾ ríÚÇiöÙgG{ûß;ÿŠIJõüNÝ+Æ¡—èÄn«¦ì¨=­Ø;‘FçlÇñ‘!Äø/, ó/NâJ(ï¼È-b?vL4u<²ÌÁôøx¿s4‹q«KÚÙü½SõWoÊ[¯<ôöĘç ‘ŸQ´Ïô?¶Ÿ~ýê‡^¿týúuCv4q¤§×LhH g1•F‹MÁ1DE€¶ ¶©ŠœÇIøO³6ã°?:¤­Õ– …‹9Oµ%¬ØV Ô§H²/‡ŠbY>µTC•(ßw‚qý´OYÂЃC,Emr _p’/¥wÁëXeŽ­+eiôŸ†iEY:VT Þ/|M<[AôV”ÉíïM&=÷~““…„÷Ϲ‹ï 4×ÕúÂs‚Ë å•Bíjæ²nYj,ca§™˜ç"lvišý *ÒÔ ^ Œ§dqg·aT–ÏÙ|Ä4Ë=ø¥s낯÷—8„ߎC%Í'«›z]k¬Ô…•ô%(Qãñ:±—²³1ªY7µ·(![7¬?¢V•{{«—.;–¡õ,­K2Q/hÓ†ÒKÀcµlŸjÀ€"‹ÔKtØq4›>CrN IDATM[ù‹“8j¡2í«Àƒ=™ì¸Ä“«þâGÚÉŸv¶c7Ú¯Õß«]þæzpó‘x{)õ(Í—{J~fí Hb®}¼öeÅ\ºëkÑÈ0:ü5r´‚¨6S ã5%€&E¥H<@©¯Ðº¢Š'îP΀Ѧí K£qSjË®‹ÁŽ­sˆh ®ÙÐ%›,ï2wëا áV]š¸Kþ"d Hô@VµL¡‰bŠRÌSUl;öl…9eé8x­–›öÚ”W<>tfì¨v..dšèt»i¤JiAÓèu=¢F¡­@¢S±žEWÚ$ÑD‹¦²«QÿAEͪìVõ~Øhhg¿PI_Á§òþ¢K#H<ȺT‰<ÿùEÿ,/GÔ‚û¹³‘ªºÒÍE¡Þ`ëë¿ËJ8¡˜Ò~Ü—“¢(𝵼:-¾-vX ¶x¿åµ¢8ÃôLRÅXJ" $[ ñ'¼>ߢR&šºEúŽÌo=]<®V³ žY½&”¥H”‰)•Êul¯e˜×n¼ýñjöÉ[`À4¸Du¦ÞSäb§¤¹;s<~M›ç:ÍÈ"ÆûŒ>èlf²šÛîD†Çq"ÉuØ7û»¥>ê· ŠÕ4¹ð×á/yÆ"›„Çmž¦þqg{5¸Iãdº7ƒ‰ç烇´tž–¢Þ:³–~xuõ¢3üÑõ?¼pýŠâ0ò!€ JŒƒ×¡¦Å˜¢#r‹-ÿc8ø ¦™ ÇC"J´COMêt,6f¦Õ£p––Ìs†Ç©ŽVΙNsä Õsc7ÞÌ€;Q’BžJµoº¾@# ]À(”TR•X‰Å WÀèe`¬#ƒ•ǃŸ)å=dÓÒ)È)£’ý‹'u£Ój*d¢,M ͤ¤žV¥ò"M Ë^h6\ŽSd‘ì‰ÃÇ¢$ ÷;ÍJB°­¼ªÉy¾ÖøBÅCÆBç6¿p[nGR»Š¸çÝ0d]o=×0uc®äm…Ëz71JA‡ÆÀtù¨Àsý}7Yäi QqáÒ¢×±8Po ¡V—¯An[*ìäéY»ÁÌÝrÄ´ Ñ Ü€Æ yusFÊy“ÿ§NÓ4‰ð«YŠCdI d9üJn6ræá³·ßþìÒ¥Œ==:zåÒ%<ÊâÒðq(i¨u‡a”"ÄUÇ1¢=³Ö€ï€ý¢P1LkÆe½‚YCp`›¦þ’÷æ {gWèö…o=¢lþ(þM²ÜßÿæéÎöÍ}÷‘÷ðÕ½–4z±îŸYû0][ûžIüäú‡¯¼r±ÞŒ¦]$Õpê,‘ÇÓóÿ¨w\dS@,!ákH@ . "·Ù2¨Ç*EbÓâd¯. Jo-°Æ/¹\«c±\Å"Zb+ ¼€rÖ—Á+7üHN•º¥h¾¡Èj?SsxükM‚6w¶®ÃèÔsshö¨‡|i,iaš$)í‰äyÒ Y)óÎúý•Â/-ç>¯AcŸ,oªX(tüA%‚ªäLÏLÉCĘœ¥]P(;·3i¸“¿W•ÿùšreëD"ù§n~ÎâáVþóUðߵ¢¶]Yfÿ^¹ÍØÚ7>º|9·ž^ âþŽYÒ¶u¡JB»Oݤ҈F%ÛV¯Ò©vî¸NjëD†ˆ­`•'ԅÂ5ªárÁìS:ÂôϼÉy<‰ïÐ9ó±é‘ Õ÷ ¢…Á#D^ùæ~t°&÷hoÝó!’JEðâÚÚ§øï“« Àó«V}biàÃt>KŠ,˺dÈ-G3$M”|^ $ÃäAxŠ(ØmkÍ¢F2ö q±c +ÑB§ÃÌ,jáz6;Ë1eÑãEQ”<>$®M»ò;ÊÚïx]¡Y pZ®ðu‰™ÙíÑñéB3±f½ÝªÿcCY&lêùœWlr{!èG`W=‘¨ç8õÖ´Ôün&ªð€W’÷›¼&ÑèxIP‹ža:åŽýúƒêŠn¾nŠ Ï‡^£êLŽrê}·és¼ ¸výhйðÜ‚` úˆŽi¢æŠÉ€¼ºS¤y¡†b7S,ê·#t€=Þç|™^CU ‚/&ñ¡ -¾¥HU ¥åM:êÈ£–l×½¹Ôéèbxîü’»Ô™PÀ=¹\R„ËZÝóTùœ_ÊøËŸ¿·9WaûA”ÕèÛµYß C}ÆÞ^»öé;Z–Å£‹”¼Š5ßÇ]I±*BD²óQ¤%I(°Ž¢±Æf*"1‘!m¬¨FQܽ냚Cc¤·ÿ’øl‚ž9º÷—Áx÷Âãðæ£ð{Ñã(úîà zôMÚÙ~èï)áÍDJãHK‹¢×K"àÚÇרÚÿ¸þéà•Ò šôžŽB´×ôl³E} u¹Ñ¢0ˉ‚Á·BGãy>BûEü…±jË·˜Ÿ²Âûþ‚ç@"x‹ç-:º·È5 ª~¤IR>.¢dá=ÉߣZ¶à$¨dEÎe!Í~M̃%‡P ãÑ®Énù è³Y™]fV3vXÿcâ‹?I ¾/d¸8BÄE‚ i} F›ëF¡ kŸH¢Òðyn.{n¢G¹šoÂÏYÿ÷¯ÿÛªèŠrå ž{ο¶»4ñ(Ÿ¯‘|}BhÛ” â?9|¢iE®Èéͽ’“ |-I‰1(ô,ïå¼[ŒL[c,á:ó¡ î²’Ž¯ 5©«9#øšVÎM&Kžß Z“Ý ‰ù\˜poÑ,tŠÉÙu¯jŽÆšœŸÈ'Eaª-danA@Ú«:ŸY:¥\ûä£ËJòZdêåŽ ´¤$ˆU“§ab‰i $}Ä£'æðž%±XÑYú§0†vÎM•¬nÖ£SŠ‚B0án D@fûh¸óŸƒ1ðQÂùÒXøÞ<Õ¾Yl•½^©i+•òâ?Ô Ìï×RgmíãëŸÀƒ¬]§¤Y•VLÕ©Ûû› ÃPsŽ¥ršNcŽšŽ!x>ÄL°k’Žt$ݦ¡ë¥rqºÈÛ’ØŠB À_pm«bkÑ[l¸TáT*£{Ëf@eÙQÐpñz»Üƒt5MãX@ðLõ’x‹¸Æ¢gëÍVŒ‡;ÔØ€YN_«œnDÇV~ÈO‚E¾žÙ÷À'ÎIa °>C•EÖÏi3dG+޶k¿a˜=ùÇ10©yñ°šÚš±Îf>ÈÏB$ ”›-¦‰hôi€²F°Ñ:Ђ Ç˱žïàªY\OýI¥â“>~2÷öËÎ’öó!3@ð‚,AŠP2ø¼ã1›ååQ+Ìêý¢H•âå'¼X&ø=“Þ¸¿´0Yç!zëLá¶Ý†dŒx>ÃÓbø¦ò¥Ñ¡‘´|Ìiv 3)ì‘Áêm‡·¤‹ssÊ9ÕÒ¨]ʲ¹EÍ×…ÏAW/ÍcÙd#§¢´8*©¡2këÚÕ·®ßxã³Ï>3´RÃ#Ö±º#Q“ ‚±Pibv¦©|Ìg©,@³^Ytü j"´c d—hl;žq™€×aŸ¥¿Ð€É{ËÛ&‹+ âc9|GìÑVT^ôT8‡$„K!•‘§¢Ì2‘Ã08£õÖœ¾úúß°¯›‘†ÔÈFÙ&Ñ9Moí!f¹-±îï@[Îäý[MÎ…n•™jØòE^Ò«64 mºÒâF;/M?¾Ç ÛP–xͨÓgi±iÀ†åL "ŽúÓO&ΤãO¼z>*ô Õr£È™¦)¹^QÊÙÔyÆ€Ç Ì‹ƒÐ©XÔ>ªÊ¶†tTÑa‹•Aý Õ”‡rk œëóXjž)u¦¿"H…ªH®˜("Ç©80u«*µ Wé]µT‰ß-»->\ôðbK#'$„Í>õÒÓ1ø7L©Ëq–¨YšÊi$åeÿ¸«%†´×¤Û¯4&(”‹…Q˜Á•G²Œ»Þ3¦Š¦qw°KÕƒþ’%XNh“t¨ßmï¶)k… Õ¶ )•8Ú$tø®ÙluÖùp¢qIÝ=ú÷ìÑrAu`÷1µLíáD¬Šf¯±·¯¾yá©þÖÛOßÖL‰®E”¥­j³å˾GªLí½KxÞ4•XœwpL^.´Ú„däX°¢½1¨ü' (€0) q[‘¡•²Ñ4–K5סŸ²4‹b>Œø$+ñ7‡ñ¾$zž&Û:©m‰_·ëìíÓàK§9”…¯49ÿ.\ð2žs¢“üâ÷[¼Ké¹Úâ[ 0—ë1úýTHdÊ&(Õ{½0õgv_ÉbQb!¡o7³7í¸ þÞþDÁÛs×]/Œ!Ne1U”®ÒUYWû/kv›J f½jxªÁa‘²Y·*ÇUØž²^ví685ë",cñŒ™è³ÙûB$Ç@ˆ´«(ÊuŸxÀ¬/抡6|AéßeÕO¤Ÿ(Ù,Ôu»à·lÙ]v˜åËn¼ìvéS·û£(þ~ýy>fÑøGOâ^FH¡q`¶1UL"5úƒUÃÃó –Ô 1Y»LÏ¥Ù3ÊvÝ„”™Xq (ÃŽØPQÿ;ÕôÎ?ÕíOÚígõ tLÙ69ž—š ~±ãq–lx^¨Sœ¨Fñ¦Ö‡oÖ=ȪPéÖÛÑÅošOÏ_½põé×/Ó¡¿HuºÎ?âIæYÀK«!ÍÛ c‰bE”À`bM"´ "L …à˜*šó]PmAÔ‚ãDYaÇÀÚ ¢¶Å0ð¥f@9fË´g¤)=ª!ÒVM•/*IÒ ’º^À‡bú~¯xFÒúN„_Sh–Õ¾ø&%ÿ™u·%Ú‡¦-¥¡@ ÿ'ºï°Q𤋲å-øk…XÜ”K) •:¢$¬¢rb…kÜòd6 _gGÇG³ÙŒ™‚cj@}{Pn{ïƒB!ã$NumðÈÛõ:%#,¯X§ è˜õÓ'åÀa Lˆv8í§»NŽè£•ùò.•g±Ù©K EæcÚËçuW‹–R² ¾LxWàåÞvÕ•JÉ><³òì!›NgåÙòìÁá>”gñÝRtˆï‚ú'~ðä ;œÍ{õ ÄX†P”¥P1Ô Œ.5á_r›¼ÜÎ’$µ)2X÷X&È™ Ùx øþÒ:ïò0'xɵùmƒäfbR~'5Ú#ÖÄ©{­³+'M¿åž-¸ÎúÂÒ‚X–1ìýÙ/irµ›ƒ Ôß«…1¦rEóéÕ×/\½Z\|ó²aY©"…P=jœÃ+‘ÃÅ'*Ÿ„<—fé_Qz­R6.êªÝJQÛvß缟¸€DWL.ø¢‘ۧH€åCÀPSØ1pN[“UÄd™š§U‡Ç^ýVw†|Uò€=h*Û?#éÌ9´Û I¡öqwð›š]ÔèÓ ´a×¢ô£–e(*ÇáÕÀËÁ;õP¨÷ÿð„û¶®^V,\†YÈ ¡´ØñÙSg³'xŸ=cíX³ª'Ó .£³}J^Ú£~ ‘˜Ô½ÙT-È ÁR;CúÌ p›Lvø®÷ÉØ3e.xÚO‹¬²GFFýÝ ÃÌKˆ§–¤Q$SÇüH’8ÏO$‰¨j\ÏÌ:oú,·V¬®ü;ýöÈvFk±ˆL ïõ'ÖrœÀ©ßêŸúÙ}GcMyQ6DU¡öXì±aveK\t[³a¨W9 Gú¾Ô7N;;QùÖ²qO™xnó\H}@™‘¨óÍíí9mG›Šˆ @Ïâ R+«{øÒ”°†ä¦;aÎYwi})hz¿7Ë¡¡ÀŒwsUä¹Aó_!_ò9P?0ß<ÿúùׯ¾~éÍóoj–”Yqä]2µVøÇí¡ÇQÈÓÞ†ÅrBGO¼$À`%±$A2™IÛéSºY®R4Ô‹:£’PíΙç½K5”šN“Í¥V(  } ©%ÕÀJà¾Sø¹D|‚ïCZøœ9é1Gƒ|¢éù\ Öë¯!š¦×'q =∆/È2×´ÔÖ"Ö¢_Q¨³lîVcÇ铃‚ga%Ψù›M=>ä÷fÇéìOÈã^âÚ ÕÔ˜cÌ|_HIëBÄyþ$òšB¢Ö†Ù6‹ ´«ÑéY™ãŒÇvÏrŒw©(z8¬º%;ÒÆ¥Ér¸`±˜m6îf?ì®XYžáFFn±HRÀ€>/D-ž[ˆa<ÏE/ètze$R®ÜÕ2˜¹´NñŰî3uÌ“ƒ/~¡ƒW®ñ| H™¬1OÒºJJQÜZ`—Ã2 ã4®iFNTš‚¼ÓqFÎ"o)༛\àåG,ïVûü/᩽;æüN‡ãƒ¸Û…vg~‡zêný#UÂÊí÷Sçy*‹n;u¥-UßꦙæqÆÂ„ ˆ]Ϲ®…ŸÇ± ÉÔ¾@Wd1¦7\p¨“­]>MÏ¿yÞŒã'mêç=å’˜™¡$4÷O)r=NÖåd(E²’18c1VŒM. sÛl;I²2êëx€f½ ±X5õþÜ€õ¥Ö˜‘"B„qÔ€A]àxn±sÚ­®N¥¶°õ|,ŽdˆAÀ…A ðg4ÍqR‹B°ªw@¯u36Øbø\ÕA\ÐA{¦ÊÏù¸ž^ñhZŽ S80´ê(‡ÉíØ&3ïÚ¸ýx… F¨°éìI<;~=À¡š¶^zé¥F›ÍÜ 8ó(ÓÓ¯Ë&"êÚ‰åjú‹Ë)!£ûýŸÚÕp@à™•9ìßýÝ!Ø©ªi¿x\±ÌŽ˜;®ò¡]y^:c«›¥ãL‰ BA½_Ÿû/òîÄŸðÁ8a9Ò ¿,V8!æEË «ª³å¬°ƒäùç;ûy^ÀzV5Æ–”<…ˆ+ŒŒvÝÆì —¥tþ·„XÄUoù-E‚€§SX£Ù¹¹è·âP5Sž“KªØ‚1ãÿ¿HP¬qiK¿6'¦!Þ¹³óó­¶·ïܳL)Q/$£Ÿ¡¯N*5¶IIStÄÒpµ=®n¹¾”´&­Wµ4cœxZ!ßU@:|Ýt0É£dmmíâ…Ï>» ¼höeÊàú$ Þäcí‚.[}]¢#'ɇ-Ö%ñœ`¬,9iH4áŽe¿ÑÊ5 /é•Q’‡õ êÆù e¥*bA¥(:I‘‚ŒR%¯+ü¾KUª4! äÀy|Ëþ×0ãz`eBëƒÒ¥äŒª›Î!¨ËjFI?=|Mm±¨ñ†ês£¦=¦,Ô_ühi‚µì®¦I·:îåÅ“‘STúîPë)Fqר`0ž@(Õo¿áÚ\5… ¡~³ðRã7(N&¤Sçµó?ò'/Vr 73Ì2³«<ýIWn™†ˆábT¬GT2V² {Êfi ÞN¡óï'•åŒs6ÒWÒL#ƒ–šv5Ed DY¹Hlµ:Í÷ñbp¥×u›µ+ :&ÎuËðy×?×r›“}‹“‰Ÿ?ñ¡Oc=jH2ve ÎÕ, c >fA‰ÀRÑ%B•*ã×PÁLÂñQ[ 8jˆ/u¶ÝðÀGxàÔi,“‡æÂÃ%µ‰µ‡ÃÝJžw4cN9¾ÿ k§uÖDS–Sý+ ’ÚÒI—Ûñ;ç.u¤ˆó3?LŠB×õ?WÈGxh¢˜Ä0kk×ÁËŸ]9þ‚L‰ÃŒi}dÅ–yÑ´BšeEÖsOW .”D^JM#.LQ1°¢Ì€ó9з|/R”Þ ÔÒ]«œkÌê\w·)oOïÒü—ŠO… ¼¼.y±pâ$£XÈÓ̲\ ùH¦|F.¬TMÎèfî.#Ë©¦BÀšàÏvT«n‰ê@èJ¦5(ÕÊr¬¡©«¼¦ª©fÓ'ÓiAÍ¥œ˜á¦=Íîä&íñQaQÞo~q^(±}ƒ¿lº›ŽqÜYŸ¼ÿ>a‘r=©Æ|ÓW¥ÔZÑsCú;Ȧ¢[öiÓ»È{èáá“›-W]‡ÅìÐÉÇÔ©³²†ÙÈÒ»Y^ÀÃQžÍ® `íd…Ü%Ö(ŠžGꬱè7DU˜Íü,Æ÷âFÇÛ¿ñÀ_.uÀoñ¯QtæO‹²°–2-©%šÑËãÔd‡}ð©˜à9Q!-%‚á爡±×14ª=׳žD¹–‰’*‰À#2P–öd ×twÇ’õ2ˆïç[›ó;›Ú6¥ü½n\« è˜Q2ÚúJ›¼Ñ6»JÐZd”"xQçÆ-!lÈ‘òç y_H"%×Áûk—Öž½]ÊK–PC°´`L¼v§+žþ§0d-Òx¿ßÕÕº£/³F†Ê,™kañYŒ‡É 1ŒóßÃ9äº*h¹,v‹n¿«öb¨íz+*¦‘顸…—t™çñ$å˜W`ï•8±ž §–·!4…²3º^:¸Ûf妖Išn©à²œëõu§ÊóSÚÌ+2²u§õÉ4ƒ£ Ž«†GñÌ;³ÜT3TMÎ #‘•”÷÷›ÆK ¼=7HÙ”p y‚‰Lå‹Þ„§úí„Æû¸QË ¼èæÏó"³ÇTðÞ=ÖÁ£ñr:‹Yêè‡vɦ¦ùýŒ¥öc8v>²Û¥ÁÒͰ©•íHC P j‘™ìnàw|1ô½}ËÖ(AÍ´sß¿ÿ ·ãqso½bÁ÷:ž\‚ê(…·,OsÃÌ ½›à -Á1‚çú1íC«ZžÊ6¥Ä+Ôj¢U…žÁ ¦aYÿ'³]—ø;CaýW½&(Eì8†mlÿÍöß¼¼µõµù\Ÿoß«{Öœøq—ºi‘Ðk<h•™+FÒâ|X;¡Ã·ä" ]¼‹¥¬˜2ïkòŸ*ä½Ðã¹€Ex×ÖdàïÕ×Ò$Å¥îªpVÝ)¡¥I™jFÀ™À@ärNû=%S»ÀàôÝ àhˆa7Ìâ8’„£Øì‘‘#æË´\v²L‰9„ê„÷G”»/Á‰¢lC“ª©jÊœ{MZÝÑë^êt„d¦s¥xFQGÎháOëá·À†°#f·î Hó;JÝí}óŸ€ò^YõÍöý´XÃw»–íÒyÔ69™‚ Fè&:›Aò-â/›z7c‘Eí¾Y9…O†ítP ´çCÚ„¾ '¢¬RÇKݶó. Îd?Ò¬qÆ*›Óg;hW,ÊgCÌsÜ.sÛ6zW²Â®ŽÌÜÔ 6mø¸SHl9‚¹–ixX$Hߢ¾<°ïS{rUÏ íô°Ò;Þºû¾±ôÏ !ø¬Û’aU2Ù¶{y’°%IÒã\ëá"x^°Â’"áñ"Ã4ŸÉavl÷̤1Y ;î9êÁÚ9LJ"O›ÙÊÐP½º#âR ¨ÎÝ“í;³5ÿêÖ?|í¯^þ‡ùÎÏO+Æ©»n>kÖ ¹q‹Ð”8Ìv;Ï|‘&ó¼ù”:®hÌŠô$Ö;ÿìÆŸ*ä]ÑóeE”õ5!X!ü½Båú‚¤šç ”,+1?¡FQ½m­§9kÙ¶ÑÓ²-Os•ªN4E‹CA“¤µ¬é) OüF5:;mú—BÀ– *Ö´Ü €ætó¯DE“µU?#Ýà«æ†ìÛ›ª®˜ÿC©œÃA›õhƒq»¯kCÚ’)hÀqß ÎGv9S¤gÈ;þãî÷Ðþ= ÀñV«ãn7ïŽÛÇ6nJ Ip2#°ÛCWÔ@y/éòÂð¡Bl“ !>afe|Q·3ñýÔ& ¥ J¤¾’Ô㤊v5­¨çQž#+³ª¬ÞÜ/Û6Mª( ¹¿b;C62-§ÌÛøXbSgG†©45áµx>R¤¼ÈžÈs|=¦ÎüVãÜ9×øBߦ  gT‘·´¤yë‚;¾ÇgÛ*––‡IàF¬Z’¤±ŸH;ê' ½Ì)öŠ 6VLØËh}ÒiL¸¾IÑ£î œ‰vqoe™Þ¾·@ ®Å„m½üòÎöÉxƒ½ IDATük_}ys{kûv4é.£Ó~ÿÞiè9?¦•úR<6hŒ–ÉTf OÆ•ÇÊCÚo.´(ºI‰Û¡õ§ y.öÅ\å•ëWÁ€×µµèU ‘T$*꥞G ´pØ!BPRk>Ÿ SÏ fJÔT3£Ù14„-“$Çq%~]êìy0И‹n§Ò Mºü×Ä‹v¬†Áe¨kU/*z=«X…àƒWÉðG)ðšm'ƒƒÏèå¸fÀ\Ò „`UG.3š©Ó—©™ðÉqö xE½,–YæÐ\ð£ o¿ÓÅ›åÄnZªµ“©`0ü½¸Ê# ¸Ê öýˆÑ^àñìˆ|1|÷ ¼ óáŸútøUŸ1Qc­oQk@ÚJ¶Gíbj;~`;‘5 ²t¥]ÂVUÛÑí”Á çæ  ªA—â÷舽Çî’€» w+‰!´‡ð€÷©“ß n>Õ¹dÓ Ö•ë‘V1wÿ~c]w1®¦éu¢qOÐVqm»:5…Îc °¥Q5-¡14 ,£eª¦€!h§¨ÒBÍÂá´yŽa0}œÉƒP ­ 804¶·N¶Í¯Í¾óòÖ|þU€ð«Ýa9¼kiXP¶ó¬¸µVƒ¶Sµ±¸2‘{)ÃÙtJR–ÂdOÉEªWýŽÔÔØÚ•§×"øõ¢ŽS Z‘ZŠõÜ&1b. SJèGìI9êv%KÈZÚ ä#’1T ÈáÂS æwÜјš1EQ’Ê <ÍåcE¹JõÊb‹x„w ¸úzxg 5R™Sm•¬o‚WMÚg&õrÒ©àI7r}H{‚ê\ï«ð´z @*î.S6X_ÜX)YD£ÛÚGäjÖë¿ÙG 7-ÔÚÉ ?ÜÖ{i”÷äO¶¸v'©U•ÇÆ»æ0Y¢L¬ @XV?€}H»ˆ²³6ËØ ZÐfÎ÷Ye±q>£-—éØž™Æ «Vf¥å¬P¬§ÌÅC‹ÍÆtÐ 7Øì~K ‰°¢ËóœßºÏ{­VÝ Øw@A¿ÉR¿¿e¨¸ ¹4½Ž>ñÆl?¿ô÷ýXTÔü—áœNº™!çqy^3-gö{‰“%<_êNÀêlfq‘÷ÏqžÇ“÷È[@}ßìÑ”ª—…ŠÖ›Cxðϵú;;Û;wï˜/ÿ|þó¿žom¿ðÕ¿ùÚËðW+%)•ŠWíÓfô°_ñXe~“&Ì@øl,và¾õ"K²Ëº³lz R-üÞÁÍHúc…ü>Ȧ”+]g¯_|ûmÁ\[Ë/$¯EtöQ—M¥KJMBéœ6Ëhœr¡6è÷C´„)[¨*ÆÇ† t1%ÎrTēĔLGyÖ ^œø‚ò÷°ðÎQ(¾&›w±\Eݰ4|ªCg'ø'ë%µ²NÀ|À†N°‚K-!ò÷Aï ñÍ©§Ý5 €]º3• RɧîÒ‰ XüžNż=-fÓi4În:Ïj'S!‡^tª¹—^"#:²_Íc¹˜™±Ù6ל¡Å– #¸é ÔF=ôÕ(5̽¢*c‡2®ˆ!ÿìˆÒuín oAÿd%#x¢ÜÌz…>¶€R`–$lšY‹`§l*E$Y@ìõD•ó"Þ%lÐØŸz÷wh–òbg!óC§¥¿\\Ò\ÈO¨“¿GÓe¢(™¹ªIÛÍOÄ£Nd:3¬±•SÒÄÊÈÜ55Ûôi‘AG-¡«,Ó dU*u‡ 8~i©Ãű¸»}²õ;;æÝ¿ÞÞÚÚ¾3iþÕ;¿Ÿëõ+Щk{ŽºÐQÌxÎGÌÒ«™Å”H ]w««fº1è{qÃÿc…¼§Q£¡™_õÚ ýé…µK¯¨Á®¦!–Æ} ‰ñÔ æ!MS˜³˜æ ‘ߢÊM’„ÁþÓ[ž§RšfqHƒ_¢ëØí¸ uûå–ï…g¤`}ÒLiU6u1§Ry²)1 ”Ò¤&¯ŸWt*š9n1\tƒ­àÒ·ïÙ‚È«FB†Ê4s#[šð4e›E‚Ë™w·w¶)öžÐÐYá‹'·N¶w© ¥3;ÖØ¤c ÑÖºRbä0ŒÆðŠ÷¼Ç­{±•+•žÆágÄ‚Ä?³ÀÌꆅ6ßµ¶Û—͵ëko}7-kíòåöšÕî¿Ý i8Ób«ì‡‚d¡äѤ2¯˜!ˆQâÆ>¢³ëæìº4QSCm%†D'C!¯¦´‰Cc¡M“Êcq•„p'“…¨c?D€‚WPŽDÂD €UMáz Z­ã¯ièÚ™ÑLç” £çÔg.§-«väÔÓîµ”}Ðë³Ø»"ú{BɦkG°³ÇþÅjZt‹¢ªr7UõÚÉT0bYM‰ï\—ÄÆC…E@žÖP†„ FNo¶²¢—}:vg½'ì,¢‹Q@ª¶±i9è²Y^Œòbh9Ã2aÀë¡Î»++ÐzAÜý¯ÉãH-vpœB¹õØTëþ?Œ ÕßC`F‰¹PŒ"?¾OôGƒ²< QÀ³x¿óÅuö¦g-ºgÁ„€Q®1O³ƒ4¤Fmº~^ˆE#Õ ÖÌ´à—~Ì5©¹PŠeñkhRjˆe‘¬±#j ˆ0?B•âÒ¢±zBÌgòûþùP\w×ýu8 ô©ýä6øz’ol¾t²qgks¾½utžcÑÌæ8É`4R(ðb@[a/\šìß|ýÆ÷n®ŠW:÷.¬ V!T$uÑ3žY`sY͵~MÈVÍìÆõ«òKk+¯Z7˜ÈôWyI„Ùj’¹ðšàè¥ÙñòØÐ­%R“)35s1ö)=G*Œ H÷e¡]ÀEÓ6ä«¥‰ÇKù»” Z bŒ›tíð0ˆÒþ:­0ƒ+_–:PîbÇαÊÜV·¶æ··o€wîl~ysãääέ»Ô¼t—®D,„IJ ‰fVVvË;¿.§ª_¹òíhæ*5å’u8o4šÚ3ò+][¾'ðj¡Ço\6Ãñ×®ÙVª¿°k®yíÚ+¯—¯È¢è'šªÂŠê, õCLTQ¤b¢(ËŠìãk™ê°¨ƒ&«u¢V"Á‹q²¡ `@íMSÁÉÔ2ÄTÌH¥ºOa¢]“{e*bFè•ò¹Z·o¥ÖJôÜ"j¯ ¾BvœxŒ°»ÕrõR_† ¡ñÚµ§5¶ÓŸÂëHÐfS%l÷º9(,ß‘ŠìÀÛ¬¾ß5htaa[¥GFN†Á` bO nÂØu‹ú4Ωßh<€¿ÅRô «ªl*Sùa­w’Ù¼u{kkãÅùí­¯ ïìÖª¦æI%ûëè<ۄ䜚 Y¸ü}Û°i[á·¹èÉbøŒü@jÌ«ÚUêÙm^5/²k«æÚ¥·®Ý;oZçW­k7ù·^©ñ%Jð‘’©ì×µí5ô:ê Dç—’¬H±LÃOÁWo&Ó nFóQ…ŽÔæwÔ4^Íd\sCºpEï¸vò­P.¹«×®4!ÔešrÏÒË»ø7Wš4ôI–´3ß‚GÀL?WêC Á=ØnmBäǼŠ4È’pßsÃ}W•úPØ/ÚíV Çœ)+¶k'ãÀ`‹n§œGL§q–¶ž­ñÓÿû °gÕ“7G¼Ö§S»= Þª÷M» »f/$ƒìL,£LÙ4ïæÊPO@z4¡9VØáAúä´J.¯¦øíˆÁÊŽø@[_ÿ"‘â0,0µŸ^ÿç%Pá’m >서b-é#¤`·¡Õ‡ÿ¤Ýã,8î¬,Y‡Ax‘—Í>Dçqøó<÷á ˆh nŠ"™®w ó]«]êÎpÇxÔšÐÞKºK KQ"²“»ÚÆæ¿ÚÜÙØØ¢‘„[[''·6¾jìž°ÿŸ¼wínë¼ÎEõY7^°î÷ÀÖkH€³?œVC¶ä¸§¶d“’Ó4MÜ„L•Œ8±ùÙíhbŸÄÝí{œÑ¦/H)µ¥´ûìv'»M$Y¤y“”ïçŒîú˜À÷3Ÿw”d;µ¥ZM½D‚¸é]ÀZÏšóyæ;ß9/bÎPœ…"ñ[.'‡(I¨$pž¤»éŽ.³âQI6@¨ ƒŒQEЉˆ¡v¿ÒG±ôžbY#é‚"jZQð²Æ¶}¤Òô5Ëžj¶HÍ,ˆb'[º™jZk.X³²ÑógΔ\2ל«¡JÖí &ÕÖ–U·Ç[YkªŽ$B¦dZD±¸™ —Imž§Úr“èµr­F=[«e[ßNâ2‹¶6D¢>UW éTה؜Zi¢TŽFDpÓXßÜ\_][]]óÖV#Û›´WƒÊÖÖ6Ê£f®VÖì5s‚ðZ²W×c;]¨^µ79býÚ]:ž¸—°ð M\ …—ÍGÌþ ´ÇŠc³EŽÏ?ḆS†AÅÂu¼‹†qH!Õ“=dD ¢È²‰4¬HÑ_u®9oƒÏ†sdÈuŽ+Ï7e²ê¦y«¦ŸßÊNYu½úl³ÁªU›X ý‹ñÍ·{ÓåT9Àz0©[ʸžm™7jIBrc;NÊi”A.̵^* 6²¡YXR«£÷WWQæÎ…¶½V#|l•ÙF3‰­ºE2yõ ÖɉG7GÁ"y.¸`,š=xà!LÏ"$82<4\àxÃQ›vT*Ū&"Ù= C+#Žâb¤’¨êxRB:–ë‹W‹_%(;rBT ÃäV"—éàWƱæÜª-›Å"?ꆢ $ºÜ…€3»½öÂboi }àç{GHŒ,Ì÷ú½Î… ‹HÆBe²ÃscCE:g•\6­¢Æ08Qqž†Ü]ÞÇ‹º’šöBßã\27ºaÙ_É})wú´ý´¨TO™3¡y"81}ræ ã$Ñ?ÌH¨ª”°rƒd•H‚!è_¤ cHryÖèZ…éb% Y‹:¤®Š>Ó:ƒä‰Ê2úT.–½‹lf¬¤e VÈPȪãÄõÙ¡¨kb (m즠(zêûòzN °8GœŒÌI3K:Ì0•TÓN®äóÕV6[+ù±æºÂþõ¢HÖíZ‘ùV-/™“µÚʼn)K'Gü¢Œ•,¹à"9]OÍ6¬Éqznb*)7³­sq9IçØI}0cake] ò“çnà GRÒMú–aæ¬Áx” IÞW·vñ—'º‘­˜Û¥Ø^Ï¡öM.×"îTI„”[ä‚ëéBuÓæÞ$cç:×™ä(¢i1‰‡s É(’sGÉÓ—y“Þrx¨VÔöF)ì× ü šU2£#‡s(©—hÁDâ7m¯ö6"WÑ™»xÈ®è• °ì_†÷&Ÿ£jIž$Ȥ-Šd„ µD:[bá#{žØëöÎÃÏ¿þú<š4̹xqeÅÖAâlžOŒÚDâÍ Y§Q9$1OÕu W‰ûÀúÁö‘AÚxX°ãÉ>±4*ËæþÐÎM?£¼‹OûwÂ9ñäõޤ?qšÙ:bCtîéz"â.a9Ý® õ° ÔGŸÜi(£ä*kO§ˆäP•X¦/Æþ£FŠ'€[$-Ô ’Ͳ¨DL9£cÎJ«“ V•¼’<¸În‡äƒ#Ž“¥žªì#_׸eh-2€5RÄ ݘH5-I’VµžÍgÏ~ëÌsŠ;ê’e(\ä@b”oZSXIˆ´¨* PÅ䂱J„E¾7Ÿ ºFæææ®½å^»ŒÉ´/.p¨ßFÜÁ#ù4âòôm ¿¡b¦èÞA¬ ):ݹñFk½„K>уD«$ÛY…:4,“SÐzÑV`bÖ*¬  8wðÐ~Y ]·;QbÓü˜cG ]FYóºç¯êŠUŠ"?Ý %ca©×&‡Û[\@gÂó °~¤‰æçû‹=ueyù²íYÛ 3=Tôe_M+‡ü¡•¹V(ŒFë'$º.JN‘óFå¢# ž+Ñ •ªa%›}öó_Ì}ñ÷>¯<ýôé X{ÂSŸ)þÞ’èË()·ƒÀ7hë)¢'cqDìPAatUØ2Ö B&“)áºBr•ŒýбÉPbQBôÞaÈDøFaQ AÐ@Q@T°2Yï_x2².yD{û\“¦tkÜnN5nÕZX†ÖÒk]ï¤i/й7 +I¸Â(7rÍÍZ>òþ6*OXM«6•m5­ÆäøÖÄÅ:« ÑÐoMLÕ­W³Úä³­º6^Ë‘ÓM.¤†Ï²'¡8ô´¿YéV±¤>7µ]rG/a•eË®¡ ^+·Y)OÙkIsËÞsÁÙÖºÙ"¨Ó*!z ñY•äÔ4¡Pf!BO+”åËš"‰ 9sÑ!ou²´Ø~…›252Vý• "h͉ñVˬéJ¶®¶ê €ç¾µöµR3ôÉ·YSu©]­^€Ž¨×'ÞE&r½­w땊U›œªWª¹¤¼™Êlƒz`“$«]±u(­:N wô-gÔÍ(Y;.ò—ËÅQ±ŠV2ÄÂIýVâWm/YßÜ\õÖÖVWW7×£Ü:æÚ°P“p·ÉVäµVm/6¯ÄûŒ¨n¯Fº_Ï…¨úA§Ì1$×"Bd/¢U"§8„ W‡ä€2~TQK5k,¶sA\ŽÈ¸JȽ$±ˆÎZIU[-y.É/³µn%±Í‘ ñÂÀ—$#)MšeÕÐZ_6­ØT;—óaDtò°€$ Ÿ©´µ¢#+ä:óCKà~; ýþÂÂÂù…vûü{Àùæn·CžXÿ‹/YfÝ 'pd°EŸ÷2‘ zŠxí )âOiqÀû¢ïÅb‘d3™BÑÙ¬ýnõ´ñ”]×I("Q‚ˆa1ò9ÇW¼„È‘®k"]ok%q\G…R¡‹FAÑPMˇuhæ6˲8ÄqCC.?â¼\Æ´’$:)CLrb­³œ")ak–9­ç¬/]ÓÐOõgfÚmofqQYZ_"'|þ|ï‡ K¢¸°ðÞaïGèa†ßÞ|§¿¼B¾ø¢Mt(ŽKXY›„!’'ɃEò©…ÓúçDDêèìCð¡DäT5„‘éÍ䈿¤(§I=åœtNœ øf|^ Q£Zä2™¼(]–Ò «…N˜€Dc°¤DèÐvʈ•S êoJÓ²ø?QpTXëv€Áâ,º/j! _‹˜¸û‰eCÖ–W80lj—‰:¢O7™®„\°•SBp4bÏÚõ¦U­Ú­Ic¢¦çè*óÕ¿’¯ÆþõØNbŸ¤™ÊI»nä&²Äñj•–U¯$µf>·29ž%µ±Éš³l6k;ŸolMk“жFµ‹® j‹—‘E¬Òå±LÆç\1\ôfã „‘QúM;ß´×ms“ߦ´Ù°¬òNl%·V'¸monš¶×ÜÄŠ¼‰œk¯…„Ë5çF´e¯6ƒÕz3òžWÌNÆ-f8—ñ½¢r^&ñœÐ¯”J^è¸aTŠy]0c$W¬1¥•[uAV µ"ŽŠ¤ðb%QwE[ +E$S*â GHÕ\|ú7ì‘Ò ºÚ´ÒEñd é†Mþ “’xº$žžxòév[•åiQúÑâÎÂúQŸLßù~·ßÛi“#^Üé} 9Šd mãBײèØY–“)4Œ8V%½Ý“O)Ú3*¨fpe,R† ÐCÇå|Äôä”:ísþ4 ¶ÝOðFI1+ —Éd)=Y@Ñé m ÀcÄ:A¨„3]Jé´‹òÿW‚ƒÖà¶#Âì Ê-âa8Rá±U¥Ã «,MFUbSÌòpÕ0#XiLS.)Z(ÊûZVnML»mê·¦²Y–ú lÞ¬µ¾ò*²çrÕ2©èÖ ÏyΪÖÏ’©³­êÖÅz3)רe['£¤^7IWtØSfe+ßÜ¢ë·OøC’Á¸¡NªYR/(1yCÏ'òË–¤2Q³KΛd‘YRQƒÒ,¦¬æúfiss=Ü´+¥JnU'aœ­n%ä‚=¬È› ¸Z ³öªeolmMØ}‡l-WBvváM§ècg¬DkžØFéYÑÝL¦”Е[†®–5­n;aƒ, ©é*š¹ ¨•$ªjÐWnLVôªNò‚Xb¥˜qÿ¦àpîedX(òîÒPd5q oíÍur?âI¾$ïüåÓ'Å'OœX}RôÜÕ§¦Ÿ–§{ $€ww~øWKó;ˆÌ, s7ž…ù#]²ˆö¶½N×ì.Û,ÃÐPP5Ñ?Oz.iFVfˆ¤J2¬ÿSP(X@µ?> fÕЬ€¼sàó¾3BF9£ùNFæèefëàoELõ"%aT2ti/N]´1ù¶$ Ó§˜½ 6ÈùB Eéû*O+‚‡µ,(%˜C¬$" GP)òe‰„%ÙèËôVÍÄ 4YFñ2?O‚f­5k®RÖÈõÖÉN´êüq.g·ò­×Ï—8fºd ù˜ë«¡„NòÑzI'ç*¡†‹¡aÙpYe]M_™¦ýÍ x¨ ¯ øŸP(äYò*ÈÊ(¾4Y?F4Ù‘¹€<]HXd/p!˜ÍÝRr¹FÕ˜¸À^Ž"„Sš¡’•7 kN‡´A›¥&EÃ3‹z±je.«5 ÉjCI .“Ý‘c1Õù¾SX(ƒÌᩘ®v:•²' DÊ"ñoe´hZ->It%n+ƒÂßÒ2;HˆyD¬¯,’Y\’æ;z·k’3Î^´ëŸ¯Æ±ŒõäVàQ¸‘Ñ!‘1ò¤ì=)¸/T8'#†™)”RxTŒñXy)„ e0«JaÈD©ŽH‰QÄ $ö¤“þˆ…ç•gŒ¾ZÖQ°ÈD HVOF ÅPAŠx¢©–©c:xZ@À BÉãIô©DvÙ«d=%TDEjZ­¿,£¬ì³s9QÊf­Šª'~•9âf­Ö =2e¿$ÒWi¢e[7«“­lí\œmmžÛ*×Ó©µºefµ•ÊržMo '¶59•­¯4X÷G(ÜDõ²P$à‰Q ú.]‡ô9™œ.1@rÀÈÕw‘2:ç¼yõê5¶|­Ι;ì*¦e5·‰ÔŒIc«± ²‡¦±ö–µ†y¹Ä.ÅäØ}ÓÞ¬–c;NêV”)d8i$š£‹03º£NèúDª]"4‚PJå¦>9Q5–±”†µ?UT¢ÜšUäa«±{ôVô¬©[‰.Z93)jfõEOäÉ–Eºš‚K.uR“¨§†¼H'Î0mÜ‹KŽ×ò]Aòˆ‡:ô¼ï?Y$-. .ñδDè‚$Â×ýCPz¡¼°Ðf|pA"KH6p;ÛË]"aÝåîÌÒ!O@'%‡Jê3J(óOœwRçèsdÜ(òG3%?C–9"ŽŠ:ªV I0 ¼ÑÂfŠàñºzHoI:ña™¬Ÿ|JO©Ñ)Ãèë¦ýýéSÿ¬”N‰O?cª^0 9cXÊçôÏêç éi³š²Ä#$ÒÁÐ@Qf] d˜E÷1::¬Ý6zÐ8 ™»µnçê-5‘[ä‰/Úf+Çr”iDtÇfrŽdéÛ¹Öfªu- äz%±j*›ÞÐ b#AU£¡sùõ$AÜfÓ´ÎêˆvU’Psï2iÅÀ§èüù>/’Æ nñê›×9ÂâÕk®{Í˸îœûæX±0ìÉ›µõ8N^ˆ##ë«¶_5㩬¶Ö°"o2_¶7õ‰zìÅêß&öÙÀÂR£ ðGæF<2¦Þ0_Ð"N©N㺎° Š”¦¹IU/'¥„ÈD²MϘÀÆjI­kªÞ2”¢Q·³“däÙÁ(š‰ÍœW¥ïñ訃k\W"‚w8ê)hÑ¢p $¨<ÊK®ó #þ žè¬z×GÏû#Ç};“%¸à¥#dðq,I°—òÀ%èá6g‚Vß ‹ r¹¬N·c£ iKWˆ\„‘›aëÈ逆‘$j¼94:Âsk.§é‘Ç=-I1}SÏ‹¢˜`Jt‘£SÁ®>Á™@"hQ‰týAO«òçúÊ)º0§§ÿß§­$H=ÑŸùç¸'ð¡Ò)UžögNË%A u¨gM<Ué•$•d×b®™GÜOŒBIÄãJXð$ï3šyº˜[¶Anœybµ%›ËUkÈñ³šïVßµ'§*‰Ýj•·*ðºHXh˜]㉢DWjšÆ¦7bÉŸ+H¼TéZF6¿¦ðè k‹NÃåH@jÙ"O}Þ >ã|Ï÷X¾«”ÊÞ‚Ç››Cî”S˜öì’Y56¾½¹N*xùÏÿ2Ef/»‰yS­ÄŽc{\µÏV%ÉÞVd’0^fxlŒØP!ðuÔðµ‹ëš¨uI!Y„ôDU¹D÷VE ¬ˆ¯„VÖ/YÍl.KE3Û¾Ðëˆ7ßëþÅ…l>‹|LÕÊ®Uç °Gœ¥ /²t)¢å<=2”„>gnì«sXFY˜›-J=ËjÔÍ­°7íµ‰l«Dþ¶aEžÕŠì³‰‘³ÏÆö6ñOIÓ\–Çæ†~¨P " … #ÔXÉÄ0DBn¹¬s"[å*¡¬£ÑFÆåø•±¨•[;‹*vFÖ­ÎëKÞQì‰Ý¥îÿi勈S4«:ëðˆ:ƒW‡8“!Ò¡ˆ„“ÔPSP Ð“eO¢'H¥zj#Ÿd…ÐÉÏ]s3™wè4ôƒn³ŸE,’ƒ)$‹Çb‚KˆG³”…O†ls\\ì._¼`¯,£e®mXÝEÂ$²Ð³&¦‹+ò2(€JXh¿îˆë`=8&#‰zg0J[:‡õL iêÿÒ si‘õȦCæEq¨ZX˜´Œ‰ÀXóÉÁxB0ÄQG 3ãd§%•%ù+?¼HÜçÊsÎèììá™(9kïë¶ 9ÒDÀ¥e¾Ê¦Öì‹ÆÅpŽŠZ1Àø–»fm9ˆ÷-aÈÈbzcÎAF7+iŒkV~›D«v[il¹àDAÀæ#CA )ä‹@!Ï AÆw‹ž¯¨m Q¹.RUŠs³sWçÞœ›=0[ð…—ŒÉ8ÚªjÛ†½]5ªFlŸm™(Ë"(š…õ‚Z …>Ñp×½Z8t–…ÂìÐ2Q¹À2l’e&EÓLLD6Õˆb›*©TÓ¤Ïèq~Ä^èœA# ’« ‚i1â&𦠧\>4B¬XCO0dSÉÚ}eFñy‰›Éx‚?­,Ò€$Œè¤Îæ€ gd`µ ¯©lɱH¬n9!;EÎNöÍ]ýñØì¡±}×DÈNò’|$Gª+VÈD,ÆG÷éLWuµªV50>I1y¡`l$ÌHã6ª\"w’àÁ!µX,&o·L£šl¯“y'­òðBè†$ƒÑã…4H! Þ.’,ö ô[DžÀ\qvöêì\aöÀV(’IªUJö¶cG‚Š¢h/KQQ7•ñ>¹ %D}-)S|kh®8”uq$“ñ 9ª±Ø_eœ£¢–ÝDÏçjOF…û²€x¨'g.¹ž `!˜ÒÒnZËV>‹BÉJQ-£“nz ³ž4q%ð1qŠÐ¥¬.q¢µ¸úñôeW1q…•1ã åIL¥äÑa΄˜•ÃlPÈK#[7#Ç$/ATú˜ìb „žKúàƒÂ~§ßmwH/wíôÔ µ S6@cÙ šÈZ¬º¼eM–~ß@r2’I‰p éa[&yâ@ Už#2’šFf!qÚ9œf‰ÍÊ»èÐÎlà ï„%U’# Í`M»¯ýõ<Žç¢’HßìÔ ™å¥²$/!¸D¾âz²Ô‡Ä L—š@‡"Fh”Å}WÝ‘¡kÎU§xµèÐ3äKÈ'“¨ÁÇÚSLÄøjz½«•¾VîkF‚„YóçMwxì->ˆx UXpà ¤ô¼°¢6ò1i›íd›|§Ñ,Ù#æÔ“…!—Œ~¯>I. \tšôÐE ‹,† ÎXqÎ+Ì:ss3÷ã‡ÆW Ã¥Õ’ÐÉ àŠ‰¯ø¢%…dÓ4Û®Ô*j D…á¢Ì=4†’<æÊäX+ƒúUËJ‰è·bh9bl‚Q’HÅŠ—‰‚† q\œ8àfË~©nX´–¦Ø¢RÍ¢gñ#¶o†<"FÓ>«’6ˆÉ†´E\Q S?Šá|ȘA;)FÅÌ çÏ<åÊLxêäO|G8%KO-‚ø¥™Ò ÈŒ^H©ßRš´Jw–˜TA+@¹”šDL¢‹‹ËÝþëÂÒ}Pa5—»ˆx˜RÒ+::P[,èaÕ![°°œâ*Š U7ŠèøºNŒÁGH‘~=:8Š0Ã(UIÊÈ Á3y‡HþI"|¥ ,^¤‘Uå‡#fEîœãÞâ¢M>Mª$DÛzs_4 ªF$i Ë0_©öMTö9îÈ(‹¿…¡&£¢®ÑÒ—Q j€ñé5Dm¥S¦ Æ'£ÓHP,Œ€ŒczÃ#ìŸ÷@ïúJ+¿ÇYƒõ²[^ HÝõ„Ë܈3ìÕ¥ôÁ õ¼O ÅõXª2ý^%YìÌŠ×Þœ¥[70&kFÀÓ+^ѹÌûü›ž£˜† ÀK˜fÙè©Âˆ02â ͆ݡaN3Ê: cÜ·ãD35u¼Ï ÙŽ}? Eúê¼"¹JS°E؉ŒzûSU£n±.1Ã6´âh‹/Ú£vQ°ÑÐ/Ÿom+éºEòZ1}ÿ7㘒òÈ.ŠÌÁוPž ~ZTd£IvN‹ôž“¾xªOOøî)y†Þ‰”htÀ«Ç‡e#í˜Gæ‚çÚKôø <4ñÀ¦_úÝåþ…Út½Oï2×VÈ ê9Ž,ºŽÛUC³¨¾³¬߃ IDAT—#:¦Ý c"¾¬‘©iïŠ+q¬pnH—ѰCÇäDé x¡/ º+›f_B?\ƪF„§Ñ§$!V˜ðþˆ'J¤pcÄ¢#Y$‹*IéLbáÊß’>ã þ,6ÈËž£+Ñ>‡uyŸEí‘ÓÉ‚GäY2]­h50¾þ¸¡U•*6¯¢¥ -‚è’;LÊJ@ß”c:VÜ”Þiz~ý+i¹c3ûbåÕ Ú˜!:Á¨WôŠn,çó„.ÞÏ1`ºu‰‚^-È3 Xw‹Î,(r€2WÆ ¢ü(9ßÔ‚d…|ˤ)“šâ‹££²6Cæ GxEIÄDѬPªè]Tªp1Røß é˜H,y!ä¼õªe²~hñigôŒ­¸’Á‘m³EÕT„L>»McÀ»†©A¢t­ E—¡ Ú‹.p=D †YGù•(£¯Ò»‘c=,EâÉpmô­ù”ã^o0ñÿÊäï3pà$EæÛ óý6C" å<½ ³ÇmÎ íååþ ±Á•SÏ";‹Ä…‹ô01Àª^±PYM©!™M¤ÏfÑ•—x¡‰õ¢`bYŸ¢ú~Ñá=…¥•’žÌdÈ1À¢“Ò7B WRé=z5D$ÅS‘+ããf‘+q*àˆ„@úæ$©etbR#ÒÖ½HãÂz…IæHж/‘z¬;-ù‹£„ËLŽE¤ŽÆW]P/DF“]ãCItÁœ7—x>"¿ ‚ˆæyÄ÷$Ô­ä¶[DE^Þ®Nfm¢îz\â‡TF±Á*!‹P@Ãaƒ  @&pç]uÙÚ]7˜+8W ¤„ –á H¡)úÎe²ssc#‘¡‘&[¢Ê2†¤I&*èb¡L£ó—¥¤BÄO2ºä…cC'ñ¢kòpÆ͈‘" ¨Ÿµ¯ä*%Íç«V§Jœ-LͰÅ*9ùQÎÆ•Ý2d‘+’·#I!`…7éѽäËtuеMj³ 8Ät0N$²4avYbuf扢ŸTÂçÄ OyZ:­3>ˆbª~!€Y šHaïu@æžÙ,1ûYJㄘ°;B¾x0Øë,'ìtûý®¾Ü5º*È@˜5.š†‰ެK'\²¡áîE²ñ Ó°`Cæ îI{£.%4–û5Ïý8ð%I %Ž­X30‰›ð"àYV€¸B×uÅ6ÅCÃÒ(’ kôe3™cÁÒâšäšÑJ“(zs öy<›DÅÁˆ…ðô¯TºrŒÚáž/[`|:yKÁ³u0¾A<'²æ¢’ƒ h›ä79`ùUÄ ´üz3‰I:kϦ¥(f†ÃcEp=Ž­å/’Ëæ1,°ôƒ”¶ œÇ÷­L"h¢9(:£‡‰ŠcWº¨ª¦vyÔH$ôú¤+²yQA¦©’½1+t!ÞÔT" z¢}þ[_ÿtmßb¾µ;@þ–ß[\ì§M #nÓëÀowØ”–‘(?¸¼ŒÛ~·ËÊ]„)´³Qüˆh ÖnÈ‹‘BgiVrìà£Id–I#‡bÇ+b˜$<êêM&ì¥e%a,­AKßR©RA3è$ ¥8!R‰ EøU¶ ‰ÜÌ?\’y‰0GŠAjW ïs=Bêu„!õ›D^F¢ZÜ%:ý.ù ‹&‰¾y¨ðåFü«Piôç»_%‹å»é…±Y”ž*¢÷–çÒ|-¿e5M¤·vÝàm;‰\nd¸H>·HŠÁ 3.’å u„¼k˜›CoYz䂘#uæ\"‚Nq„‹œP w•i·;‹m§†»fáê…Î2‰ö~¿Ó[¶b++Ä»†Ñ]F/}…8"ÑC£«kúEXÅ+@Ò…f³>Ø6z²ëfl‰jâûô¬UEâV-!7]"§!Hòž²5µ‘0+%9 #ÁG„q8W95P´HÕ.´ôðßÀôx¬\bóUQÝG‚ë `å0’Ȳ./ðHä¼ä^r±hÒgëk= }eÁ!oÓT„ÇM+ï‰äBßœ{èÇsco^-ºîu+%ìh[V0Zm¼Ú"÷­š9K7]h„@6ì wºä2kX,~õ²²ˆ ®¢z®ç­#7}©XÚ£Œƒ)’áâÐ0k"U±Ækß'qÆf‰x\•¥6W*Uâ<ãtm]å‰|%é9õïsÛí£ßt÷ýü¿rK?,ÊW²©¹%VĈhÈöµ¡;ˆm”ø%Üë,n³Õ ¤Rw:Ë]‚`·ÛAå-dq-//-¡-ç…ìËèöº´++Dõ¥å•,³“ö2¹fb)–‘ºj,\4â•ГA19OáÑ7Xë@Ó¨œ™Ð ¹Iã†Yâ1»àz‡ã9d‹›ò‘ìÏ–Ÿ@Ï (Šú€Š®ï Xü@MS­{²tY¸DÌàÄ;oŽA 0Æ' ºâz\@ O!`;üÐØadxòäŠÓõß…ÂÜÙ9Võñ*ÈCÝn×%å,†7ªe¢Ùj’Ã,IÁðÛ„$ :Að¸žçÆ Iy¼é">%4ECï5W(ò˜Ü’23†èãÓ¥©TT^Öá²F‡Á Q+Ð%D2;ÔÐH‹44}G’¹Â¿ €û“ýIòQ€J’ÛoØOf#ù7~••P`28]ĉXu;]EÌŠjµñýENÿ<‚‡ËKË Š,¿Ûéh{D {h Ûîh ‹0§mT(쮬XË+&4ÛY\ÖsÙ‹¹Üál¤Ø5,“¨Óre=hMÓl 9>k˜˜Ò%Sȉe*vM#¿Œ¥R×,C”P#-êp¤îü ÇQ6t ó’Zš…(D=õ² fˆEtÑ>²2hIÅ(E¬ÅZ1燂R8ŒPBÄZ|.Y?ÍA”ý,ŽÍ‘p˜#dþææŠî¥âCcoÎͱÑËW眵à¬_f­– ¶¬:lR8™ë’ï³R’“ñc@ÍPŠs®ïòBs˜2á™P‰D$[pœÎeÈ„Gåä[òH2¤¯©FôV É†¡K#ÁPÃDbù“㜘áwÏéýyÄrPް߀ !»ܰ‡ûÏÞ~Ã훋 –å%e‰ ‡‹lJŽ„C_ Âö }¡×ä2ÌC?//¶—É.Ã+³8!™N²…‹lIŸÜs¯³€ÒèH¨éw;]}¡¿h.-,þvoa¾ØÎÖá– ]¨hŠÆ…º™…§¶sdôÌ$â„’Aê¡D~™©hÒ«݈òÚ2åDâ9'©)‘ìç"¡Ä ga¥“¢$=MÔô¥D‹6yŸG²pÄì IÒ%AùÌ[d”.¡€TáÍMŠÎPÁ%¼A4°m…CW c$%Ðñ€ÙXqs)”ŒCÕ³¹1Ð* ÉtÎSÍ_JÉùúTªœ,û‚QSY-=-è¾vÒ—ôXR>ä}Îs×á¥\W¨QH2%”´·¤XH0ÑMRík“fU¸òO YI2Rˆ'ãXQôŠY[&jº¼Ä_öÁ9 ïs«Àão¥î§Ûýx* ÷ãa%ýsç3ìuÜÜç–~Xé)aFIgç™0T„£EH!ÂùþyBfé[H·p5‰Ö ì?t‘Ð…°ÍyæÞa-=žïö—–ûç{Ý¥ßn÷{‹P)ZŠû[Ú¸Ž°ê"€“Å„k¡4$ŒãRb™*:,fíÚrUŽÑRÍ´Í +Tr?äp]Ž÷0Œ¥1˜Ió©jäŽ/ ’ÂKûÐØž´±Ê*Â!kC ㇩ÌKWQ¬§0 sˆbf„²‡Æ†nÆÓŇ’Ž/|Ì›ñ$| h?ôÐìHqιJ¾û¡9˜ÇkäB ôŒ,â«‚˜”É÷¿JŸrJ7'Í sjÒ4êzU­$šŠ6`$¿Æ2_O¹‘Y7jUã™Kzž.žˆŒQ`!®”b¬§ˆH1!j ]ºüÕÐâXNX1mÖ–ãèÓ×IÏitŸÛøþññh?Ýé!ÝÇF éO´û{ÇŸôæþ¶ôà k¾8­HK=yqAø`¨¥öbžPxþË¢ÔÅÊê»±°ô‚ÕmPD–Ý€ŸùÛî¶o¡‡iä¥~¯}¾·Hv°ýºÑÇtÊEFs63¦‘Î+³ šlä}Y²TÒX:ò¤^]½Ò%™¬Ë‰jaa~¢H‘DTUQR¶®š¥¥"aÙX>B®t–Ä˲·O}„ô|¶jËeÈøt9Ö\Õ ÎuÑàáâð¹ËŒ0BŒ.»d& ‡‹èõëÁ„/) Q]eP\äóñP³äÀÙC²mΈÇÓ;bU¯èµq“ –,%;G·Û%U¯êZ mzT3)©ô­:®é7 U¥×Õ8‰Yº¤élWR+&JHP蕾*l#’"F¸Æ¡˜l&C?8§ñ}nµýéïþZ è~ú =¼ý"ýÞñ7ûïswé‡}Jú½ü7–ÞÑ“$xãÅ=›¶*ä%˜£[ZZJ§Pèïü`¥³´°ÔYb K×y.,²Ù=QLh›Õç‚m_\^AqÅ4W¬ æDð¸¡"—¾zÓvF½‰l¬Ö5-KE2žÙOlÄtHœô+3xÒ ‹­‚óRYð;-­¡€?ÄÉ J9iaß¹¾ù¯ýæoÏ¿ü Óäþ¶ý¤A’‰d?ýìg‚d"<ƒWð;A7ô»ûL’ì¾ç¾6|Øoó×}Èôöõ¯ã›/Lí;ûÒ‹ß~á7;ÇX¾¯mr2ýƒ{“åÉÁýrú0}u÷NúL¹|û=÷³€ÿ[œ•ÎNí{áÅ—_~ñ7{ù•W^>ûõʧc{ž>ìK/ýºÙ¿Çömð;ÿ»lg¿>þéØžÿu©¯í倯¼üï³½ò€öôqÇ=ûõê§c{þÁ‡ÿ8ãøòÙçÿ=¶³/çås`WÜoÞÛ¸/‚ˆÝ×GúõŒûk?¾÷<îK~íðÇú¯þÌÃÃßÁÏg†zø0ý;tèÐÁ‡:x×v`ÿ¿¶Ñ«n¿õàÞýç_þ΋/|í“ßÁ§sÜñrÇ$8HôÆôÚ£R)#s— ŽËìv°á^úþ$ÁÿÜMâR\°ãîûÄ7Œ{v€‡þë!àÇ q°‡éçá!vÈo;ÜÀñÜà}‡˜ýÛÝî¢îÀ<~‘O~ŸÎqËq¢_/ú—§ÊK¥x÷Ñí-DW_4˜Æ è&îþ<‰ c »fùÁŽû`øÂ€|¸Â‡vïàß!ºÞ;;Ì8À»9Ÿ?˜ivµß>ìåÝû鹿¤oøð|:ÇM"¬Áú`t-÷ÓI` ~ú$ýñq‡=b™é­7xËXÙ#ö¿ü(y°ã>X¦Ç—ÜðÃ{wàj>dÛ=¬éa<ÈŸÝÿu>wm鹯üŽGlNÓ)¦uÇÓn:xÈjžJÛkÓ÷ `וÊÝ4‰-m8[ðÂøÁŽû`È ¹áƒ‡öîÐÑ>ô~ªÃ*»ŠÙż·å_~áx;ø 7)>ª3¥æ†Ùf§XRö—&Ö“ÔM_%‰53ž;ø?¬Š‹w9?Šì¸€·/î½Ê?¸ýø®sp\ðv©Qjöî§_äþvp÷£»wðé7)…¾»ë±2`kr½=Èà©€yL¼+K¤(*IÈæÀ?¦4@9±;ø`Æ}°$'Cç0ó4ƒ;¤õá1ÝÓ‡˜:ô!6€àw0ÿüÁ|z°|ðåÝm`QîcwžÍîàÓ9î@Á pxƒÓ`  "R§e’®!3c y»H¡ÿê;Îmø€Æ½ e³ÙàAvdÙaݽÃïÃì°?|0=Ô³sÞ?x'%ÊŸ}îÕ=Í·ÇÃÜÞÞaïgïàYØÁ§sÜ2ÅañÙM†~ ›z¼Ûzp'‘_Œâ˜Á& ©THRÜʃ÷þñ÷Òêö‡"ðNîÚŸr:ŒÿxÏ?|×MæÁwøVÀèHàmŠó>*tûáà„ÞÓ>ŒÓ¿ÿá§sÜ$=w ~ªV÷¼d d+ó¤p“%¿XtÃ8L_ßcv^в;€ò Æ½oüÝ\Ÿ]> w°sôûôf†?à2î]»{Ç}p,óþço¼þ:@xöÃØöû¶ô‹ÜÓ>Ööé@qn»ÃP0X¬ôé0*¨|×é/CÉ®©ÚEŒK@)?Øq÷õáÛ¯ÆßöÆÚììõyÃlwŽ?Úëí÷¤Þè‡ðƒÌ‡\àÌîÈÿÏþüû¯¿ö§Áo|ìÿñvpGLí7tÜ$ RK5p–àj)`nûJ†Ú"ß%OêQi/hG/î…ë<²T^˜<Øqw5>^NÒP6ÞˆUB^Dµ_ÀltsuãÌÆìÕw>ø†;x´÷èñãG;í£ßo÷ÈïÒ;¶;£.ù7þü Âàw_#¾öÝ?Îï¿~œÜÛöé·Èïà‘åÇ:ýãÇÛG ·Ì |ÿQ;°w“Ï¿öúöƒï}ï{ßýÞ`žž;ó±üGïàþNè§mÜ$‰\çNKÅB&»@x($I9Š˜#Ç%¥`0e±k¯vr§|0ãð75UC¾N³Í°¢lRÏ+•?Ôþnl¬!¼zýú™÷¿ãNvÿÝ?ëë?¶Ôï÷z<"ïŒììôF~<8ØCïqÿh'3Dðûî¿öƒ7^ÿîŸþÉ~€øÚŸÜ?j÷~N?ã& Úyú,R’JÎAؾr`¥H Å"èZ¸Åó`/‚rP¼»ø`ÆM5eÛSl«ONLÔjôS©ÔƃêxõC˜mnn=·ýÕ­õÙÙ3ëW7Þoïà£íGþËòQrÂÇÚ>Ö“å^?­ÒÄþøÐÐpïh§ÓÛé}¿óXo‡Ë÷»ùtèžXý§s\ÅÙŠ'PüTž²)µ¢ãz)NB¯Ç‹ÃÁ4ïîöa|㦪Õë ¿ZÈ ,áx¥:ÕjÀìöµòììÛ³oŸyçÌìì;Ûwk•;øøcïœ?ÞýNï ³ƒr7¬à£K¾·#öv:uÚÇpóX»C7ùüŸãûßûÓ?yýûùüëßûÞ=‰±:·üá{=¡Ÿ¶q (µ T›ƒW$˜„äþw×v±—‹NÒU Ò4‚_ À2îž´íf³‘AlSæT‰¬á˜½uksó:yßÕ·¯Ÿ9ó<ðÌÛwÁ»TðÑÞyº¢¿·Óéí\í½Çzä~–Út¹ý~§ß9ºÔ>Ú~ýØÒë ½Þ{ùü÷¾ûÝïç™ ¾§0ÌÇÝÁ½žÐOÛ¸{@`$ÍYÁƒ(&‰ÒLé¼dl{F†Ë ‘¶ÁÝ@¹[?˜qSPM4›(JÙÄ–šÂjµ6Q®MÖÞÉf·om’ó]?³~æêFHVð:Á«w"ðNžß9ÿÚÎŽ0¿³Ð9zÌ<Ö^~ô±Ç?~ìñGz‹ÿW›Žòn”†îöÙÊRáCÞî1½ øñwp¯@ùt»0 eO¬µÜ;lX˜Öma» ¿»3¶©¥º€hÜlø †=²€t¯YKª“eÔØß³ƒÙæ­[Û7‰’~þí«³gÞž¥ÛÙëoÏf?€¯íÈ ó;äa޼¾xôñö½îcź{ù³íþÑöí(ÍÑcGX-’Ñ»Žé=ðãï ÿÑCÞ׸÷”5nŒ 0Îón¤dp‘:uažR#µfÈ~yP±IénWI@Ù±xP々…çVZ+!µƒÌNL4Ç«“A4¾!ÿûέw66ž› 7ÎÌnœyûúÕÙU⃫k·mà].˜õÊKëÌÓUÝ;ü‘Ç?Û9ÊÿVïxïèÒí(ÍñGVé_¸BÛϯìß?t(eß÷à‚?Þ~«½“?”¿½ƒOp\PùõKöÈwwg,n%ŠK,:7ð’wXª MjqŠn˜”Ká rœJW§èïZª5nŠ+ûîù´h‡mÙM2„ãQ’ L á‚òKot?v;Jó8ý½rågÿãÊÿüÙOÿéJqaòü·>ò°ïø³ƒÞ#½àÁ÷vwð Ž»ðÞÿã&¥ðöŒÅžN ‚Û@ dF,A PJq¸;qá¿ß? q¯›˜œ¨V*e´· }äï‡ìýõf³Z«G¥jy"›À[7n^¿±¹¹±ýÎì,xàUÂáZx†,á™=-|W2Âù‘ãǺ½%ãñök;"ú'ï<Þý­ÞÑ…ß>ßû½(Íñn÷H›à÷W~öW~þÓŸvv^wv¸Ñü7?ƒIø±ƒ^ÿHo'ŸÉÎÝÝÁ¿&2ïmÜÞÿ±°3ÿ`\Ý]ж0 ãRw%EËîûÍs n)‰îJ_PÊvÜ4 mNÕ§&Ó`·,"•¦lsr¯LVËYÆoÅõ››[åÙ­çÞÙX=óΙ-ò¿g¼¾7)r'n„ßÙéÿà5ž$9ÞùG{KG{;D°wŽ÷ìñ#ËËÝßùì£Çû;;WÌü•ÿùÿü,g™¹+ä}zâ{;ùç>€?Üui¹ƒGzÇûGvò#ùãPçl;ÃuB?ö¸Dtÿ#ŒË,Õ®T¸Ë8ñÁæƒÔx…颎] ¤òÜbL0 nªXÀ0.)à:ëÇÄâÐÐ! &F&Êa9ª6'+ã~¹VK_®×ËÛÛñúÖ LÏ®‘éC4f•ðGùí°—åwz;ó;ç{A$üh‡àHoá(×6ýþh‡ºdë=rå~ñWþñ¿]¹yãgÿx¥:wvøü ™Õïz¯§§_ä£wp^8Ò~$Ÿ·d+ŸovÀïüê|üq!Üw=vüÈ';.}Þ¥{—‰…ÛŽ’Ž2Àƒ=³”==иEX´ÀßË`¹ÓR=¨q÷eËSS“““ÌöUÇÇaúÊ¥8 ݨV)ÛSS>¹a0ûʹï¼|c{{ûíÏýé¿gά<.H–ðÌZö°ÇqÒÎyyç5þ|ùã,œ?”; ØŽ´k_ùû¿ÿû_4~¶þÎZ«õGç¿GïÞÉ“ç†öø|ÀîÌ–~‘ÞÁ£½ö‘vþ°uÐÚŸov@úWîàÆÍëdV;GzŸð¸GÚõïqÜ4i``§R´„ jþmv¶g©ö\g ßqR@¡ÇÙS«jÜ}Ùqs0 GÛ$‚0“˜«%•‰Záé°69•º`H­ë·6¢Í­çn]ÝZß„a\Û5æ„ïàgÿËQ.#ˆý^oäùÛþxgžΣ=:æ(;wt©×9Ún_ùÅ?üô畉Æz=ùÇŸÃj.ôzùç¹!Ãøà¤ýÞÌAúE>zí£ýÇò¢eò¦>’ì@~ïWïàžÆ%¢¨è‘OxÜÏ>þÙ£÷6.Ê kt?ZB.µO~0¨wíÜ ïw¼ÔV¥@ î ?¨q1 H?5ÌÃU FÐÖ«5êãÁIe²> ø›7nݼ±qcëí­¯•7¾onΞøfgW¯¾³¶qæÚ ÆÜ5×>ú»ý£s‰Bï¶?–éÚ?¿Ó¤ßù&½×ééÿùOÿéæVþÖf5ÿ³+‡G€ßê‘oÚøQwmÃ;KDÒ-Û4Ìô‹|Œ{ÿÚh†ØÎã=6]<Ïÿâï~ó—ïlÿ²µõ‹6&y¤—ÿæÎÎñ%:5óǽwèáC‡Ù:žöÔ¾n™ô1­Ý©­Úÿ^>sãz~dD¸á<Û¹¶_¹ƒ™, IDAT=nþ…ç¾ñ­oçÏæÿàôt6ûÉû^þÈg÷ÑÇáp´?æ¸årÄÔêÞ*µˆ Uäû{Yð™áž’M1ÞŽÚR\NçÎîpÁhÜ}Y2wé$ÝNÁ“'®TÆ+ QÁ4G¡Ù„I‡¼òÊKÍs·Î½üâ‹ç¶¶^|q<Šn$2ˆ/m½t#û> (èßäAžÎmÜ;Þé<Ò'§óZƒ²éâÞÎ/þÇ•í­›ï¼³¹uë;<ß#<$=JoÛ¸†¯yø¯{z_gS7h Ú7wõ.ckóZšæg;è<ú«wðqÇe£½0{îÊÙüç¾øõ3_ù¤Æ=ß;ÖnÿÙ£>þÙþ£»ä£Ç-'ÑWƒ­ñKe¤¹û·MTì…ê^3÷L¢vaBHajõKõ ÆÝ—mÖ§vsëdúÒ0L³Ñ¨Õ&›w- ÉÖ õW^ÉÞzéfýÖKßyéÖw^Ú®¿øâ+Ùòvý¥_|i;[Ñ_^Rxù5©}lé¶?&æ}äÑ•~¯?¿#÷{lºxáHûÊ­ÖöÌÖ_´>²@Œ§¡—ÉðÜ{œÀ“@ä?óðáÿ[6úG+  o˜†18¡½ƒ•ü/·ìíµ[ÛÛ[ë×7óGÈ ÿÿì}i{Ç•®?Ã7,½¯([I¸J Ú™És‡²$Ë’;÷E” '²ck·l+ÏÌLÆrl-í$vfl-@r¼FûF8¶(îâ˜dÆ?À¾ßsª»Á$“ˆsÇÏ“" ‚ øV³ûí÷,uªjC,wËÇGÝ,Eº_:Lt<ð‡†›Tú¶nÙœpNÈl\²®M'Zß«ª¢¼¼ÌÊ”Û)’ò²é\qù,/Èñ8D¨A«–KçC+‹‹Ú LouxN-–N9x ¹é¯Ã“WtýüY×QþæFÁ\šá#Í[2èØcéw!-Ó{ÿµ)@ºñ͘1>j€ywØPM3¾¡qæ§È~¸:¿ôx}x>r»ÝžodÑÚ)Yîû›/Ðö©–î€L«£ÚÈøÈØý â¿G%OM5æî`Ù¸é~ÔÀÔåO½-ŠÞûppûŸêݘ’‚»hY¸~ÑMæá‚a,£E¡ôÊ—–U@øZnœÍJ—gS%Ù˜Á2˜ÀÇZΈVW ÷‘œâœ§ÓO¤"ýxD×g¼6(ަV„»Zdù4–[mÓÛç7ebç<(tûp¸xCÌ0&FîM÷Gï²¢˜éSÏl‰“ýgp߸ÝÒÌ ¯ÇǦe1ƒ+úÃéæUº‡ ä!‹wàß@â¸ÃðøWú$8šä"xƒþGýœÊÝÁrpáÀãÈ{¼š"ä±h4 ÞØû0pA#!Ø—NöamÖ©9¸~ÁGÈ<\Z6e“ÂϪ¬N9™9š=)wäiš4eŽ¿†U|ÖˆEpeqçsìom³|@ÊlÎcÖË?`Y†î¹Ì²±·ðÜŸãÀü|óà„aLŽ ß½o@ÓL]ÑÌm›·4‚Ú_2°ÎJ¾à>cÈAÛ÷Y´òü±—ȹódjJ×Çþ82zo½A à0ÉÝÁ2pœ8—~pŽÄ–Ù£¹‘Ö®) ‚Ï7+½B¸óåšñð7°È[èu{¼²(Š ƒ¬×ãsîñâƒÇÎ9|y£ÆäèÈÄ—#ã÷‡G'MÓË ’¾rÐLCüLrË¦ØÆMiQÆ>Õlò¥ÏÚ;GqÒ‹tàý;,ǧ¦&§ÆGî~92<:®=Z Låî`I\Ë‚vqä|!Ý»wïjíÜÙñ#ŒB6¦ÿvÜ4Åe6¤3½çíDt—øåÃÇ$⟇‹Ó'K²Fϱ”VXPn›Åi¢袥ÀLþà“â5•XDZ‚Å|+‹»0§¦§ßRôy8µnOš—‡Ë,ëeáÆçå½`á–Çkà5Fï ŒOÜ7}È@åÕƒæ¹ôF²?þäS7oèí£{‹ÑªY;ù"Ë’¬fÚYŸ*gäùã¡ò,ð$DÀ_|9>qwìþ›©ë×c¹;X× úîK³VÛÓÓ±«cç.p4Ïaþä¡á2éXú©'¼¦q‰F4æØq…ÌÇÅ„±,ÊŠ¡P¹3G#K;WG9RÄŠ–òižXáDIq©5ÑhÚ\!ܹœÊRo&xi2ha|pŽ9VWöÙ24pqâµnpÌǰiQÇ'›œÆ-Õá;ç¹74 &<³ “)`|«Í1Î;C²¾´µU"îî©Jj6ù‚×VÖTA¶}ÀÅ: * ¯]G¤ããcÃ÷F «‰)/,ƒ¥qO°^`ËøŠFïijêÒu=J".:Ñ …àzœãõë’Jüš_•p X2‰Rꥤ¢&äDT©lÏ̶Šå%kÀ¬–«€+U¡`…Á_JJ+€(3”j¥p牚#l% Æ3jÝàÚcÁó/Òä4miž°‹#Sc#_ N˜«L“3 ¿—yÃKösè`‹²¢dź†vòEÎÀ/ÉN5Ìb¨Dñ‡«ë‰r||tèHàÄø”a` —»ƒ%q9È/z˜hwt?ð¹.Ýíq?D\̱»°”0‹ëǹ‰ß/+ЃN„B/™…‹“tKíµ3Ö–VÔ§‰‚ÕóðPæŒg””WàŒÇ×–‚Áȵ™6‹*pN ®,î2Xö¶Ù‰h¸¹­Ü‹Y·—žb¸÷á”ã(fb‰(81i€Þ™4sµ9eø’æ0)ˆ ?¼Œ`qeмlòãjxIr|ÀÅ: pÁÜáµuÄw|£Éñ‰ã¥t€ÁiΖÄåÓàÄñð,ÚÞÖ}ùx÷ÎŽ(ñþ’yh¸øú Ë)d,\¿ß¯éª*Èóà« ^ÝG, Ìâ†pq4{ŽxqY°ºÂ©×³‰b _PžW€;VZ‚»†¯-Áê*º´•µ·G%ÖZÍ^#zepW–€ôŒÒÜ˹áÆû½l"½ß3¼h¤G€'GîÝ5eS4ÇÇý<1TãKãî!ƒ»'¢O0Ý`'_A–…ŒœUÀÜâ“ U¿¾¾ºÎÏ?>Šü»<]Ä 'åê`)\˜Ÿ<¯w´ìljÛóRwKÛ¡ÎÁCÂ¥¢ …H™{ ˆ¸³=¸~À@I÷K>Vðq¹ŠÈL\dZëÒX¡"àŒFd‰°K¤Š!R¥z8ƒüñb0šAºý‘µ’hö¼àÁ]YÚFndÖëvc¦ l &§ÑÕfÁÂmLŒ ‚Æäè½áqSP̱Ñ1Ã5ø2F ÐÆhqÁÐ8Éd`Mœ3’³¢c¼‘§{×?Vç÷ÊÇOLN?þxÄKúúdA”ru°.rÍ¥ÞÝÖ´ý‡mÑŸï8þòîΨª<\¸w‰,÷<¦ýðOøu7¸'À7¿Ä <çõ5ÖD27h)U-û,¢”—Í2•ÓDY»&€ãkÖ‚UT¯Ö””UBüZSSEË—ËJ‹g˜àÂ]YÊ>oö§Žµ—uÛÉiLÍ ;ù´1~otÜ0¦&ÇGÆL7§˜ÃÃãÆÈ„aŒ#Cw ](%cY\ œ|‘3‚$Šj6úËÝ™š×e¬¯©'n½ð8´pƒ_$J,.ȹ:X 7-¥3`(Óú®öæç~ØÚ ž‡P‡Lã-¢XÎÍ–ØE{V ê P”S¢Õ)3Ù-Y»æqhkÖÓÅ^æ!+»,N-²Xôâ<%*§%†º N8Íey­ä4žsð€¼Ö˜½™ºo2²y|ê>²qdhü>H Ž,ÊÔâbJMQhò^”éò ¶ Æd‘] ‚u_Þ!ºO ôÉ…¤v½_ôIÕ´þ\,…Ë ]Ò‚ÞÕ²£¥kWS3¹ñÙ Òµ#ªªÂ_‹k± ȇÙE–$Ìá !ЍK*ľ*§sºÂ1D“}EŒHˆ.È2k)­;F¢ËðÀ)º í¾­]SŒzåŽR•Z\YKUÊš½6W>î²è÷ÙÅ¿’€ò)pÀ¥ŒÀ»¸ÇYšê§ WŸyY‡a‰‘Ñq àäˆéõæä$º€S#÷†Ç&DÁŠ–P‹+ Ï§R‹&czM= ?Yÿ\@Q´G¯fw@ëîWÃ#“„0h`CCCícáBÙ?nh*Õäè`)\&c8½³yûö¶]Ý-M䯇7ÈîQÌ;ÿ5¸À=ZŠI¥R’DMÔ4ÐM`"8z*!^^Ujª$ˆ¬NT…“erëö*OÈÌj‹(x™±f¥Ü*Ê›Îו;Y9xÃÚÊÎì°gŒÛ‹·”:[ÊÌ,›Z)Ü¥Ù§_¾xñ³ùËæ¬œI@xJ汋O[’O*öI.zñ0>cbl|L°irD1'GǾû Žà}ƒìW2Ö`g -nBƺ&&_UÂ`¡ãS hù耰ñÃ#c„pÄ«¬o”7„ Î?…‡¹;X ×òÛôΦg[:vwõ´u‘×ÈžnBTõ¯Á-ÃÉRŠÀJÀFEÖd– A$¢_è<0Qõq‘­ªä'î+7\Dî:¸4]bÍÿF¢);œ:=‡(»¬Š®š ì•ijë§Ù›.̪\!Ü¥è÷áeàŸÿÊ\–é’ij>—«ÀîÈ"<†Rë%¦}Š"¢w„UUBŽ>p vC÷†FÆ –”“u£÷ÆïAž„°á¾¡’—%tÞ镤Õ¦3hòÅ*D nÖ?¢˜¹: ¼åHÁ%–ü>Òð¸hð)…*( æçrv°.D¡,§ïjknéÚ½«­½{·¾PS2Ê_K€\ªw”"0Œ,‚»Ç‹"Çò¼ÄÉ~à„!§ù ' ÁîýºL\Wo¬Ò8  ê˜J›(h ÁTVXÂd–•;rUf×U#S*ÎL#$еˆ}eæHÈ á.ĺôûðòµËýó¨_ðÓæÁ‡ ³9“€ùLæ £¦9ÓapúEp‹RÐ[Qñ)ÇgÞÊdDÇdžF' #Ÿ¼ Ô»?99úDhH4žD†ÖIµŠQU¥ßÊ­9 ¨åì¨'òy<X®†àã`ƒ!xôCèÞUΖÂѽÐ;ÛÛº£=?njn'/‘žBÇåLî_ó{xW±‚&»ep%…žÇO ø)0¼¦ë!°.Ê:¢¢>èò¥Ê4QÖ¢ë:D UØž™$LkU­“/.©°–ï£Úå,#i¯ã2«"zep™gHõÅ/_üð²ÿÚeÿLàÉç½.ŒÁ"<­*¢@+¢ánÅhÄŒÊ3à]Ë>–÷ÊE®#0p|txljôž‘ ûp .Ù/¡ëN¸'ãe¤ÉêS)øŠ}Asv0Óx¬6ÐðbÃc ‚è›0cïa’«ƒ¥pE1#’®ööîèžžöÖçvvì"ÑÝmdÁÄXî_W~i2æ”…èŠ(º_UE|@NôªV\"3nx™ˆ<ÍFË"h"!=u«À?K‹¬1 0•Õ¸D³Õè ¢i¶8³‹Ö—„°Ò%»íViöaî¼àÁ}D¿ø‡?üáã‹ëÑ?vÙ!‡~ù2’ï|Í B, ”|ðXÄËêiIfÙøj&œF8㺠0L©$y ½Ÿ*ÊÁÄ‚111>9ö•1f¬¯Z\WUOÔ$\+U 5«ø¯¥fÉ º}tj9Ž­d'ãä‡îO5ÁŠÒÐcµ/5¼þúëDñOM4÷’‡IŽ–Â…H[{s{twOW{[G!Q`b\Vrø¸ºHtUW%Þ!𪠂VDye^y/ñ+*a™óx‘©¢ ‹’(¡ì):#êd®µ”nm%*UU0[£bÑe6Q,2TU©L9Û¹-¬€+ƒûˆþÉejM?µY÷±ßõ)åòïC‹€—çÇ çñod’‹ð4¸â²ÈÊIE¯Kd„¢"¶ü?0O>œ)ÖGðKã®aèvþKÁÔ~• ±®½x+HÚ,ëiÂ[ísò€¹; ãã£RO‘ŠÀÚµåµëÖýìÅ_oØ»×PŸ& w°.8éêlnŠƒ~(}dw{Ó¢j?Í£ä:ðù¸º"ü­,iX8ÃièóV‰£™¿®°Œ[Õˆ_ÖOápp‰> · 7ë(µCR õÔÎúUY[‰­x-Ë€ã£ef +… üp@@Ê@ à‡^¤ \€€gñOÏ ˆ“‘Xî}\ƒUÑUZŒæ“eÊEYàÊ> ò••Ö$ưñ|W£©pg›Xg'÷ fùPðÕ™5›|Q猭æîplt|bŠàÝYRR(¯8ü"4²7hhªñÊ‹dá–ÂŶïlÙsìСý‡©Ï°»ýÇÏEÉÎí$÷ÏÇÕU‡HË ™ç½XÃFVK+jš(ª0W=>‰^Õ‘Ï# â†BåÎRº¥kÊ‚U6Q²•UªRµ6TûZNï§e+ÕœmV 8Í@ýâMpøn!©ZœÏ¿Gô§&ؽ‹…'Ì3 pN/ܪgÐ)œ HL¹”.óøJ«ÜB‰©ëÄ7& 2.žÉóœÉ~9CÍ—Lc^t¥œä‹:gl5wë ÇÆÇ§PZ«è®å¡êÚš½5?{ ¼ÂW^2î`)\8ðr–tw5ÿ¨cÙG^ †ö~wËÎç¶7õ´Fsø<\¿¬Z@ðëT^àD¿âÇe¸o°Éº¦¿Ê뚟ç}^øYÀ+( ⧇ÌÊ ¢ÌX3-;^1sÆ.è‘/”9K8gs'óò€÷‘iº>Õõ®Üô_ñßúôÒÇ–~t ~ñÉüÿBȇ‡ó‹P”48Û:Í஀ÑÏ(˜ $ÀS¿@ð ÔU0í¢#EM‚TНè/y!öì]]DÄ aÁ±u­Áã°§ì ãÓ3…œé»–I]“:½ˆ}©³±Ì¬‘•ÁE^¦VøòïÿéàGW®ý·.ýÞåG"ÿ>_h‚:õ%4Ág! }€QÕÑ÷«p^‘p®Õ'KB_ááBpRM¸×Iyy=Üùàö€o#š ËòœHˆZ³g’,ˆ"ºõV]TÍ[ÍÝ™‚(däÞ½¯î(ʽÑ0!Á½u5õ5µu¡àë^>²pKá"ŠŒã¤­i{÷ž£ÆQ】æÓ !m­=Ï5Gsø\\M~„ç*æ¢5™HxÇúUQó‹~¿ˆ{~QTeå0Âà+æå‘…qƒ¡DÁAÛ@yÖ[³²uÎJQJˊה£TMÛÊ,QÖ–:u{+…ûeàåË—€À@›€þ[¿ÿÜÅÀß/DÀsÙ<à?.B@.Õ(ùì“ l<-ö)ò)EE^`=8Sƒ@n}I•½!Id‰Â™,ÇŠdP¬z:9‰ƒX²ŠS*M¾Ì[]¤°Ácc£ÃC÷FFAņÃáðÞ½dtlâ8¦fýäY¸ƒ%qEIòÇ Ò±sÇž#@¿ÃOÓÔ¤§©-šûÀçâ‹ Ž…[P×áÿÇ<Œ%` -J'”Qy]‘9Æç…[]PDƵænØDYÀ|‰U,o×ÍOÓëÚ5è­#Yšý^2½ÂJáÚD6} ø1ýác$à¥\(Å(1 sVÌä¹Ê <¥x·£‰ÑÐ[Q¸ü `2Ø2*’JªÊ×ù%p·ÉK$Þô2<Ë+@@̽á}Žßdjldy€®g8{lu‘üëïON€›˜TW©£áÐÞ &u“:8òÓ#$GKâŠ>Ÿ×xÕ0HûsÍ ‡Œý†ï8‰FåÜ>W•8E°4OƒW“ÁÏ$¢D8|¤ ͳ¢Â]«Ï0ˆy®<5®,ؾÚãe!tÖœ¥ ʳqâ;IW ÞZ°Ò"Šc,K)Qæ!÷‘,/bóg O?üðF.^P(Y}ñ‘Ÿ×K÷ ŸL D"H]4eÉ…óçN’M¼½òZb*‚_$Žˆ¦Qîó1^†P>‰±†Àñ^AÂ)ýê™>8ësÆVéÀhh˜ššRàkJÕ‰ð~{90ð_ÚGH®–Ä••"0¼G4´þ°}šàƒc¸5Ķ,\ä„¶@3v!øåÁ“$Þ"·Ç]$a ƒb9‡’ ä%á®^EráR¥*±•ê±’ÊšPvï¢lÍh6ugÛJ$DÈÞÍÈ!Š,ÌVÀÀAÀ?þäF½Y^üøæR0È?œœ·,«ÌgàL¾ñÙûðê`ãYDê4ïÅpªzš/÷I¡¤š˜Ñ­!÷§L¸¹YÙKdÓðñ¼ “§0ÙwJ> v/ò”|Ÿ¤CýsÇVsw`T””5´ªNðsúñãÇ÷ïßèÈÑC/¾´ïÉÝÁR¸à|ùÐ ù¤óGÛ÷¼j#ì³üŒº\\¢ð bH@øôñ a½î¢Âü¼·$p#Ȩ•"¼²À3‚NV¯ö’\¸UAJÊŒ’5Å•5UÎ.ŽPe©âÌBcY´ÆÍJ³E+´ì`ƼàÂ}ÄaàAîn|rq?¼vóÒ@ý‚DõOS}çÙqȬ(ØfKÆ3ðÙ.,ƒµQDÖ-±²¦™ #˜djrrÊ$`XbNA 9¨àhžžÔ)¬®.*ô‚/<8wl5WF°¤¢rAhjWòË~V<>]ê©äî` \¬F”€„ówþèÙ=„EZÞ·l\‰FX ‡ˆø&è,ã-**,,ôà"ªþR€ÛçÜ*a Ü$'®U4€a'HNñ㕵UÖì@Y¹“®ËfOìÚLZEÌÎf2¥¥NÝ^Ù̱à•ÀM@ÿ'?ñ|Ù&àg×>û|Aþ©V)‚.y½J ÿƒ»eú|t°]óã©F[¬R9T5do5S:Nj¦ès3æý±‘1` 7ï×Êiå” „»û Dt0­®<7˃ÐÌ[ÍÕ©)©¬FþS”"íBÅ-áPtpRÎÝÁâ¸xàŠl‡ÁU±~¼‡-$‡ŽöŸ$ËÅXÞ¡ÁëºÈûX™(Ëં…ù… „>Ö ëXŒ '•ÄiµÏ´««Áíƒ[¾¬ÌÇ1Ã0>g t±ЂbÀ¢û‹ãÍS Q¡P*3wKãêªaD÷ìî†Öݳ‡(\Ë2ö< ]ä“%qÕ"·Ï#øuY¦qÞ|Ô?ÜË„…X„aYa:Z’ ë"¢f²èñN/"DµÇÊ‚ H¸*®T¿öñÇéô4kŠšõ Þ f²¢"TcW™Î JÉ\>|\‡X_¦ü»üáÇ1%xéÒüBTEâÀ9¡ôË[mеšj ÃÀ9Cqt_iц³±(`…0޾S0‹\pxx„P1‡G TœƒIÍ£œIªgDñ¤ì ”ò Ëø|^Ÿ³(Ïb böŽ–sæå7T´Ú€&çî`i\]0˜èîîÖ–ÖŽn âž(eW¡D€}ùÄ„oKájEî¼|A€»Ad/“ŸïÃ(Ç/ø(ÿàKèÎÔˆ&)_ñƒ¸èñZc¶N@ZZ\Z‰ƒ%k×àœHh%k‹‹áIñÚx¶¶ØæÍš`˜Ó`–)eÖYÙì±à‡ëðïc«"æC$àE‹€7 Í& Þ§Jà[ú—— ¤68¯ °U<7o³B0“Ö ¾†• *‰Žåx M¼¬ 2S05qÀ/Ç& S%æÄÐ]c@#&è©ùN«§ûOãr+X¿””O1Ë*àCc»ºd‘èQVE\Õ+¾4Y‚knâ{rw°4® ˆoG{ºv>û\S'±«{!QJE°ø·$®ê)ZíáˆHxQd|î<7BÄ•¸ ®,˜ eZ`ýAö¹AdÉâÇ¢u{QÀîU–—¯][êŒÏìyBg’P 2f r% Ú›•Úmf"z…pþ]ºhñïH@ÿ ”ûä“‹—f2PiŠÈù¨ûG hkàêBT@ËŸ»MÏUÒA|]ï×2ŠN½kp¾i‘:V#©~â^Ñd€w¿™2 bà‘{V+!M<,`ÊiVWŸ:s Y9)Ë&ÃTÊí¬—qòj¹;ê8»‚—pÀgcà {@0‘³ƒ¥qE9#‹Ñî¦ç~ôã¶hwWGk[g‘ÙUù2+H¤ðQ²$®êÎsåãb<˳^MÕÏ W€G•N}ÖNÁ=¤é2 ¨¸—8^¬\¶‰BgíV”—”e3Å»ŽÙfuÍÊqýðb K©5™rz."ZY\J¬‹À?¬¼èðó>ºä¿tñ“O®\™ž-¢ÇtMX›€`ƒ¡]«Vÿ@Š8×…¹;%y½8ˆ¢£ŸÝ臋çN@à08ߊ|Èd“cƒG?ubtlÌ@—ß%õžÝôŸÑÍ3X]Ý/g”¤Hl²Bõï—ÏÚw¾ºH@@…cyŽ“œü¨B /Q-Œú£¹;XCQ1º«udzϵD­MÍ-{èZH«<Š˜O–ÆÕ¼y^ 7_ÈháJ’O`­2j(!„(ùD)Ô?ÞJ…£d•å RÙLñ ÂdsÅ΋¥%kÖ”T¢V9U{ÔTVÌWÀ‡Š‹Äº|ý¦E@à%àç]ºtÉ ¼tåÊ¥l*ZïóË’àDÀ@Al‰ÐW8æŠæðÏ:ˆOjú°Ü . é×­qL«ežEãþøèØè¸¡÷'GîŽj·²«ƒV¸šìöÈý§ÑìœÑÌ~E€}>¤ý9»ºd‘€u2Çs,#ëøTäx0ÁЪîRsw°4.8ËóÑŽ–X—ínoÝÑ´GÙEtÎ'¯ÊƒxI\uµÇCd\hÈWT§I:¸¼$ó¢Ô­íÒÔ]=*ÞCÞ|Âù?^‹(¥ViTE¨ÒÚæ¼<»©ÑŒoY¢ØU¥k×”V‚¿fG¬% ðáãZ¼~óæåoÚÄ¢J@d ˜a‡zBOŠÇw)í`‘›òçæ) J8ˆ¯Ól.5d˜Ò€KH4¿¢œ7³ø €#8;]3&Çï}5jð\U#e>ƒ“À…ž=˜Š3Á0! `˜&¡¥ ôÏÙ%r±u¼Ìó¬¨ZbÈXßηJ’œ»ƒ¥qáÀÛ$?ogÓ³QÝmoÞù\T\¢ó®P&K⪯›p¼ °^Nñc©qp¥NQìê’è:`p6œlá<~z¼Z4в8ƒ…µ%Öš¸åÁàôêeÓJeÒi¥²Wú+-^SªÆ}ìœ %¸²¸6H@:A³Ñ)ñû'Ùzh=áW ‡ÇÑ {¬i°Ïcm-À Rl½X¨´ŠXy‰U¾ôBš>Yî%±™÷[R‰Ñ\¡HŽà„]U à$1ç±® ¸’šiª2ëñy<ð¢n“ úEÉÑÏ- ¼wœÂbÈ¢ ˆCkº˜»ƒ%q½<ÏpÀ†hg˳?Œêj´£©¥3ªaÁ hM…_We€€'°“Ñüá4®—á%JÀ?Ô5bY湸QÐV–‚ÊTV¦ëUʜͳ¦•Êj{p"Q ªª2›5Æh5¸²¸”Y7oÞDN™g}›1¬÷Jè‡Ë’$â8ˆµ¦Ž.¿ÆÁM N‹t~,d¼,\4û ÒG¢ R7ܵ>¯(àòŠr8 . „¤´ µ,+qñ(/ÒÌS ŸOðøXLò„8w~®py‘øñ 1 !8àÀ³Q%T Λ»ƒ¥q}¾*AT `KTÓ¢]ÍϵFyº¨ý²qUŸB€Î……ÄXá}$‹Ë3¼Èƒ8ŠH@qEå)ELÍà#Ê"˳q«(¥ÖvZ•¡ŠéÍ:,q²—Ê:k³” ËœÁ[‹(3gÅ­ ®†Ö/_½råŸ_½zU¿zé³Ï/_Óõk×à¥+32ºÚ-™L&ÎÿãçzÉþ¹MÓç&¢á"|Àzy:ýó¦² Šš sÇbk;/†éäE\„+³<ìª<³[U¬YqYšÙbÚ  Ox\ÐÇUfMð‚°l=@&˜ÇEÁáç¢êõ¼Çç æî` Üëùɲmß¹£-ªvD;ül´KC®f°­…„pÇ€œ›¨tq_YëVõ­Cí¨Áz—Š‘²—p^¢Ö’P¬†”I÷\/znU°¼d-Î /--ÒT”;²ä„YRL{kÎn—e8J[RI§“ÓlJIq¶t~¥p³ìršßþ柿ôPî] g.T4«­nùãfy)ÍóJç.ðùÛä.ðÿ9.XQ‰æW–ò™œè-dŠ<.³çÚô€Z¹>Ô;KLËYV`ÙgYŽia|r«Ðæ¬8š£.åz0Á’J ® 88„¤ZSÕ–ÿ¬&S´jt° Zã-ZEt°.Gµ¬ÔjÑŽÏîØ#[Ü•ËAg).…e,X8pë ».0‹)¤•aDØB?/₃Ðѧ§£CéTe¹š"ëó n"àzE Å[Ås|ýš+)«¨ª,wVаè`Å YV8Be¹pt©!œÍ‹kºXîÚÌý‚W÷‘‡Þæ¤aÀ Á'ÇùošsÔö}œåÇ‚`žD,,2áz1žS4Mðpµ ¾¡ÊuЉu}>[L} ÷€a½?b+…MMÒ¯³SR®dUÎ Üxܵ(ƒ æYÒ©¨m8S‚sé ëcÛ$—RvÛCP9;èQÛ5¢ƒ×*ð`²ü`‰2•R›¤tvvh½ŽÒÛWz \™W“Ü,cKà¶ó;…&Y†Èã‡ÍQpÈ¢=]»ö4ãnss‡ÖUàz¶ÀÜWà:¸ðÊ<\µ|>7 ©—ÅË3…z»Ö!Ë‚eŒ?àð»::;Âù}ùÄ»ŠtuüªYÖr¯£T¥àöŠèº´–´¬”bzÕ4{õ ²rœ9i­éRA·T-µ–šöWwab-‹9v4œÛæ“cxŸ·¼‰ùT*ƒ>‰K³;šÄLs«ØÚ¢Ö)ªé1MÜ)Ù'+&ß,´´6+`‚›i¬{îÁ7ÜŸØ* ÌYNâ9PÏ+JMšÌz‹­$wZµˆóÞ"'¾Ÿ€éhhÝÍîJvtêšZàJ¸”6Q/pið‚}ì`)\¡Üâ½§kÇÎ(j}õðÏì‰FáÀÿÜ’lêJ(p¥·ÀÈqÀ-pÍÅõkµu·³këÐÛ$Âó>wA£!†Ö‰¸RŸ,v¨a‰7Ÿ¸Wˆ…D&ãxCè«•Z+U£¯ö¶2šå+›W··R¸ 2ky̱£áLž³Ì'|rpjy¶‰å$)”À™a<<lø0Ü㚊ʧû‰iêªÀ &³#nâ•]ä ï¬ï?|ÍbLàD©¹é›"//*ܹäqÆÍs ¼v;ý£M­g9Ð;]’9†±0g¦CÕëàûŽr:¸@ tR)¤¶:XWàCEnÖÏE÷t¶áÌ®ÎhWgwg{ëÎh4*´UËâYÀ@\èhÔ¥À5·CƽÇíÆ²+U©ƒ(·(_ƒˆ(×…ëÏuu¶ezH¯Ô–ɱh5ñ¸üäœzB8^ÜTp-æz×TÖÔÚÕ¡Ùjѹ?`í”]Eêü2„5~Î\Þ™\!ÜE¸µ.e‚}`>á“ò\ˆoi[eD”×$ð ÛÒ"ÔJn¥aê8ÏÍì0uEÄð¾½Ó0Ì¿?h[ÄÖ˜–m;wìTµòÒ5¯ñ»ŸlL‹Ù¥isv íðŸ½P¥¯¯®®«®©­'ç?€ÎSB`4wQ‡ªÀ,‰ëÃaÃöŒF÷ìQ¢»vuµïüq4ÚñCÒÕw`ÜáÀ¥×î8™‹ÛµKï&"ñå‘ðóä®.Âzò\.PB®½c'ßÒÄqL+×”ìêHø½îG Sð¨‹X'„oÞñf‰R\Y-µÊEk­†Oœ—²E¤uµÎ H–r»rj!>dÜ¿€KmÕÕÞ­vÝÙÙ¤ü‰ñµÛ™V±¥­‰û省]nUñë?|Ý)ðíš©ÉÕ" ù‘õáúª`u°¶¾–‘ȺõëÖ­'â *ø„àQõâ‚ .è`i\þOÁhWWw[ëÎçvïißNTö·´â‚Ç×Sà‚ßUàD,̘‡»›4Õ­]wGTðNywqù¿¹¯¹à®ÿf=-ÊN¾‰iîÙE>ÞFà·xBºµ] /ÈLi1^cÐÄââÇ‹_ƒíqë?œok¦±fM±ý…Õ¤kÖ–fçoÌ$àÊà.Ȭåú€ ÆË³(Ëb¯˜T”ÿâ¤Î&¢N¹£³¥[iêDqlZt¥ƒ§&瘫¦Iè=š"ú3¬’ƒ;ƒÿÙ+ïL[ )TQöX§)ßýÆ}ž}ÿÜ“`ƒ°ÉúGë€Fx]ýºuµ`|CåUÙ2caçYè Ÿ* t†¸Â…¸ ƒ¥qÁ‹ Ì®Îö¦í{éè ¤¨ñu÷¿ \í£J; ©/@\² în±…¨kêî.­Ë>²º˜$77iÚ×r“Ì75©j{Bä||48!.›°ÐñÒ`…¦¤kC±f¯VŠ–`Ýhi }†k­JÒëkK­bR{-|ê«•”Í BVwYTû‹ÚL¶J-Á–Ö?ÿç†þKTXè­íìѺ”¯÷ 8²Jè'¦ÛTÓ¯é<ÃÈš9Ý$UÆ5¢U™îÇVÂ…S‚Áò~%ó‹³.løÞ†Æï7Æ7þª×¾ ¹;ÐAñÂa#b4DÖÕ×W­#»wwvìªó+¾f: E«ZÌ­*ª[UÄàè`I\1ýcÎê1¾6²‡ÍMmA‰£¸ÛâÀçɸ`»yªâ»U¢gZ9éEêâ%õßÒ)RÜ]à0Pq‘„bç¼ã UJéÜlB.».d™•&É.‘aeQ¦_.sŠ–Iäøz–€+„»²IúsU{›ÔÞùµ¬É%vÈ­íZ§$ïBqÐ;T„JI3ýD5ÜSÒš9±©Š¯ád©¯Ijma| ûg+áâN€Xþª7Ý›ÙOÿ 7½)óô¦„/Ú™Ýæt zò¾îà°ÀÖ“ ^üžÇm8¿y¸’XÁW4ùÅZ"‘N­s6®äÉ“¿¶`ÝÄz’Y×:¬¹¸’¯Rf¸æéb½žëxó¸yǬ°v4 Xƒ^‡N^ÎáN™ói5g¡@Y–SÖÏÙõWwe ˆþR«ðŸú“Ü)IZÏ×2ËJJ·ÚÞŽâ( wئk}Ý&Ñu‘+*de³U¥Ý)5‹`”YQ…çvì´.š;ùMºÈ÷=vãæ ú}Ó…L£}A—è@hS”¦¦LO[™ÛÖ²cgÜŠHÜé +nøoÅÕµçv´[¸ÚÃÄ¥'$çñQhÉ5ù¿•ØÍ©‡·_²~˜þ%|•Xæ±Ôþ¡7.¯\YÜ•% úKnîìlÑE¹]UxE ¶(Õ-ê®m—$Éuà¶7w´Ý&Cü…LŠbâ6-b“*üY•›Î§wøZ…â5î5¢"{ÒçÎ}Scã÷¸tï&ø¾¿Û\²ƒÚ`¥ªrJBšÛØ pè ñÔÖÍ›i+n›@\ù¡âZ'$×ñqÀ5Ë”¤D)±9TbQÈf ýÑ"%J‰Å1ºQyv}ÀÂ]Y¢¿$wtuF:$Ž—ºõîjõkák^íiWš»[:[«šÁ¦~¬T:UI¶]?…åÎ*M!My®ŠžãdFÑ*ž5˜p9÷ä6^ G‚eíïqëYF’P-A8¾Ü¾¸¡ 3HAÇa+hᔳ‚óŒ-Êé²åÓkÜgߘñçÀ“ª•ÅýëH¶Ð] P–ծί[šAäB-r›(s²öµª±pzIòR•¬ÏkZ‡Â‡x>³SÐXŽù“byyÇŽg½|ÙÚÇŠeMõ–cÂ¥qCúûxlØ”Èl¶¾Ã£õ<ü¾¸ÕUAÌÓÑ.]@ŸZé8{îx¥õÛ`°²"h¥éœßTTƒ•Ùwч`UÍÊâþuüëénêîÎÁÀÙQpWwçµ·H|«Ôư^¦ª EâN¶…QyYäÄ åM¼(î¬8‹%vªäAâ¤Ï>Ç](**òxUM}‡³ýT|ã¦Íxdâ½›ñ{ãÆ OÛ¦ç!wPÞ»ùÛ‰K‡ÃìѰP•½f } ÏíOl8FʾÏú-¾Šï ¯X¿Vw1‰Ë%rzÏöΞží= ÿz&ÿGÚÁW_{åðKÇýöáÎ%`–rº~s¹^# SLßÕÓÞÙÓÕ¡OÿÙ ²NðØ¡ÿ‘vNÐÑÃÇýöáÎ! ~öw.I¿páâ .— pï.È@½µgG§«§ÅfëÖ­6lÝúÌüʼn^{夽úÚk¯þ÷Ûˆ;›€ú…/ι\¿K€üýº&´N$áˆkî6HÖ;Ûº]íÝ;t‹ßÛúO|ë÷žž·8ÑßÛßÛâm&õ >– ‡¿;«WÖÅÞKW…÷úŽ]€Ûw=»³½§•îíµµñ{›·>¹uÓÿyb˼ʼnþ‡Úk¯¿öwÜo%îÌIIÖÕÇû±ªŸFªzE>Ü{îh8\Û/ÍYžˆNXjîélîìéDk½õ‰ï>¹eËÖ­›þñÉïm»8Ñ¡ƒÿí𫯿zôðßq¿…¸ÓÔ/„×¹>êMÔ®ëðï R8Ñ'#ýê,ê'±é==4 ÖõgŸhlܸ\À'7|÷[çÌŠ{ù6´úÁð`=îŠP_ŸáT*ƒ·Ã©Ûƒƒ7oÂÇ­[ð6x¶H¤^‹è+°Âõuõ¸oDÓ‘H_‰ÀwÀßL€Ä¿ôV&óVìí·ã™xâÔégN=sêTâíÌ-¶„ÓN3Öã6a— €5ŒH}ª¶Ô% ·/ïO&ÉäÖx:> 'ûúÎ2'â‰Þxï÷ãñ¾x2‘ìK&úžI<Çh{2–¼LÆ{ÿ=//ÿ<ºŒSÞÞ¼üü½ø¼ÀÂ-(ø~~'ÿ‰ü'òàcõêÕ«žXµzÕ¬ö¨k±¿}tú­«V÷Ð +…ë0+ŽÕÕññD¸!¡GD1\‹”K¢Íš—yê—ÿäú矿éïÙÙÖÝãחׇ·l݈)¹gžzzóÖ¹|ø7H?€v‘zÊŸT8‚зëoãç­[·nÞD"“€juáˆ^¦âTH¿T$B—0À'ù™€r9t´xè…t:“ÎdboÇOn9G¦õ éð1Ýð9!û_„ýû ÁwýêW¿2j‘x5À½š°1XÛZ§G/ [¸±x<™LHç’Éd_R2ÆÏù ã‰DZo< ¿íˆÅ™X`ÈÌ©¾YýûÅ›§OŸzû_ß +„÷Õ…ÃûÂ[Ÿ~ê7oz4p)û}À–0eSxZ ‘·PÿÂÀÍAx¼x(+á€o¨—ðNE-ÔµHŠþ±½Í èüÑí°M@KßÞŠ ÂÇ[1»LæBº7«}ofp÷ôCÇŽì?ºÿØáC@Aú²i@Î…„#²®:]}ùrÕ… 4ÛÒß?|ë.ê‰mÉo¼ï§ûà…g}}‰X<HcñÞ^xw*ÛöÂþm©T<ó ]Dìçß)%|gûêüw€‰g-\Б¼¼'ìÕ (¶šÐë8ï :WÑz¾¯öôåÆ_;q§»d.¼äâûu|Æs¿s¹Þ}wÝôÒo¿yò_OœÒ]§þ‰20®® ×U?½õ»ßÙàÚôô?Pú#Ä IDAT<ñÔ|’eYƒˆDL…•·ïÜAü(dª¯¡Æ ÊÀàâ›ð«H„ãH½mÈÑþ¢U§ä¼í(à›iàÝ[ñ“±¤ßÊ<ȼÁ¼)„NÄgØ_²øÇºY7ïf‚ä-l¤´Þ¨G;¼>R{%^?X7|çúÝ,“ýIé™^0¿æÀ€_÷÷'½ž ‰D_2Ÿñä–X¬o` OÄcÔ¾”+uìð‘çoKOÿGÁ;Ûó~³½ ÿíÛóß¡KÚý&fáZvŒ^Ê9vl•saéu³®cö".Ò¾¸Nha]åºwÎÄ|Bƒa÷»‹_¸\‡Ëj þö¿~ã_ßÔõÓ¿8¬ ï«u…«~ðôO|óæ-ßý‡' p èA»‹úWo©X‘º}ýòïVàz*|ª¯A10‰4øƒz ` Þ_DW”zÿl/ %21•²¸mý#½oÅßÞrŠç?ûdôÎí«#C_^»:2vw¸$Ýû&Úãô¯2i²ÿð«¬$ó¸:ÎPÅÌdªÂµë «EB‘ÚšTjêØÕ©‘çmbÇ }ýg½qE5û} ý™Ä¹léKôk1%ž)Hè[©ÒÛ^ÚŸb\©£‡^~~›;Õûl>áíïÀׯá+oû;Ûß)ìu.h^Þê߀ŽÀå\=×—Be©U‹åµo'®¼ÿ“÷ߟÖxΞ‹q „¾ÿõÁÐ!LºÂú4þËyK×]o"«ÃûªêêÊŸÞôÄwžÜ¸å™Í6Í#`-êÔ`˜º~Ô¡KE(Ã5ð*%àud` ¸ ¢V5P5øQ¤:@E³>¨†_išŠÔ”¼„¼¤F5pÐ&JæŒ2üéðõTÍ•Û÷ï_ÿjïä¥ûW.}5ôûBîŸÑÿÃèôWT«ø“`<‚/ß Õ[4jRµáÔº;—†ï|úUVúû3q·;Ùw,ñ@âTâ›ßyAýÉþgú“ý‡øQ㽉Ø6ˆ¼ºÿ'Û R½¿}÷Ý÷~SøÞö_çoßþί½ý×çm.(#óÛÅYyö%Ïú^–ô|;q)ÿ¼^ï»?q¹Þçx½¦tHï=ûNåÁƒï‡%Ax¯ï…,ÿåíŸÿÛ/Þ|[ÿ§“HÀ}á}ÁêpÕ–Í?ø.¸Oÿà™g BRÔýCTêQ둃h›ÁþR¼]]]Pw±20x-  6VVVW‡i¢ …!ìD¼M­q=bd h„õW†‡k†Foß¿ucxïÄØ­ñÑáO¿,)£ˆÀ‘ý¯â~•ãDŒ‚i$œ©½R[1hÅ>p}MjpjlôöØ›€‰~ƒàÆX¿_7“Û’&„#ž"7„ÅÚ@"‘HžéíÐúc§Û¶½þÚÑW^C¾xØ4·¥ ~»ýÝývûo SðÛÂí…ùÛsÁž»ñÄjp¥ð‚ÉÕhÚp½ã'С‘[½€È̾šÎ{íÛ‰‹üûw:òár ®³q°Å ½êƒ  ì…ëj‡èoÿó[?ÿ·Ÿ¿ño§þï)$`e¸6X®Ý´éé']›¶<ýƒ'çå_ÀìJ8åÄ hXŠúƒ·DÔ¼EC`ZÈ€pÛ×nª++£ú:Ð ^¨îÙ‰š·A_Ò6Áµ wÖß½4y}y=6roøæí+cÃûî]ýò/t;âé ©²UÜ®E”kSÕ©TM­A#@¥ÖÑÝvhê t‰d¯o@ï‡ ,“Ž%àɤÙ?Я <£ôÅ·ýlß¾}Ô 2 L&UðCó= ÞAøÞ{ÛßûÝô: ˆ×ð ëÒ‹×õ‰UÖµ|‚^dëùªY>× ?kÚÑ·þvâÿÞ±F>Pì\guéÝÞ„¾®·~F20KÀ7Nº\ÿtÂ¥[ W‡1 n|êéMÏ<ó·Îߦ¡ž«ÔG,ay4†«ŒáïÍ[·-‚øá“êJA à`Øâ_eXÓh0JV„2#a…ŠØ ÊƸ7o: ¬ÆWøPmë_e%„Ã4¶S/NÆÊ#blý#õÕëkëÇ/A ô¹u{è±?Þž¼R6üÅów‡JQƒdÿVĵa9|è0à‘£$’:64<45 ­Ã4Œ• ßš¸>25xËÂUûÍX²ïÔ… ™a¼œ¾LÌ{Žñ~HöçvèÉd\¾òʶmûö8’bXSá<¦ÆºL ÞöÂß¾[ŸÿáNÛ&Ø]° ¡²£HçÉ2ýùNýÿ \j_ -÷}–ØÅU]¹âÞ«xÉõýªjÅè'ùæ[¿zûä'ï`¤iB}ã÷¶lÞ¼iëB[u…Œ&¸®.¬)a BÓ9xë6Ƹׯg ʯTªáåj‡• xV0 na} æ«ëÑþ†ëi–(iý#•ëjƒ©Ë!èïÖàñu“Ã##£×&†‡Ÿß›`z:(á–5D}iÿa\NR$\žx Ù/õõ ½,'püÓ± 8RÜ×ßÏö¢>|hÛ^;rôè½/jdðÖ‹)™+<× ò‹¥qøÎIœ÷¦9OÁª¹—åÑ¿š,ÿKpý,ãs OŒ -ƒ€ÚL±Óxî=Ï{±$EªO¢Ã¯kjCu6MÛà` (àm‡—96¬Æ¤1Ra¬0ÀÅ2Ë·1è½²èÈßàG•åeÕÕÕ2xêð65ƈÀèõl1P¯¾]@'©®¡¶¶öúzˆtîܼ:6zeìÒ•+žçkÉQ0À~âWÂ_Q'zý‘ÔÈ¡¡ÁuWïƒÿ—4R ·ÂƒucáÁq·c нDœ½†½Éd?—æ3Þt‚acX~qJÿÙmÇ_=zäño{åÈÁƒ'ºJ®Ü›r›…+NÀ[/$/8 Ø‹yÈ ¸…¤ /ÚW3ÿϪU’‹€Ö0\PËŽÓ$^hÍOqÜ=ðýÊË!d”/èÈ¢mˆS`8¬XœÂèv=umÖ‘£z°Çtשׂ¿{oäÊÄèíëCc·ï¦Y.HŽA xéGD¯—áÅ|õÔÈÈÔØp-¡Õ†kk‡Rc×jIà^2!$ôÓVYL"‘ñÅ{ù^>mÏ$Å×¶½ô ?}^ßü;°wïOž'ª&êäÆ[šÏÖe°x!Ó h0öÔfð$Ó«L»fÕÅÕùéÆx<ý ýV|sú§`õê¿(Zøß« ºªJÞÑ‘¯¦¦¦t×—$àM‰;b§« ᳉ðº°Ö§£`uvMð²ëÒõ›woÏ~} ÄNœPò)èÒñàÁÁúÁªª€CÀuþÊÊ@üÊ€S©O"„”¡%žá ‚@@4嘄w ¢‰zhGÁ`=‰1Ø@S)µuµÏ ^¹:2ð³—ý² Ë4êVÓDÓÛ›†H:ž¶ç1ŸTàÚKÇÁ²¥ASÒ˜ôƒøæxl#>lŽÅá®mžkÛò‰²<\oÞ_JÀeâÿ°I^ïðØÔÞž®Ü8M@Eíï•QìÖiaWñƒ ¾šš$‘~óv ¾uù³K×oßYpÆÈlÖ;iÀ”µá©F F‚†² ¦"‘²@pðÚM <£?Ï ð/H0ê@Òáä0±þ‘uõŠfRR‘Úk£_ì½;94|wäùêš½GW±ì?Lt/) ‚Ä{%]ÑÂW?® Vcl0Ö¥Â57ê§n4X¸hr!òÍ€'Nõ>ƒÖô샳À¦ÊbaƒÎyÌø…÷·;vØO¶mÛöÚ«‡¾°÷gįˆ:§ñ’.ä›é˜™‰Ç’ñdÜ1ÁñÆøF[NÒ›Ó`ßzc 'oÅ3ñÆÞXcìͽoFÒiˆ°Ïöõ_ ö/(ËÁ=ŸNó—p™¸º.øýc_irltjoGtiÏœÑ4­v<œÑû# ÔðÌ=‚¡IX]pr¦>H³0 ñoqàתê£ìÓU¥ºUzg~h(R*¼™ú( „n‡nÞFêÙ?W–¬h$ˆ-\¨ ÛÕ5ƒÔƒeŽXÿHCC}¤a=–öR“×F†zuôÊÈØÈõ±/>_¤a¨‹‡‰_&^ŽpL‘G5"©ñ+#£×n…oTÓ2@£!e †ªG¯×WÛİ|Àþ„|,-º€ýÉ>^û“¦ yUE,òúóLLï‘#nŠ´íõW~¶÷ÀËG4ݯŠËKDô™qüöÅc½ÎݨlŒõ=µyË–M·lH_øU .c¼qSc:Þ˜§™X$˜8—ì=›ŒŸX6—ÄM§ÏS5ø ¸Ü´¬èý»w‰41< Ü» ÎÚþã‘yÏ$ÙbK#ÌRÀH=ÖUÕ×GTÍ*2UiIØßì å2 \YÙÍ[ƒX ¼vÄÏþ¹Œþ2d0” „0þEULÝ®EŸ0b%µÞ ©2bÙ†ë£ÃûÆnB 2rcì§e>ÂÍÄ&Âù ®Úvmbäêõ‰š¬†nÀåÛˆwªjêïØÐûM „¥$ÄÁ~=ÙoʪœLj¦ ûTIÔU™¸Ìþm/½ôâ>ܘXñëÛ^Ü»í•C^E\nDá¿ì1ÓLƒ~Æ!à›·ÄN¦›77ÆAT¸§c™ÆXcú©M›âOÅcŸLUëH2q~ v¾ÿý~xXÂ/Fä<>V^— ˜~7ùÔÔØ8ûã—ãSS’²4r›E@Ü_¨Gp›S¬3­èÀžÚj{^}¨:ûº5x âŒÁе›Ü:?[¿t0 aú«fn;•©ÛW;Nc©õë±¢9ÒPõ‹/þx{tìÊäЉç>m•9|ø0‘…ð2.DêO­kH]¹6z'<ˆ‹‚~¦ˆ XéuÝÂÕ¨ìõÅ2AôjcÐ?YT%Í«É7½ÛŽ9¢ê7<ß¶oÛëÛŽüô0°—SR¿ã̳1¤`ÚvêÓç@6Òg7mØòt¼Ñû½ô¦tcï“}›ã™M›bpY7$7u•2p>å4×â \..9þúë¯A æu³’¾z¹‰èeoú¬&N›œ¹wwD`t‘Dà‚¤+žº\ËÙ,$×»f™à¦± ‹VÙãÑXÔ‡ ´WSÿ¼½Ûwçu/ègXqéKݯŸÍP$úZU]]ÕUÉÓ/ÙVŽœ^+9Ë‘,ß’¬1-Þ €¸ÄÓ¬•­™˜Te’œØ ¢Ñè®Y'3ŠMQ¢D -‹݈Io3kþ¡û}öþª$% ÈxŠ$КÕ]¿úíýÛßÞû3Æß/xèrß-¼{{u|ܸs h ¾Ž~˜X(˜-šzÁD4Æ—À¦ª«`_]¨¨Å¢ã;eß3Ìö‡Þ¹ÑýhíîêæñoE] 8Ÿˆ¬ ‰~VÇÜb±{óýJ<®¶*t)Žø¶UqwâðrEp£!­¬4úýzØ[ésý€×\lJ‘àf³:7=IXEÕÕêéêÂ\õÂkÕ«»‹Õsš|‚Á3·ƒ^¯^»Þ[‰c@¼˜»W‘3zõïÖzµÚ¯–_ú~ý;/V/׿_'ÿü²ŸÏ‘ÖìÔk§NN¶~ÿï­¯”í’™‰Óç¦/qisüOŽä+#Ãað+ÙEÇ!*;[Ý­ÍîVg»ÓÙèlï|´uïïÀ¡xòó—lòø§î@ K舆ІˆÚÁ2͈€ïV½ñc«·÷ŒÌ8­â‡Ø~ýð!Z4ý|‡ÖaÙn«åÊv @ÀjyV0Tñ[ö*èùnÆÝÁ,ঠÜmÕ8žKK„®…ø­Še¬}Ôj— ,†±sÏEîlÏŠ‡ç4µ N»?vÇzËËÍZ½¾Ü¿¾p:òŸ"0A#XiÔëÕ3§Ný<0QÅjUš½(¼–¾V=7¥Èl °ïM¯Ö—k‹ƒjé¥Úë»éÝE”/Õÿ§Þ ‹ÿåjïß«}÷ÊÊ àÔ^¬×¿SkXãN¡5}!â¿[oµ£û‰×¯f—Ì»—.ÍMUüEÉu_Oïî>½]_Ó}οßÀos³½¾¹ÝÙØé¶ÉN÷ë2àC¨:ˆ¿ìY2 0Ò Q A °eéÀ@à»ï¿ pp€Ü0èø.ð¹¸Ñ“ýÐÈGøbú¯åb« °©ªE/Õ±œ«ÁàÀ<)ÿËžõhÆ£+À^Üf©DÍ Cp=š ŒÂÃ_äŽ7 {4é0MBÓ6:¼p À² À[µnúžÓ*û-£uo­{«óAéK&YIˆBÆ8ŽI¥Y"0@†TZïÜìtnÝÇì·Ù2oµZ>-âbë]dw¸¡i4ƒjµúYâj-1¶Š„×ÜãNl5BÐ("uFUu!-“‹¦æƒ¥ÄÕ] u]ød°Ø«!•îŽEvÿËbúÅ•Þ÷–wwû "_ØÝíÕàß›»ÉÝÝ%åûuÌþ•¬Bk¢U"GljY8Jvw“Éݱ/u˜_É.`y~â"a,?!;—9|Ôyj»>ÑDž—ý„¿½¹¶¾¾¹öQWÚܤ ŸþAv‡¿¯´S×>ësiüëÙè‡5¬kôÉ2HºyIL‚tZî©S0>w ù‡þŠöjL.û»¸´§ÅiÐŽë–oƒai•{k£ÝÞh·ps8!1<’@P²Ìñ¸-¥ˆuYGJ÷:€Ô–á9•ŽSÀ{£âùšY.ÄÍ@adHu²ZOÕ>KŒ$€SD%öÀ¸KmXmTÏŸ:~÷#Éð³S禃Úb²:}²Z={¡ÚlŸ«7êË‹¿Žì&¯b>w±÷‹W¯¾ #,Š<¾Sû~8®4ŽÛ­ ­Âø÷ZÁöw#ÉÄ¡¡Ç/d|%»dúÜéÙy"ñÅ챂}ìHÎrÔ§¶ ”X†‘üçüN»½¹±¹¾¶)íɇ;p9ö·ûEüýgÐëTדU-êòÅ¥€¤#«T²q9ÐqAÉ®°”L•é>; é8ºBÑ\m­FAàj¼ÄŒ’&!àÛ}ÍÎ/T|£@ KwìèÀuÓ$>92’`” p¼ a£¬ÊŒ& ™P1'¸vï­µvÑñL÷†{Ã+àJñ]˯ÄLbÑ} îLµ¡4ª|blð¨r`P[^i¬Ôë¤:?;MtM—8IÑ.ÎÎMýk ‡kð—kKµ•Ë˵å^½^‹·Ôù_’)¸ì@(ÿøzr÷x´ïõà¢ö®õj/,õ–_'ÃÆÙ‰FëlË0?h½ýÂÑF¯Ç~–ØM%F‡¿ùŪ€¯d—\r/ÍTˆ/rŽiŒ7²Ïgœ§µ  Ê%“’?nxc½+)¼÷Î_Òý}í~UCCCÿ™.x¯€”6YRª-Ú bGû7Æè¤'~è*îR Ÿ”,ðAÆÄ "n ef+Z^½ƒÆž«º-`ÖxÉÌs4Çö~o•5gHЭ´Û÷N`]¤Ä%’‰«ðàƒ`QHbMèY!ïw7nC4ÙÂF<>EU@~ÅŠìŽîÒ’¿fõTu¥^­²‰±ë@AÔÄdШÒ=¼€s¦IJƒß—N s§/ž {µ~¯ºÔ_î/]_Z^®¯4»õÈn:Õë&w{»×v¯²@.Wwûßí÷1ºQ¹†¤F#\ilå2ã¹VÉ´òG¼Þ ½8¿ÝTr4ñÙ£¥yû_É.¹pú‚KæÎ-ˆ¬o3ìÊøó™§µ«ú¾ªðc#¼â'ýîÆF{»»¥*ÒÖÆ=âƒÔÛ×î({‚ã®Æô%¬‹ŽZ3mÿzeÀT7­ÇC¸©ºBÃD x7YTAV™¦=Y´,ËF5¸ŠlP¿¶ª½X[cõmL˜˜¨¬•à‚‰6!…gÒi^XTñ^DÃÊ|mB$ B6­ÕrnŒ[pZ.&cZŽïÅ®ýÛ U­Y½xüìDU€hŽET4Aá lH€Î©ž;uúÐ-Ø…sŸž<7;ìV«õZ­¶Ø{sq¹v½Qo4VàˆØ[\~±—H0x5_ïí&¿ÓßÝÛýþ"`áÚnØXY§/Õê@Ä'ZÙñçsV…äŸwjßýîò‹ßéƒØM^ÛºÄ鬌?Ûø¯`÷ê‹À€åÙŠ?sΗy3["•¡JÅJ»êýí-ßù+ø£þööÖfw{k‡(çøŠ¢ùûÚýã0êÜAì¨5.B¤ÁY|Pi"ã5b=M•Eø,("‡{Úkȃš.‹¢Ô‚ëÛr±¸*š«î©à–çä‹–k:æª1fË}ï½»w)¬’¦¤9ÜÝ^àyAÀÀPà‹C66:·Þë®âúwÙ¹…¸¯Re B’©¦Öœ;Q­^8_e8;`?Ö€¿ _«¯2 ˆV5‘I1qœTpmqw¹‡+ÀË=PÑK¸ šƒ¥­þë•c©t—°¿óÒµ×GÇ L{)ì…ËK×®7Âðz%U«ËäKEÒû\Ê—àÚ_K$Ÿ=û§Ï>G…~ÓãûâAvÁcövÉÌéIwf~~ÊWe¡X1ýQ+[ðžÎ®ºÕét7}…K :üÍõõµÎÖýmxëuˆ}m_»\ºQWœ7´µ¼¨=¤Õª ò"üè^p§ÈÀ|¸Z¬D”™”\PÁÇ-­¥Ñ®81ã©”ä‹ï–?(Z7 ¢AÛnu7Û7is„Äãf­X ͧS©4øc’)žÖÇ´·ÖµožgZ¶m8.È`Û‚h4î5ùL ëWæÏÌT“$¨@€@ÐP êõ¦¦Ì?ÏNë,jpÊ&f§¦‚«cµ•åÞÕkK‹×—pÆ ü¹ÞlÒË/Õ^¨;@Ö{qyù»}ðj¯ƒVî5—p½TpÃv*» Å*ùüQkéjoù{c‡R/¼OÛM%vß|ÙŸþ¶'aT£” IDATöEY9ÐîÕ×Á’9wú\åÜœOTYâó–•)(OgW½ß]_[ow}ŸçÿY{ý£»kû[[à}ßßÖöµûÇ Õ 8 ËŽÚ“Z­hõÌŰc>©ˆ! =®LÃ*€š*Â’P"}²”·“†#hÄæ©êÃôý¢mY7]óqàµ6n¶×n‚ð%’̤S܇A65<šLK<›e$–íwß³-¿eV+F¡Ñü\΋pWjÖAçΜX¸xr¾Ú ’ DÐáƒFM'ŠªWÏŸ9±p¬ÀIÓÎÏž VÒËH}ýÆõËõ:pá2è0ÞT°öý¥jõ?¯ÿùK=’ýï|¯Ñïõ¯í²ý.__üù Ðj~©˜ óFþí÷[½^í»µÞØÈX2ñY"•šü³?}î_Y©/€—¶»xmó s“£hz‚x:»êvgýîÖÖ6¶ÁƒÞî¬}øQç~w£»|¸ÓQ÷µûÇ`‹NÑÀ”ÝÕ¨8 À'¨() !ø£øÓDŒìQ’ß.ädš¾A Ol´0G×¢5†€Ì–¦ R­[¦m­"­ìsÍÕµ€ +¡? >ˆ¤YK'ǬDDrcýfÛY5?0WßµZ·à®ÆaeV\’ÿ§ÿ”C½Q>±0{¢ºðp: '`Õe"ÐUIBp¼½êÔ4faTO\š¿879ì.Õzµ«K >—+8¹ð7ˆ£¹ õ^íûË=q—½Þ“(¹ì^ý®7þfq^WÑt­BÖ*~ðÞÍÛß}ñ{˜ÞýûD2µ»›ø÷±±±Äg»}/'¼Ìí.÷»ô°‹ùB ( ™<•]ˆ»í»Þ½·¾¹µåáØYS÷µ{ žö«‰9€Q=û‡%8Xˆ6–ûx•ÔTôŠXEBsk€FÊxbăg†X“d¨"ч·^š2Èâ^ÉîÛVÞ¥“®Êî{kw‰,‰|(IÆ‘:ÂŽÀgpÁaÈv{Ã{ãfÅ0§h:z8(!¾ó™+rôÇÌ©… ¯UwQSAC% 8#E’‚ˆœ¦atÁb\çg§&fçƒàZm©×»Ö»~õÚU€ârtð•È.+0\kŒ£ãÅ\|±_[ÜÝ ± P×à ³¾mæóFSVù£Gœ¼´üÂÒÕ]ö³±±Ý^úõd"Åô$¡¯¨ÔCpÙMõHsyéúõÚÊJÓ·ŠùñÄ+ rù©ìª›n·½vïÞz»Ý>ã'ÆFaÒå™C#þß¾§îk÷@üMOœ?qnâk ðsŒ ÙXÁ¼ŠE&«îНþ4BÓ.*… ¢ËšN ââ, @p»’¢‹à¯}`HôÅ€@O‹èáê2¨ç=\ö[®U.­®/í¼³AdЇ† ÜvÈ€à‚“àQ³Œ¤4é¶o¶o¾Óš{¯âÜÞ2+«´ °RÑü8 ÃJZC©V/;viê—Õ+89M’Ü·2þ„$IáÆÆÚæ¦aY«ðvÙ±°?Ø×°=)²ûY³^«g¦_[˜9[ FÅ{CÐ8 ˆ*À£0L*ê ú#DVy↠˜Ÿ:¤ƒëµàPP»ÚM$/×êf¼© ŸèÃUdRpôàzŽ%ÇÒÀÊI¦×ƒÀ8ÔÃ… €@ð•ù-‘ý^|©ÿú µïaȶػÞGe†yPlBã@»¤¾xíê›×®.Ö®/Õýb®`úÍ%OnWí¬}t·ÝítÖï}t¯«núI_ÕA‰.²œÈßÒö·{ÝÁwÎ>941©}éSö  Ö¨5îŽ2¸ÎSFÑK°FP‡ˆ_S DDŠ€FQWY§ò$2r"‚ŸA˺Z.1Gõ ƒ4LÎ_-š9/ï”Ë.ºà"ÄOkDy&1öÜ¡$/“ ä@$7~ÓÿòcpÁïnßl¿k¼{»¸Úš3[tX%¡-êN\ Ó ¥zþì¥ '.ÍH}Œ"¨<æ1«£HÕBŠáE±ïIæT1)V ¦'°Œo:GwWêA]ìl.ôQ‰'pQIüH@”ÿ’)ϱí²ëéáܤ_6 ¹LÑ› ¥°Rò{ßïý ñÒ‹µï¿øBOToáz.Ó0WY9È.©/]_|óÚââÒ"~ð¢ß¨ûÇá8é?©]$Àµv§ÓÞØh¯oi›Þ>‰“@˜‰)Éÿ¦_Ûßî#øûÝ}C›ÇùÔg&fbÞqébSp!X@¸CtFHÂý#ò) n€·˜âÔTJ‚™‹@ NˆÑž pÕ8 ›ƒ4 ÄTlŸg˜$“·–JrÉ<ªJú\·]pÂÓs ‚3™Be!”ä°ä¿V[þÎ÷¾ÿçß]ZAaF×,1ž’•þÀ¥}¹]²|ýê"×W¯-Öá¥?wæµãþ“ÚU·666:µ?Üív¶Ô­µuÿY⎅+•òµì~Ž¥;øÖ¬ç]œ™˜ðÞà)S_ €Ñ<"ÌÀ@ -äÞY­ ÿiTÜ¢ñ+Ž£ L)YJɲ «"YDŽ*Ù ‰!ÐG?Ê„.Ó)¢Ñ'%ª±VåX A jW eÅÑ@FWl‰OÑòA,ð¼¤!µ~|úcHĽõÎíw:ï™&¶¤›T€oˆV$îZµ:{ñì¥ùœ›À £ßEª:Ï&xn‰K3„¯Y]H§U1• &‚´$Ù@J»AØTšƒ˜êuAè¥RàÕº \ß~}»˜ËæŠN˜ .^òíBÖp§C™ "f¢k/Ô^ÀÊcˆ"ðC.§ü+>ÂvIX[¹¾¼‚\ZF¬…õ¥%ÿµÉã§OfWÅUMÁXßRÕ­îÆ= f ámPxÁÎW°û)Ý›˜y˜½Ù‰s{Ô8xÊìWd@-n^½³êÆË¸w<Š?P½ PtÊ>8 Ó Å G+2DeF©TÑERk¨c1u lµJ-èÙ€cøÏ6-0µo´H`–ã9A¢ъ㦠PüøìÇ ER,¬uï¶ß.Ú–¿¶ØÂà‘P§a2ÇöÃêüéù™“ÜÖaFJ˜bÄb‡$—’9D ü¯J‚O ÂÈsR0HiÄà!.\¯†MuÀ€+ ‚øzêïÓ)ñRü.ºµdòu†ñ+¹l6ïè¦.LžrKV©r:T B˜õAôzJ]Æ-„xG šo‚?«CT%`—„ ¿¹ìãxÿzm xðÚ`Ñ?>uüøù_úOfWÝÜÚ÷ÛéntÕ­Íû[Ý6D}æà-®P?Àî#¤twn6rÁÑõ…oÍÍÌíQãà)_ÝGø[¥Eô8MȺ£à‚›¬Ò+ˆò] @,1bUh‘Œey%h¨FëŽ.ˆ=ô‘ŒQlY˜ïßµ Û®T€wÞéÞ&$:—rè/%a2†(Ÿù˜“ÀW’¢ù»µ»Å·!Ø·¼‚õ6­‡ö ȤA5ÌRï¹Ï†Õ‹Ó'/˜OdE€Ÿ(+€:¢Y’Y9 âDä%<°$9™‚ððP0¨¤A‹,7>ö´Ç*˜í±=¦á: T%—d$ /“€ÇÆsv(¦åpöµI·ÕZ˜ eE ©¬')t½š…õ¸p.`—€à¨û¶¿¼ÔÀ!5‹ôXòOœ>þËóÇý'²«võÖ×Ö:ªz¸½©ç‡áí>B€ÞÌĹ¡‰h{¤XmÌ{s““3{Ô8xÎìC=ÐÓaøp–Bc7LSì¹sÛV)B_\¢UbfϲqÙŽ€Æ¨ÆÔ¨×‰h¯byfiÕXµ?ð=PÂÎ[·ZDàQŽÃ>ßX,I¦ôÏþ˜'R:lÿîí¼Õ2,׿t€:­2^ŠK/Ž&v¯V/ÍZ$ˆGSȪ0‚øÃTÒ  ð pAhk*UO¢”yN =-i5r³¡as B˜t2ÍBX…ð!°=Ž¥‡_)³ã™œí…¨áÌvƒÌ…øÊ½0ͲÁÂå¾,GS©´”°Ûóí¬·æ7Wõeˆáo=ôOž>~áô¤.‰_ß.¸ànwýÞÝ»mug{Ô nøÙg†Gž=ôÌs‰4ªàƒÎ÷s87}6"À=µA9lá9—ð9aTûrJj W‚[«ÔÓ©ø«tM£9™®û >ìRÉzˆý n0[Èçóà‡­RÙ×€àG5[à„Þ÷! èÝÂÑ0ÅüŠõß²?ètx B8}Bf) Ç~|êô';€G¸™‰õ® îFÉÇñ¿ ÁGHbÌ}–ü·?c«çOÜ,H]nä±½-úu|’&ˆ,®Ùð‚ˆ§(F9NHÖÅ€“Väž ÞXÆö¦˜±“ILcŒ%)6€\àšâ"k/œó3ŸËm?TyQCì U"Ëð¬O$þí7dQRpÁˆ^U¥/ìomæ3G³e ÁFs1VˆÕ›¡ÿÚ…Sǧô¡gŸÄ®¾ÝiwÛkÞíh[ÛÝÍÏñ|yàù>€ß» 0R€É9ïÁO¢' Ô¾D^·â¹øw"ÚH€˜×¢@ ˆˆ´Ì½rè­’Îç –hAâí2D‹«g*À€´Ùþ§‹ðžå²d*«–ê+4h[o!ää Aç¨pñZÜØÇ§_ûäcÀ2£û{#oÞ+šV‚FÍÇ  ï«àI9VÁA¦£oV/ÿks B"УºšÀÄìbN•hi¼,•ƒ #B pHf½Ù ñ “dÇÆ’é±ÄX2…rU85çWÌbÑ,{¡È©*OëÇDp}<«:¾ÒÁÑ7 èáæ3\8ê‹üþvûœ_2rÇžÏäŠ. ›õ%L.×WšþÄ™ÉSúØðy»êæÆZ·ÓnkÃêfÇOøx÷¥†UàF÷“¾~àùîá/b³¹é8ÜS”çÏàOb ŒžýXEüÈJH‹néA‹è݈@Õ! Œ$ˆSF+SÄFa+gåàIÐŒ(P‰êgbÒéåƒzÀlÅ+ £,š4í—ÍVqí.@® D¸¤”JFãñ?þäÜé¿üô Ä4±Þ*¾ÿ·s¶ZQŒø¶%®ÔA1Bzä_Ÿù3®ºˆ*øockAN˜×V‰* ¿…s’Ð/À&r˜T¥`651¥@k"õ<ˆ]Zrl Si‰±ˆJ¸¤¸ºÐzáüä”ï—02àòT»*p€?VôL_Hê@*}øÃ'ƒ/û q»\Ï7­|&[,˜e`m)ªž›ÔǾÉéþÙÅL`w‹z.I6ý´¥¸tMRtà¿-x;8ßþ"6;51u*fÀÚðæfç‚2à€û§ˆ`‰N2E Ü¢A  ‘=€‰*” @l Š&·TÈå …bÎÈ ˆøDY,i¶Q Ä—¥JàèpíX£A ¢J®Šø‹ø;Ë)šFÖ´ ZMàWþ£Øº»öìÆ$+ñ˜¸ƒÁO>ž<õ1|WáBòorkz§@'‚ ãï%¢{‹)–ƒ¨Js0iBj`¤?¢BE#pN²Š|ˆ u™“TÇBr4ŠÀBÀåF3ÔÂp@‘,æçÆF“#ɱD’Á e8?}fŠÞ ¨ü»Ã&fC™a¤Ðôy éáO_èKàÔð)r]¸,ï-™}‰]–óÁ¯;:^4Ý0lÔ±Íg4þÀC. »êöæIˆ%!&j!ê†7иµ½©t¾ÙìÜÔÌä€cWKðâ^tˆ ¸§Š§§ˆ ®cƾmË/C@¼x2:4¸Wœ¨Z‡‹WùØËsVU%ÆŠðj ¥ Î@qéu0ƪ Êj0!õ†Uô-ëf¹e8”+›·ÝwÚ7Þ¥ÒJj$-D¹ÀO&¦Î~¢b²@"©1’kÿGþ÷74Ÿ¶ï]­‚A ?p•©„>¿$ ÂO–‡_‰<8(IÅI¿*=¥Kàï55ÐUˆ eUNŒ€³ ‚´À ø´4«õfó+—ã ÊFéa´|Ä2š`˜´ï<æ&Ï#•Œ,á²ð›ÿýßs­ªJXòûRS-òM¾/ñ² c`ô²¯]ÀŠŸÏ=|4kù@€Mp¿ :`Ýsݱo²Ê™ó“Çý'²«îõPB"X’ð¡úp‰F8ß={Ü g0`äu5:Ø”¢1fÀ ³ƒg?¤ˆ¿Ì¯F›‚öàÃ-Óƒ»`èÂðuѸ§™À†•Ïg,Mah¾ZFýK(KÈí@¥¥ht;9o0žíV¥‚¥6Äv€¿\‚…õ¾×ÚºíщR2Í3Dàd.õÉùɳŸpª"ܸÅ[Ek×Þ\/rÁ¾Š‹q1‚ìKŽýë¡çp*DäEÈ atI€Û @œ*ž¦B`iVe™ H¤U¡ëć‚z3Ð}P} «!Å%®¯b\•€ËwJ…"Ȫ¦!†¾myá¿üæÿç]¾îû!„M ¡$A‚+Ú0·ï¥ÂƒgÛ×n2Áø…LvüÈѬë7‘ë•z£é{™ÃÇ\–Ìœ?~òüqß»i¸…´×7”íuuìÐÐÐsτԙ£Çr>€»‰àâì±#YW=7sæø‰sÇOû_ß.ÃàÛÙ]ûè£u¸ˆ3 W ÐfûA^×0.ÎÌ>кô‰{ªx6Ä_@a@‘íKxÇÃÌ\8Ì«(qȧ MêYyK6¢"h§lÛ%Ó°1Û‡â¸OÁÎ% TQpèjÔcð¶±ê¬:-ß·Ê8jÈzoì´ÜŠûÎ-”(UeæÐð°(±q((†S¤ô(1nM«`LjK!ÄÑõ¥åZoéjCåxB Tuh 1T^ãq08A Jð9Œ @Ü',Ó¡F!âOÓ÷Ö‚†Ç˜èWr|U!²OÂör™ñ¼mW@‚„¡oCÞ»võ×ÿò¦Ú+3ÁG«©µ>°H]¢…ã¢w¬¼¯]&òí|À]tBŒ*±ä5ú;jãÇ\íÂÙ gŽŸ:qÜÿúv Ùê®ßûpm Bbô *Ä€÷IGWºú¾çû>È>2¯mï!£'Ò¼ å¾6þRFUXѦ˜x`µ;v‡# 1»‡øÃ• ”­eÇÇö8”ÇŠL—GŒ‚aÚ¶eG¤KÙHšDQZ6]b¡ÃcöB¥âø¤l›¶ãWŒöíÊÂj¥RìR´8ø‘CcÉal0©(VˆÎˆm:«XCÿ/zàùñR.^Ôû F’ zÅv`ó;©Š.º¤6q‘™è¸^‡ ÕÉ1 àî^ûé¿@ÓƒŠh9eáW”K’("Ÿ`” É—Œl6Ÿ7ÃÉi?W€€-¬_¿~íÚ¯¯5j¡³|Œâé%•PPª˜×èc‚CÙÏ..†øVýÍr¤/耠W?2î3e2{îÌÄ©ãgŽû_ß.Ç&}²³µ¾¾Ö݃@EVxUSý”¯muÚwÕ}Ï÷¤QÞçòˈµ8‰¸oà¥^y¤0*?¸=À ê ˆOÆYf@Ø×®”Ë–¼å` Š•Ï²ìVÊ¥2.  ‚q „Vb‰‘×â®_Q¥M¼bÑ.-_uÀ,Çuˆ»¹ åÕ²9X  j±9‰0™Í¾Jµl” Y\¹8q1,n©XtÃZýúoÿéŸCß-•| ó4‡…6®bv ¾±Ÿ]ÜÔ72ù\¡X(Cˆü·²²zf‚BÓõg/œ<=qjøuí ’ä‹8‡¨C[t°æRe$‹iSí¾çûFQÞ#EYÚ4UÁ3sq‰Ìç½ôÔ£ë!Æ€Qò˜öÂ!Ñt¿® ¬å;>BÁJ)›-€I£ ß,»nÉBFÓt‰„·­ Ýv0àúïMp¹eÀOÙ´‹øfÛsMóÝâ-º9*™gÇžEÌK[Ó¿x!• Ø„ 7å?ÂÇX„àÆÀ0 ¦‹,gÁ .ëRTÑ×á(s*5jð›¢KUÓÖa5ª­Â Pi…Z=Ôôø‚"§©ô.-7¤.1žñË–™ËŽgÇK¯)¾S.dž/` X¿þOÿô/áéÓÅ,2 Õ4Ñ^A)j_À6€ýì <¢Ë£ãDz‚ÿ5šÀ÷FÞÀ©ÌþüÄkç&(~]»‚Ð÷%$;u«}oK%2ϧ¥ç$t7ºëê¾çûNÆQÞÃEYÚÄì£%22 ö`=dÏ? ÀUkõÎíhSLÜ•ð6bNÇüÐ>öÝ2xK_IÝi‘ÿ‘‶ 1а}ñNKûœl8éh¸ (“¨‘S©à6ì´Ù.žŒÐîܰ°£Íó, ü÷ªo¬µZ·7\»@+±Aà’šÆ²è˜áÍbF‰…mLžOÉÇ‚húÈ0`Ž‚Á;GRXDœ„ !œ(câE–°² `§.̢ ¢JKA¸¼\o¢çýÁ P'Р®5êñrU °Ô/§ÓGE11’|kÜwl ÇáäÝ¡[ÊgŠpcW-^ÿ͵ë!ÈÛ§üAA¨F¼BiXÄT·›ÍpD”ãÇž~<áe³ŽS½ *Ñi±„´þô©3çN÷¿¾]‘ç}œpÔ£ˆe#‰‘ÑC#Šâ3>Á’÷}ÏwÀ[ͱçs§+r³{?Ù{¢÷€/¿XDø)Rü>·©~@\¢óEñi½+K®ïÚ ã;\ê–ÖºžÌ”º@7€:ĉ¢F <:$µ‹…Îx»í;])Ø@|~k£E[ˆßʦAí‹ø‹ R ¹Ñ¦Ì›o[¸A ©ÄÔç‘h=dPÝh4¯@Ø5ÙJZ e>Ú¯¬`]´Bç!à:ÜP¡åÀ’Ä&pß—ëšÖlÔþÀk Ri1\ˆ†" i~t”ÉüÃïÓãxGš¸ mVrP‹¬,×êµë×kK!ˆ|?"Úͪ€?”äøa}?»o§Ò,l@à±q @PÁZj,.Ò…³÷§Ïœ8{ü¸ÿv!r’­ô5bZdÙÄ(«É~Òßê¶õ}Ïw/t{PÙ¢y—æg¦æµG#ÀGžø€/Åë8`?Dßû·=Ê€*²9]Tó+t&iÅQ] XÈ6Arãã9ÃÆ‘1®cŽ,–J–m¹ïï¯~¥¢µâ~“è…l¼Ûi9”¼Z˜X¸áQû½Í›&F“QÉ'ΞŒG÷ QxÒþçÄݲ7oÑ>¦–W©Ä{…T°­)!FµYC‚ y§a)>ÞÊ •À˜Ñk0!F]¸xin¦ òXàÙT#ÀÆúËõåè!háåzõAL…í›´J#{&$žE‚ì±;Üä– 9Ûm¬Ô–—WêË‹8°ÍW£` þ5e ÿ7^ÌXÙn& IDAT_ayÉ~vý_y.ç—ŠÙ °àQ ¢‰jš@| ÃÍ‚Š]q8?5<µ*¸ÐMWéFàŠÒƪéa"A÷ÉÔÄÉO¢w K4ž'¿UÆ‚ ÚI\ñüH,A<âí<0¶°3"ˆ!"@"+bˆxEä@#ð]À$Ö,j—æf/ÍWÏbϳÀË©T*êa€[} BL؈{!ä(®}]’Ìò¼˜Îˆ½c ãÊ•͘§O‡áâo¯__^ñOûyß—úÔI´¤ c*Ë<ñªîk7u´8qq±ÚļddT! œ¼.Ö¹ïOŸ ðIìòÏû 4 ºW׉ §Å¤À*o÷:ßÇðKÑø%ýr<àû4¬hØŽN;1¤@Áߘf<"РÑ™ñ£Ù‚Y†XÃ(Åb`#"5U¶šà¸èè…87j'"¾«Òµ4·bâ¤B·§þdzêôé_~ú)xaB¸”B¤t3΄ØvÿcE‹»‘¨Á‡‘Ý*p%ˆÄRçÁ:0\ W $. Ø „¸P¿´pqêBõÄôù)laNó*ÏqQ¿\’PÓBuåò £j´nPÖÞÀþ+žO0Y‚Ôñ·â$n8{ 3uð¨qý·oþ°áœÎû2Ç *rªI^Žòº4¤’°Ë¦Hè[fdoÑ̯ˆ)‚`¨ƒ_eÿ8à³þ“ØMŽ"UQ„OØ•ª <­¿×ïüÚÇ#Œƒ¿[è[œ#O+ àÕxŽMË‹¦Y0J&â/ÌÀ;T2b'£Òá•f î;¬GPuµ§®H•H·Z± .¾;õûx·#pÙÖcݼٺUjÑšòɧS“g>%DJ(Da8¢°Iòîª_Y-Zf §JWœ æ!¤aùÀcÑH 鎀ĭ&u¡:j#@BŸ#Iè—Ź‹ 3¸cúÉj€ÏWY…X^åÒÏ´’, ’:¾ pѲ •‡‹‘VR’ȹl‚-„ñ1¯„ºÞ ëK×®/]_\®#ñr60&J¼  ‰ ìp$×AvEì’eXE;?þ'ãÒl¬¬„Mc('Od—æ£\.ÑýéØžß8è|÷ÓƒIø{ãó¿qÐôüÏ0€vbÒÒR_ß eѨJ¬ˆ¶œB>sôèÑlÞ0±C$ÚËËS-3@@¾¯ÑIn@Q¸Ç€¹ãFÁNsÓ1\Ý+´.„uƒ˜©sŸbG0+`œ‚ßù¨St=+Ÿâ»®âªt0H•pìÚÕ+Íe€' |&T«Ó@lX“¯‘IƒFÔ´K³Ó³ ó ³Ug r8™Zfƒ¸i^r³Þö*¢ñ@MIÔ+Š,]†¸Qàx&‘à¸d ›Ó1uCEÈÒrJ!ÏsLÑ„\W³$¸/1ÇFÓÙ%”Q=ˆ¯3‡#s$A´¨+°ëŸBü=‰]N€pP•ˆÓm!áæ<è|÷ÇߣCó¿Úøü/2 ]°§¨PÔ€% ³Vâ ÇÈå3ÇŽËfrVñA‡ÂW S€:AðF@(ŽÄý WÕ0…Lûm[wÁ´Ì·½Šïµ k·Š/zKȧ“Ÿ>Ü—©I ¹Qñ*ÖM£ˆ|çV\{°‚}é~œÞaq›AÌÂp˜ 'Lb¯õ~½zi^E5ƒÀ’ (à…ÙÉɹ…Ks¦ƒFÀHšÌ|*`Ç’iPÀ: Bˆ¹i˜¨C[UÀe]€àš¦9,‚*­nÕt\90Ê\ÈÉ+´=¯¥ˆŸ$êÍ$)Tö\Ú—Û%ÔP|)wôˆSÌX °F[gÀ®ÿKŠ¿'± ôýû;T‹`pOÈ`9øÀó=€{8|€_#ü½ÿþª¯«>] öUÚ[¤éžS¶­¨ÿƒnXèXFn˜5ä¾"EV¥" P͆­$à‚[tϹÁ^qFgÃ4¢Ù~«®Ñ*úž{³íY«¢Däü§uÃ#–º•[¥›-Ïs<7«¦™˜('¢—Ri@“FÀ…x÷ÓÁîÕ¹¾\½87ƒ5bXÕ…k,J°03sq~êÂÂô…ùºåH‰ ¸d 1ò!D -ì«’8­Å2ÆB²&@< Á9\ ”fCÙÁa`X·ѲD«4à©‚&ÓÑRد° “g¹$/b¯ESycE,î¹]‚¿ý¸‡t‹þJc…Ö¤êɈÁžÐ®(É£ÚÎýû÷·ï?¨C@þ£K"(IP"|’A¬xo[źc»¤Bö8hLße’ת±Dg+'‚«Iv±Z9þ<¡)@€2“H&ƒ…¹ “Óø_ÎOAí/ê¨x&0I,G d! PÄZ¸—Wä1>Æp©w€Ý_’•2ŒÞô=øóHݳ ¹¬ÈOcW d ¸ ܸ÷ÑÝ{›ê}ø²³¾~w½£dw_,}ãQüõUð =™®‚DÄÆt8ü  õ³F ‹¤qÔ}Tƒj5f‘óEKÈ)‚ ®W§/¾1 ÓÂC¢â¹»…ÙäÕ   1vç€ÊæÈ§ç?Å9˜’ÄJ4 Ä .‘ÜúÀ'Ë)ã( TZãíUäv“‰Ý@ç°•YArwl·ZÅåGº¢¢]E’))¸0 xj"Љ iA7vm±Ò5*'´=¬ª´.š'ÄËœˆ1^¨ª AI åˆ)RE"²Å á´/ÃåÂ+W—ùŠ˜f“éä‘ñq.:À®úÁÙ”#I™4ð I|‹¸ãk)žÊ®,v77»m`{SÜí¬¯Ý½×Q²»?˜žäøßÑè‚€H|8MâöÄaÕnBcÈXãdG7T¼´†Ê$‹¸„œ'þ|]dÚûŒÆ¯h¹ grÐ< Æ~ ‡M³å·¬OÏ}Š¿WàÒ#ŒŒo!¥aI3)®k¼kàŠ ë»®C\Z‹å`Mê ½›Hüz, ¬ ¸!üvllì7i`@B9š¯‰œœJsó³.¸¬Ì¦‚ÆòJ] öY$ÂFSÁ™ÏZcq°.ðÑ)%:V‡ ^Î TuÅÐ- ”5/H%½¨ë‚hÁé›~"„ˉպ2Íl\ÆüZŸçÆÆž>ÃqØÕd|eœL[³l u~!ôØÑ¸dŠ91¬„CçÂXF,.ÓÑÍ%5Ô–*•À¹‚å` —vtçÿ€UéÄ{¯ËZ-ÛŽç¶|»â®š¶¡\ávgÕ·n|ú)Î$E–Is¨@džÇF9ðÄ[ f¡lµœ–£y„¨¢}Z˜0N”ºz¹Ȭç£&öúõ•z­:?3K´@B¦†»‰K$Ä`áÒ…©|m ðR —?­†Ë õàÚçóÖûq°©ÒRª«0ÁYbxø ÂG˲”çÀ$`@W—©¤*㇘¾ßÐäË}ù \ÔËð‡“„þèØÑçî»A=OHbD"nq˜Šµß7¦ØPE)*YR1ç'É[NZÖ‹FX‘™àŠŠ:¾,ƒÒrýв(o ampʱc©슜 r—!®~Ü$ža›V1—1 :ö§² ±1øàN»³…£R;ÛÀöz§V~¤d—b&óüÒ‘y<Ò–Ûpæ ˆ+ö¨B»ìc,ž€¨"àOÔ°v›&ÐÙÆé0‰ä*•Ê`x€«Á8­|ZÄò4ßA좃ùWù¶ayP’ !‹ÅÐO$EP'€œkÛ¦‰Ïv²³äc•pœ¬õkK À½ƒ"XÂÕ´zufÖéòšÈb‚ù -…r<Ë!­»Ó‚úlÁ… °†Ú_ Ñ*^ÑxÆ8[™V,Á+ ÑY‹²î(‚¤›9—óõ´¡h—üP•jðF Io\ úÒò å Aø•”?Ê`Î4…pö8^\Kî?ˆÕ§³«h|*Ó‰6:¨ƒw¶6ÖÛîÚ‡÷Ôƒì"þ²Gþä?ëÈ< À÷)önG=I¸­‚NU06„`í¶FGAà…-J´QM¤ŠmØK¥’ëSüá݆ÿSQ¢8=8¨†süx%õÀÞò*[,î€~‹BHŠ•¤jV"a(ÀI)–¼k[«¦`´°ÿÿHŠÄüõkÈ Q6[‘êÕYÐÀ‚Ž $pWA<® ¸`Üu§ôâFÖ£iœoµènöŠSXtà@@d\]‚Ë¡´Ý2¨J#,,ô‡‡¾êš  ÓsE#êb‚/Xl9°LÕÃ+ʕ朻‚R éršg˜ƒìj°~9_v­üxÖ"N!gYåb B õ©ìª*Ï ÿ C¯»þ‡!ܹTؽ·¶¦dð—?òmz|ë[Cߢÿð!~¤ßüöÞCúÝøøÜ×Cøwè[ß~®Æ4ïD.øÎ*/ëtUMƪÀH†THT§ 1YŒD©‰(–qP´m!uJ2®Åá QSq_CZÐ+´‹‚ïZtv§›7¶oWö"„å9`=–ÖcMPo,IÄ4V Æ-Ú¼ªFkÀQS~Œ¸Ô¯Ëà‚q~C*¨õ—àOõÌÉèk!Ä 2u"&‡ÓA”æÁIR²’:`ïEƒ¼ñˆþà§Ø‡Që/ïåû²±P£x°Ü [œdÑwJ’ż”Ã&a»a„…l.[ðUúiUƒª^ÛóŠ(]~ã ˆ°$ùWƒy{_j—$G€ÿ ™2øàlÉ!°Ÿa,‚òâ)ìÂù RŸ¨; |·6Ö>úèÞ}°¸»±Ñ9Ðî7¾aGüõ­øß×>¾…á÷ÿäùÏçiEôJ>ÖAkt˜"Âî!>‹6µVVQŒ`MˆFÉñ0á†}¨Cp17J Äí%ùÄÍÙ–ïÅ›,Tl7~o=·iZ&QÂàú7‡e0$K&'Èí¢a[yäLÅBÒ%BøîÖꯩf—à«Z 4ð4­¨B VVÂÚZœ…‹Ï’4üÜìèßà½AÐLªËÕ þÜa%B¯*!w _š$KW|×e‡.å‹¥°l˜à63™¼ÿ ýÚßýèohÁWä¾Ò”úrC ™6é»p—ˆÄÌåJåR¡èx¾[2 ¦Q°qÌÜÓØ…ó¥í tXê&ŽŒE¼ø£)é__ìo÷e À#x Áç¡#Op á_øðF%Ñ­;t Z4– s}XË >¾YAÌáýe¿kÀ“³Ñ'ã5¦¤S_5ZÅJ'*¤à=Näµ¶¦rì Q+øTRvWõÝÛ˜"ÖÓ)JH£¯ÔR(ßµQú‚VT„ž‡#R+{y@DˆY@ˆrýr]Z©ÎNœ'¼ªhŒ'¦‹©áဠËE‹ 0gÙ„‚õ2aPG"l4,< a?ÎJñ¾Ã8 .-4`~­Ï+2Ä¡iæó¹Ìx¶,Ålf¼à+«¼*IR?Úå,”šWЯ½¡MYâ° Þ…”Í|Ñt ÃÆþCÛ2JðùÛ¿QžÆ.ž/|k£½ Bx³ÓQ·;í{èÁÿ‚ü !ûÚ}€{ø;:8âÇG|~øÛ{O:ãïàçó_Â;ú•P*ZÊ Þ Dü)¸¬ª·îwl#gÜÑÁ+(gÐÈ.UϘßP貨‚ó14ÜX{0 Ò•‹;®‹F>;~ìØ±Bè”LÌK¾(J×ÇnpþïþgÌÉá‡aò2>Ø.¸Ý\±dòV WË% 9Ž{õ)쪸o·\îf÷¾ºÝ¾×ÁÁ©@,?ßßîðw438ŽFßüèá§à“öð÷xÆ]™æÈ ãX@u€@¬d¯8åR @hê:Ýxuµ%ƒ ¶AècOœ§(t¯sœo/ ÷õŠf£R‡°b—:¶­ø ªe§LþòoÛ†yßCÒбQ1—Àº¶vÊnåÿ1JeÏst¨Ï +´­˜Nx‹ìæ9.Ïå°Ã’—RA•çe™z`¬k1j:5œBÍK,ùV9Yåi’òÁ‘ø3š¬/_´#Âý4Ø®þ¡”¤ŸJ¢ðJŠåøýeÛ(dÆ=?n„^©˜Ï¥’¯Á¥žO%S/éÀ=Œ¸˜D*‘H`W`yR)¬‚°ŒS¶éÐ1 'fpOjW×~v1 ؾ×í¶××ÖÖqX~§Û½wo½ƒw¢v€Ý=¦à°GæÈaüt4þÞÑèKûpü9~ÒQŠÝoy,Wð‹‡sÜYõPÌcÆ%*ÏDaQ M´Š¦¹&f¼Šë9^I± K–e 5¡7¡}$¨@Ы{3RcšÛåÉ\Á÷M—dÛñp‡«ÍîsÆ<õ½ Ç1ÉhB¹.qÜØ#McÎlçKePÓ¾W†_ì Öi>º‹Ž)üu.pAÀqBpªú*÷juvj’ð˜2Tðl8”C•p®}ä@:ÈÂúÓ ðƒ?îb]‰xp‘¹Bìz¤û…bf—ÿh!•Äqz Bp0,ðS6“ÍùÀ€ùl¶XÄ–t™N§J&y!E‡ß‹<ÛC$RLšÝ×®†v‰W6ÁnÞ(ÓÖæ$\ {"»Oí êN@×Y¿·¾Ö‰¨Tp§«Š2Ý ÅG¶ ÁÇè1"ìðPü ¾D¾³éÏ3ôë‡ð÷˜põ΃#â¶U•î$² )VÊŠ[v5Ù-;¸:g˜8¯’n–N%¶Vað‡«y¨H1Eݰ6hn1‹“œm«Ž#ïÈ;¦)Y„NÅM‡7Qò*ËŒ%¸h-X☑‘4o,©”ŠÝiK5œr¹R7¬û IuãDôËÿçèócÇ96xm¾šÏQŒY!MŸÇÍ’Ò"3ÇÏEIü±®W áY¸(šˆg¸ÿYprÀ¢ùB.7Ëç_Î\š†¥r²59Hì\]xõ'’d+²o’‹áù’âf5Ù ›J'{ìØ¿ÿäF ´¹…ÓÕsS¸t‘lµJÀ%)œˆWÜÛ?*Tg_Ã$º*%󧥟*–ôÓb~ÿ0°hR:™ßø´À+yM1,—MýŽeqo¥ÞbyŽÿ‰òß.A´–ÏäJvoD„MàØù•W^æôòßÿ×ðn±½á¡—¥W†‡þ*uÝ¿Ã* V”5†¨S4/Ò"•þašýÙÏ~ªþü§ÿë+h÷o. õ‡^ÿŠvÂý5¯ítµÍ{ªÚÑÀ¸±®m¶·åŸý,>_~H|¼Ý‡ó€{Ð: `ü= ƒGQ÷…‡ûîOø9"qÆ„F¼(Šz¥RÁ’ܪˈŠós„;ßó4¸åX†eº¿‰¢ÒÝ—h‹¾F]p,B²íL'ÛÝTgXÇê[ÛS…ÜLN3çÌ\щ¬'‘K@ŽK&YR|ggÛ°ÌŠkt²ãìäŽÒî´;ÃCžx¨\Š·kÏf2ãL°dþµ…3ó¯]ˆwêäÙ‰¨O Δc%¼òÿ¨ñÓŸ *ÚíýXІ‡Tñ*+r_Áî«?â3)`= ½{÷64‚ÊíÎÖ}²½ÿò»;IDATMÆÈÏ/¿o¿'?Þîcx$¢Ä£4$´‡Ž> C*:>÷ð!~ÞÓÑøÖÑß¡øK1‚g„€.E `3þù¨Bâ ðÏtœC'aاÉ?ÍS£MÔé¦K{1 eÍ•ÊÍœ\ì·1~,ÛeÃp ª;€õR*ºWÑà\§Ø·í÷¦³3›ÍŒo¶§»y¸žVÉÙ=–ΦRãGƒRÀh:ÎΜ½H´4Hi­:{BÒùC p9Ž)ŠÀˆ³SðQbY! 3›+ÿV$ˆG2“ÌÄ.ãRó2Š¥ÐO¥Òét‚có¯ðœÍ°¾W*–KÅbÑðü0ôÁ?r9¿0é§~“z,²‚><ô¸`Af‡‡žÿvz»ŠÍyâô91Êæ\[±Ž,Åéê3Lê*µ‚=ŠIrÜ4Òv¹Âèƒn·ÛÖ4`½Ÿí•›3éQüÛåÙÇÛ},ÒD3¾ ‰=ˆ£´ËWàj´9ƒI“0ðȦbäN*‘`Ôø4)]Ï 0G¹çó˜6nè** tuU<`G7àDúC׌«â1ÜfÁv-,´ åüxÞÜ2JÖ øòû4îc8^!v CqÇB¿p3ßÇ`q3sl3ŸÍæM –ñî¤5<4»Ç€ãl&••KJ>PH’LÍ,œ¼€—(Õ 'Ï몜ddÈY‘/æ¹Bõ4–} c££_(”ŒÌó#Ïÿå±ÂðP‰F€ÃCÿmü¯ùE¶ÀýèÇ«R ¤%˾ÌsiæG?â-Qò]?—-i[´Urp¤. ±”ŸôáoádøëÝ—µ¡øøÛdìÃß>|]‚«ApÂàOp;U@ Ké‹o&Si°+ü<¶÷ã¿þá_Ûqô+Ø•R@m»ÛÒ“ÇÙÙÙ!8GþŽ‘{BíþHxõñv @ša¦ËPÄ!3™Á<ë+p5žÐ»Jó0ò!“ýÿÚ»²æ6®+­g"AÞ7¬ÄÒû €d¥jªÆ‘e[ªUq'CÙ'²=v$R¤¶ÇyJõó”c¹¬$|ÊS]vMc M/?`"›? ‘ÞçœÛ  )KS¡ÈÍOT÷íÛ}Oƒg¹}ï¹Ù\ÜWìaÆù=:„y¸d„VÐQX ~t[€`|q‹ãàÉR#9yìJ¾áú+šÛ™´íU}Å4þÛpì-{-øvœ ƒ”¾ ÇK×d¥È®}{ L›Áœnë#0äðÐo%¡­ËŒd{¶I’b•Vo^%é' ¥‹×V•ÎG¶Wæ-ûâE_½Ë1[JHj†aÐh¨ÐÜyôÖ?'Ý0t~ÎZ ç„ÙùiöûYy~AšSdaûáÆöÒdkÒ1ZðÅX–Nè¶s}ÇÄ{{è7¹ÁÞã'|¦f“ ÁÈ1?(w{cû%Ì(Á±t.›93‚ŠN°54”¥Š—Ù ä>’y—8J¿i>M.~^žë*=9Ñz*Nþeyºôåæ~^B¹Ì»¿Ü˜€;ìëëe®ÅåZ­Û!]MªkIÕ^ ¸'ÁÔÝ8×jø´ƒZLp.‹Åuwˆ:WˆÃø"G2')&qY\¬z‚¸8M ånb˜¦«oº–¬áLwom ]IG¿åö´Þxék|LÄÿ.ùöƒ/´Ï_w¾Ô7õææfÍ7ææçŸƒ¸ÒÕ€…Á_ÂÌ'QA‘h\ž°H—dE½½v÷âU\”Tb£°àÿ\‹¥à"É‘ F™‰þ乊ÿ'ÇšóÁþ²b »@p³™ŒƒãØi{_”¦-•ùÞZœe´€KFza€€À1u°á]µGRxnÀÏÔ†h.—KËê0eàþñ<Èï½â{²\0²Ä1<›Ï Ÿ9£p`³Ìaºq H2Å\qÜ´+`Û¹ax¥ßüá䪕Xë‰bOëa:AäKß~î Ê“–÷—;HÀ2ª¶$ÂwÝ}5©NŠ{ø·ÃΧÝÞè@\µðµ 1Ù|ž°p4KQ@Áv{’¦/.çA—صçe à_G?üa¹¥Ò›$‡ÏR9jtdxxxˆJ'‚o;õÁ”…r-BÂC°`ÀÃùž*>/Ç–¾Þ$ËÔìh½~ ÜéTq¹ÄåjŒ˜fƒû^}­6ÐqódN„aa?b}?ˆ,² 1Ù\ÌBŠvHL«›®ñmYýÊwů<û6ÐxË Ú’ï{`ÐÛD뉱…°³ëñòž VÚ~åˆíl êFφ›Mommu_ÅY̼³­ø@@œÚT)–Ô;7ï®áhYˆèa íB+,”Úã…hkó‘%#žMûé,øíÙ4÷0‰þ¾à{¤Åñ—ÞP.oÿByb‘S&'Zá8x˜àÖQ{on,^ DV˜áŠ˜ÑK?ƒ(’c³i9Ȧ‰Ü¿Ý;÷¹¸:ž$€šbixæÃYø³/¾ùæÈ-ÊùNŒå*‰¼ yO—Ë)£ҷ_ã\oeGëÅr…%LKA>oòûï‘ÛOÀý8õÅ ÃðÓNˆ=ÐèâJ²r!.dÛT’/<›£ÀO´;„1'Ðü‚×À°ñ„^†Ì„)qJÆñPœ””ø€2è0? Ü•Mó»å¦ë’orà ÁŒG ò8¦y°yj”¡É 1LLcšúf8ŠôCìÍÌ 5´ÕäUœž×]Ž1$O "Ó$•Døs¸{}ívTü6’¹H]Ç#Ó *¾ Æ’*‰ù(e@FðË -Q±ð¼žDÁKÛ’*-/-,Js ê’(]QáÛå—¦å¿È|œ$“ä žœœÙ˜a7¦Îc%ñwÓâÜ,—™‡ÓªÄð¹¡û%6GäžûðüÓå&a™ß‹cZXaÜÅD^)yÏ$×,íÁ^¹CûË%ÔžN¬g…¾Ëgú$&àgˆ°D¦€€G³0_(Iyb…‘‚ 9°¿òN%]8ô¸(˜˜…,Uˆ=Ø@À®h®‰¾kÒüÍuઽ…݈@É×­`piN hû¡A‘y6GçóÙ1WŠSZhþïxÞ¦f|ëüWCO4 O:,¶]ž‰p¥¦¢,É¥õÛ+ï㊅H¦#‰Dˆz‡~áqߎÈY¢ä•ޏL4y£ˆ4m;?•Ÿ|¡¢¨¾±½¸$1Œ(/+ sâ¬Åo/pü|A]úÝ2?/ËÓÓߘ·è9UÿmJœDYfpÙÌK—§4QædAÝxô˜ÎI¯¾vïñÈup´‘P:<¹1»–iÀuÒCóH’AVÊgjœ¹«DRú—Hw^©$æXˆ$Àð#Ç€(ãÔ×äzd¡É¹¦k 2øÏNAL¾ÛhYÍ®uc ×ö½ ðÇ;ãíñV ”ÉåiI`i‘§„<éƒ-à RP•½ú×75Íð ò ïz–»ùu§ýgÓMÈ}o—dÓ“å`!**2æG¹³ æ·0þ8p$™ç"a$âr‘˜‰B§0&¥H`Ì :ÉÃ`’9ŽÖ,ÞżưIÿ— -(À!Ùš•ÝÙEåʬzE¥à÷²¼0³¸°=/ù–©(¬!ßq½ûYaZá*Òô‡.ççø±êhœØÜ£ßÞåŸÎŸÿGöÑG¯Œ\V+ ÜûDî¹ç/ x€Ø5+|Àð“0 šÌ„—à*IES¨8x8Öƒ…Q]‚(q9ÐVGÆàcˆsÎÀ´ºlp0khrf7Í—üà¾zCûâ:s­a~iš¶\·ýoœ@)á~V(0´”—r|ÜWÐÅD.ÖªöÀ² ËÞÔ­ˆ‰ßL4 - œ`ZzÞ Y˜P½{ûìÇÉçV#q8’†"a8Ê¥#ÍfpÕ†° €1 F×ó¹: ð±\‘åÄ岫lóÛœòÆ‚<³<»4çÌ€±m™ò’"J"ïŠ<ÇÊ û÷襗^þøÕs¯Ý|þÅ”{ªu€èŸ˜~ƒh@pÒ7@˜Դ­!ãì‚BLˆÂ0²9Yhýõœ–Óò£Ílß(åòTs¬NÕëùº¦ÓÝaHsâ<ÍP´ã`ƈËEößçm^Pþ\„{ú4'SƸ&¯"XÍ‹¬8õú%ö^6›ÍQCüícø:_ùøÕ×Î_€¯Sÿèü‹)÷¹eFX¾÷Îaàú­Ûë«ÏáV'r_`¹Së@ÀÕ•ÃÀ ¸áÚs¸Õ‰ÜTîúíõS7oÞ¹½~8¸uû։ܹýr×:§nݺs‚nMžº}çnû'8Ü›Ú]±ú®±S{ïðBC¯ÔÌr(äŒ!ßî°Zí2°€È¿„€è^­óª†c4›cˆ96°©|ɰ>3‘ñjñ¢ð°ŸAòâ=õãô5'ÂAucÍ&¨ <¬]í#`—;> á_YÑ@Ö©§•›G­Ì üdRŽC¥(‡˜»ü™Ó€<”è 1´Ä®ž!³³“&T*¾Ts µ–MÓñÆ!–<9•I¥ͧÓ;¥íÈ#mµLz§fç'óÜŸÀ¡¡YêhšîÔAj•_ö0a`€1ÿúøV¹2¦Aôâ\¸pµY³ŽÚ¡=8¸º›I¹® ÿ3)8NÀ†”2è„+tJŽ»-t·[Öw.N.s“C´Ò©=7Š‹;òH3LüÑ­ŒbžÓ¯}°ÆÊÍ«.8µrY«”ßЀ1ûØúõù€oÅ«:XgòÊ…«šƒË´x™”áyÙcÁóHÉȤºÅlŠêV’FRF¥åÅÍ»›øÔ(6 z únDЕפ2üìÜÁëoü{þ¿þ¡Át´«^ùÉY+æRËDÛ™ý> 0°Ü¯°YÕwö¥w›•ÚQwf ¨TIYV?dOÅÙˆº‡¸ ²ñœÿl¯9Èô®ÃËz%¨Ç´uÉEƒ7ÂÖ=yx °¬¿¦¯œ ãj•æ»/EXn‚üÕ€ &üëïŒu`€ïTšÞX¹î¡ãíiÝ>6HÙaQÄ{Ü„©T÷·aötJáN£äÙí³ G AÛ'ܨ'/ ãxº¯¦Þày((–—Ô`ó¤A’‹àÈóƒY­™UϪÄ–6ÞïxfþЫ8$à¯- `Åóê5Ϭ×4ïØ€Lgî“cR—ìGN÷êvµJªúKɦïlnˆÝÕ¤3 o@F'‘ÑßàPžÂá@«ÕM¯V÷¼ Ðúu—€@3sßwÁ]Œ¯9>+µF¥îùÎ<6ÇU–úŠ8*2.ƒ ,®Û¹,¹”\×-ûäto3Þ«ÞÓ'¯·ëÖôŒï½ë‹`ŽW¯4jåªî;×öŒ0p7€€+nà5ªårÕƒè. Hvüc\lÿ˜+ì1bÚxÈ¢†¸+}©Ü­TZõZ¡g6MÓ7ÿ8Т{ÔŸãXÈCh¶¼ÕξT;µ7cº±òþ 7ŽúSS¬Ü°:û2í—ž€Ä­‹IEND®B`‚fheroes2-1.1.6+dfsg/docs/images/screenshots/screenshot_world_map.png000066400000000000000000007476241476115357100256750ustar00rootroot00000000000000‰PNG  IHDR@$KäçPLTEüüüðððèèèÜÜÜÔÔÔÈÈÈÀÀÀ´´´¬¬¬¤¤¤˜˜˜„„„|||ppphhh\\\TTTHHH@@@888,,,$$$üìÜðÜÈèиàĨظ˜Ð¨ˆÈ xÀ”l¸ˆ`¬|T¤pHœh<”`4ŒT,„L |Dt<h4`0 X(P$H<4,$ ÀÌü¬¸ð˜¨èˆ˜àxˆØhxÐXhÄLX¼@L´4@¬(4¤ 0˜($ˆ € xpd\T L D¬àœœÔŒÌ€€Àpt¸dh°\\¤PPœDH<<ˆ04|(,t$$l d\T L@80( üôÐøè¬ôàŒðÜlìÔPèÌ4äÈàÄØ¼ аÈ ¼˜´Œ¨|œp”d ˆX |LtDh<`0T(L äÌøØ¼ìȨäÀœØ´ŒÐ¨|Äœp¼d´„X¨xL pD”d8Œ\0€P(xH l@d8\,P D8,´ôü¨èð àè”ØàˆÌÔ€ÄÌx¸Äp°¼d¨°\œ¨X” PŒ”H€Œ@t€8ht0`l(T` LX@L8@,8 $,$üääôÐÐð¼¼è¬¬äœœÜŒŒØ||ÐllÌ\\ÄPPÀDD¼88¸,,´$$¨ œ„ xl`THüäœøØŒôÐ|ðÄpì¸`è¬Pä Dà8à„,Ìt ¸d¤X”H€<l0\(üX Ü4À¤üüüÌÀŒŒH¤Ð”¼„¬xœhŒ\xLh@X4H(xÐhÄH´8¬ T¼8¬@´„àü˜üP䤌Œ¼ppœTT|<<\Vî¬ IDATxœì½Yp$×y&Šg°74PkîKU•YUY È*4ü2á ‡¨Å1áq¸ T垀r·zCwk™o„¯ck4–ǯu=¢,Ň¹/º³\["ÙäÏØ”äK-Ï3 Ûã}¿ßÿgVo”ÌÔ“M P'÷<ß÷ÿrNÎX–eO|²,§Ý°Ö‡•J•¿·j•Êâ⥊ÕlÕiÍzÓiÚøͶUo`±­ê%,«Õn5êuú®Õé¶©¡V­PK¥Z³ÍfkÒßÇK¥j㈵*•K‹‹Uì²Ñlw»í¶Õ®U«õ¦e·š—~áe±j;|VõF{eçú ,W¯¾ôÙ;&¤Ùì~ÜþѶ·ëõZeñ}¾õ¶Uk4ªè­f£þaô¼zÝqÐéÑÅíF»Õ¤Î]k>´8MîõÇ ¶u§QÇÞj5ô[§na§º¨jµÑjZµÅKÕ ƒ;A›-Ò‚3ÆšS»Åíàƒ5Úífͪ7›õÖ³pî_³ÕnÖñw…Zp­ ºKtp,u‹®N¹é8u€ØòÖ›À%­_c{ët¥ÕzÛa?@¼5cÛM¬ `;ñz}Ø>n\½¯°àîÕÒKÏWG­&…³¨f'AôP›²ÝKDËÁ‰¶[õº]~O=Zc‘þªÒM§ûF7·7/ÛšàŠ•ñE§ƒkÅ©‚hjŽS³Z8iðÐϳðM¦ã/Öìw¶NoçúõíéòÙ«èè”è·´íÜ1§lýs-5 XÅÿèåJçCéy ôm§T©ÕÑk‹5«ºh5Èúñˆ5ëv†âãóF'kPÀ €v 2xÖêNlp©Æ!Ѝo0íšM@ûxÇ ‹Vmâ2¬ ·ƒåsøpn=±Iö$øAðÎ`ô;¸äN˪,Z8¤Ýé¶èÓ i0ßÔŸº4tW*ÓÛ Êlwœv‡ú_ó2Þ¾z=°µÔq·´íÖ1þ3«È ò-™,{Š˜”ƇÐó0 2¾Xó–Í(mU›Ç8%ÃǾ:ý"c˜âFSÁfý ãxX+´ÚŠÅЊ5(Ö§Î ·Ô;¤µE —b±~ ëjWéÑ"ÁœOjâDê.Na –À ·ã±PÓq­ÚÆÈjòß8’Cà¨j¥ÑبnøA}¦ÑiZ[› ˆJ¥Ùi6{a°¥8ð8Ÿ¯.Æñóv}k+Ù]ºd[ÀݺÜ.¢’:D@…ùˆpW'z©UŸ'+&©E:ëV ·ÿs;íë³íY|h9|‹L¾ü¬èaÑåUéæ·»N½R±F j vZÂ=}Y´›3δӾ»s=ö†áx<>ó[è×wîvÉe±>nÿhÛI¹N­"úý¬ ¯´ÖpÐmÐA OÑ?„žG}ö±Áж-(•Â,6l’ÒÖÔ²:dÂkÉÀxZw0‰r4pA®Ã€®@âÇ8¼-]:ÎÕvNT¾†c/’×dñAUƒ j°!Á›Çò›hkz´¹Í(¬X,Òúâ8{¾Þ¸”?ÿ|ö7Î*É8¸‚ƒ }œÖg–ZÕÆV²åœÅJg)í%[É8IiĤ â¸V£æ+¸JÀߨ¤iˆ^ã—Iw¼vìke^NƒŸ?`<“/½„ç°Ó½þ™Ï¼ÔÆgö¥•ì2Ù ã‘ñ$ë7<ÂZ¥ZoÖÉuiÐþ ¶¯6[™¶;Öhtt@oãÊFdz¿ovç.žì »~ÜþQµŸÈhôe(^î)@þ£Û&ØØE ñ´ëüc{ir›  kbÀß!dÃn·)6‰5¦Dï~tY§^å¸YÝÊðO;ï»l±n“‚ÉÜj<£üª·¬)T¹ûr°mkÃUPMt•Û>ArÃqKNS >Äîå¶ým%qÔ´ÛN5ˆc§é{ã(mÏô¬öx àð¤1ÖÛÚ;$î„›ã*+N;[[¾GX´Ø=ºtɲÛ_£ÅÉÎÌW=ÅÜ|r) ަ°®B–à!´v:×?ñ™ÙÏ\oï4AÄXœêÔÐSˈmÊ!tǪDïpôÈ=#¿ÅÉ¢%O\ê :¿j¾`½½ã¥ÆðŸoÔÏpl°øü¸ý£m?é25@qò,/€ÂpX:À¿ÝÒ2·~ñÃíyUÒ#D„欗ã¨v§Õ„·ü>-ðÜ›pÐë63C< \l£Á@N9Ë€ ÑTC»ÓuNmØl9¤èÑÃ5X­FP·¦WÅ2€ì!Eá>kú5f«1ÝŠáØ¶-ô}¦°Jš¦>¶`”ã|[ø;H"€Ø óÛq܈À i2Óv\BXiõi4Nâ$»Ýd+ÞLg% ‚È[\ÈT†ërÚ_ýƒ¯~õk³_sX¹ßrj¡Ó¥`EýD¶ã)ܸû¶?÷k¿ö‰Ï|æ37&âë7nTªÇAà̳Óqvíxv•nÞñyÊ$âÇ-…CBžÖqTð†·ñ›W6<ê1IP~‹·´íÓ.Seü“n®×«Õ§?dù:(òÕ+Ç¡µÊ‡Ñó2p±"AŸ%Uá¹ü!/Iì¿ÿÃ)!éÉ!r¨Õ¤jª™ºÑ!6]–ÙÐn4ÚÍútC›Ài3J`Ãæ4«´“LΞ\Å$áÔkÓsæ»VÃî øU@2K@€†ÀP¸u?n8ÊN·Ó°ƒ¨Y«¤cÒ5'N‚4M¬úL«Õ¯÷:¶ÆÑR³ív“$u——Â`+Nž·ZÞ 1 ‡pCé´¾ò»¿ÿ•¯~ MS[¼tü éƒT?•w©Æ4ŒçðkÿäW~•žÄõ‡‰ØiM u¶j•n¡uŠ ÊàìÙPms~ç)Ë"k$H%¦é&SÇ[ ¹þÖolpÌ: 5|ÜþÑ·×8—Ô¬g~3DzŸæPF­EÑCØæÚ Q©~8=¯2 J\¢ Ž@¯AÞJ‡£TiÞ÷~ðý¿û»÷gß¿´4¥3ïM’ê˜âßâ,`£Ý†ÂbO6´hÎ4R¾ŽãøðXF´êÇÝœBL¤j¦©Ò¡F) "€¯}õ+¿ÿ»_0)$²h9ín××Jb›P^¨è.·’¨[ms4 Ùµ¿k-[ÖLci©µ‚“ˆ»5§W_n×ÛAl9Ë+QŽ“Š]ÇAMìé׈-«õ•ßùÝpÐñ´xéüt!´&ßÒê4’A, vè9ÜÀsø'¿úkx ø÷7LŸC¥šEp)Ñbïé³i5)“BnÀ±ð˜à«¤¸(cbqöƒÓ•DÔ½õßø+ÃáÐË: U³¦±¢Û?²öcaOÙò ÿ”ý®6Ÿé¡$ÓjÃÔÕ`(ÉòdàÏ÷£ç‘‰™ràÞf7>óc(i€±èüõßc ´[LŒxÊ”aeRý°Ñœ€ïÌð·˜N6¤;ƒഘȰ r–|¬.ž˜4º´F–dË®¶:Z­–á±à«_ùW¿û;_iñ@DÕf»Ûét’ N|Üæ$ŽüïÛN§ñ¼ÀÛh7«qÜaTg¬v³µÜhÆQ·Yï­z—œÿe·½á€­kõiô£Y¯P ³Í^ÀïüîïÿÁ× Ä¸hjÿkåè©,f T÷ß… Hÿ“۹Π?…i„SÍtC¶mM*ªNI B›@§ÛÅ3¨§aO;%¨4šYîçD*á9Tí»;·n¡þæoþó+ëaŒ¸ÛdëôqûGÛ>•ºSÝnP·nö£˜ v8ÙOp€ÌÊ“ÁÏ‘¼DÏ#jyÐóê\uBy8à–bï$QÈ=o$Aÿå¿g@΀اC‚ ­é¬.UØ‹à4)ÿ,8Ùp^¬CÛ‚è ”÷£J"ò"˜œTY2ƒÿ1Î(øØr*\ Ôlµ¾ö¿@Ð!pwž¯9mrõëYÌß¶¯Ûàè×+vè½ØXïØÕf¼Ô´•™jÓîtšÍ¸:lÉi´3ç¿ÕîÖí‡Eã̹°³r@Êd|ËW›MVF—² ¥4j¬èÔø«,B:u ¬ÅxÁSÀ<ñÐé©‘ßSk43J¹Tã ®¯ÂN}»N±ßf‹8€K±¦Ú¨©I`МbÉzF&qFNkgç¡uÏ»q'Ð_Ô²U>nÿèÚxðè.Ìálÿ«WÕ,Æ5Ðß%Ó€ýµÚÇÝ'«‚Éz÷£_¬çÕ‹ZÉÞ6¬LXÄ7Ó…ÃþÓx àÿþë ÈS ¸~› Jã"(ë‡5+ŒÿãLÀɆMçøkÀ~ºà[Rcü“¬©sš’íYFu…A[-"<ÈMÍæW N‹ÏrÙ>võ* ©ÔZ] Œ“Æ‹N»Ö±+ÕF·«veôL:>©pÐR«Ñaç©Õi;T2Hµ‘|IôÙuâíЉ‘»½˜= *Oädg'OÎæÆôn×) ƒˆ)uQ\ý‰sÏ)Qãúˆ:I²ÚK>}°T›e@%»Vô¦ ùdŽ[ƒù¶J5”Ä]Õêñ^X„Q¾”HŒÕâàH/·Ýé--õÐ%ºã´ ÍÕÖœý¥:ë¬Ü‚o}£±´ÔiP¤îç€BÚ­å%Ç™>–Û?²vÊèg‚|êóÁ vì“Ð@³… ß…Ñ£R?îüœÉV ¿7­=±l?èyõgö¼L-PÏc›U«7ô¼&t*ç%˜{=aèªB¦Èÿå¯ÿæûÖq.Ž•q§aQÚ K€u2K­S徦ްÞdÅß:Nnf2ƒ p¡Ùø©ç?¥Z§Ù ú Ü3Cå8dÉåö ãŒàè ïŒ+Šs¶hÌU7ÖîX«CFþ¸ò§EÏú÷A(%\t n®¾³Ž‹é.1à×[ë^€ãvkÏÛT”¶@ÎÌò(ÜŠÆN:Çpüö’{yÅq^.÷œì±Øä&áû%*7:…Sþ¨š³Áz¤ÅЉ9Ý¥åe¶Í¼ôV–!×±E‹ïà=R,YcÕï,-¯œÚ`yy©‹Ý8T Ìxæ¥Õ¦ÍVzÇ›f TÀƒeyyÙuÝ•åwùÁ7½e·O¿iYqÑÒ]é¯,/ƒþÇím;¾]Yž>,ú´âö]4œz¬<ñ•"†n‹ýÛ¬çñXºæ£=¯ýôž×î>Òó²þ=íyutòV«›š¾F"ÑØW¯Û&¶—:'˜ä?{õÅjcš‚{qÉé=´B§»Òc$w:t.dØNˆ‰v϶­¥¥öñFò»t°Ù©¥»¼ÌC—Ni+l­x/.wÉ–b ‚ö:.­Ûqë#»Ö¶+• ŸêƒâŠÝžY·’4i;©_µÛ–c~¼|¼|¼ü#k±ÎÑhò*ÕúlLÓ{ñá¿kVÛzø'õØj5gh€FžŒ£F»^m˜áȽhcc#Š’ˆ?NÂ(ŒFqDÔ&ãqÅã8ËH‚Qx¥²j¨Š(˲ %¡X* ùÒBÑËñ.ä$2°DŠquv¶k ù‚W” ‘"›º–ÏGŠjš²ªê²¡éz¹TÊçóó‚ä¥rY”E’Dya¾(ˆš©éš\$¡ìåEϋʑS ‚p%>Ÿ_€zž…qâB\„ïG>}…ëÁ÷‰âSD¡—„qø¬í£ ð’(Ž<¬èû±¢‰~øÞÈó±ùã··ýÈÂö6™eS¶¶=Ù;::ÚÛ;<<<8:Ú=œî`9<Ü=ÂW‡G´Q~ì¢ G“g·îbÏ“É.VÄ:{¼úÁþÞ­ÜŽÃbkjÙÛߥ­iû»ØlŸÛ'Gø½µöé@8'ì«ÒyâCì ‡Ýß= µ'G‡»‡Ø×þþ·<éøÇ¡Ë'ñ=]уþ÷ýaˆ¢ «š¢ây†,öUWø©ÒWJŠT’U]u±®¦ ’¤÷û²Tê=£}uµ$Éý¾.I‚ªiŠîb¹$aõ¾òSÁUûèB’,k’(ˆºÛÇ2Ђ Èšùþ{æà­û}½<¸¼ö‡ôÇè ºñôåYí´˜õE‹ˆKµÆ‹£Še†a‚åŸþÓ$¹€%|h¹pá“Yè¾d‹ªÎˆâ0ƾÿ¤í«‘åWl ÿlÊÕv&ÂîÞ怠ƒß€!ps”µ0¤&ûG{G€twwr>«P½°·K@Î÷™$vñ=ÖØ£­v± ìá`ìNˆ†v'€1>ïN±åähÐ=:àµ÷w‰+p¤]:Àdog{p°žÐ^'¼F>ŽJõ¤ãw(Mþ£äô–ö½·¾÷࿳cô5HD71îÜ6€Ñï*}ÑÕôr¾¤ë® »ýU¹Tê+ú@—ú½ÞÓÛÝÁÀíKø¨ôK%yµïÊ‚«ë¥|Y×\±¯|WuA²«Ê®è*]ºPT6…ß7AJÒª.¿yLÆb6+U8óë‹/Ž‚ZÅùå#€ZµæŒš¶=N¢V§Þžq»NÏiÕjHßxÑŒÃd}{8CÏ‹?ØŒƒ4N£$&.ÆéæV²µ½¹l'ñö8 Âp³¬˜ XYVÔBIÊB>W,æòÅ|±T K%öß™í4V£×°šM#¿‹$QWLMÖu KQ¤)†f¨š,Je¥PÈEzäºfèªTÊÍÏ‹žÖÑ´R^ÕtA–"?W(ø©? a”#ús“¹NÃØ‹½ìöë^‡@2¤žÈØyñ0ðjòž±ýh”q$VÁ$ѷƒÁÆOÜÞòª^½bSm[½ÑêÂ&ÈìîD>ð|p°78ÀºHØ&8‚`eÀ#úïéí@òö2µôû„cÀÛìoìÓÖ¼‡Ý}j'KN:X'´1±Lh¯l×'àÆ1vrˆÛ´(¨ƒ½=° (¤4!‚sµ<ñø4Ø¿J#Äçm«fìp¾qûgàrÛ•—TÝuu¡”jdâ!òäï«€ÿ½ÞÓÚu½/Šôsu0ø.̼Nô"ÚB-‘|”!ð¥X’%IÉL)æÎçÌ3æß¡/‰ƒ¾n˜è$̶½Xw¬ XÏ´büÓéò0ü‰žEO¦€ Tªíåv³–ÄÍ¥F½5³Ü±:KŽU©iÐ_ÍŒÑ#0@4ŠÖG$-Œ~’¤[i8Ž·Æq¼Éf²¹µ·77Ót+o•EU)²X‡zŠeˆøræ»P*å0VovÖ¶[ÐÆl¯×3ró¹²°¼²Bán¯¿" …’Ufšª&Á•|oaA‰ü¼DªÏ0UpÉÅBYÔ5Í0A ªXòM74%,/\,°™E>É} 1Ó˜²›!Œ|€km®ÖÃ4 Ǿôýä6†¡âðÁö¦ù³Û`ä㔹|-RâŽÀƒª€¥‡Åhûéñ­ÐŠGµØ®eZRdY8ͽ]ò`T*2åГ ¨à ÎÆþˆLû~†ögµÃT“o0uè¤ü ¡dšÉ¬ävÚ¤è'ÐXuŸý#F8TÂî>q P¿L“ȘÀAØ%" õ°w˜ñÏœ6ÀÐ^&{ ³'¿ÓjXÙ|Tƒšq °¼|ƒ‚óE׬iQÿÕÛðTUªemURаðPøR_…jïݽ÷ùþSÚ]–`WÒdˆ}øPEEZ%»âŠª*íº"»®b¸h‚+ Ì«wî™sfÑ”e «²¶Æða8 §Y±Zuo”†iÕùå#o½Rk¯,5ýpÝ™Yw,»×±«Îx+Ùô_4GÃ0 ^ßwcÄ‚7úc2õñæöx3Ù¦Ââ¿·šÝ)ÝoG%ÙÔ‚PVM)*”KEn@)W„qΗ½¢_’ àêÕ«ÆU³×k €¨ö—inØF§ÛYHÐ ‚¬Ê d>ü³¨<,ä45,€x@¾¨ˆE¸¢Ðë M“bü6tÙ y8çT9ÔˆFðàñ;òâ$M}Rícà= /ÞKoEãÀ#äÒ_)P»kžmoÎ7fû`¦'܇? )žà' È%ŠÚþäøm_KR8ÁœÁmuØŽ’ƒ½;!ðî‘ó¼{ÈN4à sNtCÐTä"À=«A í°òä‚“>8<Ê{Dæ™ÿ¢õÐLà>Èw'¼Â5O&Ä)´7hý ¯´K® {)»|Ú&88$g‚ÈŒ™…YèIǧñ1–ý*qÀ<àÖÍÏ]»LË€5ø·Ü[î»WoC¹úxY $A ü/¹2ºÉÝ/Ü@O·“r?nÀg„çTãÃÀ]hPÁÀÿÒ€Ö…Nìà+¸0xBJ’Õéªæ/) Å‹ÿì¬)¾ƒ´Ëkæ>]hûShÕª'þÓıN¹Iòþ³³a8;û8>‹~qøC„þúÒÆJ#nŽiPPk&ò7ìõ^Ã{æÆÆ}ÚKÒ$ 7àßFŒÒd Hèc s¼ ¹H“íÍ­ñVà+†„©nx……B±(ˆ‚XKåb©T*x¥¢‡+!׿eÝ5[êggÛ†$›m§Ýê,õV–ûS•Ê‚( Š¢šŠ¢Ëª  ň¢4¢óe©,—Ë"´œiþuzöX²T@¡P„—¯N=Î;H8„¦dÌážû››q²¾ß=Æñ(ÜŒ|¬¤t})možWM31ÍÓÛãapGEÄSO†ñéí§Ç¯կעºgY5›²¨6¥IwÉŽ“ïL"û¹GV˜‚g°¾dä¡°:‚Õ>XÂ>y Ïh?â(á„ö9!ÉŸ ˆðÌÂïN Ø÷å û @2~âdÖúØ|Ÿv°KÄ¡`ã4aÝ™'&p H*°å‡a"nÙ§0Àß¡âÙF­êÖ,W2®f:XŸ5Œa|áÞòeû¯Þ¾ û®ºÚw¥UÐVŒR¾ õþwwzûévSS4“Ú c I°,´aH…|‰< A^•¾«ÁpádŠîÀPV)ø'9pÐWÌ;·¿$¹øÜ™‹³æ@Äþdš§@ÿgO‡øÓÛÍf«^í´ü4M«MÇþå#ž¬ÕDc½9ÃÓ¹Nc-YÚ§Á‹Ã‡è÷ñfmŒôíÐO£ñ&|þx3I¶¢íds{+ÝÚÞ䩃6ÇQZ L]6a– å0_,KrJ¬¸/–ÂRYˆ㋎atïxþWëMpª¹²2PIЛêÚš¦Ê%Q‘TrðŸë^!R¿84À%byATÀ÷p*<@€ÞÀjðéæret]V¢°+Ž`š£aì…1À Ú‚CN¦Ær'„’£q2^AÏØoBÛÏhš£öÝ<›×£¡ùÒ-óÔö#\L†l­“…'gŠŸ€ÈóOm?=~ÝŽ«VÄS¦ÍݲiæÀa‰¬0°L`"ØØÂ+<³p?V"³:a€ýgµÐÔÀ<ñ¤Ò9ÈHºœjÜt÷ IDATŒ6¤?ÀLŽ;ØØ<¤ø?ÛøýLž ©pDq‚ƒ=þrŸ÷±O6z‚Ä] à¹ ì,7ó¤ãwhš®yK¶jŠVt[×¢q4ŒÆÆN«kìì¬^¾ì^…4D ÏÖ RêÊÀ•eBÿÝÏß½}ÕtË¥Óí Ó2eA–ú?ôaÕ%gÓ]„þàG} ²;P¨}¬9©‰’ኂ$V¿û¶!¹}Š˜·îÞPæžSæÎÎ>gdI¹|Y1Q?+ø•Ÿ¥'@½Ýª¶Û>d_­ýâè ˜å…(€H€–Ÿ…é±ðÿPa`#‰lš$È«Ïðt`ýv;Ž{Im±1ÜðGà qƒá0 À9åý‚mx›ÛÑv ëÛClm& ¨Ù “4V5¢¶î¼ ß ºX$ŒVÓø"œá&¥®Ö{¼H!wž—ËîXPD€[•%S—E¯4—¶]„ rß³€ÿÁr«7þñxŽáÅ níܾ|ùêmcÇAàYú²(«®Hè¿{÷öÍk‚鲨ÐŽÇÞ0ms +÷ßReq@íhq¢¬¾uæŸÜUC¡Y×EãÍûè^«ï¾ÙÇÊ¢$Â[½{ënéÌü‚ajê¬éªŠ$‘kñh"P ÈŸÕ9FÒŽm§ùâ(xÔø¨ ›¬Ûvœ¦Áú O6è¤ÑòR»ú|ÝôFëÃ(EiìmÀƒ†ÆÝŠâ­`3‰S8ý[ÛÛIno¦ À?oaâýDˆƒ W,xó’ –KåB©øÆ=<3óîíÙ«W=cvÖtŒYÇ(êÚê #€Áò² \«’ª²fâƒ,ŽDpI Éa~TÊ犰¬Qî8¡u·^Ó@na>ï•ÑfÈŠä‹”«‹½u?!ÙqÒŸrúžsï…# „|ã0 7VŠßã ßÈ7ÎÎ E8/I¥œižl`'œâ;.Âuð# Á?Ùý‚Ä«¦WìªU‹,«Q­ÇÈOàSS\žt5ÇÌ)¶Fp„('–zobjY¸0 <³}2!o`Ÿ2ñÙwü3#%õˆwȆïM2ÁH,@"‚£ûœ•È’{Yêÿh©½ Ó "GìGÙß§=ð¯'?«m­Ø®k¹ÆíÕ èwvüÿúù×$»~~Á—ÐUþÓ \” ÑuÃu{wÿ_ùÎßýð¥ûs&ÌüæévÓ\²l ½Ý¿¯¯rû›²¬âãýþÛš>€êw]Cp]ÑŠåÁ"ã/ $]Õ%M„o »šy÷Ú-åâìܼ隷L*0Ë«ŠžÀ[5ïþz|ûÀΗ¤8Z§<QÀ½{Çðÿ/³ü3û#䟟|ä§Ê?g²ŸO%€Ÿ‡ÌMæÄV½Ÿ´:Ñ Ov9ýn¯µx©aŽ^]ñ_EXz&ñ >ÜýÍ­íhk+ÞÞ b Ž·¶`÷“T]Å1ì° ÿ?_X(På…(J%à±k÷ŒÎg;À>¼€ëõÎ5lªf¯£e°Ô×L¨/K¢—Ò>ŠùX5ƒÂF1‚'¡Å¢BšNUUD`j¦f¨Jy~¾£tc)â–¨ËSênÿ{i@ }”ÂÆ<}ÂO)K‚  ç7£M4¤ÕBÐEâ›çÄbÙ\LI¼hÌãí#bÃhûûáz˜Œ=?]Âàƒ'Ž·§Áx¸¢ZjÕ¬W©€ôëTD“>”:0ØÀ;Ìê>‡õÙdR.nŸRp»„=Bæe)8'ÈÕü@¨S¦>Øä_x…$UÑSð|ÏOŒ³ rA‘Ð å‹.šÇÛƒ*¸Ѓã–vzCê‚¢ãíýq ¾ð‚ñÈN*µ$¬…aíUÛš·-+×huŽ8LÎp"áÎÐ;ÚËJ9pÈѺ ççÉ߇•Ý=˜ÆØŸÒN@1yõ´.@™?vå ¬@ü¥é(DGü³ÇÕ@G,ä‰%Hæ`tbõì6'‡ž ~D¡ÃCÊü±§˜ÕQ)ã“ßæé³Üê{Ư~R¿¦ëúÿ|ç­ÿxöþ;_ùƒ¯ýá5ý“¿jÜ6Œ’©. ¢ª(’¨½/Þ¹öÙ«eøaÌ%E8Ýnþð¿ÖÛ]- ÓvA‘`ð-¡¤âëh(‚¡PBZ¥ºAŠ%ô ¬¤ݼv[)Î=wnCÀepaytUû™(@ùñàñ퀳N Ј³<€y ñ{÷¨ˆú||d ¹Lßù`ðÿ@°Ô¨5“¨WµÝîÆhqqÆ©6–“Ъó4 qËŒà÷É4ÆAœP%\ÆÁ(M`ñ“Í­t;ÚŽÈí­Í8Ä^Y1 ²ÿF¡XÈG~Á/ ÐÝJ,S½,Üy8wN¯§( õÚ5º¦oûõ×%Ç0Íž90zpÄrYV¨˜S¨R¡pqa9*‚_d ý+T¤ÒZ:˜7G ¢$J……|±XŠ¢ªFJ { N}4À‚Cø‡_LHA½Ñ(òÇëTào0è`C#srAT­(çKp6Í+Óí±/oZ\yñ:¹㈨ÐQp`ºýèJp `<ò-ûëõjhWk¶U[´r4 UÎìQDêw8ý½›‰.¿%€É±uN²A}fû>§é()O1úÃìoÅáý â#Xp üe„Up@%=TÈvŸ$Å>kvÊ rÔq]}*7`Ö .ÙÖI=ðwt ŸÝý'¿M/u±€ºÛWõåž3Öß¹ÿŸ¯ýçûoëïÜüƒÿÙ»­_½}ÛhpîEAZôû”àïÝ»yõs‚¢Ï™’.öÅSíæÞÿÁýoï›hWJÇíøWU4C*áKAëê"•ôûƒU‰7¨ôž´èf« Û€ò¶õ|ç#'€fÕŽ{í kÃÕêŒSit#·^çi@¬Ž9½l GëÔ›·aðü3oCéF”ü ¶7·ÇÜŽ’­íØ—àÀÃ:ëÅ G‹_ŒDQQbÉ+‡bˆ›Å߃úÿÜçz=]ï½ñí×¾õÍ?õusÉYa0»=]K‚"cO¦j(ºPÎçs¹a¾ ©>LzЦÀÑ×u8tº¡¦&ËðI(—Êùb9_‹B¨(Q”ó}€§;„y¸ŸJ€(²7Š@@öx3 º>?ˆŒÜ¼RKZi~a¾dzA]ɶ§`*‡ ?‚;àÿ €è7DÓí±è’À[÷C“Ù¤~k4IM‘b€Gd­)î6ÙÏ¢ñ ëAÄS= À4¡ô Dåp?Ùy®~zû4O$³‹õB4•ûífeD<€€Ngp@Ù}Jé±. ìr0UdeFTÔG8¦ÌàÞ„4È4s‰/9IÊF°OQÌÇÿŸøÄÞômÆík­¿ÿâ¿ù½Ñìý¿šý¿¾÷÷ÿþ»÷gG¿÷oÚõæÍ›ܺ~¹, ´rIRܾn\»áêHšyß_=Õnþí~ð7ßÿÁû¯¸êà¤}µï.–ìyI¨Ø°OõÁuE*•µT.÷5ôI1åü… çÎ_\˜»p1WÖ´Ây0ÀE³T„`è«2×Ö̧0ÀAþ”&ÌÖúÕ‹ÄþÍÐcÎN‚}Fü3È(àñAÙrš×þó†Í^£V‰—;ü€ÚóÕ™¦]¯GËN“§±–Lª˜õ7à ÍXn3qZšlQÎ/à¸ÿ8ÚÚüA©§êJdÊÅBÍOE .ä¸$…^ÙÌ7^ý7Þà»óÆ·_í/^ýú7^Ãf·¹Ì!³·bÈ2l¹¢Â»×)%XÌÍç@² G\C Ç€ÑÇOUþA7&„žX†(-(åb¡P.J¢0EQ±D9º”D;x4‚¯ú°ÛA8òÂq˜ØÇ·›Ñ(àë]1Îç$¡(k Ï 9Û'Óíaý)ó—ëãá0“ÇOÅ‘Cb…!JeÛCZDÉ:'Ò‘mÃj:¬ˆrål„ÌÁÞWÓQrŸòT5wDyu¨IV©K±{àqEɸÃg¶Ov³¯Ù°™ç’Ýý¬2cüäÏsAIBÿ¹ä€ì;¿Ïi¾½Œ*¨(˜K–©ü¡AD…‚{T~DG™ì‹&=þ'^ ¥Ûvêv͸yû6ÍÃqûvö;ût{çêí׿`H àWWß”ú¥R©¯™%Åuµ9S×À8îžj7ÿæ½÷ÿæ½ïÿ?¯@ì¿‚…Û]·T’\{€-t NT³¬R£Ô—Þ\ÕËΩb*…¹óÏ=w~þü™3Ï»0?öìì…çΙT(¾-©n_ƒê4?œAfËiw–h Înã—“`•âºÃó=¿Xi7­Åh¥íð vÏäÑ/ðFØ2èTêšIšÀnQ`›RÄ[T¥i°)ÁsJeˆÿ\Þ/ò_uC‘e?,G©©o¼ñúk¯ í[ßxõ[¯k&¾ ·¹¬2,-“{¯ˆ€?œÙG9¸õ…\.¤º/{R9I ªþÑÔŒN˜ßJ%NÓÈ—S‹¹R±,…AÁ×T±P$oŸ²~á? ×CÖìPpç7†°Ô›ààe×çË%¹ )¹³òüœ Ï'n?‚µO¨d ‡øÓÇôuâ­cKÇòö>çhðÈ2±£ÐмÆ×ùËV»³·Ëázª©Û¥*œ,8—%¦E½»\ë7!dÁÀsA=‹óg´“'¿Gy¬Aãùˆ¨lârTh|ÀbãËùÉ¿?+PR‘ªíY‘ñÞ$°ÄuýûGYí/Ï„ë™HИ?x/ûT üèñ_8^–:Ýf£nÜ0nïܺyãÆëËÿ§{•&åºILp³uýú]CWú}Q]UÜ¿ÒE¡§š‚ ’ÿ¯‚çцG\:ÕnþÍ{ÿûïAèê+çÎÌ^¡vü“lØL ;!Š?š¯J¶­ÿ•«¬šúZ ¦2?ü_<†¡-0{þÌùçLQ•%x*¬†¾÷4'àƒ/f³á´—ã¶pÛöiȤÿwî=\LÁÁ'¹'Ëw>ôŸæ$< €ºUãé ªöÌ(Hßm7—‹Ö‹Ãž s£UÁP œ &zÿˆÆÑ(€t{sk‚`›j¶Ò­t-̇…b½˜/ T/«GªËakj´ýñ§ñú†öÆk¯}ó¯Á­ovqëMÅ\^Vår  ÂÕ‡´Ïç 9/Ìç 9E"9T…ƒ¦”Põ¯†• *9¤” DŒ!Ea1T?O#þb 6¬ëš\î‰Ó8þÏÀ‹ñ Ž¯Ï¼ •´¢¡äæÕyʳp…¶çêÚ_â“dH®HÅã÷éÁö žŒIúÖ#«fÍ_±jU»ÊU`5‹Ìd•ó»\©»ËU´\EÏ5ê¤Æ÷9Îw°ÿÌö̵ç\ÍïOKó(áGE:æ> $ @ÿðx½ êC3e²í¹Ð2Œý+±—G`ùcöFiL˜~Ó¸·Ë :þ Ÿþ£ÿŸ|á…^¯ãØÆMãÎå×½±²|ë?ÞÄo2Úƒ»Ëíæõë· QzWï¿%Puzï ŸUeà_.–Õ•©ðAûªùÞÿÛ÷HïÕxå\á•Wž;÷ pE]v±]c l>è««.­oHï®™ï* %w~öÜܸgÏœ9wþÂÜsPçM¨JÕ•tMRå·±wÓ”>0õ& E1À$ùà±Ë/JŽmUâ¿0Àª6f`ØÇô¦°ezùF»kzÐÎAäo )ZF#br¢ˆß1<ãxs{+N¶h8`Ê`±×Ôr 9“ƒ gî'ü ¤èßþ3Û‰v)nOŸ¨t‡•?¹ä¡€yÜÿ>ÖáÑü$Aȹ'ÈîòPp \/D ù… ñW*rÊðp?‹dûßåòB¾ ƒŸ=þ /|êSŸzá×_øÔ'>½²²Ô}½i7Wé­xÎÒMùšã´›v³îÞØK·›/"ƒ‰‚Ôwû½ÏùúmU-Ì™}UÌ—$Mw]cÐG¿ÉÚUCüàý÷•Š}ñ镹WÐÞ® —l[íKÅ‚ªÚèjß]3à(š¦!ÂÆ.’Ý/äæ.ýçÏœ}nþÜEâ‚ÆJð$ÝÕûæÚš¢ýü ÀÁ©2AÓ¶êí^Üâ, õ ˜-‚J„žõGÀ“Á ö'‘‚™M˜øÎrþ©3nÅc'ÍÆ×;-“ŠH+ÇþÐ $9»aŒcôü„^ï ï3Ý¢ÀÖöx;öCÊÌ“ù‡¹-擼W,…ó ¹é1̵F^$@füÿìOþíŸüÉ7aû‘Zð“H•J&CÜ êÍ/äòCI䆹‚$‘2QuZ Ï”É]—Š0’¤˜¸å\"–‘¢¨¤(C_ ©c²Ë`-Ï G úpÃ@¯óÄ £hDÕü<€®/IÌ‹JÁûÌÍC,.˜<ÊÛót1I˜¬S}0´ÓÐO£áC$Óíñ­·SL!ˆÏò#›â€v­ÎÓ6w8GU¼°›4â|BBšây'ìrº.Sù°­”ž;à2ܧ·Ó»œêçÁ}™í§ }6f~þó)ï¸7¡ÑˆܧísÚž2ž¤zŸ=¢¤]”Ͳ·—M$R„B{œd \&MðÈñA¿þéOêSî MîÖ2n\^ì´ £sK¾ÑÁ¯N}qùÆÀ^^j~ÖÐ×LsMSßuû+_¼ûÛ×îPüÊ÷EiU}__¢vW—sð^³zñŒ½h¿‚öWH(Š+Z A\µmöŒà꒨ȺÛ_{×4Ö8î_0 gΞ=g ù‹syáâ¹3ùœÙs ¹’êºeIyëíû—/Ã!ÕÿÑ`·–üî†Gu@Àw>jhÓt€8n¨7š3[Iš6“”Æ×@°î’ÔÇéü!GÌñßp”PÜ;H¶ D ˆÇ[²ûž\Šäç¹f.ðͤ‰XbIÎàÛ¯¿ö*à/¾ùïþìOÿìÏ¿ñ®Ðàú’—Fð)R²ÿ#?WÌc$Õs¹UiªnÐT ªÿ¦P…bNÐX^C€É/ʪæý‘LÉš·#£”†öAøAš•'8û(¹2Ú¤)‚²ë‹Ìy…F’¨Åóóª¤7O¶§u„ÒA4¯CKwA£F4jxº=žŒý^ÂzD/2©Evm±Æï”€$,u(y6áÉ3&<&pŸèïòúi@Žês÷¸d‡-êÅïhÌð3ÚaÜiú®ÝÉÒ†l½³äÿáQV÷··»Ç+q5/WóqÜ.nt”ÍæAaÊ#F6Ï2@íûTL‰„ý¬ˆÆúïïò€B R ñqÇÿÔ¯Áøä§VV–»íÖšñÙË—ºÆõ—ŒîíŽqëša´/-_ë[ËË[r0¼k†áŠ+Ÿ¿uõ–èÎ1ƒhˆ(BÀøS»¨_éŸ9ƒ›jšuSHRéj'ï«J¶¦UEUÕ®¨EM]“v `ÎÊüùsgÊà‚ÜŹù sîØþí¾‚½  ÑxÂÁýûï˜ïšOIèlP Y¯7ÚÝ8Úh@36æéAÀdýÉ8¦€'@¶U’|xpL&OX_ŠK4y{fEø÷¸|šJ˜°CÀó“2Øg…pÈãÈ1Ø?È&Ùã•q”•dn™%{ü>ñë/|ú…Oÿ‚³Ö,vn}ùË;Ý®±óå/ß2:‹ËWW@Í;ä€Á%Y\ù’{ã–jÌ™¨;ÎÊiŠ!”}|hWÕ’yæÌE³nÿ°öÁ@£á½%r K‚6x¯jIº1E²¥Š*ÊÓ±&óðì.ž-˜‚©LçÅ;Öœ7”3€Á¾Ä·o¾õÖÛ«ïš þ2&ÍØÛíõº½¥öúÈùå#ž°¹ÙZÝé.Ïô—ãV£?à±ÀU«eBùSÚlˆ¤ù°€šQ•ÂS¢Û‹ÒM»5Ná:HUh}?Ÿ/E4@^ "ÑKaß_ŽI‚ÞÀÿ®½ñí×¾ùê_¼Ï€×.–²ÁõEX˜ŽeU•áø/@ú º&GÑ0÷~$ ò¥Bv'èQ(Eô šH¡A¦..,äò‹ž¢(~^ð}ÈñšzŸëùëp*6CøìWhžÏ o‡ÙõùfŽf#)Í/¨Å ³M–0ÝžF­ûá8¦i!ÒhH4@|Bã$FÓí×§÷û«‡µf5²ì†ýuŠò‹_:‡\ wÀú\nÈ?hþ„§øÛç)xhtÍÞAâz’ xF;ç×”ä›dFŽ÷SÝ1Á’M9=šC0›ìýÒúìðïMg Oƒb‹dï³p%—ïqª‘ãTP´Ÿ SaŦà æø/|>À'_XY:-§e\½\ëÿ~ɬ,ÝÿÃøò’µòÛýæJ}pRNv Y|þæŽ,̙岈¿ìwáA„»²«”ѼS9Ï÷¿ÿòË&·¿-•JÆ*EWRIz»@6Är™&”Е&þË&ùg˦ráÜà_Ót0Ѝ™çgÍ &•Ii$Ñ›oþä§?úñÛoC¼ûÐÐàgPÀ£í&Ï#Ü[êõèÕ>™ Á=óþ¿3ýMßýì0¡Óƒ…‰cffvvöÀ³×ùä'y:@« ýÕ©Úè˜3àªNÿÞ—^æ±À6€7¢×7’yó“1Mž•›Œ¢0q†cXE4„›4"`{œnG‘G¥º=òd-ŠÅ’'xEšèSSÄx¤¡{o¼ñío½ª|ëu¥4W¤êÚ‹JÙàúrÞ‡²ØŽdM óÃa!Ÿ/z†ª$^>§Dò¦Iå¦Â@C‡¦Ó•²@»$0ƒA3Š™šZÌ-ä/.Ìsª¦„_X_’T"ž§‹æêQotž¿§ã„F3Ð,pep}fÞS.^\ÐÎÉfB fÛß”àóh&Ñ-¨: iÍ IDAT*öÂÔ °ÎÈÜý Æë¼=½ž€gÄ¡w›wxŠžlˆKÐ×÷í³M%´íeù·}ÎN&ÙT`{Ïj']Î!›Þ+å;µó»<‹±ÁþÁ„E•S ÏJà ù?â Ã(°OÅ4Ì7#€]r3xžlÄÚ刳\!ð¸ã¿@©€þÊR·Óh¯·.×—Œÿ°üååßÄÿÿÁ€é_¾é:ÍÁêMC*º?½|Y¬|éÎmQœ3a“UC‹š;¬±{çþÔueÀv ˆ¢ùò—^Þ¹³6m‡±×eÀ¸óVÍC•$—¼D þýtͼsÃ4óçs¦pÑìëØ …yaÖœ5‹2’TAßüñO~ò“ƒÞa¯áÓƒ\¿0âéwdEŒr ~Xð|ÓP °óš*'r„¡Lé?…þ‹pÿeAL±?*&ÐÊ ùü\¡°PœóÈ‚ùa”ÍþáÓLÆ!Õê}žxs¼Yƒë™‚íÍ¡YÐp}`€¹y­tÞð˜j…°}„SŒGÕúmxãQì‡<$ ûÆÙýž¾?~by¡íÕìùWíy+g×›%ªf+JIwšŽ‹,3ÕÞò]®8¢qB‡°#Y>ÙÀ3Ú÷(ÚÇÁ9OÚI_R™ÀdÂÕ?47(U°ãNv "+ä;¤t"«š Çà!Y1ÀËž-è0+ó£ðLÀTN¼— züñ§Ðm· ãÖjcyù_î|Ù}©÷å¹¼¼\_¹=è VoݼiˆƒUSﯮ|áÆÎ`Î\Õxü«²QTEÕ¥~£ û«ýÁ÷äJSy|þöÚq»¢ÐÔSè U€¿êÚòªÑwá&êk†¾¶ÆP&üƒÎÍ›Ðü4|¤$J®nΟ3Ï™}Ií÷uMÔ¿'ö¡Þ|“â—ÍË øÃ?ú£?~,»°NC}|ªë3øcžØ[Ò~±Ðî?îþ„8Üúô…oôÞiw¨à6‹Îrfž°Âi5²Î‡¬Áy°l¨/9úÙ\`Ïj§¹;yïCªœdøÉá´Â€‹ûÈÂïñ¤T8DËy,R63è!MÄ1>šà“‚…<Øþ!ÏüËüµÇs‡R= Åy ‘Ã'¿×[ê¶»mãÎA³ÑYúr§5ül6[—ï¬ÿ÷v s õÍË¢ºrï×ÿ—Š €¿t‹j¹()Ðx¢B¶\gÇ˽›_¸wÇ|Ð^Ì—JùJ½ªX®kÝz¥ïuIÕD(Fü ü0÷ òÞ”¾'»jÁ$Ó4XÕKâ /•i±¢$Ý¿ÿÝa®½C"€9àñ,ð˜‘@Çœ g@€ê<–¾ó‘@«aW»_ºwûÚ”ZMÇ} '¼´˜ÀV“J߯Cü„‡;Œ²b (‹{‡# ÊK¡ÿí-hpP)„a!ˆT®4ls9‚9L7UY‰’íØ4ÈR¿aJ°ý#ÓÌÍŠÓÁõ æ ø‚o¤r1¿PÈGÅ|'`BÊÇÞP6Æ0ñ”¤:»¥‚À.®+…b!w1náâ‚W\ ž¢úeU‰ £„¢÷\ž.ói€_Hs÷ø›#/Þo{ÛìlA˜%×gJ¥¼RÎñ:U÷%¶ѬHœ-wø[4h²¦†>ÍþðýY§±Ã#ÞÞJ<èR~MÙñ”`YíÝ!Çy~ýƒ O­“¥×ɰfSÿSùÿWð>«}7+ÚÏ¢z»Ù |”#žÊ—Ic?3þsÎ, ¶kõòÓþ[ýê{ê`~Â^±¥5Ói¬Ý_3x:ÀɇÚiÚeú\¸ýjÿ§?qEøùr_’%lÄ¡]ÚÝ>l¾fþhͤ©Ãñù¬)k4ˆBKô& ÛÉJõþýû« MMGs<ìO&Ô±ø%#€vݪV:Àÿ¨7èÍh‹™ ›Gq>˜6*kã×i„L>§½ž57ÑíSJ…ɲ¢¨ø«!dO5¼X 2¯ÙO6)š3ú£Ô”aûÅ|òçæÎäxp}JNE”@7,ÄpÿK~¾šdô£" &çMQXèºÊ©ÆbØ0”KÂÅ<<šBÄ_òëC¯ìkª §¡üa|%€wÐŒ>ÍËföŒ6 »›[c(¯Í Å)m¥f¾”3ÊEÝc?Þ âÛûÃÍôC£}ãñØó+“F©ŸCïϺO¬Bï¡9ÇFÙöó•ZÔªÕzFûoã©úŽ(¿FÓhQ©þϸ½¿Ëí8”ÆÅ9{»Ó‚ÝgµSàŽß5Bƒv2ã{ñÇèhz_˜tžK<›Ó÷à SïÙ„Â4#¥ü'4÷8 > ±„ÌM{<6xj÷²7 ‘O2ɼÝ=.IxÂñéÍuvË1vîèYîíÜâw쨒٠`ª„¼d÷i‰T·k*€m¨¶(©ôz^Èwz+„hH%ó¡v»f¬A£f×-ëU]ìÓ$¢ °ÓINÑÀ3f_ä)þ‡ï@ÏAH®Ky_WïÓ,S®(ºŠ» RXíLøÚe #¼ó‚€ÕÁ²x¢î”ÿ@&þé÷£°Í–‡Â‚ß™ºO]>ü‰lzy1 Å°Wm™gkw:ÝNÛL!ïƒÄg霽cŒ(Þ ¼‡÷¦Éð`cš7H¶i¬>MÅAó4&†áÑv„‡4HÁ¡LÖP‡í7͸`ž1ÎçJÓÁõPÑf¼•hŠP„é/*‚•ó0îp%²NÄOADU£ÙÂ4S ˆ9☠ÖsùrÀÏ•Š …bX,ޤB(k£uUU …ð=šŸWðÙ§ù=Â8 ßWxVÿt ×'e+1ËÁôM±hTù|Åã ¼‘ñhèùë Œ»?öSß‹ÆC+½>ŒÒ(>uüñÆM@fÛ׿múÇo¡w:TŸ7áÑýϸŸÙišå‹fã¦~<6‡³kìLd/zz;í’«ñ'<ã' RÙ— Ò<¿”j`ŸRT€P:=>×îñ;€È\è?­ëcfÈà>ÉÞLvp02HôÃ~ÀŽßí4põö¡bÕv ;k×\“W¾p«'+Æ@µ­º;ÐDÑW™§ÉĪö{–[t§C’ÞJJñ¢džn·«ØQÍ®À)¨Š/«2WŽ0d™ÊÐV  п ·ßÕ×tM[ó¦´ªI+¨¢1è+ØZ¥ ’ŽCi¦Ë¦ñÓµw³A‚›ÿãq‰Å0 PÓW‡P„&à¬øE¦]ÊU.ÍÐk†ù½ë4wÓ2·x²Ì (! {DáÐÝÉ'Nùµ7Ùª’£Y2cŸ&óWa+ŽxÆÍŒƒHˆáÑËðâ8M6=?o^ âóæÉàú{Ž7cÍTò¢Ÿ—CE Â=yš”æmÃ0Œ0–q4ï¨Jt®ˆB)Ÿ`ý…|¾@Nˆ¿¡”ж··¨`¼½-˜^hŠ×L"‡,ÎÇSþé5a±ã“-RCJ’O¿áÔýI(]˜ÄÕ(ªU‚a µR«Óò¨:žN8<È”ý8üâ¾iÀþAV†C$ÁžÕž½ú‡öR.0¦ Gy‚^~‰Ø¿%䀧ØŸP4Ÿg$<âYüi‚r*å£ J83AÀyÀQ6˜pB'¼Ï%Æ4‘¦ßçqG<Áàßm7jôf†±S3Œk–uûæµ[Ö Ë5vv®Ã°çwŒêÛ¦Ü-õhðUÛµ­÷àÜ‹µ²¨Ð{®+¶åÚv±1/]{­½Ö6‹³0_ÐOµk¶-Òô°ºd‰ešøo \ 6JyqP¤©¦}*xù¦Ù§×‡0¼|ÝT†Â/ £ô ¬¸E6ú.ÍGQ¢× ŒµUsu üÌ?>h> ¨i)ð“äý“àO뜢€ï|ø€ÐrÓ³ã7Ï,ñùV+—*5‹€^£1bˆ“çIõ“ ëß¡—ò6©qH‘µ„G¿ð¸+úÉtöLÒÛÅù¹ù\>_âT™Ä;yó½… ›ú¥H #¬¤‡CÁ©ˆ1¦Àßè —6ÒYƒw®dïò#‘‚ßÛc?1ip£Y¼fÒÛLº¾Qv}ܡшfÿ¤ñ¿#* ‡qJ„’¦ôï ÷§^‹<{ž À¦‚‹ÝL±Ó8}Ì®÷>Åè¯IVbCѽ çüyÆÿƒ ƒñ©íG<éG‹ËИ…û(êwÀ/âê¼É—éîÒkþ§/¥p?æÍÆ1æ§c 'ê?ÊFp Ÿ|4T€Ów²?ó¤ãÔjóRú7oܺuÍØ¹f\»íZ6„¿{›ôEwv»÷…;wzrÕµæõ ÕN(pR竞L‹K UÝVÉ,å/æaÁµ‡Úvå=«:?éõ´Áþ{Æ_IRyU©„˜Æí?^ãqGÀº–}AS„ ô>Í 6 „ƒäê’`¸·¯éê@2e•Æø¬­Ñ„¡Lþó«ÁÔ#ð_°j8»*ÀÒCPÀ¶Åñ8ÊÒY\è\?Ù@/ßH¼4 úz›ÆÑíƒðÁ¸›é¸™ðâÅù¹ ù"PÄ ƒ°477waÞ˜{î9ý‚¡Ksgó³÷ÏâHØv0J|š<\¥´n™ßÒ H¶Ótks›f Öþ?æÞ¬9®óLÔ5Å=‘™gßDî¶ÌÙU]…@²Ay2ó,™H¸JjQ$eGÏt;æÂÁy:ºzæÖQ5îZ¦º+z¦Ú¶lY«%^˼ÑR]}û˜÷y¿ pABvuŒRâ˳€8ïó½ëó˜ø­‘ƒ… 4:–ité—MΛ¦hdÈdEU“Ð m»›ö5‰ßè¸tÿOKÿzÌÙÐýúA„ÿcÎ቟ï`P 8@²¼ÇÑ‘Ÿ0ÐQªd僔£$=&zá¿O6“à ]–UVåâAXgÏ™koÆ’¼' ¾6[tæó<Þhé:ÂûE>q¾PæQøDÈüB É4ìÌÙ ^‘)ëû°Œyèo(ª”cDLÏ»:ûÌEöb,¦—€¢‹qÈ ®_«–`¥dÿwî~æŸ)¸9²}²ÛUȂ޿ŸÈÙ£´ñƽïoäµ:›3þÁhkʘÙÃ&ª\>ñyžüZ/óä·]*Wެó§z¾n˜M[25 fO~¼IO†c9ïo«¶‰ncƒÿÞuM6eµùÙoèŸÙªj6N½ÞpìÍÈHKõí&èéÝfÓЬm0‘9P®þ³gËßyxÇ Ê{Ú,Ÿ;Ú" <€çÀS?Ùü¿GPxr‹û­ToáPd}(8?Qÿ\¤ìÑÔƒ¨}´ˆ¸Êc`ÂŒ fÂÿ!8õ7ÌìäÏÄí¼èúµj![Èå?ÍÒŽÿyü¹ìçùDFvs \—‚lN–õÒÆÆFn…§¦ÄžžIä?_­ç³ù\&‹ôlfb½T*Ë…ãëÍl¼kÙüCK‡¨®›¦EѼ¦‘Í7šèäFRÛrTòìf£ùQƒ{Ó¡@ÞBÛÈÇÎÇïä6LUoh–­ºm×ÁäZt¯Ÿ'ð—wÜ ¾…PY@NÀÚ!`Ñ¿b¹H!@ÜA×kÄ·qaÐ¥îuB£ ¹“îtëõõJ©Ìòdjžô²ÛéP8)íyÖ¥ ^»qÅLß À8©Øÿ`°£S'÷iÃw¸“Àõœö~&AT`†P†“, Ó†®í´¤vxYñå´Nû;¼~ÆJh±|€48®ßn‘Oàƒ÷=ýqÀ2äËÇA´Þ‹Ÿ>ÞuŸ¬ãÏ‚<_ªV9)Ç$À¼¹Ž0å7ÕtåB\“wÝ)7ÿÓÂ|´|gzÇ¢ô6ƒLÛ…o3€?Á?NÇsÁN††B!,À){ŽèqôgçŠÿyV>e–)âæ@Œ&ê>ÿø*‚ÍB6Ï1|&¿š ƒ@N$W¼ L„i82À&–;…¿BØñõ£Øº½n§Ûë@ë(A1tÉÑgưӯ“‡{ß}¼GWx±HŽDJ_ÔÌß\LçˆÅMRwØÅ'Óeëð#°óYàD´ìž{Ì"7°tÏPtCû‡»÷Ç7ý3c8KÌY0MȬ@,nD¤ù™†LWü¢ã ùÏ¡Œ'_ yü(þ6ŸO&ó¨.]ÿüsòÈÖùM™,Ç9‡ÊUE¶ôŒaB!P#»·eû#Umª²d4êjÝúÐlhuÛQR²ãÔU£ÞØ6d– tôF½ qÍtêúWÛfCÕTE7 ™‚ N©YM]Ñõo@æ7¨þ)·% TY/½T,¯Rg®^¥@µC#P÷;>ú] uÒãLvÁ‹ËÙ§\ßÚ*oT*k•*Zé:-ïÒËÿ)é…èð¿ä…žçÊj]ü…‹"‚8¾ƒn`Ú`)òß?8èEñAØïA‹c¸  #]lj0Ìฎ"°LV“Õlk’”î¸fÞõ%uq|}øã1S °ÙŠ)ˆaûaÔmùdÀaÏï+˜›B!ˆÖj¡lðÌzô¼u®i»î{O=„äpñ8 TõÙ&+ñ ›͹ÂH¹9h2Šß¬¯;Åìšx—¬ÏäŸ –ß©0Z±)‹iÝ«ƒ‹Z¤Çœ¶2žbÜ—åDD1„Ÿ"º„™YÀEÂbÊŽ 7°oåŽGYâh™löól¶ˆzh±˜§?¹Z¤‹…Bò·K×óyÚJ‘MÁ›lóùûEú˜Ë/ØÀ@HL~¼j7h‹¯#øq=…°À¢@ßQÓøÈpÈ9ü°ÙÜn8NCƒ,4C_~õõWº©Y¦"[Û¶mXªÑtM]7Üãc“  è1ê(óE<Â@ %<„õý¶(rŸ_ûø:zŸ°¹·n[wÑÕ²¹ygm;*f¸Ðòú=pØ#BÅ}¸àìá™}æÛ½æTPsb³g³T óeë ÷âzž‚!¦ûÄ›ÆBœI¿Cnüóí|Â*ßCF¤8S9eL™uaq+Ðî>e·1B¼ðxx€E2UòìWsyÚÞ‹Ålœvöt“‹K×é¯äý³»ÆjÖZKä3„èÌål`  ·´O>Õ5)MÏ€ù!²ŽÃº?¸ {[7%ò(Ðä(èu[«Ó–o`B°á40wH¤û¡i×ú6fÓ U¶1ŸHöZmï¸Aý~oÈJùÕ«™Bi­R(¼T ¨³W³^„PÐd9,ÖÀîÁk†”Þcìç­C„÷èz]Ú\/ÕÊ•õʆ$†wÞ9kü Šì—앳n» nÏóºL¥Ïǃi3€Â6t‡ú çy]d øäZŽíÙf °Œb<Ø´M(?V;º–H`>DW–n†ªb¾?¾~ï16ÑA'¦(LݸΠ6 y~LŽ|Øo³ð'*üQôd}w7&o‚„ž^'¸ûÖ¿|ã^ÍúÖæýÙÜØlÔ Ú€B4ÇsX˜ uÌÞ!fz˜^cÊ]Âs°‡ D -v¾l]Ì ywž ª³Çt,ÔÐè‹1Ý!sw˜Æï#nëÇ€òTàÿ±épv¨' Zx:ºˆ8Æ|~A>üÂãkˆJùß’f¸ªÂ¯"’y°kzöJËÖùEÁçü&¤ýÈ5ø|‘ 'ÖZ°A :…ú¦n(¡}¿.ËF³aÛ.Åòͦ®ªšKÿëuÃU)tÐé’Jß·í£5r">6µOêÎï×m÷cd 4ž:;ê<-ü 3¨ßð<€eæÿìùädáþ ÞH@ûÓZ‰þ¼"à ÚȘ/ÏïöÚPÕE©/ ÉÚþázpd¬j?НoÕkëkôÐWJÕMPê‡Þ9óœñ·„ž#'ϸ!a³ÃŽžßÛÛëÁm÷{"ô ?@À„¢`xt­žv³afhZŽiòìí˜r*‘6%‚„=E&àî¶[­6ß_M¢ ¸·À.q}´,>D]Ñ$ýÀp!üq×Àñu€ƒ£Þ±u÷uñëïîžqÝíþ«l® l½~ïM”©M¸ÇŽ[f`,“ Ö"˜æbßC7!¿Áî>K.ݟ¹ÿ&ꟈÆ—¡õ$Á¸&³ Çœâ¼ÃYqlºŸˆ+ û‰ñ@Pyy(‰x$XTAFˆff';ñøA€ ‰@øä¢µºxÁÎËåÒ²uzŒ”K…ü€<'U3ìd), ðl`díVÝL7>²W)noÖaÛªõíèZƒëäøÛÒ¦õ¯`º IDAT WN¥uÔAžmaIöT(O×?lÖ›–Ùl:Î'NãcËúŠÿ¯Y§Mü ô7¨o% €û[+Q¬Å°~ú»>ùË´Yîƒ ?î2“6¸>úÝÝ ìÇýp±Yï€s§ñ:¿UÛ(U‹µruck ¢ã·.þ•ö·çÙð´ÔÚüÙÍöÚcÇGûýA+ Ó¢È…À~?´°ß[6Åà¶Å£žY`Ž·T$)>PViŠÞLÛ2Zm­cRJâûÃõ£Å{éçÚO°«ÅãÁhìíáïPùcÕ?(â—U¯·Ñ Ü¢uðŠ¶ÈŸ8ºN°Vy#쇭°ïÞ¯¬¹÷ïo_»Vݽ›¿J›&eƒÞˆ›jÉb¦¼cΘ°K¤ûéM`1˜õ]¶.2‰3qòébÃgÑ?žDï ±R(j õFRpM™àw,d†"ŸÈ~…`ö˜ÍÅ#ß4\ô@ÒŒ)D™'äÄãk5 +ˆëéSmíØKØù²u|!ÓŸ4™<VÙ"²ÿyÎ p—EN°ÙNÝJÉôtçîjN£™TL§N~½Ë"úžkÔë¦Ù¬Óö`è/0¼­¨"˜ !¬ªŠU¯Œ¸7ˆ M½áÔmòNAü8BðŽÔ)`ƒ^K@à8„€“Í ¬?€£@Œ1] ƒw¹%˜vO_¤½Éòá0÷Ÿ»Çž‚XߌÖÖJá¥!Aè·ÛÞ9ûìß©³r­€fBN[é„Gn´wÆ í÷‚˜¶ÿ8ê0F2‹y\Šý{܈j 4E1,M¶cÚeÅ6ä4g œN^L‰ûãgíBAA o$É÷‰º€9> ôúaŒ±h^ßmûý.’~qй P‚'ëdÿÍÍÊFÿê÷ûAŸ°ªy÷þ½k×^¿çÞGR02ààÔüS·Ìõ³Ë ©Ž÷ä1;+dD—®³TLjOÉ “„Lfb:—á`:á¢* B2œf<Ò7™q.wuÁü=eAráöƒ£1'HÙ¡%@´r²Ù¢zÀƒ†ˆëEW0ÏôNY‘ UÄwúq1dõ>~ÀdùñÓYÀzšã&¸4ÉRIKÖg<Ô(óìüŸSLõçôùÏ\¬×ó¹z<Á‚%§sM;m¨úJ üq Èš¡«¿j*’N¶_W]rêNSÕÔ† XÏ#ÿ_µå¤ÉU0Ëj–ª[®­j®c«Í¦Ñ¤ Á;štžúü´à7¨#°±x=kþOKƒý1½žFßž&œ(ðý­U €b­VÌ^½ruµD€@@Û=yÊ~w?܇Hp¯Ð&Úß%“éû ¿[¬‡»Í9\ïìöô’]E[›ôÀÓ[[µjfÞE7>ÿw+ÒßýMòÜù¿´¼‹/ŸI$¼ŽwäŒÏOƆŒùÿ­ì˜€mûÀ nöääå”m@žï´tÓJ¥ FáÓ„ÙáJ*±âóõÁѶ[  ÀT¡Wÿ±›ßiƒ%Àoc(àPK$æ›@Ñ€"d9Ñ<ˆÁ€‚ ¡OQPÄ}²}$iÝýgìü·æZùÌgÿí³Ï>û?:óãîÿ3÷ þ5@¡X–k´aƒ§sÌZ¬À#¤Q @Q4YGOdÓ@©Ž‹ö<ÀÙ´×ßY«º‡B~'¬KDFoFð‹÷\áT+ï°-NyN•QD2=ñPÌïÍx¶GH°øyÊÑB€„S #n]â1D”Y:T¤†¬²ìxž bö1ä%¹™lhLu8z‚KÖ‡¢ iT«ÕÊe²)r ‰l†ÙÖr(ä²9K]•‹MÛ–$[–d•ÐÀ`YÛÔÉž U³LS×LzT Í4LU“¼´¥j²©¥eORwX·€IÀû2»ô‚!\¤‡B d‚ÜÏ/;ž%NGÜ €æ!þI„b13œ.Y .ep£S€Þ¢b±eËÏ'ŠÜ! žF7¹‚dé–'£z¹ØÉÖMMÅTO£NŠîªí*ª'™Žî)dù ˜0dËÓËH{š«Éõ¦glëŠ^¯kÈ3î7h3¨gàç?Çÿ?ÿù þ¸q䣸N|äãÃÿ”@w•½zu•ì¿@‘úKkëHµrýµ¶^«y¼ÛÑ~è“Áïà }G:EÆ>vk0âŠu´ü®wÉ+è ˜Þª_ߪ€n ºµÎLJ€¿¶/»)ý?iÿùò_Ylçlò¢·ÂÃÁíð©ãÅnÛéõ;û˜ ìó<Ð$<„ møI)%¥R©¤”F#Æ„ d@ÞýÖ §“覾>ûAàB6KÐ XÇ'•²öÿ豈ßG@EXûßô[ñ ÓŠú*€´Xwï½Qù‡ÿåß?ðÏ|úÁ™_ôÿåÃOÏøþ}õ^ë­·\]%äçPÜ㑾‰È–Ö#'ý€Cl¥#¡É1f·ž½á w Ÿ¼gBð…‘¿ñþ»ÿï»î½Gªõ?üç·Ö×kå[ãñ¢.À´`ÜÓ3Bq€ÁLß<'°¨÷/êü#V…3V³$èHˆƒ>¢ÉhéñSÑ <"ƒ ñaàЄÙ¦ËÖÇsq~¦3œÔ„P,|žEKpí«èòQõ4º ê¶Fºi©ô¹nÚ EÑ›¶"ëf]×=•,Ú@û¸¡[²îéºÝÝ `Á30[꩚V7€Y'Áp­oÒŒY€cõ <ïuhœqüdøùæ{~G¨Ñ]ñݡ̲¾ö{_y/B7?3úíý¥3ß}2°’_º-ÖãÎãõ èô ‚æõfc³¾µQXßÚâãi÷õÎþ]pÙ]ùë–ñ×ÉËž|ö\ò¼“‚-·ÐHsìx¿M!:ìœ ˆwDý^ÁþºàpL9X‘Òɤ”9¸ÅB!.$ƒU‚„´¬»žnXŠj[A:PøúÈêÅݰ߂µ÷aëa$t|0°K?­vaê~4¢Èîw0æÀ7À:(EBT@‘= P"&HŠz(´Ü·„î=‹Þß?üêÞý×ïÝyó_¹yQPÄÎtŒò=Fu†L¦?dŠgËFóCÑžÉX´ô£c}KÖiŸŸÍvvnÝ"øàÝ¿ÿ9¹Ÿ=úƒ?¸µAö_½5› I"1O8{øˆÇ ‘\´OÆb·pË €{t!G†Þ¡‘(Ÿòl1ÇlðpÙ§ã¥ÇO1’4áñ£ñhA&4-Ñc¤-[ÜÃcn¤ÆyÀCnØgçøÄõÙ­­Íõ[·vnÕ|ô‹¿ÿ¯¿&øìÑ­õZµR«ÝbG}<!a7œ?|ôȶBäG‚ògÎM}¬'„ܽH; è(8¾pYÁ'ÊMC&,О=Zz<³†róx$¢„¾É\Ì6L—­óõ1h0c.4úI¸YCíùB¦Ï$rvN14²Ø”ªSì'§¶›²KÑ€QoXdó ÍÚ6ë@cØ ýހïymä&h.¾KÆÌÓ6$XP ÐaŽÀi^ûfÀqƒZ$O‡ó~1…€“àù//õè f_*} ™LkχgÞŽ8×Ǭ·0äbÊmZû¢§f±Þíto®ío¯)µÍõúÖõk´Mîïp$¼‹iõâŸIï‚d]N¿|æ‚“<ÿrâŒçuŠ® Î?¶)Øï¡Ð;ˆ{ƒ“‚ÒVOP¯¥¤ ºš–W´´F›=æ„ dHK²¬X p”4Y{:ÅŽ °ë(Oúƒ®/´<âäü¸Ïì?Q_(¡À’¢q€„ÀnÔëµú­A´@ÎK/î÷Ý·Ü·¯mÕëw¶6ïþò-ú µªæ÷7«¥7ß¼ç®f2Ü0b%Üù,µÁô\ïæ–ý!2zb]cN©?o}ggë;;SúŠŽ{·}öÙ=÷ãŸÿýß¿ïÞýŒ ¾¹Y[[ÿÎ|¶`ìƒ)>|ôðÑdш‚š„˜ú—wWÑ0åyÁûÌü5!Ì‚@˜% Ÿœ›¦(EpÞnÉñ`™Šë£¡qÆÄS¨ ¥”eë\SœŠBAô•9€ð/9›¦ÀßÎ9vVO‘áëJê×_)¨fêN}»ñÐi|¢ƒ<ÞQ Ž  ´kŽœ9‘´ã[¦mk†çÉ t]–„œM]µ®_;Jp$h>õ÷7¨o Çîð¥µÚÚÚãÌÚš‡H¹Ój!ºï™˜c!Ø/„ÿX¯÷wÃö~óúö†rA©ln5···®Çýôòűwñÿ6ÎÙöŠ÷òŠ¬Ê †ðsé3ç<¶­ÇLJá~û6ý}ºY*ÂÁÁÀîBÜã®?[UV’!@:¥` 2ð®c™*F‚Ȉٞ£'ät;-¥‘ßç.€]ð”a€°«-°‹u|E¿ÏÅ ϭþ`Bî‚ߟ@¢³Ûþ?ˆÃÁ€À‰Â‚¥€5Å¢ƒˆÀ}k;›+VÊëoo”ËÕR¾T¨¿Õ̯ß+}Ï¥í Ç“Èÿaôf":ç'öB>‘ͬZv6oçìzÞ2%Š µôé”&§Ri§AXL íý ÿ•¢|‡üèÍë¶b[®ƒ\€çX† _ŸÖµIo/€Š™!óúcà4AÞqƒú†ð$Åw¾ïèwN k‡·Vî½Tί¡jW(”Jå\¾âµü½VË÷÷À Åód >ÚæcÖÈîuû¡¿ˆ ëdG­­èZÓ3_¾¤kõë[ñA¿½?èA:Èû‹®qÞµWìËg’–#§\ð„A­::OŽ÷i× w™X„ÎßéÔ£˜Bú=€˜¶z—œC¿$º"+T#y2Èq-rÝ4”|è] •Ô¤ÜpÁSìŠw¡vÈS¯ƒ>"ë­“>ÄÃÐv"á¿Ç|ˆ‡ë , ft¢ÄQ0ˆ sï\»Z«ºní®q§FŸj…«›wšùÍõÒŸ¸ù Æ®K5.–¡‹—Âf £vÊô™³ñT`ÂËiÂ˳ˆ ð}áúÎ+¯Ý|…"ÿûî=üGàüúg°`ÂG¯lVÿà'L À*#²ÿÏ(xôHÌ"2þ0é0'ãQ—üÀÈP¢pÎ\#(É MQ‘†^ú”á,=~ÈsÑ< È‚µ>A?~ò:“"ÂYšìÓr3¾õõj1ŸOäȰrõ¬]ÏåW³H [f2•6-ìörZ•1è§[ë Ï0LO×=Í‘àåÃÂ]Ý´]~€Tz„ -&ô'm«h Æ y×ío7¨oTò¹2Æ«J•Ju-_TJù ª‚RU¼½ùÿ-¿½×ñ÷c“1 p4½õ"DÆ=ìš18À¯w·Ö·eÏJŸ9ŸP®_ßÚÑOô…¡wYs^vC÷¢wéÂùä%Åcþ@£(¦‹ã;ýN·ÇÎv§Íç¿í“•A¾“ÎB¿(Ç1=Ûpy&Д“²©JŠfºƒ,8°[³“{ƒ\£›–”Pkó=2v=á)ü…±Ð9ßÐ:Az“'Ú é3*ƒq¿EëYÁ]Ÿ¼p• Ш´÷O®]Ysßüž»v¯æÞ}Ãu«W6ßhäÈ¿‹$`®PªÊ5–Û`rŽÏN8®òˆþ"a6äí–'l`vœ_ÃÌð‹ÖwnݸÁ©¿…pïžýÞÏ>à/ þÑþáw¾Ãõtìõˆÿ~öÙC¼=⹞ž‹¾= Mi(ß9oÈÚ`äÙƒí "áÊ¢¤—Ï #¢xÊŠDEçË‚§ý£. c±àÅz"2î„­ ž¬ï[[µõ’g)é3/_XQ® B´òôúýï²ëžû›{.áxÉs¦+y=F€Xl§||zÛ¨×íõ£Ç秃{ÜdAªÅ±º ÆZš&'UC= …vú[ôûÕtÛt=òíb8f B£´ýGŒ] Ù v¹ÚßãëÇ|}f?†–tPÛ -¤7Áý$?}4ü è!­‡dúû½A¯ïï3\­Ýýáﯭ¹÷øÃ»níêæë[¥·AYÎërm(’ñ¢N>e1ž1?êÜ¥Ã}³B²‡‡üAÅ=áò÷Ië;;·^½yßýÍÇ|ð‘pQß·]v>qïÜš’uƒl4fû/@s̹5 <ÈÀG ¥"Ø®PúZ(„jþ9El´è \z<3Mü…cQËd…補b¸Â©LBï §H€ÌwÈÈd³ÅRî¡eq#@•ò+F|úCkÕrÈ6±7è†fY²d{óMÕÓ¡:ꑟ/ÔCD7¹ØP]Óp%C‘MY“)ɺã=ëëþ?xÇ êÛ««Eµ|®òÒZ%KÑ@ <,«Å"<€Ëáá3èpÉÉ";ÐÈ‘1krmp±¾¾¹Q©)„RÎ^H$•”ð⃸€>^ï®xn¾òΛ^êe·{§ý5òÅñAgw f? @¹ ¢p>'ì÷¢že êÜ `ƒ €pÚÖ4îúuèWª¨¶aºmaPÈÒÁíÚZ:i¤tîïëߨզí<ê=¹~ÇEXcÖ:arÓ¸ÃD(Òz—ÿ1 ¡qúÇ¡½Ÿ<põèþÜׯekîY¯7·6ݵÿÇýáznëO¥­BóûnIAAÄ x‚ÛŸÛݹMìþ îÇ-¬™þ Ø5 2ƒ'­ïìÜxÛýô£_`øï¿Ýßýä7î[k\¶JˆqÄþ /D°0ÔÜÀ1(Êf¿Ã-f€ÄDüѤ+ËÅ{O:S!’AnÌè"ÊÝEËÖû —Çø'“W_»qóÕÚF¹P(T*ɼž…ÿï® 7T–tŠùÓzžŒßÊ«²S7ê¨ók6EtpÊZ˜µ5Ýu¬…ì( Aõ<°ŠÊjZS%Z×5EJÛîsgÿý©oxÇ êØ0ÐQƒžù€øØkyhpZ(Wqs%ºËleí¥R5“­³W3ÅLÅó[Á®ßm·Èh¡5?X>£è¿Ö2Šv(²¼^ßäæòÑõˉK …,,&ðbˆ“ pqà^ò<ÕK\ Ûl{É—í6¦oY<ˆÏ±zi:ÿv{?¼½8Ðíz³b©.0,Ü *áwÉÿâž)]Nkº…Ù¿rp9ë©•¶&wün_`?¢>&‚™ˆhq} Á„S'fÖ_!ן¹øŸáÈ: Ì]õÜ»× ëî»›?ÜüŸéÿw]Úú7ߪ—KÍí·Ü SW—ªµÚ¢g‡äæ‚—ûû0Ô+yÇ¢þ5áê x!~âúÎïÓvï¾÷ÁŸÀ>úèã߸w*ävÜš‰¶=øÇೇ¸dÌŠ pòá” ½x¶ÐœŽËÈò$3F1Äy@Dés<ùx¦™3a²ý“93"ólò\(¼á"H•¡¿`ÆÕ‡Wfõ­õ &„ò?Ѳ¹fùŸ¤¬éÆJÂsÒ鲞¯[ùY1x~ŒfÃiššæ™šIriA‰ß4è‘`c±UÃÕ,™öÿ¦±ýЦgLÕÒôÖSµ¾Á;nPßB »ºJJ¶XÍfª%€r¦†û-\-æÐÛíV«Õm…PÀ@ŽŒl”¶K–Ú¦í´ÓYtÍb}}}£R{ƒçÚÙËçátÉ@¼Ë^8@Å p^¹|ÞÓÎx~·Ûö/;̯·"q~dçÈä:Ì*¼OçßÛpÒ='Hu»&Êý.ìß6-…^ üõt9‘ZIBô›SHÚ'H£ÌçÓí ¥B]]–è^ŸB~.iôÑÔ¢ *æà~ÈŒ!L)êw;ýÇëñ.ÖÙÃá¥ëÞÝ.nnþ›û?¬oã‡÷ÿÍææfaë^³ÖܾˀÉ|¡$£˜«Z(zƒ. ;ïˆ 6¹õ•©7POã„Sú pòúÎ÷ÝßÞ{ïÝwßý廿üÕ{ïýúÃ>£€^˜Dþì<Î"ÀhÄÝ;àEw³ ™å[L €9T´"MÄ.fÓiÚª¡ M“TÅ0‘8<(;Þqƒòž6Ñ'ÜüŸ”柧IžrÅ«@-Sä«YôU”òW‹€NÈíøLÖ½ÛÂ@,Œ¾Û§È¸O– ì>úg˜Y3ƺTß*W*kŵ"ÅßÊùs—’ mƒðÀKxûý8:ˆ½Ënä]^!¿üŒ‡­ÔK^¼ä¶0‚ƒŽ;•° ="Öà¾ÝG!0lõâ¨ß# r 5lAèQè¸Ù–‘Rt]ÇîïZž¢­¤WÒ)ÉÔ9Gè8&ÅsÉ˱””Þ=ªTw8Ÿ æ?æÁõCh|÷!ìv@ú¹¨Ò1~Lð×}²/Ö㸿0¸o¿Ý,kë?¬UÂb™>–J•koo“ýÿà¾Ë¥êBª\­¡áu$jð\9GoÊÃ}´{ÎØfÂ01ê;dñ^æ[²þ6€Ìþ=÷Ý_º¿ú•ûÞ{ïøÑÇî[<Ì+d}Fã›;7«>âP„szØÇLQ:Avqˆ$¿P#sñm*(I± ¤LPþçûòä'ì•<ÜûhÈLC.oŒ8Ǹl}²P@pQÐñÎN­’,åJµra5_6t)Û& W µ~ÉuVä\&GÞ¿S¯Û «®SÆ1mU‘UÝ¡àÐ!ŸŒ?­Ò¾o¨¶å™žjjt¸FÛŠnyM þ¿¢ÉÚ5f'ã~e (Â8fPßFȯæK…r•î3O­fW«ùUrX Wàøüï2[¶OQ@ÈdàÑ@‘.dÖ_úÂoGQ„^aXÛ*×ÐX\,•(:—.œ¿˜RöýöÁ²Þ Šú=ï¢w^:ï]ºtÆ »žw!å¤Û[œŸl )7tÑù÷‘€ ú»û!zÌ®jaîbàHä:–)¥uè†Ñ†oéòJòr*)I)¹Ìº¶zy%mØ&º{ý³ ìZ°÷àsˆë÷˜Û³ƒ†!$$;Hô1øÓoE,þ.Áç­ÈÏqßÚl^Ûn^»Óܾ\£Ï×®]Û¾¶ýöÝ·ñ8@üë J0Ñ'¹g8]"ð4@@p¥@1Àj¾ºJwJ@~Ýï•üj1w%[ñàßvº­ îñô =ô€2cÁ¬ÉSõqi_ºõR¥X­TªòÙó­´Ýö£ƒw)åÅ`õ!P.{gÕ´ã ¼‹Ócks-Îtqþððü·¸×aШZZ&jû.k…ÃèÕtR7ñÛšªHRâr*%'¤†:È p=M‘‰t`1 HÄmþ»b]½#×[mˆý ëøˆkx¸ -ÿÄõîAä¾þ½?¹ÿî[ÿòõ?ùÞ÷¾÷æ;øÁò¦ëfî¿qŸÙîÐ „p2Ü‚- vµÐÓbáÞ©˜ça–Mf ç–{ÖÞ[¶þ¶ûɇ¾÷Þ/ß}÷?ûùÏ~ö‹_þêƒxg¢—<æW_yíÖMtΧòè=—Ïî^¸¬Ðþ¸u÷bÊ ÷÷<ålÂó  §íygRcG¯…6 èv7@íïøùQÜ‹{ ´:߃äñ N¡€!Kò|èPR—+ E–å”$C‚~S¶–J®¬´$Ë1i÷'—‚Ë}ЙÃ.\¿…q?1íÔêû‹¸¾AŸ ¼ÕY²Åîý·ç¼~pÿ.kÜÏL8ÆT|sÔ·àÙ¢4X¬ü9æQxÁ®'ÑP»lðÉïÿš ð.ÙÿGlÿwèåb‡žLnùß¼ù ¢€G·nÎfp¸¹Ž«öcí‘mÇæ]xÄ8 ~A_`ÆQÎ ³7ºfœÆ\v$ŠºH#(1Às…lxÔíRÍhkck}­:çÒæº‡yʳßm­Èj‡âêÛ´î^8›M_LzhýaÆïÈ;—'x+ìqV ‚}tþÛÇÏ|Ðî$¬;ˆz[Ð8¶¾’–4™¼}Ý¥_´”X!¥ôJJ•5´tض.¥Ò©KR×¶[æ ûÀÿ v|X\?¢Àƒ¾ò‘ù É[ £…o‚A {t½ÿìzxðÂG! îçïƒÅ„×5.¡ót?=ì\X›¥>°|Mc¦ßçýû«HÍ—®SðÙÇ|@AÀ/ßýå/ß{ï=€»ºw„@—ܹysgçÖWo¸yóælôðá\°v ?cV4ØÎÇ¢ùuG§ %A8ás¡P9‘ÇÅ{1à<[züXô¢‘ iC !17òaÅpÙ:÷-hO1zÈY úN­œO`ТôÓl²’(êÊŠa’­)JÙÕeÔ‚µt*õ“Ïsu©®f ºé6­|®PWÈúmIZUuEQ3)Û•\YwVå&ÂuͶxÈsœ:…úöW_~qÝý³ÿãÿ<1 x”ð¸A}û ’¿zµHwÈ ™J€µZ¼²ZD+0Ùœ¶ZA«Í£ïqðHÖÇmAMî3ýÙ ¶6¤­ÚFq­X«•6Ö6Û´#©ÛwÓ¾Jë·÷ûaÏwW.œ»@î¸KÆìI—È€{àZ9—‹B€´ÄCA…ué´fY 8ÉnGNK‹î"²lÌ ÂO§äÏa'³]Ÿûˆüùv@ÔÍwðˆÈUh/Öû}t õŸ·îÞï»îýö½·Þ¸Þ »îýûoRÐíÞws,޶˳ð2ÅbgáÙ‹1îž›/z&Sу¸Àóeëó1À'}ô €Ì=÷=œÀp²=B›¯Ý|åáΛ¯ 5À}{ÜdÀÍ÷³…B(z˜ûsÎÃxLF̼Â|»‚"|,ò~ ä6ÅG§?îC„C®|°ä9k‘ó0â²upŒYŸåÓ˜p‘q­œËÐcQ.•®©2¸üùe£ˆ.`ÝJÉËJóË ÖóÍ|•u´÷QŒ¨hj^±$Y—G'sÛÐdê{–Ñ4TË«7]³nš–õõµ¯ –¸Çà˜A`ÖG€C3‡ûÿ!àw7îX½B@@¶’)”^ª•2ÅVþJ¦Ì@a?BK.¨˜öH$æ|f×â|:ãèÓææzµVZm{¥´^«mÅ¥¤‹çÎû²Š·!õ>8ð<ó?ag?öÎ]>'óâ^xÀd ½ý9<ÿí£ç¿}x<(Ç8;}d]×TäÅo±AõÙÐ4ÉÐÒ*&™°; GŠe)TÒéNwîm E'“Ϥ­%~qý'çGˆÞ >êîDÊïñzŸžY‡§ÿÖ»À~Ã}ã­“ãÞƒÿOO€<ÕJm(®‚Ž9HNJÇK× ò&̧Êr>Ƙù„C€,˜Á~B€?UI*2Åî*Òø’îY˜H|Nµ:ÔDó,,œ/dÌl.ïéj^wó´…x²”Rm»®Õ¿vßh|ñõ'Öv“¾¶ MN3ðÓ¯ï<€ãõ ày¿£!ÀB*ü÷€Rö š ²è,Öò±d¯dÈa)gÑD†ß¢ç>[æd@‹A{„„ëA´܇û‡’ÓúÆFÖ=Ã2S.ÞöSZàGH¸…èç눠Õb‹ARïéÑæß㟹A'z|þÇÇ“w€FAM'§Ÿ¥¿R)MÑmKwl×6Œÿº©IYÕu” É•£ÐL¥°†Àh[‡×G'_üÔõçG9÷‰YÇh/ ýˆ‹¢Ó¬S@ÿbÝåu×¥?…aäì*Õ*…¸ãg¾D ½t¢b>ÉC´ÂÀEléúìµ›·nÜ|mçµ›¯Þ„¯ÿê+7‘¹H°'^á;·nŽÆ·^£X൛èf3å1ß9Œb¶µÏ9ë¹qÌæÏØ£ç2³͘ˆt¡-6\~üd´ˆ¸ÝµtbFP6Yº>¬£6\ȉj„0 ”eÅ ŠN.@æ§ÙŠi®6›Ù²¢gW3¹f.—YÍ&XM|ü¡ùL"ÿùj=¯åsUeJ¡,ÅúªîZuUÖëªi{À€ú‡š¶mš_לBä17¨o!dËd®dòµâKùõR®F÷»Z\Í¢x¯ìµ:ao_ð}Q‹ödßïF]tÂÑJ^y»ÝkÇu2ûJ©¼†( VYß i«'çëì¹ï^’5AÁߦÀá…Ç#->ÌèhX ’C ÿ^ ;æôÕ4úŠ¢*¦,«äâ¡Ë³t åhÃG±v%!©š‘Nò h3h§4²Ûe!ÀÝ}NÔÁVŽGRû¤ûC%ð÷Xçý g©Z夓óæ™Ý©ô¦ÂBE¬F ÍPž\ aøœûæ¢ï|Šõ]ºƒù…ˆñ3ùÕÄ*™8·x˜ ºàÂêBC(Ãòâ?Eɱ¢#BËj>û™ÝÖäº&7,Ó%ûÿ´NÏ”IÀo4£©¥YÇ êTp¼é稑 øÁü¾ @™b–î –+­ç_*jùZ>·š)¯æ¯®–=¿Ý"ç¯bxÎmtE( v{d>m¶"òÑÃui½ õ×D«ÕÍ6tÿ,M>{þ»¾¤¡Ã‡ŒcêçÏJ]=ã#ú…æq¿#ïß'§;jÇQDÑw RNÚ€M˔ԕ$Eÿ†f*iŠ­¶çšé4¹ý–iØ­&M[H›iÅÔµ´dtÒ¡Ôåf^®éó|o‰.æ€î¢…±ß%÷÷»¯gÂB./þCP Ñ1É6Ks™ñ“Çܘ-T0±þ|êá˜Ç&ËÖÉ%~…"û×^Íw^}õyù"^†í w*ôºè]0ÇÉ›¸(·$WŒ›œ»CgÐt!òÉ]xÜ+ˆÜFF#Aß9;ÿTŒ+N(b2³/wñòdH52¿Šž#ô/h…¹Ëo:æ9ß“×_x}F€Bþó¤W²B^0?€ÝßæóÉdXÔ Vr+¹ ¡ý!dX…ž}Èæ~š+Z†U7ÏR¬m]‘M¬~»¾í˜ÖCò>ÑæõoÀà7¨o”W¯æWË™ÕÝe­Px©”¥ÏÕ|¦\^-_Í–½]òÿƒQ÷v[àé{0cü·T9ùºáVy£RY«Pü_«®onViëó,W—Îî^ò}ƒÞÏüñããý§ŽG¶iÿnDQÔ û½âÛ}NÌõ!Ò ú1È‚¡ªkÉ•´qkšFVob P‘Uô¹Ž¥ËÉDB³Mì´m9E‡¨†v’é´Ï€ø';cŠ4bØ>9îOß_ç©ûû×s™Âj·òT1È´–Lv9b… ôÒ¢yÄø˜³T'{ÐàÃcž|2«eëHô^AÊŒü[¯ÀÏ]¸¢Ú8[ЉÞàV"-ûã™è$B$ÛLôADçò™š“ÕDyìh(м±=?&X}}ŠoøŒ%K¸ÇØ Saü™ÉHy¶cŠáx(†‹OZ?áúà/äsÔù?Ïf‹Yæ¸Â¤[®Ñ€b¡üí ?…|ÁÍ&óðŠ„Ù¼¥ÊÅA6éÙª&S`ëÛõí1ä¦!+vó9€'pÜ ~oÀë?ÀG¿Ÿù²WéÎÊ™|•î€9Üo)_¡ï®æÊ(;AgÏoµ¡óGÛ\¯^¿ß1˜òÄlkk²ŽÕJ¥¶±¾±µlv|òtM9{~ÏO,‚öÎáñ؃ƒ'ÇßfŸ¸ñ>ÆþÉú½ƒA¯wuãíý=挘—ÂÀívz%”àü‘‘àZJ7\Ï’RÒå´¢96ÏÛä‰t "b›²r9`¢½©ú‰zí¨…pØ„ þØý!-Ð=‹ûû×Éë ³Ø› \`²™GuÙmžÉÔ™l—CNp¢…wP"+vò:Xtæ7^{e报ó§÷……²s—ZX8¦ïØá„wöÎL?¬î7ôƒ(8ùVq~øô8?g2ŸÈ@lÎ Óˆi±÷cЉ•Ì€ÜÍÄ!Á¤Á,oL?ý˜½ÿ×Oº>w¾µ’4¸s–¬¸×9<¾ÝÝÝ1Q̤{æ &DÁ€bC´¿DØ—{á~?Ü?88.ôȯwpE’‚”¤u\‹~Yôeð!ìH¦&)RZ³ÉèÌxÛz§Ó’ ctÂtªsØÅŒ„Cr„q'¦(r§ïãÂ1ØŽúGïïw\ÏÄlœ 3ÙCm@!ÊÇã7œDçBvËñD0vÎÁÕË!Ü2@"Ä.[ ú›¯×ýæMÏbÈvÁ2cAžìezÄÄp¯yÃæ_Ž„ZñéøçœŒ#Ù"4˜?}þáì0­¹=È0}L˜ôD¬ÃiAƒèœp}€)Ò–®Ÿtý¢€Rþ·dÇn·b¾{芳|AC±ÄóØyp`Ò?¥Ï\CÌå,m;Ÿo˜ªéZ¦¬6¿øÚÓÔ†®×µ/¾üʰT#-©ªçþÙ©]ï¸A}c8Þð{øõøõO(P”ÊWr X+ò•|þJ¦¸šÉ— ^·Ó! E¡ì^‹¶²|€^' §}ú 좮¿U¯­#ô¯”ª›äG CÏöM¾}®uyE58èî´{Á“ã¹É§ËÆ0qˆuàM ÿ&à úƒ8Š›Ífÿ ?›XÄÂûàývÌ õ]9•–X˜v­£*È4¥”¢+†¢@ùœ°Zº®Jé´a;ðÒi 좰‡,#ÿî':v?~‡'~¡|OÝÿé×ó!Ldò‡XW‹[hÄv8™'ôýîrÓ È4ÉÄ1:|ò:+†M`ÏÈaISŒ×BxÌNøxÎêz1̹7fÍo¨°‹ „C]?s¡70õ&ü\rþyúxJbX¹»á„y™±GÁ;;3ûΙPŒýÇËÖO¼>dEåJQ$È!­=fã¬Vår‰_Å «‰À3 P(¦‹èÐú‹\–´Œ®ç?ª×UÁÚW_š¦.S˜ioùÅ×¶iëó®rþʼnpÜ ¾}P(å3«ÅÌ•<Ýe¡´öRu£¼ž¯d®ä®s•BΣÖoù{ì…`}ï½=rÛÉY?„ƒ}Ú6k¥j±V®nl­uáШc›ºr~oÏ¿$àÛiwÛàèñý˜ö <B£“UiÃôÁ®C.@ìyÍb¹Ö„Ðþ€ÞßÛöáí;–á·÷$=Ý&›†ü‚ëZ~ºíÐþ¯Éä¹­h¦A¿?PÁQ€ ¡eº~)©h¦ãfPøÐ wÁŒ!`¸ña»óøþºqüàGÀûw(Ê÷wt=YÀ)׳íf>•6'ðòð|.syP =Õô›ÏL(àð,8÷G‚‰k6^ºŽ¼Âh,d¸†"ß7‹‰£‰h@¢p&.>=4÷©ø0áÙCPeÁÉ‚ëgÈ£z“e燿À³»sæ/ Q@¡î1a³¡  oC&dÄLÓáDDC'¯Ÿ|ýZ ÊâˆûéSmíØ«úøU«­AK¤„p ˜B Ê£~˜Í©vÓÝÖd ‚‚Î×_Ô5l“ºg|ùÕ×f\Óöž“|Q@à7¨SÀq°CiàØK€Àï ¹B%W¤»ËTòëå*ÀFi=[-^)fÊ2æ°µ‹9à¸×ò;]Q@‹wÛ~¿K8æõk×·¶J±¥ÚVm#`•½önäÓf¬Ò…ï^ºìK†¨%·ãÇ·¡þq;Dn!Øõy²6îÒýƒ}¯¶Q«zÌ(ºOîÁ   M¡KO)í®Òmæýð;¦áš†ÒI¥Û¦ mS£è߆‡€\ eëF:•HÓ/бÌP »©tsÍíN¿n¼xÌ÷»ïâÖ]nÒ甽H°æ÷Ò11øB‹›óCÑUÀù6úŠ!üåçgu² ;#P eypŽİÆ|$÷4#ÉÁépÁ,vòúÉ×' Š=¾RY«Õ08ÅÒ"XOa6g,Xß\«U*ä”K‚®,-¨&r͆iB/\U›Žýå—Û†"iªL[I£Ùp¾ø²iè×ôíë‡.€s žô5¨o%”3twÕìzic£öÒÚ&8L¡g´Êl²ìù- ›£6!4´wa¦´k!íͽííõõÍêF±´µ.!G’ýƒæÃEàÂwÏ]^‘ ôÚ0ÓÇSÇ£¿¯»ë÷q;èF ô^7êw÷ãÈ#ó'(”jÍýù½xõû´T¿%[„-a¼¿mÝèÐ~ßõåööŽaÛ¦eÄô>Ë1A à˜É•Dª­ S`˜zG’Út1"¿…/îÚ_N?zçGïøï°ÇðRèþŽ­“×Oqªuzº ^ý8€ lÄVÅr@œŸð°¦k˜ø—)÷àæ M>î‹/[gz_{–誉$þ¢>?Aºp&ÚöX؇«íÓCÆá¥Ɖ[xÌ÷qòùgr¼?«0“ .]_v}fUÎÊT . ²ŠÅsOŸ_@@ªüÓ<úsÛ¹ŽuÓP4ï«/_¾>ݼ\´‡6/zŒQR¤|¤è\ZƒpÀ§½³CsÛïí{V@UÒ¯¥5¯yƒ{?êY`¢ÝÞ4UKÑAãPH—P!Tƒ@·4þÑGÁð\“•BQ4)V$]S[:9¡$ÇQ M|-LàþâîÞy'ìç'\F ¨à $€ã£çž¿¦"PNä14´šÍÑ“«ëŠ¢ÔUYQÕ¦ ';¿ê}ýÅ—_i†ãÒãö¢‰ “<€o!ž€Â3!ä0ü=?Ø "²<àq]´ý8Z_—ÐhQ!`sc?ÞïC¸ïà ?èwºÏê²töÒ…VÂ71:@›<Ù÷Ñã[rŸãÛhDÇŒ4Žân¯×ë{ ²ô Úü7èsÕk‚w?ìE1j~é¡Á{=ù¡i€º¡çtŒ¶®Ä=¦g[=ÓäFrtYSMúÚs,Ë’’²¤èA7ݱ---µbˆ†a¯/î¯ûàAø£wÂKÆON@L_Òqb]týÒýGh ú< |tÝ3AK‹Á$³‰šœ”½l.“¿J@¥Zã†7¹Ä(ÐLÈ„ñl0{ùÓ¹h€ŸÎýL˜‡ÓöKÖ§ìL̸~ÎsCîsv›ˆçs¡'0æÿñh!í3fÙNŒ#£±n|8xÈZ_ü¶©h^v~–ç˜AÌð±hFžÐS8™ó¸8>çÂ9óÀí?„FèúY¶¾ìúÌzŠ4‹ºÌ·†$Ëôùç__CÚ™DÎÎÕ=ÚåmÛ û'‡ß4¶ë†ªË²"7„Múíê§axN? pºTßñw•6xd—@Ôîúíönî…HäuXÃz8ÝÍpcm­P)—jÕ­MPêăA¼š¿“uY]Mò/íîù>jÞÐwäø0Üít:·):è}¡Ô…zŒ:Þ&‚yèô¢};´·›šÕ…þ‡E¬æjZjhflÈè1ºm C¶*Iª†’ ËZAZ:ÔÃ@ ,³“‚ÐAÀ¤^}äó(&!Ó÷}ñéSðàÁáý±8HØA é=?î •Ä§×=KWÓÉKçÎ_J$S©$Ù?´+sW3ÜÐ…à»íã…ã=rÃÅ =là“AûÉëLûÿQ÷fÍm¥Ùµ`=ÛåªJ‘¦ƒP‹Ä{rKU¨‡½¢a²¢‰IåÀ˜‡%KüƒöOŽxj ܽ¾éõ&Xüâè®ptŠTbyÿõPkjT“?­§«©rM“, _.è!@¡”;y\”ˆ1›ÿûpˆ;È ›<@ù]pÿqàÿ8°wÝÔo84è-Ó°‡CÛZÐÐHV™ãÀ;8>lw»½N§{pxx| ¥-7€ô‡?®ð”íLæ£á`k+³½­åTOìÊþñØ“\€DZCpý@eÐÁ)ýXE•?fÐ> #ÄÑ$(Sï* ¶›“,˜’¯#Í—¨?pszâ ¥B)” ¼"’˜!Ÿ×²:ô¨&šÏ•Jºæ8ºž± nVc¯Þ·ÇØKÇãHÎý¿ø+ó/þú‘Tÿ±þâ¯âûsXû“àœ%žËQˆ,é7Ö+¾Ö³År!Ÿ«¨)ô½'Pÿ[àC·õÈ º  Wà‚•Ú9K…°Ì…06¬S1˜´1Q׊s8ÔçCjŽ8pê‚pI*²X®/Rkf!SЇÅ__P²—ßËM×ç ]È?²§€Šãl­ü [vÈå“Ñ‚HaÀûø@6®oz}>y  *—óóÃØF¾$E$ò¾ëv:­ÿœ çîÞzµý’^ÌÁþ%’+ÊùUÐüÿðñóB?ŸÏ¦%´+Ý'ø·sïs×Íÿªaßæ.¾éê@0òm €â`§¦åF¾çBJûàè ×lµ:Í^ï¸k™CÄÁbÖ’¬ËËÀ»àØß>0L-õàA*ƒžXte?å8A2@>ÞÉMÏu.jâ øvØC `<‰  .@:hþ ¾Sôõb…`Ÿ<¤KEÉö+âJTB i *@LŒAÉ$(I †ÏYì@:þ8»V8™˜)fïYõx¦xùßßÅýGà,ˆ*‰hÿ][¯Po2—Ë¢¨¥’‰TºRƒ€õ^½ÑjõØÌÂp‹œk¿Õr®rdÐàΕ\L%þ/­7®ÏAÉC-mö 1ãƒøwAQŽÐ0Ëg—~¦ C ‚ýˆÄ"À….Õß|Aº€õ’£}¯?%i!)@8Aô>Á,u,Õ ¿ð±mTGÝpãúæ×G\¤t19¨$“èÎç·\¿»ßn©!‚Z¿Ö¯nõku9÷Óé\&óó_=îƒìãõÇrþW>†øl²‚÷)þþ9€Þ`⸠4\H€bnGRxÃ=rŽ·;bü݃Öññ!A,îƒq '‹_•|N û#ã£ôö¾ÿýD.PR»Ø™]TÍPH¼ !Ë3ÌÀ¯<>>>:øOu{íär ¢ñÄ G-fýצäþ`û‡pqÔ0—û÷$hp-y(–ep} IGc ÜJAWÖŸÜÞú_Û© uÁªµF«›îͨ†< TÄcÞ°zœ£r`rð‰]ƒZtI/D+EÄuáÞ|1?¿¢/YÍ6^w^Õ2žê[)Ž?Šbª„…ø,QZœ®ÔP".2ݼ¾ùý­§1K"y (ºÎÇ­¢é-×ïí·Xø‰œþ` ­ÖjôàéÜ/ñËþÏu³‚þ<ÿq¾•ïçóÅr6·ód“¸æÚß V®8€öõ@ëf BTî˜~è›'èlÓôŽ{­ýV·uÐ<8èÙ® îË '£ý9†1 Km‰óØÖ¶¾ÿGÆw¿Ÿc—Ÿû-ÛËoÈ Û.÷»   üå_MïâþèL [>øDyÿbú£p†Áh4–/×…+¢HQb넯ï”ÈTìº+@<@»Gî*îc/WjTvÆAÅЫ`ý/Øõµ6­K€»F.RÍXiˆ¥üå*®âø#¶oNÔ.g%¾;e|±doýVAüÍdC„{\o‚B¡Ì(ª¦Øjdã%2‘3górª^Ãúæ×Ÿ’,\±…0BPÄéË…’0¸åúûf X ÚÉÓúýú–|†J ›ýÕ/û¿8ÉõåCõ¸_ʲýÇùþã¿?)V 'âž<¹:ü.°|ÕÔÛ¾} õ¨]¿†¨w®9€i¸äLväÄ6]ËF—ÿààH’¦æ~w¿òxTÚ '¡_oVbòR>§=0·’æƒï}×øîG‰<䄱?€±!Øw µËëq¿ü—žWé}ü¸tt€ÀÑÑ~ ô'“I(æÅ" @Á‘£\×Ëèñ»ªÒWô~$çüNi@€dð/Œ1—+Á„®üln{;‘| Yâ3ìdÖö™ø¦íúA41¡<0ÆÉÆboL‚pÞÂ98$®Ì'³¸CáâhŒ Fñ~!d:¨“|ô½ïþÁüÁ~o+‘®4Ù  "!BÕ±~O¸:ñ7+û˜çHø;kà4OÖ ×›ÖñÉGÏ üåâBMƒ¥®lš#HН[Åê1Ñÿ<…†õ¥€8tCgä/šª‰»®?WÊÁ³™KÁ<Ÿqt‘’†+òü¬‰z$”y¡@ºæL—÷YßôúH¤¦ÔN]*Aœ÷Ó‹h¾ÿúû½V£ñ[õ|UâÿÝj_4^é— é\?û¸Òœ+öÙ,_¥Üãñ9ºž¼E_(‡^uú}µïëÞþôMs÷ëý¯TiKRzÕôjë5€‰åÛÔÁ 't „-îKö3-ÄqÄ)˜ˆŸþ\NKhpnæ÷Íï ¾k<0&ÐÿØæ; +¯…~ÀÛý&:VPétZo7ÉæÔ8999‚eE!¦QÈ/=Wáý0wìÊÿ­ Ú³ž>ªH4P„KHˆKÌŸÉæsi]¢¶B±Pª”ŠZb;ù`{KKe³c§ƒ €î8 ü±9мI`z&FFÞ™‰º? •@$éòþ=uÿÑ$eQ8! xá¾ÿGbÿôƒíTP òQ´º=@fnÍ1žµÖùýP훑õfNŽÁUs *^$ÛÄgsk.§1pn5UòëÈŒಠÀ–;†7\¤=òBžg,ˆK›È”ÚãŠóW¡ŠP¼cì³fWdJi°»×7½>©AÖ$ C7`Á¼e®BÔn»>Tœ[51ƒŸäª{ðµz?W9ùøä'z.ÝϦ÷?>ÉëE½|rd‰žÕõñI¬”*wу\qÕÆîï†üwu-¹«êpØÞ»æ&¡|î]chæÐŽlè‚âiµÛ½ö~K;p6òȨት@ ›É%¶’ÛÉÄ÷¿7ü¡ýz°mšD¤ä4;Š<œôP»¶Ÿ[99.Ÿ©_Ožúý\<ö#?ûî…6`Ƀ‰S Xt) n`=;ÐNj¡• TDK9MÒ]Ïr¨ý¡vSÊl'“¥R’œx…¢ž-zNÒ°ƒÀ²lÛ¨ýzfè™ÁXbsߟZ¬Ëû§ïßCÀ4ia$·RÈç2â¶$øÃï~+¡e+ªõŸÖ0yš˜§dôØÉ‡€ 5·9ѯÀ»ƒ‹Åj|Î7¬ÃÆÖ@0qf…ï‚JxÁqc´ÃâÓy®F‘£Ã.æÌÐål}ñòüüB<8öª_‰ºÛÆëÏw/TÃY?Óoܘ*&ÄlÞ+jŠƒ…ˆ£ºsúŒx2éŽõ¯AdFU˜o˜CBmNtÑÅ´ãm×ïµ›ÍÚîîã¦VoVk¬êýÊÉ/~Y΃ X+<Þ©ŸäÊbÿ;â²’áî`²<·ƒ àoÿ·÷'W@ýQ훃ÜßÜæîóJ•F»ö¨~Åt[ª¼u¡í:¡X¥)ÀÐÁ̼Ö?nw:ûÍýfûx¿ß? X™–ã’Ð’@z.“ÎØ¶üà{øúõ씕"#Ö ä\à‰?±lN\ÝoNß/ëOŽòOŽ OŽºf³™ÌGcÉz ˜ôñ ˜öÙÁi²ž|» ñ@5?èJhVÊ(æ¤óyð`–+™T*ùQ"™HØ[nÂ.–lW\ˆfŠy#G üHÍ÷M@F%A@|ãû»X{ÿÞåýœYö'ˆâ ¹ýѾ÷Gß8Wi Xo$ÛÝ«3EŸÃÎ6Zç*qEmžbÁà [ì6#\‡ÝlÓ:'ÄTæŠbø¸)¸<”šÏø)¤È`ûªý9…ŠE{ ßzþâåÙ‹çоRˆ ‡¯˜_!r¦l[.ÑšÇTQ¨+ÙoR†€ b¿Ó8i¸Çúæ÷·Œ©ˆu§à’‚F¸ þÖëw›ÍˆÁ÷våÿP­ß¯=.íþ«_þªT)f²élAüA¹ß/ö‹åÇùtöñã>æLÑt’^éoþ†>@}•Øyºéª÷ÚßBPk·÷äÞ®8€C ®¤àðð,Ã0}pyaOkKø¿ß•ø¿Û=¶»*0ØA(Ó‘Ãp p.ck~ð]ó{?0Ó–2+ΟŸøL—lY¶ûî~Ïð‚ ø; ™œ.¿žà+•ÉMp–Ø€°Hò‡.a\üø`}'*©†`±ÐÒ‘t*+)€8¦år!¥¥’ßÛ~°miÛnÊ*íL±à¥L±mŠƒ`üH¿@ÝŸí¿½¿Ëõ÷Þÿ(šÀKMBÔ#$€ØÞÞóÏä+õO–zã’La×” 6ùï—¤ßãºÝ u¾±Ô…Ó™yþ†õ¥ªòp\0ŸŸqjVAågl=(î¨ï±KO$Âr¥è†<õêùù+j_¶ñ1»éúA̧K…IZ31§ÒÇJI ('µßJ‘‘CégA¢¿)'w7­o|}j.I’ˆ,=NL\!sX²yËõ{Ín£S¯ÿd«V¯iýZµÖ/f~ù‹_þêç¿(åsÐîôO>ΕQ ,–õ”öñÇ¥|ÿ±þCèPO0À¯ÿ5ö×ÀÞÃÝnû¾)À]®à}?óM‚þ› Ñîî>Ü»âöjj—ÀIW€i`ôÔí¶:Ín§#®âÓp‚ŵ/nB‚äq0F`kšù‡?0SòÏÿaÚ†ïZgúaAŒÔ9®yËþÀª /ŽVˈéäAöØÔ%ý"€5ÀØ—˜ä—¡Û¼SÔ¡ß.‡}¡X’,-À3ÁtÝrš•P” wvr¹„–|ÜN¥rÉD*“2]W/ØV‘ áÞõûóß½¿M÷?–h4AåQy-•JiâÆ*•š,`MɃ#2† ¶b³RG:Ly q0õÕp°Jo©0OÞ¦u ‰fœÂC„Á*ß”†5ãŸVq¥ž¤€Ä,I«~Jq 3~v&À™Øþz¥<€ü¶d¡`¾ÚtýÔ8<ßk3Whbài˜ê-°²¦!#¸_"Ëß´¾éõçÊbÌr¿ÀiÂwDxëõYû®Öêÿ…âBµúÇÅœ–ùù/~ù ù·ßïç×w˹½l?­ï€2ðñãt²ÿ8/?]+·ùô=©üMüE/Gößú–:€<À[ÐíTU/°¹c±È¡^oË>>:èµÚÝN÷ø°o‚Q? ^€™¾ålK‚áJÅÎiæ÷¶Åü+¦ïþ)X÷ð/ä¿ÈškD·ì |1‹X=©et[Í ŠÊJ6(óï`ÎûbY¡üËq; À \.b@7¥ùž¬ak1“Î> Xø¶–´·³Éael„/)¶½éþ6­;Qԣ܄žS_yyéC*Sîí5”X°^5W\^Pû^P™w‰Ó -&æ¬V£þ…ì`«eݽØ=H¸±¬8u—€¾*Àz™’ $ ý;th±¯IǃY™g§gÏ_¾ysŽ¿«R€¢'ráî룭ŽR$d:Ê9çõQÄl.—æJ0YÌŒ> ›×7½þœDÔ \ÍÈ{1uŽAQ­àÖëwA VßêK Ю®g3Ú¯$8ùøq.Ÿÿû“ê^5·W¯çrzÿDÏ=–ïãþÿõ_ú¹V¡ÑÈ7Ø~RêIˆ/‡Lû­øÛ¿ì¿Yû%›À7+û½ëjMx€·@ÔêÃꥈ‚P>æÆÀ0ϱŽö[ [n8Ç–ÁÛ©Ûé¹Jf Cdû“Юä3bþfÊQiJ6ý§Väø–ëÂØ’RG·ï~G¯ “žÜ–c:‹zÀ“'fïÄ0 q^9Ž`î¬ö¡ÃW`ßOÉÝÄ $pr)ÝcMPŠ\"™Iˆá'ÒÚvJs%Hɧ\½dĤ0Êûöþ¼÷Üßæõp$ÿÓO®²ìí÷z͈PTIXÝ#IøqhS±Cü¡&Þ IDATUš‹Ù–cŽæ ±]^ðnß¹NY-EÍ'!Ât©Øƒ¦œâõÙž_ªé_UÃáOSâä¾X$ÏÏÎÎÎ_ óF*@ÖᥪPl¸><À,¦Åè«j8PM1,”9Ïâ×_Æ#{±‡Ø´¾ñõç ˆÁæ%1Ò$˜­.:†·]¿ ’à½Z}ï§T ÛêçÓÉLþÿù¿Kº~Ò^­×úÕÜO'ó彯eIô¸^ÛKÕÐø‡få?7Úÿ­õCýI©ÝÛ‰£Ø<Üë6ö¾µ`¯ÑÝ{xÅ´Úûâ”pßBÉ‚ Ãt'~ƒhH8M@\‚®[½2O·‹Ý)ät¹f.“ÓÓ™TCž +­Y^©ä¤Ìœ¦ïMÝÞq½M÷w¯õÐóœ¶z¦?Á"/¬ù{rpÔª»µ½f;KU+Êzá“˸>æªã¼>éC«ñõA¡nÃ: 2颷VÆŒŒçUŠ‚ŠˆœP töç>òöi¤½í ¢3>°Ä\ÿ΃>®Äú˜¸Åļ f1Ï»kÿÁÁ!à…‚žÉkrü? !yû ª#®!û,€óG“ø» 8ÃCqhÁ’!1È?ºüÀ€ä…B:«—2…\:Mæ²Z&•–ì!¥iCS+”rùR¾¨oº¿û¯c¼ëøfÝóÔ¯¯ÕõN·;'Ÿ9ÊR+öÊÆ.ª,w3¦´*óg½ŽT–w¯$ŒXœ˜qVsþô¢4…pc"`­ŽJdf±D¬üô¹ÜÓéÙ‹³ç¯^S÷ˆ©Ã6_¡J‹‹qCY?ªy«Éãx¥7®¦£(R6¯o|}v׳¸bʂǂÕÒ)µ n½~¯ÑjüïUP6U÷ШíJ^¹÷StnwON$9ØBYìDâ€Ýê#ª‰ïBYü§{ê]n€î[ëÛT€$ì³rÐÛû/'à·Ä\Lv÷öÚoÀC‰É £/ïYÇÇàýjw¡þ»ßjõ:ÇpK+„îלûDljåÛ8*ñ›dÉ–í“Øö†6øüè1cgƒRSLE’æ O€Þ…ØD")i@2ù ‘̘.ƒm[òmà Œ©†9¡ ´„  ~“AÀyrö—ø%ÑAÁƒ¸VÌë©”žÏ¹VJËé%ïAÆL§òâ!¬«×—ˆ~00-õþÁý‡– X¹vTðpý÷ÿvýçS•ÄÁªõV·ËœÖËà ¼Þ„¯«n;,zJsRõ<Îr‘ŸâRèßU ßvÁùw×:'`– % ²Œq1°]+¢@q!/Q_ŸKðüù+ž˜˜ž+¾²Mû?xZäKJ˜òIÀ^9°0%}ÚJÍõrr]K ŽÊ¶ãò>ûzNžÓ)£&DPh5×ÕzsKrú½úîÖ®˜8L¸ù>¦Ý@úVWë‰Än½ö/HÿY3PEn÷Îzå°Ví¾—ô~e»(ºÝü;€f·Z»âvk½G{ _Œ££.¤›-ÐóµÄtl'ó¶hå.È‚MˆâáÄC+=qÎÏú¾Mî\±mßÀد˜8Âe¥Ñ :^[¾ ý¡€NÂq½âááa¡°SÑ‹§R8ýQ Håd³ a” A- ¦ðÉ(òÆš„#ùF4 ‚Ócq0Ì'»EL)êùB±Ör9«€¾Ÿ^Jj™A:£0ík †&–@Ly8|> Xô‡ðçåºï„Îåú÷RT¬¿ïùPŠA&Š€35`ËþZ1Ø1Ÿ./x¾Pðš1MXÿ¿ pFLÚAÌ|üÏJcŒ¸—›Ö9ËxFÒ‹¹Ê˜gŠŸlyЂ…=~zŠF:ÅËç /·Ú¸ÿ×9 ¤ªS2ûªR='¦¡4WŠå8Ø)T¢”`VDs¾iÿjª8ÆI @Fñ©ªWÐ4êÿR ªäëø§ý¯u±è::¸ÿV¬ïí"œ“ÿ¥ P½ÖváµúÍõJ·z +ð·Ï´»Õö°×i<êT¬À÷µh-ÉǶ-ößëˆC0CܸX°Xr`ú’ãOÙ¶KBq6öÐ-·ˆä+ò¡Å7€”&5º=* ›Ð膴†l±Ë€Ojì¹LR²ÿ[I Zà&. ©=I%œ ôGA¤Jâ&D’ádýï”Ë>FƒéÊ;eÝC:~ :ïÙ‚•Ó´”½SpSSËZ¾ü#§ú 壑¸šákóõÀfŠS°n[¿þþÃà…WŸ>¶dŒMkU޲3F²Jšä®nºw9SÙ:e­xâ-Ès/keàÁ¶aPïD;‹jÁ›Öø'ЂLdd\q¼¬¢Èà1[KvÐéé©TJn7îÿÐuPö.Ù±½Ç|vêUìx'Döã(ܱ?碧œj+ÒÝûÕ8°¢:gÀAâr¢ˆåtPkT÷ªÕ©V›UʆI&/߃ïn6‰U O²GÍZsºÃP}k$€ô¸¾^©7¾¸Û\uoöæÎ÷]ëöW¸æÚõúUÐlï6*bmýƒ£N¯#1@³}pÜ;<8<> Ž<Ò÷¡bYÖ´ˆ‘µLÛvü¶ æOÛ aÛb“qäDÑÈr ›7ÀÖ/4ºåË•´> H¬ïï”öë-æ2™,€¶hºü(D$‡»G¾? ½hH(àG“Ñ(W§(8ñYÎ`‡´ÀyÓÂ:&•0,Y@¡èf4ù†c[¹tÆ–¬Þ1‡ƒ×˜ Š€í5‡¯å”7œ¡i ïÖõkï߃Ƹ %ÄËçƒó¡îYµŸî1¨1X¨ª:Ö$õ‡U,€qSÔHñ§,°PŽžé‰-ù,@¹TÔ—jvwNålŽÖA¬ _ÃE5x# j÷¬UÓl1SMò)¥Èô¿¾þÜ´ÿC×§*˜_¡sÐ3e‹qv#ÊÇ$|ÐP ¶ð! ‰pè"-Öàîý` Z#'€ë`%% 5ÝÐc»•¬^Žh‡¢9ÐhBK¼Ö×]C Y£‡Õ#Lh4àzBͯÚjÝ\¯4Ú¿? Û¾æê=q¾iZ‡ô·šÝÖA¯p¨… çf ®YÖDTrwá¥mK¬.?mÙ(Ò…´ƒ5g4a¹\,ªÜ¶ ¨Òè%a¨ È—ËyÌïåÒéD"¹JlmoåÃЖõ¡$Ôˆ|ðò|?ÂQ€N€|…âh eR‚—0% € âÿJÓ@…\^"‹\¡TÔ’)-_Ègu#_ð²9ËN”+6 CìÝEÔD3ÌáPŒ04HÎ|Ûú•÷/‘‰ñÎó‘D`C~¯~¡ çãìPÁ8 og5j±Pþ žØ,R‘Ä{®X;H‡½$¯íL‰Pß)æn7­Ó逭úé,æ!P8Zœ÷³˜-€3Ê—J‡Œ\Zäú¹{ÿ‡®“'%Üçâ˜#Ž{îÎÙ à71õÏâÑÔp&twïçXÞœ*¬9¸àñª‡, UÿW±Û=µ:üÂÔ;Ü€Xt³%ÿ¯u8„zK"ƒV«Ýê€KL‚º&~îõJ£û^ð~óë.Š®;ÛöÞ~­û:€Ãk ÖÛmJ àt[ûûíÎÁqòK±R9¡¡­Ÿ* ÖÄÑŒÐÿÒ¶*c…@öŒ!&N¼‰ÖœÖ^ä{ƒ8ÂLq±F·ü-”+‹û½}Éàó:'jÅR·lkv"‘·äõ}ñ0Ž+¯îŽB‰<ÉúAÇ5F+0˜H(P„‚‡ÅBå@‚…ŠåB!i¼^ÒÓ©í”&.a˜IëzÖ± ÊÆp) 뇨0k9C±wCÞ‰oˆùß¹¿ÿwŸOMžOÕ¯R¼Š@ýrˆÄ|/ç?5ÛÉ-ñËÛsC3Q2É+ôBÌ ‹é‹Mâòª11,9x C‚ õ%(Šý—òùBIÏ& M<@Q7¬œÕµLr4‘‡kº†cLƒè4L× ä´7ŒÉ†uõþßÿ|pú»ªªüHqÀݱhM9 5¢áX–—ê6$ÑYqŽ•²ßhÕÆN„ñXîŸÃœ–€°\¨qœ;×™̈£YÏÎù…ñ¹ù*Žˆ×¸ƒZ!0|ªèð45– 0üv?aLËëû?|}ÆÙ]$p}+õ|áa²XµHû¹T]PP|+dô¦ý$ž+1*2AfLÅr/½”Å‘÷Ëzû×¾”hvZÝnš£°`Ä&o=´±:ǹ¹^iÝß¼Ïø¯º€ûþ8€æ ЪØÁñ1˜ÿ;­ƒC´ôTƒƒ‘ƒz¼kø´¥âÒ{áøC)ãýmÛ Æ¡ S’Œ Bƒ y¿ë‹1TEþRE"IÐ1PŸI#H>°·­D"gQGµ¾B$n%’Wa<¡8.’`Grÿ€@%'¬vXW”oé~¡ä»ÉíÄÖÐa@/x–­YÚ8  Šm8RþЗ· #–pß|nŒ6¬óý¿ïùÔ½ª-ÿÀú(*Ã(@Ž ·9D‹©UZPC .rcÚU\ÎO6ë{€Ë¢âÍÑá•âùç4ŸÒõº{V2'QïìüãÇåã{~®h4gjXAØÈù›…:¯áŸ@Gˆ åíþõE¶peÿ‡®SYDÑzP€T"*¢WÃJˆ8JL3’ï(¦R]}Ã~ÖB˜›TÌà (WŠ‚‹4ÃÉw:û½ÞõëSyt-f-ÆÞ»ø‚cž/zo¿n®ÿ^;€ýz«âhíƒn»}Ôí£iï¸dþò"Û–(ÞwMg|؆$ö¾ëc„–€€¸y¡¹®À7–l]¬4‘=æT صüÈõÜk™¨ï»å jÅ’$J ¨ÙÎvBGcTâreü¸ÜAà‡cøÄá¢áh8`x@JsaF¨²#6_A+Ð ¥RàŠsq0f¨™NÊ-–,+gåRöªT‹ŒáÐ0-?]ߎ³rÂ>6¬ãý¿ïùÔ÷jµÀFU¨qYPdÅŸƒêþjQ2Ã2<3ŠÐ<ëŽ.Ò9ý£ÑØ&ŽÒÄg ßõ1gàAÀ4¬P2€Š\ù²dìi’ê‹àlÛYyýPÂ9†KÂq/\'ô w,W‹aøòŸÑd&àRŽxŒ BEÝÅ7è‘S(eí”LZ©@³½’izº•ÕìɉdY¶38r ;bàÁH¾|Û2µiÅ¿÷=ŸšÿÓº]× yÁ›ítoI¼,ô­Y¶_›÷ÁÕ„I+§ê;£ àŒ bh$ð%ΖÂ;K6»6­“CùòùÇýÃÃýîñ"ØÃs˜ ‘€l<Η %›Á{ÕŒPÅåþÙŒ°;”ݧŠ^—û?p¼Ý¤'@„Oéþ\.ùFæîA Ì"Å¢^KŸ— A¢£ Ù–a$Ý‚¯»š§õB&en»£ ¾¼9ãMÛ4 CÞG0†Bê`øÚœlXçû¿ñ|ê5¯¾'ϧVˆ©ÕÍNo½dΉ<9?z1ÅÇÍ+ºƒ%xëXx'bx1S5n5<‹ès•«Q½‹4þöuÔÁñÑŸ‹ýöºÇûHbÏã1 ‚R†$<2‘ýÏùq^’‡@ígž `SÌ&ëõ¯#³G&¿älÔ\£ëþħÈáE4øˆ&ŽyÁÔ€tiwï_($ðL)…Ïgì°9Sb¨®?#t ¨kbY\ :øNWä*½¶þoá>ÜüïíÆ×@·Û¨ôŽZn³spløL{@¶~£j}F$¯ƒÀÜU6{‡UÁÈ‘ð>òØ&eîØŒ_“0ùbÊHlÛuÊÅb¾×ÝG±.“• ál'SövBsÒyÏ„²€=ô'ˆá7¾i6üŠï‰_ñIÊåNF~QKÙC þ`]w‹ ps…ÒÈKYVÖ* ž*ró’ QI¼âr K”o›ƒåú›°ùMë7¼ñ|ª5õ|(6Qô¨–À40eý¦Šßcª,|ªô>13'Ó?ôƒÉ¢Cú &Ì4h•,c æñ#¶Ž§:ao[?½ø’:ÿáÇ'zÇ`nœ«Þü…²Ž‚É@S+f"Q'ëåÂÍL9r‹vÜZqñS¸ìƒÖgŠ•l¶¤`òj;Ìd\.P´‹iŒQ»g‚â¨"E`±aÿ”´b‹é\¡®©Ë@’°øÜßt}¦ Ša|½ˆqF ¶¨©ðκ„пOààšètk•£^û¨³ß9<F{‘æ;f„"g"ÙGḴ]ÓÛ Q±#¶y`ϲL7ˆÿ%\Ç,ʃ/À¶éE@ç…@¾²9piNÂÖ–„™@l. ²@ ?’“Wq\¼c/O$/Ÿø”T*@d …|h©è;iðJ€‘÷ôR¨Û Ëû]ïÙb!›/H'â;"DôÃÁÐCwÐ h…¸ö``nZ§†ÂûžOÍV“%õ¦† çp¬Îª=ã€>dpË•bÑ_«Vþx>Ês"TÆ©´3Oªö¨nׂhâÛ×O_ï˜|3äôGUP~ º-2Fƒ|µ@Ë”ã~ý‰œÕH G€ØDbÄ`²m9³u J¡ò—Í¥3@‘ •ÌP ä´õ}ŸS öÀ å’®Œ< øa(×õ-ê‚3Ì¿’@7ø`´8DÅGº3´@%än'¬rÁ4ô‚“¢}C Åõ Ó ¨2»—¬ä膹iÝxßó©60£°~ÕÈ­"n¨ã(85oƒ ú…âÐ@æHlX¨”W5¹Õ(ç`ÅÞ9ßGï;×Åð1ãwöêììü±$òÕ=>èýyÿøãsÆ›SãwÎàšC€¤,Uš{sôߦ$ ‹§ € &ç'Ë”½ºþæ‹o¸®¸çŠBh1‡$Ál®”ϧ Ö?YñL ZBɬmÚÏŠó x_o¾ õ¯Yuqئësv’ž- œÆ{ÇpÀÒ7×ïŸ|+@ç;û7@¿·ßjî·úŽgEžkØø€ŽB½úZþNàF…u\É0? íç·h[‘EI˃€&}ÉÚ k ñP¬5M&Þx4CSØÅ…”Êe½ @£¼ZœšŽ•L$mWˤítÐ:`_!²B;$Y©øŸÉxä¡À Qq; —Ø_/ïhÙ¾ã•J;¥bÁ*‹AÁLçÐô¶“ ½\t̲§a®`4±>s\דÃõÆáðõ¸dzÅ`s·¬û·<ŸšW¯ïîî1èt{j¸•,9©NUqJ‘U’ f¡ò‹¹ ¹mȨ3A½J*kÆf$°-¯w¯Ÿž¾á—DOþ烓?Ðï÷ÿ§^çð|¡jëkbÿVj¾˜ƒ:›]’s`¦Jêüº*¾R ãqÁM­Ã¼ÁÒ\ 'Üo}AÂâè~1§d!ÊSÅ6ÎBèbMBYW¼fhñqîiÓþ%ƒ­õÁùúqÙå»{_?æ#å:ɕѢ…°ñlusý÷ÎônFíÖþ~«wpä{‡e!ŽáÙQà²ü'Y±…q_IämLûƒ.°‰9ª‚膇h×»$ÍBnl9ƒJ ½GíIà#+Ó¼n¥^§Ãù}]K§ðËu“ަ¥ó/ReGó¢Ð`hÛNM$ôÅ>á\H ZghÁ…x çš©Œ_ ¸SÐ]/é¡54u‰,-¹-‰‡îz•”Ç©bã³PÒ€áÉØôsCH~Z6×%߸mÝ»åùHðÿh¯º·»·GÀŒJ7Ĭ±'Æaõ•¢·PÌy1òžÕ·Uɪ¤•}‚5å,f d­Rá÷bšð®õÕéé+±ÿçâOþÓŸ‹Øß?ús8€åE+Ž¢Z$÷\°XÆâˆ8Wj`˜…ùùð7ˆXtTo×gTû·¼¸ÿ:{rKU¨_b}Jå¶1X2YQñ‡IÜ?çèÄœ-KFñ ¨Œj IDAT›ö°dz€õǘÌ#öÙt}e .e ë_,)‚¶àE®­ÿÞ9€ƒàˆ ÀÎáEOËamK‚[6û$¿†L¾’—›¾‰ž Qd±É‚A:`|Ú†$ÅŽ ,”xÇ£pXPf$ØÑ¨\.R @'“G&—N¥“ž¦YZBK%²v$‡€ú "c­ÝòF`ãÉE#Ä%Âàâ Å£A]^5,ê‰ÿËò=?,<†ÅÐó4Cs%ÐrÅÔH‚‘ÈøL² €þ‡¯‘ËË;ÅÁ€Ê€ëãÑ­ëï> Ë­Õ½j]\À^“¨}»ˆÛ~ä%+ïœ\˜Sýn– Y’§Ð9½ÐD_Î1¡ô—¬þ-V›ÖW &âúÇ''ÊÁÀÔ%h´Z=6£€Òb“,߲͡9Ø¡¼[C2}ñb~„õ ^õ}ëv,szËó! ¨Zk´ºéå*8ú§âj"–!,ŠG(M“ý—…7~ Çvf¬¦¤S :‹ƒh .6­¯ Žùäôôñ±®?=Ê?ÕûÊ|úÉ~´z¶X+Źâ,TšÛ¬QTˆsû U«·À¨g°FöÎú›Ë4ážëL½¡#xs‘ õV 8|s6ÍÄeÃ~æóé|ñžýjœêîë#?ciöæú’Ú£7×ßußÌpÿÃ@ëÐÚou÷kª§Eö[„^–Äö~ ǽm¡ îpæK¸b‰žïÜ»áaIpœ—hŒ‰3@fŒà?ìHï9'rrôL§ÙÉ1¿ŸÍ¤³^Jsm'me3:ÄI$˜ð¡Çƒ¾B„ž›ì¹9d£` b©\t<‡®ÙÓ]ÝôB cX³°Ž;ÛY½ṪºårÉb¾RH'1Rì ÏÐÇô†ãóáЃæ¯e %t‰FÚ?îà}ë‹·<Ÿºý¼Q5ñíùíWqz¹R£ª3Ìñ­”îUÌs¡€Qd™]ÄÉr )IùcZ‡´Íë ’gÏ>ùñ>ùÑÃè?yú£§¹OsŸ>}öÉÓÕ³5Ø‚Ð@ø:ºD¸ÂZ’‘BñÅî·òá<‰¼²~¹|!.xÏux;Ôn®#rPb$_ß\_"p_,7í_€ãRï¬Ó×-ïq}ŒmÌÞYç4ÃÅÔÖÛõë ö-tµ»€Ömí·;ÇûhÑP6Añ%1¸ƒ~À±7%‡bŒƒ•ÔÜ·TUЊ ×# ];tÍ$lG½\¬?Å>Z÷ªw7Є¨V¡XÌHPÈæÒZ:g™š“µµl®qQG¨¾‚äÁAr¡ä“sÅrÉwôbEò}ݳ ^ÑöQQà·¼„¦IfP*ÚZºPÖËž^H¥²-«—õd^2ˆA[ûÌÅàŸ1v÷%࿺:/·}˺íÞõ|ö„@S a³¾Ïª˜š‹ð=e€¬-a0D±¤-„€œ%Îh̽®Ö ç:߸¾x6[‹µ?{úãÿøÿøGŸ|úcú‚?]<{ú銜šà[Ÿ Ý=uü³$ÉI¥‹›}+Îsð êÏ.Ö¯ÛÆï·®ØK¦³wÖ—¤&ÇÓ À;ë1úfã~”H–Óù»ûX`Óõc¬äú½ëìb^_¿îÚ•oj¸÷u7ö®ý×@ûºhÞp½H™ìiE¨¯|´ál°üÛŽEr|¾äö1Å>#Ú6ìÀô#àãÑÃt¬iMìZ`Aå@ܾ%D"wV¢rYrv½Ójæ¡ù‘Ëå2nÖJn;š•µrÇÁ•@<ÂÓO%X(áð59@9  XöTá.–"\>?;;»"N ˜‘G­OoZˆ,ßo}®ÄOçïž°ðŽx8Œ†ï=ƒoØ¿"Çébùn°TÌã®O¸Q7×§”&šß\ÿ½w-É:Ǫ§å˜ ü´%ÆIìÃø8h£ß/§¿ ZŒ@‚bG~ŠTÿŠŒú FfYÑprv¤ˆ|äh¼ñ¤üuy'ŸP‡•êÙtÚͧ´“#+AGR +B_!R}ÛŠØsCuUÀ¨ì&§°³S‘¢ ¸å zÃÅòŽ^Hk6Å­m«P,É7Š-‘Ndór“ ø*m¤‡Ÿ$0-£m¯ÏMOrË2LGÖ=' $ϘÀãy`¹º~ëó©Ö­ú#@õF+ ,ðBeÛÜáÜ:ý¼A!nYm Ù„²ªëQ¿[©ìP"Hñé"®žÆ¾aƒóÐ(/ðl>—ß>}Š¿®ž1J'e'ù?èIÖ·/c,±>{õêU,~|:»âõ"½ÿ«9òú~ë°Ã9Ó›9< $)sv–7×Õ ½Ú´/Š"äË›û§ 5Ž}÷õµâ„ôÍûG¤âõØÔ^›ªð»˜ÿû]ÀÕ•÷ÿäm{¯9€NcC2°#=-êߨ¦ªØrˆG¶E†_ï‚ÜÐ/€‡}`³Þf<âvÅZmŽœÛFrùÖ$‡áò>“Q4)~]þ*_@~dÒ™Œ“ÔRYÄÄ*"ô"öä…#Ó÷H9 ç•!Ü[¬ìì”Åî]# ²®Ø¾8 å ¤Rèúåõ´ãI/”ÜìVFÓ2lCzÖ óYû³È¦­¼õµ•¶¾‡r¨»#°EŽ“Ì@RL\®ßú|ê •­“4Ùîö8ékØ™&3ÿZ©ï­•X0¸Â(ùƒjU.ñ£8½V€Ï/•T6ËêœV\`ÖW«g²ø >àÓO>ùD~ÿôé¿úéŸÂ¬Áœ‡™ÂÙLMM)G@ý9ÝÉr=–šüíÍÅNÖ!®¯–§§çתäoV÷\'Áb}zúêú:õÓ˜Žê÷ôôôÆ~´ãØæ¼s?'+ä„y~c}Á  ×_²9›¿¸¹Îç¾zg]@oÐzmº4¨½o¡Ø»î½ë Ýì¶÷ÙÓB±ÍÉ}iðƒ‚İà‚#3Šä¬5ͬÀʶcVàлÐÐõIžŒóydŽl9Áßóäø—¿®|U,¢Ëæõœžs³;einÚÊÊ¥AjÄ3ˆû ä‡<¹±ÈA1*œlB€å œŒç¤| ùK‚t˜«¥@\ƒïiɬiá’î¥ÒÙT*+'»ë¼nkŸ[ÆgVÎÊ;ò¯•5 {øÚѺ§IÊMHD 0kh Í+ë·=ŸZ­EU4.)Áö,Ûr®Œ#·€ß [Í耔9kÖ¿‘RÆG!ç©YÇcn(ká¶Ú´>[=cgïÙ³é qÀ ü§ÿ§OÁº­Rðd)á’)Õu“ Å]R æqŽôT"]º–ñi`j}%ë/NU’ ¾”ñæuy±ùt9\ñùÕu5¬˜Tåü>{qúòåÕuR˜fdÃ~:ÅÅúù‹—ô@o× "šm¼>E’Öë³óç§gׯ¯èo®W:GûJ†Ñ-à>Æ›aov¿ƒ¨·¯;€ýN³£zf(i®œë¦–$·8Ú!Ž'É7‡€£@i˜–å¯lHxË÷C‰ý-Aø`¶Š.˜CÁBã#ðÅ~ûõo¾Úù !@:FñzÖÔ2ÝɆ¿–£HBÐoþ+ÿ¨ž[4ò1OàO²9Ï£Vp¹TrŠ–ã†v&+6^ÜÙX(šš ²@ÏKmÙŽ¤ NˆHk“H‚w+5Ô^> ¬¬õuîuªÑLC|? ýø€U¿ü¦`6 \×Äëâô‚[ŸOj5²Í ´$¬VMÁÎêÈgÑg/u»Õp°Jš‰0—?´ÂX€Ã¦±˜N͸Gã†ï\Æ:Øú™¤ OñõìÙ'€:ÀÔ;°òèÈ­)†a­‚â>Œsç¯$xóF>ãgë¥j|ñ „é•õó—°À/^½x±Rh†{­£‹9›Ÿ¿8;Å2ÃP'£4茓‘sºËӳ篞¿€!ŽDâ¢)»w³ÅÆýhAΖ§ÏÏ^¾xù‚¯ÿü9QŠ—tãõá–ëÓ³W积ÔõŸ¿˜±;ºÁÕ;ë•nÿpµÇk¿• {=ht®§F¯/¦zÑÓ20î¦XoÈã|¶Gâ 9õ 9ÒÉømšèØÍeµÏ À€|ßÁä/)ó/fE‹}]8€¯¿þ-(²Y1ÜrÁÕܬ“µÒ ¿ü5®@°c…ªåŸcc’X¼ ŠE[‡²h©Èö_>—°=+¦Ðü*2)Í %ùw3ÉdÎÚˆxIŽ-“M¤ý`±umP|–oç, r¯³’¿˜¶áƒyD"ý±j"Û7q±>'yûó€D}o¯¡À‚õ¦¹âúZ ²Gùu|Ö8w¿¦¢ü¤ÐTS¹ ÏhÖqT]±Û È­›Ö1¡öŒxx4ù•ˆæb¨¡3}ÆÞ¤* `.Fu+ XX"þŸƒrc)v~þâüå™|‰=çÈ¡ôØeýåźøYŸ‘pë~ë„ Ÿ¾zñòL¬PÖÅ”˜1›Ab5{ñêì\ŽØ/±þüŠ~„J¬H©t÷~Lù<áÓ—g/¸þj¦š±PÑÝ×_c|ãÕùÙóó3FA²ÿTåVªŒ{s½Ò;éû‘?»{õö£Êí¦øo÷uÓàßýºêµë×Ú€µÖ[>¤­îÁñ‘㨞XýÉä%öììx†ïÅÕ—¿mƒè¶m^Ø6ê.ÎìU±À‚læ.dµ}Ç&­Àx2ö¢¯¾þí×_ù5B9õKår)çæÜðËÂ×_޾üu„vŸ‰~‚DÛ.û ì¹9i‡ø+é„;ö!X*ê9 ø½¼îê%–K;åRÁÒs^:ï i^šz¢Åœ–LÅáøQãgõŸ5ÿÜøÙÏ$ûŠH¥S­´ä3Æk‰|X*@~9x‡¦­Öƒ‘wûó©zn½ )N÷ÈóÃé}…]¯ebó ¡Ÿb¹œ.”t/…ì‡ÏAl9CE~ÉÙ•%¡:Š@dó:’„§šÆ§;ûSE÷¹z¦° ª3Á¾–âЪ€ä=$ X/`úòuvúó…k:ÞÖÏÎ/×ß|!ëëo° ‡®XŸX,èÅóS–2ÉùÏùþ™œÞ/^¾|.f,~öò•"K„…¹p÷~x´ósIaΞ¿01lÇ)Á±•£k Vhù´2l9ÿ!f}Ù/—Á~ǵM×Ç¿óÇ5óeéKrè鬮ç _~9ùrò¾>@v0”?+t€/‚šÐåýݵºÈN&‘?¶`$…ÆÊûcHLÔW:ÓÿÇêw›•É RVÊÈüI;m›ÃëÛÛø)°ŽM HàŠrþc]¢ŸapÇóìt­VÝ­í5ÛY…µŸ!Û¦öµªo¯)aCÈ-Õ2€kQsÁ 5 ·1Ÿ/=Ïl¥ô:Uûój³MëL¶ xöìé³g3  qðìéÓ§SER´R CEF€nf}X®À˜8œ>—Ïû)ÎÿòuJÍí5§Õúêù©œ~ñ:»c÷]‡:¡ÜŽÄ¯ž¿8{y~úüÕ2MDãcJ(ˆ¾µÉéËWgSj‚)%äõ¦ýÔ˜Î$D%Gô«ç‹0ÏÁ.¦c®OòÐõü•쉓^I;­§±¸¾^éõÅ|êÕ½Aíµé^ýû˜ÿfpõgÅ´wV¯8€ƒ9¤®´Û£#Ôì úl¯¤¸dþ—Hßr¡ìùCßC'¤ h8 ùÒ 1J±·2ІPÝOŒÕ´ßèäÅš’L¢¯&Ñ—ù|^KM0ùMþËøõ±bhÞܨ"b áòþî¿.q}èÁKÁ˜#wøLÿÿýÇ~&åXíœ™Í ^§_·-ù†¾–2 x@‘\c4’œÇ°±>@úûó©5<¥ بwºÝùTµÙÀöÉ!3Ö‘@¼©P¿`©›1%Ui¸âçÀTïŒk5+|I²RþÇÜÝë VG}pÆ&Àì隽ň©>ã,†ÓqP—”µ±µ ö¿Zy5¡ØE^¢¶¶V5‡øú39yON|ÿuúZàùK¦Ö´J¥æ­ò<©õ ìf ?Ἣ¥Ë_lÚOu@y/ÏÏžÇYÿš”xô˜ýßx}©¼’$†½›f1w˜âK¸¶^éïw½z­Ê^`ã[èíΣ‡{oÀao¿öèŠhõŽŽ@ù)åÀ%Œ¿®áÁ°€Ë{+ÌÆu%@tœmû6ŽJüip „|CbÓt|‡“‡.e@$–PV ƒû­»ö“#±’uË à‰#ySãÈ4 ǸrñL Ó Ò™×)£­5É×é–eHFŸ$?·0½8CÌö'˜b mÏ0dÝCЦßòþëþ^U‰ƒW[­voFÚŒØ)²›~KeĘŸÁ(-ˆ"¸[+: Eô5›_ôèpTo¥ô6ì_²¹8S‚¼ØHl,$öb®~k5{[W\*ú½¹.ÖÿòìÚ:û¨Ä‰p”ðý<Û``Ë[ ,ævÖ½˜ûFÍ—[,T3TxÈq±¢ Þ4œÌ]Å{ŠëÉ7Q>Á åÅó•#üÎç+!Âÿâý•ž8ßm4Ù ü·vï¿Ú7u-x€+ ×«>ª¾MŽ÷$ ö@ü'Fé¶ü=Bz3Ÿ„£|ÃÙ¾{ÝXVa8?ìû6çŒ]ÐìalÖLß Û Å¼-Z¹ä•ÆBëƒ÷£"Oô -?ÍY~±ÖÈȲFÆ(š7“éËW&áXÉÏZéLæOÒF²a ,ÃOž´P§ ýâ3ö'“Ç‘uÇ4lÃ@âýï´Àpò¤ÅP {¾Žu¸È¾à00Ä)ØŠ?Y½8˜ÿ¥LÈœõÙ’'çì‚¡o±Ü´ÅF´€â»$?ž¸ ¹Ê‡0ÁÀäÀVÚ32¬æ×ùž¨–qvÆ%ÔÞ á%«~ù‚R'$)x'Ä–Çrv¾à»\_±WŠÜO|ÏK¥ð¹Ro–‚(K~ƒVºôØ %È,Zª!X¨ $(êÕ$ ,™(ä©TF õ<´X+Åoœj°¡šð¦ýœ2hu½œÆS> U¥%a°tO`*#;áJ… b´HÑï^gÅóÈkåædºQÄCYmqÆãR‰÷Ü(²AÈPÖ—Šàj‘@j‚._bôq:§ì7<̘Ÿ¦9{AÝ¥u,®†’ ‰˜”j‡\ðži©8 Ð'Dïêó=ßð|ŸoøÿÃýŒº‡ò1FÏà¾_ׯ@°×èì>ì\2µš­ÎÞÃêEpÿض%s¶,@ß1àâò5ò·ßJhI´÷íìƒ)®?H$3o×%*w9.h;~HÛ ˆ á[ÔÑÑfgá bzœõ•ÿr¢Öøœ1¿'>äíGÙ!ºh`r? ž9À ÄHDÇuÍüàk³`eŒC7›Íör¹ýB` þä³ÚŸÔÉ?IÕ>7‡¾¤Ÿ†¯¡>4‚f—Å„®5Hl4´shƒ'ëñó¹Xwk¾I@µ.¿7ZÀØÏL)b+åêwŠš•ù•3£’„)õy§$Öž-È®TWNMÀ.âOë†ýèÈ ­ã—]q°Z)FN˜çŒ@"¥@Ñ †Þ Eé»Ü¸ÎRBÜÔ\(5`²œ²7yÑf[,iÄÄðŽn´ÙâМ,Ás4.Ûlü!%Ú1ƒy ±uÕ)üx;pÂÏçŠß’гA"0†d³_¢nI¡-Ÿì®¥%¶“ù0Ì$’ÉÖ󹤖H¦séí×Å2ý m bá…í!a±ìÀ– ¶ë9I7˜&©žë˜„þƽ÷c9DÀ‹®îGÖÙ¨ÖÅæ‘ç¼aú0£[YO7u«äùêú IDATD@6 8Pãg ?ûç’†áÏ)dнGè®1à8 xÂAf\®›î•u˯K°[¯Ö9 Ðéô`$ '—ñ9¬‡øŸ…"XðÄáéG]¾9u§+5óCÎ_%@¼bXù@®7í§-¬ãdN )È/UmÈ¥†[Œ*Rt;æ)P8Ùµ¢Û¸sŒC841s· [æ4Nàgñ`r¸:0 ãt“½´!Iß‚w=Y8Þm€LÀq?å‹ÏÔ{!ñZÍ>+Ä´e±½Tó} þÇÄÃ륒!_Àé@p˜Ê?jûŸïÍýæë£ýý½Fߪïüïí*Žùº6Ø}Xïî>”H¥ûƒV«^Ý«V[»›Õ^»Òèõ]0ý¨ñí„g»(¯c‡³¤âèùi[©T¶\É%´D"—wrÙTRKjùb:ñýÄ6º‡0cÛ ]Jͧ‚aì[êüC$öí«ùaƒ\Û¨ú…CëîçD…Iãý»öhäâa,L8»N˜{êfÞ.dKºª¼âãbñqáÉ“4ò µןێ·…‘ Ñ8’€C‚þáºåP`„ò¾u¯Zƒ2p­^k‚¤»¯ø5È»Ã8:þŒ.H-ÍÈ6ød¡º²J²àÍ'š}©ç<îÖK5I·šnÚ?›©Wâp ¾ æ<¿xbs𕯬¤°Tø¬æø6®¯Ù/DEG"Êz&T ƒ°!Bmgl·­8Ý‹[¹ µù6 òKâ Ô ;Æó9ÇfñŒd€ê©û^MÅ7RÀÛ µäµâUV´¡ªéHÎDñð(i|è󽹿⚯›ƒýv=xøp·ú.Àw…r\=|¸Wo‹h~çàBè@«>|Ô>hWö{Ú!pmîˆߎãBÄ3|À ßrýÔV*™Ê+;ÉăœVÈëÙB:Ê狹L*!q&€Åð L´ÏHž-§ûÀU|Á R:?6Zjáž%ˆCÜË@x_¤÷߆ñÝ aRµß…z-o@2 ׋‚h`Bð;›Ö|î0kL½u iÍL'Ói´ò¹n£ÕÍu3ýzýgÿ•a î +Fãñx$nÃ×±ðÀ}kªð÷¯» KÌ«¾µÅrË>Î8½1 7+rjh_ÑQ †0¿dšb-„VªÜ<‡9.z` ÏMûY?Cô;_Rûƒ"3rBRxÅpW>¾*+™©aDdÚ ÕØ´¾b`#a¬‚ÝF+1í8ñÛÀš§xDé¾;l³"šêLgW‡mV¼cžÝ±ô/f©BTÎcîa F/¨‘¸˜Å!Ûˆ<ÈýÃ?±bÏDcñÁÏ÷æ~e`ûí@ëN÷=ãÀÿ±àæ*#P싽÷º‡{ƒï´[’ìíîî5[ëÕN¥»xà‹±TM4Ö>Fð!Ñ- éD*‘Éé•LRÓ²…ÊN:—Ëd åR1ÊjéÒ‰üC Ø` #=ŽgÓ–ÙЦ›qƒ/X&'óäÛöçjîÀädíýöK¢EËs º!¶£ŒÀÒ …[®` A9ÈdÙlþuÎ*º¹ƒ´DAÍüýç“”vñ[+é1DXþw6ÆA_dùûðµ1°ì‘k@5üÖu0Vw40ŒƒGº`+2q£çEÖ-~ü}~\Âbœ;S ÞòÚÙ:Vë]‘ôª))ê7ì­Gæ‰<€™À¤‘ÍƒŽŒ"|—±¾­Š°M&%7­Ã>§t(«µº 0‘Ω¢Å©;5n˘™À¿µDóËéôƸ-‰L­Ñ#Uu5n‹8›´ _PÊ€Í1Âá<#îg6jsu-<]@,gDлÌ(ÈŒÄAe5*¡ù°ç{s? ̵ëµGHð­sáRwro{µVíµÙüÎAG€nk»{½JóH“¤ÙõÜ‘X;êû`þµ<‚w–Ø6¶Œ&H—+Ù¤D¥J¥Oe²Ùlr+=†)Ù„ÏÉáKp@dºÌ©0ݦÖÇ >1ƒí@“/HÝ—Cû^ûm Û‘äü®¸ÄA€(uHl³l9°Õ‚ÊÀpM òC=Sêf)À¾˜}£uñ›ÖŠLÿ_úÝšDùò DfãÑ$äüÆp€Ìß ?Ðíë{¨²ÐÍ.8¡º^¬ßvÀЧ`ž"ö]’ô²±Ä¦Ù\µ»f*aGKÊš2sU~Þ´zùbkŠ]R€ó¶ƒà9Kd”ÀíMgJ•l­J›Ö%ƒŸRVT˜óåœÂì¡ Ø·@ €|æ×7f`Ú) OnP‰[½º'ÄÞN9®8W˜jU= LúZÑšá(FÅ0òÄKd Ð]G±Püúé?ßûƒ ì ç"?ü΄ ÿ^ r(ŸSO"€ÁþkÓÙÛÿN«ÙhµjÕ½‡»õÎÃz£ÒkYbûÎÈÙòÑêa¨Á—RÆÀ˦3Z6Ÿ­FzKÓ z¥œIi…\¹’ϦÓÙtN×’[YÅðLE9º ÏŒ¢È·ÝD¦¦K¸Îù€`€á<3òÌ€‰ß!Mr÷~+æ%gp¡eXH^pò?”Æ´ìA䒱Ò×J§‡‡¹Aζ ;§7µÆA@#uñ[«1)µÒýì§™¡i ¡ê"PèjÁâ-ùƒ=ÓÞ]@ê`dÿ"5?gºŠ…BXJ_’‘“sƒT œ‘Al…Bób jTÓќڼŸé/„r)6¢P*”V'Yíæ$%jR—d]’d`ãºri ›Ó çÔ(RJ£,ÁÅ”[tDÚN®ý¸]…r ™Åœø€Ù*ž[DóOi¦²VÈ+“»€æ6'Ä`Nm5ŒMÌYOáûGiŽ?še5wȹF5¯EY Ù?ßû+Ç£ÑÈ­¹ÞnºÖî·ÏtÚÕ®ç=üˆTÜmˆh?j´«»»öº{»íJçàèÀq?Gàà™µª{äïh -‘Öòz._Ç^.¥¥4½P,$“élAÏþæÞí9ŽóÊä³"¶£-u¯¬K& TUÞ3« $öe#Úv÷Lļئ€ªÊû¥ªÚ–šæU$%qöa£z'fçag:Úê±@Aq&z§=”%Z¶ÕaiÉ/==–¦m«nÀÿ0眯’-¨ {vÄ…õÕ—UH也óû¥g²©WÌ¥ææ1:ŽÅ¡ã€T£Øƒ€µ¤H½c¦0þþgùþƒëïÆVqˆˆj‚‡ï÷q ôÀ;(‰½˜†uptÇö°Rïv)3mçÚÙy+keýFZM×En¹´¬¤–—Ù—¤Ò÷méÿ[Ò”bÚζ?ngZ·ºq çë@Ôa¾Ûi·%ÂÑéo9Ñ'××DQ\“ªš1&C† >f5©ÉpÝXìËcã»æ7œV Gc’“½‰áá´Ïº~©½9lÛ¿@J­kãi«¹ÒT߯VY2ŽKN3VÖÙŒÀîî¡ë¬+nÄâÄ Às*ŸS`ts—Õìw© z0Ú9ºIï݇2˜‚nŽ õp2aM€S$~ÌE ™ðÒÖ Ðx‰'ÿðY#*³Púޱ”¡gO0€Ã!ëVšùúÜ/˜¢R‡{_jÄ`‘~¹ðë+£ ÿT%¨Ö0´Ýyõ˜¬WìX¯Vdõ¸((‹f݉[X5wº.\ôÍÛàZ¯¥Tr.‘J¦³E$Ý.•‘Â#_* Yx([.³‰l:ËÊt V<«ƒ2‰0þÓæ0Ï- /5E5$ÙÅÎ]ßG˜1,õcó!ı,Ááû;›d\&;™‘yÛ\ G]P ž‡IIëƒ hÐÎäZù†“§@Ýú‘8÷#Yº?·5÷£­­õËilÌ(ED'¶rìJ[»|Ëju,‚x) K ,«mw,ï—¬‹3bUJª :Àºõp2­¿3:tuGt“>&†° ÅnÄê„tC²`{Ì0´ gwÀ¦{4Ûû©û{Ì7¬9¯ÒëÀPgü`Ú'0 Z= îV>Iö!ëbæÄ&jVP"SŽ”qÛ‡õfM{c‚&™²$î> »MJ‘¼ nîLa· CR0•Àbr6EŒˆ?¬—i—`¿Ðã`|_TkÅ& )=¦–ƈ)It6ØÀåÑ®ïÁý‚6o˜¡/«:Ä]ç=Ðî€L;¾‚нH<¦V+ªÆóxM0•)ì©É»$E¡åPeMÈ'ÓiPsIPn̼—ù’ùä3¥b*™M摎«€Ý+X“Å`Kr®ãŽ606ë!¥0B}á¼ÄÏ–Õ‹;aÏé1æø=7F îaWááû´ÿq… —‰cpºßFjAxÌ…hÁsÿƒ²™ÕT#s*·šÉYð/ÏiõlJ2 MËjfΤ¶ \¿g*¬E0ö?»’V“‰¶ôcDþ^í€i[= àJY-ÛnAðËÖkµY ®¯‚8S vÿŒÙ¤¥’ð›0 EÕ)L»ai}¸Ë¢j}Án”Š™³ùÉcòf?}?9øj#æ•XŽœÐºÐP’©u— bº}ÂP‡‡¯S~}L‰rL”H9Y^ÆV¼»O¼Áš}Fì— záÓÄ»Ó160L‰7(…‡A8Ê$KZîÒ4½;ÚŠ5RgЀõMX[!‘w“êEÚ¤&ÄrÔë{p¿ Í/5ÃÀ0ë ˆüÕ߬ø§¨‚_¾O0/îFAÝïöz…*Q¯Ñ!Ç«‚ܨ×i¼Íòì®o¹äX+Ž'@ÌŸÌfSÉD*ÕŠål&™¿Pʤ3ùl+éb¾,…2—6‘È Ó"©/fåB·wˆ;Yv ƒRÝÁFÑ‹Ä0@ìïCtXc=¿ç¡Ÿ¶ý³ìG¸!&´°gŸ²ÿN0Ý1‚…ñžÖõ¬8$!o¥[).ÝXÉ&:\ª©ÕU]ŲÐêõ"Ö!ø|ÞV-+Ûɾi?‚K®Î}¡ˆùÄ‹`¼w,ì þ%눀 MÞÚÔ-·ž2ÞÏãýæÙ1ð`$Sh2Y¦(¾&Tbg&#fŒµ±\Ns.‡ïǶ<†Å¶Ý)$)ãÄÃü9ÃÚë~ÇÞº©gÌšýYgFD5!v‚VíGÔá@¸cOP{íDÿñ!Q¼|€zk‡• &h¸G½EÕ–¯ÇØ`B ÔȨÓ(µ:ío@ŒÅ9"x=îÒÃ5Ѱ5=›F/x]Ù»8âõ}z¿ .4)”u©» êöÿr  ’ÐÕÀÙ6TÅ\¨S+Çk²Æ€:_4c©¸‹þ+:͈‡Q€[Îs‰L®˜žM§çòÅr9Mr\©œÏ&sã‘IgS9p ‰‹K}n.iƒ‡pqý±¥a:Žøpˆ$‚>¶ì£‡Hø_‚Žî{¸‚Í€˜±ÃAâϴߥ®_Ÿ¸LF ¦QeÚŸV§åQÌà9€³’Þ’¥=îúÛf@ÜþQ€Ï•^¯W¢*`ñã´ÝÊZé¹TRÉ>z„Ä6Øw; Áõ÷P‘í°+°½j}b½63§ 9 "õ“q3Ï–Êç„O³ãÉ`”—5Ö'4 ³;˜6¥2‹:¤d4já æÙOM±ÔýOÙ1ä!ú@*Ú YiŒÔôfG¬¹u ¶Î²k#69<¡;µñ»ÁÎSä›cÖÓƒAÕæ’o’ ±A@¬NÉ7©mhÀ†we!ú/”ÀJ‘ØòG½{˜@©¥4Åp F=P#}Ð Þ)eGyƒ£^߃û±ªËRèÉ Cž¯i¿2øÍ¶s D&݆èš,À£¨JjqÕš— XÒ½. …P~6ØcZ-ä ®›²½²çd}'Ÿ+‚6È–3ùÏ¥ó…B¡œMÍå°X.€üƒ—07ç¯à°0uœb‘eåÀ1“{*†Ùzê@AßoÁWüð bÆ4æ¶ßg\!˜B .“0&t¢`o¿O¨Â¾ë¸+¾Cö½¡_@W‘ÁofÕd]âó:|6¸\3Çy­n·Oz¡^(¼U[iÉJ¶Ò+ÉÜ£Õ 8ý8aƒƒ£H˜*Á²_{µm\¯ÌHªÊ ñ¡AX¬¾5JƈÁ=x‹½’Ýëc#vf4'‹bwæ©VãýS¾¢Ñ9Ë b 'ð™,Çó|)•Ë!6w‰ãË¥ÔÌìL*‘Þ«ÉQ¿e#n Š2rlQ­žx~\§…”V/„wæ{þA±‚B+°>Ã~ ¶b*z1`ðt?²»NÜò! AûŸÉ~PÔ S×8S×óðYಀžÑ9=«4µŒÆymDZ Ùz&½Uè‚~胔,WÞσ‹¶®í’gaFÇê´»Õqž^¯Uj4 ¼KœS—ȪÈÅz3U¯Ç¬^7õÍ)›Å(»©Z¸‹EøÉpÌÆê’eŸðýôýôT¨'óOé< Å)&߀2ôØfCúb<-ep~¬ÇîS×±ÚGï klhp@íþÌÊìƒ“Ô ýàˆfkFÔ“€ G €b‰á„ºoÐÒŽQ ©p‡(•èךÐÀv€]ÆžHßà·¢ªµâp!ž{Ä`Ï©J©`ÂwH¨eð±#^߃û©¢ª²xRua¾¢ kõà#ÿ³EMî‰zI¢$ËóÊ1µ:¼RÓ©*(.h‚¡/êE[68̽l[¹A$𥒗Lp_Ìùy!WÌ&æ’™\>Ë ™|™/—¹\®¤¿TÊ%ÉÄì\"ë3žpL$¶ö…-ìïyTá#žËöbäú@¼¾Ñc³!X϶o³ÿ~¦ý1q™ %1²byíGXq+=ѱ~‚ˆƒÅ÷‹EåäÉ4~Êð™;ùdÐăã¬ÔªÕá²uE—Ÿÿ8“n%ì$Ò­ÎÌÌ¥·œÀÁÿ°¬8D~P/Â7‡•€N§Q€ûÄzU !‚SÍŒ¦U œrhè÷‚¸Œ]vÓ3rÊ^³›ÂJѾa^êˆ:çѽ¶BÁìfP¹š2á;ÄM4f7ôÛñq  þ p0½^Æ0:l}wB£¹”kÄ|•ËF$ƒXmDQ³9¹ÑpècBÈ4z?ž:FÔ£‹ë háx8M1±úˆj ˜:’–aÀþØâ°C¶{‡á.Ð6Ó$3›%Àç¨ð0e=žàÙQMLŽz}îôVËBâøjåø|U•Ø¡iôMV˜>*É«–ôÛ9ð¼á“à;À’~Eµ…šÖÅšdÔŽ#,x%<^ÓXU°fªÜЛhUWí>øÜ.Êph—‹g§>WäŠ~ãTfÎM&,ù —çÐÿ/–žO$ggçrss ›‚!Šh‡Zb?Ž[`‹‘t]wâù ‘z çé 'vêC0ï ù ÕùÛÏȈ+À‘b¿çGÔNäĤÉTîýb¡˜¹ÿC-óïi™¯ýPËþËÕ5½†ö_Ï45%ÃÕ=kEÀCYÍY™Ôªšêj¯f³E~ B/ üNÂ×r°Öà!c˜‹)6–÷×E±*ŠŠŒÃÀÔ‡w(Ý«ˆdÇŠlÔËT»CG4ÚOóðCì½amh#‡£~Lm£ûŠªñaûw#áˆaN!6Ó`šjøêÃ¥„<©ÞŽUöáppøú€ºG ‡›QžïÚ’M¨«™ ˆt8$P¢`8fÙ9B0Ýe8&Êhþ±ÊÇÀP°?g¿ƒbO´w.ð€ŒXß/gŠðÒŒ‰-ÛèÍMT¤ƒ°G°ÈÔë{p¿P—m/ŠŒÀ;¾‚6­¯}ýëðE7 äQ|Hoé«–§ýv)m"ü)„O‹Þ<àEn³…Q»ú±Q±fÃ'VæU†_¢ê‚i*ÍÀñ;>x°½<ùQ¶Ò³~Š ¶¹b¹àBๅb9åË<ï—¸rIà ¾,dgç’Ég™¹NÊñÐz#f(Ò-ø“L¢g"Ï™xˆ£mÇëÁTpØ;!"ùùÅ{‡í'tbœPFTnÆeòÔþÀ¥ö×ûŸç¸÷!z)Ê÷ïgäû?TôÞÏj÷ Z=Ÿsi šfZG ½Ò¶Š¹dª.+TMØ­vïT+533“È<Àì~x~ÆTÜñÀê#ÛèƒN«óÄ:(PôªüXd$ˆ…ý¢¥Ьـ6vhFe…ªÎSnægO°Û}@ãóx·á4uÙQCÿ§î'L|1šCÄjà˜ ™%Ä'0tÆÅ„æìYÂïÉ!>l}4ÍÛ“.3eƒG,ÁañlÂ2ohæÙ´=ƒ%¢¡JH»Œ(p „Þ.Íg&P°Q«òpi‡æª‡lÊ!B\S´ V瘢£Ò(Iÿ_oB£A¿c»òQ¯ïÁýBÓì±!ù U™•×´—^úú×­¸•Fˆ0ŽœîÚoå€W²#/á§( V äÿ¥—"GQu1òÉ FEU?FO\‰Ë@4uAVÌæ Ú]x¯ýn? â^¹\*x)?ø¶ œ“òRY®P²ð)€TAP„¯¡”žMv’³­œ7;—ÂËn9à¦Û,+ùc; ‡?°ì2Q˜m"§aJ¯GLcÞgØÒ`2.t:žØ|%8 øA2‘HdÞ/æsÅbæäI ?!О XàYm%õ‚]Ô$¥¾U@¬P+›9¥öN©­N.›åüí8rÜ$ÞvÜ ¶Þj»v 2B tìÇ번¹X3;ãà¤.ÜY?ô“'4(ƒÖˆ¹ÑlüœAõ"v AÔaú[)½Eœ»Ôé~Ø~ŒÏ¿jÿ…ÇÌü“ý¤I’ú2  —$x0m’¶>d¤çø&©­€¦ýPúÔä?&ü>B×£Ù<¶$LX»+í ÷z‚ÆÓŠúXwCÏ|nF£<Á¡D†F@@ÔÙ„ó¸,DÇ×e0+TqÑàî+ÿÓÑT±²Ö-q*éˆ×÷à~a‰ÒìFÕe&¶V“´3ç¿÷ÞÙ?u­©ÅF*ÕªÈ@+¿£ ‚ßvâ ªT!ìªö§gßûÞù¸ëº¶ a­¢„U“Mý=Qö½†\©éŠ*èš²¸Š9´Ðï! 6"âñàp~ÒI¹Iø±,p¥,ÒÃ_( …¢‡Üœ%>Ç—Êe.Ñ™›u@Ü2éD2ë: Ä±íÆ–o §w‘çÇ ;Á ;!¡ ÛX 0OÄÿ :ûaû;ˆÖûx¿ÿÔ~ŸpÌlÿ}pò…÷AÊ‹¢²¥`PÝR·”GfÎÌ(u‘S0Ðr\s”vkeõ…)Yb@!§PÈ£9ðÒÛA».òxAßwÛíò—by‚<ÇÞ_E1À.£íaˆvØ›ñ/c÷&|9BL(ø€jmÔZCmq,xfxÚÃ!ƒ¢ºŸã#šØgݶ“)2 Ù”ŠðqCÞ˜ÎI)uL]ß%(rJ³£¤S/M ïФ/Ž;È‹g¨>»Ô^O§¥¡‚$6rêê!ô¿ ÃB­5a´;8­e2ßbH)8:Ò4!j**àõ¥ùf ۇ̿'·Q.,ɘ Èvˆf2Ž|}ìV}°¥’ ±6˜Ø=ùÿÞ{ïÀUlË Ž , JÔ”@ì·pT«5Iq^\©ùvÚ(ÿï}ï{giŽÔî`™l¡AŠŠzLsnl†² ªJM4­Qo†^¡óƒØïõÞP,•¸‚²Ý”ŸÊB‘s¹¢—w¢B©V_(f ÿ#ë¦À— ¹ÌL29ëÎ¥Rˆm Í a;¶[X0ÃI~×ö1L鲃ŒÇ±{dkÑ€oìâÇgÙï ùþ~LÊ?±J|/ü @€B¡Xh6 'š'šÍ¥Ò ¡Àåôt]â²z–Ëià ØVªµ¢¤VsuI•Ì\ÎÀÏS (´¬ö¨>@é…ì„aìQØïÂ$¼w±DFçL×ÄZmMT$•:§wÔ¼K·=»Å†¤0ýM¸3TAŸLóJD€ÍXnˆBˆáñ¢_¾·ûýäÅYäA2Bè(qcòÌÉÖQmL‰9Z“!¦Æà°õsÝÈ„A…Ò( Uç˜ލT8dc>8#¼Ë†ÇÔU€}uÓaãñËÒ 6Ø ©ÛÎø1N¬¦‰®=ƒûÙÝ¥f@6LŒBIÁ)"UP ‡„ý7bmÏ4(4¦©`têlØïÈ×÷à~ÁÖ £[óL¬Zùºë IDAT„òÿÝ·¾ûÞ3ïÅÈ“U­UæÝîÏ?þù>­ã¿Éc~¾Rµˆ±¶÷WÿúYxùïÚÖù3¦*)ŽßcÑT{½^°ªë vŸ.ˆ²6¯ˆä4Ížë…vÜã~ƒÌsœŸHÙœëdypøýdÊ-:A)* ˜(–ò þ%ð„b1Ïås`ÿ½Ôl’K¦ÛŠq>ßrbBõµ[±¹Ä¯‰)z,ï[¡v''ÆÙ¾%ìËõÿ°ý>rÇvøx¿ÿÔ~6r¸÷‹…¸EŸÅ@[²xkK‚Ï­z:wÿäICNj½Ö©¼ƒð(133›yÐîxnäy8H„MŽï$èƒÛb!–…ëU‘2(–ùbÜ›Ìßa€2TwbdÁˆ†K”@˜M¢h—²nèÇR3=£º¦´ÇpvlÒS²ˆaJÛýì8d\ÖQ÷ˆ 켟Cîñ÷Áàç ã ëgdòð½ÐØÔê]Ì  ê\õÿÑ¡)Ùº|ÿ~^»ÿC@V»_ò’333épbP}ìBpB©¸çûÝ^ Z©ëUUÀ”œ¡Ï°FÒµ¯bjDyAâí¦ÎÔiPNÅ1†v¹—ùƘ”bqÌ{§9hUÿÔýˆ—C3ô¬gnš…§Ê=ÇÐÐ=öâ!î&eɼkM ¶Ž%û1‰Éx‡•i|å\se_ñh†ùÔ¡Ó!kŠ®§AºÉËgš@×HÀá&ÖêzRB/j‹)pTU%)Ú…|:J:H<Öð@¸á&x²X÷­<½u¼Öl¨iJÂÆ¸=v}î´ê¼&)QPUºŠ$Ù6„ïü§¿ùÛ·Þ;ÿ’)Ç–ØŠ ±uÅR(ÊŠNQºø›=PþÕ8îzaÉ’öÒù÷ÞúÛ¿ùOïœ?£««¸þµX«›Š¤}¾ªSU½Df,ETº\_LA„݃`-\Â] ò~&™±AÒóÅ"¶ú¦æ2>W*b W,ðB™/òHÅ]FO;™JÏeR|Ù››×¾‘Â|†ö~øêè¡[‘¹ »¢#TßNl!âÿÔ¶ãLP¬þ÷Û^°âzïÏÔ¦ À#ÿdÐ(L=£¥õ´–~ ¥Ôú+ ÀÞ¡¬PÈ=eR|ß ºÈìb£¨'ˆ>úÄ àצuPð¼qÁt±ò9yà’)¢Ö€àuišu—ú„§Ó¯»,hß%÷§l)@Žë„œÔ]Æ6zØ~J™S€Š þ,!@ +†í–¿R+.ú÷8³0fõzjæÿÔõÝi‡ Á„â/5"XÝ¢<ñÓÒš,a. ÄW'éžštU‘“²’BTXY×HúE””¤")ÊC9-ŠÒZ­V™ï$ñ ,ƒðK P)ìy x˃†÷C.bÝãÓÔ˜¨gðÂHÝú+CJ8 z}îÔê¼dÊj`J f"zuxþoû{çÏÀ{Ô@¦\Ýt}ЊšQ»+ÿ†¸°QûÝÐ4!À0 ùíoƒüÃ5¶ëõ¥^5öÁð›ü1E¯øÚ,[®¯€` »Ù½UP±ñ 8;9—θ)‚|L¤ì¤ïå@î‹\,ø%Ð…"/9Gír’lgù‚7㹎ãÄh[8òQzzÜAˆ¿VÇGî`¬õw Ƈ=¶Á‰ß·í¾G4 ÿ„ýþ/Û´ÝÞÑ(þ¸È!nI±XHsMç2z†+fç \j¦I|.“›ûBiæƒèåw5YI1¤p?Ó½;­S)%© B ³©~Çw‘\4ò 8ÑîÀûêÁõŠã(¿éÑ]ˆðà@ÉêÃi÷,µµ²Œú€Y`ŽöÂæ0š Â×F»E=­ØÃ ³g°”¬®þ©ûYØN¯6a-5ôF¸—ÍÉ¡_ËŠÔÙË`¯Qööêú`Zo§ÝË· Ó{4ÖMÕñ!øA•*âβ.”cáš4ÃCm û¥ÄŠ7jlYxxÒ6í¯ÊUÚ%I¸,‰UD\ŸÙÆs©Š*ã9(D0t•ž&âkêÁ" /™Ò±ïÒTñQ¯ïÁý‚†€R¯‡A¨ª^„éà{÷Ο B4¨^Ô›–ëBê.,/p­Žú›=Àõ1#?v<¼ QAà;Ð$\¢FMÔ•@uµv¼e3D5а=ÁiUQh†R_ãe¯ §7ĵ`Ù `ÝRé”ãfza·úÀwÒiŸ_ êÈ@„+ðò¥l>;—JÙ³žóR9¤ˆ‘&,é„°¹‡¼ƒc{à©{šÏüu°ì ¨8Å!?Ø}›F}ÛþŒûíÝ>¸ßÂd†çÇÈx„9€x.‹gduNÏ(Üb6Q($g 'ÏæŸ›û݉™ß)œ˜ý…u#;M ö¬t딸õ£Ú}{˜Ïb! ô[*øc–åYA?Œ!Ýku\\¯VÄ…*?6Ê2N+HT#q¡äñ„!Î\7%ÏsƒªMØAGó ¹í˜¾bP”¢îÞ=l?‘‘`ˆJîÀxB„¼$ÎXec½9,Ù6AJŽ!k}ße ¬áÿS×±‹‡¡m œÀ8IÉÑÌ+2Hð‚(.ÔЂƒLË$ÄhÀÅš —‡%ª²¸^‚„“„Ò Ž“ˆÒ[P©Ui yÖ@ðk•ŠXÙ®Vgf°Ü"Žâ®ÊSq‡(ANH2{‰Å Ø»ƒ¿<«íOè*¢fû¨×÷à~A±P–?”¥†Æ>:‡Qo4–â Üæ’µq,x*æâb³nî{E¿±Ã¨7©êåS<»†ï@“Dp¹r 4lè×ZòªåjÇ´-”UÊXÎãð‚&‹ÍÆuÇêìàÒúéTrÎñ3]?}Pä DÈr¥Ð+Å®6•À(rٟϦfV29׿y¤á±]Ë¢ =lÐGЯ1‡ãØQÿB7À†½Ðåˆ ýHãa¼OcAŸ}?¦‚Þ mþQ‘ŽÂSU€l‚–Ù|9ùl¶ø\¾<û;ùòܳJF¹/×3Š˜IgÒz¶—Oõ”žÕ2¡¼u€ÔvX CjWÄXþîhÿ!ˆá\÷y½*">ô`̸oЮñe3¥CLÎ ¨á•Œç„¦î)ž¦N›!+„Öf§¨mf„),ôÍG‡ïŸŽ°`ì„édób§¦›|šßcš‹'žó=넽¸8=;¼­ÑX\Z\4çe.O`P'¢z̨(‘¢jØž°:_U“†ŽIH~4ˆzîvüÜ6ÛÃ2_¶9ÅB1ì…°¦E¾\¦Ï  ‡-³3i7cÏ$“åûl—:õp°y»„Èåá€ýÆW𬰃à½àÃÛ!ŽüA€ý¾ˆê‡ýÿGÚÎú1÷p–\ˆPŠh°´‘Æ`ŸÓ2 Mm+dæ©ô÷#ü¨ÝWÒZZâÚDRà\φ °XhËå LrŇNäZ«^·Ãr Î8ˆº>²ÆHjìuaÝòAt$±³V†¦Íˆ:S©%—Ø6ë>š0øžáãódðäF ÛOY-ÖÎGÃì˜ÍÆd<µÂàšÆ€Zx03ÁÊ…ÖC`BŸºÎÚŠ@£Œ©$8måCmƒÁ¼,m×µÊÒ"þCßý¡(ÎÍ¡tÊÛµ*[¯, Å Á5«Õ@Ôæjâ'×k Øê¶*¢¶VIøkHÄJB?µûør"ÌãÌ\}z·lŽñ P1`À°EŽt}îš”f¯«žãÛí–i£±oèzÓ0ëÍ¥Àí4¬z½a²¬¥ñdRä7é˜MÛ:Ѭ×÷OßÐ4xø¢æq '“B:ÕcfM‰|Uïjµy{¡¦ ŠZ_4CÏÂùÂÜ÷<' ÛpK·Ñš‡Høò7zØí†Ý8*ÊðŽç MÃùd"Ñáòíg]—ǽŽ3ýHÉbË‚ ƒèF‘ÏØ#"?@Â?‚î ÚoÄèmØ‚ï^Êa]€BáǰùXT4N§2`±TnMðÀ`éd±Œ!@¦ñ*¹ ½B>ý¹S§à'+?À@òÑ:„t«Äy ëðªp}ðHzˆ]‚ÀD[”TE×G¬ë„¦Úw¦-fÓÙê*° 6cÕ$hÜC #Øk†T9maŸ°”9è‡ígimê×ÝaÌ Ô„³<Œ-‹ar ÙCÿÀÎzÕû ë4ùƒ^?!æ`}@ ³;†An¹(ÏT „¦ÿyf»áë¶J°õ¹¹±¶]AÁ…/(ýUSÚßÇ'×ET 5ÊÔ¤'ÿÇ  *‘þ¥0…Ò c¢ ¤±aúSñúÜÏ:k¦Œñ¾Ý¤›ªcMï.«ó?qî÷WÖªdÂ¥Št xÌ«f૦8_Y¨Êº€¥—¦g58HºtÛr;íÀ#ä¾ÓõûQØïõû`ðz…_5 €o-ða±ÅV€l®Ð™ë8Âô J.öì8ëšjç‰óûlº÷'ø§¯;40ìuú×AjáÇv¼ÒAôÀ¶”@lŸI>*r˜x2Èy+ì`bÑÁôQp”-XÈJà$(àp/åTS å2ê’÷hÞ×JÛ·ãvçàõ±íyÑB´u¢H6Ȥqxj†ÇÑZV…'h­=~{ºsßþèëè”OÂzÊ3È/Ý©=ŸÜÚßÞØîÁCöOhv‡ªÆ@ ‚¡kb¾*V1ÌÃý:Ⱥ…Ñà$¤I…ûn†À8Ÿç+3âöm¨ð< ñSëUñ‰õ*ŽZX÷7gÄX¦ë”>Á#$âHÚEH Ïzý Œ’ ˆ\&|!CvY:åB0ýI@Û”kÝùº1Tà¿ü5ßš0h Y‰5Tc¦RA˜•σ:V5AVU³ÚxAÇj¬¥G®ãF ~6I!FÜa÷Â~ˆ„x…2O]€`þÁ(æË…¹¹Äé{Ü™ÓÉ„[ä;„fg“ ¢× $/¤ROœdÙ¶YÍžæwƒÀ!lßϺNxŸå,|©(€ôNè­´@VÛ-=à²ä¹ƒŒ‹›uý``1ïƒÈs¹œžÕzZI‰[õ¬–Ö”°P¯spz§2_Nžjêàå?¸®Ó!PÑÂÂÕüϼN áØ!ä{4÷"’°aÕ tWW;{Õ–U*mÏY ¸ÛÅ„¬…¯éWÝ•–UàŒ\FËdëùaJ¬ë¸¸ ± Áu¾úÕSÍ&*Ô$܉â­k^ë…¯®„~kÕzòú d1¼ÍZEZÀ;œØÍ$2¸,E>l#}‚ß~øËøíºNÙ{º!Fnš Ú¡!œ+î ЉðƄ˽C¸½è¬ HI¶ L—‘÷<°I|xŽ¡€ÿîÿëµÊ …ð•×ÑO¯ÊäÚ딯Ã2žÇãçø§ÐÓ2`E¬ÍÈÒBe[´k.«•jg×ð@þ×+­×j×jè4”à¦ÅuT{(ƈP˜0U9`ùš!<üúïN†¤#P‡Fˆé·¬ @` èŠ/Ú0"•:ÿÒ~y>PjõóÜ_ë<Â'ΣÓ@2x'ªªh²zL3l+îjAUjp' º)/v0œ}l·aBT-dúCx@øŽ·žÝéì÷pT¨‡vŸ/Ü:Ö ùÜÜöÝï^x÷Ìé É'ð ÿ p ÜDé›_´R³ÏìºAV¾T> Õöú}öu"Á¿å# ß”B€è?âÀn­¶\âý-•JW1 gV÷B{eÅ*LÖˆ!€¦,Hè‰^ñãtëÔ—[§t®´€«B±|s#ßà qà¶V;îÞõÁ´DŒÔµJÍÇF@4J5R, È8µGÄPÅKá·?ê: écÙkH˜þ8¦ƒ©k’æ ÀÓÌþ«QPoD 0œ³G ãCöïd1æ¢oLóˆÿc(È‹H!~õõJcv¸"ç ¢2 Hš¡_ªðgA4›ß0릮jª ~=µŠÒ‹çh½Æ¼þóê+ i÷EÑ–évíúõê-Ñ©AL±ùêlí³‚ˆôŒŠ±C!:#dЃ#‚(8ìúaØÏxKÐWÂî!¬«Ž €Q íÆÙ˜°QF;‚VStEiú‘Øm¨Šý—†òùòA €L7¼}øJ à×:ð‰ó0rÀ`ÉíÆ±RS)<ÖêTTE¯/"„ú(û¾v"ê´kµB°ÆsÛQö#ÌôûQ¿\æÊ ö`èýkœ€“Ãù ïÜ}÷ôöéçÎ$²©\¹”OÙ³‰V"]º¶ À›M&÷Ïo!ƒWäx‘õq&Àw"*©r }Ÿ\©oS³¨¥ÐEö`D¡Î`PU­p„\£J´ja%`gàg.ù¢o­¼ÐæL8¬ó¥êdEÿÀômX¨§uNé5¬ü©Ä /<*f³°[xsãúZ‰@ç´0ÎÀND?´BüؽJèTÚw1Š„”Qb`»{Ø—Tž>„ßþÈë˜íÃAXt9Ⱥ`ßå¸hF!nÃNµ0°þi*Ì ¶Ÿ*ŠØ^Kø¸#‚;ÙÕu……{þMã_sªrƒ×Áû—¤jíõmLàƒ8{æÏ^zå¥E¬Ž/6ÍK/ž£u¡ÕÈëßì) €¨µ@Dð­Ûkë7o°4@imÍ®Tí’׊ª5·2 à¦&ÿ†„iX™X€‡_¦©~ºCÅHBD ¡cå&¬2rŒÆHF¶k­Â¯j6Ì@6 ƒP•j˜þXˆê¼¸¯~óŸ8n"9`hà D¡zL§ª…ù LÐ4ÉXáqiš¶ƒxwE{BîÂÿAt,' »`ûûÝø}ðÿÁ÷/èo¾QÊ|>ïÝwßÙ~ëô™wÏœI$ç²^:cÛ³IðÃ×7Êà+8ÉDfïüù>|Å2kvñŸxý'×qNðà:ÄHïÎCb÷±fˆ#*€ZNá$ÇWÚ˜(<?sÙŸ¹ýl6 :+§@˜`ê395§ÖÅûJ®Ùlî-`ÀÙÙvâTëT³Ž“¸ûã[k·ÖŠåék´½ëCID\*ú5 “€ Õg«šfRêoLÓeØXŠŽ7„ÆoÔõñâœ;gSã:5À’F!{0ðÑD Ž ìRŸ£ÏÁ$ù!ûÚ0#Þ Ú¥[×äiP­JÕ™ É0\™dyaÆ«Ø÷SAGÚî¿È\~·õ Ï¿Ê_~¹Y-°øâ¹Ól}M¬Îø•Ê6yõ†ÿQM¬xx5›ß¸¶~“Ë_­Ê¥õkr-(ÅÕéõ©P€!€¬Õà!„b÷©¶Á¡×¯Ï‘=©ã #b!ÊÂtÚad  sl:H˜ZQU‰)€ö'òÇ_úÒùÚ×.^¼ølæ•W_»º|5³xéòåW_}ùÊ•Ë éþàÿwþ‹_úÒÿÉŸü³Ç @T«ÇçÁvï)€+Ÿ8V>ùÐþñXj“d…qH~˜™‹» þý îÆ% !W,–ËÅÒë˜b+ݽwîî;§ïÞÝ>½}19“Ì”8/™I´S¥o­9¥22%÷Îoy‚ù#ù0ª¿‹x¿Îã×zÝcxÀ˜cÛ{’˜ûø„ Þ l9Bi̳@8_èP‘¯D)»tbf.ó¨H?sýû¿à@¡­œZi³ 8âò¦.pZ&Ûã¸N§uj¥¥<Âí¾½y}ç÷^)r‘X 1 «¶G+ j`€Ì1áèï¬ÖˆÊÊ$œÃÃùí¶>bYXó"&!ö W›Ý©w«v„uE ºhùKg{²ö§í0"‡œPHî¶¡JÓr¿"U0?WCeP‘°¯¶ µÁƒ¯¸µNÍŠª Lí%?ö;~ÌŸ×Lþüùçž~éEþ,[÷kVµÆÕN^½-V;pV óf@ù»oò77øëµêF­Z*mÜ|]ŒãRÉm;}*b ©Ù0¢]DlŠü©×—8 …l@³?TÀ_Ëþ»¬·¨ŠpÈhW [%0dEÅéZR ÿ¤.\¼té¢1÷{¿—(•~/ݸüò¥W®¾vùµË—Íßÿé °¯@næAr÷Àå+>ÀýüÄcûû à©óÔ5³ÅuêP`«5£«¨F¨¡&Єº¬Ô͆C0[X³\ز­Ø  ÜsV±ÐëºA¯®@©\ˆ+¬\(]»á@ùÝííw·ßyëÌ™gîžN%fÓ°îzÉ¹ÒæõÒ›Ù²P(rnvz~ߢ$>6÷w( ±—/Üý§×}Û†ð?F¢é:•ûC»…MÕ^ÜAÊß+Œ`µµòÕ/eÅ*noBJÙu¶·²Û['~ö‹ç…•ÎsÂ/~êÿ\€ÇaÁHooÁ¿Ìö–²uߨÞ%¶·zÎΧ;§¾¼rjKØÞbgº}ãÖÆµý×Xµld-‚·êuÄ/¨ºNŪ±áÌš(k&ÎŽQÖ™aévHÕÎaüöG]§ò#ÝÂ#jBÂê¶ñMˆs{´3€a{v© ‡s”ó±q¥OÝ!òì2S«Y¢T3¢D™.£&¨ù’(ÕÉöEÿå¦Öˆ¿ŒM”1_./Ÿ=îùç_<ÇŸ§u¡²`Õàþ«ùóg"‰jÍkUý*f\;w6oݼv£²¾!Š¥[kë’$–¶ëõkö è |’bŒ €m0}›4 1"ÐÑC®#'#M®Á IDATíHm¤ÈG”02Œ'pý‰º»ʱɡ,K4]ËÉÿù‹W^~¥™N§3Ù\Ž+<÷\ó勯\}õòÕË—ÁøCþ‹Lì)€©Ü‚äî+€ƒ‡ÕYñ¬vÛ¾|yåk—÷ÀÓç1助ë±ok 1’zÌ”«R]’ ˆ±qlM Un¦†+‹æ`FÍiùÄdQÛãu¼~¿vã~Üïv1X,•‹ ÿ¥ëë|©Äî½³}úî…ÜiøúàÌ\ò\y«\v¹Ô­õÒúúÆzAàKoεèü}ó÷‹÷àVtíØ |,0úà”xݧÖÃØÚo©O‰€Aü–g[²‡Ýr@MqMúÀL0+ ” ,4à'¡–íþÏú áýçú±Ð³ñ9ô¤'þ=_*| ñBéùY¹W°¸|'=ûÕS-ZÄ3ݹçè4”?c^ÝqhMÑ AÉÀ]BXô#­3Úù üöG\ǹVÔR1oŒ!ü.Mð7e³†ÔàF)/ºÏÚwÌPñÙOIt¢ ú¾1"çììÖuE¢„_E¬Ê°AØ à¹5[Ü®,H²S“Dɪ互-9ü¹çþayy™Cç™øþÕÿñ¯øež/?qÁ+´.ûa-ÙýWsÜ–÷ªç.èüÖmþÎæµüµ[ÁFis£tmS,EmœÃnDHþu¬k0$&‚"ï²ÿÐëK?ðâ/8& A?PV`@„‰ ˜¸M蟯¬‹Ÿ_µ{_üâøË—^I'ÿmv®ø^9_Ú(ŠÍ‹—_{´Â•+ ø/|ñ‹OzLnçÉv3péòMS}ÇiwÈ8¸º§ž>..huÍ¢¦Zµlõ˜!Ù-Õð‚®”l,‚Ûê„(ûqpûa/ŒÀÆa†Ëî†^¿Ûïw«ß/ð üðYâJ·¾u£”„{÷Þ½ðîö…·.œ~ðàì…·ß>w®\âP?”677 Ó?1ׯóc³1RzØßý8‘ çö£¾ë÷»a7êÅaÜ®ÃããÅ2¢›Mï <ˆb»¸ƒYC¿ea³ð§'•ÙÙû4%9«6rjÖbáݾ_"áç¥?ú~ÞúðøMNj x¢œ”ʬ’lfõn–µö©öÇÅt.ÝéØ_Á§äŒ”<{ûÎæÚÚífNKˉٙûÓ4FUÆ…¿Þý˜Àª!*¨¦›˜3¦ z‡¡‚PG ÚÙCøí¸¾ÃRZX­Fþ!Õ†»Ór7ÎùïâXjlDõýá»— Û¿CÕ á ä‘Rq»†.ÏI2>x?•¬õ-t FgŠb)m˯yæ—|þ÷þEù¿.›ê3?ø¯?øÁþÍÿùÌ_ü9ÿ/~ÿP¯îÝ•mºÿjéžUóBœÿøzîÆ:1ÀúÚææõõÍÍÒÆú­AÉÍvBxQ–ædÝ@D f¦1@XÅ”ó8äú" 0›û£¹H2þ°aÝpH€M ²^LMìªW#±¥¬ZÞàò¥fî›ßL%‹Ø5Oðt/½òÚÕW^¾üêïÿÁ'<€Kûã½û àà¡=@à@˜ÞYùÄâžxú<Öê‚¢6Œ0ÌjU /¸öªÒÒõHYHÑ©°c&¯mÑ`­åSøü]§ïcù¯ßíuû½~ |$(2í[*òo½óîÝ»omŸÙ¾púîwÞÞÎ>xpú\¡Àå‹¥›·©TJŠ.™dçwÉœ#á–' „ã~¯ ¦¼a–'ìÁ`ë]? 7Dù6Æþ¿cCL;8ûë‚ L1Û[ÊéI1!n%³ 9•hdÔ$þ,ZWx(?5äýTèýc¼ò áÃíÙdVžUDx¢ *¾Ï6ÌöÁ(îÙªô¹ÏUì¯àS FB¾³qçÆMð;óêœVf+=>¢›Ax"àõ.Ôæ×DÊÈ*Ü®U;dð;8çxî$èÃP÷ßÿ¾§ž>îY«JÛÐâÐD?¦KUJ[ÈZ$WdÄ0ueÑÄ[9$QÃÎøC!ù\î®ya‡!+Æ=Š<_,9о××oÝ,•/Ü}ëÝwî¾saûîéõ³o?¸wúáiøó–|ø«\[[OØn4x)<`‡ö´xæ³Bލß*˜>‚—ôÃ~áÐ}„Åý8ìö#LQäO÷Æ&íÀuqLê–Mtá^3¦_ù‡ÿPæfù‡ø³ð‹ÿhyYÞ¡ßý9÷qô‘ ¬$M”“I%)ƒÊ€] ™Ëi)YÜJ(m³pªMU»­žÒ4’âÍÆíõ[o¼Z"™g¶f}êI¦E·‹µ ?¦½±¥V•Å0©Í¡¨°ë11ut(¿ýQ×qêu@uÄHÀ™ã)ˆÇîÎc¸_KQ Áu2øP¤êúôý#æ= §èû»4;h ˜áןá¯U úG±°5íÆ3ÏüYŽª5vkÙü¹Ë͆—ðý»/Ýýþ÷Ê?8óÿ­q®üâ¹s¼{ðþ‹±›?C¿Ñ¡x.hþæòµ››×Ök·Jë›^Å%gÕuû5xyø À[‘„Ê¢ œMöÐoøé×oÊAHíÒÌ5bt–h •øˆ˜@sNv|î&«Ð¬Íc€ÀåWOœ<¹„ÎúâÒÉ“‹Í¥ÅK(®W®¾ü@ à àq?Ï^àå‹/³¿CÀ5}À=X~ÀÔ½Ç÷¿?Q|â<:‰{CSBSF Iµ®[(€*zªb*ºY?‘BÖNŒ¾±á.îYV/î„=Ç Ñ&G]4Ò} @:ƒ_*s Þ·®½YŠo½õÎ…»ïn¿òúÚ»ï\rÒûãOÌñ^] yÈÎç{Zqñä‰'ø‡Eþa‰¾Â?ApÝGýF£,?ßßûi¹ûQÿgÿý£â"¢ ávI¸M¨€è´Eül›Â©v¡DÚ `…ƒå;·oÞÚ€_†f‡JÅÛE$QÄQe¸;]K °ï\Ó$ã+¯Ô Õë´[O®ÿ `P–\´È¨’ °´…ìGó¢  !ËJ½ÑA©ì`ç}‹è9 ð!öB”0û½>BƒŸÞó£(,ùRUÀë7(üÝw¶ïÝ»pwûÁéÍ7î¾{áî™ÓwÏžãKÅÍ[¥ko\ÛxÃ/úår!•°èü‘ƒY³ÐmÅ„q„Ù¿®‹Rï“—¦Û…í#/€\ý¸ëbî€ö;q[ˆh Àiù«ÊFñ¨Û“BC¥Ù” ©.™² <ê÷·ô†#ü\à… ôü‡ó]áád©PÈ•´7 ,}X,éô– ò/èœ@׿RÌs‹M]ºóæíµµë·¦OÒîû.Þª¸FðÕ¯9lz•ìFÌ;ËÎ#ÊßìpÈZÎ?ßþÈëT¯cò;¡X—´ê4(@o…Xï‘{Ê^ n<º¾ø~ÝO#ñ˜ ›ö¦ÕL]WeEN`½¾:£ûÏßH¥_¿Æ›ëßʽý&D¨‘y-‡?sîÜy8ÎcßÙOçοxî§/ó~çñýu}+ˆm§ jn {¾cwóö;o®olnòëüú†½y{óÚÚZ)°3ˆ«8Žo"oFÕu“&0jÇŠÞÎt”ÿë7Þa¸IŒÁŒžM£ƒÃ&½Éž'2pÅÁbˆE5ñ©ÀøÅ ¯6ÿúÎ_/7äú î¯àP—^¹ú/¯¾öêå—³ ž®ìÕ=ðøx¿p_»ß`æò¦Ó^0žížxÊ~à©ó°N@Í€(qÕ E´…Tæeð ÕЭ¾ÔBã >5þ»pã0è8z;»¢vq°¤À¾€U€¿Ž˜¸w!ww»´víîwOoÝ=ý³çÌ®­Ýô»Œ`BžÛÆóCÜì†XÖƒ¿±×qlR, \8îE  3€¯o3òûðDxÝ#{ Š,<>Õb;r¢t—'%s ýˆ¸ÐàÙ‡Éð©ó?' 5„ÞŠûó|®ÿ¡ |´/›¹F¶^Ò¥‡\îv³Ð,”YM““m³Œ ཥ8‚þl 2Þܼƒçæ:Çž”1@Eðëx1fÀᾯˆó¢\›yAõ´dìŸÂÓÒXú¡üöG\§²÷„Åë»S²à]ŠðQX)o)æfÐÙBöC¬‚ñ¡û Þt‡Èv±Žo‡Üä_&õ‡™þFãæ­ÅEíëËë¹ÌúµKMc3/ÄqÐñøoðçΟ=óo|ãtóÛK/ž†ã j‚3ÚéÓy?Ø¿ÿ0lÄ« lmê¸òÁåïÜâïln¬_[¿y+€0týÚ͵8òLÛî1 Â:YUð]9:ázh˜0R¹¾»ÄUÊ¢Êb×Ãý¦˜7˜Vtö†'B¸ÜÅȃ[@Ö¦À4pîò 3ÑÕæ"ÝšæÒå—¯^yõÕËW¯¼<ÍìyO"S.îß×4@>kæœÖª©zŽÓi§<~ÎT8Ï"uÊ~h"s‰v¬ijмPE§‚Ð[©;j!$²r#_\ðÞöì~¡xa,3"¿\(­ßºuíµ÷Ö6h€{oƒå/ݸöî»ÛgÎl]8½%”À¸¶~ÝOû‚ —Jâù©{3™¡æÁþ1äÇcƒ¤÷‚nˆ >Ø' Ç~?€è ‹k6àSÚÍÚ›p"$ÿQRÅ+|’?)0@­+:¸¦hHá#]`4œ²¿]« Ï Â ?sû‚Ñ03ojR^Ö õ"x%ÎȈbÛìƒP\mÐ8 .@Vkdoß¹µ¾ycsóÆ5zRÿ§…Ü}ö>,ˆEp\ûÖñ柯B:‹¨`Š¡™ >šBN¢›&‰Oå·?ò:ùŽ©¹g2RGË.k‰Çɸ]VîŸÐ–ýefDù íCö³!®ÒãDä•5917'ÖØ@tµ&,^|æÿ]ßh¬/3›ÛXo..o…Àï1†¿ðüâÒÒ7›gÿËø¾ÇòŦ®œ>}Ž÷÷ï¿(€Û#D6æVØŠ]pE  ¼QþÎ~¤ž¿~ÿõµ¨T …ŽÝö»U‚™›KÀ‚ ÀÀ^=â&"^tø9äú )@â£jþgôªˆF6Hµj f³‘aqY‹zªñtàåWuM7²¾Ø04U¯7š'N\ºòÚå×^½rõÊÓ9€OŒñ¢Ø?Þ¿¨i&yÙœY7´ºJè"s ö¦K S©ÙlH4¯|¬¾hªr­µ8²lU¨7ÓTŒzÅ®½ë´âä«ú½ÖéC/êö<ÄFâ0ͱ ðÄÌ·6˜ö-ñïÞ»·½ýööV©tó&D¿{÷ìŸ}çŒPÚ¸O¸¾–ò…’Í•ÖA„ÈéÉX€} ò×Sç/L?ÞOæóSÀ™ù¸¦ºü>Î<Ø{ÎT¦˜‹uU–£šÊ – S‘Me §íßCnD¾G*n‰°cˆÒ]øËÓ~"- PÆdÄú\~º·ý–pï^¾saûî™ ç¶/lamæÆÚ·6Ö|ðÜâ57‘ à.„±¾¶BÊ=ð÷ ˆé+Þ$àéÅð³Ûïâ"²Á­Ó:8Ôž’PÝ"´$¦Op²ÌïåÔºlʦ¨I†,|„%€·«åF£ÿ9áCì äšÓAþ3B>>@±XÈ¥Ó‰D²(pÙ¹gçææžMÂÉÏ>ËqÙÒÆæ;××ÖOD°!þúŠ—½oÃÛCìm‚·#ïØ[©‰‰!Ö€ ÒucB¼7È+Eàš‡óÛqÛ]‰ˆ‚õ=zÞ]¢ùÂŽö1•$GDsKë h!ùÁŸaÿ`Ì @& ¡1–° ’òOlÐä~ùô3~‘_Τ_æ¯þŠ  <ä¿ñü¼¡ó¼q–û†ß i¾ùe±YW¾Æûï?¸´½.Ö!*\¸Žºp;¾Éß¾uûÖúòƵ[üZióVéæõ5ˆ­RÐò¬a°SRàMéðæÈàO¦ÐÅh¹½¾à¨0>¦¬Ê¼:¨&&DDˆt˜ÞL†‚Õ‘µº†u`½®I:_YEÖ¿aœ0á ™Í¥åfãåW^»ôÚ˯]yº@®<1Ö·§èX9ï>œ}TÔ PÉæÊÏ–æ m…Q*€8ïž_¥ç1pð<Þ›Z*’Þ»êp÷J¤Ô€A}QÑtP—K^{¹‡ çíá‚ûžÝÆN{°½ÈÒŸ üB™í{ãÆúõ'ðÅíw/<¸w¾µùw/l_¸{z;[J›7oܸqs­X.Ú›o$“):?Âꇈí~]ÜŠ[ˆþrßÂ.a…]¯¶¿ :SAØÇõ j~áÃ@CÄ}ØÚ~'üQ]¬×S'rösÌ Ðá×ÿ­Ð4î÷û÷þ§¡ð‹Þs}ôÿPàè…z¶Ô0!¼À(-–hœ q²,,62 ô·îÜÚ|óúk7¦'aÿ£Ž§fï{ží[ˆ_8U?fyæTkó­C“h$ˆ¾óç‡ðÛu}‚)‡1ÕöG,ÁÇXÊ&˜ñXKüxD˜4.3˜Šš"ßüôýÀA°ÍΨ­Œüòº,á<”¢¿ Ÿæ¿ýÜzäÿõ×ÿãß=sáBŽïaf§Çíùã&úOyóœÁŸ}‰çõãÍ—NÔšMã,O•ÕéýgCH2.„~pÿÅ=¤Øóî€r¹É_¿±~ãÆ-´1ë×Ö7Öâ˜Ëë9½J¥ºVE-ÄÔoÝ‘õN޽þ4ëD¿1ŒïN ;G )©@ =X01ßSBC7A î÷üñ¿À•EÃ\j6Æâ¢i6–N<ר¿|€×.ò_øzS =1ü·§0;zÎi¯vÞ8û>h³¦æ´^0tMl:­r«@Ø-ø<ïSϪ°¹¸ZÃìA\t ÉšðG«7 ´iÀMjjðÁ˜1š>DzÛñzð% Ü]·u»”­'ùÇ^@q‡‹¿Æ—ŠßílŸ~pWGu|ýÖÜÖöé­»Û[YŒ66 nªT*æKk7½TˆM½b~‚ë€Ê3š & GrcÓ!ê·ëAŸ­÷ÐóG`BX úDfì÷»]û~¦^Wêõ“ìTüÕ‹ð~–áÇ‚!ö?üè¡P×ï ÂýøCïß—>JÉþãG^ÖJ\‰ËfD©ÜÐàêñGÏ-ªñÏþñ£mk·ïܾyûæÆÍk7¯ùJàQ>ÊÕ  8­Ðñ¼š´íˆžX™¡RTµZ™f¤¼žM¬/Oç·?âú„e®4ü¾gÀ±ávùb&L%¿ k”Ç[›0s0vØþÑ´n@û†‰(Ôº©I Ühˆì/‹Â¹Ä_ýÝ3ßJgÀº›üúšrá·rÙ—neùÞTÌg¯^=ošüù«WÏòÆ|óÅEPÊÞóž¸ÿ@úÁˆÑ º ÏÅÒü-Öo¬¯onð›¥;pâÏk¡´Ûà©v+à£Vå‹.¼AJ|ÐðFñ‡]ßi‡Hÿ¯×„FƒØðq 3OŠ‚ Âk4ê‚q>휻r¥i6ɬÓàãÄsÏåW¯\½úê¥KO{ ¸2ËÜÕ+€³ ¬ÎêIîýöìC£  ½’ÑU±iuP´AþÛBÑé¬ÀóÎî+€§Ïƒøäº‰ùÇź¡34YŒTÅ®(¶^ÓÁ‹YDšîÀr¨ÊŽÊÀöÛŶŒto».ÖQôhÜû|Þíë¼ó¶s¦µú.6lnÞ…àÂwÎ^<÷Ð,Ý8}ïÆ™ÓœoË^éúM7‘ hÚ§¡{€0àD~ÇÃÊŸ¦±^+¢†ƒ(ì" ™/Jëq`0S’\t@9³vsyy‘×ÞШ`,® QEÿâóUƒÿõ¥åÅ&oþGþj½¶øõÊ¢´|‘GÇóñýGSÞÚœÅØ Iù;ü&ØÍõë›ÌÆ”âR(x–µc†&FùXdÙÃ7iË8efþôëÇhÄ“QŸ°¦`¤£­C‚@Á6"™†¦*5„ß=~¼¾§§/^¹òš©¿93›H|ÿ½F£¾¸|âòE°þW_¹ôÊkOO‚à6Y EÞWgñhn=PfÕ-MQ·T þ“L‚¢Å|0µ•LÀð‰û à©óh5±¶0JjQVÍ H…üËg‘©A ½ BðTëK!ãèXÏ‹TÛ¡ãÚˆbTÞ»„á‚ ”Øycmcýî;·/8§W·ÒõÍ l€àí·½ÒNX6éK¥~j6: Ùžb?¶ÝØŠ±ÌR`¢ýzpô»ÙyxQÌ î­ƒB€;‡û° –±cà‡õ„ZÓSà'ggs û?Ù¯ÍÔ~òÞðG½ç„¸\*—‘ѰÿóN¯+{ö?SÎ ûÇb3£§¥b½(”ãê,ýìgK –>ú™¦Ü¿xßЕ‹†ö㓊Ї~¾úÑÉâ¼>VÕ«ýÖÞõ¹m+ËÍçœIb[$ è±Ä'€/ÑvÕ=ñ¤3}úsfb‘x¿HvWç¸ÛqœÈΟ0u«ëÞª™éزõb’gnù¤»“¹uÏLÇ–¨‡õõŽ_q’NúÓ­óý®µAJ¤mŧ; Y´Ä @›Ø{ýÖo­½öZÃ"V³ÀXÀÙ’Ž¶pn˜(þ+”J`¯iQÍ™ožWßþ‡¶cÆn’“xôF>p²\O‚ú¿"³¸·ðʯÁÿ–¬TàŠ8ï½þ$•¶¢¤ {e…2ñ—ËÚJMýÓú‹Kì?®ˆµ•d´0hI.Ø’}ñí“Ūø/õ«õ¿ƒïAÕÏ5åòïL] IDATrëÄ9Ärþ¶k;¨0ç.¹ˆë7o V—Ö®ËÀ«¡ï Ž`eÄçO˜æ!€U•¯¾%Œžóü o“´( ©ÐˆÓ„d%!Ã_‘BÏßL¢%JÅø§é|ç/_~¿®Vjÿ÷o@üe0Z­wÁøÿêåK,^õù:·ðä'à|Õ‹¥:_/Ž¿K§ØJ¦ÿ§ëoâ™0yŒ Èi/~ðþ¥jy Õó—>ø ŽY[dIÕ € UÚò}ÝC“d4 ]Ìz ¿ú̶‰Æw¿‡>zIð»]ÂV—0‹?û­î»u®}îÖEŒ \ˆÝ:7ü'ìç Kض°~íF×v)Ï5°€¦ñ;fhx–cØ@Ý€ÎÛA¿ïö{X€ÏCçO„{^M}lï‘ö>Väü>‰"ë½Û‰R•IF&ÀÚõÕ›8}÷tĆ¡üÀ[ÎH]éï»"üx¯/=”¨ý¯ÚV:“f“€ÒÉj¿ùàÞÃ{?„—{¥í;›ïœÛ¬m¿»Ýê~ øç-tïI¼{ÝÛø|À.É»ÿž+Ï–ò$–йR.7{÷añ6U#ÛMŸWßþ‡¶“ o¤&ï×Ñ6\²'»W0à÷Û¨¢G”öŽD½e@\óÃúÝXïç9×#Š¡8¡dÉX·O.Êeµ ´³LJ‰¨ñë+7ê õZ©µ$‹ Wê~MZ'ŠoŸ(ÕëW.\mþ¬võÂh)6ηÔÖ‰·ÏÍ'æüd†n]PÑüë…øè&ü,¯ˆº JHÁ¥@²"ñš+FE³¡‹2âBvþyϤÿþ*Z²%Üèh }-$|7f˜WÓ$‹P.ª(Pêñ}@BßâÃóï^Y¬¯ƒöWÐh]ºtäÿÝÅ«`èÑ1¹\n°¾Ï9¾XV“|qü]f¹$W…ÿ+*_—ñÄ ˜¸Œ[4Ô>¸t^+@{ëü¥÷«”©¦^è®+MßÄåyÃ7°ÚeèÚ=Û²0"Û ÀÖ·æröìï„sgAÞµekõ3“½xkxváÜÚÊG7®/}~·!ä K%Ðap}-p\Ë4BÜ?oX!Éúk¶CW@­£žÚïaêÑžG¼ŽA—Œ:ü¸ß\€È?®ô£uƒ;Å*%WSÖ—¯}¸²tmko{{^†ÃáÞ0@Ž‘–¤ð?ü{V6¶¥Þ—"–7ß?¸-®^×*’å¤ðþÝð~³y¯ùåãû@Þ ïÝ©lT§¶Nª VpÏ‘D£Ÿ¼÷F°°a© FkÎÏͩ͢/f`þÍ‘Ú9Ü0W!¿K²,9&¾¿¾ýmÿ+t"-'¡¯ßÈ¡ï°Ôõ·ß¹U§ˆÂ€¾ýê«ñŽ „R û9×÷­L”}T” Ëñä!%¼†QDx0,üz–e™_ƒF½¼>à³Ù¤Øë‹/¶Ê%µzU­¸%^A/¼xäÿÒlüƒùg…ø|q#J/D³/šÝž'ŠƒõµÕåµPËÂêÍ5! $Mú`ÝÎÌhR§9—/‘òd¤ò0úåoŸûüÈsÀå€oGARßà¢QRmákRí nƒÙ”ÿ Ô8¢úèwZª`„·æ›ï\Z¼zõ]@€÷€¿ž€_ÂWܨ¨\qü½Á%“ÉôèM%9zÏœ€ñ}*èRß¿tþ-µ8õgÐa ó·T$¥Z)kõ²Z©TkVÝ÷°øîÚ5Óï’ú7¾ezîÒ% ºÇó™ßf"n¿ðôù-Ý à\ç,ùM 87Üøïš6•'l0VWÖn€o¶ƒ[>pÓ‡eõ,à^”p(tàôˆã ~7 ^\tq#¨¸† “áY7èÝ©VO5€ˆ×€²×o¬®,-¡òß1ÑËžHs=NÖææ¤Ùô¤·j|šIý§¤æÃ4ÿ£æ£ûï=ì÷ PÎíjÚ¥»ïx'=·ûF¿Ÿ–ÞNz›¶kaèÙX$i±gHÙš\¼0Êf‰ ƒù| bWp‡Ê÷×·ÿ¡í ãeÌÿ oà~DÇŽ?àòÝQ *•ý25dKÐÔƒãù×ã²_y¼á çâsejMÁºÀðÅÖÊz½þÞZçÙd’~1Öj5Z-1Ûº!öÅsõÖÉ­“¿l8霄ÿOž¨ Kºþ¼ç§’¼ ö¿újÀI¶}EÂ'¿!ùp7$FâVÂ@š`Γ/qûñãw./¾ß %ä¾^k.¾séêÕÅK‹ï\¾"êùš€ã€ç}®XP®8þ.à¼MÞd’£7ÚÓpü掫 ÿ?›€_B‡°ò•ZE-© ýJ•jÚê&ã1Á C›m†çÙÝÀö£˜<1›Ùçöëƒåõ[–?t.šÏ.àºÿõµÏ7>U>=¾6™' ·m®l‘£¦ ò挭[¶ƒ‰½=ÝÆ:]XsŒ.øcºýW1$°ïGíÐæ“úÀP!ôúýÍ2€µ•›7>\ùd0Ü`oÞÜŽÅã{Û‰xâ®XÄbòTï1ñHÃ\«uG<)mMÇse…9>x~ù¸ùèѽæãÇïõ>‚¯fëÎŽº··×[â¯ß–îI]va¡`àn@ ġ.h9ŒÀ€Â&e‹ãç‘`ÜÊóêÛÿÐv”]¬ÇWÆÈ©#ªUª1¸WWÉ*#¡' ËÌVŸw=ü R +zÂå@š+æËp…¬! ñkåu1+&æŸþie ¶8­Ñà€_üìç.¼}î¿þâç?ûÙÏÎþò—¸‚}é­ŸŸE÷Â[Œ‰ù‡Å£çëYÝÌ¿ž‡¾˜­dØw„?A¿óêÒÍVWª„VݰHú¡ÑD}+Žº ]îóˆÆœ'Ä‚›§1òw£"aôI ‚†‰ þFš¨}!€XÓ¶/]~ÿòûuôÁÍ7ëÕjöãS û—Þ#ù77pc”Ÿ.êétqü]hà|½©$GoŽ™ÄÓ&À¬ òÿËÈã§?Ž€U‘d­&Ãs©—@1T¦©ãv,’Ø×»–Ýï!…‰’èÛð-‰Ü~ ­ <ï–û™µyë,dnmÍúû7;Ÿž÷”©VÿÅâè×ø`Ä—zž‡ùAp²[1+1º‡}Ü1àwCâ$›ˆ7i´ÿWW—?°+™_¯Ó,wmmY,¦ÅBZÌï‰Å“bQ´©þ=á?¤þ(Èö·¸)hðµW9YÿàËæã‡_>l>î>xüeóÁÃ{_P»ÌÞžüð¾nÞ{tJZ¤{÷ø{V,ð;—@ï?|ÏIb ÂL”Æçp{,0 üœúö?´õpT˜¯\Q&KÑa•n°ÓKT©Lƒ“ªÜHIPžË…b™*IÙ*=÷zòwàŒãÑ:'œY²²X)`?Ä_eV¹A£ÑùÆkµXJûx)tÅ ³Ï8.]x›Ô ¸09ÿÂñóÅ<• ŽÑiݾß-ªç»‚;À|ÞúÒòɰ’i5B Ç`4˜`ŽÉÏau²¨çÏ{~ˆß|~oI¥Ä¯1q(®|M&˜,„CEF à@ F :ÄRùKW._¾tùÄÇøjU®~zðÑÇS»üþ{ï_è8œ€¸Ø^}cÃ4ëûßðbŽþâÍïaDZƒyÕZ­ZÓ”èó«Š„k”X \U›ÕšY¯Û ,lÛ¡àR;°ðÐÇï¢üÒ$·×ëŸbÞ:§› ä}¨ˆ» yš§Lå ‹¶m¿ó,Ë‚q5­6nù+/À€° ×¶‰Ù[z¤™‡?`/ÓðÛ±®øšL`ávµˆ@ƒå¥ûÑêõ\ÿðÃëkb1#T±@v*µ pŠÿWêÁç%Ñ@V¸U›€ršO+©âÉþƒæ—îƒòï?~Ðï?ì67Á¸wï­…þ])ÿî¾)I½î[èy·M ©ºf-Å*uQiâþÇ­Á9ŒK!ª³yd×ß_ßþ‡¶—Ê…-ò×KQñl8JQ{‘Ô,AØÂk” yô‘!€‚¬{—Ÿw=¡Ó³ä R‰ ‰Š÷Á'§ »²ø+~°’nµj#¨§Dâ@ù=Ò;\ç‚sÁö°ø²>šãçëDÕŸ±z¥c§Üàd‹ ÍÐñÁhÎàãùyÉh5:­|n8;s0³dHPF)=ÿùMPIZDÌ‚@‚¾• ÿ#Ɇ¥]Âu’à[iZ þü´àÏ€?ý>O.‚`ç­†]}~+}„¹+åŠTÆ"¢ ý´äjC…ÓuJË7±¸9áðØ-TÓ J’ÛŽÿ®µÉšæÙ[‚t<¿cygÿ«çiÓyÂÌõÁú¥% ¾<]Ûö{Àz¶my®Ý >î C\|ì"ÿ£'pþÄ öp÷P£à·îÕ2ºÿ>f×—Óƒµ«ƒõåk¿^Ãh`­T-‹U²)€ï÷?îwv”(HJŸ™d ÿÍ«'j/›÷6õ•~SæÂ/ûûý/ï=ìŸ} õßð\úhõúµ_/­_ßÞ–vvno·6Õ/†·Õ·J…œ ò-ooV¨´TÏÔk<§quñÿ©‰ÿ:/þk†Tú}{©ßLŠÍæ©þ©æ£û»÷u})Î<‚ ’úðîmŸézÏ5 ®[$B*(?²A£¨Tô‚ø>ðÜúö?´½PšÁÕÇÂìHÊ>NT4ŠÁ¨x¶Çã`­ çHÜLTÐ+ÕÖ{Îõ3QsäÓxÆå ¹Î;E‹ïYh외û“¬ÿ`NwÇøÀh~‰äù‰HH ´Û¤2ĨýôOOÃ?×ðp㨋‰Ø$4ÕqÚ®fÖ;~VªÔ]ƒö<~º"éÄôÌ’}ÊdQvfæyÏHA²í3þ” $Û†IÀ$¾÷IDâ¤iúó˃?)¸îñTF@Ø‚r©"ÕšZcìþV«Š©4x¯¢)MÛ³1 ­6?°-Ü•ƒÞ@0ÏŸàöƒÕ¥e‡}çÓ÷j½®çëëm¸ê܃Ãó¿ÛÀùxe}}y°¼Lݬ-­ü:óá:·»C˜¿ü…6¼óÅV‰Tþ0fƒJ•Ò&ÒØÏ ùE@yM"'4ïÉHþï6²Íz6ö¨ù°ùðÞ}éÍ{ýü½Ôí{»'âñ¸ÀßNö~ÿ-3?gž_ßþ‡µó—Þ!̵?~“ =ª\Ø(Wlƒe˜xœ©r§êÜ©ßÖ¤­J9áaó¾¬ý_ÍjMÒª ìa@p¿/Ý—¤îÃ/»aï±Ûªg~£LuàáŒûš³Ò?·¾}ì9í“×gèD|¢çùäL"Nc;{,•wPÏí·“”Ä…ãÅñõÏnÿþþ¡íÁh¹çévòŸ_Ècòf2ÄÈ‘t‹(Ìï»?þ&‰O÷° ÝT;ʾ/‡µ»O?ÿç|þ¢;KömÑ ˆXU¤‘xpÑ]3SÀÂbQmpL‚e±ªã·¤ÒÓwQM€ï°$" „4%P@ÁË…?çxZpÿR÷© œGP®TË/”dPò…¹ãÇçJ`TÀÈ•«uIªµùª¢¨”1—V­¡i˜lÛÄ퀘€Ûé™fÏõ{“9€‘Ûkê` 6$ªáaöž ‰±ðö§¿þë`ž°[YWX¿ysyó 6uw¼QÈÁ4$¸Úkú@qý,jŒ$ù÷#Ñá•'~¢xÏ«ìm$é ËÑkËË×>úXÀêµ~2ÉI[ÈüoßÞ*ÕÿÔ Û°t–eâLŠi¨"ühqâ‰Ñ ÷öOÉÍfMªI§ÍfÿÞÃ{ÒÃG}éMQ’NٞΠ±Xì¶LW;L¡õ??;[(º…çÕ·ÏĨQ{*vôí“×óll&Nc{TÉgèD쪚NÌÄ@±ðZÄHã9,Š[D¹îñ9tâ¡êË?Ýþ½ýû_j;îh¹çév, 2Ì{¦1b,ÞŒ5UAüàhüÑχô`züAµOµ#û‡vx}vûäõÏÿû??ÂA`5(SJ¥€ë  ¹x¾àJ¤$x¨¬~ƒ¹OpûYöGÙCøR+¤þökR.Lš(ÌåWü“½÷sÏrÞý¥îSÉåv¯@zúB±XÑÊŹ㳅2>©Ú,kõ êùê|£Vm¨¸  6€Æ4UÇÇÈÌ(·g»6©Ùs¸}JÒ*[Ï“ŽÖ„æoÀ¬Ž?@êüf¸ñá7Ž)`ê¦A”7À²½ÀÚ&tŒˆr¨»aß­ïûNÐ'‘€}¿ï†X€ÿ=ÑŽéb=•¯rÃS`Œ|òÑêµ÷>Z]º&Iƒë`ªó¼4¼³]ÊÏýþ6sgkcT´ ‚gˆøÇOüN:õ¹Ô¬Š§ªâgõÑ ›Í{bYªk Ijö?h>쇤GBð†¤÷ÿþÑC+ ÷¥è*õ¦Ù±Æý?°¡Ÿ]ßžNúö©cÇ(ÒÎÇÄɃv´¤ÝÂäõOÌPñÄ\žH"–JP1:ÉfÒs<ÇÇ&r|Šz…ÉŒp¢ürKOÑþƒöCû÷ôß?¼ 1–{žjýæ@>†5¿ÓùÜ,2þ&<9Ì¥”;ž#ÎЊ¤6Ë*@­ Î›¾ÝÍÞ”r}¾^oV0ÜÐ$^{×Â,îýÀÈíQ§‡ýPÊvܶ gh¡áªµq}€ßm¼}T€°¼¾6ÎpÑq‚ƒ`B× 8Á·|°í°ça2`LBÚëâ≊ò†‚Ô‡½éöÀëú]GVù {ç“•ëë­,S{ p-³´.%“„ܹ½yixç‹í_ýŒê2qýT<βº–ÿüçˆóÍýîãú_YR§pàK°¤ ÷mÉ–ï/œ œ“BìUªs¡ÝõŸ¸Áí¹Âaõíéx,Áå½d<¬Ú96AÇ ËÄâ¤}ÖBÖêM\ŸÍ¦i*‘8–`"ùgbT >F03l†¥ffRBjf†Žãîù:ºm\ÎǪ<9gD{s&.LN´Ö¿§ÿþáí¡ !Öþôê÷?ݯ×:6Ù¶¹Ÿ7Àv'ƒ ÍÀCƒ];–o“ þèáóûQ°oè“,aä· ïNµû¡‡Eø Ïküæ'ìÊÖÇkİrY €çv6nßÞ¹ý{ú­ýÒž#öÏÚfûT–DÍ+R£&íŸì Q­Õ›Rÿqóñƒþ©·Ðï½qïaGºÿò]i³úߪUªªz}$nÑ·Ky·˜Ó ‡Ô·§g(*•Nîpy6E%èÍñLü•x íæ _˜s@Þö¯—$‘£€1ŠòÏ$âq:Á²ð¶Ã¤Ób†ŠÍKÒKP nFvA»åìB®8kâú\˜sÛs~¡H6ÆÚ圭LõOž-(QÿàïËsŽ2<¬ÿSý{b¹gª½`f>_êNqÛ÷º]\„Å’èÁ‹F+«MŽ?.ŽÛAìzí¾ŸÑ>yýÁóÿ¾Ïϧàì¼+WJ ùÿ{tÀOªRR0ˆ*76¢Ä_ß‚ò{x…TFÀŠ¡¸=à«?DE…¤IÀ8À«¯ž®1³¶&dW³@8·úáõ+KKKÿøë›$!Èù/?=Þ{ê8óô[ûÇ¡û§•ṨNÀÅf©ZRÊ•¼:%.íZC©–UY®V[æÉf+ôl'´IaNÌ(0Î Ü~¬Ó]é¥n¥‡‰ûB?0ü`øù~}Ïtÿïûüø|Çs nOCéÿUt Èå¡0ZA,©˜þwý%]}ogã÷ÊÕ(™"É|¥Õj]Áº‚˜Dš¨1Œ3½z:µžÉ ëËëÙÁ ËÆ^:’\ÿÇܼ¹róÆÒdF gÀå÷žøÂ¢ÀO¾·ÿõ<¨îÀ4(+µ¦¦ÚžÛ¨ªJ­RSkµVóÔ|ÓîvmßC_—ë9žåE9€·/îëtObMõˆfËY©Ï‡Ÿï×À€Xëy¦‚ mÓ bcê7J?`Q€îè’B!ŒaãöÀé†N8jŠgYžÓn²µvÀµµ•°€ÕIì‹R¿ÿEÿ§4þ 1­qrœTöìƒBå8’‘hwäÿÄ<§’´ü,¶,©Öì¼Þyýõÿ ܱÞtLÉyô¸ïtû·)ªZ¢«‰’nvÎtLÝžƒ¹•ËÙù¼á>«¾=§âI6-‰ÉM§2’Ȱl2 3ƒg¨Íe’0íœvÎÍÁó®ç²bV :P‰8EÓTŠâ@ýK'aÛÐYŒ8Á±P×Ê·gÝ9t¯kX@Äó³~ë:äs³Ks/4ó2´›rÞôäQÿdèŸ.»æœ|&oÉð÷MÙÕ-yºÿ²{\± }²}'èÛÖÁrZíÙüüáÉ!v-ËA@ ©ê’è~_Çš®&˜ï¡EÐ<ÿq;®ÿ¡þ·‘ àÏO´\_'žÿaŸÿù…ÐåÊ? ø6!{%¹hÅfs¹Â 2’õ_ƒüoí¨ÚpxåÊ·_}óíb …çÎðû1Pð[iZ Fð“('à«ÿ7²ë«ëBv-›aéXŒæÖ>ü?—Wo¬¯,¯Læ<ž< ýŒct:æåËgžj»ü¿ÊÐi4§8öT @±¬(–n7h§ &@¥¦¨õzëdë 8æävl ð½Þï¸ßÝÒä®·¯Ó¥—ƒëÈc7DݧŸ¶_À÷La&ÀAÞ€ÎæT0¡E`­‘™a Qÿ¨í} þÃÔ?ãÅÜJÒ„‘v,©„]¾¢ò*˳ümá“å›7>¾±Ç Ó}òFìH}Pï'¤‡ÃaK{beψ— ÃÝ=féT6{jÿ„Ì).³kIZƒíô:\§gf;ô¦¡?âi·«€˜T•*Uí¶n¶3†S˜3ýÜöÿõíAþS`»óY`ì©$“•R `3G%S©Tb†²“ƒ§ Ï7ºžDI@ñ€:Æ0´ ]æ3™ “°X“ËJè fñX à!‹ÇІùÀÒÑ víR7'9Ý•²á”¶#›ŠeÊŠ)“þ)KÖqÅ– ¥ç«²âø é¿õ_‘Že·Éþa7/÷<ˆ<»ûí…Âàšéäƒ!²€‰¦,äíÀ fR… +z~x2ÿ¨Õ>¾„Æiô<Õ>q=æa?ÿƒÏÁ‡¶‡ˆGaü|ÂŽvä?ˆÿþ¡Ô-–»E²s`¦¬b ï¾ûÿêÖÖFEÛø÷!‘ýí;Ã÷·¶¶”í+_c61iZ Ö8ý?~mÏf×y!ñ©d’åV}-³²Ê¯¬’ºßËÞ½üÄW¥‚åÁ;:¡O¶î(’þi•"@IUK¹ã?:>[@ >µ¨”Ô¢Šæ ®Ù€í[ÑTY­VëÕÖ|7`wÞxš^€A—®tŒqÿ@§K/µ„ëË5 ÒCOût¸qPÀwc òœ»5LØvüд‚6130³b],ûuûÝ^T0¸ßE¯ ÙÔ«z>F“Nñ•âÆðöÆíÍÛ…ÒðÎfñvq£°y;gþ}Äc"Sþ£0ð‘¿·»7¿+¶Z»ÍìŠû'àm¿ÿ]¥˜jÁtŒvgÁÐÑŽ9J…ÉúöeåÓ¤SËg„43CÓ™´”MRt†ÍJ\ŠAODšN̤¿Ótt=È¿(Ј7±d’N¦ÑŸA14\’C@Œë46ŨD*ŽÞ¸ƒétõ|TXl»8W ¾Hkàþm}S7•Ž£@ÿä93ÐÝÌ›Š*†éÈU¹b ÜHv•¹¡ìv];†ìù©þõ\“#Ë=ûžÝq{A–VÝü~¼(BÏÀÌw–iàV>2¾¨ºu×`ÇGH FŒ?¶£ì#€ä"LÍÑõ8× ?éÁó~Ü{xc‚ëÙ@jÚÑó±@…yOÈ? ZÅrÁÀ]’ÔÒÕÅ«Ww¶Tms(«…+Wî ···”÷ï.*[›‹ÊÌ¢,M TašœþŸ™Ì˜^f=K½He³i.y$Á._¤o 2«Ïgï>yT6,>É™§€B¹< ýËaG‹/”€äfÇl¤¦RÅÌÃ$`’‹jÐÍrIÑ”ZC­ž8áG‰¹Ã ôºØ@Ë¥…Iní½ u?lhZxkøÙ¸>€êû.Ú~Þ€á­Í©`B¼©ëÀÜôÉÜ7lTÑÞ_Üþã{DÝ÷]ã~Ð@èæñœnxH—¦òl¯K#32¼2•T‰“Sr^ÞÒÜÂÒž¥ q   @ïžj6wOÍHÑ E¦$K܇URj‰ƒûÀà>2¹]¬¾$U¥ ¦¡ëºÑ^°œ¦™üìd}{(:ð\š’2,ESt:Ãg &•Isf&E³iž¥ãqPj8sýèú pü,O§X^X`ûL”bA|½©TܤæLó­¹¾a÷y×mÏò³Ž{\¶Y55¬lÉ×’ €=Pµ-Þ0 ËT@õ›2þúÄß4‘xðâé²Ò“CìŸ<êÙ 1ZîÙ·Çý¸¿±ÞÝß &a€‰íÏt,RÆ/` ŸçØ‘#GgâËa§Éñ'€ö¿Ä<Ù(<Ús`|ï?ÿýÏ{Ïk5ßôÓŠªÉ‘çZ¬<Y‚ý …•]$i{¸½sewwG’‹;[;W®,..jÚð‹/¶®(»Ú»;›;ïoÝþbkû΀iJ ö}QmÀ̸o63ô8°áhr°‡Aú¯__Œj~\ºté]ò…ÿ[¶ãȤO¥3U•Çïïÿ” Q÷r`«”^(©@Ur³³ÇÃï…ŠD6|‘M«eYÖ4 Su)¦¦6*˜TµZ=b 0¦ârQ÷»¶áê®”YœÔé[+ÂòÊÊåP¢á†ŸÞºõÙÙq}0AÓöó ÏmNµˆF}œûžéu`¤L)H†6©?0;¬Ñ^èâÞ €]^ãq! ¥Á~ö!]âZ,íY¢’& ª—óúžÝ œÒ´ÝS ½›•¢d–œþÌû`Ðdµ €©‚! [ † ¦ÁB{úŸ3@ÑÔ·—@…Ç4Ť€XdáãÏ ¼”‚·RYèp"Ťҙl©ïæC+´ÉõôKð‰8-dP¼“@úÙ””¢cJ¦³’ÈÅ@x‚MÑÌ Q¸Bn‘ñq½í™aÞŸÍφ¢äMvL èŠ«è@øeà ¨Éž©‚°Ë†¬)fP ú‚ h`öT ž¡˜‚/ç•Qÿz®Û €Š{^}³;ê¿%7?r¬q¼¨w ìGÓiw€è˜çs|Ùı#/ý/½r4Fqæã.!!OÏÇtM¯ @æÏÁó~× l«9ßÀß°¤4ú!àùèö¦ ™8€\Fí¿½§îìì¼âõjëÊ{;;‹;Ã;›ïÌ· ¶ïܾ·µ5Tvv¶”+”¦ªxÀøÁ`-+ ²|VC4E½˜JK¾$­®fÖnÜà'kï\Šüß²ÜW¹™Þlm¦ÕMyüþþÿ‡%€:~|ä¿XVK/hUEQ4’èA­ªªT$$±P’eU­Õ0€l;“nÔ°l¥V×ZÐýIÀúÖÄÒ|ŽtÔÅ2-:} ÓþjšB+t>ÿ|c¿>1…š»Ÿ7àì¦1Lè¬`°!– 6ѺCcXžã]ÏC÷®úcF8LIìG!À>F"?@à§qg¹Z[Iâ+]Â×R¤Çiñp>i¥ÃÆ™çõl°2ЀڿaŒÈ Å$‡§—8¸(~¸èý *GØÕ";p馠Ýð±~¤ üŸãÓ>U’“„¤3J‰«Ð*ƒ¯¥$pz®Å7RÅ•tY0¤ã¬özaµÚî)š~ 3œN£!¡À}*ðJ )'•Rù™©«cþ½Ùns¿ÿãúö€& ðsšJ ï㳩$ÅßÏI&É¥8\`x¸~LÃc ÈfaÔáz\ìËfpu/Áe$o°(®¦~Ä?ÃeE)m¤bð;EQ‰$ÏÆIf s\Z3ŒÀô\²Ù:Ì;Sîh Zù¦‹µ2`Òz ó®© ( ä Ô)˜fUnÍ&Là ¦¬ oEÛwa‡Ý—{&¬À€Dýcþçcˆ‘+`æ»ö"æˆÆåÿ•c3G_y9B€†›~d6‰‚ŸŸšíP×ÝKLº“ó'šŸ˜QÌÄ좆3ßpÄBŒfs ø„nø” ²Pýïªww÷Þ“¤V£qegçÊÕ««ä¸‚ÇÎðöí­áÕE}´~¿¹³Y–¦jÒ°pÍñÙl&“¡^¤ÙŒ' âÊ f®xŽàƒc7s§r‡Tf9Í꜑$¿ÎææÄ)ϾOaª³/ä&C‡\jFlj¸2I}vÐu­ÙÀ‚GåªÒlô|0ü»~€µ0mFSzfü¤N¬7–×—A͸’fkŸßúl\ 2[¾´Ÿ7 ¦M®;ºo¶ÜÁŒ…9‚`ï¹óÓ ˆÒ'YI ^€ÑF¸GÐ |§×·} <«ñ2í0€,ô-r™t†e6ÊJšÅM@¬ÙõàV‚1€#:ÁKñšCLŠ”"J”«S×3à€eú¿_ß>Ë¥`®31†‰ã`RL†M Y°Y¬¸$“¢Y 0ÒôÑ8…{Ü<ßî¤qE2‰3IଘåÅ4Øû±xX?Ͱ åŽ)àÿ þh:À62~Ž×z¾’°Y¨<ˆxl{àñUÅ·U¹¦èÀ´PŒ²]3]YöXË ?*p¤¶ƒœÁÖ€¨è'@\hw`*„n¯ë„¡?i.fx¬ KË7×ÌÑã²0H…U§AaÛÎh|Ù#/KT€tϽò ÀË@¦ÇÊ~8 xz~„˜ŒÁ ½Ðœ?ÎO“ý˜\ÐÑ݆k8¸·ØEwn!rûÏfRãîÞŽr¹ºw¥Šà*¢ÀÎÖâ{Û›››C€Í (ûÄ PiZ F `䀀½–f¸$ͦYŽž .ÅŠ@€ÌÚÈð= àâ;û_ü.hi.¥±V{(eéfóàœCàøds/”&°y/IÒ]<ö¢˜ —Ôg·` kõj½Z‘Õrµ^³üOypÉNzÙ²ÏLètÔhbkI³¼Ï‡Ÿ GõF&â–¤óhÓÁ„ÂÒ*PŽÐ!IŸ04Žea6 À!˜ Y'˜"^7Ú ˆÿEyŠZ Ès)u4QÿÄ X©¤ˆì¿öêk¯I—*¬ÿY*0i›e0Øpüþ=áÄHþ=øìvljN¾P‘.½W‘«+È#”$tEöŸ@@Â@÷Ììö½mGý×·3¶M›NÖ±R®Å±< A*›äœ   ²):ÎâR`6ò,!G9`‡Á>™4zÁVÀØŸTÒa(,wDQt’C¡D'b‰P*aSV†£á¥cp†ì¸ ªB?Dé =9vôè+3q ©€»ïíln]Ù»{·zõª”åWùÆ•E@€«›Ã­÷w¶[­ÅÍÅ­í!±€lIÓ5í2ë×YŽ>B±|ÀüÅD2ö Êk7ÖøÁó}÷Ý]~T\K±úªL2€ÄÆÇ³ï3J{0>^ÐT’9Êôª‚Pìî‚üû@øR#³ô @´†R®¨•²\mXX&¼|dÀ×–8×ìº:Ýs…›7ׯ [Ö‘TËOÝúü–„õöMD§ÕòIÞNs'ƒ -KXù8´ÑÐ#«¼mÓ}Ü ¦¿Å’:@X7 SuÃ Ê à»i- äY9 ¢_Bæ¶:JïüÚ«ÿÛ«¯ýX’.2¬NŠ…JÇk€P&NöWîÞÛzøo¢%•”.J£+Œ·«°…˜†AñgªÕ"ܶm,à:€ēȾmwºJB6>%f`²‚À§i:‘Îp,Øö©4Ì7fÙ ¨r!-fz&6C'˜žÓö€|E“ üÒ¬”N1 û; ¤Ù$‹!€1 t*n2´ÉóŽéI:ÐàÀ·ÑwVz,3sôè‘#/‰Ñ„Êˈ6jr½b)ªîÕˆ×O‘kž%[Ь›5=助+0"²§xþˆ€U$¸pØëÖý^cÚ³ ó£ "&ÜX_  1îæ Ý@ÝN»­ÛXržŒ/{ôh¼|çß¿ø·Ÿ¿øâ_#xe&òŒ?ȼiá­<5?P¢q·zèN̬:m[¾ƒ©Å,Ýqµª_w£ýƒèjF—>›ìîílîn½¿½swïÊÕ€Íßjó_¼Šë‹‹Û¸¸½±yˆzmJ ö‰x´¤ Ëq¼À \†N$3I6# n,2$à{À…‹£¯]ŠãFÖ8l4MnmÂ×ÖÌæøœC@wd@Õ^ d·O §a]d;»»{cÖ4®Ï:®Y¯×”²Z’ËõyÀ§çbš.× œPzÉ6 Oët/ÂÍ¥›= °ž¤†öéÆçŸjŸž?¿o"ÖÂnóh #vLØ~û¢k ÂòG0zÁRÖÆ 2hÜ™˜†¨‡Y°P/ª¿{=Ç P\ §~ÏâY•Ïh|•ã§iÿë Âóã×ñEâ¤s\+VŠwÀ·u÷ðƒìƒ1Çý›†nN(âåç8éÇóêk¯ãË_ß7" TMq-äþŒ~ÆÖuK×;¸Àì¦åõ|OÁ¡é´È³.'}ú„7%JI òC‡Ö Ñ¥Ã&Ë“Há‚kZÄ>Ű ýd’46åùg’IÎÆëÆR‰¤‰ÏºtŒ¢’.ó™rà‘JZ +~ìÈ+p#T>òö¡Ñ ¾2CÞ´äª 6€¢èèöó@í˦Nñ~À ýc¼PEnض_s*¦w ¹6VÙü}™9š8þ@<™ž¤‘`”è©ùÑö²Ø›˜?¸øoà¶²wX×ÔVËDŸ!î¬a$‹e“>€ì|Ðж«»‹Õ½½»ì]‘² îÙ¬Ð:8êõF ð„­€È¦ê‰8€u~ÍËã…4Œ8£&RùÆêàùqQvñ3ì­Ø6_Q¨7ãÙcB\­œ‰J:\°/,ó[ÈcùƨFmAF¨” s¸*Xœ+ØÝÙà6Ò$¢ÿáy!Ùrê +H”µê|+Ê¿%‚ƒ )e‚šíZ¤Óæ{ƒåõ›×—`Ø’Úöðù0ûôü„‰ØÊ¶ÂšDáßÀàQ &@i‡ÂÚ‡ËX$Üò Ün€íNÇ'HŽû‹1Ú‡TÇ ¿.É lcÅ`ÇÁÌn×<–ǨzX€LãÂ?MÜö•$ªî×òÓ×_{í'RR:Ëeõ$s'žÒ]'É@R`—ƒø[09 ãÑ£ä GKgié'¯½öúO‚Â/¡+@NV’¥j±JSUܼ z§ófÇ2 óŒa{~€%‹zf–O§M:á¦ù4ïfÒ¢E'ã6ÃûnÒ«Þc¹4òÜ{$&€ßÇY0çMx¾¨1$1“Js+€ø'AÿσÆx‚‚Ÿ96)Àœ50©wLŠ#p3nÜF¿˜ëÝÄ • û$p( àÚÛ::ø: ÿʃ´[h¸ø¦ì(ȪíÈí޹‚‚~@¹b>”5*@³6BÍзp¹g Íw°¶¼´´„‚ C ÚÙÇÌΡƒ¾xÜÂGÆ—PL%^ŠÏýègý zãtzzüѶq À#0ðôü ó§íZÞÄüq@?aQL-FLµÞ4ëXaÄr´Z=4ÁéhˆO3€½ÝËïon«—k{W÷ö4›F½V‹j.©XÝs ,€Û_,‚ðƒðž²%M Ô~ÀO^ÿ[ ¸žEÐ$—bãìË©FqHâê¯o®ˆ?þ[dßçÏŸ¿pÃ(v·b»ª¦Ö+VûMU©êVû é6€Ù†_à¼ó‡ô æ å @%_P£þ–fg.!ÜÝÓ±‹ï²¯h4™žIW« fP.—ëZ+ôLÃÖNž %êäü|Íñ» ÓÑÎ V„•ååÁRº?/©>œ«~.Ä|ÂDô[†S“ŽzGÁ£ÜE¯í„®0X>\·C4æ{ ×j ÅóÚMŠõ å€h=ÐÃ( `^ &`y¾ÊóZšç‹2Íà*Z¸(X"þ¿¿}ýÇ?‘¤·ÀôN³•B³v"+Ô?èoÓUé®s&:ÁU€·¤Ÿüøõ¿ÅËá>©Ç$‘ÿË4<Ž*–"¬À 0; Æ‚i˜ z§Ý±l¬a6’#Hï01—æùd36˜Žá³´Ãƒ»B:+À´ÈˆY)]~,‘Œë´…EQp<Ÿå` qšbÀ:ˆÍP¨âÓ†Ã"+ˆv›„QÐÕ˜Â[ÎQ“Á8N]1ÓÉ™¥ BÉî|åØÑc”îËØ) ñ¶Ž Ùe\Ý7€ß+žå(>Qòèö󸂦ØJÅT” RÑl°•ÐN©¨RK•÷­Àn­‡•ܺƒpãC˜:¢üEb§…5;\³ zÇ—7J,•Läöóßyéå#OŒ?"€;¢è xz~À+æ uƒƒùã5°  Ô˜Þ\«°ÊÛvöj®«/„Vwoâør±£ñòfXWúýG_~ù(€Ñø·£ñv €ÉùÑÞŸ¶¸:ÂÀþüñ]@5²ýÈ×= FhÍ7kžZÕ}€?Ãô=«öžD€,ÈÿÉù»wwÞßÚÙYÜÞÛû€0€ºF2fŽOÊ.©hl£ðo½·5Ü" M ÔônÀÿüª ðˆ¬”¢_L¾H¿˜™‘° ×ÖV®Ý|þnÀ·ñ¨ol–còІ\_( z‚o–ñMzƒJÀ/xâ!P*Íbç°¦T®¢½PVærJ)€p|®47òììâ*IäÀ­ ºI}vßj4h0*•JUOžç„Z=¨Õ3'ƒVK«…¶%퇺' „åk+7ë­Ì¼´Œz«Îâ Øž³o"öÝ J/YÆ8x4‹»ñ`¾¬­|â€=`„ ›Ö°CŒôÄ„’¾IAHZ,MJê¸"8`YöºÀB:Ås ûU^c1æ§„«Œ"ã:¾œ$¯H ¤_0>Í åd*2ýþ£À2l™·­ÛFtXÚ²ô‹ HÂ}ù—ˆú'·f¨d•".#uËÀ<Ç¡½ ££ÒõD i—²h›‚³RZH¥a¶z¼/ˆ^ÊðÀ@ ˆ¬(d³é„Y`ãÁ§Rq¦ Ž îÃÐ?bÊ¡ ÄøÀ!€:àdʤ:EP+{ ¡›ðGR4ëƒéÉs)šŠaRÆ$}®+ë&´n®<4 ˆhºý@v€FÞ!‹ÀÙt;¦¬¢¡6滞We+Õ<#+Ðí¹}¿Ô`"¬,¯ÝÜß"Ðë£#§†„¸¯3èî»\üHLÞ©¤YùÎÍÊÌ˯›‰3éÑø[ãñ'Ú„óc¿ËU€Ñb¸ó·Ù éÁ.0a:ºkšn­Z3u[·áŸñ øœX«Í»›ïj{‹Ä €P­iu04µ‚e”°d@k Èÿâ»ð‚‚‹;uiZ žÌ€aX`I6É%“\–ΊƒÁ`íÆòóó¼}¾êÅR¯ÇߥSl%S‡ÿÓõ‰7ñÌCzuJ®¤äæ”2€<§b‹ÇKù9b8ÒÖÎ.ɬˆ¬ ‹l\F&õÙ-ÅmheÌVUš-'´1´V›ï‚ø«ýÀõ¤,€|×CàæòR ¥F«¾¨ùž¡{0"cmcÏ—^š혡áYÂÍõ‹[<Ú– í€î†‹YH:¦é÷@Æq÷^ò°ž‡›Ý> €Î¡—™lÔxe•®Ð ˆëvL…¼Ê%xG:ËJ”™|AI<މÁÖ±;.+; :Þ”¥³t9?܇&«Šð ¶PƒKU䟪o gÚ`O8 BíŽ$ÀÃde/éŒI›6írRVâÓvšw8+È€>ȧ2`ÿK¼ŠÙ ›œ¡¨˜ ª>i$i € “â$.;F%b“L¥˜¤ãZ):5Cè1^RL ”Ŧ–c(šƒ“E ®£e{¿_€/Ì)O€ÁZÉÄ1ËBǾ){ (:r<¯šßÑ1©Ð¾€««0vÇë˜JÝFذeE³Iè00·kÏ÷¼F£ïh5[³Ð³ØŠ­õACX]†+û[| ›ÙuÏþÎ8wÖ\Çí÷¹Ä±cÔöðÎææa¥r ,€X"™¿3’ ȉ`b~ì·“ùãLûóÃ~ч=Ú;lBy Ôš û¼öú–O.,ÞÝØ~ogkçrmïƒuµÚÐ0ŽN)ImG¹µ8ÜÚÞÁè€ÅVëD«¥JÓ5b?åxõu\–ccì‹É¿JÑ1Z¬¬¬,¯¬E à§ßÃÎáÁËj’/Ž¿Ë,—m‡uþøâø»Œ'ùÒñ"€:'#”œ¢àΧ㥹ˆ„Òöö®;ªÃèZ†¸êï×g¯7T·(c ÁjÓ©¹¾ç(–~`‘ÒKm˜ËkK¡WkzZ̶¾`Þ^´ÁDÜ!îö‰Õ‚G1««Ù„›.»d}’:@W1s ©#UÁ@ìIB@Ìîû]˜»˜$À”@~lB› À÷íषÁ¨¥*w ÉÑ4f„¬né¦îÛ†Ó‰N£ÓŸ}à*€LU‹TµÓiÿÑÑõˆ‰ À€^&Jé´› Í´m¥Ðt)Úæ-O ½¼V‰ `ÀÏsi7ô&:F¥)ÚBÀ2hPñ\žŽ3®Ë`AQ`𺀮K³Ž™¤xd:YÑàRflj–í]µßð€LÒ4§dR3ÇŽÉJHú€3[NÏë;>2Žg÷MàžÝì‡ø# 7²¯êt‹ñƒ•›k™Ì` êÑñ=ðKøâŠ•+Ž¿7€F$Ó£7•äèM<ó0˜+/”A„¡Ÿ€œ’›U ³@XŠ?€%mwAŽÀh"õÙAñOÔgWju¬ R¥«UÜëæ•…ÕZ»Ý^s}ÁVÖK+ƒ¥Ðõ\Z\cA_0­‘‰Xsû0ø}饩-„VÏr«Ë^[Õ€Þ㉫¶®c+,H¬OÚE—?ÆÿãþôT7ª ‚)Ëà‡Ò€“{W·wwöö®ÜÝÛÛE¨VçµfŠ)ŸËJ­‘ìƒ4”±,RAš¨Ñò]T\<}úo^dÙ©b€æ±4¿vL1ªþ=€Ÿ}®XP®8þ.à,JÞd’£7Ú‡ÀŠ`Ì”Yè)ðèï ³¥ürÄ]€]x¦îdy²>{C¯7µ,WŠ€‡Æ(ÇÀ-)ÑÛ•Ø.ÌÿUI œ5PÖ6Fk„¾ét °‰‰ˆ•…Qèq7=qÞ3ÑŽ`YºÄ=Îf’ÌFœS¦tÇ$€,Àç6<ÓhG'È —”.íï*’‰‰vË€*d#Ðà|wÚíÃpC˜•pÛ0û}\Ýó“ C§<^pDd>†A`€Ê|EWƒÓ|Pô1& ˜#Ð$pY8ƒ‹ÍÄcpƒFX|Ú¡‹¢L@=ꌕp)Ib:IQ4Ÿµ26§¨7‹‹5Âjó5€:ÀÜ_c½g8¡¦Êr©Œ ˜ ¹bYš¨‘÷>BñoNŸþ[€”IÆŽ¼tô壬4XN°¶:Ȉ‘ü‡Š£Ÿ.êétqü]Àš–éÑ›JrôæáL¢’ûQ¾4 ýƒ^ÊseN)‹eîGy€+mm!lÃ#´ŸUŸ]©ÕªJ¥¢ÊJ½f:Þ’ct§¥—pHÝÁÀ•4wàbÁ_LÔÕµjpâ…6šˆpM·ë“]”^š Ñ 4Ö\,#`Kw°>œ#RZÊñ°f,î <ÝoùÝ t1rÁï’¡·¾;0'½Ëqé*[,*zÇ¡µ\‹e"/Àzó':~¨ $@³Â Ð9ct: 60±LH¸‹*ÜãÜ$•4AÒq=OjOºiÇøÀ4ÆdE& Éâ-)š‰'i1ëÄgLP!‹ëéEÅc *ÁÄgl€€4—59*i%7 Ó ×ÊÍH'Ié +Ë™4 üž˜‰±šó¶îŒ={È Ü&ƒÌÀ•õƒñíáʼörÐ2@üaü»ÈÓL\!„=Ü,¤æÿgîݚ丮sA?Ÿ3”Iö¥î·î»ë~ɬ¬¬ÎDÉG–1 ¨Êû­ª"f, ƒ p:ÝèFŠÐq8æÉ"xdGÌ£h[ NÌãˆísžGøó};«»«€¾:´ @£»wUfVå^ßþÖÚk} +hÇku?«Gº&éjO×{`/² ÃZЇ¥Òeå^”÷e¥Ùäò«/¿úÊ+¯üþ7¾ñò«Ë,˜òü÷_’"xQƒxýûÒ“Ã'ÒIt íÙüC4™Òw„ùÁWenàѸŶ®m¦g¨žÜQ·\×À…Ã'ð9¿-æOc]µÛU¸Ù¯¨DÁf W@£?ÐØdŸÑJ­*ƒ,Ô|ÏŸ¯ûÛ¯Ã(­?\_—JXŒ(åPø~Yijo×ñ{¿þµeõŽÿá‹5ûÿ¹_žÑ¼z >@}C\¥€*¿Û¬o666âL@î<ýÓçàÿüË?óýÙ½£þìM–íf³!wU«×ó5j,\v]½×—^Òåž;º¤ô5ß§4‘k›æèÊ£-%°@¸A˜¹ú+å«óÉ£•”>|ÿƒøÇG6Ûˆ`Ù6î(\TæsǪ¯žÐ€t£X#$ E«RÖ©þŒÀwÍ®€´=#¨z+ *PŸË ’~Üέç•T½™½2²°Tƒ»çŒlúò¶?¡Ñ®'¥gN2r8NFxi%<7 »/æ#É+ÁÆa²R1¿^`…B£ÌzÁ]r£X¡t}-ŸJ¼š0)û™L-;`…ü~' Ÿ¤‘O:@‹|ÃK‰|i=oåíÄ+i'ô¶rò}iÇ3Ç>8f–Gf0»¿Ùï¯è¾ëS÷Õ÷ߤíG ÕÂßY€À˜‚¢Z/Ðo›9]-ê“ `Âtmßûð#!þöðá<ÊÛÖ‚>¨ïóþMÃ\rué•—_áciöŸãÚàò“'xÿO$ IOŸâÇÇ냡çü0 ˲äÊŽìp”œ[ÔqEí°ÖS´í­“Úhx¶:ãS€Õ¯m6Å;Šª®Í\€È6u]SÚm°~e“`uµ,-Ô¿CYðÚÆFWG¨êåv…€µÙ¸´Ù.€7•}þ/ÿôèóþÍ?ÿˬ?»ñƒ´Žú³«–Öì6[2h€ÚUµžÐXP]ßèYäiKRtMÔ€ N4L¶p²-Y–^asñhšO](=ø¤ôÑûÅmD»·}îÕx¢%|àrÓ‡)Š˜Ô% ˜Äl›Ð°Ìdâ:cω›É Å ¬´ÑHÆŠ@)a·Q$ÝLõóÄòòÿûyÛYW¬Ñˆ ÁÌNem«£å?!Ù’n6’±"PJ¸þÜHÀqxÐT­;rF@€†9šþ"ÚõÆÁ+{דL%m' _¶<ðìTÊËøÃ±H¥f÷7Î…ß|rÿãñ@T\O0ë ìË}‡ ¹4w¬ã9½8ÒK2l¥7™`Ð+•2?_(x±Ÿ¼¸¿0QÆ\6-*œÒ¹ï/>*ˆ©Ö`g‹;„@7k"J½±³ÀÖÖb=Êú4;5Y’º-­'õ{ª èÅЬ•Ë¯½öZEîµ{5@¥]¯6z5iÑ ¨Àó;$ YÌP(¬Á €¿¾^ð×™4œÃBoäs£WgÝ›Œ‹EI*dR þ« õ ,­¬¸îÊʪCLض?™‚ÅÃß±Â\üù»ñçqIÚÀ™—ò ¿”-HFÀuѦ¡œz}¼¿> ënyaÜç¸ÅqªñŠ@Úñ¸ ¸ÖÓÃà7º9,Û*¾ÔË£¼_zïþ‚ìÂýÅzØg÷דŸJO¾€µ“÷?…öÿø±àR¾çÌ1Náz¾ ßfË@Üó`{ÇR ‡J6 ‰„òç]€5@»ÛiƒÞøõf·§IÛšªÌra:åÍ×6˶Ðmk5bB]Ö·T­--ÔWuÛOÿjíÁ+-øåK@€rMnü^­Û¬Ê¸ÞÍÆf…©À³6î…yaOX€¥#Û›ÓPà¸ÖmË2­¿Õ ºX_ŒcF‘)2ÈtüzÚ€=uà†¾o\óQ.ëÙÎ| (Ne{i]η‰_ï0…3€#É Õ±ü$ðaE¤ Xî¬  · 3˜vo_ÀΡiº?ÙôÒGÃ+øñŠ;4/ÿkµ1âö½åçRiXþR:½¼’N%2Ü=ç^ xÄÈ_ÀÿCþŸâ°Þül€)³É䀫€òë%0Ì3ƒa´ØÅ<¡q> Ö/˜ŒÇ…Òz 0  p‚R© eS«¥5ÉKg<‰b@ëk™ ®)±´Ìd:µ¼¼ìÚÉÕÕ/aÀâü’4øRŽç—²¥¼´/\ßèw§Ë3u™›í»QÀ™„¾¤ØÇâ/^éÃ÷$`qa©4{–ûQÀÚ}Ñ$Èr±þƒ`¹üøð·ýÇÏž>í?áOøù ð€sççâüu,ø˜LΆ·3ìxL)eÕê,åæ÷×ÿê§š¬Èj]€¢öE& ªÈ{‡RV£ÙVt]U:Zc;—zõ?¾¼üòv_– êß!”\@®6»µß«×åš\«n²/ÜÆfK²¨®O,‰iV·ÔHç4Äx¯—”U @§-+­n_íÚ†ï„ÖpWèLƯw\&_kUÐÖ€I/ b®úLµ—fªô|‘ÙëE]2WÑ1¾C‹0ß¾;™‚ÿÓ ÀD±þÛy#ñ ßðMc»š#Ç©Ã]§c`ƒ áŒF#øÒÌdÿ§ðq •ñ¬Ë,3?o8BèÓºŒ™æ áè ‡6®Ë5†w’ ŒÛ¶éÂêíòæwK%sèe ²fn3 z"CgSʦ¸)˜h2ö kë" Ë?ˆ@©$­¥——˜”Ïe#¶ Y+drYfý$â‘Ì®¼:òrÉUŠná¢QøÙù 9ŒÃþ× ^C lƒã{/\ßâø‹×ö8½ f?²[à¾ãé‘Ô ÔY¡¸[*}rA¹æþÚ¶C NÅä}LÑ"w\éðÙÓC0,ÿ_`ÕÿâñáSüüXú-ã`çÏÏ“ùçD¢ŽÅ‡_Øv©.=à¬*Œ)ZðbŸöz]Y©Ã†ô–Òë‹r` Àk‚åVSÖ5@{G˜Z)ñŠÔ“ J’šµßåñ¢á~]ÇimnÔ6[åÍ*®R®×¯YÁÿZ¹ÕÚlmTZ³m"Ûd>û-cÑå—ᑆ‚}<ާЂ›Ü©Ëª¦t©æO(Õÿ!$äK)ÚŒÇpÐUçŠoK/©º²ê¸'í¥K>\h#"^Ï…¹€¬ëþÔÔH IDAT(ôšè[〵ež?aVA8Ê`Uˆ k›™_£ÓÓ±ZÎp䙯,:.–ö˘2x_æÓ†K0ÌæÒé•wàWVRêÆ{…SÅtŒáÈfb`IJ Ó‚˜æÈ¡èíÐЖ¸Ð‘µ¹¸làið8\‘¿¡ØÈAT‹:v `1Ó4š¤œ€SÑóùuæüdV“¯¤’Ò$[k=—˯™ýO%“+ÉT*a'Œ\Ê¡îÿbîù Þñù¥A–òÍYi}=gÆ€_ß»'×w7¾¾…ñS®ÿœqz.õ'ä‚°®¢&uôbD”Çõ•Ü^Ö ™ñaáv…¾á>|Ž¢óÃm<“HûŸÀø?î?~rxøL‚ßJÒEós6„¡Â÷¤8ŠýeÂh0Œ½é”ËE%§/f Ðí©=Àv[ @×tÊP  ÝnÕ«µzGïÉÝ­ÎÑj›ú uÁ à»×¿rô¾|jðk:N«²+k•k\'3«¼Þf­ßnV[R$ Ù('iEWfRECo÷`æxϲ4µ«É¬ ‚ $þ˜],Égr®3™˜)4Æj4‰T@³¥e¤—ôÞb (°çÛK—̵QÄë óܱºÇð¢ñ$EBÃI±ù€I™B†Eæ ð¶ë˜W†{X´™ùEÁ.ÎÖú\6†îè²3´Møñ9áûgð5‰u6¹’!ctÌQ‹gÉ™ Úá B€@0©:‡µ‡{”€¸ Áh¸ùÀÙ,:»bÙâ¢ãm(JÑ[GÕ•¶ÅÌeæ2ÃR¸î¯Kkæs190E5±º”J±À:!Ÿ]+’9Ðî‚¡€Œå\!“òN¶éN߯;91kYÛ JP#+Εõì½Ý½“ë»_ßüøi×î¸i=g*ÞÜ€žqáT#»”ð£Òß>(ýìÃ9 ØøÇG.3>|8MWºÿq@}‹”ëý³C>?~Jpø”þã";à¼ùy4¹-d,`0™.Ä¢Ñ |€®cD]{|]€µç@¤lQHn§ÝëmIë´~”Ü¿%ú~ÕêíA¿ÛÝ‚—0èo©Ý>?ÜEƒbôþµ¯ü8}àë9N«ŠëjµkM@õª—ZMFá0í&ζá~‰èù‰pð¬󸆕ŸÅÑFWcç°ÐóâÞ“q{9˜—ÞFc+t+>».½h¿z®½ôB‘Ùë}ð7f§Z¾P'™ÉÔ'¥ɘ*´Ó×MFæ°J9ÖpÜoS…+á˜Ü`¬Þ­Ñ¬Ñ#ç²1¢“ïæÒ©L^‹mVت'âN¢˜Tö³<“ž6–¹¡ÃõÏ2 dÁ¬@Æ¥Q,°­×66¿û‡%Д!õ„.³'Åq"Šã&­¸š‰E³kkììAmO/Ÿ-%Ùd*Hd³ì ±VÌ®­Ò™\>Ì$W3©4./•Ë®¬sùÜ|¢Vt”¨%Ø9{o‹&‹³óŠv ¥”H¦0<‘s°wà»{³ëÛ¯o~ü´ë?œù7°Dñþœ1‹ÁM×'½Y÷ ôɼ?'g|°,ψÙ6 ,ÿÒÓgÏž‰°ÿá!〇ýÃçÏðí“ç3/àÂùÉ„¸(ðâ|€?CFð½¦S/$ûUa59f~zô4VßÓzš&­o‹ñJ§‹E¯Q¯²¸3ììl÷•vû§³‡´hPÿþZÜ h¶.Ug ËÚµÚ¥2Ó›u‰ÁT*­ãÍ`òža:Á»‘Þ.Æg=œCMæeKnueM údcLúÌÜ0 & a QèŲªr}.*·òOÚKÏ·a^ÏM^'b"Pœ{>Œ ÀË„#ML6¸üJX×qF¼J ltd‚Œ°Ç“A;0Ðt–'^à ³Ù4wé$;ëeÒ€ƒÈ‚LŒ?4 ö@5á/ÀÒ-æ0YØf%"Þ“g1{á|{ ›åï— ç )çcdÒGŽSQÖ…ëBDÑ’FXŒpÍàÿàþ¬ÕK¬fã;W,沉e¶ýÉf1–…{ÏÂÚ“‰´ «Ë6«íìé©Ú¢ †@óÄùw¶õ­þV±X”,IôJ Ù›¥Â츳ëÛß·NÒ-1¾wêõŸŒŸþþ¸+Lïω||F¼>iyÞþ|^ö(ãÃü5^V*½ÿóȧ’Ÿ„À³§OEÿD:ä·€‰_>–¤/1? Úü À”öAL¶¶So2få ç‘§ Ûkÿ«ø¯$¼€Ÿ*Ý®¬ªš>Øêã;Y“Ô† ¨4A}ƒí®0ü¿š=¤Eƒz^à›ð­ïܾõÖµk×oÞxóú?|ã-YnµÞúÑŸýïßyýb=UaèAÆrG„"þ?ÓWÔøWü ʪÀÍZy³Q¾TÃUÖ›ÊïuÔV·Ö._ª^jTÛõª ™²"5=šÙÂ÷Ÿ²3×cU_<îÅãªÖé6åfƒ ºýnoÌÌS0@öëž²V‡¬Ä<N|çHâ¤QÌÕ«oŒé´Yð™gí¥ý‡smD:8=—uÜN(@37™ÅAÜŽ‚2€ŸCß m*[0{ÍYpÒC“å‹àIQ8ø#{H0dê\nÝѰF~.'6±Äf2éDj)‘É0¼nð\ì‡a8ΰиÿ:ŸüÀOÆ`†…gšÎÐmc£\Æ$·ññtgŠQ\VÜÆu L ™0P‚/å‹EDŽ  (q㯾ŸL§ÒLÄ{¥³ùB†Z¡+‰T2±ìær©¤}Z±µ±AEäï3W²-|Õ·ui(&³,¨€ëoÝÅë÷ÞÝóööÄõý$¼Ë닎 .ðœS®ÿd\Óœ:îùc/~S\åÀ|é%\_éÃè±>¨÷£ëÖIƇ:~éÁÏ>t٬˖…ýŸ=}ÂØßò~9ßÐx"]8?A0L|&¡áLµ‰¶=ðñÇ›u¸e·©±h9}HÿµhúÓŸöµ^_Í߆°ÕHƒho³Öœ-úÂðÿzö jQè[ßúƒo¾~óÖÍ·nÜxëæ·®ýðê ªwnüèÏ~ø‹TõÈìE|@à!~àʪ§§ZoW¸ºr»Öm©€ÚìV:Kr‹@2æÃ؆qfçXC!pÑ‹ãZWî0'°E t¬ù*xЦœ-¦Ä )äq, áÏ÷ŠÆQèRÀ9n/øÒ\»Yðã‡ux”%ß±ž`…ÃÒ¢SÐÔÃCÙ{¡Ã ~ÎÑÅîï˜óÛÃÍõ¶éq·À‚çhŽè°Ûv.)¢ÿ™mᤒfãÍLàûûXᇖÁäοm2·m:ñ|<ÞÈ÷‡ÖP€r9[¢BµkZ ï¨Õñ££’F žë1úç±§YimMŠ{…%2B@*ÒJ‹éĪðõ L*åó™|1›³–WWœEÁl7Ÿv¼îΗk,þ[ò"|\Þ–Äót‡ÚB;¥‚´GÂ3-¸þ± ÿppÀëÜåõE,¹Äº0zäÏ$`…ŒÑDèo'àg6i?!àiÿÙ,ð˜uOgÀ¨à“/žHçÏO6wpèÿÁ[›z0 KÆì, fs;êÌû!Å¥NÛ\}Âñ€‘ÜGÙÙÚÚîÚjgnÕ†/Ò‡ð”ƒzNð›ßüÖwnݺ‰Çí›7o\»þ–ÜnTáyß¼ñÆ¿}±& ÃiAd9CÁÑ×£0ÿ<@U´3 UÆÕu*ݦªvÔ0e?£MÁXÄ!œª±k™ÇýåÉ3=Sh(gãZÒî6Ù7°Ñl·»½nã~5°L¹Å €_8tƒ9Yù¤Pè«Qàc©í¥qc'mD WhÇÛOgG>àĵ66ÀŸLÃhN£ÐÙ Äw ‘ êmØ;7¦FX #7¾XíÜbÃ8ú†ÆðʈÍÀ àJ2™ZN$2¡cFîxìŠl9'Ö €8˜ìì1ï²-êƒÅ_0‡-ƒ(ëûXÿ×¼T6W¤¡-WVLxË =N†q30#Ë9l !äì ]æàüƒ8¿PÚÙÑ(Ï&\ÿý}úÿ»ÁÞ³GsßÝß·í=Sz{ç8þÞ ×‰ñ™·ñâûs§>…dÌ( )áú3Þ'eq}|ò3jK×y}ó^ððaé“?úØl +?xÿ!ì ¿Ÿ9€p€gÏÃxrøø±tîüd¶ŸßgO¿×Gî÷äL Q³‰ŠrS_tœà³ãD 9 üן>ÿø¯'«þjHJoÞ Nû|ó›@€Ç­Û¤7;­zµR®4Ú7¯¿q]ô8—(Gœ/þâ‡#ˆ@^í͘ÀÙ @\eUº=Ui1?|€aö޽1Ãã!8®iEÙ†‚u4>ë¯Îq­«¶•Nƒ›]EŒÛv0 Ä. ³€áš‡˜6Ò‰,Ä\/ )¤1 ”ÐteÕÄíWŽÚˆdÚ8>Űಠ#ŠjÞÐd²§ã1ŒN©‘ˆ½·°L¸+PÈÎ7 ˜>0©iÎüõþ>ë|Mx„öe€„ëŒLàÏcÓ-ARî¦^M¬d"ù\{ÌœyËë9Þ°Çmº”ì’Œ;åýùÌÊƱù& û˜÷½¤ë°ñßÿÁ}[ZâõÍg|x"@ðÐÇ¡¤gœþ'Oígàñ!<ÿ©ÔúäðÉÜ øB:w~r)°µ^Wînm[;î6.w\Åg{)ÊŒ„˜Ì˜N¥'€½6gÕ¥˜<÷ é¿à5 j‘¾Mð쿼ɒ‚róæõk×/fj~fð2é^޽~«êø3còŒœ "¥ ÕRp¥t:­uÂ7ËÕ6.Xl°¹—INúËcEÆ A<Îu9:×’ýf£#·˜¢37O0t^GáØž—…8 EÑØ£`7½/¾Àâ6"™¸v Çÿ·™e†éÐ7ã%ŽK°(rÀ‘xXÁLV©X³@å]†_ Ý¡‹€an L°mš½á^±±lrÙ„HÿÁúŸYá~@2™É¸Œ¤ùX\)-?ï0¹Ã4²X=C–£ãµsëz+¼t8>@Fô­gäH”Ò:GLSqÙ. ˜ aÃRi­°^Ìä Â Ö V6SÌL ¹BÏ(øp ÖÖ¼Ä(™Z5Vùbf^ŠŸµ†ØšSˆ¶2À@(>!±!f.ž¿X¸s'ýîÁΈ?(þ;ðÿßÅÚ°·gîíÞÝ¿3"0¹9hqxà݃¹ëß‘™{Ç¢±/¼?‘ ãçDÀíÀŸã}:5_?úÙ'xEC,w!ãÃõJ~ð Œd_b”ïé“> ÿáSI‚ñ>‹ÃRè??øâ é¼ùé9†ïô·ú]E÷ÌÐÅ]aÞ4uý å«D€™ (-FÒs߯ÅDàùÇsCüýšÔîÎÔI_€ïÆ à›ß¼ û‡  j *µ¦¬tÞ¼V›õ¼ 0[ö³JÜž þ…¦.<0œÃ@P6YÊú¿õ¶dš˜3Ñ»ªöø¹þòtx]1nŠñ£þó­¯È•’áhÇ㎌Ã13ö]ðóÈ—…Pâ@PçG×3cp ±sd^1a¼n7*n#¢P£žµ¿#Ÿ¹a"°cÀŠ}sº¦D‘ËÅì OÅpß ýiÈ0¨ºáÀT¡-rM1Gàì±$Ùox †F¦ˆÍ+^–.È?i@* (Hм¼„q¼0pLv ¡`0—„Lƒ£3µ}V•Á%°/  R¡ °Ö^䥺DzԱt-ÅxB| ¨m€÷Rr@é\¾0 äKkëpRÜ„GkRa=ïçÙ3Ð+æWŒT(Lå³ 7–mg:PàM<‚Sga! t|þ=qþA1÷.Œ»¸×÷`÷@üÛ;Øw÷ÞÝ¿·kî“ØËá<{vý{¸~œËôÍwŽeãŸ{bèKQ˜1û­»ö ïÓKKïðá}Ì#éq}s@ÓRégïäÀ€ðÛLJàýg} `Q ¾î`ýI\€gý§_<–NŸ–à^l“5 ìpèb…ÁOWØóÑq&,À}€-e¤ÁiqÀçéµçâÏ Ö¥–z üQÜÀnÜ#½¥)Mô[MYí4;7®½~qo@Úvž /hCDN?¶eíÈþå/­E¨¶%ô †Ûˆåí´þòBãö\ÿù¤Öë0ÐVº­žÃJ + ˜p0ñH’#¦ôÄ<ùWÒ¯>U˜+LÇ¢tÍ×¾PÌ‘¦ëêgÒr/>¿ˆ)Å;Ïž5 E±&:èøÄ¥²‹yl ðŠD…› Ku|oÄ»n˜lá1U>eÉÎñ[êZ— ^€åäEp&ɵe‰É@K‰ÌØ6Vk\mXflqÿÐ5F<ào‹êÀÉ©\z Rc+zF €YÔ-8jLÁ¥Ò™æDáÄck³iì~FE F^ôòá”2+«éåÕ4–x·à‰>"ëpBØQj­˜\M++†½â¤ò9Ÿ-wLp_Ÿ>ÜqðyL¸3ïQBÑÿÝqþA1wpö^ZƒË í¾cš{xÀèñooßÜÝ5­ÝÝF,ÿÁOð-ÈiÝ¥Õ‡B|˜pÜ8æ¹÷‹ó­ÃéØÇv£yÞWúù'¥?|ÿ=À˼¾…ŒÐ{ðð£÷ß»ïr½úÅSnø÷ŸÒúÀ¯ïðëÓgq~PŸ)BR<ÿØàd~ ¨æ ±>ÃÞÚö¹U0ùc`H{\0u4`_ v˜Á§#ÀÚ ?–Î;b€ àõ›·nݼõöÐuok=•Rúí–Ú{ëoÇ àÎé sû¼zÄýÕ8ô¯Ä[€ºLÛ禥ZàèïÀªp°–ŠêӵƳþòs .V<~Ü^ŒkTPaË€®&L߯làv€v꫽ÂVo^ÂôBKºŽ/A.#@Äúpô…âû€@—Šñù™ŒCEq?®°‡XÏ„ìÇúÿpâãvF/ö|ì`h#¸'&cUà©¡3 Ù98ˆFÔü7F°¦ô‘“r™UÁ—2̳€ýÆÀš@ôöÃEÀ•`u³`mÇò ƒ:'SÒy¢„í•/‘0aŸWÜZí¸5óè-PN«¿ÈF &3Xš?%‡öGz5Å>ßË«);‘NŽ}üzÍËãËZ±PXuV— +³ì&3ŸZXS¥m~4xÏì–À·k‹JžVìáüûÅ»wþ’ö®üdö~÷ÀÜ}—NpàîÞý»ï˜»ïÜ øÃÀ€Ý¼ÞÁ!ܽpŸ¶„o½`ïô÷ÇñÐÆ§ VÆDíÉ<ï£ÚÃïðñ{¶ôû¼¾ùŒH{ÀÁÇãÄæü’ôŸPäÿÀ¶él‘¼Û;ÂmœËøpÝ8@àÆÂ?Oû3˜ü3I²ùŲ¶©ödGÐÆ%Î?ª7ºÊéû‡q!vgG¡<°ômþ!hìsó'¤b˜X$ ÿeœ€óŒÿLø£ãÀwnݾuÝz››õYin4›íFõæÕïÌbç15Çh¿,Øÿу€ÂĤ «°Ê*F<åË@sÊu‰ÉôîØãöÝÅþêL±²2íÊö9n.Œ+½n¯ÛnÉÍn¿ï™:0íEêm]7ƒYÖŒì ÆbÍp8léÃe+“™_z)>¿å KŠÌ£*¸ÐB Î÷Xúb{"ÞŸN‡EpÛ]VÅF˜!|sÃñFÃSì0) ¶û_Ê 8ïÁÖŽÞy1€?Œ poj2«ŠÛ ̱¶ùZù.fJN¦J¡" @€Sáh" ˆƒ¿ Ô$ÜP,hL£µœñ‹˜KúY\Ñ:ͶÜn¶Ô-Xþ4-¼¹U”ÕõH?–…P¼hêÒ+¡/¢VjÄdÈW0%T¸ëˆß?k¼‚É<ï+= FðûïÌ´@¾v.ã#(=|PúøÃ~ÆMÀ§Òá“§ ýméÛ[J§' =k, ¶úœŸô úŒÐ`Ö¡ R‡Ë ï°ê‡%†oY¡ªx½À E  Ñéó'ð&|L¥ííÞa€õ—@ƒ£©q:ˆó¾%à­ÛQð úZµ%·ë›õÊ¥òÍ ø£s€û‰9Y=f „' Çù´/@+˜ž °ã3)žw*ÅíõÔNSn´š½-8¢b“‹;eô) „Où¨-{üzÒËp™E…“^iбÜg+0SúÆìüž l ÝÄ<#­¥•G$¸NtD#VŸÐ釂ډì¸ÐrI•EaºËØJ~ÚÜTp¯x#x…î0—jÀÂôWàd2ÜXaÀ<& XiÌ”ÓkKŽ!ThÜé„{oì:¹±S€òé.RìBqzÂLô ÕŒc `½HéOf'VÖøå•ÕTÒ4K¹L. ŠÅ’h"’J®.­¬$–V¹˜ X¸|êá²6ðáœÀ'¹,äò½1óñ¡°qK˜øÔßg÷ÎÚû]Øö]ó=üsO¸÷îÜÛçžéí¾câ退Â;ûw÷ùì½»÷îâà`Ï œXLZx$ÌX ß?:¸Ö ÿíÇ¿÷A_ʉÔè(ãC턱ä'ŸÜgÌïé³Ç‡Ožm±æOÒûížd¦?Зžk IDATUÌÏøÕóá€Ó³9‰gŒBºö戅[¼K üÝžjõÓ€‚Óç3ÕÙhRÚÞê휅gšÿÚó±.ÕÏ`"àõ[1ü‰{CWÚ@­ñZ£¾Y!¸8fß™AÿÙú, H§/@ d¿œ P_€—)®ª—ÍñÙAŒŸäêÖšNSË˜ŠŽ.ìÕŠµ@4†e!Vñ~ŸõãX«ÇLç‰4/ò#A0Å"'Qœ_ü11÷™âNA«@¬ûLEë¿Ï\îø€ÖÁÏókLÂb8ðD îûÆ;ã!·õÙ½Ó10¶0²Í8Î(Ï2@ ‚ж"0•^ ˆLPý1ÉfE¢c‹*PΑe»glF6õgíò†°ÿÊAR¤ªrS‘ED“i0=€5:ÿÅ|qÝ _]]^½’L®ÂΓ‰¬•6¥B±P\óJ¬f"ˆÁÊê(•LW I‡ z‘Î2 ž5W}€Lmâ…ü?ð"š8–ýÉî¿<`àž¹{÷VxTߤ±€gá˾·ëíïò¹»ðôïÞýËP€{&<†»& ã`÷Î^œ;„ÿ‚ÏÜ;yv4‰š¢DÛ£#À¬¸ ŽqÌû¦¥ìÏ©œ~pÿCéeýV {‘ñáÿõkV(÷ïÿÝÇïIÒÓ>—xnJ^(I½ŽdcÉh æç`ÐÛÚÒÅv $±ß¯MwÞBMë)@Ï`dkAWíyÛ£-óè¶gÌ1‡íi(é[]Ài°vŠñvòuq@ªÉ§æüÑú.À·oÞ¼uûæuâB-ºó­Jm³ù]€ï’œ9áÝw”<“ã„€£”@þ eM“s‚ ´å/”kóPkm4¥0bF¹wþ6ÏYãÉn·Óh5ÍfOîû$W!œäñ$Ûm8ÈRügB/ú¾ß˜„TfñîÑ•t6 ¢B –”œ‹LÀ6Ï>0H‹¦ä yà™i‹ aª–Ãô™€g€|²JÆŒp³ÁT0´Ùÿ%â{3`ü˜ì#òg±¯gŽrYÑ(÷̈a++édÆŸÂþdl>MºíQ>0àŽ,Ç2¼‘}²M:€Í ¬|3(/n“žl£šAЌӦŸe|ì¬3ý¯T($„…gØd%•Hæ3£D"_\+}V ¦A’+«i/¹j¬¬Œ,f3 6ˆ&¦9Á›€ùFŒ‹¸N½˜I0æ6Þ!`oïó/ÿÒÃâ÷àÞ½ƒàîž9£ú€€ŸÜx&À®)ž~ïÞÞ†§àÞ]¼ìÀ|¿­ÎÞ¨":y0CQäÜøÔÝÙ‘Œ LŽxŸ5–JáÞÿðáŽôŠ®_ÓÇÓð³Gk©¸ÖÄ ïàƒÒÇ÷?É¥á0$œ_Ö$ßÛôeÌÏ®Nµ@Iâü x`“nWëmÛý­¨×Oóü®ÜoQ3˜µ’N0ôΘ?7‰]*›oÓþÅùÊàçWüÒÜ×38TožÍX xûÖ­ë7£à ²ãÔÕ«—7*å[7Þø `–ù«Êq2Ð,'H€YR œ¡EF¾4ë/€ï\ö¹íu^¢ëiO—á…4ÛøÓý @„#Y"VùŽ_JP0ž%"¾”#ˆ˜[„Ã’¤‹U<éÒ7²ºÕcš½)ŒÜ£ãÁ`DÉ Î{ wd“W^¬*‹åÃ$ú'‰0”2˜6‰„a"ÂaLSó‚¡mddN¤\ß Çp¨Ý%³Œš› ‰P"…°±±¹Y1«vå”qߊªÁfµbÙu¿Q£XtÖ¤¢êÏ넵ì&Vé$mö+óòùBa½”ñ_YYÍfáоšLZÙd’}Wø^M+ D©ŠGµÉ¤ BåxÓ€©>»ïÒïßxw±lß»7¾ ëßÛTߣü`qspT Ëþ;wûû »UÁv÷íÝwáý…•fÝõÛa«1ŽXδ;&„ Þׯ½.M}©hõ(ÿ‹0_däç3i¹ªØÿ/•*~ð±å<9|ÆÀÿ3‰óKê)ÒÈ ´®äú-v xz(‰ù)FÔë†;ÆŽ5ÚqwFz?BKUÝÁ*†ªb·ÿÔùÃÏnh»pHp-„]G€µ…åÿKÄ¥V­} ˆ«_ÿÃÛ·Þ¾uûÆÍ?qw¹Ýµÿç³üÇ_–«·®ÿèKTþEŽ€šSfYJ.ø‘Èpòj‡±ŽŽpN*ð1´k Û€õZ¹%]†ç}™A®³S=YuÖ¸¦%›Lhw;ý¤ËTç¦L¸ðC3 <éV NÞoÀú$Hˆ½L¶Ÿ,sIÛ Jŵ¼ë'VÓéDÑK’©¥ä²Î¦¨ÃEé³lT=wˆË‰Ì©7µ¢I;Œ*ðnÍ}s·w°‹åÚ<Øßß…ì¾K>p÷à'æ>©¾'F½ïoGÝ¡æ ý¯3ïí’3Ž–ÿ½½Å÷W­øQµåea°¶Â1÷=¼Ï©¾U I±¦êµÐÔE-¿!Û——<€ ð·¿÷>n«' 󧀄ù%iŠÇГ¥Ë;½$ ˜ë’LcÇ@I½ÑÎpg´¥ivk$¼4Ç»hþеm2žz YÀ‹ò g€\­¿Gzß¾uëöÛ̆ ð–*·›õ³_ü_¿¨mvnþ À‰?ç0€¿Ð4e–„%?;s¸úç9'w:,Œóƒó_‚Ô«òTê›õ&UÞöðìbó‹A:SjµZÝŽÖguÐ6 B´ÁæÞŸmOüI¿ß—r9<âÒìT')¬fÃñ™ ¤ëª®å®qU»dÈ™¯Ç3l+Š÷©þ`[–Ø’8.†aÀ\1Ìâ8Ö૸í®#ÐÁc1I¯Ûê¶ÝfKT5*ü®K'J3ZXu½Jµ2¬—ëQÍ÷زVq­Ú¬ªz<Î ÀYãǯ¯×«¾ÓŠfGÝ9H¯,¯¤’XôWÅN¥Åb6Ö ¥dT̬:ËVºTJ»ÙäJÂÆsª”Äa|´ü(ät®F–yn;œvÆÑ¸‰Ï½Å¼··Ý›îSÌp9Ç"~oN=ؼÇ·Zî>Ã~ïxïzø.þ»ÿåÞÞ½Ý}ÂbàcÀÆîóï¯^‡z‰3™øðD"q}R¢òO‹·ô-©óãÀ¬ºf= Âz0í(Ò7š­v»Yš>,=|øså“û€SˆÕÿé3jp~I˜Õ=¸þ]}ÐW¶#_âü”âùF?²6gú¦o…Z_ßÙr»G0ÇsçCGc—ì0ídRð¸¤b.óSûÌ[ÿ©Õ@¥Ó@m•_dßÀºM¸yëÍÛÑ®ë*<¬ß­ÚfåÖÍ7®~çâöàjá™ô3Píâ{e¦ ‚ü3J f*È_ å–:µj«.Yöåˆg—{^PÚÓd·ÞêÈm¥ÛT‡rÌœ4xÑ«…ô÷ÂUU/lI/÷û½^_tt“•Oôx¾iZx­gê>Þ“x½k‘Ì2B` µ[‡u_ÁLøŠ= #+8)‡õÊa/å¤X`Àc¥Õnˆ†gr»Õ’»=3¬ÕârÓF¥ZõjfÅðj•ŠW©¸5–CWË¥1@ÆpúøÜë«U¿ZaОFÑÌø‹˜v+ÉÕD ó=i¥V“Kø~yu@à|& f3%©ä¬$“é+SÉájŠÞMÝªÛ /¨5›Êœn•Tˆ+ë˜ .ãq`~aÍŒ• H„-,äÞ=.ú÷Ì}P}ð°§xû¼ã½ã1€HáýÄü Áäf!~³g̓ëq«à`÷Å÷‡+©ù­øýùŽ×àõI¯TC\_¤G}©£ëZ4 *>÷)ÆáDÊ5[Ó ÞI•JþÃÞøç(é"=•<:~<¿@´¾ÖSØŸ[“ž›Ÿ®IY2›¦á<«?Úñxx ]4€—tÃé$ÚÞRÛÝÞ`§¯öEµÿÑb^=ð‹ @m‚K/Àµø±®Þ¾yûí[7o¿uëOÞ¼vSÇ"£´kx¢róæõ7¾ Èj¡À|Ø{޹€¹Ù€üãÑé´;9ü¨pÔËÍùjÀÊ¥r«U•„àÃ8|¸|ªàÃE‚µ×¤w:-9Ùírwš<ÀlÛ¸¦¯^ÓwÆÒËÑxœ·{clQR˜Ä'ޝ*zŽ˜åñg¯g2ÓÞ(D%DïáþY£}Üø?[ã¢q!(áh]Q³ÀgÈl,8AÐ\z„ñª_«n^Iµ²y¿\ T‡›^Ù±0íÇ/Íà¬ñ¹×íºQ‰êQБ§3û—ÒÉôj2Hyy7åÙ¯fât <¼dNZ_+À ¸`«ÅR±à¦ÓIsäJê–Wó6Ë›f<§êm”íËM»Qi†NcÒ]»žfJfÉ”"oÀ÷íš ÿÝÔs€wS­TªîHAy饠Ոê“f©HøÐÿÖ7›å‚ æÑü’4U}j_Q·N›Ÿ®E4ª5ô¶†¾m°ƒ„}ñüãJ?Ábdj»ßÅ}è}bçDñƒö¾MA6˜ö 3>Ž@GUk›ÕEˆ»ƒÿùúÛ·o¿ý¶¨¼ýè†&‹,ä[€k€¸?øyåÀ0ý\ÕxÛ/•™ ”ÇÒŸgÓ…£f(òPݬ©sP¾´Iu)–tºìŽÅ^î™’OçHBiQOëÈ uu¥§z¾H±X™Œ¹âe¹g§¨·õO}]¤ë¦ïLBêVH2S×Åñ͹ó¿^hÝSDìù…á`@å­ %±.’R¶£Éðû;f³ÙnšŠª-Uš  §ÆE¹ šëV«ø¤ÌšeÕ«•Êf€E¯V9ŸÕÔΟ}ƒÍä'ÍHVº³µ–IbÝÏ$¬dÖuSùeÛJ³ Åá ŠkT_%“)@¶è¥FÉTªV«U3©0+pø+FPkÔ,œ´Ü¬†ÞØt2­©ÚÁzê Ö-0 +¬÷àÁ´[žIˆé·L¯íu,LÁxü; ` ôÚxfhîïâckÅŒa“ÖïþþøþË`ø­NÓªáú¤—âë Ìš¨x>+s<-ФoÔlìí—ZŒŽašXÒ±Pp–™³ùÅöFZwKîvûÒióÓ —ó‡`xv·çǰö¹óG†0oöÙà&ñv:±²š)ÁKå…JÐì¡ï°ë­4ØtwŽ@m I0s¾@éV7ª‹ F€õ·ßfÉÊÛ 7ÿä:(€F›íÈL xóúõõØþÏi®æàãçX”—…öGG˜g& È  Â8`Žq ×@=Ú“p$ú8>OôñQHT—[­NOe¢o ãýþDz WLø(ŠL]U׿ìøÓiHòüñÏòúxË?ªÀ¡?Øj çBQÌ‹E3™2oµn ÝiaùoÂê6ªU`~Y³ªpÜ£Š7,µ:þÔ0½k¸óf¥¾9ß»€ VgŒ/¾^@Ãi„Ê,°&ÁüS)½äƒ íÂøÍä2À-æ“É„'”ƒƒUcÙ4éÒ:ÖÇ´±œvj^¹bÕª÷k•%¯\~´ÉÛŒSL«­rX{¤4¢Ž$åaöYO¸Ï+±`Ö˃÷ï{EX3>PyjN¸½kv`€ƒVŒ ^‡ÿ{;ò hÝÖWþ†‡…½bžùþâ÷ï6&͆S¯I/=}aµVvkŒõHßС¹Q3*ŒÇR' &Sæ›I/ çˆ.;ðÞfêȹӗN›Ÿ,‹¶˜Œb)=‘…$t Ï›?Ç{Æ¡ÃF Ô €ç7Øê±×å”-"GH$kL¦ÒÎÎŽ¼}"Z´õÏë ¹[Ù¨,0€ø±þ¶¨yñßxûÍkoõØeï‰â 7®_]7ãÇ9™€]•)Ь½-´A´œ2ãþ Š`%/íž ¸Â®Ü9Ú£J8‘}¾ü»ÊB»~G“åF»ÙlàŠ=¶f²F)ýA„OÕÅážá7~=&B$Éš¦úóçg¨&¯f³ ˜¡ÚÁV—_çe±½Sd±/²ÒXj@Ç:Xý¹Є'ØõkžUuê˜q“F£YqëåjÖVƒ‹W+Wê0b§Œ —¿ÊñÍYÀYãÏ¿¾Z¯{µÎ?f©ådÆJ¬&óż×7á¤Ìåäª^/äI» ­OWS«)3•ÉäŠy×¶ÄñUyÜZ5>|íQÍ…AnÚÍ*„Z]‰šfmy%/·mïàm§ °ð~fÖóš^Pi´±ÞWj¶ëµ‚N‡³jÃsuú €€FÓódÍ@ð¼:þ¯6ÌjË;÷ýÅïÿQ½ ÇUÊÊêÂõ•7m\^UÓ¯Ö²¡®+0ÆœH8ëÎtö¥,·©àÀùaÙ@Wº[Ý-éôù ¢çÎíúÌC6Lêž9ØÍAì3³Ëƺ`Ùà ˜N·ñN+vÃv"æjxaÈŽÈád‚Aekv»vZÝ^OcI‡PIÏ3ö¯\ªÌÀW|ü«Ê‚Ç€ë“Û­¸TîàŽ?\þ]Cp\õµ¦§áîwU­g‹Í0€¹víÇêlÁ‹W„a´Ãþ§½°`ª‹ç=ÅëƒP´r½A:±÷’_ZÄ1¬ˆÁ:³¿ý™ã¢±„9ºZ_¨Ã €/ ÊXz*QP«µÚívë“&>L[LiPüŠh‰IϵßW+÷Ë5Œ‹rÀJ¥~Öø ¯¯7Ú-E›€¤ç%œB±˜É•\`'DSðl)祿B±”s s”J§K%+•Î;âøµÆî\í_z;Ì“Àiô¾fòiWØyÃHyÞ`7n"©b¹¾$ÂõÕ« üí´•ªG±J,㵦÷QÝiµ-·Õn6<£ÞôLx: @Ó<ïý‰ëS]]Ù‘^RsšvÊõù¡é·?W,'w[×¥ŽÝVzúŽ"½¤è=±Q3›_Ò`k«×ÛêJgÌOør,TÁMf–å°ôóŒùCø?šl9!|ZöNwœ`bcÝ7(&oLiØ~äŒÇNèOomx»¶éÝRÞÁ'¬ÿõ"4[Êæ¥ò1|ÕÇYðµG|ø¹'@ûߌ@´~ºü»·†šƒEuÔ VšlÞs4/PÔG?Ö? t¬ó?6\ÑØÙ_éöÖº,Éú-SWÏ/2¶ãûçZ¡è HÂü_~ùÕW^]·Æ¢‹^ûÓÇOZK©F @VM˯Æ|µ%“Ôë• ÖHÌò* ¼RÞ„¡W0¾AÊ‹ M€‹¸»rÖø‹¯oTZ-Y$`*–°|)_Ì%M|—´ ÉÕB1›LgÒy?™Jg¬\ºDÀ[9:þ#Z~¹V]jà&>‚ÇâX›05ƒ×ÿ¨–N§³vr5•Éîlû-S€äJ:m¦úÑõm_ ¾ƒŒëÛÄxÝ«6½ª]mbêxfÝk€_Äãuw£qîûãõiº¯3«C¿æG§\ßýžrMQÓ=]7Ù|ËÔUM'dè×òtâãùu.øVOëv¥3ç';»Wœ!k¶(uæüÁÍ?žŽkQ$žé,Ü`‚ kø!+Ü¢YCÎjƒ¸õÚà»qõÆ€óÇÇÃb{æñtüÓ¿Z_€F­!—/ÀWœ_Ïq\*Ë Q €ö_‹]–ªô?Øòx<ôší8­¦MœQЉôÞ-ÜfEÆZ¼eâõŠªöM75=2åÎsÇg?y|½Re'étbyÖÿ*ÀÍ1/jžyÒ\²ÏÌ î¶ÔnàTkXÿÁY«­*S6áÏpjcÕbG¨rSðÙºxƆXæñØ|J°µfmF‡ŸŸ{ýÑx½^k$ÿí_²“i}¿`±òwÍr¬´WZ/¤¬‚•X_/Á†ÉÈik5aeç¿ôèèøø©Rž;¾¸~ž?“®VÓéL"•JWzšmSɬ[è§]_Ý­ó×ߨ5éæc¼߀¿¯xñxý¢÷‡ñžvÀaá)ׇ¿þ1î× Ìž®˜½ Ð>×{ª®åËç—p»·ôî–ܑΞq•Æ5«XÂÏž?öÜü# 8±WÀ5(1aÛt*šºq{÷¹ù3ø³ëWÿîG7sóÇ Ý±÷Ó“íÀTj@€J‹ð»y=€eûÌ–]|åþö‹ãsí¥û¬_i¶ú}–-ÓÙr­Qo·Z­¦ óÕ˜î6Oè.èì†à¼›¯½öˆtó9:|2>÷úãñZ T9Ñ^_+f<'é5;í\0Yà o¥2æäóżUȺÉDÒKæNy½8þÒÉñk奨xáü™l:…×7jéMÀAºfz} mñõ›V<^s½øüµ/ýþªUØþ ½ò¹œv}øk—«kL˜¢Ã`þÿ¢ç¯Eê/Î/¿¾µ% v¶T`´tÁüsLÜNûÜù3?ÿ°(PÞÅbã8f’’PsÞ¦t¸€“ù3¸öæô÷ÿ÷ææOè‡Á\oѵ#جɕKúWuÛOÿZíÁ«õüÿÚæt[eØÿѶ%€éÛ–h­ zì}¹þëŽkxü`™·Çí5Kë²ÎÖßj´ÛJ§ï03ƒM£D›‹’ÖQ:¥~¼«¿²ß¸jûv|~¶’‰Ïêñ˜…Î8?ÅÑê‚<7AzÝf«ÕiɽŽ]­x^u3vb1µ 檵ÀÊõÆRõ~­ÚÔªe@C>8}ZÑ‹yó5|ˆõfùÄ^¯>*ÓþmÇkñøÊÊæ)ã‹ÇgÇß\;Ç8Ic$A˜vŸÐEã5¸e2ƒÚ}:)ÏŸÿ*–r…‹¿,ÁÆ(ãÈ@>n]àIý-}«§;ý0ZznþÍæ³?íãùs2/š>Û=˜æéó“âÆsópãDîê iþüøÖÜ5±c¸°Ñþ÷õöÖÿKÇ V+Æø~œåKY-Ã'º¨ÿº'r–’+÷yfÐë%e• ömYiuûj—»˜ê7raшWd*Ûÿòѯ®_ýüú8ÀG8ÜJFœÿÔã–_}å•¥å¥ÁYç÷ØñbOï<Š7G»`ÿN«§uE¬`žÖ«÷¹£¿Ñlˆä¦ ]üj££ÕêUšÏ#1·+u,„˜ð›ÕJ£©–Áƒ7 ÷Ë ãŒÎר:þêx–‡qZàJõKŒ×âq6ìñ/L¶ú›.@£qÑ8! G]®&›Xñ; ‘Ð h4›|&°'$8{bZ`š„Trw|ÞEØ¿ßÓëtà¥u¤ÅùÏ/VG çï…óÃLß'gÊ}^Ït4µ«Qô @IözŠKÝZ{&ðm‰]ªØ:þõ_~úÙU,ú×Þ°¾g·’™§Ë&“Ôí[œu~?®öµOßæa%SÃBgn›¨§5”N³ÕÕâm¢MØ~±¯¥%C¥þ³NKUÛ |^ÕZg«^_ªUÿæoþ†ôvCÿ—¶€/M¹V†=àUÕÙýñ8Ãf ØÿÛŽ j›u\¦ëu87ð šóÇi½âøX©aÞMÚ8Vvîñ« ÆùÕ–Í8;¼Ã}Öä4•‚c…éQÿ¨jy|•ˆ=HÃ)0技„ùÇ<Ü~_í)r³!ÍÏ?1B±6QÉ~~þ^4?¼¸—[Gà5ø_ZÀ9 IDATT”—æçüüüùí4À\»!búû«o|þéo”Þ»ÒJ†ç?íøƒL @¸çŸ?´ç=0a"LÜOƒ?4ØŽd.QDëÂü;мÒJç?ýøƒÌÊ`ià^tþãTÏ€ûB,<ŒD1 b² ‰ÐãTѾ oÈZÏ*SY£æÚ|TuxÔ?Á­Dƒ"n¦9«}nI+Ý®ªte|U»]YQ1ó¹ YÄ: c›¶Üý…,Õ„ãËÏ"6®ÖxJªö¯;Ž«n&L®Á¼åH8üïf¢Yo6sáx;8~³ÍÌs.áâA;o..ú¦È[§ ­’S@:áDr£ÓÂS1<®`FTa–¬² Æ2b'õúý¾¬H‘´³­wû;Û;ý.C:šœ?GkSœE¾8/šTz¤;q›Ã®RœŸál~.Ìÿ¿ø‹7¯¾õçƒ[7ÒÕ·$q~ /†“S zGzßúÖ7¿óÇü½?–”V£ÑþÙÿÙ|¿ÑQtiý»,Iß‹A¾÷½ïŸ ùXü;þ“ó˜\³6`y¡F•@9– àϧ§±)Wç !/À̶íYûüþëûb²I¸ ü¥£7kË'*ü¼\Õ:Ý&xtûÝ£~ aÁŒ†±[Óg}öè—ÿÆŸ³uÄÇε’±ìÓ?È&Wâ,€‹Î?+ö¸ì&ôŽï„Ç Á'Å"”Yk±¿i×®:^TÄØûZp¤W«ZmФáÉR{¹Û¦óŠUofo˜þšÞn¯á3lÊ­6ˆWU¼ª¨Õ–iŒMn%À#Âk¤Ê´NB<í_m|§“jPª±Ó‘Ûbw6.2ñµ{Ѹ¨Žª‰¦oóbôlH%‹ÃÊì^EÀTðWV²D‰l‡u0 ÃX°€)k7¹OŒ ŽBÓ6$}› 'YÒ`KÛêèƒí-}«Û’fóóÇfѷЇºÖóó÷¢ùÁtÁp$Ñ< EIvµ]ççÿàMRÿ?üç,câü,%Ä’r:(•EE o}ë¾#Ißÿãlbù•—þ—ßÿÿáK+‰LAú×ë/¡$äA«;;-ôAsø¶«ÎDÔXŒRƒg@EY€Å>U‰ŸJd“‘™Þyý×ùÑr;4¬¡Ï¸kdø, °|Û¤WÅ-ßÓºr‡9-’¥kø,â´)'*sÁÈ~õËGW?½ž½Š¯¥÷ïϵ’aîÞiÇdSÌeYÌ3Àk™6.lþüGåžBjÀž0já3 4+ òËE¬Ýf£Û’µdÅwŠk–£J¥Ú\â[³^[©‹ÞF£Ûcmz»Q)‹4üšÀyklgMj×ël‘¦ö»†ûÿ™{×&·Îë\p>§ÊV³qÛ¸ß^Glܱ/¸v£fl‰2A¶øA_X­6°÷Ænô9“Y²$[–ÿ„SS‡™J¢‡”uKôåÔĉ‹‘»2SuÌ©©Êç)[vpÿ³žõ}A7»i“®P"›½zo€À»îk=OY¯•ƒPOŠƒЕŽ?+X™T”ÊZù÷(GÎ].M†,óÙdzbTäRy+’¤ÞtßÉd>Æóùb:šfôç|q™œm%ZRÅ@ÖaU3ÈxPø åñ ôk¨Z Ëô\ÄçÜ¢u±­S`:¢UÛ©ÔJUžÄmêdøüáüp}ŸÜ·ÅÓý§ÏïeçC6½nÇ€#ýŒyÇÂ)éï-Ïçñùo½ý=„þ8:ÿ”AöƒÃÁªx:X€ÿ°Äüú ß|YܼÙÔˈ³(*ÒéH¦nÀ< *pERƒTT ÿkj }Uf_V(´úXzðbF»Ð8nÈRæ2L7/à_ïvP_# ýþjº6Ö-»{&·Ú>¨WSú#íÀIU£Î6š2´}Äb€|øð‹·¾xôÖƒ·^ûEò“’÷>Â’~NçÓ¹T¸C]ÕP¡ß£|©ÇóÙx±XÌF£ýÀ|AJJšº //“Ïæ*¬€¡ÍÇ‹Ñ|²€^“|:MFãÉårÒýÑ”$š¡Uª5iŒX8¬©0\ôºé‹rypˆB‘}8êkRžÖ7éÓê ]ˆŠÀùC°Üj”+”ÿ»¢Qòü‘bóf÷Qsýü^r>˜+d«$  ù¦½Ž;t0¤†:á‰óßzçõ …þ"tþQ à xð–}€/Ö#€ÜqÀ¼×¾™âåëÍr泹Ÿå Ù«­Ùn‹ö®¸Á¼—DKøÑçe×b ]I Nç©ó<ÆäNG¥5`’f;ÀñÞã0ݼˆÝììwÁÇå—É¥·ÚÝE…µ×A§~—²o³_3(X¡H¯ŒøZR.‚'n¢ôô¾?øü‹Ï>{ðèõGo½öÉ'É~ôþûGT2xþóîß )MÔ;+9×€Ýý=¦¨ÀÖÚòùùdw˜ÐôUü Ì>ë>¥|d¦G–Q5­`¨HT,mq%+—A¬ ªÐ•³\òtª¡5ç³ …ÛFµZ1Ježˆ%k¡')1™æ‹ ô»³¹Ù‚ÿ‡a]O¦óÉtÁÙd1^Ìà$ÚïQ>Ÿ@•I¡àSòËÓÉx4& Ǘɧd&ì×IÁÇsD£ùb„ï.¦ãÙü2ùx>šÏèÕÐoF¥Ú@ìdè5XìVæ”Ìê@ýè°ì€,ɺƒC׺Àóê›î_tþDk§¥î´šªÀù£ïËógqAšÎÛ¾Õ¹ÌÙó{ñùXAª †T³R­°QlÎõøü·Þz7"¢cµ¾ûÎkßku%eÜaÏ]&§ @a øEYœ»&šñr¦\Îå3!j•ëm|÷å'Šb€ª140“TTÍü’äˆ=ð±ˆ@z¾pÊ”× €Ýe­0¹äEüë zéwò!ׄÝí÷tFt¼–USêÅ㘔€Š &©)ÜsÉÒ[o}öà‹Ï?ûü­G üäÃONPÉXÖù÷o…BØô·:+9Eˆò{.à,ì-ŸÿôÑ¡Se»üýACáž(Y‚FV ìS–R7»ùn.{ÕÍl]ÝÊÁéS¦Š@—Þjƒ\ût1S³iÅà¿ õ#VöZ5Õ0 #O²š^å·R©9}S×I·&ó é ‚í1ýF*FÊ÷û”O Ñ¤Ûd+ô©ãŒr>¢Ÿž/“SD@ ½˜À°Œ(@€*Ï96À³G—É'døö0ÓF£ÚlÔQ?¥cKéGØqêP-‹ê°¬‚JÔI0ŒØ+z¦¨’²ï‰Ö6E’Û-Càü‰²çkpì Šµ]lè¬ßKÎÇ TÕâô_‚ªáP‚ȉóßz÷Íh(õ°OýÖ÷¿'[ ˜èõy W:â`j°k¬ÿ7¯U˪hÊ<]ÍkíoŠ]ñrjÉ x±ÐXõåqG@…+ú\‚…j²øP.å.6 Øa,%RÕ]Á>û}›^¯çŠ×çõQ˜µ‚½fˆåWíïõpÝ8l¤¤ý½¥0µfW­Õu­Ž|“^g£O&4cx·Èä?xðù[Ÿ}ñèÁ£Ï^{íQ2yÿ£c*&£ûóàÕ©û·B~z1-òïòùû;=^äÞwÑÒ³œ;«ç_Â>Û]Ii0  ¨J‚Túv\¯UJTȤöòÙN/¿…ö_ŸçTî•B”ÀVkõ¶|T|Eƒ1½g\C›»Új¦âÕ ²oµZª+¥J¹¢Õ*uò‹¸ÚñdDn™v× ÍŽçмߟœþ6† &Ǽ U_†“s'=#äŸ_.Ÿ’“GN0žÑÏŽ ¦çBhAj?¾\Nör‚ €Ål:o·oÞ& RùèUyµ\Ì‹s­r‰Œ4Ù€%@rÒåó'pþÄŽÑ,7)–év(/|þó¿lîSn¿g­Ÿß“çƒÏÏúùx ¬:©¾kº=ë$ìyë;ïú£‰wßyDëûú6·!j9 xʨêinÀíöîÍk»zµ¦ˆš¦ÕDÍ+*zó¥Ý]Jž€0¾ô55fÕ´°•ÁÊ€+í×ËœWÕSÀX3àØÂ°^¤sà³Aü½Ðü+~ÏÆ•+ôEàˆøÂ$GÚ£w«»¬»î ú6øVúÎ>º‘=Ù]¥VÓšV1È4Í!oP0qÅáŸ?zøð­Ïýâµ_<úä“û÷?XQÉðóÓý[”íû¸{t {½-§³|~–úP mGɺ#Ÿ_?ô€cfïAõ™1”PŽ#I…03¢4 ‰®U~>w¼Ð’Éä|þL¡1*5ƒ´þÖ­›»»UµZ»UÀ¨#*~èn#妥ÕJÅQ¤d§ZªéÿrU«×›c²IÓH!G3xWò‡3̤9äiò4iý HÔç,œæâG.–“VS”° O?†1aAº<Ã@L(ȸDNgÈVÈ&-ô&ÖµjÌÐK‘0 `’ÉZÙþÁaß Ÿwxxpˆàð^{E<"¶›z±^/—EÏ¢Y3Jç{ÊhÙõÌþ>¶3çWžI_ˆ£±v>G¬B¡)À{ì“Ä.­?yçOü‘Ä»oø7ÅŸ†â¡×¾+˜ø•äû€-À)°ùÖkü+ýÂ7)þo‹jEø…RË+¤ÿJ³Vi¶oDFÿá"v`®¢T~PY’²¶Kpðÿ m}Ù x"zpõª¬„=¶cïã]¥ßl¦~Š• Ïã½råÊs_½²qeóé Hê+ØÊ¥å”õIþu´G:L]…>L£Ñ h˜L}ÛbA_6díÃÁ!jߊ|öè³O>I~|ÿÞ½%• ž÷o‘²û½d<¬ç-º+ *0¦üÉ<ô3^_ 4ôüÎòù™ú‰i Éý»îž»‡éM¦„“‘K걊Q,*¥Z%“µœl6õßÊ 2¹|ÎSBöÖÚíш_* WÙníàѤ`iJdjMú<¦Ó<%\-?àábÇ?“æþžäð)7 »@jʾ}Ì¢1BvJ.”ßžtnw:ÝùtŽÒý¤ÔðÙŒÒ Ø=ýò±´(c¼.úŠ~f4ŸVãtôJPÅ h6[Ä0éd;.ˆbðû¡K‘Ààð gQ‰mc»¡6uUôE³ &¯²ÀùðTŠÓÛs÷÷-ÿ=u~åù¼ƒ=ag‹ÿ§ÏÇc©Õp>q‹“Ôn°ïDè¸D4$×%õæ—†Îã €Ôÿ×Ò_¿&A’ª¢b{µ WÊäB† Àe5ò÷±24¼\@  G—0`œCƒ<¾°nÔ5@i²Õßwº{]&þµB4Á>¥›Ï}õ«Ï=·±±¹éõ3ù%¶)zh ðRÖÿzßdòJÊ£ªFs»n×lÖZMF[CÕô­áƒGdþä³×_c~Èû|r©døùqÿi€ @€€Ç Gá¾X~/ÀÿSVÐí`Š´?X>?ï‚õ`£ûΚ¿ô±ûœÞ1Hô’|´n ¸¤ÕŒêÖ£¾çj&ƒ-{ìý`Ø"|ݘÌðáM) ¸Añ?ªn”åµ² *µæ6ø¥všµj…•¿\E PkRdû›,u“Âtr¸ÝçËøþö÷"Ÿ²sž 1XŒÑ¡AáP{òÙãÓòsçYÌ#ùî¸m¦À<1éóxåâSøøÅÿ òþçËQ[OÑ]`#€¸`>›hVb6˜‚%%¶Š¤ðNÏÚÈ ) °AÅÔ’|TÔÕí¢¡©b_Iµ!*etPÄEK°@ûfwýüÊó‰¶sב§ÏÇ)rU ê+rUpÆ ²8IîJ௣ø ‹䝿´ïÜ Úy€|ÀˆöÍ—5¬“Š[y]/e3ÙB¹Fva\È 5¯q€býš.{<<Ä0€«Z”|<‰ÐÖØóÂbúoú(ú šEÖ0…ƒ!Àëóù6Éû_ynó«d®x’w%ÇeVƒóø×MKr1Ð[lԫͺ¡×æNÓ:8´Ñd±áŽ/>|ôè'þÇO@ÿÁ½À’~[>?Ý¿EÀ‹®ŸJîõù7=žP”4>öx6ý>oÀÙ¦QÅ}k;œÖ>ˆÈ­ã½nËÌXöB—­H¦‰`úqÒdÊÛ)Ъ6‘ô]å~.»•»çÏä‹Å¢fLFcÔÉeà6à\Õˆ 4̹ñQÖÊˇªëµrEÅ/Co4šÍJ%ý (®¡ä†˜53©¿H—IéP½{ærrêätQãÏ&ümrÜd1П;+o_Is¿½Ûï÷®“®Ð{Ô»¹Øo_ßß']Àô¤9#Õ^@Áé 29B } €Èî~$§…bƒÙ?3ÃÓ±m20š/„>Pó˜CÆŠ0 Û˜Bj踠Ž4Úgr©™ãwQ×vZ;¥F„¦ #  PÂ2–>\€Ïkçwy>Æ uMl>'éÕ‡½Á`Т|èÊ’Ñ ús¦woýàm‰ 'éÑ饺d³ÈˆÂ9ìÀ¤ü¯³@`Wè…?|>“Ï}­ iåìæŠeD/?A  ÕÊ:³þèµ ã/+€†¬TV !œ#<‰(ž¡_W+G¢¡ ÷êÝ õÇÿÞç6=¾@Èë·X@ÄežÏ¿¾,¢v(7ê:´J³åPîO‰À»gøðÑñð¡öÆ£?L¾ÿÑût¡)h«d®°÷W|0äè}þh  {‚M½®Å&ŠçÊf`scÓ(µ0ÙçºûòùŸì€Ð«*êz±bÔ·(uÈécþ/Ë›5¹ÀÅr¹‚9šä\!‡ g¤Ök<†…΋Q¯‘= ‡ü½Qßi-;­ú4ý O¿òÊùöü•ùšÊÁ6ªf”n£{Gî[ÊçÏLNÆa‚üd‚|1æ6j3”ïèßyû6d–ߘY7{Øñ¶oS*Ý›šíÒýÇè ¶w¥öÓóŒ8L¥X¬ääßǨ?œ”sizÑ‚å8ÍÈà?ärô>oå V.Ûïæ)s)#â—ÍÛî:%Œ¢i4[-Šœ1dšB=}ý'1ð”ÒùäjoŸ8=sÏ¥ÓÛØ: §¶ÃWÁ'ÌãçÝtÏj}÷Ý?áâ_X€tб–r¤”¾ü—ÿMΉ^—ô׿~-½+^®”ò™\‘cG2€”=ÖØ.ðÀÅ€¶¬ôë²Øeb@LZb¸ÌcÜdøу΀eˆLy…Dô{*Æ"¡` àóy=þ+ü幯|usÓ z¼¾eÍÄ›çñ¯S¢í‚‹Ân²*Y­FkÚXð1:˜&¶ÅÃÏl=ùáÉôÁ½~_\9 Ñ[FÐëUèéC~Ÿ?èó+þ€õ…7#WBìþ7ƒ>¯/D1€BÙ@£Ñ’Ïß]=ÿ„ˆJ½¨ŠèT([ï¡ô—e,ß–‡§ÜË` ”Y.ÅÊHzçðµUzïëÛͺ,ºðØœœ†5*FµÖØ‘ÊßÚiÔ'#2{ô€ KBv`ĵ3R ҚɄ}2'îÐaòÈÏN>&WFœõ™Ë(’îRDCòv»ç´oôû€×9 ·Mq¸=°ûƒùõ…u›Ž8iqû:ç¶Œ-f ôú(p±Ý¡;Èã£ä¿&ŸúóD½uüN¦3U/y‰`‹Q‘èSÊÝëØÀìµÀ"E"‚áw»ýÆú)ë×[-•2°u(èJhÇ'Hñ(hwÏFÍ g­y>!ˆ¾zØ!êÒù$•vŽžßáBRëÝ·€=€hœ™ ÂòÞ€lE/ÿEäÏ‰Ž ÀÿrMܨrû9 rë¨/i‹ë¨<ÁÜ}áÜÿC¨ 3ÀÓº, V`À pŠ8[¢ d‘ oáM~úP¤Ò‰x4RÈxýW®xý›ÿ¯lz•¨cÓ»*¢Yá_·d©\ ý~µ¦—(†¡´x»IVžL­;tݸwÅ[¶5‚kÝsEê¸H×j‘Ö‡ü~_ÜYz%J( ”K_$ðÓ!Ÿ?öú¼0­žðÎÑó?Y‘¨ŽA´r±fÔÌlד¸¥e橽Ç2¨µQ¨Øs÷™XU¿=Je:™‡Ðù åós+©;h}÷{ñ”ˆESJJðó¯^½hTEN;kÞx±H·o~¢•òŃÏþ£†yhUÿd÷æ ¤×\Rä*^¹Ò*èC˰õ€¢U—µý kZî =¸l“¡ sˆPlHú‹Ç¢(¡ÊìÏ]¹‚¼Í`8DG¶ÑlðíœË¿Îè»ØÀ`³‚á™2¸ •&ý(ùX~ ØNó¾#>þäý{Ÿ|xO|åD›® ÂJ@ •`ˆž7 ‘öûÑP_+!Èþ"„–M­ãç\›(›9nÑ»UÆx¶V½7Y¸-³Žw^Ë:šZ(x- ìãzæó1Ez³Q­VA]G‰WµjTé·ÿV«Vë¶’cœ2” ¼‚1=ž½ÁÉÉm“ÆŸ"zŸ=39\ÿ”Ëä‚9 à`ÂJ;æïÏÚ7ÑÄéÛ7ÉÞBDÛgsÝïš8 Îu-ò[œÃLÆrJ˜­ÍtL*Mî~1žI €âáº|Ì-9ž€—‡‰zŒtµ˜{/‡YËçͳí×£‚|èÒÓÚ69,ö±¯Iàv0U ÞÑ;(î=Q›×´Ïçéó<£Ó±éŸ:¤ßôÌ}RýƒÁp0 óyèÊçç©x{ÐúÁ·âÑh*Jù?ÿêõumz!‡‘/žH þÆ×¿N®þåkåBñ'ÞçþÀ÷Ï:óõ_~ù‰"fýæ•yÀdÛßÄn@™ƒ(BÐ* |rPµ˜?c–ƒ2ȆÈþÚBÄÓÑx4QÈý8Ý& @®6Q<Ï}eóhæ1üëLÁË\PD^)OKÅj½j†6=…m”v‘Ë7›o_ü(ùáûŸØà=Ôi…Rþ 1‘p¸YÙ®Ö#ô7;•P8‰DCaÄ¿¿Ì"³wôüÙ¢’éX9yjVa‹™È@Ö1p.WÈä(JÓô wÛ¦#Ч¡W˜sE9›¼ÜbZmîÃßn4›äý·IåÉïÓÛœœ²°´dxèfÆ}8–ÓפލÏM9ˆ~frúr$gƒñr¡ŒrH—3ò S«×»eÛ¬N·w±oߦoÙ·I#ÍN—ò´î¼½Û1Í1=Öfž¢g gÈ„^Ç´ÕªLG‹•|2AW‚ë<4Bl0fj1›bX>»Õç½=LÝ‘ž )ü<%\0«ãЧiŠmÄTÕjE6½ ÞçÖÛ“ z™{Gçsí|˜<ÅâðŽöB((è[EäüIŸéùÙ27ø8{­?y=ò¦bÁ Wàùåë£è€L€íˆR®|6xãÛoÐ#ýõoð,བྷµBñŸÍfBh:•û”À\¶ ˆšed]nÿj ÔW{€1ücÚÐË @9W:iò¹­’8•…öS ”©h¶EäĨn‹ÂhvF£¢W¹,Y5j ëK£ ´Üž»çÀÈç?gT4“ÏfúžýnÖ“½ÊíH«n Œ>Š*€ñ29×b »@W³XvÓè£i>sÐŒÖ)Ø¥5L½ÎfÕãG…~Mç <šGrW(÷žCÉ1…ƒ å3?+9T=9¶rχë€ÈÒ‘¤³–Û}‹¢нÉRœö.°“ú¤dvû&`Šo)4è[=~Ú7Íîþþ«ä"èý%HX·Õ0FMiÐ^@@J#Êè…NñgUèݦc—u³r4Œ”¹gTAF_Ø (4b§Ù@”UÓJÂêÍ=á¨÷ñùè|vÞWžO:/0¨:ôï’oúq8¤R¯½óÚ;­W[ßÿ–/èKÅ6ƒ\°gŒR»Ã,BËæÏèÿ·ßHƒ @[ˆE³TøÂ·±¡ü”ëFµO„ؽy3½ÿ*ÿº ˆ5s-†‰t­Âf W+•UPÇ’& …—€|öd0“¿šæêѲŒMÁ!¦D*’ ˆIé( +ˆÄC¾Í+ûþu“¢`ñº,±mªVMÇÜGÉPk |}²²¶ëÛI~?Nÿ %ïƒI¢V]-ë`òŸ{þ-ÓiUËuµªWÊßë¡fµZ®Öúû,åCãÑíöíÿûÙe0Ùo16m¦Ã²H¯j`;³LáIæ*ÌGØô»z˜ÀVfèÜ’;£ã;â2ûHÆøz2ã{<‚߯ooÏäNÈÝMÐ#…¹}«AñW–‰@÷•Sòãë)|ÇøÌÚõO#'ÿ‹¾öuÈ@ëyvˆ›õèͱüÖÂnßFHM¿÷G.ËÛ³îhÖÞ”þÁbA‚^ï:*eÖMrw)PˆŸŽ¢Œ½A˜:šR^èmíË€Û îG.8<™aÎh<á÷äÁ{t¦¼ü‹"½í’c)¨Gªï H wÐ?;z½±M¯\¶)‘?qRŸhÙkÿÔùÐè€dy>»Î/»æ`HÿìÃÔw_{çõwÉüà»ïü§Í@ÈÚx&€K¢ÆÝåÂé‹JiëŒøö·¿ýèÁ¿ñ®‹û×=â¾^(ÿÃÿáó‡eÒÿ5}â¾xùÆåôà(4ÇeÛ_Ó#L®•шéZ«ðüºªJ¶ðË ÀV©rÂäžÏ–òâÔº,Ù~ M’‰D8Q˜­€ÃÚï ø#¡ oÓƒJàeüë–îÝ®c’‘¤äÛì“ ·òØÑz¿j÷ÌÃk8´…çp˜üÎo^‡¢Üû €S[­ëò0ß¿U)S¼NŠ xɨ†Q«õš|~ü6ÐaÚÃ|jü笋f=¹­®“ÙZ®‹fÈ¢”Š:À€r’°ÂÉe7›õÐïùBAÍH›Æ³£ßÅ÷œáœç²2@ê…€˜‡é&pÅôs$oïÞº}ûv»=¥WÍ€WNÊ/»þ©ähbÝ™?¢ÔýǬ‹SÖEÈoìI»M1ÿMÑvבænh»¨’öo<¯×îšXî™Î°<4š¢Ú‡‚Tzƃ>$÷nL6<ÛzÃXÉ'<¥À[JôæM¹1ÒÊEnÿKìÐ\Îâb1¶ñ»æ!éÿ`èP б]JD1(êìÐGoTë˜ù“–'_÷>>Ÿ'Ï¥Pà±:Ÿr—MÖ÷Á º‡në»ßþþwÞ}ó»o¼ó§òÇo(›„žŸñÝzyE•"5g é(H‹{æÍrRv­DÉe­yÿÏ¢âeò´—€²ôåD£gºª—ËQžXþ¦BýãO”ä·Š''3_Û*•€ |0cx0´è•%ãñX,·L€rî`Bñù7½o@±/ã_gr ïõ ŒÞuµR^"ÃÀ¢Ÿã"ôo¦o^¿öÒ›dœj³> ØÁ÷‡þ—´R¥ÂÅ?¿¢Ò;P©X=ÿÜ}ÇÞc.(<ÿ9€9wËÉZ™L/›íXN®ªT :Žj±Lù Ó×åœ%{Å%¹r^-h(«M§Xi™Îäè 4x¨¸‘*‘û›Ž¦œsóô Æ_àŸI~ûæííë×ww¯§"€“òË®*9|¹@Öî9Z ÌOÈÛ7{}» *½Kÿ-›œ+LøM=\Ö¾mAåFäìglu&Ü9’Ó·¦23½æ©iK9E!ÓÉ‚`8G1Ôb‘B/3º.YW–H7{6˜¸,ûSù…ø!š€­ízEÇœE­ª aÛ=Ö=9àËcÎCÃ÷OžO €Xh@¸.p£Dø-1l½ûÆ÷¿÷ƒï¾û­wÞ|ç;ï|˧„¼AŸÀó[r¼°Ûúªµß¤¹«ÙÓ@²ƒ¿™~á2÷…çåRz)K>·PÖ*Íû5Ÿøàå›H~ð ºeRìÚ2ñç1‚Pe¹ ò:¬ÄT-\Ž\d¯æ*' ø™| 2ëÀ¥h y@,Ç"‘p(އÀÊC¿@Žv ÿº ÚVú8PµÁ¿ Ô`f™w™” €ndŸÏžŽ¤ ðµÔËâþ.0ŠÀpÓ«èÝÇÐMKý¿ˆ\&ùšDдU÷)AÛÅ1|;Z“Ó@z†~l ÿE€3 ™à_ÐçàZéT*žˆ&Ã1AÙ@(qì'à_G Ö–ÛûnGÆmd$ µ\ÖJjµbî*Î£æŽØ¬î4þ­6ÙÂtº3謃vÒýÁ±Ýln·"Á0›¨´ÕZ;-M©€/¦»ÓUy¹‡çWÏ€Fê:¼Ó+d­<åK™À€)þ/—ÚŠÎ*³ÄÕ§ ÕÃh×*Âÿñt •£8"Âöýt.§_°“7âëà ùdÌ›²“ÝëívûúÍ›rX>NÊ/»þ©ä‚»M1™‡Á?¬çMûóÞàR~kd/ì•üúØžÎÚ·è“ñ†|LÛ×A»Ëë†=âÙ",!³ÑÁ`1é;J$‹ÑÆtG›lŒª,Çn0E‹:(B uÐÔ9o–èí¦O ‡R´ýŽ»/QÝ·ßíˆ}È­ÖN­Tk6éϪÚlÐ'WXžôuÎ& Vç£{|>Î=Ÿ;¸C äã]ûîëo¿þý7¢q²o~ç?¾õÇï¼é%|a‰‰ë2$¦¼p,,iFæùÌ©@>؈ÿ*!›•#åÕ+ñ”Øýfº#€‡ú1 QÉ<C5=V©,‡Ð4ž "k«D.4ô íxú_`nÀ3°Ù+þu èa@ `Ø&sù$üëôA2 &1¬.Y°ÍjMÓ åb±@‰ŒY}Ðì7"ú òè?§oþøþfå<Øn¾«Y«Q(˜ öX›Ì@àèÕWëfUUÔŠ£Vk=¿ªV;j¿¦Ôt½¦õõª^·XÞU«W1K­uàL ƒülÿ1Ó%À@± øßñ8)¿ìú§“Ë!ƒåîðªyOW¢nJÞn“v@Þ¾Þ³—r2%·&]L¶o“ÂнQóû ’£ûOòQ]G‘q²1Ù)çõM–OD G”F³IL…|†Y( ë[Êе۷àP餘 §ÈcZ¢Aî-]Û–ˆ:ÕâöövM/mãü=9ì»é¾:4M›»ÔnïÎÙóé®Î'ÇÇ!«È|û{oEBD`¾õÎÁ˜N‰}yþõƒiçy°¬e¾–9ažœ÷³º4ôú´ò‰m@ðƒKrÐuâŒ#þuüK%t²äg—†ÒºŒÝÂ’‡aLÑß{° k[3Š%è@sý·ª”óW~ÝP#Ífç<⾫µMJ߈„ƒŠßïWÊBTŒ¦¡‘%Ñ«F p‰z’úªb`.§V……¬\ ¯ZÉPKôRÈ䘱®›•ÒÙô¬R€‰Ì_Ǭ7º@ºÍZ3FÍp¼#FÒ¢ÿ¡³”h4¿}s÷Öõë×oì¶o\ß½}V~ÙõO#ñŽ/é!ˆÓq4妘<-o·m›äí[]›åÈ è“Ÿ"j  –?æ~jL,–òVCÓXÞR!ß`ùÏ8C[’ì ª‘‹‰^. à"¸ÇÔ%J2PŽ7€ý}‡ŽK×q‘Ì›CåÁÀˆªÑÃÁ¡%ª¥ŠpDMÛ6ÛùÄÄ/èöS´o“ó¿ƒáäù¤ÈΧ»:Ÿ&ºÇ‡Nwpx(R±D$%œC‰Eb!ú¥ÄCbyþ×õƒ @±¤_ýÚÖ‘øm3Ïä>lÈáëÀc[èÿ’x:ëÿz·ÃõLNó³_Æ¿îô°Eq•‹˜Vž>W×Ý©Õëj]Ì"ÈëV °L?2•fç<ê.yÿV£N AÐëõ—€qÔ,èE”ÀEXQ+ÅšQÔ Š2 µJF§Hãñr²B˜K* ­VÝ¿LÖcfŽ{…«]ô)¦€GSž¦™ Fßað¬17ÔÈ "ðF E÷):àGòöîí›7¯ß¼qýæùòË®ÿ]åèYRÚ´žšó¬óFÐÅź¼=±ÇóöÂ^É\»¼#Öyt÷ô“&ŽÁ—rO«UQ!ß6 ß`)Þ¤—Mä4ÂhB¹0rèdsùçsÙ«|fúÊÃ}ô‘1ˆdû`àèü¹¢Ú®k¹y`GÔ·Qbê·µóÙY?Ÿ./¬Ðù„[3y‚³À‡‡ìN‡‡¦âÂñýbuþ×õc‰Pж¾¶2¿ýã|ðlîÃàk[ZáúŸ;f^#Ï<Á¿¯ß7×øÙ/ã_?ɯî`ǶíC×îU£QÓjÅ2L“wþœìªøÏ*nœKÞÉ÷oí4ëõíP(àó¸Z­ZSåM\fð-h¤íeµ@:N6.þ¾^¸@^ÖŠ›Õ*°= K€L½B€Ë`ÂúÏEož§eåXÎ3Œ–]FÐF‰Êê7™ˆ“òöÍë· }{ß»óÑùC(Àk%6zÓäÍmvýä¯O~>]K¶ Ñó8°zƒÁ sè:K[ Dÿøü¯éÇ $G S‚ø]ç€gtŸl¾”!ýςū¤ÿrÀ}öþõîi~öËø×Oò«wÑŸéZö«¶ÕA)¯iF苚bÔ@9ôG0ìðÚ›ßùÞyôÝ|ÿÖ6%üõpÈ/ùÁA^Qn‚\¢d€Û›ò¯ùyC344öTLø–Õ åÿ«Z¹Vƒ?Êf‚öerÒÿcà¯òżÆó¼Z3âr ãðLYýxÖNÇrƒ…)Vl'äí[»7n¸ñùe×ÿÎr¤ûœÍ/¸nªÁ ¸ƒ]ú%òéXÎòxܽÔ?H©V`zR¾1ÚØð´²”o<äW¦Ü|œŽˆ®ÕËN …-ÄY9+ŸÅ,ŽxxÈ¥£ˆ;½ÇçTyþ8ˆòüýôï¿ÕùD'IþÚù? »˜Ããó¿®Gˆ@9-ó5 ÿ®ß=x6_ ü?wŒ XÚ"ý?FZWðË ~ûb¾ó* é‡z oÓh?†½f”Éw7xª×¨©uÉßþGY‰Z<7VüígøÝºÕІ1üï÷”íæv !>ò…2©v™9n Ô“Îk”½Hã/ëô½¢V6jYjg·òOö2ÿìAr,l—Uîþ“G]ð¬í‚<—€'ÝPŸÉ¡wÚÑe_ÌÀÓöõ7$rëu`”HÊ/»þ ï?—°€³Åbíþó%Àˆ·y}}?žÛ—’‹år¯%9I ƒ.%bàX¾1ŸoŒÉh•cy8äõÃ< M1Eÿ`lhEI#œÉË.k&ƒU±A·+stàpâ¸t:&éö™Ï¿w<Ó…óÂOëU´Ýwõ©àVûœ>é\x=Ó{,éALÓ6 à7P›tùcÎ/xÅà¬Ë!Á(x¾üÿ?/?Oþÿ&`6£ž„;â_’`Ó‚â%»ß1ñ?ýB2ì’Ñ[Ã-Ýóù׫UEkh5£V­7*õa ézMØ"+J‚-€äo?ÃïÞBèÀÚï¥GÀÐfÅ(*ÀxË(ç#Ä× ôUQ/Ãßõ‹ä° šªV3[X(€)—2oÖ»¢ÿγþsÞÏX;²ÏÎíÀù4Ë\Dsk}1å¡Ü9k,Pz(>¦ßä^àî-2<4ìœÑL /¼þ ï/{€ùXœ¾ÿˆñ9¦SLOؽXéÊþëò“  åüó”»çëêýÖ¹EÀgtŸòóùòIPÐ\¾tšh­Íwi'8îÐNÿIfW,àRêåZýóXþõj×âî= ª¤ðA2Λ¤œ×`VüígøÝ[Íz#¬øêõyt½©ÕÛD0AéDU© ½ "y­Z«ëh’¼Û}œmÈZ5SÍä(>w§³¾|ޓ˾÷Þ{ 4›sÃþu,£l´½°;å]Xx[ÀÏ ¸“è3ÆåAd=e|îb}Iö‚xØ¥^výÓÞŸ§õ's‰Ñ‰Y~Ìâ ªà…Áñeò)îcчa}éIauP's-PÊ£AÏ;›QÒ?Úo«o«VÒHžLFþp"ªxx hla5¢ø®l总LàŠ-÷²]+‡Ù ×=(êùÖ@ñs‰9¼¹àÏ?áÛðùC+äIÐÓðù@'ßêìA×Wá&Ž_· Ëž.½¡«~î¥H}^Å¿˜½V©éª!"!ù…ÕM¦N¦’¿ý,¿{‹€P8T( ðûÕfM‚Ô úϬš†bU«¢ÔÕªbØJµ_“ƒuƒþëU÷Yn.噊R­ÒÛ“/äïPï¯vŽþ,™ö3ö:wOyý‹u¼I‡ôF€´`ŒŽÇå˜Ð°éÂDîÞOQ”ÇírE:™°‚^|ýÓߟ5|ƒ{|¹@=Úš“Ëä˜Þåv Üú§pÏ;B18à )‡¼›>/Ë7& c¾±1mÕIžNÅ¿?V¼þÑHŒ• ù6½-wm+Ç,¦SÈä°T;èɲMÅçõG^Èç÷ûðùG#~ÅçF‚^&M€ÏG»~ÿhÜÓµ°n-9ÂQñ5‘ŠF<žÐòütN]ß!µïŽly¸èÓqÀCe]|~âž–Ÿ49íð<«ûä¯j¹S@]c–$ëxÏu\—÷8±²ÈB(Äq=Ûí÷î`’ã,ÿzߺ‡–{@f³[Ó´¢øŠ?}]ÄÄ;‚ÒpÃu­¡mÎò»·šr Èçñá¡6Ï5*f£ çŽzvì=£âÔéàm]Íoe²?ÄÐ!€æTž­øÀ˜]¬öØbÉ‘»)Ào0D‡›‰ôHaPØ’ø›H&\x#õáZúÛzÜ®R—,®#Þ†îpŠ=¿ôú§¼?VynWzö1£2 ý0Ít‰\6ù§rŽoÊØ#!:àq–'Ÿ×ç#yh£QªÎ6FcO‹äÉD<èó*Åëàj¹…ðƒ(dd¯UÎfì ,©¥Œ"O N‰ˆOñù"Ñ^$ð+~%šúžóyѽƒšÝœ9NÖÁív±áÛÜÅy:Ÿd"™Šýž@\ž¦£8ºþ̨xw°´óPs~q{ÐåÐâÌù>ͼò8—¾›ùñ­8…©j­¯UšU½ò$ŸguŸÂÕÓìÀí´p16m“IEtsβúôj Eéßx£}¨@äü&é<þuÛ )tjlW„'"â?GȈfôÿÀ vÎ`ßð!Ìzp’-[ ûÉ£ˆ.fÀFÌÀòd,DÚ§,"~2‹ÅÆd¶‘ؘÎSIŠ 2@ÁÅèç¼äÛ•À½ú®r«s}Ž&ïéÐA xþ@8!Ò~ßfD‰Gcáx0ˆF‘P€>ó 6pÁïÓ…ë'çOî©Ôrw¯cbî´$X§—L¦èA¯ÂHÄC8?X2HP`¢ðõ§–ź}‰'lZ+ž+óÜó fkW²d®ËO³gŽ×xÏÒw3ºW¬²ñÓ+MÉõsñ:ðÓÞ§Ñ/¤‡ªa‡vµnyzÝ‘‹,§å]ûŽÓÐÎ _T Ñ?éq=Ð:Ÿ¤€=¬};CáS"ñŸGã¨H‰†øÞ+¯ÿÝC ‡CÒ~ì#»Ã!øÝûvßÝ·M8»ôï6š¦¯/7/\=»ŽŒN6{ï^ŽòNø tûŠùœ/ÏÍ)€ÓV]RÙ3Þ6†lGK0à9“æMµ à!WDäãeÙ~ŠBáTN /ñf Ñ=ÁJ̘wâ±v‡ZÛlzÙõO{ÎVøZ.èaâ‡wÇL8ž_*Ÿs0âD£(0"IÀ`ˆAYGƒþ`  ù6ª²1Å6 'ß •¥lM ‘]ÅÂa é}!Å—ÏcÐ"ÿ^þyôZMúeåÐ3FÍ>è øB‘˜H“UQÂq‘F"¡P<•La%x%bŠTðQƒ.ú!úä—MÎbÏ …B±D,Eád2•ˆE6CÉX0Dx+™H$¾ ¿¼þ̺8 Ĺ[à˜óÏ/NYsÈÝuùé`iΧï^é.»nÒÚZTÐûñàYܧ˜Ñ.4¤EdÛŽNXÀk8-_®pÑwúî“©Á À%ß8Ÿ}h ÜC÷ðà@D^‹Ä߈¤"WÈÐã¿~ëMifÅ4&}{ý.FEl6뵚*Å Xfæ…€gIð”ÏÕúüˆC1–J§´(Õ_¥¬ß@Þ?‘˜³q¿[†ØØ³Ÿ.·è¥;¤ÄyÌ…3îÇO%K¦ì§6af\LéŽ&˜"Ïe—Í´Å¥×?íý±øË˜¼SLã§rŸ‡šq:½L>e8q9"<ß‘ÄDÅX$O,å 8çP4ªx6šŸrõø…OåD"I¾v3 (ÁhIÕ#¡Ƀ±ÇÏÁ×ÖÕ›ö;6Ùiú;zfˆ IDATEc‰TH¡/‚)öS"EØï îaÖÇâ¦?zúô9;6<ÒadætBû~/KÒU"L“åñ!űœD"E/K zü¸þ<À˜Õpcw~.éÊ^kòÓ@îËïúî‰GüüÍŠJúüƒæã|žÕ}йÓ@i=+Ê È¥“Gñ›ërk¿Çøåß&·í\”@$ŽfÀüëðÅWb¿øcú˜"Þ 2öok?þü­øÀStŸþ la0ì"¼péùZ ,ÿ*]zéR¹R? 8 µIÖµV7—³è-¡÷ÀÉf¶°íýWÁ¨•uM5$Œ†ô{KH«¥7äâ8¦eÑä–sxSl#l06—#òã%ææAÕ5]ð¶>põPPšÞä²ëŸöþ(#ò¿eÆÕ Ï=æž>æôç—ÉoÈÞ±›s¡q*¡EgEÊEÀ‘‰Ïר0Èm'bá|!¥âÑ߯„òª¡(EòJ8òy(Þ"#2leÌÜ=;ÛM,»†”p4’ˆ“Ãö(J<&R¡€¤D4 †ƒ²(ž0%Þˆû(üî¡ïlî¹}ñºtdÈtƒ¾M :â éD"Oøý Å ÇÉt2™HZ^J!C~ 2É-Y—{‡ó\=þüò¶âºü”(äW”^çÑwK%f•Õ¢¹bÞ¯èc°üžÕ}ô|áBzðW): ºxô™ÏÈQýC3Äìܱºw…Á’© ø×Cw(‘Ø/DQÄ”+> *Ÿñà[o“ ×èš!Å dÓÉ ˜hC0ðvöÁ3_©/A!Fµº ¹J ~\ßf2V&w9@ùàÿª´ÅÊTÞ¡£.™r²6ÎK¯S^‚a2=ž–å@ìÝaå hÁÁ7ÓgÎn&ÊAíŽo„Kgãˆä/¹þiï™!”ø%`^p2ßÝÝE¹_bÌÏʗ퀥œÃ|ü[åÆ!›Š¹œý£WCnÖy\Ä“éx*ð¶7”`„‚B!‚É‚q2F2 L4ðx|xï=€]ÏÍrì­´â#U¢±H4‹'ã‘€PbñDœ"Šp<=a%KDŸ¯Ïkéï˜z (Hüzœ™6=ÅŽÄãÐÿý‘¤% oÉT2MÉDªëõzQÀ: ‹áæsöAf]|~Á4´&?er¥ÇyôÝËØt6¶Òeæ÷¼äéïS.å.4Lˆtvùö˜µ¬·.ï3xƒLuǾÓ# z@ŸÆ« aî9P®^Ì¿ÞïÑg”úW]Ä),„øâ‹/þþ¸1<=‰Û8ÌïÞë9Ëñ‹VótP*×%,t£l¨šV]ƒ…> KNÿ7'w½0íKiæPî•üRý¹¦íX.¿qp, ~s †5[ÉÆ…‚ †P/_òs‚g"挀ÍÃ:üCLÎî•‚l˜‘ Ïò`Kþ²ëŸöþ<³D!ty†Æ]zãv1§Ç`Ó3ò‰Äì9’ÏuyÅL.0Æý,ÂJ ‘<O&âéxÔ¯·õP˜¼w³QÏRÑ€ÏC€zBñë"F×h"èõ’ l+›yž1ÈôDR øüJ N$IK“© ¢„¢É„ #SØö‡ƒáX<Ghp§ßÙåœÕë`õ´GÉ!t:+re“ oˆÂˆ”H&“±4º{(à ÆRét9@<àùªbuNÀÆ£¡ØcØxÞ&Âþíâó».?eTuEèq}·ÌÛk’ä[¯¨ÌèS‰]<‹ûäUõ”0Ö ƒ«S†ß_/Hbs]Ža@TÙ™|Åv½f)É6ô# çMz|ÿ:ó·‹©p@‰|ë¿û»¿ð€CŠ«ɪ Ùì¸Ëºl½µ³Ý¬Õ@ºQ5hz‰!Z½d”Š…êibˆSÄ$]ÊÙ2ýÎL!ËY@&çóg E¥¬êϯOx/vÁ nHü™ycÎc7c滟±60>#][ây—ŽACDŒå,?¹PJα;-7õx_Î]výÓÞŸ€äÚ@ ww¹C¼ h 0ÜtJ¾XÈ8rŒÃbi$Iþ–x€Ž‰hÔOÞy<‡CáX’"m%ØÒŒ0¥ïõº•\¾Ÿ,@šÂîHÀ«$#ñþÃ&§ÏSØb4f`ÉZÙ¾ˆ‚A2”¬SêNj¡ˆô5$K %J ˆÆÈ4Ä1p‡|´xÒx:¡€1ç¹±¾Oñ*§PhIù~:H¥`‚0>DdBb)ÓÓó‡œÎIâ˜N‡tÄ1}æbât‘ Îïºü\zðóé»Wù»&ÑükÿÆþÿvAð,î³N^Y3L ªr:§¨–ÔHöºûÖ;ÀŒty“š²3Ô ”Š ¬¾¹×(š¸çó¯Kj®}ñ¯¿ˆƒ¯¿ ÿýƒüÉ]9ÈŽÈÁÀ’Ô5ô *F½µ]¯²â3!/E¥:¨¡šZ³R+r pšê$5Y¿‹ÒSPôØøÍ Ÿó€ŸM crmÄ`W̰-giÇØ`ƒ", °Z®Y¢q’žÌe-+s¬KŽn.ï1$t“sí±µŸq×n hžÑâÔõ¯¼ræú§¾ÿ‚ó°˜Ðï~ö¹4cÒ~ÃÐvç§å°5¼ß0^`~Ÿl # Nç’q$-$P~¤¢äŒƒ(ý‘뎫UBá–ZO¤â:é£@_„¯×‰t üŽZ,‹$A¿×ç÷~ê%ÌB.'P¤‡¹a@Æ$"¤Áñdˆž!E ˜ˆRNOÅ¢›~A;¸ÓA>€cÕëwºñ`ÀãUÐyð(adü ›H§É„É$‚Ñ´ˆÆ¡p2ÑôÉQÇq‰ÉÃrJ!lìõ‘ ¸}ë1çwM~®8Ÿ¾»RcG£“û§2¯Äÿ­raðÜgݨëþYÌóŸ"?\‘#Öåôߪô-tEº{–é’š=R@àÉIþu°¬¢ó×;t‡èÑñ¯KþvÇñ_üüµ_Ü¥ÇÏ~ö³»Ÿ~òÁ½?ÿ+:©ƒ!Î[!dª C¡  Ù`ÿÏ‚€J½g7õ¦¡WkeŠе“ä'ÉI¯f)²+`é—1)òä}Tfÿ#ÿ?c ©ü<õ"ñu¡ëØveºL•1=Ï›9«ø|ޱøÉR7¼"0G×SNÎ眞Ïe„ñ#5^]ΰ³×?Ýýù1e*ƒñb÷Áƒ’šƒ€ökZ©²{J¦QfZŒÆ¼]<á^Ï cµ& êïé\ˆD(N™z,T¼`Œ²öh¬U®' ]ÔEc§ǘ¾ÁN&ÓQLn–U•¢Ø(yhÌe€Ê\ì9+›ŠÆü´½Á /JN;Æ#±d*ÐmãqÊà22"NéêE.X^É[ý½>âpójd’üAºÛúzüóÝO~ô×ùgù#p)vp]˜êj¯¢·êZ§W]EeµaµŒf‹ÅÕÎuí=ô zr+KÆ+—½êRî¹µ•Ëz ù«[¹{þL¾X,jè¡»/ígl½Ž lÄu@®•Áù3ÿˆôÑB‚„ó¤îHŽ  `·¹r4{qžçvºõcY©Ÿ­6våõÀ ï¾Â׿râú§»?H:Ç“Y»Ý¦ø¿”Wè…ìƒb–ôÎUK9&ü€õµ^²-3ž$¡Ù8gÆŸ ³ŒbÖT$(‘ÌHÿIÁ“ÉH*ö|J8§G‹²Ô*ô_4´D" ù°³¤ü ôßËåó%úØ¢áb˹÷2[W·2[Ïg³éx¯§tû©¾¶Ìh$AÖ œ E“éX0J·M…_­ÀTœô?€©#ëÎrY yÏìÝAdžH¦"~å9²Ao–#!`Èe(¯ú§’©P€´=àGëî4}¼‹É¾Î1}üêüвöèïXwÐ [žßu¹(œÃ|>}·N®[Žðä{Y×Ó/j>‹ûœ6Å3ôà&ãt›v·#µhùüí}猋¿`q¶äö.%cÖÉÂŒ=æ_w,ù×ûGüëKþvÒÿDô_Ý¿û·~úÓ~øÅÝ~øÿûŸÿu\.X"‡Àl3j•’ÚÚÙÞ®-#ttŠš-}»ŠwD5ꎎ?@K’Á FC“w²ÙGu"Èú?ø X.WfLj‹(›ý&ªjhýaøuÎ;8Øšc®[hä˜“à‰¬L'LÏ'ûòîî£&Çó»h˜A{¹—0‘M…p1f<º3?¾~ÅB׿òÊÑõO{NÝÁMr£ÝÞÍgÕŸ×ð¾å·0ìd\K9¦$—ÏTNO‘;úÄsS†§ø ðóþ0I«è°GB‰„ˆGÀÚ¥¯-Ý¢^' P×S ÔÞƒ”{|¡$}­(ȹP|E0s»—”Šå³%©sÒqRFRø¹ðX<éP8–¦^‰DâiŠæc¤¾ŠÇëQüA«Ë¨ÿpPîžÅŽSÉpˆ²PXøCñX<™¤´!JÄÃAºG(N!)RQO0Ð (`„¸N´Gþ çU²Ÿt «ók ‡tÀ)ΧˆÿÕ£ó».…s"€óé»+`ñ©D!Ñ@o£¯5]} šï³ºÏiP8cú0ƒ}©•cJÌ”ÎþІ kVkr´cÌN§{@z¿ÿ*…&ÏÚtÍþÞ~‡³²#þu—éF‡Ìäbv;¯bˆ[ò·÷{"‘øãÿóÿþä=JÞ~øÓúéÝîÿÕ_¼w/ÛðÀº]£jh…V³V«ÈÀªPnéüMÍPu£Îu€Zw¯{"„ëÉÅ- ÑîdÍÌÕ òOI@<øŠuUf¹ Ô\,GþxíZSfºFCõ0ôç28Àº ƒd˜ù=ttÄ{z¼¼7fÈNŸÇ¼Ã‡)Ú1Oò±ÂŽ®?& }øÑõOp„·Œ¬”UòéQKZ–,çK×^K9‡äÕü`Љ}Àƒ çä ð$òzeì1«•…ˆÅƒþÅÔÑH(B¡y\×[冨ˆjµ.ôJ:™ŒE)•§€ßçUèÇb!e `¹÷ [ž\¥°òy2%É~À‹¥+*"‰°ß >œ¡h*JÅ"‘dŠœ¤ÃïA?Œ5™¢’žîwl×$K‘NÄ¢W”X4 E"1T&Ȥè¾áP$ŽQH@v$•R¾ Eÿ.Ã…ô`IúÎfWèïv·w&…+úJ3Ÿßu¹ÈŸœOß][j²dúo—¾ À3¸ÏipŠ8[‚@© QQ nýwä. ŠþÙþº¼×±² ÞESÐíw;Œ\¶k<Å¿>ÀúÀ€Ú¶]—ñ,ÉßÞÿñÛ¿øŸþÕý»ÿôÙÝ·~ñðŸüðýtL8CghÙ;Ãúv«T.ƒý«¹ŠªU]&?øVµªéeú… P¬AáŠ8Xe´-“§ €–;C¾oQª|ÕÙê ÑG„ÄmŠxèb]Nºuà’0l12`r_†Ûo+þu»xæGº``aÂ×vŽUò·Ûâµ·þö¯?ý³ï>ü»Ïaþ…B€¿üôS‘ˆ¢wZõ¦VÓÔV³ÁÅ¿å£ è»Û ãÞn6ê:?Z½læ¨cgrŽ•ë»™}'W eæ­«Ïã,’*Ê:7û0ü*+sc¾›cÖŽƒþÙx²à›‘¯EG=rÌ2óæ „åìþˆ÷„ÇrOÂ1äA­&Ê £ý¨( ä~|ý‘ ptýÓÞI~»Ý¾…²ŸQ© ö‡úWÃ×¾þ?¿xíEI#6žÈñ‚¿s¦òÁÔÏ\.b’-@"ðûü˜ŽŽµZ55– ƒÑ4ºö‰¸Q5ÑÒ´–0è‹j­ÜL"ˆ†a”äü>Åǘ‹`]Ë v˜Þü¬MZ›è½–’ KȤâ=º¤ß#åUúèäYÉ©v:O§DØë 6ý!ß¾bb—Çzü0ɳÃJD"A_8¦ø?&ïF~? G¢IÊ"’!Œ‹Tœb ŠoÉûsƒË¥c²×ßcDûÁ‰6òêüšý!f],ºÀÜGì l Àˆ¬ÉE¾xn p}÷’å¯"{CþL³¿0xêûœ2Åü°Õé J¼ L9hÑßß³»nÖ¹š]—›vï CïF;B-˜<£…ÏeÄÿúÐrKÎň?ó¯è”üí–øôGŸþ9ýú›»ÿùÝoýôó¹ûé§ŸÞûPÄÅÀv‡ÍæÎ6¹ûF¥†9À:EB¯Ñ/¡ËÖö¿oÿê×õj#B:ú[ôÑe:VNjd3Vaò<×á,4Ú+ç)dr0húDrýbɇ÷뾘qð\›3%­®$ÕÑ.× ¦ NÐÑqC9{8r ¤®pQxB¬Fh$ ¨±‹^]ûúâÈ€;ðèú§¼ÿd2ƒöïÊÎiIÓûG"×¾ñõ®]{éã@|Â\¾àäšã[l&K$Æd"@ʧL)óßníhñx4A®?™J$jÛ¤õõúŽjþS ÔZˉš%ô¤Ï>6/rË·™À#ú_ÕÊEJÝ“ñ¾b)¶Oã~ñ˜©ô•0FøÂ˜æÃH1ÒøX*.’Ao`?àÝ‹ô½>UTë›{¯RðýO Rü`(˜ŒDxê7%âáP8‹Å¢d‘Òd¢‘4—/¾&ÂxÄ…òRYÕë’;·§Éäùådµ'ƒ¦D³Žÿ´\”råsR€óè»™ãGúnôF–ýE“€Ïâ>' @9W:iò¹­’è[Ïçzý|\Š&Æ¡?g-kokÐÉv ùkr+ëáú߬Ù[<þÃ;ÚÀh4ÑaYñ¯’+¸ŽŒµú»mwVüíâ/?ýóO>ýÛ¿¹ûãwÿègÿü³ïݽÿÃ÷?&à`#à7ZÛ­:wÿ„V)S–³,è­ß|ùË_~ÙÄ–P­¦Ñ¿¸åÙïf=Ù«rTÓÊS ç#gbýá¿&à÷è_ž¥  ¬1ñ=ògÝ€óóL̘wïoêÀyÀ0fàÀ¤ {ÜÙLòÎ3´{€Óázæó1óOŒìÇ”Ëõ¼K?^^ûÆíöü8xåøú§¼ÿdÒ¾½Òþ’tþ_\{á/^{é¥ Æô•T!@>Àº¯¢Î0Á†1D²™ŠAEÇÂÍ– w™ÂiÌåÄʺh‰f];å:,@UÔJͺZ5¸1†I!C!O!Ï `õlea#§5Eú˜0•^€¾L Š,b”I8Étfú“éH:™JÅüû>¯ðûCA Ü“£êXËïtÿ§E,ÊíGpY‚g†Ì‡²ˆDIùYÿéG)/"ê÷vÝùw9JŽªž‹`‹™¾FÉ—ç—GÉ{]Ôû™Ë˜±‡:ër¡eóg»çÒw“s%_§Ä•uÂèE)À³¸ÏIÏžlfòWóEœL¿›³PéèìgÙ¾•Éföò[y7g[ùuyn¿cXYà0P˜Ö,Þ÷Ý=‚½Á1ÿzŸôž\ÿa’úºû’ùÛ»®xïÓ¿þô£?¼ûÙ|÷ÍŸ½}÷ã{?¼ÿ‘H Ë­7·«¿Ö+ì` –Tɨ«Àhýû—¿úå¯~õeµòå—_EµØ"'?C¿ÙÏÒÙ ý·²2èÜ¢?ö d=[…ÜÕ«ÙB¡¤M°ã2br»97Å/ŸûïóÙô¨¿`Vl8ÈfFr<ŽÉµxˆƒ1pÃßÅùæ_ðÂ>Wæà_¡\ ñæò;¾uûV»}óæxtD~týÓÞÞ¾¹khl&9ó¯V‘û_{³Í³—^bˆÏ£3q×|ÆÏ‚Û-§¼}„ÑÃQ2 Sæž'âÍÛÖHÇ(ø/—EClo‹Š!¶ÕG¢Ôª4 ˜¯¢gUÉPüÉemeùsá,ð ä.U‘H&cñ®Òí)V±^,ÑšƒxÝ;‘ǵ'é÷t* yoϧ(¡NHéÊe5Tïœ47üÈÑÇ!z¤éçS©´ˆ=~¯;”KÐȦ¤âÙˆ:äýWËdXsé1Õ…Ä÷ËdËó»\&söxص1¤».•ÒÖYp.}·&÷ÍõH¥\ÖèoQKy¬?‹ûœ4[¥Ê {>[Ê‹Öd2ý\¯ßÍNͼð›¬\'³o­Ës¹é>Y Cm ö±zo’•qDNò¯ÒO ]Ò~<\Ù=ÅNÌß.þöÓ÷ïßÿðîO~üÙÝÿõõ·?ýø¯QH‰®²³]©VzC¯ ͯÕ$U½¤«Ë Tný;Y€_ÿêßý›_ý¿¿ú@×Élñ:gž³ŸËgM´ýåºÙ^_‚ÜV›RùBA%ÏŽ…Úå~=tjÆì¿gúgò^g$p°ó;O2UÕéCŽÅ,¿ÒõÌ0<¶Pz ÓNÈ£SpHFIý“ðÚ‰D4¡äÝïï+Þ@, ˜r]Á GR©… "ˆF£ðþé„E¼oÅh!ÒÏÄÓ"îó&R‰?Jâ€KÚH&† 3Q¬>Z'?y~å:¹, ,¬×Gáá´œ”´H±ôZð\úîX”¼uT“û½¼èK‰Vj®?õ}Ž @~«xr0óµ­R)+®ÞÛÊQ ”Ý»jmõº¤ö3kç²W z®Ù̺ü‘' hð½lÖÅgᔡË`<(t¬3üëîж@¸„ÿ-úݺ=סäéý÷þâ½ÿvÿã»÷<¸ûŸîþí§Ÿ~úÞ}2üšR"ÿߨÑù­‘hÉM€¥0ŒUà7¿ùͯ¾üò—_þú—¿ü%×2™^6Û±èÈ‘ïÏä3 äØûäòô»/“Ïu²\.çÕ‚†\—”bÆÓï|yýÓÞ R}IeßÿÒ‹/|ã…_’³#¹Û*ÀT2~È Ë–#*âù€ŽÒÏ%ѰJäcÑúN:‘N4Õ%c ôýªØ¡ÿ´Z‹3€F¥¤Õ‹ˆ² õVè~ŽÉx²Ù%û2™rI$D’Âx¥ß§zý¤H¤»Š¶¬P"†b],šŽ£û¼¨v ‚èð'â!ŸBZÖ.š”>¤Q1H%âJ JvCÃODƒ^ߦŸ8I$° ˜N†7É|$1sÐé XB],Q§eN_Yp±øãîÛgη ÇŒ,ó´8—¾y;eOŒé’¼%ÐÇE]€gpŸ#½š«œ0à3Pæj'×íæ1§éÓÏez9¬ö"lÛëƒ6kMÎëO&ãR¨ÐÙÃÄ?@CùÄTй\®…ùÞ!e6åŽsè Áx>ñê?>øü!ýùþ½{÷"ô§U¯P$Y«V[Û¤ý:ˆŠú·…*# ¾üõo~ åÿÕ¯¿üÕ—†Þêôy…¼;½Þ‹6†ý_¾°{M†ûÐ]i6¨¸Z½ªaÏàó‘üA,6Êf2z.´Š¾Ù%# P ärä# À²|a@¡`™šþ,“F£@Ë“”á||0)Ë¡®Œ>§¥ 2þb-ˆÄ³t:“ÐÓy£ ÿ“À ŸÕ Í·È¢C“]EŠìjL²«‡)åg)-Ñîº8€þaýy}{è^ùn ð2ÇñÝíɃÃý±a '¸ÏÆÈ3öoì¿ €Â _!“BAùÐnwG¯ÿôš¯N^l"€ºŽeùë?ýáëÿÿøÓ·_ýMûµ×ªÍÚû®®o/qPð¿Eé?qÕœAc#þIÁ¯Å‚õÙc¿°NÕ1†‘°¦8rÄGËmγf2§ôy>Éž±üúú÷½?fw×?ý?ù¨ûÍ®EºHÿÉÒuC@²Ž-¶ÖñïüάX…¼®é9 ^[/^ضä'½–O àè£JååaEuhìn?“E³ïÇ©—/¶ÝD‰WÂk±êšD`Wm„éa!ÈjYG,½€3ZBûT60Šð†%!{©L¯Y’Ⱦ é™TV/—üTœá瞤ŸrJ•,Éø22ºŽ:Ùô³D2!þ%“OQ,•ËEÉ"’É¡Žv#Ô'dNt‹sü©,ö/f‚†îu Ù‡µçµ­.@\~´Úa3†7z¤ò°ó0ÛB¿ËŠòùÇ€@OpŸØÈÚ7Ã@°ÿµIÚ€ÐëhÔåøl‚<§^óãÖMmw½QõÀêþtFÿ·Yö¡õ 9·‡ô×%z:¿˜Œ/ÂIxŽ/¢J¦ò*ãJåbìõŽíŠY)t‰'ÑÖëv»‡¯_ûúääp¬*èJóm·ƒ€¿óM÷£?|û§opúÿñOü¦o¿>@Ž)Ï÷¥„ÿM 6¿Tº¿­š[o5¿lÖ"µ¶ÿ¤ÚýJÚ"Æ&I&s©z…ÎòlPn‚'“„¬´“,¥²)¥of¤ [“èg͘Å) íì"f«H}(±Ø\ÿîãß¼}ûé›O?Ù¹þ}ïÑõÿþþXS÷]Åñý‹…2÷Y¼¾œn­c P.y'öoZ†ßzÞzñêåËÔe_Ú'ö‹Wˆúa÷}Ôñ:hú§Ý¨·;ÏZ‰W/_ôlÙ@hþÓý*ÝÕ*JœØ†£¥2YO7$ÉGA@w´ÀÏ£egL*A¼V¹báƒYDÓ5í,W6ý¤¼A[︑W´ôWJÅBRÓó¹S¡ŒóDR\@F×’é\&o-´ô´–þ@÷ŠEÏu1Þ7áõè†ðÚ´@ûáý owÓ€]»öaí–x :狀rò|v÷Ö4 ôÁ•8è$§ª´M4mj¿©>o4nÀ·×åMj˜ÇN¬Àc üÓóXÓ_÷ýó(b5àb|9¹”$/YÁ¼Àd‚J¾Ò–ºƒV¿%í•úÓ·/¾>>þš5»ßØ•ãoÿp|tü‡ã¯þðÇoþô§¯ÿøí×üëõk?®27Z‰f€áßjO¨ _­~Y«&6)g~æŠi“¤H·çj~®t­Ñ¸ê’.e9Lä*¶ôæ¦OI2'ZOò÷9q9Ó#ÏÐ93òН;¿¾^ÀÏÞ¾ùøgŸn_ÿÞ÷Ç??A±A~„Ÿþä§3Ä fs¥,H³¢E.!ï²µŽÛ/çïV›…|Æ4­“W¶}øòå‹£Wâz½—/_UPx=8©Ä-1ÂT*#[¥ÙþàÇ­vûåË”¸€Z«Ö6³zC)¯²KÓ““]Îa_Ïè®—\D–øƒÀÍdCLu|n2 ÖÈ2Khæç 9Éèä°løzþF¸¦¬Þ¹XÔ´Œ–Ã(±¤° d K¾ žCË[ )Ìé)Ïå—)9á¡ €-ù#J^€7ì=ºCçÎþ¦hwúV¯À÷}=äžä>trà÷å)¯ì?V¾ÉaX³ù!¿|XÏ%~kÕàî¬Ë7\ÕCPvRŠé º œÂ €„õýuwl[¹gúUªVOˆïMÔ¯Ív½× ä€N¹Aöâüt=Œbä'&°ûÀAE ,#g– iZê¬\XWI×}Tþ—Íl&Ͳ‰ +#Ÿ×¼–Ã$p6“Ëæ´œ!@¾I—¤Cs©âÝ ø½"̵#vÇcùÿãû×v×c>€–]ýpã¾ÿë~ð4÷¡ø°j·nø`ÿ @íR ç{½ñ¼¹™žãðÆÎ:ås"É"ª2:®¢I RªKñÆ=úëØ¿/J  U&—ò //¼Š.€^éõ{­^¿}x<ðÄÒÿøÇ?}#ÿ«ß¼¾ùöÛ¯ÿ(vÿÍ¿}- ß¼ï0~=vF¾<Ø (‰ÿ_òñk˜A ÏÇÿXW)Àœö?g²Í]L¡äö B 0gbɲ£”7[.ëéh¹aŽ`µZĬ`Ÿ@¨»IJz]*—à Óº "4CåR‰ÿ„% @’‰Œ—ušV Ç×âµ@ J’Kè™\Þ*@U R4²9Ì#Ò©,xF¬b!«L3/1@ÎËŽRìÿcˆÅø»EPï´>dó’R~ÏþÝ]ß‚4ÄÔ:pÿ–×}à‰îSovjbÿkBÃöØ¿Bp'Ü—„áùõô\mwór¨F^¬ËLfh¹gä Û§¿TõÅ…+öÿA¡’¨\N¢ËñÅx\±r•“JªÒîv[íÃÁÀ‚³?}¸ãðßxüf£ï|ó­ÿÍ·ão¾ ¿…‰÷-E"<Ê;׫.ðü7Ó5GÂþ/·žÿÿi¶›6ñLz§,®ççŠÓu„ÖQ2SU¦ø"Ô³‰X+BÎ48€O½5ÒjRù¬c1…·A¡„¾ÑMXm®\ÿÍqov®ïû#·!ë¯üd˜óÇÎ~ì9®Kƒw×åì§øÀH"ïþî8€Wp‡öáÀîö»»×î3úïà±¹t6“ÉIÄÖ3õZJ<Àijg´*ùd*%¶¤Œx9>‚fÝGÜÀ"µƒ:šœŸ_ŒMû²iÈé–.héôÐ(œ=ó¼òF¾>_ ¿`rF:“`¡T, #®ϥ2¹BmB#Ÿ± y3­ùQ€ÑpÊæBNsWL<”x|ÿî®_35ìÚ‡­æ÷MÛo^?”)ØЇª^Õ™€V­Fj G…þ7M è°a¬ˆòV¤=€²¦µ"â`kLU ÍMËSfÇÌy¥†r¾ûú[y½yóöÓŸ}òî{^¿ïùÀïd¥BWv$WÀbJ1Иâ £ŠüE`:ªÍßá…7@£qñîÝk:ºÀÑÛÛ–œ÷¨÷ªRéöŽe˽31)€ ’Œ¿yÕNHðAóªRʧSϵªŠ.ºgÿøþ˜LPðHŸ›bÊâ*–)§zd™9@rys˜L Mƒ _ô\9â³¹¬)Ž''®=«ÍŠW0 …¼‘Lè¹<ʉˆ $(pÒyÙ6É,i-ÏÀ|årŠ=>Ç<Œö!œå´Px=-käAŒ'¾žç ¿¡“ày÷ߟhvŸËù‹°^ëݦk 7Vÿ}£‘JA(Oâc¸kâ¸ÀâN(×lé€ít„ØÕš…þÈÅ?ò›BHþ½pèñC¨ Gù ×//ñä|B[ì¿k÷zG˜E„(£ïŽüÿD,ÅÞ Ánî_ ª$hÑ}ª~ÆfµŽþ…<û•üÿJ’PÚ?ó~‚|UŸíÀ)YòpÒÏT/n±ÑßžQ‡k©Ù‡'b€,a€ÖÄšœˆ~àõ}χ †8NüÆ ¾8u˜ÇØÉ0ÞP… P´‡”ËÄþá$à 3Ø8€W'½ÞÀîô$9=ÈV:îu»8€wrJËyk ¥eeµ,éÜ®XYùR3AâÃ=ûgìŽÅö¡8/"èÝ xå_ 9ÛÍT*=´ Œy–áøý“I-%Ù¿‘7M]—÷.cxPÓ²FÒ’D"Ÿ“ÀÃ,bv¡\2µ¬YÈkºájîa¬-qÍü~];$´˜ž¨i!ÿzZè¶J®$ ™ê¨Ófßâ¬ÛÏ«âø·¼îôxšût«ÏíúmNÀÚ6'`Kr6TÎаm6S¿g-½¥ô3ª¤Ñ®£²£Òè&´uš£:ZþÁç#—'2ªå?ÀË&ÏïZD¹¬¤~T9ŸÄëáä%þÛ>î·íÞáÑQσ /Œ_ò ‰ß¼¹?p[÷G±ªŽò%Pô‰ÚƒÏ*¤iåé[â`ˆ÷]mÐïkêã®Ô80x?Q'ãkc_S%¾‡nàš}‚ð1Ï)øI. ìýàëûž¬¢œ$X±gspÌy©$ÀÀt„*€Í`m`5 ¹ø<À|õN½^¿ºvâº]1ÿ£ÞQç¸ûâ¤sû¯ÈwZb§E ª`©$Šþöñ›‹`FKåÚzF‡$Û•„÷íq$üäåå¥Y11Æ[,—ˆdúeËÒŸ9ºòAÚÑYë«T\-‘Jò£l¸©‘eb 0+Yˆ™ÔÊ%«I%rÉLÊ‹™´U,åŒBà¦4 •ëSðC#\މ‡!7gÁ.ë¹#w2¢F¦…¨H9J Ô‡8É1 4ª„3n“‚v›Ï%wo~ïê}õÞ"àݧû¼Ù½M Úhv¶JåJ$[ Z¹lÝJNÓ’†ñ@!ÁÊ%&V;øÜ ‡ò¥ì ¦uð  öwm£àsœÈo\­A/ ò ¼_ƒã#ÿèÖï}:ò…Çâë úÁÎÖýqþopŠWÕZ~p Cÿ\@ìvQÞç`.¸tE“mî#¶‹ûìk4ÐCk_VA5Ús3œ¸H½çä6W©kJ,þƒ¯ï{¾ÉÎW ýÑç‚•3£›0Whbý˜Ì•JðšÐgtæ<÷×*X# .àÕáñ‘=è¾èõN=ò®ÞÉA],àøÕSYÙjõ«f«ÑÁ°~> ºÿt:¡å“©À=ûÇõÅþ/áÆç—8÷Ë”ø òùÈéÒÜQ¶\ PÛ– ÀKœ\¥lôdX.êi#Ÿ.¹gÏ´Š¥§u+õãT:Ëy`ÉM2®¸É,ülò™LNOáüq°)*¹‘7Év ý3Á؇xùJg‘ ü(–κíZVïÿì{¿îï<Í}šÖ–Í»±åzÛ€šØxÁt:ðã’pP®æ6” ›~=lçð¤øã„$4B|ïóð(ðPÊÝuñ#¡·©½ ͺk…áZ÷\? O£ƒˆ$ µ&Ÿç•@4HÔÍ6æc2°mLÁOänò‚ È…Ód˜lǃ‰K±b#^fpN\.ÿƒüœ,ÙÏã’üœLÝ‹~}Ïó­c>ó™*hÌ)4@ÙrþRðoNÂcžüˆ!Jà p Ðå,–0ýÕÀk8I^)pòª3@âß=î¿êuíŽ=8"{Ê»´s@ø7›½AsÁ&¸½%)Ð+f&•Lêùb!ÀÝýãºQtyy>q.å@¸41Öy€balI_(˜bźV(”-ñ$’Qø™¬ã$µÑYzx&Y¾éjiÌ çJ•|JO¥ò…t>§¥% (X™ÔH%‹EI 52Š "Éjš> ƒÓSÏs&ÇÇç~ˆz^$ÉHà»#'ŒÃóÇE^‹A÷¡xo r´%tã‡òÙÛêÀ7C<ƒ~’^röaÞ&¤W¾Ê~ ðú°½Þ£Ã@ï}ŸÖÁ¶:pËÞvýëWìºín›µ>ÕF¯þYq[µ© \:˜ÕëÍsÿsI˜ˆ Ò€NäðûSÜYWÃàEˆ†T²ؾïzy>ç4Àq¾%Îä¡5B˜À$´L¯/ÿÇÔ ÞsêßDŽ\òÿQ$wJÞ-*m°®6x¦RlÒ±|0[SEiôœ#q‹Îü_ß÷|¨L9컀AóNëXÝcAά’nÿ€IÈaÌæ4âl¬èèÔÿºÇ½£žœÿ}ÔCEðpp‚‘„õ›ù¼ÏgrÙN£-ò°o•MSO'“i½X12º˜°™ËÉÇswÿÞE±üw9¹¼T$–$€YÉW±Ñ´4X¿¬\VKhÙ¢ákÙô™žÑµ¡ “ΦÄ1 N=Ëc8gf2â1 a,¹B¦¡£Pø •Í›a˜¯¥ôSŸáÇäh0¾<Ž#9í‡ÎxŒ úÁ©l:oäFÀ ³g!‹õ‚3à‘å„K°ào«×6†kSÔ§o ºÝ¾!v +.p޵×/ Žh² ó.ØÝGfžâ>­ZÿQyðýwÔWkÛîöä¤lrr® €3¬)%¡€Ø`(žÃ¦3:w!àëS¢M¢9Ös‚»ãÀ{Æ)w×ãqOGBŠÍÈÖDlyÙb¯6ܹ>ª×ó›FÐ8PϘHÔk©+Ô$‹AS ¡õä7…~þÊf ÛiLL’-PƒMÕPZg¤ãþ<˜C/ ˜`¢ED>‹Ëö Òh(T19ü~Ðõ}χ2> ˜Îq®SÞL:MYYDN°¢èßL!9HÑ0E.º±~y}ôú– è¾°_`&è£È?ŽOŠY ¬‚]J Ùíôób‚f>Mû‡|.•~¦çræ}ûGNóñ$º¸8sT±TªP+¬dâ ð{æÒbß¹S!/>%#ëžXð0 ® 9÷MËðry£RΦu=gVÊ™|>›5KPÊé™2Ù <@ÁÐPŠ0%0=ðÒšÆŒÞ £££ãKjQzž7ôY`sÎo4Ä6Dæ?Ây …ƒ¶á(ÜŽj×sü¶âîêõÔ G÷ûÔó’?1ÅoôĤAîó(À{ß§]³u»úï²Sl‰/º-ÀÕ.+çHÿå?ª$x••Æ0hºçþäs—R‰¯õÖ¿'¡Âîº"|ð&qŠ…0l¶ï Žö!NÄ__/W²Õô¤Á.`âŸåßþ¹Õh\á+ÕF ?ñ.¨…ÃNð÷Z…И³_(ÙmæÜË9•s97J`¶R]vÈqs°fͱÞ9gt¨¢³PøÚµ’×ýa×÷>ß’'Ô lœ+—`WòóUB‡fœ Bè³ &åBgðëÕMðú£Wʼ`Ÿô_~ôúåKØð‚‰ ™ÅP¸œJFÙÉg¡Ë—À=™ÒôL^²ù¼äã©l›ŸÐýF²m.Æ—c”M–íJVÉœø¡Y–¼Ý,gä>š‘ÍK†/‡=˜@6ÇX ±Q» d¼í^ÛÎñd·{†Øðc)Àܧßl=*¾­ÿŽÙêÇËýº,ÿWñÿÞ™VKpàÕ_¢ëa-8w>‡ÖšCŽ5Ìj»Á÷%UÜ]W¤r¼«6ëH·¹@*µ´£hs=$Þ¾{â²Æo¨Ô W”g¦ M£ÝéÈpý) -kßÀÍ‘÷B„‡Á˜%4¹—³¸+ÀoÄÒrePDâ(b.#uJ—¾Ä:³%H{àõ}ÏA ˜ žѾm>ßE,zÈ<ˆí€•Ê0b 1’q4(ÀGp*øjÍGv÷°G•;Îbf1´+g³JÁ¼;ù,•1$Og%@:ŸM'’Z ÙÎþõ¶18:_\嬆 €ZpEK,5½ Ÿ6/KçV!—ašFÁ2uy]×!Z¤4MC—дÌt:““u3“ÈéyÃ’ð#… C#›Ê¤SZ"¿ä:r}>ðågzÞi/Ï/'ýC =Æç†ž{£¿ˆÀ(á¿'‚3ô½Q€² ¤;@cË4:7l¾Ô|©Ý‰è}‡ˆ|sâ8%˶ ¶W”¿³¿ï}ºÆ£`Kÿ}>[]ëÇ#h7‰à®ÖžWWÅ,GÓsÂj£>–h;üÜ ]ÿ\’ú³SpEÐ ýž´Ê»ëŠöÙÝ­” “DaÀÊ?®ön!ó ‘×F Bóï@òþ@˜n²ë/æ ñвº$úU`³U£5( 0å( ©£Q‚d¸‰9±8˜¢Ÿ­6ú sôÓÕ@ÁŠ ÛëüÐëûŸOÝfI·ºç03 —²¸þ|—8ñW i„‘â)-“ )š1ÉV+F´þ$ó‡Të¡Ý;”®jŠ’Ê ³Ø»wÃ2 rö'´Œ!Gp®/¹cåR‰Üóöþ‘ðo|~1¹ 1,Z岨½Xr±$@<Äžž.˜VÆ(M¯àH*P*ƒ¢!‘A2íxy¹}0S•œ–ÉåJ–•KËûfÉ4$4(C+HËCDP®‘ïß`Y™:§žë‡N8‰.$«¹Œ&ƒ£óÍËê± IDATc9f< !U-Ù€{ ˆeÂ,ç ªá¶èõ6džÆ Ÿí ˜¡Û¶bõ©×E_îåZþkLè)îÓìõ¶ÀánpKÿ]6Ãò–~¼DÓj²»Ç™@í¹Xš 'QÜØ‡˜á^ø}…v×)ü0ŠÔÀf8Väín0Dá?ŠbDáHnqNè{5T'PkÕ™\5˜­Ô®š-uøÛ û‘ÿƒPžõ„ÕÌøó’l¦Ö•8’ë)%‚ãI<ñU~0WÏLña:kE*n~þÚ~èõ}ϧðþkq Ì銕~Ò/É'¼ù|S¨Š3@0%Ã8†tKÆ…è^G¯^‘^N¢£cð‰­bf1T$p­ïÈãe@"PÏäè6 rüW@õoeô4¦Ë¶öÏÄ?‡bsröÂ\N.$ 3PÑÄßz”òC-}iÙr)2½‘ëù[(¡ùÒ\Pˆ¸i •C²ýLF× Ù¢¥k9­`ÀP4Œl!/Î)›Á¤`:›×s¾¤A ˜³‘ÉÙÍcVáøäÅÅ1Þ<‰XåÄäH’¿u»CS VÝ+ñž^/%ùeµÐ¤Ãï¬G?$ì]œÍ,å=Æ ø÷Ù•ì:€[úÝÖïÛÝn§ÙlÖ«˜Äÿ«5 Sî±Zwšá:cê4‰@ÛîûJ+í®ÇÒO.å[œ1@Þò-‘’ubÅ0D›óú~MˆÎÅËä¢kÕW@üôûÏ©ì;#žJ¸@Ï0åK°Þá'ÚaL—™+ÏT~É®›ÔÌ‹Õ켪ÌÑþ–·„¿—Ó']WàÎúÞç£`{oIÝ@Š«ÁGNÜþ|I=>åüÐ܈ð1w@‰#åaÄÄIÀ«×q,x þ¤ŠÓ[ÌbKè“ÊRv–3AéW‘œ\²€l*[)æwöOè˜O qyq~~qi‰y›¨÷QÐþ’¡éQÆ,‡å²a:é‘îŠo°Ì°Ö+(•L==)ˆY/ä èd¬‚DfÉ(>ÂÔÛ$܆_;€ÞÀ„†7<%Žnù÷I|û˜¦”/faÊ2zë<Å}v@ï뿺Üѧ&g‹35˜¨W«´Êˆ7ŒjàvFC×s#(/;ßW\qw]‰?‚£ncò Œ(àFݯÍõ?pêrI‹`ß+LüÖ¡w N¡ó·ï¡ÞµŠi 懭Ïf1^&N…úsò;~I¶ ZÁ÷ÈÃÁ ~m†+ê,æóØ6au(Ê-7úÞO´ÑÀ»ë?º€¨ó¯ã?ôFlC¹ÓíÏqÕ€fœ>ž£HUE>ŽpUq/ h•à‡ÿ`F}RÌMÜa›OÁÕ-9zóÁæ»wPî’(@Oÿ8UÈË>ÚÙ? ºˆÂ`,N <ø‚(°)w›p%Ë”3<ÊdÍrÅ0 z. ¼rÅÌžC ÌwÈ„|ïÌÌ‹¯( Ð7€A’ ¿X¬˜Ô?Hi™|ÎÛ°$– ’.øžæ­¼¦%ïd*ò“b:!P “ìJA>`<‘|%¼ í ?¶£ðò8Œýh,aú=òà’˜Ç….,³ßëÙÒONmØê±’ôdÿ ÐSÜgÛØ;êÀÍÊþ;ÇLïêǃ›¼Å‚Êkµj3 Ì6Ü`Tû­ºÁ¹œJàù·åÁ¿›¼ò†¸·øÐ€ŠäCqYø÷0Ž á"yÓ‘¸æ .ΡQ?˜€†ZœSBœ‰ª×[qîÝÛ¥*ñ“wF.°)뀬…áð'ÿ” ¸’Â%õÛãªÛ>S•öåf"—‘3¹xÐFGÁn­.|Òuˆ8Ÿqý³[ë?ßl—ugœXbn) ýxÇ;Ÿ/}Ë’HBb×d%&c ’ ˆ½‹ù/—¯/Ž_“}tv/³« ¥òLÌ6‡‰ª,쟙g M¢lkÿŒÃ¨9† ´'AÀ@€‹ór¹l%“Ã@Ðû+Y†5iù|ºŸ9×M¦SËtË(ºA&¨x1ºVÊŠe#S0ÅyäôT­ÀZZZO¥t=—·J&ÈF‹¤ K_÷-ÓMË.œÈ9?¯¥D®s ®°ñäå«ð$‚dðXüBè_\^öÏGG²Y‡n8†jµ[iÝ£l’Ëö \ ˆ¼{èÔ)e_–õ~uýG"€§¸Ï¶hß‘'ç õß9J¾¾G?¾ßµ®%`v¨59ÒUŰP¢î ~­þ¹‡jæ©¡­„¿PÛ‡|€˜îçÁçhå©l~ï:‚6ÂÌG@\á»'n(¡EÜÙJ @GÆ ÕëW#l¬Z¢ÑÄÈ¿œþ8ï$áZ‚ø‹Âר’-löÌ”â.‹ hƒ0dàœí ykbrÔq¦~ Í)ß§úòsvßW±¦à®oDƒdý³Ï®×÷=_<°˜Òá¡¿» ‚0#u8œ»Ÿ/ú˜𢀨@<Ê‚©K ‘ /wó ¤‡ÇÀfš‰Å²˜'™D•rÞ.äJI-•EAikÿ¸NjÜé:¦Ñ` ž_ êå’Y0€FRÏz‰¢Ÿ¾ŸÖ„ ¯R4\=¨£èèšWÈWÊÙœ!ž£¨çó&B ˆƒè‰dBOgrô¨&ZØÀÐ=Ï0²®éçtP<Ì  ÇïzãÑðìDá“ðå8’Ã:Wræ£u&1êù_xJb°Òº'Pj^ÙÞF¶2žÝ>‚RRøÃ€Õ7bûGºOpŸmкÏ(ýwÌŽ!ž¼G?ÞÎôÚ­VýY“Á1Ý(†6°Û ˜|…€TËQ*tx=€P®ºŸC¹ôP½E¬Rˆy)ŽOâ ±_¢ˆŽß‚ñŒ³õ¨³Ž ˆoQ6r†y4‘x±má®s5cŒ€pÎéqxoödë7ªAÓÏäŸÍúÞ盪i!B}øSÍõÙŒ£„Ëû>_¡ÀŸH‰4 …¬,Œ$A%G—\­b›²ÀÇâj¾`Ms†¬Ý•ƒ¤µ½$Wk6{—˜º$`rQB³{ 4Ì´ˆ³#I Šùr©7óA:™öŠ•r86dž©1x–á¥Ó…\¹’-”Ê¥’‘Ï1 ,§}1ŸNkéd*+Lˆ‰Y–’-AÆ4‡n!ïP"H¢þñ؆#g"ŽAuwìt!¹€[(«d@cB@¨Jóž`Ð뢃/vÚSZïÇýü|Ð(‰ßd>qOpŸm°¥\ïÀ  ¤æÌ`Ó{õãíB bÔ®öü  îýÀ‰ªµÈ©6Àíû u¤ "‰îƒ pB¤‚‘bܳKW³>(ú×}¼8‚=¢ŠƒÇë1*n£Ùpµá uñä9'«MI”Òׂ&ƒmMÝ æ¦äú›«v RÈú}cW›zô¶¦<=Áȵ˜ÅY¶Ç`m+ê—È"Vdìæ ×o<€ã|v³¾ïùæd›*Ô#sv301õÏçKNqtà'§D±l‚_¦¦fJ§(…_<È,v½0[Ä"„Ð4ÐFC}wÿÔÇ^³“¹€~| p…rà— ±Ðrè¡(€Ÿ¹$Ãʹ<¤„S©”Øz¹hŒ’ãKf hš¤FJV9Ì0N$ƒX|ZK&SùT*í˜õÄM}D³àjZÖ*ºº;2{¢­„Ò³„ÿCotê:g šIæÿò…ÉžD‰Ð ü³Àúžã~~9•†}O `Чp‡‰rÀ»‡=Âwó,Ö!mï©ü½ow+>Å}¶€Ý¸#Ž—ó —ŸA9ö>ýxù!Û~«×™¾UsP«êu¯V êQÕõ= vˆÀ¼Îäb4º˜ £ ñ§ùЬWë>²ùpߺã`ÓA¼?ÂI?„VñAT¡¹% kâ-þ¤6Œ-ñ7ÔÅõ˜Kª­žÍ&˜‚ÄÀTÀuI¹%·*Zì>‰Š‚ž¡îJ)÷Åh°犊 Ðü©bàfdÁ¬QØ}5y;Ss:O¸~íÄ\¯ï{>¸(|†äüPð'¤ó!àཟᄅ*î¹>b©‚|ª PM|áŒ_h–²»êQó¢9>Ÿ„bü@DQÅ,@­ÀèܰPî7¬“r(ýf%+æªùš„óŠAÅ"Xÿƾ..I}©\ŠF Af¹TÉ%Sšö,M uᄸ"„GÌ,æ„,Ór´³Üé‘ÄÿbûÞ)@¿ggþÈ9s\GÂÔQt9ƾ¤Þ8HX"àÔ<7¬4Ûw@^©y¼DÂŽNšØ\E;%äÕ³)õ7@+¯÷Xð÷Ùríæ8é".‰£3v¿~|ßn‹@0Ñ ÐãŽZÿÿZ§ÙˆüºBœ9HÒ1àƒsÛéCPŸ¸p{îY÷FÁÐ÷‡§¡3©Gõêh„(ô ®ë….¯¯×8ú{Í߯¨qM]4Í&ˆ?z6JTJˆcopPý2ZE.M_ ¦d`W¨€¡û½&I„ÀDU „ÍèOyÄB1 <:n(Ç­Tq§%ðFó§Zÿôãõµp³¾çùæ Æ;‹ÑèõÏ–¤ Tºf÷¾QmµïúͰ=ÁœÌj‘+=ÈëvÏnµZ»û§YoJäݹ<ï^ p1)ºyVy…ü]’˜Ý×’Zƒ|EÐ…¦t ø'%#p¬’ìAÓKëf%µ@ñ@›`.f’ÚPKžæýdJ? ßP)å%,H?ÓÓ4ÝtΕ‡#ÊSÎÈsFþ©œÿ¾úˆEÓ±?‡>"Oyg€«zþÙØ÷*F÷n°›GäÞµcØ(0uèI ¨óÛï ä×CowMžâ>·@·Ñ¹íšj§Âï\MÆ¡ô€~<½7–nÎ)UOñi (Çq ‰~‘£ê°ø§’x“Ñ…3£‡îx´wù}=N«ãQ}ËÞðüfC|E ¨›P(”h$‚rùUÃ…2#Âÿè¿/A^Þ¬·̧¬j±p@(rÐ_2ÃU:ÝKæ ȃÀšHÚSÖ@ñZ(’`¤ÞØå‰»\*ÂÞ9EÅ\H§ÃzÂÓ¬úæÓ·«›à³›õ=ÏÇ©æÙÎHþ#?ÔÄ”è!QF÷~¾Lí§œ@~üúëa!:C„Sj´xªXÓç¯YÚjÜÙ?uì‡èC(4@©äaˆ 0†Y’c¿`ùÚY*€aƒ!¤”óôtz8ô%8ÈGaNó-3ÐÎ=™› iI ßWÎKQ2Ò˜ÔÒél&­åÊò &$ˆA ò,™ÐSVÑô=W;=œ< ÷Ð($õl4ôǘLeHÀ»X#âXGÁYÅ®7漣‚ŠuÚvÿØ=ãI<à`Ål Sqî9 BŽ?rÿÆäì« :Õ{Š€hÎÙýB¿€Ò=[u¬ß#dçY>h£ ×³{ýÇAžâ>·@µ3¸åÏëf x1rH0}@?Þ–üA¬«ÚhŒ›Uÿ€©Žüšç à5¦Û ¢zÔpÁ§æ×]ït$ ^ÍW|Ë{ÖIÎìµäP£ÚPÎu„ûbœúN ÌfMr¿Ñ¬»hû_5œºç+GШ*6Ðz¢m7 ²ØùÃù¿`ß|Îñ÷9ºX$Á„ÄÖ¨¶5)õ!ùçlPã á‚îq¶˜*¼ìŠ T±š)¶8°6Ë}’õO>ýôÓ·oß~|\¯ï{> ‘K˜e†~°åÙ|£rÿçË ë{®ßÂï•£FÐ%S ‹­Û½€ûöÏyÍ [јh€óŠ’#*æÜŒqîÍ RGÓ®˜°YaÏ4‡šœÐšVpßòri·h9‘1ö ƒàˆd¶ F>™A_Oj†¦»¥b¹\ÉjZúƒT:•r~J2 ×·,_‘ô$tÀø^Ï£JæéFÎP¢×@|TèŠ/ wˆjµçTìAгí€åú>«õìsz3½¬áI¾. ½2ñ<8€§¸ÏhVÛ·‘€µ«N½6xÉïÐãÌê!ýø~-ÀZí áÈ'ÔFpuŒß4|9­ÑÝ! l:A#8¨Œê’<ÕƒçU¶êj’ðÉU®³o=¹õ°Q?ÀÂÄÏÁoªpâÔO‚ªçPìOÎ~ýBÿÅFSþLÕš˜€APk۪ľ`ºÏI¸õl ¼ËJágçÄÿqÏS&|N™-ªqâ,\¢wãûÖ\ Æ€B‹üû€Þâ8Dþ Ú½µ*¬W`#ŠßwýÓ7o?þøg?û_Ÿ]¯ï{>qlœÜ@§³Û|+%núàç‹ogópÏõ;ÃBJCH)ñ.®÷l Jë÷îŸHi[C .@ñ_cÜtã<*•進Ð-Чxí¦ù ãËþfxý¼Ø½Ýî!¬ú‘à)îsíäW=¸å  e Å;üÂâAýø~¯Ý W0°@n¢U{Þh|‰y;$àè¿·(~Xk¤ïµèºL_Š¡k‘Ø·^ó-‘ç©¶ÑÁ¨á8˜J<ˆ$(hxÕFP;kÔaÿMˆsF¡QmV‘(Y–M]/ö¥‰ÿ=zZœrü'æÈçA5Ã…U’…Ÿ´Ú”Å ´nA¼,{uÔ RºÁ1Û‰:†ó|’õ·?ûø“O˟ݼn­?þ| é ô ˆZ˜ò× ú±‡¸÷ó…†vÁ¾ëw‡…€"FÔÂBÆrõðº ê÷ïŸF£yh<9ïHÔnZ¥r¨¾i –/K àf†gr—Í‚x„bÅ4<=éZ–å¦MYòiͪ.Žübdê¢ § –Øû³LÝ-ï{år>ŸÒÓÏÒIMClÕ$Â7L×±|ÿѼ Ÿ»æ¤":ÓB¾;#$ôˆQq\̯‹è֟׷€9PÄ}ŠÐgp³ùð܆M÷»€ðÚÃ~Œà)î³qòŒ‡ýûoÃ`ÜlÁQn®ÕCúñwÔžÁÔj1ó~X'i '„&õ†Suê~#¨ÖœFý7Z"¨^—éå‹ú«½ëµæ=’I-8­F,AÞC¦ä÷œù /q@–’–b-mÔ« 8ö™àøÁùÜ/Я81ç+•å®ÙkQüÙ¬œcŠãó¤Å›*_€àßÎHÓÁ³v¥úâ3ª÷ÀðPcœ")_<ÑúÛß½+ßz]¯ï{¾§T›“-ýÎ×±ú÷ô¡ÏI;²¥}×ï Í9^8W­²Ê=°Þëvqè?´M·îµÇ½šwfEÂp?c†@åt–ø_ŽùL©Xª@2È—ÿLEËO;–x Kˆd÷˜"¤¼pÙä×,ä¥é™”dÿ%?•p T{F±ð¤Ü1™KŸ,2qrúrzÃJ©˜Á‡¤ŒÀÈ_©CKÀç4 }X{^»íŽ91)榲uã1^l~bÕ†XµXoáqJ°§¸Oìä í›a ؋ڀ(€aü”Í(ÐQ? Øm£y#fêuë îÔªŽ~(ɉÞ$´Ãw¯”CßLç©2=( \àôÂÆ¾õ&È}ê5?$oMߎúF]Žÿ/%üoÖ›õ/‰ü‘=äÖ[Í/A^¬ô?kÐïØ+öù§¤Éà £wÕÉZp–ƒ€ Ô”ÐuÊÁWVÒÉÃ5e¡œ]$GŠ”‡" ’ ­;%xb¦^á”^=Õú»?~óöí§o>ýdg}ßóÁ‚ùãR+ƒÀâp8ùПï*¶ð½×ßš-”LᚣU®Ûv“„2íŸf«…¡-I|±\Ëg IãÁŒa ];Ó‚@/Šý—ÅZ2ëB) @G$È$ƒ<¸ÄŒI% Ÿ %ße€7ÄÌç%ä×ÎreÓOø–‘O¥³)1üTFOjºx’QAóâèÔ’XÁ‚³Ô‹Ü膗†Ñ×óœ3/ôFA}`^ÈW@¯ÓµkÖn9€O´àÊÈóÙÝ[Ó€ÐWâ KÔ@\ ›> ß';ŽÜ]õ½ƒº‹ö\Òó°å4Z ¹óõtž*Óã T«®±o˜þßÜ,­Õ”4a“×pAã€%p€·¤ú%l_¾R«wì9)1gjÈ€Î5ü˜ LÀËß„êzKŽ,Q' ?re’rbº…¼¡ÀÛÎùKšCncŠ„ iü”Ä"s¢ù–O¶.àgoß|ü³O·×÷>ˆ=¯ÇôÀzNÂÖfT¼ÿó³=ÀõG¯¿oXh¥šŠ Š?¸n äìŸVÔñÚ]Œë=@´ÊP‚\63Ìšù b ‚ “òJø[w‹Å¢“ÉžU*ŽÏM ƒ–x PÌr)]w’òáë .O§rrúƒh4£Ž{ff<£XrrV)ƒØÞ§Í2(€X Ü¡œR§2”£ÎýOîÈS„ íNÿàÃêµø¾¯‡À“܇@ü¾<åµ€ýÇêÀ+•‰²Ì’òSpÄ‹xpƒ/XŽèúA³•¨‡ÕjB>Ë&—¯Ô\®šÎc™Þ9شꮾÃ:¨«`ô†¸ùÕdó4ŸËáß„øwµVmÕ fòe•‘¨Ö¿<@¬§sΫ`´ÈVHmàðøuÆqxlfôþ%À8'Ù.XYŸsâvÊc—áȯ§”!Ÿ /€cÁ¡ÅGx@Øÿd럾{÷ñ»7¿Û^ß÷|øü8ôÇ¢þT1,/føœâ¡™¯÷^ï°Á•SJ¬?¸Þ낲åàñýÓK³Û r¦X½…x_¢ù¢™‡Ä`Þ1$©GÐðòº–ÔÅl­@×]³hxT| Xh–àŒ²eäÌr!§'Ó#MK•ËWdA §Á)îén&0G¹QÖ3Jþ0WF/rHQ{Kì–¨i@ÀQǧsîŒÆÃ˜ eW?Ü8€ïÿºß<Í}è>¬Ú­>ØcÀ™PHb¬U­üAýøC 8šøÈjš4J0´¦¦ñ¾!q{:O•éãxŸc {ן77ëMŠzÞ¬SaF_rY 4¿l47ñ?¦U °X+ëŽÅrg+TÉ%']òÔCœuk¶â°ë©¬A6Í’$ —ÍPAÑ,héôÐ(œ=ó¼r`³ä*IçszV˘©éúÙH7‹ùB±`¤ò!zWŸ,6aLYœQxzÃ2d{ƒ IDATÔ°k‚øßúú¡äÁëÍ–äÿNÀNUìÿ6-ø¶>ü޾ü~<éÔ I¥Ä‘_!Œ‹…™£·£sý ÁÎ#Ä…Ÿ3S‡iÔ®×ÉÛqçzœðø«bP´¥”K Ԡ¹o½!_Å00y€0ùÆ“~6_ÅKÒÊr”Ù0ó]©¡Ø7”<(g±[Ç ½˜ª²Â‚‰8í—§ø‚ƒ…ì—1™Úwýw\—ó`@twÖøÅ\ó”?”i‚ Wÿïý|{¯Wj(]líÍþyèþ=@曵ïº?\ç—Ðï­·{Ý^»+N C^¼#qò›ü›hH:YfP€\Þ&SCIt«`hEÏÍûަçbð,;Êh…¢aD>ä ½tt›Ìß AÿwÆÌ?"@ç¾ç´æßR’ày÷ߟhvŸËù‹°^ëÝ¡»¥¿¥/¿¥/Ÿ`»Õ¼Š3Š7h×€yNÕW1#/êsò·”ªÈïâ10Ù»×תäó•¯ÿ"+¯«Iñ{ |ß:’Ènf¾RÃoK–¶UÀ¼b°Ê"ÕL‘€²ó?551ö6UÙ›çþTåÃ3N ëºX«9Cå.É­‹™9õv{®ïu…-Õðº¶ü|@|ñ°õû?ß¾ë§äAÌÛûCíŸïOÐüûãñõ&õª5Ùn·×µAY×éõÅ÷ŽÍR™(À2t† «P2S©ô£ZÚ³ Д–ÌdRsÌôÐq S׳§™¬aJÒO¦º‘sêú·3T‘ùCŒ~¤h«}÷¼ ÑmVàºý¼ !ŽËë>A§¹O·úܮ߿¬msîêÃoéËoëÇÛ‡oT©½qU‹=t«Þ:À±,oÙl¦x„«õ‹tb­0Ø&BùðR¿ßºTãõÖoèá[ÊÏKÈ×¢‘C©z¥°î½‰¯î_ïvmœIkÎÿ‘9òkŠ'¢ŸM4¦ÁËP\Ú ÎSã²+Òê1â&±öz¾ºVê½ÎÉé]”QªCOîí¹þ}×1¸œÆ'9ˆ(c*âßõâýŸoÏõÔà¬0æ ·ö÷Ï#÷·»$•س?ö¬3Îl±€Ôiv[ ¬CÎѱ˜ÿÑ‹Cñ/Ð,WФ3$°,ý™£C$íèf…,å®–H¥Îòº®• 75:é9ÑùJœuÀ{2ÿ‘ ´0„+ð‚5ä6)h·ù\r÷æ÷®ÞWï->Ñ}ºÏ›ÝÛ¤ fgËìêÃoëËoéÇã—ÝúFÜïASuàê°Ã&øB›ò¹Ô$i“/`æ«Ñ /¿:¤õ”È­•â X0 ª|Þ‰‚ð+gº!u1B–¾ìï[owå1ɘÆÉtò]ò““í·°7H•~6°µJsª0µ´°%á+B#Ï.–ÊB˜­7Å;J qà/Ó>~ýû®+.pÂì^6Ça¢Þûùö\Ï!«°–8ÝÝ?ÝŸÕ¾ý±o½©ôªëUì6|Ú9•zÝÁ``šâŽOpî—匯T =³Oiî( ÔðÄè#ºi ¼ôÈÉVÊÖHO:ùLÖ™@þk„¡s €ÃD£Ðõ©L/ÙÀ©EÃPIWA+ &î+p«ÃêýŸ}ï×ý]€§¹Oó ÓÚ’ïìD«m}x Çúò;úñ¨¶ˆÅÿ§o£ÑÏ,'p»Ûîâ#êʧqñvã÷ÌÑ[Ê<å…¯ãc”¶Õ®Çm@xø¶²Z\NŒH½ž¸Â÷vÚžð?õ:êú.M~ߺÝé÷DË’—£³jk«;zýh ’•óúÔ›²µ®x‘–ª·TöÂá¹Ì@òpœQŸ“ÚÝìÁcléõ…ö\ÿ¾ëd&†Îß³ÄìÜÏ75¸e,#ò>Ï·çzµ?f¬,wöÇ‚CßßF°gì[o·ël4 –MÍ1ùÃ#äÁ J%£$f/}åô°Äþ-Ï–Jùl:§çKÅ‚î$ӧ錛.Šð“𿏥§Æ#”ÿÆaj7ܱ?–ðŸ^ rd!{°ËÁÁ`›¼a?!€ç©îÓ<°[ ·£¼£¿­/¿£ß³í–ÖjëÊÑî%Ç*‰A³­‰?nÿ¾ÕÍpæCüD›äv/~ásìtÚñìóWððl^vÔÇ‹h@üȦ¡Ñ‘—˜·ìž>ïz0N„ýë=4´—j“ié,6Œÿ͘¨×z—Ôç¬UC(½CêfR‡kÍÙ}”Ps#PCñs¢] @™>¸œÇ{®ßuõù°cOY@øK­Nðéû>߾뱈W'ÿlwÿw÷ÇüñûÛö¾ý±o]¶L·M8bõNý ÙnÉxq$àH‚€b¥X®@M d…fºÅBFÓÒ™TΰrY-¡e‹†¯eÓgÀ Ýb ÊAšžMG¡ØûÈ÷ÝÜÓ ¹ó5” N5 ÆãBd°ž€Úb[¸¶ôÀ–<´•¦wAŒÕÎ÷ìAap\èqœ¤>dòéÙ?Á}Zµmuà]yðåŽ>ü޾üýxù ÄØ¯‘è›Í· hÍ´ñ)ÊS¡«¾TÅ)’N¬Ö«5®ív3ª€Ç©8y:®¸‚.ÉçäüÆG¾"Bä‹U<aï__æo¡Øè– áž9uAÿL•ýÜø LsLŸyîp{ÅœMÄŽü1Ÿx9>~ô•"Ý\PUWÍÞëßs"¾óš)Cvü\¬^ „yïçÛs=à†üݱqgì¹ÿÞý±o{]¾x ”Tk8özfÿÅÑàèÈ<P*U¬"çqF©TÊö›Ëè…J!¯§“Y÷|-5L‚+(Wª˜–áåtG÷0à3r¨S Ú R’·¨SŸrè8nJ<0 ãQí vMæÙ/€¿[Ü}Ðö÷ ùWãGzb°æ®î£¤ ï}ŸvÍ~ÜìêÃßÖ—¿G?>¶sF‹k²È+Þ'öÙñMÈzÝC[‰PqÏ€„­+U¹’Xì½Gå¾>l÷Pyxü%8uíWj4mNH‰0`ÀªK÷ø:~ p]Ý´ ˜³ùC±ÉIÜ, Wœ X(.źTŒ98í0=ÀAim ± ð " ì ¨×©ÒØ¹Í¨ôÈõï¿>›/ÉË»˜’Ü“‰ÌL!šhx¿çÛw=›Žlý­çßÙ?{î¿oì[—wænG?¡Ö¨vk¬ûöåð?”4À| U,Y%sâ‡fÜb匜ðš‘ÍCo,¥¥%ì/y†žÖ’à 2+å¢é§¼Ñ™ORð0‚S=Ø¢Ér7Aè@¡z UºÈ—0Êæ¾üµ46dž¶:ÛxtúyÌï÷º9ùwc@Û…¨‡NßG•žâ>íÆvй«¼¥¿¥/~<ûƒ NOñIÆ‚¤±AsZv¾…~{¦È À2±VÔ“ ÜP¾dÿÌú}4ëÕ(ÛzMb\E'¹Púÿn¥To€[eAoÏ:ÌY Í+Ø '[¤¼\ÇÊØÆ÷OïyÕdn±À±¥à. q«Ž!Yª%·ÜtÌìÎö_ÿ~ë þ_°”G¬FÔßÌ Þÿù¿=3ƒ%ôDîÙ{î¿oì[çû÷mÉÑPª?—ÝiŠ¿8:>~qÈ( ,Æ/ÿÔ¢aQÎ{ßÑW3B«R4ózbA%S†p(˜A:u掆ÁpôƒÑd„®?ñ¡\/G¾7Ž cíEax1žwîºá–hmHås¨¬7oæìB/ßÏ÷ Iâ P{ØJϯ'‘|÷±à îÓGçíyp:Ý[úð[úò÷èÇS‹š¢Zè÷µ¾T©â”ª"œ0ÁG­&ÞÖ±Pc[ì_ÊV¬‘Æ+]Ú§YAŸ‘h Ml5ÃG4ÉŠ¼Wr„S¹øþÇ×ù8+•Ã2úäìÜL\“gÜ’<€÷½ÿB!agJ)}‘ …³˜Ž9+nü)ô€ãw‡Îû®ßužÁkÖÝ8Ú&Ϲ¢ufð¾Ï·ïúyìEcQÅ;ûcßý÷í}ëñû#ím×¢*q@+Ó³ ˜Pÿ„ €ZÖÿýYÿhýWËÌç´tO›—¥s«K‹ƒ0M£`™zVKëº^©Xf’h€ð0‚þK¬:¡b¡ß½ GQäMô]orî…—ç[ ÑÙPyÉ×oÄèb¬¶}${¿À¢u>zÝ>™=£{ÿût;GÀ®>ü–¾ü=úñ 郸*=q L\ôB¤·Î˜t¦ ø+rŒ¨Ðš;Ï.TÞp6OãÆ‡ÜðÆKBÉŠà}%¤˜ÑçÌo2ÝÇ×ÜSöyåøÿTÅsÂ}4?–(\)ƒb‘$Zñ¹DL¼Ð\­?'—0NÀ“““=×ï»ÿ¾õ…jÓ’º  þ÷ŒÒ>æíy¾ÕÞûï»~­Uɺ¼gì»ÿ¾ý±w}óþÈ8 Š†AÛî‹8<6%8¶Êe Ö¯ÿþÿô‹üÅ-šžž.˜VÆ(M¯àä¡ R ІDÉ´ãåÅH çµÐ½-.À 'þâN0r¨jáøž?B/ÀûÁáÑ–èõ”áv©àI ?¥ëiCÉOLUÂuc¥ðÙ;‚¾Ç-ÃåëÆ<Å}š½Þ–8Üu;úðÛúòäÜÖ'c%%gªñïàPP RÐéføž€ìS89‰ÉLM"ðŠGÇ5iú©[‡ä~J ߸1M\ïj3÷öè:I1ä·^²ŸÅf4ùAÈlñèûg¯ÀlC$4Ã¶Ž‘qwY‡ÿºä<²¦býâ°åÏÇ®ßwÿ}ëó¸.OH‡5|i°ä~øùð¡ÎßãçS×3`–¿^Ü·?öÜßþØ·~ëýeïw.zƒÃ#‰ÿ1dBTÄ(šæ¯ÿáïñâJù¡–¾´Œl¹™ÞÈu¬r±R(‹–¯¥4"nZÓ} ïcF°Ð÷\4šü~"@Žä÷>em|è×Dãh„G[Pà[œ€(ÎÉÁLå^±Ýìܾ½Pz¾v¬ï Öÿ[†¿n8Ÿà>»òàƒ°«?e¿7Ö—¿G?~¡4µ02®H·˜V®ÉX?eâ4ÛDóYL6³d â‘éLÍå­TåMMßÜÞ&% l›¹ÞLAÍ—s5•>#Ýľõt­FY§4Œ¥jNìyÿÅ\6‹xœ`ÍÝË[SŒ8¦?JïBAŽ×keý­VKù€¯ßwÿ½ï¯ ŠÔRþlµTÊkudo?ßo¿Rχà‹ÃB;÷ÿíWÿ|»×Ï”ÇGY@‘ùo¿ÚÝ?ÿ¾ý±wÿÜ~ÿ>ZÝ®Ýí´ì‡à,1oõ¾Ê¯ÿþÄþ ùwM2f9„Þ°“é.D†ÌP|Dè”J¦žy4ÉyÁDÎ}÷j‰C¡ª ˆõOBÏ ‡aèù1sïuª7w¨:õñ$wWj^<´{`òëíÜïÚpo=OwŸ]ÐÛuë}ø%cºµÒ—¿«Oýy~yX©21fêfì½ÍX &N”"u¾ÿ‚Cç›a1Ðu͇,E½¥’’[’íB¹ø äé ôŒÍtÏ:= T'X'C\Ϧ²~¾Þ÷þK–W„»#ÿ\Æ¢ ‚ÂÈ&@šÃ­â¶õ·ZÍ8xàú}÷|‰Ö÷Õì³ÏÐû(öÙ"žÁŸ-§wžï·_}E{œ/•Ñîý¹þÈÏ·{=ñ F0ÂÖoï}Ï¿wìYßy°eA5«c¾8<p؇(°)Y~©\–à,ЈgSQ&k–+†YÐsédà•+föܰ,ÃwhÈ}ï, f !ZåûîÕÕïA(pDãÐCEÈw7¼¨Ø÷;€MãŽm:ˆz zùAAûmzz’ßçä_”á¶¶@ýOwŸm`ßq»úðè¼,(@©Œ»úñrè#Ø›ÇXtœ·$ ˆÔBqÃ1“ L}†è¾à\ŽÞò˜bäH.›%q§`’¡F1?pR\B+ƒV‹Ðv¦*ýÌA÷¬/Éž { Ôa„m *8¨»çýIŒèg¡Úëü>V°¦1su»öötÛú·|À=×ï»ÿþ÷Ç€ß/4CåßÊŸá/V;Hhûù~ûÕo¿Âœ æðëß½?Öûùv¯Ÿ±,@û— ×oïÍýÅ1È뾟ïñý±o}çýß¼½8e~W¢Êå²”L ýú׿þG£dÖh¤åóñ¥œë&Ó)§X‘Cß2Šn *žD †®U4hÐ’Èu#Wÿáÿü»«ßìMü‘'‡~ºa8'XEn0qîuÄèÊ|å•©w^NìBLæ?@Mß6·o\¼km½žî>{Àj[^A/–ë˜þŽ~¼¢_R’~­Èö8¾VüÒþ†Ì(:ƒhÂs³)j>¢óÔö¥üûîÓy fQš}äí…uâ$"ŒoÉÔsÁ ¸ùþujYQI“B™e%¶à`V­ÖÖqÎU'|ªR¡™’áC¨ ¨*î ê\Ýoý±¸çú}÷ß³Žƒ™ ÍGNˆ|F½?VhvŸO T,˜¹C¦Ýû«õ‡¾ÝëUKo¥DÖñõ·öG||Y^_}¥žÿ«ëûïÛûÖwÞÿÍÛ·oOŽ^ÊK‚c1ŒãÃËJYŽôŠU)–K¿îÿý?Ë–aI=gèòõb>çûi=H˜ñ*EÃÕƒJÑ1ŠŽ®y–ÄŒ`Á©ã]9WÁÏÿU€£ð€¡9n(a€L\ÉBߟx•Ãû"&èÔí4b*äCQ:Ÿ1•wнÝw_OuŸmp¸í  ´«ÏÏ~ÎZнúñÄö­T”ÆØ5.±1¼®ÕÙŠ¬ÐÑIÈ30b‡ N9‡Çv ‹3¦3Îè!øœ©§f”ö®¯IE?³H°Ù¯qœ»zÏûC"kN1,t°¨’…ø“8£¸ÝŽ$IÁä·4?yÈú[ÍæÉÝë÷Ýß:Ò-8«X3L\ÀgP^¨ê,«êùÔ,¯ßþ·ß~5g…€ºg›ûo­ßóó=p½ô›ÜZ¿ÙñýÅü7yÁÈóõÕÍý÷í½û'~ÖCßÀ¼yaÃdröññ‹Áq €b©\,þºÿË_üâW%I÷³£T!_Ì—K…¼™ÒÉ´W¬”ñ96L-ˆÁ³ /ö f ¼àê_Oÿåç?ÿïzÏ•?G.š ƒZý0¨ôïqSöà:×ûJʻЗÿèõÙ׋üv×èn0üµÛ¯§»Ï¶èo;€.¤ÁvõáÕH(ù`î×9k1ñt*çÁXÿ0 #ËØÖÖÜÓxÎQbV龑ÍQ㊌·srέâÞ"*AòÅ©ó£Ë8ó‡G×Q™B­ˆ°Œ«æ9N¼u|Ô?þþĭͧpzS…v](äî‡9wéT!Üä'—Hÿä^ë—=yrÏõûî¿o}…bçêF8X^J;Œ3ÂëÍóÅG0^b‡_ùÔÓæþ;ëw~¾¯'–b±ÞY¿Ùêþ±  X|µ}ÿ½ûcß:ÞŸ;`¹¦x÷Bûe(‰Éábùׇ¿üÅÏÿî—¿’D?3r5H†•sy²B©T®\)±Qr|É äMÓÓy'fsƒàüKð7?ÿÑϯFND¦@Å$ÅIà{Ã`x ¯ÎeDéÌÞcu/#Vö£Û ËÿÊp;µ[s½µ§»ÏãEÀneWž1T]VÔºO?~>ü”dÒü<ÁVÄsƒ¾~¦8dˆÌÃhNáE¬h9‹±E3ÞçÈzU°<ÓkìGשm?å­ùøJ±’¹ÍFì‘÷NcCÐá@l­jî³¥‚ÆAÒ =Œ„NN”زþ£#ñÐÝ“»×ï»ÿwyä×`# ޾ùL!øñ|רÌð+bøW³ëŸow}÷ç{èzEø1¿³¾Ùñýo-3I¸õüï½ëñû¾!ÀÛO^í ‚öqÅ,@¤\üõàïÿÏ¿û«ÿòÅ/eY'äPú7ÌJÖðÍ×$˜˜—P *- ƾžI»1#˜? þÇïþæï¾øÝ¿ ®®^¾‘ ¯QU€‰ãúþy¥{Pòô¾)¶)É(ÐnœË÷Ôü OvZul¸[üÞµ§»Ï¶èn;€z·²«O°ÏšSgRl˜xïÇ×U¥n~çËÙ†ô#&§Ø÷þŒ;QSsK5ŒB¶Î¹b@ÿüø©bp¤âZ¯ß‹ÀÝë÷Ýï:Éå'o—ëòg·\€óY™ˆùåæùvOèß®øisÿ»ëÛ?ßC×]5›Ý]ßìëû£<°q_]?ÿ¾ý±o}óþD=a*pt,F`÷ŽK%ßCÉÿ~õË_ü—¿úËÿü—õ׿ü•¯¥‚Ši’!¤”óôtz8ô‹–™ÂœæCô<Г™Œ;ò&’T^V~÷Å¿ûÑï¾øÑïþåêwÇ/_V"0‚ù‘’¯ƒ0 F#oxo ´ûb«8¶û´ãXÙK‰{1oïðÌýáv>Œ_[)À{ßçÑ °£¿f…€ù}úñûôáWJ¨ Ð:t gT瘭cúú%ì"Ȉrܘ>›Q×j!s?\;‹kÑ Ök~ûžõ˜…#Kزx"rÕ­ÈZµÞûþ@ ¢q¸dáoóð¯P’=iFèia~ãŽNð±ñ½x-àîõûî¿o¿ÝÅ'ŸüìíjQ¦ ˆke´Ú«éæùvrôßÎ)ƒŽSXÝw}÷ç{èzþ¾§ÓÕõxàþŸ|úæãOUà·7 ¾ÿžý±w=~5ýù.àx Q—=8<2+¦†F™öÿ·?ÿù_ÿÕßüí’Œ’š®S7¸"9€‘àN±\‰ÆfÚó,#{~.™A¹á$Uìnûø÷¿ûÑ~ô7¿ûÑÿý »Ý²+`;sÇž8î¤Á'£ ¸7‹¥ž/ŒöǶMsÝØî@q|¨¬¾go ×~.¯åûÚ<Á}ªâvõáÙD_Pìñ>ýø}úð+¥w§Xæ1¼–˜)Y$f¬qapPÍÝ"Þ¥” bÃ9ŽbÖ¼fŠNrÁ„“u=ä€sES½]é~bò‡rÀØ‘Œ¦ aœï}Ô4ñ¸¨PA Sƒ¼n­˜31õ¤Ü;%ÿ‹¹7kn+Í®ßi»ì[JÍJ )P"Fbà$*K·R$$Šew?8˜ÎÁ”]®!35¤r¨üŽŽûâwtDßÇuݸa·]áèìˆîÛý#Îüz¯µ@$ñQVºÒD‘Ü8ÎÞß× c€÷·iÖ·Ç»ÿ“'0§7­o’£¼¹ßØ?hî7}š­܈}ÊiB=¿™,ý7ìÚEùo²þ¬üôû;çxÍü„p¦å“ûCÖ?¨Ô[û­ÃÐÿf\ øvjýÅ÷‡Yž¼>áÉôþ„Ø„R¬o®?Jݽuçöݯ7?ñâ—Ÿ~ü?ÿÅŸýìöéË×—¬k×nÜ ƒÚW»ÝÎÕ«ï¦Rwîön^;èàöÐÆ˜ÏGÝ®“ÚÚÚJýË/—–`þßÿçÓÕbe#D0¸v_lD¿m ;íN?µzvzZFó®ÒyWÊ,ém`†¿Â~”ñÂOw½ z›[Ÿ„ßÁ:³`uÎZ¯Ê IDATäR§øáÙà+öäüñ&~xöo€›ù6Ü@Ü¡“¨-ÇÈ/„ÚÄþ\øàC'/< ùØC´ŸŠÕIvk“Yßt<³­ýƒýùôý5¸~³ÕúfâLÖ7Ýf9G‹´#j|ŠØD3(ÉæÝ»·ï½ûõÖç¯^<ÿô“O~õ«Ÿýù¯~ñó¿øä“×W¯Ý¾y Äbwo¿‡B€Ý½m_pÐçŠå¤î9ƒþÐ9î÷Ÿ ú½ãT*õ¯ÿòÏ¿õÿ¿ñÏ¿üåÆã÷îl`P°í·ƒîGâ/Ì€âÄÝМýš–î+kï&U{¢Y±†÷®<ãÎÆÄuO¯ToÓ'ÀÛ¯c4süðô¡Å¬‚‡Æ;ƒ?ÞÄïëhN >Ü·Š»Í#µIŒ»&yyµï ñ›úî<,ï¢ q<44sZøóäa’c&Ei©‡D²Ä©ã=ÑCYüú°&´ñ“~gö3Õ|Xo&d}Í2Äá¼x,à’€ÉñÕÐNç3׿¸\T¢)Ú'>vë@þo ð¾¢…%VxpÐYë`_”zß(Àƒ;žæãQ?7¢qÐlR>ýú†ã¡˜b€æ~}ÿPŸ¾?·9^ÿ$Løv²¾éþ0ÉÕ0 „Zéøþl4Ð'ê°µuÿ½;w ÿ¯^}üéÇ¿úÕ/>ùÙÏ~þñ_üÅÇÏ__¾zÿλïÝOÝKݹݻöŽu÷î]ëÊû÷ï:·®\½›£`÷ƒg£ÔãÇ×?þ×ý—_ÊãÿúÏ¿H­U§ ÖíÈߎcw»ÒX©ÂY!ZôÖ°moÞæ_e·k o¥TAa[úÆFù${½[ôöÄ|ë̀Œ(ÃÌñÃ+kÉã sJnà‡÷©Th f«ÇíO<øñkwfòày{ü‡œ>ê^Ì4úêJjß8>e_›=Âx˜åÈLÐßÇrØðBrH=6½>F‹}Ƹp ¨ürKƒ©¯):#»cò@ä±}¶Ð2àv$òP½cÅ×;½~øFr$ÆöEýe“nîƒ:P¢€ûiŽVÞÚlÁˆŒ¡¤ˆÃ™¿ØŸ«ëïËáû¢âò¤&äÓ뛎Çl® u9ZäzüÔý!ë7’õ'A‚øG}eBߟ²%®”‹[ë©ûb¾øüå«—/~õé§Ï?ùů^üâq>}õÚ¹þÞ=ðÞ½c_»våÊí{wí+Ý»b1î^»víΛ—¯FCç#$*+ÅÏÅøçùüþý{ÿ,û¬üjØîvÛ0v·ß‹¨x©üYGxµf\¿2yþ õ;í¢³+ã›*ß­ ëSeÀïbYŸ6¹âÃÕÔ)~x¤Åôó?% üð¾ö¯A-CêØ(®,Âq{,ð'Nã=MÑ'˜tÄér™èÅíŽê‚¦…b’P&¹› )ñ~ÑQ_¶ ÇLYédá볯9àœ°ø™x A“:ˆÌ @K¾=܇A8hŠöom%5€÷g «k•ííõ ­@”Pž±>£ò‹ÊQzˆÅµöái7[âÜon‹Ï4ËÑäüêÜáëax2…‰õ[òFZPaÑT‘7g×_|<ªŸâß·ysúþõ›ÉúßL=NÖ7Ý&y¨¹ñ´N5¾?×Ë)”ÖR÷îŠðÙ«çÏ?yùÉó—/~ùé§òßÇòòµã\»'ú_,Àí«ïܰÀpňsýçîÍ›7G½ápˆÀã‚Dý›[•JêÞÆãTêþÆZ¹PxûðØ ‹‰C¤œë´S»p\€­À ôF%£•¯HŸ|+ú®ÂØôú!›×ÃH«M@¸†q£â€®n·Üùýìý[›ëSU5¯& ´ZöííÊÚvlo³þ¬õYS%‡I® :%‡¢ÄÍû÷ëhÝfß «ŒŽÉùÉÄEÿæ@ù@"r¤p}Q𦨰ìòuÈg×7/×Û?Ø?lñ ‡È´fîùõ[ùó7Ü&y€;N¡]ã©ûs´C…U±ï}ýÕ¯^¾|ùüÅ󯞿üôå‹O^¼Ÿ^ƒô.Ò€÷ï8Îõ˽÷ðÿ5ëÞ½{Ýë7n÷î´-ktÜÿhepÿl6u,¿(­>¶‡@ îÝîHb€~Çê¦ò«§ À›>ÎkúNÖÉæ‹'`uÆÈçÒÅÔ¬‹áÁ…h‰ К½ÆçÞúÆûà WüV×W¾AÂQñõ×6¡«_?úòóÏ>{õÙ«O?{.‘À«O_>õâÅóÏ^}qûÞ½w‘¼Ý»uíê;×nß{ï®síšuçÞíˆÿÀüÕ³»»?¿o<–S,¤†ÃûºÃá G>€hC:NÏ…›7oþ˜oàÑY€ïf›.fò+ùÕT4Ç3j‹€7ä‡g1=f‡\>XW+;Ú©Ç8ƒx}Áÿ>½ód³V:OwŒÄãå±PS@ÄêdA¤ž¯0È\À=ÿõr±´ÈÈ-¹ZªTà€ãb}½¸ŠñÀs×]¥e5È‘ ÿÁ:áìΈÀÆÚ1‚ó&å–¯˜ý~¬MB\_|ø†ìÐÈkίo8ÍÓ±ÄÿûöååçóOÖoήoº?Lr¾¾¯™*ŽE%¯¿.@`á™Ü×[_}õÅb^¾üì\Ï^½x.__Ñ»óÞ]щêoY×®\½ý^êέÝ[ ÿFŽO4ZvöÞÀ<Í·†ü¤Ä ­^ßâvü`6ºÄT8©µl¡4cþ-(îôã;\çĬ– Ùéa ÜCœp4Ïï%E>ŸÛ ËKoÄx‰÷ÊÍµì ˜as©µQ¬€ž$t¤N=FŒZ:ó&ý´;lÃpŸQÎÞäH-“ö.kZ÷…Yôú2À÷ˆ’¨5Áü "ñk“½sÐæk뛥bIt|kÚ ‡<Öþõ±öËý)æb;^´~ÈÊÂb9;ƒà·àý¶E±EºJæ‘N4Òã²ìí#®f‚ó9µ>û‰æ×7ÏÏP‹žØ‘z}þþ™¬ß:¨kÖdþü ÷‡ñþ9y}×sÝñ믑{˜ûɯ¿þê«/¿xõúóÏåË«×_|ùÙË/¾|µÝûè£á³>ºwç–}íê5çÚ»3äß–Ówº¢ÿv» LQq{`õ]{èôFŽƒÄØ=2€<Üî:©ÍbzÆøöÈæË™•‡4r¦›' ³œ.³)W›é<ŽÏ»¼‡ƒuÜéêÆB|=%†X,W+¡ea¤¦ç×'Œ·"FEºu¡#ŸÈþÜ‹‘áQÍVµöµ]ñ¥. 7­&=¼óüõ.çØ#”#LúNP‹ÒT`³¾½.Ú_*–×EûËEÑòõÍMXµµ±XƒçŸìùSÚ/>ÁÖv¤3ˆ°›¼JÊJâo—Ng‚y™è¥ôœ]RþÄãw4>ÿýVýŒóŸ¬/§|j}vLÃIo¿y¨.IÜôé×órêõMòñýÑB„ nDãð;¾¦ÎßG·Çøü+Åb.·7×}’zòå“í}þå“_ÿú³'Ÿ¿~òäsViîñÀü…ª[Žeõ-låøjp«oåý¶mu:^¿×_°Zß\•`ú?´H<€|zuóÄH/¯”‹ Ñk^zLaÁ’^?ÔÏÓeé#ZjóMr~€, ÅI*kn}ÀKá ì9ŠÇM_À~qCêÎíqo'Šñüø9ÇF¹iýsùë=Pø }A z²ýQVѰßÜÞ\Wí_ZeM´Z¾–XmÝûUëgµ}k³¼%§—٥ĒDÌ.7öR‡Ê§Å áöˆbBœ,—u—©óo4Nÿôú‡ÍÓë -ÔáÍæ~D¼vé‚ ·S¯ß¨Ÿ~}“<¹?P)A¾´Þª·÷Ïôù®x|þÕ’VxE ÀÌãý'O~ôhýѶlëâ[]îà]€ü‹B÷­ÀÀí¾Ýo÷-Ë$wúƒN¿7ìY½¡˜‡®•*onÈ‹Ž @ò(•òßócê ’ »’ÛØœŒCÿWa¦xH)Á!,_qq;…ôáu&BмQOZ£dven}Ô ž³¡([u|°Ä¨ŠÙ $Š:MÌoÜǨOäæõ£óøë#MQ…ÊÄ:ë€Ø¿±¯™ÿúááöæZ¹¼¾µí—½¿œh?þ§U8Gû×8¬­nÓE!¬ªº3ÔνGZÓˆOr8ÏF)ÒMŸoxúü›§Ïzýƒ³ÖGsq¨™“ƒHSv>ÓŠ§é×?8ëõ òïûgúüãéó¯Á’Ï­ä»TúÇ›?z¼õþãíí­ííG¯åÓØŠÂÊöݳÚòxPüæ£=H`Ývú&y¯Ýà ;C}`^[Ï>̪(%Ÿý¬ô=?¦Î@ €œãúÚú_ÈÂD:0Ë"nÀ™zv•».ñ6Hù“gsЃœ•B¶êaÞžÖyf}¶Ïß%$ÿ³s ç´„ÅY~ìØí}” ÷W3Q®k–Ö_Ä_¯mJÆI-°ý×Å£­ï# XßÞ=€·ÖA‘šh?óÓÚ_žÕþ8Ü–çm‡¬ãÇDR ÙËžT.ÉY#SÆÉIÓqšÉô#­Ç->ãúŠ¥®õR~Xž> Û-Ó&†×7Èÿ½ïŸsÏ¿R*dÁ^Èä¨ÿ[›ëëeU*È×äV+Ûv™~«×KÐýЈ’[ΰÛo#œ8 ï›äNW<{0„ 6b@ÊzF, @|éç?ýË~ÑÿŸÿ¼”×h23ë•@åt9Ÿ¦‰ºˆB˜âOøLærâ W¶SvÞùdxQ¬Ý…rnÈÜ]Ù½ϯ“ˆxýHº£Ã3Vˆ3|ÄÀóØ0ÄÜîjëW@8£Ü´þ"þzîdè@}[‘«ÈAâÖëÐ1²¡`7_æÇ‰Ø8/î‡öƸ4^R`áNáî¦ã_R›{ä.gÚqýؤ¹øüë+H/:è#æöª6ÎᆠMÊ¢×7Èÿ½îŸIöyç_)#ø«\f8àñ£­õЉÊHE¹Z(–·?§¾#jm-{è g9Ž5Ä€ïÀ€õK „Aîôí!;Žâ-¨TÉ,gaP|Ï—>~þOß|òg¥7®ãgÒŸ}òÍ?=ÿ¸”çO0™åL¥t‚ý_I @H&Wùðrçj–%]ÐA!*%L¤‡Z¹çzF¹6iŠ>fÕff}/àOLüXÞx.»¡{úéãfbLÏt~’ò÷YkÌrÓú‹øëá*xì6dö æýP³yXoÒhН5œþŸXqîÅ œµ÷onnñF# À¸á–åV9"b¨j±˜>»­m°AL¾76¿q}7)çÀ׉‰­ÉW‰ÕƒpM¯žüök7\Ò ü»Ý?ðÄêÍóοRZÍe ™|.“àñ£Íu`„qÿ/V ùÕò¶=è;„üïŠs?@²Ï‘¯Ã>~üd±À·XŽBá´ À´Õ¬×V–%)®¬¬PÿÿéX€•ïéýÿæŸhð£€Âò zQýÏM±£WžŒÚï‰nÎ !€yÕ/ =ñ& r'fwa;»>q·ÈäÁ¼ö×Ó7ÚÁcæçØ€JŸ“ D‰ñrÓú‹ùë#í•ñ<Å;„[Jâ;×ç  ÀvÄ’Ài+p:î§ÏÚ¬mo>]ÝÞ ‰Zæ'5Ïc4ÄRry)Q–4tµq‘'êæñŸ¿i}…÷™ˆ#¨"@ß•ä 9¶Ðøú*¿}sF~÷Þkï\½ü{ß?è~:çüÅä³—²Ùÿr àýGÖÕ÷/¯• èX-mw{v¯cÛVºÛíôœ#[ñ~-ÇêÀÁwº–IŽ™Àá‡N·Ó Fƒö˜¼PI/‹³½¼ ýÿíßýö›¥o>ùYiù{y”~ö‰¼¼œ,pA²¢ñ•Âp}uEô?IZfS°­„Yñµ©7áŽ!”û,?»ï%­W å~èèªO­ï%ÝŠèO¶@3ÇçL‚iDä GRJ+YÚÕ«ºErÓúþúHïÂ@“¡q¬£„©/ Ùôb5+qA3Ž˜dš²ë«…òXû} i„«ýøÇìì>U7°¢Ú¥@»„Ò¾ÒfD §¢û ½˜1õ\õû¿q}’øú:ò•À|‘ ¢­̯ùÝ›—¯OËA¶{ùòÕ›áÉýs÷Ö5Ü·ß½qíòõïìþÑ8à¬ógKþ³Ù\zåÉ“½ÿ°l¥òã'Oä¿UñŠ¥mÙÙm§Ã¿íøžÝ^׉‡ï 잎I®ÂÁQ·3ê €dÕsb2â”>þô~ó·ÿÛo¾ø^öÑÿo¾ùíßÿíoþáÓå ²%èn (qJyš0Áõò"ë³ô#9–r&?»IŽüxÜ8Šíhn}Do@ñÓÑ1 ry‘Véaû™OŠ9ÖËò{hJŽýŸ±Ò/–×çñ¹üõ4Ì5é0ñÑyƒ]\L€« JÆùq[|õÍÍuXf5îÇ«À$pµêÓ§;»Uª3¿ÏØ%ÐÖˆd·Æ¢è¦‚h‚x‰Ðá4"΂ó7­‹)/v|ç;1cÌ?Ãë«ü½k—®\÷öX~÷ÞÝ›7.¿sõzxëêe½?Þ»wùÒÕÈ¿wïöõ+?|çúwuÿ°$ƒ©Ìæüù'39ùtáI 5±ÇÅ2«€•òªÄâlKÐïô]B{ÚËîFûÈéY(þÀõcƒ4Ô:’Ð@"‚Ží &¨À¹Jf¹ÍˆøÇßüÍÿûßþ @æ{xÀüÓoÿþ¿ÿÍoþQ @&[(HüŸ;áÌfÊÓÄ p;ÅUï­ùÛQÓq“r®2ÛÌ®ÏÆ}Ñ«¿ {ïû Ø¥ë+./í»ë*.žnÂîãöž/7­¯åÃóùë™DàûžÉÁ¥éDâ '9€íPXþXÜ>hm·ñW}PkÂ*€˜m„ÓðÇDY e®zÒãŠ&2šÓþ;…üv•Ópþ¦õ”ÄÊ›+€ë%„zuL¯/òû·¯]¾zýú¥«ïÆáÝ{·ïÞ½{ûÝëW¯\½zK7¢Ôõ[òÛ«—¯ÞKïËWÞ¹rãæwsÿ4ëÍzH4Óç_)— yÔþ >ˆÏ [4kÅRÀWÛNo¨²µ·Îh4ê[ö‘=u­áQ{Ý6É%þUðàx0tF=Ë9àa)‡àþÛßüíß}óüç¥Ü÷ò(ýüù7÷·óßþ!€üøPöÿ)XðÌ,3ê±ʹd]x[þvru³êÄÓx~}0O»$z‰ÙÍ× ¼vh:@öížÖ#åýsÉ9";ºLrÓú&þzâƒ$ijb aüˆû)Þ ÀÎöθQÀu·‹årq»~x Á£m6â5Ñ4â%ûpLâ;OÆãM‘è„PÀ$s‘ŽŸ5P˜M$Ìèš›Îß´>aýX"%xÜlßWØ]žŸéõ‰‚p_ÔýÆ•ËW®Þx<¼wïÝïöÍ«¢ç7ß½{ãö{W®Šæ‹â߸}÷½»·n_¾zåòµkßÉý#>X3õF³E\†Éù‹Èe³—²_ÿ:…`}­T|L°)@A<€¯íÙë×uF½úÝ þín»; nåäk[~)®Á/@¶ò0-/ ð›ß WøžHCþæ7ÿÀ3È•Ò+Ù)^€\¾8KÎ*1ÁŽÔ¾5;v1EpÖÔÒÜú![Ù‚@ñ;‘fóø™ é·hÌ s8OmöŒØC‚ ÅrÓúFþzlØ®›l­ è?Q¬ú8ØÙyúôÇOk“F=¨øö¶zò+¦ú“F¼fsçéæê.ñè;³tF7>Œu!!b ÷Ð{ “[d5æt®G$@bƒ„ ¡ çoX_»…ã@9Ðo¥‘ñù™^ÝÍ»b®^ Ãëï¾{ç½wïÞ~ï½;wn^½öΕkïÞ»ûî½Ûï\~÷ö×ÅxïîÍ›·nÞ¸rE¾Wf÷»`U%;h5Í}ÌBògž¹¸šÉ‰ @°½½±V)½O°¨€üjY @Ïîw²[mqånÿ,?`ýè÷ºm’;]|ßéŽèrFÓÄ ¥üÃb±XýûÇí+~oñ”‹ÅLéa¾4M ’/–ç €~âè Èïóvüí$"¥¨&#Óë£ÇÁ9ª=ÚÓ)”Þ˜Äñ= ±ù*Î@bC2ñ˜ä¦õMüõD×c”ÛžšSzAÉÃêîÎOwùôí„dm½¸ @®€Öú&~»OwvÈJ@…rÕ¨D h#¦íCWíW’awiT™‡8 Ë/Ü29…é›Îÿœõk²h­JšNä7kõZX®aÖªQ-ª{þ^mW®l­×¢jÍ­÷ú°k­»÷o߸†vË›7nݺ#:ÿî­[ׯ_yçÚ›wî¦n_¹*–àæÍë×ÅC¸ kqÍuoܨ „³owÿ4—逰cò÷P¬Œ€ï—QȤ3êlm΀Õ|~mãÓצ}DɾݳìvGâxQpùm”À]Dÿ&9GÇÎñ¨=8¶f˜ Å•2¥åQ*“3Ȭ­ 3 ¿>á\صÃð<Ò8Þ5æ°à<ÝŽÙÏê'¨•&ùôú­¯_µf×7ñ×{I³«g!w!ŸX¶&pÜù×Öž<©ÖÊux úifñà’Äš‡àä‹Ò¯« ïzJTàÅ¡: !Ñ·œÅ~ßK¨—üP ŒLç?¿>¶ôZä×bht-öÄ ðê{õºUÝj­*¿«‰mûP«zòý¬N-’_†ðj{ó¯~mÅ%ƒ¶âútÏùH,d$þ˜kÓw€vÇÓ÷…ßôþÁ+¡€É Ìî‹GЪ¤áÑz9ŸËfÓ_¿þòëí÷o®W¾xòùg_|ñÕWåòj©øêÕóç¯ÉûƒÍ¼/Þ»m·­î¨?rìö {„Íß–ß ‡ŒÐ%<³0ëd++…dþ^÷ylŒÏ`U À 7àêú¬}WÁf¢(¶ßÛð·Gˆ³Ý‹ nsësÛ@Ež½Vë=ÍÔ‡ã‰^"¿ë'¤º\Çz/ Ÿ^¿õÕ§­ÙõÇüõä1Nó×3œàà‰'u·˜ÄÔTÂZ¹Hþ¯cëôäÉ£¥¢èug§º‹aa€¤/ÁKÑ $i^é×Cm:òHKÉîbÅÖsIÿ%©8x´>„ʉç?½>Ú üú^U.}uoWôßuE©ëº„ðôEý«»ü¯&Òz}¯!ÿUyÔ$6À¤žWÛû1õú±â(ác¨ïh4ô£ÉÐ%ùÖôŸ¼<5Ò*{ùú«_o¬•ž¼|ñ¼X|´^)¿xñâÓ_ew;˜õ=¶Öh0h#´·ûÖ 7²;½žm;&9"‹ÃNÏqެ°–ù~GÏz¬eÖf ÀÆœèÉs „”yÑ[ò·“bø €ÜsëlE— äGËñäP1£Y¼öÉí¥u}?iöP ŒCOy¾‰É’ÌÀ¦Ëd>ÿñúUY_üþZcO”Ú¹UʾWM”È_TW¶Ñ~Ñüj£YßË Ïÿ`¯.†Až.+xµ¸^;y}ž'•9„EoDw~m%öü™VaZ$®$]q§îŸ1gˆœÿ·ß^øþas È&ÐYð4h´Òô¿åÒ}±b^¼¿ø÷ésùóòå'¿zýu·×t•áó¨Ûs É–%[¼öûõ¡Û&yÏ: œQçxà;¶3ë$`uQ~õwûœµÌ¬Pœ3êŇlÀ u_y;þv)xÜôÜBç×gÝ–é3|p.YiÓ¨™VCãQ0ŠäœŸ§Üy²>ÔTÖoµ;­Ùõþz”ÌÅŸE£@pÂ_~v < û H;™x'(Œ8m¬¯¯oËkk ;'rЧ*ºâÇVÛ Hþ’8‰a0ú†rW¤è‹Ä7 ”õšQ¼–¿]FH»dc%Å5Ÿ¿®/jí×àìÕÅ—¯ïŠJ‡¨ª…µjM´ß«Q£†P¯Q¯×¡õUÕi?¨á{ò1Ö $4¿þ¸•˜“U˜îv âís8ÓçŸRŒ¦TĤšj%žÜ?'¤!ñ·´¼ÉõE7öA3A/mµ$ØZGÉ?—K¥¾üê‹—¯^¾|ñòùsü}ñâ“O_¼Ã'v÷^¯‡–~{p$Û8Ê}ǢݘöïIÞéÚ£¾cƒ*œt¡³@Ž:™O/lÕ[ý>g-7ë”æ {@·‘T™oËßÏhnä'Ó›³ëGIm'â<(4ê°p¦Yü˜ý]¡½„ÊêÊ¿¯˜„y¤míns·zè·Ž¬V*x²¾ò×#妠2Z>㜠¢¸TÕ€¯àé{DêPqk}h"€Ç·6åQY+—w?8iÔc KÃ!°g”ìš œ§é׵܅0ÙÃu1wéûZ` ÚÑ3v>°KÑpþº~Mþbã—×ÜÛƒûSÛ«†ì öªòfªP뺛ªò1TÕmW@8dªâþ×¼šï×&$¯ÿ¦­Äþ\+ñäþ9± ¹øýC’y^_ZÀ“" Ø?ØÚB÷_qµÅøâË/¿xù2U~þéZêù'‹ú§¾î¢ƒ¡ü‡`{õœÑèhtäX}•>è6FþMòÁ`Ô¶-Ûê ;àhƈT¥|ðàÁÒ<–——åÿÇ·òÛ•ÌÉsèó–õïòŸ"ßÍ>géArüƒ‰\žzjñ+,ãùKú“Y:CÂ…kBøáúÜZîìVÅ<ÞÜÜÝýàéN´»»“4Êš7 "QÈòVHÆRtÀ!oŽtÅ4ý:û_ £ÙOmé •ÊÅ C\%ÇEv,6ž?hº±Ã×÷|7ÅÆ. X¯©¯T+z½QE¯Šú˓ܪìÿUñÄ&ÈŸPYs«»žÇ(AžWs0rñù½Áý3±$½àý3s}ÙÔ¬ƒŠ¨Õlˆþß,æË•RêýÔ@”ãóÏ?O•Ê•Jêùkèåû¿þŸìî½Ý³GN¿$_GèûöFöaLr¸N¿kÙÇò¥?ë䊺‹Ü•—V®LMèr?~ ¿¥â&ÏYáó’ÇCÂÇòÌs–VN?–æž³<‘à5Æ?â9¥bnƬŸ2Ú„™ÌŒyoËßëð}¬š ëéõ“‘tÔ¬bÅ@ç>œB7NPkàsÎË%l’~·Tèå¸Eª»¬˜­~çî´Dy«»Q²>^5§Œ¡c¶‰xÂ_¯pƒ¬ûé¦Ë¦{†µè‘‘Û±ŠìÜÎîîÓäïNíìLå´›9GŸsÄ:¹À|=|+Â]žÐ¯“ûWÛ‘ÄŸ)ñ¶cà)½¼|ösðãùZùryÆlœ6Œ7ÅǤ`};þvm—aÈ:žã˜YŸýùd½‘0[“æÆ…€‘cé`Æ]aÿàô±Šî)u¸Q.ëï°Ní< Ÿþç?Uäâdý1½§s¡£zë†Ê^žÜ‡AÒÏ$E¯@ 1;²ýïz>…ƒC:t {”Ã=AcÎjâ1ý:ÔÄ i*è$×WÕMç”SÓùWãš(¥¨ùÞ^\s¾×äUD‰«—Þß«“ýâìïí5öšF½ÑdþO @οÆbêbIj!ÔØ.:¿ Þ?²„áIpáûgþújW Û[ëk•B¹T.¥¾L=“½g½ªa›±Ôë¯ í­{º¶Ø‚ãQÔí:Ž=ìöD©Á `”Ú.¬A¨Á3Ü€ª”˪ÌÙ¬6ç&&`9=ofô_žŸÎ΀gB~,Ϭs¶þËO03Ô`åYrPÉ`1–ÃpoÉßð}"j`‹ö‰ç>³¾¯ö™™c®;`"™hÜG™hâ”?Ú Ü~+!ãMr¬ÿT‚j¼VugG+…N~¬NÂI>¢ÙСHTùë}"ˆ)jÓ!g9Pà%9ðÚL£^¶€r|3>÷ØÛ#5veÙ˜ÈPù„~=Ö–·(™vã­ï³&Î{„f3š>ëHJb—_|þ‘hê®/š^ßÅ€DH’wÙÛë6ÕÐìëÜסîÚžX€fk¯Ñl6äËõš KP¯!3[ˆý`iÐt~»ê‡ÍúLèÃ/~ÿœ¾¾DlݧX+_/ÿï×EùË©ÏSφ#õlùÅ(õ꫞#yÄÿÿ°;êô-›“þ½®sd øa2TlÄhä¸omõßâCL•|ƬÌèÿ>?‹'Î{ GbâLÌ{Ó¾¾8Ÿ‰çdM À Wš¤ºØIÞŠ¿=dê1ùËÔÔüúÊ*ˆtuŠ;…Ë.:ÞüŠ5ÃOŽL(.Ü@fã|£ëïD [1®“#I¸“¬œNy2Laª‘Ø¿û Yºx4&]*‰³Ñà×¥6Õ¨'¢/á)ˆpHÚOKƱ,¯†bò"29¡_§ãËö¾ 'þà5èmïjù/Ò$&Ý#Ž÷.>ÿ]¨ª_õöê1»$]è0jûð ªõº{{Am¯ZÛçøa$PmÏrkðÄFÈïäíÁ_¨Â#è¢Ê`áù]èþ!¡I³qpâ\øþ9ûú ØÚX_+¯UÊe(/õYê£ããTQ‚ÍãĈÇÞïvÄ»4àˆ¨¿Ý£QgØ8ÔòÑ¿Ë*Ö¿À9Öˆ¨Àg€‡cýßÚZâCL@¢¼'Ê=­ÿéDÿ·äOö,/¢@w"ÑÿôÙ`¼b–&çÁE @Ì Š;1“ÑÑÛñ·ë@®Ö¼|"ÖÍ®ãäòHÓCô._Ÿ‹˜øýhÝEq9¸ƒeíöXw6ɱ¾÷ôƒ`<ÑÎÄ~ôÁN˜¬Ïüƒ2i‘ÙˆY&z$„Д'pcPC^¶±ºê­c52¨G×Ð^ï±|´¼’’j6/Ьœ«›Ý–ÁõgL¿®ýº¸‹‰­iÏ~âm†œìÓBÁ~95³ðük»¼}7¨Ö$lª$ö„Ç`qèÛ«‹y¨"(ÿŽ/O”¨_´É~¸ bP"'¿óÅ2âÄUW,‹éü.tÿÔÑÁ¿?M~áûç¼ëÛln–Eù‹¥Âª#Ê~¿þ³cx¥M°üôR/¿ñO§Ó“È €>¶äW}»ëØX?ƒ¾IrL wä—ýžc¥ÖÎ TEý“ï–¶ ÌîîSÑ=}º g€%¶ /ðÉ˪ܧ À8^€é9ÓXŸ5Å|ÊGŠÕå•·æogf>æäXÂ(4»>~Ã1°@Gs1‰haÐ#Їî*dì Æ´G OåŒJrË‹åð£Ý§;žÖÙ½èé;¬/q}ÜY^HèOí7 ÉjùëÕÏ„+*7.Ç ¸ýˆ­qèn…ç‰Ü¸6êÁ*ôBˆaUÆ\kZObtz¸Á ýºÚÔÈ8Àâ$Ï“%ˆ3½?†Ñ`/‚éüEíÑ3'»¹â¤HìdòåO£†ÞõÄ `”ü¾ü:¨‹Ó_õC‰ PÿÛP? f¹P,–ÙÛC´_3ßÅîñÙëÓôá¾ν¾•;å\9WÌvr©W©Ñp4 )@4n:mì_}Ùµœ~·ÛýþÓ?uîÙ¶lñýv¯ßŠïïÌ$ïÚ] þmôØg°À,Q[“|é´r?˜S\ Î1r<ÿÆÇiõýÏ.må¬Í€ @¨ééHçê|*Õ¿¿õmN·ËÓìú ;ê’ÈÙ:}mÞõóiwfþ¨SžÄù¬{q’t±êªÆÀ î²xì©CH  bÞå“õOêäÓ볯”ÔTç]RO²7Ô”?ëYú|EÉç¨ÜMºu0T€ä=îWØŸ4Å+.?C"vjC{˜”øÝ`†~¶%ñÞ•™3" â"ÅÓîEºñɤéüãjĪ_«Wý*Jý^£N´0Døµýúž¸óáÞA‰Àz8»ûFC BmG<þ}‚»ð‹‘¢-ß¡&ŸÊ5Óù]ôþÙ߯K Þðþ9ïú®U —ä/^ÊäR/R½g£g#$‘èwÅWÿìË^Mþ–èm×:ÂHDñC«ëŒÚ€Ût•û<šâ¯g÷oR®@%À‹uÞ¾JÄŒëеʀÕ÷”…Í©!+b.‰¶¸ÏónÕt¼dÜý§è×ñ‹€‘ö0ó0 „ÆÂ+‡ã7ļáüwÑ[H¥«6Å…Gׯlõ.¢ßg™¯¾×¬Õ{Õê^cooO,†ÿj»ò»fC¾?À—ÿØÇ`6 ‰ö‹M¸Ât~¿Zd[=|³ûçÜë É\Êå®S¯SyQWktœ*–+¥M{àR¯¿B›oÏîö:.?ï5ôºv»?´-«;Ê_“|Ðë[à ³G#»3²£($ê/:yÚ8Qìä‘]š3ÉRã'&¿™ &Ú/мV‹6s@F îÍPçüpß–¿=Jfß‘™ ’yØéõ£(©[sþ…lI#Çp´ññ6GÚ°Íê0Á¯µúgÖâ„¿žC8®íNñ×k 0Õ:¥KÔ®&ßcË-çÌ$ª€nÐÔiÁˆe€ô´§-VæJR®7O¿œ@îjÿ¼«e ^Lv(뙟´É™Î¿º‹®¤ã¸;ÈåïÕ|äòˆö}QàfÃÅìO}¯Ñ88Øß#!f .DÙ÷Ä`.ص߫FQ½^é>ÔØR È…ªéü.|ÿÔ÷Ùÿø†÷Ïy×·R^½”^ɦ3Ùt*•rz²×àÃÞÀI¥¾ˆ@]ôúdwï$Ðï‹_ÐZ–ìïÌäv‡ô!]À‡lÛdDÿ¹÷Ì{§ô¿ýMO€‰ÞKdðpÚÌ6©ö/­¤‹ú”â’ÑHçSè’›{DîwÀß®;%ÓæÊS=·> ½ª–Ô1ò]xJ‘@Úž¶ûÅÄ‘‹® “ܰþ„¿žØšŸ†íEÑlÙ*Iú{‘SŒ5æ×è”~ðxT7i|×4;sà—IÃ:·@×SÛ*Bˆ› ór'__¨ ýzâ'"ìp¬pÄÍ ->ÿˆý>ËCÙè÷Å‹ ÀæôžèøÞwûýŸ´ZûÍ}ùv¯VoV%mG *>Úþªl ®²åÚõª{bùª¦ó»èýÓ†Gý°%ÀÞ?ç\ßJ9ŸÉgŠ‹äÓµVjh¥lûCGÜøáвmK”¶ÝÅ̯ÃN>ôóÙ–¨öpè°Äg;¶Ý#s@„]'µºÐ §Ê¿¥5ÁS`‰.ýœHÏ” —’>"ôlÁ$ 0“Ô†#jÿÊŠªñ¡¼Üi°:gr)^l²èÅ“ŽÎ3ù×7S§cÆäŒ´Ú3Çk5)7W»ö4I—D©º~ š©j©Í°:¤Ùð N¯"Ý:]ûÑÅäÓüõðaOó×G »È8mΉÂܸc|¾ErÓû7ÉM×Wpä}8 ë a…b>Óñ„ùSý …‡ð}Ùô›âô4[­=ü3´‡â‰´ÄØ#€h¿|A·€¼iN Ökl„‡|w‘×7ÈÉUŠÝœ@ý‚ˆX àLº†OW 3  EiòL²?>—=á×å¦ÝùãÑ߃|]¨aæ›8ðøXÙÀ¯m¶žî­Ê†¡•4Ó{ì_aCH¢ß®—(_`”Oó×Çgð×£c á„êuQÅ´"p Anzÿ&¹éúÂÅñN`…ÑFïw!Òš†éøZ$šÚÜW@.Tµ¶+z/{ûÞ^M£€ƒÖAK¼ÿŸþ‰X€ŸþñOÒ:<˜vï si€ó @vb²§ õ%=ž^î °™Ÿ6¹âÃÕ”&£}BXº ›|ŸÏï8p9 í8¼BSRïȬ¡m:(ìºÌË1.bs-!|B§†šIÎöjâÃ`'FMÓ9dˆQľÅr}è)™kû$Õ  XsB‘Á 7½“Üt}µÎ}+¬G)ƒÔ¹¦ãkUTÆš{{u€*MR~íi쉀ܖìþ|(ÊÿÓ?ÁCŒ@«ÕÜCY©Àÿ«yKH(g@§}ijˆÍço¼8 *ì a(±·Ç¬æø&ù¹ëWJðõ¶øV/ƒ-zd€ïÓíƒñsÔ¸Ÿìÿ€÷µÚmÈS©ÔýyW~rFGGÐõ1G¸ž€­RðïLòsׯ”üU6“äínfÐvF(>FÖ`4YÝvg$šÜÇ„ÿ‘¨²ÝFÿò.]O© õšu Š£Oý稰T%v¨Æœ¼”5ø,~}“·fc‚ÁxÊÄÀA‹ f‹A~Þú]Êæ²—rÝL~¶{ý^»/ÚkK`ßîýéŸî‹ß }ÚCÈS7~¸ôÃä©¿LQncPžÖõŽlgö1#äŨ zb Ä‹H§çÙÝT%›?ËpËæ *µè/Ë€§’€S]¾é³òªî'àaò›©uV´¡p\n„öoј7ùleÊäf‹ùT‚CÏi.…`7€>’nžÃ5¬L:žƒí¨ÿ*¼~Ò‡ÇZ \jTØ€2Ïv;¦µ´Ò°6ýwW@HqÌ@qRŸ[$7ðÛ3Ù€Ùd‰“~’÷gd”ß¿Qnº¾13–nÒìàé‚Ã’H“䋎¯Öâº_÷é´TÃ@‚~¦õµ–·ƒ¸^óbZû ØÄ¸ ònPµ¾G\Ðe‰½†·»&Ц’º IDAT1ÝÆó7€†ÆèÇÂü |íä`ÛLòóÖg(þÃl&“Íåœl>ÛîÚÀöµŽ- t~¢ù¢ÚNÐñð~EžJ]þ?ÿÇÿ%òÔ_þuŠrÑw«&€pÿÄývÔíÑ~Èîßa ö  áÔF1}Ž($î=-À$¾ŸIžcN…S}…ÓúŸdôÄ̇éâÆ‰È,§‹ÅlÊ×Ñ6D¾Z†6ðÇkÇG æïæŽ'¡^H¦*BºäÊÓ¢8A®ugå ëù²|±€† >Ô”Ô@ØŽ´ÊO`žÈ$7ñÛÙ–¹,"F’®Š¶¶›å¦÷o–®/a…cïd„nI³ÕRÖóçSók{Õ: w²kñ5~ô{uØ_û`¿y ú^çDZüe—¯‡ ¬í1ä¯*üϨbÐeÚCÌߢ”£ÝÌxà“½€ü¼õ“\\v%¿’ͧ³yqՇѱ½Ç—¾?êòC<÷v¯#»ù0•ºyû×SâÈ‹þ«Üî¢Ç#€—}ŸIÙí;C«ÝÒ%sžh÷SåU ¦Ï*RUÅ Ù¥$˜mòQOO¼¥%"ÍxI¥pª ž5I`I[VV`–N€|zujP܃²¸)f¼eÿe³\»˜?> ÇÕ½ñƒ > ÿÊV¿W«»E0¾«îÖCô€æ îE»b «nu¯êG5Óë_@)|?|Vg=û ½ ÉÏ^¿R.òÙÌ¥¬xiQt;GZß~gÔýPTV¶î¾mwÄ÷ ¬#§+Û{;õÃß»zùÎËïQÿU>ìÙàþ=’í~Ôé;ݸ]иÝu˜D‘ÑéŒF#€ÜJö¬$à’*vvâêÏáý-ñ3€ÀÏvNŠ“ï¦ @¢ÿ'˜=…i]Émœèÿ* €vµ²½”?þxæ`¹%ò¹ã‘è ÈYAœE?§}4· •p.PXÂí"šC¨úÄ¿'3µK¢!8¼œ2…±O‡OgÁ 7ñÛ<€~±JÉL¢¸”ÜoÙ…n›Þ¿Inº¾qâ%øÌWvîæ~«\Ú®oÃt|X-ôLÀ.u\UÚ(x­Zõi@±WE¿+N€²áƒ$†%@/A­éW=:/ÕZ-ÞÝŒ¯o|®:{œÍªúˆ 0×$?}19Ñ~G @6›±''^<¸ýމí@/Â[F|†vjéêí¥«?¸óŸ ÿyÏ"ö÷‘5ì´;úžmÛ  +¡?{AÒõaÖÖ³³g!! Osû?ió;5|ÊD-4Ëöߪllï ƒÏ÷LÇs§æÕ¼zŒ?híèÿ]Uz·¦©Áš‹gÀ,ÀeàSê€ GdÀž0”@¡JX?ªnՋ̯¿XîiÏ—Òì#4b£–ÇFÉ5¤Åòó×/W3¹l.ïä¥;v¦g%ò‡Û/^¼uÔè7 }À>J]YºýŸnýÁ+·ÿ—¿N¥ÆrG‚ƒ¶m·äýeÙŽc:è @€ÕïP\l˲3‘ ²žy˜9úk²‡ë¦|ÚŒwë1|XzéÔs¦c±EÏ™Vjø×LW0´góiDm5ÉMïß$7]_¼±1èh«ÒjÅž¸ÿåGOwZëë•b+2öpÀðb¤OyþâS¹ÝÛ£&&Ù=ŒÂ„õzcϯ)EpÕ(4ÑШ€,rC1®bô^ß(W®އ(¯ï%” q˜t=/”Ÿ·~e1ƒ|f˜IçÓòC63rFöQ¿/_ÑëÛÜÀ~PÛO-]¿}ó÷®þàö_þõýøe*‘w»¢ñvl€x@–@`ÐTF0 €>Áže·Å6¨TÉ,gN€ª­KK'º}Å]>÷9¦`Íë<Ðç¨ó«”N ÿ+jbzY¼®ä€NZ5tÞm<ŸMñÛûZ¤õ’†ÛSÇkÖT\l¬'¤+€\™I‹&È1ÌüqÉpŠœ.ùCè}³4dÕ½(dÃX,µá|Û;ž•›ð۳ɞ¯ÄM½ÁŠUk³ŸInzÿ&¹éúÊ>q×—ï*¥RË“ï·?ø µ!ú_n™ÇU®E@ï¬!Äß«×ÔØ¿úý½º_lL"&È}~u?IÜïÖÜZ„Pˆjbzý…r¢—¡ˆK†cäEdÇ`»Lfåß~{J~þú¨bH1 È;Ì$°Q·ûþƒ¾hwÌ_£Û?¸}óïÜþ¿~ýç©DŽ–`Eüê¢×ׯƒÍÿXN§'»?º½£Q» 3…Z-®­ˆj΀gRz¬¬÷Á¹Ï¡þÄ.¼ €xükr–‰€þç&Ü€HÖð ñrh»A÷’Ç*À®ÙÄð^Çrcæ¦ÔL,–‡Ü§ÑuĦ5žß>™ðX]““ ùC°“„Ó"¹ñý䋯o3jmm®·Zû-Ùí+k­Õ‚„]ÑñßJ•JËøù¨¼ {çViè_#È?}$ú‘ûG‹ ƒê@ qµk°@V૲çV÷ä™a "ä4-y±×?_Nºt²£K P±ãëDÒÀyùùëWJeŒØé¬…tf´’Íu» Çgã» ïÅ™ïá«8wîÜùüå¯^ÿ×Ë_ùç©Dn÷œN]>Èù¡1áöva€†àNWÜ´ˆSa·­13P¡"Ê91ùsõÕÉsΜñœý¿ø:4ËéJaŒ ¸¾º"úÏœ“€Ìd eL›štó*ƒ:Ù±òÛ³ÁF[Â]ªáÜñänu“Auäö’Ží8gåh#.Y¸m»:Ö˶/l½,°ŠRžfú5†_,Oêî, ÛOóÛ3Ü 6©§Ðiíubr±Üøþ ò³®o³ÙÄõm6ƒ&¶þ­VkíÑ£ò#yl®–+;;ÍÖ#0‘®W]Óç3%¯‰Úo_6ÿªùèc›(€ \fJ׌Uq«>B·F< ¸j¸ZA˜l¼{ý3åä6Åçãq’i=0 °L‚‹;%iyƒ#ïÛ‰|Áúåòjn%É­ä²…X ëdry©»^÷ˆ•;ÙÕ-ù+^€ÝI]ÿ£¥wnüàë_ý?\ºöÙ/S‰Ï—¯8<á# ý;ÊÞ±ÙL‚€lÃ4' S€…ßís²ùbFô?7á,¦EÿOx"¼±yÂýeU.T:›ß^1«xŒ§œ³ÇÇ ¢Ç,¦¼\EåŠØÈèÇGz?­û'ä8®â]ßÖ!dá@ÛþIºÚíg£õnLºáŸ€vLøíu°:­u¬¸ ÈHX¾Hn|ÿùÙ×—W‡ÊquÐj=Òdž|·Çß§(¯ï> MŸÏ´<à`CÞ?غǮ!jÿÈ`æ'¨V™Ù©Õöõª\:EC5%®Ö9žãMÐH_üõÏ’'}þ«.k¾¯h¡ÖU>& ù·ßNä ÖPø«ôJ®—Í¢0—IK,б2ÑßxÌüwèÑëØ£Þ uûöï-ÝúÕ×_¿þúëOž§Ærñ0÷‡ap„[ƒð_B‚ž3¨Ç‘üÛ0AÎU2ËUÊÅÔïö9Ù|AâÿÜ 7`6S.ÌLë„™³'üë ÄÍ<¿= ¸¬ðÏÏšæòvõhÒŸ ïJ-$Zg¼™ïæœ,æ9è±®ë1eÀAƉìÔŸI-õ>9O[¸ûrWöõ]ù@žÆÀžüu‰Qê]èxÒB¹áý›äç_ßf«>6åõ½ßÚÚ¨¬½ÿþÖÆZE€GõÍòO×ôùLÉeçŽwk àÈæ¡àj}¯Q¯‡Ðý𲳋ðk{Íú¾çUYñ¼j\­yò -öY¡Üþ¯öýãê4”œN¨(Ü1lM8‘Ÿ°ß‚<4‘/X¿"¡Ž)‰.Ù™+Ó·ígÇÇÏÄo•íXÁþŽºƒvê÷oßþâëTêåç¯~žê'ò.¬€ÿƒ9‡|~Çé$Q¨¾…ùBØÆ'°àâ<,A)?R©ßísò¥‡²ÿOÁ‚gf™ &´¨> xèÖœð¯«ç>Ëo%m~>q¹‘³=ÞS”K4t³‹ütŠƒå³·†Œ/:e- ‰ªGD_•Gãð€­Þ¸C#M*rpÐ(góHB³… ?d§%8¸.oÅ€gà±øÈ^BÈ8÷¿PnzÿFù¹×·yÐ@ƒ^³µ^,n=ÞÞØ~üxs½²ñ¨%N@©UÝ}ú´J"Ãç3#¯Õ"ÒýÊ'R÷µhwww¯ZcNÇ%k!‚„Æž¸b±ÄøÄWù[" s™y7^–7yý3äìIF§”Nøй„’áNä'à1ùùë—Ñ é;mÌà\ZÉe²ûg3½¼3êž}ôQ¿ Þ³ã6(ÛýÔ]yçæ•Ô(õúÓ¿Hõ@n;C~XäïûýžÝ"w0èô„qº6mƒÝsF££)^€låaZ”rñƒœÅ¿Ëç”Ò+Ù)^€\¾8K †»US1ÑEøíÕOAî¥@[sÇ{‘"àò£ 9ÀÔ—›pçàY‰*ýXÑ·tòÓÓ9á"í×v³Â‡ªµ;Aø^(MüõxaŸÌ_!áÄ5á|qMRä¦÷o’/¸¾Í&€òZ­òæöãíõ­Öæž¼¿Y^[ߨØXoµQÓçsZ.>€W %ë^-®6T¶›¯O½^@ýU‹j5qUªâ÷„WÝ¡¶V‡oþú§äÐd%¢ 60"„l‘O,èçäç­/úŸ (»o kç´'ðøxðìøY7ë ž že²½ž“úƒ¦R·~ê€8ÌîÃ* H÷e÷:Åî•#ÜrÚÄ`ûïÓ6Œœ~ÿH¾Nƒ”òSÿ᥇ùÒ41H¾8OŠè™œ¸‘†Í‹ùí]l¦Ð[—¬îüñˆwµßŽsl:HõSb 8ä‘!bÖ"5äœ ÉrÉ©;l¡š:ˆØ‡†Š¶›ä&þz…#d]/éËaC"½Wì&F¹áý›ä ¯o³uØz´õ豸ü[›ÅÒÚúû­m±äòãÚ˃lo\øùœ'G¯ü  &oEþíâÄnW¦Eõˆja¼\ ³ŒÂK`•öŽÛë劎B”Ze öpt4t“Ε7blÄLä Ö/—.ç³—8ÜÎd²¨ö3™®öŽ†Ï†Ðýãòq¿(ÛxÚrîÿ¾lÿ·/Õ•=½×È Û8 ,Ñ~r„÷œA§ßA'‘ÃÚ íH4pdÙ£~Wmô(WTéV3 «¿ÛçäWŠ…Pž5â]_˜ßC­Zmc Ÿ:>"þPt=ù •/­u>Ãq¸É è L‡H«ÄžR{³¿Ÿ¬7âDt©#¥ƒvµ±Î gÁi=çMÂ1ˆ÷eö£G £Üðþ×gáõmŠª?z|óÑ£ÊêúÆövmw{C~±V.•V‹•R †ÏÇ$7]¦=NDôþYáUñ‰²ò–¯b d€ÇK“Í÷‚«]bïÔ[ÓQÀD~þúkåÕB~%ÇyàK+ÝÜJVl@7“מÀž F×GýÁq¡t½4h_²3ÙÔRÝ~ê×R€‘Ý_b{Ýøb&Ôév>ìv{NÇêuqm°g©m8Ç£þhÚä*jòé•EÕßésò+•Ü´(Tf ñná÷^ߟћ¯õö¹ã±Krð>ô ã Hg7\L3Ï™n¢Àgp9;ç2Þg#AÌfö˜Ë¸™òéydà¯ç^ÌúJs¼8F½Ø(7½“Üp}ÑõóøÖövåQi{{gwçÑ£R±òøÑ6œ‚VÀ4ÂâÏÇ$7]è`Œ$(Ñ”˜AM È›ßÅëcÀÝ{¾Zæ"° ø UÞh¶šû À$ ÊÏ_ cp9²þ‹ø¹¤'0süìx0:.¯Å–Š=ÍR?¼ž²R×—R§-P¿Hû[]Ç t,‡¨À£¾eRáÛîwØø!Æ…f¸Õ€úû>–ù…ýÿaÁ§Ÿ³$ÆÏÀó——äÏôsÆ«ôÁÒr²ôÌ:ËXO\Ö×| ßËs +•nÀÕõ¹€ioNï^ˆß> O;Ñ;˜%›?žu/†ÏÌ'Ñ>s/ÐãÁô$ƒµä¸t5;à3Ûæ'¸ûÈ%#!Ói:æ&ydà¯çHMt’C¥œ "v¡k’›Þ¿Qn¸¾ÍÖæ£ëë¥Gå§?þ Z­UÖjO?x´±Ñòôú›>ƒÜt}8¹!oy´\¡„ÁÈ,ÐAˆ·~ý aõ‹˜BwÒÂÐm 4 ?h2¨^?ñ&òóׇÈrœt3Y-fsIO #ÑÿÿW~6<<[->¬–¯¿wýSƒû—î[Ýd¾wÐïôû€þôF=«=KŽðP„ö ŽðnG¼1Öˆ¨Àݰ<Õ7;§CÅÅst‹^^YšÝ³—W:|ê9''Ïž{ÎÒÊòéýÏ)dÖf ÀFy> øFüöïÔòkäj‰oæøH]8TÜàŸÇ ©ƒ´Xäê€ZwaΉ2Ã!!&í|/ F(;ª*¿Ê¯ƒ`žY¾˜¿ž%y¼%åÿBÇf•èù¤ÅrÓû7ÉM×7j­o^»µVZ/ðãêNÉÿêÓ?]Ûh%¬‹7ÉMׇFKó¸dæAü¢!Jço|²‰³Q:iíu½ !ø6CùaõPèòøv"?}Ts™ç³Y¹½Q\Ig’žÀœs¹Û픎û¥Ò¨X<.=[}ïʦº©?J‰n%Èérߊßß0Qå›N·ßï Ú¢úHä†!؆ckÖÈŒ[³ç>f)½–çI‚ù‹ó˜¤O† fŸ³tŠl8Ì ¬ff=€â¼ˆßß>JxZ¡YÛéãÅGF¢ž@|ÀÃÐð‘\¤ít× PRV´*gT¨m‚ÚŽƒ½4àžhᳬ&y’©ŽÏã¯gúž&†Ù¬ÈíD4KrÃû7ÉÍ×·UÛ¼~ëÝê?õ÷ãê®Wu½ïì„ä7Ïoñõ ˜TGQÖך‹Q‚‹úÖ¯'ÃÙUªd  |EKPy«qÐ:üæÛ“ÇD~îú•›eqÈ" Ȳ#8L “‚y'gåìN¹\*¯‹S£Ü3$ºÊì @nÖ(2oÆo›†Ì˜¸%bÖÌñ.ás™¤Éø”$ý¡IT‡X9=\â=rÇö”ÍÒEPÏŒt†9_”…ñD6ÿz„1ɹ³,à¯Ç81Ò À, ó†!O & ¶&¹éý›ä¦ë‹HfgçÇ<Ýù ê&½OhØÁÒ^27½àxãú†ëƒ¶{Ÿ±Ú5XO 9‘À•¾íëã+xáÅkw15šÐppùacÿà›©ÇD~îútò™\`·%.@.w)-þ?“ðò¹\.mçÚ™Êq©Ð{VIýѵT·—zç]vEµ4tm”þ- À€ÌöùSQûâHd0ìY°‚`ª`6 ˜-Œ‡N‘þ ÿO+îXÿ ú}¢ÿéi°s'  }/̽’¢­å ÀóÛûlºG‡ wâSÇ«—W=`¼àJ‹þÈñ–'~hè)èžÏÌŽ¦Ìé(h8ÁJZ(hË<¡Qnà¯g=PŸ?Fá‡Ù€‚j™Ò 7¾“Üt}ÅÈTwwªþޏþ;;ÕÝjuÇgøír!ãñFùâëã¹êl¬´hs#yOĉðm_î%°­˜ãô¯ÿé‰Ê› 0îï6æäç­¿V)\Â0`£@¹•Ì8 Èÿ2Ìgìl'—îe3Årá™uï÷RCËIýá•ÔÝ?ÖжíA‡µ@ÙÚ=Qv1^Ïî÷,Mö¶eY£N»k £5š rE³˜ãO °0åL @ö¼…N À4èÒôc«@P*æf Àú¼xC~û€ žDïeùíÔñL~‡Êuàœ d“j &~Ù-èYJóä³\0àú µ†ƒI÷Ž#ÇAnâ¯çY1±t³bvÄœÝ!jxl’›Þ¿ñú®/™¢öíݧ»Ê¾MäÄD 7É ×'dó% Ÿä(SØvîFoýúì%ê12ì‰tv<Ô ®DÞXéAãðpN~Þú 3H!—4Œ³€øO”+7ìç-1Z(øhúÁ¥Ôà™“zç–.ÝÿP¶û¡è¹Õ±Cƒ~ÀäØÏ -¡¿ü W ã ¬~1A¿‹ùÁÁŒ(—Ç9¥ýËÎ*äÒÖ œ÷ä1ç~ÚXÚZžÑê¥åd­)0Y}šg,=6ùryÆllœ*’e#º ¿=Áa˜Ìuf·æŽ‹Žœ·&èþº:¤4ž‚¸Á“ }tÍ¸ÌæÂ¹Eâ·d0¦›'®NŊͯ|y åœÅ™Ö 9þzv÷&=K¸³<ž( ”•Ö$7½“Üt}¡eaÂBZBvV3àa„c<Þôù®’mEÄEtLŽ‹NU+åï[½>Ê$úcXá*’C¨¸?>™Çòƒƒf½~ØÜŸ•Ÿ»> @&s)›\ZÉ¡xœÄ„ Φó\ÎÉçVV²ÝRô{KWî§R©û©”¸þ²¹÷:ä£`Ûe?æÁ†ÿú—hÀîÊÓØ. ¿ìÌ€<€ÄÌh¹€Ó >:Têl‚$> ú^Ó’á0ˆL­£¨Â³ 3ef¹˳ä ðÔ Ô‚×…øí¡åÜäÉn0<¼1ŽàQ#Uµa¬Ùz¢aÓ¿Èæ¹ ¢kŸˆO>»(JêÎ8"Œ#wŒÄã’VžErWË |Õø þz$ppšA^¤«qjÏ$7½£Üx}ñkøÁÔVV;Hã¤Öp¼In¸>ä?p9¢Ó­b†.b{žv9¿Ýëü1$˜sH¶ÔHm ˜ˆž0–7ëƒýV³>+?wýJyõRz%Ëü¿VàqP6|Mˆ9Èãwmùg÷UóŸ†ýãÑ1Ù>ôÛ]Ñý¶ÄÀ®o[»ù =L vƒó -À˜(Qsý>í(<ø²b~oÍz jÆOL'(¢³à! Ǧ ÀÊÖ€8zC~{ßKÒ¯“QÛÙãCíú °;t‹µŒ$“rª§í€¸ëÐu£\œÖÌŽ¶åºÔÁçãùfy´˜¿ž©Øã $¢è#‹/Sø‹åÆ÷o’›®/ç¦8|ƒ(l¾‚EŠc:Þ$7\4qã³ðÉ«Ù{M¹ ݾƒ×4õøú bÞAS4¾\”7­}‰êÍæœü¼õ+å|&zàœxügÅ$0"¸Ð.`YélײœaÔwl«o¡Ý‡P¿Hð‹î÷ñ³ætûÈ ~8°;}Û")¸…6°ÃQ:°Vo‘˜vÆÀièÿC~£ÞüŒ8Á Ô"à© °¼¼|kÀ?ð`ôÆŽÂÉýa’ߟáóczÏš­úa«Ùl6šn‚ÄüŠ{îõ)ƒ¡+H°\Vô,—V-ifåŸÈòYT †¢ÿç{0û’Ÿ®huÛtÀÆ qóåoÿÃ>0ÃôI/î OŽO­Ÿd—¦\€ ïÇ© 1éœðPHÏêÿ¸jð`Ap¾XŸ5Å|Šmê!û÷Ѧ6¡ñнö4¿½˜µè IDATIŽ‘¾€<Ìœ1ªãDb<ÂB¼•<2ñÓ'HáFYõ#û2Ë>ýñS1öœ %ðUPð œñÈÕÁâFl aúà-„,yO^K¤ÈG ¯AY!+rUH½ªcX9€¿ÊÕ‘oº€Üt}ˆÏªo sÍó÷‡In|†ÏèDäþA‚XAÕ&JþxÞõ¡Èçò²Ç‹ú‹3€x '[¾ø錺pDs2Ö°ë úDz‰Ä“w˜ ]P~ˆïô ²ÛÛm«ßïˆ$ì3TTããSkçuѹ3ÿa&À”rÏ0eOéÿ)°¼uQ°6k䄱e‘Ÿ‡lšnòžÏoo’Ç' ÁVÞ´ZýÒÝ÷måÑbþyN!…œÚU÷RýX‚¾Þý@‘ ðh> …m ¢ˆB6¨(”hÄzlJbÆìi&-€u@BÑoL×Ï‹Np‹°›]¸ ßѱO¸%Ì' L—Ð0³ d›®º6d0Âk:{˜äÆ÷gøüôÌØ4è+:ˆÂKrŽC¹ÀÏ»>•Òj!m¾PÈ"ÿ/Ûÿ ý\®¿|:·’p`:j[¢y þb´ ²å‹%è[][6÷ÑÈîŒÀ"HV! 8  »òײìaŸÇ/ Æ`ZÿOuù)ièò™Ê=M-<¥ÿöÌ9€R‚„ÐÞe^ÝÄoo’ûÏÇ;£ –<}öÿíåþyäჄOÒe_¿§ý5A⮎Qåpç+°Ÿ€Ý©CÀ»2Ò'¸¬ú‘"Zdö4”1“ÝŽ‹¯„‡A'jBóõƒ[ Áapá½61Pv]L“ö +¾†&A¬sLF¹éú(ô'í®6nÏÝ&¹ñý>?‘ê öq†Ë6d"˜`TpÁõ)Áä³HdDõW²ŒùEàd.]ë;mñ¬^->#ëx| õ­¾3ÝÇœ_4èŽFÖ ÛÇ”`ÏžôØýn·'û¿ÓvúV»ÍãS¥E@¹ý5>ÓhÀL¨0[H8ÆÓÓ¥¹*ÀÅ=€Ò¬ÈŠÐF¶Øë º˜ßÞ$çæí‘¿“ø€¬Ñcì‰:Å};¹ÂtžË?ï%hŒÔ9‘£?…c𘂳O>ž:<5ð­Ÿ}*¬®Š³ÏRZœ€<ý\’@—0ðBòv73hcØZ¢é£ÁàÈê¶;#˲ú²ý÷Ú¨øõz£n¿ç´û¤ÅŒ@×vz}gè´0<Ðæñ©â‚`û¿?,{ÒlÐçž fõÿ-rÅ9O%TÔ°ËÆ1ñÛ›äØ `ãÿæÞ­·‘ôLÌkuÛ®JåIIQR¨DÆAF’80¼?’Æï„ë§­£¤eÃä“9…ª±Ô½v~|ßsÅ °PüŽ?‹ã¨šyÒlÙ9Ç><Ø·±ƒÈZ>d³ïÎîуÐUa€Ç[q àƒ­Ãc1v¶··ìí¡kˆç_ἪÀú·Æ† €8oxÞ8·þ¯6£ÏIöLǸ·£@Õ^—©Õëõí“Æ) ®@OÆyZ\ õX³ßpa<áTÐJ¤¤Èi];zãñýù>9nð‡qSïé~ˆh¸ בãRCQYå·àŒÒ¯Äæ“Uk¡¡-œL£ÕûLjgf0B PlKðN¬[4Ü*ÑîÀd7ÕMÚ”ÂdˆÁ¥Ð%‘.·Ñ~Œ‡ û*I˜4ž8?ÔUƒù#cCûÂý‘4žxÿ\ýˆ"gד2’’C‚ *HBªe½f~|1ž¸}â 䈶o› ±Æ-å !0P‚}è€?ÚAˆŸDû[[Gìí€ÿü€;{û‡2º 5±c · x¸·¯çnRàÌç `¬vê)(@Ký#`l¤%ȺÂÔòêJðY|¡K’€î9`ѰpÓWíËõí[}ûKÇqÑ”òŠä¿cÍŒñß)˜-|ãñ(I>î˜×Œ¹|X#HÜ~]úûtéYÇ혥.Rꦙ*¶7carc MÚ„ ¶CR!‘ï†q…ö°uçOÛõá9 ¶ 5<ö¼†TSJ†>¹Ï¸0ôÓ×>i(é=º·×@‹o(ŒsS„wÚm+wNÜ7Ç^T¢ý®¦4‹ S]vÕt˜ gù*Òåö ó©l÷»XLªDÀ't)®Ëd35²(Çâ x)q»‚éÚ¿éx¢þ<ûUBÕ ×Ñm—¥¸¸HKóì"“‘ñ¨«¤mm˜t/&ÍìqsbAŽÁ(.D‘z8Ió£ç 0ýŸÇǸ|‚+ ƒmË2•+xwûøàø¹½$ÜßÙÝÚÙ9|°EÈŸ,v@}··ÀÌŒŸ8 ;Ð Ù:<<ÜÝ>ÚÛß:ÞÝ6œë À§)üK¡À—€±üüùÀ ‘ý@pZ<ÍûŸK\bœ³À..¸†^¶úUzôí/Ó§ïŸ×^Ù^Œ=SƒNîldg»Ú¶­w@D:¬¾Z7W4ìÕúóm­nõc˜òæÊD¢_Ùj¨<‰[Œ`µvïæM߸ß^—ϧK­Xw;p­¹YHÍž;8­aü+Ûaâüµ™‡èµ»º úmJ3ÁÆÄ‘ùí¸Ž&EøCFø1¶éúñ¤ù!ïg—J €î_¸?’Æë×g×#R ¨6e²½×.q~ç“IÙaKpÞ\È“*Ô·lgŸyå Þ;’ÈßÇ{;÷Á¶³*p–ö¶¡¾§ö÷Ä ìmx° áñûG†í¿^/À™*ÀUëÿŒðÎY £—€øÈ×Fû†ÇÞQò‘àÛ Kµ@Û æî“`ý}zlQ„¾M‚U Àt/nðŽVyzªÌƒÿ!?q3×ýéMÇ“ôçûD©`AªWßUÂ0²yÅ Ø63üYáMùè2jo«pÓÙJ6I½6(vµ£°Óë„M(jÑŽyïcÇ»G¦!•@Jš?âäÕî 5N\*¤Ã‘ýìj¬Ý¡4 ¡ËÇÚ÷Ce!¤6aÂxÂüÀâÓÓ7÷ÏßIãI÷OâõcÈ(_™J)ËÐ¦Š´Ä‰ósz¾xr«ÛÔ #À²Æó¶uè˜Gf>æ Æ2¾p Ÿ>€ Ú$Dx$Ÿö¡üºÀ;ÿ÷öà -p¼{„jÀ±á¸XPùKÛã5ûŽZ€ eÀË Öÿ;ó—{—€'qšüÏ“,ÎäaÜÀ±óEƒ.­2S$“š¤Oß%\#ÔV2–Å» Ù§L_DÈÞàèÅ;yBTÏ­ßsòuã ç'éÓ IyV‰ØD§tÜùEBœ¥©úíñ^û-Å‘‹ÕijðvéÚòvë±M‡?AÚ * E# HûBヿïúùI}¢°ÅõؤrcεI°£ë Öòd_Á~Iã óƒ£{ÊÁ¡31r$'Ý? ׯi_L%Áب^UÀÏÎDCÏÍÏÈùüÐϵò »P° й‚ïK´/{¼xüßC‡?¶þÃã{;{ðö÷¶ïCdƒÇÈ &QƒåÑýûÇFÑ. @ñ<€ï`3–¯ù.Ï€&ì5 2€ ñ?& ì „Å¡(ÙgË€¦“sÄèÇÀX(7õúô+Wêӓȉ¸rî˜&ƒA˜…x½GP‰òá‹Â‚¯úÐÝP=åPõLâñ'zûY¾²Êýùˆô’ôéYp×þc6ÂPžE¿Njª£íç­ÎÛã]z `‘x>ÜœÚyÀ¤á(Øpz‰â¦}B´’ÍjáýSŸ5iþîßgߦ]:áÆÊší”7TæU@¢äñ„ù¡—Ï‚a+ó™û#JO¾^áúÉ  ÚŽpƘkèR¾£¨ Óùhà…ù=ß÷ è°#ÐAaÐÚc—`!æ ÞŽ5>wÑý·»ÝŸ=t ˱Üï÷wîC3|ë{¤-À.Föö!3hø²Â®2²¿£îx¡p‘èRÀ¦€ÑÅ­ÿµFðÎ…$ ®ÿùá?þ=ï‚p,ÿŒ°ðÃËmµZØås¢>}K´Ã· ¬anŽ½šƒ”¬Ša¢‚Êë­¬Éι¼¼ütùdñ¤ß7N ã¿™b¢åå'Ë'OžœœÄV ÏLÔèùzçêÝ;ç w¥þ|ÌÇßSrÉ“E¼½ÚìgŸa'Æ ÉÍûö7¢·n)ú†$€¡–ûC*Žãm2÷ö*¹it­¼9¥nP§Œá Éd›8à ‹T¼“åqe(!:nYhk^Põî玬„ÍIãIóC¹ŽvLÐã9'=¶ _2þ:÷OÒõë0 •›¹¯=M²õ³†*ï#<3? €z¸<ë«áü\8_¯àP+»Þ´s¶õž%NÀö¾i;XÛû»Û÷YèCcàÎýãÃýã­G‡û‰“Ì ï "a’ÀôÁÛû 1*ÅüEp5'àé½zý_H^8ò£ýç’c£@ S/VN €9Ÿ/-C›»©O¿±ÒZÛX_½VŸ>RÎ-jÞwzº^É”2ûÓýv´ö­­¯o´d—úäéòÓÅ“¥¥å¥Žìþ^>ÿߌþ‰…ÅÅO?~üÑGòI,C»³çwOI5z¡ö–'êÓóöd¡ŸÛÓa«aáAÜ ûs d²;öÛo¿5~säƒW+;z7nV鄊^ ©b×SyB6§ôHF*£Û|õ‰DRÆ\hXúªÙuzô1’æ/bß/¦!ö‹–‡ô‚ìƒ ‰À&õÚ1GAL˜~ÝxÒüô•‘] Ú(ØVÖ5ØŒN÷ŠñW¿’®Ÿ–ô¢ž¢|tü¬>Ÿhüq_}u:?ÏJ>Âæ-{\ @ÎÞµ@LÂ@skÇ4÷wwÄÉß§2ø‚÷·èìß—Ç¿³ÿ¨© R»»[{Ç»b€0¼Š‹`úÈ_0g*€§Çy´àÙ$Ý'ïžé7Ã+‚DÅ+䣯Vkmó:}zÒ{Ò+æZê«Û%r~@!K<Øy ¡ÿwhö!ޏŸd€÷·ˆ{@Zð úG“€—-Ú8YŸ;]¸cç1þƒ#wÖ\rX#Ϲàœ¾ÌÙ$ •³+§ëß-’¼óPµÖVWW×Å…»NŸ¾Å0°.ñ—īˮ"rKt™Åo­¶ž<ùè£ßüæ·OžüæØecY€º-뿾 @ÿú1׿JñvÏœO 0`PkÇôçY {Ì­¦ûç ÖI8AôŽòLGÝ·¿q«ÝI2u4J's=+tÑÀõ`Ç|¤ôÙ¸•ãÝ+ŒÓ,äÑg€tùî(5ÎG©0̲aÂü×!¡PIs´¼ÕeÞŒ1e"Åd€Á”x :ÈÂ%_??e!Ej\{§÷G›IΫÇ_ñþI¸~û‰{ W€’7&i‡ósjNN¾ÎÏ¥çkšmó`ÿõã9Û<4¡&¾ëì߇$ÀÖÁÎÑ Àx÷Åûß?ÞÞAУýG6r‚ûä|(‰?88<@*@ @P¶FË€W®\îÿè眷1#Ï–¬rP¬ÿ‚€¬«ºôãx¯Õ§W?¸K•Œa“7ºIˆ#׸“¸·Í5,ÿ>úõGtòóä“åå“哦ƶ€O?³€§œŸKÏ÷½¢Kº0kýÀ€Y°¶÷ìˆU}¸m¡ððøÑÖÖ£ã‡vË#;{»yK<ƒ=YþÛ‡Û‡¦µ+ÞÂÎñÞñ A¼¼DÔg ÀµÇ¿ìsb ¿üC ?9y€¾ò²)“g«µž O’ R¼õÚTåh#?5Ò•KIZíAÙ`jï£'œÈÿèñÓ§“ÆÉI½"æøI}ùéÓO?}¢Þ?ãÿ .ëß^Zl`)v¶#ƒ;èzýyÄ÷à§b›þÇ*ÔZfŒÍ•*²¯ÿÖx'zë ЄžÛÚÚ£¦ síëíX%ŒÚ” ®hÇ,ad+§cÀÄ€Ò…hj‹4»!ùü i•0øÕ(®‡l  ìÄ´ÇL(*ëzêiôƒ×OOœ2õÃÏî¸7r0,ºfüë‡*_ŸŠRª$ÖVôÿ¨5˜ŸÍ•þP=êÁƒù¹üüÀwÅ 8Î~àX:À>0Íí(»?4A ù‡Z€D,÷ïQ7p{ûpß:Þ9Þ•çîo™2G%pï8V†8Í\ÿ²Ïa _<5Xÿ¹ØtаÅr¯×§'ñ›6겦b>dÚÐ^  ×øàú“ÖZ+Š­€±Ÿ>^^ö\Ó|úäq£ñ® èÓËŸüßíÿ¾TëDZöýúýyjsL ÊÁëýÚ×&°„TÝèFÇŽµÇߎÞ?5Ì¥C,*!¨„Ú•ŒUËDår9¢ÒaŠ \[U¢X ˆI56ªQƤC¹IóÇ´]½=zÿ .£w©Zim XT³B¢¤ð:ýÄñ„ù¡·À¾Ffbú£÷GÒxòý“týºªH¢¨ Bµ{£PmŸÍÕÕµ^t ççŠó ×£n ûÇsÛ” 3·M'ÆnïŽïn©>èÞöVþµ¿ww÷xëÑö±ko+?g[ÛÆ÷LË1·¶òà^~Ì€ëÃø—} €iå½BA @ÙÃú·¬ÀlZÓ„òRâÁ]¯Oß#ˆ•¨q­×Óñm#aǸµ¹¾±¾.×V¾Y[Ym=é<é>ùõ“_?ýÕ¯~EPêXj·Ÿ~úX·Xø>½qbÈ…*×y›^¢_Ÿ¨?µÇZAGã²`EÃÏ&#!¯”Ãw=>½uûl³ Úx:Ý?¡r{°¾ÑnþÿåÉá.R ÈÁ4}ÝóI0Bä nãí¤ùCˆ¿=dàË h¼@¡0¥@Š<äÍ#&] óýŽò~]7ž4?ðH¼€òyFî(a<ñþI¾~1[8Û`:#ÍZ:?«+›këëíÎÉ 0œŸ+Îä:vÁŠûILå0ÓŽ1&X¿wAö ÃüË£ýãÝëx{ëxKü{owÏÚ>° À¢ÇøØÉßßHƒÑ¨¸þ æ_ò9blgÌô{`Üœ¬ÿ¸j@¤$,½Wѧ§° @dݸž¬4Z]v‡Ò…cåS.Îjke½ÕÚØ\Wýù““Çºê—Ÿè ¹wþþHO¼’®ØèøÁ|Jd´]›ó³¾²±¶±¹¹vÆÎÏçûž Êà¼Í~àÃí¡r˜cA÷ñÒ>Øu¶Âþ¡uhï@hÏÚÙ½¿uüèЃԶóæá6ú ö¶Ž‡¤ bæm€m‡åzî¼íÙì(7üb^¼[{Ô0Õ23+Füz}úˆÔ,Zž%÷Ëó€·w‰Ð’; µFU·ÖÊ*¨Ý7´~ß®Çëÿi½Ù\\n>= 8yÓ§çߌi¬]¡_¯¼«õçÕµF»›ƒÉòK^ŽH{yXçC’¬GÄá[7#€S ÙÚ‹¥’?8˜³êù§ÆJ¥ Ç)¸.,@  ,‚Eù‡;‘Cí"`ÇQ‡uL쯽Äù£QÐ<iÉù2ÀêÞ‰P¦l®ïÈ^a>íúñÄù¡|–(Š‚ô?Fî¤ñ¤û'éúEÚÚ£Pa¶kœ'lÜx}eu­µü¿_ ççªóƒRÁfØÏ~`Ë*‡™1&ÐÞ¿-þ¿uàlK˜ŸË綬]äò;ß±vÄPìÝ7÷Ímñ¬]TóÇööîöØ P(Íe‡QÐõ¯Í@eÿ†o™øƒ‡@ƒFe«Ðvµëôécܧ¶“vb1©¶j¿©×܇ï¿ÞZ__ÛX_“‹tª?ÿ¸ý¸þ¸þ´¹x²Ølžœ\®Oo3õJÙ0Ê•ÊåúõIúó]dºTžÐÊw[Sb”Ö$"¹¦ˆø•›åwÚo¡œ %×ó&duÓËWKà•¸À‹ò¹ìÝ…Ì´}ˆ @d+‹î]ôd»rhQ%h¿N7&Èï’*ëæ¯Ç¤8: Œ Å‚¯'÷Iñð™×C°‰4`GOÂxÒü´I€Ò!#%DÎÝIãI÷OÒõc‚±¯¿¢MLæ9Ê6Îx—k«'_Ãù¹êüÀsmrÛ •à ¦Í¤ ³oïØ{[ÖkëHÖ÷–i›í‚ØóÄ {û[»ãì%ßÝ‚œ¹·u`nY‘u¶·s¹_^<¾¼ôåøå‡ÿEGžûâô›/^¼|ù‡—_^òÊç~ÏË‚óâ[ßú·ßÿdž›[@ÄPv¼®éÇÀ,å]@µ»µ¯A!—ÂUúôlq#c3ŠIÊÚÀäq›òÙ¬ÊM´²¾¾±¾ººÚZ_muû£úóõæ“æ““æ“+İ•È IDATôéeëÏ@¿¥Àæ¥úõIúóL3À–U¦|BÜ×_&ãE[sɤɔmì·¢·†¤“žïîÜ{nÁqKn©ø:™fmǽë:®û‡Â„m;,_¹â]–ÅOI 1 r¶üP™Aòêu;VÞj'Îr„å26'H¨Þ¯rú…¤¿$´—-¸¶)’-´ ãIóÓ&}0p ¸àȦÞIãI÷OÒõc—¢²6,tž´5žŸuq3OÎÃù¹êü T2o˜ÀíÉ(‡Ù*ˆÞ8ÛÎïíçÍmÛzÏ6Ç÷óù—9[ÝKa‰µØ³_Úö1Va÷ÐÙß?8ÚÞ5‚By€­wìK Ž¿“ã¿âøå‡\×bùÿò—Xùö_|ašÿeÜ~ñ….ù_Èw\ø/¾|)Ç—…»wïÞ¹sçŸN;wnßÛÁ—þðÅ ê!ãtûö­[·þøÇ?Þ|û¦of¾³àÚq;pÙöoØnÙWàærbÚÆ‚ß:TÞéî•úôªo–'HIõT+O“Þ‘ÒBF‘lþâl®µPXiµxœêÏŸÔõ¸iOØÚ3¸C†ã†1WpÇcn°Ù¼0%êÓë2c<ŒÏ ÜCAÕ’ÖX%ï¼5þöø€vÚ Š¾åþ K[®»+>#–7,¬ì’îð–cCt^¢Ç‚É…ï8†ð„\‚ñ—~1ðtjÈ;€f9õ_•í§0D)ôHn¡œ¸²Í´¹òáÀïÖ¤}?¦ ”?Î|½Âøµó£l$ôëÑ/:$'Ý? ×Õ_.÷N|œ£mÌDkëk+›ë+£ósÕùå’+«TÖ{­@vÎdù4!G޹gm½„9°Ñ5dÂEx)nV>·ƒv 6bc¹Ãíí½£}Ã/È­sáÔÈíR(Œlù/^¾x¡»þ‡ºõãxñÅÏŸ[ãüÖ·þxË9n߯g-çß‘u-wîÈò¾}Gm|ç|èÜú«¿ú«Ûìy6oßúÖDZò‰úì31Þ‚90%Ç,‰0cP\pÑ 2ù ÎzgÊõr‰>}¬oߣg—:=VËB¥‚”£µº!®«…•¿ŠLÀæfkµ?ª?ßÜ?Ü980v·¾kÝwM,( àïdùß¹£Á!7~{àÉI7`4øá/¤Fó„¿TA] ÿ‡‘Ä‹² Ýfœ¯¡>yõ<žþìsÏž}1FìñD!*ûG¹±¾æ’Æç'TT/â4¿?’ƓëG[E5Ò¬{t4HˆørƒùYÛXG²™Tgççªójƒ€RA¦=ÌZ6­q€yºûã| G#×xÀÖx@>vòhA¶½gmo}Ïå‚*8 †ñ?ýÓù=/†Kðóá¡fE¾ŽéÂ}1úyþüùHJúbäpì¡Y1o#èÇ–ÿùó/žþ9\~yíçÏhžósœùb~Þ’ XPðó#¯8,y1$…íÕ‰ênÌKÕR¾hÿY¼–¨®v¯Ò—íYºÿl§~| H°¿&_>:ùôÉ'ŸþêW¥ÿc6;sœœÈ5Ä8<Œ‹ÿ°>gŸ|òñož4Ÿ|òÛß>~¬<OÎê×3mFîš8¯Fâ>âéÚCÕ©¾¶õ:Z_V…Ÿhp?ê Â,y»Y¯yNUn\¯d33|æÉÉ òÞ¹Ä:wƒ8¸Aì³7ˆ| „@‡´9ä ‚/Oõ0lWÍ_Hõ@´±¸ÖQAß6ßìÙ÷Ÿ4ž8? ãIÇðúj,¯UýX ôÍÆ#ª¶ JI«©iZ4uócÞ’Xs  ³õM$ ÚÊÆ ÊŸ1ðdT_ÇÀÃÄ­üÅgH8(—ùhÁýíCãáþñÖŽ« Ê0yW ÀèÊÇr´âÃ4™~ÐoŸqÍ>GpøÄ/FŽs?â‘ÏŸc“ç©rèjÿìs]ÿŸ©ðL•À–@ €˜~A €åçm¿èòŽX-#öÐÚqŠšŽ*ûa#]4T~A‹MG»g2qy{ ÿ¾"Á¾\ñËV6[êhÊ ¯´Vqˆ§¶ú‘¬ÿO?þtcÝ2™ôT&u/•Íf ÈÇWÖääÙ™9ãéÓO>þm³)a€X€>þøÉÉÇ|ª_sè*1€ûL ü¿˜Íª¡Â÷Tþ[Ãh’d’€+¤ NW%ûºÍFÕ+U«Ýž_´s¸2²€åÎ`Ã8bFGã fçÆEŽkÅN£'²tÔE4m‰|¶îvû±1¬À]51ƒ_/Ts,±êÙ'ÿÝéûOO˜Ÿ¤ñ¤¿=ƒëÛŽTp5d`~½7'ÓB¨¬Äj”@A¥‹<±OŠ©~ Vtµÿb$ÄS Ñk„x/å§O2ä™òL{ð ½oîmï<ÚÞ;|øðàø€ *çär0wãÈßFDÏúwó‹.Áà8õt‰¬Ü9ó~``äi°g—;L Àð¥ÅäåïZ¿Ï·ó¾eßp­bÑôM‰ $0‹†Ò½ôU@’¼6 „go%X´ÇuDXWé¿·67WVVÄ+æ{¨¿B—`U<µÖ>ýxåÓ•ÙÌ´¬ÿ‰É‰©ôôôtÇ[k³³³YùxúôãŸ4›'Oÿú£ÿöñÇ¿ù˜õëÑ@ÖjÚ´ÉNévtIÈŒV_ï±®úÔXÿôTÁò…$ÒQôÚíæb­äÙfµê»– YYdr9M)dÌ)àøã±ã/«Þ‰åfqïX•ädǰY4äÊq]?ÖºQ޶`$¡—Î_DjAàÝ ÙšDŒ ÇèQ" 8q†P©NÙëGˆä™$n·kj€ˆ,qï|’—‚×Iò"¯{ú$“–}|˜æC}!oîo?ØÛÞ=4j>ÜómYP¶3oÆ ûÎí;ÿ$±9̲€qFAW>²sß7ϯüÓPày¼…Çëúùhlp$ˆµxþÝ|.}=ûË_|®~œŒ·$Àœwì…â¼,úbÑroÍB)_’¨`ÁÍÓ ¶£­®=%¢êª.v®ÈW;Êõ¬ª+ôß7µõ¹­µõ¡~üŠxiØá×ÖÅe[Ù\]Å"Ϥ'ïÝ›˜˜J¥RéÔT*=•ÊfZk³3™”Œ63ËéfóÓ“ß~"Îÿ'¿‘ã9žˆÐlS‡@帧(s^=¥¼Õ¾½¾ÆÂÔ¡<_F"ÓpwP'î7—jÞbP† 0Íœ9,óÐOƒˆÂ\0¡5/VƒHYã§‹Þu!1ínÑóÙ6ƒ½ßŽ•3zÒ‰^:½˜*2Ãæîõ4v¶Q¡LÓ‰ãIó“4žô÷)õf|}Û*)DEê#µßx\E!ùËú´Ö¨Œ²Jz¶Œ ¦Ã¶–Á1F%²Ñ2oWU†_¹Ì‹ì„¸š¦¥O‚¸ð Ð{°ÿ@®øÎ® ¥ ãGFµ”÷ö¹ ,€Ï­[,éýÛo!?„êsãLÎsmæóßÔã¬|mý³¡{ÿÙ³ÏáØâ€sÇ—øƒx./R×§›ã·¾E`¹Hù˲/˜Å%Ûôò³àdI_#T·Ò‹õ!ÆU!ñ(ìÞêE±4×uúï2ÿCýx´´˜ì[m­­­ÍÎÍÍÍLOŠc41u÷ö]=îML¦¦ggfg3©É©æDs\AÍtyÄ(/0œê×$ÛÄä} žà@¹¶U =c½K€$Ltbýá^·¹T¯×½ØÀ«@úüÈ °ÜoÚÕ*°òsµnŽ—5:ÐEWè5ÒdØN¡Tò9}¡6kÆ;TÒÿë篳)ð$v )dwðþ“Æ“æ'iü®oox} @œÒˆLâ½áxŒ˜ I.ÕÓÊ~7¾‚pÆÙK¹`ïØü×#”¨GíÂ3ãm­U¾Ћ‡3D{ÙÜ^ÆY› CgoÛ<|Nà#£”ÊΓ+æ¾»µ`Æ]YvÃ:=>ßÏ¿=(Ëë*ý`‘ö;»Ç;ú™õ?°Ö-X"ó4Ÿ€ÌÀóVPŽ/_À xþâ9Ýš‘çÏ_|!7,BqZd±/8AÞ3íÒÀ5=3ð …|a>ï.„îQ¼SÓHœ¾AÑH›ÈúT€@Ș¤ÿ~N?+csu}u¥µ¾fÌÍÙÔÄÝ;wïÉ1)ßܺ#ßOLd¦§ggS©fSÞM³)ÀE½ð¤y‰~=§I³C±C^ †/Úiˆ8PjŒž‡’*nDÂ/ù‹›KKņ˜Ÿ&€¬ñ²èXtdiÛV¾RÍV*òcPÍV«…À<]ôà™s/wò°¹ÇJ^@Ô+“Z!ýìØÆ&Íß%É€¾øþ“Æ“æ'iü5¯/V.•Ö!—@Ù°7ï3¹!ÙÕñï*E4,Æ”»«Š*lL&gð¨7™Ä_ê-Ë­®3ÎB¡‰¤nž>€ÜyÙ À'âØ‡û6<€cñJåÃÃûÅïní¾“w C6^Åôüq|pÜ|;ºÙüx‰GüÏ>ÿìÌþÿ{ `Ñ_0O-À ?€_~ùÅKîþb ä±/¿|yZ{´,àÄÓ—Å^ðYønp#(!ðÝùBnÁ* È2õ:ñÙ! V;Ôt4¿cF˜Ž"ºXI-}­þ{G‹9ýøõ•uñþÚ4ŒÙÙéÌÔ$€ ÙøSSbîMÜ»›žÎHhm6›?üá_,ÿÙŸ={73EçõëéŽv:*ÚÑéh3š–•biMl¼à”»ê’f’ûCÑ G;·Ô¨Õ+òOL@)6hö×"ðt4í÷l+U«d+U»POW¦ƒ ¨V*ƒE_µø¤ hÛè» PCN‹ zÝ8c×Nœ?¦®}uCjw\xÿIã ó“<¯u}8F·AŸÅÇHÕ~ßd¼¯t d6 ³ 8›_î p¤™ 9Šã!¤6Øn5ÚìÕ!ÊúÕ›½ÐÓ=!weÉ[ù¼YÀN ™TLò‰˜ÎaÝÁ¶ p½C÷{[ÛGÇ9« à7cXÞp?‰ú©»/4hÇbg8OËðûÿÇïã$ÿóoŽÃ…8]ü¦–âeÎÐ_ۇХvKã ìdŠ,Y ¹Â¼ë#(7¼ÀK›ŸG+€€>›¸¤ ¶2;NéPö{ ¼  „zê0&éÛêǯ¯±Š(`Ý0¦30XüSét&³?5-_Ò©T&=•ÍÎΤeý¿ø~óÅßÿýß¿o¾ÿ—Ù4 £?¢_ÏKÙ¥°_§?ð†û*ÜßÀa[™ÿú—µ“Fàëµ¢Öo//ÕõZ½^.ŸšË¢ÀÀ¿,n@P^{ H•+©‰ R­füZ¥V©¸UY÷ã#@KnŽËÅ’ÏvðØÄ5,ˆ³çúùë“ tZzº_Ÿ¾ÿ¤ñ¤ùIž¿×»¾q ™µ<†o:N^–®úqÉpÖ9hÅ{çÚ¹UPX=þžò*ŽŒãÂw^§Ý›ç£Ãû. Â&a¶ýò¶i‰e·Æµ,DààöÞÁþî¾áUÝ¡»³u¼ÿ0ïž1/À4O‘¹ºèŸ=û|˜ãûâÅ—_ÄVàósëhž?¦qÂÀR˜ß<{XÖÐØ·«_ÌÀøÍ¼¬ôùùœ,{'ðn­y· €…*ê¼”UÑpPÍpÅU„¤™xzpe™8JзÑoõ×[+ëŠ0Œ™éLFÖ»¬ùš™ž9Ú›ÙÍf2²þ'''î5› Yÿfó²úá 4›ù£ïÿ€ ïõëÉ Ü'[/,ùb,ékH‘”øYlº %ØŒFJ|lgËU,üZ¹\)Wkò]‘&@‹>âîåáT«AP fëÕòìlyºZ-Uy¨)@O®“y'Çš!rÞ1?}#o2Z,µ];|NœþRà_G%¸â÷Ÿ4ž4?‰ó÷:×—À¬AátBÝ7'y:Y¨Ç p*5#„.!“» „2kïÜx§ÃÝàu_âóŸ¤tìüKñèþ“|ýOãtùÀ'âä-gïp÷hëø¾Q¬•ŠG•ƒãƒ‡KÖ™€ëßüât‹¿x|Î:ÿçÌÙ=Ôõ†ëŸ€.ÀóÏäø³ß!0øÝ3‚ ä/X€qšöCïÅ/äÏTд˜ àÎ[EDÅâúØb æ]kÁuM¸Q‘Ÿ’„Ù¤µ©tÝüQ˜mVT‚¾½’Þ÷ظ ­òƒ¬¶¸Žg²Xù²ÜÅçŸÎÎ<|7{°•͈/ÎÀß—ÅÿÃFãâüè‡?ü<ð£ý ùƒÌsSïÆúõl&ë°é²la뵕þ•Jsºäãë^F)ç 9=jÜ,ת4õjP®ð;5XÈøÛð2^¶–©U+Ùt½<+ÏŸÎ5¿¤åÛTÇ0§Ží‚Ÿ´¡$ª†'*Nèúù#g*aÌe+GV¤Ér}ÿIãIó“4þª×·Ïöý6ïî,è÷ÞtIH2 ²¤¡Býʨ`„Òòj€þGÎç<å³$¯Aù68ß‘pÁ¶ yqeó7YÈ›äÉomÇ\Â;†[ñ‹Gµ½‡šE×4æ¾5ζ¼qdÿÍѵ?òÓïrƒC–õï>»àœu¾>8~ÿ…˜ ¤4{òÿÜgrºŠ3¦Q`‡¨¸î‚%À3mÏso¸¥ÀÎ{âXó HÀ˜ [!X”]£Ã¬°,pcº£húýëôíOõãaÖWVVWäD3³Ù™,œ€©Ét&{´ŸzWŽƒéƒô£G©Ãø1SlóEó‡?j6ÙüAóGbšsò¬w›ïöcýú>ECU·» Z°©+Æ}ˆ*ëª_{ ©dWÎ` °þkÕZ­F/ TÔxe;˜ ü™jÐhd«5?닳,Ö‚ÊŒ_õ+©²üX¼`Ú«’â Â{ϹS,NúaG3Ö½z€u&Í__›î•z˜E$©À¥ýP ãIó“4þê×—z>mæ5éÅ#±‚ùfãJNƼ‹mž¢óÆOgI];TVe“€+ባ¤¯È$D¯Aúzz¾ø Å¢‹mÀvÆÍþìú<9r¿»x|6D¢†æ­»@Z…y ¬@y;(‰(Vl\RÂcÚý¸E_[G5 ‹ÔoȲ ‚¬Æ^¯oª¿ÒÚÜØÇnfŽËߘ™ËNÏd³ÙéÔDjúèáÃýìììqðîÁ£ qfÒÙlã‡âȺÿñá4xÌÍÍξûîþλj™‰ünwZ,X¡É ÆŸÍw1ö'd>®0Álçi¥µ¨Ëwè`åcáW*AÙ$ðóJM«Z–E^ÍTªY)SÏŠP6Ä[h”Fµ²Ø€gåa^ö çn±ä#åû.Œëó}­¶“æ¯ÝŽŸÊÛ®};fâÐ÷Ÿ4ÏOÿÊùIõë‹~R soÖ:g§û¦ã=-ãÅiÊc„ƒ)ª3´î¤Ra3B‡@Å5†QÚ÷¾6E¾íûéù`€#0RBÀTÔÙ'"0æ>2\¿Zr|S @à’õù»ß3 °€>6_ç맇Xƒßå†À€†"—{+÷¶8oçŸåóo¿-!¾|Æ\E\[`‚á4_HÿÀ Ч `ÍÑ Ä)G©V‘ù*,°LÆ[w]*1P“!QßþT?¾÷ßU/‡„ü™9cf:kdŒéi1â2=c0—/àQ:ý(“14 ˜nÎ4›±˜p`FŒÃLóÝwÛ§< ¢øÃI.-‚?£¾jëÁ­c¢¹w™°7ºŽ2g-×°ó—+µr¹Œ @ÉŸr9_ ĈK_®f«F¦ŽRáb#U©ÏÔµÅj½V­Wë‹ÙÅJ­ˆY°¬2¸€l"„$úreÂBíÀ­Du‹ÔÁ=nÛ‰óG” ö\ZºZ£i+©¯ÎOtéü$¿Æõ¥9U¨@Ð 2&¿éx7®UèS†kTX¢Jˈ°K¬ZK&ôCí8W¤îk¿Œžï«Pp^š€çí—¶uè˜Gf>æ>6\¯VtK¹’ýNÉüîÖ\¼«ŸîÎÏ?ÿ,~Lvéó;÷é1¬üþà¹|óoÎg×ùŃ0bvæÌbì\4 E£­¤u0€1‘<ÿH²´ ƒ M… GE×êÛÇà[ÕomlN!è¿wïîÄä À´xÆ£ÌÌñþÇšȼûh&õèÑ##ݼ ÀlÀ›Sø27'–õ‚Lvæƒ5DÒè1$— `‰hö5ŽLj† ¬dß¿(-ÕU¸ <ÇeñÿiÈ×À ¨z%¯$ & o‰]Ý+¿!O­gkåÊt­6“­Õ«©L}1¨ef37XöK36á€0‘Òr*zahuUf“ëç¯KÛ.k| %Ì7ÒœÞÒø™ùÁ¦x~~Ç_çú2rG,Av»ðßt\'í'$•!ór(Xò/ÒLJW¥Ýz¤\ëtU¹œJç¤ßº“¯h^YúíüëcS(Ý—ãfAë6A1—°€R½dÌï/|wk÷_)hqázÀ7  jªè@ŠçT£§ŒS‡)!²@&éÛèÇ÷Û™)$ýîMMMNMÏŠ/03cLËb´ÿpf&“NMM¢-`jzzêî›ÍæÍÛ÷RÓ²îg²ÍÌìÌÜ\jrbâÞÝ» dÞ_§‚}Üó†(¥¶[¡2_¨‚xÅ¡"›{—‰KÎ>¬ÿjµJP©ú± Jy/pý²X€ ZmÔ« ‰ü«Õút³>ݨM׋õ¥lm±±´Xm¦å,Î-WƒØÁqX‚ñÛ®ëMø`úï(ŠEÙv)þÙï$ÍQ¢û™e£åYÔì$Ÿ™4ÙœŸŸ¤ñ׺¾Ñ ¯;ª®Â7Çûë27Ùa†–˜ADqèI¢xk{ Z—uÑ6uÃNÅ_¿úJv.1_½ŽøëÅ×ñ­X¡ IDAT÷IûìXT°­=òb.ámÃ-V‹fùà¡Fsi©âWÊõr½ÞlÖ‘#–ÛªZoÖ,e½dêé2©â£R‘ï«õ§ËrÕÓU}´ZM×+ˆM‘”’»²’©ËÓp›U3ÈYËã©zº‚S*Ð]“W©¦‡?Èxe ^K•`éZà¨DK—UÌ&«~}ØQQ˶J®u©ÈÜïªâ–‘.×·êÇkÀù³Ù™éŒ,óɉ{÷ x´ÿH>Í=”å/«­S“™LjâÞm fnÞº;9=—5fæffçfç2S÷îÊ÷ÄL¦ßÿÛZ‘Ò2â·V+lµ (CLÞH„`눹 /ÃD¡Ìµ\“U@L@­È·HzùªëýŠX€ºL¸8•T¥²X›©.5³ZsqQ¢“åL³^ŸÉõZ­šnÔËå vÓÌåóãN±Xô»šñë7Õ¹“Qa˜4±^@O‹èÂTÖ…Â%N™6#ž›Ÿ„ñW¾¾Úyv%ÉHq¤o:—Ÿ-ÜÕ²~‹¬Á¢6hHO(?SfŒlQá©ü;4CÅ`œ|uòÕ%òïJ)|Qþý²×G. —Ûó&ºEßCN`{_l‚án}·d‡û¡†,úR)˜tQ:º ¬CÅ+ÚŽ[£pÏ[ À‚kÁ ¶BHH®JFeÚóËälOmnÔS¾k¤×êÛõã»d¥øùÌlµYê·ïN øðáþ#8ö|Pv÷{²¹gº{ à @&#Oœ“3³rÚÍ·Çoß½7‘JýôÛô ažqÏ’_¢ÚQ|«txðú7 —ÚôÖ>sœ^àåjEV½8ÿA¥Öh`'¯Êwõ|àÅúˆªÙF£"›}¦Ñ¬Í,6g³K‹Í¬xy3K˳b2˵%ñ—S ìèÃb70JØ=]G,L}ÐŽ’çOŸÓ;˜ c#·?s1!BýëÇÏÍãó“0þÊ×—yâ8ö ì‘JŽ¿é8Û”CvÁhGq %¢Ð:7æ¡ç·Du»Ê€œâ`€fˆ¬òŃÏl` ŒÂXR@¼V¿"*š.} €rÜÌçì] TÂ$4·Œ¢·»õÝòÖÁ¾BšKu;ã¸eË.±­ äL^î:ò3xÉä!W>Ë?'-ŸìI+íNÿtŒk»ø5èFÈà©ø'YèQuÝ”|räÅ]7í¤ìLɵ-Åý¦ÝI•A;cóuðÚ7—óa,wX(² håýØ   úvìU‘kìÛ‚ ŽUcyM`&Â$}{d×U?ž`ì7#ë}R–zjfÎx÷‘ÿŒýÓôïee3³3ÙÌô½Û7oÞº}oj:“DÐOàФ¸·nßQ  #@Á"H@Iü1½n‹H­ ]@&Yn:ïÒÅ[–}_ÖY<«J­ÒX¬‰'U.{y¿Rùþÿ^)V0Õ Ò|•åf¹Iè‹sbHŒ2ט–kz)»8]K‰á°wÌ´Å8à!⩤¶–šØcb"aþBRßébYŽg%†Hq$_˜pâÁëŽç'qü•¯/HBBUh³ÞN—âMÇᎷU†X)„´þÐÓì]¿&„#ßÉÓ@ð†ƒ0Ö ÃFõàÓáöÉ鸜ðÕW$$d3ùå¯O `[`p˜@ƒÀž™3J8¶ì@, ê>Èá åZY<‡Œ‹,bQ¾-–qÔ廲OqiÙ¹Ó?ò‹þô4*òxZv|lú1X±TÄg×-¸iù_ÊàÔÔiàfúôä(øEWž4ÍÓä—É—’Ÿñ»ÜŒ«b|ñPôKf>`P' |eHE ªÚ£Z5øf˜AÁ~ÓÙ`¨Ü˜¤oV?í/fäÈf3Àÿ¥³³³³Íiò/VTpzfn:›žž¸}K¶ú‰´ ø_ |ùŸ‘/ÈýWKWøuº‚gySÞTòk™J%ø‡ÅJ%ƒ1 üÚkâ–Åu•WÍÈSåñšÄy5ù~†#ž$˽! _P@7K¾€ŠcZž9_pr¹" A¢AY¹´€«¿UÛ­A žïtb?2¼RßþT?¾ËšÜæÿyÅÿÌÔT*Éþâÿy66ð¦äGñCvòžìôS Íiˆá€‘@óÀ?ÿlƒw¦Ü—]b“(P§ V­V‡ Jƒymh8¾,“D€ý¿Æ@`q±HPùßþý¨ÚV±.y¾z¦Ù\œ^Z’oÐ1¡!XZ®ÕËËKér…^„Ø „;N¡è‡”'Í{ö zhix¸Ââ§e`Ô´Î 3FP "íJºôõ}˜@ÛÙG?0ã=°B[ÛF œ@æQ`;-Àt±ìù¸¹j^)øi,t‰ðua{ª%`½ü$k5H#}—©,ÊbÆúÅCAZ^f¤VK‰¨áeäc}(ô]å©5¯€‡+銇W-´.ò»*ò¤Å hs ŽØÏ2Š{£˜yÏÌÏç 2+¤©`ÅªËÆÌHËTЉoõ©z¥i'éÛõã•U&ÿå©j&þyåÛ}&ñµá›Ÿ”5“+%Á)8€ Ãñeà~Ê5ìûµ*²°•²ø^¾Z¬}_B€B¡€J@ÝÂи¯-Õªbˆ †~±:›­ÕƒFPõªU;¨ªÕ<ø£$VD ½.ªÁI”.:ë Ç“0È_€kxbO·w¦Ì€O¿j~bW'qüU¯/¼A ³4a§TÃý7G:ZŠlÙä»ÂêWM˜… WÄÔ]‡­… ò‰†@0¬ëQ öãbg_G㴦اK__ 8DœqöÇÒöiȪ'Ðþ‘o/¸E£Y­úå`:ð2>÷ø „îQY”²0ýÀû´ü$+ .3ù²Ü±S²pÅ ðýI>AþÉŒ_[”S*¤®¤qƤók~ŒH¥T¤Ã!/+Ïàë{^Qb $‹.vÓôòfPºMˇŒAÁÎåä&²œ%ú÷JÑ̶R@æYéiݤÏH1QßþT?)·;àÿÝ/à|ð>~ÇÚÌcšù”,ý»·¤233³ÝU&$Zk?7?d~úÓŸü¿ÿ3÷ŒXŠ.†Õö5‹ÔÕ?¹Å# ªãž¿Œ%”kö}‰Ê„õ7ò^P¨ü‡J¥èPXɨV³l­™­.6š³ÍZs©1›Å7t=U©AU–¡ZH\¢€;ðú1 8sXÀî+Â¥›8ÔçÓÙ!õb–;MÜuû‰ãWÎR„äñW¿¾(†ôÉÚ÷ÆãðD¾§HMÖ‹AÀ¨V =åÖì=yJˆbâÞÅÚ:Öø ^¡à„;ÉÛf`h¾Ò¶Äž²#_öú¾çZ±Ù<žÛ¦¤˜¹m`/nx{¶kC°¹Äв¬ldèìÅ^AÔîaUz.W,ÖrFn»”¬ØŒ§›¸Ä>1ü¾W®úbjØÛÅ.Tè0X„× ç§biZñú±ùÃà‘RI,CJœR.À¸¹» Þò-³Üð fÑ4K´ 9[<C+jyÁý×UX)Õ¥{eÂikÇÍj½èz}û³úñHVñæYÝüàƒ~±Éeýíµ÷åàòÏfggÑZ€;ãâ JÈf)qË”d˜Íb7BŠÙªnö"¢aQšŠ4²îÑŠ‰ €YëÚfx”¸Ë ÿUügôï—ËAµ–÷‹Ž,ÿBA lÁleþz­\›©eëÙåÆòb³Q˲¼,V ;Q/›0u/P©é÷lT=b´Î„}u¡Äùƒ;ÜÑÈiz²›p*ÁÊÐO¿n~úåýºnüu®o›¼>L¯…qÞ0zÓqb&i˜ Z¤¡'LBƒâ÷l3}¢Ó´ALõúzkµß>¡ ˆs'q3 VЯÚÐ"À@^œÆNÝþË__ %à(cÅÊbFÍ/Õ‚âÑáîöîÖýûFS–£¬äÅÁŠõ$:÷%€à!9;0©‹+¶,¡@ßÈî=UA0OçA"ÙøÅ”B0ÀäAQVv)€©(•É€³å üÅåÈày%xȈ]‚·_2eáü%[”ç]¬ÀrDÀ$këk[¤î‘ÒÃR®F÷4x­¾ýYýx8 ÿª6°pç© Xm½ÿ³Ÿ½ŸÍÎÌÍÍÎÓÌôÝCP?ÿ€D¾ð9;ߌ¾ÉØ =ª¤¯¡ Õ6¢žvŠ¢(F\d«!K ž@ëŠvÐ(D™´T$ ¸†Ø¿,–¸±4E¹êåý‚«Ë¿R(Ö¬¦ÄV—½™šX‚ÙæL½º´8½8#ÁbµÖhÌÎLTÐT­zP&«´]@‚ŠX{S=õˆÛ^òüõÁliì Ñ9AÄ$¸Gn3qüºùé·“Æ_çú¢C¬G, ù{‘aë¼é8e}ÒCÚU´ J¢øü‘vnB4,#bˆÉ­%bY]ÛØØl­·i´ p2h—ß êµUq;'ƒb= r®z}ß'E û·Êb†çºRíÈ:<:ÚÚ6¦X;z€ÔŸaÀÔ#(ÀYOIœNÿ_W¯ŸÂW˜Æ~åÿN?ž–H¿’©UàÓ„”^"ãŸÂCÂ徆²)ùWôŠôÄûwç‘0}Ë.Ý(ÚŽgzö|!É@x±½(¶$¾ß#&‚E:›aƒÏPÖê&ëÛêLJ1á„n1@Ÿ·»³ÈMÜ"%ð¬1;-A~ ¡rüóO[ßfwJ¨¸^ÒûD¼AQÇ’t;ÚjÑ’”V*$ÜŽZŒXkm¬©¸„á‘»\Ǿ€HKœàáH¨‡å/;®_uòFPÍÎdldËËKËÁìl½žÍTç²õrmn¶!BΪ‚€ Á–íJ@&’(¦âìlÙ»vþÔõîÑåá].ùPc‰®ÎµãIó“4þz×—ì ™¹o·ßt\3´ÆÿÚ«vÜ™ÊGw”а Œ³_±¾ÉA·¾‰}9¾“!! Ž pÔ =¼1킽êõ}×!€Í~`ê QYÌ(:NÅ©™þñþñÎ}äJê¬K,.ñ¼¬Dnè²öÇÆ°„å rÈß#sˆï?&ŸäQ.þé@ì†ü˜¦06V RbPä,ÍÀHÈ06æ¬&àv¼1_k4~씼¢0¿`»ù¼-ËÞ±A êyfÉ™wó•ÚFØ6äù^É-‰aò jÓSiy$þ´i$"µ]t½¾ýYýøžø~ÿÉ6Ö‹»Î{”—F ãˆvà§?{?-‘ÁOúmBNÙ¡ UiÊ£ÖíÇûŠ`øÌþ—ÖO1­ÖêÊt#66Z­Ø œ¡„"lÊ-,K T)k †4>»ĸXþUWvÇôÊ…¼!J-› ªõÊÌÒòRP®W³sKà¨g²u J àv5O*ÑBÁ-ùZ˜lÙäN™ Ð^?P‰()¨Mó争NßÒxâü$¿Æõ¥D ß)ö – ßtœ·G7R±Æm4SÑ€@à¥[H¼p_›VB•·ØXÙÜ\!åÚfkHÀ“SJ81f››ë-± НXâ¢`ëU¯ïbÞÔMk ,f”œRÅ)T>ûþ¬|–U^#0Y«8\ócþâÒXº¶$ÏÀódÉÁ‘sáÁŸCÕ¯V…À ÏÂjˆà‡œº€\®àxâ 0N qnn~AœÛ,÷Ò“†Áµo@^™ ¨;½8£ÊrBEY„¹^ß¾N?1eÈkÌœõ+‘ÓëPÅŒ¸Úp0º´.h›c~šu_µ=¥-ëjŸbD¼>‘$¸áÆÙîk ŸdÉ#¸¹¶²¾ºÚRwoSâN 8r¦a ‰GVÿ+ò¥ˆç¿R”‰qk(ºŽ'‹BlÀìÔ¤œ R™ [of+ØòëÕFµ¾TËÈ·A£jB#ŒÊON±èy]«œôÊäË:aþ4,ç³Y—ŠºÓ9óþ“ƯŸ¤ñ×½¾m¯#ìzþ›Ž“²ˆ! ¼ÏžÞ èê¢3Ò;GëÞ%Ê¢¯¸¯vÜÞÛ‘~eM6ù€“Vÿ -|­mB¦B À™£+‹FW¾¾_”o’&Î.Ø*n¾4 ïþý­ÝíÝC;xX)ÚÛÍF¹4éKÔ­ß›’@ lØ€L}LÿÉÞ½ÔðÇäci.ó—b¼úX­.?4*1xò“ìç5ß—‡äÁ±ÊXM\‡†!›þX£îa| ­ë´øl&ðÓâU°Ðàº0y[¶ÿ…ù\Á·§tClSÎW)³(Á¦gÓ÷ff±þ!“‰í«TŠˆ¼ŒzZû IŸ­Í2Ôõúö—èÇ÷T™}­)áèý#]XWEëDlEÒÁHŸõTü®?Ô¯ç«ÒùEºV9+úй§R…!Zë­U¹ÂØÖÄ!+Ùæú†öUèl°·OÌÈæ]§OµŠ@uÙZ¾Q+ÖÊ€{Ä8•ŠÓShezëkcÙú¸Ùú3µòL5@ÛV |X“k'€i–© „9ôúÌ´‡¸ÂÅznû¤ù£˜¼NzßÈ„+ýÇðý''ÌOÒøÿë‹â 8E´š÷¦ãýŽVýú}¢r D¿HÜ9'ìBTö©‘Î'ÒºK«µ8_VúÊÉÉÚYa\ º„xÂÊZku GéÔ+_ß/Z Œ—Ń4 hxÁöÖÑ‘{´ïÛg#åÏÊ>3H9)¯(þ~}¬Œ•díʇ,Ú@ü{iÌ«,É®ï×ød˜lŒˆ €õ±Œ âh𳼂†2Šjc ü 1ð4È0@«¦[ 6 ë›~©x£Tv,ϵç) `L&3;eÌÈÊ7œÁ’4°èõ‰Õ¶02ÆG×迟×µª@Ú¡8  v`h:ƒDy'·DÌNÑ5Äoé“êi _OôjŒIÁ•éhߢŒ3õÚ!¹A:îôõãÀ²Çs¶JÇ! h÷wŽ÷ æAÉ,xŽ8€4JüXˈþ+^Q–fJöþ>dy{,qlóð$ ƒAÇü¸š¿4¦h@Û}Í \y¨^­‹Á¨5êrËŽbL-B¶qr†Zw’pJ~*¥r…æm׳r醄(&Š{k/H°j¤ÐÏÜžµ Û°ÛA@ôG¤0·X¦8åõúï×èÇ3C »*§|–Ãp?Ò^W¬€ÿbT¿^Õ")©À_µ ¡âU€ëÚ’o…ªã6ÖVWZ5tÿùEÃøÚí{“c¹¹¼È¾ër¹ZP(åËŽlýÅ‚ËB`¡X ÿ&ð%5ñµ±±;²à³§{µ*.A½žà† VPl `ñàõô ³msõ“掮ÂõXCA¶üìûOOšŸ¤ñ7¸¾}Õ~³qE9õ4ÿÈ¿µ­à4»çÅ]{çÅ_OÅac°2:ÅÜ2.&@ À`TЦ¸òõã€ùÿ=@5 hÔw<|è{»Û{Ä4Ä xÿ“Á‚¬x“WA¤ßµ]“$ý%˜÷d_j%‰ÆÐ5\“¨¾â§|$ÿh ä ž‡T)XBôï׿ ÆèoŠ]Àî# ¯‹óÉ6€º4êtEn½’/›‡ç!Ÿ„Ú¡×@m ¥¾ ¬Ê7$¦o :ç5uŒ4–dÅ˽ì/Õƒ% /¨ù^%†á+ˆ^Æ÷Š…zÓ(¹ ²ÔççÅ1õå½Q6ƒ²WB×±ãÌÛž‘™6 Ì7;53“7lpA6Yv0vŠ3¯Š]8R$0·gݧ•â’ù!l"(§‡ƒGqpKƒ ” äþ•úóíÅ¡Ž Ö¶52g=@…‘¡ä ý¸<¤5#€¸z§|ä+²ý#ü—ê`£ÄâÝýš˜€)€EùX^bK æ.¸²XþE~šžœL¥¦'ÆÆRc_»Ç4"år½‹¨ °òT’“›ýÀÒÞà})ÙE‡E/î§,uµÊº3k%*pߤø£õïKoàˆñ:Jõ£70ËÖýNœrï±á†évò^ôÏÙKöOGnpÌy§Ÿ|ýOÏÿÉ¥ç+¢X©>œ¯§­aa”thI «ºàPEÍz± ÛHµaºž\|þ ”4 •ìD»[Q+ÜÐ ¢sÿôúÚ÷ªHWMyØ9ކ`H Æ!kçbuac»Ò¨?¬@£\.{…"[õ*¿20;¨í ˆ¤}& üo’˜,`–øÑ?KúŠ à TB‹lí)¤Bß÷â¾8)¾BFì JMóç‰`tK^9°Ê7 fP,XyñòöB®hdÿ|Ý33³÷fm (z™³‹~¯K=žÉã{]Õag–NùEȘ>ö´fÛ5¤ƒ×ÑÒN/Q^©?ÙÒ¯jZ+FˆÛU´Ç@]Úý¾Jdó®ƒã¦‰Ü¡ '`£µ²)ážØ€zÅ›p‹EcÚ˜¼ý§o§2F³ÚlÖÍæòÒRÄ@~¾ìº`ù‹–#߉H‰÷?9•»ykòOnÝtƒò_Œ€¦šÖ Úl™d¡w·ëxõVó­+Ç.1f$À`jJ5¿èf ]Xí>ï➺°ÀY+eÎYVÂ'mm«KÐ…µOÕIÎ×ëÈfØ.Ùøc.> ¹òúÿdpý£è/¢<ª_D IDATÿo/=Ÿ®Ì‘ ·òmâÕðæï¶6v€LŒup¸ó«WAÐ" ,CCÛª<~ê_â@NI6ÿÕ• †ˆíAÇ{ˆp7!‘{"ḑ0Nüˆóxo¾€å$^6ÊÜÅýC'Æ4«¾Ü•4¼qæÑf´Žr@­Â`]»Ó1ø=BŽ ƒ.æŠúõ©8¶'Ò7~¾¼à @;€äÛI¼j†VEÁŠ˜™R!@nÁ΋· ÅÀ*Ü0«eß#ÙqÁuÄxÙ¹”¸ÄÙì샨ݚ–ë3‚Ä27 ̨ j–…Ê…) CÉ6Ë]±êB‡÷®1·rTV°RR0‰sxGç“\ƒ$ 5QHÌH‹Ù}ü:àùèÑ(Oy$ ¿ΧÐBâŠ!ÓHH.†ØD¯ºþ;¸þ¿þõ_üÏÿùß\z~ŸíNð{ôþR@DÙwî :1¯æ˜Äà}UaÑØ±Ã©Ä®²ÝˆÝNln$ŸADÊ!@³• R}U »,+oR— ‘qñ]ðüÒ4 &‘xâº;Æ4ê%/S*Á_Ä6žfƒNøsË3Ív¬`lê-Ø)¾ÇÓ-ŸÈÞ 9äyß­ƒAÿÈ(AŒŠ"‹Ùè³ö ¯šª qМstµË“ÊUë†Yö\y óbLg¾ddþ´æÝÍfgÄX8-r¦éúD_¡Âð{ÀPÙë’EEå§ŽSÓðzôܺÊHTVØÌ’b0LÒŸG¼ë=¶‰[goÌX©l¶!Åâéç"mg׸áF£eœÖê&Ð â B€Tv2===q÷OßžHSŒ¨NöÔåšx.vÿ²+ë±Yq,W €‘2RcrûÎ[·oÝû:ÐØÃª²þë^­\#¤°Œ~ÂÊ€3Öq‹ aÿJ¿‘>ßV—Ä´TÛAíý–êz#P¢ûÔ9mÈV5ßîù2V‡Vl‘éž+c!ÒÂFÙ!ç?Ú P 5cdÛµçãIˆ¯äª"§`ÙÍ;è¹üúÿüoôúüë—á—_þù_Èù3óóËÎww2Ï¡±™ÌÆqa’åÁ„ûBˆªâÒ&+JÈÛ­§êÁìa#Ú¨Gexv8â·ab¬P>‘Ú—N›š˜ÄjôÀŠÒik°aÊ:£ãXÃnA¬|q²-Û¿,+#pËrÏb©–-w»Y¯ßõY¢Ó„ï.*ÂVüô³ Ä"Nk{_…€Þ Û4‹WIË“ø÷Y Œ·xööýhüÀ–b—¼ ê1àœiv—‚RF<€Òüp¹»^  دüñbæ‹ÆäT&;“¹3›ž5¦ß„òTíÜD/}.nS4»Dl*.œ-ã@ôroµìé­ÅúÍsˆ.>úÀÄjw’ôçiKyAVò Õm}%0µ‘ “ÃmöÒFœr@˜`si€µÕÖ ˜ÈNM€¢X¼€¯MfêµzMš€J^{ŠNeQ €\ÞŠQ7 Yþ7¿qëÖ׿®,ÙZ+HÚxår­Z©yU»j½—'RÔ)H4Ç·¯< qŠ3Œ™Ui6 v¦ÑjÓV‡hyJeP¢-v“ÏY@¡ÃT. ª$ŽÇ@daXèìbw&!bL°Õ ϲÛ5…€åÍÉ¥½Á—]ÿ™÷~¦×ÿ×_þæÏÿðçrþÏ~ò·?»ìü¤Ebï@EÒe„ßeðqýý¡ÑK_£ ˜D3qLa,hg‡š<‚wu«.•€h¨„‰›z|ólÕî¶ãì*¦¾{nÜ Š~Áµÿ 0¶0qÄmåíBàÚHJöJi¹52åÏ“®McYbÏN{^EÛÉ?7óàùZFœà«k_Ñ%÷`Ðé£i¾JŠÛ¿ç§ÅÍçË2(åËLVÐ[ŽÀ|$‹ó]íâxTÅØ…rɵPÈ»V^B€Å©ììÜ­Š‘‘ ÀÖ P*kk6B„R”h›ÍшüH¿˜p·ã«~ÌëÊéÓ¢M)M8,BÞ$ýyÍ^‘›<$ K‰Y°u²ÿ•-ÁíP_3†h£—nC(g‹ÍÁâýonˆXo B€ ГÝKg2ÓwþôkAµF' ¾´ØlVl"ÅÈ÷nQ<€æØŸ¼}ó7oŽß~ë-€)P€“¾A¢tÔàH0P/W  Ó'{DA&[ù9hDéçÇ6‚ÛØÆ¸Øéš÷4|Ò>=бó­iê…PÊÎ(”•9Ovì -€LçÝ!”•òšØ{X4!ý„XrÅSëúó©M¼Kø?ÿÓ1“_O}µË®ÿÌOÞçõÿäñ÷ÿ×¾üó¢?™ù?òþ¥çãò1ýˆ‘¢ õæ!,¹Ÿx§ ŒŒ ÂÊàLŒ4ã–S2„³ß£©EB;A U¬j¼y2ÿöIF $í¸Vi„ö…q`ø'þ¿ö¾í7Ž;KOÏmÙºoͦZ]íîº_»ºÙ¤˜—@Y^?l6³²-J"E» ­iÚ¢g1 â‡Å™ 0ïIÖ´-KœìëôE&Á"Ç»˜¿ °ûÆþr¾ïT“ÔÅìI0çAeYj²ºª»ª~çþ&|:ÞF8 ÕXœ¾ÈòÉ0S §&Û¢ýb““]ýâBœ‘…ÅQ¾מÕ|­â+] ¹ö…Tƒ é‚0hãà “~$–sE>I‡‘'”CΪH@ÛG@âú°æ9';S¦ï›^h|?{CÀÈlzAŒ"sÜ Ö–0"°à¥µùÌ2Þ`(oÔð{$©ÒÙ4ZÏgΫ§é|¾bF—Ž.ºLI=}ìüyÍ?µàæqö) HôžÚ6-<§Æt2rwe®Ñ£Í—Q¼tå2ÀåËsI„êäóùé‰Iq}àd@^@ÝAñϨD¸¹ÎN:{2wǫ̀¸c¹§)ü¤ŽÀœ˜~´mË“š ÆßÁp0Ç ¢6–IwR,£É(mÊ ÚÚ §e/­jd 1 XÉjkfARš\ZZ@Kë ™¥£oð‚ñˆb‘y7ÛÝ¡ÇïóŽÓwËFïBRvÜ>ëù‹Ÿnã­Ÿïìnîl¬ï¼û^·øàÃûõ‡íõÇ33ô'ÐÜF„ÉkÎ.ÿ¸õA†wº¥œŒB²ÒÌÆkØ¿ÐÓæS4óò—~ØÍÐ jÓö£®rG2®ÈšÅØ¡€ä}zâûaè9©Ub â€n¹åª÷²yõhÁÿ£c:Ÿ6>Hˆ39Ÿ‚@L³í¬Þ!+qæÀ£a‘<Ó„‘šþB†ìgQJx …ù#=O‰†È…@| ’P¾A0¨“0\Àƒ¤g ÀvN¸vPµË M#ÍG¢ÎÌΊ `Lÿ™CÑבëé¶3xõ>ÑæˆÿÚìGë·5e ¡C‰±R‹ÃÛHĘªM­«#†»}uxŸ?O.RÎy Ñ몽D´ÌQÚ£®À0f±éV“­˜©ÊÇÛ9Å ¸´ô*À€—áLFTS“S…üÔôÄôù™Ù 3"Ê ¨¾“)[¬ÿ©3cgr¹ÉÅGO½4:ž;›Ÿw?i(ïbŠü_S^Öç’”}b· °˜„1Ûi`òXu'“w‹ƒ0n‹D¶íC܃2Ò ä¯¥Ì†}€ö¨ÎÑvÖ~V(D΃N°æ²vVBf¡‚;!¡¸£J ælÈñä~…êq8¸úšx/Z‚Ÿõü‹þþ®nowç«õovÖ?÷½í{Å­/÷n®?ÚÜ8z<{Œé_ƒm 9Ej…6GsP¿>ö™ èꔕ¬_áJb@µt¸Ûll"W‹'Ù¾‘iæ‘Ä€4Ÿb>˜Uâ/2v…‘æú£Ìå@¦¢@ç"ðg Ÿ’B0:ÌF¤ȳÐGÚ ¹äüɲÊAB€‰ À @fèX] Jl÷„ï¸ €ïØS5¾¿-Ñit*@<“¬È@«*“ gE˜ÑÍ€"¬Û´FÎFÈù~†xaÄ éáV§Û¢sÕÚ2~?ëß× såd‡Áóîè^PÆb:|õt¸¡˜XMî´­¤G*ö:ülèÑmß×Ê,q’ KÿàèuZúñû¬ðhôLÂÎn@ö뙄2=ÄQX‹³ó´¶f[ $ àûZ@¾.´¦ ©8‰³I4ãaí‘` Ýd‹§E¶ÇOfÛ8 >5„™„¤Ì"{¢âIÌ}a? 1¢ó'UB‘X»ˆÉ6'¤D¢tVÀv|*‰ü‘c… 2 ya—ÙÙBáBiò»ð;q&Œó¶c:ž;æEq¿Q[v85^Û÷:ÄfÃâ"¤këAhGï9Ô}&¯²T¶¤m‘ÆŠ2^½ê\Ÿ–ÒP)^˜‹é1v«0H ï+éïS”N—//!˜kÔÈÉ"HF§¦óâòâ H *`f±. €-€¢šSâüŸ{éÔ ¹  O޼4:zî…S³µ”%À¤6GBFmŽX¯z{¦ •(ÏCK¥V¦XG3sƈBD%äE}ÎÀêh< ûûª2X̦Àv8£G'f”V]%®Ô2"‡Ùô)­4%K£Ù‚‡Z[»Ÿ•ë{C×™Ìò“É=@qìbð¬ç¿½]¼·õɃþç»_IpzçÝ·?ß(noo~¹³»¾·þè½ 9þ£ìø¬p‡*Û>)¼ºZ~ÛWu¿?t}P´Û$B¢ëGYï*¾¡££4@hë•áƒú:#,#zÚéÜjýeÜq”rOžy®Ö|+\‹}‚PÚü̧°ÆF{v×:1HYü¢Üé±Óò¿ü5FÁ¶^” «þ±vøà]ò¶”AÖ5ó¡¦ÐÀ4 ÒùÙtFVäŒ|^A@Ù-´@Ö[Nt"öM;òìr5tåi$·ëç‹¥ÉU¸lÇl/ŒE¨»ýŒÜϬ­Á{t[ds õ6rA$§ð¢ð¬ Ì£ˆ ¬¢YøûÇÍŸ×åÊr»¯ÓþýwX*–¬§,H>‰ˆòYíg:˜)€(Dpzrbjrz‚¤yŒ£°È€x1RS“££c/ˆW àâ™s££§&^|ɨÑôã`tq)€fÚh8uyv¶ÜsA0÷ÚÊÖÍfÛdDœ2¥ÀcBššAœ¦[ ZKã삃!"*ógGH- ǃîkk<; µdž«ßÒ©¿Œ’PêSv'DÅÃŽïrZ4kä œ£9Û*üÏxþÅ¢Hûoä]Ÿï}óùæÞÎÆæ{{›ßÜ{¸»ûåÞgëv66ÚÛfÇÓ‹c{8ÉÉ{í¬~ßÏ2úÃÖGÖZJr88Ìî÷5ÙÌ"ã>ç‡p ³ÎR'œ‡T‡$=Κ3õ =ŽTöñóõh.v×BW ŸÆŒ¸þÓÊðQŸñÅÇ÷c@†›xŸ8 rät®^kˆh‡H¢L@0ÕÊzD†ñ\nnn¡y:7ƒbõÄþ~¨xCqÄëO$†Ð6B"C$M7¬ÊŸ²íÅŽéÇ'ÂÐ1=ñýËn`•C׈ ·f¿»0¹úýÍïÒÙ FÉ‘5Ýìó\w~Üà˜,óäùÐ wmåz͉E÷K„Î) êP¯Oóik±@š†1†s¡W‡èö§ç^|A¶sòŽñ“'ÇE¢k'OŠÀr8ùr‚ÓhNòO¡ÝœÃ3Ä ²€H®ÐY”¥âYP_ \ƒ/€™UqN˜>Ì¿¿hß,¢­ SIþ»ïg¿?‰7èf9çù^ ÊŠHq¨cÎãÈZÙ³žmÖç18¦£TÁÝö€h^yit ;ßM6áÙʰ|üüy±0òU2\èÜ"zž¦|ÀQÉlM'‹È´e‘9¶íT“(Lü¥ 2Œ¼(€B>Ÿ/p:©„ðò³â¼`!õ7:yztôôK/QÄéâB´82:6i úW¯Guy%ß·½Ô K~œËâˆV®ÛGƒ g´›Šæƒa†¥¿Ÿ3c+`~øêv†¡b?Y‹³Ïô™ ÄêéÑqO–ûúÛÇö?y~#ðÜÄVkž™¶o,Î%áLš'ú?Ç7êx©Å V0à'(0(Ì…¢E–¿OžI!ã/äìG±„ýÍf¢=Dpô‘(Ð!RÏû]¥ª’ÆL’ {®(€²H|µlz¡8"ñ',fÄù·Ä3c&ºq#únö»éhæ»Ô˜)ÖZ4@àÃa¤EÞFªØv[‹ôÄTf‚„6â8¨u"‰>ër­õ»ª,Q•gJ‡qã°ùóJAŒÄ³‹l”áx:ÅX„¢'‡|bÞ6ë’ÕœPÓî“a‚‘Œ†Q(Lç§ffÄöËŸ|^ÄjjæÂùéñr¹scgGe;•y L{[<óé!5äuki Ìâü;¡ãˆç– /…ý·GÆ|?šŒÁ¤OãÚUÏšå}µÿ}-÷C¿µÚ=eæ@ì¢z¶íìíCA˜ÎÃ-aÈ)#ÚÈ×;2Ü2‹6ìî¨À÷á·9÷bèñ„ eM‹L¢ øÞ¥èh©r‰ ‹ûmýw©ÓcðÞöVow@ ¾ø¢øðáîæîÞæg›ë½[¼ÿ÷ŸdÇs~s»“‰ ¦q}úã×GA §Õr–oOYCq¯;ZüËG±Ó>èrÄAŠýåE·‰3¤xjxì‘á²ß~‹ý˜ |dÿ“ç7@oܸåøþ˶g,6ò!¦L3Þd‰X@õ‚ÒÅ: Œ•þ†‚‡"úA˜^8+:$?EA£.ÿŒAÞãæ¼â|q¨ü<Ë’PÄi£ ÆEØ@¬„``H³Oˆg´(Xßr£JÙö"Û:a™näÛÕ²ï9•²å×f¾›‰óÓ7–—%0¦K(cóB1R¶L£d£õEŸ­ÂhÙÕܰ÷ìteÛ ¡š=Î`JU­FWy›ÚÃæÏg|ô]Eôu©‚Ÿiõ²ÙolûÔ®6kRS·5¥!c‘ç™ãƒñÀ÷¼ÈŸ4DâQ˜„#ŸbJ 0S( ¹Ü¨þé3£##¢Æ_X\¬/Ök‹%ˆ#®+@ÉKSãNéÎ;Nœ"PwܪiޏÜÚa¬Mõ£J&ð)SL[‚üžî¼/{ww¾0º³±÷Eñ³/wwv>ÛÛØÛ\ßAðï´YÙã :&¬‘°ôÖ#ðþ°õA4® ZŒ<µý])[&•Úg7*¼H[LÁ£ú—ÊÜz|üáxyЉË~° Ù?8¿2ж÷4Z¾¶vÛ½eºfÙuá8!:qâ0˜Mi•Ñ£WБiʆ €xXÂO“±B€8¾x:· fŸ„_A3n4DÚs§1[Nù'¿Y@ù9ç[†“´®@b…©¦ÀlÀ)Ž  |«\‘%Y©Jàš¢ªÐnµRõ<×4Ùï®MMÏb‹Œ¼xD³ŽŽ¸ µ’ÏÅééX ¢ÒcÂwíµ3r*°ß·uºP†Ôžß¶&[q‹YYÆ*k³Æzìüyš,©ϙ.C(Ë\&–YŒzZ)‚]ƒÝEºÕcrà æŒùÈ€ ÈÏf¦'òùÉiÑòrúüÔD.79zzäŒè‰N‹Hk‹õ†!ÂߨɃ­ãO£^Šr¹Ÿ÷mæK¥;¹\R*mY¦i³$–݇ͺc¡¬ ÅÔUšUÈ^*ˆÚG]€(œ>c×ÚÊúè%:†rÕebzˆ ;¾¯`?¶è´t,¼õ~ki)#í_ºj€ñ¡üß/~òѧËóßÝûjo÷Œx3ßl>Úùl÷Ë/7÷vÖßáþG÷î+#(2§Èõʉ}¥(=n} 3C`[³/š/x†‚(ào9PèÛ.ç îÏΟ1Šû­ èÜZq-˽zm±Yó¦â©i¸F¬Ø¿(-ü.Õl~žMû ¡½Ìÿ‘û$LEøE“d!GB`$áÄÉÙ“5í–›Š?S%Éç¼ 0Õ‘b!xØMqxXdºž'âîBþ«PeÓ! \ö|ߘJŒçóSçN¡xºdš€Úòö€¹Hü^Ö‘C‰~Ÿº™{e–AÔ–ùŒXgÖÌÄsVmÆeæ«7lþ|ÙšnWÑïŒûA‹¼Ã\@¬aÊXFóÐî0ù¸ »`tžóÜÀ çc¤ÄþOLH00 lÐ4º"Çs¹±3£/18ùâKgkõEè9L¢8±ÿì×J%ß½S*åJï—BqDþ½8½s'.9¢\ð DÖîÔ–"ßaQ5°ÊA.RÇ'qꢦžŽ¸ ½g¹¨Ý̱ègM5è”AÌÏ«Í8ìxxèñLA ³‚h[*ç†IÀ¿D ÏÿµŒÏåWD<(~ºuoKÞº³»clì}óÕ›{ëv6wv÷>ù_gðAG±Úhê€zÓq`m&¹¾ìéõ‡­á!àˆD |fˆ•…`ÙÈ ¯³ÉB‡ûõüƒ‘B_ ¡€žµúºyõÚ xÍ4™ÊK²–½$ÁLg$(€j ßdšú~ºprtüìɳãò×øÂ™›g^x!}A€Ex<úGM‘` IDAT[¢æÙÜÄÄÄÈ‹Lÿ×€) 9J“Ù<ÈóB¤ùd6™Æ\€pnŒß"ê–„ŽYVP–E¾S©TLã†Ýff&ÎÍ‘1- â³% P‹É\±ßÎ&ÈR9râ~™cé(u"*·}zîšA½îØX”ãüÑãçϳ ê‘}¥Éhgþ'ƒQ}Ó±I …ÛdIä'8–-ð÷F,@ùJ-,ˆ\òS@ò€IL0=ž;; Ü¿h€Ó/¾ôÒÄ‹‹†!bßLÅüÏ¡å§VƒÁ¿#jÖ½#J —Í/…^êÙ¾_bÐ÷Ð Ì/Ý'kA :…O«pÊyëÚíêTÉÛ¬R?™„z"IÕÕì*:ûZ!SU ó —gHlØñÊý„¬w€`À–üÈ/ÊËCŒÏ•KˆŠŸ|xïþV·÷ù7»ß|~ýË/®o¼~uwóáÃͽGëÖ7‹÷¶ïgÍÜm^H_ùö8ªüp}±ìxüúš–e¿qWÓØÏL²RŒÌ<دç?د”`u¯z‹P@Œ ³Ù"’³4Ö I~*ÒØiAÐõ4Ø¥sÄ÷a›l,NŽÊ¿sb~Dq,,ÀH¢Íõ%QcDßFXq ¿0Ð|)N”N4hfj0L ÞŒx"授 @Ų½c€”cÒ˜NŒó…™ÙYã{cB<€*HOmST\€Z+BCýqÞäPÙ4óš¹Íòô{dVo±X ßYµÛ™ŸûÃóç1’ÝDA„ñqœYÑëgd’Ç–/ã “ÈÅr%´1=K´€è¿h~~QT@~zjzrj™€©É©éÂÄÔÙÜè$NÉÃ8u*ÿ¢¨‰‹Môt5›Í¹$O )…"ö¥ÀÈåJašË‰F „2n ” .¦ƒ_‚FŒS<÷9Ô xh8é®ÒaL•1¤¡Mº«7oXJé°óJ“Ú¹DÂð2Øã´ìp±ïg¼LYÞB5T@wé(ÆçÊåâe‰ñ?ùøþo¶––v÷.Œî|ùæ›×ׯîíì<ÜÌïìí|³Î:a[ ¹èijgEÂáÇ××°õ1´ <¤ JB‘Ž–g”YeØ ?2?X˰<ÿ¡XŽ›Ñ[i`Æ„Š!§õ¦t1¦ODøƒ0O?Y~ª008kb“¿çÒz£i,@)nžÎÁƒíò¢±0×hÄiÆüA’*xœäI º‡IÁ’Ën@ÙDØý@ì_ À2-7 ]Q¢ªÆòwFQÖœüxìüyÄ¿˜Q„·÷3@Ÿ–n»ûÀ GˆýÁ†âZ ê²$\gK~òý/L."0==ƒ’ @A… ` `ìÌÙé’Qo.Ì-.,Ì/,,ˆ"h6“TbþóçÿZd~½”ÆÎñîiê!/Î8ÇEA(.ݵŒsµáœ)©!%¼•¤ÚÃ(ûí¦§›UdaÉP‡e pfÈñ:%Œ³9æhe,arË3 pãóêÒR±øé½ûÛºs·øÕ—o®nìl¼¾!1ÀÃ/v6Ö‹;›l}¸EÇ‚‰¥!ÒG9ÞÖ×°õ1 6 ²ßÖtHïY@«ëë#ÃÅUpv~Í@$A#tãÀJ ¸8W #8’zÌ(˜?œž‘³h ãI@‚‰2Í‘ëæâ‚„ð͹¹f*: N$(˜@©” =! °*{PM'ƒÎ68K3†E7Pñ Ú*_çTEÌÁ¡·”ø>ôÀV¹ÆJdLÅÆìD^Bñü¬!& óD0K ´èß@¼Öf·¦°ØÓÒk«¯Î:Ø Í.©¨öµÉ‘î°ùóœM fhm4aûŠ2e`‘vúá (§˜}DZL\ô€YÁX;qçê¡ …)€‚‘€˜÷Ç‹/‰øŸ10J Ùh^¬/ÎÏ/,ÊsºØœ+‰üŸ—àßaP¢Ð~ßÏÿ,—‹PE=@¹Àtf'{3²¦:;äé²×ú Ùk†AQ©m™^ÝgGQK)Gzìà'Vúx(ì°ãëQ«Õ’D}6hJ\ÌZ| ãsùÊRñ“íO?Ù¾¯;¯ŸÿêÖ£¼øþëW7öö¾Øûæ‹âÛÛÅ>üd{KËh$Hc· Qdm…lµ2¤Ø1ëc|º£TRÊô ¨µº^¯\8¢Dàuÿàü:wøëÿnÄ^êÛa`'ªââš8ÏÚØÇéqò»´à縗~ÐH/ΣoW)Bh°åå¼VúRÅô 0˜LÔcЉÂ|Åšš×þ@¶¢'q¡¦ã4Îc”pšdoƒ @ê€¨Š‘8Ö ±¡[®Ø¡n†n¥ü„1=:3; œgUÓE>;ª°ŽE‘¦\Ée+MíÊ È~шMî?eS&º”ÍüðE[ZH |dÈüy6Y¨çÜWŸ^1ò‚팭áØfA3‡hNqýÛ“‹qGFD«™œäbC½Uk^4—Ì5“æüÂE£€éÄ“ù´*”O½tzüÌè7õtnaq¡)Ò¿Ðl^œŸ¿È¬¿øþâúË«ŸÅq©”¼_Ê•Jw\¿T²·ß ˆÎö fW%CNI‡,w™˜ãõéðdÐb´†5£¬®5³ Òá·}roµ‡6à ;Æ/þgö¡'‰ ™‡E¾è\¹reé(ÆgC€âƒí­­û–0«°»óæªDo¬¿ñÈxøð›w7¿`’à~ŸÍ<]2’¡"¯ð.øÑWž‘!ëch3Øf¨ýl}î³Ûòéf+Öl®\Äékª€,ðõ`¿œ3…^Ó"À׆o%žøftÓIÜŠ±¸P túgcBú¢öéÅÓJÛ+ñA{IY LÉÄß‹/hãð\¡E™ñœÇBùƒÓ´î«tÀYT‘¤ó[°@–JB3AíJÙ û"Ö²é7ß7ÆGfÎMùÑI#~frÚYá T Z-Û#ïóÈ ÆF ÒÓtZÊîNŽ5®c\}Õá 2é¾A»Ð4xüüù>½ûê;ktL-©¤H.y|;hÖÎ)÷KÄ_Œ¿cî‰[þ_åßÿŠéÎ6Ó€–—Ô=Þ³ù‹Í‹ œ–0€ àœÄÿ§ÇÆÏŽ‹ùO£ZT @SŒãâÅùRè—~¦¾I^y%ÇGàŽ+OY~ •(ͼéìNdöµž]o$Ÿ¥†dÅ«“E"ëÍvTíƃZzÖÑÃûÎÌâãíªO¶Ã;¾ßÂOÛ$ô|¿¦œ35:¯â¼úÆgór±øà“â§Ýô­ËWò;×oíÝÜ\Þ`gæáNúî¦hˆ?Þ~À±5™…ï*8ØŠE€¶'dtèúÚ>¤Z¡½®BTŸn·F;öxd/_iQhàëƒýû½%=y¹Ý—ý†wíªk~5\³b  ŽzŸ¹žŸG ¬¼“Ö5ûÿï§N f_P¨ÔÁŠå¾2Þ䀴¦!€"‹Å½÷ý8eéDíÿWRh•˜ ƒl$™â‚C(1½7Ë"û'œÐ8øÚU»jºxἨg#?6i\˜š(à;±­Ûã /ÛàÀ h+hKbŸŸ,—ûÉ y±«P_ƒ‚û¯!H2^]?´£).¶ÕÒÊÃá}¥’9†"f ™ÿq‡Ü&– ÀÞ˜eCµ€òжkuìþiZo6ç/Î/†(€é©éB~¹×e[ϯ®î¬|uýÑÎúÞÎ#csGŽ/n? p+ƒþ`òÊü\GS{p5Xe¶>† !DÙ׌‘Ž>yáŠ|×.-½reé’ø:¯½ 3?Gö·0wøÊÒåW^¹ò5<ûƵ«Áë•`­˜eôDtÖÅrÀmŽkȘKØI8ùïµègõ(zóìû©I@‡5yA^ÖjÒ…€=¤–À$ÐpçÄÔÙ9F9º&ï=Òõ8Ÿâ'9D>#Ê×xľK išÖÕk>z¼ð„Väß“o]~]€„³³²þÅù/LÏLÏŠðÄ[!qM‹¦ Øœ »A[PSÞ„žx¯Å§Ž¾;Û[‡¢ù”°‹l+µƒÌrÿÙóçÁ7£ c%Õ,6+ãl/:žJ‡$NÊŸñÇ´åÊ9Õ ±ÍvWÔZÍ©ÕÒºü'îÖÂÅz“…ñé³âŒŒŸó/ÒßP×*_˜¯_\hÌ5çæKýÓRég¹X|~¼*á•ü_ZÏoþõùó%hL?Œ¸°¯¸ˆbëžB¡ÉŇ¿YDéÑü+ÒBÃ÷c)©äÙEѤH'½ô0z (Ò½µ')«·ˆÛ°ã£qäJœQEMþøã´ Ø<‚ñyw§¸ý›âo~³ýéÖGrG×濺¾r}ogãÍå½GÆNŠ:áÖùt{K4SÒâds‚rÚZþ〩Àôv·>†Q £DSÅ@~)”#Ÿ¢\ÛçÌ×.½úÚÒ•¥W^ãtañÿöËùÅA¸,1À¥%è#pn¯-_{óÖ\·Š@Í róEA>å+äëÂ@›t?ü7Jtr(ÈøN‘«hJÄgÆÏ'qàX‡"ô!ñw^næ ¤LtÄl"—„3É”fAÞŸ}Ý,ü‘c}‚úöë/_½vÃt}Ï®˜þ ‰\Y!¿µ(€éÉ©ÂcfjÖ8?=3c ÿWu*›6ÊÀŠB¨ˆÔ`xÞÀR º +L”ÊI>Œ3ÆA{€ÔJKéeÑK ot0àl›?Ï”3@&£MBš„A9\~Ž¿,m¬Xw„ÓÛüÇ('Q¸&×2ÜX##V­Z«“л67'Þ}õ€ÂøDî…±³âýF:Ø/ÿÏ7‹MÔš¥÷šKKwR“( §„Wè L/üló|I>ªR¬ï¾š£6g×ÕPSÿü¦„þ2–i³5FGúqÙ!¥ôÆ=ÂÉ«z)ßw\Üw}ÿ·Þ“¤•q”m!ä7ð‡?é8î–ܺ$5z XI¥ güì³/‰ñ¹·³¾¾ñèËbýŠÿðß¶Ó[xóÖß\”_^^ßYt͸¥Qô$HøèãÛ[8>‚Éð—¨0V–6j<4l} #…FŠÊ.Se]fVê)ÒUy ˜*ˆÉÒ`” þ‘ýr¦ËK¼úê%ÆFì½µrûÚuëå5Ï.›Æb3túQÌÊ-žüB­ žOŒEÓ`‡ú¢‡ù€NW~p~ÞzßEöå‰y5ya <ÄþÀM+„~^/>½îŵi:oyyc\sË)x "É¡g•íaµúŽY¹o @‚ßYcv|¸P˜½ðÝÈ^U$‡`@‘þªç9ô¤a>« ˆœƒ5Ãqê²ßBöÈÂsð£˜^Š/JnÁÊ€fô:ýaóçu0IÞSH óå|F­ýãi¡u1Ë&kuÀa]Ž·Ç Ÿlæ³ëKEÆk ïÆ|½¹ØD=`b<÷â¼ =Ü_“†Dà \@êÜë³Q‰‰@¼J½óïnbƒžZ{0!‹”¶Ù±æ¼•5úYû;[™© OñC´Ô"ٿŽÞȱ!^d‘ÌÏÆ’¶Z6OŸøqŽç;Þ>¸už…´V€ïÞÈε+‚þpsç#b|jIT,†¿©ÛÛ)ðù•/®ïH°¼^ÜðŒ3â;†^±øÉ§÷Ããc1UúèYn#¹Ho ¾û­aëc(-ü0ZônWŹy—OÒ®£[ñÊe¤3_{õÀ×—îït–®¼²´ôÊ+—˜ 4â[o½µz{õåêšÙP3<+¿6ûdØ BЏüÆŸ©‰$gÍ@Öy>p³Ä5s$Æ/м:ž¼E¬ øVäM¤üA>C êñ¡&çb°XÄÄ> 5vˆrAè:yQ. â û‘]©ž?tíê­Û¢VDŒÆ…¢aÌÎLÎ_ø~ÆâxKXH«j:¬ŸÃž`‚%ÜˉsÒt‰ùÞ9—ºÁ OµÊ/k·=ÖœX EoÈüyÓ q_ë=¥!|½×=v0D¨\›Mdº¨jŠýß³pQÈØ–[³lO|¥FØ^ òE¼/ÖELMæ^œ2”í7=º?ỉK6q®Ù¼x¢^úéÛš,•Þ;-](•Lí6¨Z4¾ÚJÓkëØ[æÚ22ý~6ÜeÊy‘õ ªfØ` º5žxizi"Ï ÑPåô<Ëjp…>pÇöä« ;·ŽÇË.p›F¢M÷[ ôîñù#ðpûCb|öv7­F=”,?öÅ?®®l^ß[Þ¨;Æiñ"M§øÉƒûoßÇñ>´JW•;F¸‘¼«¦¼Ëáã×ÇÐÁ0C£TÄì!oêSƒW´ns Í+¯¾v岈ù+í—óËŽË—ÄA¸tåÊ’!.FUVnÞàtà‹ÈÍÍ„ñt-š‰gã‹ÄSèCÊ˺üÕÃ|Œ4+É~cH»xûq4…B­èïQö ud#¶XĻ⠈´# N¨©_æê %»û âû PüÇ`šJ ß¾}û†(€Ùï£Â¬1=>e”JõÐÅÇà3‚¿åÙ"/Õ0…‹ |)²¬`E˜(Âú¢ÀCÅ@#Gòá)ÛlƇÓm F·›?ŸµÄIaê.Ùþ™+k3 ¨—Ñ>us~Óòþ¢¸Ú=DÿŽh/ñD°=VSäy$1L}ŠZŸ1“3Œ¸Q¯Ï=±¿I.àšD M‰J¥,ÈssuÈ\%WË‚ª¥“ašöé¼p=#Þïfù?Eø´µo y*­ÿ Mupi:œÒ³½*l;³5cPß®B>@~ç²:áŽývèñ‡ûmL8’@ó¾ÿ3€‘k“çÿÙžh€‡Å·Ö‹; û_5’ø·ø@ã§«_ýãFñ‘mçLÛÛ*n?½¿õÑýOy<ÈHÄ$ФPqŠD8tüú6®?d4\þq¬}B&ö3ȳ&#³Å&íµ+ÙxñW^yl4ÛàüK—^ípå²ùkÌÝ\Y}kíÚ²# sâêÌ¿ {\bú|=‰$œ¬Õu°IDµæj…9ùW~œrW4j,è6€à«gºײÖÓQø¥¸¥òÛ(–ó¢/•SG‘FN× 5×äWâgÔÒzRÐ0@Á3MS¹Y9Qµ¡åË6„øÆÊŠa`ü•nÀïkò°D@Ì-˜Ï*rf´#à»'–NŒ,+?K„úÌîÃK°H‹-ŠÓÅ)¥ì#S^ùžb?èI;žYMÆp™ ÷ *šP"ò ÿÀpÈ®øÿ"ÿ{{{¶µ‡/‹ Ž¢µ†ö"[‡¹&†z{uØxLø)'×7j‚ ÔþRÌúÀ¿Oì˜ÜW¹ù ÑsŒJˆæb¯”ÍÁJœ¯®“¯P&Kð~WKT-B|ÐrgOñ.į N9¸47âê\`ðh,{Ìvž^é`Z‰ý[ǃvö†¸ßsŠä£¢¾1øTžÿîÇ{{Å?úâöo$󫇸À›ù÷ß_žIç›Æn\±øéVñÁ‡÷19I“ÉY#Gý!ÄWi'tjÈú6vØpTN›îèø¥íP(ŠˆíXÙpÖL\z|8ëáù_Yº#ÄJÖ’ô-|qqîâüܼl …fS¬Ê|s~qa¤…Œ¡\̦Ñ-4gš˜F³85¿(ï¡]iÎ/ÌɱyËœD¥òkyƒ¼IÎÖÄÁ]½ ïš+,8ÑnAöÎ/Èñ ór€½8×ÄÜjœ}a¾6µ(ÊÍDÖ¿‰š_`WOT­ÐCROìÁê-qÝÒX´Gýûº7eÿgfËÕ °³,pÁP²Š0ydD–Œ­{Ü#Žÿ¡°\®e{ï±KŸQGÁ¼ÃæÏ÷³jl ³0ÄÜŽ>Ïý ù—ÅŒ Ìpvì=“È&fpø!‹§u⬠cÈø‹´ó×54Uüà~ÑŨèbB8þȭΪ²žgóá-?Š:Šzêö³à6#Ä&V‚“ˆ²Ó¬':+تG—fÈxjG/ml¬úŒ«óž_-¯Bÿ_¬jýÞÇóR~‹ÖFuÈCy¨%{ŸÿýÏ$®¿÷îì߈çâóŸ•Þ¿þï~ò†1[ôŠÅû¢ê[Ÿ|Š“ºÈuÅÚcÚÒ‰ß$ íqúïÐõ1t<üÐñèÙøx¦þØÞH˜PG‘ýÇÆ³/‰xr<ûàü—zÕÝ(zt- ÓÿÿÚŒ$Z_3MëšZð Dß;+«7nÜDØ¢ÛÕkÆóíùö|û¿Ü"ÑÊ••5qŒ ¸úc£Û5|Qå¯Ýºuýu/„ @箆Þm [ ý_·®^»a[On}ϱÊåJfð¡þ«Õ2& ¢¥8ð䧪é…4O^G)?£ûP̱„ò6´á?;Âòå­MAèáËEîÞÆ›B¿üÿ¼UL'é“xQãîú;²Ý¹ó—õÎÝX'$ûÉóý?îþÈu­jåÿõùú¡¬©ªí¡ÌkV+UÓEŠ (YN²ÊªÇ­<‰|+¬<= ]¶Æg+¯\…çŠZeK‹]ºiñ©Ìl#ªN‚M VÔ k‘ïÙ+«‰øfon¸ìÛV¥lêt(VÁ¦ââÝ?û°(ò i¾kÉûlO® )SŸ×I!$ÕFž-pm* ÈòOÛò¡n•‹®ìcÙ«ÖÚêíëoˆâx 1òo96jËrsQ)¼}DèÄ-vD)aÚ½h ÊàÔ(¾€šG~…o ÷"{^¦…ƒl\8î´éüÍÛo¯¿}çNîÎ߸¢ õ±[|vƒ²ùš“]‘€Ó´ãD±',^¦~hóÒT³®G¹%.Z˜c¬¿›«ÜnÿÅuY!º#žïÿq÷ÛùW«˜å‘ž±¹ƒs¶ü Lb«J¼WžÉ•caÙÓÆº¿çʳ2A™÷°³•¸~:”ÒÈôrª&°Œïª›¥ç’Ǫå&ñjl¿ Ö ”ÞEîpž޲‰ú™üO-ãÐxg ÿAŒ?úò<^ °cÔ£kå‡W-h3'»½{ÐXœh ¨ÕÎ4Õ¿w-«j¢Tµoy·ßº~ôB€ewQ^µÀ›W«ÕüâÖñ§¯!R_µå;;UP‰0‹wƒ¶ŸJNîf™}Å¢-ÖÀ;‚§‘EÁÛw³íNy*xZΊ„ê H¿EM&ßY´ ýü{»…rã×òMãèý»ë«ËoÞ”ë;ùYëwßO"@äžïÿq÷ÃPeVQlšóûU±ôvU”}UM¡E€Å/î>$ë÷_yîÑ•WÎVž…†y§b‹‘òÓ'‹¿‚Ï tƒÀLÃò…Öªë%·äÛ¼læVËH¶S «ââÈç…Å¥ËU;ÁWÞ“DÔdWyÎ*qfTÛ˜Èu#Ôvé°@îÆq(…UȦ(!ø1â¥d*À´à߯¬¬8¶B”ªÎÚòÍÕ×ÞTP1ëx.±ukÅônË \6ÍüÅûEëï™"[zM6¼Á-@0EA«ÈÍ”k¥ƒ"jˆù媗•ÁáµÄ?ÀÑ.¼\P ˆì!bÀáž;¶¿&_K4}bÈ?"vH"hõB×Ñn<9ÚL€%Q¹*ºðüzpyì,ƶéæTçˆzLÍU!Ÿ¢EMoàˆAÿÞòWW<Ÿ¥j²ÿº/4+'̲·‡þmÏŒW—yósåFL?| þЫ¢ËåûóZl'ú5¶@¿·h>uFD)¶þ* çIDAT¡²æíS‘W¡€*L¾Ã-àS¸´´ô'ò'oã9ú{zQð!½0à!xK‘‚¨X¾m2; ¤¦a~psåË—1ôÀuéU›Åøo߸x’ Уóù|ÿ» þb©}Êõ‡£€, Š,³+"fá#h~˜Øû®<‘"(¬%]å ÑSñ—yöï°¡Ä+º5v¹È7Ú¦½¶BDDÖ§¶Ža:×áâ³Ã£‡IÏ7-(—²§Lðªæ4TÙTÔø{¡—EqŒ9Ì€â!ð~È^’”Z¶h¹wvpÓ[¹y}åú›p¼²yÂ+Û±c>&^¿µvkÅY]Y½ƒD§åPóUËŒPL\Wýêï~õ«_ç~Ðs‘¸…¾3äü]è¼CŸ½ ·›<…·/ý›}éJnð°©·“½U¾¿h˜Ï“ë¶«¸yƒ;rœ_èhjWžÒ#ÖAêHà;ËoüÙŸ¿±Œ¸ Ô¡ð|ÿ»_sâÈ1û4›¦ë mŸ±1#mƑȺÍT_¶òð{û¹ò*ëÝô2#ëeÖ½•òÿïþ9dq飇ÂCêªÎ*K œ·;DFP¸Ù4@QÀK aÃl.qBBç ñ9pàùû,5 "&ù•œˆ(þJDTטù¡Ë§j#ï8IJ} H’ÕÕØ·ìxe5¹}{ù:j'vÙ;áWËÀàÈZY»¹&âïÿ(ˆÎ?Ó ˆ/D_ɽÇùó_üòW¿†Os­ŠêÜ,šC"ÏCÃä£AÁ± på)Ü}ûÒ¿ú×¢ˆß‘‡pw}}ýw²ŠoCÖ<]¼­ò åùDžs|?’e ªifHI€ëàüÉŸ¾Á¨ ×÷|ÿ¾Ÿ1º‡ SÖü¸8ãÖ#cq±!ßÿãî?ˆrIHç«ÿtÀn?W$¤59γdhýGZy"øXy–Cþ[ݘöÏò¢þÇ?© g yýÀ œ*|¿JùT ô "öÙª ¸²”z3èhyìûùE” (<èy B~C7dÖцԂÄÇgúÜ‚5ñûoˆ”‹î¨½%Qÿ2³å'ñý`ù}Ï?*ÕjePuœñ”K狨ÇbZ>LWn¼Y»¶AÐ8rRùf® ¨“¨tûHs: $&|šñ¾PFÖ åzuUGÛv³–MÖøÌ¿! O(O•ùäy´0ŸˆÔ¨G˜SUo; Ôpp.$HªÌ†°BŒ"‹E.o—Ê|ŠqœÔt"ÑeUö-«^ö¼¸¥ÉþÀ—å$Ô–A”Öäö<ßÿ£î÷޵: x¬Ggœ€ —”ޤq°Ð¢ìƒl³¬a²õZy^fúŸXyjä²l”Ê'ñíXf{Øl7<¸¥>ñ¦méÂzÚ@¥Ê?ÞøÙ.{ºæÉä廊|Ã…Ñ~âû…™]<ü~óTj ƒòÀ@VMfCÈ‹ˆ^{Sì== 9wÕtØÍ€ƒÂ&Zx¢„öªVXýÁ@6µŠiÔ'7QÂ^ù'l!>ÛÕ5Á)g¶ÕewTSñmìÒ"N„má BóOð‹NæãƒÒ3|¼…*ÂÃ-"*hÓ£Ãß„QRÓ©‡Hâbõm²Ÿïÿq÷“ò:{Xx*œè0ðVÑxü‰t£)V×þ0+/Çæ“+ïP!{“ +¯¦õÜàˆü3SèVL/+Hy®U¶ÃÇÞ ¡Lèeìy*äƒ6Ū~[¦;0°Ã2~¿è™ßϵÄAÆË¤·~ º”+ùÆ®WѼ"ȱ`p?þ%è«wG€-?IEND®B`‚fheroes2-1.1.6+dfsg/docs/json/000077500000000000000000000000001476115357100160665ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/docs/json/lang_be.json000066400000000000000000000001071476115357100203460ustar00rootroot00000000000000{"schemaVersion":1,"label":"Belarusian","message":"17%","color":"red"} fheroes2-1.1.6+dfsg/docs/json/lang_bg.json000066400000000000000000000001111476115357100203430ustar00rootroot00000000000000{"schemaVersion":1,"label":"Bulgarian","message":"81%","color":"yellow"} fheroes2-1.1.6+dfsg/docs/json/lang_cs.json000066400000000000000000000001051476115357100203630ustar00rootroot00000000000000{"schemaVersion":1,"label":"Czech","message":"100%","color":"green"} fheroes2-1.1.6+dfsg/docs/json/lang_de.json000066400000000000000000000001061476115357100203470ustar00rootroot00000000000000{"schemaVersion":1,"label":"German","message":"81%","color":"yellow"} fheroes2-1.1.6+dfsg/docs/json/lang_dk.json000066400000000000000000000001061476115357100203550ustar00rootroot00000000000000{"schemaVersion":1,"label":"Danish","message":"93%","color":"yellow"} fheroes2-1.1.6+dfsg/docs/json/lang_es.json000066400000000000000000000001041476115357100203640ustar00rootroot00000000000000{"schemaVersion":1,"label":"Spanish","message":"68%","color":"red"} fheroes2-1.1.6+dfsg/docs/json/lang_fr.json000066400000000000000000000001061476115357100203660ustar00rootroot00000000000000{"schemaVersion":1,"label":"French","message":"92%","color":"yellow"} fheroes2-1.1.6+dfsg/docs/json/lang_hu.json000066400000000000000000000001101476115357100203660ustar00rootroot00000000000000{"schemaVersion":1,"label":"Hungarian","message":"99%","color":"green"} fheroes2-1.1.6+dfsg/docs/json/lang_it.json000066400000000000000000000001041476115357100203710ustar00rootroot00000000000000{"schemaVersion":1,"label":"Italian","message":"39%","color":"red"} fheroes2-1.1.6+dfsg/docs/json/lang_lt.json000066400000000000000000000001061476115357100203760ustar00rootroot00000000000000{"schemaVersion":1,"label":"Lithuanian","message":"6%","color":"red"} fheroes2-1.1.6+dfsg/docs/json/lang_nb.json000066400000000000000000000001111476115357100203520ustar00rootroot00000000000000{"schemaVersion":1,"label":"Norwegian","message":"78%","color":"yellow"} fheroes2-1.1.6+dfsg/docs/json/lang_nl.json000066400000000000000000000001021476115357100203640ustar00rootroot00000000000000{"schemaVersion":1,"label":"Dutch","message":"11%","color":"red"} fheroes2-1.1.6+dfsg/docs/json/lang_pl.json000066400000000000000000000001061476115357100203720ustar00rootroot00000000000000{"schemaVersion":1,"label":"Polish","message":"79%","color":"yellow"} fheroes2-1.1.6+dfsg/docs/json/lang_pt.json000066400000000000000000000001231476115357100204010ustar00rootroot00000000000000{"schemaVersion":1,"label":"Brazilian Portuguese","message":"98%","color":"green"} fheroes2-1.1.6+dfsg/docs/json/lang_ro.json000066400000000000000000000001051476115357100203760ustar00rootroot00000000000000{"schemaVersion":1,"label":"Romanian","message":"14%","color":"red"} fheroes2-1.1.6+dfsg/docs/json/lang_ru.json000066400000000000000000000001061476115357100204050ustar00rootroot00000000000000{"schemaVersion":1,"label":"Russian","message":"98%","color":"green"} fheroes2-1.1.6+dfsg/docs/json/lang_sk.json000066400000000000000000000001061476115357100203740ustar00rootroot00000000000000{"schemaVersion":1,"label":"Slovak","message":"81%","color":"yellow"} fheroes2-1.1.6+dfsg/docs/json/lang_sv.json000066400000000000000000000001061476115357100204070ustar00rootroot00000000000000{"schemaVersion":1,"label":"Swedish","message":"99%","color":"green"} fheroes2-1.1.6+dfsg/docs/json/lang_tr.json000066400000000000000000000001041476115357100204020ustar00rootroot00000000000000{"schemaVersion":1,"label":"Turkish","message":"16%","color":"red"} fheroes2-1.1.6+dfsg/docs/json/lang_uk.json000066400000000000000000000001101476115357100203710ustar00rootroot00000000000000{"schemaVersion":1,"label":"Ukrainian","message":"96%","color":"green"} fheroes2-1.1.6+dfsg/docs/json/lang_vi.json000066400000000000000000000001121476115357100203720ustar00rootroot00000000000000{"schemaVersion":1,"label":"Vietnamese","message":"82%","color":"yellow"} fheroes2-1.1.6+dfsg/fheroes2-vs2019.vcxproj000066400000000000000000000046061476115357100202670ustar00rootroot00000000000000 Debug-SDL2 Win32 Debug-SDL2 x64 Release-SDL2 Win32 Release-SDL2 x64 {DD8F214C-C405-4951-8F98-66B969BA8E08} Win32Proj fheroes2 fheroes2 Application v142 MultiByte fheroes2-1.1.6+dfsg/files/000077500000000000000000000000001476115357100152675ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/data/000077500000000000000000000000001476115357100162005ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/data/resurrection.h2d000066400000000000000000003324731476115357100213370ustar00rootroot00000000000000H2D‹ê&adventure-map-grass-cave-diff-01.imageu &adventure-map-grass-cave-diff-02.image00barbarian_castle_captain_quarter_left_side.image5!circular_stone_liths_center.imageÅ2circular_stone_liths_left.image÷ècircular_stone_liths_top.imageß!graphics_icon.imageñ<!hotkeys_icon.image^‚knight_castle_left_farm.image…fRlean-to-diff-part1.image×h’lean-to-diff-part2.imageip+)main_menu_editor_highlighted_button.imageù›>}main_menu_editor_icon.image7+%main_menu_editor_pressed_button.imageÇD+&main_menu_editor_released_button.imageWpjmissing_sphinx_part.imageÁpÐ*observation_tower_desert_bottom_part.image‘wL)observation_tower_desert_right_part.imageÝwÐ+observation_tower_generic_bottom_part.image­~(observation_tower_snow_bottom_part.image½†€'observation_tower_snow_right_part.image=‡Œ%observation_tower_snow_top_part.imageÉŒŠpetrification_spell_icon.imageSŸ#petrification_spell_icon_mini.imagec§Ø 0sorceress_castle_captain_quarter_left_side.image ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿ !ÿ !"#ÿ "# !#!"ÿÿ "#!ÿÿ !#ÿÿÿÿ !ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"##!!#57€#—"!"!""4564>##®®#:!"7#<1#:8#9«#:8*>!!-+#h+#!'#:1&#! # 7#:­/)>"9(##! #"-#9=# "# #!!.#! >#!#"8#"«#7!2#>ô+  ``````îîîîî``````````îî`````````î``````ð`î````````î````````ñ``î``````îñîîï``````î`î``````î````ïð````î``î``````î```````ðð```ï`î``````î``ððñ````ñ``ï`` î``````îïïð```ññ```ñ`ð``î``````î````````î``ñ`ð`` î`````î```ññîî``î`î`ð``î````î`ñ````î`î`î`ñ``î``Â`îð``îîî`îî`î`ñ``î``ÅÅÅî ð``î``îïï`î``ñ``î``ÅÅÅî!``ñ``îïïïï``î``ð`î`````î ÅÅñ`î`îïïîîî``ñ``î`````î ÅÅñÅî`î`î````ñ```î`````î `ÂðÅñÅî``îîîñ````î`````î ``ðÂÅñÅîñ``````ï î`````î``ð`ÂñÅÅÅññðððï` î`````î``ï```ðÂÅÅÅÂ```` î`````î```ï```ððÂÅÅÅÂ`` î``ÅÂ`î ```î`````ïïÅÅÅÂ`!î``ÅÅÅî````î``````îîñðïî``ÂÅî````ñ```````ÂÅÅî``ÂÂÅî`ÂÅî``  ``ÂÅÅÅÅÅÂ`````ÂÅÅÅÅÅÅÅÅÅÅÅÂÅÅÅÅÂÂÂÅÅÅÅÅÅÅÅÅÂ```````ÂÂÅÅÅÂ`````````ÂÅÅÅÂ`````````ÂÅÅÂ``````````ÂÅÅÅÂ`````````ÂÅÅÅÅÂ`````````ÂÂÅÅÅÂ`````````ÂÅÅÅÂ``````````ÂÅÅ````````````Â``````````````````````````````````````Â```````````ÂÅ```````````ÂÅ````````````Â``````````````````````````````````îîî``````````````îî````````````îî`````````îîîî``````îî```îîî`AAzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxzx‘‘‘‘’‘’‘’‘’’’’’’“’“’“’““”“”“”“””””•”•”••••••–•–•–•––––––––––qx‘‘‘‘‘‘‘‘‘’’’’’’’’“’““““““““”“””””””””••••••••–•–––––––––––––qx‘‘‘‘‘’‘’‘’‘’’’’“’“’“’““““”“”“”“””•”•”•”••••–•–•–•––––––––––qx‘‘‘‘‘‘‘‘‘‘’’’’’’’’““““““““”“”“””””””””••••••••–––––––––––––qx‘‘‘‘‘‘’‘’‘’‘’’’’“’“’“’““““”“”“”“””•”•”•”••–•–•–•––––––––––qx‘‘‘‘‘‘‘‘‘‘’‘’’’’’’’’““““““““”“””””””””•”••••••••–––––––––––qx‘‘‘‘‘‘‘’‘’‘’‘’’“’“’“’““““”“”“”“””””•”•”•”••–•–•–•––––––––qx‘‘‘‘‘‘‘‘’‘’‘’’’’’’’’““““““““””””””””•”•”••••••–•–––––––––qx‘‘‘‘‘‘‘‘‘’‘’‘’‘’’“’“’“’““”“”“”“””””””•”•”•”••–•–•–•––––––qx‘‘‘‘‘‘‘‘’‘’’’’’’’’“’““““““““””””””””•”••••••–•–––––––––qx‘‘•–•–•–•––––––qx‘‘•••–––––––––qx‘‘”–•–•–•––––––qx‘‘’”•••–•–––––––qx‘‘“” !! !!!!!!!••–•–•–•––––qx‘’” !!!!!!!!!!!!!!!"""""""""""""!•••–•–•–––––qx‘’” !!!!!!!!!!!!!!""""""""""""""!••••–•–•–•––qx‘’” !!!!!!!!!!!!!""""""""""""""" ••••–•–––––qx‘’” !!!!!!!!!!!!"""""""""""""""" ••–•–•––––qx‘“” !!!!!!!!!!!"""""""""""""""""!••••–––––qx‘“” !!!!!!!!!!""""""""""""""""""!–•–•–•––qx‘’” !!!!!!!!!"""""""""""""""""""!••–•–––qx‘’• !!!!!!!!""""""""""""""""""""!–•–•––qx‘“• !!!!!!!"""""""""""""""""""""!–•–––qx‘“• !!!!!!""""""""""""""""""""""!•–•––qxŽ‘“• !!!!!"""""""""""""""""""""""!••–––qx‘“• !!!!!"""""""""""""""""""!"""!•–•–•qxŽŽ‘“• !!!!!!"""""""""""""""""!!!""!••••–qxŽ‘’• !!!!!!""""""""""""""""!!!!""!•–•–•qxŽŽ‘’” !"!!!""""""""""""""""!!!!!""!••–•–qxŽ‘“” """!""""""""""""""""!!!!!!""!•–•–•qxŽŽ‘“” !"!""""""""""""""""!!!!!!!""!••••–qxŽŽ‘““ !!""""""""""""""""!!!!!!!!""!•–•–•qxŽŽŽ‘““ !""""""""""""""""!!!!!!!!!""!••••–qxŽŽ‘“” """"""""""""""""!!!!!!!!!!""!•••–•qxŽŽŽ‘“” """""""""""""""!!!!!!!!!!!""!••••–qxŽŽ‘“”!""""""""""""""!!!!!!!!!!!!""!•••••qxŽŽŽŽ‘“”!"""""""""""""!!!!!!!!!!!!!""!••••••qxŽŽŽ‘’”!""""""""""""!!!!!!!!!!!!!"""!••••–•qxŽŽŽŽ‘’” """"""""""""""!!!!!!!!!!""""! ••••••qxŽŽŽ‘’“ !"""!!!"""""""""""!!!!!!"""! ”•”••••qxŽŽŽ‘’“ !!!!!!""""""""""""""! ”•”•••••qxŽŽŽŽ’’ !!!!!!!!""""! ”•”•”••••qxŽŽŽ’“ !! ”””””•••••qxŽŽŽŽ““ “””•”•”•”••qxŽŽŽ““  ”””””•”•••••qxŽŽŽŽ‘“““””•! ÑÑ “”“””•”•”•”••qxŽŽŽ‘’’’““•–••——"!  “””””””””•••••qxŽŽŽŽŽ’’““““””” !!##"! “”“”“””•”•”•”••qxŽŽŽŽŽŽŽ’’“ !"""""! “““”“””””””•”•••qxŽŽŽŽŽŽŽŽ !"""!!!!! ““”“”“””””•”•”••qxŽŽŽŽŽŽŽŽ‘  !”“““““””””””””•••••qxŽŽŽŽŽŽŽ‘“““”“”“”“””•”•”•”••qxŽŽŽŽŽŽŽŽ‘’’“•“““““““””””””””•••qxŽŽŽŽŽŽŽŽ‘‘’““””•••““““”“”“”“””•”•”•”qxŽŽŽŽŽŽŽŽ‘“’’’“”””””•••••••““““““”“””””””•”•••qxŽŽŽŽŽŽŽ‘‘’’’’“““””””•••••••••”••••“’““““““”“””””””•”••qxŽŽŽŽŽŽŽŽŽ‘‘’’’“““““””””•”•••””””’’’““““““““””””””””•••qxŽŽŽŽŽŽŽŽ’’’’’’’’““““““““‘’’“’“’“’““”“”“”“””•”•”•”qxŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘‘‘‘’‘’’’’’’“’““““““”“””””””•”•qxŽŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘’‘’’’’’’“’““““““”“”“””””•”•”qxŽŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘‘’’’’’’’’“’““““““”“””””””•”•qxŽŽŽŽŽŽŽ‘‘‘‘‘’‘’‘’‘’’“’“’“’““”“”“”“””•”•”•”qxqqqqqqqqqpqpqnpnqpqqpqopppppppqqqqqpqqqqqqqqqqppqppqqqqqqqqqqqqtAAzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxzx‘‘‘‘’‘’‘’‘’’’’’’“’“’“’““”“”“”“””””•”•”••••••–•–•–•––––––––––qx‘‘‘‘‘‘‘‘‘’’’’’’’’“’““““““““”“””””””””••••••••–•–––––––––––––qx‘‘‘‘‘’‘’‘’‘’’’’“’“’“’““““”“”“”“””•”•”•”••••–•–•–•––––––––––qx‘‘‘‘‘‘‘‘‘‘’’’’’’’’““““““““”“”“””””””””••••••••–––––––––––––qx‘‘‘‘‘‘’‘’‘’‘’’’’“’“’“’““““”“”“”“””•”•”•”••–•–•–•––––––––––qx‘‘‘‘‘‘‘‘‘‘’‘’’’’’’’’““““““““”“””””””””•”••••••••–––––––––––qx‘‘‘‘‘‘‘’‘’‘’‘’’“’“’“’““““”“”“”“””””•”•”•”••–•–•–•––––––––qx‘‘‘‘‘‘‘‘’‘’‘’’’’’’’’““““““““””””””””•”•”••••••–•–––––––––qx‘‘‘‘‘‘‘‘‘’‘’‘’‘’’“’“’“’““”“”“”“””””””•”•”•”••–•–•–•––––––qx‘‘‘‘‘‘‘‘’‘’’’’’’’’“’““““““““””””””””•”••••••–•–––––––––qx‘‘‘‘‘‘‘’‘’‘’‘’’’’“’99999999999999””•”•”••••–•–•–•––––––qx‘‘‘‘‘‘‘‘’’’’’’’’9**************9””””••••••••–––––––––qx‘‘‘‘‘’‘’‘’‘’’’’9(((((((((((( ((*9•”•”•”••–•–•–•––––––qx‘‘‘‘‘‘‘‘‘’’’’9-(((((((((((%((%*9”””•”••••••–•–––––––qx‘‘‘‘‘’‘’‘’‘99-((((((((((%(((&*9””•”•”•”••–•–•–•––––qx‘‘‘‘‘‘‘‘‘‘949-())))))))%)))(&*9”””•”•”••••–•–•–––––qx‘‘‘‘‘’‘—949-(888()888))888&*9””””•”••••••–•–•–•––qx‘‘‘‘‘‘‘“—949-( 8/( 8,), 8,%*9”””””••••••••–•–––––qx‘‘‘‘‘’“—949-() 8,( 8,( 8,(&*9””•”•”•”••••–•–•––––qx‘‘‘‘‘‘•—949-(()8,,(8+,,8,(&*9”””””””••••••••–––––qx‘‘‘‘‘‘”—949-((( 8,8 8,8,))%*9”“””•”•”•”••–•–•–•––qx‘‘‘‘‘”—949-((( 8 8 8 8,)(%*9”””””””•”••••••–•–––qx‘‘‘‘•—949-((%(88,, 88,((%*9”“””•”•”•”••••–•–•––qx‘‘‘‘”—949-( (( 8,( 8,(((&*9”””””””••••••••–•–––qx‘‘‘•—949-((((( ((( (((( *9”“””•”•”•”••••••–•––qxŽ‘‘‘–—949-(((((((())((((&*9“””””””””••••••••–––qx‘‘‘“—949-(((((((((((((((*9”“”“””•”•”•”••–•–•–•qxŽŽ‘‘–—94900000000000000009”“”“””””””•”••••••••–qxŽŽ9999999999999994999999999999999999“”“99999999999999–•–•qxŽŽ9**************099/***************“““9**************9–•–qxŽŽ9((((((((((((((%*59-(((((((((((((((*“9((((((((((((((%*9–•qxŽŽ9-(((((())((((( %*09-((((),,,,,,((((%9-((((,,,,,,,(((&*9•–qxŽŽ99-(((((( 8+((( %&*09-((()8888888,(((&9-(((8888888(,((&*9–•qxŽŽ949-((((() 8+((%%(&*09-(()8, )8)((&9-((( 8,)) 8)((&*9•–qxŽŽ“949-(((() 8,8+%(((&*09-(()8,((((()8)((&9-((( 8,(()) 8((%*9–•qxŽ“”949-(((() 8)8+((((%*09-(( 8,((((((((((%9-((('8,((() 8,(&*9•–qxŽ‘”949-((((+8,+(8((((&*09-(( 8),,,,,,((((&9-((('8,(((((8,(&*9••qxŽ““949-(((+ 8,()8+(((&*09-((''88888888,((&9-((('8,(((('8,(%*9••qxŽ“”949-(%(+8888888(((%*09-(((( (8,((%9-((('8,(((('8,(%*9–•qxŽ’”949-%() 8, 8+((%*09-(())((((((+8,((%9-(( '8,(((((8)(%*9••qxŽ‘“949-())8,(())) 8((%*09-(()88,,,,,+8,((%9-( ('8,,,,,8))(&*9••qx“”949-()888+((((888(&*09-(( 8888888)(((&9- %(8888888())( *9••qxŽ“”949-) ()) ) *09-((( (((( 9-%(( (())&*9••qx””949-())(()))))))))&*09-(((((((((((((((&9-((((((((((((()(*9••qxŽ””949-(((((((((((((((*09-(((((((((((((((*9-(((((((((((((((*9••qx““949000000000000000014900000000000000009900000000000000009•••qxŽ””94999999999999999999499999999999999999999999999999999999•”••qx“”•944444444444444444994444444444444444494444444444444449•••••qxŽ“””•99999999999999999••9999999999999999——999999999999999•”•”••qxŽ“”•”••••••••••••••••••––—–—––—–—–——————————————————————”•”•••qxŽŽ””””•””••••”•••••””–••”•–”””••••••”••–•––••—–•——•————”•”•”••qxŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘‘’’’’’’’’““”“““““””””””””•••••qxŽŽŽŽŽŽŽ‘‘‘‘‘’‘’‘’‘’’“’“’“’““”“”“”“””•”•”•”••qxŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘’‘’’’’’’’’““““““““””””””””•••qxŽŽŽŽŽŽŽŽ‘‘‘‘‘‘’‘’‘’’’’“’“’““““”“”“”“””•”•”•”qxŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘’‘’’’’’’“’““““““”“””””””•”•••qxŽŽŽŽŽŽŽ‘‘‘‘‘‘’‘’‘’’’’’’“’““““““”“””””””•”••qxŽŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘‘’’’’’’’’““““““““””””””””•••qxŽŽŽŽŽŽŽŽ‘‘‘‘‘’‘’‘’‘’’“’“’“’““”“”“”“””•”•”•”qxŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘’‘’’’’’’“’““““““”“””””””•”•qxŽŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘’‘’’’’’’“’““““““”“”“””””•”•”qxŽŽŽŽŽŽŽŽŽ‘‘‘‘‘‘‘‘’’’’’’’’“’““““““”“””””””•”•qxŽŽŽŽŽŽŽ‘‘‘‘‘’‘’‘’‘’’“’“’“’““”“”“”“””•”•”•”qxqqqqqqqqqpqpqnpnqpqqpqopppppppqqqqqpqqqqqqqqqqppqppqqqqqqqqqqqqt/+--,-,+,,+,))2/7996+0./^^_^2âãxzã\]4)))'-+,,,-.,-,,,+0-2äxã9667^å^_]^ååá\/ä]]äã-,))'))+-,,.*-ÈÈÊÈã}}àãã860548åä^^^/4ä\\\0}àä244)+)).,.ÈÉÊÊÊ)x}äãâ8.55864]^^^ã44â\[1/â{àß}2,2ÇÊÉÊÊÉãäy2xá1904/5664]\][__]6-áääâY\[Y\[-1ÇÉÊÉÉÊyã}{xàã7//2864/][XY^[åa`ââ}ââ[[\22nÈÈÈÊÊ4äãàxâàä164469842^XYY[^acå74ã]\0)2ÇÈÇÉÉË/yããàxââá1022878444XY[[[a]`^8888ó-2ÇÊÆÆÉÊÉäãäãààââá745/4788259,[[]][]^]^`^2)1ÈÈmÉÉÉ4ää4}àââââ662466842269[^]XY\^^\_)1ÇÇm+É,Ê-ã3ààààâáâ061102552556\XYYXY['0ÆmÇËÉÉ,äãäâààßâã286126855/065782[[]Y[)0nnÇÉÉÉ+2ã6ßààààâãäã05/062400527561^]Yó)/ÆmÇÊÇÉ,4ãyãàààßàâää0564.24/5144787444ó.nÆÆÈÇÉÉ+ãâââßàáâãäã6/444/660./22246óó'.ÇÆÆÈÉÊÊ/äáâàààâßâáäã50/.247420/6761óÇ-nnÆÇÊÉ-+/ãäáààààßßäää655/12744-/0565Ç/ÇnnÊÊÉ'/,ãäyßààáßáããä!:640//4545244óÈ0+nÆÇÇÇ)È-äãâxäâââãßáâä!<54242501.42óÇ/nÆ.ÈÈÈ),4åäã444 "!00É2224!'''))+,,,*,40)Ê**)))!!dd!!g!eg!!dgcþþ43:ýÿþ6ghg6:ýýýÿþgid_i6!664ýýýýýýgcfae_f9446g!eigc!if64gbhbiiýýý¢¤ª©©d¥_««¤b«!¦!¨..¦32d2:4:§©dd_d^_dae]d-,*,,*--«eddd_^1dad222332¨«e!^^ebb8:g!¨!eedd]9«eed^^h£gc!¦!]¦£¥!b£gc_þ!!gdagþþþ!ie4þdÿþþþþþþ2ÿþÿg7771171//-ýÿÿÿg74737e67474e7252i8.ýýýÿ3ýg.5;f:ifeefgefdf>>>>#>##>###>"#>####>>#=#>==<=:;=<:;<=;;:<=;;=><;:=<=>>>#!;;:;887::8999>><:9;=<;=>>#==>><<;><<><<>=>>=#!#>>>">>>>>"<>#>"=><=>">=>#=>=9ÅÅ<<">#>>#<>>"<6ÐÓÑÕ>#"><==>>>>>>=<<>;==="#"<#=>>##>=>>">>#==>=><==>>#>>>><>>#>>=##>9ÑÏÐÐÒÓÓ;:#<#;##<-uutÏÏÕÕ;=;:;>>>!!#>">#""###9!"=>#=>>>==;==;;=:<>:>>>##>#<>;<=>:;:;:82xÊvuÏÐÐÐ;:#>#;>=0upÈÈÊÌÑÂ<><>><>=""><==>>===9z8<=<<>=#=="####>##>8z>#>#>>>>">>>>=>=>=5ÓÌxËÊÌyz3;>>#:>#~ÉqnoÉxÐ34>>=>=;>;<=>>;>>=<=<Õ698;<><><;;==;<;<;<:Õ#>>=>><=><=<>=>=#>>9ÔxËËpxÍz>=#=#<#=ztpomÈÊÑ{;9<976712ÑÒ64ÐÏÑ6ÔxxxuvÐ:;><9><<78:>;‚795Õ::=‚;‚Ô39;=>:=<=92Õ7ÑxËtqtÏy4‚9>#‚#>1ÊooÆpuxÓ#ÔxÏxxÏvux6Ñxxvxvtuuutt6‚wvÏÌxuxÏÍÏÒÏzÒÐ7><=ÕÓyÏÒ0‚;>"==<3ÔÑ:ÓÌvqotËÒ;7###:=>ÉpÆnÈÉx|:ÔÑËvwxttuvttuvuvtttuut{ÑtsttuttxÏÐÍÑÏz|572ÓÒ|Ðy{}9=>=>=8833ÒvÊqoqÊz9<#>";#=7tqmmptxy:<ÑÐÊÊuuuttqttuxtvpssqsqttprrsqqtutuvxÐÍÒÓÐy/33}ÒÒyz‚;:9510ÐÔ6ÑÊtprpuÑ=>>>#;>#9vooontx|~<ÑvutqttuuÈorptttqquqprqpqpqtqoopqttvtvÐvxÏÑy0ÑwxÒz{Ñz0~|ÑÍÑ1wqppppv{7"= !=>>;unooÆvxz>yÊutsqsxvopqrrqqrqppoqpuxytvvvtvuxutttvxtvuÐxÏvvvyyyÑxÑxvÐÒ}ytpqpquz>;> ";#=upnÆÇÉxy>=ÐtttqsrspppoqpqppprpptyvvsttrrqsrqtuustustvuvxxuvuwÐÏÑxÌxuÏ6zprqrqvx"<###‚‚;;ËonmÈÊÑ6"Ìtstqrrrqqqopptppnotw|xuutvspqrqoqqptxvuutttuvttvvxxÍÑÐÏuvxÕvpopqstx==#>‚>>;ypnnÇÊw568xttrqpprropqqortppw{{ywtvrsqrprqÈopppqpÏtttvuqqttutuÐÏxÐvuxÓwtpqppuy79:=#=#<€vpopÉÉv~6<Êttpqqpqonopqqpptx{yvtsrsqppqpqÈppÇÈqpttuttqsuuttuxxÑÐxxÐ;xuppqtuy>>>>#;><ÊqnnÈty5;8vtÈqqorppqpqqppvy:|~xttrrrqqprpprtpqÈÈopqtutttqqstuvvÑy{ÐÍÒ2ytoopsux#>#"###=ynomÉtvz>=tÈnpqoqopppopqv|9|xvttrrsrroqrpqppÈpsqpoppvvuvssrpttvÐ|zyÐÒ3|upqrpÉz""#"##"=xonnÉuw}>9ÉoÇnqqpstqpqnt|9=yvuttrrrrqqÈÈÈqprqÉqppÈqptxvttqqsqtuvxwÏÏÑ0ytqoqpux:>#"#>>==ynpÆpuÑ{"=ÉoÈÈÈÉopppopt|>>{stvrsrprrqqppqprsqoqpppqptxxttqpqttttxxxÏÔytqqostz<#>"<=><1Ènmptw|=3ÉÈoÈÈÉpnqopqx€=<>=|tsssprrpprppqqqrqqÈpopÈppquttqprssuvtxuvÏ|topprty7<=>#;>=>2ÈÈnppw~75ÉÉÈÈÈptpppqt|‚=><>ÕtrssrossrqppqÈsprorrqtqpopttsqssrrsvttutxzurpqpv|7#>>"=<<;~tnpÇuw~"6ttÈÈtqpppptÒ€<=;>:ÐtsrtpoppqpppqroqortqruuutÈvxpstpssuqqqrtÏyuoqpqv~>;<##>>>>2ÉpnÈtx}"6ÊÈptÉpoqqtu~9>><#<=#>2tpnÈtw|>;;xvtssspqqrrsuttrrropttЀ€ÐsxÏuxqpsqqpqstsxÑÓtportt8>>#>>‚;"0nonÇÉw78:tqtÉÉÈÈpnuÑ7>=<><;xttssrrrstrvxuvvprpurx;<|rÏÑuusqprprqtrswÒÒpoppru};‚<=#>"<<}pnpptzz"1ÉqÈqtÈpppy=;=;=;=zutrrsrsqutvtvtuspqstrx7;ttxÐtqpppqrsqstw/xtqrpst<=<>#>>=>‚Éonpuyz"~toqptÈÈÈÇy7;><=;>>|tturrsquutszÒvvtprrtrrwysxsroorqqsrttvÓ}pqqnou‚>>##">;;#4ÉnoÇvv{7|ÈnpptÈpqny:><;>>>;wuvurrrutsy;>}tvrqqtvtz~yus|{xopqrpqsquu5Òtrqnqv3=">#"#"##~ÈnopÉw|"5npoÈtttqp}:<==<>;<=;{xtsssutx|<9{uurrutssz:~ux|;zoppossrrtt~zpqqoqu###!###>ÊopÈtyz>~ppÈpuvtoq{<=><;<>;=;xtuusvtuv}~sttuttsuy{=;~};>">###7tnÆptvy7}sqpqtturpz<=;<:;=<<>yzvutvutts{€xwzwusuz}:;<=;<=zoropuqpuspÐ{uqpqsu9;>>=#>>>;~pmnÈÉt}9:pÈÉqtuttÈÔ;<;<<=;>=>xuuxt{t{||7:;:yutsx<<=;:9<<;{pqqpttqtqrxxtqpopÊ:6‚<<#=:<<pnÆÉÉx{>2Éqtptuqoqx9<<;;=<=;;ztttvx|‚7===<;7xttÏ|;==;<>;xqqottqtqspÐ|vppqsÊ"=;=";<;<1pmnntu|<}qppttqtpoy><>;;;;><{yxtty9;>;;<;;=zstux9;;‚;;‚~xqqptptqqptxzuqqpqv7=##>#=>=;|ÆmÆÈpwz:4ttqpqspppw€:;<>:;><;;€ytt9<=><;‚=;<‚~yxxÔ<;<<<;yvrqqpqttpsu{zvpoqsv<:>>#>;#>;}nmnÇtxz>Õtqqqrqprptx7><;==;;><=yz=<;>;<<>><;=:;;:;‚=<‚ÐoqssspÉutqÉÒÒupqqqu4:::>#=>#;zpnoptu|<3tpsqoqpopqx<;<=<>>;><<:;>>;=<>==;><<=><<‚<;9}vqqssqtptuqu|}uppqqu~>=‚:#>;::ynnomtv=2tqsqoqpnpqt{<=;><=;;=<;=<<:;=<;;<;<;><=;;;:<‚:Òprsqpqspttuw;5tqooqw}>>>>#>=>;zpnnÇÉy€<7tqrponpoppox7<<=<=<==;>;;;;;;:=>=;>;><;;;:=;‚}Ðsqrttpqptuux1yuoqrpu}:;<>>##<<;<<;=>=;><<=<><=<=;>;;;;==<‚ÑtqsptttttuuxyÔyuoqoqt8<>#>="##>:=<;;>==;<<<><=>>;:=;<~ÏsqqstttqtvvvÏ|Òvoppsu1"">>"####wronmÉw{<;uqrpqoopnooqtx=>=<>;<=<;><=<<<>=<<;=;<:<=;ÕwpqpststtttvuuÐÔyupqost{;"###>>>;xonoÈtx>;xtÈqpqqoÆpporuÑ‚<;>=;;>;=>==<>><>;=;>>;=>;;Ñqoprpsrqtsstvvx|zuspopt|;#>>>>=<6wppppÉy€=;ËÉppqpoqqqnqpsuÒ:;>>>;>>=;;;;<<<>><>>=><<:ztooppprpqsqqtvuwÑÒuqqpstx9:<=#>>=;Êppottx{7=ËÈpoontqnqprquqvЀ‚===;><>;>=;>==;>=<=;;‚ÑtpqqqqqrrppsqttvwÔÒupportx<<;>#>><5wooqttx>8xpÈopoppppqqtturvÏ~7:>>;>=<<>>>;>=<"">7}utqrrrpqqrqrprssvtÏÓ|vrpprt|7"=>#>>#‚uqppttxx79uÈppoqqoopspttqtptÐÑ;‚<;<;><>;>><<==;:{wrprrrrpsttrqquqsrtÐ6xupppqux>‚;9>:>:~Êpopttv|<;uÈpqopqppprtqtutttxuxÔ};9>=<<=<>>>:~{ÒÐupqsqsqrqtrsstvtsquÏÃÑËÊpnpuw6<>;#>#>7wppptÊxy~"vproqoqppoqtuxxtÍtvutvÐxÓÀÔ{ÕÓ~ÒÐÐÐxuqtvvurtqprrtqstrttrtvxÓyÊtpprÉ|4=;<"=>#vqpppÊz|<9xutopspqputtvw{uvvvvuÊvtuxutttttuxvtropppqsprsqssqvsqrrqtuÓ7xuÉoopÊx9;:=#>=>5tqoqtÊx{==ÐuxtvuttttxuÐ;;ÐvxxvuÎxxuuxxtutuÍvuussqpttttqqtxxttsstsuvxÒ:xutppsÉ{3#>##>#"3ÉqpoÉxz5;#/ÑÐwÐÏxÏËvËÌÒ==ÏÌÐÍÏÏÏÌÍÏxxvÎvxxvvvvvxvxtxtuuvÏwÏÐvuvuxvuv5xvooosÉx:###"##6ËÉoÈÉxÓ1">Õ/xÏÐzzÑÑÔ9;3"=ÓÏÏÍÏvuxÏxxvuuvÌxÏxÏÏ3:ÏÌxtuxxÍÑÒÑxÐÏÏxxxwÐ~2|utqnrtw>>"##>=4xÊÇÉÊÐ|:=<75Ô4<96:=:;<><>"8=;661Ô695ÐÏÑ2ÓÒ-ÐÒ1;90ÐÐÏvvÏÓ295ÑÐxyÒyÒy3";yËÉqooÉx~:###=:>3xË(ËÊÏÒ59"="<">;><;<>;<>>>>> >>#>>>=#<=>>>==<#>>=;<;€ÑÔ7;9;84Õ‚57:::76ÓwvÉpqtw{Õ;9=>>>zxÊÉËÍÐÐ5">>>>=<==7=">=>>=>>>><===:;<‚:9<:;:<<;;:;>>#>;>=:;;;<‚;;>"><=60xvÊÉÉtxÓ4>>>"#>4yuÊÌÑxÑÔ==>><><=9|9‚<;<<>>=>==#>>><>"#>####>">>##>#>><"Õ{:###>>>>#>";;yÏÍÊËÊxÏÔ;>>>>#<=<ÔÑÂ2ÓÃ6;>:;;<;<<€<#>>><>;=;;=<=>>==<>><>#>>=><=>=<>>#>>9:;<>;>;#>##==‚ÔyxÏxÏÓ;><#>::<=<87ÓÑ2:>##=>=>>==;=<;<;=:;<<=<<><<==><;:<‚:9;8::::>=;;>=#>><:=;=;<;=;##7ÓÕ1ÒÒ:<>><>>>=<<:78775266999:999967766677454424422222220222246:9;;;>;=>>>>>9;955;>;9:>#>>#:8:87:89897686685676774645774666554646544356224667<<>>>>>=="#>#>>>=>##>#####>=>=>>>"<==<<><<><<;<<<=:<::98888:::::7::79::79;;"###"#####"############"######"###"#########"#####"###"#"######"#######>""#"###########"####""#"#"####"#">"m“M!"!!####><<##>"864558##>967‚>"####<;<=<=<;>#>=>=>;>"##"#‚>;##=#>###;#>#>####"##4>:Õ>=>>>#>>>=9=#>##>>=Ô>Õz5‚#;>##<<ÕzÕ;>"##7<;;Ô>:#9"#"#;:Ô<==###>‚;;=#<<;<###=:>>#;;"###"#5#:>><#;<"##><#<<=;####>€=;>=>==>#>##;#:":=##""<9#>#9>#<>####:<<>;<=>""#9;#<>9>>;###>">>>:==<###=#6><>;;=>#"#"###>>:=>=>##>=9>;>;>>=>####""=>;;>>>>#"!‚>==<=#=>#"#"##=>><;=>###>6;<<#<<#:>#####"#:#>=#:=#"8>;>><<><#"##>"#;==;>=>"##9;>;=;>#‚####"###;>#:>=:###=7><:<;">9#""###"<:>;">:###":9>>:<:>#9#"#>">##":><>=‚>##":7=<>>;=>9########":>":>;>##>€‚>=>><::>"#####>"#;>>;><>#">5;>=<#;=;##"####>#"><=>>><###;5;>>#>;>">##>###"#"";=;>#=###:6<;;>#<=######"##>#<##>#>>## ‚‚">>>#""###"#">##"#>>##=#>"#"!9!#=< >;;;=>>"######>"#######">>####"#>#>###>>#>#!;9"##"""###"##;!<:‚9998:554699867:;<=:;>>>>>#>##>###>"#>####>>#=#>==<=:;==;;<>;<;<=;;=><;:=<=>>>#""<<;=;=;<=;;<;>><:9;=<;>>>#==>><<;><<><<>=>>=#!#>>>">>>>>"<>#>"=><=>">=>#=>><>>>=#>#>><=">#>=;=;>>#"><==>>>>>>=<<>;==="#"<#=>>##>=>>">>#==>=><==>>#>>>><>>#>>=###=‚9‚:<<:;:#<#7;##>65539>=<><<<>>>!!#>">#""###9!"=>#=>>>==;==;;=:<>:>>>##>#<>;<=>:;:;:::84€59:::>=#>#9;>=7|{157;>#><>#<>=""><==>>===9z8<=<<>=#=="####>##>8z>#>#>>>>">>>>=>=>><=75469;<"#>#7:>#;3|yz3;=>#>="=;>;<=>><>>>=>=9:<;=>><><;;==;<;<;<:Õ#>>=>><=><=<>=>=#>>==865|88;#"#=8<#>7~|zx1~;<#==;<;<99:::898‚<;6Ô€4Ô9<<><;>=>;<=><<;=;;=;=:<;;9<=>>:=<><:<<;96~|~99==9>#5‚#>9~{zy|9=>#>9‚9756;9€€7Ô~55~}~9;5685€5778<9;<;>>>">=99<;>"""!!"<>;"=7€}z}7<#;###Õ:=>;|{xy13<"">;6€7~}~~}7}}}~Ò79~ÒÓ~ÓÓ379‚8;‚;<=<><=<<:9;=>"""##>>==<73zy|5;">#>"6;#=;}|yx{9‚"#<:44}}3}}7~{}Ò|}Ñ||{||Ò{Ñ}5~6‚7<=:9;====<9;>>>"=<;:>>;~~y{|<##>>#";;>#<{zzz<>#;75}}~|}}{{Ò{~~}{Ñ}{z|{z|z|~{yz{|}~€~6‚7‚;:;;78<;;<;;=<;7;<}|yy|7;"#>;""==>>=zzzz6;"#:4}Ò{|~}z{{||{|||zzy{{‚~€€~€€~}~Õ~Ô5‚9‚€79:9<9;86‚<=‚{zy|;#<> >"<;#=‚|yy049:##:}}~|}||zz{z{z|{yz|{{}‚7€}~||{|||}}}5}~Ô67Õ~7:9;8679>;}|z{|79#<### #‚‚‚;=}{zx{};>"#7~}~{Ñ||{{{yz{}{yxz}<9~€}z{{{{|||Ò€~}}55~~ÔÔÕ7;:95Ô>7|zy{}9#>#>!"5‚>>=7|zy04>>"7~}}|zz|{yzz{y|}z|;;;~€|}{|{|{0{{Ñ|||9}~}Ô||}~~~:99:€9={zz|9"‚:=#":6=#<:|{z|37=!#5}}ÑÑ{z{yyzz{{{{~9><;;€~}|}{{{{{|1{|01|{Ó~~}|}~~}~8;:78:"9{z{~€;#>>>#86;><‚4|yx1~‚=">6}1||z|{z{z{{{{€:>:=~~|||{|{|z{|Ò{|21{{|}}}}ÑÑ}~6;:<:8<<:zyz}9>#>#":7###>7zzy3~7;##~{z||z|yzzzzz{€<=<9€~~{||{|z{|z|{{1|Ò|{zÑ|~ÒÒ|{~}:<;::<=<{z{|};#"#"#:#">zyy|=#"3{zz||{}Ò|{{y<=>;€~}{|{{{|{{{|{|||{{{{||}€6~~}{Ò{}5ÔÕ798;;‚~|y{{9">#"#:>>=>€z{y|;;##3{{11|{|{{z{}<<>>‚}€|}Ñz{|{|{||z{Ò|z|||{|{}€€~}|{Ñ}}~4789>‚~{zz};><#>";7<=><7{zy|}<#=2{{{1||z{z{|=><>=;|||z|{zz|{{||{|{Ñ{{z|z{||~}|zÑÒÒ~Ô4869<{y{}~‚><=>##5;>=>7{{x||=">2|1{||}{z{|~;<=><><~|Ò||zÒÒ|{{{{0}{|{||{}||{|}}Ò|ÒÒÑ|}ÔÓ~~9;|y{{7<>#>>"94=<<;9|yz0=#>~~|0Ò|{Ñ|{}<<<=;>>:~}{ÒÑ{{z{zzz{|{|z|~{ÑÓ~~}{Ô{}~{Ò}Ó|{ÑÑÓ9‚€{zz|7=#;<###74>>>>7|{y1~9=#>41Ñ}|{z|Ò}<;>><=9€~ÒÒ{{{z{{|~{Ò||1{~}}~€€Ô~:{}{{|{{|Ñ|Ó;:~{z{|€<><<>##9Ô<=#>7|{z1~<##||100{|z|‚===>;;9~}ÒÒÐÑ{|ÑÒÓ}~}||{Ñ~~:;=:Ò9Ñ{||{z{Ò}Ò9;=~{x|~>=>>#"7Ó>‚;"7zzy03>"#~Ò}2310{z:;>=<><=9~~}ÒÑ|{|}|€z|{|=<‚|9;}{{{{{{~|Ò7<=}zyz}7="‚<=#7Ó>"<<{yz|~;;#<||{|ÒÑ|{{9;>;=;=;=‚~||||Ò|~€~€~}z{|~|‚=}}~|zzz{|ÒÑ}}7;9|z{}>"=<>#;5>>=>;1zx|‚;#>}z|{}0{Ñz::<><=;>>;}|{||~}:;€€~y{|~||‚‚}9}|yy{{|}|~}7==||zy{7"#>###78>;;#91zx077<"<{z{|}1{Òz:<><;>>>;‚€||{~}‚<>‚~|zz~€~;;9}9yz{|{{Ò|~5=<}|zz|="">##"#"##9{yy|3<#>zzz{}}}|{=;<==<>;<==;€}}}~<>‚‚€||}};>;;=;{{{z}|||~}=;}|zz|>#####6<###>1zy{‚;#={{ÐÑ~Ô}{|<<=><;<>;=;<}€~<‚|~~}::>;;<><;{|{z~|||}};<~{zy|#>#>>##"79>###:}zx|7;"=}|Ñ|~4Ó|{;<=;<:;=<<>9;€€~~};;9;7}€;;;;<=;<=;z|z|~|{~}{:;|y{}€">>>=#=7Õ>>>;‚{yz|}=""3{||}~}Òz><=;<<=;>=>9€~;~<<;9:>>97~}><=;:9<<=;z||{~}|~{}9}yy|":‚<<##‚7=:<<:{yy2}9;#<23}{}|{|9;<<;;=<=;=;~€9;=:===<;;9~‚‚;==;<>;={|{}~3~|Ò|:<7|y{}>#=;="67;<;<6{xyz~<#=}|ÑÒ}|ÒÑz:;><>;;;;><;:99;;>;;<;;=9}~=;;‚;;;;7||{}|~}|{}9;6}zz|7>"##>##67=>=<9yxx1|;"=4}|{ÑÒÑÑ{<<;<>:;><;<=‚~~=<=><;‚=;<‚‚7€;<;<<<=9€|{|{|}~|};;7|xz}7#>>>#>#5‚;#>;zxy0~9;#>}||{|{ÑÒÑ~;><;==;;><=<;;;=<;>;<<>><;=:;;:;‚=<=:{|Ò}}|1~|3<<|z{|7!<::>#Ô9=>#;7|yy|~<#=}ÑÒ|zÑÑÐ{|=<;<=<>>;><<<<;>>;=<>==;><<=><<‚<;‚;€{ÑÒ}|}|~|<={y{|=>=‚:#8;>;:;€zzy/~7>#<~{Ò|z{{yz{~;>=;><=;;=<;=<<:;=<;;<;<;><=;;;:<‚<<||}|{|}|~}#=~|yz|=#>>>#7<>=>=7|yy0}‚>#>}ÑÒÑzyzyz{{<=<=<=<==;>;;;;;;:=>=;>;><;;;:=;:;:Ò{|}~{||~59<:zz||<=;<>>#€;##<=~zyy12>""3ÒÒÑ{zyÐÐzy=<=><;<<;=>=;><<=<><=<=;>;;;;==<=;}Ñ|{~}~}}~~‚>:{zz|>>>#>=>6#"##=7{yz/27<""Õ|ÒÑ{zyyyyyz7>>;=<;;>>:=<;;>==;<<<><=>>;:=;>=9ÒÑ{Ò~~}|}77‚<<7{y{}<#">>"# 6####~|zz0~;#"5||{{zy{yzz{~9<>>=<>;<=<;><=<<<>=<<;=;<:<=<={Ñ{}}Ò~~~}€5:>:|zz};""####"6>>>><{yy1}9>##ÒÐÑz{{zy{zy|;>=;>=;;>;=>==<>><>;=;>>;=><>;|yy{zÒ|{}}}}€9<;}xz{~<"#>>>>"5=>=<9|zz}}‚>#"51{{{zz{{{yz{Ò<><>>>;>>=;;;;<<<>><>>=><=>;~yxyzyÑz{|||~Ô7<=|zz}~9>:<=##"5‚>>=>~{zz}~9;!#5Ñ{zzyÒ|y{{|ÑÓÒ6:<<===;><>;>=;>==;>=<=;=>;~z{zz{{||zÑ}|~~68><{zz|~9#<;>#"!5:>><96{y{}‚>#"8|zzzzz{{{Ñ|ÒÒÓÒÔ‚<;;>>;>=<<>>>;>=<"">;<7~z{{|z{||{{{}}}~9=<7|y{}}<>"=>##"4<>>#<~|zz~~9""{zzy{{yzÑÒÑ}~Ñ}{~‚;>==;<;><>;>><<=>>>;7|z{ÑÑ{y}}~|{||Ò}}:>96|y{|#‚;9>#"4<:>:83|yz}~7<##6Ñ{{yz{z{{ÑÒ}}~~3ÓÔ7=;><>><<=="##><;<:{{|{Ò{{{Ò|ÒÒ~~}|59>;63yy{7!<>;#> 5<>#>;€|{{}~9;!#6||z{z{{{zÑÒ~€€4Ô4ÔÓ~‚9=>>;>==<;:;|~6€~|}Ñz||Ò|Ò~|~}|~68=‚~~z{|3<==;<"#!5:=>#<|z{|5;<#"8~Ò{ÑÒ{||}}68566Ô553545Ô5~ÒÓ}}~ÔÔ~|zz{{|Ò{ÑÒ|Ò}|5}Ñ{{{~6=>93yz{~9";:=#>#6<>=>;~|y|~59;##;5€~~43}~9=<‚78Õ65Ô€Õ567Ô}Ó4ÓÔÔ55ÒÒÑ|ÒÓ~Ò||}€~~ÒÒÓ}Ó5€<"9}y{}2<=#>####6>>#"93|y{3;>##;;;7:9896766;=>86:7899679776€5€Õ666€57Õ4Ô455Ô79:€56657>>97{y{}}9"####"7‚###<53y{38=<##>;89;;;<;=>>;#><89775Õ877655Ô689789=86€35787;<;9:9‚9987;><<}|z}~>#>"###Õ##>=:84034;<"#=<<<:>==>><=>"=>";>=;;9<:;:97::;:88:9=;9‚Õ8Ô69=;><;‚79<‚<‚;##‚63|z{3<>####"‚€<=:>:85265‚=>!"="!"><><;<>;<>>>>> >>#>>>=#==>>>=>=#>>=;<;;7;;=‚;:9<=<<;<<:>=6|z|7;<;9=#<;€:>>>985357:;=#">>"=<==7=">=>>=>>>><===:;<‚:9<:;:<<;;:;>>#>;>=:;;;<‚;;>"><>>;97422=‚>>>#"<7<"#>:546;9;>#>>">><=9|9‚<;<<>>=>==#>>><>"#>####>">>##>#>><"Õ{:###>>>>#>"="‚9755479>>>>>";‚<>#<===;><=><;><<;<;<<€<#>>><>;=;;=<=>>==<>><>#>>=><=>=<>>#>>9:;<>;>;#>##>>==98989<>><#>##;::::<=<;=<;;>>##=>=>>==;=<;<;=:;<<=<<><<==><;:<‚:9;8::::>=;;>=#>><:=;=;<;=;##<<>;<<=<>><>#;#:>>>=<<:79‚76687999:999967766677454424422222220222246:9;;;>;=>>>>>=>;:;;>;9:>#>"7>#>>#:8:87:89897686685676774645774666554646544356224667<<>>>>>=="#>#>>>=>##>#=:>#####>=>=>>>"<==<<><<><<;<<<=:<::98888:::::7::79::79;;"###"#####"#########"=:####"######"###"#########"#####"###"#"######"#######>""#"###########"####""#"#"####"#">##;;Õ9<=<>><;<:=;>;=<;<<<<:;9:>;;;<;<>=>=><‚:==;=<;>>;:=:=:=:;;=;;<;::==‚<=;<;<<:<;<;;=‚9=<=><##€8>>=<=;=>><=>=#>===>>=>#=#>#>##>#>=#>##"<==<<=>>>#=>#>>>=>=>>=>=>#=>#=>=><>>>>>=>>>#>#>=#"#Õ€><;==>;<<><=;;=;>==;<><<=>>>=;>=;>>><===>;><<;;#<‚9‚‚:9;<=<<>=<>";<><=;:=<=;;==>;=<<==>>#"677#>>#>>>>>#>##>>>=="=>>">="=>###>>=>>##>#######>>#>>">>>##>>>#>##>#>>>>##>##>>#>>=>#>>#>>##4"7æ9Ô<>>#"####"#######"##"##########"#####""###"########################"############;~Ô97>"##################""##########<"##;##"#########"">#"##""#"##"#">#"#6"7==#>##>#""####!>7;#>>##>###!"9;!=##9###"##"#""##:!74!!! >7=""#:967=:>#<#>#####"#>k>"8;=>#>#### "#:;=#>#‚#==####>####:57 ! !!Ô """#~8>6~>>:>>#>>>###=<"""9<:>>;"=>#>#!96!7   >76"==##>58 8€<><:><>>##"">=!;:#<=#>;>##< #Õ<">>"9;;=>;>>==>"#=9 !6!!!!!!!3: !>"# Ó9!<9‚9=;>:#;==##"=>><<7=9<;>=<"##!"9;">"!9:;>#‚"#><>#"799!!!!! >4479>"!#>8~> =9;>9<<>=<;###>=>:>9=:=;;#####:;=">!8<‚#=;>>==;##>=7"!!! ! >"38 :=#>!Óæ= :#<==:#:;=#"# :>;><<"##"#";>"""‚=;>>;<#=;=>## 6  ;9!=7ÑÕ 7~ =#>>=>;#=#;=>;>#"#":><=:=:<#####=">>"‚<7:>==><><>"#€ !5587Ó} ""# "9===:>>‚<>"#=; 8=;;>=>:#;<###">!!9=9‚#<>>>>9>=# 9 : 3678ÔÔ:"##‚9>;:8><9=###>":<=>=#;<##!>>>"""" 9=:8>>>=#<;>##!!:  ! "!64769879=###=‚;;<:#>;>#">>>=7>=<>>;>#"!>"=>#"#>:Õ==<#>;;>##>;  !!!! 67Ò9«75!=##!>><;=;#<;<"##>>7;<=#"‚####>>">">## 5><=<<>:=##= <!" 6 !!!!65~667787€8Ô ®;#":#=;<=>;;>##>==8><;<#;###">#=<;;:<#""<><><===>##;! 9 !!""3758: 8"#9#<<=;===>##">;<7>:><><###"j<>">>>#>>#9<#9;9>;:##"7! !!""":54€8558ª7=6;;>>=><=:<=#""">">;>;;:"9###">=g>>! ">""<>>:;‚<#<>#"!Ó ! !"!#! 4Ò837‚ 867€>#<>;=>>>"#>>===:<;>:>;<>"><<">>#;=‚>9>=8>###! "" !## 57864587 ‚58=7<>;#<;=#<#"#5>9;:#<;>####6Õ‚Õ>‚=8=>9>>" 6!!!!!"!#!#Ò875Ò6764::>=:#=:;>=##5Ô~556>9=9"<=>">€7Ô5€7Õ<<=>Ô<<=8;>:<>"#7!!!"!!!"# 693557667678=<;;>>‚<>>#"; <= :7<;><"<9>#"; ‚=; ;<9 <;7<><;8>;==##7! !!!"!"!!>6 8ÓÑ66€7;#<=;#;<:=>#"< <:=:>;>:>>;>#"=>=<=;;< ;<:>>=97#<:#>#7!"!" !"!!! 48Ó543:«8679#;=:#;:<>>##<= k>!;‚=9>;>=:>"#<;;;=<=<<;;<#=;8#=‚#>#!! !""" !";95€7899778=;<><<#;8>=#"! < ! 9;:;<>;:"##;;;!<<<<<><#><8#>:>#"!!"!!""""" :6965799<:«66>==><>>=;;>#"==>‚>k<=8;";;;>:<##">>>>==!!<8;6>Ô>>=:##8>##"##"" !"!#"<5259:8 96Ó6><=><:>:‚=>##>>> >"!;=>:<<>:;#""9;=: 9<<"""5;#>"#‚############!7887655: < 8«75}9€:#=<=<9><">>>#>#>><>;<8<:>###"#>>"">">">>>Õ8>#7#>;;>#"#####:9668 :478659>#;<:>;>>#>>>>>>">9#‚"9>‚>#"####:#>‚>#9;;##<9‚=""##"87::Ó79 8658€<<>;=;::<###<6>;>=#9####‚:;99‚8::;;‚:7>#8:#8=;>#><<<===>####9 8 :84 75585>>><<;:;<#"9:;‚:;99;<>#>:####==>!>">"==7<>:;=;;‚##==!<>:!<<#!# ; Ô58259=58476Õ>=#;<>‚;>#">="><;9>>=>>>###>:<;::;: : ;<:‚=>>9#;=9>#>979:>==<>""k 75 56574‚=#>8=>;:>#!= <==>7>"#>###>">>>>">=>>>>>>:€<==;#<=9=#">>>"">"=>""";67456;=443765<>>>;><<>="":;:;9;>"###>#####!>">=>!==>:;9>6=<>9#><<<"#>">><:=><>""!525 !974:7"><>=;>:<#="#>>>===#!#"#!#!>""=:::‚">>"><8;<<<>#:;‚>#>><<">>>">">#:9Ò79> 8:589=>:#>;#=<=>""<‚;‚ ;=#######""##>>>>>>"9‚;;‚>#;<:#######""#"# :6>;><:>##!!<===>==###"##=;;<<#>:>8"##=!<:‚:::;<>"""! ; <9 : 846=<>=:#:;<#"##>>:: ="####"#######!<;9=;:=":=;>#"=:=<=>=!<==!"###" 9 94788;:>=<>=‚>>#"97‚::::‚:<=<==<"""####"!8><<9#<=;;>#""""#"">"=>!=#""""‚;=7: 57<8=:#=>#::=#"!!==">!#"#><">>"=>!>""#####!6>=#<<><=<>#>>>>=>==;==<;>=!"" !5 ;!<<35>:;<>>#>;<>##=>=<;;<;;‚<;;=<==<;>= 99####"!8>>#=<>>=>#"="; =!< ;!; =!< >""!8 ;; 97=9;;<>>;>#=#>< >=9<< ;< ;;"; =!< < >">""<9=>#<=>#<>#>>>=;=<<<=>=<<;<<==>""; ; > 8:=;>>=>==>>=#"<>=>!==>=;<;<<==>< 56>>#;>#<>##><==<==<<=;;==#=<##>#> :<>=!>= =>"<;;=;;==><===;:!;;===;:!<>""!; : >"##"##!#"!! "<>>>>"=>>=>>=;:!;;===;:!;;<<;"##""###!"#"###>"=>>">>!>>>>!===>""" : #######!!""""‚:: ‚; :=>>>!>>>>!===>>>>""#"###"#"###<"8 == !!##""9 ;###########"""""!!=<==";<<<;=8"6 == !><"8 == >>##"#< :9;;""!;#####""""!"""##!‚:99> ‚=#"##"#"""""""><9‚=>!= ==="";>##############""< 79:99Õ::9‚:99::99:99;"=<:>= ;"##""!#####""#"#"#>!>!=:‚<7=>:<<=‚ < ; = ">">"#"#""##########">"8#>>"#######"!"k>""k>###>=>"8#>>;6>=‚=;>==< < <<###############>!==<<>######"!!!><=<=="8;<<>=;=!<>>>>">">">">">"##>""####>####;=!<>>>"#####!!!>>>"!=""==>">">">"">>"!"""""><>!<W@huvvvwvvvvvwvvuuvwwvvvvuvvvuwyyyyyyyyyyyyyyyyyyyyyxyyxyyxyxyxxyyxxxyxxxxyxxxyxxxyxxyyyyxv;;:;887::8999>><:9;=<;=>>#==>><<;><<><<>=>>=#!#>>>">>>>>"<>#>"=><=>">=>#=>=9ÅÅ<<">#>>yx>>"<6ÐÓÑÕ>#"><==>>>>>>=<<>;==="#"<#=>>##>=>>">>#==>=><==>>#>>>><>>#>>=##>9ÑÏÐÐÒÓÓ;:#>>!!#>">#""###9!"=>#=>>>==;==;;=:<>:>>>##>#<>;<=>:;:;:82xÊvuÏÐÐÐ;:#>yx>=0upÈÈÊÌÑÂ<><>><>=""><==>>===9z8<=<<>=#=="####>##>8z>#>#>>>>">>>>=>=>=5ÓÌxËÊÌyz3;>>yx>#~ÉqnoÉxÐ34>>=>=;>;<=>>;>>=<=<Õ698;<><><;;==;<;<;<:Õ#>>=>><=><=<>=>=#>>9ÔxËËpxÍz>=#=yx#=ztpomÈÊÑ{;9<976712ÑÒ64ÐÏÑ6ÔxxxuvÐ:;><9><<78:>;‚795Õ::=‚;‚Ô39;=>:=<=92Õ7ÑxËtqtÏy4‚9>yx#>1ÊooÆpuxÓ#ÔxÏxxÏvux6Ñxxvxvtuuutt6‚wvÏÌxuxÏÍÏÒÏzÒÐ7><=ÕÓyÏÒ0‚;>"==<3ÔÑ:ÓÌvqotËÒ;7##yx=>ÉpÆnÈÉx|:ÔÑËvwxttuvttuvuvtttuut{ÑtsttuttxÏÐÍÑÏz|572ÓÒ|Ðy{}9=>=>=8833ÒvÊqoqÊz9<#>yx#=7tqmmptxy:<ÑÐÊÊuuuttqttuxtvpssqsqttprrsqqtutuvxÐÍÒÓÐy/33}ÒÒyz‚;:9510ÐÔ6ÑÊtprpuÑ=>>>yx>#9vooontx|~<ÑvutqttuuÈorptttqquqprqpqpqtqoopqttvtvÐvxÏÑy0ÑwxÒz{Ñz0~|ÑÍÑ1wqppppv{7"= wy>>;unooÆvxz>yÊutsqsxvopqrrqqrqppoqpuxytvvvtvuxutttvxtvuÐxÏvvvyyyÑxÑxvÐÒ}ytpqpquz>;> xx#=upnÆÇÉxy>=ÐtttqsrspppoqpqppprpptyvvsttrrqsrqtuustustvuvxxuvuwÐÏÑxÌxuÏ6zprqrqvx"<##yx‚;;ËonmÈÊÑ6"Ìtstqrrrqqqopptppnotw|xuutvspqrqoqqptxvuutttuvttvvxxÍÑÐÏuvxÕvpopqstx==#>yx>>;ypnnÇÊw568xttrqpprropqqortppw{{ywtvrsqrprqÈopppqpÏtttvuqqttutuÐÏxÐvuxÓwtpqppuy79:=yy#<€vpopÉÉv~6<Êttpqqpqonopqqpptx{yvtsrsqppqpqÈppÇÈqpttuttqsuuttuxxÑÐxxÐ;xuppqtuy>>>>yx><ÊqnnÈty5;8vtÈqqorppqpqqppvy:|~xttrrrqqprpprtpqÈÈopqtutttqqstuvvÑy{ÐÍÒ2ytoopsux#>#yy##=ynomÉtvz>=tÈnpqoqopppopqv|9|xvttrrsrroqrpqppÈpsqpoppvvuvssrpttvÐ|zyÐÒ3|upqrpÉz""#"yy#"=xonnÉuw}>9ÉoÇnqqpstqpqnt|9=yvuttrrrrqqÈÈÈqprqÉqppÈqptxvttqqsqtuvxwÏÏÑ0ytqoqpux:>#"yy>==ynpÆpuÑ{"=ÉoÈÈÈÉopppopt|>>{stvrsrprrqqppqprsqoqpppqptxxttqpqttttxxxÏÔytqqostz<#>xx=><1Ènmptw|=3ÉÈoÈÈÉpnqopqx€=<>=|tsssprrpprppqqqrqqÈpopÈppquttqprssuvtxuvÏ|topprty7<=>yx>=>2ÈÈnppw~75ÉÉÈÈÈptpppqt|‚=><>ÕtrssrossrqppqÈsprorrqtqpopttsqssrrsvttutxzurpqpv|7#>>yy<<;~tnpÇuw~"6ttÈÈtqpppptÒ€<=;>:ÐtsrtpoppqpppqroqortqruuutÈvxpstpssuqqqrtÏyuoqpqv~>;<#yy>>>2ÉpnÈtx}"6ÊÈptÉpoqqtu~9>><yx=#>2tpnÈtw|>;;xvtssspqqrrsuttrrropttЀ€ÐsxÏuxqpsqqpqstsxÑÓtportt8>>#xy‚;"0nonÇÉw78:tqtÉÉÈÈpnuÑ7>=<><;xttssrrrstrvxuvvprpurx;<|rÏÑuusqprprqtrswÒÒpoppru};‚<=yy"<<}pnpptzz"1ÉqÈqtÈpppy=;=;=;=zutrrsrsqutvtvtuspqstrx7;ttxÐtqpppqrsqstw/xtqrpst<=<>yy>=>‚Éonpuyz"~toqptÈÈÈÇy7;><=;>>|tturrsquutszÒvvtprrtrrwysxsroorqqsrttvÓ}pqqnou‚>>##yy;;#4ÉnoÇvv{7|ÈnpptÈpqny:><;>>>;wuvurrrutsy;>}tvrqqtvtz~yus|{xopqrpqsquu5Òtrqnqv3=">#yy"##~ÈnopÉw|"5npoÈtttqp}:<==<>;<=;{xtsssutx|<9{uurrutssz:~ux|;zoppossrrtt~zpqqoqu###xy##>ÊopÈtyz>~ppÈpuvtoq{<=><;<>;=;xtuusvtuv}~sttuttsuy{=;~};>yy###7tnÆptvy7}sqpqtturpz<=;<:;=<<>yzvutvutts{€xwzwusuz}:;<=;<=zoropuqpuspÐ{uqpqsu9;>>=yy>>;~pmnÈÉt}9:pÈÉqtuttÈÔ;<;<<=;>=>xuuxt{t{||7:;:yutsx<<=;:9<<;{pqqpttqtqrxxtqpopÊ:6‚<2Éqtptuqoqx9<<;;=<=;;ztttvx|‚7===<;7xttÏ|;==;<>;xqqottqtqspÐ|vppqsÊ"=;=yx<;<1pmnntu|<}qppttqtpoy><>;;;;><{yxtty9;>;;<;;=zstux9;;‚;;‚~xqqptptqqptxzuqqpqv7=##>yx>=;|ÆmÆÈpwz:4ttqpqspppw€:;<>:;><;;€ytt9<=><;‚=;<‚~yxxÔ<;<<<;yvrqqpqttpsu{zvpoqsv<:>>#yx#>;}nmnÇtxz>Õtqqqrqprptx7><;==;;><=yz=<;>;<<>><;=:;;:;‚=<‚ÐoqssspÉutqÉÒÒupqqqu4:::>yx>#;zpnoptu|<3tpsqoqpopqx<;<=<>>;><<:;>>;=<>==;><<=><<‚<;9}vqqssqtptuqu|}uppqqu~>=‚:yy;::ynnomtv=2tqsqoqpnpqt{<=;><=;;=<;=<<:;=<;;<;<;><=;;;:<‚:Òprsqpqspttuw;5tqooqw}>>>>yy=>;zpnnÇÉy€<7tqrponpoppox7<<=<=<==;>;;;;;;:=>=;>;><;;;:=;‚}Ðsqrttpqptuux1yuoqrpu}:;<>yy#<<;<<;=>=;><<=<><=<=;>;;;;==<‚ÑtqsptttttuuxyÔyuoqoqt8<>#>xy##>:=<;;>==;<<<><=>>;:=;<~ÏsqqstttqtvvvÏ|Òvoppsu1"">>yy###wronmÉw{<;uqrpqoopnooqtx=>=<>;<=<;><=<<<>=<<;=;<:<=;ÕwpqpststtttvuuÐÔyupqost{;"##yy>>;xonoÈtx>;xtÈqpqqoÆpporuÑ‚<;>=;;>;=>==<>><>;=;>>;=>;;Ñqoprpsrqtsstvvx|zuspopt|;#>>yy=<6wppppÉy€=;ËÉppqpoqqqnqpsuÒ:;>>>;>>=;;;;<<<>><>>=><<:ztooppprpqsqqtvuwÑÒuqqpstx9:<=yy>=;Êppottx{7=ËÈpoontqnqprquqvЀ‚===;><>;>=;>==;>=<=;;‚ÑtpqqqqqrrppsqttvwÔÒupportx<<;>yy><5wooqttx>8xpÈopoppppqqtturvÏ~7:>>;>=<<>>>;>=<"">7}utqrrrpqqrqrprssvtÏÓ|vrpprt|7"=>yy>#‚uqppttxx79uÈppoqqoopspttqtptÐÑ;‚<;<;><>;>><<==;:{wrprrrrpsttrqquqsrtÐ6xupppqux>‚;9yx>:~Êpopttv|<;uÈpqopqppprtqtutttxuxÔ};9>=<<=<>>>:~{ÒÐupqsqsqrqtrsstvtsquÏÃÑËÊpnpuw6<>;yy#>7wppptÊxy~"vproqoqppoqtuxxtÍtvutvÐxÓÀÔ{ÕÓ~ÒÐÐÐxuqtvvurtqprrtqstrttrtvxÓyÊtpprÉ|4=;#vqpppÊz|<9xutopspqputtvw{uvvvvuÊvtuxutttttuxvtropppqsprsqssqvsqrrqtuÓ7xuÉoopÊx9;:=yy=>5tqoqtÊx{==ÐuxtvuttttxuÐ;;ÐvxxvuÎxxuuxxtutuÍvuussqpttttqqtxxttsstsuvxÒ:xutppsÉ{3#>#yy#"3ÉqpoÉxz5;#/ÑÐwÐÏxÏËvËÌÒ==ÏÌÐÍÏÏÏÌÍÏxxvÎvxxvvvvvxvxtxtuuvÏwÏÐvuvuxvuv5xvooosÉx:###yy#6ËÉoÈÉxÓ1">Õ/xÏÐzzÑÑÔ9;3"=ÓÏÏÍÏvuxÏxxvuuvÌxÏxÏÏ3:ÏÌxtuxxÍÑÒÑxÐÏÏxxxwÐ~2|utqnrtw>>"yy>=4xÊÇÉÊÐ|:=<75Ô4<96:=:;<><>"8=;661Ô695ÐÏÑ2ÓÒ-ÐÒ1;90ÐÐÏvvÏÓ295ÑÐxyÒyÒy3";yËÉqooÉx~:##yy:>3xË(ËÊÏÒ59"="<">;><;<>;<>>>>> >>#>>>=#<=>>>==<#>>=;<;€ÑÔ7;9;84Õ‚57:::76ÓwvÉpqtw{Õ;9yy>>zxÊÉËÍÐÐ5">>>>=<==7=">=>>=>>>><===:;<‚:9<:;:<<;;:;>>#>;>=:;;;<‚;;>"><=60xvÊÉÉtxÓ4>>yy#>4yuÊÌÑxÑÔ==>><><=9|9‚<;<<>>=>==#>>><>"#>####>">>##>#>><"Õ{:###>>>>#>";;yÏÍÊËÊxÏÔ;>>yy#<=<ÔÑÂ2ÓÃ6;>:;;<;<<€<#>>><>;=;;=<=>>==<>><>#>>=><=>=<>>#>>9:;<>;>;#>##==‚ÔyxÏxÏÓ;><#yx:<=<87ÓÑ2:>##=>=>>==;=<;<;=:;<<=<<><<==><;:<‚:9;8::::>=;;>=#>><:=;=;<;=;##7ÓÕ1ÒÒ:<>>=<<:78775266999:999967766677454424422222220222246:9;;;>;=>>>>>9;955;>;9:yy>>#:8:87:89897686685676774645774666554646544356224667<<>>>>>=="#>#>>>=>##yy####>=>=>>>"<==<<><<><<;<<<=:<::98888:::::7::79::79;;"###"#####"########yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyW@h;!<:‚9998:554699867:;<=:;>>>>>#>##>###>"#>####>>#=#>==<=:;==;;<>;<;<=;;=><;:=<=>>>#""<<;=;=;<=;;<;>><:9;=<;>>>#==>><<;><<><<>=>>=#!#>>>">>>>>"<>#>"=><=>">=>#=>><>>>=#>#>>=">#>=;=;>>#"><==>>>>>>=<<>;==="#"<#=>>##>=>>">>#==>=><==>>#>>>><>>#>>=###=‚9‚:<<:;:#<#;##>65539>=<><<<>>>!!#>">#""###9!"=>#=>>>==;==;;=:<>:>>>##>#<>;<=>:;:;:::84€59:::>=#>#;>=7|{157;>#><>#<>=""><==>>===9z8<=<<>=#=="####>##>8z>#>#>>>>">>>>=>=>><=75469;<"#>#:>#;3|yz3;=>#>="=;>;<=>><>>>=>=9:<;=>><><;;==;<;<;<:Õ#>>=>><=><=<>=>=#>>==865|88;#"#=<#>7~|zx1~;<#==;<;<99:::898‚<;6Ô€4Ô9<<><;>=>;<=><<;=;;=;=:<;;9<=>>:=<><:<<;96~|~99==9>#‚#>9~{zy|9=>#>9‚9756;9€€7Ô~55~}~9;5685€5778<9;<;>>>">=99<;>"""!!"<>;"=7€}z}7<#;###:=>;|{xy13<"">;6€7~}~~}7}}}~Ò79~ÒÓ~ÓÓ379‚8;‚;<=<><=<<:9;=>"""##>>==<73zy|5;">#>";#=;}|yx{9‚"#<:44}}3}}7~{}Ò|}Ñ||{||Ò{Ñ}5~6‚7<=:9;====<9;>>>"=<;:>>;~~y{|<##>>#;>#<{zzz<>#;75}}~|}}{{Ò{~~}{Ñ}{z|{z|z|~{yz{|}~€~6‚7‚;:;;78<;;<;;=<;7;<}|yy|7;"#>;"=>>=zzzz6;"#:4}Ò{|~}z{{||{|||zzy{{‚~€€~€€~}~Õ~Ô5‚9‚€79:9<9;86‚<=‚{zy|;#<> >;#=‚|yy049:##:}}~|}||zz{z{z|{yz|{{}‚7€}~||{|||}}}5}~Ô67Õ~7:9;8679>;}|z{|79#<###‚‚;=}{zx{};>"#7~}~{Ñ||{{{yz{}{yxz}<9~€}z{{{{|||Ò€~}}55~~ÔÔÕ7;:95Ô>7|zy{}9#>#>‚>>=7|zy04>>"7~}}|zz|{yzz{y|}z|;;;~€|}{|{|{0{{Ñ|||9}~}Ô||}~~~:99:€9={zz|9"‚:=#=#<:|{z|37=!#5}}ÑÑ{z{yyzz{{{{~9><;;€~}|}{{{{{|1{|01|{Ó~~}|}~~}~8;:78:"9{z{~€;#>>>#;><‚4|yx1~‚=">6}1||z|{z{z{{{{€:>:=~~|||{|{|z{|Ò{|21{{|}}}}ÑÑ}~6;:<:8<<:zyz}9>#>#"###>7zzy3~7;##~{z||z|yzzzzz{€<=<9€~~{||{|z{|z|{{1|Ò|{zÑ|~ÒÒ|{~}:<;::<=<{z{|};#"#"##">zyy|=#"3{zz||{}Ò|{{y<=>;€~}{|{{{|{{{|{|||{{{{||}€6~~}{Ò{}5ÔÕ798;;‚~|y{{9">#"#>>=>€z{y|;;##3{{11|{|{{z{}<<>>‚}€|}Ñz{|{|{||z{Ò|z|||{|{}€€~}|{Ñ}}~4789>‚~{zz};><#>"<=><7{zy|}<#=2{{{1||z{z{|=><>=;|||z|{zz|{{||{|{Ñ{{z|z{||~}|zÑÒÒ~Ô4869<{y{}~‚><=>#;>=>7{{x||=">2|1{||}{z{|~;<=><><~|Ò||zÒÒ|{{{{0}{|{||{}||{|}}Ò|ÒÒÑ|}ÔÓ~~9;|y{{7<>#>>"=<<;9|yz0=#>~~|0Ò|{Ñ|{}<<<=;>>:~}{ÒÑ{{z{zzz{|{|z|~{ÑÓ~~}{Ô{}~{Ò}Ó|{ÑÑÓ9‚€{zz|7=#;<##>>>>7|{y1~9=#>41Ñ}|{z|Ò}<;>><=9€~ÒÒ{{{z{{|~{Ò||1{~}}~€€Ô~:{}{{|{{|Ñ|Ó;:~{z{|€<><<>#<=#>7|{z1~<##||100{|z|‚===>;;9~}ÒÒÐÑ{|ÑÒÓ}~}||{Ñ~~:;=:Ò9Ñ{||{z{Ò}Ò9;=~{x|~>=>>#">‚;"7zzy03>"#~Ò}2310{z:;>=<><=9~~}ÒÑ|{|}|€z|{|=<‚|9;}{{{{{{~|Ò7<=}zyz}7="‚<=#>"<<{yz|~;;#<||{|ÒÑ|{{9;>;=;=;=‚~||||Ò|~€~€~}z{|~|‚=}}~|zzz{|ÒÑ}}7;9|z{}>"=<>#>>=>;1zx|‚;#>}z|{}0{Ñz::<><=;>>;}|{||~}:;€€~y{|~||‚‚}9}|yy{{|}|~}7==||zy{7"#>###>;;#91zx077<"<{z{|}1{Òz:<><;>>>;‚€||{~}‚<>‚~|zz~€~;;9}9yz{|{{Ò|~5=<}|zz|="">###"##9{yy|3<#>zzz{}}}|{=;<==<>;<==;€}}}~<>‚‚€||}};>;;=;{{{z}|||~}=;}|zz|>#######>1zy{‚;#={{ÐÑ~Ô}{|<<=><;<>;=;<}€~<‚|~~}::>;;<><;{|{z~|||}};<~{zy|#>#>>#>###:}zx|7;"=}|Ñ|~4Ó|{;<=;<:;=<<>9;€€~~};;9;7}€;;;;<=;<=;z|z|~|{~}{:;|y{}€">>>=#>>>;‚{yz|}=""3{||}~}Òz><=;<<=;>=>9€~;~<<;9:>>97~}><=;:9<<=;z||{~}|~{}9}yy|":‚<<#=:<<:{yy2}9;#<23}{}|{|9;<<;;=<=;=;~€9;=:===<;;9~‚‚;==;<>;={|{}~3~|Ò|:<7|y{}>#=;=";<;<6{xyz~<#=}|ÑÒ}|ÒÑz:;><>;;;;><;:99;;>;;<;;=9}~=;;‚;;;;7||{}|~}|{}9;6}zz|7>"##>#=>=<9yxx1|;"=4}|{ÑÒÑÑ{<<;<>:;><;<=‚~~=<=><;‚=;<‚‚7€;<;<<<=9€|{|{|}~|};;7|xz}7#>>>#>;#>;zxy0~9;#>}||{|{ÑÒÑ~;><;==;;><=<;;;=<;>;<<>><;=:;;:;‚=<=:{|Ò}}|1~|3<<|z{|7!<::>#=>#;7|yy|~<#=}ÑÒ|zÑÑÐ{|=<;<=<>>;><<<<;>>;=<>==;><<=><<‚<;‚;€{ÑÒ}|}|~|<={y{|=>=‚:#>;:;€zzy/~7>#<~{Ò|z{{yz{~;>=;><=;;=<;=<<:;=<;;<;<;><=;;;:<‚<<||}|{|}|~}#=~|yz|=#>>>#>=>=7|yy0}‚>#>}ÑÒÑzyzyz{{<=<=<=<==;>;;;;;;:=>=;>;><;;;:=;:;:Ò{|}~{||~59<:zz||<=;<>>##<=~zyy12>""3ÒÒÑ{zyÐÐzy=<=><;<<;=>=;><<=<><=<=;>;;;;==<=;}Ñ|{~}~}}~~‚>:{zz|>>>#>="##=7{yz/27<""Õ|ÒÑ{zyyyyyz7>>;=<;;>>:=<;;>==;<<<><=>>;:=;>=9ÒÑ{Ò~~}|}77‚<<7{y{}<#">>"####~|zz0~;#"5||{{zy{yzz{~9<>>=<>;<=<;><=<<<>=<<;=;<:<=<={Ñ{}}Ò~~~}€5:>:|zz};""###>>><{yy1}9>##ÒÐÑz{{zy{zy|;>=;>=;;>;=>==<>><>;=;>>;=><>;|yy{zÒ|{}}}}€9<;}xz{~<"#>>>>=<9|zz}}‚>#"51{{{zz{{{yz{Ò<><>>>;>>=;;;;<<<>><>>=><=>;~yxyzyÑz{|||~Ô7<=|zz}~9>:<=#>>=>~{zz}~9;!#5Ñ{zzyÒ|y{{|ÑÓÒ6:<<===;><>;>=;>==;>=<=;=>;~z{zz{{||zÑ}|~~68><{zz|~9#<;>#>><96{y{}‚>#"8|zzzzz{{{Ñ|ÒÒÓÒÔ‚<;;>>;>=<<>>>;>=<"">;<7~z{{|z{||{{{}}}~9=<7|y{}}<>"=>#>>#<~|zz~~9""{zzy{{yzÑÒÑ}~Ñ}{~‚;>==;<;><>;>><<=>>>;7|z{ÑÑ{y}}~|{||Ò}}:>96|y{|#‚;9>:>:83|yz}~7<##6Ñ{{yz{z{{ÑÒ}}~~3ÓÔ7=;><>><<=="##><;<:{{|{Ò{{{Ò|ÒÒ~~}|59>;63yy{7!<>;#>#>;€|{{}~9;!#6||z{z{{{zÑÒ~€€4Ô4ÔÓ~‚9=>>;>==<;:;|~6€~|}Ñz||Ò|Ò~|~}|~68=‚~~z{|3<==;<"=>#<|z{|5;<#"8~Ò{ÑÒ{||}}68566Ô553545Ô5~ÒÓ}}~ÔÔ~|zz{{|Ò{ÑÒ|Ò}|5}Ñ{{{~6=>93yz{~9";:=#>=>;~|y|~59;##;5€~~43}~9=<‚78Õ65Ô€Õ567Ô}Ó4ÓÔÔ55ÒÒÑ|ÒÓ~Ò||}€~~ÒÒÓ}Ó5€<"9}y{}2<=#>##>#"93|y{3;>##;;;7:9896766;=>86:7899679776€5€Õ666€57Õ4Ô455Ô79:€56657>>97{y{}}9"######<53y{38=<##>;89;;;<;=>>;#><89775Õ877655Ô689789=86€35787;<;9:9‚9987;><<}|z}~>#>"##>=:84034;<"#=<<<:>==>><=>"=>";>=;;9<:;:97::;:88:9=;9‚Õ8Ô69=;><;‚79<‚<‚;##‚63|z{3<>###=:>:85265‚=>!"="!"><><;<>;<>>>>> >>#>>>=#==>>>=>=#>>=;<;;7;;=‚;:9<=<<;<<:>=6|z|7;<;9=>>>985357:;=#">>"=<==7=">=>>=>>>><===:;<‚:9<:;:<<;;:;>>#>;>=:;;;<‚;;>"><>>;97422=‚>>>"#>:546;9;>#>>">><=9|9‚<;<<>>=>==#>>><>"#>####>">>##>#>><"Õ{:###>>>>#>"="‚9755479>>>>>>#<===;><=><;><<;<;<<€<#>>><>;=;;=<=>>==<>><>#>>=><=>=<>>#>>9:;<>;>;#>##>>==98989<>><#>::<=<;=<;;>>##=>=>>==;=<;<;=:;<<=<<><<==><;:<‚:9;8::::>=;;>=#>><:=;=;<;=;##<<>;<<=<>><>>>=<<:79‚76687999:999967766677454424422222220222246:9;;;>;=>>>>>=>;:;;>;9:>#>>#:8:87:89897686685676774645774666554646544356224667<<>>>>>=="#>#>>>=>##>#####>=>=>>>"<==<<><<><<;<<<=:<::98888:::::7::79::79;;"###"#####"############"######"###"#########"#####"###"#"######"#######>""#"###########"####""#"#"####"#"># ÑÍÐÍÐÐÍÍÑÏÍÐÒÍÐÐÓÏÍÑÓÐÌÐÓÐÌÐÐ ````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` `````````````````````````"``````````````````````````` `````````````````````"" !``````````````````yvy`"" ! ```````````````yytvv""  `````````````z|{wqsv`"`````````!``yz{~zxrts`!  ``````````""y{|~}wwsr``!`` ```````````yz{|}|||{wtv````` ` ```````yz}|}||}|}z{yxv`````wyy```suuvy`xyxxxx`````` ````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` `````````````````````````"``````````````````````````` `````````````````````"" !`````````````````````"" ! ```````````````""  ``````````````"`"`````````!``!"``!  ``````````""``!"!````!`` ````````````""!"`````````` ` ```````````k```````` ````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````` ```````````````````````````````````````````````````` ``````````````````` `````````````````````````"``` ``````````````````` ``````````````````` "" !`` ```````````` "" ! `````````````` ""  ` ````````` `"`````````!`` `!  ` ``````""  ``!`` ````````````"  ````` ` ```````````````` ````` ```` ```` ``` ```````````````````````````````````` `````````````````` ```````````````` `````````````` `````````` ```````````````` ` ``` `` `` `````````````````````````````````` ````` `````````````````````````````````````````````````````````````````````````````````````````````````````````````` ``````````````````````` ``````````````````  ``````` ```````````````````````````````````````````````` ````````````````````````````````````````````````` `````````````````````````` ``````````````````````````````````````````````````` ``````````````````````````````````````````````````````````````````````````7+rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr**ʱ±±±±±±±±±±±^dig!i>k >!ik !kkk!! !!±±±±±±±±±±±±±±±±±±±[idb_bddhdd"digik±±dg±gd±±g±±±±±±±±±±±±±[Wb^ihibk"«bfejig#igi±±±±±±±±±±±±±±±±±±±±UX\ikkifkkid>ihi>gki±d±±±g±±±±±±±±±±±±±±±±X\hd#dk:dk>kig##k#gd±±±±±±±±g±±±±±±±±±±±±±[Xg^dk"ek"idk#gk#kd±±g±±±±±±±±±±±±±±±±±±±±UW_biik#kieijikigk#i±±±±±±±±d±±±±±±±±±±±[[Xkii#k#i"kk!digkdg±g±g±±±±±±±±±±±±±±±±±±XW[gcbkd>"hg##"=igkg±±±±±±±±±±±±±±±±±±±±±WUXiki>:kdkik#ii##gk±g±dg±±±±±±±±±±±±±±±±±[X_d"ic­kkiifigi"dkg±±±±±±±±±±±±±±±±±±±±±WWX_giki"hkk##ig:gkgkhd>±±±g±±±±±±±±±±±±±±VX[_ibkhekhdikek#jgkg#;gi±±±e±±±±±±±±±±±±XVXW^idb!fk>g"##;kkkdkg±±±±±±±±±±±±±±±±±±U[W[bgbhikkgkiiikg#iik#dg#g±±g±±±±±±±±±±±WVX[__kidk#hæk#kki®kgk#kgh±±±±±±±±±±±±±±±±XXV[\hcdkkikjigkgkgh#kg#ikhg±gi±±±±±±±±±±WUY[[dghbkkk:#k##>"hkggkkh"kh±dg±±±±±±±±±±VXWWX\iikhki"gk#kjhhk#kik±gdgi±±±±±e±±±±±WW[VX\_g=`hkek#ghk#dkikkdh±±g;g±g±±±±±±±±±VVVXWWggkkbggkigiik#jkikkk±±±±g±±±±±±±±±XWXV[W\c^ig«kbgg##eig#kdkgk±±±±±±±±±±±±±±VVXXWWWWhkhk=kg ki####"kkkk#±g±g±±±i±±±±±XVWU[VX[fh>e>k kkkigiikgk#ggdg±±±h±±±±±±±±VWYUW[WWeifkke>ig "i¬"jgdgh®#­±±g>±±±±±±±[WY[VX\W\`ig^j#"ah"h#h#":#kd­#h±i±!±±±±±±[V[VX_[XW`g e`ebfe dfdkkf®kihkhkk±k±±g±±±&% lVWV|.46 7¬7>­4>­ 4­ ­4­±±±±±±±±±±±±± &&&&Í,.Í,,.Í..,,,Í,.Í,.Í.±±±±±±±±±±±±""""########"""####!""=#### ±± ±±±±±±±#!""### """""##""##!±± ±±±±±±±±±######56<9#!#"=8#=<‚>#= #;±±±±±±±±±±±###5####<###!";#;>6# #>#±±±±±±±±±±±#6####<#####6>7>;>! ;#±±±±±±±±±±±##:####5######6#;>6>##=#±±±±±±±±±±±#####|####<#!#—:#6>6>Õ><<>#±±±±±±±±±±±###4####5#!"#!#;#=>;>"!;#±±±±±±±±±±±###Õ####<###" #7#6>Õ=!!=#±±±±±±±±±±±# 4555=<# "#"#66Õ#;="">;;±±±±±±±±±±±## ########"#"#Õ>;#Õ"#"##±±±±±±±±±±±±±######!! "=!# "";>Õ#;"!# ±±±±±±±±±±±±±±±#####  ######### # ##±±±fheroes2-1.1.6+dfsg/files/emscripten/000077500000000000000000000000001476115357100174405ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/emscripten/fheroes2.jpeg000066400000000000000000001541151476115357100220330ustar00rootroot00000000000000ÿØÿàJFIFHHÿÛC     ÿÛC   ÿ€r"ÿÄ ÿÄÿÚ ç¹V+Ñ7¥ɰ¾,/‹ âÂø°¾.ou~“•¿s'+/ÏõõÓ¶aË©m†¦6Äjh–¦6Ñ1ª§oE£I‹½ÃÙÃåôþ“Eè8økÍíK+ÂÊô—E¨¼,¯AitZ½ëlÜÊ3ùeÕ­Ÿ3a1›ŒͦÕç2-q—M«‰Fe»× c‡³‡_MÚ7µiT˜¦+‚•B•B”ˆH„Á5Ñr²™RÔÅq*˜¥1111@€2k¦ºÚ¹TR¨R¨R¨R¨R¨šU ßOæ½O§¶Ì±›æ;’º×ËitY‹Ñ+1z&,Åè´Y¢ý®ÇoóþÏz~:]8Š…*ˆ¥$Ò¨ŠS$FEŒŠßm±ÀØðú·*U©žŠnS1n›”Ú-Ór›ÖÝ7)µmÓr›ÖݫֲW ; k_ÝÛ} 8„H€ "n[¹[TE,‰‚ ´DÄ €'.º+¬Üªš€Hþ§Ëzž'Ow›…›æ;·†¾TLDÂ0„Z)¦ª-ø9¸[zþÏú?ê86GL! €"F6Eo¹Øk¶>¥ú©M…3LÄS4Þ±LÓjÅ3Mâ)šmZm\µ’–°³0¶ðaÛ®ßCL&$€×Euš…-4ÉM¡LÂ&&\ÄÛeWEuµÊ©¨€Ÿê|·©ât÷y¸Y¾c»xkå‚"a¢(ª™…QzãàæàíàÐh7úOÁ°::`„ "i21ò+}Æ~¿aÄê_ªŠµ3Å3LÄS4Þ"™¦ôŠf‹B‰¦õ‹W-^–°³0öðaÛ®í@´ &ˆ‰„ÍtWY©4ÖÈD DD HYu´ÍÙÁ—TÎÄÏŠj€œªè®³rªj gúŸ-êx=Þno˜îÞƒ_*0„IM«ILÓhÇÁÍÁÛ×Ðè7þÔp¬Ž†„‚ˆ Œ{õ¾ßa¯ÏâôïÕEZ™â™¦ÑÍ6¬S4^"™¦ÕŠf›Ö-\µ’–°òñ6paÑ]Ú¢-"`À&í»•™¢b²„X‰¦a€¿‘K©½­¥¦hfÇs]´Á—W<[ÓU9* ªé®¶¹1Ra($BD%,ÿQåý?§»Ì×äù®Þdã0å¿!âÄZ/ň´^‹4Ì_¢Õ¬a_ÅÚÁ¤Ðoô>—‰`t4Ñ"0/Ø¿[í³õù¼n–DÙ|×)¢™Šé¢›Vº)¦ñTQ­TÓMë6Ô^”bdãlâÄ¢º7u!1 0$®QI!2„!Ä L ŒuT¾~»g…[Yq6X{ 9XØÖæ.Ú2P&2ævVžÎ®­Íu¶¼CFÞ x4màÑ·ƒFÞIƒéu™<ýÍåz;wÐF‚"}h"cÆú41-õ:8˜ÞS¤‹FâÖ®/Zt[¼~–Žš6ñ·¯©m Ô¶Ñ-SiÕ¶pk8˜ÖÆÊ uüš¢r2°'Kk>0"³ŸNLgÓƒŒØÂ‹Fe8‘jåÓ‹4ãE¢þ:œ”Ç£"3á°½²½µR´¹ âT+‚ŠÕÂ"ªbb!h˜‚HL$š»˜òd²¨Åyĵk%.0i´ÀÝy?C7rïó÷5­’'ZÙ kd5­Ö¶CYNÆÅë«Ñz3Øæá1ÎVLcÁ’Æ1Ž2ðŒ†2g&1ÐÈ«¤nöšß© šôvð£: ΦÕ§:›F9´Ú0éÌ‹WŒÊ-\K9xÙñkq20º¼û‘n2Òì["äQ¹AZ\Sq@®ö=êÚúg_51\âäL[ŠâÕ¢+¦ÑLUÅQ1SYM(˜µJ‚L^‰«'$-P2ݘ¥à^€Ÿw¾ÐúévY²9 ©jŠŠŠ¥‰‡›£Ìz1èøÚ‘è9˜@$I *¦£q¼Ñïx|«Öïr·âšé¬ÑMtÞ(¦ºmZ)®›ÖŠk¦Õ¢ÕëY)‰™…·ƒU‡™…Ùæ Ë ‰ìÞ­²*¢½\äÄM14Ú"š©µb&-LÄÄDÅ«QX¦¨,ÓvÞJ@˜ríÜÇ’Í™‹Ð&ûÏAçýô»kö/ñú!Yµ‡™‡›£Ìz1é8š‘è9 @ …TÔm÷º-篙zÅîNýTM1*QjÅ3Eê¥Mê¥M«ë·’¶0²ðöõõxy˜}Žl—1$AzÍêÛ"ª*ÖÏ11…6…3¬DÓhS114Ì&•¢ä&&)ªQè½m¦&\M]Çxƽˆˆ(Ÿyè<ÿ ñ¾—m~Åþ?D+ °³p³cÔyOæ=/Uþ@$BLJvûÍóƒÖ̽b÷/~išk1 oX¦i½b™¦ÕŠf›Ö-Wnõ³…—‡·¯¬ÄËÃìsdÆ ‰]³z—¿Uk檄Z"hS111jÄ"Jf-\±\.H¦›¤Ù§&QrôÄÚ¹*ÌÅ8ÓAš€€ûÏAçýô»kö/ñú!Yµ…™‡Ÿ£Ìz1é8º¨;ü SQ¶Ýé7\.®eëy{õRˆE3Mâ)SzD)´E3Mëë·zXÄÊÄÚÁ¬ÄËÄëó d €L˜˜¬Ý¬ßªŠµóLM0S4Ú‹DDÓ0‰¦a´!E¢åÌy†LعKW15™˜˜™ˆ·+¶ìÛ½j¤½]‰´Údbɤn‘Cè<ÿ òíµûøý¬€˜-afágŨó>›ÌúN.¤wù €@„ª¦M¶ëIºáõs.ؽÌݘSÍ7¬R‹V)šoX¥M¡n«y)g+g»/­Ï ”A"˜%DÀí«•›ÕS83LB&ÌZ±LÄÂb&™„LLª«h›‘@˜&·ïgorç;nF+` öÜú=è8M½ü|Ž?D+ ZÂË̯̩ó>›ÌúN6¨w¹"HeÜ¥µñŸƒ1Õ!0"%U5]ΗsÄêeݳw›»4Í11LÓzÅ3M«Íª”^±n»w­œL¬M¬üL¬^¦€Œ´&B …Ëw+kµS8rÌ S11114ÌA„Ä gV×÷1w—¸˜b´ÙÅÔlS`Ò6ñ{­÷ŸÜù~æï#[—¿˜ÃRÙŒ1™ŒÈĉfQ‹°æÆ|X>kÑùÎÿ'V;¼«ßeÒtŠêÛ¿Ï=æö<§+õ&ú½+Pzþh&mvú}¯§™s­ ¼ŠlÓ ÔÙ‹ÅÚlÅ«v›QjÜ‹TÞ·mÑE«×±ö1`âäâôôC%0Wz³‹w"ŠÞ&™ˆ‚b"baLÄÒZ‰!˜˜ú-O ÑÙªS¥ž0®yÍœtÛ:Z€{=Ÿ–Éáu}eÏ-^¾oNóŸOdzg˜#ÓGš‰zj|ÜKÒSçbcu¥»•—‚þçm’Ÿ|ñhçß»òn´æž¢ì`ò¼ÃÓÙh#}“SEؘѷtšYÜDÆ6~ŒY6DDíãQhÕDÆÒ5q1³lZ6Të¢ccN¾&3íâM¢1ó)‡±hÌȘȸ–,eB1™1Ÿö›ýûÉucÑzïžøìûýÇþñ´ço›÷oú­?=G«çV¢%\SD%1 Î/hyýî-Áû¯Â·ñeú¯iÓ¾skóþϵñ^³H60€MÖÛ ;“¼¦¼:[OU=}µ@Ì®ÝÊ^ìÓ2” @” @”B%;ÐùßCÈèì=o•ú•ìýÏœ:;›¸zúN‘çžØ·Îþ;õ¿–ïdŧ*:øñiʦÕŧ.‹F¬¬|صZ¶§µÌ·ÜÖ”&D˜ L .Ú¹ ÛÖ246â+RÖâå2·)µmÅqh¢›”Ú´ìõ»y;3æ_MùoÌ:\Ýôÿ—úï£hö‡-u'2x\ÿƒêœp@Ü÷[Þ†ÇÍp:›æƒä4×Oy>ÛëÜw4éz÷åÖÇðN¬ô›º|5›ìz³‹“µÇÈêù½·Eý;™~×v¿*õqyúŽî¶‡eÕÇÅoðž'Zs Á¬Ý}Ëë¼lüu…Úüÿ/Éó·Ýšyó¬3xVáÛ_ZùG²Ö¦Ÿ»9ù> -z (ÙkvT¿füŸë_ ù—K¾…âúSÛêýk:7x­y¾÷¼Ý^Ó¨=÷‰èð†eò‡s›mö¸s3q^Ÿ½þ5Žy¿;ª=ÔWƒ-ýç¾³NöGÛ~“ç·8ó'è= žœ®î^X¥¼œö~73'Ûëï)±<˵û¯ÛëN·õìÞÆ?”WÚ¹~s/Ñö?û*6¿Xè?·Å:žôøf9ðÝyó?¥ùlüKåzÏÈúÜÈûÔ&œ_–=_:¿Ø~ýäz?©ïNl¼|s;ë¿u¼qn`s^Ôhò;sÄÉÁÔû?í4C>Þmü÷ åî¼ç¤ów®èê9w-ܤܘD ;ÐùßCÉè}KèœýõßÙú;‡Î:8}çÖ9ǤO—ý'Gâµ³}"×ϾŽÖæ}®³ë^—gÝ|?é¿ æÓï›]n7†ûŸ(uwCÌ=Ö6[/N|ûà½yŸ›ø¥ï“z ~ëùîÑüŽn'êïŠt÷{Åq~Sõ}ŒÝð?¸ü—ÌÛè¼­Õ<ƒÝÁÓ“Q£ŸêžkÙyÍ)øORñÿOwpfòßRrŽZv/Çõüœ¿2Ū¢òãkªÛRýŸç=7›ùZ^Ë”zx|¿ªŸªñïõ?>ö‡Œßù7ˆñ~Å»ÔûÏÅ|¼ý_“:ß»X>÷ôtÏ¥ó:3‡û{9{ãßXùgµÓê?OŒù÷Gœ>±ÎŸTözÝSó¯§ùÞÕüNQÖú¼‰ç=Ï/¹µ×ü«à]Í>ŠúO†ÇÐÛø÷Hr'_võµÜõöûZy=ß-}—ºzýuë>Ax]õK{©±¸Ðïµú™¼Òc­¢w-Ü­®M2L$!3}Ÿßòwöß_øÿؼocèœãÑé¡M‡Gó¯Eë×MÏdøVÖ_ªýÃû~>{è.~é>ƒ^Ñ|£Jßjø³Wé°ú­åލäbñ\‰ÐÜÝéµ½¿bòÇSyü¼iã}O•ú—Ý:º æÝ•ýGÄz­=Ÿ?èyÃÁú _§h¾owÔé÷Ï’ùoÞþm·ÉÞ7·¹‡ÔÆ«eà*ìcÙuÇÇþÇäv~Kð]Þ‹×j¡OSULÅ«6ïnÒùؾó—ÜyÒŸ®üïÅO­ÐïÝÃ:7æûœ£óNþåïY‡Ãöïö‡2Üâ}-^ª:ÇÉýç6Ùä­üìKÐ鿚ýC›~w¹ðì¬ Öù©¶ÖâüW·Ê~r3>ÁÍì½§ùWÉúžãOÍþOÕêúÞ¯ãNâÁ<ïð¶|OÒë^‹SÜÑé§|ãè)ïqŽ.F?Õ8}[²ÀÉù_w–;Kûwµ©ð/€}Óá}ü>·¶øƒ·¼Æn[öŸ>úFmŸ¯|‹í…Ư‡íN-íÞö¿Äùëî¿ íâAÏF:'ÖÝóž‹—»æq=ƒZl@e×EuµÉ¦ ""a 3wþÊèm~Íñ¶ø¾¿®ç¿sî¤z.‰ç΃ÔÅñŸ˜zï!ÜØû_¡Ðz9ŸúS›þïÒh>Õ<ßž¾zÇ®÷]jø.¥æn™ààåÿ{ô ©uov‡‹ÙäÐÿõ¸¾ñôœâwý'½øWHëÓ„u_ùÇÒ45Y½ 踙ùÚ}OšöëÛÞWÌúÏ ½Ê¾Û ¦½>,îoú–áìüBŸ§xsËÄ·Ôß9ååøÔM“A¿Ðz<¥Î½Í¿8Üù÷epJz ;nUï®_ÖŸI÷.kêN^óÿyøÿ¾ÔÓdô£æeæ_I÷ÞNاla|£ë¾wzß“ºËsý‡K÷Ìùþ/'açmÅ?jùÚ~‹Îèî5ìóWÐlõ›o óûgÃûß|›³Î›]>WÖxÝáñ?¤dü“³ÄA¾úŸ/ÏvÿÄ>¡à:?+çnÙä.ö¾ŽçÐ}¿SóèŸ0û'€èðÎ6þ>Êé<Œ}¯Ìzü©ÛœUÖý½_—s¯fòO­ìNúWœÚåï½s7Qwq}#ˆº÷Œµñç÷w)æ¿‹ýÇ䂚ÔÇš6õmë5x»í ¿)Í.î­(d®etUY¹U50ˆ B3wÚ ÷/m÷O…ôˆëWð²ü^–ö¿{æo[­GGÐÏÙ~ÍBóxý¿Î¼Vƒo/\êþ3ìyzÞãávþqÛŸ tW#úL¸¾wçò1½ÿ#'ªù3wÈØíŸ ä®x>Ñy/Ì{Mçcðßµ«°µ?;óþ/wÙ`ó„z¬ÏòÏ'ê¼ÖÇÐþ/¥ùÏQÖþ«˜lscª'“oN>ŸäßÏ»3Ü?*ñþ ›>B‰§è\·¨òÛ,»§™6+ñ»~Ðh#Ûóû‡gÈTùÇKé7y“S·~ÎÐüß]Ë{ÿð\OS‡¼þSá}¿œÏî>=®ø×kÿµ¸ íxzwã:¿‚ò²ý«¡¸7îù^ÿAó}-®¥âo£ü«¹Î·ºÒåú]>ðç*þ]áº~~aï¹péŸÏÿ²x^§ßr~eò~ÎG¢ø]ÿs¥ßþkážÏÁn}3–§æÞ§_êý_À¿{ÔŸ«j¾uñ],ýõŽ7ú´GÓ~cò;ÔŽýùïË}ž¿Ò9zŸ›úmië^Hú®ö³r7¾ùõÛ>Ýá/´é_ þYå>?ËÙÀ ú/YDïljkÖÍ‹&ºj‰¹U5DDÀ&37º-ç+¡ºèÞxé¿ÔùËýO”ßÍ4©èâR¦Ñ4Å6¬Ò¦õDQjÛÆ¿±‹]­Øë{Ú ÙÀ ©I(˜@R›–«¬å]³wW=HRèS0„ZªQhB-&&H˜¦ªf´ÓM¼´šf-€š¨'"¬[ôµ•뉂j˜&T‰LÒJí;Z5ÛÝn,˜q1±0H"f’AUÓ]m]QRa0"a‘ AXÞ·oYå;#åŸ=ëø»àü÷—³óÌ,z}†,Šqâõȧ-\ŠqâÑ~›zÞ¦Í6ŠìM¼¸ðuÛwSBÚcg&€ ‰B`WEq9-\ÕÏR˜‰ª)‰‰ŠbÑU*f&"&*ªŠÉDAn»­- €åH I[y*µo–ÍÊÔUjìõ›|z_\®Œ €;¬œ½§©õÌ|ìz(<ôz˜óñè"ZßÄÆ†7ÔÌh²¶Tqöü§…ç³}ãâž~Žî¶â4ñÑøD#o”¶±ªLm#V–Î5„l£[3¶jÊ¥ðc_½±»fï7uLÓ%(š©E¡J-U*oc_ÆÍ‹ M·ÔuùøC¥ € !ÀL ¼Ì,Í-«µQV¾d ˆSj¡ˆ¦bÑ‹ULÓ1M«–òÒÍÑŸ ¨„‚ MütN]‰»Kâ¯Y½`=~ãM¸óÝË7yûŠP)E¡LÓ5R¦Ð…7­ÙÙ±áiöúŽ·? Ž–ˆ@E 2²ðòôönÕDëæ˜S0¦i˜S4Ú‹V"i´)šmÛ®‹ÖÕºéφ€@@ ]0H =nãM¶ó]Í•Ì{œýºé¦ ©¦-SM6­QM6Š¢šmXƽ›&£m©êhaŽŽI@‰NVV&V¦ÅÚ­Î µR¥J- QhB&¢Ð¦iµbÝt^¶¨®ŒØH˜H H Õlµ9¾±µ¯_V®|ØÃ¦Y‘‡”âE£.œX˜Ê§-\‹V©½hÕlµûú¸KíKQtZ\"Ú´­®D(‹‘*ŠI{#ö¶{“iŽ÷"ÜLWDÅqDZ+Š"b¸¢&+¦”™¦ÑEÓ–”¥1 B$˜ Ù5¾cU'XËǽh¨ Û_ÕÕ¯›m:¹¬ìãZ˜ÙF´lc^6¯KaŒöØ\ÂØàÍn3'\ϤÁŒè´aFdLaÆdLaÆ\Lb2¢Ñ‹Ú1è¯6+±a’—âȽEÕ¤ÅÅ¡qlV V WTM  ¦*J”‘JR¥0„JP@š÷x²k6»+Ú8×ël´ÍJ­ãæÌ¼î§ÛØÚÅâ^ƒGÐÖ¶2c Ѝª¶¹4È ””A“±Öìtö²ê¦ç?n"¸‰¢›”ÌQMÊmZ)®-S\Z(¦ºm[vîÚÉLllœmÍjPËI€€1$ÄÓT+ª™¥Ä˜˜(ˆ˜˜DÄ€ܽ“‡.¥U9±È§Òëæ§9ͺØX“‡›³šž®¯-“YôS­Î×ÉpšM:Í´Yá-zo5ÙÑ›ꦨµs€ "H˜¿²ÖìtörîZ¹Ïܪ)´)šmµbhR‰Š-\µ–˜øÙ8ÛzÔŒ´Hº*‹D\¶W15™„DÌ"aDÄÄ@ «2jÖóWI³Â¯:¶Ó®[ØÂÆmm´ÚÛÄåo^ÒáYÞÖª“g ¶Õmêv¾Ðó¶÷³næ†{^CÚi¶±ùdÇcžú¨ª¶¸& Jý†»a©³—rÕÍ º¡Me oU3L™¦ÕB- &›E6ë·’˜øùûZôŒ´@„0&*¦K´WM%4Êf ""b`D€˜98yXräj¶š¨R3âlõ›Y2q2ððädzzÎÖš€>‡Qè´öqtq³c Ø€R=&ûÄúþFþN&]­LÞÞf æªzªj‹W0@L˜B ùøÚ»w-W¡·T)„Ò‹DB- f›U fÍ6Šm×o%,cäcí`“‚‘‰„‰EÙ–;Ú˜›‰‰ˆ ÀÙÙÇØ`Ϫléµ0ö‘‹Žö,B`6ùµú{XÐnj€Òy½¦ Þ‰Žÿ×g`÷ùÁ“ꨪ¶¸„Ä©)€ ” „óõùÚ»W,×¥³\S5Sh˜ŠmZ©ˆ´M1J›V(šo[/XÙÀƒ%@@‚` Spº1ÚÔL @‰UI;kšêõ³Y²la €+‰ €fáfRþÖŠ±x]/%]î`Z &ÜÄÝ›R\ŠkrW Ô%Z„+ŠR¿™“¯›:¬Zµsäň/ň˜¿M”ÅØµbÔZ.źf+¦ˆ´Sbíœøˆ^’0$AÍûw)5Ò¦&Ú‰@ ‚A Ü-®<ž«Íî|—?jÀêh€ÿÄ40@!1 P234`"#$%5ABÿÚ2÷ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀi!”´ ¡Ä8‡âCˆq!Ä8‡â l)°êËßH$ ƒA Ðh4ƒQ¨ÔA¤(öXû±ü‘ GHJP8ÇãcA Ðh4  )i¤8^øòÇ–d I‘¨Ôj05F2 ¯á'ò]vG ’ HÔj5F£Q¨Ôj0 ‚ˆ,ƒäùë¶@ˆ````c `¿„ŸÉuãˆÁ!=C ¿=vÃ@uLXWð“ù.¼q$'¨aab@wç®Øh.©ƒ þ%׎#„õ (,HüõÛ Õ0aa_tId)8íäºñÄ`ž¡……‡Ã¿=vÃ@uLXWÝO³©öìÏäºñÄ`ž¡……‡Ã¿=vÃ@uLXW܈²ØÎrÐ4ã²?’ëÇ‚Bz†üõÛ Õ0aa]‰}… Á-x¬‚Vnd-9#ìOäºñÄ`ž¡…‡ÃŸ=vÃ@uLPW`_`&Â[ ö#÷ó ƒØ–ÖA² 8ëŸÉuãˆÁ!'ôdddgË>f|õÛ ‚ë0 ®À»òöàK™{—Ð×±) o/n¹ü—^8ŽÁ(l6 †Ãa°Øl6PQ…ß=vÃ~Yò0 qIàËÜ–Œ’“ü¤³Éö^äCS˜ÔƦ51©LjcS˜ÔƦ50ÁFÃq¸Ün7 ÆÃa°Øl Á˜x8^øòÀÀl7å‘‘‘‘‘‘‘‘‘‘‘‘Ÿ5û“kÀöP6A2=’s=‘5–Gœzqéǧœzqéǧœzqéǧ-j zP=@õÔP=@õÔP=@õœsŽqÎ9žÀÚÈá#„pŽÄ8‡âCˆq1Æ8Á#8ƒrAÈ9 Ün7Æãa°ÛËYö8ìR³ ƒÉ8½A¬Ï³iÈh2C€‡8pà!ÀC€‡$8ˆ:œ—Ì9‡0æ1Ì9‡0棔rŽQÊ9G('}Ú<„ Œ¸ÈqŽ!Ä8‡ãcŒqŽ1Æ8ƃ@²ÀYàn7ÆÃa°Øl6 †Ãa°È/, t±Ç·bÒƒ§“ìØøl‚R4 ƒA Ðh4 ¤ÄŽÁ?,„| F£Q¨Ô``````;ØŸ`‚ öìˆñÚ±ðÑÀÀÀÀÀÀÀÀÀÀÀ2 ! HìòÈoà†:f 8ìHd}böxÿ „u$ |²ø.©…‰쬔ƒ<û<†B:Š ŽÀ¾Y üTÁ‡‰ë—ÐeÔJ|–hðÈGQAb@°/–CÕ0aÀçb@»L zIòQƒûD†B:Š ŽÀ¾Y üTƒÎÄvV£Q¨Ðh5ó3 <ý¦?Ã!E‰G`_,†þ ªaAÀ¾Äv$}SV•ŸµGød#¨ ± Hì åßÁuL(8Ø.ÈŒg¤jyû\†B:Š ŽÀ¾Yø.©ƒö$ ´% ý9°jûJ[5D”ˆq$Gød#¨ ± Hì åßÁuLX_b]¾FÃa°ÏÚH²–Ȇüÿ „u$ |´ð]SØ—ð?‘€IÇš¾†B:Š ý|´ð]SØ/àQØ ,} V ”„†B:Š ÿAAEq@ º äGè—ËAÕ0aa}‰ŽÖÆ”ãèvA$9 Ô2øh ddddddddddd(ÂŒ>óm³qVÝš©©fÚ§°–¨™vñ¦Eü-ÒßY|´ðF222222222222 Á……ö%ü ØÙF¥æóº’Õ±ù1ðÙ„¨n7Æãq¸Ün7ƒP3‡üí â2êõQiî]’™Bœu uì½i.þ¬¾Z øÈØl6 †FFFFFFFA……õ‰`£¬Ç¤pJOð©É§Í×5'ÜüÚ_² Oç!ÎCœ‡9rä9Èsç!ÎCœ‡1R¯!Ôdp†cîåŸO(tËþY©ÖZËÖ’u£ßŠÿMWâCˆq1Æ °`KöäƒrAÈ9 äÆãq¸Ø(ˆj5F£QO§®{ð¼:²áôVÃV}5±ÿËÓq2ǃ!7ªõ%j-Oì„YéOH)ÃÔúµ¦3ÆÍµvqSíä£ÁIwcú Ü|ãÔP=@õÔP=@çãÔP9Ç8K›£aÀ)±w~\nãæ¨0Ç÷mÄëJ¾}ÐlûðŽÂ8GâCˆ°709G(åƒrAÈ9 Ün7Á+ËQ¨Ôj5F£QAžTÙÍ_­<¸ï†o ›´ÔF¾&6å¿_EešŒê1+޼ý’|ÛtöáR|GKe¬%G“úä†FFFFFFFFFFFFFC*<“> º{ËŽŸîÑ ÛÍ_ÜÀÔj5Œ  aпžºBz´ó?QFÿ—â!ÿhþl™êb¢~“ù.»€‘i§ü·½™ŸîôTÿvœXƒu«3ƒXôamš<ñ˜‹p;Ä“ˆ4…2§ ¤šM˜n<¦:É`6Â4ÑßQ=Æ~†¢­ÑøCØv2ÚòKf°Í)穎´ &Ÿ&b-àͱ-äË¡HŠƒA‚I˜4™}ÿÜR?æxŠ`Åß©|ã;ÕÔ¼›Ž·AR2v#Œù%°Õ-çC”‡› mH42¥ÃÂÐh0†TàT7X ÅqÀ¸ µ÷bžëáús¬`8ðzØ ²§Oð‡´q£lÒ“Pjšë¡Ê[Í… Òa)5©®º¥¼ØR 'e5½Qgª.5ÌÔÃl)Ó\#,y%°Õ)çC´·š I¤d7 ǰÜkɘ.>¥¼Éc¡ý‰Gý_Iü—]QèÎTUL¢~·»nÛpå[È„Ì2Ä[û“íú \I0ÚSsÑÒTX2,€©ÊbH)v#¢§j§Ö@´bF'iQbuÿ·í¶)qê”¶j1¦(æÛ¶k1šC ªÖìZ£UÚ:é’EŽåJE"Ô‰Li-°ân[M‰q— ^¢Ø²Ð¦›f"~ yh»-§9F£9Q‘O¡B£2ÅJ+êz;r»íò§<”åvµ¤ÜÆ.»M¨QÖZ«ÊŸûŠOüß}ÖÌE¼»&€pÑuÖSK§ÌáL¦®{ô+65=¦ÛŽi¯Ú‘ªQåÀS2­K,¥!¨iÉv$ym×l–ý].ʼn“Lˆ–®újiõ!`ÑcÎUÑKˆÅß·Nµ:h@‚š,¸¨‹—R£ÐcRX¸¨ìOƒjRãÇâM«6ÓC‰ôÍwµj6¥œu›œ™4èÓ¼­ÂÝKf¥ÚvqÔztr$S¢Ìn¹dé:g~ã¨ämû ™ ¸l†iÔÛŠÄ™-*©ӫͶn*Ò³}bcSãCDºli­Ý¶¡Ó^µ¬Ãª7Ú¯4w©TêJæÎ¢[q©,Ï¥G¨±rRN™7눬‹úþ“ù.»"?Íà:kj³•ä¬ÛawS­)Û…ÉçÚ;°ýmYn7<*‹s…e¾Jt’ô˜G.F¥A¨VÜzMµ5R¡ÖÃ=Ë"Tÿü¤@LšÌú¤zq^2à[4´Ê™vW N»ä5.95—Ý,¤Bn9®EŸEM> çs)Y5·šhÈ‘qÖæþM•]yÉV\ç%û’•Ó-zcB¾g-•Ū:ÛÖý@ê4ûÅ‚vß´«pÒtk­Ä¢‹ òï•;÷4Ïùõj*+3 Z°`bæ‹Ij»\v© 2ŽEØ´$Æ{ÜgZU÷BdÜÓ^M.›U¸v]…RvRkÏzji^R¥Ìi[7âýTþošÖ%ä­h”«ê,»jæ“T©H<1jS“É:·žº¥Q‚¤Û¿ò®V}dÿìÓbB®DžåU´×«ÒÞj‡KŸr½"u­=Séw³$åÜ£F¥-ö¨tÊ¥Ìü™–EEsaÖåœVýÂý^}Ió~!¼Âë·»Õf|;÷jë^”IG—­*1Ô§N’Ý›.ï©–­ñˆÕ˜%P§µtI¡&ͬ½Trä÷£Ù”bdTkñéÏ2ê_kĘäR~¶ÕªšVHLOÔ%×d0,ÿÖígêÓýßkÙªK9zèªìí¤éªMPñO•îýŸ ë‘Ǹë}Ûr ¡Ã»g&=>Š{Ôÿþi(°.zÛ“&Óå:ó´h¾Ž}Í7ª(Vªðúw+–}E2‰LõU™n85CrT»ŠáI—%#ÚÒÊUf»êê„"ɵn¦éë·YÕµe&E&úË‹ØäeN¼ž&é ^·/ù®µUžOÊ™ûšwìdËô·–ÅyÂrÃò·¡œ¹­¡0¢\/96u•CuÙŽ8–[¤Ô:æ©Dõ°kt·bJ´.vègt^¿Š³G=æ±ú7òóUd²åŽÇøV(Ï~¥‚_íg°Ù4Ñ蕪»²fFžêܶâðsWoúÙ¶¦§½ÉaÄ?Mâ Ãn48.J‘lS•N¦_u·§“qüCÄÁ«+±k° Æ¼î¶%Çðä¶—q+Z4ãÿ!?›Ã¢ÿõV´U–ò<>§“üC™Åg•X•Rœ_OUðÛó\Dj§>ê(”‰µW%Ôm¥šèÞ$Ÿõt"9’‘”ý'ò]vC"ÏýZ‘â ¯Õ¥–d³k_áôÉï¯YÉþýhñM_õI·™â¦Ô©'Qv%,R¸£AEf¬åAëwÞ¢¿Ó¹¤þC”ç#Ö¬oQPü©¹\äœ<;s¤þÚÑŠ_‰TbªlHÖlF—"£ŽÍÓx*¢-:¿¢©!dâ+VÜz²käŠc§”*¾ý1U[ªMM¨M‰(^†›~Õ NŸ¹çé¥þæ´;ÆIǪR&•BŸ|Ò½\Ûãpx{–¥1¥?›.)8¹h¬]W¯«Eªqj1¤"SŠzÃuûNE-n%H;};MG²/eíU§·É"†Ç¥¥_‡þ¥ßÏáùµÙ¿gzjsªÝp¿qm–(¾Ì‹–qËÈ·cúz=ZÝü^T H­^1iÍ˪¹V¨[ÌzzGˆÏfxKÊ@7³ðØ¿ªè ûo ˆIk™~!ÔøÛŠ{Ê·­Ä•ÿ“ÐeÍÓ›Ó±HoE}ò]vC"ÎýJ¹âŸ'õhå™GúwTž(ª<ªÍOõ\Šc~ò©…¬ †¬õ=ÙUéÒàP¶ 5%{§ÄIz‘ûˆª«ü•ÿÞþ¢¾86ydë²ÜƒO¨ÞsTŠ›² Ôj :m*Ô¼¸ÃíÉn\6¦³tPŽ™$$¶;.ƒÌõf¦Š\*¤ÕK‘õRsÚ7ˆJÄÿêù²™ Ý¥Sç ‘ýÚ£ë©zÍ5É«½ Ô£PBôU¥xc3Z}†äµyÛ_†?k7µKÿ.µïQµ`œº‚KS¿¿å9ùüÈW±˜RLZ…š˜¿¤òT…Šî•QvF6*èÿݺåúZEˆÿ!Wõ4ªƒ|r Ì3 ÇØA:Òý9ÊMQº¬kÚ);LY]½Cr£% b‹ç¸RgŸ"iJ I§è£~éf|D?óèUB™ Rfž(¾¶#Ì›NxnæœÏ¨‡XŽmJÔq™†¢-ÓzÐÅå‘Lz…\n³[Q¯÷Jü·õÏðî•…Fš]öœÒýO“þÈÅÝ+ÔT…?÷4BÅ&ÿ‘ÅMpòºR±&ž¾H>#Ã3pýäRˆÑ&ù!øùŒdq™ ¿-ÔY¢Kýt~oç_ßò©êÖm=||HýÑhÇç©:á2ÍzO©áÊÆ©¿é U]ä“KýÍ8±Ä5f§ÒfI¤‰Ä¿cÌþK®È`$YÄ.5kNtÿ®Þ,Í ¼“öÎý;Ó½2ù­§÷ƒU…ë¡Ï€ã.Ó©Ìz¿nF§Ò­$ÿ¶?bº_æ¨ ~W¥šË„óWý ÍÖ£)OY”ÿGMñ¬JwÃú‡ó-Šï·—[ç]r‡d2pm: Œü¦¥*ˆƒJ*QÔKcÄÒ˜ªùò ~õ?—Äf¦)B“Fª"«LV¦7ø>TJšgG}†ä¶Í»—.‹ºT[2àAÉu¤>ÔÛ§Þ£PÙ£5~Ü(}Tžštw“!}×ÒËVXŠk“Í·hÁaËU¦QW¯9ÅHž­¤ Wî` øŠöÕ ^ÇbÜ% ò2QK Ãšâ‰Gw\gS—b\)Š÷ÉL·aMq-D¢Å»«ÇT™bTJ%L=mA}êôø4je…).*TVæ3!ºm¿׸›b¡ì´Í²âÉ}–cP ÝµõU%£Ý~§»ùÝ)N{®œ­dQ'érèñg;{Ì€Å9~êé!Ã@D¢2y²À?’ë² þkI‡x;„˜¦Ï8È»¤8‡œäP¥TÕOyÛÔÍ ó—M*¤Ý.ÂJ¯Vµ¬\ïN¬ÖtŠÂ©ª7ì¹,¼ç*ü©Õ7 »Oñûs|E-*µ·ªN‚< %Äý)Øþ"´h«x„ã­Ëš¹K‡5qWKñ ÖP¯Ö³z¿PIIW+´Æ˜]é1Cÿ¯˜yÍH~öšôR|Ô‹ñÈ1+µ×jÏùÁ•é^sÄY*EV¨åMñœ Èõ%Õø‘ýª½Û&¢tËøÃñÝOÄcSsêŽMr4ÅG]Ä£#ÿÑ#ëZ¾ß˜Ü—ÔòÛ_­ÛåtÖª~#lÌé˘äŠˆìÔ†+·ËõP®§iUï‰UëVêáp¼E”˜õj«µIL¼lª…~=· êPt;ؤ``úä`Œ2þÏÃa=C ‡;‚ì aJò4ÿgá°ž¡…CŠAv²%Œäƒ³ðØOPƒ¡ÎÅ »ÙämüŸ†Âz†v)Ø?ãlü6Ô0 ès±H.ÀÁÿgá³ 1‘‘‘‘‘‘‘‘‘‘f 8ìR ±?ãm% †Ãa°Øl6 †Ã`f ÃÎÅ ¼²23Ô0ÆÛPJÁ89G äƒrAÈ9 äÂÌ,†£Q¨Ôj5F£Q¨Ôj522222222222223ü!-)@¢(z5FaQ”@ÐeÙÁ:9G(壔rŽQÊ9G äƒr ²1‘ Ðh4 ƒA Ðj5F£_,†Ã###########?Á1ÜcPn!K$CQ¨ÔhAQÈð‚šR{1‘‘‘‘‘‘‘‘‘‘‘‘‘€< tTøŠk6bà%è`)’0ü?e Ò}bë 7ØP?¸¤²kF;æ™7 – <†~£NDˆÄ¢Z4WPÁuÐë˜0 qe!iÉ`û¶ÑºškR¬È$ƒšAs µZaƒrI@•Ÿ Ë"\}ˆËRë  XÁ…ëŸØ²ÐÉ$r… ”Þ½ÑDfu/€ã¤’vY˜5¾¢<åšC2Éa'Ÿ7’”Þ‹ê]s¬@þÀÒ=œ^ Õ‘Û ËbZu>â26Z¤ŸR[¦³è¥Fƒ+!*ϜֶIôÌ]ºÆ (X»òl%¢ìK<Ÿ› É)²PSM™vÅî#7ª_BRÍ]B<OìEäùe.~n‘‚ë #®`ÂõÈzN`%à¯r?Ÿ8äá$àÜ3í£§eþT¾­—ÕŒæ‹i{p½¤§t°@G\Áƒ× }ûjØoÍØÈµ'U“íâ JsTõà9ý$ñ7õ:GØ #°0`úåö/P•²F 8Á 8ïsXCëÙ]x*ÂÓ𿉩Ò>ÁƒÖ/±à4½‰ÅêJpÕݸGaðãþY—:GØ$ ddg¬`úÉûJÁ¼¯¶FýVþ$¯T¬ò®é!&2222222222223åŸ#ë—‘ýˆÏ?lŠ_ÝO²g=“ìò223ô¤ÂLl6 †Ãa‘‘‘‘‘‘‘‘‘}bòÈ3þ¿©ná+uôÿÿÄ4 !01A23@"Qq#CPaÁð4BRr¡ÿÚ?äPW#LÀÀÀÀÀ” ˺\ LLLK,IrW½|˜Š,X±o•ùêSé¾É½ëäl¤wäWëÈRŸMöO’½ëäl¤wäWäG©O¦û'É^Å+–ì5nSäl¤wäWäG©›ì—%{7o»Ž/’ù1\¹råË’e~Dzè\¹råËŒý‘%áÜräé6h³Eš,Ñf‹4Y¢ÊKO©®tk£]è×Fº5QR9šLÒf›4™¦Í6i±B•C3333#!»–,X±bÞÑH²ê9}9T☩£MhÓFš4ÐࣇC&dÌ™“2fLÉ™2`Œ‰‰‰$Mñ.\¹råü…½ƒäß…¹t…½#iäÐó&O¯!{íh‹zFÓÉ -æHŸ^B*Û©ÚÑô§“@[ó%×¹¶-á{{j"Þ‘´òh‹~Dºò>þ×MšL¢-éO&ˆ·™"]y ›kä$—oHÚ|täû.=wh‹~D¹ ø®%o4VRb‘‘‘‘‘Ù´øP¥ŠO»ž-Âw6Ÿ$[ݤ\¹råË—$KÌZíü 5Âþ–>1­câO‰>$ø“âO‰> —êÙ¯$3›_b”ŠÔò„ @Ñ4E, STÕ5MSPÔ3¹Ì LLMžœ\x$ßöBS”±½Œ¤Õã+• ¥ H—/ìhÒ‹Žs+ÓTådB•8ÅgÜ­ 9¸ò’áàÝß‹älå>·6o$ŠÜ)~F¾Xý‹,2¯! zŸ»?ɲ¿ÕH^I¯gÜÛ=fˆWƒŠÏ±Rz’r|¥ÐŸ—qò6q¸Â/&ló„`Ô™´4é'Ü•’¼º© á,aæê,*ðJ.ì[.-º ìé«Ó4)Äø²¥ŽtÊpu%ŒM Q\x•([Œ:Ù£7ýp’ùRV¼É(G„¡b¥<¡Úü|)ùÑû•?&ͪú"£Ó£ý²u1ÏJ>n%Z ,©ô#³F>~¿D|4*p§Áÿf…(ùÊ´ô§‰–.ɾ,ŽÍµöU>4…³Òoøe…Ý5ÕNŸ O…yÛ±£E}J´]9X†Íêuú œ)uŒ!~…j ¤Ü£";,xF]XãÆÄvxCÔêKgŒÕéÙ£zŒ–Í{i÷4h¯•²­7JX½ÈyJž]ÇÈÙκìlê:m´m>šHªµjaÙu% ñÀòÞO±K%»Èòx¥œbÍ¢QrrŸDB¬U'(+Ê„•8þK%S‡GþHSÓŽ=äFruW‘?I±Êq¤?ÈšuVeúÒûp#':RRìMÚœÃ=[ð»)zˆ§“«ŒIg.㲄$©8NSï.„£…|ކͪKòK…ý”¼èéRrú\§+TLýÙE÷ÍQÏ xQ±´AÔŒjGì-•ãv'óÓd¨Ï7ÀýÔ¿¯ðB2Ñw]ͦ.QŒÑZ0ƒû”眪H¬íA/©Kþ?äÚá';¥Ûu6…jˆ”qð|Šô¤G…8¢pÔÇBnò¹89ÉN,Ë Þâ¥8;Òcx^îò2‹Qmô*Ë9¹*¨ÞèÈ9Ap’±^²¶(Ô‹ŽœÅ”³à|T}?úºV‹Mªƒ»wl“ŒžY˜ÒÿÌÎ4ÒI߉xÁ¹ßÂŒ”*)2RŒ#.=HMÓ–HXÉçMØ•zrZs•ÿ²9ApŸâ£‚òº_#Mkaw{È£58`ßÍPW¿5Tø£â#Æ2|Y^qÁSNå'ŒÓeJ‘Š“O¯„*F´RnÍM/ÔŸm_©wÐ…ãÆœŠÕ”SŠwo¹NJ¬¿N¾ ç•ÍM[TR³×¼zýH^>œ•ŠÕÒM'vû›4’R‹}M¦i¨Â=ŠN›']Sœ¯¿©ugàù ú?r|>_¦ôŠœ„.M÷SdUÉ/§²{ôaœÔYÓ—Áœ%$—HŽwfFFEË•9\‡ì£ŽVà…6I_Šö*χ>øs@Ð4KtNtúÍÚn±kÆ©ªjš¦¡lŒ LK.\¹rþÑ;•Çáâ9ߨS,X±bÃEnL9 {ËÚ'c„ÌêJWö4…½"·&†=åíS³&îý•!oH­É‡!ÿ†¦-æVäÃÇüu1o2·&†>B:ÿ L[̫ɇ!øê{·ðe^Lyøø333333#"¡bÅ‹-ãåË—/ü2‹fk•›5¨ÍFj3Q™³6Gæ0000111,7båË—.\¿ðQƒ –ä©&J>Ÿ!’÷*<9ð†^HÔ‰©\œ1|úbßd½ÂVâÌÎæ¥vyQ*—鸤ãÐ…L¸? ‘Éséò/n¬OÂGqÛ·.’îNW{ôåuàø>u>L½Âù‘ƒÊ><ËãE'ixOÌùÐä¿s—Ëνùëàø¾tK—.\¹råÇü|äV••·ÿÿÄ> !01@A"2QaqÁ3P‘±Ñð#$4Bb¡Rr‚ñÿÚ?9N²t«Uj­UªµVªdŠœÜrÑHî+:γ,Ë2̃“ ƒãGNEbyWWWWW@¨Ê¥éÈwE/]ð£C|héÈ­OßRôä;¢—®øQ¡È> ü±Ó‘ZŸ¼j—§!ݽwÂAð$Ù\Þè8PéÈ­OÞ 5KÈwE/]𘇠øà}.=Îx„$täV§…•eYVU•¦MÓîŠNªÊÊÊÊÊÈĪ>œ‡#Éç…¨GyŠ‹“RŽðQõLéÈw.û¥É£ÂÔ#¼ÅEÉ©G¸nΩ9G‘nû¬ÊýÀ_ÃT#¼ÅEÈ*¥à˜™ÓyVVï² ð•¡j…PŽó&¡à˜™Óy–Vð¯~PŸ!w}B;ÌT]úh8;¦íB;Á13§ ýÂã”]=ùs".ZAN˜²,‹"Ȳ&µQ÷cœû-?UWIUJ¦w­ï+³—Ñuý»³¢Õ•eYVU•š™Ó0 3OŸÜ3»Ëº(óq=ï¦Ì¶5±-‰lKc[ØÓFŠ’³+ TÖ­»ÞV=6£X=ÿB°9téþem+i[BÚn¢ÙÖ‚ÐZ Eh­%§de¨³¬ë:̱jŠæ?-8ôPš¦¥á™ÍϾߒžž¶‡Ó{âV ˆº¦ðËëeeoŠâf€ÁrUQ¬§l¤ZëƤ¦ŸJ!Óª§”Od|© Ü€¹Mï9j¹ù`rÃþÛä±7]ÌXi´ 2̃“Jƒz'+îËêAýdÕb‰)^±`„í­øx>Ñ?ù†`XS2QÆ=Ê¿5Sê±Ö¿U b.Tž²ƒÖÜ9k¨aiˆuTó$.r©µªÛOJÒT8sò¼wTbB#•œU>,/üQeÿ`È}\*Ìe”ñ5Ìâ\°Ü_lÌ$!Tö‹+ín‹²´é¸YÊY[ Þx7i{DÎõ‡âqÖ°ž„*Îж7d„]Qã;CÃ%º®ÅKè7‹“qº€î *Z–ÕD$jÿ˜‡_Gý ¥õ ÿ¬ãô+«d4Îeø•Ùêbé ç à¤‘±73º)ûIgÚÜ,;ep ð!Vö°¿$"ê—´My´âÊnÑ€ïà²ãðTÓŠ˜›+|ÕF8!©ÙÃ|ÀüUn5)Èܨq¦ÔµæA—*ÿ±_SÑQcÆJ,¾ìªûA¥.H[{/ùhE(©wšÿ²¿7pøñT•qÕŪÅ]²úq •IÚHrÎ2¬V©µ“™#éeIÓÈ~J£Ôè†Ü ïG2­ÇÛ ôáTè¨~œÂÅVcÑ@ãc1T8³j¡t¯á•;´‡SÑg¢ ™µ‰ÐîL,åOënœŠµ_MdU, ä9UÄØ^TaÓ¹¬ FžYìUS©î:¬>:òH²‰%È΄¬JSÈÁn ’•øŒùàm!ÃA5Ëÿ%…ápÉIšVܹê¿ýOúÿñcÕ†L°7â~Ц–ž“ Ê}oª¦21’½žÅ€²gõ¾‰Ø|ûaÊÛ6÷PŸçA—ÿ%ÂÆ±²Å`@˜ž=é¸eFՔ޽þwMS}™M/9‡Š¡€WT†Lå ,ŒhªÈµ;~%Jz\0êzĵHdf¤ŒòiX t®uòU\ÒV–µž+¥Š’V6!n¢Â8PGðRJûÿ—ÕbÔPlÏŸ/¥d@s“;>ó^çüVm9K‡‘?UCƒ>® lÖö'E«PÊ@xªÆâ§‚8㪥¨}&÷î<BÉg]K@ù+LMg ÿ¥["ª13§ HËHÅT Øä>‹ª4´žSÁ`x|SFf”]b4ÛIc>!WSÓº€U5¾‘²l®[ýÇôU¸y¢Ž78ñrÀI4cçùîNÛ‹¨¸:r*–'ö+õܱµù,..åTqßôX‘õ ¤ž¡¾ª¨°öÓœîâV7öÿ%ÙØ2S™=«´½QÀ¨Å©ØÆGó²ª.}IöÜ}X]I¨ï÷îC …”Æ™£ªš ¨e³¸#ûü–ŠÎŒÝS¨©Ìš¥¼V/S´L!ËóXu6ËgŸ|ÿdVÁ%CTuM‡öŸõû੦mDM‘¾kq’µÿ!ûüTX-]UŒïà¢ÂᆜÀÑÕTÒÍA-ÃØVŒ Ÿ¯‘]¢wó-ø()ðÐãä#³Ô°Ÿü–1ýŸ†Ã¯ZÑûáû üSÚd—(ó'óL`‚›(ò Í<ÃGÖDz¨F…CAò#豇ƒ@åÙèóT¹þÀ¦û2¨«XÁïR6ñ©¤Øêšçi·Ñ>²âÕs¸,Z¥µÍeC!v~©¦!IŠÂÊ–Ó$¬CЯs´É6xÄ`’žmˆßü—h@qí]Ÿ¨k©ôP±wmuÚlø,m‚*Æ=˳qñ’O—ïñ]£ûXþEƒHÑE¿–ëšÕèOLJŽáÓ‘T±_³Þ°Áü2}ê²–Ye%ƒª‰™ª©%Õ%­¸* 3Ð:J}$ìu²þ Ü×êÌ«ðÊŠª‹Æ8¢nF¬SÛ¢³}aÑ6‹Œ–1¤]a8^ÄÜïõŠÆ0ÃV5"õ‚fZã¦GÏ‚ E&ý?jx#ˆŒ••(v¼ýS°zÉK€?¿‚ÿ…«÷~þK æƒ>¯š¢ÂªRÜãƒ{ª_š†ÔA8’Q`’1+Kªpz˜dËn<Àª_{Ϥ›‡VæÈGÏ‚”ÆïX­‹£ðÁù,3 ”Í´U,s’r&„\…†`ò¾Q$í° ¦3`mÁMÂë_Nç<ñ>K –9Óu*Q™„…aUÔ‰%»Â$t†zq{õ *® †C}ÿ¢“ ‰Ô›0OÃka}ƒÄ,#tןÖXÖ,’ëÂ/uGƒTT8ø4~þJ¿ ©ÚI‰·Sà'EúÇÒr4ôÒY7ö…„á…Úõ²Æéeª„6!~+£’Ž%êV;C-Hl‘ °ìs#dŸ€[ÖºÒ±¸î9Kw…BÌ7vɪ.ANäéqæ9Ö 7y:oÔI¥ž<”ËÜNÓæ¤&¾¦ÍéôMŽÂË"ʲ¬«*EÈ(«+oàœë&²üJ1„ÇXØøTYmkk[ZÚ–Ô¶”gÌ,S°Hæuãu•.(ôz­lëAh-¢´•ò-Uªµ¢Î³¬ë2µÖU•YYYàȺs2¡Ó¹ã3¸&°?1EË2̳,Ë2iTÜ™;®¯ºÞ>‹…sÔ.è˜Ëuð3#¼ÕMÉ“Þ>ÂáFÜ£ÁLŽóU?&N@C>æ™æª~Lœ€†ù §ÜÓ#¼ÕOÉ“äº}Ë2;ÍPr_È}Ý*!YYYYY4(9/ä>î{V™Zei•¦V™Yj‡‚¸W á]]]]]9YYYYYY[îBà:­FûPp<­ VZAi¤ZAi„ÿEj¨V¡Z‹:γ¬É¢ë*ʬ¬¬¬¬­÷ ä Oœ•r{ƒˆL¨#ªdý<Èï„Ï_ÇŸ,™%ÈFâ…;‘§r-#¯s\Zn£“8çÊŽøLñ×6 M\³šãato#“! ë¸ZÕM¸·ºù]Ï•ð›áÝ™GÝ'DÌÈ_Ï—;¿µFÀÑ¿P̦á7M7éQß ¾ ‚Ãu¨%ånf\ÒqäLÛ±y¨ýQΑmà›ârzK§4 rê”Ü›ÀsžU•eVVVVVMß?tHlÒ©Ùw\ïÿÿÄ=!"1AQqabr #2BPRp3@‘¡0`‚±4S€ °áðÿÚ?ÿÊÏ»è^ô9séoý?³=™˜þï¿ë, «[b—>s`½¦5¢:ѪŠJµÈh~….!°3iupQ/Ú6þq*7µº[›CðÓÙžÌÌnÛj¤ÉD:™I{Ì?Zt×1°W >¦zÊ…º ùeº™ÿ?x{;Ò?¼Ì]x0Ü~²¤ô›CU„횃„ùˆ–?¨·ê¤Ÿ*ʽ`”¥%î?¥X‹àkÚYhþí¢îayHÓ¨Ràî™ÖcÖrª7ˆôj ˆý£¡ Ûàª% (2âcÎl¨S„^Ú•œ\ ÅhQ…ÔåiYr±§æÕPø ”bÂVhÞA(ô:©g‘6ÕPŽ9üe%ä¢Vî6Ô¢¡Â®0Þ5jŽ*?Ì×ý=¿SN4n°J='Ûá+4o ”|§U/0ÔýÁil5W>3ªâa.HëñÒ%,y”½¦~†é»VB^Ú²5:²øLÌz |31«!=™šÌõd%Ö‹Ÿ´Û¦ËÔLý5š7J^]Tr÷µV`r-¯!/†f5e2S3S3!/iž¬„ÌjÈK‘-2Y´³!6„°ic2™,Ífz²™,Ífr‡œB{£žýY r5å2S3S3Õ’ÌÆ¬„ÍOÁ6F\L Žæ2óý§ñ;\w#…¥/,¨;à­Xlðæ‹‡•§mHYNñ®ç$Ì*ƒÍ¥žš°éi{57_„ í[ø†‘ ˜tj*/f´Vt \ï'„zn‚öÈò†˜m®”¸Ÿäå,¨ ri„©ÁÀŽŒ-mJˆ·&ª«R§Û„ÙTeîëhôÂU\ðŽ3¢×Ò†ÉÜœàEZTû¥ªRWºc§&ÝoÔÂ\{í0Ó¬¤ò…* u<æ*–Ù‰iÛéÁÀ3·Ñïƒq„#ZÍÈ%?$°ñ5ÆÛ1”7­¨,!:•nLWÒT©ÈîÈ´Èä#µ*b~î0Ó·+é4¸p*¥*]ežšTSÝ)ö%S`¯ë[— ÙžXedOdµUm"ŸhrVÁ£ÓC•ˆ\ãSRÙ’`ijsiR—bƒgdº H·$Ú*ª©ÅÈ• í\4í0]´D Rš­C{7ÏÄé t÷Tñ˜;5ÁÊЊBÈÛ@NÖ®ÍÇœ”é¡ïß0Õ¢Œ:Ltó¤Û¥§k[fˆãÎJtÓ¼ï˜jQGº"ÐÚZžÌ§Uª k€Œ»®-.Õ³òÇÒ©fR2´¨õ8A3HsAªì-K+×Ù¥þàZTQ>Ð¥Z*äÅO:M¸ÎÙØ% mß!Û›ç²ÒT©OŠˆ)¢Ü“h»ëqcZ`ß³¥3*ƒˆÞæm­º; àK& fÁy O¤aͦ{(°áȉ[¸^ª8™–ä›Â<0ÕÕ3ˆESPû\5V®FHÄýàí[3ÀGÒV (óKqp§.³3jÇ€ö‡²ñƒHir3 ™}eAûhRm…Ë©Š„ì¾Dj)m€çöQ2;„'9ÇntÏ~,¡­m§?ÄT ·€âŠí›ŒŒ'Š™÷š>R¶.6k4 „5L8Tei‹hGÍR*Tà¢3»^ú€ŸŠuÚ>Ìü5&µ½«D¹È›ML š¤vAaMr‰rMãÓcuµãÖÜiìÃÚ/îåó¬³t§Q¥ZÙ‰HTªÆçw SÊeM( Ì_kU** +)ýæ‹@o" ”©ˆiÓ}¾GŒéí*ìßýÂTYi‹(…‹_8¥óeÊñ‰Þ¬"§ Â@²ÓQ ¾qÕÍðćŒÀÌ0IJÕTÙ•n!VÿiØì¥;îY]ºJýö¥5áÄ÷BÀYPYD-Ú¶þs ŸZ¿Ì«LŒíuë*hôˆU-}Ùʽ£—Ù¾r¸ç”})†{– M¶ü@᢫ ˆ¯ó'Á–VòÃ^’½có'd§egÚWòñ²Pq›¥Û"ÐÒ¾ÓÄó OY²ÄK˜í~0%Í¥ãk™T_ pËÊ”Iñ ¤'‚"["Ò£Œ°&Q¸ç³ *gxõ\ÙT^Tn$*R_kx†âÙǧR–c •Eí)õݨÁLn_@JAþË S;Œt÷8t×Mhd´Ö9ßsxŽFÊ›“ØÙT\™›J´x°Ê>%"ÆT)c-¿1;KÙÒå}ðu‰ÒWë¿ÌÓü¡”:ÊÇÀ`f÷ç¬vÅ™1T±´ÑúCPî¥Kù0hÈÙ.þ³&1ô—ÞvD§Exí2ã_&líFmÌ©¤‘›l‰Jˆ>#/*&‘S³rr<'á´fÄ»Ës•Á4¯,h%o´nöï¹¶È”©¿j) äNª¸4«ä˜Föu_þZåÞab×¹š9<¥/'Á–VòìûFn6¿ÞO†Vé© ¤F‚Vê óO¼Ñ—šÞäƒRø «ö•¼²€;•ñDÑ”øŒFòÄ“à啺C¬ûE¦8êsÝ*j¡å–F°´Ú¨Çï3:¨ùƪt¹ ê£Öýu/C+·$3Hn‘«S6 Æ^٭ݔ͎«ˆº>oOåÓ`êxˆiÕ\Ja×x:Åj‹°™Æ¨}­Ê#17¹ôÄ¥åüDmµ˜ë›f¬-*)Žª‡Á+U¦lÊ/;f»(nÄÌåÄkmQ<9AR‹‡SÊu:c§&ÍL¤ó妃÷‡=‘ò?Abt‡Ê"86 ÞS¬»˜OÄ ÚOk¤ Ê‹Í%j2‘]€€²•ê *äLC*ƒx•IÞ™‰DxÄ1üÑ´†(ˬÒ@ÝL…ƒÍ N‡UfæÇRÍÈ%:1¼1eæ‚%^k­eæ‚-^ ¾…o(•þÑ •zˆži÷”š•9®ª#›Îw(¼væ×•ÏI^§$1¢ÍÈ%O·ôóÕqúz!ë ¥æÕSͪ¯Ús—´Àw¤d÷·ˆÃ ÷Šàúá‘ñJ^mUO6:©·#x®70¼üBŒŸýÀ¶˜È±©þ ÑÔä›úÌþ`Ã-ªìÔËaSLI=Ýò¥|!›2•`7 2Ñïìá˜x³@ª·¹™ÚþóKS¤ëK€Ý.ØGS B—Nk0Ä}&ŸiQÅíÊ£ùo»»Ð^±zGè 3ðŽwæ°« ƒ E½3š™L¶K¸êjÔ×aó–Ã;]1N6Fï¼Ò ¤l¤Äu_Ë0‹Eßk^þöRŸQ@„œRß"Ý34£{’ØŒ­ow8ÙLþS*¿%&6¥š7JiÉu)”³Í6c ¨¹¬# U 4z”ªnkûÝò–y¦Ì`¢õ1ÃpåÄò”²ÄX¯>ùUy¬Ò)åaÙ§fØWy¶éY{Ä˃Káã)zžÉ…”]©çö…m;v ¼d¾ÝL¾Òýò±ï¯‹(ÐJA*Xr—#ú·¦¨bŽøe.°Æë©Ó˜…]L5Y@=ûá;©±Ý)¸3DϘ…•B¼Â¨}ZFä¦6 `ÑݽbnïÒª·S1–ºò´ÊØídXÌMîb°6±‹QN×¼9L:ÌiKk¾“mŸjÜ#èîÖf7XÔª Jf%¨0÷ˆUÉŒÐú´ÈDuÚ¨ërÒç>ºëöp›ÎëÊew(Ó÷³>‚u‚TûjFSkµTí{Â`ªÖ;`UËÚsº`Ä TÈ÷÷•:žcn{á¥M‡lÇ»•F°©¸÷ÆG•¦*u˜C‡7;Ú~“]yæb?&¼JŠn¬/«ð”Û=ï 7?˜-÷Œš°´jÕíUÝ+öÒáé4¦ðFÔ%à×_eU½[ä{¥Æbc©Kk˜ŒÁV1¼Ã‡$\”NÆ«ZOàêí›Ã€ZT×yŒ}ÝÀwJXÙ:»F§Ÿ+ʺ8U»­…5šB@ÃJ º˜ÕYuc›4ªeÒsvŠpwZðS\É —@…Äèÿ%;A¢œGWÀøY«¡34pLcÆ1€eÐ!r_U<›ÓEÎÐh§sLY¯–¾ÇLc££cÇÁ²è¨ÿ¥é‘s´)ÀCãtu1f¾‰èàÇWF1€eÐ!Q¾½î-dHbPî‡?I;A¢œÊu1f¾RøGÇF61ÑŒ|.Pß^”ºfÈÍC5 Y$>Ž.vƒE8r‹5ô>FŠ’2F1ŒcË J7Ö¥,œJÚUhdH›Ç!Ùô1AAAÐh‚d“ÂDŒ9ƒ5ó¨ài¡2FÆÆÆÉ$lj¹t'×4ˆò(¨¾dVË ÓZ\ßþ/fkèå1Pe–Ya‡A†ljsç¤!þdnñUÞ!Œ»èXØOØðÀxà<€ðÀxëX¶‘ºÔn7›æó}.–Ó5ŽÒO±.Ä»ìK±.Ä»ìK±.ĉû$#¢x¾ø|è0Øßs‡ø&Y'ÁßIŒº9à<Ãa°Øl6 †Ãa°Øm; }Æãy¼Þo7›Æãq¼Þo7ëY6 †Ãa´Úm6ÔÙÃÂäX7òaÛ‘òþADô ] 3 ^“TÓœ N„µ/I%BD‰&L™2d‰ŽiÀADH‘"@€Ð€Ôh%)¥À&L™>—i· AECJXáÑ,ÇJ‰a?; f&®‘â¬a‡EײéãðàŠ5ËAóõG‡E(n_IˆÅEr W`jèM&Dhhh¡¡¡¢…§®¬câÖ¯ŸIbÂÿ‡Àh0庘šº Fšô1ŽŒcÆ:Øô%Ncâ|*©#QÌÉ®D_áð 9Æ&®ƒ¢›ˆltccÇ_æªpà|¶àj9II ‹ßˆÀh0çšú FŠ´1º1ŒcÇ_Ã…ð1ð§sN!ˆŽ6²!(#CKüFA‡8ÄÕÐbà:±ŒcL:´áÌ|¡Ètæ ŠT$"$JüNA‡8ÄÕÐÚ ª1±ŽŒcl:§KçA?0 9Æ&®ƒ¢¥Œc¤’1ަ¾~¼c£à|…H\‰†þ)A‡-ÔÀÕÐb4pWF1±Õ…_H>cà˜ •’I$QÖOâ4bL™ÑI€ÐaËu05t*ŒccÆúg®GÏ‘:&L˜Ùþ%¯ÈAf¨Pò`4rÝLM]#MzccÆèèÆ:¸ôrå>'ù$¤@“jâŠ&A‡)ðšú FšN*1Œc£tcêÜ|—ù4¤Â‚p$ã Ã–ØÔbkàkÙHºS2KÔr1kdš1²FHÆèëãÑ‹‰þnàV"U¸C“dHÄbæ?û­œ×U¤LžšÒûY~ä±Þn-y‘â]ù©z%Pà : 0àc„³Bä>ù8FŠ˜ë{«XGÌÀC0ƪ%,ó!¼è%Û’cüžRçÜŽþ0ÇþF**L:­Óe–Xcr 3v<£.£’M'ówQ!UO×§ÒsV*ª† ™!KÒCü‘hLøGì8ØÆ|›¼·>=Âd‰p›dR¤ DˆÔ‰¡H‘"4’¢nf~Îø ÷ÀÇð!R”„72Ù˜xÃtŽt™$’I$“YêäB$[zFŽ“%©<ÉéúHæ*ƒ£Šy)¸Ün7Æãy¼Ün§}PØaz‰R¡! g8šN¤{±·Àº±´Úm6 ¦ÒÁi›ÜçH%<χê]-"í/Ãj$’I$’zÝèˆ4 ³#³R%ß4F7“jôeY60¤M§£ÈK+,I¾a˜›¹.ä»’îK¹.ä»’îK¹.ä‰w%Ü—qDN2‡Â"7ÝÓÄݰ|è¾ 0’I$’I$’I$’xx ¢ ŠàÊžhËOõa¯øÙÚ‹-÷¯ÂÀ¼ž%ß ÐTC6ŽÚN . g;ág¹ôk&:< ä"çh4 &Çr< »yæAÌâ죯tÙtØ3_Jp@È"SçQÖâLØåôÌì¯Âø±|‰ì<}”œ°Å®hC&}ÈöÓK=¦‹äa1äùŠìb"„4„/caü$Q‰°1ÎK›Žhm bÙ<†®gvI”Ý hdQ̉½ƒ%C«;ì×1‡*?‰Voc<{a JF׈”{§>´a$S ¤Î¨~QýîÅåóû3b J×ûOo œ±W°ö]¤l8¾ˆBIú@+”=SÞÌó¤‡GQ1€¶}€Öà¤Í‚Yqƒ5²@¦è{ÃäN¨F$ÜŒ\õÍ›L˜B¢ÊPÒEø‹RJ—ÅgD¼i<)±ˆí`X±2I ‰ +×'® jv‡ìŽÜv<·aÙ–ÂMRV5¼3’„íEÜòÝØñ³—nRŸˆßÚ ïÜŸ¹èÍ®ÂBm5?Dw„4*ÀI6_ö%¡ï•ÌOɈ͉úÊÿai/'ÛÁ7c~Æ©)…lvf¨àÌŠI ¦ûÛÀÕ_N-˜ÔÓ–cÆùÂGñX’jÿô/3v_h‚¿±2ˆÕ-XæoZ>°’Y ¥åÿ[–6…¨Âñd𦡟~¡ÿ'¤K ‡µF4Õú§°Æ¼k¤L¡À*(ö¬¡]¡QP< “FrH_¸º2ö•%]Ÿaê~Pi´X´àÈ„ÖÇ+ÛAEë̇ àfS±šycÏÈ÷Øs›h·B<®Êt¤·/ ø#¡1—¸Øãõ{‹¾Ý¿o ‰UÈe7/ ø#m ËÕIVaö-·n©ê™,¶ÖÉÒìN/OªPÅsJÍ·©2Kô³(ªd†-.Ýö‹Œ.× ÅµÉz)ÿçÙpøõg±HG ¤®ÃöD‘=GYLlEžY}ƒö„÷óȲ([Ë‘;Hðƒ®È숢bÎa°ËLrT=Ñ{€X#ôÖËð+7HBCÅW¦}…¬Ö€‚‹ú\Œ#Þ±Õý† Ùìßa¯é ƈ®à¢Å“"EwG“‚Èx/1¢…=ü“––®5ql´ÈX ’cLÅúÝvf¶÷ñ¡hu38ŠB!”0egþ€$²x¥lšðc`‰[cxã¹¶5$ ´Tlˆ ¶OÀtåhòNf{Ž3&î:jͯ¡ÓÀÒ{Ȥ…û‰½~`°¿î†Mtï7%8û ‚T3e»%ØnXÔºŠznk V6vEí—Ø€¶:»¦d‹‚năV;#_ 65Ò-½™¤Ð¾ÆNë¬V†?ÊXéú?HYÜ,>a¼ §g(bÞ1¹]nÄ“·Ðd7#福yÊf7'!å<¶i{ý‡¦M—«F¤©ddÓ}ÖP£º¶BrùÒÆSw¨xM›Ú­}p_Bú®½öZ±]üéz€áµ,¹i: t¢6½…K’Á3É [W]ÕÁ«/É¿—îx\õ0ö«Üö5 ¿½Ý õ5&P"מÎâb?HB\†74x±6˜rzAòßîÿË$™(]“«¢} xâÙ5(ÖäEÎÒiˆò<†%õ"lÔ‡_ì®9Ú6Ú².ÜËž "õæO,°[$ˇ،ׄH{ý÷ Ë Ï´ÛàI'bì´%”Ï.׳E¤ô€Ù2úèKe2Ín®yä6ÔXt=,ZfÌ<-Ñ»öù“Hå¿Ú»BðÔŽÍ@[É–Yõbñ74 F”mö ‘¢ðÖ=†-Ý)rj{t¬màì©Ç7îɆ:]º$/û‚ÑïkˆbÉ0¿Ô5è–%­ÓúTBöÏ r”í SD_»?ìpEN.^E3Û‰¬ ‰(@D@»¼Œg¸H_ѱ£ðGüñ‰Ÿ±4»¯Ó.ß$þ¸g…¾‚ÊOvoú=.Ømp–$ÍîÏ䱂[Œ2f:ˆK¦ôd*›Ëù6¤/eû Ü„=*m ®®Ù,Rý…%?¡~Ë›¹ÂlSn´HÜ—Ú$[I7BßîHÐ$qtá'FÀ—7Ðß85_ 3(B$ñö/²û ¨¼ÈýlBŸÆ£º´­—ˆr_"áòûyF'(‘°óÆ?š4Ó¦~CÉÀ< oPk·76£Ì oȇâì Ú,‚d]ûBQ§ ¬‰ŸÀ¿ÖÉ`–Ç»j9ÇrDR–ù;8H{g–|Ѻ Ê?@ô Ñê(CÅ;–&³<@DñÛ'±%uY^|³µ•±äVÅå5©Qà­¸rÃØ[ü¢}L>Ïп¶pB!7"#×dÉSî#$†æ¬¿tH?Ä Gþ€±¹h}ÂW$C¬:)’²°—ÏÕ´’qû, uBíuhÊÜ „+‘¡ñ.Bþ½ÉÈm䆙Hua,—’ØÄ-ër%wýYòÉ÷_Óïd&òÙ iÜ_pþ Rõ–­øBmâäTd9>·ÅRˆ²bdÓPÁa _0ÌÔ“bc!¹}n:bÊS4#8O>ÏJ¥ò<ï8¼F{þ¬†A0äúÜk™e>èåÚ+ù<œ…z¿DX±ë‹0B‡Îƒ™}Èïy|›û|›–‚–é8|q…Ïè2‚Æ‘ô'ì[šÑ“'ß“aøÒ>h´—`Ý7V¬Nzˆkpy“øfE•w± ¼®·F*N“ø>(­IÝG6vú„¼ÿÀ+b}‹éq6!¯Øß øÜŸ#‰nED ycÔÿ“rdˆ^†º ò—vŒ BC¼É5z!Š)¯-ŽVÌmº::1g|XÔÍhÅÒï`€ä™p‡u£Ewëö-0sjD³ê­e¤r´Ì7/«ÉÖ Àµc ¢ü Ø3äǤò§Ø)2‰Ãù|3ç’ÿ gqXÝwÏIK±kêÍô=D!nÒX@'œw1É£ÙëQ p•ð?û1\‘qþ¤hþ™>Qò„þmãŠQKp¾‘_òbØ$.È&+˜ø¬]¿«š¬PÊD¶VG¬ê+§!°*‚‡Ä= ÈKÃvÂJáö,"2vPBûàn5#õ‹I؇"V“ "/NǦ”‡]£íTDb5)¡…QûB»oo¼UÔ1'ì\ýÿØ=›KI÷¦'±GWB@ºdßt,äúlv–<ødjw--Ël%Ü\M«ÓÕˆŽM%ÑuÆ4²(蓸$?ª£AÖÊïaw*¢÷ j!ˆÔ?aü!Ô\ac)'äE)]H¤î‹rÞÿºäÀïƒø–G¢^C}š ¦òí>£‰d÷·êÅÒfvú‹ö/þÕw¡F%ö/úI<ž¦‹ ü´så "x ¦¢â‘a‚]Ï”$6†5‰jT üš›~_"FáòåvŽ› ü ˆ­Ÿa¨lj?´9Øu½ÖŽ[¾D^"ýšÜ^Ãnn,ïoîh|r°9I­IA94>¹ì‘š,·‰î„é!„NgPƒûAÉöD›Ì—*÷À¨»=Ѭe p–a‹Ó®ßéëA¤eÇ™_4¾¸þCG•‰ÒÕv» ñÈûéJØH-8w TdÏV‚š×M@ïͶBÔÙ-Þ:cxŒ °–¨|ï+4½WìÄši”Õ÷]ØBØe'+²‘žãìˆò†ìÊbV]) Nµ2`ÂQ 8›G«±c=à1 åš o–{ê…ìNz=èGaH¹&}Œ¢pƒKT-M‘ñD¹6H§-¹zÆÅe„Ç1“‘×ÌÛ²ÜqÞ"H»ŽPeNv,IÄ&>ê Y%À­§’T‘ýV"Mæ‰;Äûƒ?×÷ðy7ÀJ]}ú>F…àüö–ùmY.ìsùbiÃØBr¹ôÁ£ û÷DŸg±5I²+'qg_›.âÆ%Kp¼‰4×cb2&¶Â6Ù_Ai%§é—ýAÀ‡î‡È݆øû¼lp¾Cšú¤> æ#0ò|ñçûì8Þçô'!¨qÊlMØÍ„«Ê1áðÏi0xÉw—ÀÓ@v“Ù2e3,j\+ʨô ‘Ͱ…_SìMˆÀ”¦ˆ1ô’+ÇKsîv”öH¼·ðyh|É›’=ŒGÈ3ÄEŒHêœâoÔc’Ú?{ ^ìm½FNd4Å?ŠŽønó„t´ºo0*s¶í‡a9¯¯T@™Ó¼ƒ°]ì‰kúÇv'DŠ'}g§eQÂoyÚ@¹­FèÕÐø^«)ñû-ØœÝ/¡2ºšh_ˆ¨ì±åá£Ð’”m *¶µðÐeAȺœ¢ÀÀ¢&¤JzŽŽ9Ÿ.(· )ð0l½Ñò¹4B™‹÷/Ÿ²#z¢O°T7ð]´p‹Ïq>÷ u‹ù/rmæ‰ïž*úË¡þ²,q|z´bÃ0ÑóËbD¢î“Aì‚1oÐbjetÆymÛh‘`ÒuŸ¸]»¹äÊð;¿'- …Å»æ5cл@Ô– l”ú"ò5“·ià%î7Á·.ò[8ެÂÜávcÞ "ø.oþcËòKŸqçJjöbÊ4'¹¶£þ˜ò—-µ™cS¹Ú %áä„_à˜òÙÍ’–Ø×0Æ÷} ÅC™‘½§É »Š ^×°”ý]¢×áðL‘QMÛ0M¢Ç±õ«2 ¦Ø• ×®Ð1èjLÆäcJ CZ5ä[¿Ýdbµi'Ü=¬ž£Z²sf.â´¼{‹›·Ø"+}MûJîCÑx’a¢çýº`pu$Á¨^Dˆh˜™ÓvIa;!ŽŽÌ#P®÷Ù?‰.…$¡zà äì;–í{IÍ+dô%²„¢ÐO É ÖÁ¶–ÛȉgÖe­z™3ø†h¬W»šÜJè*ª0è{Kj aæÙ¦[±še W‘÷Âg©»'äY4u"Èö¶´Œ+½©[—F95ßD½‚eö2Cñ“Žvh5²E‡Ä ý[$רÇGñ²Ù ÖÉe²(Ya$=DÄ^ðdµ¥¶ÈðS‹< Ø7,²f­ŠìH°U²O âþ6¨W±A…’È6eÎxiÄ m¤I &ǤЃÃt‰pgî7²ç„dª=¤OVH{Œ€!#cÉ dî1®œøS¬1»×†-XÙåÕ6ŽñÀêÉ «&wš%až]fF¸€@ÄÚ=k/¿2`ò>Ú<ÎdÂ[dlòë/½Shò>D²z0¹ÚM$É%Z$.®RI¡†É$llaÆ£>ŽšM&…U—'ÖCÛ#)ˆhtšeø0¹ªzÃZJáãÞ búæÃ9 FÃöYtÏj3èù$’I$’I&‹†|ÎèóÔB—j7YY-_€@ŒLC!È}ˆd2 †C!Äõtí$¦”xÉ‹™8hq˜ëL!u;Õ’¤|ø†e†µ9Ö8#™É$’I$’I"Ïp†ŸÁDšIŸ"p«ÞUŒEø/i°Øm6›iÚl£a°}&™ÆwK—x‡$š[6È|‘È=»ŒÖôàÔ Žg bI'ðb …å¸i Hú=j,MB"D‰ ÐÈ Y\Ù:fH•%Âò¥\8•"DkL9Aä¹0I#“FÇ—ø9ç‹èÇ%Xž»)9bK¥H§_A•‘D1A ¢çø\à°‰œ$9¹ 3߀À.8AA¡D05ò_T`*ºº:±Œ|ï!Q?…N ` ÈŠ>ÓøŽ34càšú ¨ÀU|N¬cçk<ü<ˆ'F—ø,Ž Ž’1’>f> àÊŒFÇÆÝÇÏÞ‡dr_ƒÁVGI«cÔÕWÍY£1ð:::1ó÷†*%ÿÂðS…]&’MÕÐeFàšº1ÑŒ},ÿ…â¸i#«­O• ’1ÑÑð±ô"ÿ 0RÜŽŒ‘¾ « Y§UÕÕð1ô$¢IøN*p£«cu‘[_1ð,Óˆ¸]XêÆ>ˆP&’/ðŒTáI¬ð>’ViÄ\…ÑÑ£ŠCµþ‹‚dÕð>’ViÄUcJ&Ba¹ÿÁKI£¬Ñ±¾T¾RÍ8Н…ð±ÿŽ˜(jHÝ$ll’hÇèÂÍ8ŠŽ’Çþ:5”,Vt_ú-fŒDÉ$l’I$šÈØÆ?ñÃYs[€u#t%š0'€I$’I$’HØÿÇD¤„¡$‘"D‰²Zg^dÉ×—Q´P\ïðI#c ‚#Š?10¨3g‰3+¢Ž‚ó7ðMÜy¿ƒ¢] ø|ì>|þ &AX#óÞÈË#I 7hif¥ƒÛˆç·qÄÝÉîK¹.ä‰îK¹"D‰¸ã ‚†‡CÜšÏ ñ¡€BÔ±!(â«4‘Rkr$‘Îy¡t ‚ ‚ hhu3è¿f Êë¼@°¡X¢DÅ­qÌnnT*É<É ®Ž…ôBÕ¿¯×,=R¬+!ÞÝÄ …´` kJ䆟1æ…ÐåÀèÝD*èHºæµ„+±j£6uR ‰o&PÆ Éo‰¸8#ÕÃ䵕“ÛYóh\SÊP¸] àóœA ­‚ £Q’Hbp橸h">ã$¾Tá TˈZ5(”bCååBèR¤Ñ±ÖxË•-ô I8€…+Á`]žRPG8¸¨µÝóòœŒ¹r¤È‘½ËÊ…Ð(Ttn¯…ôa€‚êð8)¸eذÜ©2¤øôѤ£œŽr—"×’?2Ù œê¡U¾6èø\ü·\œ: È`+©Î1dY—Ïšá˜dùl…ЈTo’Æ>…,ÐÍzé´”,‰"{ êf~ö]”iB×_—º ’>&èèÇW.vB£Ï^×±œ.=XY™—Ð*Q„xc ž^BdðI$“I¬“K*I$’I$’HØØú (ð<þØJ’übÈaÒ}Ënâd’I$’I$’I$’=%ÍÜc Ž<ór-0ü pÍGã&eó¸™$’I$ð„’I5ÎýÐaðÍ&³U&‹T’Iÿ ¾ìËóPÿÚ Àäy nÏ„£kIÔuµU`.¯Úž°¬N 0Ÿ ƒ_¤ó 0Ã,0à <ãÏ<óìpϼóÏ<²¡ëÃN3sÞü¬Ï¼Š=$6ÅÏöõË@‘Oi•2‹n0Ë 0à 0ÃL0à 0à 0ÎV°‚ ‚¬uòl'¿ÿ¸0ßüÅwüè ð öÎA$î1iÀ0à 0à 0à °Ã 0à 2ÃV°‚ ‚¬n:¥2¿¿(1ÿ¿„¬GfsvñØôâSˆ0à 0à 0ÃHúC 0à 0ÂV°‚ ‚¬ zêOî ?ÿ~ÉC1¾ûÞþ²W­|Á0 0à pË 0ÞV§ 0à 0óUÏŽ9ïŒ(»>ð ·/Ú *¿Ë]·*¾ÔöÏ—¡þâ 0à 0à 0Õð=ãˆ0à 0Ï?ßÿÿÿû¬¥ƒ,ä¼Ðçd€[±Ú®“|êNË{?~OLŠ`²ƒ0Ã80à 0ÓÝã 0à 0ÿ £M4Ò ÛÅ‚H{ž,Ñ(õhÜlTñYù4;¢Å%6£b0à 0Ât0à 0Ã"à 0à 0ý(ß¾ûêûÀ %¿·KàBVI²C3ü ŠM`jú¬0à 1ö,0à 0à 0Ã0à 0ýO}÷ß~¸‚ g¾æÜlsO Ú¯öpÔvîžÎÄEKvx(‘à ‚- 0à 0à 0à 0à 0ýO}÷ß~÷°‚ÿÿÖº&¢“ùÙìÌ÷—¼>¿Æç®AKŽrà 0à 0à 0à 0à 0üO}÷ß Œ ƒᄂ1‹Û¼Ž<œ5µã MÝrvÈãèÝûVXà 0à 0à 0à 0Ç ä@O}÷ÞrŒ ‚?ÿ悦ㄸN47ý$æ<Ò‹tâÄaüá 8“Œ0à 0à ¸Ó 0à 0Ã^¢~1Ï}÷Ò‹À!O¯j¼pÇÛIVäG}ôa5·¸¾â 0Ã0à 0à 0à 0ÃL0ֈ_Ýðg‘ñÞ"QQ㎡C!cß4´™ôáÙ ÌL0Ó 0à 0à 0à 0à 0ûÊp1¿kíI¡FN™ †øQ<’AƒhgÞ^apnˆÃ 0à 0à 5%|Ã0à 0òòÃIo¾ûéöܓهpï!Ê»î:VÝš:•åÔ{ÿàŒ0ã 0à 0à è¦ÊHË€-eÏÿç€5 0à 0Ç 0à 0à 0à 2à 0à 0Ó 0ó¦%:i± c¶ÁuÛÿ”´j¸<) “ÿÿÒ1Ú0à 0Ó 0à 0à 0à 0à 0ÃL0à 0Ã¥ŸX\êpFXÅ÷—ÂLÓ…]bõq¦|ÿõ(0Ñ0à 0à 0à 0à 0à 0à 0à 0à 0ó„ôØvYÑL0EûúdQÃMŒžÅ,\ÿÿô 0à 0à 0à 0à 0ÃL0ƒ 2à 0à 0à 0óÙùA&JP »³u{eJ¡ÏÛOn`<ÃÏ@,0à 0à 0à 0à 0à 0à 0dz‹ 0à 0ÂæMÍÀc¸0/¨ 'X:šbÈfErº?` à 0à 1à 0à 0à 0à 3¹øsó€0à °ÿ(îð~qEQ˜]¤¿ŽY=R°¬^Š¿Ò Ã 0à w 0à 0à 4ÃMà?¾2Tè`à 0Ã{ì]}ëECžJó:A"}ÙLF;d? 0ÇL0Ãj 0à 0à 0ãJp 0~°àà 0Ã9aŸ}2¡Iz\"(X¢sž"­ì0à 0Íg°òŒÀÃŒ0à pÃà 0踃 0óòPC_ïTmÈáQ¶¿@a —uïv<}Ø 0à 0ÃNÛ¬0Ã0ã 0ÇØ0à 0Óú 0ñøM‡^ÕŠ?𕆕®öw>¡Ô.“ù 0à 0à Ò 0à 0à 0ÃÄ0à 0ÃÚƒ 0ó<´kzÈÙímoqG©kAC,l¯ ¿J 0à 0Ãl4 0à 0à 0à 0à 0Ã0à 0ÏÿÄ*1! AQa0q‘±Á@¡ÑáðPñÿÚ?Måqí ÊJÊÊÊÄ”>‹à„DF6j#ŸýNZÔ®i¥IIIIQ&r¼‘‰š0™qDi6O“RåËñâÛ¬7Ö+…wy³¾@‹EÆe×(pܹÉv ‚Óª|Áo“ælžÑ–Y5þsQ"J•.y³›Ú埼;ìWÏÑš}WàþÅä(ô6½›s#ó×…Š:\C[—¥NYJñ* ¬²€û¥öˆ…WÎ'(¨,®FeÕ(äÇ´«ØÚ m—Ê¿5Lc̬y|–po ƒ©1ë+knãÑ›]úžlºÞ''âR]¾,J÷uïíA±Ãåî¿ÜâSLüÙÌíîˆF¿#È—ƒüOÛí …¬rŒÖ¼Ö¶î2¸»è<åûž‡íR®ØüÆKÜ)j¬émNAºÂ *ëxYÚù_ë¼2âÚz_زÒï³—:ø€†ã‡¬²®Lýã»rpjîÿ¶ìoú›òºvˆ3˜!uè9yĨÙÉø)½ ßÑ.»'W)˜©ˆ‡•À¬pÙizWDoí½oˆâk|ÎÄEeãÊ3Eы𢩴%ÄÄ‹m,bÇàÍcè˵ÿˆ¶ í.,XÂÇàÍkUÔæc€ÿ’ oÖS¬§YN±bzÄ3~%¥¥¥¥¥¥2˜«Rš—.,t©__‚'je §À¨)óJJJJJÊÊDë7—ÓmK¹R¥Jà~¥ ±9}ÌiW™¹›Fwðð_ щ£JÔŽp>%›¦ 5KÈ×á:À!ƒ3G”!çÒëËÐò4þUÃ*ˆ&8Œ%‰D¢Q(”L."ÎL¨Þ_gÿ%×êQuW儜%“G á^_ÁƒS¶Á~§ê9ß¾¥¤Ý~¿îlùOäô5õ1ò¦“8kíßFñ^V 7àÐò41Ó½Ý=a€¢w›f^½¿³:Êsƒoß\jv5Vƒ¿8 Tæ6}™°Ýiìgæ¡aZç7‘jW[)ëG((`Ýh}0ß®:YÒ³ZQßýÒW›"ÀS=J_B—Þ½" ÝûGg÷áñkGl7í]`Ú­ØüÚ:¯ùäK#ŽYwøM8Ýzs;CEu®Kåï*ñw–O‡2õaÐzÿ5a‚yý¨ÄBb?1jý _¨oÙÌ‹¯Ì*Ñ|¯6öïs}‘³è¯®²˜œÅøa}ÂiÔGÞX[Ho£Nu}%ïr¯šã÷Ò\-Í•œÝ˜07u¼×:¯Ý×\A8ÒµæËÚ´Ç8Èb©V³¸aºß¬¶” ß*ç-ÅÿM*¯¿x-°üsHÒ•…º•ç>‡¬Úmb6c:Ѷt®²ï\9çÚ q¡«pm1Ž ·»Zên@BÒ:·0«EòºmíÞà{¶™±étg¥Df8v×ùp¡¾¬ãKצWÏyNa_iÖ¢Maģ¡ä iä›õ%ÖЧ8ÑOê,zt ·ß€ÝŠø~æò¬ 80_ËêºÂ°º'¥ç¶¯¤-C&£º È0«o¤6i¨ëïté‡B o<ÇÎes¯þs{ÅŸŠŸ'½ûM65ÝØûé-l ¯UÇs/xÉ ¾ƒN÷3*qTSWî£ß<‡è;J¥Z»?ëí6<áì~ãiUî^Úu”‡£+D-³Ó?ä½ró/cM;UJÛPÆaö ïÒFd.öåßiÕ\zµ_L†¦\ºw×µí)tñU‹÷lÓ\éhUÖùqåú–ÇsðÔ{^k815™ª¹‚㺇yZGQXô4z[~‘zòªƒå"å—’ìæîÞ¸LDµŸ/—êäèú ·*Ïm;ÔQi«Ø Ú—´¶áP½ƒ»j]йÓ9ßX PG½c8Å:µ|êë„Þ¢ê±ß~ަw% Ø0û·ë‰¢ð®‡ÿÚˆI‹k¾RuNtPî§®e‘5 †¯ÐÍÙÈðcR¿Á¡äigØ}ÚúGìR½[Om~naºÞø¯ÜÌt—W®pU÷aÄêòô6Šè¹„Æ­ö0}_xŽô{¯ð‡¤(…^à÷ÏþCQОº9îʶöº¦Ðwo{ç3xt7ôý¯’˜'Ñ»?ǧszzæèšˆÛ¬aϯIku>®_˜˜z3A„~¢ý[Ž¿ú/ջà Ê>ã Þ¥ö(³1h-®­ó™‡ýùó7êM~ÝÎ'ïâX\—Ê&%Aø#j_­ÛóqW¨ú—žAåöÁlM‹»Cå†ÎÑ •]m5˳ϔÍG0Uz+5èÁQ((ýÀY¹3a˜¢xú'ÓúŠì©}€ýÂQ¾`9¾à¢ÿ¬þͽ¥êüWîZyÛî߀1ï4”Üøèyæÿb{‡è;Ø}³­’ßW1jÈAX{ŸÒ=´žŽ~îj‘^ ïþ¡†µØýÅ©­>£ŠÒ¯e¸Vä)õ0üÇS%ñ­ü•Þ†l=Šù‚yªÏH2¨a»ÑÎ0í¶.*¡5¤ÉÔ¨;ÓW𧤫/cŸðÝï*ÕØj—ªõwÿíº5é Œ)®÷éÔ9ÅIÑ‚ýWê^O'£Ÿgâཕö~Îü¢©hí_J¨ÉÉ5%žiy-Ö½qétÀuE_M¹S,ùäcý´À:Ò.8‚ë—.ú{ò›±µß'æåRê}˃cåo芽ah§Úߺ•O)¥¦mûôŒ‰…ëpœðþ¿Î"ú‹ðäþveÁrZ¼úÓϬ[Pí~ I,7‚ÏJü×ö$WV=ÁýF •ö[>÷öàú¹}Šfˆù!©æ{ ‡‹¤éõá¢Ã¢ZF諚Ùê•ñÔ¶ ïM³¤s¤^+}.Ȫ¼ܲåzüLøSGØŸìÁ“C\ó]ßöbrT-tË}w>!XVE×øé7ÚÊJzÝüÐÃLþÐr?»û¿íŸÓ·¼JÖéÝK~ÌA¬Ï«Ó–ÕË{Ì«ÕH}þè‹ù”5mÝyíF¦,-Ú¹ëþcIIƒÜÁî…@ô¼ès˜Ãk»3X+~­úfMnR[t m¼rÆÜàqbTB«òÎWi“dû2±W²¹Ï¦(Ö¢Õ³] Öœû/Húi7É4‡/^pR’âÑOgùÞÖ*óvÆÁƒÚ©ð)7NžŸ¶\]5k²ÖƼï•g| Òó[Vø®¸yI݆ýÓºÞ @B¼ÿ1urBÎÖÕÇÆ»ðûÒ3kçý:ëšÃÒÉ|´>¥ª0ïzß­ç®ò׉¢Uü‰èüÎÅÆµz«ºîöçxiŠB¯ç×=¥òíÞÙNÌúKÍHˆ… Çk²V¯#­VL¹QÝöŠ6E…'wìÆÌÖöÃZ½UÝw{­—€k¤2—þm36ty^5ñ-²ÖßÑèkΰ…á@¦æ¦f‡‘ºÉÛØ?ö()ox @„§(âTÕÀ @„Ó‹™ÂŽ:Ê2ELù5ˆM¤®x5ò´%’ø_!hYz1†ŸÆ OÙï§ÌB $’jš|_`y–gð+ b,±½?±¸£ynsÕ¸(H¦ƒ°»]¬kêUÅ­WWýí+ÊS”¬¤¬)R<`“‚I± oŠD¿À¯Q•¬b†5_ÀP±. (E“g‚¼:âÂ0`ÍsOå¦n´Ž šÝ_ƒ­šà@0ià¿¤× @kš|G§áÙ†,9;23\`@@šæŸ˜•?ãk`Ì·Èf¨ @pèñÙÐÏü]lÍ‘· B<€ap7ÿeƒ0 @tò®$!phò¨?âY’ AÀmã~=@?ç2¸šC‘D9äAòŠm9“­:Ü*Ê@JJCn%àààø !._ü YÃhO•BããÿHíà (8((&n%e%eee%8.¥Ëü೬Á˜Ž±ŠÌ Ì.p;òžFè Áƒ (cÄój¬×ÎF±Ëft"‹ÍGèp­!_¿ŒÓø @&eÙ^s@ÏVX§H6Yæ[. žÉ€8Bt$JÃ0ŽŒÐòb @†iò1ó†Èu½xy:L^Yp!¶³âÖcLEK*_§Š¸„@Oëà<ÊHS(F’…y‚gAä]Cdâ±é€R9A· ”·vö•$¯Á­_/­º7Ï,Ú›"ÜvÑÞ;F,[c¶‡†*”žxBÇq·føy‹8¢Å ¢‹¡G{Í /ÑÀ$«EŒX±cÅËð¦aˆmD°ˆ=lT†b°òu?òúÛ£|òÍ©xÑn.‹ôQb²=âøfèÞà_G}^|=¢Œ(Š(¢Š(±Ç¼{Ǿ¡‰s­Ì%ŽŽñÌt_Çzân~%:–ÀjÅGUÕÍ%Á‹P§´M­»Å°®ÿ‚ÎÞ˜iN‚7M0.:[Fa1‡†a–ÇðÍÜ.£\Ä%hæZUi¼›aS;ÜT„€ÅÚOyÏ ÌéZÕq:&Ñj,bè·êž’Øo-añ(§¤µ¦`º™cŠó–£”q…Ä•ùáº3_9@fw#Ý<âzǺ=ÓÊ=Ñb+x޳»-ç-†\-xžM瘶”ÎìóÐîNäîNìîè½ü ²ø3£«ÃzÜÌ#‹qeŨÅô^.^ºP·Ä@†¢XÜGBˆŸ‚ ÚÆóN½;‰ÜNâw¸Äî'q;‰ÜNâw¸‚Éo9ÌA9NHˆŽ¿q÷}Ät|Ïú¸Ž˜ž˜ž˜˜OXo2 Ì€æ6…pŽÁDy§};è¿4ï§};èõ¸Ôì3°ÆNÄìA&9ÅU*s˜s|{â:ÄuœÄuˆëè™ÝtîÁ륕Âܧ¤·In’™L¦S)”ô•£ÒT¨q7Mä]9‹ù˜;™TpÀ´K¹Ë$Èlsbß§?FøÔ²¢È¬WªWªWªWªWªWªWªWªWªWªy¾'ýT¢lEEÍÈ·ÿQQiT+—Ú.•1þ¢ÿú‹…±ÈŒŒË÷ZI†_ñQƒ¥?ðOø¨öƼ¾´ØöÏ _è÷G¾9ïÖ=Ñº=ñï¹Çº=ñî´¶G·KÙ0‰ž:|c 2éî… „Â0º,¿QBò›®÷`ÖfÃ+,å½ô~£ÑOê=8ôâ|£ÓŒú=€K FénñQZL!QRÒúK–ƒRbAb±11111–aÊŒ‰råúµø8ïø5\äå›Áø—N¡/a´·In’Ý%ºKt–é-Ò[¤·Há*4†£d;èí+ÇÂ-¡±-–ÆbQ¦2ëzeK ·Žñk[©z¼µ7œºq"FA"TH‘.:1ØŽÓ>½Í SýwF¸ÄvVïñ Ì’ Œ@©YYYYYYYYX0«iUÃJm‡}•Ä—¸E³ ZÌ[@ƒå& Œ ‡3ycÎ.‹À´pº›“—HÛSíèÍ£-F ‚½j2í§ølkC„6ô† ÄÍÉœ;èú Å·FÄy&Ø¢Š1EÇlQE9¢Þ(ÞÅË£Àž§&éåX±bÜ] ˆº.bºŽt¥Ô°•R„±×oðuÁHÛÒv›&ænøÑwÑxØñéa3è(±V‚Š¢Åqb=âŒî;º.…àÜLâ‚\X¢ÔXµ1›ÇxÆr'(Ê”#¿IV%ALÊJÚ‡® FÞ“´Ùóõi;ÇoA}<#Š)’-±EQElQb(âÌ{Ç xï~7CsC‹—1h·- h¼ã(‹¸ (‡lJ¶ŠäâÚ3›†v”. Eeü͵}JFÞ“´ÙÜÐw ð­i·ãÑEˆ±qWU"‹y‹}-Ìw‹À¼.¼ô#a ¸±‹j3¼[c#̓†V%\InÒñ²3¼ Ê œ ƒ^žžÓn=ÿø)zNÓc73sAÄ͸³Oh®,Z(±EƒÄQosÇŸ «Ä³q¡@Ë‹.‹BË‹«œK`Œ"Û´«„›B\$ÌT†Ü~fÞŽ8)zNÑáœÓsAxÜEáZ×,ÂÆ=¢Š,QEÎ,a…qoñ\=øKº^«pÙ§l¹qbűEÌ[bÑbÆ1i””Êj!. †áŽgoUüÛtà¤mél›ÍZünüO1àƒ´Qb¸³ ¢Å‹AǼy›&w7:±ÕÑΜô] ɶ,A—bÅŒ[‹¢è±t.£X¹Nú@€”9Îaæ1þg?Kœ bE:ëQÞµªUÉÁHÛÒx›#Ë^4ø–£Ä¸Õ(TcŠ-ð@¢ÐQE™D{ǘñ9£»«Á¼uº—©¹#¢ ¸±EÌTEÑ‹±‹;pˆÙœÒ$¡9¤»ÿTUzFG}PU Ê%Kåç‚‘·¥‘6±e›“d;ñ/ÇE¥<#˜4QL‘b‹qGcŽhîêðrޝçNØE‹1n-Æ1hïí¢õÂÀ Y½³¬  &äyà¤mè¨íóš,¼M°ïÄð­K‹RôÎ:J,Qf-âŠ,¢-Åqf躢ˋEÑy€ëøC|ÚR’¦Ññj'Ø8J† «sæw™Ü>gsîw>ãÔûϸõ™Ð~ç{îv1FäW2aÑ1G Ê¨¶#De;Gõ÷‰(-ƒÜ~‚6.ÛJ º>ãTy/ŠcžwNÖ‚¥»Ë÷—ï\Ìk‰Q½IÔGþõ%(õ#Ô‹FKFDê i\¶›Åh¼fÑq‚a²ÛaA¥*½­û'·òÜ*soåO“rßÜ M79{Ž~à¶Cøö`IÖm•Œ²Â#„X±…‹ù(akâJ«ØŠYAZ1t¼ ð«²¼1³Yü3,®êÌ4T –K®v–BåQL+Ñ+ÿÔ§ÿSþ/Tu¡…z²Ñ\.å ®0Q—jZƒïY–‚>?‘f`úµý¥ʇ”ާT\* †K‡þص2å꺌=Ñït{£ßö=ÓÊ=ò±îtó^ËhöǶ0Ó”e–Ò=±íŒ%lXAåeÄÖÊ·ÁP@­À—Sž KòÄ!y(ÞÌRSÿÈÜåʇ-äÆP(‡q­zYaÔ\¹rÿ âK+½!Ð^^ˆìWMÚ¢ç9Nm€…(ûFqQí"@<"Ú[«/Ö[¬·X¾²ÝbúÅõŠ9²Ýb«yn²ÝeºÅczÅµÍæZ]+,0ÂD‚ä)â §9Çhîþ©Gpýà a¹ká ï‘û> Ù e8º…ý’Ùoþj€Z’E>(k}ƒF+ÐéeäXñ¯d£`ê^QÓmrQþþÃÌKoBu ÕïòúkzîŒâÔ%ÛðÙú™fm>åþñ™çkûÑa0"*•LZ5Õueê·Àéä0ÀŒ$a4áøþ‡IGt}'ÛcfòŒçzúŠßœ¿¼oçbÀù$0QõæÏßšxtaOÚYàÑëÚõô9ú{ü¼ bo@S¯ ù}-º\YÉ7A¿1W`¯©ÛDúvÝ™ 2rŸñF%~ö}êUèDæ‡=‘ʑԈJGh+hˆh˜Ç¥Eª„ Æí¢**T= Tí^B;*HcЗ&;&^Óu¤§J\aÂá嫺ÄoLêD¨UÉèC ï‘”Ã\˜J„uŒ¨-ƒÅhiT¼7ÍAÛîBÛæ?DuŒ_?„ßÿ- q‚üHh¢ÚóEˆcÛèŽZW‘*ݬù0ú Ú‡m _óVC Ž©4”Á/OB*½‚Ñ:¢ pu!kBWZ+¤~àÆt4‡Ø”¼o’9HH´èJÐ{D©vAFëj7жfå{î}Ї8Á9?9•ó$1’ BzFÊ.ØÁL&z:šBz@”.؈p=¢æ£© Ö–8èßòZX> /Jê¬ É9v%D7]DI •§¡*³b [Ý##¬N™vƒ]^µ*$xƒpg¤p®{Jé¼é8ÌKÁÚl&=<¸ó«åôVØËÕm0rº1¸bõ ÅEï›Óµs%}nÿ¸<ÚÀµ9U_¦fõþDP râý^߸$À* QM:ÇAŒ®ãPÑZÆÌÁÑÕ”øÕo,$‹YLfÆð©ð)*Äe þðMÓRpÜBǼ«*¡m*÷aŠè1n§No8ú¬•ðóœjŠ$›¯Ü6†7ÿKÛc¼v `<YU+åCdjêNHó2›®p!dʼƒ¬,(»¹wê9ÞW…1kDËG/ ã4.;Cša0ºœŽÆY^ ªó–8Ãä%¥MÙ»ÿqÃe—aÍ^A Žß¸_i­ÞáÃ4J·¦ííúa ÊÔÏÁi²n¯ Ûážh;Èó³Ú+†ê‹˜³?Q¿æ’—´[yGç:;«Ž–÷þOxÎY_Äîö–HèR³vS°JK–c±ÝÝÇi›<—ÈF­·VÁ‹zÇ#FDj¥ã­]zywsåÖ„(ió.Xê°,ìÂíj8AmÔ¹âºF§[û~I•t®'|KÿÚz:a¯hiucÐõ=Ío‚5•H…®Û¶³Þ#k¹+iˆÊ,7ö8ù¸RŠ´¡±£iS«¬yÀ½ŽÄJá&3%<ĸ 5(v1~òˆ¿`!E7˼ô‚Ànº‡—7ÆZ²íö•UJV rÚü}ªe˜#»öò”Y€¼þr` Z´ƒ¸2{B„òÔnÝN¼ÈAÊjªw`yÛöò”œŠ/|Œª £¸2{1ÊŒC*ìfÞ^ 1.’­ç¤¨Œ¼Š¹m®zs÷,@)Kwwi-絪‚9Ð8ï„GÛšYÙ€ Q”%Xƒˆ ss êüAHUanê冈jàï#¡¬{ÇÙï°IU€¡É¹—âm•ö’Pº ­÷³Ä‚º²Ç9O³˜]¶ Cäò&HŠ@ÜD} †ÊdÆnF«å㸺/‹_FZú€Ý ªç´ÖžqS°3‘ ˆÓÁTþÀB¡i[ÊÙÛ¯×(¢ö 9~Nu°$Á\o¨¨ŸdLÁke^ÈcWÚ†ùäÿ½cc»ÅØ/`é9[coܶ£¬ko A'¦kJ†ät‡ÚþQ|)~'7|kNµÈ‚:@´i†uZÄDà!b.ý®ü¤±Â¡Ðc¢ÿu 싘™†ïº÷>aÀº•î|?¸¥Æàˆ3É=÷ø}áÄ[¯Pq^c¿æ›WQ>à´RJ‚±i¯Ñï Õ˜n.»ËïaesÍe…•åv±sªy·ºoêàÊáG"U[~ B@¶ýFîÍ»c1L¦Þô,_"Bl¦<†×îmàþ¢­hÊw/î#ó¡ý cÙhæ.`°ì¬ýFýrb\ōޱ•UëL|Üw´ cog[±0€ä""îÁÖÔ&øãÝqàzÅ:vcèù—P´xugÅß´y„‰%þ’“´êúŽ‹+¹yú;B[ð–\éwõ)¿° cê>Ú1zûÍçGå Põ2 uU¥‰ö_ÙJº­ö¿È™­ä¨¼u°H–AŽb˜ÇhRih9‹gÑóËSh/>ˆ¹rG’º…¯J„¿bã×9kHDEöö›lP€{¬§ˆQܽ^7Ž,]³˜[ñôIŽX{¹_3<«ìŽÄ»êkmgÃ^Ðy*)µÚúc»/W·Ÿƒî Ö©qއ»•òÄQ9œìŽÐß7êékð³î#»³€­²f˜ßÄ5U÷abeK¶9Äjº´ß†%^Ymel:@½¸>âáuûýK—td;]±•ñö6XxPÿ»ÌW¦e° h¨a^î>к6ÉYþ½å_õ*+YÛc—(Ç]t³¦ûvƒ¨Ÿ˜ÁÝ/׳1ÁH =mß´ ˜—h¢9©?U‘Æöô^aºïA‰ßÃZ¾^ ‹/W‡|,ÃY™wÊý“¶Ÿ®s~l¨vJü¢ù+õñИ¬s_çÌJ±fßíWÔà¡`Dæßê¾bÞŠ#¡·Û,èõ¥ *@bæLX·É™~hœùä¼bµéüÊÜ}ï_ Œ ¸Ÿؤ$»)öŒZ¢VR·÷^ÐLšÍì ýÜ4Ää.ÌììSì–Õ·bßÐaðP Áú‚Ò»Ú¹-ê(iß7íkBÞŒwhtÞP¿¸Øˆ=Ë%ÂèJq2¡­L'?xqÜFåwN¿¨]îKl}Æe–s—Ë^äQyM±Õ[°¸,Ž¡kúŠƒkƾ^¤³ŠzA°Ø•ºskâ;-«EƒØ§g¿Fo²ïaQüþáT`‘Š1^ʳþžÑ•ytÙRóš„”àtÿÂ_õçËqÐù u媈ˆÐ¬4`ô«è‹`dûédËE— ‹)í´E{‰ÐÊ1GHÉʹڣúLº>”~lDfÏ(þ32­gº{ÜøgïòŠqJëÝT¿~Sua‡%G´²Ë¼‡œF@kÿÌ¢\Ü0>ÜÆ®ƒ¡g( Qô{F‡8AΣõ‰Ÿa@½p~ îmòþ §ÉÁ”{¡í*„;°"µÝâ8zt;,ºmwëõw ƒš.ïÄF²‰ó ‘V¾HG}ó~æy9'yÑõj©| üŒp}ÊJ‘Ç&~Éñ%ù?lT6¶¸‘@‚áÃû§Ú ‡$—àX:-?qoä~Œmß#_q[A3ŸÕqÉ^æêÆuÈ‚gçÿ3ÏÓr¥²bÁkj!¤píéäÒâÅá[áÞE˜ýìž,>§¾™Ü`ûŸö<£B¼¬«ûb…kUweŸýA%¿¯ÜËùÌ QÍD¡~YÆíwÄ_uRWpm Þ&Zîÿ¨«Òø€ä‘½þ¼íyŸR™ÕÎËúqB»Po@NÔ¿«ˆ8+Ø—¸\÷PÃ/kh=‡ù x ùDyl*ÙAú¸÷ ‹ƒ{ª‚í[gïî Û¯Àý²Ö*o’ózå¤u]ñ}öƒ¯ØÄ—ïpÈ9WŸå "æŸUÏ÷(7œ¹„Pdz+ ºËJ'M”7÷ƒKaû‰Œvé’½Š=¡*D£äø+åÐa°SÄ}Êù‹(=ºvX~±A!ìvn8ä; ·¼©ã´2­Ÿgöʬ(iuü›¨QöX¼vUWÜ–…ýòʃ[·Á•ˆÝ ;ú[¾czh«¸9=Ë#œi¹'î•@x’<’4—Ýäöe`‘ç;2~Rvü>¦\¼ #Ž^°qoÞŽ2·î–n éGQrLòp.·ê0ÖªYá~åOª~Òë±B¿ãÎ#Dìõvø˜.ÊBEÎÿØ”¢¯=]·t]â7KÞr ç«p:¼Þ’YN£è@lAm¾ÿí.ŽtÂÿeæ^1„Ï›6fÁòÔµuúÙaîŸU(©¹ßºgʯêXFÇú„Š™ÿ´å$*‹kDNö ì"ý@Õº™SÒÚV<Ö¯´}£×%Íño¼f­K÷0U~Êe÷:/0\¾… ƒÃx€†öK„Rxvµ–_Ÿ›áaædëoè–®µû—®ì©õ?¤D´> Ý‹Ð(ˆËw dùgüà²sREQÉÈ y¼²’É+ãhÁu÷ˆ)½JxEòIŒðæ¨ú"­Í” ì˲`ºúÿSþI[ ›e¿óÌU¨Mû +)ŸåÔ"Í8cÀ1Ÿ¤¶HÊ¥c'¬o ]“½ÀŸ^Î\ºA¶eW5†WQä÷ûbªÿ鳓¤íq2„œoÿGÛ¬ô¡äþØá‹UmbÅ(±N¡ÂrÒ‡éÅ?ߨ2¶ žçê5[˜•axSžáLæäß'ýB…Žà§6sÅéÖÉo¼åjû±êSÖ=È«¸A“/wìçæî»Èº&ãÙŠ8Vá&XIN¯¹ö{Å@Ëô³êŒÍv~ñ^±±y~.•\:l©ö’û |­…÷–¹ø Â_:·üéÕe³÷(}[í”ø{_«Š“yA½Ñ =±NÔg#­Ê&žNŸDެÏó„%(wÆS Ÿ~Ñì´ò$}c¿:}t!¹ËI½×ïn001^0N?µAÌ_rÄÜR…aüJ;Wî IoËÿ’ôwÿ@Oa¦9ª›LŠoeþúLNnðº;ndŒƒÁµ6z%âÞE˜v<Ëél?sþ`É/½çvé.Älhƒ¾ïî+e]›öÇ ÈA%ÇþâgÔ*-¥%ÜÉýˆ¶ã €[–¼§WÿYV1nÁk¥wÜOìébTf49Y>¡ êÃ'2_t¦µq{—A™$A¬L§¨ßü!IE£µHi³È#P@ uɦ;(÷?»Ç$ _oöL,-}3CgÈE!n‹]®_È{«Zðœ½çr,ß¼± â6w‹YNí¶?¤¼úÓZùŒÔHîæ>%NáfyÇéíæG‹—G€ÿf'´ƒºª!´1³fàBíüyGÄ£&²Ô½È`lúd7Jl‡ê5¨d;–.6¼ZYú?Ô®­ùQ+kPÜ?…üÊØ!_òd=¢’^÷¼¨=Óna ¹ãc%,A§´Ó–Ù>¦z ¨ý·Í@sÑ»ž1· æ¿Äކã¡lp♌m‚OähŠÄ~’#†Ì¥bµÅ)çý‘HO£)¯Túí µÖË2 ‡^ìŒ{ÚæÒHÂèÅ“Dø¢ýCØØy%Íò§û0Dº²ìlÞ0Ïm!‡±ú±º3èúB¡1£×l‰)&ê; M*mhäãqǼŠ˼«¥¶dj­ý—>ò¿ÿ7Ç¡6< 'ÈKßû¡Qiă¦Wí =Y?°Î±èåï´B’¤dzC}@+^‡x·,FîÑÈÌ–øÇoúFˆÞÁh–æ%Æ›?%>ÌÍ ¦?’š(ùm†:,;ßì yAòûïqd<Æ2 vòmñÙi´O7I3WW7³Šóƒ“Pt!aÉo~“£ü!š O6•øÚé_Ø<°’•aÇuèwŠ‘EfzFýƒúÇI¥ýF­ýK×ÏU¯ÐÏÛ€Ús=È篩G…n@°¡-­ÖóionfD†ó£QE©Rê_sµ…õ,‡ (' Í«ööc~iÖ¤Œ°P›õ;Ÿû{ÚþÒA:‚F–0™ù3áí<¶Ñ¤ÕG6ôrëãzœnjmÛµÐ}ÅêPf™J+39Ô´ê“Jî^nIÐâŒR{´ѼŸø$\£dÖ'ØNv9º3“èò¿ì±¼§çÙVžO ¨}úÐðÿ¹n,u†OÔyÛk¦bæ‹UÞcMt÷¨>äwˆ¶ ›`IÜ ý\çµ TWô-»C«R‡*‡íö‡èéA•ú=â‘pÆÛý§û˜'Àk·õöòмh6F d«ÙÜ"¤vXOFêsúÀx6C ·cœrœ¦&ÖŽ^7q1ŸžbOþ¨VYzx_îZ;Â:¿Låݯ©Í0}Á Æ(U´ç÷öà|ŒpÝî–ƒ.Xîñ>?ÜNÄeØ9ÒÞU¼oLOaÕKà.ëz®ïêY™~³‚ûEï„Á#n0ÖR -¬nnßô¨o‹³ºä&Úäöú)‹\U#ÿÈŒ«RÚÃúävFÆVóJæœã£¹ˆÈ®£¸À­‹5ýAÄ9±?¥çÐó.µEÑUy0'¼(ôÉÌy#É#£©ê{aú„ ŒE¨ú •6qÿ³—brtRÀ ï„[Y(Q‚rcnKŒ¡}®)B·e"£ˆ> P?oÔ$›\[‹pØw?¤úÔØxÛ FêElŒ§ÔÍyöw&Y…NWQäÄNjб¸»y€ ðdXÉ÷pÛ…ÈY C“áþÍÿÉ7Mû)±ï.5¥ CäkÍDFÜð•·ìY¼2 À9Dtá‘-uìÀP¼óü‰™ ±ç)x3*ÄSa?ò¾Ðº½soå“ÞV²Š`H‚¡Ë98­ì¦í?¤°ZøedÙoÞ„ß°'.(}av«¦ïîŽã ÔÃý tö{@ 6‹6°-†ûÖþeç°Óªåc=åo›»ÝÝö9FA´¼sÜŸn±6Ia„_TÚûËÝ7ò:»¯(‹ÑŸµ±åÝîÃ]ˆüÔ+”¢gyþWw½ $ƒevÃ{rÔ2´×ZQý‘ SAPˆ›0liVÉ–Ë<ùuõüÁmסt¾ñ%#¨‰ñÇ󥸙Üw]€ñ;ó¶œ]Þì²]ÑOô‡ýÂB–c­?÷;  ¸¢Ë0'QOÙ- ¨o¦ºJE7«ç”€¸ôή  fâw^9ÅŠS‰µ§—‰ŽüK˜Áw˜øú€²O(KWV ÕXµÊŸ˜y¦Tl÷n)V¬X…T~ÁÌ{2ª&êö1ðæ°‘§+¸z;N_©ÈcÈËâ/ü‡“×Þ8„õ˜}¨Ô‘¤ëW’)-´Ä]-Z 0Û’ˆ£™J‡Þ«â£`Ÿç<·C¡ØŽÕm€R’SùÈÏD9‘,„ÍøL|À–ªÅûl=ˆõ$U\Ò ¢xO†þäÐ`<½‰ÖäØy7ý;KWmvÄÊq ¬â6µ)ýL¦I:;\›~ã xÙ-Á«"¢íË–p‰ ÈRì »äL›B+t,®ªÅíb'êmö–¹{˜ÀPE0`#´CJIW¼r] ÿ’\.ù\J¹u¡möÒs˜›#Ñ€‚QϺ¨kæ=LSÆ(ûµÉ•<Ö8¤7†€5t7üܺ¼M«—Ä4 ÑÓr»x¹Ä•xØ.å»îc³õ¹í€òÜ^½V•\« ‹R#b0 |à)¹Sr/;^f_;Dé§@,l¤ÍðH(Ø.Z°çkVŠ~)–®,tò¥ã¤¹Ø€Õ0`5{)^%opœƒ³q«pÅt}‹—‹îEs{±%¼ÇR•âÍ…Ó¡Ù¹·MŠÐûÔù"¹½Ø¤¼Çù«w Yï°ÈEïˆ Ÿ¡Rˆëø•WUcDo»]×ýŠ#ü²9bƒæcª¼‘Ð6Ä€ÝÜ&r)C,vb#ÃÑö.X–?¤y½ØˆÝ”&gm¤ ¤+ðÁ´B%.7÷ˆ§60T«—Í †»ƒNëÌ{AEÞ~*]1^XçÔçE£¾¯—‰âtÜG˜£o ‰OÆcùÐ+;ïý•™"¶(£M£9±\QfÍJi˜ŽìVB˼šxfæß} J Þ#‘ó6Ežüu¯9¼$A5ˆÈRìs Tâ=ZÔòð­ñ-è{*ªé]]ö0sËu-Ð#PØŠ¶Ü¿… u”¯¢þ&ñ‹@ë¬GX=c,§¬MAÑÅ£™Þº× ð1ÇÚ<’õYa†Xa†/0K¼j2¼[q£u1ÖÉ[VÞ­ú)W.s 6‹nxƒtÇi\çÒ;º*-Ì~~"8¦f&Úgi¦=dí3´ÎÓ;Lí1£fv™Úf#‡~%×n-˜¢Æ9qbÆâæ(µU(£‹CÁÎ/‰‹JÏX”Ö«Ÿÿ fí x‹QÊ(±F¼EŽ-âÞ8[èµYwÀº²ôÙ‹h±Ž]FQb¨±E¨±‹s-.ü._Bì¦ë*ÉVĨ¿‰_àR¸”^ pEå,W(³$X&ðǼV>5é·þ»Qí1ËŒQbÔW,QbÔX³ÎséÏUôKŽá à—¼{tô¹ú|¿À‡f‘àŽ/EŠ&‚Å¢ÒÅx|Mðºr‹Âº® ¨í#•.,X±E‹qE/x¢›ëN÷…ôõed!¾`˜êÉUÀçþ`,Àâ1FÑbÆÚ n,E†8ðÍìwâ^<6é·¼E‹F,X±EŠ:7ͳƒÐxQbU† ¶šãåÀz/ø:õ³Ö°EŠˆÆ¸—X±j:ÆéÉUøë0Ë•VeÿÃéŸ8÷ýÆ^sÊyi2{ãÝ<¥Mô¯lñŠéÈöG-¢úG²=‘ìž1ída§)„”ót{£ß¥ï›£ èº~Q†KJ¸é:LT®¢WùF@°5:6=àx)´:2ÎPÖËí#nјÞj(rW©¾®ngPBwÜNòw¸Ç©;‰ÜNãç;Ó¹;Œv³Ô£¡TÃ`Ô4¶u–Œ6GJc—ä¸RÄ#ËœÊ0-<§?DËÒL =`$ná0†2f#Žç¥QV†ÍV[À͸w‘äŠ(±…ÐVÅ‹X±j8±9¦ç†wô´UISÀbÇU¯Ã\©Ž¯Äwa{ÂzÅ·F˜†±1"áU.]ΤÛñTFëŠs1ár6#µ’ñé:R:E¹ T0˜IÊ1Ò²â=^&/,[G˜±È¢âd‹(±bÅŽ(°Å–oŒcÇÎ1ÐÞlNv«‹£hº>©À*¹Mt“l Ú6I^èëW,–b3:‘@¥1mã¯Xnè@rPÆ}dC‹ˆ@÷!˜Fí<Ó>©íÄñ¹fâ8±.‚ÔV-E‹AbŠ)¿HÑáßWPÉÈ7ÕÞ.®Ú1ÛÑ},Ä01Ô7ÔŠTÍà 1Ö:ÿ85=W†´«›ß>RÝ©`¨Ì»úÃOH„¬‘Xfr¨›óõYá[›öŽ¢Ä] ‹âÅ‹,QQ®íCõv!Á²—M㣣ÿå)*2å ^‘žiˆÑS1½ãfÿÞU®"˜¶ð.­¾^ÂXé<ú^ú“‰eð-E½9#Ú=¥…,X±t¢ÔQż{ê<æÓn#f"bbõu]_OsÑ4¾$•<Ä&æ6ÑЋnu=.^™¼}¿ªY.ñõЕtŠüÃ‰ßæ¼ô6âZ"Òå÷—Þyp Œ\ZÔ{L¦°áe¼k}±–SdðżY—Âh¼Y.T<¥ËÕk[¢/§ÏÓfláÚ5Æü¸¯‡‡ËyÌ|Qh¨ì·é{h(‡:‹Ëð ÊhÑZÆXa†^øË 0êlzOEË—øoPµJB#¨¼éz/øÛè÷£»Vþß‹¿ T.¥ãÁÝø÷à©F„Ó¾›ñþWMªÈc¼óˆëèÛœOX˜ž±=bzÄõˆb4[èó­ËÑyÑrÍ.Q–¥:º ̧ãòvÿÎ~ÝÌl㢗SÿÙfheroes2-1.1.6+dfsg/files/emscripten/index.html000066400000000000000000000223361476115357100214430ustar00rootroot00000000000000 fheroes2
fheroes2-1.1.6+dfsg/files/images/000077500000000000000000000000001476115357100165345ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/images/platform/000077500000000000000000000000001476115357100203605ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/images/platform/psv/000077500000000000000000000000001476115357100211705ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/images/platform/psv/sce_sys/000077500000000000000000000000001476115357100226405ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/images/platform/psv/sce_sys/icon0.png000066400000000000000000000654061476115357100243710ustar00rootroot00000000000000‰PNG  IHDR€€ôà‘ù<|zTXtRaw profile type exifxÚ­k’,7’^ÿÇ*f €–ƒW˜iZ¾ÎA^rº{z$™IÍ&«X7+¸‡¼öÿüßõÿñá)9])¿µ´Rnþ—Zj±óM½ÿëçŸáNçŸçýÿþO?¿þþƒÈ¾>~¡üyý_?¿ÁïKç»üo4ÿüÁøç?héÏû×y£?ô8¢È7ëϵ?oôÄß„?oÐu—Vß|„±_×_OR_þ£¶3ßì÷gÿòïéeöVæsž÷ž›ÆßŸòÕ¿Ãõt¾yÎ?™^ôò=/:?©F„ü»yºÿaT׿®Êßß…ÿæçÿ²(Oùýüâÿ<™åï¯ÿöç!ÿûÉ¿ÎÿÃ'?óïOþ§Ÿ‡ô¤}œ¿þþ¾U¯ïÛ¿§ë©0¥åÏCýõ(ç;^8˜òçüZᯗ¿3ß¿ç¯Æ_õ"z'K¾îyþš¡…Ȳ|!…zøÂ>_g˜ 1Å_¾Æ8Y(VŸ7¶8Ÿûb’…/¾O{ÖSY±Éò>ü4þ=–p>·›¡òÁ+ðÊx³à*_g©ÿ?üõß¾Ñ÷ò!Üõï¹b\Ñ d®œÿäU,AøþŠ£|&ø¯¿þõ®ëà æ3Í•ì÷ø½ÅÈáOlGÏYè‡f¾þ9¼ëÏ0E|vf0áaîžJ¸ßß@PÄÊútÞ¨Æ'ÅÁ„œãb”1=Oaqjô³ù7œ×Æ?³XˆüÒ©²@µ؈Ÿ7Ub¨ç'§œsÉo®¹å^ž’J.¥¼Eðëïó¦7¿å}ßú¶·×§¦šk©o­Wmµ·ØÀ1·ÒÞV[k½ó¡wîüvç½8ž‘Fe¼£Ž6ú$|fšy–ùÎzÍ6ûŠëYàÄ*ë]uµÕwØ„ÒN;ï²ß]wÛý#Ô¾çK_þÊ÷~õk_ÿ{ÕÂõ[Öÿò×ÿýª…¿V-ž•ò…ï߫Ư¾ï_o„“ìš±b1VüuèèšÝ5¤/—Î5»[$+rd”ÙÅYÁcÓ1áïµûÏ•û§u»RúZ·ø×Ê].Ýÿ•»\ºÿfåþëºý›U[²Í¼Ÿë¬iè¤Þé÷Á"_¾G-3„4F {|Lë7+Ýcí0rî1Œ²ö)—š®ç~Û(©ÏÉk;Ÿ]æ—vé¡íæî=óãÔÍ’ùí«é7,t¾þúæß|-cÂCi§‡hßž;1ù,ë÷¾ýKÏ|K¯mnð´¶«b©¿ß ›1æ º¦èÎ>ó‹©}¬Ú·‹SWòüvøVêwýæ*õùXÆÎÛ_yó&s¥D„Ý­ÔµÚ×,žÚS>XŒá¼ÄQˆÉóÌñ¯_¯ÿüÁèyÁFáém™Æ»¿„à›Öߊ#ö5^‚ò#šXäÐóežÑÇÉq3v˜÷ê%7Æ]x8×}ñO&u}L÷d²f 5ÇIšm µë½Œ¶ÓxÓŨóå˃"XÂvÍyÆú’Ùj /‰XœuÌ>ü“ÑT™%Ýñiwª»lDÆïŽeJU_ ¥›W¯cgøð}¾/Î ¶û|2 Tê$ðwoÏ7Vh+]Õ×Ìwü>Sò#g² ¸>£¦5}Ów^ú–gõÎ[º~­ÕÓtUÃ/ªí4(#g\߈y†¼ñÊÊ>¥÷ÕÓ[gí%’^’«½aE²h¼/Ë?Ã[÷"¥'3¿ ÖÜÛƒYäÓOˆÆØÆxHEòŒßïH1ñ<'ʾµù0|}Ÿ"4òêaå6¬×ë\¬1@†L]{±8½­B€3a@ß¼‰öÅüï‘K¸>Öy Ôøø¯Åo­‡w›Äç½Þü •˜g]a„5 ðÚÄ|”4ßø¢u½_[ïÅõ¸Áñ‡`†AЪ¦!kY‰P(“ļm³¤dia)¿¯¡åîùôAˆ}×ç¯=Ok @|¾g1Q é‹{µˆ¯¶Ë–#xñÓw¬]únr3C è¯ôñ&oO_%ÕÉägï_"©ó€Âû%¡vd ÛX+.Õ7“’Û;÷Nõ¹d޾Ż÷Œ ü*1™°?ów/å› Pˆ¦½A' b[ ‘…‰ê{.Ða5¦€cº×Îï .#Ì.¤ÓÚ3 Äó’Æ¡'€_³‰ð-~×Þ„9\»‘²ä^Ù)Àõ{*8yoT,qZ!z¢€aÜQ~:郦~ŸDHÁõÃÔ,þý#K+ܹÇ"ßÞvFñ¤¾JÚŒ÷ù 6Ð{óõ#µß?¾ë$Ñ{1ÇÁÆäÅži Ø‚±¬:ŒF*­òL<Ú7J›õ…®IÄ0¶¡–@µŽ ØŒª±üäJYsjvÐÕ÷ÂíéŒÏ$(H‘×ó¢¬`)?lØ€  %üîk­»…]yPÜçæoýv€ä»6H¢òW}8ÖùèhÚ+‘ëC´#" z·[¤x¤k2¤H·±;(V7QÑÐÏFã“gøÕk=Ö }êSB"S¿ÒRfófæV˜á„*nDÒbŠÛø‘w<|\&]°3C‘¬4÷mÖœ¤|Ü$ÙC\Ýßy.æmt\iŽäf\53Ýhó(w¦ \'Lw”ä3“ÊWÞÓÙ»½+Ão ï{f7”Z²«ï‹À LÒÿBÁ'ÈC&`5Œ¸AÆåê—Í̇µV„†@pUÔ“¥-v3G™mtÃÀƒÀ3ÉF¢¿Ð5kòɼ‰«¼8C& mïD :Éß B²´LJ^Ä;ÀÔp2{×GôÅIþ©¼@aÐÃ`bЉ” À—0yòB³ ØXw~¤X¢ò@ 'š£šV/ÙUï Ó§Ò¿³ä @@ ÀhóLüº3ñsÁº¬ìÊ4ª¤}wcj—Œ9&äëÂÝ,ãíWRWÍ.2’|¤Ž@0ïOî]/ÈL~¬ðÎe`f4ÆìÒ¨óÊïqQ&ò êüÐkÀÁ *HÄâKÎÁU0ÄŃòD»ËG ‡‚VxÕÁ“AÓpÁ5n¬âa„Oô )0DgÑBŸ6 ÄE²ž•·m©/ìGØŽ$ D:ñ»]ÇÍï—qeDÄR›aÒ_”X¯%|·LÆ F†ÐyJ¢öóµ³£º¾Ö?bŽ÷ªÝd@¥fµœùÓX‚kýÚ“O‘Ú[:!¼𩂬€»b–pA^æË‹* ÈT«¤]D?Š Ðâ½qOØ–[[ôG²!w×ÃS£&r`‰_!›÷!"Ï¢« ( |ÜW¯#4 ÙLJòáÏü¥w|p0”dö€P¨Ê¤ØGÝ*¬ <³ ¸{Å?¬(ãÏbs½ŠK¼­ä²¬Ê_’¹÷‹;8ÖÁc`™VA'œ³Ï£ñ7~àÐÞ³ë“ܥÔöã¤7J_—&kÊ*“v7C1¦Ñ*$ˆ¿Ç29—âð#þV¬|è";·•$Ë@ˆ%¨P‚plÿÉIŸ4×ÚIýJ$óFª7Ñ‹ÀkÏJG¸œ…Ýñ|bí$5œKž bZé+˜×ÐÝRZ‹a3Ùh%,$¨tfÚÏbžüÊ"÷ÉÕ½p¸8|ÀŸó˜T[Pü¡……„¼x¨î÷F“…Ãw ’‘[„«Z*1ðbŠIø ‚S`ý L”)6‹bᘸ ‚­;XÖÖÄE¿P&¿÷Å›0` ±hòì¬æüá;"6k?dÎb\²£Ë…à׈þC"Öú€Jà{A2ãÝ&©Ëýj6µžX† [Œ~ÆNH¡W@!XÂpïø±j`Ó¼3NåÛØÜóƒ2üZpyÌ9Z‡”º/‰y/¤%àevëŸY—SŒ ûÖpâ\u²N¨i,ñYŽ„7 çrWÄV&ý8Ì Œ‚È{JpB¡3¿8bLü޵ SfŽ Ä÷F‰ ¹è1Ïû7Àçïð´3±Êä,Ü6hEÆU “àãÄUxóe­`Ü•8Er`}ˆh°è„ñœËXd¢¡ÑãS‰îÈDÁÌÍ—òÞ÷Îá‚–À]ìÁ@ìGt=þÙ!<˜© Éúæ)?b¡7ˆ@Òh,âIõWg—Âe‰•ÃÞ¥±’œ\ö¾ÁOPx` C‘èsu†ÊZ¼ªf’­?ßÅT``rì fåß‘´Z ª™DGS!$ۛ℔ã?i’ð .{\ ÄäH Ø'ýÝ€.Ÿt˜Icýo¢›È‡¡üemL%€ ÷A$,¬éÚ‚¤è- ^'ÿïgX–’Ÿ»µJÂò ÕuþºU€˜9ɉìk ZÄþ¶¸Ñ£n.))Lû¹ÑuO%Ÿzq/]Ý  mD ¼éÉï}á€E€ËV1(h ¤U¢3ñŽ l L`»£B•׎{"ÿzÃ.„$Ô¯™X„DÑ"&zðM¢¼š­ÁÞèb54YÅ;ÑÒ=0îß:/F¾Ì(ˆjRÜíšÎ†Ç˜iŒ%çUS¾[U‘ÿâËôãËûþ1æu4‘¤ùeׇÉe¹*J Þ¿5äX0£OË{à¹>ô2 ŽëIŒ¨_ífÀ óÔ^"ùA·Û™@˜õ~¬ÂLÐõEæ¿k 0¬q!æ¡Ñ¶7>E³0ÑPIÌV¸Çô °<úö$›2̓•;TÊB]ØÌc¯bùS8[ÀOý»B†±jþ†\ Ñàìq§£ 5Ø:e8:!ð÷Hi€ ³ºD&üõDïU÷Ù ¾ñÜx´ð†éSƒï˜û„Bø5;®1ç|¯æxû™ú/¸èóòfböዉrxT¤ ª&y Þ…¯¼ÑÓáUz ft<: ºñõÜî ÁX•=|WZ¸Îùư ß!´%0:]|‡¼Q}÷f=°Pê¬5‰úüi±Šø¢ÉáD¼æÂ™ä `-¾@¡oxP½!×ô ÒÅÝš¬A=À,Êè½®]IYà)b´°é 3t)òoŠ~I dý!``vˆˆ³`ÙQ°FŠâQ`¾úöÎs€íêHÜäåIVóñ_vÏqINÿø %,ã« ªeã÷ñUxªÔxK5࣋¯òKüEÑÞq[$Úñʪ¬UHã€V&H°KW‡ À^ •û a¡ßÿÏ (̶‘¬è.çð‹Ëê~@«¢€€yÃÐnfñƒK¶”ŒZ˜@˜çü°ZŒCk‡U0d;~Äë?ôìcå¥%ùªø ¯£_f~Ê•ëÞV»·x2T t‡7Øó)†„xÊ_YÓÐi_ÅûAm n@J! #Öc€ÀV@i\«ññ¬s¿Ì¸néßd Kƒ_ƒ ~ç" ±ŠŸOÀÀaŽŽÒC?2ñDC@Û¢qAm‘;81˜ŒÂŒ¹G°_E1¢s?,?* óÔ#Þ–Bj‰¨Á€n Þj5ϪæÍ¿Š¶PÎ5³«ã×à-ˇ‘‘’†îx€{‚ê0ÅDAá‹FjÌ4-Ÿ) ¶Š_ACy gÎùàaÄIj1„ÃEì¡ý:kÓB'áE_t+h¯8²#„Á¿£[ÿÔ›D4Ñ„V{pL óåî'Fõ:f¶ î– a§_Hóì*ó3å-¶2ây[ùy•TáÆ‡QK½—^³ZÕƒÖ~õþ†GÒ |pЭúæÉ˜Ñ~ÏZ$1ðõãi ýb0,¥ûB!Â4* “ãCx⪣ƒYæ5a^±4g# AtÄ&ÃFíc³x˜Èx î9d¶£ã‰¿u€ vê0aÃ/ç§]ºú‚AJJ¦š®xxo)âuÀõs÷Ã=Ÿ®2I8ÛÎ`àÈYr{Z=Æ5X†}îˆ4oà$¬ ç’b@T0u ßÄ ¶ÂjƒŒ÷ܰâ½?Rä›È{Q'¤àÎÆó¢x72 ¦¨+ö ”N©øR„*êxtBsÞ]ƒ;ŸTÒ}!pJ;E*ho£ÌÖZõ$ÊÂëÓ–E14zK’ʃ`ج=#hòòänª½ïp7÷ •¤˜Aº,$a‡Í9ãÅn_ûL, ‘§#ïBån>}_VªŸ«†‡ÜH\܉ó„h¦¢Ðf"X…ßÌl"VDãQH7¦¡_Ýjo±†ƒ–Üd0 è-ÈÙ¦‹Ùo:FªA¤$öBþή?¤íÒ×’˜Fxü"•À¹¸€wT½ 볦 ìÌ&û‘ÐBE8å|j¼!‰ Ü"®*¥+ãv»Ù_ø8Ò.Dã"Ϙo_×ð@9ˆ©ÿ4ž`v¶.YTon ñÖä˜Áø•czëú™†/C¦ÆbAbBTˆÐã&—Èò§½wÂÎ:/çg£‰hmÁIéF/¬‰4çmÜq!TpBù!Ì„rƒýðÁ#\ëÙ/+=X3(„#¡;äþì}ă<GbÎZá¬J‡(‡·Y#æPPsŸM¿ïêØ^j‹L@êhúï#°=‡·ê ÃßHú¬Š˜e„³ûÝö‘xM¾ƒ(nPOP ,rëncyÖ@ñºJ½ÇÂ_ºÝÑÇq—™Õ\U—®Í"Çij"•)‡÷°Ûv„5ßmÙÒ>4ªagENfÂxtR¥.è½õe±¢Ú æe­è{„i -àg&p•H˜ _"36ëBPãEÀ­Ï7_xì¯Á @b ‰J‰àE½ˆßF …X¤*Gê)þ$xøq ›‹hlQl6ɬ~_‰Ó‹œæÙʱ©ãï¼Kˆ ôÂÆä\îE0ó[-­`µÿXö_‰Žp:#}H,¦2`ØÚÑ,ï"ÛÕØUå f£ÒŸÑŒ~*˜L4WìøÖ0j“ϳ¢¿PØ+&[¿QúüUÁ¯¨ÁáéàrHý\ÏF–,Á±¥áP¡ pÞŠR,¹Ñ#—c±°¿é–ç3®¦=âaËwwjÁR?R*Ãô+$±a®±(°zEåûd<5×:›íE)ï›v0ÙU‰L%\$k-Å&\t„PˆèÀð1Uø¡ô®+öÄp“ÝtA)D„Áx@Kö×`\é(]X5ÿgXžfÝy¬³Á‚ÎŒ°È°ŽŸ;D…Yáb¬ øë{C$JxÆÏÐÑù°OÁyÚóMbp’Nùe­“\Í–µI9bܲ-IÒN; M«…ߺð*«løÖTC·N%G Vбî™Y7‚ùêx´vîʦýy €ä³"³’[ƒ³®û`þô¼ëÓ÷Áâ3½Üäbý¢äî[[VìXA*BØ ­Œf¶ÇÙ6:×®¡]9Ú0P:m–Ý,®9¸÷©3t̼†å玲•IòàÄ‚ÒvŒVy#Âà2 Bèø„AR¶5$ç)ÜÌ×Çn¼æ­ed5?Òïcîb£:ªÙý¹'šñfüâTØ¥Œo’øÄ*Õ $}P 5Õy Àé„z0€¼LY[‹–Üpd¡²C$‚« Áȃ½` ϲÞÙçÙ!ļ‹D |YÜä½ábV9ï§”‡Ô³å?È5!»«žySkNøÂ“:H¾ç²ù¥%°ýT=9JvÌOSǸ’$@@·‰aÏ‚zKC”/»Ãé ; :^•{4 B!ñ.$"É °ºÁì9éªßnm'äGU¸üX®"_Ì×õNä°|&vLËOˆÜѶ/øˆgš7V·Ùæ“^D4MV'­Ì©Üíú€ Q#`Ŷ25úÿ=HÜøþÖÛ_%M·í©„ˆQÑ…Ddt÷ˆŸr‘z\dóÚ(íŽõ~N<›H.;ƒ±ÝÀ<à·ºky§RnŽ:~ †·ù 6œ¶!âžÉ…DZ0•K˜“çüŽüd#|‰â^ö0ž9®#pQÄ(ï‘!ªn"}ÚË¡–<‰.Ñz½íW§ãBö&¨eÌ÷•B±`®jˆñÆçÄüâ„`7q"`t»@¤Û¶åÊj‹ÑV¨o]užÍr & |o ´à_A1f…ˆD ¥Mªw·¼–¶vú³9Þzm{¶¬>í‰1½ÃÜ:}^núLÿ}Û»¯Ì$xL÷ÂÛsÊgèV¼ÚQ¾_‰þÂ&hnNÔHL8ẍÖ}ºÒÿBÄ|Š®±L¹W"îî'bI·aw R °þ€ùø¡ÿ`Žz}òm³ìpë…ÃÙ‰'7¸“-&irVwú~7–G#,aÐ)ïÜ‘ÉvË}H¸©N>ACîVWÜólº‰66^o}þÍvÈ F³üIÝŽ¢r¯Œ,Àk¹÷‰6á€Çvÿì[ú sEءݖžÉƒú†+ÛÂMF¦Ùº‰iÓ‚ ƒÍOoܯ ¼ã ‘×›í<*󷉲 ŒN(ºÝŸÝnò÷ŒØgDW‰O·UFxµ Sܶ°¬k»×ýÄcÇõ01@ý“ɧ{ÎèI†ÝPPh  ФªÌëFè‡/›ÒÐt¤áæ,øÚ™÷&<^px9½ÀÐc ]4H…¼³ÏHžB8·Ì¡xœâ‚€ºŸÖš—LT8 ”ôë;Ö8\Ç‚ápl±‡¤ƒÄ×¹}Š—Còð .d+JC³ÌX…„!¥àPt2öµüºƒ> Äþûs̼–vÏz¼ØXåþpWxI¶}`t£: 0âŽæzèë;Ïû‚+æ½N(ñ†ö¢Ñ Ca‚ç§UµÏLi•NÄ=yñ·X®_W(ãs{©±Ò§AÝã~q¶Å‰xƒÂðbiHÛ·–‡^°MjºP ƒ»V­N âܨK©°ƒäAì#^¸ÿÀkùÖð¾‡.“Õ‰7ÛÏ9j½nŸ_©Ÿ31µÎÐþé(~“XGë¸÷#¡ 8Ð.922â¶æ¸Õy=é]PŒÅ¦Û¶KO |‰, û‰&œ½p¤{ã·k9%”Û¶1OÄ’n÷ºKÍÞ~@é6Ôçe Kªõ•m¥¢vºÍ¼î» %!æÔLjÚàÿˆ|¨àoC¸9‚›ËêV3Î+ww†”5Êdœ¡`ßšBK.ó£ñFÎdjÙ€K\#ËÏ$„‰¹轓d~¾U=ÙÖwôaÿ@eAÁ*L²Ë*u@1ê¹_PÉ<Ü·â-Â([—™—[õÕRÞeÉPŸ•¿ p[j¶3Z+‚5Gg%—eôZ>ãK‡@lja_ܼrKÁÏT|TB¯DÅø÷ ‘þ|vAn›,c5Û kÔ« ¬×Çïºwv£‘ûõ|ÑšhZO†È7CtÓ‚‰UÂ{œS,Ö²Åç< H>ÊžˆæâûXŸ*(…èŽÝ© `e·(Øñð ’ÀÁöh0™@{bì­9[$/ÖLÍ!\[~t÷écôƒn"è¿×í·.í¿>=¨Á-ðÒ~‘ïrS¹®r~;XìIé`-Öj#$Š<‘px¬uBônÔ¨ýw¸®.ÏX ¾Pk jœÿY a¨¼9ŠÊñ¾¿Ã •4n’'PÜCƒy’™Vlt¹,X´o~ÙMÌÒî]„ß²‘Ne7‚}9­N>ò5+_@}Û•”m—6ô~lH)zÙcX:·  $Æe£d¸]°—À}”ó mèî Ü;6— 2Õ<·;rkO’âF#Ø©î~ž˜gÒLH÷`*ßâ+6=Ãñ}G˜^©Øã6Ý3 wôˆ'UPn¢ŠÌRš½BÈK\xRÿø;YÂÝðPã²ÆÑ'*Ú]æDÖÊ`•ˆ(Âr…;¶­àë«"K“í-kÖ¸<ˆ¡ŽäT˜`$óÙ<Ä9E EÜ*«JÆéH‘uÁF¦'òÅþSìŒç6œ.æúEԇг?‘¬®ÐøÞàO¯#7†ÆÎ“,O¶ÆÅ¿“ˆz6*·=vqjÙ®€¹–ÜX¹Ñ ÏÜßù¼•5é_<Ò˜éGo{ÒˆðÛ0… ¦•)tÔÄåÆ/hA€ ùL èßáMmè®ÑFŠb¿;Ë“‡šÛw¦\<ðÔäÝ틲…½2"Ä`–¬ÑNL¨¦ÈfvmÁ¶ Cãa—ë{2€ Ùm–Gg EÜ éë:},ˆs<ÖŠ7Gi°VÆPî‡ák2£Âmm‰ao·i ²œb§Ÿxe> çaÌ#–ÈHþì†Dg³V­2èôžîsê:éø¡ÂÞ5±¦ ×¹“3ÿ°\³mˆ‰Ì¼:þ~÷LvAâ¸Oþˆ ¤Ùc3­&Éž%›tP+Ç53&k·Zr©ÿ—ø¦i _ƒûjg•ã—˜­Øô5ì¹{šÙrŽzT\²{RðRh,R(0ñ+ ¼ž°ºðÚÚ3#¾‡ €Ñø‚ÍÆ‚S¢—Þ¬÷Z]JÌóALÛA7†…[ƒžoXÙᇾC¥êæN'RѨøƒïí5iZ°Oëfh©‘2’³‘Ç¢äÓ ‘Y¬ÑŽÇÜ rѱ@4±üaFìÏzåèí<ÁÔ×»ðo ÐÝé²7Hpã0¹ÓŠ™#ð\Övô$Bßå·>ÐÄôÃc—ÎÁSDD|_Èm;ì<ª674ì¯r§qô¹NÌêÀ:üz‹0›'rø?ˆÄá?ÖñêÙŒ<;,<Ù²F΀êÑã^äÏÙŸ[xnË:Üg‡Œ-j<’½5ÍîeíR¾A­’ξáîgÿ ‚¤ÄÎVK‚.ªGžNÏJž>•AÙ=R%úÚîÑ´ˆYú$ _d½ÅÝxúCz)zF*ýö ³¶r…a˜¾[玀-å”}ž°YOÏI`Yt:„Iº—þ+‰êŠªË®CÔd›#j£$DÄöGáåXGMë± î#Ëßša€‘éugj(h6†ÈG‹aEt&Èh"úòLËWd/¬Ý:§á6aµì¨8ñm(γˆ£¶{•õ`ÔƲàÂò6ÛÏÌd½Ñie²Öñ$÷üøýæQ;»×9°…(ˆ”‰JÁß RRð@ïddKàò®whtOAà‘ê=xm_ô°BÓÁÎa+Ȭ™‚çÈv‚&X„jϵÎi€SÅñÚÞ¦5½ ž±ÈÀÛ8•„{#áÈøvÛÞ±rˆŒÓ €Ì¹j鞥°Éïù›Y0£q&¨½„UþZC¸Åíš>©y–Ö=A{ð,ub!Æ‘DŸe,¢ÝS¢¯ˆ›ÈÍLÔížèg×ÃmŸZ·O ˆùª¾7úó¹ÜêBV¥ËñÀQl‚` ì¯]n2EóчåGR̦K•u%‰€+œÃ•ŸõÇcïG‚¹T¢‡,Ì>ä¸Ý4±•{xnôèÂ3£} _V+›=*€•ÆŸðµeD¹`óÅŠ)þ³b‘Fú¥ó‹MbÀ‹ bùO%¨í˜0áÇ…@'ä~Å„ñèCæ­°î6:ÛfÞÎY†ú^Â÷ÆdØÛßH„¹·gñè4A+ðHϧ!;äH±æõˆS´ŒúâÒ¯î¿/!±mÊóÆò‡îF¡Jwr''‹òMAü<¿TzHržÒ^·Œ;O—5ùe»NÎHûÏ^ ìÁâ]RÚÊÐÏñšÍ:ÚàeY¯>¿j7Ì›-gäŠ"d×"n×Çbµï½[²!ùàæß9U‚‰w÷©ÄáHQŠž„ã25“‘%2™itvSº£GÚ†-#n,¼ÉEPzP‡mÖp ÿœ!«vÙ`ÏõŽÌc`Q80Àéa‰eç<>Q+U¯‘¡@UèŒGê;ÿ6F®Š)ŒD’Ìž1{û⠶ƒÖYäõFÛ³ÎIëHŸ»(ÄP&²rœˆ“t}ˆà>>tìvOùçà^=ÿ´Ôxîý¯šØ__ ðà/Hw‰`ë…­n–h΄Ù;RTWÙO>TÈ–lˆ{¡?Oð,‰;x½‹„&?¹‚íèžêÖŒVŠYý[Ar™j_ÀÆËû£—DœÂÉæÖuCÐÀ§GKžlÛJÐ|Ì2Âr=–ñ»{#LoLVz#FÛ¢ÔÔÛvÛMx4žƒˆt/Xè¯KxˆäêÉ_;ÖµÙ³cš< AÎ!ò»š@ õ \ZºŽncáZ (, OøÄ;º-W” ãÖ £x=éxùBüS­µTøÞè×lHs t #Â>—{`cO‡Dµ´àéÏ›ž8ã~ªšBò9á‚Õ+©‡ ívM!”ƒò8Y°–BzÝXJëiËbÖ!T± ÐÒ#³dÂYV[Î^ðÌoœç¤ƒÅF€aÂlÀÈ€ö³ÙdÍÕ·È'ÜõJnô¹=“ÿ§Š¼þuƒ‘†Ãó[ˆÑñª”gÙTšŸÞ§ç‹ÐoukóòÊ\² nê%°0Ü>>b‰0 %½žCíÆ=÷ãvhk<ÛÖÛr8¯íá›%±ºy\ÉîO´høÉ^pN"¡ÄãÅH ;·Ð‚à„G=hÊ]ͳ©ÍÍ·²Ÿn‹énjX ö‹ºMžáKžÙ@Ëd d÷[¬¢KHr0*š°½VK‹pŒˆÞ½œ*!T$Âl…oÙpàFLEÞå[¦}‰”y}ùö¶¢Ùat´÷lçÀ9†ü–nk§7,xÝ )x²}ÿzÉàÇ{/W[¤jómÿÚ-¿=£wåɇ5~»åÌî žêÓ^‘Èô%»ˆ˜ßçyÇ{©]ÜóÈ$¦æžÇÙÆjÅÍ—e޶¬=ªW°‹É“§Çe][ø/{ÀÝKŽ&TTíA.¿"rt%ãSH: pQ•8ì^yÑ,Ö}žM-øº'x€ì“’¦‡°–÷xpµövXLá¼ÉøßX…âÖ©*,¤ršÄX6;E€¶Y2–¿,”÷Øt·ÿ§çÅ`cÏwÛG¡ý; ƺ_öí~è#+ß–5ª«€º4¡ÎÛßþ¶Ÿ,Äê9ÛJ:Aÿ Jc]ãì7¯vúìåÇ ­rª4»Ý||Ü\§°Ì ÔãMž'îŽ{Úe8&Èú5Þ_ß>CÓ[ŒðÙݹƒ§”"jéK§L‚üP-´+º‹BsóÎÐ9”Íû’+ýŽHÞŸ;Õ•ĹÍ~cíÜ!Ý~§y9Ïð@%ªs—LŠþÏÃ9ñVœÙG¨ÈK6 Ï{Ê5Þ*3yXاΉßlÆXè*rÀIŽkuÖÜMƒ<â) fÝž÷ÕõÂL§ŽÉ¦iÒþ¶BnÆéôBgw"Žâ\Ë£ot–çuo˜ËJyÙ¬ìö øm=<‹¥žÍãñÜ#-ž#›:û³´;,® NÀs 6£yVbq¬,¼Ã[XÇäù î-0ŶFñ®ëýP€h:Oiïá<–O8uõ5æ§½Ýc~!ŒùSJ‚ŽÍjöDÄy®dˆrÐ;•ÉÏgõ˲˚ ö øˆå~læ÷ƨí©È{¡{vt4ÏA¢Ž†mÞ8ƒ—çØ é`_‚çµ9/Ðø†¾.O¨|Mڞ˲Á2|‰Kø?ŽöÚ7}"Ô‹\áJ~X5´e{”û0>gƒaßÔÞYPxÞ+èlÏݘ%³üv¶käsT#¤£ö77‘vŽxÚÝØÃ¾–½“WüQC#ÏadÜvNÏ ¢mW̯ÇPWš§O`y’©‹ˆ€J…4v¾€½ÀÌ™ýÌ1q^2¡`ÛPàáÉùZ ~BPŽyì„Gó% T8L¾Þ¢–G¦,*^{<‚½¾¼iö¬º­ŸóÔ¤o;y½qª¹'N@¹YJ@Ú ÔaQ˜€OKçÐéð6•zŽî{TŽûÓ*Ê[ÍýoIþú'‰E3˜!3ÀqÅ`g(ôØ’–'{úЬ¼”6A4òàb'¼¹žÏ9íÔÎÝåõžúÀ$Ûot®Ý«=¼FÅ‚ÔnDxNæˆ\÷;¯5k±ÙV9ˆÙâ»5 Ýû}¼Â[ëm5ÒdÙ!³ñÏ…n.òsÝ#{Y™±Š­,V½,ÁœÝßd»F,.WïlàÛšøz*צH[ýã¼ì§Ô-{Á‚;8ï¹Ùu=škW6a÷ƒ}h³Z¼¶ªB…^¤óä¹{iælœÞ'7î¯7<í3ÁÍC™Š2øi<8·µyãÍijõqN½ïWY,BÕå|l`~‹‡”_‹øÛ= Uâ:ÉI6Ù{ÞÝJF¿KIŸ=KdäÅpçÙš«Þ¸!h@Î5zLF£mSE2<Þw<ßû»ù¨÷s~Ñú*éEÞßEN€ç˜÷m 6~^@¯m/{ÍKñ"8‘+Pô®¼çœ½Ñ§Ý]^ó;KV|®3˜d[V WðÒ³þë`–mj¶9/Û`êAmñâ³ÏìÔÁ…c›¼Ó"ÃÞ±ßâ£E}m>ÎÊBšw³4 ¨[Ííy§vñ.‚.®¦bw:vlb&‚pœ[rCÛ'(½tÏóÚ.ï&é“°Jq¢Ø¾âÝZ Ø àµ@‘h·¡ýR§LQô"6o' 0^G#›Ò€Ï¾¼Eè¶“ƒH"Y]òÍp®Œ×«íì¯úô–_ïªÛÆÞàÄâI Ûvº4ú»\Vn Ô…¹b"ÜHY6ÍlU¶³Èd«^Ÿ=-)¥e£Û_¾ºpÎÛ3[µÆN©ÆŠª7ó­s`}xZn`ûÂáÁdèÒR·}7yÖ6.ÏG PØœE–Îè ±é^¤c¯±¼‰ySë£9Šwò¢óI¾ÛjÝURS|ž²îSW²å.œëNà[K™;5>;ÔŽ0kµˆ•7s÷yOÞ‘œ8ÏÞPã–Ûï;/æZv‘fÏ`44·yzvõ´ë}ÎgÛÏ‘¯MöÚOOM‚#?Vï«G}M“Õ½¨ïõ,O&oÏþ¿ç¦`"'Y*;ëp…ç‚ÂÈnÏ…(0IV[¿~ÚÕ8Ôà@-¨–T5dO½=¸Qµ3ÚØmc f‡á•œ¼î™ %cà i…m³y / s+ܶÕ(÷×G"¼Ú‰ägÑf|?î"–žÕÁó¹©ðô;Jú؇úý.и­ ”ëLaïù»LéÖC‡6 ’Σ7÷œìÕsá;5ß9,h½ý>',M;Ù‹5È5ŸËû *ñ÷+ª.dvúo½îñ¾ÚÐ2ý-ÍcŠÑ_¸Y2‘·*©x7LÝ–Yù¬Í“Kq_âõšJc”|v2t Vo[,Ô^Vãǘ²lO±€ º-áNË%Áë ׄ;b;›pÉs\öëGÏ(Ù0žž’.ØÍ«½º,ØùÞ<Ó€§Å‹K¼ öz0ÖÓÓ4k_.˜5(ܽeXË„„Êwàµ,^mFÄñ ½õÊDÓDhâ`¶ñ¸<ͽy/ Y ?póòâA\DyQw?=[Ë­›©/]Èi-')Û‘ú¨)@"{RuWa¤¬'È*Mê"?mÐf=ÎöwÝ Û¯ì’ÓRÜjFí¿^Œ:•9zSã)È)(?b«¦ƒ·×ÛÄáu³×9½çí}p&zÑ 6ˆØn6ŸÙÚ‘>ÑNò«xÄü&öº†‚½´‡<–®ž{˜<îg„»Cçs“»Ï¹ï4!x­‘º¡Uí0Ë6Â…ë)!Û{ÂüB4/ÞÚN—Yâ­–V½ÏÞG·×ñÓçàê“»˜íÆ~æžl èªç|_ÀÛ€×·à_·L†l©ÑP~¸‡Ížoºáµˆ-0'Èf^ÏBÞèèÆ}j÷ˆŸ‡¦H0ïˆï‹±’^è‡;³à½Õp•K%ìËË vLúAK¾t[y¶ÕÎZÀ\hùJ³ ì–âmŸÄ‹î°–°¯s.Úî+†¨½§BÊn~{éì+}{°?Ýž&èu¦“ñ’=¦IpHo¾ÜAõÚ3LNõ*AäËäVOЧNP§–Ä« ]Þ5µ?øÆ“›kNã'Ïp Q^%¶Ý^ÇË'ïð²–$Ÿë”ªÔƒ¬!(-! §Š9…×´aA¥à^&’ÓczÞy´¼ÿD¡¹bܨÜîã}%Lk;E³½0ñ̾OžüdD@ßðþ³Žs'lA‡ ЫgâýîÙÚÁãM$óC›×}±ËsC ãW‘ÚíÅ¢þ}€/{*KüÈyª,4ú¹JæÑtÍý;ùXNc¥5ë¤ÈckÓ“êçM3³|d½—«yù©t›7 l/¼LÅ–‘s’ùs{à=®bÌ‹å“ ã8Ì“¼jÎÛÖ­-x¨¢°ÖYàn¯ô†Äˆ ­Ñ{”3»lMÄ_ý˜¶ÀG§éæú7·3ÿ¾>¿Ë>j[§¶HŠâŽ€»Í¼®È¹ =<™U!ø×º€ÇÛæ…Øž; `¡†ê”½ ×2´§šÜðƒh=æè}©{¸‰°¡}ô}ò||·ÔYH?"Ë HŸÝÅ@K$²{VW‹ž¯¶ l„Ÿu`¼”-2ß¾sp8K~÷kÚíàÔ^ô ë$EKÏonüó¢i{Ö‡—¾2.qÿÞÁ³Öü.éFý}6ìyU>bøYÉ‹”*)ÂHV²K¶E4Æ^¤`°›„)»ßåŃä›ES/Ö"7ÊÝŽ…!ÙkÌäbeÃ9Èã6q€°’7lXq¿ì[^·ùØIB2w¦¶{³ °’J°e­#®Âe ôó:…Ëm¿·[ý^TôxQîuSJ¼ÏÝœgœýå7j“Y½”ÿ€‚ÇH’fÏé¹±do[Óìå‘PS—>ëËg+üñ—ЭfCÆ8V5ÆsNõã"Y¶tÃvâŽ\†­¡ðUù{ âgwô°I‘ød±/ñåÜYà='Ã*cµ¦^p[ùTýPkÀy Ñ;Á›rÊÑz¨Fþ·Χ3G-œ»qvÀ®½^G³AªÛë$½ÓpŸxþsšä,aã%ÂÝ[·×•z¹iYŸ¿½fÿã¸9x~ÁsNÁ‹¢G¯4=Æj¼6qðª©ÎCTF%¢¢iïz¬\°Ô^VØP7÷og$%]¸‚P÷`–Op//)D4]ÍG²t+É­aT‘ËF”¼‚‡àñ ÷`â,všzEË÷wòËÉËíÚµòîê¹ôÕ{;=í_Þp}gÛŠ`ðz_ 2œÃr ¯‡Eey³Lôº£ž~÷Ͼùô'—:¼ÎǤ¹/Phþ®O{¼²³Ð0ä½MÑëY$Ð×õ1­ª›sÏÿžW–ÞM;ºQ‚”^ï÷CÆ4¥Cñv ¬.b±8ÂD:{ÞÇ› Ü£xŒÖYÔ› ß¿Ÿs™‹ÿɘŽÛÆÍ =Zófë „y½AÉÿ¬P¿U{ëµÙ¦xÉÝÛ!Œé6ñsE/†}BñnªåeÕ[N-ÉÛ zÔÀ¶@ý†Û~èÛ.n@{Ó·%9¾‹q­ ¯™„Ž14A?æ;á£yPp÷Ò $«-­º&ïðúSÀÑòj²Mi\F(Íûô-MYmV'qŽ=>eÔô¼áô·{ÂÓ†Lö†Ñ`›Q™üÿzŸ÷\:é‰òji¶Û¤Úd75{Á9yaΑëNìc`½Ü²œ:#â‹ '@/7®Š\_q2Ê'ƒ¤ÀÎë>ˆ`‹öA媱|û-jÞ^kðxû8÷ôËŠ´÷“Ü`Jì^Á.X—Øý×V´¤¯›âhxì Û˜HÄøò¼«ç¿?»}¶7¸øßò£•˜Hpa{@3Û$0RB‘®sÑ–·ØÝV°cëÞüG\/RÏË`´dÈdÿs$û³ }²¤rTá¯ùyïÿÍ:£_ÿ¢Æ>ï ¾þ<¡õÃí8fa„iCCPICC profilexœ}‘=HÃP…OSE‘J+ˆ8d¨NDE:jŠP!Ô ­:˜¼ôš4$).Ž‚kÁÁŸÅªƒ‹³®®‚ øâææ¤è"%Þ—ZÄxáñ>λçðÞ}€Ð¨0Íêš4Ý6ÓÉ„˜Í­Š=¯"€0—™eÌIR ¾õuO½Tw1žåß÷gõ«y‹‘x–¦M¼A<³iœ÷‰#¬$«ÄçÄã&]ø‘ëŠÇoœ‹. <3bfÒóÄb±ØÁJ³’©OGUM§|!ë±Êy‹³V©±Ö=ù Cy}e™ë´FÄ"– A„‚ʨÀFŒv i:Oøø‡]¿D.…\e0r,  ²ëÿƒß³µ S“^R(t¿8ÎÇ(г 4ëŽó}ì8Í ø \émµÄ?I¯·µèÞ.®Ûš²\îCO†lÊ®¤% Àû}S¸úÖ¼¹µÎqúdhV©àà+RöºÏ»{;çöoOk~?\ ržÉk‹iTXtXML:com.adobe.xmp ¡›xÉPLTEU  #   )53 - 3 ) 3 /'  * 45! ?!++&F!>$;C/*! J6"#%"7.R +X '/7"FFR8%/*.(#N"(+-:'#Q#5*!4*(+-*Z"I(R&:/X&4-=b$ 1.K+2;?.2p#b(D0"a)]+ 841g(j*\/ a0_1R5U8G<m2h4 n3;@MV> IDFAYUA3t;CFI{: p@MGA„<z@KO^HGIp~@&|B{CvFMLiuG'eP‰HDVRWtPdPA‚J#„JjP7‘H…N‰LZYrS+šQ“S!f]_W5q^Nxe \1”^—_ \ge‹b>Œf§\.–a5¨^'¡f¥b/ŠhMxop„m^²g2³kªp±p:«r@¸p1¨y «uJ¢}'¿xžÀv/²y?º|©{W³€§zv”uŒ‚‘žfÀ}E¿ƒSÅ‹³ ¹ˆYÊŠ¿Ò‰2șϗà ϓb×’Z¾™xÉ Ê—gÙ·œŒÐ Sצµ¤©Ð©Û©Ö­ß¡nÚ¨xϬɯ à¹ç¸ܽê°l趆ìÃçÇè»—ß½£×¿¹ùÆöÃQýÈFñÑîÐ$ûÑïÓ>øÉ˜ÿÕöͧêÏÂñ×TðÑ´Ñ×åóÖuýׇܸúÞJ÷Þjúä'úåOùÜÁüç>ÿêþÝ´öÞÎûå€þá¿ûérüè”ûîfûê©ÿæÊþóZþë¼þóŒýôœþø{ýóËýõÂüö×þùµþüåþüðúþÿýÿü û°ZtRNS@æØfbKGDˆH pHYs  ÒÝ~ütIMEål^GüÐIDATxÚí› TSgÚǹl± ŠÅ‚lR™Ê¨K…!V¨u¡ÑÒ²$ ‰m£òYÁV«¢hU@Q‰VÄŽ­eª²4Ã2 %Ò’ De>À¢ÐF–(PTî<ï½7 í2ç;ç{<ê©=—çwÿÏò®×ÀàÿMiØÛŸÑë_¨àdòjPQž¯ãÍÎÉòyÖ°ížý¡¢âüZg66Ï¡ŸËâGÙ=ÛsEÂÂ/„º¯Î³±{ÆŸÄç-t]Îçïž=æ'‹Šò²}T¨ àžâm9ÉÍèÙÜûï>·{å ntâÆÔUczô|Q^ÎÒÏûô˜K ´´s"€ûÈÀÝ%%_o ^˜˜È~á—ß>gíò®tlב²wåËfvcÉ„ .7È×¹?— ä–^é¾$zãAêzߟÎFo¿ö W®\½¡`Šùñ”ÁzoK›)t£_|ù `ïÝçr Î~‚Ef–CIå‘•ÞK6®Ù‘ž¾“þ’î3û‹„¼ì¥ïƒ{°ëLr¤¤¤¦Z1ÝÆÉ>Š–ðò³æ…îÎÍ-8±ó°‘öInɹsç._>²Ò?rëÖ;32ÖGD+ø`¼zΩÍó¶ÿ€¼W»WwèÜ»ÓwGJÒ¡´@×INnnöze€w_Àt]y8÷ĉ¬5i½¸µA€Y§ýó20”TžÙê³>1uÇ£¾ý6ïÛ/¿ÌËËË9•±Ɍ姑÷«W`˜^›w{1lÕÞC;$„:ØLqòt²ÆÀBÞ}üWŸ÷_'¾lC€Ù ••Õ¥G6…ÎXÁN2;û7¯}#tùgnîKƒŒh#,¤Ã±Üq(++3mõtûÉS̹t'KKK?P~s¶ûêÃgÁ}î ¿Ç{Ó&©À\ .WV]zæóMÈ>ÿæ2ìèåϸbF4KKìGÅȶ0!d%Ãdggcîâų1¾3B·d!ï¹Yl#¬:˜ØaÚf½"÷rue%DZi•W* ï_û˜b4èu6 W@Á^Kò‡ÌNÏÌÊ: «çy[û»ZÚXÚϳ ]p"3 ÜŸ³Ãh4³zï_˜›Z+++kcc"2­àòeAuié–H{ÌÄÌ̵[½“¦ ©^Ç)þhX&XV²gÏÔ‰¬¯.„ ÚØÑÜd8Þ};ÃÄ“°rðp°¢ÌAÀ?¹:؇úÚA¡ÑÌlìœÙÙÛ»Ž0Åúø!M=gï<ÞUYŸ{ö` b*Ú˜„ÜÆñ¦¶U&n˜ñ8¥)1@ cãéÓÝíÝÀètº…`ã:ÀÑCÃjDÿ$.îøñãðö™IIn4#DøMK¼‡ã×ïÑ8îjçì¬}gùxúø8ÑIs¢`{ÑXÔ$& £ Í’ðNˆi’ˆ¸“Âä{Ø:èåßÚÇçM¦'“îæÆð$žTGfCy‡· ¥Öãø@_Ž ßAÀÖz¼¡¡)˜±yøÂùLT`Îs£T “… :¶#Ø#Ùáõí(í¦˜¤Jñ¡¡öKÎ: €wëÙÿ³aφ¥ÓL Ãç²ü—Áp£Ba‡ÝèØW¦ à>2òM9GÞé>Á‰®C"®‡µ–SÃ×OVˆÅâqMmNÀŸ}Y,?ÄÀðõcp2ÊtËÐýhæHvTþîß æE0SÚð¡Þ–ëÎ< R©oj¸G\#­»ÞÒÞÒR'F{ùú²€@ø`¹H7Üeñ~Tð}+’Ëæ°`°¥)lƒ©1FDœ0 ¬®k'íI}ß… a1™LÄàçéI¼#jÔ°JËÀÎŽîÂáqÀ˜)u8>ÔԷ¯”Þêîï¾uëßßelI.olïÁÕöDšÍÜÅy—9a‚³HàIw2¹Ñ±\|ÓYŒ@¼?Åf…p8`lVX¼çýöüü°¯«³»»¿¿«ïö™ôú}ð;x¯ýÞƒ'ƒáž$':ZP&k“U ƒ€ÁY  ».°À ž¢€–àØ!<ŽW~;’ «çAw÷ýA|`àÑ£žÖëMMÈÿ=ñ±½‚c;_s!òWõ…`KÖQýþý‚XdôÙ…$èŒK>x0Y› )>v‡~€ÃŠ»ú†X È’lB0‡Ë"30׊€Àyh­ÝÝ ²äd­0ÀL+]€#Š‹›ô8‡žÍr³$Ú ƒˆ›œ€!ðÐõ…X Cr÷­X%@òp= |ß{ñ‹†iz¶_\ÏfùÑH<P"`“VÚ%Hšã”„=€6Á0%vE±½¨Qß&:Ï„T€IC¥€¾XD·Àò µ'†€Dà1`ÖÑ»¯¨QïfžÃ‰¬82ýT9ÈÀßñÏ0 v?=¸í Ò4$@I0ŽÚ=Pô¾#–é°G€P€A*@pxDzèDÀû•—=@Ò^ü'~²Š`DªBX^#Ö €'¤€²(t¼-ÖWÈqS½3Uê4Ð €mQôëmD#È"ú€R@•ƒ$ÀðxÃ*Œœˆs m†çTáµµzÛ”AèÙ\Ou‹ `xò·HDþ{šˆ©.~FOèø^qqý³ü¡- |”E0€÷k0Áµ¶HÛ‘øOÑÉ:ézÆa7û„2ý[Á³lÏfÅ€ÌQü-Ra$îiíûî/ç¡=LŠ€1¦P|Tqg„-uTDÂX¤àŒpþ Ú&+šúæ{Ðóôûx4Ô àzŠ`$_(šQ~ê`€÷k0 ¶Ô¼;5áÓxÔý8)éà°RԀ톱°¡xæ¦Ì\;”…žê2äi—áLª…A ´MôNH*B«¾'•qÉcvŠ@¶g€¡™Y~6T# Pè4"ÿ©‚:Hº/¦&Üû­»ûw%éS`X€‘àôIÙ‡#Ùž=K³ bÄVìýZ^;Ž·6&x&Z‡fçC÷ûu$H×mÅÆØ}ÅvÑ‘ÎC‚^ý:÷ ÍÎ ÇJôø;FŠãx}Ã;`W šš=éß•¬ÝÓu#c×G½ËëFÊAƒ ß„ÜL7X—- ç“¶fÍVs[XiºSæïïï=ñŠ€D8ÑÝ;íË£þ냡§s'-ý(a_Îsw·µ&ÍÖÖÚþB98¯A:âÁcSîY CÛÌÊåÜxd®°Òtð@KNø5oÞ¼—߬è‡"”$¼êèè8ub*”"þð3CG•Ϲϙƒ%ö²ÑnúKÖЯm€š›ëƒG¬Ê•›æ[ùh±‰Öœé;` zàÓr} ¾mסãYÓѼäÅ´q{Ä\=T¢`M߆֪„Qb†Út(N瘃P®¹¹É6 `ü^ ¹ØB{IIë²ëp¼»­MQN@Oßg¶Zþg:®ßF-ÒâÑþ‡Ã¥ûw(>ßù`2höáÜ\Ì$§A0~MˆrO¬K‘ö«Ò]»’ÓíA‘î¾EîZþ`§r¡ŒüGpØNïÔÉF9enÊý'†éÛR@Ü:I:°êúyÝA Àbóc|¨ý-üuˆí¤Ø¸¨º:{ÂÅͥţ@Oà©–e·¡yX烯×%S!€É9~ÿöwÚþQÈÇâÑ;‚çGkFmhÃ(‹=rKÒ ¬Ô@œ2 ÂDOÐ<ðÁ­¨¸$Àb-ŽwÖm°ÐöˆÕ ¯€¡°êÎhgÓá³èÄð¨hÆÄÆ ]âûÐyÑŠô`20l„¶X•`¡í¦cì6µ4®N>¬è]T7*€Á¬Õ%%ÖZ1°"¨D…å´£á÷Áw\Ôìvî"@VIöDo-ÿ3M×oSù8 'ü#Qcþ¨‹ýKJ>Ñ*D+sEùÔÁü`¹$ß5X  âƒu5Á¯hùŸiKÈE@,°ëPì+–½=êÑ<×çë’\íX DÅÛ£)Ò'ÄØ×J®È æOEGX=2áD ÷3­(Â? Ë(šÑ#`Àgo*ùç°<X–R,%¶Ÿ{–PÛ2H´Wó£Öšw§kø‡Jä@ŒÒ?"psé(Õ‹KJ"µ% B»l]±ô)d`oç½[Ê)À*2s@–b¡ñþ ^6èÃ~@•¦„¼Ø°bé#ôúM}?¯‹Š§B0ÍTÜ_Ìeêò&z¨ß–Å+€ à¸ìVÈ1ƒ M%%/J LùÄY¶MŠ6›[[úŠÁ|R< €Ü¹[ƒ JÝ·îÔ¼‰˜˜G@±Í 5È¢]•ß\Z'ýÅ*Aþ%çÒ´$ Â²ÑEk}ÛWaQñĨ¤˜i±bpûüŸÜ5ü;˜GÅ+K€ÃaN¶S(öýrP ç–`š!ñ*–@ê¥ÙaQDO&(Gz Ž·—Ï™®”Ÿˆ‰"ý‡ø1ÌÎŒ¡ˆ„¯T¦!¦©@H˜D:ˆ?•Ö‡-£FD°‹LüéhÛ¶Kì¨9 6çÅS%Àò p¶T(.nhŒášRøÌ‚Ü $0壹±WŠô:Ž÷Ö] ‹UÄo‹s$ÜÀQ¤£æ)ªù'¤!èÄpB‚BþQ•ìí1ðƒ>Ci¨pPPv·å‡Qc|œ&Ú¯ëEšZ[››ÃR°ÑÉiÃäªünð¨S ü/Ÿ;¡!)ŸÃêëaÔÚ¶m€ÎNvR{Šw×m654q²11omKlãqØ,´ã0!R°¸qϘ¸‘GÎ]öP BfÕßî†åp½$Ludqˆ3%óÄ0µèjØ{¾VÖPqŒnhn‹ú—ÍaAƒö½\¾HzglÕøáj 0 ‚±­ 5ëP±j‚˜ø8rÑÁƒŽ°ðǨQ¶‰6š‚±÷©Ÿ>ÙpiŒ7å6. \)‚q(.9mPƒ¤î²X ‹‰5¥ÎN¦qˆ÷ \m„a~( ³+ @Ý ÆhÑ—K¾&9(»=]XZì¥>·Š_OX›VàÁÀýGÄ©už ›äÅpf ƒûIŸäùÖcbÄç%—ƒÑô $tÞFgdÒ|/^”Büz*¶†‚øPwkSK}}'q€*-ÌÈÉNLŒqvös6k&2`Ì *+KH ÆaÆ.ûÛ »¥9^<eK8®‚tÖ75Š+ªê‰ÃêÇ-õuR©D=Áä°\%ÿ FyŸUV&Œ3æsx VIëaê !àq£¢bø1ñ11Q\.?J `nS1ˆ?%b؆b‘„Úº"ð«„©rùÍà±–€R‚ù¥•—_ –‰ÆÆ,f@€¯F‚§ÒbçX0‡‘ÄÒy¡òhp¼ab Ž—-@Ç{ÊÊÊÐEêLûá9¹ü#‘lÏ3$F¿_YyÎŒÊ|a*öãO«NªnkPŽ#©sÊ­áÑR—.æóçJÀšîhøÅ«ò‹{Æ0kÛ§K¾ ÐÜètF¸1Z1§ ãƒ`¥aý³ù¼6›ÒlÐ…åâ],ikojúùÖ þSióÝwkdÓžõÎr"¡’nF§»-6ÿôÔ²Aü‰x4©ÙQðΆV Si ƒ‹áÂÍiyøðaW^Ú,ÿ¸¸ñÒ3_šNåCJ,'ÑéA`cN p?Ôp°glEnêC«jÇEÑ ê?YŒ ³^Ûò]ßÃR"²ç¸6¾5âóÊêÃ&Nô¹ÆÈ?Œ×‹§™ZS¾­Æ‘·¬(€È‘þ2.¹»"ø¡ÿâjóÍ@iÛ4ƒç°­¡gª«·Ðœà¥<ä¿KRþ:º#fÐÓ%U|»yÚp€F† ª@àÅD'þhà…]PÈ/®m¸óöó:‘ºäHuõ9 3:Õ®¾/Ó)üp‹ iòX’³ŠÁB÷Öœa,¿6O*{ã×|º±cÅ7ÕÕÕ6·üžº½ãÝõU¢Š¢´ °D}")d1ˆ»sΓÀÿÍКçL@¥=°4¨´Æ‚N¯­8þ¼˜”b°«^T‘=M ‚‘XÕ…ÃÌ4ÕüÏ< ô¿(i”üÊOWŽî]‚4°FWK‰û¥{Å÷Q‘(Ìû£q)ÿ–WNLɤB¦'ÌÁÌ`xóÑs€ÚN –|~å º“Në”°ª…ˆGKÕùý/¼ëN*ý§Ò ëRêdÆ$Ï«èýE —~ƒOwNB?¦©KoÂÆŒ²zJ„ì Q÷`Ω"X;IŠY´0º6Oò\X×¾=¾~º¯qÏ7hc†íH/å0,ªò^…ð×E©°—_\QÕ ù>]úÇ©ýï£/l5ï „h·b@*Éf0‰ÆãÇò›ŒÎ1ðëçàýO¯•6ÔÿfŸNå/€ &ÑÐ`¦.Jtö£.®z2Ënã?]¸Ù|÷ã=ÒFÉoùéVNƛ߀¥Æ2ÐÕ#-czW~à×dFNÁ÷ÍþùÒ_YÿzÖnjn¾ñã æ)¤xSUŠ3yo—élfVz³Y~qžH*Ýð[º–—³ßû‡æ7*5¾©Ø(DH²‰×wž@;#—Ëï~¼¡¦¡ñíßþÓ¹"á©àÏàÆn-Í“ê !ŒÉ´È«Šfù5Ô ñ_ó`Îæ÷¯Bu°Š U+Á2¦3cÍÆ^X€,­’Êò¯/‹òrfoo¾ÑÜQíA¸äôÃrÄņf_Ú!‡è¿¯/›fð»Y‘0/{ÑHÆŽÒ9¤0Nhgû›¯7´ü}?œ,*+Üð>JÆŽRÑŽ?Í?Ò’o_°°¢ñÒ¿÷ךååå¥˯6+?®Æ¼„~ºpµ¹YÞ{zŽP,–ü#¾-//o¿)WÈWO|Qú=Àôž~÷¤XÜøÅõÙ* ä,]~­W.o¾ çî狲ÅâÚâ?òËaqyaá‹N÷*½×>~+_$®¿ý¹\.•í_´}ûò„à¾xšÁo€ Ê?Y^.ª=‰üw¬¸V ±?ù‚ÁÑÄo`ÿ§í?â?JE§EH¼IEND®B`‚fheroes2-1.1.6+dfsg/files/images/platform/psv/sce_sys/livearea/000077500000000000000000000000001476115357100244305ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/images/platform/psv/sce_sys/livearea/contents/000077500000000000000000000000001476115357100262655ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/images/platform/psv/sce_sys/livearea/contents/bg.png000066400000000000000000004166071476115357100274010ustar00rootroot00000000000000‰PNG  IHDRHô0®ýÎPLTE¼ˆ |>œb L* ì¤NÄbL>|N ܨüÞ$&´w ܆ôê5”N´bÄv d2¼Pd> üî ¤VL6 ,Ü–”F<&dG”ZÔy ̘´Y|J ¤n ´o ŒVôâ$̈¬fÄp <2ŒR ôò:Ä€ tA ŒH”V¤^\: Ü ì·ôî,\2´j Ü<.|GÌ‘$œj L2 d?üò5t:tG Äj|Nüè4&œO¬X<"”Zôç+üÔ쨼dd: ¼\L8´n¤b´R´~Ìx ,"Ô€ Ôr ìöRÌ ì¡¤R\FüöìšD*´^Ô‡Ìpüö ÄŽä‰ ä™œ\$¬j ŒO\8ä „GtG4.üêÄ]ŒBT.üÌ\?lB „I ¼q ”V¤^ü¾ì¯üÄ|Bä®Ôžì¾L2d:tAüî4œJlF ¬n D2üî!üÚ¼V¼jD.¤j Ìj4"¬RĈ„P ,&¼v l6T6 4üâä‘Ôl?„Pœ[T8¼p¼ Ü€ ôòL„>œbL.ôìNÄdT?ä§üàÜŠôîD”O´bÄvüï¤W”J<*Ô—´ZŒW¬cÄnôòDŒJô¸$üé4)œP¬X¼d¼]¤cÌxÌÔ†$!üê,\>ô±¬nD2üî,œV ¬^ T2 l: œV¬^„BT2l:<.Äj,"¤Rüö´^ô¾lF¼jD.¤jÌj¬Rœf L. ÄfüâÜŠôî6”R´fÄz d6dB üò ¤Z,Üš”J<*”^ ~гŠpHYsÃÃÇo¨d IDATxÚ´½=h\iÖ.ú‚O"Pr| 2c0® t)ªAAÁDˆ­ b';ÐCwp‘šžP7Jt¸ nphEÓÁä†ÏI¡¤ƒâ€iëhJ(sðâäF\æ¼ë­·ÊÝ=Ó}÷Þª*•~,u×£µÖ³žõ¬Ô´àÙt÷ãÑã‡óOÃi¿ßÿGocãxãø86à*g9ööÊ·îOû×Óá§ó‡Ç£‹q×5¿üsýÒÓx”»ü+W3èÊ/wQ~»‡W¯Î_Ÿ:ÿ×§OC¼è]<áÒ㕜x<À…'\p<†“n?•_Žñøþ¾ëƒ0úðÈ˧^îá範Ÿ˜ð½¤_Iß¿iëÿVá?Òçýá¿ Ý…Ÿ;åðcøw“ÿ©«Oð¿J O¦•¿4Ÿÿ?_©ýãŽÜàµöøÕù§ë£=€Ñÿ<>~qüâÅ‹Ý_=ýqÌ×1_rw\¾@©`éËþ—ןÎ_•WÞ}7Xù [ùjû÷ÿ;7øË]<~\pô_AÃáõ0‚*="²^+¤øxLÈzL€)”îïïHð_•Rçêëô®ú\ø‡š&ÿA]ù›]Òõ`„( míînínýÒ± W9ñ gˆ¦½½”¨t}ýéÕÃã‹ñ}×è±2NæÏÿMmZø`n~õ"•€ô ATà2¼¾.—Ãÿë€uýÉJáôé¿|ø¿2LQ€’7ˆP”.FK’ ò‡<á 8É_‚„ϧ_À“¿}£ø~&œ 9ˆ!º-gùÅþ/…¸’ÈSÅ£ÔØÚ·N-ÿ|x'¸M« “4_YŸYúÌœ?ƒ¾l…Íý(ü%É™d?ý—ÔÏñ ŸìWþÏ‹@úƒøï ™]y¥ ¯û£]з[¿åøö³Ÿ(8C0ýOKÿè_Ï_=@n×ð_Ôö38 4­¾ZüÙ?wáã·@„¦×S:®éD<Ñ› Vˆ(¼Õôï•Ëý8FaÂÞèñEùîÇÛÁ/ä2£€”ð¾ ô޳!}qøü¨Õ|ÉB €ÑSð FÁó«’½òeM6 ºLü´VÃÂa"çj4Õ«â’Ê ú ‚ý É~¦,ïeKr0Ïîsä'w’ï‹Ïð_Ž“š?òèº^ ‡ýþ¦t £oßàùùC?V>uë ?ÂsO—ö6úÓ’Ü!¿þ ¦Õa¨E,á't%Ú A02ˆúp^÷§ñL žð#”VTŸO’á!”$$5K…PÌ­Bªâ‘%]ú¤ýIVˆñWâß!@’œ(¼)¿ÿÀÄ(’$O $†iŒ+üzNz—V¼öóR&—?côËsvyág0$™kfTðŸd¢DWÀ,ß,+ú$EÌôÐý.YQD+RƒÁû÷^3xQ.Ýxòø&ucDåxçÊ ?ˆwx|«w€1ÆÒ®%I¥°@¶á_ ’þf´a@c@j,ÖãK¢>ú„(B‘©ëéÃT§áÙÐÓP=–((Hå÷¢r³ª4jÝ[–Ä£õÀ’?¦ú…©ª« „ÄÃ7 )z,ñÞSüÏ&bûƒoY¶¿êö)É…0δRø`øpÈ^ã3îå¿”$ÄbTÖ†oâ?dQÛÂ|’_Ç%ý×ÒvÓ,~çíö  ¨Yt%³{Ên²º>àõhù-ǽg\1ÂÀLJ“úHÜÆã_Òàw§¬ôÖ!Ž€‘¼Xú £ú¨Ôõ浦}Œ¨OÃOrÆÑ Ñ„• Bòvðj•"¯¼Þó/ƒÊÑcm]%eùÛ•¸ài0‘«O®–0ÙóE'aÊÿƒò’âtŠS)ŽRˆ'.K“¿ÿyuí“—«§H›ä¤Z–"9X‰Z–&ÖSÓ$+µH¨yª…$Íá3ºnñÇ\pÎ'£‡ó“Í~¿du޾t<}ù¼œOWœð¡çÏ_þ !œ¾E$”6úýáðáa4šwÛüÔ?Т Â%@}Û‡Ð#k-õ_ùí€IA]/èK|»vx*!ª/eÔta‰ðô‰#TÁÒÓ+&„nh(ç,HÊ™rPJ "ž|¦‚Åç+˜ç Êç"ÒFK9¡L‚;ÎðÆÐ D$ûæÉÁ–þ6 í¸ :u‰”bœp/ÕIÛç»3 eY^òYã¤ÿk’äþ „áПÉ~Ú2v–Ì.½þþýkÖÍG£·çÃéë ¤é ¢Àñò_8à“ŸÂµ[&AÒ Iç;˜Û-ŸƒíòBXÐcÓ ƒçb×ÒŸò‘m±’¬Î" ްEf0úGŽòàRü ׌&%ƒ›×¢Mœë0I¥Í¥’ÜKHtÁÝÛÉïi^× ÷HwD0fš­´ÔBˆ@ì!ˆ,»kÚV ¥ÐXR¨&«ó“½p9Ïr \á¥Üæ*_Ë+òº´*¯ó´Fˆ@’mÆB)øÐXçÔäi ·Yy†lédJŒ0"®vÎO¦ýã]¢FO^>)Ça¹^†Ûr”ÁÇáSðáÒ¨z AIƒÒ‹’ ίH† DŠD£Ž’ÏÙ6Å&xwV^ôæ‘2@u€Ž#× >¾rÐ!³_"Òp:mllmìÁÍÆÞt·à\Êó®MS-Ÿ(3F*Y=ƒÒcáí˜2d,a’×0‚<¯ˆ¨i…5ÈJ©ùP¨?!À It8"Á› h ]%é3ù¨¤ÿ˜œÉ•ÆÓeK†~™CHZÄ;ò/Ä.×®õ4EÖüMèHúV)»`غdñOŸÆÔ1ØÂÏÊ7üg»ßuÌÝm¹OvN6/ûwÇ€#ŒG‘Ã'‡¿|<¡“±%øZÂ&%H_ì6?•ˆt‹?@Î Ó•r p#è&LÁÍÿ¶ñ„pÏÎ(pÈÑ}‡•ãl{Ñ@¬¢w ™Ý«ó᪣À{€©#x²|ä#ŠOS¾q¼^‰N›NŸÎ‡Ÿ^}Â2éÕÑ ¤ºæß‡ÿÉ¢£Žhpmÿ÷[ÑT0Rl ×ÀD<ÔÀ„¶—äßwLŸ|7-‘„`›äþ¢'ß^®qèe­|Å ~<-•W)vi}È8sv'Ä[’.@Õ™²ÔT-gÇ¢dä¤LÊiþ{Ž!½/ÊÝÕÃùÙ´tü‚q/ÿÃý(ˆB`¹ƒ@EaéÛ7k“6ŽJ‘tþ0š(b¶ËÍ q3ãî 8„ácAÈÑ’ nךíòi%=\Ì0³›vÎKf‡ÅÐ?FÇwP §º~šòi­§R3mN7-, þððŠS;*’€×Ž—ú¬ Xò‰œÜ)§ÍP£'9 ¹‡Ä6Pæ¦1ˆn´ŸÔZj']YÁSÓúþ$IÚä_R—ç) ’Mg´X^™üù/]Îñ¬ÎñB‡ìáëz]Ùý“ɧ£ ެ©iÒÎ!å¾éÓçÝâß¿æö±4¾z¸9¹œBf÷FÒ:G¯¾z¿ S?A8`•`EaIbRI7W“qù àGØ^Íx( j˜žÀ¤p·=ë8 Íší¡«¡0UÐ „$0’¬"ÄxTŽ;R² ãR¹éoô1Ñ“LoJ 9'y}¥&àÈ MçCV<`Hºï€nhFÔº‘ÞÁˆ"“L §[Žž&š"ÊÞ|Ч©¡‰`40¹Ú9Û¿<Ú8Ýõñ¨YuôÜ}ï à©‡øê}6\Az…ÒDRÒÑtx¶sU€Tb#œ#çŒ9ÁcN[Ð{‘ò¡f!ÜÝœ3:!ó,É+Q`4ã5óîv%Ò F$ŠG"lß8f,mHšw´‡a 9ˆ K˜|TbDm’> ‡”ÝÛdC'D¡FÒ7¬˜¨lÒ X¤Û¬P& q487 H¤ ¶á²ÜN›³T" '¯Z\ÃÆýÉf|ä+w.õYsª»º*³Ö“^·ÐfÇ*¶Œ(TäëÏVåo¾%Uå€ù?H£‡ûÓ¤­­çX!=±pô9,õô®Gp‚O?ÄwP=ÏJpHzÃ@:9Ûy˜Ü"`æU,š ”0ZBò ed¤üaúh3—ˆ´”2¬00Ë/÷p†\ƒÆ#¾ ˆ0&áå£ÒÞLULªÊ%Èì¦Ã)QwÚ–Õ"©urÀ–j J÷4ßSMf{Š™Fk%cúˆÌËü7ªƒ8 ¤—8¹PÃlC#‚;£ÔÆ×xJ•&M6ö÷[S7KÊŒákõó?#O®äOJbç´T é ?¹Ö© /ç\‹g©‰ÌÀ¡NQ›«Þ¬»ÏÖ×-i2_ÿ1×|L©|º0zþaèÙÁ³gâÕ+Ï•·:<Ñ#À©GåÖE¨—”ÜAHZÛ:¾ë_nÿÍ„G'wŒÁån žr3ƒ5[ ”èVR¼Î2@!¨†*i5D$€†H643¼’Ý•Od4íÕP"¥žäx¤"BL/m×ݶ<ª³Ô*¯  q`Ûp2Ç­Û&‡Î­©‚²%H%töKü)Á›¨Xí’‚É* ÷?“ ò׌MÚ@ |A®É¹ìT:FegGª{–ÁõMùó=»‡(Pms²‚(KDmƒÜ•þÇF¤‡›“ý×Gw»[X!A<úÿ˜ »Å»Þ³ú¨×«¢T²=¨¡õ˜žüÄÉÝÚ›ÝÓãþåôüãòߊ? 9Kͼ„QƒX¢\Ooøñð¼_3÷\Þ¢á„ÅÃc‘Z¯¼ö!HË L™bˆÛ±Uüi,Ékµ£Û°`µ£ÔHGIŠ$Rà‘¾ÁôJM®&(œ°Ú‹q’g•S×(=ž¼ø-WX IŸèó½Ì—>-»?|Ìet"Eƪu”‹iöCçUòö¢æ4‡HòÇ\®‘6H%±û‰BîŸýp €:€‹SOÎG“PÌF@DBâ"RIíö!µ›ÌçšÂiDâG ½™YÄj„µo8éë\ˆªÞ”·Æú¼%û}s>ÜœÆxtZÎ%”€q€[æðªäÎE$ÈïJHâÜY» *’–4m¶§2‡*®z,ÕkDö£ø‘怮râ0&ôˆ©@R1àn’4’›ájM¡ytÕèHúÔÚ´_õÔYË· |)*EWfx9N©Ô@™¹¬Ù— †xb’ª~ºÌµ^Tð9uƒ'1äÝùúí:¤wÀí|}ôv"Òñîî›çO¹B*Èx¶F@ôÁD'G+H]¢Wàôè@Y½'Ì€¿Ù*/ÜËéÙùÕÕ¸O§Í-Ëõ:Ë÷’òh¼ °(գ °ƒÏAdkèÇWW@6”ˆ´·B’‡ÒcéŽc €¥þäx1*MñÂBi(tI…(µÖÈa JÌ€·J:H…%RCÄÔ®„˜_;X¡,8õ”G,ó€|è@½ºuzW€Tj¤«É¯‰/掂@ÚnaiguXRAª'tdts†S·¸O^ÁÐâ?B5쟾À°DÈ*0B&üNù&<}§Š!Óæ”؆³r¾:?G8ÖHÛ—-*ëÝøy$vohU¸š[êËÞ6D†TÝØû+¯Q#än9é$o î +Ç%rª›¤®b’éˆÖqäNrêyóЖm}õ#ü»ñ­Ú¬“Sš%& HsÌÐ ÿÎu[¾D¤?qDzÎíØ‘ÞqâF‡ÊPÕ{æ1DôÝÁ;ß²å®@韇/¿{ é[ Ž.7Ov®"žBTÖAd-ZyJÐ4c™ ·›T3’œ€†€ÔnŒéšY»;¢é €v5ÕpÇI’; í0 mTB¡©›ú+™Ý¦r ÒGâas«(kD*äd«$ÿ-C“9ùSà¶”ûæÖ0Õ-b»ÖÎQ´Ú¨e—du&çóBP«Í]ñÔ«&Àà9 ¤È1§ï1•žg³§ÉsÒBOÃÅÁÝÖ™“åä”JÖåõâX1Òß- |?ˆæ ~’Ö¯®ˆlø#Ò¨‘z+˜†g‘Çc²NXðг+ñÕ˜´“ˆ´» 5ÒÉÎÍdü ‰ö_]ÁD"[n.͸Jj´íäºG°v¢Xj·9%Ðñ'vÇŽmØ8¾‹éˆÅàýXÎ$©JD"Ѫ“kZgCª2û‰ÖÔ«2áרë^r:&Ÿ ¶&¶ó‚Uí5’Öå6¸UVþ Æ¡¹†lÊ¢;È®MÒÐEÍö‡ß¿ä}â—3­ÃHT&ÚfÊÀ›¡8ܵ–²3ÁÙH$G9;5¸F5bíÖ…w“Çÿê-Fµòàm‰H%µ;]{Îô·g¿ùø{ÌìÞqf÷ŽÙ=¸ûPΔz”ÜõXåpˆdS×°VR»þkŒH·†ºeâ®›Çò¨ ´¸È$Á[XOI5E+÷‘4"ir÷"VHwÇ~´‚Ó:b¾j媫‘†¬¶£~¬HŽ­k[ßMb¢.+aÇ:»Vc•¯‘??áÒº,ž !9¥u`Á™¶ñÉ(»Ê+ùÚdiüÛëß²/›â «:R$GIè·öü¶ú¾äðÉ60žë¯ö“®–¡­°çÒ6söz?·bYԺšŸs ˜4¿\íÙ@}¤’Úõ˜lø»‘¯—ž½; ¸ÔÂáY¯’µe§¤ïˆløöÍî‹»£éþ;o'·–Ûuã¹’êB‡ƒlu›"Óœé»Ùœ{J(ÿ H3fn©Fñ÷†‘ ËÜ7 ˆùoÔ®íù½±ÜUÂG)p’âœÕß@ÚÙЪHH§(‚&á‰IBIZ›;(VIT23âö–iVóø„zq5Zp¥àª’RÀŽˆß8f8åuŽ5ÍKX„±fPöCj©ø³A¡gîAF&97¹*šªé©ìÄÑÁÎ "y¡9kí,¢ü»Œ|‡ÉÍÎû¤ÓÝ-ˆHØ= ôn9 ¹†’vcßqÛ õ=·èü™]Ï+Þlmnl\^žíì ÙЭh%u.$‰Ô΀âOÃü·$t­¸‹Ô`”jHk·s~B©ÝÞÆ]Ú2ÓpwÌCJÖD!’öœ<ŠV!ALŠ9×kíÆƒ@Ö©d”G*ZÏÙ5¬ b¨qr'­WÎÉó±sêÕ¶U‰Pë¼OXª:`ß“ÂÈ™q9³Wob“?>k=»–µcÍ%«Ë ÄqCE9:yù¾RöýRû‡³·2qÒ$ŠÜŸÓ—'ï¬Ü¾*oõ‚.п—Îշ庲áh£¤v‘žy²ÁåuX½{Æ<¹ÅÄÕ!kïðÇ^ïQAÓ÷œÚaC¶D¤Ý¤á ª¿ë’u|Ø9âÛËX©‘Ä€™-;Ø6äìF¼pTŒf¯wÍ•óƒ9Yá“mp5Ûë¼n·Ž{ÓÔsÙD29-Rò}¤Ö©ö\Šj¤õ[W*IŒù.å¿‘lظC‰F¤Þ;mÈþ}9·ë1÷ÝÓ^,evït²¢‡0D$®‘v7ަ%µ{¸W£uO3k×±”i;)¢Ó I}$©Á‘Õ_PDºìcé³A™·ÜÌ9©ÍX“¬Nƒ¨Aé†áÔ„v(þÆ Y‘µ^äâdpMeˆÒˆWÇ|šè)ñˆa4ðÆ f ä|Vu€"ºNZCV*3¦#>!ÙTi=°%á¾h‰öN “Œ¢}žAØó ÎÅ|ó"ǰJp®}\+§ŒT÷h¨‘(Ö+<ý&ÊŽð¤}$’=AÖÎÑßÄ7B¨GéPv%³ëa$Ò¡’våÄÉ>W#M††¬¯Ö— ”£Í8Õ[AÃ~”ϱÆ%áØ?Z`LBê&·W8tÉó±õ<Ò¢èXH¤ˆtô¹Òõ5*V7Q!DêlXŠHF{‹ô[¬¶.€'“T½ÐØ8«„¤^R[<³rY¬v¸UMT3ø <ó6hÓÒ|Oè:ÓØØ|j¤ôjY›Žj˜HK~ÇaxÃR¯)^ÂâÕ(»°ª,Ð’Koy—_ž¤v·¤ß¶$&aŒ摤# ü© ÈêûŽPöx¬ÏM›³ªÁ9°‚ËY¯žŸ F~BVçúD ž5ÍsÝ"G#aÙš`°¯üCÜkAáF d¶\¼ãEÊ$ls‹¯á«M ŽK)~ÀûZYåç–$“byž'1Rp\Α@pšXãV»o] ºÉsß+6NÃ" ×¶+ýÍ ^è$Í}¾÷ëÝXøúÉÕÑß[ÚGú‹Œî-Ť†”®ãI¿n$™\);€âHúH˜Úaéòç3Q6(jÖ]@ #ÁÒÂCgN3H$jºÇû¸‰4Çw»Û1ŒQœì‘Ú.¤ ªú."â{›±Gæ&tä"’Pv0C1œYjG@"«UÝE÷>‰uƒN÷I;Éh=m")‡T£ IDAT·Å¥uì·6i9ðøŽ,ÉÌ­X]¸²Qê^ªšC9‘cen~!žÆóO®GiSÌØ²#í"‘£ñêÖümqi›öQ³§å[Ǿå8#P”m6>|wyBcŠDHkhâò½_áë$z]]ý}w÷5F¤ï¨´Šl˜DÒ%vï¸<¢xôŽ+¤ïP`FöŸOaB–²Çw µ;3­w݆)$òÞ›ÏÕÖA‰‡™Ð ‘XÔÀó}ԑ訹‰íJw§®‡ä©of`DV3»i­W%§HÈìÈ·ø;és?và²qìÜfÌE®žÆ­Ñ­ j„Æ;ï˾ª>"¾ÁÑ ­q€a¢OÍ´£Uœðå%ŪävÉL}|åŸSªªßá5_'ÖÓæ¨Ž½óèDÓáZGgû˜ÃL¹ù)[¼Ñ#áx°SNε’ˆ¾QÑCaµCC–µvoYk·ô7H„J‰µvNÔðìà™ Vyý@gd9ý(EÒ‘žM$D$5¿NlgæûˆÉ C#©á*‰0½MÐÞø–mvBìEEÙÙžæ  M©¬ßFC¶fñ‚£‚¤Ö!5Îuˆ\5#¶l,{ûeïdäD{"³£©$MìÍ翉»SÖîfgŸY;&z„£w«§ù̲qÔ{&Æ'lÚÀÚ ˜é{¤ÊG •ˆ´y²ƒÉ íg×q›ìcj[ç„a`IÐÂÑ $·C¡³O”ÚQ@ÚaO uAÖ!cgTÑ›æëOm~B¦c9"³A䘛9'ÙøðÆb’N˜7Ù(»&©;xSí ¿:S Ä;h dsX»´Âöy¡uözk-•ž/ RÕ>ªÆÖs®*,OÞyÞÍfÞqGøCR^ž=Z NÖÐj=Õ-+±}ÍæWüÍ×ç6P¤Ê9…×oÎí`Hõvru#Z;qµû±ävšÚýÝꣀ«ç’HµÊ­X¾ÿ+3ß@}ž¾óâ—OÿSÌOîl‰.ª‚YCÝmYgæ"S³Du¶ ?¢™gñˆl ƒÈMðÅg$A.§á(zÚ¡{1ÛpÅÉXwlÒŒù¦3ÿFòÛõ‘<ÕàÅ òêÏ:u.»^lÿ¸³2nu׸¥ý¥Fû°K#HÞËnÕÍì<â¼Z DɃîg²-{RôáZaÓmÿZö»%‚NVÒCÀQù¯9h½‡~°6 ?oLFu~0 ¹§¥Y&GÝjÌîþ• Ù ö½>:=ňô„Õß«2»wÏÄ´ò:‚Q HÏ\…wßó† hùOQ¬aC<&Á³Á¸†YçB’øv™ð{¦$[j!âi¤rÞŽ®®vh‘ Ì5lÈÛÆ£;ñ³ÛC•Ý^%Vu5Ú~ÃÂY¶:#¡Wl@ä,ZñhÈ.ìØò±ÆÉŒs0‚N¸ŒÊ†¶i¼XUB’_k¬D%ûvE [ò˜ \Ö$/9Ý[Ýkrí™0Ád3¨Q;ZiÈ=…à%ôšûû1þ]jÚ¨ ´1÷ÚœÁ¥ÞÎ(¬m0Ir¶.âï ¥/[Øäí;D$’•ˆò¬·4jþ¨ö¶#ºŽ3»SÙýHÔ·P \"=Á•‘ö.O¬! "ž!8‹»N„ß8aή' ‘XôÍ%ÒÂ-„ˆô€¢UŠH{‚$ Ù,ßñ^”}ï­dúÜ‹QÃæ&IgCTÚËZ—q§ÉdÞ"Yµ8%îÞ„ûd§NÍùÛ‰VµUÁ#iÐ ÙÍšÕV2;•îµMeÑvñ¥ì£f #rJÁ¶.dkÞ_Ë‹[}Ù¢~&©ÚÁâm„¬ÔÞ°ÿ` ®LÏÿć2§Ðò ùшϷ²§Êɳ!4‚8™ó´öo”¡—Úi@º&‰Nô H´G–6=–q¤mO~·<Ý×ÈWJ²i¬qÆ­óSõbï&7¦ÒUÍ<‚!ë/a¬Ï9žX‰ÔDÃüvIg|ÓEW&Ùøl2p·s(ì>vd‚ÑP™\޲Õv…zˆž¨j°üw4š$Á߇°Í²v}È©òkðæa*WM~µ£OèoçÛ ÍÙm‚“ §_[Dú›ºFT#½SS»¢ûî9gÈgÄ5ðÒŒåˆdÓïXjƒ}ýþþù¦všÕyW;ï¾ÊÏo³VU=!¹q¤ñ¨¡4Œ4W/}`íÞ tɘ(Wù1 ôan'³H¦Ñ`õ+¤Í)ãè÷‘^ñ¤9“ G3ˆãI›²†‚}½EìíƒÚ¸V¬1ICãt«ôb¨êPŸÚ·!ƒÌ&ÛË© RïäÙ€P‡‡je—ÌmÕ$o>´¨,Ô‘)! »'ܤ°'œ/ÇcƤý 1$è· „:/W~'a•’±æBü™Xóè_0l¥+’ û6!ûgöl8X•Ø}PkHÎêC=­J\:döÔªØFßG¤S$v&âxRª¤õ‘L„XÙ­ªx¬v¢Ue0á´ìLLQf´YiŽ&ú‘^ m‡éNQz±ÐG"µêžäuQÓpMñaÒµìtPU#¹Él|ëU8;ŽQΕ79Jãt¢­x-رõ÷€ÈuÎsLri5…ñ¾\I=Wõ6E¸Ö:cymÆ]Gµc þYѯZYQ~-d¾¡Bš ’àOm¹5Nº9Vvó™5kªìò¼k ¯®`L*ý}+þvŽ<ø—”v¤þ¾9;®çR#QÃ52 ,½&_È)m5O;ñЗeÌ€œ‘~cd[®ÚTl£ŠïFzFmbnâ(ç@¢ZÅIslKI©Âš¦p¬s¬Ëí²ܹ¸‰ Èì0ÞíKù°k,™éHXßçÕÑk€á™FA©´9”aŽrÈUÈi]pÍn””â÷¥F«ëžôFœé¸ßh}‚‰!iíN!"E!‰ý Å$ûf©ê³¥íc\!qD:D­Ý? ¤FZƒEc—ûç6ÔUBŸKÂ>¬¬>š³_¤yÅס2ˆw¼ Æ.µsIÂÜ™»ªÌ!ÕØjÅ&oêÓ]̲҅ ‹ñ¹°e5’¾µ­:5¨œ ô³[‘¤-g¶f¬4é‰ÄPÈVú±ìŸÈjl—Úàž¿¼³ÜovpÓ±ñþÊËœ]°Í…SrýU“ï$OxwÕ3Œá¿#ÞB ¿@µP´øÏ^›ÛÊÒ8ôcmh$;Oåœ,M wë‘Møeë“õÚbDzBZ;1,ùç°i¾žú«¾³ÉX®¤ÛÖîeŒH¥Fº!Ö®ÓÁ¾°oŒÀÄ­X–­úù lùx„o æ"d†¢é8µû–1ëfŠGÞ5Ÿ·‹!a'F\ý£~ÐÙ1Õ š‡²®ÏX;uãÖÎ óÍ¥åÐý#™JÊÁ•Û¯èËq“Këõll N UI÷nše»Öél\5…\.úЫj!µÑP$ ûùQ›Ú Tu&AžÄ°æ-íµ:º@(AŽ\Ž1÷“Ƥ`ÍAYä܉ÃR§ì=SµÍkjUý=w:!Ò±®»˜ô Ù>@Íê­’ T#‘úû Ú¬˜\¢Òó²³ÕHاD]¿­Ô¬+†(uWW7ïk÷äðûe­ÝiƒzæeǾùïT×À{˜Qn÷È–1+i÷fm ûH¢µ £]XM¡‚ÕN•Ab«/)ž[>¦Þª ›Fêì{ æß‘úRIÖÇÂ< V£ÿ–¬^‹·ª6‘xéìœLí^é\ŸY󢉖ô«Ô?Z蒰ܘ÷VÛ¶Ž7oÕÆ¹­¶mö»)1·ã5ÌøÈpI)Æ#I‘*î8{×-å´£½ˆ•î:’jó§.á c±ú*·F«ŠÞâLºK#Iï]’ã†Õ³Ú½ÁÐcR£&¬)ønÕ‚‡Øèm½¹K>ýZ—US²6añY3”ÛumáŠ÷·ÛÔ#?®¨:pÖAl3öxƒì!svˆlð&B˜Ú½žÝý]™¬ú<ÄA IíHAÇù[(b@2xéj‡j$HÙ¬HŠ;¿5¶|Ð$d'‚Ñ7ø@jGÛ.ɪ»H€"IIØFêÌhKšI­-‹…À´È^|׊g]ä]# L*Ç©lŒE»|ÒÐ&R#,_ä Õþä6 MsmoΪµnÛ;k-¹6øŒ*û¹%gY"lv÷÷\©qË“ x¢˜Ö ˜‹¾w¹NGmÌ#†IùyÝž1ó@™¬0>™|Æ Å'x$‚eÌdI² ÿç“}+×Ðc«€Ð;ßFbË“G=‘«ÒÅáKÜ3F²[¬lx;âx´n~©¾F’sß=b‹®Î¹¬–kÆ> œÍ!Ô˜Ÿý͉ùïã ™‹u{\öd ):BNYûKÌq.v:”ͱÄÙ yªïqAÒ…Z·jÎÅ‹ ,ÔùQF'Ì a¤±§‘°ä†'¼£ÙéÆ>ujtsä'å—r½ùNùÏu»ÕCKÆ\6f'ÑÃI – UÄšú ‡mô© 'v÷пv¶­ÎP{w1‚”²j’¹ïÇÏ"e ÓÙ¬ùyPQéo(Œ&Žl˜W–‘러pN«ë:!«‘¬lˆ‡ÐÏl2ö Ì!’åI‰ÞD¬/uAÑêF¿D$6ÑïjÛï°¹[¨A¤ÍNE'#t«p)¬‘kwMü·‰œ×7$t<±ÕË_ÇЗ‘XÕ]‹QÉì†çd ÏÓHÞC¿õ«ÌMûÖêÜQnÝfW])æèšìV ¡³ª«"Œ„æR ¥¶¬Ü=îw[ê4¹ÔSÕ|ž/$ÖðVq§%*£$§ò™ÚH…$Jìš6Ø's=y ï$ÊæØ{Íâb ïbl¥ ¹Ïm.Vš³Î2Òe|Ë-ZýÄ9xßHC "ÿ*Ôýûƒšp©Ý·Þ³¾Î!IRÇ~vž@‰Æ‘¶¬FŠêïX"u,RƒX1¸s3²#í]3çñr­“hýeIÞ>k‡i2» ç»S¶›±˜ÿíUN ¢VÝ”]—×Ì4i‡]¤sb¿Yk7ðò:Ù1Áƒ|@×5æ™/{ŽÚ0·§ª§±3ßkÇ:÷ ö9ˆ‹ž˜ÙÉ4_Ö‰§6l¬$ñ/?öÞo¢ÛIFv•Æ!„-²!.¤6ŒB$e Àz«nîbÌv'9Ì–ïÚÀœ—Iæ—u=ÛÏçý#ünÎJáÉïˆØ¹õØaS®Øˆ5^¯nѺѥ‰™Ÿ¸y$O6°Ä2¼w¢³SCH%ìhéå£ì!Óð=ÁéûÃþôäåwÏYÙ°U"RR‰Hcå¿+ÒNœT·¥ÔÙâˆ;á¹Ùä:Hlh×hL‚ˆ„N«?pD2#¡=Ëê mĵËÂØ9¿Ù™¦zHÎAèݸÄhUy9óÌçZ Á±È:ûç75Æv7fWܸñÖ¼¿Ó4p¤A®±9¤ìWôéμ`Oœ œCNõØÐÜô|w›ò’p(,ÉLA|`(„tT¯¥@ÊÊ´Ûø’„$h']ÜøEr”C°,6èºæmÝ+ž»¬-¡¹íªóZhǬ³ãr5’0u| ží)cG—Ø}?¢&,zž î›ã¶‘ž<åÁ¾­Ýã»þ%ª¿o—¦b®Ák†ª½Ó=—nÅŒ¨²iP}VÝŽ¹FºD Qj'HÝ­f bš/m¤¿`LztàÚ±‡2hþO¢¿Ÿ“‰Ð.xú;ú}비#2 jÔR·ô-0 5”ÌI(‚O\Ìf ëÀoÇHðH½¿ 5©SïÁ³?» ÔvHӔNçæ9Ö&óËN”9{5·Jíæ*”lùÞºß(»n® ·•Ø!Ĥùäæ·š²Ož~ß“²æ%ô¡fìl÷²3³õØ_#Ò÷Ák>¡–û ~öcêBØÂ²;d~²öæ%{÷ˆÞÖÅÒ92ì@ B¶Û¯hÐ kʼncp I;@ÒD$T¼ÒQóàÂUoºôÃåì£Ú)c×É,,à¦\êTÌóçå G‘¨F’E²ŽeÐáò½z,ÖÌN˜e0w¤û@ÓH.µóJÕF<ƒ²­Ž•…H­.EòFAÙ»ª6Kó|Æ};ƒoÖ5Øs¿.vÉ$1h8Þ¤0„î—#»¾“ß¹gÎAšB`j«_γ(cØ °JÓJœ–G¥,­Tx6Ä#Ä]Gq·)ìƒNaHʆ8\ºG}$>=––ž ï’$ª8F‘ÿäíŸÞKDzúô哟ЋäË¢Þì4±c5ÃÖ‡¥äŽHì!>ù H»ÿ`©éäìÕÕÈ):_ HIWV2=·¶o!Ë(^M2p‰$Bg°yÊEÐÆÑFp<ÁöÑ^½ÂÅì·È¡˜ymÅžñù'Ò5ŒTÙЙ׉vtkÂêþ ³&V}ß;ÊÕ¶1ç†ÃœË̺ I™ôܾ#,Ë¿Ô5¸š7ÏÞm>ºûŒÉ 2¾ ˆêW!õ¬©Eëă{AÒ Z<áºÂƒ{åì‰í±lt¢¹ g[RëžFžjÖ'Žó&¬`éV$1²Ö'9¤%("½?ýHà´úò?ɳõ§h`îGˆøêqú£QïPÅÞ#ŒFØ‘®á9´cHýKöþîê=.‘ ÷V¡Ám3?ÇV«ÿ±+–¬hÚ°zÙSuÒûcêä.q—l’5WœÕi\_d®>¾³™`!ûÉ"ïy_·œÚhT³ÞAÜ—]ìkíC$µÞ‡Eã‘Lš{K­ðox×JA™ô‘²ý[&UOŸEìýî¡D¤ýË˯îv·ÊëôTÁò¢Þä)~\¢Ž ç{ðî9á‘ADñp´¶µ i¯Ê†Éx_¦«§* ±¸.dlÓÉsÛÕgµ§vC’±ÛÈÏ•w¯•ê&O,Š6ÙÛˆnì½’H3:º$Y0 ¹UÈ5Ræ¨áãw—üêX+oB& *?f.ž*¼¾\éº\Û}‡WnPSçå-‘K«î,RÇä?+sJQ6ê íB~•—+2s0†±$”€ßo·ÎiM„`:fú±ëµQ€[÷’Ree”C ± 9u]´„³+Tcj÷æ)%ÐÜ}ç«$ßè°9Cèy}¼1ôÈ|Ý·Êyz|D ÙÑÄæbÇ £õ ÿÖ~Ò6ÝoóºXá½çÖ™m(¹ë41š@ ©Ý ¤k Iú‡´(~îú“Æ¢³OJsS6Ç0z`Á7JHÕì7­vºÙù|·N»`»\œÿBœê³ðÔšD$IÀs> f6éñ¼H¬LrŽnð¡âÉÃSÉ-×ä/ÈLƒÉÄ¡ª•Hmœ¨p¶$wì©j£úCŽ ]ÛØi67ÕQ5v˜kvÐ 3íݦÕÐ êÀåz!­“ÖoëÀÚa´ xH)éÚ@è)'Ö<ÿç?ŸSðy¾BŒ"|À0Z{³…š H‘.7?îìL,µ“e²¸y½*‘¶š”»#,iDšwÄ܉c±JÀÚ=<ìpj§ŒœiºW }â ó9¦ºIÃ@9ft‚#"ì@g÷x$Ë(º¦qû-i•‹~+ ÞšTˆ½óÍû[¶Q„IòZ­[ëˆT³~q5_ªvlù‰¾ììG•*0b9¯öËÙ¶dæè?â$•÷‘££s5Õ€7ñ ,¢GÑ Ä!«»`j¸Žm£8P¹ª·\ |3p꺼Â2®;ÊÕÆßm1úXÑxWa—Ëqdvsæ²S,î OKu¿1"¢íi Æ  b /Ù46h[§Nrž©9ºP¤°é,ð‡6á'iëÍ777W7åöí7pK—ÝÅóôôޤý“³ó›Ñž£ÉÕUy½OÊ͸»À«üg,çÞúkL÷¶Ûr^LnyãÛñímùO};)÷pÀ»t‚ï ÐߥH Ç™ŒŠƒüTBO8P³ðJ“8ŒAŸÇ¡Ra ç‘:q›ãcÐ4¡E+.¬­™GZ‹IœŽƒ‹~ëL*>B’Ýž>C¡pæö椮\ÉÙ”º¯±ùÒ0¸¤³Žóv¦[ü¼þ3UÉQ+Ør;¨¢;RwO•’ f-ÿU–8Àä°|ÈM)¤|ƒî†öýÙ´s~³sv³ó®¹ÊÍ{{ß}¯|ÏoüøOp‹÷ï÷÷/_¿¾»+/ø_9 yx,ïbè8–ãŽöã²Ö;´7½»MAl÷qçêêáêá¼y€Û«ÑÎn® ¾ÀwéêêJÀ†ïÒU~f$ ÷&£+`Ú¤€¬\ø‡­¼òo $I+è|%n(ü(ð 5;[ì‰@aDR; íƒíy û«Qtµ!ùk«­5’ÆPë¿ué±ßMc*³ 2ƒ¯ 1½f»ìÁàÖ“³¼§’çyë|]J±\©x<×k‘ƒ_W 5Zû'31ß“®Ž|NÆ#œákãô†I`“L>e[š5É^;á[Ñòkž¼/ÓONÎöñ:ë=?|"·ûîqù‚3º-'|êû“÷ô%£Ë×;*!éŽpZËYŽò~9 t*½/ú;Dˆžb‰pwtwDûRŽèÜ;:â½)Hû'åg:‡?;ç;r<è}yT^þ啌và5ý_ÙWoq#@jdȹ;<ÞÂWž?Èî ænu¯ ´>ÄÎàº)'€ìíc+>ñÙW;Ÿo€œreè<^FO \‚A{VÃY»qG+Lø†l§,7Œª%“Ô5~ÖU”¨&íÖO¦5}m[µ`Ý«²jIÚ‹*v‹rµO¶& Sa냢&ÅeÁôÄ{¢8Ýlv9Y¨x,'@°d“ ÍòÔRXœÞ¶f(ám,É™8©4#×>cÓåër•7¼þF=g×k{,|íN|¶ÝPîbdu”Ù5¹ ë*r(RÊ&sÉ”LŒ&¿ÅõýS襊ª4|ß;Š:5JÁRõiEWˆaUt”þ_¶Ý79šóIDŽ5ÿësZ©2É!£¾£¯Ž6î¾:*׆^G_у¯àˆ—ó+¸»ã¯‚ÏïÀô¿ý±˜  µ‰O l2àýr\|ìËÜÓ9,)÷››'%ìln‡ûÃ3À æ–'åI‚SùÖå@ðáw·–»“Ë“ýŸ÷O~žü|2DpÉí¡8û¡œŒ°Ï;Pù`,*0z|R¾%Øà-D>ØŒ?ƒOwÏw…;ˆ$xÿž.(™îPA‡'…’…)FS;h’ß5æþNªÏZ6+®Ù…i†ÖIN}²gÆò¾Žñ6ÃÁÍ$“'Rr;ÇT꣔À9{¬ÖëC¶hãGß`<ŠM,wŸãztg#亴&]ò³±üd)S°z¹³ÂþŸ»³wã‡èc§úIÿ ¸?½+Èú¿DûðrÇ·rbÉ…·Ãr–÷Ï6Ïö5XpÈ8;{÷˜¥œ¿ÿ#æeô*Ïo;ôÌ΀© ²±þëò6} áìuÉùèæ’ÇêaSFz\â&ä¹ÍŸËy2*¶Niå{ŸŸ`ó%Á¨àä ÎÉèbB'’¿ØU/à Cîí SާPB4Ý,DqtÒÕ!–Œ’™î=jÄp¿mZ_naLÊÁÎ!$¶’%»‘X¥¾r[»oùÉï„ÎYƒÖ‹ªsdÀýlQ2ç­°)Ê‚’ðíÑè‡?Yæø0 ¥% y܈f‘/¹zÉÜý‰ÏüD¡í~]®S|tê©5¹¾¶Ç_Ó‡¾Æ/áw¿¦/;ýº@ë« Ž>žßœ}üSyå¿ß9;¿wÊmyõßà<ƒ'$Rôè#/ð¨Ô17\ËÜ” nñÄ"æfç->ú¦<*åÏÉ&ÀèJ/^9yÄûò ðbÃSº»äs “—pÃÇ¥íÒ›ŠÒôDN8~8)¸†Ú`„lø/bfœÛø~^. *ãî׎ALÝ“À]ê^Ó><; Otv:‹QXÉ7N-í³”e|ÌCÀ‡¶‘lx‘K–×wdãRhñ»YÔ¼,P͹¶1Q½©ÈlÚ‚£ñÝÉ«¾·ž’—Êz^IyªÜÇ£;DæÙÑø¾Õ]eÁÅ(’"a š­¾È¡ª‹y$ýhkÀ±ËøÚß]߹@«é-6¡v®nÞÒusõVzO;xûpõ¶œWoñhxu5z;¢Ȫ]ñ#}xµsþþdx9ímü÷»ÿN–§x#›¿îlÿבìvc…£¾óW0œ^C8s»¶^kÉînJ<ºÀFÓx~;¿Ÿßv·šŽÝò[÷›0ãPÀ¢Þt„#_>ñý½ÖR€§ƒ ™r ä{ô}-@áë—³=¦#4liUŸ[Ñ8³(aa»ÝJÛ8„ þ-çÁo!)¯à'r`** ¶—ñ©ßœ9ðS•tÁ«.u…¦óæ]W™¾úY§P ¥%Ê?çˆzùAõTøð›²l<Ö¶¾>ýꨤ߰ޮZ±ôÄ$Üa3uDïÑ#|¦:`¥ë4€7(;-o/N_œ–›˜Bú‰»^y¹ß<âú=Ê‚0:^÷_¿ö¡j:ü6Žƒ­4É÷ä˜ÿ^ôÝðë»ÁÇÛÜh‹•n;í¸8" ?qá2Ge#QU|x@ñ?9ˆ9ÕL„*0uÀ¿Ë8ò-#*Ì›Á{ §8ü–»µaµ’‡&‚àò[3SµTÒoLQ›qþIKA$‡5KÙ‹8$݃Nµqxsn@9-¹ø{ÕD^¡e_ŠÆpÒàÏK‚q¸XiŠOTçKy¤tâam÷¸iÿüæŠ_íëöÂ_‡wÖÝñHúÆ2µq«vãcrS‘)}Öq9ò´€àx÷…%£r¼Ø}=ÞãÓÇKÇB˪6ú{õðëkQ%$í” WÝv·°žu°(/DðbmåÄ»fÖÐÛ/«å òŤ1pä‚%8ï•)'z‚câ鋎‹¨îžIˆmb"¤««'2‚lepçnx/É*Wg¿°“—鳜‚ìÔ,­‚gª$Ùê¶‘§hóà''ÂòI·ìÜ-;Kµ '~°ãü=òsߣu‚ˆ0—yõ°')Œâz ¼„ÓAOiD½„ ñçü”{š§ˆlšˆ?Ç žr +¹ÝÝëË’ØMpçí¯à M$Wý,½kŸ÷ËÇ€´?-@:}²ˆœ "<ƒh‚Põb Lª4ÜÛ:0«ÛsÆÃbe2ütþê ¤n1Ûn ~¶B‹Cá3Ã[†‹p÷¹ÃsÒ4×P^ácÜ™…¬ùèbl‘é#ÒØM’zâQš‡áh€!ÇÄ-µ—vÀ'¶é³½Ö­0‰3GÑ>µõû½—8eŸÜéˆ:7,æµ)Åf¬Z„³Þ'NÚ §–j¼`ª´?ø“5¤Rƒ¤Ö<úZõ³e„9…¿*¾]e5mæîéË•ÇÓøøéˈ)ÅB íKf·s5ñn’æ£4 ;¦$…2ëc> òV¡¨Ä©õ pãÉÃÎÇ“ýþë»cBÍgÔH„)Ú‹Ó KœŽ}\ÚÚÊy1 F¤ÑÕ¸ÔA% "ͺ‚ò Ÿ5ˆ¯ò ³€(<àjºeØ4Îc«qbÂˆÔ Æ"}À€SÔÆ?pÅ4æ–Bé D‘öoCr‡õPƒ“°|ÒGâéîªTýõ¯v’ç@!‹£@Ê$AŠKÌZƒœhÍ<ÈÙsµÕŠ%gâ•] ×çšq{ û©IM0‘ˆFH93M˘²Qáqøÿš¾(0bét)2-C©ÆŒ%-@‚ˆT€™@¦ÛÞÆú¢D¤‚¨(:ô”ˆ¥q ™¦{3Þ2i ]Ûç:‰H€‰1ÕH#ÉîL qaPÂÆ-x0^'}&J*Ó´Ê5P~×°W†V2R‹ ^—–²ƒ[tòŒ·{}¶-¡»iƒnÛˈ\+×fŒr¨À¬hÊÞ)/øx6 U»þüJÍ%%_ò‘4ÙšY³ Ð…ø!0ñÁ‹Î'KWý¬ûÌC±a ˜D5R‰H'ïo&+Sâ2À[Yµ¤†âô'všb‡0ÂPÖñ³%"=|<›^B´ËY É·dd©œ/êЄÙ^ŒL”Ž#šö Í㘄ÎÝ‘Ƹœ¢„Ÿ˜›f«òn‰Båém@ÖƒPAY‰G`_²Xʹw,1ži8ØÜEHÝëPptaœé!\’Eã‘:Îâ|›9ŒH’÷µmðb :QëUã£ÞB±– ,÷¢€ú¤ƒpÔurm.Ô¶N„«ýéÑü;‹°('?Æš|6–ÛAc\uëw¼Ø2ËœRP5y6AMγÍ:.Ÿ¨Ü±V»f­òÑ¢›ŸÈKyNí./÷wn®tþÏ[± j0 M RëüPR8¢<÷˜a^‡ià:†§® #ÒåÖHF<œ¡#†%Ôš¿Ø]*š,ϳ•G.¿ƒék¤ùö¬TH47[^ŠÛ Àh¤ƒ ¬—¤R¢›VÙ‡¶qºk†œÐ pIíFOZ)Ý‹¶9i/}!ä¼\; Gܨµ6-Jƒ˜w·m}º (‡EN—cåMGs[/¤p!LÚŸô{‘·OV q—d])¿f»)råm†T ÈYXh¹éZOæz¿rŠëÑtk_JŽrç-þÞƒ‘„éé@´ìÂ/ÓëÚO¦û5Çè\„ÌĘ‚PˆGݤc¶Â1 ¤)F$†0ÿd£Nêñ`p:–¢éøÅ–HÎHÚ#ßGè(Kj‡¨QÂŽÎE©‰¶! ]· ŽçŒ»–½YËI\m,™Ô£ —t¦RX ‘BÜéõ”s hÄÔ·”îï15ì¾pz¯p@²¡k5Þ0ÛR4ÑJ¡Ãc«˜¸-†ÌiÉÙÇ[=´DF"×àšÃž±ÖK²g½jtQ5‚½;³Imݪ$)›W×U•jÍ„´n"ÄM»O•ô´wèN¼ùÞÞþân«ç{¼ Þ£WÊ$&Î-"1áÀ)ˆ4&M¨ZçŒ96I<*·È†¯~Æh°…ÈâÍQÒÏ‘0ÔP Z[£™ô7[kÕìàÖ2 q¼™R²Î²¿§iX"ÒÕÅíÜ9‚o·€µM•"8†çs-)”Ú&£jâµmí€-Y :\”½#,i»¶3Ý*òJ@ÜK‰D¹]§íWÊí8 )ÞºÝ ºVÅoUñŒe¾u#Õ‡Òœýì®lrŒFXÆžª1ôVdpµÿKïðG¸í}PnzËÇ{£¾âûî[¡ˆtzw´òþê*F€©u©‰·LLØQ…"Ô:“zëspX§Hµ>¶ Ä©ô‘8Ó8¥”ko,6qÖDZé•T¥L’ãÝYvÇô÷šÛSÂlj!Èå°2jè}*’(¹›5 £ÙRü©Y¿ó ­z/IHܽ;—Ýô|ëö¦ Æ(æŒ9ô` D¬ÄXê£uÉé1>nˆµÃ\Ä€ìÖÈMSK§µ]c!\÷˜ê¦cÏAÜIÇV7†aD]ÙëJ¤mhÄ–i†$Þ@³Ðx´pŒ=$’|”9"ášné#¡ãÀHi‡ 7”4¹3owßI3ÉŽe ¤n ]É^’|R÷G„WeÎÑ2KúJq·y3 ¬ië ^¦MÞÑ;G{‹2nÎ#DŽ]SljˆÂ\ìfSý«E3;ïΕW‘½dCC¡­;ðÛ‘õx' +1(•B Ô¤ è#!kçW'­“÷mqÓgb»‰Íã`%pññh"¥F&HìÆE¤Ÿ/ûwÇBØa<"Á⨜ÑDewkÙÙ¼SÐAœš°xŠH`¦:<;?ÒúHdí 0A÷ˆ ¥R*O”׿&íÍÎVG ¦­hp¾AÙ*± #‚OÓÒ :ÕI÷NÒÚ9A+Þ|ߪ¤míÉÌRG‘¨ tCôðÎbö›ã@xÕÍÞó~ÅKŠWèEÌå’îšpŸì GAh××Ò¬œr­8 B!ý“à´ƒ>ÀøÆX6›®ìh×\εñÙÁ»gåíàÙ³w²ãžúõëÙ³ðuJ`’O #Þ¼AeÃÙÙÛI\41c<¬‰ÆH7”{¶G&æ›r‹ŸPÅ£õñ¼jÉÞ²²áˆÈ€yx¹c àTnÐveM½ÝŠ}@q `:6Ñ)ñ€§ˆ„}¤S „¢‘… ÃÃî0Þ Ÿ÷‹f5–êpdÃBd4Øî¸‘Ùäuì‚3bÆÄB÷˜áQ7Éø»Á}”ú1yG±gÐrG¶Ñ>’pyÝ¥•®©újr¾ 1Çi}£³ZAN€ê»À½üÙ‡²äë2§2·,.êb¤rD_®ùˆìe 1fÅ6¬™zWæB¨Žã³9 )"iÑø3ÜðZñìm ÿÅÛíU¦ôŽÊ$Lívlx¿sU{k5{G”ŦðÉõñçâUFëó«$4Í¢ÔŽÈHNk– À$Å÷Ý*ÁÛå¯@è…è_ïIlÁºÚŽH; DtH „õRDZi@<Ã"ˆ躙ëÕmYþwdï/F¤k ‰<¥DÄŠÒ»{´ !ú’¨J’QÚZ¹ÊÃ6FªN†ÔÕÝ7U. ê‚b±(Ì[ëˆ^½‚\ÿv£Õ)êä›Ö ÃM¤åFX*ëìW‚!ªdƒ<$y–ÖéÆLW=-åØ~ŽÔb’™? ÅY- ‘„yöáà7Áˆ?ÿ!Õº²P#ý ÅßÕºI]$7Êáq“i6¤‡þ‘G #:`DRCvè:Èë¾u“oø}(h CiMq´eý¥cÐæ¡å×±IÀÛM¿ Qj‡Ø†$w¬m €„X±þël)µ>…k‚1mŠ•~ àH´vâ/t!%jËR‘D³KŽo(ydu÷Èðm[¨n’Û±¯Sl5‘R¤´5(³£°\'ÆÜÞ¼ïiò4Yy¿¡€ÔqD²Xß Ê© -¢èfl+ÉêKi™ o«U}Aírð˜Èn´ÃyÆ&ÇÓ¹q\ùí!C#} á{òìg÷èAc¬OÆ^×H'gËʆ¹^IR1Alž'ìÆ,â&Ò8jí®ÎÏöû!µ[[šì‹%pž„R‰[Kk!ëp\5–`òbO"Ò55d'Ú5x èDL-(ŽÒí†tv>Å«R»¶ÒÝyS­_äTCÄ6CDàÙdò ,¸ãˆä'þP,ÔiWÖE$¶’S6D»óû=7ÙjNËD cÖ C®l¥v£«“ÍKŠHŽ7Ñ(Y(p¤Ø?œØ»µ]˜ç-7‘»;Æù%¥,µ»î_O‡0×w5­…#ÑbQ#RG£y3~·–­6«ú±•±¼ñdߨ¥v£ ŽI‚¦{q‚À`™ÓX!¡FÈè†FR;1€n•„ 7ÆkiY¤ã¾Ý@_VËQgwšrªV±xƒ ÷g¤P!yŽzy~ÏŽà¤Ô;a·RvÁÓ£?‡ùÜlît‘èözîìYœn){ÉkŽ{˜½%¦üN, !Ûð’"ÒWH‡ˆ4·µ“õ¹‰ÂŒ¤Ñdçg¦—ô}Lí~viëlÁ ‘Din…Á¡xItLaé…Žb'‰• רµ{ŒóH(±+y ˆqÐÆkgµÒ‚š³nÊ»G/A©]˜7¯ Ãîz ‰ú{4&‰z•ôß:G1v"!¦`uÃ Ú ñ4qè¨)ÛñT’É¢ãâ÷íš“öJªz=ÖFRif¼V=Ågrp'VjCe¤#¹Zk[ *ŒxòÊk<‡ŒÐ;éúÚ(WõÓ«"Ò»oŸ}úÃ3,’m(iëtão—' 5Ò-í…¡2Èê$ë*ñsL7H@²xÄÉ W50ýýñl³ßß8•IR»§¢5†‘öf¥5 !É$Ô±’Ì#ÒJîI×*Z-©OLÍ™™è(>5VK0˜ÂÍ*I^·hÍ|.7V#ñ¬9#! Š$ÒƒœgÎmê¼C| >*4*Ûh;–'dVÛNmGB¼qâšVïfPÙd9®-/ÉY®t/Qk™[Ï+'ï<œV,Œñå[æÕÑÞŠ)iûäèX¾´S0Z¶ºé/;jã°zi$+Ï|óƒ¢íJdÔHBs3V[I·Ö‘µ ‰FB:Ti\¢™=hÈŽdIR»µ¥ÌWüþ-‹ïH’×mÉø’˜‘snÇ À¹#‹¡s!ÙPJ¤wƒG$‘µàD2U’ª‚Ú@9´•±°<¢m”€{IC·ÍY…tqO™Û²Òpsß$¿eŽ‚T ÎS=d$©c„‘u9²úõ°Þ$¸2$Ÿ,9?Ôàpuz*$Q5øhÈ·¼s°ŸÝ‹º¥R=§®â¸VÂKÔ=óÍóå˜í¶Hq3RX¹W3§g¶úú¯îÁ]z’.&Á{z‡ÿ‹j¤­ã»¿]¾‡†¬ë#ib·N†Š#U;õDša''Ó­5?;Qú{kS»ç~ǒʶTz§+ÿ¶ü|Í)íë䙤 çLÈBDº­ÝŒx†Ù6Åžm¤¼gRI}ÔI}Ôzº¡…Biá—!ën>Vw‘Œô¦2ii´ànº:E÷<"[;Ü Œ¶%ïÓYCÞiž³Ïkê‰ì`äµa=›Oåu÷BÙÙ D®ìFrðÜŽóQaÏJÈã4¾8 Dz*ç¸`ÓmA‹ Z—¤ºíj&«K..‹g¿óøp@éɦ¿ïŽ.ÏÞãj¤u·ù*#-Žd* ‘´ÞÍ}<ª9º%cHívNö_cCj¤ŠmNÒ“vÒŽuMYËíN¹@2ªáÎ÷‘("!ýÝÁPu‘JlÒ*J£1ÛPú4ÎE)ðTC+E/X–~l# Ù±ŽRHÿhĬ7gv‹¼›Ðâ0IIåvÛ(j`/.RR¼¶ TÛ¬fm´N‰6¤9>z˃°¦Á|PZ*( i€"G=Ž™äyëÖDF!ð¹Åã$,¨¨x ›9¹©À¬«aS°Põn’Ù‹^Ýpnö@–°[³Ï~÷qð åvX#½¡†ì{ÇÚq3öÖÔª“uW¹2h²*Iàû]ÛÙ óHÚÁ†2‘fàhôíÚ®Öv—·1Ñ Èí^8/Xp´çȆ+$Êæ:2:4ÍPW·à Ò58o Ùr'iÑR$…/¡¤ÁÙìl„9ŽtÌoL2ŽÔÙ˜Õ5cU„ÍØèªJ^'4vÎÑJ-ÂdçXܨ—âÀ¨iQsÊu}žÅဲ(ª÷Æ,Wu&D¾yëÁè>‰ ³ÜöqÅ3mž³ž °hƒ­¾-ÔÊÈEÊäËm5våýþ[oAV@úÙÔî·\Ø’-éFe1µÖnÿÆj$!º4ì†UÅ£u C16­w•ÖîìDj$ŒHß®éö?xB 5­Æ×y(q@¢úèÔ‰V)µ³ˆ4*iNÃä<ÑGèÀ¶’ô¶…´£©i–(ðÈ3ø€ÄÛV4"a5ÄI:-‹r† í á<ì%sö«÷œÙ‰Kdç(nvVEÁÝ6Yñ£tUÙqR®™0Òµ)¹j¡šyV6û-äÆð–'‹²ÄËmM&;L¦´´ù2 M°¤ç¶Gò‚  :oUX—½µ²#Ã×åPûÅÍ7¿3"à"ÓßµD3;Ýêl1I¥ ·FÉ݆xÄ^vë Öà;_#v>RD:eiïm¶N,R [ÜDZ“ênÖâˆßé)»àñ'Lí8±#G.Ò’ H~ÏO H í!Á‡ÙÿĆYë(p¤½éá"l‡ ©Áø=³vcAnQº¸¸73qŠFæ¸ øù¯ʨ3 |ÿ¨yººŒ]+uǘ«Í­óšÝÀRÐËx©^R× nì»z>0Û«ÖâeçN—£Î4Û|º¨F[]ú­©ÖüÔ‹ölÙYV {^Îñrè'y»2µRþ(ú»Ðß."m~õºÔH;W·síÄŠë‰6‹,§lÉÓ¡@âÁ¤¹®Zž¸àtÛQDÚ¿ìQD‚îЛµU’ŒÌr}ÄX73Kxè§0âi¯ßiÞ!*¶ÁîA ßÛfìl3i·½œÖ9/È…‰‚~u3 l#$IBÆNĤKD±:ø‚Š$„)ÄWÛ%v¼’B¦c% d}žçìÇôüX\vZm0 ö~¿:ʇ«5 ³ó/Ds×r%SòÜæbÞJÅÛ¤èÌ_rf¨9¤æ\±ë~¤õûgƒIeŽ¡wEvÿ)²ýµI¿+¯£ÔŽéï—ÿñ|EDš+ݽ.À¹U¦NJ¥¹6‘88MDv'<Þºp ·Ñ òìgˆH2 ûf+¬w^#Î’ÉU×jå÷ «r8:ÕÉ>Tí‰éñh<™“Ön[ãy+H騥a†*Íø½w¯k‘¬þju°%žŒ7g£H©Ì¼ Ü7y h…´]ûé‹i~ËÏ“óþФÍE0Ñç$~G倛 ÷Å”*4Æ<‡”ÂbŠh¨ho?«žã:¥ä9<æÙÜ„®høçn`²a>GYT~ªé ã:¬j + ~g@"ù÷á_D"´‹ Y£¿×'ëŠ$ž›X×:‰¹ðù:æuŒ0—º™oÊØóvc­~<§Õ;±>Avá[pðœÉ†5›êãÌnË-´å’ RH‰´‡«,À €‹ÆÝöŒ” ‹Yóål"ÔX‰äÔw³ÐEòªÕEë "[ë!ÁK}›cmÉ¢²Áb’ŒÇJ'Ö|¸îƒ›¾¶uRË8¡Üß7ã/km˜Onͱí%Ž~Æ^g§k‰GŒHöãàƒJqD5WºlÕæÄÒ¿*ûStbñËÊmºÜ:祭)(ÃS\Ñ+‚ã߯‘þþÌ„ ¨lxö'äý}f Ù¹ÎNhitËFB挢u>·ëcåð>£ºÕˆ´?}}$£æ€—ÚѼ, B|ïk· $ÁòØùïÓ@@âq¤‘®ÀB‘¸‡)0eìÈ[uÑÌÚ:&µËÖv­µhenŽH°jb|áð â§/Ú uˆä!$²Zu&úŠ»…¬kÑÄŽê2 UÛ²<“]õe:‰7¯ähtÕ¦¼!Ü[ÿ¤Ã¼<ó l…_ÏÜV©~¢Èöõå螟‚˸Uj9Å­z:‚WÙPpŠØÆ*›þpÌ]òÖü澤•ý]yk€þ†ˆôü)ÔH—•DÈOLÄ!$ S¥ì\F7V·U˜D¯3|ìãæ"$^\ ’ˆ|·˜6ˆk ª™>0Žç|ç;ßG •wñPœÐ'NŒZ©FˆzS>ªp‡˜zUU1”Ö‚´ÔúüÄ5Ú[bÅOakI°b2§©“'ZÍE!‰AY@„z9øÆQ»«œ”vü½îm쑳Á+­Gka[B.!IÌŽ²ÍüfR¥%/¡fÃÂX§XF¨ú"™’$b‡“؈4B•ß1œ”íœø$M.Ž/ou=RÅÆ *BºñQ}&Œ[ë3¾Iêªõ™hë(¯óÉ! y.ivLÜ#­-Tpto£²§|‘È‚æHk¡°k† s²¢ ê7Cv4Í%ž…4D¬ÝŒÞey0GN8&ÕŒ«ÂuØÌ/ÄB‘vPb"Šœ[1F¥„Üõº@2‘«°KŠd#l#á»P"ªÅòD¨n…ÚR޶„¾‘˜É öHW³àïuë¶üçHÃSc TÚ¹Yϳó1ä3QÀÚy…Vî ¡² Á!æHn±o 3&¡°Ò à f4øÝÕÖ×Rعi,¶GAEhIôHI(ý]Ô.µmR·ÛIÂ|ä*¼îŒµ‰ë_¨Ïä­ØÇõ\«žäK´jž¢R-Hé—Qï¤Æ²'èçâ;$²˜m’Î*Y¶°#s.îoÈR6m*2aàÔú±Sž{³-¹0Ú"¶ÊR÷utA„W›3ꉂVžl؃”—Gý’\I¶å’P)É m>…al›ÌGt4ðìFÜÉ­õ9†÷H¢˜!¬Ž£„T¾S ÖE&¬Ös©þ]g¿qÂë\o!2!‰œ„S¤fÀìdÇ }ÄâXòúªYæ c3ÊH¤‚’u§‚yG1¼ðn쪌_PH¤£ƒ^J`È”¦ ®£Y¬IbezA¹Iå.²žd# Ö&Ü‚A$覹ǵ§˜à™Òš†IBȽ™$CmÍì›® #ß#yõ“u?Ýâ3‰è· ­“ }ôæXÛÎC XßUæÂD c§ÑÊZ¥5ŠQ_Ú!mÙ '@¾ׄF¤[ ˆ5íŽÂÉ c=[Õ%$’ÿîõè7d+ÀlzjÝë¬b[Q‡lTý­™–‘lž :¤P×yôhžÝ(Ú€Êv.çp+¿ÁŒ"ì¨Cò"«iäÉœ·Tv6ùÁ\–óOÁ¸Ãu²R°ÿ6Š’Ãˆh¥F•€4䌭–]å†Rˆ0©ÿeŒô*Ê=ˆÎ%r" š]I$ƒ"Õ—ÖÈ7ÊJØžI! a§ÆššÉãuý½‹B.:œcß2¸XÎ1ü=r_ƒš‘ì/ç ‰ÜÌê.0€ºÝÝ”ôÆ<Ø'¥NÝÛ1×sXÒ‰0 ‘Dk±bOÎÃF:ºÈM†`¢Âg/ýrÜR{éfF¬±Êª\”¸’Ó¢ÂfLjï 9 ‘o µ»ªò-›‡é¨ÍHc¨ý-O#Mâ”v•b†Mù2ZñƒLÔ|'8Œêy¬n—ñ^9íP„%sÇJý3R“YB”›š$öJv¼C‘¢ Ba;)šM¹`ÞLÎôêˆdÇ.!0à×eE‚ȱl>âÊÎMv³îBî§áï 5 "š²AʼëD"c'ˆOY#¨G2…VÓbRm½Êu=c4H§´€ÄÆþj&¦7( ^O§ÈûÕ±¿ÑbƒÏH[/ø›¦°¼9á§J 7LD&^*œ6ù ‚Ôàû$HU7Gè8ʬUØßЛ;j’ºP¦A p¡p~bv}#jèàâŽL]¸GéoÌHì['‘â Äóµ#“¾:sÂEh‹êrÁË:Z¨@"_Í&g"æ4?óÐ!¡ÿDÊ!A J=W»œTÄ569ÐÔ C¦©zTw©”>NÓ`èóµgMŸŠ01Ð`俬È9B¥Dm7 ×¼DÉÕçš@ä“‘œÌŠ_"ü÷”­DΞ™y‹j— / ^hÉíA¯t~ÃxÝÕÀþv‘ô¶@ílhf±A2,œcªjÌÉÚ ¹)!DWE5BŸä2Ò8¡v´‘Ô8"Àjà8jCá ¾X^ÕQƒ´Aó¯"±=Ò=8EŸ± f¤,è¨ló ü'زoFhA¦Q‡„¼)^ ëuä7 <ëfñï ’·kØÐôÂA^²Å”Íø>,gGå]îQm$àyÊ —† Mʺ1”ì—”¢ œÜw‰‡äû"ºb@awTq”û•a›hsI–S¤Ag5¾mI¤èB"¶^9³Ió²\sú1“§Ù2V¡—ÉõëÓf0 Í©5Šë­šSFÚ°ŒÆ¶÷^¼8ë¡ï@ bÓ‰aésDN¡‰ˆÊ&HPÜUµCŠsÐØ¥‹”쟱âˆ÷ËGü2_XC NØ"uzçË qí2NHˆ.ÌH:C<@¢ÌD…çàÑÇM“ñ(xêIHL…É‘áêDÅ»O *$J —ÜRÍV%–Bšû^‰S’ɽ~ƒƒìùFð¢ nRRT±ñ„2_²œkRúÑùÈýcEO5…Q×°æ§»ZÐMr»éLÂñ"¸sN?„^G¹• 5þÀyש.Z¥e”1¹A¼Ž?~Lâßn±ïé* IDATDô1#¹5Šv¥–ß.)B Át˜“òú:!UÚµHd£P¬Õ‰òVè‘ȲéßDDVmc컯-ÄQ—ÆlÉyìÒH(ì„K×ÊsNi•$ê34…- ²Á;Íú0ÊWös¡>æÖ~æ;y/ÚÐlLG>.ÄkPkã’yÁŠ'ÔÒº*AvÊ@&ƒ“ÆcwÜ%Aö´Á¹¶³mYADäãÈO^9z¨¬« ¤B£&#±8¡¼Åä7y¦G~•rʨH™Âï•HÚDŠ@ÍJ´“07Ê׈E(Ñž‰­ÄäWh‚êCnÁž)ß# s>Ú—ðK~LräÝ!yÑ“Jˆ –0Âiv¶:ð÷HÏQBœX>8"Ñ.ŒbŽz" Ïnq;}£[ßAšÇNÎØPrj\¬JÔQn«BUqP×ÕgÄÉsˆñ]ÏcKsC;6„‰lSU)5ceÕ”WùÈZŒ!€KÈ Z+äÅÄàf»y"Eè’y©¿•QD%_Ô©˜¢U åY­¦+Þ^¯+ ÷ í´Ùbƒ©$÷8±?µû ½eÒˆÜa‚8˜i%8ˆ~ê/íVÌI<½ àor5· ´¿…Æ·Ô²‹"iÂoOĈØ`FK± µÙg3Ò8’7‘E²q¡„äò‘í$Wu ;Š$f}/‘{l#Ù@êäMó†c68ÔΛˆq, a»ÀþÉ¢0 'ë|»$=ä¤kGZ«Mò·зwè«ÇئXéóÂ^’nrß!å!ˆŒÉrÊI4=ê.˜ß€Éɧ¤†Pa ;",ìÄ@0C¦œ1Å—jƉJ›D {I Mú|1£HØ &¢IŽMÒ2¥Ug‘HOöËàý-zä{¾äÿ‡„ä∸v6#ü='6`Éo¹!¼c÷H1b×Pëµ+/O,_|utò›=ÛÁŽl»]’º*i}KNƒ”ûFá £a£¯Ýc©´ ÄÈÖlD"Än&h~#Þ-wøfbéü<¶vâùy.¦³P y$Àx˜ÄîËÊ~™ú—µ$wâѵœä¾Sá“ûÉ*2»±ðò‘äâ‡x”Ž\ëTøî¨P±Än2þkú@‚].vÔö’Ñ ¦Fˆü('rc"WèÞ“l ¹´.•Œ¥î^íENìzù/8ó…uöXÒ+ÿ¥¸vW¯×#yÈ-ë~ê™ PÚµ³ð'%t"$"^¨X®ôµzƒÚ4÷ìÇþŠËH 8Œ`€ß‡ÚÔ>_Ë0D¾áÃCv÷î˜ÝAY…µ>è‘JÄl˜ar sùª®î×'ü~yžúø©so„ž×VeÕÆìœ§ªl«º¦0r ~H)Y0󩈟!á.#à9ƒv{Š k7©¥¸gƒJ¢º›û/‘¨¬ Ø•Ð*VÏ_”·r.Ò¾fž+$O•›K’DÔ9#Òƒ0NöØ_ðxQtWc„€dØÌ•fÈUI\w†?íWÁëDFs$Û#ÙÒŽ¤¶Ú'»®]”u¼Ï:¤v¹Ñ×@„¯eÕ܇‘ÓC™]^vtÐe¤O[mCqb–úöDU­QLRßA‹ü'8” ¼s é˜ÇÚHªºŒ«æyoàn.›fèwéóN‹sà2HRƒEy;/#± é«Ma=!<ÌӠ¼ÃÔ@)gIbÞC¢}¨C ™-Ut€Ü¡‹R*Önu>¢Á‘®ì|YÇÆ^ r…ÓÀ 7ÒëA+WÚðZ R÷-Ê[¹ÅW–9JZk%ZÒ͵gl.ÆÂ‰˜ó>ÒâuWµŠÐÉlÀ©¡Q» rR»÷‹û#ÿE{XGjAífÇ¡Gê8Šƒ$JI'Äðˆä‰ý"’HHBžØó®[òC¤l˜ïœß6VE®suÉHg•òQ]°SËa”ÏhÝü ÷{†*ú]Rëd<³À†&÷FMn–šd‡k±¬ø-Ì—¬ƒØ, „U?‘5¼üš ‚œ¨ 6‚hžÄØŽ–ÒBu”š¹Ãª.%±VRËÒVa‰t›Èsm—i’BŽT‹a©k¾°Ã*é@j¾K^·,]qÁ\}J”L¾Ì‹ÂÑFPÊ“_¡=ò ÷H±G„}¤FÐÀ— »ö@ûn÷bÄцyѼöJk6jP]W€?Vhàm]@±;$¸úZ‡HG¹Cêc–݈çØÅŒÕIQÚá)+ê,öíóŒe¹°›Éy3Vk ¹ïºV>ñ }†IàÈ“[+J9d6xG$‚¼,¤@8!y‘:ì’2½ˆÄH—vF9%¥¯ÝQÀ¡´Óù¨éIÞñnr:"> ޤó¶ç>&<ئ|ÁL4Œ•º ^-RÐ!ÆB ™kú¶iYØ»”É3Rz%BPn¯ã]ß‹z$@í>éÀ‰5h¢jÈOsÞw¹}¥|$7ÌçdµÃDàïÎÞÞ‘ÛÁôˆ™ªd«ýËiu‚ßfð£Ø%LJ’€¾ËH¤Ù„ÒŽôT_ðz'Qî™ñû|¤êQà~Ä.7ÊCéb(§°IjVš’„$„ì˜Ó@C€ìx½ì® b߈}CF@ÌÖúæç;)#5¨´«Xu¸à@Eaày¶‚Ñ%¢ Xá™zP¯“…©{ÒjA¥Î’ˆ,ă$䪦M”ö7GS·‚ìpë·( B1AH8²š ‡Ù,†N&È@E U(%¸Î½‚Ü·7¢K®—˰2j¼Š:­Ü<Åy;)6yU[èF W‰ë 'r¥¢—DF0^CÏaæ°‘!æÏï‘®þìi×´Fñöº[6Ð {$QÙÍÉni"ð*.Úƒ¾j EˆèAíµs–}4³1¢3ð©‹MÅÚÔRl„ŒUØ$ê7€ß$k‡=®™§no¢; jùt+´ gòð%¬ó…¨”·œ(IÔ€¡Bx[ ÊwdÏ—2¡AоS/Pì5OB{ĵ\-Òòט–ºqÂWu­Lñ‰TõÜo6aûMIÿÄë°Fioiób¤˜– 4½DWzº$LƵ 3ô ’‰×ûÔŽS „'­kN´á›H«§Ÿ[ÚýÜË]j‡Ö—¨´,'X‚ËsÚyŠäUUã|ÔNPÜÚB*ÄEö‘ Žö°Ž>à+SìÚB‡D¤ïµÛ1Òá§±ˆû [Û|i7×,Á;uyh†<’Š@LEƒ‚p>«pÑÖ‹ñøÊèC%%*º5ÞW¬ÉR߬T¤¢°óHC˜Ó E.Y ’5àWÇI¥@9¬5Eˆç×U Ô¥©ç2H9oi.+OÊäº*‘¡è + ñÉoóiZyâ-šµ’t¦1šaæ°D[’º+&Wr®1ª—Ü ^Çßû1[ÈúŒ455vþâ,‡Bè¼Ô7Ï]‚b˜wE Tb±ïPØj·|qÁb­ÛÎÑ!Úqaצe€×0rô¨ £%?‰õPCï<”vl( tŸpÒv\Ëͬ,™ŸÇr ž­š™<Ø\b"Â6ÊÐ)>!Úõ¦Ëˆ2ÐöD“]ÅšŒ€ÓBï:x.’jáDlUÃHƒ¢$Ô\ã|¶;£ÁTÁEžß€-h’Eaä º,Ë…(i´×ësVÂÎaÁ\ŒgŒÐt[°ÙI+ð.SL‡k°ABþ*Áù1-xa" IÍh^òs™ ??%íBíï=ßx{]ãCÍÁc›Ifð Ÿ‘x~Ôðêíß ?k(&Êg¶BFZÁÚ®‹š$Š&– j‹º£Ÿ¤÷„¯é0'ÙŒ4@ úŽ×0¤¿‹0[-Ðz9ÕYm«p‡°. Ÿ]oäµU1X¥0Tþ¥èKœËÃQÄ®Y4%X'O2¦40ٛĸxŠdò(ñ‰Ë…ÖÇ‘ ^ˆ0ª¨bQ±œI´¼¢BÚüyŸ˜È·%ZöšEÑdɨ|$F¹F©Ù‰ù’ j©FõIÊè/ìyˆïŠÕ&©í*Í4“Æëüé.Ÿ‘€kç²þP]CJ}O ó˜Ÿ MøXjw*ŠÀ‹vŸ‘¶ŽbF:ʃ$1>òžË˜Ú"ÐNè‹ÊŽ£é †.QØÉéC؀ nûé{ÆÓT…û2‘rÁô檮ž…bh” pÃø7ª?z—XrCª W…Wšd+V°rû³d^’T¿s±&Ž™Ç¿ÅæjÄ™êÀ„ ¯®R Ÿ ÞÆÍó\+Z™È€6bæW;ÆK¢øzøäÿ IE’ kL®'¹Aü$L­´­Äæõ”J#Fâ">)þ\ëË_$!…ÒnËFØGò‰Û#^.jg݆vNHj ‰°o`ã©¢àoƒÔ€i{¤š#ÞÐå½@ïòQ[¤«êôNz4ò-ÉA«¡ƒJ;`ÚATÃÒ.ã=Ø 'Vª‹4ÓÊkðÓ#ãIª€a·‚FSNc$D }“$$†QºfJ˜Ùó±àwdó³4—tY?¹¦kúS1A²¢ڢǬÕJ€6ØÁ9¹•ª"wý’‹£<ÀŒ—q5,gØ#Q›ÖfJË YÊ6+ÑŒ¡Dk¦JóÙ*†í$í9F쥆 ^wõMþ†@Ú°±«o¤2ÒìœWøíb¿p»àA1%’×Z¹CšS=’óuq‰š¤6opÙÆÛå‘=ߤ¤£±ôGKžÖpýÌQ°ÁöH.!!jWŸŒ!EW±í[|‘ò’*{/› Dé!Cì»N˜YJÔR9á&©Àal%¥]¤4ˆháâ´jð’u€èMò@´Ó–¡ÆñdÊKiXñóÂDÊÙ¦s!]ô×Þ6‰rê_ÓÚà\û2­b$©îdØHÙµ@¡ƒ2ÓbmO«Vho¯óB«¼!k3RWßуG/.OV+ž(Ùâ(!5æØC– ½v²ì›‹òQE°!;69åàï’mðÕ,íúúZ”¾{$ÉŽuƒ:üÓ¹õÍcFr¥.ÈfDlzù3’ªvúf¤´7Qîùè.e&š•šŒÄ³»ÑëNvHXÒ1úKH…³q‘z'ŒÖyä;0‚ W(éĬ(X„°iζ^KEµcûK’xóˆj°HN˜ì)ÃØDH˜VŠìh<­AWI'ð5–o ¢¹Ü,—ƒa©R¤]¨Åº­Ôâ»a¼N¤$_Úmlë[Z¢Œ$#I®¶Ï s)s2! ú´+b1; Ú¹@²¥ÝÔ–vŒ·uIÊ7DR›²BÌŽç°l*¶„;b«ºtÄúù½ˆ~£†>qífHTµŽB iµ!C:šiå1«ÁoÆR2Â>‰Û#Ál°çj…ÜÊ/Èè’ц”œÅnðú[©üÎ}IzP¬oÿ>/&žê\å‚Ð¥2¿¼ŽášÌ»B&ñfž¶RN´.PDˆ„D))ïq£°è@ý6&,âÏA;…^„uã•LŒúM!Ù%j›O«Ã&7Ú]õ îõAeg3ÒÈ’ÍH4GjøÕ=IÄò)‰(ø=!íDiç#À H”‘þúÞm^5HUu8CnW„0CHIbŠÔ !¤R¹F©Î ±ÝÁ¶Žu\=—æAâ$g˜ÁäX€ Âw|wëÈÜñâßkqÛ¼)>h}‚tÐ/VäˆCi&Îhû$Ñ %\Ôù•Ñ–wáàßàõ$sM× ©IâÏG#mó¢ý")—ª\c•Ûk[`Jë‰D¶üQÉ&%´"Jy.ìcá𤠰‚nð #ç»ÑDž%7Ž×¡©ù]Þ°4r!B÷ŠâiDÌèx•ê¥ÁéB©¢½±ÜŽÔ*¹\ÀãÝ=©G¤4^y”%QòDMl}ß% I^"ËŠrrÃxØë»ëf?ÙÖ(fg…ô‰å :úí^«¡%UÊP{>9C*ð§qipò e¤a:j‹ä ½fþ vÁS,¾¹CêeqHb-EÈ•vi7¹]ÖÙ2Öé§bæºÒb9)BÖMVçb•ìˆø©ˆ†HD*€ÒC ;Ľ+ÔèMæËJ(]’’÷ c¹Àãl$2‘\oó‚_d“}@äý ½×KÚ‰;÷5{Ö.‘¬#?–çFÊ©šDõY[1”Úxci]ÎØºœ÷zKtcbJ„ ‹èžIë®YQ)-'7‚×]ÕÒ߬}òÓ ‘z§ÆÎqÖKcœ4䚟hƒ"ù|0­È ªD8¬Q,ÛÒn3Rà6 ÌÐæ·ùº„øVì‚B±7/§H@vHìÃìàïEè‘&ˆÙà}'ܽn‘ê-‹|ì-ÆRv9»· «  vuC=>BI$£ß$“JÁ¦±°JŠß4/Íx )çýò £È¯–û o+0Þ l%•L“ÀISRpBd'l¯ªVÃcàÒ<êZ´Õ’V~_‘Æ‚ôObâ[Aݘ\l± „P!21Ÿ5ìG‰5C0ËmÖJËãÉãu®CÚ¤Õ=lFq‚2Ò8d¤væ§²·å„Gçí ?…•~.ñæQCéžÔ!ùÉ­QtÚÒn‰J;Âp›Ë»ô©'øNÒ÷’D¾m‡tDZäz¹díÊ57Égûå"Íð)_YÖ$’%æÄ4Õ,cÅo<Ðm,õd;ÜáC’f§"˜¸Ôi*àhíâ’¢´jÊ/CsƒxÉMœß&Wªˆb; WÂÉD‚ZQ.0QQ&Ÿ'Ê„RgN­¢3Üh3t½aÂÒ­ÖXѲI¢ÝÄ ¼Q ïÁ—Ï7CÁ«Bí ååññ±äFñº ü½‹uíPŽë #­B$`…öFÃS…ÐMùH'¤Š £H…«3R·ÍH6Pi'6)ü6Ÿ펢b>šŠQ“ÄËB8È5I5ôœô‘´Èú(Yœ ïn9AšÑŠùy€êaˆD8¸á ä×ùü 8Œmh³¢©¨xnÒTÉ{9MIa•ÜØ>‚4¸0'r²bsf5„q‘[àÒÈ\öKb‹‡K#6D@MDâŽÌ’¨»Jº–$-ºC‰è y“e~Œ ™D¬JȽñD è#€“Ä—¤rÓ<¬2iÏØ ±š7Ë¥ñ±±Îä†ðº«‚²Š ²{´s̘#Á†lCé™LxÉb!µú‹q¬à—M¢*e(ØÉöHcóS½€gØ–b»bà»ÏùòAM×s4¶Bb‘b›ŽÂNßïP8î÷¶m”‘8G*ÄGy·ÔóÖu¾,,Ô‘]¬¡mŠzλÜàrŸ!Íân¿"Ê9o»œ²–)Nµ‰ci©ç{ÔŽÎ?ÙãéÐȤN‚|HKß/˜ÓF²‡’ö®F…"—‰àÇ—D+LÁ)0‰¡ @¤¸JO•µjÅÃjØ“—KN¡2DŠ|Q[®Ú8jÍHW©}Ù»ÒÎa {¾ä" 2RïààÂg#'æF@¹l|ĵÌG¾–C|!‚ Џn—’\D¥”i}$ÛÐ×E£XÅS=J.—#Úy¨a)&5àFË~÷· ]]f2å]îWe=KH{· ìÙ<áûÎ½î ®õ™ #”²Ÿß.WRv¸7!¸ßÀ‡Ëd>Ê™”Kb±‰¤é$ I”ת½eSí7a¢‚pE"/1”ø@Ì„Èõ¤ÖÄK´¡s"1U# É„ #ÙÒ¼ÌÄ-•ÜäžíI,M”(uöžÍ*¥eG«’Àë®r‹ôcX¢àŒ„!×#~ry«波Ý+B2 εøné§1·Ó®è¦{òlmͶ£œÄ»l_Þå$g{Tz.‹ªŽ÷b;zt>-#‘¦í|d#©­ùÀ´$¸|TI™Uáº\÷¢[†r’ÈbÉE;æ$±O)Ä SìšB¼Iì{-I5ç’rO=W$;ãÓ‘iPʇ„x¹_¯” 6Æ¥¶¼¢å%zP©\ŽÅ¶DÀàŒ|”hœfô¾ÉBú›k4IíS›LI®Œ™¶ „l¸Ç…r«…|WÉšåå±mcƒƒƒÉâuÂ÷Ò9_ºiS„FÏÏÎ"Üj»@j°qÈG¤‰bí+à TÖuã6R7–v4]’)X!E Å$©Úw”ÂÉ«4Hì»°o"q‹„äoì‘R iÐGÚ\­bù”ƒrj‘êxg2n‰TpyÖ(Öhà¹,8.ã^lSØ—g,¤ˆß¨x’ IH±gžä¹`(A^Ýq$RS’h]má¦Ê–+b›[vò¢…¢9°bpâŽia(HMº$( y&sx’Äh«>Erð›ßNŠÞøÅµn £•õó¢ìêºÎÁÎÁä—Æë®  áF¿Qúàï^£@A†9%Ô>ç¥ìÚU>RòÅ+À hŒÚ)žl4u€¿ÇÆ''©G¡˜¡u> Ù Rv´$8•茤‚ˆŠ:&2°$>fb÷ ÓAç’½oN±ÃTaºª×ùn¦^É.“»±9Y‡É5$¿Ë§å¦É®QV’:ôJv&6S‰’™tÖ\žTÒ·< žÉ†\«µŠò‹G£vóB$LÍs£ ™Œ´ÊTh¹_Ô•ðŠ9ÊÕuã¶?Ô¥Ý/…×ù,g¤/¹ÒÀ†ƒƒ£ ®´ ¼¶¿D˜gHí~©Ð;0®(|¡Á’ù4@u¼F±<>ºÍy_"l‡#Y¯QìõNP{Ëyó…„DÆ|I#8еÉÈ}p‡„*«Ð#¡ÏXÍfFP*p©/ˆBBÍd,`ÇqÄæåTØåB껞ó@Éïgˆ$ÄBTˆ1R]`Þõ\r<+(¨}c>ª‡„”±^ƒ›ÄRJBkš# j©š"dËkY2ŸÌÇS%ÂERÅ©²ŸÈXƒ2оsEYðô6cÔÒ›W÷Rºo„¼Xó”2Ç™R(NòK÷I"™x&«ã_¸Æ°]e´kâ•R¨âXB ’k"E>ãÝ^l9BƒëŽlag¯Éàu5Ü ‰D„Ü: d—j7s$Ïøž›ðWNH˜Âþ^{`4TbÁoD¸¨³éÈÝ·¥ÝÄIJ}Sx×iŽP¯ÄviBêõ)b‰48¥oÀ¾Ôäókpû±4G²'ñ nÈŠPRâ ¬ïMÀwÝ+ç¼ýšKÍ ü™\ˆ“?H*Ò4d ¹=Ñ$šÝÚÔ[ÆfêÀ6I,õyÓe!$]Oô‚uh”Œ¶õP4½QüñÙCjôž5òS‘Ê©YoÚ¶¬SH´N[aJ_¼‚›ù«eÀ©Mf•Å b±AZÅð÷Õ_>ýØöGßÄt³ÓÐÿ d—:¦GAŽ+0¾Hj Ün0á®BÛåís±&W Õ1'KlÈBFêéð ‰ñ†ˆ4Ò7Ò'óî½ä—'zúY,…R§ÓýÞÆB«HZõÍQ!´ò•³KÎ[|a•OãàKä¬Â„Uムå Æ¾›AŠºµ€8»Xr_öbv9wHŠe—Q &ÔNü”U"Ò&¬Îï¨+û ÂcÙÈ~â•L¿H ‹ÇMJíLj€Úê©wÓ,K©u¢CˆD¾P¾–ŒÓ]I§8‚tµ–v7‚×í"¦ÈCÒ:Ò è‘lF ’ÅÒØe‚c‰Ãh¢4íxšÔ"öí©u*¨Šº-í\Fr=RoLjÜíëë—=ຌNH!”‚y¹”Vu@/"¬¡Z¤E,íšb¦;S~HR§ØÃ u¿›SÒáQ~H9ƒwBS4°òMûh["È4°J±PôÁ„Tdr‚” WÚÜüö„QÇB„$‘ ›D¯'„‰K¬åôy…Á‘ßJÀ½R¢(zlšÈà4‘òï&¨¢zB»)…$+ wïÜ¡¹¶ˆS%ø²¨ðmóÑ'!˜’Áë0cˆ ëö8Ð.d¤­³sÁƒB˜¸¸û6|&&fÝÇììÅ3öïI´·„ôB…ÏH.a:ª£ÒêìòÅQÈHK‘Ž®‘Ž Ûå‘‘Èšo “Ñãu̱£ÊƱ Ú9 ýšÏH3Hú&ñü<¬P°dàÚ1 .Ô²`‹”,$%*ýP´RÒZµ‚´¤ƒÖ"ÿ›â(ós¤\è’° ‡©aÍã1pÉ2Ë[–K£¢Mm9ðâ©VÀœÖر\x„P„Ñ5œpoå'L´«e.hÛrõVoÅFò¡Ì z˜š#«7ÒÅsà£EÅv.ŽÆV­‚&é6c޲„Q`ÚqFêêë8Ø;8v7dç„ý2‹Ûð¹¸pþü‚ýšzkj¾ëÀ EP±+`ˆ$¿*ltÆþ=S“®Dƒ•¤ÖËÑž>´B‚Øe)¶$Üb;¯ƒîÈO‘جB64i•ô‰Sƽ#W±Œ8ªŒ³Î·ï`‘¯Nº¼¢„©Ë`ãDø7¨zr¶L~‚„é;)ö2¥Up;VüÉ•·ª€©Cm£í[ý$FlÛäCm½&èIf¬ŸX%JBnåð´Nô²ž‰¬0¥ôèÛ§@ß´µÔç73L¨mIk/¥ €ïA—V &¿|íúžÃúvù(«Ÿq-ÒÆ}}K‡ µ„Üïk´OÌ^ªÏØÒnÖ14@FˆàGã8âö¨O«{ŠÝvÀTÀ70¿'çIùdl‘]]Ìl("JÌҀäF(Ì:?fÊy„Ä\;?AÊØ*3f60ØP°w8 d¹¶cqÕŒ÷Ëó Sœó2’ß2w¿Šz ÷Fôì  Çu•ÑFBF˜iÆöTïñ+¸y-…À¤“b«‚›à7U…R«¿×ÔUU¶¥ëo’Øo6‘i“¸êMx•o ›#›VuJÔî—KFÔcu®#AF¢9Òl™}Z(A^raôÂ¥7ß|ýûöòï|ç¯÷[ÿæï{ËF’—„«{…ÒUerP¢ ˜ cnŽ4¢p;½Ë×sc¨çh@¾—3Tƒl$ ˜ÁË5¸%ŠEÇl¨²=R!âýÆê^ ²žËõX‘¡XŸçG\ý‘~‚(ö°öÊüŠ,à k™ÒÜb©EÊp=6 v`¼ O€ïL¨ób¬ô&ŠYžFtQíæóSXÛ\‹‰¤ÔÏ—ëva/—*x:È›²(ÐÎã.ìŒøžúO„")iˆÒšyŠÞƒ²Z ¤Nà­‚9’-í¾ÃÕ_äzµE6|ÜÕup¡)Ò–'6rdK»ñ/Rĵ‹[ÕëÒ›ßùWÿù쇟û‡¿xmÿKW>Õÿ»ûÞº8oL…œ…Œ=䤹z`ÃØèäp/Ào¨[Ü…‘kœ’T±‹vn™²Ñ€OGXÖõ’ȪMG‹\Ú5 ‚¾ëb ;##';G¦3‡J¼°ëÆH³ÃÖŒÌ/]Ô$;>d¹8Z+H ¨Oœ±ƒ9*÷{á‡ÄÞËÞÆ\c`R]UªÌ'ŠH*öFMë¦^Ì6åš&nK†¬‰7Â=˜åIØbUªüòW(g­ýžØ[žÿ`ò8í³ Ø7ª˜\„IÉ t½þÁßÿEßPØÝì $ôO¸Ò®wjê<õHíDhÀânâÌù·Þüþ^;÷Òô©S§®Û±ÿÔÐééSßþ?.½:(íž[>b©‡ËH ®´ëèXâÚEÀ{˜_G®G¯7=ê`«XÒ: $;b~OÂv¬£ÚyþTÕt3ÞžOÚ s^£ð†±Ñryݨ)R2Rî%"½í1Â2vHEÐi Ì; f±RË1ËÅÉÄk{I<~Œü!d—b”þ½\ºS,¸Èé’â,J~PS@_bÔ3Ï é³œÄ&eÑ>””†•Ž:Üì¢Dsfœ»®s‹a—;îrDÕ]”\a÷6„6º@r\;ÎH~¹¼áòÑ™ÁK¯üíï›>5}úôôéé¡Ó§Ýç¡þ?{qpö:ƒ£ILjp°70„fêÅDc2Òd$"7º@Q¤sžK:áú‘,ì&ñ ì{~ÑcYÖ® ºv…ꨴÜï¼.˜9ÁnYlVxI;1Hò˜dò…î—)[ÄŒ4d4<â8¢þˆÈA¹< ž±&Ï#‰FO¡t:É»Vá &ªR?>MíëåÚÓ¨ôâU¿L®uï¯çIˆ$Ò0F(„ç%w$páÝkä‹”eR›…‚8k–ìY " « ÀK 6îÂü²ëgÝâ=?1í„Ö­[ü ÌH®GZ`!âz·»ºnð­7ÿiÇK6Œð8== wúÿé©©Ù¹h [Ä}KžðÙ£ãØ`{¤Žd€€´ _…šª”g½Q‚zWŽ¢I0F‚8Z„½¾Z¥2W°‚Ý ¯ôå±Ðw.€0dYdéÎÆH a™´n >DÑæ]>©WvùV×’á$ÍU”®C°­ñ´‚祿¥„CàÝK*ˆRçªOºL„R§ÍH.»ìú‡ÿ!›„ìánöÀ‡›!!cuã‰C}®Gc7Š o*æú£×ÿiõK¶˜º2móæ¥ÓC«ÿê>ÈHVfÝœh‘0ˆ ž!Ù”äö‘–·ŽŽvNÚ àâƒI@r©µ£-§GÄjÏS$1ØÐ,êY«@C Ùe²#–áS›MH§b‡‘r/å@®7}_X?*Ð)ëº"LasÞ@ʃPqH FH–´2sVü¬I×­ôc4To©©”w[ÖüϘ5Šba¢!£aVšˆ Ìhë"e]“Ð…¾K¢¼ù¢9n8èyn’ÓhèD’Âv®Gº #ÈGÉJ—=»à ÁW Ç Úó!ôG°°;ÑÖ××a3Ò8P„Ú^à¤Ñ>qþ­WþêøéS6túw¼÷{ú] ]±×¡ãÿÛSQi¤"¤§nLHXîÕçf ǵƒEX‘í ¼/Gõðu@É›‰£¨£%Šæ1Šˆe‡Ø7¯#á>’@¼ë3a—¯.»¤€,x˜ ¼Ìk£ˆwNYˆ*BíR4œ `â‚þD©NFGlÏ/–‡„ÄÃRæ.˜6›šÔˆöG¢ÛÆÄÚ?ehåâ鹇ÄùÕÄ@¢¹ÀžD ËÊÝ\U›ºH¢~Pþ¡GŒf°‰1bã:¤N€Va„7‰+ÏlDìrñ±+ú¸y^wÑ÷)ùË:8¶lY·¡—‘܆ìùñ/ñä«^œºï;‡_:uzè£;~òÿûßýÅ?¬v)i裧§wüíSçg[«ºPÜj. ”U8Ü@2’‹BâF¢DÄÀÂ’Z‚íõr[º¢›÷Aadû#ÔrÇø2÷HùÍxšãvʾ%÷¬†LTta(›;=.¦6vï\~)ÐNm– ï<ÁÒ[Èõ.¢Hò]˜&Q¾‰a‘T·RSMmÎå—Œ& Ñ3þtW[=ê×F–ñF]XãÓ•WK©'´~$e[pýŒ/ŽJT1¦ekNiŒŸâÂÝ¢´LKHØ#¹ÏÁ Éž¼@AUçoˆ£C`j¾}jJ»vö蛳…Ý¥×÷î·õÜ•ÿáß¿ñÊ+ßø»è· ÉÖyW|©´ºBÚ ^€«ÀB¯^8ð{®hL”ÏŒ‚°Šßw 7¹\‘X’‰È+÷¶Vt.„QÄÈ7$$WÙaiל+x{"'qÕ99"²ªÐ “%#üúÈéÒS…rZ  , ›}(ÍP„®( a EùÎ3ڜȃ[,'&#mÅò\¯åõx- d„¼£Ñ‚$X¹†w{yç’Uc¤©QD3‘‰r¢¸¥&„±T–LÔŒIž„4JXŸ2zµ#Rdžt$þÜ$7- þý˜ùvñ´Šào߯‘ƒã:[Í9€/°ÃŒ¥Ý«[/NHÅïÆÄÂ[¯ü‡¿_¢ZCé’w› 5àV,0¿ñ†Iɺë]Þö÷¶@̸"‡#È^¾´¸ª.Ž6Ú„t¨­ïhGf$þÆ„4xé;ï½4tz¨ÿÞ?~ê­…Ù3S÷ýûÇïv)éô¦ç¾iaB󼋖N©ÎˆÝâß…‹¥º1ÛÀU"Ÿ–ôeÀ{Kl "g¶ÜË©hž#Pûž'²*tHã`TFY;ÖƒÌ[D¿ý06󨙔<1~F›“ØIÝЪ9`mí–¾J½F~X=*¼dPPÞÊS¢3 M5÷ä=*ìüX^Pär]TI]ÆÈ#/Š-­>â¹6a™G®dKŸU£[z©„…!†àiž2/óZ)F¢mŠì ìÂŒž{ij«xû0I«"Q³\õä ±U´Ôg¿K¶\ç²NÌgø‹/ar´å œLñ #›ŽÚ ´Cø{By#-¼õæÎÙ„´éÀ?¾òÖ™‰ÆÄù·¾óoöÃéî¯o)Æ\¼8liA°hÎ@^(BNj´œ‰DG'WÉuxÑÔ¨ž›w‘P*çÜꑟŽ^çF±Uwu`Cû¤^ƒÐÇÏ=¢PË}ü]ãm\¼WÆùÁ=ŸZm¶´\¥‹35k6ÙõX…" Ý,§êнķß[—ý‹eµäJz´EÁ*4àˆÁhï™,Œ”Æ6aÉU Y{©¬"ÆJ-ÒxRáUm#*ð1¢–Ë"ÍèAtœ=MlôÔ½ü†yV)mEvöHÄ´ëìÄ@ú’»~‰ãäK"ãlÙò†‹6öxÒΆ[ž„ò—X×uh;äÉe¤­lÆ $¤ÃW†® {ܦÛM\|ëõ{ >=tå£{_ß~±±‚gy¡ÄNºíQ‡ÎȦ#¸cK»‰òVÌH€àpu ƒˆ‹¢ºòФGçæ1ˆ¶¹(ÂdDa´¸H¤ŒcØÐ$®]]9™GºùawUëò yb‚‰Û²!T]xuôÝá^8yòE{9yr w~±ZªUjXK¾Aê[ˆ{³ Rš)´Îó‰\ð½Õèµà”ëwkŸ˜Ü´HöDKIbOBK‹¨…õ˜L”(÷–ˆfê—Ê !ljæ-ƒ+³‰eÁƒÌ¾=Ÿ#Ib B)Êœ5¡EÂñÑ ƒvƒƒcc‰Í-+]mºÁËFüØøS¸µa´ƒK:JFI]m}=6# ¾zqvb"ˆ¨Ú°yåo\BZýw6!¹¥Ø‹Û_ÿÄ¿ƒQÒg?ñä[bòZPîqéˆÂ©î³„М+ìêÎÂéOŒÚ TKz4׋Û½­‰hòªãæ'ÅÐ9WÍA>‚D´ ‰ª‹Æ«~‹Âqí¨f«çbf$ëêyh‘][¡€AÒš)µòò«SÃ/¼øâ¾}×®ÝË-_{à¯=z˵kûzNN.ÚPj†*”RPÊ2ù¾ªË´ÔIÆË|™÷žPRÛBýWªU)»‡˜(#œY¢]Í™ Å‘¶OÎQ ÷x!s,yj ø;WÔØ<*ì4MBhóI>Éç¥îWd\(jK2rγ`vØ7h$¤j²aãÊÇŠÿJ^NlpyÈ…P#[ÙuAi×;8:î"ib¢Ý]²ûþs/MŸž¾røoŸœu|¡…·^ßûQ 6{ìIˆ-oë•òÏNÂsa¹¢1 ¨f¤Ü‚à!kë •2‘‡ç¸šÛÈ‚½NúzÎ¥#Œ"×-Big‹-`6ØÓÙ;"é Y­¢ÂÂÔ=›uÆ9‚¼;ü½øüæk÷í¡‡ïÝ{öðÕ—û/÷¯Þñ'ßÚ}ëýûz†˵"P‚éÝÔ Œ"… ƒ¼·ÈG™èŒ2FjÕàŠ õ´w¬ô­³Z#UV™ì*ų14iñ—^e"p!ê¹8…¿=—ò’&Nf¹‘6ÊP9×þ`Þ³F½Ê4¤4!#K2(¦ u8Œ/'.ž<߆‹úª oÜÁãJº.ºü=5x~ë·;‹Ç™©?üÇã§l?ôÙÇ¿qé<<4zéK{_bCÿžÜ¾€+³û©ìÐݱ—†»º£B‡»±·F>Ü‚,ôH“+Ú4`õ,&ý°íK8Ñ-2(\ /Û|Dú®¶«6#Úk¦˜±²›ñN˜ÅJþ—Ú2É}jVªï¾ðâ¾k÷?ð_ßù'ÇûÏûѦMÓÓ§àØô£c—?rË¡›”‹¡[u,^ ï,d#Ñ&‘Š]î|ô„Fx¯F¢¤‰äˆÚÈ+/Ф¬¢8MtRJ6¹sÊ&'‡)´ñMàÑæEíÁR©Tiærþ¥‚C@%-ÄY?•Môânk1KbH!ž‚™ÛŒí$šÌ’°I[®$]×¹´­ô`Ðӎ̇üJ÷’-±¦GÏÏ.ñÌ—ggíÉ>xéõØo¢éþ¿ãÒ«gìcglÓ´óŠã6 õÿý“ÛÏÏΖ˳ꈾž(—'Âײà´S29Ù‰ôW´MNúÖÇ_ÆüçÅ1îƒEàà'wØø Hƒ­9_Òî¢è.Ò"b;Ön¸™IÝÕÙLJ‹pñ6ÍEmaøÅÍ<²÷½Õýû_ÚtêÔ)Çãž&îÔôôЕþw^ë™,U Ùy”.cUb)‰@o‘ƒ¿è#i6rÉ<6s¤î$b¸²D±Ø¡UõTÄ—à],8DŠû¹”ÉÊ›µRuñ#¥Z3ͽëxž6K‹½|лX²'JM2H—Èr˜ÄJ?'-q$!î$ÞW×:0ôo”ÏŽ°ºUt/ éìˆÛpø+GQ˜ŒÁŠËÈÒQÔÔ^²q4<555:x~ü" ÃøÇg_rÙçø?=¹}ðâÅ­gƦžú㛀ÛpùoÞØ>xfùâÖe{lݺüÅeø˜]†Ã]Ýï•Ýmˆ.ûó 6#Úªlr~:·m‹  {Œ«„×e—w¢À¡KÉ^KöZ.•k0Hâ=Õ–‹§¸£›`ÂÅÜR[öÔ˜ºéw_>÷#ˆ!Çà=Mt^ &ûÕ©MýŸ8Ò3o#Éç!áØ’zSÚx¡<0Ts¥Ðк;!2‹4tÉ#¦‚j´¶} ùÀ¬´Tž' ÁÓg1Ï”r4À[üàBÏ…ùR3óaÚ¬ö~ú¶õë7º·º6 ðC®hEÑb’b %Ê×èiXÀ2¥™ÌÃ$ÙM‘:ÇV 2AhÒíÆ–ki²´äö ü-|‚»ú †\0ä$¹>X<û¹w¸×Öv£ƒcçÇìõüØøèÔö7þj‡;96¾úÊöA{î¾õ‡üC¤éË_ycûÔÂVŠº­[ÇáØZ…È·7ö$·÷–݇c`/Ÿá¯l]g/c6”¶¹`âLc£ÅÖc+Å d1x´F ÇŽ=ÊËpØøqWw±qT®4œFd³BV+^i®( _)Ûé…»¼G„eZeüƒ_û¦OáRÉi ÃO Mor·.U#¥·絞EûîŒ1„:¯Cœyƒˆ!ò‡Á ¾ÜhøWo¨]À$¹Ñ9I)ì˜D#ÇbQH-û©Œ¡äS4¡~HÌ¥ùžkü¯¿ýñOÏ—ÖúS>-õþùû«?vîòû7ÝSNÕzl$Ÿ—(ÇXE_>MÁ»%ĶÜ[V‚óäìùJ®E"mÕU¼d;¤J–lß~údw¥OþúÂÁƒÃöÎp‡½÷‡ön‡§Ô ±×)÷)¼ ¾k£ÉƒŸúÆúê~îª šÁÁÑÑÁí¯|ï,–v;¾òÆ¥©±Q{ŒŽ½jcÜÆšýôêØÂØøyû%„˸½;nÎÝ[pÁfÃhaÜþÄ(~÷:û“UÕÃ…?—)lJ26;âs­R®MØêÎÅ’½ƒO4Ùs¥)LõÒT¼²¨¸šW{õäúcÓœƒàßâ·Vïxí8ûÞÕç® !ãFØ×:ª•Ô³2ÏZðŽ"É;WÜ:®Ì$ÅFú䩽Ó`$+9Ö35âK£±;`_‚äùÑÏdµg>ýû—¿ý©cûÝ ‹*ì’´<Óš~÷¦Óÿ¬}[ÉŸð™J’´+ñ;6Ìk0r™Ühº’·dËš%¿i û6!UËEžL}sŽ©ƒSx{p*|=5å¯ts½ËàT'ݳád?Â1¼ôʿݻ߽ëÞ½óß¾²45õîàÔÔÑ'¯¾g3Ò•ÓC;úÌȰ‹8wÅ‹¿—±pØäñ4æbã‡cÈf.(]ªÚºü3.åeˆ›RyVÌŠ—æ ×Ù¢û`­"/Mú€Û9'Ð]ñº¨œ´|² i©¨ŸÜÕoSЮ” }ôôéýýÑÝþñßþÐî÷úO»´‘ô•}ó%l„< HŽ\Ãþ+’õrÉcðZ?Ú©+ø¯$J¬ÑD bk[ÊϹK!ßÇMÒºJŸA;˜Ÿ_ñÒÒÀµÕ.7Ÿúç'ïyvgó¢záþÕ°¾¶éÀmæF\ Dˆ9é FˆÜjDSײ7¢5\żٵHÈ"á ÈG²+Ul¹iC`…Ã]ñÓTøL÷¶MNNAº[wgÌ‚ý6p¾éBÉ^Ž3Ü»ôÔ¿ÖU*Ó¿õø®WŽ»(;h;¼ÉmÉNøÊOtàÀ”½ºË$“ƒóƒöÆæ¶w]p¹Î~Þáµ¢ÌÖÅñ3Ëþ(Yž-A”ƒÊeàÇu/”m*%:TèbÃÈþ”ûAKx©ð¡ÔŒ",˜ ½a®kã/lþçs—w~mõg§1fÎí~èí®žžž}oß¾{Ç÷6såôé+‡œ´)I8)³iXæ•èVsþ0*%ÚWRI_Í΃Q¤i¡˜–•ØHD¼¥I‘rvF¨^ù½÷es±ç1HÓC«oû œÒkh.Þd…µêþ[{ªMÉéº$bÚjòHjB ÏLkë­€2x¹IACÊS7E"šÂuî‹mã¥ÂþgPSù7ý±ó£ÜÝœÇ;xÁŸr׸{j¯1¸ïïÚ4á öI'‘ª³Ý¶OÛGÚþç;w@'ÝÿØ÷Þ8jëă]~å0´×›Þûʺ¾%(mÐÙË”»º`›ìµÏ4©.StÓ9é‚l²sÛ¨­Ç/.;DÃl IDATc%DÌl ¿á ¾J¹aÊle¢6H:^•ŸqiÒc¤æ‹½YxNJZUZôß5}\Áý¢©”›•åù=OmúàÀm€VÙ6òî½ï<Ó;êaj¥PLXI”1a’˜ ñ`x+)H•‹þÏ‹6óßPÔp9vÕ /Æ2Ô`Ÿò cËŒ4»ËúüE}œQ?´Âeù“çm$<¸㈧·}øûŸsJ'Ó«þê†6Ô%Ù°Ëf©iûž{å¹g?<ÔIÄ*‘ZiÅ^<8ª&'G·ÙŒtf¶<áe"¥Aá㾦£A2ýEÑp«Lî(P⇺̭nW WÞÙ8L.eÅK:¢\ÖªQõBÊÞ4E¢r†°•òòâ¶mï¾ðüún7Ëf¤s.CÌ–&ïûøãû¸2Ô{ÏbÓoYྼSfFi™È’ÉD­/+¼×(3ÖD’±M"VEc›p%œo|°‰‰R8u}UãÝQ÷AÁ”–FŽ€ùìÞk÷Ô¨ðËJ·¸¾ý':mi¾"àC+o)·§ÈBâ:{DÊK”ô«Ñ÷ìž]8µêéCÅ­·@ëâKzÁ"ÊFÒ˜ÍH6Ž ¿|Q‡èºÑz™ñäªuûQÔgêiá>26º´§wÃ¥$Û1ÚÇEa…A¥Ãª¥ÂZ£É†[©Vxòs6ù8XóÜÛ'KŽ[g#iøÐçŽÃžÉôéc½3ZËr„ï£ðQAdZù ôÕKªÒï!—2(IÒ*S,¥¸c\ÜHGc¤.‚t™ô’ŒyD6¥R,­Ž| BfúØOöÙ€ÁKKY=tÅuÔCûïµ¥]¦\WL®¨¨­H¼(Is-(d4ú"P"Á"|,%…UVjp(xçø²­»íw)Ú1nnDÝ—vþ ¡ÇÛ‘>‡ÿAÃ]í'ÛMô¸‰Ù­c£¶G9v­qH÷é+ÓÖÜñÆ àGœØðÄÃÇaRòÙHhŸ@O«R{ZcÊIi-q(MM:·•Yˆ#©;Éz럲9{Ô³pÅOu6:ò,ºHŠ8«§sØ$ñ€VÌkA/ûU ÉÉÆ F¾ækrrj–&ÝÞ?äÒi›‘zK7O›•Å“îüè4 W¾µy˜)á$ƈ:€Œ¦n'‰f‰u=˜x÷H´ñR…'[n+­ÁÉÕ¥$É¥,ŠBÃr ø&fmµçö~j;·æ¾gšôÜiùƒÛLã°íÛwö@$ÝüÕ¤™æbçÛ\¨¯Æù קd-k”ÕJc£c”:W­ú&ÒìŠÌUÒsÂdœÔQÒgbÎk;â6£lD^¯ðu…ò—4~GÇÑ>&X÷Äš§lЦ÷ÖìZw¶þæj˜ìß»þæÚa¯œ*ÁdÌ“… (oÞ}ïä¶Ñ1GÝi-ÜKË1Ó=C:ØUº‡\LA\W®{Fš‡‘¬I–bu”5•;‡Ø•4ã‚È!ê¥e ¢RùA{ 7ö¨øB¯ik¼š  öK®Š»Ú¡¡éþ;M–pÊÔ, o|¶ñí[ñáûmãíl“¯8ZŽÁ_îøm9Þ„v¼QÖ%Êå! ئ%¿îœ6 4^ÒDK¨ä&Zã󯲹øü¸‘£-gºi¼IQ–Õæ7ÆIåÜÁaÒùBr×hÖ“1yäâ$y F.ÙkîXÑ‚=sä­â!Ò¶­jp‰M;$*Áæ&ÚÉhä#üá‰vüV,ùÚÙ!Öf$Û$õBFêksqÔfcæa×)^úèÙ÷w­£÷|y÷j÷.û­w†k©–ËM¢ÄWƒÎq %+4câ4¤4-…Ó­‰”Ïí ©P´ t!¿‰˜R™’‰9u´ ›=Š"þ»”{cX¼Ç §^7.3R[[ס{ÖïîUÕ»Ÿs 8ã?\¿û2Œó/ßk©Mb£ÔjÞTèùÜD äH[]‹4ç¨>S÷uÝ _é+Š%ø l{f0áÔëi÷Œcrsâ„”ºKö“r}M¹†aT…OUŽ)ÊOåÒr JÜ&…´D ^³‚7€å•æ»lF³ÿlFBÃò´2ÞóµÃÓø6¼úžj@]wF-_+`;ŒJD,Œ½CÇß‚†›$0"ÛWáÌ ÙwFï­æÂKLÏ¡´ÿ…˜ÑVæÝ»ß Óགྷ~À6I›_:=´iõ£'«ÍX97ñb†’ÿØ^ä¸i”©™Q¶,+a¼hCb€üíYv“·-‚ˆ‰ïƒí”Â}Á_OˆC5b/—vK=.AîÙpóú{/CÙûÙk¾º6ÒOl¼yýO.»1ÉÐåŸp 8AŸâXB—£>ÊIKÔ#¹Òn|J;-%$\ûË8!ÙÊÎÆOj%¤X²¹Gm9Z©mlrºÔy.?Á¹|ÔÍ]“}¢Js¢Æ©´ÌL½jID×wT㵑ñ²‡ ŒÂ+ÍCäÞoûïÜ7Uf®êÀýÏ]Añ¿þÛÝ2PY|5týC­¯Š¹¶ËºŠTá$ ©Šh÷ñ\kI&yA#mÎE7'´ï±äW»góã?rÀ˦×\5K‰Í¤6%=züئc«ÿùg°µŽèÚMLXB±nh”X¸@õ‰‚üŒÚLr›ú$! ixBcc¥&ÊF-‡úŽ¿þ+ 7ig‰o[Ú}Ò•vÜ#è:±a׳»íØ+Óû¿õ¬ËH°ßtó³?¹ åÌå__¿gC[´«AÕP>¸ú3’mõl( %¹@ QÝÕ{PÁ¥6j0AjrQTï¶·Y·s ›qÁ’z â:~=d¤O] Qi1d¨JÕyŽ€lWLJµRÍ6K8$^.s,ìÐÈay² z$ÇzèÐ|‰–~c¯=©œfYÿ^\,äȨµœË[g3„ikÞÈÑ8WÍÐ ‚@‰’Ó7ÁÆX탋Ť<Ö71‰4¦Hâ¤`ÿeÏÔRïmÏslÓsG†ÌüØ*­-öÜöÛßúúý=÷”šY"U¿}VÒâFy$ápêUÄÒå‘a•u~.cȲû&òƒ¶— ÜXç\ÓZá]/ªæ°Ÿ"ñGŽ$TÊ/ŸƒŒdÛ4t8±eךûlø­Ï¿¼k®n¹ùÙ{¡/Z½{ý‡Î{Ö-ªŸ[PNQ~¬Äâ@“óPÚÕõ®c‡Q䟀ùâ.ƒ”âʦ ¸_5 ØÎ³Y¨î­-3ï]îñoˆNGt­z8Ü%O€… ê;n•lFjâ,í&÷Re߇ûêz·ŒªÄY³4¼ùÞcîQ÷xÏ«MÕØ–bN3ê¤Üu ! ÒÝÁH_Š$ö)Dwi¯©>©^|â ½å–>8p( CwïÝÜ[X_³¼8|áÓÝr…7¡á1°£„*äørmÁ,ÕX[µ'º˜D½Á ¬NuÚXrKæãµ©Žbj®å'H…Ø×täÇ7À†€¿µ:á@»ç>Š ¡{] m]nŒ–§_É\%€î„''JKÍ öB·€åî?ÝüLM‘Øœô`u±Z­”¦Ø¦%ñ¯Ee$A\Ð -±C³EäFEä¶IÐxA ²«V­œ´a 3÷Hq¢xŠ?|,µOød„±„ð¹+íÆG‡·wPF²Eܺ'Þ?{7d¤Ë÷®ÙµÄö7®³äЙ+Ó;~óË{H¥•÷׈ŠÞÐ UÞÑ>„@òJ»ñ3å §ØU ¸½3žI<Ͱ²ƒVÈ-øØ(³:üÛtiløRž1aÙ4•À\-—JË> á1.*ǵ]ƒçIlí=82âÀ'6~¸þá÷`;tù'/ïúÐiªœØðá/þœ;Yÿá’iūׂ Xê㦞PÛuj·\šeûpïÌK”Žê¾1Ê z̡߮+ªÓø¨Û…“½- Õqª=šàù¹lÁ©Lx¯Õb‘GY©D‘´ìfJe\®Å>©VV¤ñÒå¡+‘n¿o¾ ß6#Õl íǵóÕœ¬¦?¬Ó_ËF O´»£Ïz—TÒŒ ì†$R‚óv‚’`„‰´RÒÄЄ,9bC˜W†Î­y~±¢œg´ô D­6éZ÷+ŒÄL´'!=ÄLÄ2²œK|ùLO˜ËÕ12rüæªI`Ú•›øztÔr¥šÏ5Gs¡Aš#ib_Ú³ÁuH'6ìùò#¸01tÜj|íùêšÏ;‡Ó›^{ä‰=VPVqe^[G“ Ë•G°á"0„ê~j©©î£oŒ,—†fˆðãj¹™n¸E4<ƒüöHu?šu ^n&m¸’¬TBÔÛÆÒxÕÝî©„R™È¼^[ó$÷ú}&ôn9W†þ¯(-oëteÝä*HI¶Gr¥û™Ÿ‡/¬„6´#H‡æ–>5|i×»d3tH6ÖïzÇ•¡ã¿n dñ¶ØÆiçg]½w嵇¿lIª¹´‘äfPHm²Àä.d¤­6#5(!ЀÄDìê0#B‡Àº°qaT/˜ÂPϨ+bÔNrBF²ñB¥]ªÊ5u<„â®TC ¼“YWàÕhI"i¹·ës¸@<´ÚR Ëm õnþÄ1è¦ß»æV !‰²P}61+;¦Å…ŽFX Ì8âxý|aËeòœSb¢¨Ðsr\‰/ªH&‚^lsñù;ƒšv€ÿZ£:¹Ðº™`£ 2EY2R6ÚÞ Ëéú+m¿0|cLÝi6ü ©ó›n ËH4Gú™CKe7àn¢¡],ƒ cSS.#¹às6€U7´c÷˶Grjá[ö<ñþNW¶\¹òÞÃÐ#mô±tˆn1’׆Á„I‰L–Ý0i(BãËgDFrÍvGò…0t rÀ:ìÕ1+àOíQ= ¦ÊH J=õ®¿k3Ò\Ó dK×±ö†S¯4PBÀ6qmUÓÙjåŠ.îš%H.^Nc 5ÉM¬äàoHTwkó=ÀµKbòuT…]’D†*‰ñKm²é‘•—‘¤íÄ$I䀉ïÕA¾ØïÈ%&¼s+!Œ“„Ý 95ÚMÏ8bÃn$6ìøÚI—ƒ%ºH|½ö˜Iø…åÑ•pñô ’¹,s©ѣ䭴bÜŠ¬“‡´1CÙ)Û#á2’Ñs¤Ÿõá³ä#/`(½e…H«£½½¶GrµÝ»w "ÒÐmÝóå÷è™§¯œ}ÿ‰AmRf¥.ÍÙ<“.AuµaNb´á`ïäü˜ƒ¿]F‚z€Àòp´G®#þæ$Т<ÑÕg]5ÅÛ–ºËHÌH¥5ŒW«LöBŠûUFP9ETweBÀk‚ÃZÁÒî¡~nX}û}‹eRUmV;îÿ¡íœ6ÚÿØ;ïVò¸R5ú^’HVœ_'ê܉¸o|ož$JìGHÿšÈ”zËú¿ÆH‰ØáË3tfÎ"1ˆ"ûse¹|ÍÉÌOÓµ ‡ÎWÚÓÜt)™Ää ˜L¥~ˆµQעңŸDŽžði?v~óãÇÜ¿¤"IÂÂËF²Æ©7ƒ?_\XYDu/”[Ê…ò+J¶¢þ¤HÕÒxÙ„•)%jžçȲaäh«ŽÛ0¶\Ë|´Þ°2ÖÐU2NÂ]û‘ÅÉœÏe¤ÁÞ^˜#9à`ã†]/ÿ:ð¼í»Ìî_³¥óYwó—>{·ëœ>ûÃ5O|èñ 6¬Ûs³=>ܰÁ ¹¶¹m¹b¥ºäœÃæ€ ó£ã°ü¾pf¶Ñ@V]ј=3>::zq¹3Y-UfÏTÆÃÂÂl Ì+»SÈPPâuÏ*×h”ÎŒ/¼:¾p¦ÔÀpãöh¦h”« ïN ON½»ˆÊ‘ˆ3¸d´m²c¤Ï¾mØ?£«o¤w› %AËLBI<\Q ´ ©âðÒ=].ܾÄñžßV#ï–Úb×»Z§ÓŽØ·g*p>TJ%g\ÁZŠáòÔ©,V«‹Õå+kéü†Xh6 ½HsϸƒÇ³tmÓ…]ÎùÅžšî'›ø“î,.àñw¥MûG•¬¤)FU“¾·–Ÿž’ÅÿDvjxîÛo/Ó·Ió1«õÞö­+n*²é÷Ž8ÅJ’øÊ+þåäÊ‘…þØ„?‚áþ úÏPjòAxY•fx‡‰Ùa™*O4‡ªÉ!WÛ¹ŒJ\°~!ŒGö†`â$„ÅÝ„w$¯L”/nµ=Òˆ $#ízÈ@W†®xäå]{Ö9k‹u7¯ä¬[À™Þÿ­5‰ÛÇv}yýúõ_¾ãæuÎ ý° #AÙ0r‘¶ë‰'ví²?aÏX„íìɽýäöíã å 7Ù…Ñ.½øâ‹Û§ÊÎ]Ïqîj³ ï_zñ¾çï{qûð«gfÁQ‚6öÜȨÛÛ³¥Ñaû_>õâ¥Þ}õLL'\Såjº3Õ©Fî»oß¾®ûF:zçÇÇ}i稯kãÛ?þ³kîüÊ?¾±Ë†x)-㎒KaPð=XC¶‚veªíšµåÞCŸÃ}‰éô=SóØ;]¢²Y{ïæ©Zš+Îuž5kÕÅÞ‘ž“æK•4´ 6K‹ózìåBï3Õœ2xf/Î÷ÞsÏbµYx9<mÐ-Ú“+Å­'÷ ÕùùÞyû§rtJÏô:jÁ¼}ºf¹:ÿÁ…Þ8šûžýräÓ>˜w/ƒBÖþ]ÏôÚ×€/Îä ð…/ñž ##îq¯ø©éƒ\û!®Kì¼Öû`æUÀVõ™ùùEûrò\í9 Öê¼ýwèq¢’);!V„à®.Îß39_-73ZÍsŠ­Ÿ±ÿ.îE#l“¡¡¯BÌ;Ì8…HÐãšt ’=l aå_epɈ±ˆtÓ Œ§Šk‘\F²¥ÝTGΑì›ôž'ÞÿÓ˸éùÚ¯¿üÄÍèþ·ký#♎6ôÄ:Gö¡g×<ö‰{yvýn°„eÝ!JGF7?±þÎ÷yl÷ÃÏÞ±kÝ ‡8ìXyê•'_ý»û^ܾ0ëöÇg†ï{ó;ý;ÿjóSÃçËáÙǦNÞ÷Ý[þêοþ³¿ýþ¾‡ÝOÎ "èwݦœÚ™Ñ^Ü÷ú£·>të£×öL-ÔÍ¥…á÷}÷Ñ[×<üþCÜ¿±ëää¶qh“\68zbËwî}ïx¿½ì8ûÈ»zç«ËËDl°Q4?i#Þ¦)O_M/Þ¦¨”z}¥Õív<гXÃ)’ã¬>îŒoì*;EÊm~˜¿ðüæ#_»õêGöõ ¤\dô#î\èyúÚ×ZsçCÞöÎÈ|ÕéK¦îôèyçéÍï|úƒEL<­!znêù×ÏàyêοùzžßüôŸ÷ÀOº_·8ðüm·þγ÷ß4°X­>sᦷïxôOÏ—šö//^xþ¶«ï?{í¦÷î¶Ér~àù§ yÛøøµßþï.;Uë¡+¯ýé#/ù‰'¾j/¿¿û5Až{¼ 6HÞ»ãò¹s—ï~ö ÑÚ8t³¤.ˆÈëö<ñìÃ{ï°gëå;×üþž CþÊgþÓ?¾¿÷µ‡gŸ$3£—ö}ï¹þsÇÎø3ûˆÓeh̾úÂ}Gþæ¹ýß>v®ÿÀ'¾³oäÝÙJp˜’§ÝMˆ¿üÄáÕýçú/ÿÉ×oÙ·ýÕÙU|ËS/nþ¿ùáŽþsçÎõî‘G7ö lsöÕñÅÉ‘®-ì>Ü¿Ó)§_xÊÉu¿Ýe¿M+³ËãÛzGºžïêé˜_Æl ÛÕl ýÁßèÙVKaC¶<ßõÀ¿röÈ@5ÍewäNÞ‘wîø9÷ÏÑ`ç­›OºsþW7kãöœhïáþþoÛ¿åð×oyÇž¨5{V}гùÈî=»ãøs›/Œ73nL²Zõƒ›ŽÜúð×ÿ‹ÿúžjÓ¾—>Ò;òεÛÛy`Ç·~イ,-Í÷Üö˜ýüvÿ^{ôÜÿžû½ÿÓ§Ÿ)7›Î?íÇ?öío_þúÓU¶ \¼ðΑ÷Ÿ;o.;o}zä™R‘3ΆayäÎôí;o{¾·ê$gJl¾ý, Ü}ï6wÌ/Î?³h_:|ç¦õϽvö¿¹vÁÉC2 à"¬:ßóôöÚg:÷íþŸÿñæ ‹N¶ÕÛn¹Óž3ï­¿éØç²õò…§o=kÿeú<òôÈG*iÐô׌‹H«Ü°(²³uéìt¸£7ØÚn|¹ ÜüèB€NN`ç¼-_;R„¶ºiéhWÛ!W×=ñò#?yüÜi6lzï'÷î~ÿý—ßùåg_~äס‘ºüø³®oÚóÄË)ÍSw¯¾÷Ù¯®Ûä@íÜ­}¦õï<¾Ó4œ¯ûWïýÊ®u.ÝzçÎýÿΞÅûíû¥± IDAT¦ÎÌξºýͬþø9ôÿ™}¤Q4μ{éÍ¿{¯ÿîShópìø^ñ][ºÕ¨¨wÛÚ­9ûêÉ}ûùËÇ®œr—Mûwüý›'_-Nªa¶ú¾ï?¶ãÛ›È&âJÿá«?µIǵG6HNÜuçáþ+§X1õôÐKý?y»«wN’–«Ûº6ßñ;¿óöæ‘Þê20À±Cª´d$[êø¸ËH²«T~ã7ûOÔ°fß3îÿxµ…Î==·=|àc/Á+š¾»ç‘ççËp­-?3òôCïõ#[‹MûWï¾ÖÓûŒ=«®}Íþ³DZמî-¥Œ7¤¥Þ=VÛw™Oíø×ö ¿VìÙü¿o¶ÖÅÝûú?å^ÃôôúŸ»¥gþÁ‚†Ÿy³ôÌÈmÏî¿„ §7õ¾õlž[8ôãÿv@§÷?öGüƾç÷=ÿü…iCÉ>ß×?ö©éMÇúw WÓ0.ΚÕÞwÝyùý¿ùÔåǯõ85MûnðÌÀ¡#íÝÑÿ©M§6}ìåžEûOò{û4ä^üÇöÞfÃ> Z\ñ¬,h]aKX¤ØB\“îÚÙ‰švî'Æ@w½%Ãß<ñ…ð÷øèàÔÀÒˆÛDÚóÕõkvÿéγ9אָíܹóó?þ§ï}î??ö“À@\¾÷Ù]nùð‰—wïø©]_¹üس7o9q‚‹:›6~¸ëåÇœ›>…N N'ðìëï¸ãÖÝï]Þ ôCÇ¿ráÌÂö'ÿ¾OêéM;¾{r¡Ü83õâw»lÿñè\ÚÔ¿÷»OÎ6R†¿‹¹ÒèÈwÿzDZSC À Kߟ¸mû«¶œ«-ló¯Ûýjº }tõš-}½‹ã¶GÙøÀã—m‡“ï{»¯w°†êøÿGØû@µu_é¢,Ûƒë‘k°ï¬e,ãÆ ªäh,‡j´p‚ï‘”‡@ò…ŒÄfõ |yÅ2’üDQ$z#4o0! ²•ˆ‚Kn¢”;¡2u–rŸS7Ó*DvÚÕ7ÎòºvDÍ\ºŠ—׺TrLjü~{ïß9éÌ{Žó°8ýÛ{ûÛßg®ºu‰=¤²o—ú'7¯‹ê †HQž‘ˆÁ0X®ŠbÉÕžÊAâA/³„ä,TO…ÇG;vãÅ4éí³Kòú:”°¨ÃrG¿r¤G¸ió»€?o±* ÙݾŒ—š°?2 Ü–ÙÞÑôÓ—þ3ž2Ë?QËŸq˜Š{Øó‡w51ú†’=ÈiåÈà(v¡ËhìJ¢¼ûd?˾›ø9ö®\`¯Ëbu¨8((èâxycxyغ8Yè¸ñðáŸÎ §J•ó~åÞÊý«2"ötíj³žÚcmã/TïH¯ux럺ô£m9iéåR³ªÙDW†7"‘\.fß nê–½§æoà„i/‹p- $¶Î.¶âû.<ÝÊâHA?ûGÖWsæaíŽñh¦Yxf GÆŸWü·'›ö[ë…¦í$þfOþ7­kÈåùU†¿Nžlg)icñì5·Pð¨Ãïþ™&êÄ¥X–”œúÅáwëàÏâ&/=/í*ׯ’s"rîƒ=²§€ GêðyEæx¯2]?é?üÉ{íD©€7Ë×ÔúÓ¨ì"“ ¥M—!…šqVañÊŽRßÝPjÃ2R‡2ÕåX>JU÷$ñ»f𵩍®Àü•å#õB'{|ø¹ƒ—tsp=ÆZ!ÈÅsIúqíü~Úq÷už £ÓÓü<å^HEÅITTý“  çsªµm—ê+=p'sß_‹¤ç÷6Š·0á³ô¹ŸÂO¶‡Ì.åÈó£âwR¿?Éò‡zÁ胯ofÜ~sÐ0ï >ÏÉJÁâÁ$÷߀Ëgÿ!œ2Þ*n†…Ñ<)K¼Þ$«ÕXqúÔw[×RG•íì&‚¶PÈCŠ< ÖGª¬‚¢ð³{‹•é ÇÑ-}‚"1- ¨ïö³âÑ1¿î¾ÌOŸxbZØ­ÜfëþûµhEZÿã“æni’ÝMܘ$Am‡úßC¬Gê.úú†ìŸÄï®óLDc#qKœÒ>aM`Fb¥ÝdYÙ‹UãûZ‚ ;Ê)¿.×°LËV¿‡¼!{x×7[z„çB874u{Ääfœ?êìTýôO-ŸCNr^¹ý³×!Ö쉬DA¸'‘1žÑë®j¼C‰¬&‹­<¼ƒOhÍN²|´ìe¯MšfgMB%µ²ìÿË«X!§—Ëë͵{0Š Ÿ¡¡~£²£„ìo$ÜÍR,CFbÅÞ6u¨£ O{²Bµ&w@Û,éõtš^°ã5ÁO…94Y± f'qZY¼ŒÏ¼]¡)îÄ´pªí‘›‡‰bv¯+ÚB‡.h2>7-\7§û䕞¿¬=a‰¹Ö<íB¾vúú.i迬*¿RU—ÌŸp²ó6G*Tiº‰Ç‹oìø^îñÕƒpªŽ…ú˜Ï‹w?Oo•©¯Õ\üí$/ö¤@±1ú­ßºÌ H–JÄ5]¬Ì•x¬§²Ò…¡N:}§dÓÞX*õ£?g ;.ýÉö-ýröåmGjBsCE:âE»"5¤»h³Û&1(@ˆe#‚{S@š‚¬“^àÿ¯3"Xn‚ïÃÒëxMW€ü ¨f¤Óg. üXŠ'òÿÄœ ÛµjÂ{nh}å¥ûMI±®#õÕ=¯ì'rl4µ^¬“Á³Q"›=⤹{³uÞix˜HiÇîu¿«Õ¾[áMð×aËréís·Ö%`Â9¾<<Ÿ²ÝÚ©«9ÜuFïœÃ¯‰Û½á¹ Ék/ÁxoÓçîlLiwËHÊt_š0³v¡­Öo./ÂC”õ­¿Û|·íˆ@ù†ÖÚ²4 à)¿„CA ¿Êå[$ÎWEý–‘Ná·Ï&fÚIV1NúÆ6:9ç ±tNW€Ùéô©Ñ„F¢Âlðï3ø^4æß&w˜1w°Ÿ6sÄí†é¶f´ÑŠ ø”ú@˜Ž^ؚś¦hÚkN§žž%{;½e™â€Ò3Vˆ’å[«¥IC™÷x©GeɈHY•.WhÌ÷<ÔÒåÁ§3F¿ã±îîî¨C9² ì{Rö÷Gf3\—y´®í:ny–MÄé|´ßüåÚ¼ê«Q^d,¤9Ùšõv©@s†Ðr¯W#PKÄæŸ>‚E‚§ìÑ:O* ufù§,aÏŸv8óÒ\+ÝZ™"{u³o&­$Õ?zû ²ã²¼Gú×P:T ⣉¼ÞÉNNâÿ+f$ÛuB"XFú ­²@ªÞúdxzÚŽo ¼ìox'áÿØñü½]¦€©íâ™3WeXG`H°ÇØ.ÛÿÒéqž’@ß~ìç~gvõ­¶¶&šR²Û°‹ÅTRfÊP€jzÞëýß~%Ãáòá©ÅákÏgá ×Y*–ý&ªþsåU U÷0þX%Ú|úpíá_lïø‘»ÕbQW}æ|Þ7TeŽ|{å’«¬œwõ²ŒwCqÄrxØ\¦ ,nzB}cZh.Š$v]‹m›äyÐ5(1²X,V ð'F»\i׿»¼[9V^ÙLÒIe/¯–ei.æÂÚÝ+:Ç|1r¸â·Ê•^üÑß)£‚)ÜH¼.Ù³½*ƒÛ‹KôDÒj¹ô~.c1~ëüyµg:=ó¡‘¹Qö%¦ýìòNÉèT³{ëX.éÎmÌïuC­ϸû*+ÏŸ2•ÐÌ.Cô‚o@Gjvn_häÀo]óª“ì…Tþ†g¼Û–VŽ™²øRÁººKa  ñ„iL ýü©i {8„8²u³+6²L²âY:{ãÞ®P*×ßW**ÐX.Ú¬¤™'êô"þŸN~ƒ Q”cfÄÿW%ècyÑ;éŸ×Åb?¥Ý̉Iµß¿£öô€ðfda“ï ¢vaY&y°ÑËZ¥pOÝ÷HÒÔ6pà€uPÃß(z›ÉŠ­Õ˜‘ªpÅvîöÁå¶=îï¿ÑHˆCãISøFÝ|µ.‰Qêýê³÷>;y3âÄÁòÞw?òÁaZâ»[ù‘ñ÷ìm³ÓÉ*œòL]‘¬óêâÙÿï‡]¨«üôÍÞ÷,³X¢±‹°zb·=mØáÈN{µgµ?h†Þ^Sgm ¶ã[hk>|öËcþªÓÍî$OáÊ*u)pAàßQã.-‹ð =ª€GIþdC­²>B¥Ý‘»»o•––[êLÉiŠ£J­úgwABb ÒÞºGìÐIZÊUCg›€— á1óˆ vp»ÏBþymÇù9ZNö¶e„«¯ZŽÓ)ú^’qÓ·e(%ç­P¹é£?üîlÝ©>Ë °åVy3Ox²[wœ•vxÔÈÎbvy÷*ÛjLY5©~FÇ ;¥ßLÛXiH[j|U†q–™F… «bþ÷™X+­ÍjF9²åh*¶ÞċɿP$GÔ cm½i”ÞœJcGeß²—’’}´Ç}ó»á¦ýwÏ»á<ˆ'4u*¥’Õv1¯â­hR©£-y)‰w²îBÓÌÃ4¢Ûx¸ßÀþ>q""ÏQ“ô'hÝõ¤UG1t]ç*˜!qvЄÄqàŸe ¸vSê/YFzxhÖwéõÕïíjòb* ®¾þŸN6ƒMuíí]ß“ááàk»xñÛ=z3Tµ%âÁÖjÒpñ7¼Y%¾ýÞÚº§M@;¼æþã© ¿xòÔ/ÃÈœöVüêWÿHïxïä¨ÔÅ—ÂdyïÍá³o¾w×”åÂô,%A—ä\rûY“1XÙ{ÌåÒ>Ø/Pߥaµ¢çw>Œ•®<®¡¡”¿·ÞQ8Œ/œ>ü Jý„ïîé³êúúIuÃéíì«©³öš#rydmÜŠU9û®÷asD-LI68Ôv7ìÏ)æ,Û_µÖÝ>iO=®gœºZwK´ÞÓœh ¼ýžr*uLU9+J'Bª.hʳ³ç{qnª,?Žä#{£»ÏÒQjhî›,d¤˜\GO_¦KÀÓæ9*—§nÙ¢2tö¹5r–N‹{”úÊô&K_5ø&K³%x“ßq8½³Æ[†f¬Ÿ2w þ£)³ªrNAæ, närEðŽîê¨r¥ÓkJ¸¡ ]ífÑ{þ|Ì ³‰?{ÖÂnD…ÛýÆ¡-GÓ3¬`UÐÂÖ˜’Ãß,$j0ûfN•bó¡Ãçç(‰²Ÿ®Rzºö'žRãöóT²Ë ¼m¢;•Íò²5Aî×2ÏfåÌMþd<ðuóŸâ, }˜[¼µ»Î±º¢Ð*G¤%¾¼/Z’2‰®î¼Nð÷Æ¿°Œäb4^}ºõÉ­]«M8$)¹ñzWûýû{XZ¸ØN8gb¶ëþ·÷û²Ø˜f±p‚Û>·§•2Ò8HIšÐ/§>r“ËXwÛ>ëÀ¾ÞúÅ«&„¼ëþñ"Àžð ^ÔžÿågŸáaÊžëò³Swf¦ÎNeø¡”¹ ]Ô;[–®.z.àƒi²ôž»suÃåyßG_’ vô~Zƒ’|¾Ê^׆޶1¤ý„dØ»÷Ä;!ÈXÿ±{¼¬Þ±áH««>ƒM<*jcõzÈH÷“¼­`±Å[$›”ްGbGå4œÙàl8#À° /@pkÊEr &¥Vˆ@1eOÖ±æ)uÄ:êFyYe)­}{P®¿#ÇŽÿIÕy2ÔÑ4YJýkJ•;6Øô#'”½l.j¦ /ëäõȪqÍŒ=mYîö…©^H&¯ì³Ä,eqO‡|‰dí+Y=yŽšd]‡»¼yÞ8[*cލ\­ê.¶äÆX¨ÿ™Ð7öC{œk¾ê3–·ƒnR‚½r_gi`Á£ZPþhÑu˜×ƒOaJ ãvvp#Xòöt„Ž:äés½(¬ªIĽ«¥JuÿÑ£æÐ­>²ôð¶uÜëXÅ4Ÿ•]:’¡C›õ•óHNßlÓÉ×+¾æŸ‰nc6X»ü”õH?<ñèA”¯qí®‹ƒ#žcDéGÞ‰0ø’H[]âJ(Eì_¶«ß¡9R¶¶¶¾tq× :)4Á]÷œ9sæ•C­¯سš!øhW{[¼öƒ³»ví2e‘'®´9 Õ­as)Q2g=³o|k½jX`bîòÕ<ñïÎþ Ù„#†ä?ÿÏ>V áŸÿ¦m–=ïË•ÿå×—à¹ÏÎ}¤]¼b[º²xö£“^:µFÝ?s]q²„»FfÅ5ÿ›n)2üÞ,¦ÅãøÆjzÊÙçœN[$öé[Iî|ûÄ/j2¤š`ç¸ Èu‘”ÿðÝ0Ún°óõž¿^.wH¥]‰=¹' vèù(6j“ÔV£òµÚv¾²G20¦iWÒWSªL‘hN¾CЦ´5Ô˜Cý6+SªSøX‹w—eˆû„é<èf³†Ä¡­´+ð'0ø·ÉÓÊ ¬ÝWÅ~õ§Ú'¯,YLtÝx#ÄRÌ‘Xq÷rLm71Äzs©‰hÝÇì®KKæK\Õ‰ë"÷ŽJ;–‘^:tuõá}­îß :µäFûÖ­O?Ü÷ðô+I+û÷»Vw ÂOß8øV[×®ÿDýN·ç &¤0ÞúUÛ?}€nƒ=nºðOþç¾ìÝmÂ[²íÛÀ=†Ý©_Öùþ‘ËÂîŸÝ…à ­sW®;?Ï]uyše„7Ø}·KΫSž_Ò;o©Z¼ªÓ9ïœ3¸Q¢µXuÎ"VÔvíœ|I§ce °¬¤÷íþä“U\Ï?aýl!E\ã»ÙŽ5ùI$ýÆdC9wÜ6VMnpyÈ&¤j­æjm³Å³îYŽ€•$}«•ªXZîÔmr–Èá9 cÝ:L»mýf,EYÙs÷qWÑJVå@ÝÊÁ ) ˤ•=×9ù¹Î õbÜÅ«%— ìÅœ}ĸÕF¹X6ñ÷}V;²8ª8_i«.» O`Fb9?h±˜¨ß±ÆöGþø­Ž”Ób—·——K{,™8vW,ú®½n@ìJš @ë›VH²¬±Q™]Êâ9ôY1€T»(°ítÝ:vÝsHÁKÌÓª0û݈DcꢳoµM9¶Ì«\ÂX×’s(ŸHžÉºÝBÐw¸ÙXÞiññ[䂵ô½'i+¯-ËW¨ZpM–Ei­FäNäýåw$&v*‹ÿ¦€"¨Žgª¥¼ðþNQ>ºNâ'‘Ð#в¿Ýç©1xÿ¥Óû`ç¨z †ÕÌíª{‹<Ó[ßøö[&‚È}÷Ï Ü>tHMÐDf­¯ìÛÑÐÐPýp '‰ÐKbö‹Ú/]ÇÆošÆAÊoþ1m«ì—ÞÔžõ|ðÿ—꿯…ªÍ÷þÙ¡( ¶;þß5i8ŠÛ¬¹ºä8w «|M“!v'÷yËÒFìS÷ÇØXg›:?û5T†ñdÛ=׆óC–‘Ž•ºqûCÓôÄ?g‚]ÇÜîqs¶ù"ê*cPÃí°nùë7þ.ŦŠ=ùM¥±zyÞ’‚¨ß6Ôâ ÀšßK«^œüغ-ͳ#ZGØ"ÙÒZœ9±6€ÄAl3ìIÅÚÈ.³+1²TJ{ŒØFÄe³ƒ¥¯µõ YÉóæêªz°ï‹'kª[¦Å : ¢ÑG,¯Â7l >Û«T*NÿmH«›£¼q©¯M€!MQ¥ô‡Zÿö'¥å§ÐL"S©…—b¢ÅËc_-•‹)¥‘l,¨Ž«RÑȹ~–‘°£MÞ¥úÍ#,àž^ÚëÒ븑ôjËüº»£p#àÈ,4Ζ[ä.ÞÇ8xñ¢' ;HÞ&Έpj;; œ­†2Pé¦NW¨ Íä ÄSòbIº±_W>ïn±ÉÓ8“ýÆ£?‚E gKžý-R_Ø)%¡‚HZâÝÑu}’ˆ„ctõe4H"¥ÕñµûZﱈO46Á_u-ûõdíå\ýÞœÁÞ?ÓÚz m»u»Éz¦z\Ràg8Ø4°hª;Æ· l {ÐübüØä±7;Ã8„Iž‚§>‘ì)׺††¦\®ØÙwß÷j`8v'œW¦z)õÁû†ÊuE¿¨í„ʈÝÒÞ)k,éÄÞk™DBSaüì.VÞÕkÇ®€ÕØÆ9Õ,2ˆ2_>ü€Á¾æÚ²zPipL6<8‰E|´çž? ÌuàØ{geŸÀ)ZDy°AÕ…Òdñì¥>¢¼YÅ`ß 9´lÊG+`U -H"4”Á9Ì*œ^Î/Êú*?ÁʈuÏHçX»†¬öË?ÿI*Ú­Ó›ù–‚bÙ°†`{J!º²\ÂK:GÔ²×RÈH–Ïc1YT_¤ûSk¡Ê÷yø~ÙÁJz›c[*uTCx-{ÔZºAË› ¾8Lv®©PÙ[1XìÇO³ƒ!Ôž¤!|Ç|:m6 ât¹Ñ­B—1Ô+.‚Œ„„²lvlü OaWÝt&¹³€?b.É9BFÚÅN(‚뮨® ëÞÌñí¬äÌÆ›Š•©ôoKÛ’4^²nI;7 Çný—f³ÒV0µN"Mè§ß~ÃІ©ôˆ0¨çKɈ÷F;yH‘ëÄæ|„t†¼¿‹óŒ„z\ϰŒ„´oÓž3 "4^t{ãÕ]¬rƒèÀÖ‡°î—E„ÏŠi¼–rï&„¶ûÆYí¨nµÞ(Átíýꉪç&ïÆrÿ £é}ëÊÕ‰«Wî,Þ¾÷¬¢…ßôN]EçÒÌY£Ï=‚?;wÇáú ÇK Ã3âE‡´ïÒPPøÍƒ÷Žã¢¦‰}6 äRšžR$4Âý{ãoÞª,!Xo½8 ºBVÈõ঴Ýûƽ2HzG½¿·]Ð(4™U«õò;îLËþéP—R‘h×\ê£ü˜º!æp®¾b?a=Æ4º6£cT=†]^"#a ²¾ÀÔk-wGÿö»Š„B"-»åõž[7Ë[pûŽûç „Cl™XUÅŸDÑôp]^-5ƒqÓkÀ"ÏAÞ°{+·ÑâVÄÖœM¾Íå©„“Àžì‘ ô(/ËÖàú¼KI嘦gõˆ¡AÛ–±ìGoZH9±bŠ£,cIbäp‰H캛0@0×Žá ‚½”:JÀû²‘&L£°©nvðŒ„E\æ®åÒÇèqáIËå‹ÚãX*¯Úðuq–B³¨B]&b7n܆èØ×]Äù ƒ¡@ g¡Ù„”€ ò‘Ô#‰ò«z¤£@ mûÐüdYRat¸–¥¤ê}gö¸Î*†]'“0ö[…m –½øÜ÷çf$4)ÃXUïØÁ/˜ÎR$Èöœ>ëšü²·9L<Ǿ À¬wiyÂv5»ÆÞ$øÂJ- \-_º»Fv<1h¸=´x»ã*Ë*»+¹ÏKwŽ];ÅeO}Æ{ŸÞ¥÷A¶½×õPþŠþùòì¥/jb ½íT56«Ôih’X ¹±EÏ&­µæÈ;DÔ~Õ™KGþú“€?åÈ›ºà$±†ë‘j»(4îí0ê@À¹Þ¸¿r‘ø¦<s hr°#›ÒŽQðÄ/[ ‡ß>‚•›·§D÷íü£‹7üöÂ|„V ËgØ´ÇÑ •?~ÿÛØè°BÇ¢Lëè‘‘v¾5n(½¦±ð+`K;çÀ Ú“®ýÉiÖ‘½ß Xݬ¸ºŒ!iËc×›UÞ@–’ýrû‚yÍsN¶®þÈâGGž²Û“a>"wÄÞ6ÙqœŸ¦r’ ‘NýU˜ `¦b7Ä– Q9,XøWbô·]ÆÚŽ•–PÜ:±´CntŸÅ„P';@œ¹tè.%ªd mzI+|…BG›ˆ ´È8»k»Ÿ~cŠ–d‰kGE8€åª/KÝ’H¶[*ÌGKyªØ#ý ««ÔeRFÅbÒ³Hº/¾rººvœ¥$Ö#Ô“×[ìü—Ü@Q.øZ &çÁûgþø’™šàž­ÕXìMt|7Îý¢Ö?9uìÍÝø‰Ì¯Mì”1ýÞòÙ††ß3·qRM IDAT2ø;ÿ%”üЩgïµ—àb™qØåÒ^ âí ¤¨Fïœë­œ£Ù IOï¯c¨ÑãÚˆ.éS1­ª´VëwM–> c«–}Ñk†@ŠLV=àƒÃLó8íôPïù«<ª@CY*‚Ú'R>ÊÜ ¼±‡§¶¡HIw=\Uâ«Â™‹½|b¶ƒå+3šî ‰'‹ûŽ€‡ÛW°ÀWA Ò9åõkÃ[¶Ä\°ÃÆê!³þ8KúMì§ȹ <òaO_DÇéR¼qÒT@1ÖXÐÜݬТ¦>ie•˜‘µgæNʾbH§,Žc§ª¶L#J׼пág•$ 9³z9#d‚%`ùÃcÄíZèJKª:ù|±ÀW–Tê×Xi×ýŒz/âìDŸrQr„:i^ž0Bœàÿ‡¶J²ó8X7=«dçAn›–‹dÐ|·p ¶ÐFv³Ó@¡>ëãÑ¡GEºÝ£S'†8Õå‰cÝ›º#Q“xB\?Ú™Ï? ‰»C“„¤Õ!àÚ¡fq`(ßÐà‘™ì¹[åÐ#a}˜¸Ÿ\e¥Š]¶ë"Έ^ÙÉ^¢˜ÝÓºoÇŽ*¨ì’X+¸aB[[½õ€µ‡¼„™š­Ue'&ËXFB¤ pWMÓµ/ïØPIèêö8ž;,Û»bûõñá£ÍX+²›½Ûs,ön"Â/YÃ$¿2t¬÷£"dMÅÚáªÿEcc»PסuÝÑG7)ó—þ˜:•®Ÿl¸ç¥fm9MÒFÄUÕ9Ç›y£ÖE±ŽúIûO;ôΗd! aä´9Êji8é8ÿϸæÒHZ™HÖ±ÃH; ^ìÁ[Tîšø¨ò¾'¦Ü `4냕*L’pC»nUC72H{s ï¥ãè·ÇJ1N;‘zFv¶šU¨f(ÃðÇ -b‡@Õgè€Ìሑ c./¥4l7qý–vË¥4øp®°\lÞÐá:¸.Y{zý‰õÐ|ý3NÀFdÄ·yÒ9IÓX·IL=߇’¯¥!`²:®ÉÕGÄ&oxŸë¶)É 1þ‹#/$ÞºR×3ºîÜLˆd(’ßæÜ$¿U ÉOA#i˜ñ¬D>I¹ uI€Û=Ñ·pŠ—ÁŸåð =ĤŒôuÀ.?F*(ò #˜ä 6ÄY–¹¡A͆wz.žéo?9s± ¡¼dOS’Îó{p)J; «Ë8¯ÞZünØ;u{±êÌ€õ¤Œ&陊CÕ êú©²7/À³ÅN䊧ØÿË7]W¸D~ÅÕ[‡h€·¢×uÅI&H-¬IúÈDÄ>áÿîÖ^{ŸÃ°¥×ïš:§5¼’óƒ3Ø;›7¹ìÛ½þ;ϱPŒ¤ëÓéˆ6ö 'Ù®0…Êêò´ºv7UIÙà-jƒ”ìä ÙqlˆŽ.|‚Å r’Ã\ZçÅ+òº·7o#ˤ¹^+T…\i‰ök©ãÐÔu(]3®˜Çh #ÛÌîý»½ó©5mÛ(­øh-ªù´B 2êûdŒ½ D8Ùé |nU(í™·Å© ø”âíbvöYoâCÅÚ“ëfTv릘„»§©`——>:(>~ƒTd—w4D΄ÙKÐ"q . 7ך+倖cÜà•ï/¤óÊßÀ ãTиFÿ–ãHYP kp"`ˆ’ÿ_±|N Á!ß_d€Âù,9¯  %uâô&»4îøu=gÉ»ð!Þ%±â.²Á^µˆâEÜÚÛy}©0† Øv_L¢·£uàõP„…‘do£Â8í(©Nv™8ÈzYV½±Ç’o]ñp„ÇÅ¿]8ަÉìÉk‰ª¿—O¶u–jCb »<yg‹•õÛ\ @`þ*:Ms æ¿ògH›ˆ’€¯,ÔhÓ9ÉBC‡½“] )ý£©TÃ0øÞ늊ÚD BÔC`æ$ E¶à„:›ø³¶$ÀÆ$Xˉ¦Æ ™ñi$JH)ge“u@wzñ&“% î ¨#ÜÕÿ΃ ´=a³‰†},#••Vx±šÔô”ßvœHbVFl-ŠŸ” höºÝb|Ö”ÑvŸ]˜3„ú£9Dzfp-'›©+^0£‰¦²?¿ë0ᢦ‹7óÝØ ÜÂN+ÎdeåèbAFJdµ6ø¹â^*–6¼cÓ "Û!þRk¼y//Ã/ÖVSr‡k½é8$’Ö…úœ$àÊ_-Ø æf”œ¬”D’·8ÒÑÉýoCɨˆ{Û¡ä+jy†üÈ⬙R¥ldMyºFD¶¢@ íà1S¹”…¶S›¶ñjö2N.ð'Þdq³²Ù¦¬ÀÊ:/t×åÔˇêYJšüÆOOpM® ±š“À:‰t]úߌýÓ|´s)Ÿ8i3’Ÿ2R•v˜ÞÉi”VY4WórTvÉ“´~C#„9í7þéô @À´`WÏAY’óxI¸î‹Óã eêGë§ŽõÖ å5ë{*;°ŽD¥â‰!í¯Hó Ó©Z¢Ò®åsç•s¥¼‘­3ü ¼PûÔMƒ°˜ ÃN{Ò7 ŠÍ\Í-EbÅ>ìÎ)ºzXRr 96HeË™47TÆ æÉH„Uveã•>¬,X ÓPÏZ$nmnãš…RŽ—vN”vtÔ~\U>‡¯Î&*×& fV©Œ‘WƒénÛWsaX§Ýü¯F”ý@“YäÓ¢ =ß¹K‘7Myšù,°@<ðHÁHÚ;ñÝMoû¥ÒNM4ÑÄAVdoŒ¬É[D9_–× ˜×&kJÝëP[¡˜Ö†ÿmlWã²ímìò^à—'ôŒ(åÀáD2äç¸jQQÞü84-›—ÐçúX:ĺ ™Ä?)E¿=iõ¤_ã3ˆ¼ãÙ ËT:ç6h†€rÖdš†éÑ)l,ÞpÈo÷å0oßÄK»B_Ý•ÃBð¡Û†Û¬´C¸!"Ïåé>K¢¦·UOh¢PP5Ÿ&®KCZú4ËH‘ÿ1¤U $Ê2sã“‘Ùw- ëƒgâ7sp¶±„j’ÏÜ'›©F¿î¨Ý:€Äìx‰Iðjô”dz™#Ö3G®úúI/L¸a;§¦Agg¢¨N ÜŸÿaƒDø£á¡¥ÇEw— WïëÀ­ŒõÁ§ È•%½7q• f[wë‡ôÎr—ç  ÑvKJ;ŽMF( ºšvjT q®”ÿºN³<[SË+;ÔUÝ,›oã°7v¨7Å2’’àŠîi•¥mHNƒz³ƒµñ-y¡ü\ZIð‰Ý$$A§Ë…0{ao¬´srŽk&ˆ¸lµ8ärØP.•½ÀcˆU`‰´È@øšõÐ×dK$"NA!#5xf³<ïí’¦:0Á•Cëç™)lO$O€aPÈ6%Rpy^Åô4×c˜­Q)Am œÌ •ØâK‰XR‘„>9ÇI¤²‹/z5pÝìñWfFƒ Q,9—^ÞûYA/±¤iuöïß±:*¨ã”˜l>`ÜÄçÒ’ú9'IZÈ+…ŽÍ¢þ @”9½cèQš%ÁÂy´(O§+X㣨* ÙíÕò¥~‰÷GùiSFÂm¢ûO–íúf>#YIÒÄJìóÖ—¢úÒàíóº¶"Au`®„vL¸ C"î•éºÐºoG× <„Ïy‰ ¦A׎ÝAw$À>¨À©¾Â4v{ÆÖ‚–— äú€cÞºüÑfZlÆ}r…7ìÞ½~ÖuÇæü°êÃk$ÌWÌ!))ÕõÑŽÙzßÈ´K«ÇsH…ÌΕ7L:¸K_TZAÒ“›9âÞL,œœÎhÄ_zRC[Co¬ûË´°g@ë¦ÖÁ”§m/Ö°ñpO4 ËÖ‘I´±çÿ¨‡äi8!,æ€JoEEùÞ;.ÇÑ+{ôÏ„§iCG$óg\Ô¶ÛÃïÄq¾T0ÕE@„wLYÕ÷6±‘@„4½ÐžäÊ qªéa¶.¯%73|WÀØvÝJÑ&½dÌH,pãØ.t†9I˜2’Ø;A¦b³åÿ€ˆ_cÈ=–æ(©[ŠÌ_I"‘©äófI² G+Ý…þ2yžƒd@¶Rà›Æ÷•ZlzÜK8KIú"‰Y'âßp˜È—t|£âk€„ÏÎü&Q„ôÿÇ—‡Ä Å!ùÐp#Ü5Ðzxt¾YF²"§Œjñ¤ûb+Vv¸1aGúdÏÓÕ8Ž% |oXÈÌø.Y±Ï½ètVë§¾ü§ß8Úe’®«\êûŠëÝ&êtËo;–À_âq‚ytFÖõÙgɒ㻟Ðx3s]ÆRí¹!ù’Eí®,zš3زdyRZn¾§…HÒË%f0ºd’ÿ–• LH\6_ôC"#sQ¦£ÈÉ~#jgàKNÞ7Tf`x¤³’ãýŸ^DSª¯&$Ö­=Û(˜ÜÍÏ|½ü5ÉF:æ×çø˜ O‡› Å•ÂÕÀ" uò”ÁN|‚}i25}0{f$„¸×Ö‘Og75&ƒ©$ Ö±p&,{:AsONägèP^MðEqöv)ðòFbý9ä¯.´S‰€N…LkÞ—Npžú˜äÊ$Qæ€{±-‡!‹“W0”‚DŒÌ‰qy¾ïdôd®F°9 œñN$’Ì |.½iiåk†7›­F%DqÃo’w¾ì(’¨p#6??’Œbÿ5À®€¶*f¤«‘—‡xFj¨ªâ¥馷ü2ÈF¾dEb‚Õcöð[TÙíÖœñdÝÓ,²¿b¥R8›(iLfLsî¶š,Œv4¼zŬ¦ªŸòßû œböFVgdšµCWÑÉé¼ÃA;Ö_uÄîØÈØ2Ò”ª‹02oÛgŸmÏàÁWd5‚0ØÔÖixsøØÐ½“d¿u¹ïœSµÓn\ ñ)>[AÒj[d†$Ç׳„´üè 4˵}ÖýàþtA ±?Û.#:Ð¥·öœiÝzººzGÕ‹/’ï%e¤€L^û;0ï?wÅÖ‚¦|K‘Û>’¥ŒÄà P;è‘H èîgŸý&Éu¥¶Ö«¹¦fîè—rÎÇ[ò6}ú¡Xi{&Ë¥¼hVÛehpEÈã’fJ,!Åz›}YI¬»’ˆ}ÛjÈôåh{gHˆ7D1°$ò¶\òÉìºá^V¦Ù³'I-D)€%Ïe§íÎðGa"åÍ–³éCtìÓØPêþ˜ûýF¢]³;jðϰTä”<Ì sRä˜ÇxCPªGùŒãÀe@Ï=-PÜ:•¡qÿñ{°Ò' !¥alŽ·HN ¥m~à B½í£z›Ü8%p ³Ìvm”žÆn$ާ³• ¾ÚÒÂMX ç ¬ÜÛfÒØã\{ n(Å^%ÏšåÏ?{ò:3ì¹=ˆ¥ÒŽ0"eKaÿaM¯Ë›­>&æ‡Æ»·‡åbòû8¶z;ºlþdbaú<ñîL„Ú­äm59弡‹vuÃÀ8ŒžYFê$„(ªÝϬqr,G%DNB®¾J´ í"—Âd§,àôP Ç &ʸfÌG…1T`Ä)º›:Zq³s¾ò C'¦`›¢(/PG“#Þí)¬›,ù ÓÑ’ˆ×QuGa¨¿úW‘!àÚ½XÕ öH³¤76ÛþÒi2¹¬†]8/K€ Z $`7ë~0úÁ¸ÙñðINmV÷Ã"©¬°´;{¯3ÁAVùü `0´|‹Gái*ý?Ž,aµ»}W޽‹¥z$Þ[EÚ)ËñïžÛ¸Þ²ÉStìƒ>É¥5XM¸ˆŠ×7ZaðO:6ôÜz¶Ž,>ÔcVYa¡v¶MZß"ÐÌŽýÍ)íï åÀ»'ŸqFÓÊŽA€ íráï`Ê î‰¢",¾iêŽ^1Uå ˜F¨NäƒRNlj¶èY"Á +¼W/³'û¿’܈¸®“û‘½`‡`©£)’ØlsJuÜ~Lê¹ð)P‡FÍËB¤€ÖD/g„“¯@à É;Nrc䤉æA„¹}Oç˜ï0‘ärè¶r^êJÁþ„d–´ÙººXáÉÉ©w€^ää‰E×¥ óÑXó„¡‚½$I´a§X ŠÕDZý vÏù•|"‹„¢‰Ë¸*Q=Ž$î6xÊã%@k^7˜·€¤;IG$ÈH]ÚÁžÅ@z‘Ò—<ŽxF"×ÑFöx€Ây”K ¢ÒxvhéC´”ýüÃëŽc×hBÒè.¿÷i——8ŽM¥Ç®äd¡´­™»YN²Éc½•AAÁ‰lÙ„ Oäè´±Qoÿ4ÇØO,¨Óäaå|†ÃØ\Ô&‰!Ñ.=’²cÉ  ¤7)wæäjU»@*ø¬½öôãq˜HÔŒÏ8 ÎÊîÃd4r…FÚŤ$rÔ ¸XVpÝ%'á‚-1¤%0$eÓ¾gå5òå·¼ÓI,+ð*ð¹ÊC\ÕÖm˜‹9÷Ÿ÷Bcs¨9åêõeªñÄÞäÚJžO¹T€‰ÀqK‰~n ‹œr‘†CáÅÑBMZa%ý™™*,ãí ^„bÝêIkáy\é>Šqµ’ç…¯å^${OÐÄaª¨pãHê&D§X Ïç£ žlRBZ‚É,…ë‘`C,û(#=ajòa-¨3ÀÒÄPŸaÔ·çP5jØã²6–¢xFú’’ù93ÎcëÕ ?èù1'Ž5f×òáã¶;·GLg$àE9h×b»s–…ݽU½VÊ€¬V‚¡- Yô|Þ-E‘Ó‰.Ià6VÚ<'Ò7n)'ÑtY¿‘žl8|Šú±ðòˆ]~z”Ëg"hÀ8rêÓþòY¾´ƒ¤Ëm˜K».ó±+͒Р’“ÜØ·÷¶©&õØ#q}±Dëa\d:Ô¡â¶L–»dŒ1‡ ‡¯¨Fqi¯)z528ÃM˜là³":´¹¿¸\WÐlç¶aGŸÅq~ž‘äH™µÓ< ׆Рø oBÀŠÅ£Ñî<› mÎ!¡,F_C êCiá£îfå6²¼ƒÒK¥¢bâÅ] är+RnÒÑר|K‰ç³"‰ýT°/±I0²Hòiï^)<Š8v§¡;ca—_<âøÝN‰åÀ¥ó—$½o1ˆxyÇ•î€"Äz$H~vŒ³ŒäC̶1Èš!ÊH‡·Ø¢Œ@'\uU%j<¨³V WíkµšÈ"ÙóäìG̱†ç #¥êuý1J«Ámù¥vñ*Ú˜þ¸îº#†Ik„Ck>CÚ÷iÕÀW¬î½@ 2våFŦcf½Á IDATC«;çRôêU}tÉ©cÿ5t¬×Ø#ðɽ©¼Šš$ ß³ Äeuß$h:\yJ¸ëh »´Ì\—€ÝŠ%BœW={PÖ†‚ÃÇ´ïgCO¶Q°QuDz’óCöË.º‡äKºöxGÎ*{’ø¨Øe»j%9êýãÆ9¤Ö ]·´.Œ#¾:¡¯Xâ!E¨0Ù0Šœ6g´^i$n\ædÎæP¯×%¹’µ`íuÉAÅ)G½xƒÃ¬°ß,æ»1¨t:PIMÁ :‹hz¾”E޿ѺPJî@|PuœŸ~\˜f§z†¼ªÆ#è.r—žÉFšµäßDÈÙ´ú9êU„[µnÒ•KÌv°Ìoh㮄ˆB IÓ'±;³LÔ| -Oâ5—.-Âß™æa`6ä ua[—˜¥,ÊY€ ö…*E†yy Ü:ˆ¯Qÿu&8Î3’ȤIé<œDTAªòò+EyoÙÖ(ÍäáodoóȧJy $ÚGâafË«sm–‰dôWw†&Õ겎Ÿ~‰ˆ¨qoÓÅWöAÕR Á  Xu¨ò¾|Õ­Qš+žÅ@ªªªþC õ3q…ïÔ+@°S¾H  '?ë“­î,—I`÷êw·ïØ€f÷9çÔ‘]© KhºL{³h*"üÆãrªâªÙàµØ•¥nHHŸ¼ÀPt"z%â^P½ù£Eù¤'I½s´IÈ\•üú²€Ñ”c¡€† Š#n‹«æ)ðìkmõÛɉßXÛéYFâê#™ ÚË'-Îh¿’+K±œíÓ‚f‹N>ÉJþ¹KXXÈ9Yáo3‡ùNÞoÞò•ò¨-t¶H¬c?5·‡Ò9§š×AVŽ•Š#Á›°¦ÓÃ…&,!âÛ`õÃ5.C•ÔRP÷À®iÿB/”–z!ªÌ¨¯¢Õô¢©Þd?¬üh D°°$}š}7'hfêZØ+‹:zaѺ™àï,­W ×.dE6–E+9kÀ|5‚P Ô¸¢°E™ý ”@8ÿ!Ž:’'7GÏ;¹ä‘ñ?7‰¯ŠRA!ƒ£hs!'1&–8·³À›oÓ/ž³l|Þ$±¿!#Eˆ2ÒÃVMÁvDÌëhÙÆÈ]ÀÀP»Õ¸Aª„ÏcFªß:ü˜¯zïzš$j‘Xݦé/–MNº4e¹¼–áØ0êœ;åMK' bÑ.Úœ#8¿»v#‹TãÙÅ¡€V…&Tê&˜îóÜÇÌÐÌÐâí…ÿp$óÈÿþÛ›º%}Äÿé)GIBMÀ‘£Eìƒ:4ŽNÇË`ÁO.§•XÈG¬ƒR—)«”~5†Dj%$ž“¢õ F¢Ú¬À¬ê¢ù†RRÛÈdÏkpX¢ÒOzÚyžòvÝ;·aƒt_l:N™•†¯L‚iKJOj¤¯¥CFdÙÛ5MßgÄý[² ‡},šÒ6C êû ¾ÅÁ!0 Q;B•Hʉ.‰Ç È»a%í)ÂB5¤ B«XÛQ ´ääG:í àÚûŠÆ(ÈxgÇr•|Û6•ˆ­#”:bk`-FðwBÀLåܦÜÍ%_€!ÏÕ$[°‚}Ù…-|ÿõL4ˆdŬž&Šr‘ЮÆ%F¡DÚDô^éÞ$.TTh“T°KË—*þίMäM\væuDs± )%MHÚªþ`ã\»ïÌ =ª~Že$%ËH;¸>èxÖ!ðï‡[*’ÄP6µ¿XÃ8É|c ÅyFb´ïÉîVþãUJl‘XW>];îWO>Wõ€6¥³¬‚;wÅÉÒÑãàVu¿äÔmWœŸ³tóøÒÐðG>´ –ž‹ÜaYë&W7ië=øçÝŸ¨³]:÷ÛáØ°vý[°<·¼š¬¸ËÉ]oZf³RFbùHÝðÀš!à»ópƒyr²>U_Ÿ†%(î¢isÕú?¼X(KÉ r€¶Hà¯h}ÈH—vYs¨>Š|ÐĽ6²æ€KnkqÚÒ ËIØ#-a4‘—‚Ì#y;¯ÿëùh§P¸Na£ÙhCvTôÿ?}À*#ÿ†:VÄÕŽóŒÄ×|ÖCûpŠ$yTì´»Èv™8wôÙÿKI8GbqtúÐᇇ«Ê&]Uïq¶ˆ·«Xi÷84CK3ÿ£ç3ž½z\XÙé]\ê[¨ñL]•/j ¶ŽøGÃ(k …Ý•Åa•)ó Éd¦b„•}¬äÒiMxÄg`™\žV7ܪ ¤œ Þý¤·jØïWžUúcêÉšóÉ#eUåËÂè#¦/æ´>šã*\NÅBRbI[i"ØXÖ¬eô8˜rSJâÎJÏiSú\ ”jDQ ÞRõ† >Gõþ…þñÿ4|Z¹üì÷¶‡hÏh´‹Hh*XFú-0#°ÐS¦Òkìsp'¶÷½ÁµW*ÖMƒäAdŽ7äX,̶þÑì| Aì!W¤ ›+á”ÊDYÔœw˜CÿðÇ?ߢôóÇ4%AΧˆüÂü?9òÝ?ºŸ’ò8¥ŠFÜ»¥ÒªU½¹];ªØ­T“’ˆÎmÇ0ãzA^RGªI|,\Àš›:%âùE\±’+ØD’~Ú‡¢¼ ~!§•W¨-E´%±$IÂ×E©âBL|b5hó/ÛU°5Ÿš¢Ò®æH0{¥½¾àc$H  Šsd;Å]-”vq’µ;„Ó¾3VwAô6Õ@–baôbUõÖ/X["/s=Wõ_ÄC§PnLH:O×m ›ÍP»ƒèºsìš{€@_±ÿN$…†zß=P–„m>ù”v$8:-kî >…رų {ègŒØ’%LÆ*W:âR¾‹&eÉ#¯žúÅéÜ»wëÓò[†{3pñôŽÉØO+ŸhABŸpì8ü‹¦ho2Reh¿#²Q¯ãfK`fð§õÎÜFY)¹ %âš9cÕ”°y›>+ÈL?R×L’7{8ò=ÇQ-ÆÛJË7̼´³û,¥J¥ªvÂÀ“ ;”ä1Ë[‡-nÄesëkr—Šã©$Ð@Ó„ ( Y† ˆììX( «¹`Á¾¦jÎ$.ÿ0ä)%ý>Pr?͢ļ·ë‘éËß<ꈢx ¼gŠe$ˆ ƸcD^Nkîtr×:tºÇí§õLùSd¡v*’êq‰NŽ}ÐcPÚqÔN ²—:`,J;H›¹ ÜÕî•<.Æe#ªóD¢÷Î ‘”ßJÚ)M|­Ž»ž÷_–ÕwBµ·4ñȉɩ²2>Hb‰f¯ ’¿ñèC<×*'P×Áo^Ú%@±øÀÃjp§ÏÔÐs ή[kYšÂ¯[emÉèÏ{ýêcUF@páÐéÔM Ïîñ?Xa •0àõö|zÄ…œW‡ªÞ7¡'z׬\Ë]9†|Q(Ö¦ó½çXl-é︴Å=ÉééËû-&¢´®ÞØg$ÊV)o˜¬wù7ûnB_}õøÝí5]=MÁ¹å¹KÖ[ÿä†\Ÿ.«­¸Œ[¡£Mª²45IØAB‚XbWª¡SFØ${»ë_ƒÊ;U—h—›Èœ*)ñó=ðÚÕ1<¹¡·Pÿ½»&Å´âHßW$²>k$:¤¡8/lò9¢òsÅâÄt¿Åøàü%°þÚš-V.Íä{;²’€°¬I\\(qãì¶HâËc´ê<þ‰øL˜¸«4{7Þ2ø·E¡rM›UÍxy[B*Ú_…O·ÝšO@É>]z7“˜~êoÖQÇotè&dÄ/Ys•NoK»´\/OÓ3bÁ¼ô|ïva´ÞØF6þbT%4Mà„±‚RÇŃ”‚E–î m-QÝOZU,|£Ð½êº» Í. ”òÅÝ&ð”DDÞ IL8yô[¾—¤iÑ}è´ iŸáóHY_ï¹ÈÕ¥«3·¯¡ÛTÖÄ 9{ˆ§<¢Ý|_õåâÐÌbÌc¬ƒhSßvԳﳔÄz›Ü5nÁ¸mtßSª]þ{̓àm‘ öÝí:¹’^ÍS …â¦`©ï G½²ƒô•Y”+ëåXÕa(Ñ_Μ.§OUY2¤¥'‹ D´±uêÌrã¬ÉroX½¨>û, 0ðáãŸ6¸Rõ)sÕ-¹íÉÕ>þôý Ô ç¹|Þ° ñzÓȼ<'?·N‡»—Ûû,ˆ5&L•†òí4Yc'´ê¨&ÉŽ£žýIr ¦]/éø9/:#K£—C$ Á¹wÜ t9iµ²t;;lì—¿ò+‹ùÞ>ûôvƒ¿ß±áH)KY˜±Hï0Ëmrš82µ«C™‚?=ÿt ö#ÿ¿Ù&£Çì:º¶*­œå›Ó‚µÔì°!±ên†¯Ÿ§mÝÝ¢Ô1ölHâ¡sˆ‹Âɶr¥+åZëïa‹•ü¦,ÿi9ç¶ÐߥPåk³Y)õè@æÿsbg¾S*$5H̤ÈÅs—mâ;ßyyˆ2’’El½®b [«¥ŒÔDïE²n¥ˆ1#Á@öcš~¯íþ7¾ýç÷÷â ,“϶ռÔúÊ™SàTl÷6}2^6U6nô®çë¾³ô8lJ ÿûs+ãndI·D3÷þ›Ç Fîýu;’] PÜò!k¤>af»àþõµ7Cg=Ÿ‚H$ûß®»¿óAé[åÃSwôò+SÃpµXµþ2emç2´ÝïÌÕÍÊ’7,¦‰ÞgÏ OÔŽˆ:0 p“z¡F;)‘°´cÿt>æ„@jæ‡Eب„@‚_¬Žh{œë®ZôVywBÖ!• ¬éUc¯V[uÏhsÅ`ß]·f„AgUí`u¤\íçÉ„½ä’ê¨þ±¨ øô•˜‚ à⣆@€?¦`³2§RýýêùR4ȉ:”I©§|Qûcº-°Õ'Î3Ñü먪ÂËE—Øåu¨BÊjì\^Ö·wþ¨—“q >kÚÞˆù•Ž»¦À0‰]`Nîâ†bìËÏßÒÆ”¡õâ7„ðOªTð&Ã1Ûg¼§R©þ怡³pÀë|é|Ú±MíyvŽ zÖIͲéòÓ(¾ÏÉ…„¦GÛG1vWUª½ù0åÈ}=ÃäÌWºÿ”õþû•¿‘Hð=·üw ¶öpú¿úžö(±Þ²,Œ9ª< l¨­\f£Ýd’A¡&NÖÃÓÙ¹Ò²ú´:@FÐch¨å| 4OØß:BíRžf¬¼!¢Ð‹9Ùçôi¿¡ij0öí·tVÞí™;ΗCØ……ëØ‡*_mèôE3{H$Ý•½þ£ý)sÀ¸Ÿ èµu¶”§GÃ9| \µEuü2¥–Àçò“ZÕO^z¨ôt¬Ò…‹£"éÑE'÷ºŸBGúŒ´çM˜n "©{VFðÏÞmÊ glÍBŠ%è±p"+žm•ccc–×eYjkØ‚âøM.èkBÁH¡ýpÕY 4°¯<Ø(j‰q„O>+å&ëͨV‚/Ÿl÷@ ©!—ËwúTA$’Ñž±9uN–kŸ TŠQêpƒsË2ïh…»‘$Ù7Mšææf/Š£Ÿ,7|Ú,qÆOžï¨õJ+O!¤¨YÞ ‡t.½ÅÊçPqqý •º ÕðàÆ'+Î÷wÿQ)5ÖÑ‘–Ù­Œ8ÅSÿ¥¥.¸+‰ð˜¤ÌJžNú<"S6Î.ïÆlåZ’'×Ys#w¡Š>©·(„AwO“é2)W«X[Ó" ZáOøà³Bb:ñÔŸ¿¶xU/Yú™c¯˜˜~ä#‰“à ðìÝJcåù:€RÌ3°@õŽ$U óè·ôÍù2ÞÄ´°õk¡$ÆÇV6‘‹ f‹òѵRĽ' tN$ËØ|M—Çël<×NÑŠ2ÒÆ¿D†NLJ`nû–ÜØCĆqËGY»„©œùˆ#ôðÉ:ÈÁ)¬˜›»#OX¸Zìg¹Sq2¸{_CÙää—ov\ž°×[HC¥N®_qyjxõÏ^*doŒ]E*ÖEˆî¼âR½‘䋯€è*0·€yé°ßsR;?3ÁýÍ–»»|8Ó×,—ª Á$ñ:ÅTDRôüÅ„/´“)s/gŰcOUJnÃ!$$±Mbý4u8Ä?ÖÀJ;–Ž0%Ù"çzÛxw?;\›]1wžhÙù »ø¿ƒãÃU†çùǽ¾Õ»Ë)ÌȸI¿Ö‚"÷<Ôâ<}¢Ò6y:´››É$„nvFÞQÉ}­e`#žGX½ŠÚ|϶@4F4 ÷˜.nŸ¯˜l ا ÜÁ³á¦æ)x7áÓ1 Ø“_LšMÒgaÒýíPÀ€Jä袉iá Oi%ß~bß-s£Ç=H²ãs#1ZÕ¢DÚ¶L¶-¤ÄÅ DÅ}t@b¶³;+,¤ÑP¢ÀϼpêºR`Ç,’ DÚF~ÂVhp)nRðß8PZÚù¯#ÝT¶ü†ßGÂŒÄ 2Rö='aœUkaF"õU¸sC1(ípþŠ«åävˆƒ­[ ÜHò-+ùöÆÁæÓ;ü“õSÇj›3ülýÀuÕù!Vv,”€%d»{<`¸’Vvõ@ìÞ9ŒŒ€ sÛÛÅËäNÅS ½šÛà_\Œ}ÐÄPÁ‚,œIf €lîmPz~xyš¾œ‡Q–ögi/ÕžÙ]5ÉJ»oy©:h»_O-RN "¨îXâ9E¾* _¹2eù>ç¼Ai¸ÁiNb´Úeh7Iß4.^o6Üé1O™µÄÅ {v4– è´Á:¤uϸöŠ %­Í  )ýk8ÿáñž½ÉÝÑŠòJ7n.‰îÇ’9(à GA{æ-Ey®"€ûhMBí—ÅT¿\|«dº¡»ß«æÄñ<׋+㊠ß3/³œcmïWØEÁ%^éÊ.xÿ‡Ÿv³oE?왕Ã@Ô(d}°~‰ìd ×|ßœr…ž§PyíÂÂZº?¶· G‚ô.P† ï^˜”eîH}è‚Ò!nðA´u“ß&x L¡£|¤¨Ðfl¥Ð(© {Ú¼E%EYÞàòzµ»¾$ÑUÿ$å]‘&¤õ>±I²é¥ŒDôo˜ !Ò©À@Â&i_ë‰å+f€ëD0ç(}ÍiœÊÐî8Ĩê}gîƒT›ôÜ@¦ªiÉbÈHo>‰B«vá?w%&¤ÇuŸC´$wy:Y”dy¹@Ö¨uÉsNÜácÅmÃåiãù\"VhB“!4¥_²]YÔ}£v DàJÛÖ{ ®”¹ê>¡ qð˜ËfYüăWuJýiGÚo$úµÐp9 Ó¦$‚¿µ{høi÷©Ì›î1 0@s㲉EŸÁîê¸wË!û,U6áfGú¨~È¿þÏÒSOG”ÛøF“üw‹à~x—וÈJ²”¤¡»7XÜ«BË2 /üÔ$d˜ýC®þ>úèÚ5½¥>ZðL#4iëQº›Ùp³gÊ-ütð2/·ù§3{Tøi '`r$¬/^X®ô˜òm°g'Ò„B˜3‚;€<­™¥[ÀOi·ÇKiÃéˆ}AùO(7“¶«`ÁÅDxª„¦bøC-Ý›x¨âT°|^ož(!ØR$iå籩ÐûWòÑÄ×4í(üÄXš˜¸ù/OM¢Óû5^K¸²S‰Ø°×(f¡ßÑŒ9è7¥¤*q·™’Ì\;x½°LÅZ'ë`RŒ/x’ƒZk¾„MóÔsÚ'“v–Ú5”ºîØ>§þˆ„·`èÎsžÝ ö;‡¥/k]W Aâ;°Î%Ç1O³‰ X±o`/Þ0œ]”/9u,È´M°a.&+{"é¸G¤†ÖïÞô&…ŒÌä›]>r$È~a½¿ÏÎIïå¿ÔªòÈZà>@ØqÍ ÆHœÔ a ,ZRÊËv‡º¼¬<ºAhžÿrF#ÇT{2ôýíñÆŒÛØÛó ®‰Å­0[0ÏD¡ÝZ.mÃÈ_,ã¡n] ÅÎ J ¥•F\öƒ|^+ð™n]®Ÿuå”Kãàláñ+Ž(X‹£¹ü×Pô ù²ó|‹oÞ¼?þÍ’s [ pÛT®»…„Ø,Ú³—g—#×Bý?û4 ´DBÊßÓ3Ò¾k‰ö+¿à+_pnȺFBG¯å¢G.=…£Ÿ„×Ôn±Û¤{ŒÝ¸â9AüFuì;©‘þêá­¹ÌÚJŨ°zF'®H@ù}.ñ°ŸÖ·g=”‚8***ÚäK‘ONÝ2-EÝE›6è¥ß+_Cí¤Ý¤3!]ß`Ò‡œXÝatÂ¥¦@bé•=sx’R> £Èq:òHÆ7¬8ÐúOã;0Á_;ª·>dw9ë•-w œa_/Â"éÐÀ%Y£ÿÁ×õäéqG®ÔdýúÅÿ—²÷±ô¼îÃÔ†‰ØR±5iÝ®‹Ëëì2c›Î/†É6¼$Ê á% kHŠ+/`½ÒŠ´‘»ra3èšÕfBhŒ›Ì&kÄ´÷CꃷHË‚©¢«é‡~´Há%"æS@ <°¶¢®uÝ÷ü{Îï<ïPIfvgggÿpvxÏ=çüÎïÏoýO¾úõýÁ½vëè¸Ù±–$Àù–<ÿ?ýö“$}«¿üä‹ý©Wîmê´TÈëÏÿß“ßÙĆÿ IDATóÇßüÉ'¿õk—o¼}4#£Õ¡¥½òÃ~÷Éá¿=üqZ”žý™ŸþÂ¥»›ùÞK/ÿÃÿ峟úè¯}æ3O?ýƒ§Z^~ðôÓOæ×>ú‰¿ü_Ý9üŸ|öÛ»ó©v½ßcŠfqðýßûo¾ýä³ßúÆ?¼|²Áˆî°fœ4äöí_ èg¿ø™ŸzüÚéë¯_¿ôÃO £Ïwÿ_ýìS/_Ÿ³Î¢ŸÜzíæÓ_|õÛÃÊþÁ¿ð·žü??xù51ÿw Ç^þÞ«Ÿþ1?ùäŸÒ #ã¡—?óâ?öø_øç¯~ö‡—;½ÿÿÒ¿òÅoýù?ºô6sâÊeŸ²ÿù×ÿý{/þöŸäoð6RÌÕˆuqúÖ‡?¤ŸÞðòÕ?øêË»—‡_F²O<ûÏéæÐ·¿ôÞ/þÄËߟÏ5yãßùwïý2­¿ô/>}ùÆ—‡?Û¬ço=õ¿þ ßü…o?û3Ÿ¾üÖÞÐuÚ®æíKþkïý²<.è ñÕ—ï?óˆÃØÍ3÷/þû'_ýoüåó\òeÙªùƒOþ_ÃóÄðXú‰ç¯.é:çåèÿ ™˜šNá÷£œÝi(!ºà‘.wÊŠt笖ô¿g>íõ²#ÝåŽD³ÝÖ£yô§Ï²õ ù@Þܺxáÿýü_ùÐ'>ô‘Ÿû±ó¸Ž¶l¸J¼Õüù×_üï¾ø©¯|乿8f¾«·©’Î?÷+ŸøØ‹xïÉ<ûKík¿wþðêk»×ïÞ½¿·wo÷Ò›?øé§¾ðøïÞzcÖï4^FT%Çýw¯¿pù×¾ñâ{O>9üÏÿÐSÏ¿vë ìVêÊ@}ëú+—í‹ò{¾ñ•Ÿzü‰×§kæ¯6³É­óøWíÏ¿ûì{CïyñŸúéá±|÷`2™ÎïŸ{åñË¿p‘@Gî¾ôÔqéêãôrøø¥ß½O®Åó»—.åïþÒ<µ}íõéÌ} }Ó:4lBoýØGžþôS—/]ÛÛ,Öe°kv¸’®=þÔ_þí¯ë?ôéË“=ñl±yûµç?ýÙï¾úä“O>ûKŸýôóœÝBò>JHøþÕ>ýÙߦ¯Õ{Ï~÷g>øÃÇ¿º`þ‹±'×_þ‰_|ñÉ'_ýí¯]~ëí©<ÀÉ o(Î_žÚ>õéçß:,æ§ÿøÏ~øÕËßy‹catÏæZi™ÜëÑá×^¦_kA_š•ͽ˜_ûÎW?û­ ŸÞ«Ã§÷×¾üŒ ¨çô‹ÓkßyêSßzõÉ÷Þ{õ—þàé¿s‰û‰M×óÇ^þ“o<Ë¿ö._zŒÓ†6¸wé©o|ýëßø+?ñü¥û’ÀÝïß<ÿþüwÞ“/•W¬l:|×zìæO}õ×ÿÆu™m­yvé÷Å_úâW¾úük_žÓO| ;P02VmR!‚^¶.£‡ÌÉîä}©©ÞB•;’ÁßCG:ÿyÉÜûÓ¯âó9Á³ÝùÏ=÷œ8§òã[!ÎÿØÏ}ï#_ã ;ä2ºAЭ ñܯ|í£ŸúÔ'¾ò½ç>wqëÒƒÝÝ»4ÚìÝ»þÄþíïÞ{÷Ù1'—·Ë%±ú“ÍëO<~ù©ý½ï=ýÔO=þÚ½w‡‡ª´¢•¨aÉ%hsë‰.?õ4ýžË/?ñö†2ÐÙ±a¹>š¿ýÄËÏ?õé?ùàgž~êÏ._=w—LOÓÍÁéÝkç®Û½Î%}_ïß½{÷úõÝk×ïï ¿‹èßwÏ=~óùÇ/í ÷»×¹ÎzRC—×ùýï¿véÓNZ`܈';üêÝ_þáåËuFM­šØüú—?üÔg>ø'?ñá—_l}«F«CåŸ^¿ôü‡ËÿäÓ?uùñ׆‡]ß•GD;”Ì[/ø§ŸþáåKüè’GÐðáׯýgß¹|ùù¡<†Un˜OïÿÚõ/χ:ÊÙŸƒå¯8}Œm±î:0øUÉA×ÌæÃcør~ðOž>=ùTG¿¼ÞÜíåË_}úOž~ê‡ß¡Ï^ö#yˆÿåÇÞú·ŸþÁðG/=vð „ÿë™Ók¯|çï|çå·è÷·Â± š}ìµïüðÓŸùÞÓ?q™ÿK‘27üú—¯ÿÚýS©ùØ©Y$ß¹ô}vÙ1¤ÒqÀ“¡ŒwÙ<€,épîĎ˲%Èåç{ÒqÁ‚¾âäŽv·¹#QR ­”ßúÐsç/’[ÐБˆÜpþ/Î_ÊhkK¯±Ûêñ0üÂç~ìü›\FW/ݾDªØá/:<<ÿÏ=÷Üç>wž(àç8Š‚„§¯ïݺuëàÝéɬïW;Ôgh¨k¨–¨V†~sôÆ­ëO¼òÊ ¯á2‚#˜ry:ܔȶ)º„—Hô½©ª¯ ßàS|Æ’t'ðVAF1¥Bºg;Òáù¿÷³¯ÒVlßüº-wY­¢a¨Û’‰t¯[ò+TFC;º}õöí7nßæ4[¤¤}îHdb´žÁW«a°£ú‡HÉŒå[Ñìèù»·Þ}ýÝÉP"K·8A;Õ“Ùäƒá·l&'VFfÒ¬‡ij~ðúþë©<[HìE`²Ö=èEÑ7•—õ‚ÄæTVÌûî•bgÓ]Ã÷¢~Fö(3ûñE¶áAµ~•l¦ ÉTÖ´È~öÌf¨á [ø-ƒJ‰”Û›ùë§òéR cÏSy6¦ ÉáÁ5™ˆ+·2©’(Ìuøíb%NM#ÿ¹OÒI•ã Û®˜wAØ$øQÕ>24cþôÖèG̦ù}ýåÙ#Íɸ>W*%zôo&‹ßï­Ä¸û4ôEZ÷M±”“¯¢Ucjþ(ïX@Ìÿ §rg‰®]³¾½ëÔË¿0h÷ï“úM8$•î•LEàžìö]Ÿ’ ¦°˜šþ&Òî°#Q#¹zxþ#¿ÎÇtšýç&ùmaK{7#™í¶xÕ(ï‹ÝmîITK4áÝ&çïbjwŸÝ¸†Bb—ê°Ûiv–ŠÜqÅPs<;™°±ÖŽVÑʬTÅz‹|Ö'3t-–bêôOÖêí8?†©zÙSKqkbÍŒ]kÒ̬¾¥%5Jýî¥+5L¯ãFÄHC#“ý ‹“ø§¼åVcµé‘ÕÈc=äû$}¤÷fùÅQÛši?Ìñfu;T ’Ö&4ðŽ7 SY˜ŠE¥CÇÖåÓkä Ÿ¸å^>ûœJ7¥/O+ŸýIþEW4¨EŠÅ‚éš2ükZÿ/e dus.Œ9o¸»ì^¡yäyÓ'¯ 9’J” Ín 8ŒjRM.ºnO[ ®÷þOXÚ®–á•j1åkÔJi¨Ü7—³ÆŸU‡ Ûð‰Âl(Ò½2Ýéé¡Ñ·ãc÷WõôˆÚ‘‹>w$‰SþãoþŽ‚v[ìIyç\KÂhàÑNKi[´±—Ñ -£s䲺ËHÙ)v‹Ù S¾Ùø„: mRK+.ظ˜Vg4£®ÔL[º’ÿY´é,,bY뇧ºE‰žp·oõ±Sï|-}§ÑjÑb’™NñGè±Ïn©Ú¡+uMëT°2¤—¥$<¶p¦!k‰J¬BíáŒAÝï–R-„L ÄW<» :Îê]/(×Nš.–½Èô·µ¼{Îú¨–‹âT0K±! Žº„Y-È9u{çË%ž•Ù×föÔ{?”àË_:ÑIÉ57º\e-€âĺîÔ½HÞR!í¿Í`ðâ0Cè' ýþÖ¿#wH.£-©"í®*Ö@u´mcáÞ>q›¿©W±Œv/ICº{ŸG»;4ÚñTGƒô£%GOð.$e´²RRè»I¯„!AêJ-ÑO2ƒeôxŸ±…œ–Ñ3S‹å³ÉÎúÿ®µ»³;~76Ãqã‘Îcí¨ †~KKêdpRerk5|g˜° eGúhßèÊ]Ê#Š2Þ³1dÊo”öÙáØ$ûUÊÅ;²¦Á'$W%IÒâhù*®Û.CL³c…¶zp„¼3þc2Dï!zXç)M%ûLX¸·¿ dö§”bniE×wbŽ''Å_uÔtEš®Kw¦Ö‘XGqá9¦§~òK߬p†›ÛÛº"mé!vK®H¥Œns ]ºÍ#v$í8i÷ûÜ‘îîîÏl áö£Yj-W2еl»*,.F¾WM=ÙiÙ,Ù 2T¼ŸåÇ¡Lacdn¦FùÓÉB—¥©ä·xø„Å®9z¹€uŒ+PAõÍ#‚*؉–k‹»“,7;M#e]ª({ï°ÉÝýÙýÊâÁ=IÛ[W’®,0ðØ+,!,¹<ÑÇ·òÛ±Ç.WIJ!h²Øn3¨NÏŠ³>‡²K(«“¦‡ÿ4ðóˆ:òµtmüm°k(_Ý ÿ‰°)ºò¨ìaÌE`.œîíKØ@Uþ‘zïKӣͻ·övi´ãŽôy‰SfI¹Ð¶µ“ÉŽa†-ê¼”ø„Ä醷#™ìl¸Ëw¤SŽy#’Õh)œÕÕÒÈ Kœá–Њä3Ì_ÆoEVúÃ[E2ïH6ÚÍ£[l'u¤1.fô½ÖØeÙÄê{¦=瑾·CR£JYu’Râ¹o§/UAš¡Žt_×u¾KaŸÇ¬9-5†vÞVºìÓS.r¶²ŒtðH+-®û¢f4¢å¼9F¹`8‚M>÷3ŽãN×m‡Rï › <ƒøÔV)ïÜ?càEr°>ãg)æÚ•ª:Nà‚‚?8f©Ï?!ŒùÄKÊ:Ò¸ͪ2²"ê{&­–Žti×Îþ×_%Bá«?˱|C ÓÝÍRHB²ÛÒn´]»|A¢X1iG·bGfÅ×tEÚ:ÒþÁ•ÉÑbíV+^ŒhX1ᎻrÒ¬þÙÊXßa²ë¼3ÉT·,˜›RÖ/‰hÐS2ËB6!É-×ÙÎzÑBƒùÖŠ‚k?rÎ÷#ú–ºÆ: „bCÃg¤¶ƒ±ë5#Øã#»Tå%©¼TRÛÅ'iûîð“wÃÑT!°„xopÙNˆ;'M\ÊÐÈ´ñÅtó›TIB°ÍHðëü¶#à<.2e.ç‚ÓiN ”fÆ­/‘ž=‘fé_£dÎ~‘.aÌ¡'•"rÌ®\b_w‚;’TÒБÈ!’:Q{ÎkìÄ×YÀÇe´ ýˆ_ë®2âMUDã 7ÎédǨÁß{Ô‘ÈTû˜ØÜ;±k H¡·íHÇ3éIõh§=©[jÅ]‰f;ؑȋxˆ~ð2*£ÝBQo:ÄÎ gR)UR_æ:]”·Ëc˜Á=?ÅÎŽEe_˜Ôc 8&Ëh’àwk³KprqÐ*AöIiÅX\þ¦B&*x,c]C éÊ•+ÓÍ´o»Œs'’ÚlcÉ=àb¦Ýº ­/@”ÛÓŸÿ,ù](ƒ`"䡬‹Æl†Å6ßy&ÒCÇÊaA•žÔÛ›ž‚Æ®¼{ë–ìHäˆú‘/~‰ ‚iEÒ^¤ CYûÞ.÷#…¬”³;g Ó†ÑŽQ»+ÃSƒ =Sì"ÙÉ\g –üûQÏi§––ªGf»ÝÉhÇ;’ÊT‡…¦\ Ì Pƒ@ –r9[í£rªD²#R/V(&𕙝§¢RAQùSRù ÅH ¥5ÞõÊpðdTª%{Œæ¸„g ìÉÞ8”á ‡Ç®š7S ±i•u4Ý\‘–D•Ô… Í&¼ †Ë¡eÙ†X`ÂD°¤œƒ"¯Œ9lŽHNÅ¡éÚçË¥4d‹!Ç Íœí=:!IG:î:ÒþþÝ¡#=¸qéöö!vdðO>òcÞ¢ éê–1¾¯:Ì Ûߎ.ÙõH0ëF~sC¢ÑnhHÓÙ u¤ÕNã©‘*"îÝj¹ åÒ´0Ù-íýœ¤„d¶ãõ(K9q a²‚Lv3N[Hƒš)/HcùÖe=¬Nޱ}QO(”Æð·ѬŒu½žiËCBõdZžŠ-öqÚ0¿åBfhŒŽS=@7uÌÕåpi­#GðÇ }-‚Ó†;—ï5úgˆð´ ¤áÊæÊoÒpG‘¡ëЈT¸òÇ=1ù¿$„†ï!ç›ásÁ«Aöy’tË•2 xÅq1=9° kF3e@Çü‡`Iê­#ÜáÑŽ;Ò°$]xîlIø,¥” PWhAREÛ¡Œ¤ùñHzÑÉDŠ‰ë¨€ß“[ý‘1T‰Ôª:V²—c?ÒšZµgœ–†7¾Páà óA–Á+#a2X>Ÿ†‰q#Zh/ân¤òrë;½"àªÞ“Nd’Y¥³ÊR#8C‚§Ñª1¥º#8ÇÒ{ƒAr–-;BdŒAxj> .îÂÃ7è9ŵ½´ÛÖs „:n,|¦¶çØŽé•+Ãp7¼n¦\J¶c•]ÇW§ìk.,èô“ ež$’]²½Ïâ¿$ÜžÊsX®}O2 é½ã‡@{GH'#Y9”P¡áûLG¥Ô³gÃÁ¿ºOÈv[ç?ÿ 2+ýÓïº1±‰øñ¶"ò>dutNㆠz ˆÝ5¡5ܽO !¹#ÍôŽÄa}ÍÊÏFÊ]Å¢iU¨5¼{( ~)¸]›mQ’Ž´¡îS-w޲4¾¼l@¼ú8ÅÎ7$têm¸kÇ8CFĻЋ ^%å·X%åʾ<0€sZ ¯«ÙѺBð š[¶â½¨2Ÿ‡åL ʈëhø?I=‰Þã¨Ã¦-+`ùk`¢L!hÅ ,xi«ž:44 xC.ÐÂv¡:“(9ÔRào·ñ>1ù„]‹4|LǺ‡ Œ –X ;”Ñ-EínÖðßã3&¾º­ÃÑ A»oŽª`e¨{ð@çºs»´"cõîÃ÷÷þ^óhÇC«Ý§–ÝR;{•#íªÔÒÊ© wPЮØ»Í+‚HÝÔóÄ&(÷Âr–¹5 ¯Šyà{m+’/@k¾›¾ ©7ƒ.ÿôZË ©«€†hÌQó“})òûGÑËðlÚù´pÂrP Þãwª®äâ94¬EÀ8Í@p­k‰…Íýˆ. ~%g§wdÇÓˬè䨟v‡ðwŽ™–Ö{ @gñd@>»b0ö&Àæ‰ûXù`g éä¸îIü¡Y˜ê¤!“òçÞ½ë÷îÝåŽt㪮HŸüÀ'~å/µU[‘œŒ¸]‚N$ØÂmFö–qVPÜ¿K1x{ûó‚ Äb¦êN¿ÒIYBŒ/pZ9r¾}OêZ£5h;Zu]5ù׎öBZ"ҀؙŽuÊøÖ3¬ v3¶å>´6Ê·AJ-©ñj;RlH¶ÁôtÆec .w6Ø»•fò&O¬8?Âã<‡èTœzòÈüÚAŸí¿ž*_[ΚõLê‡rÓÐðÃäˆT]ÃOû¶ü×3~®H¦EJD’câÈ»íR•ºìÈc 4¾‚Žâ±ºÃcpÂK×”ÁßÅÙ®ÈÍ‹9¤nͪNRrôν'^xå…ÿò¥ë÷v¯=¸qiûÂÏqì%Ov[ÛgWÑí«B_ð*­ÈÊç\¨!É-– †»,Gš*üÍ8÷ŽV­BtKF”B­,Öeà¦ÚÏ–Ž4(Vǘ÷$Ö/ð‰A[†¦ú£aM/QÖ#Hе†Ô¨µ‰Ò¢œX«‡qA¿Eû a#ü­ÌŒ§vÿ¿?~ª…E¼5ÝBùƒI~ÆÕA—«Ð‹z`Ëd‘m'Š÷*ÜÖàoêZªœ ÷!Ò‰ökhPG2ßIT -̰Д6d%-Ñ®º» ä:?Äç§xFŸqʤYàNP‰¤sÝ ˆË±;ôÕ†t|ôÆõÇÿ‡ø—þŸ?|áÜî½—†î²õ¿òOØŽþ7¸!UÇ"jB·‰¹Àãœ7¢sš¶ìetíܵ—ø KedHÃýa²£Bš(ذ¤d$¢…Gô•N¤0C_+*cè"ÇNP;åØuº& T I ½À ÆÀ ËP¿¡KùJ7’¯¸Ø%$<'AK kTr†dÆî Ü–øB]WÝG F+Wü±V4ZÆY(§p –Pê“ RѲîqèAS- ¡ô¿Ã®ˆ²§ž\®ÀÈ#ÏÃÉk þù@/´s Ë €—»ð2"…/2ãµ”,Œ¹˜Ú½@'¥„dOrRPo˜ÝÉ÷ÿ£ÿþ_ñ§ÿðöƒÝkçn\½øÜG¿KödÏ~ôóâdz=Ö»ÊÈkH^ÏݸÆetÍ i("ÙJfG…4çŽÄòqF½•Á B$Ù—nN œb—í™:¤‚Ô­JÒ#’žZCí¶l¡ u¶ ­ËnÔÏ‚ñ–Wˆ©È‰Ü]¨ªZk:Ø £§Í]D¾õºpSÂEGIöªÂƒ»®Ë(OS% ŠôLï\t 'HÀ) /’E,Uÿy$CÈL¯cla1빊Tp×÷ ¡ Mf½ñs¼š9S;%çÂ4[:Q ¿1…®´ÀÜ…6‡o|.ÉÑÄ–ÔøûŽMsÁ.$Î ³Ñá9 ZJGïþÛÿùÅ¿þO?ùä¯ÿ·C% u$´†oþñ—¾ñ•ÏêˆÑíK·q*lT¡ÓºFÀt´R'p•/HTG{§s:Èž¬yG"ÈNޱríÃfÄïíŒ$~­óTËlW¤±Ô’ô¢4TÓN£Y½{¡aå¾9•Û ¸uÓ¿:xéõ@«8ƒ"ßkQÑ‘rÊQCœ!„h[v8—™ìÿˆF)EÁN élÖ,sF½QPù B ¬Öw×Ðõˆë¨Ñê×N V~Žl|&Ë:JÕ›E”9 îYp¢ÍZŽD‚…xUÈúWYžJgCøûŽÍoÆm¨Ô{wt¤;9ã{rtïñ¿ò÷‰ôâý¿4}~þ£äªýÉg?ñs¶ Ý®_´|ªmˆx@»×d”{i^¸ŒxAꈼO6Ó#…¿eØ5¥~è~¤›‘ÉL‰‹×…–Ô _)£•5£N«"i‰,ß\åð*²#ÑÊöÈò&dx¤Q¨N†:íI­ƒv Ѓøw6æÏPË|ïŦ(צ¶ Ú”g+@,í,¬>•²Éˆ:&'Å]Œ{P \ä$T0%„ÍyÍÚêˆã6svÎ`;ô¤ÉÑ0Ýѯ¥òïs¢6l |v¸\,Ñ‘Är'À`e¨)=ÂÊ)ƒö"a«øû!kH'Öt³{èl˜A«ˆ~ë×ÿ%å‹ó“ßþØÿú{ç/¼ù¹ßûÐoPÑ—¾ñ‘¡!Ý8£„è44*"^ˆv™¾`ßíå>¡uª1§×½ýa´›Lïðh'¨×V´Ôû‘ w;¼+í´° •ÁmNZêºÍåKÅÔ´½Ý‘´#i'òF¤-_0ƒ›§6ZJ\×B&]7ÃŽ—¨á|ãScÙ†]ÚUTÿZ’íè‚Ã2êl@‚!×ʆ‘»‘soJ,%k%YkY-x°c§¢@W`Mwt›5¹«Æ/T¯£‚$ÈzÝ»s,»„jÀp‚9 Aÿ(Øíg§ÓN›ÐCë]dG}ÁífAÍǵôÎÿRB(?ùäÇþö×>ÿ‘¯|⟼J¶¹Ï~ô¹ Wo×»P,!2ˆ#8nBŠè>ކn$¸7ÏuïñŽÄ¨)YØ­”Ù „:ì}hÊ~$'ó1AD IDAT¤3m„ZÃèJSRÆ¢ Ò  þv¾ÊÇÃH'sÝ#‚0P_jŽ£í¨%› ÙŒt‡*‡ØÙ•'CÀ®à¶aϘ9:½«è-\»À/ÈA¤ÔÁè:кËðü›ñ˜Ô¥ŒÇ›Öø1/‚ÿâ¶—‰K¥¢°Ò}i*Óݬզè&¸0Â#9£ç+òÀsµè)Š‹ªÑˆþ'°ñ™"Ù <…¥çä¡ã÷1B¾ÂŽD«o<ñ/¿.1pŸüg¿ó×~ögýcrõäÏüÊù­«XBÉ=pX›÷¡]A·±Ñ,·{÷±»Ü‡vï3ŸahGw¥!ñ=v3t$íVN Š5Ò¶@UE軃û«Õ’0„èý¼ÊÜ‘†2¢‚Z¶¶$QÒöZ¡º™u܆ô ÝØÉ¨a dë:ⱩžÈžÔ†UÝà0™ƒW7è8.å#‘K 7¹ (é‚=ÀÈòu>×Ðy¶Í”»;4½Ñ`×·c«+Þ“¦›7º k`Èí¾*áH7¢ä¸c͸Kï‘4”‚ÞÞ AÖ%·”`©ùCâ}òTщ}û‘/½U]‘†Ñîÿ½X}óO¿ýgßã$¹¿õ­¯|î"YÑé'/7®á'¯±éBĽè®|ãåè>È= É(Bê»Å\;F¿‰1$(x?RL,Ï0j°)oÕ¹>¶ xÚ¡ØC¸—EÈLMX+±.¶&AÛHÚr¡§Úh'S^x›µû5hé†D%ÜuÕÓ#xìàÅ#¹ƒ@t4ÌñØÅˆ—ÿe¿ÿÀSô88çÎ#Q7°Q±´¼¥ubq¹:ÃÚˆ´•Éß¹¶$¢ßña¶‹Us Mj8°tñD cqåÕPÅN‹»Œ¢ÞH½µÎwçÎÉ~9±wÊ»³áÕ_füá}™Ïf͆·êêpç{ÿ£okFÂ'ÿøŸ~“ƒºÿôÙ¿Mƒž…®•»áp|•ôðzW H¾í)̰·W:ÁßöF!cýªç7dÞ°#ïò¾´4ýìP`…5 îV]ÝÃÆ‚5ô.Aç¼ÞYu¸ákSЍ·Z@ݺ–Aãä!…{l¸Éæp˜dèÕ-$ê‘pB* AÛ~Ü$ïàÈã= Eáñùˆö·v|ÖVzÝoUÒUêqû£ílªVºÕö&éQ‰ûYŽŸ‚sL ÈÉ Îv¤·%vÊ)vbhø]:^îз;GþBïß™ÒǦwì•>àßøþmøáûî/ÿ±gµqÖ§~ŽêHZŽ!Øõèf¯<¼±;WÌ}jB{÷mŽó—Ó½ýÓ½ƒÓnHÜ‘Nú3_–00qõ­¼O"î%™‹,û¡¤¨Òè§K¯°n9Ú£–úh/¸‚lI~víÍK«QËáuiDò²Ã ì Ä–&JZmœÏ°† ‰Í k¦KÛì‘ÈÌŒçd”+e_†G kÅ;LK ¡€³Qp°Ëˆ-"Q½‡/Kô7rsm±FQCדÔïà ÿ¶ÅbF_w–«1ýÐ…Q©›‘6­Äý‘ D™­Î øûlNÕhghÊ•£+›w6G›7ÞxãÈ_7GÃG†·õ«~;šÒ›Éðå8šêëæÖÿñ‡ÿ㳿ÀiP"õ“¯~ê_\xáÁîî=«”Ðe¾{ÿa&ŸR­p§¹Kuò°—Ì~ù~:¼ìT/rlR:9^ÓkÂË÷)-_çõÝÛ`ŒnÔo„FuÖðëPD­µbYÜÊdÝ— <¹j o®iܦ®k„Šn›ÿ¡Gz7¡£¥Lì‰Gä$~e·\HÄËqøSmN¥)œòjëS‡3h .Jid’º®vF¡ßÐ3âÉì:ê6S™ìrt¾S`A€»Ÿ*IY¬L"*âŠÀ/Ä€½l¶•8ÏfÓ›PFﻌ¢ÇÊ]© •Õ'Ð¥ƒý+ï^Ù÷çèõÊÁ;ï Oûï ÿ€á½á…>ðŽý_Hü5_’¼spýßþÖמý[œ·M‰5ßüÒ‹ú«_¸}îºVÍÃôfß±byxÓ}ªœqÕxùØ«œ¿w¦3{9:Å ¿ÞÌNÖü­çŽe9^÷?ªÎJµñ8H›‘ž|ÎvW@6·ÂÛ(hí´-Ô‰ŒèÚÚtm!ÜÙ6ð[ç:¾Ótƒë‚¾³öqGËD8ƃI*—”¹…µ¯ iVzPŽÅGT¬² ÅG³f3tf±v:탮"è8šÙd3<$÷¹)QB÷¥¦Ë¨NsŒ4SG5φ`¹‹v²áðš+/=WsDæ°¢ û·äõ_Ñ÷ááÛð.ý°¿ÿúðöà_ ?¼{0|Ûçïà ½á¼C?ðÛw÷ï]áW?ø±÷¾ô§ßüä7¿ùËß~õ¿÷G‡·_º÷ð­½[û¥Fè½/–}ùËö½L®ÌæWä'ó+s®˜9 ú1¾L¨+_á#¦œ,fPQ†Ìü½µ¾ÓëéÇ9ÕÎñh4‘?ïa Æ"æ)Ìܺõb¦Ûцž|™¹À¤ÎÿžÌ³Ý•ý+?¿¿Ù¿2çJ"EeÓe§8žĸg(‡r˜ïÆÔˆ`“ ljfÇ9h ø—>~ox¥oç·oüã·Â+½¹¥?¹%ß÷oÝâ:ÓrãòÛ?¸uëÞƒÞüÁ×þü[/¾úì‹¿ýüÁ›/<¸wë•É>–ŠÖ¾·™Ë4|F­XÉHÿáÜ‚M'C+¢2:R>—ÃÛ}[Üñ÷ÉP^'^X'3xYÏØyx;ÔÔq±bÈ«é›Ö ìµg5 ¦´Õ®7bÏßebÜi¬•©yNu^Ic¡¸çÈjŽv=E`”ºT|æÉLKóhŒ“æÇ¹ÑøƒÏO¤…Nv?¿ùM^‘<á+fµ¶C! ³ÑPF¼ OXÕÏ×ÛQûò¿$;£Û©àp|BŸüЃ;Ô%¦‚jvCÄmì´•a ¼wïú]ù6¼Á×òÎ}~ûö½½{÷¾7TÚÛ·îÝ¢ò»wëîÇ÷†ŸÝ¿%/ß»þà…¿ùæýÕý/þÅ¿þ£ßúÃ\ÿøëÜbèÛ0@c"Í€üz…®Ã7ùኖËð“#yo(¡P¦ôvªkØY/Ão™ KÛÄ#!Ê;Gf(¼Ð¨5'±¸lXæÑ½VŽËI”­Ð²u+–¸¡ö-_~ûЈ¤ uRF‚Ÿ«\аõ†ÉüWðr6Œ‘½8«ÊrÄÐ¥òtØ’2zܹûòü3€À90dàZ‚7Ø@±’›â…™sÈOÍjupÊJ… ˜´ôºi[)]™n¬#ø(ã€o®Ðº!‹°„º´máXñ]î@Y™±³æ±Ô°‚gâ×)Z’‚¥xçÆ²6&ž{i×_)ŽßÊ·ë»÷蕾ћݻ\mÃ÷xï¹Gå§ïËOw_ºq{ûñ?üÃÿ¹}ã‰{ZÍòzdUBucÐ#Ó£‚WHgyߢáÚPqA¯òQnSœóu4ÙH¯¢1_ŽJ•-ÔUJ âÕX »C¹R³qá ‡›R^¥bœþÚ•co[jÉŠŽ×1jMB{à€1„Ðþ¤TRWïöit-ÂÒntƒ”Ëm°öÒ ÜrRÀ·‹ABRkþ°~SÑ30ü͸ ;Ç‚f¾T*íHW¤QÍìDÀ%ÅǸƒ•æÕaçæÌ>'§Î!WÏ¥!¨‡ìrÔóŸz@ ”hÀšîü:|{‰ÄÝòJo¤Úøî¨\nCy ov_zé‰'žxéú½[ûW6\&\(T.X$<‡ÝÑøʦG3AÛ‡!løav4ãKÖìäÎlx;žÎfôÇ©ÇcàDÞÒ8™TU¥µ5£ÿ¬T•Ö”•ÔzTù¦>¨Ú†ÚRIjáz&)¬«;ïÚ‹¬O4ÙQ ݈r`}wŠÞÙƒ0wx)êœI§*¸ËÛÃ3ž|2ÊÞЂѷ…ð¤ìxvˆ¹¬G?ØÑrêÛ…­¬y/ ±MQeØjwÀw¤^)¼ò0ï”+ÁSHøŠfˆ€kh»ÌŽÀ¬IPçF$”­$üZ—7ܾ â†`àC÷š\U‚ÏP_TgÄãÊÚÒ°Gí¼C5´àî1ã2»C¥qµq"ÕAÅqG«evrÂp›|ã×5×͉>¢O†Uf&·¾ÎDšÌ‹Õ°ŽòwÙ±æã‹w+.*îW ðfúÔ,4ª0f@mÚè1ß@ëA.„—Og%e/ÚPÌO¼í5›oG·¬ÛŽFô%É}è¤3„ãd EÈ)º±áEá`Ü܇þ UDª•â±ÜM°Pd¡›µ%úwÄL»Ô¡ðÝè-ß‘6›;ëÞÌýœ˜+qã(XÏK‘/äKy”V |V”àÈvf¥°}õñÊ~[³º/iZÞ¥7.Ýc{«5±>÷˜TÖPH·ö†±öhzrr,•1TÉñÉì!zÿ˜ª„>,AK'%sI™{3U7Í”ÂÇ÷ ö„°á#éˉ(•7’æJ Å_盃XRýa¢U5núÈ- ÚÏy½¶£®sÓ!{·;ã› s.‡È^#m±½Þv¬BGêœyWŸ”jç“èüæ«8j=# ì¨2r¤ƒÏª_‘…]ˆŠ„”Õ®²á~EÄ…a&'ƒâœ=­Ø% ¿a"À^ J¬ÂQųXFÔX¹‹ä‡\øå##Õà†Ô¡ûl4‡ûД/}1?õ—«Å3+:,ÔÎÂ7Hâz IÝ®íÞ}øÖÁ•¡Ž\GÛ»IŠÖA¨ù²²·+{X'vˆ´\Q% uÀutÊßjdpxá’š—f%e}jZjj®øælR<ØY¡WWû2¤µÂy×ÉÝè’Š?i­'ue½jvÚÒÐZ²©óí(ô$ü,J;ˆ¤‹|Õ ²*CÚ‹O[¬·c"̘S2\íz!émW9és½àÿGÓG0‚ŽLlÁ %wPòP24Ïp~-&)©¢¡§4rœÍ9¸›ä‰"‹(×U‚]½”¤˜ü=/ªKôíö%zC-ëöU0¡{éîÝ[ïnކ.Dýc§.x]SÌ%íK]¬Vö+«•úÿô"ÒëùÛÒ¬”¿C¾§Ò’„0Äoå=kKr”^µ’æVM.£)Á\BZE“iùÔ³øhIÒÑ‹:E–LW§òÐט¨¦v7។ÚÑ?%Ö Ã¡oñ“´´¶ÅêSãÂU6³ªN—²'8võf«#Gà`ëˆèùÙAÜ•Š!ƒÏœá‰;•ÿÚZåH}We'%õEáÉnºØ©°·ŒM7ÁGð[*¾¨èoœs̘H`-†g¨˜Ð‘€ýïdví=ܦ„ä›ROà*ìí Tôu¼}Õ]ºU!1t¤ïSB25Ÿ•LbCÅP {S9^ÅšZÊRiÃ/6¥î¨ï´ÇœsÄ„Ó%ýŒ¢'úŽH^L&ºÞîiGâ¼\ªèž{ÀSÞPBs] æIp3âRÒŠ¢ð°eIVùVG´%IGb™CÔ)h ’zaSɬýCê!ÛnÔy‚•œ•¤'1‹B(xoë:–Q/×Á-U;ôVMèFšðaä8À*‚kI…]ê8 Kx*Bšx€†íI<«+ȱà¨ï<诩(¸!õ]%àH(Ã+¤€‚§ˆï§tFyêÜÐ9ÝÁÐZ¡%:ï ’í_¶8—òæPP[PYRõÆÎ{èéxŽ;ÒþÁÑ0Úõb0´’oǽ¼¥ª¢2:Öº¡sG⬰ž*ŠyfAL¯ZDœkÙ‹ –ȤaØ®†Ç;v4Ù휞†Ö¤W_.¦p‹´3M`Âcô\û¯LW¾(I–<ÚqGâ:’>¡=Gº’}Dû¡Œ:ü8¨Åy¶kÌ/ŒÏQ|C ôÔ2(ÚG»Zmçü1ôªíêc4feµäh#T=§.çzµÎ’ÑÖ(c’8Z,Ò>ü’ÈÉÉ—¡{+a+týT6¤Ec´ëh/‰ÛZK¹Ê ì¶­.Ú“ùóAàCámh”j3:"`<Ї¾y=QÝ, *ÔÓU+¨mtí–=‰íKÎíÞÝ»uE:ÒJ["ôÎJÜ$­s-¥¦¤œ–ËQ·â”„商-ï”ÑnBEBe$¯ûC9íi%è˜GM‰ö%›îæRLE󦆓+úàQå†7p!‰°pÚÎ1:±G)ÝCºQ©­.;T:ŠÂÚõ²"ömS  tå{­õCý¶›BŠÃš—TÚQ[šM«`\™ÄÚROÙPì%0pÇÔˆ¹!Qî²#S4ßyAåÜ!íò&@P¤¸´uqHÕ³)Ìx#OýÚыЯº©脤IŸ8+š5qÁgìpr´`×-g^wDé¤í°!»µCîA”bò^WõbØùF˜ù˜¦QQ9⢠0?±\”—Cy½ÜÜ¢o4õmk"¹·()%™ïnËš´»{— éÎÌêê½u$k7=5$îIK*,*%*#†åvä=)*ô¤–8Tl%ø÷ÄÀzÝŠˆ¾‹`‰Óœr :.Ûx°,m´Œ½ãޤ°•«Ý c†-ï?ó6¼Î>¹+Xv"§rƒÄΨD"âØ)V ÀUÍ&µî"¹a¤ÌKÁ7´’áDø9zxweͲ.¸»†$¾ \Ї L¹k BFŸ­—#Ú“ÖîI‘ZGÍLƒ+G­\ÑÛAÐkW˜¤J iC€%ø]·K£çŠÚ×YÿµTCK5II{ }‚GpAUh„\™(ÅèÚ=J-zcí ï–jÒšêµ9q?âFį}™àøµÑXöÃ_Ñyź“T»ª®l˜ok# ‰Ëgï”åKÔ•öʪDoæ*Á8°RâUin 8¿ñ¦DeôŒá2Û‰¶·‹iÙŒ —kñ„ X^ •T w¹xo{R/‰hß-ü!îBVR\ª â¨eõQ ~2HAse&dSY CKè*} îh1ÏÅM(©’d9]ðöIjzjTòÇîß¹¦¡WéÕm4ïe¨2§x²sÀ( N¦ä×9Îò[œAú†—‹ /Yaa‡Ò5Š ˆ›<ìÝÜÒqï*7¥Kfob£ÝìŽÍsБVÚ‘lXqê—Œ2,õ{+݈×"ú;ý ¡zÝ¡ì–Æv¤£É\æ:nDTE¤Ü£öuÔ+óÍåR+#Þf2wV3ŠÁ›z'ñ° õ°ãIê…üc” G ·Ë¾Õ KfA+vJohÛ1±®+ðw4ŸÎ9Úñv5í¬þ0ÜJ2frgßÐ#t•rí¤˜Qæ”3ÞYRpgD[Ô yçnr5<‘ •4Qu&Òý)Äý(ý]ºZˆ7!©Žgpò¤h~_99Ðér×UÅåL‚H½øè®¦áEKê0¾â¤7”#7æc,‚ZWÒ0Ú½´{—‰ ³nF:Åé[œê¨€dqZ*Êmw&‰°l¤ˆ8ñ;[hÂþ°du´c“ižHU‹}éÔéäñ‘V®´sÝ”¦=-ˆ©D%Ï’[¡œBK²»t¥6ãŽTn¯y„[³¥¨^dwXKÑj”K±Ô‚Ãn ¡«¥²É'˜èuçAXAÎêÏñZ¹H¾OªXhà9ï¢ÃêNœ7-‡³#=÷¤£Âï¦åÔ3Ôr±|Èn¾¢>>ÄWÖ\Þà§’ƒãq 2•¨øWÑá¡3á?‰Ÿ‹½À¯ZM\Iú&VT|Ùˆ|û¦ wWKGÚ{Q;Þ_Z È éXOHÒ’ â–ŽÔÚ'¸Î€íJªŒ}½©#-¦Ãÿ†ƒùéÁŒuÜ‹ø;ÕÐÞ>O|ˆ<(ì ü¡ˆ…O —E险Q…$:LÕB t¤¶˜í+Úà<†x}-ç ¸¶vYö#dÄÃ(À˲•º¨ñÆ|Æ.îGÈÙ éÊ5](wõ¬Ÿp+SÅ…„Œºa´êbUßqlM”ÔKíA…yr$~à‹æË‘×…Œ‘måI¹†øàQÓs¡©¡› F»…ÃÖ£ç/œ×bâW+§áõêIª¨ô€êiK=Ê2ذyczçD1»•œ‰ä8»´ ÒªìGü³¥1€èö6´r[’•á ÿ@;’v$*ÝÌ!Eë‰å¸v\šëuVëè îI9ÌN$²g¢¸åYiøï ø6¤‚zç6.5ÀgÀÉ.ᬳ툵H½üí•ÚuµGBë•#΄>Ù.±r/†¹‚csÈ¡pý‚³'ÕÝ/Ö^Ò‘N‹Ò‚ˆB^Isíè¤døt³ L¡)ã Ô‘qå–¸—ÂQNPÎ1öµ}ß¹.ÁI¶ê÷NÁ†R~~ ­;`ZWª{¡è:ƒb´EÖùÉñ̨PCì6î¦ œtÁùjdð`b7&[Õ¡’6ÃSðT0ïŠñÔ ˆá yLLñC#X>R^Îd®¾Õ&lçäì_Ö±Õì£çy®£b¢2BØáQÃdK¢nt¡Ú”¶4¬œÈ Ú‘n1ü­Íˆáº¥ÞLJ“–­q¿—=޶¡%í¨£|Ïk!ŠPéHT+:ÍÝ?SVEíxÀà ‰ HÉB60l7㇅п%¤¼·“©†b* ÖVJ‰¶Òw;Ŭ¤`9Ÿ¿wz!­ÆÒñ{Tꢇ]hè(P GS·Úxt±„™-§˜ëظÒëóT˜Ø`¦d‡5&¤ó‹YÊ¡êƒP$a/ €F¡;¥-€Îæ‘2à“9ç×Tã’E§žrusÎIV$CÞ´¹N±o~{(£ÝÅ5Ø]vKQ»ÛŠÚí)³¡/ ar4Þ™bÂÀ;éIÇŒ6ðok¬UDÕBWªˆêiÉIbT‚Ê()u´ï _’¤#™¥+ˆ*6v”=Ø”ÁΘ«[&ŽA²ùl´3ÖOáz·@§kõ!´³Õ WìoX#KÿÚ å ‹£_êŠ'8µÁ#ÌóN3Ìgá2‰^‘)Å'í÷ÙÆ¨ð¢|ÎUVz®3Ìq$ y+¹‹š)e=ÇÆŠʈèSqù §vÈäÎù æAN]àcnÅÈ„¡I•ý±ò“­`p-~ôüo¿ H÷¤óÒŒt°;Ôì4"ú®}éP¥€Ä^- Ý¹Ý»÷yGº£Â#ZŒÆ°ì—;:ÝѲÄe´ä5Ià†ž¹ª<ÄíÌ.о•ÔÐ2A]ìdvg¡;Áv§YÁ¡zErC‡ùÖmHsSL ²ØnjÌÑǺҼê²¾ÔÈ °Eê€Kû¸–vä{ƒ †…Çˬ§#U£åü)5ç¸|‡îTQÙ2f´ÇUIõ)ªCKþ¨8Z¹ìüm<‰—2-Ö1ä+w1ñ8®3˜¨Þ…¾g*%܃2”D¯ƒ—~ ¥: 7w•9Šßå®DÍèϸŠ.X?ÒåèB©%TÕ ÝŽG» 6ì\™Íf@ú^q=µ6Ñ­Ž§Ò¯T' ¬.ù´bº¤RPò†zÒÊàïÉÁv{?-+’bv2Õ•S,sW‹ö|b7$îÌ]èœëlÇ ¡V¹@ÚoŠƒž^[kMù,,âß´$ÑrÔ‹A¤ võ’TÈB¸o ϺZ”ºàPWÑ‚¢ý{°J£M àkÄ6£” €ÁrðDÉ9@Ðøwe¶±£g­U—£~5£¸;6†‡ÏÞLCÐXe’Ò‘)†Y«(CÚnÌfÀ0Tâ§Ø7 ¬ã2RÈNÀ©#*¢ ˆ4Üă¬v¤»{ïðhLj÷Rƒd¼3Kf1ý«nJ (”£«¿O¥Äß´ãUª•Žd¨²Vñ+$æ4ÈTw*üoª>ÅlÀ¿Ño;Ä Ö0á2šÚi­ø´ÜZìHæuê'Wn é g¡VŒ‹y°cÜZ‹Ì±Œ —9ìÌì³s _®²Zjàóë€F˜ ï&Pï@M•Síø ½Ñ-2Êø‚_ö 3\™}<Ai«oÊ÷‹:Ü™¤âBë.ýûpk‹uI¸#í>l2 #Ú-浪ŒU=5V6;Ö‘ô»c'¥Ð’¤––lÒE£Ý¬0Xc¾wZ&;?Åj ý¸ª(JCÚhÆÒÄ̹6n®Ö\ £~SK™Ckž­B­v!`Öµ£1n`it…â Ù å®mÝ«CñDeV˜ãÉÝ(¢‹!|ÀØîPÖ—nDVë"9:E¼,W_J˜ºԪΒËE+îÏ)kÍš¨EFžŸ –^èô9ЉÇì¦cáÆeèË à ÞÓº 7ñÜfpíœú]’R®».HÃ`GKÒ€ Ü‘†‰¸v3AçdpcÞª‘Ä¡!*†UéÐN–$¾Éж|UhvâwÇ"8®¤Åu$™íhŒuÒ¡¸•bRÀNƺƒ#c(ªŸØL•f§" á­{·l0g/š"-Wnx Èu•XS%HJÑs˜Ë)8õÒb‹§Ô*ó|÷ðƒbF7c°Éþ|ÛU6òp›ŒXx®wÇ|@Û;Üûs`¹¡´ˆ@Ãè\p²à#\q³ŠQDHµMU-å\¥°e„´+G xjJà¡„ÀÞ’@Ôa+’mGC[’ð¾õ¾X®HÂXwshF‡ªGºq5îHDX]2bwl~[Ò˜çp¬ô¹ca3èOWåèjãZ4´îy¢8UïHŒÏ¶;ØS–,K*=;¥«úŠ$ iºn²ä;åðò™’¿Í4¨t&T™´¼?Õ1Æò%ÄÖNàï^`ÁŒêòr׉ÛNÊ!Ÿ—fœ™üa cZªï™eŠ…_‚ò- ài!%ç|Âó»`ÿê£bŒ7ÒSB-wêR<¾:âœ#Q=„ÊV|~iÎãf[项"‰Í!Áè)IÚ‘I‘ý7$#~s/²*‚"²¶BGºvv$­^Šz¡ –·pÀµ®†%‰Ìƒ`GRzÃÜlÏÐ+nGee`C˨ÝZ:Òãvfx¢ |AšÏÕL¨ðùÖåh⤵Ze'ýuãìo; ¡çV ÅT7ÏD©kHÿŸtšqQœ-©ÎÙ» ‹Õª!£ Wpçåu{ä‡b yJ]=´¸((‡-£Åû}*žå)åŠ×†QJ>ú¶¦ÀR8̬6yÊT™9ôÐ¥¸þÒ ¯J pæC®úrô}Ž,Áƒgäá-PëÞ,×Ñ¡BvÖ‹.}ìY7pG2ì9éHûÄþ&Šrí†~d§ï¡5æwËæÞ ²&­À4hP9sq ûŽ%ÚW̉ Úpª¸÷© âf~e$Ê>q?™8Ñn"q# ¬X, Ô BrU5,°À\çÖªq=ŠâS—À¶Ñ¿wzå7q ¿Ëæê 2<¡û¹2XL%¼> Máò#¿€Îá \Šv§É!,üPÊuHkä¶è:Zø§˜P /®ž‚ø#×O/Q2;4GWp§¬‰>U»a¥OÊx ¯ÀJ¾Y âÍüºC{ɤHÌj¸É’êlwŽ;ÒÞÁæ;/ÍÛ¤W¥ùñ ôæJ ÒÁN±e;ZƒÁ( ~“¿j«9íH³Q*´-< )£S°·“~tÊe„Ævb}2Qð)È'4öÅ "5‰(B&WæÎíðÛBþF…y”‹§hŸšp'é.ÊÔk@RëàÜø ÑXÁ¥­Hš.B9Zþ¸BÐ)t¼c"g® e©bÈFãÓ<²ÇÃÓlHs2v\Æ”q«ø:ý œV;nL!íÉ|˜ûŠþxî8 LÆÊî<ƒàPÓ"67φòíÑbÚÀ I÷£PD7µ!±•”€ {·†‰d- T%¦›Ú·)^UËçX÷áâRR]ŸùAò€×0 Oìóuº£ÑŽ’æbZ'ÃíIûb„2Ò~u‹Ý¨¨Ï="Õ¼xOÔBhñ [DΊҼ1¬Z{ q nó°åñh^eKâ(ç§w•®Ø%ES®ü´»Š¦‘‚jž‘À|aŠ<2•™•×Qôî3Œ0EeTŽ€>ýuÒ.^¼•dë&Ð\3”†nts[U}*ëãŽtppe:½³&¦ªµ£^‡cƒåˆ^·4cȾ¸p•É®õˆº^¥|”îG¹­ÈÍ›þx6; àŠâßÂRbÐ^¸ ¸ I±ó"žØÀŽ »ÅÔ4æ EZ«Ïª_vÐrœÿ!ìlžj˜¯°7iGbÈÁn²):î£`&p‘ËÆ r8ªV´.»áuŒytM°ar{NXÍ‚X#ý„H„‹œjË‘7Eó‘B7Š÷/¼½¦˜LxתP•¡Vð¸ÌÑ-/ƒ)×ôø0sb®¼À5úEÅ'ÅTL Sõ0ßÜŒX;TÒÖá¶A ,4—ŽDYölX‚ùzÈåÓ3•‘;}ÐΊªiÅU:é5|<Ú±àKnUä¯Ï.BÂZ-“ÝÁ¾zésw*úò9XB:QÕ¬óåM&ž![䱯jŒûÝy_v«â‘»Š”Þ—çЊP/jÙñ))£Û7œ8Ý8·xÅÅÔÔ\rN6È9G­‚‚º¸¢5ƒ ãæÜaøƒr³Km»,ª¨=æPfÀÓ ‘ÏÏPîSªf^$@öãǃƒçWä‘qzqjÍ´ç3ž/ø?¤æ[è¯zᙪuKÚ2 Á²’®úŠDÖßFÁ‘K "_–@1C–ü <ô”UogXvâÚa‹|žåÚe¡ õ²#-%»¯•—Ü‘´åßn_polH¦æS^ÓDÞL&®›°-iÁI.F¢ÉnÖ?ÒsÚ«Ú⵪uA®`ìê”Ô‰yoHBw·ÕŠío>#1,¶$å aJò;Hp7תnlÞUrÆc¼¢æ*ÏUðU{äÅa.kWqvb‰D˜2#m!Ÿe© êµÒ-Ðé« ³ †ýÉD( ÆëþÌ;éF2Ú]ÐúQïü-5…´t—«[ Û ÷›míö®XGBë-÷³[:êÀoN°\¯Hv5’M‰•$1¯è‚Ôót·Tø›9Bs“$)-H¨Aûe¨+à÷Ç1Ï'}iXCȽœ–fÍtQçï®ë‚%F^†ˆ—3§¸<&¯²1—*¯ØqÕt²©ŸÐ)4ØôŽ2öða›C1ÃꡙòÈeK8–)§ÿëH"€PYwÑèÜM‰tƒàÖˆ›ÃeÇÏ_q|C_?D_B”4D‚ufÎBQ-œá/¨ó§sY£³áϤ”¬Û­×]€Ô±’0«™˜z޽$}|G:ØLÙ²XuæË‚1ôšÒ²ìÕzËÅ}Kù6 ÚáØ:#µJa%ß1â²’ l„˜ÚÀìoyá„Pìöü„´QëüùÈk¢\l®{Fô&Ž5ü[¼OŠ z€u-¨roð)»ª-¦7ø-:Ùvô{\ö¡ÚŒnLQ Ü—<:UI É}º* Cªšs4GÉ•v`îäìRD#¶çpu–}¬»bKå¬á@|##E‡žÈááÁ¿+×Ä /E‹rñˆkùÅ ª@r´;]d·a' ’Bv 5lS»sìX|pð†w¤øz¬˜÷[¡–àúrNjiiI2‚·z5Å«¾›£þ0¯UÙ7ßÜ€.žÇ,õs°Qì¤|ŸªMƒ;)fWP;šìÖMèHØpZ´ü+‘òûè̱P:5Ó&tÅЋ±= çáÙc­Þʃµ}´hC´­Š#$™¸³'g›§H+H^»)îøXr ÊΑ¨ä·¨L#fQí½.?A Ô%äî‘+è!Û‰B,pk«!þËþ– Éâ'/^,ÞĘ?± “]©¥‚5ˆ>vØ‘îïI„ìñqiHEDÑ/c×¢ø­¤5<»-wš>ÐVÅñ¤YÉzDФV…} [jŸ¸ p_’>dëƒßjzâNßוÉnj©—‹E¡¬®g…ØÐh¡¶ÅÃ…~4¾Fªð뵚0•ƒ&%W´ „ÿç¡+”Gv`m†çXŸœRÆH´<ð.eZÑR)ŒP‘=«,›\ Y1Ñ,W'± OÍÈøÉ>ÊeGMœ/…ÄBXéòÈ£ üœÁ0¨wn¼§ðÕE’9 ‹Å÷¡{|_<<‹§ºmÀ·\b·½%)úM;Ò Äþ^†ýèØ 9Ö!­ •Äå;b)Ìo }ëºÔ*³ALõí +¨o¬*v£}ïE.A ¾O8I6$;ÆBŒ‹õQ?Z¨—Që,ÃÅI ÙåGÝX…”FœïtÖE‰ …zNîxWu£„“jã Wˆm® ÀBm›P¶*û#Ù¹ã¹ò3Îûo¨]ªs)³GgàQ)fµ”ãkÎ1q0»<ÏW¼ QãQžÌŒ•!B AœSìáà^8%’üqŸo÷%®ùÞÛ 5*Ç®$œoCª¹t$Bí†!‰,‹mK²ìò¢F2O ßxG"È!1̰tz]Û(¥Á »V9BêYÌ:£â¥ª §>ÙŒìN€eg+Ò„HSÞ‘Ô‰kÝËh§Y=ƶ%)wÁ÷dtDJÑ2U iee¼“\æ¦E›éÔ•{Šz °¿¤Þ¦9‡ÿf$¶¡££}]®RÍ*¦O¼ÙäQÊPŽÌ÷´ )L55!ºuÇóh J’.GºÈçs`ÖØ6š–Ĭ›¶†CTÆYqêWï¢Åôš/ñ˜_YÌ[‡° É9vë¶ßc¥Žè ëV&½E\¶¬5/÷÷YŒ´R9_!|ƒi¾rìʯjGZ j7îOÉd9—óÂhÐ2*¤©&¸hR!É%VƸ!ÍÖ6Ú5êùíöù‘„ÈÜ(~üýt²À^åSRwÝÈë$p~ÆF>dwš*R8D”D“lógrˆžãDÛUý)¦gF Å !ºè«’øbŽpx‹&Á/28,ŒcÂrW¹ ÇèÂ-SêHÍÜEn8w¤‹-æ‡Ø UªØáMÉžØ:”N$@ÖÌuêû}ÎsÆhGÚQ‹È•uÇOnŒ“šKe8½¡•väœï^ÄŠ1¬ä( IÉvRJîó=·ÉÎR0VõÄØM)£ÉB»iÇêh×GŠ:!½!f—¿ô]¬(b[õ]m8)©•‘?—æ*Ö4Ä#¡aŠa®­ñ<å¸V…è»*d6²‚ò89C£Œ¶¿¿Có¬ÌâŽRY•…¦«üÐ0/UzXôšMÎÖÍÑÐ¥ÃÜ-}w,9ôO]l‰Õåd¼I m³ŒÏnGÛ[[Û.2/g¤ŠÚÍ7b~âqTMÃd·j ‡aǬ‰ oˆ¦Ê#ÛŠ‰@RFº(©ƒÒ¾—ÌZm™k·.;ÒæG; ŒU’ –kÅÜ&ÚžQEßÂʈԱvFRýjÛ]¹b 0ˆq4ßû5¢˜R.Ácd½ªÀF¥,EÄ ‹ž¢G4Ä•sç Ý~;$$À„çH1ÈÅ;G–OPÖHÛoÆ{g›GJÁyÜöþ²ñøÖý4Â'h2[Û!!O¨"8ø:×Ï%¹’©$ ÿ“Oø"ÐTe;²p¾˜Î·mI—$绩’\co±a(¤û{ûW6“£Y/JXqû6r9iR9_ŒVèK¬T!¸9IL2ØÉŽ´cW$êHKƒí曹Žqæ•ohÃüÀ8ß•A±¥!¡œc=‰xß|Cšõ& ÉHn"ÔNC®‚_ÿã^;¯Sˆ)wMÓvK/W> 8Ñ9ULž³ÆŸ®<<}1AImàïÕêm§]£6¸Mi™ùâ¾ ¥]”ºBÉ:Ù=ǹР2XZÖŽù9GÂFµWùj§Ê•v$X·äØó“!v²&•™.‘§˜sø„ØS]½B×^bÔnÃ!µ,¸]³Š›‘F—›Ï÷J­ˆ ¢£ÍˆÉ ÍÄ0‹ñIÿ"Ö(ýl}RîHªî› ÊÀÉsHB’ݨAŒ2˜žO”±Ü´› h׸‡X5DÜ¡;ãäšÆ!a£E¯84êE)m•#Æ–d÷ÅÇçÞ" Ì;Žìm̡ʡ†m޶^€vúØL8õd,*¤Öó>Õ/Õ÷£ú°ìJ8xcÊAc«^Ýì8 !†cO,·L$1„ä†Å[Òªa‚C¯(ƒíH}!®6Ú‘ÈEÂÑ{E•`CÉŠ=p[Õ‰F\NM?¡$ADÏWä±2×1ù[S]”fmi,Iª ¹ô#G¼ ®‘Rê{áQtÕJÑÕŒ i¥ÑÊÞe4„ A) ªˆ¤½ PUá¬e8› 'ÈíFËÃ>¨Ô=8&Š c QŒxÈ‘a>©®¤BçÊû'¡a–ŒLµâ154ÀàX ©Ö¸*X>± Ñèä∨zSd±[8×Iñ~ijÝm=#½$²ÃŠt¢™ËÒŽŽ…$×VÄíøöJ³ÝjGXt;J`mÕö{Ù*+¨_á©QÔîd¶A’sb.Ÿú48îÍG¤ÛMÐ~«„Ôà ÝÚ‘4)¢ÅÐgµ;Óy+ŸeYÃIšiSêõ˜Ts¯“{ZEýYu¸5£Â&Ž'èà ðpÓ»‘P ¿EW­-¦(iõÈÁèv”F ^ °tØ £¤Ü½‚:ëRdæ@-Ê‘ï·ã\û,ÙvªPƒAVU¤3ûQ?b´a‹ý¾µ+Î'CGzéùCû›9u°SŽÛæ·âY¼´ÞÄèœð…Yh¸À¼£^t¬I€pc ¡g±Ü[çs¬"MàÚ÷ƨª ŠÝL=èr!c# êhÇ©_#gµ+ÑbPD9p„Òû¢téŒ=VŽC£Æ®Å·8åy3Èså:]:‡ LNÁS2åQøVU—ÞÞBë°“ƒFÃ#¢9]•žû/I9Þ†3ܧ\{ÞíLçO=!B°ú|0÷&aFv¸VH‚EpßY4ÔòâE+¥±i^$0Ö) Û¶#ݸ­+36DZ-\ÕkÃËÑÒ<ò lX |GÐ:î?¸å¯Äª¹áºC è@¨³V7s/£Sȃ+l!M,™N±…ØÀ·X9#­õ"‹y}æYÜ–Y$ª¢)½/V76Añ-]H  :ŒúE·<ÓVô¹pÞɤVX ˜ÐàC ¼d¶nxüÏZÎáWû[yä_v÷âQª`оæ`–:àƒ§Íë {©"XTe_}mKCI(ÿÏuØåhk M¾>8)CH«Ñ•¸Š@¯ v‚¤ÅHvÔ‰¸! ÷û¶©(v¥#‘?䉅õÉA¶²õv‡üÞÌ ¯U޵„š-í+d»rGâÌ>™Þæv;Ò±n3ßè{ ô½0;*!‹ ˜™Ì¼gëŽÔ뺶ª˜¢ès÷ ü> гåz),Àâu'xƒÆ¨G#<`d€“30Ër7 ô »{®×?AÏ(R5a´Z1–N)A¿Tݨ è×4¹åPyv­“,1ÕòmERƒõ£¡Ž.±×µs/q„ì†Q»H+5cP?â´#ôéMÖU—*1´n´±<ä‰ÍÁz¶à¨135)Å4·ÉïGóI¡™”SóÞ*˜—ÑL®H=Ë‘*džâÜÐv:ê¹)½_'å2;ДáÀÙµº'•ƒRªâ^K¢D¦ºb%`BÔ8£uiŽÉÊ)èxBso·\Ý”ÀØ48•µ.ç0VƒŸ-*œŒAR P‹WaœÕ)^Š3vߪªÖ âzSÅ0ç®pô¶¾¥ ³ê–Lvª@ÚbÀa{{[G;ûΓܑ® £Ý}º#i’¢ÞÊd°¸‰e[ꉘ B´SU,Ç^ bÇ€·Þaù·3fÇÒ¿¥ÛñŽdl»ùôë–nӀݤ\a§z?bÀNÀo¥Úõ ¢ÐD—¶ø}×Mè?õ>ÔC&±„b/ëf èkÜê è7ÑÚ8Ð Â8înNî ,è \€¥Ò–Š­"ZÐd5+¦‘ÜÞ»2§,ÿáJäX ]4’ÌÅFÅȶ9"½Þa¼^ó0j&T>##çQv!¡v‡¥ŽÀ3HÂ&t®ãÑî¦ùAòÍdUmH|F¬a(¤ýƒ+¥#áh§¡F»¥Ÿ”Ôˆ…|Ò|úbÑ ~ßT=;Þµ“É:’çÄÊŠ4/Úr¦Ø‘¾|2±óѦl¶Ÿ†iQÇúŠ´núQ»v丕+Ç“ô#–%¤:gebæ8£uBê1¦ÔEC‡*ŠhŒ+GןlO«ˆ–ÆL™õS„úº:Ù É•Qe*Ö&yl-Œ|ò.RÜÎ ”ŠjŽzÃÀÿ“]®\‚‰1ü˜ËW§3‡,̸¶¸3ñß+nªVJܽÎlU·Ëv¤xÝ–ToHÛˆ5\{‰ã‘æ.$ oác¬éÊÀî–´Ì#ÛŠeä ËwØc†êU–v$’öõBÿæÑŽYBs¶ÔbÚ€ 6¤Iqiðp>5V—bMéc~Ú¬ ØÐ4~EŠ>v­§¹8*t&7uüÖÏ(•½g)¥^J¸’ÿG‚S@Äh¬ï@¸”@ÞXöÕiä¥Sj3eR´íF³wi žþ°¯¤ÚKß5«Qz;¶› ]ÆÖŽÒÒÒrÇd«†ÜeˆÈHå|öelèH‡‡£$-¥­¢šà~$ —´£í«åŠÄ~Żר²á ³¿-¼E¨B:•Aºe åëÛ;j‰´48¡].[îH+þQÌUaIÒI<‹•d3ݦXØÍÍÃn^ßÏ ñå ÙÑ%–†:£ÉiÖ—Ù®éZˆå«gºÊÏ®–Ùœ…x£7Ü8qèd¼SÈÁ½å³ÇÛ;xRõ_,*¸TñJ2‡Ä´÷…˜ P¾9ÌŒ(Í@ÌK•½\YÚ5^›Cœ,\|bµTš¾`N0…“Ã=,U.˜¸dk\¸N@·E{@ Pwá,gbåØÒpukKŦé#™93„d´»;Œv“£EíVémrXñ;Ȧ-®<ÝõÂdhVÊÒE©a<|¹£Å´”ÑŽ9BT0lë K!lÐç{ã'$ä«]¬uô#ßL+I,çÚUÞv]HuéjõDú³¿ú³.JŠƒ‹B)49pÃ|xŠ~V8õ¹;\vTÕÓŸNW°’8iV(˜)úBØKX5›skKŽRF÷#©aç‰Ñ›e;JÈêB$ùåZµ1·Ù“œ2¨ Íà<©‚â¶*+Èím“òm À ¯¶#Ý6Êꮀ WÊh’›Ô5'&@Ãt%‚¹)r$™á¨šä–ý¨54:ÒÉTt²%¹=±»È¥IHÓM0úÖ ©äó•åh±X«]ƒv<_5&5/—£ÜÆ%)ÿ®º¸`¨C tYh;+¥ž7´-í*i.;…§ùc(ªKã5 ¦ÖÁ£?aÎXÐOtuØ$‰<Œdý¨Y¤¡-6B3íæE&»ç ù¦ÅNA<á·Xó±cŠÝÌL¸¨Š$ñrfPCï”Õýè|CúQ.'gñT+ÓÓʪ>eà’v:ãµúÑåZÒ,öáaïöø˜Î£GvŠ[SŠÜçTáxî_…"òËÒ˜@+ñ\€ïÜIµñÁv©QzX$ “Ù“=ãÓ–{7äŒVPŸªì§Ø‘ Iú’ì ™a+–ÑÐ e•Q;í&GÓ“¾ä‹5æ²co¹ÓáNë¸+-w¤ÆD‡´b,!w4$ù¡qØÎ˜ å"˸6¥¹^aQ+\J±ã¡nb©Sv;1…ùlVŽH 7ëÆG;CÚ:{"ç÷ÕNTücÏi«*»¨68åZê:ˆòdÙ`ªhìŠeZ±ÊFè^tªÊ1I%‘ ›ü^œÐÀ$ÄÒ¸ƒ'CD@J‘ÿWE,£¶¶¸,ŽÁUcAêb¢ŸïTŽUâ—¸"ÏÝ¡¿È bz‚væ§ÊÕm$3¤Á&;µR[;Bíä»,æ ÇÒ„vÄ9Uàp6³³1.ºW*ç#ò‚4¤(ÌwàÇ%_dÉla#¶©sñ.6†^JÂ%;p‰ÓÉ|¾©’`A”aæ¾'½ ‹ÔR—Ï6>9ã|ô>2ó´U,Ás°MLèPTžVe£kX[bL—ÙÄKuLá,$Ïx9FR_ôoÈ¥›¢ç.a)጖ÓH†Ø·e´<Á­&å’уËWö<Š ÛuÂ*v® èË]ìJÁ´Ù}ºÎŠ*¨±‡JhØv´ÎÇ:ëHþr£œ‘kééБXPn'¶/5 ×}a¥:Xa|·:Ñ mU.Hl™¨he>‘ŒÛuŠÚÙØv$ªÎ71xb³è‰é–£Â±³ý¨h(³k$pEMOÚÜ…=)á»? ðÉ6Í¥3ã^=+§4Þ$"¾)> 'dØX‡BÏ 4½—T.Šcï®BŠ`rÅ-å¼|º³S*àí&çhë'¶ð‰˜½löš ¾Þ¥Süúü"p5\Ÿ”BðowÀ‘*EŸAªÙ‰:|o‹Í‰½†®DØ·©‘v%Œ‚ܸNŽ+ì[ÒYz“ òÝk7êÛb)ÌUaÓ b§$ÕÕ² Þ†…÷Íñð@'®êÇÙ•‹Ë´å¦ˆ5I¬q¾ }O¥!-¤!qÞ¥ø5˜®OØ»žTÔ ±QCêΚõê¥:|¤8‰×t¨’v›Âð4Ÿ`×Î5ž-Y+9ޱ誢€Ô¡y‚̤\1ìb Cxò4ÅQì„+|F‰@Œ¤¤œÂѬJwʨdPSZµ0‘ߘ2´]ô^O#’ù×1^çwXíGÛ¡!ݾê“©‘vïéR˜j-1p¢ÀuÅÊ΢]؉KÌUù®Ä¸ÂRW¤¥BÞ-œ“Xó=<¶‡Çú!Û Ñâeລ(×U8á/†… £I# '9}ÖP@³)™M%ßûAk[K Ò{ !µh˜—Ÿ²#Ŧd®6üAQu&æÈ —ÿY U×¼ Îhpð[ ô¹ÞÅ«‚vîì˜W¤Ý›ßa¥9í„™:é‚Äk—ûÐs=’v$Ç¿·§ë øvÂ÷õà Éò[ìµ×ÑApï£gPˆé qíŸâÒÚ?›à~—÷Ø x/F×û>‹´Òòý"1ÿ‘²ÚÆ#ŽÎ¥GC וa“ ˆ)9agËXy®Ž9Õ¹³î…R2†î^&e°ó]©•l gÜ’~³ ¤)#-5L0sZg+™¬ž¬U³_ql’µûCpìd?Š$1ÞBí¾üÂ<»_€içw¤ã\ªoɪô‚¹.Ï2ÖU)‘ÀªiVГœ­H.òã;Ò‘¹§R3PF§! úòól¨Ó쉋A ýûá!³<õIü £z†ãп@Á# øï d)¦ôBã2Ïý·ZŸò$ukÝg“6$X&2Üj(4åd B"2‹„@·V‰Cˆ†„u/Œ€œ€†çñ9CJ‚•jœ‹‡n†99l{B ‚²Þ6ÓîíùKR–ÿg 1Ìð‡}+»ÎÊèßn4$)£¿ØŠ¤IM„Ž/ªÞS/È^E/úí³ìFoÒ‡T QwŒ{ áÎI “„‹Ilß[ƒÑîY;Ò‹Id·©”¤IÊåaðÞR—†‹ M]6è›Õ|•:::Øa(£(ñ»üN‚ ÝRN´|¾‡ËmdTÐæ%œE-ÁL™“Š¡˜£÷Íà¾Má|ˆnð€—ŒKmð§kÖ‚Æ,wPJ´àÇ%Üžr&_¬ „ÍR Lwµð-+ɕɔú~öµ(À‰Œ ¶B‘GHýÙ;Ò\zôg!©þNGÿ&3Ý/Ë’Ô#/Q¿ß‘8B–G;·øVUïE;ì”e'~[ýÝŽBHŠ‹/H¶ g¥ÀŽô±ìHÆéåÕÍ ù®´ÕpGÈ«7$+£‹Îu~D’Žä¹HÌRˆƥ;mGÿ*Jlý1<‹Ì´ÛsŒGìTRʨ¸+c„žr9º)[ ®CÀ ÊŠ¾ð.!` #kFµÃà>ö¡ôÇ;8åV R¤˜eÅøHú½ÁuÌúÄpŒT}àè`[ð(ÝÉÆ,ZyŠc¸îKõ:R'ñ°H×ר£¥ýå—_zýÅÒcùËäï¾#¤#uÎÂäó=+\) ÓìmH®DoÎ79¡xvoÏÝ ¤—”x‚|¸iCŸîT&{â]ÉLì@ƧÎ[sy9@’|õa.ÅB:"f7+eµb2Rȼ7Yìö{eŒ‚“¥:ò³GŸ(È&X-"«‚RWó¬–ÑÌ G¸à,”ÔçÆNºq%»† ÷!&¢Ùá‘ìºËÍ+0Eâà›ñ»f;™ôDEÙíEø›iû,Ùm© £yµ†œa»ÿãÿü³Çý9ѽQÉ×;Q/£ŸÕõ$ßfýý :Òä–'SŠ^U*Db_.µÑW$áM) rTÒÉn@í:ÊÇI”})œôзbµ]ÌÒ.bçeÄut„@—Ù&;Û‘J2<)í_ÑÖ ²¢À~~ƒ±jiƒ3k┡Í܃‘Oî"…ÒÑ¥ác0Ÿ»VNá-³… =Q©éžY(§&Ó® k¤ $J¶_TÒt;¸Ó•¬ÛÀ?É? ;6MZ© ãdU¤9È0ïMäžô—>رv‚ï_”ùm÷X¶µÛ2³;ÒdGØ‘Õ0íLëós³ïHÒªp”«5+Í'‘È~9°dÏÕê`g€#v[Gë.j«Ê8C\b?ÜZõC;¥~/•ô'MGÆ0Ь‡ø&ФØðüHÓDŽ.rŒÅ¢•¨¬e;¬–OQ%‡½;ã¹²uÈw:YiTÒß'Ó„¨ŒsiÉé\™ NmÄÚ)Ñ)S7L|ž«¥´a`M¨’uRqtÝJš®)ÕxK&“&Wí~]+ñçdÌ .ù¸5Õýü 7#é~Ñ:úYü|´[v¤#t¤I¼ $ô’ J¾ÙY`¬:~‹QóÈd£‚Þ¢'5GíxX³eȾRÒ6󂌢zÑÀ‰ .F"ˆuè[¬óÅ­ƒ˜uGHå_lFåFO"ÃihŒÌf§ÁQxCú÷ XË••lÌé’»¢Œð45ºÞ¥Tp$ÂB(v™\«È®£f±áeH(Ü€@Λd A*c)šào”Œ÷pÀ9Êð;RjYiˆ°9À¯¯Ó ÐÂÀOURÐÏ¿H3êcô#iH}íð÷ö›u¤i7ß[üò-é2<‰ßÄï›ßc‘c suzÍu±é»Ü‘>¾\¸’ú.tõs’Ša¹]Ãã{«+[+6ñ·¢ñïô‡PHÄBôçuK/ê´º¿ü,/^FÒø†d£]/$aWW$¹É^«ÖÕ›¸žô•IjéY vÙ]õM í¬œ&Ü‘¤#Am·>Ô!^çdç2¨6·¢HDr»†?±_ðÜ3’[RÑ-ÔrepGf§š–Ù•T‘0D·Y<6nÔ°t")™¤–%kÈS@3Ö<¯9ÉeT•»ß=ÎgáCY(KÜÓß6ÙÁâßqmçœýóGƒñäšL1ÿ•ÕçšÚà2ðrâØÈFoEùÜ«}ˆg¹_þM¶!1fˆ)¡^E¿1ôÍ*sìLdÒòzCvDˈ© B\„†— à 7Ú)“½Ó·íY|íÌ"òus=\³M~¸œðKø@zàò‡94èi>z…@vsPíjø ‰ß_™2Œ4À²²JDnëH¢!Ž9Þî“5$?¤¬È€¹óªà 2•Q휃ºí8ð&ÿAFQ†¥ÖnØ: n‘[!kÙ‰s\0sª .Z”‰d7‹¶”4‚qÅÒßîßn‘¬Bº ý‹è7ç~–‚~ÔKÉlíØD_ÎH»`Ú¢ u šUÍ7GCÒ1oÊPÝ.3„tG:r ¹ÎU Pñnäœ:3g@h 1 IDAT]ù‡©&e`fAvº ™õwmk‡­5TWþ ¹¡¬²PVüÜD3s²9\«eÇ9‚²œËê—–fCex`ư´vGÍΰ”;_âèåg(®“Ͱa%”Ò†"Žg‹`9x¯IÆ›ƒ‰9üº”lˆ(ä!î]Љ’«„þ¾Cý…¬lçý—ŸóË­‚_P”áo¼ õ*z,ïH/½í>r0·Ážmt/X‡qÑèO—mï¢ € ƒœP8‚¶lºHÉ+ðu4÷žRä3ƒ¶|ì‹kõ+a瘤¹pgÞåËOé¬!üÄÑêX;”E i&§˜‚>ç…K¤Ó 'åó‹ô¡Øƒ~6€ÛpoDRFÝðÛ$)¤O ˆ´óìóN£ÄlEzfÇ1®ë;Ûæ«6öÍoK·OHæk§¦ º%Ì!H}ë.[O*G¹D@Þ“i;ê5d(ÃÇd&\²P•Z+ÒìþHAÉ«Ø[Ce#±F!§ý”·¤Éa£ýUÞ²›>*ÌŒ 3L)Ѳï"z&hÐ- .ÄFà)Ú;fk ¬=(ÚÈ ñSÓ¯“`ÞÁT°`R:…Ð! nOé™)©wå,äuóKê@?ÿñ·uêÓ\/¡¥ÝI7âé±÷¤}Ï€è`ƒˆc¥½U·ßbµŸî:±n×›‘´¤I†·©ŠUñÌöÑ~¸À×OL|ª£¸ø&$ÜŸ-Œbž£ !1˜M·"5 :úñÈvªŽeÐŽ­¿# é_-F·,†‡ð!œl”í­–£ ‡ÆXŸ–Ìæ2Ã,¥;ä¬#TËR6Û_5À¬úÎNNÈôÜB·£43ñ¬¦!°3,÷0€°¤³5¦¼fYd¡6 i8zؽ†‘sJDÁÈ‚Ï1oþå—Õ'{3Æ Zjèoã6ôÇ¿Z/ân¤£Ý»°¿µÛMšËÖÄâïÍ„. ™æ‚ï&u6™j¤Å>Ñ3ÚI=Õþ—Bºxøž¨ ¸à† FÒ´u7q{ùJKH˜ *BbAŸV’qVÿ n åŸysŒEn'Z¡R㺠Á{«¥ ˆ26 s¢s´¬%®á€µJ-A…MTo¤ç®¡¼±t‘ ( F¼xè»›7A†@"QÀ_tƒ‰u•cK>)ùM6WÑo:Èýñç]èîw½ãúÛ_ñE¦ºþòªéxœ-tyé6oÕóøb²SWH3 ’À#U%1„7Y#‚Š~¢œ„kw´ÎcðB .\‚P† XFwÇõh)¡^PrAš¥M¦3oÁ²ÿç»r+Ç%?ìÆ! 409ŽØa9 ñfüŽ)aŒ2 µRyéNù¹¦ mFK¨’Üh×d{þP@q7_þöǿݱՖ”Ïßr i7²2zÜì÷Ÿ>‰Œbi?ŒjEã€AÐÄŠx' ÷ó)LÃrÔdÔk µ[*éø"‡¤ƒ§…¡ðÕÛÐů‡¹•S7D.Ÿ¼q1ì-Yy;³‡„†¢»ßãÖdÕìËAŒ ¢2d¿ ÖŽ·ÔÔ鄾Ö4‚ ShC¢L#Ðb)ïe$Ò Øœ2ÒXðL†äz†3ç(R I8eÿ˜ÒÐõÄpñÜ1D ¤ì΂*‰!‘yˆA¸ê% ÅüùˆÇå‚úkí›ÐЪŠt¨[u$6?™–ž4û!i7‹ÕÝ®¿M¢S2\\³ÊE?Ž¥vûŪéÙv$-›­¶!œèŒÀà0Ý%Ñ1á NRe ®i6NÃìè÷˜‹ùG.@XëøF-†n&Œé”™ðB‘œ¢N“ó"fú5#6§»˜ÝíIˆ²O)Il„™1%»„¥sP’ÔSî_k>Ký-·ã“Y–„£Õº㮄Ix€ up&†"'¯’ÃDŠKã‘γ|uç§¡±lú›|ÃuóúÈÃòíëæuß_ÎËŽt]F»ïóü2ßzaÝvÏ|IÝ-¯ÓN~d'ß]~ÿœ^¬ezVsýgycÐŽï±G¼àäêwײ.éö¢ͳbtVC¦1W‚±íV3œ97äd±rÓF}³ýjød<œi$´&›Ÿ uÝn´†¨Ÿ°Á2^˜ü4‚$»”–¼¼w‘9¥–VV PJ(ö:ž3[¦âj”î_#°^h ÉÿIá@žþ@áÿÞÚ H J* eVe}”STx Ü5“šÍkÞiðeß¿¼î— Ú?n^7ûÍ^ÎlÙ°LWßËÐõýåeùúåûüýwªêf¡Éës/§¥~ž£úäÇ{½í–óçèc»{¥s;ží_›®ˆUp+J%Äc\ÿæOÊOµ.¤hYqqG2 .NУšÂ‘ ÄM4`AÞV,eGÌÊÏÑ£¯1E²·—KŠŽ-´Cv9ÊÊ àÆxVeÆägÔÖæ!-ãC<%B ¡êØ…SEÈ® žÝ”®QRË݈÷x‹Ÿê¯¢ñœgɸJH¶ÖÌ¡4£` %½æBÙü jd3¼·‘/›Çý­—þò¾x8ŸÎï=™½‚}¸_¾¿ï_õ÷ø»Çï/½Ê¾/ìþeygöÖp»Âì½¹—‘Ö‘÷û&úNà 6gýí?ì…æ  º }ÒŒ$f¦zKj9Ï¥ù…öj÷»T!wÞ-9àR÷0v1‡Cêj^¢ÿ 1¯A¤,¢Å¬ÜµÓ¦_’Vo¼eaâXƒQ|ưfÊq¬ •€|qdÂßäm Ø!uSi^Êçtâ‡dd.Ó}˜ž–jº,Í©¶Üþ);aBÖYPö0êÌÿ{üwxÜl–·þ½e“ ¥õð®ßîϽf¸jn½|â:útÝrOúrá×eQùþ¥—Íá;ÖÔªÊ>úW³¼ÿ¢°šC/· ŒAQ⹜èÃøÛ¬Ë;ÂQH¿ü‰¿é¥ò1ûçÝGº>Ìí´Šªf0wbƒÓ¿MPQsZ_ó’ò¶¤?¹TWFI›àTƒA‹®?5Ém€” íC)v)k§Ô•©ÐZ{ƒv .ÍIQ,ƒ ²R‰†Ã޳ÝSi'+ œÇÖRlQ ühç¼LtË#âº?„—Göçþ¶¼>öÇøRLËœ§ ¡–N¦…˜²Áb¢¬Š#[)ûûýù~)ØûÞXúëC¯’•r‚wúûŸN§O§ëòå“ùö˜™Ü7÷ëÉ/‚¨}“[ºÇ·ãXa¼¤¤&¾C(XÝë,:ÍÇ ‡EÌÀÙþXÕM4kf°úDõhûZÒ4¼Ö&¤>ÖUù¦ÉWö­%;c¸ÙÂ7·ï(ü,‹œí€™¿-q²C°YU %Qi|™î²&¦1go9I”Ð2´~”oœåhÐü„sCKJA .Z„'b–OªµOtץЖzúüd/_õÛ¥š–b’Zªm}PÎÖª.ö- MC„-ÿ˸œõkù擾-¯×óµWʧÞhà¿sð÷¾õ¯þnï–‚úvð©¾|K…Å¥õí(„¸oÇ‹{¾cU}x1)`ðÒkŠ;·òKµYå¡mV;ÙÄ)†À´³¤íGób+®¸^zGªP>j)wZ@Ú¡¼W…Ýw§r#Ú/S?㬘† Ê#;?æHqÄ47‚+7²‚9æÄOoxÃÓ/ª« 0«×ø0JhËÈü+`D‡ãâ-~5ÖJâ] ¹@î®Ë²]šÑÒ‰>/Uôùëמ¾â ÔçÇÏû÷ói{ü¨U¯0“®Â6ÆTáË_âÓõÿ|ê_®ÿçú÷OQ!Oßhm|³×C•·o©6zñ¤Š2’o×í5} êâYrG•:ûr g’ôbÍj)¢!j§Zšg,+¡þ²›`\f79ööñM¾L罇?ˆÛ4%­Úr*æ0ý­Ùâ«u6£ÑáYr.=¬)ßÛÑ@ª´õ‰µÐèæ~Xe´¥Ã»QŽA$ó™öàF¸º­#Š ì³€ê¶  eWô´±ÅI¯NK]ÏïûeŽëEô{/O_Ÿ>÷!o{ø…ßøÃÜ¢úħ–§ÿwla˜¶²ý¶]*oëT¹¡Yu[0m³Zˆô=¤:°ç¼¸ÉÛ^9E#ßöÚ¨R=\!íÖ« rúýþsµ¶¤~*~¥-©6Цa.Wµœ84$\†’±O>¹´5ô—÷žXþ©xÆ¥œãäGWÆ$kÛ!•0Ú%ëÂC±±Ä $sGM.lR1FZÔI¼Ì˹Ït½m>î½èéë?{éSÞæþát½0îrûÁ™¡¥a&ˆ,3¸¾ÜØh¾ðëñpürìo‡ï_Ž;àïé7öÞwßo¾]½}:å媿}Ò¬ñUM¹‹–ø8^=süÆK4/_$€üÂ¥Äu4)‡\לn6)õ²³‚ñʱ¯›Û?,ËiKEØCÜö¡þœ-LÚ›ü—yïjz츄õ%yΗçý['ÛAW&abš-¬×tïë’¤†CÓ p p瘲2mtPnƒª›à¤e'åS¦Æ5XÀ˜;¡VŸEJŠ*Cÿs»ô2ºHE3jéîëOý«þªÅô¸ç]©rAØ5AõŸþ8j™%Ûã—^!_:´Ö_¿Pí»!Ö W îö=~Ä_^ú›\‹^^4ceé®ËËýù÷^NòÕéÌXÅòÅaŠTYꨵž­Oñh™ëôdš¦4­øŽ·“¦»T/=-ˆ#cµ2ôãâm'¿?Ù\§·Z]› oh8åùã(YH™ágKziLƒ` ±IkÚ…RíìbØÒ 1e%c<ÂI§%‡nŒKiÁ ŽŽÛâë9 –vC€Ú`bÆ åõHÿ%m^†ºs/£e3ê´¼ý%ô“¾J-i9q)m6ïçíey 5¬¥MžL#ÛùE¦Ç}Ë/s[>úáàÌ·pãÆúÒMæ–iît¾ïØù½¾þzÿ¾¼ž÷÷¿ž=¿/_Ö¥µ”Õé|Šlòqd'†ívÞJ×Á†yšFQ*”¨¸W¨ ßrÝx¸‰‡^D’oÎXžúêÃ/ÖªªyêkQ[at<žf+Õ‚þëЄÛ%% +3âÕ-É1b•Gs¬Bk~`ÖR['%›2tŸ6×dÖæ‹]Öâwš+èÀZƒ½#u:Ô­Gº»¯Ö€¤ŒâUKéó¾Ûl„óÝ.¡S ÍD@Á{=üiÌÝ™ßôíÖëRIˤÈÏ òò®_ä›÷åõ¡¿-/|¿}WP]¾^>}&¼žz%¸¤Ü£îšcޤšºÝ3@j…, j(èÿŠwÕñ¾S‰* >ë5½5#:,ÏcÖš€ß]QL/QˆÖÑ/9u;»k€È‚Öœ@†&A«ð†2z¬sÂR$lû[N ÏÈ÷ c°äBXƒC _ËÃì`jF)só–J>!͇íõ]Ëè‡õ>ô“´!þ&ºÓÝOÒ—ú²´?]·Çê$t •rúAÄB‡©R/¤·¶Ìz{Ñj¸U'òÍÎ?P%#ìíÙõãl齬M—ÃõS/¤w(£w+¥~a^¾<ì—z—Rz×A¯ÓòU¯¦¾QI,¹K˜}ªÙÔ‰„ï";R jà•ûäßöiüݨ’„ªQËåßUp[щ¸/¹iäÔLŽ0/]²ÿ՛шߥ~R²eaAÖV=c0lò3nÏdÉ’o1ÚäJŒ¼Œ¥‹þ0"Â…–Ò̤"TS”Ál f”²vŸÃ}ey­ÇÖ!†§ ŒRAýð“¶$Ÿïî´¶´–z[º~Ô¹c§‰úƒúeù²Œk»>­½Ù¼öòf-ÊÕK½¼Ø?u®/¹²¤¸vKGb´aíÞ3ŸèÓ~©ž‡^T{.£÷“x²=qìÞé¯\OÜ¢£ÝUT° ¤‰Yo\2Ôâ}~W—ù_}ä‘®¤`’ÍÆXsv’xKO[&²J™ä‹.^œÏ¬õåsa̮ۡù:4X ‚CG6 (G¤–M@À3 wàáÚ߯ù Ã`†ç݉G¾˜PÄáµäBLëH5s˜ZS8‘-'±#Lˆ õÆt2b”aÙŽö©³ÚyŒ©Î¦¹bM’ZZ¾–/2â-méþ|í=©ÝNÅuý,^³R€ï:o\.K1¼Ô—癣ÀÞ^³éÈg©j7²$ n1´á|¶*’ ²r‚õÀ5uî“Þòʵ¤é*%Õ¡ìKº.õ)ϼeGbÒvÄÚʧŒ”§6Yg’•Šì1^eì¶({G·¯Ô´š£y2ãU3´íÙ7Zì’ÉPŸa4_Évã’ã–€z”Æ5$ªAüpiëaàᬮ^Ä×D  e±U„%AZEI¼DËãXʹ{ý›Ž20ÈðÃ×Ïc Ý)H'ýèλÑO2áñ«6&éJ÷§¾(aÕ‚µLNjJ¶¿§µ#k:³“¾¾¼‰((–£¾0MoèN÷R=ærY’zÓp°¡WÐãëæñuÿ¸ß¼b51ðÐûR'ø½Ÿå•k‰ñÞέ¬etR\\ IÝã†ÔoGÜsôkÓ I; Ù¾d‹v$ '+Éʨٲ¤0†¶#cBLr’Ñ®:ŽnbZ½'5A/rÖ•ÁO4Ù(Däâ‹ä}†Ø80ÃifŒGy¬ò•€V­1Z žù”m·W¼ì’¬‡GæÓ¨à…3”NÎØuñ§"É:e€-ïÖCë«Ûüþùõ'{ûj8C¯~ózúz÷ô´áñ.Døè¿>¸S&\ÿ0Ït<Õõ$€ƒìJϲ%ÉlÇ›SŸá^–n”qˆç7·&žçï‡Ë·Þ‘Þ½Œ6û®_Ú°öoãCžÖRG$zSÚŸyH°x/'ò”apC‡¿yGj¿Ã4 ±x9"ƒõH)rº,AÑ­þ¤pâßÍHzM;’–Ï}Ò ü/£eÌp³ü΢õìV“¸Û…ÖJó•Ø3¶oØð‘ñð ei0j v}÷ »SZW ƒß€^*%# NK­ùnyH2»Ú Ó wS«ãךíLÅ(á`¾ò0)Ã-sgyˆýŠ+åà/YòÃÔEMuþø˜P‘¨IÉÒ WµLé£ÒòëyA’2S)h¢7$Ö–5îì¾ñX÷øÃ×ß¬ŠœÕpw÷SZ”¤!-_x¼ÛŸpcC;™…O¨?翜ÁÞ2Ò ÊPg») ð×$©"I”ЄX –è.lèÙÈ_v¤{mH¯¯&·}í]©7¦Í«c±0Iññzà¾äš§íVÑï8È6Gì¾ èÛÑ„©z'ûRT’}†=‰”!XÆ„"ÝÈa;/£Š,!¸ï®"òÒ0N„™<˜Çò#‡Â㊓cº|liH]¿5ašåª× ]OTÇ:0þ¥$£Çȃ =9!À>Xhi¡œFãxa/K è}ã»TT]–Ís:ä)þÓOZNËx·?ñi6 „J«w:x¶Ž$$Åóâ¨ÀÞÃIv<Ï2®IÀ†¥\^_Eµ.ö‘ý{ý+jƒ(^Ÿï–áîaoedÅ$CãgÁÁ·±#IŠÑä4ÔV«“(º}'Ó²m"w!®¶7ÔÁ(ÈÚ‘i)jhÐå¬4)_Hi®-ÿ1º›Y4êjv1†°J*Ù* }¯DnfzÒ/«œ3 G¦Áª‡Òe©¤–MD±up4š’€~D ÛÕ–’üŒøá–~ÐÌL¶sèNõ³7ƺ€<8ÇÊL<»xì0Mqæ&„¦dzQÁ(ºdô3î:Õ[øÊÒº壎®~qrÉn€c4FÄuÔ;ôŒ ëÌ'JBÁ˜çù1-Dàu>,ëÑÆ8A~Šíeõ¸ÔPW—³y‚¸(l>÷z²bú)oKwŠ:ô—^fO›sgÞe‹'Pè"|áÚÙ^däKÒ¬#_ÿ!ð¦‘>¤©,Ï’ ÷]:Ò;w$ÙŽÌ>R<ˆxÄãnÅõ,"®£w©¢èGzO:+eètUº]í¬# ´œZ£÷]‘⣶1…·0JiÄ]“ÉßTפj¿6)¢§³lH ŒR(D%…Ù—!V¤¬h( ¨ŒFØ)¬eˆåã­…®:X>…¶%EØÃj1 qƒÇÖ¦ØJ¢QòMYUIœmPld–H­hwÈäòõô±½î÷Ffø¡×ÈF»ÐæëçÇ¥ŠºVtq¬DØ?ì;z윇Àí¼†¤¤¸'=¯Ê(ÛU%ä-ù€.¨be'zŠåøvØq*¬$$÷0–¨Ý߯Êþ´ÊhÓц?0~·á–eZå³v²ƒág¿Ðž nP&¸:å ù[Bquƒ |Ҥ콛ô:©¥Ÿ¢0°  VDzMRK£›·†eä\ÕŠÙÒÚHXM:SÌ]“F8–1R™££Ÿ+¹ŒhË`Ç'íá΃ýâ… ¿8Ç2 30¸¡ÞD 3žfz)ëäØI·e®{Ø÷2zúªsÝfy[êès¯¡M?HòÓìÇËå°ýÖÃ~új°ÓFké§Øî´„¼˜zOêÐÝ@moƒ…E.Z÷žƒ-÷ÂG¢^$r¥}Ñ ƒßϳmP–yTÙ—ûmf¢'ï-µõ;Òv©‚>ÙõÖó“¾·‘»Òfÿ8’ñ¾Ó-ÉJI‘ðÞ‘ÎÚ]%L¹{ÔÉh§×V»ÌÖÀ²µÅèŒçÌ+ùbÔ !×?pKMHÑôþ*¸†·$GÓ¶Ö²Æ{]‹ú=Ý!‹`^|"C"7¯q/¨8!bŽª”œÛÚ•’0M9ë5e+“RÆ`™A¨›œˆnY Óè1ëœÀ;Ñß¾˜]c]ïE?,5´gÇ­ëöï¬Öc,µï²ì$zØ.¥ûÍã“5%@¿uCâZº»ûút:VàœÓ`zw ÑŽãÇÕgãÎqæ× ÇE<¿MÅ"ábCü¦;Îgéý¨sÀûß—•}ÒúŽ*ÚÈ— ßf76Ú©íC ÂêMÉ—$®!ÅíúÛVñ勒XhÞ³•B6‘´ Fÿvj¬H-mA†®Å÷«¦ó9,`Xœ”M5… ü”!]b«e…@¯Ásu`«:9m—”d´”¨¼%h^Öòè¶ìêZHÖ’œ‡CëNà¨P„£œ*Û²k¤SbȺ¿=殇³)DhÆšVrþ,/H÷~úA6¢^D_7݃áž]ëäºÈŸ|÷ —ÿ<±Ú눗z’t#ï¾þõi=Bâu2Ò[û1 EH&7þ¦Î̪[¾ÐNIvYY!Uô&‰–¿ÇÑzËh÷ý(‰çºÍÚ‘ w{yå©nã×YvÏ F;oHvGIúAï±6Ú9Ö­\瘝íj·aŽÔ™P}$5£”mXÖƒü†dkRu-m€ÑÖ€²:äç£ã$çÙqH–ÎŽà ©& IDATV ù·-Cp°lBúË«µ$‹†ÎJ»Ñu‹Vɬ„ñ®4vAøPòrÁ›rXÜÁ¸•QA å8N¶1öÝGºÍþátí;s$àç‘{aïOÜ—6SÿÙ–t§e¤õõéé´ÕÇx¥¡jÙcLÿoÞŒˆju£cœïži¨<¾U;Àvüž:>³9‚æM¼ E¨w¤NÿþUv$íÆ2êTÆì^£ŒÎ½+3[èüð~FªÓîÎWã6°š¢R?…ðßÅà1¿Y )#Á»^¼©ðb Ù4¨³YT‘–ŒÃ ͱ3 ç†êœ†ÖZü }ŒSÄ:•%å þ¥% dSÂ^¤]¸Z¿]Ø ?!1ŽVÊGÞŒèñÓ|ikpÒ1=1¨Â¯A±‘piÔšàCìFqoêž6½ŒØ\ËÿÊz%A~<ÿæuš¿®¿rWêh¸uQFŒ7ðp‡‰Nmˆ-;ê'Àú‘°¿¥ŒlÊãÂQèa7[†%‡…½aº²ŽxÏ|GúÂé¬ ¡×G\’:®sÝÙà*vCoHp“½Ê|§ é$ÌÝ‘Ž³è‘ TQ èÐ$,|•²/†ÙIE•ÀFÈv2ÞI-³b6´¸àÚ` ~( âØØ‡(…xw•i…G¯*•xTè³¥?–zýÇíòšÔï²`ƒÉCr3>ÖS‚y6nÃ.Êy“¢F ¥»áñízäŸUù+xOvÝX«û=òÿ'a&fb¹›Q›vÎ÷O}ÀŸWÑÕÔ׻ϧCm‰ô²È±/±°OËvÏ}7âæ´Ó6Å-I;ï>¢5u,yõ…²Ý[̵H°!½2á®cßží²Û‹ÎÏôIŠ1œÞÕÓUÔIÁ[_t¡Ú³Š"@:{W%-Ü‚ì’ÖÛ òù˜`þƒB25’Ot >¸MŠW©רŠ<8¥¥„K[JÜjª™·Nö¾ƒóP ¤l‰JÖÉJΟëŒ5;[Jé?Ôúb7¥>P´bªCS)09ÇI·¸”þåÁ59SvAR{m¾öÁîó×ϲ}þ¼¬Ó×¾êSf[ÝŸKsÚ¸Y<„§M ‹‰×¤¥%Í=Ý(Ä€i,ª¢p]è:«®ö¯ç¨ÌÕ±õE)©|1âéN›Ðn©ž—~EÒãlÏ+bÒêé,Y¥i-ñ{º!ùXçg$]Þ3ö}Ö#’ò”"¤Þ'Gõ⪠;[ެQKæ÷»N‚âv«e01àÁ†fíÈìD’Ô´˜Ð‘«¹ÔœŒhG#ôMn؆g  ðCX6íRl<¹Ùä3HŽ%mG=Qêp¼¤—¹6Ê{‘³²ü|DÆËð„½rÛqFXâ5’Öà©€€‚ðlÙ˜¨*ÛÑãç¥-ÝHÊÈ9­TRÒ!kQÌ:Ù^O÷›§G«$«&+¦eKÁ¬¯cn…<Ñyo’ýHÚÒó›Ý¸ºzBÑNv$þ™È z¤N…Ý=û`ײswË¿þýzVe9Ç¿ðD'MI9«¬{ÄÉîËHÉvç‡÷L]-ES†Ðöðï]j`CáÎåz-Ú 9á.\º+ tÕ=iÏcZt°ÓJ2ÜÎÛ`äc¢ßd˜÷Ì£öZJR˜$†\.½–!6ùÍóˆËÈ,¡ :i±çP4Z-D˜5ˆ ¢•ÉC:7ˆ\Ë“’=©eçÕH8ëÂòŽüðØ_7?l6祌æ ÃU~e»|Yþçãáü°yº à;.JwwwO1Û¥8øÌZd:׉´üù¹Ã<Ê¥UI Þ‚z3ÀÐC”qI2®Ýíμöô´WnÐæQ^¥Ž^M7kRŠwëGç¬;¿:d×ëÈf»èHÒ‘Ü›AAo=Q Âw †ÚÂ! Iv`Û-ˆé :uù"¦ ¡I¿ãÁIJ]5)R¤SÔˆ¤Xç‘瀧é(¤Ûê:OÚC°É P;YjQRÙÊSÇôÑ3 9ËŸƒŽ^VËçR/JY›Ü³]÷¸Æä›1¥ÌÊÔ(¨>fÐd>xAOþ ÛÎTý*7XnG—6°‚­  ‡=Ç#K;†wî•ôN²Ö“¾~}uòjöJÃß8é]ø›gÇ»yCêoÞ¤#í¤Šú1vfOJHÍzñ½EÙ÷¾¿ßó*ä×£W®!oI ð{PÅRB|E²Ä‹³nG>Ùu¦Xr] l˜øŽdój„8ªÁTÍ |w%åÎÁ¥Ik…G9f«J•*;¨á!Ö(vµ5ˆkƒH oæùL‘R” ÂÂcD# â$\R8@ô~t9šŸ±{`‡z®_04ˆh´ð‡ÔØ6dK¢µ}+¥„æÑl!üU.;2ý¨#v{6$^úQߎ®×Ëw•£€×nOŸ#e 0”êÇõ×^IÆârúß––tæî& üaRXA¥ ¨{â†$©¯½DXÛÐN¸½3={7²Î´«œ0ØMN*‘eÐFi«¦Ù½ïÛ«g6o°óNQK'#ÚmüÍO¢}¶—4½í\¯W e¨p…9%…ƒoE¨»«æiL¶# Úàxƒ~oKÉmÅô· Ö]{&+ÊÁçÀtƒ@c¤áÉsq6)7ó»ïu¤eTmÀå¥é dú©‚bJæçx·,k d„V!¦ô„ñå%ùìE<Ƹ>fýó³<ð±û¡ƒÞûóö(dA2³°Ãl?qKKÓåt~|ê{¼ü&ÃÝ“wëÅPëŽJ³3½;X×Án3Óº|§j?ªÜ˜úfÔù 5ñ7¦<,…t1Ó†~Jzd¼sf¡Òð*À÷™©ß|@òõH=º®¬ê¾*rCbÔŽøjEq9™yê šßò„ Ržó|ZãÏc%ÛÃT ë 5=™÷1ù’U *qdÚS.ñKÁQ ¼Gsäèåà&ÇîÂs{˜y’*½›™æp]zÒdI[·ö,J¬W% aæ†a{qq*ƒÃAÒ,†•Ò ÝÈǶå}8=|Þ|þúÔǺûNÒ®™ Ô¦’³˨·²Q=^µ’lCêeô£\e÷§°ñ·q3QÁÍéÍ4äj²eħ#ñ=ë|ÇÝhWÕƒK1;­¦g&­Îß?¼#Éqˆa†ý«¤h¾†6ÖG;–PX7BφNú>ë5VW¤«YÛdw””WP4g¨6(¦Vã6Šg#­žJ«°í$w¢ZKRWsÓWÎw¨úÌ«8ÂÑ4èÆ iÐÎ¥Kì^’‚`(ûŠ„—|÷Ö#AïKã!ƒàý‡Žw—y* ý#¬›¦nÙë'Á"£*•µÖ5½{.9͚ƾìÅ<¸!-¯ËzÄ6Ã)LÂ!Ýš%14—&w¿Y* ¶¤ßoàsyQ3îßñ%¶¾ÈvÖovÆnÐÕˆeäË4·S9ìôæ8ƒ…–ršXtt!Ñö ;µc |Šf¨úh–ôàõtºž•cç6‘JlP¨Q;í0ݵ•”ù`_´´÷Ï.£ÍýéúQ-B"“$(Z6úÂ`´ð–ßô×NR¡,—‘ wÂJwðTŸCìžßôèú¬·¤7ód¨&‡]&º„iÇòX®²¥¶¦¥#LÄf«}®Û(£±ïÁGH€Ë *$c¤µŒ kŠÐ±Ç ùŽä]×P*…I¨Êu¨þ‘XmZ„¸ØlX©Óf¥ÒØæô —M¸.I¥­V$ÊqÝþ+qIÜ„Uv9Ú&’+Zú^}’ꜘ¨òL]gmI"ôâ– B`ˆðà& !ÿ@s’nÉ^ò-…kÒ ¡V;Ù|9?°Ã÷RGŸº2 «BÜ)|ÂKÃÞæNµõcésº'Ýé`÷ãòzw÷õõ|ýþ²™,üûB&ñ&¥¾"íüÆ*žuS߈äðú†îªÜšÞDÙÇ€øÜI«ÛoÑ‘˜ºúª¨·RU]@!y÷/O€]ðU·&ëKè7Hdq]Éåæ9—H-KÊ×ç¤æà6ù‘h·ÕfÇ$ߤ¦¸#WÄ1Ó*it]^ßp³=®´„LGÌÙþÄé£_:È=¦&Ë©[M÷ᮚ ,áùÆÍ`ËrY,7ì,©ÜÊEŠM‹\°}ãÊ‹Ù2äÜåk¾!õÉn³é¹•S£Œx¯l¿`ØlP†§òïæíyÿhÓÝÒ‘„ÞðߨRSrËún-¦] [Czž;„ð¶Ó:]–æÝŽÝ!w»+0ØÝ;Óò@[¾Ó»^L¢ìãIݾ pP¦êkÚŽÞ•\'´‡–t Ö‘ vb¢“]/wU9¥»š–ŒØÍ NŒê” „ûMVІ<ŠÏIÕÀºÚr¼Rújs甈s i$#d½\˜ä1 óœ“üÁ[‚VªÉ|ïãá£Ù‚Û9q1÷NŠC…“\~ˆJŽÆNˆ°M+­Áù1ŸÙÆä¡„b.¯Ó±ß>Þ|>oº½xlZôbLâì( x¤!±?\ï¹’lIú‘ñ†Ž€Û¨?F?wcøûÙV£YÊE¯Ó[0ƒcµ„ù3T[–v“¬N_Øëa/áìNePäÛqïW!4œj° ãÚ)ŸÁ«H#^ì{éø“xŸ«ª/FF»6 CM¼o¯ ä QKÁmeªU„E¾“ª·&Uú…'¤ÊUMÜÊn‡È6Õ.’¯Iɇ'§• VJسÝpþÓ‡^¿€n[ükxòëkRÇ"ªQÞK¨…JH«©e9{uÁø«Ù&©P–,Ò­0 Šì4Ø ;ÀÖH›±«ê;4&ÌÖ>W$d4¦í„ãõþéë]€ ¿ñl×áC#²ŠVÜâíR_F„ßf¼7Ééˆñ;–üI?ê¡5ÿ~gÜN­Š­’öAj0†ÝYì¿…d{ ugìtERÐNV$‹sÿaëG5x@-æaˆâi•ÆØq¹/QÍÒ"‘j[å‹™‹Ñjº³ÅBÆ6ëJ^hëf ƒ·x²m gëòÐÎ º¨Ó÷€úÐ7…žþ»|nû§ug˜})@2/À5H{” !–ŒZzB/`ß•Uµ…J#5DñåC3“6K?º^žýÙÀI£òŽ6…„l„èHñW[ªôüùéNÐ﹌z%}ýǧ£^ssfÂwŠæHÛéÇ£'‰cÝäÞ&&’U,ÿ…ïl=2O¸\|ýÙ+ßîuï ;^Ž6ûÿ´K¬¿ðýî;©!uÿv—Õëö`÷XîH³ZWg(T5ƒT¦œYaÙ¼ÕP 5€à’JÆ[HÄÒµ`$ŽB×£0³£QE¡=)#vÏón»JFPNYÌ®u#Zìÿq¯"ç×u\$¡Ôñ€ÿ¸,éú©K+.âØ*჻àU¦ä„ïäþŠÒ B?±“ƒ+„Ý >ãpŒíMã|ÿyÓãW¾M+<¡ár9 šè¢Üò|·Õùðþ$Ã×·¥eI:u?¡˜z\ņ ÕEìf²ƒH'·0ϯb€²,F;Ù’¸xX+èïH_.Û®ì{×;ÒžŠdxîGïï겺´#?" Áî4¸~Ûd×+©3VûI:’'‹Õ|†µ2 “GlDaZHu>ø¨'d«nQI†2L–~J óJAÏüU³â´4d]bDJYÉS)éÑïSBL¶{©M3Ñ ÙåÅ#Â!z&øõ?zV¶ÖÒ‘ý#ÛZY]Àšy¬9r)¡û1[­P/ s0v%ºB‡è·,Ÿ¸¸^¦ >5*ŵ"¹e¼$'õå¡^;žïŸîl´ûMq»§ó¥Râ`Š$,fw¦ju!ù4TÐìØ·‰;w$& Õ*.üÃüžŒvŸ¤#)œï±{öà fÐw, ªr-©ðT úæi{Ò:Òh$}ÞìñH“¡vîñ¦B¾*å44LJƒì€3†ÁqµRX¦¸.)²d"»™Âc5àc’ ùÅ&ý”¡Šé+^\„(E8b¢½jÄKUÛ ÷ *Ȩ‘Ç`·Cù´ÔÑò’—–ÿÁe£K„£jaßâšá•±”<ÎÉáþ2z[fÿHÙb.Ýð¤ß:Kȱÿ4­LîÂáP78»Hdîú–t§àw¯£ŸîžîšNQV^¯ƒ­3‡ïídMšÐ´®ÎicªÏfw² ðaRÜ»û¢,ßyƒÑŽSùÄJH/°¯ûd )Þù:Ù 1è¤öùWïGçj0ê·X6L,£ ð(¦0xÄŽun¸Õ²¸¼RleÏ™,sÙˆä-†P]Šsn©±Ù¨ jG}„:ìÄ^³ÿÇd+Ž·ÔBóô¡WXFä®_– C¿aNs_’®Ÿ–—« £}vf™‚v!A+­FÿL›”ÈFY3Dcø…ŽdÔ°YÒù0·”n[†L™ì•|Ã]Eûèù?w&¸ 2ÜÝ=í¯sºCšÆË³¯ÝóîQ¸Ý­úÑl¾&ìf'©Û #•ðÊuõü2 jwî, »Ü˜eP”Ñ^¢‘ö\Bœ3æÞ[4œ®¨žÐ@U¦Ý‡zè·`GCª¡Oµí‘í N ¾Ë ©0¬Þ;ÒÔ€¶j¦AÕh9¢*pƒÂëÄ ¿³nNI"´GÅèƒ1÷ œ²åE³Yž×>”ðÍF'—Yg”;ÆòP]×REŸ–W‹ŒŸ* Œ7÷ÏB›@9à@`shŒÍ¢¼´¡! e¦ý´ãéÜ»û+ûdÍáÀèÞÙ©;ª7h³ž¤lGâùzÿ$øÞ“¾¾vº]òÓÿ2žã„®º* QF0Ín§;S‡ïÊhC'Ù‰³]oE»~Lêt‡ùãû— ’úöó~¶h—^Mû Øõ{ü 4(v. 7Jƒfš³ïÉòÿl¶v²#‘I¨Á=–2bWÁ£¡%·üðTð2ò¬êæâ¦ËÑ„yé°I™‰x$! Ó µÁþ´D6¤§¡|œiT<„.') ½õÿ‘@Ä{k.ïÕ¾#õ-É4³óTÜ:fØù߯fÏâÈ6ûhÖô0úO”’!7w·ßEÒãçsÔp×…ÏQâ¿–aø\>4oߟz%ý&íˆÑ†»Ï§—Z0ìc8Ÿù`YJ¤îåÖrÒ#¬-MUL„4+VLï˜i·«Ro|œ- ©_dÜ o¾½³Kƒ!v{ 7Ž wÆâ~ä+’` |ÉØ’Zkš¥Që"¾HØÈ‚yDHTi\gšœÎ&[õ R¤l¢“‚(¤ä7øÓ•:ðÿŸáÁ‹Òi[•(Hž%‡$„®ÿÜÉæmåÙÁ)…0渳„®ÒŒXÀoÂÐÂz 4•!åre@xb¤dŒ#ÔTŒMn“|C꤆¥!·@h $ÎOÙƒhp¿n{DÄ·õp²[ÒoÒ—~ëhCyñ­Ëíƒüë¸G’³B¶Š¿ÝK…µc;âg¹Æ2Aµ þ+W(¼ß•:’7uqËI;¿Ë%ÉÛ¹¼³?ƒ†^rCzHQ̧€ëT?±UŸÒ¸’$°OˆÙxpYuÛ|kOIK°ÉÀd—+©Z¨˜ÇXNÎñF/=£ôEB]:N¥Y-õAü*x&–tyŠ=ªŒ¹™7‚Ãï.i_ôŽd5a²dמ^¤Žº»b8¾è|•6»¢1f6¤û˜­R¢ûz9Ðà/¿¢^N÷ÜX;dn柜ÒbA޲£ º“y{~´–ij]_’~½N(ó‡™"?5óM9£0âññUÔHÏ‚0¨0–Ww"93‡Y’úh÷pÞ+ܰ—n´ ‚K'Ôžø!vWç`g“·#íÜ’.‚58Ø€fªŒÔ7" 8‘aÍfH¯–»”U\†Ô}+)c+µ¸Æò÷ÊJA›/Úà¦Z‚*ì%1S(r ü×LÈSg›ír2Qœ'kŸþ–:š§Ú†Á$ïdŬ,W¨¡ä!Q¸ @:ÐÌËœJŽP¦¼²&B$ƾOŸ‘¨ -ÇZ f-´úTgþ¬.üü5NI?þ¨2YZqø†\!­vœáÙ5GÏ»°°³lXa-ô^$>ß²A±}±Ø8<Ë1‰²_.B¶ã-i¯ pM5è;gÏ #«²i€®îUl‰ÁƦ=0–,":ºpaQkczlC«ªu¸ŠvlFÆ ^Xq;%‚+ãûV’Oâ¨j¥XËóVN"SLÇÈÈDìAQ¸2Ú~Fêâ¾ šY‰€T—,’Í…Ñå׉MYm5Êâ!Ùaå²¢>²"}Þßß_/DeD\40<°:_×O þ_À‡·Ã½´$…À;Ú Áe°k ¹üh‘ؽݼ3åÞ€Ùí8¢¯¾½í¦]7V5Ó Þ‹¸'q/â÷ÌjõzýtzglÛf;ïGò‘3›oõúé *‰=9£áV'W9 ]ÕJ‰W$Û‘ª Qkt$w ö1‹Ì-_¿åQæ½Ê‚ŪnÞCÞóÚÉÀºÒxO£l}àæ'’øüo` ška`=R²³Õ¼UýV#fßÇËÜ¡²›¯vesÿ¼VòGfŽ…Htõìù­ËpÔq?­aÅÃ;nV34»«RÒÓ¢v\zÅýÒ¶s¥2Ø%¹dK~ /$eÆ *ÈjÊãyÓ»·úõ‰íô)´Ž?úZáo¦ú<«à DÕ—ú¬hƒú2t <»i7UëF½Šx¾›çŽÚ±²¯ï>ï{O7—õh¯ãÞ#z畃íÎen+’¡ßµ›” ç±-Õ¾—:’¯K-úÔ° ³]¯£¹¥O¹„«ZÍ??”å¡R—6T\©šîH.Ûi4æ7%4ìM‡UM¸Á8´A/!úØ£ qSì/¸ÈÌiHs2CŒäÖpé¡ä–‘ñ‚-rh4’k²­xR¹ãtØMJö÷Ÿ÷WñõÉE òè=(m@᪞#×i°±œ·÷Æú‘Ëéîñô¥BŠá(DÒKµKÍmžãÉ |¸¸;íÌþ‘G¹g¡0T5Ðg ¼ËckÿûÚ©Ž"èvÁgІÄÐ÷YŽMʱ;ä7$1j¸ê†´þÊ…µ5ê2W[*ž_1ìi?Á9ä ÕAkNÆæ”:ª¼<ÄY e5Äå5(À NɃ«àÓT³·þ¨K·G4­¸mE ;È›°ÏåÙZ1³Š‚G¿¢I(„SáùE++.„—¨Æ¬:;eæjæ…£!“Ýy;·1âƼ”3>;a¸(&â"޾Ì̸Ó2âŽôó%·¤g2ŠÙµ€JX«RPv×I¶#ö€ìv(Âb}Ž¡¹vÎu9Ÿ%ɱ2ÔñvéöFT5Ž;A*X§NßVKrG’<—>¥\º…þÇ$¨øÙ™«%*’ºÁH¸0­O±~ìᡎU¸²…óAiŠôå!…‚Lqʉ–R˜S«G!†‚’ŠÌÝNЋÁ¹b¡ÍȲAQÈ~°’(I›ÖÑ•u}d«E’ð”Zk(rRNióídôø”5DpØ•Ýår=ßßwÈ®†+œÎàú;"®sp«]ñý¯R/ç§'»É2Ûncîv§‹Ð–’‡Fʰ´©;¨îT[ÑŲ) OЇIºàxŒîu…¬áßg>Ⱦg¢*CuÚ‰rV,§[©átõbRRƒ(c·>Ùƒ!d¹Ë¬Er²iÅ£‚ ~æª9o\ꀡqýj-å¶L°$‰‚À㡵lfs[¨ š»¯ÝZB’æ‚-U[JV¨MÞã"u¸³¸K¿„TSõu!JëKK£êp‘YYøR6—¤õ©k>Ëry ¼óUöŸÏçíÜ([Æàš” I¥å#wCªPUG›O›§»;îG|–eE| †v6¼X0Øýlƒ\$ò±a {h?‰ñwo@‚ÖéWÏÕ;’¡v݅؆»} ÞoÎWtù6~—ÑU9`[!Ú©«Ý< i•*&P´† \ +ùÅÖoLñ ¿¹"õ§ŒŽý‹YQ ÙÄ„‡¤vâ1”¨Î’ŽÐ;2m(ßfÂs—’f®(2ã L“Kë‡YA²«]¿ÿÀâûht-š´b ¾þ ™~Æh¼—sÑ"׬§¡æÇßùpz¿¿?Ÿ¾Õ¬„E•Õù,›l,‡°3Ì»]~Íî°ºsÐnéHûk xfLXƒ‹TÙÁŽÄèöóÎ[“Ú©¾©FÂýšÚyá‘®7¤ÚùàÇ£y³Üü£–U:ñ`‰÷s¶øÎPC*%¾eCâ†ÔýÙTE1A.R5KUèH¡™@®ÝúzTƃO0„fe®øÝð¨ä—*•?AÌåvQ0ºYÀRàv°@­(ü‘ÔÞæÖ IíÃÝÑ}¾k¤¼°6–?±‰žZÛìQŽÏÃ!©x©@Œyt4…Ì£WzŒ}Ðè¯â”¨ ÿd’@K§ñ=®ÿW-³àvÜ“–i;SRnå$ª8•cz¼mIDATV¡”Ü8AÆT•ö$ÜNy&*WÅ÷!Y•µc°AцfiSÒŒX–?8¡áÝ»O(ʰlH[‹5û ½#)÷;<ôu¡èzÇö‚\h³f¨à*h“ÝÎ;ŸBßÒ“ Iz… 2°Uoù»ã±¼FÀU1ÍE2e|xܬ$Ìuâ´Ú;zG;yÓüÑMÌeƒ°ø3¨d"º¬JéìôØó æ—µ6dW´HC©”~`íοž¯Çš¹ ÝÊhT€2ŸnÅ#F†=o„˜Â¨ ½#ÍÀ*ŒÎ yjÇ•–$ëõ«¬j: ÷ÌôðNÒ¸ËÉf¹‰!<¡Ü-iž^úÖö*³Ý;“ ¼å¬Ê‰÷\ÎöÄœÉw6KUýÕ8Hw¤kçqGºØIu}¤<»!•xoÍhÁײá½GF»i™q™oÙC ®ðUi.žHîðvËHOöÀàMñÝHª@ÌÐÊD×c +VJ~¦ü{³×ª ç¬Nó‘ǽk;~Lc y¢ÅF@¸kdÇ UxSz" „¼Ã€Å6+÷0 ä: îü. )ߢQl˜Ê´Àfhr{Ñž^Ÿî¬!uÅiN Ú,¤À„Ôs«Êéyç|‘Èî:øÍR>™àïçoózuøû v¤« Ù~IÒ0>Ñ—÷6…ŽªÀTµ~Äh•ÒA&;ùâb$·l`´¡º¥]«¹#­¢Å²©®H4@ ¤èw¿W«–¢6p òŽdÑ‚¼ËX¢œ"e у†Iu‘›.Êë ì©6xiHIXର“TSt$S.±‚æ!3=¯Ì!釕yo…( HJ@ÑidãB:þÎ ‰Ü̈Âðäÿ¸QX#“@ÊìÀ0'¢ùºÿ‡¤¥#æ¦t¶½fÌjÁ›âÈ«G+Hg½Ý¤!—,5gÞ÷¬ñæ|>ª,–­ê%?³ŽBIçÿ&x›{Kczw߯{q¹PU•¦êG¤­ÝbŒ6l°jƒ dÝv‹<|"u$ƒjb0Ü¢Ö­¼Oˆ™v½!ÅŽÄP!Õ–O¨0‡ç–ŽþMk‰kHëhª™„:Lx¨"O‚í!©(ßšÐS‹À[ŽÚ µ¿A5ú3ëG-A] 6H¤¤èè?·Â܃“H’ Ót}gØNïHOçCõÿ@` ]™ 2×½(¥œ¾Y:Ñ•F·t÷;uŠT‘_µïóA6u$nHgĺ6INh½¥–'W8Äj99H¨ßÖ’|´3kjuDíjö ªJt Ñs‹µ*.B‰Yö$ä6Ôá$¡Ïn²ZZíú‘èOà- Ìu‘`9" 9·8=ëS¹1˜C„ÈX¾§UÄxEf Ü®<»¡å•©%Aê ÍÄ:cØ*ÂL jèÂa—\ÛÓÖ˜:Ø(ƒìé¸ Š ÿuC;ÆheùÓú’tw'“Ý.‘E»ÕÕùLž¤Uå«lbz³êây® )Xc.JØ*íHÞ:{¨ê´7UáÚq!I)ØÝ[ÚÑ* $HgÓÞ‚Ñp ¸NX ׸"ýæÑn79ÆuÑ‘¾ò)­OÙå¾d ϱ˟!×SÊ@<º‰ÚrîÅãRd)M=%YBR¨%ûÒ2'À—+ÒF©`Q ¡Z¿Þ±–õ°Î ÉHe¥Ã|ÜÀ“܃âQ Ì%d6¤€¥@U‚ËžÒS´4ó—–ÿýÙíV¾üqPm”¨À¡¢UL r3lÛ;žX”¤`ÃÓû!üÐa¯J˜$Õðî7Ë>2ƒH±r¨æyR'©¶ &]FcÕÑî»)û”%ôn¦Äl94$u :ƒ¶üÝHv¤­£ßFý–XUš×^Yá<rò6Hì꾌íhTQ´I;R߯d ªXEA³óU+R–Jz~Í«èéã”͉îühlÉ„ˆÒíiÔâ,‘H‡oW••{ÀÒÎKž7K¸ ñ²Úà¬\W*I.KɹKä±—-ÇÄf#ɲr6+ 5Ah”hàÏ&.xKûZÏ÷½#ý(ð÷ãU“d ÃwЫÈþXCÁЂ$byŒvµ‘ÀtB_`÷|ïGÆkè4;~]V¤—ŽÚäŽ$7YZæœØó^Ë(‹’p‚kië. &1œ+éÈb¤^G¦ë³<ãU4ÆNè]¼‘dï¹nSÚo±ý3³S!¶£šŒì¼ñ­lƒp_²¼aœ pþA×4q¤à@¤‹ ÔU6{w-Jf­âô½4$6±;ΰ€G>ffS ÂõÀE{®tƒHô¡'ûmt0ƒŒ¦#Ÿ¸hô­o£¿%Ÿ1hÊ)Žy62ã.'€?>Ýhw·áÉ.2rÊÀˆ°A•Q;ÓûÑŽ¹©ZO܄ĦA˜A½‚$aLjØ‘¢t’¢<¼ôsO"¢á8k˜—ÓP]N]6; ²Øðò%bI=·Òn4åÃI0œ@à/!|E9{ Ô0Zu!B£ÆTI’«2 =ìôK™v“„ºWµt àO±äüoªpÐýì帤á§€_# ¦C0’7¦|ÙÃ"Ê&qòŸ?g˜* Ý@ë#(æq9HÈá·'¼· v Î;Ê ~.NFüðÌ¡ÿ~Öd¢C9d3Óó½mîV¾EÐæÌ߯¿l`!2áÞ/x+¶ æm* Æ›oñS6Ю\â±Ê@øÒ®êóüñ]LN’·§Á°ûwëMâЀ‡Ø~ŠMÙ-®@ºYÕ®±Ö‘´”i‰£©#QCÕp·_iiH_‘ÙW )€Ëé€ý`Øå¤nLy –- »aM¦6ì>¥¬SÊ[]WÇÐ í4Ö’Ž LäÞ£aþ°ä”l設’•½2ÙF©Éƒ.‚2´eF¢×»UoÜË ()#Au%KDZês̶ûïwŽ~ïsKVÇ«Ü[”4/ìY¦·7Öɬ¶[>²óä#âl9iy}©Ö‘zg0‡H9$ép·a9û×…5ñÉÒø€¨ üºry¸nÃ)V®±Œ4ô,Š)u¤Ð# o¡¹·‰¥šƒ¢"—­­Iô;ívÒ”¦ÉQoóUTóDü×DµOßiIJDyä @výA­üHögo#y„dßÒÎC²ÕCðA—¬z&´•H-üùáÞ••Hƒ©ãàa‚¶†ý9 AÙ(3ŰJäÑ„¯„À—ÑÊ´Õ ý>ÔäX vi9ä¥pð¦_//»å•'µçº3€n)”¾õS‘ 컺<”^DË5©Öœi gIhy—LKkDj¦zÒn$N')ßÒ"—M]®Ñbž/ÖG»ÃÇÅF»ÉïF1Ç¥¬rt!öìØ–+i0®OW¤ŽÚuº~+*ûÀP¼4á!%n&ô”(Y0¤«6˜UAñþÏ–äC\nªOÓ2fŒïËeB§Ê0ÛJìSZÙÍe‹4ù/x#ÄãeôR¡ôDB⌟<§<‡‚wóªë!Eβ'åaÐì¿d¾îuGZ:Òãù0%ŸXÊY€çwìN¢Å< V„GÝâÇ#Ç„ m»’¾LìÞ¹vz‘=É©Õ ¶lHÝ)“TA|dl†ƒÒì„dŽvË › —ÔÍOäᯠ]$ÅöÄ©e¤yŸçšQVûPÔëÛÈ££ÿò`ž©AæÜ&Ú9jµ9ކł›ŠËÁJ­rô#æ|_.a™]œHW`¬Ê¦Bƒq+£s2z%eà?§H­RlzJÜ#\øPƒB‹u`S ŸôÒGÿpÄX ÉP»»¥.5(]L-“‡¸g—í©Ñ–Ø?î&QHȱõÛ•ŒqܲôåíY ;’åN¦gÏ­‡Ä¯SÁ¨ì ëU´b³2EŸTÒ‡ú¬ÎÚ ùŽ ÌVó­Õ‡ººòÒÝæPŒÔ“פ!í¦°|„ÓTÔ$—³âE‘”•fé\ƒ¸§m¡e4øŒ3^t·Á¥lú NUìÄÞÞ Ö®QHM%j½€Ú¨¤“~)ƒ+¾ÿí†2ÊA¿WÁ¹8KM€]^²mk ›IICŒ3ÓŠ“¨>fòÓçí?¾²²ï§ß:eõˆAcgxª`°]Ùiu‚$:V¯]ˆØGç?ßÈKßËŸe´Ób9Eñ¼Ãftæ«‘j`OÎOEÄ[À×–_þ]¤ßÇ£'ÈZÐX‹mH{U†¼Ã¥Ý¨ Ÿ+:øÝ‹HÊÈ@»–Ê©†Ý%³É!Å%1ƒ+¦y? ¯HOIISg¦¥Ý°iz62h¤â•Uqü_GLyIt‚‡F°©"ãæ”Ý!KVÓÅïÕíxµ÷”xŠÈ°eÁD£ØWÂZvˆ¾H#J‰¡:)»o~\uGZ&»FAÙ˜êvËE1ìg‡´µ½ ÈL¸´ igÊed^ïH|Hâ&sÒpò÷3$ˆÅŽ8y@na`Z]'3øåˆùuÚ~óŠd”U«¢š}´# %¿üuBØŽSÆf•#É IΞ0O䆼 °^‡!%ÿ(JééùÏ·ƒI]Ž<W†=Ðß»ÍÿˆåÊ íx²¢,#?í' 0œfô¨1ï€+‰òete6Q0õ8J1=XßÍΉÆÞâÏ£LÇÅ$­ÌzÞy²„;l±‘ª_ãXt¹„Tr½g`Ï.%5ãšjEPn€ËQ„}ÓºÿP£qº#æ³OuÇ ‰Í!©²7´8mG·Úñ{¬Òú“b%ZRÏäXHtÉÜpM ? (ÜûODx—UKʆÞ9W#ýá`4—§GX8’=wAú+• 4M 4Ffša*ÌM¶úJAh›ùúØw¤»eC:Ä@SÇ)87àÈöÌ.¼Þcªƒ'%hNÖŸß?²mÃv»ÝÓçFÚnXÅ—Ð%Pn]‹ºÚ8A‚1m®“slެ@–·*£6®F@TÃòšdEšºåËDÂXÕ¶õ÷ј=‘Aâ’£WG†÷Ê'νqÛÍT„ÄÉÓÀWʾDm°i+¹ôÌ>L\˜ØòÖ•™i¤ ½\r òp Ý8Âái•JBN™€§«ø;ø‚èHA ÞQ ý©K!±Ö¼cë°ZŽT`äžä&“–žvc ‚ŸáäÎÚ]it¶ã)M IËHŠÇ®2ÅmY°2ú÷hE:Ð ª“fÔS(zª£ȶ‘Ðp1yìÚv‹Ö6\ ³›*Ãu,Gbÿ/¸ÌXöáî^Jé-ïÛqÆ8mA‚V’з$y…ʹÚ4guVDnÄà}ÈǹC”P¯¢Þz?ê$åMèíŸJ¿P¤Ùm]>eÕœ0Î¥¯F³Ð'<´ÏHf™‡jØ&1>é–¼ƒPA·Q4¥3²‚gÙ!‘™1ÌÙùM> ”Œu<˜P†ÇÏôüï\Á}ýÉ:†Ì_ÌK*º•ÐLØÑ+û¿$Q&-À½§„0$Daɪ.NvõðÞG»žŒt˜â×ÂgzÈÀô'ºŠ6‡5›z¸ A.·róhÓ|~k‘$,¡‹µ›«U“”Ð!ZÑÅ师ºnÏëG*h)¡­¡£V‘xÚ)A±¥æeòOQºTPÌ^PbfÖjÕô´–l¹›éTÒ‘â(s7ã£à•àl8{ŒÀ2ˆ §uŒ<ÏéhC‡¨_š²<Ø·`ÒVV*¬,ʳÑç»lÎSnZVh lNW J¾_`£³•gÿ70¤^ R{yxºãÐËÓ1{âz3çJýT·Ú©NRKi¨øÖr;ÂUY¦å雓´+ÁÞ|’륳½¨'ÈõÄÁh@ŒuóÑH‡º¥ŽŽZGÓ$^\AòY÷ÍïÕÑ͆ļ†Ê†ÅaVDÃ-© p‚­v¯F8ˆÈ› t&õ§Ùõ14ù!Žô9²b帚â´ZNå*C^2=iG[ÒB8Ü0œn¬;£#P H"ã'ß…ÄüFä0”9À™!ù+„÷à^üû§»ÿý“Dõ>#š0E T¾Q§QõH¹êd2²L¼g›þH(—Ìv2ŸC%e.æ8/!‡: ÈjG_dú/-Ò¦ö/ ä_µ¢a}‘¦#·2iHLY­SM§Ý!d¢¡ÃwöV$¿¶„òÖä>¢œ(@Wò0¦¾B¨Pð¼GËb‡¡l0˜ÕµÌ”%|ÌË)ì‹3Yƒr‚«1ÅéÖ-)ùÆr”)™×S|…ÐB‚¼ îJ-唫w]ßë²#uìû0…Úx'è –l*ÛÍKK^ß±Ò´ÌêÊnQ.•½#y%ð6…ô.©ÿØ'5Ä(÷‡}Ñ"Ò‘nêUÔ¥H2ÖÖˆ•Ùc&8NU ٽђcû±š‡»:UßÖé³ë)±¬ÝOº‚«ð`OÉ´¥Ã½íöe}™Í9 ã)˜F—RvܘR²:ÒåaqgÈÑ¡'Ù½¬ú”õFºá4~Pqëô(¡Sɶ ½ Fãï‹õ®j¤ãùOOwOO¿ž^ZRÂÊñ“J„ƒBÄÑxõcöŸ’¦þèç‘,J&¿†ˆ«†¿¾DÕ`Gš¹ˆø­ÿþ}€œìˆT×#5´«¾ç@ƒ ñ“€YUù”Ã!DŽÉw¡6µÁØD­ì9e´'CCv©¸y¨Ô¬%ç±à€_ÈP‚þ‰5Z0#¨ÂÔ‹è^úwnö) ë{eÕjýPq–›}úø×’ýŠPO9“ÿµ kŒã¬%¶ú¯vz(•l³™×¡‚NÅáÔ ŸõbœØb¾+Õ,¬‡÷÷<ýãéWI3'°ûÒ¿»±üߥÿlEa"¸@`¤Ð’j1_³ðV£­(oBàÖ îø±ãf¯Ÿ9á üÊ•ÄiR°¡äªÇc Áuh'É×¶fæAÂXe,Cʨ6·Flá×2A!¼¦ŠÓœ¼À‚#ЎƘÔ0=¥ÅQhA» bg.png startup.png fheroes2-1.1.6+dfsg/files/images/platform/switch/000077500000000000000000000000001476115357100216615ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/images/platform/switch/icon.jpg000066400000000000000000000603271476115357100233230ustar00rootroot00000000000000ÿØÿàJFIFHHÿásExifII*2&i‡:@2021:08:03 22:21:55jÿØÿàJFIFÿÛC   %# , #&')*)-0-(0%()(ÿÛC   (((((((((((((((((((((((((((((((((((((((((((((((((((ÿÀxx"ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?òR§šŠhÃ:Õ×]ÃÞ³îîÙâp®H'Ò“vÜi7¢+AÁëHFF Y–0ë¹1ë‘UˆÁ昈$Lö¨ÈÈÁ«Dd`Ô»MPš=‡Ž•_eÞ1ŒžÕé÷*»Ä.WÛ’? —%ØÔ[ÙØdb«ºí5jšË¸U­Uç¸ëVYpi¤d`ô  †º Ã:†¿s¶Æ,B§\?§Ôúûk¯Ð¾-®·pú™ó­-äÛ 0ÇâaÙ}»ý:æ«AÏÙ§©\.khSøuà·4z¦±ú ù¡‡úßöˆþï·§R½V z)ü…¡'œº•<Ö^ž¢oG€É ƒÅA—d’CÌ9À¸ýMx?Ž´åƒÅº’ÌI|ùIfêO˜Ü×=ªUp–¥T›‚÷t±ÔÛIàÿñ¡´íÿ,¯×Ë?÷ðqüêYþO*ù–níèñ²Ì§é‚+Î"·ÞëQ–v;Ud“èz>ƒð{Ç“Û ­>ÝìCsƒ3£~;AÇçZUP¡oÞrßúÛþ’©í>(Ü‚…·ó¶iÔgñèÃ#ñ"¶ì¾i:2‹~âPsºúáSó} ®_Z±ñN…9ÓõÛÍJ;•ÉÃÜ»ê <×7qŽÅä,ìz–95‹”§½Fו—åcxR®¢{…|Má»­mt]ÞK¶X%qtñˆ¢j’qÿSÈõ¦^ ]Kþñ® àÔ8ñ±s÷c²¸f>ƒg5Ýj-³QœvÝZaãVJYþhʽùuî6Š@r2(¯Hã8ªÅ³;*²“ý¸Ïþ<+*ÊôÚ4¢í4pú¥¼‰ª^ G;fuéþѪâÞbp"ÿÀMuºì&?jF1;ÌçúÔöQ ½ë‰åŠÐêXU&õ1ô0žaºaq€Çë]=ª[ e€ÀÅe눠ǣJ­n˜îhö^ÝsÞ׫ì³Jö=Çà‡‰­ü=âø-ÚxZÛQ+m(óŸ”þ|~5íÞ!Õ|àTFÌ¥õÙ,ÒÅk¸¿?ÄÃÓ?­|ahÏkd¬†Ô‚~Ÿýjò_|iñ}ö»#øa®4Ý*?–…¿,=NGéTûª\CžW­sSp„œ¹oEù$uË ´uúÅ» kGK?‰še¦¡2‰Y8²:ƒ[–ž/øG«ªé—zFk ;Qñ±‡ü·æ+çŒkW?ðýV,ëógÖ»> ª.u+_]“üÕÿŠuy…¶õ>®»ø]§øGW›]ÐnŒºUÖŸqÅ)Üѹ\®ppzש0:•Ð¥aúÕ‚>%ÕµOêºV¡p÷šrB¶ÅÎJ‰$ ·Ü8ú⡼˜BæE<4¬ß™4ð°”k¸Ët¿7ÿ𲿂e˜ßo¨¨‘ƒ Š+Ò9Œb5Éø•<­FÝÇõë°‘0r:W9⸲IýÖÅL•Ó*.ÒL¥ãñâ9eÛ:$£ê?Â’È ¥KâÖOìýõÛà01÷CëYözª¨Ý0zòœ$â¬Z3Šz±uáó[\ÿJ‚’?:ŸPÍû@ÖJóÎíŠN:Síìo2?Ñgôû†»èIFšRvg".UŠº7<á}GÅúìZV’ŠfpYÎ5Xšú÷Cð}¥ŸÃÃá;[Õy"’Yþz0<ãÓ5å³¶‘6‰áýÄWÑI’?&-ë‚@î?ÖoÂŤxÒþoÜIês•"Prªvùgè:WëûJ®6¼Wü7æŸÉy„`â¯Ôýµ’Úæk[”Û4.Ѻú085œëµˆ5èß-l´?[Þ¼ËêXŒYq“ø‚¿­y]Ƶ§oȺ_ûäÿ…rû)]Ù¤+A¤Û8o(Õ×ÕôX3’º?Ã5ö£=Ŝ͕Û"¡Á€QX—Wj¸6Óþá¯b”¢¡ßCÈ«9É¥Ôõï}—ÂZÝû¶{Ø¢É8Š6ÿ1úU`r'&·ü'jÚ7 ! )-Ìsܺô9‘ÄqŸÅ®j7ÁÁéXáýêÕ'è¾íP©¤b‹Q¹CíE3­Øb!5â}ú|˜Ûó Ù¨î#@ñžŒ SPƒûGáõâ(Ý-ŒÉr¾»OÊß—ZàíÛ+Šô¿ ÷ëc‚¬lïýv:ýU]Ù@ÿCj€Å-åÌp@7O;ˆÑ}YŽýj®›pDµV8oý ×ið’ÄßxžMRX÷Úi1ùûOñÌ~X“>çùW$×ï$ßvz±•¨¯Du¥NÓlô»cû¸vZ¡õHñÞÌ? àâ8÷­?êm×ådóÔy%ÿ¾à’ì}ËùV ±S‘]Ø(Ú’“ÞZýû~<ªÒ¼(ß”TÈ{Ñ]fFœÑ•$Ž•_#5RXÊ:P/­EöME.Usýáüéß4v×ôH5ë òÕD7 utþ ¡ÿëVÕýªÝÛ†±<%âxt½sû>b’)ÌLî8=c?__Z殜Z«›údšörٜDޝcѯíÞüqçÆá@ݸ28¯¨þ?ëq¯ÃÍédh­îÐ#¯ó¼nßš^—ãýS¾_ MpCHåÝÏD“Ó'Ú½ïâW„´_ˆ––šl^#°·‚­i ¼ë»… dç©â¼œSŒæ¤úÚÿ}ôô·âŽ”Ü,—M™WÄš~9•‰ÿpÿ…cêK&¯v÷6I¾d¼ïQ]/Žþ ø¿ÃFY`‹íÖ‰Èh†Nÿϵrž¶3¬Á„‹17Pp8®ÈºPNt]Úèúz­)λöužGÓ?³ÿ‰®,~êÖó[‰fÑ¥Ebdo›çÎi,¼wá?‰šyÓ|i¥­¤Å¿tÌ˹}aÁþ~Õða?¶< âÿØÊ‘ê× ó¯øyñÛľ»[Húž›’År2ëØõô¯Kø±á]Xð¢øÓÂ;/‡céÐdqëÿÖ®pMàωíUõ¿ñóm¶µÿ}q; ëü!¢éÞð¥ái5JÆòMĤ,’ªuÚ7p§ÉúW›]Ñv”=Ö·OKÀ{vÖý.tR拾ç“|5ÔuKé×%´÷— ß #ï&yÉè¹â½³ÆCÃVÞ"¸ñEå¼ÞÄ ·EnÞ¤Lç 2G¨â¸]g⇼%dÚg‡máÏCo`ÿxúË?Sô^{Ey.»â-CÄ—k&¥(GÄ6Ñ ±D=¯ZÒ W—55eüÏô_«ÓÔ*×KÔéâ¹>hØnR; †Š( ˜À©ÈåOQO¢€ ‘1ó†½Ãöuýž%øsˆ|C–þ‚L,y(ú“©æ4#‘<;u_›%OÙïö|—âMÔzî½¶þ†O–0J>¢êyD=V0xg›Wœ”ûV(¢¶·†ÞÞ­­ b†Þ H£ Š£€à@0:R¬2 Qš6ÉÝùþ*¿MxÖAÈúâ€3(©d‰lŒ0äÐZäu>‘â‹…pd´)²(ä|€îù'ëùVs𦓑­:n£j'I4E‰u'v0W³Cþ{ÖLÐyczó8ç¨>„zÖ½½ÄWP¤ÐȲÄÝzõ¾”ˈüÁCFåÀù‡øóZne¶ŒÆ¢¤ž ú¡û§×ÿ¯QÐA<Š(  SõÀ$*œá±ßÐÕr0px5¨@a‚†¨Éo±‚î¿‡Ž´ 5ÑdR¬2§¨§Q@÷»› •$ü¯÷³ÛÖy$zzVì¥6.p£©¤‹Ã–¥‘-ö…+Jv4¾˜ùþµœêBš¼Ý—™¤)Σ´ß‘‡EX¿Ó®´¹„Wvò[9è$R3ôõªõi©+§tCN.Ì(¢Šb+IŒ‹¹O{ýj£¦Óê§¡õ­J«4~Plcn£=?ÏNŠR¥zþb’€{«<[Kg&0sœÕªFAìhâÝ¡bq˜Éù[±¨zVͶ›s©ßǧYZO©]\6!´µV’flò¨Ÿ×Ö¾ªøû!C¤Ïi¯xþº»Öh4wD„A¸aßúf=Krµãæy¶*¥í1×¢[¿Eúìuáðµ12å‚ùô><=9¯fø ðþ ͽ¯¤¶þ†B”“Qu8(‡¨ŒÇû«ÎJu>ýåñWÅŸê!„YxbÃ]¾…míŽÏ·¼w¦8ˆÆØg›Wœ”úEU"Š(aŠ;{xQbŠP$q"Œ**ŽÀ½:UZq¨º¤þóšQå“cNÕà¶·‚;XÒÞÊ¥¼Q…HQF*¨á@ÇJº@>¾µ…n_¡¡†´`˜˜ÿÕ’ /÷3éíŸåZ’|×EX’Ý#î·\û¯@ž-ÔßJÓ ñà•# ×5áÛ[OxöÊÚã+ þ"Ü Ê7—€Ø‚3ŒŽ•µñg@p99þ¢²~ B.> 蛲L{å= ‚#ñ¯??gAϵßܙ߃\Õ9W_óD¾ ðÖ·ðÇQ$?N”å$墑}{r3ŒŒÆ@ÈKH×-µ•ÄGdøÉþðú{ðý+Òµˆž_]øK[dö#¯ÛX%,¹Â¾~Fðxäñ\ÏŒ¾9f½ðá?ßû° §?ÂÜø`Œ 9¯™N G¹'èú~^}±‰À)ÝÓw·mתëù˜WŽÀ ­Ëд=ë.hZÁå{7b=j›jzdž¦6º­¤›•¶‘8*ê}3ëìFjâëZ}ò$0±ÉÛ0Æ\ç‘Ϧkèሧ>¶<)áªGT®¼†QRyOÈ<Áýèþ`yÇo¥4D劄mèÇ5ӹ˶Œm5Ð:@?Z‘¢uûÊWýáŠp…\m%‰=“ü} 穈¥Kã‘ÓK Z·ÁòûÌ©ad`8'¶;öéW-4Iî /ˆuß×ò®ŸÃ^ Õ¼A!^—-ˆ‘W… gævùTãžHÏjõÏ|µ°O¶x—QC )s£íBþ)HÎ:ä pCW“[1kH._]þïé­¹=fù¼–ß7ý3È<9á//£·ÓíeÔõ•c]Ìq¸ŠycÓ¹¯eÐ?gÛ©íÚ]gU]>fRc‚Ö1;+ǘą#“•^¸8äWÑß gOx³O…ü;áÈ|%ái1+ë:¬f32 |ñÁþ¶v*rö«þ°×Å߶ƹã/…üQàË?êËD6‹ Ö ö#!–ÚY˜Fs÷¤`c€~kÍTê⤛ëÖ]W’Ù/é3Ðuháâã#ú½Ûþš;m_àÆ¿¥C)еëwÇg†r ðZä“ÇʆCï^aª|0Ò5©cˆË¤^ÆvË®Lgý¸[ §Û¥sßÿlÏxI¡‹WK_Ù!j"¸ ÇUxêêÆ¾€Ð¿jÏ„ÿá¶¶ñE¢é·`„5«a"FǼs¦|°?¼J'„ÅaŸ5;¯8ê¾q{þ…ˆÃb—,š~RÑü¤¿à³ç}Gá&»h Úyš’!}’ߌþ×#{es¦Ì!¼¶šÒSÈKˆÚ2yÇšûʃžñfžº‡„|@aµ“>[Ç2jVg‡x“9óÔ÷éŒcàߊ­ÐÃ>eâ<“þ‡p’œ ¼´7=I—?)öÍÓÍ14ôœTׯ+ùßO¸Æ¦[FZÁ¸þ+ð×ï>%¤##‘_Iëÿü1iíkÃWÂgΖ+9Gç,G°ÈÝI5Î]|ðDðƒmâû‹%;ã2ÞÚÌ}0UIêw~uÕý¹‡ŠN¬'X¿Òú2Ë*ÞДeèϸŒG•?uŽG·¯áÒ«‘ƒƒÁ¯¤áøðö8cšëÅw Þ©Z">8">âk®ðÇÀ߇²Inšo‡/¼U0¤‰æ§»-òœB¾QÂçpFåŸÐ_Ã¥9zGþÂYm[ÚRŠùŸ"i¶zÕòÙi¶—•ëçmµœM,‡ì¨&½³Á_²G‰uÖŽ_ÞÃáËV ›XqsxËÎFìBF:’Fyb¾´ðŸÃGh¶ú7„¬¼%§º†Ý©Ë ¤}âÚÛÌž@Äž^yÉ®¾÷áσ|¥6£ñÄßÚVƒå‘.å]3JÏaä«——¿É,Ò+wNÃʯ™fx¯v„Uú»J_%²ôgu, z͹?¹}ý~G–ü$øg¥øh^hÿ ô5[²þ]þ¦×"09ÛuxFÕÀÁòb ýÄg“^£â†ÒøEÑu+ýjM[[¿ÖÂQkºÞÂÞgy1Ž7Ç|L²eΕ>EñSþ áÿ iGDø]¡G¨ÇkË{©mþǦÚà ­Ô)a× 95îž0Õ®µß„ÿ õ+÷Yooµ+K‹‡U GÑubéÉŽèë…U9Æz+h´[þ?ÖÇŒ^±mKPÉ'ý2ã¯ýuzЦ¿]º®¤A{p?ò+T5úNøô_‘ò•>9z°§Ç+ÄÀ£`Ó(®“3ÅC©d¡4N Éì½ZÙÌB¹#ÜP ñ‘ >3רíYæX> è…ßV`@þyü+câ4EtWN™#éÚ¹ÿƒi¿â‡÷gÝÿ¡ë^fc<<¢ú¦¾ôÏC'—^_š2¿i[Uµø¥sƒÌ–лzgn8ü…RðÇŸøc¶Y×TÓTöKÒ[hã„~«ÀÀéZŸ´øâ”  g¯%¥…¥ ØJq¨®¬:õjÐÅT”%gwùŸ`h¼ñÑ-5±rFß'SUë÷&(üTÖÇÁ x„-Þ“{%¬RÁ­ÊÏŸ“zu%° ã¦>.«Zv«{£Ü ‹ Ë‹ÇIm¥hØqŽ ƒÐŸÎ¹UìÿÝê8®ÏUý|™ÙÍKøôÓ}ÖŒúÅÿfÛèüƵ×m0±ü¢d‘ßþ¤(팟\óUaøâ°cY5+Ëgmä羇ë^§|iñÖ— x|S©1 ³yÃv|Œñ×­tzÇ¿ß\H²øŽV ›€û<#¸ÿb¹¥ÅSNNQzüŽºxì<Ú¤ŸÉþg¼é¿³Ô‘HÍ{­ÂÌÏú4 &åààçf \äcç¦>øyðÚ´ë0I*®Göœêäç<”ù9À!å_3_|Cñ^¨’¥×‰5)V%–9Œc‘Œ¸Àäñ\ðƒ|­#$¯÷¤îfú“Ö¹Õ â½ë¹ÔêÃhÆþ¯ôØú7Å?µm…¤mgá"KÍ‹¶;‹¿ÜÀ¾XÇÌG·ËÒ¸ŸøÓž2øOÖ5Y^Ú}f×6vàǪ¾öùTóò©1?ZòÕƒHÚ½kö^²’Ûã§„/Z"#Ši^6‘8wò\(™®ldc‡ÁשE{ÊiîïÊÉsIEMéu¦Ës÷;\¼>ð™l Y|¨`#8 ó|Ø®5¹¡Žy†Ç×ý˜Å~øxæÉ5ÿÙ^oh¶$s€2Góø_ñËÂÖþñoì ‚4[Mrâ0å~r¿h$}ò*0’œsgJÿ»Téòy«ëøžb·Õ¤í­åSç;}*îèf8¯«| þuz/1ËsúùëŠê(¯¼<"Ž…=ÿ…nþÕ¢ê·ú]Þ1ö‹;³ ã ã(Gp+ؼ5û`üQðÒªÜj6Zü ü©ªÙ€Øçñ”'¯Sž‚¼®¥Óô{Ï_‹2ÂëR½qŸ"Ê•ñêBƒÇ¹®jÔ¨ÍsUKN¯üÍéÖ«OJrhú£Ã_ðP鬰5_:º‚Dú^¥Õ·p6:8ï¸ôsÇQÿ ÿðîù’[ÿ øŽK×HZÊÖ`õÚ`HÏ| úWÍV¿²ßÅk脱ø"þ% °Yd‰>…ó\׋~ øïÀÐGu¯xKUÓ¬÷©ûSÁ¾ ¬¹ñ¯Ê+TQ£Z<ÞSWüÎ÷ˆÆF7švó_ð´öèðv‘´é^×»ò|¸ ·ÛÇ\‰=‡ù®ÁC¥”•±ðeÍïÉ„—RÔ¶ÝÆÐÇãøWË×6Ìÿ(l9ç>õBm?`'iüË*t.žïÎç·jý§õýj{‹m¿‰ž"YbÓ§Ó¼7 1Ølm¼ÉBóÁyK„rr3ÇJðÏëÚÏ‹µ{¯j×ÚåÚŒ,ú…ÃLÊ=qùzž*Ô–¿)Ç<ŒƒÃëTÞÜŒmÉõ´e˲±2§Í»¹…“Àsùý\ÕÓÌø+ðÚîÈÿå Q¯ËKØÉ”>6ì óŒWê½Ò…ø/ð¦)Ü&²%yè4{Õ?‘eüÅy¹Ô¯–Ö·òËÿIft¢ã]|¿4x–£6ÝsUVÀ_¶Ü`çþš·ZmE¯‰5•¨¿¹=ÿzÕ*†ázg?¯±ÂÿŸ¢ü˜«üIz²ÍQ]FgŠÑEÈüD„>’Xð2:w<Ÿé\¯Á땵øƒáàÀþöé r HH®¿â“¢1êôéÁ®#áÌZ¼?q0%"¿FÀçÜc§|W57EÛúÑ£· üKy~Õv«oñ.Þ@I3éÑHsØï‘öQ^7^ëû\Y¬~2Ñ®·ÒXyEqÀ #sÿ?•xUN]%,-6»ÿzŸ¨QEèœ[¾¯nÿž_û2Öv_t9®u “.`O# °äüëÐW6%òÑ“gVsWŠ5R>@E$ž€ “Z¶ž¹œæQötw ·åþ8®’ÃLŠÛýLd8þ3É?SZðY(ÆqÄkå^&+¡õë'ÔÊÓü9kdÊþ_˜Ãø¤9#ß+Òþ ]Ûi¼-wxH.ŠŒ€ÌŒ«ù’ã\½½˜v½kzÓL0‘Ë™hÙ@ùH9ëŸòkÎÄOë4åJnÊIÇïM_ås¡aì½Õç÷Yïò?koPkm^у¡µŠA±¸ÀQ‘ǧ?•~WþÓ²ÏüYñ3Å«á_ ]kiª\Á ë$qF»Øo‚Œ2·9è3_sþÄ߇ÄïˤÞ65-8l–ü'¹ì¶wøí^óeák )n$¸(ñ.†C´Dlçõ§„¥ˆÅNŽ:£8Ç’iì¥ôèõkºiõºùÉN8oiBjéê¾×Þ~Lxoþ Sã½RÝ«ãé—L2m¬ín/6ŸBÇËç·ûf¤Õà”¾8³…äµñÞƒr€ö3ûñ±_¬QxƒÂöRý–=KLI&1:øóU5_ø3Km·Ú®–… ²·={f½Iâ«FÓÆÓ‹ÿ·mø»œª0z*-ý÷?ôïø'/Ä&×bµÔµ½ÛN<û»IežULÿ F5ËÓ$zý ø ûx[À~·´°³m>ßh2Ýno^F#<út¯mƒ[ð Æâ;Ý0•;òdÙ’}Ž3_:~Ù¿¶~—ð¯À×6^¼Ž]NáZJ ¸ä þ&ôàuùzÑ–6QþÓÅGû”©»s˼­Ñu{-üŸ\?wü8>²—D{¹ð—Ãm*wµ¸šÇí1œ8žäönzýk;Äßüñ Gk;KˆJ@6ò$¨zýåy¯Ã-oãõ}Z]BóÆZÁº•·“mzñF;|¨„(Ø­¯~ÒŸ< ­ÚÞØx·Q» 23[_ÊfG†FOÌ¿ëK‡ß&¸JÊ<Ñ)Ú÷ìì¾F1Ťô«$ûè×Ü}UûBþÀÞ-ð­«xnØjú3»J¶q­y"3ÐŽNàŽÙ¯ž,~ xÛWÔÎÏÂÔ“ÚVKcƒœ}æÀÇ#œ×éWÁ¯Û’ÃÅ:lvšôqÍx>ImÙ±*rF:aúuþµëüwð= k›-*8îǬQ£ÿ´3^ ÌèÒ\•1 6éVçŠõƒåŸ“V¿VÞ§±ˆ¥§³¿£Vzº?(5ÏÙ⾇f—sø9æ‰×v ¸‰˜~† ׋øƒE¹Ð櫓Ôlî4ÛØÉV·¼‰¢‘HëÃþû¹¥|xÓ5 ­Õ”‘ÂÇi+ó`{Nj/|*øcñÃF’ÃRÑôûÕ”nШ*}B‘ŒñÔsï]¸,|1nØLE:¯ùm*rù)9)y/wÔÎXŠ”ÿ—}ü,~k ÿÛ£ŽDMü~¯|Mi‹ü7‰w :”Žà°ŠÑUàî¿ð#^ ûbÿÁ>ï>Z¿‹<š‡’Pn´åS ytÜIÀ%xÉàôGÅDqãoÙ Ý´­flm#-Æ‹øm‘…^g‰L¾®Ž2Š’qjÒMÇfµù4ÚkTÚ*Rœd¶vôÝŸ5ës‹{V˜—·í™XÕTm§žTõëNº•'¾¼–3º7¸•”‘Œ‚ìEG_¤P‹…EôKò>R£¼Û]Ëv×!t ?•Z¬Ä}‡  ðAïW!ŸqÁû½½~¾õ¹™ã„H#v4Uû»v’L¢BNÒ?ˆz}GB€9ÿ¦ï\7\)þUæ>¹6Ý¥ÂD&‘.$dàÀ 3ŸÂ½_ÅQ´;•‘ûBiÚuÕ¬66Z´håb ‹È<î?!_¦_žŸI/‰5³OôØpÆ×‡[®Ýè£âOŠ´íwàߌ-gxÍÌš=ÄHŽ7‡‘£+yÞÉô<öÍ|Ññ&I⦒¬Û¡²ðÚ?–k×ÜOûâÑG'þYqÞ¾2ýŠ?h¿jºÔ? µýFmJÒí¡:DÓn’XöM’@Ou1,Œ }ݤt ¯¾$Þ4¼[s1=‡‡t¨·ÈpŒÉý¥rÓí*9ô÷¯‰ÎgþίC—Õúßÿèø%¨ü1ø\ú¾ªá.µ’fû1‡cÄNÐÊ[ø±±F}Aô¯1’”¨ÐÅ)Åú(µ&ý,¹íëu:¨¦”çÑ+zßeúüÏÛsK‚ëᆳ3)o5¤ªGš«ü˜þµð{Ø)Q€ ö8ÿòkôKö­ð.­âï…^)û Fy­|‹ä‰ZD‰ÕØÆ~Uo^•ùîŒC)Ê‘kãñçN­IIYJRkï>Ç-œeA$õV¹‘4 Æ;Ÿo΢­©#)FGZÉš„òý«îzè§qoæ¸*9îÏùâ¹_Û…ðÆ¿‚ž3òœþ5ÙW9ãÈGü":ëãŸìùÿÿõëZK÷‘~hίðåèÏ™îP‡Gßç§CÜ~u^¾Œí~§cn:7ÿ\Uý(üÄ«x™PÀtäŸóþxªd# ö5¥p¡¢ ‚}õíY´ïŸðOÍ!µ/ڧ“ªJÇN³¾žCʨû<†cŽeÇÔ¯ã÷'Å9ü‹ïŒ÷“yw×Ê‘†FÝÂ2£¯É¾IË7rkåßø%¿†¤Ôþ9ø§Q Yè¢Õw1<÷°< ˆß9õÞûñ'Q…þxÂö2³®­âmD£ù»¼Èα0•±óÃýžœ(¯‚â'í+aèÿ5Jqÿɹ¿CÝÁ{”¥/)?ÂLJРpGqE÷§„hÚÝ–à³wPzõäçWAî+ àŽâ´,î·`*ü㪀}ÇlûP4FŠšHÉ$᯸¨h¶¡›lýxÆx#¾kÁu˜D^$u‡r¹ç’r?¾‘wÆËê¯ñå³A­ùU޽¹¨œy¢ãܸK’j]™í_=gáÆµ¤É±œâB±+,{sÇü²<Øõ¯›ìÑ£*Œ¥Yr¤ ŽµôìåxWWÖ¬m“Û‰Ç\|®¡@ç‘#œc<{WŽøÛKþÃñæ½dW`ŽöBŠ8Xî_Ñ…||ªI.©?Ñþ'Ù¿y6¿_ÈM-°à A®ŽÃøHÈ>ÃÞ¹­(þóñ=½«¤Óþúã·8&¹êîvSØÔL\ò3\çÄŸøôҿߟùG]}~¢¹Ï‰?ñ饿?ò޶ËÿÞ¡óü™Ë˜ÿºOåù£•ÓÔFîdÇþ:kF³l$QOIž}ÔÖ•}©ðæš.ÕÓ¥;žÀ±<:“è)± 8ÆyÆ}k±øGáÙ|Qñ+ÃÖQÀn.’âT²3¸ç=²~5ψ¯5מÑMýÊæ”麳PŽíŸ¢ß°·ìw¡øgž4ñe’]ë·ÌQ8ù`\d¨  êH9ãŠúÄÿ´/Éajd¶µ‚iÖÚ5ÄJçû‘Ž9Ú·J]FAá_„bam0Än#óÍ~S|Rø©üPý¢£³¼»y4½âêËO„‘b‘^P:n$zà(¯Ï#[:«Bj5V¬íÌõÚ >‹d¶KÎ÷ö£ siÉ^<ܱ_¯ùŸ³1OͲÜFDÈÕ‡FR2:ûüÑý¤¾ÁðËâæ«ac•¤ß©X¯ð¬r½Ù\0úb¾Þý™üh¾9øA¢ÜÉ/›s"Ãu 8l÷ƒ¼ûöÀøa/‹üý¡k›XзÝBà ÉnÜËþ:{®;×»‹Ä,^y+7¿”¶kïºù€o Š•;é·ù?ë¹ðU½ˆy{³òîƒÓÓ>¾•eX2†‚2*+¥-Æx9ã?Óšù´}‘X^:\ø/^É8ûùÇû†·H#¨ÅaøägÁzð##ìŸÊ6®š_Ī"·ðåèÏ›¯òOFAú7ÿ^³+Jø®&änڣߩ8¬Úý$üÈB~µ•Zr>Ä$c>ý+2€?Bà–:lðÄŸÞ³ 9/#Ž\ÈKwžLdŒdOÔœqÛ®|Cè~és‚/¤†ÖkÂe[LÍ»Œ©ófÈQï[?³¯†ÛÃ_ðOyâh ½ç‹£’ÁŒ›‡Íª^­„nŽs2¶P¤ƒÎköÕÍÿŒ´›Pêˤ·,«•¦—ëqàú‚:×Áâ¿Ús¼-.‰ÎOþÜ£øÈ÷RöxIú%÷»³ÍÕÆT‚:qKTaƒžœõ¿ýzº¬A ×Þ´¨íS† %ÉbY— ùŠ£4l¬K}î¤cõ­ŽhË€Táב@Õå4ñö앸;Gaé^²É€úzƒ\'Ä›öÉ8:’?AùPµ/±xóA•òLíöGÇ%™Õ¢èÎnœœ Éý§Ö? |MK—†FQ³Žà:‚êÌŒ9>Š¿døzâKY#–ÜùsÃ.èÜŒ…sÊ·9èÜôí^¡ûdè±xƒá÷†×z`¿TáljW®– ˆOþÏ^ïtÄÈA=OJÌÕ¦1Z qøW³ŒCû+ñÿ3Ùy.ù¥÷¯ò<6ïÁZôQ0:pbr0·1?ñêȸð^¾éå&˜í,¤DŠ%Œ–f8a¹$‘^ÅpÜþ•Õüð—ü'_|¥˜šHc¾[Û€pòàw ñ‚Ê«ÿ®º9j’´’·£ÿ3޶WBœn›û×ùuø‹Ãx+Àÿ¾ÛÍ!K)’ipÜI›bÊã¿Ò§±nSá¶×ËŸ5EÕ¾)kΡ‚Ú¼v ðbCuøË×Ö^8Õ-î>/êRMp[Mð®…ohìFß.K—{»°Tœq :{dx䞃á¬K«^ÝßÎKMw3ÜËÓ†v,[s|÷õ²IœXÉráãö›%¡f¬[ÌAÀäõ+Üûýj½÷§ˆj+PAÈ4µJ Ø0ÎHïÏëW 4´QEE:L¯QÛÔwËxÆÀ^hò€9QœßZ몖­l.,¤\g#§¯ùâ€<'In¤€w Ž:‘ÿÖÍ} o§IñOöoÖt4S=ô0ËoŒòÆVxT{ ѧüýkçÍFÒõ|à~íòFzÿÖ¯zýŸuï³øŽïJfS£n DÿÏX·:ªýQ¦$ÿ°£Ó9˜Å¢œzëóüè²ù©Òp—M>Rÿ‚|6ÑÁëÇj×¶›sHÄ£pú‚+ªø÷àføñW\Ó–3”òýºÏåÚ¦I`“¶äÏûÅYHJ”_¾­½FqžÄ~UïÓš©8ìϤ9¸=ѪÒ¥zà wO¬m ‚–ùüå¯9ŽA*+¯B3]_ýÈ?œ•ÙºÏåù£ÐË?Þáóü™ëš4ÙV^Š0ÏùÍi³… rXð “ô뜰¹²–9#c<þ½}Óûü·ñ­–¿©üÏwº~>äYùU} Ï×¥~w‰¬è¸BæœÚŒV×oÏ¢KVúsR¬iSs“Ñ?ì)ð.ÿK»“Åú½¹‰¤ $È(%G^¹;Ð}+êωÚõ¯‡´;›û¹6Ago%ÔƒùUKŒòp§ÍsÅúW‚,ÛNÓâ†#l›Šglq/RIõÆIýM|)ûK~Ô‹ãëK¯ xraq§HÃûCU&ÁÏ•û9-ß ã9Ù×£‡¥S/„½¥i»Ô’øck.Tü’I/Ví{9N•\muY«Eméÿñ/x§Pñ¿ˆuT”Ë}¨Lg|’B÷QsÑUp z ó¯ŒN[º`'p]I@?öÂ^+°²ÁgžGç\7ÆYü¯ iãnOö‚œÿÛƽ½%‰§ê{Šÿdš]¿QŸ³&¿oáÚ ÀºÙU¶Žõ”–é¹¢uO͈R+ö ã·†Ç^ŠæÆ_:ÎhŠ?–&7R7ÿý~µó‚­b•:H§”`r÷¿e`ïŠ×~ [Ûêÿ¼ž(0$z”qÐn÷«¯=Á,Tý„åh׊‚Ë8sNÑÞIú.çÉa*ºqçŽðwù;'÷i÷Ÿ‘.ðµßÃÏj~ÔÆÛÍ6S 8ǘ˜Ê8öeÁükž¸¸26àzWÓ¿ðP Ç£|VÓoÒ1ÜÃ-œF2йÁ?@øü|´ò,c,p3ï^æOŽ–c€¥Šš´¤µõNÏñLäÄÒT*Êœv[zn…f¥ š·àùGü';|Âú€Ê»ûûž+æì)RÉóŽU éèO¿µXðl…r~Ýw¿¼Ízu‡/FgKø‘õG¾K Ë9àg>µÎêÍw.V5à/øÖ–­p©P r8`~ï?þ¿Ê¹ùj×ç1Gérd°.Nx¾¥ÿ‚vxõ¿x›ÅÒnKk(H·€G˜åe˜çý•X |™ª^Eeg$³>Äœ§ØWè7ÃÜü'ýlô$‘ì/¼ÿêÝ[±bì×.#µÏp³mà„¥|¬¬Qƒ9îßµV½o ÿ†ü'a¶³±¶ûq lÅcÙc°=W„W_ SæÁK%g^rŸ¢nÑ_$•½O˜ÇÉ{_f¶ŠKüÍ;[µaËÔžŸOoåWk£9V*}AÅiÚ]‡ch‘ýß§·òþ_`yÅÊžÞm„ß‚=}ê (VŠ’xŒ2•퓎sÆj:) =´P‘xóL6š™©㑎>€Tþ ÖntË?Pµbך}²®q½îE'û®ÃìZºŸˆ:GÛtó:¯ï¾3ÿê¯;ЮÛR Ä*\b2dz þcñ¯;M΋”wŽ¿çø†¢…e=%§ù~'ª~Úþ ³ñ'€ôéΊÛbI0]¥­'ù£fÈår Þi¯ŒÑÚ6 § :ýø=qeãë^×#K¨RKOÇ›m!ýòŽùIX¶î0&Œ»_üCð=÷ÃokÔ9¸Óç1‰0–3Ìr ÊTã¶py®\²²pto¶«Ñÿ—S§1¤ù•nú?Uþ} V³ä~쇎z7q×ñükÐþ6Ùµ~q•ƒ§^²W–Á?–æ¸#úzô¯…NZMT³`ÃŒýÿë]Yû¬þ_š0ËÞ¡óü™ëžÑnüM­Xi6e¼½•`Œ/©8'ŽÀdŸa_°_³O…‡t ¶¹xb†HOqŸ¾ý<oâë´ð%ĶI•¨“G—qvûTÄ×éG®âð€¥ŠÁJ³%¾XrÇß·â=+ó:r__ž>¯ð°‘mùÎQÑ/Dþö}aQÎ+ ä|;ûkøÒæÝ-ô‹k‡5»¹g¹Uc–‚<§ý–wäwÛ_(Då$;WkñçÇçÇõGiÌ–Úh|}ÒT“!ÿ¾÷¸zæÊ(º88ó¯zW“õ“¾¿+/‘íÓ,R4⺿)+ž9ã?ç5Æüf¸Ã{1 AsÜãÉ–ºr‡ à×ñ–éÇ„ôḂu%žL½ÿÏzú\¶*§.a®§¡ç?h‹þz§ýô+ô›þ ­‹­/Åv>qsoq*„'€¬!ql—ýÌ/µMÇï޵÷üoÇ £üf×4;‹‰¨[G2#]†èÏêÑÿ“_O›+Q§WùgMü¹Ô[ù&Ùðøme(÷‹ÿ?ÐÑÿ‚¡Á>"²ºŒl•5i£,9hó€=~LþUðt÷¹|¡Á#Û¿N½«÷ããWìµà:|v~(²kˆc»[ÕÚJ‘ Ü2 yî0Mq±~ÁàÓŽ—…´ô}¤.ø yÆ3ÊdŸ©Íxùtq¹^á¥C›Þ“Oš)5&ÚJî÷×k%æo]ÒÄIOžÚ%³è~’I$œ“ÜÖŸ…Nœ×°™w0Š)œß§ã_3o9ž…û=|4oŒŸü?¡\B×:lý¡©)?)·ˆƒµ¿Ùw1ÇöëôC⪺×Ű2%¾‹à‹3Êü'öÜAܶz{-„‘ÛPoJòŸØ»ÀÖŸ¾ë|Aa,·ú¤ x–qãÍ– í²µˆ`þòy$P õ3 <­aünñ ×Ã߃­¥_ÜÅsâßO;j3ÅŒ<Ó7›"ùæ7 ÇðWpçR•<º‹÷ë>OE¼ß¢Žþº$ê.iU{G_ò_yà>7ññ÷µÍ|’öä›xØm)n $*Gb#TϾMcVts²‘ß§¥_GÞ¹Á¸=«ôš4¡‡¥4Õ£’ôJÈù9IɹKv:•£`Êpᤢ¶§kxpFÐ1‘ý=¿•]¬b§#ƒZv—ŠÉƒ…çžz{þyü~´ÚÝÀ fo¸ÝHÛÇ_ÓùVt±Ÿiäc úŠÝªwª©CòÂÇ!‡ðŸè(.Št‰åÈËœí$f›@ÝÛ­Õ¼‘0Èa^'®i­§j@˵wJ÷*â¾ ø|]À/"¼Qó`uÿ ›áÿ‹.´û­3[³õ-:aº6m¢^ ²ÎˆYsü%³Œ¨®·öÃø[Å_é_¿u:&¯0û4Œs7OÀÇÜ›ÁÿYƒ‚d$|}XK/Å% ž±ÿÛ£ú¯ó>ž”㌠Ô÷Ú_¤¿GþGçjÙ\¾6ÛNsé…w .£Ñÿ´Eü‰`&ò¼³v| ø-»±œdgë^ÍûFü¸øAâß¶ÙÆWÃ:¬¬Ön™Å¼Z{¥}T²kÂ|w;Kg¦ï$ó “ízŽ¿×mGe.¾šþ‡4h,ûBwqéë§ê}Ýûü[Ó¼;ã/iñjV2›ˆí¯c_´!ÉÊ8=q"×éWÆ{˜oüe©‡Tž9FãÆ×\õ¯ÇÏØ+à‡ˆ‹oèD~ïWÓ[ýûØ—ú×ñ/Äšö‹§ÚÙ_ZêüH-ìeY¤Ú!—' I=}+É ú@Ik”CÜÉü¹­¿‡úì?ð›é[ ÊPÊsÐÂã©ç¿¥j²Øao^2»ßÜ'™ÏjŠJVWõb‹Ò24ëâ?ëÒ_þ&½'önñïÂÿÞñÚß[Û$ÆÞy ´ª¡$RN:o“ô­–×/ÐŒ#¹ù‰úçŠ4Û;kv˜÷ Zöê+pÒ1*7¸Çã^n/0úÎ¥Ñ\²M=z4uÓÊáJjq›ºò?i>!øÎ[…V^-ÓVâT Ò[Ûg{+|®£ÜÖ¿9—þ [tÿÁCfðM¤ßð˜øvk¸¢Œ»_ø}ÕeàrLN@Ïœ}+Gzq£‹¥U5¢mòÔý½×ï»L'³½Jp~[}ÇØúÿüóáαiqiöQ<¹äY*òã†+õæ¾SÖÿàœß´+KídÜxbiÜÚsï,•,‚@r™‘NFì1ÇL£> Á@þüP”Ç£xšî}Mc-ý‡¨Äb¼œã;"BJÈÜrN5â'5 AýªŸf“â?‹dkm&ÚVóaÓ`;¥7Aj¼ð³H‹ò†=º8|>Ú—´¢âõŒ¤ÜtW»çæ²K[ůš8#[ß,¤¤Ÿmý49¯ˆZݧ‰¼e…°Áá¯?Ÿ0!a›UîDcŒl³…Œ‚G›4}Ü×Á_~!ÿÂÒñõþ»a¦F¢ÏL‰)j„•b;3³3Ÿ÷€þ^·ûM|Bµð7…ìþøzy¦ºº‡ÎÕî甼ënîÒ8•³–žæFi$cÕY³þ°c渦*ܤñžßupîxÊÓÎk+).Ziô…þ/Y½|–ÎÍXêª)aâöÖ^½¾_Ö¥ú–ŒYÇòëõ¨#J¹Æ_zyœr ÇQÔ}gÁ1FäôžÞŸJ»‚UÈÈö4úTvƒ)Æ’ŠõZB{Z(Õ¾ü†ëÿ,Üž¿ìšÍ ‚A#±­öPÑTnm ;ð0äõ翾0 Ψ®mÒê‰À*Ã:T´ª¥˜*‚I8w ñG‡¤ÒµT•Û#×éW<ñJ¸Ö?á Ô%YåZ8šB<’ç­±lõ=±üD/SÆ7Ç_Š6ÖÎþѤó5(˜¥åê–ß±‰w빿‡ ç;| ¸ÚJràƒë\x¼,qt9;=ÓêŸFtáëËQN?5Ýv?Q<+¨éÿ|wðûÆ!î5²‘Û=ÜIŒJ ä\G….wq'9uOƒ¿hŸ…úçÂ=~×EÖ#ób-3Ùê•wØ7F{v ŸSøñsþd¶Ò5+·³ñm‘Ylïâ}²Ü•é"ù샨çzç Ùú¸Ûxsö—ð”þñͬPëÂ32½˜}  ÿË<ƒ±Ôž.vüÜÎOÉáqÂâ=uiGuÝ4UÓ˧ÑUŒq}Ǥ¶}¿ºÿGý?¨¿`};ÿð¨ìo4*IVÚTªò‘ˆÆ1õÆMtßþø»â.«¨‹¥4ù‘<Á‘£äŒ÷Ðu5ù—៌Ÿ¿àžZ‹h—–O¯ø^IXiº¬NR9¢É+¬¡À¼¦éÎ .+»¿ÿ‚Ðx‡vm<&`|²KsßøZ¼Z™G·ÂG^•IB2””©¸%;¶Ó—3Nêöýz.yÕp­*Ñ”Sj֕ºoÅø%ƃwwee©h7[Ë,ÚUÇ›;n³ìvúWÃÿÿcˆž¸•­mO‰ìÓŸ6È8x›æÿ¾wWéìáÿ`ð×ÄÍDi^0±O_°,¥äP¬ds…sþÉ yã8Í}C þ5lk+›7¿‘Nß$ùRç§Ý<1úf®•\v§²Ãb›—üû¯¤¿íÙ­%~‰;ʪGš¥=?š|×Cùƹ¶šÎâH."x'мr)VSèAäè¾ÿÈí§ÛOýÕû7ûJ~ÁZ7´iôèõ3Eb¾^Áܶïât9ùâïÙÃÄ_¾ ØÜÝ#_øy¤’8µ(ÔáÆØIWø·¡íè=ê9äq xLe7FµŸ»-¥§Ù–ÏúÜž¤*Ò—4.µí¯TlÖ¿ƒoâÒ¼káËÙÊ­½¾¥nò;tUó,~™ÏáXFéA=ùÇ ÄâhÞ=¿+ žÕäΟ´‹ƒÙè}û-ñ›Cºø‰û6$z<ƒÎ[ »‡!HŒÆX× ƒô¯ÇoHÔ¼)xtÍRÊK ÈNÒ’ r§¡Ú¿F`¯ÚV?øjÓÃZ´ÒKq [9„Ÿ6×Û„q×å`9ü}0iþߟ³õµþ†÷º5[œ›«P¹¼ïŒ}@éþÐô¯¥ˆtÄMmÉNªë%ˮ𚷣ﭼêØÔxyu»‹îº¯T~lM>åààã¦+]Io4Û‹;h¥¹¼¹ŒÃ ¡y%wùUG,I8sZeµïˆuK=/G±ŸSÕo_Ë·²·MÒ»úüO@9Å}ýû;þÌ~ýœ<8ß~%]A7ˆ“hTy¢ÑÝH[kT3\>Jü¹$ð£îû:pq´ÚЪõ¢¢âßC/öGý–t?Ù+À2üGø‰¸ñµÂ¤QÚÛÆ.%µip#±¶N’\ÊHV#’ÛWâçÅgøK¡êž;ñOÙo(Úx~Ýþ"|Gt[k?2 ÃвÊöe‘³íÈ–öUÈy)’ªÛL’Iùùñâ6¯ñsÆW>)ÖãH%‘ KØ´vvÊIH”žORY¸ÜÅx°çâŒK¦¿Ý ýù-¦Óº„_ò­äÖý:7ãÔqÀÃO‹¢íÝ¿?ë¸5åî­wyªjwO}ªj5ÕÕÔ‡-$ŒrOÐpìKYvw[ ;œgÿ¯ÿê­(ÜH†@=ˆäWéé(¥«$|ûm»²xf1¶rI8'ƒW‘÷®pAîjÌ©a”¡à…=Ž?Jb4*XçeÆÌ8úzT "È2¤oJuiÇ*Ê2àƒÔSë> J0éè3éWc“x9Xu_Jõ·P>aoJe]¸·ÜK®r~ðõªÏ ¸·8ç¨úÐtÙH»Nqx8ïN¥U,ÁTIÀ½fOhdm¹&~ûøï“ßüx‡Æ  ›øjçv¥ƒî§Ç·¬qü}‹AÎvØøíñ×û$ÜøgÃw#íÜÅ}¨ÂÙv1FÃøýX}Þƒœ•ù´  @ ”§©( Ã4¶ÓÅ4¼Äáã–6*ÈÀäG ƒÞ¾±ø+ñÂ×â Vz½pÚŠ (lµæ0µÌÀ’Dã;‘Œ›œuÚ~K£Ó’äÔW—Ëéãà”¤µŒ–éÿ—tuáñ3÷mSÝtgë>Ÿã-ân|ñGN³º–ù¼˜/¦‰RÏRrHT ö[®F0B³sV!Ç¿´ÿì#â„÷šÿƒ ¹ñ„—-5¸R׺qÏ̲ tC¯ gpnl¯ƒÿ´ÔsF¾ø„VòÂXżZÄ‘‡*¸ ²éqûÅ#«òßÞÝœ¯Û>ø¯«ø6ÎÖ§›Åþh÷Á$2 ‹ûHûyîÅÜ cÇÌP>Gpuò”±õòÊʆ1(·³ûôìû­<­¢~ÜéÒÆS熩àKü×õæ~Ft¯JømûBxËá{¥jhWîÅtYÂsŸ”ç#é_|ühý‰þ~ÑÞ2øo¨XhÚ´ï&nìA6SàÄ@n·”óaUÁf.ŒkóÓâ¯ÁOüÖ¿³¼]¡Ï¦³±]c}µÈã•r­ÁŒäddÅ}[ú®cMÒ­.éžC|æƒÓºØýQý’à¤Vž,‡MѼIsçؚܾX ã;yØIù×ÐCÒ¾ªø»ðSÃÿ´«i¶°Ý¤ñ’(º”އŒàÿ“_ξ‘«]èZ•¾¡a;Û]Û¸xåC‚¦¿b?àžŸ¶1ñôV~Ô’-«na–@Í ¡z¯}§üŠøÜÏ-§†‚Ãâ[–Z)7ïQ—Fžü¿•»^þ… ηïh®Z‹uÒKüÏ><ü'›áŒdµ„JÚ5Ùg²’S–Lclõ#ù}+ÍF'¯~Õú?ÿ/ð •—…nµ8•aVùÞEp¬×qÿ¾…~iYKu«ß[éú}¬÷÷÷'d6–q4“JÝ‚ª‚IúÕÏ–ýbP• Fµ)ÉÁ¾öÙüÕ™ïÆ´gQlÕÎûàïÄsð·â.“¬Ë)M<È"¼\œydðÜtàþuúëâO‰øµðÂÉRðßkƯoibD’3‘÷‰*ÆzïcÛ-€?~Á?uÿ]Ûê?e—GÓÛ º”Šnåé,ƒ+ú…É÷ZúzÏÅú‚´–ðwÁí'I¼6èÒk :6œËB²á¯f ư6D²+ 1Xl=i[4©Ê<³Of“¼]ÓMJ.öµÛÙ+ÚÜ5j*²*wOO×äVð×߇¿³!—[—Jûg|Lå­¬4Ô_ß7 ñÛ£0@¹Ì’±H× »r¢¸ÿŠ?¬<oÄŠWM«ðèº&œÆHìÕ¶‡‚Énù16é€' òЬuÄücøñáïÙöMAî®fñÏÅ QCÜ›ÉÔÏ3º*‚Ý”¶Œ(ê¹,~ñoµ™RÃ7–  Øã¨ô  –Ll0OçÅB¼gsŽihè ¯,^VXd¡ûÉŽ*Å*©f  ’Nè7Ébê©óîû¸kÁ~=|x]n|/á{Ú‰+ýNÿQÙ¢ˆâìÌ:r9ÄŸþ=¦†·~ð­Öëö&;ýNâÆˆþ.Ìã§AÎHùr€ŽJ6ÓÉÊö59‘õé@(¦®Tí=;uQEkÒ>üyñ/“®¥¡»ï›H»cå’z´mÖ'çªðHƒŠóz+›†£‹¦è׊”_Gý~&”êN”¹àìÏÑÿƒÿü=ñ*ùµ¯kW>ñ€Œ%Í£yhš4ä,ÐÇwÉÁ ²Œccš÷Xþ)è>&Ò'о*xzÂÓN¸ù&Ôã®ôK‘†š&Ý-¡ÉÝ—ßã>p¯Æû{‰m."¸‚W‚âG,LUÑÈe#Aî+èß…¿¶¿‰|3-½ŸŒa>*ÓT…7Á„zŒK€3æ}Ùq×÷ƒsãñ²|v]ï`%í)¯±'i/ðËòOEÙ½Ovž:•m+{¯ºÙú£èÿŒŸðLøžÖ=sáV»‹ÌB[{ ÙšïO¸.+•.ê¸ÉÏïrHÆÑ^}û&~Îþ |p•ü[¢]höpÆ£í© \Z̧<¬ÑPG)ù¾nƒ·®|'ø­àÿ\4ÿ ¼o?†u«¦2Ï¥@šB o;N˜4¾-$A›þš^Ñÿ £Çzo‘׃<7â+ÅfÔ-ué´eQœå­dµ¹)èBJùÇt¯?œPÇaªeØÙ:R’³S\­.é½ìï#¢žÙÕUé+Û¶Û~yûNxjÚŸB²ðÅ„šŽ‘¢ùª×Z”–æ)î:¶Èbq¸giùF3÷[¥p^ð¯ÂŸÙ„M¡x{HŸYñxŒ ì4´K½^Lƒu;ŽÙ÷¯õÚ¤ñX¾6ñ¾¹w¥ÏyãOZø7Ã2d ñ´›YÈ÷ÎËupØlb#nñö¯šžñ÷‹oõÏ]êµ3Â>Q¶mÂí’Ò\äùWwgl—¤‚ÃÉR6û¦90 |›ñƒöÞšöÊ_|*´:•}˜kÓF#œÄݶÐcàsµ‰,0Šù›Æ¾:ñGÅ=hjÞ*Ö®õ»ÁÄorØŠã+C ñÑŸk…QÅ{¸Nö•'6©ífµQÚœ}#Õù½ú¦õ<Ú¸ÿw’‚å]ú²Õ•ˆ¹y$w,ÌŤv9wcÉf'©>¦µÀì+6ÎèªíÜ2 ü­€úúõ­uq•9þ•÷'H²²Œdàtö«ñL$ÈÝè+:ì`rxôí@tTPÊ\aˆÜ=;Z–€ ½k}ŽüÞ§ø¿úþÿQ¢€7Õƒ ŽE-gYÞB±Ëÿè_ýçWã‘e]ÈÁ‡µO ¥Xrr=ñŸcW’Ep~£¸¬Ê–J0„ð+—„Ãâ⡈¦¦—I$ÿ3HU'xI¯C[Ä>'Ö|s¨jx‹W¿×¯äóõ+†”H]Ç =†E ™8géýÚ®ŒQjÔÀQÐŽÞÆ·„#N*VK¢!·'vY(ÀAKEb ¿gvÌvž_ÿBÿëÿ“ëT(  õ`Ã#‘KY¶— ºÿ ëïZë"†S•= H„‚p=qÈ«ðÊ$PÞŸzΧÇ&Þ v+ÔÒ¢¢‚_1pÄnÇ­K@$AÁÅ]´»;€$—'×ïöïßùÕ*(}X0ÈäRÖm¥ãUnOCþ×§ãüëAdPÊr§¡ ÿÙfheroes2-1.1.6+dfsg/files/lang/000077500000000000000000000000001476115357100162105ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/lang/Makefile000066400000000000000000000060061476115357100176520ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2024 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### ICONV = iconv # TODO: consider converting game fonts and texts to UTF-8 in the engine instead MSGFMT = sed -e '1,20 s/UTF-8/$(1)/' $< | $(ICONV) -f utf-8 -t $(1) | if msgfmt --help | grep -q no-convert >/dev/null 2>/dev/null; then msgfmt - -o $@ --no-convert; else msgfmt - -o $@; fi .PHONY: all clean merge all: $(patsubst %.po, %.mo, $(wildcard *.po)) merge: ../../src/dist/fheroes2/fheroes2.pot for i in $(wildcard *.po); do msgmerge -U --no-location $$i $<; done # Czech, Hungarian, Polish and Slovak versions use CP1250 cs.mo hu.mo pl.mo sk.mo: %.mo: %.po $(call MSGFMT,CP1250) # Belarusian, Bulgarian, Ukrainian versions use CP1251 # Russian versions from "Buka" and "XXI vek" use CP1251 encoding (supported) # Russian version from "Fargus" uses Russian keyboard layout as encoding (not supported) be.mo bg.mo ru.mo uk.mo: %.mo: %.po $(call MSGFMT,CP1251) # German, Danish, French, Italian, Dutch, Norwegian, Portuguese, Spanish and Swedish translations use CP1252 de.mo dk.mo es.mo fr.mo it.mo nb.mo pt.mo sv.mo nl.mo: %.mo: %.po $(call MSGFMT,CP1252) # Turkish uses CP1254 tr.mo: tr.po $(call MSGFMT,CP1254) # Lithaunian uses CP1257 lt.mo: lt.po $(call MSGFMT,CP1257) # Vietnamese uses CP1258 vi.mo: vi.po $(call MSGFMT,CP1258) # Romanian uses ISO-8859-16 ro.mo: ro.po $(call MSGFMT,ISO-8859-16) # All other languages: drop accents transliterated with `"` (which breaks translation file format) # and transliterate the rest with default iconv rules %.mo: %.po sed -e 'y/äëïöőüűÄËÃÅÖÜŰ/aeioouuAEIOOUU/' $< | $(ICONV) -f utf-8 -t ascii//TRANSLIT | msgfmt - -o $@ clean: -rm -f *.mo *.po~ fheroes2-1.1.6+dfsg/files/lang/be.po000066400000000000000000006744561476115357100171640ustar00rootroot00000000000000# Belarusian translation of fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2022-09-23 16:01+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: be\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<12 || n%100>14) ? 1 : 2);\n" "X-Generator: Poedit 3.2\n" "X-Poedit-SourceCharset: UTF-8\n" msgid "" "NEW\n" "GAME" msgstr "ÐОВÐЯ" msgid "" "SAVE\n" "GAME" msgstr "" "ЗÐÐ¥Ð-\n" "Ð’ÐЦЬ" msgid "" "LOAD\n" "GAME" msgstr "" "ЗÐГРУ-\n" "ЗІЦЬ" msgid "INFO" msgstr "ДÐВЕДКÐ" msgid "QUIT" msgstr "" "ЗÐВЯР-\n" "ШЫЦЬ" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "ÐОВÐЯ" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "ЗÐÐ¥Ð-\n" "Ð’ÐЦЬ" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "ЗÐГРУ-\n" "ЗІЦЬ" msgid "CANCEL" msgstr "ÐÐЗÐД" msgid "OKAY" msgstr "ДОБРÐ" msgid "ACCEPT" msgstr "ПРЫÐЯЦЬ" msgid "DECLINE" msgstr "ÐДМОВІЦЬ" msgid "LEARN" msgstr "" msgid "TRADE" msgstr "" msgid "YES" msgstr "ТÐК" msgid "NO" msgstr "ÐЕ" msgid "EXIT" msgstr "ВЫЙСЦІ" msgid "smallerButton|EXIT" msgstr "" msgid "DISMISS" msgstr "" msgid "UPGRADE" msgstr "ПÐЛЕПШЫЦЬ" msgid "RESTART" msgstr "ÐÐÐОВÐ" msgid "HEROES" msgstr "" msgid "" "TOWNS/\n" "CASTLES" msgstr "" msgid "S" msgstr "" msgid "M" msgstr "" msgid "L" msgstr "" msgid "X-L" msgstr "" msgid "ALL" msgstr "УСЕ" msgid "SELECT" msgstr "" msgid "" "STANDARD\n" "GAME" msgstr "" "ЗВЫЧÐЙÐÐЯ\n" "ГУЛЬÐЯ" msgid "" "BATTLE\n" "ONLY" msgstr "" "ÐСОБÐЫ\n" "БОЙ" msgid "" "CAMPAIGN\n" "GAME" msgstr "КÐМПÐÐІЯ" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "ШМÐТ-\n" "ÐСÐБОВÐЯ\n" "ГУЛЬÐЯ" msgid "CONFIG" msgstr "ÐÐЛÐДЫ" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" msgid "HOT SEAT" msgstr "" "ЗРÐДÐЫМ\n" "КÐМПУТÐРÐМ" msgid "2 PLAYERS" msgstr "2 ГУЛЬЦЫ" msgid "3 PLAYERS" msgstr "3 ГУЛЬЦЫ" msgid "4 PLAYERS" msgstr "4 ГУЛЬЦЫ" msgid "5 PLAYERS" msgstr "5 ГУЛЬЦОЎ" msgid "6 PLAYERS" msgstr "6 ГУЛЬЦОЎ" msgid "GIFT" msgstr "ÐДДÐЦЬ" msgid "MAX" msgstr "МÐКС" msgid "DIFFICULTY" msgstr "ЦЯЖКÐСЦЬ" msgid "VIEW INTRO" msgstr "" msgid "MIN" msgstr "МІÐ" msgid "RESET" msgstr "" #, fuzzy msgid "START" msgstr "ÐÐÐОВÐ" msgid "TOWN" msgstr "" msgid "CASTLE" msgstr "" #, fuzzy msgid "RESTRICT" msgstr "ÐÐÐОВÐ" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "ВаÑÑ€" msgid "Builder" msgstr "Будаўнік" msgid "Explorer" msgstr "ДаÑледчык" msgid "None" msgstr "" msgid "" "A few\n" "%{monster}" msgstr "" "Трохі\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Ðекалькі\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Крыху\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Шмат\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Ðрда\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Ðатоўп\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Рой\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Безліч\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Легіён\n" "%{monster}" msgid "army|Few" msgstr "Трохі" msgid "army|Several" msgstr "Ðекалькі" msgid "army|Pack" msgstr "Крыху" msgid "army|Lots" msgstr "Шмат" msgid "army|Horde" msgstr "Ðрда" msgid "army|Throng" msgstr "Ðатоўп" msgid "army|Swarm" msgstr "Рой" msgid "army|Zounds" msgstr "Безліч" msgid "army|Legion" msgstr "Легіён" msgid "All %{race} troops +1" msgstr "" msgid "NeutralRaceTroops|Neutral" msgstr "" msgid "Troops of %{count} alignments -%{penalty}" msgstr "" msgid "Some undead in army -1" msgstr "" msgid "" "Default\n" "troop" msgstr "" msgid "View %{name}" msgstr "ПраглÑдзець %{name}" msgid "Move the %{name} " msgstr "" msgid "Move or right click to redistribute %{name}" msgstr "" msgid "Combine %{name} armies" msgstr "Ðб’Ñднаць войÑкі: %{name}" msgid "Exchange %{name2} with %{name}" msgstr "" msgid "Select %{name}" msgstr "Выбраць: %{name}" msgid "Cannot move last troop" msgstr "" msgid "Move the %{name}" msgstr "ПерамÑÑціць: %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "" "Ðекалькі\n" "%{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "" msgstr[1] "" msgstr[2] "" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} выключыў аўта-бой" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} уключыў аўта-бой" msgid "Spell failed!" msgstr "Загавор нÑўдалы!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "" msgid "That spell will have no effect!" msgstr "" msgid "You may only summon one type of elemental per combat." msgstr "" msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" msgid "Speed: %{speed}" msgstr "ХуткаÑць: %{speed}" msgid "Speed" msgstr "ХуткаÑць" msgid "Off" msgstr "Выкл" msgid "On" msgstr "Укл" #, fuzzy msgid "Turn Order" msgstr "Парадак войÑку" msgid "Auto Spell Casting" msgstr "" msgid "Grid" msgstr "Сетка" msgid "Shadow Movement" msgstr "" msgid "Shadow Cursor" msgstr "" msgid "Audio" msgstr "Ðўдыё" msgid "Settings" msgstr "Ðалады" msgid "Configure" msgstr "Ðаладзіць" msgid "Hot Keys" msgstr "Ð“Ð°Ñ€Ð°Ñ‡Ñ‹Ñ ÐºÐ»Ð°Ð²Ñ–ÑˆÑ‹" #, fuzzy msgid "Damage Info" msgstr "Урон" msgid "Set the speed of combat actions and animations." msgstr "УÑталÑваць хуткаÑць баÑвых дзеÑннÑÑž Ñ– анімацый." msgid "Toggle to display the turn order during the battle." msgstr "" msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" msgid "Change the audio settings of the game." msgstr "ЗмÑніць налады аўдыё гульні." msgid "Check and configure all the hot keys present in the game." msgstr "ПраглÑдзець Ñ– наладзіць ÑпалучÑнні клавіш у гульні." msgid "Toggle to display damage information during the battle." msgstr "" msgid "Exit this menu." msgstr "ВыйÑці з меню" msgid "Okay" msgstr "Добра" msgid "The enemy has surrendered!" msgstr "Вораг здаўÑÑ!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Вораг уцёк!" msgid "A glorious victory!" msgstr "Ð¡Ð»Ð°ÑžÐ½Ð°Ñ Ð¿ÐµÑ€Ð°Ð¼Ð¾Ð³Ð°!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "За мужнаÑць у баі %{name} атрымлівае %{exp} вопыту." msgid "The cowardly %{name} flees from battle." msgstr "%{name} баÑзліва ўцÑкае з Ð¿Ð¾Ð»Ñ Ð±Ñ–Ñ‚Ð²Ñ‹." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} здаўÑÑ Ð²Ð¾Ñ€Ð°Ð³Ñƒ Ñ– Ñышоў з ганьбай." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Ð’Ð°ÑˆÑ‹Ñ Ð²Ð¾Ð¹Ñкі былі знішчаны, а %{name} пакідае ваÑ." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Ð’Ð°ÑˆÑ‹Ñ Ð²Ð¾Ð¹Ñкі былі знішчаны." msgid "Battlefield Casualties" msgstr "Страты на полі бою" msgid "Attacker" msgstr "Ðападнік" msgid "Defender" msgstr "Ðбаронца" #, fuzzy msgid "Click to leave the battle results." msgstr "ПÑтрыкні, каб ухваліць абранае раздзÑленне." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "ПÑтрыкні, каб вÑрнуцца Ñž галоўнае меню." msgid "Restart" msgstr "" msgid "You have captured an enemy artifact!" msgstr "Ð’Ñ‹ захапілі варожы артÑфакт!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "" "СÑрод вашых трафеÑÑž апынуўÑÑ Ð°Ñ€Ñ‚Ñфакт - %{name}! Ðле Ñк толькі вы " "дакрануліÑÑ Ð´Ð° Ñго, той міÑтычна знік." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Як толькі вораг дабраўÑÑ Ð´Ð° артÑфакту - %{name}, той міÑтычна знік." msgid "Necromancy!" msgstr "" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Практыкуючы цёмнае майÑÑ‚ÑÑ€Ñтва некраманціі, вы можаце адрадзіць %{count} " "паўшых ворагаў, ÑÐºÑ–Ñ Ð´Ð°Ð»ÑƒÑ‡Ð°Ñ†Ñ†Ð° да вашага войÑку Ñк %{monster}." msgid "%{name} the %{race}" msgstr "%{race} %{name}" msgid "Captain of %{name}" msgstr "Капітан %{name}" msgid "Attack" msgstr "Ðтака" msgid "Defense" msgstr "Ðбарона" msgid "Spell Power" msgstr "ÐœÐ°Ð³Ñ–Ñ‡Ð½Ð°Ñ Ð¼Ð¾Ñ†" msgid "Knowledge" msgstr "Веды" msgid "Morale" msgstr "Мараль" msgid "Luck" msgstr "Удача" msgid "Spell Points" msgstr "Ðдзінкі магіі" msgid "Hero's Options" msgstr "Ðалады героÑ" msgid "Cast Spell" msgstr "" msgid "Retreat" msgstr "" msgid "Surrender" msgstr "" msgid "Cancel" msgstr "Ðазад" msgid "Hero Screen" msgstr "Экран героÑ" msgid "Captain's Options" msgstr "Ðаладкі капітана" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Прамовіць магічны загавор. У Ð²Ð°Ñ Ñ‘Ñць магчымаÑць прамаўлÑць загаворы што " "раз, калі ÑžÑе ўдзельнікі Ð±Ð¾Ñ Ð·Ñ€Ð¾Ð±Ñць Ñвае хады." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" msgid "Open Hero Screen to view full information about the hero." msgstr "Разгарніце Ñкран героÑ, каб праглÑдзець уÑÑŽ інфармацыю пра Ñго." msgid "Return to the battle." msgstr "Ð’Ñрнуцца да бою." msgid "Not enough gold (%{gold})" msgstr "ÐедаÑтаткова золату (%{gold})" msgid "%{name} states:" msgstr "" msgid "Captain of %{name} states:" msgstr "" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" msgid "View %{monster} info" msgstr "" msgid "Fly %{monster} here" msgstr "" msgid "Move %{monster} here" msgstr "" msgid "Shoot %{monster}" msgstr "" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Attack %{monster}" msgstr "" msgid "Turn %{turn}" msgstr "" msgid "Teleport here" msgstr "ТÑлепартаваць Ñюды" msgid "Invalid teleport destination" msgstr "" msgid "Cast %{spell} on %{monster}" msgstr "" msgid "Cast %{spell}" msgstr "" msgid "Select spell target" msgstr "" msgid "View Ballista info" msgstr "" msgid "Ballista" msgstr "" #, fuzzy msgid "Automatic combat modes" msgstr "Ðўта-бой" #, fuzzy msgid "Automatic Combat Modes" msgstr "Ðўта-бой" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "" msgid "Allows you to customize the combat screen." msgstr "" msgid "System Options" msgstr "" msgid "Skip this unit" msgstr "" msgid "Skip" msgstr "" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" msgid "View Captain's options" msgstr "" msgid "View Hero's options" msgstr "" msgid "View opposing Captain" msgstr "" msgid "View opposing Hero" msgstr "" msgid "Hide logs" msgstr "" msgid "Show logs" msgstr "" msgid "Message Bar" msgstr "" msgid "Shows the results of individual monster's actions." msgstr "" #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Ð’Ñ‹ ўпÑўненыÑ, што хочаце выйÑці?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Ð’Ñ‹ ўпÑўненыÑ, што хочаце выйÑці?" msgid "The computer continues the combat for you." msgstr "" msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Ðўта-бой" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Ðўта-бой" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "У горадзе ўжо Ñ‘Ñць %{name}." msgstr[1] "У горадзе ўжо Ñ‘Ñць %{name}." msgstr[2] "У горадзе ўжо Ñ‘Ñць %{name}." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "" #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "У горадзе ўжо Ñ‘Ñць %{name}." msgstr[1] "У горадзе ўжо Ñ‘Ñць %{name}." msgstr[2] "У горадзе ўжо Ñ‘Ñць %{name}." msgid "%{name} casts %{spell} on the %{troop}." msgstr "" msgid "%{name} casts %{spell}." msgstr "" msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "" msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "" msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "" msgid "The %{spell} does %{damage} damage." msgstr "" msgid "The %{spell} does %{damage} damage to one living creature." msgstr "" msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "" msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Bad luck descends on the %{attacker}." msgstr "" msgid "Good luck shines on the %{attacker}." msgstr "" msgid "High morale enables the %{monster} to attack again." msgstr "" msgid "Low morale causes the %{monster} to freeze in panic." msgstr "" msgid "%{tower} does %{damage} damage." msgstr "" msgid "The mirror image is created." msgstr "" msgid "The mirror image is destroyed!" msgstr "" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Ð’Ñ‹ ўпÑўненыÑ, што хочаце выйÑці?" msgid "Error" msgstr "Памылка" msgid "No spells to cast." msgstr "ÐÑма загавораў." msgid "Are you sure you want to retreat?" msgstr "" msgid "Retreat disabled" msgstr "" msgid "Surrender disabled" msgstr "" msgid "Damage: %{max}" msgstr "Урон: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Урон: %{min} - %{max}" msgid "Perish: %{max}" msgstr "" msgid "Perish: %{min} - %{max}" msgstr "" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" msgid "Human" msgstr "Чалавек" msgid "AI" msgstr "Кампутар" msgid "Start" msgstr "" #, fuzzy msgid "Start the battle." msgstr "Ð’Ñрнуцца да бою." msgid "Exit" msgstr "Выхад" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Калі лаÑка, выбÑрыце іншага героÑ." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "" msgid "Monsters" msgstr "" msgid "N/A" msgstr "" msgid "Left Turret" msgstr "Ð›ÐµÐ²Ð°Ñ Ð²ÐµÐ¶Ð°" msgid "Right Turret" msgstr "ÐŸÑ€Ð°Ð²Ð°Ñ Ð²ÐµÐ¶Ð°" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "" msgid "each with a +%{attack} bonus to their attack skill." msgstr "" #, fuzzy msgid "The %{name} is destroyed." msgstr "У горадзе ўжо Ñ‘Ñць %{name}." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Dwarven Alliance" msgstr "ÐльÑÐ½Ñ Ð· гномамі" msgid "Sorceress Guild" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ñ‡Ð°Ñ€Ð°ÑžÐ½Ñ–Ñ†" msgid "Necromancer Guild" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð½ÐµÐºÑ€Ð°Ð¼Ð°Ð½Ñ‚Ð°Ñž" msgid "Ogre Alliance" msgstr "ÐльÑÐ½Ñ Ð· ограмі" msgid "Dwarfbane" msgstr "" msgid "Dragon Alliance" msgstr "ÐльÑÐ½Ñ Ð· цмокамі" msgid "Elven Alliance" msgstr "ÐльÑÐ½Ñ Ð· Ñльфамі" msgid "Kraeger defeated" msgstr "" msgid "Wayward Son" msgstr "Сын Ð’Ñйуорда" msgid "Uncle Ivan" msgstr "ДзÑдзька Іван" msgid "Annexation" msgstr "ÐнекÑÑ–Ñ" msgid "Force of Arms" msgstr "Сіла зброі" msgid "Save the Dwarves" msgstr "Уратаванне гномаў" msgid "Carator Mines" msgstr "Руднікі Каратора" msgid "Turning Point" msgstr "" msgid "scenarioName|Defender" msgstr "" msgid "Corlagon's Defense" msgstr "Ðбарона Карлагона" msgid "The Crown" msgstr "Карона" msgid "The Gauntlet" msgstr "Рукавіца" msgid "Betrayal" msgstr "Здраднік" msgid "Final Justice" msgstr "" #, fuzzy msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Роланду патрÑбна, каб вы перамаглі лордаў ÐºÐ°Ð»Ñ Ñгонага замку, каб раÑпачаць " "паўÑтанне Ñупраць брата. Яны не хаўруÑнікі, таму вÑлікую чаÑтку чаÑу будуць " "змагацца адзін з адным. Ð’Ñ‹ Ñкончыце паÑпÑхова міÑÑ–ÑŽ, Ñк толькі пераможаце " "ÑžÑÑ–Ñ… лордаў Ñ– захопіце Ñ–Ñ…Ð½Ñ‹Ñ Ð·Ð°Ð¼ÐºÑ–." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "МÑÑÑ†Ð¾Ð²Ñ‹Ñ Ð»Ð¾Ñ€Ð´Ñ‹ адмаўлÑюцца прыÑÑгаць на вернаÑць Роланду, таму Ñ–Ñ… трÑба " "ўціхамірыць. РыхтуйцеÑÑ Ð´Ð° жорÑткай барацьбы, бо Ñны Ð·Ð°Ð¼Ð¾Ð¶Ð½Ñ‹Ñ Ñ– ўплывовыÑ. " "Захапіце Ð²Ð°Ñ€Ð¾Ð¶Ñ‹Ñ Ð·Ð°Ð¼ÐºÑ–, каб перамагчы." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Ð’Ð°ÑˆÐ°Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° - абараніць гномаў ад войÑкаў Ðрчыбальда. Каб перамагчы - " "захапіце ÑžÑе Ð²Ð°Ñ€Ð¾Ð¶Ñ‹Ñ Ð³Ð°Ñ€Ð°Ð´Ñ‹ Ñ– замкі. Сачыце за тым, каб не Ñтраціць адразу " "ÑžÑе гарады гномаў, іначай вораг пераможа." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Ð’Ñ‹ ÑутыкнёцеÑÑ Ð· чатырма ворагамі-хаўруÑнікамі Ñž бітве за Ñ€ÑÑурÑÑ‹ Ñ– Ñкарбы. " "Ð”Ð»Ñ Ð¿ÐµÑ€Ð°Ð¼Ð¾Ð³Ñ– захапіце ÑžÑе Ð²Ð°Ñ€Ð¾Ð¶Ñ‹Ñ Ð·Ð°Ð¼ÐºÑ–." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Ð’Ð°ÑˆÑ‹Ñ Ð²Ð¾Ñ€Ð°Ð³Ñ– аб’ÑдналіÑÑ Ñупраць ваÑ, Ñ– Ñны побач з вамі, таму рыхтуйцеÑÑ " "адразу ÑžÑтупіць у бой. Вам неабходна авалодаць уÑімі чатырма замкамі Ñž гÑтай " "маленькай даліне, каб перамагчы." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð§Ð°Ñ€Ð°ÑžÐ½Ñ–Ñ† ÐараÑтону звÑрнулаÑÑ Ð´Ð° Роланда па дапамогу Ñž абароне ад " "нападу хаўруÑнікаў Ðрчыбальда. Захапіце ÑžÑе Ð²Ð°Ñ€Ð¾Ð¶Ñ‹Ñ Ð·Ð°Ð¼ÐºÑ–, каб перамагчы, " "але не дапуÑціце Ñтрату ÐараÑтону, іначай вы атрымаеце паразу. (Падказка: на " "воÑтраве Ñž акіÑне Ñ‘Ñць варожы замак)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "ЗбÑрыце Ñк мага болей войÑка, каб за 8 тыднÑÑž захапіць варожы замак. Вам " "ÑупрацьÑтаіць толькі адзін вораг, але вы муÑіце прайÑці доўгую дарогу да " "Ñгонага замку. УÑе войÑкі, ÑÐºÑ–Ñ Ð·Ð°Ñтануцца пад катролем вашага герою " "напрыканцы ÑцÑнару, будуць прымаць удзел у рашучым баю." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Знайдзіце Карону хутчÑй за героÑÑž Ðрчыбальда. Роланду неабходна Карона Ñž " "рашучым баю Ñупраць Ðрчыбальда." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Тры ворага-хаўруÑніка разам з Лордам Карлагонам ÑтаÑць паміж вамі Ñ– вашай " "перамогай. Роланд знаходзіцца Ñž замку на паўночна-заходнім кірунку, Ñ– вы " "прайграеце, калі Ñго захопÑць. ПамÑтайце, што захоп Лорда Карлагона гарантуе " "тое, што ён не будзе змагацца Ñупраць Ð²Ð°Ñ Ñƒ фінальным ÑцÑнары." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "ГÑта рашучы бой. Ð’Ñ‹ Ñ– Ð²Ð°ÑˆÑ‹Ñ Ð²Ð¾Ñ€Ð°Ð³Ñ– ÑžÐ·Ð±Ñ€Ð¾ÐµÐ½Ñ‹Ñ Ð´Ð° зубоў, Ñ– Ñны ÑžÑе аб’ÑдналіÑÑ " "Ñупраць ваÑ. Захапіце Ðрчыбальда, каб Ñкончыць вайну!" #, fuzzy msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Калі вы перакінецеÑÑ Ð½Ð° іншы бок, у Ð²Ð°Ñ Ð·Ð°Ñтанецца тры замкі Ñупраць замка " "ворага. ГÑты бой будзе Ñамы лёгкі з тых, з Ñкімі вы ÑутыкнёцеÑÑ Ð´Ð° канца " "вайны… здраднік." msgid "Barbarian Wars" msgstr "" msgid "First Blood" msgstr "" msgid "Necromancers" msgstr "" msgid "Slay the Dwarves" msgstr "" msgid "Country Lords" msgstr "" msgid "Dragon Master" msgstr "" msgid "Rebellion" msgstr "" msgid "Apocalypse" msgstr "" msgid "Greater Glory" msgstr "" #, fuzzy msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Роланду патрÑбна, каб вы перамаглі лордаў ÐºÐ°Ð»Ñ Ñгонага замку, каб раÑпачаць " "паўÑтанне Ñупраць брата. Яны не хаўруÑнікі, таму вÑлікую чаÑтку чаÑу будуць " "змагацца адзін з адным. Ð’Ñ‹ Ñкончыце паÑпÑхова міÑÑ–ÑŽ, Ñк толькі пераможаце " "ÑžÑÑ–Ñ… лордаў Ñ– захопіце Ñ–Ñ…Ð½Ñ‹Ñ Ð·Ð°Ð¼ÐºÑ–." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" msgid "Arrow's Flight" msgstr "" msgid "Island of Chaos" msgstr "" msgid "The Abyss" msgstr "" msgid "Uprising" msgstr "" msgid "Aurora Borealis" msgstr "" msgid "Betrayal's End" msgstr "" msgid "Corruption's Heart" msgstr "" msgid "The Giant's Pass" msgstr "" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" msgid "For the good of the Empire, eliminate Kraeger." msgstr "" msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" msgid "Border Towns" msgstr "" msgid "Conquer and Unify" msgstr "" msgid "Crazy Uncle Ivan" msgstr "" msgid "The Wayward Son" msgstr "" msgid "Ivory Gates" msgstr "" msgid "The Elven Lands" msgstr "" msgid "The Epic Battle" msgstr "" msgid "The Southern War" msgstr "" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "" msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" msgid "Fount of Wizardry" msgstr "" msgid "Power's End" msgstr "" msgid "The Eternal Scrolls" msgstr "" msgid "The Shrouded Isles" msgstr "" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" msgid "Blood is Thicker" msgstr "" msgid "King and Country" msgstr "" msgid "Pirate Isles" msgstr "" msgid "Stranded" msgstr "" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" msgid " bane" msgstr "" msgid " alliance" msgstr "" msgid "Carry-over forces" msgstr "" msgid " bonus" msgstr "" msgid " defeated" msgstr "" msgid " will always run away from your army." msgstr "" msgid " will be willing to join your army." msgstr "" msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" msgid "The army will be carried over in the campaign." msgstr "" msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" msgid "%{hero} can be hired during scenarios." msgstr "" msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "" msgid "campaignBonus|Animate Dead" msgstr "" msgid "campaignBonus|Chain Lightning" msgstr "" msgid "campaignBonus|Fireblast" msgstr "" msgid "campaignBonus|Mass Curse" msgstr "" msgid "campaignBonus|Mass Haste" msgstr "" msgid "campaignBonus|Mirror Image" msgstr "" msgid "campaignBonus|Resurrect" msgstr "" msgid "campaignBonus|Steelskin" msgstr "" msgid "campaignBonus|Summon Earth" msgstr "" msgid "campaignBonus|View Heroes" msgstr "" msgid "campaignBonus|Ballista" msgstr "" msgid "campaignBonus|Black Pearl" msgstr "" msgid "campaignBonus|Caster's Bracelet" msgstr "" msgid "campaignBonus|Defender Helm" msgstr "" msgid "campaignBonus|Breastplate" msgstr "" msgid "campaignBonus|Dragon Sword" msgstr "" msgid "campaignBonus|Fizbin Medal" msgstr "" msgid "campaignBonus|Foremost Scroll" msgstr "" msgid "campaignBonus|Gauntlets" msgstr "" msgid "campaignBonus|Hideous Mask" msgstr "" msgid "campaignBonus|Mage's Ring" msgstr "" msgid "campaignBonus|Major Scroll" msgstr "" msgid "campaignBonus|Medal of Honor" msgstr "" msgid "campaignBonus|Medal of Valor" msgstr "" msgid "campaignBonus|Minor Scroll" msgstr "" msgid "campaignBonus|Nomad Boots" msgstr "" msgid "campaignBonus|Power Axe" msgstr "" msgid "campaignBonus|Spiked Shield" msgstr "" msgid "campaignBonus|Stealth Shield" msgstr "" msgid "campaignBonus|Tax Lien" msgstr "" msgid "campaignBonus|Thunder Mace" msgstr "" msgid "campaignBonus|Traveler's Boots" msgstr "" msgid "campaignBonus|White Pearl" msgstr "" msgid "campaignBonus|Basic Archery" msgstr "" msgid "campaignBonus|Advanced Archery" msgstr "" msgid "campaignBonus|Expert Archery" msgstr "" msgid "campaignBonus|Basic Ballistics" msgstr "" msgid "campaignBonus|Advanced Ballistics" msgstr "" msgid "campaignBonus|Expert Ballistics" msgstr "" msgid "campaignBonus|Basic Diplomacy" msgstr "" msgid "campaignBonus|Advanced Diplomacy" msgstr "" msgid "campaignBonus|Expert Diplomacy" msgstr "" msgid "campaignBonus|Basic Eagle Eye" msgstr "" msgid "campaignBonus|Advanced Eagle Eye" msgstr "" msgid "campaignBonus|Expert Eagle Eye" msgstr "" msgid "campaignBonus|Basic Estates" msgstr "" msgid "campaignBonus|Advanced Estates" msgstr "" msgid "campaignBonus|Expert Estates" msgstr "" msgid "campaignBonus|Basic Leadership" msgstr "" msgid "campaignBonus|Advanced Leadership" msgstr "" msgid "campaignBonus|Expert Leadership" msgstr "" msgid "campaignBonus|Basic Logistics" msgstr "" msgid "campaignBonus|Advanced Logistics" msgstr "" msgid "campaignBonus|Expert Logistics" msgstr "" msgid "campaignBonus|Basic Luck" msgstr "" msgid "campaignBonus|Advanced Luck" msgstr "" msgid "campaignBonus|Expert Luck" msgstr "" msgid "campaignBonus|Basic Mysticism" msgstr "" msgid "campaignBonus|Advanced Mysticism" msgstr "" msgid "campaignBonus|Expert Mysticism" msgstr "" msgid "campaignBonus|Basic Navigation" msgstr "" msgid "campaignBonus|Advanced Navigation" msgstr "" msgid "campaignBonus|Expert Navigation" msgstr "" msgid "campaignBonus|Basic Necromancy" msgstr "" msgid "campaignBonus|Advanced Necromancy" msgstr "" msgid "campaignBonus|Expert Necromancy" msgstr "" msgid "campaignBonus|Basic Pathfinding" msgstr "" msgid "campaignBonus|Advanced Pathfinding" msgstr "" msgid "campaignBonus|Expert Pathfinding" msgstr "" msgid "campaignBonus|Basic Scouting" msgstr "" msgid "campaignBonus|Advanced Scouting" msgstr "" msgid "campaignBonus|Expert Scouting" msgstr "" msgid "campaignBonus|Basic Wisdom" msgstr "" msgid "campaignBonus|Advanced Wisdom" msgstr "" msgid "campaignBonus|Expert Wisdom" msgstr "" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" msgid "The starting alignment of the scenario will be %{race}." msgstr "" msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" msgid "The main hero will have %{skill} at the start of the scenario." msgstr "" msgid "Roland" msgstr "Роланд" msgid "Archibald" msgstr "Ðрчыбальд" #, fuzzy msgid "Price of Loyalty" msgstr "Кошт вернаÑці" msgid "Voyage Home" msgstr "" msgid "Wizard's Isle" msgstr "" msgid "Descendants" msgstr "" msgid "Cannot build. You have already built here today." msgstr "Ð’Ñ‹ ўжо будавалі ÑÑ‘Ð½Ð½Ñ Ñž гÑтым замку." msgid "For this action it is necessary to build a castle first." msgstr "" msgid "The %{building} produces %{monster}." msgstr "%{building} - пабудова, дзе штотыдзень падрыхтоўваюцца %{monster}." msgid "Requires:" msgstr "Ðеабходна:" msgid "Exit this menu without doing anything." msgstr "ВыйÑці з меню, нічога не змÑнÑючы." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Ðельга пабудаваць %{name}, бо замак занадта далёка ад вады." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Ðельга пабудаваць." #, fuzzy msgid "The %{name} is already built." msgstr "У горадзе ўжо Ñ‘Ñць %{name}." #, fuzzy msgid "Cannot build the %{name}." msgstr "%{name}. Ðельга пабудаваць." msgid "Build %{name}." msgstr "%{name}. Можна пабудаваць." msgid "Blackridge" msgstr "" msgid "Hillstone" msgstr "" msgid "Pinehurst" msgstr "" msgid "Whiteshield" msgstr "" msgid "Woodhaven" msgstr "" msgid "Blackwind" msgstr "" msgid "Bloodreign" msgstr "" msgid "Dragontooth" msgstr "" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" msgid "Tundara" msgstr "" msgid "Vulcania" msgstr "" msgid "Baywatch" msgstr "" msgid "Fountainhead" msgstr "" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" msgid "Sandcaster" msgstr "" msgid "Alamar" msgstr "" msgid "Burlock" msgstr "" msgid "Dragadune" msgstr "" msgid "Kalindra" msgstr "" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" msgid "Blackfang" msgstr "" msgid "New Dawn" msgstr "" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" msgid "Antioch" msgstr "" msgid "Avalon" msgstr "" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" msgid "Weed Patch" msgstr "" msgid "Brownston" msgstr "" msgid "Hilltop" msgstr "" msgid "Weddington" msgstr "УÑдзінтан" msgid "Westfork" msgstr "УÑÑтфарк" msgid "Whittingham" msgstr "УіцінгÑм" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "" msgid "Roscomon" msgstr "" msgid "Sherman" msgstr "ШÑрман" msgid "Yorksford" msgstr "ÐркÑфард" msgid "Blackburn" msgstr "БлÑкбёрн" msgid "Blacksford" msgstr "" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "ФÑнтан" msgid "Lankershire" msgstr "Ланкершыр" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "Цімберхіл" msgid "Troy" msgstr "ТроÑ" msgid "Forder Oaks" msgstr "" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "УÑÑтмур" msgid "Willow" msgstr "Уілаў" msgid "Corackston" msgstr "КаракÑтоўн" msgid "Sheltemburg" msgstr "ШÑлтÑмбург" msgid "Cannot recruit - you already have a Hero in this town." msgstr "" msgid "Cannot recruit - you have too many Heroes." msgstr "" #, fuzzy msgid "Cannot afford a Hero." msgstr "Ðельга пабудаваць." msgid "There is no room in the garrison for this army." msgstr "" msgid "Fortifications" msgstr "" msgid "Farm" msgstr "" msgid "Thatched Hut" msgstr "" msgid "Archery Range" msgstr "" msgid "Upg. Archery Range" msgstr "" msgid "Blacksmith" msgstr "" msgid "Upg. Blacksmith" msgstr "" msgid "Armory" msgstr "" msgid "Upg. Armory" msgstr "" msgid "Jousting Arena" msgstr "" msgid "Upg. Jousting Arena" msgstr "" msgid "Cathedral" msgstr "" msgid "Upg. Cathedral" msgstr "" msgid "Coliseum" msgstr "" msgid "Garbage Heap" msgstr "" msgid "Hut" msgstr "" msgid "Stick Hut" msgstr "" msgid "Upg. Stick Hut" msgstr "" msgid "Den" msgstr "" msgid "Adobe" msgstr "" msgid "Upg. Adobe" msgstr "" msgid "Bridge" msgstr "" msgid "Upg. Bridge" msgstr "" msgid "Pyramid" msgstr "" msgid "Rainbow" msgstr "Ð’ÑÑёлка" msgid "Crystal Garden" msgstr "" msgid "Treehouse" msgstr "" msgid "Cottage" msgstr "" msgid "Upg. Cottage" msgstr "" msgid "Stonehenge" msgstr "" msgid "Upg. Stonehenge" msgstr "" msgid "Fenced Meadow" msgstr "" msgid "sorceress|Red Tower" msgstr "Ð§Ñ‹Ñ€Ð²Ð¾Ð½Ð°Ñ Ð²ÐµÐ¶Ð°" msgid "Dungeon" msgstr "" msgid "Waterfall" msgstr "" msgid "Cave" msgstr "" msgid "Crypt" msgstr "" msgid "Nest" msgstr "" msgid "Maze" msgstr "" msgid "Upg. Maze" msgstr "" msgid "Swamp" msgstr "" msgid "Green Tower" msgstr "ЗÑÐ»Ñ‘Ð½Ð°Ñ Ð²ÐµÐ¶Ð°" msgid "warlock|Red Tower" msgstr "" msgid "Black Tower" msgstr "Ð§Ð¾Ñ€Ð½Ð°Ñ Ð²ÐµÐ¶Ð°" msgid "Library" msgstr "БібліÑÑ‚Ñка" msgid "Orchard" msgstr "Фруктовы Ñад" msgid "Habitat" msgstr "Жыллё" msgid "Pen" msgstr "Вальера" msgid "Foundry" msgstr "Ліцейны завод" msgid "Upg. Foundry" msgstr "" msgid "Cliff Nest" msgstr "ГнÑздо на кручы" msgid "Ivory Tower" msgstr "Вежа магаў" msgid "Upg. Ivory Tower" msgstr "ÐбÑÐµÑ€Ð²Ð°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð¼Ð°Ð³Ð°Ñž" msgid "Cloud Castle" msgstr "Воблачны замак" msgid "Upg. Cloud Castle" msgstr "" msgid "Storm" msgstr "" msgid "Skull Pile" msgstr "" msgid "Excavation" msgstr "" msgid "Graveyard" msgstr "" msgid "Upg. Graveyard" msgstr "" msgid "Upg. Pyramid" msgstr "" msgid "Mansion" msgstr "" msgid "Upg. Mansion" msgstr "" msgid "Mausoleum" msgstr "" msgid "Upg. Mausoleum" msgstr "" msgid "Laboratory" msgstr "" msgid "Shrine" msgstr "" msgid "Special" msgstr "" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Хобіты" #, fuzzy msgid "Dwelling 2" msgstr "Хобіты" #, fuzzy msgid "Upg. Dwelling 2" msgstr "Хобіты" #, fuzzy msgid "Dwelling 3" msgstr "Хобіты" #, fuzzy msgid "Upg. Dwelling 3" msgstr "Хобіты" #, fuzzy msgid "Dwelling 4" msgstr "Хобіты" #, fuzzy msgid "Upg. Dwelling 4" msgstr "Хобіты" #, fuzzy msgid "Dwelling 5" msgstr "Хобіты" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Хобіты" #, fuzzy msgid "Dwelling 6" msgstr "Хобіты" #, fuzzy msgid "Upg. Dwelling 6" msgstr "Хобіты" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" msgid "The Rainbow increases the luck of the defending units by two." msgstr "" msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" #, fuzzy msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "БібліÑÑ‚Ñка павÑлічвае колькаÑць загавораў у Гільдыі на адзін на кожны " "ўзровень гільдыі." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Фруктовы Ñад прываблівае дадатковых %{count} хобітаў штотыдзень." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" msgid "Thieves' Guild" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð²Ð°Ñ€Ð¾Ñž" msgid "Tavern" msgstr "Карчма" msgid "Shipyard" msgstr "Верф" msgid "Well" msgstr "Калодзеж" msgid "Statue" msgstr "СтатуÑ" msgid "Marketplace" msgstr "Рынак" msgid "Moat" msgstr "Роў" msgid "Castle" msgstr "Замак" msgid "Tent" msgstr "Шацёр" msgid "Captain's Quarters" msgstr "Жыллё капітана" msgid "Mage Guild, Level 1" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð¼Ð°Ð³Ð°Ñž I" msgid "Mage Guild, Level 2" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð¼Ð°Ð³Ð°Ñž II" msgid "Mage Guild, Level 3" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð¼Ð°Ð³Ð°Ñž III" msgid "Mage Guild, Level 4" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð¼Ð°Ð³Ð°Ñž IV" msgid "Mage Guild, Level 5" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð¼Ð°Ð³Ð°Ñž V" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" msgid "The Tavern increases morale for troops defending the castle." msgstr "Карчма павÑлічвае мараль вашых войÑкаў Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð°Ð±Ð°Ñ€Ð¾Ð½Ñ‹ замка." msgid "The Shipyard allows ships to be built." msgstr "Верф дазвалÑе будаваць караблі." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "The Left Turret provides extra firepower during castle combat." msgstr "Ð›ÐµÐ²Ð°Ñ Ð²ÐµÐ¶Ð° забÑÑпечвае дадатковую агнÑвую моц Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð°Ð±Ð°Ñ€Ð¾Ð½Ñ‹ замка." msgid "The Right Turret provides extra firepower during castle combat." msgstr "ÐŸÑ€Ð°Ð²Ð°Ñ Ð²ÐµÐ¶Ð° забÑÑпечвае дадатковую агнÑвую моц Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð°Ð±Ð°Ñ€Ð¾Ð½Ñ‹ замка." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Рынак дазвалÑе мÑнÑць адзін від Ñ€ÑÑурÑаў на іншы. Чым болей рынкаў вы маеце, " "тым лепей будуць умовы абмену." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Роў запавольвае Ð°Ñ‚Ð°ÐºÑƒÑŽÑ‡Ñ‹Ñ Ð²Ð¾Ð¹Ñкі. Любое войÑка, Ñкое ўвайшло Ñž роў не можа " "рухацца далей Ñ– павінна Ñкончыць Ñвой ход, а такÑама горш абаранÑецца." #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Замак узмацнÑе абарону горада Ñ– павÑлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ да %{count} " "золата штодзень." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð¼Ð°Ð³Ð°Ñž дазвалÑе героÑм вучыць загаворы Ñ– папаўнÑць Ñ–Ñ…Ð½Ñ‹Ñ Ð·Ð°Ð¿Ð°ÑÑ‹ маны." msgid "Recruit %{name}" msgstr "%{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "МеÑÑц: %{month}, Тыдзень: %{week}, Дзень: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" msgid "Click to show next town." msgstr "" msgid "Show next town" msgstr "" msgid "Click to show previous town." msgstr "" msgid "Show previous town" msgstr "" msgid "This town may not be upgraded to a castle." msgstr "" msgid "Town" msgstr "Горад" msgid "Exit Castle" msgstr "Пакінуць замак" msgid "Exit Town" msgstr "Пакінуць горад" msgid "Show Income" msgstr "Паказаць прыбытак" msgid "View Hero" msgstr "Даведацца аб героі" msgid "The above spells are available here." msgstr "" msgid "The spells the hero can learn have been added to their book." msgstr "" msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" msgid "Recruit Hero" msgstr "РÑкрутаваць героÑ" msgid "%{name} is a level %{value} %{race} " msgstr "" msgid "with %{count} artifacts." msgstr "" msgid "with 1 artifact." msgstr "" msgid "without artifacts." msgstr "" msgid "Recruit %{name} the %{race}" msgstr "РÑкрутаваць %{race} %{name}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" msgid "Spread Formation" msgstr "" msgid "Grouped Formation" msgstr "" #, fuzzy msgid "Click to show the next town." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "Click to show the previous town." msgstr "ПÑтрыкні, каб ухваліць абранае раздзÑленне." msgid "Set garrison combat formation to 'Spread'" msgstr "" msgid "Set garrison combat formation to 'Grouped'" msgstr "" msgid "Exit Castle Options" msgstr "" msgid "Castle Options" msgstr "Ðаладкі замка" msgid "Not enough resources to recruit creatures." msgstr "" msgid "You are unable to recruit at this time, your ranks are full." msgstr "" msgid "No creatures available for purchase." msgstr "" msgid "Recruit Creatures" msgstr "" msgid "Hire all creatures in the town." msgstr "" msgid "Max" msgstr "" msgid "Available" msgstr "ДаÑтупна" msgid "Town Population Information and Statistics" msgstr "" msgid "Damage" msgstr "Урон" msgid "HP" msgstr "" msgid "Growth" msgstr "" msgid "week" msgstr "тыдзень" msgid "View World" msgstr "" msgid "View the entire world." msgstr "" msgid "Puzzle" msgstr "" msgid "View the obelisk puzzle." msgstr "" msgid "Scenario Information" msgstr "" msgid "View information on the scenario you are currently playing." msgstr "" msgid "Dig for the Ultimate Artifact." msgstr "" msgid "Digging" msgstr "" msgid "Arena" msgstr "" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" msgid "Attack Skill" msgstr "Ðтака" msgid "Defense Skill" msgstr "Ðбарона" msgid "Shots" msgstr "СтрÑлы" msgid "Shots Left" msgstr "ÐÑтатак ÑтрÑлаў" msgid "Hit Points" msgstr "Здароўе" msgid "Hit Points Left" msgstr "ÐÑтатак здароўÑ" msgid "You can't afford to upgrade your troops!" msgstr "" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" msgid "Are you sure you want to dismiss this army?" msgstr "" msgid "Upgrade" msgstr "" msgid "Upgrade your troops." msgstr "" msgid "Dismiss" msgstr "" msgid "Dismiss this army." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" msgid "Followers" msgstr "" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" msgid "(Rate: %{percent})" msgstr "" msgid "off" msgstr "выкл." msgid "Music" msgstr "Музыка" msgid "Effects" msgstr "Эфекты" msgid "MIDI" msgstr "" msgid "MIDI Expansion" msgstr "" msgid "External" msgstr "Вонкавы" msgid "Music Type" msgstr "Тып Музыкі" msgid "3D Audio" msgstr "3D Ðўдыё" msgid "Toggle ambient music level." msgstr "ЗмÑніць гучнаÑць фонавай музыкі." msgid "Toggle foreground sounds level." msgstr "ЗмÑніць гучнаÑць гукаў на пÑÑ€Ñднім плане." msgid "Change the type of music." msgstr "ЗмÑніць тып музыкі." #, fuzzy msgid "Toggle the 3D effect of foreground sounds." msgstr "Укл/выкл 3D Ñфекты гукаў на пÑÑ€Ñднім плане." msgid "Build a new ship:" msgstr "" msgid "Resource cost:" msgstr "" msgid "Total: " msgstr "" msgid "Need: " msgstr "" msgid "New Game" msgstr "ÐÐ¾Ð²Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "Start a single or multi-player game." msgstr "Пачаць новую адзіночную ці шматаÑабовую гульню." msgid "Load Game" msgstr "Загрузіць гульню" msgid "Load a previously saved game." msgstr "ПрацÑгнуць захаваную гульню." msgid "Save Game" msgstr "" msgid "Save the current game." msgstr "" msgid "Quit" msgstr "Скончыць" msgid "Quit out of Heroes of Might and Magic II." msgstr "ВыйÑці з Heroes of Might and Magic II." msgid "Language" msgstr "Мова" msgid "Graphics" msgstr "ГрафічныÑ" msgid "Black & White" msgstr "Чорна-белы" msgid "Mouse Cursor" msgstr "КурÑор мышы" msgid "Color" msgstr "КалÑровы" msgid "Text Support" msgstr "ТÑкÑÑ‚Ð°Ð²Ñ‹Ñ Ð¿Ð°Ð´ÐºÐ°Ð·ÐºÑ–" msgid "Change the language of the game." msgstr "ЗмÑніць мову гульні." msgid "Select Game Language" msgstr "Мова" msgid "Change the graphics settings of the game." msgstr "Ðаладзіць графіку." #, fuzzy msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Укл/выкл калÑровы курÑор. ГÑта ўплывае толькі на візуал." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Укл/выкл Ñ‚ÑкÑÑ‚Ð°Ð²Ñ‹Ñ Ð¿Ð°Ð´ÐºÐ°Ð·ÐºÑ– з дадатковай інфармацыÑй пра вокны Ñ– падзеі Ñž " "гульні." msgid "" "Map\n" "Difficulty" msgstr "" msgid "" "Game\n" "Difficulty" msgstr "" msgid "Rating" msgstr "" msgid "Map Size" msgstr "" msgid "Opponents" msgstr "Супраціўнікі" msgid "Class" msgstr "КлаÑ" msgid "" "Victory\n" "Conditions" msgstr "" msgid "" "Loss\n" "Conditions" msgstr "" msgid "First select recipients!" msgstr "" msgid "You cannot select %{resource}!" msgstr "" #, fuzzy msgid "Set %{resource-type} Count" msgstr "" "Ðекалькі\n" "%{monster}" msgid "Select Recipients" msgstr "" msgid "Your Funds" msgstr "" msgid "Planned Gift" msgstr "" msgid "Gift from %{name}" msgstr "" msgid "Resolution" msgstr "РаздзÑленне Ñкрана" msgid "Fullscreen" msgstr "ПоўнаÑкранны" msgid "window|Mode" msgstr "РÑжым адлюÑтраваннÑ" msgid "Windowed" msgstr "Ðконны" msgid "V-Sync" msgstr "Ð’ÐµÑ€Ñ‚Ñ‹ÐºÐ°Ð»ÑŒÐ½Ð°Ñ ÑінхранізацыÑ" msgid "FPS" msgstr "" msgid "System Info" msgstr "СіÑÑ‚ÑÐ¼Ð½Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ" msgid "Change the resolution of the game." msgstr "ЗмÑніць раздзÑленне Ñкранa." msgid "Select Game Resolution" msgstr "РаздзÑленне Ñкрана" msgid "Toggle between fullscreen and windowed modes." msgstr "Пераключыцца паміж поўнаÑкранным Ñ– аконным Ñ€Ñжымам." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "Ð’ÐµÑ€Ñ‚Ñ‹ÐºÐ°Ð»ÑŒÐ½Ð°Ñ ÑÑ–Ð½Ñ…Ñ€Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ‹Ñ Ð¼Ð¾Ð¶Ð° вырашыць праблемы з мігаценнем на некаторых " "маніторах. " msgid "Show extra information such as FPS and current time." msgstr "Паказваць FPS Ñ– бÑгучы чаÑ." msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" msgid "Event: " msgstr "" msgid "Hot Keys:" msgstr "Ð“Ð°Ñ€Ð°Ñ‡Ñ‹Ñ ÐºÐ»Ð°Ð²Ñ–ÑˆÑ‹:" msgid "Hide" msgstr "" msgid "Show" msgstr "" msgid "Interface" msgstr "" msgid "Interface Type" msgstr "" msgid "Toggle the type of interface you want to use." msgstr "" msgid "Toggle interface visibility." msgstr "" msgid "Scroll Speed" msgstr "" msgid "Sets the speed at which you scroll the window." msgstr "" msgid "Select Game Language:" msgstr "Мова" #, fuzzy msgid "Select Language:" msgstr "Мова" msgid "Click to choose the selected language." msgstr "ПÑтрыкні, каб ухваліць выбар мовы." msgid "%{name} has gained a level." msgstr "" msgid "%{skill} +1" msgstr "" msgid "You have learned %{skill}." msgstr "" msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "" msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" msgid "Min" msgstr "" msgid "Qty to trade" msgstr "" msgid "Trading Post" msgstr "" msgid "Your Resources" msgstr "" msgid "Available Trades" msgstr "" msgid "guarded by %{count} %{monster}" msgstr "" msgid "guarded by " msgstr "" msgid "(available: %{count})" msgstr "" msgid "(empty)" msgstr "" msgid "already learned" msgstr "" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Веды" msgid "already claimed" msgstr "" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "" msgid "already has max skills" msgstr "" msgid "(already visited)" msgstr "" msgid "(not visited)" msgstr "" msgid "%{color} Barrier" msgstr "" msgid "(tent visited)" msgstr "" msgid "%{color} Tent" msgstr "" msgid "Road" msgstr "" msgid "(digging ok)" msgstr "" msgid "(no digging)" msgstr "" msgid "penalty: %{cost}" msgstr "" msgid "Defenders:" msgstr "" msgid "Unknown" msgstr "" msgid "heroQuickInfo|(Level %{level})" msgstr "" msgid "Attack:" msgstr "" msgid "Defense:" msgstr "" msgid "Spell Power:" msgstr "" msgid "Knowledge:" msgstr "" msgid "Spell Points:" msgstr "" msgid "Move Points:" msgstr "" msgid "Uncharted Territory" msgstr "" msgid "Cost per troop:" msgstr "Кошт за адзінку:" msgid "Available: %{count}" msgstr "ДаÑтупна: %{count}" msgid "Number to buy:" msgstr "КолькаÑць:" msgid "Recruit selected monsters." msgstr "" msgid "Select maximum monsters to be recruited." msgstr "" msgid "Select only 1 monster to be recruited." msgstr "" #, fuzzy msgid "Select this game resolution." msgstr "РаздзÑленне Ñкрана" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "ÐбрÑры раздзÑленне Ñкранa:" msgid "Click to apply the selected resolution." msgstr "ПÑтрыкні, каб ухваліць абранае раздзÑленне." #, fuzzy msgid "Click to apply the entered text." msgstr "ПÑтрыкні, каб ухваліць абранае раздзÑленне." msgid "Click to open the Virtual Keyboard dialog." msgstr "" msgid "Open Virtual Keyboard" msgstr "" msgid "How many creatures do you wish to move?" msgstr "" msgid "Select how many units to separate into:" msgstr "" msgid "Map: " msgstr "" msgid "" "\n" "\n" "Month: " msgstr "" msgid ", Week: " msgstr "" msgid ", Day: " msgstr "" msgid "" "\n" "\n" "Location: " msgstr "" msgid "Are you sure you want to delete file:" msgstr "" msgid "Warning" msgstr "Увага" msgid "Click to save the current game." msgstr "" msgid "Click to load a previously saved game." msgstr "" msgid "File to Save:" msgstr "" msgid "File to Load:" msgstr "" msgid "Terrain object" msgstr "" msgid "Accept the choice made." msgstr "Ухваліць выбар." msgid "Select Skill:" msgstr "" msgid "Select Spell:" msgstr "" msgid "Select Artifact:" msgstr "" msgid "Select Monster:" msgstr "" msgid "Select Hero:" msgstr "" msgid "race|Random" msgstr "" "Выпад-\n" "ковы" #, fuzzy msgid "Click to start placing the selected hero." msgstr "ПÑтрыкні, каб ухваліць абранае раздзÑленне." #, fuzzy msgid "%{color} %{race}" msgstr "%{color} гулец" msgid "You will place" msgstr "" #, fuzzy msgid "Click to select this class." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "Click to select this color." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "Select Treasure:" msgstr "Мова" #, fuzzy msgid "Select Ocean Object:" msgstr "Мова" #, fuzzy msgid "Castle/town placing" msgstr "Ðаладкі замка" msgid "doubleLinedRace|Neutral" msgstr "" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "ПÑтрыкні, каб ухваліць абранае раздзÑленне." #, fuzzy msgid "Click to select town placing." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "Click to select castle placing." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} гулец" msgid "race|Neutral" msgstr "" #, fuzzy msgid "Select Dwelling:" msgstr "Хобіты" #, fuzzy msgid "Select Landscape Object:" msgstr "Мова" msgid "Mine placing" msgstr "" msgid "" "Resource\n" "type:" msgstr "" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{race} %{name}" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "Select Mountain Object:" msgstr "Мова" #, fuzzy msgid "Select Rock Object:" msgstr "Мова" #, fuzzy msgid "Select Tree Object:" msgstr "Мова" #, fuzzy msgid "Select Power Up Object:" msgstr "Мова" #, fuzzy msgid "Select Adventure Object:" msgstr "Мова" msgid "Players Icon" msgstr "Іконка гульцоў" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Паказвае колькаÑць гульцоў у ÑцÑнары. За не занÑÑ‚Ñ‹Ñ Ð°Ñобамі пазіцыі будзе " "гулÑць кампутар." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Паказвае памер мапы:\n" "малы (36 Ñ… 36), ÑÑÑ€Ñдні\n" "(72 x 72), вÑлікі (108 x 108)ці звышвÑлікі (144 Ñ… 144)." msgid "Size Icon" msgstr "Іконка памеру" msgid "Map Type" msgstr "Тып мапы" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Паказвае, Ð´Ð»Ñ Ñкой верÑÑ–Ñ– гульні зроблена мапа: Ð´Ð»Ñ \"The Succession Wars\" " "альбо \"The Price of Loyalty\"" msgid "Map Type:\n" msgstr "" msgid "The Succession Wars" msgstr "" #, fuzzy msgid "The Price of Loyalty" msgstr "Кошт вернаÑці" #, fuzzy msgid "Resurrection" msgstr "РаздзÑленне Ñкрана" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Мова" msgid "Lose all your heroes and towns." msgstr "Страціціь уÑÑ–Ñ… героÑÑž Ñ– гарады." msgid "Lose a specific town." msgstr "Страціць акрÑÑлены горад." msgid "Lose a specific hero." msgstr "Страціць акрÑÑленага героÑ." msgid "Run out of time. Fail to win by a certain point." msgstr "Вычарпаць чаÑ. Ðе перамагчы за акрÑÑлены чаÑ." msgid "Loss Condition" msgstr "Умова паразы" msgid "Defeat all enemy heroes and towns." msgstr "Знішчыць уÑÑ–Ñ… варожых героÑÑž Ñ– захапіць уÑе Ð²Ð°Ñ€Ð¾Ð¶Ñ‹Ñ Ð³Ð°Ñ€Ð°Ð´Ñ‹." msgid "Capture a specific town." msgstr "Захапіць акрÑÑлены горад." msgid "Defeat a specific hero." msgstr "Перамагчы акрÑÑленага героÑ." msgid "Find a specific artifact." msgstr "Ðдшукаць акрÑÑлены артÑфакт." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "Ваш бок перамагае Ñупрацьлеглы." msgid "Accumulate a large amount of gold." msgstr "ÐазапаÑіць вÑлікую колькаÑць золата." msgid "Victory Condition" msgstr "Умова перамогі" msgid "Map difficulty:" msgstr "СкладанаÑць мапы:" msgid "N" msgstr "" #, fuzzy msgid "No maps exist at that size." msgstr "ÐÑма мап абранага памеру" msgid "Small Maps" msgstr "ÐœÐ°Ð»Ñ‹Ñ Ð¼Ð°Ð¿Ñ‹" msgid "View only maps of size small (36 x 36)." msgstr "Паказваць толькі Ð¼Ð°Ð»Ñ‹Ñ Ð¼Ð°Ð¿Ñ‹ (36 Ñ… 36)." msgid "Medium Maps" msgstr "СÑÑ€ÑÐ´Ð½Ñ–Ñ Ð¼Ð°Ð¿Ñ‹" msgid "View only maps of size medium (72 x 72)." msgstr "Паказваць толькі ÑÑÑ€ÑÐ´Ð½Ñ–Ñ Ð¼Ð°Ð¿Ñ‹ (72 Ñ… 72)." msgid "Large Maps" msgstr "Ð’ÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹" msgid "View only maps of size large (108 x 108)." msgstr "Паказваць толькі вÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹ (108Ñ… 108)." msgid "Extra Large Maps" msgstr "ЗвышвÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹" msgid "View only maps of size extra large (144 x 144)." msgstr "Паказваць толькі звышвÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹ (144 Ñ… 144)." msgid "All Maps" msgstr "УÑе мапы" msgid "View all maps, regardless of size." msgstr "Паказваць уÑе мапы, незалежна ад памеру." msgid "Selected Name" msgstr "Ðазва мапы" msgid "The name of the currently selected map." msgstr "Ðазва абранай мапы." msgid "Selected Map Difficulty" msgstr "СкладанаÑць мапы" #, fuzzy msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "СкладанаÑць мапы вызначаецца ейным аўтарам. Болей ÑÐºÐ»Ð°Ð´Ð°Ð½Ñ‹Ñ Ð¼Ð°Ð¿Ñ‹ могуць " "утрымліваць больш ворагаў, менш Ñ€ÑÑурÑаў ці Ñ–Ð½ÑˆÑ‹Ñ Ð°Ð´Ð¼Ñ‹ÑÐ»Ð¾Ð²Ñ‹Ñ Ð°ÐºÐ°Ð»Ñ–Ñ‡Ð½Ð°Ñці." msgid "Selected Description" msgstr "ÐпіÑанне" msgid "The description of the currently selected map." msgstr "ÐпіÑанне абранай мапы." msgid "Jump" msgstr "" msgid "Hero Speed" msgstr "" msgid "Don't Show" msgstr "" msgid "Enemy Speed" msgstr "" msgid "Auto Resolve" msgstr "" msgid "Auto, No Spells" msgstr "" msgid "Battles" msgstr "" msgid "combatMode|Manual" msgstr "" msgid "Change the speed at which your heroes move on the main screen." msgstr "" msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" #, fuzzy msgid "Change the interface settings of the game." msgstr "Ðаладзіць графіку." #, fuzzy msgid "Interface Settings" msgstr "Ðалады гульні" msgid "Toggle instant battle mode." msgstr "" msgid "Att." msgstr "" msgid "Def." msgstr "" msgid "Power" msgstr "" msgid "Knowl" msgstr "" msgid "1st" msgstr "" msgid "2nd" msgstr "" msgid "3rd" msgstr "" msgid "4th" msgstr "" msgid "5th" msgstr "" msgid "6th" msgstr "" msgid "Oracle: Player Rankings" msgstr "" msgid "Thieves' Guild: Player Rankings" msgstr "" msgid "Number of Towns:" msgstr "" msgid "Number of Castles:" msgstr "" msgid "Number of Heroes:" msgstr "" msgid "Gold in Treasury:" msgstr "" msgid "Wood & Ore:" msgstr "" msgid "Gems, Cr, Slf & Mer:" msgstr "" msgid "Obelisks Found:" msgstr "" msgid "Artifacts:" msgstr "" msgid "Total Army Strength:" msgstr "" msgid "Income:" msgstr "" msgid "Best Hero:" msgstr "" msgid "Best Hero Stats:" msgstr "" msgid "Personality:" msgstr "" msgid "Best Monster:" msgstr "" msgid "Random Castle Name" msgstr "" msgid "Random Town Name" msgstr "" #, fuzzy msgid "Allow Castle build" msgstr "Воблачны замак" #, fuzzy msgid "Default Buildings" msgstr "Хобіты" msgid "Default Army" msgstr "" #, fuzzy msgid "Castle Army" msgstr "Замак" #, fuzzy msgid "Town Army" msgstr "Горад" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Пакінуць замак" msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" msgid "Message Text:" msgstr "" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" msgid "Message:" msgstr "" #, fuzzy msgid "Click to save the Event properties." msgstr "Ðазва абранай мапы." msgid "No resources will be given as a reward." msgstr "" msgid "Resources" msgstr "" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Ðазва абранай мапы." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Дзень: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Ðазва абранай мапы." msgid "Add Event" msgstr "" msgid "Add an additional event." msgstr "" msgid "Edit Event" msgstr "" msgid "Edit an existing event." msgstr "" msgid "Delete Event" msgstr "" msgid "Delete an existing event." msgstr "" #, fuzzy msgid "Effects:" msgstr "Эфекты" #, fuzzy msgid "Conditions:" msgstr "Умова паразы" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" msgid "Set Experience value" msgstr "" msgid "Artifact" msgstr "" msgid "No artifact will be given by the event." msgstr "" msgid "Delete Artifact" msgstr "" msgid "Delete an artifact from the event." msgstr "" msgid "No Secondary Skill will be given by the event." msgstr "" msgid "Secondary Skill" msgstr "" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" msgid "%{objects} cannot be placed on water." msgstr "" msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" msgid "%{objects} must be placed on water." msgstr "" msgid "Objects cannot be placed outside the map." msgstr "" msgid "Action objects must be placed on clear tiles." msgstr "" msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" msgid "Editor" msgstr "" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "ÐÐÐОВÐ" msgid "Main Menu" msgstr "" msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Ð’ÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹" msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" msgid "Create a new map from scratch." msgstr "" #, fuzzy msgid "New Map" msgstr "ÐÐ¾Ð²Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" #, fuzzy msgid "Load Map" msgstr "Загрузіць гульню" msgid "Load an existing map." msgstr "" #, fuzzy msgid "Save Map" msgstr "Ð’ÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹" #, fuzzy msgid "Save the current map." msgstr "Ðазва абранай мапы." msgid "Quit out of the map editor." msgstr "" #, fuzzy msgid "Return to the game's Main Menu." msgstr "ПÑтрыкні, каб вÑрнуцца Ñž галоўнае меню." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" msgid "Set Random Ultimate Artifact Radius" msgstr "" msgid "%{object} has no properties to change." msgstr "" msgid "This artifact" msgstr "" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "" msgid "Streams" msgstr "" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "" msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" msgid "The map is corrupted." msgstr "" msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "" msgid "Unable to locate a directory to save the map." msgstr "" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Ð’Ñ‹ ўпÑўненыÑ, што хочаце выйÑці?" msgid "Map saved to: " msgstr "" msgid "Failed to save the map." msgstr "" msgid "Used to place %{object}." msgstr "" #, fuzzy msgid "Select object type" msgstr "Мова" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Калі лаÑка, выбÑрыце іншага героÑ." msgid "" "Cell\n" "Details" msgstr "" msgid "Erase" msgstr "" msgid "Mountains" msgstr "" msgid "Rocks" msgstr "" msgid "Trees" msgstr "" #, fuzzy msgid "Water Objects" msgstr "ВадзÑÐ½Ñ‹Ñ Ñлементалі" msgid "Miscellaneous" msgstr "" msgid "Artifacts" msgstr "" #, fuzzy msgid "Dwellings" msgstr "Хобіты" msgid "Mines" msgstr "" msgid "Power-ups" msgstr "" msgid "Treasures" msgstr "" msgid "Heroes" msgstr "" #, fuzzy msgid "Towns" msgstr "Горад" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Мова" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" #, fuzzy msgid "Small Brush" msgstr "ÐœÐ°Ð»Ñ‹Ñ Ð¼Ð°Ð¿Ñ‹" #, fuzzy msgid "Medium Brush" msgstr "СÑÑ€ÑÐ´Ð½Ñ–Ñ Ð¼Ð°Ð¿Ñ‹" #, fuzzy msgid "Large Brush" msgstr "Ð’ÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹" msgid "Area Fill" msgstr "" msgid "Used to click and drag for filling in large areas." msgstr "" msgid "Clear Area" msgstr "" msgid "Used to click and drag for clearing large areas." msgstr "" msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" msgid "Traversable only by boat." msgstr "" msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" #, fuzzy msgid "Used for special editing of action objects." msgstr "Знішчыць уÑÑ–Ñ… варожых героÑÑž Ñ– захапіць уÑе Ð²Ð°Ñ€Ð¾Ð¶Ñ‹Ñ Ð³Ð°Ñ€Ð°Ð´Ñ‹." msgid "Adventure Objects Mode" msgstr "" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" #, fuzzy msgid "Kingdom Objects Mode" msgstr "Прыбытак каралеўÑтва" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "МайÑтры мечнікі" msgid "Used to place monsters on the map." msgstr "" msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" msgid "Road Mode" msgstr "" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" msgid "Specifications" msgstr "" msgid "File Options" msgstr "" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" msgid "View the editor system options, which let you customize the editor." msgstr "" msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" #, fuzzy msgid "Cancel back to the New Map menu." msgstr "Ð’Ñрнуцца Ñž галоўнае меню." msgid "Cancel back to the main menu." msgstr "Ð’Ñрнуцца Ñž галоўнае меню." msgid "From Scratch" msgstr "" msgid "Start from scratch with a blank map." msgstr "" msgid "Create a randomly generated map." msgstr "" #, fuzzy msgid "Random" msgstr "" "Выпад-\n" "ковы" #, fuzzy msgid "Cancel back to the Map Editor main menu." msgstr "Ð’Ñрнуцца Ñž галоўнае меню." msgid "No maps available!" msgstr "" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{color} гулец" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race} %{name}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{color} гулец" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{color} гулец" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race} %{name}" msgid "[%{pos}]: %{name}, %{race} castle" msgstr "" msgid "None." msgstr "" #, fuzzy msgid "One side defeats another." msgstr "Калі лаÑка, выбÑрыце іншага героÑ." #, fuzzy msgid "Accumulate gold." msgstr "ÐазапаÑіць вÑлікую колькаÑць золата." msgid "Run out of time." msgstr "" msgid "alliance|1st" msgstr "" msgid "alliance|2nd" msgstr "" msgid "alliance|3rd" msgstr "" msgid "alliance|4th" msgstr "" msgid "alliance|5th" msgstr "" #, fuzzy msgid "Special Loss Condition" msgstr "Умова паразы" #, fuzzy msgid "Special Victory Condition" msgstr "Умова перамогі" #, fuzzy msgid "Allow standard victory conditions" msgstr "Умова перамогі" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr "ÐльÑÐ½Ñ Ð· ограмі" # msgid "{%number} alliance: " msgstr "" msgid "Gold:" msgstr "" msgid "Select a Town to capture to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Ðазва абранай мапы." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Ðазва абранай мапы." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Ðазва абранай мапы." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Ðазва абранай мапы." #, fuzzy msgid "Map Difficulty" msgstr "СкладанаÑць мапы:" #, fuzzy msgid "Map Description" msgstr "ÐпіÑанне" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "ÐпіÑанне" #, fuzzy msgid "Click to accept the changes made." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "Click to edit custom rumors." msgstr "Ðазва абранай мапы." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "ПÑтрыкні, каб ухваліць абранае раздзÑленне." msgid "Events" msgstr "" #, fuzzy msgid "Click to change the language of the map." msgstr "ЗмÑніць мову гульні." #, fuzzy msgid "Click to change your map name." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" #, fuzzy msgid "Map Name" msgstr "Тып мапы" #, fuzzy msgid "Click to change the description of the current map." msgstr "ÐпіÑанне абранай мапы." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "ÐпіÑанне абранай мапы." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "ÐпіÑанне абранай мапы." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Тып мапы" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "СкладанаÑць мапы вызначаецца ейным аўтарам. Болей ÑÐºÐ»Ð°Ð´Ð°Ð½Ñ‹Ñ Ð¼Ð°Ð¿Ñ‹ могуць " "утрымліваць больш ворагаў, менш Ñ€ÑÑурÑаў ці Ñ–Ð½ÑˆÑ‹Ñ Ð°Ð´Ð¼Ñ‹ÑÐ»Ð¾Ð²Ñ‹Ñ Ð°ÐºÐ°Ð»Ñ–Ñ‡Ð½Ð°Ñці." msgid "editor|%{count} %{resource}" msgstr "" #, fuzzy msgid "Animation" msgstr "ÐнекÑÑ–Ñ" msgid "Passability" msgstr "" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Ðазва абранай мапы." msgid "Add Rumor" msgstr "" msgid "Add an additional rumor." msgstr "" msgid "Edit Rumor" msgstr "" msgid "Edit an existing rumor." msgstr "" msgid "Delete Rumor" msgstr "" msgid "Delete an existing rumor." msgstr "" msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "ÐпіÑанне" #, fuzzy msgid "Save Map:" msgstr "Ð’ÑÐ»Ñ–ÐºÑ–Ñ Ð¼Ð°Ð¿Ñ‹" #, fuzzy msgid "Click to save the current map." msgstr "Ðазва абранай мапы." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Ðазва абранай мапы." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Лёгка" msgid "difficulty|Normal" msgstr "Звычайна" msgid "difficulty|Hard" msgstr "ЦÑжка" msgid "difficulty|Expert" msgstr "ЭкÑперт" msgid "difficulty|Impossible" msgstr "Ðемагчыма" msgid "and more..." msgstr "" msgid "Easy" msgstr "" #, fuzzy msgid "Normal" msgstr "ЗвычайнаÑ" msgid "Hard" msgstr "ЦÑжкаÑ" msgid "Campaign Difficulty" msgstr "" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" msgid "Start the selected scenario." msgstr "" msgid "View Intro" msgstr "ПаглÑдзець уÑтуп" msgid "View the intro video for the current state of the campaign." msgstr "" msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" msgid "Restart the current scenario." msgstr "" #, fuzzy msgid "Difficulty" msgstr "СкладанаÑць" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" msgid "Are you sure you want to restart this scenario?" msgstr "" msgid "Campaign Scenario loading failure" msgstr "" msgid "Please make sure that campaign files are correct and present." msgstr "" msgid "Days spent" msgstr "" msgid "The number of days spent on this campaign." msgstr "" msgid "Project Coordination and Core Development" msgstr "" msgid "Development" msgstr "" msgid "Visit us at " msgstr "" msgid "QA and Support" msgstr "" msgid "Dev and Support" msgstr "" msgid "Special Thanks to" msgstr "" msgid "and many-many other contributors and supporters!" msgstr "" msgid "Support us at" msgstr "" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "" msgid "Original project before 0.7" msgstr "" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "" msgid "Designed and Directed" msgstr "" msgid "Programming and Design" msgstr "" msgid "Executive Producer" msgstr "" msgid "Producer" msgstr "" msgid "Additional Design" msgstr "" msgid "Additional Programming" msgstr "" msgid "Musical Production" msgstr "" msgid "Music and Sound Design" msgstr "" msgid "Vocalists" msgstr "" msgid "Art Director" msgstr "" msgid "Assistant Art Director" msgstr "" msgid "Artists" msgstr "" msgid "QA Manager" msgstr "" msgid "QA" msgstr "" msgid "Writing" msgstr "" msgid "Manual and Helpfile" msgstr "" msgid "Scenarios" msgstr "" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "" msgid "Design Lead" msgstr "" msgid "Designers" msgstr "" msgid "Programming Lead" msgstr "" msgid "Art Lead" msgstr "" msgid "Playtesters" msgstr "" msgid "Designer" msgstr "" msgid "Producers" msgstr "" #, fuzzy msgid "QA Managers" msgstr "Стралкі" msgid "Sound Design" msgstr "" msgid "Town Themes" msgstr "" msgid "Alto Sax" msgstr "" msgid "Harpsichord and Piano" msgstr "" msgid "Basso Vocal" msgstr "" msgid "Soprano Vocal" msgstr "" msgid "Recorded at %{recordingStudio}" msgstr "" msgid "credits|Manual" msgstr "" msgid "German Consultant" msgstr "" msgid "Map Designers" msgstr "" msgid "Package Design" msgstr "" msgid "High Scores" msgstr "ÐÐ°Ð¹Ð»ÐµÐ¿ÑˆÑ‹Ñ Ð´Ð°ÑÑгненні" msgid "Your Name" msgstr "Вашае імÑ" msgid "Unknown Hero" msgstr "" msgid "Standard" msgstr "" msgid "View High Scores for Standard Maps." msgstr "" msgid "Campaign" msgstr "КампаніÑ" msgid "View High Scores for Campaigns." msgstr "" msgid "hotkey|default okay event" msgstr "" msgid "hotkey|default cancel event" msgstr "" msgid "hotkey|default left" msgstr "" msgid "hotkey|default right" msgstr "" msgid "hotkey|default up" msgstr "" msgid "hotkey|default down" msgstr "" msgid "hotkey|toggle fullscreen" msgstr "" msgid "hotkey|toggle text support mode" msgstr "" msgid "hotkey|toggle developer mode" msgstr "" msgid "hotkey|new game" msgstr "" msgid "hotkey|load game" msgstr "" #, fuzzy msgid "hotkey|high scores" msgstr "ÐÐ°Ð¹Ð»ÐµÐ¿ÑˆÑ‹Ñ Ð´Ð°ÑÑгненні" msgid "hotkey|credits" msgstr "" #, fuzzy msgid "hotkey|standard game" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" #, fuzzy msgid "hotkey|campaign game" msgstr "КампаніÑ" #, fuzzy msgid "hotkey|multi-player game" msgstr "ШматаÑÐ°Ð±Ð¾Ð²Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" #, fuzzy msgid "hotkey|settings" msgstr "Ðалады" msgid "hotkey|quit" msgstr "" msgid "hotkey|select map" msgstr "" msgid "hotkey|select small map size" msgstr "" msgid "hotkey|select medium map size" msgstr "" msgid "hotkey|select large map size" msgstr "" msgid "hotkey|select extra large map size" msgstr "" msgid "hotkey|select all map sizes" msgstr "" #, fuzzy msgid "hotkey|hot seat game" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "hotkey|battle only game" msgstr "" msgid "hotkey|choose the original campaign" msgstr "" msgid "hotkey|choose the expansion campaign" msgstr "" #, fuzzy msgid "hotkey|map editor main menu" msgstr "КампаніÑ" #, fuzzy msgid "hotkey|new map menu" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" #, fuzzy msgid "hotkey|load map menu" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "hotkey|new map from scratch" msgstr "" #, fuzzy msgid "hotkey|new random map" msgstr "Зводка аб каралеўÑтве" #, fuzzy msgid "hotkey|undo last action" msgstr "Ðаладкі замка" #, fuzzy msgid "hotkey|redo last action" msgstr "Ðаладкі замка" #, fuzzy msgid "hotkey|open game main menu" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "hotkey|toggle passability" msgstr "" msgid "hotkey|roland campaign" msgstr "" msgid "hotkey|archibald campaign" msgstr "" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "Кошт вернаÑці" msgid "hotkey|voyage home campaign" msgstr "" msgid "hotkey|wizard's isle campaign" msgstr "" msgid "hotkey|descendants campaign" msgstr "" msgid "hotkey|select first campaign bonus" msgstr "" msgid "hotkey|select second campaign bonus" msgstr "" msgid "hotkey|select third campaign bonus" msgstr "" msgid "hotkey|view campaign intro" msgstr "" #, fuzzy msgid "hotkey|select campaign difficulty" msgstr "СкладанаÑць мапы" msgid "hotkey|restart campaign scenario" msgstr "" msgid "hotkey|world map left" msgstr "" msgid "hotkey|world map right" msgstr "" msgid "hotkey|world map up" msgstr "" msgid "hotkey|world map down" msgstr "" msgid "hotkey|world map up left" msgstr "" msgid "hotkey|world map up right" msgstr "" msgid "hotkey|world map down left" msgstr "" msgid "hotkey|world map down right" msgstr "" msgid "hotkey|save game" msgstr "" msgid "hotkey|next hero" msgstr "" msgid "hotkey|change to hero under cursor" msgstr "" #, fuzzy msgid "hotkey|start hero movement" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "hotkey|cast adventure spell" msgstr "" msgid "hotkey|put hero to sleep" msgstr "" msgid "hotkey|next town" msgstr "" msgid "hotkey|end turn" msgstr "" #, fuzzy msgid "hotkey|file options" msgstr "Ðаладкі замка" msgid "hotkey|adventure options" msgstr "" msgid "hotkey|puzzle map" msgstr "" msgid "hotkey|scenario information" msgstr "" msgid "hotkey|dig for artifact" msgstr "" msgid "hotkey|view world" msgstr "" #, fuzzy msgid "hotkey|kingdom summary" msgstr "Зводка аб каралеўÑтве" msgid "hotkey|default action" msgstr "" msgid "hotkey|open focus" msgstr "" msgid "hotkey|system options" msgstr "" msgid "hotkey|scroll left" msgstr "" msgid "hotkey|scroll right" msgstr "" msgid "hotkey|scroll up" msgstr "" msgid "hotkey|scroll down" msgstr "" msgid "hotkey|toggle control panel" msgstr "" msgid "hotkey|toggle radar" msgstr "" msgid "hotkey|toggle buttons" msgstr "" msgid "hotkey|toggle status" msgstr "" msgid "hotkey|toggle icons" msgstr "" msgid "hotkey|transfer control to ai" msgstr "" msgid "hotkey|retreat from battle" msgstr "" msgid "hotkey|surrender during battle" msgstr "" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "hotkey|quick combat" msgstr "" #, fuzzy msgid "hotkey|battle options" msgstr "Ðаладкі замка" msgid "hotkey|skip turn in battle" msgstr "" msgid "hotkey|cast battle spell" msgstr "" msgid "hotkey|dwelling level 1" msgstr "" msgid "hotkey|dwelling level 2" msgstr "" msgid "hotkey|dwelling level 3" msgstr "" msgid "hotkey|dwelling level 4" msgstr "" msgid "hotkey|dwelling level 5" msgstr "" msgid "hotkey|dwelling level 6" msgstr "" msgid "hotkey|well" msgstr "" #, fuzzy msgid "hotkey|marketplace" msgstr "Рынак" msgid "hotkey|mage guild" msgstr "" #, fuzzy msgid "hotkey|shipyard" msgstr "Верф" #, fuzzy msgid "hotkey|thieves guild" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ‹Ñ Ð²Ð°Ñ€Ð¾Ñž" msgid "hotkey|tavern" msgstr "" msgid "hotkey|construction screen" msgstr "" msgid "hotkey|buy all monsters in well" msgstr "" msgid "hotkey|split stack by half" msgstr "" msgid "hotkey|split stack by one" msgstr "" msgid "hotkey|join stacks" msgstr "" msgid "hotkey|upgrade troop" msgstr "" msgid "hotkey|dismiss hero or troop" msgstr "" msgid "hotkey|exchange all troops" msgstr "" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" msgid "Default Actions" msgstr "" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Мапа Ñвету" #, fuzzy msgid "Battle Screen" msgstr "Экран героÑ" #, fuzzy msgid "Town Screen" msgstr "Экран героÑ" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "" msgid "Unsupported save format: " msgstr "" msgid "Current game version: " msgstr "" msgid "Last supported version: " msgstr "" msgid "This file contains a save with an invalid game type." msgstr "" msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" msgid "This saved game is localized to '" msgstr "" msgid "' language, but the current language of the game is '" msgstr "" msgid "No save files to load." msgstr "" msgid "Hot Seat" msgstr "За адным кампутарам" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "ГулÑй за адным кампутарам з адной-пÑццю іншымі аÑобамі, перадаючы кіраванне " "па чарзе." msgid "A single player game playing out a single map." msgstr "Ð“ÑƒÐ»ÑŒÐ½Ñ Ð´Ð»Ñ Ð°Ð´Ð½Ð¾Ð¹ аÑобы на адной мапе." msgid "Standard Game" msgstr "Ð—Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "A single player game playing through a series of maps." msgstr "Ð“ÑƒÐ»ÑŒÐ½Ñ Ð´Ð»Ñ Ð°Ð´Ð½Ð¾Ð¹ аÑобы на ланцугу мапаў." msgid "Campaign Game" msgstr "КампаніÑ" msgid "Multi-Player Game" msgstr "ШматаÑÐ°Ð±Ð¾Ð²Ð°Ñ Ð³ÑƒÐ»ÑŒÐ½Ñ" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "СупрацьÑтаÑнне некалькіх аÑобаў на адной мапе." msgid "fheroes2 Resurrection Team presents" msgstr "fheroes2 Resurrection Team прадÑтаўлÑе" #, fuzzy msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "ВыйÑці з Heroes of Might and Magic II." msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "ВыйÑці з Heroes of Might and Magic II." msgid "Greetings!" msgstr "" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "ВыйÑці з Heroes of Might and Magic II." msgid "Credits" msgstr "ЗвеÑткі пра каманду" msgid "View the credits screen." msgstr "ПраглÑдзець звеÑткі пра раÑпрацоўшчыкаў." msgid "View the high scores screen." msgstr "ПраглÑдзець Ð½Ð°Ð¹Ð»ÐµÐ¿ÑˆÑ‹Ñ Ð´Ð°ÑÑгненні." msgid "Create new or modify existing maps." msgstr "" msgid "Change language, resolution and settings of the game." msgstr "ЗмÑніць мову, раздзÑленне Ñкрана Ñ– налады гульні." msgid "Game Settings" msgstr "Ðалады гульні" #, fuzzy msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Бракуе відÑÑ Ñ„Ð°Ð¹Ð»Ð°Ñž Ð´Ð»Ñ Ð°Ð±Ñ€Ð°Ð½Ð°Ð¹ кампаніі. Праверце, ці ÑžÑе Ð½ÐµÐ°Ð±Ñ…Ð¾Ð´Ð½Ñ‹Ñ Ñ„Ð°Ð¹Ð»Ñ‹ " "былі ÑкапіÑваны." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" msgid "Original Campaign" msgstr "ÐÑноўны ÑцÑнар" msgid "Expansion Campaign" msgstr "Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ ÑцÑнары" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" msgid "Loading video. Please wait..." msgstr "" msgid "Host" msgstr "" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" msgid "Guest" msgstr "" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" #, fuzzy msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "СупрацьÑтаÑнне некалькіх аÑобаў на адной мапе." msgid "Battle Only" msgstr "ÐÑобны бой" msgid "Setup and play a battle without loading any map." msgstr "Ðаладзь Ñ– згулÑй бітву, не загружаючы мапу." #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "ГулÑй за адным кампутарам з адной-пÑццю іншымі аÑобамі, перадаючы кіраванне " "па чарзе." msgid "2 Players" msgstr "2 гульцы" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "Ð“ÑƒÐ»ÑŒÐ½Ñ Ð´Ð»Ñ 2-x аÑобаў Ñ–, па жаданні, да 4-Ñ… кампутарных гульцоў." msgid "3 Players" msgstr "3 Гульцы" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "Ð“ÑƒÐ»ÑŒÐ½Ñ Ð´Ð»Ñ 3-Ñ… аÑобаў Ñ–, па жаданні, да 3-x кампутарных гульцоў." msgid "4 Players" msgstr "4 Гульцы" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "Ð“ÑƒÐ»ÑŒÐ½Ñ Ð´Ð»Ñ 4-Ñ… аÑобаў Ñ–, па жаданні, да 2-x кампутарных гульцоў." msgid "5 Players" msgstr "5 Гульцоў" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "Ð“ÑƒÐ»ÑŒÐ½Ñ Ð´Ð»Ñ 5-ці аÑобаў Ñ–, па жаданні, аднаго камутарнага гульца." msgid "6 Players" msgstr "6 Гульцоў" msgid "Play with 6 human players." msgstr "Ð“ÑƒÐ»ÑŒÐ½Ñ Ð´Ð»Ñ 6-ці аÑобаў." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" msgid "Ultimate Artifact" msgstr "" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" msgid "Victory!" msgstr "" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" msgid "You have been eliminated from the game!!!" msgstr "" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" msgid "Defeat!" msgstr "" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" msgid "Your side defeats the opposing side." msgstr "Ваш бок перамагае Ñупрацьлеглы." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Capture the castle '%{name}'." msgstr "" msgid "Capture the town '%{name}'." msgstr "" msgid "Defeat the hero '%{name}'." msgstr "" msgid "Find the ultimate artifact." msgstr "" msgid "Find the '%{name}' artifact." msgstr "" msgid "Accumulate %{count} gold." msgstr "" msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" msgid "Lose the castle '%{name}'." msgstr "" msgid "Lose the town '%{name}'." msgstr "" msgid "Lose the hero: %{name}." msgstr "" msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" msgid "%{color} player has been vanquished!" msgstr "" msgid "Major Event!" msgstr "" msgid "Scenario:" msgstr "СцÑнар:" msgid "Game Difficulty:" msgstr "СкладанаÑць:" msgid "Opponents:" msgstr "Супраціўнікі:" msgid "Class:" msgstr "КлаÑ:" msgid "Rating %{rating}%" msgstr "РÑйтынг %{rating}%" msgid "Click here to select which scenario to play." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" msgid "Scenario" msgstr "СцÑнар" msgid "Game Difficulty" msgstr "СкладанаÑць" #, fuzzy msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "ДазвалÑе змÑніць пачаткувую ÑкладанаÑць гульні. З падвышÑннем узроўню " "ÑкладанаÑці вы пачнеце гульню з меншай колькаÑцю Ñ€ÑÑурÑаў, а ÐºÐ°Ð¼Ð¿ÑƒÑ‚Ð°Ñ€Ð½Ñ‹Ñ " "гульцы атрымаюць Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ Ñ€ÑÑурÑÑ‹." msgid "Difficulty Rating" msgstr "РÑйтынг ÑкладанаÑці" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "РÑйтынг ÑкладанаÑці улічваецца Ñž фінальнай адзнаке." msgid "Click to accept these settings and start a new game." msgstr "ПÑтрыкні, каб ухваліць налады Ñ– пачаць новую гульню." msgid "Click to return to the main menu." msgstr "ПÑтрыкні, каб вÑрнуцца Ñž галоўнае меню." msgid "Astrologers proclaim the Month of the %{name}." msgstr "" msgid "Astrologers proclaim the Week of the %{name}." msgstr "" msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "%{monster} growth +%{count}." msgstr "" msgid " All populations are halved." msgstr "" msgid " All dwellings increase population." msgstr "" msgid "New Month!" msgstr "" msgid "New Week!" msgstr "" msgid "Beware!" msgstr "" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" msgid "%{color} player's turn." msgstr "" msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" msgid "Lord Kilburn" msgstr "" msgid "Tsabu" msgstr "" msgid "Sir Galant" msgstr "" msgid "Thundax" msgstr "" msgid "Lord Haart" msgstr "" msgid "Ariel" msgstr "" msgid "Rebecca" msgstr "" msgid "Sandro" msgstr "" msgid "Crodo" msgstr "" msgid "Barock" msgstr "" msgid "Antoine" msgstr "" msgid "Astra" msgstr "" msgid "Agar" msgstr "" msgid "Vatawna" msgstr "" msgid "Vesper" msgstr "" msgid "Ambrose" msgstr "" msgid "Troyan" msgstr "" msgid "Jojosh" msgstr "" msgid "Wrathmont" msgstr "" msgid "Maximus" msgstr "" msgid "Next Hero" msgstr "" msgid "Select the next Hero." msgstr "" #, fuzzy msgid "Hero Movement" msgstr "Экран героÑ" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "Зводка аб каралеўÑтве" #, fuzzy msgid "View a summary of your Kingdom." msgstr "ПраглÑдзець зводку аб каралеўÑтве." msgid "Cast an adventure spell." msgstr "" msgid "End Turn" msgstr "" msgid "End your turn and let the computer take its turn." msgstr "" msgid "Adventure Options" msgstr "" msgid "Bring up the adventure options menu." msgstr "" msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" msgid "Are you sure you want to quit?" msgstr "Ð’Ñ‹ ўпÑўненыÑ, што хочаце выйÑці?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" msgid "Are you sure you want to overwrite the save with this name?" msgstr "" msgid "Game saved successfully." msgstr "" msgid "There was an issue during saving." msgstr "" msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" msgid "Try looking on land!!!" msgstr "" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" msgid "Congratulations!" msgstr "" msgid "Nothing here. Where could it be?" msgstr "" msgid "Try searching on clear ground." msgstr "" msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" msgid "Month: %{month} Week: %{week}" msgstr "МеÑÑц: %{month} Тыдзень: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" msgid "Status Window" msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "ДазвалÑе змÑніць пачатковую пазіцыю Ñ– колеры гульцоў. Ðд абранага колеру " "залежыць Ð¿Ð°Ñ‡Ð°Ñ‚ÐºÐ¾Ð²Ð°Ñ Ð»Ð°ÐºÐ°Ñ†Ñ‹Ñ. За Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð¿Ð°Ð·Ñ–Ñ†Ñ‹Ñ– могуць гулÑць толькі " "аÑобы, альбо толькі ÐºÐ°Ð¼Ð¿ÑƒÑ‚Ð°Ñ€Ð½Ñ‹Ñ Ð³ÑƒÐ»ÑŒÑ†Ñ‹." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "ДазвалÑе змÑніць ÐºÐ»Ð°Ñ Ð³ÑƒÐ»ÑŒÑ†Ð°, але Ð½Ñ ÐºÐ¾Ð¶Ð½Ñ‹ ÑцÑнар дазвалÑе змену.У " "залежнаÑці ад ÑцÑнара гулец можа атрымаць Ð´Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ñ‹Ñ Ð³Ð°Ñ€Ð°Ð´Ñ‹ Ñ–/альбо героÑÑž з " "клаÑам, Ñкі не адпавÑдае аÑноўнаму." msgid "Handicap" msgstr "Перашкода" # #, fuzzy msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "ДазвалÑе перашкодзіць аÑобе, ÑÐºÐ°Ñ Ð¿Ñ€Ð°Ð· гÑта пачне гульню з меншай колькаÑцю " "Ñ€ÑÑурÑаў Ñ– будзе атрымліваць на 15 альбо 30% менш Ñ€ÑÑурÑаў за ход з лёгкай Ñ– " "Ñур’ёзнай Ñтупеню перашкоды адпаведна." msgid "%{color} player" msgstr "%{color} гулец" msgid "No Handicap" msgstr "" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" msgid "Mild Handicap" msgstr "" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" msgid "Severe Handicap" msgstr "" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Даведацца пра %{skill}" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Даведацца пра %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Ðбарона" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Прыбытак каралеўÑтва" msgid "Kingdom Income per day." msgstr "Прыбытак каралеўÑтва штодзень." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "БеларуÑкаÑ" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" #, fuzzy msgid "Vietnamese" msgstr "ПраглÑдзець %{name}" msgid "Slow" msgstr "" msgid "Fast" msgstr "" #, fuzzy msgid "Very Fast" msgstr "ШпаркаÑ" msgid "Evil" msgstr "" msgid "Good" msgstr "" msgid ", FPS: " msgstr "" msgid "shipAndGraveyard|%{object} robber" msgstr "" msgid "pyramid|%{object} raided" msgstr "" msgid "Ector" msgstr "" msgid "Gwenneth" msgstr "" msgid "Sir Gallant" msgstr "" msgid "Tyro" msgstr "" msgid "Dimitry" msgstr "" msgid "Ruby" msgstr "" msgid "Crag Hack" msgstr "" msgid "Fineous" msgstr "" msgid "Jezebel" msgstr "" msgid "Atlas" msgstr "" msgid "Ergon" msgstr "" msgid "Jaclyn" msgstr "" msgid "Gem" msgstr "" msgid "Natasha" msgstr "" msgid "Carlawn" msgstr "" msgid "Luna" msgstr "" msgid "Arie" msgstr "" msgid "Barok" msgstr "" msgid "Kastore" msgstr "" msgid "Falagar" msgstr "" msgid "Dawn" msgstr "" msgid "Flint" msgstr "" msgid "Halon" msgstr "" msgid "Myra" msgstr "" msgid "Myrini" msgstr "" msgid "Wilfrey" msgstr "" msgid "Mandigal" msgstr "" msgid "Sarakin" msgstr "" msgid "Charity" msgstr "" msgid "Darlana" msgstr "" msgid "Ranloo" msgstr "" msgid "Rialdo" msgstr "" msgid "Zam" msgstr "" msgid "Zom" msgstr "" msgid "Celia" msgstr "" msgid "Roxana" msgstr "" msgid "Lord Corlagon" msgstr "" msgid "Lord Halton" msgstr "" msgid "Sister Eliza" msgstr "" msgid "Brother Brax" msgstr "" msgid "Dainwin" msgstr "" msgid "Joseph" msgstr "" msgid "Mog" msgstr "" msgid "Solmyr" msgstr "" msgid "Ceallach" msgstr "" msgid "Drakonia" msgstr "" msgid "Elderian" msgstr "" msgid "Gallavant" msgstr "" msgid "Jarkonas" msgstr "" msgid "Martine" msgstr "" msgid " gives you maximum morale" msgstr "" msgid " gives you maximum luck" msgstr "" msgid "You cannot have multiple spell books." msgstr "" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" msgid "Do you wish to buy one?" msgstr "" msgid "%{count} / day" msgstr "" msgid "one" msgstr "" msgid "two" msgstr "" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" msgid "You come upon the remains of an unfortunate adventurer." msgstr "" msgid "Treasure" msgstr "" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" msgid "Searching through the tattered clothing, you find nothing." msgstr "" msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" msgid "Searching inside, you find the %{artifact}." msgstr "" msgid "Inside, you find some of the wagon's cargo still intact." msgstr "" msgid "You search through the flotsam, and find some wood and some gold." msgstr "" msgid "You search through the flotsam, and find some wood." msgstr "" msgid "You search through the flotsam, but find nothing." msgstr "" msgid "Shrine of the 1st Circle" msgstr "" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 2nd Circle" msgstr "" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 3rd Circle" msgstr "" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" msgid "You drink from the enchanted fountain, but nothing happens." msgstr "" msgid "You enter the faerie ring, but nothing happens." msgstr "" msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" msgid "A second drink at the well in one day will not help you." msgstr "" msgid "A drink from the well has restored your spell points to maximum." msgstr "" msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" msgid "Do you wish to buy this artifact?" msgstr "" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" msgid "You've found the artifact: " msgstr "" msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" msgid "Victorious, you take your prize, the %{art}." msgstr "" msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" msgid "You gain control of a %{name}." msgstr "" msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "" msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" msgid "No Fire Elementals approach you from the lava pool." msgstr "" msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" msgid "A face forms in the water for a moment, and then is gone." msgstr "" msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" msgid "This burial site is deathly still." msgstr "" msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" msgid "From the observation tower, you are able to see distant lands." msgstr "" msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" msgid " and " msgstr "" msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "" msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" msgid "You have already been to this obelisk." msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "" msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" msgid "(Just bury it around my roots.)" msgstr "" msgid "Tears brim in the eyes of the tree." msgstr "" msgid "\"I need %{count} %{res}.\"" msgstr "" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" msgid "The Arena guards turn you away." msgstr "" msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" msgid "This eye seems to be intently studying its surroundings." msgstr "" msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" #, fuzzy msgid "No spell book is present." msgstr "ÐÑма загавораў." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" msgid "The spell was not found." msgstr "" msgid "Only heroes can cast this spell." msgstr "" msgid "This hero is not able to cast adventure spells." msgstr "" msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" msgid "This spell cannot be cast on a boat." msgstr "" msgid "This spell can only be cast near an ocean." msgstr "" msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" msgid "There are no boats available for this spell." msgstr "" msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" msgid "This hero is already in a town, so this spell will have no effect." msgstr "" msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" msgid "This spell is already in effect." msgstr "" msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" msgid "%{name} the %{race} (Level %{level})" msgstr "" msgid "Random hero (Level %{level})" msgstr "" msgid "Random %{race} hero (Level %{level})" msgstr "" #, fuzzy msgid "Hero race:" msgstr "Экран героÑ" msgid "Are you sure you want to dismiss this Hero?" msgstr "" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Ðдзінкі магіі" msgid "View Spell Points Info" msgstr "" msgid "Set patrol radius in tiles" msgstr "" msgid "Enter hero's name" msgstr "" #, fuzzy msgid "Click to change race." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" msgid "Exit Hero Screen" msgstr "" msgid "You cannot dismiss a hero in a castle" msgstr "" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "" msgid "Dismiss %{name} the %{race}" msgstr "" msgid "Show previous hero" msgstr "" msgid "Show next hero" msgstr "" msgid "Set army combat formation to 'Spread'" msgstr "" msgid "Set army combat formation to 'Grouped'" msgstr "" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "ПÑтрыкніце Ñюды, каб выбраць ÑцÑнар" msgid "Blood Morale" msgstr "" msgid "%{morale} Morale" msgstr "" msgid "%{luck} Luck" msgstr "" msgid "Current Luck Modifiers:" msgstr "" msgid "Current Morale Modifiers:" msgstr "" msgid "Entire army is undead, so morale does not apply." msgstr "" msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" msgid "%{name1} meets %{name2}" msgstr "" msgid "Enemy heroes are now fully identifiable." msgstr "" msgid "Identify Hero" msgstr "" msgid "Select town to port to." msgstr "" msgid "Town Portal" msgstr "" msgid "The creatures are willing to join us!" msgstr "" msgid "All the creatures will join us..." msgstr "" msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "\n" " for a fee of %{gold} gold." msgstr "" msgid "These weak creatures will surely flee before us." msgstr "" msgid "I fear these creatures are in the mood for a fight." msgstr "" msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" msgid "The hero's spell power determines the duration or power of a spell." msgstr "" msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" msgid "Current Modifiers:" msgstr "" msgid "skill|Basic" msgstr "" msgid "skill|Advanced" msgstr "" msgid "skill|Expert" msgstr "" msgid "Pathfinding" msgstr "" msgid "Archery" msgstr "" msgid "Logistics" msgstr "" msgid "Scouting" msgstr "" msgid "Diplomacy" msgstr "" msgid "Navigation" msgstr "" msgid "Leadership" msgstr "" msgid "Wisdom" msgstr "" msgid "Mysticism" msgstr "" msgid "Ballistics" msgstr "" msgid "Eagle Eye" msgstr "" msgid "Necromancy" msgstr "" msgid "Estates" msgstr "" msgid "Advanced Archery" msgstr "" msgid "Advanced Pathfinding" msgstr "" msgid "Basic Archery" msgstr "" msgid "Basic Pathfinding" msgstr "" msgid "Expert Pathfinding" msgstr "" msgid "Advanced Logistics" msgstr "" msgid "Basic Logistics" msgstr "" msgid "Basic Scouting" msgstr "" msgid "Expert Archery" msgstr "" msgid "Expert Logistics" msgstr "" msgid "Advanced Diplomacy" msgstr "" msgid "Advanced Scouting" msgstr "" msgid "Basic Diplomacy" msgstr "" msgid "Expert Diplomacy" msgstr "" msgid "Expert Scouting" msgstr "" msgid "Advanced Leadership" msgstr "" msgid "Advanced Navigation" msgstr "" msgid "Basic Leadership" msgstr "" msgid "Basic Navigation" msgstr "" msgid "Expert Navigation" msgstr "" msgid "Advanced Wisdom" msgstr "" msgid "Basic Mysticism" msgstr "" msgid "Basic Wisdom" msgstr "" msgid "Expert Leadership" msgstr "" msgid "Expert Wisdom" msgstr "" msgid "Advanced Luck" msgstr "" msgid "Advanced Mysticism" msgstr "" msgid "Basic Luck" msgstr "" msgid "Expert Luck" msgstr "" msgid "Expert Mysticism" msgstr "" msgid "Advanced Ballistics" msgstr "" msgid "Advanced Eagle Eye" msgstr "" msgid "Basic Ballistics" msgstr "" msgid "Basic Eagle Eye" msgstr "" msgid "Expert Ballistics" msgstr "" msgid "Advanced Necromancy" msgstr "" msgid "Basic Estates" msgstr "" msgid "Basic Necromancy" msgstr "" msgid "Expert Eagle Eye" msgstr "" msgid "Expert Necromancy" msgstr "" msgid "Advanced Estates" msgstr "" msgid "Expert Estates" msgstr "" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "" msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" msgid "All of the creatures may offer to join the hero." msgstr "" msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "%{skill} allows the hero to learn third level spells." msgstr "" msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" msgid "%{skill} allows the hero to learn fifth level spells." msgstr "" msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" msgstr[1] "" msgstr[2] "" #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" msgid "Blue" msgstr "Сіні" msgid "Green" msgstr "ЗÑлёны" msgid "Red" msgstr "Чырвоны" msgid "Yellow" msgstr "Жоўты" msgid "Orange" msgstr "Медны" msgid "Purple" msgstr "Пурпур" msgid "barrier|Aqua" msgstr "" msgid "barrier|Blue" msgstr "" msgid "barrier|Brown" msgstr "" msgid "barrier|Gold" msgstr "" msgid "barrier|Green" msgstr "" msgid "barrier|Orange" msgstr "" msgid "barrier|Purple" msgstr "" msgid "barrier|Red" msgstr "" msgid "tent|Aqua" msgstr "Блакітны" msgid "tent|Blue" msgstr "Сіні" msgid "tent|Brown" msgstr "Карычневы" msgid "tent|Gold" msgstr "Залаты" msgid "tent|Green" msgstr "ЗÑлёны" msgid "tent|Orange" msgstr "Ðранжавы" msgid "tent|Purple" msgstr "ФіÑлетавы" msgid "tent|Red" msgstr "Чырвоны" msgid "Experience" msgstr "" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" msgid "Hero/Stats" msgstr "" msgid "Skills" msgstr "" msgid "Town/Castle" msgstr "" msgid "Garrison" msgstr "" msgid "Gold Per Day:" msgstr "" msgid "View Heroes." msgstr "" msgid "Towns/Castles" msgstr "" msgid "View Towns and Castles." msgstr "" msgid "luck|Cursed" msgstr "ПраклÑтаÑ" msgid "luck|Awful" msgstr "ÐÑздольнаÑ" msgid "luck|Bad" msgstr "ДрÑннаÑ" msgid "luck|Normal" msgstr "ЗвычайнаÑ" msgid "luck|Good" msgstr "ДобраÑ" msgid "luck|Great" msgstr "ВыдатнаÑ" msgid "luck|Irish" msgstr "БагатаÑ" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" msgid "morale|Treason" msgstr "ЗдраднаÑ" msgid "morale|Awful" msgstr "ÐÑздольнаÑ" msgid "morale|Poor" msgstr "КепÑкаÑ" msgid "morale|Normal" msgstr "ЗвычайнаÑ" msgid "morale|Good" msgstr "ДобраÑ" msgid "morale|Great" msgstr "ВыдатнаÑ" msgid "morale|Blood!" msgstr "ЛютаÑ" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" msgid "Knight" msgstr "Рыцар" msgid "Barbarian" msgstr "Варвар" msgid "Sorceress" msgstr "Чараўніца" msgid "Warlock" msgstr "Ð’Ñдзьмак" msgid "Wizard" msgstr "Чарадзей" msgid "Necromancer" msgstr "Ðекрамант" msgid "Multi" msgstr "" msgid "doubleLined|Knight" msgstr "Рыцар" msgid "doubleLined|Barbarian" msgstr "Варвар" msgid "doubleLined|Sorceress" msgstr "" "Чараў-\n" "ніца" msgid "doubleLined|Warlock" msgstr "Ð’Ñдзьмак" msgid "doubleLined|Wizard" msgstr "Чарадзей" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Ðекра-\n" "мант" msgid "doubleLinedRace|Multi" msgstr "" msgid "doubleLinedRace|Random" msgstr "" "Выпад-\n" "ковы" msgid "speed|Standing" msgstr "Ðа меÑцы" msgid "speed|Crawling" msgstr "Ледзь поўзае" msgid "speed|Very Slow" msgstr "МаруднаÑ" msgid "speed|Slow" msgstr "ÐÑÑпешнаÑ" msgid "speed|Average" msgstr "ÐіштаватаÑ" msgid "speed|Fast" msgstr "ХуткаÑ" msgid "speed|Very Fast" msgstr "ШпаркаÑ" msgid "speed|Ultra Fast" msgstr "ІмкліваÑ" msgid "speed|Blazing" msgstr "ÐÑÑтрымнаÑ" msgid "speed|Instant" msgstr "ІмгненнаÑ" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "" msgid "week|Rabbit" msgstr "" msgid "week|Gopher" msgstr "" msgid "week|Badger" msgstr "" #, fuzzy msgid "week|Rat" msgstr "тыдзень" msgid "week|Eagle" msgstr "" msgid "week|Weasel" msgstr "" msgid "week|Raven" msgstr "" msgid "week|Mongoose" msgstr "" #, fuzzy msgid "week|Dog" msgstr "тыдзень" msgid "week|Aardvark" msgstr "" msgid "week|Lizard" msgstr "" msgid "week|Tortoise" msgstr "" msgid "week|Hedgehog" msgstr "" msgid "week|Condor" msgstr "" msgid "week|Ant" msgstr "" msgid "week|Grasshopper" msgstr "" msgid "week|Dragonfly" msgstr "" msgid "week|Spider" msgstr "" msgid "week|Butterfly" msgstr "" msgid "week|Bumblebee" msgstr "" msgid "week|Locust" msgstr "" msgid "week|Earthworm" msgstr "" msgid "week|Hornet" msgstr "" msgid "week|Beetle" msgstr "" msgid "week|PLAGUE" msgstr "" msgid "week|Unnamed" msgstr "" msgid "Desert" msgstr "" msgid "Snow" msgstr "" msgid "Wasteland" msgstr "" msgid "Beach" msgstr "" msgid "Lava" msgstr "" msgid "Dirt" msgstr "" msgid "Grass" msgstr "" msgid "Ocean" msgstr "" msgid "maps|Small" msgstr "" msgid "maps|Medium" msgstr "" msgid "maps|Large" msgstr "" msgid "maps|Extra Large" msgstr "" msgid "maps|Custom Size" msgstr "" msgid "Ore Mine" msgstr "" msgid "Sulfur Mine" msgstr "" msgid "Crystal Mine" msgstr "" msgid "Gems Mine" msgstr "" msgid "Gold Mine" msgstr "" msgid "Mine" msgstr "" msgid "Burma shave." msgstr "" msgid "Next sign 50 miles." msgstr "" msgid "See Rock City." msgstr "" msgid "This space for rent." msgstr "" msgid "No object" msgstr "" msgid "Alchemist Lab" msgstr "" msgid "Sign" msgstr "" msgid "Buoy" msgstr "" msgid "Skeleton" msgstr "Шкілет" msgid "Daemon Cave" msgstr "" msgid "Treasure Chest" msgstr "" msgid "Faerie Ring" msgstr "" msgid "Campfire" msgstr "" msgid "Fountain" msgstr "" msgid "Gazebo" msgstr "" msgid "Genie Lamp" msgstr "" msgid "Archer's House" msgstr "" msgid "Goblin Hut" msgstr "" msgid "Dwarf Cottage" msgstr "" msgid "Peasant Hut" msgstr "" msgid "Stables" msgstr "" msgid "Alchemist's Tower" msgstr "" msgid "Event" msgstr "" msgid "Dragon City" msgstr "" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Monster" msgstr "" msgid "Obelisk" msgstr "" msgid "Oasis" msgstr "" msgid "Resource" msgstr "" msgid "Sawmill" msgstr "" msgid "Oracle" msgstr "" msgid "Shrine of the First Circle" msgstr "" msgid "Shipwreck" msgstr "" msgid "Sea Chest" msgstr "" msgid "Desert Tent" msgstr "" msgid "Stone Liths" msgstr "" msgid "Wagon Camp" msgstr "" msgid "Hut of the Magi" msgstr "" msgid "Whirlpool" msgstr "" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Mermaid" msgstr "" msgid "Boat" msgstr "" msgid "Random Ultimate Artifact" msgstr "" msgid "Random Artifact" msgstr "" msgid "Random Resource" msgstr "" msgid "Random Monster" msgstr "" msgid "Random Town" msgstr "" msgid "Random Castle" msgstr "" msgid "Eye of the Magi" msgstr "" msgid "Random Monster - weak" msgstr "" msgid "Random Monster - medium" msgstr "" msgid "Random Monster - strong" msgstr "" msgid "Random Monster - very strong" msgstr "" #, fuzzy msgid "Hero" msgstr "Даведацца аб героі" msgid "Nothing Special" msgstr "" msgid "Mossy Rock" msgstr "" msgid "Watch Tower" msgstr "" msgid "Tree House" msgstr "" msgid "Tree City" msgstr "" msgid "Ruins" msgstr "" msgid "Fort" msgstr "" msgid "Abandoned Mine" msgstr "" msgid "Sirens" msgstr "" msgid "Standing Stones" msgstr "" msgid "Idol" msgstr "" msgid "Tree of Knowledge" msgstr "" msgid "Witch Doctor's Hut" msgstr "" msgid "Temple" msgstr "" msgid "Hill Fort" msgstr "" msgid "Halfling Hole" msgstr "" msgid "Mercenary Camp" msgstr "" msgid "Shrine of the Second Circle" msgstr "" msgid "Shrine of the Third Circle" msgstr "" msgid "City of the Dead" msgstr "" msgid "Sphinx" msgstr "" msgid "Wagon" msgstr "" msgid "Tar Pit" msgstr "" msgid "Artesian Spring" msgstr "" msgid "Troll Bridge" msgstr "" msgid "Watering Hole" msgstr "" msgid "Witch's Hut" msgstr "" msgid "Xanadu" msgstr "" msgid "Lean-To" msgstr "" msgid "Magellan's Maps" msgstr "" msgid "Flotsam" msgstr "" msgid "Derelict Ship" msgstr "" msgid "Shipwreck Survivor" msgstr "" msgid "Bottle" msgstr "" msgid "Magic Well" msgstr "" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Observation Tower" msgstr "" msgid "Freeman's Foundry" msgstr "" msgid "Reefs" msgstr "" msgid "Volcano" msgstr "" msgid "Flowers" msgstr "" msgid "Rock" msgstr "" msgid "Water Lake" msgstr "" msgid "Mandrake" msgstr "" msgid "Dead Tree" msgstr "" msgid "Stump" msgstr "" msgid "Crater" msgstr "" msgid "Cactus" msgstr "" msgid "Mound" msgstr "" msgid "Dune" msgstr "" msgid "Lava Pool" msgstr "" msgid "Shrub" msgstr "" msgid "Barrow Mounds" msgstr "" msgid "Random Artifact - Treasure" msgstr "" msgid "Random Artifact - Minor" msgstr "" msgid "Random Artifact - Major" msgstr "" msgid "Barrier" msgstr "" msgid "Traveller's Tent" msgstr "" msgid "Jail" msgstr "" msgid "Fire Summoning Altar" msgstr "" msgid "Air Summoning Altar" msgstr "" msgid "Earth Summoning Altar" msgstr "" msgid "Water Summoning Altar" msgstr "" msgid "Swampy Lake" msgstr "" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "" msgid "Unknown Monster" msgstr "" msgid "Peasant" msgstr "СелÑнін" msgid "Peasants" msgstr "СÑлÑне" msgid "Archer" msgstr "Лучнік" msgid "Archers" msgstr "Лучнікі" msgid "Ranger" msgstr "Стралок" msgid "Rangers" msgstr "Стралкі" msgid "Pikeman" msgstr "Кап'ёўшчык" msgid "Pikemen" msgstr "Кап'ёўшчыкі" msgid "Veteran Pikeman" msgstr "Бывалы кап'ёўшчык" msgid "Veteran Pikemen" msgstr "Ð‘Ñ‹Ð²Ð°Ð»Ñ‹Ñ ÐºÐ°Ð¿'ёўшчыкі" msgid "Swordsman" msgstr "Мечнік" msgid "Swordsmen" msgstr "Мечнікі" msgid "Master Swordsman" msgstr "МайÑтар мечнік" msgid "Master Swordsmen" msgstr "МайÑтры мечнікі" msgid "Cavalries" msgstr "Коннік" msgid "Cavalry" msgstr "Коннікі" msgid "Champion" msgstr "ЧÑмпіён" msgid "Champions" msgstr "ЧÑмпіёны" msgid "Paladin" msgstr "Паладзін" msgid "Paladins" msgstr "Паладзіны" msgid "Crusader" msgstr "Крыжак" msgid "Crusaders" msgstr "Крыжакі" msgid "Goblin" msgstr "Гоблін" msgid "Goblins" msgstr "Гобліны" msgid "Orc" msgstr "Орк" msgid "Orcs" msgstr "Оркі" msgid "Orc Chief" msgstr "Орк правадыр" msgid "Orc Chiefs" msgstr "Оркі правадыры" msgid "Wolf" msgstr "Воўк" msgid "Wolves" msgstr "Ваўкі" msgid "Ogre" msgstr "Волат" msgid "Ogres" msgstr "Волаты" msgid "Ogre Lord" msgstr "Волат уладар" msgid "Ogre Lords" msgstr "Волаты ўладары" msgid "Troll" msgstr "Троль" msgid "Trolls" msgstr "Тролі" msgid "War Troll" msgstr "ВаÑўнічы троль" msgid "War Trolls" msgstr "ВаÑÑžÐ½Ñ–Ñ‡Ñ‹Ñ Ñ‚Ñ€Ð¾Ð»Ñ–" msgid "Cyclopes" msgstr "Цыклопы" msgid "Cyclops" msgstr "Цыклоп" msgid "Sprite" msgstr "ФеÑ" msgid "Sprites" msgstr "Феі" msgid "Dwarf" msgstr "Гном" msgid "Dwarves" msgstr "Гномы" msgid "Battle Dwarf" msgstr "Гном ваÑўнік" msgid "Battle Dwarves" msgstr "Гномы ваÑўнікі" msgid "Elf" msgstr "Эльф" msgid "Elves" msgstr "Эльфы" msgid "Grand Elf" msgstr "ШлÑхетны Ñльф" msgid "Grand Elves" msgstr "Ð¨Ð»Ñ„Ñ…ÐµÑ‚Ð½Ñ‹Ñ Ñльфы" msgid "Druid" msgstr "Друід" msgid "Druids" msgstr "Друіды" msgid "Greater Druid" msgstr "Старшы друід" msgid "Greater Druids" msgstr "Ð¡Ñ‚Ð°Ñ€ÑˆÑ‹Ñ Ð´Ñ€ÑƒÑ–Ð´Ñ‹" msgid "Unicorn" msgstr "Ðднарог" msgid "Unicorns" msgstr "Ðднарогі" msgid "Phoenix" msgstr "ФенікÑ" msgid "Phoenixes" msgstr "ФенікÑÑ‹" msgid "Centaur" msgstr "Кентаўр" msgid "Centaurs" msgstr "Кентаўры" msgid "Gargoyle" msgstr "ГаргуллÑ" msgid "Gargoyles" msgstr "Гаргуллі" msgid "Griffin" msgstr "Грыфон" msgid "Griffins" msgstr "Грыфоны" msgid "Minotaur" msgstr "Мінатаўр" msgid "Minotaurs" msgstr "Мінатаўры" msgid "Minotaur King" msgstr "Мінатаўр кароль" msgid "Minotaur Kings" msgstr "Мінатаўры каралі" msgid "Hydra" msgstr "Гідра" msgid "Hydras" msgstr "Гідры" msgid "Green Dragon" msgstr "ЗÑлёны цмок" msgid "Green Dragons" msgstr "ЗÑÐ»Ñ‘Ð½Ñ‹Ñ Ñ†Ð¼Ð¾ÐºÑ–" msgid "Red Dragon" msgstr "Чырвоны цмок" msgid "Red Dragons" msgstr "Ð§Ñ‹Ñ€Ð²Ð¾Ð½Ñ‹Ñ Ñ†Ð¼Ð¾ÐºÑ–" msgid "Black Dragon" msgstr "Чорны цмок" msgid "Black Dragons" msgstr "Ð§Ð¾Ñ€Ð½Ñ‹Ñ Ñ†Ð¼Ð¾ÐºÑ–" msgid "Halfling" msgstr "Хобіт" msgid "Halflings" msgstr "Хобіты" msgid "Boar" msgstr "Дзік" msgid "Boars" msgstr "Дзікі" msgid "Iron Golem" msgstr "Жалезны голем" msgid "Iron Golems" msgstr "Ð–Ð°Ð»ÐµÐ·Ð½Ñ‹Ñ Ð³Ð¾Ð»ÐµÐ¼Ñ‹" msgid "Steel Golem" msgstr "Сталёвы голем" msgid "Steel Golems" msgstr "Ð¡Ñ‚Ð°Ð»Ñ‘Ð²Ñ‹Ñ Ð³Ð¾Ð»ÐµÐ¼Ñ‹" msgid "Roc" msgstr "Птушка Рух" msgid "Rocs" msgstr "Птушкі Рух" msgid "Mage" msgstr "Маг" msgid "Magi" msgstr "Магі" msgid "Archmage" msgstr "Ðрхімаг" msgid "Archmagi" msgstr "Ðрхімагі" msgid "Giant" msgstr "Гігант" msgid "Giants" msgstr "Гіганты" msgid "Titan" msgstr "Тытан" msgid "Titans" msgstr "Тытаны" msgid "Skeletons" msgstr "Шкілеты" msgid "Zombie" msgstr "МÑрцвÑк" msgid "Zombies" msgstr "МÑрцвÑкі" msgid "Mutant Zombie" msgstr "Хваравіты мÑрцвÑк" msgid "Mutant Zombies" msgstr "Ð¥Ð²Ð°Ñ€Ð°Ð²Ñ–Ñ‚Ñ‹Ñ Ð¼ÑрцвÑкі" msgid "Mummies" msgstr "Муміі" msgid "Mummy" msgstr "МуміÑ" msgid "Royal Mummies" msgstr "КаралеўÑÐºÑ–Ñ Ð¼ÑƒÐ¼Ñ–Ñ–" msgid "Royal Mummy" msgstr "КаралеўÑÐºÐ°Ñ Ð¼ÑƒÐ¼Ñ–Ñ" msgid "Vampire" msgstr "Вампір" msgid "Vampires" msgstr "Вампіры" msgid "Vampire Lord" msgstr "Лорд вампір" msgid "Vampire Lords" msgstr "Лорды вампіры" msgid "Lich" msgstr "КашчÑй" msgid "Liches" msgstr "КашчÑÑ–" msgid "Power Lich" msgstr "Магутны кашчÑй" msgid "Power Liches" msgstr "ÐœÐ°Ð³ÑƒÑ‚Ð½Ñ‹Ñ ÐºÐ°ÑˆÑ‡ÑÑ–" msgid "Bone Dragon" msgstr "КаÑцÑны цмок" msgid "Bone Dragons" msgstr "КаÑцÑÐ½Ñ‹Ñ Ñ†Ð¼Ð¾ÐºÑ–" msgid "Rogue" msgstr "Ліхадзей" msgid "Rogues" msgstr "Ліхадзеі" msgid "Nomad" msgstr "КачÑўнік" msgid "Nomads" msgstr "КачÑўнікі" msgid "Ghost" msgstr "Здань" msgid "Ghosts" msgstr "Здані" msgid "Genie" msgstr "Джын" msgid "Genies" msgstr "Джыны" msgid "Medusa" msgstr "Медуза" msgid "Medusas" msgstr "Медузы" msgid "Earth Elemental" msgstr "ЗемлÑны Ñлементаль" msgid "Earth Elementals" msgstr "ЗемлÑÐ½Ñ‹Ñ Ñлементалі" msgid "Air Elemental" msgstr "Паветраны Ñлементаль" msgid "Air Elementals" msgstr "ÐŸÐ°Ð²ÐµÑ‚Ñ€Ð°Ð½Ñ‹Ñ Ñлементалі" msgid "Fire Elemental" msgstr "Вогненны Ñлементаль" msgid "Fire Elementals" msgstr "Ð’Ð¾Ð³Ð½ÐµÐ½Ð½Ñ‹Ñ Ñлементалі" msgid "Water Elemental" msgstr "ВадзÑны Ñлементаль" msgid "Water Elementals" msgstr "ВадзÑÐ½Ñ‹Ñ Ñлементалі" msgid "Random Monsters" msgstr "" msgid "Random Monster 1" msgstr "" msgid "Random Monsters 1" msgstr "" msgid "Random Monster 2" msgstr "" msgid "Random Monsters 2" msgstr "" msgid "Random Monster 3" msgstr "" msgid "Random Monsters 3" msgstr "" msgid "Random Monster 4" msgstr "" msgid "Random Monsters 4" msgstr "" msgid "Double shot" msgstr "" msgid "2-hex monster" msgstr "" msgid "Double strike" msgstr "" msgid "Double damage to Undead" msgstr "" msgid "% magic resistance" msgstr "" msgid "Immune to Mind spells" msgstr "" msgid "Immune to Elemental spells" msgstr "" msgid "Immune to Fire spells" msgstr "" msgid "Immune to Cold spells" msgstr "" msgid "Immune to " msgstr "" msgid "% immunity to %{spell} spell" msgstr "" msgid "% damage from Elemental spells" msgstr "" msgid "% damage from %{spell} spell" msgstr "" msgid "% chance to Dispel beneficial spells" msgstr "" msgid "% chance to Paralyze" msgstr "" msgid "% chance to Petrify" msgstr "" msgid "% chance to Blind" msgstr "" msgid "% chance to Curse" msgstr "" msgid "% chance to cast %{spell} spell" msgstr "" msgid "HP regeneration" msgstr "" msgid "Two hexes attack" msgstr "" msgid "Flyer" msgstr "" msgid "Always retaliates" msgstr "" msgid "Attacks all adjacent enemies" msgstr "" msgid "No melee penalty" msgstr "" msgid "Dragon" msgstr "" msgid "Undead" msgstr "" msgid "No enemy retaliation" msgstr "" msgid "HP drain" msgstr "" msgid "Cloud attack" msgstr "" msgid "Decreases enemy's morale by " msgstr "" msgid "% chance to halve enemy" msgstr "" msgid "Soul Eater" msgstr "" msgid "Elemental" msgstr "" msgid "No Morale" msgstr "" msgid "Earth creature" msgstr "" msgid "Air creature" msgstr "" msgid "Fire creature" msgstr "" msgid "Water creature" msgstr "" msgid "Double damage from Fire spells" msgstr "" msgid "Double damage from Cold spells" msgstr "" msgid "Double damage from Earth creatures" msgstr "" msgid "Double damage from Air creatures" msgstr "" msgid "Double damage from Fire creatures" msgstr "" msgid "Double damage from Water creatures" msgstr "" msgid "Lightning" msgstr "" msgid "% immunity to " msgstr "" msgid "% damage from " msgstr "" msgid "The three Anduran artifacts magically combine into one." msgstr "" msgid "View Spells" msgstr "ПраглÑдзець загаворы" msgid "View %{name} Info" msgstr "ПраглÑдзець інфармацыю: %{name}" msgid "Move %{name}" msgstr "" msgid "Cannot move the Spellbook" msgstr "" msgid "This item can't be traded." msgstr "" msgid "Invalid Artifact" msgstr "" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "Ultimate Book of Knowledge" msgstr "" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "Ultimate Sword of Dominion" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "Ultimate Cloak of Protection" msgstr "" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "Ultimate Wand of Magic" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "Ultimate Shield" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "Ultimate Staff" msgstr "" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "Ultimate Crown" msgstr "" msgid "Golden Goose" msgstr "" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "" msgid "Arcane Necklace of Magic" msgstr "" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" msgid "Caster's Bracelet of Magic" msgstr "" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" msgid "Mage's Ring of Power" msgstr "" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" msgid "Witch's Broach of Magic" msgstr "" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" msgid "Medal of Valor" msgstr "" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" msgid "Medal of Courage" msgstr "" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" msgid "Medal of Honor" msgstr "" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" msgid "Medal of Distinction" msgstr "" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" msgid "Fizbin of Misfortune" msgstr "" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" msgid "Thunder Mace of Dominion" msgstr "" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" msgid "Armored Gauntlets of Protection" msgstr "" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" msgid "Defender Helm of Protection" msgstr "" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" msgid "Giant Flail of Dominion" msgstr "" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" msgid "Ballista of Quickness" msgstr "" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" msgid "Stealth Shield of Protection" msgstr "" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" msgid "Dragon Sword of Dominion" msgstr "" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" msgid "Power Axe of Dominion" msgstr "" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" msgid "Divine Breastplate of Protection" msgstr "" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" msgid "Minor Scroll of Knowledge" msgstr "" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" msgid "Major Scroll of Knowledge" msgstr "" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" msgid "Superior Scroll of Knowledge" msgstr "" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" msgid "Foremost Scroll of Knowledge" msgstr "" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" msgid "Endless Sack of Gold" msgstr "" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" msgid "Endless Bag of Gold" msgstr "" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" msgid "Endless Purse of Gold" msgstr "" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" msgid "Nomad Boots of Mobility" msgstr "" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" msgid "Traveler's Boots of Mobility" msgstr "" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" msgid "Lucky Rabbit's Foot" msgstr "" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" msgid "Golden Horseshoe" msgstr "" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" msgid "Gambler's Lucky Coin" msgstr "" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" msgid "Four-Leaf Clover" msgstr "" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" msgid "True Compass of Mobility" msgstr "" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" msgid "Sailor's Astrolabe of Mobility" msgstr "" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" msgid "Evil Eye" msgstr "" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" msgid "Enchanted Hourglass" msgstr "" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" msgid "Gold Watch" msgstr "" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "" msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" msgid "Skullcap" msgstr "" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" msgid "Ice Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" msgid "Fire Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" msgid "Lightning Helm" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" msgid "Evercold Icicle" msgstr "" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" msgid "Everhot Lava Rock" msgstr "" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" msgid "Lightning Rod" msgstr "" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" msgid "Snake-Ring" msgstr "" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" msgid "Ankh" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" msgid "Book of Elements" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" msgid "Elemental Ring" msgstr "" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" msgid "Holy Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" msgid "Pendant of Free Will" msgstr "" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" msgid "Pendant of Life" msgstr "" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "" msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" msgid "Serenity Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" msgid "Seeing-eye Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" msgid "Kinetic Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" msgid "Pendant of Death" msgstr "" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" msgid "Wand of Negation" msgstr "" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" msgid "Golden Bow" msgstr "" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" msgid "Telescope" msgstr "" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" msgid "Statesman's Quill" msgstr "" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" msgid "Wizard's Hat" msgstr "" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" msgid "Power Ring" msgstr "" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" msgid "Ammo Cart" msgstr "" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" msgid "Tax Lien" msgstr "" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" msgid "Hideous Mask" msgstr "" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" msgid "Endless Pouch of Sulfur" msgstr "" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "" msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" msgid "Endless Vial of Mercury" msgstr "" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "" msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" msgid "Endless Pouch of Gems" msgstr "" msgid "The %{name} provides %{count} unit of gems per day." msgstr "" msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" msgid "Endless Cord of Wood" msgstr "" msgid "The %{name} provides %{count} unit of wood per day." msgstr "" msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" msgid "Endless Cart of Ore" msgstr "" msgid "The %{name} provides %{count} unit of ore per day." msgstr "" msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" msgid "Endless Pouch of Crystal" msgstr "" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "" msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" msgid "Spiked Helm" msgstr "" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" msgid "Spiked Shield" msgstr "" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" msgid "White Pearl" msgstr "" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" msgid "Black Pearl" msgstr "" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" msgid "Magic Book" msgstr "" msgid "The %{name} enables the hero to cast spells." msgstr "" msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "" msgid "The reserved artifact." msgstr "" msgid "Dummy 3" msgstr "" msgid "Dummy 4" msgstr "" msgid "Spell Scroll" msgstr "" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" msgid "Arm of the Martyr" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" msgid "Breastplate of Anduran" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" msgid "Broach of Shielding" msgstr "" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" msgid "Battle Garb of Anduran" msgstr "" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" msgid "Crystal Ball" msgstr "" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" msgid "Heart of Fire" msgstr "" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" msgid "Heart of Ice" msgstr "" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" msgid "Helmet of Anduran" msgstr "" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" msgid "Holy Hammer" msgstr "" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" msgid "Legendary Scepter" msgstr "" msgid "The %{name} adds %{count} points to all attributes." msgstr "" msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" msgid "Masthead" msgstr "" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" msgid "Sphere of Negation" msgstr "" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" msgid "Staff of Wizardry" msgstr "" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" msgid "Sword Breaker" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð°Ð²Ñлічвае гарадcÐºÑ–Ñ Ð·Ð±Ð¾Ñ€Ñ‹ на %{count} штодзень." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" msgid "Sword of Anduran" msgstr "" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" msgid "Spade of Necromancy" msgstr "" msgid "The %{name} gives the hero increased necromancy skill." msgstr "" msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "" msgid "Mercury" msgstr "" msgid "Ore" msgstr "" msgid "Sulfur" msgstr "" msgid "Crystal" msgstr "" msgid "Gems" msgstr "" msgid "Gold" msgstr "" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" msgid "Fireball" msgstr "" msgid "Fireblast" msgstr "" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "" msgid "Lightning Bolt" msgstr "" msgid "Chain Lightning" msgstr "" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" msgid "Teleport" msgstr "" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" msgid "Cure" msgstr "" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" msgid "Mass Cure" msgstr "" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" msgid "Resurrect" msgstr "" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" msgid "Resurrect True" msgstr "" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" msgid "Haste" msgstr "" msgid "Increases the speed of any creature by %{count}." msgstr "" msgid "Increases the speed of all of your creatures by %{count}." msgstr "" msgid "Mass Haste" msgstr "" msgid "Slows target to half movement rate." msgstr "" msgid "spell|Slow" msgstr "" msgid "Mass Slow" msgstr "" msgid "Slows all enemies to half movement rate." msgstr "" msgid "spell|Blind" msgstr "" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" msgid "Bless" msgstr "" msgid "Causes the selected creatures to inflict maximum damage." msgstr "" msgid "Causes all of your units to inflict maximum damage." msgstr "" msgid "Mass Bless" msgstr "" msgid "Magically increases the defense skill of the selected creatures." msgstr "" msgid "Stoneskin" msgstr "" msgid "Steelskin" msgstr "" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" msgid "Causes the selected creatures to inflict minimum damage." msgstr "" msgid "Curse" msgstr "" msgid "Causes all enemy troops to inflict minimum damage." msgstr "" msgid "Mass Curse" msgstr "" msgid "Damages all undead in the battle." msgstr "" msgid "Holy Word" msgstr "" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" msgid "Holy Shout" msgstr "" msgid "Anti-Magic" msgstr "" msgid "Prevents any magic against the selected creatures." msgstr "" msgid "Dispel Magic" msgstr "" msgid "Removes all magic spells from a single target." msgstr "" msgid "Mass Dispel" msgstr "" msgid "Removes all magic spells from all creatures." msgstr "" msgid "Causes a magic arrow to strike the selected target." msgstr "" msgid "Magic Arrow" msgstr "" msgid "Berserker" msgstr "" msgid "Causes a creature to attack its nearest neighbor." msgstr "" msgid "Armageddon" msgstr "" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" msgid "Elemental Storm" msgstr "" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" msgid "Meteor Shower" msgstr "" msgid "Paralyze" msgstr "" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" msgid "Hypnotize" msgstr "" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" msgid "Cold Ray" msgstr "" msgid "Drains body heat from a single enemy unit." msgstr "" msgid "Cold Ring" msgstr "" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" msgid "Disrupting Ray" msgstr "" msgid "Reduces the defense rating of an enemy unit by three." msgstr "" msgid "Damages all living (non-undead) units in the battle." msgstr "" msgid "Death Ripple" msgstr "" msgid "Death Wave" msgstr "" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" msgid "Dragon Slayer" msgstr "" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "" msgid "Blood Lust" msgstr "" msgid "Increases a unit's attack skill." msgstr "" msgid "Animate Dead" msgstr "" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" msgid "Mirror Image" msgstr "" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" msgid "Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Mass Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Summon Earth Elemental" msgstr "" msgid "Summons Earth Elementals to fight for your army." msgstr "" msgid "Summon Air Elemental" msgstr "" msgid "Summons Air Elementals to fight for your army." msgstr "" msgid "Summon Fire Elemental" msgstr "" msgid "Summons Fire Elementals to fight for your army." msgstr "" msgid "Summon Water Elemental" msgstr "" msgid "Summons Water Elementals to fight for your army." msgstr "" msgid "Damages castle walls." msgstr "" msgid "Earthquake" msgstr "" msgid "Causes all mines across the land to become visible." msgstr "" msgid "View Mines" msgstr "" msgid "Causes all resources across the land to become visible." msgstr "" msgid "View Resources" msgstr "" msgid "Causes all artifacts across the land to become visible." msgstr "" msgid "View Artifacts" msgstr "" msgid "Causes all towns and castles across the land to become visible." msgstr "" msgid "View Towns" msgstr "" msgid "Causes all Heroes across the land to become visible." msgstr "" msgid "View Heroes" msgstr "" msgid "Causes the entire land to become visible." msgstr "" msgid "View All" msgstr "" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" msgid "Summon Boat" msgstr "" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" msgid "Allows the caster to magically transport to a nearby location." msgstr "" msgid "Dimension Door" msgstr "" msgid "Returns the caster to any town or castle currently owned." msgstr "" msgid "Town Gate" msgstr "" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" msgid "Visions" msgstr "" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" msgid "Haunt" msgstr "" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" msgid "Set Earth Guardian" msgstr "" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Air Guardian" msgstr "" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Fire Guardian" msgstr "" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Water Guardian" msgstr "" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" #, fuzzy msgid "Random Spell" msgstr "" "Выпад-\n" "ковы" msgid "Randomly selected spell of any level." msgstr "" msgid "Random 1st Level Spell" msgstr "" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" msgid "No spell to cast." msgstr "" msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "" msgid "View Adventure Spells" msgstr "" msgid "View Combat Spells" msgstr "" msgid "View previous page" msgstr "" msgid "View next page" msgstr "" msgid "Close Spellbook" msgstr "" msgid "View %{spell}" msgstr "" msgid "This spell does %{damage} points of damage." msgstr "" msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" msgid "This spell restores %{hp} HP." msgstr "" msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" msgid "The nearest town is %{town}." msgstr "" msgid "This town is occupied by your hero %{hero}." msgstr "" msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" msgid "The ultimate artifact is really the %{name}." msgstr "" msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" msgid "north-west" msgstr "" msgid "north" msgstr "" msgid "north-east" msgstr "" msgid "west" msgstr "" msgid "center" msgstr "" msgid "east" msgstr "" msgid "south-west" msgstr "" msgid "south" msgstr "" msgid "south-east" msgstr "" msgid "The truth is out there." msgstr "" msgid "The dark side is stronger." msgstr "" msgid "The end of the world is near." msgstr "" msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" msgid "A Black Dragon will take out a Titan any day of the week." msgstr "" msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" msgid "An unknown force is being resurrected..." msgstr "" msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" #~ msgid "Enable auto combat" #~ msgstr "Уключыць аўта-бой" #, fuzzy #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "ЗмÑніць мову, раздзÑленне Ñкрана Ñ– налады гульні." #, fuzzy #~ msgid "NEW GAME" #~ msgstr "ÐОВÐЯ" fheroes2-1.1.6+dfsg/files/lang/bg.po000066400000000000000000014576321476115357100171620ustar00rootroot00000000000000# Bulgarian translation of fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2022-11-08 16:44+0000\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: bg\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: Poedit 3.0.1\n" msgid "" "NEW\n" "GAME" msgstr "" "ÐОВÐ\n" "ИГРÐ" msgid "" "SAVE\n" "GAME" msgstr "" "ЗÐПÐЗИ\n" "ИГРÐ" msgid "" "LOAD\n" "GAME" msgstr "" "ЗÐРЕДИ\n" "ИГРÐ" msgid "INFO" msgstr "ИÐФО" msgid "QUIT" msgstr "ИЗХОД" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "ÐОВÐ\n" "ИГРÐ" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "ЗÐПÐЗИ\n" "ИГРÐ" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "ЗÐРЕДИ\n" "ИГРÐ" msgid "CANCEL" msgstr "ОТКÐЗ" msgid "OKAY" msgstr "ДОБРЕ" msgid "ACCEPT" msgstr "ПРИЕМÐМ" msgid "DECLINE" msgstr "ОТКÐЗВÐМ" msgid "LEARN" msgstr "ÐÐУЧИ" msgid "TRADE" msgstr "СДЕЛКÐ" msgid "YES" msgstr "ДÐ" msgid "NO" msgstr "ÐЕ" msgid "EXIT" msgstr "ИЗХОД" msgid "smallerButton|EXIT" msgstr "ИЗХОД" msgid "DISMISS" msgstr "ОТПРÐТИ" msgid "UPGRADE" msgstr "ЗÐСИЛИ" msgid "RESTART" msgstr "РЕСТÐРТ" msgid "HEROES" msgstr "ГЕРОЙ" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "ГРÐДОВЕ/\n" "ЗÐМЪЦИ" msgid "S" msgstr "" msgid "M" msgstr "" msgid "L" msgstr "" msgid "X-L" msgstr "" msgid "ALL" msgstr "" msgid "SELECT" msgstr "ИЗБЕРИ" msgid "" "STANDARD\n" "GAME" msgstr "" "ÐОРМÐЛÐÐ\n" "ИГРÐ" msgid "" "BATTLE\n" "ONLY" msgstr "" "СÐМО\n" "БИТКÐ" msgid "" "CAMPAIGN\n" "GAME" msgstr "" "ИГРÐЙ\n" "ИСТОРИЯ" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "ИГРРС\n" "ПОВЕЧЕ\n" "ИГРÐЧИ" msgid "CONFIG" msgstr "" "КОÐФИ-\n" "ГУРÐЦИЯ" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ÐÐЧÐЛÐÐ\n" "ИСТОРИЯ" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "ЕКСПÐÐЗИЯ" msgid "HOT SEAT" msgstr "ОБЩ СТОЛ" msgid "2 PLAYERS" msgstr "2 ИГРÐЧÐ" msgid "3 PLAYERS" msgstr "3 ИГРÐЧÐ" msgid "4 PLAYERS" msgstr "4 ИГРÐЧÐ" msgid "5 PLAYERS" msgstr "5 ИГРÐЧÐ" msgid "6 PLAYERS" msgstr "6 ИГРÐЧÐ" msgid "GIFT" msgstr "ДÐРИ" msgid "MAX" msgstr "МÐКС" msgid "DIFFICULTY" msgstr "ТРУДÐОСТ" msgid "VIEW INTRO" msgstr "ВИЖ ИÐТРО" msgid "MIN" msgstr "МИÐ" msgid "RESET" msgstr "" #, fuzzy msgid "START" msgstr "РЕСТÐРТ" msgid "TOWN" msgstr "" #, fuzzy msgid "CASTLE" msgstr "" "ГРÐДОВЕ/\n" "ЗÐМЪЦИ" #, fuzzy msgid "RESTRICT" msgstr "РЕСТÐРТ" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "О\n" "Т\n" "П\n" "Р\n" "Ð\n" "Т\n" "И" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "И\n" "З\n" "Ð¥\n" "О\n" "Д" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "К\n" "Ð\n" "М\n" "П\n" "Ð\n" "Ð\n" "И\n" "Я" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "С\n" "Т\n" "Ð\n" "Ð\n" "Д\n" "Ð\n" "Р\n" "Т\n" "Е\n" "Ð" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Войн" msgid "Builder" msgstr "Строител" msgid "Explorer" msgstr "ИзÑледовател" msgid "None" msgstr "Без" msgid "" "A few\n" "%{monster}" msgstr "" "Малко\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "ÐÑколко\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Глутница\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Много\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Орда от\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Тълпа от\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "РоÑк от\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Стотици\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Легион от\n" "%{monster}" msgid "army|Few" msgstr "Малко" msgid "army|Several" msgstr "ÐÑколко" msgid "army|Pack" msgstr "Глутница" msgid "army|Lots" msgstr "Много" msgid "army|Horde" msgstr "Орда" msgid "army|Throng" msgstr "Тълпа" msgid "army|Swarm" msgstr "РоÑк" msgid "army|Zounds" msgstr "Стотици" msgid "army|Legion" msgstr "Легион" msgid "All %{race} troops +1" msgstr "Ð’Ñички %{race} войÑки +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Ðеутрален" msgid "Troops of %{count} alignments -%{penalty}" msgstr "ВойÑки от %{count} подравнÑÐ²Ð°Ð½Ð¸Ñ -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "ÐÑкои немъртви в група -1" #, fuzzy msgid "" "Default\n" "troop" msgstr "дейÑтвие по подразбиране" msgid "View %{name}" msgstr "Виж %{name}" msgid "Move the %{name} " msgstr "ПремеÑти %{name} " msgid "Move or right click to redistribute %{name}" msgstr "ПремеÑти или щракни Ñ Ð´ÐµÑен бутон, за да разпределиш %{name}" msgid "Combine %{name} armies" msgstr "Комбинирай %{name} заедно" msgid "Exchange %{name2} with %{name}" msgstr "Размени %{name2} Ñ %{name}" msgid "Select %{name}" msgstr "Избери %{name}" msgid "Cannot move last troop" msgstr "Ðе може да премеÑти поÑÐ»ÐµÐ´Ð½Ð¸Ñ Ð¾Ñ‚Ñ€Ñд" msgid "Move the %{name}" msgstr "ПремеÑти %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "ЗаÑтрелÑй %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} унищожава половината вражеÑки войÑки!" msgstr[1] "%{name} унищожи половината вражеÑки войÑки!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} е изключил автоматичната битка" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} включи автоматичната битка" msgid "Spell failed!" msgstr "Заклинанието е неуÑпешно!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Ðртефактът Сфера на отрицанието е в Ñила за тази битка, дезактивирайки " "вÑички бойни заклинаниÑ." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Вече Ñи направил Ð¼Ð°Ð³Ð¸Ñ Ñ‚Ð¾Ð·Ð¸ рунд." msgid "That spell will have no effect!" msgstr "Това заклинание нÑма да има ефект!" msgid "You may only summon one type of elemental per combat." msgstr "Можеш да призовеш Ñамо един тип елементал за битка." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "ÐÑма открито проÑтранÑтво до Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹, където можеш да призовеш Елементал." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Ровът намалÑва Ñ -%{count} умението за защита на вÑÑка единица и Ð·Ð°Ð±Ð°Ð²Ñ " "наполовина ÑкороÑтта на движение." msgid "Speed: %{speed}" msgstr "СкороÑÑ‚: %{speed}" msgid "Speed" msgstr "СкороÑÑ‚" msgid "Off" msgstr "Изкл" msgid "On" msgstr "Вкл" msgid "Turn Order" msgstr "Ред на завъртане" msgid "Auto Spell Casting" msgstr "Ðвтоматично заклинание" msgid "Grid" msgstr "Решетка" msgid "Shadow Movement" msgstr "Движение на Ñенките" msgid "Shadow Cursor" msgstr "КурÑор в ÑÑнка" msgid "Audio" msgstr "Звукови" msgid "Settings" msgstr "ÐаÑтойки" msgid "Configure" msgstr "ÐаÑтрой" msgid "Hot Keys" msgstr "Бързи клавиши" msgid "Damage Info" msgstr "Инфо за щетите" msgid "Set the speed of combat actions and animations." msgstr "Задай ÑкороÑтта на бойните дейÑÑ‚Ð²Ð¸Ñ Ð¸ анимациите." msgid "Toggle to display the turn order during the battle." msgstr "Превключи, за да покажеш реда на ход по време на битката." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Превключи дали компютърът да прави Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð²Ð¼ÐµÑто теб, когато " "автоматичната битка е включена. (Забележка: Това не влиÑе по никакъв начин " "на правенето на Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð·Ð° компютърни играчи, нито заÑÑга бързата битка.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Включи или изключи шеÑтнадеÑетичната мрежа. ШеÑтнадеÑетичната мрежа винаги е " "в оÑновата на движението, дори и да е изключена. Този ключ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ñамо " "дали решетката е видима." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Включи или изключи Ñенките, показващи къде твойте ÑъщеÑтва могат да Ñе " "движат и атакуват." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Включи или изключи ÑÑнка, показваща текущото шеÑтнадеÑетично меÑтоположение " "на курÑора на мишката." msgid "Change the audio settings of the game." msgstr "Промени звуковите наÑтройки на играта." msgid "Check and configure all the hot keys present in the game." msgstr "Провери и конфигурирай вÑички горещи клавиши в играта." msgid "Toggle to display damage information during the battle." msgstr "Превключи за показване на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° щетите по време на битката." msgid "Exit this menu." msgstr "Излез от това меню." msgid "Okay" msgstr "Добре" msgid "The enemy has surrendered!" msgstr "Врагът Ñе предаде!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Врагът побÑгва!" msgid "A glorious victory!" msgstr "Славна победа!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "За храброÑÑ‚ в битката %{name} получава %{exp} опит." msgid "The cowardly %{name} flees from battle." msgstr "СтрахливиÑÑ‚ %{name} бÑга от битката." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} Ñе предава на врага и Ñи тръгва заÑрамен." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "Твойте Ñили претърпÑват горчиво поражение и %{name} изоÑÑ‚Ð°Ð²Ñ ÐºÐ°ÑƒÐ·Ð°Ñ‚Ð° ти." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Твойте Ñили претърпÑват горчиво поражение." msgid "Battlefield Casualties" msgstr "Жертви на бойното поле" msgid "Attacker" msgstr "Ðападател" msgid "Defender" msgstr "Защитник" #, fuzzy msgid "Click to leave the battle results." msgstr "Кликни, за да приложиш избраната резолюциÑ." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Кликни, за да Ñе върнеш към главното меню." msgid "Restart" msgstr "РеÑтарт" msgid "You have captured an enemy artifact!" msgstr "Ти Ñи заловил вражеÑки артефакт!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Когато поÑÑгаш към %{name}, той миÑтериозно изчезва." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Когато врагът ти поÑÑга към %{name}, той миÑтериозно изчезва." msgid "Necromancy!" msgstr "ÐекромантиÑ!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Практикувайки тъмните изкуÑтва на некромантиÑта, можш да Ñъбереш %{count} от " "мъртвите на врага, за да Ñе върнат под твое командване като %{monster}." msgid "%{name} the %{race}" msgstr "%{name} %{race}" msgid "Captain of %{name}" msgstr "Капитан на %{name}" msgid "Attack" msgstr "Ðтака" msgid "Defense" msgstr "Защита" msgid "Spell Power" msgstr "МагиÑ" msgid "Knowledge" msgstr "Знание" msgid "Morale" msgstr "Морал" msgid "Luck" msgstr "КъÑмет" msgid "Spell Points" msgstr "МагиÑ" msgid "Hero's Options" msgstr "Опции на героÑ" msgid "Cast Spell" msgstr "Ðаправи заклинание" msgid "Retreat" msgstr "ОтÑтъпление" msgid "Surrender" msgstr "Предаване" msgid "Cancel" msgstr "ОтменÑм" msgid "Hero Screen" msgstr "Екран на героÑ" msgid "Captain's Options" msgstr "Опции на героÑ" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Ðаправи магичеÑко заклинание. Можеш да правиш Ñамо едно заклинание на боен " "рунд. Рундът Ñе нулира, когато вÑÑко ÑъщеÑтво е имало ход." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Оттегли ÑÐ²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹, изоÑтавÑйки Ñвоите ÑъзданиÑ. ТвоÑÑ‚ герой ще бъде на " "разположение, за да го наемш отново, но героÑÑ‚ ще разполага Ñамо ÑÑŠÑ Ñилите " "на начинаещ герой." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Предаването ще Ñтрува злато. Ðко обаче платиш откупа, героÑÑ‚ и вÑички негови " "или нейни оцелели ÑъщеÑтва ще бъдат на разположение за наемане отново." msgid "Open Hero Screen to view full information about the hero." msgstr "Отвори екрана на героÑ, за да видиш пълната Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° героÑ." msgid "Return to the battle." msgstr "Върни Ñе в битката." msgid "Not enough gold (%{gold})" msgstr "ÐÑма доÑтатъчно злато (%{gold})" msgid "%{name} states:" msgstr "%{name} заÑвÑва:" msgid "Captain of %{name} states:" msgstr "Капитанът на %{name} заÑвÑва:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Ще приема капитулациÑта ти и ще оÑÐ¸Ð³ÑƒÑ€Ñ Ð½Ð° теб и войÑките ти безопаÑно " "преминаване на цената на %{price} злато.\"" msgid "View %{monster} info" msgstr "Виж Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° %{monster} " msgid "Fly %{monster} here" msgstr "Прелети %{monster} тук" msgid "Move %{monster} here" msgstr "ПремеÑти %{monster} тук" msgid "Shoot %{monster}" msgstr "ЗаÑтрелÑй %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(ОÑтава 1 изÑтрел)" msgstr[1] "(ОÑтават %{count} изÑтрела)" msgid "Attack %{monster}" msgstr "Ðападни %{monster}" msgid "Turn %{turn}" msgstr "Ход %{turn}" msgid "Teleport here" msgstr "Телепортирай Ñе тук" msgid "Invalid teleport destination" msgstr "ÐеÑъщеÑтвуващо мÑÑто за телепортиране" msgid "Cast %{spell} on %{monster}" msgstr "Ðаправи %{spell} върху %{monster}" msgid "Cast %{spell}" msgstr "Ðаправи %{spell}" msgid "Select spell target" msgstr "Избери цел за заклинание" msgid "View Ballista info" msgstr "Виж Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° Катапулт" msgid "Ballista" msgstr "Катапулта" #, fuzzy msgid "Automatic combat modes" msgstr "Ðвто Сражение" #, fuzzy msgid "Automatic Combat Modes" msgstr "Ðвто Сражение" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "ПерÑонализирай ÑиÑтемните опции" msgid "Allows you to customize the combat screen." msgstr "ПозволÑва ти да перÑонализираш Ð±Ð¾Ð¹Ð½Ð¸Ñ ÐµÐºÑ€Ð°Ð½." msgid "System Options" msgstr "СиÑтемни наÑтройки" msgid "Skip this unit" msgstr "ПропуÑни тази единица" msgid "Skip" msgstr "ПропуÑни" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "ПропуÑка текущото Ñъздание. Текущото Ñъздание завършва реда Ñи и не може да " "отиде отново до ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ ÐºÑ€ÑŠÐ³." msgid "View Captain's options" msgstr "Виж наÑтройките на героÑ" msgid "View Hero's options" msgstr "Виж наÑтройките на героÑ" msgid "View opposing Captain" msgstr "Виж Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð½Ð¸ÐºÐ¾Ð²Ð¸Ñ Ð³ÐµÑ€Ð¾Ð¹" msgid "View opposing Hero" msgstr "Виж Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð½Ð¸ÐºÐ¾Ð²Ð¸Ñ Ð³ÐµÑ€Ð¾Ð¹" msgid "Hide logs" msgstr "Скрий региÑтрационни файлове" msgid "Show logs" msgstr "Показжи региÑтрационни файлове" msgid "Message Bar" msgstr "Лента за ÑъобщениÑ" msgid "Shows the results of individual monster's actions." msgstr "Покажи резултатите от дейÑтвиÑта на отделните чудовища." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Сигурен ли Ñи, че иÑкаш да активираш автоматичните битки?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Сигурен ли Ñи че иÑкаш да презапишеш запазената игра Ñ Ñ‚Ð¾Ð²Ð° име?" #, fuzzy msgid "The computer continues the combat for you." msgstr "ПозволÑва на компютъра да води битката вмеÑто теб." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Ðвто Сражение" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Ðвто Сражение" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} пропуÑкат ÑÐ²Ð¾Ñ Ñ€ÐµÐ´." msgstr[1] "%{name} пропуÑкат ÑÐ²Ð¾Ñ Ñ€ÐµÐ´." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} нанаÑÑ %{damage} щети." msgstr[1] "%{attacker} нанаÑÑÑ‚ %{damage} щети." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 ÑъщеÑтво загива." msgstr[1] "%{count} ÑъщеÑтва загиват." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} загива." msgstr[1] "%{count} %{defender} загиват." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 душа е включена." msgstr[1] "%{count} души Ñа включени." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} е Ñъживена." msgstr[1] "%{count} %{unit} Ñа Ñъживени." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "ПремеÑтен %{monster}: %{src}, %{dst}" #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} уÑÑ‚Ð¾Ñ Ð½Ð° заклинанието!" msgstr[1] "%{name} уÑÑ‚Ð¾Ñ Ð½Ð° заклинанието!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} Ñ…Ð²ÑŠÑ€Ð»Ñ %{spell} върху %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} прави %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} нанаÑÑ %{damage} щети на едно немъртво ÑъщеÑтво." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} нанаÑÑ %{damage} щети на вÑички немъртви ÑъщеÑтва." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} нанаÑÑ %{damage} щети, %{count} ÑъщеÑтва загиват." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} нанаÑÑ %{damage} щети." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} нанаÑÑ %{damage} щети на едно живо ÑъщеÑтво." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} нанаÑÑ %{damage} щети на вÑички живи ÑъщеÑтва." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Ðападението на %{attacker} заÑлепÑва %{target}!" msgstr[1] "Ðападението на %{attacker} заÑлепÑва %{target}!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "Погледът на %{attacker} превръща %{target} в камък!" msgstr[1] "Погледът на %{attacker} превръща %{target} в камък!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "ПроклÑтието %{attacker} пада върху %{target}!" msgstr[1] "ПроклÑтието %{attacker} пада върху %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{target} Ñа парализирани от %{attacker}!" msgstr[1] "%{target} Ñа парализирани от %{attacker}!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "%{attacker} разÑейва вÑички добри Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð½Ð° Ñ‚Ð²Ð¾Ñ %{target}!" msgstr[1] "%{attacker} разÑейва вÑички добри Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð½Ð° Ñ‚Ð²Ð¾Ñ %{target}!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} направи %{spell} на %{target}!" msgstr[1] "%{attacker} направи %{spell} на %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "ЛошиÑÑ‚ къÑмет Ñе Ñтоварва върху %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "КъÑметът Ñе уÑмихва на %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "ВиÑокиÑÑ‚ морал позволÑва на %{monster} да атакува отново." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "ÐиÑкиÑÑ‚ морал кара %{monster} да замръзне от паника." msgid "%{tower} does %{damage} damage." msgstr "%{tower} нанаÑÑ %{damage} щети." msgid "The mirror image is created." msgstr "Създава Ñе огледален образ." msgid "The mirror image is destroyed!" msgstr "ОгледалниÑÑ‚ образ е унищожен!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Сигурен ли Ñте, че иÑкате да Ñе отеглите?" msgid "Error" msgstr "Грешка" msgid "No spells to cast." msgstr "ÐÑма магии за правене." msgid "Are you sure you want to retreat?" msgstr "Сигурен ли Ñте, че иÑкате да Ñе отеглите?" msgid "Retreat disabled" msgstr "ОтеглÑнето е деактивирано" msgid "Surrender disabled" msgstr "Предаването е деактивирано" msgid "Damage: %{max}" msgstr "Щети: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Щети: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Загиват: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Загиват: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Чрез наблюдение Ñ Ð¾Ñ€Ð»Ð¾Ð²Ð¸ очи, %{name} уÑпÑва да научи магичеÑкото заклинание " "%{spell}." msgid "Human" msgstr "Човек" msgid "AI" msgstr "ИИ" #, fuzzy msgid "Start" msgstr "РеÑтарт" #, fuzzy msgid "Start the battle." msgstr "Върни Ñе в битката." msgid "Exit" msgstr "Изход" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "МолÑ, избери друг герой." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{name1} Ñреща %{name2}" msgid "Monsters" msgstr "Чудовища" msgid "N/A" msgstr "Без" msgid "Left Turret" msgstr "ЛÑва кула" msgid "Right Turret" msgstr "ДÑÑна кула" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} ÑÑ‚Ñ€ÐµÐ»Ñ ÑÑŠÑ Ñилата на %{count} Ñтрелци" msgid "each with a +%{attack} bonus to their attack skill." msgstr "вÑеки получава +%{attack} Ð±Ð¾Ð½ÑƒÑ ÐºÑŠÐ¼ Ñвоето умение за нападение." msgid "The %{name} is destroyed." msgstr "%{name} е унищожен!" msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} възкръÑна от мъртвите!" msgstr[1] "%{count} %{name} възкръÑнаха от мъртвите!" msgid "Dwarven Alliance" msgstr "Съюзът на джуджетата" msgid "Sorceress Guild" msgstr "ГилдиÑта на магьоÑниците" msgid "Necromancer Guild" msgstr "ГилдиÑта на некромантите" msgid "Ogre Alliance" msgstr "Съюз на Огре" msgid "Dwarfbane" msgstr "Джуджеубиец" msgid "Dragon Alliance" msgstr "Драконов Ñъюз" msgid "Elven Alliance" msgstr "ЕлфичеÑки Ñъюз" msgid "Kraeger defeated" msgstr "Крегер е победен" msgid "Wayward Son" msgstr "Своенравен Ñин" msgid "Uncle Ivan" msgstr "Чичо Иван" msgid "Annexation" msgstr "ÐнекÑирам" msgid "Force of Arms" msgstr "ÐаÑилÑтвено" msgid "Save the Dwarves" msgstr "СпаÑи джуджетата" msgid "Carator Mines" msgstr "Мините на Каратор" msgid "Turning Point" msgstr "Повратна точка" msgid "scenarioName|Defender" msgstr "Защитник" msgid "Corlagon's Defense" msgstr "Защитата на Корлагон" msgid "The Crown" msgstr "Короната" msgid "The Gauntlet" msgstr "Под кръÑтоÑан огън" msgid "Betrayal" msgstr "ПредателÑтво" msgid "Final Justice" msgstr "ПоÑледна ÑправедливоÑÑ‚" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Роланд Ñе нуждае от теб, за да победите лордовете близо до замъка му и да " "започне ÑвоÑÑ‚ бунт Ñрещу брат Ñи. Те не Ñа Ñъюзници, така че през по-" "голÑмата чаÑÑ‚ от времето ще Ñа в битка един Ñрещу друг. Победата ще е твоÑ, " "когато победиш вÑичките им замъци и герои." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "МеÑтните лордове отказват да Ñе закълнат във вÑрноÑÑ‚ на Роланд и трÑбва да " "бъдат покорени. Те Ñа богати и могъщи, така че бъди готов за тежка битка. " "Превземи вÑички вражеÑки замъци, за да Ñпечелищ." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "ТвоÑта задача е да защитиш джуджетата Ñрещу Ñилите на Ðрчибалд. Превземи " "вÑички вражеÑки градове и замъци, за да Ñпечелиш и бъди Ñигурен, че нÑма да " "загубиш вÑички градове на джуджетата наведнъж, или врагът ще е победил." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Ще Ñе изправиш Ñрещу четирима ÑъюзничеÑки врагове в директна битка за " "реÑурÑи и Ñъкровища. Превземи вÑички вражеÑки замъци за победа." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Твойте врагове Ñа Ñъюзени Ñрещу теб и нападат отблизо, така че бъди готов да " "излезеш в битка. Ще трÑбва да притежаваш и четирите замъка в тази малка " "долина, за да Ñпечелиш." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "ГилдиÑта на магьоÑниците от ÐораÑтън е поиÑкала помощта на Роланд Ñрещу " "нападението от Ñъюзниците на Ðрчибалд. Превземи вÑички вражеÑки замъци, за " "да Ñпечелиш и не губи ÐораÑтон, или ще загубиш ÑценариÑ. (Съвет: Има " "вражеÑки замък на оÑтров в океана.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Събери възможно най-голÑма Ð°Ñ€Ð¼Ð¸Ñ Ð¸ превземи вражеÑÐºÐ¸Ñ Ð·Ð°Ð¼ÑŠÐº в рамките на 8 " "Ñедмици. Ти Ñе противопоÑтавÑш Ñамо на един враг, но трÑбва да изминеш дълъг " "път, за да Ñтигнеш до вражеÑÐºÐ¸Ñ Ð·Ð°Ð¼ÑŠÐº. Ð’Ñички войÑки, които имаш в ÑвоÑта " "Ð°Ñ€Ð¼Ð¸Ñ Ð² ÐºÑ€Ð°Ñ Ð½Ð° този Ñценарий, ще бъдат Ñ Ñ‚ÐµÐ± в поÑледната битка." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Ðамери короната, преди героите на Ðрчибалд да Ñ Ð½Ð°Ð¼ÐµÑ€ÑÑ‚. Роланд ще Ñе нуждае " "от короната за поÑледната битка Ñрещу Ðрчибалд." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Трима ÑъюзничеÑки врагове ÑтоÑÑ‚ между теб и победата, включително лорд " "Корлагон. Роланд е в замък на Ñеверозапад и ти ще загубиш, ако той загуби от " "врага. Ðе забравÑй, че залавÑнето на лорд Корлагон ще гарантира, че той нÑма " "да Ñе бие Ñрещу теб в поÑÐ»ÐµÐ´Ð½Ð¸Ñ Ñценарий." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Това е поÑледната битка. И ти и врагът Ñте въоръжени до зъби и вÑички Ñа " "обединени Ñрещу ваÑ. Хванете Ðрчибалд, за да Ñложите край на войната!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "СмÑната на отбора те оÑÑ‚Ð°Ð²Ñ Ñ Ñ‚Ñ€Ð¸ замъка Ñрещу ÐµÐ´Ð¸Ð½Ð¸Ñ Ð½Ð° врага. Тази битка " "ще бъде най-леÑната, Ñ ÐºÐ¾Ñто ще Ñе ÑблъÑкаш до ÐºÑ€Ð°Ñ Ð½Ð° войната... предател." msgid "Barbarian Wars" msgstr "ВарварÑки войни" msgid "First Blood" msgstr "Първа кръв" msgid "Necromancers" msgstr "Ðекроманти" msgid "Slay the Dwarves" msgstr "Убий джуджетата" msgid "Country Lords" msgstr "СелÑки гоÑподари" msgid "Dragon Master" msgstr "ГоÑподар на драконите" msgid "Rebellion" msgstr "Бунт" msgid "Apocalypse" msgstr "ÐпокалипÑиÑ" msgid "Greater Glory" msgstr "По-голÑма Ñлава" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Крал Ðрчибалд изиÑква от теб да победиш тримата врагове в този регион. Те не " "Ñа Ñъюзници помежду Ñи, така че ще изразходват по-голÑмата чаÑÑ‚ от енергиÑта " "Ñи в битки помежду Ñи. Ще Ñпечелиш, когато притежаваш вÑички вражеÑки замъци " "и нÑма повече герои, които да Ñе биÑÑ‚." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "ТрÑбва да обединиш варварÑките племена на Ñевер, като ги завладееш. Както и " "в предишната миÑиÑ, врагът не ти е противник, но има повече реÑурÑи на Ñвое " "разположение. Ще Ñпечелиш, когато притежаваш вÑички вражеÑки замъци и нÑма " "повече герои, които да Ñе биÑÑ‚." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Добрите магьоÑници Ñа превзели замъка на Ðекромантите. ТрÑбва да Ñи го " "върнеш обратно, за да поÑтигнеш победа. Ðе забравÑй, че макар да започваш Ñ " "мощна армиÑ, ти нÑмаш замък и трÑбва да превземеш такъв в рамките на 7 дни " "или губиш тази битка. (Съвет: Ðай-близкиÑÑ‚ замък е на югоизток.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Джуджетата Ñе нуждаÑÑ‚ от победа, преди да могат да Ñе намеÑÑÑ‚ в плановете на " "крал Ðрчибалд. Силите на Роланд разполагат Ñ Ð¿Ð¾Ð²ÐµÑ‡Ðµ от един герой и много " "градове, така че бъди готов за атака от различни поÑоки. ТрÑбва да превземеш " "вÑички вражеÑки градове и замъци, за да победиш." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "ТрÑбва да потушиш ÑелÑко въÑтание, водено от Ñилите на Роланд. Ð’Ñички Ñа " "Ñъюзници Ñрещу теб, но имаш лорд Корлагон, опитен герой, който да ти помага. " "Превземи вÑички вражеÑки замъци, за да Ñпечелиш." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Има двама врагове, обединени Ñрещу теб в тази миÑиÑ. И двамата Ñа добре " "въоръжени и Ñе ÑтремÑÑ‚ да те изгонÑÑ‚ от Ñ‚ÐµÑ…Ð½Ð¸Ñ Ð¾Ñтров. ИзбÑгвай ги и " "превземи Градът на Драконите, за да Ñпечелиш." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Твойте заповеди Ñа да завладееш ÑелÑките гоÑподари, които Ñа Ñе заклели да " "Ñлужат на Роланд. Ð’Ñички вражеÑки замъци Ñа обединени Ñрещу теб. Тъй като " "започваш без замък, трÑбва да побързаш да првземеш един преди ÐºÑ€Ð°Ñ Ð½Ð° " "Ñедмицата. Превземи вÑички вражеÑки замъци за победа." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Ðамери короната, преди героите на Роланд да Ñ Ð½Ð°Ð¼ÐµÑ€ÑÑ‚. Ðрчибалд ще Ñе нуждае " "от короната за поÑледната битка Ñрещу Роланд." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Това е поÑледната битка. И ти, и врагът Ñте въоръжени до зъби и вÑички Ñа " "обединени Ñрещу теб. Хвани Роланд, за да Ñпечелиш войната и бъди Ñигурен, че " "нÑма да загубиш Ðрчибалд в битката!" msgid "Arrow's Flight" msgstr "Полетът на Ñтрелата" msgid "Island of Chaos" msgstr "ОÑтров на хаоÑа" msgid "The Abyss" msgstr "Бездната" msgid "Uprising" msgstr "Ð’ÑŠÑтание" msgid "Aurora Borealis" msgstr "Северно СиÑние" msgid "Betrayal's End" msgstr "КраÑÑ‚ на предателÑтвото" msgid "Corruption's Heart" msgstr "Сърцето на корупциÑта" msgid "The Giant's Pass" msgstr "Проходът на великана" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Покори непокорните меÑтни лордове, за да оÑигуриш на ИмпериÑта ÑÑŠÐ¾Ñ€ÑŠÐ¶ÐµÐ½Ð¸Ñ Ð·Ð° " "работа в този регион." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Премахни вÑÑка Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð² тази облаÑÑ‚. След това първото парче от артефакта " "ще бъде твое." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "МагьоÑниците на Ñевероизток Ñе бунтуват! За доброто на империÑта трÑбва да " "потушиш Ñлабото им въÑтание по Ð¿ÑŠÑ‚Ñ Ñи към планините." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "След като Ñе е подготвил за вашето приÑтигане, Крегер е уредил Ñила от " "некроманти да оÑуети твоето търÑене. ТрÑбва да превземеш замъка СкабÑдейл " "преди Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð´ÐµÐ½ на третата Ñедмица, или некромантите ще бъдат твърде Ñилни " "за теб." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "ВарварÑкиÑÑ‚ деÑпот в тази облаÑÑ‚ вÑе още не знае за твоето приÑÑŠÑтвие. " "Бързо, Ñъбери Ñилите Ñи, преди да бъдеш открит и нападнат! ОÑигури региона, " "като подчиниш вÑички вражеÑки Ñили." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "ИмпериÑта е Ñлаба в този регион. ÐÑма да можеш да покориш напълно вÑички " "Ñили в тази облаÑÑ‚, така че вземи каквото можеш, преди да те ударÑÑ‚ ответни " "удари. Ðе забравÑй, че иÑтинÑката ти цел е да вземеш шлема на Ðндуран." msgid "For the good of the Empire, eliminate Kraeger." msgstr "За доброто на ИмпериÑта елиминирай Крегер." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Ðай-Ð½Ð°ÐºÑ€Ð°Ñ Ð¸Ð¼Ð°Ñˆ възможноÑтта и ÑъоръжениÑта да отървеш ИмпериÑта от злото на " "некроманта. Изкорени ги напълно и ще бъдеш възпÑÑ‚ като герой завинаги." msgid "Border Towns" msgstr "Погранични градове" msgid "Conquer and Unify" msgstr "Покори и обедини" msgid "Crazy Uncle Ivan" msgstr "Ð›ÑƒÐ´Ð¸Ñ Ñ‡Ð¸Ñ‡Ð¾ Иван" msgid "The Wayward Son" msgstr "СвоенравниÑÑ‚ Ñин" msgid "Ivory Gates" msgstr "Портите на Ðйвъри" msgid "The Elven Lands" msgstr "ЕлфичеÑките земи" msgid "The Epic Battle" msgstr "Епичната битка" msgid "The Southern War" msgstr "Южната война" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Покори и обедини вÑички вражеÑки племена. Ðе губи Ð³ÐµÑ€Ð¾Ñ Ð”Ð¶Ð°Ñ€ÐºÐ¾Ð½Ð°Ñ, праотецът " "на вÑички потомци." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "ТвоÑÑ‚ Ñъперник, КралÑтво Харондейл, атакува Ñлаби градове на твоÑта граница! " "ВъзÑтанови Ñе от Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð¸Ð¼ удар и ги Ñмажи напълно!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Ðамери ÑÐ²Ð¾Ñ Ñвоенравен Ñин Джоузеф, за когото Ñе говори, че живее в пуÑтите " "земи. Ðаправи го преди Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð´ÐµÐ½ на Ñ‚Ñ€ÐµÑ‚Ð¸Ñ Ð¼ÐµÑец или нÑма да е от полза за " "твоето ÑемейÑтво." #, fuzzy msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "СпаÑи Ð»ÑƒÐ´Ð¸Ñ Ñи чичо Иван. Ðамери го преди Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð´ÐµÐ½ на Ñ‡ÐµÑ‚Ð²ÑŠÑ€Ñ‚Ð¸Ñ Ð¼ÐµÑец или " "той нÑма да е от полза за твоето кралÑтво." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Унищожи варварите, които атакуват южната граница на твоето кралÑтво! " "ВъзÑтанови падналите Ñи градове и Ñлед това нахлуй в кралÑтвото на " "джунглата. Ðе оÑтавÑй нито един враг." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "" "Върни Ñи отново замъка Портите на Ивъри, който падна поради предателÑтво." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Спечели благоволението на елфите. Те нÑма да позволÑÑ‚ да Ñе изÑичат дървета, " "така че ще ти изпращат дърва на вÑеки 2 Ñедмици. ТрÑбва да завършиш миÑиÑта " "Ñи преди Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð´ÐµÐ½ на ÑÐµÐ´Ð¼Ð¸Ñ Ð¼ÐµÑец или кралÑтвото ÑÑŠÑ ÑигурноÑÑ‚ ще падне." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Това е поÑледната битка Ñрещу Ñъперничещото ти кралÑтво Харондейл. " "Елиминирай вÑички и не губи Ð³ÐµÑ€Ð¾Ñ Ð”Ð¶Ð°Ñ€ÐºÐ¾Ð½Ð°Ñ VI." msgid "Fount of Wizardry" msgstr "Изворът на магьоÑничеÑтвото" msgid "Power's End" msgstr "КраÑÑ‚ на влаÑтта" msgid "The Eternal Scrolls" msgstr "Вечните Ñвитъци" msgid "The Shrouded Isles" msgstr "Забулените оÑтрови" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "ТвоÑта миÑÐ¸Ñ Ðµ да победиш воюващите магове в магичеÑките Забулени оÑтрови. " "Изпълнението на тази задача ще ти даде ÑˆÐ°Ð½Ñ Ð´Ð° Ñе биеш Ñрещу твойте " "Ñъперници." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "МеÑтоположението на великата библиотека е открито! ТрÑбва да Ñтигнеш до него " "и да Ñи върнеш града ХроноÑ, в който Ñе намира." #, fuzzy msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Ðамери Кълбото на отрицанието, за което Ñе казва, че е заровено в тази земÑ. " "Има улики, изпиÑани върху каменни обелиÑки, които ще ти помогнат да разберш " "ÑтойноÑтта Ñи. Ðамери кълбото преди Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð´ÐµÐ½ на шеÑÑ‚Ð¸Ñ Ð¼ÐµÑец или твойте " "Ñъперници ÑÑŠÑ ÑигурноÑÑ‚ ще Ñа Ñтигнали до извора преди теб." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "ТрÑбва да поемеш контрола над замъка на магиÑта, където Ñе намира изворът на " "магьоÑничеÑтвото. Ðаправи това и твоÑта победа ще бъде върховна." msgid "Blood is Thicker" msgstr "Кръвта е по-гъÑта" msgid "King and Country" msgstr "Крал и държава" msgid "Pirate Isles" msgstr "ПиратÑки оÑтрови" msgid "Stranded" msgstr "ЗакъÑал" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Превземи града на оÑтрова край ÑŽÐ³Ð¾Ð¸Ð·Ñ‚Ð¾Ñ‡Ð½Ð¸Ñ Ð±Ñ€Ñг, за да поÑтроиш лодка и да " "пътуваш обратно към континента. Ðе губи Ð³ÐµÑ€Ð¾Ñ Ð“Ð°Ð»Ð°Ð²Ð°Ð½Ñ‚." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Ðамери и победи Мартин, водача на пиратите, който живее в ПиратÑÐºÐ¸Ñ Ð·Ð°Ð»Ð¸Ð². " "Ðе губи Галавант или миÑиÑта ти ще приключи." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Елиминирай вÑички други Ñили, които Ñе противопоÑтавÑÑ‚ на управлението на " "лорд Ðлберон. Галавант не трÑбва да умира." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Пребори утвърдената Ð¼Ð¾Ð½Ð°Ñ€Ñ…Ð¸Ñ Ð½Ð° лорд Ðлберон и поиÑкай цÑлата Ð·ÐµÐ¼Ñ Ð½Ð° твое " "име. Галавант не трÑбва да умира." msgid " bane" msgstr " проклÑтие" msgid " alliance" msgstr " Ñъюз" msgid "Carry-over forces" msgstr "ПренаÑÑщи Ñили" msgid " bonus" msgstr " бонуÑ" msgid " defeated" msgstr " победен" msgid " will always run away from your army." msgstr " винаги ще бÑга от вашата армиÑ." msgid " will be willing to join your army." msgstr " ще има желание да Ñе приÑъедини към вашата армиÑ." #, fuzzy msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "Ðртефактът \"%{artifact}\" ще бъде пренеÑен в ÑценариÑ." #, fuzzy msgid "The army will be carried over in the campaign." msgstr "ÐрмиÑта ще бъде пренеÑена по ÑценариÑ." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "КралÑтвото ще има +%{count} %{resource} вÑеки ден." #, fuzzy msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "Заклинанието \"%{spell}\" ще бъде пренеÑено в ÑценариÑ." #, fuzzy msgid "%{hero} can be hired during scenarios." msgstr "%{hero} може да бъде нает в ÑценариÑ." #, fuzzy msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "%{hero} е победен и нÑма да Ñе поÑви в Ñледващите Ñценарии." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Джуджетата разпознават Ñвоите Ñъюзници и Ñ Ñ€Ð°Ð´Ð¾ÑÑ‚ Ñе приÑъединÑват към " "вашите Ñили." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Огритата те разпознават като Джуджеубиеца и Ñе натиÑкат да Ñе приÑъединÑÑ‚ " "към теб." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Драконите, ръмжащи и ръмжейки, Ñе ÑъглаÑÑват да обединÑÑ‚ Ñили Ñ Ñ‚ÐµÐ±, Ñ‚ÐµÑ…Ð½Ð¸Ñ " "\"Ñъюзник\"." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Когато Ñе приближаваш до групата елфи, техниÑÑ‚ водач ги призовава вÑички да " "внимават. Той им крещи: \"Кой от Ð²Ð°Ñ Ðµ доÑтатъчно Ñмел да Ñе приÑъедини към " "този наш безÑтрашен Ñъюзник?\" Групата избухва от възглаÑи, докато тичат да " "Ñе приÑъединÑÑ‚ към твоите редици." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Джуджетата те приветÑтват: \"Ð’Ñеки приÑтел на Роланд е и наш приÑтел. Може " "да преминеш.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Огритата ти изÑумтÑват в знак на признание: \"Съюзниците на Ðрчибалд може да " "преминат.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Драконите те виждат и викат. \"Съюзът ни Ñ Ðрчибалд ни принуждава да Ñе " "приÑъединим към теб. За Ñъжаление нÑмаш мÑÑто. Жалко!\" Те бързо Ñе " "разпръÑкват." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Елфите ÑтоÑÑ‚ мирно, докато Ñе приближаваш. ТехниÑÑ‚ водач Ñе обръща към теб " "казва: \"Ðека не пречим на прогреÑа ти, Ñъюзнико! Продължавай напред и нека " "победата бъде твоÑ.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Джуджеубиецо!!!!, бÑгай за да опазиш живота Ñи.\"" msgid "campaignBonus|Animate Dead" msgstr "Ðнимирайте мъртвите" msgid "campaignBonus|Chain Lightning" msgstr "Верижна Ñветкавица" msgid "campaignBonus|Fireblast" msgstr "Огнена екÑплозиÑ" msgid "campaignBonus|Mass Curse" msgstr "МаÑово проклÑтие" msgid "campaignBonus|Mass Haste" msgstr "МаÑово бързане" msgid "campaignBonus|Mirror Image" msgstr "Огледална картина" msgid "campaignBonus|Resurrect" msgstr "ВъзкръÑни" msgid "campaignBonus|Steelskin" msgstr "Стоманена кожа" msgid "campaignBonus|Summon Earth" msgstr "Призови ЗемÑта" msgid "campaignBonus|View Heroes" msgstr "Виж героите" msgid "campaignBonus|Ballista" msgstr "Катапулт" msgid "campaignBonus|Black Pearl" msgstr "Черна перла" msgid "campaignBonus|Caster's Bracelet" msgstr "Гривна на КаÑтер" msgid "campaignBonus|Defender Helm" msgstr "Защитен шлем" msgid "campaignBonus|Breastplate" msgstr "Ðагръдник" msgid "campaignBonus|Dragon Sword" msgstr "Драконов меч" msgid "campaignBonus|Fizbin Medal" msgstr "Медал Физбин" msgid "campaignBonus|Foremost Scroll" msgstr "Ðай-могъщиÑÑ‚ Ñвитък" msgid "campaignBonus|Gauntlets" msgstr "Ръкавици" msgid "campaignBonus|Hideous Mask" msgstr "Отвратителна маÑка" msgid "campaignBonus|Mage's Ring" msgstr "ПръÑтенът на магьоÑника" msgid "campaignBonus|Major Scroll" msgstr "Огромен Ñвитък" msgid "campaignBonus|Medal of Honor" msgstr "Медал на чеÑтта" msgid "campaignBonus|Medal of Valor" msgstr "Медал за доблеÑÑ‚" msgid "campaignBonus|Minor Scroll" msgstr "Малък Ñвитък" msgid "campaignBonus|Nomad Boots" msgstr "ÐомадÑки ботуши" msgid "campaignBonus|Power Axe" msgstr "Брадва на Силата" msgid "campaignBonus|Spiked Shield" msgstr "Щит Ñ ÑˆÐ¸Ð¿Ð¾Ð²Ðµ" msgid "campaignBonus|Stealth Shield" msgstr "Стелт щит" msgid "campaignBonus|Tax Lien" msgstr "Данъчен залог" msgid "campaignBonus|Thunder Mace" msgstr "Гръмотевичен боздуган" msgid "campaignBonus|Traveler's Boots" msgstr "ПътничеÑки ботуши" msgid "campaignBonus|White Pearl" msgstr "БÑла перла" msgid "campaignBonus|Basic Archery" msgstr "Ðачална Ñтрелба Ñ Ð»ÑŠÐº" msgid "campaignBonus|Advanced Archery" msgstr "Стрелба Ñ Ð»ÑŠÐº за напреднали" msgid "campaignBonus|Expert Archery" msgstr "ЕкÑпертна Ñтрелба Ñ Ð»ÑŠÐº" msgid "campaignBonus|Basic Ballistics" msgstr "Ðачална балиÑтика" msgid "campaignBonus|Advanced Ballistics" msgstr "Ðапреднала балиÑтика" msgid "campaignBonus|Expert Ballistics" msgstr "ЕкÑпертна балиÑтика" msgid "campaignBonus|Basic Diplomacy" msgstr "Ðачална дипломациÑ" msgid "campaignBonus|Advanced Diplomacy" msgstr "Ðапреднала дипломациÑ" msgid "campaignBonus|Expert Diplomacy" msgstr "ЕкÑпертна дипломациÑ" msgid "campaignBonus|Basic Eagle Eye" msgstr "Ðачално орлово око" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Ðапреднало орлово око" msgid "campaignBonus|Expert Eagle Eye" msgstr "ЕкÑпертно орлово око" msgid "campaignBonus|Basic Estates" msgstr "Ðачални имоти" msgid "campaignBonus|Advanced Estates" msgstr "Ðапреднали имоти" msgid "campaignBonus|Expert Estates" msgstr "ЕкÑперт имоти" msgid "campaignBonus|Basic Leadership" msgstr "Ðачално лидерÑтво" msgid "campaignBonus|Advanced Leadership" msgstr "Ðапреднало лидерÑтво" msgid "campaignBonus|Expert Leadership" msgstr "ЕкÑпертно лидерÑтво" msgid "campaignBonus|Basic Logistics" msgstr "Ðачална логиÑтика" msgid "campaignBonus|Advanced Logistics" msgstr "Ðапреднала логиÑтика" msgid "campaignBonus|Expert Logistics" msgstr "ЕкÑпертна логиÑтика" msgid "campaignBonus|Basic Luck" msgstr "Ðачален къÑмет" msgid "campaignBonus|Advanced Luck" msgstr "Ðапреднал къÑмет" msgid "campaignBonus|Expert Luck" msgstr "ЕкÑпертен къÑмет" msgid "campaignBonus|Basic Mysticism" msgstr "Ðачален миÑтицизъм" msgid "campaignBonus|Advanced Mysticism" msgstr "Ðапреднал миÑтицизъм" msgid "campaignBonus|Expert Mysticism" msgstr "ЕкÑпертен миÑтицизъм" msgid "campaignBonus|Basic Navigation" msgstr "Ðачална навигациÑ" msgid "campaignBonus|Advanced Navigation" msgstr "Ðапреднала навигациÑ" msgid "campaignBonus|Expert Navigation" msgstr "ЕкÑпертна навигациÑ" msgid "campaignBonus|Basic Necromancy" msgstr "Ðачална некромантиÑ" msgid "campaignBonus|Advanced Necromancy" msgstr "Ðапреднала некромантиÑ" msgid "campaignBonus|Expert Necromancy" msgstr "ЕкÑпертна некромантиÑ" msgid "campaignBonus|Basic Pathfinding" msgstr "Ðачално намиране на пътÑ" msgid "campaignBonus|Advanced Pathfinding" msgstr "Ðапреднало намиране на пътÑ" msgid "campaignBonus|Expert Pathfinding" msgstr "ЕкÑпертно намиране на пътÑ" msgid "campaignBonus|Basic Scouting" msgstr "Ðачално ÑкаутÑтво" msgid "campaignBonus|Advanced Scouting" msgstr "Ðапреднало ÑкаутÑтво" msgid "campaignBonus|Expert Scouting" msgstr "ЕкÑпертно ÑкаутÑтво" msgid "campaignBonus|Basic Wisdom" msgstr "Ðачална мъдроÑÑ‚" msgid "campaignBonus|Advanced Wisdom" msgstr "Ðапреднала мъдроÑÑ‚" msgid "campaignBonus|Expert Wisdom" msgstr "ЕкÑпертна мъдроÑÑ‚" #, fuzzy msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "ГлавниÑÑ‚ герой ще има артефакт \"%{artifact}\" в началото на ÑценариÑ." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "КралÑтвото ще получи %{amount} допълнителни %{resource} в началото на " "ÑценариÑ." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "КралÑтвото ще има %{amount} по-малко %{resource} в началото на ÑценариÑ." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "ГлавниÑÑ‚ герой ще има %{count} %{monster} в началото на ÑценариÑ." #, fuzzy msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "ГлавниÑÑ‚ герой ще има заклинание \"%{spell}\" в началото на ÑценариÑ." #, fuzzy msgid "The starting alignment of the scenario will be %{race}." msgstr "Ðачалното ÑÑŠÑтезание на ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ñ‰Ðµ бъде %{race}." #, fuzzy msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "ГлавниÑÑ‚ герой ще има допълнителни %{count} %{skill} в началото на ÑценариÑ." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "The main hero will have %{skill} at the start of the scenario." msgid "Roland" msgstr "Роланд" msgid "Archibald" msgstr "Ðрчибалд" #, fuzzy msgid "Price of Loyalty" msgstr "Цената на лоÑлноÑтта" msgid "Voyage Home" msgstr "Пътуване към дома" msgid "Wizard's Isle" msgstr "ОÑтровът на вълшебника" msgid "Descendants" msgstr "Потомци" msgid "Cannot build. You have already built here today." msgstr "Ðе може да Ñе Ñтрои. Ти вече Ñи поÑтроил тук днеÑ." msgid "For this action it is necessary to build a castle first." msgstr "За това дейÑтвие е необходимо първо да поÑтроиш замък." msgid "The %{building} produces %{monster}." msgstr "%{building} произвежда %{monster}." msgid "Requires:" msgstr "ИзиÑква:" msgid "Exit this menu without doing anything." msgstr "Излез от това меню, без да правиш нищо." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Ðе може да Ñе поÑтрои %{name}, защото замъкът е твърде далеч от океан." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Ðе мога да Ñи Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñ %{name}." #, fuzzy msgid "The %{name} is already built." msgstr "%{name} вече е изграден." #, fuzzy msgid "Cannot build the %{name}." msgstr "Ðе може да Ñе изгради %{name}." msgid "Build %{name}." msgstr "ПоÑтрой %{name}." msgid "Blackridge" msgstr "Блекридж" msgid "Hillstone" msgstr "ХилÑтоун" msgid "Pinehurst" msgstr "ПайнхърÑÑ‚" msgid "Whiteshield" msgstr "БÑл щит" msgid "Woodhaven" msgstr "Удхейвън" msgid "Blackwind" msgstr "Черен вÑтър" msgid "Bloodreign" msgstr "Блъдрейн" msgid "Dragontooth" msgstr "Драконов зъб" msgid "Greywind" msgstr "Сив вÑтър" msgid "Portsmith" msgstr "ПортÑмит" msgid "Atlantium" msgstr "Ðтлантиум" msgid "Middle Gate" msgstr "Средна порта" msgid "Sansobar" msgstr "СанÑибар" msgid "Tundara" msgstr "Тундара" msgid "Vulcania" msgstr "ВулканиÑ" msgid "Baywatch" msgstr "Бейвоч" msgid "Fountainhead" msgstr "Глава на фонтан" msgid "Vertigo" msgstr "Световъртеж" msgid "Wildabar" msgstr "Вайлдабар" msgid "Winterkill" msgstr "Зимно убийÑтво" msgid "Brindamoor" msgstr "Бриндамур" msgid "Lakeside" msgstr "ЛейкÑайд" msgid "Nightshadow" msgstr "Ðощтна ÑÑнка" msgid "Olympus" msgstr "ОлимпуÑ" msgid "Sandcaster" msgstr "ПÑÑъчен колело" msgid "Alamar" msgstr "Ðлмар" msgid "Burlock" msgstr "Бурлог" msgid "Dragadune" msgstr "Драгадюн" msgid "Kalindra" msgstr "Калиндра" msgid "Xabran" msgstr "ЕкÑабран" msgid "Algary" msgstr "Ðлгари" msgid "Basenji" msgstr "БаÑенджи" msgid "Blackfang" msgstr "Черензъб" msgid "New Dawn" msgstr "Ðова Зора" msgid "Sorpigal" msgstr "Сорпигал" msgid "Avone" msgstr "Ðвон" msgid "Big Oak" msgstr "ГолÑм Дъб" msgid "Chandler" msgstr "Чандлър" msgid "Erliquin" msgstr "Ерликвин" msgid "Hampshire" msgstr "Хемпшир" msgid "Antioch" msgstr "ÐнтиохиÑ" msgid "Avalon" msgstr "Ðвалон" msgid "Roc Haven" msgstr "Рок Хейвън" msgid "South Mill" msgstr "Южна Мелница" msgid "Weed Patch" msgstr "ÐšÑŠÑ Ð¢Ñ€ÐµÐ²Ð°" msgid "Brownston" msgstr "БраунÑтън" msgid "Hilltop" msgstr "Хълм" msgid "Weddington" msgstr "Уедингтън" msgid "Westfork" msgstr "УеÑтфорк" msgid "Whittingham" msgstr "Уитингам" msgid "Cathcart" msgstr "Каткарт" msgid "Elk's Head" msgstr "Елкова глава" msgid "Roscomon" msgstr "РоÑкомън" msgid "Sherman" msgstr "Шърман" msgid "Yorksford" msgstr "ЙоркÑфорд" msgid "Blackburn" msgstr "Блекбърн" msgid "Blacksford" msgstr "БлекÑфорд" msgid "Burton" msgstr "Бъртън" msgid "Pig's Eye" msgstr "СвинÑко Око" msgid "Viper's Nest" msgstr "Гнездото на уÑойница" msgid "Fenton" msgstr "Фентън" msgid "Lankershire" msgstr "Ланкършър" msgid "Lombard" msgstr "Ломбард" msgid "Timberhill" msgstr "Тимбърхил" msgid "Troy" msgstr "ТроÑ" msgid "Forder Oaks" msgstr "Фордър ОукÑ" msgid "Meramec" msgstr "Мерамец" msgid "Quick Silver" msgstr "КуикÑилвър" msgid "Westmoor" msgstr "Западно ТреÑавище" msgid "Willow" msgstr "Уилоу" msgid "Corackston" msgstr "КоракÑтън" msgid "Sheltemburg" msgstr "Шелтембург" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Ðе може да Ñе наеме - вече имате герой в този град." msgid "Cannot recruit - you have too many Heroes." msgstr "Ðе може да Ñе наеме - имаш твърде много герои." #, fuzzy msgid "Cannot afford a Hero." msgstr "Ðе мога да Ñи Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñ Ð³ÐµÑ€Ð¾Ð¹" msgid "There is no room in the garrison for this army." msgstr "Ð’ гарнизона нÑма мÑÑто за тази армиÑ." msgid "Fortifications" msgstr "УкреплениÑ" msgid "Farm" msgstr "Ферма" msgid "Thatched Hut" msgstr "Сламена хижа" msgid "Archery Range" msgstr "Стрелба Ñ Ð»ÑŠÐº" msgid "Upg. Archery Range" msgstr "ÐадÑ. Ñтрелба Ñ Ð»ÑŠÐº" msgid "Blacksmith" msgstr "Ковачница" msgid "Upg. Blacksmith" msgstr "ÐадÑ. ковачница" msgid "Armory" msgstr "Оръжейна" msgid "Upg. Armory" msgstr "ÐадÑ. оръжейна" msgid "Jousting Arena" msgstr "Ðрена" msgid "Upg. Jousting Arena" msgstr "ÐадÑ. арена" msgid "Cathedral" msgstr "Катедрала" msgid "Upg. Cathedral" msgstr "ÐадÑ. катедрала" msgid "Coliseum" msgstr "Колизеум" msgid "Garbage Heap" msgstr "Купчина боклук" msgid "Hut" msgstr "Барака" msgid "Stick Hut" msgstr "Колиба" msgid "Upg. Stick Hut" msgstr "ÐадÑ. колиба" msgid "Den" msgstr "Бърлога" msgid "Adobe" msgstr "Глинена поÑтройка" msgid "Upg. Adobe" msgstr "ÐадÑ. глинена поÑтройка" msgid "Bridge" msgstr "МоÑÑ‚" msgid "Upg. Bridge" msgstr "ÐадÑ. МоÑÑ‚" msgid "Pyramid" msgstr "Пирамида" msgid "Rainbow" msgstr "Дъга" msgid "Crystal Garden" msgstr "КриÑтална градина" msgid "Treehouse" msgstr "Къща на дърво" msgid "Cottage" msgstr "Вила" msgid "Upg. Cottage" msgstr "ÐадÑ. вила" msgid "Stonehenge" msgstr "Стоунхендж" msgid "Upg. Stonehenge" msgstr "ÐадÑ. Стоунхендж" msgid "Fenced Meadow" msgstr "Оградена полÑна" msgid "sorceress|Red Tower" msgstr "Червена кула" msgid "Dungeon" msgstr "Тъмница" msgid "Waterfall" msgstr "Водопад" msgid "Cave" msgstr "Пещера" msgid "Crypt" msgstr "Крипта" msgid "Nest" msgstr "Гнездо" msgid "Maze" msgstr "Лабиринт" msgid "Upg. Maze" msgstr "ÐадÑ. лабиринт" msgid "Swamp" msgstr "Блато" msgid "Green Tower" msgstr "Зелена кула" msgid "warlock|Red Tower" msgstr "Червена кула" msgid "Black Tower" msgstr "Черна кула" msgid "Library" msgstr "Библиотека" msgid "Orchard" msgstr "Овощна градина" msgid "Habitat" msgstr "Хабитат" msgid "Pen" msgstr "Кошара" msgid "Foundry" msgstr "ЛеÑрна" msgid "Upg. Foundry" msgstr "ÐадÑ. леÑрна" msgid "Cliff Nest" msgstr "Скално гнездо" msgid "Ivory Tower" msgstr "Кулата на мечтите" msgid "Upg. Ivory Tower" msgstr "ÐадÑ. Кулата на мечтите" msgid "Cloud Castle" msgstr "Замък в облаците" msgid "Upg. Cloud Castle" msgstr "ÐадÑ. Замък в облаците" msgid "Storm" msgstr "БурÑ" msgid "Skull Pile" msgstr "Купчина черепи" msgid "Excavation" msgstr "Разкопки" msgid "Graveyard" msgstr "Гробище" msgid "Upg. Graveyard" msgstr "ÐадÑ. гробище" msgid "Upg. Pyramid" msgstr "ÐадÑ. пирамида" msgid "Mansion" msgstr "Имение" msgid "Upg. Mansion" msgstr "ÐадÑ. имение" msgid "Mausoleum" msgstr "Мавзолей" msgid "Upg. Mausoleum" msgstr "ÐадÑ. мавзолей" msgid "Laboratory" msgstr "ЛабораториÑ" msgid "Shrine" msgstr "Светилище" #, fuzzy msgid "Special" msgstr "Ðищо Ñпециално" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Хобити" #, fuzzy msgid "Dwelling 2" msgstr "Хобити" #, fuzzy msgid "Upg. Dwelling 2" msgstr "Хобити" #, fuzzy msgid "Dwelling 3" msgstr "Хобити" #, fuzzy msgid "Upg. Dwelling 3" msgstr "Хобити" #, fuzzy msgid "Dwelling 4" msgstr "Хобити" #, fuzzy msgid "Upg. Dwelling 4" msgstr "Хобити" #, fuzzy msgid "Dwelling 5" msgstr "Хобити" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Хобити" #, fuzzy msgid "Dwelling 6" msgstr "Хобити" #, fuzzy msgid "Upg. Dwelling 6" msgstr "Хобити" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "УкреплениÑта увеличават здравината на Ñтените, увеличавайки Ð±Ñ€Ð¾Ñ Ð½Ð° ударите, " "необходими за ÑъбарÑнето им." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Фермата увеличава производÑтвото на ÑелÑни Ñ %{count} на Ñедмица." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Колизеумът предоÑÑ‚Ð°Ð²Ñ Ð²Ð´ÑŠÑ…Ð½Ð¾Ð²Ñващи зрелища на отбранÑващите Ñе войÑки, като " "повишава морала им Ñ Ð´Ð²Ðµ по време на битка." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" "Купчината боклук увеличава производÑтвото на Гоблини Ñ %{count} на Ñедмица." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Дъгата увеличава къÑмета на защитаващите Ñе единици Ñ Ð´Ð²Ðµ." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" "КриÑталната градина увеличава производÑтвото на Фей Ñ %{count} на Ñедмица." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Подземието увеличава доходите на града Ñ %{count} злато на ден." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Водопадът увеличава производÑтвото на Кентаври Ñ %{count} на Ñедмица." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Библиотеката увеличава Ð±Ñ€Ð¾Ñ Ð½Ð° магиите в гилдиÑта Ñ Ð¿Ð¾ една за вÑÑко ниво на " "гилдиÑта." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" "Овощната градина увеличава производÑтвото на Хобити Ñ %{count} на Ñедмица." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "БурÑта Ð´Ð¾Ð±Ð°Ð²Ñ +2 към Ñилата на заклинаниÑта на защитаващ заклинател." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" "Купчината черепи увеличава производÑтвото на Скелети Ñ %{count} на Ñедмица." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Кладенецът увеличава ÑкороÑтта на раÑтеж във вÑички жилища Ñ %{count} " "ÑъщеÑтва на Ñедмица." msgid "Thieves' Guild" msgstr "Ð“Ð¸Ð»Ð´Ð¸Ñ Ð½Ð° крадците" msgid "Tavern" msgstr "Кръчма" msgid "Shipyard" msgstr "КорабоÑтроителница" msgid "Well" msgstr "Кладенец" msgid "Statue" msgstr "СтатуÑ" msgid "Marketplace" msgstr "Пазар" msgid "Moat" msgstr "Ров" msgid "Castle" msgstr "Замък" msgid "Tent" msgstr "Палатка" msgid "Captain's Quarters" msgstr "КапитанÑка Квартира" msgid "Mage Guild, Level 1" msgstr "Маг. гилдиÑ, ниво 1" msgid "Mage Guild, Level 2" msgstr "Маг. гилдиÑ, ниво 2" msgid "Mage Guild, Level 3" msgstr "Маг. гилдиÑ, ниво 3" msgid "Mage Guild, Level 4" msgstr "Маг. гилдиÑ, ниво 4" msgid "Mage Guild, Level 5" msgstr "Маг. гилдиÑ, ниво 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Светилището увеличава умението за Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚Ð¸Ñ Ð½Ð° вÑички твой некроманти Ñ 10 " "процента." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "ГилдиÑта на крадците предоÑÑ‚Ð°Ð²Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° вражеÑки играчи. Гилдиите на " "крадците Ñъщо могат да предоÑтавÑÑ‚ разузнавателна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° вражеÑките " "градове. Допълнителните гилдии предоÑтавÑÑ‚ повече информациÑ." msgid "The Tavern increases morale for troops defending the castle." msgstr "Кръчмата повишава морала на войÑките, защитаващи замъка." msgid "The Shipyard allows ships to be built." msgstr "КорабоÑтроителницата позволÑва да Ñе ÑтроÑÑ‚ кораби." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Кладенецът увеличава ÑкороÑтта на раÑтеж във вÑички жилища Ñ %{count} " "ÑъщеÑтва на Ñедмица." #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "СтатуÑта увеличава приходите на Ñ‚Ð²Ð¾Ñ Ð³Ñ€Ð°Ð´ Ñ %{count} злато на ден." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "ЛÑвата кула оÑигурÑва допълнителна огнева мощ по време на битка в замъка." msgid "The Right Turret provides extra firepower during castle combat." msgstr "" "ДÑÑната кула оÑигурÑва допълнителна огнева мощ по време на битка в замъка." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Пазарът може да Ñе използва за преобразуване на един вид реÑÑƒÑ€Ñ Ð² друг. " "Колкото повече пазари контролирате, толкова по-добър е обменниÑÑ‚ курÑ." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Ровът Ð·Ð°Ð±Ð°Ð²Ñ Ð°Ñ‚Ð°ÐºÑƒÐ²Ð°Ñ‰Ð¸Ñ‚Ðµ единици. Ð’ÑÑка единица, влизаща в рова, трÑбва да " "завърши реда Ñи там и да Ñтане по-уÑзвима за атака." #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Замъкът подобрÑва защитата на града и увеличава приходите до %{count} злато " "на ден." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Палатката оÑигурÑва работници за изграждане на замък, при уÑловие че " "материалите и златото Ñа налични." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "КапитанÑките квартири оÑигурÑват капитан, който да помага в защитата на " "замъка, когато нÑма герой." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "ГилдиÑта на магьоÑниците позволÑва на героите да учат Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¸ да " "попълват магичеÑките Ñи точки." msgid "Recruit %{name}" msgstr "Вербувай %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "МеÑец: %{month}, Седмица: %{week}, Ден: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "ТрÑбва да купиш книга ÑÑŠÑ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ, за да използваш магий, но в момента " "нÑмаш мÑÑто за неÑ. Опитай Ñе да дадеш един от твойте артефакти на друг " "герой." msgid "Click to show next town." msgstr "Кликни, за да покажеш ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´." msgid "Show next town" msgstr "Покажи ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´" msgid "Click to show previous town." msgstr "Кликни, за да покажеш Ð¿Ñ€ÐµÐ´Ð¸ÑˆÐ½Ð¸Ñ Ð³Ñ€Ð°Ð´." msgid "Show previous town" msgstr "Покажи Ð¿Ñ€ÐµÐ´Ð¸ÑˆÐ½Ð¸Ñ Ð³Ñ€Ð°Ð´" msgid "This town may not be upgraded to a castle." msgstr "Този град не може да бъде надграден до замък." msgid "Town" msgstr "Град" msgid "Exit Castle" msgstr "Изход от Замъка" msgid "Exit Town" msgstr "Изход от Града" msgid "Show Income" msgstr "Покажи приходи" msgid "View Hero" msgstr "Виж герой" msgid "The above spells are available here." msgstr "Гореизложените магии Ñа налични тук." msgid "The spells the hero can learn have been added to their book." msgstr "Магиите, които героÑÑ‚ може да научи, Ñа добавени към неговата книга." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "След щедър бакшиш бармана ÑÐ¿Ð¾Ð´ÐµÐ»Ñ ÑÐ»ÐµÐ´Ð½Ð¸Ñ Ñлух:" msgid "Recruit Hero" msgstr "Вербувай герой" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} е ниво %{value} %{race} " msgid "with %{count} artifacts." msgstr "Ñ %{count} артефакти." msgid "with 1 artifact." msgstr "Ñ 1 артефакт." msgid "without artifacts." msgstr "без артефакти." msgid "Recruit %{name} the %{race}" msgstr "Вербувай %{name} %{race}" #, fuzzy msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Бойната Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ \"РазпръÑкване\" Ñ€Ð°Ð·Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ñ‚Ð²Ð¾Ð¸Ñ‚Ðµ армии от горе до долу на " "бойното поле, Ñ Ð¿Ð¾Ð½Ðµ едно празно проÑтранÑтво между вÑÑка армиÑ." #, fuzzy msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "\"Групираната\" бойна Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð±ÐµÐ´Ð¸Ð½Ñва армиÑта ти в центъра от твоÑта " "Ñтрана на бойното поле." msgid "Spread Formation" msgstr "Ð¤Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð Ð°Ð·Ð¿Ñ€Ð¾Ñтиране" msgid "Grouped Formation" msgstr "Групирана формациÑ" #, fuzzy msgid "Click to show the next town." msgstr "Кликни, за да покажеш ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´." #, fuzzy msgid "Click to show the previous town." msgstr "Кликни, за да покажеш Ð¿Ñ€ÐµÐ´Ð¸ÑˆÐ½Ð¸Ñ Ð³Ñ€Ð°Ð´." msgid "Set garrison combat formation to 'Spread'" msgstr "Задай гарнизонна бойна Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ \"РазпроÑтиране\"" msgid "Set garrison combat formation to 'Grouped'" msgstr "Задай гарнизонна бойна Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ \"Групиране\"" msgid "Exit Castle Options" msgstr "Изход от Опции на замъка" msgid "Castle Options" msgstr "Опции на замъка" msgid "Not enough resources to recruit creatures." msgstr "ÐÑма доÑтатъчно реÑурÑи за набиране на ÑъщеÑтва." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Ðе можеш да набираш в момента, твоите редици Ñа пълни." msgid "No creatures available for purchase." msgstr "ÐÑма налични ÑъщеÑтва за покупка." msgid "Recruit Creatures" msgstr "Вербувай ÑъщеÑтва" msgid "Hire all creatures in the town." msgstr "Ðаеми вÑички ÑъщеÑтва в града." msgid "Max" msgstr "МакÑимално" msgid "Available" msgstr "Ðалични" msgid "Town Population Information and Statistics" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¸ ÑтатиÑтика за наÑелението на града" msgid "Damage" msgstr "Щети" msgid "HP" msgstr "Живот" msgid "Growth" msgstr "РаÑтеж" msgid "week" msgstr "Ñедмица" msgid "View World" msgstr "Виж Света" msgid "View the entire world." msgstr "Виж Ñ†ÐµÐ»Ð¸Ñ ÑвÑÑ‚." msgid "Puzzle" msgstr "Пъзел" msgid "View the obelisk puzzle." msgstr "Виж обелиÑка Ñ Ð¿ÑŠÐ·ÐµÐ»Ð°." msgid "Scenario Information" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° ÑценариÑ" msgid "View information on the scenario you are currently playing." msgstr "Виж Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° ÑценариÑ, който играеш в момента." msgid "Dig for the Ultimate Artifact." msgstr "Изкопай най-Ð´Ð¾Ð±Ñ€Ð¸Ñ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚." msgid "Digging" msgstr "Изкопаване" msgid "Arena" msgstr "Ðрена" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Влизаш на арената и Ñе изправÑш Ñрещу глутница жеÑтоки лъвове. Ти ги " "побеждаваш убедително, под бурните възглаÑи на тълпата. Впечатлен от твоите " "умениÑ, възраÑтниÑÑ‚ треньор на гладиатори Ñе ÑъглаÑÑва да те обучи на умение " "по твой избор." msgid "Attack Skill" msgstr "Ðтака" msgid "Defense Skill" msgstr "Защита" msgid "Shots" msgstr "ИзÑтрели" msgid "Shots Left" msgstr "ОÑÑ‚. изÑтрели" msgid "Hit Points" msgstr "Живот" msgid "Hit Points Left" msgstr "ОÑÑ‚. живот" msgid "You can't afford to upgrade your troops!" msgstr "Ðе можеш да Ñи позволиш да надграждиш войÑките Ñи!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Твоите войÑки могат да бъдат подобрени, но това ще ти Ñтрува Ñкъпо. ИÑкаш ли " "да ги надÑтроиш?" msgid "Are you sure you want to dismiss this army?" msgstr "Сигурен ли Ñи, че иÑкаш да разпуÑнеш тази армиÑ?" msgid "Upgrade" msgstr "Подобри" msgid "Upgrade your troops." msgstr "Ðадградете войÑките Ñи." msgid "Dismiss" msgstr "Oтпрати" msgid "Dismiss this army." msgstr "РазпуÑни тази войÑка." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Група от %{monster} Ñ Ð¶ÐµÐ»Ð°Ð½Ð¸Ðµ за по-голÑма Ñлава желае да Ñе приÑъедини към " "теб.\n" "Приемаш ли?" msgid "Followers" msgstr "ПоÑледователи" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} е очарован от Ñ‚Ð²Ð¾Ñ Ð´Ð¸Ð¿Ð»Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡ÐµÐ½ език и предлага да Ñе приÑъедини " "към твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ñрещу Ñумата от %{gold} злато.\n" "Приемаш ли?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "СъзданиÑта Ñа повлиÑни от твоÑта дипломатичен\n" "език, и ти правÑÑ‚ оферта:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} от %{total} %{monster} ще Ñе приÑъедини към твоÑта армиÑ, а " "оÑтаналите ще те оÑтавÑÑ‚ на мира Ñрещу Ñумата от %{gold} злато.\n" "Приемаш ли?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Ð’Ñички %{offer} от %{monster} ще Ñе приÑъединÑÑ‚ към твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ñрещу " "Ñумата от %{gold} злато.\n" "Приемаш ли?" msgid "(Rate: %{percent})" msgstr "(Оценка: %{percent})" msgid "off" msgstr "изкл" msgid "Music" msgstr "Музика" msgid "Effects" msgstr "Ефекти" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Продължение" msgid "External" msgstr "Външна" msgid "Music Type" msgstr "Източник" msgid "3D Audio" msgstr "3D Звук" msgid "Toggle ambient music level." msgstr "Превключване на нивото на околната музика." msgid "Toggle foreground sounds level." msgstr "Превключване на нивото на звуците на преден план." msgid "Change the type of music." msgstr "Промени вида на музиката." #, fuzzy msgid "Toggle the 3D effect of foreground sounds." msgstr "Превключване на 3D ефекти на звуци на преден план." msgid "Build a new ship:" msgstr "Изгради нов кораб:" msgid "Resource cost:" msgstr "Разходи за реÑурÑи:" msgid "Total: " msgstr "Общо: " msgid "Need: " msgstr "Още: " msgid "New Game" msgstr "Ðова Игра" msgid "Start a single or multi-player game." msgstr "Започни игра за един или нÑколко играча." msgid "Load Game" msgstr "Зареди Игра" msgid "Load a previously saved game." msgstr "Зареди запазена игра." msgid "Save Game" msgstr "Запази играта" msgid "Save the current game." msgstr "Запази текущата игра." msgid "Quit" msgstr "ÐапуÑкане" msgid "Quit out of Heroes of Might and Magic II." msgstr "ÐапуÑни Heroes of Might and Magic II." msgid "Language" msgstr "Език" msgid "Graphics" msgstr "Графика" msgid "Black & White" msgstr "Черно-бÑл" msgid "Mouse Cursor" msgstr "Показалец" msgid "Color" msgstr "Цветен" msgid "Text Support" msgstr "Доп. информациÑ" msgid "Change the language of the game." msgstr "ПромÑна на езика на играта." msgid "Select Game Language" msgstr "Език на играта" msgid "Change the graphics settings of the game." msgstr "Промени графичните наÑтройки на играта." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Включи или изключи Ñ†Ð²ÐµÑ‚Ð½Ð¸Ñ ÐºÑƒÑ€Ñор. Това е Ñамо еÑтетичеÑки избор." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Превключи режима на текÑтова поддръжка, за да изведеш допълнителна " "Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° прозорци и ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð² играта." msgid "" "Map\n" "Difficulty" msgstr "" "ТрудноÑÑ‚\n" "на Карта" msgid "" "Game\n" "Difficulty" msgstr "" "ТрудноÑÑ‚\n" "на играта" msgid "Rating" msgstr "КлаÑиране" msgid "Map Size" msgstr "Размер на карта" msgid "Opponents" msgstr "Противници" msgid "Class" msgstr "Вид" msgid "" "Victory\n" "Conditions" msgstr "" "УÑÐ»Ð¾Ð²Ð¸Ñ Ð·Ð°\n" "Победа" msgid "" "Loss\n" "Conditions" msgstr "" "УÑÐ»Ð¾Ð²Ð¸Ñ Ð·Ð°\n" "Загуба" msgid "First select recipients!" msgstr "Първо избери получатели!" msgid "You cannot select %{resource}!" msgstr "Ðе можеш да избереш %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "ЗаÑтрелÑй %{monster}" msgid "Select Recipients" msgstr "Избери Получатели" msgid "Your Funds" msgstr "Твоите ÑредÑтва" msgid "Planned Gift" msgstr "Планиран подарък" msgid "Gift from %{name}" msgstr "Подарък от %{name}" msgid "Resolution" msgstr "РезолюциÑ" msgid "Fullscreen" msgstr "ЦÑл екран" msgid "window|Mode" msgstr "Режим" msgid "Windowed" msgstr "Ð’ прозорец" msgid "V-Sync" msgstr "V-ÑинхронизациÑ" msgid "FPS" msgstr "" msgid "System Info" msgstr "СиÑтемна информациÑ" msgid "Change the resolution of the game." msgstr "ПромÑна на резолюциÑта на играта." msgid "Select Game Resolution" msgstr "Избери Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° играта" msgid "Toggle between fullscreen and windowed modes." msgstr "Превключи между цÑл екран и прозорец." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "ОпциÑта V-Sync може да бъде активирана за разрешаване на проблеми Ñ Ñ‚Ñ€ÐµÐ¿Ñ‚ÐµÐ½Ðµ " "на нÑкои монитори." msgid "Show extra information such as FPS and current time." msgstr "Показване на допълнителна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ ÐºÐ°Ñ‚Ð¾ FPS и текущо време." msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" #, fuzzy msgid "Event: " msgstr "Събитие" msgid "Hot Keys:" msgstr "Бързи клавиши:" msgid "Hide" msgstr "Скрий" msgid "Show" msgstr "Покажи" msgid "Interface" msgstr "ИнтерфейÑ" msgid "Interface Type" msgstr "ИнтерфейÑ" msgid "Toggle the type of interface you want to use." msgstr "Превключи типа на интерфейÑа, който иÑкаш да използваш." msgid "Toggle interface visibility." msgstr "Превключва видимоÑтта на интерфейÑа." msgid "Scroll Speed" msgstr "СкороÑÑ‚ на Превъртане" msgid "Sets the speed at which you scroll the window." msgstr "Задава ÑкороÑтта, Ñ ÐºÐ¾Ñто превърташ прозореца." msgid "Select Game Language:" msgstr "Език на играта:" #, fuzzy msgid "Select Language:" msgstr "Език на играта:" msgid "Click to choose the selected language." msgstr "Кликни, за да предпочетеш Ð¸Ð·Ð±Ñ€Ð°Ð½Ð¸Ñ ÐµÐ·Ð¸Ðº." msgid "%{name} has gained a level." msgstr "%{name} Ñпечели ниво." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Ðаучи %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} е придобил ниво.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Можеш да научиш или:\n" "%{skill1}\n" "или\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "без" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "МолÑ, прегледай нашите изиÑкани Ñтоки. Ðко иÑкаш да предложиш размÑна, " "щракни върху артикулите, Ñ ÐºÐ¾Ð¸Ñ‚Ð¾ иÑкаш да размениш и за които иÑкаш да " "размениш." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "МолÑ, провери твите фини Ñтоки. Ðко иÑкаш да предложиш размÑна, щракни върху " "артикулите, Ñ ÐºÐ¾Ð¸Ñ‚Ð¾ иÑкаш да размениш и за които иÑкаш да размениш." msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Мога да ти предложа %{count} за 1 единица от %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Мога да ти предложа 1 единица %{resto} за %{count} единици %{resfrom}." msgid "Min" msgstr "Минимално" msgid "Qty to trade" msgstr "КоличеÑтво за търговиÑ" msgid "Trading Post" msgstr "ТърговÑки щанд" msgid "Your Resources" msgstr "Твоите реÑурÑи" msgid "Available Trades" msgstr "Ðалични Ñделки" msgid "guarded by %{count} %{monster}" msgstr "охранÑвано от %{count} %{monster}" msgid "guarded by " msgstr "охранÑван от " msgid "(available: %{count})" msgstr "(наличен: %{count})" msgid "(empty)" msgstr "(празен)" msgid "already learned" msgstr "вече научен" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Дърво на познанието" #, fuzzy msgid "already claimed" msgstr "вече научен" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "вече владее това умение" msgid "already has max skills" msgstr "вече има макÑимални умениÑ" msgid "(already visited)" msgstr "(вече поÑетен)" msgid "(not visited)" msgstr "(не поÑещаван)" msgid "%{color} Barrier" msgstr "%{color} Бариера" msgid "(tent visited)" msgstr "(поÑетена палатка)" msgid "%{color} Tent" msgstr "%{color} палатка" msgid "Road" msgstr "Път" msgid "(digging ok)" msgstr "(добра за копаене)" msgid "(no digging)" msgstr "(без копаене)" msgid "penalty: %{cost}" msgstr "неуÑтойка: %{cost}" msgid "Defenders:" msgstr "Защитници:" msgid "Unknown" msgstr "неизвеÑтен" msgid "heroQuickInfo|(Level %{level})" msgstr "(Ðиво %{level})" msgid "Attack:" msgstr "Ðтака:" msgid "Defense:" msgstr "Защита:" msgid "Spell Power:" msgstr "Маг. Ñила:" msgid "Knowledge:" msgstr "ЗнаниÑ:" msgid "Spell Points:" msgstr "МагиÑ:" msgid "Move Points:" msgstr "Ход:" msgid "Uncharted Territory" msgstr "ÐеизÑледвана териториÑ" msgid "Cost per troop:" msgstr "Цена на единица:" msgid "Available: %{count}" msgstr "Ðалични: %{count}" msgid "Number to buy:" msgstr "Покупка на:" msgid "Recruit selected monsters." msgstr "Вербувай избраните чудовища." msgid "Select maximum monsters to be recruited." msgstr "Избери макÑимален брой чудовища, които да бъдат наети." msgid "Select only 1 monster to be recruited." msgstr "Избери Ñамо 1 чудовище, което да бъде наето." #, fuzzy msgid "Select this game resolution." msgstr "Избери Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° играта" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Изберете Ñ€ÐµÐ·Ð¾Ð»ÑŽÑ†Ð¸Ñ Ð½Ð° играта:" msgid "Click to apply the selected resolution." msgstr "Кликни, за да приложиш избраната резолюциÑ." msgid "Click to apply the entered text." msgstr "Кликни, за да приложиш Ð²ÑŠÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ñ‚ÐµÐºÑÑ‚." msgid "Click to open the Virtual Keyboard dialog." msgstr "Щракни, за да отвориш Ð´Ð¸Ð°Ð»Ð¾Ð³Ð¾Ð²Ð¸Ñ Ð¿Ñ€Ð¾Ð·Ð¾Ñ€ÐµÑ† за виртуална клавиатура." msgid "Open Virtual Keyboard" msgstr "Отвори виртуална клавиатура" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "Колко единици ще премеÑтите?" #, fuzzy msgid "Select how many units to separate into:" msgstr "Избери град за приÑтанище." msgid "Map: " msgstr "Карта: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "МеÑец: " msgid ", Week: " msgstr ", Седмица: " msgid ", Day: " msgstr ", Ден: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "МеÑтоположение: " msgid "Are you sure you want to delete file:" msgstr "Сигурен ли Ñи, че иÑкаш да изтриеш файла:" msgid "Warning" msgstr "Внимание" msgid "Click to save the current game." msgstr "Кликни, за да запазиш текущата игра." msgid "Click to load a previously saved game." msgstr "Кликни, за да заредиш предварително запазена игра." msgid "File to Save:" msgstr "Файл за запазване:" msgid "File to Load:" msgstr "Файл за зареждане:" #, fuzzy msgid "Terrain object" msgstr "Режим терен" msgid "Accept the choice made." msgstr "Приемете Ð½Ð°Ð¿Ñ€Ð°Ð²ÐµÐ½Ð¸Ñ Ð¸Ð·Ð±Ð¾Ñ€." msgid "Select Skill:" msgstr "Избери умение:" msgid "Select Spell:" msgstr "Избери заклинание:" msgid "Select Artifact:" msgstr "Избери артефакт:" msgid "Select Monster:" msgstr "Избери чудовище:" msgid "Select Hero:" msgstr "Избери герой:" msgid "race|Random" msgstr "Случаен" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Кликни, за да приложиш избраната резолюциÑ." #, fuzzy msgid "%{color} %{race}" msgstr "%{color} %{race} герой" msgid "You will place" msgstr "" #, fuzzy msgid "Click to select this class." msgstr "Кликни тук, за да избереш кой Ñценарий да играеш." #, fuzzy msgid "Click to select this color." msgstr "Кликни тук, за да избереш кой Ñценарий да играеш." #, fuzzy msgid "Select Treasure:" msgstr "Избери герой:" #, fuzzy msgid "Select Ocean Object:" msgstr "ОкеанÑки обекти" #, fuzzy msgid "Castle/town placing" msgstr "Опции на замъка" msgid "doubleLinedRace|Neutral" msgstr "" "Ðеутра-\n" "лен" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "Кликни, за да приложиш избраната резолюциÑ." #, fuzzy msgid "Click to select town placing." msgstr "Кликни, за да покажеш ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´." #, fuzzy msgid "Click to select castle placing." msgstr "Кликни тук, за да избереш кой Ñценарий да играеш." #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{race} герой" msgid "race|Neutral" msgstr "Ðеутрален" #, fuzzy msgid "Select Dwelling:" msgstr "Избери заклинание:" #, fuzzy msgid "Select Landscape Object:" msgstr "ОкеанÑки обекти" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "РеÑурÑ" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name} %{race}" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "Кликни тук, за да избереш кой Ñценарий да играеш." #, fuzzy msgid "Select Mountain Object:" msgstr "ОкеанÑки обекти" #, fuzzy msgid "Select Rock Object:" msgstr "ОкеанÑки обекти" #, fuzzy msgid "Select Tree Object:" msgstr "ОкеанÑки обекти" #, fuzzy msgid "Select Power Up Object:" msgstr "ОкеанÑки обекти" #, fuzzy msgid "Select Adventure Object:" msgstr "ОкеанÑки обекти" msgid "Players Icon" msgstr "Брой на играчи" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Показва колко общо играчи има в ÑценариÑ. Ð’Ñички позиции, които не Ñа заети " "от хора, ще бъдат заети от компютърни играчи." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Показва дали картата\n" "е малък (36 x 36), Ñреден\n" "(72 x 72), голÑм (108 x 108),\n" "или изключително голÑм размер (144 x 144)." msgid "Size Icon" msgstr "Размер на карта" msgid "Map Type" msgstr "Тип на карта" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Показва дали картата е направена за верÑиÑта на играта \"ÐаÑледените войни\" " "или за \"Цената на лоÑлноÑтта\"." msgid "Map Type:\n" msgstr "Тип на карта:\n" msgid "The Succession Wars" msgstr "Войните за наÑледÑтво" msgid "The Price of Loyalty" msgstr "Цената на лоÑлноÑтта" #, fuzzy msgid "Resurrection" msgstr "ВъзкреÑÑване" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Език" msgid "Lose all your heroes and towns." msgstr "Ðко загубиш вÑичките Ñи герои и градове." msgid "Lose a specific town." msgstr "ОÑвободи определен град." msgid "Lose a specific hero." msgstr "ОÑвободи определен герой." msgid "Run out of time. Fail to win by a certain point." msgstr "Времето Ñвърши. Загуба в този момент." msgid "Loss Condition" msgstr "СъÑтоÑние на загуба" msgid "Defeat all enemy heroes and towns." msgstr "Победи вÑички вражеÑки герои и градове." msgid "Capture a specific town." msgstr "Превземи конкретен град." msgid "Defeat a specific hero." msgstr "Победи конкретен герой." msgid "Find a specific artifact." msgstr "Ðамери конкретен артефакт." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "ТвоÑта Ñтрана побеждава противниковата Ñтрана." msgid "Accumulate a large amount of gold." msgstr "Ðатрупай голÑмо количеÑтво злато." msgid "Victory Condition" msgstr "УÑловие за победа" msgid "Map difficulty:" msgstr "ТрудноÑÑ‚ на карта:" msgid "N" msgstr "С" #, fuzzy msgid "No maps exist at that size." msgstr "ÐÑма карти в този размер" msgid "Small Maps" msgstr "Малки карти" msgid "View only maps of size small (36 x 36)." msgstr "Преглеждайте Ñамо карти Ñ Ð¼Ð°Ð»ÑŠÐº размер (36 x 36)." msgid "Medium Maps" msgstr "Средни карти" msgid "View only maps of size medium (72 x 72)." msgstr "Преглеждайте Ñамо карти ÑÑŠÑ Ñреден размер (72 x 72)." msgid "Large Maps" msgstr "Големи карти" msgid "View only maps of size large (108 x 108)." msgstr "Преглеждайте Ñамо карти Ñ Ð³Ð¾Ð»Ñм размер (108 x 108)." msgid "Extra Large Maps" msgstr "Много големи карти" msgid "View only maps of size extra large (144 x 144)." msgstr "Преглеждайте Ñамо карти Ñ Ð¼Ð½Ð¾Ð³Ð¾ големи размери (144 x 144)." msgid "All Maps" msgstr "Ð’Ñички карти" msgid "View all maps, regardless of size." msgstr "Виж вÑички карти, незавиÑимо от размера." msgid "Selected Name" msgstr "Избрано име" msgid "The name of the currently selected map." msgstr "Името на текущо избраната карта." msgid "Selected Map Difficulty" msgstr "Избрана трудноÑÑ‚ на карта" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "ТрудноÑтта на картата на текущо избраната карта. ТрудноÑтта на картата Ñе " "Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð¾Ñ‚ дизайнера на ÑценариÑ. По-трудните карти може да включват повече " "или по-Ñилни врагове, по-малко реÑурÑи или други Ñпециални уÑловиÑ, които " "правÑÑ‚ нещата по-трудни за играча." msgid "Selected Description" msgstr "Избрано опиÑание" msgid "The description of the currently selected map." msgstr "ОпиÑание на избраната в момента карта." msgid "Jump" msgstr "Скок" msgid "Hero Speed" msgstr "СкороÑÑ‚ на ГероÑ" msgid "Don't Show" msgstr "Ðе показвай" msgid "Enemy Speed" msgstr "СкороÑÑ‚ на Противник" msgid "Auto Resolve" msgstr "Ðвто" msgid "Auto, No Spells" msgstr "Ðвто, без магий" msgid "Battles" msgstr "СражениÑ" #, fuzzy msgid "combatMode|Manual" msgstr "Ръчно" msgid "Change the speed at which your heroes move on the main screen." msgstr "Промени ÑкороÑтта, Ñ ÐºÐ¾Ñто твоите герои Ñе движат на Ð³Ð»Ð°Ð²Ð½Ð¸Ñ ÐµÐºÑ€Ð°Ð½." #, fuzzy msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Задава ÑкороÑтта, коÑто И.И. героите Ñе движат. Можеш Ñъщо да избереш да не " "гледаш движението на И.И.." msgid "Change the interface settings of the game." msgstr "Промени Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð½Ð°Ñтройките на играта." msgid "Interface Settings" msgstr "Ð˜Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐаÑтройки" msgid "Toggle instant battle mode." msgstr "Превключи режима на незабавна битка." msgid "Att." msgstr "Ðтак." msgid "Def." msgstr "Защ." msgid "Power" msgstr "Сила" msgid "Knowl" msgstr "Зна." msgid "1st" msgstr "1ви" msgid "2nd" msgstr "2ри" msgid "3rd" msgstr "3ти" msgid "4th" msgstr "4ти" msgid "5th" msgstr "5ти" msgid "6th" msgstr "6ти" msgid "Oracle: Player Rankings" msgstr "Оракул: КлаÑиране на играчите" msgid "Thieves' Guild: Player Rankings" msgstr "Ð“Ð¸Ð»Ð´Ð¸Ñ Ð½Ð° крадците: КлаÑиране на играчите" msgid "Number of Towns:" msgstr "Брой на градовете:" msgid "Number of Castles:" msgstr "Брой на замъците:" msgid "Number of Heroes:" msgstr "Брой на героите:" msgid "Gold in Treasury:" msgstr "Злато в хазната:" msgid "Wood & Ore:" msgstr "Дърво и руда:" msgid "Gems, Cr, Slf & Mer:" msgstr "Кам, Кр, СÑÑ€ и Жив:" msgid "Obelisks Found:" msgstr "Ðамерени обелиÑки:" msgid "Artifacts:" msgstr "Ðртефакти:" msgid "Total Army Strength:" msgstr "Обща Ñила на армиÑта:" msgid "Income:" msgstr "Приходи:" msgid "Best Hero:" msgstr "Ðай-добър герой:" msgid "Best Hero Stats:" msgstr "Ðай-добри ÑтатиÑтики за герои:" msgid "Personality:" msgstr "ЛичноÑÑ‚:" msgid "Best Monster:" msgstr "Ðай-добро чудовище:" #, fuzzy msgid "Random Castle Name" msgstr "Случаен замък" #, fuzzy msgid "Random Town Name" msgstr "Случаен град" #, fuzzy msgid "Allow Castle build" msgstr "Замък в облаците" #, fuzzy msgid "Default Buildings" msgstr "дейÑтвие по подразбиране" #, fuzzy msgid "Default Army" msgstr "дейÑтвие по подразбиране" #, fuzzy msgid "Castle Army" msgstr "Замък" #, fuzzy msgid "Town Army" msgstr "Град" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Губиш героÑ: %{name}." msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Лента за ÑъобщениÑ" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Лента за ÑъобщениÑ" #, fuzzy msgid "Click to save the Event properties." msgstr "Кликни, за да запазиш текущата игра." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "РеÑурÑ" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Кликни, за да запазиш текущата игра." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Ден: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Кликни, за да запазиш текущата игра." #, fuzzy msgid "Add Event" msgstr "Събитие" #, fuzzy msgid "Add an additional event." msgstr "Допълнително програмиране" #, fuzzy msgid "Edit Event" msgstr "Събитие" #, fuzzy msgid "Edit an existing event." msgstr "Зареди ÑъщеÑтвуваща карта." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "Зареди ÑъщеÑтвуваща карта." #, fuzzy msgid "Effects:" msgstr "Ефекти" #, fuzzy msgid "Conditions:" msgstr "" "УÑÐ»Ð¾Ð²Ð¸Ñ Ð·Ð°\n" "Загуба" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "Опит" msgid "Artifact" msgstr "Ðртефакт" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Избери артефакт:" #, fuzzy msgid "Delete an artifact from the event." msgstr "Зареди ÑъщеÑтвуваща карта." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Избери умение:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Чудовищата не могат да Ñе поÑтавÑÑ‚ върху вода." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Това заклинание не може да Ñе направи на кораб." #, fuzzy msgid "%{objects} must be placed on water." msgstr "Това заклинание не може да Ñе направи на кораб." #, fuzzy msgid "Objects cannot be placed outside the map." msgstr "Това заклинание не може да Ñе направи на кораб." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Това заклинание не може да Ñе направи на кораб." #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Сигурен ли Ñи, че иÑкаш да Ñъздадеш нова карта? (Ð’Ñички незапазени промени в " "текущата карта ще бъдат загубени.)" msgid "Editor" msgstr "Редактор" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Сигурен ли Ñи, че иÑкаш да заредиш нова карта? (Ð’Ñички незапазени промени в " "текущата карта ще бъдат загубени.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Сигурен ли Ñи, че иÑкаш да Ñъздадеш нова карта? (Ð’Ñички незапазени промени в " "текущата карта ще бъдат загубени.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "РЕСТÐРТ" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Сигурен ли Ñи, че иÑкаш да Ñъздадеш нова карта? (Ð’Ñички незапазени промени в " "текущата карта ще бъдат загубени.)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "РеÑтарт" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Сигурен ли Ñи, че иÑкаш да заредиш нова карта? (Ð’Ñички незапазени промени в " "текущата карта ще бъдат загубени.)" #, fuzzy msgid "Create a new map from scratch." msgstr "нова карта от начало" msgid "New Map" msgstr "Ðова Карта" msgid "Load Map" msgstr "Зареди Карта" msgid "Load an existing map." msgstr "Зареди ÑъщеÑтвуваща карта." msgid "Save Map" msgstr "Запазване на картата" msgid "Save the current map." msgstr "Запазете текущата карта." msgid "Quit out of the map editor." msgstr "Излез от редактора на карти." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Кликни, за да Ñе върнеш към главното меню." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Случаен върховен артефакт" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "Ñ 1 артефакт." msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "Пътища" msgid "Streams" msgstr "Потоци" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Това заклинание не може да Ñе направи на кораб." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "ЗапазениÑÑ‚ файл е повреден." msgid "Unable to locate data directory to save the map." msgstr "" #, fuzzy msgid "Unable to create a directory to save the map." msgstr "Използва Ñе за изтриване на обекти от картата." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Използва Ñе за изтриване на обекти от картата." #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Сигурен ли Ñи че иÑкаш да презапишеш запазената игра Ñ Ñ‚Ð¾Ð²Ð° име?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "Файл за запазване:" #, fuzzy msgid "Used to place %{object}." msgstr "Използва Ñе за поÑтавÑне на герой." #, fuzzy msgid "Select object type" msgstr "ОкеанÑки обекти" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Кликни тук, за да избереш кой Ñценарий да играеш." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "МолÑ, избери друг герой." msgid "" "Cell\n" "Details" msgstr "" #, fuzzy msgid "Erase" msgstr "Режим на изтриване" msgid "Mountains" msgstr "Планини" #, fuzzy msgid "Rocks" msgstr "Скала" msgid "Trees" msgstr "Дървета" #, fuzzy msgid "Water Objects" msgstr "Обекти от пущинака" #, fuzzy msgid "Miscellaneous" msgstr "ФиниаÑ" msgid "Artifacts" msgstr "Ðртефакти" #, fuzzy msgid "Dwellings" msgstr "Хобити" msgid "Mines" msgstr "Мини" #, fuzzy msgid "Power-ups" msgstr "Сила" msgid "Treasures" msgstr "Съкровища" msgid "Heroes" msgstr "Герой" msgid "Towns" msgstr "Градове" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "ОкеанÑки обекти" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Ðачертава терена\n" "%{size} на %{size} квадратни Ñтъпки." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Изтрива обекти\n" "%{size} на %{size} квадратни Ñтъпки." msgid "Small Brush" msgstr "Малка четка" msgid "Medium Brush" msgstr "Средна четка" msgid "Large Brush" msgstr "ГолÑма четка" msgid "Area Fill" msgstr "Попълване на облаÑÑ‚" msgid "Used to click and drag for filling in large areas." msgstr "Използва Ñе кликване и плъзгане за запълване на големи облаÑти." msgid "Clear Area" msgstr "ИзчиÑтва облаÑÑ‚" msgid "Used to click and drag for clearing large areas." msgstr "Използва Ñе кликване и плъзгане за изчиÑтване на големи облаÑти." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Разходи %{rate} пъти нормално движение за вÑички герои. (Откриването на Ð¿ÑŠÑ‚Ñ " "намалÑва или елиминира наказанието.)" msgid "Traversable only by boat." msgstr "Преминаване Ñамо Ñ Ð»Ð¾Ð´ÐºÐ°." msgid "No special modifiers." msgstr "Без Ñпециални модификатори." msgid "Toggle the erasure of %{type} objects." msgstr "Превключи изтриването на %{type} обекти." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Обекти от този тип ще бъдат изтрити Ñ Ð¸Ð½Ñтрумента Изтриване. Щракни Ñ Ð»ÐµÐ²Ð¸Ñ " "бутон тук, за да премахнеш отметката от този тип. ÐатиÑни и задръж този " "бутон, за да демаркираш вÑички други типове обекти." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Обекти от този тип ÐЯМРда бъдат изтривани Ñ Ð¸Ð½Ñтрумента за изтриване. " "Щракни Ñ Ð»ÐµÐ²Ð¸Ñ Ð±ÑƒÑ‚Ð¾Ð½ тук, за да избереш този тип. ÐатиÑни и задръж този " "бутон, за да избереш вÑички други типове обекти." msgid "Terrain Mode" msgstr "Режим терен" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" "Използва Ñе за начертаване на оÑновната трева, мръÑотиÑ, вода и Ñ‚.н. върху " "картата." #, fuzzy msgid "Landscape Objects Mode" msgstr "Обектен режим" #, fuzzy msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Използва Ñе за поÑтавÑне на обекти (планини, дървета, Ñъкровища и др.) върху " "картата." msgid "Detail Mode" msgstr "Подробен режим" #, fuzzy msgid "Used for special editing of action objects." msgstr "Използва Ñе за Ñпециално редактиране на чудовища, герои и градове." #, fuzzy msgid "Adventure Objects Mode" msgstr "Опции за приключениÑ" #, fuzzy msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Използва Ñе за поÑтавÑне на обекти (планини, дървета, Ñъкровища и др.) върху " "картата." #, fuzzy msgid "Kingdom Objects Mode" msgstr "Обектен режим" #, fuzzy msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Използва Ñе за поÑтавÑне на обекти (планини, дървета, Ñъкровища и др.) върху " "картата." #, fuzzy msgid "Monsters Mode" msgstr "Чудовища" #, fuzzy msgid "Used to place monsters on the map." msgstr "" "Използва Ñе за поÑтавÑне\n" "на група чудовища." msgid "Allows you to draw streams by clicking and dragging." msgstr "ПозволÑва ти да риÑуваш потоци чрез кликване и плъзгане." msgid "Stream Mode" msgstr "Режим на предаване" msgid "Allows you to draw roads by clicking and dragging." msgstr "ПозволÑва ти да риÑуваш пътища чрез кликване и плъзгане." msgid "Road Mode" msgstr "Пътен режим" msgid "Erase Mode" msgstr "Режим на изтриване" msgid "Used to erase objects from the map." msgstr "Използва Ñе за изтриване на обекти от картата." msgid "Change between zoom and normal view." msgstr "ПромÑна между мащабиране и нормален изглед." msgid "Magnify" msgstr "Увеличи" msgid "Undo" msgstr "ОтмÑна" msgid "Undo your last action." msgstr "Отмени поÑледното Ñи дейÑтвие." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "Отмени поÑледното Ñи дейÑтвие." msgid "Edit map title, description, and other general information." msgstr "Редактирай заглавието на картата, опиÑанието и друга обща информациÑ." msgid "Specifications" msgstr "Спецификации" msgid "File Options" msgstr "Опции за файлове" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Отвори менюто Ñ Ð¾Ð¿Ñ†Ð¸Ð¸ за файлове, където можеш да запазваш или зареждаш " "карти или да излезеш от редактора." msgid "View the editor system options, which let you customize the editor." msgstr "" "Виж ÑиÑтемните опции на редактора, които ти позволÑват да перÑонализираш " "редактора." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Създай карта Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð° %{size} квадрата и виÑочина %{size} квадрата." msgid "Cancel back to the New Map menu." msgstr "Отказ обратно към Меню за нова карта." msgid "Cancel back to the main menu." msgstr "Отказ обратно към главното меню." msgid "From Scratch" msgstr "От начало" msgid "Start from scratch with a blank map." msgstr "Започни от начало Ñ Ð¿Ñ€Ð°Ð·Ð½Ð° карта." msgid "Create a randomly generated map." msgstr "Създай произволно генерирана карта." msgid "Random" msgstr "Случаен" msgid "Cancel back to the Map Editor main menu." msgstr "Отказ обратно към главното меню на Ð¡ÑŠÐ·Ð´Ð°Ñ‚ÐµÐ»Ñ Ð½Ð° карти." msgid "No maps available!" msgstr "ÐÑма налични карти!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{color} %{race} герой" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{name1} Ñреща %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{color} %{race} герой" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{color} %{race} герой" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{name1} Ñреща %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{name1} Ñреща %{name2}" #, fuzzy msgid "None." msgstr "Без" #, fuzzy msgid "One side defeats another." msgstr "МолÑ, избери друг герой." #, fuzzy msgid "Accumulate gold." msgstr "Ðатрупай %{count} злато." #, fuzzy msgid "Run out of time." msgstr "Излез от редактора на карти." #, fuzzy msgid "alliance|1st" msgstr " Ñъюз" #, fuzzy msgid "alliance|2nd" msgstr " Ñъюз" #, fuzzy msgid "alliance|3rd" msgstr " Ñъюз" #, fuzzy msgid "alliance|4th" msgstr " Ñъюз" #, fuzzy msgid "alliance|5th" msgstr " Ñъюз" #, fuzzy msgid "Special Loss Condition" msgstr "СъÑтоÑние на загуба" #, fuzzy msgid "Special Victory Condition" msgstr "УÑловие за победа" #, fuzzy msgid "Allow standard victory conditions" msgstr "УÑловие за победа" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " Ñъюз" #, fuzzy msgid "{%number} alliance: " msgstr " Ñъюз" #, fuzzy msgid "Gold:" msgstr "Злато" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Избери град за приÑтанище." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Кликни, за да запазиш текущата игра." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Кликни, за да запазиш текущата игра." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Кликни, за да запазиш текущата игра." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Кликни, за да запазиш текущата игра." #, fuzzy msgid "Map Difficulty" msgstr "" "ТрудноÑÑ‚\n" "на Карта" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "МеÑтоположение: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Избрано опиÑание" #, fuzzy msgid "Click to accept the changes made." msgstr "Кликни, за да покажеш ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´." #, fuzzy msgid "Click to edit custom rumors." msgstr "Кликни, за да запазиш текущата игра." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Кликни, за да приложиш избраната резолюциÑ." #, fuzzy msgid "Events" msgstr "Събитие" #, fuzzy msgid "Click to change the language of the map." msgstr "ПромÑна на езика на играта." #, fuzzy msgid "Click to change your map name." msgstr "Кликни, за да покажеш ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´." #, fuzzy msgid "Map Name" msgstr "Размер на карта" #, fuzzy msgid "Click to change the description of the current map." msgstr "ОпиÑание на избраната в момента карта." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "ОпиÑание на избраната в момента карта." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "ОпиÑание на избраната в момента карта." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Тип на карта" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "ТрудноÑтта на картата на текущо избраната карта. ТрудноÑтта на картата Ñе " "Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð¾Ñ‚ дизайнера на ÑценариÑ. По-трудните карти може да включват повече " "или по-Ñилни врагове, по-малко реÑурÑи или други Ñпециални уÑловиÑ, които " "правÑÑ‚ нещата по-трудни за играча." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Избери брой %{resource}:" #, fuzzy msgid "Animation" msgstr "ÐнекÑирам" #, fuzzy msgid "Passability" msgstr "ЛичноÑÑ‚:" #, fuzzy msgid "Toggle animation of the objects." msgstr "Превключи изтриването на %{type} обекти." msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Кликни, за да запазиш текущата игра." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "Допълнително програмиране" #, fuzzy msgid "Edit Rumor" msgstr "Редактор" #, fuzzy msgid "Edit an existing rumor." msgstr "Зареди ÑъщеÑтвуваща карта." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "Зареди ÑъщеÑтвуваща карта." msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "МеÑтоположение: " #, fuzzy msgid "Save Map:" msgstr "Запазване на картата" #, fuzzy msgid "Click to save the current map." msgstr "Кликни, за да запазиш текущата игра." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Кликни, за да запазиш текущата игра." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "ЛеÑна" msgid "difficulty|Normal" msgstr "Ðормална" msgid "difficulty|Hard" msgstr "Трудна" msgid "difficulty|Expert" msgstr "ЕкÑпертна" msgid "difficulty|Impossible" msgstr "Ðевъзможна" msgid "and more..." msgstr "и още..." msgid "Easy" msgstr "ЛеÑно" msgid "Normal" msgstr "Ðормлано" msgid "Hard" msgstr "Трудно" msgid "Campaign Difficulty" msgstr "ТрудноÑÑ‚ на КампаниÑта" #, fuzzy msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Избери тази трудноÑÑ‚, ако предпочиташ иÑториÑта на играта пред " "предизвикателÑтвото. И.И. е по-Ñлаб в Ñравнение Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»Ð½Ð°Ñ‚Ð° трудноÑÑ‚." #, fuzzy msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Избери тази трудноÑÑ‚, за да Ñе наÑладиш на кампаниÑта Ñпоред Ð¾Ñ€Ð¸Ð³Ð¸Ð½Ð°Ð»Ð½Ð¸Ñ " "дизайн." #, fuzzy msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Избери тази трудноÑÑ‚, ако иÑкаш предизвикателÑтво. И.И. е по-Ñилен в " "Ñравнение Ñ Ð½Ð¾Ñ€Ð¼Ð°Ð»Ð½Ð°Ñ‚Ð° трудноÑÑ‚." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "ЧеÑтито!\n" "\n" "Дни: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "ТрудноÑÑ‚: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Резултат: %{score}\n" "\n" "Рейтинг:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Стартирай Ð¸Ð·Ð±Ñ€Ð°Ð½Ð¸Ñ Ñценарий." msgid "View Intro" msgstr "Виж въведение" #, fuzzy msgid "View the intro video for the current state of the campaign." msgstr "Виж въвеждащи видеоклипове за текущото ÑÑŠÑтоÑние на кампаниÑта." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Избери трудноÑтта на кампаниÑта. Това може да бъде намалено по вÑÑко време " "на кампаниÑта." msgid "Restart the current scenario." msgstr "РеÑтартирай Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ñценарий." msgid "Difficulty" msgstr "ТрудноÑÑ‚" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Промени кампаниÑта на по-ниÑка трудноÑÑ‚. ÐÑма да можеш да върнете това Ñлед " "тази точка. ВиÑокиÑÑ‚ резултат ще бъде изчиÑлен въз оÑнова единÑтвено на " "новата трудноÑÑ‚. ИÑкаш ли да продължиш?" msgid "Are you sure you want to restart this scenario?" msgstr "Сигурен ли Ñи, че иÑкаш да реÑтартираш този Ñценарий?" msgid "Campaign Scenario loading failure" msgstr "ÐеуÑпешно зареждане на ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð½Ð° кампаниÑта" msgid "Please make sure that campaign files are correct and present." msgstr "МолÑ, увери Ñе, че файловете на кампаниÑта Ñа правилни и налични." msgid "Days spent" msgstr "Прекарани дни" msgid "The number of days spent on this campaign." msgstr "БроÑÑ‚ дни, прекарани в тази кампаниÑ." msgid "Project Coordination and Core Development" msgstr "ÐšÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð½Ð° проекта и оÑновно развитие" msgid "Development" msgstr "Разработка" msgid "Visit us at " msgstr "ПоÑетете ни на " msgid "QA and Support" msgstr "Гарантиране на качеÑтвото и поддръжка" msgid "Dev and Support" msgstr "Разработка и поддръжка" msgid "Special Thanks to" msgstr "Специални благодарноÑти на" #, fuzzy msgid "and many-many other contributors and supporters!" msgstr "и много-много други поддръжници!" msgid "Support us at" msgstr "Подкрепете ни на" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "Свържете Ñе Ñ Ð½Ð°Ñ Ð½Ð°" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "Ðуждаете Ñе от помощ Ñ Ð¸Ð³Ñ€Ð°Ñ‚Ð°?" msgid "Original project before 0.7" msgstr "Оригинален проект преди 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Екипът на Heroes of Might and Magic II: The Succession Wars" msgid "Designed and Directed" msgstr "Проектиран и режиÑиран" msgid "Programming and Design" msgstr "Програмиране и дизайн" msgid "Executive Producer" msgstr "Изпълнителен продуцент" msgid "Producer" msgstr "Продуцент" msgid "Additional Design" msgstr "Допълнителен дизайн" msgid "Additional Programming" msgstr "Допълнително програмиране" msgid "Musical Production" msgstr "Музикална продукциÑ" msgid "Music and Sound Design" msgstr "Музика и звуков дизайн" msgid "Vocalists" msgstr "ВокалиÑти" msgid "Art Director" msgstr "Ðрт директор" msgid "Assistant Art Director" msgstr "ÐÑиÑтент арт директор" msgid "Artists" msgstr "Художници" msgid "QA Manager" msgstr "Mениджър по качеÑтвото" msgid "QA" msgstr "ÐÑиÑтент по качеÑтвото" msgid "Writing" msgstr "Стил на пиÑане" msgid "Manual and Helpfile" msgstr "РъководÑтво и помощен файл" msgid "Scenarios" msgstr "Сценарии" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Екип на Heroes of Might and Magic II: The Price of Loyalty" msgid "Design Lead" msgstr "Ръководител дизайн" msgid "Designers" msgstr "Дизайнери" msgid "Programming Lead" msgstr "Ръководител програмиране" msgid "Art Lead" msgstr "Ръководител Ðрт" msgid "Playtesters" msgstr "ТеÑтери на играта" msgid "Designer" msgstr "Дизайнер" msgid "Producers" msgstr "Производители" msgid "QA Managers" msgstr "Mениджъри по качеÑтвото" msgid "Sound Design" msgstr "Звуков дизайн" msgid "Town Themes" msgstr "Музикални теми на Градове" msgid "Alto Sax" msgstr "Ðлто ÑакÑ" msgid "Harpsichord and Piano" msgstr "КлавеÑин и пиано" msgid "Basso Vocal" msgstr "БаÑов вокал" msgid "Soprano Vocal" msgstr "Сопрано вокал" msgid "Recorded at %{recordingStudio}" msgstr "ЗапиÑано в %{recordingStudio}" msgid "credits|Manual" msgstr "РуководÑтво по игре" msgid "German Consultant" msgstr "ÐемÑки конÑултант" msgid "Map Designers" msgstr "Дизайнери на картите" msgid "Package Design" msgstr "Дизайн на опаковката" msgid "High Scores" msgstr "КлаÑиране" msgid "Your Name" msgstr "Твоето име" msgid "Unknown Hero" msgstr "Ðезнаен герой" msgid "Standard" msgstr "Стандарт" msgid "View High Scores for Standard Maps." msgstr "Виж виÑоките резултати за Ñтандартни карти." msgid "Campaign" msgstr "КампаниÑ" msgid "View High Scores for Campaigns." msgstr "Вижте виÑоките резултати за кампании." msgid "hotkey|default okay event" msgstr "удобрение по подразбиране" msgid "hotkey|default cancel event" msgstr "отказ по подразбиране" msgid "hotkey|default left" msgstr "лÑво по подразбиране" msgid "hotkey|default right" msgstr "дÑÑно по подразбиране" msgid "hotkey|default up" msgstr "нагоре по подразбиране" msgid "hotkey|default down" msgstr "надолу по подразбиране" msgid "hotkey|toggle fullscreen" msgstr "превключване на цÑл екран" msgid "hotkey|toggle text support mode" msgstr "превключване потдръжка на текÑÑ‚" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "превключване потдръжка на текÑÑ‚" msgid "hotkey|new game" msgstr "нова игра" msgid "hotkey|load game" msgstr "зареди игра" #, fuzzy msgid "hotkey|high scores" msgstr "резултати" msgid "hotkey|credits" msgstr "учаÑтници" msgid "hotkey|standard game" msgstr "Ñтандартна игра" msgid "hotkey|campaign game" msgstr "име на кампаниÑ" msgid "hotkey|multi-player game" msgstr "мултиплейър игра" msgid "hotkey|settings" msgstr "наÑтойки" msgid "hotkey|quit" msgstr "напуÑни" msgid "hotkey|select map" msgstr "избери карта" msgid "hotkey|select small map size" msgstr "избери малка карта" msgid "hotkey|select medium map size" msgstr "избери Ñредна карта" msgid "hotkey|select large map size" msgstr "избери голÑма карта" msgid "hotkey|select extra large map size" msgstr "избери много голÑма карта" msgid "hotkey|select all map sizes" msgstr "избери вÑички карти" #, fuzzy msgid "hotkey|hot seat game" msgstr "двойна игра" msgid "hotkey|battle only game" msgstr "игра Ñамо за битка" msgid "hotkey|choose the original campaign" msgstr "избери оригиналната кампаниÑ" msgid "hotkey|choose the expansion campaign" msgstr "избери кампаниÑта за разширÑване" msgid "hotkey|map editor main menu" msgstr "Ñъздател на карти оÑновно меню" msgid "hotkey|new map menu" msgstr "ново меню на карта" msgid "hotkey|load map menu" msgstr "зареди меню за карта" msgid "hotkey|new map from scratch" msgstr "нова карта от начало" msgid "hotkey|new random map" msgstr "нова Ñлучайна игра" msgid "hotkey|undo last action" msgstr "отмени поÑледното дейÑтвие" msgid "hotkey|redo last action" msgstr "повтори поÑледното дейÑтвие" #, fuzzy msgid "hotkey|open game main menu" msgstr "ново меню на карта" #, fuzzy msgid "hotkey|toggle passability" msgstr "превключи ÑÑŠÑтоÑние" msgid "hotkey|roland campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð½Ð° роланд" msgid "hotkey|archibald campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð½Ð° арчибалд" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "цената на лоÑлноÑтта" msgid "hotkey|voyage home campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð¿ÑŠÑ‚ÑƒÐ²Ð°Ð½Ðµ до дома" msgid "hotkey|wizard's isle campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð½Ð° оÑтрова на магьоÑника" msgid "hotkey|descendants campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð½Ð° потомци" msgid "hotkey|select first campaign bonus" msgstr "избери Ð±Ð¾Ð½ÑƒÑ Ð½Ð° първа кампаниÑ" msgid "hotkey|select second campaign bonus" msgstr "избери Ð±Ð¾Ð½ÑƒÑ Ð½Ð° втора кампаниÑ" msgid "hotkey|select third campaign bonus" msgstr "избери Ð±Ð¾Ð½ÑƒÑ Ð½Ð° трета кампаниÑ" msgid "hotkey|view campaign intro" msgstr "виж въведението на кампаниÑта" msgid "hotkey|select campaign difficulty" msgstr "избери трудноÑÑ‚ на кампаниÑта" msgid "hotkey|restart campaign scenario" msgstr "реÑтартирай ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð½Ð° кампаниÑта" msgid "hotkey|world map left" msgstr "карта на Ñвета влÑво" msgid "hotkey|world map right" msgstr "карта на Ñвета вдÑÑно" msgid "hotkey|world map up" msgstr "карта на Ñвета нагоре" msgid "hotkey|world map down" msgstr "карта на Ñвета надолу" msgid "hotkey|world map up left" msgstr "карта на Ñвета нагоре и влÑво" msgid "hotkey|world map up right" msgstr "карта на Ñвета нагоре и вдÑÑно" msgid "hotkey|world map down left" msgstr "карта на Ñвета надолу и влÑво" msgid "hotkey|world map down right" msgstr "карта на Ñвета надолу и вдÑÑно" msgid "hotkey|save game" msgstr "запази играта" msgid "hotkey|next hero" msgstr "ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³ÐµÑ€Ð¾Ð¹" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³ÐµÑ€Ð¾Ð¹" msgid "hotkey|start hero movement" msgstr "започни движението на героÑ" msgid "hotkey|cast adventure spell" msgstr "направи приключенÑко заклинание." msgid "hotkey|put hero to sleep" msgstr "Ñложи Ð³ÐµÑ€Ð¾Ñ Ð´Ð° Ñпи" msgid "hotkey|next town" msgstr "ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´" msgid "hotkey|end turn" msgstr "завърши хода" msgid "hotkey|file options" msgstr "опции за файл" msgid "hotkey|adventure options" msgstr "опции за приключение" msgid "hotkey|puzzle map" msgstr "карта на пъзела" msgid "hotkey|scenario information" msgstr "Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° ÑценариÑ" msgid "hotkey|dig for artifact" msgstr "копай за артефакт" msgid "hotkey|view world" msgstr "виж Ñвета" msgid "hotkey|kingdom summary" msgstr "резюме за кралÑтвото" msgid "hotkey|default action" msgstr "дейÑтвие по подразбиране" msgid "hotkey|open focus" msgstr "отворен фокуÑ" msgid "hotkey|system options" msgstr "ÑиÑтемни опции" msgid "hotkey|scroll left" msgstr "превъртете налÑво" msgid "hotkey|scroll right" msgstr "превъртете надÑÑно" msgid "hotkey|scroll up" msgstr "превъртете нагоре" msgid "hotkey|scroll down" msgstr "превъртете надолу" msgid "hotkey|toggle control panel" msgstr "превключи ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ð½Ð¸Ñ Ð¿Ð°Ð½ÐµÐ»" msgid "hotkey|toggle radar" msgstr "превключи радар" msgid "hotkey|toggle buttons" msgstr "превключи бутоните" msgid "hotkey|toggle status" msgstr "превключи ÑÑŠÑтоÑние" msgid "hotkey|toggle icons" msgstr "превключи иконите" msgid "hotkey|transfer control to ai" msgstr "прехвърли контрола на ai" msgid "hotkey|retreat from battle" msgstr "отÑтъпление от битка" msgid "hotkey|surrender during battle" msgstr "ÐºÐ°Ð¿Ð¸Ñ‚ÑƒÐ»Ð°Ñ†Ð¸Ñ Ð¿Ð¾ време на битка" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "превключи Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¸Ñ Ñ€ÐµÐ¶Ð¸Ð¼ на битка" #, fuzzy msgid "hotkey|quick combat" msgstr "напуÑни" msgid "hotkey|battle options" msgstr "опции на битка" msgid "hotkey|skip turn in battle" msgstr "пропуÑни ход в битка" msgid "hotkey|cast battle spell" msgstr "направи бойно заклинание" msgid "hotkey|dwelling level 1" msgstr "ниво на жилище 1" msgid "hotkey|dwelling level 2" msgstr "ниво на жилище 2" msgid "hotkey|dwelling level 3" msgstr "ниво на жилище 3" msgid "hotkey|dwelling level 4" msgstr "ниво на жилище 4" msgid "hotkey|dwelling level 5" msgstr "ниво на жилище 5" msgid "hotkey|dwelling level 6" msgstr "ниво на жилище 6" msgid "hotkey|well" msgstr "кладенец" msgid "hotkey|marketplace" msgstr "пазар" msgid "hotkey|mage guild" msgstr "магичеÑка гилдиÑ" msgid "hotkey|shipyard" msgstr "корабоÑтроителница" msgid "hotkey|thieves guild" msgstr "Ð³Ð¸Ð»Ð´Ð¸Ñ Ð½Ð° крадците" msgid "hotkey|tavern" msgstr "кръчма" msgid "hotkey|construction screen" msgstr "екран за изграждане" msgid "hotkey|buy all monsters in well" msgstr "купи вÑички налични чудовища" msgid "hotkey|split stack by half" msgstr "раздели Ñтека наполовина" msgid "hotkey|split stack by one" msgstr "раздели Ñтека на един" msgid "hotkey|join stacks" msgstr "Ñъедини Ñтековете" msgid "hotkey|upgrade troop" msgstr "надгради войÑките" msgid "hotkey|dismiss hero or troop" msgstr "отпрати герой или войÑка" #, fuzzy msgid "hotkey|exchange all troops" msgstr "надгради войÑките" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "ИÑкаш ли да Ñи върнеш контрола от ИИ? Ще има ефектът на ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ñ…Ð¾Ð´." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "ИÑкаш ли да Ñи върнеш контрола от ИИ? Ще има ефектът на ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ñ…Ð¾Ð´." #, fuzzy msgid "Default Actions" msgstr "дейÑтвие по подразбиране" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Карта на Ñвета" #, fuzzy msgid "Battle Screen" msgstr "Екран на героÑ" #, fuzzy msgid "Town Screen" msgstr "Екран на героÑ" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "ЗапазениÑÑ‚ файл е повреден." msgid "Unsupported save format: " msgstr "Ðеподдържан формат за запиÑ: " msgid "Current game version: " msgstr "Текуща верÑÐ¸Ñ Ð½Ð° играта: " msgid "Last supported version: " msgstr "ПоÑледна поддържана верÑиÑ: " msgid "This file contains a save with an invalid game type." msgstr "Този файл Ñъдържа Ð·Ð°Ð¿Ð¸Ñ Ñ Ð½ÐµÐ²Ð°Ð»Ð¸Ð´ÐµÐ½ тип игра." #, fuzzy msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Този файл е запазен за \"Цената на лоÑлноÑтта\", но Ñъответните активи на " "играта не Ñа предоÑтавени на двигателÑ." msgid "This saved game is localized to '" msgstr "Запазената игра е локализирана на \"" msgid "' language, but the current language of the game is '" msgstr "\" език, но текущиÑÑ‚ език на играта е \"" msgid "No save files to load." msgstr "ÐÑма запазени файлове за зареждане." msgid "Hot Seat" msgstr "Горещ Ñтол" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Играй игра на \"Гореща Ñедалка\", при коÑто от 2-6 играчи играÑÑ‚ на един и " "Ñъщ компютър, превключвайки на \"Гореща Ñедалка\", когато им дойде реда." msgid "A single player game playing out a single map." msgstr "Игра за един играч, играещ на една карта." msgid "Standard Game" msgstr "Стандартна Игра" msgid "A single player game playing through a series of maps." msgstr "Игра за един играч, коÑто Ñе играе през поредица от карти." msgid "Campaign Game" msgstr "КампаниÑ" msgid "Multi-Player Game" msgstr "Мултиплейър игра" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Игра за много играчи, Ñ Ð½Ñколко човешки играчи, които Ñе ÑÑŠÑтезават един " "Ñрещу друг на една карта." msgid "fheroes2 Resurrection Team presents" msgstr "fheroes2 Отбор възкрeÑÑване предÑтавÑ" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Добре дошъл в Heroes of Might and Magic II, задвижван от Ð´Ð²Ð¸Ð³Ð°Ñ‚ÐµÐ»Ñ fheroes2!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Добре дошъл в Heroes of Might and Magic II, задвижван от Ð´Ð²Ð¸Ð³Ð°Ñ‚ÐµÐ»Ñ fheroes2! " "Преди да започнеш играта, Ð¼Ð¾Ð»Ñ Ð¸Ð·Ð±ÐµÑ€Ð¸ разделителна ÑпоÑобноÑÑ‚ на играта." msgid "Greetings!" msgstr "ПоздравлениÑ!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Излез от Heroes of Might and Magic II и Ñе върни към операционната ÑиÑтема." msgid "Credits" msgstr "За играта" msgid "View the credits screen." msgstr "Виж екран за играта." msgid "View the high scores screen." msgstr "Виж екрана Ñ Ð²Ð¸Ñоки резултати." #, fuzzy msgid "Create new or modify existing maps." msgstr "Зареди ÑъщеÑтвуваща карта." msgid "Change language, resolution and settings of the game." msgstr "Промени езика, резолюциÑта и наÑтройките на играта." msgid "Game Settings" msgstr "Игрови наÑтройки" #, fuzzy msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "ЛипÑват необходимите видео файлове за прозореца за избор на кампаниÑ. МолÑ, " "уверете Ñе, че вÑички необходими файлове приÑÑŠÑтват в ÑиÑтемата." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Или кампаниÑта на Роланд, или на Ðрчибалд от оригиналната Heroes of Might " "and Magic II." msgid "Original Campaign" msgstr "Оригинална кампаниÑ" msgid "Expansion Campaign" msgstr "ÐšÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð½Ð° продължение" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" "Една от четирите нови кампании от комплекта за разширение на \"Цената на " "ЛоÑлноÑтта\"." msgid "Loading video. Please wait..." msgstr "Видеото Ñе зарежда. ÐœÐ¾Ð»Ñ Ð¸Ð·Ñ‡Ð°ÐºÐ°Ð¹..." msgid "Host" msgstr "Домакин" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Домакинът наÑтройва опциите на играта. Може да има Ñамо един хоÑÑ‚ за мрежова " "игра." msgid "Guest" msgstr "ГоÑÑ‚" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "ГоÑтът чака хоÑтът да наÑтрои играта, Ñлед което автоматично Ñе добавÑ. Може " "да има нÑколко гоÑта за TCP/IP игри." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" #, fuzzy msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Игра за много играчи, Ñ Ð½Ñколко човешки играчи, които Ñе ÑÑŠÑтезават един " "Ñрещу друг на една карта." msgid "Battle Only" msgstr "Само битка" msgid "Setup and play a battle without loading any map." msgstr "ÐаÑтрой и изиграй битка, без да зареждаш никаква карта." #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Играй игра на \"Гореща Ñедалка\", при коÑто от 2-6 играчи играÑÑ‚ на един и " "Ñъщ компютър, превключвайки на \"Гореща Ñедалка\", когато им дойде реда." msgid "2 Players" msgstr "2 Играча" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Играй Ñ 2 човешки играча и по избор Ñ Ð´Ð¾ 4 допълнителни компютърни играча." msgid "3 Players" msgstr "3 Играча" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Играй Ñ 3 човешки играча и по желание до 3 допълнителни компютърни играча." msgid "4 Players" msgstr "4 Играча" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Играй Ñ 4 човешки играча и по избор Ñ Ð´Ð¾ 2 допълнителни компютърни играча." msgid "5 Players" msgstr "5 Играча" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Играй Ñ 5 човешки играча и по избор до 1 допълнителен компютърен играч." msgid "6 Players" msgstr "6 Играча" msgid "Play with 6 human players." msgstr "Играй Ñ 6 човешки играча." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Градът на драконите падна! Вече ти Ñи гоÑподарÑÑ‚ на драконите." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Ти хвана %{name}!\n" "Ти Ñи победител." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Ти залови вражеÑÐºÐ¸Ñ Ð³ÐµÑ€Ð¾Ð¹ %{name}!\n" "ТвоÑта миÑÐ¸Ñ Ðµ завършена." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Ðамери %{name}.\n" "ТвоÑта миÑÐ¸Ñ Ðµ завършена." msgid "Ultimate Artifact" msgstr "Ðай-Ð´Ð¾Ð±Ñ€Ð¸Ñ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Врагът е победен.\n" "ТвоÑта Ñтрана триумфира!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Ðатрупал Ñи над %{count} злато в Ñъкровищницата Ñи.\n" "Ð’Ñички врагове Ñе прекланÑÑ‚ пред твоето богатÑтво и Ñила." msgid "Victory!" msgstr "Победа!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Врагът е пленил %{name}!\n" "Той триумфира." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Врагът е натрупал над %{count} злато в Ñъкровищницата Ñи.\n" "ТрÑбва да Ñе поклониш победен пред неговото богатÑтво и Ñила." msgid "You have been eliminated from the game!!!" msgstr "Ти Ñи елиминиран от играта!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Ти загуби Ð³ÐµÑ€Ð¾Ñ %{name}.\n" "ТвоÑта миÑÐ¸Ñ Ð¿Ñ€Ð¸ÐºÐ»ÑŽÑ‡Ð¸." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Ðе уÑÐ¿Ñ Ð´Ð° завършиш миÑиÑта Ñи навреме.\n" "Ð’Ñичко е загубено." msgid "Defeat!" msgstr "Победен!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "ОÑновен резултат: %{score}\n" "ТрудноÑÑ‚: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Победи вÑички вражеÑки герои и превземи вÑички вражеÑки градове и замъци." msgid "Your side defeats the opposing side." msgstr "ТвоÑта Ñтрана побеждава противниковата Ñтрана." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Времето Ñвърши. (Ðе уÑÐ¿Ñ Ð´Ð° победиш в определеното време.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "ТрÑбва да победиш врага %{enemies}." msgstr[1] "ТрÑбва да победиш вражеÑкиÑÑ‚ Ñъюз от %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Съюзът, ÑÑŠÑтоÑщ Ñе от %{allies} и ти трÑбва да победите врага %{enemies}." msgstr[1] "" "Съюзът, ÑÑŠÑтоÑщ Ñе от %{allies} и ти трÑбва да победите вражеÑÐºÐ¸Ñ Ñъюз от " "%{enemies}." msgid "Capture the castle '%{name}'." msgstr "Превземи замъка '%{name}'." msgid "Capture the town '%{name}'." msgstr "Превземи града '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Победи Ð³ÐµÑ€Ð¾Ñ '%{name}'." msgid "Find the ultimate artifact." msgstr "Ðамери най-добриÑÑ‚ артефакт." msgid "Find the '%{name}' artifact." msgstr "Ðамери артефакта \"%{name}\"." msgid "Accumulate %{count} gold." msgstr "Ðатрупай %{count} злато." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", или може да Ñпечелиш, като победиш вÑички вражеÑки герои и превземеш " "вÑички вражеÑки градове и замъци." msgid "Lose the castle '%{name}'." msgstr "Губиш замъка '%{name}'." msgid "Lose the town '%{name}'." msgstr "Губиш града '%{name}'." msgid "Lose the hero: %{name}." msgstr "Губиш героÑ: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Ðе Ñпечелвай играта до ÐºÑ€Ð°Ñ Ð½Ð° меÑец %{month}, Ñедмица %{week}, ден %{day}." msgid "%{color} player has been vanquished!" msgstr "%{color} играч е победен!" msgid "Major Event!" msgstr "ГолÑмо Ñъбитие!" msgid "Scenario:" msgstr "Сценарий:" msgid "Game Difficulty:" msgstr "ТрудноÑÑ‚ на играта:" msgid "Opponents:" msgstr "Противници:" msgid "Class:" msgstr "КлаÑ:" msgid "Rating %{rating}%" msgstr "Оценка %{rating}%" msgid "Click here to select which scenario to play." msgstr "Кликни тук, за да избереш кой Ñценарий да играеш." msgid "Scenario" msgstr "Сценарий" msgid "Game Difficulty" msgstr "ТрудноÑÑ‚ на играта" #, fuzzy msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Това ти позволÑва да промениш началната трудноÑÑ‚, при коÑто ще играеш. По-" "виÑоките нива на трудноÑÑ‚ започват Ñ Ð¿Ð¾-малко реÑурÑи, а при по-виÑоките " "наÑтройки дава допълнителни реÑурÑи на компютъра." msgid "Difficulty Rating" msgstr "Оценка на трудноÑÑ‚" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Рейтингът на трудноÑÑ‚ отразÑва ÐºÐ¾Ð¼Ð±Ð¸Ð½Ð°Ñ†Ð¸Ñ Ð¾Ñ‚ различни наÑтройки за вашата " "игра. Това чиÑло ще бъде приложено към ÐºÑ€Ð°Ð¹Ð½Ð¸Ñ Ñ‚Ð¸ резултат." msgid "Click to accept these settings and start a new game." msgstr "Кликни, за да приемеш тези наÑтройки и да започнеш нова игра." msgid "Click to return to the main menu." msgstr "Кликни, за да Ñе върнеш към главното меню." msgid "Astrologers proclaim the Month of the %{name}." msgstr "ÐÑтролозите обÑвÑват меÑеца на %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "ÐÑтролозите обÑвÑват Ñедмицата на %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "След редовен раÑтеж популациÑта на %{monster} Ñе удвоÑва!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "След редовен раÑтеж популациÑта на %{monster} Ñе увеличава Ñ %{count} " "процента!" msgstr[1] "" "След редовен раÑтеж популациÑта на %{monster} Ñе увеличава Ñ %{count} " "процента!" msgid "%{monster} growth +%{count}." msgstr "%{monster} раÑтеж +%{count}." msgid " All populations are halved." msgstr " Ð’Ñички популации Ñа наполовина." msgid " All dwellings increase population." msgstr " Ð’Ñички жилища увеличават наÑелението." msgid "New Month!" msgstr "Ðов меÑец!" msgid "New Week!" msgstr "Ðова Седмица!" msgid "Beware!" msgstr "Внимавай!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} играч, това е поÑледниÑÑ‚ ти ден за превземане на град или ще бъдеш " "прогонен от тази земÑ." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} играч, имаш Ñамо %{day} дни, за да превземеш град, или ще бъдеш " "прогонен от тази земÑ." msgid "%{color} player's turn." msgstr "Ход на %{color} играч." #, fuzzy msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} играч, загуби поÑÐ»ÐµÐ´Ð½Ð¸Ñ Ñи град. Ðко не завладееш друг град през " "Ñледващата Ñедмица, ще бъдеш елиминиран." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} играч, теоите герои те изоÑтавÑÑ‚ и ти Ñи прогонени от тази земÑ." msgid "Lord Kilburn" msgstr "Лорд Килбърн" msgid "Tsabu" msgstr "Сабу" msgid "Sir Galant" msgstr "Сър Галант" msgid "Thundax" msgstr "ТъндакÑ" msgid "Lord Haart" msgstr "Лорд Хаарт" msgid "Ariel" msgstr "Ðриел" msgid "Rebecca" msgstr "Ребека" msgid "Sandro" msgstr "Сандро" msgid "Crodo" msgstr "Кродо" msgid "Barock" msgstr "Барок" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "ÐÑтра" msgid "Agar" msgstr "Егар" msgid "Vatawna" msgstr "Ватуна" msgid "Vesper" msgstr "ВеÑпер" msgid "Ambrose" msgstr "Ðмброуз" msgid "Troyan" msgstr "ТраÑна" msgid "Jojosh" msgstr "Джоджош" msgid "Wrathmont" msgstr "Вратмунд" msgid "Maximus" msgstr "МакÑимуÑ" msgid "Next Hero" msgstr "СледващиÑÑ‚ герой" msgid "Select the next Hero." msgstr "Избери ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³ÐµÑ€Ð¾Ð¹." msgid "Hero Movement" msgstr "Движение на героÑ" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "Започни движението на Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð¿ÑŠÑ‚ или поÑети отново обекта, зает от " "героÑ. ÐатиÑни и задръж този бутон, за да нулираш Ð¿ÑŠÑ‚Ñ Ð½Ð° героÑ." msgid "Kingdom Summary" msgstr "Резюме за КралÑтвото" #, fuzzy msgid "View a summary of your Kingdom." msgstr "Виж резюме на твоето кралÑтво." msgid "Cast an adventure spell." msgstr "Ðаправи приключенÑко заклинание." msgid "End Turn" msgstr "Краен завой" #, fuzzy msgid "End your turn and let the computer take its turn." msgstr "Завърши хода Ñи и оÑтави компютъра да направи ÑвоÑ." msgid "Adventure Options" msgstr "Опции за приключениÑ" msgid "Bring up the adventure options menu." msgstr "Покажи менюто Ñ Ð¾Ð¿Ñ†Ð¸Ð¸ за приключение." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Покажи менюто Ñ Ð¾Ð¿Ñ†Ð¸Ð¸ за файлове, което ти позволÑва да зареждаш, запазваш, " "Ñтартираш нова игра или да напуÑнеш играта." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Покажи менюто ÑÑŠÑ ÑиÑтемни опции, което ти позволÑва да перÑонализираш " "играта Ñи." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Един или повече герои вÑе още имат ход. Сигурен ли Ñи, че иÑкаш да приключиш " "ÑÐ²Ð¾Ñ Ñ…Ð¾Ð´?" msgid "Are you sure you want to quit?" msgstr "Сигурен ли Ñи че иÑкаш да напуÑнеш играта?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Сигурен ли Ñи че иÑкаш да пуÑнеш отново играта? (ТвоÑта наÑтоÑща игра ще Ñе " "изгуби.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Сигурен ли Ñи че иÑкаш да презапишеш запазената игра Ñ Ñ‚Ð¾Ð²Ð° име?" msgid "Game saved successfully." msgstr "Играта е запазена уÑпешно." msgid "There was an issue during saving." msgstr "Имаше проблем по време на запазването." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Сигурен ли Ñи, че иÑкаш да заредиш нова игра? (Текущата ти игра ще бъде " "загубена.)" msgid "Try looking on land!!!" msgstr "Опитай да погледнеш на земÑта!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "ТърÑенето на Ð’ÑŠÑ€Ñ…Ð¾Ð²Ð½Ð¸Ñ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚ е без резултат. ТвоÑÑ‚ герой не би могъл да " "го ноÑи, дори ако го намери - вÑичките му Ñлотове за артефакти Ñа пълни." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Копаенето на артефакти изиÑква цÑл ден, опитай отново утре." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "След като прекара много чаÑове в копаене тук, ти откри %{artifact}." msgid "Congratulations!" msgstr "ЧеÑтито!" msgid "Nothing here. Where could it be?" msgstr "Ðищо нÑма тук. Къде може да е?" msgid "Try searching on clear ground." msgstr "Опитай да търÑиш на чиÑта земÑ." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Миниатюрен изглед на Ð¿Ð¾Ð·Ð½Ð°Ñ‚Ð¸Ñ ÑвÑÑ‚. Кликни Ñ Ð»ÐµÐ²Ð¸Ñ Ð±ÑƒÑ‚Ð¾Ð½, за да премеÑтиш " "зоната за преглед." msgid "Month: %{month} Week: %{week}" msgstr "МеÑец: %{month} Седмица: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Ðамираш малко\n" "количеÑтво %{resource}." msgid "Status Window" msgstr "Прозорец на ÑÑŠÑтоÑнието" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Този прозорец предоÑÑ‚Ð°Ð²Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° ÑÑŠÑтоÑнието на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ или " "кралÑтво и показва датата." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Този прозорец предоÑÑ‚Ð°Ð²Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° ÑÑŠÑтоÑнието на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ или " "кралÑтво и показва датата. Щракни Ñ Ð»ÐµÐ²Ð¸Ñ Ð±ÑƒÑ‚Ð¾Ð½ тук, за да преминеш през " "тези прозорци." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Това ти позволÑва да променÑш началните позиции и цветовете на играчите. " "Конкретен цвÑÑ‚ винаги ще започва от определено мÑÑто. ÐÑкои позиции могат да " "Ñе играÑÑ‚ Ñамо от компютърен играч или Ñамо от човешки играч." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Това ти позволÑва да промениш клаÑа на играч. КлаÑовете не винаги могат да " "Ñе променÑÑ‚. Ð’ завиÑимоÑÑ‚ от ÑценариÑ, играчът може да получи допълнителни " "градове и/или герои, които не Ñа от оÑновното им подреждане." msgid "Handicap" msgstr "Ðедъг" # #, fuzzy msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Това ти позволÑва да промениш недъга на определен играч. Само хората могат " "да бъдат инвалиди. Играчите Ñ ÑƒÐ²Ñ€ÐµÐ¶Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¾Ñ‡Ð²Ð°Ñ‚ Ñ Ð¿Ð¾-малко реÑурÑи и " "печелÑÑ‚ Ñъответно 15 или 30% по-малко реÑурÑи на ход за леки и тежки " "уврежданиÑ." msgid "%{color} player" msgstr "%{color} играч" msgid "No Handicap" msgstr "Без недъг" #, fuzzy msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "ÐÑма Ñпециални Ð¾Ð³Ñ€Ð°Ð½Ð¸Ñ‡ÐµÐ½Ð¸Ñ Ð·Ð° Ñтартовите реÑурÑи и печеленето им на ход." msgid "Mild Handicap" msgstr "Лек недъг" # #, fuzzy msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Играчите Ñ Ð»ÐµÐºÐ¸ недъзи започват Ñ Ð¿Ð¾-малко реÑурÑи и печелÑÑ‚ 15% по-малко " "реÑурÑи на ход." msgid "Severe Handicap" msgstr "Тежък недъг" # #, fuzzy msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Играчите Ñ Ñ‚ÐµÐ¶ÐºÐ¸ ÑƒÐ²Ñ€ÐµÐ¶Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ð¾Ñ‡Ð²Ð°Ñ‚ Ñ Ð¿Ð¾-малко реÑурÑи и печелÑÑ‚ Ñ 30% по-" "малко реÑурÑи през ÑÐ²Ð¾Ñ Ñ…Ð¾Ð´." msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Задайте умение за нападение" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Виж Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Защита" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Приходи на царÑтвото" msgid "Kingdom Income per day." msgstr "Приходи на царÑтвото за ден." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "За вÑеки контролиран фар, твойте кораби ще Ñе придвижват вÑе повече вÑеки " "ден." msgid "English" msgstr "ÐнглийÑки" msgid "French" msgstr "ФренÑки" msgid "Polish" msgstr "ПолÑки" msgid "German" msgstr "ÐемÑки" msgid "Russian" msgstr "РуÑки" msgid "Italian" msgstr "ИталианÑки" msgid "Czech" msgstr "ЧехÑки" msgid "Norwegian" msgstr "Ðорвежки" msgid "Belarusian" msgstr "БеларуÑки" msgid "Bulgarian" msgstr "БългарÑки" msgid "Ukrainian" msgstr "УкраинÑки" msgid "Romanian" msgstr "РумънÑки" msgid "Spanish" msgstr "ИÑпанÑки" msgid "Swedish" msgstr "ШведÑки" msgid "Portuguese" msgstr "ПортугалÑки" msgid "Turkish" msgstr "ТурÑки" msgid "Dutch" msgstr "ХоландÑки" msgid "Hungarian" msgstr "УнгарÑки" msgid "Danish" msgstr "ДатÑки" msgid "Slovak" msgstr "Словашки" msgid "Vietnamese" msgstr "ВиетнамÑки" msgid "Slow" msgstr "Бавно" msgid "Fast" msgstr "Бързо" msgid "Very Fast" msgstr "Мн. бързo" msgid "Evil" msgstr "Зъл" msgid "Good" msgstr "Добър" msgid ", FPS: " msgstr "" #, fuzzy msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} разбойник" #, fuzzy msgid "pyramid|%{object} raided" msgstr "%{object} нападнат" msgid "Ector" msgstr "Ектор" msgid "Gwenneth" msgstr "Гуенет" msgid "Sir Gallant" msgstr "Сър Галант" msgid "Tyro" msgstr "Тайро" msgid "Dimitry" msgstr "Димитрий" msgid "Ruby" msgstr "Руби" msgid "Crag Hack" msgstr "Краг Хак" msgid "Fineous" msgstr "ФиниаÑ" msgid "Jezebel" msgstr "Джезабел" msgid "Atlas" msgstr "ÐтлаÑ" msgid "Ergon" msgstr "Ергон" msgid "Jaclyn" msgstr "Жаклин" msgid "Gem" msgstr "Джем" msgid "Natasha" msgstr "Ðаташа" msgid "Carlawn" msgstr "Карлон" msgid "Luna" msgstr "Луна" msgid "Arie" msgstr "Ери" msgid "Barok" msgstr "Барок" msgid "Kastore" msgstr "КаÑтор" msgid "Falagar" msgstr "Фалагар" msgid "Dawn" msgstr "Доон" msgid "Flint" msgstr "Флинт" msgid "Halon" msgstr "Хелан" msgid "Myra" msgstr "Майра" msgid "Myrini" msgstr "Майрини" msgid "Wilfrey" msgstr "Уилфри" msgid "Mandigal" msgstr "Мандигал" msgid "Sarakin" msgstr "Саракин" msgid "Charity" msgstr "Чарити" msgid "Darlana" msgstr "Дарлана" msgid "Ranloo" msgstr "Ранлу" msgid "Rialdo" msgstr "Риалдо" msgid "Zam" msgstr "Зам" msgid "Zom" msgstr "Зом" msgid "Celia" msgstr "СилиÑ" msgid "Roxana" msgstr "РокÑана" msgid "Lord Corlagon" msgstr "Лорд Корлагон" msgid "Lord Halton" msgstr "Лорд Холтън" msgid "Sister Eliza" msgstr "СеÑтра Елайза" msgid "Brother Brax" msgstr "Брат БракÑ" msgid "Dainwin" msgstr "Дейнуин" msgid "Joseph" msgstr "Джоузеф" msgid "Mog" msgstr "Мог" msgid "Solmyr" msgstr "Солмир" msgid "Ceallach" msgstr "Калег" msgid "Drakonia" msgstr "ДракониÑ" msgid "Elderian" msgstr "Елдериан" msgid "Gallavant" msgstr "Галевант" msgid "Jarkonas" msgstr "ДжарконаÑ" msgid "Martine" msgstr "Мартинa" msgid " gives you maximum morale" msgstr " ти дава макÑимален морал" msgid " gives you maximum luck" msgstr " ти дава макÑимален къÑмет" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Ðе може да Ñе премеÑти книгата Ñ Ð¼Ð°Ð³Ð¸Ð¹" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Ðе можеш да вземеш този артефакт, вече нÑмаш мÑÑто!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "За да правиш магии, първо трÑбва да Ñи купиш книга за магий за %{gold} злато." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "За Ñъжаление, изглежда, че в момента нÑмаш пари." msgid "Do you wish to buy one?" msgstr "ИÑкаш ли да Ñи купиш такъв?" msgid "%{count} / day" msgstr "%{count} / ден" msgid "one" msgstr "една" msgid "two" msgstr "две" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "Водовъртежът поглъща кораба ти. ЧаÑÑ‚ от армиÑта ти е паднала зад борда." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Обидени от отказа ти от офертата им, чудовищата атакуват!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "%{monster}, възхитени от твоите Ñили, започват да Ñе разпръÑват.\n" "ИÑкаш ли да ги преÑледваш и вербуваш?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "ПретърÑвайки вражеÑки лагер, откриваш Ñкрит тайник ÑÑŠÑ Ñъкровища." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Пазачът на мелницата Ñъобщава:\n" "\"Милорд, работих много уÑилено, за да ти оÑÐ¸Ð³ÑƒÑ€Ñ Ñ‚ÐµÐ·Ð¸ реÑурÑи, заповÑдай " "Ñледващата Ñедмица за още.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Пазачът на мелницата Ñъобщава:\n" "\"Милорд, ÑъжалÑвам, в момента нÑма налични реÑурÑи. МолÑ, опитай отново " "Ñледващата Ñедмица.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Пазачът на мелницата Ñъобщава:\n" "\"Милорд, работих много уÑилено, за да ти оÑÐ¸Ð³ÑƒÑ€Ñ Ñ‚Ð¾Ð²Ð° злато, ела Ñледващата " "Ñедмица за още.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Пазачът на мелницата Ñъобщава:\n" "\"Милорд, ÑъжалÑвам, в момента нÑма налично злато. МолÑ, опитай отново " "Ñледващата Ñедмица.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Ðамери изоÑтавен навеÑ.\n" "Ровейки Ñе, откриваш нÑкои реÑурÑи, Ñкрити наблизо." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "ÐавеÑÑŠÑ‚ отдавна е изоÑтавен. Тук нÑма нищо ценно." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Хващаш леприкон, който глупаво Ñпи Ñред група вълшебни гъби.\n" "Ð’ замÑна на Ñвободата Ñи той те води до малко гърне, пълно ÑÑŠÑ Ñкъпоценни " "неща." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Ðамери вълшебна градина, мÑÑтото, където леприконите и феите обичат да Ñе " "разхождат, но Ð´Ð½ÐµÑ Ñ‚ÑƒÐº нÑма никой.\n" "Може би трÑбва да опиташ отново Ñледващата Ñедмица." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Попадаш на оÑтанките на нещаÑтен авантюриÑÑ‚." msgid "Treasure" msgstr "Съкровище" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "ТърÑейки в едни дрипи, намираш %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "ПретърÑваш дрипите, но не намираш нищо." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Попадаш на Ñтара каруца, оÑтавена от търговец, който не е уÑпÑл да Ñтигне до " "безопаÑен терен." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "За Ñъжаление други Ñа го намерили първи и вагонът е празен." msgid "Searching inside, you find the %{artifact}." msgstr "ТърÑейки вътре, намираш %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Вътре намираш чаÑÑ‚ от товара на каруцата вÑе още непокътнат." msgid "You search through the flotsam, and find some wood and some gold." msgstr "ТърÑиш из отломките и намираш малко дърва и малко злато." msgid "You search through the flotsam, and find some wood." msgstr "ПретърÑваш отломките и намираш малко дърва." msgid "You search through the flotsam, but find nothing." msgstr "ТърÑиш из отломките, но не намираш нищо." msgid "Shrine of the 1st Circle" msgstr "Храм на 1-Ð²Ð¸Ñ ÐºÑ€ÑŠÐ³" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Ðатъкваш Ñе на малко Ñветилище, поÑещавано от група дÑкони.\n" "Ð’ замÑна на твоÑта защита, те Ñе ÑъглаÑÑват да те научат на заклинанието - " "'%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Храм на 2-Ñ€Ð¸Ñ ÐºÑ€ÑŠÐ³" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Ðатъкваш Ñе на богато украÑен храм, поÑещаван от група закръглени монаÑи.\n" "Ð’ замÑна на твоÑта защита, те Ñе ÑъглаÑÑват да те научат на заклинанието - " "'%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Храм на 3-Ñ‚Ð¸Ñ ÐºÑ€ÑŠÐ³" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Ðатъкваш Ñе на пищно Ñветилище, поÑещавано от група първоÑвещеници.\n" "Ð’ замÑна на твоÑта защита, те Ñе ÑъглаÑÑват да те научат на Ñложното " "заклинание - '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "За Ñъжаление нÑмаш мъдроÑтта да разбереш заклинанието и не уÑпÑваш да го " "научиш." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "За Ñъжаление вече имаш Ð·Ð½Ð°Ð½Ð¸Ñ Ð·Ð° това заклинание, така че нÑма на какво " "повече да те научат." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "За Ñъжаление нÑмаш магичеÑка книга, в коÑто да запишеш заклинанието." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Приближаваш Ñе до хижата и виждаш вътре вещица изучаваща древен том по " "%{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Докато Ñе приближаваш, Ñ‚Ñ Ñе обръща и те забелÑзва Ñ ÐµÐ´Ð½Ð¾Ñ‚Ð¾ Ñи Ñтъклено " "око.\n" "\"Вече знаеш вÑичко, което можеше да научиш!\" изпищÑва вещицата. \"СЕГРСЕ " "МÐÐ¥ÐЙ ОТ КЪЩÐТРМИ!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Докато Ñе приближаваш, Ñ‚Ñ Ñе обръща и заговарÑ.\n" "\"Вече знаеш вÑичко, на което можех да те науча. Ðе мога да ти помогна " "повече.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Древна и безÑмъртна вещица, живееща в колиба на кокоши крака за кокили, те " "учи на %{skill} за ÑобÑтвените Ñи неразгадаеми цели." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "Докато пиеш Ñладката вода, печелиш къÑмет за Ñледващата Ñи битка." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Пиеш от омагьоÑÐ°Ð½Ð¸Ñ Ñ„Ð¾Ð½Ñ‚Ð°Ð½, но нищо не Ñе Ñлучва." msgid "You enter the faerie ring, but nothing happens." msgstr "Влизаш във пръÑтена на фейте, но нищо не Ñе Ñлучва." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "С влизането в миÑÑ‚Ð¸Ñ‡Ð½Ð¸Ñ Ð¿Ñ€Ð¸ÐºÐ°Ð·ÐµÐ½ пръÑтен армиÑта ти печели къÑмет за " "Ñледващата Ñи битка." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Ðамери древен и увехтÑл каменен идол.\n" "Предполага Ñе, че дава къÑмет на поÑетителите, но тъй като звездите вече ти " "Ñе уÑмихнаха, не прави нищо." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Ðамери древен и увехтÑл каменен идол.\n" "Предполага Ñе, че целуването му ноÑи къÑмет, така че го правиш. Камъкът е " "много Ñтуден на допир." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "РуÑалките мълчаливо те примамват да Ñе върнеш по-къÑно и отново да бъдеш " "благоÑловен." #, fuzzy msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "МагичеÑката, уÑпокоÑваща краÑота на РуÑалките доÑтига до теб и Ñ‚Ð²Ð¾Ñ ÐµÐºÐ¸Ð¿.\n" "За миг забравÑш тревогите Ñи и Ñе наÑлаждаваш на краÑотата на момента.\n" "ТалиÑманите за руÑалки те благоÑлавÑÑ‚ Ñ Ð¿Ð¾Ð²ÐµÑ‡Ðµ къÑмет за Ñледващата ти битка." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Попадаш на пирамидата на велик и древен цар.\n" "Изкушаваш Ñе да Ñ Ð¿Ñ€ÐµÑ‚ÑŠÑ€Ñиш за Ñъкровища, но Ñтарите иÑтории предупреждават " "за Ñтраховити проклÑÑ‚Ð¸Ñ Ð¸ немъртви пазители.\n" "Ще търÑиш ли?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "След като победи чудовищата, дешифрираш древен йероглиф на Ñтената, " "разказващ тайната на заклинанието - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "За Ñъжаление нÑмаш магичеÑка книга, в коÑто да запишеш заклинанието." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "За Ñъжаление нÑмаш мъдроÑтта да разбереш заклинанието и не можеш да го " "научиш." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Попадаш на пирамидата на велик и древен цар.\n" "Рутинното проучване разкрива, че пирамидата е напълно празна." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Една глътка от кладенеца трÑбва да възÑтанови твоите точки за заклинаниÑ, но " "те вече Ñа на макÑимум." msgid "A second drink at the well in one day will not help you." msgstr "Втора глътка от кладенеца за един ден нÑма да ти помогне." msgid "A drink from the well has restored your spell points to maximum." msgstr "" "Глътката от кладенеца е възÑтановила точките ти за Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð´Ð¾ макÑимум." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"СъжалÑвам, ÑÑŠÑ€\", казва водачът на войниците, \"но вече знаете вÑичко, " "което можехме да те научим.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "Войниците, живеещи във форта, те учат на нÑколко нови защитни трика." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Попадаш на лагер на наемници, който упражнÑват Ñвоите умениÑ. \"Твърде Ñи " "напреднал за наÑ\", казва капитанът на наемниците. \"Ðе можем да те научим " "на нищо повече.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Попадаш на лагер на наемници, които упражнÑват Ñвоите умениÑ. Ðаемниците " "приветÑтват теб и твоите войÑки и ви канÑÑ‚ да тренирате Ñ Ñ‚ÑÑ…." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Заминавай!\", излайва врачката, \"вече знаеш вÑичко, което и аз.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "ОркÑкиÑÑ‚ знахар, който живее в колибата, задълбочава знаниÑта ти за магиÑ, " "като ти показва как да хвърлÑш камъни, да разчиташ Ð·Ð½Ð°Ð¼ÐµÐ½Ð¸Ñ Ð¸ да дешифрираш " "тънкоÑтите на пилешките вътрешноÑти." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Ðамираш група друиди на поклонение в една от техните Ñтранни каменни Ñгради. " "Мълчаливо друидите те отблъÑкват, показвайки, че нÑмат какво ново да те " "научат." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Ðамираш група друиди да Ñе покланÑÑ‚ в една от техните Ñтранни каменни " "Ñгради. Тихичко те те научават на нови начини за правене магии." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Ðеуверено Ñе приближаваш до гробището на древни воини. ИÑкаш ли да претърÑиш " "гробовете?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Прекарваш нÑколко чаÑа в претърÑване на гробовете и не намираш нищо. Подобно " "презрÑно дейÑтвие намалÑва морала на твоÑта армиÑ." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "След като побеждаваш зомбитата, претърÑваш гробовете и намираш нещо!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "ГниещиÑÑ‚ ÐºÐ¾Ñ€Ð¿ÑƒÑ Ð½Ð° голÑм пиратÑки кораб Ñкърца зловещо, докато Ñе блъÑка в " "Ñкалите. ИÑкаш ли да претърÑиш оÑтанките на кораба?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Прекарваш нÑколко чаÑа в преÑÑване на отломките и не намирате нищо. Подобно " "презрÑно дейÑтвие намалÑва морала на вашата армиÑ." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "След като побеждаваш призраците, преÑÑваш отломките и намираш нещо!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "ГниещиÑÑ‚ ÐºÐ¾Ñ€Ð¿ÑƒÑ Ð½Ð° голÑм пиратÑки кораб Ñкърца зловещо, докато Ñе блъÑка в " "Ñкалите. ИÑкаш ли да претърÑиш кораба?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "След като побеждаваш Ñкелетите, преÑÑваш отломките и намираш нещо!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Твойте хора забелÑзват навигационен буй, потвърждаващ, че Ñте на Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð½Ð¸Ñ " "курÑ." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Твойте хора забелÑзват навигационен буй, който потвърждава, че Ñте на " "Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð½Ð¸Ñ ÐºÑƒÑ€Ñ Ð¸ повишава морала им." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Ðапитката в оазиÑа е оÑвежаваща, но не ноÑи допълнителна полза. ОазиÑÑŠÑ‚ може " "да помогне отново, ако Ñи водил битка." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Едно питие в оазиÑа изпълва войÑките ти ÑÑŠÑ Ñила и повдига духа им. Ð”Ð½ÐµÑ " "можеш да пътуваш малко по-далеч." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Ðапитката във Ð²Ð¾Ð´Ð¾Ð¿Ð¾Ñ Ðµ оÑвежаваща, но не ноÑи допълнителна полза. Дупката " "за поливане може да помогне отново, ако Ñи водил битка." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Едно питие на Ð²Ð¾Ð´Ð¾Ð¿Ð¾Ñ Ð¸Ð·Ð¿ÑŠÐ»Ð²Ð° войÑките ти ÑÑŠÑ Ñила и повдига духа им. Ð”Ð½ÐµÑ " "можеш да пътуваш малко по-далеч." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Ðе помага да Ñе молиш два пъти преди битка. Върни Ñе, Ñлед като Ñи Ñе бил." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "ПоÑещението и молитвата в храма повишават морала на твойте войÑки." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Ðа Ñтъпалата на беÑедката Ñе поÑвÑва Ñтар рицар. \"СъжалÑвам, гоÑподарю мой, " "научих те на вÑичко, което мога.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Ðа Ñтъпалата на беÑедката Ñе поÑвÑва Ñтар рицар. \"ГоÑподарю мой, ще те " "науча на вÑичко, което знам, за да ти помага в пътуваниÑта ти.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "СпаÑи оцелÑл от корабокрушение от Ñигурна Ñмърт човек в безмилоÑÑ‚Ð½Ð¸Ñ Ð¾ÐºÐµÐ°Ð½. " "Благодарен, той казва: \"Бих ти дал артефакт като награда, но нÑмаш мÑÑто.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "СпаÑи оцелÑл от корабокрушение от Ñигурна Ñмърт човек в безмилоÑÑ‚Ð½Ð¸Ñ Ð¾ÐºÐµÐ°Ð½. " "Благодарен, той те възнаграждава за проÑвената доброта, като ти дава %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "Леприкона ти предлага %{art} на малката цена от %{gold} злато." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Ð›ÐµÐ¿Ñ€Ð¸ÐºÐ¾Ð½Ñ Ñ‚Ð¸ предлага %{art} на ниÑката цена от %{gold} злато и %{count} " "%{res}." msgid "Do you wish to buy this artifact?" msgstr "ИÑкаш ли да купиш този артефакт?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Опитваш Ñе да платиш на леприкона, но разбираш, че не можеш да Ñи го " "позволиш. Леприконът тропва Ñ ÐºÑ€Ð°Ðº и те игнорира." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Обиден от отказа ти на щедрото му предложение, леприконът тропва Ñ ÐºÑ€Ð°Ðº и те " "игнорира." msgid "You've found the artifact: " msgstr "Ти откри артефакта:" msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Ðамери Ñкромното жилище на изÑъхнал отшелник. Отшелникът ти казва, че е " "готов да даде %{art} на Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð¼ÑŠÐ´ÑŠÑ€ човек, когото Ñрещне." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Попаднал Ñте на ÑпартанÑките квартири на пенÑиониран войник. Войникът ти " "казва, че е готов да предаде %{art} на Ð¿ÑŠÑ€Ð²Ð¸Ñ Ð¸ÑтинÑки лидер, когото Ñрещне." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Срещаш Ñтранен човек Ñ ÑˆÐ°Ð¿ÐºÐ° и бухал върху неÑ. Той ти казва, че е готов да " "даде %{art}, ако имате %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Попадаш на древен артефакт. Когато поÑÑгаш към него, група мошеници изÑкачат " "от храÑтите, за да опазÑÑ‚ откраднатата Ñи плÑчка." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Ðа една полÑна виждаш древен артефакт. За Ñъжаление, той Ñе охранÑва от " "%{monster}. ИÑкаш ли да Ñе биеш Ñ %{monster} за артефакта?" msgid "Victorious, you take your prize, the %{art}." msgstr "Победител, ти вземаш ÑвоÑта награда, %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "ДиÑкретноÑтта е по-добрата чаÑÑ‚ от доблеÑтта и ти решаваш да избегнеш тази " "битка днеÑ." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "След като Ñи прекарал чаÑове в опити да извадиш Ñандъка от морето, ти го " "отварÑш и намирате %{gold} златни парчета." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "След като Ñи прекарал чаÑове в опити да извадиш Ñандъка от морето, ти го " "отварÑш и намираш %{gold} злато и %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "След като Ñи прекарал чаÑове в опити да извадиш Ñандъка от морето, ти го " "отварÑш, Ñамо за да го намериш празен." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "След като претърÑи района, попадаш на Ñкрит тайник ÑÑŠÑ Ñъкровище. Можеш да " "вземеш златото или да го раздадеш на ÑелÑните за опит. ИÑкаш ли да запазиш " "златото?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "След като претърÑи района, попадаш на Ñкрит Ñандък, Ñъдържащ %{gold} златни " "парчета." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "След като претърÑи района, попадаш на Ñкрит Ñандък, Ñъдържащ Ð´Ñ€ÐµÐ²Ð½Ð¸Ñ " "артефакт %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Ðатъкваш Ñе на вдлъбната и зацапана лампа, забита дълбоко в земÑта. ИÑкаш ли " "да потъркаш лампата?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Пое контрол над меÑÑ‚Ð½Ð¸Ñ Ð¼Ð°Ð³Ð°Ð·Ð¸Ð½ на Ðлхимика. Ще ти оÑигури %{count} единица " "живак на ден." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Получаваш контрол над дъÑкорезницата. Ще ти оÑигури %{count} единици дърва " "на ден." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Получаваш контрол над мина за руда. Ще ти оÑигури %{count} единица руда на " "ден." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Получаваш контрол над ÑÑрна мина. Ð¢Ñ Ñ‰Ðµ ти оÑигури %{count} единица ÑÑра на " "ден." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Получаваш контрол над криÑтална мина. Ð¢Ñ Ñ‰Ðµ ти оÑигури %{count} единица " "криÑтал на ден." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Получаваш контрол над мина за Ñкъпоценни камъни. Ð¢Ñ Ñ‰Ðµ ти оÑигури %{count} " "единица Ñкъпоценни камъни на ден." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Получаваш контрол над златна мина. Ще ти оÑигури %{count} злато на ден." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Фарът Ñега е под твой контрол и вÑички твой кораби Ñега ще Ñе движат вÑе по-" "далеч вÑеки ден." msgid "You gain control of a %{name}." msgstr "Получаваш контрол над %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Попадаш на изоÑтавена златна мина. Мината изглежда обитавана от духове. " "Желаеш ли да влезеш?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" "Ти побеждаваш Призраците и Ñи в ÑÑŠÑтоÑние да възÑтановиш мината за " "производÑтво." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Група от %{monster} Ñ Ð¶ÐµÐ»Ð°Ð½Ð¸Ðµ за по-голÑма Ñлава желае да Ñе приÑъедини към " "теб. Приемаш ли?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Когато Ñе приближаваш до жилището, забелÑзваш, че тук нÑма никой." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "ПретърÑваш руините, но Медузите, които Ñа живели тук, ги нÑма. Може би " "Ñледващата Ñедмица ще има още." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Ðамираш нÑколко медузи, живеещи в руините. Те Ñа готови да Ñе приÑъединÑÑ‚ " "към твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ñрещу определена цена. ИÑкаш ли да наемеш Медузите?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Ðамираш града на дърветата на Фейте. За Ñъжаление никой от живеещите там фей " "не желае да Ñе приÑъедини към армиÑта ти. Може би Ñледващата Ñедмица." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "ÐÑкои от Фейте, живеещи в града на дърветата, Ñа готови да Ñе приÑъединÑÑ‚ " "към твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ñрещу определена цена. ИÑкаш ли да наемеш Фей?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "Ðамираш празен катун на Мошеници. Може би те ще бъдат тук по-къÑно." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Далечни звуци на музика и ÑмÑÑ… те привличат към катун, в който Ñе намират " "Мошеници. ИÑкаш ли нÑкой мошеник да Ñе приÑъедини към твоÑта армиÑ?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Група оръфани палатки, развÑвани от пÑÑÑŠÑ‡Ð½Ð¸Ñ Ð²Ñтър, те примамват. Палатките " "Ñа празни. Може би номадите ще бъдат тук по-къÑно." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Група оръфани палатки, развÑвани от пÑÑÑŠÑ‡Ð½Ð¸Ñ Ð²Ñтър, те примамват. Желаеш ли " "нÑкой номад да Ñе приÑъедини към теб по време на пътуваниÑта ти?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Ямата от кал бълбука за малко и Ñлед това Ñтой неподвижно." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Когато Ñе приближаваш до бълбукащата Ñма от кал, ÑъщеÑтвата започват да Ñе " "изкачват и да Ñе позиционират около неÑ. Ð’ униÑон те казват: \"Майката Ð—ÐµÐ¼Ñ " "би иÑкала да ти предложи нÑколко от войÑките Ñи. ИÑкаш ли да наемеш земни " "елементали?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Влизаш в Ñтруктурата от бели каменни колони и не намираш нищо." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Бели каменни Ñтълбове поддържат покрив, който Ñе издига до небето. Когато " "влизаш в Ñтруктурата, мъртвиÑÑ‚ въздух отвън отÑтъпва мÑÑто на въртÑщ Ñе " "порив, който почти те избутва обратно. Въздушното течение Ñе материализира в " "едва видима форма. СъщеÑтвото пита, което може да Ñе опише Ñамо като Ñилен " "шепот: \"Защо Ñи дошъл? Тук Ñи, за да призовеш Ñилите на въздуха ли?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Ðикакви Огнени елементали не Ñе доближават до теб от баÑейна Ñ Ð»Ð°Ð²Ð°." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Под Ñтруктура, коÑто Ñлужи за задържане на топлина, Огнените елементали Ñе " "движат в огнен баÑейн от разтопена лава. Група от Ñ‚ÑÑ… Ñе обръщат към теб и " "предлагат уÑлугите Ñи. ИÑкаш ли да наемеш Огнени елементали?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Лице Ñе Ð¾Ñ„Ð¾Ñ€Ð¼Ñ Ð²ÑŠÐ² водата за момент и Ñлед това изчезва." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "КриÑтални Ñтруктури хвърлÑÑ‚ Ñенки върху малък отразÑващ воден баÑейн. " "Ðадникваш в баÑейна и лице, което не е твоето, Ñе оглежда там. То пита: " "\"ИÑкаш ли да призовеш Ñилите на водата?\"" msgid "This burial site is deathly still." msgstr "Това мÑÑто за погребение е вÑе още ÑмъртоноÑно." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "ÐеÑпокойните духове на отдавна мъртви воини, които търÑÑÑ‚ Ñвоето поÑледно " "мÑÑто за почивка, предлагат да Ñе приÑъединÑÑ‚ към теб Ñ Ð½Ð°Ð´ÐµÐ¶Ð´Ð°Ñ‚Ð° да намерÑÑ‚ " "покой. ИÑкаш ли да наемеш призраци?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "Ð’ Градът на мъртвите нÑма живот, както и неживот. Може би нÑкои немъртви ще " "Ñе заÑелÑÑ‚ Ñледващата Ñедмица." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "ÐÑкои Личове, живеещи тук, Ñа готови да Ñе приÑъединÑÑ‚ към твоÑта Ð°Ñ€Ð¼Ð¸Ñ " "Ñрещу определена цена. ИÑкаш ли да наемеш Личове?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Ðамери руините на древен град, Ñега обитаван Ñамо от немъртви. Ще търÑиш ли " "още?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "ÐÑкои от оцелелите Личове Ñа впечатлени от победата ти над техните ÑÑŠÐ±Ñ€Ð°Ñ‚Ñ Ð¸ " "предлагат да Ñе приÑъединÑÑ‚ към теб Ñрещу определена цена. ИÑкаш ли да " "наемеш Личове?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Ðамери един от онези моÑтове, под които троловете обичат да живеÑÑ‚, но Ñега " "ги нÑма. Може би ще има друга Ñедмица." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "ÐÑкои тролове, живеещи под моÑÑ‚, Ñа готови да Ñе приÑъединÑÑ‚ към твоÑта " "армиÑ, но Ñрещу определена цена. ИÑкаш ли да наемеш тролове?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "Троловете, живеещи под моÑта, те предизвикват. Ще Ñе биеш ли Ñ Ñ‚ÑÑ…?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "ОÑтават нÑколко трола, Ñвити под моÑта. Те Ñе приближават до теб и предлагат " "да Ñе приÑъединÑÑ‚ към Ñилите ти като наемници. ИÑкаш ли да купиш нÑколко " "трола?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "Ð’ Градът на драконите нÑма дракони, желаещи да Ñе приÑъединÑÑ‚ към теб тази " "Ñедмица. Може би ще има Ñледващата Ñедмица." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Градът на драконите е готов да предложи нÑколко дракона за твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ð½Ð° " "определена цена. ИÑкаш ли да наемеш дракони?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Ти Ñтоиш пред Града на драконите, мÑÑто, забранено за обикновени хора. ИÑкаш " "ли да нарушиш това правило и да предизвикаш Драконите на битка?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "След като победи драконовите шампиони, лидерите на града Ñе ÑъглаÑÑват да ти " "дадат нÑколко дракона за твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ñрещу определена цена. ИÑкаш ли да " "наемеш дракони?" msgid "From the observation tower, you are able to see distant lands." msgstr "От наблюдателната кула можеш да видиш далечни земи." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Изворът Ñе зарежда Ñамо веднъж Ñедмично и нÑкой вече е бил тук тази Ñедмица." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Предполага Ñе, че едно глътка от извора ще ти даде два пъти повече точки от " "обичайните за заклинаниÑ, но ти вече имаш толкова." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Глътка от извора изпълва кръвта ти Ñ Ð¼Ð°Ð³Ð¸Ñ! Имаш в резерв два пъти " "нормалните точки за заклинание." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Разпознавайки те, икономът отказва да те приеме. \"УчителÑÑ‚, казва той, не " "приема един и Ñъщ ученик два пъти.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Икономът те допуÑка да видите гоÑÐ¿Ð¾Ð´Ð°Ñ€Ñ Ð½Ð° къщата. Той те обучава в четирите " "умениÑ, които един герой трÑбва да знае." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Икономът Ð¾Ñ‚Ð²Ð°Ñ€Ñ Ð²Ñ€Ð°Ñ‚Ð°Ñ‚Ð° и те оглежда от горе до долу. \"Ðе Ñи нито извеÑтен, " "нито доÑтатъчно дипломатичен, за да бъдеш допуÑнат до гоÑÐ¿Ð¾Ð´Ð°Ñ€Ñ Ð¼Ð¸\", " "подÑмърча той. \"Върни Ñе, когато Ñтанеш доÑтоен.\"" msgid " and " msgstr " и " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Ð’Ñички %{monsters}, които имаш във твоÑта армиÑ, Ñа обучени от бойните " "майÑтори на форта. ТвоÑта Ð°Ñ€Ð¼Ð¸Ñ Ð²ÐµÑ‡Ðµ Ñъдържа %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Ðеобичаен Ñъюз на Огри, Орки и Джуджета предлага да обучава (надгражда) " "вÑички войÑки, които Ñа им доведени. За Ñъжаление нÑмаш нито една ÑÑŠÑ Ñебе " "Ñи." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Ð’Ñичките ти %{monsters} Ñа надградени до %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Ковача, който работи в леÑрната, предлага да преобразува вÑички донеÑени " "Ð¾Ñ€ÑŠÐ¶Ð¸Ñ Ð½Ð° пикермани и мечоноÑци от желÑзо в Ñтомана. Той Ñъщо така казва, че " "знае процеÑ, който ще превърне Железните Големи в Стоманени Големи. За " "Ñъжаление нÑмаш нито една от тези войÑки във твоÑта армиÑ, така че той не " "може да ти помогне." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Капитанът те поглежда изненадано и казва:\n" "\"Вече имаш вÑички карти, за които знам. Сега ме оÑтави да Ð»Ð¾Ð²Ñ Ñ€Ð¸Ð±Ð° на " "ÑпокойÑтвие.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "ПенÑиониран капитан, живеещ на тази обновена платформа за риболов, предлага " "да ти продаде карти на морето, които е направил в младоÑтта Ñи за 1000 " "злато. ИÑкаш ли да закупиш картите?" #, fuzzy msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Капитанът въздъхва. \"ÐÑмаш доÑтатъчно пари, а? Ðе можеш да очакваш от мен " "да дам картите Ñи безплатно!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Попадаш на обелиÑк, направен от вид камък, който никога преди не Ñи виждал. " "Гледайки го напрегнато, гладката повърхноÑÑ‚ изведнъж Ñе превръща в надпиÑ. " "ÐадпиÑÑŠÑ‚ е чаÑÑ‚ от изгубена антична карта. Бързо копираш парчето и надпиÑÑŠÑ‚ " "изчезва Ñъщо толкова внезапно, както Ñе и поÑви." msgid "You have already been to this obelisk." msgstr "Вече Ñи поÑетил този обелиÑк." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Когато Ñе приближаваш, дървото Ð¾Ñ‚Ð²Ð°Ñ€Ñ Ð¾Ñ‡Ð¸ от щаÑтие. \"Радвам Ñе да те видÑ, " "ученико мой. ÐадÑвам Ñе моите ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð´Ð° Ñа ти помогнали.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Когато Ñе приближаваш дървото Ð¾Ñ‚Ð²Ð°Ñ€Ñ Ð¾Ñ‡Ð¸ от щаÑтие. \"Ðаа, авантюриÑÑ‚! " "Позволи ми да те науча на малко от това, което Ñъм научил през вековете.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Когато Ñе приближаваш, дървото Ð¾Ñ‚Ð²Ð°Ñ€Ñ Ð¾Ñ‡Ð¸ от щаÑтие." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ðаа, авантюриÑÑ‚! Ще Ñе радвам да те науча на малко от това, което Ñъм " "научил през годините Ñамо за %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(ПроÑто го зарови около корените ми.)" msgid "Tears brim in the eyes of the tree." msgstr "Сълзи бликват от очите на дървото." msgid "\"I need %{count} %{res}.\"" msgstr "\"Имам нужда от %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "шепне то. (подÑмърчане) \"Е, върни Ñе, когато можеш да ми платиш.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Сгушен Ñред дърветата Ñеди ÑлÑп гледач. След като обÑÑнÑваш целта на Ñвоето " "пътуване, гледачът задейÑтва ÑвоÑта криÑтална топка, което ти позволÑва да " "видиш Ñилните и Ñлабите Ñтрани на опонентите Ñи." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Входът на пещерата е тъмен, и от него Ñе ноÑи неприÑтна миризма на ÑÑра. Ще " "влезеш ли вътре?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "ОÑвен Ñледи от ужаÑна битка, в пещерата нÑма нищо." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Ð’ пещерата намираш мощен и гротеÑков демон. \"ДнеÑ\", изхриптÑва той, \"ще " "Ñе биеш и ÑÑŠÑ ÑигурноÑÑ‚ ще умреш. Ðо аз ще ти дам да избереш как. Можеш да " "Ñе биеш Ñ Ð¼ÐµÐ½ или Ñ Ð¼Ð¾Ð¸Ñ‚Ðµ Ñлуги. Предпочиташ ли да Ñе биеш Ñ Ð¼Ð¾Ð¸Ñ‚Ðµ Ñлуги?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Демонът крещи Ñвоето предизвикателÑтво и атакува! След кратка, отчаÑна " "битка, ти убиваш чудовището и получаваш %{exp} точки опит." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Демонът крещи Ñвоето предизвикателÑтво и атакува! След кратка, отчаÑна " "битка, ти убиваш чудовището и получаваш %{exp} точки опит и %{count} злато." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Демонът крещи Ñвоето предизвикателÑтво и атакува! След кратка, отчаÑна " "битка, ти убиваш чудовището и намираш %{art} в задната чаÑÑ‚ на пещерата." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Виждайки, че нÑмаш %{count} злато, демонът те нарÑзва Ñ Ð½Ð¾ÐºÑ‚Ð¸Ñ‚Ðµ Ñи и " "поÑледното нещо, което виждаш, е червена мъгла." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Демонът Ñкача върху теб и впива ноктите Ñи в гърлото ти, преди дори да " "уÑпееш да извадиш меча Ñи. \"ТвоÑÑ‚ живот е мой\", казва той. \"Ще ти го дам " "обратно за %{count} злато.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "След като победи Ñлугите на демона, намираш Ñкрита кеÑÐ¸Ñ Ñ %{count} злато." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Когато влизаш в кулата на алхимика, към теб Ñе приближава куцащ, поÑивÑл мъж " "Ñ ÐºÐ°Ñ„Ñво наметало." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Той проверÑва багажа ти и вижда, че имаш 1 прокълнат предмет." msgstr[1] "" "Той проверÑва багажа ти и вижда, че имаш %{count} прокълнати предмета." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "За %{gold} злато, алхимикът ще го премахне вмеÑто теб. Ще платиш ли?" msgstr[1] "" "За %{gold} злато, алхимикът ще ги премахне вмеÑто теб. Ще платиш ли?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "След като Ñе ÑъглаÑи да платиш иÑканото количеÑтво злато, алхимикът грабва " "Ð¿Ñ€Ð¾ÐºÑŠÐ»Ð½Ð°Ñ‚Ð¸Ñ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚ и го Ñ…Ð²ÑŠÑ€Ð»Ñ Ð² магичеÑÐºÐ¸Ñ Ñи котел." msgstr[1] "" "След като Ñе ÑъглаÑи да платиш иÑканото количеÑтво злато, алхимикът грабва " "вÑички прокълнати артефакти и ги Ñ…Ð²ÑŠÑ€Ð»Ñ Ð² магичеÑÐºÐ¸Ñ Ñи котел." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Чуваш Ð³Ð»Ð°Ñ Ð·Ð°Ð´ заключената врата: \"ÐÑмаш доÑтатъчно злато, за да платиш за " "уÑлугите ми.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "Чуваш Ð³Ð»Ð°Ñ Ð¾Ñ‚Ð²Ð¸Ñоко в кулата: \"Върви Ñи! Ðе мога да ти помогна!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "ГлавниÑÑ‚ конÑÑ€ ти казва: \"КонÑÑ‚ ти е Ñтрахотен. Ð‘Ð¾Ñ Ñе, че не можем да ти " "дадем по-добър, но конете, които твоÑта ÐºÐ°Ð²Ð°Ð»ÐµÑ€Ð¸Ñ Ñзди, изглежда Ñа от лош " "разплод. Имаме много обучени бойни коне, които биха помогнали значително на " "твойте ездачи. ÐаÑтоÑвам да ги вземеш." msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Докато приближаваш конюшните, Ñе поÑвÑва главниÑÑ‚ конÑÑ€, водейки добре " "изглеждащ боен кон. \"Този кон ще ти помогне да уÑкорите пътуването Ñи. Уви, " "той ще Ñе умори Ñлед Ñедмица. ТрÑбва Ñъщо така да ми позволиш да дам по-" "добри коне на твоите кавалериÑти, техните коне изглеждат калпави и Ñлаби.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "ГлавниÑÑ‚ конÑÑ€ Ñе приближава към теб и ти казва: \"Ти вече имаш добър кон и " "имаш опитна кавалериÑ, коÑто може да използва нашите обучени бойни коне.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Докато приближаваш конюшните, Ñе поÑвÑва главниÑÑ‚ конÑÑ€, водейки добре " "изглеждащ боен кон. \"Този кон ще ти помогне да уÑкориш пътуването Ñи. Уви, " "издръжливоÑтта му ще отÑлабне Ñлед тежката езда и трÑбва да Ñе върнеш за нов " "кон Ñлед Ñедмица. Имаме и много добри бойни коне, които биха могли да бъдат " "от полза за кавалериÑта ти, но нÑмаш такава, ние можем да помогнем.\"" msgid "The Arena guards turn you away." msgstr "Охраната на Ðрената те отблъÑква." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Караш Ñ‚Ð²Ð¾Ñ ÐµÐºÐ¸Ð¿Ð°Ð¶ да запуши ушите Ñи Ñ Ð²Ð¾Ñък, преди зловещата пеÑен на " "Ñирените да има нÑкакъв ÑˆÐ°Ð½Ñ Ð´Ð° ги примами във Ð²Ð¾Ð´Ð½Ð¸Ñ Ð³Ñ€Ð¾Ð±." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Докато Ñирените пеÑÑ‚ зловещата Ñи пеÑен, твоÑта малка, решителна Ð°Ñ€Ð¼Ð¸Ñ " "уÑпÑва да преодолее желанието да Ñе гмурне Ñтремглаво в морето." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "От Ñирените, кацнали по Ñкалите, Ñе ноÑи зловеща плачеща пеÑен. Много от " "Ñ‚Ð²Ð¾Ñ ÐµÐºÐ¸Ð¿Ð°Ð¶ попадат под неговото заклинание и Ñе гмуркат във водата, където " "Ñе давÑÑ‚. Вече Ñте по-мъдри Ñлед Ñлучката и придобивате %{exp} опит." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Ð’ оÑлепителна демонÑÑ‚Ñ€Ð°Ñ†Ð¸Ñ Ð½Ð° ÑмелоÑÑ‚ ти нахлуваш в меÑÑ‚Ð½Ð¸Ñ Ð·Ð°Ñ‚Ð²Ð¾Ñ€ и " "оÑвобождаваш Ð¿Ð»ÐµÐ½ÐµÐ½Ð¸Ñ Ñ‚Ð°Ð¼ герой, който в замÑна Ñе заклева във вÑрноÑÑ‚ към " "твоÑта кауза." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Вече имаш %{count} герои и за Ñъжаление трÑбва да оÑтавиш затворника в този " "затвор да тъне в Ð°Ð³Ð¾Ð½Ð¸Ñ Ð±ÐµÐ·Ð±Ñ€Ð¾Ð¹ дни." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Влизаш в разклатената колиба и разговарÑш Ñ Ð¼Ð°Ð³ÑŒÐ¾Ñника, който живее там. Той " "ти разказва за близки и далечни меÑта, които могат да ти помогнат в " "пътуваниÑта ти." msgid "This eye seems to be intently studying its surroundings." msgstr "Това око изглежда внимателно изучава заобикалÑщата го Ñреда." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Попадаш на гигантÑки СфинкÑ. СфинкÑÑŠÑ‚ оÑтава Ñтранно тих." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Имам гатанка за теб\", казва СфинкÑÑŠÑ‚. \"Отговори правилно и ще бъдеш " "възнаграден. Отговори неправилно и ще бъдеш изÑден. Приемаш ли " "предизвикателÑтвото?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "СфинкÑÑŠÑ‚ ти задава Ñледната гатанка:\n" "\n" "'%{riddle}'\n" "\n" "ТвоÑÑ‚ отговор?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Отговори неправилно\", казва СфинкÑÑŠÑ‚, уÑмихвайки Ñе. СфинкÑÑŠÑ‚ замахва Ñ " "лапа, ÑъбарÑйки те на земÑта. Още един удар кара Ñвета да почернее и ти не " "знаеш нищо повече." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Изглеждайки малко разочарован, СфинкÑÑŠÑ‚ въздъхва. \"Отговори на загадката " "ми, така че ето ти наградата. Сега Ñе махай.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "МагичеÑка бариера Ñтои виÑоко пред теб и блокира Ð¿ÑŠÑ‚Ñ Ñ‚Ð¸. Руни на арката " "глаÑÑÑ‚,\n" "\"Кажи ключа и можеш да минеш.\"\n" "Докато произнаÑÑш вълшебната дума, Ñветещата бариера Ñе Ñ€Ð°Ð·Ñ‚Ð²Ð°Ñ€Ñ Ð² нищото." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "МагичеÑка бариера Ñтои виÑоко пред теб и блокира Ð¿ÑŠÑ‚Ñ Ñ‚Ð¸. Руните на арката " "глаÑÑÑ‚,\n" "\"Кажи ключа и можеш да преминеш.\"\n" "Казваш и нищо не Ñе Ñлучва." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Влизаш в палатката и виждаш възраÑтна жена, коÑто Ñе взира в магичеÑки " "Ñкъпоценен камък. Ð¢Ñ Ð²Ð´Ð¸Ð³Ð° поглед и казва:\n" "\"По време на пътуваниÑта Ñи научих много от Ð¿ÑŠÑ‚Ñ Ð½Ð° тайнÑтвената магиÑ. " "Един велик оракул ме научи на умениÑта Ñи. Имам отговора, който търÑиш.\"" msgid "No spell book is present." msgstr "ÐÑма книга ÑÑŠÑ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Това заклинание Ñтрува %{mana} точки магиÑ. ÐÑмаш точки за магиÑ, така че не " "можеш да го направиш." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Това заклинание Ñтрува %{mana} точки магиÑ. Имаш Ñамо %{point} точки магиÑ, " "така че не можеш да го направиш." msgid "The spell was not found." msgstr "Заклинанието не беше намерено." msgid "Only heroes can cast this spell." msgstr "Само герои могат да правÑÑ‚ това заклинание." msgid "This hero is not able to cast adventure spells." msgstr "Този герой не може да прави приключенÑки магии." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "ТвоÑÑ‚ герой е твърде уморен, за да направи това заклинание днеÑ. Опитай " "отново утре." msgid "This spell cannot be cast on a boat." msgstr "Това заклинание не може да Ñе направи на кораб." msgid "This spell can only be cast near an ocean." msgstr "Това заклинание може да Ñе направи Ñамо близо до океан." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "ÐÑма налични лодки и океан в близоÑÑ‚ до героÑ, където това заклинание ще " "работи." msgid "There are no boats available for this spell." msgstr "ÐÑма налични лодки за това заклинание." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "ÐÑма океан в близоÑÑ‚ до героÑ, където това заклинание ще работи." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Ðе притежаваш нито един град или замък, който в момента да не е зает от " "герой. Ðе можеш да направиш това заклинание." msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Този герой вече е в град, така че не можеш да направиш това заклинание." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Ðай-близкиÑÑ‚ град е %{town}.\n" "\n" "Този град е окупиран от Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ %{hero}." msgid "This spell is already in effect." msgstr "Това заклинание вече е в Ñила." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Ðикой противник вече нÑма и не може да има герой под Ñвое командване. " "Изричането на това заклинание нÑма да има ефект." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Ðикой противник нÑма герой под Ñвое командване в момента. Изричането на това " "заклинание нÑма да има ефект." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "ТрÑбва да Ñи в рамките на %{count} интервали от чудовище, за да работи " "заклинанието ВидениÑ." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "ТрÑбва да Ñтоиш на входа на мина (дъÑкорезници и алхимични лаборатории не Ñе " "броÑÑ‚), за да направиш това заклинание." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Първо трÑбва да победиш призраците, които пазÑÑ‚ мината, за да направиш това " "заклинание." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Вече има поне толкова елементали, които пазÑÑ‚ мината, който този герой може " "да генерира. Изричането на това заклинание нÑма да има ефект." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name} е %{race} (Ðиво %{level})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} (Ðиво %{level})" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{name} е %{race} (Ðиво %{level})" #, fuzzy msgid "Hero race:" msgstr "Екран на героÑ" msgid "Are you sure you want to dismiss this Hero?" msgstr "Сигурен ли Ñи, че иÑкаш да отпратиш този герой?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Виж Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° опит" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "МагиÑ" msgid "View Spell Points Info" msgstr "Виж Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° магичеÑките точките" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Губиш героÑ: %{name}." #, fuzzy msgid "Click to change race." msgstr "Кликни, за да покажеш ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³Ñ€Ð°Ð´." #, fuzzy msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Бойната Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ \"РазпръÑкване\" Ñ€Ð°Ð·Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ñ‚Ð²Ð¾Ð¸Ñ‚Ðµ армии от горе до долу на " "бойното поле, Ñ Ð¿Ð¾Ð½Ðµ едно празно проÑтранÑтво между вÑÑка армиÑ." #, fuzzy msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "\"Групираната\" бойна Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð±ÐµÐ´Ð¸Ð½Ñва армиÑта ти в центъра от твоÑта " "Ñтрана на бойното поле." msgid "Exit Hero Screen" msgstr "Изход от екрана на героÑ" msgid "You cannot dismiss a hero in a castle" msgstr "Ðе можеш да отпратиш герой в замък" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Отпращането на %{name} %{race} е забранено от ÑценариÑ" msgid "Dismiss %{name} the %{race}" msgstr "Отпрати %{name} %{race}" msgid "Show previous hero" msgstr "Покажи Ð¿Ñ€ÐµÐ´Ð¸ÑˆÐ½Ð¸Ñ Ð³ÐµÑ€Ð¾Ð¹" msgid "Show next hero" msgstr "Покажи ÑÐ»ÐµÐ´Ð²Ð°Ñ‰Ð¸Ñ Ð³ÐµÑ€Ð¾Ð¹" msgid "Set army combat formation to 'Spread'" msgstr "Задай армейÑка бойна Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ \"РазпръÑкване\"" msgid "Set army combat formation to 'Grouped'" msgstr "Задай армейÑка бойна Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ \"Групирана\"" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Кликни тук, за да избереш кой Ñценарий да играеш." msgid "Blood Morale" msgstr "Кръвен морал" msgid "%{morale} Morale" msgstr "%{morale} Морал" msgid "%{luck} Luck" msgstr "%{luck} КъÑмет" msgid "Current Luck Modifiers:" msgstr "Текущи модификатори на къÑмета:" msgid "Current Morale Modifiers:" msgstr "Текущи модификатори на морала:" msgid "Entire army is undead, so morale does not apply." msgstr "ЦÑлата Ð°Ñ€Ð¼Ð¸Ñ Ðµ немъртва, така че моралът не Ñе прилага." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Текущ опит %{exp1}.\n" " Следващо ниво %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Ðиво %{level}" #, fuzzy msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} в момента има %{point} точки за заклинание от макÑимум %{max}. " "МакÑималниÑÑ‚ брой точки за заклинание е 10 пъти по-голÑм от твойте знаниÑ. " "ПонÑкога е възможно да имаш повече от макÑималните Ñи точки Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸ " "Ñпециални ÑъбитиÑ." msgid "%{name1} meets %{name2}" msgstr "%{name1} Ñреща %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "ВражеÑките герои вече могат да бъдат идентифицирани напълно." msgid "Identify Hero" msgstr "Идентифицирай героÑ" msgid "Select town to port to." msgstr "Избери град за приÑтанище." msgid "Town Portal" msgstr "ГрадÑки портал" msgid "The creatures are willing to join us!" msgstr "СъщеÑтвата Ñа готови да Ñе приÑъединÑÑ‚ към наÑ!" msgid "All the creatures will join us..." msgstr "Ð’Ñички ÑъщеÑтва ще Ñе приÑъединÑÑ‚ към наÑ..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Създанието ще Ñе приÑъедини към наÑ..." msgstr[1] "%{count} от ÑъзданиÑта ще Ñе приÑъединÑÑ‚ към наÑ..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "Ñрещу такÑа от %{gold} злато." msgid "These weak creatures will surely flee before us." msgstr "Тези Ñлаби ÑÑŠÐ·Ð´Ð°Ð½Ð¸Ñ ÑÑŠÑ ÑигурноÑÑ‚ ще избÑгат преди наÑ." msgid "I fear these creatures are in the mood for a fight." msgstr "Страхувам Ñе, че тези ÑъщеÑтва Ñа в наÑтроение за битка." #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Твоето умение за атака е бонуÑ, добавен към умението за атака на вÑÑко " "ÑъщеÑтво." #, fuzzy msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Твоето защитно умение е бонуÑ, добавен към защитното умение на вÑÑко " "ÑъщеÑтво." #, fuzzy msgid "The hero's spell power determines the duration or power of a spell." msgstr "" "ТвоÑта Ñила на заклинание Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ Ð´ÑŠÐ»Ð¶Ð¸Ð½Ð°Ñ‚Ð° или Ñилата на заклинанието." #, fuzzy msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Твойте Ð·Ð½Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»ÑÑ‚ колко точки за заклинание може да има твоÑÑ‚ герой. " "При нормални обÑтоÑтелÑтва един герой е ограничен до 10 точки за заклинание " "за ниво на знание." msgid "Current Modifiers:" msgstr "Текущи модификатори:" msgid "skill|Basic" msgstr "Ðачален" msgid "skill|Advanced" msgstr "Ðапреднал" msgid "skill|Expert" msgstr "ЕкÑперт" msgid "Pathfinding" msgstr "Ориентиране" msgid "Archery" msgstr "Стрелба Ñ Ð»ÑŠÐº" msgid "Logistics" msgstr "ЛогиÑтика" msgid "Scouting" msgstr "Разузнаване" msgid "Diplomacy" msgstr "ДипломациÑ" msgid "Navigation" msgstr "ÐавигациÑ" msgid "Leadership" msgstr "ЛидерÑтво" msgid "Wisdom" msgstr "МъдроÑÑ‚" msgid "Mysticism" msgstr "МиÑтицизъм" msgid "Ballistics" msgstr "БалиÑтика" msgid "Eagle Eye" msgstr "Орлово око" msgid "Necromancy" msgstr "ÐекромантиÑ" msgid "Estates" msgstr "Имоти" msgid "Advanced Archery" msgstr "Стрелба Ñ Ð»ÑŠÐº за напреднали" msgid "Advanced Pathfinding" msgstr "Ðапреднало ориентиране" msgid "Basic Archery" msgstr "Ðачална Ñтрелба Ñ Ð»ÑŠÐº" msgid "Basic Pathfinding" msgstr "Ðачално ориентиране" msgid "Expert Pathfinding" msgstr "ЕкÑперт ориентиране" msgid "Advanced Logistics" msgstr "Ðапреднала логиÑтика" msgid "Basic Logistics" msgstr "Ðачална логиÑтика" msgid "Basic Scouting" msgstr "Ðачално разузнаване" msgid "Expert Archery" msgstr "ЕкÑпертна Ñтрелба Ñ Ð»ÑŠÐº" msgid "Expert Logistics" msgstr "ЕкÑпертна логиÑтика" msgid "Advanced Diplomacy" msgstr "Ðапреднала дипломациÑ" msgid "Advanced Scouting" msgstr "Ðапреднало разузнаване" msgid "Basic Diplomacy" msgstr "Ðачална дипломациÑ" msgid "Expert Diplomacy" msgstr "ЕкÑпертна дипломациÑ" msgid "Expert Scouting" msgstr "ЕкÑпертно разузнаване" msgid "Advanced Leadership" msgstr "Ðапреднало лидерÑтво" msgid "Advanced Navigation" msgstr "Ðапреднала навигациÑ" msgid "Basic Leadership" msgstr "Ðачално лидерÑтво" msgid "Basic Navigation" msgstr "Ðачална навигациÑ" msgid "Expert Navigation" msgstr "ЕкÑпертна навигациÑ" msgid "Advanced Wisdom" msgstr "Ðапреднала мъдроÑÑ‚" msgid "Basic Mysticism" msgstr "Ðачален миÑтицизъм" msgid "Basic Wisdom" msgstr "Ðачална мъдроÑÑ‚" msgid "Expert Leadership" msgstr "ЕкÑпертно лидерÑтво" msgid "Expert Wisdom" msgstr "ЕкÑпертна мъдроÑÑ‚" msgid "Advanced Luck" msgstr "Ðапреднал къÑмет" msgid "Advanced Mysticism" msgstr "Ðапреднал миÑтицизъм" msgid "Basic Luck" msgstr "Ðачален къÑмет" msgid "Expert Luck" msgstr "ЕкÑпертен къÑмет" msgid "Expert Mysticism" msgstr "ЕкÑпертен миÑтицизъм" msgid "Advanced Ballistics" msgstr "Ðапреднала балиÑтика" msgid "Advanced Eagle Eye" msgstr "Ðапреднал орлово око" msgid "Basic Ballistics" msgstr "Ðачална балиÑтика" msgid "Basic Eagle Eye" msgstr "Ðачално орлово око" msgid "Expert Ballistics" msgstr "ЕкÑпертна балиÑтика" msgid "Advanced Necromancy" msgstr "Ðапреднала некромантиÑ" msgid "Basic Estates" msgstr "Ðачални имоти" msgid "Basic Necromancy" msgstr "Ðачална некромантиÑ" msgid "Expert Eagle Eye" msgstr "ЕкÑпертно орлово око" msgid "Expert Necromancy" msgstr "ЕкÑпертна некромантиÑ" msgid "Advanced Estates" msgstr "Ðапреднали имоти" msgid "Expert Estates" msgstr "ЕкÑперт имоти" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} намалÑва наказанието за движение по неравен терен Ñ %{count} " "процента." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} елиминира наказанието за движение при неравен терен." #, fuzzy msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} елиминира %{count} процента наказание за твойте войÑки, ÑтрелÑщи " "покрай препÑÑ‚ÑÑ‚Ð²Ð¸Ñ (напр. Ñтени на замък)." #, fuzzy msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" "%{skill} увеличава точките за движение на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ Ñ %{count} процента." #, fuzzy msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} увеличава видимата облаÑÑ‚ на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ Ñ ÐµÐ´Ð½Ð¾ квадратче." msgstr[1] "" "%{skill} увеличава видимата облаÑÑ‚ на Ñ‚ÐµÐ¾Ñ Ð³ÐµÑ€Ð¾Ð¹ Ñ %{count} квадрата." #, fuzzy msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} ти позволÑва да преговарÑш Ñ Ñ‡ÑƒÐ´Ð¾Ð²Ð¸Ñ‰Ð°, които Ñа по-Ñлаби от вашата " "група. " #, fuzzy msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Приблизително %{count} процента от ÑъщеÑтвата може да предложат да Ñе " "приÑъединÑÑ‚ към теб." #, fuzzy msgid "All of the creatures may offer to join the hero." msgstr "Ð’Ñички ÑъщеÑтва може да предложат да Ñе приÑъединÑÑ‚ към теб." #, fuzzy msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "%{name} намалÑва цената на предаването до %{count} процента от общата цена " "на войÑките, които имаш във твоÑта армиÑ." #, fuzzy msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "%{skill} увеличава точките за движение на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ над вода Ñ %{count} " "процента." #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} повишава морала на войниците на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ Ñ %{count}." #, fuzzy msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} позволÑва на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ да научи магии от трето ниво." #, fuzzy msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} позволÑва на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ да научи Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾Ñ‚ четвърто ниво." #, fuzzy msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} позволÑва на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ да научи Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾Ñ‚ пето ниво." #, fuzzy msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" "%{skill} регенерира една допълнителна точка заклинание на ден на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹." msgstr[1] "" "%{skill} регенерира %{count} допълнителни заклинателни точки на ден за Ñ‚Ð²Ð¾Ñ " "герой." #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} увеличава къÑмета на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ Ñ %{count}." #, fuzzy msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} дава по-голÑм ÑˆÐ°Ð½Ñ Ð½Ð° катапултните изÑтрели на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ да уцели " "и да нанеÑе щети на Ñтените на замъка." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} дава допълнителен изÑтрел на катапулта на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ и вÑеки " "изÑтрел има по-голÑм ÑˆÐ°Ð½Ñ Ð´Ð° уцели и да нанеÑе щети на Ñтените на замъка." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} дава допълнителен изÑтрел на катапулта на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ и вÑеки " "изÑтрел автоматично разрушава вÑÑка Ñтена, Ñ Ð¸Ð·ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ðµ на укрепена Ñтена в " "рицарÑки замък." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} дава на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ %{count} процента ÑˆÐ°Ð½Ñ Ð´Ð° научи вражеÑко " "заклинание от 1-во или 2-ро ниво, използвано Ñрещу него в битка." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} дава на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ %{count} процента ÑˆÐ°Ð½Ñ Ð´Ð° научи заклинание от 3-" "то ниво (или по-ниÑко), използвано Ñрещу него в битка." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} дава на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ %{count} процента ÑˆÐ°Ð½Ñ Ð´Ð° научи заклинание от 4-" "то ниво (или по-ниÑко), използвано Ñрещу него в битка." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} позволÑва на %{count} процента от ÑъщеÑтвата, убити в битка, да " "бъдат върнати от мъртвите като Ñкелети." #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "ТвоÑÑ‚ герой произвежда %{count} златни монети на ден като данъчни приходи от " "имоти." msgid "Blue" msgstr "Син" msgid "Green" msgstr "Зелен" msgid "Red" msgstr "Червен" msgid "Yellow" msgstr "Жълт" msgid "Orange" msgstr "Оранжев" msgid "Purple" msgstr "Лилав" msgid "barrier|Aqua" msgstr "Воден" msgid "barrier|Blue" msgstr "Син" msgid "barrier|Brown" msgstr "КафÑв" msgid "barrier|Gold" msgstr "Златен" msgid "barrier|Green" msgstr "Зелен" msgid "barrier|Orange" msgstr "Оранжев" msgid "barrier|Purple" msgstr "Лилав" msgid "barrier|Red" msgstr "Червен" msgid "tent|Aqua" msgstr "Воден" msgid "tent|Blue" msgstr "СинÑ" msgid "tent|Brown" msgstr "КафÑва" msgid "tent|Gold" msgstr "Златна" msgid "tent|Green" msgstr "Зелена" msgid "tent|Orange" msgstr "Оранжева" msgid "tent|Purple" msgstr "Лилава" msgid "tent|Red" msgstr "Червена" msgid "Experience" msgstr "Опит" #, fuzzy msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Опитът позволÑва на твойте герои да Ñе изкачват нагоре по нивата, " "увеличавайки Ñвоите първични и вторични умениÑ." msgid "Hero/Stats" msgstr "Герой/СтатиÑтика" msgid "Skills" msgstr "УмениÑ" msgid "Town/Castle" msgstr "Град/Замък" msgid "Garrison" msgstr "Гарнизон" msgid "Gold Per Day:" msgstr "Злато на ден:" msgid "View Heroes." msgstr "Виж геройте" msgid "Towns/Castles" msgstr "Градове/Замъци" msgid "View Towns and Castles." msgstr "Виж градовете и замъците." msgid "luck|Cursed" msgstr "Прокълнат" msgid "luck|Awful" msgstr "УжаÑен" msgid "luck|Bad" msgstr "Лош" msgid "luck|Normal" msgstr "Ðормален" msgid "luck|Good" msgstr "Добър" msgid "luck|Great" msgstr "ЧудеÑен" msgid "luck|Irish" msgstr "ИрландÑки" #, fuzzy msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Лош къÑмет понÑкога ÑполетÑва твойте армии в битка, което кара техните атаки " "да нанаÑÑÑ‚ Ñамо половината щети." #, fuzzy msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Ðеутрален къÑмет означава, че армиите ти никога нÑма да получат къÑмет или " "злощаÑтни атаки Ñрещу врага." #, fuzzy msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "ДобриÑÑ‚ къÑмет понÑкога позволÑва на твойте армии да получават къÑметлийÑки " "атаки (двойна Ñила) в битка." msgid "morale|Treason" msgstr "ИзмÑна" msgid "morale|Awful" msgstr "УжаÑен" msgid "morale|Poor" msgstr "Слаб" msgid "morale|Normal" msgstr "Ðормален" msgid "morale|Good" msgstr "Добър" msgid "morale|Great" msgstr "ЧудеÑен" msgid "morale|Blood!" msgstr "Кървав!" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "ЛошиÑÑ‚ морал може да накара армиите ти да замръзнат в битка." #, fuzzy msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Ðеутрален морал означава, че твойте армии никога нÑма да бъдат благоÑловени " "Ñ Ð´Ð¾Ð¿ÑŠÐ»Ð½Ð¸Ñ‚ÐµÐ»Ð½Ð¸ атаки или да замръзнат в битка." #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "ДобриÑÑ‚ морал може да даде на твойте армии допълнителни атаки в битка." msgid "Knight" msgstr "Рицар" msgid "Barbarian" msgstr "Варварин" msgid "Sorceress" msgstr "МагьоÑница" msgid "Warlock" msgstr "МагьоÑник" msgid "Wizard" msgstr "Вълшебник" msgid "Necromancer" msgstr "Ðекромант" msgid "Multi" msgstr "СмеÑен" msgid "doubleLined|Knight" msgstr "Рицар" msgid "doubleLined|Barbarian" msgstr "Варварин" msgid "doubleLined|Sorceress" msgstr "" "МагьоÑ-\n" "ница" msgid "doubleLined|Warlock" msgstr "" "МагьоÑ-\n" "ник" msgid "doubleLined|Wizard" msgstr "" "Вълшеб-\n" "ник" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Ðекро-\n" "мант" msgid "doubleLinedRace|Multi" msgstr "" "Комбина-\n" "циÑ" msgid "doubleLinedRace|Random" msgstr "Случаен" msgid "speed|Standing" msgstr "СтоÑща" msgid "speed|Crawling" msgstr "ПълзÑща" msgid "speed|Very Slow" msgstr "Мн. бавна" msgid "speed|Slow" msgstr "Бавна" msgid "speed|Average" msgstr "Средна" msgid "speed|Fast" msgstr "Бърза" msgid "speed|Very Fast" msgstr "Мн. бърза" msgid "speed|Ultra Fast" msgstr "Суп. бърза" msgid "speed|Blazing" msgstr "ПламтÑща" msgid "speed|Instant" msgstr "Мигновена" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Катерицата" msgid "week|Rabbit" msgstr "Заека" msgid "week|Gopher" msgstr "Гризача" msgid "week|Badger" msgstr "Язовеца" msgid "week|Rat" msgstr "Плъха" msgid "week|Eagle" msgstr "Орела" msgid "week|Weasel" msgstr "ÐевеÑтулката" msgid "week|Raven" msgstr "Гарвана" msgid "week|Mongoose" msgstr "МангуÑтата" msgid "week|Dog" msgstr "Кучето" msgid "week|Aardvark" msgstr "МравоÑда" msgid "week|Lizard" msgstr "Гущера" msgid "week|Tortoise" msgstr "КоÑтенурката" msgid "week|Hedgehog" msgstr "Таралежа" msgid "week|Condor" msgstr "Кондора" msgid "week|Ant" msgstr "Мравката" msgid "week|Grasshopper" msgstr "Скакалеца" msgid "week|Dragonfly" msgstr "Водното конче" msgid "week|Spider" msgstr "ПаÑка" msgid "week|Butterfly" msgstr "Пеперудата" msgid "week|Bumblebee" msgstr "Земната пчела" msgid "week|Locust" msgstr "Скакалеца" msgid "week|Earthworm" msgstr "Ð—ÐµÐ¼ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€Ð²ÐµÐ¹" msgid "week|Hornet" msgstr "Стършела" msgid "week|Beetle" msgstr "Бръмбара" msgid "week|PLAGUE" msgstr "ЧУМÐТÐ" msgid "week|Unnamed" msgstr "БезимениÑ" msgid "Desert" msgstr "ПуÑтинÑ" msgid "Snow" msgstr "СнÑг" msgid "Wasteland" msgstr "ПуÑтош" msgid "Beach" msgstr "Плаж" msgid "Lava" msgstr "Лава" msgid "Dirt" msgstr "ПръÑÑ‚" msgid "Grass" msgstr "Трева" msgid "Ocean" msgstr "Океан" msgid "maps|Small" msgstr "Малка" msgid "maps|Medium" msgstr "Средна" msgid "maps|Large" msgstr "ГолÑма" msgid "maps|Extra Large" msgstr "Много голÑма" msgid "maps|Custom Size" msgstr "големина по избор" msgid "Ore Mine" msgstr "Мина за руда" msgid "Sulfur Mine" msgstr "Мина за ÑÑра" msgid "Crystal Mine" msgstr "Мина за криÑтал" msgid "Gems Mine" msgstr "Мина за Ñкъпоценни камъни" msgid "Gold Mine" msgstr "Мина за злато" msgid "Mine" msgstr "Мина" msgid "Burma shave." msgstr "Като не щеш мира на ти Ñекира." msgid "Next sign 50 miles." msgstr "Следваща табела 50 мили." msgid "See Rock City." msgstr "Виж Ñкален град." msgid "This space for rent." msgstr "Това проÑтранÑтво е под наем." msgid "No object" msgstr "ÐÑма обект" msgid "Alchemist Lab" msgstr "Ðлхимична лабораториÑ" msgid "Sign" msgstr "Знак" msgid "Buoy" msgstr "Шамандура" msgid "Skeleton" msgstr "Скелет" msgid "Daemon Cave" msgstr "ДемонÑка пещера" msgid "Treasure Chest" msgstr "Сандък ÑÑŠÑ Ñъкровище" msgid "Faerie Ring" msgstr "Приказен пръÑтен" msgid "Campfire" msgstr "Лагерен огън" msgid "Fountain" msgstr "Фонтан" msgid "Gazebo" msgstr "БеÑедка" msgid "Genie Lamp" msgstr "Джин от лампа" msgid "Archer's House" msgstr "Къщата на Ñтрелеца" msgid "Goblin Hut" msgstr "Хижата на гоблините" msgid "Dwarf Cottage" msgstr "Вила на джуджета" msgid "Peasant Hut" msgstr "СелÑка хижа" msgid "Stables" msgstr "Конюшни" msgid "Alchemist's Tower" msgstr "Кулата на алхимика" msgid "Event" msgstr "Събитие" msgid "Dragon City" msgstr "Драконов град" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Фар" msgstr[1] "Фарове" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Водно колело" msgstr[1] "Водни колела" msgid "Monster" msgstr "Чудовище" msgid "Obelisk" msgstr "ОбелиÑк" msgid "Oasis" msgstr "ОазиÑ" msgid "Resource" msgstr "РеÑурÑ" msgid "Sawmill" msgstr "ДъÑкорезница" msgid "Oracle" msgstr "Оракул" msgid "Shrine of the First Circle" msgstr "Светилището на Ð¿ÑŠÑ€Ð²Ð¸Ñ ÐºÑ€ÑŠÐ³" msgid "Shipwreck" msgstr "Корабокрушение" msgid "Sea Chest" msgstr "МорÑки Ñандък" msgid "Desert Tent" msgstr "ПуÑтинна палатка" msgid "Stone Liths" msgstr "Телепорт" msgid "Wagon Camp" msgstr "Вагонен лагер" msgid "Hut of the Magi" msgstr "Хижата на влъхвите" msgid "Whirlpool" msgstr "Водовъртеж" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Ð’Ñтърна мелница" msgstr[1] "Ð’Ñтърни мелници" msgid "Mermaid" msgstr "РуÑалка" msgid "Boat" msgstr "Кораб" msgid "Random Ultimate Artifact" msgstr "Случаен върховен артефакт" msgid "Random Artifact" msgstr "Случаен артефакт" msgid "Random Resource" msgstr "Случаен реÑурÑ" msgid "Random Monster" msgstr "Случайно чудовище" msgid "Random Town" msgstr "Случаен град" msgid "Random Castle" msgstr "Случаен замък" msgid "Eye of the Magi" msgstr "Окото на влъхвите" msgid "Random Monster - weak" msgstr "Случайно чудовище - Ñлабо" msgid "Random Monster - medium" msgstr "Случайно чудовище - Ñредно" msgid "Random Monster - strong" msgstr "Случайно чудовище - Ñилно" msgid "Random Monster - very strong" msgstr "Случайно чудовище - мн. Ñилно" #, fuzzy msgid "Hero" msgstr "Герой" msgid "Nothing Special" msgstr "Ðищо Ñпециално" msgid "Mossy Rock" msgstr "МъхеÑта Ñкала" msgid "Watch Tower" msgstr "Стражева кула" msgid "Tree House" msgstr "Къща на дърво" msgid "Tree City" msgstr "Град на дърво" msgid "Ruins" msgstr "Руини" msgid "Fort" msgstr "Укрепление" msgid "Abandoned Mine" msgstr "ИзоÑтавена мина" msgid "Sirens" msgstr "Сирени" msgid "Standing Stones" msgstr "Кромлех" msgid "Idol" msgstr "Идол" msgid "Tree of Knowledge" msgstr "Дърво на познанието" msgid "Witch Doctor's Hut" msgstr "Хижата на врачката" msgid "Temple" msgstr "Храм" msgid "Hill Fort" msgstr "Укрепление в хълмовете" msgid "Halfling Hole" msgstr "Дупка на Хобити" msgid "Mercenary Camp" msgstr "Лагер на наемниците" msgid "Shrine of the Second Circle" msgstr "Светилището на Ð²Ñ‚Ð¾Ñ€Ð¸Ñ ÐºÑ€ÑŠÐ³" msgid "Shrine of the Third Circle" msgstr "Светилището на Ñ‚Ñ€ÐµÑ‚Ð¸Ñ ÐºÑ€ÑŠÐ³" msgid "City of the Dead" msgstr "Градът на мъртвите" msgid "Sphinx" msgstr "СфинкÑ" msgid "Wagon" msgstr "Вагон" msgid "Tar Pit" msgstr "Катранена Ñма" msgid "Artesian Spring" msgstr "ÐртезианÑки извор" msgid "Troll Bridge" msgstr "МоÑтът на троловете" msgid "Watering Hole" msgstr "Дупка за поливане" msgid "Witch's Hut" msgstr "Хижата на вещиците" msgid "Xanadu" msgstr "КÑанаду" msgid "Lean-To" msgstr "Ðаклонена" msgid "Magellan's Maps" msgstr "Картите на Магелан" msgid "Flotsam" msgstr "Сал" msgid "Derelict Ship" msgstr "ИзоÑтавен кораб" msgid "Shipwreck Survivor" msgstr "Корабокрушенец" msgid "Bottle" msgstr "Бутилка" msgid "Magic Well" msgstr "МагичеÑки кладенец" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "МагичеÑка градина" msgstr[1] "МагичеÑки градини" msgid "Observation Tower" msgstr "Ðаблюдателна кула" msgid "Freeman's Foundry" msgstr "ЛеÑрна на Фрийман" msgid "Reefs" msgstr "Рифове" msgid "Volcano" msgstr "Вулкан" msgid "Flowers" msgstr "ЦветÑ" msgid "Rock" msgstr "Скала" msgid "Water Lake" msgstr "Водно езеро" msgid "Mandrake" msgstr "Мандрагора" msgid "Dead Tree" msgstr "Мъртво дърво" msgid "Stump" msgstr "Пън" msgid "Crater" msgstr "Кратер" msgid "Cactus" msgstr "КактуÑ" msgid "Mound" msgstr "Могила" msgid "Dune" msgstr "Дюна" msgid "Lava Pool" msgstr "БаÑейн от лава" msgid "Shrub" msgstr "ХраÑÑ‚" msgid "Barrow Mounds" msgstr "Гробни могили" msgid "Random Artifact - Treasure" msgstr "Случаен артефакт - Съкровище" msgid "Random Artifact - Minor" msgstr "Случаен артефакт - незначителен" msgid "Random Artifact - Major" msgstr "Случаен артефакт - оÑновен" msgid "Barrier" msgstr "Бариера" msgid "Traveller's Tent" msgstr "Палатка на пътешеÑтвеник" msgid "Jail" msgstr "Затвор" msgid "Fire Summoning Altar" msgstr "Олтар за призоваване на огън" msgid "Air Summoning Altar" msgstr "Олтар за призоваване на въздух" msgid "Earth Summoning Altar" msgstr "Олтар за призоваване на земÑ" msgid "Water Summoning Altar" msgstr "Олтар за призоваване на вода" #, fuzzy msgid "Swampy Lake" msgstr "Блато" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "ÐеизвеÑтни чудовища" msgid "Unknown Monster" msgstr "ÐеизвеÑтно чудовище" msgid "Peasant" msgstr "СелÑнин" msgid "Peasants" msgstr "СелÑни" msgid "Archer" msgstr "Стрелец" msgid "Archers" msgstr "Стрелци" msgid "Ranger" msgstr "ЛеÑничей" msgid "Rangers" msgstr "леÑничеи" msgid "Pikeman" msgstr "ПиконоцеÑ" msgid "Pikemen" msgstr "ПиконоÑци" msgid "Veteran Pikeman" msgstr "ÐŸÐ¸ÐºÐ¾Ð½Ð¾Ñ†ÐµÑ Ð²ÐµÑ‚ÐµÑ€Ð°Ð½" msgid "Veteran Pikemen" msgstr "ПиконоÑци ветерани" msgid "Swordsman" msgstr "Фехтовач" msgid "Swordsmen" msgstr "Фехтовачи" msgid "Master Swordsman" msgstr "МайÑтор фехтовач" msgid "Master Swordsmen" msgstr "МайÑтори фехтовачи" msgid "Cavalries" msgstr "КавалериÑти" msgid "Cavalry" msgstr "КавалериÑ" msgid "Champion" msgstr "Шампион" msgid "Champions" msgstr "Шампиони" msgid "Paladin" msgstr "Паладин" msgid "Paladins" msgstr "Паладини" msgid "Crusader" msgstr "КръÑтоноÑец" msgid "Crusaders" msgstr "КръÑтоноÑци" msgid "Goblin" msgstr "Гоблин" msgid "Goblins" msgstr "Гоблини" msgid "Orc" msgstr "Орк" msgid "Orcs" msgstr "Орки" msgid "Orc Chief" msgstr "Орк вожд" msgid "Orc Chiefs" msgstr "Орки вождове" msgid "Wolf" msgstr "Вълк" msgid "Wolves" msgstr "Вълци" msgid "Ogre" msgstr "ЧовекоÑдец" msgid "Ogres" msgstr "ЧовекоÑдци" msgid "Ogre Lord" msgstr "ЧовекоÑдец лорд" msgid "Ogre Lords" msgstr "ЧовекоÑдци лордове" msgid "Troll" msgstr "Трол" msgid "Trolls" msgstr "Тролове" msgid "War Troll" msgstr "Военен трол" msgid "War Trolls" msgstr "Военни тролове" msgid "Cyclopes" msgstr "Циклопи" msgid "Cyclops" msgstr "Циклоп" msgid "Sprite" msgstr "ФеÑ" msgid "Sprites" msgstr "Феи" msgid "Dwarf" msgstr "Джудже" msgid "Dwarves" msgstr "Джуджета" msgid "Battle Dwarf" msgstr "Бойно джудже" msgid "Battle Dwarves" msgstr "Бойни джуджета" msgid "Elf" msgstr "Елф" msgid "Elves" msgstr "Елфи" msgid "Grand Elf" msgstr "Велик елф" msgid "Grand Elves" msgstr "Велики елфове" msgid "Druid" msgstr "Друид" msgid "Druids" msgstr "Друиди" msgid "Greater Druid" msgstr "Велик друид" msgid "Greater Druids" msgstr "Велики друиди" msgid "Unicorn" msgstr "Еднорог" msgid "Unicorns" msgstr "Еднорози" msgid "Phoenix" msgstr "ФеникÑ" msgid "Phoenixes" msgstr "ФеникÑи" msgid "Centaur" msgstr "Кентавър" msgid "Centaurs" msgstr "Кентаври" msgid "Gargoyle" msgstr "Гаргойл" msgid "Gargoyles" msgstr "Гаргойли" msgid "Griffin" msgstr "Грифон" msgid "Griffins" msgstr "Грифони" msgid "Minotaur" msgstr "Минотавър" msgid "Minotaurs" msgstr "Минотаври" msgid "Minotaur King" msgstr "Крал Минотавър" msgid "Minotaur Kings" msgstr "Крале Минотавъри" msgid "Hydra" msgstr "Хидра" msgid "Hydras" msgstr "Хидри" msgid "Green Dragon" msgstr "Зелен дракон" msgid "Green Dragons" msgstr "Зелени дракони" msgid "Red Dragon" msgstr "Червен дракон" msgid "Red Dragons" msgstr "Червени дракони" msgid "Black Dragon" msgstr "Черен дракон" msgid "Black Dragons" msgstr "Черени дракони" msgid "Halfling" msgstr "Хобит" msgid "Halflings" msgstr "Хобити" msgid "Boar" msgstr "Глиган" msgid "Boars" msgstr "Глигани" msgid "Iron Golem" msgstr "Железен голем" msgid "Iron Golems" msgstr "Железени големи" msgid "Steel Golem" msgstr "Стоманен голем" msgid "Steel Golems" msgstr "Стоманени големи" msgid "Roc" msgstr "Рух" msgid "Rocs" msgstr "Рух" msgid "Mage" msgstr "МагьоÑник" msgid "Magi" msgstr "Влъхва" msgid "Archmage" msgstr "Ðрхимаг" msgid "Archmagi" msgstr "Ðрхимагове" msgid "Giant" msgstr "Гигант" msgid "Giants" msgstr "Гиганти" msgid "Titan" msgstr "Титан" msgid "Titans" msgstr "Титани" msgid "Skeletons" msgstr "Скелети" msgid "Zombie" msgstr "Зомби" msgid "Zombies" msgstr "Зомбита" msgid "Mutant Zombie" msgstr "Зомби мутант" msgid "Mutant Zombies" msgstr "Зомбита мутанти" msgid "Mummies" msgstr "Мумии" msgid "Mummy" msgstr "МумиÑ" msgid "Royal Mummies" msgstr "КралÑки мумии" msgid "Royal Mummy" msgstr "КралÑка мумиÑ" msgid "Vampire" msgstr "Вампир" msgid "Vampires" msgstr "Вампири" msgid "Vampire Lord" msgstr "ГоÑподарÑÑ‚ на вампирите" msgid "Vampire Lords" msgstr "ГоÑподари на вампирите" msgid "Lich" msgstr "Лич" msgid "Liches" msgstr "Личове" msgid "Power Lich" msgstr "Мощен Лич" msgid "Power Liches" msgstr "Мощни Личове" msgid "Bone Dragon" msgstr "КоÑтен дракон" msgid "Bone Dragons" msgstr "КоÑтни дракони" msgid "Rogue" msgstr "Мошеник" msgid "Rogues" msgstr "Мошеници" msgid "Nomad" msgstr "Ðомад" msgid "Nomads" msgstr "Ðомади" msgid "Ghost" msgstr "Дух" msgid "Ghosts" msgstr "Духове" msgid "Genie" msgstr "Джин" msgid "Genies" msgstr "Джинове" msgid "Medusa" msgstr "Медуза" msgid "Medusas" msgstr "Медузи" msgid "Earth Elemental" msgstr "Земен елементал" msgid "Earth Elementals" msgstr "Земни елементали" msgid "Air Elemental" msgstr "Въздушен елементал" msgid "Air Elementals" msgstr "Въздушни елементали" msgid "Fire Elemental" msgstr "Огнен елементал" msgid "Fire Elementals" msgstr "Огнени елементали" msgid "Water Elemental" msgstr "Воден елементал" msgid "Water Elementals" msgstr "Водни елементали" msgid "Random Monsters" msgstr "Случайни чудовища" msgid "Random Monster 1" msgstr "Случайно чудовище 1" msgid "Random Monsters 1" msgstr "Случайни чудовища 1" msgid "Random Monster 2" msgstr "Случайно чудовище 2" msgid "Random Monsters 2" msgstr "Случайни чудовища 2" msgid "Random Monster 3" msgstr "Случайно чудовище 3" msgid "Random Monsters 3" msgstr "Случайни чудовища 3" msgid "Random Monster 4" msgstr "Случайно чудовище 4" msgid "Random Monsters 4" msgstr "Случайни чудовища 4" msgid "Double shot" msgstr "Двоен изÑтрел" msgid "2-hex monster" msgstr "2-шеÑтоъгълника чудовище" msgid "Double strike" msgstr "Двоен удар" msgid "Double damage to Undead" msgstr "Двойни щети на Ðемъртвеца" msgid "% magic resistance" msgstr "% магичеÑка уÑтойчивоÑÑ‚" msgid "Immune to Mind spells" msgstr "Имунитет към умÑтвени магии" msgid "Immune to Elemental spells" msgstr "Имунитет към магии на елементал" msgid "Immune to Fire spells" msgstr "Имунитет към огнени магии" msgid "Immune to Cold spells" msgstr "Имунитет към ледени магии" msgid "Immune to " msgstr "Имунитет към " msgid "% immunity to %{spell} spell" msgstr "% имунитет към %{spell} магиÑ" msgid "% damage from Elemental spells" msgstr "% щети от магии на елементал" msgid "% damage from %{spell} spell" msgstr "% щети от %{spell} заклинание" msgid "% chance to Dispel beneficial spells" msgstr "% ÑˆÐ°Ð½Ñ Ð·Ð° отблъÑкване на полезни заклинаниÑ" msgid "% chance to Paralyze" msgstr "% ÑˆÐ°Ð½Ñ Ð·Ð° парализиране" msgid "% chance to Petrify" msgstr "% ÑˆÐ°Ð½Ñ Ð·Ð° вкаменÑване" msgid "% chance to Blind" msgstr "% ÑˆÐ°Ð½Ñ Ð·Ð° заÑлепÑване" msgid "% chance to Curse" msgstr "% ÑˆÐ°Ð½Ñ Ð·Ð° проклÑтие" msgid "% chance to cast %{spell} spell" msgstr "% ÑˆÐ°Ð½Ñ Ð´Ð° направиш %{spell} заклинание" msgid "HP regeneration" msgstr "ВъзÑтановÑване на живот" msgid "Two hexes attack" msgstr "Ðтака в два шеÑтоъгълника" msgid "Flyer" msgstr "Летец" msgid "Always retaliates" msgstr "Винаги отмъщава" msgid "Attacks all adjacent enemies" msgstr "Ðтакува вÑички ÑÑŠÑедни врагове" msgid "No melee penalty" msgstr "Без наказание за ръкопашен бой" msgid "Dragon" msgstr "Дракон" msgid "Undead" msgstr "Ðемъртъв" msgid "No enemy retaliation" msgstr "Без вражеÑко отмъщение" msgid "HP drain" msgstr "ИзÑмукване на живот" msgid "Cloud attack" msgstr "Облачна атака" msgid "Decreases enemy's morale by " msgstr "ÐамалÑва морала на врага Ñ" msgid "% chance to halve enemy" msgstr "% ÑˆÐ°Ð½Ñ Ð´Ð° намалиш враговете наполовина" msgid "Soul Eater" msgstr "ДушеÑд" msgid "Elemental" msgstr "Елементал" msgid "No Morale" msgstr "Без морал" #, fuzzy msgid "Earth creature" msgstr "Вербувай ÑъщеÑтва" #, fuzzy msgid "Air creature" msgstr "Вербувай ÑъщеÑтва" #, fuzzy msgid "Fire creature" msgstr "Вербувай ÑъщеÑтва" #, fuzzy msgid "Water creature" msgstr "Водно езеро" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% щети от огнени магии" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% щети от Ñтудени магии" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Премахва вÑички магичеÑки Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾Ñ‚ вÑички ÑъщеÑтва." #, fuzzy msgid "Double damage from Air creatures" msgstr "Двойни щети на Ðемъртвеца" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% щети от огнени магии" #, fuzzy msgid "Double damage from Water creatures" msgstr "Премахва вÑички магичеÑки Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾Ñ‚ вÑички ÑъщеÑтва." msgid "Lightning" msgstr "Светкавица" msgid "% immunity to " msgstr "% имунитет към " msgid "% damage from " msgstr "% щети от " msgid "The three Anduran artifacts magically combine into one." msgstr "Трите артефакта от Ðндуран магичеÑки Ñе комбинират в едно." msgid "View Spells" msgstr "Преглед на магиите" msgid "View %{name} Info" msgstr "Виж Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° %{name}" msgid "Move %{name}" msgstr "ПремеÑти %{name}" msgid "Cannot move the Spellbook" msgstr "Ðе може да Ñе премеÑти книгата Ñ Ð¼Ð°Ð³Ð¸Ð¹" msgid "This item can't be traded." msgstr "Този артикул не може да Ñе търгува." msgid "Invalid Artifact" msgstr "Ðеработещ артефакт" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} увеличава знаниÑта ти Ñ %{count}." msgid "Ultimate Book of Knowledge" msgstr "Върховна книга на знанието" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} увеличава умениÑта ти за атака Ñ %{count}." msgid "Ultimate Sword of Dominion" msgstr "Върховен меч на гоÑподÑтвото" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} увеличава твойте ÑƒÐ¼ÐµÐ½Ð¸Ñ Ð·Ð° защита Ñ %{count}." msgid "Ultimate Cloak of Protection" msgstr "Върховно наметало за защита" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} увеличава Ñилата на заклинанието ти Ñ %{count}." msgid "Ultimate Wand of Magic" msgstr "Върховна магичеÑка пръчка" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} увеличава твойте ÑƒÐ¼ÐµÐ½Ð¸Ñ Ð·Ð° атака и защита Ñ Ð¿Ð¾ %{count} вÑÑко." msgid "Ultimate Shield" msgstr "Върховен щит" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} увеличава твоÑта магичеÑка Ñила и Ð·Ð½Ð°Ð½Ð¸Ñ Ñ %{count} вÑеки." msgid "Ultimate Staff" msgstr "Върховен жезъл" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} увеличава вÑÑко от вашите оÑновни ÑƒÐ¼ÐµÐ½Ð¸Ñ Ñ %{count} точки." msgid "Ultimate Crown" msgstr "Върховна корона" msgid "Golden Goose" msgstr "Златна гъÑка" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} ноÑи доход от %{count} злато на ден." msgid "Arcane Necklace of Magic" msgstr "ТайнÑтвена огърлица на магиÑта" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "След като ÑпаÑи магьоÑница от прокълната гробница, Ñ‚Ñ Ð²ÑŠÐ·Ð½Ð°Ð³Ñ€Ð°Ð¶Ð´Ð°Ð²Ð° Ñ‚Ð²Ð¾Ñ " "героизъм Ñ Ð¸Ð·Ñщна огърлица ÑÑŠÑ Ñкъпоценни камъни." msgid "Caster's Bracelet of Magic" msgstr "МагичеÑка гривна на ЗаклинателÑ" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Докато търÑиш Ñред отломките на пропаднала мина, оÑвобождаваш група хванати " "в капан джуджета. Благодарен, лидерът им ти дава златна гривна." msgid "Mage's Ring of Power" msgstr "МагьоÑничеÑки пръÑтенът на Ñилата" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Вик на болка те отвежда до кентавър, хванат в капан. След като оÑвобождаваш " "Ñъзданието, то ти подава малка торбичка. Изпразвайки Ñъдържанието, намираш " "оÑлепителен пръÑтен ÑÑŠÑ Ñкъпоценни камъни." msgid "Witch's Broach of Magic" msgstr "МагичеÑка брошка на вещица" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "До оÑтанките на изгорена вещица лежи краÑива брошка ÑÑŠÑ Ñложен дизайн. " "Приближаваш предпазливо Ñ‚Ñлото, ти добавÑш брошката към инвентара Ñи." msgid "Medal of Valor" msgstr "Медал за доблеÑÑ‚" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} увеличава знаниÑта ти Ñ %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "ОÑвобождавайки добродетелна девойка от лапите на зъл владетел, ти получаваш " "Медал за доблеÑÑ‚ от кралÑÐºÐ¸Ñ Ð³Ð»Ð°ÑˆÐ°Ñ‚Ð°Ð¹." msgid "Medal of Courage" msgstr "Медал за храброÑÑ‚" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "След като ÑпаÑÑваш младо момче от жеÑтока глутница вълци, ти го връщаш в " "имението на баща му. БлагодарниÑÑ‚ благородник те награждава Ñ Ð¼ÐµÐ´Ð°Ð» за " "храброÑÑ‚." msgid "Medal of Honor" msgstr "Медал на чеÑтта" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "След като оÑвободи принцеÑа от ÑÑŠÑедно кралÑтво от злите лапи на презрени " "роби, Ñ‚Ñ Ñ‚Ðµ награждава Ñ ÐœÐµÐ´Ð°Ð» на чеÑтта." msgid "Medal of Distinction" msgstr "Медал на унищожението" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "ОÑвобождавайки провинциÑта от Ð¾Ñ‚Ð²Ñ€Ð°Ñ‚Ð¸Ñ‚ÐµÐ»Ð½Ð¸Ñ ÐœÐ¸Ð½Ð¾Ñ‚Ð°Ð²ÑŠÑ€, който Ñе забавлÑваше " "Ñ Ð¸Ð·Ñждането на рицари на благородници, ти Ñи удоÑтоен Ñ ÐœÐµÐ´Ð°Ð»." msgid "Fizbin of Misfortune" msgstr "Медал на нещаÑтието" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} значително намалÑва морала ти Ñ %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Ðатъкваш Ñе на медал край Ð¿Ñ€Ð°Ð·Ð½Ð¸Ñ Ð¿ÑŠÑ‚. ДобавÑйки медала към инвентара Ñи, " "разбираш, че Ñи Ñе Ñдобили Ñ Ð½ÐµÐ¶ÐµÐ»Ð°Ð½Ð¸Ñ ÐœÐµÐ´Ð°Ð» на нещаÑтието, което значително " "намалÑва морала на твоÑта армиÑ." msgid "Thunder Mace of Dominion" msgstr "Гръмотевичен боздуган на гоÑподÑтвото" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "По време на внезапна Ð±ÑƒÑ€Ñ Ð¼ÑŠÐ»Ð½Ð¸Ñ ÑƒÐ´Ñ€Ñ ÐµÐ´Ð½Ð¾ дърво и го разцепва. Вътре в " "дървото намираш миÑтериозен боздуган." msgid "Armored Gauntlets of Protection" msgstr "Бронирани ръкавици за защита" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} повишава умениÑта ти за защита Ñ %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Срещаш проÑÐ»Ð¾Ð²ÑƒÑ‚Ð¸Ñ Ð§ÐµÑ€ÐµÐ½ рицар! След изтощителен дуел, завършил наравно, " "РицарÑÑ‚, от уважение, ти предлага чифт бронирани ръкавици." msgid "Defender Helm of Protection" msgstr "Защитен шлем на защитата" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "ОтблÑÑък на златна Ñветлина привлича окото ти. При по-нататъшно проучване " "намираш златен шлем, Ñкрит под един храÑÑ‚." msgid "Giant Flail of Dominion" msgstr "ГигантÑка бухалка на гоÑподÑтвото" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Ðепохватен великан Ñе е Ñамоубил ÑÑŠÑ ÑобÑтвената Ñи бухалка. Знаейки " "превъзходните Ñи ÑƒÐ¼ÐµÐ½Ð¸Ñ Ñ Ñ‚Ð¾Ð²Ð° оръжие, ти уверено отÑтранÑваш зрелищната " "бухалка от Ð¿Ð°Ð´Ð½Ð°Ð»Ð¸Ñ Ð’ÐµÐ»Ð¸ÐºÐ°Ð½." msgid "Ballista of Quickness" msgstr "Катапулт на бързината" #, fuzzy msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "%{name} позволÑва на Ñ‚Ð²Ð¾Ñ ÐºÐ°Ñ‚Ð°Ð¿ÑƒÐ»Ñ‚ един допълнителен изÑтрел на боен рунд." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Разхождайки Ñе из руините на древен ограден град, намираш инÑтрумент за " "унищожаването на градове, Ñложно изработена балиÑта." msgid "Stealth Shield of Protection" msgstr "Стелт щит за защита" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Каменна ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° воин държи Ñребърен щит. Когато премахваш щита, ÑтатуÑта " "Ñе разпада на прах." msgid "Dragon Sword of Dominion" msgstr "Драконов меч на гоÑподÑтвото" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Докато вървиш по Ñ‚ÑÑна пътека, близкиÑÑ‚ храÑÑ‚ внезапно избухва в пламъци. " "Пред очите ти пламъците Ñе превръщат в образ на краÑива жена. Ð¢Ñ Ñ‚Ð¸ подава " "великолепен меч." msgid "Power Axe of Dominion" msgstr "Мощна брадва на гоÑподÑтвото" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Виждаш Ñребърна брадва забита дълбоко в земÑта. След нÑколко неуÑпешни опита " "на твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ð´Ð° извади брадвата, ти ÑтиÑкаш здраво дръжката на брадвата и " "без уÑилие Ñ Ð¸Ð·Ð´ÑŠÑ€Ð¿Ð²Ð°Ñˆ." msgid "Divine Breastplate of Protection" msgstr "БожеÑтвен нагръдник на защита" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Банда мошеници преглежда притежаниÑта на мъртви воини. Изплашвайки " "чиÑтачите, забелÑзваш, че те Ñа пропуÑнали краÑив нагръдник." msgid "Minor Scroll of Knowledge" msgstr "Малък Ñвитък на знанието" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Пред теб Ñе поÑвÑва левитираща Ñтъклена витрина ÑÑŠÑ Ñвитък, кацнал върху " "легло от пурпурно кадифе. При твоето докоÑване капакът Ñе Ð¾Ñ‚Ð²Ð°Ñ€Ñ Ð¸ Ñвитъкът " "изплува в очакващите ти ръце." msgid "Major Scroll of Knowledge" msgstr "ГолÑм Ñвитък на знанието" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "ПоÑещаваш меÑтен мъдрец, и му обÑÑнÑваш целта на твоето пътуване. Той бръква " "в един чувал, вади пожълтÑл Ñвитък и ти го подава." msgid "Superior Scroll of Knowledge" msgstr "Превъзходен Ñвитък на знанието" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Ðатъкваш Ñе на оÑтанките на древен друид. КоÑти, пожълтели от възраÑтта, " "надничат от дрипавите гънки на неговата роба. ПретърÑвайки мантиÑта, " "откриваш Ñвитък, Ñкрит в гънките." msgid "Foremost Scroll of Knowledge" msgstr "Ðай-важниÑÑ‚ Ñвитък на знанието" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Ðаранени коÑти, пожълтели от възраÑтта, надничат от парцаливите гънки на " "мантиÑта на мъртъв друид. ПретърÑвайки мантиÑта, откриваш Ñвитък, Ñкрит " "вътре." msgid "Endless Sack of Gold" msgstr "Безкраен чувал злато" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} ти оÑигурÑва %{count} злато на ден." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Малък леприкон танцува веÑело около вълшебен чувал. Виждайки, че Ñе " "приближаваш, той Ñпира. Той крещи и тропа Ñвирепо Ñ ÐºÑ€Ð°Ðº, изчезвайки във " "въздуха. СпомнÑш Ñи поговорката на ÑÑ‚Ð°Ñ€Ð¸Ñ Ð»ÐµÐ¿Ñ€Ð¸ÐºÐ¾Ð½ \"Ðамерители, пазители\", " "грабваш чувала и Ñи тръгваш." msgid "Endless Bag of Gold" msgstr "Безкрайна торба злато" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Благородничка, отделена от Ñпътниците Ñи, моли за твоÑта помощ. След като Ñ " "придружаваш до дома и, Ñ‚Ñ Ñ‚Ðµ награждава Ñ Ñ‚Ð¾Ñ€Ð±Ð° пълна ÑÑŠÑ Ð·Ð»Ð°Ñ‚Ð¾." msgid "Endless Purse of Gold" msgstr "Безкрайна кеÑÐ¸Ñ Ð·Ð»Ð°Ñ‚Ð¾" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "По време на пътуваниÑта Ñи откриваш кожена кеÑÐ¸Ñ Ð¿ÑŠÐ»Ð½Ð° ÑÑŠÑ Ð·Ð»Ð°Ñ‚Ð¾, коÑто " "нÑкога е принадлежала на велик цар-воин, който е имал ÑпоÑобноÑтта да " "превърне вÑеки неодушевен предмет в злато." msgid "Nomad Boots of Mobility" msgstr "ÐомадÑки ботуши на подвижноÑтта" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "%{name} увеличава движението ти на Ñушата." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "ÐомадÑки търговец търÑи защита от племе гоблини. За твоÑта помощ той ти дава " "фино изработен чифт ботуши, изработени от най-меката кожа. Вглеждайки Ñе " "внимателно, виждаш очарователни древни шарки, гравирани върху кожата." msgid "Traveler's Boots of Mobility" msgstr "ПътничеÑки ботуши на подвижноÑтта" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Откривайки чифт украÑени Ñ Ð¼ÑŠÐ½Ð¸Ñта ботуши, изработени от най-фината и мека " "кожа, ти благодариш на Ð°Ð½Ð¾Ð½Ð¸Ð¼Ð½Ð¸Ñ Ð´Ð°Ñ€Ð¸Ñ‚ÐµÐ» и добавÑш ботушите към инвентара Ñи." msgid "Lucky Rabbit's Foot" msgstr "Заешки крак на къÑмета" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} увеличава къÑмета ти в битка Ñ %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Пътуващ търговец ти предлага заешки крак, изработен от блеÑÑ‚Ñща Ñребърна " "козина, за безопаÑно преминаване. Търговецът обÑÑнÑва, че чарът ще увеличи " "къÑмета ти в битка." msgid "Golden Horseshoe" msgstr "Златна подкова" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Един впримчен еднорог хленчи от Ñтрах. Говорейки уÑпокоÑващи думи, ти го " "оÑвобождаваш. Смъркайки и оптечатвайки предноте Ñи копита иведнъж, той " "галопира. Поглеждаш надолу и виждаш златна подкова." msgid "Gambler's Lucky Coin" msgstr "КъÑметлийÑката монета на комарджиÑта" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Ти залови пакоÑтлив имп, който тероризира региона. Ð’ замÑна на " "оÑвобождаването Ñи, той те възнаграждава Ñ Ð¼Ð°Ð³Ð¸Ñ‡ÐµÑка монета." msgid "Four-Leaf Clover" msgstr "ЧетирилиÑтна детелина" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Ð’ Ñредата на парче мъртва и Ñуха раÑтителноÑÑ‚, за Ñ‚Ð²Ð¾Ñ Ð¸Ð·Ð½ÐµÐ½Ð°Ð´Ð° откриваш " "здрава зелена четирилиÑтна детелина." msgid "True Compass of Mobility" msgstr "ИÑтинÑки ÐºÐ¾Ð¼Ð¿Ð°Ñ Ð½Ð° подвижноÑтта" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} увеличава движението ти по Ñуша и море." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Старец, който твърди, че е изобретател, те моли да опиташ най-новото му " "изобретение. След това ти подава компаÑ." msgid "Sailor's Astrolabe of Mobility" msgstr "МорÑшка аÑÑ‚Ñ€Ð¾Ð»Ð°Ð±Ð¸Ñ Ð½Ð° подвижноÑтта" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} увеличава движението ти по море." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Един Ñтар морÑки капитан е измъчван от огрите. Ти го ÑпаÑÑваш, а в замÑна " "той те възнаграждава Ñ Ñ‡ÑƒÐ´ÐµÐ½ инÑтрумент за измерване на разÑтоÑнието до " "звезда." msgid "Evil Eye" msgstr "Окото на Злото" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} намалÑва разходите за правене на проклÑÑ‚Ð¸Ñ Ð½Ð°Ð¿Ð¾Ð»Ð¾Ð²Ð¸Ð½Ð°." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "РиÑкуваш да влезеш в порутена колиба, намираш Ñкелета на отдавна мъртва " "вещица. ИзÑледването на оÑтанките разкрива Ñтъклено око, което Ñе Ñ‚ÑŠÑ€ÐºÐ°Ð»Ñ Ð² " "празен череп." msgid "Enchanted Hourglass" msgstr "ОмагьоÑан пÑÑъчен чаÑовник" #, fuzzy msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} удължава продължителноÑтта на вÑичките ти Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ñ %{count} хода." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Изненадващ обрат в пейзажа ти открива ужаÑÑваща Ñцена: лешоÑди, човъркащи " "Ñлед ужаÑна битка. Беглото ти търÑене на оÑтанките открива омагьоÑан пÑÑъчен " "чаÑовник." msgid "Gold Watch" msgstr "Златен чаÑовник" #, fuzzy msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} удвоÑва ефективноÑтта на твойте магии за хипноза." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Като награда за това, че Ñи помогнал на количката му да излезе от канавка, " "пътуващ продавач на отвари ти дава \"магичеÑки\" златен чаÑовник. Без да " "знае, чаÑовникът наиÑтина е вълшебен." msgid "Skullcap" msgstr "Кепе" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} намалÑва наполовина разходите за правене на вÑички магии за влиÑние " "върху ума." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Кратка Ñпирка в невероÑтна ÑелÑка Ñтранноприемница води до размÑна на пари, " "приказки и Ñлучаен багаж. Ðамирате магичеÑка шапка в новата Ñи раница." msgid "Ice Cloak" msgstr "Ледено наметало" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} намалÑва наполовина вÑички щети, които твойте войÑки понаÑÑÑ‚ от " "Ñтудените магии." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "ОтговарÑш на паничеÑките викове на девойка в беда, оказва Ñе млада жена, " "коÑто бÑга от гладна мечка. Ти убиваш звÑра навреме, а благодарната " "МагьоÑница изтъкава вълшебно наметало от кожата на мечката." msgid "Fire Cloak" msgstr "Огнено наметало" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} намалÑва наполовина вÑички щети, които твойте войÑки нанаÑÑÑ‚ от " "огнени магии." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Попадаш на битка между некромант и паладин. Ðекромантът взривÑва Паладина Ñ " "огнена Ñтрела, карайки го да падне на колене. ДейÑтвайки бързо, ти убиваш " "Ð·Ð»Ð¾Ð´ÐµÑ Ð¿Ñ€ÐµÐ´Ð¸ поÑÐ»ÐµÐ´Ð½Ð¸Ñ ÑƒÐ´Ð°Ñ€. БлагодарниÑÑ‚ Паладин ти дава огненото наметало, " "което го е ÑпаÑило." msgid "Lightning Helm" msgstr "Светкавичен шлем" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} намалÑва наполовина вÑички щети, нанеÑени от твойте войÑки от " "Ñветкавични заклинаниÑ." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Пътуващ калайджиÑ, нуждаещ Ñе от провизии, ти предлага шлем Ñ Ð³Ñ€ÑŠÐ¼Ð¾Ñ‚ÐµÐ²Ð¸Ñ†Ð° на " "върха му в замÑна на храна и вода. Любопитен, ти приемаш и по-къÑно " "разбираш, че шлемът е магичеÑки." msgid "Evercold Icicle" msgstr "Вечноледена виÑулка" #, fuzzy msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} кара твойте Ñтудени магии да нанаÑÑÑ‚ %{count} процента повече щети " "на вражеÑките войÑки." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Ледена виÑулка, издържаща на топлина на обедното Ñлънце, привлича вниманието " "ти. Заинтригуван, ти Ñ Ð¾Ñ‚Ñ‡ÑƒÐ¿Ð²Ð°Ñˆ и уÑтановÑваш, че не Ñе топи в ръката ти." msgid "Everhot Lava Rock" msgstr "Вечногореща Ñкала" #, fuzzy msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} кара огнените ти Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð´Ð° нанаÑÑÑ‚ %{count} процента повече щети " "на вражеÑките войÑки." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Твойте ÑÐºÐ¸Ñ‚Ð°Ð½Ð¸Ñ Ñ‚Ðµ Ñрещат Ñ Ð¿Ð»ÐµÐ¼Ðµ маймуноподобни ÑъщеÑтва, използващи " "магичеÑка Ñкала от лава, коÑто никога не изÑтива за да палÑÑ‚ огньовете Ñи. " "Ти ги ÑъжалÑваш и ги учиш да палÑÑ‚ огън Ñ Ñ‚Ð¾Ñги. Ð’Ñрвайки, че Ñи бог, " "маймуните ти дават ÑвоÑта Ñкала." msgid "Lightning Rod" msgstr "Гръмотевичен жезъл" #, fuzzy msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} кара твойте Ñветкавични Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð´Ð° нанаÑÑÑ‚ %{count} процента " "повече щети на вражеÑките войÑки." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Докато изчакваш бурÑ, гръм поразÑва гръмоотвода на близката вила, който Ñе " "ÑÑ‚Ð°Ð¿Ñ Ð¸ пада на земÑта. Върхът на пръта обаче оÑтава непокътнат и кара " "коÑата ти да наÑтръхва, когато го докоÑваш. Хм..." msgid "Snake-Ring" msgstr "ЗмийÑки пръÑтен" #, fuzzy msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} намалÑва наполовина разходите за правене на вÑички твой благоÑлавÑщи " "магии." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Ðамираш пръÑтен ÑÑŠÑ Ñтранна форма на пръÑта на отдавна мъртъв пътник. " "ПръÑтенът прилича на змиÑ, захапала ÑобÑтвената Ñи опашка." msgid "Ankh" msgstr "Ðнх" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} удвоÑва ефективноÑтта на вÑичките ти Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð·Ð° възкреÑÑване и " "оживÑване." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Свирепа Ð±ÑƒÑ€Ñ Ñ€Ð°Ð·ÐºÑ€Ð¸Ð²Ð° входа на заровена гробница. Твоето разÑледване " "разкрива, че гробницата вече е била ограбена, но крадците не Ñа забелÑзали " "Ðнх на Ñребърна верига в тъмното." msgid "Book of Elements" msgstr "Книга на елементите" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} удвоÑва ефективноÑтта на вÑичките ти магии за призоваване." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Попадаш на фокуÑник, който моли да придружи теб и армиÑта ти извеÑтно време " "за да е в безопаÑноÑÑ‚. Ти Ñе ÑъглаÑÑваш и той предлага като заплащане копие " "от Книгата на елементите." msgid "Elemental Ring" msgstr "ПръÑтен на елементал" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" "%{name} намалÑва наполовина разходите за правене на вÑички магии за " "призоваване." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Докато Ñпираш за почивка, забелÑзваш Ñ€Ð¸Ñ Ð´Ð° Ñе катери по ниÑко дърво, за да " "Ñтигне до гарваново гнездо. ИмпулÑивно ти решаваш да Ñе качиш на дървото и " "изплашиш котката. Когато поглеждаш в гнездото, намираш ÐºÐ¾Ð»ÐµÐºÑ†Ð¸Ñ Ð¾Ñ‚ блеÑÑ‚Ñщи " "камъни и пръÑтен." msgid "Holy Pendant" msgstr "Свещен медальон" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} прави вÑичките ти войÑки имунизирани Ñрещу магии за проклÑтиÑ." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Ð’ ÑкитаниÑта Ñи попадаш на отшелник, живеещ в малка Ñпретната колиба. " "Впечатлен от твоÑта миÑиÑ, той пркъÑва Ñвоите медитации, за да те благоÑлови " "и да ти даде Ð¼Ð°Ð³Ð¸Ñ Ñрещу проклÑтиÑ." msgid "Pendant of Free Will" msgstr "Медальон на Ñвободната волÑ" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" "%{name} прави вÑичките ти войÑки имунизирани Ñрещу хипнотизиращи магии." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "ОтговарÑйки на виковете за помощ, откриваш речни духове, които Ñе готвÑÑ‚ да " "потапÑÑ‚ един Ñтарец. Решаваш да ÑпаÑиш човека и за наказание влачиш един " "речен дух на Ñушата за извеÑтно време. Духът, който Ñе чувÑтва неудобно във " "въздуха, ти дава магичеÑка медальон, за да го пуÑнеш." msgid "Pendant of Life" msgstr "Медальон на живота" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} прави вÑичките ти войÑки имунизирани Ñрещу магии за Ñмърт." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Кратка крайпътна Ñреща Ñ Ð¼Ð°Ð»ÐºÐ° каравана и игра на кокалчета печели магичеÑка " "виÑулка. БившиÑÑ‚ му ÑобÑтвеник казва, че предпазва от Ñмъртните магии на " "некромантите." msgid "Serenity Pendant" msgstr "Медальон на ÑпокойÑтвието" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} прави вÑичките ти войÑки имунизирани Ñрещу полудÑващи магии." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Звуците на битка привличат вниманието ти към битка между Ñтар варварин и " "оÑемглава хидра. ТвоÑта навременна намеÑа обръща битката в полза на мъжа и " "той те възнаграждава Ñ Ð¼ÐµÐ´Ð°Ð»ÑŒÐ¾Ð½Ð°, който е използвал за да уÑпокои ума Ñи за " "битка." msgid "Seeing-eye Pendant" msgstr "Медальон Ð’Ñевиждащо око" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" "%{name} прави вÑичките ти войÑки имунизирани Ñрещу Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð·Ð° Ñлепота." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Срещаш много Ñтара жена, отдавна ÑлÑпа от катаракта и умираща Ñама. Ти Ñе " "погрижваш за Ð½ÐµÑ Ð¸ и обещаваш подходÑщо погребение. С благодарноÑÑ‚, Ñ‚Ñ Ñ‚Ð¸ " "дава вълшебен медальон, украÑен ÑÑŠÑ Ñтилизирано око. ПозволÑва ти да виждаш " "ÑÑŠÑ Ð·Ð°Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð¸ очи." msgid "Kinetic Pendant" msgstr "Кинетичен медальон" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name} прави вÑичките ти войÑки имунизирани Ñрещу парализиращи магии." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Срещаш голем, ноÑещ Ñветещ медальон и препречващ Ð¿ÑŠÑ‚Ñ Ñ‚Ð¸. Интуитивно, " "отрÑзваш медальона от шиÑта му. Лишен от ÑÐ²Ð¾Ñ Ð¸Ð·Ñ‚Ð¾Ñ‡Ð½Ð¸Ðº на енергиÑ, големът " "Ñе разпада, оÑтавÑйки ти магичеÑката Ñи виÑулка." msgid "Pendant of Death" msgstr "Медальона на Ñмъртта" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} прави вÑичките ти войÑки имунизирани Ñрещу Ñвещени заклинаниÑ." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Бърза и ÑмъртоноÑна битка Ñ Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚ ти печели Ð½ÐµÐ³Ð¾Ð²Ð¸Ñ Ð¼Ð°Ð³Ð¸Ñ‡ÐµÑки медальон. " "По-къÑно вълшебникът ти казва, че медальонът защитава немъртвите под твой " "контрол от Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ ÑÑŠÑ Ñвещени думи." msgid "Wand of Negation" msgstr "Жезъл на отрицанието" #, fuzzy msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "%{name} прави вÑичките ти войÑки имунизирани Ñрещу разÑейващи магии." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Срещаш Ñтар твой приÑтел вълшебник, който пътува в обратната поÑока. Той ти " "предÑÑ‚Ð°Ð²Ñ Ð¿Ð¾Ð´Ð°Ñ€ÑŠÐº: жезъл, който предотвратÑва използването на магичеÑкото " "заклинание за разÑейване на твойте Ñъюзници." msgid "Golden Bow" msgstr "Златен лък" #, fuzzy msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} елиминира %{count} процента наказание за твойте войÑки, ÑтрелÑщи " "покрай препÑÑ‚ÑÑ‚Ð²Ð¸Ñ (напр. Ñтени на замък)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Случайна Ñреща Ñ Ð¸Ð·Ð²ÐµÑтен Ñтрелец ти открива в игра на кокалчета, коÑто " "Ð¸Ð·Ð¿Ñ€Ð°Ð²Ñ Ð»ÑŠÐºÐ° му Ñрещу ÐºÐ¾Ð½Ñ Ñ‚Ð¸. Ти печелиш." msgid "Telescope" msgstr "ТелеÑкоп" #, fuzzy msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} увеличава терена, който твоÑÑ‚ герой разкрива при приключение Ñ " "%{count} допълнителен квадрат." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Търговец от далечни земи Ñ€Ð°Ð·Ð¼ÐµÐ½Ñ Ñ Ñ‚ÐµÐ± ново изобретение на ÑÐ²Ð¾Ñ Ð½Ð°Ñ€Ð¾Ð´ за " "провизии за пътуване. Изобретението кара отдалечените обекти да изглеждат по-" "близки и той го нарича...\n" "\n" "телеÑкоп." msgid "Statesman's Quill" msgstr "Перото на държавника" #, fuzzy msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} намалÑва цената на предаването до %{count} процента от общата цена " "на войÑките, които имаш във твоÑта армиÑ." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Спираш, за да помогнеш на дипломат ÑÑŠÑ Ñчупена Ð¾Ñ Ð´Ð° реши проблема Ñи. Ð’ " "знак на благодарноÑÑ‚ той ти дава перо за пиÑане Ñ Ð¼Ð°Ð³Ð¸Ñ‡ÐµÑки ÑвойÑтва, което " "Ñпоред него ще \"помогне на хората да видÑÑ‚ нещата по Ñ‚Ð²Ð¾Ñ Ð½Ð°Ñ‡Ð¸Ð½\"." msgid "Wizard's Hat" msgstr "Шапката на вълшебника" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "" "%{name} увеличава продължителноÑтта на заклинаниÑта ти Ñ %{count} хода." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Виждш вълшебник, който бÑга от грифон и Ñзди като вÑтъра. Вълшебникът Ð¾Ñ‚Ð²Ð°Ñ€Ñ " "портал и минава през него, когато шапката му е Ñъборена от ръба на портала. " "Грифонът го поÑледва и портала Ñе затварÑ. Вдигаш шапката, избърÑваш праха " "от Ð½ÐµÑ Ð¸ Ñ Ñлагаш." msgid "Power Ring" msgstr "ПръÑтена на Ñилата" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "%{name} връща %{count} допълнителни точки Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð½Ð° ден на Ñ‚Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Ðамираш малко дърво, което много прилича на Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ Ð¼Ð°Ð³ÑŒÐ¾Ñник Карнаут Ñ " "пръÑтен около една от клонките му. Парчета от дрехи и гниеща кожа те карат " "да подозираш, че това е Карнаут, транÑформиран в дърво. Тъй като не можеш да " "му помогнеш, взимаш магичеÑÐºÐ¸Ñ Ð¿Ñ€ÑŠÑтен." msgid "Ammo Cart" msgstr "Количка Ñ Ð±Ð¾ÐµÐ¿Ñ€Ð¸Ð¿Ð°Ñи" #, fuzzy msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} оÑигурÑва безкрайни боеприпаÑи за вÑички твой войÑки, които ÑтрелÑÑ‚." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Количка Ñ Ð±Ð¾ÐµÐ¿Ñ€Ð¸Ð¿Ð°Ñи в Ñредата на Ñтаро бойно поле привлича вниманието ти. " "Проверката ти показва, че е в добро ÑÑŠÑтоÑние, така че Ñ Ð²Ð·ÐµÐ¼Ð°Ñˆ ÑÑŠÑ Ñебе Ñи." msgid "Tax Lien" msgstr "Данъчен залог" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} ти Ñтрува %{count} златни монети на ден." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Твойте лоши навици за харчене Ñа ти Ñпечелили огромна данъчна Ñметка, коÑто " "не можеш да платиш. ДанъчниÑÑ‚ Ñе ÑмилÑва и Ñе ÑъглаÑÑва да взема Ñамо по 250 " "злато на ден от Ñметката ти за цÑл живот. Провери тук, ако иÑкаш един долар " "да отиде във фонда за президентÑките избори." msgid "Hideous Mask" msgstr "Отвратителна маÑка" #, fuzzy msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "%{name} не позволÑва на вÑички \"Ñкитащи\" армии да Ñе приÑъединÑÑ‚ към Ñ‚Ð²Ð¾Ñ " "герой." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Твоето плÑчкоÑване на гроба на Ð¡Ð¸Ð½Ñ„Ð¸Ð»Ð°Ñ Ð“Ð°Ñ€Ð´Ð¾Ð»Ð°Ð´, извеÑтниÑÑ‚ магьоÑник " "променÑщ формата Ñи, открива легендарната му маÑка. С нетърпение Ñ Ñлагаш и " "Ñ‚Ñ Ð¸Ð·ÐºÑ€Ð¸Ð²Ñва лицето ти в ужаÑна гримаÑа! О, не! Това вÑъщноÑÑ‚ е " "Отвратителната маÑка на Громлак Грийн и ти Ñи оÑтаваш Ñ Ð½ÐµÑ." msgid "Endless Pouch of Sulfur" msgstr "Безкрайна кеÑÐ¸Ñ ÑÑŠÑ ÑÑра" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} оÑигурÑва %{count} единица ÑÑра на ден." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "ПоÑещаваш алхимик, който Ñлед като вижда твоÑта армиÑ, е поразен от " "праведноÑтта на твоÑта кауза. ÐовиÑÑ‚ лоÑлен поданик ти дава ÑвоÑта безкрайна " "кеÑÐ¸Ñ ÑÑŠÑ ÑÑра, за да ти помогне във войната." msgid "Endless Vial of Mercury" msgstr "Безкраен муÑкал Ñ Ð¶Ð¸Ð²Ð°Ðº" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} оÑигурÑва %{count} единица живак на ден." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Спираш набързо в изоÑтавена кула на вълшебник и намираш магичеÑки муÑкал Ñ " "живак, в който винаги оÑтава малко на дъното. Разпознаваш това Ñъкровище, " "затварÑш го и го пъхаш в джоба Ñи." msgid "Endless Pouch of Gems" msgstr "Безкрайна кеÑÐ¸Ñ ÑÑŠÑ Ñкъпоценни камъни" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} оÑигурÑва %{count} единица Ñкъпоценни камъни на ден." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Кратка дъждовна Ð±ÑƒÑ€Ñ Ñ€Ð°Ð¶Ð´Ð° дъга... и ти виждаш ÐºÑ€Ð°Ñ Ð¹. Яздейки бързо, ти " "грабваш гърнето ÑÑŠÑ Ð·Ð»Ð°Ñ‚Ð¾, което намираш там. Лепреконът, който го " "притежава, неÑпоÑобен да ти попречи да го вземеш, предлага безкрайна кеÑÐ¸Ñ " "ÑÑŠÑ Ñкъпоценни камъни Ñрещу връщането на златото му. Ти приемаш." msgid "Endless Cord of Wood" msgstr "Безкрайна купчина дърва" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} оÑигурÑва %{count} единица дърва на ден." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Спирайки, за да Ñи починеш и да запалиш огън, вадиш дърва от близка купчина " "дърва. Докато продължаваш да дърпаш дърва от купчината, забелÑзваш, че те не " "намалÑват. Разбираш Ñ Ñ€Ð°Ð´Ð¾ÑÑ‚, че купчината дърва е омагьоÑана, затова Ñ " "взимаш ÑÑŠÑ Ñебе Ñи." msgid "Endless Cart of Ore" msgstr "Безкрайна количка Ñ Ñ€ÑƒÐ´Ð°" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} оÑигурÑва %{count} единица руда на ден." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Откриваш ковачница за Ð¾Ñ€ÑŠÐ¶Ð¸Ñ Ð½Ð° гоблини, коÑто прави Ð¾Ñ€ÑŠÐ¶Ð¸Ñ Ð·Ð° използване " "Ñрещу хората. С огромен вик ти и твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ñе ÑпуÑкате върху лагера им и " "ги прогонвате. При претърÑването откриваш магичеÑка количка Ñ Ñ€ÑƒÐ´Ð°, в коÑто " "желÑзото никога не Ñвършва." msgid "Endless Pouch of Crystal" msgstr "Безкрайна кеÑÐ¸Ñ Ñ ÐºÑ€Ð¸Ñтали" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} оÑигурÑва %{count} единица криÑтал на ден." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Прикривайки Ñе от Ð±ÑƒÑ€Ñ Ð² малка пещера, забелÑзваш малко парче криÑтал в " "ÐµÐ´Ð¸Ð½Ð¸Ñ ÑŠÐ³ÑŠÐ». Любопитно, ти отчупваш парче и забелÑзвате, че оригиналниÑÑ‚ " "криÑтал възÑтановÑва изгубеното парче обратно. Решаваш да напъхаш цÑлото " "парче в торбичка и да го вземеш ÑÑŠÑ Ñебе Ñи." msgid "Spiked Helm" msgstr "Шлем Ñ ÑˆÐ¸Ð¿Ð¾Ð²Ðµ" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "ТвоÑта Ð°Ñ€Ð¼Ð¸Ñ Ðµ нападната от заÑада от малко племе диви (и не твърде умни) " "орки. ЛеÑно ги отблъÑкваш и оцелелите бÑгат във вÑички поÑоки. Един от " "орките ноÑеше полиран шлем Ñ ÑˆÐ¸Ð¿Ð¾Ð²Ðµ. СмÑтайки, че ще Ñтане добър Ñувенир, го " "взимаш." msgid "Spiked Shield" msgstr "Щит Ñ ÑˆÐ¸Ð¿Ð¾Ð²Ðµ" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Стигаш до моÑÑ‚, минаващ през Ñухо дере. Преди да можеш да преминеш, трол " "излиза изпод моÑта и изиÑква плащане, преди да ти позволи да преминеш. " "Отказваш и тролът напада, принуждавайки те да го убиеш. Взимаш щита му Ñ " "шипове като трофей." msgid "White Pearl" msgstr "БÑла перла" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Разходка през дъното на Ñухо Ñоленоводно езеро ноÑи невероÑтна награда: бÑла " "перла Ñред натрошени черупки и отломки." msgid "Black Pearl" msgstr "Черна перла" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Слуховете за грифон Ñ Ð½ÐµÐ¾Ð±Ð¸Ñ‡Ð°Ð¹Ð½Ð¸ размери, който плÑчкоÑва в провинциÑта, те " "отвеждат до неговото пещерно леговище. Бърза и брутална битка ликвидира " "звÑра и при претърÑването на мръÑното му гнездо откриваш огромна черна перла." msgid "Magic Book" msgstr "МагичеÑка книга" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name} ти позволÑва да правиш магии." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Манекен 2" msgid "The reserved artifact." msgstr "ЗапазениÑÑ‚ артефакт." msgid "Dummy 3" msgstr "Манекен 3" msgid "Dummy 4" msgstr "Манекен 4" msgid "Spell Scroll" msgstr "Свитък за заклинание" #, fuzzy msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Това %{name} дава на Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ ÑпоÑобноÑтта да изпълни заклинанието " "%{spell}, ако твоÑÑ‚ герой има магичеÑка книга." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Ðамери натруфена кутиÑ, в коÑто Ñе ÑъхранÑва Ñтар Ñвитък от пергамент. " "Руните по кутиÑта Ñа много Ñтари, майÑторÑки изработени и е Ñглобена " "зашеметÑващо. Докато издърпвате Ñвитъка, Ñе чувÑтвате пропити Ñ Ð¼Ð°Ð³Ð¸Ñ‡ÐµÑка " "Ñила." msgid "Arm of the Martyr" msgstr "Ръката на мъченика" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} увеличава Ñилата на заклинанието ти Ñ %{count}, но Ð´Ð¾Ð±Ð°Ð²Ñ Ð½Ð°ÐºÐ°Ð·Ð°Ð½Ð¸Ðµ " "за морала на немъртвите." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Един от по-малко интелигентните членове на твоÑта група вдига ръка от " "земÑта. Въпреки че липÑва Ñ‚Ñло, Ñ‚Ñ Ð²Ñе още Ñе движи. Твойте войÑки намират " "разчленената ръка за отблъÑкваща, но не можеш да Ñ Ð¾Ñтвиш: изглежда " "притежава нÑкаква магичеÑка Ñила, коÑто влиÑе върху вземането на решениÑ." msgid "Breastplate of Anduran" msgstr "Ðагръдник на Ðндуран" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} увеличава твоÑта защита Ñ %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Попадаш на знак. Той глаÑи: \"Тук лежи Ñ‚Ñлото на Ðндуран. Поклони Ñе и Ñе " "закълни във вÑрноÑÑ‚ и ще бъдеш възнаграден.\" Ти решаваш да направиш както е " "казано. Докато Ñе изправÑш, уÑещаш тръпки по кожата Ñи. Поглеждайки надолу, " "откриваш, че нÑкакÑи ноÑиш блеÑÑ‚Ñщ, богато украÑен нагръдник." msgid "Broach of Shielding" msgstr "Брошка за защита" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} оÑигурÑва %{count} процента защита от Ðрмагедон и Елементна бурÑ, но " "намалÑва Ñилата на заклинаниÑта Ñ 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Любезна магьоÑница ÑмÑта, че защитата на твоÑта Ð°Ñ€Ð¼Ð¸Ñ Ð¼Ð¾Ð¶Ðµ да Ñе нуждае от " "магичеÑки тлаÑък. Ð¢Ñ Ð¿Ñ€ÐµÐ´Ð»Ð°Ð³Ð° да омагьоÑа Брошка, коÑто ноÑиш на наметалото " "Ñи, и ти приемаш." msgid "Battle Garb of Anduran" msgstr "Бойно облекло на Ðндуран" #, fuzzy msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} Ñъчетава Ñилите на трите артефакта от Ðндуран. ОÑигурÑва макÑимален " "къÑмет и морал на твоите войÑки и ти дава заклинанието Портал на града." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "От Ñъжаление към беден ÑелÑнин купуваш Ñандък ÑÑŠÑ Ñтари боклуци, които той " "продава за много злато. По-къÑно, докато го претърÑваш, откриваш, че Ñъдържа " "3-те чаÑти от легендарното бойно облекло на Ðндуран!" msgid "Crystal Ball" msgstr "КриÑтална топка" #, fuzzy msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} ти позволÑва да получиш по-конкретна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° чудовища, " "вражеÑки герои и замъци в близоÑÑ‚ до героÑ, който го държи." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Попадаш на керван от цигани, които пируват и подÑилват Ñ‚Ñлото Ñи Ñ Ð¼ÐµÐ´Ð¾Ð²Ð¸Ð½Ð°. " "Извикват те напред и казват: \"Ðко докажеш, че можеш да танцуваш Рама-Бута, " "ще те възнаградим.\" Ðе го знаеш, но вÑе пак опитваш. Те Ñе ÑмеÑÑ‚ иÑтерично, " "но Ñе възхищават на ÑмелоÑтта ти, давайки ти криÑтална топка." msgid "Heart of Fire" msgstr "Огнено Ñърце" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} оÑигурÑва %{count} процента защита от огън, но удвоÑва щетите, " "причинени от Ñтуд." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Излизаш на наÑкоро опожарена полÑна и попадаш на огнен елементал, Ñеднал на " "върха на една Ñкала. Той поглежда нагоре и пламналото му лице Ñе Ñгърчва в " "израз на Ñилна болка. След това Ñ…Ð²ÑŠÑ€Ð»Ñ Ñветещ обект към теб. Вдигаш ръце, за " "да го блокираш, но той минава точно през Ñ‚ÑÑ… и Ñе врÑзва в гърдите ти." msgid "Heart of Ice" msgstr "Сърце от лед" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} оÑигурÑва %{count} процента защита от Ñтуд, но удвоÑва щетите, " "причинени от огън." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Изведнъж хапеща Ñтуденина поглъща Ñ‚Ñлото ти. Сгърчваш Ñе, падайки от ÐºÐ¾Ð½Ñ " "Ñи. Болката отшумÑва, но вÑе още Ñе чувÑтваш ÑÑкаш гърдите ти Ñа замръзнали. " "Докато Ñе повдигаш от земÑта, чуваш Ñърдечен ÑмÑÑ…. Обръщаш Ñе точно навреме, " "за да видиш леден гигант да Ñе изгубва в гората." msgid "Helmet of Anduran" msgstr "Шлем на Ðндуран" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Виждаш блеÑÑ‚Ñщ обект, който Ñтърчи от земÑта. Изпращаш член на твоÑта група " "да разÑледва. Връща Ñе ÑÑŠÑ Ð·Ð»Ð°Ñ‚ÐµÐ½ шлем в ръце. Разбираш, че това трÑбва да е " "шлемът на Ð»ÐµÐ³ÐµÐ½Ð´Ð°Ñ€Ð½Ð¸Ñ Ðндуран, единÑтвениÑÑ‚ човек, за когото е извеÑтно, че " "ноÑи Ð±Ñ€Ð¾Ð½Ñ Ð¾Ñ‚ маÑивно злато." msgid "Holy Hammer" msgstr "Свещен чук" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Попадаш в битка, в коÑто паладин е бил ÑмъртоноÑно ранен от група зомбита. " "Той те моли да вземеш Ð½ÐµÐ³Ð¾Ð²Ð¸Ñ Ñ‡ÑƒÐº и да завършиш започнатото от него. Когато " "го вдигаш, той оживÑва и размазва вÑички наоколо. Зомбитата лежат мъртви, а " "от чукът капе кръв. Закачаш го на колана Ñи." msgid "Legendary Scepter" msgstr "ЛегендарниÑÑ‚ Ñкиптър" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} Ð´Ð¾Ð±Ð°Ð²Ñ %{count} точки към вÑички атрибути." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "При изкачване на малък хълм Ñе натъкваш на нелепо изглеждаща гледка. Ð¤ÐµÑ Ñе " "опитва да ноÑи Ñкиптър, който е почти толкова голÑм, колкото неÑ. Опитвайки " "Ñе да не Ñе Ñмееш, ти питаш: \"Имаш ли нужда от помощ?\" ФеÑта те гледа " "ÑдоÑано и отговарÑ: \"МиÑлиш, че това е Ñмешно? Добре. Може да го ноÑиш. И " "без това предпочитам да летÑ.\"" msgid "Masthead" msgstr "Мачтов връх" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "%{name} повишава Ñ‚Ð²Ð¾Ñ ÐºÑŠÑмет и морал Ñ %{count} вÑеки в морÑки бой." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Един Ñтар морÑк ти разказва приказка за омагьоÑана Ñфера, коÑто използвал в " "младоÑтта Ñи, за да Ñъбере екипажа Ñи по време на проблеми. След това той ти " "дава избледнÑла карта, коÑто показва къде Ñ Ðµ Ñкрил. След дълго проучване Ñ " "намирате Ñкрита под Ð±Ð»Ð¸Ð·ÐºÐ¸Ñ Ð´Ð¾Ðº." msgid "Sphere of Negation" msgstr "Сфера на отрицанието" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} деактивира вÑички заклинаниÑ, и за двете Ñтрани, в битка." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Спираш, за да помогнеш на ÑелÑнин да хване избÑгала кобила. За да покаже " "ÑвоÑта благодарноÑÑ‚, той ти дава малка Ñфера. Веднага щом Ñ Ñ…Ð²Ð°Ñ‰Ð°Ñˆ, уÑещаш " "как магичеÑката ÐµÐ½ÐµÑ€Ð³Ð¸Ñ Ð·Ð°Ð¿Ð¾Ñ‡Ð²Ð° да Ñтруи от крайниците ти..." msgid "Staff of Wizardry" msgstr "ПерÑоналът на магьоÑничеÑтвото" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} увеличава Ñилата на заклинаниÑта ти Ñ %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Докато плашиш дивеча, твойте войÑки откриват миÑтериозен жезъл, който " "левитира на около три фута над земÑта. Подават ти го и забелÑзваш Ð½Ð°Ð´Ð¿Ð¸Ñ Ð½Ð° " "него. Той глаÑи: \"Мозъците Ñа най-добрите муÑкули и магиÑта бие мощта. " "Ð’Ñлушай Ñе в думите ми и ще Ñпечелиш вÑÑка битка.\"" msgid "Sword Breaker" msgstr "Разбивач на мечове" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} увеличава защитата ти Ñ %{count} и атаката Ñ 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Бивш капитан на гвардиÑта Ñе възхищава на твоÑта миÑÐ¸Ñ Ð¸ ти дава омагьоÑÐ°Ð½Ð¸Ñ " "Разбивач на мечове, на който е разчитал по време на Ñлужбата Ñи." msgid "Sword of Anduran" msgstr "Мечът на Ðндуран" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Трол те Ñпира и казва: \"Плати ми 5000 злато, или Мечът на Ðндуран ще те " "убие там, където Ñтоиш.\" Отказваш. Тролът грабва меча, виÑÑщ на колана му, " "крещи от болка и бÑга. Взимайки Ð»ÐµÐ³ÐµÐ½Ð´Ð°Ñ€Ð½Ð¸Ñ Ð¼ÐµÑ‡, ти благодариш, че " "малоумните тролове Ñа Ñклонни да хващат Ð³Ñ€ÐµÑˆÐ½Ð¸Ñ ÐºÑ€Ð°Ð¹ на оÑтрите предмети." msgid "Spade of Necromancy" msgstr "Пика на некромантиÑта" #, fuzzy msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} ти дава повишено умение за некромантиÑ." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "МръÑна лопата е забита в земна могила наблизо. След проучване откриваш, че " "това е омагьоÑаната лопата на Гробарите, дълго ÑмÑтана за изгубена от " "Ñмъртните." msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Дърво" msgid "Mercury" msgstr "Живак" msgid "Ore" msgstr "Руда" msgid "Sulfur" msgstr "СÑра" msgid "Crystal" msgstr "КриÑтал" msgid "Gems" msgstr "Скъпоценни камъни" msgid "Gold" msgstr "Злато" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Има Ñедем реÑурÑа в \"Герой 2\", използвани за изграждане и подобрÑване на " "замъци, закупуване на войÑки и набиране на герои. Златото е най-чеÑто " "Ñрещаното, необходимо за почти вÑичко. За повечето Ñгради Ñе използват дърво " "и руда. Скъпоценни камъни, живак, ÑÑра и криÑтал Ñа редки магичеÑки реÑурÑи, " "използвани за най-мощните ÑъщеÑтва и Ñгради." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "ПричинÑва удър от гигантÑка огнена топка в избраната облаÑÑ‚, увреждайки " "вÑички близки ÑъщеÑтва." msgid "Fireball" msgstr "Огнена топка" msgid "Fireblast" msgstr "Огнена екÑплозиÑ" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Подобрена верÑÐ¸Ñ Ð½Ð° огнена топка, Огнена екÑÐ¿Ð»Ð¾Ð·Ð¸Ñ Ð·Ð°ÑÑга два хекÑа около " "централната точка на заклинанието, а не един." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "" "ПричинÑва удър на Ñтрелба от електричеÑка ÐµÐ½ÐµÑ€Ð³Ð¸Ñ Ð² избраното Ñъздание." msgid "Lightning Bolt" msgstr "Светкавица" msgid "Chain Lightning" msgstr "Верижна Ñветкавица" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "ПричинÑва Ð¼ÑŠÐ»Ð½Ð¸Ñ Ð¾Ñ‚ електричеÑка ÐµÐ½ÐµÑ€Ð³Ð¸Ñ Ð² избрано ÑъщеÑтво, Ñлед това ÑƒÐ´Ð°Ñ€Ñ " "най-близкото ÑъщеÑтво Ñ Ð¿Ð¾Ð»Ð¾Ð²Ð¸Ð½ щета, Ñлед това ÑƒÐ´Ð°Ñ€Ñ Ð¡Ð›Ð•Ð”Ð’ÐЩОТО най-близко " "ÑъщеÑтво отново Ñ Ð¿Ð¾Ð»Ð¾Ð²Ð¸Ð½ щета и така нататък, докато Ñтане твърде Ñлабо, за " "да бъде вредно. Предупреждение: Това заклинание може да удари твойте " "ÑобÑтвени ÑъщеÑтва!" msgid "Teleport" msgstr "Телепорт" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Телепортира избраното от теб ÑъщеÑтво до произволна отворена Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ Ð½Ð° " "бойното поле." msgid "Cure" msgstr "Лек" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Премахва вÑички негативни заклинаниÑ, хвърлени върху една от твойте единици, " "и възÑтановÑва до %{count} HP на ниво Ñила на заклинанието." msgid "Mass Cure" msgstr "Ð’Ñеобщ лек" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Премахва вÑички негативни заклинаниÑ, хвърлени върху една от твойте единици, " "и възÑтановÑва Живота до %{count} на вÑÑко ниво Ñила на заклинанието." msgid "Resurrect" msgstr "ВъзкреÑÑване" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "ВъзкреÑÑва ÑъщеÑтва от повредена или мъртва единица до ÐºÑ€Ð°Ñ Ð½Ð° битката." msgid "Resurrect True" msgstr "ИÑтинÑко възкреÑÑване" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "ВъзкреÑÑва ÑъщеÑтва от повредена или мъртва единица за поÑтоÑнно." msgid "Haste" msgstr "Бързина" msgid "Increases the speed of any creature by %{count}." msgstr "Увеличава ÑкороÑтта на вÑÑко Ñъздание Ñ %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Увеличава ÑкороÑтта на вÑички ваши ÑъщеÑтва Ñ %{count}." msgid "Mass Haste" msgstr "Ð’Ñеобща бързина" msgid "Slows target to half movement rate." msgstr "Ð—Ð°Ð±Ð°Ð²Ñ Ñ†ÐµÐ»Ñ‚Ð° до половината ÑкороÑÑ‚ на движение." msgid "spell|Slow" msgstr "ЗабавÑне" msgid "Mass Slow" msgstr "Ð’Ñеобщо забавÑне" msgid "Slows all enemies to half movement rate." msgstr "Ð—Ð°Ð±Ð°Ð²Ñ Ð²Ñички врагове до половината ÑкороÑÑ‚ на движение." msgid "spell|Blind" msgstr "Слепота" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "ЗамъглÑва очите на заÑегнатите ÑъщеÑтва, като им пречи да Ñе движат." msgid "Bless" msgstr "БлагоÑловиÑ" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Кара избраните ÑъщеÑтва да нанаÑÑÑ‚ макÑимални щети." msgid "Causes all of your units to inflict maximum damage." msgstr "Кара вÑичките ти единици да нанаÑÑÑ‚ макÑимални щети." msgid "Mass Bless" msgstr "Ð’Ñеобща Ñлепота" msgid "Magically increases the defense skill of the selected creatures." msgstr "МагичеÑки увеличава защитните ÑƒÐ¼ÐµÐ½Ð¸Ñ Ð½Ð° избраните ÑъщеÑтва." msgid "Stoneskin" msgstr "Каменна кожа" msgid "Steelskin" msgstr "Стоманена кожа" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Увеличава защитните ÑƒÐ¼ÐµÐ½Ð¸Ñ Ð½Ð° набелÑзаните ÑъщеÑтва. Това е подобрена верÑÐ¸Ñ " "на Каменна кожа." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Кара избраните ÑъщеÑтва да нанаÑÑÑ‚ минимални щети." msgid "Curse" msgstr "ПроклÑтие" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Кара вÑички вражеÑки войÑки да нанаÑÑÑ‚ минимални щети." msgid "Mass Curse" msgstr "Ð’Ñеобщо проклÑтие" msgid "Damages all undead in the battle." msgstr "ÐанаÑÑ Ñ‰ÐµÑ‚Ð¸ на вÑички немъртви в битката." msgid "Holy Word" msgstr "СвÑто Слово" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "ÐанаÑÑ Ñ‰ÐµÑ‚Ð¸ на вÑички немъртви в битката. Това е подобрена верÑÐ¸Ñ Ð½Ð° СвÑто " "Слово." msgid "Holy Shout" msgstr "Свещен вик" msgid "Anti-Magic" msgstr "ÐнтимагиÑ" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "ПредотвратÑва вредната Ð¼Ð°Ð³Ð¸Ñ Ñрещу избраните ÑъщеÑтва." msgid "Dispel Magic" msgstr "Премахване на магиÑ" msgid "Removes all magic spells from a single target." msgstr "Премахва вÑички магичеÑки Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾Ñ‚ една цел." msgid "Mass Dispel" msgstr "Ð’Ñеобщо премахване на магиÑ" msgid "Removes all magic spells from all creatures." msgstr "Премахва вÑички магичеÑки Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¾Ñ‚ вÑички ÑъщеÑтва." msgid "Causes a magic arrow to strike the selected target." msgstr "Кара магичеÑка Ñтрела да удари избраната цел." msgid "Magic Arrow" msgstr "МагичеÑка Ñтрела" msgid "Berserker" msgstr "БерÑерк" msgid "Causes a creature to attack its nearest neighbor." msgstr "Кара Ñъздание да атакува най-Ð±Ð»Ð¸Ð·ÐºÐ¸Ñ Ñи ÑÑŠÑед." msgid "Armageddon" msgstr "Ðрмагедон" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "СвещениÑÑ‚ ÑƒÐ¶Ð°Ñ Ð²Ñ€ÑŠÑ…Ð»Ð¸Ñ‚Ð° бойното поле, причинÑвайки Ñериозни щети на вÑички " "ÑъщеÑтва." msgid "Elemental Storm" msgstr "Стихийна бурÑ" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "МагичеÑки елементи Ñе изÑипват на бойното поле, увреждайки вÑички ÑъщеÑтва." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Дъжд от камъни ÑƒÐ´Ñ€Ñ Ð·Ð¾Ð½Ð° на бойното поле, увреждайки вÑички близки ÑъщеÑтва." msgid "Meteor Shower" msgstr "Метеоритен дъжд" msgid "Paralyze" msgstr "Парализиране" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "ÐабелÑзаните ÑъщеÑтва Ñа парализирани, не могат да Ñе движат или да отмъÑÑ‚ÑÑ‚." msgid "Hypnotize" msgstr "Хипнотизиране" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "ПоÑÑ‚Ð°Ð²Ñ Ð¿Ð¾Ð´ твой контрол една вражеÑка единица, ако нейните удари Ñа по-" "малко от %{count} пъти Ñилата на заклинанието на заклинателÑ." msgid "Cold Ray" msgstr "Студен лъч" msgid "Drains body heat from a single enemy unit." msgstr "Изцежда телеÑната топлина от една вражеÑка единица." msgid "Cold Ring" msgstr "Студен пръÑтен" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Източва топлината на Ñ‚Ñлото от вÑички единици, заобикалÑщи централната " "точка, но без да включва централната точка." msgid "Disrupting Ray" msgstr "Разрушаващ лъч" msgid "Reduces the defense rating of an enemy unit by three." msgstr "ÐамалÑва рейтинга на отбраната на вражеÑка единица Ñ Ñ‚Ñ€Ð¸." msgid "Damages all living (non-undead) units in the battle." msgstr "ÐанаÑÑ Ñ‰ÐµÑ‚Ð¸ на вÑички живи (не-мъртви) единици в битката." msgid "Death Ripple" msgstr "СмъртоноÑна вълна" msgid "Death Wave" msgstr "Вълна на Ñмъртта" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "ÐанаÑÑ Ñ‰ÐµÑ‚Ð¸ на вÑички живи (не-мъртви) единици в битката. Това заклинание е " "подобрена верÑÐ¸Ñ Ð½Ð° СмъртоноÑна вълна." msgid "Dragon Slayer" msgstr "Убиец на дракони" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Увеличава значително умението за атака на единица Ñрещу дракони." msgid "Blood Lust" msgstr "КръвожадноÑÑ‚" msgid "Increases a unit's attack skill." msgstr "Увеличава умението за атака на единица." msgid "Animate Dead" msgstr "Ðнимирана Ñмърт" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "ВъзкреÑÑва за поÑтоÑнно ÑъщеÑтва от повредена или мъртва немъртва единица." msgid "Mirror Image" msgstr "Огледална картина" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Създава илюзорна единица, коÑто дублира една от твойте ÑъщеÑтвуващи единици. " "Тази илюзорна единица нанаÑÑ Ñъщите щети като оригинала, но ще изчезне, ако " "понеÑе нÑкакви щети." msgid "Shield" msgstr "Щит" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "ÐамалÑва наполовина щетите, получени от далечни атаки за една единица. Ðе " "заÑÑга щетите, получени от кули или балиÑти." msgid "Mass Shield" msgstr "Ð’Ñеобщ щит" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "ÐамалÑва наполовина щетите, получени от далечни атаки за вÑички твой " "единици. Ðе заÑÑга щетите, получени от кули или балиÑти." msgid "Summon Earth Elemental" msgstr "Призови земен елементал" msgid "Summons Earth Elementals to fight for your army." msgstr "Призовава земните елементали да Ñе биÑÑ‚ за твоÑта армиÑ." msgid "Summon Air Elemental" msgstr "Призови въздушен елементал" msgid "Summons Air Elementals to fight for your army." msgstr "Призовава въздушни елементали да Ñе биÑÑ‚ за твоÑта армиÑ." msgid "Summon Fire Elemental" msgstr "Призови огнен елементал" msgid "Summons Fire Elementals to fight for your army." msgstr "Призовава огнени елементали да Ñе биÑÑ‚ за твоÑта армиÑ." msgid "Summon Water Elemental" msgstr "Призови воден елементал" msgid "Summons Water Elementals to fight for your army." msgstr "Призовава водни елементали да Ñе биÑÑ‚ за твоÑта армиÑ." msgid "Damages castle walls." msgstr "Поврежда Ñтените на замъка." msgid "Earthquake" msgstr "ЗеметреÑение" msgid "Causes all mines across the land to become visible." msgstr "Кара вÑички мини по земÑта да Ñтанат видими." msgid "View Mines" msgstr "Виж мините" msgid "Causes all resources across the land to become visible." msgstr "Кара вÑички реÑурÑи в земÑта да Ñтанат видими." msgid "View Resources" msgstr "Виж реÑурÑите" msgid "Causes all artifacts across the land to become visible." msgstr "Кара вÑички артефакти по земÑта да Ñтанат видими." msgid "View Artifacts" msgstr "Виж артефактите" msgid "Causes all towns and castles across the land to become visible." msgstr "Кара вÑички градове и замъци по земÑта да Ñтанат видими." msgid "View Towns" msgstr "Виж градовете" msgid "Causes all Heroes across the land to become visible." msgstr "Кара вÑички герои в цÑлата Ñтрана да Ñтанат видими." msgid "View Heroes" msgstr "Виж героите" msgid "Causes the entire land to become visible." msgstr "Кара цÑлата Ð·ÐµÐ¼Ñ Ð´Ð° Ñтане видима." msgid "View All" msgstr "Виж вÑичко" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" "ПозволÑва на Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ñ‚ÐµÐ»Ñ Ð´Ð° вижда подробна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° вражеÑките герои." msgid "Summon Boat" msgstr "Призови кораб" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Извиква най-близката незаета, приÑтелÑка лодка до ÑÑŠÑедно мÑÑто на брега. " "ПриÑтелÑка лодка е тази, коÑто току-що Ñи поÑтроил или Ñи бил поÑледниÑÑ‚ " "играч, който Ñ Ðµ ползвал." msgid "Allows the caster to magically transport to a nearby location." msgstr "ПозволÑва на Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ñ‚ÐµÐ»Ñ Ð¼Ð°Ð³Ð¸Ñ‡ÐµÑки да Ñе транÑпортира до близко мÑÑто." msgid "Dimension Door" msgstr "Врата между измерениÑта" msgid "Returns the caster to any town or castle currently owned." msgstr "Връща Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ñ‚ÐµÐ»Ñ Ð²ÑŠÐ² вÑеки град или замък, притежаван в момента." msgid "Town Gate" msgstr "ГрадÑка порта" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Връща Ð³ÐµÑ€Ð¾Ñ Ð² град или замък по избор, при уÑловие че е контролиран от теб." msgid "Visions" msgstr "ВидениÑ" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "ВидениÑта предÑказват вероÑÑ‚Ð½Ð¸Ñ Ñ€ÐµÐ·ÑƒÐ»Ñ‚Ð°Ñ‚ от Ñреща Ñ Ð½ÐµÑƒÑ‚Ñ€Ð°Ð»ÐµÐ½ армейÑки лагер." msgid "Haunt" msgstr "Обладаване" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Обладава мина, коÑто контролирате Ñ Ð¿Ñ€Ð¸Ð·Ñ€Ð°Ñ†Ð¸. Тази мина Ñпира да произвежда " "реÑурÑи. (Ðко аз не мога да го запазÑ, никой нÑма да го направи!)" msgid "Set Earth Guardian" msgstr "Задай Земен пазител" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Кара земните елементали да пазÑÑ‚ мина Ñрещу вражеÑки армии." msgid "Set Air Guardian" msgstr "Задай Въздушен паззител" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Кара Въздушни елементали да пазÑÑ‚ мина Ñрещу вражеÑки армии." msgid "Set Fire Guardian" msgstr "Задай Огнен пазител" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Кара Огнени елементали да пазÑÑ‚ мина Ñрещу вражеÑки армии." msgid "Set Water Guardian" msgstr "Задай Воден пазител" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Кара Водни елементали да пазÑÑ‚ мина Ñрещу вражеÑки армии" #, fuzzy msgid "Random Spell" msgstr "Случаен" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "Случаен замък" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "ВкаменÑване" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Превръща заÑегнатото ÑъщеÑтво в камък. Вкаменено ÑъщеÑтво получава " "половината щети от директна атака." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "ÐÑмаш магичеÑка книга, така че не можеш да направиш магиÑ." msgid "No spell to cast." msgstr "ÐÑма Ð¼Ð°Ð³Ð¸Ñ Ð·Ð° правене." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "ТвоÑÑ‚ герой има %{point} оÑтаващи точки магиÑ." msgid "View Adventure Spells" msgstr "Виж приключенÑки магии" msgid "View Combat Spells" msgstr "Виж бойни магии" msgid "View previous page" msgstr "Виж предишната Ñтраница" msgid "View next page" msgstr "Виж Ñледващата Ñтраница" msgid "Close Spellbook" msgstr "Затвори книгата Ñ Ð¼Ð°Ð³Ð¸Ð¹" msgid "View %{spell}" msgstr "Виж %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Това заклинание нанаÑÑ %{damage} точки щети." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Това заклинание призовава\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Това заклинание възÑтановÑва %{hp} живот." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Това заклинание призовава %{count} %{monster} да пазÑÑ‚ мината." msgid "The nearest town is %{town}." msgstr "Ðай-близкиÑÑ‚ град е %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Този град е окупиран от Ñ‚Ð²Ð¾Ñ Ð³ÐµÑ€Ð¾Ð¹ %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Това заклинание контролира до\n" "%{hp} живот." msgid "The ultimate artifact is really the %{name}." msgstr "ВърховниÑÑ‚ артефакт наиÑтина е %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "ВърховниÑÑ‚ артефакт може да бъде намерен в %{name} региони на Ñвета." msgid "north-west" msgstr "Ñеверозапад" msgid "north" msgstr "Ñевер" msgid "north-east" msgstr "Ñевероизток" msgid "west" msgstr "запад" msgid "center" msgstr "център" msgid "east" msgstr "изток" msgid "south-west" msgstr "югозапад" msgid "south" msgstr "юг" msgid "south-east" msgstr "югоизток" msgid "The truth is out there." msgstr "ИÑтината е нÑкъде там." msgid "The dark side is stronger." msgstr "Тъмната Ñтрана е по-Ñилна." msgid "The end of the world is near." msgstr "КраÑÑ‚ на Ñвета е близо." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "КоÑтите на Лорд Убиец Ñа погребани в оÑновата на арената." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Черен дракон ще унищожава титан вÑеки ден от Ñедмицата." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "Той й каза: \"Яда, блÑ, дÑ...\" и тогава Ñ‚Ñ ÐºÐ°Ð·Ð°: \"Бла, бла, бла..." msgid "An unknown force is being resurrected..." msgstr "Ðепозната Ñила възкръÑва..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Проверете най-новата верÑÐ¸Ñ Ð½Ð° играта на\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Избери брой %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Включи на автоматична битка" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "завърши битката в автоматичен режим" #~ msgid "Please Remember" #~ msgstr "МолÑ, запомни" #, fuzzy #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Винаги можеш да промениш разделителната ÑпоÑобноÑÑ‚ на играта, като " #~ "щракнеш върху " #~ msgid "door" #~ msgstr "вратата" #, fuzzy #~ msgid "NEW GAME" #~ msgstr "" #~ "ÐОВÐ\n" #~ "ИГРÐ" #~ msgid "Warning!" #~ msgstr "Внимание!" #~ msgid "Dummy 1" #~ msgstr "Манекен 1" fheroes2-1.1.6+dfsg/files/lang/cs.po000066400000000000000000012051661476115357100171700ustar00rootroot00000000000000# Czech translation for fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-11 14:11+0000\n" "PO-Revision-Date: 2025-02-10 14:34+0100\n" "Last-Translator: fheroes2 team \n" "Language-Team: Czech \n" "Language: cs\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==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" "X-Launchpad-Export-Date: 2010-05-27 09:12+0000\n" "X-Generator: Poedit 3.5\n" msgid "" "NEW\n" "GAME" msgstr "" "NOVÃ\n" "HRA" msgid "" "SAVE\n" "GAME" msgstr "" "ULOŽIT\n" "HRU" msgid "" "LOAD\n" "GAME" msgstr "" "NAHRÃT\n" "HRU" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "KONEC" msgid "" "NEW\n" "MAP" msgstr "" "NOVÃ\n" "HRA" msgid "" "SAVE\n" "MAP" msgstr "" "ULOŽIT\n" "HRU" msgid "" "LOAD\n" "MAP" msgstr "" "NAHRÃT\n" "HRU" msgid "CANCEL" msgstr "ZRUÅ IT" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "PŘIJMI" msgid "DECLINE" msgstr "ZRUÅ IT" msgid "LEARN" msgstr "UÄŒIT" msgid "TRADE" msgstr "VYMĚŇ" msgid "YES" msgstr "ANO" msgid "NO" msgstr "NE" msgid "EXIT" msgstr "PRYÄŒ" msgid "smallerButton|EXIT" msgstr "ZPÄšT" msgid "DISMISS" msgstr "PROPUSŤ" msgid "UPGRADE" msgstr "VYLEPÅ IT" msgid "RESTART" msgstr "OPAKOVAT" msgid "HEROES" msgstr "HRDINOVÉ" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "MÄšSTA/\n" "HRADY" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "X-L" msgid "ALL" msgstr "VÅ E" msgid "SELECT" msgstr "ZVOLIT" msgid "" "STANDARD\n" "GAME" msgstr "" "STANDARDNÃ\n" "HRA" msgid "" "BATTLE\n" "ONLY" msgstr "" "VOLNÃ\n" "BOJ" msgid "" "CAMPAIGN\n" "GAME" msgstr "" "HRÃT\n" "KAMPAŇ" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "HRA\n" "VÃCE\n" "HRÃČŮ" msgid "CONFIG" msgstr "CONFIG" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ORIGINÃLNÃ\n" "KAMPAŇ" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "KAMPAŇ\n" "DATADISKU" msgid "HOT SEAT" msgstr "HORKÉ KŘESLO" msgid "2 PLAYERS" msgstr "2 HRÃÄŒI" msgid "3 PLAYERS" msgstr "3 HRÃÄŒI" msgid "4 PLAYERS" msgstr "4 HRÃÄŒI" msgid "5 PLAYERS" msgstr "5 HRÃČŮ" msgid "6 PLAYERS" msgstr "6 HRÃČŮ" msgid "GIFT" msgstr "DARUJ" msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "OBTÃŽNOST" msgid "VIEW INTRO" msgstr "ZOBRAZIT ÚVOD" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "RESET" msgid "START" msgstr "START" msgid "TOWN" msgstr "MÄšSTO" msgid "CASTLE" msgstr "HRAD" msgid "RESTRICT" msgstr "OMEZIT" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "P\n" "R\n" "O\n" "P\n" "U\n" "S\n" "Ť" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "O\n" "D\n" "E\n" "J\n" "Ã\n" "T" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "H\n" "L\n" "Ã\n" "D\n" "K\n" "A" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "K\n" "A\n" "M\n" "P\n" "A\n" "Ň" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D\n" "N\n" "Ã" msgid "RUMORS" msgstr "POVÄšSTI" msgid "EVENTS" msgstr "UDÃLOSTI" msgid "LANGUAGE" msgstr "JAZYK" msgid "" "AUTO\n" "COMBAT" msgstr "" "AUTOMA-\n" "TICKà BOJ" msgid "" "QUICK\n" "COMBAT" msgstr "" "RYCHLÃ\n" "BOJ" msgid "Warrior" msgstr "VáleÄník" msgid "Builder" msgstr "Stavitel" msgid "Explorer" msgstr "Průzkumník" msgid "None" msgstr "Nic" msgid "" "A few\n" "%{monster}" msgstr "" "Málo\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "NÄ›kolik\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Skupinka\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Houf\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Horda\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Zástup\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Dav\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "MraÄna\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Legie\n" "%{monster}" msgid "army|Few" msgstr "Málo" msgid "army|Several" msgstr "NÄ›kolik" msgid "army|Pack" msgstr "Skupinka" msgid "army|Lots" msgstr "Houf" msgid "army|Horde" msgstr "Horda" msgid "army|Throng" msgstr "Zástup" msgid "army|Swarm" msgstr "Dav" msgid "army|Zounds" msgstr "MraÄna" msgid "army|Legion" msgstr "Legie" msgid "All %{race} troops +1" msgstr "VÅ¡echny %{race} jednotky +1" msgid "NeutralRaceTroops|Neutral" msgstr "Neutrální" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Jednotky z %{count} různých frakcí -%{penalty} postih." msgid "Some undead in army -1" msgstr "Jakýkoli nemrtvý v armádÄ› -1" msgid "" "Default\n" "troop" msgstr "" "Výchozí\n" "jednotka" msgid "View %{name}" msgstr "Zobrazit %{name}" msgid "Move the %{name} " msgstr "PÅ™esunout %{name} " msgid "Move or right click to redistribute %{name}" msgstr "PÅ™esuň nebo pravým klikem pro pÅ™eskup %{name}" msgid "Combine %{name} armies" msgstr "SlouÄit vojska %{name}" msgid "Exchange %{name2} with %{name}" msgstr "ZamÄ›nit %{name2} s %{name}" msgid "Select %{name}" msgstr "Vybrat %{name}" msgid "Cannot move last troop" msgstr "Poslední jednotku nelze pÅ™esunout" msgid "Move the %{name}" msgstr "PÅ™esunout %{name}" msgid "Set %{monster} Count" msgstr "Nastavit poÄet %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} niÄí polovinu nepřátelských jednotek!" msgstr[1] "%{name} niÄí polovinu nepřátelských jednotek!" msgstr[2] "%{name} niÄí polovinu nepřátelských jednotek!" msgid "%{name} has turned off the auto combat" msgstr "%{name} vypnul automatický boj." msgid "%{name} has turned on the auto combat" msgstr "%{name} zapnul automatický boj." msgid "Spell failed!" msgstr "Kouzlo selhalo!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "Artefakt Sféra Negace znemožňuje v této bitvÄ› použít jakékoliv kouzla." msgid "You cannot cast spells without a commanding hero." msgstr "Nemůžete sesílat kouzla bez hrdiny, který by velel." msgid "You have already cast a spell this round." msgstr "V tomto kole si již kouzlil." msgid "That spell will have no effect!" msgstr "Toto kouzlo nebude na nikoho uÄinkovat!" msgid "You may only summon one type of elemental per combat." msgstr "V této bitvÄ› můžeÅ¡ pÅ™ivolat pouze jeden druh elementálů." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Vedle vaÅ¡eho hrdiny není žádné volné místo, kam by se dal Elementál pÅ™ivolat." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Příkop snižuje obrannou sílu útoÄících jednotek o -%{count} a zpomaluje " "jejich pohyb." msgid "Speed: %{speed}" msgstr "Rychlost: %{speed}" msgid "Speed" msgstr "Rychlost" msgid "Off" msgstr "Vyp" msgid "On" msgstr "Zap" msgid "Turn Order" msgstr "PoÅ™adí tahu" msgid "Auto Spell Casting" msgstr "Automické Kouzlení" msgid "Grid" msgstr "Mřížka" msgid "Shadow Movement" msgstr "Stín pohybu" msgid "Shadow Cursor" msgstr "Stín kurzoru" msgid "Audio" msgstr "Zvuk" msgid "Settings" msgstr "Nastavení" msgid "Configure" msgstr "Konfigurovat" msgid "Hot Keys" msgstr "Kláv. zkratky" msgid "Damage Info" msgstr "Å kody" msgid "Set the speed of combat actions and animations." msgstr "Nastavit rychlost akcí a animací v bitvÄ›." msgid "Toggle to display the turn order during the battle." msgstr "Zap/Vyp zobrazení poÅ™adí tahu jednotek v bitvÄ›." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "PÅ™epni, zda za bude poÄítaÄ kouzlit, když je zapnutý automatický boj. " "(Pozn.: Toto nijak neovlivňuje sesílání kouzel pro poÄítaÄem ovládané hráÄe, " "ani rychlý boj.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Zap/Vyp hexagonální mřížku. Mřížka vždy ohraniÄuje pohyb i když je vypnutá. " "Tento pÅ™epínaÄ pouze ovládá, zda bude mřížka viditelná." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "Za/Vyp stín možného pohybu resp. útoku tvých jednotek." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "Zap/Vyp stín aktuální pozice kurzoru myÅ¡i na mřížce." msgid "Change the audio settings of the game." msgstr "ZmÄ›nit nastavení zvuku." msgid "Check and configure all the hot keys present in the game." msgstr "Zkontrolujte a nastavte vÅ¡echny klávesové zkratky dostupné ve hÅ™e." msgid "Toggle to display damage information during the battle." msgstr "PÅ™epnout zobrazení informací o poÅ¡kození bÄ›hem bitvy." msgid "Exit this menu." msgstr "Odejít z menu." msgid "Okay" msgstr "OK" msgid "The enemy has surrendered!" msgstr "Nepřítel se vzdal!" msgid "Their cowardice costs them %{gold} gold." msgstr "Jejich zbabÄ›lost je stojí %{gold} zlata." msgid "The enemy has fled!" msgstr "Nepřítel utekl!" msgid "A glorious victory!" msgstr "Slavné vítÄ›zství!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Za stateÄnost v boji získává %{name} %{exp} zkuÅ¡eností." msgid "The cowardly %{name} flees from battle." msgstr "%{name} zbabÄ›le utíká z bitvy." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} se vzdal nepříteli a odchází v hanbÄ›." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Tvá armáda utrpÄ›la hoÅ™kou porážku a %{name} tÄ› opouÅ¡tí." msgid "Your forces suffer a bitter defeat." msgstr "Tvá armáda utrpÄ›la hoÅ™kou porážku." msgid "Battlefield Casualties" msgstr "Ztráty na bojiÅ¡ti" msgid "Attacker" msgstr "ÚtoÄník" msgid "Defender" msgstr "Obránce" msgid "Click to leave the battle results." msgstr "Kliknutím se rozliÅ¡ení zmÄ›ní na vybrané." msgid "Click to restart the battle in manual mode." msgstr "KliknÄ›te pro restartování bitvy v manuálním režimu." msgid "Restart" msgstr "Opakovat" msgid "You have captured an enemy artifact!" msgstr "UkoÅ™istil si artefakt nepřítele!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Když saháš po %{name}, tak záhadnÄ› zmizí." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Když protivník sahá po %{name}, tak záhadnÄ› zmizí." msgid "Necromancy!" msgstr "Nekromancie!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Nácvikem temného umÄ›ní nekromancie jsi schopen oživit až %{count} usmrcených " "nepřátelských jednotek a povolat je do služby jako %{monster}." msgid "%{name} the %{race}" msgstr "%{name} z rodu %{race}" msgid "Captain of %{name}" msgstr "Velitel %{name}" msgid "Attack" msgstr "Útok" msgid "Defense" msgstr "Obrana" msgid "Spell Power" msgstr "Síla kouzel" msgid "Knowledge" msgstr "Znalosti" msgid "Morale" msgstr "Morálka" msgid "Luck" msgstr "Å tÄ›stí" msgid "Spell Points" msgstr "Mana" msgid "Hero's Options" msgstr "Možnosti hrdiny" msgid "Cast Spell" msgstr "Seslat kouzlo" msgid "Retreat" msgstr "Ústup" msgid "Surrender" msgstr "Vzdát se" msgid "Cancel" msgstr "ZruÅ¡it" msgid "Hero Screen" msgstr "Obrazovka hrdiny" msgid "Captain's Options" msgstr "Možnosti velení" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Seslat magické kouzlo. MůžeÅ¡ použít jenom jednou za kolo. Nové kolo zaÄne až " "když vÅ¡echna stvoÅ™ení provedou svůj tah." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Hrdina ustoupí a opustí své bojovníky. Hrdina bude dostupný pro opÄ›tovné " "najmutí. Hrdina bude mít pouze minimální armádu." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Kapitulace stojí zlato. Pokud vÅ¡ak zaplatíte výkupné, hrdina a vÅ¡echny jeho " "pÅ™eživší jednotky budou opÄ›t dostupné k najmutí. Cena za kapitulaci Äiní " "polovinu celkových nákladů na zbývající jednotky v armádÄ›." msgid "Open Hero Screen to view full information about the hero." msgstr "" "Pro zobrazení kompletních informací o hrdinovi otevÅ™i obrazovku hrdiny." msgid "Return to the battle." msgstr "ZpÄ›t do bitvy." msgid "Not enough gold (%{gold})" msgstr "Nemáš dost zlata (%{gold})" msgid "%{name} states:" msgstr "%{name} říká:" msgid "Captain of %{name} states:" msgstr "Velitel %{name} říká:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"PÅ™ijmu tvou kapitulaci a umožním tobÄ› a tvým jednotkám bezpeÄný odchod za " "%{price} zlata.\"" msgid "View %{monster} info" msgstr "Zobraz info o %{monster}" msgid "Fly %{monster} here" msgstr "PÅ™eleÅ¥ s %{monster} sem" msgid "Move %{monster} here" msgstr "PÅ™esuň %{monster} sem" msgid "Shoot %{monster}" msgstr "VystÅ™el na %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(Zbývá 1 výstÅ™el)" msgstr[1] "(Zbývají %{count} výstÅ™ely)" msgstr[2] "(Zbývá %{count} výstÅ™elů)" msgid "Attack %{monster}" msgstr "ZaútoÄ na %{monster}" msgid "Turn %{turn}" msgstr "Pohnout %{turn}" msgid "Teleport here" msgstr "Teleportovat sem" msgid "Invalid teleport destination" msgstr "Nesprávné místo teleportace" msgid "Cast %{spell} on %{monster}" msgstr "SeÅ¡li %{spell} na %{monster}" msgid "Cast %{spell}" msgstr "SeÅ¡li %{spell}" msgid "Select spell target" msgstr "Vyberte cíl kouzla" msgid "View Ballista info" msgstr "Zobrazit informace o Katapultu" msgid "Ballista" msgstr "Katapult" msgid "Automatic combat modes" msgstr "Režimy automatického boje" msgid "Automatic Combat Modes" msgstr "Režimy automatického boje" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" "Zvolte, zda chcete pokraÄovat v boji v režimu automatického boje, nebo v " "režimu rychlého boje." msgid "Customize system options" msgstr "Upravit systémové nastavení" msgid "Allows you to customize the combat screen." msgstr "Umožňuje upravit obrazovku bojiÅ¡tÄ›." msgid "System Options" msgstr "Nastavení systému" msgid "Skip this unit" msgstr "Vynechat tah" msgid "Skip" msgstr "PÅ™eskoÄit" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "PÅ™eskoÄí stvoÅ™ení na tahu. StvoÅ™ení tím ukonÄí svůj tah a k boji se pÅ™idá " "znovu až v dalším kole." msgid "View Captain's options" msgstr "Zobraz možn. velitele" msgid "View Hero's options" msgstr "Zobraz možn. hrdiny" msgid "View opposing Captain" msgstr "Zobraz nepÅ™. velitele" msgid "View opposing Hero" msgstr "Zobraz nepÅ™. hrdinu" msgid "Hide logs" msgstr "Schovat logy" msgid "Show logs" msgstr "Zobrazit logy" msgid "Message Bar" msgstr "Pruh zpráv" msgid "Shows the results of individual monster's actions." msgstr "Zobrazuje následky poÄínání jednotlivých jednotek." msgid "Are you sure you want to enable the auto combat mode?" msgstr "Opravdu si pÅ™ejete zapnout režim automatického boje?" msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Opravdu si pÅ™ejete dokonÄit bitvu v režimu rychlého boje?" msgid "The computer continues the combat for you." msgstr "Umožňuje poÄítaÄi vybojovat bitvu za tebe." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" "Tento proces lze kdykoliv pÅ™eruÅ¡it stisknutím klávesové zkratky pro " "automatický boj, výchozí klávesy ZruÅ¡it, nebo kliknutím levým Äi pravým " "tlaÄítkem myÅ¡i kdekoliv na obrazovce hry." msgid "Auto Combat" msgstr "Automatický boj" msgid "The combat is resolved from the current state." msgstr "Boj je vyÅ™eÅ¡en ze souÄasného stavu." msgid "quickCombat|This cannot be undone." msgstr "Toto nelze vrátit zpÄ›t." msgid "Quick Combat" msgstr "Rychlý boj" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} pÅ™eskoÄí svůj tah." msgstr[1] "%{name} nebudou táhnout." msgstr[2] "%{name} pÅ™eskoÄí svůj tah." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} způsobil %{damage} Å¡kod." msgstr[1] "%{attacker} způsobili %{damage} Å¡kod." msgstr[2] "%{attacker} způsobili %{damage} Å¡kod." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 jednotka zahynula." msgstr[1] "%{count} jednotky umírají." msgstr[2] "%{count} jednotek umírá." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} umírá." msgstr[1] "%{count} %{defender} umírají." msgstr[2] "%{count} %{defender} umírají." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "Jedna duÅ¡e je zaÄlenÄ›na." msgstr[1] "%{count} duÅ¡e jsou zaÄlenÄ›ny." msgstr[2] "%{count} duší je zaÄlenÄ›no." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} oživen/a." msgstr[1] "%{count} %{unit} bylo oživeno." msgstr[2] "%{count} %{unit} bylo oživeno." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "PÅ™esunuto %{monster}: z [%{src}] na [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} odolává kouzlu!" msgstr[1] "%{name} kouzlu odolali!" msgstr[2] "%{name} odolávají kouzlu!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} sesílá %{spell} na %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} sesílá %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} působí %{damage} Å¡kod na vybrané nemrtvé stvoÅ™ení." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} působí %{damage} Å¡kod na vÅ¡echny nemrtvé stvoÅ™ení." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} působí %{damage} Å¡kod, %{count} stvoÅ™ení bylo zahubeno." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} působí %{damage} Å¡kod." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} působí %{damage} Å¡kod na vybrané žijící stvoÅ™ení." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} působí %{damage} Å¡kod vÅ¡em žijícím stvoÅ™ením." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Útok %{attacker} oslepil %{target}!" msgstr[1] "Útok %{attacker} oslepil %{target}!" msgstr[2] "Útok %{attacker} oslepil %{target}!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "UpÅ™ený pohled %{attacker}' promÄ›nil %{target} na kámen!" msgstr[1] "UpÅ™ený pohled %{attacker}' promÄ›nil %{target} na kámen!" msgstr[2] "UpÅ™ený pohled %{attacker}' promÄ›nil %{target} na kámen!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "%{attacker} uvalili kletbu na %{target}!" msgstr[1] "%{attacker} uvalili kletbu na %{target}!" msgstr[2] "%{attacker} uvalili kletbu na %{target}!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{target} jsou paralyzovaní úderem %{attacker}!" msgstr[1] "%{target} jsou paralyzovaní úderem %{attacker}!" msgstr[2] "%{target} jsou paralyzovaní úderem %{attacker}!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "%{attacker} zruÅ¡il vÅ¡echna kladná kouzla na %{target}!" msgstr[1] "%{attacker} zruÅ¡il vÅ¡echna kladná kouzla na %{target}!" msgstr[2] "%{attacker} zruÅ¡il vÅ¡echna kladná kouzla na %{target}!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} seslal %{spell} na %{target}!" msgstr[1] "%{attacker} seslal %{spell} na %{target}!" msgstr[2] "%{attacker} seslal %{spell} na %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "%{attacker} postihlo neÅ¡tÄ›stí." msgid "Good luck shines on the %{attacker}." msgstr "Na %{attacker} se usmálo Å¡tÄ›stí." msgid "High morale enables the %{monster} to attack again." msgstr "Dobrá morálka způsobila, že %{monster} může zaútoÄit znovu." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "" "Chabá morálka způsobila, že %{monster} zpanikaÅ™ili a neumůžou se hnout." msgid "%{tower} does %{damage} damage." msgstr "%{tower} působí %{damage} Å¡kod." msgid "The mirror image is created." msgstr "Zrcadlová jednotka byla vytvoÅ™ena." msgid "The mirror image is destroyed!" msgstr "Zrcadlová jednotka byla zniÄena!" msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Opravdu si pÅ™ejete pÅ™eruÅ¡it režim automatického boje?" msgid "Error" msgstr "Chyba" msgid "No spells to cast." msgstr "Nic ke kouzlení." msgid "Are you sure you want to retreat?" msgstr "Opravdu si pÅ™ejete utéct?" msgid "Retreat disabled" msgstr "Není kam utéct" msgid "Surrender disabled" msgstr "Nelze se vzdát" msgid "Damage: %{max}" msgstr "Å kody: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Å kody: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Zabije: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Zabije: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Za pomoci orlího oka byl %{name} schopen odpozorovat a nauÄit se kouzlo " "%{spell}." msgid "Human" msgstr "ÄŒlovÄ›k" msgid "AI" msgstr "AI" msgid "Start" msgstr "Start" msgid "Start the battle." msgstr "Zahájit bitvu." msgid "Exit" msgstr "PryÄ" msgid "Reset" msgstr "Reset" msgid "Reset to default settings." msgstr "Obnovit výchozí nastavení." msgid "Please select another hero." msgstr "Vyber jiného hrdinu." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} vs %{race2} %{name2}" msgid "Monsters" msgstr "Monstra" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Levá věž" msgid "Right Turret" msgstr "Pravá věž" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} střílí silou %{count} LuÄiÅ¡níků" msgid "each with a +%{attack} bonus to their attack skill." msgstr "každý s +%{attack} bonusem k jejich útoÄné síle." msgid "The %{name} is destroyed." msgstr "%{name} byl zniÄen." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} vstává z mrtvých!" msgstr[1] "%{count} %{name} vstájí z mrtvých!" msgstr[2] "%{count} %{name} vstájí z mrtvých!" msgid "Dwarven Alliance" msgstr "TrpasliÄí aliance" msgid "Sorceress Guild" msgstr "Cech ÄarodÄ›jů" msgid "Necromancer Guild" msgstr "Cech Nekromantů" msgid "Ogre Alliance" msgstr "Zlobří aliance" msgid "Dwarfbane" msgstr "TrpasliÄí prokletí" msgid "Dragon Alliance" msgstr "DraÄí aliance" msgid "Elven Alliance" msgstr "Elfí aliance" msgid "Kraeger defeated" msgstr "Kreager poražen" msgid "Wayward Son" msgstr "Scestný syn" msgid "Uncle Ivan" msgstr "Strýc Ivan" msgid "Annexation" msgstr "Zabrání" msgid "Force of Arms" msgstr "Síla armády" msgid "Save the Dwarves" msgstr "Zachraň trpaslíky" msgid "Carator Mines" msgstr "Caratrovy doly" msgid "Turning Point" msgstr "Bod zlomu" msgid "scenarioName|Defender" msgstr "Obránce" msgid "Corlagon's Defense" msgstr "Corlagonova obrana" msgid "The Crown" msgstr "Koruna" msgid "The Gauntlet" msgstr "Hozená rukavice" msgid "Betrayal" msgstr "Zrada" msgid "Final Justice" msgstr "Poslední zůÄtování" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland potÅ™ebuje abys porazil Å¡lechtice poblíž jeho hradu a tím zaÄal " "povstání proti jeho bratrovi. Protivníci nemají mezi sebou smluvené " "spojenectví, proto asi budou po vÄ›tÅ¡inu Äasu bojovat mezi sebou. VítÄ›zství " "bude tvoje když dobijeÅ¡ vÅ¡echny jejich mÄ›sta a porazíš vÅ¡echny hrdiny." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Místní Å¡lechta odmíta odpřísáhnout Rolandovi svou vÄ›rnost, proto musí být " "potlaÄena. Panství jsou mocná a bohatá, musíš být pÅ™ipraven na tÄ›zký odpor. " "Zmocni se vÅ¡ech nepřátelských hradů a tím vyhrajeÅ¡." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Tvým úkolem je ochránít Å křítky pÅ™ed Archibaldovými vojsky. Zmocni se vÅ¡ech " "nepřátelských hradů a vesnic, zároveň dej pozor abys neztratil vÅ¡echny " "vesnice Å¡kÅ™itků najednou, jinak zvítÄ›zí náš protivník." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "BudeÅ¡ vystaven přímému souboji o suroviny se ÄtyÅ™mi spojeneckými protivníky. " "Zaber vÅ¡echny nepřátelské hrady a vyhrajeÅ¡." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Tví protivníci uzavÅ™eli spojenecký pakt a jsou umístnÄ›ní poblíž, takže buÄ " "pÅ™ipraven vyrazit do boje. Abys vyhrál, budeÅ¡ muset dobít vÅ¡echny ÄtyÅ™i " "hrady v tomto malém údolí." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Cech ÄarodÄ›jů mÄ›sta Noraston požádal Rolanda o pomoc proti útokům " "Archibaldových spojenců. ObsaÄ vÅ¡echny nepřátelské hrady, zároveň nesmíš " "pÅ™ijít o Noraston, jinak bude naÅ¡e tažení zmaÅ™eno. (Tip: Jeden nepřátelský " "hrad je na ostrovÄ› v oceánu.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Nashromáždi co nejvÄ›tší armádu a dobij nepřátelský hrad do 8 týdnů. Proti " "tobÄ› stojí pouze jeden nepřítel, ale musíš urazit dlouhou cestu, aby ses " "dostal k jeho hradu. VÅ¡echny jednotky, které zůstanou ve tvé armádÄ› na konci " "tohoto scénáře budou s tebou i v závÄ›reÄné bitvÄ›." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Najdi korunu dříve, než ji najdou Archibaldovi hrdinové. Roland bude korunu " "potÅ™ebovat pro poslední bitvu proti Archibaldovi." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "TÅ™i nepřátelé se spojili a stojí mezi tebou a vítÄ›zstvím, a to vÄetnÄ› lorda " "Corlagona. Roland je na hradÄ› na severozápadÄ›, pokud padne do rukou " "nepřítele tak prohrajeÅ¡. Pamatuj, dopadení lorda Corlagona zajistí, že proti " "nám nebude bojovat v závereÄné bitvÄ›." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Je taty poslední bitva. Ty i nepřátelé jste po zuby ozbrojení, vÅ¡ichni jsou " "ve spojenectví proti tobÄ›. Poraž Archibalda a ukonÄi tuto válku!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "PÅ™ebÄ›hnutím k nepříteli získáš tÅ™i hrady naproti jednomu nepřátelskému. Tato " "bitva bude ta nejjednodušší, které budeÅ¡ Äelit po zbytek války...zrádÄe." msgid "Barbarian Wars" msgstr "Barbarské Války" msgid "First Blood" msgstr "První Krev" msgid "Necromancers" msgstr "Nekromanti" msgid "Slay the Dwarves" msgstr "ZniÄ Skřítky" msgid "Country Lords" msgstr "Pánové Krajiny" msgid "Dragon Master" msgstr "Pán Draků" msgid "Rebellion" msgstr "Povstání" msgid "Apocalypse" msgstr "Apokalypsa" msgid "Greater Glory" msgstr "VÄ›tší Sláva" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Král Archibald potÅ™ebuje abys porazil tÅ™i protivníky v tomto regionu. " "Protivníci nemají mezi sebou smluvené spojenectví, proto asi spotÅ™ebují " "vÄ›tÅ¡inu energie vzájemnými souboji. VítÄ›zství bude tvoje, když zabereÅ¡ " "vÅ¡echny nepřátelské hrady a nezbyde žádný hrdina k boji." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Musíš sjednotit barbarské kmeny na severu tím, že si je podrobíš. StejnÄ› " "jako v pÅ™edchozí misi, nepřátelé nemají smluvené spojenectví proti TobÄ›, ale " "mají k dispozici více zdrojů. ZvítÄ›zíš, až budeÅ¡ vlastnit vÅ¡echny " "nepřátelské hrady a nezbude žádný hrdina k boji." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "DobrodÄ›jové obsadili hrad nekromantů. Abys zvítÄ›zil, musíš ho znovu dobýt. " "Nezapomeň, že i když zaÄínáš se silnou armádou, tak nemáš žádný hrad a musíš " "ho do 7 dnů dobýt, jinak tuto bitvu prohrajeÅ¡. (NápovÄ›da: Nejbližší hrad je " "na jihovýchodÄ›.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Je potÅ™eba podrobit si Skřítky, než budou moci zasáhnout do plánů krále " "Archibalda. Rolandova vojska mají víc než jednoho hrdinu a mnoho mÄ›st, takže " "buÄ pÅ™ipraven na útok z více smÄ›rů. Abys zvítÄ›zil, musíš dobýt vÅ¡echna " "nepřátelská mÄ›sta a hrady." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Musíš potlaÄit rolnické povstání vedené Rolandovými vojsky. VÅ¡ichni jsou ve " "spojenectví proti tobÄ›, ale Ty máš po boku lorda Corlagona, zkuÅ¡eného " "hrdinu. Zaber vÅ¡echny nepřátelské hrady a vyhrajeÅ¡." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "V této misi proti TobÄ› stojí dva nepřátelé. Oba jsou dobÅ™e vyzbrojeni a " "chtÄ›jí tÄ› ze svého ostrova vyhnat. Abys zvítÄ›zil, musíš jim v tom zabránit a " "dobít DraÄí mÄ›sto." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Rozkaz zní dobít zemÄ› pánů, kteří odpÅ™isáhli vÄ›rnost a slouží Rolandovi. " "VÅ¡echny nepřátelské hrady se spolÄily proti TobÄ›. Protože zaÄínáš bez hradu, " "musíš si pospíšit, abys nÄ›jaký zabral do konce týdne. VítÄ›zství ti zajistí, " "když zabereÅ¡ vÅ¡echny nepřátelské hrady." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Najdi korunu dříve, než ji najdou Rolandovi hrdinové. Archibald bude korunu " "potÅ™ebovat pro poslední bitvu proti Rolandovi." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Je tady poslední bitva. Ty i nepřátelé jste po zuby ozbrojení, vÅ¡ichni jsou " "ve spojenectví proti TobÄ›. Poraz Rolanda a ukonÄi tuto válku, v bitvÄ› ale " "nesmíš pÅ™ijít o Archibalda!" msgid "Arrow's Flight" msgstr "Let Šípu" msgid "Island of Chaos" msgstr "Ostrov chaosu" msgid "The Abyss" msgstr "Propast" msgid "Uprising" msgstr "Povstání" msgid "Aurora Borealis" msgstr "Aurora Borealis" msgid "Betrayal's End" msgstr "PotlaÄení zrady" msgid "Corruption's Heart" msgstr "Srdce korupce" msgid "The Giant's Pass" msgstr "Obrův průsmyk" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Podmaň si neukáznÄ›né místní pány, tím poskytneÅ¡ království potÅ™ebné zázemí " "pro fungování v tomto regionu." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Zlikviduj veÅ¡kerou opozici v této oblasti. Pak bude první Äást artefaktu " "tvoje." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "ÄŒarodÄ›jky na severovýchodÄ› se bouří! Pro dobro říše musíš vyrazit do hor a " "potlaÄit jejich chabé povstání." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Kraeger se pÅ™ipravil na tvůj vpád a sestavil celou armádu nekromantů, aby " "zmaÅ™ili tvou výpravu. Musíš dobýt hrad Scabsdale do prvního dne tÅ™etího " "týdne, jinak už budou nekromanti k neporažení." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Barbarský despota v této oblasti o tvé přítomnosti zatím neví. Rychle sestav " "své vojsko, dříve než budeÅ¡ odhalen a napaden! PodmanÄ›ním vÅ¡ech " "nepřátelských síl si podrobíš a zabezpeÄíš tento kraj." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Říše je v této oblasti slabá. NebudeÅ¡ proto schopen si zcela podmanit " "vÅ¡echny vojska v této oblasti, takže si vem co můžeÅ¡, než udeří odvetným " "útokem. Nezapomeň, že skuteÄným cílem je získat Anduranskou pÅ™ilbu." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Zabij Kreagera, pro slávu impéria." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "KoneÄnÄ› máš možnost a prostÅ™edky zbavit říši od onoho nekromantského zla. " "Když je zcela je vymýtíš, budeÅ¡ navÄ›ky opÄ›vován jako hrdina." msgid "Border Towns" msgstr "PohraniÄní mÄ›sta" msgid "Conquer and Unify" msgstr "Dobýt a sjednotit" msgid "Crazy Uncle Ivan" msgstr "Šílený strýc Ivan" msgid "The Wayward Son" msgstr "Scestný syn" msgid "Ivory Gates" msgstr "Ivory Gates" msgid "The Elven Lands" msgstr "Elfské území" msgid "The Epic Battle" msgstr "Epická bitva" msgid "The Southern War" msgstr "Jižní válka" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Dobij a sjednoÅ¥ vÅ¡echny nepřátelské kmeny. NeztraÅ¥ hrdinu Jarkonase, praotce " "vÅ¡ech potomků." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Tvůj protivník, království Harondalu, útoÄí na slabá mÄ›sta na hranicích! " "Vzpamatuj se z jejich prvního úderu a kompletnÄ› je rozdrÅ¥!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Najdi svého umínÄ›ného syna Josefa, o nÄ›mž se povídá, že žije v pustých " "konÄinách. Musíš ho najít do prvního dne tÅ™etího mÄ›síce, jinak to rodinÄ› již " "nepomůže." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Zachraň svého šíleného strýce Ivana. Musíš ho najít do prvního dne Ätvrtého " "mÄ›síce, jinak to tvému království již nepomůže." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "ZniÄ barbary, kteří útoÄí na jižní hranici království! Získej zpÄ›t svá padlá " "mÄ›sta a pak vtrhni do království džungle. Žádný z protivníků nesmí zůstat na " "živu." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Získej zpÄ›t hrad Ivory Gates, který padl kvůli zradÄ›." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Získej si přízeň elfů. Kácení stromů je v tomto kraji zakázáno, ale každé " "dva týdny ti nÄ›jaké dÅ™evo poÅ¡lou. Svůj úkol musíš splnit do prvního dne " "sedmého mÄ›síce, jinak království jistÄ› padne." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Je tady poslední bitva proti nepřátelskému království Harondale. Poraž je " "vÅ¡echny a neztraÅ¥ pÅ™i tom hrdinu Jarkonase VI." msgid "Fount of Wizardry" msgstr "Pramen kouzelnictví" msgid "Power's End" msgstr "Konec moci" msgid "The Eternal Scrolls" msgstr "VÄ›Äné svitky" msgid "The Shrouded Isles" msgstr "Zahalené ostrovy" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Tvým úkolem je porazit bojové mágy na kouzelných Zahalených ostrovech. " "SplnÄ›ní tohoto úkolu ti zaruÄí výhodu v boji proti tvým protivníkům." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Místo, kde se nachází velká knihovna, bylo objeveno! Musíš se za ní vydat a " "získat zpÄ›t mÄ›sto Chronos, ve kterém se nachází." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Najdi Sféru negace, která je prý pohÅ™bena nÄ›kde v této zemi. Na kamenných " "obeliscích jsou vepsány indicie, které tÄ› dovedou až k cíli. Najdi sféru do " "prvního dne Å¡estého mÄ›síce, jinak aftefakt jistÄ› získají tví protivníci." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Musíš ovládnout hrad Magic, ve kterém se nachází pramen kouzel. Dokaž to a " "tvé vítÄ›zství bude to nejslavnÄ›jší ze vÅ¡ech." msgid "Blood is Thicker" msgstr "Pokrevné pouto" msgid "King and Country" msgstr "Král a jeho zemÄ›" msgid "Pirate Isles" msgstr "Pirátské ostrovy" msgid "Stranded" msgstr "Uvízlý" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Dobytí mÄ›sta na ostrovÄ› u jihovýchodního pobÅ™eží ti umožní postavit loÄ a " "doplout na pevninu. NeztraÅ¥ hrdinu Gallavanta." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Najdi a poraz Martine, vůdkyni pirátů, která sídlí v mÄ›stÄ› Pirates Cove. " "NeztraÅ¥ pÅ™i tom Gallavanta, jinak bude vÅ¡e ztraceno." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Zlikviduj vÅ¡echny, kteÅ™i se staví proti vládÄ› lorda Alberona. Gallavant " "nesmí zemřít." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Svrhni zkůrnatÄ›lou monarchii lorda Alberona a prohlaÅ¡ celou zemi za svou. " "Gallavant nesmí zemřít." msgid " bane" msgstr " zkáza" msgid " alliance" msgstr " aliance" msgid "Carry-over forces" msgstr "PÅ™evedené vojska" msgid " bonus" msgstr " bonus" msgid " defeated" msgstr " poražení" msgid " will always run away from your army." msgstr " vždy uteÄou pÅ™ed tvými vojsky." msgid " will be willing to join your army." msgstr " se budou chtít k tobÄ› pÅ™idat." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "\"%{artifact}\" si poneseÅ¡ s sebou do další hry." msgid "The army will be carried over in the campaign." msgstr "Armáda bude pÅ™enesena do další hry." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Příjmy království budou vyšśí o %{count} %{resource} dennÄ›." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "\"%{spell}\" bude pÅ™eneseno do další hry." msgid "%{hero} can be hired during scenarios." msgstr "Ve hÅ™e bude možné najmout hrdinu %{hero}." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "%{hero} byl poražen a už se v dalších krocích kampanÄ› neobjeví." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "Skřítci poznají své spojence a rádi se pÅ™ipojí k tvým silám." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "ZlobÅ™i poznávají, že jsi ten kdo porazil skřítky a pÅ™idávají se k tobÄ›." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Prskající a funící draci souhlasí, že spojí své síly s tebou, jejich " "'spojencem'." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Když se pÅ™iblížíš ke skupinÄ› elfů, jejich vůdce je vÅ¡echny vyzve k " "pozornosti. ZakÅ™iÄí na nÄ›: \"Kdo z vás je dost odvážný, aby se pÅ™idal k " "naÅ¡emu neohroženému spojenci?\" Skupina propukne v jásot a běží aby se " "pÅ™idali k tvým Å™adám." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Skřítci tÄ› vítají, \"Každý Rolandův přítel je i náš přítel. MůžeÅ¡ projít.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "ZlobÅ™i na tebe uznale zavrÄí: \"Archibaldovi spojenci mohou projít.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Draci tÄ› vidí a zvolají. \"NaÅ¡e spojenectví s Archibaldem nás zavazuje " "abychom se k TobÄ› pÅ™ipojili. Bohužel už nemáš místo. To je Å¡koda!\" A rychle " "se rozprchli." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Elfové stojí v pozoru, když se pÅ™iblížíš. Jejich vůdce zvolá a Å™ekne: " "\"Nebudeme ti bránít v postupu, spojenÄe! PokraÄuj, věříme ve tvé vítÄ›zství." "\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"TrpasliÄí zhouba!!! Utíkejte jako o život!\"" msgid "campaignBonus|Animate Dead" msgstr "Oživení mrtvých" msgid "campaignBonus|Chain Lightning" msgstr "Kulový blesk" msgid "campaignBonus|Fireblast" msgstr "Ohnivý výbuch" msgid "campaignBonus|Mass Curse" msgstr "Hromadná léÄba" msgid "campaignBonus|Mass Haste" msgstr "Hromadné zrychlení" msgid "campaignBonus|Mirror Image" msgstr "Zdvojení" msgid "campaignBonus|Resurrect" msgstr "Oživení" msgid "campaignBonus|Steelskin" msgstr "Ocelová kůže" msgid "campaignBonus|Summon Earth" msgstr "PÅ™ivolat Zemské Elementály" msgid "campaignBonus|View Heroes" msgstr "Zobraz Hrdiny" msgid "campaignBonus|Ballista" msgstr "Katapult" msgid "campaignBonus|Black Pearl" msgstr "ÄŒerná perla" msgid "campaignBonus|Caster's Bracelet" msgstr "Náramek kouzelníka" msgid "campaignBonus|Defender Helm" msgstr "Helma obránce" msgid "campaignBonus|Breastplate" msgstr "Božský krunýř" msgid "campaignBonus|Dragon Sword" msgstr "DraÄí meÄ" msgid "campaignBonus|Fizbin Medal" msgstr "Medaile neÅ¡tÄ›stí" msgid "campaignBonus|Foremost Scroll" msgstr "Vrcholný svitek poznání" msgid "campaignBonus|Gauntlets" msgstr "ObrnÄ›né rukavice" msgid "campaignBonus|Hideous Mask" msgstr "Ohavná maska" msgid "campaignBonus|Mage's Ring" msgstr "Prsten moci" msgid "campaignBonus|Major Scroll" msgstr "Velký svitek poznání" msgid "campaignBonus|Medal of Honor" msgstr "Medaile cti" msgid "campaignBonus|Medal of Valor" msgstr "Medaile za stateÄnost" msgid "campaignBonus|Minor Scroll" msgstr "Menší svitek poznání" msgid "campaignBonus|Nomad Boots" msgstr "Boty rychlosti" msgid "campaignBonus|Power Axe" msgstr "Bojová sekera" msgid "campaignBonus|Spiked Shield" msgstr "Å tít s hroty" msgid "campaignBonus|Stealth Shield" msgstr "Tajný Å¡tít" msgid "campaignBonus|Tax Lien" msgstr "Daňová zástava" msgid "campaignBonus|Thunder Mace" msgstr "Palcát" msgid "campaignBonus|Traveler's Boots" msgstr "Boty cestovatele" msgid "campaignBonus|White Pearl" msgstr "Bílá perla" msgid "campaignBonus|Basic Archery" msgstr "Zákl. LukoÅ¡tÅ™elba" msgid "campaignBonus|Advanced Archery" msgstr "Pokr. LukostÅ™elba" msgid "campaignBonus|Expert Archery" msgstr "Exp. LukostÅ™elba" msgid "campaignBonus|Basic Ballistics" msgstr "Zákl. Balistika" msgid "campaignBonus|Advanced Ballistics" msgstr "Pokr. Balistika" msgid "campaignBonus|Expert Ballistics" msgstr "Exp. Balistika" msgid "campaignBonus|Basic Diplomacy" msgstr "Zákl. Diplomacie" msgid "campaignBonus|Advanced Diplomacy" msgstr "Pokr. Diplomacie" msgid "campaignBonus|Expert Diplomacy" msgstr "Exp. Diplomacie" msgid "campaignBonus|Basic Eagle Eye" msgstr "Zákl. Orlí oko" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Pokr. Orlí oko" msgid "campaignBonus|Expert Eagle Eye" msgstr "Exp. Orlí oko" msgid "campaignBonus|Basic Estates" msgstr "Zákl.HospodaÅ™ení" msgid "campaignBonus|Advanced Estates" msgstr "Pokr. HospodaÅ™ení" msgid "campaignBonus|Expert Estates" msgstr "Exp. HospodaÅ™ení" msgid "campaignBonus|Basic Leadership" msgstr "Zákl. Vedení" msgid "campaignBonus|Advanced Leadership" msgstr "Pokr. Vedení" msgid "campaignBonus|Expert Leadership" msgstr "Exp. Vedení" msgid "campaignBonus|Basic Logistics" msgstr "Zákl. Logistika" msgid "campaignBonus|Advanced Logistics" msgstr "Pokr. Logistika" msgid "campaignBonus|Expert Logistics" msgstr "Exp. Logistika" msgid "campaignBonus|Basic Luck" msgstr "Zákl. Å tÄ›stí" msgid "campaignBonus|Advanced Luck" msgstr "Pokr. Å tÄ›stí" msgid "campaignBonus|Expert Luck" msgstr "Exp. Å tÄ›stí" msgid "campaignBonus|Basic Mysticism" msgstr "Zákl. Mystika" msgid "campaignBonus|Advanced Mysticism" msgstr "Pokr. Mystika" msgid "campaignBonus|Expert Mysticism" msgstr "Exp. Mystika" msgid "campaignBonus|Basic Navigation" msgstr "Zákl. Navigace" msgid "campaignBonus|Advanced Navigation" msgstr "Pokr. Navigace" msgid "campaignBonus|Expert Navigation" msgstr "Exp. Navigace" msgid "campaignBonus|Basic Necromancy" msgstr "Zákl. Nekromancie" msgid "campaignBonus|Advanced Necromancy" msgstr "Pokr. Nekromancie" msgid "campaignBonus|Expert Necromancy" msgstr "Exp. Nekromancie" msgid "campaignBonus|Basic Pathfinding" msgstr "Zákl. Hledání cest" msgid "campaignBonus|Advanced Pathfinding" msgstr "Pokr. Hledání cest" msgid "campaignBonus|Expert Pathfinding" msgstr "Exp. Hledání cest" msgid "campaignBonus|Basic Scouting" msgstr "Zákl. Průzkumník" msgid "campaignBonus|Advanced Scouting" msgstr "Pokr. Průzkumník" msgid "campaignBonus|Expert Scouting" msgstr "Exp. Průzkumník" msgid "campaignBonus|Basic Wisdom" msgstr "Zákl. Moudrost" msgid "campaignBonus|Advanced Wisdom" msgstr "Pokr. Moudrost" msgid "campaignBonus|Expert Wisdom" msgstr "Exp. Moudrost" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "Tvůj hlavní hrdina bude mít na zaÄátku hry artefakt \"%{artifact}\"." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "Tvé království bude mít na zaÄátku hry o %{amount} %{resource} víc." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "Tvé království bude mít na zaÄátku hry o %{amount} %{resource} míň." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Tvůj hlavní hrdina bude hru zaÄínat s %{count} %{monster}." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "Tvůj hlavní hrdina bude umÄ›t vykouzlit \"%{spell}\" od zaÄátku hry." msgid "The starting alignment of the scenario will be %{race}." msgstr "Hru zaÄneÅ¡ jako Älen %{race} frakce." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "Hlavní hrdina na zaÄátku scénáře získá +%{count} k jejich %{skill}." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Tvůj hlavní hrdina bude ovládat %{skill} od zaÄátku hry." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" msgid "Price of Loyalty" msgstr "Cena za vÄ›rnost" msgid "Voyage Home" msgstr "Cesta domů" msgid "Wizard's Isle" msgstr "Kouzelníkův ostrov" msgid "Descendants" msgstr "Potomci" msgid "Cannot build. You have already built here today." msgstr "Nelze postavit. Dnes si zde již stavÄ›l." msgid "For this action it is necessary to build a castle first." msgstr "Pro tuto akci bude nutné nejdříve postavit hrad." msgid "The %{building} produces %{monster}." msgstr "%{building} produkuje %{monster}." msgid "Requires:" msgstr "Vyžaduje:" msgid "Exit this menu without doing anything." msgstr "Odejít z menu bez provedení zmÄ›m." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "%{name} nelze postavit, protože hrad je moc daleko od moÅ™e." msgid "This building has been disabled." msgstr "Tato budova není povolena." msgid "Cannot afford the %{name}." msgstr "Na %{name} zatím nemáš." msgid "The %{name} is already built." msgstr "%{name}, již postaveno." msgid "Cannot build the %{name}." msgstr "Není možné postavit %{name}." msgid "Build %{name}." msgstr "Postavit %{name}." msgid "Blackridge" msgstr "Blackridge" msgid "Hillstone" msgstr "Hillstone" msgid "Pinehurst" msgstr "Pinehurst" msgid "Whiteshield" msgstr "Whiteshield" msgid "Woodhaven" msgstr "Woodhaven" msgid "Blackwind" msgstr "Blackwind" msgid "Bloodreign" msgstr "Bloodreign" msgid "Dragontooth" msgstr "Dragontooth" msgid "Greywind" msgstr "Greywind" msgid "Portsmith" msgstr "Portsmith" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Middle Gate" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "Baywatch" msgid "Fountainhead" msgstr "Fountainhead" msgid "Vertigo" msgstr "Vertigo" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Winterkill" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Lakeside" msgid "Nightshadow" msgstr "Nightshadow" msgid "Olympus" msgstr "Olympus" msgid "Sandcaster" msgstr "Sandcaster" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "New Dawn" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Big Oak" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antioch" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Roc Haven" msgid "South Mill" msgstr "South Mill" msgid "Weed Patch" msgstr "Weed Patch" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Hilltop" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Westfork" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "Elk's Head" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Blackburn" msgid "Blacksford" msgstr "Blacksford" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Pig's Eye" msgid "Viper's Nest" msgstr "Viper's Nest" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Timberhill" msgid "Troy" msgstr "Troy" msgid "Forder Oaks" msgstr "Forder Oaks" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Quick Silver" msgid "Westmoor" msgstr "Westmoor" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Nelze najmout - ve mÄ›ste se nachází hrdina." msgid "Cannot recruit - you have too many Heroes." msgstr "Nelze najmout - máš příliž mnoho hrdinů." msgid "Cannot afford a Hero." msgstr "NemůžeÅ¡ si ho dovolit." msgid "There is no room in the garrison for this army." msgstr "Pro tuto jednotku už v posádce není místo." msgid "Fortifications" msgstr "OpevnÄ›ní" msgid "Farm" msgstr "Farma" msgid "Thatched Hut" msgstr "Chalupa" msgid "Archery Range" msgstr "StÅ™elnice" msgid "Upg. Archery Range" msgstr "Upg. StÅ™elnice" msgid "Blacksmith" msgstr "Kovárna" msgid "Upg. Blacksmith" msgstr "Upg. Kovárna" msgid "Armory" msgstr "Zbrojnice" msgid "Upg. Armory" msgstr "Upg. Zbrojnice" msgid "Jousting Arena" msgstr "Turnajová aréna" msgid "Upg. Jousting Arena" msgstr "Upg. Turnajová aréna" msgid "Cathedral" msgstr "Katedrála" msgid "Upg. Cathedral" msgstr "Upg. Katedrála" msgid "Coliseum" msgstr "Koloseum" msgid "Garbage Heap" msgstr "SmetiÅ¡tÄ›" msgid "Hut" msgstr "Bouda" msgid "Stick Hut" msgstr "ChatrÄ" msgid "Upg. Stick Hut" msgstr "Upg. ChatrÄ" msgid "Den" msgstr "DoupÄ›" msgid "Adobe" msgstr "Pueblo" msgid "Upg. Adobe" msgstr "Upg. Pueblo" msgid "Bridge" msgstr "Most" msgid "Upg. Bridge" msgstr "Upg. Most" msgid "Pyramid" msgstr "Pyramida" msgid "Rainbow" msgstr "Duha" msgid "Crystal Garden" msgstr "Krystalová zahrada" msgid "Treehouse" msgstr "Letohrádek" msgid "Cottage" msgstr "Chata" msgid "Upg. Cottage" msgstr "Upg. Chata" msgid "Stonehenge" msgstr "Kamenný kruh" msgid "Upg. Stonehenge" msgstr "Upg. Kamenný kruh" msgid "Fenced Meadow" msgstr "Ohrada" msgid "sorceress|Red Tower" msgstr "ÄŒervená Věž" msgid "Dungeon" msgstr "Kobka" msgid "Waterfall" msgstr "Vodopád" msgid "Cave" msgstr "Sluj" msgid "Crypt" msgstr "Krypta" msgid "Nest" msgstr "Hnízdo" msgid "Maze" msgstr "Labyrint" msgid "Upg. Maze" msgstr "Upg. Labyrint" msgid "Swamp" msgstr "MoÄál" msgid "Green Tower" msgstr "Zelená Věž" msgid "warlock|Red Tower" msgstr "Rudá Věž" msgid "Black Tower" msgstr "ÄŒerná Věž" msgid "Library" msgstr "Knihovna" msgid "Orchard" msgstr "Sad" msgid "Habitat" msgstr "Domov" msgid "Pen" msgstr "Chlév" msgid "Foundry" msgstr "Slévárna" msgid "Upg. Foundry" msgstr "Upg. Slevárna" msgid "Cliff Nest" msgstr "Hnízdo" msgid "Ivory Tower" msgstr "Bílá věž" msgid "Upg. Ivory Tower" msgstr "Upg. Bílá věž" msgid "Cloud Castle" msgstr "OblaÄný hrad" msgid "Upg. Cloud Castle" msgstr "Upg. OblaÄný hrad" msgid "Storm" msgstr "BouÅ™e" msgid "Skull Pile" msgstr "Kupa lebek" msgid "Excavation" msgstr "Vykopávky" msgid "Graveyard" msgstr "HÅ™bitov" msgid "Upg. Graveyard" msgstr "Upg. HÅ™bitov" msgid "Upg. Pyramid" msgstr "Upg. Pyramida" msgid "Mansion" msgstr "Sídlo" msgid "Upg. Mansion" msgstr "Upg. Sídlo" msgid "Mausoleum" msgstr "Mauzoleum" msgid "Upg. Mausoleum" msgstr "Upg. Mauzoleum" msgid "Laboratory" msgstr "LaboratoÅ™" msgid "Shrine" msgstr "SvatynÄ›" msgid "Special" msgstr "Speciální" msgid "Horde Building" msgstr "Budova hordy" msgid "Dwelling 1" msgstr "Obydlí 1" msgid "Dwelling 2" msgstr "Obydlí 2" msgid "Upg. Dwelling 2" msgstr "Upg. Obydlí 2" msgid "Dwelling 3" msgstr "Obydlí 3" msgid "Upg. Dwelling 3" msgstr "Upg. Obydlí 3" msgid "Dwelling 4" msgstr "Obydlí 4" msgid "Upg. Dwelling 4" msgstr "Upg. Obydlí 4" msgid "Dwelling 5" msgstr "Obydlí 5" msgid "Upg. Dwelling 5" msgstr "Upg. Obydlí 5" msgid "Dwelling 6" msgstr "Obydlí 6" msgid "Upg. Dwelling 6" msgstr "Upg. Obydlí 6" msgid "2x Upg. Dwelling 6" msgstr "2x Upg. Obydlí 6" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "OpevnÄ›ní zvyÅ¡uje odolnost zdí, zvyÅ¡uje poÄet zásahů než budou zniÄeny." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Farma zvyÅ¡uje produkci Rolníků o %{count} týdnÄ›." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Koloseum nabízí inspirující podívanou obráncům, Äímž bÄ›hem boje zvyÅ¡uje " "jejich morálku o 2 body." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "SmetiÅ¡tÄ› zvyÅ¡uje produkci Goblinů o %{count} týdnÄ›." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Duha zvyÅ¡uje Å¡tÄ›stí bránících jednotek o dvÄ›." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "Krystalová zahrada zvyÅ¡uje produkci Víl o %{count} týdnÄ›." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Kobka zvyÅ¡uje mÄ›stské příjmy o %{count} za den." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Vodopád zvyÅ¡uje produkci Kentaurů o %{count} týdnÄ›." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "Knihovna zvyÅ¡uje poÄet kouzel ve věži o jedno na každé úrovni." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Sad zvyÅ¡uje produkci Hobitů o %{count} týdnÄ›." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "BouÅ™e pÅ™idává +2 na síle kouzel obránci hradu." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Hromada Lebek zvyÅ¡uje produkci Kostlivců o %{count} týdnÄ›." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "Speciální budova poskytuje konkrétní bonus vybranému typu hradu." msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "Budova hordy zvyÅ¡uje růst jednotek 1. úrovnÄ› o 8 týdnÄ›." msgid "Thieves' Guild" msgstr "Cech zlodÄ›jů" msgid "Tavern" msgstr "Putyka" msgid "Shipyard" msgstr "Přístav" msgid "Well" msgstr "Studna" msgid "Statue" msgstr "Socha" msgid "Marketplace" msgstr "Tržnice" msgid "Moat" msgstr "Příkop" msgid "Castle" msgstr "Hrad" msgid "Tent" msgstr "Stan" msgid "Captain's Quarters" msgstr "Kapitánovo obydlí" msgid "Mage Guild, Level 1" msgstr "Věž Kouzel, Úroveň 1" msgid "Mage Guild, Level 2" msgstr "Věž Kouzel, Úroveň 2" msgid "Mage Guild, Level 3" msgstr "Věž Kouzel, Úroveň 3" msgid "Mage Guild, Level 4" msgstr "Věž Kouzel, Úroveň 4" msgid "Mage Guild, Level 5" msgstr "Věž Kouzel, Úroveň 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "SvatynÄ› zvyÅ¡uje schopnost nekromancie o 10 procent u vÅ¡ech vaÅ¡ich nekromantů." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Cech zlodÄ›jů poskytuje informace o nepřátelích. Může také poskytovat " "Å¡pionážní informace o nepřátelských mÄ›stech. Čím více cechů máte, tím vice " "informací uvidíte." msgid "The Tavern increases morale for troops defending the castle." msgstr "Putyka zvyÅ¡uje morálku jednotek bránících hrad." msgid "The Shipyard allows ships to be built." msgstr "Přístav umožňuje stavbu lodí." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Studna zvyÅ¡uje tempo růstu ve vÅ¡ech obydlích o %{count} jednotky týdnÄ›." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Socha zvyÅ¡uje příjmy mÄ›sta o %{count} zlata dennÄ›." msgid "The Left Turret provides extra firepower during castle combat." msgstr "Levá věž zvyÅ¡uje palebnou sílu pÅ™i obranÄ› hradu." msgid "The Right Turret provides extra firepower during castle combat." msgstr "Pravá věž zvyÅ¡uje palebnou sílu pÅ™i obranÄ› hradu." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Tržnice slouží ke smÄ›nÄ› surovin. Čím více tržnic kontrolujete, tím lepší " "bude smÄ›nný kurz." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Příkop zpomaluje útoÄící jednotky. Jakákoli jednotka zde musí ukonÄit pohyb " "a je zranitelnÄ›jší pÅ™i útoku." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "Hrad zlepÅ¡uje obranyschopnost mÄ›sta a zvyÅ¡uje příjem o %{count} dennÄ›." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Stan poskytuje dÄ›lníky ke stavbÄ› hradu, pokud je k dispozici dostatek " "materiálu a zlaťáků." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Kapitánovo obydlí poskytuje velitele, který bude asistovat pÅ™i obranÄ› hradu " "když v nÄ›m není hrdina." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Věž kouzel umožňuje hrdinům nauÄit se kouzla a doplnit jejich magickou " "energii." msgid "Recruit %{name}" msgstr "Najmout %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "MÄ›síc: %{month}, Týden: %{week}, Den: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Pro vstup do věže si musíš zakoupit knihu kouzel, teÄ ale nemáš pro ni " "místo. Zkus podarovat jeden ze svých artefaktů jinému hrdinovi." msgid "Click to show next town." msgstr "Klikni pro zobrazení následujícího mÄ›sta." msgid "Show next town" msgstr "Zobrazit následující mÄ›sto" msgid "Click to show previous town." msgstr "Klikni pro zobrazení pÅ™edchozího mÄ›sta." msgid "Show previous town" msgstr "Zobrazit pÅ™edchozí mÄ›sto" msgid "This town may not be upgraded to a castle." msgstr "Toto mÄ›sto nemůže být povýšeno na hrad." msgid "Town" msgstr "MÄ›sto" msgid "Exit Castle" msgstr "Opustit hrad" msgid "Exit Town" msgstr "Opustit mÄ›sto" msgid "Show Income" msgstr "Zobrazit příjmy" msgid "View Hero" msgstr "Zobrazit hrdinu" msgid "The above spells are available here." msgstr "Nacházejí se zde výše uvedená kouzla." msgid "The spells the hero can learn have been added to their book." msgstr "Do knihy byla pÅ™idána kouzla, která se hrdina může nauÄit." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Vrchní po Å¡tÄ›drém spropitném postil tuto zvÄ›st:" msgid "Recruit Hero" msgstr "Najmout hrdinu" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} je %{race} úroveň %{value} " msgid "with %{count} artifacts." msgstr "s %{count} artefakty." msgid "with 1 artifact." msgstr "s 1 artefaktem." msgid "without artifacts." msgstr "bez artefaktů." msgid "Recruit %{name} the %{race}" msgstr "Najmout %{race} %{name}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Volná' bojová formace roztáhne tvoje jednotky shora až dolů po celém " "bojiÅ¡ti, s minimálnÄ› jedným volným polem mezi jednotkami." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "'TÄ›sná' bojová formace seskupí tvoje jednotky do stÅ™edu na tvé stranÄ› " "bojiÅ¡tÄ›." msgid "Spread Formation" msgstr "Volná formace" msgid "Grouped Formation" msgstr "TÄ›sná formace" msgid "Click to show the next town." msgstr "Klikni pro zobrazení následujícího mÄ›sta." msgid "Click to show the previous town." msgstr "Klikni pro zobrazení pÅ™edchozího mÄ›sta." msgid "Set garrison combat formation to 'Spread'" msgstr "Nastavit bojovou formaci pevnosti na 'Volná'" msgid "Set garrison combat formation to 'Grouped'" msgstr "Nastavit bojovou formaci pevnosti na 'TÄ›sná'" msgid "Exit Castle Options" msgstr "Odejít z hradu" msgid "Castle Options" msgstr "Možnosti hradu" msgid "Not enough resources to recruit creatures." msgstr "Nemáš dost prostÅ™edků pro najmutí jednotek." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Tentokrát nemůžeÅ¡ nikoho najmout, tvé Å™ady jsou již plné." msgid "No creatures available for purchase." msgstr "Nejsou zde žádné jednotky k najmutí." msgid "Recruit Creatures" msgstr "Najmout jednotky" msgid "Hire all creatures in the town." msgstr "Najmout vÅ¡echny jednotky ve mÄ›stÄ›." msgid "Max" msgstr "Max" msgid "Available" msgstr "Dostupných" msgid "Town Population Information and Statistics" msgstr "Populace ve mÄ›stÄ› Informace a Statistiky" msgid "Damage" msgstr "Å kody" msgid "HP" msgstr "Zdravi" msgid "Growth" msgstr "Růst" msgid "week" msgstr "týden" msgid "View World" msgstr "Zobrazit SvÄ›t" msgid "View the entire world." msgstr "Zobraz celou mapu svÄ›ta." msgid "Puzzle" msgstr "Skládanka" msgid "View the obelisk puzzle." msgstr "Zobraz skládanku obelisků." msgid "Scenario Information" msgstr "Informace o HÅ™e" msgid "View information on the scenario you are currently playing." msgstr "Zobraz informaci o hÅ™e, kterou právÄ› hrajeÅ¡." msgid "Dig for the Ultimate Artifact." msgstr "Vykopej Ultimátní artefakt." msgid "Digging" msgstr "Kopání" msgid "Arena" msgstr "Aréna" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Vstoupíš do arény a postavíš se smeÄce divokých lvů. Snadno je porazíš za " "bouÅ™livého jásotu davu. Ohromen tvými schopnostmi ti starý trenér gladiátorů " "nabídne výcvik v dovednosti dle tvého výbÄ›ru." msgid "Attack Skill" msgstr "Útok" msgid "Defense Skill" msgstr "Obrana" msgid "Shots" msgstr "StÅ™ely" msgid "Shots Left" msgstr "Zbývá stÅ™el" msgid "Hit Points" msgstr "Životy" msgid "Hit Points Left" msgstr "Zbývá životů" msgid "You can't afford to upgrade your troops!" msgstr "NemůžeÅ¡ si dovolit vylepÅ¡it své jednotky!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Tvé jednotky mohou být vylepÅ¡eny ale nebude to zadarmo. PÅ™ejeÅ¡ si je " "vylepÅ¡it?" msgid "Are you sure you want to dismiss this army?" msgstr "Opravdu si pÅ™ejete rozpustit tuto armádu?" msgid "Upgrade" msgstr "Povýšit" msgid "Upgrade your troops." msgstr "VylepÅ¡i své jednotky." msgid "Dismiss" msgstr "Propustit" msgid "Dismiss this army." msgstr "Propustit tuto armádu." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Skupina %{monster} s touhou po velké slávÄ› se k tobÄ› chce pÅ™idat.\n" "PÅ™ijímáš?" msgid "Followers" msgstr "Následovníci" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} jsou uchlácholeni tvou diplomatickou Å™eÄí a nabízí ti, že vstoupí " "do tvé armády za %{gold} zlaťáků.\n" "PÅ™ijímáš?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "StvoÅ™ení jsou uchlácholeni tvou diplomatickou\n" "Å™eÄí a davají ti nabídku:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} z %{total} %{monster} se pÅ™idá k tvé armádÄ›, a zbytek tÄ› nechá na " "pokoji za %{gold} zlata.\n" "PÅ™ijímáš?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "VÅ¡ech %{offer} %{monster} se pÅ™idá k tvé armádÄ› za %{gold} zlata.\n" "PÅ™ijímáš?" msgid "(Rate: %{percent})" msgstr "(Hodn.:%{percent})" msgid "off" msgstr "off" msgid "Music" msgstr "Hudba" msgid "Effects" msgstr "Efekty" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Rozšířené" msgid "External" msgstr "Externí" msgid "Music Type" msgstr "Typ Hudby" msgid "3D Audio" msgstr "3D Audio" msgid "Toggle ambient music level." msgstr "Nastav úroveň hudby v pozadí." msgid "Toggle foreground sounds level." msgstr "Nastav úroveň herních zvuků." msgid "Change the type of music." msgstr "Změň typ hudby." msgid "Toggle the 3D effect of foreground sounds." msgstr "PÅ™epnout 3D efekty herních zvuků." msgid "Build a new ship:" msgstr "Postavit novou loÄ:" msgid "Resource cost:" msgstr "Náklady:" msgid "Total: " msgstr "Celkem: " msgid "Need: " msgstr "PotÅ™eba: " msgid "New Game" msgstr "Nová hra" msgid "Start a single or multi-player game." msgstr "Spustit hru jednoho nebo více hráÄů." msgid "Load Game" msgstr "NaÄíst hru" msgid "Load a previously saved game." msgstr "NaÄíst dříve uloženou hru." msgid "Save Game" msgstr "Uložit hru" msgid "Save the current game." msgstr "Uložit aktuální hru." msgid "Quit" msgstr "UkonÄit" msgid "Quit out of Heroes of Might and Magic II." msgstr "UkonÄit Heroes of Might and Magic II." msgid "Language" msgstr "Jazyk" msgid "Graphics" msgstr "Grafika" msgid "Black & White" msgstr "ÄŒernobílý" msgid "Mouse Cursor" msgstr "Kurzor" msgid "Color" msgstr "Barevný" msgid "Text Support" msgstr "Textová podpora" msgid "Change the language of the game." msgstr "ZmÄ›nit jazyk hry." msgid "Select Game Language" msgstr "Vybrat jazyk hry" msgid "Change the graphics settings of the game." msgstr "ZmÄ›nit grafické nastavení hry." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "PÅ™epnout barevný kurzor zap/vyp. Toto je jenom volba vzhledu." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Zap/Vyp textovou podporu - výstupem budou extra informace o oknech a " "událostech ve hÅ™e." msgid "" "Map\n" "Difficulty" msgstr "" "Obtížnost\n" "mapy" msgid "" "Game\n" "Difficulty" msgstr "" "Obtížnost\n" "hry" msgid "Rating" msgstr "Hodnocení" msgid "Map Size" msgstr "" "Velikost\n" "mapy" msgid "Opponents" msgstr "Protivníci" msgid "Class" msgstr "Rasa" msgid "" "Victory\n" "Conditions" msgstr "" "Podmínky\n" "výhry" msgid "" "Loss\n" "Conditions" msgstr "" "Podmínky\n" "prohry" msgid "First select recipients!" msgstr "Nejprve vyber příjemce!" msgid "You cannot select %{resource}!" msgstr "NemůžeÅ¡ vybrat %{resource}!" msgid "Set %{resource-type} Count" msgstr "Nastavit poÄet %{resource-type}" msgid "Select Recipients" msgstr "Vyber příjemce" msgid "Your Funds" msgstr "Tvé suroviny" msgid "Planned Gift" msgstr "Plánovaný dar" msgid "Gift from %{name}" msgstr "Dar od %{name}" msgid "Resolution" msgstr "RozliÅ¡ení" msgid "Fullscreen" msgstr "Celá obrazovka" msgid "window|Mode" msgstr "Režim" msgid "Windowed" msgstr "Okno" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Info o systému" msgid "Change the resolution of the game." msgstr "ZmÄ›nit rozlíšení." msgid "Select Game Resolution" msgstr "Vybrat rozliÅ¡ení" msgid "Toggle between fullscreen and windowed modes." msgstr "PÅ™epnout mezi celou obrazovkou a zobr. v oknÄ›." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "V-Sync může pomoct s blikáním na nÄ›kterých monitorech." msgid "Show extra information such as FPS and current time." msgstr "Zobraz extra informace jako FPS a místní Äas." msgid "Hotkey: " msgstr "Klávesová zkratka: " msgid "Category: " msgstr "Kategorie: " msgid "Event: " msgstr "Událost: " msgid "Hot Keys:" msgstr "Klávesové zkratky:" msgid "Hide" msgstr "Skrýt" msgid "Show" msgstr "Zobrazit" msgid "Interface" msgstr "Rozhraní" msgid "Interface Type" msgstr "Rozhraní" msgid "Toggle the type of interface you want to use." msgstr "PÅ™epnÄ›te typ rozhraní, které chcete používat." msgid "Toggle interface visibility." msgstr "PÅ™epnÄ›te viditelnost rozhraní." msgid "Scroll Speed" msgstr "Rychlost posunu" msgid "Sets the speed at which you scroll the window." msgstr "Nastavit rychlost posouvání okna." msgid "Select Game Language:" msgstr "Vybrat jazyk hry:" msgid "Select Language:" msgstr "Vybrat jazyk:" msgid "Click to choose the selected language." msgstr "Kliknutím vybereÅ¡ zvolený jazyk." msgid "%{name} has gained a level." msgstr "%{name} získal úroveň." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "NauÄil ses %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} získal úroveň.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "MůžeÅ¡ se nauÄit buÄ:\n" "%{skill1}\n" "nebo\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "NauÄit se %{secondary-skill}" msgid "n/a" msgstr "n/a" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Prohlédni si prosím naÅ¡e kvalitní zboží. Pokud máš chuÅ¥ nabídnout nÄ›co na " "výmÄ›nu, klikni na položky, které chceÅ¡ vymÄ›nit za jiné." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Nakoupil jsi opravdu výhodnÄ›. Myslím, že na tomhle obchodu skoro nic " "nevydÄ›lám. Zaujalo tÄ› jeÅ¡tÄ› nÄ›jaké jiné zboží?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Mohu ti nabídnout %{count} za 1 díl %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Mohu ti nabídnout 1 %{resto} za %{count} %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "K výmÄ›nÄ›" msgid "Trading Post" msgstr "SmÄ›nárna" msgid "Your Resources" msgstr "Tvoje suroviny" msgid "Available Trades" msgstr "Možno zamÄ›nit" msgid "guarded by %{count} %{monster}" msgstr "hlídáno %{count} %{monster}" msgid "guarded by " msgstr "hlídáno " msgid "(available: %{count})" msgstr "(K dispozici: %{count})" msgid "(empty)" msgstr "(prázdno)" msgid "already learned" msgstr "už to umíš" msgid "treeOfKnowledge|free" msgstr "zdarma" msgid "already claimed" msgstr "už to umíš" msgid "not claimed" msgstr "nevyzvednuto" msgid "already knows this skill" msgstr "tuhle dovednost už máš" msgid "already has max skills" msgstr "má už maximální dovednosti" msgid "(already visited)" msgstr "(navÅ¡tíveno)" msgid "(not visited)" msgstr "(nenavÅ¡tíveno)" msgid "%{color} Barrier" msgstr "%{color} bariéra" msgid "(tent visited)" msgstr "(nenavÅ¡tíveno)" msgid "%{color} Tent" msgstr "%{color} stan" msgid "Road" msgstr "Cesta" msgid "(digging ok)" msgstr "(lze kopat)" msgid "(no digging)" msgstr "(nelze kopat)" msgid "penalty: %{cost}" msgstr "odebere: %{cost}" msgid "Defenders:" msgstr "Obránci:" msgid "Unknown" msgstr "Není známo" msgid "heroQuickInfo|(Level %{level})" msgstr "(Úroveň %{level})" msgid "Attack:" msgstr "Útok:" msgid "Defense:" msgstr "Obrana:" msgid "Spell Power:" msgstr "Síla Kouzel:" msgid "Knowledge:" msgstr "Znalosti:" msgid "Spell Points:" msgstr "Mana:" msgid "Move Points:" msgstr "Body pohybu:" msgid "Uncharted Territory" msgstr "Neprobádaná oblast" msgid "Cost per troop:" msgstr "Cena za jedince:" msgid "Available: %{count}" msgstr "K dispozici: %{count}" msgid "Number to buy:" msgstr "Nakoupit:" msgid "Recruit selected monsters." msgstr "Najmout vybrané jednotky." msgid "Select maximum monsters to be recruited." msgstr "Vybrat maximální poÄet k najmutí." msgid "Select only 1 monster to be recruited." msgstr "Vybrat pouze 1 jednotku k najmutí." msgid "Select this game resolution." msgstr "Vybrat rozliÅ¡ení." msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" "VýbÄ›rem tohoto rozliÅ¡ení nastavíte rozliÅ¡ení, které je Å¡kálováno z původního " "rozliÅ¡ení (%{resolution}) vynásobením Äíslem v závorce (%{scale}).\n" "\n" "RozliÅ¡ení s celým násobkem (2.0x, 3.0x atd.) obvykle vypadá lépe, protože " "pixely jsou rovnomÄ›rnÄ› zvÄ›tÅ¡ovány ve vodorovném i svislém smÄ›ru." msgid "Select Game Resolution:" msgstr "Nastav rozliÅ¡ení hry:" msgid "Click to apply the selected resolution." msgstr "Kliknutím se rozliÅ¡ení zmÄ›ní na vybrané." msgid "Click to apply the entered text." msgstr "KliknÄ›te pro použití zadaného textu." msgid "Click to open the Virtual Keyboard dialog." msgstr "KliknÄ›te pro otevÅ™ení dialogu s virtuální klávesnicí." msgid "Open Virtual Keyboard" msgstr "Oteřít virtuální klávesnici" msgid "How many creatures do you wish to move?" msgstr "Kolik jednotek si pÅ™ejeÅ¡ pÅ™esunout?" msgid "Select how many units to separate into:" msgstr "Vyberte kolik jednotek chcete rozdÄ›lit:" msgid "Map: " msgstr "Mapa: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "MÄ›síc: " msgid ", Week: " msgstr ", Týden: " msgid ", Day: " msgstr ", Den: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Cesta: " msgid "Are you sure you want to delete file:" msgstr "Opravdu chceÅ¡ smazat soubor:" msgid "Warning" msgstr "Varování" msgid "Click to save the current game." msgstr "Klikni pro uložení aktuální hry." msgid "Click to load a previously saved game." msgstr "Klikni pro naÄtení dříve uložené hry." msgid "File to Save:" msgstr "Uložit do souboru:" msgid "File to Load:" msgstr "Soubor k naÄtení:" msgid "Terrain object" msgstr "Terén" msgid "Accept the choice made." msgstr "PÅ™ijmout vybranou volbu." msgid "Select Skill:" msgstr "Vybrat dovednost:" msgid "Select Spell:" msgstr "Seslat kouzlo:" msgid "Select Artifact:" msgstr "Vybrat arkefakt:" msgid "Select Monster:" msgstr "Vybrat jednotku:" msgid "Select Hero:" msgstr "Vybrat hrdinu:" msgid "race|Random" msgstr "Náhodný" msgid "Click to start placing the selected hero." msgstr "KliknÄ›te pro zahájení umístÄ›ní vybraného hrdiny." msgid "%{color} %{race}" msgstr "%{color} %{race}" msgid "You will place" msgstr "Umístíte" msgid "Click to select this class." msgstr "KliknÄ›te pro výbÄ›r této třídy." msgid "Click to select this color." msgstr "Kliknout pro výbÄ›r barvy." msgid "Select Treasure:" msgstr "Vyberte poklad:" msgid "Select Ocean Object:" msgstr "Vyberte oceánský objekt:" msgid "Castle/town placing" msgstr "UmístÄ›ní hradu/mÄ›sta" msgid "doubleLinedRace|Neutral" msgstr "Neutrální" msgid "Click to start placing the selected castle/town." msgstr "KliknÄ›te pro zahájení umístÄ›ní vybraného hradu/mÄ›sta." msgid "Click to select town placing." msgstr "KliknÄ›te pro výbÄ›r umístÄ›ní mÄ›sta." msgid "Click to select castle placing." msgstr "KliknÄ›te pro výbÄ›r umístÄ›ní hradu." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{race} %{townOrCastle}" msgid "race|Neutral" msgstr "Neutrální" msgid "Select Dwelling:" msgstr "Vybrat jednotku:" msgid "Select Landscape Object:" msgstr "Vybrat object krajiny:" msgid "Mine placing" msgstr "UmístÄ›ní dolu" msgid "" "Resource\n" "type:" msgstr "Typ suroviny:" msgid "%{mineName} appearance:" msgstr "Vzhled %{mineName}:" msgid "Click to select %{object} as the resource generator to be placed." msgstr "KliknÄ›te pro výbÄ›r %{object} jako generátoru surovin k umístÄ›ní." msgid "Select Mountain Object:" msgstr "Vyberte horský objekt:" msgid "Select Rock Object:" msgstr "Vyberte skalní objekt:" msgid "Select Tree Object:" msgstr "Vyberte stromový objekt:" msgid "Select Power Up Object:" msgstr "Vyberte objekt pro zvýšení síly:" msgid "Select Adventure Object:" msgstr "Vyberte dobrodružný objekt:" msgid "Players Icon" msgstr "Ikona hráÄe" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Udává, kolik hráÄů celkem je ve scénáři. Jakékoli pozice, které nejsou " "obsazeny hráÄi, budou obsazeny hráÄi ovládanými poÄítaÄem." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Udává, zda je mapa\n" "malá (36 x 36), stÅ™ední\n" "(72 x 72), velká (108 x 108)\n" "nebo extra velká (144 x 144)." msgid "Size Icon" msgstr "Velikost ikon" msgid "Map Type" msgstr "Typ mapy" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Udává, zda je mapa vytvoÅ™ena pro verzi hry \"Války o následnictví\", \"Cena " "za vÄ›rnost\" nebo \"Vzkříšení\"." msgid "Map Type:\n" msgstr "Typ mapy\n" msgid "The Succession Wars" msgstr "Války o následnictví" msgid "The Price of Loyalty" msgstr "Cena za vÄ›rnost" msgid "Resurrection" msgstr "Resurrection" msgid "" "\n" "\n" "Language:\n" msgstr "" "\n" "\n" "Jazyk:\n" msgid "Lose all your heroes and towns." msgstr "Ztráta vÅ¡ech mÄ›st a hrdinů." msgid "Lose a specific town." msgstr "Ztráta vybraného mÄ›sta." msgid "Lose a specific hero." msgstr "Ztráta vybraného hrdiny." msgid "Run out of time. Fail to win by a certain point." msgstr "Vyprší vám Äas. Pokud nezvítÄ›zíte do stanoveného bodu, prohrajete." msgid "Loss Condition" msgstr "Podmínky prohry" msgid "Defeat all enemy heroes and towns." msgstr "Porazte vÅ¡echny nepřátelské hrdiny a mÄ›sta." msgid "Capture a specific town." msgstr "Dobijte konkrétní mÄ›sto." msgid "Defeat a specific hero." msgstr "Porazte konkrétního hrdinu." msgid "Find a specific artifact." msgstr "NajdÄ›te konkrétní artefakt." msgid "Your side must defeat the opposing side." msgstr "VaÅ¡e strana musí porazit stranu protivníka." msgid "Accumulate a large amount of gold." msgstr "NahromadÄ›te velké množství zlata." msgid "Victory Condition" msgstr "Podmínky vítÄ›zství" msgid "Map difficulty:" msgstr "Obtížnost mapy:" msgid "N" msgstr "N" msgid "No maps exist at that size." msgstr "V této velikosti neexistují žádné mapy." msgid "Small Maps" msgstr "Malé mapy" msgid "View only maps of size small (36 x 36)." msgstr "Zobrazí pouze mapy velikosti malá (36 x 36)." msgid "Medium Maps" msgstr "StÅ™ední mapy" msgid "View only maps of size medium (72 x 72)." msgstr "Zobrazí pouze mapy velikosti stÅ™ední (72 x 72)." msgid "Large Maps" msgstr "Velké mapy" msgid "View only maps of size large (108 x 108)." msgstr "Zobrazí pouze mapy velikosti velká (108 x 108)." msgid "Extra Large Maps" msgstr "Velmi velké mapy" msgid "View only maps of size extra large (144 x 144)." msgstr "Zobrazí pouze mapy velikosti Velmi velká (144 x 144)." msgid "All Maps" msgstr "VÅ¡echny mapy" msgid "View all maps, regardless of size." msgstr "Zobrazí vÅ¡echny mapy, nezávisle na velikosti." msgid "Selected Name" msgstr "Vybrané jméno" msgid "The name of the currently selected map." msgstr "Název aktuálnÄ› vybrané mapy." msgid "Selected Map Difficulty" msgstr "Vybraná obtížnost mapy" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Obtížnost aktuálnÄ› vybrané mapy. Obtížnost mapy je stanovena tvůrcem " "scénáře. NároÄnÄ›jší mapy mohou zahrnovat více nebo silnÄ›jší nepřátele, ménÄ› " "surovin Äi jiné speciální podmínky, které ztěžují hráÄi hru." msgid "Selected Description" msgstr "Vybraný popis" msgid "The description of the currently selected map." msgstr "Popis aktuálnÄ› vybrané mapy." msgid "Jump" msgstr "Skok" msgid "Hero Speed" msgstr "Rychlost hrdiny" msgid "Don't Show" msgstr "Nezobrazovat" msgid "Enemy Speed" msgstr "Rychlost nepřátel" msgid "Auto Resolve" msgstr "Automaticky" msgid "Auto, No Spells" msgstr "Auto, Bez kouzel" msgid "Battles" msgstr "Bitvy" msgid "combatMode|Manual" msgstr "RuÄnÄ›" msgid "Change the speed at which your heroes move on the main screen." msgstr "Změňte rychlost, jakou se vaÅ¡i hrdinové pohybují na hlavní obrazovce." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Nastavte rychlost pohybu poÄítaÄem ovládaných hrdinů. Můžete také zvolit, že " "vůbec nechcete sledovat pohyb poÄítaÄe." msgid "Change the interface settings of the game." msgstr "ZmÄ›nit grafické nastavení hry." msgid "Interface Settings" msgstr "Grafické Nastavení" msgid "Toggle instant battle mode." msgstr "PÅ™epnÄ›te režim okamžité bitvy." msgid "Att." msgstr "Útok" msgid "Def." msgstr "Obrana" msgid "Power" msgstr "S. Kou." msgid "Knowl" msgstr "Znal." msgid "1st" msgstr "1." msgid "2nd" msgstr "2." msgid "3rd" msgstr "3." msgid "4th" msgstr "4." msgid "5th" msgstr "5." msgid "6th" msgstr "6." msgid "Oracle: Player Rankings" msgstr "PoÅ™adí hráÄů" msgid "Thieves' Guild: Player Rankings" msgstr "PoÅ™adí hráÄů" msgid "Number of Towns:" msgstr "PoÄet mÄ›st:" msgid "Number of Castles:" msgstr "PoÄet hradů:" msgid "Number of Heroes:" msgstr "PoÄet hrdinů:" msgid "Gold in Treasury:" msgstr "Zlato v pokladici:" msgid "Wood & Ore:" msgstr "DÅ™evo & Kamení:" msgid "Gems, Cr, Slf & Mer:" msgstr "Drah., Kryst., Síra:" msgid "Obelisks Found:" msgstr "Nalezeno Obelisků:" msgid "Artifacts:" msgstr "Artefakty:" msgid "Total Army Strength:" msgstr "Celková síla armády:" msgid "Income:" msgstr "Příjem:" msgid "Best Hero:" msgstr "Nejlepší hrdina:" msgid "Best Hero Stats:" msgstr "Statistiky hrdiny:" msgid "Personality:" msgstr "Osobnost:" msgid "Best Monster:" msgstr "Nejlepší jednotka:" msgid "Random Castle Name" msgstr "Náhodný název hradu" msgid "Random Town Name" msgstr "Náhodný název mÄ›sta" msgid "Allow Castle build" msgstr "Povolit stavbu hradu" msgid "Default Buildings" msgstr "Výchozí budovy" msgid "Default Army" msgstr "Výchozí armáda" msgid "Castle Army" msgstr "Armáda hradu" msgid "Town Army" msgstr "Armáda mÄ›sta" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" "KliknÄ›te pro zmÄ›nu názvu hradu. Pravým tlaÄítkem myÅ¡i obnovte výchozí " "nastavení." msgid "Enter Castle name" msgstr "Zadejte název hradu" msgid "Allow to build a castle in this town." msgstr "Povolit stavbu hradu v tomto mÄ›stÄ›." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "PÅ™epnout použití výchozích budov. Vlastní budovy budou resetovány!" msgid "Toggle building construction restriction mode." msgstr "PÅ™epnout režim omezení stavby budov." msgid "Restrict Building Construction" msgstr "Omezení výstavby budov" msgid "Use default defenders army." msgstr "Použít armádu výchozích obránců." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" "Nastavte vlastní armádu hradu. KliknÄ›te pravým tlaÄítkem pro obnovení " "jednotky." msgid "Message Text:" msgstr "Text zprávy:" msgid "Reward:" msgstr "OdmÄ›na:" msgid "Player colors allowed to get event:" msgstr "Barvy hráÄů, které mohou získat událost:" msgid "Computer colors allowed to get event:" msgstr "Barvy poÄítaÄových hráÄů, které mohou získat událost:" msgid "First day of occurrence:" msgstr "První den výskytu:" msgid "Repeat period (days):" msgstr "Opakovací období (dny):" msgid "Allow %{color} human player to get event" msgstr "Povolit hráÄi %{color} získat událost" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" "Pokud je toto zaÅ¡krtávací políÄko oznaÄeno, tato událost se spustí pro " "%{color} hráÄe, pokud ho ovládá ÄlovÄ›k." msgid "Allow %{color} computer player to get event" msgstr "Povolit poÄítaÄovému hráÄi %{color} získat událost" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" "Pokud je toto zaÅ¡krtávací políÄko oznaÄeno, tato událost se spustí pro " "%{color} hráÄe, pokud ho ovládá poÄítaÄ." msgid "Message:" msgstr "Zpráva:" msgid "Click to save the Event properties." msgstr "KliknÄ›te pro uložení vlastnosti události." msgid "No resources will be given as a reward." msgstr "Žádné suroviny nebudou poskytnuty jako odmÄ›na." msgid "Resources" msgstr "Suroviny" msgid "Resources will be given as a reward." msgstr "Suroviny budou poskytnuty jako odmÄ›na." msgid "Click here to change the event message." msgstr "KliknÄ›te zde pro zmÄ›nu zprávy události." msgid "Event Message Text" msgstr "Text události" msgid "Day: %{day}" msgstr "Den: %{day}" msgid "Daily Events" msgstr "Denní události" msgid "Click to save the events." msgstr "KliknÄ›te pro uložení událostí." msgid "Add Event" msgstr "PÅ™idat událost" msgid "Add an additional event." msgstr "PÅ™idat další událost." msgid "Edit Event" msgstr "Upravit událost" msgid "Edit an existing event." msgstr "Upravit stávající událost." msgid "Delete Event" msgstr "Smazat událost" msgid "Delete an existing event." msgstr "Smazat stávající událost." msgid "Effects:" msgstr "Efekty:" msgid "Conditions:" msgstr "Podmínky:" msgid "Cancel event after first visit" msgstr "ZruÅ¡it událost po první návÅ¡tÄ›vÄ›" msgid "Computer colors allowed to get the event:" msgstr "Barvy poÄítaÄe, kterým je povoleno získat událost:" msgid "Set Experience value" msgstr "Nastavte hodnotu zkuÅ¡eností" msgid "Artifact" msgstr "Artefakt" msgid "No artifact will be given by the event." msgstr "Událost neposkytne žádný artefakt." msgid "Delete Artifact" msgstr "Odstranit artefakt" msgid "Delete an artifact from the event." msgstr "Odstranit artefakt z události." msgid "No Secondary Skill will be given by the event." msgstr "Událost neposkytne žádnou druhotnou schopnost." msgid "Secondary Skill" msgstr "Druhotná schopnost" msgid "Delete Secondary Skill" msgstr "Odstranit druhotnou schopnost" msgid "Delete the Secondary Skill from the event." msgstr "Odstranit druhotnou schopnost z události." msgid "No resources will be part of this event." msgstr "Žádné suroviny nebudou souÄástí této události." msgid "These resources will be a part of the event." msgstr "Tyto suroviny budou souÄástí události." msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" "Pokud je toto zaÅ¡krtávací políÄko zaÅ¡krtnuto, událost se spustí pouze " "jednou. Pokud není zaÅ¡krtnuto, událost se spustí pokaždé, když nÄ›který z " "uvedených hráÄů pÅ™ekroÄí políÄko s událostí." msgid "%{objects} cannot be placed on water." msgstr "%{objects} nelze umístit na vodu." msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Ultimátní artefakt lze umístit pouze na terén, kde je možné kopat." msgid "%{objects} must be placed on water." msgstr "%{objects} musí být umístÄ›ny na vodÄ›." msgid "Objects cannot be placed outside the map." msgstr "Objekty nelze umístit mimo mapu." msgid "Action objects must be placed on clear tiles." msgstr "AkÄní objekty musí být umístÄ›ny na prázdných polích." msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "PÅ™ejete si se vrátit do hlavního menu hry? VÅ¡echny neuložené zmÄ›ny budou " "ztraceny." msgid "Editor" msgstr "Editor" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Opravdu si pÅ™ejete naÄíst novou mapu? (VÅ¡echny neuložené zmÄ›ny na aktuální " "mapÄ› budou ztraceny.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Opravdu si pÅ™ejete vytvoÅ™it novou mapu? (VÅ¡echny neuložené zmÄ›ny na aktuální " "mapÄ› budou ztraceny.)" msgid "" "MAIN\n" "MENU" msgstr "" "HLAVNÃ\n" "MENU" msgid "" "START\n" "MAP" msgstr "" "SPUSTIT\n" "MAPU" msgid "Main Menu" msgstr "Hlavní menu" msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "PÅ™ejete si vrátit se do hlavního menu hry? (VÅ¡echny neuložené zmÄ›ny na " "aktuální mapÄ› budou ztraceny.)" msgid "Unsaved Changes" msgstr "Neuložené zmÄ›ny" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" "Tato mapa obsahuje zmÄ›ny terénu, historii akcí nebo jeÅ¡tÄ› nebyla uložena do " "souboru.\n" "\n" "PÅ™ejete si uložit aktuální mapu?" msgid "Unplayable Map" msgstr "Nehratelná mapa" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" "Tato mapa není hratelná. Pro její spuÅ¡tÄ›ní je potÅ™eba alespoň jeden ÄlovÄ›k." msgid "Start Map" msgstr "Spustit mapu" msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "PÅ™ejete si opustit editor a spustit mapu? (VÅ¡echny neuložené zmÄ›ny na " "aktuální mapÄ› budou ztraceny.)" msgid "Create a new map from scratch." msgstr "VytvoÅ™it novou mapu od základu." msgid "New Map" msgstr "Nová mapa" msgid "Load Map" msgstr "NaÄíst mapu" msgid "Load an existing map." msgstr "NaÄíst existující mapu." msgid "Save Map" msgstr "Uložit mapu" msgid "Save the current map." msgstr "Uložit aktuální mapu." msgid "Quit out of the map editor." msgstr "UkonÄit editor map." msgid "Return to the game's Main Menu." msgstr "Vrátit se do hlavního menu hry." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "Opustit editor a spustit mapu v režimu standardní hry." msgid "Input %{object} text" msgstr "Zadejte text %{object}" msgid "Set Random Ultimate Artifact Radius" msgstr "Nastavit náhodný rádius Ultimátního artefaktu" msgid "%{object} has no properties to change." msgstr "%{object} nemá žádné vlastnosti k úpravÄ›." msgid "This artifact" msgstr "Tento artefakt" msgid "The total number of obelisks is %{count}." msgstr "Celkový poÄet obelisků je %{count}." msgid "Roads" msgstr "Cesty" msgid "Streams" msgstr "Řeky" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "Na mapÄ› může být umístÄ›no maximálnÄ› %{count} hrdinů stejné barvy." msgid "Failed to update player information." msgstr "Aktualizace informací o hráÄi se nezdaÅ™ila." msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Na mapÄ› může být umístÄ›n pouze jeden náhodný Ultimátní artefakt." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "Na mapÄ› může být umístÄ›no maximálnÄ› %{count} obelisků." msgid "The map is corrupted." msgstr "Mapa je poÅ¡kozena." msgid "Unable to locate data directory to save the map." msgstr "Nelze najít adresář s daty pro uložení mapy." msgid "Unable to create a directory to save the map." msgstr "Nelze vytvoÅ™it adresář pro uložení mapy." msgid "Unable to locate a directory to save the map." msgstr "Nelze najít adresář pro uložení mapy." msgid "Are you sure you want to overwrite the existing map?" msgstr "Opravdu si pÅ™ejete pÅ™epsat stávající mapu?" msgid "Map saved to: " msgstr "Mapa uložena do: " msgid "Failed to save the map." msgstr "Uložení mapy se nezdaÅ™ilo." msgid "Used to place %{object}." msgstr "Používá se k umístÄ›ní %{object}." msgid "Select object type" msgstr "Vyberte typ objektu" msgid "" "Click here to\n" "select a monster." msgstr "" "KliknÄ›te zde\n" "pro výbÄ›r jednotky." msgid "" "Click here to\n" "select another monster." msgstr "" "KliknÄ›te zde\n" "pro další jednotky." msgid "" "Cell\n" "Details" msgstr "" "Podrobnosti\n" "buňky" msgid "Erase" msgstr "Vymazat" msgid "Mountains" msgstr "Hory" msgid "Rocks" msgstr "Skály" msgid "Trees" msgstr "Stromy" msgid "Water Objects" msgstr "Vodní objekty" msgid "Miscellaneous" msgstr "Různé" msgid "Artifacts" msgstr "Artefakty" msgid "Dwellings" msgstr "Obydlí" msgid "Mines" msgstr "Doly" msgid "Power-ups" msgstr "VylepÅ¡ení" msgid "Treasures" msgstr "Poklady" msgid "Heroes" msgstr "Hrdinové" msgid "Towns" msgstr "MÄ›sta" msgid "editorErasure|Landscape objects" msgstr "Krajinné objekty" msgid "editorErasure|Adventure non pickable objects" msgstr "Dobrodružné nevyzvednutelné objekty" msgid "editorErasure|Castles" msgstr "Hrady" msgid "editorErasure|Adventure pickable objects" msgstr "Dobrodružné vyzvednutelné objekty" msgid "editorErasure|Monsters" msgstr "Jednotky" msgid "editorErasure|Heroes" msgstr "Hrdinové" msgid "editorErasure|Roads" msgstr "Cesty" msgid "editorErasure|Streams" msgstr "Řeky" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Kreslí terén ve\n" "Ätvercových rozmÄ›rech %{size} na %{size}." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Odstraňuje objekty ve\n" "Ätvercových rozmÄ›rech %{size} na %{size}." msgid "Small Brush" msgstr "Malý Å¡tÄ›tec" msgid "Medium Brush" msgstr "StÅ™ední Å¡tÄ›tec" msgid "Large Brush" msgstr "Velký Å¡tÄ›tec" msgid "Area Fill" msgstr "VyplnÄ›ní oblasti" msgid "Used to click and drag for filling in large areas." msgstr "Používá se k vyplnÄ›ní velkých oblastí kliknutím a tažením." msgid "Clear Area" msgstr "VyÄistit oblast" msgid "Used to click and drag for clearing large areas." msgstr "Používá se k vyÄiÅ¡tÄ›ní velkých oblastí kliknutím a tažením." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Stojí %{rate} násobek běžného pohybu pro vÅ¡echny hrdiny. (Dovednost Hledání " "cest snižuje nebo eliminuje tuto penalizaci.)" msgid "Traversable only by boat." msgstr "PÅ™ekonatelné pouze lodí." msgid "No special modifiers." msgstr "Žádné speciální modifikátory." msgid "Toggle the erasure of %{type} objects." msgstr "PÅ™epnout mazání objektů typu %{type}." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Objekty tohoto typu budou smazány pomocí nástroje guma. Kliknutím levým " "tlaÄítkem zde zrušíte výbÄ›r tohoto typu. StisknÄ›te a podržte toto tlaÄítko " "pro zruÅ¡ení výbÄ›ru vÅ¡ech ostatních typů objektů." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Objekty tohoto typu NEBUDOU smazány pomocí nástroje guma. Kliknutím levým " "tlaÄítkem zde vyberete tento typ. StisknÄ›te a podržte toto tlaÄítko pro " "výbÄ›r vÅ¡ech ostatních typů objektů." msgid "Terrain Mode" msgstr "Režim terénu" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "Používá se k nakreslení podkladové trávy, hlíny, vody atd. na mapÄ›." msgid "Landscape Objects Mode" msgstr "Režim objektů krajiny" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Používá se k umístÄ›ní krajinných objektů (hory, skály, stromy atd.) na mapu." msgid "Detail Mode" msgstr "Detailní ežim" msgid "Used for special editing of action objects." msgstr "Používá se pro speciální úpravy akÄních objektů." msgid "Adventure Objects Mode" msgstr "Režim objektů dobrodružství" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Používá se k umístÄ›ní dobrodružných objektů (artefakty, obydlí, doly, " "poklady atd.) na mapu." msgid "Kingdom Objects Mode" msgstr "Režim objektu království" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Používá se k umístÄ›ní objektů království (mÄ›sta, hrady a hrdinové) na mapu." msgid "Monsters Mode" msgstr "Režim jednotek" msgid "Used to place monsters on the map." msgstr "Používá se k umístÄ›ní jednotek na mapu." msgid "Allows you to draw streams by clicking and dragging." msgstr "Umožňuje kreslit Å™eky kliknutím a tažením." msgid "Stream Mode" msgstr "Režim Å™ek" msgid "Allows you to draw roads by clicking and dragging." msgstr "Umožňuje kreslit cesty kliknutím a tažením." msgid "Road Mode" msgstr "Režim cesty" msgid "Erase Mode" msgstr "Režim mazání" msgid "Used to erase objects from the map." msgstr "Používá se k vymazání objektů z mapy." msgid "Change between zoom and normal view." msgstr "PÅ™epnout mezi pÅ™iblíženým a normálním zobrazením." msgid "Magnify" msgstr "PÅ™iblížit" msgid "Undo" msgstr "ZpÄ›t" msgid "Undo your last action." msgstr "ZruÅ¡it poslední akci." msgid "Redo" msgstr "Opakovat" msgid "Redo the last undone action." msgstr "Znovu proveÄ poslední vrácenou akci." msgid "Edit map title, description, and other general information." msgstr "Upravit název mapy, popis a další obecné informace." msgid "Specifications" msgstr "Specifikace" msgid "File Options" msgstr "Soubory" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Zobrazit volby pro uložení, naÄtení hry, stuÅ¡tÄ›ní nové hry anebo ukonÄení " "stávající." msgid "View the editor system options, which let you customize the editor." msgstr "Zobrazí systémové menu, s volbami pro úpravu chování hry." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" "VytvoÅ™te mapu, která je %{size} Ätverců Å¡iroká a %{size} Ätverců vysoká." msgid "Cancel back to the New Map menu." msgstr "ZruÅ¡it a vrátit se do nabídky Nová mapa." msgid "Cancel back to the main menu." msgstr "ZruÅ¡it a vrátit se do hlavní nabídky." msgid "From Scratch" msgstr "Od zaÄátku" msgid "Start from scratch with a blank map." msgstr "ZaÄít od zaÄátku s prázdnou mapou." msgid "Create a randomly generated map." msgstr "VytvoÅ™it náhodnÄ› generovanou mapu." msgid "Random" msgstr "NáhodnÄ›" msgid "Cancel back to the Map Editor main menu." msgstr "ZruÅ¡it a vrátit se do hlavního menu editoru map." msgid "No maps available!" msgstr "Žádné mapy k dispozici!" msgid "[%{pos}]: %{race} hero" msgstr "[%{pos}]: %{race} hrdina" msgid "[%{pos}]: %{name}, %{race} hero" msgstr "[%{pos}]: %{name}, %{race} hrdina" msgid "[%{pos}]: %{race} town" msgstr "[%{pos}]: %{race} mÄ›sto" msgid "[%{pos}]: %{race} castle" msgstr "[%{pos}]: %{race} hrad" msgid "[%{pos}]: %{name}, %{race} town" msgstr "[%{pos}]: %{name}, %{race} mÄ›sto" msgid "[%{pos}]: %{name}, %{race} castle" msgstr "[%{pos}]: %{name}, %{race} hrad" msgid "None." msgstr "Nic." msgid "One side defeats another." msgstr "Jedna strana poráží druhou." msgid "Accumulate gold." msgstr "NashromáždÄ›ní zlata." msgid "Run out of time." msgstr "VyprÅ¡ení Äasu znamená prohru." msgid "alliance|1st" msgstr "1." msgid "alliance|2nd" msgstr "2." msgid "alliance|3rd" msgstr "3." msgid "alliance|4th" msgstr "4." msgid "alliance|5th" msgstr "5." msgid "Special Loss Condition" msgstr "Speciální podmínky prohry" msgid "Special Victory Condition" msgstr "Speciální podmínky výhry" msgid "Allow standard victory conditions" msgstr "Povolit standardní podmínky vítÄ›zství" msgid "Allow this condition also for AI" msgstr "Povolit tuto podmínku také pro AI" msgid "Set alliances:" msgstr "Nastavení aliancí:" msgid "{%number} alliance: " msgstr "{%number} aliancí: " msgid "Gold:" msgstr "Zlato:" msgid "Select a Town to capture to achieve victory" msgstr "Vyberte mÄ›sto, které je tÅ™eba dobýt pro dosažení vítÄ›zství" msgid "Click here to change the town needed to capture to achieve victory." msgstr "" "KliknÄ›te zde pro zmÄ›nu mÄ›sta, které je tÅ™eba dobýt pro dosažení vítÄ›zství." msgid "Select a Hero to defeat to achieve victory" msgstr "Vyberte hrdinu, kterého je tÅ™eba porazit pro dosažení vítÄ›zství" msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "" "KliknÄ›te zde pro zmÄ›nu hrdiny, kterého je tÅ™eba porazit pro dosažení " "vítÄ›zství." msgid "Put %{color} player in the %{alliance} alliance" msgstr "PÅ™iÅ™adit hráÄe %{color} do aliance %{alliance}" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" "Pokud je toto zaÅ¡krtávací políÄko zaÅ¡krtnuto, %{color} hrÃ¡Ä bude v alianci " "%{alliance}." msgid "Days:" msgstr "Dny:" msgid "Select a Town to lose to suffer defeat" msgstr "Vyberte mÄ›sto, jehož ztráta způsobí prohru" msgid "Click here to change the town whose loss would mean defeat." msgstr "KliknÄ›te zde pro zmÄ›nu mÄ›sta, jehož ztráta by znamenala porážku." msgid "Select a Hero to lose to suffer defeat" msgstr "Vyberte hrdinu, jehož ztráta způsobí prohru" msgid "Click here to change the hero whose loss would mean defeat." msgstr "KliknÄ›te zde pro zmÄ›nu hrdiny, jehož ztráta by znamenala porážku." msgid "Map Difficulty" msgstr "Obtížnost mapy" msgid "Map Description" msgstr "Popis mapy" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" "Zadaný popis mapy pÅ™ekraÄuje maximálnÄ› povolených 5 řádků. Bude zkrácen tak, " "aby se veÅ¡el do pole pro popis mapy." msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" "Chystáte se zmÄ›nit jazyk mapy z %{oldLanguage} na %{newLanguage}. NÄ›které " "texty nemusí být po této zmÄ›nÄ› zobrazeny správnÄ›.Chcete pokraÄovat?" msgid "Change Map Name" msgstr "ZmÄ›nit název mapy" msgid "Change Map Description" msgstr "ZmÄ›nit popis mapy" msgid "Click to accept the changes made." msgstr "KliknÄ›te pro potvrzení provedených zmÄ›n." msgid "Click to edit custom rumors." msgstr "KliknÄ›te pro úpravu vlastních povÄ›stí." msgid "Rumors" msgstr "PovÄ›sti" msgid "Click to edit daily events." msgstr "KliknÄ›te pro úpravu denních událostí." msgid "Events" msgstr "Události" msgid "Click to change the language of the map." msgstr "KliknÄ›te pro zmÄ›nu jazyka mapy." msgid "Click to change your map name." msgstr "KliknÄ›te pro zmÄ›nu názvu mapy." msgid "Map Name" msgstr "Název mapy" msgid "Click to change the description of the current map." msgstr "KliknÄ›te pro zmÄ›nu popisu mapy." msgid "Click to change the victory condition of the current map." msgstr "KliknÄ›te pro zmÄ›nu podmínek vítÄ›zství aktuální mapy." msgid "Click to change the loss condition of the current map." msgstr "KliknÄ›te pro zmÄ›nu podmínek prohry aktuální mapy." msgid "Indicates the player types in the scenario. Click to change." msgstr "OznaÄuje typy hráÄů ve scénáři. Kliknutím změňte." msgid "Player Type" msgstr "Typ hráÄe" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "KliknÄ›te pro nastavení obtížnosti mapy. ObtížnÄ›jší mapy mohou zahrnovat " "silnÄ›jší nepřátele, ménÄ› surovin nebo jiné speciální podmínky, které ztěžují " "hru hráÄi." msgid "editor|%{count} %{resource}" msgstr "%{count} %{resource}" msgid "Animation" msgstr "Animace" msgid "Passability" msgstr "Průchodnost" msgid "Toggle animation of the objects." msgstr "PÅ™epnout animaci objektů." msgid "Toggle display of objects' passability." msgstr "PÅ™epnout zobrazení průchodnosti objektů." msgid "Rumor:" msgstr "PovÄ›st:" msgid "Rumor" msgstr "PovÄ›st" msgid "This rumor already exists in the list." msgstr "Tato povÄ›st již existuje v seznamu." msgid "Click to save the rumors." msgstr "KliknÄ›te pro uložení povÄ›stí." msgid "Add Rumor" msgstr "PÅ™idat povÄ›st" msgid "Add an additional rumor." msgstr "PÅ™idat další povÄ›st." msgid "Edit Rumor" msgstr "Upravit povÄ›st" msgid "Edit an existing rumor." msgstr "Upravit existující povÄ›st." msgid "Delete Rumor" msgstr "Odstranit povÄ›st" msgid "Delete an existing rumor." msgstr "Odtranit existující povÄ›st." msgid "" "\n" "\n" "Size: " msgstr "" "\n" "\n" "Velikost: " msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Popis: " msgid "Save Map:" msgstr "Uložit mapu:" msgid "Click to save the current map." msgstr "Klikni pro uložení aktuální mapy." msgid "Riddle:" msgstr "Hádanka:" msgid "Answers:" msgstr "OdpovÄ›di:" msgid "Answer:" msgstr "OdpovÄ›Ä:" msgid "Answer" msgstr "OdpovÄ›Ä" msgid "This answer exists in the list." msgstr "Tato odpovÄ›Ä již existuje v seznamu." msgid "Click to save the Sphinx properties." msgstr "KliknÄ›te pro uložení vlastností Sfingy." msgid "Add Answer" msgstr "PÅ™idat odpovÄ›Ä" msgid "Add an additional answer for the question." msgstr "PÅ™idat další odpovÄ›Ä na tuto otázku." msgid "Edit Answer" msgstr "Upravit odpovÄ›Ä" msgid "Edit an existing answer for the question." msgstr "Upravit stávající odpovÄ›Ä na tuto otázku." msgid "Delete Answer" msgstr "Odstranit odpovÄ›Ä" msgid "Delete an existing answer for the question." msgstr "Smazat stávající odpovÄ›Ä na tuto otázku." msgid "No artifact will be given as a reward." msgstr "Žádný artefakt nebude udÄ›len jako odmÄ›na." msgid "Delete an artifact from the reward." msgstr "Smazat artefakt z odmÄ›ny." msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "Den: %{day} Týden: %{week} MÄ›síc: %{month}" msgid "difficulty|Easy" msgstr "Lehká" msgid "difficulty|Normal" msgstr "Normální" msgid "difficulty|Hard" msgstr "Těžká" msgid "difficulty|Expert" msgstr "Expert" msgid "difficulty|Impossible" msgstr "Nehratelná" msgid "and more..." msgstr "a víc..." msgid "Easy" msgstr "Lehká" msgid "Normal" msgstr "Normální" msgid "Hard" msgstr "Těžká" msgid "Campaign Difficulty" msgstr "Obtížnost kampanÄ›" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Zvolte tuto obtížnost, pokud si chcete užít příbÄ›h hry s menší výzvou. AI " "bude slabší než na normální obtížnosti." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Zvolte tuto obtížnost, abyste zažili kampaň tak, jak byla původnÄ› navržena." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Zvolte tuto obtížnost, pokud chcete vÄ›tší výzvu. AI bude silnÄ›jší než na " "normální obtížnosti." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Gratulace!\n" "\n" "Dny: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Obtížnost: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Skóre: %{score}\n" "\n" "Hodnocení:\n" "%{rating}" msgid "Start the selected scenario." msgstr "SpusÅ¥te vybraný scénář." msgid "View Intro" msgstr "Zobrazit úvod" msgid "View the intro video for the current state of the campaign." msgstr "Zobrazit úvodní video pro aktuální stav kampanÄ›." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "Vyberte obtížnost kampanÄ›. Tu lze snížit kdykoli bÄ›hem kampanÄ›." msgid "Restart the current scenario." msgstr "Restartuj aktuální scénář." msgid "Difficulty" msgstr "Obtížnost" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "ZmÄ›nili jste obtížnost kampanÄ› na nižší. Po tomto bodÄ› již nebude možné " "zmÄ›nu vrátit zpÄ›t. Nejvyšší skóre bude vypoÄítáno pouze na základÄ› nové " "obtížnosti. Chcete pokraÄovat?" msgid "Are you sure you want to restart this scenario?" msgstr "Opravdu si pÅ™ejete restartovat tento scénář?" msgid "Campaign Scenario loading failure" msgstr "NapodaÅ™ilo se naÄíst hru kampanÄ›" msgid "Please make sure that campaign files are correct and present." msgstr "Prosím ujistÄ›te se, že jsou soubory v pořádku a k dispozici." msgid "Days spent" msgstr "UbÄ›hlo dní" msgid "The number of days spent on this campaign." msgstr "PoÄet dní od zaÄátku této kampanÄ›." msgid "Project Coordination and Core Development" msgstr "Koordinace projektu a hlavní vývoj" msgid "Development" msgstr "Vývoj" msgid "Visit us at " msgstr "NavÅ¡tivte nás na " msgid "QA and Support" msgstr "ZajiÅ¡tÄ›ní kvality a podpora" msgid "Dev and Support" msgstr "Vývoj a podpora" msgid "Special Thanks to" msgstr "Speciální podÄ›kování" msgid "and many-many other contributors and supporters!" msgstr "a mnoho dalších pÅ™ispÄ›vatelů a podporovatelů!" msgid "Support us at" msgstr "PodpoÅ™te nás na" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Spojte se s námi na" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "PotÅ™ebujete pomoc s hrou?" msgid "Original project before 0.7" msgstr "Originální projekt pÅ™ed verzí 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Tým Heroes of Might and Magic II: Války o následnictví" msgid "Designed and Directed" msgstr "Navrženo a režírováno" msgid "Programming and Design" msgstr "Programování a design" msgid "Executive Producer" msgstr "Výkonný producent" msgid "Producer" msgstr "Producent" msgid "Additional Design" msgstr "Doplňkový design" msgid "Additional Programming" msgstr "Doplňkové programování" msgid "Musical Production" msgstr "Hudební produkce" msgid "Music and Sound Design" msgstr "Hudba a zvukový design" msgid "Vocalists" msgstr "Vokalisté" msgid "Art Director" msgstr "UmÄ›lecký Å™editel" msgid "Assistant Art Director" msgstr "Asistent umÄ›leského Å™editele" msgid "Artists" msgstr "UmÄ›lci" msgid "QA Manager" msgstr "Manažer zajiÅ¡tÄ›ní kvality" msgid "QA" msgstr "ZajiÅ¡tÄ›ní kvality" msgid "Writing" msgstr "Scénář" msgid "Manual and Helpfile" msgstr "Manuál a nápovÄ›da" msgid "Scenarios" msgstr "Scénář" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Tým Heroes of Might and Magic II: Cena za vÄ›rnost" msgid "Design Lead" msgstr "Vedoucí návrhář" msgid "Designers" msgstr "Návrháři" msgid "Programming Lead" msgstr "Vedoucí programátor" msgid "Art Lead" msgstr "Vedoucí umÄ›lec" msgid "Playtesters" msgstr "TesteÅ™i" msgid "Designer" msgstr "Návrhář" msgid "Producers" msgstr "Producenti" msgid "QA Managers" msgstr "ManažeÅ™i QA" msgid "Sound Design" msgstr "Zvukový design" msgid "Town Themes" msgstr "Témata mÄ›st" msgid "Alto Sax" msgstr "Altový saxofón" msgid "Harpsichord and Piano" msgstr "Cembalo a klavír" msgid "Basso Vocal" msgstr "Basový zpÄ›v" msgid "Soprano Vocal" msgstr "Sopránový zpÄ›v" msgid "Recorded at %{recordingStudio}" msgstr "Nahráno v %{recordingStudio}" msgid "credits|Manual" msgstr "Návod" msgid "German Consultant" msgstr "NÄ›mecký konzultant" msgid "Map Designers" msgstr "Návrháři map" msgid "Package Design" msgstr "Návrh obalu" msgid "High Scores" msgstr "Nejlepší výsledky" msgid "Your Name" msgstr "Jméno" msgid "Unknown Hero" msgstr "Neznámý hrdina" msgid "Standard" msgstr "Standarní" msgid "View High Scores for Standard Maps." msgstr "Zobrazit nejlepší výsledky standardních map." msgid "Campaign" msgstr "Kampaň" msgid "View High Scores for Campaigns." msgstr "Zobrazit nejlepší výsledky kampanÄ›." msgid "hotkey|default okay event" msgstr "Výchozí potvrzení události" msgid "hotkey|default cancel event" msgstr "Výchozí zruÅ¡ení události" msgid "hotkey|default left" msgstr "Vlevo" msgid "hotkey|default right" msgstr "Vpravo" msgid "hotkey|default up" msgstr "Nahoru" msgid "hotkey|default down" msgstr "Dolů" msgid "hotkey|toggle fullscreen" msgstr "PÅ™epnout na celou obrazovku" msgid "hotkey|toggle text support mode" msgstr "PÅ™epnout režim podpory textu" msgid "hotkey|toggle developer mode" msgstr "pÅ™epnout režim vývojáře" msgid "hotkey|new game" msgstr "Nová hra" msgid "hotkey|load game" msgstr "NaÄíst hru" msgid "hotkey|high scores" msgstr "Nejlepší výsledky" msgid "hotkey|credits" msgstr "AutoÅ™i" msgid "hotkey|standard game" msgstr "Standadní hra" msgid "hotkey|campaign game" msgstr "Kampaň" msgid "hotkey|multi-player game" msgstr "Hra více hráÄů" msgid "hotkey|settings" msgstr "Nastavení" msgid "hotkey|quit" msgstr "UkonÄit" msgid "hotkey|select map" msgstr "VýbÄ›r mapy" msgid "hotkey|select small map size" msgstr "Vybrat malou mapu" msgid "hotkey|select medium map size" msgstr "Vybrat stÅ™ední mapu" msgid "hotkey|select large map size" msgstr "Vybrat velkou mapu" msgid "hotkey|select extra large map size" msgstr "Vybrat extra velkou mapu" msgid "hotkey|select all map sizes" msgstr "Vybrat vÅ¡echny mapy" msgid "hotkey|hot seat game" msgstr "Horké kÅ™eslo" msgid "hotkey|battle only game" msgstr "Volný boj" msgid "hotkey|choose the original campaign" msgstr "Vybrat originální kampaň" msgid "hotkey|choose the expansion campaign" msgstr "Vybrat kampaň datadisku" msgid "hotkey|map editor main menu" msgstr "Hlavní menu editor map" msgid "hotkey|new map menu" msgstr "Menu nová mapa" msgid "hotkey|load map menu" msgstr "Menu naÄíst mapu" msgid "hotkey|new map from scratch" msgstr "ZaÄít novou mapu" msgid "hotkey|new random map" msgstr "Nová náhodná mapa" msgid "hotkey|undo last action" msgstr "Vzít zpÄ›t poslední akci" msgid "hotkey|redo last action" msgstr "Opakovat poslední akci" msgid "hotkey|open game main menu" msgstr "Otevřít hlavní menu hry" msgid "hotkey|toggle passability" msgstr "PÅ™epnout průchodnost" msgid "hotkey|roland campaign" msgstr "Rolandova kampaň" msgid "hotkey|archibald campaign" msgstr "Archibaldova kampaň" msgid "hotkey|price of loyalty campaign" msgstr "Kampaň Cena za vÄ›rnost" msgid "hotkey|voyage home campaign" msgstr "Kampaň cesta domů" msgid "hotkey|wizard's isle campaign" msgstr "Kampaň Kouzelníkův ostrov" msgid "hotkey|descendants campaign" msgstr "Kampaň Potomci" msgid "hotkey|select first campaign bonus" msgstr "Vybrat první bonus kampanÄ›" msgid "hotkey|select second campaign bonus" msgstr "Vybrat druhý bonus kampanÄ›" msgid "hotkey|select third campaign bonus" msgstr "Vybrat tÅ™etí bonus kampanÄ›" msgid "hotkey|view campaign intro" msgstr "Zobrazit popis kampanÄ›" msgid "hotkey|select campaign difficulty" msgstr "Vybrat obtížnost kampanÄ›" msgid "hotkey|restart campaign scenario" msgstr "Restartovat scénář" msgid "hotkey|world map left" msgstr "Vlevo na mapÄ› svÄ›ta" msgid "hotkey|world map right" msgstr "Vpravo na mapÄ› svÄ›ta" msgid "hotkey|world map up" msgstr "Nahoru na mapÄ› svÄ›ta" msgid "hotkey|world map down" msgstr "Dolů na mapÄ› svÄ›ta" msgid "hotkey|world map up left" msgstr "Nahoru vlevo na mapÄ› svÄ›ta" msgid "hotkey|world map up right" msgstr "Nahoru vpravo na mapÄ› svÄ›ta" msgid "hotkey|world map down left" msgstr "Dolů vlevo na mapÄ› svÄ›ta" msgid "hotkey|world map down right" msgstr "Dolů vpravo na mapÄ› svÄ›ta" msgid "hotkey|save game" msgstr "Uložit hru" msgid "hotkey|next hero" msgstr "Následující hrdina" msgid "hotkey|change to hero under cursor" msgstr "PÅ™ejít na hrdinu pod kurzorem" msgid "hotkey|start hero movement" msgstr "Zahájit pohyb hrdiny" msgid "hotkey|cast adventure spell" msgstr "Seslat kouzlo" msgid "hotkey|put hero to sleep" msgstr "Uspat hrdinu" msgid "hotkey|next town" msgstr "Následující mÄ›sto" msgid "hotkey|end turn" msgstr "Konec kola" msgid "hotkey|file options" msgstr "Možnosti souboru" msgid "hotkey|adventure options" msgstr "Možnosti dobrodružství" msgid "hotkey|puzzle map" msgstr "Skládanka" msgid "hotkey|scenario information" msgstr "Informace o scénáři" msgid "hotkey|dig for artifact" msgstr "Kopání artefaktu" msgid "hotkey|view world" msgstr "Zobrazit svÄ›t" msgid "hotkey|kingdom summary" msgstr "PÅ™ehled království" msgid "hotkey|default action" msgstr "Výchozí akce" msgid "hotkey|open focus" msgstr "Otevřít zaměření" msgid "hotkey|system options" msgstr "Systémové nastavení" msgid "hotkey|scroll left" msgstr "Posun vlevo" msgid "hotkey|scroll right" msgstr "Posun vpravo" msgid "hotkey|scroll up" msgstr "Posun nahoru" msgid "hotkey|scroll down" msgstr "Posun dolů" msgid "hotkey|toggle control panel" msgstr "PÅ™epnout ovládací panel" msgid "hotkey|toggle radar" msgstr "PÅ™epnout radar" msgid "hotkey|toggle buttons" msgstr "PÅ™epnout tlaÄítka" msgid "hotkey|toggle status" msgstr "PÅ™epnout status" msgid "hotkey|toggle icons" msgstr "PÅ™epnout ikony" msgid "hotkey|transfer control to ai" msgstr "PÅ™edat ovládání AI" msgid "hotkey|retreat from battle" msgstr "Ústup z bitvy" msgid "hotkey|surrender during battle" msgstr "Kapitulace bÄ›hem bitvy" msgid "hotkey|toggle auto combat mode" msgstr "PÅ™epnout režim automatického boje" msgid "hotkey|quick combat" msgstr "rychlý boj" msgid "hotkey|battle options" msgstr "Možnosti bitvy" msgid "hotkey|skip turn in battle" msgstr "PÅ™eskoÄit tah v bitvÄ›" msgid "hotkey|cast battle spell" msgstr "Seslat bojové kouzlo" msgid "hotkey|dwelling level 1" msgstr "Obydlí úrovnÄ› 1" msgid "hotkey|dwelling level 2" msgstr "Obydlí úrovnÄ› 2" msgid "hotkey|dwelling level 3" msgstr "Obydlí úrovnÄ› 3" msgid "hotkey|dwelling level 4" msgstr "Obydlí úrovnÄ› 4" msgid "hotkey|dwelling level 5" msgstr "Obydlí úrovnÄ› 5" msgid "hotkey|dwelling level 6" msgstr "Obydlí úrovnÄ› 6" msgid "hotkey|well" msgstr "Studna" msgid "hotkey|marketplace" msgstr "Tržnice" msgid "hotkey|mage guild" msgstr "Věž kouzel" msgid "hotkey|shipyard" msgstr "Přístav" msgid "hotkey|thieves guild" msgstr "Cech zlodÄ›jů" msgid "hotkey|tavern" msgstr "Putyka" msgid "hotkey|construction screen" msgstr "Obrazovka výstavby" msgid "hotkey|buy all monsters in well" msgstr "Koupit vÅ¡echny jednotky ve studni" msgid "hotkey|split stack by half" msgstr "RozdÄ›lit jednotku napůl" msgid "hotkey|split stack by one" msgstr "RozdÄ›lit jednotku po jednom" msgid "hotkey|join stacks" msgstr "SlouÄit jednotky" msgid "hotkey|upgrade troop" msgstr "VylepÅ¡it jednotku" msgid "hotkey|dismiss hero or troop" msgstr "Propustit hrdinu nebo jednotku" msgid "hotkey|exchange all troops" msgstr "vymÄ›nit vÅ¡echny jednotky" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Chcete pÅ™evzít kontrolu zpÄ›t od AI? ZmÄ›na se projeví až v příštím tahu." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "Chcete pÅ™edat kontrolu AI? ZmÄ›na se projeví až v příštím tahu." msgid "Default Actions" msgstr "Výchozí akce" msgid "Global Actions" msgstr "Globální akce" msgid "World Map" msgstr "Mapa svÄ›ta" msgid "Battle Screen" msgstr "Obrazovka bitvy" msgid "Town Screen" msgstr "Obrazovka mÄ›sta" msgid "Army Actions" msgstr "Akce armády" msgid "The save file is corrupted." msgstr "Soubor je požkozen." msgid "Unsupported save format: " msgstr "Nepodporovaný formát: " msgid "Current game version: " msgstr "Aktuální verze hry: " msgid "Last supported version: " msgstr "Poslední podporovaná verze: " msgid "This file contains a save with an invalid game type." msgstr "Soubor obsahuje údaje z neplatné verze hry." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Hra byla uložena jako mapa z datadisku \"Cena za vÄ›rnost\", ale nebyly " "poskytnuty odpovídající zdrojové soubory." msgid "This saved game is localized to '" msgstr "Tato hra je uložena s lokalizací pro '" msgid "' language, but the current language of the game is '" msgstr "' jazyk, aktuálnÄ› máš ale nastaven jazyk '" msgid "No save files to load." msgstr "Žádné uložené hry k naÄtení." msgid "Hot Seat" msgstr "Horké kÅ™eslo" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Hrajte hru na jednom zařízení, kde se 2 až 6 hráÄů střídá na svém tahu v " "režimu 'Horké kÅ™eslo'." msgid "A single player game playing out a single map." msgstr "Hra pro jednoho hráÄe." msgid "Standard Game" msgstr "Standardní hra" msgid "A single player game playing through a series of maps." msgstr "Hra pro jednoho hráÄe, která probíhá na sérii map." msgid "Campaign Game" msgstr "Kampaň" msgid "Multi-Player Game" msgstr "Hra pro více hráÄů" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Hra pro více hráÄů, kde nÄ›kolik hráÄů soutěží proti sobÄ› na jedné mapÄ›." msgid "fheroes2 Resurrection Team presents" msgstr "Tým fheroes2 Resurrection uvádí" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "Vítejte ve hÅ™e Heroes of Might and Magic II běžící na enginu fheroes2!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" "\n" "\n" "Pro zobrazení informací o různých pÅ™edmÄ›tech pomocí dotykového ovládání " "staÄí pÅ™idržet prst na pÅ™edmÄ›tu, který vás zajímá, a poté se druhým prstem " "dotknout jiného místa na obrazovce. Jakmile držíte druhý prst, můžete první " "prst uvolnit a informace o pÅ™edmÄ›tu zůstanou zobrazené." msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "\n" "\n" "PÅ™ed spuÅ¡tÄ›ním hry prosím vyberte rozliÅ¡ení obrazovky." msgid "Greetings!" msgstr "Vítej!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "UkonÄí Heroes of Might and Magic II a vrátí se do operaÄního systému." msgid "Credits" msgstr "AutoÅ™i" msgid "View the credits screen." msgstr "Zobraz obrazovku s autory." msgid "View the high scores screen." msgstr "Zobraz tabulku s nej. skóre." msgid "Create new or modify existing maps." msgstr "VytvoÅ™it nebo upravit mapu." msgid "Change language, resolution and settings of the game." msgstr "Změň jazyk, rozliÅ¡ení a další nastavení hry." msgid "Game Settings" msgstr "Nastavení Hry" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Požadované video soubory pro okno výbÄ›ru kampanÄ› chybí. UjistÄ›te se, že jsou " "vÅ¡echny potÅ™ebné soubory v systému přítomny." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Rolandova nebo Archibaldova kampaň z původní hry Heroes of Might and Magic " "II." msgid "Original Campaign" msgstr "Originální kampaň" msgid "Expansion Campaign" msgstr "Kampaň datadisku" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "Jedna ze ÄtyÅ™ nových kampaní z datadisku Cena za vÄ›rnost." msgid "Loading video. Please wait..." msgstr "NaÄítání videa. Prosím, Äekej..." msgid "Host" msgstr "Hostitel" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Hostitel nastavuje herní možnosti. Může být pouze jeden hostitel na každé " "síťové hÅ™e." msgid "Guest" msgstr "Host" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "Host Äeká, až hostitel nastaví hru, poté je automaticky pÅ™idán. Pro hry TCP/" "IP může být více hostů." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "Aby mohl fheroes2 fungovat potÅ™ebuje soubory z původní hry Heroes of Might " "and Magic II. Zdá se, že k používáte demoverzi Heroes of Might and Magic II. " "VezmÄ›te prosím na vÄ›domí, že v tomto nastavení bude dostupný pouze jeden " "scénář." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Hra pro více hráÄů, kde nÄ›kolik hráÄů soutěží proti sobÄ› na jedné mapÄ›." msgid "Battle Only" msgstr "Pouze bitva" msgid "Setup and play a battle without loading any map." msgstr "Nastavte a zahrajte si bitvu bez naÄítání jakékoli mapy." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Hrajte hru na jednom zařízení, kde se 2 až 6 hráÄů střídá na svém tahu v " "režimu 'Horkého kÅ™esla'." msgid "2 Players" msgstr "2 hráÄi" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "Hrají 2 hráÄi a volitelnÄ› až se 4 dalšími hráÄi ovládanými poÄítaÄem." msgid "3 Players" msgstr "3 hráÄi" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "Hrají 3 hráÄi a volitelnÄ› až se 3 dalšími hráÄi ovládanými poÄítaÄem." msgid "4 Players" msgstr "4 hráÄi" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "Hrají 4 hráÄi a volitelnÄ› až se 2 dalšími hráÄi ovládanými poÄítaÄem." msgid "5 Players" msgstr "5 hráÄů" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "Hraje 5 hráÄů a volitelnÄ› až s 1 dalším hráÄem ovládaným poÄítaÄem." msgid "6 Players" msgstr "6 hráÄů" msgid "Play with 6 human players." msgstr "Hraje 6 hráÄů." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "DraÄí mÄ›sto padlo! Stal ses Pánem Draků." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Dobyl jsi %{name}!\n" "Jsi vítÄ›z." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Zajal jsi hrdinu %{name}!\n" "Tvůj úkol byl splnÄ›n." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Nalezl jsi %{name}.\n" "Tvůj úkol byl splnÄ›n." msgid "Ultimate Artifact" msgstr "Ultimátní Artefakt" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Nepřátel je poražen.\n" "Tvá strana triumfovala!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Nashromáždil si %{count} zlaťáků v pokladnici.\n" "VÅ¡ichni nepřátelé se klanÄ›jí tvému bohatství a síle." msgid "Victory!" msgstr "VítÄ›zství!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Nepřítel dobyl %{name}!\n" "Slaví vítÄ›zství." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Nepřátel nashromáždil %{count} zlaťáků v jeho pokladnici.\n" "Příjmi porážku a zkloň se pÅ™ed jeho bohatstvím a silou." msgid "You have been eliminated from the game!!!" msgstr "Byl jsi vyÅ™azen ze hry!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "PÅ™iÅ¡el jsi o hrdinu %{name}.\n" "Úkol nebyl splnÄ›n." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "NepodaÅ™ilo se ti dokonÄit úkol vÄas.\n" "VÅ¡e je ztraceno." msgid "Defeat!" msgstr "Porážka!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Základní skóre: %{score}\n" "Obtížnost: %{difficulty}\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "Porážka vÅ¡ech nepřátelských hrdinů a zabrání jejich mÄ›st a hradů." msgid "Your side defeats the opposing side." msgstr "VaÅ¡e strana poráží stranu protivníka." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "VyÄerpání Äasu. (Výhra není dosažena do urÄ. doby.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Musíš porazit %{enemies}." msgstr[1] "Musíš porazit nepřátelskou alianci %{enemies}." msgstr[2] "Musíš porazit nepřátelskou alianci %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Aliance je složená z %{allies}, musíte porazit nepřítele %{enemies}." msgstr[1] "" "Aliance je složená z %{allies}, musíte porazit nepřátelskou alianci tvořící " "%{enemies}." msgstr[2] "" "Aliance je složená z %{allies}, musíte porazit nepřátelskou alianci tvořící " "%{enemies}." msgid "Capture the castle '%{name}'." msgstr "Dobýt hrad '%{name}'." msgid "Capture the town '%{name}'." msgstr "Dobýt mÄ›sto '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Porážka hrdiny '%{name}'." msgid "Find the ultimate artifact." msgstr "Najít ultimátní artefakt." msgid "Find the '%{name}' artifact." msgstr "Najít artefakt '%{name}'." msgid "Accumulate %{count} gold." msgstr "Nashromáždit %{count} zlata." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", nebo můžeÅ¡ vyhrát i porážkou vÅ¡ech vÅ¡ech nepřátelských hrdinů a zabráním " "jejich mÄ›st a hradů." msgid "Lose the castle '%{name}'." msgstr "Ztratit hrad '%{name}'." msgid "Lose the town '%{name}'." msgstr "Ztratit mÄ›sto '%{name}'." msgid "Lose the hero: %{name}." msgstr "Ztratit hrdinu: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Nedosažení výhry pÅ™ed dovrÅ¡ením mÄ›síc %{month}, týden %{week}, den %{day}." msgid "%{color} player has been vanquished!" msgstr "%{color} hrÃ¡Ä byl poražen!" msgid "Major Event!" msgstr "Hlavní událost!" msgid "Scenario:" msgstr "Scénář:" msgid "Game Difficulty:" msgstr "Obtížnost hry:" msgid "Opponents:" msgstr "Protivníci:" msgid "Class:" msgstr "Rasa:" msgid "Rating %{rating}%" msgstr "Hodnocení %{rating}%" msgid "Click here to select which scenario to play." msgstr "Kliknout sem pro výbÄ›r scénáře." msgid "Scenario" msgstr "Scénář" msgid "Game Difficulty" msgstr "Obtížnost hry" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Toto vám umožňuje zmÄ›nit poÄáteÄní obtížnost, na které budete hrát. U vyšší " "úrovnÄ› obtížnosti zaÄnete s ménÄ› surovin a na vyšších nastaveních dají " "poÄítaÄi dodateÄné suroviny." msgid "Difficulty Rating" msgstr "Hodnocení obtížnosti" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Hodnocení obtížnosti odráži výslednou kombinaci voleb hry. Tento koeficient " "bude použit i pÅ™i výpoÄtu finálního skóre." msgid "Click to accept these settings and start a new game." msgstr "Klikni pro potvrzení volby a spusti novou hru." msgid "Click to return to the main menu." msgstr "Klikni pro návrat do hlavního menu." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Astrologové hlásí, že nastává mÄ›síc %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Astrologové hlásí, že nastává týden %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "PÅ™i pravidelném nárůstu doÅ¡lo ke zdvojení populace %{monster}!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "PÅ™i pravidelném nárůstu populace %{monster} narostla o %{count} procent!" msgstr[1] "" "PÅ™i pravidelném nárůstu populace %{monster} narostla o %{count} procenta!" msgstr[2] "" "PÅ™i pravidelném nárůstu populace %{monster} narostla o %{count} procent!" msgid "%{monster} growth +%{count}." msgstr "Růst %{monster} +%{count}." msgid " All populations are halved." msgstr " Populace jednotek k najmutí klesá na polovinu." msgid " All dwellings increase population." msgstr " VÅ¡echna obydlí zvyÅ¡ují svou populaci." msgid "New Month!" msgstr "Nový mÄ›síc!" msgid "New Week!" msgstr "ZaÄal nový týden!" msgid "Beware!" msgstr "Pozor!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "HráÄi %{color}, toto je tvůj poslední den na dobytí mÄ›sta, jinak budeÅ¡ " "vyhnán z této zemÄ›." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "HráÄi %{color}, zbývá ti už jen %{day} dní na dobytí mÄ›sta, jinak budeÅ¡ " "vyhnán z této zemÄ›." msgid "%{color} player's turn." msgstr "Táhne %{color} hráÄ." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "HráÄi %{color}, ztratil jsi své poslední mÄ›sto. Pokud bÄ›hem příštího týdne " "nedobudeÅ¡ jiné mÄ›sto, budeÅ¡ vyÅ™azen." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "HráÄi %{color}, tvoji hrdinové tÄ› opustili a byl jsi vyhnán z této zemÄ›." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "Další Hrdina" msgid "Select the next Hero." msgstr "Vybrat dalšího Hrdinu." msgid "Hero Movement" msgstr "Pohyb hrdiny" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "SpusÅ¥te pohyb hrdiny po aktuální cestÄ› nebo znovu navÅ¡tivte objekt, který " "hrdina obsadil. Podržením tohoto tlaÄítka resetujete cestu hrdiny." msgid "Kingdom Summary" msgstr "PÅ™ehled Království" msgid "View a summary of your Kingdom." msgstr "Zobrazte pÅ™ehled království." msgid "Cast an adventure spell." msgstr "Seslat kouzlo." msgid "End Turn" msgstr "UkonÄit tah" msgid "End your turn and let the computer take its turn." msgstr "UkonÄi svůj tah a nech táhnout poÄítaÄ." msgid "Adventure Options" msgstr "Možnosti hry" msgid "Bring up the adventure options menu." msgstr "Zobrazit možnosti hry." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Zobrazit volby pro uložení, naÄtení hry, stuÅ¡tÄ›ní nové hry anebo ukonÄení " "stávající." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "Zobrazí systémové menu, s volbami pro úpravu chování hry." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Jeden nebo více hrdinů se jeÅ¡tÄ› může pohybovat, urÄitÄ› chceÅ¡ ukonÄit svůj " "tah?" msgid "Are you sure you want to quit?" msgstr "Opravdu si pÅ™ejete ukonÄit hru?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "Opravdu si pÅ™ejete restartovat? (VaÅ¡e aktuální hra bude ztracena.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Opravdu si pÅ™ejete pÅ™epsat uloženou hru s tímto názvem?" msgid "Game saved successfully." msgstr "Hra byla uložena." msgid "There was an issue during saving." msgstr "BÄ›hem ukládání se vyskytla chyba." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Opravdu si pÅ™ejete naÄíst novou hru? (VaÅ¡e aktuální hra bude ztracena.)" msgid "Try looking on land!!!" msgstr "Zkus hledat v přírodÄ›!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Hledání ultimátního artefaktu nemá cenu. Tvůj hrdina si ho nemůže vzít, ani " "kdyby ho naÅ¡el - vÅ¡echny jeho sloty pro artefakty jsou plné." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Kopání vyžaduje celodenní úsilí, zkus to opÄ›t zítra." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Po nÄ›kolika hodinách strávených kopáním, jsi koneÄné objevil %{artifact}." msgid "Congratulations!" msgstr "Gratulace!" msgid "Nothing here. Where could it be?" msgstr "Nic jsi nenaÅ¡el. Kde to jen může být?" msgid "Try searching on clear ground." msgstr "Zkus hledat na volném místÄ›." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "ZmenÅ¡ený pohled na známý svÄ›t. Levým kliknutím posunete zobrazenou oblast." msgid "Month: %{month} Week: %{week}" msgstr "MÄ›síc: %{month} Týden: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Nalezl jsi malé\n" "množství %{resource}." msgid "Status Window" msgstr "Stavové okénko" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Zobrazuje informaci o stavu království nebo hrdinech, dále zobrazuje datum." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Toto okénko poskytuje informaci o stavu království, zobrazuje datum. Levým " "kliknutím můžeÅ¡ procházet zobrazované informace v oknÄ›." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Umožňuje mÄ›nit výchozí pozice a barvy hráÄů. Konkrétní barva bude vždy " "zaÄínat na urÄitém místÄ›. NÄ›které pozice může hrát pouze poÄítaÄový hrÃ¡Ä " "nebo pouze lidský hráÄ." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Umožňuje zmÄ›nit rasu hráÄe. Rasy nejdou zmÄ›nit vždy. V závislosti na scénáři " "může hrÃ¡Ä získat další mÄ›sta a nebo hrdiny, kteří nepatří k jeho primárnímu " "zaÄlenÄ›ní." msgid "Handicap" msgstr "Postih" msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Toto vám umožňuje zmÄ›nit postih konkrétního hráÄe. Postih může mít pouze " "ÄlovÄ›k. HráÄi s postihem zaÄínají s ménÄ› surovinami a získávají o 15 % nebo " "30 % ménÄ› surovin na tah, v závislosti na mírném nebo těžkém postihu." msgid "%{color} player" msgstr "%{color} hráÄ" msgid "No Handicap" msgstr "Bez postihu" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Žádná speciální omezení týkající se poÄáteÄních surovin a příjmu surovin za " "tah." msgid "Mild Handicap" msgstr "Lehký postih" msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "HráÄi s mírným postihem zaÄínají s menším množstvím surovin a získávají o 15 " "% ménÄ› surovin za tah." msgid "Severe Handicap" msgstr "Těžký postih" msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "HráÄi s velkým postihem zaÄínají s menším množstvím surovin a získávají o 30 " "% ménÄ› surovin za tah." msgid "" "Default\n" "value" msgstr "" "Výchozí\n" "hodnota" msgid "Set %{skill} Skill" msgstr "Nastavit dovednost %{skill}" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" "Nastavit základní hodnotu %{skill}. Pravým tlaÄítkem myÅ¡i obnovte vÅ¡echny " "dovednosti na výchozí hodnoty." msgid "View %{skill} Info" msgstr "Zobrazit informace o %{skill}" msgid "" "Default\n" "skill" msgstr "" "Výchozí\n" "dovednost" msgid "The available values range from %{min} to %{max}." msgstr "Dostupné hodnoty se pohybují v rozmezí od %{min} do %{max}." msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "Mezerník" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "Vložená hodnota není platná." msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" "Zadaná hodnota je mimo povolený rozsah.\n" "Musí být minimálnÄ› %{minValue} a maximálnÄ› %{maxValue}." msgid "Kingdom Income" msgstr "Příjmy království" msgid "Kingdom Income per day." msgstr "Příjem království za den." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Za každý ovládaný maják se budou vaÅ¡e lodÄ› pohybovat každý den o kus dále." msgid "English" msgstr "AngliÄtina" msgid "French" msgstr "FrancouzÅ¡tina" msgid "Polish" msgstr "PolÅ¡tina" msgid "German" msgstr "NÄ›mÄina" msgid "Russian" msgstr "RuÅ¡tina" msgid "Italian" msgstr "ItalÅ¡tina" msgid "Czech" msgstr "ÄŒeÅ¡tina" msgid "Norwegian" msgstr "NorÅ¡tina" msgid "Belarusian" msgstr "BÄ›loruÅ¡tina" msgid "Bulgarian" msgstr "BulharÅ¡tina" msgid "Ukrainian" msgstr "UkrajinÅ¡tina" msgid "Romanian" msgstr "RumunÅ¡tina" msgid "Spanish" msgstr "Å panÄ›lÅ¡tina" msgid "Swedish" msgstr "Å védÅ¡tina" msgid "Portuguese" msgstr "PortugalÅ¡tina" msgid "Turkish" msgstr "TureÄina" msgid "Dutch" msgstr "HolandÅ¡tina" msgid "Hungarian" msgstr "MaÄarÅ¡tina" msgid "Danish" msgstr "DánÅ¡tina" msgid "Slovak" msgstr "SlovenÅ¡tina" msgid "Vietnamese" msgstr "VÄ›tnamÅ¡tina" msgid "Slow" msgstr "Pomalá" msgid "Fast" msgstr "Rychlá" msgid "Very Fast" msgstr "Velmi rychlá" msgid "Evil" msgstr "Zlý" msgid "Good" msgstr "Dobrý" msgid ", FPS: " msgstr ", FPS: " msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} vykraden" msgid "pyramid|%{object} raided" msgstr "%{object} byla vykradena" # Heroes names section - translate not needed msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Sestra Eliza" msgid "Brother Brax" msgstr "Bratr Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " dává maximální morálku" msgid " gives you maximum luck" msgstr " dává maximální Å¡tÄ›stí" msgid "You cannot have multiple spell books." msgstr "Nemůžete mít více než jednu knihu kouzel." msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Tento artefakt nemůžeÅ¡ sebrat, již nemáš místo." msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "Abys mohl kouzlit, musíš si koupit knihu kouzel za %{gold} zlata." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Bohužel to vypadá, že vám momentálnÄ› schází zlato." msgid "Do you wish to buy one?" msgstr "PÅ™ejeÅ¡ si jeden koupit?" msgid "%{count} / day" msgstr "%{count}/ den" msgid "one" msgstr "jeden" msgid "two" msgstr "dva" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "Vodní vír pohltil vaÅ¡i loÄ. Část posádky spadla pÅ™es palubu." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Zamítnutí nabídky je urazilo a obratem na tebe zaútoÄili!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "%{monster} ohromeni sílou tvé armády zaÄali utíkat.\n" "ChceÅ¡ je pronásledovat a rozdrtit?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "Po vyplenÄ›ní nepřátelského tábora objevujeÅ¡ skrytou skrýš s poklady." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Správce mlýna oznámil:\n" "\"Pane, tvrdÄ› jsem pracoval na tom, abych vám zajistil tyto suroviny, vraÅ¥te " "se příští týden pro další.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Správce mlýna oznámil:\n" "\"Pane, omlouvám se, momentálnÄ› nejsou k dispozici žádné suroviny, vraÅ¥te se " "příští týden pro další.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Správce mlýna oznámil:\n" "\"Pane, tvrdÄ› jsem pracoval na tom, abych vám zajistil toto zlato, vraÅ¥te se " "příští týden pro další.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Správce mlýna oznámil:\n" "\"Pane, omlouvám se, momentálnÄ› není k dispozici žádné zlato, zkuste to " "prosím příští týden.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "NaÅ¡el jsi opuÅ¡tÄ›ný přístÅ™eÅ¡ek.\n" "PÅ™i prohledávání okolí objevíš poblíž schované suroviny." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "PřístÅ™eÅ¡ek je již dlouho opuÅ¡tÄ›n. Není zde nic hodnotného." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Chytil jsi skřítka, který bláhovÄ› spal uprostÅ™ed trsu kouzelných hub.\n" "VýmÄ›nou za svou svobodu tÄ› zavedl k malému hrnci naplnÄ›nému cennostmi." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "NaÅ¡el si kouzelnou zahradu, místo, kde se rádi prohánÄ›jí skřítci a víly, ale " "dnes tu nikdo není.\n" "Možná bys to mÄ›l zkusit příští týden." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Narazil jsi na ostatky nešťastného dobrodruha." msgid "Treasure" msgstr "Poklad" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "PÅ™i prohledávání roztrhaného obleÄení nalézáš %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "PÅ™i prohledávání roztrhaného obleÄení jsi nic nanaÅ¡el." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Naražíš na starý vůz po obchodníkovi, který to oÄividnÄ› nedotáhl až na " "bezpeÄný terén." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Bohužel, jiní ho asi naÅ¡li již dříve, vůz je zcela prázdný." msgid "Searching inside, you find the %{artifact}." msgstr "Prohledáváš uvnitÅ™ a nalézáš %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "UvnitÅ™ nalézáš Äást nákladu, který je stále neporuÅ¡ený." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Prohledal jsi trosky a naÅ¡el jsi trochu dÅ™eva a zlata." msgid "You search through the flotsam, and find some wood." msgstr "Prohledal jsi trosky a naÅ¡el trochu dÅ™eva." msgid "You search through the flotsam, but find nothing." msgstr "Prohledal jsi trosky ale nic jsi nenaÅ¡el." msgid "Shrine of the 1st Circle" msgstr "SvatynÄ› 1. úrovnÄ›" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Narazíš na malou svatyni, o kterou se stará skupina mladých uÄedníků.\n" "VýmÄ›nou za tvou ochranu souhlasí, že tÄ› nauÄí jednoduché kouzlo – '%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "SvatynÄ› 2. úrovnÄ›" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Narazíš na zdobenou svatyni, o kterou se stará skupina obtloustlých mnichů.\n" "VýmÄ›nou za tvou ochranu souhlasí, že tÄ› nauÄí kouzlo – '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "SvatynÄ› 3. úrovnÄ›" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Narazíš na honosnou svatyni, o kterou se stará skupina veleknÄ›zů.\n" "VýmÄ›nou za tvou ochranu souhlasí, že tÄ› nauÄí pokroÄilé kouzlo – '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Bohužel nemáš dostatek moudrosti, abys kouzlo pochopil, a nemůžeÅ¡ se ho " "nauÄit." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Bohužel toto kouzlo už znáš, takže tÄ› už nemají co nauÄit." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Bohužel nemáš knihu kouzel, do které bys mohl kouzlo zapsat." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Vstoupíš do chýše a vidíš uvnitÅ™ ÄarodÄ›jku, jak studuje starobylý svazek o " "%{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Když se k ní pÅ™iblížíš, otoÄí se a upÅ™e na tebe své jediné sklenÄ›né oko.\n" "\"Už víš vÅ¡echno, co si zasloužíš vÄ›dÄ›t!\" vyjekla ÄarodÄ›jka. \"A TEÄŽ " "VYPADNI Z MÉHO DOMU!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Když se k ní pÅ™iblížíš, otoÄí se a promluví.\n" "\"To, co bych tÄ› mohla nauÄit už umíš. Nemohu ti nijak pomoct.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Prastará a nesmrtelná ÄarodÄ›jnice žijící v chaloupce na ptaÄích nohách vás " "uÄí %{skill} pro své vlastní nepochopitelné cíle." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "Když se napijeÅ¡ sladké vody, získáš Å¡tÄ›stí pro svůj příští boj." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "NapijeÅ¡ se z kouzelné fontány, ale nic se nestane." msgid "You enter the faerie ring, but nothing happens." msgstr "Vstoupil jsti do Äarovného kruhu, ale nic se nestalo." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Po vstupu do Äarovného kruhu získává vaÅ¡e armáda Å¡tÄ›stí pro svou příští " "bitvu." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "NaÅ¡li jste starodávnou a vybledlou kamennou sochu.\n" "MÄ›la by návÅ¡tÄ›vníkům pÅ™inášet Å¡tÄ›stí, ale protože na vás už hvÄ›zdy usmívají, " "nedÄ›lá nic." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "NaÅ¡li jste starodávnou a vybledlou kamennou sochu.\n" "Polibek na ni by mÄ›l pÅ™inášet Å¡tÄ›stí, takže to udÄ›láte. Kámen je na dotek " "velmi studený." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "MoÅ™ské panny vás tiÅ¡e lákají, abyste se vrátili pozdÄ›ji a byli znovu " "požehnáni." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Magická, uklidňující krása moÅ™ských panen vás a vaÅ¡i posádku osloví.\n" "Na chvíli zapomenete na své starosti a vychutnáváte si krásu okamžiku.\n" "Kouzla moÅ™ských panen vás obdarují zvýšeným Å¡tÄ›stím pro váš příští boj." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Narazíte na pyramidu velkého a starobylého krále.\n" "Jste v pokuÅ¡ení prozkoumat ji za úÄelem nalezení pokladu, ale vÅ¡echny staré " "příbÄ›hy varují pÅ™ed dÄ›sivými kletbami a nemrtvými strážci.\n" "Budete prozkoumávat?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Po poražení monster rozluÅ¡títe starobylý symbol na zdi, který odhaluje " "tajemství kouzla -'" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Bohužel nemáte knihu kouzel, do které byste si mohli kouzlo zapsat." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Bohužel nemáte dovednost Moudrost na to, abyste kouzlo pochopili, a nemůžete " "se ho nauÄit." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Narazíte na pyramidu velkého a starobylého krále.\n" "Rutinní prozkoumání odhalí, že pyramida je zcela prázdná." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Napití ze studny by mÄ›lo obnovit vaÅ¡e magické body, ale už je máte na " "maximum." msgid "A second drink at the well in one day will not help you." msgstr "Druhý douÅ¡ek z této studny bÄ›hem jednoho dne ti již nepomůže." msgid "A drink from the well has restored your spell points to maximum." msgstr "DouÅ¡ek ze studny ti obnovil vÅ¡echny body magické energie na maximum." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Omlouvám se, pane,\" říká vůdce vojáků, \"ale už znáte vÅ¡e, co vás můžeme " "nauÄit.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "Vojáci žijící v pevnosti vás nauÄili nÄ›kolik nových obranných triků." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Narazili jste na tábor žoldáků, kteří trénují své taktiky. \"Jste pro nás " "příliÅ¡ pokroÄilí,\" říká kapitán žoldáků. \"Nemůžeme vás už nic víc nauÄit.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Narazili jste na tábor žoldáků, kteří trénují své taktiky. Žoldáci vás a " "vaÅ¡i armádu vítají a zvou vás, abyste se s nimi trénovali." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Jdi pryÄ!\", zavrÄí ÄarodÄ›j, \"už umíš vÅ¡echno, co já.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "ÄŒarodÄ›j žijící v chaloupce prohlubuje vaÅ¡e znalosti magie tím, že vám ukáže, " "jak sesílat kameny, Äíst znamení a deÅ¡ifrovat složitosti z kuÅ™ecích " "vnitÅ™ností." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Narazil jsi na skupinu druidů uctívajících jeden ze svých podivných " "kamenných monumentů. Druidové tÄ› mlÄky odmítnou a naznaÄí, že tÄ› už nemají " "co nového nauÄit." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Narazil jsi na skupinu druidů uctívajících jeden ze svých podivných " "kamenných monumentů. MlÄky tÄ› nauÄí nové způsoby, jak sesílat kouzla." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "OpatrnÄ› se blížíš k pohÅ™ebiÅ¡ti starovÄ›kých váleÄníků. ChceÅ¡ prohledat hroby?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Strávil jsi nÄ›kolik hodin prohledáváním hrobů, ale nic jsi nenaÅ¡el. Takový " "hanebný Äin snižuje morálku tvé armády." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "Po porážce Zombie prohledáváš hroby a nÄ›co jsi naÅ¡el!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Shnilý trup velké pirátské lodi straÅ¡idelnÄ› skřípe, když se tlaÄí na skály. " "Chcete prozkoumat vrak lodi?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Strávili jste nÄ›kolik hodin probíráním trosek, ale nic jste nenaÅ¡li. Takové " "ohavné jednání snižuje morálku vaší armády." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "Po poražení duchů procházíte troskami a nÄ›co nacházíte!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Shnilý trup velké pirátské lodi straÅ¡idelnÄ› skřípe, když se tlaÄí proti " "skalám. Chcete prozkoumat loÄ?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "Po poražení Kostlivců procházíte troskami a nÄ›co nacházíte!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "VaÅ¡i muži spatÅ™ili navigaÄní bóji, což potvrzuje, že jedete správným smÄ›rem." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "VaÅ¡i muži spatÅ™ili navigaÄní bóji, což potvrzuje, že jedete správným smÄ›rem " "a to zvyÅ¡uje jejich morálku." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "DouÅ¡ek v oáze je osvěžující, ale nepÅ™ináší žádné další výhody. Oáza by ti " "mohla znovu pomoci, pokud bys nejprve svedl bitvu." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "DouÅ¡ek v oáze naplní tvé jednotky silou a pozvedne jejich ducha. Dnes můžeÅ¡ " "cestovat o nÄ›co dál." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "DouÅ¡ek u napajedla je osvěžující, ale nepÅ™ináší žádné další výhody. " "Napajedlo by ti mohlo znovu pomoci, pokud bys nejprve svedl bitvu." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "DouÅ¡ek u napajedla naplní tvé jednotky silou a pozvedne jejich morálku. Dnes " "můžeÅ¡ cestovat o nÄ›co dál." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "Modlit se dvakrát pÅ™ed bitvou nepomáhá. VraÅ¥ se, až svedeÅ¡ bitvu." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "NávÅ¡tÄ›va a modlitba v chrámu pozvedne morálku tvých jednotek." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Na schodech altánu se objeví starý rytíř. \"Omlouvám se, můj pane, ale " "nauÄil jsem tÄ› vÅ¡e, co jsem mohl.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Na schodech altánu se objeví starý rytíř. \"Můj pane, nauÄím tÄ› vÅ¡e, co " "znám, aby ti to pomohlo na tvých cestách.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Zachránil jsi troseÄníka z potápÄ›jící se lodi pÅ™ed jistou smrtí v " "nemilosrdném oceánu. VdÄ›ÄnÄ› ti říká: \"Dal bych ti artefakt jako odmÄ›nu, ale " "už na nÄ›j nemáš místo.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Zachránil jsi troseÄníka z potápÄ›jící se lodi pÅ™ed jistou smrtí v " "nemilosrdném oceánu. VdÄ›ÄnÄ› tÄ› odmÄ›ní za tvůj Äin laskavosti a daruje ti " "%{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "Leprikón vám nabízí %{art} za %{gold} zlata." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "Skřítek vám nabízí %{art} za %{gold} zlata a %{count} %{res}." msgid "Do you wish to buy this artifact?" msgstr "PÅ™ejete si koupit tento artefakt?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Snažíte se zaplatit lepriónovi, ale uvÄ›domíte si, že si to nemůžete dovolit. " "Leprikón dupne nohou a ignoruje vás." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Uražený vaší odmítnutím jeho Å¡tÄ›dré nabídky, leprikón dupne nohou a ignoruje " "vás." msgid "You've found the artifact: " msgstr "NaÅ¡el jsi artefakt: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Objevil jsi skromné obydlí stárnoucího poustevníka. Poustevník ti sdÄ›lí, že " "%{art} pÅ™edá prvnímu moudrému ÄlovÄ›ku, na kterého narazí." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Narazil jsi na strohou komnatu vysloužilého vojáka. Voják ti sdÄ›lí, že je " "ochoten pÅ™edat %{art} prvnímu pravému vůdci, kterého potká." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Narazil jsi na podivného ÄlovÄ›ka s kloboukem, na kterém sedí sova. Říká ti, " "že je ochoten ti dát %{art}, pokud máš %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Narazil jsi na starovÄ›ký artefakt. Když se ho pokusíš vzít, ze kÅ™oví vyskoÄí " "skupina zlodÄ›jů, aby ochránili svůj ukradený lup." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Skrz mýtinu zahlédneÅ¡ starovÄ›ký artefakt. Bohužel ho hlídá nedaleko stojící " "%{monster}. ChceÅ¡ bojovat s %{monster} o artefakt?" msgid "Victorious, you take your prize, the %{art}." msgstr "VítÄ›znÄ› si bereÅ¡ svou odmÄ›nu, %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "Opatrnost je lepší Äástí odvahy, a tak se rozhodneÅ¡ tento boj pro dneÅ¡ek " "vynechat." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Po hodinách snahy vytáhnout truhlu z moÅ™e ji koneÄnÄ› otevÅ™eÅ¡ a najdeÅ¡ " "%{gold} zlata." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Po hodinách snahy vytáhnout truhlu z moÅ™e ji koneÄnÄ› otevÅ™eÅ¡ a najdeÅ¡ " "%{gold} zlata a %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Po hodinách snahy vytáhnout truhlu z moÅ™e ji koneÄnÄ› otevÅ™eÅ¡, jen abys " "zjistil, že je prázdná." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Po důkladném prozkoumání oblasti narazíš na skrytou pokladnici. MůžeÅ¡ si " "vzít zlato, nebo ho rozdat rolníkům a získat zkuÅ¡enosti. ChceÅ¡ si zlato " "nechat?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Po důkladném prozkoumání oblasti narazíš na skrytou truhlu, která obsahuje " "%{gold} zlata." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Po důkladném prozkoumání oblasti narazíš na skrytou truhlu, která obsahuje " "starovÄ›ký artefakt %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Narazíte na promáÄknutou a zrezivÄ›lou lampu zapadlou hluboko v zemi. PÅ™ejete " "si lampu otřít?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Získali jste kontrolu nad místní alchymistickou dílnou. Ta vám poskytne " "%{count} rtuti dennÄ›." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Získali jste kontrolu nad pilou. Ta vám poskytne %{count} kusy dÅ™eva dennÄ›." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Získali jste kontrolu nad kameným dolem. Ten vám poskytne %{count} kameny " "dennÄ›." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Získali jste kontrolu nad sirným dolem. Ten vám poskytne %{count} kus síry " "dennÄ›." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Získali jste kontrolu nad krystalovým dolem. Ten vám poskytne %{count} " "krystal dennÄ›." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Získali jste kontrolu nad drahokamovým dolem. Ten vám poskytne %{count} " "drahokam dennÄ›." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Získali jste kontrolu nad zlatým dolem. Ten vám poskytne %{count} zlata " "dennÄ›." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Maják je nyní pod vaší kontrolou a vÅ¡echny vaÅ¡e lodÄ› se nyní budou pohybovat " "dále každý den." msgid "You gain control of a %{name}." msgstr "Získali jste kontrolu nad %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Narazíte na opuÅ¡tÄ›ný zlatý důl. Důl vypadá jako by v nÄ›m straÅ¡ilo. PÅ™ejete " "si vstoupit?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Porazili jste duchy a obnovujete provoz v dolu." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Skupina %{monster} s touhou po vÄ›tší slávÄ› si pÅ™eje pÅ™ipojit se k vám. " "PÅ™ijmete je?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Když se pÅ™iblížíte k obydlí, vÅ¡imnete si, že zde nikdo není." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Prozkoumali jste ruiny, ale Medúzy, které zde dříve žily, jsou pryÄ. Možná " "se zde objeví příští týden." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "NaÅ¡li jste nÄ›kolik Medúz žijících v ruinách. Jsou ochotny se pÅ™ipojit k vaší " "armádÄ› za zlato. Chcete najmout Medúzy?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "NaÅ¡li jste Strom Skřítků. Bohužel žádný ze Skřítků, kteří zde žijí, si " "nepÅ™eje pÅ™ipojit se k armádÄ›. Možná příští týden." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "NÄ›kteří ze Skřítků žijících na stromÄ› jsou ochotni se pÅ™ipojit k vaší armádÄ› " "za zlato. Chcete najmout Skřítky?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Pestrobarevný vůz zlodÄ›jů zde stojí prázdný. Možná se sem zlodÄ›ji vrátí " "pozdÄ›ji." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Vzdálené zvuky hudby a smíchu tÄ› pÅ™ilákají k pestrobarevnému vozu, kde se " "ukrývají zlodÄ›ji. PÅ™ejeÅ¡ si, aby se nÄ›jací zlodÄ›ji pÅ™idali k tvé armádÄ›?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Skupina otrhaných stanů, které se tÅ™epotají v píseÄném vÄ›tru, tÄ› láká k " "sobÄ›. Stany jsou vÅ¡ak prázdné. Možná se sem koÄovníci vrátí pozdÄ›ji." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Skupina otrhaných stanů, které se tÅ™epotají v píseÄném vÄ›tru, tÄ› láká k " "sobÄ›. PÅ™ejeÅ¡ si, aby se k tobÄ› bÄ›hem tvých cest pÅ™ipojili nÄ›jací koÄovníci?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Jáma plná bahna chvíli bublá a pak se uklidní." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Když se pÅ™iblížíš k bublající jámÄ› bahna, zaÄnou z ní vylézat tvorové a " "rozmístí se kolem ní. JednohlasnÄ› pronesou: \"Matka ZemÄ› ti nabízí nÄ›kolik " "svých vojáků. ChceÅ¡ naverbovat zemské elementály?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Vstoupil jsi do stavby z bílých kamenných sloupů, ale nenacházíš nic." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Bílé kamenné sloupy podpírají stÅ™echu, která se tyÄí až k nebi. Když " "vstoupíš do stavby, mrtvý vzduch venku ustoupí vířícímu poryvu, který tÄ› " "málem vyžene zpÄ›t. VzduÅ¡ný proud nabývá téměř neviditelného tvaru. Tvor se " "zeptá hlasitým Å¡epotem: \"ProÄ jsi pÅ™iÅ¡el? Jsi zde, abys povolal síly " "vzduchu?" msgid "No Fire Elementals approach you from the lava pool." msgstr "Z lávového jezírka k nevycházejí žádní ohniví elementálové." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Pod stavbou, která slouží k udržení tepla, se ohniví elementálové pohybují v " "žhnoucím jezírku roztavené lávy. Skupina z nich k tobÄ› pÅ™istoupí a nabídne " "ti své služby. ChceÅ¡ naverbovat ohnivé elementály?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Na okamžik se ve vodÄ› vytvoří obliÄej, a pak zmizí." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Krystalické struktury vrhají stíny na malé jezírko. Když do nÄ›j nahlédneÅ¡, " "objeví se tvář, která není tvá. Zeptá se: \"ChceÅ¡ povolat síly vody?\"" msgid "This burial site is deathly still." msgstr "Toto pohÅ™ebiÅ¡tÄ› je dÄ›sivÄ› tiché." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Nepokojní duchové dávno mrtvých váleÄníků, kteří hledají své poslední místo " "odpoÄinku, ti nabízejí, že se k tobÄ› pÅ™idají v nadÄ›ji, že naleznou klid. " "ChceÅ¡ naverbovat duchy?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "MÄ›sto mrtvých je prázdné, bez života i nemrtvích. Možná se sem příští týden " "nastÄ›hují nÄ›jací nemrtví." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "NÄ›kteří Lichové, kteří zde žijí, jsou ochotni se za urÄitý obnos pÅ™idat k " "tvé armádÄ›. ChceÅ¡ naverbovat Lichy?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "NaÅ¡el jsi ruiny starovÄ›kého mÄ›sta, které nyní obývají pouze nemrtví. ChceÅ¡ " "je prohledat?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "NÄ›kteří z pÅ™eživších Lichů jsou ohromeni tvým vítÄ›zstvím nad jejich druhy a " "nabízejí ti, že se za urÄitý obnos pÅ™idají k tobÄ›. ChceÅ¡ naverbovat Lichy?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "NaÅ¡el jsi jeden z tÄ›ch mostů, pod kterými Trollové tak rádi žijí, ale žádní " "zde nejsou. Možná se tu objeví příští týden." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "NÄ›kteří Trollové, kteří žijí pod mostem, jsou ochotni se za urÄitý obnos " "pÅ™idat k tvé armádÄ›. ChceÅ¡ naverbovat Trolly?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Trollové žijící pod mostem tÄ› vyzývají na souboj. ChceÅ¡ s nimi bojovat?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "NÄ›kolik Trollů zůstalo, skrývajíce se pod mostem. PÅ™istoupí k tobÄ› a " "nabídnou, že se pÅ™idají k tvým silám jako žoldnéři. ChceÅ¡ si nÄ›jaké Trolly " "najmout?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "DraÄí mÄ›sto nemá tento týden žádné draky ochotné se k tobÄ› pÅ™idat. Možná " "bude nÄ›jaký drak dostupný příští týden." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "DraÄí mÄ›sto je ochotné nabídnout ti nÄ›kolik draků pro tvou armádu za urÄitý " "obnos. ChceÅ¡ naverbovat draky?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Stojíš pÅ™ed DraÄím mÄ›stem, místem, kam obyÄejným lidem není vstup povolen. " "ChceÅ¡ poruÅ¡it toto pravidlo a vyzvat draky k boji?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Po porážce draÄích Å¡ampionů souhlasí vůdci mÄ›sta, že ti za urÄitý obnos " "poskytnou nÄ›kolik draků do tvé armády. ChceÅ¡ naverbovat draky?" msgid "From the observation tower, you are able to see distant lands." msgstr "Z rohledny jsi prozkoumal okolí." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "Pramen se doplňuje pouze jednou týdnÄ› a nÄ›kdo už tu tento týden byl." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "DouÅ¡ek z pramene ti má zdvojnásobit magickou energii, ale už jsi na této " "úrovni." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "DouÅ¡ek z pramene plní tvou krev magií! Máš v rezervÄ› dvojnásobek svých " "obvyklých bodů magie." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Jakmile tÄ› komorník poznává, odmítá tÄ› vpustit. \"Mistr nepÅ™ijímá stejného " "studenta dvakrát.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Komorník tÄ› nakonec vpustí k pánovi domu. Ten tÄ› vycviÄí ve ÄtyÅ™ech " "dovednostech, které by mÄ›l každý hrdina ovládat." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Komorník otevÅ™e dveÅ™e a změří tÄ› pohledem. \"Nejsi ani slavný, ani diplomat, " "aby tÄ› můj pán pÅ™ijal\", poznamená s opovržením. ‚VraÅ¥ se, až uznáš, že jsi " "toho hoden." msgid " and " msgstr " a " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "VÅ¡ichni %{monsters}, které máš ve své armádÄ›, byli vycviÄeni bojovými mistry " "pevnosti. Tvoje armáda nyní obsahuje %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Neobvyklá aliance obrů, orkům a trpaslíků nabízí, že vycviÄí jakékoli takové " "vojáky, které k nim pÅ™ivedeÅ¡. Bohužel, žádné nemáš s sebou." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "VÅ¡ichni tvoji %{monsters} byli vylepÅ¡eni na %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Kovář pracující v kovárnÄ› nabízí, že pÅ™evede vÅ¡echny zbranÄ› kopiníků a " "Å¡ermířů, které mu pÅ™ivedeÅ¡, z železných na ocelové. Také říká, že zná " "proces, který pÅ™evede železné golemy na ocelové golemny. Bohužel, žádné z " "tÄ›chto vojáků nemáš ve své armádÄ›, takže ti nemůže pomoci." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Kapitán se na tebe s pÅ™ekvapením podívá a říká:\n" "\"Už máš vÅ¡echny mapy, o kterých vím. Nech mÄ› teÄ rybaÅ™it v klidu.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Vysloužilý kapitán, který žije na této zrenovované rybářské ploÅ¡inÄ›, ti " "nabízí mapy moÅ™e, které vytvoÅ™il za svých mladších let, za 1000 zlata. ChceÅ¡ " "tyto mapy koupit?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Kapitán si povzdechne. \"Nemáš dostatek penÄ›z, co? NemůžeÅ¡ oÄekávat, že ti " "své mapy dám zadarmo!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Narazil jsi na obelisk vyrobený z kamene, který jsi nikdy pÅ™edtím nevidÄ›l. " "Když se na nÄ›j intenzivnÄ› díváš, hladký povrch se náhle zmÄ›ní na nápis. " "Nápis je Äást ztracené starovÄ›ké mapy. Rychle si kus okopírujeÅ¡ a nápis " "zmizí tak náhle, jak se objevil." msgid "You have already been to this obelisk." msgstr "Tento obelisk jsi už navÅ¡tívil." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Když se pÅ™iblížíte, strom otevÅ™e své oÄi s radostí. \"Je dobré tÄ› vidÄ›t, můj " "žáku. Doufám, že ti moje uÄení pomohla.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Když se pÅ™iblížíte, strom otevÅ™e své oÄi s radostí. \"Ahh, dobrodruhu! " "Dovolte mi, abych vás nauÄil trochu z toho, co jsem se nauÄil bÄ›hem vÄ›ků.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Když se pÅ™iblížíte, strom otevÅ™e své oÄi s radostí." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ahh, dobrodruhu! Rád tÄ› nauÄím trochu z toho, co jsem se nauÄil bÄ›hem " "vÄ›ků, za pouhých %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(JednoduÅ¡e to zakopej k mým koÅ™enům.)" msgid "Tears brim in the eyes of the tree." msgstr "Slzy se mu hrnou do oÄí." msgid "\"I need %{count} %{res}.\"" msgstr "\"PotÅ™ebuji %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "Å¡eptá. (pššt) \"Nuže, vraÅ¥te se, až mi budete moci zaplatit.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "UprostÅ™ed stromů sedí slepý věštec. Poté, co mu vysvÄ›tlíte zámÄ›r své cesty, " "věštec aktivuje svou kÅ™išťálovou kouli, což vám umožní vidÄ›t síly a slabosti " "vaÅ¡ich protivníků." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Vchod do jeskynÄ› je tmavý a z ústí jeskynÄ› se line odporný zápach síry. " "Vstoupíte?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "KromÄ› důkazů o hrozné bitvÄ› je jeskynÄ› prázdná." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "V jeskyni narazíte na mocného a groteskního Démona. \"Dnes,\" huhlá, " "\"budete bojovat a jistÄ› zemÅ™ete. Ale dám vám na výbÄ›r, jak zemÅ™ete. Můžete " "bojovat se mnou, nebo se můžete utkat s mými služebníky. Preferujete boj s " "mými služebníky?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Démon dodrží své výzvy a zaútoÄí! Po krátkém a zoufalém boji zabijete " "monstra a získáte %{exp} zkuÅ¡eností." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Démon dodrží své výzvy a zaútoÄí! Po krátkém a zoufalém boji zabijete " "monstra a získáte %{exp} zkuÅ¡eností a %{count} zlata." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Démon dodrží své výzvy a zaútoÄí! Po krátkém a zoufalém boji zabijete " "monstra a v zadní Äásti jeskynÄ› naleznete %{art}." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Když vidí, že nemáte %{count} zlata, démon vás Å¡krábne svými drápy a " "poslední vÄ›c, kterou vidíte, je Äervená mlha." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Démon na vás skoÄí a dříve, než staÄíte vytáhnout meÄ, má své drápy na vaÅ¡em " "hrdle. \"Tvůj život je můj,\" říká. \"Prodám ti ho zpÄ›t za %{count} zlata.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Po poražení démonových služebníků naleznete skrytý úkryt, který obsahuje " "%{count} zlata." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Když vstoupíte do Alchymistovy věže, pÅ™ibližuje se k vám kulhavý, Å¡edivý muž " "v hnÄ›dém plášti." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Zkontroluje váš batoh a zjistí, že máte 1 prokletý pÅ™edmÄ›t." msgstr[1] "" "Zkontroluje váš batoh a zjistí, že máte %{count} prokletých pÅ™edmÄ›tů." msgstr[2] "" "Zkontroluje váš batoh a zjistí, že máte %{count} prokletých pÅ™edmÄ›tů." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "Za %{gold} zlata vás alchymista prokletého pÅ™edmÄ›tu zbaví. Zaplatíte?" msgstr[1] "" "Za %{gold} zlata vás alchymista prokletých pÅ™edmÄ›tů zbaví. Zaplatíte?" msgstr[2] "" "Za %{gold} zlata vás alchymista prokletých pÅ™edmÄ›tů zbaví. Zaplatíte?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Poté, co souhlasíte s zaplacením požadované Äástky zlata, alchymista uchopí " "prokletý artefakt a hodí ho do svého kouzelného kotle." msgstr[1] "" "Poté, co souhlasíte s zaplacením požadované Äástky zlata, alchymista uchopí " "prokleté artefakty a hodí ho do svého kouzelného kotle." msgstr[2] "" "Poté, co souhlasíte s zaplacením požadované Äástky zlata, alchymista uchopí " "prokleté artefakty a hodí ho do svého kouzelného kotle." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Zpoza zamÄených dveří slyšíte hlas: \"Nemáte dost zlata na zaplacení mých " "služeb.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "Z věži slyšíte hlas: \"Jdi pryÄ! Nemohu ti pomoci!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Hlavní oÅ¡etÅ™ovatel vám říká: \"To je pÄ›kný kůň, kterého máte. Obávám se, že " "vám nemůžeme nabídnout lepší, ale konÄ›, na kterých jezdí vaÅ¡e jezdecké " "jednotky, vypadají jako Å¡patnÄ› chované. Máme mnoho vycviÄených váleÄných " "koní, kteří by velmi pomohli vaÅ¡im jezdcům. Trvám na tom, abyste si je vzali." "\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Když se pÅ™iblížíte ke stáji, hlavní oÅ¡etÅ™ovatel se objeví a vede pÄ›kného " "váleÄného konÄ›. \"Tento kůň vám pomůže urychlit vaÅ¡e cesty. Ach, za týden se " "unaví. Také mi dovolte, abych dal lepší konÄ› vaÅ¡im jezdeckým vojákům, jejich " "konÄ› vypadají podÄ›lanÄ› a slabÄ›.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Hlavní oÅ¡etÅ™ovatel k vám pÅ™istupuje a říká: \"Již máte pÄ›kného konÄ› a nemáte " "žádné nezkuÅ¡ené jezdecké jednotky, které by mohly využít naÅ¡e vycviÄené " "váleÄné konÄ›.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Když se pÅ™iblížíte ke stáji, hlavní oÅ¡etÅ™ovatel se objeví a vede pÄ›kného " "váleÄného konÄ›. \"Tento kůň vám pomůže urychlit vaÅ¡e cesty. Bohužel, jeho " "vytrvalost slábne pÅ™i velkém zatížení a musíte se vrátit pro Äerstvého konÄ› " "za týden. Také máme mnoho kvalitních váleÄných koní, které by mohly prospÄ›t " "jezdeckým vojákům, ale žádné nemáte, s nimiž bychom mohli pomoci." msgid "The Arena guards turn you away." msgstr "Stráže arény vás odvádí pryÄ." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Dáváte své posádce vosk, aby si jím ucpal uÅ¡i, než bude mít sirénina podivná " "píseň Å¡anci je vylákat do vodní hrobky." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Když sirény zpívají svou podivnou píseň, vaÅ¡e malá, odhodlaná armáda se " "dokáže pÅ™emoci a nepodlehne touze vrhnout se do moÅ™e." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Z podivného zpÄ›vu sirén sedících na skalách vám pÅ™ebÄ›hne mráz po zádech. " "Mnozí z vaší posádky propadnou jejich kouzlu a skoÄí do vody, kde se utopí. " "Po této zkuÅ¡enosti jste nyní moudÅ™ejší a získáváte %{exp} zkuÅ¡eností." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Ve fascinujícím projevu odvahy se vloupáte do místního vÄ›zení a osvobodíte " "hrdinu, který je tam uvÄ›znÄ›n. Ten vám na oplátku slibuje loajalitu." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Již máte %{count} hrdinů, a s lítostí musíte nechat vÄ›znÄ› v tomto vÄ›zení " "trpÄ›t v agonii po zbytek jeho dní." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Vstoupíte do rozpadlé chatrÄe a promluvíte s mágem, který zde žije. Ten vám " "poví o místech blízkých i dalekých, která vám mohou pomoci na vaÅ¡ich cestách." msgid "This eye seems to be intently studying its surroundings." msgstr "Toto oko se zdá být soustÅ™edÄ›nÄ› a zkoumá své okolí." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Narazíte na obrovskou Sfingu. Sfinga zůstává podivnÄ› tiÅ¡e." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Mám pro tebe hádanku,\" říká Sfinga. \"OdpovÄ›z správnÄ› a budeÅ¡ odmÄ›nÄ›n. " "OdpovÄ›z Å¡patnÄ› a budeÅ¡ snÄ›den. PÅ™ijímáš výzvu?\"" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Sfinga vám pokládá následující hádanku:\n" "\n" "'" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" "'\n" "\n" "VaÅ¡e odpovÄ›Ä?" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"OdpovÄ›dÄ›l jsi Å¡patnÄ›,\" říká Sfinga s úsmÄ›vem. Sfinga tÄ› Å¡vihne tlapou, " "což tÄ› srazí na zem. Další úder pÅ™ivede svÄ›t k ÄernotÄ› a ty už nic nevnímáš." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Sfinga vypadá ponÄ›kud zklamanÄ› a vzdychá. \"OdpovÄ›dÄ›l jsi na moji hádanku, " "takže tady je tvoje odmÄ›na. Nyní zmizni.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "PÅ™ed vámi se tyÄí magická bariéra, která vám blokuje cestu. Runy na oblouku " "praví:\n" "\"Vyslovte heslo a můžete projít.\"\n" "Jakmile vyslovíte magické slovo, zářící bariéra se rozplyne." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "PÅ™ed vámi se tyÄí magická bariéra, která vám blokuje cestu. Runy na oblouku " "praví:\n" "\"Vyslovte heslo a můžete projít.\"\n" "Vyslovíte magické slovo, ale nic se nestane." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Vstoupíte do stanu a uvidíte starou ženu, jak se dívá do magického krystalu. " "Zvedne hlavu a říká: \"Na svých cestách jsem se mnoho nauÄila v oblasti " "tajemné magie. Mám odpovÄ›Ä, kterou hledáš.\"" msgid "No spell book is present." msgstr "Nemáš Knihu kouzel, bez ní nemůžeÅ¡ kouzlit." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Toto kouzlo stojí %{mana} magických bodů. Nemáte žádné magické body, takže " "ho nemůžete seslat." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Toto kouzlo stojí %{mana} magických bodů. Máte pouze %{point} magických " "bodů, takže ho nemůžete seslat." msgid "The spell was not found." msgstr "Kouzlo nenalezeno." msgid "Only heroes can cast this spell." msgstr "Toto kouzlo mohou sesílat pouze hrdinové." msgid "This hero is not able to cast adventure spells." msgstr "Tento hrdina nemůže sesílat kouzla." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Tvůj hrdina je příliÅ¡ unavený na to, aby dnes toto kouzlo seslal. Zkuste to " "znovu zítra." msgid "This spell cannot be cast on a boat." msgstr "Toto kouzlo nelze seslat na lodi." msgid "This spell can only be cast near an ocean." msgstr "Toto kouzlo lze seslat pouze v blízkosti oceánu." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Nejsou k dispozici žádné lodÄ› a v blízkosti hrdiny není žádný oceán, kde by " "toto kouzlo fungovalo." msgid "There are no boats available for this spell." msgstr "Pro toto kouzlo nejsou k dispozici žádné lodÄ›." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "V blízkosti hrdiny není žádný oceán, kde by toto kouzlo fungovalo." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Nevlastníte žádné mÄ›sto ani hrad, který by aktuálnÄ› nebyl obsazen hrdinou. " "Toto kouzlo nebude mít žádný úÄinek." msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Tento hrdina se již nachází ve mÄ›stÄ›, takže toto kouzlo nebude mít žádný " "úÄinek." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Nejbližší mÄ›sto je %{town}.\n" "\n" "Toto mÄ›sto obývá tvůj hrdina %{hero}." msgid "This spell is already in effect." msgstr "Toto kouzlo už úÄinkuje." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Žádný protivník už nemá ani nemůže mít žádného hrdinu pod svým velením. " "Vyvolání tohoto kouzla nebude mít žádný úÄinek." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Žádný protivník v tuto chvíli nemá pod svým velením hrdinu. Vyvolání tohoto " "kouzla nebude mít žádný úÄinek." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Musíš být v okruhu %{count} polí od jednotky, aby kouzlo Vize fungovalo." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Musíš stát na vchodu do dolu (pily a alchymistické laboratoÅ™e se " "nepoÄítají), aby bylo možné toto kouzlo vyvolat." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Nejprve musíš porazit duchy, kteří stráží důl, aby bylo možné toto kouzlo " "vyvolat." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "U dolu už stráží alespoň tolik elementálů, kolik tento hrdina může vytvoÅ™it. " "Vyvolání tohoto kouzla nebude mít žádný úÄinek." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name}, %{race} (Úroveň %{level})" msgid "Random hero (Level %{level})" msgstr "Náhodný hrdina (Úroveň %{level})" msgid "Random %{race} hero (Level %{level})" msgstr "Náhodný hrdina %{race} (Úroveň %{level})" msgid "Hero race:" msgstr "Rasa hrdiny:" msgid "Are you sure you want to dismiss this Hero?" msgstr "Opravdu chceÅ¡ propustit tohoto hrdinu?" msgid "Set custom Experience value. Current value is default." msgstr "Nastavte vlastní hodnotu zkuÅ¡eností. Aktuální hodnota je výchozí." msgid "Change Experience value. Right-click to reset to default value." msgstr "" "Změňte hodnotu zkuÅ¡eností. KliknÄ›te pravým tlaÄítkem pro obnovení na výchozí " "hodnotu." msgid "View Experience Info" msgstr "Zobrazit informace o zkuÅ¡enostech" msgid "Set custom Spell Points value. Current value is default." msgstr "Nastavte vlastní hodnotu bodů magie. Aktuální hodnota je výchozí." msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" "Změňte hodnotu bodů magie. KliknÄ›te pravým tlaÄítkem pro obnovení na výchozí " "hodnotu." msgid "Set Spell Points value" msgstr "Nastavte hodnotu bodů magie" msgid "View Spell Points Info" msgstr "Zobrazit informace o bodech magie" msgid "Set patrol radius in tiles" msgstr "Nastavte hlídkový rádius v polích" msgid "Enter hero's name" msgstr "Zadejte jméno hrdiny" msgid "Click to change race." msgstr "Klikni pro zmÄ›nu rasy." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Volná' bojová formace roztáhne tvoje jednotky shora až dolů po celém " "bojiÅ¡ti, s minimálnÄ› jedním volným polem mezi jednotkami." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "'TÄ›sná' bojová formace srazí tvoje jednotky do stÅ™edu bojiÅ¡tÄ› na tvé stranÄ› " "bojiÅ¡tÄ›." msgid "Exit Hero Screen" msgstr "Odejít z obrazovky hrdiny" msgid "You cannot dismiss a hero in a castle" msgstr "Nemůžete propustit hrdinu v hradu" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "PropuÅ¡tÄ›ní %{name} hrdiny %{race} je zakázáno scénářem" msgid "Dismiss %{name} the %{race}" msgstr "Propustit %{name} hrdinu %{race}" msgid "Show previous hero" msgstr "Zobrazit pÅ™edchozího hrdinu" msgid "Show next hero" msgstr "Zobrazit následujícího hrdinu" msgid "Set army combat formation to 'Spread'" msgstr "Nastavit bojovou formaci armády na 'Volná'" msgid "Set army combat formation to 'Grouped'" msgstr "Nastavit bojovou formaci armády na 'TÄ›snou'" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" "Nastavte artefakty hrdiny. KliknÄ›te pravým tlaÄítkem pro obnovení artefaktu." msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" "Nastavte sekundární dovednosti hrdiny. KliknÄ›te pravým tlaÄítkem pro " "obnovení dovednosti." msgid "Set hero's Army. Right-click to reset unit." msgstr "" "Nastavte armádu hrdiny. KliknÄ›te pravým tlaÄítkem pro obnovení jednotky." msgid "Set hero's portrait. Right-click to reset to default." msgstr "" "Nastavte portrét hrdiny. KliknÄ›te pravým tlaÄítkem pro obnovení na výchozí " "hodnotu." msgid "Click to change hero's name. Right-click to reset to default." msgstr "" "KliknÄ›te pro zmÄ›nu jména hrdiny. KliknÄ›te pravým tlaÄítkem pro obnovení na " "výchozí hodnotu." msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" "Hrdina je v režimu hlídkování v okruhu %{tiles} polí. KliknÄ›te pro jeho " "deaktivaci." msgid "Click to enable hero's patrol mode." msgstr "KliknÄ›te pro povolení režimu hlídkování hrdiny." msgid "Blood Morale" msgstr "Krevní morálka" msgid "%{morale} Morale" msgstr "%{morale} Morálky" msgid "%{luck} Luck" msgstr "%{luck} Å tÄ›stí" msgid "Current Luck Modifiers:" msgstr "Å tÄ›stí ovlivňují:" msgid "Current Morale Modifiers:" msgstr "Morálku ovlivňují:" msgid "Entire army is undead, so morale does not apply." msgstr "Celá armáda je nemrtvá, morálka se nevztahuje." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Aktuální zkuÅ¡enosti %{exp1}.\n" " Další úroveň %{exp2}." msgid "million|M" msgstr "M" msgid "Level %{level}" msgstr "Úroveň %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} má aktuálnÄ› %{point} magických bodů z maximálních %{max}. Maximální " "poÄet magických bodů je 10krát vÄ›tší než hrdinovi znalosti. NÄ›kdy je možné, " "aby hrdina mÄ›l více než maximální poÄet magických bodů díky speciálním " "událostem." msgid "%{name1} meets %{name2}" msgstr "%{name1} se setkává s %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "NepřátelÅ¡tí hrdinové jsou nyní plnÄ› identifikovatelní." msgid "Identify Hero" msgstr "Identifikuj hrdinu" msgid "Select town to port to." msgstr "Vyber cílové mÄ›sto." msgid "Town Portal" msgstr "MÄ›stská brána" msgid "The creatures are willing to join us!" msgstr "Jednotky jsou ochotny se k nám pÅ™ipojit!" msgid "All the creatures will join us..." msgstr "VÅ¡echny jednotky se k nám pÅ™ipojí..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Jednotka se k nám pÅ™ipojí..." msgstr[1] "%{count} jednotek se k nám pÅ™ipojí..." msgstr[2] "%{count} jednotek se k nám pÅ™ipojí..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "za poplatek ve výši %{gold} zlata." msgid "These weak creatures will surely flee before us." msgstr "Tyto slabé jednotky pÅ™ed námi jistÄ› uprchnou." msgid "I fear these creatures are in the mood for a fight." msgstr "Obávám se, že tyto jednotky mají náladu na boj." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Dovednost útoku hrdiny je bonus, který se pÅ™idává k dovednosti útoku každé " "jednotky." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Dovednost obrany hrdiny je bonus, který se pÅ™idává k dovednosti obrany každé " "jednotky." msgid "The hero's spell power determines the duration or power of a spell." msgstr "Síla kouzel hrdiny urÄuje trvání nebo sílu kouzla." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Znalosti hrdiny urÄují, kolik magických bodů může hrdina mít. Za normálních " "okolností je hrdina omezen na 10 magických bodů za každou úroveň znalostí." msgid "Current Modifiers:" msgstr "Aktuální modifikátory:" msgid "skill|Basic" msgstr "Základní" msgid "skill|Advanced" msgstr "PokroÄilá" msgid "skill|Expert" msgstr "Expert" msgid "Pathfinding" msgstr "Hledání cest" msgid "Archery" msgstr "LukostÅ™elba" msgid "Logistics" msgstr "Logistika" msgid "Scouting" msgstr "Průzkumník" msgid "Diplomacy" msgstr "Diplomacie" msgid "Navigation" msgstr "Navigace" msgid "Leadership" msgstr "Vedení" msgid "Wisdom" msgstr "Moudrost" msgid "Mysticism" msgstr "Mystika" msgid "Ballistics" msgstr "Balistika" msgid "Eagle Eye" msgstr "Orlí Oko" msgid "Necromancy" msgstr "Nekromancie" msgid "Estates" msgstr "HospodaÅ™ení" msgid "Advanced Archery" msgstr "PokroÄilá LukostÅ™elba" msgid "Advanced Pathfinding" msgstr "PokroÄilé Hledání cest" msgid "Basic Archery" msgstr "Základní LukostÅ™elba" msgid "Basic Pathfinding" msgstr "Základní Hledání cest" msgid "Expert Pathfinding" msgstr "Expertní Hledání cest" msgid "Advanced Logistics" msgstr "PokroÄilá Logistika" msgid "Basic Logistics" msgstr "Základní Logistika" msgid "Basic Scouting" msgstr "Základní Průzkumník" msgid "Expert Archery" msgstr "Expertní LukostÅ™elba" msgid "Expert Logistics" msgstr "Expertní Logistika" msgid "Advanced Diplomacy" msgstr "PokroÄilá Diplomacie" msgid "Advanced Scouting" msgstr "PokroÄilý Průzkumník" msgid "Basic Diplomacy" msgstr "Základní Diplomacie" msgid "Expert Diplomacy" msgstr "Expertní Diplomacie" msgid "Expert Scouting" msgstr "Expertní Průzkumník" msgid "Advanced Leadership" msgstr "PokroÄilé Vedení" msgid "Advanced Navigation" msgstr "PokroÄilá Navigace" msgid "Basic Leadership" msgstr "Základní Vedení" msgid "Basic Navigation" msgstr "Základní Navigace" msgid "Expert Navigation" msgstr "Expertní Navigace" msgid "Advanced Wisdom" msgstr "PokroÄilá Moudrost" msgid "Basic Mysticism" msgstr "Základní Mystika" msgid "Basic Wisdom" msgstr "Základní Moudrost" msgid "Expert Leadership" msgstr "Expertní Vedení" msgid "Expert Wisdom" msgstr "Expertní Moudrost" msgid "Advanced Luck" msgstr "PokroÄilé Å tÄ›stí" msgid "Advanced Mysticism" msgstr "PokroÄilá Mystika" msgid "Basic Luck" msgstr "Základní Å tÄ›stí" msgid "Expert Luck" msgstr "Expertní Å tÄ›stí" msgid "Expert Mysticism" msgstr "Expertní Mystika" msgid "Advanced Ballistics" msgstr "PokroÄilá Balistika" msgid "Advanced Eagle Eye" msgstr "PokroÄilé Orlí Oko" msgid "Basic Ballistics" msgstr "Základní Balistika" msgid "Basic Eagle Eye" msgstr "Základní Orlí Oko" msgid "Expert Ballistics" msgstr "Expertní Balistika" msgid "Advanced Necromancy" msgstr "PokroÄilá Nekromancie" msgid "Basic Estates" msgstr "Základní HospodaÅ™ení" msgid "Basic Necromancy" msgstr "Základní Nekromancie" msgid "Expert Eagle Eye" msgstr "Expertní Orlí Oko" msgid "Expert Necromancy" msgstr "Expertní Nekromantie" msgid "Advanced Estates" msgstr "PokroÄilé HospodaÅ™ení" msgid "Expert Estates" msgstr "Expertní HospodaÅ™ení" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "%{skill} snižuje zpomalení na nerovném terénu o %{count} procent." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} kompletnÄ› ruší zpomalení na nerovném terénu." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} zvyÅ¡uje poÅ¡kození způsobené hrdinovými jednotkami s útokem na dálku " "o %{count} procent a eliminuje %{penalty} procentní postih pÅ™i střílení pÅ™es " "pÅ™ekážky (napÅ™. hradby)." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} zvyÅ¡uje body pohybu hrdiny o %{count} procent." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} rozÅ¡iÅ™uje viditelnou oblast kolem hrdiny o jedno pole." msgstr[1] "" "%{skill} rozÅ¡iÅ™uje viditelnou oblast kolem hrdiny o %{count} Ätverce." msgstr[2] "%{skill} rozÅ¡iÅ™uje viditelnou oblast kolem hrdiny o %{count} polí." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} umožňuje vyjednávat s jednotkami, které jsou slabší než tvoje " "armáda." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "PÅ™ibližnÄ› %{count} procent ze stvoÅ™ení ti může nabídnout, že se pÅ™idají." msgid "All of the creatures may offer to join the hero." msgstr "VÅ¡echna stvoÅ™ení ti můžou nabídnout, že se pÅ™idají." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "Cena za kapitulaci je snížena na %{percent} procent celkových nákladů na " "jednotky v armádÄ›." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "%{skill} zvyÅ¡uje body pohybu hrdiny na vodÄ› o %{count} procent." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} zvyÅ¡uje morálku u jednotek hrdiny o %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} umožnuje hrdinovi nauÄit se kouzla 3. úrovnÄ›." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} umožnuje hrdinovi nauÄit se kouzla 4. úrovnÄ›." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} umožnuje hrdinovi nauÄit se kouzla 5. úrovnÄ›." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} obnovuje jeden bod magické energie dennÄ›." msgstr[1] "%{skill} regeneruje %{count} body magické energie za den." msgstr[2] "%{skill} obnovuje %{count} bodů magické energie dennÄ›." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} zvyÅ¡uje Å¡tÄ›stí hrdiny o %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} dává katapultu vÄ›tší Å¡anci na zásah a způsobení poÅ¡kození hradbám." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} dává hrdinovÄ› katapultu extra stÅ™elu a každá stÅ™ela má vÄ›tší Å¡anci " "na zásah a způsobení poÅ¡kození hradbám." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} dává hrdinovÄ› katapultu extra stÅ™elu, a každá stÅ™ela automaticky " "zniÄí jakoukoli zeÄ, kromÄ› zpevnÄ›né zdi v hradu rytířů." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} dává hrdinovi %{count} procentní Å¡anci nauÄit se jakékoliv kouzlo " "1. nebo 2. úrovnÄ›, které protivník použil v boji." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} dává hrdinovi %{count} procentní Å¡anci nauÄit se jakékoliv kouzlo " "3. (nebo nižší) úrovnÄ›, které protivník použil v boji." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} dává hrdinovi %{count} procentní Å¡anci nauÄit se jakékoliv kouzlo " "4. (nebo nižší) úrovnÄ›, které protivník použil v boji." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} umožnuje aby %{count} procent jednotek padlých v boji mohlo být " "vzkříšeno jako Kostlivci." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "Hrdina dennÄ› produkuje %{count} zlata jako daňové příjmy z panství." msgid "Blue" msgstr "Modrý" msgid "Green" msgstr "Zelený" msgid "Red" msgstr "ÄŒervený" msgid "Yellow" msgstr "Žlutý" msgid "Orange" msgstr "Oranžový" msgid "Purple" msgstr "Fialový" msgid "barrier|Aqua" msgstr "Tyrkysová" msgid "barrier|Blue" msgstr "Modrá" msgid "barrier|Brown" msgstr "HnÄ›dá" msgid "barrier|Gold" msgstr "Zlatá" msgid "barrier|Green" msgstr "Zelená" msgid "barrier|Orange" msgstr "Oranžová" msgid "barrier|Purple" msgstr "Fialová" msgid "barrier|Red" msgstr "ÄŒervená" msgid "tent|Aqua" msgstr "Tyrkysový" msgid "tent|Blue" msgstr "Modrý" msgid "tent|Brown" msgstr "HnÄ›dý" msgid "tent|Gold" msgstr "Zlatý" msgid "tent|Green" msgstr "Zelený" msgid "tent|Orange" msgstr "Oranžový" msgid "tent|Purple" msgstr "Fialový" msgid "tent|Red" msgstr "ÄŒervený" msgid "Experience" msgstr "ZkuÅ¡enosti" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "ZkuÅ¡enosti umožňují vaÅ¡im hrdinům získávat úrovnÄ›, Äímž se zvyÅ¡ují jejich " "primární a sekundární dovednosti." msgid "Hero/Stats" msgstr "Hrdina/Statistika" msgid "Skills" msgstr "Znalosti" msgid "Town/Castle" msgstr "MÄ›sto/Hrad" msgid "Garrison" msgstr "Posádka" msgid "Gold Per Day:" msgstr "Zlata za den:" msgid "View Heroes." msgstr "Zobraz Hrdiny." msgid "Towns/Castles" msgstr "MÄ›sta/Hrady" msgid "View Towns and Castles." msgstr "Zobraz MÄ›sta a Hrady." msgid "luck|Cursed" msgstr "Prokletí" msgid "luck|Awful" msgstr "Hrozné" msgid "luck|Bad" msgstr "Zlé" msgid "luck|Normal" msgstr "Normální" msgid "luck|Good" msgstr "Dobré" msgid "luck|Great" msgstr "SkvÄ›lé" msgid "luck|Irish" msgstr "Irské" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Nízké Å¡tÄ›stí obÄas dolehne na tvoje jednotky v bitvÄ› a zapříÄíní, že jejich " "útok způsobí pouze poloviÄní Å¡kody." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Neutrální Å¡tÄ›stí znamená, že tvoje jednotky nikdy nezasadí nepříteli Å¡tastný " "ale ani ménÄ› povedený úder." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Vysoké Å¡tÄ›stí obÄas způsobí šťastný úder tvých jednotek (dvojitou silou) v " "bitvÄ›." msgid "morale|Treason" msgstr "Zrada" msgid "morale|Awful" msgstr "Hrozná" msgid "morale|Poor" msgstr "Nízká" msgid "morale|Normal" msgstr "Normální" msgid "morale|Good" msgstr "Dobrá" msgid "morale|Great" msgstr "SkvÄ›lá" msgid "morale|Blood!" msgstr "Krev!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Zlá morálka může způsobit, že tvé jednotky v bitvÄ› ztuhnou." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Neutrální morálka znamená, že tvé jednotky neboudou obdaÅ™ené útokem navíc " "ale ani v boji neztuhnou." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Dobrá morálka může dát tvým jednotkám jeden útok navíc." msgid "Knight" msgstr "Rytíř" msgid "Barbarian" msgstr "Barbar" msgid "Sorceress" msgstr "Kouzelnice" msgid "Warlock" msgstr "ÄŒarodÄ›j" msgid "Wizard" msgstr "Mág" msgid "Necromancer" msgstr "Nekromant" msgid "Multi" msgstr "Více" msgid "doubleLined|Knight" msgstr "Rytíř" msgid "doubleLined|Barbarian" msgstr "Barbar" msgid "doubleLined|Sorceress" msgstr "Kouzelnice" msgid "doubleLined|Warlock" msgstr "ÄŒarodÄ›j" msgid "doubleLined|Wizard" msgstr "Mág" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "Nekromant" msgid "doubleLinedRace|Multi" msgstr "Více" msgid "doubleLinedRace|Random" msgstr "NáhodnÄ›" msgid "speed|Standing" msgstr "Stojící" msgid "speed|Crawling" msgstr "Plazící" msgid "speed|Very Slow" msgstr "Vel. pomalý" msgid "speed|Slow" msgstr "Pomalý" msgid "speed|Average" msgstr "PrůmÄ›r" msgid "speed|Fast" msgstr "Rychlý" msgid "speed|Very Fast" msgstr "Vel. rychlý" msgid "speed|Ultra Fast" msgstr "Ult. rychlý" msgid "speed|Blazing" msgstr "Rychlá" msgid "speed|Instant" msgstr "Okamžitá" msgid "Click this button to adjust the level of zoom." msgstr "KliknÄ›te na toto tlaÄítko pro úpravu úrovnÄ› pÅ™iblížení." msgid "Zoom" msgstr "PÅ™iblížení" msgid "week|Squirrel" msgstr "Veverky" msgid "week|Rabbit" msgstr "Králíka" msgid "week|Gopher" msgstr "Pískomila" msgid "week|Badger" msgstr "Jezevce" msgid "week|Rat" msgstr "Krysy" msgid "week|Eagle" msgstr "Orla" msgid "week|Weasel" msgstr "TchoÅ™e" msgid "week|Raven" msgstr "Havrana" msgid "week|Mongoose" msgstr "Mangusty" msgid "week|Dog" msgstr "Psa" msgid "week|Aardvark" msgstr "MraveneÄníka" msgid "week|Lizard" msgstr "JeÅ¡tÄ›ra" msgid "week|Tortoise" msgstr "Želvy" msgid "week|Hedgehog" msgstr "Ježk" msgid "week|Condor" msgstr "Kondora" msgid "week|Ant" msgstr "Mravence" msgid "week|Grasshopper" msgstr "Kobylky" msgid "week|Dragonfly" msgstr "Vážky" msgid "week|Spider" msgstr "Pavouka" msgid "week|Butterfly" msgstr "Motýla" msgid "week|Bumblebee" msgstr "ÄŒmeláka" msgid "week|Locust" msgstr "SaranÄete" msgid "week|Earthworm" msgstr "Žížaly" msgid "week|Hornet" msgstr "SrÅ¡nÄ›" msgid "week|Beetle" msgstr "Brouka" msgid "week|PLAGUE" msgstr "MORU" msgid "week|Unnamed" msgstr "Bez jména" msgid "Desert" msgstr "Poušť" msgid "Snow" msgstr "Sníh" msgid "Wasteland" msgstr "Pustina" msgid "Beach" msgstr "Pláž" msgid "Lava" msgstr "Láva" msgid "Dirt" msgstr "Hlína" msgid "Grass" msgstr "Tráva" msgid "Ocean" msgstr "Oceán" msgid "maps|Small" msgstr "Malá" msgid "maps|Medium" msgstr "StÅ™ední" msgid "maps|Large" msgstr "Velká" msgid "maps|Extra Large" msgstr "Extra velká" msgid "maps|Custom Size" msgstr "Vlastní velikost" msgid "Ore Mine" msgstr "Kamenný důl" msgid "Sulfur Mine" msgstr "Sirný důl" msgid "Crystal Mine" msgstr "KÅ™išťálový důl" msgid "Gems Mine" msgstr "Drahokamový důl" msgid "Gold Mine" msgstr "Zlatý důl" msgid "Mine" msgstr "Důl" msgid "Burma shave." msgstr "Burma shave." msgid "Next sign 50 miles." msgstr "Další cedule za 50 mil." msgid "See Rock City." msgstr "NavÅ¡tivte Skalní mÄ›sto." msgid "This space for rent." msgstr "Tento prostor je k pronájmu." msgid "No object" msgstr "Žádný objekt" msgid "Alchemist Lab" msgstr "LaboratoÅ™" msgid "Sign" msgstr "Cedule" msgid "Buoy" msgstr "Bóje" msgid "Skeleton" msgstr "Kostlivec" msgid "Daemon Cave" msgstr "JeskynÄ› démonů" msgid "Treasure Chest" msgstr "Truhla s pokladem" msgid "Faerie Ring" msgstr "ÄŒarovný kruh" msgid "Campfire" msgstr "OhniÅ¡tÄ›" msgid "Fountain" msgstr "Fontána" msgid "Gazebo" msgstr "Altán" msgid "Genie Lamp" msgstr "Džinova lampa" msgid "Archer's House" msgstr "Dům luÄiÅ¡tníků" msgid "Goblin Hut" msgstr "ChatrÄ goblinů" msgid "Dwarf Cottage" msgstr "Chata trpaslíků" msgid "Peasant Hut" msgstr "ChatrÄ rolníků" msgid "Stables" msgstr "Stáje" msgid "Alchemist's Tower" msgstr "Alchymistova věž" msgid "Event" msgstr "Událost" msgid "Dragon City" msgstr "DraÄí mÄ›sto" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Maják" msgstr[1] "Majáky" msgstr[2] "Majáky" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Vodní mlýn" msgstr[1] "Vodní mlýny" msgstr[2] "Vodní mlýny" msgid "Monster" msgstr "Jednotka" msgid "Obelisk" msgstr "Obelisk" msgid "Oasis" msgstr "Oáza" msgid "Resource" msgstr "Suroviny" msgid "Sawmill" msgstr "Pila" msgid "Oracle" msgstr "Věštírna" msgid "Shrine of the First Circle" msgstr "SvatynÄ› 1. úrovnÄ›" msgid "Shipwreck" msgstr "Vrak" msgid "Sea Chest" msgstr "MoÅ™ská truhla" msgid "Desert Tent" msgstr "PouÅ¡tní stan" msgid "Stone Liths" msgstr "Teleport" msgid "Wagon Camp" msgstr "TáboÅ™iÅ¡tÄ›" msgid "Hut of the Magi" msgstr "Bouda mága" msgid "Whirlpool" msgstr "Vodní vír" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "VÄ›trný mlýn" msgstr[1] "VÄ›trné mlýny" msgstr[2] "VÄ›trné mlýny" msgid "Mermaid" msgstr "MoÅ™ská panna" msgid "Boat" msgstr "LoÄ" msgid "Random Ultimate Artifact" msgstr "Náhodný Ultimátní artefakt" msgid "Random Artifact" msgstr "Náhodný artefakt" msgid "Random Resource" msgstr "Náhodná surovina" msgid "Random Monster" msgstr "Náhodná jednotka" msgid "Random Town" msgstr "Náhodné mÄ›sto" msgid "Random Castle" msgstr "Náhodný hrad" msgid "Eye of the Magi" msgstr "Oko mága" msgid "Random Monster - weak" msgstr "Náhodná jednotka - slabá" msgid "Random Monster - medium" msgstr "Náhodná příšera - stÅ™ední" msgid "Random Monster - strong" msgstr "Náhodná jednotka - silná" msgid "Random Monster - very strong" msgstr "Náhodná jednotka - velmi silná" msgid "Hero" msgstr "Hrdina" msgid "Nothing Special" msgstr "Nic zvláštního" msgid "Mossy Rock" msgstr "OmÅ¡elá skála" msgid "Watch Tower" msgstr "Strážná Věž" msgid "Tree House" msgstr "Letohrádek" msgid "Tree City" msgstr "Letohrádek" msgid "Ruins" msgstr "Ruiny" msgid "Fort" msgstr "Pevnost" msgid "Abandoned Mine" msgstr "OpuÅ¡tÄ›ný důl" msgid "Sirens" msgstr "Sirény" msgid "Standing Stones" msgstr "Posvátné kameny" msgid "Idol" msgstr "Socha" msgid "Tree of Knowledge" msgstr "Strom poznání" msgid "Witch Doctor's Hut" msgstr "ÄŒarodÄ›jova chýše" msgid "Temple" msgstr "Chrám" msgid "Hill Fort" msgstr "Pevnost" msgid "Halfling Hole" msgstr "Hobití nora" msgid "Mercenary Camp" msgstr "Kemp žoldáků" msgid "Shrine of the Second Circle" msgstr "SvatynÄ› 2. úrovnÄ›" msgid "Shrine of the Third Circle" msgstr "SvatynÄ› 3. úrovnÄ›" msgid "City of the Dead" msgstr "MÄ›sto Mrtvých" msgid "Sphinx" msgstr "Sfinga" msgid "Wagon" msgstr "Vagón" msgid "Tar Pit" msgstr "Dehet" msgid "Artesian Spring" msgstr "Arteská studna" msgid "Troll Bridge" msgstr "Trolí most" msgid "Watering Hole" msgstr "Napajedlo" msgid "Witch's Hut" msgstr "Chýše VÄ›dmy" msgid "Xanadu" msgstr "Zámek" msgid "Lean-To" msgstr "PřístÅ™eÅ¡ek" msgid "Magellan's Maps" msgstr "Magellanovy mapy" msgid "Flotsam" msgstr "Trosky" msgid "Derelict Ship" msgstr "Vrak Lodi" msgid "Shipwreck Survivor" msgstr "TroseÄník" msgid "Bottle" msgstr "Láhev" msgid "Magic Well" msgstr "Magická studna" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Kouzelná zahrada" msgstr[1] "Kouzelné zahrady" msgstr[2] "Kouzelné zahrady" msgid "Observation Tower" msgstr "Rozhledna" msgid "Freeman's Foundry" msgstr "Slévárna" msgid "Reefs" msgstr "Útesy" msgid "Volcano" msgstr "Sopka" msgid "Flowers" msgstr "KvÄ›tiny" msgid "Rock" msgstr "Skála" msgid "Water Lake" msgstr "Jezero" msgid "Mandrake" msgstr "Mandragora" msgid "Dead Tree" msgstr "Suchý strom" msgid "Stump" msgstr "Pahýl" msgid "Crater" msgstr "Kráter" msgid "Cactus" msgstr "Kaktus" msgid "Mound" msgstr "Kopec" msgid "Dune" msgstr "Duna" msgid "Lava Pool" msgstr "Lávové jezero" msgid "Shrub" msgstr "KÅ™oví" msgid "Barrow Mounds" msgstr "Hrobové mohyly" msgid "Random Artifact - Treasure" msgstr "Náhodný artefakt - poklad" msgid "Random Artifact - Minor" msgstr "Náhodný artefakt - Menší" msgid "Random Artifact - Major" msgstr "Náhodný artefakt - Hlavní" msgid "Barrier" msgstr "Bariéra" msgid "Traveller's Tent" msgstr "Stan pocestného" msgid "Jail" msgstr "VÄ›zení" msgid "Fire Summoning Altar" msgstr "Oltář OhnÄ›" msgid "Air Summoning Altar" msgstr "Oltář Vzduchu" msgid "Earth Summoning Altar" msgstr "Oltář ZemÄ›" msgid "Water Summoning Altar" msgstr "Oltář Vody" msgid "Swampy Lake" msgstr "Bažinaté jezero" msgid "Frozen Lake" msgstr "Zamrzlé jezero" msgid "randomRace|level 1 creatures" msgstr "Jednotky 1. úrovnÄ›" msgid "randomRace|level 2 creatures" msgstr "Jednotky 2. úrovnÄ›" msgid "randomRace|level 3 creatures" msgstr "Jednotky 3. úrovnÄ›" msgid "randomRace|level 4 creatures" msgstr "Jednotky 4. úrovnÄ›" msgid "randomRace|level 5 creatures" msgstr "Jednotky 5. úrovnÄ›" msgid "randomRace|level 6 creatures" msgstr "Jednotky 6. úrovnÄ›" msgid "Unknown Monsters" msgstr "Neznámé jednotky" msgid "Unknown Monster" msgstr "Neznámá jednotka" msgid "Peasant" msgstr "Rolník" msgid "Peasants" msgstr "Rolníci" msgid "Archer" msgstr "LukostÅ™elec" msgid "Archers" msgstr "LukostÅ™elci" msgid "Ranger" msgstr "HraniÄář" msgid "Rangers" msgstr "HraniÄáři" msgid "Pikeman" msgstr "Kopiník" msgid "Pikemen" msgstr "Kopiníci" msgid "Veteran Pikeman" msgstr "Kopiník veterán" msgid "Veteran Pikemen" msgstr "Kopiníci veteráni" msgid "Swordsman" msgstr "Å ermíř" msgid "Swordsmen" msgstr "Å ermíři" msgid "Master Swordsman" msgstr "Mistr Å ermíř" msgid "Master Swordsmen" msgstr "MistÅ™i Å ermíři" msgid "Cavalries" msgstr "Kavalérie" msgid "Cavalry" msgstr "Kavalérie" msgid "Champion" msgstr "Å ampión" msgid "Champions" msgstr "Å ampióni" msgid "Paladin" msgstr "Paladin" msgid "Paladins" msgstr "Paladini" msgid "Crusader" msgstr "KÅ™ižák" msgid "Crusaders" msgstr "KÅ™ižáci" msgid "Goblin" msgstr "Goblin" msgid "Goblins" msgstr "Goblini" msgid "Orc" msgstr "SkÅ™et" msgid "Orcs" msgstr "SkÅ™eti" msgid "Orc Chief" msgstr "SkÅ™etí Velitel" msgid "Orc Chiefs" msgstr "SkÅ™etí Velitelé" msgid "Wolf" msgstr "Vlk" msgid "Wolves" msgstr "Vlci" msgid "Ogre" msgstr "Zlobr" msgid "Ogres" msgstr "ZlobÅ™i" msgid "Ogre Lord" msgstr "Pán Zlobr" msgid "Ogre Lords" msgstr "Páni Zlobrů" msgid "Troll" msgstr "Trol" msgid "Trolls" msgstr "Trolové" msgid "War Troll" msgstr "VáleÄný Trol" msgid "War Trolls" msgstr "VáleÄní Trolové" msgid "Cyclopes" msgstr "Kyklop" msgid "Cyclops" msgstr "Kyklopové" msgid "Sprite" msgstr "Víla" msgid "Sprites" msgstr "Víly" msgid "Dwarf" msgstr "Trpaslík" msgid "Dwarves" msgstr "Trpaslíci" msgid "Battle Dwarf" msgstr "Bojový trpaslík" msgid "Battle Dwarves" msgstr "Bojoví trpaslíci" msgid "Elf" msgstr "Elf" msgid "Elves" msgstr "Elfové" msgid "Grand Elf" msgstr "Velký Elf" msgid "Grand Elves" msgstr "Velcí Elfové" msgid "Druid" msgstr "Druid" msgid "Druids" msgstr "Druidi" msgid "Greater Druid" msgstr "VÄ›tší druid" msgid "Greater Druids" msgstr "VÄ›tší druidi" msgid "Unicorn" msgstr "Jednorožec" msgid "Unicorns" msgstr "Jednorožci" msgid "Phoenix" msgstr "Fénix" msgid "Phoenixes" msgstr "Fénixové" msgid "Centaur" msgstr "Kentaur" msgid "Centaurs" msgstr "KentauÅ™i" msgid "Gargoyle" msgstr "ChrliÄ" msgid "Gargoyles" msgstr "ChrliÄi" msgid "Griffin" msgstr "Gryf" msgid "Griffins" msgstr "Gryfové" msgid "Minotaur" msgstr "Minotaur" msgid "Minotaurs" msgstr "MinotauÅ™i" msgid "Minotaur King" msgstr "Král Minotaurů" msgid "Minotaur Kings" msgstr "Králové Minotaurů" msgid "Hydra" msgstr "Hydra" msgid "Hydras" msgstr "Hydry" msgid "Green Dragon" msgstr "Zelený Drak" msgid "Green Dragons" msgstr "Zelení Draci" msgid "Red Dragon" msgstr "Rudý Drak" msgid "Red Dragons" msgstr "Rudí Draci" msgid "Black Dragon" msgstr "ÄŒerný Drak" msgid "Black Dragons" msgstr "ÄŒerní Draci" msgid "Halfling" msgstr "Hobit" msgid "Halflings" msgstr "Hobiti" msgid "Boar" msgstr "Kanec" msgid "Boars" msgstr "Kanci" msgid "Iron Golem" msgstr "Železný Golem" msgid "Iron Golems" msgstr "Železní Golemové" msgid "Steel Golem" msgstr "Ocelový Golem" msgid "Steel Golems" msgstr "Oceloví Golemové" msgid "Roc" msgstr "Roch" msgid "Rocs" msgstr "Rochové" msgid "Mage" msgstr "Mág" msgid "Magi" msgstr "Mágové" msgid "Archmage" msgstr "Arcimág" msgid "Archmagi" msgstr "Arcimágové" msgid "Giant" msgstr "Obr" msgid "Giants" msgstr "ObÅ™i" msgid "Titan" msgstr "Titán" msgid "Titans" msgstr "Titáni" msgid "Skeletons" msgstr "Kostlivci" msgid "Zombie" msgstr "Zombie" msgid "Zombies" msgstr "Zombie" msgid "Mutant Zombie" msgstr "Mutantní Zombie" msgid "Mutant Zombies" msgstr "Mutantní Zombie" msgid "Mummies" msgstr "Mumie" msgid "Mummy" msgstr "Mumie" msgid "Royal Mummies" msgstr "Královské Mumie" msgid "Royal Mummy" msgstr "Královská Mumie" msgid "Vampire" msgstr "Upír" msgid "Vampires" msgstr "Upíři" msgid "Vampire Lord" msgstr "Pán Upírů" msgid "Vampire Lords" msgstr "Pánové Upírů" msgid "Lich" msgstr "Lich" msgid "Liches" msgstr "Lichové" msgid "Power Lich" msgstr "Mocný Lich" msgid "Power Liches" msgstr "Mocní Lichové" msgid "Bone Dragon" msgstr "KostÄ›ný Drak" msgid "Bone Dragons" msgstr "KostÄ›ní Draci" msgid "Rogue" msgstr "ZlodÄ›j" msgid "Rogues" msgstr "ZlodÄ›ji" msgid "Nomad" msgstr "KoÄovník" msgid "Nomads" msgstr "KoÄovníci" msgid "Ghost" msgstr "Duch" msgid "Ghosts" msgstr "Duchové" msgid "Genie" msgstr "Džin" msgid "Genies" msgstr "Džinové" msgid "Medusa" msgstr "Medúza" msgid "Medusas" msgstr "Medúzy" msgid "Earth Elemental" msgstr "Zemský Elementál" msgid "Earth Elementals" msgstr "ZemÅ¡tí Elementálové" msgid "Air Elemental" msgstr "VzduÅ¡ný Elementál" msgid "Air Elementals" msgstr "VzduÅ¡ní Elementálové" msgid "Fire Elemental" msgstr "Ohnivý Elementál" msgid "Fire Elementals" msgstr "Ohniví Elementálové" msgid "Water Elemental" msgstr "Vodní Elementál" msgid "Water Elementals" msgstr "Vodní Elementálové" msgid "Random Monsters" msgstr "Náhodné jednotky" msgid "Random Monster 1" msgstr "Náhodná jednotka 1" msgid "Random Monsters 1" msgstr "Náhodné jednotky 1" msgid "Random Monster 2" msgstr "Náhodná jednotka 2" msgid "Random Monsters 2" msgstr "Náhodné jednotky 2" msgid "Random Monster 3" msgstr "Náhodná jednotka 3" msgid "Random Monsters 3" msgstr "Náhodné jednotky 3" msgid "Random Monster 4" msgstr "Náhodná jednotka 4" msgid "Random Monsters 4" msgstr "Náhodné jednotky 4" msgid "Double shot" msgstr "Střílí dvakrát" msgid "2-hex monster" msgstr "Jednotka pÅ™es 2 Å¡estúhelníky" msgid "Double strike" msgstr "ÚtoÄí dvakrát" msgid "Double damage to Undead" msgstr "Dvojnásobné zranÄ›ní nemrtvých" msgid "% magic resistance" msgstr "% magické odolnosti" msgid "Immune to Mind spells" msgstr "Imunní vůÄi kouzlům mysli" msgid "Immune to Elemental spells" msgstr "Imunní vůÄi vyvolání elementálů" msgid "Immune to Fire spells" msgstr "Imunní vůÄi ohnivým kouzlům" msgid "Immune to Cold spells" msgstr "Imunní vůÄi ledovým kouzlům" msgid "Immune to " msgstr "Imunní vůÄi " msgid "% immunity to %{spell} spell" msgstr "% imunita vůÄi kouzlu %{spell}" msgid "% damage from Elemental spells" msgstr "% poÅ¡kození z elementálských kouzel" msgid "% damage from %{spell} spell" msgstr "% poÅ¡kození z kouzla %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% Å¡ance na zruÅ¡ení prospěšných kouzel" msgid "% chance to Paralyze" msgstr "% Å¡ance na paralyzování" msgid "% chance to Petrify" msgstr "% Å¡ance na zkamÄ›ní" msgid "% chance to Blind" msgstr "% Å¡ance na oslepení" msgid "% chance to Curse" msgstr "% Å¡ance na prokletí" msgid "% chance to cast %{spell} spell" msgstr "% Å¡ance na seslání kouzla %{spell}" msgid "HP regeneration" msgstr "Regenerace života" msgid "Two hexes attack" msgstr "Útok pÅ™es dvÄ› pole" msgid "Flyer" msgstr "Létá" msgid "Always retaliates" msgstr "Vždy vrací útok" msgid "Attacks all adjacent enemies" msgstr "ÚtoÄí na vÅ¡echny nepřátele v okolí" msgid "No melee penalty" msgstr "Útok z blízka bez postihu" msgid "Dragon" msgstr "Drak" msgid "Undead" msgstr "Nemrtvý" msgid "No enemy retaliation" msgstr "Nepřítel nevrací úder" msgid "HP drain" msgstr "OdÄerpání života" msgid "Cloud attack" msgstr "Útok z oblaku" msgid "Decreases enemy's morale by " msgstr "Snižuje morálku nepřítele o " msgid "% chance to halve enemy" msgstr "% Å¡ance na zmenÅ¡ení nepřítele na polovinu" msgid "Soul Eater" msgstr "PožíraÄ duší" msgid "Elemental" msgstr "Elementál" msgid "No Morale" msgstr "Žádná morálka" msgid "Earth creature" msgstr "Zemská jednotka" msgid "Air creature" msgstr "VzduÅ¡ná jednotka" msgid "Fire creature" msgstr "Ohnivá jednotka" msgid "Water creature" msgstr "Vodní jednotka" msgid "Double damage from Fire spells" msgstr "Dvojnásobné poÅ¡kození z ohnivých kouzel" msgid "Double damage from Cold spells" msgstr "Dvojnásobné poÅ¡kození z ledových kouzel" msgid "Double damage from Earth creatures" msgstr "Dvojnásobné poÅ¡kození od zemských jednotek" msgid "Double damage from Air creatures" msgstr "Dvojnásobné poÅ¡kození od vzduÅ¡ných jednotek" msgid "Double damage from Fire creatures" msgstr "Dvojnásobné poÅ¡kození od ohnivých jednotek" msgid "Double damage from Water creatures" msgstr "Dvojnásobné poÅ¡kození od vodních jednotek" msgid "Lightning" msgstr "Blesk" msgid "% immunity to " msgstr "% imunita vůÄi " msgid "% damage from " msgstr "% poÅ¡kození z " msgid "The three Anduran artifacts magically combine into one." msgstr "TÅ™i Anduranovy artefakty se magicky spojí v jeden." msgid "View Spells" msgstr "Zobrazit kouzla" msgid "View %{name} Info" msgstr "Zobrazit informace o %{name}" msgid "Move %{name}" msgstr "PÅ™esunout %{name}" msgid "Cannot move the Spellbook" msgstr "Knihu kouzel nelze pÅ™esunout" msgid "This item can't be traded." msgstr "Tento pÅ™edmÄ›t nelze prodat." msgid "Invalid Artifact" msgstr "Nesprávný Artefakt" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} zvyÅ¡uje hrdinovy znalosti o %{count}." msgid "Ultimate Book of Knowledge" msgstr "Ultimátní kniha znalostí" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} zvyÅ¡uje hrdinovu dovednost útok o %{count}." msgid "Ultimate Sword of Dominion" msgstr "Ultimátní meÄ nadvlády" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} zvyÅ¡uje hrdinovu dovednost obrana o %{count}." msgid "Ultimate Cloak of Protection" msgstr "Ultimátní plášť ochrany" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} zvyÅ¡uje hrdinovu sílu kouzel o %{count}." msgid "Ultimate Wand of Magic" msgstr "Ultimátní kouzelná hůlka" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} zvyÅ¡uje hrdinovu dovednost útok a obranu o %{count}." msgid "Ultimate Shield" msgstr "Ultimátní Å¡tít" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} zvyÅ¡uje hrdinovu sílu kouzel a znalosti o %{count}." msgid "Ultimate Staff" msgstr "Ultimátní tyÄ" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} zvyÅ¡uje hrdinovy základní dovednosti o %{count}." msgid "Ultimate Crown" msgstr "Ultimátní koruna" msgid "Golden Goose" msgstr "Zlatá husa" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} pÅ™ináší příjem ve výši %{count} zlata dennÄ›." msgid "Arcane Necklace of Magic" msgstr "Arkánský náhrdelník magie" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Po záchranÄ› ÄarodÄ›jky z prokleté hrobky tÄ› odmÄ›ní za tvé hrdinství nádherným " "zdobeným náhrdelníkem." msgid "Caster's Bracelet of Magic" msgstr "Náramek kouzelníka" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "PÅ™i prohledávání trosek zříceného dolu osvobodíš skupinu uvÄ›znÄ›ných " "trpaslíků. VdÄ›Äný vůdce ti dá zlatý náramek." msgid "Mage's Ring of Power" msgstr "Prsten moci" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "VýkÅ™ik bolesti tÄ› zavede ke Kentaurovi, který uvízl v pasti. Po osvobození " "tohoto tvora ti podá malý měšec. Když obsah vysypeÅ¡, najdeÅ¡ okouzlující " "zdobený prsten." msgid "Witch's Broach of Magic" msgstr "Brož ÄarodÄ›jnice" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Vedle pozůstatků spálené ÄarodÄ›jnice leží nádherná brož. OpatrnÄ› se " "pÅ™iblížíš k tÄ›lu a brož pÅ™idáš do svého inventáře." msgid "Medal of Valor" msgstr "Medaile za stateÄnost" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} zvyÅ¡uje morálku hrdinovy armády o %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Osvobozením ctnostné panny z drápů Äábla obdržíte Medaili cti od králova " "posla." msgid "Medal of Courage" msgstr "Medaile odvahy" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Poté, co jste zachránili mladého chlapce pÅ™ed krvelaÄným houfem vlků, " "vracíte ho do sídla jeho otce. VdÄ›Äný Å¡lechtic vám udÄ›lí Medaili odvahy." msgid "Medal of Honor" msgstr "Medaile cti" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Po osvobození princezny z sousedního království z Äábelských spárů " "neodpustitelných otrokářů vám udÄ›lí Medaili cti." msgid "Medal of Distinction" msgstr "Medaile vyznamenání" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Poté, co jste zbavili venkov od ohavného Minotaura, který si dÄ›lal legraci z " "pojídání rytířů vzneÅ¡ených mužů, jste vyznamenán Medailí vyznamenání." msgid "Fizbin of Misfortune" msgstr "Medaile neÅ¡tÄ›stí" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} výraznÄ› snižuje morálku hrdinovy armády o %{count}" msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Narazíte na medaili ležící podél prázdné cesty. PÅ™idáním medaile do vaÅ¡eho " "inventáře si uvÄ›domíte, že jste získali nechtÄ›nou Medaili neÅ¡tÄ›stí, což " "výraznÄ› snižuje morálku vaší armády." msgid "Thunder Mace of Dominion" msgstr "Palcát" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "BÄ›hem neÄekané bouÅ™e zasáhne strom blesk, který jej rozpůlí. UvnitÅ™ stromu " "najdete tajemnou zbraň." msgid "Armored Gauntlets of Protection" msgstr "ObrnÄ›né rukavice" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} zvyÅ¡ují hrdinovu dovednost obrany o %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Narazíte na nechvalnÄ› proslulého ÄŒerného rytíře! Po vyÄerpávajícím souboji, " "který konÄí remízou, vám rytíř z úcty nabízí pár brnÄ›ných rukavic." msgid "Defender Helm of Protection" msgstr "Helma obránce" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Záblesk zlatého svÄ›tla ti padne do oka. PÅ™i bližším zkoumání najdeÅ¡ pod " "keÅ™em skrytou zlatou helmu." msgid "Giant Flail of Dominion" msgstr "Obří cep" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "NeÅ¡ikovný obr se zabil vlastní zbraní. VÄ›dom si svých dovedností s touto " "zbraní, s jistotou sebereÅ¡ ohromný cep z tÄ›la padlého obra." msgid "Ballista of Quickness" msgstr "Balista rychlosti" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "%{name} dává hrdinovÄ› balistÄ› jeden dodateÄný výstÅ™el každé kolo." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Když kráÄíš ruinami starovÄ›kého opevnÄ›ného mÄ›sta, najdeÅ¡ nástroj jeho " "zniÄení, peÄlivÄ› vyrobenou balistu." msgid "Stealth Shield of Protection" msgstr "Tajný Å¡tít" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Kamenná socha váleÄníka drží stříbrný Å¡tít. Když Å¡tít sejmeÅ¡, socha se " "rozpadne na prach." msgid "Dragon Sword of Dominion" msgstr "DraÄí meÄ" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Když kráÄíš po úzké cestiÄce, náhle poblíž vzplane keÅ™. PÅ™ed tvýma oÄima se " "plameny promÄ›ní v obraz krásné ženy. Vytahuje a podává ti nádherný meÄ." msgid "Power Axe of Dominion" msgstr "Bojová sekera" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Vidíš stříbrnou sekeru zaraženou hluboko v zemi. Po nÄ›kolika neúspěšných " "pokusech tvé armády ji vytáhnout pevnÄ› uchopíš rukojeÅ¥ a bez námahy ji " "vytrhneÅ¡." msgid "Divine Breastplate of Protection" msgstr "Božský krunýř" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Skupina zlodÄ›jů prohledává majetek mrtvých váleÄníků. Když vyženeÅ¡ zlodÄ›je, " "vÅ¡imneÅ¡ si, že zlodÄ›ji pÅ™ehlédli nádherné brnÄ›ní." msgid "Minor Scroll of Knowledge" msgstr "Menší svitek poznání" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "PÅ™ed tebou se objeví levitující sklenÄ›ná vitrína se svitkem, umístÄ›ná na " "lůžku karmínového sametu. PÅ™i tvém dotyku se víko otevÅ™e a svitek letí do " "tvých Äekajících rukou." msgid "Major Scroll of Knowledge" msgstr "Velký svitek poznání" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "NavÅ¡tívíš místního mudrce a vysvÄ›tlíš mu úmysl své cesty. On sáhne do pytle, " "vytáhne zažloutlý svitek a podá ti ho." msgid "Superior Scroll of Knowledge" msgstr "Mocný svitek poznání" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Narazíš na pozůstatky starovÄ›kého druida. Kosti, zažloutlé vÄ›kem, vykukují z " "roztrhaných záhybů jeho roucha. PÅ™i prohledávání roucha objevíš svitek " "schovaný v záhybech." msgid "Foremost Scroll of Knowledge" msgstr "Vrcholný svitek poznání" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Zohavené kosti zažloutlé vÄ›kem, vykukují z roztrhaných záhybů roucha mrtvého " "druida. PÅ™i prohledávání roucha objevíš svitek skrytý uvnitÅ™." msgid "Endless Sack of Gold" msgstr "Bezedná taÅ¡ka zlata" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} poskytuje hrdinovi %{count} zlata dennÄ›." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Malý skřítek radostnÄ› tanÄí kolem magického měšce. Když tÄ› spatří pÅ™icházet, " "zastaví se v půli kroku. Malý muž zakÅ™iÄí a zuÅ™ivÄ› dupne nohou, než zmizí " "beze stopy. Vzpomínajíc na staré přísloví skřítků \"Kdo najde, ten si " "vezme\", chytíš měšec a odejdeÅ¡." msgid "Endless Bag of Gold" msgstr "NekoneÄná braÅ¡na zlata" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Noblesní dáma, oddÄ›lená od svých cestovních spoleÄníků, žádá o vaÅ¡i pomoc. " "Po doprovodu domů vás odmÄ›ní pytlem plným zlata." msgid "Endless Purse of Gold" msgstr "Bezedná tobolka zlata" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "BÄ›hem svých cest naleznete koženou tobolku plnou zlata, který kdysi patÅ™il " "velkému váleÄnému králi, jenž mÄ›l schopnost promÄ›nit jakýkoli neživý objekt " "na zlato." msgid "Nomad Boots of Mobility" msgstr "Boty rychlosti" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} zvyÅ¡ují hrdinovu pohyblivost na souÅ¡i." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "KoÄovný obchodník hledá ochranu pÅ™ed kmenem goblinů. Za tvou pomoc ti dává " "preciznÄ› zpracovaný pár bot vyrobených z nejjemnÄ›jší kůže. Když se podíváš " "blíže, uvidíš fascinující starovÄ›ké rytiny vyryté do kůže." msgid "Traveler's Boots of Mobility" msgstr "Boty cestovatele" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "ObjevujeÅ¡ pár krásnÄ› perliÄkovaných bot vyrobených z nejjemnÄ›jší a nejmÄ›kÄí " "kůže. DÄ›kujeÅ¡ anonymnímu dárci a pÅ™idáváš boty do svého inventáře." msgid "Lucky Rabbit's Foot" msgstr "KráliÄí pracka" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} zvyÅ¡uje Å¡tÄ›stí hrdinovy armády o %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Obchodník ti nabízí králiÄí pracku vyrobenou z lesklé stříbrné srsti výmÄ›nou " "za bezpeÄný průchod. Obchodník vysvÄ›tluje, že tento amulet zvýší tvé Å¡tÄ›stí " "v boji." msgid "Golden Horseshoe" msgstr "Zlatá podkova" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Uchvácený jednorožec hÅ™ebÄí ve strachu. Å eptáš mu uklidňující slova a " "osvobodíš ho. Odfrkne si a dupne pÅ™ední nohou, než se rozbÄ›hne. Když se " "podíváš dolů, uvidíš zlatou podkovu." msgid "Gambler's Lucky Coin" msgstr "Šťastná mince hráÄe" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Zachytil jsi zlomyslného skřítka, který terorizoval okolí. Na oplátku za své " "propuÅ¡tÄ›ní tÄ› odmÄ›ní kouzelnou mincí." msgid "Four-Leaf Clover" msgstr "ÄŒtyÅ™lístek" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "UprostÅ™ed plochy mrtvé a suché vegetace tÄ› pÅ™ekvapí zdravý zelený ÄtyÅ™lístek." msgid "True Compass of Mobility" msgstr "Kompas" msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} zvyÅ¡uje hrdinovu pohyblivost na souÅ¡i i na moÅ™i." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Starý muž, který se oznaÄuje za vynálezce, tÄ› žádá, abys vyzkouÅ¡el jeho " "nejnovÄ›jší vynález. Poté ti podá kompas." msgid "Sailor's Astrolabe of Mobility" msgstr "Astroláb" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} zvyÅ¡uje hrdinovu pohyblivost na moÅ™i." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Starý námoÅ™ní kapitán je muÄen obry. Zachráníš ho a on ti na oplátku dá " "úžasný přístroj k měření vzdáleností hvÄ›zd." msgid "Evil Eye" msgstr "Oko zla" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} snižuje náklady na vyvolání kleteb o polovinu." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Když vstupujeÅ¡ do zchátralé chatrÄe, najdeÅ¡ kostru dávno mrtvé ÄarodÄ›jnice. " "PÅ™i zkoumání pozůstatků objevíš sklenÄ›né oko, které se válí uvnitÅ™ prázdné " "lebky." msgid "Enchanted Hourglass" msgstr "PÅ™esýpací hodiny" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "%{name} prodlužují trvání vÅ¡ech hrdinových kouzel o %{count} kol." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "NepÅ™edvídaný cesta krajinou tÄ› zavede do straÅ¡idelné scény: supi, kteří se " "krmí na pozůstatcích hrozné bitvy. PÅ™i povrchním prohledávání pozůstatků " "objevíš kouzelné pÅ™esýpací hodiny." msgid "Gold Watch" msgstr "Zlaté hodinky" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} zdvojnásobují úÄinnost hrdinových hypnotizaÄních kouzel." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Jako odmÄ›nu za pomoc s vytažením jeho vozu z příkopu ti pocestný prodejce " "lektvarů dá \"kouzelné\" zlaté hodinky. NevÄ›domky pro nÄ›j jsou hodinky " "opravdu kouzelné." msgid "Skullcap" msgstr "Helmice" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} snižuje náklady na vyvolání vÅ¡ech kouzel ovlivňujících mysl na " "polovinu." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Krátká zastávka ve venkovské hospodÄ› pÅ™inese výmÄ›nu penÄ›z, příbÄ›hů a omylem " "i zavazadel. V novém batohu najdeÅ¡ kouzelnou helmici." msgid "Ice Cloak" msgstr "Ledový plášť" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} snižuje na polovinu veÅ¡keré poÅ¡kození, které hrdinovy jednotky utrpí " "od ledových kouzel." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Na panické výkÅ™iky dívky v nesnázích reagujeÅ¡ a objevujeÅ¡ mladou ženu " "prchající pÅ™ed hladovým medvÄ›dem. Bestii v pravý Äas zabijeÅ¡, a vdÄ›Äná " "ÄarodÄ›jka uplete kouzelný plášť z medvÄ›dí kůže." msgid "Fire Cloak" msgstr "Ohnivý plášť" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} snižuje na polovinu veÅ¡keré poÅ¡kození, které hrdinovy jednotky utrpí " "od ohnivých kouzel." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Narazil jsi na souboj mezi nekromantem a paladinem. Nekromant zasáhne " "paladina ohnivým bleskem, pÅ™ivede ho na kolena. Rychle jednáš a zabijeÅ¡ " "zlého nekromanta dříve, než udÄ›lí poslední úder. VdÄ›Äný paladin ti dá ohnivý " "plášť, který ho zachránil." msgid "Lightning Helm" msgstr "Blesková helma" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} snižuje na polovinu veÅ¡keré poÅ¡kození, které hrdinovy jednotky utrpí " "od bleskových kouzel." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Cestující kovář, který potÅ™ebuje zásoby, ti nabízí helmu s bleskovým vzorem " "na vrchu výmÄ›nou za jídlo a vodu. ZvÄ›davÄ› souhlasíš a pozdÄ›ji zjistíš, že " "helma je kouzelná." msgid "Evercold Icicle" msgstr "VÄ›ÄnÄ› studený rampouch" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} způsobuje, že hrdinova ledová kouzla způsobují nepřátelským " "jednotkám o %{count} procent více poÅ¡kození." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Rampouch, který odolává plnému žáru poledního slunce, upoutá tvou pozornost. " "ZvÄ›davÄ› ho ulomíš a zjistíš, že se ti v ruce neroztéká." msgid "Everhot Lava Rock" msgstr "Lávový kámen" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} způsobuje, že hrdinova ohnivá kouzla způsobují nepřátelským " "jednotkám o %{count} procent více poÅ¡kození." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Tvé toulky tÄ› pÅ™ivedou do kontaktu s kmenem opiÄích bytostí, které používají " "kouzelný lávový kámen, jenž nikdy neochladne, k rozdÄ›lování ohnÄ›. Je ti jich " "líto, a tak je nauÄíš, jak si udÄ›lat oheň pomocí klacků. Věříce, že jsi bůh, " "ti opice dají svůj kámen." msgid "Lightning Rod" msgstr "Blesková tyÄ" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} způsobuje, že hrdinova blesková kouzla způsobují nepřátelským " "jednotkám o %{count} procent více poÅ¡kození." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Když Äekáš, až pÅ™ejde bouÅ™e, blesk zasáhne tyÄ nedaleké chalupy, která se " "roztaví a spadne na zem. Hrot tyÄe vÅ¡ak zůstává nepoÅ¡kozený a když se ho " "dotkneÅ¡, naježí se ti vlasy . Hmm..." msgid "Snake-Ring" msgstr "Ouroboros" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} snižuje náklady na vyvolání vÅ¡ech hrdinových požehnání na polovinu." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "NaÅ¡el jsi podivnÄ› tvarovaný prsten na prstu dávno mrtvého cestovatele. " "Prsten vypadá jako had, který se kouÅ¡e do vlastního ocasu." msgid "Ankh" msgstr "Ankh" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} zdvojnásobuje úÄinnost vÅ¡ech hrdinových kouzel oživení a vzkříšení." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Silný vÄ›trný bouÅ™ka odhalí vchod do pohÅ™bené hrobky. VaÅ¡e zkoumání ukazuje, " "že hrobka už byla vykradena, ale zlodÄ›ji pÅ™ehlédli Ankh na stříbrném Å™etízku " "ve tmÄ›." msgid "Book of Elements" msgstr "Kniha elementů" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} zdvojnásobuje úÄinnost vÅ¡ech hrdinových vyvolávacích kouzel." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Narazíš na vyvolávaÄe, který prosí, aby mohl s tebou a tvou armádou nÄ›jakou " "dobu cestovat a být v bezpeÄí. Souhlasíš a on ti na oplátku nabízí kopii " "Knihy elementů." msgid "Elemental Ring" msgstr "Elementární prsten" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" "%{name} snižuje náklady na vyvolání vÅ¡ech vyvolávacích kouzel na polovinu." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Když si dáš pauzu na odpoÄinek, vÅ¡imneÅ¡ si rysa, který Å¡plhá na malý strom, " "aby se dostal k hnízdu vrány. PodlehneÅ¡, vyÅ¡plháš na strom a vydÄ›síš koÄku. " "Když se podíváš do hnízda, najdeÅ¡ sbírku lesklých kamenů a prsten." msgid "Holy Pendant" msgstr "Svatý medailon" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní kletbám." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "PÅ™i svých toulkách narazíš na poustevníka, který žije v malé, uklizené " "chatrÄi. Ohromen tvou misí, na chvíli pÅ™eruší své meditace, aby tÄ› požehnal " "a dal ti amulet proti kletbám." msgid "Pendant of Free Will" msgstr "Medailon svobodné vůle" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní vůÄi hypnotizaÄním kouzlům." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "V reakci na výkÅ™iky o pomoc najdeÅ¡ říÄní skřítky, kteří chtÄ›jí utopit " "starého muže. Cítíc touhu po pomstÄ›, muže zachráníš a jednoho skřítka " "vytáhneÅ¡ na suchou zem. Skřítek, který se na vzduchu cítí nepohodlnÄ›, ti za " "propuÅ¡tÄ›ní dá kouzelný medailon." msgid "Pendant of Life" msgstr "Medailon života" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní vůÄi kouzlům smrti." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Krátké setkání na silnici s malou karavanou a hra s kostkami ti pÅ™inese " "kouzelný medailon. Jeho bývalý majitel říká, že chrání pÅ™ed kouzly smrti " "nekromantů." msgid "Serenity Pendant" msgstr "Medailon klidu" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní kouzlu berserk." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Zvuky boje tÄ› pÅ™itáhnou k místu, kde se bije starý barbar s osmihlavou " "hydrou. Tvá vÄasná intervence otoÄí bitvu ve prospÄ›ch muže, který tÄ› odmÄ›ní " "medailonem, který dříve používal k uklidnÄ›ní své mysli pÅ™ed bojem." msgid "Seeing-eye Pendant" msgstr "PřívÄ›sek vidÄ›ní" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní vůÄi kouzlům oslepení." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Narazíš na velmi starou ženu, která byla dlouho slepá kvůli Å¡edému zákalu a " "umírá sama. Postaráš se o její poslední potÅ™eby a slíbíš jí důstojný pohÅ™eb. " "VdÄ›Äná ti dá kouzelný medailon se stylovým okem. Umožňuje ti vidÄ›t i se " "zavÅ™enýma oÄima." msgid "Kinetic Pendant" msgstr "Medailon pohybu" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní vůÄi kouzlům paralyzování." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Narazíš na golema, který nosí zářící medailon a blokuje ti cestu. Na základÄ› " "intuice mu medailon usekneÅ¡ z krku. Oslabený o svůj zdroj síly se golem " "rozpadne, a ty zůstaneÅ¡ s kouzelným medailonem." msgid "Pendant of Death" msgstr "Medailon smrti" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní vůÄi svatým kouzlům." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Rychlá a smrtící bitva s nekromantem ti pÅ™inese jeho kouzelný medailon. " "PozdÄ›ji ti ÄarodÄ›j Å™ekne, že medailon chrání nemrtvé pod tvou kontrolou pÅ™ed " "kouzly svatého slova." msgid "Wand of Negation" msgstr "Hůlka negace" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "%{name} Äiní vÅ¡echny hrdinovy jednotky imunní vůÄi kouzlům na zruÅ¡ení magie." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Potkáš starého přátelského ÄarodÄ›je, který cestuje opaÄným smÄ›rem. PÅ™edstaví " "ti dárek: hůlku, která zabraňuje použití kouzla na zruÅ¡ení magie na tvé " "spojence." msgid "Golden Bow" msgstr "Zlatý luk" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} odstraňuje %{count} procentní penalizaci za to, že hrdinovy jednotky " "střílí pÅ™es pÅ™ekážky (napÅ™. hradby)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Náhodné setkání se slavným lukostÅ™elcem tÄ› pÅ™ivede do hry s kostkami, kde " "jeho luk stavíš proti tvému koni. Vyhráváš." msgid "Telescope" msgstr "Teleskop" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} zvyÅ¡uje množství terénu, které hrdina odhalí pÅ™i dobrodružství, o " "%{count} dodateÄných polí." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Obchodník z dalekých krajů vymÄ›ní za tvé cestovní potÅ™eby nový vynález jeho " "lidu. Tento přístroj zblízka pÅ™ibližuje vzdálené objekty a on ho nazývá...\n" "\n" "teleskop." msgid "Statesman's Quill" msgstr "Brk státníka" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} snižuje náklady na kapitulaci na %{count} procent celkových nákladů " "za jednotky, které hrdina má ve své armádÄ›." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Zastavíš se, abys pomohl diplomatovi s rozbitou osou opravit jeho vůz. " "VdÄ›Äný ti dá psací brk s kouzelnými vlastnostmi, o kterém říká, že \"pomůže " "lidem vidÄ›t vÄ›ci tvým způsobem\"." msgid "Wizard's Hat" msgstr "ÄŒarodÄ›jův klobouk" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} zvyÅ¡uje trvání hrdinových kouzel o %{count} tahů." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Vidíte, jak se ÄŒarodÄ›j snaží uniknout pÅ™ed Gryfem a letí jako vítr. ÄŒarodÄ›j " "otevÅ™e portál a projíždí jím, pÅ™iÄemž mu okraj brány strhne klobouk. Gryf ho " "následuje; brána se zavÅ™e. Zvednete klobouk, otÅ™ete ho a nasadíte si ho." msgid "Power Ring" msgstr "Prsten síly" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} vrací hrdinovi %{count} dodateÄných magické energie dennÄ›." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "NajdeÅ¡ malý strom, který tÄ›snÄ› pÅ™ipomíná velkého ÄarodÄ›je Carnautha, s " "prstenem kolem jednoho z jeho vÄ›tví. Kousky obleÄení a hnilobná kůže tÄ› " "vedou k podezÅ™ení, že je to ON, ale promÄ›nÄ›ný. Protože mu nemůžeÅ¡ pomoci, " "vezmeÅ¡ si kouzelný prsten." msgid "Ammo Cart" msgstr "Vozík se stÅ™elivem" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} poskytuje nekoneÄné stÅ™elivo pro vÅ¡echny hrdinovy jednotky, které " "střílejí." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "UprostÅ™ed starého bojiÅ¡tÄ› vám padne do oka vozík se stÅ™elivem. Prozkoumání " "ukazuje, že je v dobrém stavu, takže si ho vezmete s sebou." msgid "Tax Lien" msgstr "Daňová zástava" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} tÄ› stojí %{count} zlata dennÄ›." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Tvoje velké výdajové návyky ti vynesly obrovský daňový úÄet, který si " "nemůžeÅ¡ dovolit zaplatit. Daňový úředník má slitování a souhlasí s tím, že " "ti bude strhávat pouze 250 zlata dennÄ› z tvého úÄtu po zbytek života." msgid "Hideous Mask" msgstr "Ohavná maska" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "%{name} zabraňuje vÅ¡em 'putujícím' armádám pÅ™ipojit se k hrdinovi." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "VaÅ¡e rabování hrobu Sinfilase Gardolada, slavného promÄ›nlivého ÄarodÄ›je, " "odhaluje jeho legendární masku. S chvÄ›ním ji nasadíte a ta vám zkroutí " "obliÄej do hrůzostraÅ¡ného grimasy! Ó ne! To je ve skuteÄnosti ohavná maska " "Gromlucka Greena a vy v ní zůstáváte uvÄ›znÄ›ni." msgid "Endless Pouch of Sulfur" msgstr "Bezedná moÅ¡na síry" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} poskytuje %{count} síry dennÄ›." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "NavÅ¡tívíte alchymistu, který, když spatří vaÅ¡i armádu, je pÅ™esvÄ›dÄen o " "správnosti vaÅ¡eho cíle. NovÄ› loajální poddaný vám dá svůj nekoneÄnou braÅ¡nu " "síry, aby pomohl s váleÄným úsilím." msgid "Endless Vial of Mercury" msgstr "Bezedná ampule rtuti" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} poskytuje %{count} rtuti dennÄ›." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Krátká zastávka u rychle opuÅ¡tÄ›né věže ÄarodÄ›je pÅ™ináší magickou ampuli " "rtuti, která má vždy trochu na dnÄ›. Když rozpoznáte poklad, který vidíte, " "uzavÅ™ete ji a schováte do kapsy." msgid "Endless Pouch of Gems" msgstr "Bezedná moÅ¡na drahokamů" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} poskytuje %{count} drahokamů dennÄ›." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Krátká dešťová pÅ™eháňka pÅ™ináší duhu... a vy vidíte její konec. Rychle " "jedete a uchopíte hrnec zlata, který tam najdete. Skřítek, který mu patří, " "vás nemůže zastavit, a nabízí vám nekoneÄný sáÄek drahokamů za vrácení jeho " "zlata. PÅ™ijímáte." msgid "Endless Cord of Wood" msgstr "Bezedný sáh dÅ™eva" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} poskytuje %{count} jednotek dÅ™eva dennÄ›." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Zastavíte se, abyste si odpoÄinuli a rozdÄ›lali oheň na vaÅ™ení. Vytahujete " "dÅ™evo z nedaleké hromady. Když z hromady stále taháte dÅ™evo, vÅ¡imnete si, že " "se nezmenÅ¡uje. S radostí si uvÄ›domíte, že dÅ™evo je zakleté, a vezmete si ho " "s sebou." msgid "Endless Cart of Ore" msgstr "Bezedný vozík kamení" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} poskytuje %{count} kamení dennÄ›." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "NaÅ¡li jste goblinskou zbrojírnu vyrábÄ›jící zbranÄ› pro boj proti lidem. S " "ohromným výkÅ™ikem se vy a vaÅ¡e armáda vrháte na jejich tábor a zaháníte je. " "PÅ™i prozkoumání najdete magický vozík s kamením, který se nikdy nevyÄerpá." msgid "Endless Pouch of Crystal" msgstr "Bezedná moÅ¡na krystalů" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} poskytuje %{count} krystalů dennÄ›." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "PÅ™i hledání úkrytu pÅ™ed bouří v malé jeskyni si vÅ¡imnete malého kusu " "krystalu v jednom rohu. ZvÄ›davý, odlomíte kousek a vÅ¡imnete si, že původní " "krystal dorůstá ztracený kus zpÄ›t. Rozhodnete se, že celý kus vložíte do " "sáÄku a vezmete si ho s sebou." msgid "Spiked Helm" msgstr "Helmice s hroty" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "VaÅ¡i armádu pÅ™epadne malá skupina divokých (a ne příliÅ¡ chytrých) Orců. " "Snadno je odrazíte a pÅ™eživší prchají do vÅ¡ech smÄ›rů. Jeden z Orců mÄ›l na " "sobÄ› leÅ¡tÄ›nou helmu s hroty. PÅ™edpokládáte, že to bude dobrý suvenýr, a " "vezmete si ji." msgid "Spiked Shield" msgstr "Å tít s hroty" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Narazíte na most pÅ™es vyschlou rokli. Než stihnete pÅ™ejít, vystoupí zpod " "mostu Troll a požaduje zaplacení, než vám dovolí projít. Odpíráte, a Troll " "se na vás vrhá, což vás nutí ho zabít. Jako trofej si vezmete jeho Å¡tít s " "hroty." msgid "White Pearl" msgstr "Bílá perla" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Procházka po vyschlém dnÄ› slaného jezera pÅ™ináší neÄekanou odmÄ›nu: bílou " "perlu mezi rozbitými lasturami a troskami." msgid "Black Pearl" msgstr "ÄŒerná perla" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "PovÄ›sti o Gryfu neobvyklé velikosti, který se živí na venkovÄ›, vás dovedou k " "jeho jeskyni. Rychlý a brutální souboj ukonÄí bestii, a pÅ™i prozkoumání " "jejího odporného hnízda objevíte obrovskou Äernou perlu." msgid "Magic Book" msgstr "Kniha kouzel" msgid "The %{name} enables the hero to cast spells." msgstr "%{name} umožňuje hrdinovi sesílat kouzla." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" "Můj Pane, dovolte mi, abych vám ukázal svůj poslední vynález na šíření " "znalostí!\" Následujete muže do jeho dílny a okamžitÄ› si vÅ¡imnete velkého " "zařízení s páÄkami a klikami. \"Toto je ono!\" říká nadÅ¡enÄ›, \"Tiskárna.\" A " "než stihnete říct jediné slovo, podá vám Knihu kouzel." msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "VítÄ›zství lze dosáhnout nalezením Ultimátního artefaktu." msgid "Dummy 2" msgstr "Dummy 2" msgid "The reserved artifact." msgstr "Vyhrazený artefakt." msgid "Dummy 3" msgstr "Dummy 3" msgid "Dummy 4" msgstr "Dummy 4" msgid "Spell Scroll" msgstr "Kouzelný svitek" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Tento %{name} dává hrdinovi schopnost vyvolat kouzlo %{spell}, pokud má " "hrdina knihu kouzel." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "NajdeÅ¡ propracovaný kontejner, ve kterém se nachází starý pergamenový " "svitek. Runy na kontejneru jsou velmi staré a umÄ›lecké zpracování, se kterým " "byl vyroben, je ohromující. Když vytáhneÅ¡ svitek, pocítíš, jak tÄ› naplní " "magická síla." msgid "Arm of the Martyr" msgstr "Paže muÄedníka" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} zvyÅ¡uje hrdinovu sílu kouzel o %{count}, ale pÅ™idává postih na " "morálku jako kdyby v armádÄ› byli nemrtvý." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Jeden z ménÄ› inteligentních Älenů tvé skupiny zvedne ruku ze zemÄ›. PÅ™estože " "postrádá tÄ›lo, stále se hýbe. Tvoje jednotky považují useknutou ruku za " "odpornou, ale ty se nemůžeÅ¡ pÅ™imÄ›t ji odhodit: zdá se, že drží jakousi " "magickou moc, která ovlivňuje tvoje rozhodování." msgid "Breastplate of Anduran" msgstr "Anduranavo brnÄ›ní" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} zvyÅ¡uje hrdinovu obranu o %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Narazíš na znamení. ÄŒteÅ¡: \"Zde leží tÄ›lo Andurana. Pokloňte se a přísahajte " "vÄ›rnost, a budete odmÄ›nÄ›ni.\" RozhodneÅ¡ se udÄ›lat, jak říká. Když vstaneÅ¡, " "ucítíš chlad na své kůži. Když se podíváš dolů, zjistíš, že máš na sobÄ› " "najednou lesklé, zdobené brnÄ›ní." msgid "Broach of Shielding" msgstr "Brož ochrany" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} poskytuje %{count} procent ochrany pÅ™ed Armageddonem a Elementárním " "bouÅ™emi, ale snižuje sílu kouzel o 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Laskavá ÄarodÄ›jka si myslí, že obrana tvé armády by mohla potÅ™ebovat magické " "vylepÅ¡ení. Nabízí, že oÄaruje brož, kterou nosíš na svém plášti, a ty " "souhlasíš." msgid "Battle Garb of Anduran" msgstr "Anduranův bojový odÄ›v" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} spojuje síly tří artefaktů Andurana. Zajišťuje maximální Å¡tÄ›stí a " "morálku pro hrdinovy jednotky a dává hrdinovi kouzlo MÄ›stského brána." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Z lítosti nad chudým sedlákem koupíš truhlu se starým haraburdím, které " "prodávají za příliÅ¡ mnoho zlata. PozdÄ›ji, když ji prohledáváš, zjistíš, že " "obsahuje 3 kusy legendárního bojového odÄ›vu Andurana!" msgid "Crystal Ball" msgstr "KÅ™išťálová koule" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} umožňuje hrdinovi získat konkrétnÄ›jší informace o jednotkách, " "nepřátelských hrdinech a hradech v okolí hrdiny." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Narazíš na karavanu cikánů, kteří hodují a posilují svá tÄ›la medovinou. " "Zvolají tÄ› blíž a říkají: \"Pokud dokážeÅ¡, že umíš tancovat Rama-Butu, " "odmÄ›níme tÄ›.\" Nevíš, jak na to, ale pokusíš se. Hystericky se smÄ›jí, ale " "obdivují tvou odvahu a dají ti kÅ™išťálovou kouli." msgid "Heart of Fire" msgstr "Srdce ohnÄ›" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} poskytuje ochranu %{count} procent pÅ™ed ohnÄ›m, ale zdvojnásobuje " "poÅ¡kození způsobené ledem." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "VstupujeÅ¡ do nedávno spálené mýtiny a narazíš na ohnivého elementála, který " "sedí na kameni. Podívá se nahoru, jeho plamenná tvář je zkÅ™ivená výrazem " "silné bolesti. Poté ti hodí zářící pÅ™edmÄ›t. Zvedáš ruce, abys ho zablokoval, " "ale prochází ti jimi a vpálí se ti do hrudi." msgid "Heart of Ice" msgstr "Srdce ledu" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} poskytuje ochranu %{count} procent pÅ™ed ledem, ale zdvojnásobuje " "poÅ¡kození způsobené ohnÄ›m." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Náhle tÄ› obklopí kousavý chlad. ZtuhneÅ¡ a spadneÅ¡ ze svého konÄ›. Bolest " "ustupuje, ale stále máš pocit, jako by ti hrudník zmrzl. Když se zvedáš ze " "zemÄ›, uslyšíš bujarý smích. OtoÄíš se právÄ› vÄas, abys vidÄ›l, jak ledový obr " "utíká do lesa a mizí." msgid "Helmet of Anduran" msgstr "Anduranova helma" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Zaznamenáš lesknoucí se objekt vyÄnívající ze zemÄ›. PoÅ¡leÅ¡ jednoho Älena své " "skupiny, aby to prozkoumal. Vrátí se s zlatou helmou v rukou. UvÄ›domíš si, " "že to musí být helma legendárního Andurana, jediného muže, který byl znám " "tím, že nosil solidní zlatou zbroj." msgid "Holy Hammer" msgstr "Svaté kladivo" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Narazíš na bitvu, ve které byl paladin smrtelnÄ› zranÄ›n skupinou zombíků. " "Požádá tÄ›, abys vzal jeho kladivo a dokonÄil, co zaÄal. Když ho zvedneÅ¡, " "zaÄne bzuÄet a poté se vÅ¡echno rozmaže. Zombíci leží mrtví, kladivo kapající " "krví. PÅ™ipneÅ¡ si ho k opasku." msgid "Legendary Scepter" msgstr "Legendární žezlo" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} pÅ™idává %{count} bodů ke vÅ¡em atributům." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Když pÅ™ekonáš malý kopec, narazíš na směšný pohled. Skřítek se snaží unést " "žezlo, které je téměř tak velké jako on sám. Snažíš se nesmát a ptáš se: " "\"PotÅ™ebujeÅ¡ pomoc?\" Skřítek na tebe zafixuje pohled a odpoví: \"Myslíš, že " "je to legraÄní? DobÅ™e. MůžeÅ¡ to nést. StejnÄ› radÄ›ji létám.\"" msgid "Masthead" msgstr "Tiráž" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} zvyÅ¡uje Å¡tÄ›stí a morálku hrdinových jednotek o %{count} pÅ™i " "námoÅ™ních bitvách." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Starý námoÅ™ník ti vypráví příbÄ›h o kouzelné tiráži, kterou v mládí používal " "k povzbuzení své posádky v těžkých Äasech. Poté ti podá vybledlou mapu, " "která ukazuje, kde ji schoval. Po mnoha dobrodružstvích ho najdeÅ¡ schované " "pod nedalekým molem." msgid "Sphere of Negation" msgstr "Sféra negace" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} zakazuje veÅ¡keré kouzlení, pro obÄ› strany, v boji." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Zastavíš se, abys pomohl sedlákovi chytit klisnu na útÄ›ku. Aby ti podÄ›koval, " "podá ti malou kouli. Jakmile ji uchopíš, pocítíš, jak ti magická energie " "odtéká z konÄetin..." msgid "Staff of Wizardry" msgstr "ÄŒarodÄ›jná hůlka" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} zvyÅ¡uje hrdinovu sílu kouzel o %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "PÅ™i hledání zvěře tvoje jednotky narazí na tajemnou hůlku, která levituje " "asi tÅ™i stopy nad zemí. Podají ti ji a ty si vÅ¡imneÅ¡ nápisu. Zní: \"Mozek je " "lepší než svaly a magie porazí sílu. Naslouchej mým slovům a vyhrajeÅ¡ každý " "boj.\"" msgid "Sword Breaker" msgstr "MeÄ drtiÄ" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} zvyÅ¡uje hrdinovu obranu o %{count} a útok o 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Bývalý kapitán stráže obdivuje tvou výpravu a podává ti kouzelný meÄ, na " "který spoléhali bÄ›hem jeho služby." msgid "Sword of Anduran" msgstr "Anduranův meÄ" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Trol tÄ› zastaví a říká: \"ZaplaÅ¥ mi 5000 zlata, nebo tÄ› meÄ Andurana zabije, " "kde stojíš.\" Odpovíš mu odmítnutím. Troll chytí meÄ visící na svém opasku, " "zakÅ™iÄí bolestí a utíká pryÄ. Když zvedneÅ¡ bájný meÄ, dÄ›kujeÅ¡ osudu, že " "trolové mají tendenci chytat nesprávný konec ostrých pÅ™edmÄ›tů." msgid "Spade of Necromancy" msgstr "RÃ½Ä nekromancie" msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} zvyÅ¡uje hrdinovu dovednost nekromancie." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Å pinavá lopata je zaražena do hroudy hlíny nedaleko. PÅ™i prozkoumání " "zjistíš, že jde o kouzelnou lopatu nekromantů, o které se dlouho myslelo, že " "ji smrtelníci ztratili." msgid "spellBonus|selected by user" msgstr "Vybráno uživatelem" msgid "Wood" msgstr "DÅ™evo" msgid "Mercury" msgstr "RtuÅ¥" msgid "Ore" msgstr "Kamení" msgid "Sulfur" msgstr "Síra" msgid "Crystal" msgstr "Krystal" msgid "Gems" msgstr "Drahokamy" msgid "Gold" msgstr "Zlato" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Ve hÅ™e Heroes 2 je 7 surovin, které slouží ke stavbÄ›, vylepÅ¡ování, nákupu " "vojska a náboru hrdinů. NejběžnÄ›jší je zlato, které je potÅ™eba prakticky ke " "vÅ¡emu. DÅ™evo a kamení se používá pro vÄ›tÅ¡inu budov. Drahokamy, rtuÅ¥, síra a " "krystaly jsou vzácnÄ›jší suroviny, které se používají pro nejmocnÄ›jší " "jednotky a budovy." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Vybranou oblast zasáhne obří ohnivá koule, která poraní vÅ¡echny bytosti " "poblíž." msgid "Fireball" msgstr "Ohnivá koule" msgid "Fireblast" msgstr "Ohnivý výbuch" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "VylepÅ¡ená verze ohnivé koule, výbuch působí na dva Å¡estúhelníky kolem stÅ™edu " "kouzla místo jednoho." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Způsobí zasažení vybrané jednotky bleskem elektrické energie." msgid "Lightning Bolt" msgstr "Blesk" msgid "Chain Lightning" msgstr "Kulový blesk" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Způsobí zásah vybrané jednotky bleskem elektrické energie ale následnÄ› " "zasáhne nejbližší jednotku s poloviÄním poÅ¡kozením a poté zasáhne DALÅ Ã " "nejbližší jednotku a opÄ›t s poloviÄním poÅ¡kozením a tak dále, dokud není " "příliÅ¡ slabý na to, aby byl Å¡kodlivý. Pozor: Kouzlo může zasáhnout i tvou " "stranu!" msgid "Teleport" msgstr "Teleport" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Teleportuje vybranou jednotku na libovolné volné místo na bojiÅ¡ti." msgid "Cure" msgstr "LéÄba" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Odstraní vÅ¡echna negativní kouzla seslaná na jednu z tvých jednotek a obnoví " "až %{count} životů dle dosažené úrovnÄ› síly kouzel." msgid "Mass Cure" msgstr "Hromadná léÄba" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Odstraní vÅ¡echna negativní kouzla seslaná na tvé jednotky a obnoví až " "%{count} životů dle dosažené úrovnÄ› síly kouzel na jednotku." msgid "Resurrect" msgstr "Vzkříšení" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "Vzkřísí jednotky z poranÄ›ných nebo mrtvých jednotek až do konce bitvy." msgid "Resurrect True" msgstr "Trvalé vzkříšení" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Trvale vzkřísí jednotky z poranÄ›ných nebo mrtvých jednotek." msgid "Haste" msgstr "Zrychlení" msgid "Increases the speed of any creature by %{count}." msgstr "ZvyÅ¡uje rychlost jakékoli jednotky o %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "ZvyÅ¡uje rychlost vÅ¡ech tvých jednotek o %{count}." msgid "Mass Haste" msgstr "Hromadné zrychlení" msgid "Slows target to half movement rate." msgstr "Zpomalí cílovou jednotku o polovinu." msgid "spell|Slow" msgstr "Zpomalení" msgid "Mass Slow" msgstr "Hromadné zpomalení" msgid "Slows all enemies to half movement rate." msgstr "Zpomalí vÅ¡echny nepřátelské jednotky o polovinu." msgid "spell|Blind" msgstr "Slepota" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" "Zahaluje zrak zasažených jednotek, brání jim v pohybu a snižuje poÅ¡kození " "pÅ™i odvetÄ› o %{count} procent." msgid "Bless" msgstr "Požehnání" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Vybraná jednotka bude způsobovat maximální poÅ¡kození." msgid "Causes all of your units to inflict maximum damage." msgstr "VÅ¡echny tvé jednotky budou způsobovat maximální poÅ¡kození." msgid "Mass Bless" msgstr "Hromadné požehnání" msgid "Magically increases the defense skill of the selected creatures." msgstr "Magicky zvýší obrannou sílu vybraných jednotek." msgid "Stoneskin" msgstr "Kamenná kůže" msgid "Steelskin" msgstr "Ocelová kůže" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "ZvyÅ¡uje obranu cílových jednotek. Toto je vylepÅ¡ená verze Kouzla kamenné " "kůže." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Vybrané jednotky budou způsobovat minimální poÅ¡kození." msgid "Curse" msgstr "Prokletí" msgid "Causes all enemy troops to inflict minimum damage." msgstr "VÅ¡echny nepřátelské jednotky budou působit minimální poÅ¡kození." msgid "Mass Curse" msgstr "Hromadné prokletí" msgid "Damages all undead in the battle." msgstr "PoÅ¡kodí vÅ¡echny nemrtvé v bitvÄ›." msgid "Holy Word" msgstr "Svaté slovo" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "PoÅ¡kodí vÅ¡echny nemrtvé v bitvÄ›. Jedná se o vylepÅ¡enou verzi kouzla Svaté " "slovo." msgid "Holy Shout" msgstr "Svatý výkÅ™ik" msgid "Anti-Magic" msgstr "Antimagie" msgid "Prevents any magic against the selected creatures." msgstr "Znemožňuje použití magie proti vybraným jednotkám." msgid "Dispel Magic" msgstr "ZruÅ¡it kouzla" msgid "Removes all magic spells from a single target." msgstr "Odstraní vÅ¡echna kouzla z cílové jednotky." msgid "Mass Dispel" msgstr "Hromadné zruÅ¡ení" msgid "Removes all magic spells from all creatures." msgstr "Odstraní vÅ¡echna kouzla ze vÅ¡ech jednotek." msgid "Causes a magic arrow to strike the selected target." msgstr "Způsobí zasažení vybraného cíle magickým šípem." msgid "Magic Arrow" msgstr "Magický šíp" msgid "Berserker" msgstr "Berserk" msgid "Causes a creature to attack its nearest neighbor." msgstr "Vybraná jednotka zaútoÄí na jakoukoli nejbližší jednotku." msgid "Armageddon" msgstr "Armagedon" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "Svatá hrůza zasáhne bojiÅ¡tÄ› a způsobí vážné poÅ¡kození vÅ¡em jednotkám." msgid "Elemental Storm" msgstr "Živelná bouÅ™e" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Na bojiÅ¡tÄ› se snesou magické živly a poÅ¡kodí vÅ¡echny jednotky." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "Déšť kamenů zasáhne oblast bojiÅ¡tÄ› a poÅ¡kodí vÅ¡echny jednotky poblíž." msgid "Meteor Shower" msgstr "Pád meteoritů" msgid "Paralyze" msgstr "Paralýza" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "Cílová jednotka je ochromena a nemůže se hýbat ani bránit." msgid "Hypnotize" msgstr "Hypnóza" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "PÅ™evede jednu nepřátelskou jednotku pod tvou kontrolu, pokud jsou její " "životy menší než %{count} násobek síly kouzel." msgid "Cold Ray" msgstr "Ledový paprsek" msgid "Drains body heat from a single enemy unit." msgstr "OdÄerpá tÄ›lesné teplo z nepřátelské jednotky." msgid "Cold Ring" msgstr "Ledový kruh" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "OdÄerpá tÄ›lesné teplo ze vÅ¡ech nepřátelských jednotek kolem stÅ™edu, stÅ™ed " "kruhu vyjímaje." msgid "Disrupting Ray" msgstr "Rušící paprsek" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Sníží obranyschopnost nepřátelské jednotky o tÅ™i." msgid "Damages all living (non-undead) units in the battle." msgstr "PoÅ¡kozuje vÅ¡echny živé (ne nemrtvé) jednotky v bitvÄ›." msgid "Death Ripple" msgstr "Smrtící vlnka" msgid "Death Wave" msgstr "Smrtící vlna" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "PoÅ¡kodí vÅ¡echny živé (nemrtvé) jednotky v bitvÄ›. Toto kouzlo je vylepÅ¡ená " "verze kouzla Smrtící vlnka." msgid "Dragon Slayer" msgstr "Drakobijec" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "VýraznÄ› zvyÅ¡uje útoÄnou sílu jednotky vůÄi drakům." msgid "Blood Lust" msgstr "Krvežíznivost" msgid "Increases a unit's attack skill." msgstr "ZvyÅ¡uje útoÄnou sílu jednotky." msgid "Animate Dead" msgstr "Oživení mrtvých" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "Trvale vzkřísí bytosti z poÅ¡kozené nebo mrtvé nemrtvé jednotky." msgid "Mirror Image" msgstr "Zdvojení" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Vytvoří iluzní jednotku, která je duplikátem jedné z tvých stávajících " "jednotek. Tato iluzní jednotka způsobuje stejné poÅ¡kození jako původní " "jednotka, ale zmizí pokud utrpí jakékoliv poÅ¡kození." msgid "Shield" msgstr "Å tít" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Snižuje poÅ¡kození pÅ™ijímané od útoku na dálku na polovinu pro jednu " "jednotku. Neovlivňuje poÅ¡kození pÅ™ijímané od věží nebo balist." msgid "Mass Shield" msgstr "Hromadný Å¡tít" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Snižuje poÅ¡kození pÅ™ijímané od útoku na dálku na polovinu pro vÅ¡echny vaÅ¡e " "jednotky. Neovlivňuje poÅ¡kození pÅ™ijímané od věží nebo balist." msgid "Summon Earth Elemental" msgstr "PÅ™ivolej Zemské Elementály" msgid "Summons Earth Elementals to fight for your army." msgstr "Do tvé armády povolá Zemské Elementály." msgid "Summon Air Elemental" msgstr "PÅ™ivolej VzduÅ¡né Elementály" msgid "Summons Air Elementals to fight for your army." msgstr "Do tvé armády povolá VzduÅ¡né Elementály." msgid "Summon Fire Elemental" msgstr "PÅ™ivolej Ohnivé Elementály" msgid "Summons Fire Elementals to fight for your army." msgstr "Do tvé armády povolá Ohnivé Elementály." msgid "Summon Water Elemental" msgstr "PÅ™ivolej Vodní Elementály" msgid "Summons Water Elementals to fight for your army." msgstr "Do tvé armády povolá Vodní Elementály." msgid "Damages castle walls." msgstr "PoÅ¡kozuje obranné hradby." msgid "Earthquake" msgstr "ZemÄ›tÅ™esení" msgid "Causes all mines across the land to become visible." msgstr "Zviditelní vÅ¡echny doly v zemi." msgid "View Mines" msgstr "Zobrazit doly" msgid "Causes all resources across the land to become visible." msgstr "Zviditelní vÅ¡echny suroviny v zemi." msgid "View Resources" msgstr "Zobrazit suroviny" msgid "Causes all artifacts across the land to become visible." msgstr "Zviditelní vÅ¡echny artefakty v zemi." msgid "View Artifacts" msgstr "Zobraz artefakty" msgid "Causes all towns and castles across the land to become visible." msgstr "Zviditelní vÅ¡echny mÄ›sta a hrady v zemi." msgid "View Towns" msgstr "Zobrazit mÄ›sta" msgid "Causes all Heroes across the land to become visible." msgstr "Zviditelní vÅ¡echny hrdiny v zemi." msgid "View Heroes" msgstr "Zobrazit hrdiny" msgid "Causes the entire land to become visible." msgstr "Zviditelní celou zemi." msgid "View All" msgstr "Zobrazit vÅ¡e" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "Umožňuje zobrazit podrobné informace o nepřátelských hrdinech." msgid "Summon Boat" msgstr "PÅ™ivolej loÄ" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "PÅ™ivolá nejbližší neobsazenou přátelskou loÄ na pÅ™ilehlé místo na pobÅ™eží. " "Přátelská loÄ je taková, kterou jsi právÄ› postavil nebo jsi ji použil jako " "poslední." msgid "Allows the caster to magically transport to a nearby location." msgstr "Umožní hrdinovi se magicky pÅ™enést na místo poblíž." msgid "Dimension Door" msgstr "Dimenzní brána" msgid "Returns the caster to any town or castle currently owned." msgstr "PÅ™enese hrdinu do jakéhokoli mÄ›sta nebo hradu, který vlastníš." msgid "Town Gate" msgstr "MÄ›stská brána" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Vrátí hrdinu do vybraného mÄ›sta nebo hradu, pokud je pod tvojí kontrolou." msgid "Visions" msgstr "Vize" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Vize pÅ™edpovídají pravdÄ›podobný výsledek stÅ™etu s táborem neutrální armády." msgid "Haunt" msgstr "Duchové" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "V dole, který ovládáte zaÄnou straÅ¡it duchové. Tento důl pak pÅ™estane " "produkovat suroviny. (Pokud ho nebudu mít já, tak nikdo jiný!)" msgid "Set Earth Guardian" msgstr "Zanech zemského strážce" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" "Zanechá u dolu Zemské Elementály, aby ho bránili pÅ™ed nepřátelskými vojsky." msgid "Set Air Guardian" msgstr "Zanech vzduÅ¡ného strážce" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" "Zanechá u dolu VzduÅ¡né Elementály, aby ho bránili pÅ™ed nepřátelskými vojsky." msgid "Set Fire Guardian" msgstr "Zanech ohnivého strážce" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" "Zanechá u dolu Ohnivé Elementály, aby ho bránili pÅ™ed nepřátelskými vojsky." msgid "Set Water Guardian" msgstr "Zanech vodního strážce" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" "Zanechá u dolu Vodní Elementály, aby ho bránili pÅ™ed nepřátelskými vojsky." msgid "Random Spell" msgstr "Náhodné kouzlo" msgid "Randomly selected spell of any level." msgstr "NáhodnÄ› vybrané kouzlo jakékoliv úrovnÄ›." msgid "Random 1st Level Spell" msgstr "Náhodné kouzlo 1. úrovnÄ›" msgid "Randomly selected 1st level spell." msgstr "NáhodnÄ› vybrané kouzlo 1. úrovnÄ›." msgid "Random 2nd Level Spell" msgstr "Náhodné kouzlo 2. úrovnÄ›" msgid "Randomly selected 2nd level spell." msgstr "NáhodnÄ› vybrané kouzlo 2. úrovnÄ›." msgid "Random 3rd Level Spell" msgstr "Náhodné kouzlo 3. úrovnÄ›" msgid "Randomly selected 3rd level spell." msgstr "NáhodnÄ› vybrané kouzlo 3. úrovnÄ›." msgid "Random 4th Level Spell" msgstr "Náhodné kouzlo 4. úrovnÄ›" msgid "Randomly selected 4th level spell." msgstr "NáhodnÄ› vybrané kouzlo 4. úrovnÄ›." msgid "Random 5th Level Spell" msgstr "Náhodné kouzlo 5. úrovnÄ›" msgid "Randomly selected 5th level spell." msgstr "NáhodnÄ› vybrané kouzlo 5. úrovnÄ›." msgid "Petrification" msgstr "ZkamenÄ›ní" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "PromÄ›ní zasaženou jednotku v kámen. ZkamenÄ›lý tvor pak utrpí pÅ™i přímém " "útoku pouze poloviÄní poÅ¡kození." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Nemáš Knihu kouzel, bez ní nemůžeÅ¡ kouzlit." msgid "No spell to cast." msgstr "Žádné kouzlo k seslání." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Váš hrdina má %{sp} magických bodů zbývajících z %{max}." msgid "View Adventure Spells" msgstr "Zobrazit kouzla svÄ›ta" msgid "View Combat Spells" msgstr "Zobrazit bojové kouzla" msgid "View previous page" msgstr "Zobrazt pÅ™edchozí stranu" msgid "View next page" msgstr "Zobrazit další stranu" msgid "Close Spellbook" msgstr "Zavřít knihu" msgid "View %{spell}" msgstr "Zobrazit %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Toto kouzlo způsobí %{damage} Å¡kod." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Toto kouzlo pÅ™ivolá\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Toto kouzlo obnovuje %{hp} zdraví." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Toto kouzlo vyvolává %{count} %{monster}, aby chránili důl." msgid "The nearest town is %{town}." msgstr "Nejbližší mÄ›sto je %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Toto mÄ›sto je obsazeno vaším hrdinou %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Toto kouzlo ovládá až\n" "%{hp} zdraví." msgid "The ultimate artifact is really the %{name}." msgstr "Ultimátním artefaktem je skuteÄnÄ› %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Ultimátní artefakt je možné najít v %{name} oblasti svÄ›ta." msgid "north-west" msgstr "severozápadní" msgid "north" msgstr "severní" msgid "north-east" msgstr "severovýchodní" msgid "west" msgstr "západní" msgid "center" msgstr "centrální" msgid "east" msgstr "východní" msgid "south-west" msgstr "jihozápadní" msgid "south" msgstr "jižní" msgid "south-east" msgstr "jihovýchodní" msgid "The truth is out there." msgstr "Pravda je nÄ›kde venku." msgid "The dark side is stronger." msgstr "Temná strana je silnÄ›jší." msgid "The end of the world is near." msgstr "Konec svÄ›ta je již blízko." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Kosti pána PÅ™emožitele jsou pohÅ™beny v základech bitevní arény." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "ÄŒerný drak sejme Titána kdykoliv a kdekoliv." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "On jí Å™ekl: Yada yada yada... ona pak Å™ekla: Bla, bla, bla..." msgid "An unknown force is being resurrected..." msgstr "Neznámá síla se probouzí..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "NejnovÄ›jší verzi hry nalezneÅ¡ na\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Vyberte množství %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Zapnout automatický boj" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "DokonÄit boj v automatickém režimu" #~ msgid "Please Remember" #~ msgstr "Prosím pamatujte" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "Vždy můžete zmÄ›nit jazyk, rozliÅ¡ení a nastavení hry kliknutím na " #~ msgid "door" #~ msgstr "dveÅ™e" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " na levé stranÄ› hlavního menu, nebo pomocí " #~ msgid " button from the " #~ msgstr " tlaÄítka z " #~ msgid "NEW GAME" #~ msgstr "NOVà HRA" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ " menu. \n" #~ "\n" #~ "Užijte si hru!" #~ msgid "Warning!" #~ msgstr "Varování!" fheroes2-1.1.6+dfsg/files/lang/de.po000066400000000000000000012200761476115357100171500ustar00rootroot00000000000000# German translation of fheroes2 # Copyright (C) 2022-2024 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-11-07 12:48+0100\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: de\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: Poedit 3.5\n" msgid "" "NEW\n" "GAME" msgstr "" "NEUES\n" "SPIEL" msgid "" "SAVE\n" "GAME" msgstr "" "SPIEL\n" "SPEICH." msgid "" "LOAD\n" "GAME" msgstr "" "SPIEL\n" "LADEN" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "BEEND." #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "NEUES\n" "SPIEL" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "SPIEL\n" "SPEICH." #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "SPIEL\n" "LADEN" msgid "CANCEL" msgstr "ABBRUCH" msgid "OKAY" msgstr "OKAY" msgid "ACCEPT" msgstr "AKZEPT." msgid "DECLINE" msgstr "ABLEHNEN" msgid "LEARN" msgstr "LERNEN" msgid "TRADE" msgstr "HANDELN" msgid "YES" msgstr "JA" msgid "NO" msgstr "NEIN" msgid "EXIT" msgstr "ENDE" msgid "smallerButton|EXIT" msgstr "ENDE" msgid "DISMISS" msgstr "ABLEHNEN" msgid "UPGRADE" msgstr "AUFRÜSTEN" msgid "RESTART" msgstr "NEUSTART" msgid "HEROES" msgstr "HELDEN" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "STÄDTE/\n" "BURGEN" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "X-L" msgid "ALL" msgstr "ALLE" msgid "SELECT" msgstr "AUSW." msgid "" "STANDARD\n" "GAME" msgstr "" "STANDARD\n" "SPIEL" msgid "" "BATTLE\n" "ONLY" msgstr "" "NUR\n" "KAMPF" msgid "" "CAMPAIGN\n" "GAME" msgstr "" "FELDZUG\n" "SPIEL" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "MEHR-\n" "SPIELER\n" "SPIEL" msgid "CONFIG" msgstr "KONFIG." msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ORIGINAL\n" "FELDZUG" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "ZUSATZ\n" "FELDZUG" msgid "HOT SEAT" msgstr "" "HEISSER\n" "STUHL" msgid "2 PLAYERS" msgstr "2 SPIELER" msgid "3 PLAYERS" msgstr "3 SPIELER" msgid "4 PLAYERS" msgstr "4 SPIELER" msgid "5 PLAYERS" msgstr "5 SPIELER" msgid "6 PLAYERS" msgstr "6 SPIELER" msgid "GIFT" msgstr "SPEND." msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "SCHWIER." msgid "VIEW INTRO" msgstr "INTRO ANZEIGEN" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "" msgid "START" msgstr "START" msgid "TOWN" msgstr "STÄDT" msgid "CASTLE" msgstr "BURG" #, fuzzy msgid "RESTRICT" msgstr "NEUSTART" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "E\n" "N\n" "T\n" "L\n" "A\n" "S\n" "S\n" "E\n" "N" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "E\n" "N\n" "D\n" "E" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "F\n" "E\n" "L\n" "D\n" "Z\n" "U\n" "G" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "SPRACHE" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Krieger" msgid "Builder" msgstr "Ersteller" msgid "Explorer" msgstr "Forscher" msgid "None" msgstr "Niemand" msgid "" "A few\n" "%{monster}" msgstr "" "Wenige\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Einige\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Mehrere\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Viele\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Eine Menge\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Eine Horde\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Massen\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Ein Schwarm\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Eine Legion\n" "%{monster}" msgid "army|Few" msgstr "Wenige" msgid "army|Several" msgstr "Einige" msgid "army|Pack" msgstr "Mehrere" msgid "army|Lots" msgstr "Viele" msgid "army|Horde" msgstr "Eine Menge" msgid "army|Throng" msgstr "Horde" msgid "army|Swarm" msgstr "Massen" msgid "army|Zounds" msgstr "Schwarm" msgid "army|Legion" msgstr "Legion" msgid "All %{race} troops +1" msgstr "Alle %{race}-Truppen +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Neutral" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Truppen aus %{count} Gattungen -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "Einige Untote in der Gruppe -1" #, fuzzy msgid "" "Default\n" "troop" msgstr "Standardaktion" msgid "View %{name}" msgstr "%{name} ansehen" msgid "Move the %{name} " msgstr "%{name} umstellen " msgid "Move or right click to redistribute %{name}" msgstr "%{name} verteilen: ziehen oder mit der rechten Maustaste tippen" msgid "Combine %{name} armies" msgstr "%{name} Armeen kombinieren" msgid "Exchange %{name2} with %{name}" msgstr "Tauschen %{name2} mit %{name} aus" msgid "Select %{name}" msgstr "%{name} wählen" msgid "Cannot move last troop" msgstr "Letzte Truppe kann nicht umgestellt werden" msgid "Move the %{name}" msgstr "%{name} umstellen" #, fuzzy msgid "Set %{monster} Count" msgstr "Schieße auf %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} vernichtet die Hälfte der feindlichen Truppen!" msgstr[1] "%{name} vernichten die Hälfte der feindlichen Truppen!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} hat den automatischen Kampf ausgeschaltet" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} hat den automatischen Kampf eingeschaltet" msgid "Spell failed!" msgstr "Zauberspruch fehlgeschlagen!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Das Artefakt \"Sphäre der Aufhebung\" ist in diesem Kampf aktiv und macht " "alle Kampfzauber unwirksam." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Ihr habt in dieser Runde bereits einen Zauberspruch ausgesprochen." #, fuzzy msgid "That spell will have no effect!" msgstr "Dieser Zauber wirkt sich auf niemanden aus!" msgid "You may only summon one type of elemental per combat." msgstr "Ihr könnt nur eine Art von Wesen pro Kampf beschwören." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "In der Nähe Eures Helden gibt es keinen freien Platz, um ein Wesen zu " "beschwören." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Der Burggraben reduziert die Verteidigungsfähigkeit jeder Einheit, die auf " "den tritt, um -%{count} und verlangsamt seine Bewegungsrate auf die Hälfte." msgid "Speed: %{speed}" msgstr "Geschw.: %{speed}" msgid "Speed" msgstr "Geschwindigkeit" msgid "Off" msgstr "Aus" msgid "On" msgstr "An" #, fuzzy msgid "Turn Order" msgstr "Reihen- folge" msgid "Auto Spell Casting" msgstr "Auto Zauber" msgid "Grid" msgstr "Gitter" msgid "Shadow Movement" msgstr "Schatten-bewegung" msgid "Shadow Cursor" msgstr "Schatten-Zeiger" msgid "Audio" msgstr "Audio" msgid "Settings" msgstr "Einstellungen" msgid "Configure" msgstr "Konfigurieren" msgid "Hot Keys" msgstr "Hotkeys" msgid "Damage Info" msgstr "Schadens-Information" msgid "Set the speed of combat actions and animations." msgstr "Geschwindigkeit von Kampfhandlungen und Animationen festlegen." msgid "Toggle to display the turn order during the battle." msgstr "Ansicht der Reihenfolge von Truppen ein- oder ausschalten." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Umschalten, ob bei aktiviertem Autokampf der Computer selbständig zaubert " "oder nicht. (Hinweis: Dies hat keinen Einfluss auf das Zaubern für " "Computerspieler und auch nicht auf den Schnellkampf)." msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Hex-Gitters ein-/ausblenden. Das Hex-Gitter bestimmt immer die Bewegung, " "auch wenn es ausgeblendet ist. Dieser Schalter bestimmt nur, ob es sichtbar " "ist." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Schattierung ein-/ausblenden, die anzeigt, wo die Kreatur hinbewegt werden " "und angreifen kann." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Schatten ein-/ausschalten, der die aktuelle Hex-Position des Mauszeigers " "anzeigt." msgid "Change the audio settings of the game." msgstr "Audioeinstellungen des Spiels ändern." msgid "Check and configure all the hot keys present in the game." msgstr "Alle im Spiel verwendeten Hotkeys überprüfen und konfigurieren." msgid "Toggle to display damage information during the battle." msgstr "Die Ansicht der Schadensinformation während des Kampfes umschalten." msgid "Exit this menu." msgstr "Dieses Menü verlassen." msgid "Okay" msgstr "Okay" msgid "The enemy has surrendered!" msgstr "Der Feind hat kapituliert!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Der Feind ist geflohen!" msgid "A glorious victory!" msgstr "Ein glorreicher Sieg!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Für Tapferkeit im Kampf erhält %{name} %{exp} Erfahrung." msgid "The cowardly %{name} flees from battle." msgstr "Der feige %{name} flieht vor der Schlacht." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} kapituliert vor dem Feind und zieht beschämt von dannen." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "Eure Truppe erleidet eine bittere Niederlage, und %{name} verlässt Euch." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Eure Truppe erleidet eine bittere Niederlage." msgid "Battlefield Casualties" msgstr "Opfer auf dem Schlachtfeld" msgid "Attacker" msgstr "Angreifer" msgid "Defender" msgstr "Verteidiger" #, fuzzy msgid "Click to leave the battle results." msgstr "Klicken um die ausgewählte Auflösung anzuwenden." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Klicken, um zum Hauptmenü zurückzukehren." msgid "Restart" msgstr "Neustart" msgid "You have captured an enemy artifact!" msgstr "Ihr habt ein gegnerisches Artefakt erbeutet!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Als Ihr nach dem %{name} greift, verschwindet es auf mysteriöse Weise." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" "Als Euer Gegner nach dem %{name} greift, verschwindet es auf mysteriöse " "Weise." msgid "Necromancy!" msgstr "Nekromantie!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Durch Ausübung der dunklen Künste der Nekromantie, seid Ihr in der Lage, " "%{count} der gegnerischen Toten auferstehen zu lassen, und als %{monster} in " "Eure Dienste zu stellen." msgid "%{name} the %{race}" msgstr "%{name} (%{race})" msgid "Captain of %{name}" msgstr "Hauptmann von %{name}" msgid "Attack" msgstr "Angriff" msgid "Defense" msgstr "Verteid." msgid "Spell Power" msgstr "Zauberkraft" msgid "Knowledge" msgstr "Wissen" msgid "Morale" msgstr "Moral" msgid "Luck" msgstr "Glück" msgid "Spell Points" msgstr "Zauberpunkte" msgid "Hero's Options" msgstr "Helden-Optionen" msgid "Cast Spell" msgstr "Zauber wirken" msgid "Retreat" msgstr "Zurückziehen" msgid "Surrender" msgstr "Aufgeben" msgid "Cancel" msgstr "Abbrechen" msgid "Hero Screen" msgstr "Heldenbildschirm" msgid "Captain's Options" msgstr "Möglichkeiten des Hauptmanns" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Einen Zauberspruch aussprechen. Ihr könnt pro Kampfrunde nur einen " "Zauberspruch aussprechen. Die Runde ist beendet, wenn alle Kreaturen an der " "Reihe waren." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Euren Helden zurückziehen und Eure Kreaturen aufgeben. Euer Held kann erneut " "rekrutiert werden, allerdings hat er dann den Status eines Anfängers." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Kapitulieren kostet Gold. Wenn Ihr jedoch das Lösegeld bezahlt, könnt Ihr " "den Helden und alle überlebende Kreaturen wieder rekrutieren." msgid "Open Hero Screen to view full information about the hero." msgstr "" "Öffne den Heldenbildschirm, um alle Informationen über den Helden anzuzeigen." msgid "Return to the battle." msgstr "Zurück in die Schlacht." msgid "Not enough gold (%{gold})" msgstr "Nicht genug Gold (%{gold})" msgid "%{name} states:" msgstr "%{name} erklärt:" msgid "Captain of %{name} states:" msgstr "Hauptmann von %{name}:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Ich akzeptiere Eure Kapitulation und gewähre Euch einen sicheren " "Truppenabzug für den Preis von %{price} Gold.\"" msgid "View %{monster} info" msgstr "%{monster}-Infos anzeigen" msgid "Fly %{monster} here" msgstr "%{monster} hierhin fliegen" msgid "Move %{monster} here" msgstr "%{monster} hierher bewegen" msgid "Shoot %{monster}" msgstr "Schieße auf %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 Schuss übrig)" msgstr[1] "(%{count} Schüsse übrig)" msgid "Attack %{monster}" msgstr "%{monster} angreifen" msgid "Turn %{turn}" msgstr "Runde %{turn}" msgid "Teleport here" msgstr "Hierhin teleportieren" msgid "Invalid teleport destination" msgstr "Ungültiges Teleporter-Ziel" msgid "Cast %{spell} on %{monster}" msgstr "%{spell} auf %{monster} zaubern" msgid "Cast %{spell}" msgstr "Zaubern %{spell}" msgid "Select spell target" msgstr "Ziel des Zaubers auswählen" msgid "View Ballista info" msgstr "Ballista-Infos anzeigen" msgid "Ballista" msgstr "Ballista" #, fuzzy msgid "Automatic combat modes" msgstr "Autokampf" #, fuzzy msgid "Automatic Combat Modes" msgstr "Autokampf" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "System-Optionen anpassen" msgid "Allows you to customize the combat screen." msgstr "Ermöglicht es, den Kampfbildschirm anzupassen." msgid "System Options" msgstr "System-Optionen" msgid "Skip this unit" msgstr "Diesen Zug aussetzen" msgid "Skip" msgstr "Aussetzen" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Aktive Kreatur überspringen. Die Einheit, die am Zug ist, setzt aus und darf " "erst in der nächsten Runde wieder losziehen." msgid "View Captain's options" msgstr "Optionen des Hauptmanns anzeigen" msgid "View Hero's options" msgstr "Optionen für den Helden anzeigen" msgid "View opposing Captain" msgstr "Ansicht des gegnerischen Hauptmanns" msgid "View opposing Hero" msgstr "Gegnerischen Helden anzeigen" msgid "Hide logs" msgstr "Protokolle ausblenden" msgid "Show logs" msgstr "Protokolle einblenden" msgid "Message Bar" msgstr "Nachrichtenleiste" msgid "Shows the results of individual monster's actions." msgstr "Ergebnisse der Aktionen der einzelnen Monster anzeigen." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Wollt Ihr den automatischen Kampfmodus wirklich aktivieren?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Seid Ihr sicher, dass Ihr den Kampf im Automodus beenden möchtet?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Erlaubt dem Computer, den Kampf für Euch auszuführen." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Autokampf" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Autokampf" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} setzt den Zug aus." msgstr[1] "%{name} setzt den Zug aus." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} verursacht %{damage} Schaden." msgstr[1] "%{attacker} verursachen %{damage} Schaden." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 Kreatur stirbt." msgstr[1] "%{count} Kreaturen sterben." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} stirbt." msgstr[1] "%{count} %{defender} sterben." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 Seele wird aufgenommen." msgstr[1] "%{count} Seelen werden aufgenommen." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} wird wiederbelebt." msgstr[1] "%{count} %{unit} werden wiederbelebt." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Hat %{monster}: von [%{src}] nach [%{dst}] verschoben." #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "Die %{name} widerstehen dem Zauber!" msgstr[1] "Die %{name} widerstehen dem Zauber!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} zaubert %{spell} auf die %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} zaubert %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "Der %{spell} verursacht %{damage} an einer untoten Kreatur." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "Der %{spell} verursacht %{damage} an allen Untoten." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "Der %{spell} verursacht %{damage} Schaden, %{count} Kreaturen sterben." msgid "The %{spell} does %{damage} damage." msgstr "Der %{spell} verursacht %{damage} Schaden." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "Der %{spell} fügt einer lebenden Kreatur %{damage} Schaden zu." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "Der %{spell} verursacht %{damage} Schaden an allen lebenden Kreaturen." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "%{target} wegen des Angriffs von %{attacker} geblendet!" msgstr[1] "%{target} wegen des Angriffs von %{attacker} geblendet!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "Der Blick des %{attacker} verwandelt das %{target} in Stein!" msgstr[1] "Der Blick des %{attacker} verwandelt das %{target} in Stein!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "Der Fluch des %{attacker} fällt auf das %{target}!" msgstr[1] "Der Fluch des %{attacker} fällt auf das %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "Die %{target} sind durch den %{attacker} gelähmt!" msgstr[1] "Die %{target} sind durch den %{attacker} gelähmt!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" "Der %{attacker} verbannt alle guten Zaubersprüche auf Eurem %{target}!" msgstr[1] "" "Der %{attacker} verbannt alle guten Zaubersprüche auf Eurem %{target}!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "Der %{attacker} hat %{spell} auf %{target} gewirkt!" msgstr[1] "Der %{attacker} hat %{spell} auf %{target} gewirkt!" msgid "Bad luck descends on the %{attacker}." msgstr "%{attacker} wird vom Pech verfolgt." msgid "Good luck shines on the %{attacker}." msgstr "Glück fällt auf %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Durch Hohe Moral können die %{monster} erneut anzugreifen." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Aufgrund schlechter Moral erstarren die %{monster} vor Angst." msgid "%{tower} does %{damage} damage." msgstr "%{tower} verursacht %{damage} Schaden." msgid "The mirror image is created." msgstr "Das Spiegelbild wurde erstellt." msgid "The mirror image is destroyed!" msgstr "Das Spiegelbild ist zerstört!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Seid Ihr sicher, dass Ihr den Autokampf unterbrechen möchtet?" msgid "Error" msgstr "Fehler" msgid "No spells to cast." msgstr "Keine Zaubersprüche zur Verfügung." msgid "Are you sure you want to retreat?" msgstr "Wollt Ihr Euch wirklich zurueckziehen?" msgid "Retreat disabled" msgstr "Rückzug deaktiviert" msgid "Surrender disabled" msgstr "Kapitulation deaktiviert" msgid "Damage: %{max}" msgstr "Schaden: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Schäden: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Sterben: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Sterben: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Durch die Beobachtung mit seinen Adleraugen ist %{name} in der Lage, den " "Zauberspruch %{spell} zu erlernen." msgid "Human" msgstr "Mensch" msgid "AI" msgstr "KI" #, fuzzy msgid "Start" msgstr "Neustart" #, fuzzy msgid "Start the battle." msgstr "Zurück in die Schlacht." msgid "Exit" msgstr "Verlassen" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Bitte wählt einen anderen Helden aus." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{name1} trifft %{name2}" msgid "Monsters" msgstr "Monster" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Linker Turm" msgid "Right Turret" msgstr "Rechter Turm" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} feuert mit der Kraft von %{count} Bogenschützen" msgid "each with a +%{attack} bonus to their attack skill." msgstr "jeder mit einem +%{attack} Bonus auf seine Angriffsfähigkeit." msgid "The %{name} is destroyed." msgstr "%{name} ist zerstört." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} steht von den Toten auf!" msgstr[1] "%{count} %{name} stehen von den Toten auf!" msgid "Dwarven Alliance" msgstr "Zwergen-Allianz" msgid "Sorceress Guild" msgstr "Gilde der Zauberinnen" msgid "Necromancer Guild" msgstr "Totenbeschwörer-Gilde" msgid "Ogre Alliance" msgstr "Oger-Allianz" msgid "Dwarfbane" msgstr "Zwergenfluch" msgid "Dragon Alliance" msgstr "Drachen-Allianz" msgid "Elven Alliance" msgstr "Elfen-Bündnis" msgid "Kraeger defeated" msgstr "Kraeger besiegt" msgid "Wayward Son" msgstr "Eigensinniger Sohn" msgid "Uncle Ivan" msgstr "Onkel Ivan" msgid "Annexation" msgstr "Annektion" msgid "Force of Arms" msgstr "Macht des Schwerts" msgid "Save the Dwarves" msgstr "Rettet die Zwerge" msgid "Carator Mines" msgstr "Die Carator-Minen" msgid "Turning Point" msgstr "Wendepunkt" msgid "scenarioName|Defender" msgstr "Verteidiger" msgid "Corlagon's Defense" msgstr "Corlagons Kampf" msgid "The Crown" msgstr "Die Krone" msgid "The Gauntlet" msgstr "Fehdehandschuh" msgid "Betrayal" msgstr "Verrat" msgid "Final Justice" msgstr "Gerechtigkeit" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland braucht Euch, um die Fürsten in der Nähe seiner Burg zu besiegen und " "um die Rebellion gegen Archibald zu beginnen. Diese sind nicht miteinander " "verbündet, so dass sie die meiste Zeit damit verbringen werden, sich " "gegenseitig zu bekämpfen. Besiegt alle Burgen und Helden für den Sieg." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Die örtlichen Fürsten weigern sich, Roland die Treue zu schwören, und müssen " "daher unterworfen werden. Sie sind wohlhabend und mächtig, macht Euch auf " "einen harten Kampf gefasst. Für den Sieg müsst Ihr alle Burgen einnehmen." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Eure Aufgabe ist es, die Zwerge gegen Archibalds Streitkräfte zu " "verteidigen. Erobert alle feindlichen Städte und Burgen, um zu gewinnen, und " "achtet darauf, nicht alle Zwergenstädte auf einmal zu verlieren, denn sonst " "hat der Feind gewonnen." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Ihr werdet vier verbündeten Feinden in einem direkten Kampf um Ressourcen " "und Schätze gegenüberstehen. Erobert alle feindlichen Burgen für den Sieg." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Eure Feinde haben sich gegen Euch verbündet und starten ganz in Eurer Naehe. " "Seid also bereit für einen baldigen Kampf. Ihr müsst alle vier Burgen in dem " "schmalen Tal kontrollieren, um zu gewinnen." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Die Gilde der Zauberinnen von Noraston hat Roland um Hilfe gegen einen " "Angriff von Archibalds Verbündeten ersucht. Erobert alle feindlichen Burgen, " "um zu gewinnen, und verliert Noraston nicht, oder Ihr verliert das Szenario. " "(Hinweis: Auf einer Insel im Ozean befindet sich eine feindliche Burg.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Stellt eine größtmögliche Armee auf und erobert die feindliche Burg " "innerhalb von 8 Wochen. Euch steht nur ein Feind gegenueber, aber Ihr habt " "einen sehr weiten Weg zurückzulegen. Alle Eure bis zum Ende des Szenarios " "überlebenden Truppen begleiten Euch in die letzte Schlacht." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Findet die Krone, bevor Archibalds Helden sie finden. Roland wird die Krone " "für den letzten Kampf gegen Archibald benötigen." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Drei verbündete Feinde stehen zwischen Euch und dem Sieg, darunter Lord " "Corlagon. Roland befindet sich in einer Burg im Nordwesten, wenn sie an den " "Feind fällt, ist alles verloren. Denkt daran, dass Lord Corlagons " "Gefangennahme ihn daran hindern wird, im letzten Szenario gegen Euch zu " "kämpfen." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Dies ist die letzte Schlacht. Sowohl Ihr als auch Eure Feinde sind bis an " "die Zähne bewaffnet, und alle sind gegen Euch verbündet. Nehmt Archibald " "gefangen und der Krieg ist beendet!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Wenn Ihr die Seiten wechselt, habt Ihr drei Schlösser gegen eines des " "Feindes. Diese Schlacht wird für den Rest des Krieges die einfachste sein... " "Verräter." msgid "Barbarian Wars" msgstr "Barbaren-Kriege" msgid "First Blood" msgstr "Erstes Blut" msgid "Necromancers" msgstr "Totenbeschwörer" msgid "Slay the Dwarves" msgstr "Schlachtet die Zwerge" msgid "Country Lords" msgstr "Landesfürsten" msgid "Dragon Master" msgstr "Drachenmeister" msgid "Rebellion" msgstr "Rebellion" msgid "Apocalypse" msgstr "Apocalypse" msgid "Greater Glory" msgstr "Größte Ehre" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "König Archibald braucht Euch, um die drei Feinde in dieser Region zu " "besiegen. Diese sind nicht miteinander verbündet, also werden sie die meiste " "Zeit miteinander kämpfen. Ihr werdet gewinnen, wenn Ihr alle feindlichen " "Burgen kontrolliert und alle Helden besiegt." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Ihr müsst die Barbarenstämme des Nordens vereinen, indem Ihr sie erobert. " "Wie in der vorherigen Mission sind die Feinde nicht miteinander verbündet, " "aber sie haben mehr Ressourcen zur Verfügung. Ihr werdet gewinnen, wenn Ihr " "alle feindlichen Burgen kontrolliert und alle Helden besiegt." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Gutmenschen-Zauberer haben die Burg der Nekromanten eingenommen. Ihr müsst " "sie zurückerobern, um den Sieg zu erringen. Obwohl Ihr mit einer mächtigen " "Armee startet, habt Iht keine Burg und müsst innerhalb von 7 Tagen eine " "einnehmen, sonst verliert Ihr die Schlacht. (Tipp: Die nächstgelegene Burg " "ist im Südosten)." msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Die Zwerge müssen unterworfen werden, bevor sie sich in König Archibalds " "Pläne einmischen können. Rolands Streitkräfte haben mehr als einen Helden " "und viele Städte. Seid also bereit aus verschiedenen Richtungen angegriffen " "zu werden. Ihr müsst alle feindlichen Städte und Burgen erobern, um den Sieg " "zu erringen. " msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Ihr müsst einen Bauernaufstand niederschlagen, der von Rolands Streitkräften " "angeführt wird. Alle sind gegen Euch verbündet, aber Ihr habt Lord Corlagon, " "einen erfahrenen Helden, der Euch helfen wird. Erobert alle gegnerischen " "Burgen, um zu gewinnen." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "In dieser Mission sind zwei Feinde gegen Euch verbündet. Beide sind gut " "bewaffnet und versuchen Euch von ihrer Insel zu vertreiben. Vermeidet sie " "und erobert die Drachenstadt, um zu gewinnen." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Euer Auftrag lautet, die Landesfürsten zu bezwingen, die Roland die Treue " "geschworen haben. Alle feindlichen Burgen sind gegen Euch vereint. Da Ihr " "ohne eine Burg beginnt, müsst Ihr Euch beeilen, eine vor dem Ende der Woche " "zu erobern. Erobert alle feindlichen Burgen, um zu gewinnen." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Findet die Krone, bevor Rolands Helden sie finden. Archibald wird die Krone " "für den letzten Kampf gegen Roland brauchen." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Dies ist die letzte Schlacht. Sowohl Ihr als auch Euer Feind sind bis an die " "Zähne bewaffnet, und alle sind gegen Euch verbündet. Nehmt Roland gefangen, " "um den Krieg zu gewinnen, und passt auf, dass Ihr Archibald nicht verliert! " msgid "Arrow's Flight" msgstr "Flug des Pfeils" msgid "Island of Chaos" msgstr "Insel des Chaos" msgid "The Abyss" msgstr "Der Abgrund" msgid "Uprising" msgstr "Aufstand" msgid "Aurora Borealis" msgstr "Aurora Borealis" msgid "Betrayal's End" msgstr "Das Ende des Betrugs" msgid "Corruption's Heart" msgstr "Das Herz der Korruption" msgid "The Giant's Pass" msgstr "Der Pass des Riesen" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Unterwerft die widerspenstigen Landesfürsten, um dem Imperium Gelegenheiten " "für Operationen in der Region zu geben." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Beseitigt jede Opposition in diesem Gebiet. Dann wedet ihr das erste Teil " "des Artefakts bekommen." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Die Zauberinnen im Nordosten rebellieren! Zum Wohle des Imperiums müsst Ihr " "auf Eurem Weg in die Berge den schwachen Aufstand niederschlagen." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Auf Eure Ankunft vorbereitet, hat Kraeger Streitkräfte von Totenbeschwörern " "aufgestellt, die Eure Suche vereiteln sollen. Erobert die Burg von Scabsdale " "vor dem ersten Tag der dritten Woche, oder die Totenbeschwörer werden zu " "stark für Euch sein." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Der barbarische Despot in diesem Gebiet weiß noch nichts von Eurer " "Anwesenheit. Baut schnell Eure Streitkräfte auf, bevor Ihr entdeckt und " "angegriffen werdet! Sichert die Region, indem Ihr alle feindlichen Truppen " "unterwerft." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Das Imperium ist in dieser Region schwach. Ihr werdet nicht alle " "Streitkräfte in diesem Gebiet völlig unterwerfen können, also nehmt, was Ihr " "könnt, bevor es Vergeltung gibt. Denkt daran, Euer wahres Ziel ist, den Helm " "von Anduran zu erlangen." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Eliminiert Kraeger zum Wohle des Imperiums." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Endlich habt Ihr die Gelegenheit und die Möglichkeit, das Imperium von dem " "Übel der Totenbeschwörer zu befreien. Löscht sie vollständig aus, und Ihr " "werdet bis in alle Zeiten als Held gefeiert werden." msgid "Border Towns" msgstr "Grenzstädte" msgid "Conquer and Unify" msgstr "Erobern und vereinen" msgid "Crazy Uncle Ivan" msgstr "Der verrückte Onkel Ivan" msgid "The Wayward Son" msgstr "Der eigensinnige Sohn" msgid "Ivory Gates" msgstr "Ivory Gates" msgid "The Elven Lands" msgstr "Das Land der Elfen" msgid "The Epic Battle" msgstr "Die heldenhafte Schlacht" msgid "The Southern War" msgstr "Der Südkrieg" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Erobert und vereinigt alle gegnerischen Stämme. Verliert nicht den Helden " "Jarkonas, dem Urvater aller Nachkommen." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Euer Rivale, das Königreich Harondale, greift schwache Städte an Eurer " "Grenze an! Erholt Euch von ihrem ersten Schlag und zerschlagt sie " "vollständig!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Findet Euren eigensinnigen Sohn Joseph, von dem gemunkelt wird, dass er in " "den trostlosen Ländern lebt. Findet ihn vor dem ersten Tag des dritten " "Monats oder er wird Eurer Familie nicht mehr helfen können." #, fuzzy msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Rettet Euren verrückten Onkel Ivan. Findet ihn vor dem ersten Tag des " "vierten Monats oder er wird keine Hilfe für Euer Königreich sein." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Vernichtet die Barbaren, die die Südgrenze Eures Königreichs angreifen! " "Holet Eure gefallenen Städte zurück und dringt dann in das " "Dschungelkönigreich ein. Lasst keinen Feind am Leben." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Erobert die Burg Ivory Gates zurück, die durch Verrat gefallen ist." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Gewinnet die Gunst der Elfen. Sie werden nicht zulassen, dass Bäume gefällt " "werden, und werden Euch daher alle 2 Wochen Holz schicken. Beendet Eure " "Mission vor dem ersten Tag des siebten Monats, oder das Königreich wird " "fallen." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Dies ist die letzte Schlacht gegen das rivalisierendes Königreich Harondale. " "Beseitigt alle Feinde und verliert nicht Euren Helden Jarkonas VI." msgid "Fount of Wizardry" msgstr "Der Zauberbrunnen" msgid "Power's End" msgstr "Das Ende der Macht" msgid "The Eternal Scrolls" msgstr "Die ewigen Schriftrollen" msgid "The Shrouded Isles" msgstr "Die Nebelinseln" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Eure Mission ist es, die kriegerischen Magier auf den magischen Nebelinseln " "zu besiegen. Die Erfüllung dieser Aufgabe wird Euch die Chance auf einen " "Kampf gegen Eure Rivalen geben." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Der Standort der großen Bibliothek ist entdeckt worden! Schlagt Euch dorthin " "durch und erlangt die Herrschaft über die Stadt Chronos, in der sie sich " "befindet." #, fuzzy msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Findet die Kugel der Aufhebung, von der gesagt wird, dass sie in diesem Land " "begraben ist. Hinweise zum Ort stehen auf Steinobelisken geschrieben. Findet " "die Kugel vor dem ersten Tag des sechsten Monats, oder Eure Rivalen werden " "die Quelle vor Euch gefunden haben." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Ihr müsst die Kontrolle über die Burg der Magie erlangen, in der sich die " "Quelle der Zauberei befindet. Tut dies und Euer Sieg wird der Höchste sein." msgid "Blood is Thicker" msgstr "Blut ist dicker" msgid "King and Country" msgstr "König und Vaterland" msgid "Pirate Isles" msgstr "Pirateninseln" msgid "Stranded" msgstr "Gestrandet" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Erobert die Stadt auf der Insel vor der Südostküste, um dort ein Boot zu " "bauen um damit zurück aufs Festland zu gelangen. Verliert dabei nicht den " "Helden Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Findet und besiegt Martine, die Piratenanführerin, die in der Piratenbucht " "lebt. Verliert Gallavant nicht oder Eure Suche wird zu Ende sein." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Vernichtet alle anderen Streitkräfte, die sich der Herrschaft von Lord " "Alberon widersetzen. Gallavant darf nicht fallen." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Stürzt die tief verwurzelte Monarchie von Lord Alberon und beansprucht das " "ganze Land in Eurem Namen. Gallavant darf nicht fallen." msgid " bane" msgstr " Fluch" msgid " alliance" msgstr " Allianz" msgid "Carry-over forces" msgstr "Übertragungskräfte" msgid " bonus" msgstr " Bonus" msgid " defeated" msgstr " besiegt" msgid " will always run away from your army." msgstr " werden immer vor Eurer Armee weglaufen." msgid " will be willing to join your army." msgstr " bereit sein werden, sich Eurer Armee anzuschließen." #, fuzzy msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "Das Artefakt \"%{artifact}\" wird in das Szenario übernommen." #, fuzzy msgid "The army will be carried over in the campaign." msgstr "Die Armee wird über das Szenario mitgenommen." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Das Königreich wird jeden Tag über +%{count} %{resource} verfügen." #, fuzzy msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "\"%{spell}\" wird in das Szenario übernommen." #, fuzzy msgid "%{hero} can be hired during scenarios." msgstr "%{hero} kann in dem Szenario angeheuert werden." #, fuzzy msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" "%{hero} wurde besiegt und wird in den folgenden Szenarien nicht mehr " "erscheinen." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Die Zwerge erkennen ihren Verbündeten und schließen sich gerne Euren Kräften " "an." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Die Oger erkennet Euch als den Zwergenfluch und humpeln zu Euch hinüber, um " "sich Euch anzuschließen." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Die Drachen, knurrend und grollend, stimmen zu, sich mit Euch, ihrem " "\"Verbündeten\", zusammenzuschließen." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Als Ihr Euch der Gruppe der Elfen nähert, macht ihr Anführer sie alle auf " "sich aufmerksam. Er ruft ihnen zu: \"Wer von euch ist tapfer genug, sich " "unserem furchtlosen Verbündeten anzuschließen?\" Die Gruppe explodiert vor " "Jubel, als sie hinüberstürmen um in Euren Reihen aufgenommen zu werden." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Die Zwerge grüßen Euch: \"Jeder Freund Rolands ist ein Freund von uns. Ihr " "könnt durchgehen.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Die Oger geben ein anerkennendes Grunzen von sich: \"Archibalds Verbündete " "dürfen durchgehen.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Die Drachen sehen Euch zu und rufen. \"Unser Bündnis mit Archibald zwingt " "uns, uns Euch anzuschließen. Leider habt Ihr keinen Platz. Das ist schade! " "\" Schnell zerstreuen sie sich." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Die Elfen stehen stramm, als Ihr Euch ihnen nähert. Ihr Anführer ruft Euch " "zu: \"Lasst uns Euer Vorankommen nicht behindern, Verbündeter! Zieht weiter, " "und möge der Sieg Euer sein.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Zwergenfluch!!!!, rennt um euer Leben.\"" msgid "campaignBonus|Animate Dead" msgstr "Tote beleben" msgid "campaignBonus|Chain Lightning" msgstr "Kettenblitzstrahl" msgid "campaignBonus|Fireblast" msgstr "Feuerstoß" msgid "campaignBonus|Mass Curse" msgstr "Massenfluch" msgid "campaignBonus|Mass Haste" msgstr "Masseneile" msgid "campaignBonus|Mirror Image" msgstr "Spiegelbild" msgid "campaignBonus|Resurrect" msgstr "Tote beleben" msgid "campaignBonus|Steelskin" msgstr "Stahlhaut" msgid "campaignBonus|Summon Earth" msgstr "Erdwesen beschwören" msgid "campaignBonus|View Heroes" msgstr "Helden anzeigen" msgid "campaignBonus|Ballista" msgstr "Ballista" msgid "campaignBonus|Black Pearl" msgstr "Schwarze Perle" msgid "campaignBonus|Caster's Bracelet" msgstr "Zauberarmband" msgid "campaignBonus|Defender Helm" msgstr "Verteidigungshelm" msgid "campaignBonus|Breastplate" msgstr "Brustpanzer" msgid "campaignBonus|Dragon Sword" msgstr "Drachenschwert" msgid "campaignBonus|Fizbin Medal" msgstr "Fizbin des Pechs" msgid "campaignBonus|Foremost Scroll" msgstr "Herausragendste Schriftrolle" msgid "campaignBonus|Gauntlets" msgstr "Gepanzerter Handschuh" msgid "campaignBonus|Hideous Mask" msgstr "Scheußliche Maske" msgid "campaignBonus|Mage's Ring" msgstr "Ring des Magiers" msgid "campaignBonus|Major Scroll" msgstr "Grosse Schriftrolle" msgid "campaignBonus|Medal of Honor" msgstr "Medaille der Ehre" msgid "campaignBonus|Medal of Valor" msgstr "Medaille der Tapferkeit" msgid "campaignBonus|Minor Scroll" msgstr "Kleine Schriftrolle" msgid "campaignBonus|Nomad Boots" msgstr "Nomadenstiefel" msgid "campaignBonus|Power Axe" msgstr "Power-Axt" msgid "campaignBonus|Spiked Shield" msgstr "Stachelschild" msgid "campaignBonus|Stealth Shield" msgstr "Tarnkappenschild" msgid "campaignBonus|Tax Lien" msgstr "Steuererklärung" msgid "campaignBonus|Thunder Mace" msgstr "Donnerstab" msgid "campaignBonus|Traveler's Boots" msgstr "Reisestiefel" msgid "campaignBonus|White Pearl" msgstr "Weisse Perle" msgid "campaignBonus|Basic Archery" msgstr "Einfach Bogen" msgid "campaignBonus|Advanced Archery" msgstr "Verbessert Bogen" msgid "campaignBonus|Expert Archery" msgstr "Meisterhaft Bogen" msgid "campaignBonus|Basic Ballistics" msgstr "Einfache Ballistik" msgid "campaignBonus|Advanced Ballistics" msgstr "Verbesserte Ballistik" msgid "campaignBonus|Expert Ballistics" msgstr "Meisterhafte Ballistik" msgid "campaignBonus|Basic Diplomacy" msgstr "Einfache Diplomatie" msgid "campaignBonus|Advanced Diplomacy" msgstr "Verbesserte Diplomatie" msgid "campaignBonus|Expert Diplomacy" msgstr "Meisterhafte Diplomatie" msgid "campaignBonus|Basic Eagle Eye" msgstr "Einfaches Adlerauge" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Verbessertes Adlerauge" msgid "campaignBonus|Expert Eagle Eye" msgstr "Meisterhaftes Adlerauge" msgid "campaignBonus|Basic Estates" msgstr "Einfach Grundbesitz" msgid "campaignBonus|Advanced Estates" msgstr "Verbessert Grundbesitz" msgid "campaignBonus|Expert Estates" msgstr "Meisterhaft Grundbesitz" msgid "campaignBonus|Basic Leadership" msgstr "Einfache Führung" msgid "campaignBonus|Advanced Leadership" msgstr "Verbesserte Führung" msgid "campaignBonus|Expert Leadership" msgstr "Meisterhafte Führung" msgid "campaignBonus|Basic Logistics" msgstr "Einfache Logistik" msgid "campaignBonus|Advanced Logistics" msgstr "Verbesserte Logistik" msgid "campaignBonus|Expert Logistics" msgstr "Meisterhafte Logistik" msgid "campaignBonus|Basic Luck" msgstr "Einfaches Glück" msgid "campaignBonus|Advanced Luck" msgstr "Verbessertes Glück" msgid "campaignBonus|Expert Luck" msgstr "Meisterhaftes Glück" msgid "campaignBonus|Basic Mysticism" msgstr "Einfache Mystik" msgid "campaignBonus|Advanced Mysticism" msgstr "Verbesserte Mystik" msgid "campaignBonus|Expert Mysticism" msgstr "Meisterhafte Mystik" msgid "campaignBonus|Basic Navigation" msgstr "Einfache Navigation" msgid "campaignBonus|Advanced Navigation" msgstr "Verbesserte Navigation" msgid "campaignBonus|Expert Navigation" msgstr "Meisterhafte Navigation" msgid "campaignBonus|Basic Necromancy" msgstr "Einfache Nekromantie" msgid "campaignBonus|Advanced Necromancy" msgstr "Verbesserte Nekromantie" msgid "campaignBonus|Expert Necromancy" msgstr "Meisterhafte Nekromantie" msgid "campaignBonus|Basic Pathfinding" msgstr "Einfaches Pfadfinden" msgid "campaignBonus|Advanced Pathfinding" msgstr "Verbessert Pfadfinden" msgid "campaignBonus|Expert Pathfinding" msgstr "Meisterhaft Pfadfinden" msgid "campaignBonus|Basic Scouting" msgstr "Einfaches Spähen" msgid "campaignBonus|Advanced Scouting" msgstr "Verbessertes Spähen" msgid "campaignBonus|Expert Scouting" msgstr "Meisterhaftes Spähen" msgid "campaignBonus|Basic Wisdom" msgstr "Einfache Weisheit" msgid "campaignBonus|Advanced Wisdom" msgstr "Verbesserte Weisheit" msgid "campaignBonus|Expert Wisdom" msgstr "Meisterhafte Weisheit" #, fuzzy msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" "Der Hauptheld hat zu Beginn des Szenarios ein \"%{artifact}\"-Artefakt." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Das Königreich erhält zu Beginn des Szenarios %{amount} zusätzliche " "%{resource}." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Das Königreich hat zu Beginn des Szenarios %{amount} weniger %{resource}." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Der Hauptheld hat zu Beginn des Szenarios %{count} %{monster}." #, fuzzy msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "Der Hauptheld hat zu Beginn des Szenarios einen \"%{spell}\"-Zauber." #, fuzzy msgid "The starting alignment of the scenario will be %{race}." msgstr "Die Startrasse des Szenarios ist %{race}." #, fuzzy msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "Der Hauptheld hat zu Beginn des Szenarios zusätzliche %{count} %{skill}." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Der Hauptheld hat zu Beginn des Szenarios %{skill}." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" msgid "Price of Loyalty" msgstr "Der Preis der Loyalität" msgid "Voyage Home" msgstr "Heimreise" msgid "Wizard's Isle" msgstr "Die Insel der Zauberer" msgid "Descendants" msgstr "Nachkommen" msgid "Cannot build. You have already built here today." msgstr "Kann nicht gebaut werden. Ihr habt an diesem Tag hier bereits gebaut." msgid "For this action it is necessary to build a castle first." msgstr "Für diese Aktion ist es notwendig, zuerst eine Burg zu bauen." msgid "The %{building} produces %{monster}." msgstr "Der %{building} produziert %{monster}." msgid "Requires:" msgstr "Erfordert:" msgid "Exit this menu without doing anything." msgstr "Dieses Menü verlassen." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "" "%{name} kann nicht gebaut werden, weil keine Gewässer in der Nähe sind." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "%{name} ist zu teuer." #, fuzzy msgid "The %{name} is already built." msgstr "%{name} ist bereits gebaut." #, fuzzy msgid "Cannot build the %{name}." msgstr "Kann %{name} nicht bauen." msgid "Build %{name}." msgstr "%{name} Bauen." msgid "Blackridge" msgstr "Blackridge" msgid "Hillstone" msgstr "Hillstone" msgid "Pinehurst" msgstr "Pinehurst" msgid "Whiteshield" msgstr "Whiteshield" msgid "Woodhaven" msgstr "Woodhaven" msgid "Blackwind" msgstr "Blackwind" msgid "Bloodreign" msgstr "Bloodreign" msgid "Dragontooth" msgstr "Dragontooth" msgid "Greywind" msgstr "Greywind" msgid "Portsmith" msgstr "Portsmith" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Middle Gate" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "Baywatch" msgid "Fountainhead" msgstr "Fountainhead" msgid "Vertigo" msgstr "Vertigo" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Winterkill" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Lakeside" msgid "Nightshadow" msgstr "Nightshadow" msgid "Olympus" msgstr "Olympus" msgid "Sandcaster" msgstr "Sandcaster" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "New Dawn" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Big Oak" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antioch" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Roc Haven" msgid "South Mill" msgstr "South Mill" msgid "Weed Patch" msgstr "Weed Patch" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Hilltop" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Westfork" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "Elk's Head" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Blackburn" msgid "Blacksford" msgstr "Blacksford" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Pig's Eye" msgid "Viper's Nest" msgstr "Viper's Nest" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Timberhill" msgid "Troy" msgstr "Troy" msgid "Forder Oaks" msgstr "Forder Oaks" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Quick Silver" msgid "Westmoor" msgstr "Westmoor" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Rekrutieren nicht möglich - ein Held steht bereits in dieser Stadt." msgid "Cannot recruit - you have too many Heroes." msgstr "Rekrutieren nicht möglich - Sie haben zu viele Helden." #, fuzzy msgid "Cannot afford a Hero." msgstr "Ihr könnt Euch keinen Helden leisten." msgid "There is no room in the garrison for this army." msgstr "Es gibt keinen Platz in der Garnison für diese Armee." msgid "Fortifications" msgstr "Befestigungen" msgid "Farm" msgstr "Farm" msgid "Thatched Hut" msgstr "Strohhütte" msgid "Archery Range" msgstr "Schießplatz" msgid "Upg. Archery Range" msgstr "Aufg. Schießplatz" msgid "Blacksmith" msgstr "Schmiede" msgid "Upg. Blacksmith" msgstr "Aufg. Schmiede" msgid "Armory" msgstr "Waffenfabrik" msgid "Upg. Armory" msgstr "Aufg. Waffenfabrik" msgid "Jousting Arena" msgstr "Turnierplatz" msgid "Upg. Jousting Arena" msgstr "Aufg. Turnierplatz" msgid "Cathedral" msgstr "Kathedrale" msgid "Upg. Cathedral" msgstr "Aufg. Kathedrale" msgid "Coliseum" msgstr "Kolosseum" msgid "Garbage Heap" msgstr "Müllhaufen" msgid "Hut" msgstr "Hütte" msgid "Stick Hut" msgstr "Stockhütte" msgid "Upg. Stick Hut" msgstr "Aufg. Stockhütte" msgid "Den" msgstr "Bau" msgid "Adobe" msgstr "Lehmsteinhaus" msgid "Upg. Adobe" msgstr "Aufg. Lehmsteinhaus" msgid "Bridge" msgstr "Brücke" msgid "Upg. Bridge" msgstr "Aufg. Brücke" msgid "Pyramid" msgstr "Pyramide" msgid "Rainbow" msgstr "Regenbogen" msgid "Crystal Garden" msgstr "Kristallgarten" msgid "Treehouse" msgstr "Baumhaus" msgid "Cottage" msgstr "Landhaus" msgid "Upg. Cottage" msgstr "Aufg. Landhaus" msgid "Stonehenge" msgstr "Stonehenge" msgid "Upg. Stonehenge" msgstr "Aufg. Stonehenge" msgid "Fenced Meadow" msgstr "Eingezäunte Wiese" msgid "sorceress|Red Tower" msgstr "Roter Turm" msgid "Dungeon" msgstr "Burgverlies" msgid "Waterfall" msgstr "Wasserfall" msgid "Cave" msgstr "Höhle" msgid "Crypt" msgstr "Gruft" msgid "Nest" msgstr "Nest" msgid "Maze" msgstr "Labyrinth" msgid "Upg. Maze" msgstr "Aufg. Labyrinth" msgid "Swamp" msgstr "Sumpf" msgid "Green Tower" msgstr "Grüner Turm" msgid "warlock|Red Tower" msgstr "Roter Turm" msgid "Black Tower" msgstr "Schwarzer Turm" msgid "Library" msgstr "Bibliothek" msgid "Orchard" msgstr "Obstgarten" msgid "Habitat" msgstr "Wohnhaus" msgid "Pen" msgstr "Verschlag der Eber" msgid "Foundry" msgstr "Gießerei" msgid "Upg. Foundry" msgstr "Aufg. Gießerei" msgid "Cliff Nest" msgstr "Felsennest" msgid "Ivory Tower" msgstr "Elfenbeinturm" msgid "Upg. Ivory Tower" msgstr "Aufg. Elfenbeinturm" msgid "Cloud Castle" msgstr "Wolkenburg" msgid "Upg. Cloud Castle" msgstr "Aufg. Wolkenburg" msgid "Storm" msgstr "Sturm" msgid "Skull Pile" msgstr "Schädelhaufen" msgid "Excavation" msgstr "Ausgrabung" msgid "Graveyard" msgstr "Friedhof" msgid "Upg. Graveyard" msgstr "Aufg. Friedhof" msgid "Upg. Pyramid" msgstr "Aufg. Pyramide" msgid "Mansion" msgstr "Spukhaus" msgid "Upg. Mansion" msgstr "Aufg. Spukhaus" msgid "Mausoleum" msgstr "Mausoleum" msgid "Upg. Mausoleum" msgstr "Aufg. Mausoleum" msgid "Laboratory" msgstr "Laboratorium" msgid "Shrine" msgstr "Schrein" #, fuzzy msgid "Special" msgstr "Nichts besonderes" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Halblinge" #, fuzzy msgid "Dwelling 2" msgstr "Halblinge" #, fuzzy msgid "Upg. Dwelling 2" msgstr "Halblinge" #, fuzzy msgid "Dwelling 3" msgstr "Halblinge" #, fuzzy msgid "Upg. Dwelling 3" msgstr "Halblinge" #, fuzzy msgid "Dwelling 4" msgstr "Halblinge" #, fuzzy msgid "Upg. Dwelling 4" msgstr "Halblinge" #, fuzzy msgid "Dwelling 5" msgstr "Halblinge" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Halblinge" #, fuzzy msgid "Dwelling 6" msgstr "Halblinge" #, fuzzy msgid "Upg. Dwelling 6" msgstr "Halblinge" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Die Befestigungen erhöhen die Stärke der Mauern, und es dauert länger die " "Mauern zu durchbrechen." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Die Farm erhöht die Produktion von Bauern um %{count} pro Woche." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Das Kolosseum bietet den verteidigenden Truppen ein inspirierendes Spektakel " "und hebt ihre Moral während des Kampfes um zwei." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" "Der Müllhaufen erhöht die Produktion von Goblins um %{count} pro Woche." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Der Regenbogen erhöht das Glück der verteidigenden Einheiten um zwei." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" "Der Kristallgarten erhöht die Produktion von Feen um %{count} pro Woche." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "" "Das Burgverlies erhöht das Einkommen der Stadt um %{count} Gold pro Tag." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" "Der Wasserfall erhöht die Produktion von Zentauren um %{count} pro Woche." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Die Bibliothek erhöht die Anzahl der Zaubersprüche in der Gilde um einen für " "jede Stufe der Gilde." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" "Der Obstgarten erhöht die Produktion von Halblingen um %{count} pro Woche." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" "Der Sturm fügt der Zauberkraft eines verteidigenden Zauberwirkers +2 hinzu." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" "Der Schädelhaufen erhöht die Produktion von Skeletten um %{count} pro Woche." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Der Brunnen erhöht die Wachstumsrate aller Behausungen um %{count} Lebewesen " "pro Woche." msgid "Thieves' Guild" msgstr "Diebesgilde" msgid "Tavern" msgstr "Taverne" msgid "Shipyard" msgstr "Schiffswerft" msgid "Well" msgstr "Brunnen" msgid "Statue" msgstr "Statue" msgid "Marketplace" msgstr "Marktplatz" msgid "Moat" msgstr "Burggraben" msgid "Castle" msgstr "Burg" msgid "Tent" msgstr "Zelt" msgid "Captain's Quarters" msgstr "Hauptmannsquartier" msgid "Mage Guild, Level 1" msgstr "Magiergilde, Stufe 1" msgid "Mage Guild, Level 2" msgstr "Magiergilde, Stufe 2" msgid "Mage Guild, Level 3" msgstr "Magiergilde, Stufe 3" msgid "Mage Guild, Level 4" msgstr "Magiergilde, Stufe 4" msgid "Mage Guild, Level 5" msgstr "Magiergilde, Stufe 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Der Schrein erhöht die Nekromantiefertigkeit aller Eurer Nekromanten um 10 " "Prozent." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Die Diebesgilde liefert Informationen über gegnerische Spieler. Die " "Diebesgilde kann auch Aufklärungsinformationen über gegnerische Städte " "liefern. Zusätzliche Diebesgilden liefern mehr Informationen." msgid "The Tavern increases morale for troops defending the castle." msgstr "Die Taverne erhöht die Moral der Truppen, die die Burg verteidigen." msgid "The Shipyard allows ships to be built." msgstr "In der Schiffswerft können Boote gebaut werden." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Der Brunnen erhöht die Wachstumsrate aller Behausungen um %{count} Lebewesen " "pro Woche." #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Die Statue erhöht das Einkommen Eurer Stadt um %{count} Gold pro Tag." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "Der linker Geschützturm bietet zusätzliche Feuerkraft während der Belagerung." msgid "The Right Turret provides extra firepower during castle combat." msgstr "" "Der rechter Geschützturm bietet zusätzliche Feuerkraft während der " "Belagerung." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Der Marktplatz kann dazu verwendet werden, eine Art von Ressource in eine " "andere umzuwandeln. Je mehr Marktplätze Ihr kontrolliert, desto besser ist " "der Umtauschkurs." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Der Burggraben verlangsamt angreifende Einheiten. Jede Einheit, die den " "Graben betritt, muss ihren Zug dort beenden und wird für Angriffe anfälliger." #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Die Burg verbessert die Stadtverteidigung und erhöht das Einkommen auf " "%{count} Gold pro Tag." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Das Zelt stellt Arbeiter zur Verfügung, um eine Burg zu bauen, sofern die " "Rohstoffe und das Gold vorhanden sind." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Das Hauptmannsquartier stellt den Hauptmann zur Verfügung, der bei der " "Verteidigung der Burg hilft, wenn kein Held anwesend ist." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Die Magiergilde ermöglicht es Helden, Zaubersprüche zu erlernen und ihre " "Zauberpunkte wieder aufzufüllen." msgid "Recruit %{name}" msgstr "%{name} rekrutieren" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Monat: %{month}, Woche: %{week}, Tag: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Ihr müsst ein Zauberbuch kaufen, um die Magiergilde zu nutzen, aber Ihr habt " "derzeit keinen Platz für ein Zauberbuch. Versuchet, eines Eurer Artefakte " "einem anderen Helden zu übergeben." msgid "Click to show next town." msgstr "Klicken um die nächste Stadt anzuzeigen." msgid "Show next town" msgstr "Nächste Stadt anzeigen" msgid "Click to show previous town." msgstr "Klicken um die vorherige Stadt anzuzeigen." msgid "Show previous town" msgstr "Vorherige Stadt anzeigen" msgid "This town may not be upgraded to a castle." msgstr "Diese Stadt darf nicht zu einer Burg ausgebaut werden." msgid "Town" msgstr "Stadt" msgid "Exit Castle" msgstr "Burg verlassen" msgid "Exit Town" msgstr "Stadt verlassen" msgid "Show Income" msgstr "Einkommen anzeigen" msgid "View Hero" msgstr "Helden anzeigen" msgid "The above spells are available here." msgstr "Die oben genannten Zaubersprüche sind hier verfügbar." msgid "The spells the hero can learn have been added to their book." msgstr "Diese Zaubersprüche wurden Eurem Zauberbuch hinzugefügt." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" "Ein großzügiges Trinkgeld für den Barkeeper führt zu dem folgenden Gerücht:" msgid "Recruit Hero" msgstr "Held rekrutieren" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} ist ein Erfahrungsstufe %{value} %{race} " msgid "with %{count} artifacts." msgstr "mit %{count} Artefakten." msgid "with 1 artifact." msgstr "mit 1 Artefakt." msgid "without artifacts." msgstr "ohne Artefakte." msgid "Recruit %{name} the %{race}" msgstr "%{name} (%{race}) rekrutieren" #, fuzzy msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Die \"Verstreute\" Kampfformation verteilt die Armeen von oben bis unten " "über das Schlachtfeld, mit wenigstens einem Freiraum zwischen jeder Armee." #, fuzzy msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "Die 'Gruppierte' Kampfformation bündelt Eure Armee in der Mitte Eurer Seite " "des Schlachtfelds." msgid "Spread Formation" msgstr "Verstreute Formation" msgid "Grouped Formation" msgstr "Gruppierte Formation" #, fuzzy msgid "Click to show the next town." msgstr "Klicken um die nächste Stadt anzuzeigen." #, fuzzy msgid "Click to show the previous town." msgstr "Klicken um die vorherige Stadt anzuzeigen." msgid "Set garrison combat formation to 'Spread'" msgstr "Garnisonskampfformation auf \"Ausbreitend\" einstellen" msgid "Set garrison combat formation to 'Grouped'" msgstr "Garnisonskampfformation auf \"Gruppiert\" einstellen" msgid "Exit Castle Options" msgstr "Burg Optionen verlassen" msgid "Castle Options" msgstr "Burg Optionen" msgid "Not enough resources to recruit creatures." msgstr "Nicht genügend Ressourcen, um Kreaturen zu rekrutieren." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Ihr könnt zur Zeit nicht rekrutieren, Eure Ränge sind voll." msgid "No creatures available for purchase." msgstr "Keine Kreatur zum Kauf verfügbar." msgid "Recruit Creatures" msgstr "Kreaturen rekrutieren" msgid "Hire all creatures in the town." msgstr "Alle Kreaturen in der Stadt rekrutieren." msgid "Max" msgstr "Max" msgid "Available" msgstr "Verfügbar" msgid "Town Population Information and Statistics" msgstr "Informationen und Statistiken zur Bevölkerung der Stadt" msgid "Damage" msgstr "Schaden" msgid "HP" msgstr "TP" msgid "Growth" msgstr "Wachstum" msgid "week" msgstr "Woche" msgid "View World" msgstr "Alles anzeigen" msgid "View the entire world." msgstr "Die ganze Welt sehen." msgid "Puzzle" msgstr "Puzzle" msgid "View the obelisk puzzle." msgstr "Das Obelisken-Puzzle ansehen." msgid "Scenario Information" msgstr "Informationen zum Szenario" msgid "View information on the scenario you are currently playing." msgstr "Informationen anzeigen über das Szenario, das gerade gespielt wird." msgid "Dig for the Ultimate Artifact." msgstr "Nach dem ultimativen Artefakt graben." msgid "Digging" msgstr "Graben" msgid "Arena" msgstr "Arena" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Ihr betretet die Arena und stehet einem Rudel bösartiger Löwen gegenüber. " "Unter jubelndem Beifall der Menge besiegt Ihr sie mit Leichtigkeit. " "Beeindruckt von Euren Fähigkeiten, erklärt sich der alte Gladiatorentrainer " "bereit, Euch in einer Fähigkeit Eurer Wahl zu unterrichten." msgid "Attack Skill" msgstr "Angriff" msgid "Defense Skill" msgstr "Verteidigung" msgid "Shots" msgstr "Schüsse" msgid "Shots Left" msgstr "Schüsse übrig" msgid "Hit Points" msgstr "Trefferpunkte" msgid "Hit Points Left" msgstr "TP übrig" msgid "You can't afford to upgrade your troops!" msgstr "Ihr könnt es Euch nicht leisten, Eure Truppen aufzurüsten!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Eure Truppen können aufgerüstet werden, aber das wird Euch eine Menge " "kosten. Wollt Ihr sie aufrüsten?" msgid "Are you sure you want to dismiss this army?" msgstr "Seid Ihr sicher, dass Ihr diese Armee entlassen wollt?" msgid "Upgrade" msgstr "Aufrüsten" msgid "Upgrade your troops." msgstr "Aufrüsten der Truppen." msgid "Dismiss" msgstr "Entlassen" msgid "Dismiss this army." msgstr "Entlassen der Armee." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Eine Gruppe %{monster} mit dem Wunsch nach größerem Ruhm, möchte sich Euch " "anschließen.\n" "Nehmt Ihr an?" msgid "Followers" msgstr "Anhänger" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "Der %{monster} lässt sich von Eurem diplomatischen Geschick überreden und " "bietet Euch an, sich Eurer Armee für %{gold} Goldstücke anzuschließen.\n" "Nehmt Ihr an?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Die Kreaturen lassen sich von Eurem diplomatischen\n" "Geschick überzeugen und machen Euch ein Angebot:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} von %{total} %{monster} werden sich Eurer Armee anschließen, und " "der Rest wird Euch in Ruhe lassen, für %{gold} Goldstücke.\n" "Nehmt Ihr an?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Alle %{offer} der %{monster} werden sich Eurer Armee für %{gold} Goldstücke " "anschließen.\n" "Nehmt Ihr an?" msgid "(Rate: %{percent})" msgstr "(Grad: %{percent})" msgid "off" msgstr "Aus" msgid "Music" msgstr "Musik" msgid "Effects" msgstr "Effekte" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Expansion" msgid "External" msgstr "Extern" msgid "Music Type" msgstr "Klangtyp" msgid "3D Audio" msgstr "3D Audio" msgid "Toggle ambient music level." msgstr "Lautstärke der Hintergrundmusik umschalten." msgid "Toggle foreground sounds level." msgstr "Lautstärke der Vordergrundgeräusche umschalten." msgid "Change the type of music." msgstr "Klangtyp ändern." #, fuzzy msgid "Toggle the 3D effect of foreground sounds." msgstr "3D-Effekte der Vordergrundgeräusche umschalten." msgid "Build a new ship:" msgstr "Ein neues Boot bauen:" msgid "Resource cost:" msgstr "Ressourcenkosten:" msgid "Total: " msgstr "Insgesamt: " msgid "Need: " msgstr "Bedarf: " msgid "New Game" msgstr "Neues Spiel" msgid "Start a single or multi-player game." msgstr "Einzel- oder Multi-Player Spiel starten." msgid "Load Game" msgstr "Spiel laden" msgid "Load a previously saved game." msgstr "Zuvor gespeichertes Spiel laden." msgid "Save Game" msgstr "Spiel speichern" msgid "Save the current game." msgstr "Das aktuelle Spiel speichern." msgid "Quit" msgstr "Beenden" msgid "Quit out of Heroes of Might and Magic II." msgstr "Heroes of Might and Magic II beenden." msgid "Language" msgstr "Sprache" msgid "Graphics" msgstr "Grafik" msgid "Black & White" msgstr "Schwarz & Weiß" msgid "Mouse Cursor" msgstr "Mauszeiger" msgid "Color" msgstr "Farbe" msgid "Text Support" msgstr "Text-Unterst." msgid "Change the language of the game." msgstr "Sprache des Spiels ändern." msgid "Select Game Language" msgstr "Spielsprache auswählen" msgid "Change the graphics settings of the game." msgstr "Grafikeinstellungen des Spiels ändern." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" "Farbigen Cursor ein- oder ausschalten. Dies ist nur eine ästhetische " "Entscheidung." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Textunterstützungsmodus umschalten, um zusätzliche Informationen über " "Fenster und Ereignisse im Spiel auszugeben." msgid "" "Map\n" "Difficulty" msgstr "" "Karten-\n" "grad" msgid "" "Game\n" "Difficulty" msgstr "" "Spiel-\n" "grad" msgid "Rating" msgstr "Grad" msgid "Map Size" msgstr "" "Karten-\n" "größe" msgid "Opponents" msgstr "Gegner" msgid "Class" msgstr "Klasse" msgid "" "Victory\n" "Conditions" msgstr "" "Sieg-\n" "bedingungen" msgid "" "Loss\n" "Conditions" msgstr "" "Verlust-\n" "bedingungen" msgid "First select recipients!" msgstr "Zuerst die Empfänger auswählen!" msgid "You cannot select %{resource}!" msgstr "%{resource} nicht ausgewählt werden!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Schieße auf %{monster}" msgid "Select Recipients" msgstr "Empfänger auswählen" msgid "Your Funds" msgstr "Eure Kasse" msgid "Planned Gift" msgstr "Geplantes Geschenk" msgid "Gift from %{name}" msgstr "Geschenk von %{name}" msgid "Resolution" msgstr "Auflösung" msgid "Fullscreen" msgstr "Vollbild" msgid "window|Mode" msgstr "Modus" msgid "Windowed" msgstr "Mit Fenster" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "System-Information" msgid "Change the resolution of the game." msgstr "Auflösung des Spiels ändern." msgid "Select Game Resolution" msgstr "Spielauflösung wählen" msgid "Toggle between fullscreen and windowed modes." msgstr "Umschalten zwischen Vollbildmodus und Fenstermodus." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "Die Option V-Sync kann aktiviert werden, um Flackerprobleme auf einigen " "Monitoren zu beheben." msgid "Show extra information such as FPS and current time." msgstr "" "Zusätzliche Informationen anzeigen, wie die FPS und die aktuelle Zeit an." msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" #, fuzzy msgid "Event: " msgstr "Ereignis" msgid "Hot Keys:" msgstr "Hotkeys:" msgid "Hide" msgstr "Ausblenden" msgid "Show" msgstr "Einblenden" msgid "Interface" msgstr "Interface" msgid "Interface Type" msgstr "Interface" msgid "Toggle the type of interface you want to use." msgstr "Art der Schnittstelle umschalten, die verwenden soll." msgid "Toggle interface visibility." msgstr "Sichtbarkeit der Interface ändern." msgid "Scroll Speed" msgstr "Scrollgeschw." msgid "Sets the speed at which you scroll the window." msgstr "Geschwindigkeit festlegen, mit der das Fenster verschoben wird." msgid "Select Game Language:" msgstr "Spielsprache wählen:" #, fuzzy msgid "Select Language:" msgstr "Spielsprache wählen:" msgid "Click to choose the selected language." msgstr "Klicken um die ausgewählte Sprache auszuwählen." msgid "%{name} has gained a level." msgstr "%{name} hat eine neue Stufe erreicht." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Ihr habt %{skill} gelernt." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} hat eine neue Stufe erreicht.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Ihr könnt lernen entweder:\n" "%{skill1}\n" "oder\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/a" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Bitte seht Euch unsere feinen Waren an. Wenn Ihr einen Handel anbieten " "möchtet, so klickt auf die Gegenstände, mit denen Ihr handeln wollt." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Ihr habt ein ganz schönes Schnäppchen gemacht. Ich werde wohl nichts daran " "verdient haben. Kann ich Euch an anderen meiner Waren interessieren?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Ich kann Euch %{count} für 1 Einheit von %{resfrom} anbieten." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" "Ich kann Euch 1 Einheit von %{resto} für %{count} Einheiten von %{resfrom} " "anbieten." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Menge zu handeln" msgid "Trading Post" msgstr "Handelsposten" msgid "Your Resources" msgstr "Eure Ressourcen" msgid "Available Trades" msgstr "Verfügbarer Handel" msgid "guarded by %{count} %{monster}" msgstr "bewacht von %{count} %{monster}" msgid "guarded by " msgstr "beschützt von " msgid "(available: %{count})" msgstr "(vorhanden: %{count})" msgid "(empty)" msgstr "(leer)" msgid "already learned" msgstr "schon gelernt" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Baum des Wissens" #, fuzzy msgid "already claimed" msgstr "schon gelernt" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "kennt diese Fähigkeit schon" msgid "already has max skills" msgstr "hat bereits maximale Fähigkeiten" msgid "(already visited)" msgstr "(schon besucht)" msgid "(not visited)" msgstr "(nicht besucht)" msgid "%{color} Barrier" msgstr "%{color} Barriere" #, fuzzy msgid "(tent visited)" msgstr "(nicht besucht)" msgid "%{color} Tent" msgstr "%{color} Zelt" msgid "Road" msgstr "Weg" msgid "(digging ok)" msgstr "(graben möglich)" msgid "(no digging)" msgstr "(graben unmöglich)" msgid "penalty: %{cost}" msgstr "Strafe: %{cost}" msgid "Defenders:" msgstr "Verteidiger:" msgid "Unknown" msgstr "Unbekannt" msgid "heroQuickInfo|(Level %{level})" msgstr "(Stufe %{level})" msgid "Attack:" msgstr "Angriff:" msgid "Defense:" msgstr "Verteidigung:" msgid "Spell Power:" msgstr "Zauberkraft:" msgid "Knowledge:" msgstr "Wissen:" msgid "Spell Points:" msgstr "Zauberpunkte:" msgid "Move Points:" msgstr "Bewegungspunkte:" msgid "Uncharted Territory" msgstr "Unerforschtes Land" msgid "Cost per troop:" msgstr "Kosten pro Truppe:" msgid "Available: %{count}" msgstr "Vorhanden: %{count}" msgid "Number to buy:" msgstr "Anzahl:" msgid "Recruit selected monsters." msgstr "Ausgewählte Monster rekrutieren." msgid "Select maximum monsters to be recruited." msgstr "Maximale Anzahl an zu rekrutierenden Monstern wählen." msgid "Select only 1 monster to be recruited." msgstr "Nur 1 Monster auswählen, das rekrutiert werden soll." #, fuzzy msgid "Select this game resolution." msgstr "Spielauflösung wählen" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Spielauflösung wählen:" msgid "Click to apply the selected resolution." msgstr "Klicken um die ausgewählte Auflösung anzuwenden." msgid "Click to apply the entered text." msgstr "Klicken zur Übernahme des eingegebenen Textes." msgid "Click to open the Virtual Keyboard dialog." msgstr "Hier klicken, um die virtuelle Tastatur zu öffnen." msgid "Open Virtual Keyboard" msgstr "Virtuelle Tastatur öffnen" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "Wie viele Truppen sollen verlegt werden?" #, fuzzy msgid "Select how many units to separate into:" msgstr "Zielstadt auswählen." msgid "Map: " msgstr "Karte: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "Monat: " msgid ", Week: " msgstr ", Woche: " msgid ", Day: " msgstr ", Tag: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "Ort: " msgid "Are you sure you want to delete file:" msgstr "Seid Ihr sicher, dass Ihr die Datei löschen möchten:" msgid "Warning" msgstr "Achtung" msgid "Click to save the current game." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Click to load a previously saved game." msgstr "Klicken um ein zuvor gespeichertes Spiel zu laden." msgid "File to Save:" msgstr "Datei zum Speichern:" msgid "File to Load:" msgstr "Datei zum Laden:" #, fuzzy msgid "Terrain object" msgstr "Gelände-Modus" msgid "Accept the choice made." msgstr "Die getroffene Wahl bestätigen." msgid "Select Skill:" msgstr "Fähigkeit auswählen:" msgid "Select Spell:" msgstr "Zauberspruch auswählen:" msgid "Select Artifact:" msgstr "Artefakt auswählen:" msgid "Select Monster:" msgstr "Monster auswählen:" msgid "Select Hero:" msgstr "Held auswählen:" msgid "race|Random" msgstr "Zufällig" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Klicken um die ausgewählte Auflösung anzuwenden." #, fuzzy msgid "%{color} %{race}" msgstr "Spieler %{color}" msgid "You will place" msgstr "" #, fuzzy msgid "Click to select this class." msgstr "Hier klicken, um auszuwählen, welches Szenario gespielt werden soll." #, fuzzy msgid "Click to select this color." msgstr "Hier klicken, um auszuwählen, welches Szenario gespielt werden soll." #, fuzzy msgid "Select Treasure:" msgstr "Held auswählen:" #, fuzzy msgid "Select Ocean Object:" msgstr "Ozean-Objekte" #, fuzzy msgid "Castle/town placing" msgstr "Burg Optionen" msgid "doubleLinedRace|Neutral" msgstr "Neutral" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "Klicken um die ausgewählte Auflösung anzuwenden." #, fuzzy msgid "Click to select town placing." msgstr "Klicken um die nächste Stadt anzuzeigen." #, fuzzy msgid "Click to select castle placing." msgstr "Hier klicken, um auszuwählen, welches Szenario gespielt werden soll." #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "Spieler %{color}" msgid "race|Neutral" msgstr "Neutral" #, fuzzy msgid "Select Dwelling:" msgstr "Zauberspruch auswählen:" #, fuzzy msgid "Select Landscape Object:" msgstr "Ozean-Objekte" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "Ressource" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name} (%{race})" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "Hier klicken, um auszuwählen, welches Szenario gespielt werden soll." #, fuzzy msgid "Select Mountain Object:" msgstr "Ozean-Objekte" #, fuzzy msgid "Select Rock Object:" msgstr "Ozean-Objekte" #, fuzzy msgid "Select Tree Object:" msgstr "Ozean-Objekte" #, fuzzy msgid "Select Power Up Object:" msgstr "Ozean-Objekte" #, fuzzy msgid "Select Adventure Object:" msgstr "Ozean-Objekte" msgid "Players Icon" msgstr "Spieleranzahl" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Gibt an, wie viele Spieler insgesamt im Szenario sind. Alle Positionen, die " "nicht von Menschen besetzt sind, werden von Computerspielern besetzt." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Zeigt an, ob die Karte\n" "klein (36 x 36), mittelgroß\n" "(72 x 72), groß (108 x 108)\n" "oder extragroß (144 x 144) ist." msgid "Size Icon" msgstr "Kartengröße" msgid "Map Type" msgstr "Kartenart" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Zeigt an, ob die Karte für die Version \"The Succession Wars\" oder \"The " "Price of Loyalty\" des Spiels erstellt wurde." msgid "Map Type:\n" msgstr "Kartentyp:\n" msgid "The Succession Wars" msgstr "The Succession Wars" msgid "The Price of Loyalty" msgstr "The Price of Loyalty" #, fuzzy msgid "Resurrection" msgstr "Auferstehung" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Sprache" msgid "Lose all your heroes and towns." msgstr "Alle Helden und Städte verlieren." msgid "Lose a specific town." msgstr "Eine bestimmte Stadt verlieren." msgid "Lose a specific hero." msgstr "Einen bestimmten Helden verlieren." msgid "Run out of time. Fail to win by a certain point." msgstr "Keine Zeit mehr haben. Nicht bis zu einem bestimmten Punkt gewinnen." msgid "Loss Condition" msgstr "Verlustbedingungen" msgid "Defeat all enemy heroes and towns." msgstr "Alle feindlichen Helden und Städte besiegen." msgid "Capture a specific town." msgstr "Eine bestimmte Stadt einnehmen." msgid "Defeat a specific hero." msgstr "Einen bestimmten Helden besiegen." msgid "Find a specific artifact." msgstr "Ein bestimmtes Artefakt finden." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "Eurer Seite besiegt die gegnerische Seite." msgid "Accumulate a large amount of gold." msgstr "Eine große Menge an Gold ansammeln." msgid "Victory Condition" msgstr "Siegbedingung" msgid "Map difficulty:" msgstr "Kartenschwierigkeit:" msgid "N" msgstr "N" #, fuzzy msgid "No maps exist at that size." msgstr "Es gibt keine Karten in dieser Größe" msgid "Small Maps" msgstr "Kleine Karten" msgid "View only maps of size small (36 x 36)." msgstr "Nur kleine Karten (36 x 36) anzeigen." msgid "Medium Maps" msgstr "Mittelgroße Karten" msgid "View only maps of size medium (72 x 72)." msgstr "Nur mittelgroße Karten (72 x 72) anzeigen." msgid "Large Maps" msgstr "Große Karten" msgid "View only maps of size large (108 x 108)." msgstr "Nur große Karten (108 x 108) anzeigen." msgid "Extra Large Maps" msgstr "Extragrosse Karten" msgid "View only maps of size extra large (144 x 144)." msgstr "Nur extragroße Karten (144 x 144) anzeigen." msgid "All Maps" msgstr "Alle Karten" msgid "View all maps, regardless of size." msgstr "Alle Maps anzeigen, unabhängig von der Größe." msgid "Selected Name" msgstr "Ausgewählter Name" msgid "The name of the currently selected map." msgstr "Der Name der aktuell ausgewählten Karte." msgid "Selected Map Difficulty" msgstr "Ausgewählter Schwierigkeitsgrad" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Der Schwierigkeitsgrad der aktuell ausgewählten Karte. Die " "Kartenschwierigkeit wird vom Szenario-Ersteller festgelegt. Schwierigere " "Karten können mehr oder stärkere Feinde, weniger Ressourcen oder andere " "spezielle Bedingungen enthalten, die die Dinge für den menschlichen Spieler " "schwieriger machen." msgid "Selected Description" msgstr "Ausgewählte Beschreibung" msgid "The description of the currently selected map." msgstr "Die Beschreibung der aktuell ausgewählten Karte." msgid "Jump" msgstr "Sprung" msgid "Hero Speed" msgstr "Heldgeschw." msgid "Don't Show" msgstr "Nicht anzeigen" msgid "Enemy Speed" msgstr "Feindgeschw." msgid "Auto Resolve" msgstr "Auto-Auflösen" msgid "Auto, No Spells" msgstr "Auto, ohne Zauber" msgid "Battles" msgstr "Schlachten" #, fuzzy msgid "combatMode|Manual" msgstr "Manuell" msgid "Change the speed at which your heroes move on the main screen." msgstr "" "Ändert die Geschwindigkeit, mit der sich Euer Helden auf dem Hauptbildschirm " "bewegen." #, fuzzy msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Legt die Geschwindigkeit fest, mit der sich die KI-Helden bewegen. Ihr könnt " "auch festlegen, dass die KI-Bewegung überhaupt nicht angezeigt wird." msgid "Change the interface settings of the game." msgstr "Die Grafikeinstellungen des Spiels ändern." #, fuzzy msgid "Interface Settings" msgstr "Spieleinstellungen" msgid "Toggle instant battle mode." msgstr "Sofortigen Kampfmodus umschalten." msgid "Att." msgstr "Angr." msgid "Def." msgstr "Vert." msgid "Power" msgstr "Kraft" msgid "Knowl" msgstr "Wissen" msgid "1st" msgstr "1." msgid "2nd" msgstr "2." msgid "3rd" msgstr "3." msgid "4th" msgstr "4." msgid "5th" msgstr "5." msgid "6th" msgstr "6." msgid "Oracle: Player Rankings" msgstr "Orakel: Spieler-Ränge" msgid "Thieves' Guild: Player Rankings" msgstr "Diebesgilde: Spieler-Ränge" msgid "Number of Towns:" msgstr "Anzahl der Städte:" msgid "Number of Castles:" msgstr "Anzahl der Burgen:" msgid "Number of Heroes:" msgstr "Anzahl der Helden:" msgid "Gold in Treasury:" msgstr "Gold in Schatzkammer:" msgid "Wood & Ore:" msgstr "Holz & Erz:" msgid "Gems, Cr, Slf & Mer:" msgstr "Andere Rohstoffe:" msgid "Obelisks Found:" msgstr "Obelisken gefunden:" msgid "Artifacts:" msgstr "Artefakte:" msgid "Total Army Strength:" msgstr "Gesamte Armeestärke:" msgid "Income:" msgstr "Einkommen:" msgid "Best Hero:" msgstr "Bester Held:" msgid "Best Hero Stats:" msgstr "Status bester Held:" msgid "Personality:" msgstr "Person:" msgid "Best Monster:" msgstr "Bestes Monster:" #, fuzzy msgid "Random Castle Name" msgstr "Zufälliges Burg" #, fuzzy msgid "Random Town Name" msgstr "Zufällige Stadt" #, fuzzy msgid "Allow Castle build" msgstr "Wolkenburg" #, fuzzy msgid "Default Buildings" msgstr "Standardaktion" #, fuzzy msgid "Default Army" msgstr "Standardaktion" #, fuzzy msgid "Castle Army" msgstr "Burg" #, fuzzy msgid "Town Army" msgstr "Stadt" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Den Helden verlieren: %{name}." msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Nachrichtenleiste" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Nachrichtenleiste" #, fuzzy msgid "Click to save the Event properties." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "Ressource" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Tag: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Klicken um das aktuelle Spiel zu speichern." #, fuzzy msgid "Add Event" msgstr "Ereignis" #, fuzzy msgid "Add an additional event." msgstr "Zusätzliche Programmierung" #, fuzzy msgid "Edit Event" msgstr "Ereignis" #, fuzzy msgid "Edit an existing event." msgstr "Eine vorhandene Karte laden." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "Eine vorhandene Karte laden." #, fuzzy msgid "Effects:" msgstr "Effekte" #, fuzzy msgid "Conditions:" msgstr "" "Verlust-\n" "bedingungen" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "Erfahrung" msgid "Artifact" msgstr "Artefakt" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Artefakt auswählen:" #, fuzzy msgid "Delete an artifact from the event." msgstr "Eine vorhandene Karte laden." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Fähigkeit auswählen:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Monster können nicht auf Wasser plaziert werden." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Monster können nicht auf Wasser plaziert werden." #, fuzzy msgid "%{objects} must be placed on water." msgstr "Monster können nicht auf Wasser plaziert werden." #, fuzzy msgid "Objects cannot be placed outside the map." msgstr "Monster können nicht auf Wasser plaziert werden." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Monster können nicht auf Wasser plaziert werden." #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Seid Ihr sicher, dass Ihr eine neue Karte erstellen wollt? (Alle nicht " "gespeicherten Änderungen an der aktuellen Karte gehen verloren)." msgid "Editor" msgstr "Editor" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Wollt Ihr wirklich eine neue Karte laden? (Nicht gespeicherte Änderungen an " "der aktuellen Karte gehen verloren)." msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Seid Ihr sicher, dass Ihr eine neue Karte erstellen wollt? (Alle nicht " "gespeicherten Änderungen an der aktuellen Karte gehen verloren)." msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "START" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Seid Ihr sicher, dass Ihr eine neue Karte erstellen wollt? (Alle nicht " "gespeicherten Änderungen an der aktuellen Karte gehen verloren)." msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Neustart" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Wollt Ihr wirklich eine neue Karte laden? (Nicht gespeicherte Änderungen an " "der aktuellen Karte gehen verloren)." #, fuzzy msgid "Create a new map from scratch." msgstr "Neue Karte von Beginn Menü" msgid "New Map" msgstr "Neue Karte" msgid "Load Map" msgstr "Karte laden" msgid "Load an existing map." msgstr "Eine vorhandene Karte laden." msgid "Save Map" msgstr "Karte speichern" msgid "Save the current map." msgstr "Speichern der aktuellen Karte." msgid "Quit out of the map editor." msgstr "Den Karteneditor verlassen." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Klicken, um zum Hauptmenü zurückzukehren." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Zufälliges ultimatives Artefakt" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "mit 1 Artefakt." msgid "The total number of obelisks is %{count}." msgstr "" #, fuzzy msgid "Roads" msgstr "Weg" #, fuzzy msgid "Streams" msgstr "Wasserlauf-Modus" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Monster können nicht auf Wasser plaziert werden." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Die Speicherdatei ist beschädigt." msgid "Unable to locate data directory to save the map." msgstr "" #, fuzzy msgid "Unable to create a directory to save the map." msgstr "Dient zum Löschen von Objekten von der Karte." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Dient zum Löschen von Objekten von der Karte." #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "" "Seid Ihr sicher, dass Ihr die Datei mit diesem Namen überschreiben wollt?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "Datei zum Speichern:" #, fuzzy msgid "Used to place %{object}." msgstr "Wird verwendet, um einen Helden zu platzieren." #, fuzzy msgid "Select object type" msgstr "Ozean-Objekte" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Hier klicken, um auszuwählen, welches Szenario gespielt werden soll." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Bitte wählt einen anderen Helden aus." msgid "" "Cell\n" "Details" msgstr "" #, fuzzy msgid "Erase" msgstr "Lösch-Modus" msgid "Mountains" msgstr "Berge" #, fuzzy msgid "Rocks" msgstr "Fels" msgid "Trees" msgstr "Bäume" #, fuzzy msgid "Water Objects" msgstr "Ödland-Objekte" #, fuzzy msgid "Miscellaneous" msgstr "Fineous" msgid "Artifacts" msgstr "Artefakte" #, fuzzy msgid "Dwellings" msgstr "Halblinge" msgid "Mines" msgstr "Minen" #, fuzzy msgid "Power-ups" msgstr "Kraft" msgid "Treasures" msgstr "Schätze" msgid "Heroes" msgstr "Helden" msgid "Towns" msgstr "Städte" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Ozean-Objekte" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Zeichnet das Terrain in\n" "%{size} mal %{size} in Quadratschritten." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Löscht Objekte in\n" "%{size} mal %{size} in Quadratschritten." msgid "Small Brush" msgstr "Kleiner Pinsel" msgid "Medium Brush" msgstr "Mittlerer Pinsel" msgid "Large Brush" msgstr "Großer Pinsel" msgid "Area Fill" msgstr "Bereich füllen" msgid "Used to click and drag for filling in large areas." msgstr "Wird zum Klicken und Ziehen verwendet, um große Flächen auszufüllen." msgid "Clear Area" msgstr "Bereich löschen" msgid "Used to click and drag for clearing large areas." msgstr "Wird zum Klicken und Ziehen verwendet, um große Bereiche zu löschen." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Kostet das %{rate}-fache der normalen Bewegung für alle Helden. " "(Pfadfinderei reduziert oder eliminiert den Abzug)." msgid "Traversable only by boat." msgstr "Nur mit dem Boot befahrbar." msgid "No special modifiers." msgstr "Keine besonderen Modifikatoren." msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "Gelände-Modus" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" "Wird verwendet, um das darunter liegende Gras, die Erde, das Wasser usw. auf " "der Karte zu zeichnen." #, fuzzy msgid "Landscape Objects Mode" msgstr "Objekt-Modus" #, fuzzy msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Wird verwendet, um Objekte (Berge, Bäume, Schätze usw.) auf der Karte zu " "platzieren." msgid "Detail Mode" msgstr "Detail-Modus" #, fuzzy msgid "Used for special editing of action objects." msgstr "" "Wird für die spezielle Bearbeitung von Monstern, Helden und Städten " "verwendet." #, fuzzy msgid "Adventure Objects Mode" msgstr "Abenteuer-Optionen" #, fuzzy msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Wird verwendet, um Objekte (Berge, Bäume, Schätze usw.) auf der Karte zu " "platzieren." #, fuzzy msgid "Kingdom Objects Mode" msgstr "Objekt-Modus" #, fuzzy msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Wird verwendet, um Objekte (Berge, Bäume, Schätze usw.) auf der Karte zu " "platzieren." #, fuzzy msgid "Monsters Mode" msgstr "Monster" #, fuzzy msgid "Used to place monsters on the map." msgstr "" "Verwendet, um eine\n" "Monstergruppe zu platzieren." msgid "Allows you to draw streams by clicking and dragging." msgstr "Ermöglicht das Zeichnen von Wasserläufen durch Klicken und Ziehen." msgid "Stream Mode" msgstr "Wasserlauf-Modus" msgid "Allows you to draw roads by clicking and dragging." msgstr "Ermöglicht das Zeichnen von Straßen durch Klicken und Ziehen." msgid "Road Mode" msgstr "Straßen-Modus" msgid "Erase Mode" msgstr "Lösch-Modus" #, fuzzy msgid "Used to erase objects from the map." msgstr "Dient zum Löschen von Objekten von der Karte." msgid "Change between zoom and normal view." msgstr "Wechsel zwischen Zoom- und Normalansicht." msgid "Magnify" msgstr "Vergrößern" msgid "Undo" msgstr "Rückgängig" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" "Bearbeiten des Kartentitel, der Beschreibung und anderen allgemeinen " "Informationen." msgid "Specifications" msgstr "Spezifikationen" msgid "File Options" msgstr "Datei-Optionen" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Dateioptionen-Menü öffnen, in welchem Maps gespeichert oder geladen oder den " "Editor verlassen werden kann." msgid "View the editor system options, which let you customize the editor." msgstr "" "Editor-Systemoptionen anzeigen, mit denen der Editor angepasst werden kann." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" "Eine Karte erstellen, die %{size} Quadrate breit und %{size} Quadrate hoch " "ist." msgid "Cancel back to the New Map menu." msgstr "Abbrechen, zurück zum Neue Karte Menü." msgid "Cancel back to the main menu." msgstr "Abbrechen und zurück zum Hauptmenü." msgid "From Scratch" msgstr "Von Grund auf neu" msgid "Start from scratch with a blank map." msgstr "Beginne bei Null mit einer leeren Karte." msgid "Create a randomly generated map." msgstr "Erstelle eine zufällig generierte Karte." msgid "Random" msgstr "Zufällig" msgid "Cancel back to the Map Editor main menu." msgstr "Abbrechen und zurück zum Hauptmenü des Karteneditors." msgid "No maps available!" msgstr "Keine Karten vorhanden!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "Spieler %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{name1} trifft %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "Spieler %{color}" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "Spieler %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{name1} trifft %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{name1} trifft %{name2}" #, fuzzy msgid "None." msgstr "Niemand" #, fuzzy msgid "One side defeats another." msgstr "Bitte wählt einen anderen Helden aus." #, fuzzy msgid "Accumulate gold." msgstr "%{count} Gold ansammeln." #, fuzzy msgid "Run out of time." msgstr "Den Karteneditor verlassen." #, fuzzy msgid "alliance|1st" msgstr " Allianz" #, fuzzy msgid "alliance|2nd" msgstr " Allianz" #, fuzzy msgid "alliance|3rd" msgstr " Allianz" #, fuzzy msgid "alliance|4th" msgstr " Allianz" #, fuzzy msgid "alliance|5th" msgstr " Allianz" #, fuzzy msgid "Special Loss Condition" msgstr "Verlustbedingungen" #, fuzzy msgid "Special Victory Condition" msgstr "Siegbedingung" #, fuzzy msgid "Allow standard victory conditions" msgstr "Siegbedingung" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " Allianz" #, fuzzy msgid "{%number} alliance: " msgstr " Allianz" #, fuzzy msgid "Gold:" msgstr "Gold" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Zielstadt auswählen." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Klicken um das aktuelle Spiel zu speichern." #, fuzzy msgid "Map Difficulty" msgstr "" "Karten-\n" "grad" #, fuzzy msgid "Map Description" msgstr "" "\n" "Ort: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Ausgewählte Beschreibung" #, fuzzy msgid "Click to accept the changes made." msgstr "Klicken um die nächste Stadt anzuzeigen." #, fuzzy msgid "Click to edit custom rumors." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Klicken um die ausgewählte Auflösung anzuwenden." #, fuzzy msgid "Events" msgstr "Ereignis" #, fuzzy msgid "Click to change the language of the map." msgstr "Sprache des Spiels ändern." #, fuzzy msgid "Click to change your map name." msgstr "Klicken um die nächste Stadt anzuzeigen." #, fuzzy msgid "Map Name" msgstr "" "Karten-\n" "größe" #, fuzzy msgid "Click to change the description of the current map." msgstr "Die Beschreibung der aktuell ausgewählten Karte." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Die Beschreibung der aktuell ausgewählten Karte." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Die Beschreibung der aktuell ausgewählten Karte." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Kartenart" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Der Schwierigkeitsgrad der aktuell ausgewählten Karte. Die " "Kartenschwierigkeit wird vom Szenario-Ersteller festgelegt. Schwierigere " "Karten können mehr oder stärkere Feinde, weniger Ressourcen oder andere " "spezielle Bedingungen enthalten, die die Dinge für den menschlichen Spieler " "schwieriger machen." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Anzahl %{resource} wählen:" #, fuzzy msgid "Animation" msgstr "Annektion" #, fuzzy msgid "Passability" msgstr "Person:" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "Zusätzliche Programmierung" #, fuzzy msgid "Edit Rumor" msgstr "Editor" #, fuzzy msgid "Edit an existing rumor." msgstr "Eine vorhandene Karte laden." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "Eine vorhandene Karte laden." msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "Ort: " #, fuzzy msgid "Save Map:" msgstr "Karte speichern" #, fuzzy msgid "Click to save the current map." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Klicken um das aktuelle Spiel zu speichern." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Leicht" msgid "difficulty|Normal" msgstr "Normal" msgid "difficulty|Hard" msgstr "Schwer" msgid "difficulty|Expert" msgstr "Experte" msgid "difficulty|Impossible" msgstr "Unmögl." msgid "and more..." msgstr "und mehr..." msgid "Easy" msgstr "Leicht" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "Schwer" msgid "Campaign Difficulty" msgstr "Feldzugschwierigkeit" #, fuzzy msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Wenn Ihr die Geschichte der Herausforderung vorzieht: Die KI ist im " "Vergleich zum normalen Schwierigkeitsgrad schwächer." #, fuzzy msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Wählt diesen Schwierigkeitsgrad, um den Feldzug wie im Original zu spielen." #, fuzzy msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Stellt Euch der Herausforderung! Die KI ist im Vergleich zum normalen " "Schwierigkeitsgrad stärker." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Herzlichen Glückwunsch!\n" "\n" "Tage: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Schwierigkeitsgrad: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Punktzahl: %{score}\n" "\n" "Bewertung:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Das ausgewählte Szenario starten." msgid "View Intro" msgstr "Intro ansehen" #, fuzzy msgid "View the intro video for the current state of the campaign." msgstr "Die Intro-Videos zum aktuellen Stand des Feldzuges ansehen." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Schwierigkeitsgrad der Kampagne auswählen. Dieser kann während der Kampagne " "jederzeit herabgesetzt werden." msgid "Restart the current scenario." msgstr "Neustart des aktuellen Szenarios." msgid "Difficulty" msgstr "Schwierigkeitsgrad" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Ihr habt einen niedrigeren Schwierigkeitsgrad für die Kampagne gewählt. Ihr " "könnt dies danach nicht mehr rückgängig machen. Der Highscore wird " "ausschließlich auf Basis des neuen Schwierigkeitsgrades berechnet. Möchtet " "Ihr fortfahren?" msgid "Are you sure you want to restart this scenario?" msgstr "Seid Ihr sicher, dass Ihr dieses Szenario neu starten wollt?" msgid "Campaign Scenario loading failure" msgstr "Fehler beim Laden des Feldzugspiels" msgid "Please make sure that campaign files are correct and present." msgstr "" "Bitte stellt sicher, dass die Feldzugdateien korrekt und vorhanden sind." msgid "Days spent" msgstr "Verbrachte Tage" msgid "The number of days spent on this campaign." msgstr "Die Anzahl der Tage, die für diesen Feldzug aufgewendet wurden." msgid "Project Coordination and Core Development" msgstr "Projektkoordination und Kernentwicklung" msgid "Development" msgstr "Entwicklung" msgid "Visit us at " msgstr "Besucht uns bei " msgid "QA and Support" msgstr "QA und Unterstützung" msgid "Dev and Support" msgstr "Entwicklung und Support" msgid "Special Thanks to" msgstr "Besonderen Dank an" #, fuzzy msgid "and many-many other contributors and supporters!" msgstr "und viele, viele andere Unterstützer!" msgid "Support us at" msgstr "Unterstützet uns bei" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Verbindet Euch mit uns bei" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Braucht Ihr Hilfe beim Spiel?" msgid "Original project before 0.7" msgstr "Ursprüngliches Projekt vor 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Heroes of Might and Magic II: The Succession Wars-Team" msgid "Designed and Directed" msgstr "Entworfen und geleitet" msgid "Programming and Design" msgstr "Programmierung und Gestaltung" msgid "Executive Producer" msgstr "Ausführender Produzent" msgid "Producer" msgstr "Produzent" msgid "Additional Design" msgstr "Zusätzliches Gestaltung" msgid "Additional Programming" msgstr "Zusätzliche Programmierung" msgid "Musical Production" msgstr "Musikalische Produktion" msgid "Music and Sound Design" msgstr "Musik und Klanggestaltung" msgid "Vocalists" msgstr "Vokalisten" msgid "Art Director" msgstr "Künstlerischer Leiter" msgid "Assistant Art Director" msgstr "Assistentin der künstlerischen Leitung" msgid "Artists" msgstr "Künstler" msgid "QA Manager" msgstr "QA-Leiter" msgid "QA" msgstr "QA" msgid "Writing" msgstr "Schriftsteller" msgid "Manual and Helpfile" msgstr "Handbuch und Hilfedatei" msgid "Scenarios" msgstr "Szenarien" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Heroes of Might and Magic II: The Price of Loyalty-Team" msgid "Design Lead" msgstr "Designleitung" msgid "Designers" msgstr "Designer" msgid "Programming Lead" msgstr "Leitung der Programmierung" msgid "Art Lead" msgstr "Künstlerische Leitung" msgid "Playtesters" msgstr "Spieltester" msgid "Designer" msgstr "Designer" msgid "Producers" msgstr "Produzenten" msgid "QA Managers" msgstr "QA-Manager" msgid "Sound Design" msgstr "Sounddesign" msgid "Town Themes" msgstr "Stadt-Themen" msgid "Alto Sax" msgstr "Altsaxophon" msgid "Harpsichord and Piano" msgstr "Cembalo und Piano" msgid "Basso Vocal" msgstr "Basso-Gesang" msgid "Soprano Vocal" msgstr "Sopran-Gesang" msgid "Recorded at %{recordingStudio}" msgstr "Aufgenommen in den %{recordingStudio}" msgid "credits|Manual" msgstr "Anleitung" msgid "German Consultant" msgstr "Deutscher Berater" msgid "Map Designers" msgstr "Kartendesigner" msgid "Package Design" msgstr "Verpackungsdesign" msgid "High Scores" msgstr "Bestenliste" msgid "Your Name" msgstr "Euer Name" msgid "Unknown Hero" msgstr "Unbekannter Held" msgid "Standard" msgstr "Standard" msgid "View High Scores for Standard Maps." msgstr "Bestenliste für Standardkarten anzeigen." msgid "Campaign" msgstr "Feldzug" msgid "View High Scores for Campaigns." msgstr "Bestenliste für Feldzüge anzeigen." msgid "hotkey|default okay event" msgstr "Standard-Event: Okay" msgid "hotkey|default cancel event" msgstr "Standard-Event: Abbrechen" msgid "hotkey|default left" msgstr "Standard: Links" msgid "hotkey|default right" msgstr "Standard: Rechts" msgid "hotkey|default up" msgstr "Standard: Hoch" msgid "hotkey|default down" msgstr "Standard: Runter" msgid "hotkey|toggle fullscreen" msgstr "Vollbild umschalten" msgid "hotkey|toggle text support mode" msgstr "Textunterstützungsmodus umschalten" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "Textunterstützungsmodus umschalten" msgid "hotkey|new game" msgstr "Neues Spiel" msgid "hotkey|load game" msgstr "Spiel laden" #, fuzzy msgid "hotkey|high scores" msgstr "Highscores" msgid "hotkey|credits" msgstr "Credits" msgid "hotkey|standard game" msgstr "Standard-Spiel" msgid "hotkey|campaign game" msgstr "Feldzug-Spiel" msgid "hotkey|multi-player game" msgstr "Multi-Player Spiel" msgid "hotkey|settings" msgstr "Einstellungen" msgid "hotkey|quit" msgstr "Beenden" msgid "hotkey|select map" msgstr "Karte auswählen" msgid "hotkey|select small map size" msgstr "Kleine Karten auswählen" msgid "hotkey|select medium map size" msgstr "Mittelgroße Karten auswählen" msgid "hotkey|select large map size" msgstr "Große Karten auswählen" msgid "hotkey|select extra large map size" msgstr "Extra große Karten auswählen" msgid "hotkey|select all map sizes" msgstr "Alle Kartengrößen auswählen" #, fuzzy msgid "hotkey|hot seat game" msgstr "\"Heißer Stuhl\" Spiel" msgid "hotkey|battle only game" msgstr "\"Nur Schlacht\" Spiel" msgid "hotkey|choose the original campaign" msgstr "Originaler Feldzug auswählen" msgid "hotkey|choose the expansion campaign" msgstr "Zusätzlicher Feldzug auswählen" msgid "hotkey|map editor main menu" msgstr "Hauptmenü des Karteneditors" msgid "hotkey|new map menu" msgstr "Neue Karte Menü" msgid "hotkey|load map menu" msgstr "Karte Laden Menü" msgid "hotkey|new map from scratch" msgstr "Neue Karte von Beginn Menü" msgid "hotkey|new random map" msgstr "Neue zufällige Karte Menü" #, fuzzy msgid "hotkey|undo last action" msgstr "Standardaktion" #, fuzzy msgid "hotkey|redo last action" msgstr "Standardaktion" #, fuzzy msgid "hotkey|open game main menu" msgstr "Neue Karte Menü" #, fuzzy msgid "hotkey|toggle passability" msgstr "Status umschalten" msgid "hotkey|roland campaign" msgstr "Roland-Feldzug" msgid "hotkey|archibald campaign" msgstr "Archibald-Feldzug" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "\"The Price of Loyalty\"-Feldzug" msgid "hotkey|voyage home campaign" msgstr "Heimreise-Feldzug" msgid "hotkey|wizard's isle campaign" msgstr "\"Die Insel der Zauberer\"-Feldzug" msgid "hotkey|descendants campaign" msgstr "Nachkommen-Feldzug" msgid "hotkey|select first campaign bonus" msgstr "Wähle ersten Feldzug-Bonus" msgid "hotkey|select second campaign bonus" msgstr "Wähle zweiten Feldzug-Bonus" msgid "hotkey|select third campaign bonus" msgstr "Wähle dritten Feldzug-Bonus" msgid "hotkey|view campaign intro" msgstr "Feldzug-Intro anzeigen" msgid "hotkey|select campaign difficulty" msgstr "Feldzugschwierigkeit" msgid "hotkey|restart campaign scenario" msgstr "Feldzug-Szenario neustarten" msgid "hotkey|world map left" msgstr "Weltkarte links" msgid "hotkey|world map right" msgstr "Weltkarte rechts" msgid "hotkey|world map up" msgstr "Weltkarte hoch" msgid "hotkey|world map down" msgstr "Weltkarte runter" msgid "hotkey|world map up left" msgstr "Weltkarte hoch links" msgid "hotkey|world map up right" msgstr "Weltkarte hoch rechts" msgid "hotkey|world map down left" msgstr "Weltkarte runter links" msgid "hotkey|world map down right" msgstr "Weltkarte runter rechts" msgid "hotkey|save game" msgstr "Spiel speichern" msgid "hotkey|next hero" msgstr "Nächster Held" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "Nächster Held" #, fuzzy msgid "hotkey|start hero movement" msgstr "Bewegung fortsetzen" msgid "hotkey|cast adventure spell" msgstr "Abenteuer-Zauberspruch aussprechen" msgid "hotkey|put hero to sleep" msgstr "Held schlafen legen" msgid "hotkey|next town" msgstr "Nächste Stadt" msgid "hotkey|end turn" msgstr "Zug beenden" msgid "hotkey|file options" msgstr "Datei-Optionen" msgid "hotkey|adventure options" msgstr "Abenteuer-Optionen" msgid "hotkey|puzzle map" msgstr "Puzzlekarte" msgid "hotkey|scenario information" msgstr "Szenario-Informationen" msgid "hotkey|dig for artifact" msgstr "Nach dem Artefakt graben" msgid "hotkey|view world" msgstr "Weltkarte anzeigen" msgid "hotkey|kingdom summary" msgstr "Zusammenfassung des Königreichs" msgid "hotkey|default action" msgstr "Standardaktion" msgid "hotkey|open focus" msgstr "Fokus öffnen" msgid "hotkey|system options" msgstr "System-Optionen" msgid "hotkey|scroll left" msgstr "Links scrollen" msgid "hotkey|scroll right" msgstr "Rechts scrollen" msgid "hotkey|scroll up" msgstr "Nach oben scrollen" msgid "hotkey|scroll down" msgstr "Nach unten scrollen" msgid "hotkey|toggle control panel" msgstr "Bedienfeld umschalten" msgid "hotkey|toggle radar" msgstr "Radar umschalten" msgid "hotkey|toggle buttons" msgstr "Buttons umschalten" msgid "hotkey|toggle status" msgstr "Status umschalten" msgid "hotkey|toggle icons" msgstr "Icons umschalten" msgid "hotkey|transfer control to ai" msgstr "Kontrolle zur KI übertragen" msgid "hotkey|retreat from battle" msgstr "Vom Kampf zurückziehen" msgid "hotkey|surrender during battle" msgstr "Aufgeben während des Kampfes" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Auto-Kampf-Modus umschalten" #, fuzzy msgid "hotkey|quick combat" msgstr "Beenden" msgid "hotkey|battle options" msgstr "Kampf-Optionen" msgid "hotkey|skip turn in battle" msgstr "Runde im Kampf überspringen" msgid "hotkey|cast battle spell" msgstr "Kampfzauber wirken" msgid "hotkey|dwelling level 1" msgstr "Behausung Stufe 1" msgid "hotkey|dwelling level 2" msgstr "Behausung Stufe 2" msgid "hotkey|dwelling level 3" msgstr "Behausung Stufe 3" msgid "hotkey|dwelling level 4" msgstr "Behausung Stufe 4" msgid "hotkey|dwelling level 5" msgstr "Behausung Stufe 5" msgid "hotkey|dwelling level 6" msgstr "Behausung Stufe 6" msgid "hotkey|well" msgstr "Brunnen" msgid "hotkey|marketplace" msgstr "Marktplatz" msgid "hotkey|mage guild" msgstr "Magiergilde" msgid "hotkey|shipyard" msgstr "Schiffswerft" msgid "hotkey|thieves guild" msgstr "Diebesgilde" msgid "hotkey|tavern" msgstr "Taverne" msgid "hotkey|construction screen" msgstr "Bau-Bildschirm" msgid "hotkey|buy all monsters in well" msgstr "Alle Monster im Brunnen kaufen" msgid "hotkey|split stack by half" msgstr "Stapel halbieren" msgid "hotkey|split stack by one" msgstr "Stapel um eins aufteilen" msgid "hotkey|join stacks" msgstr "Stapel zusammenfügen" msgid "hotkey|upgrade troop" msgstr "Truppen aufrüsten" msgid "hotkey|dismiss hero or troop" msgstr "Held oder Truppe entlassen" #, fuzzy msgid "hotkey|exchange all troops" msgstr "Truppen aufrüsten" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Möchtet Ihr die Kontrolle über die KI zurückgewinnen? Der Effekt tritt erst " "in der nächsten Runde ein." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Möchtet Ihr die Kontrolle von Euch auf die KI übertragen? Der Effekt tritt " "erst in der nächsten Runde ein." #, fuzzy msgid "Default Actions" msgstr "Standardaktion" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Weltkarte" #, fuzzy msgid "Battle Screen" msgstr "Heldenbildschirm" #, fuzzy msgid "Town Screen" msgstr "Heldenbildschirm" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "Die Speicherdatei ist beschädigt." msgid "Unsupported save format: " msgstr "Unterstütztes Speicherformat: " msgid "Current game version: " msgstr "Aktuelle Spielversion: " msgid "Last supported version: " msgstr "Letzte unterstützte Version: " msgid "This file contains a save with an invalid game type." msgstr "Diese Datei enthält einen Spielstand mit einem ungültigen Spieltyp." #, fuzzy msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Diese Datei wurde als \"The Price of Loyalty\"-Karte gespeichert, aber die " "entsprechenden Spiel-Assets wurden der Engine nicht zur Verfügung gestellt." msgid "This saved game is localized to '" msgstr "Dieses gespeicherte Spiel ist lokalisiert in '" msgid "' language, but the current language of the game is '" msgstr "' Sprache, aber die aktuelle Sprache des Spiels ist '" msgid "No save files to load." msgstr "Keine Speicherdateien vorhanden." msgid "Hot Seat" msgstr "Heißer Stuhl" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "\"Heißen Stuhl\" spielen, bei dem 2 bis 6 Spieler spielen an einem Rechner " "abwechselnd gegeneinander." msgid "A single player game playing out a single map." msgstr "Ein Einzelspieler-Spiel, das auf einer einzigen Karte spielt." msgid "Standard Game" msgstr "Standard-Spiel" msgid "A single player game playing through a series of maps." msgstr "" "Ein Einzelspieler-Spiel, bei dem man sich durch eine Reihe von Karten spielt." msgid "Campaign Game" msgstr "Feldzug-Spiel" msgid "Multi-Player Game" msgstr "Multi-Player Spiel" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Ein Multiplayer-Spiel, bei dem mehrere menschliche Spieler auf einer " "einzigen Karte gegeneinander antreten." msgid "fheroes2 Resurrection Team presents" msgstr "fheroes2 Resurrection Team präsentiert" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Willkommen bei Heroes of Might and Magic II (ermöglicht durch die fheroes2-" "Engine)!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Willkommen bei Heroes of Might and Magic II (ermöglicht durch die fheroes2-" "Engine)! Bevor das Spiel startet, bitte die Auflösung des Spiels wählen." msgid "Greetings!" msgstr "Grüße!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Heroes of Might and Magic II beenden und zum Betriebssystem zurückkehren." msgid "Credits" msgstr "Credits" msgid "View the credits screen." msgstr "Abspannbildschirm zeigen." msgid "View the high scores screen." msgstr "Die Bestenliste anzeigen." #, fuzzy msgid "Create new or modify existing maps." msgstr "Eine vorhandene Karte laden." msgid "Change language, resolution and settings of the game." msgstr "Sprache, Auflösung und Einstellungen des Spiels ändern." msgid "Game Settings" msgstr "Spieleinstellungen" #, fuzzy msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Die erforderlichen Videodateien für das Feldzugauswahlfenster fehlen. Bitte " "sicherstellen, dass alle erforderlichen Dateien im System vorhanden sind." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Entweder Rolands oder Archibalds Feldzug aus dem ursprünglichen Heroes of " "Might and Magic II." msgid "Original Campaign" msgstr "Original Feldzug" msgid "Expansion Campaign" msgstr "Zusätzlicher Feldzug" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" "Ein der vier neuen Feldzüge aus dem Erweiterungsset \"The Price of Loyalty\"." msgid "Loading video. Please wait..." msgstr "Video wird geladen. Bitte warten..." msgid "Host" msgstr "Gastgeber" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Der Gastgeber legt die Spieloptionen fest. Es kann nur einen Gastgeber pro " "Netzwerkspiel geben." msgid "Guest" msgstr "Gast" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "Der Gast wartet darauf, dass der Gastgeber das Spiel einrichtet, und wird " "dann automatisch hinzugefügt. Bei TCP/IP-Spielen kann es mehrere Gäste geben." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" #, fuzzy msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Ein Multiplayer-Spiel, bei dem mehrere menschliche Spieler auf einer " "einzigen Karte gegeneinander antreten." msgid "Battle Only" msgstr "Nur Schlacht" msgid "Setup and play a battle without loading any map." msgstr "Einen Schlacht einrichten und spielen, ohne eine Karte zu laden." #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "\"Heißen Stuhl\" spielen, bei dem 2 bis 6 Spieler spielen an einem Rechner " "abwechselnd gegeneinander." msgid "2 Players" msgstr "2 Spieler" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Ein Spiel mit 2 menschlichen Spielern und optional mit bis zu 4 zusätzlichen " "Computerspielern." msgid "3 Players" msgstr "3 Spieler" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Ein Spiel mit 3 menschlichen Spielern und optional mit bis zu 3 zusätzlichen " "Computerspielern." msgid "4 Players" msgstr "3 Spieler" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Ein Spiel mit 4 menschlichen Spielern und optional mit bis zu 2 zusätzlichen " "Computerspielern." msgid "5 Players" msgstr "5 Spieler" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Ein Spiel mit 5 menschlichen Spielern und optional mit bis zu 1 zusätzliche " "Computerspieler." msgid "6 Players" msgstr "6 Spieler" msgid "Play with 6 human players." msgstr "Ein Spiel mit 6 menschlichen Spielern." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" "Die Drachenstadt ist gefallen! Ihr seid sind nun der Meister der Drachen." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Ihr habt %{name} gefasst!\n" "Ihr seid siegreich." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Ihr habt den feindlichen Helden %{name} gefangen genommen!\n" "Eure Suche ist abgeschlossen." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Ihr habt den %{name} gefunden.\n" "Eure Suche ist abgeschlossen." msgid "Ultimate Artifact" msgstr "Ultimativen Artefakt" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Der Feind ist besiegt.\n" "Eure Seite hat gesiegt!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Ihr habt über %{count} Gold in Eurer Schatzkammer angehäuft.\n" "Alle Feinde verneigen sich vor Eure Reichtum und Eurer Macht." #, fuzzy msgid "Victory!" msgstr "Ector" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Der Feind hat %{name} gefangen genommen!\n" "Der ist triumphierend." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Der Feind hat über %{count} Gold in seiner Schatzkammer angehäuft.\n" "Ihr müsst Euch in der Niederlage vor seinem Reichtum und seiner Macht beugen." msgid "You have been eliminated from the game!!!" msgstr "Ihr seid aus dem Spiel ausgeschieden!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Ihr habt den Helden %{name} verloren.\n" "Euer Abenteuer ist vorbei." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Ihr habt es nicht geschafft, Euer Abenteuer rechtzeitig zu beenden.\n" "Alles ist verloren." msgid "Defeat!" msgstr "Besiegt!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Basispunktzahl: %{score}\n" "Schwierigkeit: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Alle feindlichen Helden besiegen und alle feindlichen Städte und Burgen " "bezwingen." msgid "Your side defeats the opposing side." msgstr "Eurer Seite besiegt die gegnerische Seite." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" "Die Zeit läuft ab. (Nicht mit einem bestimmten Punkt Vorsprung gewinnen.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Ihr müsst den Feind %{enemies} besiegen." msgstr[1] "Ihr müsst die feindliche Allianz %{enemies} besiegen." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Die Allianz, bestehend aus %{allies} und Euch, muss den Feind %{enemies} " "besiegen." msgstr[1] "" "Die Allianz, bestehend aus %{allies} und Euch, muss die feindliche Allianz " "%{enemies} besiegen." msgid "Capture the castle '%{name}'." msgstr "Die Burg '%{name}' erobern." msgid "Capture the town '%{name}'." msgstr "Die Stadt '%{name}' erobern." msgid "Defeat the hero '%{name}'." msgstr "Den Helden '%{name}' besiegen." msgid "Find the ultimate artifact." msgstr "Das ultimative Artefakt finden." msgid "Find the '%{name}' artifact." msgstr "Das Artefakt '%{name}' finden." msgid "Accumulate %{count} gold." msgstr "%{count} Gold ansammeln." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", oder Ihr könnt gewinnen, indem Ihr alle gegnerischen Helden besiegt und " "alle gegnerischen Städte und Burgen erobert." msgid "Lose the castle '%{name}'." msgstr "Die Burg '%{name}' verlieren." msgid "Lose the town '%{name}'." msgstr "Die Stadt '%{name}' verlieren." msgid "Lose the hero: %{name}." msgstr "Den Helden verlieren: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Nicht bis zum Ende des Monats %{month}, der Woche %{week}, des Tages %{day} " "gewinnen." msgid "%{color} player has been vanquished!" msgstr "Spieler %{color} wurde besiegt!" msgid "Major Event!" msgstr "Großes Ereignis!" msgid "Scenario:" msgstr "Szenario:" msgid "Game Difficulty:" msgstr "Schwierigkeitsgrad:" msgid "Opponents:" msgstr "Gegner:" msgid "Class:" msgstr "Klasse:" msgid "Rating %{rating}%" msgstr "Grad %{rating}%" msgid "Click here to select which scenario to play." msgstr "Hier klicken, um auszuwählen, welches Szenario gespielt werden soll." msgid "Scenario" msgstr "Szenario" msgid "Game Difficulty" msgstr "Spielschwierigkeit" #, fuzzy msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Damit kann die Startschwierigkeit verändert werden, mit der gespielt wird. " "Bei höheren Schwierigkeitsgraden hat der Spieler zu Beginn weniger " "Ressourcen, und bei höheren Einstellungen erhält der Computer zusätzliche " "Ressourcen." msgid "Difficulty Rating" msgstr "Schwierigkeitsgrad" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Der Schwierigkeitsgrad spiegelt eine Kombination aus verschiedenen " "Einstellungen für das Spiel wider. Diese Zahl wird auf Euer Endergebnis " "angewandt." msgid "Click to accept these settings and start a new game." msgstr "Diese Einstellungen übernehmen und ein neues Spiel beginnen." msgid "Click to return to the main menu." msgstr "Klicken, um zum Hauptmenü zurückzukehren." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Astrologen verkündigen den Monat des %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Astrologen verkündigen die Woche des %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" "Nach regelmäßigem Wachstum verdoppelt sich die Population von %{monster}!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Nach regelmäßigem Wachstum steigt die Bevölkerung von %{monster} um %{count} " "Prozent!" msgstr[1] "" "Nach regelmäßigem Wachstum steigt die Bevölkerung von %{monster} um %{count} " "Prozent!" msgid "%{monster} growth +%{count}." msgstr "Die Bevölkerung von %{monster} steigt um +%{count}." msgid " All populations are halved." msgstr " Alle Bevölkerungen werden halbiert." msgid " All dwellings increase population." msgstr " Alle Wohnungen erhöhen die Bevölkerung." msgid "New Month!" msgstr "" msgid "New Week!" msgstr "Neue Woche!" msgid "Beware!" msgstr "Aufgepasst!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "Spieler %{color}, dies ist Euer letzter Tag, um eine Stadt zu erobern, oder " "Ihr werdet aus diesem Land verbannt." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "Spieler %{color}, Ihr habt nur noch %{day} Tage Zeit, um eine Stadt zu " "erobern, oder Ihr werdet aus diesem Land verbannt." msgid "%{color} player's turn." msgstr "Spieler %{color} ist dran." #, fuzzy msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "Spieler %{color}, Ihr habt Eure letzte Stadt verloren. Wenn Ihr in der " "nächsten Woche keine Stadt erobert, werdet Ihr aus diesem Land verbannt." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "Spieler %{color}, Eure Helden lassen Euch im Stich, und Ihr werdet aus " "diesem Land verbannt." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "Nächster Held" msgid "Select the next Hero." msgstr "Nächster Held wählen." #, fuzzy msgid "Hero Movement" msgstr "Schatten-bewegung" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "Zusammenfassung des Königreichs" #, fuzzy msgid "View a summary of your Kingdom." msgstr "Eine Zusammenfassung Eures Königreichs anzeigen." msgid "Cast an adventure spell." msgstr "Einen Abenteuer-Zauberspruch aussprechen." msgid "End Turn" msgstr "Zug beenden" #, fuzzy msgid "End your turn and let the computer take its turn." msgstr "Beendet Euren Zug und lasst den Computer seinen Zug machen." msgid "Adventure Options" msgstr "Abenteuer-Optionen" msgid "Bring up the adventure options menu." msgstr "Ruft das Menü der Abenteuer-Optionen auf." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Ruft das Menü \"Dateioptionen\" auf, in dem Sie das Spiel laden, speichern, " "neu starten oder aufgeben können." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Ruft das Menü \"Systemoptionen\" auf, in dem Ihr Euer Spiel anpassen könnt." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Ein oder mehrere Helden können sich noch bewegen. Sied Ihr sicher, dass Ihr " "Eure Zug beenden wollt?" msgid "Are you sure you want to quit?" msgstr "Seid Ihr sicher, dass Ihr das Spiel verlassen wollt?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Seid Ihr sicher, dass Ihr neu starten wollt? (Euer aktuelles Spiel wird " "verloren gehen.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "" "Seid Ihr sicher, dass Ihr die Datei mit diesem Namen überschreiben wollt?" msgid "Game saved successfully." msgstr "Spiel erfolgreich gespeichert." msgid "There was an issue during saving." msgstr "Es gab ein Problem beim Speichern." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Seid Ihr sicher, dass Ihr ein neues Spiel laden wollt? (Euer aktuelles Spiel " "geht dabei verloren.)" msgid "Try looking on land!!!" msgstr "Ihr solltet probieren an Land zu suchen!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Die Suche nach dem ultimativen Artefakt ist erfolglos. Euer Held könnte es " "nicht tragen, selbst wenn er es gefunden hätte - alle seine Artefaktplätze " "sind voll." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" "Das Graben nach Artefakten dauert einen ganzen Tag, versucht es morgen noch " "einmal." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Nachdem Ihr hier viele Stunden gegraben habt, habt Ihr das %{artifact} " "gefunden." msgid "Congratulations!" msgstr "Gratulation!" msgid "Nothing here. Where could it be?" msgstr "Hier ist nichts. Wo könnte es nur sein?" msgid "Try searching on clear ground." msgstr "Versucht auf freiem Feld zu suchen." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Eine Miniaturansicht der bekannten Welt. Klickt mit der linken Maustaste, um " "den Sichtbereich zu verschieben." msgid "Month: %{month} Week: %{week}" msgstr "Monat: %{month} Woche: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Ihr findet eine kleine\n" "Menge %{resource}." msgid "Status Window" msgstr "Statusfenster" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Dieses Fenster gibt Auskunft über den Status Eures Helden oder Königreichs " "und zeigt das Datum an." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Dieses Fenster gibt Auskunft über den Status Eures Helden oder Königreichs " "und zeigt das Datum an. Klickt hier mit der linken Maustaste, um durch diese " "Fenster zu rotieren." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Damit kann die Startpositionen und Farben der Spieler geändert werden. Eine " "bestimmte Farbe beginnt immer an einer bestimmten Stelle. Einige Positionen " "können nur von einem Computerspieler oder nur von einem menschlichen Spieler " "gespielt werden." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Damit kann die Klasse eines Spielers geändert werden. Die Klassen sind nicht " "immer änderbar. Je nach Szenario kann ein Spieler zusätzliche Städte und/" "oder Helden erhalten, die nicht seiner primären Ausrichtung angehören." msgid "Handicap" msgstr "Handicap" # #, fuzzy msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Damit kann das Handicap eines bestimmten Spielers geändert werden. Nur " "Menschen können ein Handicap haben. Spieler mit Handicap beginnen mit " "weniger Ressourcen und erhalten 15 bzw. 30 % weniger Ressourcen pro Runde " "für leichte bzw. schwere Handicaps." msgid "%{color} player" msgstr "Spieler %{color}" msgid "No Handicap" msgstr "Kein Handicap" #, fuzzy msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Es gibt keine besonderen Beschränkungen für Startressourcen und deren Erwerb " "pro Zug." msgid "Mild Handicap" msgstr "Leichtes Handicap" # #, fuzzy msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Spieler mit einem leichten Handicap beginnen mit weniger Ressourcen und " "erhalten 15% weniger Ressourcen pro Zug." msgid "Severe Handicap" msgstr "Schweres Handicap" # #, fuzzy msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Spieler mit einem schwerem Handicap beginnen mit weniger Ressourcen und " "erhalten 30% weniger Ressourcen pro Zug." msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Angriff setzen" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Info über %{skill} anzeigen" #, fuzzy msgid "" "Default\n" "skill" msgstr "Verteidigung" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "LEERTASTE" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Einkommen" msgid "Kingdom Income per day." msgstr "Einkommen des Königreichs pro Tag." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Für jeden kontrollierten Leuchtturm bewegen sich Eure Schiffe jeden Tag " "weiter." msgid "English" msgstr "Englisch" msgid "French" msgstr "Französisch" msgid "Polish" msgstr "Polnisch" msgid "German" msgstr "Deutsch" msgid "Russian" msgstr "Russisch" msgid "Italian" msgstr "Italienisch" msgid "Czech" msgstr "Tschechisch" msgid "Norwegian" msgstr "Norwegisch" msgid "Belarusian" msgstr "Weißrussisch" msgid "Bulgarian" msgstr "Bulgarisch" msgid "Ukrainian" msgstr "Ukrainisch" msgid "Romanian" msgstr "Rumänisch" msgid "Spanish" msgstr "Spanisch" msgid "Swedish" msgstr "Schwedisch" msgid "Portuguese" msgstr "Portugiesisch" msgid "Turkish" msgstr "Türkisch" msgid "Dutch" msgstr "Niederländisch" msgid "Hungarian" msgstr "Ungarisch" msgid "Danish" msgstr "Dänisch" msgid "Slovak" msgstr "Slowakisch" msgid "Vietnamese" msgstr "Vietnamesisch" msgid "Slow" msgstr "Langsam" msgid "Fast" msgstr "Schnell" msgid "Very Fast" msgstr "Sehr Schnell" msgid "Evil" msgstr "Böse" msgid "Good" msgstr "Gut" msgid ", FPS: " msgstr ", FPS: " #, fuzzy msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} Räuber" #, fuzzy msgid "pyramid|%{object} raided" msgstr "%{object} überfallen" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natascha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Schwester Eliza" msgid "Brother Brax" msgstr "Bruder Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " gibt Euch maximale Moral" msgid " gives you maximum luck" msgstr " gibt Euch maximales Glück" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Das Zauberbuch kann nicht umgestellt werden" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" "Ihr könnt dieses Artefakt nicht aufsammlen, Ihr habt bereits eine volle " "Ladung!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Um Zaubersprüche auszusprechen zu können, müsst Ihr zuerst ein Zauberbuch " "für %{gold} Gold kaufen." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Leider scheint Ihr im Moment ein wenig knapp bei Kasse zu sein." msgid "Do you wish to buy one?" msgstr "Möchtet Ihr eines kaufen?" msgid "%{count} / day" msgstr "%{count} / Tag" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "Ein Strudel verschlingt Euer Schiff. Ein Teil Eurer Armee ist über Bord " "gegangen." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Beleidigt durch Eure Ablehnung ihres Angebots, greifen die Monster an!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "Erschrocken über die Macht Eurer Truppen beginnen die %{monster} sich zu " "zerstreuen.\n" "Wollt Ihr sie verfolgen und angreifen?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" "Bei der Plünderung eines feindlichen Lagers entdeckt Ihr eine versteckte " "Schatzkiste." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Der Wächter der Mühle verkündet:\n" "\"Mein Herr, ich habe sehr hart gearbeitet, um Euch diese Ressourcen zur " "Verfügung zu stellen, kommt nächste Woche wieder für mehr.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Der Wächter der Mühle meldet sich:\n" "\"Mein Herr, es tut mir leid, es sind derzeit keine Ressourcen verfügbar. " "Bitte versucht es nächste Woche noch einmal.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Der Wächter der Mühle verkündet:\n" "\"Mein Herr, ich habe sehr hart gearbeitet, um Euch dieses Gold zu " "beschaffen, kommt nächste Woche wieder für mehr.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Der Wächter der Mühle meldet:\n" "\"Mein Herr, es tut mir leid, es ist derzeit kein Gold verfügbar. Bitte " "versuch es nächste Woche wieder.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Ihr habt einen verlassenen Anbau gefunden.\n" "Beim Herumstöbern findet Ihr einige in der Nähe versteckte Ressourcen." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "Der Anbau ist schon lange verlassen. Es gibt hier nichts wertvolles." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Ihr fangt einen Kobold, der dummerweise inmitten eines Haufens von " "Zauberpilzen schläft.\n" "Im Tausch für seine Freilassung, führt er Euch zu einem mit wertvollen " "Dingen gefüllten Topf." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Ihr habt einen Zaubergarten gefunden, einem Ort an dem sich Kobolde und Feen " "gerne tummeln, aber heute ist niemand da.\n" "Vielleicht solltet Ihr es nächste Woche noch einmal versuchen." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Ihr stoßt auf die Überreste eines unglückseligen Abenteurers." msgid "Treasure" msgstr "Schatz" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Beim Durchsuchen der zerlumpten Kleidung findet Ihr %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Beim Durchsuchen der zerlumpten Kleidung findet Ihr nichts." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Ihr stoßt auf einen alten Wagen, der von einem Händler zurückgelassen wurde, " "der es nicht bis in sichere Gefilde geschafft hat." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Leider waren schon andere hier, der Wagen ist leer." msgid "Searching inside, you find the %{artifact}." msgstr "Ihr durchsucht ihn und findet ein %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Im Innern bemerkt Ihr, dass Teile der Ladung noch intakt sind." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Ihr durchsucht das Treibgut und findet etwas Holz und etwas Gold." msgid "You search through the flotsam, and find some wood." msgstr "Ihr durchsucht das Treibgut und findet etwas Holz." msgid "You search through the flotsam, but find nothing." msgstr "Ihr durchsucht das Treibgut, findet aber nichts." msgid "Shrine of the 1st Circle" msgstr "Schrein des ersten Kreises" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Ihr stoßt auf einen kleinen Schrein, der von einer Gruppe Akolyten-Novizen " "besucht wird.\n" "Als Gegenleistung für ihren Schutz erklären sie sich bereit, Euch einen " "einfachen Zauberspruch beizubringen - \"%{spell}\"." msgid "Shrine of the 2nd Circle" msgstr "Schrein des zweiten Kreises" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Ihr stoßt auf einen reichverzierten Schrein, der von einer Gruppe rundlicher " "Mönche besucht wird.\n" "Als Gegenleistung für ihren Schutz erklären sie sich bereit, Euch einen " "Zauberspruch zu lehren - \"%{spell}\"." msgid "Shrine of the 3rd Circle" msgstr "Schrein des dritten Kreises" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Ihr stoßt auf einen üppigen Schrein, der von einer Gruppe von Hohepriestern " "besucht wird.\n" "Als Gegenleistung für ihren Schutz erklären sie sich bereit, Euch einen " "raffinierten Zauberspruch beizubringen - \"%{spell}\"." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Leider habt Ihr nicht die Weisheit, den Zauberspruch zu verstehen, und könnt " "ihn nicht lernen." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Leider habt Ihr bereits Kenntnisse über diesen Zauber, so dass sie Euch " "nichts mehr beibringen können." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Leider habt Ihr kein Zauberbuch, um den Zauberspruch aufzuschreiben." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Ihr nähert Euch der Hütte und beobachtet darin eine Hexe, die einen uralten " "Wälzer über %{skill} studiert.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Als Ihr Euch nähert, dreht sie sich um und richtet ihr einziges Glasauge auf " "Euch.\n" "\"Du weißt bereits alles, was Du zu lernen verdienst!\", kreischt die Hexe. " "\"UND JETZT VERSCHWINDE AUS MEINEM HAUS!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Als Ihr Euch nähert, dreht sie sich um und spricht.\n" "\"Du weißt bereits, was ich Dich lehren möchte. Ich kann dir nicht weiter " "helfen.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Eine uralte und unsterbliche Hexe, die in einer Hütte lebt und Vogelbeine " "als Stelzen benutzt, lehrt Euch %{skill} für ihre eigenen undurchschaubaren " "Zwecke." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" "Als Ihr das süße Wasser trinkt, erhaltet Ihr Glück für Euren nächsten Kampf." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Ihr trinkt aus dem verwunschenen Brunnen, aber es passiert nichts." msgid "You enter the faerie ring, but nothing happens." msgstr "Ihr betretet den Feenring, aber nichts passiert." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Beim Betreten des mystischen Feenrings erhält Eure Armee Glück für die " "nächste Schlacht." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Ihr habt ein uraltes und verwittertes Steingötzenbild gefunden.\n" "Es soll den Besuchern Glück bringen, aber da Euch die Sterne bereits " "zulächeln, bewirkt es nichts." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Ihr habt ein altes und verwittertes Steingötzenbild gefunden.\n" "Ihn zu küssen soll Glück bringen, also tut Ihr es. Der Stein fühlt sich sehr " "kalt an." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Die Meerjungfrauen locken Euch leise dazu, später zurückzukehren und Euch " "erneut segnen zu lassen." #, fuzzy msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Die magische, beruhigende Schönheit der Meerjungfrauen erreicht Euch und " "Eure Besatzung.\n" "Nur für einen Moment vergesst Ihr Eure Sorgen und sonnt Euch in der " "Schönheit des Augenblicks.\n" "Der Charme der Meerjungfrauen segnet Euch mit mehr Glück für Euren nächsten " "Kampf." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Ihr stoßt auf die Pyramide eines großen Königs aus alten Zeiten.\n" "Ihr seid versucht, sie nach Schätzen zu durchsuchen, aber all die alten " "Geschichten warnen vor schrecklichen Flüchen und untoten Wächtern.\n" "Werdet Ihr suchen gehen?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Nachdem Ihr die Monster besiegt habt, entziffert Ihr alte Schriftzeichen an " "der Wand, die einen geheimen Zauberspruch preisgeben - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Leider habt Ihr kein Zauberbuch, um den Zauberspruch aufzuschreiben. " msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Leider habt Ihr nicht die Weisheit, den Zauberspruch zu verstehen, und könnt " "ihn nicht lernen." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Ihr stoßt auf die Pyramide eines großen Königs aus alten Zeiten.\n" "Die routinemäßige Erkundung zeigt, dass die Pyramide völlig leer ist." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Ein Schluck aus dem Brunnen soll Eure Zauberpunkte wiederherstellen, aber " "sie sind bereits am Maximum." msgid "A second drink at the well in one day will not help you." msgstr "" "Ein zweiter Schluck aus dem Brunnen am selben Tag wird Euch nicht helfen." msgid "A drink from the well has restored your spell points to maximum." msgstr "" "Ein Schluck aus dem Brunnen hat Eure maximalen Zauberpunkte " "wiederhergestellt." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Es tut mir leid, Herr\", sagt der Anführer der Soldaten, \"aber Ihr wisst " "bereits alles, was wir Euch beibringen könnten.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Die im Fort lebenden Soldaten bringen Euch ein paar neue Verteidigungstricks " "bei." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Ihr seid auf ein Lager gestoßen, wo Söldner ihre Taktik üben. \"Ihr seid zu " "weit fortgeschritten für uns\", sagt der Söldnerhauptmann. \"Wir können Euch " "nichts mehr beibringen.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Ihr seid auf ein Lager gestoßen, wo Söldner ihre Taktik üben. Die Söldner " "begrüßen Euch und Eure Truppen und laden Euch ein, mitzutrainieren. " msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" "\"Geh weg!\", schnauzt der Medizinmann, \"Du weißt alles, was ich weiß.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Ein Ork-Medizinmann, der in der Hütte lebt, vertieft Eure Kenntnisse über " "Magie, indem er Euch zeigt, wie man Steine wirft, Vorzeichen liest und die " "Verwicklungen von Hühnerinnereien entschlüsselt." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Ihr habt eine Gruppe von Druiden gefunden, die eines ihrer seltsamen " "Steinbauten anbeten. Die Druiden weisen Euch schweigend ab und geben zu " "verstehen, dass sie Euch nichts Neues beibringen können." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Ihr habt eine Gruppe von Druiden gefunden, die eines ihrer seltsamen " "Steinbauten anbeten. Im Stillen bringen diese Euch neue Wege bei " "Zaubersprueche anzuwenden." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Ihr nähert Euch zögerlich der Ruhestätte alter Krieger. Wollt Ihr die Gräber " "durchsuchen?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Ihr verbringt mehrere Stunden damit, die Gräber zu durchsuchen und findet " "nichts. Ein solch abscheulicher Akt senkt die Moral Eurer Armee." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "Nachdem Ihr die Zombies besiegt habt, durchsucht Ihr die Gräber und findet " "etwas!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Der faulige Rumpf eines großen Piratenschiffs knarrt unheimlich, als er " "gegen die Felsen gedrückt wird. Wollt Ihr das Schiffswrack durchsuchen?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Nachdem Ihr die Geister besiegt habt, verbringt Ihr mehrere Stunden damit, " "die Trümmer zu durchsuchen und findet nichts. Solch eine " "verabscheuungswürdige Tat senkt die Moral Eurer Armee." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" "Nachdem Ihr die Geister besiegt habt, durchsucht Ihr die Trümmer und finden " "etwas!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Der faulige Rumpf eines großen Piratenschiffs knarrt unheimlich, als er " "gegen die Felsen gedrückt wird. Wollt Ihr das Schiffswrack durchsuchen?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "Nachdem Ihr die Skelette besiegt habt, durchsucht Ihr die Trümmer und finden " "etwas!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Eure Männer entdecken eine Navigationsboje, die Euch bestätigt, dass Ihr auf " "Kurs seid." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Eure Männer entdecken eine Navigationsboje, die Euch bestätigt, dass Ihr auf " "Kurs seid. Dies steigert Eure Moral." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Der Schluck an der Oase ist erfrischend, bietet aber keinen weiteren Nutzen. " "Die Oase könnte helfen, wenn Ihr zuvor eine Schlacht geschlagen habt." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Ein Schluck an der Oase gibt Eure Truppen Stärke und hebt deren Stimmung. So " "könnt Ihr heute etwas weiter reisen." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Der Schluck an der Wasserstelle ist erfrischend, bietet aber keinen weiteren " "Nutzen. Die Wasserstelle könnte helfen, wenn Ihr zuvor eine Schlacht " "geschlagen habt." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Ein Schluck an dem Wasserstelle gibt Eure Truppen Stärke und hebt deren " "Stimmung. So könnt Ihr heute etwas weiter reisen." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Es nützt nichts, vor einem Kampf zweimal zu beten. Kommt zurück, nachdem Ihr " "gekämpft habt." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Ein Besuch des Tempels und ein Gebet heben die Moral Eurer Truppen." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Ein alter Ritter erscheint auf den Stufen des Pavillons. \"Es tut mir leid, " "mein Herr, ich habe Euch alles beigebracht, was ich kann.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Ein alter Ritter erscheint auf den Stufen des Pavillons. \"Mein Herr, ich " "werde Euch alles lehren, was ich weiß, um Euch auf Eurer Reise zu helfen.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Ihr habt einen Schiffbrüchigen vor dem sicheren Tod im unbarmherzigen Ozean " "gerettet. Dankbar sagt er: \"Ich würde Euch ein Artefakt als Belohnung " "geben, aber Ihr seid schon voll davon.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Ihr habt einen Schiffbrüchigen vor dem sicheren Tod im unbarmherzigen Ozean " "gerettet. Aus Dankbarkeit belohnt er Euch für Euren Akt der Freundlichkeit, " "indem er Euch die %{art} schenkt." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "Ein Kobold bietet Euch die %{art} für den kleinen Preis von %{gold} Gold an." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Ein Kobold bietet Euch die %{art} für den kleinen Preis von %{gold} Gold und " "%{count} %{res} an." msgid "Do you wish to buy this artifact?" msgstr "Möchtet Ihr dieses Artefakt kaufen?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Ihr wollt den Kobold bezahlen, merkt aber, dass Ihr es Euch nicht leisten " "könnt. Der Kobold stampft mit dem Fuß auf und ignoriert Euch." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Beleidigt durch Eure Ablehnung seines großzügigen Angebots, stampft der " "Kobold mit dem Fuß auf und ignoriert Euch." msgid "You've found the artifact: " msgstr "Ihr habt das Artefakt gefunden: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Ihr habt die bescheidene Behausung eines vertrockneten Einsiedlers gefunden. " "Der Einsiedler erzählt Euch, dass er bereit ist, die %{art} dem ersten " "weisen Menschen zu geben, den er trifft." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Ihr seid auf das spartanische Quartier eines pensionierten Soldaten " "gestoßen. Der Soldat erzählt Euch, dass er bereit ist, die %{art} an den " "ersten wahren Anführer weiterzugeben, den er trifft." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Ihr seid einer seltsamen Person mit einem Hut und einer Eule darauf " "begegnet. Er sagt Euch, dass er bereit ist, %{art} zu geben, wenn Ihr " "%{skill} habt." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Ihr stoßt auf ein antikes Artefakt. Als Ihr danach greift, springt eine " "Bande Schurken aus dem Gebüsch, um ihre gestohlene Beute zu verteidigen." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Auf einer Lichtung entdeckt Ihr ein antikes Artefakt. Leider wird es von " "einem %{monster} in der Nähe bewacht. Wollt Ihr gegen %{monster} um das " "Artefakt kämpfen?" msgid "Victorious, you take your prize, the %{art}." msgstr "Siegreich nehmt Ihr Euren Preis, die %{art}, entgegen." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "Besonnenheit ist wichtiger als Werte und so beschließt Ihr, diesen Kampf für " "heute zu vermeiden." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Nachdem Ihr stundenlang versucht habt, die Kiste aus dem Meer zu fischen, " "öffnet Ihr sie und findet %{gold}-Goldstücke." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Nachdem Ihr stundenlang versucht habt, die Kiste aus dem Meer zu fischen, " "öffnet Ihr sie und findet %{gold} Gold und die %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Nachdem Ihr stundenlang versucht habt, die Kiste aus dem Meer zu fischen, " "öffnet Ihr sie, nur um sie leer vorzufinden." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Nachdem Ihr das Gebiet durchkämmt habt, stoßt Ihr auf eine verborgene " "Schatzkiste. Ihr könnt das Gold nehmen oder das Gold an die Bauern gegen " "Erfahrungspunkte verteilen. Möchtet Ihr das Gold behalten?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Nachdem Ihr das Gebiet durchkämmt habt, stoßt Ihr auf eine versteckte Kiste, " "die %{gold} Goldstücke enthält." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Nachdem Ihr das Gebiet durchkämmt habt, stoßt Ihr auf eine versteckte Kiste, " "die das antike Artefakt %{art} enthält." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Ihr stolpert über eine verbeulte und angeschlagene Lampe, die tief im Boden " "steckt. Möchtet Ihr an der Lampe reiben?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Ihr habt nun die Kontrolle über den örtlichen Alchemistenladen. Er versorgt " "Euch mit %{count} Einheit Quecksilber pro Tag." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Ihr erlangt die Kontrolle über ein Sägewerk. Es wird Euch mit %{count} " "Einheiten Holz pro Tag versorgen." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Ihr erlangt die Kontrolle über eine Erzmine. Sie versorgt Euch mit %{count} " "Einheiten Erz pro Tag." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Ihr erlangt die Kontrolle über eine Schwefelmine. Sie versorgt Euch mit " "%{count} Einheiten Schwefel pro Tag." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Ihr erlangt die Kontrolle über eine Kristallmine. Sie versorgt Euch mit " "%{count} Einheit Kristall pro Tag." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Ihr erlangt die Kontrolle über eine Edelsteinmine. Sie versorgt Euch mit " "%{count} Einheit Edelsteine pro Tag." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Ihr erlangt die Kontrolle über eine Goldmine. Sie versorgt Euch mit %{count} " "Gold pro Tag." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Der Leuchtturm ist nun unter Eurer Kontrolle, und all Eure Schiffe bewegen " "sich nun jeden Tag weiter." msgid "You gain control of a %{name}." msgstr "Ihr erlangt die Kontrolle über einen %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Ihr stoßt auf eine verlassene Goldmine. In der Mine scheint es zu spuken. " "Möchtet Ihr hineingehen?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" "Ihr habt die Geister besiegt und könnt die Mine wieder in Betrieb nehmen." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Eine Gruppe von %{monster} mit dem Wunsch nach größerem Ruhm möchte sich " "Euch anschließen. Akzeptiert Ihr?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Als Ihr Euch der Behausung nähert, bemerkt Ihr, dass niemand da ist." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Ihr durchsucht die Ruinen, aber die Medusen, die hier früher lebten, sind " "weg. Vielleicht gibt es nächste Woche mehr." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Ihr habt einige Medusen gefunden, die in den Ruinen leben. Sie sind bereit, " "sich Eurer Armee für einen bestimmten Preis anzuschließen. Möchtet Ihr " "Medusen rekrutieren?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Ihr habt ein Baumhaus gefunden. Leider ist keine der hier lebenden Feen " "bereit, sich Eurer Armee anzuschließen. Vielleicht in der nächsten Woche." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Einige der im Baumhaus lebenden Feen sind bereit, sich Eurer Armee für einen " "bestimmten Preis anzuschließen. Möchtet Ihr Feen rekrutieren?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Ein bunter Wagen der Schurken steht leer da. Vielleicht sind später ein paar " "Schurken hier." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Ferne Klänge von Musik und Gelächter führen Euch zu einem bunten Wagen, in " "dem Schurken wohnen. Möchtet Ihr, dass sich Schurken Eurer Armee anschließen?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Ihr bemerket eine Gruppe zerlumpter Zelte, die sich im sandigen Wind wiegen. " "Die Zelte stehen leer. Vielleicht sind spaeter ein paar Nomaden hier. " msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Ihr bemerkt eine Gruppe zerlumpter Zelte, die sich im sandigen Wind wiegen. " "Wünscht Ihr, dass sich Euch Nomaden auf Eurer Reise anschließen?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Die Schlammgrube blubbert für einen Moment und ist dann wieder ruhig." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Als Ihr Euch der blubbernden Schlammgrube nähert, beginnen Kreaturen " "herauszuklettern und umstellen Euch. Im Enklang sagen sie: \"Mutter Erde " "möchte Euch ein paar ihrer Truppen anbieten. Wollt Ihr Erdwesen rekrutieren?" "\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Ihr betretet die Struktur aus weißen Steinsäulen und findet nichts." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Weiße Steinsäulen stützen ein Dach, das sich in den Himmel erhebt. Als Ihr " "das Bauwerk betretet, weicht die tote Luft des Außenbereichs einem " "wirbelnden Windstoß, der Euch fast wieder hinausdrängt. Der Luftstrom " "materialisiert sich zu einer kaum sichtbaren Gestalt. Die Kreatur fragt, was " "man nur als lautes Flüstern bezeichnen kann: \"Warum bist du gekommen? Bist " "du hier, um die Mächte der Luft anzurufen?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Es nähern sich keine Feuerwesen aus dem Lavapool." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Unter einer Struktur, die dazu dient, die Hitze zurückzuhalten, bewegen sich " "Feuerwesen in einem feurigen Becken aus geschmolzener Lava. Eine Gruppe von " "ihnen kommt auf Euch zu und bietet Euch ihre Dienste an. Möchtet Ihr " "Feuerwesen rekrutieren?" msgid "A face forms in the water for a moment, and then is gone." msgstr "" "Ein Gesicht formt sich für einen Moment im Wasser und ist dann verschwunden." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Kristalline Strukturen werfen Schatten auf ein kleines, spiegelndes " "Wasserbecken. Ihr blickt in das Becken, und ein Gesicht, das nicht Euer " "eigenes ist, blickt zurück. Es fragt: \"Möchtet Ihr die Kräfte des Wassers " "anrufen?\"" msgid "This burial site is deathly still." msgstr "Diese Grabstätte ist totenstill." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Rastlose Geister längst verstorbener Krieger, die ihre letzte Ruhe suchen," "bieten Euch an, sich Euch anzuschließen, in der Hoffnung, Frieden zu finden. " "Möchtet Ihr Geister rekrutieren?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "In der Stadt der Toten gibt es kein Leben aber auch keine Untoten. " "Vielleicht werden nächste Woche einige Untote eingezogen sein." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Einige hier lebende Liches sind bereit, sich Eurer Armee gegen einen Preis " "anzuschließen. Wollt Ihr Liches rekrutieren?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Ihr habt die Ruinen einer alten Stadt gefunden, die jetzt nur noch von " "Untoten bewohnt wird. Werdet Ihr danach suchen?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Einige der überlebenden Liches sind von Eurem Sieg über ihre Gefährten " "beeindruckt und bieten Euch an, sich Euch gegen einen Preis anzuschließen. " "Wollt Ihr Liches rekrutieren?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Ihr habt eine dieser Brücken gefunden, unter denen Trolle so gerne leben, " "aber es sind keine hier. Vielleicht wird es nächste Woche hier welche geben." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Einige Trolle, die unter einer Brücke leben, sind bereit gegen einen Preis " "Eurer Armee beizutreten. Wollt Ihr Trolle rekrutieren?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Trolle, die unter der Brücke leben, fordern Euch heraus. Werdet Ihr sie " "bekämpfen?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Ein paar Trolle bleiben zusammengekauert unter der Bruecke. Sie nähern sich " "Euch und bieten an, sich Euren Truppen anzuschliessen. Wollt Ihr Trolle " "rekrutieren?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "Die Drachenstadt hat diese Woche keine Drachen, die bereit sind, sich Euch " "anzuschließen. Vielleicht wird nächste Woche ein Drache zur Verfügung stehen." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Die Drachenstadt ist bereit, Euch gegen einen Preis einige Drachen für Eure " "Armee anzubieten. Möchtet Ihr Drachen rekrutieren?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Ihr steht vor der Drachenstadt, ein Ort, an dem Menschen keinen Zutritt " "haben. Wollt Ihr gegen diese Regel verstoßen und die Drachen zu einem Kampf " "herausfordern?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Da Ihr die Drachenmeister besiegt habt, erklären sich die Anführer der Stadt " "bereit, Eurer Armee einige Drachen für einen bestimmten Preis zur Verfügung " "zu stellen. Möchtet Ihr Drachen rekrutieren?" msgid "From the observation tower, you are able to see distant lands." msgstr "Vom Beobachtungsturm aus könnt Ihr ferne Ländereien sehen." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Die Quelle füllt sich nur einmal die Woche, und diese Woche war schon jemand " "hier." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Ein Schluck an der Quelle soll Euch das Doppelte Eurer normalen Zauberpunkte " "geben, aber sie sind bereits auf dieser Stufe." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Ein Schluck aus der Quelle füllt Euer Blut mit Magie! Ihr habt das Doppelte " "Eurer normalen Zauberpunkte in Reserve." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Der Butler erkennt Euch und verweigert Euch den Einlass. \"Der Hausherr\", " "sagt er, \"möchte denselben Schüler nicht zweimal sehen.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Der Butler gewährt Euch Einlass zum Hausherr. Dieser bildet Euch aus in den " "vier Fertigkeiten, die ein Held beherrschen sollte." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Der Butler öffnet die Tür und mustert Euch von oben bis unten. \"Ihr seid " "weder berühmt noch diplomatisch genug, um zu meinem Herrn vorgelassen zu " "werden\", schnieft er. \"Kommt wieder, wenn Ihr Euch für würdig haltet.\"" msgid " and " msgstr " und " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Alle %{monsters}, die Ihr in Eurer Armee habt, wurden von den Kampfmeistern " "der Forts ausgebildet. Eure Armee beinhaltet nun %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Eine ungewöhnliche Allianz aus Ogern, Orks und Zwergen bietet an, alle " "solche Truppen, die zu ihnen gebracht werden, auszubilden (aufzurüsten). " "Leider habt Ihr keine davon dabei." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "All Eure %{monsters} wurden zu %{monsters2} aufgerüstet." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Ein Schmied, der in der Gießerei arbeitet, bietet an, die Waffen von " "Speermänner und Schwertkämpfer, die zu ihm gebracht werden, von Eisen in " "Stahl umzuwandeln. Er sagt auch, dass er ein Verfahren kennt, mit dem man " "Eisengoleme in Stahlgoleme umwandeln kann. Leider habt Ihr keine dieser " "Truppen in Eurer Armee, sodass er Euch nicht helfen kann." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Der Kapitän sieht Euch überrascht an und sagt:\n" "\"Ihr habt bereits alle Karten, die ich kenne. Lasst mich jetzt in Ruhe " "fischen.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Ein pensionierten Kapitän, der die renovierten Angelplattform bewohnt, " "bietet Euch für 1.000 Goldstücke Seekarten zum Kauf an, die er in seinen " "jüngeren Tagen angefertigt hat. Möchtet Ihr die Karten kaufen?" #, fuzzy msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Der Kapitän seufzt. \"Du hast nicht genug Geld, was? Du kannst nicht " "erwarten, dass ich meine Karten umsonst herausgebe!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Ihr stoßt auf einen Obelisken, aus einer Steinsorte gemacht, die Ihr noch " "nie gesehen habt. Ihr starrt ihn intensiv an, als auf der glatten Oberfläche " "plötzlich eine Inschrift erscheint. Die Inschrift ist ein Stück einer alten " "verlorenen Karte. Schnell malt Ihr das Stück ab und die Inschrift " "verschwindet so schnell, wie sie erschienen war." msgid "You have already been to this obelisk." msgstr "Ihr wart bereits an diesem Obelisken." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Als Ihr Euch nähert, öffnet der Baum erfreut seine Augen. \"Es ist schön, " "Dich zu sehen, mein Schüler. Ich hoffe, meine Lehren haben Dir geholfen.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Als Ihr Euch nähert, öffnet der Baum erfreut seine Augen. \"Ahh, ein " "Abenteurer! Erlaube mir, Dich ein wenig von dem zu lehren, was ich im Laufe " "der Zeit gelernt habe.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Als Ihr Euch nähert, öffnet der Baum erfreut seine Augen." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ahh, ein Abenteurer! Ich bringe Dir gerne ein wenig von dem bei, was ich " "im Laufe der Zeit gelernt habe, für nur %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Vergrabe es einfach neben meine Wurzeln.)" msgid "Tears brim in the eyes of the tree." msgstr "In den Augen des Baumes kullern Tränen." msgid "\"I need %{count} %{res}.\"" msgstr "\"Ich brauche %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" "flüstert er. (schnieft) \"Na, dann komm wieder, wenn du mich bezahlen kannst." "\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Eingebettet zwischen den Bäumen sitzt ein blinder Wahrsager. Nachdem Ihr die " "Absicht Eurer Reise erklärt habt, aktiviert er seine Kristallkugel und Ihr " "könnt die Stärken und Schwächen Eurer Gegner sehen." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Der Eingang der Höhle ist dunkel, und ein fauliger, schwefliger Geruch " "strömt aus dem Höhleneingang. Werdet Ihr eintreten?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Bis auf die Spuren einer schrecklichen Schlacht ist die Höhle leer." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Ihr findet einen mächtigen und grotesken Dämon in der Höhle. \"Heute\", " "krächzt er, \"wirst Du kämpfen und sicher sterben. Aber ich lasse Dir die " "Wahl zwischen zwei Todesarten. Du kannst gegen mich kämpfen, oder gegen " "meine Diener. Willst Du lieber gegen meine Diener kämpfen?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Der Dämon schreit herausfordernd und greift an! Nach einem kurzen, " "verzweifelten Kampf erschlagt Ihr das Monster und erhaltet %{exp} " "Erfahrungspunkte." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Der Dämon schreit herausfordernd und greift an! Nach einem kurzen, " "verzweifelten Kampf erschlagt Ihr das Monster und erhaltet %{exp} " "Erfahrungspunkte und %{count} Goldstücke." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Der Dämon schreit herausfordernd und greift an! Nach einem kurzen, " "verzweifelten Kampf erschlagt Ihr das Monster und findet die %{art} im " "hinteren Teil der Höhle." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Als der Dämon sieht, dass Ihr keine %{count} Goldstücke habt, schlitzt er " "Euch mit seinen Klauen auf. Das Letzte, was Ihr seht, ist ein roter Schleier." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Der Dämon stürzt sich auf Euch und krallt sich in Eure Kehle, bevor Ihr " "überhaupt Euer Schwert ziehen könnt. \"Dein Leben ist mein\", sagt er. \"Ich " "werde es Dir für %{count} Goldstücke zurückverkaufen.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Nachdem Ihr die Diener des Dämons besiegt habt, findet Ihr ein verborgenes " "Versteck mit %{count} Goldstücken." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Als Ihr den Alchemistenturm betretet, kommt ein humpelnder, ergrauter Mann " "in einem braunen Umhang auf Euch zu." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" "Er prüft Euer Gepäck und sieht, dass Ihr einen verfluchten Gegenstand habt." msgstr[1] "" "Er prüft Euer Gepäck und sieht, dass Ihr %{count} verfluchte Gegenstände " "habt." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "Für %{gold} Gold wird der Alchemist es für Euch entfernen. Bezahlt Ihr?" msgstr[1] "" "Für %{gold} Gold wird der Alchemist die für Euch entfernen. Bezahlt Ihr?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Nachdem Ihr eingewilligt habt, den geforderten Goldbetrag zu zahlen, " "schnappt sich der Alchemist das verfluchte Artefakt und wirft es in seinen " "magischen Kessel." msgstr[1] "" "Nachdem Ihr eingewilligt habt, den geforderten Goldbetrag zu zahlen, " "schnappt sich der Alchemist alle verfluchten Artefakte und wirft sie in " "seinen magischen Kessel." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Ihr hört hinter der verschlossenen Tür eine Stimme: \"Ihr habt nicht genug " "Gold, um meine Dienste zu bezahlen.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Ihr hört eine Stimme von hoch oben aus dem Turm: \"Geh weg! Ich kann Dir " "nicht helfen!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Der Stallmeister spricht zu Euch: \"Das ist ein schönes Pferd, das Ihr da " "habt. Ich fürchte, wir können Euch kein besseres geben, aber die Pferde, " "Eurer Kavallerie, scheinen aus schlechter Zucht zu sein. Wir haben viele " "trainierte Kriegspferde, die Euren Reitern sehr helfen würden. Ich bestehe " "darauf, dass Ihr sie nehmt.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Als Ihr Euch den Ställen nähert, erscheint der Stallmeister und führt ein " "bestens aussehendes Schlachtross. \"Dieses Ross wird Euch helfen, Eure " "Reisen zu beschleunigen. Leider wird es in einer Woche müde werden. Ihr " "müsst mir auch erlauben, Euren berittenen Soldaten bessere Pferde zu geben, " "ihre Pferde sehen schäbig und schwach aus.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Der Oberpfleger tritt an Euch heran und spricht: \"Ihr habt bereits ein " "schönes Pferd und keine unerfahrene Kavallerie, die unsere trainierten " "Schlachtrösser gebrauchen könnte.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Als Ihr Euch den Ställen nähert, erscheint der Stallmeister und führt ein " "gut aussehendes Schlachtross. \"Dieses Ross wird Euch auf Euren Reisen " "helfen, schneller voranzukommen. Leider wird seine Ausdauer bei viel " "schwerem Reiten nachlassen, und Ihr müsst in einer Woche wiederkommen, um " "ein neues Pferd zu holen. Wir haben auch viele gute Kriegspferde, die " "berittenen Soldaten helfen könnten, aber Ihr habt keines, dem wir helfen " "können.\"" msgid "The Arena guards turn you away." msgstr "Die Wachen der Arena weisen Euch ab." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Eure Mannschaft muss sich die Ohren mit Wachs zustopfen, bevor der " "unheimliche Gesang der Sirenen sie in ein nasses Grab lockt." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Als die Sirenen ihr unheimliches Lied singen, gelingt es Eurer kleinen, " "entschlossenen Armee, den Drang zu überwinden, kopfüber ins Meer zu stürzen." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Von den auf den Felsen sitzenden Sirenen geht ein unheimliches Klagelied " "aus. Viele Eurer Mannschaft geraten in seinen Bann und tauchen ins Wasser, " "wo sie ertrinken. Ihr seid nun um diesen Besuch reicher und erhaltet %{exp} " "Erfahrung." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "In einem Anflug von Wagemut brecht Ihr in das örtliche Gefängnis ein und " "befreit den hier eingesperrten Helden, der Euch als Dank seine Treue schwört." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Ihr habt bereits %{count} Helden und müsst leider den Gefangenen hier in " "unbeschreiblichen Qualen zurücklassen." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Ihr betretet eine klapprige Hütte und sprecht mit dem dort lebenden Magier. " "Er erzählt Euch von Orten, nah und fern, die Euch auf Euren Reisen hilfreich " "sein könnten." msgid "This eye seems to be intently studying its surroundings." msgstr "Dieses Auge scheint aufmerksam seine Umgebung zu studieren." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Ihr stoßt auf eine riesige Sphinx. Die Sphinx bleibt seltsam ruhig." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Ich habe ein Rätsel für Dich\", sagt die Sphinx. \"Antwortest Du richtig, " "so sollst Du belohnt werden. Antwortest Du falsch, so sollst Du gefressen " "werden. Nimmst du die Herausforderung an?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Die Sphinx stellt Euch das folgende Rätsel:\n" "\n" "'%{riddle}'\n" "\n" "Eure Antwort?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Du hast falsch geraten\", sagt die Sphinx und lächelt. Die Sphinx schlägt " "mit einer Pranke nach Euch und wirft Euch zu Boden. Ein weiterer Schlag, und " "Euch wird schwarz vor Augen. Das ist Eure letzte Erinnerung." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Ein wenig enttäuscht wirkend säufzt die Sphinx. \"Du hast mein Rätsel " "gelöst, hier ist Deine Belohnung. Und nun verschwinde.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Eine magische Barriere ragt hoch vor Euch auf und versperrt Euch den Weg. In " "Runen steht auf dem Bogen,\n" "\"Sprich das Schlüsselwort und du darfst passieren.\"\n" "Als Ihr das magische Wort sprecht, löst sich die glühende Barriere in Nichts " "auf." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Eine magische Barriere ragt hoch vor Euch auf und versperrt Euch den Weg. In " "Runen steht auf dem Bogen,\n" "\"Sprich das Schlüsselwort und du kannst passieren.\"\n" "Ihr sprecht, aber nichts passiert." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Ihr betretet das Zelt und seht dort eine alte Frau, auf einen magischen " "Edelstein starrt. Sie schaut zu Euch auf und sagt,\n" "\"Auf meinen Reisen habe ich viel über die geheim Magie gelernt. Ein großes " "Orakel lehrte mich sein Können. Ich habe die Antwort, die Ihr sucht.\"" msgid "No spell book is present." msgstr "Kein Zauberbuch vorhanden." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Dieser Zauberspruch kostet %{mana} Zauberpunkte. Ihr habt keine " "Zauberpunkte, also könnt Ihr den Zauber nicht sprechen." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Dieser Zauberspruch kostet %{mana} Zauberpunkte. Ihr habt nur %{point} " "Zauberpunkte, also könnt Ihr den Zauber nicht sprechen." msgid "The spell was not found." msgstr "Der Zauberspruch wurde nicht gefunden." msgid "Only heroes can cast this spell." msgstr "Nur Helden können diesen Zauberspruch sprechen." msgid "This hero is not able to cast adventure spells." msgstr "Dieser Held ist nicht in der Lage, Abenteuerzauber zu sprechen." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Euer Held ist zu müde, um heute diesen Zauber auszusprechen. Versucht es " "morgen erneut." msgid "This spell cannot be cast on a boat." msgstr "Dieser Zauber kann nicht auf einem Boot verwendet werden." msgid "This spell can only be cast near an ocean." msgstr "Dieser Zauber kann nur in der Nähe von Wasser verwendet werden." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "In der Nähe des Helden gibt es kein Boot und keinen freien Platz im Meer, um " "diesen Zauber zu verwenden." msgid "There are no boats available for this spell." msgstr "Es ist kein Boot verfügbar, um diesen Zauber zu verwenden." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "In der Nähe des Helden gibt es kein Gewässer, in dem dieser Zauber wirken " "könnte." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Ihr besitzt derzeit keine Stadt oder Burg, die nicht von einem Helden " "bewohnt wird, daher kann der Zauber nicht wirken." msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Dieser Held befindet sich bereits in einer Stadt, sodass dieser Zauber nicht " "verwendet werden kann." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Die nächstgelegene Stadt ist %{town}.\n" "\n" "Diese Stadt ist von deinem Helden %{hero} besetzt." msgid "This spell is already in effect." msgstr "Dieser Zauber ist bereits in Gebrauch." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Kein Gegner kann mehr Helden unter seinem Kommando haben. Das Aussprechen " "dieses Zaubers bringt keinen Vorteil." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Kein Gegner hat zu diesem Zeitpunkt einen Helden unter seinem Kommando. Das " "Aussprechen dieses Zaubers bringt keinen Vorteil." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Ihr müsst sich innerhalb von %{count} Feldern eines Monsters befinden, damit " "die Vision wirkt." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Ihr müsst am Eingang einer Mine stehen (Sägewerke und Alchemisten zählen " "nicht), um diesen Zauber auzusprechen." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Damit dieser Zauber wirkt, müssen zuerst die Geister besiegt werden, die die " "Mine bewachen." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Es gibt mehr Elementare, die die Mine bewachen, als der Zauberspruch " "erzeugenkann. Daher kann dieser Zauber nicht wirken." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name} (Stufe %{level} %{race})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} (Stufe %{level})" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{name} (Stufe %{level} %{race})" #, fuzzy msgid "Hero race:" msgstr "Heldenbildschirm" msgid "Are you sure you want to dismiss this Hero?" msgstr "Seid Ihr sicher, dass Ihr diesen Helden entlassen wollt?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Infos zur Erfahrung anzeigen" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Zauberpunkte" msgid "View Spell Points Info" msgstr "Infos zu Zauberpunkten anzeigen" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Den Helden verlieren: %{name}." #, fuzzy msgid "Click to change race." msgstr "Klicken um die nächste Stadt anzuzeigen." #, fuzzy msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Die \"Verstreute\" Kampfformation verteilt die Armeen von oben bis unten " "über das Schlachtfeld, mit wenigstens einem Freiraum zwischen jeder Armee." #, fuzzy msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "Die 'Gruppierte' Kampfformation bündelt Eure Armee in der Mitte Eurer Seite " "des Schlachtfelds." msgid "Exit Hero Screen" msgstr "Heldenbildschirm verlassen" msgid "You cannot dismiss a hero in a castle" msgstr "Man kann einen Helden nicht in einer Burg entlassen" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Die Entlassung von %{name} (%{race}) ist durch das Szenario verboten" msgid "Dismiss %{name} the %{race}" msgstr "%{name} (%{race}) entlassen" msgid "Show previous hero" msgstr "Vorherigen Helden anzeigen" msgid "Show next hero" msgstr "Nächsten Helden anzeigen" msgid "Set army combat formation to 'Spread'" msgstr "Armeekampfformation auf \"Ausbreitend\" einstellen" msgid "Set army combat formation to 'Grouped'" msgstr "Armeekampfformation auf \"Gruppiert\" einstellen" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Hier klicken, um auszuwählen, welches Szenario gespielt werden soll." msgid "Blood Morale" msgstr "Blutmoral" msgid "%{morale} Morale" msgstr "%{morale} Moral" msgid "%{luck} Luck" msgstr "%{luck} Glück" msgid "Current Luck Modifiers:" msgstr "Aktuelle Glücksmodifikatoren:" msgid "Current Morale Modifiers:" msgstr "Aktuelle Moralmodifikatoren:" msgid "Entire army is undead, so morale does not apply." msgstr "Die gesamte Armee ist untot, also gilt die Moral nicht." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Aktuelle Erfahrung %{exp1}.\n" " Nächste Stufe %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Stufe %{level}" #, fuzzy msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} hat derzeit %{point} Zauberpunkte von maximal %{max}. Die " "Maximalzahl der Zauberpunkte ist das 10-fache Eures Wissens. Es ist " "gelegentlich möglich, durch besondere Ereignisse mehr als die maximale " "Anzahl an Zauberpunkten zu erhalten." msgid "%{name1} meets %{name2}" msgstr "%{name1} trifft %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Feindliche Helden sind jetzt vollständig identifizierbar." msgid "Identify Hero" msgstr "Held identifiz." msgid "Select town to port to." msgstr "Zielstadt auswählen." msgid "Town Portal" msgstr "Stadtportal" msgid "The creatures are willing to join us!" msgstr "Die Kreaturen sind bereit, sich uns anzuschließen!" msgid "All the creatures will join us..." msgstr "Alle Kreaturen werden sich uns anschließen..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Die Kreatur wird sich uns anschließen..." msgstr[1] "%{count} der Kreaturen werden sich uns anschließen..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "gegen %{gold} Goldstücke." msgid "These weak creatures will surely flee before us." msgstr "Diese schwachen Kreaturen werden sicher vor uns fliehen." msgid "I fear these creatures are in the mood for a fight." msgstr "Ich fürchte, diese Kreaturen sind in der Stimmung für einen Kampf." #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Eure Angriffsfähigkeit ist ein Bonus, der zur Angriffsfähigkeit jeder " "Kreatur addiert wird." #, fuzzy msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Eure Verteidigungsfähigkeit ist ein Bonus, der zur Verteidigungsfähigkeit " "jeder Kreatur addiert wird." #, fuzzy msgid "The hero's spell power determines the duration or power of a spell." msgstr "Eure Zauberkraft bestimmt die Länge oder Stärke eines Zaubers." #, fuzzy msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Euer Wissen bestimmt, wie viele Zauberpunkte Euer Held haben darf. Unter " "normalen Umständen ist ein Held auf 10 Zauberpunkte pro Wissensstufe " "beschränkt." msgid "Current Modifiers:" msgstr "Aktuelle Modifikatoren:" msgid "skill|Basic" msgstr "Einfach" msgid "skill|Advanced" msgstr "Verbessert" msgid "skill|Expert" msgstr "Meisterhaft" msgid "Pathfinding" msgstr "Pfadfinden" msgid "Archery" msgstr "Bogen" msgid "Logistics" msgstr "Logistik" msgid "Scouting" msgstr "Spähen" msgid "Diplomacy" msgstr "Diplomatie" msgid "Navigation" msgstr "Navigation" msgid "Leadership" msgstr "Führung" msgid "Wisdom" msgstr "Weisheit" msgid "Mysticism" msgstr "Mystik" msgid "Ballistics" msgstr "Ballistik" msgid "Eagle Eye" msgstr "Adlerauge" msgid "Necromancy" msgstr "Nekromantie" msgid "Estates" msgstr "Grundbesitz" msgid "Advanced Archery" msgstr "Verbessert Bogen" msgid "Advanced Pathfinding" msgstr "Verbessert Pfadfinden" msgid "Basic Archery" msgstr "Einfach Bogen" msgid "Basic Pathfinding" msgstr "Einfaches Pfadfinden" msgid "Expert Pathfinding" msgstr "Meisterhaft Pfadfinden" msgid "Advanced Logistics" msgstr "Verbesserte Logistik" msgid "Basic Logistics" msgstr "Einfache Logistik" msgid "Basic Scouting" msgstr "Einfaches Spähen" msgid "Expert Archery" msgstr "Meisterhaft Bogen" msgid "Expert Logistics" msgstr "Meisterhafte Logistik" msgid "Advanced Diplomacy" msgstr "Verbesserte Diplomatie" msgid "Advanced Scouting" msgstr "Verbessertes Spähen" msgid "Basic Diplomacy" msgstr "Einfache Diplomatie" msgid "Expert Diplomacy" msgstr "Meisterhafte Diplomatie" msgid "Expert Scouting" msgstr "Meisterhaftes Spähen" msgid "Advanced Leadership" msgstr "Verbesserte Führung" msgid "Advanced Navigation" msgstr "Verbesserte Navigation" msgid "Basic Leadership" msgstr "Einfache Führung" msgid "Basic Navigation" msgstr "Einfache Navigation" msgid "Expert Navigation" msgstr "Meisterhafte Navigation" msgid "Advanced Wisdom" msgstr "Verbesserte Weisheit" msgid "Basic Mysticism" msgstr "Einfache Mystik" msgid "Basic Wisdom" msgstr "Einfache Weisheit" msgid "Expert Leadership" msgstr "Meisterhafte Führung" msgid "Expert Wisdom" msgstr "Meisterhafte Weisheit" msgid "Advanced Luck" msgstr "Verbessertes Glück" msgid "Advanced Mysticism" msgstr "Verbesserte Mystik" msgid "Basic Luck" msgstr "Einfaches Glück" msgid "Expert Luck" msgstr "Meisterhaftes Glück" msgid "Expert Mysticism" msgstr "Meisterhafte Mystik" msgid "Advanced Ballistics" msgstr "Verbesserte Ballistik" msgid "Advanced Eagle Eye" msgstr "Verbessertes Adlerauge" msgid "Basic Ballistics" msgstr "Einfache Ballistik" msgid "Basic Eagle Eye" msgstr "Einfaches Adlerauge" msgid "Expert Ballistics" msgstr "Meisterhafte Ballistik" msgid "Advanced Necromancy" msgstr "Verbesserte Nekromantie" msgid "Basic Estates" msgstr "Einfach Grundbesitz" msgid "Basic Necromancy" msgstr "Einfache Nekromantie" msgid "Expert Eagle Eye" msgstr "Meisterhaftes Adlerauge" msgid "Expert Necromancy" msgstr "Meisterhafte Nekromantie" msgid "Advanced Estates" msgstr "Verbessert Grundbesitz" msgid "Expert Estates" msgstr "Meisterhaft Grundbesitz" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} reduziert den Bewegungsabzug für unwegsames Gelände um %{count} " "Prozent." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} eliminiert den Bewegungsabzug für unwegsames Gelände." #, fuzzy msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "Der %{name} eliminiert den %{count} Prozentabzug für Eure Truppen, die an " "Hindernissen (z.B. Burgmauern) vorbeischießen." #, fuzzy msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} erhöht die Bewegungspunkte Eures Helden um %{count} Prozent." #, fuzzy msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} erweitert das Blickfeld Eures Helden um ein Feld." msgstr[1] "%{skill} erweitert das Blickfeld Eures Helden um %{count} Felder." #, fuzzy msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} erlaubt es Euch, mit Monstern zu verhandeln, die schwächer sind als " "Eure Truppe. " #, fuzzy msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Ungefähr %{count} Prozent der Kreaturen werden Euch anbieten, sich Euch " "anzuschließen." #, fuzzy msgid "All of the creatures may offer to join the hero." msgstr "Alle Kreaturen könnten anbieten, sich Euch anzuschließen." #, fuzzy msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "Der %{name} reduziert die Kosten der Kapitulation auf %{count} Prozent der " "Gesamtkosten der Truppen in Eurer Armee." #, fuzzy msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "%{skill} erhöht die Bewegungspunkte Eures Helden über Wasser um %{count} " "Prozent." #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} erhöht die Moral der Truppen Eures Helden um %{count}." #, fuzzy msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} erlaubt es Eurem Helden, Zauber der dritten Stufe zu lernen." #, fuzzy msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} erlaubt es Eurem Helden, Zauber der vierten Stufe zu lernen." #, fuzzy msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} erlaubt es Eurem Helden, Zauber der fünften Stufe zu lernen." #, fuzzy msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" "%{skill} regeneriert einen zusätzlichen Zauberpunkt Eures Helden pro Tag." msgstr[1] "" "%{skill} regeneriert %{count} zusätzliche Zauberpunkte Eures Helden pro Tag." #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} erhöht das Glück Eures Helden um %{count}." #, fuzzy msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} gibt den Katapultschüssen Eures Helden eine größere Chance, die " "Burgmauern zu treffen und Schaden zu verursachen." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} gibt dem Katapult Eures Helden einen zusätzlichen Schuss, und jeder " "Schuss hat eine größere Chance, die Burgmauern zu treffen und Schaden zu " "verursachen." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} gibt dem Katapult Eures Helden einen zusätzlichen Schuss, und jeder " "Schuss zerstört automatisch jede Mauer, außer einer befestigten Mauer in " "einer Ritterburg." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} gibt Eurem Helden eine %{count} Prozent Chance, jeden gegnerischen " "Zauber der Stufe 1 oder 2 zu erlernen, der in einem Kampf gegen ihn " "eingesetzt wird." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} gibt Eurem Helden eine %{count} Prozent Chance, jeden beliebigen " "Zauber der Stufe 3 (oder niedriger) zu lernen, der im Kampf gegen ihn " "eingesetzt wird." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} gibt Eurem Helden eine %{count} Prozent Chance, jeden beliebigen " "Zauber der Stufe 4 (oder niedriger) zu lernen, der im Kampf gegen ihn " "eingesetzt wird." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} ermögicht Euch %{count} Prozent der im Kampf getöteten Kreaturen " "als Skelette von den Toten wiederauferstehen zu lassen." #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Euer Held produziert %{count} Goldstücke pro Tag als Steuereinnahmen aus " "Ländereien." msgid "Blue" msgstr "Blau" msgid "Green" msgstr "Grün" msgid "Red" msgstr "Rot" msgid "Yellow" msgstr "Gelb" msgid "Orange" msgstr "Orange" msgid "Purple" msgstr "Lila" msgid "barrier|Aqua" msgstr "Aqua" msgid "barrier|Blue" msgstr "Blaue" msgid "barrier|Brown" msgstr "Braune" msgid "barrier|Gold" msgstr "Goldene" msgid "barrier|Green" msgstr "Grüne" msgid "barrier|Orange" msgstr "Orange" msgid "barrier|Purple" msgstr "Lila" msgid "barrier|Red" msgstr "Rote" msgid "tent|Aqua" msgstr "Aqua" msgid "tent|Blue" msgstr "Blaues" msgid "tent|Brown" msgstr "Braunes" msgid "tent|Gold" msgstr "Goldenes" msgid "tent|Green" msgstr "Grünes" msgid "tent|Orange" msgstr "Orange" msgid "tent|Purple" msgstr "Lila" msgid "tent|Red" msgstr "Rotes" msgid "Experience" msgstr "Erfahrung" #, fuzzy msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Mit der Erfahrung steigen die Helden im Level auf und verbessern ihre " "primären und sekundären Fähigkeiten." msgid "Hero/Stats" msgstr "Held/Stats" msgid "Skills" msgstr "Fähigkeiten" msgid "Town/Castle" msgstr "Stadt/Burg" msgid "Garrison" msgstr "Garnison" msgid "Gold Per Day:" msgstr "Gold pro Tag:" msgid "View Heroes." msgstr "Helden anzeigen." msgid "Towns/Castles" msgstr "Stadt/Burg" msgid "View Towns and Castles." msgstr "Städte anzeigen." msgid "luck|Cursed" msgstr "Verfluchtes" msgid "luck|Awful" msgstr "Furchtbares" msgid "luck|Bad" msgstr "Schlechtes" msgid "luck|Normal" msgstr "Normales" msgid "luck|Good" msgstr "Gutes" msgid "luck|Great" msgstr "Wunderbares" msgid "luck|Irish" msgstr "Irisches" #, fuzzy msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Eure Armeen werden im Kampf manchmal vom Pech verfolgt, so dass ihre " "Angriffe nur halben Schaden anrichten." #, fuzzy msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Neutrales Glück bedeutet, dass Eure Armeen weder Glück noch Unglück haben " "werden bei Angriffen auf den Feind." #, fuzzy msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "Glück lässt Eure Truppen manchmal mit doppelter Stärke angreifen." msgid "morale|Treason" msgstr "Verratende" msgid "morale|Awful" msgstr "Furchtbare" msgid "morale|Poor" msgstr "Schlechte" msgid "morale|Normal" msgstr "Normale" msgid "morale|Good" msgstr "Hohe" msgid "morale|Great" msgstr "Wunderbare" msgid "morale|Blood!" msgstr "Blut!" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "Eine niedrige Moral kann dazu führen, dass Eure Armeen im Kampf vor Angst " "erstarren." #, fuzzy msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Neutrale Moral bedeutet, dass Eure Armeen keine zusätzlichen Angriffen " "erhalten werden aber auch nicht im Kampf einfrieren." #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "Eine hohe Moral kann Eurer Armee zu zusätzlichen Angriffen im Kampf " "verhelfen." msgid "Knight" msgstr "Ritter" msgid "Barbarian" msgstr "Barbar" msgid "Sorceress" msgstr "Zauberin" msgid "Warlock" msgstr "Hexer" msgid "Wizard" msgstr "Zauberer" msgid "Necromancer" msgstr "Totenbeschwörer" msgid "Multi" msgstr "Verschied" msgid "doubleLined|Knight" msgstr "Ritter" msgid "doubleLined|Barbarian" msgstr "Barbar" msgid "doubleLined|Sorceress" msgstr "Zauberin" msgid "doubleLined|Warlock" msgstr "Hexer" msgid "doubleLined|Wizard" msgstr "Zauberer" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Totenbe-\n" "schwörer" msgid "doubleLinedRace|Multi" msgstr "Verschied" msgid "doubleLinedRace|Random" msgstr "Zufällig" msgid "speed|Standing" msgstr "Stehend" msgid "speed|Crawling" msgstr "Schleichend" msgid "speed|Very Slow" msgstr "Sehr langsam" msgid "speed|Slow" msgstr "Langsam" msgid "speed|Average" msgstr "Normal" msgid "speed|Fast" msgstr "Schnell" msgid "speed|Very Fast" msgstr "Sehr Schnell" msgid "speed|Ultra Fast" msgstr "Ultra schnell" msgid "speed|Blazing" msgstr "Blitzschnell" msgid "speed|Instant" msgstr "Sofort" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Eichhörnchen" msgid "week|Rabbit" msgstr "Kaninchen" msgid "week|Gopher" msgstr "Erdhörnchen" msgid "week|Badger" msgstr "Dachs" msgid "week|Rat" msgstr "Ratte" msgid "week|Eagle" msgstr "Adler" msgid "week|Weasel" msgstr "Wiesel" msgid "week|Raven" msgstr "Rabe" msgid "week|Mongoose" msgstr "Manguste" msgid "week|Dog" msgstr "Hund" msgid "week|Aardvark" msgstr "Erdferkel" msgid "week|Lizard" msgstr "Eidechse" msgid "week|Tortoise" msgstr "Schildkröte" msgid "week|Hedgehog" msgstr "Igel" msgid "week|Condor" msgstr "Condor" msgid "week|Ant" msgstr "Ameise" msgid "week|Grasshopper" msgstr "Grashüpfer" msgid "week|Dragonfly" msgstr "Libelle" msgid "week|Spider" msgstr "Spinne" msgid "week|Butterfly" msgstr "Schmetterling" msgid "week|Bumblebee" msgstr "Hummel" msgid "week|Locust" msgstr "Heuschrecke" msgid "week|Earthworm" msgstr "Regenwurm" msgid "week|Hornet" msgstr "Hornisse" msgid "week|Beetle" msgstr "Käfer" msgid "week|PLAGUE" msgstr "PEST" msgid "week|Unnamed" msgstr "Unbenannt" msgid "Desert" msgstr "Wüste" msgid "Snow" msgstr "Schnee" msgid "Wasteland" msgstr "Ödland" msgid "Beach" msgstr "Strand" msgid "Lava" msgstr "Lava" msgid "Dirt" msgstr "Erde" msgid "Grass" msgstr "Gras" msgid "Ocean" msgstr "Ozean" msgid "maps|Small" msgstr "Kleine" msgid "maps|Medium" msgstr "Mittlere" msgid "maps|Large" msgstr "Grosse" msgid "maps|Extra Large" msgstr "Extragrosse" msgid "maps|Custom Size" msgstr "Individuelle Größe" msgid "Ore Mine" msgstr "Erzmine" msgid "Sulfur Mine" msgstr "Schwefelmine" msgid "Crystal Mine" msgstr "Kristallmine" msgid "Gems Mine" msgstr "Edelsteinmine" msgid "Gold Mine" msgstr "Goldmine" msgid "Mine" msgstr "Mine" msgid "Burma shave." msgstr "Burma shave." msgid "Next sign 50 miles." msgstr "Nächstes Schild 50 Meilen." msgid "See Rock City." msgstr "Siehe Rock City." msgid "This space for rent." msgstr "Dieser Raum ist zu vermieten." msgid "No object" msgstr "Kein Objekt" msgid "Alchemist Lab" msgstr "Alchemistenlabor" msgid "Sign" msgstr "Zeichen" msgid "Buoy" msgstr "Boje" msgid "Skeleton" msgstr "Skelett" msgid "Daemon Cave" msgstr "Dämonenhöhle" msgid "Treasure Chest" msgstr "Schatzkiste" msgid "Faerie Ring" msgstr "Feenring" msgid "Campfire" msgstr "Lagerfeuer" msgid "Fountain" msgstr "Brunnen" msgid "Gazebo" msgstr "Pavillon" msgid "Genie Lamp" msgstr "Antike Lampe" msgid "Archer's House" msgstr "Haus des Bogenschützen" msgid "Goblin Hut" msgstr "Goblinhütte" msgid "Dwarf Cottage" msgstr "Zwergenhaus" msgid "Peasant Hut" msgstr "Bauernhaus" msgid "Stables" msgstr "Ställe" msgid "Alchemist's Tower" msgstr "Turm des Alchemisten" msgid "Event" msgstr "Ereignis" msgid "Dragon City" msgstr "Drachenstadt" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Leuchtturm" msgstr[1] "Leuchttürme" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Wasserrad" msgstr[1] "Wasserräder" msgid "Monster" msgstr "Monster" msgid "Obelisk" msgstr "Obelisk" msgid "Oasis" msgstr "Oase" msgid "Resource" msgstr "Ressource" msgid "Sawmill" msgstr "Sägemühle" msgid "Oracle" msgstr "Orakel" msgid "Shrine of the First Circle" msgstr "Schrein des ersten Kreises" msgid "Shipwreck" msgstr "Schiffswrack" msgid "Sea Chest" msgstr "Seekiste" msgid "Desert Tent" msgstr "Wüstenzelt" msgid "Stone Liths" msgstr "Steinsäulen" msgid "Wagon Camp" msgstr "Wagenlager" msgid "Hut of the Magi" msgstr "Hütte des Magiers" msgid "Whirlpool" msgstr "Whirlpool" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Windmühle" msgstr[1] "Windmühlen" msgid "Mermaid" msgstr "Meerjungfrau" msgid "Boat" msgstr "Boot" msgid "Random Ultimate Artifact" msgstr "Zufälliges ultimatives Artefakt" msgid "Random Artifact" msgstr "Zufälliges Artefakt" msgid "Random Resource" msgstr "Zufällige Ressource" msgid "Random Monster" msgstr "Zufälliges Monster" msgid "Random Town" msgstr "Zufällige Stadt" msgid "Random Castle" msgstr "Zufälliges Burg" msgid "Eye of the Magi" msgstr "Auge des Magiers" msgid "Random Monster - weak" msgstr "Zufälliges Monster - schwach" msgid "Random Monster - medium" msgstr "Zufälliges Monster - mittel" msgid "Random Monster - strong" msgstr "Zufälliges Monster - stark" msgid "Random Monster - very strong" msgstr "Zufälliges Monster - sehr stark" #, fuzzy msgid "Hero" msgstr "Helden" msgid "Nothing Special" msgstr "Nichts besonderes" msgid "Mossy Rock" msgstr "Moosiger Felsen" msgid "Watch Tower" msgstr "Wachturm" msgid "Tree House" msgstr "Baumhaus" msgid "Tree City" msgstr "Baumhausstadt" msgid "Ruins" msgstr "Ruinen" msgid "Fort" msgstr "Fort" msgid "Abandoned Mine" msgstr "Verlassene Mine" msgid "Sirens" msgstr "Sirenen" msgid "Standing Stones" msgstr "Stehende Steine" msgid "Idol" msgstr "Götzenbild" msgid "Tree of Knowledge" msgstr "Baum des Wissens" msgid "Witch Doctor's Hut" msgstr "Hütte des Hexendoktors" msgid "Temple" msgstr "Tempel" msgid "Hill Fort" msgstr "Hügelfort" msgid "Halfling Hole" msgstr "Loch des Halblings" msgid "Mercenary Camp" msgstr "Söldnerlager" msgid "Shrine of the Second Circle" msgstr "Schrein des zweiten Kreises" msgid "Shrine of the Third Circle" msgstr "Schrein des dritten Kreises" msgid "City of the Dead" msgstr "Stadt der Toten" msgid "Sphinx" msgstr "Sphinx" msgid "Wagon" msgstr "Waggon" msgid "Tar Pit" msgstr "Teergrube" msgid "Artesian Spring" msgstr "Artesische Quelle" msgid "Troll Bridge" msgstr "Trollbrücke" msgid "Watering Hole" msgstr "Wasserloch" msgid "Witch's Hut" msgstr "Hexenhütte" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Anbau" msgid "Magellan's Maps" msgstr "Magellans Karten" msgid "Flotsam" msgstr "Treibgut" msgid "Derelict Ship" msgstr "Heruntergekommenes Schiff" msgid "Shipwreck Survivor" msgstr "Schiffbrüchiger" msgid "Bottle" msgstr "Flasche" msgid "Magic Well" msgstr "Magischer Brunnen" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Zaubergarten" msgstr[1] "Zaubergärten" msgid "Observation Tower" msgstr "Beobachtungsturm" msgid "Freeman's Foundry" msgstr "Freemans Giesserei" msgid "Reefs" msgstr "Riffe" msgid "Volcano" msgstr "Vulkan" msgid "Flowers" msgstr "Blumen" msgid "Rock" msgstr "Fels" msgid "Water Lake" msgstr "See" msgid "Mandrake" msgstr "Mandragola" msgid "Dead Tree" msgstr "Toter Baum" msgid "Stump" msgstr "Stumpf" msgid "Crater" msgstr "Krater" msgid "Cactus" msgstr "Kaktus" msgid "Mound" msgstr "Erdhügel" msgid "Dune" msgstr "Düne" msgid "Lava Pool" msgstr "Lavabecken" msgid "Shrub" msgstr "Strauch" msgid "Barrow Mounds" msgstr "Vergrabener Karren" msgid "Random Artifact - Treasure" msgstr "Zufälliges Artefakt - Schatz" msgid "Random Artifact - Minor" msgstr "Zufälliges Artefakt - Klein" msgid "Random Artifact - Major" msgstr "Zufälliges Artefakt - Groß" msgid "Barrier" msgstr "Barriere" msgid "Traveller's Tent" msgstr "Zelt des Reisenden" msgid "Jail" msgstr "Gefängnis" msgid "Fire Summoning Altar" msgstr "Feuerwesen-Altar" msgid "Air Summoning Altar" msgstr "Luftwesen-Altar" msgid "Earth Summoning Altar" msgstr "Erdwesen-Altar" msgid "Water Summoning Altar" msgstr "Wasserwesen-Altar" #, fuzzy msgid "Swampy Lake" msgstr "Sumpf" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "Unbekannte Monster" msgid "Unknown Monster" msgstr "Unbekanntes Monster" msgid "Peasant" msgstr "Bauer" msgid "Peasants" msgstr "Bauern" msgid "Archer" msgstr "Bogenschütze" msgid "Archers" msgstr "Bogenschützen" msgid "Ranger" msgstr "Ranger" msgid "Rangers" msgstr "Rangers" msgid "Pikeman" msgstr "Pikenier" msgid "Pikemen" msgstr "Pikeniere" msgid "Veteran Pikeman" msgstr "Meister-Pikenier" msgid "Veteran Pikemen" msgstr "Meister-Pikeniere" msgid "Swordsman" msgstr "Schwertkämpfer" msgid "Swordsmen" msgstr "Schwertkämpfer" msgid "Master Swordsman" msgstr "Schwertmeister" msgid "Master Swordsmen" msgstr "Schwertmeistern" msgid "Cavalries" msgstr "Kavallerien" msgid "Cavalry" msgstr "Kavallerie" msgid "Champion" msgstr "Champion" msgid "Champions" msgstr "Champions" msgid "Paladin" msgstr "Paladin" msgid "Paladins" msgstr "Paladine" msgid "Crusader" msgstr "Kreuzritter" msgid "Crusaders" msgstr "Kreuzritter" msgid "Goblin" msgstr "Goblin" msgid "Goblins" msgstr "Goblins" msgid "Orc" msgstr "Ork" msgid "Orcs" msgstr "Orks" msgid "Orc Chief" msgstr "Orkführer" msgid "Orc Chiefs" msgstr "Orkführer" msgid "Wolf" msgstr "Wolf" msgid "Wolves" msgstr "Wölfe" msgid "Ogre" msgstr "Oger" msgid "Ogres" msgstr "Oger" msgid "Ogre Lord" msgstr "Ogerlord" msgid "Ogre Lords" msgstr "Ogerlords" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Trolle" msgid "War Troll" msgstr "Kriegstroll" msgid "War Trolls" msgstr "Kriegstrolle" msgid "Cyclopes" msgstr "Zyklopen" msgid "Cyclops" msgstr "Zyklop" msgid "Sprite" msgstr "Fee" msgid "Sprites" msgstr "Feen" msgid "Dwarf" msgstr "Zwerg" msgid "Dwarves" msgstr "Zwerge" msgid "Battle Dwarf" msgstr "Kampfzwerg" msgid "Battle Dwarves" msgstr "Kampfzwerge" msgid "Elf" msgstr "Elf" msgid "Elves" msgstr "Elfen" msgid "Grand Elf" msgstr "Grosself" msgid "Grand Elves" msgstr "Grosselfen" msgid "Druid" msgstr "Druide" msgid "Druids" msgstr "Druiden" msgid "Greater Druid" msgstr "Grossdruide" msgid "Greater Druids" msgstr "Grossdruiden" msgid "Unicorn" msgstr "Einhorn" msgid "Unicorns" msgstr "Einhörner" msgid "Phoenix" msgstr "Phönix" msgid "Phoenixes" msgstr "Phönixe" msgid "Centaur" msgstr "Zentaur" msgid "Centaurs" msgstr "Zentauren" msgid "Gargoyle" msgstr "Wasserspeier" msgid "Gargoyles" msgstr "Wasserspeier" msgid "Griffin" msgstr "Greifvogel" msgid "Griffins" msgstr "Greifvögel" msgid "Minotaur" msgstr "Minotaur" msgid "Minotaurs" msgstr "Minotauren" msgid "Minotaur King" msgstr "Minotaurenkönig" msgid "Minotaur Kings" msgstr "Minotaurenkönige" msgid "Hydra" msgstr "Hydra" msgid "Hydras" msgstr "Hydras" msgid "Green Dragon" msgstr "Grüner Drache" msgid "Green Dragons" msgstr "Grüne Drachen" msgid "Red Dragon" msgstr "Roter Drache" msgid "Red Dragons" msgstr "Rote Drachen" msgid "Black Dragon" msgstr "Schwarzer Drache" msgid "Black Dragons" msgstr "Schwarze Drachen" msgid "Halfling" msgstr "Halbling" msgid "Halflings" msgstr "Halblinge" msgid "Boar" msgstr "Eber" msgid "Boars" msgstr "Eber" msgid "Iron Golem" msgstr "Eisengolem" msgid "Iron Golems" msgstr "Eisengoleme" msgid "Steel Golem" msgstr "Stahlgolem" msgid "Steel Golems" msgstr "Stahlgoleme" msgid "Roc" msgstr "Roc" msgid "Rocs" msgstr "Rocs" msgid "Mage" msgstr "Magier" msgid "Magi" msgstr "Magier" msgid "Archmage" msgstr "Meistermagier" msgid "Archmagi" msgstr "Meistermagier" msgid "Giant" msgstr "Riese" msgid "Giants" msgstr "Riesen" msgid "Titan" msgstr "Titan" msgid "Titans" msgstr "Titane" msgid "Skeletons" msgstr "Skelette" msgid "Zombie" msgstr "Zombie" msgid "Zombies" msgstr "Zombies" msgid "Mutant Zombie" msgstr "Mutierter Zombie" msgid "Mutant Zombies" msgstr "Mutierte Zombies" msgid "Mummies" msgstr "Mumien" msgid "Mummy" msgstr "Mumie" msgid "Royal Mummies" msgstr "Königsmumien" msgid "Royal Mummy" msgstr "Königsmumie" msgid "Vampire" msgstr "Vampir" msgid "Vampires" msgstr "Vampire" msgid "Vampire Lord" msgstr "Vampirlord" msgid "Vampire Lords" msgstr "Vampirlorde" msgid "Lich" msgstr "Lich" msgid "Liches" msgstr "Liches" msgid "Power Lich" msgstr "Meister-Lich" msgid "Power Liches" msgstr "Meister-Liches" msgid "Bone Dragon" msgstr "Knochendrache" msgid "Bone Dragons" msgstr "Knochendrachen" msgid "Rogue" msgstr "Schurke" msgid "Rogues" msgstr "Schurken" msgid "Nomad" msgstr "Nomade" msgid "Nomads" msgstr "Nomaden" msgid "Ghost" msgstr "Geist" msgid "Ghosts" msgstr "Geister" msgid "Genie" msgstr "Dschinn" msgid "Genies" msgstr "Dschinne" msgid "Medusa" msgstr "Meduse" msgid "Medusas" msgstr "Medusen" msgid "Earth Elemental" msgstr "Erdwesen" msgid "Earth Elementals" msgstr "Erdwesen" msgid "Air Elemental" msgstr "Luftwesen" msgid "Air Elementals" msgstr "Luftwesen" msgid "Fire Elemental" msgstr "Feuerwesen" msgid "Fire Elementals" msgstr "Feuerwesen" msgid "Water Elemental" msgstr "Wasserwesen" msgid "Water Elementals" msgstr "Wasserwesen" msgid "Random Monsters" msgstr "Zufällige Monster" msgid "Random Monster 1" msgstr "Zufälliges Monster 1" msgid "Random Monsters 1" msgstr "Zufällige Monster 1" msgid "Random Monster 2" msgstr "Zufälliges Monster 2" msgid "Random Monsters 2" msgstr "Zufällige Monster 2" msgid "Random Monster 3" msgstr "Zufälliges Monster 3" msgid "Random Monsters 3" msgstr "Zufällige Monster 3" msgid "Random Monster 4" msgstr "Zufälliges Monster 4" msgid "Random Monsters 4" msgstr "Zufällige Monster 4" msgid "Double shot" msgstr "Doppelter Schuss" msgid "2-hex monster" msgstr "2-Felder Monster" msgid "Double strike" msgstr "Doppelschlag" msgid "Double damage to Undead" msgstr "Doppelter Schaden an Untoten" msgid "% magic resistance" msgstr "% Magieresistenz" msgid "Immune to Mind spells" msgstr "Immun gegen Geisteszauber" msgid "Immune to Elemental spells" msgstr "Immun gegen Elementarzauber" msgid "Immune to Fire spells" msgstr "Immun gegen Feuerzauber" msgid "Immune to Cold spells" msgstr "Immun gegen Kältezauber" msgid "Immune to " msgstr "Immun gegen " msgid "% immunity to %{spell} spell" msgstr "% immunität gegen %{spell}" msgid "% damage from Elemental spells" msgstr "% Schaden von Elementarzaubern" msgid "% damage from %{spell} spell" msgstr "% Schaden durch %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% Chance, nützliche Zauber zu bannen" msgid "% chance to Paralyze" msgstr "% Chance auf Lähmen" msgid "% chance to Petrify" msgstr "% Chance auf Versteinern" msgid "% chance to Blind" msgstr "% Chance auf Blendung" msgid "% chance to Curse" msgstr "% Chance auf Fluch" msgid "% chance to cast %{spell} spell" msgstr "% Chance um %{spell} zu wirken" msgid "HP regeneration" msgstr "TP-Regeneration" msgid "Two hexes attack" msgstr "Angriff an zwei Felder" msgid "Flyer" msgstr "Fliegend" msgid "Always retaliates" msgstr "Vergeltet immer" msgid "Attacks all adjacent enemies" msgstr "Greift alle benachbarten Feinde an" msgid "No melee penalty" msgstr "Keine Strafe im Nahkampf" msgid "Dragon" msgstr "Drache" msgid "Undead" msgstr "Untot" msgid "No enemy retaliation" msgstr "Keine feindliche Vergeltung" msgid "HP drain" msgstr "TP-Abfluss" msgid "Cloud attack" msgstr "Wolke-Angriff" msgid "Decreases enemy's morale by " msgstr "Senkt die Moral des Gegners um " msgid "% chance to halve enemy" msgstr "% Chance, den Gegner zu halbieren" msgid "Soul Eater" msgstr "Seelenfresser" msgid "Elemental" msgstr "Element" msgid "No Morale" msgstr "Keine Moral" #, fuzzy msgid "Earth creature" msgstr "Kreaturen rekrutieren" #, fuzzy msgid "Air creature" msgstr "Kreaturen rekrutieren" #, fuzzy msgid "Fire creature" msgstr "Kreaturen rekrutieren" #, fuzzy msgid "Water creature" msgstr "See" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% Schaden von Feuerzaubern" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% Schaden von Kälterzaubern" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Entfernt alle Zaubersprüche von allen Kreaturen." #, fuzzy msgid "Double damage from Air creatures" msgstr "Doppelter Schaden an Untoten" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% Schaden von Feuerzaubern" #, fuzzy msgid "Double damage from Water creatures" msgstr "Entfernt alle Zaubersprüche von allen Kreaturen." msgid "Lightning" msgstr "Blitz" msgid "% immunity to " msgstr "% immunität gegen " msgid "% damage from " msgstr "% Schaden von " msgid "The three Anduran artifacts magically combine into one." msgstr "" "Die drei Anduranischen Artefakte setzen sich magisch zu einem zusammen." msgid "View Spells" msgstr "Zaubersprüche anzeigen" msgid "View %{name} Info" msgstr "Info von %{name} anzeigen" msgid "Move %{name}" msgstr "%{name} umstellen" msgid "Cannot move the Spellbook" msgstr "Das Zauberbuch kann nicht umgestellt werden" msgid "This item can't be traded." msgstr "Dieser Gegenstand kann nicht gehandelt werden." msgid "Invalid Artifact" msgstr "Ungültiges Artefakt" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "Der %{name} steigert Euer Wissen um %{count}." msgid "Ultimate Book of Knowledge" msgstr "Ultimatives Buch des Wissens" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "Der %{name} steigert Eure Angriffsfähigkeit um %{count}." msgid "Ultimate Sword of Dominion" msgstr "Ultimatives Schwert der Herrschaft" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "Der %{name} steigert Eure Verteidigungsfähigkeit um %{count}." msgid "Ultimate Cloak of Protection" msgstr "Ultimativer Mantel des Schutzes" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "Der %{name} steigert Eure Zauberkraft um %{count}." msgid "Ultimate Wand of Magic" msgstr "Ultimativer Zauberstab" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" "Der %{name} erhöht Euren Angriff und Eure Verteidigung um jeweils %{count}." msgid "Ultimate Shield" msgstr "Ultimatives Schild" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "" "Die %{name} erhöht Eure Zauberkraft und Euer Wissen um jeweils %{count}." msgid "Ultimate Staff" msgstr "Ultimativer Stab" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "Der %{name} erhöht jede Eurer Grundfertigkeiten um %{count} Punkte." msgid "Ultimate Crown" msgstr "Ultimative Krone" msgid "Golden Goose" msgstr "Goldene Gans" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "Der %{name} bringt ein Einkommen von %{count} Gold pro Tag." msgid "Arcane Necklace of Magic" msgstr "Geheime Zauberhalskette" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Nachdem Ihr eine Zauberin aus einer verfluchten Gruft gerettet habt, belohnt " "sie Euren Heldenmut mit einer exquisiten Juwelenhalskette." msgid "Caster's Bracelet of Magic" msgstr "Zauberarmband der Magie" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Während Ihr den Schutt einer eingestürzten Mine durchsucht, befreit Ihr eine " "Gruppe gefangener Zwerge. Aus Dankbarkeit schenkt Euch der Anführer einen " "goldenen Armreif." msgid "Mage's Ring of Power" msgstr "Magierring der Macht" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Ein Schmerzensschrei führt Euch zu einem Zentauren, der in einer Falle " "gefangen ist. Nachdem Ihr die Kreatur befreit habt, überreicht er Euch einen " "kleinen Beutel. Als Ihr den Inhalt ausleert, findet Ihr einen schillernden " "Ring mit Juwelen." msgid "Witch's Broach of Magic" msgstr "Hexenbrosche der Magie" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Neben den Überresten einer verbrannten Hexe liegt eine wunderschöne, " "kunstvoll gestaltete Brosche. Ihr nähert euch dem Leichnam vorsichtig und " "nehmt die Brosche mit." msgid "Medal of Valor" msgstr "Medaille der Tapferkeit" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "Der %{name} erhöht Eure Moral um %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Ihr befreit ein tugendhaftes Mädchen aus den Fängen eines bösen Herrschers " "und erhaltet dafür vom Herold des Königs eine Tapferkeitsmedaille." msgid "Medal of Courage" msgstr "Medaille des Mutes" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Nachdem Ihr einen kleinen Jungen vor einem bösartigen Wolfsrudel gerettet " "habt, bringt Ihr ihn auf das Landgut seines Vaters zurück. Der dankbare " "Adlige verleiht Euch eine Tapferkeitsmedaille." msgid "Medal of Honor" msgstr "Medaille der Ehre" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Nachdem Ihr die Prinzessin eines Nachbarkönigreichs aus den Fängen " "abscheulicher Sklavenhändler befreit haben, zeichnet sie Euch mit einer " "Ehrenmedaille aus." msgid "Medal of Distinction" msgstr "Medaille der Auszeichnung" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Ihr habt das Land von dem abscheulichen Minotaurus befreit, der sich einen " "Spaß daraus machte, die Ritter der Adligen zu verspeisen, und werdet dafür " "mit der Medaille für besondere Verdienste geehrt." msgid "Fizbin of Misfortune" msgstr "Fizbin des Pechs" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "Der %{name} senkt Eure Moral stark um %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Ihr stoßt auf eine Medaille, die am Rande der leeren Straße liegt. Als Ihr " "die Medaille an Euch nehmt, stellt Ihr fest, dass Ihr den unerwünschten " "Fizbin des Unglücks erhalten habt, der die Moral Eurer Armee stark senkt." msgid "Thunder Mace of Dominion" msgstr "Donnerstab der Herrschaft" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Während eines plötzlichen Gewitters schlägt ein Blitz in einen Baum ein und " "spaltet ihn. Im Inneren des Baumes findet Ihr einen geheimnisvollen " "Streitkolben." msgid "Armored Gauntlets of Protection" msgstr "Panzerhandschuhe des Schutzes" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "Die %{name} erhöhen Eure Verteidigung um %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Ihr begegnet dem berüchtigten Schwarzen Ritter! Nach einem aufreibenden " "Duell, das in einem Unentschieden endet, bietet der Ritter Euch aus Respekt " "ein Paar gepanzerte Stulpen an." msgid "Defender Helm of Protection" msgstr "Verteidigungshelm des Schutzes" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Ein glitzernder goldener Lichtschimmer fällt Euch ins Auge. Bei näherer " "Untersuchung entdeckt Ihr einen, unter einem Busch versteckten, goldenen " "Helm." msgid "Giant Flail of Dominion" msgstr "Riesige Peitsche der Herrschaft" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Ein unbeholfener Riese hat sich mit seinem eigenen Peitsche umgebracht. Im " "Wissen um Eure überragenden Fähigkeiten mit dieser Waffe nehmt Ihr dem " "gefallenen Riesen selbstbewusst die spektakuläre Peitsche ab." msgid "Ballista of Quickness" msgstr "Balliste der Schnelligkeit" #, fuzzy msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "Der %{name} gibt Eurem Katapult einen zusätzlichen Schuss pro Kampfrunde." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Bei einem Spaziergang durch die Ruinen einer alten, befestigten Stadt findet " "Ihr das Instrument ihrer Zerstörung der Stadt, eine ausgeklügelt " "konstruierte Balliste." msgid "Stealth Shield of Protection" msgstr "Tarnschild des Schutzes" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Eine steinerne Statue eines Kriegers hält einen silbernen Schild. Als Ihr " "das Schild entfernt, zerfällt die Statue zu Staub." msgid "Dragon Sword of Dominion" msgstr "Drachenschwert der Herrschaft" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Ihr geht einen schmalen Pfad entlang, als plötzlich ein naher Busch in " "Flammen aufgeht. Vor Euren Augen formt sich aus den Flammen das Bild einer " "schönen Frau. Sie hält Euch ein prächtiges Schwert hin." msgid "Power Axe of Dominion" msgstr "Poweraxt der Herrschaft" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Ihr seht eine silberne Axt, die tief im Boden steckt. Nach mehreren " "erfolglosen Versuchen Eurer Armee, die Axt zu heben, packt Ihr fest den " "Griff der Axt und zieht sie mühelos aus dem Boden." msgid "Divine Breastplate of Protection" msgstr "Göttlicher Brustpanzer des Schutzes" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Eine Schurkenbande durchwühlt die Besitztümer eines toter Krieger. Ihr " "verscheucht die Aasfresser und bemerkt, dass die Schurken einen schönen " "Brustpanzer übersehen haben." msgid "Minor Scroll of Knowledge" msgstr "Kleine Schriftrolle des Wissens" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Vor euch erscheint ein schwebender Glaskasten mit einer Schriftrolle, die " "auf purpurnem Samt gebettet liegt. Als Ihr es berührt, öffnet sich der " "Deckel und die Schriftrolle schwebt in Eure erwartungsvollen Hände." msgid "Major Scroll of Knowledge" msgstr "Grosse Schriftrolle des Wissens" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Ihr besucht einen örtlichen Weisen und erklärt ihm das Ziel eurer Reise. Er " "greift in einen Sack, zieht eine vergilbte Schriftrolle heraus und " "überreicht sie Euch." msgid "Superior Scroll of Knowledge" msgstr "Überlegene Schriftrolle des Wissens" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Ihr stoßt auf die Überreste einer alten Druidin. Vom Alter vergilbte Knochen " "lugen aus den Falten ihres Gewandes hervor. Beim Durchsuchen des Gewandes " "entdeckt Ihr eine Schriftrolle, die in den Falten versteckt ist." msgid "Foremost Scroll of Knowledge" msgstr "Herausragendste Schriftrolle des Wissens" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Zerfetzte, vom Alter vergilbte Knochen lugen aus den zerrissenen Falten des " "Gewandes eines toten Druiden hervor. Beim Durchsuchen des Gewandes entdeckt " "Ihr eine Schriftrolle, die darin versteckt ist." msgid "Endless Sack of Gold" msgstr "Endloser Goldsack" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "Der %{name} bringt ein Einkommen von %{count} Gold pro Runde." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Ein kleiner Kobold tanzt vergnügt um einen Zaubersack herum. Als er Euch " "kommen sieht, bleibt er unvermittelt stehen. Der kleine Mann schreit auf, " "stampft wild mit den Füßen und löst sich in Luft auf. Ihr erinnert euch an " "das alte Kobold-Sprichwort \"Wers findet, dem gehörts\", schnappt euch den " "Sack und geht." msgid "Endless Bag of Gold" msgstr "Endlose Goldtasche" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Eine Adlige, die von ihren Reisebegleitern getrennt wurde, bittet Euch um " "Hilfe. Nachdem Ihr sie nach Hause begleitet habt, belohnt sie Euch mit einem " "mit Gold gefüllten Beutel." msgid "Endless Purse of Gold" msgstr "Endlose Goldbörse" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Auf Eurer Reise findet Ihr einen mit Gold gefüllten Lederbeutel, der einst " "einem großen Kriegerkönig gehörte, der die Fähigkeit besaß, jeden leblosen " "Gegenstand in Gold zu verwandeln." msgid "Nomad Boots of Mobility" msgstr "Nomadenstiefel der Mobilität" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "Die %{name} erhöhen Eure Bewegung auf dem Land." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Ein Nomadenhändler sucht Schutz vor einem Goblin-Stamm. Für Eure " "Unterstützung schenkt er euch ein fein gearbeitetes Paar Stiefel aus " "weichstem Leder. Ihr seht genauer hin und entdeckt faszinierende Gravuren " "auf dem Leder." msgid "Traveler's Boots of Mobility" msgstr "Reisestiefel der Mobilität" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Ihr entdeckt ein Paar wunderschöner, mit Perlen besetzter Stiefel aus " "feinstem und weichem Leder, dankt dem anonymen Spender und nehmt die Stiefel " "an Euch." msgid "Lucky Rabbit's Foot" msgstr "Glückbringende Hasenpfote" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "Der %{name} erhöht Euer Glück im Kampf um %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Ein reisender Händler bietet Euch eine Hasenpfote aus schimmerndem " "Silberfell für eine sichere Weiterreise an. Der Händler erklärt, dass der " "Talisman euer Glück im Kampf erhöhen wird." msgid "Golden Horseshoe" msgstr "Goldenes Hufeisen" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Ein in einer Schlinge gefangenes Einhorn wiehert verängstigt. Ihr murmelt " "beruhigende Worte und befreit es. Es schnaubt und stampft einmal mit dem " "Vorderhuf, dann galoppiert es davon. Ihr seht auf dem Boden und findet ein " "goldenes Hufeisen." msgid "Gambler's Lucky Coin" msgstr "Glücksmünze des Spielers" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Ihr habt einen schelmischen Kobold gefangen genommen, der die Region " "terrorisiert hat. Im Austausche für seine Freilassung belohnt er euch mit " "einer magischen Münze." msgid "Four-Leaf Clover" msgstr "Vierblättriges Kleeblatt" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Inmitten einer Gegend toter und trockener Vegetation findet Ihr, zu Eurer " "Überraschung, einen gesunden, grünen, vierblättrigen Klee." msgid "True Compass of Mobility" msgstr "Wahrer Kompass der Mobilität" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "Der %{name} erhöht Eure Bewegung auf dem Land und Meer." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Ein alter Mann, der behauptet, ein Erfinder zu sein, bittet Euch, seine " "neueste Erfindung auszuprobieren. Dann überreicht er Euch einen Kompass." msgid "Sailor's Astrolabe of Mobility" msgstr "Seemannsastrolabium der Mobilität" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "Der %{name} erhöht Eure Bewegung auf dem Meer." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Ein alter Seekapitän wird von Ogern gefoltert. Ihr rettet ihn und er belohnt " "Euch im Gegenzug mit einem wundersamen Instrument zur Messung der Entfernung " "eines Sterns." msgid "Evil Eye" msgstr "Auge des Bösen" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "Der %{name} reduziert die Zauberkosten von Fluchzaubern um die Hälfte." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Beim Betreten einer verfallenen Hütte findet Ihr das Skelett einer längst " "verstorbenen Hexe. Bei der Untersuchung der Überreste findet sich ein " "Glasauge, das in ihrem leeren Schädel herumrollt." msgid "Enchanted Hourglass" msgstr "Verzauberte Sanduhr" #, fuzzy msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "Der %{name} verlängert die Dauer aller Eurer Zauber um %{count} Runden." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Plötzlich wandelt sich die Landschaft und Ihr befindet Euch inmitten einer " "grässlichen Szenerie: Geier rupfen an den Überresten einer schrecklichen " "Schlacht. Bei der flüchtigen Durchsuchung der Überreste stoßt Ihr auf eine " "verzauberte Sanduhr." msgid "Gold Watch" msgstr "Goldene Uhr" #, fuzzy msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "Die %{name} verdoppelt die Wirksamkeit Eurer Hypnosezauber." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Als Belohnung dafür, dass Ihr seinem Karren aus dem Graben helft, schenkt " "euch ein fahrender Apotheker eine \"magische\" Golduhr. Was er nicht weiß, " "ist, dass die Uhr wirklich magisch ist." msgid "Skullcap" msgstr "Totenkopfkappe" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "Der %{name} halbiert die Zauberkosten aller bewusstseinsverändernden Zauber." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Bei einem kurzen Halt in einem unwahrscheinlichen ländlichen Gasthaus werden " "Geld, Geschichten und zufällig auch Gepäck ausgetauscht. Ihr findet eine " "magische Schädeldecke in Eurem neuen Rucksack." msgid "Ice Cloak" msgstr "Eismantel" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "Der %{name} halbiert den Schaden, den Eure Truppen durch Kältezauber " "erleiden." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Als Ihr auf die panikerfüllten Schreie eines Mädchens reagiert, entdeckt Ihr " "eine junge Frau auf der Flucht vor einem hungrigen Bären. Ihr erschlagt das " "Ungeheuer in letzter Sekunde. Die dankbare Zauberin Euch webt aus dem Fell " "des Bären einen magischen Umhang." msgid "Fire Cloak" msgstr "Feuermantel" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "Der %{name} halbiert den Schaden, den Eure Truppen durch Feuerzauber " "erleiden." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Ihr seid in einen Kampf zwischen einem Nekromanten und einem Paladin " "geraten. Der Nekromant beschießt den Paladin mit einem Feuerball, der ihn in " "die Knie zwingt. Ihr handelt schnell und tötet den Bösewicht vor dem letzten " "Schlag. Der dankbare Paladin schenkt Euch den Feuerumhang, der ihn gerettet " "hat." msgid "Lightning Helm" msgstr "Blitzstrahlhelm" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "Der %{name} halbiert den Schaden, den Eure Truppen durch Blitzzauber " "erleiden." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Ein umherziehender Kesselflicker, der Vorräte benötigt, bietet Euch im " "Tausch gegen Essen und Wasser einen Helm an, auf dessen Oberseite ein Blitz " "abgebildet ist. Aus Neugier nehmt Ihr an und findet später heraus, dass der " "Helm magisch ist." msgid "Evercold Icicle" msgstr "Immerkalter Eiszapfen" #, fuzzy msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "Der %{name} bewirkt, dass Eure Kältezauber %{count} Prozent mehr Schaden an " "gegnerischen Truppen verursachen." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Ein Eiszapfen, der der vollen Mittagshitze widersteht, erregt Eure " "Aufmerksamkeit. Fasziniert brecht Ihr ihn ab und stellt fest, dass er in " "Eurer Hand nicht schmilzt." msgid "Everhot Lava Rock" msgstr "Immerheisser Lavafelsen" #, fuzzy msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "Der %{name} bewirkt, dass Eure Feuerzauber %{count} Prozent mehr Schaden an " "gegnerischen Truppen verursachen." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Auf Euren Wanderungen stoßt Ihr auf einen Stamm von affenähnlichen Wesen, " "die zum Anzünden ihrer Feuer einen magisches Lavastein benutzen, das nie " "abkühlt. Ihr habt Mitleid mit ihnen und lehrt sie, mit Stöcken Feuer zu " "machen. Die Affen halten Euch für einen Gott, und schenken Euch ihren Stein." msgid "Lightning Rod" msgstr "Blitzableiter" #, fuzzy msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "Der %{name} bewirkt, dass Eure Blitzzauber %{count} Prozent mehr Schaden an " "gegnerischen Truppen verursachen." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Während Ihr ein Gewitter abwartet, schlägt ein Blitz in den Blitzableiter " "eines nahe gelegenen Landhauses ein. Dieser schmilzt und fällt zu Boden. Die " "Spitze des Blitzableiters ist jedoch unversehrt geblieben und lässt einem " "die Haare zu Berge stehen, wenn man ihn berührt. Hmm..." msgid "Snake-Ring" msgstr "Schlangenring" #, fuzzy msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "Der %{name} halbiert die Zauberkosten aller Eurer Segenszauber." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Ihr habt einen seltsam geformten Ring am Finger eines längst verstorbenen " "Reisenden gefunden. Der Ring sieht aus wie eine Schlange, die sich selbst in " "den Schwanz beißt." msgid "Ankh" msgstr "Ankh" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "Das %{name} verdoppelt die Wirksamkeit aller Eurer Wiederbelebungs- und " "Belebungszauber." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Ein heftiger Windsturm enthüllt den Eingang zu einem vergrabenen Grab. Eure " "Untersuchung ergibt, dass das Grab bereits geplündert wurde, aber die Diebe " "haben in der Dunkelheit ein Ankh an einer Silberkette übersehen." msgid "Book of Elements" msgstr "Buch der Elemente" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "Das %{name} verdoppelt die Wirksamkeit all Eurer Beschwörungszauber." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Ihr trefft auf einen Zauberkünstler, der Euch und Eure Armee anbettelt, ihn " "eine Zeit lang zu beschützen. Ihr stimmt zu und er bietet als Gegenleistung " "ein Exemplar des Buchs der Elemente an." msgid "Elemental Ring" msgstr "Elementring" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "Der %{name} halbiert die Zauberkosten aller Beschwörungszauber." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Bei einer Rast bemerkt Ihr einen Rotluchs, der auf einen kurzen Baum " "klettert, um an ein Krähennest zu gelangen. Spontan besteigt Ihr selbst den " "Baum und verscheucht die Katze. Als Ihr das Nest untersucht, findet Ihr eine " "Sammlung glänzender Steine und einen Ring." msgid "Holy Pendant" msgstr "Heiliger Anhänger" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen Fluchzauber." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Auf eurer Wanderschaft trefft Ihr auf einen Einsiedler, der in einer " "kleinen, aufgeräumten Hütte lebt. Beeindruckt von Eurer Mission, nimmt er " "sich die Zeit, Euch zu segnen und ein Zaubermittel gegen Flüche zu geben." msgid "Pendant of Free Will" msgstr "Anhänger des Freien Willens" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen Hypnosezauber." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Ihr hört Hilferufe. Danach schauend findet Ihr Fluss-Kobolde, die sich einen " "Spaß daraus machen, einen alten Mann zu ertränken. Ihr fühlt Euch " "rachsüchtig, rettet den Mann und zieht einen der Kobolde für eine Weile an " "Land. Der Kobold, der es hasst an der Luft zu sein, gibt euch einen " "magischen Anhänger, damit Ihr ihn gehen lasst." msgid "Pendant of Life" msgstr "Anhänger des Lebens" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen Todeszauber." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Bei einer kurzen Begegnung mit einer kleinen Karawane gewinnt Ihr beim " "Glücksspiel einen magischer Anhänger. Sein früherer Besitzer sagt, er " "schütze vor den Todeszaubern der Totenbeschwörer." msgid "Serenity Pendant" msgstr "Anhänger der Heiterkeit" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen Berserker-Zauber." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Laute Kampfgeräusche locken Euch an den Schauplatz eines Kampfes zwischen " "einem alten Barbaren und einer achtköpfigen Hydra. Durch Euer rechtzeitiges " "Eingreifen wird der Kampf zu Gunsten des Mannes entschieden, und er belohnt " "Euch mit einem Anhänger, mit dem er seinen Geist für den Kampf zu beruhigen " "pflegte." msgid "Seeing-eye Pendant" msgstr "Anhänger des Sehenden Auges" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen Blendungszauber." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Ihr trefft auf eine sehr alte Frau, die seit langem am Grauen Star erblindet " "ist und allein im Sterben liegt. Ihr kümmert Euch um ihre letzten " "Bedürfnisse und versprecht Ihr ein angemessenes Begräbnis. Aus Dankbarkeit " "schenkt sie Euch einen magischen Anhänger, auf dem ein stilisiertes Auge " "prangt. Er lässt euch mit geschlossenen Augen sehen." msgid "Kinetic Pendant" msgstr "Kinetischer Anhänger" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen Lähmungszauber." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Euer Weg wird versperrt von einem Golem, der einen leuchtenden Anhänger " "trägt. Aufgrund einer Vorahnung schneidet Ihr ihm den Anhänger vom Hals. " "Seiner Kraftquelle beraubt, bricht der Golem zusammen und überlässt Euch den " "magischen Anhänger." msgid "Pendant of Death" msgstr "Anhänger des Todes" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen heilige Zaubersprüche." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "In einem schnellen und tödlichen Kampf mit einem Nekromanten gewinnt Ihr " "seinen magischen Anhänger. Später erfahrt Ihr von einem Zauberer, dass der " "Anhänger die Untoten in Euren Truppen vor den Zaubern des heiligen Wortes " "schützt." msgid "Wand of Negation" msgstr "Stab der Aufhebung" #, fuzzy msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "Der %{name} macht alle Eure Truppen immun gegen Todeszauber." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Ihr trefft einen alten Zaubererfreund, der euch auf dem Weg entgegengen " "kommt. Er überreicht Euch ein Geschenk: Einen Zauberstab, der die Anwendung " "des Zaubers \"Magie vertreiben\" bei deinen Truppen verhindert." msgid "Golden Bow" msgstr "Goldene Bogen" #, fuzzy msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "Der %{name} eliminiert den %{count} Prozentabzug für Eure Truppen, die an " "Hindernissen (z.B. Burgmauern) vorbeischießen." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Ein zufälliges Treffen mit einem berühmten Bogenschützen führt zu einem " "Würfelspiel. Er setzt seinen Bogen, Ihr Euer Pferd. Ihr gewinnt." msgid "Telescope" msgstr "Teleskop" #, fuzzy msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "Der %{name} erhöht die Menge an Gelände, die Euer Held bei Abenteuern " "aufdeckt, um %{count} zusätzliche Felder." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Ein Händler aus einem fernen Land tauscht eine neue Erfindung seines Volkes " "gegen Reiseproviant ein. Sie lässt entfernte Objekte näher erscheinen, und " "er nennt sie...\n" "\n" "ein Teleskop." msgid "Statesman's Quill" msgstr "Feder des Staatsmannes" #, fuzzy msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "Der %{name} reduziert die Kosten der Kapitulation auf %{count} Prozent der " "Gesamtkosten der Truppen in Eurer Armee." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Ihr haltet an, um einem Diplomaten bei der gebrochenen Achse seines Wagens " "zu helfen. Zum Dank schenkt er euch eine Schreibfeder mit magischen " "Eigenschaften, die, wie er sagt, \"den Leuten helfen wird, die Dinge auf " "eure Weise zu sehen\"." msgid "Wizard's Hat" msgstr "Hut des Zauberers" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "Der %{name} erhöht die Dauer Eurer Zaubersprüche um %{count} Runden." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Ihr seht einen berittenen Zauberer, der vor einem Greifen flieht. Der " "Zauberer öffnet ein Portal und reitet hindurch, wobei ihm der Hut von der " "Kante des Tores abgeschlagen wird. Der Greif folgt ihm; das Tor schließt " "sich. Ihr hebt den Hut auf, staubt ihn ab und setzt ihn auf." msgid "Power Ring" msgstr "Ring der Macht" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "Der %{name} gibt Eurem Helden %{count} zusätzliche Zauberpunkte pro Tag." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Ihr findet einen kleinen Baum, der dem großen Hexenmeister Carnauth sehr " "ähnelt und einen Ring an einem seiner Zweige trägt. Stofffetzen und " "verrottendes Leder lässt euch vermuten, dass es sich tatsächlich um den " "verwandelten Carnauth handelt. Da Ihr ihm nicht helfen könnt, nehmt Ihr den " "magischen Ring." msgid "Ammo Cart" msgstr "Munitionskarren" #, fuzzy msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "Der %{name} liefert unendlich viel Munition für alle Eure Truppen, die " "schießen." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Inmitten eines alten Schlachtfeld fällt Euch ein Munitionswagen ins Auge. " "Bei der Inspektion stellt sich heraus, dass er in gutem Zustand ist, also " "nehmt Ihr ihn mit." msgid "Tax Lien" msgstr "Steuererklärung" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "Der %{name} kostet Euch %{count} Goldstücke pro Tag." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Euer überschwängliches Konsumverhalten hat Euch eine Steuerrechnung " "eingebracht, die Ihr niemals werdet zahlen können. Der Finanzbeamte hat " "Mitleid und willigt ein, lebenslang nur 250 Gold pro Tag von Eurem Konto " "abzuziehen. Unterschreibt hier, wenn Ihr für den Wahlkampffonds des " "Praesidenten spenden wollt." msgid "Hideous Mask" msgstr "Scheußliche Maske" #, fuzzy msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "Der %{name} verhindert, dass sich alle \"wandernden\" Armeen Eurem Helden " "anschließen." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Ihr plündert das Grab von Sinfilas Gardolad, dem berühmten " "gestaltenwandlendem Hexenmeister und grabt seine sagenumwobene Maske aus. " "Zitternd setzt Ihr sie auf, und Euer Gesicht wird zu einer furchtbaren " "Fratze entstellt! Oh nein! Jetzt habt Ihr die scheussliche Maske von " "Gromluck Greene am Hals." msgid "Endless Pouch of Sulfur" msgstr "Endloser Schwefelbeutel" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "Der %{name} liefert %{count} Einheit Schwefel pro Tag." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Ihr besucht einen Alchemisten, der beim Anblick Eurer Armee von der " "Rechtschaffenheit eurer Sache überzeugt wird. Der neue loyale Untertan " "schenkt Euch seinen endlosen Beutel mit Schwefel, um Euch bei den " "Kriegsanstrengungen zu helfen." msgid "Endless Vial of Mercury" msgstr "Endloses Quecksilberfläschchen" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "Der %{name} liefert %{count} Einheit Quecksilber pro Tag." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Bei einem kurzen Zwischenstopp in einem hastig verlassenen Zaubererturm " "findet Ihr ein magisches Fläschchen mit Quecksilber, in dem immer ein wenig " "am Boden übrig bleibt. Einen Schatz erkennt Ihr immer sofort wenn Ihr ihn " "seht! Schnell steckt Ihr das Fläschchen in eure Tasche." msgid "Endless Pouch of Gems" msgstr "Endloser Edelsteinbeutel" msgid "The %{name} provides %{count} unit of gems per day." msgstr "Der %{name} liefert %{count} Einheit Edelsteine pro Tag." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Ein kurzer Regenschauer bringt einen Regenbogen hervor... und Ihr könnt das " "Ende des Regenbogens sehen. Schnell reitet Ihr los und nehmt den Goldtopf, " "den Ihr dort findet. Der Kobold, dem er gehört, kann Euch nicht daran " "hindern, bietet euch aber einen endlosen Beutel mit Edelsteinen an, wenn Ihr " "ihm sein Gold zurückgebt. Ihr akzeptiert diesen Tausch." msgid "Endless Cord of Wood" msgstr "Endloses Holzbündel" msgid "The %{name} provides %{count} unit of wood per day." msgstr "Der %{name} liefert %{count} Einheit Holz pro Tag." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Neben einem Holzestoß macht Ihr eine Rast, um euch auszuruhen. Für ein " "Lagerfeuer zieht Ihr einige Holzscheite aus dem Haufen. Dabei bemerkt Ihr, " "dass der Haufen nicht zu schrumpfen scheint. Zu Eurer Freude handelt es sich " "um verzaubertes Holz, welches Ihr sofort mitnehmt." msgid "Endless Cart of Ore" msgstr "Endloser Erzkarren" msgid "The %{name} provides %{count} unit of ore per day." msgstr "Der %{name} liefert %{count} Einheit Erz pro Tag." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Ihr habt eine Goblin-Waffenschmiede gefunden, die Waffen für den Einsatz " "gegen Menschen herstellt. Mit einem gewaltigen Schrei fallt Ihr mit eurer " "Armee über das Lager her und vertreibt die Goblins. Bei der Durchsuchung " "wird ein magischer Erzkarren sichergestellt, dem das Eisen nie ausgeht." msgid "Endless Pouch of Crystal" msgstr "Endloser Kristallbeutel" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "Der %{name} liefert %{count} Einheiten Kristall pro Tag." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Als Ihr in einer kleinen Höhle Schutz vor einem Sturm sucht, bemerkt Ihr in " "einer Ecke ein kleinen Kristall. Neugierig brecht Ihr ein Stück ab und " "stellt fest, dass dem Kristall das abgebrochene Stück nachwächst. Ihr " "beschließt, das gesamte Stück in einen Beutel zu stecken und mitzunehmen." msgid "Spiked Helm" msgstr "Stachelhelm" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Eure Armee gerät in einen Hinterhalt eines kleinen Stammes wilder (und nicht " "sehr schlauer) Orks. Ihr wehrt sie mühelos ab, und die Überlebenden fliehen " "in alle Richtungen. Einer der Orks trug einen polierten Helm mit Stacheln. " "Da er ein gutes Souvenir abgibt, nehmt Ihr ihn mit." msgid "Spiked Shield" msgstr "Stachelschild" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Ihr kommt zu einer Brücke, die eine trockene Schlucht überspannt. Bevor Ihr " "sie überqueren könnt, tritt ein Troll unter der Brücke hervor und verlangt " "einen Wegezoll. Ihr lehnt ab, woraufhin der Troll angreift und Ihr ihn " "erschlagt. Ihr nehmt seinen Stachelschild als Trophäe an euch." msgid "White Pearl" msgstr "Weisse Perle" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Bei einem Spaziergang über das Bett eines vertrockneten Salzwassersees " "findet Ihr eine unwahrscheinliche Beute: Eine weiße Perle inmitten von " "zerbrochenen Muscheln und Schutt." msgid "Black Pearl" msgstr "Schwarze Perle" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Gerüchte über einen Greif von ungewöhnlicher Größe, der das Land heimsucht, " "führen Euch zu seinem Höhlennest. Ein schneller, brutaler Kampf schickt die " "Bestie ins Jenseits. Bei der Durchsuchung des fauligen Nestes findet Ihr " "eine riesige schwarze Perle." msgid "Magic Book" msgstr "Zauberbuch" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "Das %{name} ermöglicht Euch Zaubersprüche auszusprechen." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Dummy 2" msgid "The reserved artifact." msgstr "Das reservierte Artefakt." msgid "Dummy 3" msgstr "Dummy 3" msgid "Dummy 4" msgstr "Dummy 4" msgid "Spell Scroll" msgstr "Zauberspruchrolle" #, fuzzy msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Dieser %{name} gibt Eurem Helden die Fähigkeit, den %{spell} zu wirken, wenn " "Euer Held ein Zauberbuch besitzt." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Ihr findet ein kunstvolles Gefäß, das eine alte Pergamentschriftrolle " "enthält. Die Runen auf dem Behälter sind sehr alt, und die Kunstfertigkeit, " "mit der er zusammengesetzt wurde, ist atemberaubend. Als Ihr die " "Schriftrolle herauszieht, fühlt Ihr Euch von magischer Kraft durchdrungen." msgid "Arm of the Martyr" msgstr "Arm des Märtyrers" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "Der %{name} erhöht Eure Zauberkraft um %{count}, fügt aber eine Strafe auf " "die Moral für die Untote in der Armee hinzu." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Eines der weniger hellen Mitglieder Eurer Gruppe hebt einen Arm vom Boden " "auf. Obwohl ihm einen Körper fehlt, bewegt er sich noch. Eure Truppen finden " "den abgetrennten Arm abstoßend, aber Ihr könnt Euch nicht überwinden, ihn " "fallen zu lassen: Er scheint eine Art magische Kraft zu besitzen, die Eure " "Entscheidungsfindung beeinflusst." msgid "Breastplate of Anduran" msgstr "Brustpanzer von Anduran" msgid "The %{name} increases the hero's defense by %{count}." msgstr "Der %{name} erhöht Eure Verteidigung um %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Ihr kommt an ein Schild. Darauf steht: \"Hier liegt der Körper von Anduran. " "Verbeuge Dich und schwöre, so sollst du belohnt werden.\". Ihr tut, was das " "Schild verlangt. Als Ihr euch aufrichtet, spürt Ihr Kälte auf der Haut. Ihr " "seht herab und merkt, dass Ihr einen glänzenden, verzierten Brustpanzer " "tragt." msgid "Broach of Shielding" msgstr "Brosche der Abschirmung" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "Der %{name} bietet %{count} Prozent Schutz vor Armageddon und " "Elementarsturm, verringert aber die Zauberkraft um 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Eine freundliche Zauberin ist der Meinung, dass die Verteidigung Eurer Armee " "eine magische Verstärkung gebrauchen könnte. Sie bietet Euch an, die " "Brosche, die Ihr an Euren Mantel tragt, zu verzaubern, was Ihr akzeptiert." msgid "Battle Garb of Anduran" msgstr "Kampfrüstung von Anduran" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "Die %{name} vereint die Kräfte der drei Anduranischen Artefakte. Sie " "maximales Glück und Moral für Eure Truppen und gibt Euch den Stadtportal-" "Zauberspruch." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Aus Mitleid für einen armen Bauern kauft Ihr ihm für viel zu viel Gold eine " "Truhe mit altem Gerümpel ab, mit der er hausieren geht. Als Ihr sie später " "durchsucht, findet Ihr die 3 Teile der legendären Kampfrüstung von Anduran!" msgid "Crystal Ball" msgstr "Kristallkugel" #, fuzzy msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "Mit %{name} erhaltet Ihr genauere Informationen über Monster, feindliche " "Helden und Burgen in der Nähe des Helden, der sie hält." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Ihr trefft auf eine Karawane von Zigeunern, die gerade auf einer Weise " "feiern und sich mit Met stärken. Sie rufen Euch nach vorne und sagen: \"Wenn " "Du den Rama-Buta tanzen kannst, werden wir Dich belohnen.\" Ihr wisst nicht " "genau was gemeint ist, versucht es aber trotzdem. Die Zigeunern lachen " "hysterisch, bewundern aber Eure Tapferkeit und schenken Euch eine " "Kristallkugel." msgid "Heart of Fire" msgstr "Herz aus Feuer" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "Der %{name} bietet %{count} Prozent Schutz vor Feuer, verdoppelt aber den " "durch Kälte erlittenen Schaden." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Ihr betretet eine kürzlich abgebrannte Lichtung, wo ein Feuerwesen auf einem " "Felsen sitzt. Es schaut auf und sein flammendes Gesicht ist schmerzverzerrt. " "Dann wirft es ein glühendes Objekt nach Euch. Schnell schützt Ihr Euch mit " "Euren Händen, aber es fliegt einfach durch sie hindurch und brennt sich ein " "in Eure Brust." msgid "Heart of Ice" msgstr "Herz aus Eis" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "Der %{name} bietet %{count} Prozent Schutz vor Kälte, verdoppelt aber den " "durch Feuer erlittenen Schaden." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Plötzlich durchdringt eine beißende Kälte Euren Körper. Ihr erstarrt und " "fallt vom Pferd. Der Schmerz lässt nach, aber Eure Brust fühlt sich noch " "immer gefroren an. Als Ihr vom Boden aufsteht, hört Ihr lautes Gelächter. " "Ihr dreht Euch um und seht gerade noch einen Frostriesen, der im Wald " "verschwindet." msgid "Helmet of Anduran" msgstr "Helm von Anduran" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Ihr entdeckt ein schimmerndes Objekt, das aus dem Boden ragt. Ihr schickt " "ein Mitglied Eurer Truppen los, um nachzusehen. Er kommt mit einem goldenen " "Helm in den Händen zurück. Ihr bemerkt, dass es der Helm des legendären " "Anduran ist, des einzigen Mannes, der eine Rüstung aus massivem Gold trug." msgid "Holy Hammer" msgstr "Heiliger Hammer" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Ihr kommt zu einem Kampf, bei dem ein Paladin von einer Gruppe Zombies " "tödlich verletzt wurde. Er bittet Euch, seinen Hammer zu nehmen und den " "Kampf zu beenden. Als Ihr ihn aufhebt, beginnt er zu summen und alles " "verschwimmt. Die Zombies sind tot, der Hammer trieft vor Blut. Ihr hängt ihn " "an Euren Gürtel." msgid "Legendary Scepter" msgstr "Legendäres Zepter" msgid "The %{name} adds %{count} points to all attributes." msgstr "Der %{name} fügt %{count} Punkte zu allen Attributen hinzu." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Auf einem Hügel bietet sich Euch ein lächerlicher Anblick. Eine Fee versucht " "ein Zepter zu tragen, das fast so groß ist wie sie selbst. Ihr versucht " "nicht zu lachen und fragen: \"Brauchst Du Hilfe?\" Der Fee starrt Euch an " "und antwortet: \"Findest Du das lustig? Gut. Dann nimm es. Ich fliege lieber " "davon.\"" msgid "Masthead" msgstr "Gallionsfigur" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "Der %{name} erhöht Euer Glück und Eure Moral im Seekampf um jeweils %{count}." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Ein alter Seemann erzählt Euch eine Geschichte von einer verzauberten " "Gallionsfigur, mit der er früher seine Crew in schwierigen Zeiten bei Laune " "hielt. Er gibt Euch eine ausgeblichene Karte, die zeigt, wo er sie versteckt " "hat. Nach langer Suche findet Ihr sie an einem nahen Dock." msgid "Sphere of Negation" msgstr "Zauberkugel der Aufhebung" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "Der %{name} deaktiviert alle Zaubersprüche für beide Seiten im Kampf." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Ihr haltet an, um einem Bauern zu helfen, eine entlaufene Stute zu fangen. " "Als Zeichen seiner Dankbarkeit gibt er Euch eine winzige Kugel. Als Ihr sie " "ergreifet, fühlt Ihr die magische Energie aus Euren Gliedern abfliessen..." msgid "Staff of Wizardry" msgstr "Stab der Zauberei" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "Der %{name} erhöht Eure Zauberkraft um %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Während einer Erkundung finden Eure Truppen einen mysterioesen Stab, der " "etwa auf Bauchhöhe über dem Boden schwebt. Sie geben Euch den Stab, wobei " "Ihr eine Inschrift bemerkt: \"Geist schlägt Muskel und Magie schlägt Macht. " "Beachte meine Worte, dann gewinnst Du jede Schlacht.\"" msgid "Sword Breaker" msgstr "Parierdolch" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "" "Der %{name} erhöht Eure Verteidigung um %{count} und Euren Angriff um 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Ein ehemaliger Hauptmann der Garde bewundert Eure Mission und schenkt Euch " "den verzauberten Parierdolch, auf den er sich während seiner gesamten " "Dienstzeit verlassen hat." msgid "Sword of Anduran" msgstr "Schwert von Anduran" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Ein Troll stoppt Euch und sagt: \"Zahle 5.000 Goldstücke, oder das Schwert " "von Anduran wird Dich auf der Stelle töten.\" Ihr lehnt ab. Der Troll nimmt " "das an seinem Gürtel hängende Schwert, schreit vor Schmerz und läuft davon. " "Ihr hebt das Fabelschwert auf und denkt, dass dumme Trolle oft scharfe Dinge " "am falschen Ende packen." msgid "Spade of Necromancy" msgstr "Spaten der Nekromantie" #, fuzzy msgid "The %{name} gives the hero increased necromancy skill." msgstr "Der %{name} verleiht Euch erhöhte Nekromantie-Fähigkeiten." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Eine schmutziger Spaten wurde in einen nahen Erdhügel gestossen. Bei näherer " "Untersuchung stellt Ihr fest, dass es sich um den verzauberten Spaten der " "Totengräber handelt, der den Sterblichen schon lange als verschollen galt." msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Holz" msgid "Mercury" msgstr "Quecksilber" msgid "Ore" msgstr "Erz" msgid "Sulfur" msgstr "Schwefel" msgid "Crystal" msgstr "Kristalle" msgid "Gems" msgstr "Edelsteine" msgid "Gold" msgstr "Gold" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "In Heroes 2 gibt es sieben Ressourcen, mit denen Burgen gebaut und " "verbessert, Truppen gekauft und Helden rekrutiert werden können. Gold ist " "der häufigste und wird für praktisch alles benötigt. Holz und Erze werden " "für die meisten Gebäude verwendet. Edelsteine, Quecksilber, Schwefel und " "Kristall sind seltene magische Ressourcen, die für die mächtigsten Kreaturen " "und Gebäude verwendet werden." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Verursacht einen riesigen Feuerball, der das ausgewählte Gebiet trifft und " "allen Kreaturen in der Nähe Schaden zufügt." msgid "Fireball" msgstr "Feuerball" msgid "Fireblast" msgstr "Feuerstoß" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Eine verbesserte Version des Feuerballs: Der Feuerstoß wirkt auf zwei Felder " "um den Mittelpunkt des Zaubers statt auf ein Feld." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "" "Verursacht einen Blitz aus elektrischer Energie, der die ausgewählte Kreatur " "trifft." msgid "Lightning Bolt" msgstr "Blitzstrahl" msgid "Chain Lightning" msgstr "Kettenblitzstrahl" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Verursacht einen Blitz elektrischer Energie, der eine ausgewählte Kreatur " "trifft, dann die nächste Kreatur mit halbem Schaden trifft, dann die nächste " "Kreatur mit wieder halbem Schaden trifft, und so weiter, bis er zu schwach " "wird, um Schaden anzurichten. Warnung! Dieser Zauber kann Eure eigenen " "Kreaturen treffen!" msgid "Teleport" msgstr "Teleport" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Teleportiert die Kreatur, die Ihr auswählt, an eine freie Position Eurer " "Wahl auf dem Schlachtfeld." msgid "Cure" msgstr "Heilung" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Entfernt alle negativen Zauber, die auf eine Eurer Einheiten gewirkt wurden, " "und stellt bis zu %{count} TP pro Stufe der Zauberkraft wieder her." msgid "Mass Cure" msgstr "Massenheilung" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Entfernt alle negativen Zauber, die auf Eure Truppen gewirkt wurden, und " "stellt bis zu %{count} TP pro Stufe der Zauberkraft und pro Kreatur wieder " "her." msgid "Resurrect" msgstr "Auferstehung" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Lässt Kreaturen einer beschädigten oder toten Einheit bis zum Ende des " "Kampfes wieder auferstehen." msgid "Resurrect True" msgstr "Wahre Auferstehung" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" "Lässt Kreaturen aus einer beschädigten oder toten Einheit dauerhaft wieder " "auferstehen." msgid "Haste" msgstr "Eile" msgid "Increases the speed of any creature by %{count}." msgstr "Erhöht die Geschwindigkeit einer beliebigen Kreatur um %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Erhöht die Geschwindigkeit aller Eurer Kreaturen um %{count}." msgid "Mass Haste" msgstr "Masseneile" msgid "Slows target to half movement rate." msgstr "Verlangsamt die Bewegungsgeschwindigkeit des Ziels auf die Hälfte." msgid "spell|Slow" msgstr "Verlangsamung" msgid "Mass Slow" msgstr "Massenverlangsamung" msgid "Slows all enemies to half movement rate." msgstr "Verlangsamt alle Feinde auf die halbe Bewegungsrate." msgid "spell|Blind" msgstr "Blenden" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" "Trübt die Augen der betroffenen Kreaturen und hindert sie daran, sich zu " "bewegen." msgid "Bless" msgstr "Segen" msgid "Causes the selected creatures to inflict maximum damage." msgstr "" "Bewirkt, dass die ausgewählten Kreaturen maximalen Schaden verursachen." msgid "Causes all of your units to inflict maximum damage." msgstr "Bewirkt, dass alle Eure Einheiten maximalen Schaden verursachen." msgid "Mass Bless" msgstr "Massensegen" msgid "Magically increases the defense skill of the selected creatures." msgstr "" "Erhöht auf magische Weise die Verteidigungsfähigkeit der ausgewählten " "Kreaturen." msgid "Stoneskin" msgstr "Steinhaut" msgid "Steelskin" msgstr "Stahlhaut" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Erhöht die Verteidigungsfähigkeit der ausgewählten Kreaturen. Dies ist eine " "verbesserte Version von Steinhaut." msgid "Causes the selected creatures to inflict minimum damage." msgstr "" "Bewirkt, dass die ausgewählten Kreaturen minimalen Schaden verursachen." msgid "Curse" msgstr "Fluch" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Bewirkt, dass alle gegnerischen Truppen minimalen Schaden verursachen." msgid "Mass Curse" msgstr "Massenfluch" msgid "Damages all undead in the battle." msgstr "Schadet allen Untoten im Kampf." msgid "Holy Word" msgstr "Heiliges Wort" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Schadet allen Untoten im Kampf. Dies ist eine verbesserte Version von " "Heiliges Wort." msgid "Holy Shout" msgstr "Heiliger Ruf" msgid "Anti-Magic" msgstr "Anti-Magie" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Verhindert schädliche Magie gegen die ausgewählten Kreaturen." msgid "Dispel Magic" msgstr "Magie zerstreuen" msgid "Removes all magic spells from a single target." msgstr "Entfernt alle Zaubersprüche von einem einzigen Ziel." msgid "Mass Dispel" msgstr "Magie-Mas- senzerstrg." msgid "Removes all magic spells from all creatures." msgstr "Entfernt alle Zaubersprüche von allen Kreaturen." msgid "Causes a magic arrow to strike the selected target." msgstr "Bewirkt, dass ein magischer Pfeil das ausgewählte Ziel trifft." msgid "Magic Arrow" msgstr "Magischer Pfeil" msgid "Berserker" msgstr "Berserker" msgid "Causes a creature to attack its nearest neighbor." msgstr "Bewirkt, dass eine Kreatur ihren nächsten Nachbarn angreift." msgid "Armageddon" msgstr "Armageddon" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Heiliger Terror schlägt auf dem Schlachtfeld zu und verursacht an allen " "Kreaturen schweren Schaden." msgid "Elemental Storm" msgstr "Elementsturm" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "Magische Elemente ergießen sich auf das Schlachtfeld und fügen allen " "Kreaturen Schaden zu." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Ein Steinregen trifft ein Gebiet auf dem Schlachtfeld und fügt allen " "Kreaturen in der Nähe Schaden zu." msgid "Meteor Shower" msgstr "Meteorregen" msgid "Paralyze" msgstr "Lähmen" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "Die anvisierten Kreaturen sind gelähmt und können sich nicht bewegen oder " "sich wehren." msgid "Hypnotize" msgstr "Hypnose" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Bringt eine einzelne feindliche Einheit unter deine Kontrolle, wenn ihre " "Treffer weniger als das %{count}-fache der Zauberkraft des Zaubernden " "betragen." msgid "Cold Ray" msgstr "Kalter Strahl" msgid "Drains body heat from a single enemy unit." msgstr "Entzieht einer einzelnen gegnerischen Einheit Körperwärme." msgid "Cold Ring" msgstr "Kalter Ring" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Leitet die Körperwärme von allen Einheiten ab, die den Mittelpunkt umgeben, " "aber den Mittelpunkt nicht einschließen." msgid "Disrupting Ray" msgstr "Zertruemmerungsstrahl" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Reduziert den Verteidigungswert einer gegnerischen Einheit um drei." msgid "Damages all living (non-undead) units in the battle." msgstr "Schadet allen lebenden (nicht untoten) Einheiten in der Schlacht." msgid "Death Ripple" msgstr "Kleine Todeswelle" msgid "Death Wave" msgstr "Todeswelle" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Schadet allen lebenden (nicht untoten) Einheiten in der Schlacht. Dieser " "Zauber ist eine verbesserte Version von Kleine Todeswelle." msgid "Dragon Slayer" msgstr "Drachentöter" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Erhöht die Angriffsfähigkeit einer Einheit gegen Drachen erheblich." msgid "Blood Lust" msgstr "Blutdurst" msgid "Increases a unit's attack skill." msgstr "Erhöht die Angriffsfähigkeit einer Einheit." msgid "Animate Dead" msgstr "Tote beleben" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "Lässt Kreaturen aus einer beschädigten oder toten untoten Einheit dauerhaft " "wieder auferstehen." msgid "Mirror Image" msgstr "Spiegelbild" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Erzeugt eine illusionäre Einheit als Spiegelbild einer wirklichen Einheit. " "Die illusionäre Einheit verursacht die gleichen Schäden wie die Echte,löst " "sich aber bei der geringsten Verletzung in Luft auf." msgid "Shield" msgstr "Schild" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halbiert den Schaden von Fernkampfangriffen für eine einzelne Einheit. " "Beeinflusst nicht den von Geschütztürmen oder Ballisten erlittenen Schaden." msgid "Mass Shield" msgstr "Massenschild" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halbiert den Schaden von Fernkampfangriffen für alle Eure Einheiten. " "Beeinflusst nicht den von Geschütztürmen oder Ballisten erlittenen Schaden." msgid "Summon Earth Elemental" msgstr "Erdwesen herbeirufen" msgid "Summons Earth Elementals to fight for your army." msgstr "Beschwört Erdwesen, um für Eure Armee zu kämpfen." msgid "Summon Air Elemental" msgstr "Luftwesen herbeirufen" msgid "Summons Air Elementals to fight for your army." msgstr "Beschwört Luftwesen, um für Eure Armee zu kämpfen." msgid "Summon Fire Elemental" msgstr "Feuerwesen herbeirufen" msgid "Summons Fire Elementals to fight for your army." msgstr "Beschwört Feuerwesen, um für Eure Armee zu kämpfen." msgid "Summon Water Elemental" msgstr "Wasserwesen herbeirufen" msgid "Summons Water Elementals to fight for your army." msgstr "Beschwört Wasserwesen, um für Eure Armee zu kämpfen." msgid "Damages castle walls." msgstr "Beschädigt die Burgmauern." msgid "Earthquake" msgstr "Erdbeben" msgid "Causes all mines across the land to become visible." msgstr "Bewirkt, dass alle Minen im Land sichtbar werden." msgid "View Mines" msgstr "Minen anzeigen" msgid "Causes all resources across the land to become visible." msgstr "Bewirkt, dass alle Ressourcen im Land sichtbar werden." msgid "View Resources" msgstr "Ressourcen anzeigen" msgid "Causes all artifacts across the land to become visible." msgstr "Bewirkt, dass alle Artefakte im Land sichtbar werden." msgid "View Artifacts" msgstr "Artefakte anzeigen" msgid "Causes all towns and castles across the land to become visible." msgstr "" "Bewirkt, dass alle Städte und Schlösser im ganzen Land sichtbar werden." msgid "View Towns" msgstr "Städte anzeigen" msgid "Causes all Heroes across the land to become visible." msgstr "Bewirkt, dass alle Helden im ganzen Land sichtbar werden." msgid "View Heroes" msgstr "Held anzeigen" msgid "Causes the entire land to become visible." msgstr "Lässt das gesamte Land sichtbar werden." msgid "View All" msgstr "Alles anzeigen" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" "Ermöglicht es dem Zaubernden, detaillierte Informationen über feindliche " "Helden einzusehen." msgid "Summon Boat" msgstr "Boot herbeirufen" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Ruft das nächstgelegene unbesetzte, eigene Boot an ein dem Helden " "angrenzendes Ufer. Ein eigenes Boot ist eines, das Ihr gerade gebaut oder " "das Ihr als letzter Spieler belegt habt." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Ermöglicht es dem Zaubernden, sich auf magische Weise an einen nahe " "gelegenen Ort zu begeben." msgid "Dimension Door" msgstr "Dimensionstor" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Bringt den Zaubernden in jene Stadt oder Burg zurück, die er gerade besitzt." msgid "Town Gate" msgstr "Stadttor" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Bringt den Helden in die Stadt oder Burg Eurer Wahl zurück, sofern diese von " "Euch kontrolliert wird." msgid "Visions" msgstr "Vision" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Die Visionen sagen den wahrscheinlichen Ausgang einer Begegnung mit einem " "neutralen Heerlager voraus." msgid "Haunt" msgstr "Spuk" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Lässt Geister in einer von Euch kontrollierten Mine spuken. Diese Mine " "stellt die Produktion ein. (Wenn ich sie nicht behalten kann, soll es " "niemand tun!)" msgid "Set Earth Guardian" msgstr "Erdwesen-Wache" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Setzt Erdwesen ein, um eine Mine vor feindlichen Armeen zu schützen." msgid "Set Air Guardian" msgstr "Luftwsn.-Wache" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Setzt Luftwesen ein, um eine Mine vor feindlichen Armeen zu schützen." msgid "Set Fire Guardian" msgstr "Feuerwsn.-Wache" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Setzt Feuerwesen ein, um eine Mine vor feindlichen Armeen zu schützen." msgid "Set Water Guardian" msgstr "Wasserws.-Wache" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" "Setzt Wasserwesen ein, um eine Mine vor feindlichen Armeen zu schützen." #, fuzzy msgid "Random Spell" msgstr "Zufällig" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "Zufälliges Burg" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "Versteinerung" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Verwandelt die betroffene Kreatur in Stein. Eine versteinerte Kreatur " "erleidet bei einem direkten Angriff die Hälfte des Schadens." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Ihr habt kein Zauberbuch und könnt daher nicht zaubern." msgid "No spell to cast." msgstr "Kein Zauber zu wirken." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Euer Held hat noch %{point} Zauberpunkte übrig." msgid "View Adventure Spells" msgstr "Abenteuerzauber anzeigen" msgid "View Combat Spells" msgstr "Kampfzauber anzeigen" msgid "View previous page" msgstr "Vorherige Seite anzeigen" msgid "View next page" msgstr "Nächste Seite anzeigen" msgid "Close Spellbook" msgstr "Zauberbuch schließen" msgid "View %{spell}" msgstr "%{spell} Anzeigen" msgid "This spell does %{damage} points of damage." msgstr "Dieser Zauber verursacht %{damage} Schaden." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Dieser Zauber beschwört\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Dieser Zauber stellt %{hp} TP wieder her." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Dieser Zauber beschwört %{count} %{monster}, um die Mine zu bewachen." msgid "The nearest town is %{town}." msgstr "Die nächstgelegene Stadt ist %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Diese Stadt ist von Eurem Helden %{hero} besetzt." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Dieser Zauberspruch kontrolliert bis zu\n" "%{hp} TP." msgid "The ultimate artifact is really the %{name}." msgstr "Das ultimative Artefakt ist eigentlich der %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Das ultimative Artefakt kann im %{name} von der Welt gefunden werden." msgid "north-west" msgstr "Nordwesten" msgid "north" msgstr "Nord" msgid "north-east" msgstr "Nordosten" msgid "west" msgstr "Westen" msgid "center" msgstr "Zentrum" msgid "east" msgstr "Osten" msgid "south-west" msgstr "Südwesten" msgid "south" msgstr "Süden" msgid "south-east" msgstr "Südosten" msgid "The truth is out there." msgstr "Die Wahrheit liegt auf der Hand." msgid "The dark side is stronger." msgstr "Die dunkle Seite ist stärker." msgid "The end of the world is near." msgstr "Das Ende der Welt ist nah." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Die Gebeine von Lord Slayer sind im Fundament der Arena begraben." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Ein Schwarzer Drache kann es jederzeit mit einem Titanen aufnehmen." #, fuzzy msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "Er sagte ihr: Yada yada yada... und dann sagte sie: Bla, bla, bla..." msgid "An unknown force is being resurrected..." msgstr "Eine unbekannte Macht wird wiederbelebt..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Die neueste Version des Spiels finden Sie unter\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Anzahl %{resource} wählen:" #~ msgid "Enable auto combat" #~ msgstr "Autokampf einschalten" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "Kampf im Automodus beenden" #~ msgid "Please Remember" #~ msgstr "Bitte merken" # Needs extra whitespace to avoid yellow word splitting #, fuzzy #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Die Auflösung des Spiels kann jederzeit geändernt werden, durch klicken " #~ "auf die " #~ msgid "door" #~ msgstr "Tür" #, fuzzy #~ msgid "NEW GAME" #~ msgstr "" #~ "NEUES\n" #~ "SPIEL" #~ msgid "Warning!" #~ msgstr "Achtung!" #~ msgid "Dummy 1" #~ msgstr "Dummy 1" fheroes2-1.1.6+dfsg/files/lang/dk.po000066400000000000000000011750021476115357100171540ustar00rootroot00000000000000# Danish translation for fheroes2 # Copyright (C) 2021 - 2023 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-05-21 12:45+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: Danish (Denmark)\n" "Language: da\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-Loco-Source-Locale: da_DK\n" "X-Launchpad-Export-Date: 2010-05-27 09:12+0000\n" "X-Generator: Poedit 3.2.2\n" "X-Loco-Parser: loco_parse_po\n" msgid "" "NEW\n" "GAME" msgstr "" "NYT\n" "SPIL" msgid "" "SAVE\n" "GAME" msgstr "" "GEM\n" "SPIL" msgid "" "LOAD\n" "GAME" msgstr "" "INDLÆS\n" "SPIL" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "AFSLUT" msgid "" "NEW\n" "MAP" msgstr "" "NYT\n" "KORT" msgid "" "SAVE\n" "MAP" msgstr "" "GEM\n" "KORT" msgid "" "LOAD\n" "MAP" msgstr "" "INDLÆS\n" "KORT" msgid "CANCEL" msgstr "AFBRYD" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "GODTAG" msgid "DECLINE" msgstr "AFSLÃ…" msgid "LEARN" msgstr "LÆR" msgid "TRADE" msgstr "BYT" msgid "YES" msgstr "JA" msgid "NO" msgstr "NEJ" msgid "EXIT" msgstr "UD" msgid "smallerButton|EXIT" msgstr "UD" msgid "DISMISS" msgstr "BORTVIS" msgid "UPGRADE" msgstr "OPG." msgid "RESTART" msgstr "OMKAMP" msgid "HEROES" msgstr "HELTE" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "BYER\n" "BORGE" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "XL" msgid "ALL" msgstr "ALT" msgid "SELECT" msgstr "VÆLG" msgid "" "STANDARD\n" "GAME" msgstr "" "ENKELT\n" "SPILLER" msgid "" "BATTLE\n" "ONLY" msgstr "" "KUN\n" "KAMP" msgid "" "CAMPAIGN\n" "GAME" msgstr "FELTTOG" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "FLER-\n" "SPILLER" msgid "CONFIG" msgstr "INDSTIL" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ORIGINALT\n" "FELTTOG" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "UDVIDELSE\n" "FELTTOG" msgid "HOT SEAT" msgstr "LOKALT" msgid "2 PLAYERS" msgstr "2 SPILLERE" msgid "3 PLAYERS" msgstr "3 SPILLERE" msgid "4 PLAYERS" msgstr "4 SPILLERE" msgid "5 PLAYERS" msgstr "5 SPILLERE" msgid "6 PLAYERS" msgstr "6 SPILLERE" msgid "GIFT" msgstr "FORÆR" msgid "MAX" msgstr "MAKS" msgid "DIFFICULTY" msgstr "NIVEAU" msgid "VIEW INTRO" msgstr "VIS INTRO" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "NULSTIL" msgid "START" msgstr "START" msgid "TOWN" msgstr "BY" msgid "CASTLE" msgstr "BORGE" msgid "RESTRICT" msgstr "BEGRÆNS" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "B\n" "O\n" "R\n" "T\n" "V\n" "I\n" "S" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "U\n" "D" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "P\n" "A\n" "T\n" "R\n" "U\n" "L\n" "J\n" "E" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "F\n" "E\n" "L\n" "T\n" "T\n" "O\n" "G" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "E\n" "N\n" "K\n" "E\n" "L\n" "T" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Kriger" msgid "Builder" msgstr "Bygger" msgid "Explorer" msgstr "Udforsker" msgid "None" msgstr "Ingen" msgid "" "A few\n" "%{monster}" msgstr "" "Nogle fÃ¥\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Flere\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "En flok\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Masser af\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "En horde af\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "En skare af\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "En sværm af\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Pokkers mange\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "En legion af\n" "%{monster}" msgid "army|Few" msgstr "FÃ¥" msgid "army|Several" msgstr "Flere" msgid "army|Pack" msgstr "Flok" msgid "army|Lots" msgstr "Mange" msgid "army|Horde" msgstr "Horde" msgid "army|Throng" msgstr "Skare" msgid "army|Swarm" msgstr "Sværm" msgid "army|Zounds" msgstr "Pokkers" msgid "army|Legion" msgstr "Legion" msgid "All %{race} troops +1" msgstr "Alle %{race} tropper +1" msgid "NeutralRaceTroops|Neutral" msgstr "Neutral" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Tropper af %{count} tilknytninger -%{penalty}" msgid "Some undead in army -1" msgstr "Der er udøde i hæren -1" msgid "" "Default\n" "troop" msgstr "" "standard\n" "trop" msgid "View %{name}" msgstr "Vis %{name}" msgid "Move the %{name} " msgstr "Flyt %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Flyt eller højreklik for at omfordele %{name}" msgid "Combine %{name} armies" msgstr "Kombiner %{name} hærene" msgid "Exchange %{name2} with %{name}" msgstr "Byt %{name2} med %{name}" msgid "Select %{name}" msgstr "Vælg %{name}" msgid "Cannot move last troop" msgstr "Sidste trop kan ikke flyttes" msgid "Move the %{name}" msgstr "Flyt %{name}" msgid "Set %{monster} Count" msgstr "Indstil antal %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} udsletter halvdelen af fjendens tropper!" msgstr[1] "%{name} udsletter halvdelen af fjendens tropper!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} har deaktiveret automatisk kamp" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} har aktiveret automatisk kamp" msgid "Spell failed!" msgstr "Magien mislykkedes!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Artefaktet Negationskuglen er i kraft, hvilket deaktiverer brug af enhver " "kampmagi." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Du har allerede kastet magi én gang i denne runde." msgid "That spell will have no effect!" msgstr "Dén besværgelse vil ikke pÃ¥virke nogen!" msgid "You may only summon one type of elemental per combat." msgstr "Du mÃ¥ kun hidkalde én slags elemental per kamp." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Der er ingen Ã¥ben plads ved siden af din helt til at hidkalde elementaler pÃ¥." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Enhver enhed, der mÃ¥tte træde ned i voldgraven, fÃ¥r -%{count} forsvarsevne " "samt begrænset bevægelsesevne, indtil denne igen forlader voldgraven." msgid "Speed: %{speed}" msgstr "Hastighed: %{speed}" msgid "Speed" msgstr "Hastighed" msgid "Off" msgstr "Fra" msgid "On" msgstr "Til" msgid "Turn Order" msgstr "Turorden" msgid "Auto Spell Casting" msgstr "Autobrug af magi" msgid "Grid" msgstr "Gitter" msgid "Shadow Movement" msgstr "" "Skygge-\n" "bevægelse" msgid "Shadow Cursor" msgstr "Skyggemarkør" msgid "Audio" msgstr "Lyd" msgid "Settings" msgstr "Indstillinger" msgid "Configure" msgstr "Indstil" msgid "Hot Keys" msgstr "Genvejstaster" msgid "Damage Info" msgstr "Skadeinfo" msgid "Set the speed of combat actions and animations." msgstr "Indstil hastighed for kamphandlinger og animationer." msgid "Toggle to display the turn order during the battle." msgstr "Vælg om kampens turorden skal vises eller ej." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Vælg om computerens evne til selv at kaste magi for dig skal være aktiv " "eller ej, nÃ¥r Autokamp er slÃ¥et til. (Note: Dette pÃ¥virker hverken AI-" "spillere eller kvikkamp pÃ¥ nogen mÃ¥de.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Vælg om hex-gitteret skal være synligt eller ej. Hex-gitteret ligger til " "grund for bevægelse, selv hvis det ikke er synligt." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Vælg om der skal være skygger, som bÃ¥de viser hvor dine væsener kan angribe " "og gÃ¥ hen, eller ej." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Vælg om der skal være skygger, som viser musemarkørens nuværende hex-" "lokation, eller ej." msgid "Change the audio settings of the game." msgstr "Ændr spillets lydindstillinger." msgid "Check and configure all the hot keys present in the game." msgstr "Tjek og indstil alle spillets nuværende genvejstaster." msgid "Toggle to display damage information during the battle." msgstr "Vælg om kampens skadeinformationer skal vises eller ej." msgid "Exit this menu." msgstr "Forlad denne menu." msgid "Okay" msgstr "Okay" msgid "The enemy has surrendered!" msgstr "Fjenden har overgivet sig!" msgid "Their cowardice costs them %{gold} gold." msgstr "Deres fejhed koster dem %{gold} guld." msgid "The enemy has fled!" msgstr "Fjenden er flygtet!" msgid "A glorious victory!" msgstr "En glorværdig sejr!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "For at udvise tapperhed i kamp, fÃ¥r %{name} %{exp} erfaringspoint." msgid "The cowardly %{name} flees from battle." msgstr "Den kujonagtige %{name} flygter fra kampen." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} overgiver sig til fjenden, og træder fra med skam." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Dine styrker lider et bittert nederlag, og %{name} opgiver din sag." msgid "Your forces suffer a bitter defeat." msgstr "Dine styrker lider et bittert nederlag." msgid "Battlefield Casualties" msgstr "Slagmarkens ofre" msgid "Attacker" msgstr "Angriber" msgid "Defender" msgstr "Forsvarer" msgid "Click to leave the battle results." msgstr "Klik for at godkende kampresultaterne." msgid "Click to restart the battle in manual mode." msgstr "Klik for at genstarte kampen i manuel tilstand." msgid "Restart" msgstr "Genstart" msgid "You have captured an enemy artifact!" msgstr "Du har stjÃ¥let et af fjendens artefakter!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Lige som du rækker ud efter %{name}, forsvinder det mysteriøst." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" "Lige som din fjende rækker ud efter %{name}, forsvinder det mysteriøst." msgid "Necromancy!" msgstr "Nekromanti!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Ved brug af nekromantiens mørke kunst, er du i stand til at lade %{count} af " "fjendens døde genopstÃ¥ under din tjeneste som %{monster}." msgid "%{name} the %{race}" msgstr "%{race}en %{name}" msgid "Captain of %{name}" msgstr "Kaptajn af %{name}" msgid "Attack" msgstr "Angreb" msgid "Defense" msgstr "Forsvar" msgid "Spell Power" msgstr "Magikraft" msgid "Knowledge" msgstr "Kundskab" msgid "Morale" msgstr "Moral" msgid "Luck" msgstr "Held" msgid "Spell Points" msgstr "Mana" msgid "Hero's Options" msgstr "Helts mulige træk" msgid "Cast Spell" msgstr "Kast magi" msgid "Retreat" msgstr "Flygt" msgid "Surrender" msgstr "Overgivelse" msgid "Cancel" msgstr "Afbryd" msgid "Hero Screen" msgstr "Helteskærm" msgid "Captain's Options" msgstr "Kaptajns mulige træk" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Kast en magisk besværgelse. Du mÃ¥ kun kaste én magi per kamprunde. Runden " "nulstilles nÃ¥r alle væsener har taget et træk." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Lad din helt flygte og dine væsener lades i stikken. Det kan blive muligt at " "rekruttere din helt igen, men helten vil, igen, kun have en begynderstyrke." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "At overgive sig koster guld. Men hvis du betaler løsesummen, vil helten og " "alle hans eller hendes overlevende skabninger være tilgængelige for " "rekruttering igen. Omkostningerne ved overgivelse er halvdelen af de samlede " "omkostninger for de ikke-midlertidige tropper, der er tilbage i hæren." msgid "Open Hero Screen to view full information about the hero." msgstr "Ã…bn helteskærm for at se fuld information om helten." msgid "Return to the battle." msgstr "Vend tilbage til kampen." msgid "Not enough gold (%{gold})" msgstr "Ikke nok guld (%{gold})" msgid "%{name} states:" msgstr "%{name} erklærer:" msgid "Captain of %{name} states:" msgstr "Kaptajnen af %{name} erklærer:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Jeg modtager gerne din overgivelse og giver Dem og Deres tropper fri lejde " "til en pris pÃ¥ %{price} guldstykker.\"" msgid "View %{monster} info" msgstr "Se info om %{monster}" msgid "Fly %{monster} here" msgstr "Flyv %{monster} hertil" msgid "Move %{monster} here" msgstr "Flyt %{monster} hertil" msgid "Shoot %{monster}" msgstr "Skyd %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 skud tilbage)" msgstr[1] "(%{count} skud tilbage)" msgid "Attack %{monster}" msgstr "Angrib %{monster}" msgid "Turn %{turn}" msgstr "Runde %{turn}" msgid "Teleport here" msgstr "Teleporter hertil" msgid "Invalid teleport destination" msgstr "Ugyldig teleportationsmÃ¥l" msgid "Cast %{spell} on %{monster}" msgstr "Kast %{spell} pÃ¥ %{monster}" msgid "Cast %{spell}" msgstr "Kast %{spell}" msgid "Select spell target" msgstr "Vælg magiens mÃ¥l" msgid "View Ballista info" msgstr "Se Ballistens info" msgid "Ballista" msgstr "Ballist" #, fuzzy msgid "Automatic combat modes" msgstr "Autokamp" #, fuzzy msgid "Automatic Combat Modes" msgstr "Autokamp" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Tilpas systemindstillinger" msgid "Allows you to customize the combat screen." msgstr "Tillader dig tilpasning af Kampskærmen." msgid "System Options" msgstr "Systemindstillinger" msgid "Skip this unit" msgstr "Skip denne enhed" msgid "Skip" msgstr "Skip" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Skipper nuværende enheds tur. Denne enhed slutter sin tur og kan intet gøre " "før sin tur i næste runde." msgid "View Captain's options" msgstr "Vis kaptajns mulige træk" msgid "View Hero's options" msgstr "Vis helts mulige træk" msgid "View opposing Captain" msgstr "Vis modstanders kaptajn" msgid "View opposing Hero" msgstr "Vis modstanders helt" msgid "Hide logs" msgstr "Skjul log" msgid "Show logs" msgstr "Vis log" msgid "Message Bar" msgstr "Beskedlinje" msgid "Shows the results of individual monster's actions." msgstr "Viser resultater for individuelle monstres handlinger." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Er du sikker pÃ¥, at du vil aktivere autokamp?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Er du sikker pÃ¥, at du vil færdiggøre denne kamp automatisk?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Tillader computeren at udkæmpe kampen for dig." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Autokamp" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Autokamp" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} skipper sin tur." msgstr[1] "%{name} skipper deres tur." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} giver %{damage} i skade." msgstr[1] "%{attacker} giver %{damage} i skade." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 væsen omkommer." msgstr[1] "%{count} væsener omkommer." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} omkommer." msgstr[1] "%{count} %{defender} omkommer." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 sjæl blev indsamlet" msgstr[1] "%{count} sjæle blev indsamlet." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} blev genoplivet." msgstr[1] "%{count} %{unit} blev genoplivet." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Flyttede %{monster}: fra [%{src}] til [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "Troppen med %{name} modstod magien!" msgstr[1] "Troppen med %{name} modstod magien!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} kaster %{spell} pÃ¥ %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} kaster %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} giver %{damage} i skade til én udød enhed." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} giver %{damage} i skade til alle udøde enheder." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} giver %{damage} i skade, %{count} væsener omkommer." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} giver %{damage} i skade." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} giver %{damage} i skade pÃ¥ én levende enhed." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} giver %{damage} i skade til alle levende enheder." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Angrebet af %{attacker} blænder troppen med %{target}!" msgstr[1] "Angrebet af %{attacker} blænder troppen med %{target}!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "%{attacker}ens stirrende blik forvandler %{target} til sten!" msgstr[1] "%{attacker}ernes stirrende blik forvandler %{target} til sten!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "" "En forbandelse kastes over troppen med %{target} forÃ¥rsaget af troppen med " "%{attacker}!" msgstr[1] "" "En forbandelse kastes over troppen med %{target} forÃ¥rsaget af troppen med " "%{attacker}!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "Enheden %{target} paralyseres af troppen med %{attacker}!" msgstr[1] "Enheden %{target} paralyseres af troppen med %{attacker}!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" "Troppen med %{attacker} fordriver alle positive besværgelser fra troppen med " "%{target}!" msgstr[1] "" "Troppen med %{attacker} fordriver alle positive besværgelser fra troppen med " "%{target}!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "" "Troppen med %{attacker} kaster besværgelsen %{spell} pÃ¥ troppen med " "%{target}!" msgstr[1] "" "Troppen med %{attacker} kaster besværgelsen %{spell} pÃ¥ troppen med " "%{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Sort uheld sænker sig over troppen med %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "Held og lykke skinner pÃ¥ troppen med %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Høj moral gør det muligt for troppen med %{monster} at angribe igen." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Lav moral vækker frysende panik i troppen med %{monster}." msgid "%{tower} does %{damage} damage." msgstr "Borgens %{tower} giver %{damage} i skade." msgid "The mirror image is created." msgstr "Spejlbilledet er skabt." msgid "The mirror image is destroyed!" msgstr "Spejlbilledet er ødelagt!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Er du sikker pÃ¥, du vil afbryde autokamp-tilstand?" msgid "Error" msgstr "Fejl" msgid "No spells to cast." msgstr "Ingen magi at kaste." msgid "Are you sure you want to retreat?" msgstr "Er du sikker pÃ¥, at du vil flygte?" msgid "Retreat disabled" msgstr "Flugt slÃ¥et fra" msgid "Surrender disabled" msgstr "Overgivelse slÃ¥et fra" msgid "Damage: %{max}" msgstr "Skade: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Skade: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Dræber: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Dræber: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Med sit ørneblik observerer %{name} magien %{spell} og lærer den selv at " "kende." msgid "Human" msgstr "Menneske" msgid "AI" msgstr "AI" msgid "Start" msgstr "Genstart" msgid "Start the battle." msgstr "Start kampen." msgid "Exit" msgstr "GÃ¥" msgid "Reset" msgstr "Nulstil" msgid "Reset to default settings." msgstr "Nulstil til standardindstillinger" msgid "Please select another hero." msgstr "Vælg venligst en anden helt." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} vs %{race2} %{name2}" msgid "Monsters" msgstr "Væsener" msgid "N/A" msgstr "I/T" msgid "Left Turret" msgstr "Venstre tÃ¥rn" msgid "Right Turret" msgstr "Højre tÃ¥rn" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "Borgens %{name} skyder med en styrke af %{count} bueskyttere" msgid "each with a +%{attack} bonus to their attack skill." msgstr "hver med en +%{attack} bonus til deres angrebsevne." msgid "The %{name} is destroyed." msgstr "Borgens %{name} er ødelagt." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} rejser sig fra de døde!" msgstr[1] "%{count} %{name} rejser sig fra de døde!" msgid "Dwarven Alliance" msgstr "Dværgalliance" msgid "Sorceress Guild" msgstr "Hekselaug" msgid "Necromancer Guild" msgstr "Nekromantikerlaug" msgid "Ogre Alliance" msgstr "Jættealliance" msgid "Dwarfbane" msgstr "Dværgsmorder" msgid "Dragon Alliance" msgstr "Dragealliance" msgid "Elven Alliance" msgstr "Elveralliance" msgid "Kraeger defeated" msgstr "Kraeger besejret" msgid "Wayward Son" msgstr "EgenrÃ¥dig Søn" msgid "Uncle Ivan" msgstr "Onkel Ivan" msgid "Annexation" msgstr "Anneksering" msgid "Force of Arms" msgstr "VÃ¥benstyrke" msgid "Save the Dwarves" msgstr "Red dværgene" msgid "Carator Mines" msgstr "Karatorminer" msgid "Turning Point" msgstr "Vendepunkt" msgid "scenarioName|Defender" msgstr "Forsvarer" msgid "Corlagon's Defense" msgstr "Korlagons Forsvar" msgid "The Crown" msgstr "Kronen" msgid "The Gauntlet" msgstr "Kapløbet" msgid "Betrayal" msgstr "Forræderi" msgid "Final Justice" msgstr "Endelige Retfærdighed" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland har brug for dig til at besejre herrerne nær hans borg, for at " "begynde sin oprørskrig mod sin bror. De er ikke allierede med hinanden. SÃ¥ " "de vil bruge det meste af deres tid pÃ¥, at bekæmpe hinanden. \n" "\n" "Sejren er din, nÃ¥r du har indtaget alle deres borge og besejret alle deres " "helte." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "De lokale herrer nægter at sværge troskab til Roland, og mÃ¥ undertrykkes. De " "er velhavende og magtfulde, sÃ¥ vær forberedt pÃ¥ en hÃ¥rd kamp. Indtag alle " "fjendens borge for at vinde." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Din opgave er at forsvare dværgene mod Archibalds styrker. Overtag alle " "fjendens borge og byer for at vinde, men undgÃ¥ at miste alle dine dværg-" "byer, for sÃ¥ vinder fjenden." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Du vil møde fire allierede fjender i en ligetil kamp om resurser og skatte. " "For at sejre, skal du erobre alle fjendens borge." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Dine fjender er allierede mod dig og starter tæt pÃ¥, sÃ¥ vær klar til at " "komme ud og kæmpe. For at vinde skal du eje alle fire borge i denne lille " "dal." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Norastons hekselaug har anmodet om Rolands hjælp mod et angreb fra " "Archibalds allierede. For at vinde skal du indtage alle fjendens borge. \n" "\n" "Du taber dette scenarie, hvis du mister Noraston (Tip: Der er en fjendtlig " "borg pÃ¥ en ø i havet.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Saml sÃ¥ stor en hær som muligt og indtag fjendens borg. Du er kun oppe imod " "én fjende. Men du skal rejse langt, for at komme til fjendens borg. Alle " "tropper, du har i din hær i slutningen af dette scenarie, vil være med dig i " "det sidste scenarie. Du taber dette scenarie, hvis du ikke indtager borgen " "inden for 8 uger." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Find kronen før Archibalds helte finder den. Roland skal bruge kronen til " "det sidste slag mod Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Tre allierede fjender stÃ¥r foran dig og sejren, inklusive Fyrst Korlagon. " "Roland er i en borg mod nordvest, og du vil tabe, hvis han falder for " "fjenden. Husk, at fange Fyrst Korlagon vil sikre, at han ikke vil kæmpe mod " "dig i det endelige scenarie." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Dette er det sidste slag. BÃ¥de du og din fjende er bevæbnet til tænderne, og " "alle er allierede imod dig. For at afslutte krigen skal du fange Archibald!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Ved at skifte side, kommer du til at starte med tre borge mod fjendens ene. " "Dette slag vil blive det letteste du vil møde resten af krigen... Din " "forræder." msgid "Barbarian Wars" msgstr "Barbarkrigene" msgid "First Blood" msgstr "Første Blodsudgydelse" msgid "Necromancers" msgstr "Nekromantikere" msgid "Slay the Dwarves" msgstr "Dræb dværgene" msgid "Country Lords" msgstr "Landsherrer" msgid "Dragon Master" msgstr "Dragemester" msgid "Rebellion" msgstr "Oprør" msgid "Apocalypse" msgstr "Dommedag" msgid "Greater Glory" msgstr "Større Hæder" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Kong Archibald kræver, at du besejrer de tre fjender i denne region. De er " "ikke allierede med hinanden. SÃ¥ de vil bruge det meste af deres energi pÃ¥, " "at bekæmpe hinanden. Du vinder, nÃ¥r du ejer alle fjenders borge og der ikke " "er flere helte tilbage at bekæmpe." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Du skal forene nordens barbarstammer, ved at erobre dem. Som i det forrige " "scenarie er fjenderne ikke allierede imod dig, men de har flere ressourcer " "til deres rÃ¥dighed. Du vinder, nÃ¥r du ejer alle fjendens borge, og der ikke " "er flere helte tilbage at kæmpe." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Gode magikere har taget nekromantikerens borg. Du skal genindtage den, for " "at opnÃ¥ sejr. Husk, at selvom du starter med en stærk hær, har du ingen " "borg.\n" "Du taber dette scenarie, hvis ikke du indtager en by inden 7 dage er gÃ¥et. " "(Tip: Mod sydøst ligger den nærmeste borg.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Dværgene skal erobres, før de kan blande sig i kong Archibalds planer. " "Rolands styrker har mere end én helt og mange byer til at starte med, sÃ¥ vær " "klar til angreb fra flere retninger. Du skal erobre alle fjendens borge og " "byer for at hævde sejren." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Du skal nedkæmpe et bondeoprør ledet af Rolands styrker. Alle er allierede " "imod dig, men du har Fyrst Korlagon, en erfaren helt, til at hjælpe dig. " "Indtag alle fjendens borge, for at vinde." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "I dette scenarie er to fjender allierede imod dig. Begge er godt bevæbnede, " "og de søger at fordrive dig fra deres ø. UndgÃ¥ dem og indtag Dragebyen, for " "at vinde." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Du er blevet beordret til at besejre landsherrerne, der har svoret at tjene " "Roland. Alle fjendens borge er forenet mod dig. Da du starter uden en borg, " "skal du skynde dig at indtage en inden ugen er omme. Indtag alle fjendens " "borge, for at sejre." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Find Kronen før Rolands helte finder den. Archibald skal bruge Kronen til " "det sidste slag mod Roland." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Dette er det sidste slag. BÃ¥de du og dine fjender er bevæbnet til tænderne, " "og alle er allierede imod dig. Fang Roland for at vinde krigen.\n" "\n" "Du taber dette scenarie, hvis du mister Archibald i kampens hede!" msgid "Arrow's Flight" msgstr "Pilens Flugt" msgid "Island of Chaos" msgstr "Kaosøen" msgid "The Abyss" msgstr "Dybet" msgid "Uprising" msgstr "Opstand" msgid "Aurora Borealis" msgstr "Aurora Borealis" msgid "Betrayal's End" msgstr "Forræderiets Ende" msgid "Corruption's Heart" msgstr "Fordærvelsens Hjerte" msgid "The Giant's Pass" msgstr "Kæmpens Pas" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Underlæg de uregerlige lokale herrer, for at kunne faciliterer imperiets " "operationer i denne region." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Eliminér alle modstandere i dette omrÃ¥de. SÃ¥ den første del af artefaktet " "bliver dit." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Heksene mod nordøst gør oprør! Til gavn for imperiet skal du kvase deres " "svage opstand pÃ¥ din vej til bjergene." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Efter at have forberedt din ankomst, har Kraeger sørget for en styrke af " "nekromantikere, for at forpurre din mission, som er at indtage borgen " "Scabsdale. Du taber dette scenarie, hvis du ikke nÃ¥r det inden den første " "dag i den tredje uge. Ellers bliver nekromantikerne for stærke for dig." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Den barbariske despot i dette omrÃ¥de er endnu uvidende om din " "tilstedeværelse. Byg hurtigt dine styrker op, før du bliver opdaget og " "angrebet! Du skal sikre regionen, ved at undertrykke alle fjendens styrker." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Imperiet er svagt i denne region. Du vil ikke være i stand til fuldstændigt " "at undertrykke alle styrker i dette omrÃ¥de. SÃ¥ tag hvad du kan, før " "repressalierne rammer. Husk, dit sande mÃ¥l er at gøre krav pÃ¥ Andurans Hjelm." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Til gavn for imperiet, skal du eliminere Kraeger." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Endelig har du muligheden, og faciliteterne, til at befri imperiet for " "nekromantikerens ondskab. Udryd dem fuldstændigt, og du vil for eftertiden " "blive besunget som helt." msgid "Border Towns" msgstr "Grænsebyer" msgid "Conquer and Unify" msgstr "Erobr og foren" msgid "Crazy Uncle Ivan" msgstr "Skøre Onkel Ivan" msgid "The Wayward Son" msgstr "Den EgenrÃ¥dige Søn" msgid "Ivory Gates" msgstr "Ivory Gates" msgid "The Elven Lands" msgstr "Elverrigerne" msgid "The Epic Battle" msgstr "Det Episke Slag" msgid "The Southern War" msgstr "Sydkrigen" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Erobr og foren alle fjendens stammer. \n" "\n" "Du taber dette scenarie, hvis du mister helten Jarkonas, forfaderen til alle " "efterkommere." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Det rivaliserende kongerige, Harondale, angriber svage byer tæt ved din " "grænse! Vind styrken tilbage, ovenpÃ¥ deres første angreb, og knus dem sÃ¥ " "fuldstændigt!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Find din egenrÃ¥dige søn, Joseph, der rygtes at bo ude i ødemarkerne.\n" "\n" "Hvis du ikke gør det inden første dag i den tredje mÃ¥ned, hjælper det ikke " "din familie." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Red din skøre onkel Ivan.\n" "\n" "Hvis du ikke finder ham inden den første dag i den fjerde mÃ¥ned, vil " "eftersøgningen have været forgæves for dit rige." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Knus barbarerne, der angriber dit riges sydlige grænse! Genopbyg dine faldne " "byer, og invadér derefter jungleriget. Efterlad ingen overlevende." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "" "Genindtag borgen kaldet Ivory Gates, som er faldet pÃ¥ grund af forræderi." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Vind elvernes gunst. De vil ikke tillade, at deres træer bliver fældet. SÃ¥ " "vi sender dig træ hver anden uge. \n" "\n" "Du taber dette scenarie, hvis du ikke fuldfører din mission inden den første " "dag i den syvende mÃ¥ned. Ellers vil Elverrigerne helt sikkert falde." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Dette er det sidste slag mod dit rivaliserende kongerige Harondale. Eliminér " "alle.\n" "\n" "Du taber dette scenarie, hvis du mister helten Jarkonas VI." msgid "Fount of Wizardry" msgstr "Trolddomskilden" msgid "Power's End" msgstr "Magtens Ende" msgid "The Eternal Scrolls" msgstr "De Evige Skriftruller" msgid "The Shrouded Isles" msgstr "TÃ¥geøerne" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Din mission er at overvinde de genstridige troldmænd pÃ¥ TÃ¥geøerne. " "Gennemførelsen af denne mission vil styrke dine chancer i kampen mod dine " "rivaler." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Placeringen af det store bibliotek er blevet opdaget! Du skal rejse hen til " "det og genindtage byen kaldet Chronos, hvori det ligger." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Find Negationskuglen, som siges at være begravet i dette land. Der er spor " "indskrevet pÃ¥ stenobelisker, som vil hjælpe med at føre dig til din " "belønning.\n" "\n" "Hvis du ikke finder kuglen før den første dag i den sjette mÃ¥ned, vil dine " "rivaler helt sikkert være nÃ¥et til Trolddomskilden før dig." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Du skal tage kontrol over magiens borg, hvor Trolddomskilden ligger. Gør " "dette, og din sejr vil være suveræn." msgid "Blood is Thicker" msgstr "Blod er Tykkere" msgid "King and Country" msgstr "Land og Rige" msgid "Pirate Isles" msgstr "Piratøerne" msgid "Stranded" msgstr "Strandet" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Indtag byen pÃ¥ øen ud for den sydøstlige kyst, for at bygge en bÃ¥d og rejse " "tilbage mod fastlandet. \n" "\n" "Du taber dette scenarie, hvis du mister helten Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Find og besejr Martine, piratlederen, som bor i byen Pirate Cove. \n" "\n" "Du taber dette scenarie, hvis du mister Gallavant. For sÃ¥ vil din mission " "være forbi." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Eliminér alle de andre kræfter, der modsætter sig Lord Alberons styre. \n" "\n" "Du taber dette scenarie, hvis du mister Gallavant." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Omstyrt Lord Alberons forankrede monarki, og kræv hele landet i dit navn. \n" "\n" "Du taber dette scenarie, hvis du mister Gallavant." msgid " bane" msgstr " bane" msgid " alliance" msgstr " alliance" msgid "Carry-over forces" msgstr "Overførselsstyrker" msgid " bonus" msgstr " bonus" msgid " defeated" msgstr " død" msgid " will always run away from your army." msgstr " vil altid flygte i rædsel for din hær." msgid " will be willing to join your army." msgstr " vil velvilligt tilslutte sig din hær." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" "Artefaktet \"%{artifact}\" viderebringes til et af felttogets senere " "scenarier." msgid "The army will be carried over in the campaign." msgstr "Hæren viderebringes til et af felttogets senere scenarier." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Kongeriget vil have +%{count} %{resource} om dagen." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" "Besværgelsen \"%{spell}\" viderebringes til et af felttogets senere " "scenarier." msgid "%{hero} can be hired during scenarios." msgstr "Helten %{hero} kan rekrutteres i løbet af scenarier." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" "Helten %{hero} er blevet besejret og viser sig ikke i efterfølgende " "scenarier." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "Dværgene genkender deres allierede og slutter sig gerne til din hær." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Jætterne genkender dig som dværgbanen og kommer trampende over, for at " "slutte sig til dig." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Dragerne, snerrende og knurrende, er enige om at følge dig, deres " "'allierede'." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Da du nærmer dig gruppen af elvere, pÃ¥kalder elverlederen deres alles " "opmærksomhed. Han rÃ¥ber til dem: \"Hvem af jer er modig nok til at slutte " "sig til denne, vores frygtløse allieret?\" Gruppen bryder ud i jubel, mens " "de løber for at slutte sig til dine rækker." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Dværgene hylder dig, \"Enhver ven af Roland er en ven af os. Du mÃ¥ gerne " "passere.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Jætter giver dig et grynt af genkendelse, \"Archibalds allierede kan passere." "\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Dragerne ser dig og rÃ¥ber. \"Vores alliance med Archibald tvinger os til at " "slutte os til dig. Desværre har du ikke plads. En skam!\" De spreder sig " "hurtigt." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Elverne stÃ¥r vagtsomme, mens du nærmer dig. Deres leder kalder pÃ¥ dig og " "siger: \"Lad os ikke hæmme din fremgang, min allieret! Fortsæt fremad, og mÃ¥ " "sejren blive din.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Dværgbanen!!!!, løb for dit liv.\"" msgid "campaignBonus|Animate Dead" msgstr "Dødebesjæling" msgid "campaignBonus|Chain Lightning" msgstr "Lynkæde" msgid "campaignBonus|Fireblast" msgstr "Flammebrag" msgid "campaignBonus|Mass Curse" msgstr "Masse-forbandelse" msgid "campaignBonus|Mass Haste" msgstr "Masse-forhastning" msgid "campaignBonus|Mirror Image" msgstr "Spejlbillede" msgid "campaignBonus|Resurrect" msgstr "Genoplivelse" msgid "campaignBonus|Steelskin" msgstr "StÃ¥lhud" msgid "campaignBonus|Summon Earth" msgstr "Hidkald jord-elem." msgid "campaignBonus|View Heroes" msgstr "Vis helte" msgid "campaignBonus|Ballista" msgstr "Ballisten" msgid "campaignBonus|Black Pearl" msgstr "Den sorte perle" msgid "campaignBonus|Caster's Bracelet" msgstr "Magisk armbÃ¥nd" msgid "campaignBonus|Defender Helm" msgstr "Forsvarshjelm" msgid "campaignBonus|Breastplate" msgstr "Brystpladen" msgid "campaignBonus|Dragon Sword" msgstr "Dragesværdet" msgid "campaignBonus|Fizbin Medal" msgstr "Fizbin-medalje" msgid "campaignBonus|Foremost Scroll" msgstr "Magisk skriftrulle" msgid "campaignBonus|Gauntlets" msgstr "Handsker" msgid "campaignBonus|Hideous Mask" msgstr "Hæslig maske" msgid "campaignBonus|Mage's Ring" msgstr "Troldmandsring" msgid "campaignBonus|Major Scroll" msgstr "Magisk skriftrulle" msgid "campaignBonus|Medal of Honor" msgstr "Æresmedalje" msgid "campaignBonus|Medal of Valor" msgstr "Tapperhedsmedalje" msgid "campaignBonus|Minor Scroll" msgstr "Magisk skriftrulle" msgid "campaignBonus|Nomad Boots" msgstr "Syvmilestøvler" msgid "campaignBonus|Power Axe" msgstr "Kraftøksen" msgid "campaignBonus|Spiked Shield" msgstr "Pigskjoldet" msgid "campaignBonus|Stealth Shield" msgstr "Skalkeskjold" msgid "campaignBonus|Tax Lien" msgstr "Pantebrevet" msgid "campaignBonus|Thunder Mace" msgstr "Morgenstjerne" msgid "campaignBonus|Traveler's Boots" msgstr "Syvmilestøvler" msgid "campaignBonus|White Pearl" msgstr "Den hvide perle" msgid "campaignBonus|Basic Archery" msgstr "Begynder skydning" msgid "campaignBonus|Advanced Archery" msgstr "Øvet skydning" msgid "campaignBonus|Expert Archery" msgstr "Ekspert skydning" msgid "campaignBonus|Basic Ballistics" msgstr "Beg. ballistik" msgid "campaignBonus|Advanced Ballistics" msgstr "Øvet ballistik" msgid "campaignBonus|Expert Ballistics" msgstr "Ekspert ballistik" msgid "campaignBonus|Basic Diplomacy" msgstr "Beg. diplomati" msgid "campaignBonus|Advanced Diplomacy" msgstr "Øvet diplomati" msgid "campaignBonus|Expert Diplomacy" msgstr "Ekspert diplomati" msgid "campaignBonus|Basic Eagle Eye" msgstr "Begynder ørneblik" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Øvet ørneblik" msgid "campaignBonus|Expert Eagle Eye" msgstr "Ekspert ørneblik" msgid "campaignBonus|Basic Estates" msgstr "Begynder adelskab" msgid "campaignBonus|Advanced Estates" msgstr "Øvet adelskab" msgid "campaignBonus|Expert Estates" msgstr "Ekspert adelskab" msgid "campaignBonus|Basic Leadership" msgstr "Beg. lederskab" msgid "campaignBonus|Advanced Leadership" msgstr "Øvet lederskab" msgid "campaignBonus|Expert Leadership" msgstr "Ekspert lederskab" msgid "campaignBonus|Basic Logistics" msgstr "Begynder logistik" msgid "campaignBonus|Advanced Logistics" msgstr "Øvet logistik" msgid "campaignBonus|Expert Logistics" msgstr "Ekspert logistik" msgid "campaignBonus|Basic Luck" msgstr "Begynder held" msgid "campaignBonus|Advanced Luck" msgstr "Øvet held" msgid "campaignBonus|Expert Luck" msgstr "Ekspert held" msgid "campaignBonus|Basic Mysticism" msgstr "Beg. mysticisme" msgid "campaignBonus|Advanced Mysticism" msgstr "Øvet mysticisme" msgid "campaignBonus|Expert Mysticism" msgstr "Eks. mysticisme" msgid "campaignBonus|Basic Navigation" msgstr "Beg. navigation" msgid "campaignBonus|Advanced Navigation" msgstr "Øvet navigation" msgid "campaignBonus|Expert Navigation" msgstr "Eks. navigation" msgid "campaignBonus|Basic Necromancy" msgstr "Beg. nekromanti" msgid "campaignBonus|Advanced Necromancy" msgstr "Øvet nekromanti" msgid "campaignBonus|Expert Necromancy" msgstr "Eks. nekromanti" msgid "campaignBonus|Basic Pathfinding" msgstr "Beg. stifinding" msgid "campaignBonus|Advanced Pathfinding" msgstr "Øvet stifinding" msgid "campaignBonus|Expert Pathfinding" msgstr "Eks. stifinding" msgid "campaignBonus|Basic Scouting" msgstr "Beg. udspejdning" msgid "campaignBonus|Advanced Scouting" msgstr "Øvet udspejdning" msgid "campaignBonus|Expert Scouting" msgstr "Eks. udspejdning" msgid "campaignBonus|Basic Wisdom" msgstr "Begynder visdom" msgid "campaignBonus|Advanced Wisdom" msgstr "Øvet visdom" msgid "campaignBonus|Expert Wisdom" msgstr "Ekspert visdom" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" "Din hovedhelt vil modtage artefaktet \"%{artifact}\" i starten af scenariet." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Dit kongerige vil modtage %{amount} ekstra mængder %{resource} i starten af " "scenariet." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Dit kongerige vil modtage %{amount} færre mængder %{resource} i starten af " "scenariet." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Din hovedhelt vil modtage %{count} %{monster} i starten af scenariet." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" "Din hovedhelt vil have lært besværgelsen \"%{spell}\" i starten af scenariet." msgid "The starting alignment of the scenario will be %{race}." msgstr "" "Dit kongerige har et tilhørsforhold til klassen %{race} i starten af " "scenariet." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "Din hovedhelt vil modtage yderligere %{count} point i %{skill} i starten af " "scenariet." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Hovedhelten vil have lært %{skill} i starten af scenariet." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" msgid "Price of Loyalty" msgstr "Prisen for Loyalitet" msgid "Voyage Home" msgstr "Hjemrejse" msgid "Wizard's Isle" msgstr "Troldmandsøen" msgid "Descendants" msgstr "Efterkommere" msgid "Cannot build. You have already built here today." msgstr "Byggeri umuligt. Du har allerede bygget her i dag." msgid "For this action it is necessary to build a castle first." msgstr "Til denne handling er det nødvendigt først at bygge en borg." msgid "The %{building} produces %{monster}." msgstr "%{building} frembringer %{monster}." msgid "Requires:" msgstr "Kræver:" msgid "Exit this menu without doing anything." msgstr "Forlad denne menu, uden at gøre noget." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "%{name}et kan ikke bygges, da borgen er for langt fra vand." msgid "This building has been disabled." msgstr "Denne bygning er blevet deaktiveret." msgid "Cannot afford the %{name}." msgstr "Ikke nok resurser til byggeriet af %{name}." msgid "The %{name} is already built." msgstr "Bygningen %{name} er allerede blevet bygget." msgid "Cannot build the %{name}." msgstr "Det er ikke muligt at bygge %{name}." msgid "Build %{name}." msgstr "Byg %{name}" msgid "Blackridge" msgstr "Sortekam" msgid "Hillstone" msgstr "Voldsten" msgid "Pinehurst" msgstr "Fyrenskov" msgid "Whiteshield" msgstr "Hvidskjold" msgid "Woodhaven" msgstr "Skovhaven" msgid "Blackwind" msgstr "Sortrup" msgid "Bloodreign" msgstr "Bloddum" msgid "Dragontooth" msgstr "DraggÃ¥rd" msgid "Greywind" msgstr "GrÃ¥vinde" msgid "Portsmith" msgstr "Smedehaven" msgid "Atlantium" msgstr "Atlantum" msgid "Middle Gate" msgstr "Midborg" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulkania" msgid "Baywatch" msgstr "Bugtvad" msgid "Fountainhead" msgstr "Kildspring" msgid "Vertigo" msgstr "Snurrum" msgid "Wildabar" msgstr "Vildabar" msgid "Winterkill" msgstr "Barfrost" msgid "Brindamoor" msgstr "Fakkelhede" msgid "Lakeside" msgstr "Søsted" msgid "Nightshadow" msgstr "Natskygge" msgid "Olympus" msgstr "Olympos" msgid "Sandcaster" msgstr "Sandborg" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Sabran" msgid "Algary" msgstr "Algær" msgid "Basenji" msgstr "Dingo" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "Nygry" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Stor-ege" msgid "Chandler" msgstr "Lysning" msgid "Erliquin" msgstr "Arliquin" msgid "Hampshire" msgstr "Hampdrup" msgid "Antioch" msgstr "Antiokia" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Rokskov" msgid "South Mill" msgstr "Søndermølle" msgid "Weed Patch" msgstr "Bakkestjerne" msgid "Brownston" msgstr "Brunborg" msgid "Hilltop" msgstr "Bakketop" msgid "Weddington" msgstr "Væderup" msgid "Westfork" msgstr "Vesterskille" msgid "Whittingham" msgstr "Viderup" msgid "Cathcart" msgstr "KasgÃ¥rd" msgid "Elk's Head" msgstr "Elgevir" msgid "Roscomon" msgstr "Rosenborg" msgid "Sherman" msgstr "Ulsakse" msgid "Yorksford" msgstr "Rodbæk" msgid "Blackburn" msgstr "Kulbrand" msgid "Blacksford" msgstr "Mørkbæk" msgid "Burton" msgstr "Skodby" msgid "Pig's Eye" msgstr "Svinerøje" msgid "Viper's Nest" msgstr "Bande-rede" msgid "Fenton" msgstr "Hegnby" msgid "Lankershire" msgstr "Langherred" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Tømmerhøj" msgid "Troy" msgstr "Troja" msgid "Forder Oaks" msgstr "Egebæk" msgid "Meramec" msgstr "Meramek" msgid "Quick Silver" msgstr "Kviksølver" msgid "Westmoor" msgstr "Vesthede" msgid "Willow" msgstr "Virlund" msgid "Corackston" msgstr "Coraktun" msgid "Sheltemburg" msgstr "Sheltemborg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Umuligt at rekruttere - Du har allerede en helt i denne borg." msgid "Cannot recruit - you have too many Heroes." msgstr "Umuligt at rekruttere - Du har for mange helte." msgid "Cannot afford a Hero." msgstr "Umuligt at rekruttere en helt." msgid "There is no room in the garrison for this army." msgstr "Der er ikke plads i garnisonen til denne trop." msgid "Fortifications" msgstr "Befæstninger" msgid "Farm" msgstr "Mark" msgid "Thatched Hut" msgstr "StrÃ¥tækt hytte" msgid "Archery Range" msgstr "Bueskydningsbane" msgid "Upg. Archery Range" msgstr "Opg. bueskydningsbane" msgid "Blacksmith" msgstr "Grovsmedje" msgid "Upg. Blacksmith" msgstr "Opg. grovsmedje" msgid "Armory" msgstr "VÃ¥bensmedje" msgid "Upg. Armory" msgstr "Opg. vÃ¥bensmedje" msgid "Jousting Arena" msgstr "Dystningsarena" msgid "Upg. Jousting Arena" msgstr "Opg. dystningsarena" msgid "Cathedral" msgstr "Katedral" msgid "Upg. Cathedral" msgstr "Opg. katedral" msgid "Coliseum" msgstr "Amfiteater" msgid "Garbage Heap" msgstr "Affaldsbunke" msgid "Hut" msgstr "Hytte" msgid "Stick Hut" msgstr "Pindehytte" msgid "Upg. Stick Hut" msgstr "Opg. pindehytte" msgid "Den" msgstr "Hule" # Adobe-sten er ler, som bruges til at bygge adobehuse med. De findes ogsÃ¥ i Danmark msgid "Adobe" msgstr "Adobehus" msgid "Upg. Adobe" msgstr "Opg. adobehus" msgid "Bridge" msgstr "Bro" msgid "Upg. Bridge" msgstr "Opg. bro" msgid "Pyramid" msgstr "Pyramide" msgid "Rainbow" msgstr "Regnbue" msgid "Crystal Garden" msgstr "Krystalhave" msgid "Treehouse" msgstr "Træhus" # Oversættes normalt til sommerhus. Men kottage er faktisk ogsÃ¥ dansk ord. msgid "Cottage" msgstr "Kottage" msgid "Upg. Cottage" msgstr "Opg. kottage" msgid "Stonehenge" msgstr "Stenkreds" msgid "Upg. Stonehenge" msgstr "Opg. stenkreds" msgid "Fenced Meadow" msgstr "Indhegnet eng" msgid "sorceress|Red Tower" msgstr "IldtÃ¥rn" msgid "Dungeon" msgstr "Fangehul" msgid "Waterfall" msgstr "Vandfald" msgid "Cave" msgstr "Grotte" msgid "Crypt" msgstr "Krypt" msgid "Nest" msgstr "Rede" msgid "Maze" msgstr "Labyrint" msgid "Upg. Maze" msgstr "Opg. labyrint" msgid "Swamp" msgstr "Sump" msgid "Green Tower" msgstr "Grønt tÃ¥rn" msgid "warlock|Red Tower" msgstr "Rødt tÃ¥rn" msgid "Black Tower" msgstr "Sort tÃ¥rn" msgid "Library" msgstr "Bibliotek" msgid "Orchard" msgstr "Frugthave" msgid "Habitat" msgstr "Habitat" msgid "Pen" msgstr "Svinesti" msgid "Foundry" msgstr "Støberi" msgid "Upg. Foundry" msgstr "Opg. støberi" msgid "Cliff Nest" msgstr "Klipperede" msgid "Ivory Tower" msgstr "ElfenbenstÃ¥rn" msgid "Upg. Ivory Tower" msgstr "Opg. elfenbenstÃ¥rn" msgid "Cloud Castle" msgstr "Skyslot" msgid "Upg. Cloud Castle" msgstr "Opg. skyslot" msgid "Storm" msgstr "Storm" msgid "Skull Pile" msgstr "Kraniebunke" msgid "Excavation" msgstr "Udgravning" msgid "Graveyard" msgstr "KirkegÃ¥rd" msgid "Upg. Graveyard" msgstr "Opg. kirkegÃ¥rd" msgid "Upg. Pyramid" msgstr "Opg. pyramide" msgid "Mansion" msgstr "Palæ" msgid "Upg. Mansion" msgstr "Opg. palæ" msgid "Mausoleum" msgstr "Mausoleum" msgid "Upg. Mausoleum" msgstr "Opg. mausoleum" msgid "Laboratory" msgstr "Laboratorium" msgid "Shrine" msgstr "Helligdom" msgid "Special" msgstr "Specialbygning" msgid "Horde Building" msgstr "Hordebygning" msgid "Dwelling 1" msgstr "Bosted 1" msgid "Dwelling 2" msgstr "Bosted 2" msgid "Upg. Dwelling 2" msgstr "Opg. bosted 2" msgid "Dwelling 3" msgstr "Bosted 3" msgid "Upg. Dwelling 3" msgstr "Opg. bosted 3" msgid "Dwelling 4" msgstr "Bosted 4" msgid "Upg. Dwelling 4" msgstr "Opg. bosted 4" msgid "Dwelling 5" msgstr "Bosted 5" msgid "Upg. Dwelling 5" msgstr "Opg. Bosted 5" msgid "Dwelling 6" msgstr "Bosted 6" msgid "Upg. Dwelling 6" msgstr "Opg. bosted 6" msgid "2x Upg. Dwelling 6" msgstr "2x opg. bosted 6" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Befæstningerne styrker ringmurene, sÃ¥ de kan modstÃ¥ mindst ét ekstra angreb, " "før muren væltes." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Marken øger tilvæksten af bønder med %{count} om ugen." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "I amfiteatret inspirerer gladiatorkampe de forsvarende styrkers kampgejst, " "sÃ¥ deres moral under kamp løftes med to point." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Affaldsbunken øger tilvæksten af vætter med %{count} om ugen." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Regnbuen øger de forsvarende styrkers held med 2 point." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "Krystalhaven øger tilvæksten af feer med %{count} om ugen." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Fangehullet øger byens guldindkomst med %{count} guldstykker om dagen." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Vandfaldet øger tilvæksten af kentaurer med %{count} om ugen." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Biblioteket øger antallet af besværgelser i magikerlauget med én for hvert " "plan-niveau." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Frugthaven øger tilvæksten af halvlange med %{count} om ugen." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" "Stormen øger en forsvarende besværgers magikraft med 2 point under kamp." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Kraniebunken øger tilvæksten af skeletter med %{count} om ugen." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "Specialbygningen giver en specifik bonus til den valgte borgtype." msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "Hordebygningen øger tilvæksten for niveau 1 væsener med 8 per uge." msgid "Thieves' Guild" msgstr "Tyvelaug" msgid "Tavern" msgstr "Kro" msgid "Shipyard" msgstr "Skibsværft" msgid "Well" msgstr "Brønd" msgid "Statue" msgstr "Statue" msgid "Marketplace" msgstr "Markedsplads" msgid "Moat" msgstr "Voldgrav" msgid "Castle" msgstr "Borg" msgid "Tent" msgstr "Telt" msgid "Captain's Quarters" msgstr "Kaptajnens kvarter" msgid "Mage Guild, Level 1" msgstr "Magikerlaug, 1. plan" msgid "Mage Guild, Level 2" msgstr "Magikerlaug, 2. plan" msgid "Mage Guild, Level 3" msgstr "Magikerlaug, 3. plan" msgid "Mage Guild, Level 4" msgstr "Magikerlaug, 4. plan" msgid "Mage Guild, Level 5" msgstr "Magikerlaug, 5. plan" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Helligdommen øger alle dine nekromantikeres nekromantik med 10 procent." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Tyvelauget skaffer informationer om hvordan andre spillere klarer sig i " "forhold til dig. Desuden udspejdes fjendtlige byer og borge ogsÃ¥. Jo flere " "Tyvelaug du har, jo flere informationer fÃ¥r du." msgid "The Tavern increases morale for troops defending the castle." msgstr "Kroen øger de forsvarende styrkers moral med to point." msgid "The Shipyard allows ships to be built." msgstr "Skibsværftet gør det muligt at bygge skibe." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Brønden øger den ugentlige tilvækst af byens bosteder med %{count}. Brønden " "gør det ogsÃ¥ muligt at fÃ¥ en oversigt over byens væsener. Du kan desuden " "hverve dem herfra." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Statuen øger byens guldindkomst med %{count} guldstykker om dagen." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "Venstre tÃ¥rn frembringer et ekstra skydetÃ¥rn, som øger ildkraft under " "belejring af borgen." msgid "The Right Turret provides extra firepower during castle combat." msgstr "" "Højre tÃ¥rn frembringer et ekstra skydetÃ¥rn, som øger ildkraft under " "belejring af borgen." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "PÃ¥ markedspladsen kan man bytte én resursetype til en anden. Du opnÃ¥r mere " "og mere fordelagtige byttehandlinger, jo flere markedspladser du har i dit " "rige." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Voldgraven forsinker angribende tropper. Enhver trop, som træder ned i " "voldgraven, ender sin tur dér. SÃ¥ længe den befinder sig her, vil den " "desuden være mere sÃ¥rbar overfor angreb." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Borgen forstærker byens forsvar mod angreb. Borgen øger desuden byens " "guldindkomst med %{count} guldstykker om dagen." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Teltet frembringer arbejdere til at bygge en borg, sÃ¥fremt de fornødne " "resurser og guld er pÃ¥ plads." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Kaptajnens kvarter frembringer en kaptajn til at assistere de forsvarende " "styrker, nÃ¥r der ikke er en helt tilstede." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Helte kan købe en magibog og lære besværgelser, nÃ¥r de besøger " "magikerlauget. Desuden fornyes heltes maksimale antal mana automatisk, hvis " "de ender deres tur stÃ¥ende i byen." msgid "Recruit %{name}" msgstr "Rekruttér %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "MÃ¥ned: %{month}, Uge: %{week}, Dag: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Din helt er nødt til at købe en magibog, før denne mÃ¥ træde ind i " "magikerlauget. Men helten har desværre ikke plads til at bære en magibog. " "Prøv at afgive én af dine artefakter til en anden helt." msgid "Click to show next town." msgstr "Klik for at se næste by." msgid "Show next town" msgstr "Se næste by" msgid "Click to show previous town." msgstr "Klik for at se forrige by." msgid "Show previous town" msgstr "Se forrige by" msgid "This town may not be upgraded to a castle." msgstr "Der kan ikke bygges en borg i denne by." msgid "Town" msgstr "By" msgid "Exit Castle" msgstr "Forlad borg" msgid "Exit Town" msgstr "Forlad by" msgid "Show Income" msgstr "Vis indkomst" msgid "View Hero" msgstr "Vis helt" msgid "The above spells are available here." msgstr "Med nok visdom kan alle disse besværgelser læres af dine helte." msgid "The spells the hero can learn have been added to their book." msgstr "De besværgelser, den besøgende helt kan lære, er nu i magibogen." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "En generøs mængde drikkepenge fÃ¥r krokarlen til at dele dette rygte:" msgid "Recruit Hero" msgstr "Rekruttér helt" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} er en level %{value} %{race} " msgid "with %{count} artifacts." msgstr "med %{count} artefakter." msgid "with 1 artifact." msgstr "med 1 artefakt." msgid "without artifacts." msgstr "uden artefakter." msgid "Recruit %{name} the %{race}" msgstr "Rekruttér %{race}en %{name}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Spredt' kampformation spreder borgens tropper, fra top til bund pÃ¥ " "slagmarken, med mindst én tom plads mellem hver enhed pÃ¥ borgens side af " "slagmarken." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "'Gruppe'-formation samler borgens tropper i midten af borgens side af " "slagmarken." msgid "Spread Formation" msgstr "Spredt formation" msgid "Grouped Formation" msgstr "Gruppeformation" msgid "Click to show the next town." msgstr "Klik for at se næste by." msgid "Click to show the previous town." msgstr "Klik for at se forrige by." msgid "Set garrison combat formation to 'Spread'" msgstr "" "Indstil garnisonen til at stÃ¥ opstille sig i 'spredt' formation under kamp" msgid "Set garrison combat formation to 'Grouped'" msgstr "" "Indstil garnisonen til at stÃ¥ opstille sig i 'gruppe'-formation under kamp" msgid "Exit Castle Options" msgstr "Forlad borg-vindue" msgid "Castle Options" msgstr "Borg-vindue" msgid "Not enough resources to recruit creatures." msgstr "Der er ikke nok resurser til at rekruttere væsener for." msgid "You are unable to recruit at this time, your ranks are full." msgstr "" "Du kan ikke rekruttere nye væsener til din hær, sÃ¥ længe dine rækker er " "fulde." msgid "No creatures available for purchase." msgstr "Der er i øjeblikket intet væsen at rekruttere." msgid "Recruit Creatures" msgstr "Rekruttér væsener" msgid "Hire all creatures in the town." msgstr "Hyr alle byens tilgængelige væsener." msgid "Max" msgstr "Maks" msgid "Available" msgstr "Tilgængelig" msgid "Town Population Information and Statistics" msgstr "Informationer og tal om byens indbyggere" msgid "Damage" msgstr "Skade" msgid "HP" msgstr "Liv" msgid "Growth" msgstr "Vækst" msgid "week" msgstr "uge" msgid "View World" msgstr "Vis verden" msgid "View the entire world." msgstr "Vis hele verdenen." msgid "Puzzle" msgstr "Puslespil" msgid "View the obelisk puzzle." msgstr "Vis obeliskens puslespil." msgid "Scenario Information" msgstr "Kortbeskrivelse" msgid "View information on the scenario you are currently playing." msgstr "Vis information om det scenarie, du er i gang med at spille." msgid "Dig for the Ultimate Artifact." msgstr "Grav efter Det Ultimative Artefakt." msgid "Digging" msgstr "Gravning" msgid "Arena" msgstr "Arena" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Du gÃ¥r ind i arenaen og stÃ¥r over for en flok glubske løver. Publikums vilde " "jubel lyder, idet du snildt besejrer løverne. Imponeret over dine evner, er " "den gamle gladiatortræner villig til at træne dig i en færdighed - Du vælger " "selv hvilken." msgid "Attack Skill" msgstr "Angreb" msgid "Defense Skill" msgstr "Forsvar" msgid "Shots" msgstr "Skud" msgid "Shots Left" msgstr "Skudreserve" msgid "Hit Points" msgstr "Liv" msgid "Hit Points Left" msgstr "Resterende liv" msgid "You can't afford to upgrade your troops!" msgstr "Du har ikke rÃ¥d til at opgradere dine tropper!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Dine tropper kan opgraderes, men det vil koste dig dyrt. Vil du opgradere " "dem alligevel?" msgid "Are you sure you want to dismiss this army?" msgstr "Er du sikker pÃ¥ du vil bortvise denne trop?" msgid "Upgrade" msgstr "Opgradér" msgid "Upgrade your troops." msgstr "Opgradér dine tropper." msgid "Dismiss" msgstr "Bortvis" msgid "Dismiss this army." msgstr "Bortvis denne hær." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "En gruppe %{monster} med drømme om magt og ære ønsker at forene sig med din " "hær.\n" "Godtager du disse betingelser?" msgid "Followers" msgstr "Følgere" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "Et enkelt medlem af %{monster}-hæren lader sig overtale af din diplomatiske " "tunge og vil gerne forene sig med din hær, for en sum af %{gold} " "guldstykker.\n" "Godtager du disse betingelser?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Disse væsener lader sig overtale af din diplomatiske\n" "tunge. De giver dig et tilbud:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "Ud af %{total} %{monster} er %{offer} af dem villige til at forene sig med " "din hær, mens de resterende vil lade dig være i fred, til en sum af %{gold} " "guldstykker.\n" "\n" "Godtager du disse betingelser?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Alle %{offer} %{monster} er villige til at forene sig med din hær til en " "pris af %{gold} guldstykker.\n" "Godtager du disse betingelser?" msgid "(Rate: %{percent})" msgstr "(Grad: %{percent})" msgid "off" msgstr "fra" msgid "Music" msgstr "Musik" msgid "Effects" msgstr "Effekter" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Udvidelse" msgid "External" msgstr "Ekstern" msgid "Music Type" msgstr "Musiktype" msgid "3D Audio" msgstr "3D Lyd" msgid "Toggle ambient music level." msgstr "Indstil niveau for omgivelseslyde." msgid "Toggle foreground sounds level." msgstr "Indstil niveau for forgrundslyde." msgid "Change the type of music." msgstr "Ændr musikstil." msgid "Toggle the 3D effect of foreground sounds." msgstr "Skift 3D-effekter for forgrundslyde." msgid "Build a new ship:" msgstr "Byg et nyt skib:" msgid "Resource cost:" msgstr "Resurseomkostninger:" msgid "Total: " msgstr "Total: " msgid "Need: " msgstr "Behov: " msgid "New Game" msgstr "Nyt spil" msgid "Start a single or multi-player game." msgstr "Start et enkelt- eller et flerspiller-spil." msgid "Load Game" msgstr "Indlæs spil" msgid "Load a previously saved game." msgstr "Indlæs et tidligere gemt spil." msgid "Save Game" msgstr "Gem spil" msgid "Save the current game." msgstr "Gem nuværende spil." msgid "Quit" msgstr "Afslut" msgid "Quit out of Heroes of Might and Magic II." msgstr "Forlad Heroes of Might and Magic II." msgid "Language" msgstr "Sprog" msgid "Graphics" msgstr "Grafik" msgid "Black & White" msgstr "Sort & Hvid" msgid "Mouse Cursor" msgstr "Musemarkør" msgid "Color" msgstr "Farve" msgid "Text Support" msgstr "Tekstsupport" msgid "Change the language of the game." msgstr "Ændr spillets sprogindstillinger." msgid "Select Game Language" msgstr "Vælg spillets sprog" msgid "Change the graphics settings of the game." msgstr "Ændr spillets grafikindstillinger." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Vælg farvet musemarkør til eller fra. Dette er kun et æstetisk valg." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Tilvælg tekststøttetilstand for at fÃ¥ flere tekstbaserede informationer om " "spillets vinduer og hændelser." msgid "" "Map\n" "Difficulty" msgstr "" "Kort\n" "Niveau" msgid "" "Game\n" "Difficulty" msgstr "" "Spil-\n" "niveau" msgid "Rating" msgstr "Bedømmelse" msgid "Map Size" msgstr "Kort størrelse" msgid "Opponents" msgstr "Spillere" msgid "Class" msgstr "Klasse" msgid "" "Victory\n" "Conditions" msgstr "" "Vinder-\n" "vilkÃ¥r" msgid "" "Loss\n" "Conditions" msgstr "" "Tabs-\n" "vilkÃ¥r" msgid "First select recipients!" msgstr "Vælg først modtagere!" msgid "You cannot select %{resource}!" msgstr "Du kan ikke vælge %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Indstil antal %{monster}" msgid "Select Recipients" msgstr "Vælg modtagere" msgid "Your Funds" msgstr "Dine midler" msgid "Planned Gift" msgstr "Planlagt foræring" msgid "Gift from %{name}" msgstr "Gave fra %{name}" msgid "Resolution" msgstr "Resolution" msgid "Fullscreen" msgstr "Fuld skærm" msgid "window|Mode" msgstr "Vinduestilstand" msgid "Windowed" msgstr "Vindue" msgid "V-Sync" msgstr "V-Synk." msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "System info" msgid "Change the resolution of the game." msgstr "Skift spilopløsning." msgid "Select Game Resolution" msgstr "Vælg spilopløsning" msgid "Toggle between fullscreen and windowed modes." msgstr "Vælg mellem fuldskærms- og vinduestilstand." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "V-synk. i aktiv tilstand kan løse potentielle renderingsproblemer pÃ¥ visse " "skærme." msgid "Show extra information such as FPS and current time." msgstr "Vis flere informationer som billeder i sekundet (FPS) og klokkeslæt." msgid "Hotkey: " msgstr "Genvejstast: " msgid "Category: " msgstr "Kategori: " msgid "Event: " msgstr "Begivenhed: " msgid "Hot Keys:" msgstr "Genvejstaster:" msgid "Hide" msgstr "Skjul" msgid "Show" msgstr "Vis" msgid "Interface" msgstr "Interface" msgid "Interface Type" msgstr "Interface-type" msgid "Toggle the type of interface you want to use." msgstr "Vælg hvilken interface-type du ønsker at bruge." msgid "Toggle interface visibility." msgstr "Vælg interfacets synlighed til eller fra." msgid "Scroll Speed" msgstr "" "Rulle\n" "hastighed" msgid "Sets the speed at which you scroll the window." msgstr "Bestemmer vinduets rullehastighed." msgid "Select Game Language:" msgstr "Vælg spilsprog:" #, fuzzy msgid "Select Language:" msgstr "Vælg spilsprog:" msgid "Click to choose the selected language." msgstr "Klik for at vælge det valgte sprog." msgid "%{name} has gained a level." msgstr "%{name} har opnÃ¥et et nyt level." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Du har lært %{skill}" msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} har opnÃ¥et et nyt level.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Du kan enten lære:\n" "%{skill1}\n" "eller\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "i/t" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Inspicér venligst vores fine varer. Hvis du føler dig fristet til at handle, " "skal du klikke pÃ¥ de ting du ønsker at handle for og med." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Du har gjort en god handel. Jeg forventer ikke at gøre profit pÃ¥ dette. Er " "der andre af mine varer, der kunne have interesse?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Jeg bytter gerne %{count} for 1 %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Jeg bytter gerne 1 %{resto} for %{count} %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Bytteantal" msgid "Trading Post" msgstr "Handelsstation" msgid "Your Resources" msgstr "Dine resurser" msgid "Available Trades" msgstr "Handlemuligheder" msgid "guarded by %{count} %{monster}" msgstr "Bevogtet af %{count} %{monster}" msgid "guarded by " msgstr "Bevogtet af " msgid "(available: %{count})" msgstr "(tilgængelig: %{count})" msgid "(empty)" msgstr "(tom)" msgid "already learned" msgstr "allerede lært" msgid "treeOfKnowledge|free" msgstr "gratis" msgid "already claimed" msgstr "allerede hævdet" msgid "not claimed" msgstr "ej hævdet" msgid "already knows this skill" msgstr "kender allerede denne evne" msgid "already has max skills" msgstr "har allerede maksimale evner" msgid "(already visited)" msgstr "(allerede besøgt)" msgid "(not visited)" msgstr "(ikke besøgt)" msgid "%{color} Barrier" msgstr "%{color} barriere" msgid "(tent visited)" msgstr "(telt besøgt)" msgid "%{color} Tent" msgstr "%{color} telt" msgid "Road" msgstr "Vej" msgid "(digging ok)" msgstr "(mulig gravning)" msgid "(no digging)" msgstr "(ingen gravning)" msgid "penalty: %{cost}" msgstr "Skridttab: %{cost}" msgid "Defenders:" msgstr "Forsvarere:" msgid "Unknown" msgstr "Ukendt" msgid "heroQuickInfo|(Level %{level})" msgstr "(Level %{level})" msgid "Attack:" msgstr "Angreb:" msgid "Defense:" msgstr "Forsvar:" msgid "Spell Power:" msgstr "Magikraft:" msgid "Knowledge:" msgstr "Kundskab:" msgid "Spell Points:" msgstr "Mana:" msgid "Move Points:" msgstr "Skridtpoint:" msgid "Uncharted Territory" msgstr "Ukendt omrÃ¥de" msgid "Cost per troop:" msgstr "Pris per trop:" msgid "Available: %{count}" msgstr "Tilgængelig: %{count}" msgid "Number to buy:" msgstr "Købeantal:" msgid "Recruit selected monsters." msgstr "Rekruttér valgte væsener." msgid "Select maximum monsters to be recruited." msgstr "Vælg maksimalt antal væsener til rekruttering." msgid "Select only 1 monster to be recruited." msgstr "Vælg kun 1 væsen til rekruttering." #, fuzzy msgid "Select this game resolution." msgstr "Vælg spilopløsning" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Vælg spilopløsning:" msgid "Click to apply the selected resolution." msgstr "Klik for at godkende valgte opløsning." msgid "Click to apply the entered text." msgstr "Klik for at anvende den indtastede tekst." msgid "Click to open the Virtual Keyboard dialog." msgstr "Klik for at Ã¥bne dialogboksen Virtuelt Tastatur." msgid "Open Virtual Keyboard" msgstr "Ã…ben Virtuel Tastatur" msgid "How many creatures do you wish to move?" msgstr "Hvor mange væsener ønsker du at flytte?" msgid "Select how many units to separate into:" msgstr "Vælg hvor mange gange troppen skal deles:" msgid "Map: " msgstr "Kort:" msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "MÃ¥ned: " msgid ", Week: " msgstr ", Uge: " msgid ", Day: " msgstr ", Dag: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Placering: " msgid "Are you sure you want to delete file:" msgstr "Er du sikker pÃ¥ at du vil slette denne fil:" msgid "Warning" msgstr "Advarsel" msgid "Click to save the current game." msgstr "Klik for at gemme igangværende spil." msgid "Click to load a previously saved game." msgstr "Klik for at indlæse et tidligere gemt spil." msgid "File to Save:" msgstr "Fil som skal gemmes:" msgid "File to Load:" msgstr "Fil som skal indlæses:" msgid "Terrain object" msgstr "Terræn-objekt" msgid "Accept the choice made." msgstr "Acceptér de trufne valg." msgid "Select Skill:" msgstr "Vælg evne:" msgid "Select Spell:" msgstr "Vælg magi:" msgid "Select Artifact:" msgstr "Vælg artefakt:" msgid "Select Monster:" msgstr "Vælg væsen:" msgid "Select Hero:" msgstr "Vælg helt:" msgid "race|Random" msgstr "Tilfældig" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Klik for at godkende placering af valgte borg/by." #, fuzzy msgid "%{color} %{race}" msgstr "%{color} %{race} helt" msgid "You will place" msgstr "Du vil placere" msgid "Click to select this class." msgstr "Klik for at vælge denne klasse." msgid "Click to select this color." msgstr "Klik for at vælge denne farve." msgid "Select Treasure:" msgstr "Vælg skat:" msgid "Select Ocean Object:" msgstr "Vælg hav-objekt:" msgid "Castle/town placing" msgstr "Borg/by-vindue" msgid "doubleLinedRace|Neutral" msgstr "Neutral" msgid "Click to start placing the selected castle/town." msgstr "Klik for at godkende placering af valgte borg/by." msgid "Click to select town placing." msgstr "Klik for at vælge By-placering." msgid "Click to select castle placing." msgstr "Klik for at vælge Borg-placering." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{race} %{townOrCastle}" msgid "race|Neutral" msgstr "Neutral" msgid "Select Dwelling:" msgstr "Vælg Bosted:" msgid "Select Landscape Object:" msgstr "Vælg Landskab-objekt:" msgid "Mine placing" msgstr "Mine-placering" msgid "" "Resource\n" "type:" msgstr "" "Resurse-\n" "type:" msgid "%{mineName} appearance:" msgstr "%{mineName} udseende:" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" "Klik for at vælge %{object} som den resursegenerator, der skal placeres." msgid "Select Mountain Object:" msgstr "Vælg Bjerg-objekt:" msgid "Select Rock Object:" msgstr "Vælg Sten-objekt:" msgid "Select Tree Object:" msgstr "Vælg Træ-objekt:" msgid "Select Power Up Object:" msgstr "Vælg Power Up-objekt:" msgid "Select Adventure Object:" msgstr "Vælg Eventyr-objekt:" msgid "Players Icon" msgstr "Spiller-ikon" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Angiver, hvor mange spillere der er i alt i scenariet. Alle positioner, der " "ikke er besat af menneskelige spillere, vil blive besat af AI-spillere." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Angiver om kortet\n" "er lille (36 x 36), mellemstor\n" "(72 x 72), stor (108 x 108),\n" "eller ekstrastor (144 x 144)." msgid "Size Icon" msgstr "Størrelsesikon" msgid "Map Type" msgstr "Korttype" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Angiver om kortet er lavet til \"Arvefølgekrigene\"- eller \"Prisen for " "Loyalitet\"-versionen af spillet." msgid "Map Type:\n" msgstr "Korttype:\n" msgid "The Succession Wars" msgstr "Arvefølgekrigene" msgid "The Price of Loyalty" msgstr "Prisen for Loyalitet" msgid "Resurrection" msgstr "Opstandelse" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Sprog" msgid "Lose all your heroes and towns." msgstr "Mist alle dine helte og byer." msgid "Lose a specific town." msgstr "Mist en bestemt by." msgid "Lose a specific hero." msgstr "Mist en bestemt helt." msgid "Run out of time. Fail to win by a certain point." msgstr "Undlad at vinde, inden et bestemt antal dage er gÃ¥et." msgid "Loss Condition" msgstr "TabsvilkÃ¥r" msgid "Defeat all enemy heroes and towns." msgstr "Besejr alle fjendtlige helte og byer." msgid "Capture a specific town." msgstr "Indtag en bestemt by." msgid "Defeat a specific hero." msgstr "Besejr en bestemt helt." msgid "Find a specific artifact." msgstr "Find et bestemt artefakt." msgid "Your side must defeat the opposing side." msgstr "Din side skal besejre den modsatte." msgid "Accumulate a large amount of gold." msgstr "Saml en stor mængde guld." msgid "Victory Condition" msgstr "VindervilkÃ¥r" msgid "Map difficulty:" msgstr "Kort-niveau:" msgid "N" msgstr "N" msgid "No maps exist at that size." msgstr "Ingen kort i den størrelse" msgid "Small Maps" msgstr "SmÃ¥ kort" msgid "View only maps of size small (36 x 36)." msgstr "Vis kun smÃ¥ kort (36 x 36)." msgid "Medium Maps" msgstr "Mellemstore kort" msgid "View only maps of size medium (72 x 72)." msgstr "Vis kun mellemstore kort (72 x 72)." msgid "Large Maps" msgstr "Store kort" msgid "View only maps of size large (108 x 108)." msgstr "Vis kun store kort (108 x 108)." msgid "Extra Large Maps" msgstr "Ekstrastore kort" msgid "View only maps of size extra large (144 x 144)." msgstr "Vis kun ekstra store kort (144 x 144)." msgid "All Maps" msgstr "Alle kort" msgid "View all maps, regardless of size." msgstr "Vis alle kort, uanset størrelse." msgid "Selected Name" msgstr "Valgte navn" msgid "The name of the currently selected map." msgstr "Navnet pÃ¥ det valgte kort." msgid "Selected Map Difficulty" msgstr "Valgte kort-niveau" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Det nuværende kort-niveau for det valgte kort. Kortets sværhedsgrad er " "udelukkende bedømt af scenariets designer. Vanskeligere kort inkluderer " "flere og stærkere fjender, færre resurser eller andre særlige vilkÃ¥r, som " "gør det sværere for menneskelige spillere." msgid "Selected Description" msgstr "Valgte beskrivelse" msgid "The description of the currently selected map." msgstr "Beskrivelsen til det valgte kort." msgid "Jump" msgstr "Hop" msgid "Hero Speed" msgstr "Heltes hastighed" msgid "Don't Show" msgstr "Vis ikke" msgid "Enemy Speed" msgstr "Fjenders hastighed" msgid "Auto Resolve" msgstr "Fuldt auto" msgid "Auto, No Spells" msgstr "Auto, ingen magi" msgid "Battles" msgstr "Kamp" #, fuzzy msgid "combatMode|Manual" msgstr "Manuelt" msgid "Change the speed at which your heroes move on the main screen." msgstr "Vælg hvor hurtigt dine helte skal flytte sig pÃ¥ hovedskærmen." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Bestemmer hvor hurtigt AI-spillernes helte bevæger sig. Du kan ogsÃ¥ vælge " "ikke at se deres bevægelser overhovedet." msgid "Change the interface settings of the game." msgstr "Ændr spillets brugerfladeindstillinger." msgid "Interface Settings" msgstr "Brugerfladeindstillinger" msgid "Toggle instant battle mode." msgstr "Vælg øjeblikkelig kamptilstand." msgid "Att." msgstr "Angr." msgid "Def." msgstr "Forsv." msgid "Power" msgstr "Magikr." msgid "Knowl" msgstr "Kunds." msgid "1st" msgstr "1." msgid "2nd" msgstr "2." msgid "3rd" msgstr "3." msgid "4th" msgstr "4." msgid "5th" msgstr "5." msgid "6th" msgstr "6." msgid "Oracle: Player Rankings" msgstr "Orakel: Spilleres rangering" msgid "Thieves' Guild: Player Rankings" msgstr "Tyvelaug: Spilleres rangering" msgid "Number of Towns:" msgstr "Antal byer:" msgid "Number of Castles:" msgstr "Antal borge:" msgid "Number of Heroes:" msgstr "Antal helte:" msgid "Gold in Treasury:" msgstr "Guld i statskassen:" msgid "Wood & Ore:" msgstr "Træ & malm:" msgid "Gems, Cr, Slf & Mer:" msgstr "Juveler, kr, sv & kv:" msgid "Obelisks Found:" msgstr "Besøgte obelisker:" msgid "Artifacts:" msgstr "Antal artefakter:" msgid "Total Army Strength:" msgstr "Samlet hærstyrke:" msgid "Income:" msgstr "Indkomst:" msgid "Best Hero:" msgstr "Bedste helt:" msgid "Best Hero Stats:" msgstr "Bedste helt (info):" msgid "Personality:" msgstr "Personlighed:" msgid "Best Monster:" msgstr "Bedste væsen:" msgid "Random Castle Name" msgstr "Tilfældigt borgnavn" #, fuzzy msgid "Random Town Name" msgstr "Tilfældig by" msgid "Allow Castle build" msgstr "Tillad borgbyggeri" msgid "Default Buildings" msgstr "Standardbygninger" msgid "Default Army" msgstr "" "standard\n" "hær" msgid "Castle Army" msgstr "Borghær" #, fuzzy msgid "Town Army" msgstr "By" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "Klik for at ændre borgnavnet. Højreklik: Nulstil til standard." msgid "Enter Castle name" msgstr "Skriv borgnavn" msgid "Allow to build a castle in this town." msgstr "Tillad borgbyggeri i denne by." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" "Skift brugen af standardbygninger. Brugerdefinerede bygninger vil blive " "nulstillet!" msgid "Toggle building construction restriction mode." msgstr "Skift begrænsningstilstand for bygningskonstruktion." msgid "Restrict Building Construction" msgstr "Begræns bygningskonstruktion" msgid "Use default defenders army." msgstr "Brug standard forsvarshær." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "Indstil brugerdefinerede borghær. Højreklik: Fjern trop." msgid "Message Text:" msgstr "Tekstbesked:" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" msgid "Message:" msgstr "Besked:" msgid "Click to save the Event properties." msgstr "Klik for at gemme begivenhedens egenskaber." msgid "No resources will be given as a reward." msgstr "" msgid "Resources" msgstr "Resurser" msgid "Resources will be given as a reward." msgstr "" msgid "Click here to change the event message." msgstr "Klik her for at gemme begivenhedsbeskeden." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Dag: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Klik for at gemme begivenhedens egenskaber." #, fuzzy msgid "Add Event" msgstr "Begivenhed" #, fuzzy msgid "Add an additional event." msgstr "Ekstra programmering" #, fuzzy msgid "Edit Event" msgstr "Begivenhed" #, fuzzy msgid "Edit an existing event." msgstr "indlæs et eksisterende kort." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "indlæs et eksisterende kort." #, fuzzy msgid "Effects:" msgstr "Effekter" #, fuzzy msgid "Conditions:" msgstr "" "Tabs-\n" "vilkÃ¥r" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" msgid "Set Experience value" msgstr "Indstil erfaringspoint" msgid "Artifact" msgstr "Artefakt" msgid "No artifact will be given by the event." msgstr "" msgid "Delete Artifact" msgstr "Slet artefakt:" #, fuzzy msgid "Delete an artifact from the event." msgstr "indlæs et eksisterende kort." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Vælg evne:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" msgid "%{objects} cannot be placed on water." msgstr "%{objects} kan ikke placeres pÃ¥ vand." msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" "Det Ultimative Artefakt kan kun placeres i terræn, hvor det er muligt at " "grave." msgid "%{objects} must be placed on water." msgstr "%{objects} mÃ¥ kun placeres pÃ¥ vand." msgid "Objects cannot be placed outside the map." msgstr "Objekter kan ikke placeres udenfor kortet." msgid "Action objects must be placed on clear tiles." msgstr "Handlingsobjekter skal placeres pÃ¥ rene felter." msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Er du sikker pÃ¥, at du vil tilbage til spillets hovedmenu? Alle ikke-gemte " "ændringer vil gÃ¥ tabt." msgid "Editor" msgstr "Editor" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Er du sikker pÃ¥, at du vil indlæse et nyt kort? (Alle ikke-gemte ændringer " "pÃ¥ det nuværende kort, vil gÃ¥ tabt.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Er du sikker pÃ¥, at du vil oprette et nyt kort? (Alle ikke-gemte ændringer " "af det nuværende kort, vil gÃ¥ tabt.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "START" msgid "Main Menu" msgstr "Hovedmenu" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Er du sikker pÃ¥, at du vil tilbage til spillets hovedmenu? Alle ikke-gemte " "ændringer vil gÃ¥ tabt." msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Genstart" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Er du sikker pÃ¥, at du vil indlæse et nyt kort? (Alle ikke-gemte ændringer " "pÃ¥ det nuværende kort, vil gÃ¥ tabt.)" msgid "Create a new map from scratch." msgstr "Opret et nyt kort fra bunden." msgid "New Map" msgstr "Nyt kort" msgid "Load Map" msgstr "Indlæs kort" msgid "Load an existing map." msgstr "indlæs et eksisterende kort." msgid "Save Map" msgstr "Gem kort" msgid "Save the current map." msgstr "Gem nuværende kort." msgid "Quit out of the map editor." msgstr "Forlad korteditoren." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Klik her for at vende tilbage til hovedmenuen." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "Indtast tekst til %{object}" msgid "Set Random Ultimate Artifact Radius" msgstr "Indstil radius: Tilfældigt Ultimativt Artefakt" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "med 1 artefakt." msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "Veje" msgid "Streams" msgstr "Ã…-tilstand" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "Der kan maksimalt placeres %{count} helte af samme farve pÃ¥ kortet." msgid "Failed to update player information." msgstr "Opdatering af spilleroplysninger mislykkedes." msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Kun et tilfældigt artefakt kan placeres pÃ¥ kortet." #, fuzzy msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "Der kan maksimalt placeres %{count} helte af samme farve pÃ¥ kortet." msgid "The map is corrupted." msgstr "Kortet er beskadiget." msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "Kan ikke oprette en mappe til at gemme kortet i." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Kan ikke oprette en mappe til at gemme kortet i." msgid "Are you sure you want to overwrite the existing map?" msgstr "Er du sikker pÃ¥, at du vil overskrive det eksisterende kort?" msgid "Map saved to: " msgstr "" msgid "Failed to save the map." msgstr "Kunne ikke gemme kortet." msgid "Used to place %{object}." msgstr "Bruges til at placere %{object}." msgid "Select object type" msgstr "Vælg objekttype:" msgid "" "Click here to\n" "select a monster." msgstr "" "Klik her, for at\n" "vælge et væsen." msgid "" "Click here to\n" "select another monster." msgstr "" "Klik her, for at\n" "vælge et andet væsen." msgid "" "Cell\n" "Details" msgstr "" "Celle-\n" "detaljer" msgid "Erase" msgstr "Viskelæder" msgid "Mountains" msgstr "Bjerge" msgid "Rocks" msgstr "Klipper" msgid "Trees" msgstr "Træer" msgid "Water Objects" msgstr "Hav-objekter" msgid "Miscellaneous" msgstr "Diverse" msgid "Artifacts" msgstr "Artefakter" msgid "Dwellings" msgstr "Bosteder" msgid "Mines" msgstr "Miner" msgid "Power-ups" msgstr "Power Ups" msgid "Treasures" msgstr "Skatte" msgid "Heroes" msgstr "Helte" msgid "Towns" msgstr "Byer" msgid "editorErasure|Landscape objects" msgstr "Landskabsobjekter" msgid "editorErasure|Adventure non pickable objects" msgstr "Ikke-opsamlingsobjekter" msgid "editorErasure|Castles" msgstr "Borge" msgid "editorErasure|Adventure pickable objects" msgstr "Opsamlingsobjekter" msgid "editorErasure|Monsters" msgstr "Væsener" msgid "editorErasure|Heroes" msgstr "Helte" msgid "editorErasure|Roads" msgstr "Veje" msgid "editorErasure|Streams" msgstr "Ã…er" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Tegner terræn indenfor en firkant med et størrelsesforhold pÃ¥\n" "%{size}x%{size}." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Fjerner alle ting indenfor en firkant med et størrelsesforhold pÃ¥\n" "%{size}x%{size}." msgid "Small Brush" msgstr "Lille pensel" msgid "Medium Brush" msgstr "Mellemstor pensel" msgid "Large Brush" msgstr "Stor pensel" msgid "Area Fill" msgstr "OmrÃ¥deudfyldning" msgid "Used to click and drag for filling in large areas." msgstr "" "Bruges til at fylde omrÃ¥der, ved at klikke og trække musen henover dem." msgid "Clear Area" msgstr "Tøm omrÃ¥de" msgid "Used to click and drag for clearing large areas." msgstr "" "Bruges til at tømme omrÃ¥der, ved at klikke og trække musen henover dem." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Koster %{rate}x normal skridtpoint for alle helte. (Stifinding reducerer " "eller eliminerer straffen.)" msgid "Traversable only by boat." msgstr "Farbar kun ved sejlads." msgid "No special modifiers." msgstr "Ingen særlige pÃ¥virkninger." msgid "Toggle the erasure of %{type} objects." msgstr "Vælg sletning af %{type}objekter til og fra." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Objekter af denne type vil blive visket ud med viskelæderværktøjet. Venstre-" "klik her for at vælge denne type. Hold knappen nede, for at fravælge alle " "andre objekttyper." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Objekter af denne type vil IKKE blive visket ud med viskelæderværktøjet. " "Venstre-klik her for at vælge type. Hold denne knap nede, for at vælge alle " "andre objekttyper." msgid "Terrain Mode" msgstr "Terræn-tilstand" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" "Bruges til at tegne det underliggende græs, jord, vand, osv. pÃ¥ kortet." msgid "Landscape Objects Mode" msgstr "Landskabsobjekt-tilstand" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Bruges til at placere landskabsobjekter (bjerge, sten, træer, osv.) pÃ¥ " "kortet." msgid "Detail Mode" msgstr "Detalje-tilstand" msgid "Used for special editing of action objects." msgstr "Bruges til speciel redigering af handlingsobjekter." msgid "Adventure Objects Mode" msgstr "Eventyr objekt-tilstand" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Bruges til at placere eventyr-objekter (artefakter, bosteder, miner, skatte, " "osv.) pÃ¥ kortet." msgid "Kingdom Objects Mode" msgstr "Kongerigeobjekt-tilstand" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Bruges til at placere kongerige-objekter (byer, borge og helte) pÃ¥ kortet." msgid "Monsters Mode" msgstr "Væsen-tilstand" msgid "Used to place monsters on the map." msgstr "Bruges til at placere væsener pÃ¥ kortet." msgid "Allows you to draw streams by clicking and dragging." msgstr "Lader dig tegne Ã¥er ved at klikke og trække i dem." msgid "Stream Mode" msgstr "Ã…-tilstand" msgid "Allows you to draw roads by clicking and dragging." msgstr "Lader dig tegne stier ved at klikke og trække i dem." msgid "Road Mode" msgstr "Vej-tilstand" msgid "Erase Mode" msgstr "Viskelæder" msgid "Used to erase objects from the map." msgstr "Bruges til at fjerne objekter fra kortet." msgid "Change between zoom and normal view." msgstr "Vælg mellem normal og forstørret visning." msgid "Magnify" msgstr "Forstør" msgid "Undo" msgstr "Fortryd" msgid "Undo your last action." msgstr "Fortryd din sidste handling." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "Fortryd din sidste handling." msgid "Edit map title, description, and other general information." msgstr "Rediger kortets navn, beskrivelse eller andre informationer." msgid "Specifications" msgstr "Specifikationer" msgid "File Options" msgstr "Filindstillinger" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Frembring filindstillingsmenuen, som tillader dig at gemme/indlæse kort " "eller afslutte Korteditoren." msgid "View the editor system options, which let you customize the editor." msgstr "Vis korteditorens systemindstillinger, som lader dig tilpasse den." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Opret et kort, som er %{size} kvadrater høj og %{size} kvadrater bred." msgid "Cancel back to the New Map menu." msgstr "Afbryd og gÃ¥ tilbage til hovedmenuen for Nyt-kort." msgid "Cancel back to the main menu." msgstr "Afbryd og gÃ¥ tilbage til hovedmenuen." msgid "From Scratch" msgstr "Fra bunden" msgid "Start from scratch with a blank map." msgstr "Begynd pÃ¥ et kort helt fra bunden." msgid "Create a randomly generated map." msgstr "Opret et kort automatisk." msgid "Random" msgstr "Tilfældigt" msgid "Cancel back to the Map Editor main menu." msgstr "Afbryd og gÃ¥ tilbage til Korteditorens hovedmenu." msgid "No maps available!" msgstr "Intet kort tilgængelig!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{color} %{race} helt" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{color} %{race} helt" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{color} %{race} %{townOrCastle}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "None." msgstr "Ingen" #, fuzzy msgid "One side defeats another." msgstr "Vælg venligst en anden helt." #, fuzzy msgid "Accumulate gold." msgstr "Akkumuler %{count} guldstykker." #, fuzzy msgid "Run out of time." msgstr "Forlad korteditoren." #, fuzzy msgid "alliance|1st" msgstr " alliance" #, fuzzy msgid "alliance|2nd" msgstr " alliance" #, fuzzy msgid "alliance|3rd" msgstr " alliance" #, fuzzy msgid "alliance|4th" msgstr " alliance" #, fuzzy msgid "alliance|5th" msgstr " alliance" #, fuzzy msgid "Special Loss Condition" msgstr "TabsvilkÃ¥r" #, fuzzy msgid "Special Victory Condition" msgstr "VindervilkÃ¥r" #, fuzzy msgid "Allow standard victory conditions" msgstr "VindervilkÃ¥r" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " alliance" #, fuzzy msgid "{%number} alliance: " msgstr " alliance" #, fuzzy msgid "Gold:" msgstr "guld" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Vælg den by, du gerne vil havne i." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Klik her for at gemme begivenhedsbeskeden." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Klik her for at gemme begivenhedsbeskeden." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Klik her for at gemme begivenhedsbeskeden." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Klik her for at gemme begivenhedsbeskeden." #, fuzzy msgid "Map Difficulty" msgstr "" "Kort\n" "Niveau" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "Placering: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Valgte beskrivelse" #, fuzzy msgid "Click to accept the changes made." msgstr "Klik for at se næste by." #, fuzzy msgid "Click to edit custom rumors." msgstr "Klik for at gemme det aktuelle kort." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Klik for at godkende kampresultaterne." #, fuzzy msgid "Events" msgstr "Begivenhed" #, fuzzy msgid "Click to change the language of the map." msgstr "Ændr spillets sprogindstillinger." #, fuzzy msgid "Click to change your map name." msgstr "Klik for at se næste by." #, fuzzy msgid "Map Name" msgstr "Kort-filnavn" #, fuzzy msgid "Click to change the description of the current map." msgstr "Beskrivelsen til det valgte kort." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Beskrivelsen til det valgte kort." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Beskrivelsen til det valgte kort." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Korttype" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Det nuværende kort-niveau for det valgte kort. Kortets sværhedsgrad er " "udelukkende bedømt af scenariets designer. Vanskeligere kort inkluderer " "flere og stærkere fjender, færre resurser eller andre særlige vilkÃ¥r, som " "gør det sværere for menneskelige spillere." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Vælg antal %{resource}:" msgid "Animation" msgstr "Animation" msgid "Passability" msgstr "Fremkommelighed" msgid "Toggle animation of the objects." msgstr "SlÃ¥ animation af objekterne til eller fra." msgid "Toggle display of objects' passability." msgstr "SlÃ¥ visning af objekters fremkommelighed til eller fra." msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Klik for at gemme begivenhedens egenskaber." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "Ekstra programmering" #, fuzzy msgid "Edit Rumor" msgstr "Editor" #, fuzzy msgid "Edit an existing rumor." msgstr "indlæs et eksisterende kort." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "indlæs et eksisterende kort." msgid "" "\n" "\n" "Size: " msgstr "" msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Beskrivelse: " msgid "Save Map:" msgstr "Gem kort:" msgid "Click to save the current map." msgstr "Klik for at gemme det aktuelle kort." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" msgid "Click to save the Sphinx properties." msgstr "Klik for at gemme Sfinksens egenskaber." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Let" msgid "difficulty|Normal" msgstr "Normal" msgid "difficulty|Hard" msgstr "Svær" msgid "difficulty|Expert" msgstr "Ekspert" msgid "difficulty|Impossible" msgstr "Umulig" msgid "and more..." msgstr "og mere..." msgid "Easy" msgstr "Let" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "Svær" msgid "Campaign Difficulty" msgstr "Felttogsniveau" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Vælg dette niveau, for at opleve felttoget med mindre udfordring. AI-" "spillerne vil være svagere end de vil være pÃ¥ 'normal'." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Vælg dette niveau, for at opleve felttoget i henhold til det originale " "design." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Vælg dette niveau, for at opleve felttoget med større udfordring. AI-" "spillerne vil være stærkere end de vil være pÃ¥ 'normal'." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Tillykke!\n" "\n" "Dage: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Niveau: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Score: %{score}\n" "\n" "Bedømmelse:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Start det valgte scenarie." msgid "View Intro" msgstr "Vis intro" msgid "View the intro video for the current state of the campaign." msgstr "Vis introvideoer til felttogets nuværende stadie." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Vælg felttogets niveau. Dette kan sænkes nÃ¥r som helst under felttoget." msgid "Restart the current scenario." msgstr "Genstart det igangværende scenarie." msgid "Difficulty" msgstr "Kort-niveau:" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Du har ændret felttogets sværhedsgrad til et lavere niveau. Du vil ikke være " "i stand til at fortryde dette efter dette tidspunkt. Højscoren beregnes " "udelukkende pÃ¥ baggrund af den nye sværhedsgrad. Vil du fortsætte?" msgid "Are you sure you want to restart this scenario?" msgstr "Er du sikker pÃ¥ du vil genstarte dette scenarie?" msgid "Campaign Scenario loading failure" msgstr "Indlæsningsfejl af felttogs-scenarie" msgid "Please make sure that campaign files are correct and present." msgstr "Sørg for, at felttogsfilerne er korrekte og tilstede." msgid "Days spent" msgstr "Dage brugt" msgid "The number of days spent on this campaign." msgstr "Antal dage brugt pÃ¥ dette felttog." msgid "Project Coordination and Core Development" msgstr "Projektkoordination og kerneudvikling" msgid "Development" msgstr "Udvikling" msgid "Visit us at " msgstr "Besøg os pÃ¥ " msgid "QA and Support" msgstr "QA og support" msgid "Dev and Support" msgstr "Udv. og support" msgid "Special Thanks to" msgstr "Særlig tak til" msgid "and many-many other contributors and supporters!" msgstr "og mange-mange andre bidragydere og tilhængere!" msgid "Support us at" msgstr "Støt os pÃ¥" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "local-donation-platform|https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Kontakt os pÃ¥" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "local-social-network|https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Brug for hjælp til spillet?" msgid "Original project before 0.7" msgstr "Originale projekt før 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Teamet bag Heroes of Might and Magic II: The Succession Wars" msgid "Designed and Directed" msgstr "Designet og instrueret" msgid "Programming and Design" msgstr "Programmering og design" msgid "Executive Producer" msgstr "Executive Producer" msgid "Producer" msgstr "Producer" msgid "Additional Design" msgstr "Ekstra design" msgid "Additional Programming" msgstr "Ekstra programmering" msgid "Musical Production" msgstr "Musikproduktion" msgid "Music and Sound Design" msgstr "Musik- og lyddesign" msgid "Vocalists" msgstr "Vokalister" msgid "Art Director" msgstr "Art Director" msgid "Assistant Art Director" msgstr "Assisterende Art Director" msgid "Artists" msgstr "Kunstnere" msgid "QA Manager" msgstr "QA Manager" msgid "QA" msgstr "QA" msgid "Writing" msgstr "Skribent" msgid "Manual and Helpfile" msgstr "Manual og hjælpefil" msgid "Scenarios" msgstr "Scenarier" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Teamet bag Heroes of Might and Magic II: The Price of Loyalty" msgid "Design Lead" msgstr "Design-leder" msgid "Designers" msgstr "Designere" msgid "Programming Lead" msgstr "Programmeringsleder" msgid "Art Lead" msgstr "Kunstleder" msgid "Playtesters" msgstr "Spiltestere" msgid "Designer" msgstr "Designer" msgid "Producers" msgstr "Producere" msgid "QA Managers" msgstr "QA Managere" msgid "Sound Design" msgstr "Lyddesign" msgid "Town Themes" msgstr "Byernes musiktemaer" msgid "Alto Sax" msgstr "Altsax" msgid "Harpsichord and Piano" msgstr "Cembalo og klaver" msgid "Basso Vocal" msgstr "Bass vokal" msgid "Soprano Vocal" msgstr "Sopran vokal" msgid "Recorded at %{recordingStudio}" msgstr "Indspillet hos %{recordingStudio}" msgid "credits|Manual" msgstr "Manual" msgid "German Consultant" msgstr "Tysk rÃ¥dgiver" msgid "Map Designers" msgstr "Kortdesignere" msgid "Package Design" msgstr "Pakkedesign" msgid "High Scores" msgstr "Ranglister" msgid "Your Name" msgstr "Dit navn" msgid "Unknown Hero" msgstr "Ukendt helt" msgid "Standard" msgstr "Standard" msgid "View High Scores for Standard Maps." msgstr "Vis højeste score for enkelt spiller kort." msgid "Campaign" msgstr "Felttog" msgid "View High Scores for Campaigns." msgstr "Vis højeste score for enkelt spiller kort." msgid "hotkey|default okay event" msgstr "Bekræft" msgid "hotkey|default cancel event" msgstr "Afbryd" msgid "hotkey|default left" msgstr "Venstre" msgid "hotkey|default right" msgstr "Højre" msgid "hotkey|default up" msgstr "Op" msgid "hotkey|default down" msgstr "Ned" msgid "hotkey|toggle fullscreen" msgstr "Fuldskærm" msgid "hotkey|toggle text support mode" msgstr "Tekstunderstøttelsestilstand" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "Tekstunderstøttelsestilstand" msgid "hotkey|new game" msgstr "Nyt spil" msgid "hotkey|load game" msgstr "Indlæs spil" msgid "hotkey|high scores" msgstr "Ranglister" msgid "hotkey|credits" msgstr "Kreditter" msgid "hotkey|standard game" msgstr "Enkeltspillerspil" msgid "hotkey|campaign game" msgstr "Felttog" msgid "hotkey|multi-player game" msgstr "Flerspillerspil" msgid "hotkey|settings" msgstr "Indstillinger" msgid "hotkey|quit" msgstr "Forlad" msgid "hotkey|select map" msgstr "Vælg kort" msgid "hotkey|select small map size" msgstr "Vælg lille kortstørrelse" msgid "hotkey|select medium map size" msgstr "Vælg mellemstor kortstørrelse" msgid "hotkey|select large map size" msgstr "Vælg stor kortstørrelse" msgid "hotkey|select extra large map size" msgstr "Vælg ekstrastor kortstørrelse" msgid "hotkey|select all map sizes" msgstr "Vælg alle kortstørrelser" msgid "hotkey|hot seat game" msgstr "Lokalt spil" msgid "hotkey|battle only game" msgstr "Kun-kamp spil" msgid "hotkey|choose the original campaign" msgstr "Vælg det originale felttog" msgid "hotkey|choose the expansion campaign" msgstr "Vælg udvidelsens felttog" msgid "hotkey|map editor main menu" msgstr "Korteditorens hovedmenu" msgid "hotkey|new map menu" msgstr "Nyt-kort menu" msgid "hotkey|load map menu" msgstr "Indlæs-kort menu" msgid "hotkey|new map from scratch" msgstr "Nyt blankt kort" msgid "hotkey|new random map" msgstr "Generer nyt kort" msgid "hotkey|undo last action" msgstr "Fortryd forrige handling" msgid "hotkey|redo last action" msgstr "Gentag forrige handling" msgid "hotkey|open game main menu" msgstr "Ã…ben spillets hovedmenu" #, fuzzy msgid "hotkey|toggle passability" msgstr "Status (til/fra)" msgid "hotkey|roland campaign" msgstr "Felttoget: Roland" msgid "hotkey|archibald campaign" msgstr "Felttoget: Archibald" msgid "hotkey|price of loyalty campaign" msgstr "Felttoget: Prisen for Loyalitet" msgid "hotkey|voyage home campaign" msgstr "Felttoget: Hjemrejse" msgid "hotkey|wizard's isle campaign" msgstr "Felttoget: Troldmændenes Ø" msgid "hotkey|descendants campaign" msgstr "Felttoget: Efterkommere" msgid "hotkey|select first campaign bonus" msgstr "Vælg felttogsbonus nr.1" msgid "hotkey|select second campaign bonus" msgstr "Vælg felttogsbonus nr.2" msgid "hotkey|select third campaign bonus" msgstr "Vælg felttogsbonus nr.3" msgid "hotkey|view campaign intro" msgstr "Vis felttogets intro" msgid "hotkey|select campaign difficulty" msgstr "Vælg felttogets sværhedsgrad" msgid "hotkey|restart campaign scenario" msgstr "Genstart felttogsscenarie" msgid "hotkey|world map left" msgstr "Verdenskort venstre" msgid "hotkey|world map right" msgstr "Verdenskort højre" msgid "hotkey|world map up" msgstr "Verdenskort op" msgid "hotkey|world map down" msgstr "Verdenskort ned" msgid "hotkey|world map up left" msgstr "Verdenskort op til venstre" msgid "hotkey|world map up right" msgstr "Verdenskort op til højre" msgid "hotkey|world map down left" msgstr "Verdenskort ned til venstre" msgid "hotkey|world map down right" msgstr "Verdenskort ned til højre" msgid "hotkey|save game" msgstr "Gem spil" msgid "hotkey|next hero" msgstr "Næste helt" msgid "hotkey|change to hero under cursor" msgstr "Skift til markeret helt" msgid "hotkey|start hero movement" msgstr "Fortsæt heltebevægelse" msgid "hotkey|cast adventure spell" msgstr "Kast eventyrmagi" msgid "hotkey|put hero to sleep" msgstr "Sæt helt i dvale" msgid "hotkey|next town" msgstr "Næste by" msgid "hotkey|end turn" msgstr "End tur" msgid "hotkey|file options" msgstr "Filindstillinger" msgid "hotkey|adventure options" msgstr "Eventyrindstillinger" msgid "hotkey|puzzle map" msgstr "Puslespilskort" msgid "hotkey|scenario information" msgstr "Scenarieinfo" msgid "hotkey|dig for artifact" msgstr "Grav efter artefakt" msgid "hotkey|view world" msgstr "Vis verden" msgid "hotkey|kingdom summary" msgstr "Oversigt over kongedømmet" msgid "hotkey|default action" msgstr "Standardhandling" msgid "hotkey|open focus" msgstr "Fokusér pÃ¥ helt" msgid "hotkey|system options" msgstr "Tilpas systemindstillinger" msgid "hotkey|scroll left" msgstr "Rul til venstre" msgid "hotkey|scroll right" msgstr "Rul til højre" msgid "hotkey|scroll up" msgstr "Rul opad" msgid "hotkey|scroll down" msgstr "Rul nedad" msgid "hotkey|toggle control panel" msgstr "Kontrolpanel (til/fra)" msgid "hotkey|toggle radar" msgstr "Minikort (til/fra)" msgid "hotkey|toggle buttons" msgstr "Knapper (til/fra)" msgid "hotkey|toggle status" msgstr "Status (til/fra)" msgid "hotkey|toggle icons" msgstr "Ikoner (til/fra)" msgid "hotkey|transfer control to ai" msgstr "Overgiv kontrol til en AI" msgid "hotkey|retreat from battle" msgstr "Tilbagetog fra kamp" msgid "hotkey|surrender during battle" msgstr "Overgivelse i kamp" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Autokamp (til/fra)" #, fuzzy msgid "hotkey|quick combat" msgstr "Forlad" msgid "hotkey|battle options" msgstr "Kampindstillinger" msgid "hotkey|skip turn in battle" msgstr "Skift tur i kamp" msgid "hotkey|cast battle spell" msgstr "Kast kampmagi" msgid "hotkey|dwelling level 1" msgstr "Bosted niveau 1" msgid "hotkey|dwelling level 2" msgstr "Bosted niveau 2" msgid "hotkey|dwelling level 3" msgstr "Bosted niveau 3" msgid "hotkey|dwelling level 4" msgstr "Bosted niveau 4" msgid "hotkey|dwelling level 5" msgstr "Bosted niveau 5" msgid "hotkey|dwelling level 6" msgstr "Bosted niveau 6" msgid "hotkey|well" msgstr "Brønd" msgid "hotkey|marketplace" msgstr "Markedsplads" msgid "hotkey|mage guild" msgstr "Magikerlaug" msgid "hotkey|shipyard" msgstr "Skibsværft" msgid "hotkey|thieves guild" msgstr "Tyvelaug" msgid "hotkey|tavern" msgstr "Kro" msgid "hotkey|construction screen" msgstr "Borg-vindue" msgid "hotkey|buy all monsters in well" msgstr "Rekruttér alle væsener fra brønden" msgid "hotkey|split stack by half" msgstr "Del tropper i to" msgid "hotkey|split stack by one" msgstr "Tag én enhed ud af en trop" msgid "hotkey|join stacks" msgstr "Foren tropper" msgid "hotkey|upgrade troop" msgstr "Opgradér trop" msgid "hotkey|dismiss hero or troop" msgstr "Bortvis helt eller trop" #, fuzzy msgid "hotkey|exchange all troops" msgstr "Opgradér trop" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Vil du genoptage kontrollen fra AI'en? Dette vil kun have effekt pÃ¥ næste " "tur." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Vil du lade AI'en overtage kontrollen? Effekten vil først træde i kraft " "under næste tur." msgid "Default Actions" msgstr "Standardhandlinger" msgid "Global Actions" msgstr "Globale Handlinger" msgid "World Map" msgstr "Verdenskort" msgid "Battle Screen" msgstr "Kamp-vindue" msgid "Town Screen" msgstr "Borg-vindue" msgid "Army Actions" msgstr "Hær-handlinger" msgid "The save file is corrupted." msgstr "Det gemte spil er korrupt." msgid "Unsupported save format: " msgstr "Ikke-understøttet gem-format: " msgid "Current game version: " msgstr "Nuværende spilversion: " msgid "Last supported version: " msgstr "Sidste understøttede version: " msgid "This file contains a save with an invalid game type." msgstr "Denne fil indeholder et gemt spil af en invalid spiltype." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Den gemte fil kræver 'Prisen for loyalitet's spilaktiver, men de er ikke " "blevet leveret til spilmotoren." msgid "This saved game is localized to '" msgstr "Dette gemte spil er lokaliseret til '" msgid "' language, but the current language of the game is '" msgstr "' sprog, men spillets nuværende sprog er '" msgid "No save files to load." msgstr "Ingen gemte filer at indlæse." msgid "Hot Seat" msgstr "Lokalt spil" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Spil et lokalt spil, hvor 2-6 spillere skiftes til at spille sin tur pÃ¥ den " "samme enhed." msgid "A single player game playing out a single map." msgstr "Et enkeltspillerspil, der gennemspilles pÃ¥ ét enkelt kort." msgid "Standard Game" msgstr "Enkelt spil" msgid "A single player game playing through a series of maps." msgstr "Et enkeltspillerspil, der gennemspilles pÃ¥ en serie af kort." msgid "Campaign Game" msgstr "Felttog spil" msgid "Multi-Player Game" msgstr "Flerspiller spil" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Et flerspillerspil, hvor flere menneskelige spillere konkurrerer mod " "hinanden pÃ¥ ét enkelt kort." msgid "fheroes2 Resurrection Team presents" msgstr "Teamet bag fheroes2 Resurrection præsenterer" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Velkommen til Heroes of Might and Magic II, drevet af fheroes2-motoren!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Velkommen til Heroes of Might and Magic II, drevet af fheroes2-motoren!\n" "Vælg venligst den ønskede spilopløsning, før du starter et spil." msgid "Greetings!" msgstr "Vær hilset!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Afslut Heroes of Might and Magic II og vend tilbage til operativsystemet." msgid "Credits" msgstr "Kreditter" msgid "View the credits screen." msgstr "Se kreditskærmen." msgid "View the high scores screen." msgstr "Vis skærmen for højeste score." msgid "Create new or modify existing maps." msgstr "Modificer et eksisterende kort eller opret et nyt." msgid "Change language, resolution and settings of the game." msgstr "Skift spillets sprog, opløsning og indstillinger." msgid "Game Settings" msgstr "Spilindstillinger" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "De nødvendige videofiler til felttogsvalgsvinduet mangler. Sørg venligst for " "at alle nødvendige filer er til stede blandt systemfilerne." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Enten Rolands eller Archibalds felttog fra den originale Heroes of Might and " "Magic II." msgid "Original Campaign" msgstr "Originalt felttog" msgid "Expansion Campaign" msgstr "Udvidelse-felttog" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "En af de fire nye felttog fra Prisen for loyalitet-udvidelsessættet." msgid "Loading video. Please wait..." msgstr "Indlæser video. Vent venligst..." msgid "Host" msgstr "Vært" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Værten opsætter spilmulighederne. Der kan kun være én vært per netværksspil." msgid "Guest" msgstr "Gæst" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "Gæsten venter pÃ¥, at værten sætter spillet op, og tilføjes derefter " "automatisk. Der kan være flere gæster til TCP/IP-spil." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "For at kunne køre har fheroes2 brug for datafiler fra det originale Heroes " "of Might and Magic II. Du ser ud til at bruge demoversionen af Heroes of " "Might and Magic II til dette formÃ¥l. Bemærk venligst, at kun ét scenarie vil " "være tilgængeligt i denne opsætning." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Et flerspillerspil, hvor flere menneskelige spillere konkurrerer mod " "hinanden pÃ¥ ét enkelt kort." msgid "Battle Only" msgstr "Kun kamp" msgid "Setup and play a battle without loading any map." msgstr "Opsæt og spil en kamp uden at indlæse et kort." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Spil et lokalt spil, hvor 2-6 spillere spiller sin tur pÃ¥ den samme enhed, " "mens de skiftes til at sidde i \"det varme sæde\"." msgid "2 Players" msgstr "2 spillere" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Spil med 2 menneskelige spillere og eventuelt op til 4 ekstra " "computerspillere." msgid "3 Players" msgstr "3 spillere" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Spil med 3 menneskelige spillere og eventuelt op til 3 ekstra " "computerspillere." msgid "4 Players" msgstr "4 spillere" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Spil med 4 menneskelige spillere og eventuelt op til 2 ekstra " "computerspillere." msgid "5 Players" msgstr "5 spillere" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Spil med 5 menneskelige spillere og eventuelt 1 ekstra computerspillere." msgid "6 Players" msgstr "6 spillere" msgid "Play with 6 human players." msgstr "Spil med 2 menneskelige spillere." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Dragebyen er faldet! Du er nu dragernes mester!" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Du fangede %{name}!\n" "Du har sejret!" msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Du har fanget fjendens helt %{name}!\n" "Din opgave er fuldført!" msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Du har fundet %{name}!\n" "Din opgave er fuldført!" msgid "Ultimate Artifact" msgstr "Det Ultimative Artefakt" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Fjenden er slÃ¥et!\n" "Din side har sejret!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Du har akkumuleret over %{count} guldstykker i dit skatkammer.\n" "Alle fjender bøjer sig for din rigdom og magt!" msgid "Victory!" msgstr "Sejr!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Fjenden har erobret %{name}!\n" "De har sejret!" msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Fjenden har akkumuleret over %{count} guldstykker i sit skatkammer.\n" "Med dette nederlag skal du nu bøje dig for hans rigdom og magt!" msgid "You have been eliminated from the game!!!" msgstr "Du er blevet slÃ¥et ud af spillet!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Du har mistet helten %{name}.\n" "Fjendens opgave er fuldført!" msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Du fuldførte ikke din opgave i tide.\n" "Alt er tabt!" msgid "Defeat!" msgstr "Nederlag!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Grundscore: %{score}\n" "Niveau: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "Besejr alle fjendens helte og erobr alle fjendens borge og byer." msgid "Your side defeats the opposing side." msgstr "Din side besejrer den modsatte." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Løb tør for tid. (Du kan ikke vinde efter et bestemt antal dage)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Du skal besejre fjenden %{enemies}." msgstr[1] "Du skal besejre fjendens alliance af %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Alliancen bestÃ¥r af %{allies}, og du skal besejre fjenden %{enemies}." msgstr[1] "" "Alliancen bestÃ¥r af %{allies}, og du skal besejre fjendens alliance af " "%{enemies}." msgid "Capture the castle '%{name}'." msgstr "Erobr borgen '%{name}'." msgid "Capture the town '%{name}'." msgstr "Erobr byen '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Besejr helten '%{name}'." msgid "Find the ultimate artifact." msgstr "Find Det Ultimative Artefakt." msgid "Find the '%{name}' artifact." msgstr "Find artefaktet '%{name}'." msgid "Accumulate %{count} gold." msgstr "Akkumuler %{count} guldstykker." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", eller du kan vinde ved at besejre alle fjendens helte og erobre alle " "fjendens byer og borge." msgid "Lose the castle '%{name}'." msgstr "Mist borgen '%{name}'." msgid "Lose the town '%{name}'." msgstr "Mist byen '%{name}'." msgid "Lose the hero: %{name}." msgstr "Mist helten '%{name}'." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Du taber, hvis du ikke vinder inden udgangen af mÃ¥ned %{month}, uge%{week}, " "dag %{day}." msgid "%{color} player has been vanquished!" msgstr "%{color} spiller er blevet besejret!" msgid "Major Event!" msgstr "Stor begivenhed!" msgid "Scenario:" msgstr "Kort:" msgid "Game Difficulty:" msgstr "Spil-niveau:" msgid "Opponents:" msgstr "Spillere:" msgid "Class:" msgstr "Klasse:" msgid "Rating %{rating}%" msgstr "Bedømmelse %{rating}%" msgid "Click here to select which scenario to play." msgstr "Klik her for at vælge, hvilket kort du vil spille pÃ¥." msgid "Scenario" msgstr "Kort" msgid "Game Difficulty" msgstr "Spil-niveau" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Dette lader dig ændre start-niveau, som du vil spille pÃ¥. Højere niveauer " "giver dig færre resurser at starte med, mens AI-spillere til gengæld fÃ¥r " "ekstra resurser at starte med." msgid "Difficulty Rating" msgstr "Niveau-bedømmelse" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Sværhedsgraden afspejler en kombination af forskellige indstillinger for dit " "spil. Dette tal vil blive anvendt pÃ¥ din endelige score." msgid "Click to accept these settings and start a new game." msgstr "Klik for at acceptere disse indstillinger og start et nyt spil." msgid "Click to return to the main menu." msgstr "Klik her for at vende tilbage til hovedmenuen." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Astrologer kundgør, at mÃ¥nedens væsen er %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Astrologer kundgør, at ugens væsen er %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "Efter regelmæssig tilvækst er befolkningen pÃ¥ %{monster} fordoblet!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Efter regelmæssig tilvækst stiger befolkningen af %{monster} med %{count} " "procent!" msgstr[1] "" "Efter regelmæssig vækst stiger befolkningen af %{monster} med %{count} " "procent!" msgid "%{monster} growth +%{count}." msgstr "" "Tilvækst: +%{count}\n" "%{monster}" msgid " All populations are halved." msgstr "Hele befolkningen er halveret." msgid " All dwellings increase population." msgstr "Alle bosteder fÃ¥r øget deres befolkning." msgid "New Month!" msgstr "Ny mÃ¥ned!" msgid "New Week!" msgstr "Ny uge!" msgid "Beware!" msgstr "Pas pÃ¥!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} spiller! Dette er din sidste dag til at erobre en by, ellers bliver " "du forvist fra dette land!" msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} spiller! Du har kun %{day} dage til at erobre en by, ellers bliver " "du forvist fra dette land!" msgid "%{color} player's turn." msgstr "%{color} spillers tur." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} spiller, du har mistet din sidste by. Hvis du ikke erobrer en anden " "by i løbet af én uge, vil du blive elimineret." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} spiller! Dine helte forlader dig og du bliver forvist fra dette " "land!" msgid "Lord Kilburn" msgstr "Fyrst Kilburn" msgid "Tsabu" msgstr "Sabu" msgid "Sir Galant" msgstr "Herr Galant" msgid "Thundax" msgstr "Thorøks" msgid "Lord Haart" msgstr "Fyrst Hjart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebekka" msgid "Sandro" msgstr "Sander" msgid "Crodo" msgstr "Krodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antonius" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatavne" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrosius" msgid "Troyan" msgstr "Trojan" msgid "Jojosh" msgstr "Joshua" msgid "Wrathmont" msgstr "Vredeberg" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "Næste helt" msgid "Select the next Hero." msgstr "Vælg næste helt." msgid "Hero Movement" msgstr "Heltebevægelse" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "Begynd heltens bevægelse langs den nuværende sti eller foretag et genbesøg " "ved det objekt, som helten stÃ¥r ved. Hold denne knap nede, for at nulstille " "heltens sti." msgid "Kingdom Summary" msgstr "Oversigt over kongedømmet" msgid "View a summary of your Kingdom." msgstr "Se en oversigt over dit kongerige." msgid "Cast an adventure spell." msgstr "Kast en eventyrbesværgelse" msgid "End Turn" msgstr "End tur" msgid "End your turn and let the computer take its turn." msgstr "End din tur og lad computeren spille sin." msgid "Adventure Options" msgstr "Eventyrindstillinger" msgid "Bring up the adventure options menu." msgstr "Frembring menuen for eventyrindstillingerne." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Frembring filindstillingsmenuen, som tillader dig at indlæse, gemme, starte " "et nyt spil eller afslutte." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Frembring menuen for systemindstillingerne, sÃ¥ du kan tilpasse dit spil." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "En eller flere helte kan stadig ride. Er du sikker pÃ¥ at du vil ende din tur?" msgid "Are you sure you want to quit?" msgstr "Er du sikker pÃ¥ om du vil afslutte?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Er du sikker pÃ¥, om du vil indlæse et nyt spil? (Dit nuværende spil vil gÃ¥ " "tabt.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Er du sikker pÃ¥, om du vil overskrive det gemte spil med dette navn?" msgid "Game saved successfully." msgstr "Spillet blev gemt." msgid "There was an issue during saving." msgstr "Mens spillet forsøgtes gemt, opstod der et problem." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Er du sikker pÃ¥, om du vil indlæse et nyt spil? (Dit nuværende spil vil gÃ¥ " "tabt.)" msgid "Try looking on land!!!" msgstr "Prøv at søge pÃ¥ land!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "At søge efter Det Ultimative Artefakt er frugtesløst. Din helt kunne ikke " "bære den, selvom han fandt den - alle hans artefaktpladser er fulde." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "At grave efter artefakter kræver en hel dag. Prøv igen i morgen." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Efter at have brugt mange timer pÃ¥ at grave her, finder du endelig " "%{artifact}." msgid "Congratulations!" msgstr "TILLYKKE!!!" msgid "Nothing here. Where could it be?" msgstr "Intet her. Hvor kan den være?" msgid "Try searching on clear ground." msgstr "Prøv at søge pÃ¥ et bart omrÃ¥de." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Et miniaturebillede af den kendte verden. Venstre klik for at flytte " "visningsomrÃ¥de." msgid "Month: %{month} Week: %{week}" msgstr "MÃ¥ned: %{month} Uge: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Du fandt en lille\n" "mængde %{resource}." msgid "Status Window" msgstr "Statusvindue" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Dette vindue giver information om status pÃ¥ din helt eller dit rige og viser " "datoen." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Dette vindue giver information om status pÃ¥ din helt eller dit rige og viser " "datoen. Venstre klik her for at bladre gennem disse vinduer." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Dette lader dig ændre spillerens startpositioner og farver. En bestemt farve " "starter altid pÃ¥ et bestemt sted. Nogle positioner kan kun spilles af en " "computerspiller eller kun af en menneskelig spiller." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Dette lader dig ændre en spillers klasse. Klasser er ikke altid " "udskiftelige. Afhængigt af scenariet kan en spiller modtage yderligere byer " "og/eller helte, der ikke er i deres primære linje." msgid "Handicap" msgstr "Handicap" msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Dette lader dig ændre handicappet for en bestemt spiller. Kun menneskelige " "spillere mÃ¥ have et handicap. Handicappede spillere starter med færre " "resurser og tjener 15 eller 30% færre resurser pr. omgang for henholdsvis " "milde og svære handicap." msgid "%{color} player" msgstr "%{color} spiller" msgid "No Handicap" msgstr "Intet handicap" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Ingen særlige begrænsninger for startresurser og resurseindkomst af per tur." msgid "Mild Handicap" msgstr "Mildt handicap" msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Spillere med mildt handicap starter med færre resurser og tjener 15% færre " "resurser per tur." msgid "Severe Handicap" msgstr "Svært handicap" msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Spillere med alvorligt handicap starter med færre resurser og tjener 30% " "færre resurser per tur." msgid "" "Default\n" "value" msgstr "" "standard\n" "værdi" msgid "Set %{skill} Skill" msgstr "Indstil %{skill} Evne" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "Indstil %{skill} startværdi. Højreklik: Nulstil evner til standard." msgid "View %{skill} Info" msgstr "Vis info om %{skill}" msgid "" "Default\n" "skill" msgstr "" "standard\n" "evne" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "MELLEMRUM" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Kongerigets indkomst" msgid "Kingdom Income per day." msgstr "Kongerigets daglige indkomst" msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "For hvert fyrtÃ¥rn, der kontrolleres, kan dine skibe sejle længere om dagen." msgid "English" msgstr "Engelsk" msgid "French" msgstr "Fransk" msgid "Polish" msgstr "Polsk" msgid "German" msgstr "Tysk" msgid "Russian" msgstr "Russisk" msgid "Italian" msgstr "Italiensk" msgid "Czech" msgstr "Tjekkisk" msgid "Norwegian" msgstr "Norsk" msgid "Belarusian" msgstr "Hviderussisk" msgid "Bulgarian" msgstr "Bulgarisk" msgid "Ukrainian" msgstr "Ukrainsk" msgid "Romanian" msgstr "Rumænsk" msgid "Spanish" msgstr "Spansk" msgid "Swedish" msgstr "Svensk" msgid "Portuguese" msgstr "Portugisisk" msgid "Turkish" msgstr "Tyrkisk" msgid "Dutch" msgstr "Hollandsk" msgid "Hungarian" msgstr "Ungarnsk" msgid "Danish" msgstr "Dansk" msgid "Slovak" msgstr "Slovensk" msgid "Vietnamese" msgstr "Vietnamesisk" msgid "Slow" msgstr "Langsom" msgid "Fast" msgstr "Hurtig" msgid "Very Fast" msgstr "Meget hurtig" msgid "Evil" msgstr "Ond" msgid "Good" msgstr "God" msgid ", FPS: " msgstr ", FPS:" msgid "shipAndGraveyard|%{object} robber" msgstr "%{object}srøver" msgid "pyramid|%{object} raided" msgstr "%{object} plyndret" msgid "Ector" msgstr "Hektor" msgid "Gwenneth" msgstr "Lykke" msgid "Sir Gallant" msgstr "Herr Gallant" msgid "Tyro" msgstr "Tyr" msgid "Dimitry" msgstr "Dimitri" msgid "Ruby" msgstr "Rubin" msgid "Crag Hack" msgstr "Lars Hug" msgid "Fineous" msgstr "Fineas" msgid "Jezebel" msgstr "Izabel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Egon" msgid "Jaclyn" msgstr "Jakobine" msgid "Gem" msgstr "Perle" msgid "Natasha" msgstr "Natasja" msgid "Carlawn" msgstr "Karlana" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastor" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dagny" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Mira" msgid "Myrini" msgstr "Myrine" msgid "Wilfrey" msgstr "Vilfred" msgid "Mandigal" msgstr "Mandalei" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Godemine" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranlov" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxanne" msgid "Lord Corlagon" msgstr "Fyrst Korlagon" msgid "Lord Halton" msgstr "Fyrst Halton" msgid "Sister Eliza" msgstr "Søster Eliza" msgid "Brother Brax" msgstr "Bror Braks" msgid "Dainwin" msgstr "Dejnvin" msgid "Joseph" msgstr "Josef" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ketil" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Oldrian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Harkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " giver dig maksimal moral" msgid " gives you maximum luck" msgstr " giver dig maksimalt held" # "You can't have multiple spell books" will have ambiguous meanings. It could mean that you can't have more than you already have. msgid "You cannot have multiple spell books." msgstr "Du kan kun have én Magibog." msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Du kan ikke opsamle denne artefakt, da du allerede har fuld last!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "For at kaste besværgelser, mÃ¥ du først købe en magibog. Den koster %{gold} " "guldstykker." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Desværre ser det ud til, at du mangler kontanter i øjeblikket." msgid "Do you wish to buy one?" msgstr "Ønsker du at købe én?" msgid "%{count} / day" msgstr "%{count} / dag" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "En hvirvelstrøm opsluger dit skib. Noget af din hær er faldet over bord." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Fornærmet over din afvisning af deres tilbud, angriber væsenerne!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "Disse %{monster} beundres ved synet af din mægtige hær og begynder at sprede " "sig.\n" "Ønsker du at forfølge og gÃ¥ pÃ¥ dem?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "Idet du ransager en fjendelejr, opdager du en skjult skat." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Mølleren annoncerer:\n" "\"Deres excellence, jeg har arbejdet hÃ¥rdt for at skaffe Dem disse resurser. " "FÃ¥ mere ved at komme igen i næste uge.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Mølleren annoncerer:\n" "\"Deres excellence, jeg beklager, der er ingen resurser at hente i " "øjeblikket. Prøv at vende tilbage i næste uge.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Mølleren annoncerer:\n" "\"Deres excellence, jeg har arbejdet hÃ¥rdt for at skaffe Dem disse " "guldstykker. FÃ¥ mere ved at komme igen i næste uge.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Mølleren annoncerer:\n" "\"Deres excellence, jeg beklager, der er intet guld at hente i øjeblikket. " "Prøv at vende tilbage i næste uge.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Du har fundet et forladt shelter.\n" "Idet du roder rundt, opdager du nogle resurser gemt i nærheden." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "Shelteret er for længst forladt. Der er intet af værdi her." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Du fanger en tÃ¥belig alf i at sove mellem en samling magiske svampe.\n" "I bytte for sin frihed, viser han dig vejen til en lille potte fyldt med " "værdigenstande." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Du finder en magisk have, den slags haver som feer og alfer kan lide at " "boltre sig i. Men der er ingen her at finde i dag.\n" "MÃ¥ske du skulle prøve igen i næste uge." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Du støder pÃ¥ resterne af en uheldig eventyrer." msgid "Treasure" msgstr "Skat" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Du gennemsøger det lasede tøj og finder %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Du gennemsøger det lasede tøj, men finder intet af værdi." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Du støder pÃ¥ en gammel vogn efterladt af en handelsmand, der ikke helt nÃ¥ede " "til sikkert terræn." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Desværre har andre fundet den først, og vognen er tom." msgid "Searching inside, you find the %{artifact}." msgstr "Indenfor kigger du søgende rundt. Du finder %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Indeni vognen er noget af dens last stadig intakt." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Du undersøger vraggodset og finder noget træ og guld." msgid "You search through the flotsam, and find some wood." msgstr "Du undersøger vraggodset og finder noget træ." msgid "You search through the flotsam, but find nothing." msgstr "Du gennemsøger vraggodset, men du finder intet af værdi." msgid "Shrine of the 1st Circle" msgstr "Helligdom af den 1. cirkel" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Du støder pÃ¥ en lille helligdom, der overværes af en gruppe præstelærlinge.\n" "Til gengæld for din beskyttelse, er de enige om at lære dig en simpel " "besværgelse - '%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Helligdom af den 2. cirkel" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Du støder pÃ¥ en udsmykket helligdom, der overværes af en gruppe runde " "munke.\n" "Til gengæld for din beskyttelse, er de enige om at lære dig en simpel " "besværgelse - '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Helligdom af den 3. cirkel" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Du støder pÃ¥ en overdÃ¥dig helligdom, der overværes af en gruppe højpræste.\n" "Til gengæld for din beskyttelse, er de enige om at lære dig en simpel " "besværgelse - '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Desværre har du ikke visdom til at forstÃ¥ besværgelsen, og du er ikke i " "stand til at lære den." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Desværre kender du allerede til denne besværgelse, sÃ¥ der er ikke mere de " "kan lære dig." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Desværre har du ingen magibog, at nedskrive besværgelsen i." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Du nærmer dig hytten og observerer en heks indenfor, som studerer et " "ældgammelt bind om %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Idet du nærmer dig, vender hun sig om og retter sit glasøje mod dig.\n" "\"Du ved allerede alt hvad du fortjener at lære!\" hviner heksen. \"OG " "FORSVIND SÃ… FRA MIT HJEM!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Idet du nærmer dig, vender hun sig om og siger:\n" "\"Du evner allerede det, som jeg ville have lært dig at kunne. Jeg kan ikke " "hjælpe dig.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "I en hytte med stolper af enorme fugleben lever en udødelig og ældgammel " "heks. Af sine egne uransagelige Ã¥rsager lærer hun dig %{skill}." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "Du drikker det søde vand og vinder held til dit næste slag." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Du drikker af det fortryllede springvand, men der sker ikke noget." msgid "You enter the faerie ring, but nothing happens." msgstr "Du gÃ¥r ind i fe-ringen, men der sker ikke noget." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Idet du gÃ¥r ind i den mystiske fe-ring, vinder din hær held til det næste " "slag." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Du har fundet et gammelt og forvitret stenidol.\n" "Det er meningen, at det skal give held til besøgende, men da stjernerne " "allerede smiler til dig, gør det ingenting." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Du har fundet et gammelt og forvitret stenidol.\n" "Det siges at bringe held, hvis man kysser pÃ¥ den. SÃ¥ det gør du. Stenen er " "meget kold at røre ved." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Havfruerne lokker dig lydløst til at vende tilbage senere, for igen at blive " "velsignet." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Du og dit mandskab beskuer havfruernes magiske, beroligende skønhed.\n" "For en stund, glemmer du dine bekymringer og soler dig i øjeblikkets " "skønhed.\n" "Havfruernes tryllesange velsigner dig med øget held til din næste kamp." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Du kommer forbi pyramiden af en stor og gammel konge.\n" "Du er fristet til at søge efter skatte, men alle gamle fortællinger advarer " "om frygtsomme forbandelser og udøde vogtere.\n" "Vil du søge alligevel?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "NÃ¥r du besejrer monstrene, tyder du en gammel glyf pÃ¥ væggen, som afslører " "besværgelsens hemmelighed - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Desværre har du ingen magibog, at nedskrive besværgelsen i." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Desværre har du ikke visdom til at forstÃ¥ besværgelsen, og du er ikke i " "stand til at lære den." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Du kommer forbi pyramiden af en stor og gammel konge.\n" "En rutinemæssig udforskning afslører, at pyramiden er helt tom." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Drikken af denne brønd skulle gerne genopfylde din mana, men det er allerede " "fuldt." msgid "A second drink at the well in one day will not help you." msgstr "Drikken af denne brønd virker ikke to gange pÃ¥ samme dag." msgid "A drink from the well has restored your spell points to maximum." msgstr "Drikken fra denne brønd genopfylder din mana." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Jeg er ked af det herre,\" siger soldaterlederen, \"men du ved allerede " "alt, hvad vi kunne have lært dig.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "Soldaterne, der bor i fortet, lærer dig et par nye defensive tricks." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Du er stødt pÃ¥ en lejesoldatslejr, der øver deres taktiske evner. \"Dine " "evner overgÃ¥r vores egne,\" siger lejesoldatskaptajnen. \"Vi kan ikke lære " "dig mere.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Du er stødt pÃ¥ en lejesoldatslejr, der øver pÃ¥ deres taktik. Lejetropperne " "byder dig og dine tropper velkommen og inviterer dig til at træne sammen med " "dem." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"GÃ¥ væk!\", bjæffer heksedoktoren, \"du ved alt, hvad jeg ved.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "En orkisk heksedoktor, der bor i hytten, gør din viden om magi dybere, ved " "at vise dig, hvordan du kaster sten, læser varsler og tyder forviklingerne " "af kyllingeindvolde." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Du har fundet en gruppe druider, i færd med en gudstjeneste ved en af deres " "sære bygningsværker af sten. Tavse afviser druiderne dig, hvilket indikerer, " "at de ikke har noget nyt at lære dig." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Du har fundet en gruppe druider, i færd med en gudstjeneste ved en af deres " "sære bygningsværker af sten. Tavse lærer de dig nye mÃ¥der at kaste " "besværgelser pÃ¥." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Foreløbigt nærmer du dig gravpladsen for gamle krigere. Vil du gennemsøge " "gravene?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Du bruger flere timer pÃ¥ at gennemsøge gravene, men du finder intet af " "værdi. En sÃ¥ foragtelig handling reducerer din hærs moral." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "Efter besejringen af zombierne, gennemsøger du gravene og finder noget!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Det rÃ¥dnende skrog af et stort piratskib knirker uhyggeligt, nÃ¥r det skubbes " "mod klipperne. Ønsker du at gennemsøge skibsvraget?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Du bruger flere timer pÃ¥ at gennemrode vragresterne, men du finder intet af " "værdi. En sÃ¥dan foragtelig handling reducerer din hærs moral." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" "Efter besejringen af spøgelserne, gennemroder du vragresterne og finder " "noget!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Det rÃ¥dnende skrog af et stort piratskib knirker uhyggeligt, nÃ¥r det skubbes " "mod klipperne. Ønsker du at gennemsøge skibet?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "Efter besejringen af skeletterne, gennemroder du vragresterne og finder " "noget!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Dine mænd opdager en navigationsbøje, der bekræfter, at du er pÃ¥ rette vej." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Dine mænd opdager en navigationsbøje, der bekræfter, at du er pÃ¥ rette vej " "og øger deres moral." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Drikken fra oasen er forfriskende, men giver ingen yderligere fordele. Det " "hjælper mÃ¥ske, igen, hvis du udkæmper en kamp først." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Drikken fra oasen fylder dine tropper med styrke og løfter deres humør. Du " "kan ride lidt længere i dag." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Drikken fra vandhullet er forfriskende, men giver ingen yderligere fordele. " "Det hjælper mÃ¥ske, igen, hvis du udkæmper en kamp først." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Drikken fra vandhullet fylder dine tropper med styrke og løfter deres humør. " "Du kan ride lidt længere i dag." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Det hjælper ikke at bede to gange før en kamp. Kom tilbage efter du har " "kæmpet." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Et besøg og en bøn i templet hæver moralen hos dine tropper." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "En gammel ridder dukker op pÃ¥ trappen til lysthuset. \"Jeg er ked af det, " "min herre, jeg har lært dig alt, hvad jeg kan.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "En gammel ridder dukker op pÃ¥ trappen til lysthuset. \"Min herre, jeg vil " "lære dig alt, hvad jeg ved, for at hjælpe dig pÃ¥ dine rejser.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Du har reddet en skibbruden fra den sikre død op fra et nÃ¥desløst hav. " "Taknemmelig, siger han, \"jeg ville give dig et artefakt som belønning, men " "du er fuldt oppakket.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Du har reddet en skibbruden fra den sikre død op fra et nÃ¥desløst hav. " "Taknemmelig, belønner han dig for din venlighed, ved at give dig %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "En alf tilbyder dig %{art} til den nette pris af %{gold} guldstykker." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "En alf tilbyder dig %{art} til den nette pris af %{gold} guldstykker og " "%{count} %{res}." msgid "Do you wish to buy this artifact?" msgstr "Ønsker du at købe denne artefakt?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Du prøver at betale alfen, men indser, at du ikke har rÃ¥d til det. " "Leprechaunen stamper med foden og ignorerer dig." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Fornærmet over dit afslag pÃ¥ hans generøse tilbud, stamper alfen med foden " "og ignorerer dig." msgid "You've found the artifact: " msgstr "Du har fundet artefaktet:" msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Du har fundet den ydmyge bolig for en visnet eremit. Eremitten fortæller " "dig, at han er villig til at give %{art} til den første vise person, han " "møder." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Du er stødt pÃ¥ en pensioneret soldats spartanske kvarter. Soldaten fortæller " "dig, at han er villig til at give %{art} videre til den første rigtige " "leder, han møder." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Du har mødt en sær person med en ugle siddende ovenpÃ¥ sin hat. Han fortæller " "dig, at han er villig til at give %{art}, hvis du har %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Du støder pÃ¥ et gammelt artefakt. Lige som du rækker ud efter den, springer " "en flok slyngler ud af krattet, for at beskytte deres stjÃ¥lne bytte." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Gennem en lysning observerer du et gammelt artefakt. Desværre er det " "bevogtet af en nærliggende %{monster}. Vil du udfordre væsenet %{monster} " "til kamp, for at fÃ¥ artefaktet?" msgid "Victorious, you take your prize, the %{art}." msgstr "Sejrrig, tager du din præmie, %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "Diskretion er den bedste del af tapperhed, og du beslutter dig for at undgÃ¥ " "denne kamp for i dag." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Efter at have brugt timevis pÃ¥ at prøve at fiske kisten op af havet, Ã¥bner " "du den og finder %{gold} guldstykker." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Efter at have brugt timevis pÃ¥ at prøve at fiske kisten op af havet, Ã¥bner " "du den og finder %{gold} guldstykker og %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Efter at have brugt timer pÃ¥ at prøve at fiske kisten op af havet, Ã¥bner du " "den, kun for at finde den tom." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Efter at have undersøgt omrÃ¥det, falder du over en hemmelig skattekiste. Du " "har to valg: Enten beholder du guldet for dig selv, eller ogsÃ¥ fordeler du " "guldet mellem dine undersÃ¥tter for nogle erfaringspoint. Hvad gør du?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Efter at have gennemsøgt omrÃ¥det, falder du over en skjult kiste, der " "indeholder %{gold} guldstykker." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Efter at have gennemsøgt omrÃ¥det, falder du over en skjult kiste, der " "indeholder det gamle artefakt %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Du støder pÃ¥ en bulet og plettet lampe, der ligger dybt i jorden. Ønsker du " "at gnide pÃ¥ lampen?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Dette alkymist laboratorium er nu under din kontrol. Den forsyner dit rige " "med %{count} mængde kviksølv om dagen." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Denne savmølle er nu under din kontrol. Den forsyner dit rige med %{count} " "mængde træ om dagen." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Denne malmmine er nu under din kontrol. Den forsyner dit rige med %{count} " "mængde malm om dagen." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Denne svovlmine er nu under din kontrol. Den forsyner dit rige med %{count} " "mængde svovl om dagen." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Denne krystalmine er nu under din kontrol. Den forsyner dit rige med " "%{count} mængde krystaller om dagen." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Denne juvelmine er nu under din kontrol. Den forsyner dit rige med %{count} " "mængde juveler om dagen." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Denne guldmine er nu under din kontrol. Den forsyner dit rige med %{count} " "guldstykker om dagen." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Fyret er nu under din kontrol, og alle dine skibe vil nu kunne sejle længere " "om dagen." msgid "You gain control of a %{name}." msgstr "Du fÃ¥r kontrol over en %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Du støder pÃ¥ en forladt guldmine. Minen ser ud til at være hjemsøgt. Vil du " "ind?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" "Du besejrer spøgelserne og er i stand til at genoprette minens produktion." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "En gruppe %{monster}, med et ønske om større ære, vil gerne tilslutte sig " "til din hær. Accepterer du?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Idet du nærmer dig bostedet, bemærker du, at der ikke er nogen hjemme." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Du søger i ruinerne, men de medusaer, der plejede at bo her, er væk. MÃ¥ske " "kommer der flere i næste uge." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Du har fundet nogle medusaer, der bor i ruinerne. De vil gerne tilslutte sig " "din hær, men for en pris. Vil du rekruttere medusaer?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Du har fundet en fe-træby. Desværre er der ingen af de feer, der bor der, " "som ønsker at tilslutte sig din hær. MÃ¥ske i næste uge." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Nogle af de feer, der bor i træbyen, vil gerne tilslutte sig din hær, men " "for en pris. Vil du rekruttere feer?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "En farverig slyngelvogn stÃ¥r tom her. MÃ¥ske er der flere slyngler tilstede " "her senere." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Fjerne lyde af musik og latter drager dig hen til en farverig vogn, hvor " "slyngler bor. Ønsker du at lade nogle slyngler tilslutte sig din hær?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "En gruppe af lasede telte, der bølger i sandvinden, lokker dig. Teltene er " "ubesatte. MÃ¥ske er der flere nomader tilstede her senere." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "En gruppe af lasede telte, der bølger i sandvinden, lokker dig. Vil du have " "nogen nomader med dig pÃ¥ dine rejser?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Mudderhullet bobler et minuts tid og ligger derefter stille." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Idet du nærmer dig det boblende mudderhul, begynder væsner at kravle ud og " "placere sig omkring den. I kor siger de: \"Moder Jord vil gerne tilbyde dig " "et par af sine tropper. Vil du rekruttere Jord-elementaler?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" "Du gÃ¥r ind i en bygning af hvide stensøjler, men du finder intet af værdi." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Hvide stensøjler understøtter et tag, som strækker sig op mod himlen. Da du " "træder ind i bygningen, giver den døde luft udefra plads til et hvirvlende " "vindstød, der næsten skubber dig ud igen. Luftstrømmen materialiserer sig i " "en knap synlig form. Væsenet spørger, i hvad der kun kan beskrives som en " "høj hvisken: \"Hvorfor er du kommet? Er du her for at kalde pÃ¥ luftens " "kræfter?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Ingen ild-elementaler gÃ¥r dig i møde fra lavasøen." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Under en bygning, der tjener til at holde pÃ¥ varmen, bevæger ild-" "elementalerne sig rundt i en brændende sø af smeltet lava. En gruppe af dem " "henvender sig til dig og melder sig til tjeneste. Ønsker du tænke dig at " "rekruttere ild-elementaler?" msgid "A face forms in the water for a moment, and then is gone." msgstr "For et øjeblik formes et ansigt i vandet, og sÃ¥ forsvinder det igen." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Krystallinske bygninger kaster skygger over en lille reflekterende sø af " "vand. Du kigger ned i søen, og et ansigt, der ikke er dit eget, ser tilbage " "pÃ¥ dig. Ansigtet spørger: \"Vil du kalde pÃ¥ vandets kræfter?\"" msgid "This burial site is deathly still." msgstr "Dette gravsted er dødstille." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Rastløse Ã¥nder af for længst afdøde krigere, der søger deres sidste " "hvilested, tilbyder at tilslutte sig din hær i hÃ¥b om at finde fred. Ønsker " "du at rekruttere spøgelser?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "De dødes by er tom for liv og ogsÃ¥ tom for 'uliv'. MÃ¥ske flytter nogle udøde " "ind i næste uge." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Nogle kraftlicher, der bor her, vil gerne tilslutte sig din hær, men for en " "pris. Vil du rekruttere kraftlicher?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Du har fundet ruinerne af en ældgammel by, som nu udelukkende er beboet af " "udøde. Vil du gerne udforske den?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Nogle af de overlevende kraftlicher er imponerede over din sejr over deres " "kammerater og tilbyder at tilslutte sig din hær, men for en pris. Vil du " "rekruttere kraftlicher?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Du har fundet en af de broer, som trolde er sÃ¥ glade for at bo under, men " "her er ingen. MÃ¥ske kommer der nogle i næste uge." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Nogle trolde, der bor under broen, vil gerne tilslutte sig din hær, men for " "en pris. Vil du rekruttere trolde?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "Trolde, der bor under broen, udfordrer dig. Vil du bekæmpe dem?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Der er nogle fÃ¥ trolde tilbage, som kryber sammen under broen. De henvender " "sig til dig og tilbyder at tilslutte sig din hær som lejesoldater. Vil du " "rekruttere nogle trolde?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "I denne uge er der ingen røddrager i Dragebyen, der vil tilslutte sig din " "hær. MÃ¥ske bliver en røddrage tilgængelig i næste uge." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Dragebyens røddrager vil gerne tilbyde dig, at lade nogle af dem tilslutte " "sig din hær, men for en pris. Ønsker du at rekruttere røddrager?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Du stÃ¥r foran Dragebyen, et sted, som er forbudt omrÃ¥de for almindelige " "mennesker. Ønsker du at overtræde denne regel og udfordre dragerne til kamp?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Efter at have besejret dragemestrene, er byens ledere enige om at lade nogle " "røddrager tilslutte sig din hær, men for en pris. Ønsker du at rekruttere " "røddrager?" msgid "From the observation tower, you are able to see distant lands." msgstr "Fra udsigtstÃ¥rnet er du i stand til at se fjerne lande." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Springvandet genopfyldes kun en gang om ugen, og nogen har allerede været " "her i denne uge." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Drikken af springvandet skulle gerne give dig to gange dit maksimale mana i " "reserve, men det har du allerede." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Drikken af springvandet fylder dit blod med magi! Du har nu to gange dit " "maksimale mana i reserve." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Butleren genkender dig, men nægter at lade dig blive optaget. \"Mesteren,\" " "siger han, \"vil ikke se den samme elev to gange.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Butleren tillader dig at se herren i huset. Herren træner dig indenfor de " "fire evner, enhver helt bør kende." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Butleren Ã¥bner døren og ser op og ned af dig. \"Du er hverken berømt eller " "diplomatisk nok til at blive optaget til at se min herre,\" fnyser han. " "\"Kom tilbage, nÃ¥r du finder dig værdig.\"" msgid " and " msgstr " og " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Alle de %{monsters}, du har i din hær, er blevet trænet af fortets " "kampmestre. Disse er nu blevet til %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "En usædvanlig alliance af jætter, orker og dværge tilbyder at træne " "(opgradere) samme slags tropper, der bringes hertil. Desværre har du ingen " "med dig." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Alle dine %{monsters} er blevet opgraderet til %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "En smed, der arbejder pÃ¥ støberiet, tilbyder at omdanne alle pikenéres og " "sværdkæmperes vÃ¥ben, som bringes til ham, fra jern til stÃ¥l. Han siger ogsÃ¥, " "at han kender en proces, der vil omskabe jerngolemmer til stÃ¥lgolemmer. " "Desværre har du ingen af de nævnte tropper i din hær, sÃ¥ han kan ikke hjælpe " "dig." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Kaptajnen kigger overrasket pÃ¥ dig og siger:\n" "\"Du har allerede alle de kort, jeg kender til. Lad mig nu fiske i fred.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "En pensioneret kaptajn, der bor pÃ¥ denne renoverede fiskeplatform, tilbyder " "at sælge dig et komplet kort over havet fra hans yngre dage. Han tilbyder " "dig at købe det for 1.000 guldstykker. \n" "Ønsker du at købe kortet?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Kaptajnen sukker. \"Du har ikke penge nok, hva'? Du kan ikke forvente, at " "jeg giver mine søkort væk gratis!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Du støder pÃ¥ en obelisk lavet af en type sten, du aldrig før har set. Du " "stirrer intenst pÃ¥ det, mens den glatte overflade pludselig ændrer sig til " "en inskription. Indskriften viser et stykke af et tabt ældgammelt kort. " "Hurtigt skriver du stykket af, og inskriptionen forsvinder lige sÃ¥ brat, som " "den dukkede frem." msgid "You have already been to this obelisk." msgstr "Du har allerede været pÃ¥ denne obelisk." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Idet du nærmer dig, Ã¥bner træet glad sine øjne. \"Det er godt at se dig, min " "elev. Jeg hÃ¥ber, at min lære har hjulpet dig.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Idet du nærmer dig, Ã¥bner træet glad sine øjne. \"Ahh, en eventyrer! Tillad " "mig at lære dig lidt af det, jeg har lært gennem tiderne.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Idet du nærmer dig, Ã¥bner træet glad sine øjne." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ahh, en eventyrer! Jeg vil med glæde lære dig lidt af det, jeg har lært " "gennem tiderne for blot %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Begrav det bare omkring mine rødder.)" msgid "Tears brim in the eyes of the tree." msgstr "Træet fÃ¥r tÃ¥rer i øjnene." msgid "\"I need %{count} %{res}.\"" msgstr "\"Jeg har brug for %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "det hvisker. (snif) \"NÃ¥, kom tilbage, nÃ¥r du kan betale mig.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "En blind seer sidder og putter sig blandt træerne. Efter du har forklaret " "hensigten med din rejse, aktiverer seeren sin krystalkugle, sÃ¥ du kan se " "dine modstanderes styrker og svagheder." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Indgangen til hulen er mørk, og der kommer en grim, svovlholdig lugt fra " "hulens gab. \n" "Vover du at gÃ¥ derind?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Bortset fra tegn pÃ¥ en frygtelig kamp, er hulen tom." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Du finder en mægtig og grotesk dæmon i hulen. \"I dag,\" rasper den, \"skal " "du kæmpe og uden tvivl dø. Men hvordan du skal dø, vil jeg lade dig vælge. \n" "Du kan kæmpe mod mig, eller du kan kæmpe mod mine tjenere. \n" "Foretrækker du at kæmpe mod mine tjenere?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Dæmonen skriger udfordrende og angriber! Efter en kort, desperat kamp dræber " "du monsteret og modtager %{exp} erfaringspoint." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Dæmonen skriger udfordrende og angriber! Efter en kort, desperat kamp dræber " "du monsteret og modtager %{exp} erfaringspoint og %{count} guldstykker." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Dæmonen skriger udfordrende og angriber! Efter en kort, desperat kamp dræber " "du monsteret og finder artefaktet %{art} bagerst i hulen." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Da dæmonen indser, at du ikke har %{count} guldstykker, hugger den dig med " "sine kløer, og det sidste, du ser, er en rød tÃ¥ge." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Dæmonen springer pÃ¥ dig og dens kløer er om din strube, før du overhovedet " "nÃ¥r at trække dit sværd. \"Du er min,\" hvæser den. \"Men jeg vil lade dig " "gÃ¥ med livet i behold for %{count} guldstykker.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Efter at have besejret dæmonens tjenere, finder du et skjult lager med " "%{count} guldstykker i." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "NÃ¥r du træder ind i alkymisttÃ¥rnet, kommer en humpende, grÃ¥nende mand i en " "brun kappe hen imod dig." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Han tjekker din sæk og ser, at du har 1 forbandet artefakt." msgstr[1] "" "Han tjekker din sæk og ser, at du har %{count} forbandede artefakter." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "For %{gold} guldstykker vil alkymisten fjerne det for dig. Vil du betale?" msgstr[1] "" "For %{gold} guldstykker vil alkymisten fjerne dem for dig. Vil du betale?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Efter at have givet samtykke til at betale den ønskede mængde guld, griber " "alkymisten det forbandede artefakt og smider den i sin magiske kedel." msgstr[1] "" "Efter at have givet samtykke til at betale den ønskede mængde guld, griber " "alkymisten de forbandede artefakter og smider dem i sin magiske kedel." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Du hører en stemme bag den lÃ¥ste dør, \"Du har ikke guld nok til at betale " "for mine tjenester.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Du hører en stemme fra højt oppe i tÃ¥rnet, \"GÃ¥ væk! Jeg kan ikke hjælpe dig!" "\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Overstaldkarlen taler til dig: \"Det er en flot hest, du har. Jeg er bange " "for, at vi ikke kan give dig noget bedre, men de heste, dine ryttere rider " "pÃ¥, ser ud til at være af dÃ¥rlig avlsbestand. Vi har mange trænede " "krigsheste, som virkelig kunne gavne dine ryttere at bruge. Jeg insisterer " "pÃ¥, at du tager dem.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Da du nærmer dig stalden, dukker overstaldskarlen op, mens han fører en flot " "krigshest. \"Denne hingst vil hjælpe dig med at rejse længere om dagen. Ak, " "han bliver dog træt inden ugen er omme. \n" "Du skal ogsÃ¥ lade mig give bedre heste til dine ridende soldater, deres " "heste ser sjuskede og svage ud.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Overstaldkarlen taler til dig: \"Du har allerede en fin hest og har ingen " "uerfarne ryttere, som kan gøre brug af vores trænede krigsheste.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Da du nærmer dig stalden, dukker overstaldkarlen op, mens han fører en flot " "krigshest. \"Denne hingst vil hjælpe dig med at fremskynde dig pÃ¥ dine " "rejser. Ak, hans udholdenhed vil aftage, inden ugen er omme.\n" "Vi har ogsÃ¥ mange fine krigsheste, som kunne gavne beredne soldater, men du " "har ingen, vi kan hjælpe.\"" msgid "The Arena guards turn you away." msgstr "Arena-vagterne afviser dig." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Du fÃ¥r dit mandskab til at stoppe deres ører med voks, før sirenernes " "uhyggelige sang har nogen chance for at lokke dem til en vandig grav." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Mens sirenerne synger deres uhyggelige sang, formÃ¥r din lille, beslutsomme " "hær at overvinde trangen til at springe hovedkulds i havet." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "En uhyggelig klagesang udgÃ¥r fra sirenerne, der ligger pÃ¥ klipperne. Mange " "af dit mandskab falder under dens fortryllelse og dykker ned i vandet, hvor " "de drukner. Du er nu klogere ved dette besøg, og fÃ¥r %{exp} erfaringspoint." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "I en blændende demonstration af vovemod bryder du ind i det lokale fængsel " "og befrier helten, der er fængslet dér, og som til gengæld lover loyalitet " "over for din sag." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Du har allerede %{count} helte, og du mÃ¥ desværre efterlade fangen i dette " "fængsel, for at sygne hen i smerte i utallige dage." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Du træder ind i en vakkelvorn hytte og taler med spÃ¥manden, som bor der. Han " "fortæller dig om steder nær og fjern, som kan hjælpe dig pÃ¥ dine rejser." msgid "This eye seems to be intently studying its surroundings." msgstr "Dette øje ser ud til nøje at studere sine omgivelser." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Du støder pÃ¥ en kæmpe sfinks. Sfinksen forbliver underlig stille." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Jeg har en gÃ¥de til dig,\" siger sfinksen. \"Svar rigtigt, og du skal " "blive belønnet. Svar forkert, og du skal blive spist. \n" "Tager du imod udfordringen?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Sfinksen stiller dig følgende gÃ¥de:\n" "\n" "'%{riddle}'\n" "\n" "Dit svar?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Du gættede forkert,\" siger sfinksen og smiler. Sfinksen stryger mod dig " "med en pote og slÃ¥r dig til jorden. Endnu et slag fÃ¥r verden til at gÃ¥ i " "sort, og du ved ikke mere." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Sukkende siger den noget skuffede sfinks: \"Du har løst min gÃ¥de, sÃ¥ her er " "din belønning. Forsvind sÃ¥!\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "En magisk barriere stÃ¥r højt foran dig og blokerer din vej. Runer pÃ¥ buen " "siger,\n" "\"Sig nøgleordet, og du kan passere.\"\n" "Idet du siger det magiske nøgleord, opløses den glødende barriere i " "intetheden." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "En magisk barriere stÃ¥r højt foran dig og blokerer din vej. Runer pÃ¥ buen " "siger,\n" "\"Sig nøgleordet, og du kan passere.\"\n" "Du udtaler noget, men der sker intet." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Du gÃ¥r ind i teltet og ser en gammel kvinde stirre ind i en magisk ædelsten. " "Hun kigger op og siger:\n" "\"PÃ¥ mine rejser har jeg lært meget om mystisk magi. Et stort orakel lærte " "mig sine færdigheder. Jeg har svaret, du søger.\"" msgid "No spell book is present." msgstr "Der er ingen magibog at finde." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Denne besværgelse koster %{mana} mana. Du har ingen mana, sÃ¥ du kan ikke " "kaste den." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Denne besværgelse koster %{mana} mana. Du har kun %{point} mana, sÃ¥ du kan " "ikke kaste den." msgid "The spell was not found." msgstr "Besværgelsen blev ikke fundet." msgid "Only heroes can cast this spell." msgstr "Kun helte kan kaste denne magi." msgid "This hero is not able to cast adventure spells." msgstr "Denne helt er ikke i stand til at kaste eventyrmagi." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Din helt er for træt til at kaste denne besværgelse i dag. Prøv igen i " "morgen." msgid "This spell cannot be cast on a boat." msgstr "Denne besværgelse kan ikke kastes ombord pÃ¥ et skib." msgid "This spell can only be cast near an ocean." msgstr "Denne besværgelse kan kun kastes i nærheden af et hav." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Der er hverken et hav ved siden af helten eller nogen tilgængelige skibe at " "hidkalde." msgid "There are no boats available for this spell." msgstr "Der er ingen tilgængelige skibe at hidkalde." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Der er intet hav ved siden af helten, hvor denne besværgelse vil virke." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Du ejer ikke nogen by eller borg, der ikke i øjeblikket er besat af en helt. " "Denne besværgelse har ingen effekt." msgid "This hero is already in a town, so this spell will have no effect." msgstr "Denne helt er allerede i en by, sÃ¥ denne besværgelse har ingen effekt." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Den nærmeste by er %{town}.\n" "\n" "Denne by er besat af din helt %{hero}." msgid "This spell is already in effect." msgstr "Denne besværgelse er allerede trÃ¥dt i kraft." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Ingen modstander hverken har eller kan have nogen helt under deres kommando " "længere. At kaste denne besværgelse, vil ikke have nogen effekt." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Ingen modstander har en helt under deres kommando pÃ¥ nuværende tidspunkt. At " "kaste denne besværgelse vil ikke have nogen effekt." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Du skal være inden for %{count} mellemrum fra et væsen, før visions-" "besværgelsen kan virke." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Du skal stÃ¥ ved indgangen til en mine (savværker og alkymistlaboratorier " "tæller ikke med), for at kaste denne besværgelse." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Du skal først besejre spøgelserne, der vogter minen, for at kaste denne " "besværgelse." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Der er allerede mindst lige sÃ¥ mange elementaler, der bevogter minen, som " "denne helt kan generere. At kaste denne besværgelse vil ikke have nogen " "effekt." msgid "%{name} the %{race} (Level %{level})" msgstr "%{race}en %{name} (Level %{level})" msgid "Random hero (Level %{level})" msgstr "Tilfældig helt (Level %{level})" msgid "Random %{race} hero (Level %{level})" msgstr "Tilfældig helt af klassen %{race} (Level %{level})" msgid "Hero race:" msgstr "Helteklasse:" msgid "Are you sure you want to dismiss this Hero?" msgstr "Er du sikker pÃ¥, du vil bortvise denne helt?" msgid "Set custom Experience value. Current value is default." msgstr "Indstil tilpasset erfaringspointværdi. Nuværende værdi er standard." msgid "Change Experience value. Right-click to reset to default value." msgstr "Skift erfaringspointværdi. Højreklik: Nulstil til standardværdi." msgid "View Experience Info" msgstr "Vis erfaringsinfo" msgid "Set custom Spell Points value. Current value is default." msgstr "Indstil magipointværdi. Højreklik: Nulstil til standardværdi." msgid "Change Spell Points value. Right-click to reset to default value." msgstr "Skift magipointværdi. Højreklik: Nulstil til standardværdi." msgid "Set Spell Points value" msgstr "Indstil antal magipoint" msgid "View Spell Points Info" msgstr "Vis info om mana" msgid "Set patrol radius in tiles" msgstr "Indstil patruljeradius i feltantal" msgid "Enter hero's name" msgstr "Indtast heltens navn" msgid "Click to change race." msgstr "Klik for at skifte race." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Spredt' kampformation spreder heltens hær, fra top til bund pÃ¥ deres side " "af slagmarken, med mindst én tom plads mellem hver trop." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "'Gruppe'-kampformation samler heltens hær i midten af deres side af " "slagmarken." msgid "Exit Hero Screen" msgstr "Forlad helteskærm" msgid "You cannot dismiss a hero in a castle" msgstr "Du kan ikke bortvise en helt, som befinder sig i en borg." msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Afvisning af %{race}en %{name} er ifølge scenariet forbudt" msgid "Dismiss %{name} the %{race}" msgstr "Bortvis %{race}en %{name}" msgid "Show previous hero" msgstr "Vis forrige helt" msgid "Show next hero" msgstr "Vis næste helt" msgid "Set army combat formation to 'Spread'" msgstr "Sæt hærens kampformation til 'spredt'" msgid "Set army combat formation to 'Grouped'" msgstr "Sæt hærens kampformation til 'grupperet'" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "Indstil heltens artefakter. Højreklik: Fjern artefakt." msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "Indstil heltens sekundære evner. Højreklik: Fjern evne." msgid "Set hero's Army. Right-click to reset unit." msgstr "Indstil heltenes hær. Højreklik: Fjern trop." msgid "Set hero's portrait. Right-click to reset to default." msgstr "Indstil heltens portræt. Højreklik: Nulstil til standard." msgid "Click to change hero's name. Right-click to reset to default." msgstr "Klik for at ændre heltens navn. Højreklik: Nulstil til standard." msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "Helten patruljerer en radius pÃ¥ %{tiles} felter. Venstreklik: SlÃ¥ fra." msgid "Click to enable hero's patrol mode." msgstr "Klik for at aktivere heltens patruljetilstand." msgid "Blood Morale" msgstr "Blodsmoral" msgid "%{morale} Morale" msgstr "%{morale} moral" msgid "%{luck} Luck" msgstr "%{luck} held" msgid "Current Luck Modifiers:" msgstr "PÃ¥virkninger pÃ¥ held:" msgid "Current Morale Modifiers:" msgstr "PÃ¥virkninger pÃ¥ moral:" msgid "Entire army is undead, so morale does not apply." msgstr "Hele hæren er udød, sÃ¥ den pÃ¥virkes ikke af moral." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Nuværende erfaringspoint %{exp1}.\n" " Næste level %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Level %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} har i øjeblikket %{point} magipoint ud af et maksantal pÃ¥ %{max}. " "Maksantallet af magipoint er 10 gange heltens kundskabspoint. Af og til er " "det muligt for helten, at have mere end deres maksantal magipoint via " "særlige begivenheder." msgid "%{name1} meets %{name2}" msgstr "%{name1} møder %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Fjendtlige helte er nu fuldt identificerbare." msgid "Identify Hero" msgstr "Identificer helt" msgid "Select town to port to." msgstr "Vælg den by, du gerne vil havne i." msgid "Town Portal" msgstr "Byportal" msgid "The creatures are willing to join us!" msgstr "Disse væsener er villige til at forene sig med os!" msgid "All the creatures will join us..." msgstr "Alle disse væsener vil gerne forene sig med os..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Væsenet vil gerne forene sig med os..." msgstr[1] "%{count} af disse væsener vil gerne forene sig med os..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "til en pris af %{gold} guldstykker." msgid "These weak creatures will surely flee before us." msgstr "Disse svage væsener vil sikkert flygte fra os." msgid "I fear these creatures are in the mood for a fight." msgstr "Jeg frygter at disse væsener er i humør til at slÃ¥s." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Heltens angrebsevne angiver en mængde bonuspoint, der tillægges troppernes " "angrebsevne." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Heltens forsvarsevne angiver en mængde bonuspoint, der tillægges troppernes " "forsvarsevne." msgid "The hero's spell power determines the duration or power of a spell." msgstr "" "Heltens magikraft er en mængde bonuspoint, der bestemmer den kraft og " "varighed besværgelser har." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Din kundskab bestemmer hvor meget mana helten mÃ¥ have. Under normale " "omstændigheder er en helt begrænset til at have 10 mana per level i kundskab." msgid "Current Modifiers:" msgstr "Nuværende modifikationer" msgid "skill|Basic" msgstr "Begynder" msgid "skill|Advanced" msgstr "Øvet" msgid "skill|Expert" msgstr "Ekspert" msgid "Pathfinding" msgstr "Stifinding" msgid "Archery" msgstr "Skydning" msgid "Logistics" msgstr "Logistik" msgid "Scouting" msgstr "Udspejdning" msgid "Diplomacy" msgstr "Diplomati" msgid "Navigation" msgstr "Navigation" msgid "Leadership" msgstr "Lederskab" msgid "Wisdom" msgstr "Visdom" msgid "Mysticism" msgstr "Mysticisme" msgid "Ballistics" msgstr "Ballistik" msgid "Eagle Eye" msgstr "Ørneblik" msgid "Necromancy" msgstr "Nekromanti" msgid "Estates" msgstr "Adelskab" msgid "Advanced Archery" msgstr "Øvet skydning" msgid "Advanced Pathfinding" msgstr "Øvet stifinding" msgid "Basic Archery" msgstr "Begynder skydning" msgid "Basic Pathfinding" msgstr "Begynder stifinding" msgid "Expert Pathfinding" msgstr "Ekspert stifinding" msgid "Advanced Logistics" msgstr "Øvet logistik" msgid "Basic Logistics" msgstr "Begynder logistik" msgid "Basic Scouting" msgstr "Begynder udspejdning" msgid "Expert Archery" msgstr "Ekspert skydning" msgid "Expert Logistics" msgstr "Ekspert logistik" msgid "Advanced Diplomacy" msgstr "Øvet diplomati" msgid "Advanced Scouting" msgstr "Øvet udspejdning" msgid "Basic Diplomacy" msgstr "Begynder diplomati" msgid "Expert Diplomacy" msgstr "Ekspert diplomati" msgid "Expert Scouting" msgstr "Ekspert udspejdning" msgid "Advanced Leadership" msgstr "Øvet lederskab" msgid "Advanced Navigation" msgstr "Øvet navigation" msgid "Basic Leadership" msgstr "Begynder lederskab" msgid "Basic Navigation" msgstr "Begynder navigation" msgid "Expert Navigation" msgstr "Ekspert navigation" msgid "Advanced Wisdom" msgstr "Øvet visdom" msgid "Basic Mysticism" msgstr "Begynder mysticisme" msgid "Basic Wisdom" msgstr "Begynder visdom" msgid "Expert Leadership" msgstr "Ekspert lederskab" msgid "Expert Wisdom" msgstr "Ekspert visdom" msgid "Advanced Luck" msgstr "Øvet held" msgid "Advanced Mysticism" msgstr "Øvet mysticisme" msgid "Basic Luck" msgstr "Begynder held" msgid "Expert Luck" msgstr "Ekspert held" msgid "Expert Mysticism" msgstr "Ekspert mysticisme" msgid "Advanced Ballistics" msgstr "Øvet ballistik" msgid "Advanced Eagle Eye" msgstr "Øvet ørneblik" msgid "Basic Ballistics" msgstr "Begynder ballistik" msgid "Basic Eagle Eye" msgstr "Begynder ørneblik" msgid "Expert Ballistics" msgstr "Ekspert ballistik" msgid "Advanced Necromancy" msgstr "Øvet nekromanti" msgid "Basic Estates" msgstr "Begynder adelskab" msgid "Basic Necromancy" msgstr "Begynder nekromanti" msgid "Expert Eagle Eye" msgstr "Ekspert ørneblik" msgid "Expert Necromancy" msgstr "Ekspert nekromanti" msgid "Advanced Estates" msgstr "Øvet adelskab" msgid "Expert Estates" msgstr "Ekspert adelskab" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} reducerer bevægelsesbesvær i ujævnt terræn med %{count} procent." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} eliminerer bevægelsesbesvær i ujævnt terræn." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} øger den skade, som heltens skydende tropper forÃ¥rsager, med " "%{count} procent, og eliminerer %{penalty} procentstraffen, nÃ¥r de skyder " "forbi forhindringer (f.eks. borgmure)." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} øger heltens bevægelsespoint med %{count} procent." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} øger heltens sigtbarhed med én firkant." msgstr[1] "%{skill} øger heltens sigtbarhed med %{count} firkanter." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} giver helten mulighed for at forhandle med grupper af væsener, der " "er svagere end sin egen, og reducerer omkostningerne ved overgivelse." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Cirka %{count} procent af væsenerne vil tilbyde at tilslutte sig heltens hær." msgid "All of the creatures may offer to join the hero." msgstr "Alle disse væsener tilbyder at tilslutte sig til heltens hær." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "Omkostningerne ved overgivelse er reduceret til %{percent} procent af de " "samlede omkostninger for tropper i hæren." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "%{skill} øger heltens daglige bevægelsespoint over vand med %{count} procent." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} øger moralen for heltens tropper med %{count} point." msgid "%{skill} allows the hero to learn third level spells." msgstr "" "%{skill} gør det muligt for helten at lære besværgelser af tredje niveau." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" "%{skill} gør det muligt for helten at lære besværgelser af fjerde niveau." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "" "%{skill} gør det muligt for helten at lære besværgelser af femte niveau." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} regenerer ét af heltens mana per dag." msgstr[1] "%{skill} regenerer %{count} af heltens mana per dag." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} øger held for heltens tropper med %{count} point." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} giver heltens katapultskud en større chance for at ramme og gøre " "skade pÃ¥ borgens mure." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} giver heltens katapult et ekstra skud, og hvert skud har en større " "chance for at ramme og skade borgens mure." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} giver heltens katapult et ekstra skud, og hvert skud ødelægger " "automatisk enhver mur, undtagen en befæstet mur i en ridderborg." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} giver %{count} procent chance, for at lære en given besværgelse af " "1-2.niveau, som en fjendtlig helt har kastet i løbet af en kamp." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} giver %{count} procent chance, for at lære en given besværgelse af " "1-3.niveau, som en fjendtlig helt har kastet i løbet af en kamp." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} giver %{count} procent chance, for at lære en given besværgelse af " "1-4.niveau, som en fjendtlig helt har kastet i løbet af en kamp." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} tillader %{count} procent af de væsener, der blev dræbt i kamp, at " "blive bragt tilbage fra de døde som skeletter." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Med sit adelskab producerer helten %{count} guldstykker om dagen som " "skatteindtægter." msgid "Blue" msgstr "BlÃ¥" msgid "Green" msgstr "Grøn" msgid "Red" msgstr "Rød" msgid "Yellow" msgstr "Gul" msgid "Orange" msgstr "Orange" msgid "Purple" msgstr "Lilla" msgid "barrier|Aqua" msgstr "LyseblÃ¥" msgid "barrier|Blue" msgstr "BlÃ¥" msgid "barrier|Brown" msgstr "Brun" msgid "barrier|Gold" msgstr "Guld" msgid "barrier|Green" msgstr "Grøn" msgid "barrier|Orange" msgstr "Orange" msgid "barrier|Purple" msgstr "Lilla" msgid "barrier|Red" msgstr "Rød" msgid "tent|Aqua" msgstr "LyseblÃ¥t" msgid "tent|Blue" msgstr "BlÃ¥t" msgid "tent|Brown" msgstr "Brunt" msgid "tent|Gold" msgstr "Guld" msgid "tent|Green" msgstr "Grønt" msgid "tent|Orange" msgstr "Orange" msgid "tent|Purple" msgstr "Lilla" msgid "tent|Red" msgstr "Rødt" msgid "Experience" msgstr "Erfaringspoint" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Erfaringspoint giver dine helte mulighed for at stige i level, hvilket øger " "deres primære og sekundære evner." msgid "Hero/Stats" msgstr "Helt/Egenskaber" msgid "Skills" msgstr "Evner" msgid "Town/Castle" msgstr "By/Borg" msgid "Garrison" msgstr "Garnison" msgid "Gold Per Day:" msgstr "Guld per dag:" msgid "View Heroes." msgstr "Vis helte." msgid "Towns/Castles" msgstr "Byer/Borge" msgid "View Towns and Castles." msgstr "Vis byer og borge." msgid "luck|Cursed" msgstr "Forbandet" msgid "luck|Awful" msgstr "Elendig" msgid "luck|Bad" msgstr "DÃ¥rlig" msgid "luck|Normal" msgstr "Jævn" msgid "luck|Good" msgstr "God" msgid "luck|Great" msgstr "Fremragende" msgid "luck|Irish" msgstr "Svineheldig" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Negativt held falder nogle gange pÃ¥ heltens tropper i kamp, hvilket halverer " "deres angrebsskade." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Neutralt held betyder, at heltens tropper hverken giver heldig eller uheldig " "angrebsskade." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Positivt held falder nogle gange pÃ¥ heltens tropper i kamp, hvilket " "fordobler deres angrebsskade." msgid "morale|Treason" msgstr "Horribel" msgid "morale|Awful" msgstr "Elendig" msgid "morale|Poor" msgstr "DÃ¥rlig" msgid "morale|Normal" msgstr "Jævn" msgid "morale|Good" msgstr "God" msgid "morale|Great" msgstr "Fremragende" msgid "morale|Blood!" msgstr "Blodig!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Negativ moral kan fÃ¥ heltens tropper til at fryse i kamp." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Neutral moral betyder, at heltens tropper hverken velsignes med ekstra træk " "eller fryser i kamp." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Positiv moral kan give heltens tropper ekstra træk i kamp." msgid "Knight" msgstr "Ridder" msgid "Barbarian" msgstr "Barbar" msgid "Sorceress" msgstr "Heks" msgid "Warlock" msgstr "Heksemester" msgid "Wizard" msgstr "Magiker" msgid "Necromancer" msgstr "Nekromantiker" msgid "Multi" msgstr "Flere" msgid "doubleLined|Knight" msgstr "Ridder" msgid "doubleLined|Barbarian" msgstr "Barbar" msgid "doubleLined|Sorceress" msgstr "Heks" msgid "doubleLined|Warlock" msgstr "" "Hekse-\n" "mester" msgid "doubleLined|Wizard" msgstr "Magiker" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Necro-\n" "mantiker" msgid "doubleLinedRace|Multi" msgstr "Flere" msgid "doubleLinedRace|Random" msgstr "Tilfældig" msgid "speed|Standing" msgstr "StÃ¥ende" msgid "speed|Crawling" msgstr "Kravlende" msgid "speed|Very Slow" msgstr "Sløv" msgid "speed|Slow" msgstr "Langsom" msgid "speed|Average" msgstr "Almindelig" msgid "speed|Fast" msgstr "Hurtig" msgid "speed|Very Fast" msgstr "Lynhurtig" msgid "speed|Ultra Fast" msgstr "Susende" msgid "speed|Blazing" msgstr "Stormende" msgid "speed|Instant" msgstr "Fantom" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "egern" msgid "week|Rabbit" msgstr "hare" msgid "week|Gopher" msgstr "jordegern" msgid "week|Badger" msgstr "grævling" msgid "week|Rat" msgstr "rotte" msgid "week|Eagle" msgstr "ørn" msgid "week|Weasel" msgstr "væsel" msgid "week|Raven" msgstr "ravn" msgid "week|Mongoose" msgstr "mangust" msgid "week|Dog" msgstr "hund" msgid "week|Aardvark" msgstr "jordsvin" msgid "week|Lizard" msgstr "firben" msgid "week|Tortoise" msgstr "landskildpadde" msgid "week|Hedgehog" msgstr "pindsvin" msgid "week|Condor" msgstr "kondor" msgid "week|Ant" msgstr "myre" msgid "week|Grasshopper" msgstr "græshoppe" msgid "week|Dragonfly" msgstr "guldsmed" msgid "week|Spider" msgstr "edderkop" msgid "week|Butterfly" msgstr "sommerfugl" msgid "week|Bumblebee" msgstr "humlebi" msgid "week|Locust" msgstr "ørkengræshoppe" msgid "week|Earthworm" msgstr "regnorm" msgid "week|Hornet" msgstr "hveps" msgid "week|Beetle" msgstr "mariehøne" msgid "week|PLAGUE" msgstr "FORPESTET" msgid "week|Unnamed" msgstr "unavngivet" msgid "Desert" msgstr "Ørken" msgid "Snow" msgstr "Sne" msgid "Wasteland" msgstr "Ødemark" msgid "Beach" msgstr "Strand" msgid "Lava" msgstr "Lava" msgid "Dirt" msgstr "Jord" msgid "Grass" msgstr "Græs" msgid "Ocean" msgstr "Hav" msgid "maps|Small" msgstr "Lille" msgid "maps|Medium" msgstr "Mellemstor" msgid "maps|Large" msgstr "Stor" msgid "maps|Extra Large" msgstr "Ekstra stor" msgid "maps|Custom Size" msgstr "Tilpasset størrelse" msgid "Ore Mine" msgstr "Malmmine" msgid "Sulfur Mine" msgstr "Svovlmine" msgid "Crystal Mine" msgstr "Krystalmine" msgid "Gems Mine" msgstr "Juvelmine" msgid "Gold Mine" msgstr "Guldmine" msgid "Mine" msgstr "Mine" msgid "Burma shave." msgstr "Barbercreme." msgid "Next sign 50 miles." msgstr "Næste skilt 80 km." msgid "See Rock City." msgstr "Se Stenby." msgid "This space for rent." msgstr "Skilt til udlejning." msgid "No object" msgstr "Intet objekt" msgid "Alchemist Lab" msgstr "Alkymist laboratorium" msgid "Sign" msgstr "Skilt" msgid "Buoy" msgstr "Bøje" msgid "Skeleton" msgstr "Skelet" msgid "Daemon Cave" msgstr "Dæmongrotte" msgid "Treasure Chest" msgstr "Skattekiste" msgid "Faerie Ring" msgstr "Fe-ring" msgid "Campfire" msgstr "LejrbÃ¥l" msgid "Fountain" msgstr "Springvand" msgid "Gazebo" msgstr "Lysthus" msgid "Genie Lamp" msgstr "Magisk lampe" msgid "Archer's House" msgstr "Bueskyttes hus" msgid "Goblin Hut" msgstr "Vættehytte" msgid "Dwarf Cottage" msgstr "Dværge-kottage" msgid "Peasant Hut" msgstr "Bondehytte" msgid "Stables" msgstr "Stalde" msgid "Alchemist's Tower" msgstr "AlkymisttÃ¥rn" msgid "Event" msgstr "Begivenhed" msgid "Dragon City" msgstr "Drageby" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "FyrtÃ¥rn" msgstr[1] "FyrtÃ¥rne" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Vandmølle" msgstr[1] "Vandmøller" msgid "Monster" msgstr "Væsen" msgid "Obelisk" msgstr "Obelisk" msgid "Oasis" msgstr "Oase" msgid "Resource" msgstr "Resurse" msgid "Sawmill" msgstr "Savmølle" msgid "Oracle" msgstr "Orakel" msgid "Shrine of the First Circle" msgstr "Helligdom for 1. cirkel" msgid "Shipwreck" msgstr "Skibsvrag" msgid "Sea Chest" msgstr "Søkiste" msgid "Desert Tent" msgstr "Ørkentelt" msgid "Stone Liths" msgstr "Monolit" msgid "Wagon Camp" msgstr "Vogn-lejr" msgid "Hut of the Magi" msgstr "Magikerens hytte" msgid "Whirlpool" msgstr "Virvelstrøm" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Vindmølle" msgstr[1] "Vindmøller" msgid "Mermaid" msgstr "Havfrue" msgid "Boat" msgstr "Skib" msgid "Random Ultimate Artifact" msgstr "Tilfældigt ultimativt artefakt" msgid "Random Artifact" msgstr "Tilfældigt artefakt" msgid "Random Resource" msgstr "Tilfældig resurse" msgid "Random Monster" msgstr "Tilfældigt væsen" msgid "Random Town" msgstr "Tilfældig by" msgid "Random Castle" msgstr "Tilfældig borg" msgid "Eye of the Magi" msgstr "Magikerens øje" msgid "Random Monster - weak" msgstr "Tilfældigt væsen - svag" msgid "Random Monster - medium" msgstr "Tilfældigt væsen - medium" msgid "Random Monster - strong" msgstr "Tilfældigt væsen - stærk" msgid "Random Monster - very strong" msgstr "Tilfældigt væsen - meget stærk" msgid "Hero" msgstr "Helt" msgid "Nothing Special" msgstr "Intet særligt" msgid "Mossy Rock" msgstr "Mosset sten" msgid "Watch Tower" msgstr "UdkigstÃ¥rn" msgid "Tree House" msgstr "Træhus" msgid "Tree City" msgstr "Træby" msgid "Ruins" msgstr "Ruiner" msgid "Fort" msgstr "Fort" msgid "Abandoned Mine" msgstr "Forladt mine" msgid "Sirens" msgstr "Sirener" msgid "Standing Stones" msgstr "Bautastenring" msgid "Idol" msgstr "Stenidol" msgid "Tree of Knowledge" msgstr "Visdomstræ" msgid "Witch Doctor's Hut" msgstr "Heksedoktorens hytte" msgid "Temple" msgstr "Tempel" msgid "Hill Fort" msgstr "Bakkefort" msgid "Halfling Hole" msgstr "Halvlang-hul" msgid "Mercenary Camp" msgstr "Lejesoldaterlejr" msgid "Shrine of the Second Circle" msgstr "Helligdom for 2. cirkel" msgid "Shrine of the Third Circle" msgstr "Helligdom for 3. cirkel" msgid "City of the Dead" msgstr "De dødes by" msgid "Sphinx" msgstr "Sfinks" msgid "Wagon" msgstr "Vogn" msgid "Tar Pit" msgstr "Tjæresø" msgid "Artesian Spring" msgstr "Artesisk springvand" msgid "Troll Bridge" msgstr "Troldebro" msgid "Watering Hole" msgstr "Vandhul" msgid "Witch's Hut" msgstr "Heksens hytte" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Shelter" msgid "Magellan's Maps" msgstr "Magellans kort" msgid "Flotsam" msgstr "Vraggods" msgid "Derelict Ship" msgstr "Forladt skib" msgid "Shipwreck Survivor" msgstr "Skibbruden" msgid "Bottle" msgstr "Flaske" msgid "Magic Well" msgstr "Magisk brønd" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Magisk have" msgstr[1] "Magiske haver" msgid "Observation Tower" msgstr "ObservationstÃ¥rn" msgid "Freeman's Foundry" msgstr "Friborgeres støberi" msgid "Reefs" msgstr "Rev" msgid "Volcano" msgstr "Vulkan" msgid "Flowers" msgstr "Blomster" msgid "Rock" msgstr "Sten" msgid "Water Lake" msgstr "Indsø" msgid "Mandrake" msgstr "Alrune" msgid "Dead Tree" msgstr "Dødt træ" msgid "Stump" msgstr "Stub" msgid "Crater" msgstr "Krater" msgid "Cactus" msgstr "Kaktus" msgid "Mound" msgstr "Høj" msgid "Dune" msgstr "Klit" msgid "Lava Pool" msgstr "Lavasø" msgid "Shrub" msgstr "Buskads" msgid "Barrow Mounds" msgstr "Gravhøj" msgid "Random Artifact - Treasure" msgstr "Tilfældigt artefakt - Skat" msgid "Random Artifact - Minor" msgstr "Tilfældigt artefakt - Minor" msgid "Random Artifact - Major" msgstr "Tilfældigt artefakt - Major" msgid "Barrier" msgstr "Barriere" msgid "Traveller's Tent" msgstr "Rejsendes telt" msgid "Jail" msgstr "Fængsel" msgid "Fire Summoning Altar" msgstr "Ild-elementalers alter" msgid "Air Summoning Altar" msgstr "Luft-elementalers alter" msgid "Earth Summoning Altar" msgstr "Jord-elementalers alter" msgid "Water Summoning Altar" msgstr "Vand-elementalers alter" msgid "Swampy Lake" msgstr "Sumpsø" msgid "Frozen Lake" msgstr "Frossen sø" msgid "randomRace|level 1 creatures" msgstr "niveau 1 væsener" msgid "randomRace|level 2 creatures" msgstr "niveau 2 væsener" msgid "randomRace|level 3 creatures" msgstr "niveau 3 væsener" msgid "randomRace|level 4 creatures" msgstr "niveau 4 væsener" msgid "randomRace|level 5 creatures" msgstr "niveau 5 væsener" msgid "randomRace|level 6 creatures" msgstr "niveau 6 væsener" msgid "Unknown Monsters" msgstr "Ukendte væsener" msgid "Unknown Monster" msgstr "Ukendt væsen" msgid "Peasant" msgstr "Bonde" msgid "Peasants" msgstr "Bønder" msgid "Archer" msgstr "Bueskytte" msgid "Archers" msgstr "Bueskyttere" # We don't have a proper word for a military trained "ranger" in danish... msgid "Ranger" msgstr "Skovridder" msgid "Rangers" msgstr "Skovriddere" msgid "Pikeman" msgstr "Pikenér" msgid "Pikemen" msgstr "Pikenérer" msgid "Veteran Pikeman" msgstr "Veteran pikenér" msgid "Veteran Pikemen" msgstr "Veteran pikenérer" msgid "Swordsman" msgstr "Sværdkæmper" msgid "Swordsmen" msgstr "Sværdkæmpere" msgid "Master Swordsman" msgstr "Sværdkampsmester" msgid "Master Swordsmen" msgstr "Sværdkampsmestre" msgid "Cavalries" msgstr "Ryttere" msgid "Cavalry" msgstr "Rytter" msgid "Champion" msgstr "Mesterrytter" msgid "Champions" msgstr "Mesterryttere" msgid "Paladin" msgstr "Paladin" msgid "Paladins" msgstr "Paladiner" msgid "Crusader" msgstr "Korsridder" msgid "Crusaders" msgstr "Korsriddere" msgid "Goblin" msgstr "Vætte" msgid "Goblins" msgstr "Vætter" msgid "Orc" msgstr "Ork" msgid "Orcs" msgstr "Orker" msgid "Orc Chief" msgstr "Orkhøvding" msgid "Orc Chiefs" msgstr "Orkhøvdinger" msgid "Wolf" msgstr "Ulv" msgid "Wolves" msgstr "Ulve" msgid "Ogre" msgstr "Jætte" msgid "Ogres" msgstr "Jætter" msgid "Ogre Lord" msgstr "Jætteherre" msgid "Ogre Lords" msgstr "Jætteherrer" msgid "Troll" msgstr "Trold" msgid "Trolls" msgstr "Trolde" msgid "War Troll" msgstr "Krigstrold" msgid "War Trolls" msgstr "Krigstrolde" msgid "Cyclopes" msgstr "Kykloper" msgid "Cyclops" msgstr "Kyklop" msgid "Sprite" msgstr "Fe" msgid "Sprites" msgstr "Feer" msgid "Dwarf" msgstr "Dværg" msgid "Dwarves" msgstr "Dværge" msgid "Battle Dwarf" msgstr "Dværgkæmper" msgid "Battle Dwarves" msgstr "Dværgkæmpere" msgid "Elf" msgstr "Elver" msgid "Elves" msgstr "Elvere" msgid "Grand Elf" msgstr "Storelver" msgid "Grand Elves" msgstr "Storelvere" msgid "Druid" msgstr "Druide" msgid "Druids" msgstr "Druider" msgid "Greater Druid" msgstr "Højdruide" msgid "Greater Druids" msgstr "Højdruider" msgid "Unicorn" msgstr "Enhjørning" msgid "Unicorns" msgstr "Enhjørninger" msgid "Phoenix" msgstr "Føniks" msgid "Phoenixes" msgstr "Fønikser" msgid "Centaur" msgstr "Kentaur" msgid "Centaurs" msgstr "Kentaurer" msgid "Gargoyle" msgstr "Gargoyle" msgid "Gargoyles" msgstr "Gargoyler" msgid "Griffin" msgstr "Grif" msgid "Griffins" msgstr "Griffe" msgid "Minotaur" msgstr "Minotaur" msgid "Minotaurs" msgstr "Minotaurer" msgid "Minotaur King" msgstr "Minotaurkonge" msgid "Minotaur Kings" msgstr "Minotaurkonger" msgid "Hydra" msgstr "Hydra" msgid "Hydras" msgstr "Hydraer" msgid "Green Dragon" msgstr "Grøndrage" msgid "Green Dragons" msgstr "Grøndrager" msgid "Red Dragon" msgstr "Røddrage" msgid "Red Dragons" msgstr "Røddrager" msgid "Black Dragon" msgstr "Sortdrage" msgid "Black Dragons" msgstr "Sortdrager" msgid "Halfling" msgstr "Halvlang" msgid "Halflings" msgstr "Halvlange" msgid "Boar" msgstr "Vildsvin" msgid "Boars" msgstr "Vildsvin" msgid "Iron Golem" msgstr "Jerngolem" msgid "Iron Golems" msgstr "Jerngolemmer" msgid "Steel Golem" msgstr "StÃ¥lgolem" msgid "Steel Golems" msgstr "StÃ¥lgolemmer" msgid "Roc" msgstr "Rok" msgid "Rocs" msgstr "Roker" msgid "Mage" msgstr "Troldmand" msgid "Magi" msgstr "Troldmænd" msgid "Archmage" msgstr "Ærketroldmand" msgid "Archmagi" msgstr "Ærketroldmænd" msgid "Giant" msgstr "Kæmpe" msgid "Giants" msgstr "Kæmper" msgid "Titan" msgstr "Titan" msgid "Titans" msgstr "Titaner" msgid "Skeletons" msgstr "Skeletter" msgid "Zombie" msgstr "Zombie" msgid "Zombies" msgstr "Zombier" msgid "Mutant Zombie" msgstr "Muteret zombie" msgid "Mutant Zombies" msgstr "Muterede zombier" msgid "Mummies" msgstr "Mumier" msgid "Mummy" msgstr "Mumie" msgid "Royal Mummies" msgstr "Royale mumier" msgid "Royal Mummy" msgstr "Royal mumie" msgid "Vampire" msgstr "Vampyr" msgid "Vampires" msgstr "Vampyrer" msgid "Vampire Lord" msgstr "Vampyrherre" msgid "Vampire Lords" msgstr "Vampyrherrer" msgid "Lich" msgstr "Lich" msgid "Liches" msgstr "Licher" msgid "Power Lich" msgstr "Kraftlich" msgid "Power Liches" msgstr "Kraftlicher" msgid "Bone Dragon" msgstr "Skeletdrage" msgid "Bone Dragons" msgstr "Skeletdrager" msgid "Rogue" msgstr "Slyngel" msgid "Rogues" msgstr "Slyngler" msgid "Nomad" msgstr "Nomade" msgid "Nomads" msgstr "Nomader" msgid "Ghost" msgstr "Spøgelse" msgid "Ghosts" msgstr "Spøgelser" msgid "Genie" msgstr "LampeÃ¥nd" msgid "Genies" msgstr "LampeÃ¥nder" msgid "Medusa" msgstr "Medusa" msgid "Medusas" msgstr "Medusaer" msgid "Earth Elemental" msgstr "Jord-elemental" msgid "Earth Elementals" msgstr "Jord-elementaler" msgid "Air Elemental" msgstr "Luft-elemental" msgid "Air Elementals" msgstr "Luft-elementaler" msgid "Fire Elemental" msgstr "Ild-elemental" msgid "Fire Elementals" msgstr "Ild-elementaler" msgid "Water Elemental" msgstr "Vand-elemental" msgid "Water Elementals" msgstr "Vand-elementaler" msgid "Random Monsters" msgstr "Tilfældige væsener" msgid "Random Monster 1" msgstr "Tilfældigt væsen 1" msgid "Random Monsters 1" msgstr "Tilfældige væsener 1" msgid "Random Monster 2" msgstr "Tilfældigt væsen 2" msgid "Random Monsters 2" msgstr "Tilfældige væsener 2" msgid "Random Monster 3" msgstr "Tilfældigt væsen 3" msgid "Random Monsters 3" msgstr "Tilfældige væsener 3" msgid "Random Monster 4" msgstr "Tilfældigt væsen 4" msgid "Random Monsters 4" msgstr "Tilfældige væsener 4" msgid "Double shot" msgstr "Dobbeltskud" msgid "2-hex monster" msgstr "2-feltsvæsen" msgid "Double strike" msgstr "Dobbeltslag" msgid "Double damage to Undead" msgstr "Dobbelt skade til udøde" msgid "% magic resistance" msgstr "% magiresistens" msgid "Immune to Mind spells" msgstr "Immun overfor sindsbesværgelser" msgid "Immune to Elemental spells" msgstr "Immun overfor elementalbesværgelser" msgid "Immune to Fire spells" msgstr "Immun overfor ildbesværgelser" msgid "Immune to Cold spells" msgstr "Immun overfor koldbesværgelser" msgid "Immune to " msgstr "Immun overfor " msgid "% immunity to %{spell} spell" msgstr "% immunitet overfor %{spell} besværgelse" msgid "% damage from Elemental spells" msgstr "% skade af elementalbesværgelser" msgid "% damage from %{spell} spell" msgstr "% skade af %{spell} besværgelsen" msgid "% chance to Dispel beneficial spells" msgstr "% chance, for at fordrive gavnlige besværgelser" msgid "% chance to Paralyze" msgstr "% chance, for at lamme" msgid "% chance to Petrify" msgstr "% chance, for at forstene" msgid "% chance to Blind" msgstr "% chance, for at blinde" msgid "% chance to Curse" msgstr "% chance, for at forbande" msgid "% chance to cast %{spell} spell" msgstr "% chance, for at kaste en %{spell} besværgelse" msgid "HP regeneration" msgstr "Selvhelbredende" msgid "Two hexes attack" msgstr "2-feltsangreb" msgid "Flyer" msgstr "Kan flyve" msgid "Always retaliates" msgstr "SlÃ¥r altid igen" msgid "Attacks all adjacent enemies" msgstr "Angriber alle fjender omkring sig" msgid "No melee penalty" msgstr "Ingen nærkampsstraf" msgid "Dragon" msgstr "Drage" msgid "Undead" msgstr "Udød" msgid "No enemy retaliation" msgstr "Fjender kan ikke slÃ¥ igen" msgid "HP drain" msgstr "Stjæler liv" msgid "Cloud attack" msgstr "Skyangreb" msgid "Decreases enemy's morale by " msgstr "Sænker fjendens moral med " msgid "% chance to halve enemy" msgstr "% chance for at halvere fjenden" msgid "Soul Eater" msgstr "Sjælefortærer" msgid "Elemental" msgstr "Elementalt" msgid "No Morale" msgstr "Ingen moral" #, fuzzy msgid "Earth creature" msgstr "Rekruttér væsener" #, fuzzy msgid "Air creature" msgstr "Rekruttér væsener" #, fuzzy msgid "Fire creature" msgstr "Rekruttér væsener" #, fuzzy msgid "Water creature" msgstr "Indsø" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% skade af ildbesværgelser" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% skade af koldbesværgelser" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Fjerner alle magiske besværgelser fra samtlige tropper." #, fuzzy msgid "Double damage from Air creatures" msgstr "Dobbelt skade til udøde" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% skade af ildbesværgelser" #, fuzzy msgid "Double damage from Water creatures" msgstr "Fjerner alle magiske besværgelser fra samtlige tropper." msgid "Lightning" msgstr "Lyn" msgid "% immunity to " msgstr "% immunitet overfor " msgid "% damage from " msgstr "% skade af " msgid "The three Anduran artifacts magically combine into one." msgstr "Andurans tre artefakter forenes pÃ¥ magisk vis til ét." msgid "View Spells" msgstr "Vis besværgelser" msgid "View %{name} Info" msgstr "Vis %{name} info" msgid "Move %{name}" msgstr "Flyt %{name}" msgid "Cannot move the Spellbook" msgstr "Kan ikke flytte magibogen" msgid "This item can't be traded." msgstr "Magibogen er bundet til den enkelte helt." msgid "Invalid Artifact" msgstr "Ugyldigt artefakt" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} øger heltens kundskab med %{count} point." msgid "Ultimate Book of Knowledge" msgstr "Den Ultimative Bog for Kundskab" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} øger angrebsevnen for heltens tropper med %{count} point." msgid "Ultimate Sword of Dominion" msgstr "Det Ultimative Herredømmesværd" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} øger forsvarsevnen for heltens tropper med %{count} point." msgid "Ultimate Cloak of Protection" msgstr "Den Ultimative Beskyttelseskappe" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} øger heltens magikraft med %{count} point." msgid "Ultimate Wand of Magic" msgstr "Den Ultimative Tryllestav" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} øger heltens angrebs- og forsvarsevne med %{count} point." msgid "Ultimate Shield" msgstr "Det Ultimative Skjold" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} øger heltens magikraft og kundskab med %{count} point." msgid "Ultimate Staff" msgstr "Den Ultimative Stav" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} øger alle heltens primære evner med %{count} point." msgid "Ultimate Crown" msgstr "Den Ultimative Krone" msgid "Golden Goose" msgstr "Den Gyldne GÃ¥s" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} bringer en guldindkomst med %{count} guldstykker om dagen." msgid "Arcane Necklace of Magic" msgstr "Den Magiske Mystikhalskæde" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Efter at have reddet en heks fra en forbandet grav, belønner hun dit " "heltemod med en udsøgt juvelhalskæde." msgid "Caster's Bracelet of Magic" msgstr "Kasterens MagiarmbÃ¥nd" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Mens du gennemsøger murbrokkerne af en nedgravet mine, befrier du en gruppe " "fangede dværge. Taknemmelig giver lederen dig et gyldent armbÃ¥nd." msgid "Mage's Ring of Power" msgstr "Troldmandens Magtring" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Et skrig af smerte fører dig til en kentaur, fanget i en fælde. Efter at " "have sat væsenet fri, rækker han dig en lille pose. Da du tømmer posens " "indhold, finder du en blændende juvelbesat ring." msgid "Witch's Broach of Magic" msgstr "Troldkællingens Magibroche" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Ved siden af resterne af en brændt troldkælling ligger en smukt udformet " "broche. Med forsigtighed nærmer du dig liget. Du tilføjer brochen til din " "oppakning." msgid "Medal of Valor" msgstr "Hædersmedaljen" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} øger moralen for heltens tropper med %{count} point." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Ved at befri en dydig jomfru fra en ond overherres kløer, fÃ¥r du en " "hædersmedalje af kongens herold." msgid "Medal of Courage" msgstr "Tapperhedsmedaljen" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Efter at have reddet en ung dreng fra en ond flok ulve, returnerer du ham " "til sin fars herregÃ¥rd. Den taknemmelige adelsmand belønner dig med en " "tapperhedsmedalje." msgid "Medal of Honor" msgstr "Æresmedaljen" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Efter at have befriet en prinsesse af et nabokongerige fra nogle foragtelige " "slavehandleres onde kløer, tildeler hun dig en æresmedalje." msgid "Medal of Distinction" msgstr "Udmærkelsesmedaljen" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Da du befrier landskabet for den hæslige minotaur, der gjorde en sport ud af " "at æde adelsmænds riddere, beæres du med en udmærkelsesmedalje." msgid "Fizbin of Misfortune" msgstr "Fizbin Ulykkesmedaljen" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "" "%{name} reducerer markant moralen for heltens tropper med %{count} point." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Du falder over en medalje, der ligger langs den tomme vej. Du tilføjer " "medaljen til din oppakning og bliver opmærksom pÃ¥, at du har erhvervet den " "uønskede Fizbin Ulykkesmedalje, hvilket i høj grad mindsker din hærs moral." msgid "Thunder Mace of Dominion" msgstr "Overmagtens Tordenplejle" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Under en pludselig storm slÃ¥r et lyn ned i et træ og flækker det. Inde i " "træet finder du en mystisk stridsplejle." msgid "Armored Gauntlets of Protection" msgstr "Værnerens Pansrede Handsker" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} øger heltens forsvarsevne med %{count} point." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Du møder den berygtede Sorte Ridder! Efter en opslidende duel, som ender " "uafgjort, vinder du ridderens respekt, og han tilbyder dig et par pansrede " "handsker." msgid "Defender Helm of Protection" msgstr "Værnerens Forsvarshjelm" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Dit øje fanger et gyldent lysglimt. Ved nærmere undersøgelse finder du en " "gylden hjelm gemt under en busk." msgid "Giant Flail of Dominion" msgstr "Overmagtens Kæmpeslagle" # ordet "plejl" beskrives som en "flail" typisk ser ud msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "En klodset kæmpe har dræbt sig selv med sin egen slagle. NÃ¥r du kender dine " "overlegne færdigheder med dette vÃ¥ben, fjerner du trygt den spektakulære " "slagle fra den faldne kæmpe." msgid "Ballista of Quickness" msgstr "Den Hastfulde Ballista" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "%{name} giver heltens katapult et ekstra skud per kamprunde." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "GÃ¥ende gennem ruinerne af en ældgammel befæstet by, finder du instrumentet " "til byens ødelæggelse, en omhyggeligt udformet ballista." msgid "Stealth Shield of Protection" msgstr "Værnerens Skalkeskjold" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "En krigerstatue af sten holder et sølvskjold. Idet du fjerner skjoldet, " "smuldrer statuen til støv." msgid "Dragon Sword of Dominion" msgstr "Overmagtens Dragesværd" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Mens du gÃ¥r ad en smal sti, bryder en busk i nærheden pludselig i flammer. " "Flammerne danner et billede af en smuk kvinde for dine øjne. Hun fremrækker " "dig et storslÃ¥et sværd." msgid "Power Axe of Dominion" msgstr "Overmagtens Kraftøkse" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Du ser en sølvøkse dybt i jorden. Efter adskillige mislykkede forsøg fra " "dine mænd pÃ¥ at fjerne øksen, tager du selv hÃ¥rdt fat i øksens skaft og " "trækker den ubesværet fri." msgid "Divine Breastplate of Protection" msgstr "Værnerens Guddommelige Brystplade" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "En slyngelbande gennemsøger de døde krigeres ejendele. Efter at have skræmt " "de plyndrende slyngler væk, bemærker du, at de havde overset en smuk " "brystplade." msgid "Minor Scroll of Knowledge" msgstr "Skriftrullen om mindre Kundskaber" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Foran dig dukker et svævende glasmontre op. Indeni den ligger en skriftrulle " "ovenpÃ¥ noget karmosinrødt fløjl. Din berøring Ã¥bner glaslÃ¥get, og " "skriftrullen flyver ind i dine afventende hænder." msgid "Major Scroll of Knowledge" msgstr "Skriftrullen om større Kundskaber" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Da du besøger en lokal vismand, forklarer du hensigten med din rejse. Op af " "en sæk trækker han en gulnet skriftrulle, og rækker den til dig." msgid "Superior Scroll of Knowledge" msgstr "Skriftrullen om overlegne Kundskaber" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Du støder pÃ¥ resterne af en ældgammel druide. Fra hendes forrevne folder i " "hendes robe ses der knogler, gulnede af alderen. Du søger i roben og opdager " "en skriftrulle gemt i folderne." msgid "Foremost Scroll of Knowledge" msgstr "Skriftrullen om førende Kundskaber" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Fra de forrevne folder i en død druides robe ses der lemlæstede knogler, " "gulnede af alderen. Du søger i roben og opdager en skriftrulle gemt i " "folderne." msgid "Endless Sack of Gold" msgstr "Den Uudtømmelige Guldsæk" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} bringer en guldindkomst med %{count} guldstykker om dagen." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "En lille alf danser lystigt rundt om en magisk sæk. Da han ser dig nærme " "sig, stopper han midt i et trin. Den lille mand skriger og stamper voldsomt " "med foden og forsvinder ud i den blÃ¥ luft. Du husker den gamle alfs " "ordsprog: 'Det man finder, mÃ¥ man beholde'. Du griber sækken og gÃ¥r." msgid "Endless Bag of Gold" msgstr "Den Uudtømmelige Guldtaske" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "En adelig kvinde, adskilt fra sine rejsekammerater, beder om din hjælp. " "Efter at have eskorteret hende hjem, belønner hun dig med en taske fyldt med " "guld." msgid "Endless Purse of Gold" msgstr "Den Uudtømmelige Guldpose" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "PÃ¥ dine rejser finder du en læderpung fyldt med guld. Den tilhørte engang en " "stor krigerkonge, som havde evnen til at forvandle enhver livløs genstand " "til guld." msgid "Nomad Boots of Mobility" msgstr "Nomadens Syvmilestøvler" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} øger heltens bevægelsespoint til lands." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "En nomadehandler søger beskyttelse fra en vættestamme. For din hjælp giver " "han dig et par fint forarbejdede støvler, lavet af det blødeste læder. Ved " "nærmere eftersyn, ser du fascinerende ældgamle udskæringer indgraveret pÃ¥ " "læderet." msgid "Traveler's Boots of Mobility" msgstr "Vandrerens Syvmilestøvler" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Idet du opdager et par smukke støvler med perler, lavet af det fineste og " "blødeste læder, takker du den anonyme donor og tilføjer støvlerne til din " "oppakning." msgid "Lucky Rabbit's Foot" msgstr "Den Heldige Kaninfod" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} øger heldet for heltens tropper med %{count} point." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "En rejsende købmand tilbyder dig en kaninfod, lavet af skinnende sølvpels, " "for sikker passage. Købmanden forklarer, at denne berlok vil øge dit held i " "kamp." msgid "Golden Horseshoe" msgstr "Den Gyldne Hestesko" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "En fanget enhjørning vrinsker rædselsslagent. Mens du mumler beroligende " "ord, sætter du hende fri. Hun pruster og stamper en gang med sin forhov før " "den galopperer derudaf. Du kigger ned og ser den efterladte hestesko af guld." msgid "Gambler's Lucky Coin" msgstr "Hasardspillerens Lykkemønt" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Du har fanget en drilsk djævleunge, som har terroriseret omrÃ¥det. Til " "gengæld for sin løsladelse belønner han dig med en magisk mønt." msgid "Four-Leaf Clover" msgstr "Firkløveren" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Midt pÃ¥ en død og udtørret eng finder du, til din overraskelse, en sund grøn " "firkløver." msgid "True Compass of Mobility" msgstr "Det sande Kompas for Bevægelighed." msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} øger heltens bevægelsespoint, bÃ¥de til lands og til vands." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "En gammel mand, som hævder at være opfinder, beder dig prøve hans seneste " "opfindelse. Han rækker dig et sandt kompas." msgid "Sailor's Astrolabe of Mobility" msgstr "Søfarerens Astrolabium for Bevægelighed" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} øger heltens bevægelsespoint til vands." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "En gammel søkaptajn bliver tortureret af jætter. Du redder ham, og til " "gengæld belønner han dig med et vidunderligt instrument til at mÃ¥le " "afstanden til stjerner." msgid "Evil Eye" msgstr "Ondt Øje" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} halverer manaprisen for at kaste forbandelsesbesværgelser." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Mens du begiver dig ind i en forfalden hytte, finder du skelettet af en for " "længst død troldkælling. Undersøgelse af resterne afslører et glasøje, som " "ruller rundt inde i et tomt kranie." msgid "Enchanted Hourglass" msgstr "Det Fortryllede Timeglas" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} forlænger varigheden pÃ¥ alle heltens besværgelser med %{count} " "runder." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Midt i et overraskende sving i landskabet oplever du et uhyggeligt syn: " "Gribbe, plukkende i kølvandet af en frygtelig kamp. Overfladisk søger du " "gennem ligresterne og finder et fortryllet timeglas." msgid "Gold Watch" msgstr "Gulduret" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} fordobler effektiviteten pÃ¥ heltens hypnosebesværgelser." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Som belønning, for at have hjulpet hans vogn op af en grøft, giver en " "omrejsende eliksirsælger dig et \"magisk\" guldur. Han vidste ikke, at uret " "faktisk er magisk." msgid "Skullcap" msgstr "Kalotten" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} halverer manaprisen for alle dine sindspÃ¥virkende besværgelser." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Et kort stop pÃ¥ en usandsynlig landlig kro resulterer i en udveksling af " "penge, fortællinger og tilfældig bagage. Du finder en magisk kalot i din nye " "rygsæk." msgid "Ice Cloak" msgstr "Iskappen" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} halverer al skade, som heltens tropper modtager fra " "kuldebesværgelser." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Som reaktion pÃ¥ paniske skrig fra en pige i nød, opdager du en ung kvinde, " "der flygter fra en sulten bjørn. I sidste øjeblik dræber du udyret. Og ud af " "bjørnens skind væver den taknemmelige heks dig en magisk kappe." msgid "Fire Cloak" msgstr "Ildkappen" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} halverer al skade, som heltens tropper modtager fra ildbesværgelser." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Du er stødt pÃ¥ en kamp mellem en nekromantiker og en paladin. " "Nekromantikeren sprænger paladinen med en ildkugle, hvilket fÃ¥r ham i knæ. " "Du handler hurtigt og dræber den onde, før nÃ¥destødet nÃ¥r at indtræffe. Den " "taknemmelige paladin giver dig Ildkappen, som reddede ham." msgid "Lightning Helm" msgstr "Lynhjelmen" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} halverer al skade, som heltens tropper modtager fra lynbesværgelser." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "En rejsende kedelflikker, som har brug for forsyninger, tilbyder dig en " "hjelm med et lynmærke pÃ¥ sig i bytte for mad og drikke. Nysgerrig accepterer " "du, og finder senere ud af, at hjelmen er magisk." msgid "Evercold Icicle" msgstr "Den Evigtkolde Istap" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} fÃ¥r heltens kuldebesværgelser til at gøre %{count} procent mere " "skade pÃ¥ fjendens tropper." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "En istap, som modstÃ¥r middagssolens varme til fulde, tiltrækker din " "opmærksomhed. Nysgerrigt brækker du det af og opdager, at det ikke smelter i " "din hÃ¥nd." msgid "Everhot Lava Rock" msgstr "Den Evigtvarme Lavasten" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} fÃ¥r heltens ildbesværgelser til at gøre %{count} procent mere skade " "pÃ¥ fjendens tropper." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Dine vandringer bringer dig i kontakt med en stamme af abelignende væsener, " "der bruger en magisk lavasten, som aldrig køler, til at tænde deres ild med. " "Du forbarmer dig over dem og lærer dem, at lave ild med pinde. I troen pÃ¥, " "at du er en gud, giver aberne dig deres lavasten." msgid "Lightning Rod" msgstr "Lynaflederen" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} fÃ¥r heltens lynbesværgelser til at gøre %{count} procent mere skade " "pÃ¥ fjendens tropper." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Ventende pÃ¥ at et uvejr stopper, slÃ¥r et lyn ned i en nærliggende hyttes " "lynafleder, som smelter og falder til jorden. Spidsen forbliver dog intakt " "og fÃ¥r dit hÃ¥r til at rejse sig, nÃ¥r du rører ved det. Hmm..." msgid "Snake-Ring" msgstr "Slangeringen" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} halverer heltens manapris, for at kaste velsignelsesbesværgelser." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Du har fundet en sært formet ring pÃ¥ fingeren af en for længst død rejsende. " "Ringen ligner en slange, der bider sig selv i halen." msgid "Ankh" msgstr "Ankhen" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} fordobler effektiviteten af alle heltens genoplivende og " "dødebesjælende besværgelser." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "En voldsom vindstorm afslører indgangen til et underjordisk gravkammer. Din " "undersøgelse afslører, at graven allerede er blevet plyndret, men " "gravrøverne oversÃ¥ en ankh pÃ¥ en sølvkæde i mørket." msgid "Book of Elements" msgstr "Elementalernes Bog" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" "%{name} fordobler effektiviteten af alle heltens hidkaldelsesbesværgelser." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Du støder pÃ¥ en Ã¥ndemaner, som for sin sikkerheds skyld trygler dig om at " "ledsage dig og din hær et stykke tid. Du gÃ¥r med til det, og han tilbyder, " "som betaling, en kopi af Elementalernes Bog." msgid "Elemental Ring" msgstr "Elemental-ringen" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "%{name} halverer manaprisen for at kaste hidkaldelsesbesværgelser." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Mens du tager en hvilepause, bemærker du en bobcat, som klatrer op til en " "kragerede i et lille træ. Impulsivt klatrer du selv op i træet og skræmmer " "katten væk. Idet du ser ned i reden, finder du en samling skinnende sten, og " "en ring." msgid "Holy Pendant" msgstr "Den Hellige Amulet" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" "%{name} gør alle heltens tropper immune overfor forbandelsesbesværgelser." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "PÃ¥ dine vandringer støder du pÃ¥ en eremit, der bor i en lille, ryddelig " "hytte. Imponeret over din mission tager han en pause fra sine meditationer, " "for at velsigne og give dig en berlok mod forbandelser." msgid "Pendant of Free Will" msgstr "Amuletten af Fri Vilje" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "%{name} gør alle heltens tropper immune overfor hypnosebesværgelser." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Idet du reagerer pÃ¥ rÃ¥b om hjælp, ser du nogle flodfeer, som gør en sport ud " "af dunke en gammel mand ned i vandet. Med en følelse af hævngerrighed redder " "du manden og trækker derefter en af feerne ind pÃ¥ land. Feen, som ikke kan " "klare luften, giver dig en magisk amulet mod sin frihed." msgid "Pendant of Life" msgstr "Livsamuletten" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} gør alle heltens tropper immune overfor dødsbesværgelser." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Et kort møde i vejkanten med en lille karavane og et spil knoben vinder dig " "en magisk amulet. Dens tidligere ejer siger, at den beskytter mod " "nekromantikeres dødsbesværgelser." msgid "Serenity Pendant" msgstr "Amuletten af Sindsro" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} gør alle heltens tropper immune overfor bersærkbesværgelser." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Tiltrukket af lydene fra et slagsmÃ¥l overværer du en kamp mellem en gammel " "barbar og en otte-hovedet hydra. Din rettidige indgriben svinger kampen til " "barbarens fordel, og han belønner dig med en amulet, han plejede at bruge " "til at berolige sit sind til kamp." msgid "Seeing-eye Pendant" msgstr "Amuletten af Det Seende Øje" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} gør alle heltens tropper immune overfor blindingsbesværgelser." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Du støder pÃ¥ en meget gammel kvinde, for længst blind af grÃ¥ stær og døende " "alene. Du plejer hendes endelige behov og lover hende en ordentlig " "begravelse. Taknemmelig giver hun dig en magisk amulet med et stiliseret " "øje. Det lader dig se med lukkede øjne." msgid "Kinetic Pendant" msgstr "Den Kinetiske Amulet" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name} gør alle heltens tropper immune overfor paralysebesværgelser." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Du støder pÃ¥ en golem iført en glødende amulet, som spærrer din vej. " "Handlende pÃ¥ din mavefornemmelse, klipper du vedhænget af dets hals. " "Frataget sin kraftkilde gÃ¥r golemmen i stykker og efterlader dig med den " "magiske amulet." msgid "Pendant of Death" msgstr "Dødsamuletten" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} gør alle heltens tropper immune overfor hellige besværgelser" msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "En hurtig og dødbringende kamp med en nekromantiker vinder dig hans magiske " "amulet. Senere fortæller en magiker, at amuletten beskytter udøde under din " "kontrol mod hellige ord." msgid "Wand of Negation" msgstr "Negationens Tryllestav" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "%{name} gør alle heltens tropper immune overfor magi-ophævelser." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Du møder en gammel magikerven, der rejser i den modsatte retning. Han giver " "dig en gave: En tryllestav, der forhindrer brugen af besværgelsen " "magiophævelse pÃ¥ dine tropper." msgid "Golden Bow" msgstr "Den Gyldne Bue" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} eliminerer %{count}-procentstraffen for heltens tropper, der skyder " "forbi forhindringer (f.eks. borgmure)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Et tilfældigt møde med en berømt bueskytte fÃ¥r dig til at indgÃ¥ i et " "knoglespil om hans bue mod din hest. Du vinder." msgid "Telescope" msgstr "Teleskopet" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} øger mængden af det terræn, som afsløres af heltens udforskning, med " "%{count} extra kvadrat." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Af en købmand fra fjerne lande køber du en ny opfindelse af hans " "rejseforsynende folk. Det fÃ¥r fjerne objekter til at synes tættere pÃ¥, og " "han kalder det...\n" "\n" "et teleskop." msgid "Statesman's Quill" msgstr "Statsmandens Fjerpen" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} reducerer overgivelsesprisen til %{count} procent af de samlede " "omkostninger for tropper, helten har i sin hær." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Du holder pause, for at hjælpe en diplomat med at løse sit problem med en " "brækket aksel. Taknemmelig giver han dig en fjerpen med magiske egenskaber, " "som han siger vil \"hjælpe folk med at se tingene pÃ¥ din mÃ¥de\"." msgid "Wizard's Hat" msgstr "Troldmandshatten" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "" "%{name} forlænger varigheden pÃ¥ heltens besværgelser med %{count} runder." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Du ser en magiker, flygtende fra en grif, mens han rider som vinden. " "Magikeren Ã¥bner en portal, rider igennem den og fÃ¥r sin hat slÃ¥et af ved en " "af portalens kanter. Griffen følger efter, portalen lukker i. Du samler " "hatten op, støver den af og tager den pÃ¥." msgid "Power Ring" msgstr "Kraftringen" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} returnerer helten %{count} ekstra magipoint om dagen." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Du finder et lille træ, der ligner den store heksemester Carnauth, med en " "ring omkring en af dens kviste. Rester af tøj og rÃ¥dnende læder fÃ¥r dig til " "at mistænke, at det ER Carnauth, forvandlet. Da du ikke kan hjælpe ham, " "tager du den magiske ring." msgid "Ammo Cart" msgstr "Ammunitionsvognen" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "%{name} giver heltens skydende tropper uendelig ammunition." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "En ammunitionsvogn midt pÃ¥ en gammel slagmark fanger dit blik. Nærmere " "eftersyn viser, at den er i god stand, sÃ¥ du tager den med dig." msgid "Tax Lien" msgstr "Pantebrevet" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} koster helten %{count} guldstykker om dagen." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Dine store forbrugsvaner har givet dig en massiv skattegæld, som du ikke kan " "hÃ¥be pÃ¥ at betale. Pantefogeden forbarmer sig og indvilliger i kun at " "modtage 250 guldstykker om dagen fra din konto, i resten af dit liv. Sæt " "kryds her, hvis du vil lade en krone gÃ¥ til præsidentkampagnens valgfond." msgid "Hideous Mask" msgstr "Den Hæslige Maske" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "%{name} forhindrer alle 'vandrende' hære i at tilslutte sig helten." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Din plyndring af Sinfilas Gardolads grav, den berømte formskiftende " "heksemester, afslører hans sagnomspundne maske. Rystende tager du den pÃ¥, og " "det vrider dit ansigt til en forfærdelig grimase! Ã…h nej! Det er faktisk " "Gromluck Greenes hæslige maske, og nu sidder den fast pÃ¥ dit ansigt." msgid "Endless Pouch of Sulfur" msgstr "Den Uudtømmelige Svovlpose" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} giver %{count} mængde svovl om dagen." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Du besøger en alkymist, som efter at have set din hær, bliver pÃ¥virket af " "din sags retskaffenhed. Din nye loyale undersÃ¥t giver dig sin uudtømmelige " "svovlpose, for at hjælpe med krigsindsatsen." msgid "Endless Vial of Mercury" msgstr "Den Uudtømmelige Kviksølvsflaske" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} giver %{count} mængde kviksølv om dagen." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Et kort stop ved en hurtigt forladt troldmandstÃ¥rn viser et magisk hætteglas " "med kviksølv, der altid har lidt tilbage pÃ¥ bunden. \n" "Da du kender et artefakt, nÃ¥r du ser en, lukker du den og lægger den i " "lommen." msgid "Endless Pouch of Gems" msgstr "Den Uudtømmelige Juvelpose" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} giver %{count} mængde juveler om dagen." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "En kort regnbyge frembringer en regnbue ... og du kan se, hvor den ender. Du " "rider hurtigt derhen og griber krukken med guld, som du finder der. Alfen, " "der ejer den, som ikke er i stand til at forhindre dig i at tage den, " "tilbyder dig en uudtømmelig juvelpose, for at fÃ¥ sit guld tilbage. Du " "accepterer tilbuddet." msgid "Endless Cord of Wood" msgstr "Den Endeløse Træsnor" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} giver %{count} mængder træ om dagen." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Mens du holder hvilepause og tænder et kogebÃ¥l, samler du brænde fra en " "nærliggende bunke dødt træ. Fortsættende med at trække træ fra bunken, " "bemærker du, at den ikke bliver mindre. Til din glæde indser du, at træet er " "fortryllet, sÃ¥ du tager hele bunken med dig." msgid "Endless Cart of Ore" msgstr "Den Uudtømmelige Malmvogn" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} giver %{count} mængder malm om dagen." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Du har fundet en vætte-vÃ¥bensmedje, der laver vÃ¥ben til brug mod mennesker. " "Med et voldsomt rÃ¥b gÃ¥r du og din hær ned mod deres lejr og driver dem væk. " "En søgen rundt afslører en magisk malmvogn, der aldrig løber tør for malm." msgid "Endless Pouch of Crystal" msgstr "Den Uudtømmelige krystalpose" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} giver %{count} mængde krystal om dagen." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Da du søger ly for en storm i en lille hule, bemærker du undervejs en lille " "samling af krystaller i det ene hjørne. Nysgerrig brækker du et stykke af og " "bemærker, at der ud af den originale krystal fremvokser et nyt stykke. Du " "beslutter dig for at proppe hele samlingen i en pose og tager den med dig." msgid "Spiked Helm" msgstr "Pighjelmen" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Din hær bliver overfaldet af en lille stamme af vilde (og ikke alt for " "kloge) orker. Du afværger dem let, og de overlevende flygter i alle " "retninger. En af orkerne bar en poleret pighjelm. Med et indtryk af, at den " "vil være en god souvenir, tager du den." msgid "Spiked Shield" msgstr "Pigskjoldet" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Du støder pÃ¥ en bro, der strækker sig over en udtørret bjergkløft. Før du " "kan krydse, træder en trold ud under broen og kræver betaling, før den giver " "dig lov til at passere. Du nægter. Trolden angriber, hvilket tvinger dig til " "at dræbe den. Du tager dets pigskjold som et trofæ." msgid "White Pearl" msgstr "Den Hvide Perle" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "En tur pÃ¥ tværs af en tør saltvandssø giver en usandsynlig gevinst: En hvid " "perle midt i knuste skaller og affald." msgid "Black Pearl" msgstr "Den Sorte Perle" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Rygter om en grif af usædvanlig størrelse, der terroriserer folk ude pÃ¥ " "landet, fører dig til dens klippehule. En hurtig, brutal kamp sender udyret " "af sted, og en undersøgelse af dens modbydelige rede afslører en enorm sort " "perle." msgid "Magic Book" msgstr "Magibog" msgid "The %{name} enables the hero to cast spells." msgstr "%{name} gør det muligt for helten at kaste besværgelser." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Pladsholder 2" msgid "The reserved artifact." msgstr "Pladsholder-artefaktet." msgid "Dummy 3" msgstr "Pladsholder 3" msgid "Dummy 4" msgstr "Pladsholder 4" msgid "Spell Scroll" msgstr "Trolddomsrulle" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "%{name} giver helten mulighed for at kaste besværgelsen %{spell}, hvis denne " "har en magibog." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Du finder en udførlig beholder, som rummer en gammel pergamentrulle. Runerne " "pÃ¥ beholderen er meget gamle. Det kunstgreb, der mÃ¥tte stÃ¥ bag dette " "hÃ¥ndværk, er storslÃ¥et. Lige som du trækker rullen ud, føler du dig " "gennemsyret af magisk kraft." msgid "Arm of the Martyr" msgstr "Martyrens Arm" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} øger heltens magikraft med %{count} point, men tilfører dennes hær " "moralstraffen for at have udøde i blandt sig." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Et af de mindre intelligente medlemmer af din hær samler en arm op fra " "jorden. PÃ¥ trods af at den mangler en krop, bevæger den sig stadig. Dine " "tropper finder den afhuggede arm frastødende, men du kan ikke fÃ¥ dig selv " "til at slippe den: Den ser ud til at have en slags magisk kraft, der " "pÃ¥virker din beslutsomhed." msgid "Breastplate of Anduran" msgstr "Andurans Brynje" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} øger forsvarsevne for heltens tropper med %{count} point." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Du støder pÃ¥ et skilt, hvorpÃ¥ der stÃ¥r: \"Her ligger Andurans lig. Bøj dig " "og sværg troskab, og du skal blive belønnet.\"\n" "Du beslutter dig for at gøre, som der stÃ¥r. Da du rejser dig op, mærker du " "en kulde mod din hud. Du kigger ned, og opdager, at du pludselig har en " "skinnende, udsmykket brynje pÃ¥." msgid "Broach of Shielding" msgstr "Beskyttelsens Broche" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} giver dine tropper %{count}% beskyttelse mod besværgelserne Ragnarok " "og Elemental Storm, men den reducerer ogsÃ¥ din magikraft med 2 point." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "En venlig heks syntes, at din hærs forsvarsevne godt kunne bruge et magisk " "løft. Hun tilbyder at fortrylle den broche, som du bærer pÃ¥ din kappe, og du " "accepterer." msgid "Battle Garb of Anduran" msgstr "Andurans Udstyr" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} kombinerer kræfterne fra Andurans tre artefakter. \n" "Det giver helten Byportal-besværgelsen samt maksimerer troppernes held og " "moral i kamp." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Af ren medlidenhed køber du en kiste fyldt med gammelt skrammel af en fattig " "bonde, som han godt ved, han kræver for meget guld for. \n" "Senere, mens du gennemsøger kisten, finder du ud af, at den indeholder de " "tre dele af Andurans legendariske kampudstyr!" msgid "Crystal Ball" msgstr "Krystalkuglen" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} gør det muligt for helten, at fÃ¥ flere specifikke informationer om " "væsener, fjendens helte og borge, som er i nærheden af denne." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Du støder pÃ¥ en sigøjnerkaravane, der fester og fylder deres kroppe med " "mjød. De kalder dig frem og siger \"Hvis du beviser, at du kan danse Rama-" "Buta, vil vi belønne dig.\" Du kender ikke dansen, men prøver alligevel. De " "griner hysterisk, men beundrer dit mod og giver dig en krystalkugle." msgid "Heart of Fire" msgstr "Hjertet af Ild" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} giver %{count}% beskyttelse mod ildbesværgelser, men fordobler " "skaden fra kuldebesværgelser." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Du gÃ¥r ind i en nyligt brændt lysning og støder pÃ¥ en ild-elemental, som " "sidder pÃ¥ toppen af en klippe. Den ser op, dens flammende ansigt forvredet i " "et blik af alvorlig smerte. Den kaster derefter en glødende genstand mod " "dig. Du løfter dine hænder for at parere den, men den passerer lige igennem " "dem og svier sig ind i dit bryst." msgid "Heart of Ice" msgstr "Hjertet af Is" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} giver %{count}% beskyttelse mod kuldebesværgelser, men fordobler " "skaden fra ildbesværgelser." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Pludselig griber en bidende kulde fat i din krop. Du forfryser og falder ned " "fra din hest. Smerten aftager, men du føler stadig, som om dit bryst er " "frosset. Du rejser dig fra jorden og hører en rungende latter. Du vender dig " "om, lige i tide til at se en frostkæmpe spurte ind i skoven og forsvinde." msgid "Helmet of Anduran" msgstr "Andurans Hjelm" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Du fÃ¥r øje pÃ¥ en skinnende genstand, der stikker op af jorden. Du sender et " "medlem af din hær over, for at undersøge sagen. Han kommer tilbage med en " "gylden hjelm i hænderne. Du indser, at det mÃ¥ være hjelmen tilhørende den " "legendariske Anduran, den eneste mand, der var kendt for at bære solidt " "guldudstyr." msgid "Holy Hammer" msgstr "Den Hellige Hammer" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Du støder ind i en kamp, hvor en paladin er blevet dødeligt sÃ¥ret af en " "gruppe zombier. Han beder dig om at tage hans hammer og afslutte det, han " "startede. Mens du samler den op, begynder den straks at summe, og sÃ¥ bliver " "alt sløret. Zombierne ligger døde, hammeren drypper af blod. Du spænder den " "fast i bæltet." msgid "Legendary Scepter" msgstr "Det Legendariske Scepter" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} tilføjer %{count} point til alle attributter." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Da du gÃ¥r op pÃ¥ en lille bakke, fÃ¥r du dig pÃ¥ et latterligt syn at se. En fe " "forsøger at bære et scepter, som er næsten lige sÃ¥ stort, som den er. Mens " "du forsøger ikke at grine, spørger du: \"Brug for hjælp?\" Feen stirrer pÃ¥ " "dig og svarer: \"Tror du, det her er sjovt? Fint. Du kan bære det. Jeg " "foretrækker alligevel at flyve.\"" msgid "Masthead" msgstr "Masthovedet" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} øger held og moral for heltens tropper med %{count} point, i søkamp." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "En gammel sømand fortæller dig en historie om en fortryllet mastehoved, som " "han, i sin ungdom, brugte til at samle sit mandskab i vanskeligheder. Han " "rækker dig sÃ¥ et falmet kort, der viser, hvor han gemte det. Efter megen " "udforskning finder du det gemt under en nærliggende dok." msgid "Sphere of Negation" msgstr "Negationskuglen" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} umuliggør kastning af besværgelser for begge sider i kamp." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Du stopper, for at hjælpe en bonde med at fange en løbsk hoppe. Han viser " "taknemmelighed, ved at række dig en lille kugle. SÃ¥ snart du griber om den, " "mærker du den magiske energi blive drænet fra dine lemmer..." msgid "Staff of Wizardry" msgstr "Troldmandsstav" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} øger heltens magikraft med %{count} point." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Mens de var ude at fange vildt, fandt dine tropper en mystisk stav, svævende " "omkring en meter over jorden. De overrækker den til dig, og du bemærker en " "inskription. Det lyder: \"Vid slÃ¥r muskler og magi slÃ¥r styrke. Lyt til mine " "ord, og du vil vinde hver kamp.\"" msgid "Sword Breaker" msgstr "Sværdbrækkeren" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} øger bÃ¥de heltens angrebs- og forsvarsevne med %{count} point." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "En tidligere kaptajn af vagten beundrer din sag og giver dig den fortryllede " "sværdbryder, som hans liv afhang af under sin tjenesterejse." msgid "Sword of Anduran" msgstr "Andurans Sværd" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "En trold standser dig og siger: \"Giv mig 5.000 guldstykker, ellers slÃ¥r " "Andurans Sværd dig ihjel, hvor du stÃ¥r.\" Du nægter. Trolden griber sværdet, " "som hænger i dets bælte, skriger af smerte og løber væk. \n" "Idet du samler det sagnomspundne sværd op, takker du for, at halvkloge " "trolde har tendens til at gribe fat den forkerte ende af skarpe genstande." msgid "Spade of Necromancy" msgstr "Nekromantikerens Spade" msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} øger heltens nekromantiske evne." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "En snavset skovl er blevet stukket ned i en jordhøj i nærheden. Efter en " "søgen opdager du, at det er dødgravernes fortryllede skovl, som man længe " "har troet var gÃ¥et tabt for dødelige." msgid "spellBonus|selected by user" msgstr "Valgt af bruger" msgid "Wood" msgstr "træ" msgid "Mercury" msgstr "kviksølv" msgid "Ore" msgstr "malm" msgid "Sulfur" msgstr "svovl" msgid "Crystal" msgstr "krystal" msgid "Gems" msgstr "juveler" msgid "Gold" msgstr "guld" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Der er syv resursetyper i Heroes 2. Disse bruges til at bygge og udvikle " "borge og byer samt rekruttering af helte og tropper.\n" "Guld er den mest almindelige resurse, som grundlæggende bruges til alt.\n" "Træ og malm bruges til de fleste byggerier.\n" "Kviksølv, svovl, krystaller og juveler er sjældne magiske resurser, som " "bruges til de mægtigste byggerier og væsener." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "FÃ¥r en kæmpe ildkugle til at ramme og give skade til alle væsener i det " "valgte omrÃ¥de." msgid "Fireball" msgstr "Ildkugle" msgid "Fireblast" msgstr "Flammebrag" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Rammer og giver skade til alle væsener i det valgte omrÃ¥de. Dette er en " "forbedret version af Ildkugle." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "FÃ¥r et lyn af elektrisk energi til at ramme det valgte væsen." msgid "Lightning Bolt" msgstr "Lynkile" msgid "Chain Lightning" msgstr "Lynkæde" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "FÃ¥r et lyn af elektrisk energi til først at ramme det valgte væsen, for " "derefter ramme dets nærmeste væsen med 50% skade, sÃ¥ det næstnærmeste væsen " "med 25% skade, og sÃ¥ videre, indtil det bliver for svagt til at være " "skadeligt. Advarsel: Denne besværgelse kan ramme dine egne tropper!" msgid "Teleport" msgstr "Teleport" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Teleporterer det væsen, du vælger, til en hvilken som helst Ã¥ben position pÃ¥ " "slagmarken." msgid "Cure" msgstr "Kur" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Fjerner alle negative besværgelser fra en af dine tropper og gendanner op " "til %{count} HP per magikraftspoint." msgid "Mass Cure" msgstr "Massekur" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Fjerner alle negative besværgelser, som din hær er blevet underlagt, og " "genopretter op til %{count} HP per magikraftspoint, per væsen." msgid "Resurrect" msgstr "Genoplivelse" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Genopliver væsener fra en beskadiget eller død trop indtil slutningen af " "kampen." msgid "Resurrect True" msgstr "Ægte genoplivelse" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Genopliver væsener fra en beskadiget eller død trop permanent." msgid "Haste" msgstr "Forhastning" msgid "Increases the speed of any creature by %{count}." msgstr "Øger en af dine troppers bevægelseshastighed med %{count} point." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Øger hele din hærs bevægelseshastighed med %{count} point." msgid "Mass Haste" msgstr "" "Masse-\n" "forhastning" msgid "Slows target to half movement rate." msgstr "Halverer en fjendtlig trops bevægelseshastighed." msgid "spell|Slow" msgstr "Forsløvning" msgid "Mass Slow" msgstr "" "Masse-\n" "forsløvning" msgid "Slows all enemies to half movement rate." msgstr "Halverer hele den fjendtlige hærs bevægelseshastighed." msgid "spell|Blind" msgstr "Blinding" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Skygger den berørte trops øjne og forhindrer dem i at bevæge sig." msgid "Bless" msgstr "Velsignelse" msgid "Causes the selected creatures to inflict maximum damage." msgstr "FÃ¥r den valgte trop til at yde maksimal skade." msgid "Causes all of your units to inflict maximum damage." msgstr "FÃ¥r hele din hær til at yde maksimal skade." msgid "Mass Bless" msgstr "" "Masse-\n" "velsignelse" msgid "Magically increases the defense skill of the selected creatures." msgstr "Øger pÃ¥ magisk vis den valgte trops forsvarsevne." msgid "Stoneskin" msgstr "Stenhud" msgid "Steelskin" msgstr "StÃ¥lhud" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Øger den valgte trops forsvarsevne. Dette er en forbedret version af " "besværgelsen Stenhud." msgid "Causes the selected creatures to inflict minimum damage." msgstr "FÃ¥r den valgte trop til at yde minimal skade." msgid "Curse" msgstr "Forbandelse" msgid "Causes all enemy troops to inflict minimum damage." msgstr "FÃ¥r alle fjendtlige tropper til at yde minimal skade." msgid "Mass Curse" msgstr "" "Masse-\n" "forbandelse" msgid "Damages all undead in the battle." msgstr "Skader alle udøde pÃ¥ slagmarken." msgid "Holy Word" msgstr "Helligt Ord" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Skader alle udøde pÃ¥ slagmarken. Dette er en forbedret version af Helligt " "Ord." msgid "Holy Shout" msgstr "Helligt RÃ¥b" msgid "Anti-Magic" msgstr "Anti-magi" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Forhindrer skadelig magi mod den valgte trop." msgid "Dispel Magic" msgstr "" "Magi-\n" "ophævelse" msgid "Removes all magic spells from a single target." msgstr "Fjerner alle magiske besværgelser fra den valgte trop." msgid "Mass Dispel" msgstr "" "Masse-\n" "ophævelse" msgid "Removes all magic spells from all creatures." msgstr "Fjerner alle magiske besværgelser fra samtlige tropper." msgid "Causes a magic arrow to strike the selected target." msgstr "FÃ¥r en magisk pil til at ramme den valgte trop." msgid "Magic Arrow" msgstr "Magisk Pil" msgid "Berserker" msgstr "Bersærker" msgid "Causes a creature to attack its nearest neighbor." msgstr "" "FÃ¥r en trop til, pÃ¥ sin tur, at angribe den nærmeste trop, ven som fjende!" msgid "Armageddon" msgstr "Ragnarok" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Guddommelig rædsel rammer slagmarken og forÃ¥rsager alvorlig skade pÃ¥ alle " "tropper." msgid "Elemental Storm" msgstr "Elemental Storm" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Magiske elementer strømmer ned pÃ¥ slagmarken og skader alle tropper." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "En regn af sten rammer det valgte omrÃ¥de pÃ¥ slagmarken, som skader alle " "berørte tropper." msgid "Meteor Shower" msgstr "Meteorregn" msgid "Paralyze" msgstr "Paralyse" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "Den valgte trop lammes og vil derefter være ude af stand til at bevæge sig " "eller slÃ¥ igen." msgid "Hypnotize" msgstr "Hypnose" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Bringer en enkelt fjendtlig trop under din kontrol, hvis dens HP er mindre " "end %{count} gange kasterens magikraftspoint." msgid "Cold Ray" msgstr "KoldstrÃ¥le" msgid "Drains body heat from a single enemy unit." msgstr "Dræner kropsvarmen fra en enkelt fjendtlig trop." msgid "Cold Ring" msgstr "Koldring" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Dræner kropsvarmen fra alle tropper omkring træfpunktet, men ikke inklusiv " "dette træfpunkt." msgid "Disrupting Ray" msgstr "" "Erossions-\n" "strÃ¥le" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Reducerer en fjendtlig trops forsvarsevne med 3 point." msgid "Damages all living (non-undead) units in the battle." msgstr "Skader alle levende (ikke-udøde) tropper pÃ¥ slagmarken." msgid "Death Ripple" msgstr "" "Døds-\n" "krusning" msgid "Death Wave" msgstr "" "Døds-\n" "bølge" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Skader alle levende (ikke-udøde) tropper pÃ¥ slagmarken. Dette er en " "forbedret version af besværgelsen Dødskrusning." msgid "Dragon Slayer" msgstr "" "Drage-\n" "dræber" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Øger i høj grad en trops angrebsevne mod drager." msgid "Blood Lust" msgstr "Blodtørst" msgid "Increases a unit's attack skill." msgstr "Øger en trops angrebsevne." msgid "Animate Dead" msgstr "" "Døde-\n" "besjæling" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "Genopliver væsener fra en beskadiget eller død udød trop permanent." msgid "Mirror Image" msgstr "Spejlbillede" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Skaber en illusionær trop, der dublerer en af dine eksisterende tropper. " "Denne illusionære trop giver det samme i skade som originalen, men den " "forsvinder, hvis den tager skade." msgid "Shield" msgstr "Skærmning" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halverer skade modtaget fra afstandsangreb for en enkelt trop. PÃ¥virker ikke " "skade modtaget af skydetÃ¥rne eller ballister." msgid "Mass Shield" msgstr "" "Masse-\n" "skærmning" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halverer skade modtaget fra afstandsangreb for hele din hær. PÃ¥virker ikke " "skade modtaget af skydetÃ¥rne eller ballister." msgid "Summon Earth Elemental" msgstr "" "Hidkald jord-\n" "elemental" msgid "Summons Earth Elementals to fight for your army." msgstr "Hidkald jord-elementaler til at kæmpe for din hær." msgid "Summon Air Elemental" msgstr "" "Hidkald luft-\n" "elemental" msgid "Summons Air Elementals to fight for your army." msgstr "Hidkald luft-elementaler til at kæmpe for din hær." msgid "Summon Fire Elemental" msgstr "" "Hidkald ild-\n" "elemental" msgid "Summons Fire Elementals to fight for your army." msgstr "Hidkald ild-elementaler til at kæmpe for din hær." msgid "Summon Water Elemental" msgstr "" "Hidkald vand-\n" "elemental" msgid "Summons Water Elementals to fight for your army." msgstr "Hidkald vand-elementaler til at kæmpe for din hær." msgid "Damages castle walls." msgstr "Skader alle borgmure." msgid "Earthquake" msgstr "Jordskælv" msgid "Causes all mines across the land to become visible." msgstr "FÃ¥r alle miner pÃ¥ tværs af landet til at blive synlige." msgid "View Mines" msgstr "Vis miner" msgid "Causes all resources across the land to become visible." msgstr "FÃ¥r alle resurser pÃ¥ tværs af landet til at blive synlige." msgid "View Resources" msgstr "Vis resurser" msgid "Causes all artifacts across the land to become visible." msgstr "FÃ¥r alle artefakter pÃ¥ tværs af landet til at blive synlige." msgid "View Artifacts" msgstr "Vis artefakter" msgid "Causes all towns and castles across the land to become visible." msgstr "FÃ¥r alle byer og borge over hele landet til at blive synlige." msgid "View Towns" msgstr "Vis byer" msgid "Causes all Heroes across the land to become visible." msgstr "FÃ¥r alle helte over hele landet til at blive synlige." msgid "View Heroes" msgstr "Vis helte" msgid "Causes the entire land to become visible." msgstr "FÃ¥r hele landet til at blive synligt." msgid "View All" msgstr "Vis alt" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" "Giver kasteren mulighed for at se detaljerede oplysninger om modstander-" "helte." msgid "Summon Boat" msgstr "Hidkald skib" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Hidkalder det nærmeste ubesatte, venlige skib til et tilstødende landsted. " "Et venligt skib kan være et skib, som du lige har bygget eller har været den " "seneste spiller til at besætte." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Tillader kasteren pÃ¥ magisk vis at teleportere sig selv og hele sin hær til " "et nærliggende sted." msgid "Dimension Door" msgstr "" "Dimensions-\n" "dør" msgid "Returns the caster to any town or castle currently owned." msgstr "Returnerer kasteren til enhver af spillerens byer eller borge." msgid "Town Gate" msgstr "Byflugt" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Returnerer helten til en af dine byer eller borge, efter eget valg, forudsat " "at den er under din kontrol." msgid "Visions" msgstr "Visioner" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "'Visioner' forudsiger det sandsynlige udfald af et møde med en neutral " "hærlejr." msgid "Haunt" msgstr "Besæt" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Hjemsøger en mine du kontrollerer, med spøgelser. Denne mine holder op med " "at producere resurser. ('Hvis jeg ikke kan beholde den, er der ingen der " "vil!')" msgid "Set Earth Guardian" msgstr "Sæt Jord-vagt" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Sætter jord-elementaler til at beskytte en mine mod fjendtlige hære." msgid "Set Air Guardian" msgstr "Sæt Luft-vagt" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Sætter luft-elementaler til at beskytte en mine mod fjendtlige hære." msgid "Set Fire Guardian" msgstr "Sæt Ild-vagt" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Sætter ild-elementaler til at beskytte en mine mod fjendtlige hære." msgid "Set Water Guardian" msgstr "Sæt Vand-vagt" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Sætter vand-elementaler til at beskytte en mine mod fjendtlige hære." msgid "Random Spell" msgstr "Tilfældig besværgelse" msgid "Randomly selected spell of any level." msgstr "Tilfældigt valgt besværgelse fra ethvert niveau." msgid "Random 1st Level Spell" msgstr "Tilfældig 1.niveau besværgelse" msgid "Randomly selected 1st level spell." msgstr "Tilfældigt valgt 1.niveau besværgelse." msgid "Random 2nd Level Spell" msgstr "Tilfældig 2.niveau besværgelse" msgid "Randomly selected 2nd level spell." msgstr "Tilfældigt valgt 2.niveau besværgelse." msgid "Random 3rd Level Spell" msgstr "Tilfældig 3.niveau besværgelse." msgid "Randomly selected 3rd level spell." msgstr "Tilfældigt valgt 3.niveau besværgelse." msgid "Random 4th Level Spell" msgstr "Tilfældig 4.niveau besværgelse." msgid "Randomly selected 4th level spell." msgstr "Tilfældigt valgt 4.niveau besværgelse." msgid "Random 5th Level Spell" msgstr "Tilfældig 5.niveau besværgelse." msgid "Randomly selected 5th level spell." msgstr "Tilfældigt valgt 5.niveau besværgelse." msgid "Petrification" msgstr "Forstening" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Forvandler den berørte trop til sten. En forstenet trop fÃ¥r halv skade fra " "et direkte angreb." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Du har ingen magibog, sÃ¥ du kan ikke kaste magi." msgid "No spell to cast." msgstr "Ingen magi at kaste." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Din helt har %{point} manapoint tilbage." msgid "View Adventure Spells" msgstr "Vis eventyrmagi" msgid "View Combat Spells" msgstr "Vis kampmagi" msgid "View previous page" msgstr "Vis forrige side" msgid "View next page" msgstr "Vis næste side" msgid "Close Spellbook" msgstr "Luk magibog" msgid "View %{spell}" msgstr "Vis %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Denne besværgelse giver %{damage} i skade." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Denne besværgelse hidkalder\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Denne besværgelse gendanner %{hp} HP." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" "Denne besværgelse hidkalder %{count} %{monster}, for at beskytte minen." msgid "The nearest town is %{town}." msgstr "Den nærmeste by er %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Denne by er besat af helten %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Denne besværgelse kontrollerer op til\n" "%{hp} HP." msgid "The ultimate artifact is really the %{name}." msgstr "Det ultimative artefakt er i virkeligheden %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Det ultimative artefakt kan findes i verdens %{name}-regioner." msgid "north-west" msgstr "nordvest" msgid "north" msgstr "nord" msgid "north-east" msgstr "nordøst" msgid "west" msgstr "vest" msgid "center" msgstr "centrum" msgid "east" msgstr "øst" msgid "south-west" msgstr "sydvest" msgid "south" msgstr "syd" msgid "south-east" msgstr "sydøst" msgid "The truth is out there." msgstr "Sandheden er derude." msgid "The dark side is stronger." msgstr "Den mørke side er stærkere." msgid "The end of the world is near." msgstr "Verdens ende er nær." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Fyrst Slayers knogler er begravet i arenaens fundament." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "En sortdrage kan til enhver tid klare en titan." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" "Til hende sagde han: \"snakke, snakke, snakke...\", og til det svarede hun: " "\"Bla, bla, bla...\"" msgid "An unknown force is being resurrected..." msgstr "En ukendt styrke er ved at genopstÃ¥..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Check den nyeste version af spillet pÃ¥\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Vælg antal %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Aktiver Autokamp" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "Færdiggør kampen automatisk" #~ msgid "Please Remember" #~ msgstr "Husk venligst" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Du kan altid ændre sprog, spilopløsning eller -indstillinger ved at " #~ "klikke pÃ¥ " #~ msgid "door" #~ msgstr "døren" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " pÃ¥ venstre side a hovedmenuen, eller med denne " #~ msgid " button from the " #~ msgstr " knap fra " #~ msgid "NEW GAME" #~ msgstr "NYT SPIL" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ " menu. \n" #~ "\n" #~ "Nyd spillet!" #~ msgid "Warning!" #~ msgstr "Advarsel!" #~ msgid "Dummy 1" #~ msgstr "Pladsholder 1" fheroes2-1.1.6+dfsg/files/lang/es.po000066400000000000000000011026601476115357100171650ustar00rootroot00000000000000# Spanish translation for fheroes2 # Copyright (C) 2020 - 2025 fheroes2 team # Copyright (C) 2009 Rosetta Contributors and Canonical Ltd 2009 # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-10-07 15:36+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: Spanish \n" "Language: es\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-Launchpad-Export-Date: 2013-10-09 02:01+0000\n" "X-Generator: Poedit 3.4.4\n" msgid "" "NEW\n" "GAME" msgstr "" "NUEVO\n" "JUEGO" msgid "" "SAVE\n" "GAME" msgstr "" "GUARD.\n" "PAR-\n" "TIDA" msgid "" "LOAD\n" "GAME" msgstr "" "CARGAR\n" "PAR-\n" "TIDA" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "SALIR" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "NUEVO\n" "JUEGO" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "GUARD.\n" "PAR-\n" "TIDA" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "CARGAR\n" "PAR-\n" "TIDA" msgid "CANCEL" msgstr "CANCELAR" msgid "OKAY" msgstr "VALE" msgid "ACCEPT" msgstr "ACEPTAR" msgid "DECLINE" msgstr "RECHAZAR" msgid "LEARN" msgstr "ESCOGE" msgid "TRADE" msgstr "COMERCIAR" msgid "YES" msgstr "SÃ" msgid "NO" msgstr "NO" msgid "EXIT" msgstr "SALIR" msgid "smallerButton|EXIT" msgstr "SALIR" msgid "DISMISS" msgstr "DESPEDIR" msgid "UPGRADE" msgstr "MEJORAR" msgid "RESTART" msgstr "REINICIAR" msgid "HEROES" msgstr "HÉROES" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "CIU-\n" "DADES" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "XL" msgid "ALL" msgstr "TODO" msgid "SELECT" msgstr "ESCOGER" msgid "" "STANDARD\n" "GAME" msgstr "" "PARTIDA\n" "ESTÃNDAR" msgid "" "BATTLE\n" "ONLY" msgstr "BATALLA" msgid "" "CAMPAIGN\n" "GAME" msgstr "CAMPAÑA" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "MULTI-\n" "JUGADOR" msgid "CONFIG" msgstr "AJUSTES" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "CAMPAÑA\n" "ORIGINAL" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "CAMPAÑA\n" "DE EXPAN-\n" "SIÓN" msgid "HOT SEAT" msgstr "ASIENTO CALIENTE" msgid "2 PLAYERS" msgstr "" "2 JUGA-\n" "DORES" msgid "3 PLAYERS" msgstr "" "3 JUGA-\n" "DORES" msgid "4 PLAYERS" msgstr "" "4 JUGA-\n" "DORES" msgid "5 PLAYERS" msgstr "" "5 JUGA-\n" "DORES" msgid "6 PLAYERS" msgstr "" "6 JUGA-\n" "DORES" msgid "GIFT" msgstr "DONAR" msgid "MAX" msgstr "MÃX" msgid "DIFFICULTY" msgstr "DIFICULTAD" msgid "VIEW INTRO" msgstr "VER INTRO" msgid "MIN" msgstr "MÃN" msgid "RESET" msgstr "REINICIAR" msgid "START" msgstr "COMENZAR" msgid "TOWN" msgstr "CIUDAD" msgid "CASTLE" msgstr "CASTILLO" #, fuzzy msgid "RESTRICT" msgstr "REINICIAR" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "D\n" "E\n" "S\n" "P\n" "E\n" "D\n" "I\n" "R" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "S\n" "A\n" "L\n" "I\n" "R" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "C\n" "A\n" "M\n" "P\n" "A\n" "Ñ\n" "A" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "E\n" "S\n" "T\n" "Ã\n" "N\n" "D\n" "A\n" "R" msgid "RUMORS" msgstr "RUMORES" msgid "EVENTS" msgstr "EVENTOS" msgid "LANGUAGE" msgstr "IDIOMA" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Guerrero" msgid "Builder" msgstr "Constructor" msgid "Explorer" msgstr "Explorador" msgid "None" msgstr "Ninguno" msgid "" "A few\n" "%{monster}" msgstr "" "Unos pocos\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Varios\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Un grupo de\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Muchos\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Una horda de\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Una multitud de\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Un enjambre de\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Demasiados\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Una legión de\n" "%{monster}" msgid "army|Few" msgstr "Pocos" msgid "army|Several" msgstr "Varios" msgid "army|Pack" msgstr "Grupo" msgid "army|Lots" msgstr "Muchos" msgid "army|Horde" msgstr "Horda" msgid "army|Throng" msgstr "Multitud" msgid "army|Swarm" msgstr "Enjambre" msgid "army|Zounds" msgstr "Demasiados" msgid "army|Legion" msgstr "Legión" msgid "All %{race} troops +1" msgstr "Todas las tropas %{race} +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Neutral" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Tropas de %{count} alineamientos -%{penalty}" msgid "Some undead in army -1" msgstr "Algunos nomuertos en el ejercito -1" msgid "" "Default\n" "troop" msgstr "" "Por defecto\n" "Tropa" msgid "View %{name}" msgstr "Ver %{name}" msgid "Move the %{name} " msgstr "Mueve el %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Mueve o haz clic derecho para redistribuir %{name}" msgid "Combine %{name} armies" msgstr "Combina los ejércitos de %{name}" msgid "Exchange %{name2} with %{name}" msgstr "Intercambiar %{name2} por %{name}" msgid "Select %{name}" msgstr "Seleccionar %{name}" msgid "Cannot move last troop" msgstr "No puedes mover la última tropa" #, fuzzy msgid "Move the %{name}" msgstr "Pierdes el héroe: %{name}." msgid "Set %{monster} Count" msgstr "Establece la cantidad de %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "El %{name} elimina mitad de las tropas enemigas!" msgstr[1] "Los %{name} eliminan mitad de las tropas enemigas!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "Daña a todos los Nomuertos en combate." #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "Daña a todos los Nomuertos en combate." msgid "Spell failed!" msgstr "¡Hechizo fallido!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "El artefacto Esfera de la Negación está afectando a esta batalla, " "deshabilitando todos los hechizos de combate." msgid "You cannot cast spells without a commanding hero." msgstr "No puedes lanzar hechizos sin un héroe." msgid "You have already cast a spell this round." msgstr "Ya has lanzado un hechizo en este turno." msgid "That spell will have no effect!" msgstr "¡Ese hechizo no tendrá ningún efecto!" msgid "You may only summon one type of elemental per combat." msgstr "Solo puedes convocar un tipo de elemental por combate." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "No hay un espacio libre adyacente a tu héroe para convocar un Elemental." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "El foso reduce la habilidad de defensa de las tropas atrapadas en él en un " "%{count} y limita su rango de movimiento." msgid "Speed: %{speed}" msgstr "Velocidad: %{speed}" msgid "Speed" msgstr "Velocidad" msgid "Off" msgstr "Desactivado" msgid "On" msgstr "Activado" msgid "Turn Order" msgstr "Orden de turno" #, fuzzy msgid "Auto Spell Casting" msgstr "Conjuradores" msgid "Grid" msgstr "Rejilla" #, fuzzy msgid "Shadow Movement" msgstr "Continuar movimento" msgid "Shadow Cursor" msgstr "Cursor Sombreado" msgid "Audio" msgstr "Sonido" msgid "Settings" msgstr "Ajustes" msgid "Configure" msgstr "Configurar" msgid "Hot Keys" msgstr "Atajos de Teclado" msgid "Damage Info" msgstr "Info de Daño" msgid "Set the speed of combat actions and animations." msgstr "Ajustar velocidad de las acciones y animaciones de combate." msgid "Toggle to display the turn order during the battle." msgstr "" "Activar o desactivar para mostrar el orden de turno durante la batalla." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Activa o desactiva si la computadora lanzará hechizos por ti cuando el " "combate automático esté activado. (Nota: Esto no afecta de ninguna manera el " "lanzamiento de hechizos por parte de los jugadores controlados por la " "computadora, ni afecta al combate rápido)." msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Activa o desactiva la cuadrícula hexagonal. El movimiento siempre se realiza " "en base a los hexágonos, incluso cuando la cuadrícula no está visible. Esta " "opción solo controla si la cuadrícula se muestra o no." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Activa o desactiva las sombras que muestran dónde pueden moverse y atacar " "tus criaturas." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Activa o desactiva una sombra que muestra la ubicación actual del cursor del " "ratón en el hexágono." msgid "Change the audio settings of the game." msgstr "Cambia la configuración de audio del juego." msgid "Check and configure all the hot keys present in the game." msgstr "" "Comprueba y configura todas las teclas de acceso rápido presentes en el " "juego." msgid "Toggle to display damage information during the battle." msgstr "" "Activa o desactiva para mostrar la información de daño durante la batalla." msgid "Exit this menu." msgstr "Salir de este menú." msgid "Okay" msgstr "Vale" msgid "The enemy has surrendered!" msgstr "¡El enemigo se ha rendido!" msgid "Their cowardice costs them %{gold} gold." msgstr "Su cobardía le cuesta %{gold} piezas de oro." msgid "The enemy has fled!" msgstr "¡El enemigo ha huido!" msgid "A glorious victory!" msgstr "¡Una gloriosa victoria!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Por valor en el combate, %{name} recibe %{exp} experiencia." msgid "The cowardly %{name} flees from battle." msgstr "El cobarde %{name} huye de la batalla." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} se rinde al enemigo, marchandose avergonzado." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Tus fuerzas sufren una amarga derrota, y %{name} abandona tu causa." msgid "Your forces suffer a bitter defeat." msgstr "Tus fuerzas sufren una amarga derrota." msgid "Battlefield Casualties" msgstr "Bajas en el campo de batalla" msgid "Attacker" msgstr "Agresor" msgid "Defender" msgstr "Defensor" #, fuzzy msgid "Click to leave the battle results." msgstr "Haz clic para volver al menú principal" #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Haz clic para volver al menú principal" msgid "Restart" msgstr "Reiniciar" msgid "You have captured an enemy artifact!" msgstr "¡Has capturado un artefacto enemigo!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Cuando coges %{name}, desaparece misteriosamente." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Cuando tu enemigo coge %{name}, desaparece misteriosamente." msgid "Necromancy!" msgstr "¡Nigromancia!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Practicando las oscuras artes de la nigromancia, eres capaz de alzar " "%{count} de los enemigos muertos para que vuelvan bajo tu servicio como " "%{monster}." msgid "%{name} the %{race}" msgstr "%{name}, %{race}" msgid "Captain of %{name}" msgstr "El capitán de %{name}" msgid "Attack" msgstr "Ataque" msgid "Defense" msgstr "Defensa" msgid "Spell Power" msgstr "Potencia" msgid "Knowledge" msgstr "Conocimiento" msgid "Morale" msgstr "Moral" msgid "Luck" msgstr "Suerte" msgid "Spell Points" msgstr "Maná" msgid "Hero's Options" msgstr "Opciones del Héroe" msgid "Cast Spell" msgstr "Lanzar Hechizo" msgid "Retreat" msgstr "Retirarse" msgid "Surrender" msgstr "Rendirse" msgid "Cancel" msgstr "Cancelar" msgid "Hero Screen" msgstr "Pantalla de Héroe" msgid "Captain's Options" msgstr "Opciones del capitán" #, fuzzy msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Lanza un hechizo mágico. Solo se puede lanzar un hechizo por ronda de " "combate. La ronda de combate vuelve a comenzar cuando todas las criaturas " "han tenido un turno." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Retirar a tu héroe, abandonando sus criaturas. Tu héroe estará disponible " "para que lo reclutes, sin embargo, el héroe tendrá los reclutas de un novato " "(como cualquier otro héroe)." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Rendirse cuesta oro. Sin embargo, si pagas el rescate, el héroe y todas sus " "criaturas supervivientes estarán disponibles para ser reclutadas otra vez." #, fuzzy msgid "Open Hero Screen to view full information about the hero." msgstr "Permite al lanzador ver información detallada de los héroes enemigos." msgid "Return to the battle." msgstr "Volver a la batalla." msgid "Not enough gold (%{gold})" msgstr "No hay suficiente oro (%{gold})" msgid "%{name} states:" msgstr "%{name} declara:" msgid "Captain of %{name} states:" msgstr "El capitán de %{name} declara:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Aceptaré tu rendición y concederé salvoconducto a ti y tus tropas por " "%{price} piezas de oro.\"" msgid "View %{monster} info" msgstr "Ver información de %{monster}" msgid "Fly %{monster} here" msgstr "%{monster} vuela aquí" msgid "Move %{monster} here" msgstr "Mover a %{monster} aquí" msgid "Shoot %{monster}" msgstr "Dispara a %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 tiro restante)" msgstr[1] "(%{count} tiros restantes)" msgid "Attack %{monster}" msgstr "Atacar a %{monster}" msgid "Turn %{turn}" msgstr "Turno %{turn}" msgid "Teleport here" msgstr "Teletransportar aquí" msgid "Invalid teleport destination" msgstr "Destino de teletransporte inválido" msgid "Cast %{spell} on %{monster}" msgstr "Lanzar %{spell} sobre %{monster}" msgid "Cast %{spell}" msgstr "Lanzar %{spell}" msgid "Select spell target" msgstr "Seleccionar objetivo del hechizo" msgid "View Ballista info" msgstr "Ver información de la ballesta" msgid "Ballista" msgstr "Balista" msgid "Automatic combat modes" msgstr "Combate Automático" #, fuzzy msgid "Automatic Combat Modes" msgstr "Combate Automático" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Personalizar opciones de sistema" msgid "Allows you to customize the combat screen." msgstr "Te permite personalizar la pantalla de combate." msgid "System Options" msgstr "Opciones de Sistema" msgid "Skip this unit" msgstr "Saltar el turno de esta unidad" msgid "Skip" msgstr "Saltar" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Salta la criatura actual. La criatura actual termina su turno y no puede " "volver a jugar hasta la siguiente ronda." msgid "View Captain's options" msgstr "Ver opciones de Capitán" #, fuzzy msgid "View Hero's options" msgstr "Opciones del héroe" msgid "View opposing Captain" msgstr "Ver Capitán del oponente" msgid "View opposing Hero" msgstr "Ver Héroe del oponente" msgid "Hide logs" msgstr "Ocultar registro" msgid "Show logs" msgstr "Mostrar registros" msgid "Message Bar" msgstr "Barra de mensajes" msgid "Shows the results of individual monster's actions." msgstr "Muestra los resultados de las acciones de cada monstruo." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "¿Estás seguro de que quieres activar el combate automático?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "¿Estás seguro de que quieres terminar la batalla en modo automático?" msgid "The computer continues the combat for you." msgstr "" msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Combate Automático" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Combate Automático" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} se pasa su turno." msgstr[1] "%{name} se pasan su turno." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} hace %{damage} de daño." msgstr[1] "%{attacker} hacen %{damage} de daño." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "Una criatura perece." msgstr[1] "%{count} criaturas perecen." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} perece." msgstr[1] "%{count} %{defender} perecieron." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 alma está incorporada." msgstr[1] "%{count} almas están incorporadas." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} revive." msgstr[1] "%{count} %{unit} reviven." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "%{monster} movido: De [%{src}] a [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "¡El %{name} resiste el hechizo!" msgstr[1] "¡Los %{name} resisten el hechizo!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} lanza %{spell} sobre %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} lanza %{spell}." #, fuzzy msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "" "El hechizo %{spell} hace %{damage} puntos de daño a todas las criaturas " "nomuertas." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "" "El hechizo %{spell} hace %{damage} puntos de daño a todas las criaturas " "nomuertas." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "" "El hechizo %{spell} hace %{damage} puntos de daño, %{count} criaturas " "perecen." msgid "The %{spell} does %{damage} damage." msgstr "El hechizo %{spell} hacen %{damage} de daño." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "El hechizo %{spell} hace %{damage} puntos de daño a una criatura viva." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "" "El hechizo %{spell} hace %{damage} puntos de daño a todas las criaturas " "vivas." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "¡El ataque del %{attacker} ciega a %{target}!" msgstr[1] "¡El ataque de los %{attacker} ciega a %{target}!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "¡La mirada de la %{attacker} convierte a %{target} en piedra!" msgstr[1] "¡La mirada de las %{attacker} convierte a %{target} en piedra!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "¡La maldición de la %{attacker} cae sobre %{target}!" msgstr[1] "¡La maldición de las %{attacker} cae sobre %{target}!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "¡%{target} es paralizado por el %{attacker}!" msgstr[1] "¡%{target} es paralizado por los %{attacker}!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "¡El %{attacker} dispersó todos los hechizos buenos en tu %{target}!" msgstr[1] "" "¡Los %{attacker} dispersaron todos los hechizos buenos en tu %{target}!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "¡El %{attacker} lanza %{spell} sobre %{target}!" msgstr[1] "¡Los %{attacker} lanzan %{spell} sobre %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "La mala suerte desciende sobre %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "La buena suerte brilla sobre %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "La alta moral permite a %{monster} atacar otra vez." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "La baja moral provoca que %{monster} se paralice por el pánico." msgid "%{tower} does %{damage} damage." msgstr "La %{tower} ha causado %{damage} de daño." #, fuzzy msgid "The mirror image is created." msgstr "Reflejo creado." msgid "The mirror image is destroyed!" msgstr "¡La imagen espejo ha sido destruida!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "¿Estas seguro de que quieres interrumpir la batalla automática?" msgid "Error" msgstr "Error" msgid "No spells to cast." msgstr "No hay hechizos para lanzar." msgid "Are you sure you want to retreat?" msgstr "¿Estás seguro de que quieres retirarte?" msgid "Retreat disabled" msgstr "Retirada desactivada" msgid "Surrender disabled" msgstr "Rendición desactivada" msgid "Damage: %{max}" msgstr "Daño: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Daño: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Mueren: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Mueren: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Mediante la observación del ojo de aquila, %{name} es capaz de aprender el " "hechizo mágico %{spell}." msgid "Human" msgstr "Humano" msgid "AI" msgstr "IA" msgid "Start" msgstr "Comenzar" msgid "Start the battle." msgstr "Comenzar la batalla." msgid "Exit" msgstr "Salir" msgid "Reset" msgstr "Reiniciar" msgid "Reset to default settings." msgstr "Restablecer la configuración predeterminada." msgid "Please select another hero." msgstr "Por favor, selecciona otro héroe." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} vs %{race2} %{name2}" msgid "Monsters" msgstr "Monstruos" msgid "N/A" msgstr "N/D" msgid "Left Turret" msgstr "Torreón Izquierdo" msgid "Right Turret" msgstr "Torreón Derecho" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "La %{name} dispara con la fuerza de %{count} Arqueros" msgid "each with a +%{attack} bonus to their attack skill." msgstr "cada uno con un bono de +%{attack} a su ataque." msgid "The %{name} is destroyed." msgstr "La %{name} es destruida." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "¡%{count} %{name} se eleva de la muerte!" msgstr[1] "¡%{count} %{name} se elevan de la muerte!" msgid "Dwarven Alliance" msgstr "Alianza de enanos" msgid "Sorceress Guild" msgstr "Gremio de hechiceras" msgid "Necromancer Guild" msgstr "Gremio de Nigromantes" msgid "Ogre Alliance" msgstr "Alianza de ogros" msgid "Dwarfbane" msgstr "Asesina de enanos" msgid "Dragon Alliance" msgstr "Alianza Dragontina" msgid "Elven Alliance" msgstr "Alianza Élfica" msgid "Kraeger defeated" msgstr "Kraeger derrotado" msgid "Wayward Son" msgstr "Hijo Descarriado" msgid "Uncle Ivan" msgstr "Tío Iván" msgid "Annexation" msgstr "Anexión" msgid "Force of Arms" msgstr "Fuerza de las Armas" msgid "Save the Dwarves" msgstr "Salva a los Enanos" msgid "Carator Mines" msgstr "Minas de Carator" msgid "Turning Point" msgstr "Momento Crucial" msgid "scenarioName|Defender" msgstr "Defensor" msgid "Corlagon's Defense" msgstr "Defensa de Corlagon" msgid "The Crown" msgstr "La Corona" msgid "The Gauntlet" msgstr "El Guantelete" msgid "Betrayal" msgstr "Traición" msgid "Final Justice" msgstr "Justicia Final" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" msgid "Barbarian Wars" msgstr "Guerras Bárbaras" msgid "First Blood" msgstr "Primera Sangre" msgid "Necromancers" msgstr "Nigromantes" msgid "Slay the Dwarves" msgstr "Da muerte a los Enanos" msgid "Country Lords" msgstr "Señores del Pais" msgid "Dragon Master" msgstr "Maestro Dragón" msgid "Rebellion" msgstr "Rebelión" msgid "Apocalypse" msgstr "Apocalipsis" msgid "Greater Glory" msgstr "Gloria Mayor" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" msgid "Arrow's Flight" msgstr "" #, fuzzy msgid "Island of Chaos" msgstr "Isla de los Elfos" msgid "The Abyss" msgstr "" msgid "Uprising" msgstr "" msgid "Aurora Borealis" msgstr "" #, fuzzy msgid "Betrayal's End" msgstr "\"¡Traición!\"" #, fuzzy msgid "Corruption's Heart" msgstr "Alojamiento del Capitán" #, fuzzy msgid "The Giant's Pass" msgstr "Los yermos reales" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" msgid "For the good of the Empire, eliminate Kraeger." msgstr "" msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" #, fuzzy msgid "Border Towns" msgstr "Tierras fronterizas" msgid "Conquer and Unify" msgstr "" #, fuzzy msgid "Crazy Uncle Ivan" msgstr "Uncle Ivan" msgid "The Wayward Son" msgstr "El Hijo Descarriado" msgid "Ivory Gates" msgstr "Puertas de Marfil" #, fuzzy msgid "The Elven Lands" msgstr "Siete Lagos" msgid "The Epic Battle" msgstr "" #, fuzzy msgid "The Southern War" msgstr "El Otro Lado" #, fuzzy msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Une las Tribus. No pierdas a tu héroe principal, el primer Descendiente." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" #, fuzzy msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Encuentra a tu caprichoso hijo, del que se rumorea que vive en las tierras " "desoladas. Házlo en menos de 8 semanas o no será de ninguna ayuda para tu " "familia." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Rescata a tu loco Tío Iván. Encuéntrale en 4 meses o no habrá ayuda para tu " "reino." #, fuzzy msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "¡Destruye a los Bárbaros que están atacando la frontera sur de tu reino! " "Recupera tus ciudades y entonces invade el reino jungla." #, fuzzy msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Reconquista el Castillo de las Puertas de Marfil." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Consigue la ayuda de los elfos. No permitirán que se talen árboles, así que " "te enviaremos madera cada 2 semanas. ¡Tienes 7 meses!" msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" #, fuzzy msgid "Fount of Wizardry" msgstr "El Cayado de Brujería" #, fuzzy msgid "Power's End" msgstr "Anillo de Poder" #, fuzzy msgid "The Eternal Scrolls" msgstr "La Isla Esmeralda" #, fuzzy msgid "The Shrouded Isles" msgstr "La Isla Esmeralda" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" msgid "Blood is Thicker" msgstr "La Sangre es Espesa" msgid "King and Country" msgstr "Rey y Patria" #, fuzzy msgid "Pirate Isles" msgstr "Ensenada Pirata" msgid "Stranded" msgstr "" #, fuzzy msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Captura la ciudad de la isla en la costa sureste para construir un barco y " "navegar de vuelta al continente." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" msgid " bane" msgstr "" msgid " alliance" msgstr " alianza" msgid "Carry-over forces" msgstr "Fuerzas mantenidas" msgid " bonus" msgstr " bonificación" msgid " defeated" msgstr " derrotado" msgid " will always run away from your army." msgstr "" msgid " will be willing to join your army." msgstr "" msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" msgid "The army will be carried over in the campaign." msgstr "" msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" msgid "%{hero} can be hired during scenarios." msgstr "" msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "" msgid "campaignBonus|Animate Dead" msgstr "Animar Muertos" msgid "campaignBonus|Chain Lightning" msgstr "Cadena de Rayos" msgid "campaignBonus|Fireblast" msgstr "" msgid "campaignBonus|Mass Curse" msgstr "" msgid "campaignBonus|Mass Haste" msgstr "" msgid "campaignBonus|Mirror Image" msgstr "Doble Imagen" msgid "campaignBonus|Resurrect" msgstr "" #, fuzzy msgid "campaignBonus|Steelskin" msgstr "Anillo del Mago del Poder" #, fuzzy msgid "campaignBonus|Summon Earth" msgstr "LLamar Barco" msgid "campaignBonus|View Heroes" msgstr "Ver Heroes" msgid "campaignBonus|Ballista" msgstr "" msgid "campaignBonus|Black Pearl" msgstr "Perla Negra" #, fuzzy msgid "campaignBonus|Caster's Bracelet" msgstr "Brazalete del Lanzador de la Magia" #, fuzzy msgid "campaignBonus|Defender Helm" msgstr "Defensor" msgid "campaignBonus|Breastplate" msgstr "Peto de Anduran" #, fuzzy msgid "campaignBonus|Dragon Sword" msgstr "Matadragones" msgid "campaignBonus|Fizbin Medal" msgstr "" #, fuzzy msgid "campaignBonus|Foremost Scroll" msgstr "Principal Pergamino de Conocimiento" msgid "campaignBonus|Gauntlets" msgstr "Guanteletes" msgid "campaignBonus|Hideous Mask" msgstr "Máscara Horrenda" msgid "campaignBonus|Mage's Ring" msgstr "Anillo del Mago del Poder" #, fuzzy msgid "campaignBonus|Major Scroll" msgstr "Rollo Mayor del Conocimiento" msgid "campaignBonus|Medal of Honor" msgstr "La Medalla de Honor" msgid "campaignBonus|Medal of Valor" msgstr "La Medalla de Valor" msgid "campaignBonus|Minor Scroll" msgstr "Pergamino Menor de Conocimiento" #, fuzzy msgid "campaignBonus|Nomad Boots" msgstr "Nómadas" msgid "campaignBonus|Power Axe" msgstr "" msgid "campaignBonus|Spiked Shield" msgstr "Escudo Picudo" #, fuzzy msgid "campaignBonus|Stealth Shield" msgstr "El Escudo Supremo" msgid "campaignBonus|Tax Lien" msgstr "" msgid "campaignBonus|Thunder Mace" msgstr "Maza del Trueno de Dominio" msgid "campaignBonus|Traveler's Boots" msgstr "Botas de Viajero de la Movilidad" msgid "campaignBonus|White Pearl" msgstr "Perla Blanca" #, fuzzy msgid "campaignBonus|Basic Archery" msgstr "Perla Negra" msgid "campaignBonus|Advanced Archery" msgstr "Tiro con Arco Avanzado" #, fuzzy msgid "campaignBonus|Expert Archery" msgstr "Maza del Trueno de Dominio" #, fuzzy msgid "campaignBonus|Basic Ballistics" msgstr "Perla Negra" msgid "campaignBonus|Advanced Ballistics" msgstr "Balística Avanzada" msgid "campaignBonus|Expert Ballistics" msgstr "Balística Experta" #, fuzzy msgid "campaignBonus|Basic Diplomacy" msgstr "Peto de Anduran" msgid "campaignBonus|Advanced Diplomacy" msgstr "Diplomacia Avanzada" msgid "campaignBonus|Expert Diplomacy" msgstr "Diplomacia Experta" #, fuzzy msgid "campaignBonus|Basic Eagle Eye" msgstr "Perla Negra" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Ojo de águila avanzado" msgid "campaignBonus|Expert Eagle Eye" msgstr "Ojo de águila experto" #, fuzzy msgid "campaignBonus|Basic Estates" msgstr "Peto de Anduran" #, fuzzy msgid "campaignBonus|Advanced Estates" msgstr "Peto de Anduran" #, fuzzy msgid "campaignBonus|Expert Estates" msgstr "Peto de Anduran" #, fuzzy msgid "campaignBonus|Basic Leadership" msgstr "Perla Negra" msgid "campaignBonus|Advanced Leadership" msgstr "Liderazgo Avanzado" msgid "campaignBonus|Expert Leadership" msgstr "Liderazgo Experto" #, fuzzy msgid "campaignBonus|Basic Logistics" msgstr "Cadena de Rayos" msgid "campaignBonus|Advanced Logistics" msgstr "Logística Avanzada" msgid "campaignBonus|Expert Logistics" msgstr "Logística Experta" #, fuzzy msgid "campaignBonus|Basic Luck" msgstr "Perla Negra" #, fuzzy msgid "campaignBonus|Advanced Luck" msgstr "Animar Muertos" #, fuzzy msgid "campaignBonus|Expert Luck" msgstr "Maza del Trueno de Dominio" msgid "campaignBonus|Basic Mysticism" msgstr "Misticismo Básico" msgid "campaignBonus|Advanced Mysticism" msgstr "Misticismo Avanzado" msgid "campaignBonus|Expert Mysticism" msgstr "Misticismo Experto" #, fuzzy msgid "campaignBonus|Basic Navigation" msgstr "Cadena de Rayos" msgid "campaignBonus|Advanced Navigation" msgstr "Navegación Avanzada" msgid "campaignBonus|Expert Navigation" msgstr "Navegación Experta" #, fuzzy msgid "campaignBonus|Basic Necromancy" msgstr "Perla Negra" msgid "campaignBonus|Advanced Necromancy" msgstr "Necromancia Avanzada" msgid "campaignBonus|Expert Necromancy" msgstr "Necromancia Experta" #, fuzzy msgid "campaignBonus|Basic Pathfinding" msgstr "Cadena de Rayos" #, fuzzy msgid "campaignBonus|Advanced Pathfinding" msgstr "Cadena de Rayos" #, fuzzy msgid "campaignBonus|Expert Pathfinding" msgstr "Escudo Picudo" #, fuzzy msgid "campaignBonus|Basic Scouting" msgstr "Anillo del Mago del Poder" #, fuzzy msgid "campaignBonus|Advanced Scouting" msgstr "Anillo del Mago del Poder" #, fuzzy msgid "campaignBonus|Expert Scouting" msgstr "Anillo del Mago del Poder" #, fuzzy msgid "campaignBonus|Basic Wisdom" msgstr "Perla Negra" #, fuzzy msgid "campaignBonus|Advanced Wisdom" msgstr "Animar Muertos" #, fuzzy msgid "campaignBonus|Expert Wisdom" msgstr "Escudo Picudo" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" msgid "The starting alignment of the scenario will be %{race}." msgstr "" msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" msgid "The main hero will have %{skill} at the start of the scenario." msgstr "" msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" #, fuzzy msgid "Price of Loyalty" msgstr "El Precio de la Lealtad" msgid "Voyage Home" msgstr "Viaje a Casa" #, fuzzy msgid "Wizard's Isle" msgstr "Sombrero de Mago" #, fuzzy msgid "Descendants" msgstr "Campesinos" msgid "Cannot build. You have already built here today." msgstr "No se puede construir. Ya se construyo en este turno." msgid "For this action it is necessary to build a castle first." msgstr "Para realizar esa acción primero es necesario construir un castillo." msgid "The %{building} produces %{monster}." msgstr "Produce: %{monster}." msgid "Requires:" msgstr "Requiere:" msgid "Exit this menu without doing anything." msgstr "Cerrar este menú sin hacer cambios." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "" "No se puede construir %{name}. El castillo está demasiado lejos del agua." msgid "This building has been disabled." msgstr "" msgid "Cannot afford the %{name}." msgstr "Recursos insuficientes para construir %{name}." msgid "The %{name} is already built." msgstr "El %{name} ya está construido." msgid "Cannot build the %{name}." msgstr "No se puede construir %{name}." msgid "Build %{name}." msgstr "Construir %{name}." #, fuzzy msgid "Blackridge" msgstr "Puente" msgid "Hillstone" msgstr "" msgid "Pinehurst" msgstr "" #, fuzzy msgid "Whiteshield" msgstr "Perla Blanca" #, fuzzy msgid "Woodhaven" msgstr "Madera" #, fuzzy msgid "Blackwind" msgstr "Herrero" #, fuzzy msgid "Bloodreign" msgstr "Buena Moral" #, fuzzy msgid "Dragontooth" msgstr "Dragón rojo" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" #, fuzzy msgid "Tundara" msgstr "Thundax" #, fuzzy msgid "Vulcania" msgstr "Volcán" msgid "Baywatch" msgstr "" #, fuzzy msgid "Fountainhead" msgstr "Fuente" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" #, fuzzy msgid "Sandcaster" msgstr "Sandro" msgid "Alamar" msgstr "Alamar" #, fuzzy msgid "Burlock" msgstr "Brujo" #, fuzzy msgid "Dragadune" msgstr "Dragón rojo" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" #, fuzzy msgid "Blackfang" msgstr "Dragón Negro" #, fuzzy msgid "New Dawn" msgstr "Dawn" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" #, fuzzy msgid "Antioch" msgstr "\"Anexión\"" #, fuzzy msgid "Avalon" msgstr "Halon" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" #, fuzzy msgid "Weed Patch" msgstr "Reloj de Oro" #, fuzzy msgid "Brownston" msgstr "Marrón" #, fuzzy msgid "Hilltop" msgstr "Fuerte de la Colina" msgid "Weddington" msgstr "" msgid "Westfork" msgstr "" #, fuzzy msgid "Whittingham" msgstr "Nivel" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "" msgid "Roscomon" msgstr "" #, fuzzy msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "" msgid "Blackburn" msgstr "" msgid "Blacksford" msgstr "" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "" msgid "Lankershire" msgstr "" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "" #, fuzzy msgid "Troy" msgstr "Troyan" #, fuzzy msgid "Forder Oaks" msgstr "Tierras fronterizas" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "" msgid "Willow" msgstr "" msgid "Corackston" msgstr "" msgid "Sheltemburg" msgstr "" msgid "Cannot recruit - you already have a Hero in this town." msgstr "No puedes reclutar, ya tienes un Héroe en esta ciudad." msgid "Cannot recruit - you have too many Heroes." msgstr "No puedes reclutar, tienes demasiados Héroes." msgid "Cannot afford a Hero." msgstr "No te puedes permitir un Héroe." msgid "There is no room in the garrison for this army." msgstr "" msgid "Fortifications" msgstr "Fortificación" msgid "Farm" msgstr "Granja" msgid "Thatched Hut" msgstr "Cobertizo" msgid "Archery Range" msgstr "Campo de Tiro" msgid "Upg. Archery Range" msgstr "Mej. Campo de Tiro" msgid "Blacksmith" msgstr "Herrero" msgid "Upg. Blacksmith" msgstr "Herrería Mejorada" msgid "Armory" msgstr "Armería" msgid "Upg. Armory" msgstr "Armería Mejorada" msgid "Jousting Arena" msgstr "Campo de Justa" msgid "Upg. Jousting Arena" msgstr "Mej. Campo de Justa" msgid "Cathedral" msgstr "Catedral" msgid "Upg. Cathedral" msgstr "Catedral Mejorada" msgid "Coliseum" msgstr "Coliseo" msgid "Garbage Heap" msgstr "Vertedero" msgid "Hut" msgstr "Choza" msgid "Stick Hut" msgstr "Chamizo" msgid "Upg. Stick Hut" msgstr "Mej. Chamizo" msgid "Den" msgstr "Lobera" msgid "Adobe" msgstr "Adobe" msgid "Upg. Adobe" msgstr "Adobe Mejorado" msgid "Bridge" msgstr "Puente" msgid "Upg. Bridge" msgstr "Puente Mejorado" msgid "Pyramid" msgstr "Pirámide" msgid "Rainbow" msgstr "Arcoíris" msgid "Crystal Garden" msgstr "Jardín de Cristales" msgid "Treehouse" msgstr "Casa en los Ãrboles" msgid "Cottage" msgstr "Casa de Campo" msgid "Upg. Cottage" msgstr "Mej. Casa de Campo" msgid "Stonehenge" msgstr "Stonehenge" msgid "Upg. Stonehenge" msgstr "Mej. Mejorado" msgid "Fenced Meadow" msgstr "Prado Vallado" msgid "sorceress|Red Tower" msgstr "Torre Roja" msgid "Dungeon" msgstr "Mazmorra" msgid "Waterfall" msgstr "Cascada" msgid "Cave" msgstr "Cueva" msgid "Crypt" msgstr "Cripta" msgid "Nest" msgstr "Nido" msgid "Maze" msgstr "Laberinto" msgid "Upg. Maze" msgstr "Laberinto Mejorado" msgid "Swamp" msgstr "Ciénaga" msgid "Green Tower" msgstr "Torre Verde" msgid "warlock|Red Tower" msgstr "Torre Roja" msgid "Black Tower" msgstr "Torre Negra" msgid "Library" msgstr "Biblioteca" msgid "Orchard" msgstr "Huerta" msgid "Habitat" msgstr "Hábitat" msgid "Pen" msgstr "Corral" msgid "Foundry" msgstr "Fundición" msgid "Upg. Foundry" msgstr "Fundición Mejorada" msgid "Cliff Nest" msgstr "Nido del acantilado" msgid "Ivory Tower" msgstr "Torre de Marfil" msgid "Upg. Ivory Tower" msgstr "Mej. Torre de Marfil" msgid "Cloud Castle" msgstr "Castillo de las Nubes" msgid "Upg. Cloud Castle" msgstr "Mej. Castillo Nubes" msgid "Storm" msgstr "Tormenta" msgid "Skull Pile" msgstr "Pila de Calaveras" msgid "Excavation" msgstr "Excavación" msgid "Graveyard" msgstr "Cementerio" msgid "Upg. Graveyard" msgstr "Cementerio Mejorado" msgid "Upg. Pyramid" msgstr "Pirámide Mejorada" msgid "Mansion" msgstr "Mansión" msgid "Upg. Mansion" msgstr "Mansión Mejorada" msgid "Mausoleum" msgstr "Mausoleo" msgid "Upg. Mausoleum" msgstr "Mausoleo Mejorado" msgid "Laboratory" msgstr "Laboratorio" msgid "Shrine" msgstr "Santuario" #, fuzzy msgid "Special" msgstr "Nada especial" msgid "Horde Building" msgstr "Edificio de la Horda" msgid "Dwelling 1" msgstr "Morada 1" msgid "Dwelling 2" msgstr "Morada 2" msgid "Upg. Dwelling 2" msgstr "Actu. Morada 2" msgid "Dwelling 3" msgstr "Morada 3" msgid "Upg. Dwelling 3" msgstr "Actu. Morada 3" msgid "Dwelling 4" msgstr "Morada 4" msgid "Upg. Dwelling 4" msgstr "Actu. Morada 4" msgid "Dwelling 5" msgstr "Morada 5" msgid "Upg. Dwelling 5" msgstr "Actu. Morada 5" msgid "Dwelling 6" msgstr "Morada 6" msgid "Upg. Dwelling 6" msgstr "Actu. Morada 6" msgid "2x Upg. Dwelling 6" msgstr "2x Actu. Morada 6" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "La Fortificación incrementa la dureza de los muros, incrementa el número de " "turnos que se tarda en derribar el muro." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" "La Granja incrementa la producción de Campesinos en %{count} por semana." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "El Coliseo provee de inspiradores espectaculos a las tropas defensoras, " "aumentando la moral en 2 durante el combate." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" "El Montón de Basura incrementa la producción de Globlins en %{count} por " "semana." msgid "The Rainbow increases the luck of the defending units by two." msgstr "El Arcoíris incrementa la suerte de las unidades defensoras en 2." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" "El Jardín de Cristales incrementa la producción de Hadas en %{count} por " "semana." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "La Mazmorra incrementa los ingresos de la ciudad en %{count} por día." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" "La Cascada incrementa la producción de Centauros en %{count} por semana." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "La Biblioteca proporciona un hechizo extra en cada nivel de la Torre Mágica." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "El Huerto incrementa la producción de Medianos en %{count} por semana." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" "La Tormenta añade +2 al poder de hechizo del lanzador de hechizos defensor." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" "La Pila de Calaberas incrementa la producción de Esqueletos en %{count} por " "semana." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" "El edificio especial otorga una bonificación específica al tipo de castillo " "elegido." #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "El Pozo incrementa el ritmo de crecimiento de todas las moradas en %{count} " "criaturas por semana." msgid "Thieves' Guild" msgstr "Gremio de Ladrones" msgid "Tavern" msgstr "Taberna" msgid "Shipyard" msgstr "Astillero" msgid "Well" msgstr "Pozo" msgid "Statue" msgstr "Estatua" msgid "Marketplace" msgstr "Mercado" msgid "Moat" msgstr "Foso" msgid "Castle" msgstr "Castillo" msgid "Tent" msgstr "Tienda" msgid "Captain's Quarters" msgstr "Alojamiento del Capitán" msgid "Mage Guild, Level 1" msgstr "Torre Mágica, Nivel 1" msgid "Mage Guild, Level 2" msgstr "Torre Mágica, Nivel 2" msgid "Mage Guild, Level 3" msgstr "Torre Mágica, Nivel 3" msgid "Mage Guild, Level 4" msgstr "Torre Mágica, Nivel 4" msgid "Mage Guild, Level 5" msgstr "Torre Mágica, Nivel 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "El Santuario incrementa la habilidad de nigromancia." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "El Gremio de los Ladrones ofrece información sobre los héroes enemigos y sus " "cuidades. Los Gremios de los Ladrones también pueden dar información sobre " "las ciudades enemigas. Los gremios adicionales proporcionan más información." msgid "The Tavern increases morale for troops defending the castle." msgstr "" "La Taberna incrementa la moral de las tropas miestras defiendes el castillo." msgid "The Shipyard allows ships to be built." msgstr "El Astillero permite construir barcos." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "El Pozo incrementa el ritmo de crecimiento de todas las moradas en %{count} " "criaturas por semana." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "" "La Estatua incrementa los ingresos de tus ciudades en %{count} piezas de oro " "por día." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "El Torreón Izquierdo proporciona un disparo extra durante el asalto al " "castillo." msgid "The Right Turret provides extra firepower during castle combat." msgstr "" "El Torreón Derecho proporciona un disparo extra durante el asalto al " "castillo." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "El Mercado puede ser usado para convertir uno de los tipos de recursos en " "otro. Cuantos más mercados controles, mejor será el precio de intercambio." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "El Foso ralentiza a las unidades atacantes. Cualquier unidad que entre en el " "foso terminará su turno y será más vulnerable a los ataques." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "El Castillo mejora las defensas de la ciudad e incrementa los ingresos en " "%{count} piezas de oro al día." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "La Tienda provee de trabajadores para construir un castillo, con la " "condición de que estén disponibles los materiales y el oro." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "El Alojamiento del Capitán provee un capitán para que asista en la defensa " "del castillo cuando no hay un héroe presente." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "La Torre Mágica permite aprender hechizos y restablecer los puntos de Maná a " "los héroes visitantes." msgid "Recruit %{name}" msgstr "Recluta %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Mes: %{month}, Semana: %{week}, Día: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Debes compra un libro de hechizos para usar el gremio de magos, pero " "actualmente no tienes espacio para un libro de hechizos. Prueba dando uno de " "tus artefactos a otro héroe." msgid "Click to show next town." msgstr "Haga clic para ver la siguiente ciudad." msgid "Show next town" msgstr "Ver ciudad siguiente" msgid "Click to show previous town." msgstr "Haga clic para ver la ciudad anterior." msgid "Show previous town" msgstr "Ver ciudad anterior" msgid "This town may not be upgraded to a castle." msgstr "Este pueblo no se puede actualizar a castillo." msgid "Town" msgstr "Pueblo" msgid "Exit Castle" msgstr "Salir del castillo" msgid "Exit Town" msgstr "Salir de la ciudad" msgid "Show Income" msgstr "Mostrar Ingresos" msgid "View Hero" msgstr "Ver Heroe" msgid "The above spells are available here." msgstr "Los hechizos anteriores están disponibles aquí." msgid "The spells the hero can learn have been added to their book." msgstr "Los hechizos que el héroe puede aprender se han añadido a su libro." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Una generosa propina para el camarero te cede el siguiente rumor:" msgid "Recruit Hero" msgstr "Reclutar Héroe" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} es un nivel %{value} %{race} " msgid "with %{count} artifacts." msgstr "con %{count} artefactos." msgid "with 1 artifact." msgstr "con un artefacto." msgid "without artifacts." msgstr "sin artefactos." msgid "Recruit %{name} the %{race}" msgstr "Reclutar a %{name} el %{race}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "La formación 'Desplegada' de combate disemina las tropas del castillo desde " "la parte superior a la inferior del campo de batalla con al menos un espacio " "vacío entre las tropas." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "La formación 'Agrupada' de combate aglutina las trupas del castillo en el " "centro del su lado del campo de batalla." msgid "Spread Formation" msgstr "Formación Desplegada" msgid "Grouped Formation" msgstr "Formación Agrupada" msgid "Click to show the next town." msgstr "Haga clic para ver la siguiente ciudad." msgid "Click to show the previous town." msgstr "Haga clic para ver la ciudad anterior." msgid "Set garrison combat formation to 'Spread'" msgstr "Ordena a la guarnición formación Desplegada de combate." msgid "Set garrison combat formation to 'Grouped'" msgstr "Ordena a la guarnición formación Agrupada de combate." msgid "Exit Castle Options" msgstr "Salir de las Opciones del Castillo" msgid "Castle Options" msgstr "Opciones del Castillo" msgid "Not enough resources to recruit creatures." msgstr "No hay suficientes recursos para reclutar criaturas." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Eres incapaz de reclutar ahora mismo, tus filas están completas." msgid "No creatures available for purchase." msgstr "No hay criaturas disponibles para comprar." msgid "Recruit Creatures" msgstr "Reclutar Criaturas" msgid "Hire all creatures in the town." msgstr "Recluta a todas las criaturas de la ciudad." msgid "Max" msgstr "Máx" msgid "Available" msgstr "Disponible" msgid "Town Population Information and Statistics" msgstr "Población y estadísticas de la ciudad" msgid "Damage" msgstr "Daño" msgid "HP" msgstr "PV" msgid "Growth" msgstr "Crecimiento" msgid "week" msgstr "semana" msgid "View World" msgstr "Ver Todo" msgid "View the entire world." msgstr "Ver el mundo entero." msgid "Puzzle" msgstr "Rompecabezas" msgid "View the obelisk puzzle." msgstr "Ver el puzzle del Obelisco." msgid "Scenario Information" msgstr "Información del escenario" msgid "View information on the scenario you are currently playing." msgstr "Ver información del escenario que estás jugando actualmente." msgid "Dig for the Ultimate Artifact." msgstr "Cavar buscando el Artefacto Definitivo." msgid "Digging" msgstr "Excavando" msgid "Arena" msgstr "Arena" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Entras a la arena y te enfrentas a un grupo de fieros leones. Los derrotas " "sin problemas mientras la muchedumbre te vitorea. Impresionado, el veterano " "entrenador de gladiadores acepta adiestrarte en la habilidad que prefieras." msgid "Attack Skill" msgstr "Ataque" msgid "Defense Skill" msgstr "Defensa" msgid "Shots" msgstr "Disparos" msgid "Shots Left" msgstr "Disparos restantes" msgid "Hit Points" msgstr "Pts. de Vida" msgid "Hit Points Left" msgstr "Vida Restante" msgid "You can't afford to upgrade your troops!" msgstr "¡No puedes permitirte mejorar tus tropas!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Tus tropas pueden ser mejoradas, pero te saldrá caro. ¿Quieres actualizarlas?" msgid "Are you sure you want to dismiss this army?" msgstr "¿Estás seguro de que quieres despedir a este ejército?" msgid "Upgrade" msgstr "Mejorar" msgid "Upgrade your troops." msgstr "Mejorar tus tropas." msgid "Dismiss" msgstr "Despedir" msgid "Dismiss this army." msgstr "Despedir a este ejército." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Un grupo de %{monster} con ansia de gloria desea unirse a tus tropas.\n" "¿Aceptas?" msgid "Followers" msgstr "Seguidores" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "El %{monster} es dominado por tu diplomático lenguaje, y te ofrece unirse a " "tu ejercito por la suma de %{gold} piezas de oro.\n" "¿Aceptas?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Las criaturas, influidas por tu diplomacia,\n" "te hacen una oferta:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} de los %{total} %{monster} se unirán a tu ejercito y el resto te " "dejará continuar, por la módica cantidad de %{gold} piezas de oro.\n" "¿Aceptas?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Todos los %{monster} (%{offer}) se unirán a tu ejercito por la cantidad de " "%{gold} piezas de oro.\n" "¿Acepta?" msgid "(Rate: %{percent})" msgstr "(Tasa: %{percent})" msgid "off" msgstr "apagado" msgid "Music" msgstr "Música" msgid "Effects" msgstr "Efectos" msgid "MIDI" msgstr "MIDIs" msgid "MIDI Expansion" msgstr "MIDI Expansión" msgid "External" msgstr "Externa" msgid "Music Type" msgstr "Tipo de Música" msgid "3D Audio" msgstr "Sonido 3D" msgid "Toggle ambient music level." msgstr "Cambia el volumen de la música ambiental." msgid "Toggle foreground sounds level." msgstr "Cambia el volumen de los sonidos de primer plano." msgid "Change the type of music." msgstr "Cambiar el tipo de música." msgid "Toggle the 3D effect of foreground sounds." msgstr "Alternar el efecto 3D de los sonidos en primer plano." msgid "Build a new ship:" msgstr "Construir un nuevo barco:" msgid "Resource cost:" msgstr "Coste del recurso:" msgid "Total: " msgstr "Total: " msgid "Need: " msgstr "Necesita: " msgid "New Game" msgstr "Nueva Partida" msgid "Start a single or multi-player game." msgstr "Comenzar una partida simple o multijugador." msgid "Load Game" msgstr "Cargar Partida" msgid "Load a previously saved game." msgstr "Cargar una partida previamente guardada." msgid "Save Game" msgstr "Guardar Partida" msgid "Save the current game." msgstr "Guardar la partida en curso." msgid "Quit" msgstr "Salir" msgid "Quit out of Heroes of Might and Magic II." msgstr "Salir de Heroes of Might and Magic II." msgid "Language" msgstr "Idioma" msgid "Graphics" msgstr "Gráficos" msgid "Black & White" msgstr "Blanco y Negro" msgid "Mouse Cursor" msgstr "Cursor Ratón" msgid "Color" msgstr "Color" msgid "Text Support" msgstr "Soporte de Texto" msgid "Change the language of the game." msgstr "Cambiar el idioma del juego." msgid "Select Game Language" msgstr "Seleccionar Idioma del Juego" msgid "Change the graphics settings of the game." msgstr "Cambiar los ajustes gráficos del juego." #, fuzzy msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Activa o desactiva el cursor de color. Elección estética." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Alternar el modo de soporte de texto para generar información adicional " "sobre ventanas y eventos en el juego." msgid "" "Map\n" "Difficulty" msgstr "" "Dificultad\n" "del Mapa" msgid "" "Game\n" "Difficulty" msgstr "" "Dificultad\n" "del Juego" msgid "Rating" msgstr "Nivel" msgid "Map Size" msgstr "" "Tamaño\n" "del Mapa" msgid "Opponents" msgstr "Contrincantes" msgid "Class" msgstr "Raza" msgid "" "Victory\n" "Conditions" msgstr "" "Condiciones\n" "de Victoria" msgid "" "Loss\n" "Conditions" msgstr "" "Condiciones\n" "de Derrota" msgid "First select recipients!" msgstr "¡Selecciona primero los destinatarios!" msgid "You cannot select %{resource}!" msgstr "¡No puedes seleccionar %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Dispara a %{monster}" msgid "Select Recipients" msgstr "Selecciona Destinatarios" msgid "Your Funds" msgstr "Tus Fondos" msgid "Planned Gift" msgstr "Tributo Planeado" msgid "Gift from %{name}" msgstr "Regalo de %{name}" msgid "Resolution" msgstr "Resolución" msgid "Fullscreen" msgstr "Pantalla Completa" msgid "window|Mode" msgstr "Modo" msgid "Windowed" msgstr "Ventana" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Información del Sistema" msgid "Change the resolution of the game." msgstr "Cambiar la resolución del juego." msgid "Select Game Resolution" msgstr "Seleccionar Resolución del Juego" msgid "Toggle between fullscreen and windowed modes." msgstr "Alternar entre pantalla completa y modos de ventana." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "Se puede habilitar la opción V-Sync para resolver problemas de parpadeo en " "algunos monitores." msgid "Show extra information such as FPS and current time." msgstr "Muestra información adicional como FPS y la hora actual." msgid "Hotkey: " msgstr "Tecla de acceso rápido: " msgid "Category: " msgstr "Categoría: " msgid "Event: " msgstr "Evento: " msgid "Hot Keys:" msgstr "Atajos de Teclado:" msgid "Hide" msgstr "Ocultar" msgid "Show" msgstr "Mostrar" msgid "Interface" msgstr "Interfaz" msgid "Interface Type" msgstr "Tipo de interfaz" msgid "Toggle the type of interface you want to use." msgstr "Cambia el tipo de interfaz que deseas utilizar." msgid "Toggle interface visibility." msgstr "Alterna la visibilidad de la interfaz." msgid "Scroll Speed" msgstr "Velocidad de desplazamiento" msgid "Sets the speed at which you scroll the window." msgstr "Establece la velocidad a la que se desplaza la ventana." msgid "Select Game Language:" msgstr "Seleccionar Idioma del Juego:" #, fuzzy msgid "Select Language:" msgstr "Seleccionar Idioma del Juego:" msgid "Click to choose the selected language." msgstr "Haz clic para seleccionar el idioma." msgid "%{name} has gained a level." msgstr "%{name} ha ganado un nivel." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Has aprendido %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} ha ganado un nivel.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Puedes aprender:\n" "%{skill1}\n" "o\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/d" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Por favor ojea nuestros magníficos puestos. Si te apetece comerciar, haz " "click en los artículos que deseas cambiar y obtener." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Te llevas una ganga, creo que no ganaré nada con el trato. ¿Hay algo que te " "pueda ofrecer de cualquiera de mis otros puestos ?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Te puedo ofrecer %{count} por 1 unidad de %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" "Te puedo ofrecer 1 unidad de %{resto} por %{count} unidades de %{resfrom}." msgid "Min" msgstr "Mín" msgid "Qty to trade" msgstr "Cantitades" msgid "Trading Post" msgstr "Mercadillo" msgid "Your Resources" msgstr "Tus recursos" msgid "Available Trades" msgstr "Tratos Disponibles" msgid "guarded by %{count} %{monster}" msgstr "protegido por %{count} %{monster}" msgid "guarded by " msgstr "protegido por " msgid "(available: %{count})" msgstr "(disponibles: %{count})" msgid "(empty)" msgstr "(vacío)" msgid "already learned" msgstr "ya se ha aprendido" msgid "treeOfKnowledge|free" msgstr "gratis" msgid "already claimed" msgstr "EXP ya adquirida" msgid "not claimed" msgstr "EXP disponible" msgid "already knows this skill" msgstr "ya conoce esta habilidad" msgid "already has max skills" msgstr "ya tiene las habilidades al máximo" msgid "(already visited)" msgstr "(ya visitado)" msgid "(not visited)" msgstr "(no visitado)" msgid "%{color} Barrier" msgstr "Barrera %{color}" msgid "(tent visited)" msgstr "(tienda visitada)" msgid "%{color} Tent" msgstr "Tienda %{color}" msgid "Road" msgstr "Carretera" msgid "(digging ok)" msgstr "(excavación posible)" msgid "(no digging)" msgstr "(excavación imposible)" msgid "penalty: %{cost}" msgstr "Penalización: %{cost}" msgid "Defenders:" msgstr "Defensores:" msgid "Unknown" msgstr "Desconocido" msgid "heroQuickInfo|(Level %{level})" msgstr "( Nivel %{level} )" msgid "Attack:" msgstr "Ataque:" msgid "Defense:" msgstr "Defensa:" msgid "Spell Power:" msgstr "Pot. de Hech:" msgid "Knowledge:" msgstr "Conocimiento:" msgid "Spell Points:" msgstr "Maná:" msgid "Move Points:" msgstr "Movimiento:" msgid "Uncharted Territory" msgstr "Territorio inexplorado" msgid "Cost per troop:" msgstr "Coste por tropa:" msgid "Available: %{count}" msgstr "Disponible: %{count}" msgid "Number to buy:" msgstr "Reclutar:" msgid "Recruit selected monsters." msgstr "Recluta los monstruos seleccionados." msgid "Select maximum monsters to be recruited." msgstr "Selecciona el máximo de monstruos que deseas reclutar." msgid "Select only 1 monster to be recruited." msgstr "Selecciona solo 1 monstruo para reclutar." #, fuzzy msgid "Select this game resolution." msgstr "Seleccionar Resolución del Juego" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" "Seleccionar esta resolución establecerá una resolución que se escala a " "partir de la resolución original (%{resolution}) multiplicándola por el " "número en los corchetes (%{scale}).\n" "\n" "Una resolución con un número entero limpio (2.0x, 3.0x, etc.) generalmente " "se verá mejor porque los píxeles se amplían de manera uniforme en ambas " "direcciones, horizontal y vertical." msgid "Select Game Resolution:" msgstr "Seleccione la resolución del juego:" msgid "Click to apply the selected resolution." msgstr "Haz clic para aplicar la resolución seleccionada." #, fuzzy msgid "Click to apply the entered text." msgstr "Haz clic para volver al menú principal" msgid "Click to open the Virtual Keyboard dialog." msgstr "Haz clic para abrir el cuadro de diálogo del Teclado virtual." msgid "Open Virtual Keyboard" msgstr "Abrir teclado virtual" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "¿Cuántas tropas deseas mover?" #, fuzzy msgid "Select how many units to separate into:" msgstr "Seleccione la ciudad a la que transportarse." msgid "Map: " msgstr "Mapa: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "Mes: " msgid ", Week: " msgstr ", Semana: " msgid ", Day: " msgstr ", Día: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Ubicación: " msgid "Are you sure you want to delete file:" msgstr "Estas seguro de que quieres eliminar el archivo:" msgid "Warning" msgstr "Advertencia" #, fuzzy msgid "Click to save the current game." msgstr "Haz clic para volver al menú principal" #, fuzzy msgid "Click to load a previously saved game." msgstr "Cargar una partida previamente grabada." msgid "File to Save:" msgstr "Archivo a Guardar:" msgid "File to Load:" msgstr "Archivo a Cargar:" msgid "Terrain object" msgstr "Objeto de terreno" msgid "Accept the choice made." msgstr "Aceptar la elección realizada." #, fuzzy msgid "Select Skill:" msgstr "Defensa" #, fuzzy msgid "Select Spell:" msgstr "Seleccionar objetivo del hechizo" #, fuzzy msgid "Select Artifact:" msgstr "Artefactos" #, fuzzy msgid "Select Monster:" msgstr "Mejor monstruo:" #, fuzzy msgid "Select Hero:" msgstr "Mejor héroe:" msgid "race|Random" msgstr "Aleatorio" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Haz clic para volver al menú principal" #, fuzzy msgid "%{color} %{race}" msgstr "Héroe %{race} %{color}" msgid "You will place" msgstr "Colocarás" #, fuzzy msgid "Click to select this class." msgstr "Haga clic aquí para seleccionar el escenario donde jugar." #, fuzzy msgid "Click to select this color." msgstr "Haga clic aquí para seleccionar el escenario donde jugar." #, fuzzy msgid "Select Treasure:" msgstr "Mejor héroe:" #, fuzzy msgid "Select Ocean Object:" msgstr "Artefactos" #, fuzzy msgid "Castle/town placing" msgstr "Opciones del Castillo" msgid "doubleLinedRace|Neutral" msgstr "Neutral" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "Haz clic para volver al menú principal" #, fuzzy msgid "Click to select town placing." msgstr "Ver ciudad siguiente" #, fuzzy msgid "Click to select castle placing." msgstr "Haga clic aquí para seleccionar el escenario donde jugar." #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "Héroe %{race} %{color}" msgid "race|Neutral" msgstr "Neutral" #, fuzzy msgid "Select Dwelling:" msgstr "Seleccionar objetivo del hechizo" #, fuzzy msgid "Select Landscape Object:" msgstr "Artefactos" msgid "Mine placing" msgstr "Colocación de minas" #, fuzzy msgid "" "Resource\n" "type:" msgstr "Recursos" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name} el %{race}" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "Haga clic aquí para seleccionar el escenario donde jugar." #, fuzzy msgid "Select Mountain Object:" msgstr "Artefactos" #, fuzzy msgid "Select Rock Object:" msgstr "Artefactos" #, fuzzy msgid "Select Tree Object:" msgstr "Artefactos" #, fuzzy msgid "Select Power Up Object:" msgstr "Artefactos" #, fuzzy msgid "Select Adventure Object:" msgstr "Artefactos" msgid "Players Icon" msgstr "Icono de los jugadores" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Indica cuantos jugadores hay en total en el escenario. Cualquier posición no " "ocupada por jugadores humanos, será ocupada por jugadores virtuales." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Indica si los mapas son pequeños (36x36), medianos (72x72), grandes " "(108x108) o extra grandes (144x144)." msgid "Size Icon" msgstr "Icono del tamaño" #, fuzzy msgid "Map Type" msgstr "Tamaño del Mapa" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Indica si el mapa está hecho para la versión \"Las Guerras de Sucesión\", " "\"El Precio de la Lealtad\" o \"Resurrección\" del juego." #, fuzzy msgid "Map Type:\n" msgstr "Tamaño del Mapa" #, fuzzy msgid "The Succession Wars" msgstr "El Otro Lado" msgid "The Price of Loyalty" msgstr "El Precio de la Lealtad" #, fuzzy msgid "Resurrection" msgstr "Resurrección" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Idioma" msgid "Lose all your heroes and towns." msgstr "Perder todos tus héroes y ciudades." msgid "Lose a specific town." msgstr "Perder una ciudad específica." msgid "Lose a specific hero." msgstr "Perder un héroe específico." msgid "Run out of time. Fail to win by a certain point." msgstr "Se acaba el tiempo. No conseguir ganar llegado un punto determinado." msgid "Loss Condition" msgstr "Condiciones de derrota" msgid "Defeat all enemy heroes and towns." msgstr "Derrota a todos los heroes enemígos y sus ciudades." msgid "Capture a specific town." msgstr "Capturar una ciudad específica." msgid "Defeat a specific hero." msgstr "Derrotar un héroe específico." msgid "Find a specific artifact." msgstr "Encontrar un artefacto específico." msgid "Your side must defeat the opposing side." msgstr "Tu bando debe derrotar al bando contrario." msgid "Accumulate a large amount of gold." msgstr "Acumular una gran cantidad de dinero." msgid "Victory Condition" msgstr "Condiciones de victoria" msgid "Map difficulty:" msgstr "Nivel del mapa:" msgid "N" msgstr "P" msgid "No maps exist at that size." msgstr "No existen mapas de ese tamaño." msgid "Small Maps" msgstr "Mapas pequeños" msgid "View only maps of size small (36 x 36)." msgstr "Ver sólo mapas pequeños (36x36)." msgid "Medium Maps" msgstr "Mapas medianos" msgid "View only maps of size medium (72 x 72)." msgstr "Ver sólo mapas medianos (72x72)" msgid "Large Maps" msgstr "Mapas grandes" msgid "View only maps of size large (108 x 108)." msgstr "Ver sólo mapas grandes (108x108)" msgid "Extra Large Maps" msgstr "Mapas extra grandes" msgid "View only maps of size extra large (144 x 144)." msgstr "Ver sólo mapas extra grandes (144x144)." msgid "All Maps" msgstr "Todos los mapas" msgid "View all maps, regardless of size." msgstr "Ver todos los mapas, independientemente de su tamaño." msgid "Selected Name" msgstr "Nombre elegido" msgid "The name of the currently selected map." msgstr "El nombre del mapa actualmente seleccionado." msgid "Selected Map Difficulty" msgstr "Dificultad del mapa elegido" #, fuzzy msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "La dificultad de mapa del mapa seleccionado actualmente. La dificultad de " "mapa se determina por el diseñador del escenario. Los mapas más difíciles " "pueden incluir enemigos más abundantes o poderosos, menos recursos, o " "algunas otras condiciones que vuelvan las cosas más duras para el jugador " "humano." msgid "Selected Description" msgstr "Descripción seleccionada" msgid "The description of the currently selected map." msgstr "La descripción del mapa actualmente elegido." msgid "Jump" msgstr "Salta" msgid "Hero Speed" msgstr "Velocidad del héroe" msgid "Don't Show" msgstr "No mostrar" msgid "Enemy Speed" msgstr "Velocidad del enemigo" msgid "Auto Resolve" msgstr "Automáticas" msgid "Auto, No Spells" msgstr "Automáticas, sin hechizos" msgid "Battles" msgstr "Batallas" #, fuzzy msgid "combatMode|Manual" msgstr "Manuales" msgid "Change the speed at which your heroes move on the main screen." msgstr "" "Cambia la velocidad a la que se mueven tus héroes en el mapa de aventura." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Establece la velocidad a la que se mueven los héroes controlados por la " "computadora. También puedes optar por no ver el movimiento de la computadora." #, fuzzy msgid "Change the interface settings of the game." msgstr "Cambiar los ajustes gráficos del juego." msgid "Interface Settings" msgstr "Ajustes de interfaz" msgid "Toggle instant battle mode." msgstr "Activa o desactiva el modo de batalla instantánea." msgid "Att." msgstr "Ataq." msgid "Def." msgstr "Def." msgid "Power" msgstr "Poder" msgid "Knowl" msgstr "Conoc." msgid "1st" msgstr "1er" msgid "2nd" msgstr "2do" msgid "3rd" msgstr "3er" msgid "4th" msgstr "4o" msgid "5th" msgstr "5o" msgid "6th" msgstr "6o" msgid "Oracle: Player Rankings" msgstr "Oracle: Clasificación de jugadores" msgid "Thieves' Guild: Player Rankings" msgstr "Gremio de ladrones: Clasificación de jugadores" msgid "Number of Towns:" msgstr "Número de ciudades:" msgid "Number of Castles:" msgstr "Número de castillos:" msgid "Number of Heroes:" msgstr "Número de héroes:" msgid "Gold in Treasury:" msgstr "Fondos de oro:" msgid "Wood & Ore:" msgstr "Madera y Hierro:" msgid "Gems, Cr, Slf & Mer:" msgstr "Gem, Cri, Azu y Mer:" msgid "Obelisks Found:" msgstr "Obeliscos encontrados:" msgid "Artifacts:" msgstr "Artefactos:" msgid "Total Army Strength:" msgstr "Fuerza total del ejercito:" msgid "Income:" msgstr "Ingresos:" msgid "Best Hero:" msgstr "Mejor héroe:" msgid "Best Hero Stats:" msgstr "Estads. mejor héroe:" msgid "Personality:" msgstr "Personalidad:" msgid "Best Monster:" msgstr "Mejor monstruo:" #, fuzzy msgid "Random Castle Name" msgstr "Cualquier castillo" #, fuzzy msgid "Random Town Name" msgstr "Cualquier torre" #, fuzzy msgid "Allow Castle build" msgstr "Castillo de las Nubes" #, fuzzy msgid "Default Buildings" msgstr "Medianos" msgid "Default Army" msgstr "Ejército por defecto" #, fuzzy msgid "Castle Army" msgstr "Castillo" #, fuzzy msgid "Town Army" msgstr "Pueblo" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" "Haz clic para cambiar el nombre del castillo. Haz clic derecho para " "restablecer al valor predeterminado." #, fuzzy msgid "Enter Castle name" msgstr "Pierdes el héroe: %{name}." msgid "Allow to build a castle in this town." msgstr "Permite construir un castillo en esta ciudad." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" "Activa o desactiva el uso de los edificios predeterminados. ¡Los edificios " "personalizados se restablecerán!" msgid "Toggle building construction restriction mode." msgstr "" "Activa o desactiva el modo de restricción de construcción de edificios." msgid "Restrict Building Construction" msgstr "Restringe la construcción de edificios" msgid "Use default defenders army." msgstr "Usa el ejército defensor predeterminado." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" "Establece un ejército personalizado del castillo. Haz clic derecho para " "restablecer la unidad." msgid "Message Text:" msgstr "Texto del mensaje:" msgid "Reward:" msgstr "Recompensa:" msgid "Player colors allowed to get event:" msgstr "Colores de jugador permitidos para obtener el evento:" msgid "Computer colors allowed to get event:" msgstr "Colores de la computadora permitidos para obtener el evento:" msgid "First day of occurrence:" msgstr "Primer día de ocurrencia:" msgid "Repeat period (days):" msgstr "Periodo de repetición (días):" msgid "Allow %{color} human player to get event" msgstr "Permitir que el jugador humano %{color} obtenga el evento" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" "Si esta casilla de verificación está marcada, este evento se activará para " "el jugador %{color} si está controlado por un humano." msgid "Allow %{color} computer player to get event" msgstr "" "Permitir que el jugador controlado por la computadora %{color} reciba el " "evento" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" "Si esta casilla está marcada, este evento se activará para el jugador " "%{color} si está controlado por la computadora." msgid "Message:" msgstr "Mensaje:" #, fuzzy msgid "Click to save the Event properties." msgstr "Haz clic para volver al menú principal" msgid "No resources will be given as a reward." msgstr "No se entregarán recursos como recompensa." #, fuzzy msgid "Resources" msgstr "Recursos" msgid "Resources will be given as a reward." msgstr "Se entregarán recursos como recompensa." #, fuzzy msgid "Click here to change the event message." msgstr "Haz clic para volver al menú principal" msgid "Event Message Text" msgstr "Texto del mensaje del evento" msgid "Day: %{day}" msgstr "Día: %{day}" msgid "Daily Events" msgstr "Eventos diarios" #, fuzzy msgid "Click to save the events." msgstr "Haz clic para volver al menú principal" msgid "Add Event" msgstr "Agregar evento" msgid "Add an additional event." msgstr "Añadir un evento adicional." msgid "Edit Event" msgstr "Editar evento" msgid "Edit an existing event." msgstr "" msgid "Delete Event" msgstr "Eliminar evento" msgid "Delete an existing event." msgstr "Eliminar un evento existente." #, fuzzy msgid "Effects:" msgstr "Efectos" #, fuzzy msgid "Conditions:" msgstr "" "Condiciones\n" "de Derrota" msgid "Cancel event after first visit" msgstr "Cancelar evento después de la primera visita" #, fuzzy msgid "Computer colors allowed to get the event:" msgstr "Colores de la computadora permitidos para obtener el evento:" #, fuzzy msgid "Set Experience value" msgstr "Experiencia" msgid "Artifact" msgstr "Artefacto" #, fuzzy msgid "No artifact will be given by the event." msgstr "No se entregará ningún artefacto como recompensa." #, fuzzy msgid "Delete Artifact" msgstr "Artefactos" #, fuzzy msgid "Delete an artifact from the event." msgstr "Eliminar un artefacto de la recompensa." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Defensa" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" #, fuzzy msgid "No resources will be part of this event." msgstr "No se entregarán recursos como recompensa." #, fuzzy msgid "These resources will be a part of the event." msgstr "No se entregarán recursos como recompensa." msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" "Si esta casilla está marcada, el evento se activará solo una vez. Si no está " "marcada, el evento se activará cada vez que uno de los jugadores " "especificados cruce la casilla del evento." #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Este pueblo no se puede actualizar a castillo." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Este pueblo no se puede actualizar a castillo." #, fuzzy msgid "%{objects} must be placed on water." msgstr "Este pueblo no se puede actualizar a castillo." #, fuzzy msgid "Objects cannot be placed outside the map." msgstr "Este pueblo no se puede actualizar a castillo." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Este pueblo no se puede actualizar a castillo." #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "¿Estás seguro de que quieres cargar una nueva partida? (Tu partida actual se " "perderá)" msgid "Editor" msgstr "Editor" #, fuzzy msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "¿Estás seguro de que quieres cargar una nueva partida? (Tu partida actual se " "perderá)" #, fuzzy msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "¿Estás seguro de que quieres cargar una nueva partida? (Tu partida actual se " "perderá)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "COMENZAR" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "¿Estás seguro de que quieres cargar una nueva partida? (Tu partida actual se " "perderá)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Comenzar" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "¿Estás seguro de que quieres cargar una nueva partida? (Tu partida actual se " "perderá)" msgid "Create a new map from scratch." msgstr "Crea un nuevo mapa desde cero." #, fuzzy msgid "New Map" msgstr "Dawn" #, fuzzy msgid "Load Map" msgstr "Cargar juego" msgid "Load an existing map." msgstr "Cargar un mapa existente." #, fuzzy msgid "Save Map" msgstr "Guardar Partida" #, fuzzy msgid "Save the current map." msgstr "Guardar la partida en curso." msgid "Quit out of the map editor." msgstr "Salir del editor de mapas." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Haz clic para volver al menú principal." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "Introduzca texto del %{object}" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Encuentra el artefacto definitivo" msgid "%{object} has no properties to change." msgstr "%{object} no tiene propiedades que se puedan cambiar." #, fuzzy msgid "This artifact" msgstr "con un artefacto." msgid "The total number of obelisks is %{count}." msgstr "" #, fuzzy msgid "Roads" msgstr "Fin del camino" msgid "Streams" msgstr "Arroyos" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" "Se puede colocar un máximo de %{count} héroes del mismo color en el mapa." msgid "Failed to update player information." msgstr "No se pudo actualizar la información del jugador." #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Este pueblo no se puede actualizar a castillo." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "Se pueden colocar un máximo de %{count} obeliscos en el mapa." #, fuzzy msgid "The map is corrupted." msgstr "Reflejo creado." msgid "Unable to locate data directory to save the map." msgstr "No se puede localizar el directorio de datos para guardar el mapa." msgid "Unable to create a directory to save the map." msgstr "No se pudo crear un directorio para guardar el mapa." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Archivo a Guardar:" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "" "¿Estás seguro de que quieres sobreescribir la guardada con este nombre?" msgid "Map saved to: " msgstr "Mapa guardado en: " #, fuzzy msgid "Failed to save the map." msgstr "Archivo a Guardar:" #, fuzzy msgid "Used to place %{object}." msgstr "Encuentra el artefacto definitivo" #, fuzzy msgid "Select object type" msgstr "Artefactos" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Haga clic aquí para seleccionar el escenario donde jugar." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Por favor, selecciona otro héroe." msgid "" "Cell\n" "Details" msgstr "" "Detalles\n" "Celda" msgid "Erase" msgstr "Borrar" msgid "Mountains" msgstr "Montañas" #, fuzzy msgid "Rocks" msgstr "Roca" msgid "Trees" msgstr "Ãrboles" #, fuzzy msgid "Water Objects" msgstr "Paraje baldio" #, fuzzy msgid "Miscellaneous" msgstr "Fineous" msgid "Artifacts" msgstr "Artefactos" #, fuzzy msgid "Dwellings" msgstr "Medianos" msgid "Mines" msgstr "Minas" #, fuzzy msgid "Power-ups" msgstr "Poder" #, fuzzy msgid "Treasures" msgstr "Tesoro" msgid "Heroes" msgstr "Héroes" #, fuzzy msgid "Towns" msgstr "Pueblo" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Artefactos" msgid "editorErasure|Adventure non pickable objects" msgstr "Objetos no recolectables de aventura" msgid "editorErasure|Castles" msgstr "Castillos" msgid "editorErasure|Adventure pickable objects" msgstr "Objetos recolectables de aventura" msgid "editorErasure|Monsters" msgstr "Monstruos" msgid "editorErasure|Heroes" msgstr "Héroes" msgid "editorErasure|Roads" msgstr "Carreteras" msgid "editorErasure|Streams" msgstr "Arroyos" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Dibuja el terreno en secciones \n" "de %{size} por %{size} cuadrados." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Borra objetos en secciones de \n" "%{size} por %{size} cuadrados." #, fuzzy msgid "Small Brush" msgstr "Mapas pequeños" #, fuzzy msgid "Medium Brush" msgstr "Mapas medianos" #, fuzzy msgid "Large Brush" msgstr "Mapas grandes" msgid "Area Fill" msgstr "Relleno de área" msgid "Used to click and drag for filling in large areas." msgstr "Se utiliza para hacer clic y arrastrar para rellenar áreas grandes." msgid "Clear Area" msgstr "Ãrea despejada" msgid "Used to click and drag for clearing large areas." msgstr "Se utiliza para hacer clic y arrastrar para limpiar áreas grandes." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Cuesta %{rate} veces el movimiento normal para todos los héroes. (La " "búsqueda de rutas reduce o elimina la penalización)." msgid "Traversable only by boat." msgstr "Transitable únicamente en barco." msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" #, fuzzy msgid "Used for special editing of action objects." msgstr "Derrota a todos los heroes enemígos y sus ciudades." #, fuzzy msgid "Adventure Objects Mode" msgstr "Opciones de la Aventura" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" #, fuzzy msgid "Kingdom Objects Mode" msgstr "Ingresos del reino" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "Monstruo" #, fuzzy msgid "Used to place monsters on the map." msgstr "Encuentra el artefacto definitivo" msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" #, fuzzy msgid "Road Mode" msgstr "Fin del camino" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" #, fuzzy msgid "Specifications" msgstr "Fortificación" msgid "File Options" msgstr "Opciones de archivo" #, fuzzy msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Desplegar el menú de opciones de archivo, permiéndote cargar, grabar etc." #, fuzzy msgid "View the editor system options, which let you customize the editor." msgstr "" "Desplegar el menú de opciones de sistema, permitiéndote personalizar tu " "partida." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" #, fuzzy msgid "Cancel back to the New Map menu." msgstr "Cancelar y volver al menú principal." msgid "Cancel back to the main menu." msgstr "Cancelar y volver al menú principal." msgid "From Scratch" msgstr "" msgid "Start from scratch with a blank map." msgstr "" msgid "Create a randomly generated map." msgstr "" #, fuzzy msgid "Random" msgstr "Cualquier torre" #, fuzzy msgid "Cancel back to the Map Editor main menu." msgstr "Cancelar y volver al menú principal." msgid "No maps available!" msgstr "¡Ningún mapa disponible!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "Héroe %{race} %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "Héroe %{race} %{color}" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "Héroe %{race} %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "None." msgstr "Ninguno" #, fuzzy msgid "One side defeats another." msgstr "Por favor, selecciona otro héroe." #, fuzzy msgid "Accumulate gold." msgstr "Acumula %{count} oro." msgid "Run out of time." msgstr "" #, fuzzy msgid "alliance|1st" msgstr " alianza" #, fuzzy msgid "alliance|2nd" msgstr " alianza" #, fuzzy msgid "alliance|3rd" msgstr " alianza" #, fuzzy msgid "alliance|4th" msgstr " alianza" #, fuzzy msgid "alliance|5th" msgstr " alianza" #, fuzzy msgid "Special Loss Condition" msgstr "Condiciones de derrota" #, fuzzy msgid "Special Victory Condition" msgstr "Condiciones de victoria" #, fuzzy msgid "Allow standard victory conditions" msgstr "Condiciones de victoria" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " alianza" #, fuzzy msgid "{%number} alliance: " msgstr " alianza" #, fuzzy msgid "Gold:" msgstr "Oro" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Seleccione la ciudad a la que transportarse." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Haz clic para volver al menú principal" msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Haz clic para volver al menú principal" msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Haz clic para volver al menú principal" msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Haz clic para volver al menú principal" #, fuzzy msgid "Map Difficulty" msgstr "" "Dificultad\n" "del Mapa" #, fuzzy msgid "Map Description" msgstr "Descripción seleccionada" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Descripción seleccionada" #, fuzzy msgid "Click to accept the changes made." msgstr "Haga clic para ver la siguiente ciudad." #, fuzzy msgid "Click to edit custom rumors." msgstr "Haz clic para volver al menú principal" msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Haz clic para volver al menú principal" msgid "Events" msgstr "" #, fuzzy msgid "Click to change the language of the map." msgstr "Cambiar el idioma del juego." #, fuzzy msgid "Click to change your map name." msgstr "Haga clic para ver la siguiente ciudad." #, fuzzy msgid "Map Name" msgstr "" "Tamaño\n" "del Mapa" #, fuzzy msgid "Click to change the description of the current map." msgstr "La descripción del mapa actualmente elegido." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "La descripción del mapa actualmente elegido." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "La descripción del mapa actualmente elegido." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Tamaño del Mapa" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "La dificultad de mapa del mapa seleccionado actualmente. La dificultad de " "mapa se determina por el diseñador del escenario. Los mapas más difíciles " "pueden incluir enemigos más abundantes o poderosos, menos recursos, o " "algunas otras condiciones que vuelvan las cosas más duras para el jugador " "humano." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Seleccionar cantidad de %{resource}:" #, fuzzy msgid "Animation" msgstr "Anexión" #, fuzzy msgid "Passability" msgstr "Personalidad:" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Haz clic para volver al menú principal" msgid "Add Rumor" msgstr "" msgid "Add an additional rumor." msgstr "" msgid "Edit Rumor" msgstr "" msgid "Edit an existing rumor." msgstr "" msgid "Delete Rumor" msgstr "" msgid "Delete an existing rumor." msgstr "" msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "Descripción seleccionada" #, fuzzy msgid "Save Map:" msgstr "Guardar Partida" #, fuzzy msgid "Click to save the current map." msgstr "Haz clic para volver al menú principal" msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Haz clic para volver al menú principal" msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "No se entregará ningún artefacto como recompensa." msgid "Delete an artifact from the reward." msgstr "Eliminar un artefacto de la recompensa." msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Fácil" msgid "difficulty|Normal" msgstr "Normal" msgid "difficulty|Hard" msgstr "Difícil" msgid "difficulty|Expert" msgstr "Experto" msgid "difficulty|Impossible" msgstr "Imposible" msgid "and more..." msgstr "" msgid "Easy" msgstr "Fácil" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "Difícil" msgid "Campaign Difficulty" msgstr "Dificultad de la campaña" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "¡Enhorabuena!\n" "\n" "Días: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Dificultad: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Puntuación: %{score}\n" "\n" "Clasificación:\n" "%{rating}" msgid "Start the selected scenario." msgstr "" msgid "View Intro" msgstr "Ver Intro" msgid "View the intro video for the current state of the campaign." msgstr "Vea el vídeo de introducción para el escenario actual de la campaña." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" #, fuzzy msgid "Restart the current scenario." msgstr "Ver la pantalla de créditos" msgid "Difficulty" msgstr "Dificultad" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" msgid "Are you sure you want to restart this scenario?" msgstr "¿Estás seguro de que quieres reiniciar este escenario?" msgid "Campaign Scenario loading failure" msgstr "" msgid "Please make sure that campaign files are correct and present." msgstr "" msgid "Days spent" msgstr "" msgid "The number of days spent on this campaign." msgstr "" msgid "Project Coordination and Core Development" msgstr "" msgid "Development" msgstr "" msgid "Visit us at " msgstr "" msgid "QA and Support" msgstr "" #, fuzzy msgid "Dev and Support" msgstr "Teletransporte" msgid "Special Thanks to" msgstr "" msgid "and many-many other contributors and supporters!" msgstr "" msgid "Support us at" msgstr "" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "" msgid "Original project before 0.7" msgstr "" #, fuzzy msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Salir del juego y volver al sistema operativo." msgid "Designed and Directed" msgstr "" msgid "Programming and Design" msgstr "" msgid "Executive Producer" msgstr "" msgid "Producer" msgstr "" msgid "Additional Design" msgstr "" msgid "Additional Programming" msgstr "" msgid "Musical Production" msgstr "" msgid "Music and Sound Design" msgstr "" #, fuzzy msgid "Vocalists" msgstr "Balística" msgid "Art Director" msgstr "" msgid "Assistant Art Director" msgstr "" #, fuzzy msgid "Artists" msgstr "Artefactos" msgid "QA Manager" msgstr "" msgid "QA" msgstr "" #, fuzzy msgid "Writing" msgstr "Nivel" msgid "Manual and Helpfile" msgstr "" msgid "Scenarios" msgstr "Escenarios" #, fuzzy msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Salir del juego y volver al sistema operativo." msgid "Design Lead" msgstr "" msgid "Designers" msgstr "" msgid "Programming Lead" msgstr "" msgid "Art Lead" msgstr "" #, fuzzy msgid "Playtesters" msgstr "2 jugadores" msgid "Designer" msgstr "" msgid "Producers" msgstr "" #, fuzzy msgid "QA Managers" msgstr "Cazadores" msgid "Sound Design" msgstr "" #, fuzzy msgid "Town Themes" msgstr "Puerta de la Ciudad" msgid "Alto Sax" msgstr "" msgid "Harpsichord and Piano" msgstr "" msgid "Basso Vocal" msgstr "" msgid "Soprano Vocal" msgstr "" msgid "Recorded at %{recordingStudio}" msgstr "" msgid "credits|Manual" msgstr "" msgid "German Consultant" msgstr "" msgid "Map Designers" msgstr "" msgid "Package Design" msgstr "" msgid "High Scores" msgstr "Puntuaciones más altas" msgid "Your Name" msgstr "Tu nombre" msgid "Unknown Hero" msgstr "Héroe desconocido" #, fuzzy msgid "Standard" msgstr "Juego estandar" #, fuzzy msgid "View High Scores for Standard Maps." msgstr "Ver la pantalla de puntuaciones más altas" msgid "Campaign" msgstr "Partida de Campaña" #, fuzzy msgid "View High Scores for Campaigns." msgstr "Ver la pantalla de puntuaciones más altas" msgid "hotkey|default okay event" msgstr "" msgid "hotkey|default cancel event" msgstr "" msgid "hotkey|default left" msgstr "" msgid "hotkey|default right" msgstr "" msgid "hotkey|default up" msgstr "" msgid "hotkey|default down" msgstr "" msgid "hotkey|toggle fullscreen" msgstr "" msgid "hotkey|toggle text support mode" msgstr "" msgid "hotkey|toggle developer mode" msgstr "" msgid "hotkey|new game" msgstr "" msgid "hotkey|load game" msgstr "" msgid "hotkey|high scores" msgstr "Puntuaciones más altas" msgid "hotkey|credits" msgstr "" msgid "hotkey|standard game" msgstr "Juego estandar" msgid "hotkey|campaign game" msgstr "Partida de Campaña" msgid "hotkey|multi-player game" msgstr "Juego multi-jugador" msgid "hotkey|settings" msgstr "Ajustes" msgid "hotkey|quit" msgstr "" msgid "hotkey|select map" msgstr "" msgid "hotkey|select small map size" msgstr "" msgid "hotkey|select medium map size" msgstr "" msgid "hotkey|select large map size" msgstr "" msgid "hotkey|select extra large map size" msgstr "" msgid "hotkey|select all map sizes" msgstr "" msgid "hotkey|hot seat game" msgstr "Asiento caliente" msgid "hotkey|battle only game" msgstr "" msgid "hotkey|choose the original campaign" msgstr "" msgid "hotkey|choose the expansion campaign" msgstr "" #, fuzzy msgid "hotkey|map editor main menu" msgstr "Partida de Campaña." #, fuzzy msgid "hotkey|new map menu" msgstr "Mostrar el siguiente héroe" #, fuzzy msgid "hotkey|load map menu" msgstr "Juego estandar" msgid "hotkey|new map from scratch" msgstr "" #, fuzzy msgid "hotkey|new random map" msgstr "Resumen del reino" #, fuzzy msgid "hotkey|undo last action" msgstr "Ver ciudad siguiente" #, fuzzy msgid "hotkey|redo last action" msgstr "Ver ciudad siguiente" #, fuzzy msgid "hotkey|open game main menu" msgstr "Mostrar el siguiente héroe" msgid "hotkey|toggle passability" msgstr "" msgid "hotkey|roland campaign" msgstr "" msgid "hotkey|archibald campaign" msgstr "" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "Ver ciudad siguiente" msgid "hotkey|voyage home campaign" msgstr "" msgid "hotkey|wizard's isle campaign" msgstr "" msgid "hotkey|descendants campaign" msgstr "" msgid "hotkey|select first campaign bonus" msgstr "" msgid "hotkey|select second campaign bonus" msgstr "" msgid "hotkey|select third campaign bonus" msgstr "" msgid "hotkey|view campaign intro" msgstr "" #, fuzzy msgid "hotkey|select campaign difficulty" msgstr "Dificultad del juego" msgid "hotkey|restart campaign scenario" msgstr "" msgid "hotkey|world map left" msgstr "" msgid "hotkey|world map right" msgstr "" msgid "hotkey|world map up" msgstr "" msgid "hotkey|world map down" msgstr "" msgid "hotkey|world map up left" msgstr "" msgid "hotkey|world map up right" msgstr "" msgid "hotkey|world map down left" msgstr "" msgid "hotkey|world map down right" msgstr "" msgid "hotkey|save game" msgstr "" msgid "hotkey|next hero" msgstr "Siguiente héroe" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "Mostrar el siguiente héroe" msgid "hotkey|start hero movement" msgstr "Empezar el desplazamiento del héroe" msgid "hotkey|cast adventure spell" msgstr "Lanzar un hechizo tipo aventura" msgid "hotkey|put hero to sleep" msgstr "" msgid "hotkey|next town" msgstr "Ciudad siguiente" msgid "hotkey|end turn" msgstr "" msgid "hotkey|file options" msgstr "Opciones de archivo" msgid "hotkey|adventure options" msgstr "Opciones de la Aventura" msgid "hotkey|puzzle map" msgstr "" #, fuzzy msgid "hotkey|scenario information" msgstr "Formación Desplegada" msgid "hotkey|dig for artifact" msgstr "" msgid "hotkey|view world" msgstr "" msgid "hotkey|kingdom summary" msgstr "Resumen del reino" msgid "hotkey|default action" msgstr "" msgid "hotkey|open focus" msgstr "" msgid "hotkey|system options" msgstr "Opciones del sistema" msgid "hotkey|scroll left" msgstr "" msgid "hotkey|scroll right" msgstr "" msgid "hotkey|scroll up" msgstr "" msgid "hotkey|scroll down" msgstr "" msgid "hotkey|toggle control panel" msgstr "" msgid "hotkey|toggle radar" msgstr "" msgid "hotkey|toggle buttons" msgstr "" msgid "hotkey|toggle status" msgstr "" msgid "hotkey|toggle icons" msgstr "" msgid "hotkey|transfer control to ai" msgstr "" msgid "hotkey|retreat from battle" msgstr "" msgid "hotkey|surrender during battle" msgstr "" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Mostrar el siguiente héroe" msgid "hotkey|quick combat" msgstr "" #, fuzzy msgid "hotkey|battle options" msgstr "Opciones del castillo" msgid "hotkey|skip turn in battle" msgstr "" msgid "hotkey|cast battle spell" msgstr "" msgid "hotkey|dwelling level 1" msgstr "" msgid "hotkey|dwelling level 2" msgstr "" msgid "hotkey|dwelling level 3" msgstr "" msgid "hotkey|dwelling level 4" msgstr "" msgid "hotkey|dwelling level 5" msgstr "" msgid "hotkey|dwelling level 6" msgstr "" msgid "hotkey|well" msgstr "" msgid "hotkey|marketplace" msgstr "Mercado" msgid "hotkey|mage guild" msgstr "" msgid "hotkey|shipyard" msgstr "Astillero" msgid "hotkey|thieves guild" msgstr "Gremio de Ladrones" msgid "hotkey|tavern" msgstr "" msgid "hotkey|construction screen" msgstr "" msgid "hotkey|buy all monsters in well" msgstr "" msgid "hotkey|split stack by half" msgstr "" msgid "hotkey|split stack by one" msgstr "" msgid "hotkey|join stacks" msgstr "" msgid "hotkey|upgrade troop" msgstr "" msgid "hotkey|dismiss hero or troop" msgstr "" #, fuzzy msgid "hotkey|exchange all troops" msgstr "Siguiente héroe" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "¿Quieres recuperar el control de la IA? El efecto sólo tendrá efecto en\n" "el siguiente turno." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" msgid "Default Actions" msgstr "" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Mapa del mundo" #, fuzzy msgid "Battle Screen" msgstr "Pantalla de Héroe" #, fuzzy msgid "Town Screen" msgstr "Pantalla de Héroe" msgid "Army Actions" msgstr "" #, fuzzy msgid "The save file is corrupted." msgstr "Reflejo creado." msgid "Unsupported save format: " msgstr "" msgid "Current game version: " msgstr "Versión actual del juego: " msgid "Last supported version: " msgstr "" msgid "This file contains a save with an invalid game type." msgstr "" msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" msgid "This saved game is localized to '" msgstr "" msgid "' language, but the current language of the game is '" msgstr "" msgid "No save files to load." msgstr "No hay partidas para cargar." msgid "Hot Seat" msgstr "Asiento caliente" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Juega una partida de \"Asiento caliente\" donde de 2 a 6 jugadores juegan en " "el mismo PC por turnos." msgid "A single player game playing out a single map." msgstr "Un solo jugador jugando un único mapa." msgid "Standard Game" msgstr "Juego estandar" #, fuzzy msgid "A single player game playing through a series of maps." msgstr "Un solo jugador jugando un único mapa." msgid "Campaign Game" msgstr "Partida de Campaña" msgid "Multi-Player Game" msgstr "Juego multi-jugador" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Una partida multijugador con varios jugadores humanos compitiendo entre " "ellos en un mapa." msgid "fheroes2 Resurrection Team presents" msgstr "El equipo fheroes2 Resurrection presenta" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "Bienvenido a Heroes of Might and Magic II con el motor fheroes2." msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Bienvenido a Heroes of Might and Magic II con el motor fheroes2.\n" "Antes de empezar el juego, selecciona una resolución de juego." msgid "Greetings!" msgstr "¡Saludos!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "Sal de Heroes of Might and Magic II y vuelve al sistema operativo." msgid "Credits" msgstr "Creditos" msgid "View the credits screen." msgstr "Ver la pantalla de créditos." msgid "View the high scores screen." msgstr "Ver la pantalla de puntuaciones más altas." msgid "Create new or modify existing maps." msgstr "" msgid "Change language, resolution and settings of the game." msgstr "Cambia el idioma, la resolución y la configuración del juego." msgid "Game Settings" msgstr "Ajustes del juego" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Faltan los archivos de vídeo necesarios para la ventana de selección de " "campaña. Por favor, asegúrese de que todos los archivos necesarios están " "presentes en el sistema." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" msgid "Original Campaign" msgstr "" msgid "Expansion Campaign" msgstr "" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" msgid "Loading video. Please wait..." msgstr "Cargando vídeo. Por favor espere..." msgid "Host" msgstr "Anfitrión" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "El anfitrión establece las opciones de la partida. Solo puede haber un " "anfitrión por partida en red." msgid "Guest" msgstr "Invitado" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "El invitado espera a que el anfitrión monte una partida, entonces es " "añadido automáticamente en ella. Pueden haber varios invitados en las " "partidas TCP/IP." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Una partida multijugador con varios jugadores humanos compitiendo entre " "ellos en un mapa." #, fuzzy msgid "Battle Only" msgstr "Enano de Combate" msgid "Setup and play a battle without loading any map." msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Juega una partida de \"Asiento caliente\" donde de 2 a 6 jugadores juegan en " "el mismo dispositivo por turnos." msgid "2 Players" msgstr "2 jugadores" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Jugar con 2 jugadores humanos y opcionalmente, hasta 4 jugadores virtuales." msgid "3 Players" msgstr "3 Jugadores" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Jugar con 3 jugadores humanos y, opcionalmente, hasta con 3 jugadores " "virtuales." msgid "4 Players" msgstr "4 Jugadores" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Jugar con 4 jugadores humanos y opcionalmente, hasta con 2 jugadores " "virtuales." msgid "5 Players" msgstr "5 Jugadores" #, fuzzy msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Jugar con 5 jugadores humanos y, opcionalmente, con un jugador virtual " "adicional." msgid "6 Players" msgstr "6 Jugadores" msgid "Play with 6 human players." msgstr "Jugar con 6 jugadores humanos." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "¡Capturas %{name}!\n" "Eres el vencedor." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "¡Has capturado al héroe enemigo (%{name})!\n" "Tu búsqueda está completada." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Has encontrado %{name}.\n" "Tu búsqueda ha concluido." msgid "Ultimate Artifact" msgstr "El artefacto definitivo" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Tu enemigo esta derrotado.\n" "¡Tu bando ha triunfado!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Has recaudado por encima de %{count} piezas de oro en tu tesoro.\n" "Todos los enemigos te reverencia ante tu riqueza y poder." msgid "Victory!" msgstr "¡Victoria!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "¡El enemigo ha capturado %{name}!\n" "Son los triunfadores." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "El enemigo a recaudado más de %{count} de oro en su tesoro.\n" "Debes inclinarte derrotado ante su riqueza y poder." msgid "You have been eliminated from the game!!!" msgstr "¡¡¡Has sido eliminado del juego!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Has perdido al héroe %{name}.\n" "Tu búsqueda ha terminado." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Has fallado en completar tu búsqueda a tiempo.\n" "Todo está perdido." msgid "Defeat!" msgstr "¡Derrota!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Puntuación base: %{score}\n" "Dificultad: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Derrota a todos los héroes enemigos y captura todas las ciudades y castillos " "enemigos." msgid "Your side defeats the opposing side." msgstr "Tu bando derrota al bando contrario." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Agotarse el tiempo. (Fracasando sin ganar por alguna condición.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Debes derrotar al enemigo %{enemies}." msgstr[1] "Debes derrotar a la alianza enemiga de %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" msgstr[1] "" msgid "Capture the castle '%{name}'." msgstr "Captura el castillo de '%{name}'." msgid "Capture the town '%{name}'." msgstr "Captura la ciudad de '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Derrota el héroe '%{name}'." msgid "Find the ultimate artifact." msgstr "Encuentra el artefacto definitivo." msgid "Find the '%{name}' artifact." msgstr "Encuentra el artefacto '%{name}'." msgid "Accumulate %{count} gold." msgstr "Acumula %{count} oro." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", o puedes ganar derrotando a todos los héroes enemigos y capturando todas " "las ciudades y castillos enemigos." msgid "Lose the castle '%{name}'." msgstr "Pierde el castillo '%{name}'." msgid "Lose the town '%{name}'." msgstr "Pierde la ciudad de '%{name}'." msgid "Lose the hero: %{name}." msgstr "Pierdes el héroe: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "No consigas ganar para el final del mes %{month}, semana %{week}, día %{day}." msgid "%{color} player has been vanquished!" msgstr "¡El jugador %{color} ha sido derrotado!" msgid "Major Event!" msgstr "¡Evento importante!" msgid "Scenario:" msgstr "Escenario:" msgid "Game Difficulty:" msgstr "Dificultad del juego:" msgid "Opponents:" msgstr "Contrincantes:" msgid "Class:" msgstr "Raza:" msgid "Rating %{rating}%" msgstr "Nivel %{rating}%" msgid "Click here to select which scenario to play." msgstr "Haga clic aquí para seleccionar el escenario donde jugar." msgid "Scenario" msgstr "Escenario" msgid "Game Difficulty" msgstr "Dificultad del juego" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Te permite cambiar la dificultad de la partida en la que jugarás. A mayor " "nivel de dificultad comienzas con menos recursos, cuanto más alta la " "configuración más recursos extra recibe el jugador virtual." msgid "Difficulty Rating" msgstr "Nivel de Dificultad" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "El Nivel de Dificultad refleja la combinación de varias configuraciones del " "juego. Este número se aplicará a tu puntuación final." msgid "Click to accept these settings and start a new game." msgstr "" "Haz clic para aceptar estas configuraciones y empezar una nueva partida." msgid "Click to return to the main menu." msgstr "Haz clic para volver al menú principal." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Los Astrólogos proclaman el Mes de %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Los Astrólogos proclaman la Semana de %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" "Tras un crecimiento normal, ¡la población del %{monster} se ha doblado!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Tras un crecimiento normal, ¡la población de %{monster} aumenta un %{count} " "por ciento!" msgstr[1] "" "Tras un crecimiento normal, ¡la población de %{monster} aumenta un %{count} " "por ciento!" msgid "%{monster} growth +%{count}." msgstr "Crecimiento de %{monster} +%{count}." msgid " All populations are halved." msgstr " El crecimiento de las poblaciones se reduce a la mitad." msgid " All dwellings increase population." msgstr " Todas las moradas aumentan su población." msgid "New Month!" msgstr "¡Nuevo mes!" msgid "New Week!" msgstr "¡Nueva semana!" msgid "Beware!" msgstr "¡Atención!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "Jugador %{color}, éste es tu último día para capturar una ciudad o serás " "desterrado de estas tierras." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "Jugador %{color}, sólo te quedan %{day} días para capturar una ciudad o " "serás desterrado de estas tierras." msgid "%{color} player's turn." msgstr "Turno del jugador %{color}." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "Jugador %{color}, has perdido tu última ciudad. Si no conquistas ótra la " "próxima semana serás eliminado." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "Jugador %{color}, tus héroes te abandonan y eres desterrado de estas tierras." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "Siguiente Héroe" msgid "Select the next Hero." msgstr "Seleccione el siguiente Héroe." #, fuzzy msgid "Hero Movement" msgstr "Continuar movimento" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "Resumen del reino" msgid "View a summary of your Kingdom." msgstr "Ver un resumen de tu reino." msgid "Cast an adventure spell." msgstr "Lanzar un hechizo tipo aventura." msgid "End Turn" msgstr "Finalizar el turno" msgid "End your turn and let the computer take its turn." msgstr "Finalizar tu turno y pasárselo al jugador virtual." msgid "Adventure Options" msgstr "Opciones de la Aventura" msgid "Bring up the adventure options menu." msgstr "Desplegar el menú de opciones de aventura." #, fuzzy msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Desplegar el menú de opciones de archivo, permiéndote cargar, grabar etc." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Desplegar el menú de opciones de sistema, permitiéndote personalizar tu " "partida." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Uno o más de tus héroes todavía tiene posibilidad de movimiento. ¿Seguro que " "quieres terminar tu turno?" msgid "Are you sure you want to quit?" msgstr "¿Estás seguro que deseas salir?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "¿Estás seguro que quieres reiniciar? (Tu partida actual se perderá.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "" "¿Estás seguro de que quieres sobreescribir la guardada con este nombre?" msgid "Game saved successfully." msgstr "Partida guardada con éxito." msgid "There was an issue during saving." msgstr "" msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "¿Estás seguro de que quieres cargar una nueva partida? (Tu partida actual se " "perderá.)" msgid "Try looking on land!!!" msgstr "" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Excavar artefactos requiere un día entero, inténtalo mañana." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Desoyñes de muchas horas cabando aquí, al fin has desenterrado %{artifact}." msgid "Congratulations!" msgstr "¡Enhorabuena!" msgid "Nothing here. Where could it be?" msgstr "No hay nada aquí. ¿Dónde puede estar?" msgid "Try searching on clear ground." msgstr "Prueba buscando en terreno despejado." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Una vista en minatura del mundo explorado. Cliquea con el botón izquierdo " "para ver dicha área." msgid "Month: %{month} Week: %{week}" msgstr "Mes: %{month} Semana: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "Encuentras un poco de %{resource}." msgid "Status Window" msgstr "Ventana de estado" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Esta ventana muestra información de la situación de tu héroe o reino y " "muestra la fecha." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Esta ventana muestra información de la situación de tu héroe o reino y " "muestra la fecha. Cliquea en el botón izquierdo para alternar entre las " "ventanas." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Te permite cambiar las posición inicial y los colores. Cada color siempre " "comenzará en una situación precisa. Algunas posiciones sólo puede ser " "jugadas por un jugador humano o uno virtual." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Te permite cambiar la raza de un jugador. No siempre se pueden cambiar las " "razas. Dependiendo del escenario, un jugador puede recibir ciudades y/o " "héroes adicionales no pertenecientes a su primer alineamiento." msgid "Handicap" msgstr "Handicap" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" msgid "%{color} player" msgstr "%{color} jugador" msgid "No Handicap" msgstr "" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" msgid "Mild Handicap" msgstr "" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" msgid "Severe Handicap" msgstr "" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Ataque" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Ver información de %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Defensa" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "ESPACIO" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Ingresos del reino" msgid "Kingdom Income per day." msgstr "Ingresos del Reino por día." #, fuzzy msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "El faro está ahora bajo tu control, todos tus barcos podrán recorrer mayor " "distancia por turno." msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "Español" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" msgid "Vietnamese" msgstr "" msgid "Slow" msgstr "Lento" msgid "Fast" msgstr "" msgid "Very Fast" msgstr "Muy rápido" msgid "Evil" msgstr "Mal" msgid "Good" msgstr "Bien" msgid ", FPS: " msgstr "" msgid "shipAndGraveyard|%{object} robber" msgstr "Ladrón de %{object}" msgid "pyramid|%{object} raided" msgstr "%{object} asaltada" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Katore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Hermana Eliza" msgid "Brother Brax" msgstr "Hermano Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr "" msgid " gives you maximum luck" msgstr "" #, fuzzy msgid "You cannot have multiple spell books." msgstr "No se puede transferir el Libro de Hechizos" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "No puedes recoger este artefacto, ¡tu inventario está lleno!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Para lanzar hechizos primero has de comprar un libro de hechizos por %{gold} " "piezas de oro." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" "Desafortunadamente, parece que andas un poco justo de dinero en estos " "momentos." msgid "Do you wish to buy one?" msgstr "¿Quiéres comprar uno?" msgid "%{count} / day" msgstr "%{count} / día" msgid "one" msgstr "uno" msgid "two" msgstr "dos" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "Un remolino engulle tu nave. Parte de tu ejército ha caído por la borda." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "¡Insultados por la negativa a su oferta, los monstruos te atacan!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "Ante la superioridad de tus fuerzas, el ejército de %{monster} comienza a " "dispersarse.\n" "¿Deseas proceder a su persecución y entablar combate?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" "Saqueando un campamento enemigo descubres un depósito oculto con tesoros." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "El guarda del molino anuncia:\n" "\"Mi Señor, he estado trabajando muy duro para proporcionarte estos " "recursos, vuelve la próxima semana a por más.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "El guarda del molino anuncia:\n" "\"Mi Señor, lo siento, pero no hay recursos disponibles en este momento. Por " "favor, vuelve a intentarlo la próxima semana.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "El guarda del molino anuncia:\n" "\"Mi Señor, he estado trabajando muy duro para proporcionarte este oro, " "vuelve la próxima semana a por más.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "El guarda del molino anuncia:\n" "\"Mi Señor, lo siento, no hay oro disponible en este momento. Por favor, " "vuelve a intentarlo la próxima semana.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Has encontrado un alpendre abandonado.\n" "Dando una vuelta a su alrededor, descubres cerca algunos recursos ocultos." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "El alpendre hace tiempo que fue abandonado. No hay nada de valor aquí." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Atrapas un leprechaun que dormía descuidado entre unas setas mágicas.\n" "A cambio de su libertad, te guía a una pequeña olla llena de objetos " "preciosos." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Has encontrado un jardín mágico, el tipo de sitio en el que suelen estar " "leprechauns y hadas, pero no hay ninguno hoy aquí.\n" "A lo mejor debieras de intentarlo de nuevo la próxima semana." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Te topas con los restos de un desafortunado aventurero." msgid "Treasure" msgstr "Tesoro" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Mientras buscabas entre las ropas sucias, encontraste %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Mientras buscabas entre las ropas sucias, encontraste %{artifact}." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Te encuentras con una vieja carreta abandonada por un comerciante que no " "llegó a terreno seguro." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" "Desafortunadamente, otros han estado aquí antes, y el vagón está vacío." msgid "Searching inside, you find the %{artifact}." msgstr "Buscando dentro, encuentras %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Dentro, descubres que parte de la carga aún está allí." msgid "You search through the flotsam, and find some wood and some gold." msgstr "" "Buscas entre los restos del naufragio y encuentras algo de de madera y oro." msgid "You search through the flotsam, and find some wood." msgstr "Buscas entre los restos del naufragio y encuentras algo de madera." msgid "You search through the flotsam, but find nothing." msgstr "Buscas entre los restos del naufragio pero no encuentras nada." msgid "Shrine of the 1st Circle" msgstr "Santuario del Primer Círculo" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Te encuentras con un pequeño santuario atendido por un grupo de acólitos " "novicios. A cambio de tu protección aceptan enseñarte un hechizo sencillo: " "'%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Santuario del Segundo Círculo" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Te encuentras con un santuario ornamentado atendido por un grupo de " "voluminosos frailes. A cambio de tu protección aceptan enseñarte un hechizo: " "'%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Santuario del Tercer Círculo" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Te encuentras con un esplendido santuario atendido por un grupo de sumo " "sacerdotes. A cambio de tu protección aceptan enseñarte un sofisticado " "hechizo: '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Desafortunadamente, no tienes la sabiduría necesaria para comprender el " "hechizo, y eres incapaz de aprenderlo." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Desafortunadamente, ya conocías ese hechizo, así que no hay nada más que te " "pueda enseñar." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Desafortunadamente, no tienes un Libro de Hechizos donde registrar este " "hechizo." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Te aproximas a la cabaña y observas dentro a una bruja estudiando un antiguo " "tomo de %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Al aproximarte, ella se gira y enfoca su único ojo de cristal en hacia ti.\n" "\"¡Ya sabes todo lo que merecías aprender!\" chilla la bruja. \"¡AHORA, " "FUERA DE MI CASA!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Al aproximarte, ella se gira y habla.\n" "\"Ya sabes lo que yo te enseñaría. Ya no puedo ayudarte más.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Una antigua e inmortal bruja que vive en una cabaña rodeada de zancos de " "aves te enseña %{skill}, para sus inescrutables propósitos." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" "Mientras bebes la dulce agua adquieres suerte para tu siguiente batalla." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Bebes de una fuente encantada pero nada sucede." msgid "You enter the faerie ring, but nothing happens." msgstr "Entras en el anillo místico de hadas pero nada sucede." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Justo al entrar el anillo místico de las hadas tu ejército adquiere suerte " "para su próxima batalla." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Has encontrado un antiguo y erosionado ídolo de piedra.\n" "Se supone que otorga suerte a los visitantes, pero dado que las estrellas ya " "te sonríen, no ocurre nada." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Has encontrado un antiguo y erosionado ídolo de piedra.\n" "Besarlo se supone que da suerte, así que lo haces. La piedra esta muy fría " "al tacto." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Las sirenas en silencio te engatusan para volver más tarde y ser bendecido " "de nuevo." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "La mágica y calmante belleza de las Sirenas te alcanza a ti y a tu " "tripulación.\n" "Por un momento olvidas tus preocupaciones y te deleitas con su belleza.\n" "Los encantos de las Sirenas te bendicen e incrementan tu suerte para el " "próximo combate." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Te aproximas a la pirámide de un antiguo y gran rey.\n" "Te tienta buscar en ella su tesoro, pero todas las historias te advierten de " "las espantosas maldiciones y los guardianes nomuertos.\n" "¿Vas a buscar?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Al derrotar a los monstruos, descrifras un antiguo jeroglífico de la pared " "que explica el secreto del hechizo - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "Desafortunamente, no posees Libro de Hechizos donde registrar este hechizo." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Desafortunadamente, no tienes el conocimiento necesario para comprender el " "hechizo y no eres capaz de aprenderlo." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Te aproximas a la pirámide de un antiguo y gran rey.\n" "Exploraciones rutinarias te indican que la pirámide está completamente vacía." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "Al beber pozo se restablece tu Maná, pero ya estás al máximo." msgid "A second drink at the well in one day will not help you." msgstr "Beber dos veces del pozo en el mismo día no te ayudará." msgid "A drink from the well has restored your spell points to maximum." msgstr "Al beber del pozo se han restablecido tus puntos de Maná al máximo." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Lo siento\" dice el lider de los solados, \"pero ya has sabeis todo lo que " "nosotros podemos enserñarte\"." msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Los soldados que viven en el fuerte te enseñan algunos trucos defensivos " "nuevos." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Te has topado con un campamento de mercenarios practicando sus estrategias. " "\"Eres demasiado avanzado para nosotros\", dice el capitán de los " "mercenarios. \"No podemos enseñarte nada más\"." msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Te has topado con un campamento de mercenarios practicando sus estrategias. " "Los mercenarios te dan la bienvenida a ti y a tus tropas y os invitan a " "entrenar con ellos." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "¡Vete! grita el curandero, \"sabes todo lo que yo sé\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Una Curandera Orca que vive en la choza profundiza tu conocimiento de la " "magia enseñándote a: invocar piedras, leer augurios y descifrar las " "complejidades en las entrañas de los pollos." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Encuentras un grupo de Druidas rindiendo culto a uno de sus extraños " "edificios de piedra. Los Druidas te apartan silenciosamente, indicando que " "no tienen nada nuevo que enseñarte." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Encuentras un grupo de Druidas rindiendo culto a uno de sus extraños " "edificios de piedra. Silenciosamente te enseñan nuevas formas de lanzar " "hechizos." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Tímidamente te aproximas al cementerio de antiguos guerreros. ¿Deseas buscar " "en las tumbas?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Después derrotar a los zombis y pasar varias horas buscando en las tumbas " "sin premio, la moral de tu ejercito se reduce por un hecho tan despreciable." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "¡Después de derrotar a los zombis entras en las tumbas y encuentras algo!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "El casco putrefacto de una gran nave pirata chirría de manera inquietante " "contra las rocas.¿Deseas buscar entre los restos del naufragio?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Después de derrotar a los fantamas y pasar varias horas tamizando sus restos " "sin premio la moral de tu ejercito se reduce por un acto tan despreciable." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "¡Despúes de derrotar a los fantasmas tamizas sus restos sin premio!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "El casco putrefacto de una gran nave pirata chirría inquietantemente contra " "las rocas. ¿Deseas buscar en la nave?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "!Después de derrotar a los esqueletos tamizas sus restos y encuentras algo!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Tus hombres descubren una boya de navegación, confirmando que estás en la " "ruta correcta." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Tus hombres descubren una boya de navegación, confirmando que estás en la " "ruta correcta e incrementa su moral." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Beber en el oasis es refrescante, pero no ofrece ningún beneficio adicional. " "El oasis te podrá ayudar otra vez si primero has luchado en una batalla." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Al beber en el oasis se restablecen las fuerzas de tus tropas y se elevan " "sus espíritus. Puedes viajar un poco más hoy." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Beber por esta grieta de la que fluye agua es refrescante pero no ofrece " "otros beneficios. La grieta te podría ayudar de nuevo si antes luchas en " "batalla." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Beber por esta grieta de la que fluye agua restablece las fuerzas de tus " "tropas y eleva sus espíritus. Puedes viajar un poco más hoy." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "No ayuda rezar dos veces antes de una batalla. Regresa después de que hayas " "luchado." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Una visita y una oración en el templo aumenta la moral de tus tropas." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Un anciano caballero aparece en los peldaños del cenador. \"Lo siento os he " "enseñado todo lo que puedo\"." msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Un anciano caballero aparece en los peldaños del cenador. \"Os enseñaré todo " "lo que sé para ayudaros en vuestros viajes\"." msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Has rescatado a un superviviente de un naufragio de una muerte segura en un " "océano olvidado. Agradecido, él dice, \"Yo te daría un artefacto como " "recompensa, pero no tienes espacio\"." msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Arrastras a un superviviente de un naufragio, salvándolo de una muerte " "segura en un océano sin compasión. Agradecido, te recompensa por tu acto de " "bondad con %{art}" msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "Un Leprechaun te ofrece %{art} por el pequeño precio de %{gold} piezas de " "Oro." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Un Leprechaun te ofrece %{art} por el precio de %{gold} piezas de Oro y " "%{count} %{res}." msgid "Do you wish to buy this artifact?" msgstr "¿Deseas comprar este artefacto?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Intentas pagar al leprechaun, pero te das cuenta de que no te lo puedes " "permitir. El leprechaun patea el suelo y te ignora." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Insultado por el rechazo de su generosa oferta, el Leprechaun te da una " "patada y te ignora." msgid "You've found the artifact: " msgstr "Has encontrado el artefacto: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Has encontrado la humilde morada de un anciano eremita. El eremita te dice " "que está dispuesto a darle el %{art} a la primera persona sabia que se " "encuentre." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Llegas a la espartana morada de un soldado retirado. El soldado te dice que " "está dispuesto a darle el %{art} al primer líder auténtico que se encuentre." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Te encuentras un artefacto antiguo. Al ir a recogerlo, un grupo de Pícaros " "saltan de entre la maleza para proteger su botín." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "A través de un claro, observas un artefacto antiguo. Desafortunadamente, " "está guardado por un %{monster} cercano. ¿Quiers combatir el %{monster} por " "el artefacto?" msgid "Victorious, you take your prize, the %{art}." msgstr "Victorioso, tomas tu premio: %{art}" msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "La madurez es la mejor parte del valor, así pues decides evitar esta lucha " "hoy." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Después de varias horas intentando sacar el cofre del mar, lo abres y " "encentras %{gold} piezas de oro." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Después de pasar horas intentando sacar el cofre del mar, lo abres y " "encuentras %{gold} piezas de oro y %{art}" msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Después de pasar horas intentando sacar el cofre del mar, lo abres y resulta " "estar vacío." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Después de dar una batida por el área, das con un tesoro escondido. Puedes " "quedarte con el oro o distribuirlo entre los campesinos a cambio de " "experiencia. ¿Deseas quedarte con el oro?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Después de dar una batida por el área, das con un cofre escondido que " "contiene %{gold} piezas de oro." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Después de dar una batida por el área, das con un cofre escondido que " "contiene un antiguo artefacto: %{art}" msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Te tropiezas con una lámpara abollada que está depositada en lo profundo de " "la tierra. ¿Deseas frotar la lámpara?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Has tomado el control de la casa del Alquimista local. Te proveerá con " "%{count} unidades de mercurio al día." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Has tomado el control de un aserradero. Te proveerá con %{count} unidades de " "madera al día." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Has tomado el control de una mina de hierro. Te proveerá con %{count} " "unidades de mineral al día." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Has tomado el control de una mina de azufre. Te proveerá con %{count} " "unidades de azufre al día." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Has tomado el control de una mina de cristal. Te proveerá con %{count} " "unidades de cristal al día." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Has tomado el control de una mina de gemas. Te proveerá con %{count} " "unidades de gemas al día." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Has tomado el control de una mina de oro. Te proveerá con %{count} piezas de " "oro al día." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "El faro está ahora bajo tu control, todos tus barcos podrán recorrer mayor " "distancia por turno." msgid "You gain control of a %{name}." msgstr "Tomas control de %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Llegas a una mina de oro abandonada. La mina parece estar embrujada. " "¿Quieres entrar en ella?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" "Derrotas a los Fantasmas y eres capaz de restablecer la producción de la " "mina." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Un grupo de %{monster} con ansias de gloria desea unirse a tus tropas. " "¿Aceptas?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Al aproximarte a la morada te percatas de que ya no hay nadie allí." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Buscas en las ruinas, pero las Medusas que solían vivir aquí se han ido. " "Quizás habrá más la próxima semana." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Has encontrado algunas Medusas viviendo en las Ruinas. Están deseosas de " "servir como mercenarias por un buen precio. ¿Deseas reclutar Medusas?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Has encontrado la Ciudad de los Ãrboles de las Hadas. Desafortunadamente " "ninguna desea unirse a tu ejército. Quizás la próxima semana." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Alguna de las Hadas que viven en la ciudad están deseosas de unirse como " "mercenarias a tu ejército por un precio. ¿Quieres reclutar Hadas?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Un colorido vagón de Bandidos se encuentra vacio ahora mismo. Quizás estarán " "aquí más tarde." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Sonidos de música y risas distantes te guían a una colorida caravana de " "Bandidos. ¿Quieres que se una algún Bandido a tu ejército?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Te intriga un grupo de destartaladas tiendas, que se mueven con el viento. " "Las tiendas están vacías. Quizás haya mas Nómadas mas adelante." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Te intriga un grupo de destartaladas tiendas, que se mueven con el viento. " "¿Quieres que algún Nómada te acompañe durante tus viajes?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "La fosa de barro burbujea por un minuto y entonces permanece en calma." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Cuando le aproximas a la fosa de barro que burbujea, unas critaturas surgen " "y te rodean. Dicen al unísono: \"La Madre Tierra le gustaría ofrecerte " "algunas de sus tropas. ¿Quieres reclutar Elementales de la Tierra?" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" "Entras en la estructura de blancos pilares de piedra y no encuentras nada." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Los pilares blancos de piedra soportan un tejado que asciende hasta el " "cielo. Cuando entras en la estructura, el aire putrefacto del exterior envía " "una rafaga que casi te hace retroceder. La corriente de aire se materializa " "en una forma apenas visible. La criatura pregunta, en lo que sólo puede " "considerarse un susurro. ¿Por qué has venido?, ¿Estás aquí para invocar a " "las fuerzas del Aire?" msgid "No Fire Elementals approach you from the lava pool." msgstr "Ningun Elemental del Fuego se aproxima a ti desde el charco de lava." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Bajo la estructura incandescente que sirve de sujección, Elementales del " "Fuego se mueven por una ardiente charca de lava fundida. Un grupo de ellos " "se aproxima a ti y te ofrece sus servicios. ¿Te gustaría reclutar " "Elementales de Fuego?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Una cara se forma en el agua por un momento y entonces se va." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Formas cristalinas proyectan sombras que se reflejan en una pequeña charca " "de agua. Miras con detenimiento la charca y una cara que no es la tuya te " "devuelve la mirada. Dice: \"¿Te gustaría invocar los poderes del agua?" msgid "This burial site is deathly still." msgstr "En este lugar de enterramiento se respira una quietud de muerte." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Los espíritus sin descanso de unos guerreros muertos en el pasado buscan su " "lugar de definitivo descanso, ofrecen incorporase a tus fuezas con la " "esperanza de encontrar la paz. ¿Deseas reclutar Fantasmas?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "La Ciudad de los Muertos está vacía de vida y de muertos vivientes también. " "Quizás algunos nomuertos vendrán la próxima semana." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Algunos Liches que moran aquí están deseando unirse a tu ejército por una " "buena suma. ¿Quieres reclutar Liches?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Has encontrado las ruinas de una antigua ciudad, ahora habitada sólamente " "por nomuertos. ¿Quieres investigar?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Algunas Liches, impresionadas por tu victoria sobre sus camaradas, se " "ofrecen como mercenarias. ¿Quieres reclutar liches?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Has encontrado uno de esos puentes debajo de los cuales los Trolls están tan " "a gusto viviendo. Quizás la próxima semana habrá algunos." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Algunos Trolls que viven bajo un puente están deseosos de unirse a tu " "ejercitgo por un precio. ¿Quieres reclutar Trolls?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Los Trolls que viven bajo el puente te desafían. ¿Lucharás contra ellos?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Unos cuantos Trolls permanecen asustados bajo el Puente. Se aproximan y te " "ofrecen unirse a tus fuerzas como mercenarios. ¿Quieres reclutar algunos " "Trolls?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "En la Ciudad del Dragón no hay ningún Dragón que desee unirse a tus filas " "esta semana. Quizás un dragón estará disponible la próxima semana." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "La Ciudad del Dragón está deseando ofrecer algunos Dragones a tu ejercito " "por un precio. ¿Deseas reclutar Dragones?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Estás ante la Ciudad del Dragón, un lugar fuera de los límites de los " "humanos. ¿Deseas romper esta norma y desafiar a los Dragones en combate?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Habiendo desafíado a los campeones de los Dragones, el Lider de la ciudad " "accede a sumistrar algunos Dragones a tu ejército por un precio. ¿Deseas " "reclutar Dragones?" msgid "From the observation tower, you are able to see distant lands." msgstr "Desde la torre de observación, puedes ver tierras lejanas." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "El manaltial sólo se rellena una vez a la semana y alguien ya ha estado aquí " "esta semana." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Al beber del manantial se duplican tus puntos normales de Maná, pero ya " "estás a ese nivel." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "¡Beber del manantial colma tu sangre con magia! Duplicas la reserva de tus " "puntos normales de Maná." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "El mayordomo te reconoce y rechaza admitirte. \"El Maestro\" dice, \"no " "atenderá al mismo estudiante dos veces\"." msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "El Mayordomo permite que veas al Maestro de la Casa. Él te adiestra en las " "cuatro habilidades que todo héroe debería conocer." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "El Mayordomo abre la puerte y te mira de arriba abajo. \"Tú no eres ni " "famoso ni suficientemente letrado para llegar a ver a mi maestro\" dice con " "desdén. \"Vuelve cuando te consideres suficientemente válido\"." msgid " and " msgstr " y " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Tus %{monsters} han sido entrenados por los Maestros en Batalla del fuerte. " "Tus ejército ahora cuenta con %{monsters2}" msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Una inusual alianza entre Orcos, Ogros y Enanos te ofrece mejorar ese clase " "de tropas si se las traes. Desafortunadamente no tienes ninguno de ellos " "contigo." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Tus %{monsters} han mejorado a %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "El herrero que trabaja en la Fundición te ofrece convertir todas las armas " "de Piqueros y Espadachines a acero . También dice que conoce un proceso que " "convertirá Golems en Golems de Acero. Desafortunadamente no tienes esas " "tropas en tu ejército, por lo tanto no puede ayudarte." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Un Capitán retirado que vive de esta plataforma de pesca ofrece venderte " "mapas marítimos que hizo en sus días de juventud por 1.000 piezas de Oro.\n" "¿Deseas comprar los mapas?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "El Capitán suspira: \"No tienes suficiente dinero, ¿eh? No esperarás que te " "ofrezca mis mapas gratis\"." msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Te topas con un obelisco hecho de un tipo de piedra que nunca has visto " "antes. Fijándote con atención, la lisa superficie de repente cambia su " "inscripción. La inscripción es un trozo de un antiguo mapa perdido. " "Rápidamente lo copias y la inscripción se esfuma tan abruptamente como " "apareció." msgid "You have already been to this obelisk." msgstr "Ya has habias estado en este obelisco." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Al aproximarte, el Ãrbol abre sus ojos con deleite. \"Es bueno verte de " "nuevo, alumno mío. Espero que mis enseñanzas te hayan ayudado.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Al aproximarte, el Ãrbol abre sus ojos con deleite. \"Ahh, ¡un aventurero! " "Permíteme enseñarte un poco de lo que aprendido con los años.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Al aproximarte, el Ãrbol abre sus ojos con deleite." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" msgid "(Just bury it around my roots.)" msgstr "(Simplemente entierra lo que te pido alredor de mis raices.)" msgid "Tears brim in the eyes of the tree." msgstr "Las lágrimas colman los ojos del Ãrbol." msgid "\"I need %{count} %{res}.\"" msgstr "" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "suspira .. sniff, \"Bien, regresa cuando puedas pagarme.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "La entrada a la Cueva es oscura, un hediondo y sufuroso olor sale de la boca " "de la cueva. ¿Entrarás?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Excepto por la evidencia de una terrible batalla, la Cueva está vacía." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Encuentras un poderoso y grotesco Demonio en la cueva. \"Hoy\" brama " "\"lucharás y seguramente morirás\". Pero podrás elegir la muerte que gustes: " "puedes luchar contra mi o contra mis sirvientes. ¿Prefieres luchar contra " "mis sirvientes?" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "¡El Demonio grita su desafío y ataca! Después de una pequeña y desesperada " "batalla, matas al monstruo y recibes %{exp} puntos de experiencia y %{count} " "piezas de oro." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "¡El Demonio grita su desafío y ataca! Después de una pequeña y desesperada " "batalla, das muerte al monstruo y encuentras %{art} in la parte posterior de " "la cueva." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" msgstr[1] "" msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" msgstr[1] "" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" msgstr[1] "" msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Oyes una voz que proviene de lo alto de la torre, \"¡Vete, no puedo ayudarte!" "\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "El mozo de establo dice: \"Parece buen caballo el que montas. Me temo que no " "puedo ofrecer uno mejor, pero los caballos que lleva tu caballería parecen " "no ser de raza. Hemos entrenado muchos caballos de batalla lo cual ayudará a " "tus jinetes mucho. Insisto en que te los lleves." msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Al aproximarte a los establos, el mozo de cuadra aparece guiando un buen " "caballo de batalla. \"Este corcel te ayudará a acelerar tus viajes. Oh, se " "cansará en una semana. Deberíais permitirme daros mejores caballos para tus " "soldados montados, puesto que sus caballos parecen debiluchos." msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "El mozo de cuadra se aproxima y dice: \"Ya tienes un buen caballo y " "caballería con experiencia lo que evitará hacer uso de nuestros caballos de " "batalla entrenados." msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Al aproximarte a los establos el mozo de cuadra aparece guiando un buen " "caballo de batalla. \"Este corcel te ayudará a acelerar tus viajes. Oh, su " "resistencia disminuira mucho con el tiempo, debes volver por una nueva monta " "en una semana. También tenemos buenos caballos de batalla que podrían " "beneficiar a tus solados montados, pero no tienes ninguno así que no te " "podemos ayudar\"." msgid "The Arena guards turn you away." msgstr "Los Guardas de la Arena te apartan." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Obligas a tu tripulación a ponerse tapones en los oídos antes de que la " "inquietante canción de las sirenas pueda atraerlos a una muerte segura." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Ta pronto como las sirenas cantan su escalofriante canción, tu pequeño " "ejercito empieza a pensar en dejarse llevar por el impulso de tirarse de " "cabeza al mar." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Una espeluznante canción de gemidos emana de las sirenas subidas a las " "rocas. Algunos tripulantes caen bajo su hechizo y se lanzan al agua donde se " "ahogan. Ahora estas prevenido de su localización, y ganas %{exp} de " "experiencia." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "En una deslumbrante momento de atrevimiento, irrumpes en la cárcel local y " "liberas el héroe que está prisionero allí, quien, a cambio, jura lealtad a " "tu causa." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Ya tienes %{count} héroes, y lamentablemente debes dejar al prisionero en su " "cárcel languideciendo de agonía por incontables días." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Entras en una desvencijada cabaña y hablas con el mago que vive allí. El te " "habla de lugares cercanos y lejanos que te pueden ayudar en tus viajes." msgid "This eye seems to be intently studying its surroundings." msgstr "Este ojo parece estar atentamente estudiando los alrededores." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" "Te topas con una Esfinge Gigante. La Esfinge permanece extrañamente " "tranquila." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Tengo un acertijo para ti\" dice la Esfinge. \"Contesta correctamente y " "serás recompensado. Falla y serás engullido.\" ¿Aceptas el Desafío?" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "La Esfinge te pregunta el siguiente acertijo:\n" "\n" "%{riddle}\n" "\n" "¿Tú respuesta?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"No has adivinado\" dice la Esfinge. La Esfinge te golpea con una pata, " "tirándote al suelo. Otro soplido hace retrodecer al mundo y no sabes nada " "más." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Pareciendo en cierto modo decepcionada, la Esfinge suspira. Has acertado mi " "acertijo, por lo tanto aquí está tu recompensa. Ahora vete." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Una barrera mágica se alza frente a ti, bloqueándote el paso. La runas en el " "arco dicen, \"Di la clave y podrás pasar\".\n" "En cuanto dices la palabra mágica, la brillante barrera se disuelve en la " "nada." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Una barrera mágica se alza frente a ti, bloqueándote el paso. Las runas en " "el arco dicen, \"Di la clave y podrás pasar\".\n" "Hablas, pero no ocurre nada." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Entras en la tienda y ves una mujer anciana contemplando una gema mágica. " "Ella mira hacia arriba y dice,\n" "\"En mis viajes, he aprendido mucho del camino de la magia arcana. Un gran " "oráculo me paso sus habilidades. Tengo la respuesta que buscas.\"" msgid "No spell book is present." msgstr "No hay libro de hechizos." #, fuzzy msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "No puedes usar ese hechizo. Cuesta %{mana} puntos de Maná y sólo tienes " "&{point}." #, fuzzy msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "No puedes usar ese hechizo. Cuesta %{mana} puntos de Maná y sólo tienes " "&{point}." #, fuzzy msgid "The spell was not found." msgstr "¡El hechizo no afectará a nadie!" msgid "Only heroes can cast this spell." msgstr "" #, fuzzy msgid "This hero is not able to cast adventure spells." msgstr "Lanzar un hechizo tipo aventura." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Tu héroe está demasiado cansado como para conjurar este hechizo hoy. Prueba " "de nuevo mañana." #, fuzzy msgid "This spell cannot be cast on a boat." msgstr "Este pueblo no se puede actualizar a castillo." #, fuzzy msgid "This spell can only be cast near an ocean." msgstr "Este pueblo no se puede actualizar a castillo." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" #, fuzzy msgid "There are no boats available for this spell." msgstr "Lanzar un hechizo tipo aventura." #, fuzzy msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "No hay un espacio libre adyacente a tu héroe para convocar un Elemental." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" #, fuzzy msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "No puedes usar ese hechizo. Cuesta %{mana} puntos de Maná y sólo tienes " "&{point}." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "La ciudad más cercana es %{town}.\n" "\n" "Esta ciudad está ocupada por tu héroe %{hero}." msgid "This spell is already in effect." msgstr "" msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Debes estar a %{count} casillas de un monstruo para que el hechizo Visiones " "funcione." #, fuzzy msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Has de estar en la entrada de una mina para lanzar este hechizo (las " "serrerías y las casas de alquimia no cuentan)." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" msgid "%{name} the %{race} (Level %{level})" msgstr "%{name}, %{race} ( Nivel %{level} )" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} ( Nivel %{level} )" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{name}, %{race} ( Nivel %{level} )" #, fuzzy msgid "Hero race:" msgstr "Pantalla de Héroe" msgid "Are you sure you want to dismiss this Hero?" msgstr "¿Estas seguro que quieres despedir este Héroe?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Ver información sobre Experiencia" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Maná" msgid "View Spell Points Info" msgstr "Ver información sobre Maná" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Pierdes el héroe: %{name}." #, fuzzy msgid "Click to change race." msgstr "Haga clic para ver la siguiente ciudad." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "La formación 'Desplegada' de combate disemina las tropas del héroe desde la " "parte superior a la inferior del campo de batalla, con al menos un espacio " "vacío entre las tropas." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "La formación 'Agrupada' de combate aglutina las tropas del heroe en el " "centro de su lado del campo de batalla." #, fuzzy msgid "Exit Hero Screen" msgstr "Pantalla de Héroe" msgid "You cannot dismiss a hero in a castle" msgstr "" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "" msgid "Dismiss %{name} the %{race}" msgstr "Despedir a %{name} (%{race})" #, fuzzy msgid "Show previous hero" msgstr "Ver ciudad anterior" msgid "Show next hero" msgstr "Mostrar el siguiente héroe" msgid "Set army combat formation to 'Spread'" msgstr "Ordenar al ejercito formación Desplegada." msgid "Set army combat formation to 'Grouped'" msgstr "Ordenar al ejercito formación Agrupada" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Haga clic aquí para seleccionar el escenario donde jugar." #, fuzzy msgid "Blood Morale" msgstr "Buena Moral" msgid "%{morale} Morale" msgstr "%{morale} Moral" msgid "%{luck} Luck" msgstr "" msgid "Current Luck Modifiers:" msgstr "Modificadores de suerte actuales:" msgid "Current Morale Modifiers:" msgstr "Modificadores de moral actuales:" msgid "Entire army is undead, so morale does not apply." msgstr "Todo el ejército es nomuerto, por lo tanto la moral no se aplica." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Experiencia actual: %{exp1}.\n" "Siguiente nivel a: %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Nivel %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} actualmente tiene %{point} puntos de Maná de un total de %{max}. El " "máximo número de puntos de Maná es 10 veces el conocimiento del héroe. " "Ocasionalmente es posible sobrepasar el máximo de puntos de Maná mediante " "eventos especiales." msgid "%{name1} meets %{name2}" msgstr "%{name1} se reune con %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Ahora se identifica totalmente a los héroes enemigos." msgid "Identify Hero" msgstr "Identificar Héroe" msgid "Select town to port to." msgstr "Seleccione la ciudad a la que transportarse." msgid "Town Portal" msgstr "Portal de la Ciudad" msgid "The creatures are willing to join us!" msgstr "¡Las criaturas quieren unirse a nosotros!" msgid "All the creatures will join us..." msgstr "Todas las criaturas se nos unirán..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "La criatura se unirá a nosotros..." msgstr[1] "%{count} de las criaturas se unirán a nosotros..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" " por un precio de %{gold} piezas de oro." msgid "These weak creatures will surely flee before us." msgstr "Esas débiles criaturas seguramente huirán nada más vernos." msgid "I fear these creatures are in the mood for a fight." msgstr "Me temo que esas criaturas tienen ganas de luchar." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "El ataque del héroe es una bonificación que se añade al ataque de cada " "unidad." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "La defensa del héroe es una bonificación añadida a la defensa de cada unidad." msgid "The hero's spell power determines the duration or power of a spell." msgstr "" "La potencia de hechizo del héroe determina la longitud o el poder de los " "hechizos." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "El conocimiento del héroe determina el número máximo de puntos de Maná que " "el héroe puede alcanzar. Bajo circunstancias normales, un héroe está " "limitado a 10 puntos de Maná por nivel de conocimiento." msgid "Current Modifiers:" msgstr "Modificadores actuales:" msgid "skill|Basic" msgstr "Básica" msgid "skill|Advanced" msgstr "Avanzada" msgid "skill|Expert" msgstr "Experta" msgid "Pathfinding" msgstr "Orientación" msgid "Archery" msgstr "Tiro con Arco" msgid "Logistics" msgstr "Logística" msgid "Scouting" msgstr "Exploración" msgid "Diplomacy" msgstr "Diplomacia" msgid "Navigation" msgstr "Navegación" msgid "Leadership" msgstr "Liderazgo" msgid "Wisdom" msgstr "Sabiduría" msgid "Mysticism" msgstr "Misticismo" msgid "Ballistics" msgstr "Balística" msgid "Eagle Eye" msgstr "Ojo de Ãguila" msgid "Necromancy" msgstr "Nigromancia" msgid "Estates" msgstr "Patrimonio" msgid "Advanced Archery" msgstr "Tiro con Arco Avanzado" msgid "Advanced Pathfinding" msgstr "Orientación Avanzada" msgid "Basic Archery" msgstr "Tiro con Arco Básico" msgid "Basic Pathfinding" msgstr "Orientación Básica" msgid "Expert Pathfinding" msgstr "Orientación Experta" msgid "Advanced Logistics" msgstr "Logística Avanzada" msgid "Basic Logistics" msgstr "Logística Básica" msgid "Basic Scouting" msgstr "Exploración Básica" msgid "Expert Archery" msgstr "Tiro con Arco Experto" msgid "Expert Logistics" msgstr "Logística Experta" msgid "Advanced Diplomacy" msgstr "Diplomacia Avanzada" msgid "Advanced Scouting" msgstr "Exploración Avanzada" msgid "Basic Diplomacy" msgstr "Diplomacia Básica" msgid "Expert Diplomacy" msgstr "Diplomacia Experta" msgid "Expert Scouting" msgstr "Exploración Experta" msgid "Advanced Leadership" msgstr "Liderazgo Avanzado" msgid "Advanced Navigation" msgstr "Navegación Avanzada" msgid "Basic Leadership" msgstr "Liderazgo Básico" msgid "Basic Navigation" msgstr "Navegación Básica" msgid "Expert Navigation" msgstr "Navegación Experta" msgid "Advanced Wisdom" msgstr "Sabiduría Avanzada" msgid "Basic Mysticism" msgstr "Misticismo Básico" msgid "Basic Wisdom" msgstr "Sabiduría Básica" msgid "Expert Leadership" msgstr "Liderazgo Experto" msgid "Expert Wisdom" msgstr "Sabiduría Experta" msgid "Advanced Luck" msgstr "Suerte Avanzada" msgid "Advanced Mysticism" msgstr "Misticismo Avanzado" msgid "Basic Luck" msgstr "Suerte Básica" msgid "Expert Luck" msgstr "Suerte Experta" msgid "Expert Mysticism" msgstr "Misticismo Experto" msgid "Advanced Ballistics" msgstr "Balística Avanzada" msgid "Advanced Eagle Eye" msgstr "Ojo de águila avanzado" msgid "Basic Ballistics" msgstr "Balística Básica" msgid "Basic Eagle Eye" msgstr "Ojo de águila básico" msgid "Expert Ballistics" msgstr "Balística Experta" msgid "Advanced Necromancy" msgstr "Necromancia Avanzada" msgid "Basic Estates" msgstr "Partimonio Básico" msgid "Basic Necromancy" msgstr "Necromancia Básica" msgid "Expert Eagle Eye" msgstr "Ojo de águila experto" msgid "Expert Necromancy" msgstr "Necromancia Experta" msgid "Advanced Estates" msgstr "Partimonio Avanzado" msgid "Expert Estates" msgstr "Partimonio Experto" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "La %{skill} reduce la penalización al movimiento debida a terreno agreste en " "un %{count} por ciento." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "La %{skill} elimina la penalización de movimiento por terreno agreste." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "El %{skill} aumenta un %{count}% el daño infligido por las criaturas " "atacantes a distancia del héroe y elimina la penalización del %{penalty}% al " "disparar más allá de obstáculos (por ejemplo, muros de castillos)." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" "La %{skill} aumenta los puntos de movimiento del héroe en un %{count}%." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "La %{skill} aumenta el área visible del héroe en una casilla." msgstr[1] "La %{skill} aumenta el área visible del héroe en %{count} casillas." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "La %{skill} permite al héroe negociar con monstruos más débiles que su " "ejército, y reduce el coste de la rendición." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Aproximadamente el %{count}% de las criaturas pueden ofrecer unirse al héroe." msgid "All of the creatures may offer to join the hero." msgstr "Todas las criaturas pueden ofrecer unirse al héroe." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "El coste de la rendición se reduce al %{percent}% del coste total de las " "tropas del ejército." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "La %{skill} aumenta los puntos de movimiento del héroe sobre el agua en un " "%{count}%." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "El %{skill} aumenta la moral de las tropas del héroe en %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "La %{skill} permite al héroe aprender hechizos de tercer nivel." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "La %{skill} permite al héroe aprender hechizos de cuarto nivel." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "La %{skill} permite al héroe aprender hechizos de quinto nivel." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" "El %{skill} regenera un punto de hechizo adicional por día al héroe." msgstr[1] "" "El %{skill} regenera %{count} puntos de hechizo adicionales al día al héroe." msgid "%{skill} increases the hero's luck by %{count}." msgstr "La %{skill} aumenta la suerte del héroe en %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "La %{skill} da a los disparos de catapulta del héroe una mayor probabilidad " "de impactar y hacer daño a los muros del castillo." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "La %{skill} da a la catapulta del héroe un disparo extra, y cada disparo " "tiene más posibilidades de acertar y hacer daño a los muros del castillo." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "La %{skill} da a la catapulta del héroe un disparo extra, y cada disparo " "destruye automáticamente cualquier muro, excepto un muro fortificado en un " "castillo de caballero." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "El %{skill} otorga al héroe un %{count}% de posibilidades de aprender " "cualquier hechizo de 1o o 2o nivel lanzado por un enemigo durante el combate." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "El %{skill} otorga al héroe un %{count}% de posibilidades de aprender " "cualquier hechizo de 4o nivel (o inferior) lanzado por un enemigo durante el " "combate." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "El %{skill} otorga al héroe un %{count}% de posibilidades de aprender " "cualquier hechizo de 3er nivel (o inferior) lanzado por un enemigo durante " "el combate." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "La %{skill} permite resucitar como esqueletos al %{count}% de las criaturas " "muertas en combate." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "El héroe produce %{count} piezas de oro al día como ingresos fiscales de las " "propiedades." msgid "Blue" msgstr "Azul" msgid "Green" msgstr "Verde" msgid "Red" msgstr "Rojo" msgid "Yellow" msgstr "Amarillo" msgid "Orange" msgstr "Naranja" msgid "Purple" msgstr "Morado" msgid "barrier|Aqua" msgstr "turquesa" msgid "barrier|Blue" msgstr "azul" msgid "barrier|Brown" msgstr "marrón" msgid "barrier|Gold" msgstr "dorada" msgid "barrier|Green" msgstr "verde" msgid "barrier|Orange" msgstr "naranja" msgid "barrier|Purple" msgstr "morada" msgid "barrier|Red" msgstr "roja" msgid "tent|Aqua" msgstr "turquesa" msgid "tent|Blue" msgstr "azul" msgid "tent|Brown" msgstr "marrón" msgid "tent|Gold" msgstr "dorada" msgid "tent|Green" msgstr "verde" msgid "tent|Orange" msgstr "naranja" msgid "tent|Purple" msgstr "morada" msgid "tent|Red" msgstr "roja" msgid "Experience" msgstr "Experiencia" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" msgid "Hero/Stats" msgstr "Héroe / Estadísticas" msgid "Skills" msgstr "Experiencia" msgid "Town/Castle" msgstr "Ciudad/Castillo" msgid "Garrison" msgstr "Guarnición" msgid "Gold Per Day:" msgstr "Oro por día:" msgid "View Heroes." msgstr "Mostrar Héroes." msgid "Towns/Castles" msgstr "Ciudades/Castillos" msgid "View Towns and Castles." msgstr "Ver Ciudades y Castillos." msgid "luck|Cursed" msgstr "Maldito" msgid "luck|Awful" msgstr "Horrible" msgid "luck|Bad" msgstr "Mala" msgid "luck|Normal" msgstr "Normal" msgid "luck|Good" msgstr "Buena" msgid "luck|Great" msgstr "Grande" msgid "luck|Irish" msgstr "Irlandés" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "La Mala suerte cae a veces en combate sobre tus tropas dividiendo por 2 el " "daño de sus ataques." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Con Suerte Neutral tus ejércitos nunca lograrán ataques afortunados o " "desafortunados." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Con Buena Suerte a veces tus tropas consegirán ataques afortunados " "duplicando su daño." msgid "morale|Treason" msgstr "Traición" msgid "morale|Awful" msgstr "Horrible" msgid "morale|Poor" msgstr "Pobre" msgid "morale|Normal" msgstr "Normal" msgid "morale|Good" msgstr "Bueno" msgid "morale|Great" msgstr "Grande" msgid "morale|Blood!" msgstr "¡Sangre!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Con Baja Moral tus tropas puede paralizarse en combate." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Con Moral Neutral tus tropas no serán bendecidas con ataques adicionales ni " "se petrificarán en combate." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Con Moral Alta tus tropas podrán lograr ataques extra en combate." msgid "Knight" msgstr "Caballero" msgid "Barbarian" msgstr "Bárbaro" msgid "Sorceress" msgstr "Hechicera" msgid "Warlock" msgstr "Brujo" msgid "Wizard" msgstr "Mago" msgid "Necromancer" msgstr "Nigromante" msgid "Multi" msgstr "Multi" msgid "doubleLined|Knight" msgstr "Caballero" msgid "doubleLined|Barbarian" msgstr "Bárbaro" msgid "doubleLined|Sorceress" msgstr "Hechicera" msgid "doubleLined|Warlock" msgstr "Brujo" msgid "doubleLined|Wizard" msgstr "Mago" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Nigro-\n" "mante" msgid "doubleLinedRace|Multi" msgstr "Multi" msgid "doubleLinedRace|Random" msgstr "Aleatorio" msgid "speed|Standing" msgstr "Fijo" msgid "speed|Crawling" msgstr "Arrastrando" msgid "speed|Very Slow" msgstr "Muy lenta" msgid "speed|Slow" msgstr "Lenta" msgid "speed|Average" msgstr "Media" msgid "speed|Fast" msgstr "Rápida" msgid "speed|Very Fast" msgstr "Muy rápida" msgid "speed|Ultra Fast" msgstr "Ultra rápida" msgid "speed|Blazing" msgstr "Fugaz" msgid "speed|Instant" msgstr "Instantáneo" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Ardilla" msgid "week|Rabbit" msgstr "Conejo" msgid "week|Gopher" msgstr "Tuza" msgid "week|Badger" msgstr "Tejón" msgid "week|Rat" msgstr "Rata" msgid "week|Eagle" msgstr "Ãguila" msgid "week|Weasel" msgstr "Comadreja" msgid "week|Raven" msgstr "Cuervo" msgid "week|Mongoose" msgstr "Mangosta" msgid "week|Dog" msgstr "Perro" msgid "week|Aardvark" msgstr "Oso hormiguero" msgid "week|Lizard" msgstr "Lagarto" msgid "week|Tortoise" msgstr "Tortuga" msgid "week|Hedgehog" msgstr "Puercoespín" msgid "week|Condor" msgstr "Cóndor" msgid "week|Ant" msgstr "Hormiga" msgid "week|Grasshopper" msgstr "Saltamontes" msgid "week|Dragonfly" msgstr "Libélula" msgid "week|Spider" msgstr "Araña" msgid "week|Butterfly" msgstr "Mariposa" msgid "week|Bumblebee" msgstr "Abejorro" msgid "week|Locust" msgstr "Langosta" msgid "week|Earthworm" msgstr "Gusano" msgid "week|Hornet" msgstr "Avispa" msgid "week|Beetle" msgstr "Escarabajo" msgid "week|PLAGUE" msgstr "PLAGA" msgid "week|Unnamed" msgstr "Sin nombre" msgid "Desert" msgstr "Desierto" msgid "Snow" msgstr "Nieve" msgid "Wasteland" msgstr "Paraje baldio" msgid "Beach" msgstr "Playa" msgid "Lava" msgstr "Zona Volcánica" msgid "Dirt" msgstr "Terreno arcilloso" msgid "Grass" msgstr "Pastos" msgid "Ocean" msgstr "Océano" msgid "maps|Small" msgstr "Pequeño" msgid "maps|Medium" msgstr "Mediano" msgid "maps|Large" msgstr "Grande" msgid "maps|Extra Large" msgstr "Extra grande" msgid "maps|Custom Size" msgstr "" msgid "Ore Mine" msgstr "Mina de Hierro" msgid "Sulfur Mine" msgstr "Mina de Azufre" msgid "Crystal Mine" msgstr "Mina de Cristal" msgid "Gems Mine" msgstr "Mina de Gemas" msgid "Gold Mine" msgstr "Mina de Oro" msgid "Mine" msgstr "Mina" msgid "Burma shave." msgstr "" msgid "Next sign 50 miles." msgstr "" #, fuzzy msgid "See Rock City." msgstr "Ciudad del Ãrbol" msgid "This space for rent." msgstr "" msgid "No object" msgstr "" msgid "Alchemist Lab" msgstr "Alquimista" msgid "Sign" msgstr "Señal" msgid "Buoy" msgstr "Boya" msgid "Skeleton" msgstr "Esqueleto" msgid "Daemon Cave" msgstr "Cueva del Demonio" msgid "Treasure Chest" msgstr "Cofre del Tesoro" msgid "Faerie Ring" msgstr "Anillo del Hada" msgid "Campfire" msgstr "Hoguera" msgid "Fountain" msgstr "Fuente" msgid "Gazebo" msgstr "Cenador" msgid "Genie Lamp" msgstr "Lampara del Genio" msgid "Archer's House" msgstr "Casa del Arquero" msgid "Goblin Hut" msgstr "Palloza" msgid "Dwarf Cottage" msgstr "Casita de Enanos" msgid "Peasant Hut" msgstr "Cabaña de Campesinos" msgid "Stables" msgstr "Establos" msgid "Alchemist's Tower" msgstr "Torre del Alquimista" msgid "Event" msgstr "" msgid "Dragon City" msgstr "Ciudad Dragón" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Faro" msgstr[1] "Faros" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Molino de Agua" msgstr[1] "Molinos de Agua" msgid "Monster" msgstr "Monstruo" msgid "Obelisk" msgstr "Obelisco" msgid "Oasis" msgstr "Oasis" msgid "Resource" msgstr "Recursos" msgid "Sawmill" msgstr "Aserradero" msgid "Oracle" msgstr "Oráculo" msgid "Shrine of the First Circle" msgstr "Capilla del Primer Círculo" msgid "Shipwreck" msgstr "Naufragio" msgid "Sea Chest" msgstr "Cofre Marino" msgid "Desert Tent" msgstr "Tienda del Desierto" msgid "Stone Liths" msgstr "" msgid "Wagon Camp" msgstr "Carromato" msgid "Hut of the Magi" msgstr "Cabaña del los Magos" msgid "Whirlpool" msgstr "Remolino" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Molino de Viento" msgstr[1] "Molinos de Viento" msgid "Mermaid" msgstr "Sirena" msgid "Boat" msgstr "Bote" #, fuzzy msgid "Random Ultimate Artifact" msgstr "Encuentra el artefacto definitivo" #, fuzzy msgid "Random Artifact" msgstr "Artefacto" #, fuzzy msgid "Random Resource" msgstr "Recursos" #, fuzzy msgid "Random Monster" msgstr "Cualquier castillo" msgid "Random Town" msgstr "Cualquier torre" msgid "Random Castle" msgstr "Cualquier castillo" msgid "Eye of the Magi" msgstr "Ojo de los Magos" #, fuzzy msgid "Random Monster - weak" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monster - medium" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monster - strong" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monster - very strong" msgstr "Cualquier castillo" msgid "Hero" msgstr "Héroe" msgid "Nothing Special" msgstr "Nada especial" msgid "Mossy Rock" msgstr "" msgid "Watch Tower" msgstr "Torre de Vigilancia" msgid "Tree House" msgstr "Casa de Ãrbol" msgid "Tree City" msgstr "Ciudad del Ãrbol" msgid "Ruins" msgstr "Ruinas" msgid "Fort" msgstr "Fortaleza" msgid "Abandoned Mine" msgstr "Mina Abandonada" msgid "Sirens" msgstr "Sirenas" msgid "Standing Stones" msgstr "Círculo Lítico" msgid "Idol" msgstr "Ãdolo" msgid "Tree of Knowledge" msgstr "Ãrbol del conocimiento" msgid "Witch Doctor's Hut" msgstr "Cabaña de la Bruja" msgid "Temple" msgstr "Templo" msgid "Hill Fort" msgstr "Fuerte de la Colina" msgid "Halfling Hole" msgstr "Hoyo de los Medianos" msgid "Mercenary Camp" msgstr "Campamento Mercenario" msgid "Shrine of the Second Circle" msgstr "Capilla del Segundo Círculo" msgid "Shrine of the Third Circle" msgstr "Capilla del Tercer Círculo" msgid "City of the Dead" msgstr "Ciudad de la muerte" msgid "Sphinx" msgstr "Esfinge" msgid "Wagon" msgstr "Vagón" msgid "Tar Pit" msgstr "Fosa de Alquitrán" msgid "Artesian Spring" msgstr "Pozo Artesiano" msgid "Troll Bridge" msgstr "Puente de los Trolls" msgid "Watering Hole" msgstr "Gotera" msgid "Witch's Hut" msgstr "Choza de brujas" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Apoyar" msgid "Magellan's Maps" msgstr "Mapas de Magallanes" msgid "Flotsam" msgstr "Restos de un naufragio" msgid "Derelict Ship" msgstr "Barco Abandonado" msgid "Shipwreck Survivor" msgstr "" msgid "Bottle" msgstr "Botella" msgid "Magic Well" msgstr "Pozo Mágico" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Jardín mágico" msgstr[1] "Jardines mágicos" msgid "Observation Tower" msgstr "Torre de observación" #, fuzzy msgid "Freeman's Foundry" msgstr "Fundición" msgid "Reefs" msgstr "Arrecifes" msgid "Volcano" msgstr "Volcán" msgid "Flowers" msgstr "Flores" msgid "Rock" msgstr "Roca" msgid "Water Lake" msgstr "Lago" msgid "Mandrake" msgstr "Mandrágora" msgid "Dead Tree" msgstr "Ãrbol muerto" msgid "Stump" msgstr "Cepa" msgid "Crater" msgstr "Cráter" msgid "Cactus" msgstr "Cactus" msgid "Mound" msgstr "Montón" msgid "Dune" msgstr "Duna" msgid "Lava Pool" msgstr "Charca de Lava" msgid "Shrub" msgstr "Arbusto" msgid "Barrow Mounds" msgstr "Montículo de la Carretilla" msgid "Random Artifact - Treasure" msgstr "" msgid "Random Artifact - Minor" msgstr "" msgid "Random Artifact - Major" msgstr "" msgid "Barrier" msgstr "Barrera" msgid "Traveller's Tent" msgstr "Tienda del Viajero" msgid "Jail" msgstr "Cárcel" msgid "Fire Summoning Altar" msgstr "Altar del Fuego" msgid "Air Summoning Altar" msgstr "Altar del Aire" msgid "Earth Summoning Altar" msgstr "Altar de la Tierra" msgid "Water Summoning Altar" msgstr "Altar del Agua" #, fuzzy msgid "Swampy Lake" msgstr "Ciénaga" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" #, fuzzy msgid "Unknown Monsters" msgstr "Monstruos" #, fuzzy msgid "Unknown Monster" msgstr "Monstruo" msgid "Peasant" msgstr "Campesino" msgid "Peasants" msgstr "Campesinos" msgid "Archer" msgstr "Arquero" msgid "Archers" msgstr "Arqueros" msgid "Ranger" msgstr "Cazador" msgid "Rangers" msgstr "Cazadores" msgid "Pikeman" msgstr "Piquero" msgid "Pikemen" msgstr "Piqueros" msgid "Veteran Pikeman" msgstr "Piquero veterano" msgid "Veteran Pikemen" msgstr "Piqueros veteranos" msgid "Swordsman" msgstr "Espadachín" msgid "Swordsmen" msgstr "Espadachín" msgid "Master Swordsman" msgstr "Maestro Espadachín" msgid "Master Swordsmen" msgstr "Maestros Espadachines" msgid "Cavalries" msgstr "Caballerías" msgid "Cavalry" msgstr "Caballería" msgid "Champion" msgstr "Campeón" msgid "Champions" msgstr "Campeones" msgid "Paladin" msgstr "Paladín" msgid "Paladins" msgstr "Paladines" msgid "Crusader" msgstr "Cruzado" msgid "Crusaders" msgstr "Cruzados" msgid "Goblin" msgstr "Trasgo" msgid "Goblins" msgstr "Trasgos" msgid "Orc" msgstr "Orco" msgid "Orcs" msgstr "Orcos" msgid "Orc Chief" msgstr "Jefe Orco" msgid "Orc Chiefs" msgstr "Jefes Orcos" msgid "Wolf" msgstr "Lobo" msgid "Wolves" msgstr "Lobos" msgid "Ogre" msgstr "Ogro" msgid "Ogres" msgstr "Ogros" msgid "Ogre Lord" msgstr "Ogro de Combate" msgid "Ogre Lords" msgstr "Ogros de Combate" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Trolls" msgid "War Troll" msgstr "Troll de Guerra" msgid "War Trolls" msgstr "Trolls de Guerra" msgid "Cyclopes" msgstr "Cíclopes" msgid "Cyclops" msgstr "Cíclope" msgid "Sprite" msgstr "Hada" msgid "Sprites" msgstr "Hadas" msgid "Dwarf" msgstr "Enano" msgid "Dwarves" msgstr "Enanos" msgid "Battle Dwarf" msgstr "Enano de Combate" msgid "Battle Dwarves" msgstr "Enanos de Combate" msgid "Elf" msgstr "Elfo" msgid "Elves" msgstr "Elfos" msgid "Grand Elf" msgstr "Gran Elfo" msgid "Grand Elves" msgstr "Grandes Elfos" msgid "Druid" msgstr "Druida" msgid "Druids" msgstr "Druidas" msgid "Greater Druid" msgstr "Gran Druida" msgid "Greater Druids" msgstr "Grandes Druidas" msgid "Unicorn" msgstr "Unicornio" msgid "Unicorns" msgstr "Unicornios" msgid "Phoenix" msgstr "Fénix" msgid "Phoenixes" msgstr "Fénix" msgid "Centaur" msgstr "Centauro" msgid "Centaurs" msgstr "Centauros" msgid "Gargoyle" msgstr "Gárgola" msgid "Gargoyles" msgstr "Gárgolas" msgid "Griffin" msgstr "Grifo" msgid "Griffins" msgstr "Grifos" msgid "Minotaur" msgstr "Minotauro" msgid "Minotaurs" msgstr "Minotauros" msgid "Minotaur King" msgstr "Minotauro Rey" msgid "Minotaur Kings" msgstr "Minotauros Reyes" msgid "Hydra" msgstr "Hidra" msgid "Hydras" msgstr "Hidras" msgid "Green Dragon" msgstr "Dragón Verde" msgid "Green Dragons" msgstr "Dragones Verdes" msgid "Red Dragon" msgstr "Dragón Rojo" msgid "Red Dragons" msgstr "Dragones Rojos" msgid "Black Dragon" msgstr "Dragón Negro" msgid "Black Dragons" msgstr "Dragones Negros" msgid "Halfling" msgstr "Mediano" msgid "Halflings" msgstr "Medianos" msgid "Boar" msgstr "Jabalí" msgid "Boars" msgstr "Jabalíes" msgid "Iron Golem" msgstr "Golem de Hierro" msgid "Iron Golems" msgstr "Golems de Hierro" msgid "Steel Golem" msgstr "Golem de Acero" msgid "Steel Golems" msgstr "Golems de Acero" msgid "Roc" msgstr "Roc" msgid "Rocs" msgstr "Rocs" msgid "Mage" msgstr "Mago" msgid "Magi" msgstr "Magos" msgid "Archmage" msgstr "Archimago" msgid "Archmagi" msgstr "Archimagos" msgid "Giant" msgstr "Gigante" msgid "Giants" msgstr "Gigantes" msgid "Titan" msgstr "Titán" msgid "Titans" msgstr "Titanes" msgid "Skeletons" msgstr "Esqueletos" msgid "Zombie" msgstr "Zombi" msgid "Zombies" msgstr "Zombis" msgid "Mutant Zombie" msgstr "Zombi Mutante" msgid "Mutant Zombies" msgstr "Zombis Mutantes" msgid "Mummies" msgstr "Momias" msgid "Mummy" msgstr "Momia" msgid "Royal Mummies" msgstr "Momias Reales" msgid "Royal Mummy" msgstr "Momia Real" msgid "Vampire" msgstr "Vampiro" msgid "Vampires" msgstr "Vampiros" msgid "Vampire Lord" msgstr "Maestro Vampiro" msgid "Vampire Lords" msgstr "Maestros Vampiros" msgid "Lich" msgstr "Liche" msgid "Liches" msgstr "Liches" msgid "Power Lich" msgstr "Gran Liche" msgid "Power Liches" msgstr "Grandes Liches" msgid "Bone Dragon" msgstr "Dragón de Hueso" msgid "Bone Dragons" msgstr "Dragones de Hueso" msgid "Rogue" msgstr "Bandido" msgid "Rogues" msgstr "Bandidos" msgid "Nomad" msgstr "Nómada" msgid "Nomads" msgstr "Nómadas" msgid "Ghost" msgstr "Fantasma" msgid "Ghosts" msgstr "Fantasmas" msgid "Genie" msgstr "Genio" msgid "Genies" msgstr "Genios" msgid "Medusa" msgstr "Medusa" msgid "Medusas" msgstr "Medusas" msgid "Earth Elemental" msgstr "Elemental de la Tierra" msgid "Earth Elementals" msgstr "Elementales de la Tierra" msgid "Air Elemental" msgstr "Elemental del Aire" msgid "Air Elementals" msgstr "Elementales del Aire" msgid "Fire Elemental" msgstr "Elemental del Fuego" msgid "Fire Elementals" msgstr "Elementales del Fuego" msgid "Water Elemental" msgstr "Elemental del Agua" msgid "Water Elementals" msgstr "Elementales del Agua" #, fuzzy msgid "Random Monsters" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monster 1" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monsters 1" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monster 2" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monsters 2" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monster 3" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monsters 3" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monster 4" msgstr "Cualquier castillo" #, fuzzy msgid "Random Monsters 4" msgstr "Cualquier castillo" msgid "Double shot" msgstr "Doble tiro" msgid "2-hex monster" msgstr "Ocupa dos casillas" msgid "Double strike" msgstr "Doble golpe" msgid "Double damage to Undead" msgstr "Doble daño a nomuertos" msgid "% magic resistance" msgstr "% de resistencia mágica" msgid "Immune to Mind spells" msgstr "Inmune a los hechizos mentales" msgid "Immune to Elemental spells" msgstr "Inmune a hechizos elementales" msgid "Immune to Fire spells" msgstr "Inmune a los hechizos de fuego" msgid "Immune to Cold spells" msgstr "Inmune a los hechizos de frío" msgid "Immune to " msgstr "Inmune a " msgid "% immunity to %{spell} spell" msgstr "% de inmunidad al hechizo %{spell}" msgid "% damage from Elemental spells" msgstr "% de daño de los hechizos elementales" msgid "% damage from %{spell} spell" msgstr "% de daño del hechizo %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% de probabilidad de disipar hechizos beneficiosos" msgid "% chance to Paralyze" msgstr "% de probabilidad de paralizar" msgid "% chance to Petrify" msgstr "% de probabilidad de petrificar" msgid "% chance to Blind" msgstr "% de probabilidad de cegar" msgid "% chance to Curse" msgstr "% de probabilidad de maldecir" msgid "% chance to cast %{spell} spell" msgstr "% de probabilidad de lanzar hechizo de %{spell}" msgid "HP regeneration" msgstr "Regeneración de PV" msgid "Two hexes attack" msgstr "Ataque a dos casillas" msgid "Flyer" msgstr "Volador" msgid "Always retaliates" msgstr "Siempre contraataca" msgid "Attacks all adjacent enemies" msgstr "Ataca a todos los enemigos adyacentes" msgid "No melee penalty" msgstr "Ninguna penalización cuerpo a cuerpo" msgid "Dragon" msgstr "Dragón" msgid "Undead" msgstr "Nomuerto" msgid "No enemy retaliation" msgstr "Ningún contraataque enemigo" msgid "HP drain" msgstr "Drenaje PV" msgid "Cloud attack" msgstr "Ataque de nube" msgid "Decreases enemy's morale by " msgstr "Disminuye la moral del enemigo en " msgid "% chance to halve enemy" msgstr "% de probabilidad de reducir a la mitad a un enemigo" msgid "Soul Eater" msgstr "Devorador de almas" msgid "Elemental" msgstr "Elemental" msgid "No Morale" msgstr "Sin moral" #, fuzzy msgid "Earth creature" msgstr "Reclutar Criaturas" #, fuzzy msgid "Air creature" msgstr "Reclutar Criaturas" #, fuzzy msgid "Fire creature" msgstr "Reclutar Criaturas" #, fuzzy msgid "Water creature" msgstr "Lago" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% de daño de los hechizos de fuego" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% de daño de los hechizos de frío" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Elimina todos los hechizos mágicos que afectan a todas las criaturas." #, fuzzy msgid "Double damage from Air creatures" msgstr "Doble daño a nomuertos" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% de daño de los hechizos de fuego" #, fuzzy msgid "Double damage from Water creatures" msgstr "Elimina todos los hechizos mágicos que afectan a todas las criaturas." msgid "Lightning" msgstr "Rayo" msgid "% immunity to " msgstr "% de inmunidad al " msgid "% damage from " msgstr "% de daño de " msgid "The three Anduran artifacts magically combine into one." msgstr "Los tres artefactos mágicos de Anduran combinados en uno." #, fuzzy msgid "View Spells" msgstr "Ver Todo" #, fuzzy msgid "View %{name} Info" msgstr "Ver %{name}" msgid "Move %{name}" msgstr "" msgid "Cannot move the Spellbook" msgstr "No se puede transferir el Libro de Hechizos" msgid "This item can't be traded." msgstr "Este artefacto no puede transferirse." #, fuzzy msgid "Invalid Artifact" msgstr "Artefacto" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} aumenta lo conocimiento del héroe en %{count}." msgid "Ultimate Book of Knowledge" msgstr "El Libro Definitivo del Conocimiento" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} aumenta el ataque del héroe en %{count}." msgid "Ultimate Sword of Dominion" msgstr "La Espada Final de la Dominación" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} aumenta la defensa del héroe en %{count}." msgid "Ultimate Cloak of Protection" msgstr "La Capa Final de la Protección" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} aumenta la potencia del héroe en %{count}." msgid "Ultimate Wand of Magic" msgstr "La Varíta Final de la Magia" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} aumenta el ataque y la defensa del héroe en %{count} cada uno." msgid "Ultimate Shield" msgstr "El Escudo Supremo" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "" "%{name} aumenta la potencia y el conocimiento del héroe en %{count} cada uno." msgid "Ultimate Staff" msgstr "El Cayado Supremo" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "" "%{name} aumenta cada una de las habilidades básicas del héroe en %{count} " "puntos." msgid "Ultimate Crown" msgstr "La Corona Suprema" msgid "Golden Goose" msgstr "El Ganso Dorado" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} aporta unos ingresos de %{count} piezas de oro al día." msgid "Arcane Necklace of Magic" msgstr "El Collar Arcano de la Magia" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" msgid "Caster's Bracelet of Magic" msgstr "El Brazalete del Lanzador de la Magia" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" msgid "Mage's Ring of Power" msgstr "El Anillo del Mago del Poder" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" msgid "Witch's Broach of Magic" msgstr "El Broche de Bruja de la Magia" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" msgid "Medal of Valor" msgstr "La Medalla de Valor" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} aumenta la moral del ejército del héroe en %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" msgid "Medal of Courage" msgstr "La Medalla de Coraje" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" msgid "Medal of Honor" msgstr "La Medalla de Honor" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" msgid "Medal of Distinction" msgstr "La Medalla de Distinción" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" msgid "Fizbin of Misfortune" msgstr "El Fizbin de la Mala Suerte" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "" "%{name} disminuye enormemente la moral del ejército del héroe en %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" msgid "Thunder Mace of Dominion" msgstr "La Maza del Trueno de Dominio" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" msgid "Armored Gauntlets of Protection" msgstr "Los Guanteletes Blindados de Protección" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} aumenta la defensa del héroe en %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" msgid "Defender Helm of Protection" msgstr "El Yelmo Defensor de la Protección" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" msgid "Giant Flail of Dominion" msgstr "El Mangual Gigante de la Dominación" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" msgid "Ballista of Quickness" msgstr "La Ballesta de Rapidez" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "%{name} otorga a la catapulta del héroe un disparo extra por ronda de " "combate." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" msgid "Stealth Shield of Protection" msgstr "El Escudo Sigiloso de la Protección" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" msgid "Dragon Sword of Dominion" msgstr "La Espada Dragón de la Dominación" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" msgid "Power Axe of Dominion" msgstr "La Hacha Poderosa de la Dominación" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" msgid "Divine Breastplate of Protection" msgstr "La Coraza Divina de Protección" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" msgid "Minor Scroll of Knowledge" msgstr "El Pergamino Menor de Conocimiento" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" msgid "Major Scroll of Knowledge" msgstr "El Rollo Mayor del Conocimiento" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" msgid "Superior Scroll of Knowledge" msgstr "El Rollo Superior del Conocimiento" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" msgid "Foremost Scroll of Knowledge" msgstr "El Principal Pergamino de Conocimiento" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" msgid "Endless Sack of Gold" msgstr "La Saca inagotable de Oro" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} proporciona al héroe %{count} piezas de oro al día." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" msgid "Endless Bag of Gold" msgstr "La Bolsa inagotable de Oro" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" msgid "Endless Purse of Gold" msgstr "La Cartera inagotable de Oro" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" msgid "Nomad Boots of Mobility" msgstr "Las Botas Nómadas de la Movilidad" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} aumenta el movimiento del héroe en tierra." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" msgid "Traveler's Boots of Mobility" msgstr "Las Botas de Viajero de la Movilidad" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" msgid "Lucky Rabbit's Foot" msgstr "La Pata de Conejo de la Suerte" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} aumenta la suerte del ejército del héroe en %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" msgid "Golden Horseshoe" msgstr "La Herradura Dorada" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" msgid "Gambler's Lucky Coin" msgstr "La Moneda de la Suerte del Jugador" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" msgid "Four-Leaf Clover" msgstr "El Trébol de 4 Hojas" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" msgid "True Compass of Mobility" msgstr "La Brújula de la Verdera Movilidad" msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} aumenta el movimiento del héroe en tierra y mar." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" msgid "Sailor's Astrolabe of Mobility" msgstr "El Astrolabio del Marinero de la Movilidad" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} aumenta el movimiento del héroe en el mar." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" msgid "Evil Eye" msgstr "El Ojo Maligno" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" "%{name} reduce a la mitad el coste de lanzamiento de los hechizos de " "maldición." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" msgid "Enchanted Hourglass" msgstr "El Reloj de Arena Encantado" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} prolonga la duración de todos los hechizos del héroe en %{count} " "turnos." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" msgid "Gold Watch" msgstr "El Reloj de Oro" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} dobla la eficacia de los hechizos de hipnosis del héroe." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" msgid "Skullcap" msgstr "El Casco de Cráneo" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} reduce a la mitad el coste de lanzamiento de todos los hechizos que " "influencian la mente." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" msgid "Ice Cloak" msgstr "La Capa de Hielo" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} reduce a la mitad todo el daño que las tropas del héroe reciben de " "hechizos de frío." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" msgid "Fire Cloak" msgstr "La Capa de Fuego" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} reduce a la mitad todo el daño que las tropas del héroe reciben de " "hechizos de fuego." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" msgid "Lightning Helm" msgstr "El Casco Relampagueante" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} reduce a la mitad todo el daño que las tropas del héroe reciben de " "hechizos de rayo." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" msgid "Evercold Icicle" msgstr "El Carámbano del Frío Eterno" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} hace que los hechizos de frío del héroe inflijan un %{count}% más de " "daño a las tropas enemigas." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" msgid "Everhot Lava Rock" msgstr "La Roca de Lava del Calor Eterno" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} hace que los hechizos de fuego del héroe hagan un %{count}% más de " "daño a las tropas enemigas." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" msgid "Lightning Rod" msgstr "La Vara Relampagueante" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} hace que los hechizos de rayo del héroe hagan un %{count}% más de " "daño a las tropas enemigas." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" msgid "Snake-Ring" msgstr "El Anillo-Serpiente" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} reduce a la mitad el coste de lanzamiento de todos los hechizos de " "bendición del héroe." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" msgid "Ankh" msgstr "Llave de la Vida" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} duplica la eficacia de todos los hechizos de resurrección y animar " "del héroe." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" msgid "Book of Elements" msgstr "El Libro de los Elementos" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" "%{name} duplica la eficacia de todos los hechizos de invocación del héroe." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" msgid "Elemental Ring" msgstr "El Anillo Elemental" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" "%{name} reduce a la mitad el coste de lanzamiento de todos los hechizos de " "invocación." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" msgid "Holy Pendant" msgstr "El Colgante Sagrado" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos de " "maldición." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" msgid "Pendant of Free Will" msgstr "El Colgante de la Voluntad Libre" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos de " "hipnotizar." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" msgid "Pendant of Life" msgstr "El Colgante de la Vida" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos de " "muerte." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" msgid "Serenity Pendant" msgstr "El Colgante de la Serenidad" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos de " "berserk." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" msgid "Seeing-eye Pendant" msgstr "El Colgante Visionario" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos de " "ceguera." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" msgid "Kinetic Pendant" msgstr "El Colgante Cinético" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos de " "paralizar." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" msgid "Pendant of Death" msgstr "El Colgante de la Muerte" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos " "sagrados." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" msgid "Wand of Negation" msgstr "La Varita de la Negación" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "%{name} hace que todas las tropas del héroe sean inmunes a los hechizos de " "disipar." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" msgid "Golden Bow" msgstr "El Arco Dorado" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} elimina la penalización del %{count}% para las tropas del héroe que " "disparan más allá de obstáculos (por ejemplo, muros de castillos)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" msgid "Telescope" msgstr "El Telescopio" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} aumentan la cantidad de terreno que el héroe revela al aventurarse " "en %{count} casilla extra." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" msgid "Statesman's Quill" msgstr "La Pluma de Estadista" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} reduce el coste de la rendición al %{count}% del coste total de las " "tropas que el héroe tiene en su ejército." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" msgid "Wizard's Hat" msgstr "El Sombrero de Mago" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "" "%{name} aumenta la duración de los hechizos del héroe en %{count} turnos." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" msgid "Power Ring" msgstr "El Anillo de Poder" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} devuelve %{count} puntos de hechizo extra por día al héroe." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" msgid "Ammo Cart" msgstr "El Carro de Munición" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} proporciona munición infinita para todas las tropas del héroe que " "disparan." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" msgid "Tax Lien" msgstr "La Tasa de Embargo" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} le cuesta al héroe %{count} piezas de oro al día." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" msgid "Hideous Mask" msgstr "La Máscara Horrenda" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "%{name} impide que todos los ejércitos \"errantes\" se unan al héroe." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" msgid "Endless Pouch of Sulfur" msgstr "La Bolsa Inagotable de Sulfuro" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} proporciona %{count} unidades de azufre al día." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" msgid "Endless Vial of Mercury" msgstr "El Frasco Inagotable de Mercurio" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} proporciona %{count} unidades de mercurio al día." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" msgid "Endless Pouch of Gems" msgstr "La Bolsa Inagotable de Gemas" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} proporciona %{count} unidades de gemas al día." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" msgid "Endless Cord of Wood" msgstr "La Cuerda Interminable de Madera" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} proporciona %{count} unidades de madera al día." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" msgid "Endless Cart of Ore" msgstr "El Carro de Piedra Inagotable" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} proporciona %{count} unidades de mineral al día." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" msgid "Endless Pouch of Crystal" msgstr "La Bolsa Inagotable de Cristal" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} proporciona %{count} unidades de cristal al día." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" msgid "Spiked Helm" msgstr "El Casco Picudo" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" msgid "Spiked Shield" msgstr "El Escudo Picudo" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" msgid "White Pearl" msgstr "La Perla Blanca" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" msgid "Black Pearl" msgstr "La Perla Negra" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" msgid "Magic Book" msgstr "El Libro de Hechizos" msgid "The %{name} enables the hero to cast spells." msgstr "%{name} permite al héroe lanzar hechizos." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" #, fuzzy msgid "Dummy 2" msgstr "Momia" #, fuzzy msgid "The reserved artifact." msgstr " con un artefacto" #, fuzzy msgid "Dummy 3" msgstr "Momia" #, fuzzy msgid "Dummy 4" msgstr "Momia" msgid "Spell Scroll" msgstr "Pegamino del Hechizo" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Este %{name} le da a tu héroe la habilidad de lanzar el hechizo %{spell} si " "el héroe tiene un Libro de Hechizos." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Encuentras una caja labrada que contiene un antiguo rollo de pergamino. Las " "runas de la caja son muy antiguas, y la destreza con la que se elaboró es " "impresionante. Al sacar el pergamino de la caja sientes cómo el poder mágico " "te envuelve." msgid "Arm of the Martyr" msgstr "El Brazo del Martir" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} aumenta el poder de hechizo del héroe en %{count}, pero añade la " "penalización de moral de nomuerto al ejército." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Uno de los miembros menos inteligentes de tu grupo recoge un brazo del " "suelo. A pesar de estar amputado del cuerpo, aún se mueve. Tus tropas " "encuentran el brazo repulsivo, pero no puedes dejarlo: parece que posee " "algún tipo de poder mágico que influye en tu capacidad de decisión." msgid "Breastplate of Anduran" msgstr "El Peto de Anduran" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} aumenta la defensa del héroe en %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Encuentras una señal. En ella se lee: \"Aquí yace el cuerpo de Anduran. " "Inclínate y jura fidelidad, y serás recompensad.\" Decides hacer tal y como " "dice. Al levantarte, sientes frío contra la piel. Al mirar hacia abajo, ves " "que de repente estás llevando una brillante y ornada coraza." msgid "Broach of Shielding" msgstr "El Broche de Protección" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Una amable Hechicera piensa que a las defensas de tu ejército le vendría " "bien un plus mágico. Se ofrece para encantar el Broche de tu capa, y tú " "aceptas." msgid "Battle Garb of Anduran" msgstr "El Traje de Batalla de Anduran" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Al darte pena un pobre campesino, le compras un baúl lleno de viejos " "cachivaches, por el que pedía demasiado dinero. Más tarde, cuando estás " "revisando su contenido, ¡encuentras en su interior las tres piezas del " "legendario traje de combate de Anduran!" msgid "Crystal Ball" msgstr "La Bola de Cristal" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Te encuentras con una caravana de gitanos que están de fiesta, fortaleciendo " "sus cuerpos con hidromiel. Te invitan a unirte a ellos, diciéndote: \"Si " "demuestras que eres capaz de bailar el Rama-Buta, te recompensaremos.\" No " "tienes ni idea, pero aún así lo intentas. Se ríen a carcajadas, pero admiran " "tu coraje, y te regalan una Bola de Cristal." msgid "Heart of Fire" msgstr "El Corazón de Fuego" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Entras en un claro quemado recientemente y te encuentras con un Elemental de " "Fuego, sentado en lo alto de una roca. Éste alza la vista, con la cara " "desfigurada en una mueca de dolor intenso. Entonces te lanza un objeto " "brillante. Te cubres con las manos, pero las atraviesa, y te quema, " "incrustándose en tu pecho." msgid "Heart of Ice" msgstr "El Corazón de Hielo" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" #, fuzzy msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "De repente, un frío aterrador envuelve tu cuerpo. Te agarrotas de tal modo " "que te caes del caballo. El dolor se suaviza lentamente, pero aún tienes la " "sensación de tener el pecho congelado. Al levantarte del suelo, oyes una " "sonora carcajada. Te das la vuelta justo a tiempo para ver a un Gigante de " "Hielo huyendo hacia los bosques hasta desaparecer." msgid "Helmet of Anduran" msgstr "El Casco de Anduran" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Ves un objeto brillante que sobresale del suelo. Envías a un miembro de tu " "grupo a investigar. Regresa con un casco dorado en las manos. Te das cuenta " "de que debe de ser el casco del legendario Anduran, el único hombre que haya " "llevado una armadura de oro macizo." msgid "Holy Hammer" msgstr "El Martillo Sagrado" #, fuzzy msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Te encuentras con una batalla en la que un Paladín ha sido mortalmente " "herido por un grupo de Zombies. Te pide que tomes su martillo y termines lo " "que él empezó. Al tomarlo en tu mano, comienza a zumbar, y todo se convierte " "en un borrón. Los zombies yacen muertos, y el martillo gotea su sangre. Lo " "enganchas a tu cinturón." msgid "Legendary Scepter" msgstr "El Cetro Legendario" msgid "The %{name} adds %{count} points to all attributes." msgstr "" msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Al llegar a lo alto de una pequeña colina, te encuentras con una vista " "ridícula. Un hada está intentando llevar un Cetro que es casi tan grande " "como ella. Intentando no reir, le preguntas \"¿Necesitas ayuda?\". El hada " "te mira y te responde: \"¿Crees que es divertido? Vale. Puedes llevártelo. " "De cualquier modo, prefiero volar.\"" msgid "Masthead" msgstr "El Mástil" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} aumenta la suerte y la moral de las tropas del héroe en %{count} " "cada una en combate marítimo." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Un viejo marinero te cuenta una historia acerca de un \"masthead\" que solía " "usar para arengar a su tripulación en momentos difíciles. Te da entonces un " "mapa borroso que muestra dónde lo escondió. Después de un buen rato " "explorando, lo encuentras escondido debajo de un embarcadero cercano." msgid "Sphere of Negation" msgstr "La Esfera de la Negación" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Te detienes a ayudar a un campesino, que trata de capturar a una yegua " "escapada. En muestra de gratitud, te entrega una esfera diminuta. Tan pronto " "como la coges, sientes la energía mágica fluir de tus miembros..." msgid "Staff of Wizardry" msgstr "El Cayado de Brujería" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} aumenta la potencia de hechizo del héroe en %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Al dejar la caza, asustados, tus tropas encuentran un misterioso bastón " "levitando unos tres pies por encima del suelo. Ellos te lo traen, y notas " "una inscripción en él. Se lee: \"Cerebro mejor que musculo y la magia vence " "a la fuerza. Considera mis palabras, y ganarás todas las batallas\"." msgid "Sword Breaker" msgstr "El Quebranta Espadas" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} aumenta la defensa del héroe en %{count} y el ataque en 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Un Capitán de la Guardia retirado admira tu búsqueda, y te entrega la " "Rompedora de Espadas encantada en la que confiaba durante sus años de " "servicio." msgid "Sword of Anduran" msgstr "La Espada de Anduran" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Un Troll te detiene, diciendo: \"Págame 5,000 de oro, o la Espada de Anduran " "te abatirá donde estás.\" Te niegas. El Troll coge la espada que cuelga de " "su cinturón, chilla de dolor, y huye corriendo. Al recoger la fabulosa " "espada, das gracias por los trolls medio idiotas que tienden a agarrar el " "extremo incorrecto de los objetos afilados." msgid "Spade of Necromancy" msgstr "La Pica de Nigromancia" msgid "The %{name} gives the hero increased necromancy skill." msgstr "" msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Una sucia pala ha sido clavada en un montón de tierra cercano. Tras " "investigarla, descubres que es la pala encantada de los Enterradores, que se " "creía perdida hacía tiempo por los mortales." msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Madera" msgid "Mercury" msgstr "Mercurio" msgid "Ore" msgstr "Hierro" msgid "Sulfur" msgstr "Azufre" msgid "Crystal" msgstr "Cristal" msgid "Gems" msgstr "Gemas" msgid "Gold" msgstr "Oro" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Origina una Bola de Fuego gigante dañándo las criaturas del area " "seleccionada." msgid "Fireball" msgstr "Bola de Fuego" msgid "Fireblast" msgstr "Explosión" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Una versión mejorada de Bola de Fuego, Explosión afecta a dos cuadrados " "alrededor del punto central del Hechizo, en vez de uno." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Hace que un rayo de energía alcance a la criatura seleccionada." msgid "Lightning Bolt" msgstr "Rayo" msgid "Chain Lightning" msgstr "Cadena de Rayos" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Hace que un rayo alcance a la criatura seleccionada, seguidamente alcanza a " "la criatura más cercana causándo la midad de daño, luego alcanza a una " "tercera causando de nuevo la mitad de daño y así sucesivamente hasta que es " "demasiado debil para ser dañino. ADVERTENCIA: Este hechizo puede alcanzar a " "tus propias criaturas!" msgid "Teleport" msgstr "Teletransporte" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Teletransporta la critatura seleccionada a cualquier punto desocupado del " "campo de batalla." msgid "Cure" msgstr "Cura" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Quita todos los hechizos negativos que afecten a tus unidades, y restaura " "hasta %{count} puntos de vida por nivel del hechizo." msgid "Mass Cure" msgstr "Curar en Masas" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" msgid "Resurrect" msgstr "Resurrección" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Devuelve a la vida las criaturas de una unidad dañada o muerta hasta el " "final de combate." msgid "Resurrect True" msgstr "Resurrección Verdadera" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" "Devuelve permanentemente a la vida las unidades de una criatura muerta o " "dañana." msgid "Haste" msgstr "Prisa" msgid "Increases the speed of any creature by %{count}." msgstr "Aumenta la velocidad de cualquier criatura en %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Aumenta la velocidad de todas tus criaturas en %{count}." msgid "Mass Haste" msgstr "Prisa en Masas" msgid "Slows target to half movement rate." msgstr "Ralentiza el objetivo a la mitad del movimiento." msgid "spell|Slow" msgstr "Ralentizar" msgid "Mass Slow" msgstr "Ralentizar en Masas" msgid "Slows all enemies to half movement rate." msgstr "Ralentiza a todos los enemigas a la mitad del movimiento." msgid "spell|Blind" msgstr "Cegar" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Cubre los ojos de la criatura afectada, previniendo que se mueva." msgid "Bless" msgstr "Bendecir" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Hace que las criaturas seleccionadas inflijan daños máximos." msgid "Causes all of your units to inflict maximum damage." msgstr "Hace que todas tus unidades inflijan daños máximos." msgid "Mass Bless" msgstr "Bendición en Masa" msgid "Magically increases the defense skill of the selected creatures." msgstr "" "Magicamente incrementa la habilidad de Defensa de las criaturas " "seleccionadas." msgid "Stoneskin" msgstr "Piel de Roca" msgid "Steelskin" msgstr "Piel de Acero" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Incrementa la habilidad de Defensa de las criaturas seleccionadas. Ésta es " "una versión mejorada de Piel de Roca." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Hace que las criaturas seleccionadas inflijan daños mínimos." msgid "Curse" msgstr "Maldición" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Hace que todas las tropas enemigas inflijan daños mínimos." msgid "Mass Curse" msgstr "Maldición en Masa" msgid "Damages all undead in the battle." msgstr "Daña a todos los nomuertos en combate." msgid "Holy Word" msgstr "Palabra Sagrada" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Daña a todos los nomuertos en la batalla. Es una versión mejorada de la " "Palabra Sagrada." msgid "Holy Shout" msgstr "Grito Sagrado" msgid "Anti-Magic" msgstr "Anti-Magia" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Previene de magia perjudicial contra la criatura seleccionada." msgid "Dispel Magic" msgstr "Disipar" msgid "Removes all magic spells from a single target." msgstr "" "Elimina todos los hechizos mágicos que afectan a la criatura que se " "selecciona." msgid "Mass Dispel" msgstr "Disipar en Masa" msgid "Removes all magic spells from all creatures." msgstr "Elimina todos los hechizos mágicos que afectan a todas las criaturas." msgid "Causes a magic arrow to strike the selected target." msgstr "Hace que una flecha mágica alcance al objetivo seleccionado." msgid "Magic Arrow" msgstr "Flecha Mágica" msgid "Berserker" msgstr "Berserker" msgid "Causes a creature to attack its nearest neighbor." msgstr "Hace que una criatura ataque a su vecino más cercano." msgid "Armageddon" msgstr "Armagedón" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "El terror sagrado ataca el campo de batalla, causando daños severos a todas " "las criaturas." msgid "Elemental Storm" msgstr "Tormenta Elemental" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "Elementos mágicos caen sobre el campo de batalla, dañando a todas las " "criaturas." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Una lluvia de piedras se abate sobre el campo de batalla, dañando a todas " "criaturas cercanas." msgid "Meteor Shower" msgstr "Lluvia de Meteoritos" msgid "Paralyze" msgstr "Paralizar" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "Las criaturas seleccionadas quedan paralizadas y no se pueden mover ni " "contratacar." msgid "Hypnotize" msgstr "Hipnotizar" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" msgid "Cold Ray" msgstr "Rayo Frío" msgid "Drains body heat from a single enemy unit." msgstr "Absorbe el calor del cuerpo de una sola unidad enemiga." msgid "Cold Ring" msgstr "Anillo Frío" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Absorbe el calor del cuerdo de todas las unidades alrededor del punto " "central, pero sin incluir dicho punto." msgid "Disrupting Ray" msgstr "Rayo Pertubador" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Reduce la defensa de una unidad enemiga en 3." msgid "Damages all living (non-undead) units in the battle." msgstr "Daña todas las unidades Vivientes (no Nomuertas) en la batalla." msgid "Death Ripple" msgstr "Onda de la Muerte" msgid "Death Wave" msgstr "Ola de la Muerte" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Daña todas las unidades Vivientes (no Nomuertas) en la batalla. Es una " "versión mejorada de Onda de la Muerte." msgid "Dragon Slayer" msgstr "Matadragones" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Incrementa enormente tu habilidad de ataque contra Dragones." msgid "Blood Lust" msgstr "Ansia de Sangre" msgid "Increases a unit's attack skill." msgstr "Incrementa la habilidad de ataque de una unidad." msgid "Animate Dead" msgstr "Animar Muertos" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "Devuelve permanentemente a la vida las unidades muertas o dañadas de una " "criatura Nomuerta." msgid "Mirror Image" msgstr "Doble Imagen" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Crea una unidad ficticia que duplica a una de tus unidades existentes. Ésta " "causará los mismos daños que la original, pero se esfumará si recibe algún " "daño." msgid "Shield" msgstr "Escudo" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Reduce a la midad los daños recibidos en ataques a distancia por una unidad. " "No afecta al daño recibido de torretas o ballestas." msgid "Mass Shield" msgstr "Escudo en Masa" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Reduce a la midad los daños recibidos en ataques a distancia por todas tus " "unidades. No afecta al daño recibido de torretas o ballestas." msgid "Summon Earth Elemental" msgstr "LLamar al Elemental de la Tierra" msgid "Summons Earth Elementals to fight for your army." msgstr "Llama a los Elementales de la Tierra para luchar en tu ejercito." msgid "Summon Air Elemental" msgstr "LLamar al Elemental del Aire" msgid "Summons Air Elementals to fight for your army." msgstr "LLama a los Elementales del Aire para luchar en tu ejercito." msgid "Summon Fire Elemental" msgstr "LLamar al Elemental del Fuego" msgid "Summons Fire Elementals to fight for your army." msgstr "LLama a los Elementales del Fuego para luchar en tu ejercito." msgid "Summon Water Elemental" msgstr "LLamar al Elemental del Agua" msgid "Summons Water Elementals to fight for your army." msgstr "LLama a los Elementales del Agua para luchar en tu ejercito." msgid "Damages castle walls." msgstr "Daña los muros del castillo." msgid "Earthquake" msgstr "Terremoto" msgid "Causes all mines across the land to become visible." msgstr "Hace que todas las minas del territorio sean visibles." msgid "View Mines" msgstr "Ver Minas" msgid "Causes all resources across the land to become visible." msgstr "Hace que todos los recursos del territorio sean visibles." msgid "View Resources" msgstr "Ver Recursos" msgid "Causes all artifacts across the land to become visible." msgstr "Hace que todos los Artefactos del territorio sean visibles." msgid "View Artifacts" msgstr "Ver Artefactos" msgid "Causes all towns and castles across the land to become visible." msgstr "Hace que todas las ciudades y castillos del territorio sean visibles." msgid "View Towns" msgstr "Ver Ciudades" msgid "Causes all Heroes across the land to become visible." msgstr "Hace que todos los Héroes del territorio sean visibles." msgid "View Heroes" msgstr "Ver Heroes" msgid "Causes the entire land to become visible." msgstr "Hace que todo el territorio sea visible." msgid "View All" msgstr "Ver Todo" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "Permite al lanzador ver información detallada de los héroes enemigos." msgid "Summon Boat" msgstr "LLamar Barco" #, fuzzy msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "LLama a un barco amigo desocupado al punto de costa más cercano. Un barco " "amigo es aquel que has contruido o has sido el último jugador en ocupar." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Permite al lanzador del hechizo ser magicamente transportado a un punto " "cercano." msgid "Dimension Door" msgstr "Puerta Dimensional" msgid "Returns the caster to any town or castle currently owned." msgstr "LLeva al Héroe a cualquier ciudad o castillo que posea." msgid "Town Gate" msgstr "Puerta de la Ciudad" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Devuelve al héroe que lanza este hechizo a cualquier ciudad o castillo, " "siempre que sea controlado por él." msgid "Visions" msgstr "Visiones" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Visiones predice el resultado problable de un encuentro con un ejército " "neutral." msgid "Haunt" msgstr "Encantar" #, fuzzy msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Encanta una mina que controlas con Fantasmas. La mina no podrá producir " "recursos para nadie." msgid "Set Earth Guardian" msgstr "Establecer Guardián de la Tierra" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Ordena a los Elementales de la Tierra que protejan una mina." msgid "Set Air Guardian" msgstr "Establecer Guardián del Aire" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Ordena a los Elementales del Aire que protejan una mina." msgid "Set Fire Guardian" msgstr "Establecer Guardián del Fuego" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Ordenar a los Elementales del Fuego proteger una mina." msgid "Set Water Guardian" msgstr "Establecer Guardián del Agua" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Ordenar que los Elementales del Agua protejan una mina." #, fuzzy msgid "Random Spell" msgstr "Cualquier torre" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "Cualquier castillo" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "Petrificación" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" "No tienes un Libro de Hechizos, por lo que no puedes lanzar un hechizo." msgid "No spell to cast." msgstr "No hay hechizo que lanzar." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Tú héroe tiene todavía %{point} puntos de Maná." msgid "View Adventure Spells" msgstr "Ver Hechizos de Aventura" msgid "View Combat Spells" msgstr "Ver Hechizos de Combate" #, fuzzy msgid "View previous page" msgstr "Ver ciudad anterior" #, fuzzy msgid "View next page" msgstr "Ver %{name}" #, fuzzy msgid "Close Spellbook" msgstr "Lanzar hechizo" msgid "View %{spell}" msgstr "Ver %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Este hechizo hace %{damage} de daño." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Este hechizo llama a\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Este hechizo restaura %{hp} PV." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" msgid "The nearest town is %{town}." msgstr "La ciudad más cercana es %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Esta ciudad está ocupada por el héroe %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" #, fuzzy msgid "The ultimate artifact is really the %{name}." msgstr "¡La maldición de la Momia cae sobre %{name}!" msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" msgid "north-west" msgstr "" #, fuzzy msgid "north" msgstr "Enroth" msgid "north-east" msgstr "" #, fuzzy msgid "west" msgstr "Nido" #, fuzzy msgid "center" msgstr "Monstruo" #, fuzzy msgid "east" msgstr "Nido" msgid "south-west" msgstr "" #, fuzzy msgid "south" msgstr "Ostoroth" msgid "south-east" msgstr "" msgid "The truth is out there." msgstr "" msgid "The dark side is stronger." msgstr "" msgid "The end of the world is near." msgstr "El fin del mundo está cerca." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" msgid "A Black Dragon will take out a Titan any day of the week." msgstr "" msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" msgid "An unknown force is being resurrected..." msgstr "" msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Puedes descargar la última versión del juego desde el sítio:\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Seleccionar cantidad de %{resource}:" #, fuzzy #~ msgid "Enable auto combat" #~ msgstr "Combate automático" #, fuzzy #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "¿Estás seguro de que desea descartar este ejército?" #~ msgid "Please Remember" #~ msgstr "Recuerde" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Siempre puedes cambiar el idioma, la resolución y la configuración del " #~ "juego haciendo clic en la " #~ msgid "door" #~ msgstr "puerta" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr "de la izquierda del menú principal, o con el botón " #~ msgid " button from the " #~ msgstr " del menú " #~ msgid "NEW GAME" #~ msgstr "NUEVO JUEGO" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ ".\n" #~ "\n" #~ "¡Disfruta del juego!" #~ msgid "Warning!" #~ msgstr "¡Advertencia!" #, fuzzy #~ msgid "Dummy 1" #~ msgstr "Momia" fheroes2-1.1.6+dfsg/files/lang/fr.po000066400000000000000000012314321476115357100171650ustar00rootroot00000000000000# French translation for fheroes2 # Copyright (C) 2021 - 2024 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2025-02-11 15:05+0100\n" "Last-Translator: fheroes2 team \n" "Language-Team: French \n" "Language: fr\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-Launchpad-Export-Date: 2010-05-27 09:12+0000\n" "X-Generator: Poedit 3.2.2\n" msgid "" "NEW\n" "GAME" msgstr "" "NOU-\n" "VEAU" msgid "" "SAVE\n" "GAME" msgstr "" "SAUVE-\n" "GARDER" msgid "" "LOAD\n" "GAME" msgstr "" "CHAR-\n" "GER" msgid "INFO" msgstr "INFOS" msgid "QUIT" msgstr "" "QUIT-\n" "TER" msgid "" "NEW\n" "MAP" msgstr "" "NOU-\n" "VELLE" msgid "" "SAVE\n" "MAP" msgstr "" "SAUVE-\n" "GARDER" msgid "" "LOAD\n" "MAP" msgstr "" "CHAR-\n" "GER" msgid "CANCEL" msgstr "ANNULER" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "ACCEPTER" msgid "DECLINE" msgstr "REFUSER" msgid "LEARN" msgstr "OK" msgid "TRADE" msgstr "TROQUER" msgid "YES" msgstr "OUI" msgid "NO" msgstr "NON" msgid "EXIT" msgstr "FIN" msgid "smallerButton|EXIT" msgstr "FIN" msgid "DISMISS" msgstr "RENVOYER" msgid "UPGRADE" msgstr "AMÉLIORER" msgid "RESTART" msgstr "REJOUER" msgid "HEROES" msgstr "HÉROS" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "VIL-\n" "LAGES" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "XL" msgid "ALL" msgstr "TOUT" msgid "SELECT" msgstr "AUTRE" msgid "" "STANDARD\n" "GAME" msgstr "SCÉNARIO" msgid "" "BATTLE\n" "ONLY" msgstr "BATAILLE" msgid "" "CAMPAIGN\n" "GAME" msgstr "CAMPAGNE" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "MODES\n" "MULTI-\n" "JOUEUR" msgid "CONFIG" msgstr "" "PARA-\n" "MÈTRES" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "CAMPAGNE\n" "ORIGINALE" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "SCÉNARIO\n" "DISC" msgid "HOT SEAT" msgstr "" "JOUER À\n" "PLUSIEURS" msgid "2 PLAYERS" msgstr "2 JOUEURS" msgid "3 PLAYERS" msgstr "3 JOUEURS" msgid "4 PLAYERS" msgstr "4 JOUEURS" msgid "5 PLAYERS" msgstr "5 JOUEURS" msgid "6 PLAYERS" msgstr "6 JOUEURS" msgid "GIFT" msgstr "DONNER" msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "DIFFICULTÉ" msgid "VIEW INTRO" msgstr "VOIR INTRO" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "R.A.Z." msgid "START" msgstr "COMMENCER" msgid "TOWN" msgstr "VILLAGE" msgid "CASTLE" msgstr "CHÂTEAU" msgid "RESTRICT" msgstr "LIMITER" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "R\n" "E\n" "N\n" "V\n" "O\n" "Y\n" "E\n" "R" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "Q\n" "U\n" "I\n" "T\n" "T\n" "E\n" "R" # Patrouille is too long. msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "R\n" "A\n" "Y\n" "O\n" "N" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "C\n" "A\n" "M\n" "P\n" "A\n" "G\n" "N\n" "E" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "S\n" "C\n" "É\n" "N\n" "A\n" "R\n" "I\n" "O" msgid "RUMORS" msgstr "RUMEURS" # EVENEMENTS is too long for the UI currently. It overlaps with other buttons. msgid "EVENTS" msgstr "ÉVÉNEMENT" msgid "LANGUAGE" msgstr "LANGUE" msgid "" "AUTO\n" "COMBAT" msgstr "" "COMBAT\n" "AUTOM." msgid "" "QUICK\n" "COMBAT" msgstr "" "COMBAT\n" "RAPIDE" msgid "Warrior" msgstr "Guerrier" msgid "Builder" msgstr "Bâtisseur" msgid "Explorer" msgstr "Voyageur" msgid "None" msgstr "Aucune" msgid "" "A few\n" "%{monster}" msgstr "" "Quelques\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Plusieurs\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Un groupe de\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Une troupe de\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Une horde de \n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Une foule de \n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Une colonie de \n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Une armée de \n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Une légion de\n" "%{monster}" msgid "army|Few" msgstr "1-4" msgid "army|Several" msgstr "5-9" msgid "army|Pack" msgstr "10-19" msgid "army|Lots" msgstr "20-49" msgid "army|Horde" msgstr "50-99" msgid "army|Throng" msgstr "100-249" msgid "army|Swarm" msgstr "250-499" msgid "army|Zounds" msgstr "500-999" msgid "army|Legion" msgstr "1000+" msgid "All %{race} troops +1" msgstr "+1 pour toutes les troupes %{race}" msgid "NeutralRaceTroops|Neutral" msgstr "Neutres" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Troupes de %{count} alignements -%{penalty}" msgid "Some undead in army -1" msgstr "Morts-vivants parmi les troupes -1" msgid "" "Default\n" "troop" msgstr "Troupes par défaut" msgid "View %{name}" msgstr "Voir %{name}" msgid "Move the %{name} " msgstr "Déplacer la troupe de %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Déplacer ou faire un clic droit pour répartir les %{name}" msgid "Combine %{name} armies" msgstr "Fusionner les armées de %{name}" msgid "Exchange %{name2} with %{name}" msgstr "Échanger %{name2} contre %{name}" msgid "Select %{name}" msgstr "Sélectionner %{name}" msgid "Cannot move last troop" msgstr "Impossible de déplacer la dernière armée dans la garnison" msgid "Move the %{name}" msgstr "Déplacer la troupe de %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Tirer sur %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "La troupe de %{name} décime la troupe ennemie !" msgstr[1] "Les %{name} déciment la troupe ennemie !" msgid "%{name} has turned off the auto combat" msgstr "%{name} a désactivé le combat auto" msgid "%{name} has turned on the auto combat" msgstr "%{name} a activé le combat auto" msgid "Spell failed!" msgstr "Sort échoué !" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "L'artéfact Sphère de négation est en vigueur pour cette bataille, " "désactivant tous les sorts de combat." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Vous avez déjà jeté un sort pendant ce tour." msgid "That spell will have no effect!" msgstr "Ce sort n'aura aucun effet !" msgid "You may only summon one type of elemental per combat." msgstr "Vous ne pouvez invoquer qu'un seul type d'élémentaire par combat." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Il n'y a pas d'espace libre adjacent à votre héros pour y invoquer un " "élémentaire." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Le Fossé réduit de -%{count} la caractéristique de défense de n'importe " "quelle créature et ralentit sa capacité de mouvement." msgid "Speed: %{speed}" msgstr "Vitesse : %{speed}" msgid "Speed" msgstr "Vitesse" msgid "Off" msgstr "Désactivé" msgid "On" msgstr "Activé" msgid "Turn Order" msgstr "Ordre de jeu" msgid "Auto Spell Casting" msgstr "Sorts auto" msgid "Grid" msgstr "Grille" msgid "Shadow Movement" msgstr "Ombre de portée" msgid "Shadow Cursor" msgstr "Ombre du curseur" msgid "Audio" msgstr "Audio" msgid "Settings" msgstr "Paramètres" msgid "Configure" msgstr "Configurer" msgid "Hot Keys" msgstr "" "Raccourcis\n" "clavier" msgid "Damage Info" msgstr "Infos sur dégâts" msgid "Set the speed of combat actions and animations." msgstr "Définir la vitesse des actions et animations de combat." msgid "Toggle to display the turn order during the battle." msgstr "" "Activer ou désactiver l'affichage de l'ordre de jeu des créatures pendant le " "combat." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Activer ou désactiver le lancement de sorts pendant le combat automatique. " "(Remarque : cela n'affecte en aucun cas le lancement de sorts pour les héros " "de l'ordinateur, ni le combat rapide.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Activer ou désactiver l'affichage de la grille d'hexagones. Même désactivée, " "le jeu utilise cette grille pour les déplacements et certains sortilèges." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Activer ou désactiver la zone ombragée indiquant où vos créatures peuvent se " "déplacer et attaquer." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Activer ou désactiver l'ombre montrant l'hexagone où est situé le curseur de " "la souris." msgid "Change the audio settings of the game." msgstr "Changer les paramètres du son du jeu." msgid "Check and configure all the hot keys present in the game." msgstr "Vérifier et configurer les raccourcis clavier du jeu." msgid "Toggle to display damage information during the battle." msgstr "" "Basculez pour afficher les informations sur les dégâts pendant la bataille." msgid "Exit this menu." msgstr "Quitter ce menu." msgid "Okay" msgstr "OK" msgid "The enemy has surrendered!" msgstr "L'ennemi s'est rendu !" msgid "Their cowardice costs them %{gold} gold." msgstr "Sa couardise lui coûte %{gold} pièces d'or." msgid "The enemy has fled!" msgstr "L'ennemi a pris la fuite !" msgid "A glorious victory!" msgstr "Une glorieuse victoire !" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Pour sa bravoure au combat, %{name} reçoit %{exp} points d'expérience." msgid "The cowardly %{name} flees from battle." msgstr "%{name} fuit la bataille avec lâcheté." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} se rend à l'ennemi et part, son nom couvert de honte." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Votre armée subit une défaite amère, et %{name} abandonne votre cause." msgid "Your forces suffer a bitter defeat." msgstr "Votre armée subit une défaite amère." msgid "Battlefield Casualties" msgstr "Pertes sur le champ de bataille" msgid "Attacker" msgstr "Attaquant" msgid "Defender" msgstr "Défenseur" msgid "Click to leave the battle results." msgstr "Cliquez pour quitter les résultats de la bataille." msgid "Click to restart the battle in manual mode." msgstr "Cliquez pour relancer la bataille en mode manual." msgid "Restart" msgstr "Recommencer" msgid "You have captured an enemy artifact!" msgstr "Vous vous emparez d'un artéfact ennemi !" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Alors que vous vous approchez %{name}, il disparaît mystérieusement." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Tandis que votre ennemi atteint %{name}, il disparaît mystérieusement." msgid "Necromancy!" msgstr "Nécromancie !" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Pratiquant les arts sombres de la nécromancie, vous êtes capable de réanimer " "%{count} des morts de l'ennemi en tant que %{monster}." msgid "%{name} the %{race}" msgstr "%{name} le %{race}" msgid "Captain of %{name}" msgstr "Capitaine de %{name}" msgid "Attack" msgstr "Attaque" msgid "Defense" msgstr "Défense" msgid "Spell Power" msgstr "Puissance" msgid "Knowledge" msgstr "Connaissance" msgid "Morale" msgstr "Moral" msgid "Luck" msgstr "Chance" msgid "Spell Points" msgstr "Points de magie" msgid "Hero's Options" msgstr "Les options du héros" msgid "Cast Spell" msgstr "Lancer un sort" msgid "Retreat" msgstr "Sonner la retraite" msgid "Surrender" msgstr "Se rendre" msgid "Cancel" msgstr "Annuler" msgid "Hero Screen" msgstr "Fenêtre d'informations du héros" msgid "Captain's Options" msgstr "Options du capitaine" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Lance un sortilège. Vous pouvez seulement en lancer un par tour pendant le " "combat. Le tour se termine lorsque chaque créature a effectué une action." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Retirer votre héros de la bataille en abandonnant vos créatures. Votre héros " "pourra ensuite être recruté de nouveau, mais ne disposera que des forces " "d'un héros novice." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Se rendre prisonnier coûte de l'or. Toutefois, si vous payez la rançon, le " "héros et toutes les créatures survivantes pourront être recrutés de nouveau. " "Le coût de la reddition est égal à la moitié du coût total des troupes non " "temporaires restantes dans l'armée." msgid "Open Hero Screen to view full information about the hero." msgstr "" "Ouvrir la fenêtre d'informations du Héros pour afficher toutes les " "informations sur le héros." msgid "Return to the battle." msgstr "Retourner à la bataille." msgid "Not enough gold (%{gold})" msgstr "Pas assez d'or (%{gold})" msgid "%{name} states:" msgstr "%{name} déclare :" msgid "Captain of %{name} states:" msgstr "Capitaine de %{name} :" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\" J'accepterai votre reddition et vous accorderai, à vous et à vos troupes, " "un passage sûr pour le prix de %{price} pièces d'or. \"" msgid "View %{monster} info" msgstr "Voir les infos de %{monster}" msgid "Fly %{monster} here" msgstr "Faire voler %{monster} ici" msgid "Move %{monster} here" msgstr "Déplacer %{monster} ici" msgid "Shoot %{monster}" msgstr "Tirer sur %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 tir restant)" msgstr[1] "(%{count} tirs restants)" msgid "Attack %{monster}" msgstr "Attaquer %{monster}" msgid "Turn %{turn}" msgstr "Tour %{turn}" msgid "Teleport here" msgstr "Téléporter ici" msgid "Invalid teleport destination" msgstr "Destination de téléportation invalide" msgid "Cast %{spell} on %{monster}" msgstr "Lancer %{spell} sur %{monster}" msgid "Cast %{spell}" msgstr "Lancer %{spell}" msgid "Select spell target" msgstr "Sélectionner la cible du sort" msgid "View Ballista info" msgstr "Voir les infos de la baliste" msgid "Ballista" msgstr "Baliste" msgid "Automatic combat modes" msgstr "Modes de combat automatique" msgid "Automatic Combat Modes" msgstr "Modes de combat automatique" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" "Choisissez entre lancer le combat en mode combat automatique ou en mode " "combat rapide." msgid "Customize system options" msgstr "Modifier les options système" msgid "Allows you to customize the combat screen." msgstr "Modifier les options de l'écran de combat." msgid "System Options" msgstr "Options du système" msgid "Skip this unit" msgstr "Passer ce peloton" msgid "Skip" msgstr "Passer" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Le peloton actif passe son tour et ne peut pas jouer avant le prochain tour." msgid "View Captain's options" msgstr "Voir les options du capitaine" msgid "View Hero's options" msgstr "Voir les options du héros" msgid "View opposing Captain" msgstr "Voir le capitaine adverse" msgid "View opposing Hero" msgstr "Voir le héros adverse" msgid "Hide logs" msgstr "Cacher le journal" msgid "Show logs" msgstr "Afficher le journal" msgid "Message Bar" msgstr "Barre d'informations" msgid "Shows the results of individual monster's actions." msgstr "" "Affiche le déroulement du combat et indique toutes les actions individuelles." msgid "Are you sure you want to enable the auto combat mode?" msgstr "Êtes-vous sûr de vouloir désactiver le mode combat automatique ?" msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Êtes-vous sûr de vouloir résoudre le combat en mode combat rapide ?" msgid "The computer continues the combat for you." msgstr "L'ordinateur joue le combat à votre place." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" "Ceci peut être interrompu à tout moment en appuyant sur le raccourci du mode " "combat automatique ou la touche Annuler ou en cliquant gauche ou droite avec " "votre souris n'importe où sur l'écran de jeu." msgid "Auto Combat" msgstr "Combat Auto" msgid "The combat is resolved from the current state." msgstr "Le combat sera résolu à partir de la situation actuelle." msgid "quickCombat|This cannot be undone." msgstr "Cela ne peut pas être modifié." msgid "Quick Combat" msgstr "Combat rapide" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} passe son tour." msgstr[1] "%{name} passent leur tour." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} inflige %{damage} dégâts." msgstr[1] "Les %{attacker} infligent %{damage} dégâts." # if only 1 monster: "... inflige ..." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 créature périt." msgstr[1] "%{count} créatures périssent." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} périt." msgstr[1] "%{count} %{defender} périssent." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 âme est incorporée." msgstr[1] "%{count} âmes sont incorporées." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} a été réanimé." msgstr[1] "%{count} %{unit} ont été réanimés." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Déplacement %{monster} : de [%{src}] à [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "Le %{name} résiste au sort !" msgstr[1] "Les %{name} résistent au sort !" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} lance %{spell} sur les %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} lance %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} inflige %{damage} dégâts à un mort-vivant." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} inflige %{damage} dégâts à tous les morts-vivants." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} inflige %{damage} dégâts, %{count} créatures meurent." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} inflige %{damage} dégâts." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} inflige %{damage} dégâts à une créature vivante." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} inflige %{damage} dégâts à toutes les créatures vivantes." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "L'attaque de la %{attacker} aveugle le peloton de %{target} !" msgstr[1] "L'attaque des %{attacker} aveugle le peloton de %{target} !" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "" "Le regard de la %{attacker} transforme le peloton de %{target} en pierre !" msgstr[1] "" "Le regard des %{attacker} transforme le peloton de %{target} en pierre !" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "" "La malédiction de la %{attacker} s'abat sur le peloton de %{target} !" msgstr[1] "La malédiction des %{attacker} s'abat sur le peloton de %{target} !" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "" "La troupe de %{target} est paralysée par le peloton de %{attacker} !" msgstr[1] "" "La troupe de %{target} est paralysée par le peloton de %{attacker} !" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" "Le %{attacker} dissipe tous les sorts bénéfiques sur le peloton de " "%{target} !" msgstr[1] "" "Les %{attacker} dissipent tous les sorts bénéfiques sur le peloton de " "%{target} !" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "Le %{attacker} lance %{spell} sur le peloton de %{target} !" msgstr[1] "Les %{attacker} lancent %{spell} sur le peloton de %{target} !" msgid "Bad luck descends on the %{attacker}." msgstr "La malchance s'abat sur les %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "La chance sourit aux %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Un moral élevé permet aux %{monster} d'attaquer à nouveau." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Un faible moral paralyse les %{monster}." msgid "%{tower} does %{damage} damage." msgstr "%{tower} fait %{damage} dégât(s)." msgid "The mirror image is created." msgstr "L'image miroir est créée." msgid "The mirror image is destroyed!" msgstr "L'image miroir est détruite !" msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Êtes-vous sûr de vouloir interrompre le mode combat automatique ?" msgid "Error" msgstr "Erreur" msgid "No spells to cast." msgstr "Aucun sort disponible." msgid "Are you sure you want to retreat?" msgstr "Voulez-vous vraiment sonner la retraite ?" msgid "Retreat disabled" msgstr "Retraite impossible" msgid "Surrender disabled" msgstr "Reddition impossible" msgid "Damage: %{max}" msgstr "Dégâts : %{max}" msgid "Damage: %{min} - %{max}" msgstr "Dégâts : %{min} - %{max}" msgid "Perish: %{max}" msgstr "Perte : %{max}" msgid "Perish: %{min} - %{max}" msgstr "Perte : %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "En observant de son oeil d'aigle, %{name} a pu apprendre le sortilège " "%{spell}." msgid "Human" msgstr "Humain" msgid "AI" msgstr "IA" msgid "Start" msgstr "Commencer" msgid "Start the battle." msgstr "Commencer la bataille." msgid "Exit" msgstr "Quitter" msgid "Reset" msgstr "Remise à zéro" msgid "Reset to default settings." msgstr "Réinitialiser les paramétres par défaut." msgid "Please select another hero." msgstr "Veuillez choisir un autre héros." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} vs. %{race2} %{name2}" msgid "Monsters" msgstr "Monstres" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Tourelle gauche" msgid "Right Turret" msgstr "Tourelle droite" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "La %{name} tire avec la force de %{count} archers" msgid "each with a +%{attack} bonus to their attack skill." msgstr "chacun avec un bonus de +%{attack} à leur caractéristique d'attaque." msgid "The %{name} is destroyed." msgstr "La %{name} est détruite." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} revient à la vie !" msgstr[1] "%{count} %{name} reviennent à la vie !" msgid "Dwarven Alliance" msgstr "Alliance des nains" msgid "Sorceress Guild" msgstr "Guilde des sorcières" msgid "Necromancer Guild" msgstr "Guilde des nécromanciens" msgid "Ogre Alliance" msgstr "Alliance des ogres" msgid "Dwarfbane" msgstr "Fléau des nains" msgid "Dragon Alliance" msgstr "Alliance des dragons" msgid "Elven Alliance" msgstr "Alliance des elfes" msgid "Kraeger defeated" msgstr "Kraeger vaincu" msgid "Wayward Son" msgstr "Fils dévoyé" msgid "Uncle Ivan" msgstr "Oncle Ivan" msgid "Annexation" msgstr "Annexion" msgid "Force of Arms" msgstr "Force des armes" msgid "Save the Dwarves" msgstr "Sauve les nains" msgid "Carator Mines" msgstr "Mines de Carator" msgid "Turning Point" msgstr "Moment décisif" msgid "scenarioName|Defender" msgstr "Défenseur" msgid "Corlagon's Defense" msgstr "Défense de Corlagon" msgid "The Crown" msgstr "La couronne" msgid "The Gauntlet" msgstr "Le gantelet" msgid "Betrayal" msgstr "Trahison" msgid "Final Justice" msgstr "Justice définitive" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland a besoin de vous pour vaincre les seigneurs près de son château afin " "de commencer sa guerre de rébellion contre son frère. Ces seigneurs ne sont " "pas alliés, et ils s'affronteront donc entre eux. La victoire vous reviendra " "lorsque vous aurez vaincu tous les châteaux et héros ennemis." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Les seigneurs locaux refusent de prêter allégeance à Roland et doivent être\n" "matés. Ils sont riches et puissants, alors préparez-vous à un combat " "difficile. Capturez tous les châteaux ennemis pour gagner." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Votre tâche est de défendre les Nains contre les forces d'Archibald. " "Capturez tous les villages et tous les châteaux ennemis pour gagner, et " "veillez à ne pas perdre tous les villages nains d'un coup, ou l'ennemi aura " "gagné." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Vous affronterez quatre ennemis alliés dans une lutte directe pour les " "ressources et les trésors. Capturez tous les châteaux ennemis pour remporter " "la victoire." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Vos ennemis sont alliés contre vous et commencent tout près, alors soyez " "prêt à vous battre. Vous devrez posséder les quatre châteaux de cette petite " "vallée pour gagner." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "La guilde des sorcières de Noraston a demandé l'aide de Roland contre une " "attaque des alliés d'Archibald. Capturez tous les châteaux ennemis pour " "gagner, et ne perdez pas Noraston, ou vous perdrez le scénario. (Indice : il " "y a un château ennemi sur une île dans l'océan)." msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Rassemblez une armée aussi grande que possible et capturez le château ennemi " "en 8 semaines. Vous n'affronterez qu'un seul ennemi, mais vous devez " "parcourir un long chemin pour atteindre le château ennemi. Toutes les " "troupes que vous avez dans votre armée à la fin de ce scénario seront avec " "vous lors de la bataille finale." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Trouvez la couronne avant que les héros d'Archibald ne la trouvent. Roland " "aura besoin de la couronne pour la bataille finale contre Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Trois ennemis alliés se dressent devant vous et la victoire, y compris Lord " "Corlagon. Roland se trouve dans un château au nord-ouest, et vous perdrez " "s'il tombe aux mains de l'ennemi. N'oubliez pas que si vous capturez Lord " "Corlagon, il ne se battra pas contre vous dans le scénario final." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "C'est la bataille finale. Vous et votre ennemi êtes armés jusqu'aux dents, " "et tous sont alliés contre vous. Capturez Archibald pour mettre fin à la " "guerre !" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Changer de camp vous laisse avec trois châteaux contre un seul pour " "l'ennemi. Cette bataille sera la plus facile que vous aurez à mener jusqu'à " "la fin de la guerre... traître." msgid "Barbarian Wars" msgstr "Guerres barbares" msgid "First Blood" msgstr "Premier sang" msgid "Necromancers" msgstr "Nécromanciens" msgid "Slay the Dwarves" msgstr "Massacre des nains" msgid "Country Lords" msgstr "Seigneurs du pays" msgid "Dragon Master" msgstr "Maître des dragons" msgid "Rebellion" msgstr "Rébellion" msgid "Apocalypse" msgstr "Apocalypse" msgid "Greater Glory" msgstr "Grande gloire" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Le roi Archibald vous demande de vaincre les trois ennemis de cette région. " "Ils ne sont pas alliés les uns aux autres, ils dépenseront donc la majeure " "partie de leur énergie à se battre entre eux. Vous gagnerez lorsque vous " "posséderez tous les châteaux ennemis et qu'il ne restera plus de héros à " "combattre." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Vous devez unifier les tribus barbares du nord en les conquérant. Comme dans " "la mission précédente, les ennemis ne sont pas alliés contre vous, mais ils " "ont plus de ressources à leur disposition. Vous gagnerez lorsque vous " "posséderez tous les châteaux ennemis et qu'il n'y aura plus de héros à " "combattre." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Des sorciers bienfaisants ont pris le château des nécromanciens. Reprenez-le " "pour remporter la victoire. Rappelez-vous que si vous commencez avec une " "puissante armée, vous n'avez pas de château et devez en prendre un dans les " "7 jours, ou vous perdrez cette bataille. (Indice : le château le plus proche " "est au sud-est)." msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Les nains doivent être conquis avant de pouvoir interférer dans les plans du " "roi Archibald. Les forces de Roland ont plus d'un héros et de nombreux " "villages au départ, alors soyez prêt à être attaqué de plusieurs directions. " "Vous devez capturer tous les villages et tous les châteaux ennemis pour " "remporter la victoire." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Vous devez réprimer une révolte paysanne menée par les forces de Roland. " "Tous sont alliés contre vous, mais vous avez Lord Corlagon, un héros " "expérimenté, pour vous aider. Capturez tous les châteaux ennemis pour gagner." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Il y a deux ennemis alliés contre vous dans cette mission. Tous deux sont " "bien armés et cherchent à vous expulser de leur île. Évitez-les et capturez " "la cité des dragons pour gagner." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Vos ordres sont de conquérir les seigneurs du pays qui ont juré de servir " "Roland. Tous les châteaux ennemis sont unis contre vous. Comme vous " "commencez sans château, vous devez vous dépêcher d'en capturer un avant la " "fin de la semaine. Capturez tous les châteaux ennemis pour remporter la " "victoire." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Trouvez la couronne avant que les héros de Roland ne la trouvent. Archibald " "aura besoin de la couronne pour la bataille finale contre Roland." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "C'est la bataille finale. Vous et votre ennemi êtes tous deux armés " "jusqu'aux dents, et tous sont alliés contre vous. Capturez Roland pour " "gagner la guerre, et assurez-vous de ne pas perdre Archibald dans le combat !" msgid "Arrow's Flight" msgstr "Vol de la flèche" msgid "Island of Chaos" msgstr "L'île du chaos" msgid "The Abyss" msgstr "L'abîme" msgid "Uprising" msgstr "Révolte" msgid "Aurora Borealis" msgstr "Aurore boréale" msgid "Betrayal's End" msgstr "Fin de la trahison" msgid "Corruption's Heart" msgstr "Coeur de la corruption" msgid "The Giant's Pass" msgstr "Col des géants" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Soumettez les seigneurs locaux indisciplinés afin de fournir à l'empire des " "installations pour opérer dans cette région." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Éliminez tous les opposants dans cette zone. Ensuite, la première pièce de " "l'artéfact sera à vous." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Les sorcières du nord-est se rebellent ! Pour le bien de l'empire, vous " "devez réprimer leur faible soulèvement en vous rendant dans les montagnes." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Ayant préparé votre arrivée, Kraeger a mis en place une force de " "nécromanciens pour contrecarrer votre quête. Vous devez capturer le château " "de Scabsdale avant le premier jour de la troisième semaine, ou les " "nécromanciens seront trop forts pour vous." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Le despote barbare de cette région ignore pour l'instant votre présence. " "Vite, renforcez vos forces avant d'être découvert et attaqué ! Sécurisez la " "région en soumettant toutes les forces ennemies." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "L'Empire est faible dans cette région. Vous ne pourrez pas soumettre " "complètement toutes les forces dans cette zone, alors prenez ce que vous " "pouvez avant que les représailles ne frappent. Rappelez-vous, votre " "véritable objectif est de revendiquer le casque d'Anduran." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Pour le bien de l'Empire, éliminez Kraeger." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Vous avez enfin l'occasion et les moyens de débarrasser l'empire du mal des " "nécromanciens. Éradiquez-les complètement, et on chantera vos louanges pour " "l'éternité." msgid "Border Towns" msgstr "Villes frontalières" msgid "Conquer and Unify" msgstr "Conquérir et unifier" msgid "Crazy Uncle Ivan" msgstr "Oncle Fou Ivan" msgid "The Wayward Son" msgstr "Le Fils dévoyé" msgid "Ivory Gates" msgstr "Portes d'ivoire" msgid "The Elven Lands" msgstr "Les Terres elfiques" msgid "The Epic Battle" msgstr "Le combat épique" msgid "The Southern War" msgstr "La guerre du sud" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Conquérez et unissez toutes les tribus ennemies. Ne perdez pas le héros " "Jarkonas, l'ancêtre de tous les descendants." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Votre rival, le Royaume d'Harondale, attaque des villages faibles à votre " "frontière ! Remettez-vous de leur première frappe et écrasez-les " "complètement !" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Trouvez votre fils Joseph qui, selon la rumeur, vit dans les terres " "désolées. Faites-le avant le premier jour du troisième mois ou il ne sera " "d'aucune aide pour votre famille." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Sauvez votre oncle fou Ivan. Trouvez-le avant le premier jour du quatrième " "mois ou il ne sera d'aucune aide pour votre royaume." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Détruisez les barbares qui attaquent la frontière sud de votre royaume ! " "Récupérez vos villages perdus, puis envahissez le royaume de la jungle. Ne " "laissez aucun ennemi debout." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "" "Reprenez le château des portes d'ivoire, qui est tombé à la suite d'une " "trahison." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Gagnez la faveur des elfes. Ils ne permettront pas aux arbres d'être coupés, " "nous vous enverrons donc du bois toutes les 2 semaines. Vous devez terminer " "votre mission avant le premier jour du septième mois, sinon le royaume va " "sûrement s'effondrer." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "C'est la bataille finale contre votre rival, le royaume de Harondale. " "Éliminez tout le monde et ne perdez pas le héros Jarkonas VI." msgid "Fount of Wizardry" msgstr "Source de magie" msgid "Power's End" msgstr "Fin du pouvoir" msgid "The Eternal Scrolls" msgstr "Les parchemins éternels" msgid "The Shrouded Isles" msgstr "Les îles du linceul" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Votre mission est de vaincre les mages en guerre dans les îles magiques du " "linceul. L'achèvement de cette tâche vous donnera une chance de vous battre " "contre vos rivaux." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "L'emplacement de la grande bibliothèque a été découverte ! Vous devez vous y " "rendre, et reconquérir le village de Chronos dans lequel elle se trouve." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Trouvez l'orbe de la négation, qui serait enterré dans ce pays. Il y a des " "indices inscrits sur les obélisques en pierre qui vous aideront à vous " "conduire à votre prix. Trouvez l'orbe avant le premier jour du sixième mois, " "ou vos rivaux seront sûrement arrivés à la source avant vous." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Vous devez prendre le contrôle du château de la magie, où se trouve la " "source de magie. Faites-le et votre victoire sera suprême." msgid "Blood is Thicker" msgstr "Sang épais" msgid "King and Country" msgstr "Roi et pays" msgid "Pirate Isles" msgstr "Iles pirates" msgid "Stranded" msgstr "Échoué" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Capturez le village sur l'île au large de la côte sud-est afin de construire " "un bateau et de retourner vers le continent. Ne perdez pas le héros " "Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Trouvez et battez Martine, la chef des pirates, qui réside à Pirates Cove. " "Ne perdez pas Gallavant ou votre quête sera terminée." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Éliminez toutes les autres forces qui résistent au joug de lord Alberon. " "Gallavant ne doit pas mourir." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Renversez la monarchie enracinée de lord Alberon et revendiquez toutes les " "terres en votre nom. Gallavant ne doit pas mourir." msgid " bane" msgstr " fléau" msgid " alliance" msgstr " alliance" msgid "Carry-over forces" msgstr "Renforts" msgid " bonus" msgstr " bonus" msgid " defeated" msgstr " vaincu" msgid " will always run away from your army." msgstr " fuiront toujours face à votre armée." msgid " will be willing to join your army." msgstr " voudront toujours se joindre à votre armée." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "L'artéfact \"%{artifact}\" sera conservé dans le scénario suivant." msgid "The army will be carried over in the campaign." msgstr "Les renforts rejoindront vos rangs dans le scénario final." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" "Le royaume obtiendra +%{count} ressources supplémentaires en %{resource} " "chaque jour." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "Le sort \"%{spell}\" sera conservé dans le scénario suivant." msgid "%{hero} can be hired during scenarios." msgstr "Le héros %{hero} peut être recruté dans ce scénario." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "Le héros vaincu %{hero} n'apparaîtra pas dans les scénarios suivants." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Les nains reconnaissent leurs alliés et se joignent volontiers à vos forces." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Les ogres vous reconnaissent comme le fléau des nains et vous rallient." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Les dragons, en grognant, acceptent d'unir leurs forces avec vous, leur " "\"allié\"." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Alors que vous vous approchez du groupe d'elfes, leur chef les appelle tous " "au garde-à-vous. Il leur crie : \"Qui d'entre vous est assez courageux pour " "joindre notre allié intrépide ?\" Le groupe explose d'acclamations en " "courant pour rejoindre vos rangs." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Les nains vous saluent, \"Tous les amis de Roland sont nos amis. Vous pouvez " "passer.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Les ogres poussent un grognement de reconnaissance à votre encontre, \"Les " "alliés d'Archibald peuvent passer\"." msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Les dragons vous voient et crient. \"Notre alliance avec Archibald nous " "oblige à nous joindre à vous. Malheureusement, vous n'avez pas de place. " "C'est dommage !\" Ils se dispersent rapidement." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Les elfes se tiennent au garde-à-vous à votre approche. Leur chef vous " "appelle et dit : \"N'entravons pas votre progression, allié ! Avancez, et " "que la victoire soit vôtre.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Le fléau des nains !!!!, sauve qui peut.\"" msgid "campaignBonus|Animate Dead" msgstr "Mort-vivant" msgid "campaignBonus|Chain Lightning" msgstr "Foudre" msgid "campaignBonus|Fireblast" msgstr "Souffle de feu" msgid "campaignBonus|Mass Curse" msgstr "Malédiction massive" msgid "campaignBonus|Mass Haste" msgstr "Célérité de masse" msgid "campaignBonus|Mirror Image" msgstr "Image miroir" msgid "campaignBonus|Resurrect" msgstr "Résurrection" msgid "campaignBonus|Steelskin" msgstr "Chair d'acier" msgid "campaignBonus|Summon Earth" msgstr "Invoquer la terre" msgid "campaignBonus|View Heroes" msgstr "Voir héros" msgid "campaignBonus|Ballista" msgstr "Baliste" msgid "campaignBonus|Black Pearl" msgstr "Perle noire" msgid "campaignBonus|Caster's Bracelet" msgstr "Bracelet magique" msgid "campaignBonus|Defender Helm" msgstr "Casque défenseur" msgid "campaignBonus|Breastplate" msgstr "Plastron divin" msgid "campaignBonus|Dragon Sword" msgstr "Épée du dragon" msgid "campaignBonus|Fizbin Medal" msgstr "Médaille Fizbin" msgid "campaignBonus|Foremost Scroll" msgstr "Parchemin ultime" msgid "campaignBonus|Gauntlets" msgstr "Gantelets" msgid "campaignBonus|Hideous Mask" msgstr "Masque sinistre" msgid "campaignBonus|Mage's Ring" msgstr "Anneau du magicien" msgid "campaignBonus|Major Scroll" msgstr "Parchemin majeur" msgid "campaignBonus|Medal of Honor" msgstr "Médaille d'honneur" msgid "campaignBonus|Medal of Valor" msgstr "Médaille de bravoure" msgid "campaignBonus|Minor Scroll" msgstr "Parchemin mineur" msgid "campaignBonus|Nomad Boots" msgstr "Bottes de nomade" msgid "campaignBonus|Power Axe" msgstr "Puissante hache" msgid "campaignBonus|Spiked Shield" msgstr "Bouclier à pointes" msgid "campaignBonus|Stealth Shield" msgstr "Bouclier furtif" msgid "campaignBonus|Tax Lien" msgstr "Privilège fiscal" msgid "campaignBonus|Thunder Mace" msgstr "Marteau de foudre" msgid "campaignBonus|Traveler's Boots" msgstr "Bottes de sept lieues" msgid "campaignBonus|White Pearl" msgstr "Perle blanche" msgid "campaignBonus|Basic Archery" msgstr "Principes d'archerie" msgid "campaignBonus|Advanced Archery" msgstr "Archerie avancée" msgid "campaignBonus|Expert Archery" msgstr "Expert en archerie" msgid "campaignBonus|Basic Ballistics" msgstr "Principes de balistique" msgid "campaignBonus|Advanced Ballistics" msgstr "Balistique avancée" msgid "campaignBonus|Expert Ballistics" msgstr "Expert en balistique" msgid "campaignBonus|Basic Diplomacy" msgstr "Principes de diplomatie" msgid "campaignBonus|Advanced Diplomacy" msgstr "Diplomatie avancée" msgid "campaignBonus|Expert Diplomacy" msgstr "Expert en diplomatie" msgid "campaignBonus|Basic Eagle Eye" msgstr "Principes d'oeil d'aigle" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Oeil d'aigle avancé" msgid "campaignBonus|Expert Eagle Eye" msgstr "Expert en oeil d'aigle" msgid "campaignBonus|Basic Estates" msgstr "Principes de finances" msgid "campaignBonus|Advanced Estates" msgstr "Finances avancées" msgid "campaignBonus|Expert Estates" msgstr "Expert en finances" msgid "campaignBonus|Basic Leadership" msgstr "Principes de charisme" msgid "campaignBonus|Advanced Leadership" msgstr "Charisme avancé" msgid "campaignBonus|Expert Leadership" msgstr "Expert en charisme" msgid "campaignBonus|Basic Logistics" msgstr "Principes de logistique" msgid "campaignBonus|Advanced Logistics" msgstr "Logistique avancée" msgid "campaignBonus|Expert Logistics" msgstr "Expert en logistique" msgid "campaignBonus|Basic Luck" msgstr "Principes de chance" msgid "campaignBonus|Advanced Luck" msgstr "Chance avancée" msgid "campaignBonus|Expert Luck" msgstr "Expert en chance" msgid "campaignBonus|Basic Mysticism" msgstr "Principes de mysticisme" msgid "campaignBonus|Advanced Mysticism" msgstr "Mysticisme avancé" msgid "campaignBonus|Expert Mysticism" msgstr "Expert en mysticisme" msgid "campaignBonus|Basic Navigation" msgstr "Principes de navigation" msgid "campaignBonus|Advanced Navigation" msgstr "Navigation avancée" msgid "campaignBonus|Expert Navigation" msgstr "Expert en navigation" msgid "campaignBonus|Basic Necromancy" msgstr "Principes de nécromancie" msgid "campaignBonus|Advanced Necromancy" msgstr "Nécromancie avancée" msgid "campaignBonus|Expert Necromancy" msgstr "Expert en nécromancie" msgid "campaignBonus|Basic Pathfinding" msgstr "Principes d'orientation" msgid "campaignBonus|Advanced Pathfinding" msgstr "Orientation avancée" msgid "campaignBonus|Expert Pathfinding" msgstr "Expert en orientation" msgid "campaignBonus|Basic Scouting" msgstr "Principes de reconnaissance" msgid "campaignBonus|Advanced Scouting" msgstr "Reconnaissance avancée" msgid "campaignBonus|Expert Scouting" msgstr "Expert en reconnaissance" msgid "campaignBonus|Basic Wisdom" msgstr "Principes de sagesse" msgid "campaignBonus|Advanced Wisdom" msgstr "Sagesse avancée" msgid "campaignBonus|Expert Wisdom" msgstr "Expert en sagesse" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" "Le héros principal recevra l'artéfact \"%{artifact}\" au début du scénario." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Le royaume bénéficiera de %{amount} %{resource} supplémentaire(s) au début " "du scénario." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Le royaume aura %{amount} ressource(s) en %{resource} en moins au début du " "scénario." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Le héros principal recevra %{count} %{monster} au début du scénario." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "Le héros principal recevra le sort \"%{spell}\" au début du scénario." msgid "The starting alignment of the scenario will be %{race}." msgstr "La faction de départ sur ce scénario sera %{race}." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "Le héros principal recevra %{count} %{skill} supplémentaire(s) au début du " "scénario." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Le héros principal recevra %{skill} au début du scénario." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" msgid "Price of Loyalty" msgstr "Price of Loyalty" msgid "Voyage Home" msgstr "Le retour" msgid "Wizard's Isle" msgstr "L'archipel" msgid "Descendants" msgstr "Les héritiers" msgid "Cannot build. You have already built here today." msgstr "Construction impossible. Une construction a déjà eu lieu aujourd'hui." msgid "For this action it is necessary to build a castle first." msgstr "Pour effectuer cette action il faut d'abord construire un château." msgid "The %{building} produces %{monster}." msgstr "Le %{building} produit des %{monster}." msgid "Requires:" msgstr "Nécessite :" msgid "Exit this menu without doing anything." msgstr "Sortir de ce menu sans modification." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Impossible de construire %{name} - le château est trop loin de l'eau." msgid "This building has been disabled." msgstr "La construction de ce bâtiment est désactivée pour ce château." msgid "Cannot afford the %{name}." msgstr "Impossible d'acheter %{name}." msgid "The %{name} is already built." msgstr "%{name} est déjà construit(e)." msgid "Cannot build the %{name}." msgstr "Impossible de construire %{name}." msgid "Build %{name}." msgstr "Construire %{name}." msgid "Blackridge" msgstr "Blackridge" msgid "Hillstone" msgstr "Hillstone" msgid "Pinehurst" msgstr "Pinehurst" msgid "Whiteshield" msgstr "Whiteshield" msgid "Woodhaven" msgstr "Woodhaven" msgid "Blackwind" msgstr "Blackwind" msgid "Bloodreign" msgstr "Bloodreign" msgid "Dragontooth" msgstr "Dragontooth" msgid "Greywind" msgstr "Greywind" msgid "Portsmith" msgstr "Portsmith" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Middle Gate" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "Baywatch" msgid "Fountainhead" msgstr "Fountainhead" msgid "Vertigo" msgstr "Vertigo" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Winterkill" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Lakeside" msgid "Nightshadow" msgstr "Nightshadow" msgid "Olympus" msgstr "Olympus" msgid "Sandcaster" msgstr "Sandcaster" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "New Dawn" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Big Oak" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antioch" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Roc Haven" msgid "South Mill" msgstr "South Mill" msgid "Weed Patch" msgstr "Weed Patch" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Hilltop" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Westfork" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "Elk's Head" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Blackburn" msgid "Blacksford" msgstr "Blacksford" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Pig's Eye" msgid "Viper's Nest" msgstr "Viper's Nest" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Timberhill" msgid "Troy" msgstr "Troy" msgid "Forder Oaks" msgstr "Forder Oaks" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Quick Silver" msgid "Westmoor" msgstr "Westmoor" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Impossible de recruter - vous avez déjà un héros dans ce village." msgid "Cannot recruit - you have too many Heroes." msgstr "Impossible de recruter - vous avez trop de héros." msgid "Cannot afford a Hero." msgstr "Pas assez d'or pour recruter un héros." msgid "There is no room in the garrison for this army." msgstr "Il n'y a pas de place dans la garnison pour cette armée." msgid "Fortifications" msgstr "Fortifications" msgid "Farm" msgstr "Ferme" msgid "Thatched Hut" msgstr "Grange" msgid "Archery Range" msgstr "Archerie" msgid "Upg. Archery Range" msgstr "Archerie renforcée" msgid "Blacksmith" msgstr "Forge" msgid "Upg. Blacksmith" msgstr "Forge renforcée" msgid "Armory" msgstr "Armurerie" msgid "Upg. Armory" msgstr "Armurerie renforcée" msgid "Jousting Arena" msgstr "Arène" msgid "Upg. Jousting Arena" msgstr "Arène améliorée" msgid "Cathedral" msgstr "Cathédrale" msgid "Upg. Cathedral" msgstr "Basilique" msgid "Coliseum" msgstr "Colisée" msgid "Garbage Heap" msgstr "Tas d'ordures" msgid "Hut" msgstr "Paillote" msgid "Stick Hut" msgstr "Hutte" msgid "Upg. Stick Hut" msgstr "Hutte renforcée" msgid "Den" msgstr "Tanière" msgid "Adobe" msgstr "Cahute" msgid "Upg. Adobe" msgstr "Cahute renforcée" msgid "Bridge" msgstr "Pont" msgid "Upg. Bridge" msgstr "Pont renforcé" msgid "Pyramid" msgstr "Pyramide" msgid "Rainbow" msgstr "Arc-en-ciel" msgid "Crystal Garden" msgstr "Jardin de cristaux" msgid "Treehouse" msgstr "Cabane" msgid "Cottage" msgstr "Cottage" msgid "Upg. Cottage" msgstr "Cottage renforcé" msgid "Stonehenge" msgstr "Cromlech" msgid "Upg. Stonehenge" msgstr "Grand cromlech" msgid "Fenced Meadow" msgstr "Pré" msgid "sorceress|Red Tower" msgstr "Tour rouge" msgid "Dungeon" msgstr "Donjon" msgid "Waterfall" msgstr "Cascades" msgid "Cave" msgstr "Grotte" msgid "Crypt" msgstr "Crypte" msgid "Nest" msgstr "Nid" msgid "Maze" msgstr "Labyrinthe" msgid "Upg. Maze" msgstr "Grand labyrinthe" msgid "Swamp" msgstr "Marais" msgid "Green Tower" msgstr "Tour verte" msgid "warlock|Red Tower" msgstr "Tour rouge" msgid "Black Tower" msgstr "Tour noire" msgid "Library" msgstr "Bibliothèque" msgid "Orchard" msgstr "Verger" msgid "Habitat" msgstr "Repaire" msgid "Pen" msgstr "Enclos" msgid "Foundry" msgstr "Fonderie" msgid "Upg. Foundry" msgstr "Fonderie renforcée" msgid "Cliff Nest" msgstr "Nid perché" msgid "Ivory Tower" msgstr "Tour d'ivoire" msgid "Upg. Ivory Tower" msgstr "Haute tour d'ivoire" msgid "Cloud Castle" msgstr "Château céleste" msgid "Upg. Cloud Castle" msgstr "Grand château céleste" msgid "Storm" msgstr "Tempête" msgid "Skull Pile" msgstr "Crânes empilés" msgid "Excavation" msgstr "Fouille" msgid "Graveyard" msgstr "Cimetière" msgid "Upg. Graveyard" msgstr "Grand cimetière" msgid "Upg. Pyramid" msgstr "Grande pyramide" msgid "Mansion" msgstr "Manoir" msgid "Upg. Mansion" msgstr "Grand manoir" msgid "Mausoleum" msgstr "Mausolée" msgid "Upg. Mausoleum" msgstr "Grand mausolée" msgid "Laboratory" msgstr "Laboratoire" msgid "Shrine" msgstr "Autel des ténèbres" #, fuzzy msgid "Special" msgstr "Rien de spécial" msgid "Horde Building" msgstr "" msgid "Dwelling 1" msgstr "Demeure 1" msgid "Dwelling 2" msgstr "Demeure 2" msgid "Upg. Dwelling 2" msgstr "Demeure 2 renforcée" msgid "Dwelling 3" msgstr "Demeure 3" msgid "Upg. Dwelling 3" msgstr "Demeure 3 renforcée" msgid "Dwelling 4" msgstr "Demeure 4" msgid "Upg. Dwelling 4" msgstr "Demeure 4 renforcée" msgid "Dwelling 5" msgstr "Demeure 5" msgid "Upg. Dwelling 5" msgstr "Demeure 5 renforcée" msgid "Dwelling 6" msgstr "Demeure 6" msgid "Upg. Dwelling 6" msgstr "Demeure 6 renforcée" msgid "2x Upg. Dwelling 6" msgstr "Demeure 6 ren. 2x" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Les fortifications augmentent la résistance des murs, augmentant le nombre " "de tours nécessaires pour les détruire." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "La ferme augmente la production de paysans de %{count} par semaine." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Le Colisée fournit des spectacles motivants aux troupes en défense, " "augmentant leur moral de deux pendant le combat." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" "Le Tas d'ordures augmente la production de gobelins de %{count} par semaine." msgid "The Rainbow increases the luck of the defending units by two." msgstr "L'arc-en-ciel augmente de deux la chance des créatures en défense." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" "Le jardin de cristaux augmente la production de fées de %{count} par semaine." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "" "Le donjon augmente les revenus du village de %{count} pièces d'or par jour." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" "Les cascades augmentent la production de centaures de %{count} par semaine." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "La bibliothèque rajoute 1 sort à chaque niveau de la guilde des magiciens." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Le verger augmente la production de galopins de %{count} par semaine." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" "La tempête ajoute +2 à la Puissance des sorts du héros qui défend lors d'un " "siège." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" "Les crânes empilés augmentent la production de squelettes de %{count} par " "semaine." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Le puits augmente le taux de croissance de population de %{count} créatures " "par semaine dans chaque demeure." msgid "Thieves' Guild" msgstr "Guilde des voleurs" msgid "Tavern" msgstr "Taverne" msgid "Shipyard" msgstr "Ponton" msgid "Well" msgstr "Puits" msgid "Statue" msgstr "Statue" msgid "Marketplace" msgstr "Place du marché" msgid "Moat" msgstr "Fossé" msgid "Castle" msgstr "Château" msgid "Tent" msgstr "Tente" msgid "Captain's Quarters" msgstr "Quartiers du capitaine" msgid "Mage Guild, Level 1" msgstr "Guilde des M. niv. 1" msgid "Mage Guild, Level 2" msgstr "Guilde des M. niv. 2" msgid "Mage Guild, Level 3" msgstr "Guilde des M. niv. 3" msgid "Mage Guild, Level 4" msgstr "Guilde des M. niv. 4" msgid "Mage Guild, Level 5" msgstr "Guilde des M. niv. 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "L'Autel des ténèbres augmente la puissance de nécromancie de tous les " "nécromanciens de 10 pour cent." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "La Guilde des voleurs fournit des informations sur les joueurs ennemis. Les " "guildes de voleurs vous informent également sur les villages ennemis en vue. " "Plus de guildes donnent des informations plus précises." msgid "The Tavern increases morale for troops defending the castle." msgstr "La taverne augmente le moral des défenseurs du château." msgid "The Shipyard allows ships to be built." msgstr "Le ponton permet la construction de navires." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Le puits augmente le taux de croissance de population de %{count} créatures " "par semaine dans chaque demeure." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "" "La statue augmente les revenus du village de %{count} pièces d'or par jour." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "La tourelle gauche fournit une puissance de feu supplémentaire lorsque le " "château est assiégé." msgid "The Right Turret provides extra firepower during castle combat." msgstr "" "La tourelle droite fournit une puissance de feu supplémentaire lorsque le " "château est assiégé." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "La place du marché peut être utilisée pour convertir un type de ressource en " "un autre. Plus vous contrôlez de places de marchés, plus le taux de change " "est favorable." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Le fossé ralentit les attaques des ennemis. Chaque créature qui tente de " "franchir le fossé perd son tour et devient plus vulnérable aux attaques." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Le château améliore la défense du village et augmente ses revenus totaux à " "%{count} pièces d'or par jour." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "La tente permet aux travailleurs de construire un château, si les matériaux " "et l'or sont disponibles." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Les quartiers du capitaine permettent au capitaine d'assurer une aide à la " "défense du château lorsque aucun héros n'est présent." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "La guilde des magiciens permet aux héros d'apprendre des sortilèges et de " "restaurer leurs points de magie." msgid "Recruit %{name}" msgstr "Recruter %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Mois : %{month}, Semaine : %{week}, Jour : %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Vous devez acheter un grimoire pour utiliser la guilde des magiciens, mais " "vous n'avez actuellement pas de place pour un grimoire. Essayez de donner un " "de vos artéfacts à un autre héros." msgid "Click to show next town." msgstr "Cliquez pour afficher le village suivant." msgid "Show next town" msgstr "Montrer le village suivant" msgid "Click to show previous town." msgstr "Cliquez pour afficher le village précédent." msgid "Show previous town" msgstr "Montrer le village précédent" msgid "This town may not be upgraded to a castle." msgstr "Ce village ne peut pas être amélioré en château." msgid "Town" msgstr "Village" msgid "Exit Castle" msgstr "Quitter le château" msgid "Exit Town" msgstr "Quitter le village" msgid "Show Income" msgstr "Afficher le revenu" msgid "View Hero" msgstr "Voir le héros" msgid "The above spells are available here." msgstr "Les sorts ci-dessus sont disponibles." msgid "The spells the hero can learn have been added to their book." msgstr "Les sorts que le héros peut apprendre ont été ajoutés au grimoire." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Le tavernier fait courir la rumeur suivante :" msgid "Recruit Hero" msgstr "Recruter un héros" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} est un %{race} de niveau %{value} " msgid "with %{count} artifacts." msgstr "avec %{count} artéfacts." msgid "with 1 artifact." msgstr "avec un artéfact." msgid "without artifacts." msgstr "sans artéfact." msgid "Recruit %{name} the %{race}" msgstr "Recrutement de %{name} le %{race}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "La formation de combat 'dispersée' propage les troupes du château du haut " "vers le bas du champ de bataille, avec au moins un espace vide entre chaque " "troupe." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "La formation de combat 'groupée' regroupe les troupes du château au centre " "du champ de bataille, à l'intérieur du château." msgid "Spread Formation" msgstr "Formation dispersée" msgid "Grouped Formation" msgstr "Formation groupée" msgid "Click to show the next town." msgstr "Cliquez pour afficher le village suivant." msgid "Click to show the previous town." msgstr "Cliquez pour afficher le village précédent." msgid "Set garrison combat formation to 'Spread'" msgstr "Utiliser la formation de combat 'dispersée' pour la garnison" msgid "Set garrison combat formation to 'Grouped'" msgstr "Utiliser la formation de combat 'groupée' pour la garnison" msgid "Exit Castle Options" msgstr "Quitter les options du château" msgid "Castle Options" msgstr "Options du château" msgid "Not enough resources to recruit creatures." msgstr "Pas assez de ressources pour recruter des créatures." msgid "You are unable to recruit at this time, your ranks are full." msgstr "" "Vous n'êtes pas en mesure de recruter pour le moment. Vos rangs sont pleins." msgid "No creatures available for purchase." msgstr "Pas de créatures disponibles à l'achat." msgid "Recruit Creatures" msgstr "Recruter des créatures" msgid "Hire all creatures in the town." msgstr "Recruter toutes les créatures disponibles dans le village." msgid "Max" msgstr "Max" msgid "Available" msgstr "Disponible" msgid "Town Population Information and Statistics" msgstr "Informations et statistiques sur la population du village" msgid "Damage" msgstr "Dégâts" msgid "HP" msgstr "PV" msgid "Growth" msgstr "Croissance" msgid "week" msgstr "semaine" msgid "View World" msgstr "Tout voir" msgid "View the entire world." msgstr "Voir le monde entier." msgid "Puzzle" msgstr "Puzzle" msgid "View the obelisk puzzle." msgstr "Voir le puzzle de l'obélisque." msgid "Scenario Information" msgstr "Informations sur le scénario" msgid "View information on the scenario you are currently playing." msgstr "Voir les informations du scénario de la partie actuelle." msgid "Dig for the Ultimate Artifact." msgstr "Creuser pour l'ultime artéfact." msgid "Digging" msgstr "Fouille" msgid "Arena" msgstr "Arène" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Vous entrez dans l'arène et vous vous retrouvez face à un groupe de lions " "féroces. Vous vous débarrassez facilement d'eux, sous les applaudissements " "déchaînés de la foule. Impressionné par votre talent, l'entraîneur des " "gladiateurs vous propose d'entraîner le talent de votre choix." msgid "Attack Skill" msgstr "Attaque" msgid "Defense Skill" msgstr "Défense" msgid "Shots" msgstr "Tirs" msgid "Shots Left" msgstr "Tirs restants" msgid "Hit Points" msgstr "Points de vie" msgid "Hit Points Left" msgstr "PV restants" msgid "You can't afford to upgrade your troops!" msgstr "Vous n'avez pas les moyens d'améliorer vos troupes !" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Vos troupes peuvent être améliorées, mais cela vous coûtera cher. Souhaitez-" "vous les améliorer ?" msgid "Are you sure you want to dismiss this army?" msgstr "Voulez-vous vraiment renvoyer cette troupe ?" msgid "Upgrade" msgstr "Améliorer" msgid "Upgrade your troops." msgstr "Améliorer vos troupes." msgid "Dismiss" msgstr "Renvoyer" msgid "Dismiss this army." msgstr "Ronvoyer cette armée." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Un groupe de %{monster} désirant de plus grandes gloires souhaite vous " "rallier.\n" "Acceptez-vous ?" msgid "Followers" msgstr "Alliés" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "Le %{monster} est influencé par votre discours diplomatique, et propose de " "rallier votre armée pour la somme de %{gold} pièces d'or.\n" "Acceptez-vous ?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Les créatures sont charmées par votre habileté\n" "diplomatique, et vous propose ceci :\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} des %{total} %{monster} rallieront votre armée, et le reste vous " "laissera tranquille, pour la somme de %{gold} pièces d'or.\n" "Acceptez-vous ?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Tous les %{offer} de la %{monster} rallieront votre armée pour la somme de " "%{gold} pièces d'or.\n" "Acceptez-vous ?" msgid "(Rate: %{percent})" msgstr "(Taux : %{percent})" msgid "off" msgstr "coupé" msgid "Music" msgstr "Musique" msgid "Effects" msgstr "Effets" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Expansion" msgid "External" msgstr "Externe" msgid "Music Type" msgstr "Musique" msgid "3D Audio" msgstr "Audio 3D" msgid "Toggle ambient music level." msgstr "Change le volume de la musique." msgid "Toggle foreground sounds level." msgstr "Change le volume des effets sonores." msgid "Change the type of music." msgstr "Change de type de musique." msgid "Toggle the 3D effect of foreground sounds." msgstr "Basculer les effets 3D des sons au premier plan." msgid "Build a new ship:" msgstr "Construire un nouveau navire :" msgid "Resource cost:" msgstr "Coût en ressources :" msgid "Total: " msgstr "Total : " msgid "Need: " msgstr "Besoin : " msgid "New Game" msgstr "Nouvelle partie" msgid "Start a single or multi-player game." msgstr "Démarrer un jeu solo ou multijoueur." msgid "Load Game" msgstr "Charger une partie" msgid "Load a previously saved game." msgstr "Charger une partie sauvegardée." msgid "Save Game" msgstr "Enregistrer" msgid "Save the current game." msgstr "Enregistrer le jeu en cours." msgid "Quit" msgstr "Quitter" msgid "Quit out of Heroes of Might and Magic II." msgstr "Quittez Heroes of Might and Magic II." msgid "Language" msgstr "Langue" msgid "Graphics" msgstr "" "Paramètres\n" "d'affichage" msgid "Black & White" msgstr "Noir et blanc" msgid "Mouse Cursor" msgstr "Curseur" msgid "Color" msgstr "Couleur" msgid "Text Support" msgstr "Mode texte" msgid "Change the language of the game." msgstr "Changer la langue du jeu." msgid "Select Game Language" msgstr "Choix de la langue" msgid "Change the graphics settings of the game." msgstr "Changer les paramètres d'affichage." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" "Basculer le curseur en couleur. Il ne s'agit que d'un choix esthétique." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Activer le mode texte pour afficher des informations supplémentaires sur les " "différentes fenêtres et les événements du jeu." msgid "" "Map\n" "Difficulty" msgstr "" "Difficulté\n" "de la carte" msgid "" "Game\n" "Difficulty" msgstr "" "Difficulté\n" "du jeu" msgid "Rating" msgstr "Taux" msgid "Map Size" msgstr "" "Taille de\n" "la carte" msgid "Opponents" msgstr "Adversaires" msgid "Class" msgstr "Alignement" msgid "" "Victory\n" "Conditions" msgstr "" "Conditions\n" "de victoire" msgid "" "Loss\n" "Conditions" msgstr "" "Conditions\n" "de défaite" msgid "First select recipients!" msgstr "Sélectionnez d'abord les destinataires !" msgid "You cannot select %{resource}!" msgstr "Vous ne pouvez pas sélectionner %{resource} !" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Tirer sur %{monster}" msgid "Select Recipients" msgstr "Sélectionner les destinataires" msgid "Your Funds" msgstr "Vos fonds" msgid "Planned Gift" msgstr "Don planifié" msgid "Gift from %{name}" msgstr "Don de la part de %{name}" msgid "Resolution" msgstr "Résolution" msgid "Fullscreen" msgstr "Plein écran" msgid "window|Mode" msgstr "Mode" msgid "Windowed" msgstr "Fenêtré" msgid "V-Sync" msgstr "V-sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "" "Information\n" "système" msgid "Change the resolution of the game." msgstr "Changer la résolution du jeu." msgid "Select Game Resolution" msgstr "Choisir la résolution d'écran" msgid "Toggle between fullscreen and windowed modes." msgstr "Basculez entre les modes plein écran et fenêtré." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "L'option V-Sync peut être activée pour résoudre les problèmes de " "scintillement sur certains moniteurs." msgid "Show extra information such as FPS and current time." msgstr "" "Afficher des informations supplémentaires telles que le FPS et l'heure " "actuelle." msgid "Hotkey: " msgstr "Raccourci clavier : " msgid "Category: " msgstr "Catégorie : " msgid "Event: " msgstr "Événement : " msgid "Hot Keys:" msgstr "Raccourcis clavier :" msgid "Hide" msgstr "Libre" msgid "Show" msgstr "Attachée" msgid "Interface" msgstr "Interface" msgid "Interface Type" msgstr "Interface" msgid "Toggle the type of interface you want to use." msgstr "Bascule le type d'interface que vous voulez utiliser." msgid "Toggle interface visibility." msgstr "Visibilité d'interface." msgid "Scroll Speed" msgstr "Défilement" msgid "Sets the speed at which you scroll the window." msgstr "Définit la vitesse à laquelle vous faites défiler la fenêtre." msgid "Select Game Language:" msgstr "Choix de la langue :" msgid "Select Language:" msgstr "Choix de la langue :" msgid "Click to choose the selected language." msgstr "Cliquez pour valider la langue choisie." msgid "%{name} has gained a level." msgstr "%{name} a gagné un niveau." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Vous avez appris %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} a gagné un niveau.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Vous pouvez apprendre :\n" "%{skill1}\n" "ou\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/a" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Regardez nos belles marchandises. Si vous souhaitez faire affaire, cliquez " "sur les objets que vous souhaitez échanger." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Vous avez fait une bonne affaire. Je ne compte pas faire de profit sur cette " "affaire. Puis-je vous proposer d'autres de mes produits ?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Je peux vous offrir %{count} pour une unité de %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" "Je peux vous offrir 1 unité de %{resto} pour %{count} unités de %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Qté à échanger" msgid "Trading Post" msgstr "Comptoir" msgid "Your Resources" msgstr "Vos ressources" msgid "Available Trades" msgstr "Échanges possibles" # artifact is guarded by? (=gardé). A mine is guarded by? (=gardée). Ruins are guarded by? (=gardées). msgid "guarded by %{count} %{monster}" msgstr "gardé par %{count} %{monster}" msgid "guarded by " msgstr "gardée par " # same "gardé/e/s problem as above. msgid "(available: %{count})" msgstr "(disponible : %{count})" msgid "(empty)" msgstr "(vide)" msgid "already learned" msgstr "déjà appris" msgid "treeOfKnowledge|free" msgstr "gratuit" msgid "already claimed" msgstr "XP déjà acquise" msgid "not claimed" msgstr "XP disponible" msgid "already knows this skill" msgstr "connaît déjà cette compétence" msgid "already has max skills" msgstr "a déjà le nombre maximum de compétences" msgid "(already visited)" msgstr "(déjà visité)" msgid "(not visited)" msgstr "(non visité)" msgid "%{color} Barrier" msgstr "Barrière magique %{color}" msgid "(tent visited)" msgstr "(tente visitée)" msgid "%{color} Tent" msgstr "Tente %{color}" msgid "Road" msgstr "Route" msgid "(digging ok)" msgstr "(fouille possible)" msgid "(no digging)" msgstr "(fouille impossible)" msgid "penalty: %{cost}" msgstr "pénalité : %{cost}" msgid "Defenders:" msgstr "Défenseurs :" msgid "Unknown" msgstr "Inconnu" msgid "heroQuickInfo|(Level %{level})" msgstr "(niveau %{level})" msgid "Attack:" msgstr "Attaque :" msgid "Defense:" msgstr "Défense :" msgid "Spell Power:" msgstr "Puissance :" msgid "Knowledge:" msgstr "Connaissance :" msgid "Spell Points:" msgstr "Pts. de magie :" msgid "Move Points:" msgstr "Mouvement :" msgid "Uncharted Territory" msgstr "Terra Incognita" msgid "Cost per troop:" msgstr "Coût par troupe :" msgid "Available: %{count}" msgstr "Disponible : %{count}" msgid "Number to buy:" msgstr "Recruter :" msgid "Recruit selected monsters." msgstr "Recruter les forces sélectionnées." msgid "Select maximum monsters to be recruited." msgstr "Sélectionnez les forces maximales à recruter." msgid "Select only 1 monster to be recruited." msgstr "Ne sélectionnez qu'une seule unité à recruter." msgid "Select this game resolution." msgstr "Choisissez cette résolution d'écran." msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Choisir la résolution d'écran:" msgid "Click to apply the selected resolution." msgstr "Cliquez pour valider la résolution choisie." msgid "Click to apply the entered text." msgstr "Cliquez pour valider le texte." msgid "Click to open the Virtual Keyboard dialog." msgstr "Cliquez pour ouvrir la fenêtre du clavier virtuel." msgid "Open Virtual Keyboard" msgstr "Open Virtual Keyboard" msgid "How many creatures do you wish to move?" msgstr "Combien de créatures voulez-vous déplacer ? " msgid "Select how many units to separate into:" msgstr "Sélectionnez le nombre d'unités que vous voulez séparer :" msgid "Map: " msgstr "Carte : " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "Mois : " msgid ", Week: " msgstr ", Semaine : " msgid ", Day: " msgstr ", Jour : " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Emplacement : " msgid "Are you sure you want to delete file:" msgstr "Voulez-vous vraiment effacer le fichier :" msgid "Warning" msgstr "Attention" msgid "Click to save the current game." msgstr "Enregistrer le jeu en cours." msgid "Click to load a previously saved game." msgstr "Charger une partie sauvegardée." msgid "File to Save:" msgstr "Fichier à sauvegarder :" msgid "File to Load:" msgstr "Fichier à charger :" msgid "Terrain object" msgstr "Objets généraux" msgid "Accept the choice made." msgstr "Confirmez le choix." msgid "Select Skill:" msgstr "Choisir compétence :" msgid "Select Spell:" msgstr "Choisir sort :" msgid "Select Artifact:" msgstr "Choisir artéfact :" msgid "Select Monster:" msgstr "Choisir créature :" msgid "Select Hero:" msgstr "Choisir héros :" msgid "race|Random" msgstr "Aléatoire" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Cliquez pour commencer le placement du village/château sélectionné." msgid "%{color} %{race}" msgstr "%{race} %{color}" msgid "You will place" msgstr "Vous avez choisi de placer" msgid "Click to select this class." msgstr "Cliquez ici pour sélectionner cet alignement." msgid "Click to select this color." msgstr "Cliquez ici pour sélectionner cette couleur." msgid "Select Treasure:" msgstr "Choix du trésor :" msgid "Select Ocean Object:" msgstr "Choix d'élément (océan) :" msgid "Castle/town placing" msgstr "Choix du village à placer" msgid "doubleLinedRace|Neutral" msgstr "Neutre" msgid "Click to start placing the selected castle/town." msgstr "Cliquez pour commencer le placement du village/château sélectionné." msgid "Click to select town placing." msgstr "Cliquez pour sélectionner le village." msgid "Click to select castle placing." msgstr "Cliquez pour sélectionner le château." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{townOrCastle} %{race} %{color}" msgid "race|Neutral" msgstr "Neutre" msgid "Select Dwelling:" msgstr "Séléctionner demeure :" msgid "Select Landscape Object:" msgstr "Choix d'élément (paysage) :" msgid "Mine placing" msgstr "Choix de la mine à placer" msgid "" "Resource\n" "type:" msgstr "" "Type de\n" "ressource :" msgid "%{mineName} appearance:" msgstr "Aspect de %{mineName} :" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" "Cliquez ici pour sélectionner %{object} comme générateur de ressources à " "placer." msgid "Select Mountain Object:" msgstr "Choix d'élément (montagnes) :" msgid "Select Rock Object:" msgstr "Choix d'élément (rochers) :" msgid "Select Tree Object:" msgstr "Choix d'élément (arbres) :" msgid "Select Power Up Object:" msgstr "Choix d'élément (bonus) :" msgid "Select Adventure Object:" msgstr "Choix d'élément (aventure) :" msgid "Players Icon" msgstr "Icônes des joueurs" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Indique combien de joueurs au total sont dans le scenario. Toute position " "non occupée par un humain sera occupée par l'ordinateur." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Indique si la carte est\n" "petite (36x36), moyenne\n" "(72x72), grande (108x108)\n" "ou très grande (144x144)." msgid "Size Icon" msgstr "Taille de l'icône" msgid "Map Type" msgstr "Type de carte" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Indique si la carte est faite pour la version du jeu \"The Succession " "Wars\", \"The Price of Loyalty\" ou \"Resurrection\"." msgid "Map Type:\n" msgstr "Type de carte :\n" msgid "The Succession Wars" msgstr "The Succession Wars" msgid "The Price of Loyalty" msgstr "Le prix de la loyauté" msgid "Resurrection" msgstr "Résurrection" msgid "" "\n" "\n" "Language:\n" msgstr "" "\n" "\n" "Langue:\n" msgid "Lose all your heroes and towns." msgstr "Perdre tous les héros et tous les villages." msgid "Lose a specific town." msgstr "Perdre un village spécifique." msgid "Lose a specific hero." msgstr "Perdre un héros spécifique." msgid "Run out of time. Fail to win by a certain point." msgstr "Manquer de temps. Ne pas gagner avant un certain point." msgid "Loss Condition" msgstr "Conditions de défaite" msgid "Defeat all enemy heroes and towns." msgstr "Vaincre tous les héros et villages ennemis." msgid "Capture a specific town." msgstr "Capturer un village spécifique." msgid "Defeat a specific hero." msgstr "Vaincre un héros spécifique." msgid "Find a specific artifact." msgstr "Trouver un artéfact spécifique." msgid "Your side must defeat the opposing side." msgstr "Vaincre le camp adverse." msgid "Accumulate a large amount of gold." msgstr "Accumuler une grande quantité d'or." msgid "Victory Condition" msgstr "Conditions de victoire" msgid "Map difficulty:" msgstr "Difficulté de la carte :" msgid "N" msgstr "P" msgid "No maps exist at that size." msgstr "Aucune carte de cette taille n'existe." msgid "Small Maps" msgstr "Petites cartes" msgid "View only maps of size small (36 x 36)." msgstr "Voir seulement les petites cartes (36x36)." msgid "Medium Maps" msgstr "Cartes moyennes" msgid "View only maps of size medium (72 x 72)." msgstr "Voir seulement les cartes de taille moyenne (72x72)." msgid "Large Maps" msgstr "Grandes cartes" msgid "View only maps of size large (108 x 108)." msgstr "Voir seulement les grandes cartes (108x108)." msgid "Extra Large Maps" msgstr "Très grandes cartes" msgid "View only maps of size extra large (144 x 144)." msgstr "Voir seulement les très grandes cartes (144x144)." msgid "All Maps" msgstr "Toutes les cartes" msgid "View all maps, regardless of size." msgstr "Voir toutes les cartes, sans tenir compte de leur taille." msgid "Selected Name" msgstr "Carte sélectionnée" msgid "The name of the currently selected map." msgstr "Le nom de la carte actuellement sélectionnée." msgid "Selected Map Difficulty" msgstr "Difficulté de la carte choisie" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Difficulté de la carte actuellement sélectionnée. La difficulté de la carte " "est déterminée par le concepteur du scénario. Les cartes plus difficiles " "peuvent inclure des ennemis plus nombreux ou plus forts, moins de ressources " "ou d'autres conditions spéciales rendant les choses plus difficiles pour le " "joueur humain." msgid "Selected Description" msgstr "Description sélectionnée" msgid "The description of the currently selected map." msgstr "La description de la carte actuellement sélectionnée." msgid "Jump" msgstr "Immédiat" msgid "Hero Speed" msgstr "Vitesse" msgid "Don't Show" msgstr "Masquer" msgid "Enemy Speed" msgstr "Vitesse IA" msgid "Auto Resolve" msgstr "Combat auto" msgid "Auto, No Spells" msgstr "Auto sans magie" msgid "Battles" msgstr "Batailles" msgid "combatMode|Manual" msgstr "Manuelles" msgid "Change the speed at which your heroes move on the main screen." msgstr "" "Change la vitesse à laquelle vos héros se déplacent sur l'écran principal." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Définit la vitesse à laquelle les héros CPU se déplacent. Vous pouvez " "également choisir de ne pas voir du tout le mouvement des CPU." msgid "Change the interface settings of the game." msgstr "Modifier les paramètres de l'interface du jeu." msgid "Interface Settings" msgstr "Paramètres de l'interface" msgid "Toggle instant battle mode." msgstr "Change les modes de combat instantané." msgid "Att." msgstr "Att." msgid "Def." msgstr "Déf." msgid "Power" msgstr "Puiss." msgid "Knowl" msgstr "Conn." msgid "1st" msgstr "1er" msgid "2nd" msgstr "2ème" msgid "3rd" msgstr "3ème" msgid "4th" msgstr "4ème" msgid "5th" msgstr "5ème" msgid "6th" msgstr "6ème" msgid "Oracle: Player Rankings" msgstr "Oracle : Classement des joueurs" msgid "Thieves' Guild: Player Rankings" msgstr "Guilde des voleurs : Classement des joueurs" msgid "Number of Towns:" msgstr "Nombre de villages :" msgid "Number of Castles:" msgstr "Nombre de châteaux :" msgid "Number of Heroes:" msgstr "Nombre de héros :" msgid "Gold in Treasury:" msgstr "Or dans la trésorerie :" msgid "Wood & Ore:" msgstr "Bois et fer :" msgid "Gems, Cr, Slf & Mer:" msgstr "Gemmes, Cr, Sfr & Mer :" msgid "Obelisks Found:" msgstr "Obélisques trouvés :" msgid "Artifacts:" msgstr "Artéfacts :" msgid "Total Army Strength:" msgstr "Force totale de l'armée :" msgid "Income:" msgstr "Rentrées d'argent :" msgid "Best Hero:" msgstr "Meilleur héros :" msgid "Best Hero Stats:" msgstr "Stats du meilleur héros :" msgid "Personality:" msgstr "Personnalité :" msgid "Best Monster:" msgstr "Meilleure créature :" msgid "Random Castle Name" msgstr "Nom du château aléatoire" msgid "Random Town Name" msgstr "Nom du village aléatoire" #, fuzzy msgid "Allow Castle build" msgstr "Château céleste" #, fuzzy msgid "Default Buildings" msgstr "Actions par défaut" #, fuzzy msgid "Default Army" msgstr "Actions par défaut" #, fuzzy msgid "Castle Army" msgstr "Château" #, fuzzy msgid "Town Army" msgstr "Village" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Perdre le héros : %{name}." msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Barre d'informations" msgid "Reward:" msgstr "Récompense :" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Barre d'informations" #, fuzzy msgid "Click to save the Event properties." msgstr "Enregistrer le jeu en cours." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "Ressource" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Enregistrer le jeu en cours." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Jour : %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Enregistrer le jeu en cours." #, fuzzy msgid "Add Event" msgstr "Événement" #, fuzzy msgid "Add an additional event." msgstr "Programmation supplémentaire" #, fuzzy msgid "Edit Event" msgstr "Événement" #, fuzzy msgid "Edit an existing event." msgstr "Charger une carte existante." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "Charger une carte existante." #, fuzzy msgid "Effects:" msgstr "Effets" #, fuzzy msgid "Conditions:" msgstr "" "Conditions\n" "de défaite" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "Expérience" msgid "Artifact" msgstr "Artéfact" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Choisir artéfact :" #, fuzzy msgid "Delete an artifact from the event." msgstr "Charger une carte existante." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Choisir compétence :" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Les rochers ne peuvent pas être placés sur l'eau." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Les artéfacts ne peuvent pas être placés sur l'eau." #, fuzzy msgid "%{objects} must be placed on water." msgstr "Les éléments liés à la mer doivent être placés sur l'eau." msgid "Objects cannot be placed outside the map." msgstr "Les élements ne peuvent pas être placés en dehors de la carte." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Les éléments liés à la mer doivent être placés sur l'eau." # Needs line break to have insectile space but keep partie and ? together. #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Voulez-vous vraiment créer une nouvelle carte ? (Toutes les modifications " "non enregistrées seront perdues.)" msgid "Editor" msgstr "Éditeur" # Needs line break to have insectile space but keep partie and ? together. msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Voulez-vous vraiment charger une carte ? (Toutes les modifications non " "enregistrées seront perdues.)" # Needs line break to have insectile space but keep partie and ? together. msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Voulez-vous vraiment créer une nouvelle carte ? (Toutes les modifications " "non enregistrées seront perdues.)" msgid "" "MAIN\n" "MENU" msgstr "" "MENU\n" "PRINCI." msgid "" "START\n" "MAP" msgstr "LANCER" msgid "Main Menu" msgstr "Menu principal" # Needs line break to have insectile space but keep partie and ? together. #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Voulez-vous vraiment créer une nouvelle carte ? (Toutes les modifications " "non enregistrées seront perdues.)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" msgid "Start Map" msgstr "Lancer carte" # Needs line break to have insectile space but keep partie and ? together. #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Voulez-vous vraiment charger une carte ? (Toutes les modifications non " "enregistrées seront perdues.)" #, fuzzy msgid "Create a new map from scratch." msgstr "Carte vierge" msgid "New Map" msgstr "Nouvelle carte" msgid "Load Map" msgstr "Charger une carte" msgid "Load an existing map." msgstr "Charger une carte existante." msgid "Save Map" msgstr "Sauvegarder la carte" msgid "Save the current map." msgstr "Sauvegarder la carte actuelle." msgid "Quit out of the map editor." msgstr "Quitter l'éditeur de carte." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Cliquez pour revenir au menu principal." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Ultime artéfact aléatoire" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "avec un artéfact." msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "Routes" msgid "Streams" msgstr "Rivières" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" "Un maximum de %{count} héros de la même couleur peuvent être placés sur la " "carte." msgid "Failed to update player information." msgstr "La mise à jour des informations sur les joueurs a échoué." #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Les artéfacts ne peuvent pas être placés sur l'eau." #, fuzzy msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" "Un maximum de %{count} héros de la même couleur peuvent être placés sur la " "carte." #, fuzzy msgid "The map is corrupted." msgstr "Le fichier de sauvegarde est corrompu." msgid "Unable to locate data directory to save the map." msgstr "" #, fuzzy msgid "Unable to create a directory to save the map." msgstr "Permet d'effacer les éléments placés sur la carte." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Permet d'effacer les éléments placés sur la carte." #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Voulez-vous vraiment remplacer la sauvegarde avec ce nom ?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "Fichier à sauvegarder :" msgid "Used to place %{object}." msgstr "Permet de placer %{object}." msgid "Select object type" msgstr "Choix d'élément" msgid "" "Click here to\n" "select a monster." msgstr "" "Cliquez ici pour\n" "sélectionner une créature." msgid "" "Click here to\n" "select another monster." msgstr "" "Cliquez ici pour\n" "sélectionner un autre créature." msgid "" "Cell\n" "Details" msgstr "" "Details\n" "cellule" msgid "Erase" msgstr "Effacer" msgid "Mountains" msgstr "Montagnes" msgid "Rocks" msgstr "Rochers" msgid "Trees" msgstr "Arbres" msgid "Water Objects" msgstr "Éléments d'eau" msgid "Miscellaneous" msgstr "Divers" msgid "Artifacts" msgstr "Artéfacts" msgid "Dwellings" msgstr "Demeures" msgid "Mines" msgstr "Mines" msgid "Power-ups" msgstr "Bonus" msgid "Treasures" msgstr "Trésors" msgid "Heroes" msgstr "Héros" msgid "Towns" msgstr "Villages" msgid "editorErasure|Landscape objects" msgstr "d'éléments de paysage" msgid "editorErasure|Adventure non pickable objects" msgstr "d'éléments d'aventure (non piquables)" msgid "editorErasure|Castles" msgstr "de châteaux" msgid "editorErasure|Adventure pickable objects" msgstr "d'éléments d'aventure (piquables)" msgid "editorErasure|Monsters" msgstr "de monstres" msgid "editorErasure|Heroes" msgstr "de héros" msgid "editorErasure|Roads" msgstr "de routes" msgid "editorErasure|Streams" msgstr "de rivières" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Place le terrain sélectionné sur la carte\n" "(précision: %{size} cases sur %{size})." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Efface des éléments sélectionnés sur la carte\n" "(précision: %{size} cases sur %{size})." msgid "Small Brush" msgstr "Petit pinceau" msgid "Medium Brush" msgstr "Pinceau moyen" msgid "Large Brush" msgstr "Grand pinceau" msgid "Area Fill" msgstr "Remplissage de zone" msgid "Used to click and drag for filling in large areas." msgstr "Permet de remplir de vastes zones avec la texture sélectionnée." msgid "Clear Area" msgstr "Effacement de zone" msgid "Used to click and drag for clearing large areas." msgstr "" "Permet l'effacement de tous les éléments qui se trouvent dans la zone " "sélectionné." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Requiert %{rate} fois les points de mouvement normaux pour tous les héros. " "(L'orientation réduit, voire annule cette pénalité)." msgid "Traversable only by boat." msgstr "Traversable uniquement par bateau." msgid "No special modifiers." msgstr "Aucun modificateur particulier." msgid "Toggle the erasure of %{type} objects." msgstr "Effacement %{type}." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Les éléments de ce type seront effacés à l'aide de l'outil d'effacement. " "Cliquez ici avec le bouton gauche de la souris pour désélectionner ce type " "d'élément. Maintenez ce bouton enfoncé pour désélectionner tous les autres " "types d'éléments." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Les éléments de ce type ne seront PAS supprimés avec l'outil d'effacement. " "Cliquez ici avec le bouton gauche de la souris pour sélectionner ce type " "d'élément. Maintenez ce bouton enfoncé pour sélectionner tous les autres " "types d'éléments." msgid "Terrain Mode" msgstr "Terrains" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "Permet de placer de l'herbe, la boue, la mer, etc. sur la carte." msgid "Landscape Objects Mode" msgstr "Éléments de paysage" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Permet de placer des éléments de paysage sur la carte (montagnes, rochers, " "arbres, etc.)." msgid "Detail Mode" msgstr "Details" #, fuzzy msgid "Used for special editing of action objects." msgstr "" "Permet de spécifier les paramètres spécifiques des monstres, héros et " "villages." msgid "Adventure Objects Mode" msgstr "Éléments d'aventure" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Permet de placer des éléments d'aventure sur la carte (artéfacts, demeures, " "mines, trésors, etc.)." msgid "Kingdom Objects Mode" msgstr "Royaumes" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Permet de placer des éléments de royaume sur la carte (villages, châteaux et " "héros)." msgid "Monsters Mode" msgstr "Créatures" msgid "Used to place monsters on the map." msgstr "Permet de placer des créatures sur la carte." msgid "Allows you to draw streams by clicking and dragging." msgstr "Permet de dessiner des cours d'eau en cliquant et en faisant glisser." msgid "Stream Mode" msgstr "Rivières" msgid "Allows you to draw roads by clicking and dragging." msgstr "Permet de dessiner des routes en cliquant et en faisant glisser." msgid "Road Mode" msgstr "Routes" msgid "Erase Mode" msgstr "Effacement" msgid "Used to erase objects from the map." msgstr "Permet d'effacer les éléments placés sur la carte." msgid "Change between zoom and normal view." msgstr "Passer de la vue zoom à la vue normale." msgid "Magnify" msgstr "Agrandir" msgid "Undo" msgstr "Annuler" msgid "Undo your last action." msgstr "Annuler votre dernière action." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "Annuler votre dernière action." msgid "Edit map title, description, and other general information." msgstr "" "Modifier le titre de la carte, la description et d'autres informations " "générales." msgid "Specifications" msgstr "Spécificités" msgid "File Options" msgstr "Options fichier" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Ouvre le menu des options du fichier, qui vous permet de sauvegarder ou " "charger une carte, ou quitter l'éditeur." msgid "View the editor system options, which let you customize the editor." msgstr "" "Affiche les options système de l'éditeur, qui vous permettent de " "personnaliser l'application." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Créer une carte de %{size} cases de large sur %{size} cases de haut." msgid "Cancel back to the New Map menu." msgstr "Annuler et revenir au menu de création de carte." msgid "Cancel back to the main menu." msgstr "Annuler et revenir au menu principal." msgid "From Scratch" msgstr "À partir de zéro" msgid "Start from scratch with a blank map." msgstr "Partir de zéro avec une carte vierge." msgid "Create a randomly generated map." msgstr "Créer une carte générée de manière aléatoire." msgid "Random" msgstr "Aléatoire" msgid "Cancel back to the Map Editor main menu." msgstr "Annuler et revenir au menu principal de l'éditeur." msgid "No maps available!" msgstr "Aucune carte disponible !" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "Héros %{race} %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race1} %{name1} vs. %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "Héros %{race} %{color}" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{townOrCastle} %{race} %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race1} %{name1} vs. %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{race1} %{name1} vs. %{race2} %{name2}" #, fuzzy msgid "None." msgstr "Aucune" #, fuzzy msgid "One side defeats another." msgstr "Veuillez choisir un autre héros." #, fuzzy msgid "Accumulate gold." msgstr "Amasser %{count} pièces d'or." #, fuzzy msgid "Run out of time." msgstr "Quitter l'éditeur de carte." #, fuzzy msgid "alliance|1st" msgstr " alliance" #, fuzzy msgid "alliance|2nd" msgstr " alliance" #, fuzzy msgid "alliance|3rd" msgstr " alliance" #, fuzzy msgid "alliance|4th" msgstr " alliance" #, fuzzy msgid "alliance|5th" msgstr " alliance" #, fuzzy msgid "Special Loss Condition" msgstr "Conditions de défaite" #, fuzzy msgid "Special Victory Condition" msgstr "Conditions de victoire" #, fuzzy msgid "Allow standard victory conditions" msgstr "Conditions de victoire" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " alliance" #, fuzzy msgid "{%number} alliance: " msgstr " alliance" #, fuzzy msgid "Gold:" msgstr "Or" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Sélectionnez la destination." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Enregistrer le jeu en cours." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Enregistrer le jeu en cours." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Enregistrer le jeu en cours." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Enregistrer le jeu en cours." #, fuzzy msgid "Map Difficulty" msgstr "" "Difficulté\n" "de la carte" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "Emplacement : " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Description sélectionnée" #, fuzzy msgid "Click to accept the changes made." msgstr "Cliquez pour afficher le village suivant." #, fuzzy msgid "Click to edit custom rumors." msgstr "Enregistrer le jeu en cours." msgid "Rumors" msgstr "Rumeurs" #, fuzzy msgid "Click to edit daily events." msgstr "Cliquez pour quitter les résultats de la bataille." msgid "Events" msgstr "Événements" #, fuzzy msgid "Click to change the language of the map." msgstr "Changer la langue du jeu." #, fuzzy msgid "Click to change your map name." msgstr "Cliquez pour afficher le village suivant." #, fuzzy msgid "Map Name" msgstr "Nom du fichier pour la carte" #, fuzzy msgid "Click to change the description of the current map." msgstr "La description de la carte actuellement sélectionnée." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "La description de la carte actuellement sélectionnée." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "La description de la carte actuellement sélectionnée." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Type de carte" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Difficulté de la carte actuellement sélectionnée. La difficulté de la carte " "est déterminée par le concepteur du scénario. Les cartes plus difficiles " "peuvent inclure des ennemis plus nombreux ou plus forts, moins de ressources " "ou d'autres conditions spéciales rendant les choses plus difficiles pour le " "joueur humain." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Sélectionner %{resource} :" #, fuzzy msgid "Animation" msgstr "Annexion" #, fuzzy msgid "Passability" msgstr "Personnalité :" #, fuzzy msgid "Toggle animation of the objects." msgstr "Effacement %{type}." msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "Rumeur :" msgid "Rumor" msgstr "Rumeur" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Enregistrer le jeu en cours." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "Programmation supplémentaire" #, fuzzy msgid "Edit Rumor" msgstr "Éditeur" #, fuzzy msgid "Edit an existing rumor." msgstr "Charger une carte existante." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "Charger une carte existante." msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Emplacement : " #, fuzzy msgid "Save Map:" msgstr "Sauvegarder la carte" #, fuzzy msgid "Click to save the current map." msgstr "Enregistrer le jeu en cours." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Enregistrer le jeu en cours." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Facile" msgid "difficulty|Normal" msgstr "Normal" msgid "difficulty|Hard" msgstr "Difficile" msgid "difficulty|Expert" msgstr "Expert" msgid "difficulty|Impossible" msgstr "Impossible" msgid "and more..." msgstr "et plus encore..." msgid "Easy" msgstr "Facile" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "Difficile" msgid "Campaign Difficulty" msgstr "Difficulté de la campagne" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Choisissez cette difficulté si vous préférez profiter de l'histoire du jeu " "avec moins de challenge. L'IA sera plus faible dans ce mode de difficulté." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Choisissez cette difficulté si vous voulez jouer à la campagne telle qu'elle " "a été conçue originellement." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Choisissez cette difficulté si vous voulez plus de challenge. L'IA sera plus " "forte dans ce mode de difficulté." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Félicitations !\n" "\n" "Jours : %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Difficulté : %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Score : %{score}\n" "\n" "Rang :\n" "%{rating}" msgid "Start the selected scenario." msgstr "Démarrer le scénario sélectionné." msgid "View Intro" msgstr "Voir l'intro" msgid "View the intro video for the current state of the campaign." msgstr "Voir la vidéo d'introduction du scénario actuel." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Choisissez la difficulté de la campagne. Elle pourra être abaissée à tout " "moment au cours de la campagne." msgid "Restart the current scenario." msgstr "Recommencer le scénario actuel." msgid "Difficulty" msgstr "Difficulté" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Vous avez diminué la difficulté de la campagne. Vous ne pourrez plus annuler " "ce changement après validation. Le score final sera calculé en se basant " "seulement sur le nouveau niveau de difficulté. Voulez-vous confirmer ?" msgid "Are you sure you want to restart this scenario?" msgstr "Voulez-vous vraiment recommencer ce scénario ?" msgid "Campaign Scenario loading failure" msgstr "Échec du chargement du scénario de campagne" msgid "Please make sure that campaign files are correct and present." msgstr "Assurez-vous que les fichiers de campagne sont corrects et présents." msgid "Days spent" msgstr "Jours passés" msgid "The number of days spent on this campaign." msgstr "Le nombre de jours passés dans cette campagne." msgid "Project Coordination and Core Development" msgstr "Coordination du projet et développement" msgid "Development" msgstr "Développement" msgid "Visit us at " msgstr "Rendez-vous sur " msgid "QA and Support" msgstr "AQ et support" msgid "Dev and Support" msgstr "Dév et support" msgid "Special Thanks to" msgstr "Remerciements spéciaux à" msgid "and many-many other contributors and supporters!" msgstr "et de nombreux autres contributeurs et soutiens !" msgid "Support us at" msgstr "Soutenez-nous sur" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Prenez contact avec nous sur" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Besoin d'aide avec le jeu ?" msgid "Original project before 0.7" msgstr "Projet original avant 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "L'équipe de Heroes of Might and Magic II: The Succession Wars" msgid "Designed and Directed" msgstr "Conçu et réalisé" msgid "Programming and Design" msgstr "Programmation et conception" msgid "Executive Producer" msgstr "Producteur exécutif" msgid "Producer" msgstr "Producteur" msgid "Additional Design" msgstr "Conception supplémentaire" msgid "Additional Programming" msgstr "Programmation supplémentaire" msgid "Musical Production" msgstr "Production musicale" msgid "Music and Sound Design" msgstr "Musique et conception sonore" msgid "Vocalists" msgstr "Vocalistes" msgid "Art Director" msgstr "Directeur artistique" msgid "Assistant Art Director" msgstr "Directeur artistique adjoint" msgid "Artists" msgstr "Artistes" msgid "QA Manager" msgstr "Responsable AQ" msgid "QA" msgstr "AQ" msgid "Writing" msgstr "Écriture" msgid "Manual and Helpfile" msgstr "Manuel et fichier d'aide" msgid "Scenarios" msgstr "Scénarios" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "L'équipe de Heroes of Might and Magic II: The Price of Loyalty" msgid "Design Lead" msgstr "Chef du design" msgid "Designers" msgstr "Concepteurs" msgid "Programming Lead" msgstr "Responsable de programmation" msgid "Art Lead" msgstr "Responsable artistique" msgid "Playtesters" msgstr "Testeurs" msgid "Designer" msgstr "Concepteur" msgid "Producers" msgstr "Producteurs" msgid "QA Managers" msgstr "Responsables AQ" msgid "Sound Design" msgstr "Conception sonore" msgid "Town Themes" msgstr "Thèmes des villages" msgid "Alto Sax" msgstr "Saxo alto" msgid "Harpsichord and Piano" msgstr "Clavecin et piano" msgid "Basso Vocal" msgstr "Basse (Voix)" msgid "Soprano Vocal" msgstr "Soprano (Voix)" msgid "Recorded at %{recordingStudio}" msgstr "Enregistrée aux %{recordingStudio}" msgid "credits|Manual" msgstr "Manuel" msgid "German Consultant" msgstr "Consultant allemand" msgid "Map Designers" msgstr "Concepteurs de cartes" msgid "Package Design" msgstr "Conception du conditionnement" msgid "High Scores" msgstr "Meilleurs scores" msgid "Your Name" msgstr "Votre nom" msgid "Unknown Hero" msgstr "Héros inconnu" msgid "Standard" msgstr "Jeu standard" msgid "View High Scores for Standard Maps." msgstr "Voir l'écran des meilleurs scores des cartes standards." msgid "Campaign" msgstr "Campagne" msgid "View High Scores for Campaigns." msgstr "Voir l'écran des meilleurs scores." msgid "hotkey|default okay event" msgstr "Confirmer l'action prédéfinie" msgid "hotkey|default cancel event" msgstr "Annuler l'action en cours" msgid "hotkey|default left" msgstr "Direction gauche" msgid "hotkey|default right" msgstr "Direction droite" msgid "hotkey|default up" msgstr "Direction haut" msgid "hotkey|default down" msgstr "Direction bas" msgid "hotkey|toggle fullscreen" msgstr "Basculer en plein écran" msgid "hotkey|toggle text support mode" msgstr "Basculer en mode texte" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "Basculer en mode texte" msgid "hotkey|new game" msgstr "Nouveau partie" msgid "hotkey|load game" msgstr "Charger une partie" msgid "hotkey|high scores" msgstr "Écran des meilleurs scores" msgid "hotkey|credits" msgstr "Crédits" msgid "hotkey|standard game" msgstr "Partie standard" msgid "hotkey|campaign game" msgstr "Partie campagne" msgid "hotkey|multi-player game" msgstr "Partie multijoueur" msgid "hotkey|settings" msgstr "Paramètres" msgid "hotkey|quit" msgstr "Quitter" msgid "hotkey|select map" msgstr "Sélectionner carte" msgid "hotkey|select small map size" msgstr "Voir les petites cartes" msgid "hotkey|select medium map size" msgstr "Voir les cartes moyennes" msgid "hotkey|select large map size" msgstr "Voir les grandes cartes" msgid "hotkey|select extra large map size" msgstr "Voir les très grandes cartes" msgid "hotkey|select all map sizes" msgstr "Voir toutes les cartes" msgid "hotkey|hot seat game" msgstr "Partie à tour de rôle" msgid "hotkey|battle only game" msgstr "Mode bataille" msgid "hotkey|choose the original campaign" msgstr "Sélectionner la campagne originale" msgid "hotkey|choose the expansion campaign" msgstr "Choisir les campagnes de l'extension \"The Price of Loyalty\"" msgid "hotkey|map editor main menu" msgstr "Menu principal de l'éditeur" msgid "hotkey|new map menu" msgstr "Nouvelle carte" msgid "hotkey|load map menu" msgstr "Menu de chargement de carte" msgid "hotkey|new map from scratch" msgstr "Carte vierge" msgid "hotkey|new random map" msgstr "Nouvelle carte aléatoire" msgid "hotkey|undo last action" msgstr "Annuler la dernière action" msgid "hotkey|redo last action" msgstr "Refaire la dernière action" #, fuzzy msgid "hotkey|open game main menu" msgstr "Nouvelle carte" #, fuzzy msgid "hotkey|toggle passability" msgstr "Afficher/masquer la fenêtre d'état" msgid "hotkey|roland campaign" msgstr "Campagne de Roland" msgid "hotkey|archibald campaign" msgstr "Campagne d'Archibald" msgid "hotkey|price of loyalty campaign" msgstr "La campagne \"Price of Loyalty\"" msgid "hotkey|voyage home campaign" msgstr "La campagne \"Le retour\"" msgid "hotkey|wizard's isle campaign" msgstr "La campagne \"L'archipel\"" msgid "hotkey|descendants campaign" msgstr "La campagne \"Les héritiers\"" msgid "hotkey|select first campaign bonus" msgstr "Choisir le premier bonus de campagne" msgid "hotkey|select second campaign bonus" msgstr "Choisir le second bonus de campagne" msgid "hotkey|select third campaign bonus" msgstr "Choisir le troisième bonus de campagne" msgid "hotkey|view campaign intro" msgstr "Voir l'intro de la campagne" msgid "hotkey|select campaign difficulty" msgstr "Choisir la difficulté de la campagne" msgid "hotkey|restart campaign scenario" msgstr "Recommencer le scénario de campagne" msgid "hotkey|world map left" msgstr "Déplacement vers la gauche" msgid "hotkey|world map right" msgstr "Déplacement vers la droite" msgid "hotkey|world map up" msgstr "Déplacement vers le haut" msgid "hotkey|world map down" msgstr "Déplacement vers le bas" msgid "hotkey|world map up left" msgstr "Déplacement vers le haut et la gauche" msgid "hotkey|world map up right" msgstr "Déplacement vers le haut et la droite" msgid "hotkey|world map down left" msgstr "Déplacement vers le bas et la gauche" msgid "hotkey|world map down right" msgstr "Déplacement vers le bas et la droite" msgid "hotkey|save game" msgstr "Sauvegarder la partie" msgid "hotkey|next hero" msgstr "Héros suivant" msgid "hotkey|change to hero under cursor" msgstr "Sélectionner le héros sous le curseur" msgid "hotkey|start hero movement" msgstr "Commencer le déplacement du héros" msgid "hotkey|cast adventure spell" msgstr "Lancement de sorts d'aventure." msgid "hotkey|put hero to sleep" msgstr "Mettre le héros en mode \"endormi\"" msgid "hotkey|next town" msgstr "Village suivant" msgid "hotkey|end turn" msgstr "Fin du tour" msgid "hotkey|file options" msgstr "Options fichier" msgid "hotkey|adventure options" msgstr "Options d'aventure" msgid "hotkey|puzzle map" msgstr "Visualiser le puzzle" msgid "hotkey|scenario information" msgstr "Informations du scénario" msgid "hotkey|dig for artifact" msgstr "Creuser pour trouver l'artéfact" msgid "hotkey|view world" msgstr "Voir le monde entier" msgid "hotkey|kingdom summary" msgstr "Informations du royaume" msgid "hotkey|default action" msgstr "Action par défaut" msgid "hotkey|open focus" msgstr "Ouvrir l'objet actuel" msgid "hotkey|system options" msgstr "Options système" msgid "hotkey|scroll left" msgstr "Défilement gauche" msgid "hotkey|scroll right" msgstr "Défilement droite" msgid "hotkey|scroll up" msgstr "Défilement en haut" msgid "hotkey|scroll down" msgstr "Défilement en bas" msgid "hotkey|toggle control panel" msgstr "Afficher/masquer le panneau de commande" msgid "hotkey|toggle radar" msgstr "Afficher/masquer le radar" msgid "hotkey|toggle buttons" msgstr "Afficher/masquer les boutons" msgid "hotkey|toggle status" msgstr "Afficher/masquer la fenêtre d'état" msgid "hotkey|toggle icons" msgstr "Afficher/masquer les icônes" msgid "hotkey|transfer control to ai" msgstr "Transférer le contrôle à l'IA" msgid "hotkey|retreat from battle" msgstr "Retraite" msgid "hotkey|surrender during battle" msgstr "Reddition" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Activer/désactiver le mode combat auto" msgid "hotkey|quick combat" msgstr "Combat rapide" msgid "hotkey|battle options" msgstr "Options de bataille" msgid "hotkey|skip turn in battle" msgstr "Passer le tour dans le combat" msgid "hotkey|cast battle spell" msgstr "Lancer sortilège de bataille" msgid "hotkey|dwelling level 1" msgstr "Demeure de niveau 1" msgid "hotkey|dwelling level 2" msgstr "Demeure de niveau 2" msgid "hotkey|dwelling level 3" msgstr "Demeure de niveau 3" msgid "hotkey|dwelling level 4" msgstr "Demeure de niveau 4" msgid "hotkey|dwelling level 5" msgstr "Demeure de niveau 5" msgid "hotkey|dwelling level 6" msgstr "Demeure de niveau 6" msgid "hotkey|well" msgstr "Puits" msgid "hotkey|marketplace" msgstr "Place du marché" msgid "hotkey|mage guild" msgstr "Guilde des magiciens" msgid "hotkey|shipyard" msgstr "Ponton" msgid "hotkey|thieves guild" msgstr "Guilde des voleurs" msgid "hotkey|tavern" msgstr "Taverne" msgid "hotkey|construction screen" msgstr "Écran de construction" msgid "hotkey|buy all monsters in well" msgstr "Enrôler toutes les créatures dans le puits" msgid "hotkey|split stack by half" msgstr "Diviser la troupe en deux" msgid "hotkey|split stack by one" msgstr "Détacher une créature de la troupe" msgid "hotkey|join stacks" msgstr "Fusionner les troupes" msgid "hotkey|upgrade troop" msgstr "Améliorer une troupe" msgid "hotkey|dismiss hero or troop" msgstr "Renvoyer un héros ou une troupe" msgid "hotkey|exchange all troops" msgstr "Échanger toutes les troupes" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Voulez-vous reprendre à l'IA le contrôle du jeu ? L'effet aura lieu " "uniquement au prochain tour." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Voulez-vous laisser l'IA prendre les commandes ? L'effet aura lieu " "uniquement au prochain tour." msgid "Default Actions" msgstr "Actions par défaut" msgid "Global Actions" msgstr "Actions globales" msgid "World Map" msgstr "Carte du monde" msgid "Battle Screen" msgstr "Écran de bataille" msgid "Town Screen" msgstr "Écran de ville" msgid "Army Actions" msgstr "Actions de l'armée" msgid "The save file is corrupted." msgstr "Le fichier de sauvegarde est corrompu." msgid "Unsupported save format: " msgstr "Format de sauvegarde non supporté : " msgid "Current game version: " msgstr "Version actuelle du jeu : " msgid "Last supported version: " msgstr "Dernière version supportée : " msgid "This file contains a save with an invalid game type." msgstr "Ce fichier contient une sauvegarde avec un type de jeu invalide." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Cette sauvegarde a besoin des ressources de l'extension \"The Price of " "Loyalty\". Mais ces ressources n'ont pas été fournis au moteur." msgid "This saved game is localized to '" msgstr "Cette partie a été sauvegardée en langue '" msgid "' language, but the current language of the game is '" msgstr "', mais la langue actuelle du jeu est '" msgid "No save files to load." msgstr "Pas de sauvegarde disponible." msgid "Hot Seat" msgstr "Jouer à plusieurs" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Jouez à tour de rôle, où 2 à 6 joueurs jouent autour du même ordinateur, se " "passant la souris lorsque c'est leur tour." msgid "A single player game playing out a single map." msgstr "Une partie joueur solo sur une seule carte." msgid "Standard Game" msgstr "Jeu standard" msgid "A single player game playing through a series of maps." msgstr "Une partie joueur solo à travers une série de cartes." msgid "Campaign Game" msgstr "Mode campagne" msgid "Multi-Player Game" msgstr "Jeu multijoueur" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Une partie multijoueurs, avec plusieurs joueurs humains en compétition les " "uns contre les autres sur une seule carte." msgid "fheroes2 Resurrection Team presents" msgstr "L'équipe fheroes2 Resurrection présente" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Bienvenue sur Heroes of Might and Magic II (amélioré par le moteur " "fheroes2) !" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "\n" "\n" "Avant de commencer le jeu choisissez la résolution du jeu." msgid "Greetings!" msgstr "Salutations !" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Quitter Heroes of Might and Magic II et retourner au système d'exploitation." msgid "Credits" msgstr "Crédits" msgid "View the credits screen." msgstr "Voir l'écran des crédits." msgid "View the high scores screen." msgstr "Voir l'écran des meilleurs scores." #, fuzzy msgid "Create new or modify existing maps." msgstr "Charger une carte existante." msgid "Change language, resolution and settings of the game." msgstr "Changer la langue, la résolution et les paramètres du jeu." msgid "Game Settings" msgstr "Paramètres du jeu" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Les fichiers vidéo requis pour la fenêtre de sélection de la campagne sont " "manquants. Assurez-vous que tous les fichiers nécessaires sont présents dans " "le système." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "La campagne de Roland ou d'Archibald du jeu original Heroes of Might and " "Magic II." msgid "Original Campaign" msgstr "Campagne originale" msgid "Expansion Campaign" msgstr "Campagne expansion" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" "L'une des quatre nouvelles campagnes de l'extension The Price of Loyalty." msgid "Loading video. Please wait..." msgstr "Chargement de la vidéo. Veuillez patienter..." msgid "Host" msgstr "Hôte" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "L'hôte configure les options de jeu. Il ne peut y avoir qu'un seul hôte par " "jeu en réseau." msgid "Guest" msgstr "Invité" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "L'invité attend que l'hôte configure le jeu, puis est automatiquement " "ajouté. Il peut y avoir plusieurs invités pour les jeux TCP/IP." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "fheroes2 neccessite les fichiers du jeu d'origine Heroes of Might and Magic " "II pour fonctionner. Apparemment vous utilissez la version démo du jeu à " "cette fin. Veuillez noter qu'un seul scénario sera disponible dans cette " "configuration." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Une partie multijoueurs, avec plusieurs joueurs humains en compétition les " "uns contre les autres sur une seule carte." msgid "Battle Only" msgstr "Champ de bataille" msgid "Setup and play a battle without loading any map." msgstr "Configurez et jouez une bataille sans charger de carte." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "Jouez de 2 à 6 joueurs à tour de rôle sur le même appareil." msgid "2 Players" msgstr "2 Joueurs" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Jouez avec 2 joueurs humains, et éventuellement, jusqu'à 4 joueurs " "ordinateur supplémentaires." msgid "3 Players" msgstr "3 Joueurs" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Jouez avec 3 joueurs humains, et éventuellement, jusqu'à 3 joueurs " "ordinateur supplémentaires." msgid "4 Players" msgstr "4 Joueurs" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Jouez avec 4 joueurs humains, et éventuellement, jusqu'à 2 joueurs " "ordinateur supplémentaires." msgid "5 Players" msgstr "5 Joueurs" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Jouez avec 5 joueurs humains, et éventuellement, jusqu'à 1 joueur ordinateur " "supplémentaire." msgid "6 Players" msgstr "6 Joueurs" msgid "Play with 6 human players." msgstr "Jouer avec 6 joueurs humains." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" "La cité des dragons est tombée ! Vous êtes maintenant le maître des dragons." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Vous avez capturé %{name} !\n" "Vous êtes victorieux." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Vous avez capturé le héros ennemi %{name} !\n" "Votre quête est terminée." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Vous avez trouvé le %{name}.\n" "Votre quête est terminée." msgid "Ultimate Artifact" msgstr "Ultime artéfact" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "L'ennemi est battu.\n" "Votre camp a triomphé !" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Vous avez accumulé plus de %{count} pièces d'or dans votre trésorerie.\n" "Tous les ennemis s'inclinent devant votre richesse et votre puissance." msgid "Victory!" msgstr "Victoire !" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "L'ennemi a capturé %{name} !\n" "Ce camp adverse a triomphé." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "L'ennemi a accumulé plus de %{count} pièces d'or dans sa trésorerie.\n" "Vous devez vous incliner dans la défaite devant sa richesse et sa puissance." msgid "You have been eliminated from the game!!!" msgstr "Vous avez été éliminé du jeu !!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Vous avez perdu le héros %{name} .\n" "Votre quête est terminée." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Vous n'avez pas réussi à terminer votre quête à temps.\n" "Tout est perdu." msgid "Defeat!" msgstr "Défaite !" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Score de base : %{score}\n" "Difficulté : %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "Défaire tous les héros et capturer tous les villages ennemis." msgid "Your side defeats the opposing side." msgstr "Votre camp l'emporte sur le camp adverse." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Manquer de temps. (Ne pas gagner avant un certain point.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Vaincre l'ennemi %{enemies}." msgstr[1] "Vaincre l'alliance ennemie de %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "L'alliance est composée de %{allies} et vous devez vaincre %{enemies}." msgstr[1] "" "L'alliance est composée de %{allies} et vous devez vaincre l'alliance " "ennemie composée de %{enemies}." msgid "Capture the castle '%{name}'." msgstr "Capturer le château '%{name}'." msgid "Capture the town '%{name}'." msgstr "Capturer le village '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Vaincre le héros '%{name}'." msgid "Find the ultimate artifact." msgstr "Trouver l'ultime artéfact." msgid "Find the '%{name}' artifact." msgstr "Trouver l'artéfact '%{name}'." msgid "Accumulate %{count} gold." msgstr "Amasser %{count} pièces d'or." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr ", ou éliminer tous les adversaires." msgid "Lose the castle '%{name}'." msgstr "Perdre le château '%{name}'." msgid "Lose the town '%{name}'." msgstr "Perdre le village de '%{name}'." msgid "Lose the hero: %{name}." msgstr "Perdre le héros : %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "Limite de temps : mois %{month}, semaine %{week}, jour %{day}." msgid "%{color} player has been vanquished!" msgstr "Le joueur %{color} a été vaincu !" msgid "Major Event!" msgstr "Événement majeur !" msgid "Scenario:" msgstr "Scénario :" msgid "Game Difficulty:" msgstr "Difficulté du jeu :" msgid "Opponents:" msgstr "Adversaires :" msgid "Class:" msgstr "Alignement :" msgid "Rating %{rating}%" msgstr "Taux %{rating}%" msgid "Click here to select which scenario to play." msgstr "Cliquez ici pour sélectionner le scénario à jouer." msgid "Scenario" msgstr "Scénario" msgid "Game Difficulty" msgstr "Difficulté du jeu" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Vous permet de modifier la difficulté de départ à laquelle vous allez jouer. " "Les niveaux de difficulté plus élevés vous font commencer avec moins de " "ressources et, aux paramètres les plus élevés, donne des ressources " "supplémentaires à l'ordinateur." msgid "Difficulty Rating" msgstr "Taux de difficulté" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Le taux de difficulté reflète une combinaison de différents paramètres pour " "votre jeu. Ce taux sera appliqué à votre score final." msgid "Click to accept these settings and start a new game." msgstr "Cliquez pour accepter ces paramètres et démarrer une nouvelle partie." msgid "Click to return to the main menu." msgstr "Cliquez pour revenir au menu principal." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Les astrologues proclament le mois %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Les astrologues proclament la semaine %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" "Après une croissance régulière, la population de %{monster} est doublée !" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Après une croissance régulière, la population de %{monster} augmente de " "%{count} pour cent !" msgstr[1] "" "Après une croissance régulière, la population de %{monster} augmente de " "%{count} pour cent !" msgid "%{monster} growth +%{count}." msgstr "La population de %{monster} augmente de +%{count}." msgid " All populations are halved." msgstr " Toutes les populations sont réduites de moitié." msgid " All dwellings increase population." msgstr " La population de toutes les demeures augmente." msgid "New Month!" msgstr "Nouveau mois !" msgid "New Week!" msgstr "Nouvelle semaine !" msgid "Beware!" msgstr "Attention !" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color}, c'est votre dernier jour pour capturer un village, ou vous serez " "banni de cette terre." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "Joueur %{color}, il ne vous reste que %{day} jours pour capturer un village, " "sinon vous serez banni de cette terre." msgid "%{color} player's turn." msgstr "Tour du joueur %{color}." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "Joueur %{color}, vous venez de perdre votre dernier village. Si vous n'avez " "pas de village dans une semaine, vous serez éliminé." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "Joueur %{color}, vos héros vous abandonnent et vous êtes banni de cette " "terre." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "Héros suivant" msgid "Select the next Hero." msgstr "Passer au héros suivant." msgid "Hero Movement" msgstr "Déplacement du héros" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "Commence le déplacement du héros selon le chemin choisi ou revisite le lieu " "occupé par le héros. Appuyez sur ce bouton et maintenez-le enfoncé pour " "réinitialiser le chemin du héros." msgid "Kingdom Summary" msgstr "Informations sur votre royaume" msgid "View a summary of your Kingdom." msgstr "Voir un récapitulatif de votre royaume." msgid "Cast an adventure spell." msgstr "Lancer un sort d'aventure." msgid "End Turn" msgstr "Fin du tour" msgid "End your turn and let the computer take its turn." msgstr "Terminer votre tour et laisser l'ordinateur faire son tour." msgid "Adventure Options" msgstr "Options d'aventure" msgid "Bring up the adventure options menu." msgstr "Fait apparaître le menu des options d'aventure." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Affiche le menu des options fichier, qui vous permet de charger, " "sauvegarder, recommencer ou quitter." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Affiche le menu des options du système, qui vous permet de personnaliser " "votre jeu." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Un ou plusieurs héros peuvent encore se déplacer. Voulez-vous vraiment " "terminer votre tour ?" msgid "Are you sure you want to quit?" msgstr "Voulez-vous vraiment quitter ?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Voulez-vous vraiment recommencer ? (Votre partie en cours sera perdue.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Voulez-vous vraiment remplacer la sauvegarde avec ce nom ?" msgid "Game saved successfully." msgstr "Sauvegarde réussie." msgid "There was an issue during saving." msgstr "Il y a eu un problème lors de la sauvegarde." # Needs line break to have insectile space but keep partie and ? together. msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Voulez-vous vraiment charger une nouvelle\n" "partie ? (Votre partie en cours sera perdue.)" msgid "Try looking on land!!!" msgstr "Essayez de chercher sur la terre ferme !!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Rechercher l'artéfact ultime est vain. Même s'il le trouvait, votre héros ne " "pourrait pas le porter - tous ses emplacements d'artéfacts sont occupés." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" "La fouille pour les artéfacts nécessite une journée entière, réessayez " "demain." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Après avoir passé de nombreuses heures à creuser ici, vous avez découvert " "l'artéfact '%{artifact}'." msgid "Congratulations!" msgstr "Félicitations !" msgid "Nothing here. Where could it be?" msgstr "Rien ici. Où cela pourrait-il être ?" msgid "Try searching on clear ground." msgstr "Essayez de chercher sur un terrain dégagé." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Une vue miniature du monde connu. Cliquez avec le bouton gauche de la souris " "pour déplacer la zone d'affichage." msgid "Month: %{month} Week: %{week}" msgstr "Mois : %{month}, Semaine : %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Vous trouvez une petite\n" "quantité de %{resource}." msgid "Status Window" msgstr "Fenêtre d'état" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Cette fenêtre fournit des informations sur le statut de votre héros et de " "votre royaume, et affiche la date." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Cette fenêtre fournit des informations sur le statut de votre héros ou " "royaume, et affiche la date. Faites un clic gauche ici pour passer d'une " "fenêtre à l'autre." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Cela vous permet de changer les positions de départ et les couleurs du " "joueur. Une couleur particulière commencera toujours dans un emplacement " "particulier. Certaines positions ne peuvent être jouées que par un joueur " "d'ordinateur ou uniquement par un joueur humain." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Ceci vous permet de changer l'alignement d'un joueur. Les alignements ne " "sont pas toujours modifiables. Selon le scénario, un joueur peut recevoir " "des villages et/ou des héros supplémentaires qui ne sont pas de son " "alignement principal." msgid "Handicap" msgstr "Pénalité" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Cela vous permet de modifier la pénalité d'un joueur particulier. Seuls les " "joueurs humains peuvent avoir une pénalité. Les joueurs avec une pénalité " "commencent avec moins de ressources et reçoivent 15 ou 30 % de ressources en " "moins à chaque tour pour la pénalité légère et la pénalité sévère." msgid "%{color} player" msgstr "Joueur %{color}" msgid "No Handicap" msgstr "Pas de pénalité" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Pas de diminution des ressources de départ ni de celles reçues à chaque tour." msgid "Mild Handicap" msgstr "Pénalité légère" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Les joueurs avec la pénalité légère commenceront avec moins de ressources et " "recevront 15 % de ressources en moins à chaque tour." msgid "Severe Handicap" msgstr "Pénalité sévère" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Les joueurs avec la pénalité sévère commenceront avec moins de ressources et " "recevront 30 % de ressources en moins à chaque tour." msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Régler Attaque" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Voir les infos de %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Défense" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "ESPACE" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Revenu du royaume" msgid "Kingdom Income per day." msgstr "Revenu du royaume par jour." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Chaque phare sous votre contrôle donnera un bonus de déplacement journalier " "à tous vos navires." msgid "English" msgstr "Anglais" msgid "French" msgstr "Français" msgid "Polish" msgstr "Polonais" msgid "German" msgstr "Allemand" msgid "Russian" msgstr "Russe" msgid "Italian" msgstr "Italien" msgid "Czech" msgstr "Tchèque" msgid "Norwegian" msgstr "Norvégien" msgid "Belarusian" msgstr "Biélorusse" msgid "Bulgarian" msgstr "Bulgare" msgid "Ukrainian" msgstr "Ukrainien" msgid "Romanian" msgstr "Roumain" msgid "Spanish" msgstr "Espagnol" msgid "Swedish" msgstr "Suédois" msgid "Portuguese" msgstr "Portugais" msgid "Turkish" msgstr "Turc" msgid "Dutch" msgstr "Néerlandais" msgid "Hungarian" msgstr "Hongrois" msgid "Danish" msgstr "Danois" msgid "Slovak" msgstr "Slovaque" msgid "Vietnamese" msgstr "Vietnamien" msgid "Slow" msgstr "Lente" msgid "Fast" msgstr "Rapide" msgid "Very Fast" msgstr "Très rapide" msgid "Evil" msgstr "Mal" msgid "Good" msgstr "Bien" msgid ", FPS: " msgstr ", FPS : " msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} cambriolé" msgid "pyramid|%{object} raided" msgstr "%{object} pillée" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Soeur Eliza" msgid "Brother Brax" msgstr "Frère Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " augmente votre moral à son maximum" msgid " gives you maximum luck" msgstr " augmente votre chance à son maximum" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Impossible de déplacer le grimoire" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Vous ne pouvez pas ramasser cet artéfact, vous êtes déjà surchargé !" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Pour lancer des sorts, vous devez d'abord acheter un grimoire pour %{gold} " "pièces d'or." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" "Malheureusement, vous semblez être un peu à court d'argent pour le moment." msgid "Do you wish to buy one?" msgstr "Voulez-vous en acheter un ?" msgid "%{count} / day" msgstr "%{count} / jour" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "Un tourbillon engloutit votre vaisseau. Une partie de votre armée est tombée " "par-dessus du bord." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Insultés par votre refus de leur offre, les monstres attaquent !" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "Intimidés par votre puissance, les %{monster} commencent à se disperser.\n" "Voulez-vous les rattraper et les affronter ?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "En fouillant le camp, vous découvrez des trésors cachés." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Le gardien du moulin annonce :\n" "\"Milord, j'ai travaillé très dur pour vous fournir ces ressources, revenez " "la semaine prochaine pour en avoir plus.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Le gardien du moulin annonce :\n" "\"Milord, je suis désolé, il n'y a pas de ressources disponibles " "actuellement. Veuillez réessayer la semaine prochaine.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Le gardien du moulin annonce :\n" "\"Milord, j'ai travaillé très dur pour vous fournir cet or, revenez la " "semaine prochaine pour en avoir plus.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Le gardien du moulin annonce :\n" "\"Milord, je suis désolé, il n'y a pas d'or disponible actuellement. " "Veuillez réessayer la semaine prochaine.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Vous avez trouvé un appentis abandonné.\n" "En fouillant, vous découvrez des ressources cachées à proximité." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" "L'appentis est abandonné depuis longtemps. Il n'y a rien de valeur ici." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Vous attrapez un lutin qui dort bêtement au milieu d'un amas de champignons " "magiques.\n" "En échange de sa liberté, il vous guide vers un petit pot rempli de choses " "précieuses." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Vous avez trouvé un jardin magique, le genre d'endroit où les lutins et les " "fées aiment s'ébattre, mais il n'y a personne aujourd'hui.\n" "Vous devriez peut-être réessayer la semaine prochaine." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Vous tombez sur les restes d'un malheureux aventurier." msgid "Treasure" msgstr "Trésor" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" "En cherchant dans les vêtements en lambeaux, vous trouvez l'artéfact " "'%{artifact}'." msgid "Searching through the tattered clothing, you find nothing." msgstr "En cherchant dans les vêtements en lambeaux, vous ne trouvez rien." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Vous tombez sur un vieux chariot laissé par un commerçant qui n'a pas réussi " "à atteindre un terrain sûr." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" "Malheureusement, d'autres l'ont trouvé en premier, et le wagon est vide." msgid "Searching inside, you find the %{artifact}." msgstr "En cherchant à l'intérieur, vous trouvez l'artéfact '%{artifact}'." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "" "A l'intérieur, vous trouvez une partie de la cargaison du wagon encore " "intacte." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Vous cherchez dans les débris, et vous trouvez du bois et de l'or." msgid "You search through the flotsam, and find some wood." msgstr "Vous cherchez dans les débris et trouvez du bois." msgid "You search through the flotsam, but find nothing." msgstr "Vous cherchez parmi les débris, mais ne trouvez rien." msgid "Shrine of the 1st Circle" msgstr "Sanctuaire du premier cercle" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Vous tombez sur un petit sanctuaire fréquenté par un groupe d'acolytes " "novices.\n" "En échange de votre protection, ils acceptent de vous enseigner un sort " "simple - '%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Sanctuaire du second cercle" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Vous tombez sur un sanctuaire orné, fréquenté par un groupe de frères " "corpulents.\n" "En échange de votre protection, ils acceptent de vous enseigner un sort - " "'%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Sanctuaire du troisième cercle" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Vous tombez sur un sanctuaire somptueux fréquenté par un groupe de grands " "prêtres.\n" "En échange de votre protection, ils acceptent de vous enseigner un sort " "sophistiqué : '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Malheureusement, vous n'avez pas la sagesse nécessaire pour comprendre ce " "sort et vous ne pouvez pas l'apprendre." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Malheureusement, vous connaissez déjà ce sort, il n'y a donc rien de plus à " "vous apprendre." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Malheureusement, vous n'avez pas de grimoire pour enregistrer le sort." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Vous vous approchez de la hutte et observez une sorcière à l'intérieur qui " "étudie un tome ancien sur %{skill}.\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Quand vous vous approchez, elle se retourne et concentre son unique oeil de " "verre sur vous.\n" "\"Tu sais déjà tout ce que tu mérites d'apprendre !\" hurle la sorcière. " "\"MAINTENANT, SORS DE CHEZ MOI !\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Lorsque vous vous approchez, elle se tourne et parle.\n" "\"Tu sais déjà ce que je voudrais t'enseigner. Je ne peux pas t'aider " "davantage.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Une sorcière ancienne et immortelle vivant dans une hutte avec des pattes " "d'oiseau en guise d'échasses vous enseigne %{skill} pour ses propres " "objectifs impénétrables." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" "En buvant l'eau douce, vous gagnez de la chance pour votre prochaine " "bataille." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Vous buvez à la fontaine enchantée, mais rien ne se passe." msgid "You enter the faerie ring, but nothing happens." msgstr "Vous entrez dans l'anneau des fées, mais rien ne se passe." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "En entrant dans l'anneau mystique des fées, votre armée gagne de la chance " "pour sa prochaine bataille." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Vous avez trouvé une ancienne idole de pierre usée par le temps.\n" "Elle est censée porter chance aux visiteurs, mais comme les étoiles vous " "sourient déjà, elle ne fait rien." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Vous avez trouvé une idole en pierre ancienne et usée par le temps.\n" "L'embrasser est censé porter chance, alors vous le faites. La pierre est " "très froide au toucher." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Sans aucune parole, les sirènes vous intiment de revenir plus tard pour une " "nouvelle bénédiction." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "La beauté magique et apaisante des sirènes vous atteint, vous et votre " "équipage.\n" "Pendant un court instant, vous oubliez vos soucis et savourez la beauté du " "moment.\n" "Les charmes des sirènes vous bénissent avec une chance accrue pour votre " "prochain combat." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Vous tombez sur la pyramide d'un grand et ancien roi.\n" "Vous êtes tenté d'entrer à la recherche d'un trésor, mais toutes les " "vieilles histoires mettent en garde contre les malédictions effrayantes et " "les gardiens morts-vivants.\n" "Allez-vous entrer ?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Après avoir vaincu les monstres, vous déchiffrez un ancien glyphe sur le " "mur, qui révèle le secret du sort - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Malheureusement, vous n'avez pas de grimoire pour enregistrer le sort." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Malheureusement, vous n'avez pas la sagesse nécessaire pour comprendre ce " "sort et vous ne pouvez pas l'apprendre." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Vous tombez sur la pyramide d'un grand et ancien roi.\n" "Une exploration de routine révèle que la pyramide est complètement vide." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Boire au puits est censé restaurer tous vos points de magie, mais vous êtes " "déjà au maximum." msgid "A second drink at the well in one day will not help you." msgstr "Un deuxième passage au puits en une journée ne vous aidera pas." msgid "A drink from the well has restored your spell points to maximum." msgstr "Une gorgée d'eau du puits a restauré vos points de magie au maximum." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Je suis désolé, monsieur\", dit le chef des soldats, \"mais vous savez " "déjà tout ce que nous avons à enseigner.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Les soldats vivant dans le fort vous enseignent quelques nouvelles astuces " "défensives." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Vous êtes tombé sur un camp de mercenaires qui pratiquent leurs tactiques. " "\"Vous êtes trop avancé pour nous\", dit le capitaine mercenaire. \"Nous ne " "pouvons rien enseigner de plus.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Vous êtes tombé sur un camp de mercenaires en plein entraînement tactique. " "Les mercenaires vous accueillent et vous invitent à vous entraîner avec eux." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Pars !\", aboie le sorcier, \"tu sais tout ce que je sais.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Un sorcier orc vivant dans la cabane approfondit votre connaissance de la " "magie en vous montrant comment jeter des pierres, lire des présages, et " "déchiffrer les subtilités des entrailles de poulet." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Vous avez trouvé un groupe de druides en train de prier dans l'un de leurs " "étranges édifices de pierre. En silence, les druides vous repoussent, " "indiquant qu'ils n'ont rien de nouveau à vous apprendre." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Vous avez trouvé un groupe de druides en train de prier dans l'un de leurs " "étranges édifices de pierre. En silence, ils vous enseignent de nouvelles " "façons de lancer des sorts." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Vous vous approchez disctrètement du cimetière d'anciens guerriers. Voulez-" "vous fouiller les tombes ?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Après avoir vaincu les zombies, vous passez plusieurs heures à fouiller les " "tombes sans rien trouver. Un tel acte méprisable réduit le moral de votre " "armée." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "Après avoir vaincu les zombies, vous fouillez les tombes et trouvez quelque " "chose !" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "La coque en décomposition d'un grand bateau pirate grince sinistrement " "lorsqu'elle est poussée contre les rochers. Voulez-vous fouiller l'épave ?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Vous passez plusieurs heures à fouiller les débris et ne trouvez rien. Un " "tel acte méprisable réduit le moral de votre armée." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" "Après avoir vaincu les fantômes, vous passez en revue les débris et trouvez " "quelque chose !" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "La carcasse pourrie d'un grand bateau pirate grince sinistrement lorsqu'elle " "est poussée contre les rochers. Voulez-vous fouiller le navire ?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "Après avoir vaincu les squelettes, vous passez en revue les débris et " "trouvez quelque chose !" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Vos hommes repèrent une bouée de navigation, confirmant que vous êtes sur la " "bonne voie." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Vos hommes repèrent une bouée de navigation, confirmant que vous êtes sur la " "bonne voie et augmentant leur moral." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "L'eau de l'oasis est rafraîchissante, mais n'offre aucun autre avantage. " "L'oasis pourrait vous aider à nouveau si vous livriez d'abord une bataille." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Une gorgée d'eau de l'oasis remplit vos troupes de force et leur remonte le " "moral. Vous pouvez voyager un peu plus loin aujourd'hui." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "L'eau de l'abreuvoir est rafraîchissante, mais n'offre aucun autre avantage. " "L'abreuvoir pourrait vous aider à nouveau si vous vous battiez d'abord." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Boire à l'abreuvoir donne de la force à vos troupes et leur remonte le " "moral. Vous pouvez voyager un peu plus loin aujourd'hui." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Ça ne sert à rien de prier deux fois avant une bataille. Revenez après avoir " "combattu." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Une visite et une prière au temple remontent le moral de vos troupes." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Un vieux chevalier apparaît sur les marches du belvédère. \"Je suis désolé, " "mon seigneur, je vous ai appris tout ce que je pouvais.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Un vieux chevalier apparaît sur les marches du belvédère. \"Mon seigneur, je " "vais vous apprendre tout ce que je sais pour vous aider dans vos voyages.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Vous avez tiré un survivant du naufrage d'une mort certaine dans un océan " "impitoyable. Reconnaissant, dit-il, \"Je vous donnerais un artéfact en " "récompense, mais vous êtes tout plein.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Vous avez tiré un survivant du naufrage d'une mort certaine dans un océan " "impitoyable. Reconnaissant, il vous récompense pour votre acte de " "gentillesse en vous donnant l'artéfact '%{art}'." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "Un lutin vous offre l'artéfact '%{art}' pour le petit prix de %{gold} pièces " "d'or." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Un lutin vous offre l'artéfact '%{art}' pour le petit prix de %{gold} pièces " "d'or et %{count} de %{res}." msgid "Do you wish to buy this artifact?" msgstr "Souhaitez-vous acheter cet artéfact ?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Vous essayez de payer le lutin, mais réalisez que vous ne pouvez pas vous le " "permettre. Le lutin frappe le sol avec son pied et vous ignore." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Insulté par votre refus de son offre généreuse, le lutin tape du pied sur le " "sol et vous ignore." msgid "You've found the artifact: " msgstr "Vous avez trouvé un artéfact : " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Vous avez trouvé l'humble demeure d'un ermite desséché. L'ermite vous dit " "qu'il est prêt à donner l'artéfact '%{art}' à la première personne sage " "qu'il rencontre." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Vous avez rencontré les quartiers spartiates d'un soldat à la retraite. Le " "soldat vous dit qu'il est prêt à transmettre l'artéfact '%{art}' au premier " "vrai chef qu'il rencontre." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Vous avez rencontré une personne étrange avec un chapeau et un hibou dessus. " "Il vous dit qu'il est prêt à vous donner %{art} si vous avez %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Vous tombez sur un ancien artéfact. Alors que vous l'atteignez, une bande de " "pillards bondit des broussailles pour garder le butin volé." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "À travers une clairière, vous observez un ancien artéfact. Malheureusement, " "il est gardé par un %{monster} à proximité. Voulez-vous combattre le " "%{monster} pour l'artéfact ?" msgid "Victorious, you take your prize, the %{art}." msgstr "Victorieux, vous prenez votre prix, l'artéfact '%{art}'." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "Le discernement est le meilleur aspect de la vaillance, et vous décidez " "d'éviter ce combat pour aujourd'hui." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Après avoir passé des heures à essayer de repêcher le coffre de la mer, vous " "l'ouvrez et trouvez %{gold} pièces d'or." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Après avoir passé des heures à essayer de repêcher le coffre de la mer, vous " "l'ouvrez et trouvez %{gold} pièces d'or et l'artéfact '%{art}'." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Après avoir passé des heures à essayer de repêcher le coffre de la mer, vous " "l'ouvrez, et découvrez qu'il est vide." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Après avoir parcouru la zone, vous tombez sur une cache au trésor. Vous " "pouvez prendre l'or ou distribuer l'or aux paysans pour l'expérience. " "Souhaitez-vous garder l'or ?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Après avoir parcouru la zone, vous tombez sur un coffre caché, contenant " "%{gold} pièces d'or." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Après avoir parcouru la zone, vous tombez sur un coffre caché, contenant " "l'ancien artéfact '%{art}'." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Vous tombez sur une lampe cabossée et ternie, enfouie dans la terre. Voulez-" "vous frotter la lampe ?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Vous avez pris le contrôle du laboratoire de l'alchimiste local. Il vous " "fournira %{count} fiole de mercure par jour." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Vous prenez le contrôle d'une scierie. Elle vous fournira %{count} bûches de " "bois par jour." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Vous prenez le contrôle d'une mine de fer. Elle vous fournira %{count} " "morceaux de fer par jour." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Vous prenez le contrôle d'une mine de soufre. Elle vous fournira %{count} " "morceau de soufre par jour." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Vous prenez le contrôle d'une mine de cristal. Elle vous fournira %{count} " "cristal par jour." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Vous prenez le contrôle d'une mine de gemmes. Elle vous fournira %{count} " "gemmes par jour." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Vous prenez le contrôle d'une mine d'or. Elle vous fournira %{count} pièces " "d'or par jour." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Le phare est à présent sous votre contrôle, et tous vos navires se " "déplaceront maintenant plus loin chaque jour." msgid "You gain control of a %{name}." msgstr "Vous avez capturé %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Vous tombez sur une mine d'or abandonnée. La mine semble hantée. Souhaitez-" "vous entrer ?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" "Vous battez les fantômes et êtes capable de remettre la mine en production." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Un groupe de %{monster} désirant de plus grandes gloires souhaite vous " "rallier. Acceptez-vous ?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" "En vous approchant du logement, vous remarquez qu'il n'y a personne ici." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Vous fouillez les ruines, mais les méduses qui vivaient ici ont disparu. " "Peut-être y en aura-t-il d'autres la semaine prochaine." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Vous avez trouvé des méduses vivant dans les ruines. Elles sont prêtes à " "rallier votre armée pour un prix. Voulez-vous recruter des méduses ?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Vous avez trouvé une cité des arbres de fées. Malheureusement, aucune des " "fées qui y vivent ne souhaite rallier une armée. Peut-être la semaine " "prochaine." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Certaines des fées vivant dans la cité des arbres sont prêtes à rallier " "votre armée pour un prix. Voulez-vous recruter des fées ?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Un chariot coloré appartenant aux pillards se tient là, vide. Peut-être que " "d'autres pillards seront là plus tard." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Des sons lointains de musique et de rires vous attirent vers un wagon coloré " "abritant des pillards. Souhaitez-vous que des pillards rallient votre armée ?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Un groupe de tentes en lambeaux, gonflées par le vent de sable, vous attire." "Les tentes sont inoccupées. Peut-être que d'autres nomades seront là plus " "tard." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Un groupe de tentes en lambeaux, flottant dans le vent ensablé, vous " "appelle. Souhaitez-vous que des nomades vous rallient durant votre aventure ?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "La fosse de boue bouillonne pendant une minute, puis reste immobile." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Lorsque vous vous approchez de la fosse de boue bouillonnante, des créatures " "commencent à en sortir et à se positionner autour d'elle. À l'unisson, elles " "disent : \"Mère terre aimerait vous offrir quelques-unes de ses troupes. " "Voulez-vous recruter des élémentaires de la terre ?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" "Vous entrez dans la structure de piliers de pierre blanche, et ne trouvez " "rien." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Des piliers de pierre blanche soutiennent un toit qui s'élève vers le ciel. " "En entrant dans la structure, l'air mort de l'extérieur fait place à une " "bourrasque tourbillonnante qui vous repousse presque à l'extérieur. Le " "courant d'air se matérialise en une forme à peine visible. La créature " "demande, dans ce qui ne peut être décrit que comme un fort chuchotement : " "\"Pourquoi es-tu venu ? Es-tu ici pour faire appel aux forces de l'air ?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "" "Aucun élémentaire de feu ne s'approche de vous depuis le bassin de lave." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Dans une mare ardente de lave en fusion, des élémentaires de feu se " "déplacent. Certains d'entre eux s'approchent de vous et vous proposent leurs " "services. Voulez-vous recruter des élémentaires de feu ?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Un visage se forme dans l'eau pendant un instant, puis disparaît." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Des structures cristallines projettent des ombres sur un petit bassin d'eau " "réfléchissant. Vous regardez dans la piscine, et un visage qui n'est pas le " "vôtre vous regarde en retour. Il demande : \"Voulez-vous faire appel aux " "pouvoirs de l'eau ?\"" msgid "This burial site is deathly still." msgstr "Ce site funéraire est mortellement calme." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Les esprits agités de guerriers morts depuis longtemps et cherchant leur " "dernière demeure vous proposent de vous rallier dans l'espoir de trouver la " "paix. Voulez-vous recruter des fantômes ?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "La Cité des morts est vide de vie, et vide de non-vie aussi. Peut-être que " "des morts-vivants vont emménager la semaine prochaine." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Certains macchabées vivant ici sont prêts à rallier votre armée pour un " "prix. Voulez-vous recruter des macchabées ?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Vous avez trouvé les ruines d'une ancienne cité, désormais habitée " "uniquement par des morts-vivants. Allez-vous la fouiller ?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Certains des macchabées survivants sont impressionnés par votre victoire sur " "leurs congénères et proposent de vous rallier moyennant un certain prix. " "Voulez-vous recruter des macchabées ?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Vous avez trouvé un de ces ponts sous lesquels les trolls aiment tant vivre, " "mais il n'y en a pas ici. Peut-être qu'il y en aura la semaine prochaine." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Des trolls vivant sous un pont sont prêts à rallier votre armée, mais à un " "prix. Voulez-vous recruter des trolls ?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Les trolls qui vivent sous le pont vous défient. Allez-vous les combattre ?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Il reste quelques trolls, qui se cachent sous le pont. Ils s'approchent de " "vous et proposent de rallier vos forces en tant que mercenaires. Voulez-vous " "acheter des trolls ?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "La cité des dragons n'a pas de dragons prêts à vous rallier cette semaine. " "Peut-être un dragon sera-t-il disponible la semaine prochaine." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "La cité des dragons est prête à offrir quelques dragons pour votre armée " "moyennant un certain prix. Souhaitez-vous recruter des dragons ?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Vous vous trouvez devant la cité des dragons, un lieu interdit aux simples " "humains. Voulez-vous enfreindre cette règle et défier les dragons dans un " "combat ?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Après avoir vaincu les champions dragons, les dirigeants du village " "acceptent de fournir quelques dragons à votre armée contre un certain prix. " "Souhaitez-vous recruter des dragons ?" msgid "From the observation tower, you are able to see distant lands." msgstr "" "Depuis la tour d'observation, vous êtes en mesure de voir des terres " "lointaines." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "La source ne se remplit qu'une fois par semaine, et quelqu'un est déjà venu " "cette semaine." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Boire à la source est censé vous donner deux fois vos points de magie " "normaux, mais vous avez déjà atteint ce niveau." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Une gorgée de la source remplit votre sang de magie ! Vous avez deux fois " "vos points de magie normaux en réserve." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "En vous reconnaissant, le majordome refuse de vous admettre. \"Le maître,\" " "dit-il, \"ne verra pas deux fois le même élève.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Le majordome vous admet à voir le maître de maison. Il vous forme aux quatre " "compétences qu'un héros doit connaître." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Le majordome ouvre la porte et vous regarde de haut en bas. \"Vous n'êtes ni " "assez célèbre ni assez diplomate pour être admis à voir mon maître\", " "renifle-t-il. \"Revenez quand vous vous en croirez digne.\"" msgid " and " msgstr " et " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Tous les %{monsters} que vous avez dans votre armée ont été entraînés par " "les maîtres de guerre du fort. Votre armée contient maintenant %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Une alliance inhabituelle d'ogres, d'orques et de nains propose de former " "(améliorer) toutes les troupes de ce type qui leur sont apportées. " "Malheureusement, vous n'en avez aucune avec vous." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Tous vos %{monsters} ont été transformés en %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Un forgeron travaillant à la fonderie propose de convertir en acier toutes " "les armes de piquiers et d'épéistes qui lui sont apportées. Il dit également " "qu'il connaît un procédé permettant de convertir les golems de fer en golems " "d'acier. Malheureusement, vous n'avez aucune de ces troupes dans votre " "armée, il ne peut donc pas vous aider." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Le capitaine vous regarde avec surprise et dit :\n" "\"Vous avez déjà toutes les cartes que je connais. Laissez-moi pêcher en " "paix maintenant.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Un capitaine à la retraite vivant sur cette plate-forme de pêche rénovée " "propose de vous vendre des cartes de la mer qu'il a faites dans sa jeunesse " "pour 1000 pièces d'or. Souhaitez-vous acheter ces cartes ?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Le capitaine soupire. \"Tu n'as pas assez d'argent, hein ? Tu ne peux pas " "attendre de moi que je donne mes cartes gratuitement !\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Vous tombez sur un obélisque fait d'un type de pierre que vous n'avez jamais " "vu auparavant. Lorsque vous l'étudiez, la surface lisse se transforme " "soudainement en une inscription. L'inscription est un morceau d'une ancienne " "carte perdue. Vous copiez rapidement le morceau et l'inscription disparaît " "aussi brusquement qu'elle est apparue." msgid "You have already been to this obelisk." msgstr "Vous avez déjà visité cet obélisque." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "À votre approche, l'arbre ouvre ses yeux avec joie. \"C'est bon de te voir, " "mon élève. J'espère que mes enseignements t'ont aidé.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "À votre approche, l'arbre ouvre ses yeux avec joie. \"Ahh, un aventurier ! " "Permettez-moi de vous enseigner un peu de ce que j'ai appris au cours des " "âges.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "À votre approche, l'arbre ouvre ses yeux avec joie." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ahh, un aventurier ! Je serai heureux de vous enseigner un peu de ce que " "j'ai appris au cours des âges pour un prix de %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Enterrez-les juste autour de mes racines.)" msgid "Tears brim in the eyes of the tree." msgstr "Des larmes coulent dans les yeux de l'arbre." msgid "\"I need %{count} %{res}.\"" msgstr "\"J'ai besoin de %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "il chuchote. (sniff) \"Eh bien, reviens quand tu pourras me payer.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Niché parmi les arbres se trouve un devin aveugle. Lorsque vous lui " "expliquez l'intention de votre voyage, le devin active sa boule de cristal, " "vous permettant de voir les forces et les faiblesses de vos adversaires." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "L'entrée de la grotte est sombre, et une odeur nauséabonde et sulfureuse " "provient de la bouche de la grotte. Allez-vous entrer ?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "À part les preuves d'une terrible bataille, la grotte est vide." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Vous trouvez un démon puissant et grotesque dans la grotte. \"Aujourd'hui, " "râpe-t-il, vous allez vous battre et sûrement mourir. Mais je vais vous " "donner le choix du décès. Vous pouvez me combattre, ou vous pouvez combattre " "mes serviteurs. Préférez-vous combattre mes serviteurs ?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Le Démon pousse son cri de défi et attaque ! Après une courte bataille " "désespérée, vous tuez le monstre et recevez %{exp} points d'expérience." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Le Démon pousse son cri de défi et attaque ! Après une courte bataille " "désespérée, vous tuez le monstre et recevez %{exp} points d'expérience et " "%{count} pièces d'or." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Le Démon pousse son cri de défi et attaque ! Après une courte bataille " "désespérée, vous tuez le monstre et trouvez l'artéfact '%{art}' à l'arrière " "de la grotte." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Voyant que vous n'avez pas %{count} pièces d'or, le démon vous coupe avec " "ses griffes, et la dernière chose que vous voyez est une brume rouge." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Le démon saute sur vous et a ses griffes à votre gorge avant même que vous " "puissiez tirer votre épée. \"Votre vie est à moi\", dit-il. \"Je vous la " "céderai pour %{count} pièces d'or.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "En battant les serviteurs du démon, vous trouvez une cache dissimulée avec " "%{count} pièces d'or." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Lorsque vous entrez dans la tour de l'alchimiste, un homme boiteux et " "grisonnant portant un manteau brun se dirige vers vous." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Il vérifie votre sac, et voit que vous avez un objet maudit." msgstr[1] "" "Il vérifie votre sac, et voit que vous avez %{count} objets maudits." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "Pour %{gold} pièces d'or, l'alchimiste l'enlèvera pour vous. Payez-vous ?" msgstr[1] "" "Pour %{gold} pièces d'or, l'alchimiste les enlèvera pour vous. Payez-vous ?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Après avoir consenti à payer la quantité d'or demandée, l'alchimiste prend " "l'artéfact maudit et le jette dans son chaudron magique." msgstr[1] "" "Après avoir consenti à payer la quantité d'or demandée, l'alchimiste prend " "les artéfacts maudits et les jette dans son chaudron magique." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Vous entendez une voix derrière la porte fermée : \"Vous n'avez pas assez " "d'or pour payer mes services.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Vous entendez une voix venant des hauteurs de la tour : \"Allez-vous-en ! Je " "ne peux pas vous aider !\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Le palefrenier en chef vous parle : \"C'est un beau cheval que vous avez. Je " "crains que nous ne puissions pas vous donner mieux, mais les chevaux que " "votre cavalerie monte semblent être de mauvaise race. Nous avons beaucoup de " "chevaux de guerre entraînés qui aideraient grandement vos cavaliers. " "J'insiste pour que vous les preniez.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Alors que vous approchez des écuries, le palefrenier en chef apparaît, " "conduisant un beau cheval de guerre. \"Ce coursier vous aidera à accélérer " "vos déplacements. Hélas, il sera fatigué dans une semaine. Vous devez " "également me permettre de donner de meilleurs chevaux à vos soldats montés, " "leurs chevaux sont en mauvais état et faibles.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Le palefrenier en chef s'approche de vous et vous dit : \"Vous avez déjà un " "bon cheval, et vous n'avez pas de cavalerie inexpérimentée qui pourrait se " "servir de nos chevaux de guerre entraînés.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Alors que vous approchez des écuries, le palefrenier en chef apparaît, " "conduisant un beau cheval de guerre. \"Ce destrier vous aidera à accélérer " "vos déplacements. Hélas, son endurance diminuera avec beaucoup de " "chevauchées, et vous devrez revenir pour une nouvelle monture dans une " "semaine. Nous avons aussi beaucoup de beaux chevaux de guerre qui pourraient " "profiter aux soldats montés, mais vous n'en avez aucun que nous puissions " "aider.\"" msgid "The Arena guards turn you away." msgstr "Les gardes de l'arène vous repoussent." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Vous demandez à votre équipage de se boucher les oreilles avec de la cire " "avant que le chant sinistre des sirènes n'ait la moindre chance de les " "attirer vers une mort certaine." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Alors que les sirènes chantent leur sinistre chanson, votre petite armée " "déterminée parvient à surmonter l'envie de plonger tête baissée dans la mer." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Un chant sinistre et plaintif émane des sirènes perchées sur les rochers. " "Plusieurs membres de votre équipage tombent sous son charme et plongent dans " "l'eau où ils se noient. Vous êtes maintenant plus sage pour cette visite, et " "gagnez %{exp} d'expérience." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Dans une démonstration d'audace éblouissante, vous vous introduisez dans la " "prison locale et libérez le héros qui y est emprisonné, qui, en retour, " "promet d'être loyal à votre cause." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Vous avez déjà %{count} héros, et vous devez malheureusement laisser le " "prisonnier dans cette prison languir dans l'agonie pendant des jours " "indicibles." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Vous entrez dans une cabane branlante et parlez au magicien qui y vit. Il " "vous parle de lieux proches et lointains qui peuvent vous aider dans vos " "voyages." msgid "This eye seems to be intently studying its surroundings." msgstr "Cet oeil semble étudier attentivement son environnement." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" "Vous tombez sur un sphinx géant. Le sphinx reste étrangement silencieux." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"J'ai une énigme pour vous\", dit le sphinx. \"Répondez correctement, et " "vous serez récompensé. Répondez incorrectement, et vous serez mangé. " "Acceptez-vous de relever le défi ?\"" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Le Sphinx vous pose l'énigme suivante :\n" "\n" "'" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" "'\n" "\n" "Votre réponse ?" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Vous avez mal deviné\", dit le sphinx en souriant. Le sphinx vous frappe " "d'un coup de patte, vous faisant tomber au sol. Un autre coup rend le monde " "noir, et vous ne savez plus rien." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Le sphinx soupire, l'air un peu déçu. \"Vous avez répondu à mon énigme, " "voici votre récompense. Maintenant, partez.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Une barrière magique se dresse devant vous, bloquant votre chemin. Les runes " "sur l'arche disent,\n" "\"Prononcez la clé et vous pourrez passer.\"\n" "Lorsque vous prononcez le mot magique, la barrière lumineuse se dissout dans " "le néant." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Une barrière magique se dresse devant vous, bloquant votre chemin. Les runes " "sur l'arche disent :\n" "\"Prononcez le mot clé et vous pouvez passer.\"\n" "Vous parlez, mais rien ne se passe." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Vous entrez dans la tente et voyez une vieille femme regarder fixement un " "joyau magique. Elle relève son regard et dit :\n" "\"Au cours de mes voyages, j'ai beaucoup appris sur le sujet de la magie " "arcane. Un grand oracle m'a appris son talent. J'ai la réponse que vous " "cherchez.\"" msgid "No spell book is present." msgstr "Le grimoire n'est pas présent." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Ce sort coûte %{mana} points de magie. Vous n'avez pas assez de points de " "magie, vous ne pouvez donc pas lancer le sort." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Ce sort coûte %{mana} points de magie. Vous n'avez que %{point} points de " "magie, vous ne pouvez donc pas lancer le sort." msgid "The spell was not found." msgstr "Sort introuvable." msgid "Only heroes can cast this spell." msgstr "Seuls les héros peuvent lancer ce sort." msgid "This hero is not able to cast adventure spells." msgstr "Ce héros ne peut pas lancer de sort d'aventure." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Votre héros est trop fatigué pour lancer ce sort aujourd'hui. Essayez à " "nouveau demain." msgid "This spell cannot be cast on a boat." msgstr "Ce sort ne peut pas être lancé en mer." msgid "This spell can only be cast near an ocean." msgstr "Ce sort ne peut être lancé qu'à proximité d'une mer." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Il n'y a pas de bâteau disponible ni de mer adjacente au héros où ce " "sortilège peut fonctionner." msgid "There are no boats available for this spell." msgstr "Il n'y a pas de bateau disponible pour lancer ce sort." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Il n'y a pas de mer à proximité du héros, vous ne pouvez donc pas lancer ce " "sort." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Vous ne possédez aucun village ou château qui ne soit pas occupé par un " "héros, vous ne pouvez donc pas lancer ce sort." msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Ce héros est déjà dans un village ou un château, le sort n'a donc aucun " "effet." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Le village le plus proche est %{town}.\n" "\n" "Ce village est occupé par votre héros %{hero}." msgid "This spell is already in effect." msgstr "Ce sort est déjà actif." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Aucun adversaire n'a ni ne peut plus avoir de héros sous son commandement. " "Lancer ce sort n'aura aucun effet." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Aucun adversaire n'a de héros sous son commandement à ce moment. Lancer ce " "sort n'aura aucun effet." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Vous devez être à maximum %{count} de distance d'un monstre pour que le sort " "visions fonctionne." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Vous devez être à l'entrée d'une mine (les scieries et les alchimistes ne " "comptent pas) pour lancer ce sort." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Vous devez d'abord vaincre les fantômes qui gardent la mine pour lancer ce " "sort." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Il y a déjà au moins autant d'élémentaires qui gardent la mine que ce héros " "peut invoquer. Lancer ce sort n'aura aucun effet." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name} le %{race} (niveau %{level})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} (niveau %{level})" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{name} le %{race} (niveau %{level})" #, fuzzy msgid "Hero race:" msgstr "Fenêtre d'informations du héros" msgid "Are you sure you want to dismiss this Hero?" msgstr "Voulez-vous vraiment renvoyer ce héros ?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Voir les infos de l'expérience" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Points de magie" msgid "View Spell Points Info" msgstr "Voir les infos sur les points de magie" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Perdre le héros : %{name}." #, fuzzy msgid "Click to change race." msgstr "Cliquez pour afficher le village suivant." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "La formation de combat 'dispersée' propage les troupes du héros du haut vers " "le bas du champ de bataille, avec au moins un espace vide entre chaque " "troupe." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "La formation de combat 'groupée' regroupe les troupes du héros au centre du " "champ de bataille, du côté du héros." msgid "Exit Hero Screen" msgstr "Quitter la fenêtre d'informations du héros" msgid "You cannot dismiss a hero in a castle" msgstr "Vous ne pouvez pas renvoyer un héros dans un château" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Le renvoi de %{name} le %{race} est interdit par le scénario" msgid "Dismiss %{name} the %{race}" msgstr "Renvoyer %{name} le %{race}" msgid "Show previous hero" msgstr "Afficher le héros précédent" msgid "Show next hero" msgstr "Afficher le héros suivant" msgid "Set army combat formation to 'Spread'" msgstr "Utiliser la formation de combat 'dispersée'" msgid "Set army combat formation to 'Grouped'" msgstr "Utiliser la formation de combat 'groupée'" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Cliquez ici pour sélectionner cette couleur." msgid "Blood Morale" msgstr "Moral de sang" msgid "%{morale} Morale" msgstr "Moral %{morale}" msgid "%{luck} Luck" msgstr "Chance %{luck}" msgid "Current Luck Modifiers:" msgstr "Modificateurs de chance actuels :" msgid "Current Morale Modifiers:" msgstr "Modificateurs de moral actuels :" msgid "Entire army is undead, so morale does not apply." msgstr "" "L'armée entière est composée de morts-vivants, donc le moral ne s'applique " "pas." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Expérience actuelle %{exp1}.\n" " Niveau suivant %{exp2}." msgid "million|M" msgstr "M" msgid "Level %{level}" msgstr "Niveau %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} dispose actuellement de %{point} points de magie sur un maximum de " "%{max}. Le nombre maximum de points de magie est égal à 10 fois le niveau de " "Connaissance. Il est toutefois possible de dépasser ce maximum dans des cas " "particuliers grâce à des événements spéciaux." msgid "%{name1} meets %{name2}" msgstr "Rencontre entre %{name1} et %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Les héros ennemis sont désormais parfaitement identifiables." msgid "Identify Hero" msgstr "Identifier héros" msgid "Select town to port to." msgstr "Sélectionnez la destination." msgid "Town Portal" msgstr "Portes du village" msgid "The creatures are willing to join us!" msgstr "Les créatures sont prêtes à nous rallier !" msgid "All the creatures will join us..." msgstr "Toutes les créatures vont nous rallier..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "La créature va nous rallier..." msgstr[1] "%{count} créatures vont nous rallier..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" " pour une somme de %{gold} or." msgid "These weak creatures will surely flee before us." msgstr "Ces faibles créatures vont sûrement fuir devant nous." msgid "I fear these creatures are in the mood for a fight." msgstr "Je crains que ces créatures ne soient d'humeur à se battre." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "L'Attaque du héros est ajoutée á la statistique d'attaque de chacune de ses " "créatures." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "La Défense du héros est ajoutée á la statistique de défense de chacune de " "ses créatures." msgid "The hero's spell power determines the duration or power of a spell." msgstr "La Puissance du héros détermine la durée ou la puissance de ses sorts." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "La Connaissance du héros détermine le nombre de points de magie dont dispose " "ce héros. Dans des circonstances normales, un héros est limité à 10 points " "de magie par niveau de Connaissance." msgid "Current Modifiers:" msgstr "Modificateurs actuels :" msgid "skill|Basic" msgstr "Principes" msgid "skill|Advanced" msgstr "Avancé" msgid "skill|Expert" msgstr "Expert" msgid "Pathfinding" msgstr "Orientation" msgid "Archery" msgstr "Archerie" msgid "Logistics" msgstr "Logistique" msgid "Scouting" msgstr "Reconnaiss." msgid "Diplomacy" msgstr "Diplomatie" msgid "Navigation" msgstr "Navigation" msgid "Leadership" msgstr "Charisme" msgid "Wisdom" msgstr "Sagesse" msgid "Mysticism" msgstr "Mysticisme" msgid "Ballistics" msgstr "Balistique" msgid "Eagle Eye" msgstr "Oeil d'aigle" msgid "Necromancy" msgstr "Nécromancie" msgid "Estates" msgstr "Finances" msgid "Advanced Archery" msgstr "Archerie avancée" msgid "Advanced Pathfinding" msgstr "Orientation avancée" msgid "Basic Archery" msgstr "Principes d'archerie" msgid "Basic Pathfinding" msgstr "Principes d'orientation" msgid "Expert Pathfinding" msgstr "Expert en orientation" msgid "Advanced Logistics" msgstr "Logistique avancée" msgid "Basic Logistics" msgstr "Principes de logistique" msgid "Basic Scouting" msgstr "Principes de reconnaissance" msgid "Expert Archery" msgstr "Expert en archerie" msgid "Expert Logistics" msgstr "Expert en logistique" msgid "Advanced Diplomacy" msgstr "Diplomatie avancée" msgid "Advanced Scouting" msgstr "Reconnaissance avancée" msgid "Basic Diplomacy" msgstr "Principes de diplomatie" msgid "Expert Diplomacy" msgstr "Expert en diplomatie" msgid "Expert Scouting" msgstr "Expert en reconnaissance" msgid "Advanced Leadership" msgstr "Charisme avancée" msgid "Advanced Navigation" msgstr "Navigation avancée" msgid "Basic Leadership" msgstr "Principes de charisme" msgid "Basic Navigation" msgstr "Principes de navigation" msgid "Expert Navigation" msgstr "Expert en navigation" msgid "Advanced Wisdom" msgstr "Sagesse avancée" msgid "Basic Mysticism" msgstr "Principes de mysticisme" msgid "Basic Wisdom" msgstr "Principes de sagesse" msgid "Expert Leadership" msgstr "Expert en charisme" msgid "Expert Wisdom" msgstr "Expert en sagesse" msgid "Advanced Luck" msgstr "Chance avancée" msgid "Advanced Mysticism" msgstr "Mysticisme avancé" msgid "Basic Luck" msgstr "Principes de chance" msgid "Expert Luck" msgstr "Expert en chance" msgid "Expert Mysticism" msgstr "Expert en mysticisme" msgid "Advanced Ballistics" msgstr "Balistique avancée" msgid "Advanced Eagle Eye" msgstr "Oeil d'aigle avancé" msgid "Basic Ballistics" msgstr "Principes de balistique" msgid "Basic Eagle Eye" msgstr "Principes d'oeil d'aigle" msgid "Expert Ballistics" msgstr "Expert en balistique" msgid "Advanced Necromancy" msgstr "Nécromancie avancée" msgid "Basic Estates" msgstr "Principes de finances" msgid "Basic Necromancy" msgstr "Principes de nécromancie" msgid "Expert Eagle Eye" msgstr "Expert en oeil d'aigle" msgid "Expert Necromancy" msgstr "Expert en nécromancie" msgid "Advanced Estates" msgstr "Finances avancées" msgid "Expert Estates" msgstr "Expert en finances" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} réduit la pénalité de mouvement pour les terrains accidentés de " "%{count} pour cent." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} élimine la pénalité de mouvement pour terrain accidenté." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} augmente de %{count} % les dégâts infligés par les créatures qui " "attaquent à distance dans l'armée du héros, et élimine la pénalité de " "%{penalty} pour cent pour les troupes qui tirent au-delà des obstacles (par " "exemple, les murs d'un château)." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" "%{skill} augmente les points de mouvement du héros de %{count} pour cent." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} augmente le champ de vision du héros d'une case." msgstr[1] "%{skill} augmente le champ de vision du héros de %{count} cases." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} permet au héros de négocier avec des monstres plus faibles que son " "armée." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Environ %{count} pour cent des créatures peuvent vous proposer de rallier le " "héros." msgid "All of the creatures may offer to join the hero." msgstr "Toutes les créatures peuvent proposer de rallier le héros." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "Le coût de la reddition est reduite à %{percent} pour cent du coût total des " "troupes dans l'armée du héros." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "%{skill} augmente les points de mouvement du héros sur l'eau de %{count} " "pour cent." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} augmente le moral des troupes du héros de %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} permet au héros d'apprendre des sorts de troisième niveau." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} permet au héros d'apprendre des sorts de quatrième niveau." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} permet au héros d'apprendre des sorts de cinquième niveau." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} octroie un point de magie par jour au héros." msgstr[1] "%{skill} octroie %{count} points de magie par jour au héros." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} augmente la chance du héros de %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} donne aux tirs de catapulte du héros plus de chance de toucher et " "d'infliger des dégâts aux murs du château." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} donne à la catapulte du héros un tir supplémentaire, et chaque tir " "a plus de chance de toucher et d'endommager les murs du château." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} donne à la catapulte du héros un tir supplémentaire, et chaque tir " "détruit automatiquement n'importe quel mur, sauf le mur fortifié d'un " "château de chevalier." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} donne au héros %{count} de chance d'apprendre un sort ennemi de 1er " "ou 2eme niveau utilisé lors d'un combat." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} donne au héros %{count} de chance d'apprendre un sort de 3eme " "niveau (ou inférieur) utilisé lors d'un combat." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} donne au héros %{count} de chance d'apprendre un sort de 4eme " "niveau (ou inférieur) utilisé lors d'un combat." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} permet à %{count} pour cent des créatures tuées au combat d'être " "réanimées en tant que squelettes." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "Le héros produit %{count} pièces d'or par jour en recettes fiscales." msgid "Blue" msgstr "Bleu" msgid "Green" msgstr "Vert" msgid "Red" msgstr "Rouge" msgid "Yellow" msgstr "Jaune" msgid "Orange" msgstr "Orange" msgid "Purple" msgstr "Violet" msgid "barrier|Aqua" msgstr "turquoise" msgid "barrier|Blue" msgstr "bleue" msgid "barrier|Brown" msgstr "marron" msgid "barrier|Gold" msgstr "dorée" msgid "barrier|Green" msgstr "verte" msgid "barrier|Orange" msgstr "orange" msgid "barrier|Purple" msgstr "violette" msgid "barrier|Red" msgstr "rouge" msgid "tent|Aqua" msgstr "turquoise" msgid "tent|Blue" msgstr "bleue" msgid "tent|Brown" msgstr "marron" msgid "tent|Gold" msgstr "dorée" msgid "tent|Green" msgstr "verte" msgid "tent|Orange" msgstr "orange" msgid "tent|Purple" msgstr "violette" msgid "tent|Red" msgstr "rouge" msgid "Experience" msgstr "Expérience" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "L'expérience permet à votre héros de monter de niveau, et ainsi d'améliorer " "ses statistiques et ses compétences." msgid "Hero/Stats" msgstr "Héros/Stats" msgid "Skills" msgstr "Compétences" msgid "Town/Castle" msgstr "Village/Château" msgid "Garrison" msgstr "Garnison" msgid "Gold Per Day:" msgstr "Or par jour :" msgid "View Heroes." msgstr "Voir héros." msgid "Towns/Castles" msgstr "Villages/Châteaux" msgid "View Towns and Castles." msgstr "Voir villages et châteaux." msgid "luck|Cursed" msgstr "Maudite" msgid "luck|Awful" msgstr "Affreuse" msgid "luck|Bad" msgstr "Défavorable" msgid "luck|Normal" msgstr "Normale" msgid "luck|Good" msgstr "Favorable" msgid "luck|Great" msgstr "Superbe" msgid "luck|Irish" msgstr "Maximale" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "La malchance s'abat parfois sur les troupes du héros au combat, leurs " "attaques ne faisant que la moitié des dégâts." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "La chance neutre signifie que les troupes du héros n'auront jamais de chance " "ou de malchance en attaquant l'ennemi." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "La chance permet parfois aux troupes du héros d'obtenir des attaques " "chanceuses (dégâts doublés) au combat." msgid "morale|Treason" msgstr "Traître" msgid "morale|Awful" msgstr "Désastreux" msgid "morale|Poor" msgstr "Médiocre" msgid "morale|Normal" msgstr "Normal" msgid "morale|Good" msgstr "Bon" msgid "morale|Great" msgstr "Superbe" msgid "morale|Blood!" msgstr "Sanglant !" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "Un moral négatif peut provoquer, pour une troupe, une perte de tour de jeu " "lors d'un combat." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Un moral neutre signifie que les troupes du héros ne seront jamais bénies " "avec des attaques supplémentaires ni ne se figeront au combat." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "Un moral positif peut donner aux troupes du héros l'occasion de rejouer un " "tour supplémentaires en combat." msgid "Knight" msgstr "Chevalier" msgid "Barbarian" msgstr "Barbare" msgid "Sorceress" msgstr "Sorcière" msgid "Warlock" msgstr "Mage" msgid "Wizard" msgstr "Magicien" msgid "Necromancer" msgstr "Nécromant" msgid "Multi" msgstr "Multi" msgid "doubleLined|Knight" msgstr "Chevalier" msgid "doubleLined|Barbarian" msgstr "Barbare" msgid "doubleLined|Sorceress" msgstr "Sorcière" msgid "doubleLined|Warlock" msgstr "Mage" msgid "doubleLined|Wizard" msgstr "Magicien" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Nécro-\n" "mant" msgid "doubleLinedRace|Multi" msgstr "Multi" msgid "doubleLinedRace|Random" msgstr "Aléatoire" msgid "speed|Standing" msgstr "Immobile" msgid "speed|Crawling" msgstr "Rampante" msgid "speed|Very Slow" msgstr "Très lente" msgid "speed|Slow" msgstr "Lente" msgid "speed|Average" msgstr "Moyenne" msgid "speed|Fast" msgstr "Rapide" msgid "speed|Very Fast" msgstr "Très rapide" msgid "speed|Ultra Fast" msgstr "Ultra rapide" msgid "speed|Blazing" msgstr "Foudroyante" msgid "speed|Instant" msgstr "Téléportée" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "de l'écureuil" msgid "week|Rabbit" msgstr "du lapin" msgid "week|Gopher" msgstr "de la marmotte" msgid "week|Badger" msgstr "du blaireau" msgid "week|Rat" msgstr "du rat" msgid "week|Eagle" msgstr "de l'aigle" msgid "week|Weasel" msgstr "de la belette" msgid "week|Raven" msgstr "du corbeau" msgid "week|Mongoose" msgstr "de la mangouste" msgid "week|Dog" msgstr "du chien" msgid "week|Aardvark" msgstr "de l'oryctérope" msgid "week|Lizard" msgstr "du lézard" msgid "week|Tortoise" msgstr "de la tortue" msgid "week|Hedgehog" msgstr "du hérisson" msgid "week|Condor" msgstr "du condor" msgid "week|Ant" msgstr "de la fourmi" msgid "week|Grasshopper" msgstr "de la sauterelle" msgid "week|Dragonfly" msgstr "de la libellule" msgid "week|Spider" msgstr "de l'araignée" msgid "week|Butterfly" msgstr "du papillon" msgid "week|Bumblebee" msgstr "du bourdon" msgid "week|Locust" msgstr "du criquet" msgid "week|Earthworm" msgstr "du ver" msgid "week|Hornet" msgstr "du frelon" msgid "week|Beetle" msgstr "de la coccinelle" msgid "week|PLAGUE" msgstr "de la PESTE" msgid "week|Unnamed" msgstr "sans nom" msgid "Desert" msgstr "Désert" msgid "Snow" msgstr "Neige" msgid "Wasteland" msgstr "Terrain vague" msgid "Beach" msgstr "Plage" msgid "Lava" msgstr "Lave" msgid "Dirt" msgstr "Boue" msgid "Grass" msgstr "Herbe" msgid "Ocean" msgstr "Océan" msgid "maps|Small" msgstr "Petite" msgid "maps|Medium" msgstr "Moyenne" msgid "maps|Large" msgstr "Grande" msgid "maps|Extra Large" msgstr "Très grande" msgid "maps|Custom Size" msgstr "Taille personnalisée" msgid "Ore Mine" msgstr "Mine de fer" msgid "Sulfur Mine" msgstr "Mine de soufre" msgid "Crystal Mine" msgstr "Mine de cristal" msgid "Gems Mine" msgstr "Mine de gemmes" msgid "Gold Mine" msgstr "Mine d'or" msgid "Mine" msgstr "Mine" msgid "Burma shave." msgstr "Burma shave." msgid "Next sign 50 miles." msgstr "Panneau suivant : 50 miles." msgid "See Rock City." msgstr "Visitez Rock City." msgid "This space for rent." msgstr "Espace à louer." msgid "No object" msgstr "Aucun objet" msgid "Alchemist Lab" msgstr "Laboratoire d'alchimiste" msgid "Sign" msgstr "Panneau" msgid "Buoy" msgstr "Bouée" msgid "Skeleton" msgstr "Squelette" msgid "Daemon Cave" msgstr "Grotte de démon" msgid "Treasure Chest" msgstr "Coffre au trésor" msgid "Faerie Ring" msgstr "Anneau des fées" msgid "Campfire" msgstr "Feu de camp" msgid "Fountain" msgstr "Fontaine" msgid "Gazebo" msgstr "Belvédère" msgid "Genie Lamp" msgstr "Lampe ancienne" msgid "Archer's House" msgstr "Demeure des archers" msgid "Goblin Hut" msgstr "Paillote" msgid "Dwarf Cottage" msgstr "Cottage des nains" msgid "Peasant Hut" msgstr "Grange" msgid "Stables" msgstr "Écurie" msgid "Alchemist's Tower" msgstr "Tour d'alchimiste" msgid "Event" msgstr "Événement" msgid "Dragon City" msgstr "Cité des dragons" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Phare" msgstr[1] "Phares" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Roue hydraulique" msgstr[1] "Roue hydraulique" msgid "Monster" msgstr "Monstre" msgid "Obelisk" msgstr "Obélisque" msgid "Oasis" msgstr "Oasis" msgid "Resource" msgstr "Ressource" msgid "Sawmill" msgstr "Scierie" msgid "Oracle" msgstr "Oracle" msgid "Shrine of the First Circle" msgstr "Sanctuaire du premier cercle" msgid "Shipwreck" msgstr "Épave" msgid "Sea Chest" msgstr "Coffre au trésor englouti" msgid "Desert Tent" msgstr "Tente de désert" msgid "Stone Liths" msgstr "Portail magique" msgid "Wagon Camp" msgstr "Roulotte" msgid "Hut of the Magi" msgstr "Hutte des mages" msgid "Whirlpool" msgstr "Tourbillon" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Moulin à vent" msgstr[1] "Moulins à vent" msgid "Mermaid" msgstr "Nymphe" msgid "Boat" msgstr "Navire" msgid "Random Ultimate Artifact" msgstr "Ultime artéfact aléatoire" msgid "Random Artifact" msgstr "Artéfact aléatoire" msgid "Random Resource" msgstr "Ressource aléatoire" msgid "Random Monster" msgstr "Monstre aléatoire" msgid "Random Town" msgstr "Village aléatoire" msgid "Random Castle" msgstr "Château aléatoire" msgid "Eye of the Magi" msgstr "Oeil des mages" msgid "Random Monster - weak" msgstr "Monstre aléatoire - faible" msgid "Random Monster - medium" msgstr "Monstre aléatoire - moyen" msgid "Random Monster - strong" msgstr "Monstre aléatoire - fort" msgid "Random Monster - very strong" msgstr "Monstre aléatoire - très fort" msgid "Hero" msgstr "Héros" msgid "Nothing Special" msgstr "Rien de spécial" msgid "Mossy Rock" msgstr "Mousse et rochers" msgid "Watch Tower" msgstr "Tour de guet" msgid "Tree House" msgstr "Cabane" msgid "Tree City" msgstr "Cité des arbres" msgid "Ruins" msgstr "Ruines" msgid "Fort" msgstr "Fort" msgid "Abandoned Mine" msgstr "Mine abandonnée" msgid "Sirens" msgstr "Sirènes" msgid "Standing Stones" msgstr "Pierres dressées" msgid "Idol" msgstr "Idole" msgid "Tree of Knowledge" msgstr "Arbre de connaissance" msgid "Witch Doctor's Hut" msgstr "Chaumière de sorcier" msgid "Temple" msgstr "Temple" msgid "Hill Fort" msgstr "Fort sur la colline" msgid "Halfling Hole" msgstr "Repaire des galopins" msgid "Mercenary Camp" msgstr "Camp de mercenaires" msgid "Shrine of the Second Circle" msgstr "Sanctuaire du second cercle" msgid "Shrine of the Third Circle" msgstr "Sanctuaire du troisième cercle" msgid "City of the Dead" msgstr "Cité des morts" msgid "Sphinx" msgstr "Sphinx" msgid "Wagon" msgstr "Charrette" msgid "Tar Pit" msgstr "Fosse de goudron" msgid "Artesian Spring" msgstr "Puits artésien" msgid "Troll Bridge" msgstr "Pont des trolls" msgid "Watering Hole" msgstr "Point d'eau" msgid "Witch's Hut" msgstr "Cabane de la sorcière" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Appentis" msgid "Magellan's Maps" msgstr "Cartes de Magellan" msgid "Flotsam" msgstr "Débris" msgid "Derelict Ship" msgstr "Navire abandonné" msgid "Shipwreck Survivor" msgstr "Survivant du naufrage" msgid "Bottle" msgstr "Bouteille" msgid "Magic Well" msgstr "Puits magique" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Jardin magique" msgstr[1] "Jardins magiques" msgid "Observation Tower" msgstr "Tour d'observation" msgid "Freeman's Foundry" msgstr "Fonderie du citoyen" msgid "Reefs" msgstr "Récifs" msgid "Volcano" msgstr "Volcan" msgid "Flowers" msgstr "Fleurs" msgid "Rock" msgstr "Caillou" msgid "Water Lake" msgstr "Lac" msgid "Mandrake" msgstr "Mandragore" msgid "Dead Tree" msgstr "Arbre mort" msgid "Stump" msgstr "Souche" msgid "Crater" msgstr "Cratère" msgid "Cactus" msgstr "Cactus" msgid "Mound" msgstr "Monticule" msgid "Dune" msgstr "Dune" msgid "Lava Pool" msgstr "Lac de lave" msgid "Shrub" msgstr "Arbuste" msgid "Barrow Mounds" msgstr "Tumulus" msgid "Random Artifact - Treasure" msgstr "Artéfact aléatoire - trésor" msgid "Random Artifact - Minor" msgstr "Artéfact aléatoire - mineur" msgid "Random Artifact - Major" msgstr "Artéfact aléatoire - majeur" msgid "Barrier" msgstr "Barrière magique" msgid "Traveller's Tent" msgstr "Tente de voyageur" msgid "Jail" msgstr "Prison" msgid "Fire Summoning Altar" msgstr "Autel d'invocation du feu" msgid "Air Summoning Altar" msgstr "Autel d'invocation de l'air" msgid "Earth Summoning Altar" msgstr "Autel d'invocation de la terre" msgid "Water Summoning Altar" msgstr "Autel d'invocation de l'eau" msgid "Swampy Lake" msgstr "Lac marécageux" msgid "Frozen Lake" msgstr "Lac gélé" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "Monstres inconnus" msgid "Unknown Monster" msgstr "Monstre inconnu" msgid "Peasant" msgstr "Paysan" msgid "Peasants" msgstr "Paysans" msgid "Archer" msgstr "Archer" msgid "Archers" msgstr "Archers" msgid "Ranger" msgstr "Ranger" msgid "Rangers" msgstr "Rangers" msgid "Pikeman" msgstr "Fantassin" msgid "Pikemen" msgstr "Fantassins" msgid "Veteran Pikeman" msgstr "Fantassin vétéran" msgid "Veteran Pikemen" msgstr "Fantassins vétérans" msgid "Swordsman" msgstr "Spadassin" msgid "Swordsmen" msgstr "Spadassins" msgid "Master Swordsman" msgstr "Maître spadassin" msgid "Master Swordsmen" msgstr "Maîtres spadassins" msgid "Cavalries" msgstr "Cavaliers" msgid "Cavalry" msgstr "Cavalier" msgid "Champion" msgstr "Champion" msgid "Champions" msgstr "Champions" msgid "Paladin" msgstr "Paladin" msgid "Paladins" msgstr "Paladins" msgid "Crusader" msgstr "Grand paladin" msgid "Crusaders" msgstr "Grands paladins" msgid "Goblin" msgstr "Gobelin" msgid "Goblins" msgstr "Gobelins" msgid "Orc" msgstr "Orc" msgid "Orcs" msgstr "Orcs" msgid "Orc Chief" msgstr "Chef orc" msgid "Orc Chiefs" msgstr "Chefs orcs" msgid "Wolf" msgstr "Loup" msgid "Wolves" msgstr "Loups" msgid "Ogre" msgstr "Ogre" msgid "Ogres" msgstr "Ogres" msgid "Ogre Lord" msgstr "Grand ogre" msgid "Ogre Lords" msgstr "Grands ogres" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Trolls" msgid "War Troll" msgstr "Troll guerrier" msgid "War Trolls" msgstr "Trolls guerriers" msgid "Cyclopes" msgstr "Cyclopes" msgid "Cyclops" msgstr "Cyclope" msgid "Sprite" msgstr "Fée" msgid "Sprites" msgstr "Fées" msgid "Dwarf" msgstr "Nain" msgid "Dwarves" msgstr "Nains" msgid "Battle Dwarf" msgstr "Nain guerrier" msgid "Battle Dwarves" msgstr "Nains guerriers" msgid "Elf" msgstr "Elfe" msgid "Elves" msgstr "Elfes" msgid "Grand Elf" msgstr "Grand elfe" msgid "Grand Elves" msgstr "Grands elfes" msgid "Druid" msgstr "Druide" msgid "Druids" msgstr "Druides" msgid "Greater Druid" msgstr "Grand druide" msgid "Greater Druids" msgstr "Grands druides" msgid "Unicorn" msgstr "Licorne" msgid "Unicorns" msgstr "Licornes" msgid "Phoenix" msgstr "Phénix" msgid "Phoenixes" msgstr "Phénix" msgid "Centaur" msgstr "Centaure" msgid "Centaurs" msgstr "Centaures" msgid "Gargoyle" msgstr "Gargouille" msgid "Gargoyles" msgstr "Gargouilles" msgid "Griffin" msgstr "Griffon" msgid "Griffins" msgstr "Griffons" msgid "Minotaur" msgstr "Minotaure" msgid "Minotaurs" msgstr "Minotaures" msgid "Minotaur King" msgstr "Roi minotaure" msgid "Minotaur Kings" msgstr "Rois minotaures" msgid "Hydra" msgstr "Hydre" msgid "Hydras" msgstr "Hydres" msgid "Green Dragon" msgstr "Dragon vert" msgid "Green Dragons" msgstr "Dragons verts" msgid "Red Dragon" msgstr "Dragon rouge" msgid "Red Dragons" msgstr "Dragons rouges" msgid "Black Dragon" msgstr "Dragon noir" msgid "Black Dragons" msgstr "Dragons noirs" msgid "Halfling" msgstr "Galopin" msgid "Halflings" msgstr "Galopins" msgid "Boar" msgstr "Sanglier" msgid "Boars" msgstr "Sangliers" msgid "Iron Golem" msgstr "Golem de fer" msgid "Iron Golems" msgstr "Golems de fer" msgid "Steel Golem" msgstr "Golem d'acier" msgid "Steel Golems" msgstr "Golems d'acier" msgid "Roc" msgstr "Rock" msgid "Rocs" msgstr "Rocks" msgid "Mage" msgstr "Mage" msgid "Magi" msgstr "Mages" msgid "Archmage" msgstr "Grand mage" msgid "Archmagi" msgstr "Grands mages" msgid "Giant" msgstr "Géant" msgid "Giants" msgstr "Géants" msgid "Titan" msgstr "Titan" msgid "Titans" msgstr "Titans" msgid "Skeletons" msgstr "Squelettes" msgid "Zombie" msgstr "Zombie" msgid "Zombies" msgstr "Zombies" msgid "Mutant Zombie" msgstr "Zombie mutant" msgid "Mutant Zombies" msgstr "Zombies mutants" msgid "Mummies" msgstr "Momies" msgid "Mummy" msgstr "Momie" msgid "Royal Mummies" msgstr "Momies royales" msgid "Royal Mummy" msgstr "Momie royale" msgid "Vampire" msgstr "Vampire" msgid "Vampires" msgstr "Vampires" msgid "Vampire Lord" msgstr "Grand vampire" msgid "Vampire Lords" msgstr "Grands vampires" msgid "Lich" msgstr "Macchabée" msgid "Liches" msgstr "Macchabées" msgid "Power Lich" msgstr "Grand macchabée" msgid "Power Liches" msgstr "Grands macchabées" msgid "Bone Dragon" msgstr "Dragon étique" msgid "Bone Dragons" msgstr "Dragons étiques" msgid "Rogue" msgstr "Pillard" msgid "Rogues" msgstr "Pillards" msgid "Nomad" msgstr "Nomade" msgid "Nomads" msgstr "Nomades" msgid "Ghost" msgstr "Fantôme" msgid "Ghosts" msgstr "Fantômes" msgid "Genie" msgstr "Génie" msgid "Genies" msgstr "Génies" msgid "Medusa" msgstr "Méduse" msgid "Medusas" msgstr "Méduses" msgid "Earth Elemental" msgstr "Elémentaire de la terre" msgid "Earth Elementals" msgstr "Elémentaires de la terre" msgid "Air Elemental" msgstr "Elémentaire de l'air" msgid "Air Elementals" msgstr "Elémentaires de l'air" msgid "Fire Elemental" msgstr "Elémentaire de feu" msgid "Fire Elementals" msgstr "Elémentaires de feu" msgid "Water Elemental" msgstr "Elémentaire de l'eau" msgid "Water Elementals" msgstr "Elémentaires de l'eau" msgid "Random Monsters" msgstr "Monstres aléatoires" msgid "Random Monster 1" msgstr "Monstre aléatoire 1" msgid "Random Monsters 1" msgstr "Monstres aléatoires 1" msgid "Random Monster 2" msgstr "Monstre aléatoire 2" msgid "Random Monsters 2" msgstr "Monstres aléatoires 2" msgid "Random Monster 3" msgstr "Monstre aléatoire 3" msgid "Random Monsters 3" msgstr "Monstres aléatoires 3" msgid "Random Monster 4" msgstr "Monstre aléatoire 4" msgid "Random Monsters 4" msgstr "Monstres aléatoires 4" msgid "Double shot" msgstr "Double tir" msgid "2-hex monster" msgstr "Occupe deux cases" msgid "Double strike" msgstr "Double attaque" msgid "Double damage to Undead" msgstr "Double dégâts aux morts-vivants" msgid "% magic resistance" msgstr "% de résistance magique" msgid "Immune to Mind spells" msgstr "Immunité contre les sorts de l'esprit" msgid "Immune to Elemental spells" msgstr "Immunité contre sorts élémentaires" msgid "Immune to Fire spells" msgstr "Immunité contre les sorts de feu" msgid "Immune to Cold spells" msgstr "Immunité contre sorts de froid" msgid "Immune to " msgstr "Immunité contre " msgid "% immunity to %{spell} spell" msgstr "% d'immunité contre le sort %{spell}" msgid "% damage from Elemental spells" msgstr "% de dégâts des sorts élémentaires" msgid "% damage from %{spell} spell" msgstr "% de dégâts du sort %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% de chances de dissiper les sorts bénéfiques" msgid "% chance to Paralyze" msgstr "% de chances de paralyser" msgid "% chance to Petrify" msgstr "% de chances de pétrifier" msgid "% chance to Blind" msgstr "% de chances d'aveugler" msgid "% chance to Curse" msgstr "% de chances de maudire" msgid "% chance to cast %{spell} spell" msgstr "% de chances de lancer le sort %{spell}" msgid "HP regeneration" msgstr "Régénération PV" msgid "Two hexes attack" msgstr "Attaque sur deux hexagones" msgid "Flyer" msgstr "Volant" msgid "Always retaliates" msgstr "Riposte toujours" msgid "Attacks all adjacent enemies" msgstr "Attaque tous les ennemis adjacents" msgid "No melee penalty" msgstr "Pas de pénalité de mêlée" msgid "Dragon" msgstr "Dragon" msgid "Undead" msgstr "Mort-vivant" msgid "No enemy retaliation" msgstr "Aucune riposte de l'ennemi" msgid "HP drain" msgstr "Drainage PV" msgid "Cloud attack" msgstr "Attaque nuage" msgid "Decreases enemy's morale by " msgstr "Diminue le moral de l'ennemi de " msgid "% chance to halve enemy" msgstr "% de chances de tuer la moitié du peloton ennemi" msgid "Soul Eater" msgstr "Dévoreur d'âmes" msgid "Elemental" msgstr "Élémentaire" msgid "No Morale" msgstr "Pas de moral" msgid "Earth creature" msgstr "Créature de la terre" msgid "Air creature" msgstr "Créature de l'air" msgid "Fire creature" msgstr "Créature de feu" msgid "Water creature" msgstr "Créature de l'eau" msgid "Double damage from Fire spells" msgstr "Double les dégâts subis par les sorts de feu" msgid "Double damage from Cold spells" msgstr "Double les dégats subis par les sorts de froid" msgid "Double damage from Earth creatures" msgstr "Double les dégâts subis par les créatures de la terre" msgid "Double damage from Air creatures" msgstr "Double les dégâts subis par les créatures de l'air" msgid "Double damage from Fire creatures" msgstr "Double les dégâts subis par les créatures de feu" msgid "Double damage from Water creatures" msgstr "Double les dégâts subis par les créatures de l'eau" msgid "Lightning" msgstr "Éclair foudroyant" msgid "% immunity to " msgstr "% d'immunité contre " msgid "% damage from " msgstr "% de dégâts de " msgid "The three Anduran artifacts magically combine into one." msgstr "Les trois artéfacts d'Anduran se combinent magiquement en un seul." msgid "View Spells" msgstr "Voir les sorts" msgid "View %{name} Info" msgstr "Voir les infos de %{name}" msgid "Move %{name}" msgstr "Déplacer %{name}" msgid "Cannot move the Spellbook" msgstr "Impossible de déplacer le grimoire" msgid "This item can't be traded." msgstr "Cet objet ne peut pas être échangé." msgid "Invalid Artifact" msgstr "Artéfact non valide" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} augmente la Connaissance du héros de %{count}." msgid "Ultimate Book of Knowledge" msgstr "L'ultime livre de la Connaissance" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} augmente l'Attaque du héros de %{count}." msgid "Ultimate Sword of Dominion" msgstr "L'ultime épée de domination" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} augmente la Défense du héros de %{count}." msgid "Ultimate Cloak of Protection" msgstr "L'ultime voile de protection" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} augmente la Puissance des sorts du héros de %{count}." msgid "Ultimate Wand of Magic" msgstr "L'ultime baguette magique" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" "%{name} augmente les compétences d'attaque et de défense du héros de " "%{count} chacune." msgid "Ultimate Shield" msgstr "L'ultime bouclier" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "" "%{name} augmente la Puissance et la Connaissance du héros de %{count} chacun." msgid "Ultimate Staff" msgstr "L'ultime bâton" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "" "%{name} augmente chacune des statistiques primaires du héros de %{count} " "points." msgid "Ultimate Crown" msgstr "L'ultime couronne" msgid "Golden Goose" msgstr "La poule aux oeufs d'or" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} apporte un revenu de %{count} pièces d'or par jour." msgid "Arcane Necklace of Magic" msgstr "L'obscur collier magique" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Après avoir sauvé une sorcière d'une tombe maudite, elle récompense votre " "héroïsme avec un superbe collier de joyaux." msgid "Caster's Bracelet of Magic" msgstr "Le bracelet magique du jeteur de sorts" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "En fouillant dans les décombres d'une mine effondrée, vous libérez un groupe " "de nains piégés. Reconnaissant, le chef vous donne un bracelet en or." msgid "Mage's Ring of Power" msgstr "L'anneau de Puissance du magicien" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Un cri de douleur vous conduit à un Centaure, pris dans un piège. Après " "avoir libéré la créature, elle vous tend une petite pochette. En vidant son " "contenu, vous trouvez un anneau éblouissant orné de pierres précieuses." msgid "Witch's Broach of Magic" msgstr "La broche magique de la sorcière" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "À côté des restes d'une sorcière brûlée se trouve une belle broche, finement " "conçue. Approchant le cadavre avec précaution, vous ajoutez la broche à " "votre inventaire." msgid "Medal of Valor" msgstr "La médaille de la bravoure" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} augmente le moral de l'armée du héros de %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "En libérant une jeune femme vertueuse des griffes d'un seigneur maléfique, " "vous êtes récompensé de la médaille de bravoure par le hérault du roi." msgid "Medal of Courage" msgstr "La médaille du courage" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Après avoir sauvé un jeune garçon d'une dangereuse meute de loups, vous le " "ramenez au manoir de son père. Reconnaissant, le noble vous remet la " "médaille du courage." msgid "Medal of Honor" msgstr "La médaille d'honneur" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Après avoir libéré la princesse d'un royaume voisin des griffes d'ignobles " "esclavagistes, elle vous décerne la médaille d'honneur." msgid "Medal of Distinction" msgstr "La médaille de distinction" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Après avoir débarrassé ces terres de l'affreux minotaure qui adorait dévorer " "les nobles chevaliers, on vous décerne la médaille de la distinction." msgid "Fizbin of Misfortune" msgstr "Le Fizbin de l'infortune" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} diminue fortement le moral de l'armée du héros de %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Vous tombez sur une médaille gisant sur le bord d'une route déserte. En " "ajoutant la médaille à votre inventaire, vous vous rendez compte que vous " "avez acquis l'indésirable Fizbin de l'infortune, diminuant considérablement " "le moral de votre armée." msgid "Thunder Mace of Dominion" msgstr "Le marteau de foudre de domination" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "En pleine tempête, un éclair frappe un arbre, le fendant. A l'intérieur de " "l'arbre, vous trouvez une mystérieuse masse d'armes." msgid "Armored Gauntlets of Protection" msgstr "Les gantelets de protection" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} augmentent la Défense du héros de %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Vous rencontrez le tristement célèbre chevalier noir ! Après un duel " "éreintant suivi d'un match nul, le chevalier, par respect, vous offre une " "paire de gantelets renforcés." msgid "Defender Helm of Protection" msgstr "Le casque de protection du défenseur" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Un éclat de lumière attire votre attention. En y regardant de plus près, " "vous trouvez un casque en or caché dans un buisson." msgid "Giant Flail of Dominion" msgstr "Le fléau géant de domination" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Un géant maladroit s'est tué avec son propre fléau. Vous sachant plus habile " "avec cette arme, vous retirez avec confiance le spectaculaire fléau de la " "dépouille du géant." msgid "Ballista of Quickness" msgstr "La baliste de rapidité" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "%{name} permet à la catapulte du héros de tirer un coup supplémentaire par " "tour en combat." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "En marchant dans les ruines d'une ancienne ville fortifiée, vous trouvez " "l'instrument de sa destruction, une baliste artisanale minutieusement " "confectionnée." msgid "Stealth Shield of Protection" msgstr "Le bouclier furtif de protection" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Une statue de pierre représente un guerrier tenant un bouclier en argent. Au " "moment où vous retirez le bouclier, la statue tombe en poussière." msgid "Dragon Sword of Dominion" msgstr "L'épée de domination du dragon" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Alors que vous marchez sur un chemin étroit, un buisson s'enflamme " "soudainement. Devant vos yeux, les flammes se transforment et dessinent la " "silhouette d'une belle femme. Elle vous tend une magnifique épée." msgid "Power Axe of Dominion" msgstr "La puissante hache de domination" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Vous voyez une hache en argent profondément enfoncée dans le sol. Après " "plusieurs tentatives infructueuses de vos troupes pour retirer la hache, " "vous en saisissez fermement le manche et la libérez sans effort." msgid "Divine Breastplate of Protection" msgstr "Le plastron divin de protection" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Une bande de voleurs pille les dépouilles de guerriers. En effrayant les " "charognards, vous remarquez qu'ils ont oublié un beau plastron." msgid "Minor Scroll of Knowledge" msgstr "Le parchemin mineur de la Connaissance" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Devant vous apparaît un coffre en verre contenant un parchemin, juché sur un " "lit de velours cramoisi. À votre contact, le couvercle s'ouvre et le " "parchemin flotte jusqu'à vos mains impatientes." msgid "Major Scroll of Knowledge" msgstr "Le parchemin majeur de la Connaissance" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Rendant visite à un sage des alentours, vous expliquez l'intention de votre " "voyage. Il fouille dans un sac et en retire un parchemin jauni qu'il vous " "remet." msgid "Superior Scroll of Knowledge" msgstr "Le parchemin supérieur de la Connaissance" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Vous tombez sur les restes d'un ancien druide. Des os, jaunis par l'âge, " "émergent des plis de sa robe. En la fouillant, vous découvrez un parchemin " "caché." msgid "Foremost Scroll of Knowledge" msgstr "Le parchemin de Connaissance ultime" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Des ossements abîmés, jaunis par l'âge, émergent des plis de la robe en " "lambeaux d'un druide mort. En fouillant la robe, vous découvrez un parchemin " "caché." msgid "Endless Sack of Gold" msgstr "La besace d'or sans fin" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} fournit au héros %{count} pièces d'or par jour." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Un petit lutin danse gaiement autour d'un sac magique. En vous voyant " "approcher, il s'arrête soudainement. Le petit homme crie et tape du pied " "férocement, puis disparaît magiquement. Vous vous souvenez alors du vieux " "dicton des lutins 'Qui trouve, garde !'. Vous prenez le sac et vous partez." msgid "Endless Bag of Gold" msgstr "Le sac d'or sans fin" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Une noble séparée de ses compagnons de voyage, demande votre aide. Après " "l'avoir raccompagnée chez elle, elle vous récompense en vous donnant un sac " "rempli d'or." msgid "Endless Purse of Gold" msgstr "La bourse d'or sans fin" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Au cours de votre voyage, vous trouvez une bourse en cuir remplie d'or qui " "appartenait autrefois à un grand roi guerrier qui avait la capacité de " "transformer tout objet inanimé en or." msgid "Nomad Boots of Mobility" msgstr "Les bottes de nomade" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} augmentent le potentiel de déplacement d'un héros sur terre." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Un commerçant nomade cherche à se protéger d'une tribu de gobelins. Pour " "avoir offert votre aide, il vous donne une paire de bottes finement " "confectionnées en cuir très souple. En regardant de plus près, vous " "remarquez de fascinantes gravures creusées à même le cuir." msgid "Traveler's Boots of Mobility" msgstr "Les bottes de sept lieues" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "En découvrant une paire de bottes ornées de perles et fabriquées dans un " "cuir de grande qualité, vous remerciez le donateur anonyme et ajoutez les " "bottes à votre inventaire." msgid "Lucky Rabbit's Foot" msgstr "La patte de lapin porte-bonheur" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} augmente la chance de l'armée du héros en combat de %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Un marchand ambulant vous offre une patte de lapin à la fourrure argentée " "étincelante en échange d'un passage sûr. Le marchand vous explique que ce " "charme augmentera votre chance au combat." msgid "Golden Horseshoe" msgstr "Le fer à cheval en or" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Une licorne effrayée est prisonnière. Vous lui murmurez des mots apaisants " "tout en la libérant. Elle hennit soudainement, frappe du sabot devant elle, " "puis part au galop. En regardant au sol, vous trouvez un fer à cheval doré." msgid "Gambler's Lucky Coin" msgstr "La pièce porte-bonheur" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Vous avez capturé un diablotin espiègle qui terrorisait la région. En " "échange de sa libération, il vous récompense avec une pièce magique." msgid "Four-Leaf Clover" msgstr "Le trèfle à quatre feuilles" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Au milieu d'une parcelle de végétation morte et sèche, vous êtes surpris de " "trouver un trèfle à quatre feuilles vert en très bon état." msgid "True Compass of Mobility" msgstr "La boussole de mobilité" msgid "The %{name} increases the hero's movement on land and sea." msgstr "" "%{name} augmente le potentiel de déplacement d'un héros sur terre et en mer." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Un vieil homme prétendant être un inventeur vous demande d'essayer sa " "dernière invention. Il vous tend alors une boussole." msgid "Sailor's Astrolabe of Mobility" msgstr "Le sextant du marin" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} augmente le potentiel de déplacement d'un héros en mer." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Un vieux capitaine marin est torturé par des ogres. Vous le sauvez, et en " "retour il vous récompense avec un merveilleux instrument pour mesurer la " "distance d'une étoile." msgid "Evil Eye" msgstr "L'oeil du diable" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" "%{name} réduit de moitié le coût d'incantation des sorts de malédiction." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "En vous aventurant dans une cabane décrépite, vous trouvez le squelette " "d'une sorcière morte depuis longtemps. Une recherche sur la dépouille révèle " "un Å“il de verre roulant à l'intérieur d'un crâne vide." msgid "Enchanted Hourglass" msgstr "Le sablier magique" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} prolonge la durée de tous les sorts du héros de %{count} tours." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Vous vous retrouvez au milieu d'une scène macabre : des vautours picorant " "les restes d'une terrible bataille. Votre fouille rapide des corps révèle un " "sablier enchanté." msgid "Gold Watch" msgstr "La montre en or" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} double l'efficacité des sorts d'hypnose du héros." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "En récompense de l'avoir aidé à sortir son chariot du fossé, un vendeur de " "potions ambulant vous offre une montre en or 'magique'. Sans qu'il le sache, " "il se trouve que la montre est vraiment magique." msgid "Skullcap" msgstr "La calotte" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} réduit de moitié le coût de tous les sorts influençant l'esprit." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Un bref arrêt dans une improbable auberge donne lieu à un échange d'argent, " "de contes et accidentellement de bagages. Vous trouvez une calotte magique " "dans votre nouveau sac de voyage." msgid "Ice Cloak" msgstr "Le manteau de glace" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} réduit de moitié tous les dégâts de froid subis par les troupes du " "héros." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Répondant aux cris paniqués d'une demoiselle en détresse, vous découvrez une " "jeune femme fuyant un ours affamé. Vous tuez la bête à temps, et la sorcière " "reconnaissante tisse un manteau magique à partir de la peau de l'ours." msgid "Fire Cloak" msgstr "Le manteau de feu" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} réduit de moitié tous les dégâts de feu subis par les troupes du " "héros." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Vous tombez sur un combat entre un nécromancien et un paladin. Le " "nécromancien frappe le paladin avec un éclair de feu, le mettant à genoux. " "Agissant rapidement, vous tuez le nécromancien juste avant le coup fatal. " "Reconnaissant, le paladin vous donne le manteau de feu qui l'a sauvé." msgid "Lightning Helm" msgstr "Le casque paratonnerre" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} réduit de moitié tous les dégâts de foudre subis par les troupes du " "héros." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Un rétameur itinérant à la recherche de provisions vous offre un casque qui " "porte le motif d'un éclair sur le dessus, en échange de nourriture et d'eau. " "Curieux, vous acceptez, et découvrez plus tard que le casque est magique." msgid "Evercold Icicle" msgstr "Le morceau de glace éternel" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} permet aux sorts de froid du héros d'infliger %{count} pour cent de " "dégâts supplémentaires aux troupes ennemies." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Un morceau de glace qui résiste à la forte chaleur du soleil de midi attire " "votre attention. Intrigué, vous le détachez, et vous vous rendez compte " "qu'il ne fond pas dans votre main." msgid "Everhot Lava Rock" msgstr "La pierre de lave brûlante" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} permet aux sorts de feu du héros d'infliger %{count} pour cent de " "dégâts supplémentaires aux troupes ennemies." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Vos pérégrinations vous mettent en contact avec une tribu d'êtres " "ressemblant à des singes, qui utilisent un rocher de lave magique qui ne " "refroidit jamais pour allumer leurs feux. Vous les prenez en pitié et leur " "apprenez à faire du feu avec des bouts de bois. Vous prenant pour un dieu, " "les singes vous offrent leur rocher." msgid "Lightning Rod" msgstr "La baguette éclair" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} permet aux sorts de foudre du héros d'infliger %{count} pour cent de " "dégâts supplémentaires aux troupes ennemies." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "En attendant la fin d'un orage, un éclair frappe le paratonnerre d'une " "chaumière voisine, qui fond alors et tombe au sol. L'extrémité du " "paratonnerre est intact mais vos cheveux se hérissent lorsque vous le " "touchez. Intéressant..." msgid "Snake-Ring" msgstr "L'anneau-serpent" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} réduit de moitié le coût de tous les sorts de bénédiction du héros." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Vous avez trouvé une bague étrange sur le doigt d'un voyageur mort depuis " "bien longtemps. L'anneau ressemble à un serpent qui se mord la queue." msgid "Ankh" msgstr "L'ânkh" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} double l'efficacité de tous les sorts de résurrection et de " "réanimation du héros." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Une violente tempête vous révèle l'entrée d'un tombeau enseveli. En faisant " "des recherches vous découvrez que le tombeau a déjà été pillé, mais les " "voleurs n'ont pas remarqué une ânkh accrochée à une chaîne d'argent cachée " "dans l'obscurité." msgid "Book of Elements" msgstr "Le livre des éléments" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} double l'efficacité des sorts d'invocation du héros." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Vous rencontrez un invocateur qui vous supplie de l'accompagner vous et " "votre armée pour le protéger du danger. Vous acceptez, et en récompense il " "vous offre une copie du livre des éléments." msgid "Elemental Ring" msgstr "L'anneau des éléments" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "%{name} réduit de moitié le coût de vos sorts d'invocation." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Alors que vous vous reposez, vous remarquez un lynx qui grimpe à un arbuste " "pour atteindre un nid de corbeaux. Sur un coup de tête, vous grimpez à votre " "tour à l'arbre et effrayez le félin. Lorsque vous regardez le nid, vous " "découvrez une collection de pierres brillantes et un anneau." msgid "Holy Pendant" msgstr "Le pendentif sacré" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} immunise les troupes du héros contre les sorts de malédiction." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Au cours de vos pérégrinations, vous croisez un ermite qui vit dans une " "petite cabane bien rangée. Impressionné par votre mission, il sort quelque " "temps de sa méditation pour bénir un charme contre les malédictions, dont il " "vous fait cadeau." msgid "Pendant of Free Will" msgstr "Le pendentif du libre arbitre" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "%{name} immunise les troupes du héros contre les sorts d'hypnose." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Guidé par des appels à l'aide, vous trouvez des fées de rivière qui " "s'amusent à plonger un vieil homme dans l'eau. Épris de revanche, vous " "sauvez l'homme et placez une fée sur la terre ferme pendant quelque temps. " "La fée, se sentant mal hors de l'eau, vous donne un pendentif magique afin " "de la laisser partir." msgid "Pendant of Life" msgstr "Le pendentif de la vie" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} immunise les troupes du héros contre les sorts de mort." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Vous gagnez un pendentif magique grâce à une brève rencontre avec une petite " "caravane sur le bord de la route et une victoire au jeu des osselets. Son " "ancien propriétaire vous affirme qu'il protège contre les sorts mortels des " "nécromanciens." msgid "Serenity Pendant" msgstr "Le pendentif de la sérénité" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} immunise les troupes du héros contre le sort furie." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Les échos d'une bataille vous attirent vers les lieux d'un combat entre un " "barbare âgé et une hydre à huit têtes. Votre intervention à point nommé fait " "basculer la bataille à la faveur du vieil homme, et il vous récompense avec " "un pendentif qu'il utilisait afin d'apaiser son esprit lors des combats." msgid "Seeing-eye Pendant" msgstr "Le pendentif de l'oeil qui voit" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} immunise les troupes du héros contre les sorts de cécité." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Vous tombez sur une très vieille dame, aveugle, seule et mourante. Vous vous " "occupez de ses dernières volontés et vous lui promettez un enterrement " "digne. Reconnaissante, elle vous offre un pendentif magique orné du symbole " "d'un oeil. Il vous permet de voir les yeux fermés." msgid "Kinetic Pendant" msgstr "Le pendentif cinétique" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name} immunise les troupes du héros contre les sorts de paralysie." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Vous tombez sur un golem portant un pendentif brillant qui bloque votre " "route. Sur un pressentiment, vous coupez le pendentif de son cou. Privé de " "sa source de pouvoir, le golem tombe en morceaux, vous laissant son " "pendentif magique." msgid "Pendant of Death" msgstr "Le pendentif de la mort" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} immunise les troupes du héros contre les sorts divins." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Un combat rapide et mortel contre un nécromancien vous fait gagner son " "pendentif magique. Plus tard, un magicien vous raconte que ce pendentif " "protège les morts-vivants sous votre contrôle contre les sorts divins." msgid "Wand of Negation" msgstr "La baguette de la négation" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "%{name} immunise les troupes du héros contre les sortilèges de contre-sort." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Vous rencontrez un vieil ami sorcier qui voyage dans une direction opposée. " "Il vous offre un cadeau : une baguette qui empêche le contre-sort d'affecter " "vos troupes." msgid "Golden Bow" msgstr "L'arc doré" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} élimine la pénalité de %{count} pour cent pour les troupes du héros " "qui tirent au-delà des obstacles (par exemple, les murs d'un château)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Une rencontre fortuite avec un célèbre archer vous entraîne dans un jeu " "d'osselets. Il vous propose de parier son arc contre votre cheval. Vous " "gagnez." msgid "Telescope" msgstr "Le télescope" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} augmente la quantité de terrain que le héros révèle lorsqu'il part à " "l'aventure de %{count} cases supplémentaires." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Un marchand venu d'un pays lointain vous échange une nouvelle invention de " "son peuple contre des fournitures de voyage. Étrangement, les objets " "éloignés vous semblent plus proches, il appelle ça...\n" "\n" "un télescope." msgid "Statesman's Quill" msgstr "La plume de l'homme d'état" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} réduit le coût de la reddition à %{count} pour cent du coût total " "des troupes dans l'armée du héros." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Vous faites une pause pour aider un diplomate dont l'essieu est cassé. Pour " "montrer sa gratitude, il vous donne une plume qui possède des propriétés " "magiques qui, selon lui, \"Aideront les gens à voir les choses à votre " "façon\"." msgid "Wizard's Hat" msgstr "Le chapeau du sorcier" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} augmente la durée des sorts du héros de %{count} tours." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Vous apercevez un sorcier qui se sauve d'un griffon, courant à toute allure. " "Le sorcier ouvre un portail qu'il emprunte, alors que son chapeau tombe à " "terre en heurtant le portail. Le griffon le suit ; enfin le portail se " "referme. Vous ramassez le chapeau, enlevez la poussière, et le déposez sur " "votre tête." msgid "Power Ring" msgstr "L'anneau de Puissance" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "%{name} restaure %{count} points de magie supplémentaires par jour au héros." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Vous découvrez un arbuste qui ressemble fort au grand sorcier Carnauth, avec " "un anneau autour d'une petite branche. Des bouts de vêtements et de cuir " "pourrissant vous amènent à penser qu'il s'AGIT de Carnauth, transformé. " "Puisque vous ne pouvez pas l'aider, vous vous emparez de l'anneau magique." msgid "Ammo Cart" msgstr "La charrette de munitions" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} fournit des munitions illimités pour toutes les troupes qui tirent " "dans l'armée du héros." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Une charrette de munitions au milieu d'un vieux champ de bataille attire " "votre regard. En l'examinant, les munitions ont l'air opérationnelles, vous " "l'emportez donc avec vous." msgid "Tax Lien" msgstr "Le privilège fiscal" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} coûte au héros %{count} pièces d'or par jour." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Vos habitudes particulièrement dépensières ont engendré une taxe importante " "que vous ne pouvez pas espérer régler. Le collecteur de taxes vous prend en " "pitié et consent à vous prélever de seulement 250 pièces d'or par jour " "jusqu'au restant de votre vie. Cochez cette case si vous voulez qu'un euro " "aille au financement de la campagne pour l'élection présidentielle." msgid "Hideous Mask" msgstr "Le masque sinistre" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "%{name} empêche toutes les armées 'errantes' de rallier le héros." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "En pillant la tombe de Sinfilas Gardolad, le fameux sorcier changeforme, " "vous exhumez son masque légendaire. En tremblant, vous mettez son masque et " "votre visage se change en une affreuse grimace ! Oh, non ! Il s'agit en fait " "du masque hideux de Gromluck Greene, et il reste collé à votre visage." msgid "Endless Pouch of Sulfur" msgstr "Le sac de soufre sans fin" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} fournit %{count} morceau de soufre par jour." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Vous rendez visite à un alchimiste qui, en voyant votre armée, est " "impressionné par la justesse de votre cause. Votre nouveau sujet loyal vous " "donne son sac de source infinie de soufre pour aider en tant qu'effort de " "guerre." msgid "Endless Vial of Mercury" msgstr "La fiole de mercure sans fin" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} fournit %{count} fiole de mercure par jour." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Un arrêt bref dans une tour de sorcier abandonnée à la hâte fait refaire " "surface une fiole magique de mercure qui n'est jamais totalement vide. " "Sachant reconnaître d'un coup d'oeil un trésor, vous recouvrez la fiole d'un " "bouchon et la fourrez dans votre poche." msgid "Endless Pouch of Gems" msgstr "La bourse de gemmes sans fin" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} fournit %{count} gemmes par jour." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Une courte averse orageuse laisse place à un arc-en-ciel... et vous pouvez " "voir son extrémité. Allant à vive allure, vous vous emparez de la marmite " "d'or qui s'y trouve. Le leprechaun à qui elle appartient, incapable de vous " "empêcher de la prendre, vous offre une bourse infinie de gemmes en retour de " "son or. Vous acceptez." msgid "Endless Cord of Wood" msgstr "Le tas de bois sans fin" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} fournit %{count} bûche de bois par jour." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "En vous arrêtant pour vous reposer et allumer un feu de cuisine, vous prenez " "des branches à partir d'un tas de bois mort à proximité. Alors que vous " "continuez à retirer du bois du tas, vous vous rendez compte qu'il ne diminue " "pas de volume. Vous réalisez à votre grande joie que le bois est enchanté, " "vous l'emportez donc avec vous." msgid "Endless Cart of Ore" msgstr "Le chariot de fer sans fin" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} fournit %{count} morceau de fer par jour." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Vous avez trouvé une forge de gobelins qui façonne des armes contre les " "humains. Avec d'immenses cris, vous et votre armée effectuent un assaut " "contre leur base, les délogeant. En explorant, vous trouvez un chariot " "magique qui ne se vide jamais, rempli de fer." msgid "Endless Pouch of Crystal" msgstr "La bourse de cristal sans fin" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} fournit %{count} cristal par jour." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "En vous abritant d'un orage dans une petite caverne, vous remarquez dans un " "coin un petit amas de cristal. Curieux, vous en détachez un morceau et vous " "vous rendez compte que le morceau a repoussé chez le cristal d'origine. Vous " "décidez de fourrer l'amas entier dans une bourse et l'emportez avec vous." msgid "Spiked Helm" msgstr "Le casque à pointes" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Votre armée est prise en embuscade par une petite tribu d'orcs sauvages (et " "pas très fûtés). Vous les repoussez facilement et les survivants s'enfuient " "dans toutes les directions. Un des orcs portait un casque à pointes poli. En " "pensant qu'il fera un bon souvenir, vous l'emportez." msgid "Spiked Shield" msgstr "Le bouclier à pointes" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Vous tombez sur un pont qui passe au-dessus d'une ravine asséchée. Avant de " "poser un pied dessus, un troll sort d'en-dessous le pont et exige un " "paiement afin de vous laisser passer. Vous refusez et le troll charge alors, " "vous forçant à l'abbatre. Vous emportez son bouclier à pointes en guise de " "trophée." msgid "White Pearl" msgstr "La perle blanche" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Une promenade dans le bassin d'un lac salé asséché vous a permis de trouver " "un objet improbable : une perle blanche parmi des coquillages brisés et des " "débris." msgid "Black Pearl" msgstr "La perle noire" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Les rumeurs à propos d'un griffon de taille inhabituelle s'attaquant à ces " "terres vous conduisent à son repaire. Un combat rapide et brutal permet de " "vous débarrasser de la bête, et une fouille de son nid fétide vous permet de " "trouver une énorme perle noire." msgid "Magic Book" msgstr "Le grimoire" msgid "The %{name} enables the hero to cast spells." msgstr "%{name} permet au héros de lancer des sorts." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" "Un jeune homme s'approche de vous : \"Mon Seigneur, permettez moi de vous " "montrer ma dernière invention pour partager la connaissance !\" Vous suivez " "le jeune homme dans son atelier et vous apercevez immédiatement une machine " "volumineuse avec des leviers et des manivelles. \"La voici\" dit-il avec " "entrain, \"La presse à imprimer\" et avant que vous ne puissiez dire quelque " "chose, il vous tend Le Grimoire." msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Emplacement 2" msgid "The reserved artifact." msgstr "L'artéfact réservé." msgid "Dummy 3" msgstr "Emplacement 3" msgid "Dummy 4" msgstr "Emplacement 4" msgid "Spell Scroll" msgstr "Parchemin magique" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Ce %{name} donne au héros la capacité de lancer le sort %{spell} si celui-ci " "possède un grimoire." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Vous trouvez un récipient élaboré qui contient un vieux parchemin en vélin. " "Les runes sur le récipient sont très anciennes, et l'art avec lequel il a " "été assemblé est stupéfiant. Lorsque vous sortez le parchemin, vous vous " "sentez imprégné d'un pouvoir magique." msgid "Arm of the Martyr" msgstr "Le bras du martyre" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} augmente la Puissance des sorts du héros de %{count} mais ajoute la " "pénalité de moral des morts-vivants." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "L'un des membres les moins intelligents de votre troupe ramasse un bras par " "terre. Malgré l'absence d'un corps, il est toujours en mouvement. Vos " "troupes trouvent le bras démembré répugnant, mais vous ne pouvez pas vous " "résoudre à le laisser tomber : il semble détenir une sorte de pouvoir " "magique qui influence votre prise de décision." msgid "Breastplate of Anduran" msgstr "Le plastron d'Anduran" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} augmente la Défense du héros de %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Vous tombez sur un panneau. On peut y lire : \"Ici se trouve le corps " "d'Anduran. Inclinez-vous et jurez fidélité, et vous serez récompensés.\" " "Vous décidez de faire ce qu'il dit. En vous relevant, vous ressentez une " "froideur contre votre peau. En regardant vers le bas, vous constatez que " "vous portez soudainement une cuirasse étincelante et ornée." msgid "Broach of Shielding" msgstr "La broche-bouclier" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} fournit %{count} pour cent de protection contre Apocalypse et Orage, " "mais diminue la Puissance de 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Une sorcière bienveillante pense que les défenses de votre armée pourraient " "utiliser un coup de pouce magique. Elle propose d'enchanter la broche que " "vous portez sur votre manteau, et vous acceptez." msgid "Battle Garb of Anduran" msgstr "La cuirasse d'Anduran" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} combine les pouvoirs des trois artéfacts d'Anduran. Il offre un " "maximum de chance et de moral aux troupes du héros et lui donne le sortilège " "Portes du village." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Par pitié pour un pauvre paysan, vous achetez hors de prix un coffre de " "vieilles ordures qu'il colporte. Plus tard, en fouillant dedans, vous " "constatez qu'il contient les 3 pièces du légendaire costume de bataille " "d'Anduran !" msgid "Crystal Ball" msgstr "La boule de cristal" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} permet au héros d'obtenir des informations plus spécifiques sur les " "monstres, les héros ennemis et les châteaux à proximité du héros." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Vous tombez sur une caravane de gitans qui se régalent et fortifient leurs " "corps avec de l'hydromel. Ils vous appellent vers l'avant et disent : \"Si " "vous prouvez que vous pouvez danser le Rama-Buta, nous vous récompenserons." "\" Vous ne le savez pas, mais essayez quand même. Ils rient hystériquement, " "mais admirent votre bravoure, vous donnant une boule de cristal." msgid "Heart of Fire" msgstr "Le coeur de feu" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} offre une protection de %{count} pour cent contre le feu, mais " "double les dégâts de froid infligés à vos troupes." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Vous entrez dans une clairière récemment brûlée et tombez sur un élémentaire " "de feu assis au sommet d'un rocher. Il lève les yeux au ciel, son visage " "flamboyant tordu montre un regard de douleur intense. Il vous lance alors un " "objet lumineux. Vous levez les mains pour le bloquer, mais il passe à " "travers elles et se loge dans votre poitrine." msgid "Heart of Ice" msgstr "Le coeur de glace" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} offre une protection de %{count} pour cent contre le froid, mais " "double les dégâts de feu infligés à vos troupes." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Soudain, un froid mordant envahit votre corps. Sous la surprise glaciale, " "vous tombez de votre cheval. La douleur s'atténue, mais vous avez toujours " "l'impression que votre poitrine est gelée. Lorsque vous vous relevez, vous " "entendez rire de bon coeur. Vous vous retournez juste à temps pour voir un " "géant de glace s'enfuir et disparaître dans les bois." msgid "Helmet of Anduran" msgstr "Le casque d'Anduran" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Vous scrutez un objet étincelant qui sort du sol. Vous envoyez un membre de " "votre groupe pour enquêter. Il revient avec un casque d'or à la main. Vous " "vous rendez compte que ce doit être le casque du légendaire d'Anduran, le " "seul homme qui était connu pour porter une armure en or massif." msgid "Holy Hammer" msgstr "Le marteau saint" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Vous tombez sur une bataille où un paladin a été mortellement blessé par un " "groupe de zombies. Il vous demande de prendre son marteau et de terminer ce " "qu'il a commencé. Lorsque vous le ramassez, un bourdonnement s'entend, puis " "tout devient flou. Les zombies gisent sur le sol, le marteau dégouline de " "sang. Vous l'attachez à votre ceinture." msgid "Legendary Scepter" msgstr "Le sceptre légendaire" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} ajoute %{count} points à tous les attributs." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "En culminant une petite colline, vous tombez sur un spectacle ridicule. Une " "fée tente de transporter un sceptre presque aussi grand qu'elle. En essayant " "de ne pas rire, vous demandez : \"Besoin d'aide ?\" La fée vous regarde et " "répond : \"Vous trouvez ça drôle ? Bien. Vous pouvez le prendre. Je préfère " "voler de toute façon.\"" msgid "Masthead" msgstr "La tête de mât" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} augmente la chance et le moral de l'armée du héros de %{count} " "points chacun lors des batailles en mer." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Un vieux marin vous raconte l'histoire d'une tête de mât enchantée qu'il a " "utilisée dans sa jeunesse pour rallier son équipage pendant les moments " "difficiles. Il vous remet ensuite une carte fanée qui montre où il l'a " "cachée. Après beaucoup d'exploration, vous le trouvez planqué sous un quai à " "proximité." msgid "Sphere of Negation" msgstr "La sphère de négation" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} désactive tout lancer de sorts, pour chaque camp, au combat." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Vous vous arrêtez pour aider un paysan à attraper une jument fugueuse. Pour " "montrer sa gratitude, il vous tend une minuscule sphère. Dès que vous la " "saisissez, vous sentez l'énergie magique s'écouler de vos membres..." msgid "Staff of Wizardry" msgstr "Le bâton de la sorcellerie" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} augmente la Puissance des sorts du héros de %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Vos troupes trouvent un mystérieux bâton en lévitation à un mètre au dessus " "du sol. Ils vous le remettent et vous remarquez une inscription. On peut y " "lire : \"Cerveau plutôt que muscle, magie plutôt que force. Faites vôtres " "ces paroles, et vous gagnerez tous les combats.\"" msgid "Sword Breaker" msgstr "Le briseur d'épée" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} augmente la défense du héros de %{count} et l'attaque de 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Un ancien capitaine de la garde admire votre quête et vous donne le briseur " "d'épée enchanté sur lequel il s'appuyait pendant ses tours de service." msgid "Sword of Anduran" msgstr "L'épée d'Anduran" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Un troll vous arrête et dit : \"Payez-moi 5000 or, ou l'épée d'Anduran vous " "tuera où vous vous tenez.\" Vous refusez. Le troll attrape l'épée suspendue " "à sa ceinture, crie de douleur et s'enfuit. Vous ramassez l'épée " "légendaire ; une chance que ces crétins de Trolls saisissent parfois les " "objets tranchants par le mauvais bout." msgid "Spade of Necromancy" msgstr "La pelle du fossoyeur" msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} améliore la compétence de nécromancie du héros." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Une pelle sale a été enfoncée dans un monticule de terre à proximité. Après " "enquête, vous découvrez qu'il s'agit de la pelle enchantée du fossoyeur, " "longtemps pensée perdue par les mortels." msgid "spellBonus|selected by user" msgstr "choisi par le joueur" msgid "Wood" msgstr "Bois" msgid "Mercury" msgstr "Mercure" msgid "Ore" msgstr "Fer" msgid "Sulfur" msgstr "Soufre" msgid "Crystal" msgstr "Cristal" msgid "Gems" msgstr "Gemmes" msgid "Gold" msgstr "Or" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Il existe sept ressources différentes dans Heroes 2, utiles pour construire " "et améliorer les châteaux, acheter des troupes et recruter des héros. L'or " "est la ressource la plus courante, nécessaire pour pratiquement tout. Le " "bois et le fer sont utilisés pour la plupart des bâtiments. Les gemmes, le " "mercure, le soufre et le cristal sont des ressources magiques rares " "utilisées pour les créatures et les bâtiments les plus puissants." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Provoque une boule de feu géante qui frappe la zone sélectionnée, " "endommageant toutes les créatures proches." msgid "Fireball" msgstr "Boule de feu" msgid "Fireblast" msgstr "Souffle de feu" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Version améliorée de boule de feu, le souffle de feu affecte deux hexagones " "autour du point central du sort, au lieu d'un seul." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Provoque un éclair qui frappe la créature sélectionnée." msgid "Lightning Bolt" msgstr "Éclair foudroyant" msgid "Chain Lightning" msgstr "Foudre" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Provoque un éclair qui frappe une créature sélectionnée, puis la créature la " "plus proche en infligeant la moitié des dégâts, puis la créature suivante la " "plus proche infligeant encore la moitié des dégâts, et ainsi de suite, " "jusqu'à ce que l'éclair devienne trop faible pour être nuisible. " "Avertissement : Ce sort peut toucher vos propres créatures !" msgid "Teleport" msgstr "Téléportation" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Téléporte la créature que vous sélectionnez vers n'importe quelle place " "libre sur le champ de bataille." msgid "Cure" msgstr "Guérison" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Annule tous les sorts négatifs lancés sur l'une de vos créatures, et " "restaure jusqu'à %{count} PV par niveau de Puissance." msgid "Mass Cure" msgstr "Grande guérison" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Supprime tous les sorts négatifs lancés sur vos forces, et restaure jusqu'à " "%{count} de PV par niveau de Puissance, par créature." msgid "Resurrect" msgstr "Résurrection" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Ressuscite les créatures d'un peloton endommagé ou mort jusqu'à la fin du " "combat." msgid "Resurrect True" msgstr "Ultime résurrection" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" "Ressuscite définitivement les créatures d'un peloton endommagé ou mort." msgid "Haste" msgstr "Célérité" msgid "Increases the speed of any creature by %{count}." msgstr "Augmente la vitesse d'une créature de %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Augmente la vitesse de toutes vos créatures de %{count}." msgid "Mass Haste" msgstr "Célérité collective" msgid "Slows target to half movement rate." msgstr "Ralentit la cible à la moitié de sa vitesse de déplacement." msgid "spell|Slow" msgstr "Lourdeur" msgid "Mass Slow" msgstr "Lourdeur collective" msgid "Slows all enemies to half movement rate." msgstr "Ralentit tous les ennemis à la moitié de leur vitesse de déplacement." msgid "spell|Blind" msgstr "Aveugler" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" "Aveugle l'ennemi, l'empêchant de se déplacer et réduit les dommages de la " "riposte de %{count} pourcent." msgid "Bless" msgstr "Bénédiction" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Permet à la créature sélectionnée d'infliger un maximum de dégâts." msgid "Causes all of your units to inflict maximum damage." msgstr "Permet à toutes vos créatures d'infliger un maximum de dégâts." msgid "Mass Bless" msgstr "Grande bénédiction" msgid "Magically increases the defense skill of the selected creatures." msgstr "Augmente la statistique de défense des créatures sélectionnées." msgid "Stoneskin" msgstr "Chair de pierre" msgid "Steelskin" msgstr "Chair d'acier" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Augmente la caractéristique de défense des créatures ciblées. Il s'agit " "d'une version améliorée de chair de pierre." msgid "Causes the selected creatures to inflict minimum damage." msgstr "La créature choisie inflige des dégâts minimums." msgid "Curse" msgstr "Malédiction" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Toutes les troupes ennemies infligent des dégâts minimums." msgid "Mass Curse" msgstr "Grande malédiction" msgid "Damages all undead in the battle." msgstr "Inflige des dégâts à tous les morts-vivants du champ de bataille." msgid "Holy Word" msgstr "Sainte parole" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Inflige des dégâts à tous les morts-vivants du champ de bataille. Il s'agit " "d'une version améliorée de sainte parole." msgid "Holy Shout" msgstr "Saint cri" msgid "Anti-Magic" msgstr "Anti-magie" msgid "Prevents any magic against the selected creatures." msgstr "Immunise la créature ciblée à la magie." msgid "Dispel Magic" msgstr "Contre-sorts" msgid "Removes all magic spells from a single target." msgstr "Lève tous les sortilèges de la créature choisie." msgid "Mass Dispel" msgstr "Ultime contre-sorts" msgid "Removes all magic spells from all creatures." msgstr "Lève tous les sortilèges de toutes les créatures." msgid "Causes a magic arrow to strike the selected target." msgstr "Provoque une flèche magique qui frappe la cible sélectionnée." msgid "Magic Arrow" msgstr "Flèche magique" msgid "Berserker" msgstr "Furie" msgid "Causes a creature to attack its nearest neighbor." msgstr "Fait en sorte qu'une créature attaque son plus proche voisin." msgid "Armageddon" msgstr "Apocalypse" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "La terreur sacrée frappe le champ de bataille, causant de graves dégâts à " "toutes les créatures." msgid "Elemental Storm" msgstr "Orage" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "Les éléments magiques se déversent sur le champ de bataille, frappant toutes " "les créatures." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Une pluie de pierres frappe une zone du champ de bataille, frappant toutes " "les créatures proches." msgid "Meteor Shower" msgstr "Pluie de météores" msgid "Paralyze" msgstr "Paralysie" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "Le créature ciblée est paralysée, incapable de bouger ni de riposter." msgid "Hypnotize" msgstr "Hypnose" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Ramène un peloton ennemi sous votre contrôle si ses points de vie sont " "inférieurs à %{count} fois le niveau de Puissance du lanceur." msgid "Cold Ray" msgstr "Rayon froid" msgid "Drains body heat from a single enemy unit." msgstr "Draine la chaleur corporelle d'une créature ennemie." msgid "Cold Ring" msgstr "Anneau froid" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Draine la chaleur corporelle de toutes les créatures entourant le point " "central, mais sans le point central." msgid "Disrupting Ray" msgstr "Rayon perturbateur" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Réduit de trois points la défense d'une créature ennemie." msgid "Damages all living (non-undead) units in the battle." msgstr "" "Blesse toutes les créatures vivantes (non mortes-vivantes) de la bataille." msgid "Death Ripple" msgstr "Onde mortelle" msgid "Death Wave" msgstr "Vague mortelle" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Blesse toutes les créatures vivantes (non mortes-vivantes) dans la bataille. " "Ce sort est une version améliorée d'onde mortelle." msgid "Dragon Slayer" msgstr "Anti-dragon" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "" "Augmente considérablement la statistique d'attaque d'une créature contre les " "dragons." msgid "Blood Lust" msgstr "Soif de sang" msgid "Increases a unit's attack skill." msgstr "Augmente la statistique d'attaque d'une créature." msgid "Animate Dead" msgstr "Mort-vivant" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "Ressuscite les créatures décimées d'un peloton de mort-vivants, de façon " "permanente." msgid "Mirror Image" msgstr "Image miroir" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Crée un peloton illusoire qui réplique un de vos pelotons existant. Cette " "illusion inflige les mêmes dégâts que l'original, mais disparaît si elle " "subit des dégâts." msgid "Shield" msgstr "Bouclier" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Réduit de moitié les dégâts reçus par les attaques à distance sur la troupe " "choisie. Cela n'affecte pas les dégâts infligés par les balistes et les " "tourelles." msgid "Mass Shield" msgstr "Grand bouclier" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Réduit de moitié les dégâts reçus par les attaques à distance pour toutes " "vos troupes. Cela n'affecte pas les dégâts infligés par les balistes et les " "tourelles." msgid "Summon Earth Elemental" msgstr "Invoquer élémentaire de la terre" msgid "Summons Earth Elementals to fight for your army." msgstr "" "Invoque des élémentaires de la terre pour qu'ils se battent à vos côtés." msgid "Summon Air Elemental" msgstr "Invoquer élémentaire de l'air" msgid "Summons Air Elementals to fight for your army." msgstr "Invoque des élémentaires de l'air pour qu'ils se battent à vos côtés." msgid "Summon Fire Elemental" msgstr "Invoquer élémentaire de feu" msgid "Summons Fire Elementals to fight for your army." msgstr "Invoque des élémentaires de feu pour qu'ils se battent à vos côtés." msgid "Summon Water Elemental" msgstr "Invoquer élémentaire de l'eau" msgid "Summons Water Elementals to fight for your army." msgstr "Invoque des élémentaires de l'eau pour qu'ils se battent à vos côtés." msgid "Damages castle walls." msgstr "Endommage les murs des châteaux." msgid "Earthquake" msgstr "Séisme" msgid "Causes all mines across the land to become visible." msgstr "Rend visibles toutes les mines du pays." msgid "View Mines" msgstr "Voir mines" msgid "Causes all resources across the land to become visible." msgstr "Rend visibles toutes les ressources du pays." msgid "View Resources" msgstr "Voir ressources" msgid "Causes all artifacts across the land to become visible." msgstr "Rend visibles tous les artéfacts du pays." msgid "View Artifacts" msgstr "Voir artéfacts" msgid "Causes all towns and castles across the land to become visible." msgstr "Rend visibles toutes les villages et tous les châteaux du pays." msgid "View Towns" msgstr "Voir villages" msgid "Causes all Heroes across the land to become visible." msgstr "Rend visibles tous les héros." msgid "View Heroes" msgstr "Voir héros" msgid "Causes the entire land to become visible." msgstr "Rend visible tout le pays." msgid "View All" msgstr "Tout voir" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" "Permet au lanceur du sort de visualiser des informations détaillées sur les " "héros ennemis." msgid "Summon Boat" msgstr "Embarquement" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Invoque le bateau ami inoccupé le plus proche sur un emplacement côtier " "adjacent. Un bateau ami est un bateau que vous venez de construire ou que " "vous êtes le dernier joueur à avoir occupé." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Permet au lanceur du sort de se transporter magiquement dans un lieu proche." msgid "Dimension Door" msgstr "Autre dimension" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Ramène le lanceur du sort dans n'importe quelle village ou château qu'il " "possède actuellement." msgid "Town Gate" msgstr "Retour village" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Ramène le héros dans le village ou le château de son choix, à condition " "qu'il soit contrôlé par vous." msgid "Visions" msgstr "Visions" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Visions prédit l'issue probable d'une rencontre avec un camp d'armée neutre." msgid "Haunt" msgstr "Hanter" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Hante une mine que vous contrôlez avec des fantômes. Cette mine cesse de " "produire des ressources. (Si je ne peux pas la garder, personne ne l'aura !)" msgid "Set Earth Guardian" msgstr "Gardien de terre" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" "Invoque les élémentaires de la terre pour garder une mine contre les armées " "ennemies." msgid "Set Air Guardian" msgstr "Gardien d'air" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" "Invoque les élémentaires de l'air pour garder une mine contre les armées " "ennemies." msgid "Set Fire Guardian" msgstr "Gardien de feu" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" "Invoque les élémentaires du feu pour garder une mine contre les armées " "ennemies." msgid "Set Water Guardian" msgstr "Gardien d'eau" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" "Invoque les élémentaires de l'eau pour garder une mine contre les armées " "ennemies." msgid "Random Spell" msgstr "Sortilège aléatoire" msgid "Randomly selected spell of any level." msgstr "Sortilège choisi au hasard, de n'importe quel niveau." msgid "Random 1st Level Spell" msgstr "Sortilège aléatoire de 1er niveau" msgid "Randomly selected 1st level spell." msgstr "Sortilège de 1er niveau choisi au hasard." msgid "Random 2nd Level Spell" msgstr "Sortilège aléatoire de 2ème niveau" msgid "Randomly selected 2nd level spell." msgstr "Sortilège de 2ème niveau choisi au hasard." msgid "Random 3rd Level Spell" msgstr "Sortilège aléatoire de 3ème niveau" msgid "Randomly selected 3rd level spell." msgstr "Sortilège de 3ème niveau choisi au hasard." msgid "Random 4th Level Spell" msgstr "Sortilège aléatoire de 4ème niveau" msgid "Randomly selected 4th level spell." msgstr "Sortilège de 4ème niveau choisi au hasard." msgid "Random 5th Level Spell" msgstr "Sortilège aléatoire de 5ème niveau" msgid "Randomly selected 5th level spell." msgstr "Sortilège de 5ème niveau choisi au hasard." msgid "Petrification" msgstr "Pétrification" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Transforme en pierre la créature affectée. Une créature pétrifiée reçoit la " "moitié des dégâts d'une attaque directe." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Vous n'avez pas de grimoire, vous ne pouvez donc pas lancer un sort." msgid "No spell to cast." msgstr "Aucun sort à lancer." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Il reste %{sp} points de magie sur %{max} au héro." msgid "View Adventure Spells" msgstr "Voir les sorts d'aventure" msgid "View Combat Spells" msgstr "Voir les sorts de combat" msgid "View previous page" msgstr "Voir la page précédente" msgid "View next page" msgstr "Voir la page suivante" msgid "Close Spellbook" msgstr "Fermer le grimoire" msgid "View %{spell}" msgstr "Voir %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Ce sort fait %{damage} points de dégâts." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Ce sort invoque\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Ce sort restaure %{hp} PV." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Ce sort invoque %{count} %{monster} pour garder la mine." msgid "The nearest town is %{town}." msgstr "Le village le plus proche est %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Ce village est occupé par votre héros %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Ce sort contrôle jusqu'à\n" "%{hp} PV." msgid "The ultimate artifact is really the %{name}." msgstr "L'ultime artéfact est vraiment le %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "L'ultime artéfact peut être trouvé dans les régions %{name} du monde." msgid "north-west" msgstr "nord-ouest" msgid "north" msgstr "nord" msgid "north-east" msgstr "nord-est" msgid "west" msgstr "ouest" msgid "center" msgstr "centre" msgid "east" msgstr "est" msgid "south-west" msgstr "sud-ouest" msgid "south" msgstr "sud" msgid "south-east" msgstr "sud-est" msgid "The truth is out there." msgstr "La vérité est là." msgid "The dark side is stronger." msgstr "Le côté obscur est plus fort." msgid "The end of the world is near." msgstr "La fin du monde est proche." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Les os de Lord Slayer sont ensevelis dans les fondations de l'arène." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Un dragon noir éliminera un titan n'importe quel jour de la semaine." # Orignal H2-fr: Un Dragon noir peut vaincre un Titan à tout moment. msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "Il lui a dit : Yada yada yada... et elle a répondu : Bla, bla, bla..." msgid "An unknown force is being resurrected..." msgstr "Une force inconnue est ressuscitée..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Téléchargez la dernière version du jeu sur\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Sélectionner %{resource} :" #~ msgid "Enable auto combat" #~ msgstr "Activer le combat automatique" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "Finir la bataille en mode auto" #~ msgid "Please Remember" #~ msgstr "N'oubliez pas" # Needs extra whitespace to avoid yellow word splitting #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Vous pouvez toujours changer la langue, la résolution et les paramètres " #~ "en cliquant sur la " #~ msgid "door" #~ msgstr "porte" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " située à gauche du menu principal, ou avec le bouton " #~ msgid " button from the " #~ msgstr " à partir du menu " #~ msgid "NEW GAME" #~ msgstr "NOUVELLE PARTIE" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ ".\n" #~ "\n" #~ "Bon jeu !" #~ msgid "Warning!" #~ msgstr "Attention !" #~ msgid "Dummy 1" #~ msgstr "Emplacement 1" fheroes2-1.1.6+dfsg/files/lang/hu.po000066400000000000000000012230531476115357100171720ustar00rootroot00000000000000# Hungarian translation for fheroes2 # Copyright (C) 2024 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2023-09-04 21:55+0200\n" "Last-Translator: Berda JenÅ‘ \n" "Language-Team: Hungarian \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-Launchpad-Export-Date: 2011-06-02 03:12+0000\n" "X-Generator: Poedit 3.5\n" msgid "" "NEW\n" "GAME" msgstr "" "ÚJ\n" "JÃTÉK" msgid "" "SAVE\n" "GAME" msgstr "" "JÃTÉK\n" "MENTÉS" msgid "" "LOAD\n" "GAME" msgstr "" "JÃTÉK\n" "BETÖLTÉS" msgid "INFO" msgstr "INFÓ" msgid "QUIT" msgstr "KILÉPÉS" msgid "" "NEW\n" "MAP" msgstr "" "ÚJ\n" "TÉRKÉP" msgid "" "SAVE\n" "MAP" msgstr "" "TÉRKÉP\n" "MENTÉS" msgid "" "LOAD\n" "MAP" msgstr "" "TÉRKÉP\n" "BETÖLTÉS" msgid "CANCEL" msgstr "MÉGSEM" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "ELFOGAD" msgid "DECLINE" msgstr "ELUTASÃT" msgid "LEARN" msgstr "TANUL" msgid "TRADE" msgstr "ÜZLET" msgid "YES" msgstr "IGEN" msgid "NO" msgstr "NEM" msgid "EXIT" msgstr "KILÉP" msgid "smallerButton|EXIT" msgstr "EXIT" msgid "DISMISS" msgstr "ELBOCSÃT" msgid "UPGRADE" msgstr "FEJLESZT" msgid "RESTART" msgstr "ÚJRA" msgid "HEROES" msgstr "HÅSÖK" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "VÃROS\n" "/VÃR" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "XL" msgid "ALL" msgstr "MIND" msgid "SELECT" msgstr "VÃLASZT" msgid "" "STANDARD\n" "GAME" msgstr "" "NORMÃL\n" "JÃTÉK" msgid "" "BATTLE\n" "ONLY" msgstr "" "CSAK\n" "CSATA" msgid "" "CAMPAIGN\n" "GAME" msgstr "" "HADJÃRAT\n" "JÃTÉK" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "TÖBB-\n" "JÃTÉKOS\n" "MÓD" msgid "CONFIG" msgstr "OPCIÓK" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "EREDETI\n" "HADJÃRAT" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "KIEGÉSZÃTÅ\n" "HADJÃRAT" msgid "HOT SEAT" msgstr "HELYCSERE" msgid "2 PLAYERS" msgstr "2 JÃTÉKOS" msgid "3 PLAYERS" msgstr "3 JÃTÉKOS" msgid "4 PLAYERS" msgstr "4 JÃTÉKOS" msgid "5 PLAYERS" msgstr "5 JÃTÉKOS" msgid "6 PLAYERS" msgstr "6 JÃTÉKOS" msgid "GIFT" msgstr "AJÃND." msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "NEHÉZSÉG" msgid "VIEW INTRO" msgstr "BEVEZETÅ" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "ÚJRA" msgid "START" msgstr "START" msgid "TOWN" msgstr "VÃROS" msgid "CASTLE" msgstr "VÃR" msgid "RESTRICT" msgstr "KORLÃTOZ" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "E\n" "L\n" "B\n" "O\n" "C\n" "S\n" "Ã\n" "T" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "K\n" "I\n" "L\n" "É\n" "P" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "Å\n" "R\n" "J\n" "Ã\n" "R\n" "A\n" "T" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "H\n" "A\n" "D\n" "J\n" "Ã\n" "R\n" "A\n" "T" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "N\n" "O\n" "R\n" "M\n" "Ã\n" "L" msgid "RUMORS" msgstr "SZÓBESZÉDEK" msgid "EVENTS" msgstr "ESEMÉNYEK" msgid "LANGUAGE" msgstr "NYELV" msgid "" "AUTO\n" "COMBAT" msgstr "" "AUTOM.\n" "CSATA" msgid "" "QUICK\n" "COMBAT" msgstr "" "GYORS\n" "CSATA" msgid "Warrior" msgstr "Harcos" msgid "Builder" msgstr "ÉpítÅ‘" msgid "Explorer" msgstr "FelfedezÅ‘" msgid "None" msgstr "Nincs" msgid "" "A few\n" "%{monster}" msgstr "" "Néhány\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Több\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Tucatnyi\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Sok\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Hordányi\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Tömegnyi\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Többszáz\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Seregnyi\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Légiónyi\n" "%{monster}" msgid "army|Few" msgstr "Néhány" msgid "army|Several" msgstr "Több" msgid "army|Pack" msgstr "Tucat" msgid "army|Lots" msgstr "Sok" msgid "army|Horde" msgstr "Horda" msgid "army|Throng" msgstr "Tömeg" msgid "army|Swarm" msgstr "Többszáz" msgid "army|Zounds" msgstr "Sereg" msgid "army|Legion" msgstr "Légió" msgid "All %{race} troops +1" msgstr "Minden %{race} egység +1" msgid "NeutralRaceTroops|Neutral" msgstr "Semleges" msgid "Troops of %{count} alignments -%{penalty}" msgstr "%{count} féle csapatod van: -%{penalty}" msgid "Some undead in army -1" msgstr "ÉlÅ‘halottak a seregben -1" msgid "" "Default\n" "troop" msgstr "" "Alapért.\n" "csapat" msgid "View %{name}" msgstr "%{name} mutatása" msgid "Move the %{name} " msgstr "%{name} ide lép " msgid "Move or right click to redistribute %{name}" msgstr "Mozgasd vagy jobb gombot nyomj %{name} szétosztásához" msgid "Combine %{name} armies" msgstr "%{name} seregek egyesítése" msgid "Exchange %{name2} with %{name}" msgstr "%{name2} és %{name} cseréje" msgid "Select %{name}" msgstr "%{name} kiválasztása" msgid "Cannot move last troop" msgstr "A sereg utolsó egységét nem lehet áthelyezni" msgid "Move the %{name}" msgstr "%{name} ide lép" msgid "Set %{monster} Count" msgstr "%{monster} létszám beállítása" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} elpusztítja az ellenséges csapatok felét!" msgstr[1] "%{name} elpusztítják az ellenséges csapatok felét!" msgid "%{name} has turned off the auto combat" msgstr "%{name} kikapcsolta az automata csata módot" msgid "%{name} has turned on the auto combat" msgstr "%{name} bekapcsolta az automata csata módot" msgid "Spell failed!" msgstr "A varázslat meghiúsult!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "A Tagadás Gömbje varázstárgy hatására a csatában nem lehet varázsolni." msgid "You cannot cast spells without a commanding hero." msgstr "Nem varázsolhatsz hÅ‘s nélkül." msgid "You have already cast a spell this round." msgstr "Már varázsoltál ebben a körben." msgid "That spell will have no effect!" msgstr "Ez a varázslat nem hatásos senkire!" msgid "You may only summon one type of elemental per combat." msgstr "Csak egyféle elementált idézhetsz meg egy csatában." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "Nincs szabad hely a hÅ‘söd körül egy újabb Elementál idézéséhez." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "A várárok csökkenti a benne álló egység védelmi képességét %{count} " "százalékkal és korlátozza a mozgástartományát." msgid "Speed: %{speed}" msgstr "Sebesség: %{speed}" msgid "Speed" msgstr "Sebesség" msgid "Off" msgstr "Ki" msgid "On" msgstr "Be" msgid "Turn Order" msgstr "Körsorrend" msgid "Auto Spell Casting" msgstr "Automata varázslás" msgid "Grid" msgstr "Háló" msgid "Shadow Movement" msgstr "Mozgás árnyék" msgid "Shadow Cursor" msgstr "Kurzor árnyék" msgid "Audio" msgstr "Hang" msgid "Settings" msgstr "Beállítások" msgid "Configure" msgstr "Beállítás" msgid "Hot Keys" msgstr "" "Funkció-\n" "billentyűk" msgid "Damage Info" msgstr "Sebzés infó" msgid "Set the speed of combat actions and animations." msgstr "A harci cselekmények és animációk gyorsaságának beállítása." msgid "Toggle to display the turn order during the battle." msgstr "Csatában a támadási sorrend kijelzésének váltása." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Be- és kikapcsolja, hagy a gép automata csata idején varázsolhat-e vagy nem. " "(Figyelem! Ez nincs hatással arra, hogy az ellenfelek varázsolhatnak-e.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Be- és kikapcsolja a hatszögű rácsozat láthatóságát. A hatszögek mindenképp " "a mozgás alapját képezik, így a láthatóságuk kikapcsolásakor is." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "Be- és kikapcsolja az egységek mozgástartományát jelzÅ‘ árnyékot." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "Be- és kikapcsolja az egérkurzor alatti árnyékot." msgid "Change the audio settings of the game." msgstr "Itt lehet megváltoztatni a játék hangbeállításait." msgid "Check and configure all the hot keys present in the game." msgstr "A játékban használható billentyűkombinációk áttekintése és beállítása." msgid "Toggle to display damage information during the battle." msgstr "Be- és kikapcsolja a sebzés információkat a csatában." msgid "Exit this menu." msgstr "Kilépés a menübÅ‘l." msgid "Okay" msgstr "OK" msgid "The enemy has surrendered!" msgstr "Az ellenség megadta magát!" msgid "Their cowardice costs them %{gold} gold." msgstr "Gyávaságuk %{gold} aranyukba került." msgid "The enemy has fled!" msgstr "Az ellenség elmenekült!" msgid "A glorious victory!" msgstr "DicsÅ‘séges gyÅ‘zelem!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Vitézségéért %{name} %{exp} tapasztalati pontot kap." msgid "The cowardly %{name} flees from battle." msgstr "A gyáva %{name} elmenekül a csatából." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} megadja magát az ellenségnek és szégyenteljesen elvonul." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "A sereged súlyos vereséget szenvedett, ezért %{name} otthagy téged." msgid "Your forces suffer a bitter defeat." msgstr "A sereged súlyos vereséget szenvedett." msgid "Battlefield Casualties" msgstr "Harctéri veszteségek" msgid "Attacker" msgstr "Támadó" msgid "Defender" msgstr "VédekezÅ‘" msgid "Click to leave the battle results." msgstr "Kattints a csata eredményeibÅ‘l való kilépéshez." msgid "Click to restart the battle in manual mode." msgstr "Kattints a csata újrakezdéséhez kézi vezérléssel." msgid "Restart" msgstr "Újra" msgid "You have captured an enemy artifact!" msgstr "Megszereztél egy tárgyat az ellenségtÅ‘l!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Amint %{name} felé nyúlsz, az hirtelen eltűnik." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Amint %{name} felé nyúl az ellenség, az hirtelen eltűnik." msgid "Necromancy!" msgstr "Nekromancia!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "A nekromancia tudományának köszönhetÅ‘en képes vagy az ellenség seregében " "elhullott lényekbÅ‘l %{count} %{monster} lényt feltámasztani." msgid "%{name} the %{race}" msgstr "%{name} a %{race}" msgid "Captain of %{name}" msgstr "%{name} kapitánya" msgid "Attack" msgstr "Támadás" msgid "Defense" msgstr "Védekezés" msgid "Spell Power" msgstr "VarázserÅ‘" msgid "Knowledge" msgstr "Tudás" msgid "Morale" msgstr "Morál" msgid "Luck" msgstr "Szerencse" msgid "Spell Points" msgstr "Varázspontok" msgid "Hero's Options" msgstr "HÅ‘s beállításai" msgid "Cast Spell" msgstr "Varázslás" msgid "Retreat" msgstr "Visszavonulás" msgid "Surrender" msgstr "Megadás" msgid "Cancel" msgstr "Mégsem" msgid "Hero Screen" msgstr "HÅ‘s képernyÅ‘" msgid "Captain's Options" msgstr "Kapitány beállítások" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Varázslat idézés. A harc során körönként csak egyszer varázsolhatsz. A kör " "az összes egység lépése után indul újra." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "A visszavonuló hÅ‘söd, elhagyja a lényeidet. A hÅ‘st újra toborozhatod, habár " "a hÅ‘snek csak újonc serege lesz." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "A megadás aranyba kerül. Ha megfizeted a váltságdíjat, akkor a hÅ‘st és az " "összes túlélÅ‘ lényét újra toborozhatod. A megadás ára a csapatban maradó " "(kivéve a csata alatt megidézett lények, tükörképek) egységek árának fele." msgid "Open Hero Screen to view full information about the hero." msgstr "" "Nyisd meg a HÅ‘s képernyÅ‘t, hogy megnézhesd az összes információt a hÅ‘srÅ‘l." msgid "Return to the battle." msgstr "Visszatérés a csatába." msgid "Not enough gold (%{gold})" msgstr "Nincs elég aranyad (%{gold})" msgid "%{name} states:" msgstr "%{name} kinyilvánítja:" msgid "Captain of %{name} states:" msgstr "%{name} kapitánya kinyilvánítja:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Elfogadom a megadásodat és garantálom, hogy %{price} aranyért cserébe a " "csapatod szabadon távozhat.\"" msgid "View %{monster} info" msgstr "Megmutatja %{monster} információit" msgid "Fly %{monster} here" msgstr "%{monster} ide repül" msgid "Move %{monster} here" msgstr "%{monster} ide lép" msgid "Shoot %{monster}" msgstr "%{monster} lövése" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 lövés maradt)" msgstr[1] "(%{count} lövés maradt)" msgid "Attack %{monster}" msgstr "%{monster} támadása" msgid "Turn %{turn}" msgstr "Kör %{turn}" msgid "Teleport here" msgstr "Teleportálás ide" msgid "Invalid teleport destination" msgstr "Nem megfelelÅ‘ teleport cél" msgid "Cast %{spell} on %{monster}" msgstr "%{spell} varázslat idézése a(z) %{monster} lényre" msgid "Cast %{spell}" msgstr "%{spell} varázslat idézése" msgid "Select spell target" msgstr "Varázslat célpontjának kiválasztása" msgid "View Ballista info" msgstr "Hajítógép információk" msgid "Ballista" msgstr "Hajítógép" msgid "Automatic combat modes" msgstr "Automatikus csata módok" msgid "Automatic Combat Modes" msgstr "Automatikus csata módok" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "Válassz a csata automatikus vagy gyors lefolytatása között." msgid "Customize system options" msgstr "Rendszerbeállítások testreszabása" msgid "Allows you to customize the combat screen." msgstr "Harci képernyÅ‘ testreszabásának engedélyezése." msgid "System Options" msgstr "Rendszerbeállítások" msgid "Skip this unit" msgstr "Egység kimarad" msgid "Skip" msgstr "Kimarad" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Az aktuális egység kimarad egy lépésbÅ‘l, azaz köre véget ér és csak a " "következÅ‘ körben kerül rá sor újra." msgid "View Captain's options" msgstr "Kapitány beállításai" msgid "View Hero's options" msgstr "HÅ‘s beállításai" msgid "View opposing Captain" msgstr "Ellenséges kapitány megmutatása" msgid "View opposing Hero" msgstr "Ellenséges hÅ‘s megmutatása" msgid "Hide logs" msgstr "Napló elrejtése" msgid "Show logs" msgstr "Napló mutatása" msgid "Message Bar" msgstr "Üzenetsáv" msgid "Shows the results of individual monster's actions." msgstr "Mutatja egy lény tevékenységének eredményét." msgid "Are you sure you want to enable the auto combat mode?" msgstr "Biztos, hogy be akarod kapcsolni az automatikus csata módot?" msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Biztos vagy benne hogy gyors csata módban kívánod befejezni a csatát?" msgid "The computer continues the combat for you." msgstr "A számítógép folytatja helyetted a csatát." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" "Bármikor megszakítható az Automatikus csata gyorsbillentyű vagy a Mégse gomb " "lenyomására, illetve ha bárhol a játéktéren lenyomjuk valamelyik egérgombot." msgid "Auto Combat" msgstr "Automatikus csata" msgid "The combat is resolved from the current state." msgstr "A csata kimenetele a jelenlegi állapot szerint dÅ‘l el." msgid "quickCombat|This cannot be undone." msgstr "Ezt nem lehet visszavonni." msgid "Quick Combat" msgstr "Gyors csata" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} kihagy egy kört." msgstr[1] "%{name} kihagynak egy kört." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "A(z) %{attacker} %{damage} sebzést okoz." msgstr[1] "A(z) %{attacker} %{damage} sebzést okoz." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "egy lény elpusztult." msgstr[1] "%{count} lény elpusztult." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "egy %{defender} elpusztult." msgstr[1] "%{count} %{defender} elpusztult." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 lélek visszatért." msgstr[1] "%{count} lélek visszatért." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} újjáéledt." msgstr[1] "%{count} %{unit} újjáéledt." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "%{monster} mozgása: [%{src}] -> [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} ellenáll a varázslatnak!" msgstr[1] "%{name} ellenállnak a varázslatnak!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} %{spell} -t varázsol a %{troop} egységre." msgid "%{name} casts %{spell}." msgstr "%{name} megidézte ezt a varázslatot: %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "A %{spell} varázslat %{damage} sebzést okoz egy élÅ‘halottnak." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "" "A %{spell} varázslat %{damage} sebzést okoz valamennyi élÅ‘halott lénynek." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "" "A %{spell} varázslat %{damage} sebzést okoz, %{count} teremtmény elpusztul." msgid "The %{spell} does %{damage} damage." msgstr "The %{spell} varázslat %{damage} sebzést okoz." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "A %{spell} varázslat %{damage} sebzést okoz egy élÅ‘ lénynek." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "A %{spell} varázslat %{damage} sebzést okoz valamennyi élÅ‘ lénynek." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "A(z) %{attacker} megvakítja ezt a lényt: %{target}!" msgstr[1] "A(z) %{attacker} megvakítják ezt a lényt: %{target}!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "A(z) %{attacker} tekintete kÅ‘vé dermeszti ezt a lényt: %{target}!" msgstr[1] "A(z) %{attacker} tekintetei kÅ‘vé dermesztik ezt a lényt: %{target}!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "A(z) %{attacker} átka lesújt erre a lényre: %{target}!" msgstr[1] "A(z) %{attacker} átkai lesújtanak erre a lényre: %{target}!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "A(z) %{attacker} lebénítja ezt a lényt: %{target}!" msgstr[1] "A(z) %{attacker} lebénítják ezt a lényt: %{target}!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" "A(z) %{attacker} eloszlat minden pozitív varázslatot errÅ‘l a lényrÅ‘l: " "%{target}!" msgstr[1] "" "A(z) %{attacker} eloszlatnak minden pozitív varázslatot errÅ‘l a lényrÅ‘l: " "%{target}!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "A(z) %{attacker} %{spell} varázslatot szór a %{target} lényre!" msgstr[1] "A(z) %{attacker} %{spell} varázslatot szórnak a %{target} lényre!" msgid "Bad luck descends on the %{attacker}." msgstr "A támadó %{attacker} lénynek balszerencséje van." msgid "Good luck shines on the %{attacker}." msgstr "A támadó %{attacker} lénynek jó szerencséje van." msgid "High morale enables the %{monster} to attack again." msgstr "A jó morál következtében a(z) %{monster} újra támadhat." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Az alacsony morál miatt a(z) %{monster} pánikba esett és kimarad." msgid "%{tower} does %{damage} damage." msgstr "%{tower} sebzése: %{damage}." msgid "The mirror image is created." msgstr "Tükör képmás készült." msgid "The mirror image is destroyed!" msgstr "Tükör képmás megsemmisült!" msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Biztos, hogy meg akarod szakítani az automatikus csata módot?" msgid "Error" msgstr "Hiba" msgid "No spells to cast." msgstr "Nincsenek varázslataid." msgid "Are you sure you want to retreat?" msgstr "Biztos, hogy vissza akarsz vonulni?" msgid "Retreat disabled" msgstr "Visszavonulás nem lehetséges" msgid "Surrender disabled" msgstr "Megadás nem lehetséges" msgid "Damage: %{max}" msgstr "Sebzés: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Sebzés: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Megöl: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Megöl: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "%{name} sasszemével a következÅ‘ varázslatot lesi el és tanulja meg: %{spell}." msgid "Human" msgstr "Ember" msgid "AI" msgstr "Gép" msgid "Start" msgstr "Start" msgid "Start the battle." msgstr "Csata indítása." msgid "Exit" msgstr "Kilép" msgid "Reset" msgstr "Reset" msgid "Reset to default settings." msgstr "Alapbeállítások visszaállítása." msgid "Please select another hero." msgstr "Kérlek válassz másik hÅ‘st." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} és %{race2} %{name2} találkozik" msgid "Monsters" msgstr "Lények" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Bal torony" msgid "Right Turret" msgstr "Jobb torony" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} %{count} íjász erejével lÅ‘" msgid "each with a +%{attack} bonus to their attack skill." msgstr "mindenki +%{attack} támadóerÅ‘vel rendelkezik." msgid "The %{name} is destroyed." msgstr "A %{name} megsemmisült." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} lényt feltámasztottak a halálból!" msgstr[1] "%{count} %{name} lényt feltámasztottak a halálból!" msgid "Dwarven Alliance" msgstr "Törp Szövetség" msgid "Sorceress Guild" msgstr "VarázslónÅ‘ Testület" msgid "Necromancer Guild" msgstr "Nekromanta Testület" msgid "Ogre Alliance" msgstr "Ogre Szövetség" msgid "Dwarfbane" msgstr "Törpveszedelem" msgid "Dragon Alliance" msgstr "Sárkány Szövetség" msgid "Elven Alliance" msgstr "Tünde Szövetség" msgid "Kraeger defeated" msgstr "Kraeger legyÅ‘zetett" msgid "Wayward Son" msgstr "Önfejű fiú" msgid "Uncle Ivan" msgstr "Iván nagybácsi" msgid "Annexation" msgstr "Birtokbavétel" msgid "Force of Arms" msgstr "Fegyverek ereje" msgid "Save the Dwarves" msgstr "Mentsd meg a törpöket" msgid "Carator Mines" msgstr "Carator bányái" msgid "Turning Point" msgstr "Fordulópont" msgid "scenarioName|Defender" msgstr "VédÅ‘" msgid "Corlagon's Defense" msgstr "Corlagon oltalma" msgid "The Crown" msgstr "Korona" msgid "The Gauntlet" msgstr "A vesszÅ‘futás" msgid "Betrayal" msgstr "Ãrulás" msgid "Final Justice" msgstr "Utolsó ítélet" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Rolandnak szüksége van rád, hogy legyÅ‘zze a vára körüli uraságokat és " "megkezdje a bátyja elleni felkelést. Az uraságok nem szövetségesei " "egymásnak, idejüket az egymással való csatározásokkal töltik. Csak akkor " "tiéd a gyÅ‘zelem, ha elesett minden váruk és hÅ‘sük." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Helyi nagyurak megtagadták a hűségesküt Rolandnak, így erÅ‘vel kell Å‘ket " "igába hajtani. Gazdagok és erÅ‘sek, így kemény harcra kell felkészüljél. A " "gyÅ‘zelemhez minden ellenséges várat el kell foglalnod." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "A feladatod megvédeni a törpöket Archibald csapataitól. Minden ellenséges " "várat el kell foglalnod, de közben nem szabad elvesztened minden törp várat, " "különben veszítesz." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Négy, egymással szövetséges ellenféllel kell szembenézned egy nyílt csatában " "kincsekért és erÅ‘forrásokért. Foglalj el minden ellenséges várat a " "gyÅ‘zelemhez." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Ellenségeid szövetkeztek ellened és közelednek, így készen kell állnod a " "harcra. A kis völgy mind a négy várára szükséged lesz a gyÅ‘zelemhez." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Noraston boszorkányszövetsége a Roland segítségét kérte Archibald támadásai " "ellen. Foglalj el minden ellenséges várat és közben ne veszítsd el " "Norastont, különben elbukod a küldetést. (Tipp: van egy vár egy óceáni " "szigeten is)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Gyűjts akkora sereget, amennyit csak lehet és foglald el az ellenséges várat " "8 héten belül. Csak egy ellenfeled lesz, de hosszú út vezet a váráig. A " "küldetés végén megmaradt lényeidet tovább viheted a végsÅ‘ ütközetbe." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Találd meg a Koronát, mielÅ‘tt Archibald hÅ‘seik teszik meg ugyanezt. " "Rolandnak szüksége lesz a Koronára a végsÅ‘ összecsapásban Archibald ellen." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Három, egymással szövetséges ellenfél - köztük Lord Corlagon - áll közted és " "a gyÅ‘zelem között. Roland vára észak-nyugaton van, melyet nem veszíthetsz " "el. Ne feledd, Lord Corlagon elfogása biztosítja, hogy Å‘ ne harcoljon " "ellened a végsÅ‘ ütközetben." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Ez a végsÅ‘ ütközet. Te és ellenfeleid is állig felfegyverkezve várják a " "csatát. Fogd el Archibaldot és megnyered a háborút!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Miután átálltál a másik oldalra, három várad maradt az ellenség egyetlenével " "szemben. Ez a csata lesz a legkönnyebb, mellyel a háború további részében " "szembesülsz, te hitszegÅ‘." msgid "Barbarian Wars" msgstr "Barbár háborúk" msgid "First Blood" msgstr "ElsÅ‘ vérig" msgid "Necromancers" msgstr "Nekromanták" msgid "Slay the Dwarves" msgstr "Öld meg a törpöket" msgid "Country Lords" msgstr "Vidéki nagyurak" msgid "Dragon Master" msgstr "Sárkánymester" msgid "Rebellion" msgstr "Lázadás" msgid "Apocalypse" msgstr "Apokalipszis" msgid "Greater Glory" msgstr "Nagyobb dicsÅ‘ség" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Archibald királynak szüksége van rád, hogy legyÅ‘zze három ellenségét ezen a " "területen. Åk nem szövetségesei egymásnak, így energiáik nagy része az " "egymással való csatározásokra megy el. Te gyÅ‘zöl, ha a kezedre kerül az " "összes ellenséges vár és nincs több ellenséges hÅ‘s, aki harcolhatna ellened." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Egyesítened kell az északi barbár törzseket, miután leigáztad Å‘ket. Ahogy az " "elÅ‘zÅ‘ küldetésben, úgy az ellenségek most sem állnak szövetségben ellened, " "de több erÅ‘forrással rendelkeznek nálad. Te gyÅ‘zöl, ha a kezedre kerül az " "összes ellenséges vár és nincs több ellenséges hÅ‘s, aki harcolhatna ellened." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Jó varázslók elfoglalták a nekromanták várát. Vedd vissza a gyÅ‘zelemért. Ne " "feledd! Egy viszonylag erÅ‘s csapattal kezdesz, de nincs várad, és hogy ne " "veszítsd el a küldetést rögtön az elején, 7-non belül birtokba kell venned " "egyet. (Jótanács: A legközelebbi vár délkeletre van.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Le kell gyÅ‘zni a törpöket, mielÅ‘tt keresztülhúzzák Archibald király terveit. " "Roland erÅ‘inek egynél több hÅ‘se van és több vára kezdéskor, így légy résen, " "mert egyszerre több oldalról támadhatnak. Minden ellenséges várat és várost " "el kell foglalj a gyÅ‘zelemért." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Verd le a jobbágyfelkelést, melyet Roland követÅ‘i vezetnek. Mindegyik " "összeszövetkezett ellened, viszont téged erÅ‘sít Lord Corlagon, aki egy " "tapasztalt hÅ‘s. Foglalj el minden ellenséges várat a gyÅ‘zelemért." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Ebben a küldetésben két, egymással szövetséges ellenfeled lesz. MindkettÅ‘ " "erÅ‘s és azon vannak, hogy kiűzzenek téged a szigetükrÅ‘l. Kerüld Å‘ket és " "foglald el Sárkányvárost a gyÅ‘zelemért." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "A parancs szerint le kell gyÅ‘zzed a Rolandhoz hű nagyurakat a területen. " "Minden ellenséges vár egyesült ellened. Vár nélkül kezdesz és egy héten " "belül el kell foglalnod egyet. Vegyél be minden ellenséges várat a " "gyÅ‘zelemért." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Találd meg a Koronát Roland hÅ‘sei elÅ‘tt. Archibaldnak nagy szüksége lesz rá " "a Roland elleni végsÅ‘ csatában." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Ez a végsÅ‘ csata. Te és ellenségeid is állig fel vannak fegyverkezve és " "mindegyikük összeesküdött ellened. Fogd el Rolandot és tegyél róla, hogy ne " "veszítsd el Archibaldot a csatában!" msgid "Arrow's Flight" msgstr "A nyíl röpte" msgid "Island of Chaos" msgstr "A káosz szigete" msgid "The Abyss" msgstr "A szakadék" msgid "Uprising" msgstr "Felkelés" msgid "Aurora Borealis" msgstr "Sarki fény" msgid "Betrayal's End" msgstr "Az árulás vége" msgid "Corruption's Heart" msgstr "A romlás szíve" msgid "The Giant's Pass" msgstr "Óriás hágó" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Fékezd meg az engedetlen helyi nagyurakat, hogy elláthasd javakkal a " "Birodalmat és megszilárdítsd a hatalmát a régióban." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Pusztíts el minden ellenséget a területen. Eztán lesz tied a varázstárgy " "elsÅ‘ darabja." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Az északkeleti varázslónÅ‘k fellázadtak! A Birodalom érdekében fojtsd el " "csírájában erÅ‘tlen próbálkozásukat, útban a hegyek felé." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Jöttödre készülvén Kraeger intézkedéseket tett, hogy a nekromanták ereje " "meghiúsítsa a küldetésedet. Vedd be Scabsdale várát a harmadik hét elejéig " "különben a nektromanták felülkerekednek rajtad." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "A despota barbárok - eddig még - nincsenek tudatában a jelenlétednek a " "térségben. SürgÅ‘sen erÅ‘sítsd meg a csapataidat, míg fel nem fedeznek és rád " "nem támadnak! Biztosítsd a területet az ellenséges erÅ‘k kiiktatásával." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "A Birodalom hatalma gyenge ezen a területen. Nem fogod tudni teljesen " "legyÅ‘zni az ellenséges erÅ‘ket, úgyhogy vidd, amit csak lehet, még a várható " "megtorlás elÅ‘tt. Ne feledd! A cél Anduran sisakjának megszerzése." msgid "For the good of the Empire, eliminate Kraeger." msgstr "A Birodalom érdekében iktasd ki Kraegert." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Végre meg vannak a lehetÅ‘ségeid és eszközeid arra, hogy leigázd a " "nekromanták gonosz birodalmát. Pusztítsd el mindegyiküket és nevedet hÅ‘sként " "zengik majd örök idÅ‘kre." msgid "Border Towns" msgstr "Határvárosok" msgid "Conquer and Unify" msgstr "Hódíts és egyesíts" msgid "Crazy Uncle Ivan" msgstr "Årült Iván nagybácsi" msgid "The Wayward Son" msgstr "Önfejű fiú" msgid "Ivory Gates" msgstr "Elefántcsont kapuk" msgid "The Elven Lands" msgstr "Tünde vidék" msgid "The Epic Battle" msgstr "A hÅ‘sies csata" msgid "The Southern War" msgstr "A déli háború" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Hódítsd meg és egyesítsd az ellenséges törzseket. Ne hagyd veszni Jarkonast, " "minden leszármazott Å‘satyját." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "A rivális Harondale királyság megtámadta a határmenti gyengébb városaidat! " "Miután felocsúdtál az elsÅ‘ meglepetésbÅ‘l, morzsold fel Å‘ket mind egy szálig!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Találd meg önfejű fiadat, Josephet, aki a szóbeszéd szerint egy elhagyatott " "vidéken él. Meg kell találnod a harmadik hónap elejéig, különben nem lesz " "segítségére a családodnak." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Mentsd meg az Å‘rült Iván bácsikádat. Találd meg a negyedik hónap legelsÅ‘ " "napjáig, különben a királyságodon nem lehet segíteni." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Pusztítsd el a barbárokat, akik megtámadták királyságod déli határvidékét! " "Vedd vissza váraidat, majd hatolj be a dzsungel királyságba." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Vedd vissza Elefántcsont kapuk várát, mely árulás miatt veszett el." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Nyerd el a tündék kegyét. Åk nem engedik a fák kivágását, ezért kéthetente " "inkább maguk küldenek faanyagot. Be kell tudd fejezni a küldetést a hetedik " "hónap elejéig, különben a királyság menthetetlenül elesik." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Ez az utolsó csata a rivális Harondale királysággal. Pusztíts el mindenkit " "és ne veszítsd el VI. Jarkonas hÅ‘södet." msgid "Fount of Wizardry" msgstr "Varázslás forrása" msgid "Power's End" msgstr "A hatalom vége" msgid "The Eternal Scrolls" msgstr "Örök pergamenek" msgid "The Shrouded Isles" msgstr "Ködbe borult szigetek" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Az a küldetésed, hogy legyÅ‘zd a varázslatos ködbe borult szigetek háborúzó " "mágusait. A feladat teljesítése ad lehetÅ‘séget számodra a riválisaid ellen." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Megtalálták a nagy könyvtár pontos helyét! Utat kell találj oda és módot, " "hogy birtokba vegyed Chronost a várost, mely magában rejti." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Találd meg a Tagadás Gömbjét, melyrÅ‘l úgy tartják, hogy ezen a vidéken lett " "eltemetve. A hozzá vezetÅ‘ nyomok kÅ‘obeliszkekre vannak felvésve. Találd meg " "a Gömböt a hatodik hónap elejéig, különben ellenfeleid bízvást elorozzák " "elÅ‘led és elÅ‘bb érnek a varázslat forrásához." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Be kell vegyed a varázslatos Magic várat, ahol a varázslás forrása " "található. Ha sikerrel jársz, gyÅ‘zelmed döntÅ‘ jelentÅ‘ségű lesz." msgid "Blood is Thicker" msgstr "A vér nem válik vízzé" msgid "King and Country" msgstr "Király és ország" msgid "Pirate Isles" msgstr "Kalóz szigetek" msgid "Stranded" msgstr "Hajótörés" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Vedd be a várost a délkeleti partokon túli szigeten, hogy hajót ácsolva " "visszatérj a szárazföldre. Ne veszítsd el Gallavant hÅ‘södet." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Keresd meg és gyÅ‘zd le a kalózvezért, Martine-t, aki a Kalóz öbölben " "tanyázik. Ne veszítsd el Gallavant hÅ‘södet, különben a küldetésednek " "befellegzett." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Iktass ki minden más ellenséges erÅ‘t, aki szembe mer szállni Lord Alberon " "uralmával. Gallavant nem halhat meg." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Döntsd meg a védművekkel körbesáncolt Alberon monarchiát és követeld " "magadnak az egész vidéket. Gallavant nem halhat meg." msgid " bane" msgstr " veszedelem" msgid " alliance" msgstr " szövetség" msgid "Carry-over forces" msgstr "Ãtvitt csapatok" msgid " bonus" msgstr " bónusz" msgid " defeated" msgstr " legyÅ‘zetett" msgid " will always run away from your army." msgstr " mindig elmenekülnek majd a sereged elÅ‘l." msgid " will be willing to join your army." msgstr " csatlakozni szándékoznak majd a seregedhez." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "\"%{artifact}\" varázstárgy továbbvihetÅ‘ a hadjárat küldetéseire." msgid "The army will be carried over in the campaign." msgstr "A hadsereg továbbvihetÅ‘ a hadjárat küldetéseire." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Királyságod napi +%{count} %{resource} erÅ‘forrással gyarapszik." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "\"%{spell}\" varázslat továbbvihetÅ‘ a hadjárat küldetéseire." msgid "%{hero} can be hired during scenarios." msgstr "%{hero} hÅ‘s felvehetÅ‘ a küldetések alatt." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "%{hero} legyÅ‘zetett, így nem szerepel a további küldetésekben." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "A törpök felismerik a szövetségeseiket és szívesen csatlakoznak csapataidhoz." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Az ogrék felismerik benned a Törpveszedelmet és komótosan csatlakoznak " "hozzád." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "A sárkányok vicsorognak és morognak, majd beleegyeznek, hogy egyesítsék " "erÅ‘iket veled, a 'szövetségesükkel'." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Amint közeledsz a tündék csoportjához, hallod, hogy a vezetÅ‘jük a " "figyelmüket kéri és így kiállt: \"Ki elég bátor közületek, hogy csatlakozzon " "rettenthetetlen szövetségesünkhöz?\" A csoport éljenzésben tör ki és futnak, " "hogy beálljanak a soraid közé." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "A törpök fennhangon üdvözölnek téged: \"Bárki, aki Roland barátja, az a mi " "barátunk is egyben. Továbbhaladhatsz.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "Az ogrék elismerÅ‘en röfögnek: \"Archibald szövetségesei átkelhetnek.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "A sárkányok meglátnak és így kiáltanak: \"Archibalddal kötött szövetségünk " "arra kötelez, hogy csatlakozzunk hozzád. Azonban sajnos nincs hely a " "csapatodban. Nagy kár!\" Ezután gyorsan szétrebbennek." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "A tündék vigyázzba vágják magukat a közeledtedre. VezetÅ‘jük megszólít és azt " "mondja: \"Nem akadályozzuk az elÅ‘rehaladásodat, szövetségesünk! Haladj " "tovább és legyen a gyÅ‘zelem a tiéd.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Törp veszedelem! Fuss az életedért.\"" msgid "campaignBonus|Animate Dead" msgstr "Halott feltámasztás" msgid "campaignBonus|Chain Lightning" msgstr "Láncvillám" msgid "campaignBonus|Fireblast" msgstr "Tűzrobbanás" msgid "campaignBonus|Mass Curse" msgstr "Tömeges átok" msgid "campaignBonus|Mass Haste" msgstr "Tömeges gyorsítás" msgid "campaignBonus|Mirror Image" msgstr "Tükör képmás" msgid "campaignBonus|Resurrect" msgstr "Újjáélesztés" msgid "campaignBonus|Steelskin" msgstr "AcélbÅ‘r" msgid "campaignBonus|Summon Earth" msgstr "Föld idézés" msgid "campaignBonus|View Heroes" msgstr "HÅ‘sök mutatása" msgid "campaignBonus|Ballista" msgstr "Hajítógép" msgid "campaignBonus|Black Pearl" msgstr "Fekete gyöngy" msgid "campaignBonus|Caster's Bracelet" msgstr "Varázs Karperec" msgid "campaignBonus|Defender Helm" msgstr "VédÅ‘sisak" msgid "campaignBonus|Breastplate" msgstr "Mellvért" msgid "campaignBonus|Dragon Sword" msgstr "Sárkánykard" msgid "campaignBonus|Fizbin Medal" msgstr "Fizbin medál" msgid "campaignBonus|Foremost Scroll" msgstr "LegfÅ‘bb pergamentekercs" msgid "campaignBonus|Gauntlets" msgstr "Kesztyűk" msgid "campaignBonus|Hideous Mask" msgstr "Szörnyű Maszk" msgid "campaignBonus|Mage's Ring" msgstr "Varázsló gyűrűje" msgid "campaignBonus|Major Scroll" msgstr "Nagy pergamentekercs" msgid "campaignBonus|Medal of Honor" msgstr "Becsületrend" msgid "campaignBonus|Medal of Valor" msgstr "Vitézség medál" msgid "campaignBonus|Minor Scroll" msgstr "Kis pergamentekercs" msgid "campaignBonus|Nomad Boots" msgstr "Nomád csizma" msgid "campaignBonus|Power Axe" msgstr "Hatalom fejszéje" msgid "campaignBonus|Spiked Shield" msgstr "Tüskés pajzs" msgid "campaignBonus|Stealth Shield" msgstr "Tolvaj pajzs" msgid "campaignBonus|Tax Lien" msgstr "Adósságlevél" msgid "campaignBonus|Thunder Mace" msgstr "Mennydörgés pálcája" msgid "campaignBonus|Traveler's Boots" msgstr "Utazócsizma" msgid "campaignBonus|White Pearl" msgstr "Fehér gyöngy" msgid "campaignBonus|Basic Archery" msgstr "Alap íjászat" msgid "campaignBonus|Advanced Archery" msgstr "Haladó íjászat" msgid "campaignBonus|Expert Archery" msgstr "SzakértÅ‘ íjászat" msgid "campaignBonus|Basic Ballistics" msgstr "Alap ballisztika" msgid "campaignBonus|Advanced Ballistics" msgstr "Haladó ballisztika" msgid "campaignBonus|Expert Ballistics" msgstr "SzakértÅ‘ ballisztika" msgid "campaignBonus|Basic Diplomacy" msgstr "Alap diplomácia" msgid "campaignBonus|Advanced Diplomacy" msgstr "Haladó diplomácia" msgid "campaignBonus|Expert Diplomacy" msgstr "SzakértÅ‘ diplomácia" msgid "campaignBonus|Basic Eagle Eye" msgstr "Alap sasszem" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Haladó sasszem" msgid "campaignBonus|Expert Eagle Eye" msgstr "SzakértÅ‘ sasszem" msgid "campaignBonus|Basic Estates" msgstr "Alap vagyon" msgid "campaignBonus|Advanced Estates" msgstr "Haladó vagyon" msgid "campaignBonus|Expert Estates" msgstr "SzakértÅ‘ vagyon" msgid "campaignBonus|Basic Leadership" msgstr "Alap vezetés" msgid "campaignBonus|Advanced Leadership" msgstr "Haladó vezetés" msgid "campaignBonus|Expert Leadership" msgstr "SzakértÅ‘ vezetés" msgid "campaignBonus|Basic Logistics" msgstr "Alap logisztika" msgid "campaignBonus|Advanced Logistics" msgstr "Haladó logisztika" msgid "campaignBonus|Expert Logistics" msgstr "SzakértÅ‘ logisztika" msgid "campaignBonus|Basic Luck" msgstr "Alap szerencse" msgid "campaignBonus|Advanced Luck" msgstr "Haladó szerencse" msgid "campaignBonus|Expert Luck" msgstr "SzakértÅ‘ szerencse" msgid "campaignBonus|Basic Mysticism" msgstr "Alap misztika" msgid "campaignBonus|Advanced Mysticism" msgstr "Haladó misztika" msgid "campaignBonus|Expert Mysticism" msgstr "SzakértÅ‘ misztika" msgid "campaignBonus|Basic Navigation" msgstr "Alap navigáció" msgid "campaignBonus|Advanced Navigation" msgstr "Fejlett navigáció" msgid "campaignBonus|Expert Navigation" msgstr "SzakértÅ‘ navigáció" msgid "campaignBonus|Basic Necromancy" msgstr "Alap nekromancia" msgid "campaignBonus|Advanced Necromancy" msgstr "Haladó nekromancia" msgid "campaignBonus|Expert Necromancy" msgstr "SzakértÅ‘ nekromancia" msgid "campaignBonus|Basic Pathfinding" msgstr "Alap nyomkövetés" msgid "campaignBonus|Advanced Pathfinding" msgstr "Haladó nyomkövetés" msgid "campaignBonus|Expert Pathfinding" msgstr "SzakértÅ‘ nyomkövetés" msgid "campaignBonus|Basic Scouting" msgstr "Alap felderítés" msgid "campaignBonus|Advanced Scouting" msgstr "Haladó felderítés" msgid "campaignBonus|Expert Scouting" msgstr "SzakértÅ‘ felderítés" msgid "campaignBonus|Basic Wisdom" msgstr "Alap bölcsesség" msgid "campaignBonus|Advanced Wisdom" msgstr "Haladó bölcsesség" msgid "campaignBonus|Expert Wisdom" msgstr "SzakértÅ‘ bölcsesség" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "A fÅ‘hÅ‘s \"%{artifact}\" varázstárgy birtokában kezdi a küldetést." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "A királyság %{amount} %{resource} plusz erÅ‘forrással indul a küldetésben." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "A királyság %{amount} %{resource} erÅ‘forrással kevesebbel indul a " "küldetésben." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "A fÅ‘hÅ‘s %{count} %{monster} lénnyel kezdi meg a küldetést." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "A fÅ‘hÅ‘s \"%{spell}\" varázslat birtokában kezdi meg a küldetést." msgid "The starting alignment of the scenario will be %{race}." msgstr "%{race} kezd elÅ‘ször a küldetésben." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "A fÅ‘hÅ‘s +%{count} %{skill} képesség birtokában kezdi a küldetést." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "A fÅ‘hÅ‘s %{skill} képesség birtokában kezdi a küldetést." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" msgid "Price of Loyalty" msgstr "A hűség ára" msgid "Voyage Home" msgstr "Hazaút" msgid "Wizard's Isle" msgstr "Varázsló-sziget" msgid "Descendants" msgstr "Utódok" msgid "Cannot build. You have already built here today." msgstr "Nem építhetÅ‘. Már építettél ide ebben körben." msgid "For this action it is necessary to build a castle first." msgstr "Ehhez a művelethez elÅ‘ször a várat kell felépíteni." msgid "The %{building} produces %{monster}." msgstr "A(z) %{building} %{monster}-t hoz létre." msgid "Requires:" msgstr "ElÅ‘feltétel:" msgid "Exit this menu without doing anything." msgstr "Kilépés ebbÅ‘l a menübÅ‘l, bármilyen cselekvés nélkül." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "" "Nem lehet megépíteni ezt: %{name}, mert a vár túl messze van az óceántól." msgid "This building has been disabled." msgstr "Az építmény tiltott." msgid "Cannot afford the %{name}." msgstr "Nem engedheted meg magadnak ezt: %{name}." msgid "The %{name} is already built." msgstr "%{name} már fel van építve." msgid "Cannot build the %{name}." msgstr "Nem tudod felépíteni ezt: %{name}." msgid "Build %{name}." msgstr "%{name} építése." msgid "Blackridge" msgstr "Blackridge" msgid "Hillstone" msgstr "Hillstone" msgid "Pinehurst" msgstr "Pinehurst" msgid "Whiteshield" msgstr "Whiteshield" msgid "Woodhaven" msgstr "Woodhaven" msgid "Blackwind" msgstr "Blackwind" msgid "Bloodreign" msgstr "Bloodreign" msgid "Dragontooth" msgstr "Dragontooth" msgid "Greywind" msgstr "Greywind" msgid "Portsmith" msgstr "Portsmith" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Middle Gate" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "Baywatch" msgid "Fountainhead" msgstr "Fountainhead" msgid "Vertigo" msgstr "Vertigo" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Winterkill" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Lakeside" msgid "Nightshadow" msgstr "Nightshadow" msgid "Olympus" msgstr "Olümposz" msgid "Sandcaster" msgstr "Sandcaster" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "New Dawn" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Big Oak" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antiókhia" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Rukh menedék" msgid "South Mill" msgstr "South Mill" msgid "Weed Patch" msgstr "Weed Patch" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Hilltop" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Westfork" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "ElkfÅ‘" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Blackburn" msgid "Blacksford" msgstr "Blacksford" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Pig's Eye" msgid "Viper's Nest" msgstr "Viperafészek" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Timberhill" msgid "Troy" msgstr "Trója" msgid "Forder Oaks" msgstr "Forder Oaks" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Quick Silver" msgid "Westmoor" msgstr "Westmoor" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Nem lehet tobrozni - van már hÅ‘söd ebben a városban." msgid "Cannot recruit - you have too many Heroes." msgstr "Nem lehet tobrozni - túl sok hÅ‘söd van." msgid "Cannot afford a Hero." msgstr "Nem engedhetsz meg magadnak hÅ‘st." msgid "There is no room in the garrison for this army." msgstr "Nincs elég hely a helyÅ‘rségben a csapat számára." msgid "Fortifications" msgstr "ErÅ‘dítmények" msgid "Farm" msgstr "Szántóföldek" msgid "Thatched Hut" msgstr "Nádkunyhó" msgid "Archery Range" msgstr "Ãjászpálya" msgid "Upg. Archery Range" msgstr "Fejl. íjászpálya" msgid "Blacksmith" msgstr "Kovácsműhely" msgid "Upg. Blacksmith" msgstr "Fejl. kovácsműhely" msgid "Armory" msgstr "Fegyverkovács" msgid "Upg. Armory" msgstr "Fejl. fegyverkovács" msgid "Jousting Arena" msgstr "Lovarda" msgid "Upg. Jousting Arena" msgstr "Fejl. lovarda" msgid "Cathedral" msgstr "Katedrális" msgid "Upg. Cathedral" msgstr "Fejl. katedrális" msgid "Coliseum" msgstr "Kolosszeum" msgid "Garbage Heap" msgstr "Szemétdomb" msgid "Hut" msgstr "Kunyhó" msgid "Stick Hut" msgstr "Fakunyhó" msgid "Upg. Stick Hut" msgstr "Fejl. fakunyhó" msgid "Den" msgstr "Barlang" msgid "Adobe" msgstr "Vályogház" msgid "Upg. Adobe" msgstr "Fejl. vályogház" msgid "Bridge" msgstr "Híd" msgid "Upg. Bridge" msgstr "Fejl. híd" msgid "Pyramid" msgstr "Piramis" msgid "Rainbow" msgstr "Szivárvány" msgid "Crystal Garden" msgstr "Kristálykert" msgid "Treehouse" msgstr "Fa ház" msgid "Cottage" msgstr "Törp kunyhó" msgid "Upg. Cottage" msgstr "Fejl. törp kunyhó" msgid "Stonehenge" msgstr "KÅ‘kör" msgid "Upg. Stonehenge" msgstr "Fejl. kÅ‘kör" msgid "Fenced Meadow" msgstr "LegelÅ‘" msgid "sorceress|Red Tower" msgstr "Vörös torony" msgid "Dungeon" msgstr "Kazamata" msgid "Waterfall" msgstr "Vízesés" msgid "Cave" msgstr "Barlang" msgid "Crypt" msgstr "Kripta" msgid "Nest" msgstr "Fészek" msgid "Maze" msgstr "ÚtvesztÅ‘" msgid "Upg. Maze" msgstr "Fejl. útvesztÅ‘" msgid "Swamp" msgstr "Mocsár" msgid "Green Tower" msgstr "Zöld torony" msgid "warlock|Red Tower" msgstr "Vörös torony" msgid "Black Tower" msgstr "Fekete torony" msgid "Library" msgstr "Könyvtár" msgid "Orchard" msgstr "Gyümölcsöskert" msgid "Habitat" msgstr "Félszerzet-lak" msgid "Pen" msgstr "Akol" msgid "Foundry" msgstr "Öntöde" msgid "Upg. Foundry" msgstr "Fejl. Öntöde" msgid "Cliff Nest" msgstr "Sziklafészek" msgid "Ivory Tower" msgstr "Elefántcsont torony" msgid "Upg. Ivory Tower" msgstr "Fejl. elefántcsont torony" msgid "Cloud Castle" msgstr "Fellegvár" msgid "Upg. Cloud Castle" msgstr "Fejl. fellegvár" msgid "Storm" msgstr "Vihar" msgid "Skull Pile" msgstr "Csonthalom" msgid "Excavation" msgstr "Ãsatás" msgid "Graveyard" msgstr "Sírkert" msgid "Upg. Graveyard" msgstr "Fejl. sírkert" msgid "Upg. Pyramid" msgstr "Fejl. piramis" msgid "Mansion" msgstr "Kúria" msgid "Upg. Mansion" msgstr "Fejl. kúria" msgid "Mausoleum" msgstr "Mauzóleum" msgid "Upg. Mausoleum" msgstr "Fejl. mauzóleum" msgid "Laboratory" msgstr "Laboratórium" msgid "Shrine" msgstr "Szentély" msgid "Special" msgstr "Különleges" msgid "Horde Building" msgstr "Sereg épület" msgid "Dwelling 1" msgstr "Toborzóhely 1" msgid "Dwelling 2" msgstr "Toborzóhely 2" msgid "Upg. Dwelling 2" msgstr "Fejl. toborzóhely 2" msgid "Dwelling 3" msgstr "Toborzóhely 3" msgid "Upg. Dwelling 3" msgstr "Fejl. toborzóhely 3" msgid "Dwelling 4" msgstr "Toborzóhely 4" msgid "Upg. Dwelling 4" msgstr "Fejl. toborzóhely 4" msgid "Dwelling 5" msgstr "Toborzóhely 5" msgid "Upg. Dwelling 5" msgstr "Fejl. toborzóhely 5" msgid "Dwelling 6" msgstr "Toborzóhely 6" msgid "Upg. Dwelling 6" msgstr "Fejl. toborzóhely" msgid "2x Upg. Dwelling 6" msgstr "2x fejl. toborzóhely" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Az ErÅ‘dítmények növelik a várfalak védelmét, melynek hatására több lövéssel " "lehet lerombolni Å‘ket." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" "A szántóföldek a jobbágyok szaporulatát hetente ennyivel növelik: %{count}." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "A Kolosszeum látványa lelkesíti a védÅ‘ket, ezért a moráljuk kettÅ‘vel nÅ‘ a " "csata idejére." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" "A Szemétdomb a Goblinok szaporulatát hetente ennyivel növeli: %{count}." msgid "The Rainbow increases the luck of the defending units by two." msgstr "A Szivárvány növeli a védÅ‘egységek szerencséjét kettÅ‘vel." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" "A Kristálykert a Tündérek szaporulatát hetente ennyivel növeli: %{count}." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "A Várbörtön naponta %{count} arannyal növeli a város bevételét." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "A Vízesés a Kentaurok szaporulatát hetente ennyivel növeli: %{count}." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "A könyvtár növeli a varázstorony varázslatainak számát eggyel mindegyik " "szinten." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" "A Gyümölcsöskert a Félszeretek szaporulatát hetente ennyivel növeli: " "%{count}." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "A Vihar növeli a védÅ‘ varázserejét kettÅ‘vel." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" "A Koponyahalom a Csontvázak termelÅ‘dését hetente ennyivel növeli: %{count}." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" "A különleges építmény egy különleges bónuszt ad a kiválasztott vártípushoz." msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "A Sereg épület 8-ccal növeli az 1. szintű lények szaporulatát." msgid "Thieves' Guild" msgstr "Tolvajcéh" msgid "Tavern" msgstr "Fogadó" msgid "Shipyard" msgstr "Hajógyár" msgid "Well" msgstr "Kút" msgid "Statue" msgstr "Szobor" msgid "Marketplace" msgstr "Piactér" msgid "Moat" msgstr "Várárok" msgid "Castle" msgstr "Vár" msgid "Tent" msgstr "Sátor" msgid "Captain's Quarters" msgstr "Kapitány Å‘rház" msgid "Mage Guild, Level 1" msgstr "Varázstorony, 1. szint" msgid "Mage Guild, Level 2" msgstr "Varázstorony, 2. szint" msgid "Mage Guild, Level 3" msgstr "Varázstorony, 3. szint" msgid "Mage Guild, Level 4" msgstr "Varázstorony, 4. szint" msgid "Mage Guild, Level 5" msgstr "Varázstorony, 5. szint" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "A Szentély növeli az összes nekromantád nekromancia képességét 10%-kal." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "A Tolvajcéh tagjai hasznos információkkal tudnak szolgálni az ellenfelekrÅ‘l, " "illetve kémkedhetnek az ellenséges városokban." msgid "The Tavern increases morale for troops defending the castle." msgstr "A Fogadó növeli a várvédÅ‘ katonák morálját." msgid "The Shipyard allows ships to be built." msgstr "A Hajógyárban építhetsz hajókat." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "A Kút hetente ennyivel növeli az összes lény szaporulatát: %{count}." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "A Szobor naponta ennyivel növeli a város bevételét: %{count}." msgid "The Left Turret provides extra firepower during castle combat." msgstr "A Bal Torony megnöveli a várvédÅ‘id tűzerejét ostrom idején." msgid "The Right Turret provides extra firepower during castle combat." msgstr "A Jobb Torony megnöveli a várvédÅ‘id tűzerejét ostrom idején." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "A Piactéren vásárolhatsz és eladhatsz nyersanyagokat. Több Piactér " "birtoklása javítja az átváltási arányt." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "A Vizesárok lassítja a támadó egységeket. Minden egység, aki belelép az " "árokba, ott be kell fejezze a körét és sebezhetÅ‘bbé válik." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "A Vár javítja a város védelmét és naponta %{count} arannyal növeli a " "bevételét." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "A Sátor biztosítja a munkásokat a vár felépítéséhez a megfelelÅ‘ mennyiségű " "nyersanyag és arany rendelkezésre állása esetén." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "A Kapitány Å‘rház egy várkapitányt biztosít, aki segít a város védelmében, " "amikor nincs hÅ‘s a várban." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "A Varázstorony lehetÅ‘vé teszi varázslatok megtanulását és a varázspontok " "feltöltését." msgid "Recruit %{name}" msgstr "%{name} toborzása" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Hónap: %{month}, hét: %{week}, nap: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Ahhoz, hogy használhasd a varázstoronyban lévÅ‘ varázslatokat, szükséged van " "varázskönyvre, de nincs szabad hely a könyv számára. Próbálj meg egy " "varázstárgyat átadni egy másik hÅ‘snek." msgid "Click to show next town." msgstr "Kattints a következÅ‘ város mutatásához." msgid "Show next town" msgstr "KövetkezÅ‘ város mutatása" msgid "Click to show previous town." msgstr "Kattints az elÅ‘zÅ‘ város mutatásához." msgid "Show previous town" msgstr "ElÅ‘zÅ‘ város mutatása" msgid "This town may not be upgraded to a castle." msgstr "Ezt a várost nem lehet várrá fejleszteni." msgid "Town" msgstr "Város" msgid "Exit Castle" msgstr "Kilépés a várból" msgid "Exit Town" msgstr "Kilépés a városból" msgid "Show Income" msgstr "Jövedelem mutatása" msgid "View Hero" msgstr "HÅ‘s mutatása" msgid "The above spells are available here." msgstr "A fenti varázslatok érhetÅ‘k el itt." msgid "The spells the hero can learn have been added to their book." msgstr "A hÅ‘s által megtanulható varázslatok beíródtak a varázskönyvébe." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" "A nagylelkű borravalód hatására a csapos a következÅ‘ szóbeszédet osztja meg " "veled:" msgid "Recruit Hero" msgstr "HÅ‘s toborzása" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} %{value}. szintű %{race} " msgid "with %{count} artifacts." msgstr "%{count} varázstárggyal." msgid "with 1 artifact." msgstr "egy varázstárggyal." msgid "without artifacts." msgstr "varázstárgyak nélkül." msgid "Recruit %{name} the %{race}" msgstr "%{name} a %{race} toborzása" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Laza' csataalakzatban a várvédÅ‘ egységeid szétszóródva helyezkednek el a " "harcmezÅ‘n fentrÅ‘l lefelé, úgy, hogy legalább 1 üres hely marad közöttük." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "'Szoros' csataalakzatban a várvédÅ‘ egységeid szorosan egymás mellett " "helyezkednek el a harcmezÅ‘ várvédÅ‘ oldalának közepén." msgid "Spread Formation" msgstr "Laza felállás" msgid "Grouped Formation" msgstr "Szoros felállás" msgid "Click to show the next town." msgstr "Kattints a következÅ‘ város mutatásához." msgid "Click to show the previous town." msgstr "Kattints az elÅ‘zÅ‘ város mutatásához." msgid "Set garrison combat formation to 'Spread'" msgstr "A helyÅ‘rség csataalakzata legyen 'Laza'." msgid "Set garrison combat formation to 'Grouped'" msgstr "A helyÅ‘rség csataalakzata legyen 'Szoros'." msgid "Exit Castle Options" msgstr "Kilépés a vár beállításokból" msgid "Castle Options" msgstr "Vár beállítások" msgid "Not enough resources to recruit creatures." msgstr "Nincs elég erÅ‘forrás a lények toborzásához." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Most nem tudsz toborozni, a csapatod tele van." msgid "No creatures available for purchase." msgstr "Nincsenek megvásárolható lények." msgid "Recruit Creatures" msgstr "Lények toborzása" msgid "Hire all creatures in the town." msgstr "Összes lény toborzása." msgid "Max" msgstr "Max" msgid "Available" msgstr "ElérhetÅ‘" msgid "Town Population Information and Statistics" msgstr "A város lakosságának adatai és statisztikái" msgid "Damage" msgstr "Sebzés" msgid "HP" msgstr "ÉleterÅ‘" msgid "Growth" msgstr "Szaporulat" msgid "week" msgstr "hét" msgid "View World" msgstr "Világ mutatása" msgid "View the entire world." msgstr "Az egész világ mutatása." msgid "Puzzle" msgstr "Rejtvény" msgid "View the obelisk puzzle." msgstr "Az obeliszk rejtvény mutatása." msgid "Scenario Information" msgstr "Küldetés információ" msgid "View information on the scenario you are currently playing." msgstr "Nézd meg az éppen játszott küldetés információit." msgid "Dig for the Ultimate Artifact." msgstr "A Szent Varázstárgy kiásása." msgid "Digging" msgstr "Ãsás" msgid "Arena" msgstr "Aréna" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Belépve a küzdÅ‘térre egy csomó megvadult oroszlánnal találod szembe magad, " "melyeket könnyedén leterítesz a tömeg éljenzése közepette. Látva a " "tehetségedet az idÅ‘s gladiátormester felajánlja, hogy kiképzést ad neked egy " "választott képességbÅ‘l." msgid "Attack Skill" msgstr "TámadóerÅ‘" msgid "Defense Skill" msgstr "VédÅ‘erÅ‘" msgid "Shots" msgstr "Lövések" msgid "Shots Left" msgstr "Maradék lövés" msgid "Hit Points" msgstr "ÉleterÅ‘" msgid "Hit Points Left" msgstr "Maradék élete." msgid "You can't afford to upgrade your troops!" msgstr "Nem engedheted meg magadnak a csapatok fejlesztését!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Felfejlesztheted a csoportot, de ez többe kerül. Fel szeretnéd fejleszteni " "Å‘ket?" msgid "Are you sure you want to dismiss this army?" msgstr "Biztos vagy benne hogy feloszlatod ezt a sereget?" msgid "Upgrade" msgstr "Fejlesztés" msgid "Upgrade your troops." msgstr "Fejleszti a csapataidat." msgid "Dismiss" msgstr "Elbocsátás" msgid "Dismiss this army." msgstr "Sereg feloszlatása." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "%{monster} csoportja a nagyobb dicsÅ‘ség reményében csatlakozna hozzád.\n" "Elfogadod Å‘ket?" msgid "Followers" msgstr "Csatlakozók" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} a diplomatikus modorod hatására hajlanak rá, hogy csatlakozzanak " "hozzád %{gold} arany ellenében.\n" "Elfogadod?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "A diplomáciai képességed hatására a lények \n" "egy ajánlattal állnak elÅ‘:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{total} lénybÅ‘l %{offer} %{monster} csatlakozna hozzád összesen %{gold} " "aranyért. A többiek pedig szabadon távoznának.\n" "Elfogadod az ajánlatot?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "%{offer} %{monster} mindegyike csatlakozna hozzád összesen %{gold} " "aranyért.\n" "Elfogadod az ajánlatukat?" msgid "(Rate: %{percent})" msgstr "(Arány: %{percent})" msgid "off" msgstr "ki" msgid "Music" msgstr "Zene" msgid "Effects" msgstr "Effektusok" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI kiegészítÅ‘" msgid "External" msgstr "KülsÅ‘" msgid "Music Type" msgstr "Zene típusa" msgid "3D Audio" msgstr "3D hangzás" msgid "Toggle ambient music level." msgstr "Háttérzene jelszint kapcsolója." msgid "Toggle foreground sounds level." msgstr "Hanghatások jelszint kapcsolója." msgid "Change the type of music." msgstr "Zene típusának megváltoztatása." msgid "Toggle the 3D effect of foreground sounds." msgstr "SzembÅ‘l jövÅ‘ 3D hanghatások kapcsolója." msgid "Build a new ship:" msgstr "Új hajó építése:" msgid "Resource cost:" msgstr "ErÅ‘forrás költség:" msgid "Total: " msgstr "Összesen: " msgid "Need: " msgstr "Szükséges: " msgid "New Game" msgstr "Új játék" msgid "Start a single or multi-player game." msgstr "Egy- vagy többszemélyes játék indítása." msgid "Load Game" msgstr "Játék betöltése" msgid "Load a previously saved game." msgstr "Mentett játék betöltése." msgid "Save Game" msgstr "Játék mentése" msgid "Save the current game." msgstr "Aktuális játék mentése." msgid "Quit" msgstr "Kilépés" msgid "Quit out of Heroes of Might and Magic II." msgstr "Kilépés a Heroes of Might and Magic II-bÅ‘l." msgid "Language" msgstr "Nyelv" msgid "Graphics" msgstr "Grafika" msgid "Black & White" msgstr "Fekete-fehér" msgid "Mouse Cursor" msgstr "Egér kurzor" msgid "Color" msgstr "Szín" msgid "Text Support" msgstr "Szöveg támogatás" msgid "Change the language of the game." msgstr "A játék nyelvének megváltoztatása." msgid "Select Game Language" msgstr "Játék nyelvének kiválasztása" msgid "Change the graphics settings of the game." msgstr "Játék grafikai beállításainak módosítása." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" "Színes kurzor be-/kikapcsolása. Ez csak egy esztétikai jellegű választás." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "A szöveges támogatás kapcsolója, mellyel extra információkhoz juthatunk a " "játék párbeszédablakairól, illetve eseményeirÅ‘l." msgid "" "Map\n" "Difficulty" msgstr "" "Térkép\n" "nehézség" msgid "" "Game\n" "Difficulty" msgstr "" "Játék\n" "nehézség" msgid "Rating" msgstr "Besorolás" msgid "Map Size" msgstr "" "Térkép\n" "mérete" msgid "Opponents" msgstr "Ellenfelek" msgid "Class" msgstr "Osztály" msgid "" "Victory\n" "Conditions" msgstr "" "GyÅ‘zelmi\n" "feltételek" msgid "" "Loss\n" "Conditions" msgstr "" "Vesztési\n" "feltételek" msgid "First select recipients!" msgstr "ElÅ‘ször válaszd ki a kedvezményezetteket!" msgid "You cannot select %{resource}!" msgstr "Nem választhatod a(z) %{resource} erÅ‘forrást!" msgid "Set %{resource-type} Count" msgstr "%{resource-type} mennyiség beállítása" msgid "Select Recipients" msgstr "Kedvezményezettek kiválasztása" msgid "Your Funds" msgstr "Forrásaid" msgid "Planned Gift" msgstr "Tervezett ajándék" msgid "Gift from %{name}" msgstr "Ajándék %{name} játékostól" msgid "Resolution" msgstr "Felbontás" msgid "Fullscreen" msgstr "Teljes képernyÅ‘" msgid "window|Mode" msgstr "Mód" msgid "Windowed" msgstr "Ablakos" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "" "Rendszer-\n" "információk" msgid "Change the resolution of the game." msgstr "A játék felbontásának megváltoztatása." msgid "Select Game Resolution" msgstr "Játék felbontás kiválasztása" msgid "Toggle between fullscreen and windowed modes." msgstr "Váltás teljes képernyÅ‘s és ablakos mód között." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "A V-Sync opciót akkor érdemes használni, amikor egyes monitorokon vibrálást " "tapasztalunk." msgid "Show extra information such as FPS and current time." msgstr "Extra információkat jelenít meg, mint például FPS, illetve pontos idÅ‘." msgid "Hotkey: " msgstr "Gyorsbillentyű: " msgid "Category: " msgstr "Kategória: " msgid "Event: " msgstr "Esemény: " msgid "Hot Keys:" msgstr "Billentyűfunkciók:" msgid "Hide" msgstr "Elrejt" msgid "Show" msgstr "Mutat" msgid "Interface" msgstr "KezelÅ‘felület" msgid "Interface Type" msgstr "KezelÅ‘felület típusa" msgid "Toggle the type of interface you want to use." msgstr "KezelÅ‘felület kívánt típusának kapcsolója." msgid "Toggle interface visibility." msgstr "KezelÅ‘felület láthatóságának kapcsolója." msgid "Scroll Speed" msgstr "KépernyÅ‘görgetés sebessége" msgid "Sets the speed at which you scroll the window." msgstr "Beállítja az ablakok görgetésének sebességét." msgid "Select Game Language:" msgstr "Játék nyelvének kiválasztása:" msgid "Select Language:" msgstr "Nyelv kiválasztása:" msgid "Click to choose the selected language." msgstr "Kattints a kijelölt nyelv kiválasztásához." msgid "%{name} has gained a level." msgstr "%{name} a következÅ‘ szintre lépett." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "%{skill} képességre tettél szert." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} a következÅ‘ szintre lépett.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Tanulható:\n" "%{skill1}\n" "vagy\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/a" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Kérem tekintsd meg nagyszerű portékáinkat. Amennyiben kereskedni kívánsz, " "kattints arra az elemre, amit és amire cserélni akarsz." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Jó alkut kötöttél. Nem várok el nyereséget az üzleten. Érdekel esetleg más " "áru is?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "%{count}-t ajánlok 1 darab %{resfrom}-ért." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "1 darab %{resto}-t ajánlok %{count} darab %{resfrom}-ért." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Darab eladása" msgid "Trading Post" msgstr "Kereskedelmi állomás" msgid "Your Resources" msgstr "ErÅ‘forrásaid" msgid "Available Trades" msgstr "Üzleti lehetÅ‘ségek" msgid "guarded by %{count} %{monster}" msgstr "%{count} %{monster} Å‘rzi." msgid "guarded by " msgstr "Å‘rzÅ‘k: " msgid "(available: %{count})" msgstr "(elérhetÅ‘: %{count})" msgid "(empty)" msgstr "(üres)" msgid "already learned" msgstr "már ismered" msgid "treeOfKnowledge|free" msgstr "ingyenes" msgid "already claimed" msgstr "már megszerzett" msgid "not claimed" msgstr "még nem megszerzett" msgid "already knows this skill" msgstr "már bírsz ezzel a képességgel" msgid "already has max skills" msgstr "már elérted a max. képességet" msgid "(already visited)" msgstr "(már meglátogatott)" msgid "(not visited)" msgstr "(nem látogatott)" msgid "%{color} Barrier" msgstr "%{color} útakadály" msgid "(tent visited)" msgstr "(nem látogatott)" msgid "%{color} Tent" msgstr "%{color} sátor" msgid "Road" msgstr "Út" msgid "(digging ok)" msgstr "(ásható)" msgid "(no digging)" msgstr "(nem ásható)" msgid "penalty: %{cost}" msgstr "büntetés: %{cost}" msgid "Defenders:" msgstr "VédÅ‘k:" msgid "Unknown" msgstr "Ismeretlen" msgid "heroQuickInfo|(Level %{level})" msgstr "(%{level}. szint)" msgid "Attack:" msgstr "TámadóerÅ‘:" msgid "Defense:" msgstr "VédÅ‘erÅ‘:" msgid "Spell Power:" msgstr "VarázserÅ‘:" msgid "Knowledge:" msgstr "Tudás:" msgid "Spell Points:" msgstr "Varázspontok:" msgid "Move Points:" msgstr "Mozgáspontok:" msgid "Uncharted Territory" msgstr "Felderítetlen terület" msgid "Cost per troop:" msgstr "Költség egységenként:" msgid "Available: %{count}" msgstr "Toborozható: %{count}" msgid "Number to buy:" msgstr "Vétel (db):" msgid "Recruit selected monsters." msgstr "A kiválasztott lények toborzása." msgid "Select maximum monsters to be recruited." msgstr "A lények maximális számának kiválasztása toborzáshoz." msgid "Select only 1 monster to be recruited." msgstr "Csak egyetlen lény kiválasztása toborzáshoz." msgid "Select this game resolution." msgstr "Pálya felbontás kiválasztása." msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" "A pálya felbontásának kiválasztásával az eredeti felbontáshoz " "(%{resolution}) képest adhatjuk meg a skálázás mértékét egy szorzószámmal " "(%{scale}).\n" "\n" "Az egész számú szorzó (2.0x, 3.0x stb.) általában jobb képet ad, mivel a " "pixelek egyformán lesznek felskálázva vízszintesen és függÅ‘legesen." msgid "Select Game Resolution:" msgstr "Játék felbontás kiválasztása:" msgid "Click to apply the selected resolution." msgstr "Kattints a kiválasztott képernyÅ‘felbontás alkalmazásához." msgid "Click to apply the entered text." msgstr "Kattints a begépelt szöveg elküldéséhez." msgid "Click to open the Virtual Keyboard dialog." msgstr "Kattints a virtuális billentyűzet dialógusablak megnyitásához." msgid "Open Virtual Keyboard" msgstr "Virtuális billentyűzet megnyitása" msgid "How many creatures do you wish to move?" msgstr "Hány teremtményt szeretnél mozgatni?" msgid "Select how many units to separate into:" msgstr "Válaszd ki, hány darabba akarsz szétosztani:" msgid "Map: " msgstr "Térkép: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "Hónap: " msgid ", Week: " msgstr ", Hét: " msgid ", Day: " msgstr ", Nap: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Hely: " msgid "Are you sure you want to delete file:" msgstr "Biztosan törlöd ezt a fájlt?:" msgid "Warning" msgstr "Figyelmeztetés" msgid "Click to save the current game." msgstr "Kattints az aktuális játékállás mentéséhez." msgid "Click to load a previously saved game." msgstr "Kattints a mentett játékállás betöltéséhez." msgid "File to Save:" msgstr "Fájl mentése:" msgid "File to Load:" msgstr "Fájl betöltése:" msgid "Terrain object" msgstr "Szárazföldi objektum" msgid "Accept the choice made." msgstr "A választás elfogadása." msgid "Select Skill:" msgstr "Képesség kiválasztása:" msgid "Select Spell:" msgstr "Varázslat kiválasztása:" msgid "Select Artifact:" msgstr "Varázstárgy kiválasztása:" msgid "Select Monster:" msgstr "Lény kiválasztása:" msgid "Select Hero:" msgstr "HÅ‘s kiválasztása:" msgid "race|Random" msgstr "Véletlen" msgid "Click to start placing the selected hero." msgstr "Kattints a kiválasztott hÅ‘s elhelyezéséhez." msgid "%{color} %{race}" msgstr "%{color} %{race}" msgid "You will place" msgstr "El fogod helyezni" msgid "Click to select this class." msgstr "Kattints az osztály kiválasztásához." msgid "Click to select this color." msgstr "Kattints a szín kiválasztásához." msgid "Select Treasure:" msgstr "Kincs kiválasztása:" msgid "Select Ocean Object:" msgstr "Tengeri objektum kiválasztása:" msgid "Castle/town placing" msgstr "Vár/város elhelyezés" msgid "doubleLinedRace|Neutral" msgstr "Semleges" msgid "Click to start placing the selected castle/town." msgstr "Kattints a kiválasztott vár/város elhelyezéséhez." msgid "Click to select town placing." msgstr "Kattints a következÅ‘ város elhelyezéséhez." msgid "Click to select castle placing." msgstr "Kattints a következÅ‘ vár elhelyezéséhez." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{race} %{townOrCastle}" msgid "race|Neutral" msgstr "Semleges" msgid "Select Dwelling:" msgstr "Toborzóhely kiválasztása:" msgid "Select Landscape Object:" msgstr "Szárazföldi objektum kiválasztása:" msgid "Mine placing" msgstr "Bánya elhelyezése" msgid "" "Resource\n" "type:" msgstr "" "ErÅ‘forrás\n" "típus:" msgid "%{mineName} appearance:" msgstr "%{mineName} elÅ‘fordulásai:" msgid "Click to select %{object} as the resource generator to be placed." msgstr "Kattints ide az erÅ‘forrástermelÅ‘ %{object} elhelyezéséhez." msgid "Select Mountain Object:" msgstr "Hegy objektum kiválasztása:" msgid "Select Rock Object:" msgstr "KÅ‘ objektum kiválasztása:" msgid "Select Tree Object:" msgstr "Fa objektum kiválasztása:" msgid "Select Power Up Object:" msgstr "KépességnövelÅ‘ objektum kiválasztása:" msgid "Select Adventure Object:" msgstr "Kaland objektum kiválasztása:" msgid "Players Icon" msgstr "Játékos ikon" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Jelzi, hogy összesen hány játékos van a küldetésben. Minden ember által le " "nem foglalt pozíciót a számítógép fog elfoglalni." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Jelzi a térkép méretét,\n" "azaz: kicsi (36 x 36), közepes\n" "(72 x 72), nagy (108 x 108),vagy hatalmas (144 x 144)." msgid "Size Icon" msgstr "Ikon méret" msgid "Map Type" msgstr "Térkép típusa" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Azt jelzi, hogy a térkép az \"Örökösödési háborúk\" vagy a \"Hűség ára\" " "vagy pedig a \"Feltámadás\" verzióhoz készült-e." msgid "Map Type:\n" msgstr "Térképtípus:\n" msgid "The Succession Wars" msgstr "Örökösödési háborúk" msgid "The Price of Loyalty" msgstr "A hűség ára" msgid "Resurrection" msgstr "Feltámasztás" msgid "" "\n" "\n" "Language:\n" msgstr "" "\n" "\n" "Nyelv:\n" msgid "Lose all your heroes and towns." msgstr "Összes hÅ‘s és város elvesztése." msgid "Lose a specific town." msgstr "Meghatározott város elvesztése." msgid "Lose a specific hero." msgstr "Meghatározott hÅ‘s elvesztése." msgid "Run out of time. Fail to win by a certain point." msgstr "Elfogy a szabott idÅ‘. Nem sikerül gyÅ‘zni egy bizonyos idÅ‘pontig." msgid "Loss Condition" msgstr "Vesztési feltétel" msgid "Defeat all enemy heroes and towns." msgstr "Az ellenfelek összes hÅ‘sének és városának elpusztítása." msgid "Capture a specific town." msgstr "Meghatározott város elfoglalása." msgid "Defeat a specific hero." msgstr "Megadott hÅ‘s legyÅ‘zése." msgid "Find a specific artifact." msgstr "Egy különleges varázstárgy megtalálása." msgid "Your side must defeat the opposing side." msgstr "A te oldalad legyÅ‘zi az ellenfeleket." msgid "Accumulate a large amount of gold." msgstr "Nagy mennyiségű arany összegyűjtése." msgid "Victory Condition" msgstr "GyÅ‘zelmi feltétel" msgid "Map difficulty:" msgstr "Térkép nehézsége:" msgid "N" msgstr "N" msgid "No maps exist at that size." msgstr "Nincs ilyen méretű térkép." msgid "Small Maps" msgstr "Kicsi térképek" msgid "View only maps of size small (36 x 36)." msgstr "Csak a kicsi térképek (36x36) mutatása." msgid "Medium Maps" msgstr "Közepes térképek" msgid "View only maps of size medium (72 x 72)." msgstr "Csak a közepes térképek (72x72) mutatása." msgid "Large Maps" msgstr "Nagy térképek" msgid "View only maps of size large (108 x 108)." msgstr "Csak a nagy térképek (108x108) mutatása." msgid "Extra Large Maps" msgstr "Hatalmas térképek" msgid "View only maps of size extra large (144 x 144)." msgstr "Csak a hatalmas térképek (144x144) mutatása." msgid "All Maps" msgstr "Összes térkép" msgid "View all maps, regardless of size." msgstr "Összes térkép mutatása, mérettÅ‘l függetlenül." msgid "Selected Name" msgstr "Kiválasztott név" msgid "The name of the currently selected map." msgstr "A kiválasztott térkép neve." msgid "Selected Map Difficulty" msgstr "Kiválasztott nehézség" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Az aktuálisan kiválasztott térkép nehézségi fokozata. A térkép nehézségét a " "pálya szerkesztÅ‘je határozta meg. A nehezebb pályák több és erÅ‘sebb " "ellenfeleket, kevesebb erÅ‘forrást, vagy más különleges nehezítÅ‘ feltételeket " "foglalhatnak magukban." msgid "Selected Description" msgstr "Kiválasztott leírás" msgid "The description of the currently selected map." msgstr "A kiválasztott térkép leírása." msgid "Jump" msgstr "Ugrás" msgid "Hero Speed" msgstr "HÅ‘s sebessége" msgid "Don't Show" msgstr "Ne mutasd" msgid "Enemy Speed" msgstr "Ellenfél sebessége" msgid "Auto Resolve" msgstr "Auto. döntés" msgid "Auto, No Spells" msgstr "Auto, nincs varázslás" msgid "Battles" msgstr "Csaták" msgid "combatMode|Manual" msgstr "Kézi vezérlés" msgid "Change the speed at which your heroes move on the main screen." msgstr "A hÅ‘s sebességének megválasztása a fÅ‘ képernyÅ‘n." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "A gépi játékosok sebességének beállítása. Opció az is, hogy egyáltalán nem " "látszik az ellenség mozgása." msgid "Change the interface settings of the game." msgstr "A játék kezelÅ‘felülete beállításainak megváltoztatása." msgid "Interface Settings" msgstr "KezelÅ‘felület beállítások" msgid "Toggle instant battle mode." msgstr "Gyors csata mód váltása." msgid "Att." msgstr "Tám." msgid "Def." msgstr "Véd." msgid "Power" msgstr "ErÅ‘" msgid "Knowl" msgstr "Tudás" msgid "1st" msgstr "1." msgid "2nd" msgstr "2." msgid "3rd" msgstr "3." msgid "4th" msgstr "4." msgid "5th" msgstr "5." msgid "6th" msgstr "6." msgid "Oracle: Player Rankings" msgstr "Orákulum: Játékos ranglista" msgid "Thieves' Guild: Player Rankings" msgstr "Tolvajcéh: Játékos ranglista" msgid "Number of Towns:" msgstr "Városok száma:" msgid "Number of Castles:" msgstr "Várak száma:" msgid "Number of Heroes:" msgstr "HÅ‘sök száma:" msgid "Gold in Treasury:" msgstr "Arany a kincstárban:" msgid "Wood & Ore:" msgstr "Fa és érc:" msgid "Gems, Cr, Slf & Mer:" msgstr "Dr.kÅ‘, Krist., Kén és Hg:" msgid "Obelisks Found:" msgstr "Megtalált obeliszkek:" msgid "Artifacts:" msgstr "Varázstárgyak:" msgid "Total Army Strength:" msgstr "Sereg összereje:" msgid "Income:" msgstr "Jövedelem:" msgid "Best Hero:" msgstr "Legjobb hÅ‘s:" msgid "Best Hero Stats:" msgstr "Legjobb hÅ‘s statisztikái:" msgid "Personality:" msgstr "Személyiség:" msgid "Best Monster:" msgstr "LegerÅ‘sebb lény:" msgid "Random Castle Name" msgstr "Véletlenszerű vár név" msgid "Random Town Name" msgstr "Véletlenszerű város neve" msgid "Allow Castle build" msgstr "Vár építhetÅ‘ség" msgid "Default Buildings" msgstr "Alapért. épületek" msgid "Default Army" msgstr "Alapért. sereg" msgid "Castle Army" msgstr "VárvédÅ‘k" msgid "Town Army" msgstr "VárosvédÅ‘k" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" "Kattints a vár nevének megváltoztatásához. Jobb kattintásra alaphelyzetbe " "áll." msgid "Enter Castle name" msgstr "Vár nevének megadása" msgid "Allow to build a castle in this town." msgstr "LehetÅ‘vé teszi vár építését a városban." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" "Alapértelmezett épületek használata. Korábbi egyéni beállítások törlÅ‘dnek!" msgid "Toggle building construction restriction mode." msgstr "Épület építés korlátozásának kapcsolója." msgid "Restrict Building Construction" msgstr "Épület építésének korlátozása" msgid "Use default defenders army." msgstr "Alapértelmezett védÅ‘sereg használata." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" "VárvédÅ‘k egyéni beállítása. Jobb kattintásra az egységek alaphelyzetbe " "állnak." msgid "Message Text:" msgstr "Üzenet szövege:" msgid "Reward:" msgstr "Jutalom:" msgid "Player colors allowed to get event:" msgstr "Játékosok, akiknek megengedett az esemény:" msgid "Computer colors allowed to get event:" msgstr "Gépi játékosok, akiknek megengedett az esemény:" msgid "First day of occurrence:" msgstr "ElsÅ‘ elÅ‘fordulás napja:" msgid "Repeat period (days):" msgstr "IsmétlÅ‘dési periódus (nap):" msgid "Allow %{color} human player to get event" msgstr "Esemény engedélyzése %{color} játékos számára" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" "Ha ez a jelölÅ‘négyzet meg van jelölve, akkor az esemény %{color} emberi " "játékos számára ki fog váltódni." msgid "Allow %{color} computer player to get event" msgstr "Esemény engedélyzése %{color} gépi játékos számára" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" "Ha ez a jelölÅ‘négyzet meg van jelölve, akkor az esemény %{color} gépi " "játékos számára ki fog váltódni." msgid "Message:" msgstr "Üzenet:" msgid "Click to save the Event properties." msgstr "Kattints az esemény beállítások mentéséhez." msgid "No resources will be given as a reward." msgstr "Nincs erÅ‘forrás jutalom." msgid "Resources" msgstr "ErÅ‘források" msgid "Resources will be given as a reward." msgstr "A jutalom erÅ‘forrás lesz." msgid "Click here to change the event message." msgstr "Kattints az esemény üzenetének megváltoztatásához." msgid "Event Message Text" msgstr "Esemény üzenet szöveg" msgid "Day: %{day}" msgstr "Nap: %{day}" msgid "Daily Events" msgstr "Napi események" msgid "Click to save the events." msgstr "Kattints az események mentéséhez." msgid "Add Event" msgstr "Esemény hozzáadása" msgid "Add an additional event." msgstr "További esemény hozzáadása." msgid "Edit Event" msgstr "Esemény szerkesztése" msgid "Edit an existing event." msgstr "MeglévÅ‘ esemény szerkesztése." msgid "Delete Event" msgstr "Esemény törlése" msgid "Delete an existing event." msgstr "MeglévÅ‘ esemény törlése." #, fuzzy msgid "Effects:" msgstr "Effektusok" #, fuzzy msgid "Conditions:" msgstr "" "Vesztési\n" "feltételek" msgid "Cancel event after first visit" msgstr "Esemény törlése az elsÅ‘ látogatás után" #, fuzzy msgid "Computer colors allowed to get the event:" msgstr "Gépi játékosok, akiknek megengedett az esemény:" msgid "Set Experience value" msgstr "Tapasztalati érték beállítása" msgid "Artifact" msgstr "Varázstárgy" #, fuzzy msgid "No artifact will be given by the event." msgstr "Nincs varázstárgy jutalom." msgid "Delete Artifact" msgstr "Varázstárgy törlése" #, fuzzy msgid "Delete an artifact from the event." msgstr "Varázstárgy törlése a jutalmak közül." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Képesség kiválasztása:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" #, fuzzy msgid "No resources will be part of this event." msgstr "Nincs erÅ‘forrás jutalom." #, fuzzy msgid "These resources will be a part of the event." msgstr "Nincs erÅ‘forrás jutalom." msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" "Ha ez a jelölÅ‘négyzet meg van jelölve, akkor az esemény csak egyszer " "váltódik ki. Ha nincs bejelölve, akkor mindahányszor a megadott játékos " "rálép területre." msgid "%{objects} cannot be placed on water." msgstr "Vízen nem helyezhetÅ‘k el %{objects}." msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Szent Varázstárgy csak ásásra alkalmas terepen helyezhetÅ‘ el." msgid "%{objects} must be placed on water." msgstr "%{objects} elhelyezése vízre kell történjen." msgid "Objects cannot be placed outside the map." msgstr "Tárgyakat nem lehet a térképen kívülre helyezni." msgid "Action objects must be placed on clear tiles." msgstr "Cselekmény objektumokat tiszta területre kell elhelyezni." msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Biztos hogy vissza akarsz lépni a fÅ‘menübe? Minden változtatás el fog veszni." msgid "Editor" msgstr "SzerkesztÅ‘" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Biztos hogy benne hogy új térképet töltesz be? (A jelenlegi térkép " "változtatásai el fognak veszni.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Biztos hogy benne hogy új térképet hozol létre? (A jelenlegi térkép " "változtatásai el fognak veszni.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "START" msgid "Main Menu" msgstr "FÅ‘menü" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Biztos hogy vissza akarsz lépni a fÅ‘menübe? Minden változtatás el fog veszni." msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Start" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Biztos hogy benne hogy új térképet töltesz be? (A jelenlegi térkép " "változtatásai el fognak veszni.)" msgid "Create a new map from scratch." msgstr "Teljesen új térkép létrehozása." msgid "New Map" msgstr "Új térkép" msgid "Load Map" msgstr "Térkép betöltése" msgid "Load an existing map." msgstr "LétezÅ‘ térkép betöltése." msgid "Save Map" msgstr "Térkép mentése" msgid "Save the current map." msgstr "Az aktuális térkép mentése." msgid "Quit out of the map editor." msgstr "Kilépés a térképszerkesztÅ‘bÅ‘l." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Kattints a fÅ‘menübe való visszatéréshez." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "%{object} szöveg megadása" msgid "Set Random Ultimate Artifact Radius" msgstr "Véletlenszerű Szent Varázstárgy sugarának megadása" msgid "%{object} has no properties to change." msgstr "Nincs megváltoztatható tulajdonsága ennek: %{object}" msgid "This artifact" msgstr "Ez a varázstárgy" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "Utak" msgid "Streams" msgstr "Folyóvizek" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "Maximum %{count} hÅ‘s helyezhetÅ‘ el a térképen ugyanabból a színbÅ‘l." msgid "Failed to update player information." msgstr "A játékos adatainak frissítése nem sikerült." msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Csak egy véletlenszerű Szent Varázstárgy helyezhetÅ‘ el a térképen." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "Maximum %{count} obeliszk helyezhetÅ‘ el a térképen." msgid "The map is corrupted." msgstr "A térkép fájl sérült." msgid "Unable to locate data directory to save the map." msgstr "Nem található az adatkönyvtár a térkép mentéséhez." msgid "Unable to create a directory to save the map." msgstr "Nem hozható létre könyvtár a térkép mentéséhez." msgid "Unable to locate a directory to save the map." msgstr "Nem található könyvtár a térkép mentéséhez." msgid "Are you sure you want to overwrite the existing map?" msgstr "Biztosan felülírod a meglévÅ‘ térképet?" msgid "Map saved to: " msgstr "Térkép mentve ide: " msgid "Failed to save the map." msgstr "Térkép mentése sikertelen." msgid "Used to place %{object}." msgstr "%{object} elhelyezésére való." msgid "Select object type" msgstr "Objektum típusok" msgid "" "Click here to\n" "select a monster." msgstr "" "Kattints ide, a\n" "lény kiválasztásához." msgid "" "Click here to\n" "select another monster." msgstr "" "Kattints ide, egy másik\n" "lény kiválasztásához." msgid "" "Cell\n" "Details" msgstr "" "Cella\n" "tulajdonságok" msgid "Erase" msgstr "Törlés" msgid "Mountains" msgstr "Hegyek" msgid "Rocks" msgstr "Kövek" msgid "Trees" msgstr "Fák" msgid "Water Objects" msgstr "Vízi tárgyak" msgid "Miscellaneous" msgstr "Vegyes tárgyak" msgid "Artifacts" msgstr "Varázstárgyak" msgid "Dwellings" msgstr "Toborzóhelyek" msgid "Mines" msgstr "Bányák" msgid "Power-ups" msgstr "KépességnövelÅ‘k" msgid "Treasures" msgstr "Kincsek" msgid "Heroes" msgstr "HÅ‘sök" msgid "Towns" msgstr "Városok" msgid "editorErasure|Landscape objects" msgstr "Szárazföldi objektumok" msgid "editorErasure|Adventure non pickable objects" msgstr "Nem felvehetÅ‘ tárgyak a kalandtérképen" msgid "editorErasure|Castles" msgstr "Várak" msgid "editorErasure|Adventure pickable objects" msgstr "FelvehetÅ‘ tárgyak a kalandtérképen" msgid "editorErasure|Monsters" msgstr "Lények" msgid "editorErasure|Heroes" msgstr "HÅ‘sök" msgid "editorErasure|Roads" msgstr "Utak" msgid "editorErasure|Streams" msgstr "Vízfolyások" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Talaj rajzolása\n" "%{size} x %{size} négyzetes egységekben." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Tárgyak törlése\n" "%{size} x %{size} négyzetes egységekben." msgid "Small Brush" msgstr "Kicsi ecset" msgid "Medium Brush" msgstr "Közepes ecset" msgid "Large Brush" msgstr "Nagy ecset" msgid "Area Fill" msgstr "Terület kitöltése" msgid "Used to click and drag for filling in large areas." msgstr "Nagy térképterületek kitöltésére használatos." msgid "Clear Area" msgstr "Terület törlése" msgid "Used to click and drag for clearing large areas." msgstr "Nagy térképterületek törlésére használatos." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Költség: a hÅ‘sök normál lépésszáma x %{rate}. (A nyomkövetés képesség " "csökkenti vagy teljesen lenullázza ezt a hátrányt.)" msgid "Traversable only by boat." msgstr "Csak hajóval járható." msgid "No special modifiers." msgstr "Nincs speciális módosító." msgid "Toggle the erasure of %{type} objects." msgstr "%{type} tárgyak törlésének kapcsolója." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Ezek a típusú tárgyak fognak törlÅ‘dni a Törlés eszközzel. Bal kattintásra a " "típuskiválasztás törlÅ‘dik, a gomb nyomva tartására pedig az összes többi " "típuskiválasztás is törlÅ‘dik." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Ezek a típusú tárgyak NEM fognak törlÅ‘dni a Törlés eszközzel. Bal " "kattintásra a típuskiválasztás törlÅ‘dik, a gomb nyomva tartására pedig az " "összes többi típuskiválasztás is törlÅ‘dik." msgid "Terrain Mode" msgstr "Talaj mód" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "Különféle talajokat (fű, föld, víz stb.) rajzol a térképen." msgid "Landscape Objects Mode" msgstr "Szárazföldi objektum mód" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Elhelyezi a szárazföldi tereptárgyakat (hegyek, kövek, fák stb.) a térképen." msgid "Detail Mode" msgstr "Tulajdonságok mód" msgid "Used for special editing of action objects." msgstr "Cselekvés objektumok speciális szerkesztéséhez használatos." msgid "Adventure Objects Mode" msgstr "Kaland objektum mód" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Elhelyezi a kaland térkép tárgyakat (varázstárgyak, toborzóhelyek, bányák, " "kincsek stb.) a térképen." msgid "Kingdom Objects Mode" msgstr "Királyság objektum mód" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "Elhelyezi a királyság tárgyait (városok, várak, hÅ‘sök) a térképen." msgid "Monsters Mode" msgstr "Lények mód" msgid "Used to place monsters on the map." msgstr "Elhelyezi a lényeket a térképen." msgid "Allows you to draw streams by clicking and dragging." msgstr "Kattintás és húzás révén lehetÅ‘vé teszi vízfolyások rajzolását." msgid "Stream Mode" msgstr "Vízfolyás mód" msgid "Allows you to draw roads by clicking and dragging." msgstr "Kattintás és húzás révén lehetÅ‘vé teszi utak rajzolását." msgid "Road Mode" msgstr "Út mód" msgid "Erase Mode" msgstr "Törlés mód" msgid "Used to erase objects from the map." msgstr "Ezzel törölheted a tárgyakat a térképrÅ‘l." msgid "Change between zoom and normal view." msgstr "Váltás nagyított és normál nézet között." msgid "Magnify" msgstr "Nagyítás" msgid "Undo" msgstr "Visszavonás" msgid "Undo your last action." msgstr "Utolsó cselekedet visszavonása." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "Utolsó cselekedet visszavonása." msgid "Edit map title, description, and other general information." msgstr "A pályanevek, leírások és egyéb általános információk szerkesztése." msgid "Specifications" msgstr "JellemzÅ‘k" msgid "File Options" msgstr "Fájlbeállítások" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "A beállítások menü megnyitása, ahol elmenteni vagy betölteni tudsz pályákat, " "vagy kilépni a szerkesztÅ‘bÅ‘l." msgid "View the editor system options, which let you customize the editor." msgstr "" "Tekintsd meg a szerkesztÅ‘ rendszer beállításait, amik lehetÅ‘vé teszik annak " "testreszabását." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Egy %{size} széles és %{size} magas térképet hoz létre." msgid "Cancel back to the New Map menu." msgstr "Vissza az új térkép menübe." msgid "Cancel back to the main menu." msgstr "Vissza a fÅ‘menübe." msgid "From Scratch" msgstr "ElölrÅ‘l kezd" msgid "Start from scratch with a blank map." msgstr "Egy teljesen üres térképpel a legelejérÅ‘l kezdeni." msgid "Create a randomly generated map." msgstr "Egy véletlenszerű térkép generálása." msgid "Random" msgstr "Véletlenszerű" msgid "Cancel back to the Map Editor main menu." msgstr "Vissza a térképszerkesztÅ‘ fÅ‘menüjébe." msgid "No maps available!" msgstr "Nincs használható térkép!" msgid "[%{pos}]: %{race} hero" msgstr "[%{pos}]: %{race} hÅ‘s" msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%[%{pos}]: %{name}, %{race} hÅ‘s" msgid "[%{pos}]: %{race} town" msgstr "[%{pos}]: %{race} város" msgid "[%{pos}]: %{race} castle" msgstr "[%{pos}]: %{race} vár" msgid "[%{pos}]: %{name}, %{race} town" msgstr "[%{pos}]: %{name}, %{race} város" msgid "[%{pos}]: %{name}, %{race} castle" msgstr "[%{pos}]: %{name}, %{race} vár" msgid "None." msgstr "Nincs." msgid "One side defeats another." msgstr "Egyik oldal legyÅ‘zi a másikat." msgid "Accumulate gold." msgstr "Arany összegyűjtése." msgid "Run out of time." msgstr "Kifutás az idÅ‘bÅ‘l." msgid "alliance|1st" msgstr "1." msgid "alliance|2nd" msgstr "2." msgid "alliance|3rd" msgstr "3." msgid "alliance|4th" msgstr "4." msgid "alliance|5th" msgstr "5." msgid "Special Loss Condition" msgstr "Speciális vesztési feltétel" msgid "Special Victory Condition" msgstr "Speciális gyÅ‘zelmi feltétel" msgid "Allow standard victory conditions" msgstr "Normál gyÅ‘zelmi feltételek engedélyezése" msgid "Allow this condition also for AI" msgstr "A gépi játékos számára is megengedett ez a feltétel" msgid "Set alliances:" msgstr "Szövetségesek beállítása:" msgid "{%number} alliance: " msgstr "{%number} szövetséges: " msgid "Gold:" msgstr "Arany:" msgid "Select a Town to capture to achieve victory" msgstr "Válaszd ki a várost, melynek elfoglalása a gyÅ‘zelem feltétele" msgid "Click here to change the town needed to capture to achieve victory." msgstr "" "Kattints a gyÅ‘zelem kivívásához szükséges elfoglalandó vár " "megváltoztatásához." msgid "Select a Hero to defeat to achieve victory" msgstr "Válaszd ki a hÅ‘st, akinek legyÅ‘zése a gyÅ‘zelem feltétele" msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "" "Kattints a gyÅ‘zelem kivívásához szükséges legyÅ‘zendÅ‘ hÅ‘s megváltoztatásához." msgid "Put %{color} player in the %{alliance} alliance" msgstr "%{color} játékos felvétele %{alliance} szövetségbe" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" "Ha ez a jelölÅ‘négyzet meg van jelölve, akkor %{color} játékos %{alliance}" "szövetség tagja lesz." msgid "Days:" msgstr "Napok:" msgid "Select a Town to lose to suffer defeat" msgstr "Válaszd ki a várost, melynek elvesztése teljes bukással jár" msgid "Click here to change the town whose loss would mean defeat." msgstr "" "Kattints annak a városnak a megváltoztatásához, melynek elvesztése teljes " "bukással jár." msgid "Select a Hero to lose to suffer defeat" msgstr "Válaszd ki a hÅ‘st, akinek elvesztése teljes bukással jár" msgid "Click here to change the hero whose loss would mean defeat." msgstr "" "Kattints annak a hÅ‘snek a megváltoztatásához, akinek elvesztése teljes " "bukással jár." msgid "Map Difficulty" msgstr "Térkép nehézség" msgid "Map Description" msgstr "Térkép leírása" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" "A megadott térképleírás hosszabb, mint a maximálisan elfogadott 5 sor. A " "térképleírás lerövidítésre kerül, hogy beleférjen a rendelkezésre álló " "mezÅ‘be." msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" "A térkép nyelvét készülsz megváltoztatni. Régi nyelv: %{oldLanguage}, új " "nyelv: %{newLanguage}. Néhány szöveg nem biztos, hogy megfelelÅ‘en jelenik " "meg ezután. Ãgy is végre akarod hajtani a műveletet?" msgid "Change Map Name" msgstr "Térkép nevének megváltoztatása" msgid "Change Map Description" msgstr "Térképleírás megváltoztatása" msgid "Click to accept the changes made." msgstr "Kattints a változtatások elfogadásához." msgid "Click to edit custom rumors." msgstr "Kattints egyéni szóbeszéd szerkesztéséhez." msgid "Rumors" msgstr "Szóbeszédek" msgid "Click to edit daily events." msgstr "Kattints a napi események szerkesztéséhez." msgid "Events" msgstr "Események" msgid "Click to change the language of the map." msgstr "Kattints a térkép nyelvének megváltoztatásához." msgid "Click to change your map name." msgstr "Kattints a térképed nevének megváltoztatásához." msgid "Map Name" msgstr "Térkép neve" msgid "Click to change the description of the current map." msgstr "Kattints az aktuális térkép leírásának megváltoztatásához." msgid "Click to change the victory condition of the current map." msgstr "Kattints az aktuális térkép gyÅ‘zelmi feltételeinek megváltoztatásához." msgid "Click to change the loss condition of the current map." msgstr "Kattints az aktuális térkép vesztési feltételeinek megváltoztatásához." msgid "Indicates the player types in the scenario. Click to change." msgstr "Jelzi a küldetés játékosainak típusait. Kattints a változtatáshoz." msgid "Player Type" msgstr "Játékos típusa" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Kattints a térkép nehézségi fokozatának beállításához. Nehezebb térképek " "több vagy erÅ‘sebb ellenfelet, kevesebb erÅ‘forrást, vagy egyéb speciális " "nehezítÅ‘ feltételt tartalmazhatnak az emberi játékos számára." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "A számításba veendÅ‘ %{resource} kiválasztása:" msgid "Animation" msgstr "Animáció" msgid "Passability" msgstr "Ãtjárhatóság" msgid "Toggle animation of the objects." msgstr "Objektumok animációjának kapcsolója." msgid "Toggle display of objects' passability." msgstr "Kattints az objektumok átjárhatóságának megjelenítéséhez." msgid "Rumor:" msgstr "Szóbeszéd:" msgid "Rumor" msgstr "Szóbeszéd" msgid "This rumor already exists in the list." msgstr "Ez a szóbeszéd már megtalálható a listában." msgid "Click to save the rumors." msgstr "Kattints a szóbeszédek mentéséhez." msgid "Add Rumor" msgstr "Szóbeszéd hozzáadása" msgid "Add an additional rumor." msgstr "További szóbeszéd hozzáadása." msgid "Edit Rumor" msgstr "Szóbeszéd szerkesztés" msgid "Edit an existing rumor." msgstr "MeglévÅ‘ szóbeszéd szerkesztése." msgid "Delete Rumor" msgstr "Szóbeszéd törlése" msgid "Delete an existing rumor." msgstr "MeglévÅ‘ szóbeszéd törlése." msgid "" "\n" "\n" "Size: " msgstr "" "\n" "\n" "Méret: " msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Leírás: " msgid "Save Map:" msgstr "Térkép mentése:" msgid "Click to save the current map." msgstr "Kattints az aktuális térkép mentéséhez." msgid "Riddle:" msgstr "Találós kérdés:" msgid "Answers:" msgstr "Válaszok:" msgid "Answer:" msgstr "Válasz:" msgid "Answer" msgstr "Válasz" msgid "This answer exists in the list." msgstr "A válasz megtalálható a listában." msgid "Click to save the Sphinx properties." msgstr "Kattints a Szfinx beállításainak mentéséhez." msgid "Add Answer" msgstr "Válasz hozzáadása" msgid "Add an additional answer for the question." msgstr "További válasz hozzáadása a kérdéshez." msgid "Edit Answer" msgstr "Válasz szerkesztése" msgid "Edit an existing answer for the question." msgstr "MeglévÅ‘ válasz szerkesztése." msgid "Delete Answer" msgstr "Válasz törlése" msgid "Delete an existing answer for the question." msgstr "MeglévÅ‘ válasz törlése." msgid "No artifact will be given as a reward." msgstr "Nincs varázstárgy jutalom." msgid "Delete an artifact from the reward." msgstr "Varázstárgy törlése a jutalmak közül." msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "Nap: %{day} hét: %{week} hónap: %{month}" msgid "difficulty|Easy" msgstr "Könnyű" msgid "difficulty|Normal" msgstr "Normál" msgid "difficulty|Hard" msgstr "Nehéz" msgid "difficulty|Expert" msgstr "SzakértÅ‘" msgid "difficulty|Impossible" msgstr "Lehetetlen" msgid "and more..." msgstr "és egyebek..." msgid "Easy" msgstr "Könnyű" msgid "Normal" msgstr "Normál" msgid "Hard" msgstr "Nehéz" msgid "Campaign Difficulty" msgstr "Hadjárat nehézsége" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Válaszd ezt a nehézséget, ha kevesebb kihívással szeretnéd végigvinni a " "játékot. A gép gyengébb lesz, mint a Normál nehézségi fokozaton." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Válaszd ezt a nehézséget, ha a hadjáratot az eredeti elgondolásnak " "megfelelÅ‘en szeretnéd játszani." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Válaszd ezt a nehézséget, ha több kihívást akarsz. A gép erÅ‘sebb lesz, mint " "a Normál nehézségi fokozaton." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Gratulálunk!\n" "\n" "Nap: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Nehézség: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Pontszám: %{score}\n" "\n" "Besorolás:\n" "%{rating}" msgid "Start the selected scenario." msgstr "A kiválasztott küldetés indítása." msgid "View Intro" msgstr "Intró mutatása" msgid "View the intro video for the current state of the campaign." msgstr "A hadjárat jelenlegi állásához tartozó bemutató videó megnézése." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "A hadjárat nehézségének kiválasztása. Ez bármikor csökkenthetÅ‘ a hadjárat " "során." msgid "Restart the current scenario." msgstr "Aktuális küldetés újraindítása." msgid "Difficulty" msgstr "Nehézség" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Alacsonyabb nehézségi szintre szeretnéd állítani a hadjáratot. InnentÅ‘l nem " "állíthatod újra vissza és a pontszámaid is az újonnan választott szintnek " "megfelelÅ‘en számolódnak majd. Ãgy is végre akarod hajtani?" msgid "Are you sure you want to restart this scenario?" msgstr "Biztosan újra akarod indítani a küldetést?" msgid "Campaign Scenario loading failure" msgstr "A hadjárat küldetésének betöltése sikertelen" msgid "Please make sure that campaign files are correct and present." msgstr "Bizonyosodj meg róla, hogy a hadjárat fájljai épek és mind megvannak." msgid "Days spent" msgstr "Nap eltelt" msgid "The number of days spent on this campaign." msgstr "Az eltöltött napok száma ebben a hadjáratban." msgid "Project Coordination and Core Development" msgstr "Projekt-koordináció és fÅ‘ fejlesztés" msgid "Development" msgstr "Fejlesztés" msgid "Visit us at " msgstr "Látogass meg minket itt: " msgid "QA and Support" msgstr "MinÅ‘ségbiztosítás és támogatás" msgid "Dev and Support" msgstr "Fejl. és támogatás" msgid "Special Thanks to" msgstr "Külön köszönet" msgid "and many-many other contributors and supporters!" msgstr "és sok-sok egyéb közreműködÅ‘nek és támogatónak!" msgid "Support us at" msgstr "Támogass minket itt" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Kapcsolat" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Segítség kell a játékhoz?" msgid "Original project before 0.7" msgstr "Eredeti projekt, v0.7 elÅ‘tti" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Heroes of Might and Magic II: Az örökösödési háborúk csapata" msgid "Designed and Directed" msgstr "Tervezte és rendezte" msgid "Programming and Design" msgstr "Programozta és tervezte" msgid "Executive Producer" msgstr "VezetÅ‘ gyártásvezetÅ‘" msgid "Producer" msgstr "GyártásvezetÅ‘" msgid "Additional Design" msgstr "További tervezés" msgid "Additional Programming" msgstr "További programozás" msgid "Musical Production" msgstr "Zenei produkció" msgid "Music and Sound Design" msgstr "Zene és hang tervezés" msgid "Vocalists" msgstr "Énekesek" msgid "Art Director" msgstr "Művészeti igazgató" msgid "Assistant Art Director" msgstr "Művészeti igazgató asszisztens" msgid "Artists" msgstr "Művészek" msgid "QA Manager" msgstr "MinÅ‘ségbiztosítási menedzser" msgid "QA" msgstr "MinÅ‘ségbiztosítás" msgid "Writing" msgstr "Alaptörténet" msgid "Manual and Helpfile" msgstr "Kézikönyv és segédlet" msgid "Scenarios" msgstr "Küldetések" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Heroes of Might and Magic II: A hűség ára csapata" msgid "Design Lead" msgstr "VezetÅ‘ tervezÅ‘" msgid "Designers" msgstr "TervezÅ‘k" msgid "Programming Lead" msgstr "VezetÅ‘ programozó" msgid "Art Lead" msgstr "Művészeti vezetÅ‘" msgid "Playtesters" msgstr "TesztelÅ‘k" msgid "Designer" msgstr "TervezÅ‘" msgid "Producers" msgstr "GyártásvezetÅ‘k" msgid "QA Managers" msgstr "MinÅ‘ségbiztosítási menedzserek" msgid "Sound Design" msgstr "Hang tervezÅ‘" msgid "Town Themes" msgstr "Város témák" msgid "Alto Sax" msgstr "Altszaxofon" msgid "Harpsichord and Piano" msgstr "Csembaló és zongora" msgid "Basso Vocal" msgstr "Basszus ének" msgid "Soprano Vocal" msgstr "Szoprán ének" msgid "Recorded at %{recordingStudio}" msgstr "Felvétel: %{recordingStudio}" msgid "credits|Manual" msgstr "Kézikönyv" msgid "German Consultant" msgstr "Német tanácsadó" msgid "Map Designers" msgstr "Térkép tervezÅ‘k" msgid "Package Design" msgstr "Csomagterv" msgid "High Scores" msgstr "DicsÅ‘ségtábla" msgid "Your Name" msgstr "A te neved" msgid "Unknown Hero" msgstr "Ismeretlen hÅ‘s" msgid "Standard" msgstr "Normál" msgid "View High Scores for Standard Maps." msgstr "A normál térképek dicsÅ‘ségtáblájának megmutatása." msgid "Campaign" msgstr "Hadjárat" msgid "View High Scores for Campaigns." msgstr "A hadjárat térképek dicsÅ‘ségtáblájának megmutatása." msgid "hotkey|default okay event" msgstr "nyugtázás (OK)" msgid "hotkey|default cancel event" msgstr "visszavonás (MÉGSE)" msgid "hotkey|default left" msgstr "balra" msgid "hotkey|default right" msgstr "jobbra" msgid "hotkey|default up" msgstr "fel" msgid "hotkey|default down" msgstr "le" msgid "hotkey|toggle fullscreen" msgstr "teljes képernyÅ‘ váltás" msgid "hotkey|toggle text support mode" msgstr "szöveges támogatás váltás" msgid "hotkey|toggle developer mode" msgstr "fejlesztÅ‘i mód kapcsoló" msgid "hotkey|new game" msgstr "új játék" msgid "hotkey|load game" msgstr "játék betöltés" msgid "hotkey|high scores" msgstr "dicsÅ‘ségtábla" msgid "hotkey|credits" msgstr "stáblista" msgid "hotkey|standard game" msgstr "normál játék" msgid "hotkey|campaign game" msgstr "hadjárat" msgid "hotkey|multi-player game" msgstr "többjátékos mód" msgid "hotkey|settings" msgstr "beállítások" msgid "hotkey|quit" msgstr "kilépés" msgid "hotkey|select map" msgstr "térkép kiválasztás" msgid "hotkey|select small map size" msgstr "kis térkép kiválasztása" msgid "hotkey|select medium map size" msgstr "közepes térkép kiválasztása" msgid "hotkey|select large map size" msgstr "nagy térkép kiválasztása" msgid "hotkey|select extra large map size" msgstr "nagyon nagy térkép kiválasztása" msgid "hotkey|select all map sizes" msgstr "minden térképméret kiválasztása" msgid "hotkey|hot seat game" msgstr "helycserés játék" msgid "hotkey|battle only game" msgstr "csak csata mód" msgid "hotkey|choose the original campaign" msgstr "eredeti hadjárat kiválasztása" msgid "hotkey|choose the expansion campaign" msgstr "kiegészítÅ‘ hadjárat kiválasztása" msgid "hotkey|map editor main menu" msgstr "térképszerkesztÅ‘ fÅ‘menü" msgid "hotkey|new map menu" msgstr "új térkép menü" msgid "hotkey|load map menu" msgstr "térkép betöltés menü" msgid "hotkey|new map from scratch" msgstr "teljesen új térkép" msgid "hotkey|new random map" msgstr "véletlenszerű térkép" msgid "hotkey|undo last action" msgstr "Legutolsó cselekvés visszavonása (UNDO)" msgid "hotkey|redo last action" msgstr "Legutolsó cselekvés visszaállítása (REDO)" msgid "hotkey|open game main menu" msgstr "fÅ‘menü megnyitása" msgid "hotkey|toggle passability" msgstr "átjárhatóság kapcsoló" msgid "hotkey|roland campaign" msgstr "roland hadjárata" msgid "hotkey|archibald campaign" msgstr "archibald hadjárata" msgid "hotkey|price of loyalty campaign" msgstr "a hűség ára hadjárat" msgid "hotkey|voyage home campaign" msgstr "hazatérés hadjárat" msgid "hotkey|wizard's isle campaign" msgstr "varázslósziget hadjárat" msgid "hotkey|descendants campaign" msgstr "leszármazottak hadjárata" msgid "hotkey|select first campaign bonus" msgstr "elsÅ‘ hadjárat bónusz kiválasztása" msgid "hotkey|select second campaign bonus" msgstr "második hadjárat bónusz kiválasztása" msgid "hotkey|select third campaign bonus" msgstr "harmadik hadjárat bónusz kiválasztása" msgid "hotkey|view campaign intro" msgstr "hadjárat bevezetÅ‘jének megtekintése" msgid "hotkey|select campaign difficulty" msgstr "térkép nehézségének kiválasztása" msgid "hotkey|restart campaign scenario" msgstr "hadjárat küldetés újrakezdése" msgid "hotkey|world map left" msgstr "világtérkép: balra" msgid "hotkey|world map right" msgstr "világtérkép: jobbra" msgid "hotkey|world map up" msgstr "világtérkép: fel" msgid "hotkey|world map down" msgstr "világtérkép: le" msgid "hotkey|world map up left" msgstr "világtérkép: fel-balra" msgid "hotkey|world map up right" msgstr "világtérkép: fel-jobbra" msgid "hotkey|world map down left" msgstr "világtérkép: le-balra" msgid "hotkey|world map down right" msgstr "világtérkép: le-jobbra" msgid "hotkey|save game" msgstr "játék mentése" msgid "hotkey|next hero" msgstr "következÅ‘ hÅ‘s" msgid "hotkey|change to hero under cursor" msgstr "váltás a kurzor alatti hÅ‘sre" msgid "hotkey|start hero movement" msgstr "hÅ‘s mozgásának megkezdése" msgid "hotkey|cast adventure spell" msgstr "kalandozó varázslat idézése" msgid "hotkey|put hero to sleep" msgstr "hÅ‘s altatása" msgid "hotkey|next town" msgstr "következÅ‘ város" msgid "hotkey|end turn" msgstr "kör befejezése" msgid "hotkey|file options" msgstr "fájlbeállítások" msgid "hotkey|adventure options" msgstr "kaland opciók" msgid "hotkey|puzzle map" msgstr "rejtvény térkép" msgid "hotkey|scenario information" msgstr "küldetés infromáció" msgid "hotkey|dig for artifact" msgstr "varázstárgy kiásása" msgid "hotkey|view world" msgstr "világ mutatása" msgid "hotkey|kingdom summary" msgstr "királyság összesítÅ‘" msgid "hotkey|default action" msgstr "alapértelmezett cselekvés" msgid "hotkey|open focus" msgstr "fókuszálás kezdése" msgid "hotkey|system options" msgstr "rendszerbeállítások" msgid "hotkey|scroll left" msgstr "görgetés balra" msgid "hotkey|scroll right" msgstr "görgetés jobbra" msgid "hotkey|scroll up" msgstr "görgetés fel" msgid "hotkey|scroll down" msgstr "görgetés le" msgid "hotkey|toggle control panel" msgstr "vezérlÅ‘pult kapcsoló" msgid "hotkey|toggle radar" msgstr "radar kapcsoló" msgid "hotkey|toggle buttons" msgstr "gomb átkapcsoló" msgid "hotkey|toggle status" msgstr "státusz kapcsoló" msgid "hotkey|toggle icons" msgstr "ikon kapcsoló" msgid "hotkey|transfer control to ai" msgstr "irányítás átadása a gépnek" msgid "hotkey|retreat from battle" msgstr "visszavonulás a csatából" msgid "hotkey|surrender during battle" msgstr "megadás a csatában" msgid "hotkey|toggle auto combat mode" msgstr "automatikus csata mód kapcsoló" msgid "hotkey|quick combat" msgstr "gyors csata" msgid "hotkey|battle options" msgstr "csata beállítások" msgid "hotkey|skip turn in battle" msgstr "kör kihagyása a csatában" msgid "hotkey|cast battle spell" msgstr "varázslat idézése csatában" msgid "hotkey|dwelling level 1" msgstr "toborzóhely 1. szint" msgid "hotkey|dwelling level 2" msgstr "toborzóhely 2. szint" msgid "hotkey|dwelling level 3" msgstr "toborzóhely 3. szint" msgid "hotkey|dwelling level 4" msgstr "toborzóhely 4. szint" msgid "hotkey|dwelling level 5" msgstr "toborzóhely 5. szint" msgid "hotkey|dwelling level 6" msgstr "toborzóhely 6. szint" msgid "hotkey|well" msgstr "kút" msgid "hotkey|marketplace" msgstr "piactér" msgid "hotkey|mage guild" msgstr "varázstorony" msgid "hotkey|shipyard" msgstr "hajógyár" msgid "hotkey|thieves guild" msgstr "tolvajcéh" msgid "hotkey|tavern" msgstr "fogadó" msgid "hotkey|construction screen" msgstr "tervezési képernyÅ‘" msgid "hotkey|buy all monsters in well" msgstr "minden lény megvásárlása a kútban" msgid "hotkey|split stack by half" msgstr "egység kétfelé osztása" msgid "hotkey|split stack by one" msgstr "egység szétosztása" msgid "hotkey|join stacks" msgstr "egységek összevonása" msgid "hotkey|upgrade troop" msgstr "egység fejlesztése" msgid "hotkey|dismiss hero or troop" msgstr "hÅ‘s/egység elbocsátása" msgid "hotkey|exchange all troops" msgstr "összes egység cseréje" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Szeretnéd visszavenni az irányítást az AI-tól? Ez csak a következÅ‘ körben " "lesz érvényes." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Ãt akarod adni az irányítást a gépnek? Ez csak a következÅ‘ körtÅ‘l lesz " "hatásos." msgid "Default Actions" msgstr "Alapértelmezett cselekvés" msgid "Global Actions" msgstr "Globális cselekvések" msgid "World Map" msgstr "Világtérkép" msgid "Battle Screen" msgstr "Csata képernyÅ‘" msgid "Town Screen" msgstr "Város képernyÅ‘" msgid "Army Actions" msgstr "Sereg cselekvései" msgid "The save file is corrupted." msgstr "A mentés fájl sérült." msgid "Unsupported save format: " msgstr "Nem támogatott mentés formátum: " msgid "Current game version: " msgstr "Jelenlegi játék verziója: " msgid "Last supported version: " msgstr "Utolsó támogatott verzió: " msgid "This file contains a save with an invalid game type." msgstr "Ez a fájl nem megfelelÅ‘ játékverzióval lett mentve." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Ehhez a mentés fájlhoz szükség van a \"Hűség ára\" kiegészítÅ‘höz, amely " "azonban nem található." msgid "This saved game is localized to '" msgstr "Ez a mentett játék lokalizált '" msgid "' language, but the current language of the game is '" msgstr "' nyelvre, azonban a játék jelenlegi nyelve '" msgid "No save files to load." msgstr "Nincsenek mentések a betöltéshez." msgid "Hot Seat" msgstr "Helycserés" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "A helycserés játék során 2-6 játékos játszik ugyanazon a számítógépen és " "körönként cserélÅ‘dnek (Hot Seat)." msgid "A single player game playing out a single map." msgstr "Egyjátékos mód egy pályán." msgid "Standard Game" msgstr "Szimpla játék" msgid "A single player game playing through a series of maps." msgstr "Egyjátékos mód egy csomó pályán át." msgid "Campaign Game" msgstr "Hadjárat" msgid "Multi-Player Game" msgstr "Többjátékos mód" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "A többjátékos módban több emberi játékos vesz részt, hogy legyÅ‘zze a másikat " "egy pályán." msgid "fheroes2 Resurrection Team presents" msgstr "fheroes2 Resurrection Team bemutatja" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Üdvözlünk az fheroes2 motorral működÅ‘ Heroes of Might and Magic II-ben!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" "\n" "\n" "Ha szimulálni szeretné a jobb gombbal történÅ‘ kattintást érintéssel, hogy " "információkat kapjon a különbözÅ‘ elemekrÅ‘l, elÅ‘ször érintse meg és tartsa " "érintve az érdeklÅ‘désre számot tartó elemet, majd érintse meg bárhol máshol " "a képernyÅ‘t. Amíg a második ujját lenyomva tartja, eltávolíthatja az elsÅ‘t a " "képernyÅ‘rÅ‘l, és továbbra is megtekintheti az elemen található információkat." msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "\n" "\n" "MielÅ‘tt megkezded a játékot, válaszd ki a képernyÅ‘felbontást." msgid "Greetings!" msgstr "Üdvözlet!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Kilépés a Heroes of Might and Magic II-bÅ‘l és visszatérés az operációs " "rendszerhez." msgid "Credits" msgstr "KészítÅ‘k" msgid "View the credits screen." msgstr "KészítÅ‘k listájának megjelenítése." msgid "View the high scores screen." msgstr "DicsÅ‘ségtábla megjelenítése." msgid "Create new or modify existing maps." msgstr "Új térkép létrehozása vagy meglévÅ‘ módosítása." msgid "Change language, resolution and settings of the game." msgstr "" "Játék nyelvének, képernyÅ‘felbontásának kiválasztása, illetve egyéb " "beállítások." msgid "Game Settings" msgstr "Játékbeállítások" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "A hadjárat kiválasztási ablak megnyitásához a szükséges videók hiányoznak. " "Kérlek bizonyosodj meg róla, hogy minden szükséges fájl jelen van-e a " "rendszerben." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Roland, illetve Archibald hadjárata az eredeti Heroes of Might and Magic II-" "bÅ‘l." msgid "Original Campaign" msgstr "Eredeti hadjárat" msgid "Expansion Campaign" msgstr "KiegészítÅ‘ hadjárat" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "A Hűség ára kiegészítÅ‘ négy új hadjáratának egyike." msgid "Loading video. Please wait..." msgstr "Videó betöltése. Kérlek várj..." msgid "Host" msgstr "Kiszolgáló" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "A kiszolgáló határozza meg a játék beállításait. Csak egy kiszolgáló lehet " "egy hálózati játékban." msgid "Guest" msgstr "Vendég" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "A vendég várja a kiszolgálót, hogy állítson be egy játékot, ami aztán " "automatikusan látható lesz. Több vendég is lehet egyszerre egy hálózati " "játszmában." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "Az fheroes2 működéséhez szükségesek az eredeti Heroes of Might and Magic II " "adatfájljai. Úgy tűnik, hogy a Heroes of Might and Magic II demó változatát " "használod. Felhívjuk a figyelmet arra, hogy ezzel a beállítással csak " "egyetlen küldetés érhetÅ‘ el." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Többjátékos játék, több emberi játékos részvételével, akik egymás ellen " "küzdenek egyetlen térképen." msgid "Battle Only" msgstr "Csak csata" msgid "Setup and play a battle without loading any map." msgstr "Egyetlen csata beállítása és lejátszása térkép betöltése nélkül." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Helycserés játék, mely során 2-6 játékos játszik ugyanazon az eszközön és " "körönként cserélÅ‘dnek, amikor rájuk kerül a sor (Hot Seat)." msgid "2 Players" msgstr "2 játékos" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "Kétszemélyes játék, opcionálisan max. 4 további gépi ellenféllel." msgid "3 Players" msgstr "3 játékos" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "Háromszemélyes játék, opcionálisan max. 3 további gépi ellenféllel." msgid "4 Players" msgstr "4 játékos" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "Négyszemélyes játék, opcionálisan max. 2 további gépi ellenféllel." msgid "5 Players" msgstr "5 játékos" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "Ötszemélyes játék, opcionálisan max. 1 további gépi ellenféllel." msgid "6 Players" msgstr "6 játékos" msgid "Play with 6 human players." msgstr "Hatszemélyes játék." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Sárkányváros elesett! Mától te vagy a Sárkánymester." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Elfoglaltad %{name} várat!\n" "GyÅ‘ztél." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Elkaptad az ellenséges %{name} hÅ‘st!\n" "Küldetés teljesítve." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Megtaláltad %{name} varázstárgyat.\n" "Küldetés teljesítve." msgid "Ultimate Artifact" msgstr "Szent Varázstárgy" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Az ellenség elbukott.\n" "GyÅ‘ztél!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Sikerült %{count} aranyat felhalmoznod a kincstáradban.\n" "Az összes ellenfeled fejet hajt elÅ‘tted." msgid "Victory!" msgstr "GyÅ‘zelem!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Az ellenfél elfoglalta %{name} várat!\n" "Åk gyÅ‘ztek." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Az ellenfél már %{count} aranyat felhalmozott a kincstárában.\n" "Fejet kell hajtanod az ereje és hatalma elÅ‘tt." msgid "You have been eliminated from the game!!!" msgstr "Kiestél a játékból!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Elveszítetted %{name} hÅ‘st.\n" "A küldetésed elbukott." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Nem tudtad idÅ‘ben teljesíteni a küldetésed.\n" "Minden elveszett." msgid "Defeat!" msgstr "Vereség!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Alap pontszám: %{score}\n" "Nehézség: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Az ellenfelek összes hÅ‘sének legyÅ‘zése és várainak, városainak elpusztítása." msgid "Your side defeats the opposing side." msgstr "Te vagy szövetségeseid legyÅ‘zik az ellenfeleket." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Az idÅ‘ lejárt. (Nem sikerült nyernie adott idÅ‘ alatt.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Le kell gyÅ‘znöd %{enemies} ellenfelet." msgstr[1] "Le kell gyÅ‘znöd %{enemies} ellenfeleket." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Szövetséged tagja %{allies} és te. LegyÅ‘zendÅ‘ ellenségeitek: %{enemies}." msgstr[1] "" "Szövetséged tagjai %{allies} és te. LegyÅ‘zendÅ‘ ellenséges szövetség: " "%{enemies}." msgid "Capture the castle '%{name}'." msgstr "'%{name}' vár elfoglalása." msgid "Capture the town '%{name}'." msgstr "'%{name}' város elfoglalása." msgid "Defeat the hero '%{name}'." msgstr "'%{name}' hÅ‘s legyÅ‘zése." msgid "Find the ultimate artifact." msgstr "A Szent Varázstárgy megtalálása." msgid "Find the '%{name}' artifact." msgstr "'%{name}' varázstárgy megtalálása." msgid "Accumulate %{count} gold." msgstr "%{count} arany összegyűjtése." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", vagy legyÅ‘zöd az ellenfelek összes hÅ‘sét és elfoglalsz minden ellenséges " "várat és várost." msgid "Lose the castle '%{name}'." msgstr "'%{name}' vár elvesztése." msgid "Lose the town '%{name}'." msgstr "'%{name}' város elvesztése." msgid "Lose the hero: %{name}." msgstr "'%{name}' hÅ‘s elvesztése." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "Nem sikerül gyÅ‘zni %{month} hó %{week} hét %{day} napjáig." msgid "%{color} player has been vanquished!" msgstr "%{color} játékos legyÅ‘zetett!" msgid "Major Event!" msgstr "Fontos esemény!" msgid "Scenario:" msgstr "Küldetés:" msgid "Game Difficulty:" msgstr "Játék nehézsége:" msgid "Opponents:" msgstr "Ellenfelek:" msgid "Class:" msgstr "Osztály:" msgid "Rating %{rating}%" msgstr "Besorolás: %{rating}%" msgid "Click here to select which scenario to play." msgstr "Kattints ide, hogy kiválaszd melyik Küldetéssel játszol." msgid "Scenario" msgstr "Küldetés" msgid "Game Difficulty" msgstr "Játék nehézsége" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "LehetÅ‘vé teszi a játék kezdÅ‘ nehézségének beállítását. Nehezebb fokozatokon " "egyre kevesebb erÅ‘forrással kezdesz, illetve a számítógép extra " "erÅ‘forrásokat kap." msgid "Difficulty Rating" msgstr "Nehézség besorolás" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "A nehézségi besorolás visszatükrözi a játék beállításait. Ez a besorolás meg " "fog jelenni majd az összpontszámnál is." msgid "Click to accept these settings and start a new game." msgstr "Kattints a beállítások elfogadásához és új játék indításához." msgid "Click to return to the main menu." msgstr "Kattints a fÅ‘menübe való visszatéréshez." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Az asztrológusok kihirdették a(z) %{name} havát." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Az asztrológusok kihirdették a(z) %{name} hetét." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "A(z) %{monster} népessége megduplázódott!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "A(z) %{monster} népessége %{count} százalékkal megnövekedett!" msgstr[1] "A(z) %{monster} népessége %{count} százalékkal megnövekedett!" msgid "%{monster} growth +%{count}." msgstr "%{monster} szaporulat: +%{count}." msgid " All populations are halved." msgstr " Minden populáció megfelezÅ‘dött." msgid " All dwellings increase population." msgstr " Mindegyik toborzóhelynek nÅ‘tt a szaporulata." msgid "New Month!" msgstr "Új hónap!" msgid "New Week!" msgstr "Új hét!" msgid "Beware!" msgstr "Vigyázat!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} játékos, ez az utolsó napod, hogy elfoglalj egy várost vagy " "száműznek errÅ‘l a földrÅ‘l." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} játékos, már csak %{day} napod maradt, hogy elfoglalj egy város, " "vagy száműznek errÅ‘l a földrÅ‘l." msgid "%{color} player's turn." msgstr "%{color} játékos köre." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} játékos, elvesztetted az utolsó városod is, ha nem szerzel egy " "másik várost a következÅ‘ héten, akkor végleg elbuksz." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} játékos, a hÅ‘seid elhagytak, téged pedig száműztek errÅ‘l a földrÅ‘l." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebeka" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "KövetkezÅ‘ hÅ‘s" msgid "Select the next Hero." msgstr "KövetkezÅ‘ hÅ‘s kiválasztása." msgid "Hero Movement" msgstr "HÅ‘s mozgása" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "A hÅ‘s mozgásának megkezdése a kijelölt útvonal mentén vagy pedig a hÅ‘s által " "elfoglalt objektum újra-látogatása. A gombot hosszan nyomva tartva, törlÅ‘dik " "a hÅ‘s útvonala." msgid "Kingdom Summary" msgstr "Királyság összesítése" msgid "View a summary of your Kingdom." msgstr "Királyságod áttekintésének megjelenítése." msgid "Cast an adventure spell." msgstr "Kalandozó varázslat idézése." msgid "End Turn" msgstr "A kör befejezése" msgid "End your turn and let the computer take its turn." msgstr "Befejezed a kört és a számítógép lép." msgid "Adventure Options" msgstr "Kaland Opciók" msgid "Bring up the adventure options menu." msgstr "Megjeleníti a kaland opciók menüt." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Megjeleníti a fájlbeállítások menüt, ahol pl. létrehozhatsz új játékot, " "illetve menthetsz és betölthetsz játékállásokat." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Megjeleníti a rendszerbeállítások menüt, melyben testre szabhatod a " "játékprogram működését." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Egy vagy több hÅ‘s még mozoghat, biztos vagy benne hogy be akarod fejezni a " "kört?" msgid "Are you sure you want to quit?" msgstr "Biztosan ki szeretnél lépni?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Biztos vagy benne hogy újrakezded? (A jelenlegi játékod el fog veszni.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Biztosan felülírod a mentést ezzel a névvel?" msgid "Game saved successfully." msgstr "A játék sikeresen mentve." msgid "There was an issue during saving." msgstr "Valami szösz került a gépezetbe mentés közben." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Biztos hogy új játékot töltesz be? (A jelenlegi játékod el fog veszni.)" msgid "Try looking on land!!!" msgstr "Próbálkozz a szárazföldön!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Megtaláltad a Szent varázstárgyat, de nem tudod magadhoz venni, mert tele " "vagy egyéb felszereléssel." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" "Egy varázstárgy kiásása egy teljes napot vesz igénybe, holnap próbáld újra." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "Több órányi ásás után megtaláltad ezt: %{artifact}." msgid "Congratulations!" msgstr "Gratulálunk!" msgid "Nothing here. Where could it be?" msgstr "Itt nincs semmi, hol lehet?" msgid "Try searching on clear ground." msgstr "Keress tiszta területet." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Az ismert világ kicsinyített mása. Bal kattintással mozgathatod a látható " "területet." msgid "Month: %{month} Week: %{week}" msgstr "Hónap: %{month} Hét: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Találtál\n" "egy kis %{resource}-t." msgid "Status Window" msgstr "ÃllapotjelzÅ‘ ablak" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Ez az ablak információkat ad a hÅ‘södrÅ‘l, a királyságodról és mutatja a " "dátumot." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Ez az ablak információkat ad a hÅ‘södrÅ‘l, a királyságodról és mutatja a " "dátumot. Bal kattintással lehet lépkedni az ablakok között." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "LehetÅ‘vé teszi a játékos színének és kezdÅ‘pontjának megválasztását. Egy " "bizonyos szín mindig egy bizonyos helyrÅ‘l indul a játékban. Néhány pozíciót " "csak gépi vagy emberi játékos foglalhat el." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "LehetÅ‘vé teszi a játékos osztályának megválasztását. Az osztály nem mindig " "módosítható. KüldetéstÅ‘l függÅ‘en a játékos további várakat és hÅ‘söket kaphat." msgid "Handicap" msgstr "Hátrány" msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "LehetÅ‘vé teszi az egyes játékosok hátrányának megváltoztatását. Csak emberi " "játékos sújtható hátránnyal. A hátrányban lévÅ‘ játékosok kevesebb " "erÅ‘forrással kezdenek és azok 15-30%-kal kevesebbel gyarapodnak körönként a " "hátrány mértékétÅ‘l függÅ‘en, mely lehet mérsékelt vagy súlyos." msgid "%{color} player" msgstr "%{color} játékos" msgid "No Handicap" msgstr "Nincs hátrány" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Nincs semmilyen megkötés az induló erÅ‘forrásokkal és a körönkénti " "gyarapodásukkal kapcsolatban." msgid "Mild Handicap" msgstr "Mérsékelt hátrány" msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Mérsékelt hátrányban lévÅ‘ játékosok kevesebb erÅ‘forrással kezdenek és azok " "15%-kal kevesebbel gyarapodnak körönként." msgid "Severe Handicap" msgstr "Súlyos hátrány" msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Súlyosan hátrányban lévÅ‘ játékosok kevesebb erÅ‘forrással kezdenek és azok " "30%-kal kevesebbel gyarapodnak körönként." msgid "" "Default\n" "value" msgstr "" "Alapért.\n" "érték" msgid "Set %{skill} Skill" msgstr "%{skill} képesség beállítása" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" "%{skill} alapértékének beállítása. Jobb kattintásra minden képesség " "alapértékekre áll." msgid "View %{skill} Info" msgstr "%{skill} információ megtekintése" msgid "" "Default\n" "skill" msgstr "" "Alapértelmezett\n" "képesség" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "SPACE" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "A megadott érték helytelen." msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" "A megadható érték nem lehet kevesebb, mint %{minValue} és nem lehet több, " "mint %{maxValue},\n" "de a megadott érték ezen a tartományon kívül van." msgid "Kingdom Income" msgstr "Királyság jövedelme" msgid "Kingdom Income per day." msgstr "Királyság napi jövedelme." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Minden fennhatóságod alatt lévÅ‘ világítótorony miatt a hajóid többet " "mozoghatnak minden nap." msgid "English" msgstr "angol" msgid "French" msgstr "francia" msgid "Polish" msgstr "lengyel" msgid "German" msgstr "német" msgid "Russian" msgstr "orosz" msgid "Italian" msgstr "olasz" msgid "Czech" msgstr "cseh" msgid "Norwegian" msgstr "norvég" msgid "Belarusian" msgstr "fehérorosz" msgid "Bulgarian" msgstr "bolgár" msgid "Ukrainian" msgstr "ukrán" msgid "Romanian" msgstr "román" msgid "Spanish" msgstr "spanyol" msgid "Swedish" msgstr "svéd" msgid "Portuguese" msgstr "portugál" msgid "Turkish" msgstr "török" msgid "Dutch" msgstr "holland" msgid "Hungarian" msgstr "Magyar" msgid "Danish" msgstr "dán" msgid "Slovak" msgstr "szlovák" msgid "Vietnamese" msgstr "vietnámi" msgid "Slow" msgstr "Lassú" msgid "Fast" msgstr "Gyors" msgid "Very Fast" msgstr "Nagyon gyors" msgid "Evil" msgstr "Gonosz" msgid "Good" msgstr "Jó" msgid ", FPS: " msgstr ", FPS: " msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} rabló" msgid "pyramid|%{object} raided" msgstr "%{object} már ki van fosztva" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlasz" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasa" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxána" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Eliza nÅ‘vér" msgid "Brother Brax" msgstr "Brax atya" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " maximális morált ad" msgid " gives you maximum luck" msgstr " maximális szerencsét ad" msgid "You cannot have multiple spell books." msgstr "Nem birtokolhatsz több varázskönyvet." msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" "Nem tudod felvenni ezt a varázstárgyat, mert már így is túl vagy terhelve!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Hogy varázsolhass, elÅ‘ször vásárolnod kell %{gold} aranyért varázskönyvet." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Sajnos, nincs elég aranyad." msgid "Do you wish to buy one?" msgstr "Szeretnél venni egyet?" msgid "%{count} / day" msgstr "%{count} / nap" msgid "one" msgstr "egy" msgid "two" msgstr "kettÅ‘" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "Egy örvény elnyeli a hajód. A csapatod néhány tagja a tengerbe esett." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Visszautasítottad az ajánlatukat, ezért megtámadnak!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "A(z) %{monster} félnek a csapatod erejétÅ‘l és megpróbálnak elmenekülni.\n" "Akarod üldözni és megtámadni Å‘ket?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "Az ellenséges tábor kifosztása közben rálelsz egy elrejtett kicsre." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "A malom gazdája azt mondja:\n" "\"Uram, keményen dolgoztam, hogy ezeket a nyersanyagokat neked adjam, Gyere " "vissza a következÅ‘ héten továbbiakért." msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "A malom gazdája azt mondja:\n" "\"Uram, elnézést, de jelenleg nincsen nyersanyagom. Próbálja meg jövÅ‘ héten." "\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "A malom gazdája azt mondja:\n" "\"Uram, keményen dolgoztam, hogy ennyi aranyat tudjak neked adni, Gyere " "vissza a következÅ‘ héten továbbiakért.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "A malom gazdája azt mondja:\n" "\"Uram, elnézést, de jelenleg nincsen aranyam. Próbálja meg jövÅ‘ héten.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Rátaláltál egy elhagyatott viskóra.\n" "Körbekutatva rálelsz a közelben némi elrejtett erÅ‘forrásra." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "A viskó már régóta elhagyatott. Semmi értékes nincs már itt." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Fülön csípsz egy koboldot, amint egy csomó varázsgomba között szunyókál.\n" "Szabadságáért cserébe mutat neked egy edényt tele különleges dolgokkal." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Egy varázskertre bukkantál, ahol koboldok és tündérek szoktak játszadozni. " "Ma azonban senki sincs itt.\n" "Próbáld meg esetleg a jövÅ‘ héten." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Egy szerencsétlen kalandor maradványaira lelsz rá." msgid "Treasure" msgstr "Kincs" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" "Ãtkutatod rongyos ruházatát és rábukkansz erre a varázstárgyra: %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Ãtkutatod rongyos ruházatát, de semmit sem találsz." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Rábukkansz egy öreg szekérre, amit egy kereskedÅ‘ hagyott hátra, mivel nem " "tudta megvédeni." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Sajnos, valaki hamarabb rátalált a szekérre, így az üres." msgid "Searching inside, you find the %{artifact}." msgstr "Ãtkutatva megtaláltad a(z) %{artifact} varázstárgyat." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Ãtkutatva találsz némi érintetlen rakományt." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Ãtkutatod az uszadékot, és találsz egy kevés fát és aranyat." msgid "You search through the flotsam, and find some wood." msgstr "Ãtkutatod az uszadékot, és találsz egy kevés fát." msgid "You search through the flotsam, but find nothing." msgstr "Ãtkutatod az uszadékot, de semmit sem találsz." msgid "Shrine of the 1st Circle" msgstr "ElsÅ‘ Kör szentélye" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Egy kis szentélyhez értél, melyet novíciusok csoportja látogat.\n" "Védelmedért cserébe megtanítanak egy varázslatra: '%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Második Kör szentélye" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Egy díszes szentélyhez értél, melyet joviális szerzetesek látogatnak.\n" "Védelmedért cserébe megtanítanak egy varázslatra: '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Harmadik Kör szentélye" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Egy pazar szentélyhez értél, melyet fÅ‘papok csoportja látogat.\n" "Védelmedért cserébe megtanítanak egy bonyolult varázslatra: '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Sajnos nem elegendÅ‘ a bölcsességed, hogy megértsd a varázslatot, így nem " "vagy képes azt megtanulni." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Már ismered a varázslatot, másuk pedig nincs, amit taníthatnának neked." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Sajnos nincs varázskönyved, amibe a varázslatot beírhatnád." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "A kunyhóhoz érve meglátsz egy öreg banyát, aki egy %{skill}-könyvet " "olvasgat.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Amint észrevesz, elkezd téged bámulni az egy szem üvegszemével.\n" "Rádkiabál: \"Te már mindent tudsz, amit kiérdemeltél! KIFELÉ A HÃZAMBÓL!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Ahogy közeledsz megfordul és ezt mondja:\n" "\"Te már tudod azt amit én tanítani tudnék neked, Másban nem segíthetek.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Egy vénséges, halhatatlan boszorkány lakik a cölöpkunyhóban, aki " "kifürkészhetetlen okok miatt megtanít téged a(z) %{skill} képességre." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" "Ha iszol az édesvízbÅ‘l, akkor a következÅ‘ csatádhoz szerencsét szerzel." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Iszol az elvarázsolt kútból, de dem történik semmi." msgid "You enter the faerie ring, but nothing happens." msgstr "Belépsz a körbe, de semmi nem történik." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Ahogy belépsz a misztikus körbe, a sereged szerencsét nyer a következÅ‘ " "csatáig." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Rábukkantál egy Å‘srégi, szélkoptatta kÅ‘bálványra.\n" "Azt mondják, szerencsét hoz a látogatónak, azonban a szerencse már " "rádmosolygott, ezért nem történik semmi." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Rábukkantál egy Å‘srégi, szélkoptatta kÅ‘bálványra.\n" "Azt mondják, ha megcsókolják, szerencsét hoz - így is teszel. A kÅ‘ nagyon " "hideg." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "A sellÅ‘k csábítanak, hogy késÅ‘bb jöjj vissza és újra megáldanak." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "A sellÅ‘k varászlatos és andalító szépsége magával ragad téged és " "embereidet.\n" "Egy pillanatra elfelejted minden bánatod és csak fürdesz a pillanat " "szépségében.\n" "A sellÅ‘k bűbájától szerencsésebb leszel a következÅ‘ csatában." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Egy Å‘si és nagy király piramisához érkezel.\n" "Izgat a kíváncsiság és átkutatnád kincsek után, de visszatartanak a " "félelmetes átkokról és élÅ‘halott Å‘rzÅ‘krÅ‘l szóló mendemondák.\n" "Ãtkutatod ennek ellenére?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "A lények legyÅ‘zése után egy Å‘si írásjelet betűzöl ki a falon, mely e " "varázslat titkáról mesél: '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "Szerencsétlenségedre, nincs varázskönyved, amibe a varázslatot beírhatnád." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Szerencsétlenségedre, nem vagy elég bölcs, hogy megértsd a varázslatot, nem " "hogy megtanuld..." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Egy Å‘si és nagy király piramisához érkezel.\n" "Rutinszerűen átkutatod, de a piramis teljesen üres." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "A kútból történÅ‘ ivás feltöltené a varázspontodat, de már maximumon van." msgid "A second drink at the well in one day will not help you." msgstr "Egy napon belüli második ivás nem hat rád." msgid "A drink from the well has restored your spell points to maximum." msgstr "A kútból történÅ‘ ivás feltölti a varázspontodat." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Sajnálom Uram,\" - mondja a katonák vezetÅ‘je - \"de Ön már mindent tud, " "amit mi megtaníthatnánk...\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Az erÅ‘dítményben állomásozó katonák tanítanak neked néhány új védelmi " "trükköt." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Zsoldosok táborához érkezel, akik éppen harci taktikáikat gyakorolják. \"Túl " "képzett vagy hozzánk\" - mondja a zsoldosvezér. \"Nem tudunk többet tanítani." "\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Zsoldosok táborához érkezel, akik éppen harci taktikáikat gyakorolják. A " "zsoldosok köszöntenek téged és embereidet, majd meghívnak egy kis " "gyakorlatozásra velük." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" "\"Takarodj innen!\" - rivall rád az vajákos - \"Nem tudok neked újat mondani!" "\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "A kunyhóban élÅ‘ ork vajákos boszorkány szélesíti a mágikus tudásodat kövek " "elmozdítása, csodás jelek értelmezése, illetve csirke zsigerekbÅ‘l jóslás " "terén." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Druidák egy csoportjára bukkansz, akik furcsa kőépítményükben imádkoznak. A " "Druidák elküldenek azzal, hogy nem tudnak neked semmi újat tanítani." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Druidák egy csoportjára bukkansz, akik furcsa kőépítményükben imádkoznak. Új " "dolgokat tanítanak meg neked a varázslás terén." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Óvatosan megközelíted a letűnt harcosok temetkezési helyét. Ãt akarod " "kutatni a sírokat?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Miután legyÅ‘zted a Zombikat, órákat töltöttél el a sírok átkutatásával, de " "nem találtál semmit. Csökkent a csapatod morálja." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "Miután legyÅ‘zted a zombikat, átkutattad a sírokat és találtál valamit!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Egy nagy kalózhajó korhadó fateste nyikorog hátborzongatóan a sziklákon. Ãt " "akarod kutatni a hajóroncsot?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Órákat töltesz el a törmelék átkutatásával, de nem találsz semmit. Csapatod " "tagjai alantasnak találják ezt a munkát és csökken a moráljuk." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "A szellemek legyÅ‘zése után átkutatod a törmeléket és találsz valamit!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Egy nagy kalózhajó korhadó fateste nyikorog hátborzongatóan a sziklákon. Ãt " "akarod kutatni a hajóroncsot?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "A csontvázak legyÅ‘zése után átkutatod a törmeléket és találsz valamit!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "A matrózaid meglátnak egy bóját a vízen. Jó irányba haladsz." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "A matrózaid meglátnak egy bóját a vízen. Jó irányba haladsz és növekszik " "sereged morálja." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Ha iszol az oázisban, akkor felfrissülsz, de más nem történik. Csak az elsÅ‘ " "csatádban segít a hatása." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Ha iszol az oázisban, akkor az egységeid ereje és morálja feltöltÅ‘dik. Ezért " "ma egy kicsit tovább tudsz haladni." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Ha iszol az itatónál, akkor felfrissülsz, de más nem történik. Csak az elsÅ‘ " "csatádban segít a hatása." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Ha iszol az itatónál, akkor az egységeid ereje és hangulata feltöltÅ‘dik. " "Ezért ma egy kicsit tovább tudsz haladni." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Az nem segít, ha többször imádkozol csata elÅ‘tt, gyere vissza harc után." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Egy látogatás és egy imádság a templomban niveli a csapataid morálját." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Egy öreg lovag jelenik meg a kilátó lépcsÅ‘in. \"Bocsánat, Uram, mindenre " "megtanítottam Önt, amit én tudok.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Egy öreg lovag jelenik meg a kilátó lépcsÅ‘in. \"Uram, mindenre meg akarom " "Önt tanítani, amit én tudok, hogy segítsem az utazását.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Megmentesz egy hajótöröttet az óceán halálosan ölelÅ‘ karjából. Jótettedért " "cserébe azt mondja: \"Jutalmul adnék neked egy varázstárgyat, de tele van a " "hátizsákod.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Megmentesz egy hajótöröttet az óceán halálosan ölelÅ‘ karjából. Jótettedért " "cserébe megjutalmaz egy %{art} varázstárggyal." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "Egy kobold %{art}-t kínál neked %{gold} aranyért cserébe." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Egy kobold %{art}-t kínál neked %{gold} aranyért és %{count} %{res}-ért " "cserébe." msgid "Do you wish to buy this artifact?" msgstr "Meg akarod venni ezt a varázstárgyat?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Épp fizetnél a koboldnak, de rájössz, hogy nincs elég pénzed. A kobold " "dobbant egyet a lábával és nem vesz rólad tudomást." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "A kobold vérig sértÅ‘dik, mert visszautasítottad nagylelkű ajánlatát. Dobbant " "egyet a lábával és nem vesz rólad tudomást." msgid "You've found the artifact: " msgstr "Megtaláltad a varázstárgyat. " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Rátalálsz egy ráncos vén remete szerény lakhelyére. A remete elmondja neked, " "hogy a legelsÅ‘ bölcs embernek akarja odadni ezt: %{art}." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Rátalálsz egy obsitos katona szerény lakhelyére. A volt katona elmondja " "neked, hogy a legelsÅ‘ igazi vezéregyéniségnek akarja odadni ezt: %{art}." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Összetalálkozol egy furcsa emberrel, akinek a kalapján egy bagoly ül. Azt " "mondja, hogy ha bírsz a(z) %{skill} képességgel, akkor odaadja neked ezt: " "%{art}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Ráakadsz egy Å‘si varázstárgyra, de amint közeledsz hozzá, egy rablócsapat " "lép elÅ‘ a környezÅ‘ bokrokból, hogy megvédjék lopott zsákmányukat." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Kiürítés közben felfedezel egy varázstárgyat. Sajnos, %{monster} Å‘rzik. Meg " "akarsz küzdeni velük a varázstárgyért?" msgid "Victorious, you take your prize, the %{art}." msgstr "GyÅ‘zelem! Vedd át megérdemelt jutalmadat, mely egy %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "A megfontoltság a vitézség tiszteletre méltó oldala. Ma úgy döntesz, hogy " "elállsz a harctól." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Több órás munkával sikerül kihalásznod egy ládát a tengerbÅ‘l. Kinyitod, és " "%{gold} aranyat találsz benne." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Több órás munkával sikerül kihalásznod egy ládát a tengerbÅ‘l. Kinyitod, és " "%{gold} aranyat valamint egy %{art} varázstárgyat találsz benne." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Több órás munkával sikerül kihalásznod egy ládát a tengerbÅ‘l. Kinyitod, de " "nem találsz benne semmit sem." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "A terület átkutatása után rábukkansz egy elrejtett kincsesraktárra. " "Elteheted magadnak az aranyat, vagy szétoszthatod tapasztalati ponttért " "cserébe a parasztok között. Megtartod az aranyat?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "A terület átkutatása után rábukkansz egy elrejtett ládára, amiben %{gold} " "arany van." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "A terület átkutatása után rábukkansz egy elrejtett ládára, amiben egy régi " "%{art} varázstárgy van." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Egy horpadt, patinás lámpásra bukkansz mélyen a földbe fúródva. Ki akarod " "fényesíteni a lámpást?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Megszerezted a helyi alkímista labort. Ez naponta %{count} egységnyi higanyt " "biztosít számodra." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Megszereztél egy fűrészmalmot. Ez naponta %{count} egységnyi fát biztosít " "számodra." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Megszereztél egy vasércbányát. Ez naponta %{count} egységnyi vasércet ad " "neked." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Megszereztél egy kénbányát. Ez naponta %{count} egységnyi ként ad neked." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Megszereztél egy kristálybányát. Ez naponta %{count} egységnyi kristályt ad " "neked." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Megszereztél egy gyöngybányát. Ez naponta %{count} egységnyi gyöngyöt ad " "neked." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "Megszereztél egy aranybányát. Ez naponta %{count} aranyat ad neked." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "A kilátótorony a fennhatóságod alá került, így minden hajód többet mozoghat " "körönként." msgid "You gain control of a %{name}." msgstr "Irányítást szereztél %{name} felett." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Egy elhagyatott aranybányához érsz, mely kísértetjártának tűnik. Be akarsz " "lépni?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Elűzted a szellemeket, a bánya újra használható." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "%{monster} egy csoportja a dicsÅ‘ség reményében csatlakozna hozzád. Elfogadod " "Å‘ket?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" "Ahogy megközelítetted a lakóhelyet, észreveszed, hogy nincs senki bent." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Ãtkutattad a romokat, ahol Medúzák laknak, de most nem találsz itt senkit. " "Próbáld meg a jövÅ‘ héten." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Megtaláltad a romok közt élÅ‘ Medúzákat. Csatlakoznak hozzád aranyért " "cserébe. Akarsz Medúzát toborozni?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Találtál egy Tündér Fa Várost. Sajnos egyetlen Tündér sem tartózkodik itt, " "hogy csatlakozzanak hozzád. Talán a jövÅ‘ héten." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Tündérek laknak a Fa Városukban és csatlakoznának hozzád aranyért cserébe. " "Szeretnél Tündért toborozni?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Egy tarkabarka szekér áll itt, láthatóan rablóké. Lehet, hogy késÅ‘bb még " "felbukkannak itt." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Távoli zeneszó és nevetés hallatszik, mely odavonz a rablóknak otthont adó " "tarkabarka szekérhez. Akarod, hogy csatlakozzon hozzád bármelyikük?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Ütött-kopott sátrak hullámoznak a szélben hívogatóan. A sátrak " "elhagyatottak, de késÅ‘bb talán lesznek még nomádok itt." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Ütött-kopott sátrak hullámoznak a szélben hívogatóan. Akarod, hogy nomádok " "csatlakozzanak hozzád utazásaid során?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "A sárgödör bugyog egy percig, majd elcsitul." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Ahogy közeledsz a bugyogó sárgödörhöz, fura lények kezdenek elÅ‘bújni belÅ‘le " "és körbeállni azt. Együtt, egyszólamban mondják neked: \"Föld Anya szeretne " "felajánlani számodra néhányat a seregeibÅ‘l. Akarsz Földelementálokat " "toborozni?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Belépsz a fehér kÅ‘oszlopos építménybe, de nem találsz semmit." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "A fehér kÅ‘oszlopok az egekig nyúló tetÅ‘t tartanak. Ahogy belépsz közéjük, " "áporodott levegÅ‘ kerekdik fel és kavarog hatalmas erÅ‘vel, mely majdnem téged " "is kilök. A légáramlat lassan alig látható formát kezd ölteni, majd a lény " "susogva így szól: \"Miért jöttél? Meg akarod idézni a levegÅ‘ erejét?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "A lávatóból nem közeledik feléd egyetlen Tűzelementál sem." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "A meleget magában tartó struktúrák alatt Tűzelementálok mozgolódnak egy " "tüzes lávatóban. Egy kisebb csoportjuk közeledik hozzád és felajánlják a " "szolgálataikat neked. Akarsz Tűzelementálokat toborozni?" msgid "A face forms in the water for a moment, and then is gone." msgstr "" "Egy arckép válik láthatóvá a vízben egy piilanatra és aztán el is tűnik." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "A kristály struktúrák árnyékot vetnek egy kicsi, tükrözÅ‘dÅ‘ vízű tócsára. " "Belepillantasz a vízbe, de az arc, ami visszabámul rád, nem a tied. Emígyen " "szólít meg: \"Valóban e víz hatalmához szeretnél fordulni?\"" msgid "This burial site is deathly still." msgstr "A temetkezési hely még mindig halálos." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Sok halott harcos nyughatatlan lelke a végsÅ‘ nyughely megtalálásának " "reményében csatlakoznának hozzád. Szeretnél szellemeket toborozni?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "A Halott Városban jelenleg egy lélek sem található. Talán a jövÅ‘ héten lesz " "néhány élÅ‘halott." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Néhány Lich él itt és fizetség fejében csatlakoznak hozzád. Akarsz Lich-eket " "toborozni?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Egy Å‘si város romjaira bukkantál, melyet kizárólag élÅ‘holtak laknak. " "Szeretnél körülnézni?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "A túlélÅ‘ Lich-ek elismerik a társaik felett aratott gyÅ‘zelmedet és " "felajánlják, hogy fizettségért cserébe csatlakoznak hozzád. Akarsz Lich-eket " "toborozni?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Találtál egy olyan hidat, amely alatt Trollok laknak, de most nincs itt egy " "sem. Talán a jövÅ‘ héten itt lesznek néhánzan." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Néhány Troll él a híd alatt, akik némi pénzért cserébe csatlakoznának " "hozzád. Felfogadod Å‘ket?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "A híd alatt élÅ‘ Trollok belédkötnek. Megküzdesz velük?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Egy kevés Troll a híd alatt rejtÅ‘zködik. Felajánlják, hogy beállnak hozzád " "zsoldosnak. Akarsz vásárolni néhány Trollt?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "A Sárkány városban nincsenek Sárkányok ezen a héten. Talán a következÅ‘ héten " "újra lesznek." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "A Sárkányvárosban lévÅ‘ Sárkányok fizetség fejében csatlakoznak hozzád. " "Akarsz Sárkányokat toborozni?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Sárkányváros kapui elÅ‘tt állsz, mely tiltott terület egyszerű halandók " "számára. Meg akarod szegni a szabályt és kihívni a sárkányokat egy " "küzdelemre?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Miután legyÅ‘zted a bajnok Sárkányokat a város vezetÅ‘i beleegyeznek, hogy " "fizetségért cserébe Sárkányokat vehetsz a csapatodba. Szeretnél Sárkányokat " "toborozni?" msgid "From the observation tower, you are able to see distant lands." msgstr "A Kilátótoronyból láthatod a távoli vidéket is." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "A forrás csak heti egyszer telik meg, és valaki már járt itt mostanában." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Ãllítólag, ha iszol a forrásból, akkor megkétszerezÅ‘dik a normál " "varázspontjaid száma, de te ezt a szintet már elérted." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Ha iszol a forrásból, akkor a véred megtelik varázserÅ‘vel! MegkétszerezÅ‘dik " "a normál varázspontjaid száma." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "A komornyik felismer téged és nem engedi, hogy belépj. \"A Mester\" mondja " "\"egy tanítványt sem fogad kétszer.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "Az inas beenged a mesterhez, aki 4 tulajdonságodban is kiképez." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Az inas ajtót nyit, és alaposan megnéz. \"Nem vagy elég ismert és " "diplomatikus ahhoz, hogy beengedjelek a mesteremhez. Gyere vissza, ha úgy " "érzed, hogy fejlÅ‘dtél valamennyit.\"" msgid " and " msgstr " és " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Az összes csapatodban lévÅ‘ %{monsters} lényed az erÅ‘dítmény harcos " "mestereitÅ‘l vettek leckét. A csapatodban már %{monsters2} lények vannak." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Az ogrék, orkok és törpök közötti szokatlan szövetkezés eredményeképpen " "bármely közülük való egységet ki lehet képezni (fejleszteni) ezen a helyen. " "Sajnos neked egyikbÅ‘l sincs a csapatodban." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Minden %{monsters} fel lett fejlesztve erre: %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Az Öntödében dolgozó kovácsmester felajánlja, hogy az összes Lándzsásod és " "Kardforgatód fegyverét vasból acéllá edzi. Azt mondja, ismeri a Vasgólem - " "Acélgólem átalakításának módszerét is. Sajnos, egyik egység sincs a " "seregedben, ezért nem tud neked segíteni." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "A kapitány meglepetten néz rád és azt mondja:\n" "\"Már rendelkezel minden térképpel, ami nekem csak van. Hagy nyugodtan " "pecázni.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Egy vén kapitány, aki ezen a mólón lakik, felajánlja neked megvételre az Å‘ " "általa, fiatalkorában készített tengeri térképet, 1000 aranyért cserébe. " "Megvásárolod a térképet?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "A kapitány felsóhajt. \"Ehh, nincs elég pénzed, ugye? Csak nem képzeled, " "hogy ingyen odaadom a térképeimet?\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Rátalálsz egy obeliszkre, mely olyan kÅ‘bÅ‘l készült, amilyent még sohasem " "láttál. Bámulod a sima felületét, melybÅ‘l egyszercsak rajzolat tűnik elÅ‘, " "egy régi térkép darabja. Gyorsan lemásolod a térképrészletet, majd a " "rajzolat ugyanolyan hirtelen tűnik el, ahogy megjelent." msgid "You have already been to this obelisk." msgstr "Már megnézted ezt az obeliszket." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Ahogy megközelíted, a fa kinyitja a szemeit. \"Öröm látni téged, " "tanítványom. Remélem a tanításaim segítségedre lesznek.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Ahogy megközelíted, a fa kinyitja a szemeit . \"Ahh, egy kalandor! Engedd " "meg, hogy megtanítsalak valamire, amit évek során megtanultam.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Ahogy megközelíted, a fa kinyitja a szemeit." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ahh, egy kalandor! Szívesen megtanítalak cserébe valamire, amit az évek " "során megtanultam. Ennek ára: %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Csak ásd el a gyökereim közé.)" msgid "Tears brim in the eyes of the tree." msgstr "A fa szemei megtelnek könnyel." msgid "\"I need %{count} %{res}.\"" msgstr "Szükségem van a következÅ‘kre: %{count} %{res}." msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "azt suttogja. (hüpp) \"Nos, gyere vissza amikor már tudsz fizetni.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Fák között megbújva üldögél egy vak látnok. Miután elmagyaráztad neki a " "küldetésed célját, a látnok működésbe hozza kristálygömbjét, melyben " "lehetÅ‘séged van meglátni ellenségeid gyengéit és erÅ‘sségeit." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "A barlang bejárata sötét, és undorító, kénes szag áramlik ki a barlang " "szájából. Belépsz?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Egy iszonyú csata tanújelein kívül a barlang üres." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "A barlangban egy hatalmas és groteszk démont találsz, aki fület tépÅ‘ hangon " "azt mondja: \"Harcolni fogsz és halál fia leszel. De megadom neked a " "lehetÅ‘séget, hogy megválaszd a halálod módját. Harcolhatsz velem vagy a " "szolgáimmal. Szívesebben harcolnál a szolgáimmal?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "A démon felüvölt a kihívás hallatán és támad! Rövid, de ádáz küzdelem után " "elpusztítod a szörnyet és ennyi tapasztalati ponttal gazdagodsz: %{exp}." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "A démon felüvölt a kihívás hallatán és támad! Rövid, de ádáz küzdelem után " "elpusztítod a szörnyet és ennyi tapasztalati ponttal gazdagodsz: %{exp}, " "valamint %{count} aranyat zsebelsz be." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "A démon felüvölt a kihívás hallatán és támad! Rövid, de ádáz küzdelem után " "elpusztítod a szörnyet és a barlang hátuljában rátalálsz erre: %{art}." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Látva, hogy nincs %{count} aranyad, a démon lesújt rád hatalmas karmaival és " "az utolsó emléked vörös ködbe vész." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "A démon rádugrik és karmaival megragadja a nyakadat, mielÅ‘tt akárcsak " "elÅ‘húzhatnád a kardodat. \"Az életed a kezemben van\" - ordítja - és csak " "%{count} aranyért adom vissza." msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Miután legyÅ‘zted a démon alattvalóit, egy titkos rejtekhelyen találsz " "%{count} aranyat." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Ahogy belépsz az alkimista toronyba egy barna-köpenyes sánta, öregedÅ‘ ember " "botorkál feléd." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Ãtnézi a batyudat és egy elátkozott tárgyat talál." msgstr[1] "Ãtnézi a batyudat és %{count} elátkozott tárgyat talál." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "Az alkimista %{gold} arany ellenében megszabadít tÅ‘le. Kifizeted?" msgstr[1] "Az alkimista %{gold} arany ellenében megszabadít tÅ‘lük. Kifizeted?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Miután belementél, hogy fizess, az alkimista megragadja az átokkal sújtott " "varázstárgyat és a varázsüstjébe veti." msgstr[1] "" "Miután belementél, hogy fizess, az alkimista megragadja az átokkal sújtott " "varázstárgyakat és a varázsüstjébe veti azokat." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Egy hangot hallasz a bezárt ajtó mögül: \"Nincs elég aranyad, hogy megfizesd " "a szolgálataimat.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Egy hangot hallasz a torony tetejérÅ‘l: \"Menj el! Nem tudok neked segíteni!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "A lovászmester megszólít: \"Szép lovad van. Attól tartok nem tudunk neked " "jobbat adni, viszont a lovasaid nem ilyen jó ménesbÅ‘l való lovakat ülnek meg." "Számos gyakorlott csatalovunk van, mely jó szolgálatot tehet nekik. Jó " "szívvelajánlom, hogy vigyél belÅ‘lük.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Ahogy közeledsz az istállóhoz, megjelenik a lovászmester, aki egy jó " "kiállású lovat vezet maga mellett. \"Ez a paripa segíteni fog, hogy gyorsabb " "legyen az utad. Sajnos egy hét után ez is elfárad. Engedd meg, hogy a " "lovasaidnak is jobb lovakat adjak, mert a lovaik hitványnak és gyengének " "tűnnek.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "A lovászmester feléd közeledik és azt mondja: \"Jó lovad van és a többi ló " "is elég harcedzettnek tűnik, csakúgy mint a mi csatalovaink.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Ahogy közeledsz az istállóhoz, megjelenik a lovászmester, aki egy jó " "kiállású lovat vezet maga mellett. \"Ez a paripa segíteni fog, hogy gyorsabb " "legyen az utad. Sajnos az ereje majd ennek is alábbhagy a nehéz vágtáktól és " "egy hét után vissza kell térj egy friss hátaslóért. Sok jó csatalovunk van, " "melyek jó szolgálatot tesznek felvértezett katonáknak, de úgy látom " "csapatodban nincs ilyen.\"" msgid "The Arena guards turn you away." msgstr "Az aréna Å‘rei elküldenek téged." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Megparancsolod a legénységednek, hogy viasszal tömjék be a fülüket, hogy ne " "hallják a szirének félelmetes énekét, ami hullámsírba csalhatná Å‘ket." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Amikor a szirének rákezdenek énekükre, kicsi és eltökélt seregednek sikerül " "leküzdeni a csábítást a halált hozó mélységek felé." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Félelmetes jajveszékelÅ‘ hang tör elÅ‘ a sziklákon tanyázó szirénekbÅ‘l. Több " "embered is elcsábul a bűbájuktól és a vízbe ugorva, belefulladnak. Bölcsebb " "lettél és tanultál az esetbÅ‘l, így ennyi tapasztalatra teszel szert: %{exp}." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Egy ragyogó és merész húzással betörsz a fogdába és kiszabadítod az ott " "bebörtönzött hÅ‘st, aki hálából hűséget esküszik neked és ügyednek." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Már %{count} hÅ‘söd van, így sajnos itt kell hagyd a foglyot a börtönében, " "aki még beláthatatlan ideig tovább fog sínylÅ‘dni." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Belépsz egy rozoga kunyhóba és beszédbe elegyedsz az itt lakó varázslóval. " "Elárul neked helyeket közel s távol, melyek segítségedre lesznek utadon." msgid "This eye seems to be intently studying its surroundings." msgstr "Úgy tűnik, ez a szem erÅ‘sen fürkészi a környéket." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Egy hatalmas Szfinxhez érkezel. A Szfinx furcsán suttogva megszólít." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Van számodra egy rejtvényem.\" - mondja. \"Ha jó a válaszod, " "megjutalmazlak. Ha rossz a válaszod, felfallak. Elfogadod a kihívást?\"" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "A Szfinx a következÅ‘ találós kérdést teszi fel:\n" "\n" "'" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" "'\n" "\n" "Mit válaszolsz?" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Rossz a válaszod.\" - mondja gúnyosan a Szfinx. Rádcsap egy hatalmasat a " "mancsával, és ledönt a földre. A következÅ‘ ütésre elsötétül elÅ‘tted a világ, " "többre nem emlékszel." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "A Szfinx kissé csalódottan felsóhajt. \"Jó a válaszod, itt van a jutalmad. " "Most menj!\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Egy mágikus útakadály állja utadat. A kapuív rúnái ezt üzenik:\n" "\"Mondd ki a varázsigét, hogy átmehess.\"\n" "Ahogy kimondtad a varázsigét, a sugárzó útakadály semmivé foszlik elÅ‘tted." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Egy mágikus útakadály állja utadat. A kapuív rúnái ezt üzenik:\n" "\"Mondd ki a varázsigét, hogy átmehess.\"\n" "A próbálkozásod hatástalan, nem történik semmi." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Belépsz a sátorba és meglátsz egy öregasszonyt, amint egy mágikus drágakövet " "bámul. Felnéz és azt mondja: \"Utazásaim során sokat megtanultam a titkos " "mágia módozatairól. Egy nagy orákulum tanított engem. Tudom a választ arra, " "amit keresel.\"" msgid "No spell book is present." msgstr "Nincs varázskönyved." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "A varázslat %{mana} varázslatpontot emészt fel, de neked nincs már " "varázslatpontod, ezért nem használhatod most." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "A varázslat %{mana} varázslatpontot emészt fel, de neked csak %{point} " "varázslatpontod van, ezért nem használhatod most." msgid "The spell was not found." msgstr "A varázslat nem található." msgid "Only heroes can cast this spell." msgstr "Csak hÅ‘sök idézhetik meg ezt a varázslatot." msgid "This hero is not able to cast adventure spells." msgstr "A hÅ‘s nem képes kaland varázslatok megidézésére." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "HÅ‘söd ma már túl fáradt ehhez a varázslathoz. Próbáld újra holnap." msgid "This spell cannot be cast on a boat." msgstr "A varázslat nem használható hajón." msgid "This spell can only be cast near an ocean." msgstr "A varázslat csak tengerparton használható." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Nincs elérhetÅ‘ hajó, illetve nincs szabad tengerpart a hÅ‘s közelében. Ãgy " "nem használható a varázslat." msgid "There are no boats available for this spell." msgstr "Nincs elérhetÅ‘ hajó a varázslathoz." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Nincs szabad tengerpart a hÅ‘s közelében, így nem használható a varázslat." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Jelenleg nincs olyan saját várad vagy városod, melyet ne foglalna el egy " "hÅ‘söd. Ãgy ez a varázslat hatástalan." msgid "This hero is already in a town, so this spell will have no effect." msgstr "A hÅ‘s már városban áll, így a varázslat most nem használható." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "A legközelebbi város %{town}.\n" "\n" "A várost %{hero} foglalja el." msgid "This spell is already in effect." msgstr "A varázslat már hat." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Egyik ellenfeled parancsnoksága alá sem tartozik/tartozhat hÅ‘s többé. A " "varázslat így hatástalan." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Jelenleg egyik ellenfeled parancsnoksága alá sem tartozik hÅ‘s. A varázslat " "így hatástalan." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "A vízió varázslat működéséhez %{count} lépésen belül kell legyél a lénytÅ‘l." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "A bánya bejáratánál kell állnod (a fűrészmalmot és az alkimista labort " "leszámítva), hogy használd ezt a varázslatot." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "ElÅ‘bb le kell gyÅ‘znöd a bányát Å‘rzÅ‘ szellemeket, mielÅ‘tt ezt a varázslatot " "használnád." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Már jelenleg is annyi elementál Å‘rzi a bányát, amennyit ez a hÅ‘s meg tud " "idézni. A varázslat megidézése hatástalan." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name} a %{race} (%{level}. szint)" msgid "Random hero (Level %{level})" msgstr "Véletlenszerű hÅ‘s (%{level}. szint)" msgid "Random %{race} hero (Level %{level})" msgstr "Véletlenszerű %{race} hÅ‘s (%{level}. szint)" msgid "Hero race:" msgstr "HÅ‘s osztály:" msgid "Are you sure you want to dismiss this Hero?" msgstr "Biztos, hogy elbocsátod ezt a hÅ‘st?" msgid "Set custom Experience value. Current value is default." msgstr "" "Egyéni tapasztalati érték beállítása. A jelenlegi érték az alapbeállítás." msgid "Change Experience value. Right-click to reset to default value." msgstr "" "Tapasztalati érték megváltoztatása. Jobb kattintásra alapértékre áll be." msgid "View Experience Info" msgstr "Tapasztalat információ" msgid "Set custom Spell Points value. Current value is default." msgstr "" "Egyedi varázspont érték beállítása. A jelenlegi érték az alapbeállítás." msgid "Change Spell Points value. Right-click to reset to default value." msgstr "Varázspont érték megváltoztatása. Jobb kattintásra alapértékre áll be." msgid "Set Spell Points value" msgstr "Varázspont érték beállítása" msgid "View Spell Points Info" msgstr "Varázspont információ" msgid "Set patrol radius in tiles" msgstr "JárÅ‘rözési sugár beállítása" msgid "Enter hero's name" msgstr "HÅ‘s nevének megadása" msgid "Click to change race." msgstr "Kattints az osztály megváltoztatásához." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Laza' csataalakzatban a hÅ‘s egységei szétszóródva helyezkednek el a " "harcmezÅ‘n fentrÅ‘l lefelé, úgy, hogy legalább 1 üres hely marad közöttük." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "'Szoros' csataalakzatban a hÅ‘s egységei szorosan egymás mellett helyezkednek " "el a harcmezÅ‘ általuk elfoglalt oldalának közepén." msgid "Exit Hero Screen" msgstr "Kilépés a hÅ‘s képernyÅ‘bÅ‘l" msgid "You cannot dismiss a hero in a castle" msgstr "Várban nem lehet hÅ‘st elbocsátani" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "%{name} a %{race} elbocsátása tiltott ebben a küldetésben" msgid "Dismiss %{name} the %{race}" msgstr "%{name} a %{race} elbocsátása" msgid "Show previous hero" msgstr "ElÅ‘zÅ‘ hÅ‘s mutatása" msgid "Show next hero" msgstr "KövetkezÅ‘ hÅ‘s mutatása" msgid "Set army combat formation to 'Spread'" msgstr "A csataalakzat legyen 'Laza'." msgid "Set army combat formation to 'Grouped'" msgstr "A csataalakzat legyen 'Szoros'." msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" "A hÅ‘s varázstárgyainak beállítása. Jobb kattintásra a varázstárgyak " "alaphelyzetbe állnak." msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" "A hÅ‘s másodlagos képességeinek beállítása. Jobb kattintásra a képességek " "alaphelyzetbe állnak." msgid "Set hero's Army. Right-click to reset unit." msgstr "" "A hÅ‘s seregének beállítása. Jobb kattintásra az egységek alaphelyzetbe " "állnak." msgid "Set hero's portrait. Right-click to reset to default." msgstr "A hÅ‘s arcképének beállítása. Jobb kattintásra alaphelyzetbe áll." msgid "Click to change hero's name. Right-click to reset to default." msgstr "" "Kattints a hÅ‘s nevének megváltoztatásához. Jobb kattintásra alaphelyzetbe " "áll." msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" "A hÅ‘s %{tiles} egység sugarú körben járÅ‘rözik. Kattints a mód " "kikapcsolásához." msgid "Click to enable hero's patrol mode." msgstr "Kattints a hÅ‘sök járÅ‘rözési módjának bekapcsolásához." msgid "Blood Morale" msgstr "Szenvedélyes morál" msgid "%{morale} Morale" msgstr "%{morale} morál" msgid "%{luck} Luck" msgstr "%{luck} szerencse" msgid "Current Luck Modifiers:" msgstr "Ható szerencse módosítók:" msgid "Current Morale Modifiers:" msgstr "Ható morál módosítók:" msgid "Entire army is undead, so morale does not apply." msgstr "A csapat minden tagja élÅ‘halott, így a morál nem hat rájuk." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Jelenlegi tapasztalati pont: %{exp1}\n" " KövetkezÅ‘ szint: %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "%{level} szint" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} jelenleg %{point} varázsponttal bír a lehetséges %{max} maximumból. " "A varázspontok maximális száma a hÅ‘s tudása értékének 10-szerese. Különleges " "esetben a hÅ‘snek maximum feletti varázspontja is lehet." msgid "%{name1} meets %{name2}" msgstr "%{name1} és %{name2} találkozik" msgid "Enemy heroes are now fully identifiable." msgstr "Az ellenséges hÅ‘sök teljes mértékben azonosíthatóak." msgid "Identify Hero" msgstr "HÅ‘sazonosítás" msgid "Select town to port to." msgstr "Válaszd ki, melyik városba szeretnél menni." msgid "Town Portal" msgstr "Városba lépés" msgid "The creatures are willing to join us!" msgstr "A lények csatlakozni akarnak hozzád!" msgid "All the creatures will join us..." msgstr "Minden lény csatlakozni fog hozzád..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "A lény csatlakozni fog hozzád..." msgstr[1] "%{count} lény csatlakozni fog hozzád..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "%{gold} arany fizetségért." msgid "These weak creatures will surely flee before us." msgstr "Ezek a gyenge lények valószínű elmenekül elÅ‘led." msgid "I fear these creatures are in the mood for a fight." msgstr "FélÅ‘, hogy ezek a lények készek harcolni." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "A hÅ‘s támadóerejének értéke bónuszként hozzáadódik mindegyik egység " "támadóerejéhez." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "A hÅ‘s védÅ‘erejének értéke bónuszként hozzáadódik mindegyik egység " "védÅ‘erejéhez." msgid "The hero's spell power determines the duration or power of a spell." msgstr "A hÅ‘s varázsereje meghatározza a varázslat hatóidejét." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "A hÅ‘s tudása határozza meg, hogy hány varázspontja lehet. Ãltalában a hÅ‘s " "tudásszintenként 10 varázspontot kaphat." msgid "Current Modifiers:" msgstr "Ható módosítók:" msgid "skill|Basic" msgstr "Alap" msgid "skill|Advanced" msgstr "Haladó" msgid "skill|Expert" msgstr "SzakértÅ‘" msgid "Pathfinding" msgstr "Nyomkövetés" msgid "Archery" msgstr "Ãjászat" msgid "Logistics" msgstr "Logisztika" msgid "Scouting" msgstr "Cserkészet" msgid "Diplomacy" msgstr "Diplomácia" msgid "Navigation" msgstr "Navigáció" msgid "Leadership" msgstr "Vezetés" msgid "Wisdom" msgstr "Bölcsesség" msgid "Mysticism" msgstr "Misztika" msgid "Ballistics" msgstr "Ballisztika" msgid "Eagle Eye" msgstr "Sasszem" msgid "Necromancy" msgstr "Nekromancia" msgid "Estates" msgstr "Vagyon" msgid "Advanced Archery" msgstr "Haladó íjászat" msgid "Advanced Pathfinding" msgstr "Haladó nyomkövetés" msgid "Basic Archery" msgstr "Alap íjászat" msgid "Basic Pathfinding" msgstr "Alap nyomkövetés" msgid "Expert Pathfinding" msgstr "SzakértÅ‘ nyomkövetés" msgid "Advanced Logistics" msgstr "Haladó logisztika" msgid "Basic Logistics" msgstr "Alap logisztika" msgid "Basic Scouting" msgstr "Alap cserkészet" msgid "Expert Archery" msgstr "SzakértÅ‘ íjászat" msgid "Expert Logistics" msgstr "SzakértÅ‘ logisztika" msgid "Advanced Diplomacy" msgstr "Haladó diplomácia" msgid "Advanced Scouting" msgstr "Haladó cserkészet" msgid "Basic Diplomacy" msgstr "Alap diplomácia" msgid "Expert Diplomacy" msgstr "SzakértÅ‘ diplomácia" msgid "Expert Scouting" msgstr "SzakértÅ‘ cserkészet" msgid "Advanced Leadership" msgstr "Haladó vezetés" msgid "Advanced Navigation" msgstr "Haladó navigáció" msgid "Basic Leadership" msgstr "Alap vezetés" msgid "Basic Navigation" msgstr "Alap navigáció" msgid "Expert Navigation" msgstr "SzakértÅ‘ navigáció" msgid "Advanced Wisdom" msgstr "Haladó bölcsesség" msgid "Basic Mysticism" msgstr "Alap misztika" msgid "Basic Wisdom" msgstr "Alap bölcsesség" msgid "Expert Leadership" msgstr "SzakértÅ‘ vezetés" msgid "Expert Wisdom" msgstr "SzakértÅ‘ bölcsesség" msgid "Advanced Luck" msgstr "Haladó szerencse" msgid "Advanced Mysticism" msgstr "Haladó misztika" msgid "Basic Luck" msgstr "Alap szerencse" msgid "Expert Luck" msgstr "SzakértÅ‘ szerencse" msgid "Expert Mysticism" msgstr "SzakértÅ‘ misztika" msgid "Advanced Ballistics" msgstr "Haladó ballisztika" msgid "Advanced Eagle Eye" msgstr "Haladó sasszem" msgid "Basic Ballistics" msgstr "Alap ballisztika" msgid "Basic Eagle Eye" msgstr "Alap sasszem" msgid "Expert Ballistics" msgstr "SzakértÅ‘ ballisztika" msgid "Advanced Necromancy" msgstr "Haladó nekromancia" msgid "Basic Estates" msgstr "Alap vagyon" msgid "Basic Necromancy" msgstr "Alap nekromancia" msgid "Expert Eagle Eye" msgstr "SzakértÅ‘ sasszem" msgid "Expert Necromancy" msgstr "SzakértÅ‘ nekromancia" msgid "Advanced Estates" msgstr "Haladó vagyon" msgid "Expert Estates" msgstr "SzakértÅ‘ vagyon" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} csökkenti a nehéz terepen történÅ‘ haladásból fakadó hátrányt " "%{count} százalékkal." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} kiiktatja a nehéz terepen történÅ‘ haladásból fakadó hátrányt." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} megnöveli a hÅ‘s távolra lövÅ‘ egységeinek sebzését %{count} " "százalékkal és eltörli %{penalty} százalékos büntetést akadályokon (pl. " "várfalak) keresztül történÅ‘ lövések esetén." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} növeli a hÅ‘söd mozgáspontjait %{count} százalékkal." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} növeli a hÅ‘s látóhatárát egy egységgel." msgstr[1] "%{skill} növeli a hÅ‘s látóhatárát %{count} egységgel." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "A(z) %{skill} lehetÅ‘vé teszi a hÅ‘s seregénél gyengébb lényekkel való " "tárgyalást." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "A lények kb. %{count} százaléka csatlakozhat a hÅ‘s seregéhez." msgid "All of the creatures may offer to join the hero." msgstr "Az összes lény csatlakozhat a hÅ‘s seregéhez." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "A megadás költsége csökken a sereg egységeinek összköltsége %{percent} " "százalékára." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "%{skill} növeli a hÅ‘s vízen történÅ‘ mozgáspontjait %{count} százalékkal." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} ennyivel növeli a hÅ‘s seregének morálját: %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} képessé teszi a hÅ‘st 3. szintű varázslatok megtanulására." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} képessé teszi a hÅ‘st 4. szintű varázslatok megtanulására." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} képessé teszi a hÅ‘st 5. szintű varázslatok megtanulására." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" "%{skill} naponta eggyel növeli a hÅ‘s varázspontjainak újratermelÅ‘dését." msgstr[1] "" "%{skill} naponta %{count}-vel növeli a hÅ‘s varázspontjainak újratermelÅ‘dését." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} ennyivel növeli a hÅ‘s szerencséjét: %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} nagyobb esélyt ad a hÅ‘s katapultjának a találatra és a várfal " "rombolására." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} egy plusz lövést és nagyobb esélyt ad a hÅ‘s katapultjának a " "találatra és a várfal rombolására." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} egy plusz lövést ad a hÅ‘s katapultjának. Minden lövés automatikusan " "rombolja a falat, kivéve a Lovagvár sánccal megerÅ‘sített várát." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} %{count} százaléknyi esélyt ad a hÅ‘snek, hogy az ellenfél által a " "csatában használt 1-es vagy 2-es szintű varázslatot tanuljon el." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} %{count} százaléknyi esélyt ad a hÅ‘snek, hogy az ellenfél által a " "csatában használt 3-as (vagy alacsonyabb) szintű varázslatot tanuljon el." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} %{count} százaléknyi esélyt ad a hÅ‘snek, hogy az ellenfél által a " "csatában használt 4-es (vagy alacsonyabb) szintű varázslatot tanuljon el." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} segítségével a csatában megölt lények %{count} százalékából " "Csontvázakat idézhetünk meg." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "A hÅ‘s napi %{count} arany adóbevételt kap birtokai után." msgid "Blue" msgstr "Kék" msgid "Green" msgstr "Zöld" msgid "Red" msgstr "Vörös" msgid "Yellow" msgstr "Sárga" msgid "Orange" msgstr "Narancs" msgid "Purple" msgstr "Lila" msgid "barrier|Aqua" msgstr "Tengerkék" msgid "barrier|Blue" msgstr "Kék" msgid "barrier|Brown" msgstr "Barna" msgid "barrier|Gold" msgstr "Arany" msgid "barrier|Green" msgstr "Zöld" msgid "barrier|Orange" msgstr "Narancs" msgid "barrier|Purple" msgstr "Lila" msgid "barrier|Red" msgstr "Vörös" msgid "tent|Aqua" msgstr "Tengerkék" msgid "tent|Blue" msgstr "Kék" msgid "tent|Brown" msgstr "Barna" msgid "tent|Gold" msgstr "Arany" msgid "tent|Green" msgstr "Zöld" msgid "tent|Orange" msgstr "Narancs" msgid "tent|Purple" msgstr "Lila" msgid "tent|Red" msgstr "Vörös" msgid "Experience" msgstr "Tapasztalat" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "A tapasztalat lehetÅ‘vé teszi, hogy a hÅ‘sök elsÅ‘dleges és másodlagos " "képességei fejlÅ‘djenek, illetve szintet lépjenek." msgid "Hero/Stats" msgstr "HÅ‘s statisztikái" msgid "Skills" msgstr "Képességek" msgid "Town/Castle" msgstr "Város/Vár" msgid "Garrison" msgstr "HelyÅ‘rség" msgid "Gold Per Day:" msgstr "Arany naponta:" msgid "View Heroes." msgstr "HÅ‘sök mutatása." msgid "Towns/Castles" msgstr "Városok/Várak" msgid "View Towns and Castles." msgstr "Városok/Várak mutatása." msgid "luck|Cursed" msgstr "Ãtkozott" msgid "luck|Awful" msgstr "Szörnyű" msgid "luck|Bad" msgstr "Rossz" msgid "luck|Normal" msgstr "Normál" msgid "luck|Good" msgstr "Jó" msgid "luck|Great" msgstr "Nagyszerű" msgid "luck|Irish" msgstr "Páratlan" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "A Rossz szerencse következtében a csatában a hÅ‘s egységeinek sebzése " "alkalmanként a felére csökken." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "A Semleges szerencse azt jelenti, hogy a csata során se szerencse se " "balszerencse nem éri az egységeid támadását." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Jó szerencse esetén a hÅ‘s egységeinek alkalmanként esélye van szerencsés " "(dupla erÅ‘sségű) támadásra a csata során." msgid "morale|Treason" msgstr "Felségárulás" msgid "morale|Awful" msgstr "Szörnyű" msgid "morale|Poor" msgstr "Rossz" msgid "morale|Normal" msgstr "Normál" msgid "morale|Good" msgstr "Jó" msgid "morale|Great" msgstr "Nagyszerű" msgid "morale|Blood!" msgstr "ÖrjöngÅ‘!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Rossz morál a hÅ‘s egységeinek ledermedését eredményezheti a csatában." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Semleges morál azt jelenti, hogy a hÅ‘s egységei nem kapnak lehetÅ‘séget extra " "támadásra, de nem is maradnak ki." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "Jó morál esetén a hÅ‘s egységei extra támadási lehetÅ‘séget kaphatnak a " "csatában." msgid "Knight" msgstr "Lovag" msgid "Barbarian" msgstr "Barbár" msgid "Sorceress" msgstr "VarázslónÅ‘" msgid "Warlock" msgstr "Boszorkánymester" msgid "Wizard" msgstr "Varázsló" msgid "Necromancer" msgstr "Nekromanta" msgid "Multi" msgstr "Többféle" msgid "doubleLined|Knight" msgstr "Lovag" msgid "doubleLined|Barbarian" msgstr "Barbár" msgid "doubleLined|Sorceress" msgstr "" "Varázsló-\n" "nÅ‘" msgid "doubleLined|Warlock" msgstr "" "Boszor-\n" "kánymester" msgid "doubleLined|Wizard" msgstr "Varázsló" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Nekro-\n" "manta" msgid "doubleLinedRace|Multi" msgstr "" "Több-\n" "féle" msgid "doubleLinedRace|Random" msgstr "Véletlen" msgid "speed|Standing" msgstr "Ãlló" msgid "speed|Crawling" msgstr "Vánszorgó" msgid "speed|Very Slow" msgstr "Csigalassú" msgid "speed|Slow" msgstr "Lassú" msgid "speed|Average" msgstr "Ãtlagos" msgid "speed|Fast" msgstr "Sebes" msgid "speed|Very Fast" msgstr "Szélsebes" msgid "speed|Ultra Fast" msgstr "Nyílsebes" msgid "speed|Blazing" msgstr "Villámgyors" msgid "speed|Instant" msgstr "Itt terem" msgid "Click this button to adjust the level of zoom." msgstr "Nyomd meg ezt a gombot a nagyítás mértékének beállításához." msgid "Zoom" msgstr "Nagyítás" msgid "week|Squirrel" msgstr "Mókus" msgid "week|Rabbit" msgstr "Nyúl" msgid "week|Gopher" msgstr "Hörcsög" msgid "week|Badger" msgstr "Borz" msgid "week|Rat" msgstr "Patkány" msgid "week|Eagle" msgstr "Sas" msgid "week|Weasel" msgstr "Menyét" msgid "week|Raven" msgstr "Holló" msgid "week|Mongoose" msgstr "Mongúz" msgid "week|Dog" msgstr "Kutya" msgid "week|Aardvark" msgstr "Földimalac" msgid "week|Lizard" msgstr "Gyík" msgid "week|Tortoise" msgstr "TeknÅ‘sbéka" msgid "week|Hedgehog" msgstr "Sün" msgid "week|Condor" msgstr "Kondorkeselyű" msgid "week|Ant" msgstr "Hangya" msgid "week|Grasshopper" msgstr "Szöcske" msgid "week|Dragonfly" msgstr "SzitakötÅ‘" msgid "week|Spider" msgstr "Pók" msgid "week|Butterfly" msgstr "Pillangó" msgid "week|Bumblebee" msgstr "Darázs" msgid "week|Locust" msgstr "Sáska" msgid "week|Earthworm" msgstr "Földigiliszta" msgid "week|Hornet" msgstr "Lódarázs" msgid "week|Beetle" msgstr "Bogár" msgid "week|PLAGUE" msgstr "PESTIS" msgid "week|Unnamed" msgstr "Névtelen" msgid "Desert" msgstr "Sivatag" msgid "Snow" msgstr "Hó" msgid "Wasteland" msgstr "Pusztaság" msgid "Beach" msgstr "Part" msgid "Lava" msgstr "Láva" msgid "Dirt" msgstr "Sár" msgid "Grass" msgstr "Fű" msgid "Ocean" msgstr "Óceán" msgid "maps|Small" msgstr "Kicsi" msgid "maps|Medium" msgstr "Közepes" msgid "maps|Large" msgstr "Nagy" msgid "maps|Extra Large" msgstr "Nagyon nagy" msgid "maps|Custom Size" msgstr "Egyedi" msgid "Ore Mine" msgstr "Ércbánya" msgid "Sulfur Mine" msgstr "Kénbánya" msgid "Crystal Mine" msgstr "Kristálybánya" msgid "Gems Mine" msgstr "DrágakÅ‘bánya" msgid "Gold Mine" msgstr "Aranybánya" msgid "Mine" msgstr "Bánya" msgid "Burma shave." msgstr "HirdetÅ‘tábla." msgid "Next sign 50 miles." msgstr "KövetkezÅ‘ jelzés 50 mérföldre." msgid "See Rock City." msgstr "Nézd KÅ‘várost." msgid "This space for rent." msgstr "Ez a hely kiadó." msgid "No object" msgstr "Nincs tárgy" msgid "Alchemist Lab" msgstr "Alkímista labor" msgid "Sign" msgstr "Jel" msgid "Buoy" msgstr "Bója" msgid "Skeleton" msgstr "Csontváz" msgid "Daemon Cave" msgstr "Démonbarlang" msgid "Treasure Chest" msgstr "Kincsesláda" msgid "Faerie Ring" msgstr "Tündérgyűrű" msgid "Campfire" msgstr "Tábortűz" msgid "Fountain" msgstr "SzökÅ‘kút" msgid "Gazebo" msgstr "Kilátó" msgid "Genie Lamp" msgstr "Lámpás" msgid "Archer's House" msgstr "Ãjász Ház" msgid "Goblin Hut" msgstr "Goblinkunyhó" msgid "Dwarf Cottage" msgstr "Törp tanya" msgid "Peasant Hut" msgstr "Tanya" msgid "Stables" msgstr "Istálló" msgid "Alchemist's Tower" msgstr "Alkímista torony" msgid "Event" msgstr "Esemény" msgid "Dragon City" msgstr "Sárkányváros" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Világítótorony" msgstr[1] "Világítótornyok" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Vízimalom" msgstr[1] "Vízimalmok" msgid "Monster" msgstr "Lény" msgid "Obelisk" msgstr "Obeliszk" msgid "Oasis" msgstr "Oázis" msgid "Resource" msgstr "ErÅ‘forrás" msgid "Sawmill" msgstr "Fűrészmalom" msgid "Oracle" msgstr "Orákulum" msgid "Shrine of the First Circle" msgstr "Az ElsÅ‘ Kör szentélye" msgid "Shipwreck" msgstr "Hajóroncs" msgid "Sea Chest" msgstr "Tengeri kincs" msgid "Desert Tent" msgstr "Sivatagi sátor" msgid "Stone Liths" msgstr "Ãtjáró" msgid "Wagon Camp" msgstr "Szekértábor" msgid "Hut of the Magi" msgstr "Máguskunyhó" msgid "Whirlpool" msgstr "Örvény" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Szélmalom" msgstr[1] "Szélmalmok" msgid "Mermaid" msgstr "SellÅ‘" msgid "Boat" msgstr "Hajó" msgid "Random Ultimate Artifact" msgstr "Véletlenszerű Szent Varázstárgy" msgid "Random Artifact" msgstr "Véletlenszerű varázstárgy" msgid "Random Resource" msgstr "Véletlenszerű erÅ‘forrás" msgid "Random Monster" msgstr "Véletlenszerű lény" msgid "Random Town" msgstr "Véletlenszerű város" msgid "Random Castle" msgstr "Véletlenszerű vár" msgid "Eye of the Magi" msgstr "Mágus szeme" msgid "Random Monster - weak" msgstr "Véletlenszerű lény - gyenge" msgid "Random Monster - medium" msgstr "Véletlenszerű lény - közepes" msgid "Random Monster - strong" msgstr "Véletlenszerű lény - erÅ‘s" msgid "Random Monster - very strong" msgstr "Véletlenszerű lény - nagyon erÅ‘s" msgid "Hero" msgstr "HÅ‘s" msgid "Nothing Special" msgstr "Semmi érdekes" msgid "Mossy Rock" msgstr "Mohás kÅ‘" msgid "Watch Tower" msgstr "Toronyóra" msgid "Tree House" msgstr "Faház" msgid "Tree City" msgstr "Fa város" msgid "Ruins" msgstr "Romok" msgid "Fort" msgstr "ErÅ‘d" msgid "Abandoned Mine" msgstr "Elhagyott bánya" msgid "Sirens" msgstr "Szirének" msgid "Standing Stones" msgstr "Ãllókövek" msgid "Idol" msgstr "Bálvány" msgid "Tree of Knowledge" msgstr "A Tudás fája" msgid "Witch Doctor's Hut" msgstr "Vajákoskunyhó" msgid "Temple" msgstr "Templom" msgid "Hill Fort" msgstr "ErÅ‘d" msgid "Halfling Hole" msgstr "Félszerzet odú" msgid "Mercenary Camp" msgstr "Zsoldostábor" msgid "Shrine of the Second Circle" msgstr "A Második Kör szentélye" msgid "Shrine of the Third Circle" msgstr "A Harmadik Kör szentélye" msgid "City of the Dead" msgstr "Holtak városa" msgid "Sphinx" msgstr "Szfinx" msgid "Wagon" msgstr "Szekér" msgid "Tar Pit" msgstr "Kátrányosgödör" msgid "Artesian Spring" msgstr "Artéziforrás" msgid "Troll Bridge" msgstr "Trollhíd" msgid "Watering Hole" msgstr "Itató" msgid "Witch's Hut" msgstr "Boszorkánykunyhó" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Viskó" msgid "Magellan's Maps" msgstr "Magellán térképe" msgid "Flotsam" msgstr "Uszadék" msgid "Derelict Ship" msgstr "Gazdátlan hajó" msgid "Shipwreck Survivor" msgstr "Hajótörött" msgid "Bottle" msgstr "Palack" msgid "Magic Well" msgstr "Varázskút" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Varázskert" msgstr[1] "Varázskertek" msgid "Observation Tower" msgstr "Kilátótorony" msgid "Freeman's Foundry" msgstr "ÖntÅ‘de" msgid "Reefs" msgstr "Zátonyok" msgid "Volcano" msgstr "Vulkán" msgid "Flowers" msgstr "Virágok" msgid "Rock" msgstr "KÅ‘" msgid "Water Lake" msgstr "Tó" msgid "Mandrake" msgstr "Mandragóra" msgid "Dead Tree" msgstr "Kiszáradt fa" msgid "Stump" msgstr "Tuskó" msgid "Crater" msgstr "Kráter" msgid "Cactus" msgstr "Kaktusz" msgid "Mound" msgstr "Bucka" msgid "Dune" msgstr "Dűne" msgid "Lava Pool" msgstr "Lávató" msgid "Shrub" msgstr "Bozót" msgid "Barrow Mounds" msgstr "Halomsírok" msgid "Random Artifact - Treasure" msgstr "Véletlen tárgy - kincs" msgid "Random Artifact - Minor" msgstr "Véletlen tárgy - kisebb" msgid "Random Artifact - Major" msgstr "Véletlen tárgy - nagyobb" msgid "Barrier" msgstr "Mágikus útakadály" msgid "Traveller's Tent" msgstr "Utazók sátra" msgid "Jail" msgstr "Börtön" msgid "Fire Summoning Altar" msgstr "TűzidézÅ‘ oltár" msgid "Air Summoning Altar" msgstr "LégidézÅ‘ oltár" msgid "Earth Summoning Altar" msgstr "FöldidézÅ‘ oltár" msgid "Water Summoning Altar" msgstr "VízidézÅ‘ oltár" msgid "Swampy Lake" msgstr "Mocsaras tó" msgid "Frozen Lake" msgstr "Befagyott tó" msgid "randomRace|level 1 creatures" msgstr "1. szintű lények" msgid "randomRace|level 2 creatures" msgstr "2. szintű lények" msgid "randomRace|level 3 creatures" msgstr "3. szintű lények" msgid "randomRace|level 4 creatures" msgstr "4. szintű lények" msgid "randomRace|level 5 creatures" msgstr "5. szintű lények" msgid "randomRace|level 6 creatures" msgstr "6. szintű lények" msgid "Unknown Monsters" msgstr "Ismeretlen lények" msgid "Unknown Monster" msgstr "Ismeretlen lény" msgid "Peasant" msgstr "Jobbágy" msgid "Peasants" msgstr "Jobbágyok" msgid "Archer" msgstr "Ãjász" msgid "Archers" msgstr "Ãjászok" msgid "Ranger" msgstr "ErdÅ‘kerülÅ‘" msgid "Rangers" msgstr "ErdÅ‘kerülÅ‘k" msgid "Pikeman" msgstr "Lándzsás" msgid "Pikemen" msgstr "Lándzsások" msgid "Veteran Pikeman" msgstr "Veterán lándzsás" msgid "Veteran Pikemen" msgstr "Veterán lándzsások" msgid "Swordsman" msgstr "Kardforgató" msgid "Swordsmen" msgstr "Kardforgatók" msgid "Master Swordsman" msgstr "Kardforgató mester" msgid "Master Swordsmen" msgstr "Kardforgató mesterek" msgid "Cavalries" msgstr "Lovasok" msgid "Cavalry" msgstr "Lovas" msgid "Champion" msgstr "Bajnok" msgid "Champions" msgstr "Bajnokok" msgid "Paladin" msgstr "Lovag" msgid "Paladins" msgstr "Lovagok" msgid "Crusader" msgstr "Kereszteslovag" msgid "Crusaders" msgstr "Kereszteslovagok" msgid "Goblin" msgstr "Goblin" msgid "Goblins" msgstr "Goblinok" msgid "Orc" msgstr "Ork" msgid "Orcs" msgstr "Orkok" msgid "Orc Chief" msgstr "Ork vezér" msgid "Orc Chiefs" msgstr "Ork vezérek" msgid "Wolf" msgstr "Farkas" msgid "Wolves" msgstr "Farkas" msgid "Ogre" msgstr "Ogre" msgid "Ogres" msgstr "Ogrék" msgid "Ogre Lord" msgstr "Ogre nagyúr" msgid "Ogre Lords" msgstr "Ogre nagyurak" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Trollok" msgid "War Troll" msgstr "Harci troll" msgid "War Trolls" msgstr "Harci trollok" msgid "Cyclopes" msgstr "Küklopszok" msgid "Cyclops" msgstr "Küklopsz" msgid "Sprite" msgstr "Tündér" msgid "Sprites" msgstr "Tündérek" msgid "Dwarf" msgstr "Törp" msgid "Dwarves" msgstr "Törpök" msgid "Battle Dwarf" msgstr "Törp harcos" msgid "Battle Dwarves" msgstr "Törp harcosok" msgid "Elf" msgstr "Tünde" msgid "Elves" msgstr "Tündék" msgid "Grand Elf" msgstr "Tünde úr" msgid "Grand Elves" msgstr "Tünde urak" msgid "Druid" msgstr "Druida" msgid "Druids" msgstr "Druidák" msgid "Greater Druid" msgstr "Nemes druida" msgid "Greater Druids" msgstr "Nemes druidák" msgid "Unicorn" msgstr "Egyszarvú" msgid "Unicorns" msgstr "Egyszarvúak" msgid "Phoenix" msgstr "FÅ‘nix" msgid "Phoenixes" msgstr "FÅ‘nixek" msgid "Centaur" msgstr "Kentaur" msgid "Centaurs" msgstr "Kentaurok" msgid "Gargoyle" msgstr "VízköpÅ‘" msgid "Gargoyles" msgstr "VízköpÅ‘k" msgid "Griffin" msgstr "Griff" msgid "Griffins" msgstr "Griffek" msgid "Minotaur" msgstr "Minotaurusz" msgid "Minotaurs" msgstr "Minotauruszok" msgid "Minotaur King" msgstr "Királyi minotaurusz" msgid "Minotaur Kings" msgstr "Királyi minotauruszok" msgid "Hydra" msgstr "Hidra" msgid "Hydras" msgstr "Hidrák" msgid "Green Dragon" msgstr "Zöld sárkány" msgid "Green Dragons" msgstr "Zöld sárkányok" msgid "Red Dragon" msgstr "Vörös sárkány" msgid "Red Dragons" msgstr "Vörös sárkányok" msgid "Black Dragon" msgstr "Fekete sárkány" msgid "Black Dragons" msgstr "Fekete sárkányok" msgid "Halfling" msgstr "Félszerzet" msgid "Halflings" msgstr "Félszerzetek" msgid "Boar" msgstr "Vaddisznó" msgid "Boars" msgstr "Vaddisznók" msgid "Iron Golem" msgstr "Vasgólem" msgid "Iron Golems" msgstr "Vasgólemek" msgid "Steel Golem" msgstr "Acélgólem" msgid "Steel Golems" msgstr "Acélgólemek" msgid "Roc" msgstr "Rukh-madár" msgid "Rocs" msgstr "Rukh-madarak" msgid "Mage" msgstr "Mágus" msgid "Magi" msgstr "Mágusok" msgid "Archmage" msgstr "FÅ‘mágus" msgid "Archmagi" msgstr "FÅ‘mágusok" msgid "Giant" msgstr "Óriás" msgid "Giants" msgstr "Óriások" msgid "Titan" msgstr "Titán" msgid "Titans" msgstr "Titánok" msgid "Skeletons" msgstr "Csontvázak" msgid "Zombie" msgstr "Zombi" msgid "Zombies" msgstr "Zombik" msgid "Mutant Zombie" msgstr "Mutáns zombi" msgid "Mutant Zombies" msgstr "Mutáns zombik" msgid "Mummies" msgstr "Múmiák" msgid "Mummy" msgstr "Múmia" msgid "Royal Mummies" msgstr "Királyi múmiák" msgid "Royal Mummy" msgstr "Királyi múmia" msgid "Vampire" msgstr "Vámpír" msgid "Vampires" msgstr "Vámpírok" msgid "Vampire Lord" msgstr "Vámpír nagyúr" msgid "Vampire Lords" msgstr "Vámpír nagyurak" msgid "Lich" msgstr "Lich" msgid "Liches" msgstr "Lichek" msgid "Power Lich" msgstr "Åslich" msgid "Power Liches" msgstr "Åslichek" msgid "Bone Dragon" msgstr "Csontsárkány" msgid "Bone Dragons" msgstr "Csontsárkányok" msgid "Rogue" msgstr "Rabló" msgid "Rogues" msgstr "Rablók" msgid "Nomad" msgstr "Nomád" msgid "Nomads" msgstr "Nomádok" msgid "Ghost" msgstr "Szellem" msgid "Ghosts" msgstr "Szellemek" msgid "Genie" msgstr "Dzsinn" msgid "Genies" msgstr "Dzsinnek" msgid "Medusa" msgstr "Medúza" msgid "Medusas" msgstr "Medúzák" msgid "Earth Elemental" msgstr "Földelementál" msgid "Earth Elementals" msgstr "Földelementálok" msgid "Air Elemental" msgstr "Légelementál" msgid "Air Elementals" msgstr "Légelementálok" msgid "Fire Elemental" msgstr "Tűzelementál" msgid "Fire Elementals" msgstr "Tűzelementálok" msgid "Water Elemental" msgstr "Vízelementál" msgid "Water Elementals" msgstr "Vízelementálok" msgid "Random Monsters" msgstr "Véletlenszerű lények" msgid "Random Monster 1" msgstr "Véletlenszerű lény 1" msgid "Random Monsters 1" msgstr "Véletlenszerű lények 1" msgid "Random Monster 2" msgstr "Véletlenszerű lény 2" msgid "Random Monsters 2" msgstr "Véletlenszerű lények 2" msgid "Random Monster 3" msgstr "Véletlenszerű lény 3" msgid "Random Monsters 3" msgstr "Véletlenszerű lények 3" msgid "Random Monster 4" msgstr "Véletlenszerű lény 4" msgid "Random Monsters 4" msgstr "Véletlenszerű lények 4" msgid "Double shot" msgstr "Dupla lövés" msgid "2-hex monster" msgstr "Két hexás lény" msgid "Double strike" msgstr "Dupla csapás" msgid "Double damage to Undead" msgstr "Dupla sebzés élÅ‘halottakon" msgid "% magic resistance" msgstr "% varázslat ellenállóképesség" msgid "Immune to Mind spells" msgstr "Immunis az elmére ható varázslatokra" msgid "Immune to Elemental spells" msgstr "Immunis az elemi varázslatokra" msgid "Immune to Fire spells" msgstr "Immunis a tűz varázslatokra" msgid "Immune to Cold spells" msgstr "Immunis a fagy varázslatokra" msgid "Immune to " msgstr "Immunis erre: " msgid "% immunity to %{spell} spell" msgstr "% immunitás a(z) %{spell} varázslattól" msgid "% damage from Elemental spells" msgstr "% sebzés elemi varázslatoktól" msgid "% damage from %{spell} spell" msgstr "% sebzés %{spell} varázslattól" msgid "% chance to Dispel beneficial spells" msgstr "% esély jótékony varázslatok eloszlatására" msgid "% chance to Paralyze" msgstr "% esély bénításra" msgid "% chance to Petrify" msgstr "% esély kÅ‘vé dermesztésre" msgid "% chance to Blind" msgstr "% esély vakításra" msgid "% chance to Curse" msgstr "% esély átokra" msgid "% chance to cast %{spell} spell" msgstr "% eséllyel varázsolja a(z) %{spell} varázslatot" msgid "HP regeneration" msgstr "ÉleterÅ‘ visszatöltÅ‘dés" msgid "Two hexes attack" msgstr "Két hexára támad" msgid "Flyer" msgstr "Repül" msgid "Always retaliates" msgstr "Mindig visszatámad" msgid "Attacks all adjacent enemies" msgstr "Minden mellette álló ellenséget támad" msgid "No melee penalty" msgstr "Nincs közelharc hátrány" msgid "Dragon" msgstr "Sárkány" msgid "Undead" msgstr "ÉlÅ‘halott" msgid "No enemy retaliation" msgstr "Nem támad vissza rá az ellenség" msgid "HP drain" msgstr "ÉleterÅ‘t szív" msgid "Cloud attack" msgstr "Gyilkos köd támadás" msgid "Decreases enemy's morale by " msgstr "Csökkenti az ellenfél morálját ennyivel: " msgid "% chance to halve enemy" msgstr "% esély az ellenség megfelezésére" msgid "Soul Eater" msgstr "Lélekfaló" msgid "Elemental" msgstr "Elemi lény" msgid "No Morale" msgstr "Nincs morál" msgid "Earth creature" msgstr "Föld teremtmény" msgid "Air creature" msgstr "LevegÅ‘ teremtmény" msgid "Fire creature" msgstr "Tűz teremtmény" msgid "Water creature" msgstr "Víz teremtmény" msgid "Double damage from Fire spells" msgstr "Dupla sebzés tűzvarázslatoktól" msgid "Double damage from Cold spells" msgstr "Dupla sebzés fagyvarázslatoktól" msgid "Double damage from Earth creatures" msgstr "Dupla sebzés föld teremtményektÅ‘l" msgid "Double damage from Air creatures" msgstr "Dupla sebzés levegÅ‘ teremtményektÅ‘l" msgid "Double damage from Fire creatures" msgstr "Dupla sebzés tűz teremtményektÅ‘l" msgid "Double damage from Water creatures" msgstr "Dupla sebzés víz teremtményektÅ‘l" msgid "Lightning" msgstr "Villámlás" msgid "% immunity to " msgstr "% immunitás ettÅ‘l: " msgid "% damage from " msgstr "% sebzés ettÅ‘l: " msgid "The three Anduran artifacts magically combine into one." msgstr "A három Anduran varázstárgy mágikusan eggyéolvadt." msgid "View Spells" msgstr "Varázslatok mutatása" msgid "View %{name} Info" msgstr "%{name} adatai" msgid "Move %{name}" msgstr "%{name} lép" msgid "Cannot move the Spellbook" msgstr "A varázskönyv nem mozgatható" msgid "This item can't be traded." msgstr "Ezt a tárgyat nem lehet elcserélni." msgid "Invalid Artifact" msgstr "Érvénytelen varázstárgy" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "A %{name} ennyivel növeli a hÅ‘s tudását: %{count}." msgid "Ultimate Book of Knowledge" msgstr "Tudás szent könyve" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "A %{name} ennyivel növeli a hÅ‘s támadóerejét: %{count}." msgid "Ultimate Sword of Dominion" msgstr "Hatalom szent kardja" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "A %{name} ennyivel növeli a hÅ‘s védÅ‘erejét: %{count}." msgid "Ultimate Cloak of Protection" msgstr "Védelem szent köpenye" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "A %{name} megnöveli a hÅ‘s varázserejét ennyivel: %{count}." msgid "Ultimate Wand of Magic" msgstr "Varázslás szent pálcája" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" "A %{name} mind a hÅ‘s támadóerejét, mind a védÅ‘erejét megnöveli ennyivel: " "%{count}." msgid "Ultimate Shield" msgstr "Szent pajzs" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "" "A %{name} mind a hÅ‘s tudását, mind a varázserejét megnöveli ennyivel: " "%{count}." msgid "Ultimate Staff" msgstr "Szent jogar" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "A %{name} a hÅ‘s minden alapképességét növeli ennyivel: %{count}." msgid "Ultimate Crown" msgstr "Szent Korona" msgid "Golden Goose" msgstr "Arany lúd" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "Az %{name} naponta %{count} aranyat hoz a konyhára." msgid "Arcane Necklace of Magic" msgstr "Misztikus varázslás nyaklánc" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Miután megmentetted a varázslónÅ‘t az elátkozott sírboltból, megjutalmaz " "hÅ‘siességedért egy gazdagon ékesített nyaklánccal." msgid "Caster's Bracelet of Magic" msgstr "IdézÅ‘ varázslat karkötÅ‘" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Amint átkutatod a beomlott bánya törmelékét, kiszabadítasz egy csapat " "csapdába esett törpöt. Hálából a vezetÅ‘jük megajándékoz egy arany " "karpereccel." msgid "Mage's Ring of Power" msgstr "MáguserÅ‘ gyűrű" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Fájdalmas jajgatása vezet el egy kentaurhoz, aki csapdába esett. " "Kiszabadítod és hálából átad neked egy kis erszényt. Amikor kiüríted a " "tartalmát, egy gazdagon díszített gyűrűt találsz." msgid "Witch's Broach of Magic" msgstr "Boszorkány mágikus mellcsatja" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Egy megégetett boszorkány maradványai mellett rátalálsz egy gyönyörű melltűt " "találsz, melyet elteszel magadnak." msgid "Medal of Valor" msgstr "Vitézség medál" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "A %{name} ennyivel növeli a hÅ‘s seregének morálját: %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Megmentesz egy erényes szűzlányt egy gonosz kegyúr karmaiból, melynek " "elismeréseként a király hírnöke átadja neked a Vitézség medált." msgid "Medal of Courage" msgstr "Bátorság medál" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Miután megmentesz egy fiút az ádáz farkasok szorításából és visszakíséred " "apja birtokára, a nemesember hálából megjutalmaz a Bátorság medállal." msgid "Medal of Honor" msgstr "Becsület medál" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Miután megmentesz egy hercegnÅ‘t a szomszédos királyságból egy aljas " "rabszolgakereskedÅ‘ gonosz karmaiból, megajándékoz a Becsület medállal." msgid "Medal of Distinction" msgstr "Kiválóság medál" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Megtisztítottad a vidéket a rettenetes Minotaurusztól, aki puszta " "szórakozásból falta fel nemesemberek lovagjait. Jutalmad a Kiválóság medál." msgid "Fizbin of Misfortune" msgstr "Balszerencse medál" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "A %{name} %{count} egységgel lecsökkenti a hÅ‘s seregének morálját." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Belebotlasz egy úton heverÅ‘ medálba. Ahogy a felszereléseid közé teszed, " "rögtön ráeszmélsz, hogy egy nagyon nemkívánatos tárgyra tettél szert, a " "Balszerencse medálra, mely nagymértékben lecsökkenti a sereged morálját." msgid "Thunder Mace of Dominion" msgstr "Hatalom mennydörgÅ‘ buzogánya" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Hirtelen vihar támad és egy villám belecsap egy fába, mely kettéhasad. A " "fában egy titokzatos buzogányt találsz." msgid "Armored Gauntlets of Protection" msgstr "Védelem páncélkesztyűi" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "A %{name} ennyivel növelik a hÅ‘s védÅ‘erejét: %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Összetalálkozol a hírhedt Fekete Lovaggal! KimerítÅ‘ párbajt vívtok " "egymással, mely döntetlennel zárul. A Lovag tisztelete jeléül felajánl neked " "egy pár páncélkesztyűt." msgid "Defender Helm of Protection" msgstr "Védelem sisak" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Aranyló csillanásra figyelsz fel a szemed sarkából. Elkezded keresni a " "kibocsátóját és egy bokor alatt rálelsz egy arany sisakra." msgid "Giant Flail of Dominion" msgstr "Óriás hatalom cséphadaró" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Egy ügyetlen Óriás megölte magát a saját cséphadarójával. Tudatában saját " "kiváló fegyverforgató képességeidnek, óvatosan eltávolítod a cséphadarót a " "pórul járt Óriásból." msgid "Ballista of Quickness" msgstr "GyorstüzelÅ‘ hajítógép" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "A %{name} plusz lövést ad körönként a hÅ‘s hajítógépének." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Ãthaladva a fallal körülvett Å‘si város romjai között, rátalálsz a város " "elpusztításának eszközére, egy gondosan megmunkált hajítógépre." msgid "Stealth Shield of Protection" msgstr "Védelem titkos pajzsa" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Egy harcost ábrázoló kÅ‘szobor ezüst színű pajzsot tart a kezében. Ahogy " "eltávolítod a pajzsot, a szobor darabokra hullik szét." msgid "Dragon Sword of Dominion" msgstr "Sárkány hatalom kard" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Ahogy a szűk ösvényen haladsz, egy közeli bokor hirtelen lángra kap. A " "lángok a szemed láttára változnak át egy gyönyörű nÅ‘ képmásává. A nÅ‘ " "odanyújt neked egy pompás kardot." msgid "Power Axe of Dominion" msgstr "ErÅ‘ hatalom fejsze" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Egy ezüstös színű fejszét látsz belesüppedve a talajba. A katonáid néhány " "sikertelen kísérlete után odalépsz és megmarkolva a fejsze nyelét könnyedén " "kihúzod a földbÅ‘l." msgid "Divine Breastplate of Protection" msgstr "Védelem isteni mellvértje" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Egy rablócsapat éppen halott harcosokat foszt ki. Elűzöd a hullarablókat és " "észreveszed, hogy elkerülte a figyelmüket egy gyönyörű mellvért." msgid "Minor Scroll of Knowledge" msgstr "Tudás kis tekercse" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Megjelenik elÅ‘tted egy lebegÅ‘ üvegtartály, benne egy karmazsinvörös " "bársonypárnán nyugvó tekerccsel. Ahogy hozzáérsz, kinyílik a fedele és a " "tekercs a kezeid közé lebeg." msgid "Major Scroll of Knowledge" msgstr "Tudás nagy tekercse" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Egy helybeli bölcs ember meglátogatásakor felfeded elÅ‘tte utazásod célját. Å " "belenyúl egy zsákba és kihúz belÅ‘le egy megsárgult tekercset, majd átadja " "neked." msgid "Superior Scroll of Knowledge" msgstr "FelsÅ‘bb tudás tekercse" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Egy agg druida maradványaira bukkansz. Megsárgult csontok kandikálnak ki " "köpenye gyűrött redÅ‘i közül. A köpenyt átkutatva, felfedezel egy a redÅ‘k " "közé rejtett tekercset." msgid "Foremost Scroll of Knowledge" msgstr "FelsÅ‘bb tudás nagy tekercse" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Egy szétmarcangolt, halott druida megsárgult csontjai kandikálnak ki köpenye " "gyűrött redÅ‘i közül. A köpenyt átkutatva, felfedezel egy a redÅ‘k közé " "rejtett tekercset." msgid "Endless Sack of Gold" msgstr "Végtelen aranyzsák" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "A %{name} naponta %{count} arannyal gazdagítja a hÅ‘st." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Egy kis kobold táncol vidáman egy varázstarisznya körül. Amint észrevesz " "téged közeledni, két lépés között hirtelen megáll. A kicsi manó felsikít, " "vadul topogni kezd a lábaival, majd köddé válik. Emlékezve a régi kobold " "mondásra: 'aki kapja, marja', magadhoz ragadod a tarisznyát és távozol." msgid "Endless Bag of Gold" msgstr "Végtelen aranytarisznya" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Egy nemesasszony, elszakad az utazótársaitól és a segítségedet kéri. Miután " "hazakísérted, megjutalmaz egy arannyal teli tarisznyával." msgid "Endless Purse of Gold" msgstr "Végtelen aranyerszény" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Utad során ráakadsz egy arannyal teli bÅ‘rerszényre, mely egykor egy elÅ‘kelÅ‘ " "harcos király tulajdona volt, aki rendelkezett az élettelen tárgyak arannyá " "változtatásának képességével." msgid "Nomad Boots of Mobility" msgstr "Nomádcsizma" msgid "The %{name} increase the hero's movement on land." msgstr "A %{name} megnöveli a hÅ‘s mozgáspontjait szárazföldön." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Egy nomád kereskedÅ‘ védelmet keres egy goblintörzzsel szemben. " "Közreműködésedért átad neked egy pár - a legfinomabb bÅ‘rbÅ‘l készített - " "aprólékosan megmunkált csizmát. KözelebbrÅ‘l megszemlélve lenyűgözÅ‘ Å‘si " "rovásjeleket veszel észre a bÅ‘rbe metszve." msgid "Traveler's Boots of Mobility" msgstr "Utazócsizma" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Felfedezel egy pár gyöngysorral díszített csizmát, mely a legfinomabb bÅ‘rbÅ‘l " "készült. Hálával telve az ismeretlen adományozó iránt, elteszed a csizmákat " "a felszereléseid közé." msgid "Lucky Rabbit's Foot" msgstr "Szerencsehozó nyúlláb" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "A %{name} ennyivel növeli a hÅ‘s seregének szerencséjét: %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Egy utazó árus egy ezüstösen csillogó szÅ‘rbÅ‘l készültnyúllábat ajánl " "megvételre, hogy biztonságos legyen az utazás. Az árus elmagyarázza, hogy a " "bűbáj hogyan fogja növelni a szerencsédet a csatában." msgid "Golden Horseshoe" msgstr "Arany lópatkó" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Egy kelepcébe csalt Egyszarvú nyerít rémülten. Megnyugtató szavakat suttogsz " "neki, miközben kiszabadítod. Felhorkant és dobbant egyet az egyik elülsÅ‘ " "patájával, majd elvágtat. Lepillantasz és meglátsz egy arany lópatkót." msgid "Gambler's Lucky Coin" msgstr "Szerencsepénz" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Elfogtál egy gonosz kis ördögfiókát, aki rettegésben tartotta környéket. " "Szabadulásáért cserébe megjutalmaz egy varázsérmével." msgid "Four-Leaf Clover" msgstr "Négylevelű lóhere" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Egy parcella halott és kiszáradt növény között, meglepetésedre rátalálsz egy " "egészséges zöld nénylevelű lóherére." msgid "True Compass of Mobility" msgstr "Iránytű" msgid "The %{name} increases the hero's movement on land and sea." msgstr "" "Az %{name} megnöveli a hÅ‘s mozgáspontjait szárazföldön és vízen egyaránt." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Egy öregember azt állítja, hogy Å‘ egy feltaláló és kéri, hogy próbáld ki " "legújabb találmányát. Egy iránytűt ad át neked." msgid "Sailor's Astrolabe of Mobility" msgstr "Tengerész asztrolábium" msgid "The %{name} increases the hero's movement on sea." msgstr "A %{name} megnöveli a hÅ‘s mozgáspontjait vízen." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Az ogrék éppen egy vén tengerészkapitányt kínoznak. Megmented Å‘t és " "viszonzásul megjutalmaz egy bámultos eszközzel, mellyel csillagászati " "számításokat lehet végezni." msgid "Evil Eye" msgstr "Gonosz szem" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "A %{name} felére csökkenti az átok varázslat varázslatpont-igényét." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Ahogy bemerészkedsz egy roskatag kunyhóba, egy régóta halott boszorkány " "csontvázára lelsz. Ãtvizsgálva az emberi maradványokat, az üres koponya " "belsejébÅ‘l egy üvegszem gurul elÅ‘." msgid "Enchanted Hourglass" msgstr "Bűvös homokóra" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "A %{name} megnöveli a hÅ‘s varázslatainak hatóidÅ‘it %{count} körrel." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "A táj hirtelen megváltozik és egy hátborzongató helyen találod magad: " "Dögkeselyűk lakmároznak egy szörnyű csata helyszínén. Csak felszínesen " "kutatjátok át a terepet, de így is ráakadtok egy bűvös homokórára a " "maradványok között." msgid "Gold Watch" msgstr "Aranyóra" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "Az %{name} megduplázza a hÅ‘s hipnózis varázslatának hatásosságát." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Jutalmul, amiért kihúztátok a kocsiját az árokból, egy utazó bájital árus " "átad neked egy \"mágikus\" aranyórát. Maga sem volt tudatában, hogy az óra " "ténylegesen milyen varázserÅ‘vel bír." msgid "Skullcap" msgstr "FejfedÅ‘" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "A %{name} felére csökkenti minden elmére ható varázslat varázslatpont-" "igényét." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Egy rövid pihenÅ‘ egy vidéki fogadóban lehetÅ‘séget ad pénz, történetek, vagy " "- akaratlanul - csomagok cseréjére. Az elcserélt új hátizsákodban egy " "fejfedÅ‘t találsz." msgid "Ice Cloak" msgstr "Jégköpeny" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "A %{name} felére csökkenti a fagy-varázslatok által a hÅ‘s egységein okozott " "sérüléseket." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Egy bajba került lányka rémült kiáltásaira figyelsz fel és a hangokat " "követve, meglátsz egy fiatal lányt egy éhes medve elÅ‘l menekülve. Kivárod a " "kedvezÅ‘ alkalmat és végzel a vadállattal. A lányka valójában egy varázslónÅ‘, " "aki hálából varázsköpenyt szÅ‘ a megve irhájából." msgid "Fire Cloak" msgstr "Tűzköpeny" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "A %{name} felére csökkenti a tűz-varázslatok által a hÅ‘s egységein okozott " "sérüléseket." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Utad során belebotlasz egy nekromantába és egy lovagba, akik éppen egymással " "harcolnak. A nekromanta tűzcsapással sújt le a lovagra, amitÅ‘l az térdre " "esik. Gyorsan cselekszel és megölöd a gonosz felet, mielÅ‘tt bevihetné a " "végsÅ‘ csapást. A hálás lovag odaadja neked a tűzköpenyét, mely megvédte Å‘t." msgid "Lightning Helm" msgstr "Villámló sisak" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "A %{name} felére csökkenti a villám-varázslatok által a hÅ‘s egységein " "okozott sérüléseket." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Egy nélkülözÅ‘ vándor bádogos ételért és vízért cserébe felajánl neked egy " "sisakot villámforma díszítéssel a csúcsán. Kíváncsian elfogadod, majd késÅ‘bb " "jössz rá, hogy a sisak varázserÅ‘vel bír." msgid "Evercold Icicle" msgstr "Örök jégcsap" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "Az %{name} %{count} százalékkal megnöveli a hÅ‘s fagy-varázslatainak " "hatásosságát az ellenséges csapatokon." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Egy a déli napsütés hÅ‘jének ellenálló jégcsap ragadja meg a figyelmedet. " "Kíváncsiságból letöröd és azt tapasztalod, hogy a kezed melegétÅ‘l sem olvad " "meg." msgid "Everhot Lava Rock" msgstr "Örökké izzó lávakÅ‘" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "Az %{name} %{count} százalékkal megnöveli a hÅ‘s tűz-varázslatainak " "hatásosságát az ellenséges csapatokon." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Vándorlásaid során kapcsolatba kerülsz majomszerű lények törzsével, melyek " "egy soha ki nem hűlÅ‘ varázs lávakövet használnak tűzgyújtásra. Megszánod " "ezeket a lényeket és megtanítod Å‘ket a tűzcsiholásra botok segítségével. Azt " "hívén, valamiféle isten vagy, odaadják neked a lávakövüket." msgid "Lightning Rod" msgstr "Villámló bot" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "A %{name} %{count} százalékkal megnöveli a hÅ‘s villám-varázslatainak " "hatásosságát az ellenséges csapatokon." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Várjátok a vihar elvonultát, miközben egy közeli tanya villámhárítójába " "belecsap a villám, mely ettÅ‘l megolvad és földre borul. A rúd hegye azonban " "egyben marad és érintésre feláll az embernek a haja tÅ‘le. Hmm..." msgid "Snake-Ring" msgstr "Kígyógyűrű" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "A %{name} felére csökkenti a hÅ‘s összes áldás varázslatának varázslatpont-" "igényét." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Találsz egy nagyon furcsa kialakítású gyűrűt egy régóta halott utazó ujján. " "A gyűrű egy saját farkába harapó kígyóra hasonlít." msgid "Ankh" msgstr "Ankh" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "Az %{name} megduplázza a hÅ‘s feltámasztó varázslatainak hatásosságát." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Heves szélvihar tombol, melynek nyomán feltárul egy eltemetett sírhely " "bejárata. Ãtkutatod és észreveszed, hogy valaki már kifosztotta elÅ‘tted. A " "korábbi tolvajok azonban nem vettek észre egy ezüstláncon függÅ‘ ankhot a " "sötétben." msgid "Book of Elements" msgstr "Elemek könyve" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "Az %{name} megduplázza a hÅ‘s idézÅ‘ varázslatainak hatásosságát." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Összetalálkozol egy szellemidézÅ‘vel, aki kérlel, hogy hadd csatlakozzon a " "csapatodhoz egy ideig, hogy védelmet leljen. Ráállsz és fizetségül felajánl " "neked egy másolatot az Elemek könyvébÅ‘l." msgid "Elemental Ring" msgstr "Elementál gyűrű" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" "Az %{name} felére csökkenti az idézÅ‘ varázslatok varázslatpont-igényét." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Megálltok pihenÅ‘t tartani, majd felfigyelsz egy hiúzra, ami épp egy kisebb " "fára mászik fel, hogy elérje egy holló fészkét. Egy sugallattól vezérelve, " "felmászol a fára és elijeszted a hiúzt. Amikor belepillantasz a fészekbe, " "csillogó köveket és egy gyűrűt találsz." msgid "Holy Pendant" msgstr "Szent nyakék" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "A %{name} immunissá teszi a hÅ‘s csapatait az átok varázslatokra." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Vándorlásaid során szembetalálkozol egy remetével, aki egy kicsiny, de " "takaros kunyhóban lakik. Mély benyomást tesz rá a küldetésed, ezért " "kizökkenve meditációjából, idÅ‘t szakít rád, hogy megáldjon és átadjon neked " "egy fityegÅ‘t az átkok ellen." msgid "Pendant of Free Will" msgstr "Szabad akarat nyakék" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "A %{name} immunissá teszi a hÅ‘s csapatait a hipnózis varázslatokra." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Segélykiáltásokra figyelsz fel és rátalálsz egy öregemberre a folyónál, akit " "folyami tündérek szórakozásból a víz alá nyomnak. Megmented az öregembert és " "bosszúból megragadod az egyik tündért és kirángatod a szárazra. A tündér " "nagyon nem érzi jól magát a levegÅ‘n, ezért odaad neked egy varáűzsnyakéket, " "csak engedd szabadon." msgid "Pendant of Life" msgstr "Élet nyakék" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "Az %{name} immunissá teszi a hÅ‘s csapatait a halál varázslatokra." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Út közben rövid idÅ‘re összefuttok egy karavánnal és asztragalos " "kockajátékban elnyersz egy varázsnyakéket. Korábbi tulajdonosa azt mondja, " "hogy megvéd a nekromanták halál-varázslataitól." msgid "Serenity Pendant" msgstr "Higgadtság nyakék" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "A %{name} immunissá teszi a hÅ‘s csapatait az Å‘rjöngés varázslatokra." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Tusakodás zaja csalogat oda egy idÅ‘s barbár és egy nyolcfejű hidra közötti " "harc színhelyére. Épp idejében avatkozol közbe s így a csata a férfi javára " "dÅ‘l el, aki megjutalmaz egy nyakékkel, melyet arra szokott használni, hogy " "lecsendesítje elméjét a csata ideje alatt." msgid "Seeing-eye Pendant" msgstr "Látás nyakék" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "A %{name} immunissá teszi a hÅ‘s csapatait a vakítás varázslatokra." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Összetalálkozol egy vénségesen vén öregasszonnyal, aki már régóta vak a " "szürkehályogtól és magányosan haldoklik. Igyekszel teljesítani utolsó " "kívánságait és tisztességes temetést ígérsz neki. Hálából átad neked egy " "varázslatos nyakéket, mely stilizált szemmel van díszítve és lehetÅ‘vé teszi " "a csukott szemmel való látást." msgid "Kinetic Pendant" msgstr "Eleven nyakék" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "A %{name} immunissá teszi a hÅ‘s csapatait a paralízis varázslatokra." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Összetalálkozol egy gólemmel, aki egy csillogó nyakéket visel és mellesleg " "elállja az utadat. LökdösÅ‘dés közben levágod a nyakéket a nyakáról. " "Megfosztva erejének forrásától a gólem összeesik s így a nyakék rád marad." msgid "Pendant of Death" msgstr "Halál nyakék" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "A %{name} immunissá teszi a hÅ‘s csapatait a szent varázslatokra." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Egy nektromantával vívott gyors és halálos csata nyomán elnyered a " "varázsnyakékét. KésÅ‘bb egy varázsló felvilágosít arról, hogy a nyakék " "megvédi a csapatodban lévÅ‘ élÅ‘halottakat a szent varázslatoktól." msgid "Wand of Negation" msgstr "Hatástalanító pálca" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "A %{name} immunissá teszi a hÅ‘s csapatait a varázslatoszlató varázslatoktól." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Összetalálkoztok egy ismerÅ‘s öreg varázslóval, aki épp az ellenkezÅ‘ irányba " "tart. Megajándékoz egy varázspálcával, mely megakadályozza a " "varázslatoszlatás varázslat használatát a csapataid ellen." msgid "Golden Bow" msgstr "Arany íj" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "Az %{name} eltörli a hÅ‘s csapatait sújtó %{count} százalékos távolsági lövés " "büntetést tereptárgyakon, várfalakon keresztül." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Egy híres íjásszal való véletlen találkozás az Å‘si asztragalos kockajátékban " "csúcsosodik ki. A játék hevében az íjász felteszi az íját a te lovad " "ellenében. Te nyersz." msgid "Telescope" msgstr "TávcsÅ‘" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "A %{name} %{count} egységgel megnöveli a hÅ‘s által a kalandozásai közben " "felfedett terület nagyságát." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Egy messze földrÅ‘l jött kereskedÅ‘ eladja neked népe egy új fejlesztését, " "mely utazók hasznos felszerelése lehet. Távoli tárgyak közelinek látszanak " "vele és úgy nevezik...\n" "\n" "távcsÅ‘." msgid "Statesman's Quill" msgstr "Ãllamférfi pennája" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "Az %{name} a hÅ‘s seregét alkotó egységek összköltségének %{count} " "százalékára csökkenti a megadás költségét." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Megállsz, hogy egy diplomata kocsijának törött tengelyét megjavítsd. Hálából " "odaad neked egy varázserejű írópennát, melyrÅ‘l azt állítja, hogy \"segít " "abban, hogy az emberek úgy lássák a dolgokat, ahogy te\"." msgid "Wizard's Hat" msgstr "Varázslósüveg" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "A %{name} megnöveli a hÅ‘s varázslatainak hatóidejét %{count} körrel." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Meglátsz egy varázslót, amint szélsebesen menekül egy griffmadár elÅ‘l. A " "varázsló megnyit egy portált és átsiklik rajta, de a kalapja fennakad a kapu " "szegélyén és lepürdül a fejérÅ‘l. A griff követi Å‘t a kapun kéresztül, mely " "ezután bezárul. Felveszed a kalapot, leporolod és a fejedre húzod." msgid "Power Ring" msgstr "Hatalom gyűrűje" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "A %{name} naponta %{count} ponttal tölti vissza a hÅ‘s lecsökkent " "varázserejét." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Találsz egy kis cserjét, melynek formája emlékeztet Carnauth-ra a nagy " "boszorkánymesterre és aminek az egyik ágára húzva egy gyűrű pihen. A fácska " "körül heverÅ‘ ruhafecnik és rothadó bÅ‘rdarabok alapján azt gyanítod, hogy ez " "tényleg Å, csak átlényegülve. Miután segíteni nem tudsz rajta, magadhoz " "veszed a gyűrűt." msgid "Ammo Cart" msgstr "LÅ‘szeres kordé" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "A %{name} végtelen lÅ‘szert ad a hÅ‘s távolsági lövÅ‘ egységeinek." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Egy régi csatamezÅ‘ közepén felfigyelsz egy lÅ‘szeres kordéra. Alapos " "vizsgálat után jó állapotúnak találod, úgyhogy magaddal viszed." msgid "Tax Lien" msgstr "Adósságlevél" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "Az %{name} napi %{count} aranyba kerül a hÅ‘snek." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Nagyvonalú költekezéseid eredményeképp súlyos adósságokba verted magad, " "melyet reménytelennek látsz megfizetni. Az adóellenÅ‘r megkönyörül rajtad és " "belegyezik abba, hogy napi 250 aranyat emeljen le a számládról életed " "végéig. Megadja azt is, hol kell kipipálnod, hogy egy arany menjen a " "következÅ‘ elnöki választási kampányalapba." msgid "Hideous Mask" msgstr "Förtelmes maszk" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "A %{name} megakadályozza a kósza lények csatlakozását a hÅ‘shöz." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "A híres alakváltó boszorkánymester, Sinfilas Gardolad sírjának kifosztása " "közben napvilágra kerül legendás maszkja. ReszketÅ‘ kézzel teszed fel " "magadra, mely borzalmas grimasszá torzítja az ábrázatodat! Óh, ne! Ez " "igazából Gromluck Greene förtelmes maszkja, mely a fejedre szorult." msgid "Endless Pouch of Sulfur" msgstr "Végtelen kénzacskó" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "A %{name} napi %{count} ként biztosít neked." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Látogatást teszel egy alkímistánál, aki a seregedet látva, a nemes ügyed " "hatása alá kerül. Az újsütetű támogatód átadja neked a végtelen " "kénzacskóját, hogy segítségedre legyen a törekvéseidben." msgid "Endless Vial of Mercury" msgstr "Végtelen higanyfiola" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "A %{name} napi %{count} higanyt biztosít neked." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Rövid pihenÅ‘t tartasz egy sietÅ‘sen elhagyott varázslótorony mellett és " "rábukkansz egy mágikus higanyfiolára, melynek mindig van az alján egy kicsi. " "Felismered az értékét, így magadhoz veszed és a csomagjaid közé teszed." msgid "Endless Pouch of Gems" msgstr "Végtelen drágakÅ‘erszény" msgid "The %{name} provides %{count} unit of gems per day." msgstr "A %{name} napi %{count} drágakövet biztosít neked." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Egy rövid zápor szivárványt varázsol az égre ... és felfigyelsz arra, hol ér " "földet a vége. Gyors vágtában egy arannyal teli cserépedényre lelsz, melyet " "magadhoz ragadsz, mielÅ‘tt a kobold tulajdonosa ebben megakadályozhatna. " "Felajánl neked egy végtelen drágakÅ‘erszényt az aranyáért cserébe, melyet " "elfogadsz." msgid "Endless Cord of Wood" msgstr "Végtelen fahalom" msgid "The %{name} provides %{count} unit of wood per day." msgstr "A %{name} napi %{count} fát biztosít neked." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Lepihentek és fÅ‘zéshez tüzet készültök gyújtani, így egy közeli rakás " "elszáradt faágból kihúzol egyet. Ahogy tovább húzogatog ki az ágakat, azt " "veszed észre, hogy nem akar elfogyni. Örömmel tudatosítod, hogy ez egy " "elvarázsolt halom fa, így magaddal viszed az egészet." msgid "Endless Cart of Ore" msgstr "Végtelen érccsille" msgid "The %{name} provides %{count} unit of ore per day." msgstr "A %{name} napi %{count} ércet biztosít neked." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Ráakadsz egy goblin fegyverkovácsműhelyre, ahol éppen emberek ellen " "használatos fegyvereket készítenek. Félelmetes csatakiáltással vetitek rá " "magatokat a táborukra és elűzitek Å‘ket. Ãtkutattok mindent és rábukkantok " "egy varázslatos érccsillére, mely sosem fogy ki a vasból." msgid "Endless Pouch of Crystal" msgstr "Végtelen kristályzacskó" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "A %{name} napi %{count} kristályt biztosít neked." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Menedéket találva egy vihar elÅ‘l egy kis barlangban, felfigyelsz egy kis " "darabka kristályra a sarokban. Kíváncsian letörsz belÅ‘le egy darabot, de azt " "veszed észre, hogy a kristály visszanöveszti, amit letörtél. Úgy döntesz az " "egész darabot elteszed egy zacskóba és magaddal viszed." msgid "Spiked Helm" msgstr "Tüskés sisak" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Csapadtodra orvul rátámad egy kicsi, de annál vadabb (viszont nem túl eszes) " "ork törzs. Könnyedén hárítod a támadást és a túlélÅ‘k fejvesztve menekülnek " "szerteszét. Egyikük egy tüskés sisakot viselt, úgy véled, jó kis ajándék " "lesz, ezért elteszed." msgid "Spiked Shield" msgstr "Tüskés pajzs" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Egy kiszáradt vízmosáson átvezetÅ‘ hídhoz érkezel. MielÅ‘tt átkelhetnél, egy " "troll lép elÅ‘ a híd alól és közli, hogy csak fizetségért cserébe enged át " "rajta. Ezt visszautasítod, mire a troll rádtámad és rákényszerít, hogy " "megöld. Tüskés pajzsát elteszed hadizsákmányként." msgid "White Pearl" msgstr "Fehér gyöngy" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Egy kiszáradt sóstó medrében megtett séta valószerűtlen eredménnyel zárul: " "darabokra tört kagylóhéjak és más törmelék közt egy fehér gyöngyre lelsz." msgid "Black Pearl" msgstr "Fekete gyöngy" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Egy a vidéken zsákmányra vadászó szokatlan méretű griffmadárról szóló " "szóbeszéd elvezet a búvóhelyéül szolgáló odúhoz. Gyors és brutális " "küzdelemben végzel vele és visszataszító fészkét átkutatva elÅ‘kerül egy " "óriási fekete gyöngy." msgid "Magic Book" msgstr "Varázskönyv" msgid "The %{name} enables the hero to cast spells." msgstr "A %{name} lehetÅ‘vé teszi, hogy a hÅ‘s varázsolhasson." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" "Egy fiatalember közeledik hozzád: \"Nagyuram, engedd meg, hogy megmutassam " "legújabb találmányomat, mely a tudást terjeszti!\" Követed az ifjút a " "műhelyébe és felfigyelsz egy karokkal és fogantyúkkal ellátott készüléket. " "\"Ez az itt!\" - mondja izgatottan - \"A nyomdagép.\" Majd mielÅ‘tt " "megszólalhatnál, kezedbe nyom egy Varázskönyvet." msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "A gyÅ‘zelem elnyeréséhez meg kell találni a Szent Varázstárgyat." msgid "Dummy 2" msgstr "Próba 2" msgid "The reserved artifact." msgstr "A félretett varázstárgy." msgid "Dummy 3" msgstr "Próba 3" msgid "Dummy 4" msgstr "Próba 4" msgid "Spell Scroll" msgstr "Varázsige tekercs" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "A %{name} lehetÅ‘vé teszi a hÅ‘snek a(z) %{spell} varázslat használatát, ha " "van varázskönyve." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Találsz egy míves tárolóedényt, mely egy régi borjúbÅ‘r tekercset tartalmaz. " "Az edényen lévÅ‘ rúnák nagyon Å‘siek és az azokat körülölelÅ‘ díszítÅ‘ motívumok " "lenyűgözÅ‘ek. Ahogy kitekered a tekercset, varázserÅ‘ tölt el téged." msgid "Arm of the Martyr" msgstr "Mártír keze" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "A %{name} %{count} ponttal növeli a hÅ‘s varázserejét, de büntetésként " "élÅ‘halott morált ad." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "A csapatod egy nem túl eszes tagja felszed a földrÅ‘l egy test nélküli, de " "még mozgó kart. A katonáid undorítónak találják a csonkolt kart, de te " "mégsem tudod rávenni magad, hogy eldobd. Úgy érzed, valamiféle varázserÅ‘t " "rejt magában, mely befolyásolja a döntéseid meghozatalát." msgid "Breastplate of Anduran" msgstr "Anduran mellvértje" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} %{count} ponttal növeli a hÅ‘s védekezÅ‘képességét." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Meglátsz egy feliratot, mely így hangzik: \"Itt nyugszik Anduran teste. " "Hódolj és esküdj hűséget s jutalmad nem marad el.\" Úgy döntesz, hogy így is " "teszel és amint felállsz, hidegséget érzel a bÅ‘rödön. Lenézel és azt veszed " "észre, hogy magadon viselsz egy ragyogó és gazdagon díszített mellvértet." msgid "Broach of Shielding" msgstr "Védelem mellcsat" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "A %{name} %{count} százalék védelmet nyújt az Armageddon és az Elemi vihar " "varázslatok ellen, ugyanakkor kettÅ‘vel csökkenti a varázserÅ‘t." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Egy barátságos varázslónÅ‘ úgy véli, hogy seregednek hasznára lehet a mágia " "elleni védelmének a megerÅ‘sítése. Felajánlja, hogy a köpenyed mellcsatját " "védelmezÅ‘ varázstárggyá változtatja. Elfogadod az ajánlatot." msgid "Battle Garb of Anduran" msgstr "Anduran Harci Pajzsa" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} összekapcsolja a három Anduran varázstárgy erejét. A hÅ‘s egységeinek " "maximális szerencsét és morált, a hÅ‘snek pedig Városkapu varázslatot ad." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Megszánva egy ágról szakadt jobbágyot, drága pénzért megveszed régi lomokkal " "teli ládikáját. KésÅ‘bb, amikor átnézed a portékát, felfedezed a legendás " "Anduran harci öltözet három darabját!" msgid "Crystal Ball" msgstr "Kristálygömb" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "A %{name} sokkal pontosabb információkat nyújt az azt viselÅ‘ hÅ‘s " "környezetében lévÅ‘ lényekrÅ‘l, kastélyokról, hÅ‘sökrÅ‘l." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Egy cigánykaravánnal találkozol szembe, akik lakomáznak és mézsörrel edzik a " "testüket. Odahívnak és azt mondják: \"Ha bizonyságát adod, hogy el tudod " "járni a Rama-Buta táncot, akkor megjutalmazunk.\" Fogalmad sincs mi fán " "terem, de azért kipróbálod. Hisztérikus röhögésben törnek ki, de csodálják a " "bátorságodat és átadnak neked végül egy kristálygömböt." msgid "Heart of Fire" msgstr "Tűzszív" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "A %{name} %{count} százalékos védelmet nyújt a tűzvarázslatok ellen, de " "duplázza a sebzést a fagyvarázslatoktól." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Egy nemrégiben felperzselt tisztásra érsz és meglátsz egy tűzelementált egy " "kÅ‘ tetején kuporogva. Felnéz és lángoló arcát súlyos kínok torzítják el. " "Hozzádvág egy izzó tárgyat, melyet próbálsz kivédeni a kezeiddel, de az " "átsiklik köztük és a mellkasodba égeti magát." msgid "Heart of Ice" msgstr "Jégszív" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "A %{name} %{count} százalékos védelmet nyújt a fagyvarázslatok ellen, de " "duplázza a sebzést a tűzvarázslatoktól." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Hirtelen dermesztÅ‘ hideg önti el testedet, mely lesújt és lever a lovadról. " "A kín kissé alábbhagy, de olyan érzés kerít hatalmába, mintha megfagyott " "volna a szíved. Ahogy feltápászkodsz a földrÅ‘l, hangos nevetést hallasz. " "Megfordulsz és még éppen látod, ahogy egy Jégóriás szalad be a fák közé és " "tűnik el." msgid "Helmet of Anduran" msgstr "Anduran sisakja" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Észreveszel egy csillogó tárgyat kifordulva a földbÅ‘l. Odaküldöd az egyik " "emberedet, hogy vizsgálja meg, aki visszatér a kezében egy arany sisakkal. " "Rájössz, hogy ez nem lehet más, mint a legendás Anduran sisakja. Å az " "egyetlen, akirÅ‘l úgy tartják, hogy tömör arany vértet viselt." msgid "Holy Hammer" msgstr "Szent kalapács" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Egy csata helyszínére érkezel, ahol egy paladin halálos sebet kapott egy " "csapat zombitól. Megkér, hogy vedd el a kalapácsát és végezd be, amit " "elkezdett. Amint a kezedbe veszed, zúgni kezd és aztán minden elhomályosul. " "A zombik holtan rogynak össze, a kalapácsra pedig vér csurog. Felszíjazod az " "övedre." msgid "Legendary Scepter" msgstr "Legendás jogar" msgid "The %{name} adds %{count} points to all attributes." msgstr "A %{name} %{count} ponttal növeli az összes képességedet." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Amint felérsz egy kis dombtetÅ‘re, nevetséges látvány fogad. Egy tündér egy " "csaknem akkora jogart próbál elcipelni, mint saját maga. Próbálod magadba " "fojtani a nevetést, majd kuncogva megkérded: \"Kell segítség?\" A tündér " "gyanakodva méreget és azt válaszolja: \"Te ezt viccesnek találod? Jól van, " "akár tovább is cipelheted. Amúgy is jobb szeretek repkedni." msgid "Masthead" msgstr "Ãrbóc" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "Az %{name} %{count} ponttal növeli a hÅ‘s egységeinek szerencséjét, illetve " "morálját tengeri ütközetben." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Egy vén tengerész elmesél egy történetet egy elvarázsolt árbócról, melyet " "még fiatalkorában használt, hogy csapatai új erÅ‘re kapjanak vész esetén. Egy " "megfakult térképet ad át neked, mely megmutatja, hova rejtették el. Hosszas " "keresés-kutatás után rátaláltok egy közeli hajódokk alá rejtve." msgid "Sphere of Negation" msgstr "Tagadás gömbje" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "A %{name} megakadályozza, hogy a háborúzó felek varázsolhassanak." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Megállsz, hogy segíts egy jobbágynak befogni elszabadult kancáját. Hálája " "jeléül átad neked egy kicsi gömböt. Amint megragadod, azt érzed, hogy a " "varázserÅ‘d távozik a tagjaidból." msgid "Staff of Wizardry" msgstr "Varázspálca" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "A %{name} %{count} ponttal növeli a hÅ‘s varázserejét." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Míg csapataid fel-alá kutattak, egy rejtélyes botot találtak vagy három láb " "magasan lebegve. Ãtadták neked és kezedbe véve egy feliratra lettél " "figyelmes, mely így szól: \"Az elme fortélya legyÅ‘zi a nyers erÅ‘t, a mágia " "pedig legyÅ‘zi a hatalmat. Figyeld meg szavaim s minden csatát megnyersz.\"" msgid "Sword Breaker" msgstr "KardtörÅ‘" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "" "A %{name} eggyel növeli a hÅ‘s támadó- és %{count} ponttal a védÅ‘erejét." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "A korábbi Årkapitány küldetésed nagyrabecsülése jeléül átadja neked ezt a " "nagyszerű KardtörÅ‘t, melyet szolgálati ideje alatt viselt." msgid "Sword of Anduran" msgstr "Anduran Kardja" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Egy troll megállít és ezt mondja: \"Fizess 5000 aranyat, különben Anduran " "Kardja menten kettéhasít.\" Elutasítod. Erre a troll megragadja az övén lógó " "kardot és rögtön felordít a fájdalomtól, majd elszalad. Felveszed a mesés " "kardot és hálát adsz, amiért ezek a féleszű trollok az élénél fogják meg az " "éles tárgyakat." msgid "Spade of Necromancy" msgstr "Nekromancia sírásó lapát" msgid "The %{name} gives the hero increased necromancy skill." msgstr "A %{name} fokozza a hÅ‘s Nekromancia képességét." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Egy koszos ásólapátot szúrtak egy közeli sárhalomba. Tüzetesen megvizsgálod " "és felismered, hogy ez a Sírásók ásólapátja, melyrÅ‘l régóta azt hitték, hogy " "elvesztették a halandók." msgid "spellBonus|selected by user" msgstr "kiválasztva" msgid "Wood" msgstr "Fa" msgid "Mercury" msgstr "Higany" msgid "Ore" msgstr "Érc" msgid "Sulfur" msgstr "Kén" msgid "Crystal" msgstr "Kristály" msgid "Gems" msgstr "DrágakÅ‘" msgid "Gold" msgstr "Arany" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Hét erÅ‘forrás van a Heroes 2-ben, melyeket építésre, csapatok vásárlására, " "hÅ‘sök toborzására lehet használni. Az Arany a legáltalánosabb, mely szinte " "mindenhez szükséges. A Fa és Érc használatos a legtöbb épülethez. A DrágakÅ‘, " "a Higany és a Kristály a legerÅ‘sebb teremtményekhez, vagy építményekhez kell." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Egy hatalmas tűzgolyó robban a területen, megsebesítvén a közeli lényeket." msgid "Fireball" msgstr "Tűzgolyó" msgid "Fireblast" msgstr "Tűzlabda" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "A tűzgolyó fejlettebb változata, a varázslat középpontjától 2 hexányi " "területen hat." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Villámcsapást okoz a kiválasztott lényen." msgid "Lightning Bolt" msgstr "Villám" msgid "Chain Lightning" msgstr "Láncvillám" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Villámcsapások láncolatát okozza a kiválasztott lénytÅ‘l kezdÅ‘dÅ‘en, aztán a " "hozzá LEGKÖZELEBBIN feleakkora sebzéssel, és így tovább mindaddig, amíg el " "nem fogy az energiája. Vigyázat: ez a varázslat saját egységet is sebezhet!" msgid "Teleport" msgstr "Teleportálás" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Ãthelyezi a kiválasztott egységet a csatatér bármely szabad pontjára." msgid "Cure" msgstr "Gyógyítás" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Elűz minden negatív varázslatot egy egységedrÅ‘l és a varázserÅ‘d mértéke " "függvényében visszaállít %{count} életerÅ‘t." msgid "Mass Cure" msgstr "Tömeges gyógyítás" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Elűz minden negatív varázslatot az egységeidrÅ‘l és a varázserÅ‘d mértéke " "függvényében visszaállít %{count} életerÅ‘t." msgid "Resurrect" msgstr "Feltámasztás" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "A csata végéig feltámaszt teremtményeket halott vagy sérült egységekbÅ‘l." msgid "Resurrect True" msgstr "Valódi feltámasztás" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Maradandóan feltámaszt teremtményeket halott vagy sérült egységekbÅ‘l." msgid "Haste" msgstr "Gyorsítás" msgid "Increases the speed of any creature by %{count}." msgstr "%{count} ponttal növeli bármely lény sebességét." msgid "Increases the speed of all of your creatures by %{count}." msgstr "%{count} ponttal növeli az összes saját lény sebességét." msgid "Mass Haste" msgstr "Tömeges gyorsítás" msgid "Slows target to half movement rate." msgstr "Felére lassítja a kiválasztott lény sebességét." msgid "spell|Slow" msgstr "Lassítás" msgid "Mass Slow" msgstr "Tömeges lassítás" msgid "Slows all enemies to half movement rate." msgstr "Felezi az összes ellenség sebességét." msgid "spell|Blind" msgstr "Vakítás" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Elhomályosítja az érintett lény látását és megakadályozza a mozgásban." msgid "Bless" msgstr "Ãldás" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Maximális sebzést ad a kiválasztott lényeknek." msgid "Causes all of your units to inflict maximum damage." msgstr "Maximális sebzést ad az összes saját egységednek." msgid "Mass Bless" msgstr "Tömeges áldás" msgid "Magically increases the defense skill of the selected creatures." msgstr "A kiválasztott lény védÅ‘ereje varázslatosan növekszik." msgid "Stoneskin" msgstr "KÅ‘bÅ‘r" msgid "Steelskin" msgstr "AcélbÅ‘r" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "A kiválasztott lény védÅ‘ereje növekszik. Ez a KÅ‘bÅ‘r egy fejlettebb változata." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Minimálisra csökkenti a kiválasztott lények sebzését." msgid "Curse" msgstr "Ãtok" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Minimálisra csökkenti az összes ellenséges lény sebzését." msgid "Mass Curse" msgstr "Tömeges átok" msgid "Damages all undead in the battle." msgstr "Megsebzi az összes élÅ‘halott egységet a csatában." msgid "Holy Word" msgstr "Szent Ige" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Megsebesít minden élÅ‘holtat a csatában. A Szent Ige varázslat egy fejlettebb " "formája." msgid "Holy Shout" msgstr "Szent kiáltás" msgid "Anti-Magic" msgstr "Antimágia" msgid "Prevents any magic against the selected creatures." msgstr "Megakadályoz bármely varázslatot a kiválasztott lények ellen." msgid "Dispel Magic" msgstr "Varázslatűzés" msgid "Removes all magic spells from a single target." msgstr "Eloszlat minden varászlatot a kiválasztott egységrÅ‘l." msgid "Mass Dispel" msgstr "Tömeges varázslatűzés" msgid "Removes all magic spells from all creatures." msgstr "Eloszlat minden varászlatot minden lényrÅ‘l." msgid "Causes a magic arrow to strike the selected target." msgstr "Varázsnyíllal mér csapást a kiválasztott célpontra." msgid "Magic Arrow" msgstr "Varázsnyíl" msgid "Berserker" msgstr "Årjöngés" msgid "Causes a creature to attack its nearest neighbor." msgstr "A lény megtámadja a legközelebbi szomszédját." msgid "Armageddon" msgstr "Végítélet" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "Isteni csapást mér a harcmezÅ‘ összes egységére." msgid "Elemental Storm" msgstr "Elemi vihar" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Varázslat zúdul a csatatérre és minden lény sebzÅ‘dik." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "KÅ‘esÅ‘ zúdul a csatatérre és minden lényt megsebez a közelben." msgid "Meteor Shower" msgstr "MeteoresÅ‘" msgid "Paralyze" msgstr "Bénítás" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "A kiválasztott egység megbénul, nem képes mozogni vagy visszaütni." msgid "Hypnotize" msgstr "Hipnózis" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Ãtadja egy ellenséges egység irányítását, ha ütÅ‘ereje kisebb, mint a " "varázserÅ‘d %{count}-szorosa." msgid "Cold Ray" msgstr "Jégsugár" msgid "Drains body heat from a single enemy unit." msgstr "TesthÅ‘t von el a kiválasztott ellenséges egységbÅ‘l." msgid "Cold Ring" msgstr "Jéggyűrű" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "TesthÅ‘t von el minden szomszédos egységbÅ‘l, kivéve a középpontban állót." msgid "Disrupting Ray" msgstr "GyengítÅ‘ sugár" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Csökkenti egy ellenséges egység védelmi képességét hárommal." msgid "Damages all living (non-undead) units in the battle." msgstr "Az összes élÅ‘ (nem élÅ‘halott) egység a csatatéren sebzÅ‘dik." msgid "Death Ripple" msgstr "Halállökés" msgid "Death Wave" msgstr "Halálhullám" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Megsebesít minden élÅ‘t (nem élÅ‘halottat) a csatában. Ez a varázslat a " "Halállökés egy fejlettebb változata." msgid "Dragon Slayer" msgstr "SárkányölÅ‘" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Az egység támadóereje jelentÅ‘sen növekszik sárkányok ellen." msgid "Blood Lust" msgstr "Vérszomj" msgid "Increases a unit's attack skill." msgstr "Az egység támadóereje növekszik." msgid "Animate Dead" msgstr "Feltámasztás" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "Maradandóan feltámaszt teremtményeket halott vagy sérült egységekbÅ‘l." msgid "Mirror Image" msgstr "Tükörkép" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Egy kiválasztott létezÅ‘ egységedrÅ‘l készít egy hamis másolatot. Az illúzió " "ugyanakkora erÅ‘vel támad, mint az eredeti, de bármekkora sebzés " "következtében eltűnik." msgid "Shield" msgstr "Pajzs" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Felére csökkenti a kiválasztott egység sérülékenységét a távolsági " "lövésektÅ‘l. Ez nem vonatkozik a vártornyok, illetve a hajítógép által " "okozott sérülésekre." msgid "Mass Shield" msgstr "Tömeges pajzs" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Felére csökkenti minden egység sérülékenységét a távolsági lövésektÅ‘l. Ez " "nem vonatkozik a vártornyok, illetve a hajítógép által okozott sérülésekre." msgid "Summon Earth Elemental" msgstr "Földelementál idézése" msgid "Summons Earth Elementals to fight for your army." msgstr "Megidézett Földelementálok segítenek a harcban." msgid "Summon Air Elemental" msgstr "Légelementál idézése" msgid "Summons Air Elementals to fight for your army." msgstr "Megidézett Légelementálok segítenek a harcban." msgid "Summon Fire Elemental" msgstr "Tűzelementál idézése" msgid "Summons Fire Elementals to fight for your army." msgstr "Megidézett Tűzelementálok segítenek a harcban." msgid "Summon Water Elemental" msgstr "Vízelementál idézése" msgid "Summons Water Elementals to fight for your army." msgstr "Megidézett Vízelementálok segítenek a harcban." msgid "Damages castle walls." msgstr "Rombolja a vár falait." msgid "Earthquake" msgstr "Földrengés" msgid "Causes all mines across the land to become visible." msgstr "Láthatóvá teszi a környék összes bányáját." msgid "View Mines" msgstr "Bányák mutatása" msgid "Causes all resources across the land to become visible." msgstr "Láthatóvá teszi a környék összes nyersanyagát." msgid "View Resources" msgstr "Nyersanyagok mutatása" msgid "Causes all artifacts across the land to become visible." msgstr "Minden varázstárgyat megmutat a vidéken." msgid "View Artifacts" msgstr "Varázstárgyak mutatása" msgid "Causes all towns and castles across the land to become visible." msgstr "A környék összes városa és vára láthatóvá válik." msgid "View Towns" msgstr "Városok mutatása" msgid "Causes all Heroes across the land to become visible." msgstr "A környék összes hÅ‘se láthatóvá válik." msgid "View Heroes" msgstr "HÅ‘sök mutatása" msgid "Causes the entire land to become visible." msgstr "Az egész vidék láthatóvá válik." msgid "View All" msgstr "Minden mutatása" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "Részletes információkat ad az ellenséges hÅ‘sökrÅ‘l." msgid "Summon Boat" msgstr "Hajó idézése" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Megidézi egy közeli partra a legközelebbi használaton kívüli baráti " "tulajdonban lévÅ‘ hajót. Baráti hajó az, amit te építettél, vagy hÅ‘söd " "használt legutóbb." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "LehetÅ‘vé teszi a megidézÅ‘ számára, hogy egy közeli helyre teleportáljon." msgid "Dimension Door" msgstr "Dimenziókapu" msgid "Returns the caster to any town or castle currently owned." msgstr "" "A varázslat megidézÅ‘jét visszarepíti bármelyik saját városba vagy várba." msgid "Town Gate" msgstr "Városkapu" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "A hÅ‘s visszaugorhat egy kiválasztott saját városba vagy várba." msgid "Visions" msgstr "Látomás" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "Megjósolja az összecsapás kimenetelét egy semleges csapattal szemben." msgid "Haunt" msgstr "Bánya elátkozás" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "A bánya kísértjárta hellyé válik és nem termel többé. (Ha az enyém nem " "lehet, ne legyen másé sem!)" msgid "Set Earth Guardian" msgstr "Földelementál Å‘r" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Földelementálok beállítása bányaÅ‘rzÅ‘nek." msgid "Set Air Guardian" msgstr "Légelementál Å‘r" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Légelementálok beállítása bányaÅ‘rzÅ‘nek." msgid "Set Fire Guardian" msgstr "Tűzelementál Å‘r" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Tűzelementálok beállítása bányaÅ‘rzÅ‘nek." msgid "Set Water Guardian" msgstr "Vízelementál Å‘r" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Vízelementálok beállítása bányaÅ‘rzÅ‘nek." msgid "Random Spell" msgstr "Véletlenszerű varázslat" msgid "Randomly selected spell of any level." msgstr "Véletlenszerűen kiválasztott bármilyen szintű varázslat." msgid "Random 1st Level Spell" msgstr "Véletlenszerű 1. szintű varázslat" msgid "Randomly selected 1st level spell." msgstr "Véletlenszerűen kiválasztott 1. szintű varázslat." msgid "Random 2nd Level Spell" msgstr "Véletlenszerű 2. szintű varázslat" msgid "Randomly selected 2nd level spell." msgstr "Véletlenszerűen kiválasztott 2. szintű varázslat." msgid "Random 3rd Level Spell" msgstr "Véletlenszerű 3. szintű varázslat" msgid "Randomly selected 3rd level spell." msgstr "Véletlenszerűen kiválasztott 3. szintű varázslat." msgid "Random 4th Level Spell" msgstr "Véletlenszerű 4. szintű varázslat" msgid "Randomly selected 4th level spell." msgstr "Véletlenszerűen kiválasztott 4. szintű varázslat." msgid "Random 5th Level Spell" msgstr "Véletlenszerű 5. szintű varázslat" msgid "Randomly selected 5th level spell." msgstr "Véletlenszerűen kiválasztott 5. szintű varázslat." msgid "Petrification" msgstr "KÅ‘vé dermesztés" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "KÅ‘vé dermeszti az érintett lényt. A kÅ‘vé vált egység fele sebzést szenved " "el, ha közvetlenül támadják." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Nincs varázskönyved, így nem tudsz varázsolni." msgid "No spell to cast." msgstr "Nincs idézhetÅ‘ varázslat." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "A hÅ‘södnek van még %{sp} varázspontja (Maximum: %{max})." msgid "View Adventure Spells" msgstr "Kaland varázslatok mutatása" msgid "View Combat Spells" msgstr "Csata varázslatok mutatása" msgid "View previous page" msgstr "ElÅ‘zÅ‘ oldal mutatása" msgid "View next page" msgstr "KövetkezÅ‘ oldal mutatása" msgid "Close Spellbook" msgstr "Varázskönyv becsukása" msgid "View %{spell}" msgstr "%{spell} mutatása" msgid "This spell does %{damage} points of damage." msgstr "Ez a varázslat %{damage} sebzést okoz." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Megidézett lények:\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "A varázslat visszaállít %{hp} életerÅ‘t." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Ez a varázslat %{count} %{monster} Å‘rzÅ‘t idéz meg a bánya védelmére." msgid "The nearest town is %{town}." msgstr "A legközelebbi város: %{town}" msgid "This town is occupied by your hero %{hero}." msgstr "Ezt a várost %{hero} hÅ‘söd foglalja el." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "A varázslat %{hp} vagy ez alatti életerÅ‘vel\n" "rendelkezÅ‘ csapatokra van hatással." msgid "The ultimate artifact is really the %{name}." msgstr "A legszentebb varázstárgy kétség kívül a(z) %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "A legszentebb varázstárgyat a %{name} régióban találhatod." msgid "north-west" msgstr "észak-nyugati" msgid "north" msgstr "északi" msgid "north-east" msgstr "észak-keleti" msgid "west" msgstr "nyugati" msgid "center" msgstr "középsÅ‘" msgid "east" msgstr "keleti" msgid "south-west" msgstr "dél-nyugati" msgid "south" msgstr "déli" msgid "south-east" msgstr "dél-keleti" msgid "The truth is out there." msgstr "Az igazság odaát van." msgid "The dark side is stronger." msgstr "A sötét oldal erÅ‘sebb." msgid "The end of the world is near." msgstr "Közel a világvége." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Lord Slayer csontjai az aréna talapzatába vannak eltemetve." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "A fekete sárkány titánt eszik reggelire." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "A férfi üres fecsegésére a nÅ‘ így válaszolt: bla-bla-bla..." msgid "An unknown force is being resurrected..." msgstr "Egy ismeretlen erÅ‘ kelt új életre ..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Letöltheted a legújabb verziót innen:\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "A számításba veendÅ‘ %{resource} kiválasztása:" #~ msgid "Enable auto combat" #~ msgstr "Automatikus harc bekapcsolása" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "csata befejezése automatikus módban" #~ msgid "Please Remember" #~ msgstr "Kérlek, ne felejtsd el" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Mindig megváltoztathatod a játék nyelvét, felbontását, illetve " #~ "beállításait, ha megnyomod az " #~ msgid "door" #~ msgstr "ajtót" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " gombot a fÅ‘menü baloldalán, illetve a " #~ msgid " button from the " #~ msgstr " gomb megnyomásával a " #~ msgid "NEW GAME" #~ msgstr "ÚJ JÃTÉK" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ " menübÅ‘l. \n" #~ "\n" #~ "Élvezetes játékot!" #~ msgid "Warning!" #~ msgstr "Figyelem!" #~ msgid "Dummy 1" #~ msgstr "Próba 1" fheroes2-1.1.6+dfsg/files/lang/it.po000066400000000000000000007255671476115357100172120ustar00rootroot00000000000000# Italian translation of fheroes2 # Copyright (C) 2021 - 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2022-12-03 04:36+0100\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: it\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-Launchpad-Export-Date: 2021-10-08 00:00+0800\n" "X-Generator: Poedit 3.2\n" msgid "" "NEW\n" "GAME" msgstr "" msgid "" "SAVE\n" "GAME" msgstr "" msgid "" "LOAD\n" "GAME" msgstr "" msgid "INFO" msgstr "" msgid "QUIT" msgstr "" msgid "" "NEW\n" "MAP" msgstr "" msgid "" "SAVE\n" "MAP" msgstr "" msgid "" "LOAD\n" "MAP" msgstr "" msgid "CANCEL" msgstr "" msgid "OKAY" msgstr "" msgid "ACCEPT" msgstr "" msgid "DECLINE" msgstr "" msgid "LEARN" msgstr "" msgid "TRADE" msgstr "" msgid "YES" msgstr "" msgid "NO" msgstr "" msgid "EXIT" msgstr "" msgid "smallerButton|EXIT" msgstr "" msgid "DISMISS" msgstr "" msgid "UPGRADE" msgstr "" msgid "RESTART" msgstr "" msgid "HEROES" msgstr "" msgid "" "TOWNS/\n" "CASTLES" msgstr "" msgid "S" msgstr "" msgid "M" msgstr "" msgid "L" msgstr "" msgid "X-L" msgstr "" msgid "ALL" msgstr "" msgid "SELECT" msgstr "" msgid "" "STANDARD\n" "GAME" msgstr "" msgid "" "BATTLE\n" "ONLY" msgstr "" msgid "" "CAMPAIGN\n" "GAME" msgstr "" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" msgid "CONFIG" msgstr "" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" msgid "HOT SEAT" msgstr "" msgid "2 PLAYERS" msgstr "" msgid "3 PLAYERS" msgstr "" msgid "4 PLAYERS" msgstr "" msgid "5 PLAYERS" msgstr "" msgid "6 PLAYERS" msgstr "" msgid "GIFT" msgstr "" msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "" msgid "VIEW INTRO" msgstr "" msgid "MIN" msgstr "" msgid "RESET" msgstr "" msgid "START" msgstr "" msgid "TOWN" msgstr "" msgid "CASTLE" msgstr "" msgid "RESTRICT" msgstr "" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Lottare" msgid "Builder" msgstr "Costruire" msgid "Explorer" msgstr "Esplorare" msgid "None" msgstr "Nessun/a" msgid "" "A few\n" "%{monster}" msgstr "Pochi/e" msgid "" "Several\n" "%{monster}" msgstr "" "Alcuni/e\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Banda di\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Molti/e\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Orda di\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Una folla di\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Un plotone di\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Un esercito di\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Una legione di\n" "%{monster}" msgid "army|Few" msgstr "Pochi/e" msgid "army|Several" msgstr "Alcuni/e" msgid "army|Pack" msgstr "Banda" msgid "army|Lots" msgstr "Molti/e" msgid "army|Horde" msgstr "Orda" msgid "army|Throng" msgstr "Folla" msgid "army|Swarm" msgstr "Plotone" msgid "army|Zounds" msgstr "Esercito" msgid "army|Legion" msgstr "Legione" msgid "All %{race} troops +1" msgstr "Tutte le forze da %{race}: +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Neutro" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Truppe da 3 fazioni -1" #, fuzzy msgid "Some undead in army -1" msgstr "Dei non-morti nell'esercito -1" msgid "" "Default\n" "troop" msgstr "" msgid "View %{name}" msgstr "Mostra %{name}" #, fuzzy msgid "Move the %{name} " msgstr "Sposta %{name}" msgid "Move or right click to redistribute %{name}" msgstr "Muovi o schiaccia il tasto destro per riposizionare %{name}." msgid "Combine %{name} armies" msgstr "Unisci le truppe di %{name}" msgid "Exchange %{name2} with %{name}" msgstr "Scambia %{name2} con %{name}" msgid "Select %{name}" msgstr "Scegli %{name}" msgid "Cannot move last troop" msgstr "Impossibile spostare l'ultima unità" #, fuzzy msgid "Move the %{name}" msgstr "Sposta %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Tira a %{monster}" #, fuzzy msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "Le unità nemiche sono state dimezzate da %{name}!" msgstr[1] "Le unità nemiche sono state dimezzate da %{name}!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "Colpisce tutti i non-morti nella battaglia." #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "Colpisce tutti i non-morti nella battaglia." #, fuzzy msgid "Spell failed!" msgstr "magia fallita!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Hai già gettato una magia questo round." #, fuzzy msgid "That spell will have no effect!" msgstr "Questa magia non influirà nessuno!" msgid "You may only summon one type of elemental per combat." msgstr "" msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" msgid "Speed: %{speed}" msgstr "Velocità: %{speed}" msgid "Speed" msgstr "Velocità" msgid "Off" msgstr "No" msgid "On" msgstr "Sì" msgid "Turn Order" msgstr "" msgid "Auto Spell Casting" msgstr "" "Lancio Magie\n" "Automatico" msgid "Grid" msgstr "Griglia" msgid "Shadow Movement" msgstr "Movimento Ombra" msgid "Shadow Cursor" msgstr "Cursore Ombra" msgid "Audio" msgstr "" msgid "Settings" msgstr "Impostazioni" msgid "Configure" msgstr "" msgid "Hot Keys" msgstr "" #, fuzzy msgid "Damage Info" msgstr "Danni" msgid "Set the speed of combat actions and animations." msgstr "" msgid "Toggle to display the turn order during the battle." msgstr "" msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" msgid "Change the audio settings of the game." msgstr "Cambia le impostazioni dell'audio del gioco." msgid "Check and configure all the hot keys present in the game." msgstr "" msgid "Toggle to display damage information during the battle." msgstr "" msgid "Exit this menu." msgstr "Lascia questo menù." msgid "Okay" msgstr "Okay" msgid "The enemy has surrendered!" msgstr "Il nemico si è ceduto!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "L'avversario è scappato!" msgid "A glorious victory!" msgstr "Una gloriosa vittoria!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Per valore in combattimento %{name} riceve %{exp} punti d'esperienza." msgid "The cowardly %{name} flees from battle." msgstr "Il vigliacco %{name} si scappa dalla battaglia." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "" #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "Il tuo esercito subisce una sconfitta amara, e %{name} abbandona la tua " "causa." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Il tuo esercito subisce una sconfitta amara." msgid "Battlefield Casualties" msgstr "Vittime in Battaglia" msgid "Attacker" msgstr "Attaccante" msgid "Defender" msgstr "Difensore" #, fuzzy msgid "Click to leave the battle results." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Sei sicuro di voler congedare queste forze?" msgid "Restart" msgstr "" msgid "You have captured an enemy artifact!" msgstr "Hai ottenuto un artefatto nemico!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "" msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" msgid "Necromancy!" msgstr "Negromanzia!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" msgid "%{name} the %{race}" msgstr "%{name}: %{race}" #, fuzzy msgid "Captain of %{name}" msgstr "Mancano delle risorse per %{name}." msgid "Attack" msgstr "Attacco" msgid "Defense" msgstr "Difesa" msgid "Spell Power" msgstr "Potere" msgid "Knowledge" msgstr "Sapere" msgid "Morale" msgstr "Morale" msgid "Luck" msgstr "Fortuna" msgid "Spell Points" msgstr "Pt. Magia" msgid "Hero's Options" msgstr "Opzioni Eroe" msgid "Cast Spell" msgstr "Lancia magia" msgid "Retreat" msgstr "Ritirata" msgid "Surrender" msgstr "Resa" msgid "Cancel" msgstr "Annulla" msgid "Hero Screen" msgstr "Schermata Eroe" #, fuzzy msgid "Captain's Options" msgstr "Opzioni Castello" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" msgid "Open Hero Screen to view full information about the hero." msgstr "" msgid "Return to the battle." msgstr "Torna al combattimento." msgid "Not enough gold (%{gold})" msgstr "Manca dell'oro (%{gold})" msgid "%{name} states:" msgstr "%{name} dichiara:" #, fuzzy msgid "Captain of %{name} states:" msgstr "Mancano delle risorse per %{name}." msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Ti permetterò di arrenderti e ti lascierò passare con le tue truppe per " "%{price} Oro.\"" msgid "View %{monster} info" msgstr "Mostra dettagli su %{monster}" msgid "Fly %{monster} here" msgstr "Fai volare %{monster} qua" msgid "Move %{monster} here" msgstr "Sposta %{monster} qua" msgid "Shoot %{monster}" msgstr "Tira a %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(rimasto 1 colpo)" msgstr[1] "(rimasti %{count} colpi)" msgid "Attack %{monster}" msgstr "Attacca %{monster}" msgid "Turn %{turn}" msgstr "Round %{turn}" msgid "Teleport here" msgstr "Teletrasporta qui" msgid "Invalid teleport destination" msgstr "" msgid "Cast %{spell} on %{monster}" msgstr "Getta %{spell} su %{monster}" msgid "Cast %{spell}" msgstr "Getta %{spell}" msgid "Select spell target" msgstr "Seleziona il bersaglio della magia" msgid "View Ballista info" msgstr "Mostra dettagli sulla Ballista" msgid "Ballista" msgstr "Ballista" #, fuzzy msgid "Automatic combat modes" msgstr "Combattimento Automatico" #, fuzzy msgid "Automatic Combat Modes" msgstr "Combattimento Automatico" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Modifica le opzioni di sistema" msgid "Allows you to customize the combat screen." msgstr "Permette di modificare la schermata del combattimento." msgid "System Options" msgstr "Opzioni Sistema" msgid "Skip this unit" msgstr "Salta questa unità" msgid "Skip" msgstr "Salta" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Salta l'unità attuale. L'unità salta il suo turno senza fare nulla e deve " "aspettare per il prossimo round." #, fuzzy msgid "View Captain's options" msgstr "Mostra opzioni eroe" msgid "View Hero's options" msgstr "Mostra opzioni eroe" #, fuzzy msgid "View opposing Captain" msgstr "Mostra eroe avversario" msgid "View opposing Hero" msgstr "Mostra eroe avversario" msgid "Hide logs" msgstr "Nascondi registro" msgid "Show logs" msgstr "Mostra registro" msgid "Message Bar" msgstr "" msgid "Shows the results of individual monster's actions." msgstr "" #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Sei sicuro di voler fuggire?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Sei sicuro di voler congedare queste forze?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Il computer fa le mossa al posto tuo." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Combattimento Automatico" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Combattimento Automatico" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} salta il suo turno." msgstr[1] "%{name} salta il suo turno." #, fuzzy msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} fanno %{damage} danni." msgstr[1] "%{attacker} fanno %{damage} danni." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 creatura perisce." msgstr[1] "%{count} creature periscono." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} perisce." msgstr[1] "%{count} %{defender} periscono." #, fuzzy msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "Non esistono punti di salvataggio da caricare." msgstr[1] "Non esistono punti di salvataggio da caricare." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "" msgstr[1] "" #, fuzzy msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Spostamento %{monster}: %{src}, %{dst}" #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "La magia non ha funzianto a %{name}!" msgstr[1] "La magia non ha funzianto a %{name}!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} getta %{spell} al gruppo di %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} getta %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "" msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "" msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "" msgid "The %{spell} does %{damage} damage." msgstr "" msgid "The %{spell} does %{damage} damage to one living creature." msgstr "" msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "" #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "%{name} getta %{spell} al gruppo di %{troop}." msgstr[1] "%{name} getta %{spell} al gruppo di %{troop}." #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "%{name} getta %{spell} al gruppo di %{troop}." msgstr[1] "%{name} getta %{spell} al gruppo di %{troop}." #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "%{name} getta %{spell} al gruppo di %{troop}." msgstr[1] "%{name} getta %{spell} al gruppo di %{troop}." msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "" msgstr[1] "" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "%{name} getta %{spell} al gruppo di %{troop}." msgstr[1] "%{name} getta %{spell} al gruppo di %{troop}." #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{name} getta %{spell} al gruppo di %{troop}." msgstr[1] "%{name} getta %{spell} al gruppo di %{troop}." msgid "Bad luck descends on the %{attacker}." msgstr "" msgid "Good luck shines on the %{attacker}." msgstr "La fortuna sorride su %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Il morale alto permette a %{monster} di attaccare ancora." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Per via di morale basso viene saltato il turno di %{monster}." msgid "%{tower} does %{damage} damage." msgstr "%{tower} fa %{damage} punti di danno." msgid "The mirror image is created." msgstr "" msgid "The mirror image is destroyed!" msgstr "" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Sei sicuro di voler fuggire?" msgid "Error" msgstr "" msgid "No spells to cast." msgstr "Nessuna magia da lanciare." msgid "Are you sure you want to retreat?" msgstr "Sei sicuro di voler fuggire?" msgid "Retreat disabled" msgstr "" msgid "Surrender disabled" msgstr "" msgid "Damage: %{max}" msgstr "Danni: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Danni: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Periti: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Periti: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" msgid "Human" msgstr "Umano" msgid "AI" msgstr "Computer" msgid "Start" msgstr "" #, fuzzy msgid "Start the battle." msgstr "Torna al combattimento." msgid "Exit" msgstr "Esci" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Per favore, scegli un altro eroe." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{name1} incontra %{name2}" msgid "Monsters" msgstr "Mostri" msgid "N/A" msgstr "N/D" msgid "Left Turret" msgstr "Torrione Sinistro" msgid "Right Turret" msgstr "Torrione Destro" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "" msgid "each with a +%{attack} bonus to their attack skill." msgstr "" #, fuzzy msgid "The %{name} is destroyed." msgstr "%{name} incrementa il morale delle tue truppe." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "" msgstr[1] "" msgid "Dwarven Alliance" msgstr "" msgid "Sorceress Guild" msgstr "" msgid "Necromancer Guild" msgstr "" msgid "Ogre Alliance" msgstr "" #, fuzzy msgid "Dwarfbane" msgstr "Nano" msgid "Dragon Alliance" msgstr "" msgid "Elven Alliance" msgstr "" msgid "Kraeger defeated" msgstr "" msgid "Wayward Son" msgstr "" msgid "Uncle Ivan" msgstr "" msgid "Annexation" msgstr "" msgid "Force of Arms" msgstr "" msgid "Save the Dwarves" msgstr "" msgid "Carator Mines" msgstr "" msgid "Turning Point" msgstr "" msgid "scenarioName|Defender" msgstr "" msgid "Corlagon's Defense" msgstr "" msgid "The Crown" msgstr "" msgid "The Gauntlet" msgstr "" msgid "Betrayal" msgstr "" msgid "Final Justice" msgstr "" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" msgid "Barbarian Wars" msgstr "" msgid "First Blood" msgstr "" msgid "Necromancers" msgstr "" msgid "Slay the Dwarves" msgstr "" msgid "Country Lords" msgstr "" msgid "Dragon Master" msgstr "" msgid "Rebellion" msgstr "" msgid "Apocalypse" msgstr "" msgid "Greater Glory" msgstr "" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" msgid "Arrow's Flight" msgstr "" msgid "Island of Chaos" msgstr "" msgid "The Abyss" msgstr "" msgid "Uprising" msgstr "" msgid "Aurora Borealis" msgstr "" msgid "Betrayal's End" msgstr "" msgid "Corruption's Heart" msgstr "" msgid "The Giant's Pass" msgstr "" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" msgid "For the good of the Empire, eliminate Kraeger." msgstr "" msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" msgid "Border Towns" msgstr "" msgid "Conquer and Unify" msgstr "" msgid "Crazy Uncle Ivan" msgstr "" msgid "The Wayward Son" msgstr "" msgid "Ivory Gates" msgstr "" msgid "The Elven Lands" msgstr "" msgid "The Epic Battle" msgstr "" msgid "The Southern War" msgstr "" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "" msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" msgid "Fount of Wizardry" msgstr "" msgid "Power's End" msgstr "" msgid "The Eternal Scrolls" msgstr "" msgid "The Shrouded Isles" msgstr "" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" msgid "Blood is Thicker" msgstr "" msgid "King and Country" msgstr "" msgid "Pirate Isles" msgstr "" msgid "Stranded" msgstr "" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" msgid " bane" msgstr "" msgid " alliance" msgstr "" msgid "Carry-over forces" msgstr "" msgid " bonus" msgstr "" msgid " defeated" msgstr "" msgid " will always run away from your army." msgstr "" msgid " will be willing to join your army." msgstr "" msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" msgid "The army will be carried over in the campaign." msgstr "" msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" msgid "%{hero} can be hired during scenarios." msgstr "" msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "" #, fuzzy msgid "campaignBonus|Animate Dead" msgstr "Anima i Morti" #, fuzzy msgid "campaignBonus|Chain Lightning" msgstr "Fulmini in Serie" msgid "campaignBonus|Fireblast" msgstr "" msgid "campaignBonus|Mass Curse" msgstr "" msgid "campaignBonus|Mass Haste" msgstr "" #, fuzzy msgid "campaignBonus|Mirror Image" msgstr "Rispecchia" msgid "campaignBonus|Resurrect" msgstr "" #, fuzzy msgid "campaignBonus|Steelskin" msgstr "La Perla Bianca" msgid "campaignBonus|Summon Earth" msgstr "" #, fuzzy msgid "campaignBonus|View Heroes" msgstr "Mostra Eroi" msgid "campaignBonus|Ballista" msgstr "" #, fuzzy msgid "campaignBonus|Black Pearl" msgstr "La Perla Nera" msgid "campaignBonus|Caster's Bracelet" msgstr "" msgid "campaignBonus|Defender Helm" msgstr "" msgid "campaignBonus|Breastplate" msgstr "" msgid "campaignBonus|Dragon Sword" msgstr "" msgid "campaignBonus|Fizbin Medal" msgstr "" msgid "campaignBonus|Foremost Scroll" msgstr "" #, fuzzy msgid "campaignBonus|Gauntlets" msgstr "La Perla Bianca" msgid "campaignBonus|Hideous Mask" msgstr "" msgid "campaignBonus|Mage's Ring" msgstr "" msgid "campaignBonus|Major Scroll" msgstr "" msgid "campaignBonus|Medal of Honor" msgstr "" #, fuzzy msgid "campaignBonus|Medal of Valor" msgstr "La Medaglia al Valore" msgid "campaignBonus|Minor Scroll" msgstr "" msgid "campaignBonus|Nomad Boots" msgstr "" msgid "campaignBonus|Power Axe" msgstr "" msgid "campaignBonus|Spiked Shield" msgstr "" #, fuzzy msgid "campaignBonus|Stealth Shield" msgstr "Scudo Segreto" msgid "campaignBonus|Tax Lien" msgstr "" msgid "campaignBonus|Thunder Mace" msgstr "" #, fuzzy msgid "campaignBonus|Traveler's Boots" msgstr "Scarpe del viaggiante" #, fuzzy msgid "campaignBonus|White Pearl" msgstr "La Perla Bianca" #, fuzzy msgid "campaignBonus|Basic Archery" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Archery" msgstr "Tiro con L'Arco Avanzato" #, fuzzy msgid "campaignBonus|Expert Archery" msgstr "La Perla Bianca" #, fuzzy msgid "campaignBonus|Basic Ballistics" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Ballistics" msgstr "Balistica Avanzata" #, fuzzy msgid "campaignBonus|Expert Ballistics" msgstr "Balistica Esperta" #, fuzzy msgid "campaignBonus|Basic Diplomacy" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Diplomacy" msgstr "Diplomazia Avanzata" #, fuzzy msgid "campaignBonus|Expert Diplomacy" msgstr "Diplomazia Esperta" #, fuzzy msgid "campaignBonus|Basic Eagle Eye" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Eagle Eye" msgstr "Vista Avanzata" #, fuzzy msgid "campaignBonus|Expert Eagle Eye" msgstr "Vista Esperta" #, fuzzy msgid "campaignBonus|Basic Estates" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Estates" msgstr "Investimenti Avanzati" #, fuzzy msgid "campaignBonus|Expert Estates" msgstr "Mostra Eroi" #, fuzzy msgid "campaignBonus|Basic Leadership" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Leadership" msgstr "Carisma Avanzato" #, fuzzy msgid "campaignBonus|Expert Leadership" msgstr "Carisma Esperto" #, fuzzy msgid "campaignBonus|Basic Logistics" msgstr "Fulmini in Serie" #, fuzzy msgid "campaignBonus|Advanced Logistics" msgstr "Logistica Avanzata" #, fuzzy msgid "campaignBonus|Expert Logistics" msgstr "Logistica Esperta" #, fuzzy msgid "campaignBonus|Basic Luck" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Luck" msgstr "Anima i Morti" #, fuzzy msgid "campaignBonus|Expert Luck" msgstr "La Perla Bianca" #, fuzzy msgid "campaignBonus|Basic Mysticism" msgstr "Misticismo Normale" #, fuzzy msgid "campaignBonus|Advanced Mysticism" msgstr "Misticismo Avanzato" #, fuzzy msgid "campaignBonus|Expert Mysticism" msgstr "Misticismo Esperto" #, fuzzy msgid "campaignBonus|Basic Navigation" msgstr "Fulmini in Serie" #, fuzzy msgid "campaignBonus|Advanced Navigation" msgstr "Navigazione Avanzata" #, fuzzy msgid "campaignBonus|Expert Navigation" msgstr "Navigazione Esperta" #, fuzzy msgid "campaignBonus|Basic Necromancy" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Necromancy" msgstr "Negromanzia Avanzata" #, fuzzy msgid "campaignBonus|Expert Necromancy" msgstr "Negromanzia Esperta" #, fuzzy msgid "campaignBonus|Basic Pathfinding" msgstr "Fulmini in Serie" #, fuzzy msgid "campaignBonus|Advanced Pathfinding" msgstr "Orientamento Avanzato" #, fuzzy msgid "campaignBonus|Expert Pathfinding" msgstr "Orientamento Esperto" #, fuzzy msgid "campaignBonus|Basic Scouting" msgstr "Fulmini in Serie" #, fuzzy msgid "campaignBonus|Advanced Scouting" msgstr "Esplorazione Avanzata" #, fuzzy msgid "campaignBonus|Expert Scouting" msgstr "La Perla Bianca" #, fuzzy msgid "campaignBonus|Basic Wisdom" msgstr "La Perla Nera" #, fuzzy msgid "campaignBonus|Advanced Wisdom" msgstr "Anima i Morti" #, fuzzy msgid "campaignBonus|Expert Wisdom" msgstr "Scudo Segreto" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" msgid "The starting alignment of the scenario will be %{race}." msgstr "" msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" msgid "The main hero will have %{skill} at the start of the scenario." msgstr "" msgid "Roland" msgstr "Rolando" msgid "Archibald" msgstr "" msgid "Price of Loyalty" msgstr "" msgid "Voyage Home" msgstr "" #, fuzzy msgid "Wizard's Isle" msgstr "Mago" #, fuzzy msgid "Descendants" msgstr "Burini" #, fuzzy msgid "Cannot build. You have already built here today." msgstr "Costruzione impossibile. Già costruito qua questo turno." msgid "For this action it is necessary to build a castle first." msgstr "Per fare questo bisogna prima costruire il castello." msgid "The %{building} produces %{monster}." msgstr "Il/la %{building} produce %{monster}." msgid "Requires:" msgstr "Richiede:" msgid "Exit this menu without doing anything." msgstr "Esci dal menù senza far nulla." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "" "Non si può costruire il %{name}. Troppo lontano dall'acqua per costruire il " "%{name}." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Mancano delle risorse per %{name}." #, fuzzy msgid "The %{name} is already built." msgstr "Questo castello ha già %{name}." #, fuzzy msgid "Cannot build the %{name}." msgstr "Impossibile costruire %{name}." msgid "Build %{name}." msgstr "Costruisci %{name}." #, fuzzy msgid "Blackridge" msgstr "Ponte" msgid "Hillstone" msgstr "" msgid "Pinehurst" msgstr "" #, fuzzy msgid "Whiteshield" msgstr "La Perla Bianca" #, fuzzy msgid "Woodhaven" msgstr "Legno" #, fuzzy msgid "Blackwind" msgstr "Fabbro" #, fuzzy msgid "Bloodreign" msgstr "Morale Sangue" #, fuzzy msgid "Dragontooth" msgstr "Drago" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" msgid "Tundara" msgstr "" #, fuzzy msgid "Vulcania" msgstr "Vulcano" msgid "Baywatch" msgstr "" #, fuzzy msgid "Fountainhead" msgstr "Fontana" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" msgid "Sandcaster" msgstr "" msgid "Alamar" msgstr "" #, fuzzy msgid "Burlock" msgstr "Guerriero" #, fuzzy msgid "Dragadune" msgstr "Drago" msgid "Kalindra" msgstr "" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" #, fuzzy msgid "Blackfang" msgstr "Drago Nero" #, fuzzy msgid "New Dawn" msgstr "Nuova Partita" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" #, fuzzy msgid "Antioch" msgstr "Attenzione" msgid "Avalon" msgstr "" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" #, fuzzy msgid "Weed Patch" msgstr "L'Orologio d'Oro" #, fuzzy msgid "Brownston" msgstr "Marrone" #, fuzzy msgid "Hilltop" msgstr "Forte in Collina" msgid "Weddington" msgstr "" msgid "Westfork" msgstr "" msgid "Whittingham" msgstr "" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "" msgid "Roscomon" msgstr "" msgid "Sherman" msgstr "" msgid "Yorksford" msgstr "" #, fuzzy msgid "Blackburn" msgstr "Drago Nero" #, fuzzy msgid "Blacksford" msgstr "Torre Nera" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "" #, fuzzy msgid "Lankershire" msgstr "Carisma" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "" msgid "Troy" msgstr "" msgid "Forder Oaks" msgstr "" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "" #, fuzzy msgid "Willow" msgstr "Giallo" msgid "Corackston" msgstr "" msgid "Sheltemburg" msgstr "" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Reclutamento impossibile. Eroe già presente in questa città." msgid "Cannot recruit - you have too many Heroes." msgstr "Impossibile reclutare - sei al numero massimo di eroi contemporanei." #, fuzzy msgid "Cannot afford a Hero." msgstr "Manca dell'oro per reclutare l'eroe" msgid "There is no room in the garrison for this army." msgstr "La guarnigione non ha posto libero per questa unità." msgid "Fortifications" msgstr "Fortificazioni" msgid "Farm" msgstr "Fattoria" msgid "Thatched Hut" msgstr "Capanna di Paglia" msgid "Archery Range" msgstr "Campo di Tiro" msgid "Upg. Archery Range" msgstr "Migl. Campo di Tiro" msgid "Blacksmith" msgstr "Fabbro" msgid "Upg. Blacksmith" msgstr "Migl. Fabbro" msgid "Armory" msgstr "Armeria" msgid "Upg. Armory" msgstr "Migl. Armeria" msgid "Jousting Arena" msgstr "Arena del Torneo" msgid "Upg. Jousting Arena" msgstr "Migl. Arena Torneo" msgid "Cathedral" msgstr "Cattedrale" msgid "Upg. Cathedral" msgstr "Migl. Cattedrale" msgid "Coliseum" msgstr "Colosseo" msgid "Garbage Heap" msgstr "Mucchio di Rifiuti" msgid "Hut" msgstr "Capanna" msgid "Stick Hut" msgstr "Capanna di Frasche" msgid "Upg. Stick Hut" msgstr "Migl. Cap. Frasche" msgid "Den" msgstr "Antro" msgid "Adobe" msgstr "Casa d'Adobe" msgid "Upg. Adobe" msgstr "Migl. Casa d'Adobe" msgid "Bridge" msgstr "Ponte" msgid "Upg. Bridge" msgstr "Migl. Ponte" msgid "Pyramid" msgstr "Piramide" msgid "Rainbow" msgstr "Arcobaleno" msgid "Crystal Garden" msgstr "Giardino di Cristallo" msgid "Treehouse" msgstr "Casa sugli Alberi" msgid "Cottage" msgstr "Casetta" msgid "Upg. Cottage" msgstr "Migl. Casetta" msgid "Stonehenge" msgstr "Dolmen" msgid "Upg. Stonehenge" msgstr "Migl. Dolmen" msgid "Fenced Meadow" msgstr "Prato Recintato" #, fuzzy msgid "sorceress|Red Tower" msgstr "Torre Rossa" msgid "Dungeon" msgstr "Sotterraneo" msgid "Waterfall" msgstr "Cascata" msgid "Cave" msgstr "Caverna" msgid "Crypt" msgstr "Cripta" msgid "Nest" msgstr "Nido" msgid "Maze" msgstr "Labirinto" msgid "Upg. Maze" msgstr "Migl. Labirinto" msgid "Swamp" msgstr "Palude" msgid "Green Tower" msgstr "Torre Verde" #, fuzzy msgid "warlock|Red Tower" msgstr "Torre Rossa" msgid "Black Tower" msgstr "Torre Nera" msgid "Library" msgstr "Biblioteca" msgid "Orchard" msgstr "Frutteto" msgid "Habitat" msgstr "Habitat" msgid "Pen" msgstr "Recinto" msgid "Foundry" msgstr "Fucina" msgid "Upg. Foundry" msgstr "Migl. Fucina" msgid "Cliff Nest" msgstr "Nido su Scogliera" msgid "Ivory Tower" msgstr "Torre d'Avorio" msgid "Upg. Ivory Tower" msgstr "Migl. Torre Avorio" msgid "Cloud Castle" msgstr "Castello Celeste" msgid "Upg. Cloud Castle" msgstr "Migl. Cast. Cielo" msgid "Storm" msgstr "Tempesta Perpetua" msgid "Skull Pile" msgstr "Pila di Teschi" msgid "Excavation" msgstr "Scavo" msgid "Graveyard" msgstr "Cimitero" msgid "Upg. Graveyard" msgstr "Migl. Cimitero" msgid "Upg. Pyramid" msgstr "Migl. Piramide" msgid "Mansion" msgstr "Magione" msgid "Upg. Mansion" msgstr "Migl. Magione" msgid "Mausoleum" msgstr "Mausoleo" msgid "Upg. Mausoleum" msgstr "Migl. Mausoleo" msgid "Laboratory" msgstr "Laboratorio" msgid "Shrine" msgstr "Altare Oscuro" #, fuzzy msgid "Special" msgstr "Niente particolare" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Frombolieri" #, fuzzy msgid "Dwelling 2" msgstr "Frombolieri" #, fuzzy msgid "Upg. Dwelling 2" msgstr "Frombolieri" #, fuzzy msgid "Dwelling 3" msgstr "Frombolieri" #, fuzzy msgid "Upg. Dwelling 3" msgstr "Frombolieri" #, fuzzy msgid "Dwelling 4" msgstr "Frombolieri" #, fuzzy msgid "Upg. Dwelling 4" msgstr "Frombolieri" #, fuzzy msgid "Dwelling 5" msgstr "Frombolieri" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Frombolieri" #, fuzzy msgid "Dwelling 6" msgstr "Frombolieri" #, fuzzy msgid "Upg. Dwelling 6" msgstr "Frombolieri" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" msgid "The Rainbow increases the luck of the defending units by two." msgstr "" msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" #, fuzzy msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" msgid "Thieves' Guild" msgstr "Lega dei Ladri" msgid "Tavern" msgstr "Taverna" msgid "Shipyard" msgstr "Cantiere Navale" msgid "Well" msgstr "Pozzo" msgid "Statue" msgstr "Statua" msgid "Marketplace" msgstr "Piazza del Mercato" msgid "Moat" msgstr "Fossato" msgid "Castle" msgstr "Castello" msgid "Tent" msgstr "Tenda" msgid "Captain's Quarters" msgstr "Alloggio del Capitano" msgid "Mage Guild, Level 1" msgstr "Lega dei Maghi" msgid "Mage Guild, Level 2" msgstr "Lega dei Maghi, liv. 2" msgid "Mage Guild, Level 3" msgstr "Lega dei Maghi, liv. 3" msgid "Mage Guild, Level 4" msgstr "Lega dei Maghi, liv. 4" msgid "Mage Guild, Level 5" msgstr "Lega dei Maghi, liv. 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "L'Altare Oscuro aumenta la capacità negromantica dei tuoi negromanti di 10 " "percento." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" msgid "The Tavern increases morale for troops defending the castle." msgstr "" msgid "The Shipyard allows ships to be built." msgstr "" msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" msgid "The Right Turret provides extra firepower during castle combat." msgstr "" msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" msgid "Recruit %{name}" msgstr "Recluta %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Mese: %{month}, Sett.: %{week}, Giorno: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" msgid "Click to show next town." msgstr "Clicca per andare alla città succ." msgid "Show next town" msgstr "Va alla città pross." msgid "Click to show previous town." msgstr "Clicca per andare alla città prec." msgid "Show previous town" msgstr "Vai alla città prec." msgid "This town may not be upgraded to a castle." msgstr "" msgid "Town" msgstr "Castello" msgid "Exit Castle" msgstr "Esci dal Castello" msgid "Exit Town" msgstr "Esci dalla Città" msgid "Show Income" msgstr "Mostra Rendita" msgid "View Hero" msgstr "Mostra Eroe" msgid "The above spells are available here." msgstr "Qua sono disponibili queste magie." #, fuzzy msgid "The spells the hero can learn have been added to their book." msgstr "" "Le magie alle quali sodisfi i requisiti sono state aggiunte nel tuo libro." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Una mancia generosa al gestore del bar risulta in questa informazione:" msgid "Recruit Hero" msgstr "Recluta Eroe" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} è un/a %{race} di livello %{value} " msgid "with %{count} artifacts." msgstr "con %{count} artefatti." msgid "with 1 artifact." msgstr "con 1 artefatto." msgid "without artifacts." msgstr "senza artefatti." msgid "Recruit %{name} the %{race}" msgstr "Recluta %{name}: %{race}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" msgid "Spread Formation" msgstr "Formazione sparsa" msgid "Grouped Formation" msgstr "Formazione chiusa" #, fuzzy msgid "Click to show the next town." msgstr "Clicca per andare alla città succ." #, fuzzy msgid "Click to show the previous town." msgstr "Clicca per andare alla città prec." msgid "Set garrison combat formation to 'Spread'" msgstr "" msgid "Set garrison combat formation to 'Grouped'" msgstr "" msgid "Exit Castle Options" msgstr "Esci dal castello" msgid "Castle Options" msgstr "Opzioni Castello" #, fuzzy msgid "Not enough resources to recruit creatures." msgstr "Mancano risorse per comprare truppe." msgid "You are unable to recruit at this time, your ranks are full." msgstr "" #, fuzzy msgid "No creatures available for purchase." msgstr "Niente truppe disponibili da comprare." #, fuzzy msgid "Recruit Creatures" msgstr "Recluta Eroe" #, fuzzy msgid "Hire all creatures in the town." msgstr "Perdi tutti i tuoi eroi e le città." msgid "Max" msgstr "Max" msgid "Available" msgstr "Disponibile" msgid "Town Population Information and Statistics" msgstr "Populazione e Dati della Città" msgid "Damage" msgstr "Danni" msgid "HP" msgstr "PF" msgid "Growth" msgstr "Crescita" msgid "week" msgstr "sett." msgid "View World" msgstr "Mostra Mondo" msgid "View the entire world." msgstr "Fa vedere il mondo intero." msgid "Puzzle" msgstr "Puzzle" msgid "View the obelisk puzzle." msgstr "Mostra il puzzle obelisco." msgid "Scenario Information" msgstr "Informazioni sullo scenario" msgid "View information on the scenario you are currently playing." msgstr "Mostra lo scenario sul quale stai giocando." msgid "Dig for the Ultimate Artifact." msgstr "Scava alla ricerca dell'Estremo Artefatto." msgid "Digging" msgstr "Scavo" msgid "Arena" msgstr "Arena" #, fuzzy msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Entri nell'arena e affronti un branco di leoni feroci. Li sconfiggi, senza " "sforzo, e il pubblico ti applaude. Colpito dalle tue capacità, un allenatore " "di gladiatori attempato acconsente ad allenarti in una dote a scelta tua." msgid "Attack Skill" msgstr "Attacco" msgid "Defense Skill" msgstr "Difesa" msgid "Shots" msgstr "Colpi" msgid "Shots Left" msgstr "Colpi Residui" msgid "Hit Points" msgstr "Pt. Ferita" msgid "Hit Points Left" msgstr "PF Rimasti" msgid "You can't afford to upgrade your troops!" msgstr "" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" msgid "Are you sure you want to dismiss this army?" msgstr "Sei sicuro di voler congedare queste forze?" msgid "Upgrade" msgstr "" msgid "Upgrade your troops." msgstr "" msgid "Dismiss" msgstr "" msgid "Dismiss this army." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Un gruppo di %{monster} con un desiderio di gloria vuole unirsi alla tua " "armata.\n" "Accetti?" msgid "Followers" msgstr "Accoliti" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "Il gruppo di %{monster} è persuaso dalle tue abilità diplomatiche ed offre " "di aggiungersi al tuo esercito per %{gold} pezzi d'oro.\n" "Accetti?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Il gruppo di mostri è persuaso dalla tua capacità diplomatica \n" "e ti offrono questo:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} dei/delle %{total} %{monster} si aggiungeranno al tuo esercito, e " "gli altri ti lasceranno andare per %{gold} pezzi d'oro.\n" "Accetti?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Tutti/e %{offer} %{monster} si aggiungono al tuo esercito per %{gold} pezzi " "d'oro.\n" "Accetti?" msgid "(Rate: %{percent})" msgstr "(Grado: %{percent})" msgid "off" msgstr "Muto" msgid "Music" msgstr "Musica" msgid "Effects" msgstr "Effetti" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "Espansione MIDI" msgid "External" msgstr "Esterna" msgid "Music Type" msgstr "Stile di Musica" msgid "3D Audio" msgstr "" msgid "Toggle ambient music level." msgstr "" msgid "Toggle foreground sounds level." msgstr "" msgid "Change the type of music." msgstr "" msgid "Toggle the 3D effect of foreground sounds." msgstr "" msgid "Build a new ship:" msgstr "Costruisci una nave:" msgid "Resource cost:" msgstr "Costo Risorse:" msgid "Total: " msgstr "Totale: " msgid "Need: " msgstr "Servono: " msgid "New Game" msgstr "Nuova Partita" msgid "Start a single or multi-player game." msgstr "Inizia una partita singola o multigiocatore." msgid "Load Game" msgstr "Carica Partita" msgid "Load a previously saved game." msgstr "Carica una partita salvata." msgid "Save Game" msgstr "Salva Partita" msgid "Save the current game." msgstr "Salva la partita in corso." msgid "Quit" msgstr "Esci" #, fuzzy msgid "Quit out of Heroes of Might and Magic II." msgstr "Esci da fheroes2." msgid "Language" msgstr "Lingua" msgid "Graphics" msgstr "" #, fuzzy msgid "Black & White" msgstr "Ponte" #, fuzzy msgid "Mouse Cursor" msgstr "Cursore Ombra" msgid "Color" msgstr "" #, fuzzy msgid "Text Support" msgstr "" "Tele-\n" "trasporto" msgid "Change the language of the game." msgstr "Cambia la lingua del gioco." msgid "Select Game Language" msgstr "Scegli lingua del gioco" #, fuzzy msgid "Change the graphics settings of the game." msgstr "Cambia le impostazioni dell'audio del gioco." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" msgid "" "Map\n" "Difficulty" msgstr "" "Difficoltà\n" "Mappa" msgid "" "Game\n" "Difficulty" msgstr "" "Difficoltà\n" "Gioco" msgid "Rating" msgstr "Classifica" msgid "Map Size" msgstr "" "Dimensioni\n" "Mappa" msgid "Opponents" msgstr "Avversari" msgid "Class" msgstr "Classe" msgid "" "Victory\n" "Conditions" msgstr "" "Condizioni\n" "Vittoria" msgid "" "Loss\n" "Conditions" msgstr "" "Condizioni\n" "Sconfitta" msgid "First select recipients!" msgstr "Prima scegli destinatari!" msgid "You cannot select %{resource}!" msgstr "Non puoi scegliere %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Tira a %{monster}" msgid "Select Recipients" msgstr "Scegli Destinatari" msgid "Your Funds" msgstr "Le Tue Risorse" msgid "Planned Gift" msgstr "Dono Scelto" msgid "Gift from %{name}" msgstr "Dono da %{name}" msgid "Resolution" msgstr "Risoluzione" msgid "Fullscreen" msgstr "" msgid "window|Mode" msgstr "" msgid "Windowed" msgstr "" msgid "V-Sync" msgstr "" msgid "FPS" msgstr "" #, fuzzy msgid "System Info" msgstr "Opzioni Sistema" msgid "Change the resolution of the game." msgstr "Cambia la risoluzione del gioco." msgid "Select Game Resolution" msgstr "Scegli la risoluzione del gioco" msgid "Toggle between fullscreen and windowed modes." msgstr "" msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" msgid "Show extra information such as FPS and current time." msgstr "" msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" #, fuzzy msgid "Event: " msgstr "Evento" msgid "Hot Keys:" msgstr "" msgid "Hide" msgstr "Nascondi" msgid "Show" msgstr "Mostra" msgid "Interface" msgstr "Interfaccia" msgid "Interface Type" msgstr "Stile d'Interfaccia" msgid "Toggle the type of interface you want to use." msgstr "" msgid "Toggle interface visibility." msgstr "" msgid "Scroll Speed" msgstr "Velocità dello Scorrimento" msgid "Sets the speed at which you scroll the window." msgstr "" msgid "Select Game Language:" msgstr "Scegli la lingua del gioco:" #, fuzzy msgid "Select Language:" msgstr "Scegli la lingua del gioco:" #, fuzzy msgid "Click to choose the selected language." msgstr "Clicca per salvare la partita in corso." msgid "%{name} has gained a level." msgstr "%{name} sale di livello." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Hai appreso %{skill}." #, fuzzy msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "%{name} sale di livello." #, fuzzy msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "Può imparare:" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/d" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Hai davvero fatto un affare. Non ci guadagno nulla su questo. Ti possono " "interessare degli altri articoli?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Ti offro %{count} unità d'oro per 1 unità di %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Ti offro 1 unità di %{resto} per %{count} unità di %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Qtà di scambio" msgid "Trading Post" msgstr "Punto di Scambio" msgid "Your Resources" msgstr "Le Tue Risorse" msgid "Available Trades" msgstr "Scambi disponibili" msgid "guarded by %{count} %{monster}" msgstr "Protetto/a da %{count} %{monster}" msgid "guarded by " msgstr "Protetto/a da " msgid "(available: %{count})" msgstr "(disponibiltà: %{count})" msgid "(empty)" msgstr "(vuoto/a)" msgid "already learned" msgstr "già appreso/a" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Albero del Sapere" #, fuzzy msgid "already claimed" msgstr "già appreso/a" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "già imparato/a" msgid "already has max skills" msgstr "già al massimo dei doti" msgid "(already visited)" msgstr "(già visitato/a)" msgid "(not visited)" msgstr "(non visitato/a)" msgid "%{color} Barrier" msgstr "Barriera %{color}" #, fuzzy msgid "(tent visited)" msgstr "(non visitato/a)" msgid "%{color} Tent" msgstr "Tenda %{color}" msgid "Road" msgstr "Strada" msgid "(digging ok)" msgstr "(scavo possibile)" msgid "(no digging)" msgstr "(scavo impossibile)" msgid "penalty: %{cost}" msgstr "penalità: %{cost}" msgid "Defenders:" msgstr "Difensori:" msgid "Unknown" msgstr "Sconosciuta" msgid "heroQuickInfo|(Level %{level})" msgstr "(Livello %{level})" #, fuzzy msgid "Attack:" msgstr "Attacco" #, fuzzy msgid "Defense:" msgstr "Difesa" #, fuzzy msgid "Spell Power:" msgstr "Potere" #, fuzzy msgid "Knowledge:" msgstr "Sapere" #, fuzzy msgid "Spell Points:" msgstr "Pt. Magia" #, fuzzy msgid "Move Points:" msgstr "Pt. Movim." msgid "Uncharted Territory" msgstr "Terra Ignota" msgid "Cost per troop:" msgstr "" msgid "Available: %{count}" msgstr "Disponibile/i: %{count}" msgid "Number to buy:" msgstr "Quantità:" msgid "Recruit selected monsters." msgstr "" msgid "Select maximum monsters to be recruited." msgstr "" msgid "Select only 1 monster to be recruited." msgstr "" #, fuzzy msgid "Select this game resolution." msgstr "Scegli la risoluzione del gioco" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Scegli la risoluzione del gioco:" msgid "Click to apply the selected resolution." msgstr "" #, fuzzy msgid "Click to apply the entered text." msgstr "Clicca per salvare la partita in corso." msgid "Click to open the Virtual Keyboard dialog." msgstr "" msgid "Open Virtual Keyboard" msgstr "" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "Quante forze spostare?" msgid "Select how many units to separate into:" msgstr "" msgid "Map: " msgstr "Mappa: " msgid "" "\n" "\n" "Month: " msgstr "" msgid ", Week: " msgstr "" msgid ", Day: " msgstr "" msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Percorso: " msgid "Are you sure you want to delete file:" msgstr "Sei sicuro di voler cancellare il file:" msgid "Warning" msgstr "" msgid "Click to save the current game." msgstr "Clicca per salvare la partita in corso." msgid "Click to load a previously saved game." msgstr "Clicca per caricare una partita precedente." msgid "File to Save:" msgstr "File da Salvare:" msgid "File to Load:" msgstr "File da Caricare:" #, fuzzy msgid "Terrain object" msgstr "Nessun oggetto" msgid "Accept the choice made." msgstr "Accetta la scelta." msgid "Select Skill:" msgstr "Scegli dote:" msgid "Select Spell:" msgstr "Scegli magia:" msgid "Select Artifact:" msgstr "Scegli artefatto:" msgid "Select Monster:" msgstr "Scegli mostro:" msgid "Select Hero:" msgstr "Scegli eroe:" msgid "race|Random" msgstr "Casuale" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "%{color} %{race}" msgstr "Giocatore %{color}" msgid "You will place" msgstr "" #, fuzzy msgid "Click to select this class." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "Click to select this color." msgstr "Clicca per andare alla città succ." #, fuzzy msgid "Select Treasure:" msgstr "Scegli eroe:" #, fuzzy msgid "Select Ocean Object:" msgstr "Scegli artefatto:" #, fuzzy msgid "Castle/town placing" msgstr "Opzioni Castello" msgid "doubleLinedRace|Neutral" msgstr "Neutro" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "Click to select town placing." msgstr "Clicca per andare alla città succ." #, fuzzy msgid "Click to select castle placing." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "Giocatore %{color}" msgid "race|Neutral" msgstr "Neutro" #, fuzzy msgid "Select Dwelling:" msgstr "Scegli magia:" #, fuzzy msgid "Select Landscape Object:" msgstr "Scegli artefatto:" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "Risorso" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name}: %{race}" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" #, fuzzy msgid "Select Mountain Object:" msgstr "Scegli artefatto:" #, fuzzy msgid "Select Rock Object:" msgstr "Scegli artefatto:" #, fuzzy msgid "Select Tree Object:" msgstr "Scegli artefatto:" #, fuzzy msgid "Select Power Up Object:" msgstr "Scegli artefatto:" #, fuzzy msgid "Select Adventure Object:" msgstr "Scegli artefatto:" msgid "Players Icon" msgstr "Icona dei Giocatori" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Indica quanti giocatori vi sono in totale nello scenario. Ogni posizione non " "occupata da umani sarà occupata da giocatori computer." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Indica se la mappa è\n" "piccola (36 x 36), media\n" "(72 x 72), grande (108 x 108), o\n" "XL (114 x 114)." msgid "Size Icon" msgstr "Icona del Dimensione" msgid "Map Type" msgstr "Tipo di mappa" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Indica se la mappa è stata creata per la versione del gioco Guerre di " "Successione o The Price of Loyalty." #, fuzzy msgid "Map Type:\n" msgstr "Tipo di mappa" msgid "The Succession Wars" msgstr "" msgid "The Price of Loyalty" msgstr "" #, fuzzy msgid "Resurrection" msgstr "Risorgi" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Lingua" msgid "Lose all your heroes and towns." msgstr "Perdi tutti i tuoi eroi e le città." msgid "Lose a specific town." msgstr "Perdi una città specifica." msgid "Lose a specific hero." msgstr "Perdi un eroe specifico." msgid "Run out of time. Fail to win by a certain point." msgstr "Vai fuori tempo. Non riuscire a vincere entro un certo tempo." msgid "Loss Condition" msgstr "Condizione Sconfitta" msgid "Defeat all enemy heroes and towns." msgstr "Sconfiggi tutti gli eroi e città nemiche." msgid "Capture a specific town." msgstr "Cattura una città specifica." msgid "Defeat a specific hero." msgstr "Sconfiggi un eroe specifico." msgid "Find a specific artifact." msgstr "Trova un dato artefatto." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "La tua alleanza sconfigge quella avversaria." msgid "Accumulate a large amount of gold." msgstr "Accumula una grande quantità d'oro." msgid "Victory Condition" msgstr "Condizione Vittoria" msgid "Map difficulty:" msgstr "Difficoltà mappa:" msgid "N" msgstr "" #, fuzzy msgid "No maps exist at that size." msgstr "Non esistono mappe di quella dimensione" msgid "Small Maps" msgstr "Mappe Piccole" msgid "View only maps of size small (36 x 36)." msgstr "Mostra solo le mappe piccole (36 x 36)." msgid "Medium Maps" msgstr "Mappe Medie" msgid "View only maps of size medium (72 x 72)." msgstr "Mostra solo le mappe medie (72 x 72)." msgid "Large Maps" msgstr "Mappe Grandi" msgid "View only maps of size large (108 x 108)." msgstr "Mostra solo le mappe grandi (108 x 108)." msgid "Extra Large Maps" msgstr "Mappe XL" msgid "View only maps of size extra large (144 x 144)." msgstr "Mostra solo mappe XL (144 x 144)." msgid "All Maps" msgstr "Tutte le Mappe" msgid "View all maps, regardless of size." msgstr "Mostra tutte le mappe, indipendentemente dalla dimensione." msgid "Selected Name" msgstr "Nome della Mappa" msgid "The name of the currently selected map." msgstr "Il nome della mappa scelta attualmente." msgid "Selected Map Difficulty" msgstr "Difficoltà della Mappa Scelta" #, fuzzy msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "La difficoltà della mappa scelta attualmente. La difficoltà della mappa è " "data dallo scenario. Mappe più difficili includono più nemici (o più forti), " "meno risorse oppure altre condizioni speciali che rendono la partita più " "dura all'umano." msgid "Selected Description" msgstr "Descrizione scelta" msgid "The description of the currently selected map." msgstr "La descrizione della mappa scelta attualmente." msgid "Jump" msgstr "Salta" msgid "Hero Speed" msgstr "Velocità dell'Eroe" msgid "Don't Show" msgstr "Nascondi" msgid "Enemy Speed" msgstr "Velocità Nemica" msgid "Auto Resolve" msgstr "Auto-Risolva" msgid "Auto, No Spells" msgstr "Auto, Senza Magie" msgid "Battles" msgstr "Battaglie" #, fuzzy msgid "combatMode|Manual" msgstr "Manuali" msgid "Change the speed at which your heroes move on the main screen." msgstr "" msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" #, fuzzy msgid "Change the interface settings of the game." msgstr "Cambia le impostazioni dell'audio del gioco." #, fuzzy msgid "Interface Settings" msgstr "Impostazioni del gioco." msgid "Toggle instant battle mode." msgstr "" msgid "Att." msgstr "Att." msgid "Def." msgstr "Dif." msgid "Power" msgstr "Potere" msgid "Knowl" msgstr "Sapere" msgid "1st" msgstr "Primo" msgid "2nd" msgstr "Secondo" msgid "3rd" msgstr "Terzo" msgid "4th" msgstr "Quarto" msgid "5th" msgstr "Quinto" msgid "6th" msgstr "Sesto" msgid "Oracle: Player Rankings" msgstr "Tempio: Graduatoria Giocatori" msgid "Thieves' Guild: Player Rankings" msgstr "Lega dei Ladri: Graduatoria" msgid "Number of Towns:" msgstr "Numero di Città:" msgid "Number of Castles:" msgstr "Numero di Castelli:" msgid "Number of Heroes:" msgstr "Numero di Eroi:" msgid "Gold in Treasury:" msgstr "Oro nei Forzieri:" msgid "Wood & Ore:" msgstr "Legname e Ferro:" msgid "Gems, Cr, Slf & Mer:" msgstr "Gem, Cr, Zlf e Merc:" msgid "Obelisks Found:" msgstr "Obelischi Trovati:" msgid "Artifacts:" msgstr "Artefatti:" msgid "Total Army Strength:" msgstr "Forza Totale Esercito:" msgid "Income:" msgstr "Rendita:" msgid "Best Hero:" msgstr "Miglior Eroe:" msgid "Best Hero Stats:" msgstr "Dati Miglior Eroe:" msgid "Personality:" msgstr "Ruolo:" msgid "Best Monster:" msgstr "Miglior Mostro:" #, fuzzy msgid "Random Castle Name" msgstr "Castello casuale" #, fuzzy msgid "Random Town Name" msgstr "Città casuale" #, fuzzy msgid "Allow Castle build" msgstr "Castello Celeste" #, fuzzy msgid "Default Buildings" msgstr "Frombolieri" msgid "Default Army" msgstr "" #, fuzzy msgid "Castle Army" msgstr "Castello" #, fuzzy msgid "Town Army" msgstr "Castello" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Esci dal Castello" msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" msgid "Message Text:" msgstr "" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" msgid "Message:" msgstr "" #, fuzzy msgid "Click to save the Event properties." msgstr "Clicca per salvare la partita in corso." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "Risorso" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Clicca per salvare la partita in corso." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Giorno: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "Add Event" msgstr "Evento" msgid "Add an additional event." msgstr "" #, fuzzy msgid "Edit Event" msgstr "Evento" msgid "Edit an existing event." msgstr "" msgid "Delete Event" msgstr "" msgid "Delete an existing event." msgstr "" #, fuzzy msgid "Effects:" msgstr "Effetti" #, fuzzy msgid "Conditions:" msgstr "" "Condizioni\n" "Sconfitta" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "Sperimentale" msgid "Artifact" msgstr "Artefatto" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Scegli artefatto:" msgid "Delete an artifact from the event." msgstr "" msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Scegli dote:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Opzioni Avventura" msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" #, fuzzy msgid "%{objects} must be placed on water." msgstr "Opzioni Avventura" msgid "Objects cannot be placed outside the map." msgstr "" #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Opzioni Avventura" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Sei sicuro di voler cominciare una nuova partita? (La partita attuale andrà " "perduta.)" msgid "Editor" msgstr "" #, fuzzy msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Sei sicuro di voler cominciare una nuova partita? (La partita attuale andrà " "perduta.)" #, fuzzy msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Sei sicuro di voler cominciare una nuova partita? (La partita attuale andrà " "perduta.)" msgid "" "MAIN\n" "MENU" msgstr "" msgid "" "START\n" "MAP" msgstr "" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Sei sicuro di voler cominciare una nuova partita? (La partita attuale andrà " "perduta.)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Salva Partita" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Sei sicuro di voler cominciare una nuova partita? (La partita attuale andrà " "perduta.)" msgid "Create a new map from scratch." msgstr "" #, fuzzy msgid "New Map" msgstr "Nuova Partita" #, fuzzy msgid "Load Map" msgstr "Carica Partita" msgid "Load an existing map." msgstr "" #, fuzzy msgid "Save Map" msgstr "Salva Partita" #, fuzzy msgid "Save the current map." msgstr "Salva la partita in corso." msgid "Quit out of the map editor." msgstr "" #, fuzzy msgid "Return to the game's Main Menu." msgstr "Torna al combattimento." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Artefatto estremo casuale" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "con 1 artefatto." msgid "The total number of obelisks is %{count}." msgstr "" #, fuzzy msgid "Roads" msgstr "Strada" msgid "Streams" msgstr "" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "" msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Non esistono punti di salvataggio da caricare." msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "" #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "File da Salvare:" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Sei sicuro di voler sovrascrivere il salvataggio di questo nome?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "File da Salvare:" msgid "Used to place %{object}." msgstr "" #, fuzzy msgid "Select object type" msgstr "Scegli artefatto:" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Clicca per andare alla città succ." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Per favore, scegli un altro eroe." msgid "" "Cell\n" "Details" msgstr "" msgid "Erase" msgstr "" msgid "Mountains" msgstr "Montagne" #, fuzzy msgid "Rocks" msgstr "Roccia" msgid "Trees" msgstr "Alberi" #, fuzzy msgid "Water Objects" msgstr "Terra sterile" #, fuzzy msgid "Miscellaneous" msgstr "Fineo" msgid "Artifacts" msgstr "Artefatti" #, fuzzy msgid "Dwellings" msgstr "Frombolieri" msgid "Mines" msgstr "Miniere" #, fuzzy msgid "Power-ups" msgstr "Potere" #, fuzzy msgid "Treasures" msgstr "Tesoro" msgid "Heroes" msgstr "Eroi" #, fuzzy msgid "Towns" msgstr "Castello" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Scegli artefatto:" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" #, fuzzy msgid "Small Brush" msgstr "Mappe Piccole" #, fuzzy msgid "Medium Brush" msgstr "Mappe Medie" #, fuzzy msgid "Large Brush" msgstr "Mappe Grandi" msgid "Area Fill" msgstr "" msgid "Used to click and drag for filling in large areas." msgstr "" msgid "Clear Area" msgstr "" msgid "Used to click and drag for clearing large areas." msgstr "" msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" msgid "Traversable only by boat." msgstr "" msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" #, fuzzy msgid "Used for special editing of action objects." msgstr "Sconfiggi tutti gli eroi e città nemiche." #, fuzzy msgid "Adventure Objects Mode" msgstr "Opzioni Avventura" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" #, fuzzy msgid "Kingdom Objects Mode" msgstr "Rendita" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "Mostri" msgid "Used to place monsters on the map." msgstr "" msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" #, fuzzy msgid "Road Mode" msgstr "Strada" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" #, fuzzy msgid "Specifications" msgstr "Pietrificazione" msgid "File Options" msgstr "Opzioni File" #, fuzzy msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "Mostra il menù file che ti permette di caricare, salvare ecc.." #, fuzzy msgid "View the editor system options, which let you customize the editor." msgstr "" "Mostra il menù di opzioni per il sistema per modificare l'esperienza del " "gioco." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" msgid "Cancel back to the New Map menu." msgstr "" msgid "Cancel back to the main menu." msgstr "" msgid "From Scratch" msgstr "" msgid "Start from scratch with a blank map." msgstr "" msgid "Create a randomly generated map." msgstr "" #, fuzzy msgid "Random" msgstr "Casuale" msgid "Cancel back to the Map Editor main menu." msgstr "" msgid "No maps available!" msgstr "" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "Giocatore %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{name1} incontra %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "Giocatore %{color}" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "Giocatore %{color}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{name1} incontra %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{name1} incontra %{name2}" #, fuzzy msgid "None." msgstr "Nessun/a" #, fuzzy msgid "One side defeats another." msgstr "Per favore, scegli un altro eroe." #, fuzzy msgid "Accumulate gold." msgstr "Accumula una grande quantità d'oro." msgid "Run out of time." msgstr "" #, fuzzy msgid "alliance|1st" msgstr "Ballista" msgid "alliance|2nd" msgstr "" msgid "alliance|3rd" msgstr "" msgid "alliance|4th" msgstr "" msgid "alliance|5th" msgstr "" #, fuzzy msgid "Special Loss Condition" msgstr "Condizione Sconfitta" #, fuzzy msgid "Special Victory Condition" msgstr "Condizione Vittoria" #, fuzzy msgid "Allow standard victory conditions" msgstr "Condizione Vittoria" msgid "Allow this condition also for AI" msgstr "" msgid "Set alliances:" msgstr "" # msgid "{%number} alliance: " msgstr "" #, fuzzy msgid "Gold:" msgstr "Oro" msgid "Select a Town to capture to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Clicca per salvare la partita in corso." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Clicca per salvare la partita in corso." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Clicca per salvare la partita in corso." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "Map Difficulty" msgstr "" "Difficoltà\n" "Mappa" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "Percorso: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Descrizione scelta" #, fuzzy msgid "Click to accept the changes made." msgstr "Clicca per andare alla città succ." #, fuzzy msgid "Click to edit custom rumors." msgstr "Clicca per salvare la partita in corso." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Clicca per salvare la partita in corso." #, fuzzy msgid "Events" msgstr "Evento" #, fuzzy msgid "Click to change the language of the map." msgstr "Cambia la lingua del gioco." #, fuzzy msgid "Click to change your map name." msgstr "Clicca per andare alla città succ." #, fuzzy msgid "Map Name" msgstr "" "Dimensioni\n" "Mappa" #, fuzzy msgid "Click to change the description of the current map." msgstr "La descrizione della mappa scelta attualmente." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "La descrizione della mappa scelta attualmente." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "La descrizione della mappa scelta attualmente." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Tipo di mappa" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "La difficoltà della mappa scelta attualmente. La difficoltà della mappa è " "data dallo scenario. Mappe più difficili includono più nemici (o più forti), " "meno risorse oppure altre condizioni speciali che rendono la partita più " "dura all'umano." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Scegli quantità di %{resource}:" #, fuzzy msgid "Animation" msgstr "Navigazione" #, fuzzy msgid "Passability" msgstr "Ruolo:" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Clicca per salvare la partita in corso." msgid "Add Rumor" msgstr "" msgid "Add an additional rumor." msgstr "" msgid "Edit Rumor" msgstr "" msgid "Edit an existing rumor." msgstr "" msgid "Delete Rumor" msgstr "" msgid "Delete an existing rumor." msgstr "" msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Percorso: " #, fuzzy msgid "Save Map:" msgstr "Salva Partita" #, fuzzy msgid "Click to save the current map." msgstr "Clicca per salvare la partita in corso." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Clicca per salvare la partita in corso." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Facile" msgid "difficulty|Normal" msgstr "Normale" msgid "difficulty|Hard" msgstr "Duro" msgid "difficulty|Expert" msgstr "Esperto" msgid "difficulty|Impossible" msgstr "Impossibile" msgid "and more..." msgstr "" msgid "Easy" msgstr "" #, fuzzy msgid "Normal" msgstr "Normale" msgid "Hard" msgstr "" #, fuzzy msgid "Campaign Difficulty" msgstr "Difficoltà Gioco" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" #, fuzzy msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "Complimenti!" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" msgid "Start the selected scenario." msgstr "" #, fuzzy msgid "View Intro" msgstr "Mostra Eroe" msgid "View the intro video for the current state of the campaign." msgstr "" msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" #, fuzzy msgid "Restart the current scenario." msgstr "Salva la partita in corso." #, fuzzy msgid "Difficulty" msgstr "" "Difficoltà\n" "Mappa" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" msgid "Are you sure you want to restart this scenario?" msgstr "Sei sicuro di voler ricominciare questo scenario?" msgid "Campaign Scenario loading failure" msgstr "" msgid "Please make sure that campaign files are correct and present." msgstr "" msgid "Days spent" msgstr "" msgid "The number of days spent on this campaign." msgstr "" msgid "Project Coordination and Core Development" msgstr "" msgid "Development" msgstr "" msgid "Visit us at " msgstr "" msgid "QA and Support" msgstr "" #, fuzzy msgid "Dev and Support" msgstr "" "Tele-\n" "trasporto" msgid "Special Thanks to" msgstr "" msgid "and many-many other contributors and supporters!" msgstr "" msgid "Support us at" msgstr "" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "" msgid "Original project before 0.7" msgstr "" #, fuzzy msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Esci da fheroes2." msgid "Designed and Directed" msgstr "" msgid "Programming and Design" msgstr "" msgid "Executive Producer" msgstr "" msgid "Producer" msgstr "" msgid "Additional Design" msgstr "" msgid "Additional Programming" msgstr "" msgid "Musical Production" msgstr "" msgid "Music and Sound Design" msgstr "" msgid "Vocalists" msgstr "" msgid "Art Director" msgstr "" msgid "Assistant Art Director" msgstr "" msgid "Artists" msgstr "" msgid "QA Manager" msgstr "" msgid "QA" msgstr "" msgid "Writing" msgstr "" msgid "Manual and Helpfile" msgstr "" msgid "Scenarios" msgstr "" #, fuzzy msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Esci da fheroes2." msgid "Design Lead" msgstr "" msgid "Designers" msgstr "" msgid "Programming Lead" msgstr "" msgid "Art Lead" msgstr "" #, fuzzy msgid "Playtesters" msgstr "Icona dei Giocatori" msgid "Designer" msgstr "" msgid "Producers" msgstr "" #, fuzzy msgid "QA Managers" msgstr "Cacciatori" msgid "Sound Design" msgstr "" #, fuzzy msgid "Town Themes" msgstr "Alle Porte" msgid "Alto Sax" msgstr "" msgid "Harpsichord and Piano" msgstr "" msgid "Basso Vocal" msgstr "" msgid "Soprano Vocal" msgstr "" msgid "Recorded at %{recordingStudio}" msgstr "" msgid "credits|Manual" msgstr "Manuale" msgid "German Consultant" msgstr "" msgid "Map Designers" msgstr "" msgid "Package Design" msgstr "" msgid "High Scores" msgstr "Classifiche" msgid "Your Name" msgstr "" msgid "Unknown Hero" msgstr "" msgid "Standard" msgstr "" msgid "View High Scores for Standard Maps." msgstr "" msgid "Campaign" msgstr "" msgid "View High Scores for Campaigns." msgstr "" msgid "hotkey|default okay event" msgstr "" msgid "hotkey|default cancel event" msgstr "" msgid "hotkey|default left" msgstr "" msgid "hotkey|default right" msgstr "" msgid "hotkey|default up" msgstr "" msgid "hotkey|default down" msgstr "" msgid "hotkey|toggle fullscreen" msgstr "" msgid "hotkey|toggle text support mode" msgstr "" msgid "hotkey|toggle developer mode" msgstr "" msgid "hotkey|new game" msgstr "" msgid "hotkey|load game" msgstr "" #, fuzzy msgid "hotkey|high scores" msgstr "Classifiche" msgid "hotkey|credits" msgstr "" msgid "hotkey|standard game" msgstr "" msgid "hotkey|campaign game" msgstr "" #, fuzzy msgid "hotkey|multi-player game" msgstr "Inizia una partita singola o multigiocatore." #, fuzzy msgid "hotkey|settings" msgstr "Impostazioni" msgid "hotkey|quit" msgstr "" msgid "hotkey|select map" msgstr "" msgid "hotkey|select small map size" msgstr "" msgid "hotkey|select medium map size" msgstr "" msgid "hotkey|select large map size" msgstr "" msgid "hotkey|select extra large map size" msgstr "" msgid "hotkey|select all map sizes" msgstr "" #, fuzzy msgid "hotkey|hot seat game" msgstr "Inizia una partita singola o multigiocatore." msgid "hotkey|battle only game" msgstr "" msgid "hotkey|choose the original campaign" msgstr "" msgid "hotkey|choose the expansion campaign" msgstr "" msgid "hotkey|map editor main menu" msgstr "" #, fuzzy msgid "hotkey|new map menu" msgstr "Mostra eroe successivo" msgid "hotkey|load map menu" msgstr "" msgid "hotkey|new map from scratch" msgstr "" #, fuzzy msgid "hotkey|new random map" msgstr "Sommario Regno" #, fuzzy msgid "hotkey|undo last action" msgstr "Va alla città pross." #, fuzzy msgid "hotkey|redo last action" msgstr "Va alla città pross." #, fuzzy msgid "hotkey|open game main menu" msgstr "Mostra eroe successivo" msgid "hotkey|toggle passability" msgstr "" msgid "hotkey|roland campaign" msgstr "" msgid "hotkey|archibald campaign" msgstr "" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "Va alla città pross." msgid "hotkey|voyage home campaign" msgstr "" msgid "hotkey|wizard's isle campaign" msgstr "" msgid "hotkey|descendants campaign" msgstr "" msgid "hotkey|select first campaign bonus" msgstr "" msgid "hotkey|select second campaign bonus" msgstr "" msgid "hotkey|select third campaign bonus" msgstr "" msgid "hotkey|view campaign intro" msgstr "" #, fuzzy msgid "hotkey|select campaign difficulty" msgstr "Difficoltà Gioco" msgid "hotkey|restart campaign scenario" msgstr "" msgid "hotkey|world map left" msgstr "" msgid "hotkey|world map right" msgstr "" msgid "hotkey|world map up" msgstr "" msgid "hotkey|world map down" msgstr "" msgid "hotkey|world map up left" msgstr "" msgid "hotkey|world map up right" msgstr "" msgid "hotkey|world map down left" msgstr "" msgid "hotkey|world map down right" msgstr "" msgid "hotkey|save game" msgstr "" #, fuzzy msgid "hotkey|next hero" msgstr "Mostra eroe successivo" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "Mostra eroe successivo" #, fuzzy msgid "hotkey|start hero movement" msgstr "Continua spostamento" #, fuzzy msgid "hotkey|cast adventure spell" msgstr "Lancia una magia avventura." msgid "hotkey|put hero to sleep" msgstr "" #, fuzzy msgid "hotkey|next town" msgstr "Va alla città pross." msgid "hotkey|end turn" msgstr "" #, fuzzy msgid "hotkey|file options" msgstr "Opzioni File" #, fuzzy msgid "hotkey|adventure options" msgstr "Opzioni Avventura" msgid "hotkey|puzzle map" msgstr "" #, fuzzy msgid "hotkey|scenario information" msgstr "Informazioni sullo scenario" msgid "hotkey|dig for artifact" msgstr "" msgid "hotkey|view world" msgstr "" #, fuzzy msgid "hotkey|kingdom summary" msgstr "Sommario Regno" msgid "hotkey|default action" msgstr "" msgid "hotkey|open focus" msgstr "" #, fuzzy msgid "hotkey|system options" msgstr "Modifica le opzioni di sistema" msgid "hotkey|scroll left" msgstr "" msgid "hotkey|scroll right" msgstr "" msgid "hotkey|scroll up" msgstr "" msgid "hotkey|scroll down" msgstr "" msgid "hotkey|toggle control panel" msgstr "" msgid "hotkey|toggle radar" msgstr "" msgid "hotkey|toggle buttons" msgstr "" msgid "hotkey|toggle status" msgstr "" msgid "hotkey|toggle icons" msgstr "" msgid "hotkey|transfer control to ai" msgstr "" msgid "hotkey|retreat from battle" msgstr "" msgid "hotkey|surrender during battle" msgstr "" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Mostra eroe successivo" msgid "hotkey|quick combat" msgstr "" #, fuzzy msgid "hotkey|battle options" msgstr "Opzioni Castello" msgid "hotkey|skip turn in battle" msgstr "" msgid "hotkey|cast battle spell" msgstr "" msgid "hotkey|dwelling level 1" msgstr "" msgid "hotkey|dwelling level 2" msgstr "" msgid "hotkey|dwelling level 3" msgstr "" msgid "hotkey|dwelling level 4" msgstr "" msgid "hotkey|dwelling level 5" msgstr "" msgid "hotkey|dwelling level 6" msgstr "" msgid "hotkey|well" msgstr "" #, fuzzy msgid "hotkey|marketplace" msgstr "Piazza del Mercato" msgid "hotkey|mage guild" msgstr "" #, fuzzy msgid "hotkey|shipyard" msgstr "Cantiere Navale" #, fuzzy msgid "hotkey|thieves guild" msgstr "Lega dei Ladri" msgid "hotkey|tavern" msgstr "" msgid "hotkey|construction screen" msgstr "" msgid "hotkey|buy all monsters in well" msgstr "" msgid "hotkey|split stack by half" msgstr "" msgid "hotkey|split stack by one" msgstr "" msgid "hotkey|join stacks" msgstr "" msgid "hotkey|upgrade troop" msgstr "" msgid "hotkey|dismiss hero or troop" msgstr "" #, fuzzy msgid "hotkey|exchange all troops" msgstr "Mostra eroe successivo" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" msgid "Default Actions" msgstr "" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Mappa mondiale" #, fuzzy msgid "Battle Screen" msgstr "Schermata Eroe" #, fuzzy msgid "Town Screen" msgstr "Schermata Eroe" msgid "Army Actions" msgstr "" #, fuzzy msgid "The save file is corrupted." msgstr "Non esistono punti di salvataggio da caricare." msgid "Unsupported save format: " msgstr "" msgid "Current game version: " msgstr "" msgid "Last supported version: " msgstr "" msgid "This file contains a save with an invalid game type." msgstr "" msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" msgid "This saved game is localized to '" msgstr "" msgid "' language, but the current language of the game is '" msgstr "" msgid "No save files to load." msgstr "Non esistono punti di salvataggio da caricare." msgid "Hot Seat" msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "A single player game playing out a single map." msgstr "" msgid "Standard Game" msgstr "" msgid "A single player game playing through a series of maps." msgstr "" msgid "Campaign Game" msgstr "" msgid "Multi-Player Game" msgstr "" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" msgid "fheroes2 Resurrection Team presents" msgstr "Il Team di fheroes2 Resurrection presenta" #, fuzzy msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Benvenuti a fheroes2! Gentilmente, prima di cominciare il gioco scegli una " "risoluzione per il gioco." msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Benvenuti a fheroes2! Gentilmente, prima di cominciare il gioco scegli una " "risoluzione per il gioco." msgid "Greetings!" msgstr "Saluti!" #, fuzzy msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "Lascia fheroes2." msgid "Credits" msgstr "Titoli di coda" msgid "View the credits screen." msgstr "Mostra titoli di coda." msgid "View the high scores screen." msgstr "Vedi i migliori punteggi." msgid "Create new or modify existing maps." msgstr "" #, fuzzy msgid "Change language, resolution and settings of the game." msgstr "Cambia la risoluzione del gioco." #, fuzzy msgid "Game Settings" msgstr "Impostazioni del gioco." msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" #, fuzzy msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "O la campagna di Rolando or quella di Arcibaldo dal gioco originale di " "Heroes of Might and Magic II." msgid "Original Campaign" msgstr "Campagna Originale" msgid "Expansion Campaign" msgstr "Campagna Espansione" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" "Una delle quattro nuove campagne dalla espansione 'The Price of Loyalty\"." msgid "Loading video. Please wait..." msgstr "" msgid "Host" msgstr "" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" msgid "Guest" msgstr "" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" msgid "Battle Only" msgstr "" msgid "Setup and play a battle without loading any map." msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "2 Players" msgstr "" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" msgid "3 Players" msgstr "" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" msgid "4 Players" msgstr "" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" msgid "5 Players" msgstr "" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" msgid "6 Players" msgstr "" msgid "Play with 6 human players." msgstr "" msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" msgid "Ultimate Artifact" msgstr "" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" msgid "Victory!" msgstr "" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" msgid "You have been eliminated from the game!!!" msgstr "Sei stato eliminato dal gioco!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" msgid "Defeat!" msgstr "" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Sconfiggi tutti gli eroi nemici e cattura tutte le città e i castelli nemici." msgid "Your side defeats the opposing side." msgstr "La tua alleanza sconfigge quella avversaria." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" #, fuzzy msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "La tua alleanza sconfigge quella avversaria." msgstr[1] "La tua alleanza sconfigge quella avversaria." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" msgstr[1] "" msgid "Capture the castle '%{name}'." msgstr "" msgid "Capture the town '%{name}'." msgstr "" msgid "Defeat the hero '%{name}'." msgstr "" msgid "Find the ultimate artifact." msgstr "" msgid "Find the '%{name}' artifact." msgstr "" msgid "Accumulate %{count} gold." msgstr "" msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" msgid "Lose the castle '%{name}'." msgstr "" msgid "Lose the town '%{name}'." msgstr "" msgid "Lose the hero: %{name}." msgstr "" msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" msgid "%{color} player has been vanquished!" msgstr "Giocatore %{color} è stato sconfitto!" msgid "Major Event!" msgstr "" msgid "Scenario:" msgstr "Scenario:" msgid "Game Difficulty:" msgstr "Difficoltà Partita:" msgid "Opponents:" msgstr "Avversari:" msgid "Class:" msgstr "Classe:" msgid "Rating %{rating}%" msgstr "Punteggio %{rating}%" msgid "Click here to select which scenario to play." msgstr "" msgid "Scenario" msgstr "Scenario" msgid "Game Difficulty" msgstr "Difficoltà Gioco" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" msgid "Difficulty Rating" msgstr "Grado di Difficoltà" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" msgid "Click to accept these settings and start a new game." msgstr "" msgid "Click to return to the main menu." msgstr "" msgid "Astrologers proclaim the Month of the %{name}." msgstr "Gli Astrologi prevedono il mese di %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Gli Astrologi prevedono la settimana di %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" "Dopo un periodo di crescita normale, la populazione di %{monster} si " "raddoppia!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Dopo un periodo di crescita normale, la populazione di %{monster} incrementa " "di %{count} percento!" msgstr[1] "" "Dopo un periodo di crescita normale, la populazione di %{monster} incrementa " "di %{count} percento!" msgid "%{monster} growth +%{count}." msgstr "Crescita %{monster} +%{count}." msgid " All populations are halved." msgstr "Tutte le populazioni dimezzate." msgid " All dwellings increase population." msgstr "Cresce il numero di truppe disponibili di ogni dimora." msgid "New Month!" msgstr "" msgid "New Week!" msgstr "" msgid "Beware!" msgstr "" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" msgid "%{color} player's turn." msgstr "Turno di giocatore %{color}" msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" msgid "Lord Kilburn" msgstr "" msgid "Tsabu" msgstr "" #, fuzzy msgid "Sir Galant" msgstr "Guardiano d'Aria" msgid "Thundax" msgstr "" msgid "Lord Haart" msgstr "" msgid "Ariel" msgstr "" msgid "Rebecca" msgstr "" msgid "Sandro" msgstr "" msgid "Crodo" msgstr "" msgid "Barock" msgstr "" msgid "Antoine" msgstr "" msgid "Astra" msgstr "" msgid "Agar" msgstr "" msgid "Vatawna" msgstr "" msgid "Vesper" msgstr "" msgid "Ambrose" msgstr "Ambrogio" msgid "Troyan" msgstr "" msgid "Jojosh" msgstr "" msgid "Wrathmont" msgstr "Flagello" msgid "Maximus" msgstr "" msgid "Next Hero" msgstr "Pross. Eroe" msgid "Select the next Hero." msgstr "Scegli il prossimo eroe." #, fuzzy msgid "Hero Movement" msgstr "Movimento Ombra" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "Sommario Regno" #, fuzzy msgid "View a summary of your Kingdom." msgstr "Mostra un sommario del tuo regno." msgid "Cast an adventure spell." msgstr "Lancia una magia avventura." msgid "End Turn" msgstr "Fine Turno" #, fuzzy msgid "End your turn and let the computer take its turn." msgstr "Conclude il tuo turno e passa al/ai computer." msgid "Adventure Options" msgstr "Opzioni Avventura" msgid "Bring up the adventure options menu." msgstr "Mostra il menù con le opzioni dell'avventura." #, fuzzy msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "Mostra il menù file che ti permette di caricare, salvare ecc.." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Mostra il menù di opzioni per il sistema per modificare l'esperienza del " "gioco." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Sei sicuro di voler concludere il tuo turno? Alcuni eroi si possono ancora " "spostare." msgid "Are you sure you want to quit?" msgstr "Sei sicuro di voler chiudere il gioco?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Sei sicuro di voler cominciare da capo? (Il gioco in corso sarà perduto)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Sei sicuro di voler sovrascrivere il salvataggio di questo nome?" msgid "Game saved successfully." msgstr "Il salvataggio è andato a buon fine." msgid "There was an issue during saving." msgstr "Si è verificato un errore durante il salvataggio." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Sei sicuro di voler cominciare una nuova partita? (La partita attuale andrà " "perduta.)" msgid "Try looking on land!!!" msgstr "Cerca sulla terraferma!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" msgid "Congratulations!" msgstr "Complimenti!" msgid "Nothing here. Where could it be?" msgstr "" "Nulla qua.\n" "Dove potrebbe stare?" msgid "Try searching on clear ground." msgstr "Riprova su terreno sgombro." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" msgid "Month: %{month} Week: %{week}" msgstr "Mese: %{month} Settimana: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Trovi una piccola\n" "quantità di %{resource}." msgid "Status Window" msgstr "Finestra di Stato" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" msgid "Handicap" msgstr "" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" msgid "%{color} player" msgstr "Giocatore %{color}" msgid "No Handicap" msgstr "" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" msgid "Mild Handicap" msgstr "" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" msgid "Severe Handicap" msgstr "" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Scegli Attacco" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Mostra dettagli su %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Difesa" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Rendita" #, fuzzy msgid "Kingdom Income per day." msgstr "Rendita" #, fuzzy msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Hai catturato un faro, e ora i punti di movimento in nave si aumentano per " "tutti i tuoi eroi." msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "Italiano" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "" #, fuzzy msgid "Bulgarian" msgstr "Barbaro" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" #, fuzzy msgid "Portuguese" msgstr "Furfanti" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "" #, fuzzy msgid "Hungarian" msgstr "Barbaro" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" #, fuzzy msgid "Vietnamese" msgstr "Mostra %{name}" #, fuzzy msgid "Slow" msgstr "Pianissimo" msgid "Fast" msgstr "" #, fuzzy msgid "Very Fast" msgstr "Velocissima" msgid "Evil" msgstr "Cattivo" msgid "Good" msgstr "Buono" msgid ", FPS: " msgstr "" msgid "shipAndGraveyard|%{object} robber" msgstr "" msgid "pyramid|%{object} raided" msgstr "" msgid "Ector" msgstr "" msgid "Gwenneth" msgstr "Guendal" msgid "Sir Gallant" msgstr "" msgid "Tyro" msgstr "" msgid "Dimitry" msgstr "" msgid "Ruby" msgstr "" msgid "Crag Hack" msgstr "" msgid "Fineous" msgstr "Fineo" msgid "Jezebel" msgstr "Gezebel" msgid "Atlas" msgstr "" msgid "Ergon" msgstr "" msgid "Jaclyn" msgstr "" msgid "Gem" msgstr "" msgid "Natasha" msgstr "" msgid "Carlawn" msgstr "Teodolinda" msgid "Luna" msgstr "" msgid "Arie" msgstr "" msgid "Barok" msgstr "" msgid "Kastore" msgstr "" msgid "Falagar" msgstr "" msgid "Dawn" msgstr "" msgid "Flint" msgstr "" msgid "Halon" msgstr "" msgid "Myra" msgstr "" msgid "Myrini" msgstr "" msgid "Wilfrey" msgstr "" msgid "Mandigal" msgstr "" msgid "Sarakin" msgstr "" msgid "Charity" msgstr "" msgid "Darlana" msgstr "" msgid "Ranloo" msgstr "" msgid "Rialdo" msgstr "" msgid "Zam" msgstr "" msgid "Zom" msgstr "" msgid "Celia" msgstr "" msgid "Roxana" msgstr "" msgid "Lord Corlagon" msgstr "" msgid "Lord Halton" msgstr "" msgid "Sister Eliza" msgstr "Sorella Eliza" msgid "Brother Brax" msgstr "Frate Brax" msgid "Dainwin" msgstr "" msgid "Joseph" msgstr "" msgid "Mog" msgstr "" msgid "Solmyr" msgstr "" msgid "Ceallach" msgstr "" msgid "Drakonia" msgstr "" msgid "Elderian" msgstr "" msgid "Gallavant" msgstr "" msgid "Jarkonas" msgstr "" msgid "Martine" msgstr "" msgid " gives you maximum morale" msgstr "" msgid " gives you maximum luck" msgstr "" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Impossibile spostare l'ultima unità" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Bisogna prima acquistare un libro magie per %{gold} pezzi d'oro per poter " "gettare magie." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" msgid "Do you wish to buy one?" msgstr "Ne desideri uno?" msgid "%{count} / day" msgstr "%{count} al giorno" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "Un gorgo travolge la tua nave." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Rifiutandoli si sono offesi i mostri e ti attaccano!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Il custode del mulino dice: \"Mio signore, mi sono sforzato molto per " "procurarti queste risorse. Se torni la prossima settimana ne avrò ancora.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Il custode del mulino dice: \"Mio signore, perdonami, al momento non ho " "risorse. Ti chiedo di ritornare la settimana prossima.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Il custode del mulino dice: \"Mio signore, mi sono sforzato molto per " "procurarti quest'oro. Se ripassi la settimana prossima ne avrò ancora.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Il custode del mulino dice: \"Mio signore, perdonami, al momento sono senza " "oro. Ti chiedo di riprovare la settimana prossima.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" msgid "You come upon the remains of an unfortunate adventurer." msgstr "Trovi le spoglie di un avventuriero sfortunato." msgid "Treasure" msgstr "Tesoro" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" msgid "Searching through the tattered clothing, you find nothing." msgstr "" msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" msgid "Searching inside, you find the %{artifact}." msgstr "" msgid "Inside, you find some of the wagon's cargo still intact." msgstr "" msgid "You search through the flotsam, and find some wood and some gold." msgstr "Spulci i detriti galleggianti e scopri del legname e dell'oro." msgid "You search through the flotsam, and find some wood." msgstr "Spulci i detriti galleggianti e scopri del legname." msgid "You search through the flotsam, but find nothing." msgstr "Spulci i detriti galleggianti, però non scopri niente." msgid "Shrine of the 1st Circle" msgstr "" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 2nd Circle" msgstr "" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 3rd Circle" msgstr "" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Prendi un sorso dalla fontana incantata, ma non accade niente." msgid "You enter the faerie ring, but nothing happens." msgstr "Visiti il cerchio fatato, ma non accade nulla." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Visitando il mistico cerchio fatato, l'esercito riceve la fortuna buona per " "il combattimento prossimo." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" msgid "A second drink at the well in one day will not help you." msgstr "" msgid "A drink from the well has restored your spell points to maximum." msgstr "" msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" msgid "Do you wish to buy this artifact?" msgstr "Vuoi acquistare questo artefatto?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" msgid "You've found the artifact: " msgstr "Hai scoperto l'artefatto: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" msgid "Victorious, you take your prize, the %{art}." msgstr "Trionfante, cogli la ricompensa, il/la %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Hai catturato la locale Bottega dell'Alchimista. Ti fornirà %{count} " "mercurio al giorno." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "Hai catturato una segheria, e ti fornirà %{count} legname al giorno." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Hai catturato una miniera di ferro. Ti fornirà %{count} ferro al giorno." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Hai catturato una miniera di zolfo. Ti fornirà %{count} zolfo al giorno." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Hai catturato una miniera di cristallo. Ti fornirà %{count} cristallo al " "giorno." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Hai catturato una miniera di gemme. Ti fornirà %{count} gemma al giorno." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "Hai catturato una miniera d'oro. Ti fornirà %{count} oro al giorno." #, fuzzy msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Hai catturato un faro, e ora i punti di movimento in nave si aumentano per " "tutti i tuoi eroi." msgid "You gain control of a %{name}." msgstr "Catturi un %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Sconfiggi i Fantasmi e puoi rimettere in produzione la miniera." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Un gruppo di %{monster} desideroso di gloria vuole unirsi a te.\n" "Accetti?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "" msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" msgid "No Fire Elementals approach you from the lava pool." msgstr "" msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" msgid "A face forms in the water for a moment, and then is gone." msgstr "" msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" msgid "This burial site is deathly still." msgstr "Il luogo di sepoltura è sinistramente calmo." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" msgid "From the observation tower, you are able to see distant lands." msgstr "" msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" msgid " and " msgstr " e i " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "" msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Il comandante ti guarda stupito e dice:\n" "\"Hai già tutte le mappe che conosco. Lasciami pescare in pace adesso.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" msgid "You have already been to this obelisk." msgstr "Hai già visitato questo obelisco." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "L'albero si apre gli occhi in delizia mentre ti avvicini." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" msgid "(Just bury it around my roots.)" msgstr "(Basta seppellirli intorno alle mie radici.)" msgid "Tears brim in the eyes of the tree." msgstr "Le lacrime traboccano dagli occhi dell'albero." msgid "\"I need %{count} %{res}.\"" msgstr "\"Ho bisgno di %{count} %{res},\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" "sussurra mentre fiuta. \"D'accordo, vieni di nuovo qua quando potrai pagarmi." "\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" "Tranne che per le tracce di una terribile battaglia, la caverna è " "abbandonata." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" msgstr[1] "" msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" msgstr[1] "" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" msgstr[1] "" msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" msgid "The Arena guards turn you away." msgstr "" msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" msgid "This eye seems to be intently studying its surroundings." msgstr "" msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Trovi una Sfinge enorme, però stranamente resta in silenzio." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Per te ho un enigma,\" dichiara la Sfinge. \"Rispondi corretto, e ti " "ricompenserò. Rispondi invece scorretto, e ti divorerò. Acconsenti le " "condizioni?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "La Sfinge ti presenta questo enigma:\n" "\n" "'%{riddle}'\n" "\n" "La tua risposta?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"La tua risposta è scorretta,\" spiega la Sfinge, sorridendo. E così la " "Sfinge ti colpisce con la sua zampa, lanciando ti per terra. Un'altra " "zampata ancora ti fa svenire, e dopodiché non sai più cosa succede." #, fuzzy msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "La Sfinge fa un soffio di delusione. Hai dato la risposta giusta e come ti " "ho premesso qua è il tuo premio. Ora sparisci da qui." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" #, fuzzy msgid "No spell book is present." msgstr "Nessuna magia disponibile." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" #, fuzzy msgid "The spell was not found." msgstr "Questa magia non influirà nessuno!" msgid "Only heroes can cast this spell." msgstr "" #, fuzzy msgid "This hero is not able to cast adventure spells." msgstr "Lancia una magia avventura." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" msgid "This spell cannot be cast on a boat." msgstr "" msgid "This spell can only be cast near an ocean." msgstr "" msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" #, fuzzy msgid "There are no boats available for this spell." msgstr "Lancia una magia avventura." #, fuzzy msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "Lancia una magia avventura." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" #, fuzzy msgid "This hero is already in a town, so this spell will have no effect." msgstr "Lancia una magia avventura." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" msgid "This spell is already in effect." msgstr "" msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" msgid "%{name} the %{race} (Level %{level})" msgstr "%{name}: %{race} (Livello %{level})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} (Livello %{level})" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{name}: %{race} (Livello %{level})" #, fuzzy msgid "Hero race:" msgstr "Schermata Eroe" msgid "Are you sure you want to dismiss this Hero?" msgstr "Sei sicuro di voler congedare questo eroe?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Mostra dettagli sull'esperienza" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Pt. Magia" msgid "View Spell Points Info" msgstr "Mostra dettagli sui Punti Magia" msgid "Set patrol radius in tiles" msgstr "" msgid "Enter hero's name" msgstr "" #, fuzzy msgid "Click to change race." msgstr "Clicca per andare alla città succ." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" msgid "Exit Hero Screen" msgstr "Lascia la schermata eroe" msgid "You cannot dismiss a hero in a castle" msgstr "" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "" msgid "Dismiss %{name} the %{race}" msgstr "Congeda %{name}: %{race}" msgid "Show previous hero" msgstr "Mostra eroe precedente" msgid "Show next hero" msgstr "Mostra eroe successivo" msgid "Set army combat formation to 'Spread'" msgstr "Imposta formazione sparsa all'esercito" msgid "Set army combat formation to 'Grouped'" msgstr "Imposta formazione chiusa all'esercito" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Clicca per andare alla città succ." msgid "Blood Morale" msgstr "Morale Sangue" msgid "%{morale} Morale" msgstr "Morale %{morale}" msgid "%{luck} Luck" msgstr "Fortuna %{luck}" msgid "Current Luck Modifiers:" msgstr "Influenze sulla Fortuna:" msgid "Current Morale Modifiers:" msgstr "Influenze sul Morale:" msgid "Entire army is undead, so morale does not apply." msgstr "Tutto l'esercito è non-morto, quindi il morale non vale." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Esperienza attuale: %{exp1}\n" "Livello prossimo: %{exp2}" msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Livello %{level}" #, fuzzy msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "Attualmente %{name} ha %{point} sul totale di %{max} punti di magia. I punti " "totali di magia sono dieci volte il sapere dell'eroe. Vari avvenimenti " "possono influire al numero attuale, aumentandolo anche sopra il numero " "previsto dal sapere." msgid "%{name1} meets %{name2}" msgstr "%{name1} incontra %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "" msgid "Identify Hero" msgstr "Riconosci Eroi" msgid "Select town to port to." msgstr "" msgid "Town Portal" msgstr "Alla Porta" msgid "The creatures are willing to join us!" msgstr "" msgid "All the creatures will join us..." msgstr "" msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "" msgstr[1] "" msgid "" "\n" " for a fee of %{gold} gold." msgstr "" msgid "These weak creatures will surely flee before us." msgstr "" msgid "I fear these creatures are in the mood for a fight." msgstr "" msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" msgid "The hero's spell power determines the duration or power of a spell." msgstr "" msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" msgid "Current Modifiers:" msgstr "Modifiche Attuali:" msgid "skill|Basic" msgstr "Normale" msgid "skill|Advanced" msgstr "Avanzato/a" msgid "skill|Expert" msgstr "Esperto/a" msgid "Pathfinding" msgstr "Orientam." msgid "Archery" msgstr "Tiro col arco" msgid "Logistics" msgstr "Logistica" msgid "Scouting" msgstr "Esplorazione" msgid "Diplomacy" msgstr "Diplomazia" msgid "Navigation" msgstr "Navigazione" msgid "Leadership" msgstr "Carisma" msgid "Wisdom" msgstr "Saggezza" msgid "Mysticism" msgstr "Misticismo" msgid "Ballistics" msgstr "Balistica" msgid "Eagle Eye" msgstr "Vista d'aquila" msgid "Necromancy" msgstr "Negromanz" msgid "Estates" msgstr "Investimenti" msgid "Advanced Archery" msgstr "Tiro con L'Arco Avanzato" msgid "Advanced Pathfinding" msgstr "Orientamento Avanzato" msgid "Basic Archery" msgstr "Tiro con l'Arco Normale" msgid "Basic Pathfinding" msgstr "Orientamento Normale" msgid "Expert Pathfinding" msgstr "Orientamento Esperto" msgid "Advanced Logistics" msgstr "Logistica Avanzata" msgid "Basic Logistics" msgstr "Logistica Normale" msgid "Basic Scouting" msgstr "Esplorazione Normale" msgid "Expert Archery" msgstr "Tiro con l'Arco Esperto" msgid "Expert Logistics" msgstr "Logistica Esperta" msgid "Advanced Diplomacy" msgstr "Diplomazia Avanzata" msgid "Advanced Scouting" msgstr "Esplorazione Avanzata" msgid "Basic Diplomacy" msgstr "Diplomazia Normale" msgid "Expert Diplomacy" msgstr "Diplomazia Esperta" msgid "Expert Scouting" msgstr "Esplorazione Esperta" msgid "Advanced Leadership" msgstr "Carisma Avanzato" msgid "Advanced Navigation" msgstr "Navigazione Avanzata" msgid "Basic Leadership" msgstr "Carisma Normale" msgid "Basic Navigation" msgstr "Navigazione Normale" msgid "Expert Navigation" msgstr "Navigazione Esperta" msgid "Advanced Wisdom" msgstr "Sagezza Avanzata" msgid "Basic Mysticism" msgstr "Misticismo Normale" msgid "Basic Wisdom" msgstr "Sagezza Normale" msgid "Expert Leadership" msgstr "Carisma Esperto" msgid "Expert Wisdom" msgstr "Sagezza Esperta" msgid "Advanced Luck" msgstr "Fortuna Avanzata" msgid "Advanced Mysticism" msgstr "Misticismo Avanzato" msgid "Basic Luck" msgstr "Fortuna Normale" msgid "Expert Luck" msgstr "Fortuna Esperta" msgid "Expert Mysticism" msgstr "Misticismo Esperto" msgid "Advanced Ballistics" msgstr "Balistica Avanzata" msgid "Advanced Eagle Eye" msgstr "Vista Avanzata" msgid "Basic Ballistics" msgstr "Balistica Normale" msgid "Basic Eagle Eye" msgstr "Vista Normale" msgid "Expert Ballistics" msgstr "Balistica Esperta" msgid "Advanced Necromancy" msgstr "Negromanzia Avanzata" msgid "Basic Estates" msgstr "Investimenti Normali" msgid "Basic Necromancy" msgstr "Negromanzia Normale" msgid "Expert Eagle Eye" msgstr "Vista Esperta" msgid "Expert Necromancy" msgstr "Negromanzia Esperta" msgid "Advanced Estates" msgstr "Investimenti Avanzati" msgid "Expert Estates" msgstr "Investimenti Esperti" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "" msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "" msgstr[1] "" msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" msgid "All of the creatures may offer to join the hero." msgstr "" #, fuzzy msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "%{name} diminuisce di %{count} percento il costo della resa." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "%{skill} allows the hero to learn third level spells." msgstr "" msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" msgid "%{skill} allows the hero to learn fifth level spells." msgstr "" msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" msgstr[1] "" #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{name} ti dà più fortuna in combattimento." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "%{name} contiene le tue magie." msgid "Blue" msgstr "Blu" msgid "Green" msgstr "Verde" msgid "Red" msgstr "Rosso" msgid "Yellow" msgstr "Giallo" msgid "Orange" msgstr "Arancio" msgid "Purple" msgstr "Viola" msgid "barrier|Aqua" msgstr "Acqua" msgid "barrier|Blue" msgstr "Blu" msgid "barrier|Brown" msgstr "Marrone" msgid "barrier|Gold" msgstr "Dorata" msgid "barrier|Green" msgstr "Verde" msgid "barrier|Orange" msgstr "Arancia" msgid "barrier|Purple" msgstr "Viola" msgid "barrier|Red" msgstr "Rossa" msgid "tent|Aqua" msgstr "Acqua" msgid "tent|Blue" msgstr "Blu" msgid "tent|Brown" msgstr "Marrone" msgid "tent|Gold" msgstr "Dorata" msgid "tent|Green" msgstr "Verde" msgid "tent|Orange" msgstr "Arancia" msgid "tent|Purple" msgstr "Viola" msgid "tent|Red" msgstr "Rossa" #, fuzzy msgid "Experience" msgstr "Sperimentale" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" msgid "Hero/Stats" msgstr "Dati Eroe" msgid "Skills" msgstr "Doti" msgid "Town/Castle" msgstr "Città/Castello" msgid "Garrison" msgstr "Guarnigione" msgid "Gold Per Day:" msgstr "Oro al giorno:" msgid "View Heroes." msgstr "Mostra Eroi." msgid "Towns/Castles" msgstr "Città/Castelli" msgid "View Towns and Castles." msgstr "Mostra Città e Castelli." msgid "luck|Cursed" msgstr "Maledetta" msgid "luck|Awful" msgstr "Bassissima" msgid "luck|Bad" msgstr "Scarsa" msgid "luck|Normal" msgstr "Normale" msgid "luck|Good" msgstr "Buona" msgid "luck|Great" msgstr "Alta" msgid "luck|Irish" msgstr "Irlandese" #, fuzzy msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "La fortuna cattiva potrebbe accadere al tuo esercito in combattimento, " "facendo sì che i danni che fanno si dimezzano." #, fuzzy msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "La fortuna normale non dà la possibiltà di fare ne colpi fortunati ne " "sfortunati al tuo esercito." #, fuzzy msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "La buona fortuna potrebbe radoppiare i danni che fanno le tue forze." msgid "morale|Treason" msgstr "Tradimento" msgid "morale|Awful" msgstr "Bassissimo" msgid "morale|Poor" msgstr "Basso" msgid "morale|Normal" msgstr "Normale" msgid "morale|Good" msgstr "Buono" msgid "morale|Great" msgstr "Alto" msgid "morale|Blood!" msgstr "Sangue!" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "Il morale negativo potrebbe far perdere il turno alle tue unità in battagla." #, fuzzy msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Il morale normale vuol dire che il tuo esercito non avrà mai la fortuna di " "avere turni in più mai il vantaggio di attacchi o paralisi supplementari in " "battaglia." #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "Il morale positivo potrebbe dare turni in più alle tue unità in battaglia." msgid "Knight" msgstr "Cavaliere" msgid "Barbarian" msgstr "Barbaro" msgid "Sorceress" msgstr "Strega" msgid "Warlock" msgstr "Guerriero" msgid "Wizard" msgstr "Mago" msgid "Necromancer" msgstr "Negromante" msgid "Multi" msgstr "Multiplo" msgid "doubleLined|Knight" msgstr "Cavaliere" msgid "doubleLined|Barbarian" msgstr "Barbaro" msgid "doubleLined|Sorceress" msgstr "Strega" msgid "doubleLined|Warlock" msgstr "Guerriero" msgid "doubleLined|Wizard" msgstr "Mago" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Negro-\n" "mante" msgid "doubleLinedRace|Multi" msgstr "Multiplo" msgid "doubleLinedRace|Random" msgstr "Casuale" msgid "speed|Standing" msgstr "Fermo" msgid "speed|Crawling" msgstr "Lumaca" msgid "speed|Very Slow" msgstr "Lentissima" msgid "speed|Slow" msgstr "Lenta" msgid "speed|Average" msgstr "Media" msgid "speed|Fast" msgstr "Veloce" msgid "speed|Very Fast" msgstr "Velocissima" msgid "speed|Ultra Fast" msgstr "Ultraveloce" msgid "speed|Blazing" msgstr "Folgore" msgid "speed|Instant" msgstr "Istantanea" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Scoiattolo" msgid "week|Rabbit" msgstr "Coniglio" msgid "week|Gopher" msgstr "Topo" msgid "week|Badger" msgstr "Tasso" #, fuzzy msgid "week|Rat" msgstr "Coniglio" msgid "week|Eagle" msgstr "Aquila" msgid "week|Weasel" msgstr "Donnola" msgid "week|Raven" msgstr "Corvo" msgid "week|Mongoose" msgstr "Mangusta" #, fuzzy msgid "week|Dog" msgstr "Aquila" msgid "week|Aardvark" msgstr "Formichiere" msgid "week|Lizard" msgstr "Lucertola" msgid "week|Tortoise" msgstr "Testuggine" msgid "week|Hedgehog" msgstr "Riccio" msgid "week|Condor" msgstr "Condor" msgid "week|Ant" msgstr "Formica" msgid "week|Grasshopper" msgstr "Cavalletta" msgid "week|Dragonfly" msgstr "Libellula" msgid "week|Spider" msgstr "Ragno" msgid "week|Butterfly" msgstr "Farfalla" msgid "week|Bumblebee" msgstr "Bombo" msgid "week|Locust" msgstr "Locusta" msgid "week|Earthworm" msgstr "Verme" msgid "week|Hornet" msgstr "Calabrone" msgid "week|Beetle" msgstr "Scarabeo" msgid "week|PLAGUE" msgstr "PESTE" #, fuzzy msgid "week|Unnamed" msgstr "Aquila" msgid "Desert" msgstr "Deserto" msgid "Snow" msgstr "Neve" msgid "Wasteland" msgstr "Terra sterile" msgid "Beach" msgstr "Spiaggia" msgid "Lava" msgstr "Lava" msgid "Dirt" msgstr "Terra" msgid "Grass" msgstr "Prato" msgid "Ocean" msgstr "Oceano" msgid "maps|Small" msgstr "Piccola" msgid "maps|Medium" msgstr "Media" msgid "maps|Large" msgstr "Grande" msgid "maps|Extra Large" msgstr "XL" msgid "maps|Custom Size" msgstr "Dimensione personalizzata" msgid "Ore Mine" msgstr "Miniera di Ferro" msgid "Sulfur Mine" msgstr "Miniera di Zolfo" msgid "Crystal Mine" msgstr "Miniera di Cristallo" msgid "Gems Mine" msgstr "Miniera di Gemme" msgid "Gold Mine" msgstr "Miniera d'Oro" msgid "Mine" msgstr "Miniera" msgid "Burma shave." msgstr "Schiuma da Burba." msgid "Next sign 50 miles." msgstr "Prossimo cartello tra 50 miglia." msgid "See Rock City." msgstr "Vai a Hard Rock." msgid "This space for rent." msgstr "Affittasi." msgid "No object" msgstr "Nessun oggetto" msgid "Alchemist Lab" msgstr "Laboratorio dell'Alchimista" msgid "Sign" msgstr "Cartello" msgid "Buoy" msgstr "Boa" msgid "Skeleton" msgstr "Scheletro" msgid "Daemon Cave" msgstr "Caverna del Demone" msgid "Treasure Chest" msgstr "Forziere del Tesoro" msgid "Faerie Ring" msgstr "Cerchio Fatato" msgid "Campfire" msgstr "Fuoco da Campo" msgid "Fountain" msgstr "Fontana" msgid "Gazebo" msgstr "Gazebo" msgid "Genie Lamp" msgstr "Lampa Antica" msgid "Archer's House" msgstr "Casa degli Arcieri" msgid "Goblin Hut" msgstr "Capanna dei Goblin" msgid "Dwarf Cottage" msgstr "Casetta dei Nani" msgid "Peasant Hut" msgstr "Capanna dei Burini" msgid "Stables" msgstr "Stalla" msgid "Alchemist's Tower" msgstr "Torre dell'Alchimista" msgid "Event" msgstr "Evento" msgid "Dragon City" msgstr "Dragon City" #, fuzzy msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Faro" msgstr[1] "Faro" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Mulino ad Acqua" msgstr[1] "Mulini ad Acqua" msgid "Monster" msgstr "Mostro" msgid "Obelisk" msgstr "Obelisco" msgid "Oasis" msgstr "Oasi" msgid "Resource" msgstr "Risorso" msgid "Sawmill" msgstr "Segheria" msgid "Oracle" msgstr "Oracolo" msgid "Shrine of the First Circle" msgstr "Tempio del Primo Cerchio" msgid "Shipwreck" msgstr "Naufragio" msgid "Sea Chest" msgstr "Forziere Marino" msgid "Desert Tent" msgstr "Tenda da Deserto" msgid "Stone Liths" msgstr "Monoliti" msgid "Wagon Camp" msgstr "Campo Carri" msgid "Hut of the Magi" msgstr "Capanna del Mago" msgid "Whirlpool" msgstr "Gorgo" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Mulino a Vento" msgstr[1] "Mulini a Vento" msgid "Mermaid" msgstr "Sirenetta" msgid "Boat" msgstr "Nave" msgid "Random Ultimate Artifact" msgstr "Artefatto estremo casuale" msgid "Random Artifact" msgstr "Artefatto casuale" msgid "Random Resource" msgstr "Risorso casuale" msgid "Random Monster" msgstr "Mostro casuale" msgid "Random Town" msgstr "Città casuale" msgid "Random Castle" msgstr "Castello casuale" msgid "Eye of the Magi" msgstr "Occhio del Mago" msgid "Random Monster - weak" msgstr "Mostro casuale - debole" msgid "Random Monster - medium" msgstr "Mostro casuale - medio" msgid "Random Monster - strong" msgstr "Mostro casuale - forte" msgid "Random Monster - very strong" msgstr "Mostra casuale - molto forte" #, fuzzy msgid "Hero" msgstr "Eroi" msgid "Nothing Special" msgstr "Niente particolare" msgid "Mossy Rock" msgstr "" msgid "Watch Tower" msgstr "Torre di Guardia" msgid "Tree House" msgstr "Casa sugli Alberi" msgid "Tree City" msgstr "Città degli Alberi" msgid "Ruins" msgstr "Rovine" msgid "Fort" msgstr "Forte" msgid "Abandoned Mine" msgstr "Miniera Abbandonata" msgid "Sirens" msgstr "Sirene" msgid "Standing Stones" msgstr "Massi Eretti" msgid "Idol" msgstr "Idolo" msgid "Tree of Knowledge" msgstr "Albero del Sapere" msgid "Witch Doctor's Hut" msgstr "Capanna dello Sciamano" msgid "Temple" msgstr "Tempio" msgid "Hill Fort" msgstr "Forte in Collina" msgid "Halfling Hole" msgstr "Tana dei Frombolieri" msgid "Mercenary Camp" msgstr "Campo Mercenari" msgid "Shrine of the Second Circle" msgstr "Tempio del Secondo Cerchio" msgid "Shrine of the Third Circle" msgstr "Tempio del Terzo Cerchio" msgid "City of the Dead" msgstr "Città dei Morti" msgid "Sphinx" msgstr "Sfinge" msgid "Wagon" msgstr "Carro" msgid "Tar Pit" msgstr "Pozzo di Catrame" msgid "Artesian Spring" msgstr "PozzoAartesiano" msgid "Troll Bridge" msgstr "Ponte dei Troll" msgid "Watering Hole" msgstr "Abbeveratoio" msgid "Witch's Hut" msgstr "Capanna della Strega" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Casotto" msgid "Magellan's Maps" msgstr "Mappe di Magellano" msgid "Flotsam" msgstr "Rottami" msgid "Derelict Ship" msgstr "Relitto Navale" msgid "Shipwreck Survivor" msgstr "Superstite Naufragio" msgid "Bottle" msgstr "Bottiglia" msgid "Magic Well" msgstr "Pozzo Magico" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Giardino Magico" msgstr[1] "Giardini Magici" msgid "Observation Tower" msgstr "Osservatorio" msgid "Freeman's Foundry" msgstr "Fucina dei Liberti" msgid "Reefs" msgstr "Barriera Corallina" msgid "Volcano" msgstr "Vulcano" msgid "Flowers" msgstr "Fiori" msgid "Rock" msgstr "Roccia" msgid "Water Lake" msgstr "Lago" msgid "Mandrake" msgstr "Mandragola" msgid "Dead Tree" msgstr "Albero Morto" msgid "Stump" msgstr "Troncone" msgid "Crater" msgstr "Cratere" msgid "Cactus" msgstr "Cactus" msgid "Mound" msgstr "Terrapieno" msgid "Dune" msgstr "Duna" msgid "Lava Pool" msgstr "Pozza di Lava" msgid "Shrub" msgstr "Arbusto" msgid "Barrow Mounds" msgstr "Tumulo" msgid "Random Artifact - Treasure" msgstr "Artefatto casuale - tesoro" msgid "Random Artifact - Minor" msgstr "Artefatto casuale - minore" msgid "Random Artifact - Major" msgstr "Artefatto casuale - maggiore" msgid "Barrier" msgstr "Barriera" msgid "Traveller's Tent" msgstr "Tenda del Viaggiatore" msgid "Jail" msgstr "Galera" msgid "Fire Summoning Altar" msgstr "Altare Convocante del Fuoco" msgid "Air Summoning Altar" msgstr "Altare Convocante d'Aria" msgid "Earth Summoning Altar" msgstr "Altare Convocante di Terra" msgid "Water Summoning Altar" msgstr "Altare Convocante dell'Acqua" #, fuzzy msgid "Swampy Lake" msgstr "Palude" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "Mostri sconosciuti" msgid "Unknown Monster" msgstr "Mostro sconosciuto" msgid "Peasant" msgstr "Burino" msgid "Peasants" msgstr "Burini" msgid "Archer" msgstr "Arciere" msgid "Archers" msgstr "Arcieri" msgid "Ranger" msgstr "Cacciatore" msgid "Rangers" msgstr "Cacciatori" msgid "Pikeman" msgstr "Alabardiere" msgid "Pikemen" msgstr "Alabardieri" msgid "Veteran Pikeman" msgstr "Alabardiere Esperto" msgid "Veteran Pikemen" msgstr "Alabardieri Esperti" msgid "Swordsman" msgstr "Spadaccino" msgid "Swordsmen" msgstr "Spadaccini" msgid "Master Swordsman" msgstr "Maestro Spadaccino" msgid "Master Swordsmen" msgstr "Maestri Spadaccini" msgid "Cavalries" msgstr "Cavalleria" msgid "Cavalry" msgstr "Cavallerie" msgid "Champion" msgstr "Campione" msgid "Champions" msgstr "Campioni" msgid "Paladin" msgstr "Paladino" msgid "Paladins" msgstr "Paladini" msgid "Crusader" msgstr "Crociato" msgid "Crusaders" msgstr "Crociati" msgid "Goblin" msgstr "Goblin" msgid "Goblins" msgstr "Goblins" msgid "Orc" msgstr "Orchino" msgid "Orcs" msgstr "Orchini" msgid "Orc Chief" msgstr "Capo Orchino" msgid "Orc Chiefs" msgstr "Capo Orchini" msgid "Wolf" msgstr "Lupo" msgid "Wolves" msgstr "Lupi" msgid "Ogre" msgstr "Orco" msgid "Ogres" msgstr "Orchi" msgid "Ogre Lord" msgstr "Lord Orco" msgid "Ogre Lords" msgstr "Lord Orchi" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Troll" msgid "War Troll" msgstr "Troll da Guerra" msgid "War Trolls" msgstr "Troll da Guerra" msgid "Cyclopes" msgstr "Ciclope" msgid "Cyclops" msgstr "Ciclopi" msgid "Sprite" msgstr "Spiritello" msgid "Sprites" msgstr "Spiritelli" msgid "Dwarf" msgstr "Nano" msgid "Dwarves" msgstr "Nani" msgid "Battle Dwarf" msgstr "Nano da Battaglia" msgid "Battle Dwarves" msgstr "Nani da Battaglia" msgid "Elf" msgstr "Elfo" msgid "Elves" msgstr "Elfi" msgid "Grand Elf" msgstr "Grande Elfo" msgid "Grand Elves" msgstr "Grandi Elfi" msgid "Druid" msgstr "Druido" msgid "Druids" msgstr "Druidi" msgid "Greater Druid" msgstr "Druido Maggiore" msgid "Greater Druids" msgstr "Druidi Maggiori" msgid "Unicorn" msgstr "Unicorno" msgid "Unicorns" msgstr "Unicorni" msgid "Phoenix" msgstr "Fenice" msgid "Phoenixes" msgstr "Fenici" msgid "Centaur" msgstr "Centauro" msgid "Centaurs" msgstr "Centauri" msgid "Gargoyle" msgstr "Gargolla" msgid "Gargoyles" msgstr "Gargolle" msgid "Griffin" msgstr "Grifone" msgid "Griffins" msgstr "Grifoni" msgid "Minotaur" msgstr "Minotauro" msgid "Minotaurs" msgstr "Minotauri" msgid "Minotaur King" msgstr "Minotauro Re" msgid "Minotaur Kings" msgstr "Minotauri Re" msgid "Hydra" msgstr "Idra" msgid "Hydras" msgstr "Idre" msgid "Green Dragon" msgstr "Drago Verde" msgid "Green Dragons" msgstr "Draghi Verdi" msgid "Red Dragon" msgstr "Drago Rosso" msgid "Red Dragons" msgstr "Draghi Rossi" msgid "Black Dragon" msgstr "Drago Nero" msgid "Black Dragons" msgstr "Draghi Neri" msgid "Halfling" msgstr "Fromboliere" msgid "Halflings" msgstr "Frombolieri" msgid "Boar" msgstr "Cinghiale" msgid "Boars" msgstr "Cinghiali" msgid "Iron Golem" msgstr "Golem del Ferro" msgid "Iron Golems" msgstr "Golem del Ferro" msgid "Steel Golem" msgstr "Golem dell'Acciaio" msgid "Steel Golems" msgstr "Golem dell'Acciaio" # Roc? msgid "Roc" msgstr "Aquila" msgid "Rocs" msgstr "Aquile" msgid "Mage" msgstr "Mago" msgid "Magi" msgstr "Maghi" msgid "Archmage" msgstr "Arcimago" msgid "Archmagi" msgstr "Arcimaghi" msgid "Giant" msgstr "Gigante" msgid "Giants" msgstr "Giganti" msgid "Titan" msgstr "Titano" msgid "Titans" msgstr "Titani" msgid "Skeletons" msgstr "Scheletri" msgid "Zombie" msgstr "Zombi" msgid "Zombies" msgstr "Zombi" msgid "Mutant Zombie" msgstr "Zombi Mutante" msgid "Mutant Zombies" msgstr "Zombi Mutanti" msgid "Mummies" msgstr "Mummie" msgid "Mummy" msgstr "Mummia" msgid "Royal Mummies" msgstr "Mummie Reali" msgid "Royal Mummy" msgstr "Mummia Reale" msgid "Vampire" msgstr "Vampiro" msgid "Vampires" msgstr "Vampiri" msgid "Vampire Lord" msgstr "Lord Vampiro" msgid "Vampire Lords" msgstr "Lord Vampiri" msgid "Lich" msgstr "Salma" msgid "Liches" msgstr "Salme" msgid "Power Lich" msgstr "Salma Potente" msgid "Power Liches" msgstr "Salme Potenti" msgid "Bone Dragon" msgstr "Drago d'Ossa" msgid "Bone Dragons" msgstr "Draghi d'Ossa" msgid "Rogue" msgstr "Furfante" msgid "Rogues" msgstr "Furfanti" msgid "Nomad" msgstr "Nomade" msgid "Nomads" msgstr "Nomadi" msgid "Ghost" msgstr "Fantasma" msgid "Ghosts" msgstr "Fantasmi" msgid "Genie" msgstr "Genio" msgid "Genies" msgstr "Geni" msgid "Medusa" msgstr "Medusa" msgid "Medusas" msgstr "Meduse" msgid "Earth Elemental" msgstr "Creatura di Terra" msgid "Earth Elementals" msgstr "Creature di Terra" msgid "Air Elemental" msgstr "Creatura d'Aria" msgid "Air Elementals" msgstr "Creature d'Aria" msgid "Fire Elemental" msgstr "Creatura del Fuoco" msgid "Fire Elementals" msgstr "Creature del Fuoco" msgid "Water Elemental" msgstr "Creatura dell'Acqua" msgid "Water Elementals" msgstr "Creature dell'Acqua" msgid "Random Monsters" msgstr "Mostri casuali" msgid "Random Monster 1" msgstr "" msgid "Random Monsters 1" msgstr "" msgid "Random Monster 2" msgstr "" msgid "Random Monsters 2" msgstr "" msgid "Random Monster 3" msgstr "" msgid "Random Monsters 3" msgstr "" msgid "Random Monster 4" msgstr "" msgid "Random Monsters 4" msgstr "" msgid "Double shot" msgstr "Doppio Tiro" msgid "2-hex monster" msgstr "Occupa due riquadri" msgid "Double strike" msgstr "Doppio Attacco" msgid "Double damage to Undead" msgstr "Doppio danno contro non-morti" msgid "% magic resistance" msgstr "% di resistenza magica" msgid "Immune to Mind spells" msgstr "Immune alle magie mentali" msgid "Immune to Elemental spells" msgstr "Immune alle magie elementali" msgid "Immune to Fire spells" msgstr "Immune alle magie del fuoco" msgid "Immune to Cold spells" msgstr "Immune alle magie del gelo" msgid "Immune to " msgstr "Immune a " msgid "% immunity to %{spell} spell" msgstr "% di immunità alla magia %{spell}" msgid "% damage from Elemental spells" msgstr "% di danni dalle magie elementali" msgid "% damage from %{spell} spell" msgstr "% di danni dalla magia %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% di probabiltà di annullare magie positive" msgid "% chance to Paralyze" msgstr "% di probabiltà di paralizzare" msgid "% chance to Petrify" msgstr "% di probabiltà di pietrificare" msgid "% chance to Blind" msgstr "% di probabiltà di accecare" msgid "% chance to Curse" msgstr "% di probabiltà di maledire" msgid "% chance to cast %{spell} spell" msgstr "% di probabiltà di gettare la magia %{spell}" msgid "HP regeneration" msgstr "Rigenerazione PF" msgid "Two hexes attack" msgstr "Colpo di due riquardri" msgid "Flyer" msgstr "Creatura Volante" msgid "Always retaliates" msgstr "Contrattacca sempre" msgid "Attacks all adjacent enemies" msgstr "Attacca tutti i nemici adiacenti" msgid "No melee penalty" msgstr "Nessuna pena per il corpo a corpo" msgid "Dragon" msgstr "Drago" msgid "Undead" msgstr "Non-Morto" msgid "No enemy retaliation" msgstr "Nessun contrattacco nemico" msgid "HP drain" msgstr "Prosciuga Pt. Ferita" msgid "Cloud attack" msgstr "Attacco di Nuvola" msgid "Decreases enemy's morale by " msgstr "Diminuisce il morale nemico di " msgid "% chance to halve enemy" msgstr "% possibiltà di dimezzare il nemico" msgid "Soul Eater" msgstr "Mietitrice d'Anime" msgid "Elemental" msgstr "Elementale" msgid "No Morale" msgstr "Nessun morale" #, fuzzy msgid "Earth creature" msgstr "Recluta Eroe" #, fuzzy msgid "Air creature" msgstr "Recluta Eroe" #, fuzzy msgid "Fire creature" msgstr "Recluta Eroe" #, fuzzy msgid "Water creature" msgstr "Lago" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% di danni dalle magie del fuoco" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% di danni dalle magie del gelo" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Rimuove tutte le magie da tutte le creature nel campo di battaglia." #, fuzzy msgid "Double damage from Air creatures" msgstr "Doppio danno contro non-morti" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% di danni dalle magie del fuoco" #, fuzzy msgid "Double damage from Water creatures" msgstr "Rimuove tutte le magie da tutte le creature nel campo di battaglia." msgid "Lightning" msgstr "Fulmine" msgid "% immunity to " msgstr "% di immunità a " msgid "% damage from " msgstr "% di danni da " msgid "The three Anduran artifacts magically combine into one." msgstr "" msgid "View Spells" msgstr "Mostra Magie" msgid "View %{name} Info" msgstr "Mostra dettagli su %{name}" msgid "Move %{name}" msgstr "Sposta %{name}" #, fuzzy msgid "Cannot move the Spellbook" msgstr "Impossibile spostare l'ultima unità" msgid "This item can't be traded." msgstr "Questo oggetto non si può spostare." #, fuzzy msgid "Invalid Artifact" msgstr "Artefatto casuale" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "Ultimate Book of Knowledge" msgstr "Il Massimo Libro del Sapere" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} incrementa di %{count} la capacità d'attacco del tuo eroe." msgid "Ultimate Sword of Dominion" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} incrementa di %{count} la capacità d'attacco del tuo eroe." msgid "Ultimate Cloak of Protection" msgstr "" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "Ultimate Wand of Magic" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} incrementa di %{count} la capacità d'attacco del tuo eroe." msgid "Ultimate Shield" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "Ultimate Staff" msgstr "" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} incrementa di %{count} punti tutte le tue capacità base." msgid "Ultimate Crown" msgstr "La Massima Corona" msgid "Golden Goose" msgstr "" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "" msgid "Arcane Necklace of Magic" msgstr "" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" msgid "Caster's Bracelet of Magic" msgstr "" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" msgid "Mage's Ring of Power" msgstr "" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" msgid "Witch's Broach of Magic" msgstr "" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" msgid "Medal of Valor" msgstr "La Medaglia al Valore" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" msgid "Medal of Courage" msgstr "" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" msgid "Medal of Honor" msgstr "" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" msgid "Medal of Distinction" msgstr "" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" msgid "Fizbin of Misfortune" msgstr "Il Fizbin della Malasorte" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} diminuisce di molto il morale delle tue truppe di %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" msgid "Thunder Mace of Dominion" msgstr "La Mazza Tonante del Dominio" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" msgid "Armored Gauntlets of Protection" msgstr "" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} incrementa di %{count} la capacità d'attacco del tuo eroe." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" msgid "Defender Helm of Protection" msgstr "L'Elmo di Protezione del Difensore" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" msgid "Giant Flail of Dominion" msgstr "" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" msgid "Ballista of Quickness" msgstr "La Ballista della Rapidità" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" msgid "Stealth Shield of Protection" msgstr "Lo Scudo Segreto di Protezione" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" msgid "Dragon Sword of Dominion" msgstr "La Spada Dominio del Drago" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" msgid "Power Axe of Dominion" msgstr "" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" msgid "Divine Breastplate of Protection" msgstr "" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" msgid "Minor Scroll of Knowledge" msgstr "" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" msgid "Major Scroll of Knowledge" msgstr "" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" msgid "Superior Scroll of Knowledge" msgstr "" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" msgid "Foremost Scroll of Knowledge" msgstr "" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" msgid "Endless Sack of Gold" msgstr "Borsa d'Oro Infinita" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} contiene le tue magie." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" msgid "Endless Bag of Gold" msgstr "La Sacca d'Oro Infinita" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" msgid "Endless Purse of Gold" msgstr "" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" msgid "Nomad Boots of Mobility" msgstr "Gli Stivali di Mobilità dei Nomadi" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" msgid "Traveler's Boots of Mobility" msgstr "" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" msgid "Lucky Rabbit's Foot" msgstr "La Zampa del Coniglio Fortunato" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} ti dà più fortuna in combattimento." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" msgid "Golden Horseshoe" msgstr "Il Ferro di Cavallo d'Oro" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" msgid "Gambler's Lucky Coin" msgstr "" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" msgid "Four-Leaf Clover" msgstr "Il Quadrifoglio" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" msgid "True Compass of Mobility" msgstr "" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" msgid "Sailor's Astrolabe of Mobility" msgstr "L'Astrolabio del Marinaio" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" msgid "Evil Eye" msgstr "" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" msgid "Enchanted Hourglass" msgstr "" #, fuzzy msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "%{name} incrementa di %{count} punti tutte le tue capacità base." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" msgid "Gold Watch" msgstr "L'Orologio d'Oro" #, fuzzy msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} aumenta di due volte il potere delle tua magia Ipnotizza." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" msgid "Skullcap" msgstr "" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" msgid "Ice Cloak" msgstr "Il Mantello di Ghiaccio" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} riduce a metà i danni le tue forze predono da magie di fulmini." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" msgid "Fire Cloak" msgstr "Il Mantello di Fuoco" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} riduce a metà i danni le tue forze predono da magie di fulmini." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" msgid "Lightning Helm" msgstr "L'Elmo Parafulmini" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} riduce a metà i danni le tue forze predono da magie di fulmini." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" msgid "Evercold Icicle" msgstr "Il Ghiacciolo Semprefreddo" #, fuzzy msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} fa sì che le tue magie di gelo fanno %{count} % più danni contro le " "unità nemiche." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" msgid "Everhot Lava Rock" msgstr "Lava Semprecalda" #, fuzzy msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} fa sì che le tue magie di gelo fanno %{count} % più danni contro le " "unità nemiche." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" msgid "Lightning Rod" msgstr "" #, fuzzy msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} fa sì che le tue magie di gelo fanno %{count} % più danni contro le " "unità nemiche." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" msgid "Snake-Ring" msgstr "" #, fuzzy msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "%{name} aumenta di due volte il potere delle tua magia Ipnotizza." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" msgid "Ankh" msgstr "" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "%{name} aumenta di due volte il potere delle tua magia Ipnotizza." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" msgid "Book of Elements" msgstr "" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} aumenta di due volte il potere delle tua magia Ipnotizza." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" msgid "Elemental Ring" msgstr "" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" msgid "Holy Pendant" msgstr "" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" msgid "Pendant of Free Will" msgstr "Il Pendente Arbitrio" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" msgid "Pendant of Life" msgstr "" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" msgid "Serenity Pendant" msgstr "" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" msgid "Seeing-eye Pendant" msgstr "" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" msgid "Kinetic Pendant" msgstr "" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" msgid "Pendant of Death" msgstr "Il Pendente Mortale" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" msgid "Wand of Negation" msgstr "" #, fuzzy msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "%{name} protegge le tue forze da Ipnotizza." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" msgid "Golden Bow" msgstr "" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" msgid "Telescope" msgstr "" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" msgid "Statesman's Quill" msgstr "Il Calamo dello Statista" #, fuzzy msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "%{name} diminuisce di %{count} percento il costo della resa." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" msgid "Wizard's Hat" msgstr "" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} incrementa di %{count} punti tutte le tue capacità base." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" msgid "Power Ring" msgstr "" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} contiene le tue magie." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" msgid "Ammo Cart" msgstr "" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" msgid "Tax Lien" msgstr "" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} contiene le tue magie." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" msgid "Hideous Mask" msgstr "" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" msgid "Endless Pouch of Sulfur" msgstr "" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "" msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" msgid "Endless Vial of Mercury" msgstr "" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "" msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" msgid "Endless Pouch of Gems" msgstr "" msgid "The %{name} provides %{count} unit of gems per day." msgstr "" msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" msgid "Endless Cord of Wood" msgstr "" msgid "The %{name} provides %{count} unit of wood per day." msgstr "" msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" msgid "Endless Cart of Ore" msgstr "" msgid "The %{name} provides %{count} unit of ore per day." msgstr "" msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" msgid "Endless Pouch of Crystal" msgstr "" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "" msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" msgid "Spiked Helm" msgstr "" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" msgid "Spiked Shield" msgstr "" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" msgid "White Pearl" msgstr "La Perla Bianca" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" msgid "Black Pearl" msgstr "La Perla Nera" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" msgid "Magic Book" msgstr "Il Libro Magico" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name} contiene le tue magie." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" #, fuzzy msgid "Dummy 2" msgstr "Mummia" #, fuzzy msgid "The reserved artifact." msgstr "con 1 artefatto." #, fuzzy msgid "Dummy 3" msgstr "Mummia" #, fuzzy msgid "Dummy 4" msgstr "Mummia" msgid "Spell Scroll" msgstr "" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" msgid "Arm of the Martyr" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" msgid "Breastplate of Anduran" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" msgid "Broach of Shielding" msgstr "" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" msgid "Battle Garb of Anduran" msgstr "" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" msgid "Crystal Ball" msgstr "" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" msgid "Heart of Fire" msgstr "" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" msgid "Heart of Ice" msgstr "" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" msgid "Helmet of Anduran" msgstr "" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" msgid "Holy Hammer" msgstr "" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" msgid "Legendary Scepter" msgstr "" msgid "The %{name} adds %{count} points to all attributes." msgstr "" msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" msgid "Masthead" msgstr "" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" msgid "Sphere of Negation" msgstr "" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" msgid "Staff of Wizardry" msgstr "" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" msgid "Sword Breaker" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} incrementa di %{count} punti il sapere del tuo eroe." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" msgid "Sword of Anduran" msgstr "" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" msgid "Spade of Necromancy" msgstr "" msgid "The %{name} gives the hero increased necromancy skill." msgstr "" msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Legno" msgid "Mercury" msgstr "Mercurio" msgid "Ore" msgstr "Ferro" msgid "Sulfur" msgstr "Zolfo" msgid "Crystal" msgstr "Crystallo" msgid "Gems" msgstr "Gemme" msgid "Gold" msgstr "Oro" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Un'enorme massa di fiamme si schianta contro i riquadri selezionati " "colpendovi tutte le unità." msgid "Fireball" msgstr "Palla di Fuoco" msgid "Fireblast" msgstr "Vampata" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "La forma potenziata di palla di fuoco. La vampata danneggia due riquadri " "circostanti all'esagono specificato, piuttosto che solo uno." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Un colpo d'energia elettrica daneggia l'unità specificata." msgid "Lightning Bolt" msgstr "Colpo di Fulmine" msgid "Chain Lightning" msgstr "Fulmini in Serie" #, fuzzy msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Un colpo di fulmine colpisce un'unità specificata, poi colpisce quella gli " "sta più vicina a metà del danno, poi quell'altra più vicina all'ultima " "sempre a metà del danno, finché non riesca a fare più danni. Attenti: Questa " "magia può anche colpire le tue forze!" msgid "Teleport" msgstr "" "Tele-\n" "trasporto" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Sposta un'unità a scelta tua in un posto non occupato del campo di battaglia." msgid "Cure" msgstr "Cura" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Rimuove le magie negative su una creatura prescelta e cura %{count} PF per " "ogni livello di potere magia dell'eroe." msgid "Mass Cure" msgstr "Max Cura" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Rimuove le magie negative su tutte le tue creature e cura %{count} PF per " "ogni livello di potere magia dell'eroe." msgid "Resurrect" msgstr "Risorgi" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "Fa risuscitare delle unità per la durata della battaglia." msgid "Resurrect True" msgstr "Risorgi Sempre" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Fa risuscitare definitivamente delle unità morte." msgid "Haste" msgstr "Furia" msgid "Increases the speed of any creature by %{count}." msgstr "Aumenta la velocità di un'unità di %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Aumenta la velocità di tutte le tue unità di %{count}." msgid "Mass Haste" msgstr "Max Furia" msgid "Slows target to half movement rate." msgstr "Dimezza la distanza di spostamento e la velocità del bersaglio." msgid "spell|Slow" msgstr "Adagio" msgid "Mass Slow" msgstr "Pianissimo" msgid "Slows all enemies to half movement rate." msgstr "" "Dimezza la distanza di spostamento e la velocità di tutte le unità nemiche." msgid "spell|Blind" msgstr "Blind" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Acceca l'unità prescelta, inibendola di fare il suo turno." msgid "Bless" msgstr "Bless" msgid "Causes the selected creatures to inflict maximum damage." msgstr "" "Fa sì che l'unità prescelta infligga il massimo del suo danno potenziale." msgid "Causes all of your units to inflict maximum damage." msgstr "" "Fa sì che tutte le tue creature infliggano il massimo del loro danno " "potenziale." msgid "Mass Bless" msgstr "Max Bless" msgid "Magically increases the defense skill of the selected creatures." msgstr "Incrementa la difesa dell'unità prescelta." msgid "Stoneskin" msgstr "Schermo di Pietra" msgid "Steelskin" msgstr "Corazza" #, fuzzy msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Incrementa la capacità di difesa dell'unità prescelta. È la forma sviluppata " "di Schermo di pietra." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Costringe l'unità nemiche prescelta di fare il danno minimo." msgid "Curse" msgstr "Maledizione" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Costringe tutte le truppe nemiche di fare il danno minimo." msgid "Mass Curse" msgstr "Malefizio" msgid "Damages all undead in the battle." msgstr "Colpisce tutti i non-morti nella battaglia." msgid "Holy Word" msgstr "Sacro Motto" #, fuzzy msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Colpisce tutti i non-morti nella battaglia. È la forma sviluppata di Sacro " "Motto." msgid "Holy Shout" msgstr "Sacro Grido" msgid "Anti-Magic" msgstr "Anti-Magia" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Previene tutte le magie, sia utili che dannose, all'unità prescelta." msgid "Dispel Magic" msgstr "" "Annulla-\n" "Magie" msgid "Removes all magic spells from a single target." msgstr "Rimuove tutte le magie da un unico bersaglio." msgid "Mass Dispel" msgstr "" "Max Annulla-\n" "Magie" msgid "Removes all magic spells from all creatures." msgstr "Rimuove tutte le magie da tutte le creature nel campo di battaglia." msgid "Causes a magic arrow to strike the selected target." msgstr "Fa colpire il bersaglio prescelto da una freccia magica." msgid "Magic Arrow" msgstr "Freccia Magica" msgid "Berserker" msgstr "Berzerker" msgid "Causes a creature to attack its nearest neighbor." msgstr "" "Provoca una creatura di partire all'attacco al suo vicino più prossimo." msgid "Armageddon" msgstr "Armageddon" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Un sacro terrore beraglia tutti sul campo di battaglia, causando danni " "severi." msgid "Elemental Storm" msgstr "Tempesta di Elementi" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Elementi magici bersagliano tutte le creature nella battaglia." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Una pioggia di rocce cade su una parte del campo, colpendo tutte le creature " "vicine." msgid "Meteor Shower" msgstr "Pioggia di Meteore" msgid "Paralyze" msgstr "Paralizza" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "Manda in paralizzo l'unità prescelta, rendendola non più in grado di " "spostarsi o di contrattaccare." msgid "Hypnotize" msgstr "Ipnotizza" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Assuma il controllo di un'unità nemica se la sua capacità di danni è minore " "di %{count} volte al confronto del potere magia dell'incantatore." msgid "Cold Ray" msgstr "Raggio Freddo" msgid "Drains body heat from a single enemy unit." msgstr "Prosciuga il calore corporeo da una singola unità nemica." msgid "Cold Ring" msgstr "Anello Freddo" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Prosciuga il calore corporeo da tutte le unità che stanno appena attorno al " "riquadro centrale della magia, tranne l'unità che sta in quel esagono." msgid "Disrupting Ray" msgstr "Raggio Dispersore" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Riduce la capacità di difesa di un'unità nemica di tre." msgid "Damages all living (non-undead) units in the battle." msgstr "Colpisce tutte le unità viventi (non quelle non-morti) in battaglia." msgid "Death Ripple" msgstr "Ondina Mortale" msgid "Death Wave" msgstr "Onda Mortale" #, fuzzy msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Colpisce tutte le unità viventi (cioè non quelle non-morti) nella battaglia. " "È la miglioria di ondina mortale." msgid "Dragon Slayer" msgstr "Trucida Drago" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Incrementa di tanto i danni contro i draghi." msgid "Blood Lust" msgstr "Ferocia" msgid "Increases a unit's attack skill." msgstr "Incrementa la capacità d'attacco di un'unità." msgid "Animate Dead" msgstr "Anima i Morti" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "Fa risorgere permanentamente dei non-morti distrutti di un'unità." msgid "Mirror Image" msgstr "Rispecchia" #, fuzzy msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Fa comparire un'unità illusionale che copia una delle tue già esistenti " "unità. Questa illusione è capace di fare gli stessi di quello di cui sono la " "copia, però sparisce se subisce qualsiasi danno." msgid "Shield" msgstr "Scudo" #, fuzzy msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Riduce a metà i danni subiti da colpi a distanza per una singola unità." msgid "Mass Shield" msgstr "Max Scudo" #, fuzzy msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Riduce a metà i danni subiti da colpi a distanza per tutte le tue unità." msgid "Summon Earth Elemental" msgstr "Richiama Creature di Terra" msgid "Summons Earth Elementals to fight for your army." msgstr "Convoca creature di terra a combattere per il tuo esercito." msgid "Summon Air Elemental" msgstr "Richiama Creature d'Aria" msgid "Summons Air Elementals to fight for your army." msgstr "Convoca creature d'aria a combattere per il tuo esercito." msgid "Summon Fire Elemental" msgstr "Richiama Creature del Fuoco" msgid "Summons Fire Elementals to fight for your army." msgstr "Convoca Creature del Fuoco a combattere per il tuo esercito." msgid "Summon Water Elemental" msgstr "Richiama Creature dell'Acqua" msgid "Summons Water Elementals to fight for your army." msgstr "Convoca Creature dell'Acqua a combattere per il tuo esercito." msgid "Damages castle walls." msgstr "Colpisce le mura del castello." msgid "Earthquake" msgstr "Terremoto" msgid "Causes all mines across the land to become visible." msgstr "Mostra dove stanno tutte le miniere della mappa." msgid "View Mines" msgstr "Mostra Miniere" msgid "Causes all resources across the land to become visible." msgstr "Mostra dove stanno tutte le risorse della mappa." msgid "View Resources" msgstr "Mostra Risorse" msgid "Causes all artifacts across the land to become visible." msgstr "Mostra dove stanno tutti gli artefatti della mappa." msgid "View Artifacts" msgstr "Mostra Artefatti" msgid "Causes all towns and castles across the land to become visible." msgstr "Mostra dove stanno tutte le città e i castelli della mappa." msgid "View Towns" msgstr "Mostra Città" msgid "Causes all Heroes across the land to become visible." msgstr "Mostra la posizione ed il colore di tutti gli eroi sulla mappa." msgid "View Heroes" msgstr "Mostra Eroi" msgid "Causes the entire land to become visible." msgstr "Rivela tutta la mappa." msgid "View All" msgstr "Mostra Tutto" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "Permette di ottenere informazioni in detaglio sugli eroi del nemico." msgid "Summon Boat" msgstr "Richiama Nave" #, fuzzy msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Convoca una nave attualmente libera, amica e più vicina ad una costa " "adiacente. Una nave amica vuol dire o una che hai appena costruita, o una " "che sei stato l'ultimo ad usare." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Consente a chi invoca la magia di trasportarsi magicamente ad una parte " "della mappa vicina." msgid "Dimension Door" msgstr "Porta Magica" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Trasporta subito chi la lancia ad un qualsiasi castello o città al momento " "posseduto/a." msgid "Town Gate" msgstr "Alle Porte" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Permette all'eroe di scegliere un castello o città a cui tornare, finché " "appartenga all'eroe." msgid "Visions" msgstr "Visioni" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Mostra all'eroe che la usa un risultato probabile di uno scontro con un " "esercito neutrale." msgid "Haunt" msgstr "Stregata" #, fuzzy msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Infesta una miniera vicina al tuo eroe con i fantasmi. La miniera smette di " "produrre risorse (se non lo posso avere io, non l'avrà nessuno!)" msgid "Set Earth Guardian" msgstr "Guardiano di Terra" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Convoca una Creatura di Terra per proteggere una miniera." msgid "Set Air Guardian" msgstr "Guardiano d'Aria" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Convoca una Creatura d'Aria per proteggere una miniera." msgid "Set Fire Guardian" msgstr "Guardiano del Fuoco" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Convoca una Creatura del Fuoco per proteggere una miniera." msgid "Set Water Guardian" msgstr "Guardiano dell'Acqua" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Convoca una Creatura dell'Acqua per proteggere una miniera." #, fuzzy msgid "Random Spell" msgstr "Casuale" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "Castello casuale" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "Pietrificazione" #, fuzzy msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Trasforma la creatura colpita in pietra. Una creatura impietrita subisce " "metà dei danni da un attacco diretto." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" msgid "No spell to cast." msgstr "Nessuna magia disponibile." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Sono rimasti %{point} punti magia al tuo eroe." msgid "View Adventure Spells" msgstr "Mostra Magie d'Avventura" msgid "View Combat Spells" msgstr "Mostra Magie di Battaglia" msgid "View previous page" msgstr "Mostra pag. precedente" msgid "View next page" msgstr "Mostra pag. successiva" msgid "Close Spellbook" msgstr "Chiudi Libro Magie" msgid "View %{spell}" msgstr "Mostra %{spell}" #, fuzzy msgid "This spell does %{damage} points of damage." msgstr "%{tower} fa %{damage} punti di danno." #, fuzzy msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "Getta %{spell} su %{monster}" msgid "This spell restores %{hp} HP." msgstr "" msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" msgid "The nearest town is %{town}." msgstr "" msgid "This town is occupied by your hero %{hero}." msgstr "" msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" msgid "The ultimate artifact is really the %{name}." msgstr "Ho sentito che l'Estremo Artefatto è in verità il/la %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" "L'Estremo Artefatto può essere trovato in un parte del mondo con il/la " "%{name}." msgid "north-west" msgstr "nord-ovest" msgid "north" msgstr "nord" msgid "north-east" msgstr "nord-est" msgid "west" msgstr "ovest" msgid "center" msgstr "centro" msgid "east" msgstr "est" msgid "south-west" msgstr "sud-ovest" msgid "south" msgstr "sud" msgid "south-east" msgstr "sud-est" msgid "The truth is out there." msgstr "Lì fuori da qualche parte sta la verità." msgid "The dark side is stronger." msgstr "Il Lato Oscuro è più potente." msgid "The end of the world is near." msgstr "Sta arrivando La Fine del Mondo." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" "Le ossa di Lord Slayer sono state sepolte sotto il fondamento dell'arena." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Un Drago Nero farà fuori un Titano qualsiasi giorno della settimana." #, fuzzy msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" "Egli ha detto a lei: Bla bla bla... e poi lei ha detto: Bla, bla, bla..." msgid "An unknown force is being resurrected..." msgstr "Una forza sconosciuta sta risorgendo..." #, fuzzy msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Scopri l'ultima versione del gioco su\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Scegli quantità di %{resource}:" #, fuzzy #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "Sei sicuro di voler congedare queste forze?" #~ msgid "Please Remember" #~ msgstr "Non Dimenticare" # Needs extra whitespace to avoid yellow word splitting #, fuzzy #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "Puoi sempre modificare la risoluzione cliccando sulla " #~ msgid "door" #~ msgstr "porta" #~ msgid "Warning!" #~ msgstr "Attenzione!" #, fuzzy #~ msgid "Dummy 1" #~ msgstr "Mummia" fheroes2-1.1.6+dfsg/files/lang/lt.po000066400000000000000000006350331476115357100172010ustar00rootroot00000000000000# Lithuanian translation for fheroes2 # Copyright (C) 2022 fheroes2 team # Copyright (C) 2012-2014 Mantas KriauÄiÅ«nas # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2022-09-23 16:14+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: Lithuanian \n" "Language: lt\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%100<10 || n%100>=20) ? 1 : 2;\n" "X-Launchpad-Export-Date: 2014-12-05 05:56+0000\n" "X-Generator: Poedit 3.1.1\n" msgid "" "NEW\n" "GAME" msgstr "" msgid "" "SAVE\n" "GAME" msgstr "" msgid "" "LOAD\n" "GAME" msgstr "" msgid "INFO" msgstr "" msgid "QUIT" msgstr "" msgid "" "NEW\n" "MAP" msgstr "" msgid "" "SAVE\n" "MAP" msgstr "" msgid "" "LOAD\n" "MAP" msgstr "" msgid "CANCEL" msgstr "" msgid "OKAY" msgstr "" msgid "ACCEPT" msgstr "" msgid "DECLINE" msgstr "" msgid "LEARN" msgstr "" msgid "TRADE" msgstr "" msgid "YES" msgstr "" msgid "NO" msgstr "" msgid "EXIT" msgstr "" msgid "smallerButton|EXIT" msgstr "" msgid "DISMISS" msgstr "" msgid "UPGRADE" msgstr "" msgid "RESTART" msgstr "" msgid "HEROES" msgstr "" msgid "" "TOWNS/\n" "CASTLES" msgstr "" msgid "S" msgstr "" msgid "M" msgstr "" msgid "L" msgstr "" msgid "X-L" msgstr "" msgid "ALL" msgstr "" msgid "SELECT" msgstr "" msgid "" "STANDARD\n" "GAME" msgstr "" msgid "" "BATTLE\n" "ONLY" msgstr "" msgid "" "CAMPAIGN\n" "GAME" msgstr "" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" msgid "CONFIG" msgstr "" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" msgid "HOT SEAT" msgstr "" msgid "2 PLAYERS" msgstr "" msgid "3 PLAYERS" msgstr "" msgid "4 PLAYERS" msgstr "" msgid "5 PLAYERS" msgstr "" msgid "6 PLAYERS" msgstr "" msgid "GIFT" msgstr "" msgid "MAX" msgstr "" msgid "DIFFICULTY" msgstr "" msgid "VIEW INTRO" msgstr "" msgid "MIN" msgstr "" msgid "RESET" msgstr "" msgid "START" msgstr "" msgid "TOWN" msgstr "" msgid "CASTLE" msgstr "" msgid "RESTRICT" msgstr "" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "" msgid "Builder" msgstr "" msgid "Explorer" msgstr "" msgid "None" msgstr "" msgid "" "A few\n" "%{monster}" msgstr "" "Mažai\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Keletas\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Keliolika\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" msgid "" "A horde of\n" "%{monster}" msgstr "" msgid "" "A throng of\n" "%{monster}" msgstr "" msgid "" "A swarm of\n" "%{monster}" msgstr "" msgid "" "Zounds...\n" "%{monster}" msgstr "" msgid "" "A legion of\n" "%{monster}" msgstr "" msgid "army|Few" msgstr "" msgid "army|Several" msgstr "" msgid "army|Pack" msgstr "" msgid "army|Lots" msgstr "" msgid "army|Horde" msgstr "" msgid "army|Throng" msgstr "" msgid "army|Swarm" msgstr "" msgid "army|Zounds" msgstr "" msgid "army|Legion" msgstr "" msgid "All %{race} troops +1" msgstr "" msgid "NeutralRaceTroops|Neutral" msgstr "" msgid "Troops of %{count} alignments -%{penalty}" msgstr "" msgid "Some undead in army -1" msgstr "" msgid "" "Default\n" "troop" msgstr "" msgid "View %{name}" msgstr "ŽiÅ«rÄ—ti %{name}" #, fuzzy msgid "Move the %{name} " msgstr "Prarasti miestÄ… '%{name}'." msgid "Move or right click to redistribute %{name}" msgstr "" msgid "Combine %{name} armies" msgstr "" msgid "Exchange %{name2} with %{name}" msgstr "Sukeisti %{name2} su %{name}" msgid "Select %{name}" msgstr "Pasirinkti %{name}" msgid "Cannot move last troop" msgstr "" #, fuzzy msgid "Move the %{name}" msgstr "Prarasti miestÄ… '%{name}'." #, fuzzy msgid "Set %{monster} Count" msgstr "Pulti %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "" msgstr[1] "" msgstr[2] "" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "Grįžti į mūšį." #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "Grįžti į mūšį." msgid "Spell failed!" msgstr "" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "" msgid "That spell will have no effect!" msgstr "" msgid "You may only summon one type of elemental per combat." msgstr "" msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" msgid "Speed: %{speed}" msgstr "" msgid "Speed" msgstr "Greitis" msgid "Off" msgstr "" msgid "On" msgstr "" msgid "Turn Order" msgstr "" msgid "Auto Spell Casting" msgstr "" msgid "Grid" msgstr "" msgid "Shadow Movement" msgstr "" msgid "Shadow Cursor" msgstr "" msgid "Audio" msgstr "" msgid "Settings" msgstr "" msgid "Configure" msgstr "" msgid "Hot Keys" msgstr "" msgid "Damage Info" msgstr "" msgid "Set the speed of combat actions and animations." msgstr "" msgid "Toggle to display the turn order during the battle." msgstr "" msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" msgid "Change the audio settings of the game." msgstr "" msgid "Check and configure all the hot keys present in the game." msgstr "" msgid "Toggle to display damage information during the battle." msgstr "" #, fuzzy msgid "Exit this menu." msgstr "Å is karys palauks" msgid "Okay" msgstr "Gerai" msgid "The enemy has surrendered!" msgstr "PrieÅ¡as pasidavÄ—!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "PrieÅ¡as pabÄ—go!" msgid "A glorious victory!" msgstr "Å lovinga pergalÄ—!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "" msgid "The cowardly %{name} flees from battle." msgstr "" msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "" msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" msgid "Your forces suffer a bitter defeat." msgstr "" msgid "Battlefield Casualties" msgstr "" msgid "Attacker" msgstr "" msgid "Defender" msgstr "" msgid "Click to leave the battle results." msgstr "" #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "" "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" msgid "Restart" msgstr "" msgid "You have captured an enemy artifact!" msgstr "JÅ«s gavote magiÅ¡kÄ… artefaktÄ… iÅ¡ prieÅ¡o!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "" msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" msgid "Necromancy!" msgstr "" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" msgid "%{name} the %{race}" msgstr "" #, fuzzy msgid "Captain of %{name}" msgstr "Pasamdyti %{name}" msgid "Attack" msgstr "Puolimas" msgid "Defense" msgstr "Gynyba" msgid "Spell Power" msgstr "Burtų galia" msgid "Knowledge" msgstr "IÅ¡manymas" msgid "Morale" msgstr "" msgid "Luck" msgstr "" msgid "Spell Points" msgstr "" msgid "Hero's Options" msgstr "" msgid "Cast Spell" msgstr "" msgid "Retreat" msgstr "" msgid "Surrender" msgstr "Pasiduoti" msgid "Cancel" msgstr "Atsisakyti" msgid "Hero Screen" msgstr "" #, fuzzy msgid "Captain's Options" msgstr "IÅ¡eiti iÅ¡ pilies" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" msgid "Open Hero Screen to view full information about the hero." msgstr "" msgid "Return to the battle." msgstr "Grįžti į mūšį." msgid "Not enough gold (%{gold})" msgstr "Neužtenka aukso (%{gold})" msgid "%{name} states:" msgstr "" #, fuzzy msgid "Captain of %{name} states:" msgstr "Pasamdyti %{name}" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" msgid "View %{monster} info" msgstr "ŽiÅ«rÄ—ti %{monster} informacijÄ…" msgid "Fly %{monster} here" msgstr "" msgid "Move %{monster} here" msgstr "" #, fuzzy msgid "Shoot %{monster}" msgstr "Pulti %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Attack %{monster}" msgstr "Pulti %{monster}" msgid "Turn %{turn}" msgstr "" msgid "Teleport here" msgstr "" msgid "Invalid teleport destination" msgstr "" msgid "Cast %{spell} on %{monster}" msgstr "" msgid "Cast %{spell}" msgstr "" msgid "Select spell target" msgstr "" msgid "View Ballista info" msgstr "" msgid "Ballista" msgstr "" msgid "Automatic combat modes" msgstr "" msgid "Automatic Combat Modes" msgstr "" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "" msgid "Allows you to customize the combat screen." msgstr "" msgid "System Options" msgstr "" msgid "Skip this unit" msgstr "Å is karys praleis Ä—jimÄ…" msgid "Skip" msgstr "" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" msgid "View Captain's options" msgstr "" msgid "View Hero's options" msgstr "" msgid "View opposing Captain" msgstr "" msgid "View opposing Hero" msgstr "" msgid "Hide logs" msgstr "" msgid "Show logs" msgstr "" msgid "Message Bar" msgstr "" msgid "Shows the results of individual monster's actions." msgstr "" #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "" "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "" "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" msgid "The computer continues the combat for you." msgstr "" msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" msgid "Quick Combat" msgstr "" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "" msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "%{name} casts %{spell} on the %{troop}." msgstr "" msgid "%{name} casts %{spell}." msgstr "" msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "" msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "" msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "" msgid "The %{spell} does %{damage} damage." msgstr "" msgid "The %{spell} does %{damage} damage to one living creature." msgstr "" msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "" msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Bad luck descends on the %{attacker}." msgstr "" msgid "Good luck shines on the %{attacker}." msgstr "" msgid "High morale enables the %{monster} to attack again." msgstr "" msgid "Low morale causes the %{monster} to freeze in panic." msgstr "" msgid "%{tower} does %{damage} damage." msgstr "" msgid "The mirror image is created." msgstr "" msgid "The mirror image is destroyed!" msgstr "" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "" "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" msgid "Error" msgstr "" msgid "No spells to cast." msgstr "" msgid "Are you sure you want to retreat?" msgstr "" msgid "Retreat disabled" msgstr "" #, fuzzy msgid "Surrender disabled" msgstr "Pasiduoti" msgid "Damage: %{max}" msgstr "Žala: %{max}" msgid "Damage: %{min} - %{max}" msgstr "" msgid "Perish: %{max}" msgstr "" msgid "Perish: %{min} - %{max}" msgstr "" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" msgid "Human" msgstr "" msgid "AI" msgstr "" msgid "Start" msgstr "" #, fuzzy msgid "Start the battle." msgstr "Grįžti į mūšį." #, fuzzy msgid "Exit" msgstr "IÅ¡eiti iÅ¡ miesto" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "" #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "ŽiÅ«rÄ—ti %{name}" #, fuzzy msgid "Monsters" msgstr "AtsitiktinÄ— pilis" msgid "N/A" msgstr "" msgid "Left Turret" msgstr "Kairysis bokÅ¡telis" msgid "Right Turret" msgstr "DeÅ¡inysis bokÅ¡telis" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "" msgid "each with a +%{attack} bonus to their attack skill." msgstr "" msgid "The %{name} is destroyed." msgstr "" msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "" msgstr[1] "" msgstr[2] "" #, fuzzy msgid "Dwarven Alliance" msgstr "Drakonų miestas" #, fuzzy msgid "Sorceress Guild" msgstr "Vagių gildija" msgid "Necromancer Guild" msgstr "" #, fuzzy msgid "Ogre Alliance" msgstr "Drakonų miestas" msgid "Dwarfbane" msgstr "" #, fuzzy msgid "Dragon Alliance" msgstr "Drakonų miestas" msgid "Elven Alliance" msgstr "" msgid "Kraeger defeated" msgstr "" msgid "Wayward Son" msgstr "" msgid "Uncle Ivan" msgstr "" msgid "Annexation" msgstr "" msgid "Force of Arms" msgstr "" msgid "Save the Dwarves" msgstr "" #, fuzzy msgid "Carator Mines" msgstr "Kristalų kasykla" msgid "Turning Point" msgstr "" msgid "scenarioName|Defender" msgstr "" msgid "Corlagon's Defense" msgstr "" #, fuzzy msgid "The Crown" msgstr "Rytų miestas." msgid "The Gauntlet" msgstr "" msgid "Betrayal" msgstr "" msgid "Final Justice" msgstr "" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" msgid "Barbarian Wars" msgstr "" msgid "First Blood" msgstr "" msgid "Necromancers" msgstr "" msgid "Slay the Dwarves" msgstr "" msgid "Country Lords" msgstr "" msgid "Dragon Master" msgstr "" msgid "Rebellion" msgstr "" msgid "Apocalypse" msgstr "" msgid "Greater Glory" msgstr "" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" msgid "Arrow's Flight" msgstr "" msgid "Island of Chaos" msgstr "" msgid "The Abyss" msgstr "" msgid "Uprising" msgstr "" msgid "Aurora Borealis" msgstr "" msgid "Betrayal's End" msgstr "" msgid "Corruption's Heart" msgstr "" msgid "The Giant's Pass" msgstr "" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" msgid "For the good of the Empire, eliminate Kraeger." msgstr "" msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" #, fuzzy msgid "Border Towns" msgstr "Rodyti miestus" msgid "Conquer and Unify" msgstr "" msgid "Crazy Uncle Ivan" msgstr "" msgid "The Wayward Son" msgstr "" msgid "Ivory Gates" msgstr "" msgid "The Elven Lands" msgstr "" msgid "The Epic Battle" msgstr "" msgid "The Southern War" msgstr "" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "" msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" msgid "Fount of Wizardry" msgstr "" msgid "Power's End" msgstr "" #, fuzzy msgid "The Eternal Scrolls" msgstr "Rytų miestas." msgid "The Shrouded Isles" msgstr "" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" msgid "Blood is Thicker" msgstr "" msgid "King and Country" msgstr "" msgid "Pirate Isles" msgstr "" msgid "Stranded" msgstr "" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" msgid " bane" msgstr "" msgid " alliance" msgstr "" msgid "Carry-over forces" msgstr "" msgid " bonus" msgstr "" msgid " defeated" msgstr "" msgid " will always run away from your army." msgstr "" msgid " will be willing to join your army." msgstr "" msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" msgid "The army will be carried over in the campaign." msgstr "" msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" msgid "%{hero} can be hired during scenarios." msgstr "" msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "" msgid "campaignBonus|Animate Dead" msgstr "" msgid "campaignBonus|Chain Lightning" msgstr "" msgid "campaignBonus|Fireblast" msgstr "" msgid "campaignBonus|Mass Curse" msgstr "" msgid "campaignBonus|Mass Haste" msgstr "" msgid "campaignBonus|Mirror Image" msgstr "" msgid "campaignBonus|Resurrect" msgstr "" #, fuzzy msgid "campaignBonus|Steelskin" msgstr "Gynybos įgÅ«dis" msgid "campaignBonus|Summon Earth" msgstr "" msgid "campaignBonus|View Heroes" msgstr "" msgid "campaignBonus|Ballista" msgstr "" msgid "campaignBonus|Black Pearl" msgstr "" msgid "campaignBonus|Caster's Bracelet" msgstr "" #, fuzzy msgid "campaignBonus|Defender Helm" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Breastplate" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Dragon Sword" msgstr "Drakonų miestas" msgid "campaignBonus|Fizbin Medal" msgstr "" msgid "campaignBonus|Foremost Scroll" msgstr "" #, fuzzy msgid "campaignBonus|Gauntlets" msgstr "Turgus" msgid "campaignBonus|Hideous Mask" msgstr "" msgid "campaignBonus|Mage's Ring" msgstr "" msgid "campaignBonus|Major Scroll" msgstr "" msgid "campaignBonus|Medal of Honor" msgstr "" msgid "campaignBonus|Medal of Valor" msgstr "" msgid "campaignBonus|Minor Scroll" msgstr "" msgid "campaignBonus|Nomad Boots" msgstr "" msgid "campaignBonus|Power Axe" msgstr "" msgid "campaignBonus|Spiked Shield" msgstr "" msgid "campaignBonus|Stealth Shield" msgstr "" msgid "campaignBonus|Tax Lien" msgstr "" msgid "campaignBonus|Thunder Mace" msgstr "" msgid "campaignBonus|Traveler's Boots" msgstr "" msgid "campaignBonus|White Pearl" msgstr "" #, fuzzy msgid "campaignBonus|Basic Archery" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Archery" msgstr "Pažangus Å¡audymas" #, fuzzy msgid "campaignBonus|Expert Archery" msgstr "Eksperto Å¡audymas" #, fuzzy msgid "campaignBonus|Basic Ballistics" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Ballistics" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Expert Ballistics" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Basic Diplomacy" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Diplomacy" msgstr "Pažangi diplomatija" #, fuzzy msgid "campaignBonus|Expert Diplomacy" msgstr "Eksperto diplomatija" #, fuzzy msgid "campaignBonus|Basic Eagle Eye" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Eagle Eye" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Expert Eagle Eye" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Basic Estates" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Estates" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Expert Estates" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Basic Leadership" msgstr "PradinÄ— lyderystÄ—" #, fuzzy msgid "campaignBonus|Advanced Leadership" msgstr "Pažangi lyderystÄ—" #, fuzzy msgid "campaignBonus|Expert Leadership" msgstr "Eksperto lyderystÄ—" #, fuzzy msgid "campaignBonus|Basic Logistics" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Logistics" msgstr "Drakonų miestas" #, fuzzy msgid "campaignBonus|Expert Logistics" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Basic Luck" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Luck" msgstr "Drakonų miestas" #, fuzzy msgid "campaignBonus|Expert Luck" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Basic Mysticism" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Mysticism" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Expert Mysticism" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Basic Navigation" msgstr "PradinÄ— navigacija" #, fuzzy msgid "campaignBonus|Advanced Navigation" msgstr "Pažangi navigacija" #, fuzzy msgid "campaignBonus|Expert Navigation" msgstr "Eksperto navigacija" #, fuzzy msgid "campaignBonus|Basic Necromancy" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Necromancy" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Expert Necromancy" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Basic Pathfinding" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Pathfinding" msgstr "Drakonų miestas" #, fuzzy msgid "campaignBonus|Expert Pathfinding" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Basic Scouting" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Advanced Scouting" msgstr "Drakonų miestas" #, fuzzy msgid "campaignBonus|Expert Scouting" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "campaignBonus|Basic Wisdom" msgstr "Turgus" #, fuzzy msgid "campaignBonus|Advanced Wisdom" msgstr "Pažangi iÅ¡mintis" #, fuzzy msgid "campaignBonus|Expert Wisdom" msgstr "Gynybos įgÅ«dis" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" msgid "The starting alignment of the scenario will be %{race}." msgstr "" msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" msgid "The main hero will have %{skill} at the start of the scenario." msgstr "" msgid "Roland" msgstr "" msgid "Archibald" msgstr "" msgid "Price of Loyalty" msgstr "" msgid "Voyage Home" msgstr "" msgid "Wizard's Isle" msgstr "" msgid "Descendants" msgstr "" msgid "Cannot build. You have already built here today." msgstr "" msgid "For this action it is necessary to build a castle first." msgstr "Pradžioje bÅ«tina pastatyti pilį." msgid "The %{building} produces %{monster}." msgstr "" msgid "Requires:" msgstr "Reikalauja:" msgid "Exit this menu without doing anything." msgstr "" #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Negalima statyti %{name} kadangi pilis yra per toli nuo vandens." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Užimti miestÄ… '%{name}'" msgid "The %{name} is already built." msgstr "" #, fuzzy msgid "Cannot build the %{name}." msgstr "ŽiÅ«rÄ—ti %{name}" #, fuzzy msgid "Build %{name}." msgstr "ŽiÅ«rÄ—ti %{name}" #, fuzzy msgid "Blackridge" msgstr "Tiltas" msgid "Hillstone" msgstr "" msgid "Pinehurst" msgstr "" msgid "Whiteshield" msgstr "" #, fuzzy msgid "Woodhaven" msgstr "Mediena" #, fuzzy msgid "Blackwind" msgstr "KalvÄ—" msgid "Bloodreign" msgstr "" #, fuzzy msgid "Dragontooth" msgstr "Drakonų miestas" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" msgid "Tundara" msgstr "" msgid "Vulcania" msgstr "" msgid "Baywatch" msgstr "" msgid "Fountainhead" msgstr "" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" msgid "Sandcaster" msgstr "" msgid "Alamar" msgstr "" msgid "Burlock" msgstr "" #, fuzzy msgid "Dragadune" msgstr "Drakonų miestas" msgid "Kalindra" msgstr "" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" #, fuzzy msgid "Blackfang" msgstr "Juodas bokÅ¡tas" msgid "New Dawn" msgstr "" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" msgid "Antioch" msgstr "" msgid "Avalon" msgstr "" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" msgid "Weed Patch" msgstr "" msgid "Brownston" msgstr "" msgid "Hilltop" msgstr "" msgid "Weddington" msgstr "" msgid "Westfork" msgstr "" msgid "Whittingham" msgstr "" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "" msgid "Roscomon" msgstr "" msgid "Sherman" msgstr "" msgid "Yorksford" msgstr "" #, fuzzy msgid "Blackburn" msgstr "Juodas bokÅ¡tas" #, fuzzy msgid "Blacksford" msgstr "Juodas bokÅ¡tas" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "" msgid "Lankershire" msgstr "" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "" msgid "Troy" msgstr "" #, fuzzy msgid "Forder Oaks" msgstr "Rodyti miestus" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "" msgid "Willow" msgstr "" msgid "Corackston" msgstr "" msgid "Sheltemburg" msgstr "" msgid "Cannot recruit - you already have a Hero in this town." msgstr "" msgid "Cannot recruit - you have too many Heroes." msgstr "" msgid "Cannot afford a Hero." msgstr "" msgid "There is no room in the garrison for this army." msgstr "" msgid "Fortifications" msgstr "Ä®tvirtinimai" msgid "Farm" msgstr "Ferma" msgid "Thatched Hut" msgstr "" msgid "Archery Range" msgstr "" msgid "Upg. Archery Range" msgstr "" msgid "Blacksmith" msgstr "KalvÄ—" msgid "Upg. Blacksmith" msgstr "GeresnÄ— kalvÄ—" msgid "Armory" msgstr "" msgid "Upg. Armory" msgstr "" msgid "Jousting Arena" msgstr "Riterių arena" msgid "Upg. Jousting Arena" msgstr "GeresnÄ— riterių arena" msgid "Cathedral" msgstr "Katedra" msgid "Upg. Cathedral" msgstr "GeresnÄ— katedra" msgid "Coliseum" msgstr "Koliziejus" msgid "Garbage Heap" msgstr "" msgid "Hut" msgstr "" msgid "Stick Hut" msgstr "" msgid "Upg. Stick Hut" msgstr "" msgid "Den" msgstr "Ola" msgid "Adobe" msgstr "Moliniai nameliai" msgid "Upg. Adobe" msgstr "" msgid "Bridge" msgstr "Tiltas" msgid "Upg. Bridge" msgstr "Tobulesnis tiltas" msgid "Pyramid" msgstr "PiramidÄ—" msgid "Rainbow" msgstr "VaivorykÅ¡tÄ—" msgid "Crystal Garden" msgstr "" msgid "Treehouse" msgstr "Namelis medyje" msgid "Cottage" msgstr "" msgid "Upg. Cottage" msgstr "" msgid "Stonehenge" msgstr "" msgid "Upg. Stonehenge" msgstr "" msgid "Fenced Meadow" msgstr "Aptverta pieva" #, fuzzy msgid "sorceress|Red Tower" msgstr "Raudonas bokÅ¡tas" msgid "Dungeon" msgstr "Požemiai" msgid "Waterfall" msgstr "Krioklys" msgid "Cave" msgstr "Urvas" msgid "Crypt" msgstr "" msgid "Nest" msgstr "Lizdas" msgid "Maze" msgstr "Labirintas" msgid "Upg. Maze" msgstr "Tobulesnis labirintas" msgid "Swamp" msgstr "PelkÄ—" msgid "Green Tower" msgstr "Žalias bokÅ¡tas" #, fuzzy msgid "warlock|Red Tower" msgstr "Raudonas bokÅ¡tas" msgid "Black Tower" msgstr "Juodas bokÅ¡tas" msgid "Library" msgstr "Biblioteka" msgid "Orchard" msgstr "Vaisių sodas" msgid "Habitat" msgstr "" msgid "Pen" msgstr "" msgid "Foundry" msgstr "Liejykla" msgid "Upg. Foundry" msgstr "GeresnÄ— liejykla" msgid "Cliff Nest" msgstr "Lizdas ant uolos" msgid "Ivory Tower" msgstr "Burtininkų bokÅ¡tas" msgid "Upg. Ivory Tower" msgstr "Tobulesnis burtininkų bokÅ¡tas" msgid "Cloud Castle" msgstr "Dangaus pilis" msgid "Upg. Cloud Castle" msgstr "GeresnÄ— dangaus pilis" msgid "Storm" msgstr "Audra" msgid "Skull Pile" msgstr "" msgid "Excavation" msgstr "" msgid "Graveyard" msgstr "KapinÄ—s" msgid "Upg. Graveyard" msgstr "GeresnÄ—s kapinÄ—s" msgid "Upg. Pyramid" msgstr "Didžioji piramidÄ—" msgid "Mansion" msgstr "Apleisti rÅ«mai" msgid "Upg. Mansion" msgstr "" msgid "Mausoleum" msgstr "Mauzoliejus" msgid "Upg. Mausoleum" msgstr "" msgid "Laboratory" msgstr "Laboratorija" msgid "Shrine" msgstr "" msgid "Special" msgstr "" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "Dwelling 2" msgstr "Gynybos įgÅ«dis" msgid "Upg. Dwelling 2" msgstr "" #, fuzzy msgid "Dwelling 3" msgstr "Gynybos įgÅ«dis" msgid "Upg. Dwelling 3" msgstr "" #, fuzzy msgid "Dwelling 4" msgstr "Gynybos įgÅ«dis" msgid "Upg. Dwelling 4" msgstr "" #, fuzzy msgid "Dwelling 5" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "Dwelling 6" msgstr "Gynybos įgÅ«dis" msgid "Upg. Dwelling 6" msgstr "" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" msgid "The Rainbow increases the luck of the defending units by two." msgstr "" msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" #, fuzzy msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "" "Požeminiai rÅ«siai padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Å ulinys padidina prieaugį visuose bÅ«stuose % {count} bÅ«tybÄ—m per savaitÄ™." msgid "Thieves' Guild" msgstr "Vagių gildija" msgid "Tavern" msgstr "Taverna" msgid "Shipyard" msgstr "Laivų statykla" msgid "Well" msgstr "Å ulinys" msgid "Statue" msgstr "Statula" msgid "Marketplace" msgstr "Turgus" msgid "Moat" msgstr "" msgid "Castle" msgstr "Pilis" msgid "Tent" msgstr "PalapinÄ—" msgid "Captain's Quarters" msgstr "" msgid "Mage Guild, Level 1" msgstr "" msgid "Mage Guild, Level 2" msgstr "" msgid "Mage Guild, Level 3" msgstr "" msgid "Mage Guild, Level 4" msgstr "" msgid "Mage Guild, Level 5" msgstr "" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" msgid "The Tavern increases morale for troops defending the castle." msgstr "" msgid "The Shipyard allows ships to be built." msgstr "Laivų statykla leidžia statyti laivus." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Å ulinys padidina prieaugį visuose bÅ«stuose % {count} bÅ«tybÄ—m per savaitÄ™." #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" msgid "The Right Turret provides extra firepower during castle combat." msgstr "" msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Turguje galima iÅ¡keisti vienokius iÅ¡teklius į kitokius (pvz. rÅ«dÄ… į " "gyvsidabrį). Kuo daugiau turÄ—site turgų, tuo geresniu santykiu galÄ—site " "keisti." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Pilis sustiprina miesto gynybÄ… bei padidina pajamas %{count} aukso monetų " "per dienÄ…." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" msgid "Recruit %{name}" msgstr "Pasamdyti %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "MÄ—nuo: %{month}, SavaitÄ—: %{week}, Diena: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" #, fuzzy msgid "Click to show next town." msgstr "Rodyti kitÄ… miestÄ…" msgid "Show next town" msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Click to show previous town." msgstr "Rodyti ankstesnį miestÄ…" msgid "Show previous town" msgstr "Rodyti ankstesnį miestÄ…" msgid "This town may not be upgraded to a castle." msgstr "" msgid "Town" msgstr "Miestelis" #, fuzzy msgid "Exit Castle" msgstr "IÅ¡eiti iÅ¡ pilies" #, fuzzy msgid "Exit Town" msgstr "IÅ¡eiti iÅ¡ miesto" msgid "Show Income" msgstr "" msgid "View Hero" msgstr "" #, fuzzy msgid "The above spells are available here." msgstr "Å ie burtai buvo įdÄ—ti į jÅ«sų knygÄ…." #, fuzzy msgid "The spells the hero can learn have been added to their book." msgstr "Å ie burtai buvo įdÄ—ti į jÅ«sų knygÄ…." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" msgid "Recruit Hero" msgstr "" msgid "%{name} is a level %{value} %{race} " msgstr "" #, fuzzy msgid "with %{count} artifacts." msgstr " su vienu artefaktu" #, fuzzy msgid "with 1 artifact." msgstr " su vienu artefaktu" #, fuzzy msgid "without artifacts." msgstr " su vienu artefaktu" msgid "Recruit %{name} the %{race}" msgstr "" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" msgid "Spread Formation" msgstr "" msgid "Grouped Formation" msgstr "" #, fuzzy msgid "Click to show the next town." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Click to show the previous town." msgstr "Rodyti ankstesnį miestÄ…" msgid "Set garrison combat formation to 'Spread'" msgstr "" msgid "Set garrison combat formation to 'Grouped'" msgstr "" #, fuzzy msgid "Exit Castle Options" msgstr "IÅ¡eiti iÅ¡ pilies" msgid "Castle Options" msgstr "" msgid "Not enough resources to recruit creatures." msgstr "" msgid "You are unable to recruit at this time, your ranks are full." msgstr "" msgid "No creatures available for purchase." msgstr "" #, fuzzy msgid "Recruit Creatures" msgstr "Pasamdyti %{name}" #, fuzzy msgid "Hire all creatures in the town." msgstr "Prarasti visus savo herojus bei miestus." msgid "Max" msgstr "" msgid "Available" msgstr "" msgid "Town Population Information and Statistics" msgstr "Miesto gyventojų informacija bei statistika" msgid "Damage" msgstr "" msgid "HP" msgstr "" msgid "Growth" msgstr "" msgid "week" msgstr "savait." #, fuzzy msgid "View World" msgstr "Rodyti miestus" msgid "View the entire world." msgstr "" msgid "Puzzle" msgstr "" msgid "View the obelisk puzzle." msgstr "" msgid "Scenario Information" msgstr "" msgid "View information on the scenario you are currently playing." msgstr "" msgid "Dig for the Ultimate Artifact." msgstr "" msgid "Digging" msgstr "" msgid "Arena" msgstr "" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" msgid "Attack Skill" msgstr "Puolimo įgÅ«dis" msgid "Defense Skill" msgstr "Gynybos įgÅ«dis" msgid "Shots" msgstr "Å Å«viai" msgid "Shots Left" msgstr "" msgid "Hit Points" msgstr "" msgid "Hit Points Left" msgstr "" msgid "You can't afford to upgrade your troops!" msgstr "" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" msgid "Are you sure you want to dismiss this army?" msgstr "" msgid "Upgrade" msgstr "" msgid "Upgrade your troops." msgstr "" msgid "Dismiss" msgstr "" msgid "Dismiss this army." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" #, fuzzy msgid "Followers" msgstr "Burtų galia" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" msgid "(Rate: %{percent})" msgstr "" msgid "off" msgstr "" msgid "Music" msgstr "" msgid "Effects" msgstr "" msgid "MIDI" msgstr "" #, fuzzy msgid "MIDI Expansion" msgstr "Apleisti rÅ«mai" msgid "External" msgstr "" msgid "Music Type" msgstr "" msgid "3D Audio" msgstr "" msgid "Toggle ambient music level." msgstr "" msgid "Toggle foreground sounds level." msgstr "" msgid "Change the type of music." msgstr "" msgid "Toggle the 3D effect of foreground sounds." msgstr "" msgid "Build a new ship:" msgstr "Statyti naujÄ… laivÄ…:" msgid "Resource cost:" msgstr "IÅ¡teklio kaina:" msgid "Total: " msgstr "" msgid "Need: " msgstr "" msgid "New Game" msgstr "" msgid "Start a single or multi-player game." msgstr "" msgid "Load Game" msgstr "Ä®kelti žaidimÄ…" msgid "Load a previously saved game." msgstr "Atverti prieÅ¡ tai įraÅ¡ytÄ… žaidimÄ…" #, fuzzy msgid "Save Game" msgstr "Ä®kelti žaidimÄ…" msgid "Save the current game." msgstr "" msgid "Quit" msgstr "" msgid "Quit out of Heroes of Might and Magic II." msgstr "" msgid "Language" msgstr "" msgid "Graphics" msgstr "" #, fuzzy msgid "Black & White" msgstr "Tiltas" msgid "Mouse Cursor" msgstr "" msgid "Color" msgstr "" msgid "Text Support" msgstr "" msgid "Change the language of the game." msgstr "" msgid "Select Game Language" msgstr "" msgid "Change the graphics settings of the game." msgstr "" msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" msgid "" "Map\n" "Difficulty" msgstr "" "ŽemÄ—lapis\n" "SudÄ—tingumas" msgid "" "Game\n" "Difficulty" msgstr "" "Žaidimas\n" "SudÄ—tingumas" msgid "Rating" msgstr "" msgid "Map Size" msgstr "" "Pasaulio\n" "dydis" msgid "Opponents" msgstr "" msgid "Class" msgstr "" msgid "" "Victory\n" "Conditions" msgstr "" msgid "" "Loss\n" "Conditions" msgstr "" msgid "First select recipients!" msgstr "" msgid "You cannot select %{resource}!" msgstr "" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Pulti %{monster}" msgid "Select Recipients" msgstr "" msgid "Your Funds" msgstr "" msgid "Planned Gift" msgstr "" #, fuzzy msgid "Gift from %{name}" msgstr "Pasamdyti %{name}" msgid "Resolution" msgstr "" msgid "Fullscreen" msgstr "" msgid "window|Mode" msgstr "" msgid "Windowed" msgstr "" msgid "V-Sync" msgstr "" msgid "FPS" msgstr "" msgid "System Info" msgstr "" msgid "Change the resolution of the game." msgstr "" msgid "Select Game Resolution" msgstr "" msgid "Toggle between fullscreen and windowed modes." msgstr "" msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" msgid "Show extra information such as FPS and current time." msgstr "" msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" msgid "Event: " msgstr "" msgid "Hot Keys:" msgstr "" msgid "Hide" msgstr "" msgid "Show" msgstr "" msgid "Interface" msgstr "" msgid "Interface Type" msgstr "" msgid "Toggle the type of interface you want to use." msgstr "" msgid "Toggle interface visibility." msgstr "" msgid "Scroll Speed" msgstr "" msgid "Sets the speed at which you scroll the window." msgstr "" msgid "Select Game Language:" msgstr "" #, fuzzy msgid "Select Language:" msgstr "Pasirinkti %{name}" msgid "Click to choose the selected language." msgstr "" msgid "%{name} has gained a level." msgstr "" #, fuzzy msgid "%{skill} +1" msgstr "ŽiÅ«rÄ—ti %{skill} informacijÄ…" msgid "You have learned %{skill}." msgstr "JÅ«s iÅ¡mokote %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "" msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" #, fuzzy msgid "Min" msgstr "Apleisti rÅ«mai" msgid "Qty to trade" msgstr "" msgid "Trading Post" msgstr "" msgid "Your Resources" msgstr "Tavo iÅ¡tekliai" msgid "Available Trades" msgstr "" msgid "guarded by %{count} %{monster}" msgstr "" msgid "guarded by " msgstr "" msgid "(available: %{count})" msgstr "" msgid "(empty)" msgstr "" msgid "already learned" msgstr "" #, fuzzy msgid "treeOfKnowledge|free" msgstr "IÅ¡manymas" msgid "already claimed" msgstr "" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "jau moka šį įgÅ«dį" msgid "already has max skills" msgstr "" msgid "(already visited)" msgstr "" msgid "(not visited)" msgstr "" msgid "%{color} Barrier" msgstr "" msgid "(tent visited)" msgstr "" msgid "%{color} Tent" msgstr "" msgid "Road" msgstr "" msgid "(digging ok)" msgstr "" msgid "(no digging)" msgstr "" msgid "penalty: %{cost}" msgstr "" msgid "Defenders:" msgstr "" msgid "Unknown" msgstr "" msgid "heroQuickInfo|(Level %{level})" msgstr "" #, fuzzy msgid "Attack:" msgstr "Puolimas" #, fuzzy msgid "Defense:" msgstr "Gynyba" #, fuzzy msgid "Spell Power:" msgstr "Burtų galia" #, fuzzy msgid "Knowledge:" msgstr "IÅ¡manymas" #, fuzzy msgid "Spell Points:" msgstr "Burtų galia" msgid "Move Points:" msgstr "" msgid "Uncharted Territory" msgstr "" msgid "Cost per troop:" msgstr "" msgid "Available: %{count}" msgstr "Yra: %{count}" msgid "Number to buy:" msgstr "Norimas kiekis:" msgid "Recruit selected monsters." msgstr "" msgid "Select maximum monsters to be recruited." msgstr "" msgid "Select only 1 monster to be recruited." msgstr "" msgid "Select this game resolution." msgstr "" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "" msgid "Click to apply the selected resolution." msgstr "" msgid "Click to apply the entered text." msgstr "" msgid "Click to open the Virtual Keyboard dialog." msgstr "" msgid "Open Virtual Keyboard" msgstr "" msgid "How many creatures do you wish to move?" msgstr "" msgid "Select how many units to separate into:" msgstr "" msgid "Map: " msgstr "" msgid "" "\n" "\n" "Month: " msgstr "" msgid ", Week: " msgstr "" msgid ", Day: " msgstr "" msgid "" "\n" "\n" "Location: " msgstr "" msgid "Are you sure you want to delete file:" msgstr "Ar jÅ«s tikrai norite iÅ¡trinti failÄ…:" msgid "Warning" msgstr "" msgid "Click to save the current game." msgstr "" #, fuzzy msgid "Click to load a previously saved game." msgstr "Atverti prieÅ¡ tai įraÅ¡ytÄ… žaidimÄ…" msgid "File to Save:" msgstr "Ä®raÅ¡yti į failÄ…:" msgid "File to Load:" msgstr "Failas įkÄ—limui:" msgid "Terrain object" msgstr "" msgid "Accept the choice made." msgstr "" #, fuzzy msgid "Select Skill:" msgstr "Gynybos įgÅ«dis" msgid "Select Spell:" msgstr "" #, fuzzy msgid "Select Artifact:" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "Select Monster:" msgstr "Pasirinkti %{name}" #, fuzzy msgid "Select Hero:" msgstr "Pasirinkti %{name}" msgid "race|Random" msgstr "" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Rodyti kitÄ… miestÄ…" msgid "%{color} %{race}" msgstr "" msgid "You will place" msgstr "" msgid "Click to select this class." msgstr "" #, fuzzy msgid "Click to select this color." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Select Treasure:" msgstr "Pasirinkti %{name}" #, fuzzy msgid "Select Ocean Object:" msgstr "MagiÅ¡kas artefaktas" msgid "Castle/town placing" msgstr "" msgid "doubleLinedRace|Neutral" msgstr "" msgid "Click to start placing the selected castle/town." msgstr "" #, fuzzy msgid "Click to select town placing." msgstr "Rodyti kitÄ… miestÄ…" msgid "Click to select castle placing." msgstr "" msgid "%{color} %{race} %{townOrCastle}" msgstr "" msgid "race|Neutral" msgstr "" #, fuzzy msgid "Select Dwelling:" msgstr "Gynybos įgÅ«dis" #, fuzzy msgid "Select Landscape Object:" msgstr "MagiÅ¡kas artefaktas" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "IÅ¡tekliai" msgid "%{mineName} appearance:" msgstr "" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" #, fuzzy msgid "Select Mountain Object:" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "Select Rock Object:" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "Select Tree Object:" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "Select Power Up Object:" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "Select Adventure Object:" msgstr "MagiÅ¡kas artefaktas" msgid "Players Icon" msgstr "" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" msgid "Size Icon" msgstr "" #, fuzzy msgid "Map Type" msgstr "Pasaulio dydis" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" #, fuzzy msgid "Map Type:\n" msgstr "Pasaulio dydis" msgid "The Succession Wars" msgstr "" msgid "The Price of Loyalty" msgstr "" msgid "Resurrection" msgstr "" msgid "" "\n" "\n" "Language:\n" msgstr "" msgid "Lose all your heroes and towns." msgstr "Prarasti visus savo herojus bei miestus." msgid "Lose a specific town." msgstr "Prarasti konkretų miestÄ…." msgid "Lose a specific hero." msgstr "" msgid "Run out of time. Fail to win by a certain point." msgstr "" msgid "Loss Condition" msgstr "PralaimÄ—jimo sÄ…lygos" msgid "Defeat all enemy heroes and towns." msgstr "NugalÄ—ti visus priešų herojus bei miestus." msgid "Capture a specific town." msgstr "Užimti konkretų miestÄ…." msgid "Defeat a specific hero." msgstr "" msgid "Find a specific artifact." msgstr "Rasti konkretų magiÅ¡kÄ… artefaktÄ…." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "Prarasti miestÄ… '%{name}'." msgid "Accumulate a large amount of gold." msgstr "Sukaupti labai daug aukso." msgid "Victory Condition" msgstr "PergalÄ—s salygos" #, fuzzy msgid "Map difficulty:" msgstr "" "ŽemÄ—lapis\n" "SudÄ—tingumas" msgid "N" msgstr "" msgid "No maps exist at that size." msgstr "" msgid "Small Maps" msgstr "Maži žemÄ—lapiai" msgid "View only maps of size small (36 x 36)." msgstr "" msgid "Medium Maps" msgstr "Vidutiniai žemÄ—lapiai" msgid "View only maps of size medium (72 x 72)." msgstr "" msgid "Large Maps" msgstr "Dideli žemÄ—lapiai" msgid "View only maps of size large (108 x 108)." msgstr "" msgid "Extra Large Maps" msgstr "YpaÄ dideli žemÄ—lapiai" msgid "View only maps of size extra large (144 x 144)." msgstr "" msgid "All Maps" msgstr "Visi žemÄ—lapiai" msgid "View all maps, regardless of size." msgstr "" msgid "Selected Name" msgstr "" msgid "The name of the currently selected map." msgstr "" msgid "Selected Map Difficulty" msgstr "" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" msgid "Selected Description" msgstr "" msgid "The description of the currently selected map." msgstr "" msgid "Jump" msgstr "" #, fuzzy msgid "Hero Speed" msgstr "Greitis" msgid "Don't Show" msgstr "" #, fuzzy msgid "Enemy Speed" msgstr "Greitis" msgid "Auto Resolve" msgstr "" msgid "Auto, No Spells" msgstr "" msgid "Battles" msgstr "" msgid "combatMode|Manual" msgstr "" msgid "Change the speed at which your heroes move on the main screen." msgstr "" msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" msgid "Change the interface settings of the game." msgstr "" msgid "Interface Settings" msgstr "" msgid "Toggle instant battle mode." msgstr "" msgid "Att." msgstr "" msgid "Def." msgstr "" msgid "Power" msgstr "" #, fuzzy msgid "Knowl" msgstr "IÅ¡manymas" msgid "1st" msgstr "" msgid "2nd" msgstr "" msgid "3rd" msgstr "" msgid "4th" msgstr "" msgid "5th" msgstr "" msgid "6th" msgstr "" msgid "Oracle: Player Rankings" msgstr "" #, fuzzy msgid "Thieves' Guild: Player Rankings" msgstr "Vagių gildija" msgid "Number of Towns:" msgstr "Miestų kiekis:" msgid "Number of Castles:" msgstr "Pilių kiekis:" msgid "Number of Heroes:" msgstr "Herojų kiekis:" msgid "Gold in Treasury:" msgstr "Aukso saugyklose:" msgid "Wood & Ore:" msgstr "Mediena bei rÅ«da:" msgid "Gems, Cr, Slf & Mer:" msgstr "" msgid "Obelisks Found:" msgstr "" #, fuzzy msgid "Artifacts:" msgstr "MagiÅ¡kas artefaktas" msgid "Total Army Strength:" msgstr "" msgid "Income:" msgstr "" msgid "Best Hero:" msgstr "" msgid "Best Hero Stats:" msgstr "" msgid "Personality:" msgstr "" msgid "Best Monster:" msgstr "" #, fuzzy msgid "Random Castle Name" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Town Name" msgstr "Atsitiktinis miestas" #, fuzzy msgid "Allow Castle build" msgstr "Dangaus pilis" #, fuzzy msgid "Default Buildings" msgstr "Gynybos įgÅ«dis" msgid "Default Army" msgstr "" #, fuzzy msgid "Castle Army" msgstr "Pilis" #, fuzzy msgid "Town Army" msgstr "Miestelis" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "IÅ¡eiti iÅ¡ pilies" msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" msgid "Message Text:" msgstr "" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" msgid "Message:" msgstr "" #, fuzzy msgid "Click to save the Event properties." msgstr "Rodyti kitÄ… miestÄ…" msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "IÅ¡tekliai" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Rodyti kitÄ… miestÄ…" msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Rodyti kitÄ… miestÄ…" msgid "Add Event" msgstr "" msgid "Add an additional event." msgstr "" msgid "Edit Event" msgstr "" msgid "Edit an existing event." msgstr "" msgid "Delete Event" msgstr "" msgid "Delete an existing event." msgstr "" msgid "Effects:" msgstr "" #, fuzzy msgid "Conditions:" msgstr "PralaimÄ—jimo sÄ…lygos" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" msgid "Set Experience value" msgstr "" msgid "Artifact" msgstr "MagiÅ¡kas artefaktas" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "MagiÅ¡kas artefaktas" msgid "Delete an artifact from the event." msgstr "" msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Gynybos įgÅ«dis" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" msgid "%{objects} cannot be placed on water." msgstr "" msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" msgid "%{objects} must be placed on water." msgstr "" msgid "Objects cannot be placed outside the map." msgstr "" msgid "Action objects must be placed on clear tiles." msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Ar tikrai norite įkelti anksÄiau įraÅ¡ytÄ… žaidimÄ…? (Dabartinis žaidimas bus " "prarastas, jei neįrašėte)" msgid "Editor" msgstr "" #, fuzzy msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Ar tikrai norite įkelti anksÄiau įraÅ¡ytÄ… žaidimÄ…? (Dabartinis žaidimas bus " "prarastas, jei neįrašėte)" #, fuzzy msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Ar tikrai norite įkelti anksÄiau įraÅ¡ytÄ… žaidimÄ…? (Dabartinis žaidimas bus " "prarastas, jei neįrašėte)" msgid "" "MAIN\n" "MENU" msgstr "" msgid "" "START\n" "MAP" msgstr "" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Ar tikrai norite įkelti anksÄiau įraÅ¡ytÄ… žaidimÄ…? (Dabartinis žaidimas bus " "prarastas, jei neįrašėte)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Ä®kelti žaidimÄ…" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Ar tikrai norite įkelti anksÄiau įraÅ¡ytÄ… žaidimÄ…? (Dabartinis žaidimas bus " "prarastas, jei neįrašėte)" msgid "Create a new map from scratch." msgstr "" msgid "New Map" msgstr "" #, fuzzy msgid "Load Map" msgstr "Ä®kelti žaidimÄ…" msgid "Load an existing map." msgstr "" #, fuzzy msgid "Save Map" msgstr "Ä®kelti žaidimÄ…" msgid "Save the current map." msgstr "" msgid "Quit out of the map editor." msgstr "" #, fuzzy msgid "Return to the game's Main Menu." msgstr "Grįžti į mūšį." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Rasti magiÅ¡kÄ… artefaktÄ… '%{name}'" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr " su vienu artefaktu" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "" msgid "Streams" msgstr "" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "" msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" msgid "The map is corrupted." msgstr "" msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "" #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Ä®raÅ¡yti į failÄ…:" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "" "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "Ä®raÅ¡yti į failÄ…:" #, fuzzy msgid "Used to place %{object}." msgstr "Rasti magiÅ¡kÄ… artefaktÄ… '%{name}'" #, fuzzy msgid "Select object type" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Rodyti kitÄ… miestÄ…" msgid "" "Cell\n" "Details" msgstr "" msgid "Erase" msgstr "" msgid "Mountains" msgstr "" msgid "Rocks" msgstr "" msgid "Trees" msgstr "" msgid "Water Objects" msgstr "" msgid "Miscellaneous" msgstr "" msgid "Artifacts" msgstr "" msgid "Dwellings" msgstr "" msgid "Mines" msgstr "" msgid "Power-ups" msgstr "" msgid "Treasures" msgstr "" msgid "Heroes" msgstr "" #, fuzzy msgid "Towns" msgstr "Miestelis" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "MagiÅ¡kas artefaktas" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" #, fuzzy msgid "Small Brush" msgstr "Maži žemÄ—lapiai" #, fuzzy msgid "Medium Brush" msgstr "Vidutiniai žemÄ—lapiai" #, fuzzy msgid "Large Brush" msgstr "Dideli žemÄ—lapiai" msgid "Area Fill" msgstr "" msgid "Used to click and drag for filling in large areas." msgstr "" msgid "Clear Area" msgstr "" msgid "Used to click and drag for clearing large areas." msgstr "" msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" msgid "Traversable only by boat." msgstr "" msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" #, fuzzy msgid "Used for special editing of action objects." msgstr "NugalÄ—ti visus priešų herojus bei miestus." msgid "Adventure Objects Mode" msgstr "" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" msgid "Kingdom Objects Mode" msgstr "" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Used to place monsters on the map." msgstr "Rasti magiÅ¡kÄ… artefaktÄ… '%{name}'" msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" msgid "Road Mode" msgstr "" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" #, fuzzy msgid "Specifications" msgstr "Ä®tvirtinimai" msgid "File Options" msgstr "" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" msgid "View the editor system options, which let you customize the editor." msgstr "" msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" msgid "Cancel back to the New Map menu." msgstr "" msgid "Cancel back to the main menu." msgstr "" msgid "From Scratch" msgstr "" msgid "Start from scratch with a blank map." msgstr "" msgid "Create a randomly generated map." msgstr "" #, fuzzy msgid "Random" msgstr "Atsitiktinis miestas" msgid "Cancel back to the Map Editor main menu." msgstr "" msgid "No maps available!" msgstr "" msgid "[%{pos}]: %{race} hero" msgstr "" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "ŽiÅ«rÄ—ti %{name}" msgid "[%{pos}]: %{race} town" msgstr "" msgid "[%{pos}]: %{race} castle" msgstr "" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "ŽiÅ«rÄ—ti %{name}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "ŽiÅ«rÄ—ti %{name}" msgid "None." msgstr "" msgid "One side defeats another." msgstr "" #, fuzzy msgid "Accumulate gold." msgstr "Sukaupti %{count} aukso" msgid "Run out of time." msgstr "" msgid "alliance|1st" msgstr "" msgid "alliance|2nd" msgstr "" msgid "alliance|3rd" msgstr "" msgid "alliance|4th" msgstr "" msgid "alliance|5th" msgstr "" #, fuzzy msgid "Special Loss Condition" msgstr "PralaimÄ—jimo sÄ…lygos" #, fuzzy msgid "Special Victory Condition" msgstr "PergalÄ—s salygos" #, fuzzy msgid "Allow standard victory conditions" msgstr "PergalÄ—s salygos" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr "Drakonų miestas" # msgid "{%number} alliance: " msgstr "" #, fuzzy msgid "Gold:" msgstr "Auksas" msgid "Select a Town to capture to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Rodyti kitÄ… miestÄ…" msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Rodyti kitÄ… miestÄ…" msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Rodyti kitÄ… miestÄ…" msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Map Difficulty" msgstr "" "ŽemÄ—lapis\n" "SudÄ—tingumas" msgid "Map Description" msgstr "" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" msgid "Change Map Description" msgstr "" #, fuzzy msgid "Click to accept the changes made." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Click to edit custom rumors." msgstr "Rodyti kitÄ… miestÄ…" msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Rodyti kitÄ… miestÄ…" msgid "Events" msgstr "" #, fuzzy msgid "Click to change the language of the map." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Click to change your map name." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Map Name" msgstr "" "Pasaulio\n" "dydis" #, fuzzy msgid "Click to change the description of the current map." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Rodyti kitÄ… miestÄ…" msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Pasaulio dydis" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" msgid "editor|%{count} %{resource}" msgstr "" msgid "Animation" msgstr "" msgid "Passability" msgstr "" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Rodyti kitÄ… miestÄ…" msgid "Add Rumor" msgstr "" msgid "Add an additional rumor." msgstr "" msgid "Edit Rumor" msgstr "" msgid "Edit an existing rumor." msgstr "" msgid "Delete Rumor" msgstr "" msgid "Delete an existing rumor." msgstr "" msgid "" "\n" "\n" "Size: " msgstr "" msgid "" "\n" "\n" "Description: " msgstr "" #, fuzzy msgid "Save Map:" msgstr "Ä®kelti žaidimÄ…" #, fuzzy msgid "Click to save the current map." msgstr "Rodyti kitÄ… miestÄ…" msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Rodyti kitÄ… miestÄ…" msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "" msgid "difficulty|Normal" msgstr "" msgid "difficulty|Hard" msgstr "" msgid "difficulty|Expert" msgstr "" msgid "difficulty|Impossible" msgstr "" msgid "and more..." msgstr "" msgid "Easy" msgstr "" msgid "Normal" msgstr "" msgid "Hard" msgstr "" #, fuzzy msgid "Campaign Difficulty" msgstr "" "ŽemÄ—lapis\n" "SudÄ—tingumas" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" msgid "Start the selected scenario." msgstr "" #, fuzzy msgid "View Intro" msgstr "Rodyti iÅ¡teklius" msgid "View the intro video for the current state of the campaign." msgstr "" msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" msgid "Restart the current scenario." msgstr "" #, fuzzy msgid "Difficulty" msgstr "" "ŽemÄ—lapis\n" "SudÄ—tingumas" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" #, fuzzy msgid "Are you sure you want to restart this scenario?" msgstr "" "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" msgid "Campaign Scenario loading failure" msgstr "" msgid "Please make sure that campaign files are correct and present." msgstr "" msgid "Days spent" msgstr "" msgid "The number of days spent on this campaign." msgstr "" msgid "Project Coordination and Core Development" msgstr "" msgid "Development" msgstr "" msgid "Visit us at " msgstr "" msgid "QA and Support" msgstr "" msgid "Dev and Support" msgstr "" msgid "Special Thanks to" msgstr "" msgid "and many-many other contributors and supporters!" msgstr "" msgid "Support us at" msgstr "" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "" msgid "Original project before 0.7" msgstr "" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "" msgid "Designed and Directed" msgstr "" msgid "Programming and Design" msgstr "" msgid "Executive Producer" msgstr "" msgid "Producer" msgstr "" msgid "Additional Design" msgstr "" msgid "Additional Programming" msgstr "" msgid "Musical Production" msgstr "" msgid "Music and Sound Design" msgstr "" msgid "Vocalists" msgstr "" msgid "Art Director" msgstr "" msgid "Assistant Art Director" msgstr "" #, fuzzy msgid "Artists" msgstr "MagiÅ¡kas artefaktas" msgid "QA Manager" msgstr "" msgid "QA" msgstr "" msgid "Writing" msgstr "" msgid "Manual and Helpfile" msgstr "" msgid "Scenarios" msgstr "" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "" msgid "Design Lead" msgstr "" msgid "Designers" msgstr "" msgid "Programming Lead" msgstr "" msgid "Art Lead" msgstr "" msgid "Playtesters" msgstr "" msgid "Designer" msgstr "" msgid "Producers" msgstr "" msgid "QA Managers" msgstr "" msgid "Sound Design" msgstr "" msgid "Town Themes" msgstr "" msgid "Alto Sax" msgstr "" msgid "Harpsichord and Piano" msgstr "" msgid "Basso Vocal" msgstr "" msgid "Soprano Vocal" msgstr "" msgid "Recorded at %{recordingStudio}" msgstr "" msgid "credits|Manual" msgstr "" msgid "German Consultant" msgstr "" msgid "Map Designers" msgstr "" msgid "Package Design" msgstr "" msgid "High Scores" msgstr "Geriausi rezultatai" msgid "Your Name" msgstr "" msgid "Unknown Hero" msgstr "" msgid "Standard" msgstr "" msgid "View High Scores for Standard Maps." msgstr "" msgid "Campaign" msgstr "" msgid "View High Scores for Campaigns." msgstr "" msgid "hotkey|default okay event" msgstr "" msgid "hotkey|default cancel event" msgstr "" msgid "hotkey|default left" msgstr "" msgid "hotkey|default right" msgstr "" msgid "hotkey|default up" msgstr "" msgid "hotkey|default down" msgstr "" msgid "hotkey|toggle fullscreen" msgstr "" msgid "hotkey|toggle text support mode" msgstr "" msgid "hotkey|toggle developer mode" msgstr "" msgid "hotkey|new game" msgstr "" msgid "hotkey|load game" msgstr "" #, fuzzy msgid "hotkey|high scores" msgstr "Geriausi rezultatai" msgid "hotkey|credits" msgstr "" msgid "hotkey|standard game" msgstr "" msgid "hotkey|campaign game" msgstr "" msgid "hotkey|multi-player game" msgstr "" msgid "hotkey|settings" msgstr "" msgid "hotkey|quit" msgstr "" msgid "hotkey|select map" msgstr "" msgid "hotkey|select small map size" msgstr "" msgid "hotkey|select medium map size" msgstr "" msgid "hotkey|select large map size" msgstr "" msgid "hotkey|select extra large map size" msgstr "" msgid "hotkey|select all map sizes" msgstr "" #, fuzzy msgid "hotkey|hot seat game" msgstr "Rodyti kitÄ… miestÄ…" msgid "hotkey|battle only game" msgstr "" msgid "hotkey|choose the original campaign" msgstr "" msgid "hotkey|choose the expansion campaign" msgstr "" msgid "hotkey|map editor main menu" msgstr "" #, fuzzy msgid "hotkey|new map menu" msgstr "Rodyti kitÄ… miestÄ…" msgid "hotkey|load map menu" msgstr "" msgid "hotkey|new map from scratch" msgstr "" #, fuzzy msgid "hotkey|new random map" msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "hotkey|undo last action" msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "hotkey|redo last action" msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "hotkey|open game main menu" msgstr "Rodyti kitÄ… miestÄ…" msgid "hotkey|toggle passability" msgstr "" msgid "hotkey|roland campaign" msgstr "" msgid "hotkey|archibald campaign" msgstr "" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "Rodyti kitÄ… miestÄ…" msgid "hotkey|voyage home campaign" msgstr "" msgid "hotkey|wizard's isle campaign" msgstr "" msgid "hotkey|descendants campaign" msgstr "" msgid "hotkey|select first campaign bonus" msgstr "" msgid "hotkey|select second campaign bonus" msgstr "" msgid "hotkey|select third campaign bonus" msgstr "" msgid "hotkey|view campaign intro" msgstr "" #, fuzzy msgid "hotkey|select campaign difficulty" msgstr "" "ŽemÄ—lapis\n" "SudÄ—tingumas" msgid "hotkey|restart campaign scenario" msgstr "" msgid "hotkey|world map left" msgstr "" msgid "hotkey|world map right" msgstr "" msgid "hotkey|world map up" msgstr "" msgid "hotkey|world map down" msgstr "" msgid "hotkey|world map up left" msgstr "" msgid "hotkey|world map up right" msgstr "" msgid "hotkey|world map down left" msgstr "" msgid "hotkey|world map down right" msgstr "" msgid "hotkey|save game" msgstr "" #, fuzzy msgid "hotkey|next hero" msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "Rodyti kitÄ… miestÄ…" #, fuzzy msgid "hotkey|start hero movement" msgstr "Rodyti kitÄ… miestÄ…" msgid "hotkey|cast adventure spell" msgstr "" msgid "hotkey|put hero to sleep" msgstr "" #, fuzzy msgid "hotkey|next town" msgstr "Rodyti kitÄ… miestÄ…" msgid "hotkey|end turn" msgstr "" msgid "hotkey|file options" msgstr "" msgid "hotkey|adventure options" msgstr "" msgid "hotkey|puzzle map" msgstr "" msgid "hotkey|scenario information" msgstr "" msgid "hotkey|dig for artifact" msgstr "" msgid "hotkey|view world" msgstr "" msgid "hotkey|kingdom summary" msgstr "" msgid "hotkey|default action" msgstr "" msgid "hotkey|open focus" msgstr "" msgid "hotkey|system options" msgstr "" msgid "hotkey|scroll left" msgstr "" msgid "hotkey|scroll right" msgstr "" msgid "hotkey|scroll up" msgstr "" msgid "hotkey|scroll down" msgstr "" msgid "hotkey|toggle control panel" msgstr "" msgid "hotkey|toggle radar" msgstr "" msgid "hotkey|toggle buttons" msgstr "" msgid "hotkey|toggle status" msgstr "" msgid "hotkey|toggle icons" msgstr "" msgid "hotkey|transfer control to ai" msgstr "" msgid "hotkey|retreat from battle" msgstr "" msgid "hotkey|surrender during battle" msgstr "" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Rodyti kitÄ… miestÄ…" msgid "hotkey|quick combat" msgstr "" #, fuzzy msgid "hotkey|battle options" msgstr "IÅ¡eiti iÅ¡ pilies" msgid "hotkey|skip turn in battle" msgstr "" msgid "hotkey|cast battle spell" msgstr "" msgid "hotkey|dwelling level 1" msgstr "" msgid "hotkey|dwelling level 2" msgstr "" msgid "hotkey|dwelling level 3" msgstr "" msgid "hotkey|dwelling level 4" msgstr "" msgid "hotkey|dwelling level 5" msgstr "" msgid "hotkey|dwelling level 6" msgstr "" msgid "hotkey|well" msgstr "" #, fuzzy msgid "hotkey|marketplace" msgstr "Turgus" msgid "hotkey|mage guild" msgstr "" #, fuzzy msgid "hotkey|shipyard" msgstr "Laivų statykla" #, fuzzy msgid "hotkey|thieves guild" msgstr "Vagių gildija" msgid "hotkey|tavern" msgstr "" msgid "hotkey|construction screen" msgstr "" msgid "hotkey|buy all monsters in well" msgstr "" msgid "hotkey|split stack by half" msgstr "" msgid "hotkey|split stack by one" msgstr "" msgid "hotkey|join stacks" msgstr "" msgid "hotkey|upgrade troop" msgstr "" msgid "hotkey|dismiss hero or troop" msgstr "" #, fuzzy msgid "hotkey|exchange all troops" msgstr "Rodyti kitÄ… miestÄ…" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" msgid "Default Actions" msgstr "" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "" msgid "Battle Screen" msgstr "" msgid "Town Screen" msgstr "" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "" msgid "Unsupported save format: " msgstr "" msgid "Current game version: " msgstr "" msgid "Last supported version: " msgstr "" msgid "This file contains a save with an invalid game type." msgstr "" msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" msgid "This saved game is localized to '" msgstr "" msgid "' language, but the current language of the game is '" msgstr "" msgid "No save files to load." msgstr "" msgid "Hot Seat" msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "A single player game playing out a single map." msgstr "" msgid "Standard Game" msgstr "" msgid "A single player game playing through a series of maps." msgstr "" msgid "Campaign Game" msgstr "" msgid "Multi-Player Game" msgstr "" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" msgid "fheroes2 Resurrection Team presents" msgstr "" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" msgid "Greetings!" msgstr "" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" msgid "Credits" msgstr "" msgid "View the credits screen." msgstr "" msgid "View the high scores screen." msgstr "" msgid "Create new or modify existing maps." msgstr "" msgid "Change language, resolution and settings of the game." msgstr "" msgid "Game Settings" msgstr "" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" msgid "Original Campaign" msgstr "" msgid "Expansion Campaign" msgstr "" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" msgid "Loading video. Please wait..." msgstr "" msgid "Host" msgstr "" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" msgid "Guest" msgstr "" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" msgid "Battle Only" msgstr "" msgid "Setup and play a battle without loading any map." msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "2 Players" msgstr "" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" msgid "3 Players" msgstr "" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" msgid "4 Players" msgstr "" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" msgid "5 Players" msgstr "" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" msgid "6 Players" msgstr "" msgid "Play with 6 human players." msgstr "" msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" #, fuzzy msgid "Ultimate Artifact" msgstr "Rasti magiÅ¡kÄ… artefaktÄ… '%{name}'" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" msgid "Victory!" msgstr "" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" msgid "You have been eliminated from the game!!!" msgstr "" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" msgid "Defeat!" msgstr "" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "NugalÄ—ti visus prieÅ¡o herojus bei užimti visas prieÅ¡o pilis bei miestelius." msgid "Your side defeats the opposing side." msgstr "" msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" #, fuzzy msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Prarasti miestÄ… '%{name}'." msgstr[1] "Prarasti miestÄ… '%{name}'." msgstr[2] "Prarasti miestÄ… '%{name}'." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" msgstr[1] "" msgstr[2] "" #, fuzzy msgid "Capture the castle '%{name}'." msgstr "Užimti pilį '%{name}'" #, fuzzy msgid "Capture the town '%{name}'." msgstr "Užimti miestÄ… '%{name}'" #, fuzzy msgid "Defeat the hero '%{name}'." msgstr "Prarasti miestÄ… '%{name}'." #, fuzzy msgid "Find the ultimate artifact." msgstr "Rasti magiÅ¡kÄ… artefaktÄ… '%{name}'" #, fuzzy msgid "Find the '%{name}' artifact." msgstr "Rasti magiÅ¡kÄ… artefaktÄ… '%{name}'" #, fuzzy msgid "Accumulate %{count} gold." msgstr "Sukaupti %{count} aukso" msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" msgid "Lose the castle '%{name}'." msgstr "Prarasti pilį '%{name}'." msgid "Lose the town '%{name}'." msgstr "Prarasti miestÄ… '%{name}'." msgid "Lose the hero: %{name}." msgstr "" msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" msgid "%{color} player has been vanquished!" msgstr "" msgid "Major Event!" msgstr "" msgid "Scenario:" msgstr "" msgid "Game Difficulty:" msgstr "" msgid "Opponents:" msgstr "" msgid "Class:" msgstr "" msgid "Rating %{rating}%" msgstr "" msgid "Click here to select which scenario to play." msgstr "" msgid "Scenario" msgstr "" msgid "Game Difficulty" msgstr "" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" msgid "Difficulty Rating" msgstr "" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" msgid "Click to accept these settings and start a new game." msgstr "" msgid "Click to return to the main menu." msgstr "" msgid "Astrologers proclaim the Month of the %{name}." msgstr "" msgid "Astrologers proclaim the Week of the %{name}." msgstr "" msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "%{monster} growth +%{count}." msgstr "" msgid " All populations are halved." msgstr "" msgid " All dwellings increase population." msgstr "" msgid "New Month!" msgstr "" msgid "New Week!" msgstr "" msgid "Beware!" msgstr "" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} žaidÄ—jau, Å¡iandien bus paskutinÄ— tavo diena Å¡iame žaidime, jei " "neužimsi kokio nors miesto." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} žaidÄ—jau, tau liko tik %{day} dienos Å¡iame žaidime - jei neužimsi " "kokio nors miesto, bÅ«si paÅ¡alintas." msgid "%{color} player's turn." msgstr "" msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" msgid "Lord Kilburn" msgstr "" msgid "Tsabu" msgstr "" msgid "Sir Galant" msgstr "" msgid "Thundax" msgstr "" msgid "Lord Haart" msgstr "" msgid "Ariel" msgstr "" msgid "Rebecca" msgstr "" msgid "Sandro" msgstr "" msgid "Crodo" msgstr "" msgid "Barock" msgstr "" msgid "Antoine" msgstr "" msgid "Astra" msgstr "" msgid "Agar" msgstr "" msgid "Vatawna" msgstr "" msgid "Vesper" msgstr "" msgid "Ambrose" msgstr "" msgid "Troyan" msgstr "" msgid "Jojosh" msgstr "" msgid "Wrathmont" msgstr "" msgid "Maximus" msgstr "" msgid "Next Hero" msgstr "" msgid "Select the next Hero." msgstr "" #, fuzzy msgid "Hero Movement" msgstr "Greitis" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "" msgid "View a summary of your Kingdom." msgstr "" msgid "Cast an adventure spell." msgstr "" msgid "End Turn" msgstr "" msgid "End your turn and let the computer take its turn." msgstr "" msgid "Adventure Options" msgstr "" msgid "Bring up the adventure options menu." msgstr "" msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" msgid "Are you sure you want to quit?" msgstr "" #, fuzzy msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Ar tikrai norite įkelti anksÄiau įraÅ¡ytÄ… žaidimÄ…? (Dabartinis žaidimas bus " "prarastas, jei neįrašėte)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "" "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" msgid "Game saved successfully." msgstr "Žaidimas sÄ—kmingai įraÅ¡ytas." msgid "There was an issue during saving." msgstr "" #, fuzzy msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Ar tikrai norite įkelti anksÄiau įraÅ¡ytÄ… žaidimÄ…? (Dabartinis žaidimas bus " "prarastas, jei neįrašėte)" msgid "Try looking on land!!!" msgstr "" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" "MagiÅ¡ko artefakto kasinÄ—jimas užima visÄ… dienÄ… - bandykite dar kartÄ… rytoj." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" msgid "Congratulations!" msgstr "" msgid "Nothing here. Where could it be?" msgstr "" msgid "Try searching on clear ground." msgstr "" msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" msgid "Month: %{month} Week: %{week}" msgstr "MÄ—nuo: %{month} SavaitÄ—: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "JÅ«s radote Å¡iek\n" "tiek %{resource}." msgid "Status Window" msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" msgid "Handicap" msgstr "" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" msgid "%{color} player" msgstr "" msgid "No Handicap" msgstr "" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" msgid "Mild Handicap" msgstr "" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" msgid "Severe Handicap" msgstr "" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Puolimo įgÅ«dis" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "ŽiÅ«rÄ—ti %{skill} informacijÄ…" #, fuzzy msgid "" "Default\n" "skill" msgstr "Gynybos įgÅ«dis" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "" msgid "Kingdom Income per day." msgstr "" msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" #, fuzzy msgid "Vietnamese" msgstr "ŽiÅ«rÄ—ti %{name}" msgid "Slow" msgstr "" msgid "Fast" msgstr "" msgid "Very Fast" msgstr "" msgid "Evil" msgstr "" msgid "Good" msgstr "" msgid ", FPS: " msgstr "" msgid "shipAndGraveyard|%{object} robber" msgstr "" msgid "pyramid|%{object} raided" msgstr "" msgid "Ector" msgstr "" msgid "Gwenneth" msgstr "" msgid "Sir Gallant" msgstr "" msgid "Tyro" msgstr "" msgid "Dimitry" msgstr "" msgid "Ruby" msgstr "" msgid "Crag Hack" msgstr "" msgid "Fineous" msgstr "" msgid "Jezebel" msgstr "" msgid "Atlas" msgstr "" msgid "Ergon" msgstr "" msgid "Jaclyn" msgstr "" msgid "Gem" msgstr "Brangakmenis" msgid "Natasha" msgstr "" msgid "Carlawn" msgstr "" msgid "Luna" msgstr "" msgid "Arie" msgstr "" msgid "Barok" msgstr "" msgid "Kastore" msgstr "" msgid "Falagar" msgstr "" msgid "Dawn" msgstr "" msgid "Flint" msgstr "" msgid "Halon" msgstr "" msgid "Myra" msgstr "" msgid "Myrini" msgstr "" msgid "Wilfrey" msgstr "" msgid "Mandigal" msgstr "" msgid "Sarakin" msgstr "" msgid "Charity" msgstr "" msgid "Darlana" msgstr "" msgid "Ranloo" msgstr "" msgid "Rialdo" msgstr "" msgid "Zam" msgstr "" msgid "Zom" msgstr "" msgid "Celia" msgstr "" msgid "Roxana" msgstr "" msgid "Lord Corlagon" msgstr "" msgid "Lord Halton" msgstr "" msgid "Sister Eliza" msgstr "" msgid "Brother Brax" msgstr "" msgid "Dainwin" msgstr "" msgid "Joseph" msgstr "" msgid "Mog" msgstr "" msgid "Solmyr" msgstr "" msgid "Ceallach" msgstr "" msgid "Drakonia" msgstr "" msgid "Elderian" msgstr "" msgid "Gallavant" msgstr "" msgid "Jarkonas" msgstr "" msgid "Martine" msgstr "" msgid " gives you maximum morale" msgstr "" msgid " gives you maximum luck" msgstr "" msgid "You cannot have multiple spell books." msgstr "" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Burtus galÄ—site naudoti tik nusipirkÄ™ burtų knygÄ… už %{gold} aukso monetų." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" msgid "Do you wish to buy one?" msgstr "Ar norite nusipirkti vienÄ…?" msgid "%{count} / day" msgstr "" msgid "one" msgstr "" msgid "two" msgstr "" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" msgid "You come upon the remains of an unfortunate adventurer." msgstr "" msgid "Treasure" msgstr "" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" msgid "Searching through the tattered clothing, you find nothing." msgstr "" msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" msgid "Searching inside, you find the %{artifact}." msgstr "" msgid "Inside, you find some of the wagon's cargo still intact." msgstr "" msgid "You search through the flotsam, and find some wood and some gold." msgstr "" msgid "You search through the flotsam, and find some wood." msgstr "" msgid "You search through the flotsam, but find nothing." msgstr "" msgid "Shrine of the 1st Circle" msgstr "" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 2nd Circle" msgstr "" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 3rd Circle" msgstr "" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Deja, jÅ«s neturite pakankamai iÅ¡minties kad suprasti šį burtÄ…, todÄ—l " "negalite jo iÅ¡mokti." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" msgid "You drink from the enchanted fountain, but nothing happens." msgstr "" msgid "You enter the faerie ring, but nothing happens." msgstr "" msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Deja, jÅ«s neturite pakankamai iÅ¡minties kad suprasti šį burtÄ…, todÄ—l " "negalite jo iÅ¡mokti." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" msgid "A second drink at the well in one day will not help you." msgstr "" msgid "A drink from the well has restored your spell points to maximum." msgstr "" msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" msgid "Do you wish to buy this artifact?" msgstr "Ar jÅ«s norite pirkti šį magiÅ¡kÄ… artefaktÄ…?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" msgid "You've found the artifact: " msgstr "" msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" msgid "Victorious, you take your prize, the %{art}." msgstr "" msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "JÅ«s užvaldÄ—te lentpjÅ«vÄ™. Å i lentpjÅ«vÄ— gamins jums %{count} medienos vnt. per " "dienÄ…." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "JÅ«s užvaldÄ—te geležies rÅ«dos kasyklÄ…. Å i kasykla iÅ¡kas jums %{count} rÅ«dos " "vnt. per dienÄ…." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "JÅ«s užvaldÄ—te sieros kasyklÄ…. Å i kasykla iÅ¡kas jums %{count} sieros vnt. per " "dienÄ…." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "JÅ«s užvaldÄ—te kristalų kasyklÄ…. Å i kasykla iÅ¡kas jums %{count} kristalÄ…(us) " "per dienÄ…." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "JÅ«s užvaldÄ—te brangakmenių kasyklÄ…. Å i kasykla iÅ¡kas jums %{count} " "brangakmenį per dienÄ…." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "JÅ«s užvaldÄ—te aukso kasyklÄ…. Å i kasykla pagamins jums %{count} aukso monetų " "per dienÄ…." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" msgid "You gain control of a %{name}." msgstr "" msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "" msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" msgid "No Fire Elementals approach you from the lava pool." msgstr "" msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" msgid "A face forms in the water for a moment, and then is gone." msgstr "" msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" msgid "This burial site is deathly still." msgstr "" msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" msgid "From the observation tower, you are able to see distant lands." msgstr "" msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" msgid " and " msgstr "" msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "" msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" msgid "You have already been to this obelisk." msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "" msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" msgid "(Just bury it around my roots.)" msgstr "" msgid "Tears brim in the eyes of the tree." msgstr "" msgid "\"I need %{count} %{res}.\"" msgstr "" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" msgid "The Arena guards turn you away." msgstr "" msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" msgid "This eye seems to be intently studying its surroundings." msgstr "" msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" msgid "No spell book is present." msgstr "" msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" msgid "The spell was not found." msgstr "" msgid "Only heroes can cast this spell." msgstr "" msgid "This hero is not able to cast adventure spells." msgstr "" msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" msgid "This spell cannot be cast on a boat." msgstr "" msgid "This spell can only be cast near an ocean." msgstr "" msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" msgid "There are no boats available for this spell." msgstr "" msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" msgid "This hero is already in a town, so this spell will have no effect." msgstr "" msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" msgid "This spell is already in effect." msgstr "" msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" msgid "%{name} the %{race} (Level %{level})" msgstr "" #, fuzzy msgid "Random hero (Level %{level})" msgstr "AtsitiktinÄ— pilis" msgid "Random %{race} hero (Level %{level})" msgstr "" #, fuzzy msgid "Hero race:" msgstr "Greitis" msgid "Are you sure you want to dismiss this Hero?" msgstr "" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Burtų galia" msgid "View Spell Points Info" msgstr "" msgid "Set patrol radius in tiles" msgstr "" msgid "Enter hero's name" msgstr "" #, fuzzy msgid "Click to change race." msgstr "Rodyti kitÄ… miestÄ…" msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" msgid "Exit Hero Screen" msgstr "" msgid "You cannot dismiss a hero in a castle" msgstr "" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "" msgid "Dismiss %{name} the %{race}" msgstr "" #, fuzzy msgid "Show previous hero" msgstr "Rodyti ankstesnį miestÄ…" #, fuzzy msgid "Show next hero" msgstr "Rodyti kitÄ… miestÄ…" msgid "Set army combat formation to 'Spread'" msgstr "" msgid "Set army combat formation to 'Grouped'" msgstr "" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Rodyti kitÄ… miestÄ…" msgid "Blood Morale" msgstr "" msgid "%{morale} Morale" msgstr "" msgid "%{luck} Luck" msgstr "" msgid "Current Luck Modifiers:" msgstr "" msgid "Current Morale Modifiers:" msgstr "" msgid "Entire army is undead, so morale does not apply." msgstr "" msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" msgid "%{name1} meets %{name2}" msgstr "" msgid "Enemy heroes are now fully identifiable." msgstr "" msgid "Identify Hero" msgstr "" msgid "Select town to port to." msgstr "" msgid "Town Portal" msgstr "" msgid "The creatures are willing to join us!" msgstr "" msgid "All the creatures will join us..." msgstr "" msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "\n" " for a fee of %{gold} gold." msgstr "" msgid "These weak creatures will surely flee before us." msgstr "" msgid "I fear these creatures are in the mood for a fight." msgstr "" msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" #, fuzzy msgid "The hero's spell power determines the duration or power of a spell." msgstr "" "Nuo herojaus burtų galios priklauso burtų galiojimo laikas bei galingumas." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" msgid "Current Modifiers:" msgstr "" msgid "skill|Basic" msgstr "" msgid "skill|Advanced" msgstr "" msgid "skill|Expert" msgstr "" msgid "Pathfinding" msgstr "" msgid "Archery" msgstr "" msgid "Logistics" msgstr "" msgid "Scouting" msgstr "" msgid "Diplomacy" msgstr "" msgid "Navigation" msgstr "" msgid "Leadership" msgstr "" msgid "Wisdom" msgstr "IÅ¡mintis" msgid "Mysticism" msgstr "" msgid "Ballistics" msgstr "" msgid "Eagle Eye" msgstr "" msgid "Necromancy" msgstr "" msgid "Estates" msgstr "" msgid "Advanced Archery" msgstr "Pažangus Å¡audymas" msgid "Advanced Pathfinding" msgstr "" msgid "Basic Archery" msgstr "Pradinis Å¡audymas" msgid "Basic Pathfinding" msgstr "" msgid "Expert Pathfinding" msgstr "" msgid "Advanced Logistics" msgstr "" msgid "Basic Logistics" msgstr "" msgid "Basic Scouting" msgstr "" msgid "Expert Archery" msgstr "Eksperto Å¡audymas" msgid "Expert Logistics" msgstr "" msgid "Advanced Diplomacy" msgstr "Pažangi diplomatija" msgid "Advanced Scouting" msgstr "" msgid "Basic Diplomacy" msgstr "PradinÄ— diplomatija" msgid "Expert Diplomacy" msgstr "Eksperto diplomatija" msgid "Expert Scouting" msgstr "" msgid "Advanced Leadership" msgstr "Pažangi lyderystÄ—" msgid "Advanced Navigation" msgstr "Pažangi navigacija" msgid "Basic Leadership" msgstr "PradinÄ— lyderystÄ—" msgid "Basic Navigation" msgstr "PradinÄ— navigacija" msgid "Expert Navigation" msgstr "Eksperto navigacija" msgid "Advanced Wisdom" msgstr "Pažangi iÅ¡mintis" msgid "Basic Mysticism" msgstr "" msgid "Basic Wisdom" msgstr "PradinÄ— iÅ¡mintis" msgid "Expert Leadership" msgstr "Eksperto lyderystÄ—" msgid "Expert Wisdom" msgstr "Eksperto iÅ¡mintis" msgid "Advanced Luck" msgstr "" msgid "Advanced Mysticism" msgstr "" msgid "Basic Luck" msgstr "" msgid "Expert Luck" msgstr "" msgid "Expert Mysticism" msgstr "" msgid "Advanced Ballistics" msgstr "" msgid "Advanced Eagle Eye" msgstr "" msgid "Basic Ballistics" msgstr "" msgid "Basic Eagle Eye" msgstr "" msgid "Expert Ballistics" msgstr "" msgid "Advanced Necromancy" msgstr "" msgid "Basic Estates" msgstr "" msgid "Basic Necromancy" msgstr "" msgid "Expert Eagle Eye" msgstr "" msgid "Expert Necromancy" msgstr "" msgid "Advanced Estates" msgstr "" msgid "Expert Estates" msgstr "" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "" #, fuzzy msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." #, fuzzy msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." #, fuzzy msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgstr[1] "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgstr[2] "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" msgid "All of the creatures may offer to join the hero." msgstr "" msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" #, fuzzy msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "%{skill} allows the hero to learn third level spells." msgstr "" msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" msgid "%{skill} allows the hero to learn fifth level spells." msgstr "" #, fuzzy msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{name} teikia %{count} geležies rÅ«dos vnt. per dienÄ…." msgstr[1] "%{name} teikia %{count} geležies rÅ«dos vnt. per dienÄ…." msgstr[2] "%{name} teikia %{count} geležies rÅ«dos vnt. per dienÄ…." #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "%{name} kainuos jums %{count} aukso monetų per dienÄ…." msgid "Blue" msgstr "" msgid "Green" msgstr "" msgid "Red" msgstr "" msgid "Yellow" msgstr "" msgid "Orange" msgstr "" msgid "Purple" msgstr "" msgid "barrier|Aqua" msgstr "" msgid "barrier|Blue" msgstr "" msgid "barrier|Brown" msgstr "" msgid "barrier|Gold" msgstr "" msgid "barrier|Green" msgstr "" msgid "barrier|Orange" msgstr "" msgid "barrier|Purple" msgstr "" msgid "barrier|Red" msgstr "" msgid "tent|Aqua" msgstr "" msgid "tent|Blue" msgstr "" msgid "tent|Brown" msgstr "" #, fuzzy msgid "tent|Gold" msgstr "Auksas" msgid "tent|Green" msgstr "" msgid "tent|Orange" msgstr "" msgid "tent|Purple" msgstr "" msgid "tent|Red" msgstr "" msgid "Experience" msgstr "" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" msgid "Hero/Stats" msgstr "" msgid "Skills" msgstr "Ä®gÅ«džiai" msgid "Town/Castle" msgstr "Miestelis/Pilis" msgid "Garrison" msgstr "" msgid "Gold Per Day:" msgstr "Aukso per dienÄ…:" #, fuzzy msgid "View Heroes." msgstr "Rodyti iÅ¡teklius" #, fuzzy msgid "Towns/Castles" msgstr "Miestelis/Pilis" #, fuzzy msgid "View Towns and Castles." msgstr "Rodyti miestus" msgid "luck|Cursed" msgstr "" msgid "luck|Awful" msgstr "" msgid "luck|Bad" msgstr "" msgid "luck|Normal" msgstr "" msgid "luck|Good" msgstr "" msgid "luck|Great" msgstr "" msgid "luck|Irish" msgstr "" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" msgid "morale|Treason" msgstr "" msgid "morale|Awful" msgstr "" msgid "morale|Poor" msgstr "" msgid "morale|Normal" msgstr "" msgid "morale|Good" msgstr "" msgid "morale|Great" msgstr "" msgid "morale|Blood!" msgstr "" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" msgid "Knight" msgstr "" msgid "Barbarian" msgstr "" msgid "Sorceress" msgstr "" msgid "Warlock" msgstr "" msgid "Wizard" msgstr "" msgid "Necromancer" msgstr "" msgid "Multi" msgstr "" msgid "doubleLined|Knight" msgstr "" msgid "doubleLined|Barbarian" msgstr "" msgid "doubleLined|Sorceress" msgstr "" msgid "doubleLined|Warlock" msgstr "" msgid "doubleLined|Wizard" msgstr "" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" msgid "doubleLinedRace|Multi" msgstr "" msgid "doubleLinedRace|Random" msgstr "" msgid "speed|Standing" msgstr "" msgid "speed|Crawling" msgstr "" msgid "speed|Very Slow" msgstr "" msgid "speed|Slow" msgstr "" msgid "speed|Average" msgstr "" msgid "speed|Fast" msgstr "" msgid "speed|Very Fast" msgstr "" msgid "speed|Ultra Fast" msgstr "" msgid "speed|Blazing" msgstr "" msgid "speed|Instant" msgstr "" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "" msgid "week|Rabbit" msgstr "" msgid "week|Gopher" msgstr "" msgid "week|Badger" msgstr "" #, fuzzy msgid "week|Rat" msgstr "savait." msgid "week|Eagle" msgstr "" msgid "week|Weasel" msgstr "" msgid "week|Raven" msgstr "" msgid "week|Mongoose" msgstr "" #, fuzzy msgid "week|Dog" msgstr "savait." msgid "week|Aardvark" msgstr "" msgid "week|Lizard" msgstr "" msgid "week|Tortoise" msgstr "" msgid "week|Hedgehog" msgstr "" msgid "week|Condor" msgstr "" msgid "week|Ant" msgstr "" msgid "week|Grasshopper" msgstr "" msgid "week|Dragonfly" msgstr "" msgid "week|Spider" msgstr "" msgid "week|Butterfly" msgstr "" msgid "week|Bumblebee" msgstr "" msgid "week|Locust" msgstr "" msgid "week|Earthworm" msgstr "" msgid "week|Hornet" msgstr "" msgid "week|Beetle" msgstr "" msgid "week|PLAGUE" msgstr "" msgid "week|Unnamed" msgstr "" msgid "Desert" msgstr "" msgid "Snow" msgstr "" msgid "Wasteland" msgstr "" msgid "Beach" msgstr "" msgid "Lava" msgstr "" msgid "Dirt" msgstr "" msgid "Grass" msgstr "" msgid "Ocean" msgstr "" msgid "maps|Small" msgstr "" msgid "maps|Medium" msgstr "" msgid "maps|Large" msgstr "" msgid "maps|Extra Large" msgstr "" msgid "maps|Custom Size" msgstr "" msgid "Ore Mine" msgstr "RÅ«dos kasykla" msgid "Sulfur Mine" msgstr "Sieros kasykla" msgid "Crystal Mine" msgstr "Kristalų kasykla" msgid "Gems Mine" msgstr "Brangakmenių telkinys" msgid "Gold Mine" msgstr "Aukso kasykla" msgid "Mine" msgstr "" msgid "Burma shave." msgstr "" msgid "Next sign 50 miles." msgstr "" msgid "See Rock City." msgstr "" msgid "This space for rent." msgstr "" msgid "No object" msgstr "" msgid "Alchemist Lab" msgstr "" msgid "Sign" msgstr "" msgid "Buoy" msgstr "" msgid "Skeleton" msgstr "" msgid "Daemon Cave" msgstr "" msgid "Treasure Chest" msgstr "" msgid "Faerie Ring" msgstr "" msgid "Campfire" msgstr "" msgid "Fountain" msgstr "" msgid "Gazebo" msgstr "" msgid "Genie Lamp" msgstr "" msgid "Archer's House" msgstr "" msgid "Goblin Hut" msgstr "" msgid "Dwarf Cottage" msgstr "" msgid "Peasant Hut" msgstr "" msgid "Stables" msgstr "" msgid "Alchemist's Tower" msgstr "" msgid "Event" msgstr "" msgid "Dragon City" msgstr "" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Monster" msgstr "" msgid "Obelisk" msgstr "" msgid "Oasis" msgstr "" msgid "Resource" msgstr "IÅ¡tekliai" msgid "Sawmill" msgstr "" msgid "Oracle" msgstr "" msgid "Shrine of the First Circle" msgstr "" msgid "Shipwreck" msgstr "" msgid "Sea Chest" msgstr "" msgid "Desert Tent" msgstr "" msgid "Stone Liths" msgstr "" msgid "Wagon Camp" msgstr "" msgid "Hut of the Magi" msgstr "" msgid "Whirlpool" msgstr "" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Mermaid" msgstr "" msgid "Boat" msgstr "" #, fuzzy msgid "Random Ultimate Artifact" msgstr "Rasti magiÅ¡kÄ… artefaktÄ… '%{name}'" #, fuzzy msgid "Random Artifact" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "Random Resource" msgstr "IÅ¡tekliai" #, fuzzy msgid "Random Monster" msgstr "AtsitiktinÄ— pilis" msgid "Random Town" msgstr "Atsitiktinis miestas" msgid "Random Castle" msgstr "AtsitiktinÄ— pilis" msgid "Eye of the Magi" msgstr "" #, fuzzy msgid "Random Monster - weak" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monster - medium" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monster - strong" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monster - very strong" msgstr "AtsitiktinÄ— pilis" msgid "Hero" msgstr "" msgid "Nothing Special" msgstr "" msgid "Mossy Rock" msgstr "" msgid "Watch Tower" msgstr "" msgid "Tree House" msgstr "" msgid "Tree City" msgstr "" msgid "Ruins" msgstr "" msgid "Fort" msgstr "" msgid "Abandoned Mine" msgstr "" msgid "Sirens" msgstr "" msgid "Standing Stones" msgstr "" msgid "Idol" msgstr "" msgid "Tree of Knowledge" msgstr "" msgid "Witch Doctor's Hut" msgstr "" msgid "Temple" msgstr "" msgid "Hill Fort" msgstr "" msgid "Halfling Hole" msgstr "" msgid "Mercenary Camp" msgstr "" msgid "Shrine of the Second Circle" msgstr "" msgid "Shrine of the Third Circle" msgstr "" msgid "City of the Dead" msgstr "" msgid "Sphinx" msgstr "" msgid "Wagon" msgstr "" msgid "Tar Pit" msgstr "" msgid "Artesian Spring" msgstr "" msgid "Troll Bridge" msgstr "" msgid "Watering Hole" msgstr "" msgid "Witch's Hut" msgstr "" msgid "Xanadu" msgstr "" msgid "Lean-To" msgstr "" msgid "Magellan's Maps" msgstr "" msgid "Flotsam" msgstr "" msgid "Derelict Ship" msgstr "" msgid "Shipwreck Survivor" msgstr "" msgid "Bottle" msgstr "" msgid "Magic Well" msgstr "" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Observation Tower" msgstr "" msgid "Freeman's Foundry" msgstr "" msgid "Reefs" msgstr "" msgid "Volcano" msgstr "" msgid "Flowers" msgstr "" msgid "Rock" msgstr "" msgid "Water Lake" msgstr "" msgid "Mandrake" msgstr "" msgid "Dead Tree" msgstr "" msgid "Stump" msgstr "" msgid "Crater" msgstr "" msgid "Cactus" msgstr "" msgid "Mound" msgstr "" msgid "Dune" msgstr "" msgid "Lava Pool" msgstr "" msgid "Shrub" msgstr "" msgid "Barrow Mounds" msgstr "" msgid "Random Artifact - Treasure" msgstr "" msgid "Random Artifact - Minor" msgstr "" msgid "Random Artifact - Major" msgstr "" msgid "Barrier" msgstr "" msgid "Traveller's Tent" msgstr "" msgid "Jail" msgstr "" msgid "Fire Summoning Altar" msgstr "" msgid "Air Summoning Altar" msgstr "" msgid "Earth Summoning Altar" msgstr "" msgid "Water Summoning Altar" msgstr "" #, fuzzy msgid "Swampy Lake" msgstr "PelkÄ—" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "" msgid "Unknown Monster" msgstr "" msgid "Peasant" msgstr "" msgid "Peasants" msgstr "" #, fuzzy msgid "Archer" msgstr "Pradinis Å¡audymas" #, fuzzy msgid "Archers" msgstr "Pradinis Å¡audymas" msgid "Ranger" msgstr "" msgid "Rangers" msgstr "" msgid "Pikeman" msgstr "" msgid "Pikemen" msgstr "" msgid "Veteran Pikeman" msgstr "" msgid "Veteran Pikemen" msgstr "" msgid "Swordsman" msgstr "" msgid "Swordsmen" msgstr "" msgid "Master Swordsman" msgstr "" msgid "Master Swordsmen" msgstr "" msgid "Cavalries" msgstr "" msgid "Cavalry" msgstr "" msgid "Champion" msgstr "" msgid "Champions" msgstr "" msgid "Paladin" msgstr "" msgid "Paladins" msgstr "" msgid "Crusader" msgstr "" msgid "Crusaders" msgstr "" msgid "Goblin" msgstr "" msgid "Goblins" msgstr "" #, fuzzy msgid "Orc" msgstr "RÅ«da" msgid "Orcs" msgstr "" msgid "Orc Chief" msgstr "" msgid "Orc Chiefs" msgstr "" msgid "Wolf" msgstr "" msgid "Wolves" msgstr "" msgid "Ogre" msgstr "" msgid "Ogres" msgstr "" msgid "Ogre Lord" msgstr "" msgid "Ogre Lords" msgstr "" msgid "Troll" msgstr "" msgid "Trolls" msgstr "" msgid "War Troll" msgstr "" msgid "War Trolls" msgstr "" msgid "Cyclopes" msgstr "" msgid "Cyclops" msgstr "" msgid "Sprite" msgstr "" msgid "Sprites" msgstr "" msgid "Dwarf" msgstr "" msgid "Dwarves" msgstr "" msgid "Battle Dwarf" msgstr "" msgid "Battle Dwarves" msgstr "" msgid "Elf" msgstr "" msgid "Elves" msgstr "" msgid "Grand Elf" msgstr "" msgid "Grand Elves" msgstr "" msgid "Druid" msgstr "" msgid "Druids" msgstr "" msgid "Greater Druid" msgstr "" msgid "Greater Druids" msgstr "" msgid "Unicorn" msgstr "" msgid "Unicorns" msgstr "" msgid "Phoenix" msgstr "" msgid "Phoenixes" msgstr "" msgid "Centaur" msgstr "" msgid "Centaurs" msgstr "" msgid "Gargoyle" msgstr "" msgid "Gargoyles" msgstr "" msgid "Griffin" msgstr "" msgid "Griffins" msgstr "" msgid "Minotaur" msgstr "" msgid "Minotaurs" msgstr "" msgid "Minotaur King" msgstr "" msgid "Minotaur Kings" msgstr "" msgid "Hydra" msgstr "" msgid "Hydras" msgstr "" #, fuzzy msgid "Green Dragon" msgstr "Žalias bokÅ¡tas" msgid "Green Dragons" msgstr "" msgid "Red Dragon" msgstr "" msgid "Red Dragons" msgstr "" #, fuzzy msgid "Black Dragon" msgstr "Juodas bokÅ¡tas" msgid "Black Dragons" msgstr "" msgid "Halfling" msgstr "" msgid "Halflings" msgstr "" msgid "Boar" msgstr "" msgid "Boars" msgstr "" msgid "Iron Golem" msgstr "" msgid "Iron Golems" msgstr "" msgid "Steel Golem" msgstr "" msgid "Steel Golems" msgstr "" msgid "Roc" msgstr "" msgid "Rocs" msgstr "" msgid "Mage" msgstr "" msgid "Magi" msgstr "" msgid "Archmage" msgstr "" msgid "Archmagi" msgstr "" msgid "Giant" msgstr "" msgid "Giants" msgstr "" msgid "Titan" msgstr "" msgid "Titans" msgstr "" msgid "Skeletons" msgstr "" msgid "Zombie" msgstr "" msgid "Zombies" msgstr "" msgid "Mutant Zombie" msgstr "" msgid "Mutant Zombies" msgstr "" msgid "Mummies" msgstr "" msgid "Mummy" msgstr "" msgid "Royal Mummies" msgstr "" msgid "Royal Mummy" msgstr "" msgid "Vampire" msgstr "" msgid "Vampires" msgstr "" msgid "Vampire Lord" msgstr "" msgid "Vampire Lords" msgstr "" msgid "Lich" msgstr "" msgid "Liches" msgstr "" msgid "Power Lich" msgstr "" msgid "Power Liches" msgstr "" msgid "Bone Dragon" msgstr "" msgid "Bone Dragons" msgstr "" msgid "Rogue" msgstr "" msgid "Rogues" msgstr "" msgid "Nomad" msgstr "" msgid "Nomads" msgstr "" msgid "Ghost" msgstr "" msgid "Ghosts" msgstr "" msgid "Genie" msgstr "" msgid "Genies" msgstr "" msgid "Medusa" msgstr "" msgid "Medusas" msgstr "" msgid "Earth Elemental" msgstr "" msgid "Earth Elementals" msgstr "" msgid "Air Elemental" msgstr "" msgid "Air Elementals" msgstr "" msgid "Fire Elemental" msgstr "" msgid "Fire Elementals" msgstr "" msgid "Water Elemental" msgstr "" msgid "Water Elementals" msgstr "" #, fuzzy msgid "Random Monsters" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monster 1" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monsters 1" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monster 2" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monsters 2" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monster 3" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monsters 3" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monster 4" msgstr "AtsitiktinÄ— pilis" #, fuzzy msgid "Random Monsters 4" msgstr "AtsitiktinÄ— pilis" msgid "Double shot" msgstr "" #, fuzzy msgid "2-hex monster" msgstr "Pulti %{monster}" msgid "Double strike" msgstr "" msgid "Double damage to Undead" msgstr "" msgid "% magic resistance" msgstr "" msgid "Immune to Mind spells" msgstr "" msgid "Immune to Elemental spells" msgstr "" msgid "Immune to Fire spells" msgstr "" msgid "Immune to Cold spells" msgstr "" msgid "Immune to " msgstr "" msgid "% immunity to %{spell} spell" msgstr "" msgid "% damage from Elemental spells" msgstr "" msgid "% damage from %{spell} spell" msgstr "" msgid "% chance to Dispel beneficial spells" msgstr "" msgid "% chance to Paralyze" msgstr "" msgid "% chance to Petrify" msgstr "" msgid "% chance to Blind" msgstr "" msgid "% chance to Curse" msgstr "" msgid "% chance to cast %{spell} spell" msgstr "" msgid "HP regeneration" msgstr "" msgid "Two hexes attack" msgstr "" msgid "Flyer" msgstr "" msgid "Always retaliates" msgstr "" msgid "Attacks all adjacent enemies" msgstr "" msgid "No melee penalty" msgstr "" #, fuzzy msgid "Dragon" msgstr "Drakonų miestas" msgid "Undead" msgstr "" msgid "No enemy retaliation" msgstr "" msgid "HP drain" msgstr "" #, fuzzy msgid "Cloud attack" msgstr "Dangaus pilis" msgid "Decreases enemy's morale by " msgstr "" msgid "% chance to halve enemy" msgstr "" msgid "Soul Eater" msgstr "" msgid "Elemental" msgstr "" msgid "No Morale" msgstr "" #, fuzzy msgid "Earth creature" msgstr "Pasamdyti %{name}" #, fuzzy msgid "Air creature" msgstr "Pasamdyti %{name}" #, fuzzy msgid "Fire creature" msgstr "Pasamdyti %{name}" #, fuzzy msgid "Water creature" msgstr "Pasamdyti %{name}" msgid "Double damage from Fire spells" msgstr "" msgid "Double damage from Cold spells" msgstr "" msgid "Double damage from Earth creatures" msgstr "" msgid "Double damage from Air creatures" msgstr "" msgid "Double damage from Fire creatures" msgstr "" msgid "Double damage from Water creatures" msgstr "" msgid "Lightning" msgstr "" msgid "% immunity to " msgstr "" msgid "% damage from " msgstr "" msgid "The three Anduran artifacts magically combine into one." msgstr "" msgid "View Spells" msgstr "" #, fuzzy msgid "View %{name} Info" msgstr "ŽiÅ«rÄ—ti %{name}" msgid "Move %{name}" msgstr "" msgid "Cannot move the Spellbook" msgstr "" msgid "This item can't be traded." msgstr "" #, fuzzy msgid "Invalid Artifact" msgstr "MagiÅ¡kas artefaktas" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "Ultimate Book of Knowledge" msgstr "" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "Ultimate Sword of Dominion" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "Ultimate Cloak of Protection" msgstr "" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "Ultimate Wand of Magic" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "Ultimate Shield" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "Ultimate Staff" msgstr "" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "Ultimate Crown" msgstr "" msgid "Golden Goose" msgstr "" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} teikia jums %{count} aukso monetų per dienÄ…." msgid "Arcane Necklace of Magic" msgstr "" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" msgid "Caster's Bracelet of Magic" msgstr "" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" msgid "Mage's Ring of Power" msgstr "" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" msgid "Witch's Broach of Magic" msgstr "" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" msgid "Medal of Valor" msgstr "" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" msgid "Medal of Courage" msgstr "" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" msgid "Medal of Honor" msgstr "" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" msgid "Medal of Distinction" msgstr "" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" msgid "Fizbin of Misfortune" msgstr "" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" msgid "Thunder Mace of Dominion" msgstr "" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" msgid "Armored Gauntlets of Protection" msgstr "" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" msgid "Defender Helm of Protection" msgstr "" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" msgid "Giant Flail of Dominion" msgstr "" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" msgid "Ballista of Quickness" msgstr "" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" msgid "Stealth Shield of Protection" msgstr "" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" msgid "Dragon Sword of Dominion" msgstr "" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" msgid "Power Axe of Dominion" msgstr "" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" msgid "Divine Breastplate of Protection" msgstr "" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" msgid "Minor Scroll of Knowledge" msgstr "" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" msgid "Major Scroll of Knowledge" msgstr "" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" msgid "Superior Scroll of Knowledge" msgstr "" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" msgid "Foremost Scroll of Knowledge" msgstr "" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" msgid "Endless Sack of Gold" msgstr "" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} teikia jums %{count} aukso monetų per dienÄ…." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" msgid "Endless Bag of Gold" msgstr "" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" msgid "Endless Purse of Gold" msgstr "" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" msgid "Nomad Boots of Mobility" msgstr "" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" msgid "Traveler's Boots of Mobility" msgstr "" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" msgid "Lucky Rabbit's Foot" msgstr "" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" msgid "Golden Horseshoe" msgstr "" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" msgid "Gambler's Lucky Coin" msgstr "" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" msgid "Four-Leaf Clover" msgstr "" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" msgid "True Compass of Mobility" msgstr "" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" msgid "Sailor's Astrolabe of Mobility" msgstr "" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" msgid "Evil Eye" msgstr "" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" msgid "Enchanted Hourglass" msgstr "" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" msgid "Gold Watch" msgstr "" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "" msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" msgid "Skullcap" msgstr "" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" msgid "Ice Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" msgid "Fire Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" msgid "Lightning Helm" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" msgid "Evercold Icicle" msgstr "" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" msgid "Everhot Lava Rock" msgstr "" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" msgid "Lightning Rod" msgstr "" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" msgid "Snake-Ring" msgstr "" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" msgid "Ankh" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" msgid "Book of Elements" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" msgid "Elemental Ring" msgstr "" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" msgid "Holy Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" msgid "Pendant of Free Will" msgstr "" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" msgid "Pendant of Life" msgstr "" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "" msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" msgid "Serenity Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" msgid "Seeing-eye Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" msgid "Kinetic Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" msgid "Pendant of Death" msgstr "" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" msgid "Wand of Negation" msgstr "" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" msgid "Golden Bow" msgstr "Auksinis lankas" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" msgid "Telescope" msgstr "" #, fuzzy msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "Å ulinys padidina prieaugį visuose bÅ«stuose % {count} bÅ«tybÄ—m per savaitÄ™." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" msgid "Statesman's Quill" msgstr "" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" msgid "Wizard's Hat" msgstr "" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" msgid "Power Ring" msgstr "" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} teikia %{count} geležies rÅ«dos vnt. per dienÄ…." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" msgid "Ammo Cart" msgstr "" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" msgid "Tax Lien" msgstr "" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} kainuos jums %{count} aukso monetų per dienÄ…." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" msgid "Hideous Mask" msgstr "" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" msgid "Endless Pouch of Sulfur" msgstr "" #, fuzzy msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} teikia %{count} sieros vnt. per dienÄ…." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" msgid "Endless Vial of Mercury" msgstr "" #, fuzzy msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} teikia %{count} gyvsidabrio vnt. per dienÄ…." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" msgid "Endless Pouch of Gems" msgstr "" #, fuzzy msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} teikia %{count} brangakmenį per dienÄ…." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" msgid "Endless Cord of Wood" msgstr "" #, fuzzy msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} teikia %{count} medienos vnt. per dienÄ…." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" msgid "Endless Cart of Ore" msgstr "" #, fuzzy msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} teikia %{count} geležies rÅ«dos vnt. per dienÄ…." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" msgid "Endless Pouch of Crystal" msgstr "" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} teikia %{count} kristalÄ… per dienÄ…." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" msgid "Spiked Helm" msgstr "" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" msgid "Spiked Shield" msgstr "" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" msgid "White Pearl" msgstr "" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" msgid "Black Pearl" msgstr "" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" msgid "Magic Book" msgstr "MagiÅ¡ka knyga" msgid "The %{name} enables the hero to cast spells." msgstr "" msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "" #, fuzzy msgid "The reserved artifact." msgstr " su vienu artefaktu" msgid "Dummy 3" msgstr "" msgid "Dummy 4" msgstr "" msgid "Spell Scroll" msgstr "" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" msgid "Arm of the Martyr" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" msgid "Breastplate of Anduran" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" msgid "Broach of Shielding" msgstr "" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" msgid "Battle Garb of Anduran" msgstr "" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" msgid "Crystal Ball" msgstr "KriÅ¡tolinis kamuolys" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" msgid "Heart of Fire" msgstr "" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" msgid "Heart of Ice" msgstr "" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" msgid "Helmet of Anduran" msgstr "" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" msgid "Holy Hammer" msgstr "" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" msgid "Legendary Scepter" msgstr "" msgid "The %{name} adds %{count} points to all attributes." msgstr "" msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" msgid "Masthead" msgstr "" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" msgid "Sphere of Negation" msgstr "" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" msgid "Staff of Wizardry" msgstr "" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" msgid "Sword Breaker" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "Statula padidina jÅ«sų miesto pajamas %{count} auksinių per dienÄ…." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" msgid "Sword of Anduran" msgstr "" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" msgid "Spade of Necromancy" msgstr "" msgid "The %{name} gives the hero increased necromancy skill." msgstr "" msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Mediena" msgid "Mercury" msgstr "Gyvsidabris" msgid "Ore" msgstr "RÅ«da" msgid "Sulfur" msgstr "Siera" msgid "Crystal" msgstr "Kristalai" msgid "Gems" msgstr "Brangakmeniai" msgid "Gold" msgstr "Auksas" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" msgid "Fireball" msgstr "" msgid "Fireblast" msgstr "" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "" msgid "Lightning Bolt" msgstr "" msgid "Chain Lightning" msgstr "" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" msgid "Teleport" msgstr "" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" msgid "Cure" msgstr "" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" msgid "Mass Cure" msgstr "" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" msgid "Resurrect" msgstr "" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" msgid "Resurrect True" msgstr "" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Atgaivina sužeistas ar numirusias bÅ«tybes." msgid "Haste" msgstr "" msgid "Increases the speed of any creature by %{count}." msgstr "" msgid "Increases the speed of all of your creatures by %{count}." msgstr "" msgid "Mass Haste" msgstr "" msgid "Slows target to half movement rate." msgstr "" msgid "spell|Slow" msgstr "" msgid "Mass Slow" msgstr "" msgid "Slows all enemies to half movement rate." msgstr "" msgid "spell|Blind" msgstr "" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" msgid "Bless" msgstr "" msgid "Causes the selected creatures to inflict maximum damage." msgstr "" msgid "Causes all of your units to inflict maximum damage." msgstr "" msgid "Mass Bless" msgstr "" msgid "Magically increases the defense skill of the selected creatures." msgstr "MagiÅ¡kai padidina pasirinktų karių gynybos įgÅ«džius." msgid "Stoneskin" msgstr "" msgid "Steelskin" msgstr "" #, fuzzy msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "MagiÅ¡kai padidina pasirinktų karių gynybos įgÅ«džius." msgid "Causes the selected creatures to inflict minimum damage." msgstr "" msgid "Curse" msgstr "" msgid "Causes all enemy troops to inflict minimum damage." msgstr "" msgid "Mass Curse" msgstr "" msgid "Damages all undead in the battle." msgstr "" msgid "Holy Word" msgstr "" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" msgid "Holy Shout" msgstr "" msgid "Anti-Magic" msgstr "" msgid "Prevents any magic against the selected creatures." msgstr "" msgid "Dispel Magic" msgstr "" msgid "Removes all magic spells from a single target." msgstr "" msgid "Mass Dispel" msgstr "" msgid "Removes all magic spells from all creatures." msgstr "" msgid "Causes a magic arrow to strike the selected target." msgstr "" msgid "Magic Arrow" msgstr "" msgid "Berserker" msgstr "" msgid "Causes a creature to attack its nearest neighbor." msgstr "" msgid "Armageddon" msgstr "" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" msgid "Elemental Storm" msgstr "" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" msgid "Meteor Shower" msgstr "" msgid "Paralyze" msgstr "" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" msgid "Hypnotize" msgstr "" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" msgid "Cold Ray" msgstr "" msgid "Drains body heat from a single enemy unit." msgstr "" msgid "Cold Ring" msgstr "" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" msgid "Disrupting Ray" msgstr "" msgid "Reduces the defense rating of an enemy unit by three." msgstr "" msgid "Damages all living (non-undead) units in the battle." msgstr "" msgid "Death Ripple" msgstr "" msgid "Death Wave" msgstr "" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" msgid "Dragon Slayer" msgstr "" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Smarkiai padidina kario puolimo įgÅ«džius prieÅ¡ drakonus." msgid "Blood Lust" msgstr "" msgid "Increases a unit's attack skill." msgstr "Padidina kario puolimo įgÅ«džius." msgid "Animate Dead" msgstr "" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" msgid "Mirror Image" msgstr "" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" msgid "Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Mass Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Summon Earth Elemental" msgstr "" msgid "Summons Earth Elementals to fight for your army." msgstr "" msgid "Summon Air Elemental" msgstr "" msgid "Summons Air Elementals to fight for your army." msgstr "" msgid "Summon Fire Elemental" msgstr "" msgid "Summons Fire Elementals to fight for your army." msgstr "" msgid "Summon Water Elemental" msgstr "" msgid "Summons Water Elementals to fight for your army." msgstr "" msgid "Damages castle walls." msgstr "" msgid "Earthquake" msgstr "" msgid "Causes all mines across the land to become visible." msgstr "" msgid "View Mines" msgstr "" msgid "Causes all resources across the land to become visible." msgstr "" msgid "View Resources" msgstr "Rodyti iÅ¡teklius" msgid "Causes all artifacts across the land to become visible." msgstr "" msgid "View Artifacts" msgstr "Rodyti magiÅ¡kus artefaktus" msgid "Causes all towns and castles across the land to become visible." msgstr "" msgid "View Towns" msgstr "Rodyti miestus" msgid "Causes all Heroes across the land to become visible." msgstr "" msgid "View Heroes" msgstr "" msgid "Causes the entire land to become visible." msgstr "" msgid "View All" msgstr "" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" msgid "Summon Boat" msgstr "" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" msgid "Allows the caster to magically transport to a nearby location." msgstr "" msgid "Dimension Door" msgstr "" msgid "Returns the caster to any town or castle currently owned." msgstr "" msgid "Town Gate" msgstr "" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" msgid "Visions" msgstr "" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" msgid "Haunt" msgstr "" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" msgid "Set Earth Guardian" msgstr "" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Air Guardian" msgstr "" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Fire Guardian" msgstr "" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Water Guardian" msgstr "" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" #, fuzzy msgid "Random Spell" msgstr "Atsitiktinis miestas" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "AtsitiktinÄ— pilis" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" #, fuzzy msgid "Petrification" msgstr "Ä®tvirtinimai" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" msgid "No spell to cast." msgstr "" msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "" msgid "View Adventure Spells" msgstr "" msgid "View Combat Spells" msgstr "" #, fuzzy msgid "View previous page" msgstr "Rodyti ankstesnį miestÄ…" #, fuzzy msgid "View next page" msgstr "ŽiÅ«rÄ—ti %{name}" msgid "Close Spellbook" msgstr "" #, fuzzy msgid "View %{spell}" msgstr "ŽiÅ«rÄ—ti %{name}" msgid "This spell does %{damage} points of damage." msgstr "" msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" msgid "This spell restores %{hp} HP." msgstr "" msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" msgid "The nearest town is %{town}." msgstr "" msgid "This town is occupied by your hero %{hero}." msgstr "" msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" msgid "The ultimate artifact is really the %{name}." msgstr "" msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" msgid "north-west" msgstr "" msgid "north" msgstr "" msgid "north-east" msgstr "" msgid "west" msgstr "" msgid "center" msgstr "" msgid "east" msgstr "" msgid "south-west" msgstr "" msgid "south" msgstr "" msgid "south-east" msgstr "" msgid "The truth is out there." msgstr "" msgid "The dark side is stronger." msgstr "" msgid "The end of the world is near." msgstr "" msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" msgid "A Black Dragon will take out a Titan any day of the week." msgstr "" msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" msgid "An unknown force is being resurrected..." msgstr "" msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" #, fuzzy #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "" #~ "Ar tikrai norite perraÅ¡yti anksÄiau tuo paÄiu pavadinimu įraÅ¡ytÄ… failÄ…?" #~ msgid "Warning!" #~ msgstr "Ä®spÄ—jimas!" fheroes2-1.1.6+dfsg/files/lang/nb.po000066400000000000000000012010251476115357100171500ustar00rootroot00000000000000# Norwegian translation for fheroes2 # Copyright (C) 2021 - 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2023-09-03 18:42+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: nb_NO\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: Poedit 3.2.2\n" msgid "" "NEW\n" "GAME" msgstr "" "NYTT\n" "PARTI" msgid "" "SAVE\n" "GAME" msgstr "" "LAGRE\n" "PARTI" msgid "" "LOAD\n" "GAME" msgstr "" "LAST\n" "INN\n" "PARTI" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "" "AV-\n" "SLUTT" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "NYTT\n" "PARTI" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "LAGRE\n" "PARTI" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "LAST\n" "INN\n" "PARTI" msgid "CANCEL" msgstr "AVBRYT" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "GODTA" msgid "DECLINE" msgstr "AVSLÃ…" msgid "LEARN" msgstr "LÆR" msgid "TRADE" msgstr "BYTT" msgid "YES" msgstr "JA" msgid "NO" msgstr "NEI" msgid "EXIT" msgstr "UT" msgid "smallerButton|EXIT" msgstr "UT" msgid "DISMISS" msgstr "BORTVIS" msgid "UPGRADE" msgstr "OPPGRAD." msgid "RESTART" msgstr "OMSTART" msgid "HEROES" msgstr "HELTER" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "BYER/\n" "BORGER" msgid "S" msgstr "L" msgid "M" msgstr "M" msgid "L" msgstr "S" msgid "X-L" msgstr "XS" msgid "ALL" msgstr "ALT" msgid "SELECT" msgstr "ENDRE" msgid "" "STANDARD\n" "GAME" msgstr "" "ENKELT\n" "PARTI" msgid "" "BATTLE\n" "ONLY" msgstr "KAMP" msgid "" "CAMPAIGN\n" "GAME" msgstr "FELTTOG" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "FLER-\n" "SPILLER" msgid "CONFIG" msgstr "VALG" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "KRIGEN\n" "OM\n" "TRONEN" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "PRISEN FOR\n" "LOJALITET" msgid "HOT SEAT" msgstr "" "BYTTE-\n" "SPILLING" msgid "2 PLAYERS" msgstr "2 SPILLERE" msgid "3 PLAYERS" msgstr "3 SPILLERE" msgid "4 PLAYERS" msgstr "4 SPILLERE" msgid "5 PLAYERS" msgstr "5 SPILLERE" msgid "6 PLAYERS" msgstr "6 SPILLERE" msgid "GIFT" msgstr "SEND" msgid "MAX" msgstr "MAKS" msgid "DIFFICULTY" msgstr "FELTTOGSNIVÃ…" msgid "VIEW INTRO" msgstr "VIS VIDEO" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "" #, fuzzy msgid "START" msgstr "OMSTART" msgid "TOWN" msgstr "" #, fuzzy msgid "CASTLE" msgstr "" "BYER/\n" "BORGER" #, fuzzy msgid "RESTRICT" msgstr "OMSTART" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "B\n" "O\n" "R\n" "T\n" "V\n" "I\n" "S" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "F\n" "O\n" "R\n" "L\n" "A\n" "T" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Kriger" msgid "Builder" msgstr "Bygger" msgid "Explorer" msgstr "Utforsker" msgid "None" msgstr "Ingen" msgid "" "A few\n" "%{monster}" msgstr "" "Noen fÃ¥\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Flere\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "En flokk med\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Mange\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "En horde med\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "En skare av\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "En sverm av\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Helsikens mange\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "En legion av\n" "%{monster}" msgid "army|Few" msgstr "FÃ¥" msgid "army|Several" msgstr "Flere" msgid "army|Pack" msgstr "Flokk" msgid "army|Lots" msgstr "Mange" msgid "army|Horde" msgstr "Horde" msgid "army|Throng" msgstr "Skare" msgid "army|Swarm" msgstr "Sverm" msgid "army|Zounds" msgstr "Helsike" msgid "army|Legion" msgstr "Legion" msgid "All %{race} troops +1" msgstr "Kun styrker av %{race}tilhørighet: +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Nøytral" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Straff for Ã¥ ha styrker fra %{count} tilhørigheter -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "Vandøde blant styrkene -1" #, fuzzy msgid "" "Default\n" "troop" msgstr "Standard handling" msgid "View %{name}" msgstr "Vis %{name}" msgid "Move the %{name} " msgstr "Flytt %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Flytt eller høyreklikk for Ã¥ omfordele %{name}" msgid "Combine %{name} armies" msgstr "SlÃ¥ sammen %{name} styrker" msgid "Exchange %{name2} with %{name}" msgstr "Bytt %{name2} med %{name}" msgid "Select %{name}" msgstr "Velg %{name}" msgid "Cannot move last troop" msgstr "Kan ikke flytte siste styrke i garnisonen" msgid "Move the %{name}" msgstr "Flytt %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Skyt pÃ¥ %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "Troppen med 1 %{name} halverte fiendestyrken!" msgstr[1] "Troppen med %{name} halverte fiendestyrken!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} slo av autotrekk" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} slo pÃ¥ autotrekk" msgid "Spell failed!" msgstr "Trolldommen mislyktes!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Sfæren av opphevelse er til stede i denne kampen og dermed forhindres all " "kampmagi." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Du har allerede brukt trolldom denne runden." msgid "That spell will have no effect!" msgstr "Denne trolldommen vil ikke ha noen virkning!" msgid "You may only summon one type of elemental per combat." msgstr "Du kan kun mane fram én type elementærÃ¥nd per kamp." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "Det er ikke plass nær helten din til Ã¥ framkalle en elementærÃ¥nd." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Vollgraven reduserer forsvarsevnen til krigere som befinner seg i den med " "%{count} og halverer skrittene deres." msgid "Speed: %{speed}" msgstr "Hurtighet : %{speed}" msgid "Speed" msgstr "Hurtighet" msgid "Off" msgstr "Av" msgid "On" msgstr "PÃ¥" #, fuzzy msgid "Turn Order" msgstr "" "Tur-\n" "rekkefølge" msgid "Auto Spell Casting" msgstr "" "Auto-\n" "trylling" msgid "Grid" msgstr "Rutenett" msgid "Shadow Movement" msgstr "" "Uthevd\n" "rekkevidde" msgid "Shadow Cursor" msgstr "" "Rute-\n" "markør" msgid "Audio" msgstr "Lyd" msgid "Settings" msgstr "Innstillinger" msgid "Configure" msgstr "Konfigurer" msgid "Hot Keys" msgstr "Hurtigtaster" msgid "Damage Info" msgstr "Skadeinfo" msgid "Set the speed of combat actions and animations." msgstr "Juster hastigheten til handlingene og animasjonene i kamp." #, fuzzy msgid "Toggle to display the turn order during the battle." msgstr "" "Skru pÃ¥ denne innstillingen for Ã¥ vise rekkefølgen av krigernes tur i kamp." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Velg om datamaskinen skal bruke trolldom nÃ¥r autokamp er skrudd pÃ¥. (Merk: " "Dette pÃ¥virker ikke magibruken til datamaskinspillere pÃ¥ noen som helst " "mÃ¥te, og det pÃ¥virker heller ikke hurtigkamp.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Velg om rutenettet for slagmarken skal være synlig eller ikke. Det er de " "samme rutene man kan flytte seg til enten rutenettet vises eller ikke." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Velg om rekkevidden for hvor krigerene dine kan flytte seg skal utheves ved " "Ã¥ gjøres mørkere." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Velg om den ruten du peker pÃ¥ med markøren din skal utheves ved Ã¥ gjøres " "mørkere." msgid "Change the audio settings of the game." msgstr "Endre lydinnstillingene til spillet." msgid "Check and configure all the hot keys present in the game." msgstr "Kontroller og endre alle hurtigtastene i spillet." msgid "Toggle to display damage information during the battle." msgstr "" "Skru pÃ¥ dette for Ã¥ vise et vindu som forklarer hvor mye skade du kommer til " "Ã¥ gjøre." msgid "Exit this menu." msgstr "Forlat denne menyen." msgid "Okay" msgstr "Bekreft" msgid "The enemy has surrendered!" msgstr "Fienden overga seg!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Fienden rømte!" msgid "A glorious victory!" msgstr "En storslagen seier!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "" "For sin utmerkelse i kamp\n" " fÃ¥r %{name} %{exp} erfaringspoeng." msgid "The cowardly %{name} flees from battle." msgstr "Den feige %{name} rømmer fra kampen." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} gir opp kampen mot fienden og forlater slagmarken i skam." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Hæren din lider et bittert nederlag og %{name} forlater din sak." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Hæren din lider et bittert nederlag." msgid "Battlefield Casualties" msgstr "Slagmarkens offre" msgid "Attacker" msgstr "Angripende side" msgid "Defender" msgstr "Forsvarende side" #, fuzzy msgid "Click to leave the battle results." msgstr "Trykk for Ã¥ bruke den valgte oppløsningen." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Klikk her for Ã¥ dra tilbake til hovedmenyen." msgid "Restart" msgstr "Start pÃ¥ nytt" msgid "You have captured an enemy artifact!" msgstr "Du har overtatt en av fiendens skatter!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Idet du skal til Ã¥ gripe %{name} forsvinner den pÃ¥ mystisk vis." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Idet fienden din skal til Ã¥ ta %{name} forsvinner den pÃ¥ mystisk vis." msgid "Necromancy!" msgstr "Sortekunst!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Gjennom din utøvelse av sortekunst er du i stand til Ã¥ gjenreise %{count} av " "fiendens døde til Ã¥ tjene deg som %{monster}." msgid "%{name} the %{race}" msgstr "%{race}en %{name}" msgid "Captain of %{name}" msgstr "Kapteinen til %{name}" msgid "Attack" msgstr "Angrep" msgid "Defense" msgstr "Forsvar" msgid "Spell Power" msgstr "Kraft" msgid "Knowledge" msgstr "Kunnskap" msgid "Morale" msgstr "KampÃ¥nd" msgid "Luck" msgstr "Flaks" msgid "Spell Points" msgstr "Mana" msgid "Hero's Options" msgstr "Heltevalg" msgid "Cast Spell" msgstr "Bruk trolldom" msgid "Retreat" msgstr "Flykt" msgid "Surrender" msgstr "Overgi deg" msgid "Cancel" msgstr "Avbryt" msgid "Hero Screen" msgstr "Heltevindu" msgid "Captain's Options" msgstr "Innstillinger for kapteinen" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Bruk en trolldom. Du kan kun bruke én per kamprunde. Runden er over nÃ¥r hver " "kriger har gjort sin tur." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Flykt med helten din og forlat dine krigere. Helten vil bli tilgjengelig for " "verving med en gang, men kun med startstyrker." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Det koster gull Ã¥ overgi seg. Dersom du betaler løsepengene vil helten din, " "samt alle de gjenværende krigerne, kunne verves igjen." msgid "Open Hero Screen to view full information about the hero." msgstr "Ã…pne heltevinduet for Ã¥ se all informasjon om en helt." msgid "Return to the battle." msgstr "GÃ¥ tilbake til kampen." msgid "Not enough gold (%{gold})" msgstr "Ikke nok gull (%{gold})" msgid "%{name} states:" msgstr "%{name} erklærer:" msgid "Captain of %{name} states:" msgstr "Kapteinen av %{name} erklærer:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Jeg vil akseptere din overgivelse og gÃ¥ med pÃ¥ Ã¥ gi deg og dine styrker " "fritt leide imot %{price} gullstykker.\"" msgid "View %{monster} info" msgstr "Vis info om %{monster}" msgid "Fly %{monster} here" msgstr "Fly %{monster} hit" msgid "Move %{monster} here" msgstr "Flytt %{monster} hit" msgid "Shoot %{monster}" msgstr "Skyt pÃ¥ %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 skudd igjen)" msgstr[1] "(%{count} skudd igjen)" msgid "Attack %{monster}" msgstr "Angrip %{monster}" msgid "Turn %{turn}" msgstr "Runde %{turn}" msgid "Teleport here" msgstr "Teleporter hit" msgid "Invalid teleport destination" msgstr "Ugyldig teleporteringsmÃ¥l" msgid "Cast %{spell} on %{monster}" msgstr "Bruk %{spell} pÃ¥ %{monster}" msgid "Cast %{spell}" msgstr "Bruk %{spell}" msgid "Select spell target" msgstr "Velg trolldomsmÃ¥l" msgid "View Ballista info" msgstr "Vis info om ballisten" msgid "Ballista" msgstr "Ballist" #, fuzzy msgid "Automatic combat modes" msgstr "Autokamp" #, fuzzy msgid "Automatic Combat Modes" msgstr "Autokamp" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Skreddersy systeminnstillinger" msgid "Allows you to customize the combat screen." msgstr "Lar deg skreddersy kampvinduet." msgid "System Options" msgstr "Systeminnstillinger" msgid "Skip this unit" msgstr "Hopp over denne styrken" msgid "Skip" msgstr "Hopp over" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Hopper over den nÃ¥værende krigeren. Turen dens avsluttes og neste tur vil " "ikke komme før neste runde." msgid "View Captain's options" msgstr "Vis innstillinger for kapteinen" msgid "View Hero's options" msgstr "Vis helteinnstillinger" msgid "View opposing Captain" msgstr "Vis info om motstanderens kaptein" msgid "View opposing Hero" msgstr "Vis motstanderhelt" msgid "Hide logs" msgstr "Gjem logg" msgid "Show logs" msgstr "Vis logg" msgid "Message Bar" msgstr "Kamplogg" msgid "Shows the results of individual monster's actions." msgstr "Viser en logg over alle krigernes trekk." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Er du sikker pÃ¥ at du ønsker Ã¥ skru pÃ¥ autokamp?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Er du sikker pÃ¥ at du vil fullføre kampen med automatiske trekk?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Lar datamaskinen gjøre trekkene for deg." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Autokamp" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Autokamp" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "Troppen med %{name} hoppet over turen sin." msgstr[1] "Troppen med %{name} hoppet over turen sin." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "Troppen med 1 %{attacker} gjorde %{damage} skadepoeng." msgstr[1] "Troppen med %{attacker} gjorde %{damage} skadepoeng." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 kriger døde." msgstr[1] "%{count} krigere dør." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} døde." msgstr[1] "%{count} %{defender} dør." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 sjel ble sanket." msgstr[1] "%{count} sjeler ble sanket." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} ble gjenreist." msgstr[1] "%{count} %{unit} ble gjenreist." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Flyttet troppen med %{monster} fra [%{src}] til [%{dst}]." #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "Troppen med %{name} motstod trolldommen!" msgstr[1] "Troppen med %{name} motstod trolldommen!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} brukte %{spell} pÃ¥ troppen med %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} brukte %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} gjorde %{damage} skadepoeng pÃ¥ én vandød kriger." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} gjorde %{damage} skadepoeng pÃ¥ alle vandøde." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} gjorde %{damage} skadepoeng, %{count} krigere dør." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} gjorde %{damage} skadepoeng." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} gjorde %{damage} skadepoeng pÃ¥ én levende kriger." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} gjorde %{damage} skadepoeng pÃ¥ alle levende krigere." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "" "Angrepet til troppen med %{attacker} gjorde troppen med %{target} blind!" msgstr[1] "" "Angrepet til troppen med %{attacker} gjorde troppen med %{target} blind!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "" "Blikket til troppen med %{attacker} forsteinet troppen med %{target}!" msgstr[1] "" "Blikket til troppen med %{attacker} forsteinet troppen med %{target}!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "" "Forbannelsen til troppen med %{attacker} la seg over troppen med %{target}!" msgstr[1] "" "Forbannelsen til troppen med %{attacker} la seg over troppen med %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "Troppen med %{target} ble lammet av troppen med %{attacker}!" msgstr[1] "Troppen med %{target} ble lammet av troppen med %{attacker}!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" "Troppen med %{attacker} opphevde alle gode trolldommer pÃ¥ dine %{target}!" msgstr[1] "" "Troppen med %{attacker} opphevde alle gode trolldommer pÃ¥ dine %{target}!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "Gruppen med %{attacker} brukte %{spell} pÃ¥ troppen med %{target}!" msgstr[1] "Gruppen med %{attacker} brukte %{spell} pÃ¥ troppen med %{target}!" # Bestemtform flertall feks. Dvergene fÃ¥r uflaks i stedet for "dverger fÃ¥r uflaks" msgid "Bad luck descends on the %{attacker}." msgstr "Troppen med %{attacker} fikk uflaks." msgid "Good luck shines on the %{attacker}." msgstr "Troppen med %{attacker} fikk flaks." msgid "High morale enables the %{monster} to attack again." msgstr "God kampÃ¥nd gjorde at troppen med %{monster} fikk en ny tur." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "DÃ¥rlig kampÃ¥nd gjorde at troppen med %{monster} stivnet av panikk." # Kan være det venstre tÃ¥rnet eller Ballisten. Foreløpig best er Borgens ballist gjør... msgid "%{tower} does %{damage} damage." msgstr "Borgens %{tower} gjorde %{damage} skadepoeng." msgid "The mirror image is created." msgstr "Speilbildet ble skapt." msgid "The mirror image is destroyed!" msgstr "Speilbildet ble ødelagt!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Er du sikker pÃ¥ at du vil avbryte de automatiske trekkene?" msgid "Error" msgstr "Feil" msgid "No spells to cast." msgstr "Ingen trolldommer tilgjengelige." msgid "Are you sure you want to retreat?" msgstr "Er du sikker pÃ¥ at du vil flykte fra kampen?" msgid "Retreat disabled" msgstr "Tilbaketrekning forhindret" msgid "Surrender disabled" msgstr "Overgivelse forhindret" msgid "Damage: %{max}" msgstr "Skadepoeng : %{max}" msgid "Damage: %{min} - %{max}" msgstr "Skadepoeng : %{min} - %{max}" msgid "Perish: %{max}" msgstr "Dødstall : %{max}" msgid "Perish: %{min} - %{max}" msgstr "Dødstall : %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Gjennom sitt skarpe ørneblikk fikk %{name} til Ã¥ plukke opp trolldommen:\n" " %{spell}." msgid "Human" msgstr "Menneske" msgid "AI" msgstr "Datamaskin" #, fuzzy msgid "Start" msgstr "Start pÃ¥ nytt" #, fuzzy msgid "Start the battle." msgstr "GÃ¥ tilbake til kampen." msgid "Exit" msgstr "GÃ¥ ut" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Vennligst velg en annen helt." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{name1} møter %{name2}" msgid "Monsters" msgstr "Monstre" msgid "N/A" msgstr "Ingen" # Brukes til borgbygging ogsÃ¥. Det venstre tÃ¥rnet eller Ballisten. msgid "Left Turret" msgstr "Venstre tÃ¥rn" msgid "Right Turret" msgstr "Høyre tÃ¥rn" # Samme som over. Det venstre tÃ¥rnet eller Ballisten. msgid "The %{name} fires with the strength of %{count} Archers" msgstr "Borgens %{name} skyter med styrken til %{count} bueskyttere" msgid "each with a +%{attack} bonus to their attack skill." msgstr "hver med en angrepsbonus pÃ¥ +%{attack}." msgid "The %{name} is destroyed." msgstr "Borgens %{name} ble ødelagt." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} gjenoppstod fra de døde!" msgstr[1] "%{count} %{name} gjenoppstod fra de døde!" msgid "Dwarven Alliance" msgstr "Dvergealliansen" msgid "Sorceress Guild" msgstr "Trollkvinnelauget" msgid "Necromancer Guild" msgstr "Sortekunstnerlaug" msgid "Ogre Alliance" msgstr "Jettealliansen" msgid "Dwarfbane" msgstr "Dvergebane" msgid "Dragon Alliance" msgstr "Dragealliansen" msgid "Elven Alliance" msgstr "Alvealliansen" msgid "Kraeger defeated" msgstr "Kreiger fanget" msgid "Wayward Son" msgstr "Den villfarne sønnen" msgid "Uncle Ivan" msgstr "Onkel Ivan" msgid "Annexation" msgstr "Underleggelse" msgid "Force of Arms" msgstr "Til vÃ¥pnene!" msgid "Save the Dwarves" msgstr "Dvergenes unnsetning" msgid "Carator Mines" msgstr "Karatorgruvene" msgid "Turning Point" msgstr "Vendepunktet" msgid "scenarioName|Defender" msgstr "Beskytteren" msgid "Corlagon's Defense" msgstr "Korlagon sitt forsvar" msgid "The Crown" msgstr "Kronen" msgid "The Gauntlet" msgstr "Kappløpet" msgid "Betrayal" msgstr "Forræderi" msgid "Final Justice" msgstr "Rettferd, for godt" #, fuzzy msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Som første steg i opprøret mot sin bror, ber Roland deg om Ã¥ beseire " "krigsherrene i omrÃ¥det rundt hans borg. Krigsherrene er ikke allierte og vil " "dermed bruke mesteparten av sin tid pÃ¥ Ã¥ krige seg imellom. Seieren er din " "nÃ¥r du har erobret alle deres borger og overvunnet deres helter." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "De lokale fyrstene nekter Ã¥ underlegge seg Roland, og mÃ¥ tvinges til det. De " "er rike og mektige, sÃ¥ vær forberedt pÃ¥ en hard kamp. Erobre alle fiendtlige " "borger for Ã¥ vinne." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Din oppgave er Ã¥ beskytte dvergene fra Archibalds styrker. Erobre alle " "fiendens byer og borger for Ã¥ vinne, og pass pÃ¥ Ã¥ ikke miste alle " "dvergebyene til samme tid, ellers vinner fienden." # rett fram? #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Du vil møte fire allierte fiender i en renspikket kamp om rÃ¥varer og " "skatter. Erobre alle fiendens borger for Ã¥ vinne." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Dine fiender er allierte mot deg, og de starter i nærheten av deg, sÃ¥ du mÃ¥ " "være klar for kamp nÃ¥r som helst. Du mÃ¥ kontrollere alle de fire borgene i " "denne lille dalen for Ã¥ vinne." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Trollkvinnenes laug i Noraston ber om Roland sin hjelp for Ã¥ klare Ã¥ stÃ¥ " "imot et angrep fra Archibald sine allierte. Overta alle fiendens borger for " "Ã¥ vinne og ikke mist Noraston, ellers taper du kartet.\n" "(Hint: Det ligger en fiendtlig borg pÃ¥ en øy i havet.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Samle sammen en sÃ¥ stor hær som mulig og ta over borgen til fienden innen " "Ã¥tte uker. Du har kun én motstander, men du mÃ¥ reise langt for Ã¥ komme til " "ham. Alle styrkene du mÃ¥tte ha i hæren din ved enden av scenarioet vil følge " "med deg videre til det siste scenarioet." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Finn kronen før Archibald sine helter finner den. Roland vil trenge kronen " "for det siste slaget mot Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Tre allierte fiender stÃ¥r mellom deg og seier. Blant fiendene dine er baron " "Korlagon. Roland er i en borg i nordvest, og du taper dersom han faller i " "fiendens hender. Merk at hvis du fanger baron Korlagon vil det sørge for at " "du ikke møter ham i det siste scenarioet." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Dette er det siste slaget. BÃ¥de du og fienden din er væpnet til tennene, og " "alle er allierte mot deg. Fang Archibald for Ã¥ avslutte krigen!" #, fuzzy msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Hvis du bytter lag vil du begynne med tre borger, mens fienden kun med én. " "Dette slaget vil bli ditt enkleste under hele krigen...forræder." msgid "Barbarian Wars" msgstr "Barbarkrigene" msgid "First Blood" msgstr "Den første bloddrÃ¥pen" msgid "Necromancers" msgstr "Sortekunstnere" # Slakt brukes mer om dyr pÃ¥ norsk. msgid "Slay the Dwarves" msgstr "Myrd dvergene" msgid "Country Lords" msgstr "Landsherrene" msgid "Dragon Master" msgstr "Dragemesteren" msgid "Rebellion" msgstr "Opprør" msgid "Apocalypse" msgstr "Dommedag" msgid "Greater Glory" msgstr "Heder og ære" #, fuzzy msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Kong Archibald forlanger at du beseirer hans tre fiender i dette omrÃ¥det. De " "er ikke allierte med hverandre og vil derfor bruke mesteparten av kreftene " "sine pÃ¥ Ã¥ krige seg imellom. Du vinner nÃ¥r du har underlagt deg alle de " "fiendtlige borgene og det ikke er flere helter igjen Ã¥ slÃ¥." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Du mÃ¥ forene de barbariske stammene i nord ved Ã¥ beseire dem. Som i det " "forrige oppdraget er fiendene ikke alliert mot deg, men de har mer rÃ¥varer " "tilgjengelig. Du vil vinne nÃ¥r du eier alle de fiendtlige borgene og det " "ikke er flere helter igjen Ã¥ slÃ¥." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Regelryttende magimestere har tatt over Sortekunstnernes borg. Du mÃ¥ " "gjenerobre den for Ã¥ oppnÃ¥ seier. Husk at selv om du starter med en sterk " "hær sÃ¥ har du ikke en borg. Derfor mÃ¥ du overta en innen 7 dager, hvis ikke " "taper du dette slaget. (Hint: Den nærmeste borgen ligger i sørøst.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Dvergene mÃ¥ slÃ¥s ut før de rekker Ã¥ blande seg i Kong Archibald sine planer. " "Roland sine styrker har mer enn én helt, for ikke Ã¥ nevne flere byer i " "begynnelsen, sÃ¥ vær forberedt pÃ¥ angrep fra alle kanter. Du mÃ¥ overta alle " "de fiendtlige byene og borgene for Ã¥ ta seieren." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Du mÃ¥ slÃ¥ ned pÃ¥ bondeopprøret ledet av Roland sine styrker. Alle er " "allierte mot deg, men du har den erfarne helten fyrst Korlagon pÃ¥ din side. " "Underlegg deg alle fiendens borger for Ã¥ vinne." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Det er to fiender som er allierte mot deg i dette oppdraget. Begge to er " "godt utrustede og vil forsøke Ã¥ drive deg ut av landet deres. UnngÃ¥ dem og " "overta Dragenes landsby for Ã¥ vinne." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Dine ordre er Ã¥ slÃ¥ ut landsherrene som har sverget troskap til Roland. Alle " "de fiendtlige borgene er forente mot deg. Siden du starter uten en borg mÃ¥ " "du skynde deg med Ã¥ ta over én før slutten av uka. Overta alle fiendtlige " "borger for Ã¥ vinne." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Finn kronen før Roland sine helter finner den. Archibald kommer til Ã¥ trenge " "kronen i det endelige slaget mot Roland." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Dette er det endelige slaget. BÃ¥de du og din fiende er væpnet til tennene, " "og alle er allierte mot deg. Fang Roland for Ã¥ vinne krigen, og pass pÃ¥ Ã¥ " "ikke miste Archibald i kamp!" msgid "Arrow's Flight" msgstr "I pilens skuddlinje" msgid "Island of Chaos" msgstr "Kaosøya" msgid "The Abyss" msgstr "Avgrunnen" msgid "Uprising" msgstr "Opprør" msgid "Aurora Borealis" msgstr "Nordlys" msgid "Betrayal's End" msgstr "Forræderiets ende" msgid "Corruption's Heart" msgstr "Fordervelsens hjerte" msgid "The Giant's Pass" msgstr "Fjellovergangen" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Underlegg deg de motvillige lokalhøvdingene slik at Keiserriket fÃ¥r et " "fotfeste i regionen." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "SlÃ¥ ned pÃ¥ all motstanden i dette omrÃ¥det. NÃ¥r du har klart det vil den " "første biten av skatten du søker bli din." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Trollkvinnene i nordøst gjør opprør!\n" "For Keiserrikets sak mÃ¥ du knuse deres stusslige opprør pÃ¥ ferden din mot " "fjellene." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "For Ã¥ forberede seg pÃ¥ deg har Kreiger gjort klar en styrke med " "sortekunstnere hvis mÃ¥l er Ã¥ sette en stopper for oppdraget ditt Du mÃ¥ " "overta borgen kalt Scabsdale før den første dagen av den tredje uka, ellers " "vil sortekunstnerne bli for sterke for deg." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Det barbariske tyranniet i omrÃ¥det er, enn sÃ¥ lenge, uvitende om din " "tilstedeværelse. Bygg opp styrkene dine raskt før du blir oppdaget og " "angrepet! Sikre omrÃ¥det ved Ã¥ slÃ¥ ut alle fiendtlige styrker." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Keiserriket stÃ¥r svakt i denne regionen, og derfor vil det være umulig Ã¥ " "underlegge seg alle motstanderne. Du bør heller samle det du rekker før de " "gÃ¥r til angrep pÃ¥ deg. Husk at mÃ¥let ditt er Ã¥ fÃ¥ tak i Andurans hjelm." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Du mÃ¥ utrydde Kreiger, for Keiserrikets beste." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Endelig har du muligheten og evnene til Ã¥ befri Keiserriket fra " "sortekunstnerens ondskap. Tilintetgjør dem fullstendig, og du vil bli sunget " "om som en helt for evig tid." msgid "Border Towns" msgstr "Grensebyene" msgid "Conquer and Unify" msgstr "Erobre og foren" msgid "Crazy Uncle Ivan" msgstr "Den gale onkel Ivan" msgid "The Wayward Son" msgstr "Den villfarne sønnen" msgid "Ivory Gates" msgstr "Elfenbensportene" msgid "The Elven Lands" msgstr "Alvelandene" msgid "The Epic Battle" msgstr "Det store slaget" msgid "The Southern War" msgstr "Krigen i sør" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Erobre og foren alle de fiendtlige stammene. Ikke mist helten ved navn " "Jarkonas, alle etterkommeres forfeder." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Motstanderen din, kongedømmet av Harondale, driver og angriper svake byer pÃ¥ " "grensa di! Reis hæren din pÃ¥ nytt etter det første angrepet deres, og sÃ¥ " "knus dem fullstendig!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Finn din villfarne sønn, Josef, som ryktes Ã¥ bo pÃ¥ de øde øyene. Gjør det " "før den første dagen av den tredje mÃ¥neden, ellers vil alt være til ingen " "nytte for familien din." #, fuzzy msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Redd din gale onkel Ivan. Finn han før den første dagen av den fjerde " "mÃ¥neden, ellers vil ikke kongedømmet ditt ha noe Ã¥ tjene pÃ¥ det." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Utslett barbarene som angriper kongedømmet ditt sin sørlige grense! Ta " "tilbake dine tapte byer, og rykk inn i kongeriket som befinner seg i " "jungelen. Ikke etterlat deg noen overlevende." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Gjenerobre borgen kalt Ivory Gates, som har falt grunnet forræderi ." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Kom pÃ¥ godfot med alvene. De tillater ikke nedhogging av trær, sÃ¥ derfor " "sender de deg ved annenhver uke. Du mÃ¥ fullføre oppdraget ditt før den " "første dagen av den sjuende mÃ¥neden, ellers vil kongedømmet ditt falle." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Dette er det siste slaget mot motstanderen din, kongeriket av Harondale. " "Utrydd alle, og ikke mist helten kalt Jarkonas VI." msgid "Fount of Wizardry" msgstr "Trolldomskilden" msgid "Power's End" msgstr "Maktens ende" msgid "The Eternal Scrolls" msgstr "Evighetens skriftruller" msgid "The Shrouded Isles" msgstr "De skyggelagte øyene" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Ditt oppdrag er Ã¥ utslette de krigende magikerne pÃ¥ De magiske skyggelagte " "øyene. Hvis du klarer denne oppgaven, vil du ha sjanse mot motstanderne dine." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Beliggenheten til det store biblioteket har blitt funnet! Du mÃ¥ bane deg vei " "til det og gjenvinn byen av Chronos der det ligger." #, fuzzy msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Finn Kulen av benektelse som ryktes Ã¥ være gravd ned et sted i denne " "regionen. Det fins ledetrÃ¥der til denne skatten i form av innriss pÃ¥ " "obelisker. Finn kulen før den første dagen av den sjette mÃ¥neden, ellers vil " "motstanderne dine fÃ¥ klørne i den før deg." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Du mÃ¥ ta kontrollen over Magislottet som er stedet hvor trolldomskilden " "ligger. Gjør dette, og seieren vil bli den største du noen sinne har oppnÃ¥dd." msgid "Blood is Thicker" msgstr "Blod er tykkere" msgid "King and Country" msgstr "Konge og velde" msgid "Pirate Isles" msgstr "Piratøyene" msgid "Stranded" msgstr "Strandet" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Overta byen pÃ¥ øya utenfor kysten i sørøst for Ã¥ kunne lage et skip og reise " "tilbake til fastlandet. Ikke mist helten kalt Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Finn og beseir Martine, lederen av piratene. Hun oppholder seg i Piratbukta. " "Ikke mist Gallavant, ellers vil oppdraget ditt mislykkes." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Utslett alle styrker som motsier seg veldet til baron Alberon. Gallavant mÃ¥ " "under ingen omstendigheter dø." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Styrt det dypt rotfestede kongedømmet til baron Alberon, og legg krav pÃ¥ " "hele landet i ditt navn. Gallavant mÃ¥ ikke dø." msgid " bane" msgstr "morderen" msgid " alliance" msgstr "allianse" # Medbrakte? Videreførbare? msgid "Carry-over forces" msgstr "Medbrakte styrker" # Ville ha vært bedre med "Ekstra ved" msgid " bonus" msgstr "bonus" msgid " defeated" msgstr " fanget" msgid " will always run away from your army." msgstr " kommer alltid til Ã¥ rømme i frykt fra hæren din." msgid " will be willing to join your army." msgstr " kommer alltid til Ã¥ ønske Ã¥ bli med i hæren din." #, fuzzy msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "\"%{artifact}\" vil bli brakt med videre til det neste kartet." #, fuzzy msgid "The army will be carried over in the campaign." msgstr "Disse styrkene vil komme til deg ved et senere kart." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" "Kongedømmet ditt vil fÃ¥ %{count} ekstra %{resource} ved oppstarten av kartet." #, fuzzy msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "Trolldommen %{spell} vil bli brakt med videre til det neste kartet." #, fuzzy msgid "%{hero} can be hired during scenarios." msgstr "Helten %{hero} kan bli vervet pÃ¥ kartet." #, fuzzy msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" "Helten %{hero} vil ikke komme i senere kart dersom han/hun har blitt fanget." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Dvergene kjenner igjen sine allierte og slÃ¥r seg med glede sammen med " "styrkene dine." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Jettene gjenkjenner deg som Dvergebanen og tumler seg tungt bort til deg for " "Ã¥ slÃ¥ seg til din armé." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Dragene, mens de ser pÃ¥ deg og knurrer og snerrer, godtar Ã¥ slÃ¥ seg sammen " "med deg, deres \"allierte\"." #, fuzzy msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Idet du gÃ¥r mot en gruppe alver kommanderer lederen dem alle til Ã¥ stÃ¥ i " "givakt. Han roper til dem, \"Hvem av dere er tapre nok til Ã¥ slÃ¥ dere sammen " "med vÃ¥r fryktløse allierte?\". Gruppen bryter ut i jubel mens alle løper " "bort for Ã¥ slutte seg til styrken din." #, fuzzy msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Dvergene hilser deg, \"En venn av Roland er en venn av oss. Du kan fÃ¥ gÃ¥ " "forbi.\"." msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Jettene gir fra seg et grynt av annerkjennelse, \"Archibald sine allierte " "skal fÃ¥ slippe forbi.\"." #, fuzzy msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Dragene ser deg og roper ut: \"VÃ¥r allianse med Archibald tvinger oss til Ã¥ " "bli med deg. Uheldigvis har du ikke plass. Det var synd!\" De drar raskt av " "gÃ¥rde." #, fuzzy msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Alvene stÃ¥r i givakt idet du kommer nærmere. Lederen deres roper pÃ¥ deg og " "sier: \"La oss ikke komme i veien for deg, vÃ¥r allierte! Dra nÃ¥ videre, og " "mÃ¥tte seieren bli din.\"." msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Dvergebanen!!!! Flykt for livene deres!\"" msgid "campaignBonus|Animate Dead" msgstr "Dødebesjelning" msgid "campaignBonus|Chain Lightning" msgstr "Kjedelyn" msgid "campaignBonus|Fireblast" msgstr "Ildblest" msgid "campaignBonus|Mass Curse" msgstr "Masseforbannelse" msgid "campaignBonus|Mass Haste" msgstr "Full hast" msgid "campaignBonus|Mirror Image" msgstr "Speilbilde" msgid "campaignBonus|Resurrect" msgstr "Gjenreising" msgid "campaignBonus|Steelskin" msgstr "StÃ¥lhud" msgid "campaignBonus|Summon Earth" msgstr "Tilkall jordÃ¥nd" msgid "campaignBonus|View Heroes" msgstr "Vis helter" msgid "campaignBonus|Ballista" msgstr "Hurtigballisten" msgid "campaignBonus|Black Pearl" msgstr "Den sorte perlen" msgid "campaignBonus|Caster's Bracelet" msgstr "FortryllerarmbÃ¥nd" msgid "campaignBonus|Defender Helm" msgstr "Forsvarerhjelmen" msgid "campaignBonus|Breastplate" msgstr "Brystplate" msgid "campaignBonus|Dragon Sword" msgstr "Dragesverdet" msgid "campaignBonus|Fizbin Medal" msgstr "Fizbinmedaljen" msgid "campaignBonus|Foremost Scroll" msgstr "Yprst. kunskpsrull" msgid "campaignBonus|Gauntlets" msgstr "Panserhansker" msgid "campaignBonus|Hideous Mask" msgstr "Avskyelig maske" msgid "campaignBonus|Mage's Ring" msgstr "Magikerens ring" msgid "campaignBonus|Major Scroll" msgstr "Str. kunskpsrull" msgid "campaignBonus|Medal of Honor" msgstr "Æresmedaljen" msgid "campaignBonus|Medal of Valor" msgstr "Heltemotmedaljen" msgid "campaignBonus|Minor Scroll" msgstr "Mindre skriftrull" msgid "campaignBonus|Nomad Boots" msgstr "Nomadens sko" msgid "campaignBonus|Power Axe" msgstr "Styrkeøksa" msgid "campaignBonus|Spiked Shield" msgstr "Piggskjoldet" msgid "campaignBonus|Stealth Shield" msgstr "Snikeskjoldet" msgid "campaignBonus|Tax Lien" msgstr "Skattepant" msgid "campaignBonus|Thunder Mace" msgstr "Tordenklubben" msgid "campaignBonus|Traveler's Boots" msgstr "Vandrerens sko" msgid "campaignBonus|White Pearl" msgstr "Den hvite perlen" msgid "campaignBonus|Basic Archery" msgstr "Enkel skyting" msgid "campaignBonus|Advanced Archery" msgstr "Forbedret skyting" msgid "campaignBonus|Expert Archery" msgstr "Ekspert skyting" msgid "campaignBonus|Basic Ballistics" msgstr "Enkel ballistikk" msgid "campaignBonus|Advanced Ballistics" msgstr "Forbedret ballistikk" msgid "campaignBonus|Expert Ballistics" msgstr "Ekspert ballistikk" msgid "campaignBonus|Basic Diplomacy" msgstr "Enkel megling" msgid "campaignBonus|Advanced Diplomacy" msgstr "Forbedret megling" msgid "campaignBonus|Expert Diplomacy" msgstr "Ekspert megling" msgid "campaignBonus|Basic Eagle Eye" msgstr "Enkelt ørneblikk" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Forbedret ørneblikk" msgid "campaignBonus|Expert Eagle Eye" msgstr "Ekspert ørneblikk" msgid "campaignBonus|Basic Estates" msgstr "Enkel investering" msgid "campaignBonus|Advanced Estates" msgstr "Forbedret investering" msgid "campaignBonus|Expert Estates" msgstr "Ekspert investering" msgid "campaignBonus|Basic Leadership" msgstr "Enkelt lederskap" msgid "campaignBonus|Advanced Leadership" msgstr "Forbedret lederskap" msgid "campaignBonus|Expert Leadership" msgstr "Ekspert lederskap" msgid "campaignBonus|Basic Logistics" msgstr "Enkel logistikk" msgid "campaignBonus|Advanced Logistics" msgstr "Forbedret logistikk" msgid "campaignBonus|Expert Logistics" msgstr "Ekspert logistikk" msgid "campaignBonus|Basic Luck" msgstr "Enkel flaks" msgid "campaignBonus|Advanced Luck" msgstr "Forbedret flaks" msgid "campaignBonus|Expert Luck" msgstr "Ekspert flaks" msgid "campaignBonus|Basic Mysticism" msgstr "Enkel mystikk" msgid "campaignBonus|Advanced Mysticism" msgstr "Forbedret mystikk" msgid "campaignBonus|Expert Mysticism" msgstr "Ekspert mystikk" msgid "campaignBonus|Basic Navigation" msgstr "Enkel skipsfart" msgid "campaignBonus|Advanced Navigation" msgstr "Forbedret skipsfart" msgid "campaignBonus|Expert Navigation" msgstr "Ekspert skipsfart" msgid "campaignBonus|Basic Necromancy" msgstr "Enkel sortekunst" msgid "campaignBonus|Advanced Necromancy" msgstr "Forbedret sortekunst" msgid "campaignBonus|Expert Necromancy" msgstr "Ekspert sortekunst" msgid "campaignBonus|Basic Pathfinding" msgstr "Enkel kartlesing" msgid "campaignBonus|Advanced Pathfinding" msgstr "Forbedret kartlesing" msgid "campaignBonus|Expert Pathfinding" msgstr "Ekspert kartlesing" msgid "campaignBonus|Basic Scouting" msgstr "Enkel speiding" msgid "campaignBonus|Advanced Scouting" msgstr "Forbedret speiding" msgid "campaignBonus|Expert Scouting" msgstr "Ekspert speiding" msgid "campaignBonus|Basic Wisdom" msgstr "Enkel visdom" msgid "campaignBonus|Advanced Wisdom" msgstr "Forbedret visdom" msgid "campaignBonus|Expert Wisdom" msgstr "Ekspert visdom" #, fuzzy msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "Hovedhelten din vil begynne kartet med %{artifact} i sin besittelse." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "Kongedømmet ditt vil begynne kartet med %{amount} ekstra %{resource}." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Kongedømmet ditt vil fÃ¥ %{amount} mindre %{resource} ved oppstarten av " "kartet." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Hovedhelten din vil begynne kartet med %{count} %{monster}." #, fuzzy msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" "Hovedhelten din vil begynne kartet med trolldommen\n" "%{spell}." #, fuzzy msgid "The starting alignment of the scenario will be %{race}." msgstr "Begynn kartet med helteslaget %{race}." #, fuzzy msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "Hovedhelten din vil begynne kartet med %{count} ekstrapoeng i %{skill}." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Hovedhelten din vil begynne kartet med ferdigheten %{skill}." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" #, fuzzy msgid "Price of Loyalty" msgstr "Prisen for trofasthet" msgid "Voyage Home" msgstr "Ferden hjem" msgid "Wizard's Isle" msgstr "Magimestrenes øy" msgid "Descendants" msgstr "Etterkommerene" msgid "Cannot build. You have already built here today." msgstr "Kan ikke bygges. Det har allerede blitt bygd her denne runden." msgid "For this action it is necessary to build a castle first." msgstr "For Ã¥ utføre denne handlingen mÃ¥ man bygge en borg først." msgid "The %{building} produces %{monster}." msgstr "%{building} gjør det mulig Ã¥ verve %{monster}." msgid "Requires:" msgstr "Trenger:" msgid "Exit this menu without doing anything." msgstr "Forlat menyen uten Ã¥ gjøre endringer." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Borgen er for langt unna vann til Ã¥ bygge %{name}." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Du har ikke rÃ¥d til %{name}." #, fuzzy msgid "The %{name} is already built." msgstr "%{name} har allerede blitt bygd." #, fuzzy msgid "Cannot build the %{name}." msgstr "Det kan ikke bygges %{name}." msgid "Build %{name}." msgstr "Bygg %{name}." msgid "Blackridge" msgstr "Svartfjellryggen" msgid "Hillstone" msgstr "Vollsten" msgid "Pinehurst" msgstr "Furuskogen" msgid "Whiteshield" msgstr "Hvitskjold" msgid "Woodhaven" msgstr "Skogheimen" msgid "Blackwind" msgstr "Sortevind" msgid "Bloodreign" msgstr "Bloddømme" msgid "Dragontooth" msgstr "Dragetann" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "" #, fuzzy msgid "Fountainhead" msgstr "Fontene" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" msgid "Sandcaster" msgstr "Sandeborg" msgid "Alamar" msgstr "Alamar" #, fuzzy msgid "Burlock" msgstr "Trollmann" msgid "Dragadune" msgstr "Drakendyn" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" msgid "Blackfang" msgstr "Svarttann" msgid "New Dawn" msgstr "Nygry" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" #, fuzzy msgid "Antioch" msgstr "Advarsel" #, fuzzy msgid "Avalon" msgstr "Halon" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" #, fuzzy msgid "Weed Patch" msgstr "Gulluret" msgid "Brownston" msgstr "Brunnbygd" msgid "Hilltop" msgstr "Bakketopp" msgid "Weddington" msgstr "" msgid "Westfork" msgstr "" #, fuzzy msgid "Whittingham" msgstr "Skribent" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "" msgid "Roscomon" msgstr "" #, fuzzy msgid "Sherman" msgstr "Tysk" msgid "Yorksford" msgstr "" #, fuzzy msgid "Blackburn" msgstr "Svartdrage" #, fuzzy msgid "Blacksford" msgstr "Svart tÃ¥rn" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "" msgid "Lankershire" msgstr "Slankersyssel" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "Tømmertopp" #, fuzzy msgid "Troy" msgstr "Trojann" #, fuzzy msgid "Forder Oaks" msgstr "Grensebyene" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "" msgid "Willow" msgstr "Vierlund" msgid "Corackston" msgstr "" msgid "Sheltemburg" msgstr "" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Det kan ikke verves en helt. Det befinner seg alt én i byen." msgid "Cannot recruit - you have too many Heroes." msgstr "Kan ikke verves - du har for mange helter." #, fuzzy msgid "Cannot afford a Hero." msgstr "Ikke rÃ¥d til helt" msgid "There is no room in the garrison for this army." msgstr "Det er ikke plass i garnisonen for denne styrken." # Forskansing eller festningsanlegg msgid "Fortifications" msgstr "Befestninger" msgid "Farm" msgstr "Ã…ker" msgid "Thatched Hut" msgstr "StrÃ¥tekt hytte" msgid "Archery Range" msgstr "Skytebane" msgid "Upg. Archery Range" msgstr "Oppg. skytebane" msgid "Blacksmith" msgstr "Smed" msgid "Upg. Blacksmith" msgstr "Oppg. smed" msgid "Armory" msgstr "Rustkammer" msgid "Upg. Armory" msgstr "Oppg. rustkammer" msgid "Jousting Arena" msgstr "Ridderbane" msgid "Upg. Jousting Arena" msgstr "Oppg. ridderbane" msgid "Cathedral" msgstr "Domkirke" msgid "Upg. Cathedral" msgstr "Oppg. domkirke" msgid "Coliseum" msgstr "Amfiteater" msgid "Garbage Heap" msgstr "Skrothaug" msgid "Hut" msgstr "Hytte" msgid "Stick Hut" msgstr "Kvisthytte" msgid "Upg. Stick Hut" msgstr "Oppg. kvisthytte" msgid "Den" msgstr "Hi" msgid "Adobe" msgstr "Leirhus" msgid "Upg. Adobe" msgstr "Oppg. leirhus" msgid "Bridge" msgstr "Bru" msgid "Upg. Bridge" msgstr "Oppg. bru" msgid "Pyramid" msgstr "Pyramide" msgid "Rainbow" msgstr "Regnbue" msgid "Crystal Garden" msgstr "Krystallhage" msgid "Treehouse" msgstr "Trehytte" msgid "Cottage" msgstr "Stue" msgid "Upg. Cottage" msgstr "Oppg. stue" msgid "Stonehenge" msgstr "Steinring" msgid "Upg. Stonehenge" msgstr "Oppg. steinring" # hesteslette heller enn hesteeng. Enkelte sprÃ¥k bruker plen. msgid "Fenced Meadow" msgstr "Inngjerdet slette" msgid "sorceress|Red Tower" msgstr "IldtÃ¥rn" msgid "Dungeon" msgstr "Skattehvelv" msgid "Waterfall" msgstr "Foss" msgid "Cave" msgstr "Hule" msgid "Crypt" msgstr "Gravkammer" msgid "Nest" msgstr "Rede" msgid "Maze" msgstr "Labyrint" msgid "Upg. Maze" msgstr "Oppg. labyrint" msgid "Swamp" msgstr "Myr" msgid "Green Tower" msgstr "Grønt tÃ¥rn" msgid "warlock|Red Tower" msgstr "Rødt tÃ¥rn" msgid "Black Tower" msgstr "Svart tÃ¥rn" msgid "Library" msgstr "Bibliotek" msgid "Orchard" msgstr "Frukthage" msgid "Habitat" msgstr "Hjemsted" msgid "Pen" msgstr "Binge" msgid "Foundry" msgstr "Støperi" msgid "Upg. Foundry" msgstr "Oppg. støperi" msgid "Cliff Nest" msgstr "Klipperede" msgid "Ivory Tower" msgstr "ElfenbenstÃ¥rn" msgid "Upg. Ivory Tower" msgstr "Oppg. elfenbenstÃ¥rn" msgid "Cloud Castle" msgstr "Himmelslott" msgid "Upg. Cloud Castle" msgstr "Oppg. himmelslott" msgid "Storm" msgstr "Storm" msgid "Skull Pile" msgstr "Beinhaug" msgid "Excavation" msgstr "Utgravninger" msgid "Graveyard" msgstr "Gravplass" msgid "Upg. Graveyard" msgstr "Oppg. gravplass" msgid "Upg. Pyramid" msgstr "Oppg. pyramide" # Evt herskapshus msgid "Mansion" msgstr "HerregÃ¥rd" msgid "Upg. Mansion" msgstr "Oppg. herregÃ¥rd" msgid "Mausoleum" msgstr "Kongegrav" msgid "Upg. Mausoleum" msgstr "Oppg. kongegrav" msgid "Laboratory" msgstr "Laboratorium" # Sortekunstnerens by. Offerplass? Offeralter? Tempel? Helligdom? msgid "Shrine" msgstr "Mørkets alter" #, fuzzy msgid "Special" msgstr "Ingenting spesielt" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Halvinger" #, fuzzy msgid "Dwelling 2" msgstr "Halvinger" #, fuzzy msgid "Upg. Dwelling 2" msgstr "Halvinger" #, fuzzy msgid "Dwelling 3" msgstr "Halvinger" #, fuzzy msgid "Upg. Dwelling 3" msgstr "Halvinger" #, fuzzy msgid "Dwelling 4" msgstr "Halvinger" #, fuzzy msgid "Upg. Dwelling 4" msgstr "Halvinger" #, fuzzy msgid "Dwelling 5" msgstr "Halvinger" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Halvinger" #, fuzzy msgid "Dwelling 6" msgstr "Halvinger" #, fuzzy msgid "Upg. Dwelling 6" msgstr "Halvinger" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Befestningene styrker ringmuren til borgen slik at det mÃ¥ flere treff til " "for Ã¥ rive den ned." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Ã…keren øker veksten av bønder med %{count} i uka." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Amfiteateret oppildner de forsvarende styrkene slik at kampÃ¥nden deres " "stiger med to." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Skrothaugen øker veksten av vetter med %{count} i uka." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Regnbuen øker flaksen til de forsvarende styrkene med to." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "Krystallhagen øker veksten av feer med %{count} i uka." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "" "Skattehvelvet øker den daglige inntekten til byen med %{count} gullstykker." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Fossen øker veksten av kentaurer med %{count} i uka." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Biblioteket øker antall trolldommer hos Magikerlauget med én for hver level." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Frukthagen øker veksten av halvinger med %{count} i uka." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "Stormen legger til +2 pÃ¥ kraften til en forsvarende trolldomsbruker." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Beinhaugen øker veksten av skjeletter med %{count} i uka." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Brønnen øker den ukentlige veksten til alle borgens bosteder med %{count} " "krigere. Hvis du besøker den kan du fÃ¥ en oversikt over alle de forskjellige " "krigerne i borgen i tillegg til at du kan verve dem derfra." msgid "Thieves' Guild" msgstr "Tyvenes laug" msgid "Tavern" msgstr "Vertshus" msgid "Shipyard" msgstr "Skipsverft" msgid "Well" msgstr "Brønn" msgid "Statue" msgstr "Statue" msgid "Marketplace" msgstr "Markedsplass" msgid "Moat" msgstr "Vollgrav" msgid "Castle" msgstr "Borg" msgid "Tent" msgstr "Telt" msgid "Captain's Quarters" msgstr "Kapteinens kvarter" # Første nivÃ¥ uten forkortelse ser bÃ¥de bedre ut og gjør at man vet hva forkortelsen er for senere uten Ã¥ mÃ¥tte # høyre klikke osv. msgid "Mage Guild, Level 1" msgstr "Magikerlaug" # nivÃ¥ eller level? etasje? msgid "Mage Guild, Level 2" msgstr "Magikerlaug, level 2" msgid "Mage Guild, Level 3" msgstr "Magikerlaug, level 3" msgid "Mage Guild, Level 4" msgstr "Magikerlaug, level 4" msgid "Mage Guild, Level 5" msgstr "Magikerlaug, level 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Mørkets alter forbedrer sortekunstevnen til heltene dine med 10 prosent." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Tyvenes laug skaffer informasjon om motstanderspillerne og borgene deres. Jo " "flere tyvelaug du eier, desto mer informasjon fÃ¥r du om de andre spillerne." msgid "The Tavern increases morale for troops defending the castle." msgstr "Vertshuset styrker kampÃ¥nden til krigerne som forsvarer borgen." msgid "The Shipyard allows ships to be built." msgstr "Skipsverftet lar deg bygge skip." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Brønnen øker den ukentlige veksten til alle borgens bosteder med %{count} " "krigere. Hvis du besøker den kan du fÃ¥ en oversikt over alle de forskjellige " "krigerne i borgen i tillegg til at du kan verve dem derfra." #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Statuen øker den daglige inntekten til byen med %{count} gullstykker." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "Det venstre tÃ¥rnet tilfører ekstra ildstyrke under beleiring av borgen." msgid "The Right Turret provides extra firepower during castle combat." msgstr "Det høyre tÃ¥rnet tilfører ekstra ildstyrke under beleiring av borgen." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "PÃ¥ markedsplassen kan man bytte én type rÃ¥vare mot en annen. Jo flere " "markedsplasser du eier, desto bedre vekslingskurs fÃ¥r du." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Vollgraven forsinker angripende styrker. Alle styrker som havner i " "vollgraven mÃ¥ avslutte turen sin der og i tillegg tar de mer skade fra " "angrep sÃ¥ lenge de befinner seg i den." #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Borgen forsterker byens beskyttelse og øker den daglige inntekten du fÃ¥r fra " "byen til %{count} gullstykker." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Teltet skaffer arbeidere til Ã¥ bygge en borg, gitt at rÃ¥varene og gullet er " "pÃ¥ plass." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Kapteinens kvarter huser en kaptein som vil forsvare borgen dersom ingen " "helt er til stede." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Hos Magikerlauget kan heltene dine lære seg trolldommer og fÃ¥ fylt opp " "magipoengene sine." msgid "Recruit %{name}" msgstr "Verv %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "MÃ¥ned: %{month}, Uke : %{week}, Dag : %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Du mÃ¥ kjøpe en tryllebok for Ã¥ bruke Magikerforbundet, men du har ikke plass " "til en tryllebok nÃ¥. Prøv Ã¥ gi en av dine skatter til en annen helt." msgid "Click to show next town." msgstr "Klikk for Ã¥ vise neste by." msgid "Show next town" msgstr "Vis neste by" msgid "Click to show previous town." msgstr "Klikk for Ã¥ vise forrige by." msgid "Show previous town" msgstr "Vis forrige by" msgid "This town may not be upgraded to a castle." msgstr "Denne byen kan ikke oppgraderes til borg." msgid "Town" msgstr "By" msgid "Exit Castle" msgstr "Forlat borgen" msgid "Exit Town" msgstr "Forlat byen" msgid "Show Income" msgstr "Vis inntekt" msgid "View Hero" msgstr "Vis helt" msgid "The above spells are available here." msgstr "Trolldommene ovenfor er tilgjengelige her." #, fuzzy msgid "The spells the hero can learn have been added to their book." msgstr "Med nok visdom kan du lære deg trolldommene over." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Et sjenerøst tips til bartenderen fÃ¥r han til Ã¥ dele dette ryktet:" msgid "Recruit Hero" msgstr "Verv en helt" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} er en level %{value} %{race} " msgid "with %{count} artifacts." msgstr "med %{count} skatter." msgid "with 1 artifact." msgstr "med 1 skatt." msgid "without artifacts." msgstr "uten skatter." msgid "Recruit %{name} the %{race}" msgstr "Verv %{race}en %{name}" #, fuzzy msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "\"Spredd\" kampoppstilling sprer styrkene dine fra topp til bunn av " "slagmarken med minst ett ledig felt mellom hver enkelt tropp." #, fuzzy msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "\"Gruppert\" kampoppstilling setter styrkene dine tett sammen i midten av " "din side av slagmarken." msgid "Spread Formation" msgstr "Spredd oppstilling" msgid "Grouped Formation" msgstr "Gruppert oppstilling" #, fuzzy msgid "Click to show the next town." msgstr "Klikk for Ã¥ vise neste by." #, fuzzy msgid "Click to show the previous town." msgstr "Klikk for Ã¥ vise forrige by." msgid "Set garrison combat formation to 'Spread'" msgstr "Sett kampoppstillingen til garnisonen til \"Spredd\"." msgid "Set garrison combat formation to 'Grouped'" msgstr "Sett kampoppstillingen til garnisonen til \"Gruppert\"." msgid "Exit Castle Options" msgstr "Forlat borgvalg" msgid "Castle Options" msgstr "Borgvalg" msgid "Not enough resources to recruit creatures." msgstr "Ikke nok rÃ¥varer til Ã¥ verve krigere." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Du kan ikke verve noen fordi hæren din har ikke plass." msgid "No creatures available for purchase." msgstr "Ingen krigere tilgjengelige for verving." msgid "Recruit Creatures" msgstr "Verv krigere" msgid "Hire all creatures in the town." msgstr "Verv alle krigerene som er tilgjengelige i byen." msgid "Max" msgstr "Maks" msgid "Available" msgstr "Tilgjengelig" msgid "Town Population Information and Statistics" msgstr "Info og tall om byens bosteder" msgid "Damage" msgstr "Skade" msgid "HP" msgstr "Liv" msgid "Growth" msgstr "Vekst" msgid "week" msgstr "uke" msgid "View World" msgstr "Vis verden" msgid "View the entire world." msgstr "Vis hele verdenen." msgid "Puzzle" msgstr "Puslekart" msgid "View the obelisk puzzle." msgstr "Vis obeliskenes puslekart." msgid "Scenario Information" msgstr "Kartbeskrivelse" msgid "View information on the scenario you are currently playing." msgstr "Vis beskrivelsen av kartet du spiller akkurat nÃ¥." msgid "Dig for the Ultimate Artifact." msgstr "Grav etter den sjeldneste skatten." msgid "Digging" msgstr "Graving" msgid "Arena" msgstr "Arena" #, fuzzy msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Du gÃ¥r inn i arenaen og finner deg selv ansikt til ansikt med en flokk " "blodtørstige løver. Du tar lett hÃ¥nd om dem og publikum jubler. En gammel " "gladiatormester ble sÃ¥ imponert av deg at han gÃ¥r med pÃ¥ Ã¥ trene deg opp i " "én ferdighet etter ditt ønske." msgid "Attack Skill" msgstr "Angrep" msgid "Defense Skill" msgstr "Forsvar" msgid "Shots" msgstr "Skudd" msgid "Shots Left" msgstr "Skudd igjen" msgid "Hit Points" msgstr "Liv" msgid "Hit Points Left" msgstr "Liv igjen" msgid "You can't afford to upgrade your troops!" msgstr "Du har ikke rÃ¥d til Ã¥ oppgradere troppene dine!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Krigerne dine kan oppgraderes, men det vil koste deg dyrt. Ønsker du Ã¥ " "oppgradere dem likevel?" # Avskjedige msgid "Are you sure you want to dismiss this army?" msgstr "Er du sikker pÃ¥ at du vil bortvise denne troppen?" msgid "Upgrade" msgstr "Oppgrader" msgid "Upgrade your troops." msgstr "Oppgrader troppene dine." msgid "Dismiss" msgstr "Bortvis" msgid "Dismiss this army." msgstr "Bortvis denne troppen." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "En gruppe %{monster} med en drøm om heder og ære ønsker Ã¥ bli med deg.\n" "Godtar du?" msgid "Followers" msgstr "Følgere" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "En enkelt %{monster} lar seg overtale av dine meglingsevner, og den tilbyr " "deg Ã¥ bli med i hæren din mot en pris pÃ¥ %{gold} gullstykker.\n" "Godtar du?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Krigerne lar seg overtale takket være dine formidable meglingsevner, og de " "gir deg følgende tilbud:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} av %{total} av gruppen med %{monster} vil slutte seg til hæren din, " "mens resten vil la deg gÃ¥ uforstyrret videre i bytte mot %{gold} " "gullstykker.\n" "Godtar du?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Hele hærstyrken pÃ¥ %{offer} %{monster} vil slutte seg til hæren din i bytte " "mot %{gold} gullstykker.\n" "Godtar du?" msgid "(Rate: %{percent})" msgstr "(Grad: %{percent})" msgid "off" msgstr "av" msgid "Music" msgstr "Musikk" msgid "Effects" msgstr "Lydeffekter" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Expansion" msgid "External" msgstr "Ekstern" msgid "Music Type" msgstr "Musikktype" msgid "3D Audio" msgstr "3D-lyd" msgid "Toggle ambient music level." msgstr "Juster volumet til musikken." msgid "Toggle foreground sounds level." msgstr "Juster volumet til lydeffekter og videosnutter." msgid "Change the type of music." msgstr "Skift typen musikk." #, fuzzy msgid "Toggle the 3D effect of foreground sounds." msgstr "Skru 3D-effekten av bakgrunnslyder pÃ¥ eller av." msgid "Build a new ship:" msgstr "Bygg et nytt skip:" msgid "Resource cost:" msgstr "Pris i rÃ¥varer:" msgid "Total: " msgstr "Totalt: " msgid "Need: " msgstr "Trenger: " msgid "New Game" msgstr "Nytt parti" msgid "Start a single or multi-player game." msgstr "Start et enkelt- eller flerspillerparti." msgid "Load Game" msgstr "Last inn et parti" msgid "Load a previously saved game." msgstr "Last inn et tidligere lagret parti." msgid "Save Game" msgstr "Lagre spill" msgid "Save the current game." msgstr "Lagre det nÃ¥værende spillet." msgid "Quit" msgstr "Avslutt" msgid "Quit out of Heroes of Might and Magic II." msgstr "Forlat Heroes of Might and Magic II." msgid "Language" msgstr "SprÃ¥k" msgid "Graphics" msgstr "Bilde" msgid "Black & White" msgstr "Svart-hvit" msgid "Mouse Cursor" msgstr "Markør" msgid "Color" msgstr "Farget" msgid "Text Support" msgstr "Tekstmodus" msgid "Change the language of the game." msgstr "Endre sprÃ¥ket til spillet." msgid "Select Game Language" msgstr "Velg spillsprÃ¥k" msgid "Change the graphics settings of the game." msgstr "Endre bildeinnstillingene til spillet." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Skru farget markør av eller pÃ¥. Dette er kun et estetisk valg." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Skru pÃ¥ tekstmodus for Ã¥ gi tekstbasert informasjon om vinduer og hendelser " "som skjer i spillet." msgid "" "Map\n" "Difficulty" msgstr "" "Kartets\n" "utfordring" msgid "" "Game\n" "Difficulty" msgstr "" "Spillets\n" "utfordring" msgid "Rating" msgstr "Utbytte" msgid "Map Size" msgstr "" "Kartets\n" "størrelse" # Evt Spillere # Motspillere og motstandere høres ut som dine egne motspillere og motstandere. Evt Konkurrenter men # det høres feil setting ut. Motspillere osv passer dÃ¥rlig nÃ¥r du har allierte blant dem. msgid "Opponents" msgstr "Deltakere" # Slag? Type? Klasse er feil. msgid "Class" msgstr "Helteslag" msgid "" "Victory\n" "Conditions" msgstr "" "Seiers-\n" "vilkÃ¥r" msgid "" "Loss\n" "Conditions" msgstr "" "Taps-\n" "vilkÃ¥r" msgid "First select recipients!" msgstr "Velg først mottakere!" msgid "You cannot select %{resource}!" msgstr "Du kan ikke velge %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Skyt pÃ¥ %{monster}" msgid "Select Recipients" msgstr "Velg mottakere" msgid "Your Funds" msgstr "Dine midler" msgid "Planned Gift" msgstr "Gis bort" msgid "Gift from %{name}" msgstr "Gave fra %{name}" msgid "Resolution" msgstr "Oppløsning" msgid "Fullscreen" msgstr "Fullskjerm" msgid "window|Mode" msgstr "Skjermmodus" msgid "Windowed" msgstr "Vindu" msgid "V-Sync" msgstr "V-synk" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Systeminfo" msgid "Change the resolution of the game." msgstr "Endre oppløsningen til spillet." msgid "Select Game Resolution" msgstr "Velg spilloppløsning" msgid "Toggle between fullscreen and windowed modes." msgstr "Velg mellom fullskjerm og vindusskjerm." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "V-synk kan bli skrudd pÃ¥ for Ã¥ potensielt løse problemer med hakkete bilde " "eller ujevn bildeflyt." msgid "Show extra information such as FPS and current time." msgstr "Vis ekstra informasjon som bilder per sekund (FPS) og tid." msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" #, fuzzy msgid "Event: " msgstr "Hendelse" msgid "Hot Keys:" msgstr "Hurtigtaster:" msgid "Hide" msgstr "Løs" msgid "Show" msgstr "Bundet" msgid "Interface" msgstr "Grensesnitt" msgid "Interface Type" msgstr "Grensesnitt" msgid "Toggle the type of interface you want to use." msgstr "Velg den typen grensesnitt du ønsker." msgid "Toggle interface visibility." msgstr "Skift synlighet for grensesnittet." msgid "Scroll Speed" msgstr "" "Panorerings-\n" "fart" msgid "Sets the speed at which you scroll the window." msgstr "Setter farten du panorerer rundt kartet pÃ¥." msgid "Select Game Language:" msgstr "Velg sprÃ¥k:" #, fuzzy msgid "Select Language:" msgstr "Velg sprÃ¥k:" msgid "Click to choose the selected language." msgstr "Trykk for Ã¥ velge et sprÃ¥k." msgid "%{name} has gained a level." msgstr "%{name} gikk opp en level." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Du har lært %{skill}." #, fuzzy msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "%{name} gikk opp en level." #, fuzzy msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "Du kan velge mellom Ã¥ lære:" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/a" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Ta en titt pÃ¥ vÃ¥re utmerkede varer. Hvis du ønsker Ã¥ gi et tilbud, klikker " "du pÃ¥ rÃ¥varene du ønsker Ã¥ bytte mellom." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Du fikk en veldig god pris! Jeg forventer ikke Ã¥ gÃ¥ i pluss pÃ¥ dette. Er du " "interessert i noen av de andre varene mine?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Jeg kan tilby deg %{count} gullstykker for 1 enhet %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Jeg kan tilby deg 1 enhet %{resto} mot %{count} enheter %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Ant. Ã¥ bytte" msgid "Trading Post" msgstr "Handelssted" msgid "Your Resources" msgstr "Dine rÃ¥varer" msgid "Available Trades" msgstr "Mulige bytter" msgid "guarded by %{count} %{monster}" msgstr "bevoktet av %{count} %{monster}" msgid "guarded by " msgstr "Bevoktet av " msgid "(available: %{count})" msgstr "(tilgjengelig: %{count})" msgid "(empty)" msgstr "(tom)" msgid "already learned" msgstr "allerede lært" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Kunnskapstre" #, fuzzy msgid "already claimed" msgstr "allerede lært" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "kan allerede denne ferdigheten" msgid "already has max skills" msgstr "har allerede fullt med evner" msgid "(already visited)" msgstr "(allerede besøkt)" msgid "(not visited)" msgstr "(ikke besøkt)" msgid "%{color} Barrier" msgstr "%{color} barriere" #, fuzzy msgid "(tent visited)" msgstr "(ikke besøkt)" msgid "%{color} Tent" msgstr "%{color} telt" msgid "Road" msgstr "Vei" msgid "(digging ok)" msgstr "(Graving mulig)" msgid "(no digging)" msgstr "(Ingen graving)" msgid "penalty: %{cost}" msgstr "Tap av skritt: %{cost}" msgid "Defenders:" msgstr "Forsvarere:" msgid "Unknown" msgstr "Uvisst" msgid "heroQuickInfo|(Level %{level})" msgstr "(Level %{level})" msgid "Attack:" msgstr "Angrep:" msgid "Defense:" msgstr "Forsvar:" msgid "Spell Power:" msgstr "Kraft:" msgid "Knowledge:" msgstr "Kunnskap:" msgid "Spell Points:" msgstr "Magipoeng:" msgid "Move Points:" msgstr "Skritt:" msgid "Uncharted Territory" msgstr "Ikke kartlagt omrÃ¥de" msgid "Cost per troop:" msgstr "Pris per kriger:" msgid "Available: %{count}" msgstr "Tilgjengelig: %{count}" msgid "Number to buy:" msgstr "Antall valgt:" msgid "Recruit selected monsters." msgstr "Verv det utvalgte antall krigere." msgid "Select maximum monsters to be recruited." msgstr "Velg maksimalt antall vervbare krigere." msgid "Select only 1 monster to be recruited." msgstr "Velg kun én kriger til Ã¥ verves." #, fuzzy msgid "Select this game resolution." msgstr "Velg spilloppløsning" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Velg en oppløsning:" msgid "Click to apply the selected resolution." msgstr "Trykk for Ã¥ bruke den valgte oppløsningen." msgid "Click to apply the entered text." msgstr "Trykk for Ã¥ bekrefte den innskrevne teksten." msgid "Click to open the Virtual Keyboard dialog." msgstr "Trykk for Ã¥ Ã¥pne skjermtastaturet." msgid "Open Virtual Keyboard" msgstr "Ã…pne skjermtastatur" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "Flytt hvor mange styrker?" #, fuzzy msgid "Select how many units to separate into:" msgstr "Velg by Ã¥ reise til." msgid "Map: " msgstr "Kart: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "MÃ¥ned: " msgid ", Week: " msgstr ", uke: " msgid ", Day: " msgstr ", dag: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Plassering: " msgid "Are you sure you want to delete file:" msgstr "Er du sikker pÃ¥ at du vil slette filen:" msgid "Warning" msgstr "Advarsel" msgid "Click to save the current game." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Click to load a previously saved game." msgstr "Klikk for Ã¥ laste inn et tidligere lagret spill." msgid "File to Save:" msgstr "Lagringsfil:" msgid "File to Load:" msgstr "Lastingsfil:" #, fuzzy msgid "Terrain object" msgstr "Terrengmodus" msgid "Accept the choice made." msgstr "Bekreft valget og gÃ¥ videre." msgid "Select Skill:" msgstr "Velg ferdighet:" msgid "Select Spell:" msgstr "Velg trolldom:" msgid "Select Artifact:" msgstr "Velg en skatt:" msgid "Select Monster:" msgstr "Velg monster:" msgid "Select Hero:" msgstr "Velg helt:" msgid "race|Random" msgstr "Tilfeldig" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Trykk for Ã¥ bruke den valgte oppløsningen." #, fuzzy msgid "%{color} %{race}" msgstr "%{color} spiller" msgid "You will place" msgstr "" #, fuzzy msgid "Click to select this class." msgstr "Klikk her for Ã¥ velge hvilket kart du vil spille." #, fuzzy msgid "Click to select this color." msgstr "Klikk her for Ã¥ velge hvilket kart du vil spille." #, fuzzy msgid "Select Treasure:" msgstr "Velg helt:" #, fuzzy msgid "Select Ocean Object:" msgstr "Sjøting" #, fuzzy msgid "Castle/town placing" msgstr "Borgvalg" msgid "doubleLinedRace|Neutral" msgstr "Nøytral" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "Trykk for Ã¥ bruke den valgte oppløsningen." #, fuzzy msgid "Click to select town placing." msgstr "Klikk for Ã¥ vise neste by." #, fuzzy msgid "Click to select castle placing." msgstr "Klikk her for Ã¥ velge hvilket kart du vil spille." #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} spiller" msgid "race|Neutral" msgstr "Nøytral" #, fuzzy msgid "Select Dwelling:" msgstr "Velg trolldom:" #, fuzzy msgid "Select Landscape Object:" msgstr "Sjøting" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "RÃ¥vare" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{race}en %{name}" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "Klikk her for Ã¥ velge hvilket kart du vil spille." #, fuzzy msgid "Select Mountain Object:" msgstr "Sjøting" #, fuzzy msgid "Select Rock Object:" msgstr "Sjøting" #, fuzzy msgid "Select Tree Object:" msgstr "Sjøting" #, fuzzy msgid "Select Power Up Object:" msgstr "Sjøting" #, fuzzy msgid "Select Adventure Object:" msgstr "Sjøting" msgid "Players Icon" msgstr "Spillerikon" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Viser hvor mange spillere som totalt er med pÃ¥ kartet. Hver plass som ikke " "er tatt av et menneske vil bli tatt av en computerspiller." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Viser om kartet er\n" "smÃ¥tt (36 x 36), middels\n" "(72 x 72), stort (108 x 108)\n" "eller veldig stort (144 x 144)." msgid "Size Icon" msgstr "Størrelsesikon" msgid "Map Type" msgstr "Kart-type" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Viser om kartet er laget for spillutgaven \"Krigen om tronen\" eller " "\"Prisen for trofasthet\"." msgid "Map Type:\n" msgstr "Kart-type:\n" msgid "The Succession Wars" msgstr "Krigen om tronen" msgid "The Price of Loyalty" msgstr "Prisen for trofasthet" #, fuzzy msgid "Resurrection" msgstr "" "Gjen-\n" "opplivning" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "SprÃ¥k" msgid "Lose all your heroes and towns." msgstr "Mist alle helter og byer." msgid "Lose a specific town." msgstr "Mist en spesifikk by." msgid "Lose a specific hero." msgstr "Mist en spesifikk helt." msgid "Run out of time. Fail to win by a certain point." msgstr "GÃ¥ tom for tid. Mislykkes i Ã¥ vinne innen et spesifikt antall runder." msgid "Loss Condition" msgstr "TapsvilkÃ¥r" msgid "Defeat all enemy heroes and towns." msgstr "Beseire alle fiendtlige helter og byer." msgid "Capture a specific town." msgstr "Erobre en spesifikk by." msgid "Defeat a specific hero." msgstr "Beseire en spesifikk helt." msgid "Find a specific artifact." msgstr "Finn en spesifikk gjenstand." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "Den siden du spiller pÃ¥ mÃ¥ slÃ¥ motstandersiden." msgid "Accumulate a large amount of gold." msgstr "Samle sammen mer enn en spesifisert mengde gull." msgid "Victory Condition" msgstr "SeiersvilkÃ¥r" msgid "Map difficulty:" msgstr "Kartets utfordring:" msgid "N" msgstr "" #, fuzzy msgid "No maps exist at that size." msgstr "Det fins ingen kart i den størrelsen" msgid "Small Maps" msgstr "SmÃ¥ kart" msgid "View only maps of size small (36 x 36)." msgstr "Vis kun smÃ¥ kart (36 x 36)." msgid "Medium Maps" msgstr "Middels kart" msgid "View only maps of size medium (72 x 72)." msgstr "Vis kun middels store kart (72 x 72)." msgid "Large Maps" msgstr "Store kart" msgid "View only maps of size large (108 x 108)." msgstr "Vis kun store kart (108 x 108)." msgid "Extra Large Maps" msgstr "Ekstra store kart" msgid "View only maps of size extra large (144 x 144)." msgstr "Vis kun ekstra store kart (144 x 144)." msgid "All Maps" msgstr "Alle kart" msgid "View all maps, regardless of size." msgstr "Vis alle kart, uavhengig av størrelse." msgid "Selected Name" msgstr "Navn" msgid "The name of the currently selected map." msgstr "Navnet til det utvalgte kartet." msgid "Selected Map Difficulty" msgstr "Kartets utfordring" #, fuzzy msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Dette er utfordringen til det utvalgte kartet. Utfordringen til kartet er " "spesifisert av skaperen av kartet. De vanskeligste kartene kan inneholde " "sterkere fiender, færre rÃ¥varer, eller andre spesielle vilkÃ¥r som skal gjøre " "ting mer utfordrende for den menneskelige spilleren." msgid "Selected Description" msgstr "Kartbeskrivelse" msgid "The description of the currently selected map." msgstr "Beskrivelse av det utvalgte kartet." msgid "Jump" msgstr "Sprang" msgid "Hero Speed" msgstr "Heltefart" msgid "Don't Show" msgstr "Skjul" msgid "Enemy Speed" msgstr "Fiendefart" msgid "Auto Resolve" msgstr "Datastyrt" msgid "Auto, No Spells" msgstr "Data, ingen magi" msgid "Battles" msgstr "Kampstyring" #, fuzzy msgid "combatMode|Manual" msgstr "Manuell" msgid "Change the speed at which your heroes move on the main screen." msgstr "Juster hvor fort heltene dine flytter seg rundt pÃ¥ kartet." #, fuzzy msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Justerer hvor fort datamaskinspillere flytter seg rundt pÃ¥ kartet. Du kan " "ogsÃ¥ velge Ã¥ ikke vise hva de gjør i det hele tatt." #, fuzzy msgid "Change the interface settings of the game." msgstr "Endre bildeinnstillingene til spillet." #, fuzzy msgid "Interface Settings" msgstr "Spillinnstillinger" msgid "Toggle instant battle mode." msgstr "Skift modus for hurtigkamp." msgid "Att." msgstr "Ang." msgid "Def." msgstr "Fors." msgid "Power" msgstr "Kraft" msgid "Knowl" msgstr "Kunns" msgid "1st" msgstr "Første" msgid "2nd" msgstr "Andre" msgid "3rd" msgstr "Tredje" msgid "4th" msgstr "Fjerde" msgid "5th" msgstr "Femte" msgid "6th" msgstr "Sjette" msgid "Oracle: Player Rankings" msgstr "Orakel: Spillerrangering" msgid "Thieves' Guild: Player Rankings" msgstr "Tyvenes forbund: SpillerkÃ¥ring" msgid "Number of Towns:" msgstr "Antall byer:" msgid "Number of Castles:" msgstr "Antall borger:" msgid "Number of Heroes:" msgstr "Antall helter:" msgid "Gold in Treasury:" msgstr "Gull i statskassa:" msgid "Wood & Ore:" msgstr "Ved og malm:" msgid "Gems, Cr, Slf & Mer:" msgstr "Edelsten, Kr, Svl & Kvik:" msgid "Obelisks Found:" msgstr "Obelisker funnet:" msgid "Artifacts:" msgstr "Skatter i besittelse:" msgid "Total Army Strength:" msgstr "Samlet hærstyrke:" msgid "Income:" msgstr "Inntekt:" msgid "Best Hero:" msgstr "Beste helt:" msgid "Best Hero Stats:" msgstr "Beste helteevner:" msgid "Personality:" msgstr "Rolle:" msgid "Best Monster:" msgstr "Beste krigerslag:" #, fuzzy msgid "Random Castle Name" msgstr "VilkÃ¥rlig borg" #, fuzzy msgid "Random Town Name" msgstr "VilkÃ¥rlig by" #, fuzzy msgid "Allow Castle build" msgstr "Himmelslott" #, fuzzy msgid "Default Buildings" msgstr "Standard handling" #, fuzzy msgid "Default Army" msgstr "Standard handling" #, fuzzy msgid "Castle Army" msgstr "Borg" #, fuzzy msgid "Town Army" msgstr "By" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Mist helten kalt %{name}." msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Kamplogg" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Kamplogg" #, fuzzy msgid "Click to save the Event properties." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "RÃ¥vare" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Dag: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." #, fuzzy msgid "Add Event" msgstr "Hendelse" #, fuzzy msgid "Add an additional event." msgstr "Øvrig programmering" #, fuzzy msgid "Edit Event" msgstr "Hendelse" #, fuzzy msgid "Edit an existing event." msgstr "Last inn et eksisterende kart." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "Last inn et eksisterende kart." #, fuzzy msgid "Effects:" msgstr "Lydeffekter" #, fuzzy msgid "Conditions:" msgstr "" "Taps-\n" "vilkÃ¥r" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "Erfaringspoeng" msgid "Artifact" msgstr "Gjenstand" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Velg en skatt:" #, fuzzy msgid "Delete an artifact from the event." msgstr "Last inn et eksisterende kart." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Velg ferdighet:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Denne trolldommen kan ikke brukes pÃ¥ et skip." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Denne trolldommen kan ikke brukes pÃ¥ et skip." #, fuzzy msgid "%{objects} must be placed on water." msgstr "Denne trolldommen kan ikke brukes pÃ¥ et skip." #, fuzzy msgid "Objects cannot be placed outside the map." msgstr "Denne trolldommen kan ikke brukes pÃ¥ et skip." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Denne trolldommen kan ikke brukes pÃ¥ et skip." #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Er du sikker pÃ¥ at du ønsker Ã¥ lage et nytt kart?(Alt som er ulagret i dette " "kartet vil gÃ¥ tapt.)" msgid "Editor" msgstr "" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Er du sikker pÃ¥ at du ønsker Ã¥ laste inn et nytt kart?\n" "(Alt som er ulagret i dette kartet vil gÃ¥ tapt.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Er du sikker pÃ¥ at du ønsker Ã¥ lage et nytt kart?(Alt som er ulagret i dette " "kartet vil gÃ¥ tapt.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "OMSTART" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Er du sikker pÃ¥ at du ønsker Ã¥ lage et nytt kart?(Alt som er ulagret i dette " "kartet vil gÃ¥ tapt.)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Start pÃ¥ nytt" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Er du sikker pÃ¥ at du ønsker Ã¥ laste inn et nytt kart?\n" "(Alt som er ulagret i dette kartet vil gÃ¥ tapt.)" #, fuzzy msgid "Create a new map from scratch." msgstr "Nytt kart fra bunnen av" msgid "New Map" msgstr "Nytt kart" msgid "Load Map" msgstr "Last inn kart" msgid "Load an existing map." msgstr "Last inn et eksisterende kart." msgid "Save Map" msgstr "Lagre kart" msgid "Save the current map." msgstr "Lagre det nÃ¥værende kartet." msgid "Quit out of the map editor." msgstr "Forlat karttegneren" #, fuzzy msgid "Return to the game's Main Menu." msgstr "Klikk her for Ã¥ dra tilbake til hovedmenyen." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Tilfeldig sjeldneste skatt" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "med 1 skatt." msgid "The total number of obelisks is %{count}." msgstr "" #, fuzzy msgid "Roads" msgstr "Vei" #, fuzzy msgid "Streams" msgstr "Bekkmodus" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Denne trolldommen kan ikke brukes pÃ¥ et skip." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Lagringsfilen er korrupt." msgid "Unable to locate data directory to save the map." msgstr "" #, fuzzy msgid "Unable to create a directory to save the map." msgstr "Brukes til Ã¥ fjerne ting fra kartet." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Brukes til Ã¥ fjerne ting fra kartet." #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Er du sikker pÃ¥ at du vil overskrive lagringspunktet med dette navnet?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "Lagringsfil:" #, fuzzy msgid "Used to place %{object}." msgstr "Brukes til Ã¥ plassere en helt." #, fuzzy msgid "Select object type" msgstr "Sjøting" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Klikk her for Ã¥ velge hvilket kart du vil spille." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Vennligst velg en annen helt." msgid "" "Cell\n" "Details" msgstr "" #, fuzzy msgid "Erase" msgstr "Viskemodus" msgid "Mountains" msgstr "Fjell" #, fuzzy msgid "Rocks" msgstr "Stein" msgid "Trees" msgstr "Trær" #, fuzzy msgid "Water Objects" msgstr "Ødemarksting" #, fuzzy msgid "Miscellaneous" msgstr "Finneas" msgid "Artifacts" msgstr "Gjenstander" #, fuzzy msgid "Dwellings" msgstr "Halvinger" msgid "Mines" msgstr "Gruver" #, fuzzy msgid "Power-ups" msgstr "Kraft" msgid "Treasures" msgstr "Verdifulle gjenstander" msgid "Heroes" msgstr "Helter" msgid "Towns" msgstr "Byer" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Sjøting" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Tegner terreng innenfor en firkant med et størrelsesforhold pÃ¥\n" "%{size} ganger %{size}." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Fjerner alle ting innenfor en firkant med et størrelsesforhold pÃ¥ \n" "%{size} ganger %{size}." msgid "Small Brush" msgstr "Liten pensel" msgid "Medium Brush" msgstr "Middels pensel" msgid "Large Brush" msgstr "Stor pensel" msgid "Area Fill" msgstr "OmrÃ¥defylling" msgid "Used to click and drag for filling in large areas." msgstr "Brukes til Ã¥ fylle omrÃ¥der ved Ã¥ klikke og dra over dem." msgid "Clear Area" msgstr "Tøm omrÃ¥de" msgid "Used to click and drag for clearing large areas." msgstr "Brukes til Ã¥ tømme omrÃ¥der ved Ã¥ klikke og dra over dem." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Koster %{rate} ganger mer enn vanlig forflytning for alle helter.\n" "(Kartlesing minsker eller fjerner denne reduksjonen." msgid "Traversable only by boat." msgstr "Kan kun overfares med skip." msgid "No special modifiers." msgstr "Ingen spesielle pÃ¥virkninger." msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "Terrengmodus" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" "Brukes til Ã¥ tegne det underliggende gresset, gjørmen, vannet osv. pÃ¥ kartet." #, fuzzy msgid "Landscape Objects Mode" msgstr "Tingmodus" #, fuzzy msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Brukes til Ã¥ plassere ting (fjell, trær, verdifulle gjenstander osv.) pÃ¥ " "kartet." msgid "Detail Mode" msgstr "Detaljemodus" #, fuzzy msgid "Used for special editing of action objects." msgstr "Brukes for spesielle tilpasninger av monster, helter eller byer." #, fuzzy msgid "Adventure Objects Mode" msgstr "Kartinnstillinger" #, fuzzy msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Brukes til Ã¥ plassere ting (fjell, trær, verdifulle gjenstander osv.) pÃ¥ " "kartet." #, fuzzy msgid "Kingdom Objects Mode" msgstr "Tingmodus" #, fuzzy msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Brukes til Ã¥ plassere ting (fjell, trær, verdifulle gjenstander osv.) pÃ¥ " "kartet." #, fuzzy msgid "Monsters Mode" msgstr "Monstre" #, fuzzy msgid "Used to place monsters on the map." msgstr "" "Brukes til Ã¥ plassere\n" "en gruppe monstre." msgid "Allows you to draw streams by clicking and dragging." msgstr "Lar deg tegne bekker ved Ã¥ klikke og dra." msgid "Stream Mode" msgstr "Bekkmodus" msgid "Allows you to draw roads by clicking and dragging." msgstr "Lar deg tegne veier ved Ã¥ klikke og dra." msgid "Road Mode" msgstr "Veimodus" msgid "Erase Mode" msgstr "Viskemodus" #, fuzzy msgid "Used to erase objects from the map." msgstr "Brukes til Ã¥ fjerne ting fra kartet." msgid "Change between zoom and normal view." msgstr "Bytt mellom forstørret og normal visning." msgid "Magnify" msgstr "Forstørr" msgid "Undo" msgstr "Angre" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "Rediger kartets navn, beskrivelse eller andre detaljer." msgid "Specifications" msgstr "Spesifikasjoner" msgid "File Options" msgstr "Filvalg" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Ã…pne menyen for filvalg, hvor du kan lagre eller laste inn kart, eller " "forlate karttegneren." msgid "View the editor system options, which let you customize the editor." msgstr "Vis karttegnerens systeminnstillinger der den kan skreddersys." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" "Lag et kart som har en høyde pÃ¥ %{size} kvadrater og en bredde pÃ¥ %{size} " "kvadrater." msgid "Cancel back to the New Map menu." msgstr "Avbryt og dra tilbake til menyen for nye kart." msgid "Cancel back to the main menu." msgstr "Avbryt og dra tilbake til hovedmenyen." msgid "From Scratch" msgstr "Fra bunnen av" msgid "Start from scratch with a blank map." msgstr "Begynn pÃ¥ et kart helt fra bunn av." msgid "Create a randomly generated map." msgstr "Lag et kart automatisk." msgid "Random" msgstr "Tilfeldig" msgid "Cancel back to the Map Editor main menu." msgstr "Avbryt og dra tilbake til karttegnerens hovedmeny." msgid "No maps available!" msgstr "Ingen kart er tilgjengelige!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{color} spiller" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{name1} møter %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{color} spiller" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{color} spiller" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{name1} møter %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{name1} møter %{name2}" #, fuzzy msgid "None." msgstr "Ingen" #, fuzzy msgid "One side defeats another." msgstr "Vennligst velg en annen helt." #, fuzzy msgid "Accumulate gold." msgstr "Samle opp %{count} gullstykker." #, fuzzy msgid "Run out of time." msgstr "Forlat karttegneren" #, fuzzy msgid "alliance|1st" msgstr "allianse" #, fuzzy msgid "alliance|2nd" msgstr "allianse" #, fuzzy msgid "alliance|3rd" msgstr "allianse" #, fuzzy msgid "alliance|4th" msgstr "allianse" #, fuzzy msgid "alliance|5th" msgstr "allianse" #, fuzzy msgid "Special Loss Condition" msgstr "TapsvilkÃ¥r" #, fuzzy msgid "Special Victory Condition" msgstr "SeiersvilkÃ¥r" #, fuzzy msgid "Allow standard victory conditions" msgstr "SeiersvilkÃ¥r" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr "allianse" #, fuzzy msgid "{%number} alliance: " msgstr "allianse" #, fuzzy msgid "Gold:" msgstr "Gull" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Velg by Ã¥ reise til." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." #, fuzzy msgid "Map Difficulty" msgstr "" "Kartets\n" "utfordring" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "Plassering: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Kartbeskrivelse" #, fuzzy msgid "Click to accept the changes made." msgstr "Klikk for Ã¥ vise neste by." #, fuzzy msgid "Click to edit custom rumors." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Trykk for Ã¥ bruke den valgte oppløsningen." #, fuzzy msgid "Events" msgstr "Hendelse" #, fuzzy msgid "Click to change the language of the map." msgstr "Endre sprÃ¥ket til spillet." #, fuzzy msgid "Click to change your map name." msgstr "Klikk for Ã¥ vise neste by." #, fuzzy msgid "Map Name" msgstr "" "Kartets\n" "størrelse" #, fuzzy msgid "Click to change the description of the current map." msgstr "Beskrivelse av det utvalgte kartet." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Beskrivelse av det utvalgte kartet." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Beskrivelse av det utvalgte kartet." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Kart-type" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Dette er utfordringen til det utvalgte kartet. Utfordringen til kartet er " "spesifisert av skaperen av kartet. De vanskeligste kartene kan inneholde " "sterkere fiender, færre rÃ¥varer, eller andre spesielle vilkÃ¥r som skal gjøre " "ting mer utfordrende for den menneskelige spilleren." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Velg mengde %{resource}:" #, fuzzy msgid "Animation" msgstr "Underleggelse" #, fuzzy msgid "Passability" msgstr "Rolle:" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "Øvrig programmering" msgid "Edit Rumor" msgstr "" #, fuzzy msgid "Edit an existing rumor." msgstr "Last inn et eksisterende kart." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "Last inn et eksisterende kart." msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Plassering: " #, fuzzy msgid "Save Map:" msgstr "Lagre kart" #, fuzzy msgid "Click to save the current map." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Klikk for Ã¥ lagre det nÃ¥værende spillet." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Lett" msgid "difficulty|Normal" msgstr "Middels" msgid "difficulty|Hard" msgstr "Vanskelig" msgid "difficulty|Expert" msgstr "Ekspert" msgid "difficulty|Impossible" msgstr "Umulig" msgid "and more..." msgstr "og mer..." msgid "Easy" msgstr "Enkel" msgid "Normal" msgstr "Middels" msgid "Hard" msgstr "Vanskelig" msgid "Campaign Difficulty" msgstr "FelttogsnivÃ¥" #, fuzzy msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Velg dette nivÃ¥et hvis du kun er ute etter Ã¥ oppleve historien. Motstanderne " "dine vil være svakere enn ved middels nivÃ¥." #, fuzzy msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Velg dette nivÃ¥et for Ã¥ oppleve felttoget slik som det opprinnelig var " "tiltenkt." #, fuzzy msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Velg nivÃ¥et hvis du ønsker en utfordring. Motstanderne dine vil være " "sterkere enn ved middels nivÃ¥." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Gratulerer!\n" "\n" "Dager: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "FelttogsnivÃ¥: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Poeng: %{score}\n" "\n" "Grad:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Begynn det kartet du har valgt." msgid "View Intro" msgstr "Vis video" #, fuzzy msgid "View the intro video for the current state of the campaign." msgstr "Vis filmen for det inneværende punktet av felttoget." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Velg vanskelighetsgrad for felttoget. Dette kan nedjusteres nÃ¥r som helst " "senere i felttoget." msgid "Restart the current scenario." msgstr "Start det nÃ¥værende kartet pÃ¥ nytt." msgid "Difficulty" msgstr "Vanskelighetsgrad" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Du har endret til en lavere vanskelighetsgrad for felttoget. Du vil ikke " "kunne omgjøre dette. Din endelige poengsum vil bli beregnet kun ut ifra den " "nye vanskelighetsgraden. Ønsker du Ã¥ gÃ¥ videre med valget?" msgid "Are you sure you want to restart this scenario?" msgstr "Er du sikker pÃ¥ at du vil begynne dette kartet pÃ¥ nytt?" msgid "Campaign Scenario loading failure" msgstr "Lasting av felttogskart mislyktes" msgid "Please make sure that campaign files are correct and present." msgstr "Vennligst forsikre deg om at kampanjefilene er riktige og til stede." msgid "Days spent" msgstr "Dager brukt" msgid "The number of days spent on this campaign." msgstr "Antall dager som har blitt brukt pÃ¥ felttoget sÃ¥ langt." msgid "Project Coordination and Core Development" msgstr "" "Prosjektkoordinering \n" "og hovedprogramvare-\n" "utvikling" msgid "Development" msgstr "Programvareutvikling" msgid "Visit us at " msgstr "Treff oss pÃ¥ " msgid "QA and Support" msgstr "Kvalitetssikring og støtte" msgid "Dev and Support" msgstr "Utvikling og støtte" msgid "Special Thanks to" msgstr "Spesielt takk til" #, fuzzy msgid "and many-many other contributors and supporters!" msgstr "og mange flere bidragsytere!" msgid "Support us at" msgstr "Støtt oss pÃ¥" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Kontakt oss pÃ¥" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Behov for hjelp med spillet?" msgid "Original project before 0.7" msgstr "Opprinnelig prosjekt før 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Teamet bak Heroes of Might and Magic II" msgid "Designed and Directed" msgstr "Utforming og ledelse" msgid "Programming and Design" msgstr "Programmering og utforming" msgid "Executive Producer" msgstr "Sjefsprodusent" msgid "Producer" msgstr "Produsent" msgid "Additional Design" msgstr "Øvrig utforming" msgid "Additional Programming" msgstr "Øvrig programmering" msgid "Musical Production" msgstr "Musikkproduksjon" msgid "Music and Sound Design" msgstr "Musikk- og lyddesign" msgid "Vocalists" msgstr "Vokalister" msgid "Art Director" msgstr "Kunstnerisk leder" msgid "Assistant Art Director" msgstr "Kunstnerisk leder-assistent" msgid "Artists" msgstr "Artister" msgid "QA Manager" msgstr "Koordinator for kvalitetssikring" msgid "QA" msgstr "Kvalitetssikring" msgid "Writing" msgstr "Skribent" msgid "Manual and Helpfile" msgstr "HÃ¥ndbok og hjelpefil" msgid "Scenarios" msgstr "Kart" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Teamet bak Heroes of Might and Magic II: The Price of Loyalty" msgid "Design Lead" msgstr "Hoveddesigner" msgid "Designers" msgstr "Designere" msgid "Programming Lead" msgstr "Hovedprogrammerer" msgid "Art Lead" msgstr "Artistisk leder" msgid "Playtesters" msgstr "Spilltestere" msgid "Designer" msgstr "Designer" msgid "Producers" msgstr "Produsenter" msgid "QA Managers" msgstr "Kvalitetssikringsledelse" msgid "Sound Design" msgstr "Lyddesign" msgid "Town Themes" msgstr "Musikktema i byer" msgid "Alto Sax" msgstr "Altsaksofonist" msgid "Harpsichord and Piano" msgstr "Cembalo og piano" msgid "Basso Vocal" msgstr "Bass" msgid "Soprano Vocal" msgstr "Sopran" msgid "Recorded at %{recordingStudio}" msgstr "Lydopptak gjort ved %{recordingStudio}" msgid "credits|Manual" msgstr "HÃ¥ndbok" msgid "German Consultant" msgstr "TyskrÃ¥dgiver" msgid "Map Designers" msgstr "Karttegnere" msgid "Package Design" msgstr "Innpakningsdesign" msgid "High Scores" msgstr "Rekordtavle" msgid "Your Name" msgstr "Ditt navn" msgid "Unknown Hero" msgstr "Ukjent helt" msgid "Standard" msgstr "Standard" msgid "View High Scores for Standard Maps." msgstr "Vis rekordtavle for enkle parti." msgid "Campaign" msgstr "Felttog" msgid "View High Scores for Campaigns." msgstr "Vis rekordtavle for felttog." msgid "hotkey|default okay event" msgstr "Bekreft" msgid "hotkey|default cancel event" msgstr "Avbryt" msgid "hotkey|default left" msgstr "Venstre" msgid "hotkey|default right" msgstr "Høyre" msgid "hotkey|default up" msgstr "Opp" msgid "hotkey|default down" msgstr "Ned" msgid "hotkey|toggle fullscreen" msgstr "Fullskjerm" msgid "hotkey|toggle text support mode" msgstr "Tekstmodus" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "Tekstmodus" msgid "hotkey|new game" msgstr "Nytt parti" msgid "hotkey|load game" msgstr "Last inn parti" #, fuzzy msgid "hotkey|high scores" msgstr "Rekordtavle" msgid "hotkey|credits" msgstr "Rulletekst" msgid "hotkey|standard game" msgstr "Enkelt parti" msgid "hotkey|campaign game" msgstr "Felttog" msgid "hotkey|multi-player game" msgstr "Flerspillermodus" msgid "hotkey|settings" msgstr "Innstillinger" msgid "hotkey|quit" msgstr "Avslutt" msgid "hotkey|select map" msgstr "Velg kart" msgid "hotkey|select small map size" msgstr "Velg smÃ¥ kart" msgid "hotkey|select medium map size" msgstr "Velg middles kart" msgid "hotkey|select large map size" msgstr "Velg store kart" msgid "hotkey|select extra large map size" msgstr "Velg ekstra store kart" msgid "hotkey|select all map sizes" msgstr "Velg alle kart" #, fuzzy msgid "hotkey|hot seat game" msgstr "Byttespillingsparti" msgid "hotkey|battle only game" msgstr "Kampparti" msgid "hotkey|choose the original campaign" msgstr "Velg Krigen om tronen" msgid "hotkey|choose the expansion campaign" msgstr "Velg Prisen for Lojalitet" msgid "hotkey|map editor main menu" msgstr "Karttegnerens hovedmeny" msgid "hotkey|new map menu" msgstr "Menyen for nye kart" msgid "hotkey|load map menu" msgstr "Menyen for kartlasting" msgid "hotkey|new map from scratch" msgstr "Nytt kart fra bunnen av" msgid "hotkey|new random map" msgstr "Nytt automatisk kart" #, fuzzy msgid "hotkey|undo last action" msgstr "Standard handling" #, fuzzy msgid "hotkey|redo last action" msgstr "Standard handling" #, fuzzy msgid "hotkey|open game main menu" msgstr "Menyen for nye kart" #, fuzzy msgid "hotkey|toggle passability" msgstr "SlÃ¥ av/pÃ¥ status" msgid "hotkey|roland campaign" msgstr "Rolands felttog" msgid "hotkey|archibald campaign" msgstr "Archibalds felttog" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "Felttoget Prisen for trofasthet" msgid "hotkey|voyage home campaign" msgstr "Felttoget Ferden hjem" msgid "hotkey|wizard's isle campaign" msgstr "Felttoget Magimestrenes øy" msgid "hotkey|descendants campaign" msgstr "Felttoget Etterkommerene" msgid "hotkey|select first campaign bonus" msgstr "Velg felttogsbonus nr.1" msgid "hotkey|select second campaign bonus" msgstr "Velg felttogsbonus nr.2" msgid "hotkey|select third campaign bonus" msgstr "Velg felttogsbonus nr.3" msgid "hotkey|view campaign intro" msgstr "Vis felttogsintro" msgid "hotkey|select campaign difficulty" msgstr "Velg felttogets vanskelighetsgrad" msgid "hotkey|restart campaign scenario" msgstr "Start felttogskart pÃ¥ nytt" msgid "hotkey|world map left" msgstr "Verdenskart venstre" msgid "hotkey|world map right" msgstr "Verdenskart høyre" msgid "hotkey|world map up" msgstr "Verdenskart opp" msgid "hotkey|world map down" msgstr "Verdenskart ned" msgid "hotkey|world map up left" msgstr "Verdenskart opp til venstre" msgid "hotkey|world map up right" msgstr "Verdenskart opp til høyre" msgid "hotkey|world map down left" msgstr "Verdenskart ned til venstre" msgid "hotkey|world map down right" msgstr "Verdenskart ned til høyre" msgid "hotkey|save game" msgstr "Lagre parti" msgid "hotkey|next hero" msgstr "Neste helt" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "Neste helt" #, fuzzy msgid "hotkey|start hero movement" msgstr "Fortsett heltens forflytning" msgid "hotkey|cast adventure spell" msgstr "Bruk kartmagi" msgid "hotkey|put hero to sleep" msgstr "Sett helt i dvale" msgid "hotkey|next town" msgstr "Neste by" msgid "hotkey|end turn" msgstr "Avslutt tur" msgid "hotkey|file options" msgstr "Filvalg" msgid "hotkey|adventure options" msgstr "Kartinnstillinger" msgid "hotkey|puzzle map" msgstr "Puslekart" msgid "hotkey|scenario information" msgstr "Kartbeskrivelse" msgid "hotkey|dig for artifact" msgstr "Grav etter gjenstand" msgid "hotkey|view world" msgstr "Vis verden" msgid "hotkey|kingdom summary" msgstr "Oversikt over kongedømmet" msgid "hotkey|default action" msgstr "Standard handling" msgid "hotkey|open focus" msgstr "Ã…pne nÃ¥værende plassering" msgid "hotkey|system options" msgstr "Systeminnstillinger" msgid "hotkey|scroll left" msgstr "Panorer til venstre" msgid "hotkey|scroll right" msgstr "Panorer til høyre" msgid "hotkey|scroll up" msgstr "Panorer opp" msgid "hotkey|scroll down" msgstr "Panorer ned" msgid "hotkey|toggle control panel" msgstr "SlÃ¥ av/pÃ¥ kontrollpanel" msgid "hotkey|toggle radar" msgstr "SlÃ¥ av/pÃ¥ minikart" msgid "hotkey|toggle buttons" msgstr "SlÃ¥ av/pÃ¥ knapper" msgid "hotkey|toggle status" msgstr "SlÃ¥ av/pÃ¥ status" msgid "hotkey|toggle icons" msgstr "SlÃ¥ av/pÃ¥ ikoner" msgid "hotkey|transfer control to ai" msgstr "Overfør styring til KI" msgid "hotkey|retreat from battle" msgstr "Trekk tilbake fra kamp" msgid "hotkey|surrender during battle" msgstr "Overgivelse i kamp" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "SlÃ¥ pÃ¥/av automatiske trekk i kamp" #, fuzzy msgid "hotkey|quick combat" msgstr "Avslutt" msgid "hotkey|battle options" msgstr "Kampvalg" msgid "hotkey|skip turn in battle" msgstr "Velg pass i kamp" msgid "hotkey|cast battle spell" msgstr "Bruk magi i kamp" msgid "hotkey|dwelling level 1" msgstr "Bosted nivÃ¥ 1" msgid "hotkey|dwelling level 2" msgstr "Bosted nivÃ¥ 2" msgid "hotkey|dwelling level 3" msgstr "Bosted nivÃ¥ 3" msgid "hotkey|dwelling level 4" msgstr "Bosted nivÃ¥ 4" msgid "hotkey|dwelling level 5" msgstr "Bosted nivÃ¥ 5" msgid "hotkey|dwelling level 6" msgstr "Bosted nivÃ¥ 6" msgid "hotkey|well" msgstr "Brønn" msgid "hotkey|marketplace" msgstr "Markedsplass" msgid "hotkey|mage guild" msgstr "Magikerforbund" msgid "hotkey|shipyard" msgstr "Skipsverft" msgid "hotkey|thieves guild" msgstr "Tyvenes laug" msgid "hotkey|tavern" msgstr "Vertshus" msgid "hotkey|construction screen" msgstr "Byggeskjerm" msgid "hotkey|buy all monsters in well" msgstr "Kjøp alle krigere fra brønnen" msgid "hotkey|split stack by half" msgstr "Del tropper i to" msgid "hotkey|split stack by one" msgstr "Del av én kriger fra tropp" msgid "hotkey|join stacks" msgstr "Foren tropper" msgid "hotkey|upgrade troop" msgstr "Oppgrader tropp" msgid "hotkey|dismiss hero or troop" msgstr "Bortvis helt" #, fuzzy msgid "hotkey|exchange all troops" msgstr "Oppgrader tropp" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Vil du gi styringen til datamaskinen? Dette vil først tre i kraft den neste " "runden." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Ønsker du Ã¥ ta styringen fra datamaskinen? Dette vil kun tre i kraft den " "neste runden." #, fuzzy msgid "Default Actions" msgstr "Standard handling" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Verdenskart" #, fuzzy msgid "Battle Screen" msgstr "Heltevindu" #, fuzzy msgid "Town Screen" msgstr "Heltevindu" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "Lagringsfilen er korrupt." msgid "Unsupported save format: " msgstr "Ustøttet lagringsformat: " msgid "Current game version: " msgstr "Spillutgave som brukes: " msgid "Last supported version: " msgstr "Sist støttede utgave: " msgid "This file contains a save with an invalid game type." msgstr "Denne filen inneholder et lagringspunkt med en ugyldig spillversjon." #, fuzzy msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Denne filen ble lagret i spillutgaven \"Prisen for trofasthet\", men de " "tilhørende utvidelsesfilene mangler." msgid "This saved game is localized to '" msgstr "Dette lagrede spillet er satt opp for sprÃ¥ket '" msgid "' language, but the current language of the game is '" msgstr "', men det gjeldende sprÃ¥ket for spillet er '" msgid "No save files to load." msgstr "Ingen lagrede spill Ã¥ laste inn." msgid "Hot Seat" msgstr "Byttespilling" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Spill en runde byttespilling hvor 2 til 6 spillere rullerer pÃ¥ Ã¥ spille pÃ¥ " "den samme enheten og bytter plass nÃ¥r det er nestemann sin tur." msgid "A single player game playing out a single map." msgstr "Et enkeltspillerparti som spilles ut pÃ¥ et enkelt kart." msgid "Standard Game" msgstr "Enkelt parti" msgid "A single player game playing through a series of maps." msgstr "Et enkeltspillerparti som utspilles over en rekke kart." msgid "Campaign Game" msgstr "Felttog" msgid "Multi-Player Game" msgstr "Flerspillermodus" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Et flerspillerparti hvor flere menneskelige spillere konkurrerer mot " "hverandre pÃ¥ et enkelt kart." msgid "fheroes2 Resurrection Team presents" msgstr "Teamet bak fheroes2 Resurrection presenterer" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Velkommen til Heroes of Might and Magic II drevet av fheroes2-spillmotoren!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Velkommen til Heroes of Might and Magic II drevet av fheroes2 spillmotoren! " "Vennligst velg skjermoppløsning før du begynner." msgid "Greetings!" msgstr "Heisann!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Forlat Heroes of Might and Magic II og dra tilbake til operativsystemet." msgid "Credits" msgstr "Rulletekst" msgid "View the credits screen." msgstr "Vis rulleteksten." msgid "View the high scores screen." msgstr "Vis rekordtavlen." #, fuzzy msgid "Create new or modify existing maps." msgstr "Last inn et eksisterende kart." msgid "Change language, resolution and settings of the game." msgstr "Endre sprÃ¥ket, oppløsningen og andre spillinnstillinger." msgid "Game Settings" msgstr "Spillinnstillinger" #, fuzzy msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "De nødvendige filene for felttogets valgvindu mangler. Vennligst forsikre " "deg om at alle nødvendige filer er tilstede i systemet." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Velg mellom felttoget til Roland og Archibald fra det originale Heroes of " "Might and Magic II." msgid "Original Campaign" msgstr "Originalt felttog" msgid "Expansion Campaign" msgstr "Utvidelsesfelttog" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" "En av de fire nye utvidelsesfelttogene fra utvidelsen Prisen for trofasthet." msgid "Loading video. Please wait..." msgstr "Laster video. Vennligst vent..." msgid "Host" msgstr "Vert" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Verten fyller ut spillvalgene. Det kan kun være én vert per nettverksspill." msgid "Guest" msgstr "Gjest" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "Gjesten venter pÃ¥ at verten setter opp partiet og blir deretter automatisk " "lagt til. Det kan være flere gjester for TCP/IP-parti." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" #, fuzzy msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Et flerspillerparti hvor flere menneskelige spillere konkurrerer mot " "hverandre pÃ¥ et enkelt kart." msgid "Battle Only" msgstr "Kampmodus" msgid "Setup and play a battle without loading any map." msgstr "Sett opp og spill en kamp uten Ã¥ laste inn et kart." #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Spill en runde byttespilling hvor 2 til 6 spillere rullerer pÃ¥ Ã¥ spille pÃ¥ " "den samme enheten og bytter plass nÃ¥r det er nestemann sin tur." msgid "2 Players" msgstr "2 Spillere" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Spill med 2 menneskelige spillere, og eventuelt opp til 4 ekstra " "computerspillere." msgid "3 Players" msgstr "3 Spillere" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Spill med 3 menneskelige spillere, og eventuelt opp til 3 ekstra " "computerspillere." msgid "4 Players" msgstr "4 Spillere" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Spill med 4 menneskelige spillere, og eventuelt opp til 2 ekstra " "computerspillere." msgid "5 Players" msgstr "5 Spillere" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Spill med 5 menneskelige spillere, og eventuelt opp til 1 ekstra " "computerspiller." msgid "6 Players" msgstr "6 Spillere" msgid "Play with 6 human players." msgstr "Spill med 6 menneskelige spillere." #, fuzzy msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Dragenes landsby har falt! Du har nÃ¥ blitt mesteren av dragene." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Du har overtatt %{name}!\n" "Seieren er din." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Du har fanget fiendens helt %{name}!\n" "Oppdraget ditt er fullført." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Du har funnet %{name}.\n" "Oppdraget ditt er fullført." msgid "Ultimate Artifact" msgstr "Den sjeldneste gjenstanden" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Fienden har blitt slÃ¥tt ut.\n" "Din side har seiret!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Du har spart opp over %{count} gullstykker i statskassa di.\n" "Alle motstanderne bøyer seg foran din rikdom og makt." #, fuzzy msgid "Victory!" msgstr "Hektor" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Fienden har fanget %{name}!\n" "De har seiret." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Fienden har spart opp mer enn %{count} gull i statskassa si.\n" "Du mÃ¥ bøye deg i nederlag for fiendens rikdom og makt." msgid "You have been eliminated from the game!!!" msgstr "Du har blitt slÃ¥tt ut av spillet!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Du har mistet helten %{name}.\n" "Oppdraget ditt er over." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Du klarte ikke Ã¥ fullføre oppdraget innen tiden.\n" "Alt er tapt." msgid "Defeat!" msgstr "Nederlag!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Grunnpoeng: %{score}\n" "Vanskelighetsgrad: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "SlÃ¥ ut alle fiendtlige helter og overta alle fiendtlige byer og borger." msgid "Your side defeats the opposing side." msgstr "Den siden du spiller pÃ¥ mÃ¥ slÃ¥ motstandersiden." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "GÃ¥ tom for tid. (Mislykkes i Ã¥ vinne innen en viss tid.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "SlÃ¥ ut motstanderen din %{enemies}." msgstr[1] "SlÃ¥ ut den fiendtlige alliansen bestÃ¥ende av %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Alliansen som bestÃ¥r av %{allies} og deg mÃ¥ slÃ¥ motstanderen %{enemies}." msgstr[1] "" "Alliansen som bestÃ¥r av %{allies} og deg mÃ¥ slÃ¥ den fiendtlige alliansen som " "bestÃ¥r av %{enemies}." msgid "Capture the castle '%{name}'." msgstr "Overta borgen kalt %{name}." msgid "Capture the town '%{name}'." msgstr "Overta byen kalt %{name}." msgid "Defeat the hero '%{name}'." msgstr "SlÃ¥ ut helten ved navn %{name}." msgid "Find the ultimate artifact." msgstr "Finn den sjeldneste skatten." msgid "Find the '%{name}' artifact." msgstr "Finn skatten kalt %{name}." msgid "Accumulate %{count} gold." msgstr "Samle opp %{count} gullstykker." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", eller du kan vinne ved Ã¥ slÃ¥ ut alle fiendtlige helter og overta alle " "fiendtlige byer og borger." msgid "Lose the castle '%{name}'." msgstr "Mist borgen kalt %{name}." msgid "Lose the town '%{name}'." msgstr "Mist byen kalt %{name}." msgid "Lose the hero: %{name}." msgstr "Mist helten kalt %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Mislykkes i Ã¥ vinne innen slutten av mÃ¥ned %{month}, uke %{week}, dag %{day}." msgid "%{color} player has been vanquished!" msgstr "%{color} spiller har blitt utslettet!" msgid "Major Event!" msgstr "Viktig hendelse!" msgid "Scenario:" msgstr "Kart:" msgid "Game Difficulty:" msgstr "Vanskelighetsgrad:" # Evt spillere. MÃ¥ funke for bÃ¥de motspillere og lagkamerater. msgid "Opponents:" msgstr "Deltakere:" msgid "Class:" msgstr "Helteslag:" msgid "Rating %{rating}%" msgstr "Utbytte %{rating}%" msgid "Click here to select which scenario to play." msgstr "Klikk her for Ã¥ velge hvilket kart du vil spille." msgid "Scenario" msgstr "Kart" msgid "Game Difficulty" msgstr "Vanskelighetsgrad" #, fuzzy msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Dette lar deg forandre utfordringen du starter med. Jo høyere " "vanskelighetsgraden er desto større blir forskjellen mellom rÃ¥varene du " "starter med og den motspillerne starter med." msgid "Difficulty Rating" msgstr "Utbytte" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Utbytteprosenten regnes ut som summen av de forskjellige innstilligene du " "har valgt for partiet ditt. Denne prosenten pÃ¥virker den endelige " "poengsummen din dersom du vinner partiet." msgid "Click to accept these settings and start a new game." msgstr "Klikk her for Ã¥ bekrefte disse valgene og begynne pÃ¥ et nytt parti." msgid "Click to return to the main menu." msgstr "Klikk her for Ã¥ dra tilbake til hovedmenyen." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Astrologene kunngjør at det er mÃ¥neden av %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Astrologene kunngjør at det er uka av %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "Etter en vanlig vekst dobles nÃ¥ alle befolkninger med %{monster}!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Etter en vanlig vekst øker nÃ¥ befolkningen med %{monster} med %{count} " "prosent!" msgstr[1] "" "Etter en vanlig vekst øker nÃ¥ befolkningen av %{monster} med %{count} " "prosent!" msgid "%{monster} growth +%{count}." msgstr "Alle befolkninger med %{monster} vokser med +%{count}." msgid " All populations are halved." msgstr " Alle befolkninger halveres." msgid " All dwellings increase population." msgstr " Alle bostedenes befolkninger opplever vanlig vekst." msgid "New Month!" msgstr "" msgid "New Week!" msgstr "Ny uke!" msgid "Beware!" msgstr "Viktig beskjed!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} spiller, dette er den siste dagen for Ã¥ ta over en by, ellers blir " "du bannlyst fra landet." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} spiller, du har kun %{day} dager igjen pÃ¥ Ã¥ ta over en by, ellers " "blir du bannlyst fra landet." msgid "%{color} player's turn." msgstr "%{color} spillers tur." #, fuzzy msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} spiller, du har mistet den siste byen din. Hvis du ikke tar over en " "ny by innen neste uke vil du bli slÃ¥tt ut." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} spiller, dine helter forlater deg og du er bannlyst fra landet." msgid "Lord Kilburn" msgstr "Fyrst Kilburn" msgid "Tsabu" msgstr "Sabu" msgid "Sir Galant" msgstr "Herr Galant" msgid "Thundax" msgstr "Tordøks" msgid "Lord Haart" msgstr "Fyrst Hjart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebekka" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Krod" msgid "Barock" msgstr "Barokk" msgid "Antoine" msgstr "" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Hagar" msgid "Vatawna" msgstr "Vatavna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyann" msgid "Jojosh" msgstr "Jojosva" msgid "Wrathmont" msgstr "Vredeberg" msgid "Maximus" msgstr "Maksimus" msgid "Next Hero" msgstr "Neste helt" msgid "Select the next Hero." msgstr "Velg neste helt." #, fuzzy msgid "Hero Movement" msgstr "" "Uthevd\n" "rekkevidde" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "Oppsummert kongedømme" #, fuzzy msgid "View a summary of your Kingdom." msgstr "Vis en oppsummering av kongedømmet ditt." msgid "Cast an adventure spell." msgstr "Bruk kartmagi." msgid "End Turn" msgstr "Avslutt tur" #, fuzzy msgid "End your turn and let the computer take its turn." msgstr "Avslutt turen din og la motstanderne gjøre sine turer." msgid "Adventure Options" msgstr "Kartinnstillinger" msgid "Bring up the adventure options menu." msgstr "Hent fram menyen for kartinnstillinger." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Ã…pne menyen for filvalg, som lar deg laste inn et parti, lagre et parti, " "begynne pÃ¥ et nytt parti eller avslutte." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "Hent fram menyen for systeminnstillinger og skreddersy spillet." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Én eller flere helter kan fortsatt forflytte seg. Vil du likevel avslutte " "turen din?" msgid "Are you sure you want to quit?" msgstr "Er du sikker pÃ¥ at du vil avslutte?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Er du sikker pÃ¥ at du vil begynne pÃ¥ nytt?\n" "(Alt som er ulagret i dette partiet vil gÃ¥ tapt.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Er du sikker pÃ¥ at du vil overskrive lagringspunktet med dette navnet?" msgid "Game saved successfully." msgstr "Lagring vellykket." msgid "There was an issue during saving." msgstr "Det oppstod et problem under lagringen." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Er du sikker pÃ¥ at du ønsker Ã¥ laste inn et tidligere parti?\n" "(Alt som er ulagret i dette partiet vil gÃ¥ tapt.)" msgid "Try looking on land!!!" msgstr "Prøv Ã¥ let pÃ¥ land!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Det vil være nytteløst Ã¥ lete etter den sjeldneste skatten fordi helten din " "vil ikke kunne ta den med seg - det er ikke plass til mer." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Graving etter sjeldne skatter krever en hel dag. Prøv igjen i morgen." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "Etter mange timer med graving her, oppdager du %{artifact}." msgid "Congratulations!" msgstr "Gratulerer!" msgid "Nothing here. Where could it be?" msgstr "Ingenting her. Hvor kan den være?" msgid "Try searching on clear ground." msgstr "Prøv Ã¥ let pÃ¥ bar bakke." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Et overblikk over den utforskede verdenen. Venstre-klikk for Ã¥ flytte " "visningsomrÃ¥det." msgid "Month: %{month} Week: %{week}" msgstr "MÃ¥ned: %{month}, Uke: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Du fant en liten\n" "mengde %{resource}." msgid "Status Window" msgstr "Statusvindu" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Dette vinduet gir informasjon om tilstanden til helten din og kongedømmet " "ditt, samt at det viser dagens dato." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Dette vinduet viser informasjon om tilstanden til helten og kongedømmet " "ditt, i tillegg til dagens dato. Venstre-klikk her for Ã¥ bla gjennom de " "forskjellige informasjonsvinduene." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Dette lar deg forandre startplassen og fargen til spillerne. Hver startplass " "er knyttet til en farge. Noen plasser kan kun tas av computerspillere, mens " "andre kun av menneskelige spillere." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Dette lar deg bytte helteslaget til en spiller. Helteslaget kan ikke alltid " "byttes. Avhengig av kartet, kan en spiller fÃ¥ flere byer og/eller helter som " "ikke er av spillerens hovedtilhørighet." msgid "Handicap" msgstr "Handikap" # #, fuzzy msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Denne innstillingen lar deg justere handikapet til de forskjellige " "spillerne. Kun menneskelige spillere kan ha handikap. Spillere med handikap " "begynner kartet med færre rÃ¥varer og tjener 15 eller 30% færre rÃ¥varer hver " "runde for henholdsvis lett og sterkt handikap." msgid "%{color} player" msgstr "%{color} spiller" msgid "No Handicap" msgstr "Ingen handikap" #, fuzzy msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Ingen spesielle begrensninger pÃ¥ hvor mye rÃ¥varer man starter med pÃ¥ kartet " "og hvor mye man tjener hver runde." msgid "Mild Handicap" msgstr "Lett handikap" # #, fuzzy msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Spillere med et lett handikap vil begynne kartet med færre rÃ¥varer og tjene " "15% mindre rÃ¥varer hver runde." msgid "Severe Handicap" msgstr "Sterkt handikap" #, fuzzy msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Spillere med sterkt handikap vil begynne kartet med færre rÃ¥varer og tjene " "30% mindre rÃ¥varer hver runde." msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Spesifiser angrepsevne" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Vis info om %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Forsvar" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "MELLOMROM" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Kongedømmets inntekt" msgid "Kingdom Income per day." msgstr "Dette er den daglige inntekten til kongedømmet ditt." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "For hvert fyrtÃ¥rn under din besittelse vil skipene dine kunne flytte seg " "lengre hver dag." msgid "English" msgstr "Engelsk" msgid "French" msgstr "Fransk" msgid "Polish" msgstr "Polsk" msgid "German" msgstr "Tysk" msgid "Russian" msgstr "Russisk" msgid "Italian" msgstr "Italiensk" msgid "Czech" msgstr "Tsjekkisk" msgid "Norwegian" msgstr "Norsk" msgid "Belarusian" msgstr "" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" msgid "Vietnamese" msgstr "" msgid "Slow" msgstr "Treg" msgid "Fast" msgstr "Fort" msgid "Very Fast" msgstr "Rask" msgid "Evil" msgstr "Ond" msgid "Good" msgstr "God" msgid ", FPS: " msgstr ", FPS: " #, fuzzy msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} ranet" #, fuzzy msgid "pyramid|%{object} raided" msgstr "%{object} plyndret" msgid "Ector" msgstr "Hektor" msgid "Gwenneth" msgstr "Lycke" msgid "Sir Gallant" msgstr "Herr Gallant" msgid "Tyro" msgstr "Tyros" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Rubin" msgid "Crag Hack" msgstr "Kragg Hakk" msgid "Fineous" msgstr "Finneas" msgid "Jezebel" msgstr "Izabell" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Herkon" msgid "Jaclyn" msgstr "Bina" msgid "Gem" msgstr "Edelsten" msgid "Natasha" msgstr "Natalie" msgid "Carlawn" msgstr "Karlana" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastor" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Morgengry" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myrha" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Vilfrid" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakinn" msgid "Charity" msgstr "Karita" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Rannlov" msgid "Rialdo" msgstr "Rialto" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roksana" msgid "Lord Corlagon" msgstr "Fyrst Korlagon" msgid "Lord Halton" msgstr "Fyrst Halton" msgid "Sister Eliza" msgstr "Søster Eliza" msgid "Brother Brax" msgstr "Broder Brax" msgid "Dainwin" msgstr "Deinvinn" msgid "Joseph" msgstr "Josef" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ketill" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Harkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " gir deg den beste kampÃ¥nden" msgid " gives you maximum luck" msgstr " gir deg den beste flaksen" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Trylleboken kan ikke flyttes" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" "Du kan ikke plukke opp denne skatten - du er helt fullastet med skatter!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "For Ã¥ bruke trolldom mÃ¥ du først kjøpe ei tryllebok. Den koster %{gold} " "gullstykker." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Dessverre ser det ut til at du ikke har rÃ¥d akkurat nÃ¥." msgid "Do you wish to buy one?" msgstr "Ønsker du Ã¥ kjøpe én?" msgid "%{count} / day" msgstr "%{count} / dag" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "Virvelstrømmen sluker skipet ditt. Noen av krigerne dine har falt om bord." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Fornærmet over at du avslo tilbudet deres angriper styrken deg!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "Gruppen med %{monster} blir mÃ¥lløs nÃ¥r den ser hvor overlegen hæren din er, " "og den begynner Ã¥ rømme.\n" "Ønsker du Ã¥ følge etter og gÃ¥ til kamp?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" "Du gjennomsøker den forlatte leirplassen og avdekker et skjult gjemmested " "for verdifulle ting." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Vokteren av mølla sier:\n" "\"Min herre, jeg har jobbet veldig hardt for Ã¥ kunne gi deg disse rÃ¥varene. " "Kom tilbake neste uke for mer.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Vokteren av mølla sier:\n" "\"Min herre, jeg har ingen rÃ¥varer igjen. Vennligst prøv igjen neste uke.\"." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Vokteren av mølla sier:\n" "\"Min herre, jeg har jobbet veldig hardt for Ã¥ kunne gi deg dette gullet. " "Kom tilbake neste uke for mer.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Vokteren av mølla sier:\n" "\"Min herre, det er ikke noe gull igjen. Vennligst prøv igjen neste uke.\"." msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Du kommer over en forlatt gapahuk.\n" "Etter Ã¥ ha sett litt rundt omkring den finner du noen bortgjemte rÃ¥varer." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "Gapahuken er for lengst forlatt. Det fins ingenting av verdi her." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Du fÃ¥r fatt i en regnbuegnom som lÃ¥ og sov i dÃ¥rskap blant en klynge magiske " "sopper.\n" "I bytte mot sin frihet viser han deg veien til en liten gryte fylt med " "verdifulle ting." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Du fant en magisk hage, den typen sted hvor regnbuegnomer og feer liker Ã¥ " "hoppe rundt, men det er ingen her i dag.\n" "Kanskje du skal prøve igjen neste uke." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Du kommer over levningene til en uheldig eventyrer." msgid "Treasure" msgstr "Verdifull gjenstand" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Etter Ã¥ ha lett gjennom de fillete plaggene, finner du: %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Du leter gjennom de fillete plaggene, men finner ingenting." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Du kommer over en gammel varevogn etterlatt av en handelsmann, som etter alt " "Ã¥ bedømme ikke hadde hellet pÃ¥ sin side." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Dessverre har noen andre funnet den først og vognen er tom." msgid "Searching inside, you find the %{artifact}." msgstr "Etter Ã¥ ha lett inni den, finner du %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Inni vognen finner du noe av lasten dens i behold." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Du gÃ¥r gjennom vrakgodset og finner litt ved og litt gull." msgid "You search through the flotsam, and find some wood." msgstr "Du gÃ¥r gjennom vrakgodset og finner litt ved." msgid "You search through the flotsam, but find nothing." msgstr "Du gÃ¥r gjennom vrakgodset, men finner ingenting." msgid "Shrine of the 1st Circle" msgstr "Tempel av første sirkel" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Du kommer over et lite tempel passet pÃ¥ av en gruppe nyutdannete " "tempeltjenere.\n" "I bytte mot din beskyttelse gÃ¥r de med pÃ¥ Ã¥ lære deg den enkle trolldommen: " "'%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Tempel av andre sirkel" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Du kommer over et flott tempel passet pÃ¥ av en gruppe omfangsrike munker.\n" "I bytte mot din beskyttelse gÃ¥r de med pÃ¥ Ã¥ lære deg trolldommen: '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Tempel av tredje sirkel" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Du kommer over et overdÃ¥dig tempel passet pÃ¥ av en gruppe øversteprester.\n" "I bytte mot din beskyttelse gÃ¥r de med pÃ¥ Ã¥ lære deg den mektige " "trolldommen: '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Dessverre har du ikke visdommen som skal til for Ã¥ forstÃ¥ trolldommen, og " "dermed klarer du ikke Ã¥ lære deg den." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Dessverre kan du allerede denne trolldommen, sÃ¥ det er ingenting mer de kan " "lære deg." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Dessverre har du ingen tryllebok Ã¥ notere ned trolldommen i." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Du kommer nærme en hytte og fÃ¥r øye pÃ¥ en heks pÃ¥ innsiden. Hun leser fra en " "eldgammel bok om %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Idet du gÃ¥r nærmere snur hun seg og retter sitt ene glassøye mot deg.\n" "\"Du kan allerede alt du fortjener Ã¥ lære!\" skriker heksen. \"SE Ã… KOM DEG " "UT AV HUSET MITT!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Imens du gÃ¥r nærmere snur hun seg og sier:\n" "\"Du kan allerede det jeg ville ha lært deg. Jeg kan ikke hjelpe deg med mer." "\"." msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Den eldgamle og udødelige heksa som er bosatt i hytta pÃ¥ de gigantiske " "fuglebeinene velger av hennes egne merkelige grunner Ã¥ lære deg\n" "%{skill}." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" "Etter Ã¥ ha drukket det forfriskende vannet øker flaksen din for det neste " "slaget ditt." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Du drikker fra den magiske fontenen, men det skjer ingenting." msgid "You enter the faerie ring, but nothing happens." msgstr "Du gÃ¥r inn i feenes ring, men ingenting skjer." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "PÃ¥ innsiden av feenes ring fÃ¥r hæren din flaks for sin neste kamp." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Du fant en eldgammel og værbitt gudestatue av stein.\n" "Den skal visstnok bringe lykke til besøkende, men siden sola allerede " "skinner pÃ¥ deg gjør den ingenting." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Du fant en eldgammel og værbitt gudestatue av stein.\n" "Ã… kysse den skal visstnok bringe lykke, sÃ¥ du gjør akkurat det. Steinen " "kjentes veldig kald ut." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "I stillhet lokker havfruene deg til Ã¥ komme tilbake senere og bli velsignet " "igjen." #, fuzzy msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Den magiske og beroligende skjønnheten til havfruene klarer Ã¥ lokke til seg " "deg og mannskapet ditt.\n" "For et øyeblikk glemmer du bekymringene dine og nyter stunden.\n" "Havfruenes fortryllelser velsigner deg med økt flaks til din neste kamp." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Du kommer over pyramiden til en mektig oldtidskonge.\n" "Du er fristet til Ã¥ lete etter skatter i den, men gamle fortellinger har " "advart deg om fryktelige forbannelser og vandøde voktere.\n" "Vil du likevel lete gjennom den?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Etter Ã¥ ha utryddet monstrene tyder du en eldgammel tekst pÃ¥ veggen, og den " "skjuler hemmeligheten bak trolldommen:\n" "'" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Dessverre har du ingen tryllebok Ã¥ notere ned trolldommen i." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Dessverre har du ikke visdommen som skal til for Ã¥ forstÃ¥ trolldommen, og du " "klarer ikke Ã¥ lære deg den." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Du kommer over pyramiden til en stor konge av oldtiden.\n" "Etter en rask sjekk viser det seg at pyramiden er fullstendig tom." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "En slurk fra brønnen skal egentlig fylle opp manaen din, men du har allerede " "fullt." msgid "A second drink at the well in one day will not help you." msgstr "" "Flere slurker fra brønnen pÃ¥ én og samme dag vil ikke kunne hjelpe deg." msgid "A drink from the well has restored your spell points to maximum." msgstr "" "Du tar deg en slurk fra brønnen, og manaen din blir fullstendig fylt opp." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Jeg beklager, min herre\", sier lederen av soldatene, \"men du kan " "allerede alt vi har Ã¥ lære bort.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Soldatene som holder til ved fortet lærer deg et par nye forsvarstriks." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Du kommer over leiren til noen leiesoldater som driver med kamptrening. \"Du " "har et mye høyere nivÃ¥ enn oss,\" sier leiesoldatenes kaptein. \"Det er " "ingenting vi kan lære deg.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Du kommer over leiren til noen leiesoldater som driver med kamptrening. " "Leiesoldatene ønsker deg og styrkene dine velkomne og inviterer dere til Ã¥ " "sparre med dem." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"GÃ¥ vekk!\", bjeffer heksedoktoren, \"du kan alt jeg kan.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "En heksedoktor av en ork bor i hytta, og han beriker kunnskapen din om magi " "ved Ã¥ vise deg hvordan man kaster steiner, tolker jærtegn og finner skjulte " "sannheter i kyllinginnvoller." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Du har funnet en gruppe druider som tilber ved et av deres merkelige " "byggverk i stein. I stillhet bortviser druidene deg for Ã¥ vise at de ikke " "har noe nytt Ã¥ lære deg." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Du har funnet en gruppe druider som tilber ved et av deres merkelige " "byggverk i stein. I stillhet lærer de deg nye mÃ¥ter Ã¥ trylle pÃ¥." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Du tilnærmer deg forsiktig et gravsted for krigere fra oldtiden. Ønsker du Ã¥ " "plyndre gravene deres?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Du tilbringer flere timer pÃ¥ Ã¥ lete gjennom gravene, men finner ingenting. " "En slik fordømmelig handling svekker kampÃ¥nden til hæren din." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "Etter Ã¥ ha tatt hÃ¥nd om zombiene tilbringer du flere timer pÃ¥ Ã¥ lete gjennom " "gravene, og tilslutt finner du noe!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Det rÃ¥tne skroget til et storslagent sjørøverskip knaker nifst mens det " "skubber borti steinene.\n" "Vil du lete gjennom skipbruddet?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Du tilbringer flere timer pÃ¥ Ã¥ gÃ¥ gjennom vraket, men finner ingenting. En " "slik forkastelig handling svekker kampÃ¥nden til hæren din." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" "Etter Ã¥ ha beseiret gjenferdene bruker du flere timer pÃ¥ Ã¥ gÃ¥ gjennom " "vraket, og tilslutt finner du noe!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Det rÃ¥tne skroget til et mektig sjørøverskip knaker nifst mens det skubber " "borti steinene.\n" "Vil du lete gjennom skipet?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "Etter Ã¥ ha beseiret skjelettene tilbringer du flere timer pÃ¥ Ã¥ gÃ¥ gjennom " "godset, og tilslutt finner du noe!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Mannskapet ditt fÃ¥r øye pÃ¥ et flytende sjømerke. Det bekrefter at dere er pÃ¥ " "rett kurs." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Mannskapet ditt fÃ¥r øye pÃ¥ et flytende sjømerke. Det bekrefter at dere er pÃ¥ " "rett kurs og dette styrker kampÃ¥nden til hele mannskapet." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Slurken fra oasen er forfriskende, men den gjør ingenting mer utover det. " "Oasen kan kanskje hjelpe deg igjen dersom du tar en kamp først." #, fuzzy msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "En slurk fra oasen fyller troppene dine med styrke og løfter stemningen " "deres. Du kan reise litt lengre i dag." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Slurken fra vannkilden er forfriskende, men utover det skjer det ingenting. " "Vannkilden kan kanskje hjelpe deg igjen hvis du tar en kamp først." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "En slurk fra vannkilden fyller troppene dine med styrke og løfter stemningen " "deres. Du kan reise litt lengre i dag." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Det hjelper ikke Ã¥ be to ganger før en kamp. Kom tilbake etter at du har " "kjempet." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Et besøk og en bønn ved tempelet styrker kampÃ¥nden til hæren din." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "En gammel ridder dukker opp pÃ¥ trappa til lysthuset, \"Jeg beklager, min " "herre. Jeg har lært deg alt jeg kan.\"." msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "En gammel ridder dukker opp pÃ¥ trappa til lysthuset, \"Min herre, jeg skal " "lære deg alt jeg kan for Ã¥ hjelpe deg pÃ¥ din ferd.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Du berget en skipbrudden fra en sikker død i det nÃ¥deløse havet. Takknemlig " "sier han: \"Jeg skulle gjerne ha gitt deg en belønning som takk, men du har " "ikke plass.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Du berget en skipbrudden fra en sikker død i det nÃ¥deløse havet. Som takk " "for din godhet gir han deg skatten:\n" " %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "En regnbuegnom tilbyr deg %{art} imot en beskjeden sum pÃ¥ %{gold} " "gullstykker." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "En regnbuegnom tilbyr deg %{art} imot en beskjeden sum pÃ¥ %{gold} " "gullstykker og %{count} enheter %{res}." msgid "Do you wish to buy this artifact?" msgstr "Ønsker du Ã¥ kjøpe denne verdifulle gjenstanden?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Du forsøker Ã¥ betale regnbuegnomen, men innser at du ikke har rÃ¥d. Gnomen " "tramper foten sin og snur seg vekk fra deg." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Fornærmet av avslaget ditt pÃ¥ det sjenerøse tilbudet hans tramper gnomen med " "foten sin og snur seg vekk fra deg." msgid "You've found the artifact: " msgstr "Du fant den verdifulle gjenstanden: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Du kommer over det beskjedne bostedet til en gammel og rynkete einstøing. " "Gamlingen forteller deg at han er villig til Ã¥ gi bort den verdifulle " "gjenstanden %{art} til det første vise mennesket han møter." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Du kommer over det nøysomme kvarteret til en avgÃ¥tt soldat. Soldaten " "forteller deg at han er villig til Ã¥ gi bort skatten %{art} til den første " "sanne lederen han møter." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Du har møtt pÃ¥ en snodig type med en hatt som har en ugle pÃ¥ seg. Han " "forteller deg at han er villig til Ã¥ gi deg skatten %{art} hvis du kan " "%{skill}" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Du kommer over en skatt fra oldtiden. Idet du strekker deg fram for Ã¥ ta " "den, hopper en gjeng banditter ut fra buskene for Ã¥ beskytte det som " "antakeligvis er tyvegodset deres." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Gjennom en klarning fÃ¥r du øye pÃ¥ en verdifull gjenstand fra oldtiden. " "Dessverre er den bevoktet av 1 %{monster} like ved.\n" "Ønsker du Ã¥ kjempe mot 1 %{monster} for den verdifulle gjenstanden?" msgid "Victorious, you take your prize, the %{art}." msgstr "" "Seirende griper du premien din, som er den verdifulle gjenstanden:\n" "%{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "Du velger varsomhet framfor dumdristighet og unngÃ¥r denne kampen for i dag." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Etter Ã¥ ha strevd i timesvis med Ã¥ fiske opp kista fra havet, Ã¥pner du den " "og finner %{gold} gullstykker." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Etter Ã¥ ha strevd i timesvis med Ã¥ fiske opp kista fra havet, Ã¥pner du den " "og finner %{gold} gullstykker og skatten: %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Etter Ã¥ ha strevd i timesvis med Ã¥ fiske opp kista fra havet, Ã¥pner du den " "kun for Ã¥ finne ut at den er tom." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Etter Ã¥ ha gjennomsøkt omrÃ¥det kommer du over ei bortgjemt skattekiste. Du " "kan enten ta gullet selv, eller dele det ut til fattige bønder imot " "erfaringspoeng.\n" "Vil du beholde gullet?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Etter Ã¥ ha gjennomsøkt omrÃ¥det kommer du over ei bortgjemt skattekiste som " "inneholder %{gold} gullstykker." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Etter Ã¥ ha gjennomsøkt omrÃ¥det kommer du over ei bortgjemt skattekiste. Den " "inneholder en verdifull gjenstand fra oldtiden:\n" "%{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Du snubler over en bulkete og tilskitnet lampe gravd dypt ned i bakken.\n" "Vil du gni pÃ¥ den?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Du tar kontroll over den lokale alkymistforretningen. Den vil gi deg " "%{count} enhet kvikksølv hver dag." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Du tar kontroll over et sagbruk. Det vil gi deg %{count} enheter ved hver " "dag." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Du tar kontroll over ei malmgruve. Den vil gi deg %{count} enheter malm hver " "dag." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Du tar kontroll over ei svovelgruve. Den vil gi deg %{count} enhet svovel " "hver dag." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Du tar kontroll over ei krystallgruve. Den vil gi deg %{count} enhet " "krystall hver dag." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Du tar kontroll over ei edelstensgruve. Den vil gi deg %{count} enhet " "edelsten hver dag." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Du tar kontroll over ei gullgruve. Den vil gi deg %{count} gullstykker hver " "dag." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "FyrtÃ¥rnet er herved under din kontroll og alle skipene dine vil fra nÃ¥ av " "kunne flytte seg lengre hver dag." msgid "You gain control of a %{name}." msgstr "Du tar kontroll over en %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Du kommer over ei forlatt gullgruve. Gruva ser ut til Ã¥ være hjemsøkt.\n" "Vil du gÃ¥ inn?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Du fordriver gjenferdene og fÃ¥r satt gruva tilbake i drift." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "En gruppe %{monster} med en drøm om heder og ære ønsker Ã¥ bli med deg.\n" "Godtar du?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" "Idet du kommer nærmere bostedet, legger du merke til at det er forlatt." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Du leter gjennom ruinene, men medusaene som pleide Ã¥ leve her ikke er her " "lenger. Kanskje det kommer flere neste uke." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Du møter pÃ¥ noen medusaer som bor i ruinene. De er villige til Ã¥ bli med i " "hæren din for en penge.\n" "Ønsker du Ã¥ verve medusaer?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Du fant en treby for feer. Dessverre vil ingen av feene som bor der bli med " "i hæren din. Kanskje neste uke." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Noen av feene som bor i trebyen er villige til Ã¥ bli med i hæren din for en " "penge. Ønsker du Ã¥ verve feer?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Det stÃ¥r en fargerik men tom røverkjerre her. Kanskje det vil komme røvere " "hit senere." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Musikk og latter i det fjerne lokker deg til en fargerik kjerre der det " "viser seg at røvere holder til.\n" "Vil du Ã¥ ha røvere i hæren din?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "En samling utslitte telt som bølger i den sandete vinden kaller deg mot seg. " "Teltene er tomme. Kanskje flere nomader kommer hit senere." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "En samling utslitte telt bølger i ørkenvinden og lokker deg til seg.\n" "Ønsker du Ã¥ ta med deg noen nomader pÃ¥ ferden din?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Pytten bobler litt i et minutt før den stilner til." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Idet du kommer nærmere lavapytten begynner skapninger Ã¥ krype ut og stille " "seg opp rundt den. I ett sier de: \"Moderjord ønsker Ã¥ tilby deg noen av " "sine krigere. Ønsker du Ã¥ verve jordÃ¥nder?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" "Du gÃ¥r inn i bygningen med de hvite steinsøylene, men du finner ingenting." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Hvite steinsøyler støtter opp under et tak som gÃ¥r høyt opp mot himmelen. " "Idet du gÃ¥r inn blir den stille luften pÃ¥ utsiden brÃ¥tt om til et virvlende " "vindkast som nesten slenger deg ut igjen. Luftstrømmen forvandler seg til en " "nesten gjennomsiktig skikkelse. Den spør, med en stemme som bare kan " "beskrives som høy visking: \"Hva bringer deg hit? Er du her for Ã¥ tilkalle " "luftens krefter?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Ingen av ildÃ¥ndene kommer imot deg fra lavadammen." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Under et varmefangende byggverk beveger ildÃ¥nder seg i en ildfull dam av " "lava. En gruppe kommer bort til deg og tilbyr deg Ã¥ bli med i hæren din. \n" "Ønsker du Ã¥ verve ildÃ¥nder?" msgid "A face forms in the water for a moment, and then is gone." msgstr "" "For et kort øyeblikk dukker et ansikt opp av vannet, før det sÃ¥ forsvinner." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Mektige krystaller kaster skygger over en liten blank vanndam. Du stirrer " "ned pÃ¥ vannspeilet og plutselig stirrer et annet ansikt tilbake pÃ¥ deg.\n" "Det spør deg: \"Ønsker du Ã¥ tilkalle vannets krefter?\"" msgid "This burial site is deathly still." msgstr "Gravstedet er dødsens rolig." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "De urolige sjelene til for lengst døde krigere søker deres endelige " "hvilested, og de tilbyr deg Ã¥ bli med i hæren din i hÃ¥p om Ã¥ endelig kunne " "finne fred.\n" "Vil du verve gjenferd?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "Dødens by er helt uten liv, og helt uten uliv ogsÃ¥. Kanskje noen vandøde vil " "flytte inn neste uke." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Noen heksekonger som holder til her er villige til Ã¥ bli med i hæren din " "imot en pris. Ønsker du Ã¥ verve heksekonger?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Du har funnet ruinene til en by fra oldtiden. Den er nÃ¥ kun bebodd av " "vandøde.\n" "Vil du lete gjennom den?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Noen av de overlevende heksekongene ble imponert over seieren din mot brødre " "deres, og de tilbyr Ã¥ bli med deg mot et beløp. Ønsker du Ã¥ verve " "heksekonger?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Du kommer over typisk bru som troll liker Ã¥ bosette seg under, men stedet er " "forlatt. Kanskje det kommer noen neste uke." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Noen troll som bor under ei bru er villige til Ã¥ bli med i hæren din, men " "imot et beløp. Ønsker du Ã¥ verve troll?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Trollene som bor under brua utfordrer deg til kamp. Vil du kjempe mot dem?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Noen fÃ¥ livredde troll som er igjen gjemmer seg under brua. De kommer " "forsiktig ut og tilbyr deg Ã¥ bli med i styrken din som leiesoldater.\n" "Ønsker du Ã¥ kjøpe troll?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "Dragenes landsby har ingen drager som er villige til Ã¥ bli med deg denne " "uka. Kanskje det kommer flere drager neste uke." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Dragenes landsby er villig til Ã¥ tilby noen drager for hæren din imot en " "pris. Ønsker du Ã¥ verve drager?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Du stÃ¥r overfor Dragenes landsby, et forbudt sted for vanlige mennesker.\n" "Tør du Ã¥ trosse denne regelen og utfordre dragene til kamp?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "NÃ¥ som du har slÃ¥tt mestrene av dragene, gÃ¥r byens ledere med pÃ¥ Ã¥ tilby deg " "noen drager til hæren din imot en penge. Ønsker du Ã¥ verve drager?" msgid "From the observation tower, you are able to see distant lands." msgstr "Du kan se fjerntliggende land fra utkikkstÃ¥rnet." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Vannkilden fÃ¥r kun pÃ¥fyll én gang i uka, og noen har allerede vært her denne " "uka." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "En slurk fra kilden skal egentlig gi deg dobbelt sÃ¥ mye mana, men du har det " "allerede." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "En slurk fra kilden fÃ¥r blodet ditt til Ã¥ strømme av magi! Du har nÃ¥ dobbelt " "sÃ¥ mye mana som du har til vanlig." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Etter Ã¥ ha gjenkjent deg nekter hovmesteren Ã¥ slippe deg inn. \"Herren,\" " "sier han, \"ønsker ikke Ã¥ møte den samme eleven to ganger.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Hovmesteren slipper deg inn for Ã¥ møte herren av huset. Han trener deg opp i " "de fire egenskapene en hver helt burde ha." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Hovmesteren Ã¥pner døra og skuer deg opp og ned. \"Du er verken berømt eller " "veltalende nok til Ã¥ fÃ¥ tillatelse til Ã¥ møte herren min,\" fnyser han. " "\"Kom tilbake nÃ¥r du er verdig.\"" msgid " and " msgstr " og " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Alt du hadde av %{monsters} i hæren din har blitt trent opp av fortets " "kampmestre. Disse har nÃ¥ blitt til %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "En usedvanlig allianse av orker, jetter og dverger tilbyr Ã¥ trene opp " "(oppgradere) det du har av samme krigere som dem. Dessverre har du ingen " "slike i hæren din." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Alle dine %{monsters} har blitt oppgradert til %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Smeden som driver støperiet tilbyr deg Ã¥ gjøre om alle jernvÃ¥pnene til " "pikenérene og sverdmennene dine til stÃ¥l. Han sier at han ogsÃ¥ vet hvordan " "man kan gjøre jerngolemer om til stÃ¥lgolemer. Dessverre har du ingen slike i " "hæren din, sÃ¥ det er ingenting han kan gjøre for deg." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Kapteinen ser overrasket pÃ¥ deg og sier:\n" "\"Du har allerede fÃ¥tt det eneste kartet jeg hadde. La meg fÃ¥ fiske i fred " "nÃ¥.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Kapteinen som bor pÃ¥ denne velkonstruerte fiskeflÃ¥ta tilbyr deg et komplett " "kart over havet fra hans yngre dager. Han tilbyr deg det for 1000 " "gullstykker.\n" "Vil du kjøpe kartet av ham?" #, fuzzy msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Kapteinen sukker. \"Du har ikke nok penger, hva? Du kan ikke forvente at jeg " "skal gi fra meg kartet gratis!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Du kommer over en obelisk laget av en bergart du aldri før har sett. Mens du " "skuer over den dannes det plutselig et innriss pÃ¥ dens tidligere glatte " "overflate. Innrisset viser et stykke av et eldgammelt, fortapt kart. Du " "skynder deg Ã¥ skissere ned kartet og rekker sÃ¥ vidt Ã¥ bli ferdig før det " "forsvinner like brÃ¥tt som det dukket opp." msgid "You have already been to this obelisk." msgstr "Du har allerede besøkt denne obelisken." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Du kommer til et tre som Ã¥pner et par øyne i glede idet det ser deg komme " "nærmere. \"Det er godt Ã¥ se deg, min elev. Jeg hÃ¥per lærdommen min har " "hjulpet deg.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Du kommer til et tre som Ã¥pner et par øyne i glede idet det ser deg komme " "nærmere. \"Oi, en eventyrer! Tillat meg Ã¥ lære deg litt av hva jeg har lært " "gjennom tidene.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "" "Du kommer til et tre som Ã¥pner et par øyne i glede idet det ser deg komme " "nærmere." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Oi, en eventyrer! Jeg skal gledelig lære deg litt av hva jeg har lært opp " "gjennom tidene for bare %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Bare grav det ned ved røttene mine)" msgid "Tears brim in the eyes of the tree." msgstr "TÃ¥rer ligger i øyekroken til treet." msgid "\"I need %{count} %{res}.\"" msgstr "\"Jeg trenger %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" "visker det mens det snufser, \"Vel, kom tilbake nÃ¥r du kan betale meg.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "En blind spÃ¥mann har slÃ¥tt seg til rede i et tre du oppdager ham i. Etter Ã¥ " "ha forklart ham hensikten med reisen din, tar spÃ¥mannen fram krystallkula " "si. Den lar deg se styrkene og svakhetene til motstanderne dine." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Inngangen til hula er bekmørk, og en fæl eggete lukt oser ut av munningen " "til den.\n" "Vil du gÃ¥ inn?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Sett bort ifra sporene etter et fryktelig slag er hula tom." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Du finner en sterk og ufyselig djevel i hula. Med en skjærende stemme sier " "den: \"I dag,\" og den trekker pusten, \"skal du kjempe, og du vil uten tvil " "dø. Men, jeg skal la deg fÃ¥ velge hvordan du vil dø. Du kan enten kjempe mot " "meg, eller mot lakeiene mine.\n" "Blir det lakeiene?" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Djevelen gir fra seg et vræl og angriper! Etter en kort og stusslig kamp, " "tar du livet av beistet. Du fÃ¥r %{exp} erfaringspoeng." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Djevel skriker i været og angriper! Etter en kort og stusslig kamp dreper du " "monsteret. Du fÃ¥r %{exp} erfaringspoeng og %{count} gullstykker." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Djevel skriker i været og angriper! Etter en kort og stusslig kamp dreper du " "monsteret. Du finner %{art} i enden av hula." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Etter Ã¥ ha innsett at du ikke eier %{count} gullstykker hugger djevelen til " "deg med klørene sine, og det siste du ser er en rød tÃ¥ke." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Djevelen hopper pÃ¥ deg og har klørne sine pÃ¥ strupen din før du engang " "rekker Ã¥ dra sverdet ditt. \"Livet ditt ligger i mine klør nÃ¥,\" sier den. " "\"Du skal fÃ¥ beholde det imot %{count} gullstykker.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Etter Ã¥ ha slÃ¥tt lakeiene til djevelen finner du et skjult lager med " "%{count} gullstykker." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Idet du kommer inn i alkymistens tÃ¥rn kommer en haltende grÃ¥ mann med brun " "kappe mot deg." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Han sjekker sekken din og ser at du har 1 forhekset gjenstand." msgstr[1] "" "Han sjekker sekken din og ser at du har %{count} forheksede gjenstander." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "For %{gold} gullstykker tilbyr alkymisten Ã¥ fjerne den for deg. Vil du " "betale?" msgstr[1] "" "For %{gold} gullstykker tilbyr alkymisten Ã¥ fjerne dem for deg. Vil du " "betale?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "SÃ¥ snart du gÃ¥r med pÃ¥ Ã¥ betale den forespurte mengden gull, tar alkymisten " "tak i den forbannede gjenstanden din og hiver den i den magiske gryta si." msgstr[1] "" "SÃ¥ snart du gÃ¥r med pÃ¥ Ã¥ betale den forespurte mengden gull tar alkymisten " "tak i alle de forbannede gjenstandene dine og kaster dem i den magiske gryta " "si." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Du hører en stemme fra de lukkede dørene, \"Du har ikke nok gull til Ã¥ " "betale for tjenestene mine.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Du hører en stemme fra høyt oppe i tÃ¥rnet: \"GÃ¥ vekk! Jeg kan ikke hjelpe " "deg!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Stallmesteren kommer mot deg og sier, \"Det er en flott hest du har. Jeg er " "redd for at jeg ikke kan gi deg noe bedre, men hestene rytterne dine rir pÃ¥ " "ser ut til Ã¥ være av en dÃ¥rlig avl. Vi har mange trente stridshester som vil " "hjelpe rytterne dine enormt. Jeg insisterer pÃ¥ at du tar dem.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Idet du ankommer stallen dukker stallmesteren opp, og han har med seg en " "flott stridshest. \"Denne hingsten vil fÃ¥ fart pÃ¥ deg i reisene dine. " "Dessverre vil hesten bli utmattet om ei uke. Du mÃ¥ ogsÃ¥ la meg gi deg bedre " "hester til dine ridende soldater. Hestene deres ser slitne og svake ut." msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Stallmesteren kommer mot deg og sier, \"Du har allerede en fin hest og har " "ingen uerfarne ryttere som kan dra nytte av vÃ¥re trente stridshester.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Idet du ankommer stallen dukker stallmesteren opp med en flott stridshest. " "\"Denne hingsten vil bringe deg fort fram pÃ¥ reisene dine. Dessverre vil den " "etter hvert bli utslitt. Om ei uke kan du komme tilbake og fÃ¥ en ny hest. Vi " "har ogsÃ¥ mange flotte stridshester for ridende krigere, men det har du ingen " "av i hæren din.\"" msgid "The Arena guards turn you away." msgstr "Vokterne av arenaen avviser deg." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Du fÃ¥r mannskapet ditt til Ã¥ tette ørene sine med voks før sirenenes " "uhyggelige sang fÃ¥r muligheten til Ã¥ lokke dem ut til en vÃ¥t grav." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Mens sirenene synger deres uhyggelige sang, klarer din lille men mÃ¥lrettede " "hær Ã¥ motstÃ¥ fristelsen til Ã¥ stupe med hodet først i sjøen." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "En ulende og nifs sang kommer fra sirenene pÃ¥ svaberget. Flere av mannskapet " "ditt blir offer for forhekselsen deres og stuper ut i sjøen hvor de drukner. " "Du kommer helberget ut av hendelsen med ny lærdom og %{exp} erfaringspoeng." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "I en imponerende framvisning av mot bryter du deg inn i det lokale fengselet " "og frigjør den innesperrede helten der. Til gjengjeld sverger helten troskap " "til din sak." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Du har allerede %{count} helter, og du blir nødt til Ã¥ forlate fangen i " "fengselet for Ã¥ tæres av smertende lengsel i utallige dager." # fjernt og nært? # magician ? Betyr ofte tryllekunstner pÃ¥ engelsk. msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Du gÃ¥r inn i ei skrøpelig hytte og snakker med spÃ¥mannen som bor der. Han " "forteller deg om steder fjerne og nære. Dette vil kunne komme til nytte pÃ¥ " "reisene dine." msgid "This eye seems to be intently studying its surroundings." msgstr "Dette øyet ser ut til Ã¥ følge oppmerksomt med pÃ¥ omgivelsene sine." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Du kommer over en stor sfinks. Sfinksen forblir merkverdig nok stille." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Jeg har en gÃ¥te til deg,\" sier sfinksen. \"Svar riktig, og du vil bli " "belønnet. Svar galt, og du vil bli spist levende. Tar du imot utfordringen?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Sfinksen stiller deg den følgende gÃ¥ten :\n" "\n" "\"%{riddle}\n" "\n" "Ditt svar?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Du gjettet feil\", sier sfinksen med et lurt smil før den denger til deg " "med en av potene sine slik at du gÃ¥r rett i bakken. Nok et slag treffer deg, " "og det svartner. Mer fÃ¥r du ikke med deg." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Tilsynelatende litt skuffet, sukker Sfinksen: \"Du klarte Ã¥ løse gÃ¥ten min, " "sÃ¥ her er belønningen din. NÃ¥ forsvinn.\"." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "En magisk barriere rager foran deg og blokkerer veien. Runene pÃ¥ buen dens " "sier det følgende:\n" "\"Uttal nøkkelordet og du vil fÃ¥ komme forbi.\"\n" "Idet du roper ut det magiske ordet gÃ¥r den glødende barrieren i oppløsning." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "En magisk barriere rager foran deg og blokkerer veien. Runene pÃ¥ buen dens " "sier,\n" "\"Uttal nøkkelordet og du vil fÃ¥ komme forbi.\"\n" "Du taler, men ingenting skjer." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Du gÃ¥r inn i teltet og ser en gammel dame som stirrer inn i en magisk " "edelsten. Hun ser opp og sier:\n" "\"PÃ¥ vandringene mine har jeg lært mye om mørkets kunster. Jeg har gÃ¥tt i " "læren hos et dyktig orakel. Du skal fÃ¥ svaret du søker.\"" msgid "No spell book is present." msgstr "Det fins ingen tryllebok." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Denne trolldommen koster %{mana} magipoeng. Du har null magipoeng, sÃ¥ du kan " "ikke bruke denne trolldommen." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Denne trolldommen koster %{mana} magipoeng. Du har kun %{point} magipoeng, " "sÃ¥ du kan ikke bruke denne trolldommen." msgid "The spell was not found." msgstr "Trolldommen ble ikke funnet." msgid "Only heroes can cast this spell." msgstr "Kun helter kan bruke denne trolldommen." msgid "This hero is not able to cast adventure spells." msgstr "Denne helten er ikke i stand til Ã¥ bruke kartmagi." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Din helt er for sliten til Ã¥ bruke denne trolldommen i dag. Prøv igjen i " "morgen." msgid "This spell cannot be cast on a boat." msgstr "Denne trolldommen kan ikke brukes pÃ¥ et skip." msgid "This spell can only be cast near an ocean." msgstr "Denne trolldommen kan kun bli brukt i nærheten av sjø." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Det er ingen skip tilgjengelige eller sjø i nærheten av helten hvor denne " "trolldommen vil virke." msgid "There are no boats available for this spell." msgstr "Ingen skip er tilgjengelige for denne trolldommen." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Det er ingen sjø i umiddelbar nærhet av helten hvor denne trolldommen kan " "brukes." #, fuzzy msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Du eier ingen byer eller borger som ikke har besøk av andre helter for " "øyeblikket. Du kan ikke bruke denne trolldommen." #, fuzzy msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Denne helten befinner seg allerede i en by, og dermed kan ikke denne " "trolldommen brukes." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Den nærmeste byen er %{town}.\n" "\n" "Denne byen er blokkert av helten din %{hero}." msgid "This spell is already in effect." msgstr "Denne trolldommen er allerede i virkning." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Ingen av motstanderne dine har eller vil kunne ha helter under sitt befal " "lenger, og dermed vil ikke denne trolldommen ha noen virkning." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Ingen av motstanderne dine har helter under sitt befal for øyeblikket, og " "dermed vil ikke denne trolldommen ha noen virkning." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Du mÃ¥ være innenfor %{count} ruter av et monster for at trolldommen 'Syner' " "skal virke." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Du mÃ¥ stÃ¥ ved inngangen til en gruve (sagbruk og alkymistlaber telles ikke) " "for Ã¥ bruke denne trolldommen." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Du mÃ¥ først fordrive spøkelsene som vokter over gruven for Ã¥ bruke denne " "trolldommen." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Det befinner seg alt minst like mange elementærÃ¥nder som denne helten kan " "tilkalle her. Ã… bruke denne trolldommen vil være uten nytte." msgid "%{name} the %{race} (Level %{level})" msgstr "%{race}en %{name} (level %{level})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} (Level %{level})" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{race}en %{name} (level %{level})" #, fuzzy msgid "Hero race:" msgstr "Heltevindu" msgid "Are you sure you want to dismiss this Hero?" msgstr "Er du sikker pÃ¥ at du ønsker Ã¥ bortvise denne helten?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Vis erfaringsinfo" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Mana" msgid "View Spell Points Info" msgstr "Vis info om mana" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Mist helten kalt %{name}." #, fuzzy msgid "Click to change race." msgstr "Klikk for Ã¥ vise neste by." #, fuzzy msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "\"Spredd\" kampoppstilling sprer styrkene dine fra topp til bunn av " "slagmarken med minst ett ledig felt mellom hver enkelt tropp." #, fuzzy msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "\"Gruppert\" kampoppstilling setter styrkene dine tett sammen i midten av " "din side av slagmarken." msgid "Exit Hero Screen" msgstr "GÃ¥ ut av heltevinduet" msgid "You cannot dismiss a hero in a castle" msgstr "Du kan ikke bortvise en helt i en borg" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Bortvisning av %{race}en %{name} er forbudt pÃ¥ dette kartet" msgid "Dismiss %{name} the %{race}" msgstr "Bortvis %{race}en %{name}" msgid "Show previous hero" msgstr "Vis forrige helt" msgid "Show next hero" msgstr "Vis neste helt" msgid "Set army combat formation to 'Spread'" msgstr "Sett hærens kampoppstilling til \"Spredd\"" msgid "Set army combat formation to 'Grouped'" msgstr "Sett hærens kampoppstilling til \"Gruppert\"" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Klikk her for Ã¥ velge hvilket kart du vil spille." msgid "Blood Morale" msgstr "BlodskampÃ¥nd" msgid "%{morale} Morale" msgstr "%{morale} kampÃ¥nd" msgid "%{luck} Luck" msgstr "%{luck} flaks" msgid "Current Luck Modifiers:" msgstr "PÃ¥virkninger pÃ¥ flaksen:" msgid "Current Morale Modifiers:" msgstr "PÃ¥virkninger pÃ¥ kampÃ¥nden:" msgid "Entire army is undead, so morale does not apply." msgstr "Hele hæren er vandød sÃ¥ kampÃ¥nd gjelder ikke." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "NÃ¥værende erfaring: %{exp1}.\n" "Neste level: %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Level %{level}" #, fuzzy msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} har for øyeblikket %{point} av maks %{max} mana. Den maksimal manaen " "til en helt er 10 ganger kunnskapen til helten. I visse tilfeller kan helten " "ha mer enn den maksimale manaen." msgid "%{name1} meets %{name2}" msgstr "%{name1} møter %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "De fiendtlige heltene er nÃ¥ helt kartlagte." msgid "Identify Hero" msgstr "Kartlegg helt" msgid "Select town to port to." msgstr "Velg by Ã¥ reise til." msgid "Town Portal" msgstr "Byportal" msgid "The creatures are willing to join us!" msgstr "Krigerne er villige til Ã¥ slÃ¥ seg til oss!" msgid "All the creatures will join us..." msgstr "Alle krigerne kommer til Ã¥ ville slÃ¥ seg til oss..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Krigeren vil bli med oss..." msgstr[1] "%{count} krigere vil bli med oss..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "imot en pris pÃ¥ %{gold} gullstykker." msgid "These weak creatures will surely flee before us." msgstr "Disse svake krigerne vil uten tvil flykte fra oss." msgid "I fear these creatures are in the mood for a fight." msgstr "Jeg er redd for at disse krigerne er ute etter en kamp." #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "Angrepsevnen til helten din legges til angrepsevnen til krigerne dine." #, fuzzy msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Forsvarsevnen til helten din legges til forsvarsevnen til krigerne dine." #, fuzzy msgid "The hero's spell power determines the duration or power of a spell." msgstr "Kraften din bestemmer varigheten og styrken til trolldommene dine." #, fuzzy msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Kunnskapen din bestemmer hvor mye mana helten din kan ha. Vanligvis er en " "helt begrenset til 10 mana per kunnskapsnivÃ¥." msgid "Current Modifiers:" msgstr "PÃ¥virkninger:" msgid "skill|Basic" msgstr "Enkel" msgid "skill|Advanced" msgstr "Forbedret" msgid "skill|Expert" msgstr "Ekspert" msgid "Pathfinding" msgstr "Kartlesing" msgid "Archery" msgstr "Skyting" # Transport? Varelevering? Forsyninger? msgid "Logistics" msgstr "Logistikk" msgid "Scouting" msgstr "Speiding" msgid "Diplomacy" msgstr "Megling" msgid "Navigation" msgstr "Skipsfart" msgid "Leadership" msgstr "Lederskap" msgid "Wisdom" msgstr "Visdom" msgid "Mysticism" msgstr "Mystikk" msgid "Ballistics" msgstr "Ballistikk" msgid "Eagle Eye" msgstr "Ørneblikk" msgid "Necromancy" msgstr "Sortekunst" # Eiendomsinvestering. msgid "Estates" msgstr "Investering" msgid "Advanced Archery" msgstr "Forbedret skyting" msgid "Advanced Pathfinding" msgstr "Forbedret kartlesing" msgid "Basic Archery" msgstr "Enkel skyting" msgid "Basic Pathfinding" msgstr "Enkel kartlesing" msgid "Expert Pathfinding" msgstr "Ekspert kartlesing" msgid "Advanced Logistics" msgstr "Forbedret logistikk" msgid "Basic Logistics" msgstr "Enkel logistikk" msgid "Basic Scouting" msgstr "Enkel speiding" msgid "Expert Archery" msgstr "Ekspert skyting" msgid "Expert Logistics" msgstr "Ekspert logistikk" msgid "Advanced Diplomacy" msgstr "Forbedret megling" msgid "Advanced Scouting" msgstr "Forbedret speiding" msgid "Basic Diplomacy" msgstr "Enkel megling" msgid "Expert Diplomacy" msgstr "Ekspert megling" msgid "Expert Scouting" msgstr "Ekspert speiding" msgid "Advanced Leadership" msgstr "Forbedret lederskap" msgid "Advanced Navigation" msgstr "Forbedret skipsfart" msgid "Basic Leadership" msgstr "Enkelt lederskap" msgid "Basic Navigation" msgstr "Enkel skipsfart" msgid "Expert Navigation" msgstr "Ekspert skipsfart" msgid "Advanced Wisdom" msgstr "Forbedret visdom" msgid "Basic Mysticism" msgstr "Enkel mystikk" msgid "Basic Wisdom" msgstr "Enkel visdom" msgid "Expert Leadership" msgstr "Ekspert lederskap" msgid "Expert Wisdom" msgstr "Ekspert visdom" msgid "Advanced Luck" msgstr "Forbedret flaks" msgid "Advanced Mysticism" msgstr "Forbedret mystikk" msgid "Basic Luck" msgstr "Enkel flaks" msgid "Expert Luck" msgstr "Ekspert flaks" msgid "Expert Mysticism" msgstr "Ekspert mystikk" msgid "Advanced Ballistics" msgstr "Forbedret ballistikk" msgid "Advanced Eagle Eye" msgstr "Forbedret ørneblikk" msgid "Basic Ballistics" msgstr "Enkel ballistikk" msgid "Basic Eagle Eye" msgstr "Enkelt ørneblikk" msgid "Expert Ballistics" msgstr "Ekspert ballistikk" msgid "Advanced Necromancy" msgstr "Forbedret sortekunst" msgid "Basic Estates" msgstr "Enkel investering" msgid "Basic Necromancy" msgstr "Enkel sortekunst" msgid "Expert Eagle Eye" msgstr "Ekspert ørneblikk" msgid "Expert Necromancy" msgstr "Ekspert sortekunst" msgid "Advanced Estates" msgstr "Forbedret investering" msgid "Expert Estates" msgstr "Ekspert investering" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "%{skill} minsker tap av skritt pÃ¥ ulendt terreng med %{count} prosent." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} fjerner all tap av skritt pÃ¥ ulendt terreng." #, fuzzy msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} fjerner minskningen pÃ¥ %{count} prosent av skaden troppene dine gjør " "nÃ¥r de skyter pÃ¥ tvers av hindringer\n" "(f.eks. forbi ringmurer)." #, fuzzy msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} øker skrittene til helten din med %{count} prosent." #, fuzzy msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} utvider sikten til helten din med én rute." msgstr[1] "%{skill} utvider sikten til helten din med %{count} ruter." #, fuzzy msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} gjør at du kan forhandle med hærstyrker som er svakere enn din " "egen. " #, fuzzy msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Rundt %{count} prosent av en nøytral motstanderstyrke vil kunne tilby Ã¥ bli " "med deg." #, fuzzy msgid "All of the creatures may offer to join the hero." msgstr "En hel nøytral motstanderstyrke vil kunne tilby Ã¥ bli med deg." #, fuzzy msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "%{name} reduserer prisen for Ã¥ overgi seg med %{count} prosent av den totale " "verdien av hærstyrken din." #, fuzzy msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "%{skill} øker helten din sine skritt til sjøs med %{count} prosent." #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} bedrer kampÃ¥nden til krigerne dine med %{count}." #, fuzzy msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} lar helten din lære seg trolldommer av tredje nivÃ¥." #, fuzzy msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} lar helten din lære seg trolldommer av fjerde nivÃ¥." #, fuzzy msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} lar helten din lære seg trolldommer av femte nivÃ¥." #, fuzzy msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} fyller opp ett manapoeng for helten din per dag." msgstr[1] "" "%{skill} fyller opp %{count} ekstra manapoeng for helten din per dag." #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} øker hæren din sin flaks med %{count}." #, fuzzy msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} gjør at skuddene til katapulten din har større sjanse for Ã¥ treffe " "og dermed skade ringmuren til borgene." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} gir katapulten til helten din et ekstra skudd, og hvert skudd har " "en større sjanse til Ã¥ treffe og skade ringmuren til en borg." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} gir katapulten til helten din et ekstra skudd, og hvert skudd " "ødelegger en del av ringmuren, bortsett fra pÃ¥ en ridderborg med " "befestninger." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} gir helten din %{count} prosent sjanse til Ã¥ lære første eller " "andre nivÃ¥s trolldommer som blir brukt mot krigerne dine i kamp." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} gir helten din %{count} prosent sjanse til Ã¥ lære en av fiendens " "trolldommer av tredje nivÃ¥ (eller lavere) som blir brukt mot krigerne dine i " "kamp." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} gir helten din %{count} prosent sjanse til Ã¥ lære en av fiendens " "trolldommer av fjerde nivÃ¥ (eller lavere) som blir brukt mot krigerne dine i " "kamp." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} gjør at %{count} prosent av krigerne som faller i kamp blir brakt " "tilbake fra de døde i form av skjeletter." #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Helten tjener %{count} gullstykker pÃ¥ daglige skatteinntekter fra faste " "eiendommer." msgid "Blue" msgstr "BlÃ¥" msgid "Green" msgstr "Grønn" msgid "Red" msgstr "Rød" msgid "Yellow" msgstr "Gul" msgid "Orange" msgstr "Oransje" msgid "Purple" msgstr "Lilla" msgid "barrier|Aqua" msgstr "LyseblÃ¥" msgid "barrier|Blue" msgstr "BlÃ¥" msgid "barrier|Brown" msgstr "Brun" msgid "barrier|Gold" msgstr "Gullfarget" msgid "barrier|Green" msgstr "Grønn" msgid "barrier|Orange" msgstr "Oransje" msgid "barrier|Purple" msgstr "Lilla" msgid "barrier|Red" msgstr "Rød" msgid "tent|Aqua" msgstr "LyseblÃ¥tt" msgid "tent|Blue" msgstr "BlÃ¥tt" msgid "tent|Brown" msgstr "Brunt" msgid "tent|Gold" msgstr "Gullfarget" msgid "tent|Green" msgstr "Grønt" msgid "tent|Orange" msgstr "Oransje" msgid "tent|Purple" msgstr "Lilla" msgid "tent|Red" msgstr "Rødt" msgid "Experience" msgstr "Erfaringspoeng" #, fuzzy msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Erfaringspoeng gjør at helten din kan gÃ¥ opp i level. Det vil forbedre " "heltens hovedferdigheter og sideferdigheter." msgid "Hero/Stats" msgstr "Helt/Egenskaper" msgid "Skills" msgstr "Evner" msgid "Town/Castle" msgstr "By/Borg" msgid "Garrison" msgstr "Garnison" msgid "Gold Per Day:" msgstr "Gull per dag:" msgid "View Heroes." msgstr "Vis helter." msgid "Towns/Castles" msgstr "Byer/Borger" msgid "View Towns and Castles." msgstr "Vis byer og borger." msgid "luck|Cursed" msgstr "Forbannet" msgid "luck|Awful" msgstr "Elendig" msgid "luck|Bad" msgstr "DÃ¥rlig" msgid "luck|Normal" msgstr "Normal" msgid "luck|Good" msgstr "God" msgid "luck|Great" msgstr "GullhÃ¥r" msgid "luck|Irish" msgstr "Heldiggris" #, fuzzy msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Uflaks kan av og til føre til at styrkene dine kun skader halvparten av det " "vanlige." #, fuzzy msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Nøytral flaks gjør at styrkene dine aldri vil fÃ¥ heldige eller uheldige slag " "nÃ¥r de angriper fienden." #, fuzzy msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Positiv flaks gjør at styrkene dine av og til gjør heldige slag (dobbel " "skade) i kamp." msgid "morale|Treason" msgstr "Forræderi" msgid "morale|Awful" msgstr "Elendig" msgid "morale|Poor" msgstr "DÃ¥rlig" msgid "morale|Normal" msgstr "Normal" msgid "morale|Good" msgstr "God" msgid "morale|Great" msgstr "Ypperlig" msgid "morale|Blood!" msgstr "Blod!" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "Negativ kampÃ¥nd kan føre til at styrkene dine stivner til av panikk i kamp." #, fuzzy msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Nøytral kampÃ¥nd betyr at styrkene dine aldri verken vil bli velsignet med en " "ekstra tur eller stivne til av panikk i kamp." #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Positiv kampÃ¥nd kan av og til gi styrkene dine en ekstra tur i kamp." msgid "Knight" msgstr "Ridder" msgid "Barbarian" msgstr "Barbar" # Heks brukes allerede som Witch i witch hut. Trollkvinne er best men passer ikke med formatet og bestemtformsbøyningen til # de andre rasene. Feks. Trollkvinne(en) "heltenavn". msgid "Sorceress" msgstr "Trollkjerring" msgid "Warlock" msgstr "Trollmann" # Magiker blir allerede brukt om mage: # Wizard kommer av wise og betegner en som har studert mye for Ã¥ bli flink. # Vurder vismann og visdame nÃ¥r det blir mulig med tittel for hvert kjønn. Slaget/tilhørigheten kan kalles visfolk. # Alternativer: Allviter (kjønnsnøytral), trolldomslærd fortryller, vismenneske, filosof, tryllemester, lærd, tryllelærd, # alkymist (siden de lager golemer), magilærd, trylleviter, Magiviter, trolldomsviter (litt mange slag med trolldom i navnet.) # Hvitkunstner siden de er pÃ¥ den gode siden og en slags motsetning til sortekunstnerne. Merk: Tryllekunstner er profesjonen # som gjør synsbedrageri osv. msgid "Wizard" msgstr "Magimester" msgid "Necromancer" msgstr "Sortekunstner" msgid "Multi" msgstr "Flere" msgid "doubleLined|Knight" msgstr "Ridder" msgid "doubleLined|Barbarian" msgstr "Barbar" # Heks brukes allerede som Witch i witch hut. Trollkvinne er best men passer ikke med formatet og bestemtformsbøyningen til # de andre rasene. Feks. Trollkvinne(en) "heltenavn". msgid "doubleLined|Sorceress" msgstr "" "Troll-\n" "kjerring" msgid "doubleLined|Warlock" msgstr "" "Troll-\n" "mann" msgid "doubleLined|Wizard" msgstr "" "Magi-\n" "mester" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Sorte-\n" "kunstner" msgid "doubleLinedRace|Multi" msgstr "Flere" msgid "doubleLinedRace|Random" msgstr "Tilfeldig" # StillestÃ¥ende (for lang), bomstille. msgid "speed|Standing" msgstr "Bomfast" # Sneglefart? Sneglende? Krypende, krÃ¥lende, smygende, langsom msgid "speed|Crawling" msgstr "Snegle" # Veldig sein blir for langt. maks 9 bokstaver. Særs sein? Veldig stivt. msgid "speed|Very Slow" msgstr "Treigost" msgid "speed|Slow" msgstr "Sein" msgid "speed|Average" msgstr "Middels" # God? Bra? Brukbar? msgid "speed|Fast" msgstr "Grei" # Veldig rask blir for langt msgid "speed|Very Fast" msgstr "Rask" msgid "speed|Ultra Fast" msgstr "Superrask" # Lynrask msgid "speed|Blazing" msgstr "Fykende" # Øyeblikkelig, tvert, umiddelbar. msgid "speed|Instant" msgstr "Lynrask" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "ekorn" msgid "week|Rabbit" msgstr "hare" msgid "week|Gopher" msgstr "jordekorn" msgid "week|Badger" msgstr "grevling" msgid "week|Rat" msgstr "rotte" msgid "week|Eagle" msgstr "ørn" msgid "week|Weasel" msgstr "vesel" msgid "week|Raven" msgstr "ravn" msgid "week|Mongoose" msgstr "manguster" msgid "week|Dog" msgstr "hund" msgid "week|Aardvark" msgstr "jordsvin" msgid "week|Lizard" msgstr "øgle" msgid "week|Tortoise" msgstr "landskilpadde" msgid "week|Hedgehog" msgstr "piggsvin" msgid "week|Condor" msgstr "gribb" msgid "week|Ant" msgstr "maur" msgid "week|Grasshopper" msgstr "gresshopper" msgid "week|Dragonfly" msgstr "øyenstikker" msgid "week|Spider" msgstr "edderkopp" msgid "week|Butterfly" msgstr "sommerfugl" msgid "week|Bumblebee" msgstr "humle" msgid "week|Locust" msgstr "ørkengresshopper" msgid "week|Earthworm" msgstr "meitemark" msgid "week|Hornet" msgstr "veps" msgid "week|Beetle" msgstr "bille" msgid "week|PLAGUE" msgstr "pest" msgid "week|Unnamed" msgstr "navnløshet" msgid "Desert" msgstr "Ørken" msgid "Snow" msgstr "Snø" msgid "Wasteland" msgstr "Ødemark" msgid "Beach" msgstr "Strand" msgid "Lava" msgstr "Lava" msgid "Dirt" msgstr "Jord" msgid "Grass" msgstr "Gress" msgid "Ocean" msgstr "Sjø" msgid "maps|Small" msgstr "Liten" msgid "maps|Medium" msgstr "Middels" msgid "maps|Large" msgstr "Stor" msgid "maps|Extra Large" msgstr "Ekstra stor" msgid "maps|Custom Size" msgstr "Tilpasset størrelse" msgid "Ore Mine" msgstr "Malmgruve" msgid "Sulfur Mine" msgstr "Svovelgruve" msgid "Crystal Mine" msgstr "Krystallgruve" msgid "Gems Mine" msgstr "Edelstensgruve" msgid "Gold Mine" msgstr "Gullgruve" msgid "Mine" msgstr "Gruve" # Hensetting av hester forbudt. Bortsleping skjer pÃ¥ eiers regning. msgid "Burma shave." msgstr "Hensatte hester vil ende opp som pÃ¥legg." msgid "Next sign 50 miles." msgstr "Neste skilt om 50 mil." # Vennligst les pÃ¥ den andre siden av skiltet. msgid "See Rock City." msgstr "" "Gratulerer! \n" "Du er besøkende nr. 32167. \n" "Ta en tørr kjeks." msgid "This space for rent." msgstr "Skilt til utleie." msgid "No object" msgstr "Ingen objekt" msgid "Alchemist Lab" msgstr "Alkymistlab" msgid "Sign" msgstr "Skilt" msgid "Buoy" msgstr "Bøye" msgid "Skeleton" msgstr "Skjelett" msgid "Daemon Cave" msgstr "Djevelens hule" msgid "Treasure Chest" msgstr "Skattekiste" msgid "Faerie Ring" msgstr "Feenes ring" msgid "Campfire" msgstr "LeirbÃ¥l" msgid "Fountain" msgstr "Fontene" msgid "Gazebo" msgstr "Lysthus" msgid "Genie Lamp" msgstr "Magisk lampe" msgid "Archer's House" msgstr "Bueskytternes hus" msgid "Goblin Hut" msgstr "Vettehytte" msgid "Dwarf Cottage" msgstr "Dvergstue" msgid "Peasant Hut" msgstr "Bondehytte" msgid "Stables" msgstr "Stall" msgid "Alchemist's Tower" msgstr "Alkymistens tÃ¥rn" msgid "Event" msgstr "Hendelse" msgid "Dragon City" msgstr "Dragenes landsby" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "FyrtÃ¥rn" msgstr[1] "FyrtÃ¥rn" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Vannhjul" msgstr[1] "Vannhjul" msgid "Monster" msgstr "Monster" msgid "Obelisk" msgstr "Obelisk" msgid "Oasis" msgstr "Oase" msgid "Resource" msgstr "RÃ¥vare" msgid "Sawmill" msgstr "Sagbruk" msgid "Oracle" msgstr "Orakel" # Sirkel? Ring? msgid "Shrine of the First Circle" msgstr "Tempel av den første sirkelen" msgid "Shipwreck" msgstr "Skipbrudd" msgid "Sea Chest" msgstr "Sjøkiste" msgid "Desert Tent" msgstr "Ørkentelt" msgid "Stone Liths" msgstr "Steinportal" msgid "Wagon Camp" msgstr "Vognleir" msgid "Hut of the Magi" msgstr "SpÃ¥mannens hytte" msgid "Whirlpool" msgstr "Virvelstrøm" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Vindmølle" msgstr[1] "Vindmøller" msgid "Mermaid" msgstr "Havfrue" msgid "Boat" msgstr "Skip" msgid "Random Ultimate Artifact" msgstr "Tilfeldig sjeldneste skatt" msgid "Random Artifact" msgstr "Tilfeldig gjenstand" msgid "Random Resource" msgstr "Tilfeldig rÃ¥vare" msgid "Random Monster" msgstr "Tilfeldig monster" msgid "Random Town" msgstr "VilkÃ¥rlig by" msgid "Random Castle" msgstr "VilkÃ¥rlig borg" msgid "Eye of the Magi" msgstr "SpÃ¥mannens øye" msgid "Random Monster - weak" msgstr "Tilfeldig monster - svak" msgid "Random Monster - medium" msgstr "Tilfeldig monster - middels" msgid "Random Monster - strong" msgstr "Tilfeldig monster - sterk" msgid "Random Monster - very strong" msgstr "Tilfeldig monster - veldig sterk" #, fuzzy msgid "Hero" msgstr "Helter" msgid "Nothing Special" msgstr "Ingenting spesielt" msgid "Mossy Rock" msgstr "Mosesten" msgid "Watch Tower" msgstr "VakttÃ¥rn" msgid "Tree House" msgstr "Trehytte" msgid "Tree City" msgstr "Trærenes landsby" msgid "Ruins" msgstr "Ruiner" msgid "Fort" msgstr "Fort" msgid "Abandoned Mine" msgstr "Forlatt gruve" msgid "Sirens" msgstr "Sirener" msgid "Standing Stones" msgstr "Steinsøyler" # idol har ikke samme betydning pÃ¥ norsk. msgid "Idol" msgstr "Gudestatue" msgid "Tree of Knowledge" msgstr "Kunnskapstre" # Sjaman? Det er vel en ork. # Kvinnelig msgid "Witch Doctor's Hut" msgstr "Heksedoktorens hytte" msgid "Temple" msgstr "Tempel" msgid "Hill Fort" msgstr "Bergfestning" msgid "Halfling Hole" msgstr "Halvinghule" msgid "Mercenary Camp" msgstr "Leiesoldatleir" msgid "Shrine of the Second Circle" msgstr "Tempel av den andre sirkelen" msgid "Shrine of the Third Circle" msgstr "Tempel av den tredje sirkelen" msgid "City of the Dead" msgstr "De dødes by" msgid "Sphinx" msgstr "Sfinks" msgid "Wagon" msgstr "Vogn" msgid "Tar Pit" msgstr "Tjærepytt" msgid "Artesian Spring" msgstr "Artesisk brønn" msgid "Troll Bridge" msgstr "Trollbru" msgid "Watering Hole" msgstr "Vannkilde" msgid "Witch's Hut" msgstr "Heksehytte" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Gapahuk" msgid "Magellan's Maps" msgstr "Magellanske kart" msgid "Flotsam" msgstr "Vrakgods" msgid "Derelict Ship" msgstr "Havarert skip" msgid "Shipwreck Survivor" msgstr "Skipbruddent menneske" msgid "Bottle" msgstr "Flaskepost" msgid "Magic Well" msgstr "Magisk brønn" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Magisk hage" msgstr[1] "Magiske hager" msgid "Observation Tower" msgstr "UtkikkstÃ¥rn" msgid "Freeman's Foundry" msgstr "Borgerens støperi" msgid "Reefs" msgstr "Rev" msgid "Volcano" msgstr "Vulkan" msgid "Flowers" msgstr "Blomster" msgid "Rock" msgstr "Stein" msgid "Water Lake" msgstr "Innsjø" msgid "Mandrake" msgstr "Alrune" msgid "Dead Tree" msgstr "Trestubbe" msgid "Stump" msgstr "Stubbe" msgid "Crater" msgstr "Krater" msgid "Cactus" msgstr "Kaktus" msgid "Mound" msgstr "Haug" msgid "Dune" msgstr "Sanddyne" msgid "Lava Pool" msgstr "Lavadam" msgid "Shrub" msgstr "Busk" msgid "Barrow Mounds" msgstr "Gravhaug" msgid "Random Artifact - Treasure" msgstr "Tilfeldig skatt - Litt verdifull" msgid "Random Artifact - Minor" msgstr "Tilfeldig skatt - Mer verdifull" msgid "Random Artifact - Major" msgstr "Tilfeldig skatt - Ekstremt verdifull" msgid "Barrier" msgstr "Sperre" msgid "Traveller's Tent" msgstr "Vandrerens telt" msgid "Jail" msgstr "Fengsel" msgid "Fire Summoning Altar" msgstr "Ildmanende alter" msgid "Air Summoning Altar" msgstr "Luftmanende alter" msgid "Earth Summoning Altar" msgstr "Jordmanende alter" msgid "Water Summoning Altar" msgstr "Vannmanende alter" #, fuzzy msgid "Swampy Lake" msgstr "Myr" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "Ukjente monstre" msgid "Unknown Monster" msgstr "Ukjent monster" msgid "Peasant" msgstr "Bonde" msgid "Peasants" msgstr "Bønder" msgid "Archer" msgstr "Bueskytter" msgid "Archers" msgstr "Bueskyttere" # Denne oversettelsen brukes i norsk D&D msgid "Ranger" msgstr "Jeger" msgid "Rangers" msgstr "Jegere" msgid "Pikeman" msgstr "Spydmann" msgid "Pikemen" msgstr "Spydmenn" msgid "Veteran Pikeman" msgstr "Spydveteran" msgid "Veteran Pikemen" msgstr "Spydveteraner" msgid "Swordsman" msgstr "Sverdmann" msgid "Swordsmen" msgstr "Sverdmenn" msgid "Master Swordsman" msgstr "Sverdmester" msgid "Master Swordsmen" msgstr "Sverdmestre" msgid "Cavalries" msgstr "Ryttere" msgid "Cavalry" msgstr "Rytter" msgid "Champion" msgstr "Mesterrytter" msgid "Champions" msgstr "Mesterryttere" msgid "Paladin" msgstr "Ridderhelt" msgid "Paladins" msgstr "Ridderhelter" msgid "Crusader" msgstr "Korsfarer" msgid "Crusaders" msgstr "Korsfarere" # Tusse, smÃ¥troll? - For søtt. Landvette (litt likt stokkholm flyplass). Vette? For enkelt? Kampvette? msgid "Goblin" msgstr "Vette" msgid "Goblins" msgstr "Vetter" msgid "Orc" msgstr "Ork" msgid "Orcs" msgstr "Orker" msgid "Orc Chief" msgstr "Orkehøvding" msgid "Orc Chiefs" msgstr "Orkehøvdinger" msgid "Wolf" msgstr "Varg" msgid "Wolves" msgstr "Varger" msgid "Ogre" msgstr "Jette" msgid "Ogres" msgstr "Jetter" msgid "Ogre Lord" msgstr "Herskerjette" msgid "Ogre Lords" msgstr "Herskerjetter" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Troll" msgid "War Troll" msgstr "Stridstroll" msgid "War Trolls" msgstr "Stridstroll" msgid "Cyclopes" msgstr "Kykloper" msgid "Cyclops" msgstr "Kyklop" msgid "Sprite" msgstr "Fe" msgid "Sprites" msgstr "Feer" msgid "Dwarf" msgstr "Dverg" msgid "Dwarves" msgstr "Dverger" msgid "Battle Dwarf" msgstr "Stridsdverg" msgid "Battle Dwarves" msgstr "Stridsdverger" msgid "Elf" msgstr "Alv" msgid "Elves" msgstr "Alver" msgid "Grand Elf" msgstr "Storalv" msgid "Grand Elves" msgstr "Storalver" msgid "Druid" msgstr "Druide" msgid "Druids" msgstr "Druider" msgid "Greater Druid" msgstr "Mektig druide" msgid "Greater Druids" msgstr "Mektige druider" msgid "Unicorn" msgstr "Enhjørning" msgid "Unicorns" msgstr "Enhjørninger" msgid "Phoenix" msgstr "Føniks" msgid "Phoenixes" msgstr "Fønikser" msgid "Centaur" msgstr "Kentaur" msgid "Centaurs" msgstr "Kentaurer" msgid "Gargoyle" msgstr "Gravstatue" msgid "Gargoyles" msgstr "Gravstatuer" msgid "Griffin" msgstr "Griff" msgid "Griffins" msgstr "Griffer" msgid "Minotaur" msgstr "Minotaur" msgid "Minotaurs" msgstr "Minotaurer" msgid "Minotaur King" msgstr "Minotaurkonge" msgid "Minotaur Kings" msgstr "Minotaurkonger" msgid "Hydra" msgstr "Hydra" msgid "Hydras" msgstr "Hydraer" msgid "Green Dragon" msgstr "Grønndrage" msgid "Green Dragons" msgstr "Grønndrager" msgid "Red Dragon" msgstr "Røddrage" msgid "Red Dragons" msgstr "Røddrager" msgid "Black Dragon" msgstr "Svartdrage" msgid "Black Dragons" msgstr "Svartdrager" msgid "Halfling" msgstr "Halving" msgid "Halflings" msgstr "Halvinger" msgid "Boar" msgstr "Villsvin" msgid "Boars" msgstr "Villsvin" msgid "Iron Golem" msgstr "Jerngolem" msgid "Iron Golems" msgstr "Jerngolemer" msgid "Steel Golem" msgstr "StÃ¥lgolem" msgid "Steel Golems" msgstr "StÃ¥lgolemer" msgid "Roc" msgstr "Rokk" msgid "Rocs" msgstr "Rokker" msgid "Mage" msgstr "Magiker" msgid "Magi" msgstr "Magikere" msgid "Archmage" msgstr "Erkemagiker" msgid "Archmagi" msgstr "Erkemagikere" msgid "Giant" msgstr "Kjempe" msgid "Giants" msgstr "Kjemper" msgid "Titan" msgstr "Titan" msgid "Titans" msgstr "Titaner" msgid "Skeletons" msgstr "Skjeletter" msgid "Zombie" msgstr "Zombie" msgid "Zombies" msgstr "Zombier" msgid "Mutant Zombie" msgstr "Mutert zombie" msgid "Mutant Zombies" msgstr "Muterte zombier" msgid "Mummies" msgstr "Mumier" msgid "Mummy" msgstr "Mumie" msgid "Royal Mummies" msgstr "Kongelige mumier" msgid "Royal Mummy" msgstr "Kongelig mumie" msgid "Vampire" msgstr "Vampyr" msgid "Vampires" msgstr "Vampyrer" msgid "Vampire Lord" msgstr "Vampyrgreve" msgid "Vampire Lords" msgstr "Vampyrgrever" # Ser ut som konger og kommer fra mausoleum/kongegrav. Bedre enn hekselik som virker litt kvinnelig. # Konge beholder det som hankjønn. Lich betyr lik opprinnelig. msgid "Lich" msgstr "Heksekonge" msgid "Liches" msgstr "Heksekonger" msgid "Power Lich" msgstr "Mektig heksekonge" msgid "Power Liches" msgstr "Mektige heksekonger" msgid "Bone Dragon" msgstr "Beindrage" msgid "Bone Dragons" msgstr "Beindrager" msgid "Rogue" msgstr "Banditt" msgid "Rogues" msgstr "Banditter" msgid "Nomad" msgstr "Nomade" msgid "Nomads" msgstr "Nomader" msgid "Ghost" msgstr "Gjenferd" msgid "Ghosts" msgstr "Gjenferd" msgid "Genie" msgstr "LampeÃ¥nd" msgid "Genies" msgstr "LampeÃ¥nder" msgid "Medusa" msgstr "Medusa" msgid "Medusas" msgstr "Medusaer" msgid "Earth Elemental" msgstr "JordÃ¥nd" msgid "Earth Elementals" msgstr "JordÃ¥nder" msgid "Air Elemental" msgstr "LuftÃ¥nd" msgid "Air Elementals" msgstr "LuftÃ¥nder" msgid "Fire Elemental" msgstr "IldÃ¥nd" msgid "Fire Elementals" msgstr "IldÃ¥nder" msgid "Water Elemental" msgstr "VannÃ¥nd" msgid "Water Elementals" msgstr "VannÃ¥nder" msgid "Random Monsters" msgstr "Tilfeldige monstre" msgid "Random Monster 1" msgstr "Tilfeldig monster 1" msgid "Random Monsters 1" msgstr "Tilfeldige monstre 1" msgid "Random Monster 2" msgstr "Tilfeldig monster 2" msgid "Random Monsters 2" msgstr "Tilfeldige monstre 2" msgid "Random Monster 3" msgstr "Tilfeldig monster 3" msgid "Random Monsters 3" msgstr "Tilfeldige monstre 3" msgid "Random Monster 4" msgstr "Tilfeldig monster 4" msgid "Random Monsters 4" msgstr "Tilfeldige monstre 4" msgid "Double shot" msgstr "Dobbeltskudd" msgid "2-hex monster" msgstr "2-feltsmonster" msgid "Double strike" msgstr "Dobbeltslag" msgid "Double damage to Undead" msgstr "Dobbel skade mot vandøde" msgid "% magic resistance" msgstr "% magimotstand" msgid "Immune to Mind spells" msgstr "Immun mot sinnsmagi" msgid "Immune to Elemental spells" msgstr "Immun mot elementbasert magi" msgid "Immune to Fire spells" msgstr "Immun mot ildmagi" msgid "Immune to Cold spells" msgstr "Immun mot kuldemagi" msgid "Immune to " msgstr "Immun mot " msgid "% immunity to %{spell} spell" msgstr "% immunitet mot trolldommen %{spell}" msgid "% damage from Elemental spells" msgstr "% skade fra elementbasert magi" msgid "% damage from %{spell} spell" msgstr "% skade fra trolldommen %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% sjanse til Ã¥ oppheve all fordelaktig trolldom" msgid "% chance to Paralyze" msgstr "% sjanse til Ã¥ lamme" msgid "% chance to Petrify" msgstr "% sjanse til Ã¥ forsteine" msgid "% chance to Blind" msgstr "% sjanse til Ã¥ forblinde" msgid "% chance to Curse" msgstr "% sjanse for forbannelse" msgid "% chance to cast %{spell} spell" msgstr "% sjanse til Ã¥ bruke trolldommen %{spell}" msgid "HP regeneration" msgstr "Selvhelbredning" msgid "Two hexes attack" msgstr "Tofeltsangrep" msgid "Flyer" msgstr "Flyger" msgid "Always retaliates" msgstr "Tar alltid igjen" msgid "Attacks all adjacent enemies" msgstr "Angriper alle fiender rundt seg" msgid "No melee penalty" msgstr "Ingen ulempe i nærkamp" msgid "Dragon" msgstr "Drage" msgid "Undead" msgstr "Vandød" msgid "No enemy retaliation" msgstr "Ingen fiendtlige hevnslag" msgid "HP drain" msgstr "Stjeling av liv" msgid "Cloud attack" msgstr "TÃ¥keskudd" msgid "Decreases enemy's morale by " msgstr "Svekker fiendens kampÃ¥nd med " msgid "% chance to halve enemy" msgstr "% sjanse til Ã¥ halvere antallet til den angrepne styrken" msgid "Soul Eater" msgstr "Sjelesanking" msgid "Elemental" msgstr "Elementær" msgid "No Morale" msgstr "Ingen kampÃ¥nd" #, fuzzy msgid "Earth creature" msgstr "Verv krigere" #, fuzzy msgid "Air creature" msgstr "Verv krigere" #, fuzzy msgid "Fire creature" msgstr "Verv krigere" #, fuzzy msgid "Water creature" msgstr "Innsjø" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% skade fra ildmagi" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% skade fra kuldemagi" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Fjerner all trolldom fra alle krigere, bÃ¥de vennlige og fiendtlige." #, fuzzy msgid "Double damage from Air creatures" msgstr "Dobbel skade mot vandøde" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% skade fra ildmagi" #, fuzzy msgid "Double damage from Water creatures" msgstr "Fjerner all trolldom fra alle krigere, bÃ¥de vennlige og fiendtlige." msgid "Lightning" msgstr "Lynnedslag" msgid "% immunity to " msgstr "% immunitet mot trolldommen %{spell} " msgid "% damage from " msgstr "% skade fra " msgid "The three Anduran artifacts magically combine into one." msgstr "De tre skattene til Anduran blir pÃ¥ magisk vis om til én." msgid "View Spells" msgstr "Vis trolldommer" msgid "View %{name} Info" msgstr "Vis info om %{name}" msgid "Move %{name}" msgstr "Flytt %{name}" msgid "Cannot move the Spellbook" msgstr "Trylleboken kan ikke flyttes" msgid "This item can't be traded." msgstr "Denne tingen kan ikke overføres." msgid "Invalid Artifact" msgstr "Ugyldig gjenstand" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} øker kunnskapen din med %{count}." # ypperste? beste? msgid "Ultimate Book of Knowledge" msgstr "Den ultimate kunnskapsboka" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} øker angrepsevnen din med %{count}." msgid "Ultimate Sword of Dominion" msgstr "Det ultimate sverdet av Herreveldet" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} øker forsvarsevnen din med %{count}." msgid "Ultimate Cloak of Protection" msgstr "Den ultimate beskyttelseskappen" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} øker kraften din med %{count}." msgid "Ultimate Wand of Magic" msgstr "Den ultimate tryllestaven" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} øker angreps- og forsvarsevnen din med %{count} hver." msgid "Ultimate Shield" msgstr "Det ultimate skjoldet" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} øker kraften og kunnskapen din med %{count} hver." msgid "Ultimate Staff" msgstr "Den ultimate stokken" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} øker alle egenskapene dine med %{count} poeng." msgid "Ultimate Crown" msgstr "Den ultimate kronen" msgid "Golden Goose" msgstr "GullgÃ¥sa" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} gir deg en ekstra inntekt pÃ¥ %{count} gullstykker hver dag." msgid "Arcane Necklace of Magic" msgstr "Det mørke magihalskjedet" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Etter Ã¥ ha reddet ei trollkvinne fra et forhekset gravkammer, belønner hun " "deg for heltemotet ditt med Ã¥ gi deg et storartet halskjede av juveler." msgid "Caster's Bracelet of Magic" msgstr "Fortryllerens magiarmbÃ¥nd" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Mens du leter gjennom restene av ei sammenfalt gruve, befrir du en gruppe " "med innesperrede dverger. Takknemlig gir lederen deg et armbÃ¥nd av gull." msgid "Mage's Ring of Power" msgstr "Magikerens kraftring" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Et skrik av smerte fører deg til en kentaur fanget i en felle. Etter Ã¥ ha " "hjulpet det stakkars vesenet ut, gir han deg en liten taske. Blant innholdet " "i den finner du en fantastisk ring med en edelsten pÃ¥ seg." msgid "Witch's Broach of Magic" msgstr "Heksens magiske brystnÃ¥l" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Ved levningene til ei ihjelbrent heks ligger ei vakker brystnÃ¥l av nøye " "hÃ¥ndverk. Du trÃ¥r varsomt mot liket og tar brystnÃ¥la." msgid "Medal of Valor" msgstr "Medaljen av heltemot" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} øker kampÃ¥nden din med %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Etter Ã¥ ha befridd en stakkars ungpike fra fangenskapet til en ond hersker, " "belønner det kongelige hoffet deg med en medalje av heltemot." msgid "Medal of Courage" msgstr "Medaljen av tapperhet" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Etter Ã¥ ha kommet en unggutt til unnsetning fra en flokk med blodtørstige " "varger, tar du ham med tilbake til faren hans sin herregÃ¥rd. Den takknemlige " "adelsmannen belønner deg med en medalje av tapperhet." msgid "Medal of Honor" msgstr "Æresmedaljen" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Etter Ã¥ ha befridd en prinsesse fra et naborike fra det onde klørne til " "foraktelige slavehandlere, belønner hun deg med en medalje av ære." msgid "Medal of Distinction" msgstr "Utmerkelsesmedaljen" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Etter Ã¥ ha fjernet fra bygdelandet en grusom minotaur som hadde gÃ¥tt inn for " "Ã¥ jakte og spise adelsmennenes riddere, blir du hedret med en medalje for " "særskilt utmerkelse." msgid "Fizbin of Misfortune" msgstr "Fizbinen av uflaks" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} svekker kampÃ¥nden din skikkelig med %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Du kommer over en medalje liggende langs den øde veien. Etter Ã¥ ha lagt " "medaljen sammen med resten av tingene dine, innser du at den er den lite " "ettertraktede Fizbinen av uflaks. Den svekker styrkene dine sin kampÃ¥nd " "betydelig." msgid "Thunder Mace of Dominion" msgstr "Tordenklubben av Herreveldet" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Midt i en uforventet storm, slÃ¥r et lyn ned i et tre, og det deles tvers " "gjennom. PÃ¥ innsiden av treet finner du en forunderlig klubbe." msgid "Armored Gauntlets of Protection" msgstr "Panserhanskene av beskyttelse" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} øker forsvarsevnen din med %{count}." #, fuzzy msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Du møter pÃ¥ den berømte Sorte ridderen! Etter en intens men uavgjort duell " "tilbyr ridderen, av sin nylig ervervede respekt for deg, et par pansrede " "hansker." msgid "Defender Helm of Protection" msgstr "Forsvarerens hjelm av beskyttelse" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Et eller annet som glitrer av gull fanger oppmerksomheten din. Ved nærmere " "undersøkelse oppdager du en gullhjelm bortgjemt under en busk." msgid "Giant Flail of Dominion" msgstr "Kjempeklubben av Herreveldet" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Du oppdager en klønete kjempe som har prestert Ã¥ drepe seg selv med sin egen " "klubbe. Trygg pÃ¥ dine langt bedre ferdigheter med dette vÃ¥penet, fjerner du " "selvsikkert den imponerende klubben fra den falne kjempen." msgid "Ballista of Quickness" msgstr "Ballisten av hurtighet" #, fuzzy msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "%{name} lar katapulten din avfyre ett ekstra skudd per kamprunde." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Mens du gÃ¥r gjennom ruinene til en eldgammel innmuret by, finner du Ã¥rsaken " "til byens ødeleggelse: en omhyggelig utarbeidet ballist." msgid "Stealth Shield of Protection" msgstr "Tyvenes skjold av beskyttelse" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "En krigers statue i stein bærer et sølvskjold. Idet du fjerner skjoldet " "smuldrer statuen opp." msgid "Dragon Sword of Dominion" msgstr "Dragesverdet av Herreveldet" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "I mens du spaserer langs en smal sti, tar en busk i nærheten plutselig fyr. " "Flammene foran deg blir om til en skikkelse av en prektig kvinne. Hun rekker " "ut et storslÃ¥tt sverd til deg." msgid "Power Axe of Dominion" msgstr "Styrkeøksa av Herreveldet" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Du fÃ¥r øynene pÃ¥ ei øks av sølv som er plantet dypt ned i bakken. Etter " "flere mislykkede forsøk fra følget ditt pÃ¥ Ã¥ fjerne øksa, tar du et godt tak " "i hÃ¥ndtaket og fÃ¥r den lett opp." msgid "Divine Breastplate of Protection" msgstr "Den gudommelige brystplata av beskyttelse" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "En gjeng røvere holder pÃ¥ Ã¥ gÃ¥ gjennom eiendelene til en avdød kriger. Etter " "Ã¥ ha jaget vekk plyndrerene, legger du merke til at de hadde oversett ei " "forseggjort brystplate." msgid "Minor Scroll of Knowledge" msgstr "Den mindre kunnskapsrullen" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Rett foran deg dukker ei svevende glasskiste opp med en skriftrull lagt pÃ¥ " "en kongelig rød pute. Idet du berører den, Ã¥pner lokket seg og rullen svever " "magisk inn i dine utÃ¥lmodige hender." msgid "Major Scroll of Knowledge" msgstr "Den større kunnskapsrullen" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "PÃ¥ besøk hos en lokal vismann forklarer du hensikten med ferden din. Han " "strekker hÃ¥nden ned i sekken sin og ut av den drar han fram en gulnet " "skriftrull, som han overrekker deg." msgid "Superior Scroll of Knowledge" msgstr "Den overlegne kunnskapsrullen" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Du kommer over levningene til en druide fra fortiden. Knokler, som har blitt " "gul med tiden, kan synes pÃ¥ innsiden av den fillete kjortelen hennes. Du " "leter gjennom den og oppdager en bortgjemt skriftrull i foldene." msgid "Foremost Scroll of Knowledge" msgstr "Den ypperste kunnskapsrullen" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Oppsprukne knokler, som har gulnet med tiden, synes fra de fillete foldene " "til en omkommet druides kÃ¥pe. Du leter gjennom kÃ¥pen og oppdager en " "bortgjemt skriftrull." msgid "Endless Sack of Gold" msgstr "Den uendelige gullsekken" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} gir deg %{count} gullstykker hver dag." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "En liten regnbuegnom danser lykkelig rundt en magisk sekk. Idet han ser deg " "komme, stanser han midt i steget. Den lille mannen hyler og tramper med " "foten sin febrilsk, før han forsvinner i løse luften. Du kommer pÃ¥ det gamle " "ordtaket til regnbuegnomene: \"Finneren er vinneren\", og du tar sekken og " "gÃ¥r din vei." msgid "Endless Bag of Gold" msgstr "Den uendelige gullbagen" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "En adelskvinne, som har mistet følge sitt, ber deg om hjelp. Etter Ã¥ ha " "eskortert henne hjem, belønner hun deg med en sekk fylt med gull." msgid "Endless Purse of Gold" msgstr "Den uendelige gullvesken" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Midt under reisen din kommer du over ei skinntaske fylt med gull. Den skal " "en gang ha tilhørt en mektig krigerkonge som visstnok hadde evnen til Ã¥ " "forvandle alle ting til gull." msgid "Nomad Boots of Mobility" msgstr "Nomadens sko av bevegelighet" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "%{name} øker skrittene dine pÃ¥ land." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "En forretningsnomade ber om beskyttelse fra en stamme med vetter. Som takk " "for hjelpen din, gir han deg et par forseggjorte sko av den mykeste typen " "skinn. Ved nærmere blikk oppdager du forunderlige eldgamle inngraveringer pÃ¥ " "skinnet." msgid "Traveler's Boots of Mobility" msgstr "Vandrerens bevegelighetssko" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Du oppdager et par sko med utsmykninger i perler og lagd av den fineste og " "mykeste typen skinn. Du takker den navnløse giveren og tilføyer skoene til " "samlingen din av skatter." msgid "Lucky Rabbit's Foot" msgstr "Lykkeharens pote" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} øker flaksen din i kamp med %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "En reisende handelsmann tilbyr deg en kaninpote med en skinnende sølvpels " "imot at du beskytter ham pÃ¥ reisen hans. Handelsmannen forklarer deg at " "denne magiske tingen vil bedre flaksen din i kamp." msgid "Golden Horseshoe" msgstr "Den gylne hesteskoen" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "En fastbundet enhjørning vrinsker av redsel. Mens du sier beroliggende ord " "frigjør du henne. Den snøfter og tramper med den framre hoven sin en gang " "før den galopperer av gÃ¥rde. Du ser ned pÃ¥ bakken og finner en gyllen " "hestesko." msgid "Gambler's Lucky Coin" msgstr "Pengespillerens lykkemynt" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Du klarer Ã¥ fange en rampete smÃ¥djevel som har drevet ugagn i omrÃ¥det. I " "bytte mot sin frihet, gir han deg en magisk mynt." msgid "Four-Leaf Clover" msgstr "Firkløveren" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Midt i et stykke uttørket og livløs eng, finner du til din overraskelse en " "frisk og grønn firkløver." msgid "True Compass of Mobility" msgstr "Det sanne kompasset av bevegelighet" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} øker skrittene dine pÃ¥ land og til sjøs." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "En gammel mann som hevder at han er en oppfinner ber deg om Ã¥ prøve hans " "nyeste oppfinnelse. Han tar deretter og gir deg et kompass." msgid "Sailor's Astrolabe of Mobility" msgstr "Sjøfarerens sekstant av bevegelighet" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} øker skrittene dine til sjøs." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Du kommer over en gammel sjøulk som blir torturert av noen jetter. Du befrir " "ham, og til gjengjeld belønner han deg med et underlig verktøy som kan mÃ¥le " "avstanden til stjerner." msgid "Evil Eye" msgstr "Ondskapens øye" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} halverer tapet av mana ved bruk av forbannelsesmagi." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Du leter gjennom en forfallen hytte og fÃ¥r øyet pÃ¥ skjelettet til en for " "lengst død heks. Ved nærmere inspeksjon oppdager du et glassøye som ruller " "rundt i hennes tomme hodeskalle." msgid "Enchanted Hourglass" msgstr "Det fortryllede timeglasset" #, fuzzy msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} forlenger varigheten av alle dine trolldommer med %{count} runder." #, fuzzy msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "En brÃ¥ endring i landskapet gir vei til et uhyggelig syn: gribber som Ã¥tsler " "pÃ¥ restene fra et blodig slag. Et raskt søk gjennom omrÃ¥det avdekker et " "fortryllet timeglass." msgid "Gold Watch" msgstr "Gulluret" #, fuzzy msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} dobler virkningen av trollbinding." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Som belønning for Ã¥ ha hjulpet en vandrende eliksirselger med Ã¥ fÃ¥ kjerren " "sin ut av en grøft, gir han deg et \"magisk\" gullur. Uvitende for ham, " "viser det seg at uret faktisk er magisk." msgid "Skullcap" msgstr "Kalotten" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "%{name} halverer tapet av mana ved bruk av all slags sinnsmagi." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "En kort rast hos et uforventet vertshus langs landeveien fører til " "utveksling av penger, historier, og ved et uhell, reisegods. Du oppdager en " "magisk kalott i den nye ryggsekken din." msgid "Ice Cloak" msgstr "Iskappe" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "%{name}n halverer all skade styrkene dine tar av kuldemagi." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Du hører kvinnelige redselsskrik og oppdager ei ungkvinne pÃ¥ flukt fra en " "hungrig bjørn. Ikke et sekund for tidlig fÃ¥r du tatt livet av bjørnen, og " "damen, som viser seg Ã¥ være en trollkvinne, lager deg en magisk kappe av " "bjørneskinnet for Ã¥ vise sin takknemlighet." msgid "Fire Cloak" msgstr "Flammekappe" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "%{name}n halverer all skade styrkene dine tar fra ildmagi." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Du blir plutselig vitne til en pÃ¥gÃ¥ende kamp mellom en sortekunstner og en " "ridderhelt. Sortekunstneren skyter en ildkule pÃ¥ ridderhelten som faller ned " "pÃ¥ kne. Raskt griper du inn og dreper den onde før han fÃ¥r satt nÃ¥destøtet. " "Den takknemlige ridderhelten gir deg en ildkappe for Ã¥ ha kommet ham til " "unnsetning." msgid "Lightning Helm" msgstr "Lynhjelmen" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "%{name} halverer all skade styrkene dine tar av lynmagi." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "En vandrende kjeleflikker med behov for forsyninger tilbyr deg en hjelm med " "et lynmerke pÃ¥ seg imot mat og vann. Nysgjerrig godtar du byttet, og senere " "oppdager du at hjelmen er magisk." msgid "Evercold Icicle" msgstr "Den evigkalde istappen" #, fuzzy msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} gjør at kuldemagien din gjør %{count} prosent mer skade pÃ¥ " "fiendtlige styrker." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Oppmerksomheten din fanges av en istapp som unngÃ¥r Ã¥ smelte tross den " "heftige varmen til middagssolen. Fylt av nysgjerrighet brekker du den av og " "oppdager at den ikke smelter i hÃ¥nden din heller." msgid "Everhot Lava Rock" msgstr "Den evigvarme lavasteinen" #, fuzzy msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} gjør at ildmagien din gjør %{count} prosent mer skade pÃ¥ fiendtlige " "styrker." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Dine vandringer ender deg opp i et møte med en stamme apelignende " "skapninger. De bruker en magisk lavastein som aldri kjøler seg ned til Ã¥ fÃ¥ " "ild nÃ¥r de trenger det. Du syns synd pÃ¥ dem og lærer dem Ã¥ lage ild med " "pinner. De tror derfor at du er en gud og gir deg steinen sin." msgid "Lightning Rod" msgstr "Lynstav" #, fuzzy msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name}en gjør at lynmagien din gjør %{count} prosent mer skade pÃ¥ " "fiendtlige styrker." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Mens du venter pÃ¥ at et uvær skal gi seg, slÃ¥r et lyn ned i lynavlederen til " "ei hytte like ved. Avlederen løsner og faller pÃ¥ bakken. Endestykket til den " "lange stangen overlever fallet og nÃ¥r du tar pÃ¥ den reiser hÃ¥ret ditt seg. " "Hmm..." msgid "Snake-Ring" msgstr "Slangering" #, fuzzy msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "%{name}en halverer tapet av mana ved bruk av velsignelsesmagi." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Du fant en merkelig utformet ring pÃ¥ fingeren til en for lengst avdød " "reisende. Ringen ser ut som en slange som biter sin egen hale." msgid "Ankh" msgstr "Henkelkorset" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} fordobler virkningen til all din gjenopplivnings- og " "gjenreisingsmagi." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "En heftig storm avdekker inngangen til et underjordisk gravkammer. Ved " "nærmere undersøkelse oppdager du at graven allerede har blitt ransaket, men " "tyvene oversÃ¥ et henkelkors med et sølvkjede i mørket." msgid "Book of Elements" msgstr "Boken om elementene" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} fordobler virkningsgraden til all din tilkallingsmagi." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Du kommer over en Ã¥ndemaner som trygler deg om Ã¥ fÃ¥ slÃ¥ følge med deg og " "hæren din for en stund for sin egen trygghet. Du gÃ¥r med pÃ¥ det, og som " "betaling tilbyr han en kopi av Boken om elementene." msgid "Elemental Ring" msgstr "Den elementære ringen" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "%{name} halverer tapet av mana for all din tilkallingsmagi." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "I løpet av en av rastene dine, legger du merke til en gaupe som klatrer opp " "et lite tre for Ã¥ komme seg til et krÃ¥kerede. Av instinkt klatrer du ogsÃ¥ " "opp treet og jager vekk kattedyret. NÃ¥r du titter ned i reiret finner du en " "liten samling glinsende steiner og en ring." msgid "Holy Pendant" msgstr "Det hellige halskjedet" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} gjør alle krigerne dine immune mot forbannelsesmagi." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Ferden din blir avbrutt av et møte med en einstøing bosatt i ei ryddig, lita " "hytte. Han blir imponert nÃ¥r han fÃ¥r høre om oppdraget ditt, og han " "bestemmer seg for Ã¥ ta en pause fra mediteringen for Ã¥ velsigne deg og gi " "deg en magisk gjenstand som vil verne deg mot forbannelser." msgid "Pendant of Free Will" msgstr "Halskjedet av fri vilje" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "%{name} gjør alle krigerne dine immune mot trollbinding." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Du hører rop om hjelp og oppdager elvefeer som har det gøy med Ã¥ plage en " "gammel mann. Synet fyller deg av sinne og du bestemmer deg for Ã¥ komme " "mannen til unnsetning. Du tar tak i en av feene og drar den med deg opp pÃ¥ " "land. Feen pines utenfor vannet og imot sin frihet gir den deg et magisk " "halskjede." msgid "Pendant of Life" msgstr "Halskjedet av liv" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} gjør alle krigerne dine immune mot dødsmagi." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Et kort møte med en liten karavane og en runde hÃ¥ndbak som du vinner, gjør " "deg til den nye eieren av et magisk halskjede. Dens forrige eier forklarer " "deg at halskjedet beskytter mot sortekunstneres dødsbesvergelser." msgid "Serenity Pendant" msgstr "Halskjedet av sinnsro" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} gjør alle krigerne dine immune mot berserkergang." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Lyder av kamp trekker deg mot det pÃ¥gÃ¥ende slaget mellom en gammel barbar og " "en Ã¥ttehodet hydra. Du griper inn akkurat i tide til Ã¥ snu kampen mot " "barbarens favør. EtterpÃ¥ takker han deg med Ã¥ gi deg et halskjede han pleide " "Ã¥ bruke for Ã¥ berolige sinnet før kamp." msgid "Seeing-eye Pendant" msgstr "Halskjedet av det ublinde øyet" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} gjør alle krigerne dine immune mot forblindelsesmagi." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Du kommer over en veldig gammel kvinne, for lengst blind av stær og i ferd " "med Ã¥ dø alene. Du tar deg av hennes siste behov og lover henne Ã¥ gi henne " "en ordentlig begravelse. Av takknemlighet gir hun deg et magisk halskjede " "prydet med et nøye utformet øye. Halskjedet lar deg kunne se med øynene " "lukket." msgid "Kinetic Pendant" msgstr "Halskjedet av bevegelse" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name} gjør alle krigerne dine immune mot lammelsesmagi." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Du kommer over en golem som bærer et skinnende halskjede og som sperrer " "veien for deg. Du handler ut ifra magefølelsen din og kutter halskjedet fra " "halsen pÃ¥ den. NÃ¥ uten en energikilde faller golemen sammen og etterlater " "deg det magiske halskjedet." msgid "Pendant of Death" msgstr "Dødens halskjede" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} gjør alle krigerne dine immune mot hellig magi." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "En rask og dødelig kamp med en sortekunstner vinner deg det magiske " "halskjedet hans. Senere forteller en magimester deg at halskjedet beskytter " "vandøde under din makt fra trolldommer av hellige ord." msgid "Wand of Negation" msgstr "Tryllestaven av benektelse" #, fuzzy msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "%{name} gjør alle krigerne dine immune mot dødsmagi." #, fuzzy msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Du møter pÃ¥ en av dine gamle magimestervenner som reiser i motsatt retning " "av deg. Han overrekker deg en gave: En tryllestav som forhindrer bruken av " "trolldommen magiopphevelse mot krigerne dine." msgid "Golden Bow" msgstr "Gullbuen" #, fuzzy msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} fjerner minskningen pÃ¥ %{count} prosent av skaden troppene dine gjør " "nÃ¥r de skyter pÃ¥ tvers av hindringer\n" "(f.eks. forbi ringmurer)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Helt tilfeldig møter du pÃ¥ en berømt bueskytter og dette fører til en runde " "hÃ¥ndbak der skytteren vedder bua si mot hesten din. Du vinner." msgid "Telescope" msgstr "Himmelkikkerten" #, fuzzy msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} utvider omrÃ¥det som helten din avdekker under forflytning med " "%{count} ekstra hakk." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "En forretningsmann fra et fjerntliggende land gÃ¥r med pÃ¥ Ã¥ bytte sin nye " "oppfinnelse mot reiseforsyninger fra deg. Denne duppedingsen fÃ¥r fjerne ting " "til Ã¥ framstÃ¥ nærmere, og han har gitt den navnet...\n" "\n" "teleskop." msgid "Statesman's Quill" msgstr "Statsmannens fjærpenn" #, fuzzy msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} reduserer prisen for Ã¥ overgi seg med %{count} prosent av den totale " "verdien av hærstyrken din." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Du tar et avbrekk fra reisen din for Ã¥ hjelpe en megler med Ã¥ fikse ei " "ødelagt hjulaksling. For Ã¥ vise sin takknemlighet gir han deg ei fjærpenn " "med magiske egenskaper. Han forklarer deg at den vil \"gjøre folk " "tilbøyelige til Ã¥ se ting pÃ¥ din mÃ¥te\"." msgid "Wizard's Hat" msgstr "Magimesterens hatt" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} øker varigheten til trolldommene dine med %{count} runder." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Du fÃ¥r øye pÃ¥ en magimester ridende som vinden pÃ¥ flukt fra en griff. " "Magimesteren Ã¥pner en portal og fyker gjennom den, men i farten fÃ¥r han " "hatten sin slÃ¥tt av av munningen til portalen. Griffen følger etter og " "portalen lukkes. Du plukker opp hatten, børster av den, og setter den pent " "pÃ¥ hodet ditt." msgid "Power Ring" msgstr "Kraftsringen" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} fyller opp %{count} mana til helten din hver dag." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Du finner et lite tre som ligner svært pÃ¥ den mektige trollmannen Karnauth. " "Treet har en ring rundt en av greinene sine. Rester av bekledning og rÃ¥tne " "lærstykker fÃ¥r deg til Ã¥ mistenke at det faktisk ER Karnauth, dog noe " "forvandlet. Siden du ikke ser noen vei du kan hjelpe ham, tar du den magiske " "ringen." msgid "Ammo Cart" msgstr "Ammunisjonsvogn" #, fuzzy msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "%{name}en forsyner de skytende krigerne dine med uendelig ammunisjon." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "En ammunisjonsvogn plassert midt i en forlatt slagmark fanger " "oppmerksomheten din. Nærmere inspeksjon viser at den er i god stand, sÃ¥ du " "tar den med deg." msgid "Tax Lien" msgstr "Skattepant" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name}en koster deg %{count} gullstykker hver dag." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Din vane for Ã¥ bruke store penger har endt deg opp med en gedigen " "skattegjeld som du ikke har nubbe sjans til Ã¥ nedbetale. Kemneren syns synd " "pÃ¥ deg og gÃ¥r med pÃ¥ Ã¥ kun innkreve 250 gullstykker per dag fra deg resten " "av livet. Hak av herunder hvis du vil at én denar skal brukes til Ã¥ støtte " "presidentens valgfond." msgid "Hideous Mask" msgstr "Den avskyelige masken" #, fuzzy msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "%{name} hindrer alle \"omstreifende\" styrker fra Ã¥ bli med helten din." #, fuzzy msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Din ransaking av graven til Sinfilas Gardolad, den berømte hamskiftende " "trollmannen, avdekker hans legendariske maske. Skjelvende tar du den pÃ¥ deg " "og den forvrenger fjeset ditt til et uhyggelig uttrykk! Ã… nei! Dette er " "egentlig den avskyelige masken til Gromluck Greene, og nÃ¥ fÃ¥r du ikke " "kvittet deg med den." msgid "Endless Pouch of Sulfur" msgstr "Den uendelige posen av svovel" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} gir deg %{count} enhet svovel hver dag." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Du besøker en alkymist som, ved synet av hæren din, blir grepet av " "rettskaffenheten til kallet ditt. Din nye trofaste støttespiller gir deg " "hans uendelige svovelpose for Ã¥ bistÃ¥ med innsatsen til krigen." msgid "Endless Vial of Mercury" msgstr "Den uendelige kvikksølvkolben" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} gir deg %{count} enhet kvikksølv hver dag." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Et kort stopp ved en magimesters tÃ¥rn som har blitt forlatt i hastverk, " "avdekker en kolbe med kvikksølv som ser ut til Ã¥ alltid ha igjen litt pÃ¥ " "bunnen. Du kjenner igjen en skatt nÃ¥r du ser en, og du setter en kork i den " "og slipper den i tasken din." msgid "Endless Pouch of Gems" msgstr "Den uendelige edesteinsposen" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} gir deg %{count} enhet edelsten hver dag." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "En kortvarig regnbyge fÃ¥r regnbuen til Ã¥ dukke opp... og sannelig klarer du " "Ã¥ se enden pÃ¥ den. Du rir i full fart bort for Ã¥ gripe gullgryta som " "befinner seg der. Eieren dens, en regnbuegnom, klarer ikke Ã¥ hindre deg fra " "Ã¥ ta den og tilbyr heller en uendelig pose med edelstener i bytte mot gullet " "sitt. Du gÃ¥r med pÃ¥ det." msgid "Endless Cord of Wood" msgstr "Den uendelige vedfavnen" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} gir deg %{count} enheter ved hver dag." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Du tar en rast for lage bÃ¥l til matlaging og henter ved fra en haug med " "morken ved i nærheten. I mens du henter ved fra haugen legger du merke til " "at den ikke blir mindre. Du innser til din glede at veden er fortryllet og " "du tar den derfor med deg." msgid "Endless Cart of Ore" msgstr "Den uendelige malmvogna" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} gir deg %{count} enheter malm hver dag." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Du har kommet over en vettesmed som lager vÃ¥pen til bruk mot mennesker. Med " "et mektig brøl stormer du og hæren din ned pÃ¥ leiren og jager dem vekk. " "Ransakingen avdekker en magisk malmvogn som aldri gÃ¥r tom for jern." msgid "Endless Pouch of Crystal" msgstr "Den uendelige krystallposen" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} gir deg %{count} enhet krystall hver dag." #, fuzzy msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Du søker ly i en liten hule fra en storm og oppdager en liten mengde " "krystaller i et hjørne. Av nysgjerrighet brekker du av en bit og legger " "merke til at den opprinnelige krystallen gror den tapte delen tilbake. Du " "bestemmer deg for Ã¥ stappe hele mengden i en pose og tar den med deg." msgid "Spiked Helm" msgstr "Den piggete hjelmen" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Hæren din blir overfalt av en liten stamme av ville (og ikke særlig kloke) " "orker. Du tar lett hÃ¥nd om dem og de fÃ¥ overlevende flykter i alle " "retninger. En av orkene hadde pÃ¥ seg en blankpolert hjelm med pigger. Du " "tenker at den vil gjøre seg bra som en suvenir og tar den med deg." msgid "Spiked Shield" msgstr "Det piggete skjoldet" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Du kommer over ei bru som strekker seg over en uttørket kløft. Før du rekker " "Ã¥ krysse den dukker et troll opp fra under brua og krever betaling før det " "lar deg slippe forbi. Du nekter Ã¥ betale og trollet stormer mot deg, og du " "blir nødt til Ã¥ drepe det. Du tar det taggete skjoldet til det som trofé." msgid "White Pearl" msgstr "Den hvite perlen" #, fuzzy msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "En spasertur langs et uttørket brakkvann fÃ¥r et øyeblikks opphold nÃ¥r du " "oppdager noe usedvanlig: ei hvit perle blant noen ødelagte skjell og andre " "rester." msgid "Black Pearl" msgstr "Den sorte perlen" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Ryktene om en usedvanlig stor griff som terroriserte folk ute pÃ¥ landsbygda " "førte deg til hulen dens. Et raskt men brutal slag blir til slutten pÃ¥ " "beistet. Du gÃ¥r gjennom de groteske restene i redet og oppdager en stor, " "svart perle." msgid "Magic Book" msgstr "Tryllebok" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name}a gjør at du kan bruke trolldom." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Plassholder 2" msgid "The reserved artifact." msgstr "Plassholderskatten." msgid "Dummy 3" msgstr "Plassholder 3" msgid "Dummy 4" msgstr "Plassholder 4" msgid "Spell Scroll" msgstr "Trolldomsrull" #, fuzzy msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Denne %{name}en gir helten din evnen til Ã¥ bruke trolldommen %{spell}, gitt " "at helten din har ei tryllebok." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Du finner en detaljert beholder som rommer et gammelt pergament i " "kalveskinn. Runene pÃ¥ beholderen er veldig gamle, og hÃ¥ndverket som ligger " "bak den er fabelaktig. Idet du tar ut rullen føler du deg fylt med magisk " "kraft." msgid "Arm of the Martyr" msgstr "Martyrens arm" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} øker kraften din med %{count} men legger til vandød " "kampÃ¥ndspÃ¥virkning." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "En av de mindre begavede medlemmene av følget ditt plukker opp en arm fra " "bakken. Til tross for at den mangler en kropp, beveger den seg. Styrkene " "dine syns den kroppsløse armen er motbydelig, men du klarer ikke Ã¥ fÃ¥ deg " "til Ã¥ kaste den: den ser ut til Ã¥ ha en slags magisk pÃ¥virkning over " "beslutningsevnen din." msgid "Breastplate of Anduran" msgstr "Andurans brystplate" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} øker forsvarsevnen din med %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Du kommer over et skilt. Det stÃ¥r: \"Her ligger kroppen til Anduran. Bøy deg " "og sverg troskap, og du vil bli belønnet.\" Du bestemmer deg for Ã¥ gjøre det " "som stÃ¥r. Idet du reiser deg, føler du en kulde treffe huden din. NÃ¥r du ser " "ned oppdager du at du plutselig har pÃ¥ deg en skinnende og vakker brystplate." msgid "Broach of Shielding" msgstr "BrystnÃ¥len av beskyttelse" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} gir %{count} prosent beskyttelse mot ragnarok og elementær storm, " "men minsker kraften med 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "En snill trollkjerring syns at forsvarsevnen til hæren din kunne ha trengt " "en magisk forsterkning. Hun tilbyr Ã¥ fortrylle brystnÃ¥len du har pÃ¥ kappen " "din, og du godtar det." msgid "Battle Garb of Anduran" msgstr "Andurans kamputstyr" #, fuzzy msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} slÃ¥r sammen kreftene til alle Andurans tre skatter. Den gir maksimal " "flaks og kampÃ¥nd til styrkene dine og gir deg mulighet til Ã¥ bruke " "trolldommen Byportal." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Av medlidenhet til en fattig bonde kjøper du ei kiste med gammelt skrap som " "han selger for alt for mye gull. Senere mens du gÃ¥r gjennom den oppdager du " "at den inneholder de 3 delene av det legendariske kamputstyret til Anduran!" msgid "Crystal Ball" msgstr "Krystallkule" #, fuzzy msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name}n lar deg fÃ¥ mer detaljert informasjon om monster, fiendtlige helter " "og borger i nærheten av helten som holder den." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Du kommer over en karavane med vandringsfolk som storfester og fyller " "kroppene sine med mjød. De kaller deg fram og sier \"Hvis du kan bevise at " "du kan danse Rama-Butaen vil vi belønne deg.\" Du kan den ikke, men prøver " "likevel. De ler seg i hjel, men beundrer motet ditt og gir deg en " "krystallkule." msgid "Heart of Fire" msgstr "Ildhjerte" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name}t gir %{count} prosent beskyttelse mot ild, men dobler skaden fra " "kulde." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Du kommer inn i en nylig nedbrent skogsklarning og møter en ildÃ¥nd som " "sitter pÃ¥ en stein. Den ser opp pÃ¥ deg med sitt brennende ansikt, og et " "uttrykk preget av sterk smerte. Plutselig kaster den et skinnende objekt pÃ¥ " "deg. Du tar fram hendene dine for Ã¥ skjerme deg, men det gÃ¥r rett igjennom " "dem og brenner seg inn i brystkassa di." msgid "Heart of Ice" msgstr "Ishjerte" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name}t gir %{count} prosent beskyttelse mot kulde, men dobler skaden fra " "ild." #, fuzzy msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Ut av intet griper en sterk kulde fatt i kroppen din. Du fryser til og " "faller av hesten din. Smerten gÃ¥r over, men det føles fortsatt ut som at " "brystkassa di er av is. Du tar deg selv opp fra bakken og hører en rungende " "latter. Du snur deg rundt akkurat i tide til Ã¥ fÃ¥ øye pÃ¥ en frostkjempe som " "løper av gÃ¥rde inn i skogen og forsvinner." msgid "Helmet of Anduran" msgstr "Andurans hjelm" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Du fÃ¥r øynene pÃ¥ en glinsende gjenstand som stikker opp av bakken. Du sender " "en ufrivillig frivillig fra følget ditt bort for Ã¥ ta en nærmere titt. Han " "kommer tilbake med en gyllen hjelm i hendene. Du innser at det mÃ¥ være " "hjelmen til den legendariske Anduran, det eneste mennesket kjent for Ã¥ bruke " "en rustning laget av rent gull." msgid "Holy Hammer" msgstr "Den hellige hammeren" #, fuzzy msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Du kommer over en slagmark hvor en ridderhelt har blitt dødelig sÃ¥ret av en " "gruppe zombier. Han ber deg om Ã¥ ta hammeren hans og avslutte det han " "begynte. Idet du plukker den opp, begynner den Ã¥ dure før alt blir tÃ¥kete " "for deg. NÃ¥r du kommer til igjen, ligger zombiene døde, og det drypper blod " "fra hammeren. Du fester hammeren til beltet ditt." msgid "Legendary Scepter" msgstr "Septeret av legender" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} legger til %{count} poeng til alle egenskapene dine." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Idet du kommer til toppen av en kolle, kommer du over et latterlig syn: en " "fe som prøver Ã¥ bære et septer som er nesten like stort som seg selv. " "Samtidig som du prøver Ã¥ holde deg fra Ã¥ le, spør du \"Trenger du hjelp?\" " "Feen myser bort pÃ¥ deg og svarer: \"Syns du dette er morsomt? Greit. Da kan " "DU fÃ¥ bære den. Jeg foretrekker Ã¥ fly uansett.\"" msgid "Masthead" msgstr "Mastetoppen" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "%{name} øker flaksen og kampÃ¥nden din med %{count} under sjøslag." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "En gammel sjøulk forteller deg en historie om en fortryllet mastetopp som " "han brukte i sine yngre dager for Ã¥ samle mannskapet sitt i vanskelig " "farvann. Han gir deg deretter et falmet kart som viser hvor han gjemte den. " "Etter mye leting finner du den bortgjemt under en brygge i nærheten." msgid "Sphere of Negation" msgstr "Kulen av benektelse" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} stanser all bruk av trolldom for begge sider i kampen." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Du stanser for Ã¥ hjelpe en bonde med Ã¥ fange en løpsk hingst. For Ã¥ vise sin " "takknemmelighet gir han deg en liten kule. Idet du griper den føler du den " "magiske energien tappes fra lemmene dine." msgid "Staff of Wizardry" msgstr "Trolldomsstaven" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} øker kraften din med %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Imens de var ute og fanget vilt fant styrkene dine en mystisk stav som " "svevde en meter over bakken. De overrekker deg den og du legger merke til en " "innrisset tekst. Det stÃ¥r: \"Vett slÃ¥r muskler og magi trumfer et slag. Lytt " "til mine ord og du vil vinne hver dag.\"" msgid "Sword Breaker" msgstr "Sverdknuser" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name}en øker forsvarsevnen din med %{count} og angrepsevnen med 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "En tidligere kaptein av vaktstyrkene blir grepet av respekt for deg nÃ¥r han " "fÃ¥r høre om oppdraget ditt, og han gir deg den magiske sverdknuseren som han " "satte sin lit til da han var i tjeneste." msgid "Sword of Anduran" msgstr "Andurans sverd" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Et troll stopper deg og sier: \"Betal meg 5000 gullstykker, ellers vil " "Andurans sverd ende ditt liv her og nÃ¥.\" Du nekter. Trollet griper tak i " "sverdet pÃ¥ beltet sitt, gir fra seg et ul av smerte, og løper vekk. Mens du " "plukker opp det berømte sverdet, er du takknemlig for at tomsete troll ofte " "griper tak i feil ende av skarpe gjenstander." msgid "Spade of Necromancy" msgstr "Sortekunstnerens spade" #, fuzzy msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} forbedrer sortekunstevnen din." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "En skitten spade har blitt kjørt inn i en jordhaug i nærheten. Ved en " "nærmere titt oppdager du at det er den fortryllede spaden til Gravleggerne, " "lenge trodd Ã¥ være forsvunnet av de dødelige." msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Ved" msgid "Mercury" msgstr "Kvikksølv" msgid "Ore" msgstr "Malm" msgid "Sulfur" msgstr "Svovel" msgid "Crystal" msgstr "Krystall" msgid "Gems" msgstr "Edelstener" msgid "Gold" msgstr "Gull" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Det fins sju rÃ¥varer i Heroes II. Disse brukes til Ã¥ bygge pÃ¥ og forbedre " "byer, samt Ã¥ verve krigere og helter.\n" "Gull er den vanligste rÃ¥varen og trengs i bunn og grunn til alt.\n" "Ved og malm blir brukt til de fleste bygninger.\n" "Edelstener, kvikksølv, svovel og krystall er sjeldne, magiske rÃ¥varer som " "trengs for de sterkeste krigerne og mest avanserte bygningene." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "FÃ¥r en stor ildkule til Ã¥ slÃ¥ ned pÃ¥ det utvalgte omrÃ¥det og skader alle " "nærstÃ¥ende krigere." msgid "Fireball" msgstr "Ildkule" msgid "Fireblast" msgstr "Ildblest" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "En forbedret utgave av ildkulen. Ildsmellet pÃ¥virker to felt rundt " "midtpunktet for trolldommen, i stedet for kun én." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Sender et kraftig elektrisk støt ned pÃ¥ en utvalgt kriger." msgid "Lightning Bolt" msgstr "Lynnedslag" msgid "Chain Lightning" msgstr "Kjedelyn" #, fuzzy msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "FÃ¥r et støt av elektrisk kraft til Ã¥ slÃ¥ ned pÃ¥ den utvalgte krigeren, " "deretter pÃ¥ den nærmeste krigeren med kun halvparten av styrken, og sÃ¥ pÃ¥ " "den som er nærmest den igjen med nok en gang halvparten, og sÃ¥ videre helt " "til lynet blir sÃ¥ svakt at det gjør skade. Advarsel: Denne trolldommen kan " "treffe dine egne krigere!" msgid "Teleport" msgstr "" "Tele-\n" "portering" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Teleporterer den utvalgte krigeren til en ledig rute pÃ¥ slagmarken." msgid "Cure" msgstr "Kur" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Fjerner alle ugunstige trolldommer fra en av dine krigere og helbreder " "%{count} liv for hvert nivÃ¥ av brukerens kraft." msgid "Mass Cure" msgstr "Helbredelse" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Fjerner alle ugunstige trolldommer og helbreder %{count} livspoeng per " "kraftsnivÃ¥ pÃ¥ alle krigerne dine." msgid "Resurrect" msgstr "" "Gjen-\n" "opplivning" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Gjenoppliver krigere fra en skadet eller død tropp, men kun fram til kampens " "slutt." msgid "Resurrect True" msgstr "" "Sann gjen-\n" "opplivning" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Gjenoppliver krigere fra en skadet eller død tropp permanent." msgid "Haste" msgstr "Hast" msgid "Increases the speed of any creature by %{count}." msgstr "Øker hurtigheten til én kriger med %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Øker hurtigheten til alle krigerne dine med %{count}." msgid "Mass Haste" msgstr "Full hast" msgid "Slows target to half movement rate." msgstr "Halverer skrittene og minsker hurtigheten til mÃ¥let." msgid "spell|Slow" msgstr "" "Forsink-\n" "else" msgid "Mass Slow" msgstr "" "Full for-\n" "sinkelse" msgid "Slows all enemies to half movement rate." msgstr "Reduserer alle fiender ned til halvparten av skrittene deres." msgid "spell|Blind" msgstr "Forblinding" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" "TÃ¥kelegger øynene til den pÃ¥virkede krigeren slik at den ikke fÃ¥r til Ã¥ " "flytte seg." msgid "Bless" msgstr "Velsignelse" msgid "Causes the selected creatures to inflict maximum damage." msgstr "FÃ¥r den utvalgte krigeren til Ã¥ gjøre maksimal skade." msgid "Causes all of your units to inflict maximum damage." msgstr "FÃ¥r alle krigerne dine til Ã¥ gjøre maksimal skade." msgid "Mass Bless" msgstr "Forhelligelse" msgid "Magically increases the defense skill of the selected creatures." msgstr "Øker pÃ¥ magisk vis forsvarsevnen til den utvalgte krigeren." msgid "Stoneskin" msgstr "Stenhud" msgid "Steelskin" msgstr "StÃ¥lhud" #, fuzzy msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Øker forsvarsevnen til de utvalgte krigerne. Dette er en forbedret utgave av " "stenhud." msgid "Causes the selected creatures to inflict minimum damage." msgstr "FÃ¥r den utvalgte krigeren til Ã¥ gjøre minst mulig skade." msgid "Curse" msgstr "Forbannelse" msgid "Causes all enemy troops to inflict minimum damage." msgstr "FÃ¥r alle fiendtlige tropper til Ã¥ gjøre minst mulig skade." msgid "Mass Curse" msgstr "Besvergelse" msgid "Damages all undead in the battle." msgstr "Skader alle vandøde pÃ¥ slagmarken." msgid "Holy Word" msgstr "Hellig ord" #, fuzzy msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Skader alle vandøde i kampen. Dette er en forbedret utgave av hellig ord." msgid "Holy Shout" msgstr "Hellig rop" msgid "Anti-Magic" msgstr "" "Trolldoms-\n" "vern" # en enkelt? flere? #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Skjermer den utvalgte krigeren mot skadelig magi." msgid "Dispel Magic" msgstr "" "Magi-\n" "opphevelse" msgid "Removes all magic spells from a single target." msgstr "Fjerner alle trolldommer fra mÃ¥let." msgid "Mass Dispel" msgstr "" "All-\n" "opphevelse" msgid "Removes all magic spells from all creatures." msgstr "Fjerner all trolldom fra alle krigere, bÃ¥de vennlige og fiendtlige." msgid "Causes a magic arrow to strike the selected target." msgstr "Skyter en magisk pil pÃ¥ det utvalgte mÃ¥let." msgid "Magic Arrow" msgstr "Tryllepil" msgid "Berserker" msgstr "Berserk" # nabo? msgid "Causes a creature to attack its nearest neighbor." msgstr "" "FÃ¥r en kriger til Ã¥ angripe dens nærmeste tropp, uavhengig om den er vennlig " "eller fiendtlig." msgid "Armageddon" msgstr "Dommedag" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Hellig forferdelse slÃ¥r ned pÃ¥ slagmarken og gjør alvorlig skade pÃ¥ alle " "krigere." msgid "Elemental Storm" msgstr "Elementær storm" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Magiske elementer høljer ned pÃ¥ slagmarken og skader alle krigere." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Et regn av steiner hamrer ned pÃ¥ et omrÃ¥de av slagmarken, og skader alle " "krigere innenfor trolldommens rekkevidde." msgid "Meteor Shower" msgstr "Meteorregn" msgid "Paralyze" msgstr "Lammelse" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "De utvalgte krigerne lammes og fÃ¥r ikke til Ã¥ flytte pÃ¥ seg eller Ã¥ slÃ¥ " "tilbake." msgid "Hypnotize" msgstr "Trollbinding" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "En enkelt fiendtlig kriger havner under din kontroll sÃ¥ lenge livene dens er " "mindre enn %{count} ganger kraften til helten din." msgid "Cold Ray" msgstr "KuldestrÃ¥le" msgid "Drains body heat from a single enemy unit." msgstr "PÃ¥fører ekstrem kulde pÃ¥ en enkelt fiendtlig kriger." msgid "Cold Ring" msgstr "Kuldering" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "PÃ¥fører ekstrem kulde pÃ¥ alle krigerne omkring sentrum av mÃ¥lomrÃ¥det. " "Krigeren i midten unngÃ¥r skade." msgid "Disrupting Ray" msgstr "" "Forvitrings-\n" "strÃ¥le" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Svekker forsvarsevnen til en fiendtlig tropp med 3." msgid "Damages all living (non-undead) units in the battle." msgstr "Skader alle levende (ikke vandøde) styrker pÃ¥ slagmarken." msgid "Death Ripple" msgstr "" "Døds-\n" "krusning" msgid "Death Wave" msgstr "Dødsbølge" #, fuzzy msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Skader alle levende (ikke-vandøde) tropper i kampen. Denne trolldommen er en " "forbedret utgave av dødskrusning." msgid "Dragon Slayer" msgstr "Dragebane" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "En tropp fÃ¥r sitt angrep voldsomt forsterket mot drager." msgid "Blood Lust" msgstr "Blodlyst" msgid "Increases a unit's attack skill." msgstr "Øker en tropp sin angrepsevne." msgid "Animate Dead" msgstr "" "Døde-\n" "besjelning" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "Gjenreiser krigere fra en skadet eller død vandød tropp permanent." msgid "Mirror Image" msgstr "Speilbilde" # tilsynelatende ekte , uvirkelig, # etterligner # kopierer #, fuzzy msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Tryller fram en illusjonstropp av samme slaget som en av dine eksisterende " "tropper. Denne falske troppen skader like mye som en ekte, men skulle den ta " "noe som helst skade sÃ¥ forsvinner den." msgid "Shield" msgstr "Skjold" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halverer skade en enkelt kriger tar fra skuddangrep. Dette pÃ¥virker ikke " "skudd fra tÃ¥rn og ballister." msgid "Mass Shield" msgstr "" "For-\n" "skansning" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halverer skade fra skuddangrep pÃ¥ alle dine styrker. Dette pÃ¥virker ikke " "skudd fra tÃ¥rn og ballister." msgid "Summon Earth Elemental" msgstr "Tilkall jordÃ¥nd" msgid "Summons Earth Elementals to fight for your army." msgstr "Maner fram en jordÃ¥nd for Ã¥ kjempe pÃ¥ din side." msgid "Summon Air Elemental" msgstr "Tilkall luftÃ¥nd" msgid "Summons Air Elementals to fight for your army." msgstr "Maner fram en luftÃ¥nd for Ã¥ kjempe pÃ¥ din side." msgid "Summon Fire Elemental" msgstr "Tilkall ildÃ¥nd" msgid "Summons Fire Elementals to fight for your army." msgstr "Maner fram en ildÃ¥nd for Ã¥ kjempe pÃ¥ din side." msgid "Summon Water Elemental" msgstr "Tilkall vannÃ¥nd" msgid "Summons Water Elementals to fight for your army." msgstr "Maner fram en vannÃ¥nd for Ã¥ kjempe pÃ¥ din side." msgid "Damages castle walls." msgstr "Skader ringmuren." msgid "Earthquake" msgstr "Jordskjelv" msgid "Causes all mines across the land to become visible." msgstr "Viser alle gruvene pÃ¥ kartet." msgid "View Mines" msgstr "Vis gruver" msgid "Causes all resources across the land to become visible." msgstr "Viser alle rÃ¥varene pÃ¥ kartet." msgid "View Resources" msgstr "Vis rÃ¥varer" msgid "Causes all artifacts across the land to become visible." msgstr "Viser alle kartets skatter." msgid "View Artifacts" msgstr "Vis skatter" msgid "Causes all towns and castles across the land to become visible." msgstr "Viser alle kartets borger og byer." msgid "View Towns" msgstr "Vis byer" msgid "Causes all Heroes across the land to become visible." msgstr "Viser alle kartets helter." msgid "View Heroes" msgstr "Vis helter" msgid "Causes the entire land to become visible." msgstr "Viser alt pÃ¥ hele kartet." msgid "View All" msgstr "Vis alt" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "Lar magibrukeren se detaljert informasjon om fiendtlige helter." msgid "Summon Boat" msgstr "Tilkall skip" #, fuzzy msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Tilkaller det nærmeste ledige og vennlige skipet til det nærmeste " "kystpunktet. Med vennlig skip menes et som du har lagd eller som du var den " "siste til Ã¥ benytte." msgid "Allows the caster to magically transport to a nearby location." msgstr "Transporterer helten pÃ¥ magisk vis til et utvalgt sted i nærheten." # Dimensjon brukes egentlig ikke slik pÃ¥ norsk: verdensportal, verdensdør? msgid "Dimension Door" msgstr "" "Verdens-\n" "portal" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Sender helten til en hvilken som helst by eller borg i heltens nÃ¥værende " "besittelse." msgid "Town Gate" msgstr "Byflukt" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Sender helten tilbake til en utvalgt by eller en borg, gitt at den tilhører " "spilleren." msgid "Visions" msgstr "Syner" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Forutser det mest sannsynlige utfallet av et sammenstøt med en nøytral " "styrke." msgid "Haunt" msgstr "Hjemsøking" #, fuzzy msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "FÃ¥r gjenferd til Ã¥ hjemsøke ei gruve du eier. Denne gruva slutter da Ã¥ " "produsere rÃ¥varer. (Hvis jeg ikke fÃ¥r beholde den skal ingen fÃ¥ det!)" msgid "Set Earth Guardian" msgstr "Plasser jordvokter" # mot? msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Tilkaller en jordÃ¥nd for Ã¥ vokte over ei gruve mot fiendtlige styrker." msgid "Set Air Guardian" msgstr "Plasser luftvokter" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Tilkaller en luftÃ¥nd for Ã¥ vokte over ei gruve mot fiendtlige styrker." msgid "Set Fire Guardian" msgstr "Plasser ildvokter" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Tilkaller en ildÃ¥nd for Ã¥ vokte over ei gruve mot fiendtlige styrker." msgid "Set Water Guardian" msgstr "Plasser vannvokter" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Tilkaller en vannÃ¥nd for Ã¥ vokte over ei gruve mot fiendtlige styrker." #, fuzzy msgid "Random Spell" msgstr "Tilfeldig" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "VilkÃ¥rlig borg" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "Forstening" #, fuzzy msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Forvandler den pÃ¥virkede krigeren til sten. En forstenet kriger tar halv " "skade fra fysiske angrep." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Du har ingen tryllebok og kan derfor ikke bruke magi." msgid "No spell to cast." msgstr "Ingen trolldommer tilgjengelige." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Helten din har %{point} mana igjen." msgid "View Adventure Spells" msgstr "Vis kartmagi" msgid "View Combat Spells" msgstr "Vis kampmagi" msgid "View previous page" msgstr "Vis forrige side" msgid "View next page" msgstr "Vis neste side" msgid "Close Spellbook" msgstr "Lukk trylleboka" msgid "View %{spell}" msgstr "Vis %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Denne trolldommen gjør %{damage} skadepoeng." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Denne trolldommen tilkaller\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Denne trolldommen fyller opp %{hp} liv." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Denne trolldommen tilkaller %{count} %{monster} for Ã¥ beskytte gruva." msgid "The nearest town is %{town}." msgstr "Den nærmeste byen er %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Denne byen er blokkert av helten din %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Denne trolldommen gir deg kontroll over\n" "opptil %{hp} liv." msgid "The ultimate artifact is really the %{name}." msgstr "Den sjeldneste skatten er faktisk %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Den sjeldneste gjenstanden befinner seg et sted %{name} verden." msgid "north-west" msgstr "nordvest i" msgid "north" msgstr "nord i" msgid "north-east" msgstr "nordøst i" msgid "west" msgstr "vest i" msgid "center" msgstr "i midten av" msgid "east" msgstr "øst i" msgid "south-west" msgstr "sørvest i" msgid "south" msgstr "sør i" msgid "south-east" msgstr "sørøst i" msgid "The truth is out there." msgstr "Sannheten er der ute." msgid "The dark side is stronger." msgstr "Den mørke siden er sterkere." msgid "The end of the world is near." msgstr "Verdens ende er nær." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" "Skjelettet til baron Myrder ligger begravd under grunnmuren til arenaen." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "En svartdrage klarer Ã¥ slÃ¥ ut en titan en hvilken som helst dag i uka." #, fuzzy msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" "Han sa til henne: \"Bla, bla, bla...\", og da svarte hun: \"Bla, bla, bla..." "\"" msgid "An unknown force is being resurrected..." msgstr "En ukjent styrke holder pÃ¥ Ã¥ komme tilbake..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Finn den siste oppdateringen av spillet pÃ¥\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Velg mengde %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Skru pÃ¥ autokamp" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "Fullfør kamp med autotrekk" #~ msgid "Please Remember" #~ msgstr "Merk" # Needs extra whitespace to avoid yellow word splitting #, fuzzy #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "Du kan alltid bytte oppløsning ved Ã¥ klikke pÃ¥ " #~ msgid "door" #~ msgstr "døra" #, fuzzy #~ msgid "NEW GAME" #~ msgstr "" #~ "NYTT\n" #~ "PARTI" #~ msgid "Warning!" #~ msgstr "Advarsel!" #~ msgid "Dummy 1" #~ msgstr "Plassholder 1" fheroes2-1.1.6+dfsg/files/lang/nl.po000066400000000000000000006537571476115357100172100ustar00rootroot00000000000000# Dutch translation for fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2022-10-25 08:52+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: Dutch \n" "Language: nl\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-Launchpad-Export-Date: 2010-05-27 09:12+0000\n" "X-Generator: Poedit 3.1.1\n" msgid "" "NEW\n" "GAME" msgstr "" msgid "" "SAVE\n" "GAME" msgstr "" msgid "" "LOAD\n" "GAME" msgstr "" msgid "INFO" msgstr "" msgid "QUIT" msgstr "" msgid "" "NEW\n" "MAP" msgstr "" msgid "" "SAVE\n" "MAP" msgstr "" msgid "" "LOAD\n" "MAP" msgstr "" msgid "CANCEL" msgstr "" msgid "OKAY" msgstr "" msgid "ACCEPT" msgstr "" msgid "DECLINE" msgstr "" msgid "LEARN" msgstr "" msgid "TRADE" msgstr "" msgid "YES" msgstr "" msgid "NO" msgstr "" msgid "EXIT" msgstr "" msgid "smallerButton|EXIT" msgstr "" msgid "DISMISS" msgstr "" msgid "UPGRADE" msgstr "" msgid "RESTART" msgstr "" msgid "HEROES" msgstr "" msgid "" "TOWNS/\n" "CASTLES" msgstr "" msgid "S" msgstr "" msgid "M" msgstr "" msgid "L" msgstr "" msgid "X-L" msgstr "" msgid "ALL" msgstr "" msgid "SELECT" msgstr "" msgid "" "STANDARD\n" "GAME" msgstr "" msgid "" "BATTLE\n" "ONLY" msgstr "" "ALLEEN\n" "STRIJD" msgid "" "CAMPAIGN\n" "GAME" msgstr "" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" msgid "CONFIG" msgstr "" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" msgid "HOT SEAT" msgstr "" msgid "2 PLAYERS" msgstr "" msgid "3 PLAYERS" msgstr "" msgid "4 PLAYERS" msgstr "" msgid "5 PLAYERS" msgstr "" msgid "6 PLAYERS" msgstr "" msgid "GIFT" msgstr "DONEREN" msgid "MAX" msgstr "" msgid "DIFFICULTY" msgstr "NIVEAU" msgid "VIEW INTRO" msgstr "" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "" msgid "START" msgstr "" msgid "TOWN" msgstr "" msgid "CASTLE" msgstr "" msgid "RESTRICT" msgstr "" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Strijder" msgid "Builder" msgstr "Bouwer" msgid "Explorer" msgstr "Ontdekker" msgid "None" msgstr "Geen" msgid "" "A few\n" "%{monster}" msgstr "" "Een paar\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Meerdere\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Een groep van\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Veel\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Een horde van\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Een menigte van\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Een zwerm van\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Honderden\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Een legioen van\n" "%{monster}" msgid "army|Few" msgstr "Een paar" msgid "army|Several" msgstr "Meerdere" msgid "army|Pack" msgstr "Groep" msgid "army|Lots" msgstr "Veel" msgid "army|Horde" msgstr "Horde" msgid "army|Throng" msgstr "Menigte" msgid "army|Swarm" msgstr "Zwerm" msgid "army|Zounds" msgstr "Honderden" msgid "army|Legion" msgstr "Legioen" msgid "All %{race} troops +1" msgstr "Alle %{ras} troepen +1" msgid "NeutralRaceTroops|Neutral" msgstr "" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Troepen van %{count} uitlijningen -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "Enkele ondoden in groepen -1" msgid "" "Default\n" "troop" msgstr "" msgid "View %{name}" msgstr "Zie %{name}" msgid "Move the %{name} " msgstr "Beweeg de %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Beweeg of rechter click om %{name} te herverdelen" msgid "Combine %{name} armies" msgstr "Combineer %{name} legers" msgid "Exchange %{name2} with %{name}" msgstr "Ruil %{name2} met %{name}" msgid "Select %{name}" msgstr "Selecteer %{name}" msgid "Cannot move last troop" msgstr "Kan laatste troep niet verplaatsen" msgid "Move the %{name}" msgstr "Verplaats de %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Schiet %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} vernietigd helft van de veihandelijke troepen!" msgstr[1] "%{name} vernietigd helft van de veihandelijke troepen!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} heeft de automatische wedstrijd uitgezet" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} heeft de automatische wedstrijd aangezet!" msgid "Spell failed!" msgstr "Spreuk gefaald!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Het Sphere of Negation artefact is in effect voor deze wedstrijd, alle " "strijd spreuken zijn uitgeschakeld." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Je hebt all een spreuk uitgesproken deze ronde." #, fuzzy msgid "That spell will have no effect!" msgstr "Die spreuk zal niemand beïnvloeden!" msgid "You may only summon one type of elemental per combat." msgstr "Je kan maar 1 type van elemental oproepen per strijd." #, fuzzy msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Er is geen open plek aangrenzend bij je held om een Elemental naar toe te " "oproepen." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "De Moat verminderd by -%{count} de verdedgings vaardigheid van een eenheid " "en versloomt naar de helft van de bewegings snelheid" msgid "Speed: %{speed}" msgstr "Snelheid: %{speed}" msgid "Speed" msgstr "Snelheid" msgid "Off" msgstr "Uit" msgid "On" msgstr "Aan" #, fuzzy msgid "Turn Order" msgstr "Legerorde" msgid "Auto Spell Casting" msgstr "Automatisch spreuk uitroepen" msgid "Grid" msgstr "Rooster" msgid "Shadow Movement" msgstr "Schaduw Beweging" msgid "Shadow Cursor" msgstr "Schaduw Cursor" msgid "Audio" msgstr "" msgid "Settings" msgstr "" msgid "Configure" msgstr "" msgid "Hot Keys" msgstr "" msgid "Damage Info" msgstr "" msgid "Set the speed of combat actions and animations." msgstr "Zet de snelheid van gevechts acties en animaties." #, fuzzy msgid "Toggle to display the turn order during the battle." msgstr "Schakel om het legerorde weer te geven tijdens het gevecht." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Schakel wel of niet de computer spreuken voor je zal uitspreken waneer " "automatisch vechten aan staat. (Opmerking: Dit heeft geen invloed op " "spreuken uitspreken voor computer spelers hoe dan ook, het heeft ook geen " "invloed op snel vechten.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Schakel het hex raster aan of uit. Het hex raster onderlijnt altijd " "beweeging, even als uitgeschakeld. Deze schakel bepaalt alleen of het raster " "zichtbaar is." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Schakel aan of uit of schaduwen worden weergegeven waar je schepsels kunnen " "bewegen en aanvallen." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Schakel aan of uit een schaduw die de huidige hex-locatie van de muiscursor " "toont." msgid "Change the audio settings of the game." msgstr "" msgid "Check and configure all the hot keys present in the game." msgstr "" #, fuzzy msgid "Toggle to display damage information during the battle." msgstr "Schakel om het legerorde weer te geven tijdens het gevecht." msgid "Exit this menu." msgstr "" msgid "Okay" msgstr "" msgid "The enemy has surrendered!" msgstr "De vijand heeft zich overgegeven!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "De vijand is gevlucht!" msgid "A glorious victory!" msgstr "Een glorieuze overwinning!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Voor moed in de strijd, %{name} ontvangt %{exp} ervaring." msgid "The cowardly %{name} flees from battle." msgstr "De laffe %{name} vlucht voor de strijd." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} geeft zich over aan de vijand en vertrekt in schaamte." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "Je strijdmacht lijdt een bittere nederlaag en %{name} geeft je zaak op." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Je strijdmacht lijdt een bittere nederlaag." msgid "Battlefield Casualties" msgstr "Slachtoffers op het slagveld" msgid "Attacker" msgstr "Aanvaller" msgid "Defender" msgstr "Verdediger" msgid "Click to leave the battle results." msgstr "" #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Restart" msgstr "" msgid "You have captured an enemy artifact!" msgstr "Je hebt een vijandelijk artefact gevangen!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Als je naar de %{name} reikt, verdwijnt deze op mysterieuze wijze." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" "Als je vijand naar de %{name} reikt, verdwijnt deze op mysterieuze wijze." msgid "Necromancy!" msgstr "Necromantie!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Door de duistere kunst van necromantie te beoefenen, ben je in staat om " "%{count} van de vijandelijke doden te verhogen om terug te keren onder jouw " "dienst als %{monster}." msgid "%{name} the %{race}" msgstr "%{name} de %{race}" msgid "Captain of %{name}" msgstr "Kapitein van %{name}" msgid "Attack" msgstr "Aanval" msgid "Defense" msgstr "Verdedig" msgid "Spell Power" msgstr "Spreuk Kracht" msgid "Knowledge" msgstr "Kennis" msgid "Morale" msgstr "Moreel" msgid "Luck" msgstr "Geluk" msgid "Spell Points" msgstr "Spreuk Punten" msgid "Hero's Options" msgstr "Held's Opties" msgid "Cast Spell" msgstr "Spreuk uitspreken" msgid "Retreat" msgstr "Terugtrekken" msgid "Surrender" msgstr "Overgave" msgid "Cancel" msgstr "Annuleren" msgid "Hero Screen" msgstr "Held Scherm" msgid "Captain's Options" msgstr "Kapitein's Opties" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Spreek een magische spruik uit. Je kan maar 1 spreuk uitspreken per gevechts " "ronde. De ronde resets waneer elk schepsel een beurt heeft gehad." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Trek je held terug en laat je schepsels in de steek. Je held zal beschikbaar " "zijn om opnieuw te rekruteren, maar de held zal alleen de troepen van een " "beginnende held hebben." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Overgave kost geld. Echter als je het losgeld betaalt zal de held en al van " "de overlevende schepsels beschikbaar zijn om opnieuw te rekruteren." msgid "Open Hero Screen to view full information about the hero." msgstr "" "Open het heldenscherm om volledige informatie over de held te bekijken." msgid "Return to the battle." msgstr "Keer terug naar de strijd." msgid "Not enough gold (%{gold})" msgstr "Niet genoeg goud (%{gold})" msgid "%{name} states:" msgstr "%{name} staat:" msgid "Captain of %{name} states:" msgstr "De Kapitein van %{name} staat:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Ik zal je overgave accepteren en jou en je troepen een veilige doorgang " "geven voor de prijs van %{price} goud.\"" msgid "View %{monster} info" msgstr "Bekijk de info van %{monster}" msgid "Fly %{monster} here" msgstr "Vlieg %{monster} hier" msgid "Move %{monster} here" msgstr "Beweeg %{monster} hier" msgid "Shoot %{monster}" msgstr "Schiet %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 schot over)" msgstr[1] "(%{count} schoten over)" msgid "Attack %{monster}" msgstr "Val %{monster} aan" msgid "Turn %{turn}" msgstr "Draai %{turn}" msgid "Teleport here" msgstr "Teleporteer hier" msgid "Invalid teleport destination" msgstr "Ongeldige teleporteers bestemming" msgid "Cast %{spell} on %{monster}" msgstr "%{spell} uitgesproken op %{monster}" msgid "Cast %{spell}" msgstr "%{spell} uitspreken" msgid "Select spell target" msgstr "Selecteer spreuk doelwit" msgid "View Ballista info" msgstr "Ballista-info bekijken" msgid "Ballista" msgstr "Ballista" #, fuzzy msgid "Automatic combat modes" msgstr "Automatisch Vechten" #, fuzzy msgid "Automatic Combat Modes" msgstr "Automatisch Vechten" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Systeem instellingen aanpassen" msgid "Allows you to customize the combat screen." msgstr "Hiermee kan je het gevechts scherm aanpassen" msgid "System Options" msgstr "Systeem Instellingen" msgid "Skip this unit" msgstr "Deze eenheid overslaan" msgid "Skip" msgstr "Overslaan" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Slaat het huidige schepsel over. Het huidige schepsel eindigt zijn beurt en " "mag pas de volgende ronde weer gaan." msgid "View Captain's options" msgstr "Bekijk Kapitein's opties" msgid "View Hero's options" msgstr "Bekijk Held's opties" msgid "View opposing Captain" msgstr "Bekijk tegenstander Kapitein" msgid "View opposing Hero" msgstr "Bekijk tegenstander Held" msgid "Hide logs" msgstr "Logboeken verbergen" msgid "Show logs" msgstr "Logboeken weergeven" msgid "Message Bar" msgstr "Brichtenbalk" msgid "Shows the results of individual monster's actions." msgstr "Toont de resultaten van de acties van individuele monsters." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Weet je zeker dat je je wilt terugtrekken?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Hiermee kan de computer de strijd voor je uitvechten." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Automatisch Vechten" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Automatisch Vechten" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} slaat zijn beurt over." msgstr[1] "%{name} slaat zijn beurt over." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} doet %{damage} schade." msgstr[1] "%{attacker} doet %{damage} schade." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 schepsel vergaat." msgstr[1] "%{count} schepsels vergaan." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} vergaat." msgstr[1] "%{count} %{defender} vergaan." #, fuzzy msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "Het spiegelbeeld wordt gecreëerd." msgstr[1] "Het spiegelbeeld wordt gecreëerd." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "" msgstr[1] "" msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Bewoog %{monster}: van [%{src}] naar [%{dst}]" #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "De %{name} weerstaat de spreuk!" msgstr[1] "De %{name} weerstaat de spreuk!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} spreekt %{spell} uit op %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} spreekt %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "De %{spell} richt %{damage} schade aan een ondode schepsel." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "De %{spell} richt %{damage} schade aan aan alle ondode schepsels." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "De %{spell} richt %{damage} schade aan, %{count} schepsels komen om." msgid "The %{spell} does %{damage} damage." msgstr "De %{spell} richt %{damage} schade aan." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "De %{spell} richt %{damage} schade aan aan 1 levend schepsel." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "De %{spell} richt %{damage} schade aan aan alle levende schepsels." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "De aanval van %{attacker} verblindt de %{target}!" msgstr[1] "De aanval van %{attacker} verblindt de %{target}!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "De blik van de %{attacker} verandert het %{target} in steen!" msgstr[1] "De blik van de %{attacker} verandert het %{target} in steen!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "De vloek van de %{attacker} valt op de %{target}!" msgstr[1] "De vloek van de %{attacker} valt op de %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "De %{target} zijn verlamd door de %{attacker}!" msgstr[1] "De %{target} zijn verlamd door de %{attacker}!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "De %{attacker} verdrijft alle goede spreuken op je %{target}!" msgstr[1] "De %{attacker} verdrijft alle goede spreuken op je %{target}!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "De %{attacker} spreekt %{spell} uit op %{target}!" msgstr[1] "De %{attacker} spreekt %{spell} uit op %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Pech komt neer op de %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "Geluk komt neer op de %{attacker}" msgid "High morale enables the %{monster} to attack again." msgstr "Een hoog moreel stelt het %{monster} in staat opnieuw aan te vallen." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Een laag moreel zorgt ervoor dat het %{monster} in paniek bevriest." msgid "%{tower} does %{damage} damage." msgstr "%{tower} doet %{damage} schade." msgid "The mirror image is created." msgstr "Het spiegelbeeld wordt gecreëerd." msgid "The mirror image is destroyed!" msgstr "Het spiegelbeeld is vernietigd!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Weet je zeker dat je het automatisch vechten wilt onderbreken?" msgid "Error" msgstr "Fout" msgid "No spells to cast." msgstr "Geen spreuken om uit te spreken." msgid "Are you sure you want to retreat?" msgstr "Weet je zeker dat je je wilt terugtrekken?" msgid "Retreat disabled" msgstr "Terugtrekken uitgeschakeld" msgid "Surrender disabled" msgstr "Overgave uitgeschakeld" msgid "Damage: %{max}" msgstr "Schade: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Schade: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Vergaan: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Vergaan: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Door observatie met arendsogen kan %{name} de magische spreuk %{spell} leren." msgid "Human" msgstr "Mens" msgid "AI" msgstr "Computer" msgid "Start" msgstr "" #, fuzzy msgid "Start the battle." msgstr "Keer terug naar de strijd." msgid "Exit" msgstr "" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Selecteer een andere held." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1}" msgid "Monsters" msgstr "Monsters" msgid "N/A" msgstr "Nvt" msgid "Left Turret" msgstr "Linker torentje" msgid "Right Turret" msgstr "Rechter torentje" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "each with a +%{attack} bonus to their attack skill." msgstr "elk met een +%{attack} bonus voor hun aanvalsvaardigheid." #, fuzzy msgid "The %{name} is destroyed." msgstr "Het spiegelbeeld is vernietigd!" #, fuzzy msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} opstaan uit de dood!" msgstr[1] "%{count} %{name} opstaan uit de dood!" msgid "Dwarven Alliance" msgstr "Dwergen Alliantie" msgid "Sorceress Guild" msgstr "Tovenares Gilde" msgid "Necromancer Guild" msgstr "Necromancer gilde" msgid "Ogre Alliance" msgstr "Ogre Alliantie" msgid "Dwarfbane" msgstr "Drawven Moordenaar" msgid "Dragon Alliance" msgstr "Draken Alliantie" msgid "Elven Alliance" msgstr "Elven Alliantie" msgid "Kraeger defeated" msgstr "Kraeger verslagen" msgid "Wayward Son" msgstr "Wayward zoon" msgid "Uncle Ivan" msgstr "Oom Ivan" msgid "Annexation" msgstr "Annexatie" msgid "Force of Arms" msgstr "Kracht van Wapens" msgid "Save the Dwarves" msgstr "Red de Dwarfen" msgid "Carator Mines" msgstr "Caratormijnen" msgid "Turning Point" msgstr "Draaipunt" msgid "scenarioName|Defender" msgstr "Beschermer" msgid "Corlagon's Defense" msgstr "Corlagons Verdediging" msgid "The Crown" msgstr "De Kroon" msgid "The Gauntlet" msgstr "" msgid "Betrayal" msgstr "Veraad" msgid "Final Justice" msgstr "Laatste Gerechtigheid" #, fuzzy msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland heeft je nodig om de heren in de buurt van zijn kasteel te verslaan " "om zijn rebellie tegen zijn broer te beginnen. Ze zijn niet met elkaar " "verbonden, dus zullen ze het grootste deel van hun tijd met elkaar vechten. " "De overwinning is van jou als je al hun kastelen en helden hebt verslagen." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "De lokale heren weigeren trouw te zweren aan Roland en moeten worden " "onderworpen. Ze zijn rijk en machtig, dus wees voorbereid op een zwaar " "gevecht. Verover alle vijandelijke kastelen om te winnen." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Jouw taak is om de Dwergen te verdedigen tegen de troepen van Archibald. " "Verover alle vijandige steden en kastelen om te winnen, en zorg ervoor dat " "je niet alle dwergsteden in één keer verliest, anders heeft de vijand " "gewonnen." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Je neemt het op tegen vier geallieerde vijanden in een ongecompliceerd " "gevecht om grondstoffen en schatten. Verover alle vijandelijke kastelen voor " "de overwinning." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Je vijanden zijn tegen je geallieerd en beginnen dichtbij, dus wees klaar om " "te vechten. Je moet alle vier de kastelen in deze kleine vallei bezitten om " "te winnen." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Het Tovenaarsgilde van Noraston heeft Roland om hulp gevraagd tegen een " "aanval van Archibalds bondgenoten. Verover alle vijandelijke kastelen om te " "winnen, en verlies Noraston niet, anders verlies je het scenario. (Hint: er " "is een vijandelijk kasteel op een eiland in de oceaan.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Verzamel een zo groot mogelijk leger en verover het vijandelijke kasteel " "binnen 8 weken. Je wordt tegengewerkt door slechts één vijand, maar je moet " "een lange weg afleggen om bij het vijandelijke kasteel te komen. Alle " "troepen die je aan het einde van dit scenario in je leger hebt, zullen bij " "je zijn in het laatste gevecht." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Vind de kroon voordat de helden van Archibald hem vinden. Roland heeft de " "Kroon nodig voor het laatste gevecht tegen Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Drie geallieerde vijanden staan voor je en zegevieren, waaronder Lord " "Corlagon. Roland bevindt zich in een kasteel in het noordwesten en je zult " "verliezen als hij door de vijand valt. Onthoud dat het vangen van Lord " "Corlagon ervoor zal zorgen dat hij niet tegen je zal vechten in het laatste " "scenario." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Dit is de laatste strijd. Zowel jij als je vijand zijn tot de tanden " "bewapend, en ze zijn allemaal tegen je geallieerd. Vang Archibald om de " "oorlog te beëindigen!" #, fuzzy msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Als je van kant wisselt, krijg je drie kastelen tegen die van de vijand. " "Deze strijd zal de gemakkelijkste zijn die je de rest van de oorlog zult " "tegenkomen... verrader." msgid "Barbarian Wars" msgstr "Barbaarse Oorlogen" msgid "First Blood" msgstr "Eerste Bloed" msgid "Necromancers" msgstr "Necromancers" msgid "Slay the Dwarves" msgstr "Versla de Dwergen" msgid "Country Lords" msgstr "Landheren" msgid "Dragon Master" msgstr "Drakenmeester" msgid "Rebellion" msgstr "Opstand" msgid "Apocalypse" msgstr "Apocalypse" msgid "Greater Glory" msgstr "Grotere Glorie" #, fuzzy msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "King Archibald vereist dat je de drie vijanden in deze regio verslaat. Ze " "zijn niet met elkaar verbonden, dus zullen ze het grootste deel van hun " "energie onder elkaar vechten. Je wint als je alle vijandelijke kastelen " "bezit en er geen helden meer zijn om tegen te vechten." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Je moet de barbaarse stammen van het noorden verenigen door ze te veroveren. " "Net als in de vorige missie is de vijand niet geallieerd tegen jou, maar " "hebben ze meer middelen tot hun beschikking. Je wint als je alle " "vijandelijke kastelen bezit en er geen helden meer zijn om tegen te vechten." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Weldoener tovenaars hebben het kasteel van de Necromancers ingenomen. Je " "moet het heroveren om de overwinning te behalen. Onthoud dat terwijl je " "begint met een machtig leger, je geen kasteel hebt en er binnen 7 dagen een " "moet veroveren, anders verlies je deze strijd. (Hint: het dichtstbijzijnde " "kasteel ligt in het zuidoosten.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "De dwergen moeten worden overwonnen voordat ze zich kunnen bemoeien met de " "plannen van koning Archibald. Rolands strijdkrachten hebben om te beginnen " "meer dan één held en veel steden, dus wees voorbereid op aanvallen vanuit " "meerdere richtingen. Je moet alle vijandige steden en kastelen veroveren om " "de overwinning te claimen." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Je moet een boerenopstand neerslaan onder leiding van Rolands troepen. Ze " "zijn allemaal tegen je geallieerd, maar je hebt Lord Corlagon, een ervaren " "held, om je te helpen. Verover alle vijandelijke kastelen om te winnen." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Er zijn twee vijanden die tegen je geallieerd zijn in deze missie. Beiden " "zijn goed bewapend en proberen je van hun eiland te verdrijven. Ontwijk ze " "en verover Dragon City om te winnen." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Jouw orders zijn om de landheren te veroveren die gezworen hebben om Roland " "te dienen. Alle vijandige kastelen zijn tegen je verenigd. Aangezien je " "zonder kasteel begint, moet je je haasten om er voor het einde van de week " "een te veroveren. Verover alle vijandelijke kastelen voor de overwinning." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Vind de kroon voordat de helden van Roland hem vinden. Archibald heeft de " "Kroon nodig voor het laatste gevecht tegen Roland." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Dit is de laatste strijd. Zowel jij als je vijand zijn tot de tanden " "bewapend, en ze zijn allemaal tegen je geallieerd. Leg Roland vast om de " "oorlog te winnen en zorg ervoor dat je Archibald niet verliest in het " "gevecht!" msgid "Arrow's Flight" msgstr "De vlucht van de Pijl" msgid "Island of Chaos" msgstr "Eiland van Chaos" msgid "The Abyss" msgstr "De Afgrond" msgid "Uprising" msgstr "Opstand" msgid "Aurora Borealis" msgstr "Noorderlicht" msgid "Betrayal's End" msgstr "Het einde van verraad" msgid "Corruption's Heart" msgstr "Het hart van corruptie" msgid "The Giant's Pass" msgstr "De Reuzenpas" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Onderwerp de weerbarstige lokale heren om het rijk te voorzien van " "faciliteiten om in deze regio te opereren." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Elimineer alle oppositie op dit gebied. Dan is het eerste stuk van het " "artefact van jou." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "De tovenaressen in het noordoosten komen in opstand! Voor het welzijn van " "het rijk moet je hun zwakke opstand neerslaan op weg naar de bergen." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Kraeger heeft zich voorbereid op je komst en heeft een leger van " "necromancers geregeld om je zoektocht te dwarsbomen. Je moet het kasteel van " "Scabsdale veroveren voor de eerste dag van de derde week, anders zijn de " "Necromancers te sterk voor je." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "De barbaarse despoot in dit gebied is nog niet op de hoogte van je " "aanwezigheid. Bouw snel je troepen op voordat je ontdekt en aangevallen " "wordt! Beveilig de regio door alle vijandelijke troepen te onderwerpen." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Het rijk is zwak in deze regio. Je zult niet in staat zijn om alle troepen " "in dit gebied volledig te bedwingen, dus pak wat je kunt voordat " "represailles toeslaan. Onthoud dat je echte doel is om de Helm van Anduran " "te claimen." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Schakel Kraeger uit voor het welzijn van het rijk." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Eindelijk heb je de kans en de faciliteiten om het rijk te verlossen van het " "kwaad van de necromancer. Als je ze volledig uitroeit, word je voor altijd " "als een held bezongen." msgid "Border Towns" msgstr "Grenssteden" msgid "Conquer and Unify" msgstr "Verover en verenig" msgid "Crazy Uncle Ivan" msgstr "Gekke Oom Ivan" msgid "The Wayward Son" msgstr "De Eigenzinnige Zoon" msgid "Ivory Gates" msgstr "Ivoren Poorten" msgid "The Elven Lands" msgstr "De Elfen Landen" msgid "The Epic Battle" msgstr "De Epische Strijd" msgid "The Southern War" msgstr "De Zuidelijke Oorlog" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Verover en verenig alle vijandige stammen. Verlies de held Jarkonas niet, de " "voorvader van alle nakomelingen." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Je rivaal, het koninkrijk Harondale, valt zwakke steden aan je grens aan! " "Herstel van hun eerste aanval en verpletter ze volledig!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Vind je eigenzinnige zoon Joseph, van wie wordt gezegd dat hij in de " "verlaten landen woont. Doe het voor de eerste dag van de derde maand, anders " "heeft je gezin er niets aan." #, fuzzy msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Red je gekke oom Ivan. Vind hem voor de eerste dag van de vierde maand of " "het zal je koninkrijk niet helpen." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Vernietig de barbaren die de zuidelijke grens van je koninkrijk aanvallen! " "Herstel je gevallen steden en val dan het junglekoninkrijk binnen. Laat geen " "vijand staan." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Herover het kasteel van Ivory Gates, dat door verraad is gevallen." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Win de gunst van de elfen. Ze laten niet toe dat bomen worden gekapt, dus " "sturen ze je elke 2 weken hout. Je moet je missie voltooien vóór de eerste " "dag van de zevende maand, anders zal het koninkrijk zeker vallen." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Dit is de laatste strijd tegen je rivaliserende koninkrijk Harondale. " "Schakel iedereen uit en verlies de held Jarkonas VI niet." msgid "Fount of Wizardry" msgstr "Bron van Tovenarij" msgid "Power's End" msgstr "Einde van de macht" msgid "The Eternal Scrolls" msgstr "De Eeuwige Rollen" msgid "The Shrouded Isles" msgstr "De Gehulde Eilanden" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Jouw missie is om de strijdende magiërs op de magische Shrouded Isles te " "verslaan. De voltooiing van deze taak geeft je een vechtkans tegen je " "rivalen." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "De locatie van de grote bibliotheek is ontdekt! Je moet je weg ernaartoe " "vinden en de stad Chronos waarin het ligt terugwinnen." #, fuzzy msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Vind de bol van ontkenning, waarvan wordt gezegd dat deze in dit land " "begraven ligt. Er zijn aanwijzingen op stenen obelisken gegraveerd die je " "naar je prijs zullen leiden. Vind de bol vóór de eerste dag van de zesde " "maand, anders zullen je rivalen zeker de bron voor je hebben bereikt." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Je moet het kasteel van Magic overnemen, waar de bron van tovenarij ligt. " "Doe dit en je overwinning zal oppermachtig zijn." msgid "Blood is Thicker" msgstr "Bloed is Dikker" msgid "King and Country" msgstr "Koning en Land" msgid "Pirate Isles" msgstr "Pirateneilanden" msgid "Stranded" msgstr "Gestrand" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Verover de stad op het eiland voor de zuidoostkust om een boot te bouwen en " "terug te reizen naar het vasteland. Verlies de held Gallavant niet." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Vind en versla Martine, de piratenleider, die in Pirates Cove woont. Verlies " "Gallavant niet, anders is je zoektocht voorbij." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Schakel alle andere krachten uit die zich verzetten tegen de heerschappij " "van Lord Alberon. Gallavant mag niet sterven." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Omver de diepgewortelde monarchie van Lord Alberon en claim al het land in " "je naam. Gallavant mag niet sterven." msgid " bane" msgstr " vloek" msgid " alliance" msgstr " alliantie" msgid "Carry-over forces" msgstr "Overdrachtskrachten" msgid " bonus" msgstr " bonus" msgid " defeated" msgstr " verslagen" msgid " will always run away from your army." msgstr " zal altijd wegrennen van je leger." msgid " will be willing to join your army." msgstr " zal bereid zijn om zich bij je leger aan te sluiten." #, fuzzy msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "\"%{artifact}\" artefact zal over het scenario worden overgedragen." #, fuzzy msgid "The army will be carried over in the campaign." msgstr "Het leger zal het scenario overnemen." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Het koninkrijk zal elke dag +%{count} %{resource} hebben." #, fuzzy msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "De spreuk \"%{spell}\" wordt over het scenario overgedragen." #, fuzzy msgid "%{hero} can be hired during scenarios." msgstr "%{hero} kan worden ingehuurd in het scenario." #, fuzzy msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" "%{hero} is verslagen en zal niet verschijnen in de volgende scenario's." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "De dwergen herkennen hun bondgenoten en sluiten zich graag bij je aan." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "De ogres herkennen je als de Drawven Moordenaar en sjokken naar je toe." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "De draken komen grommend en grommend overeen om hun krachten te bundelen met " "jou, hun 'bondgenoot'." #, fuzzy msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Als je de groep elfen nadert, roept hun leider ze allemaal onder de " "aandacht. Hij roept naar hen: 'Wie van jullie is dapper genoeg om zich bij " "deze onverschrokken bondgenoot van ons aan te sluiten?' De groep explodeert " "met gejuich terwijl ze rennen om zich bij je gelederen te voegen." #, fuzzy msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "De dwergen begroeten je, \"Elke vriend van Roland is een vriend van ons. Je " "mag passeren.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "De ogres geven je een grom van herkenning, \"Archibald's bondgenoten kunnen " "passeren.\"" #, fuzzy msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "De draken zien je en roepen. \"Onze alliantie met Archibald dwingt ons om " "met je mee te doen. Helaas heb je geen ruimte. Jammer!\" Ze verspreiden zich " "snel." #, fuzzy msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "De elfen staan in de houding als je dichterbij komt. Hun leider roept je en " "zegt: \"Laten we je voortgang niet belemmeren, bondgenoot! Ga verder, en " "moge de overwinning van jou zijn.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"De Drawven Moordenaar!!!!, ren voor je leven.\"" msgid "campaignBonus|Animate Dead" msgstr "Dood Animeren" msgid "campaignBonus|Chain Lightning" msgstr "Ketting Bliksem" msgid "campaignBonus|Fireblast" msgstr "Vuurstraal" msgid "campaignBonus|Mass Curse" msgstr "Massa Vloek" msgid "campaignBonus|Mass Haste" msgstr "Massale Haast" msgid "campaignBonus|Mirror Image" msgstr "Spiegelbeeld" msgid "campaignBonus|Resurrect" msgstr "Herrijzen" msgid "campaignBonus|Steelskin" msgstr "Staalhuid" msgid "campaignBonus|Summon Earth" msgstr "Aarde Oproepen" msgid "campaignBonus|View Heroes" msgstr "Bekijk Helden" msgid "campaignBonus|Ballista" msgstr "Ballista" msgid "campaignBonus|Black Pearl" msgstr "Zwarte Parel" msgid "campaignBonus|Caster's Bracelet" msgstr "Magiers's Armband" msgid "campaignBonus|Defender Helm" msgstr "Verdediger Helm" msgid "campaignBonus|Breastplate" msgstr "Borstplaat" msgid "campaignBonus|Dragon Sword" msgstr "Drakenzwaard" msgid "campaignBonus|Fizbin Medal" msgstr "Fizbin Medaille" msgid "campaignBonus|Foremost Scroll" msgstr "Voorste Scroll" #, fuzzy msgid "campaignBonus|Gauntlets" msgstr "Ballista" msgid "campaignBonus|Hideous Mask" msgstr "Afschuwelijk Masker" msgid "campaignBonus|Mage's Ring" msgstr "Magiër's Ring" msgid "campaignBonus|Major Scroll" msgstr "Grote Rol" msgid "campaignBonus|Medal of Honor" msgstr "Medaille van Eer" msgid "campaignBonus|Medal of Valor" msgstr "Medaille van Moed" msgid "campaignBonus|Minor Scroll" msgstr "Kleine Rol" msgid "campaignBonus|Nomad Boots" msgstr "Nomadenlaarzen" msgid "campaignBonus|Power Axe" msgstr "Machtsbijl" msgid "campaignBonus|Spiked Shield" msgstr "Puntig Schild" msgid "campaignBonus|Stealth Shield" msgstr "Stealth-schild" msgid "campaignBonus|Tax Lien" msgstr "Belastingrecht" msgid "campaignBonus|Thunder Mace" msgstr "Donderstaf" msgid "campaignBonus|Traveler's Boots" msgstr "Reizigerslaarzen" msgid "campaignBonus|White Pearl" msgstr "Witte Parel" msgid "campaignBonus|Basic Archery" msgstr "Basis Boogschieten" msgid "campaignBonus|Advanced Archery" msgstr "Geavanceerd Boogschieten" msgid "campaignBonus|Expert Archery" msgstr "Expert Boogschieten" msgid "campaignBonus|Basic Ballistics" msgstr "Basis Ballistiek" msgid "campaignBonus|Advanced Ballistics" msgstr "Geavanceerd Ballistiek" msgid "campaignBonus|Expert Ballistics" msgstr "Expert Ballistiek" msgid "campaignBonus|Basic Diplomacy" msgstr "Basis Diplomatie" msgid "campaignBonus|Advanced Diplomacy" msgstr "Geavanceerd Diplomatie" msgid "campaignBonus|Expert Diplomacy" msgstr "Expert Diplomatie" msgid "campaignBonus|Basic Eagle Eye" msgstr "Basis Adelaarsoog" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Geavanceerd Adelaarsoog" msgid "campaignBonus|Expert Eagle Eye" msgstr "Expert Adelaarsoog" msgid "campaignBonus|Basic Estates" msgstr "Basis Landgoederen" msgid "campaignBonus|Advanced Estates" msgstr "Geavanceerd Landgoederen" msgid "campaignBonus|Expert Estates" msgstr "Expert Landgoederen" msgid "campaignBonus|Basic Leadership" msgstr "Basis Leiderschap" msgid "campaignBonus|Advanced Leadership" msgstr "Geavanceerd Leiderschap" msgid "campaignBonus|Expert Leadership" msgstr "Expert Leiderschap" msgid "campaignBonus|Basic Logistics" msgstr "Basis Logistiek" msgid "campaignBonus|Advanced Logistics" msgstr "Geavanceerd Logistiek" msgid "campaignBonus|Expert Logistics" msgstr "Expert Logistiek" msgid "campaignBonus|Basic Luck" msgstr "Basis Geluk" msgid "campaignBonus|Advanced Luck" msgstr "Geavanceerd Geluk" msgid "campaignBonus|Expert Luck" msgstr "Expert Geluk" msgid "campaignBonus|Basic Mysticism" msgstr "Basis Mystiek" msgid "campaignBonus|Advanced Mysticism" msgstr "Geavanceerd Mystiek" msgid "campaignBonus|Expert Mysticism" msgstr "Expert Mystiek" msgid "campaignBonus|Basic Navigation" msgstr "Basis Navigatie" msgid "campaignBonus|Advanced Navigation" msgstr "Geavanceerd Navigatie" msgid "campaignBonus|Expert Navigation" msgstr "Expert Navigatie" msgid "campaignBonus|Basic Necromancy" msgstr "Basis Necromantie" msgid "campaignBonus|Advanced Necromancy" msgstr "Geavanceerd Necromantie" msgid "campaignBonus|Expert Necromancy" msgstr "Expert Necromantie" msgid "campaignBonus|Basic Pathfinding" msgstr "Basis Padvinden" msgid "campaignBonus|Advanced Pathfinding" msgstr "Geavanceerd Padvinden" msgid "campaignBonus|Expert Pathfinding" msgstr "Expert Padvinden" msgid "campaignBonus|Basic Scouting" msgstr "Basis Scouting" msgid "campaignBonus|Advanced Scouting" msgstr "Geavanceerd Scouting" msgid "campaignBonus|Expert Scouting" msgstr "Expert Scouting" msgid "campaignBonus|Basic Wisdom" msgstr "Basis Wijsdom" msgid "campaignBonus|Advanced Wisdom" msgstr "Geavanceerd Wijsdom" msgid "campaignBonus|Expert Wisdom" msgstr "Expert Wijsdom" #, fuzzy msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" "De hoofdheld zal het \"%{artifact}\" artefact hebben aan het begin van het " "scenario." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Het koninkrijk zal aan het begin van het scenario %{amount} extra " "%{resource} ontvangen." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Het koninkrijk zal %{amount} minder %{resource} hebben aan het begin van het " "scenario." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "De hoofdheld heeft %{count} %{monster} aan het begin van het scenario." #, fuzzy msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" "De hoofdheld heeft de spreuk \"%{spell}\" aan het begin van het scenario." #, fuzzy msgid "The starting alignment of the scenario will be %{race}." msgstr "De startrace van het scenario is %{race}." #, fuzzy msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "De hoofdheld heeft extra %{count} %{skill} aan het begin van het scenario." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "De hoofdheld heeft %{skill} aan het begin van het scenario." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" #, fuzzy msgid "Price of Loyalty" msgstr "De Prijs van Loyaliteit" msgid "Voyage Home" msgstr "Rijs Naar Huis" msgid "Wizard's Isle" msgstr "Tovenaarseiland" msgid "Descendants" msgstr "Afstammelingen" msgid "Cannot build. You have already built here today." msgstr "Kan niet bouwen. Je hebt hier vandaag al gebouwd." msgid "For this action it is necessary to build a castle first." msgstr "Voor deze actie moet je eerst een kasteel bouwen." msgid "The %{building} produces %{monster}." msgstr "Het %{building} produceert %{monster}." msgid "Requires:" msgstr "Vereist:" msgid "Exit this menu without doing anything." msgstr "" #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Kan %{name} niet bouwen omdat het kasteel te ver van water is." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Kan %{name} niet betalen." #, fuzzy msgid "The %{name} is already built." msgstr "%{name} is al gebouwd." #, fuzzy msgid "Cannot build the %{name}." msgstr "Kan %{name} niet bouwen." msgid "Build %{name}." msgstr "Bouw %{name}." msgid "Blackridge" msgstr "" msgid "Hillstone" msgstr "" msgid "Pinehurst" msgstr "" msgid "Whiteshield" msgstr "" msgid "Woodhaven" msgstr "" msgid "Blackwind" msgstr "" msgid "Bloodreign" msgstr "" msgid "Dragontooth" msgstr "Drakentand" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" msgid "Tundara" msgstr "" msgid "Vulcania" msgstr "" msgid "Baywatch" msgstr "" msgid "Fountainhead" msgstr "" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" msgid "Sandcaster" msgstr "" msgid "Alamar" msgstr "" msgid "Burlock" msgstr "" msgid "Dragadune" msgstr "" msgid "Kalindra" msgstr "" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" msgid "Blackfang" msgstr "" msgid "New Dawn" msgstr "" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" msgid "Antioch" msgstr "" msgid "Avalon" msgstr "" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" msgid "Weed Patch" msgstr "" msgid "Brownston" msgstr "" msgid "Hilltop" msgstr "" msgid "Weddington" msgstr "" msgid "Westfork" msgstr "" msgid "Whittingham" msgstr "" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "" msgid "Roscomon" msgstr "" msgid "Sherman" msgstr "" msgid "Yorksford" msgstr "" msgid "Blackburn" msgstr "" msgid "Blacksford" msgstr "" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "" msgid "Lankershire" msgstr "" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "" msgid "Troy" msgstr "" msgid "Forder Oaks" msgstr "" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "" msgid "Willow" msgstr "" msgid "Corackston" msgstr "" msgid "Sheltemburg" msgstr "" msgid "Cannot recruit - you already have a Hero in this town." msgstr "" msgid "Cannot recruit - you have too many Heroes." msgstr "" #, fuzzy msgid "Cannot afford a Hero." msgstr "Kan %{name} niet betalen." msgid "There is no room in the garrison for this army." msgstr "" msgid "Fortifications" msgstr "" msgid "Farm" msgstr "" msgid "Thatched Hut" msgstr "" msgid "Archery Range" msgstr "" msgid "Upg. Archery Range" msgstr "" msgid "Blacksmith" msgstr "" msgid "Upg. Blacksmith" msgstr "" msgid "Armory" msgstr "" msgid "Upg. Armory" msgstr "" msgid "Jousting Arena" msgstr "" msgid "Upg. Jousting Arena" msgstr "" msgid "Cathedral" msgstr "" msgid "Upg. Cathedral" msgstr "" msgid "Coliseum" msgstr "" msgid "Garbage Heap" msgstr "" msgid "Hut" msgstr "" msgid "Stick Hut" msgstr "" msgid "Upg. Stick Hut" msgstr "" msgid "Den" msgstr "" msgid "Adobe" msgstr "" msgid "Upg. Adobe" msgstr "" msgid "Bridge" msgstr "" msgid "Upg. Bridge" msgstr "" msgid "Pyramid" msgstr "" msgid "Rainbow" msgstr "" msgid "Crystal Garden" msgstr "" msgid "Treehouse" msgstr "" msgid "Cottage" msgstr "" msgid "Upg. Cottage" msgstr "" msgid "Stonehenge" msgstr "" msgid "Upg. Stonehenge" msgstr "" msgid "Fenced Meadow" msgstr "" msgid "sorceress|Red Tower" msgstr "" msgid "Dungeon" msgstr "" msgid "Waterfall" msgstr "" msgid "Cave" msgstr "" msgid "Crypt" msgstr "" msgid "Nest" msgstr "" msgid "Maze" msgstr "" msgid "Upg. Maze" msgstr "" msgid "Swamp" msgstr "" msgid "Green Tower" msgstr "" msgid "warlock|Red Tower" msgstr "" msgid "Black Tower" msgstr "" msgid "Library" msgstr "" msgid "Orchard" msgstr "" msgid "Habitat" msgstr "" msgid "Pen" msgstr "" msgid "Foundry" msgstr "" msgid "Upg. Foundry" msgstr "" msgid "Cliff Nest" msgstr "" msgid "Ivory Tower" msgstr "" msgid "Upg. Ivory Tower" msgstr "" msgid "Cloud Castle" msgstr "" msgid "Upg. Cloud Castle" msgstr "" msgid "Storm" msgstr "" msgid "Skull Pile" msgstr "" msgid "Excavation" msgstr "" msgid "Graveyard" msgstr "" msgid "Upg. Graveyard" msgstr "" msgid "Upg. Pyramid" msgstr "" msgid "Mansion" msgstr "" msgid "Upg. Mansion" msgstr "" msgid "Mausoleum" msgstr "" msgid "Upg. Mausoleum" msgstr "" msgid "Laboratory" msgstr "" msgid "Shrine" msgstr "" msgid "Special" msgstr "" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Dwelling 2" msgstr "Selecteer spreuk doelwit" msgid "Upg. Dwelling 2" msgstr "" #, fuzzy msgid "Dwelling 3" msgstr "Selecteer spreuk doelwit" msgid "Upg. Dwelling 3" msgstr "" #, fuzzy msgid "Dwelling 4" msgstr "Selecteer spreuk doelwit" msgid "Upg. Dwelling 4" msgstr "" #, fuzzy msgid "Dwelling 5" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Dwelling 6" msgstr "Selecteer spreuk doelwit" msgid "Upg. Dwelling 6" msgstr "" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" msgid "The Rainbow increases the luck of the defending units by two." msgstr "" msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "" msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" msgid "Thieves' Guild" msgstr "" msgid "Tavern" msgstr "" msgid "Shipyard" msgstr "" msgid "Well" msgstr "" msgid "Statue" msgstr "" msgid "Marketplace" msgstr "" msgid "Moat" msgstr "" msgid "Castle" msgstr "" msgid "Tent" msgstr "" msgid "Captain's Quarters" msgstr "" msgid "Mage Guild, Level 1" msgstr "" msgid "Mage Guild, Level 2" msgstr "" msgid "Mage Guild, Level 3" msgstr "" msgid "Mage Guild, Level 4" msgstr "" msgid "Mage Guild, Level 5" msgstr "" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" msgid "The Tavern increases morale for troops defending the castle." msgstr "" msgid "The Shipyard allows ships to be built." msgstr "" msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" msgid "The Statue increases the town's income by %{count} gold per day." msgstr "" msgid "The Left Turret provides extra firepower during castle combat." msgstr "" msgid "The Right Turret provides extra firepower during castle combat." msgstr "" msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" msgid "Recruit %{name}" msgstr "" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" msgid "Click to show next town." msgstr "" msgid "Show next town" msgstr "" msgid "Click to show previous town." msgstr "" msgid "Show previous town" msgstr "" msgid "This town may not be upgraded to a castle." msgstr "" msgid "Town" msgstr "" msgid "Exit Castle" msgstr "" msgid "Exit Town" msgstr "" msgid "Show Income" msgstr "" msgid "View Hero" msgstr "" msgid "The above spells are available here." msgstr "" msgid "The spells the hero can learn have been added to their book." msgstr "" msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" msgid "Recruit Hero" msgstr "" msgid "%{name} is a level %{value} %{race} " msgstr "" msgid "with %{count} artifacts." msgstr "" msgid "with 1 artifact." msgstr "" msgid "without artifacts." msgstr "" msgid "Recruit %{name} the %{race}" msgstr "" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" msgid "Spread Formation" msgstr "" msgid "Grouped Formation" msgstr "" msgid "Click to show the next town." msgstr "" msgid "Click to show the previous town." msgstr "" msgid "Set garrison combat formation to 'Spread'" msgstr "" msgid "Set garrison combat formation to 'Grouped'" msgstr "" msgid "Exit Castle Options" msgstr "" msgid "Castle Options" msgstr "" msgid "Not enough resources to recruit creatures." msgstr "" msgid "You are unable to recruit at this time, your ranks are full." msgstr "" msgid "No creatures available for purchase." msgstr "" msgid "Recruit Creatures" msgstr "" msgid "Hire all creatures in the town." msgstr "" msgid "Max" msgstr "" msgid "Available" msgstr "" msgid "Town Population Information and Statistics" msgstr "" msgid "Damage" msgstr "" msgid "HP" msgstr "" msgid "Growth" msgstr "" msgid "week" msgstr "" msgid "View World" msgstr "" msgid "View the entire world." msgstr "" msgid "Puzzle" msgstr "" msgid "View the obelisk puzzle." msgstr "" msgid "Scenario Information" msgstr "" msgid "View information on the scenario you are currently playing." msgstr "" msgid "Dig for the Ultimate Artifact." msgstr "" msgid "Digging" msgstr "" msgid "Arena" msgstr "" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" msgid "Attack Skill" msgstr "" msgid "Defense Skill" msgstr "" msgid "Shots" msgstr "" msgid "Shots Left" msgstr "" msgid "Hit Points" msgstr "" msgid "Hit Points Left" msgstr "" msgid "You can't afford to upgrade your troops!" msgstr "" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" msgid "Are you sure you want to dismiss this army?" msgstr "" msgid "Upgrade" msgstr "" msgid "Upgrade your troops." msgstr "" msgid "Dismiss" msgstr "" msgid "Dismiss this army." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" msgid "Followers" msgstr "" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" msgid "(Rate: %{percent})" msgstr "" msgid "off" msgstr "" msgid "Music" msgstr "" msgid "Effects" msgstr "" msgid "MIDI" msgstr "" msgid "MIDI Expansion" msgstr "" msgid "External" msgstr "" msgid "Music Type" msgstr "" msgid "3D Audio" msgstr "" msgid "Toggle ambient music level." msgstr "" msgid "Toggle foreground sounds level." msgstr "" msgid "Change the type of music." msgstr "" msgid "Toggle the 3D effect of foreground sounds." msgstr "" msgid "Build a new ship:" msgstr "" msgid "Resource cost:" msgstr "" msgid "Total: " msgstr "" msgid "Need: " msgstr "" msgid "New Game" msgstr "" msgid "Start a single or multi-player game." msgstr "" msgid "Load Game" msgstr "" msgid "Load a previously saved game." msgstr "" msgid "Save Game" msgstr "" msgid "Save the current game." msgstr "" msgid "Quit" msgstr "" msgid "Quit out of Heroes of Might and Magic II." msgstr "" msgid "Language" msgstr "" msgid "Graphics" msgstr "" msgid "Black & White" msgstr "" msgid "Mouse Cursor" msgstr "" msgid "Color" msgstr "" msgid "Text Support" msgstr "" msgid "Change the language of the game." msgstr "" msgid "Select Game Language" msgstr "" msgid "Change the graphics settings of the game." msgstr "" msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" msgid "" "Map\n" "Difficulty" msgstr "" msgid "" "Game\n" "Difficulty" msgstr "" msgid "Rating" msgstr "" msgid "Map Size" msgstr "" msgid "Opponents" msgstr "" msgid "Class" msgstr "" msgid "" "Victory\n" "Conditions" msgstr "" msgid "" "Loss\n" "Conditions" msgstr "" msgid "First select recipients!" msgstr "" msgid "You cannot select %{resource}!" msgstr "" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Schiet %{monster}" msgid "Select Recipients" msgstr "" msgid "Your Funds" msgstr "" msgid "Planned Gift" msgstr "" msgid "Gift from %{name}" msgstr "" msgid "Resolution" msgstr "" msgid "Fullscreen" msgstr "" msgid "window|Mode" msgstr "" msgid "Windowed" msgstr "" msgid "V-Sync" msgstr "" msgid "FPS" msgstr "" #, fuzzy msgid "System Info" msgstr "Systeem Instellingen" msgid "Change the resolution of the game." msgstr "" msgid "Select Game Resolution" msgstr "" msgid "Toggle between fullscreen and windowed modes." msgstr "" msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" msgid "Show extra information such as FPS and current time." msgstr "" msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" msgid "Event: " msgstr "" msgid "Hot Keys:" msgstr "" #, fuzzy msgid "Hide" msgstr "Horde" msgid "Show" msgstr "" msgid "Interface" msgstr "" msgid "Interface Type" msgstr "" msgid "Toggle the type of interface you want to use." msgstr "" msgid "Toggle interface visibility." msgstr "" msgid "Scroll Speed" msgstr "" msgid "Sets the speed at which you scroll the window." msgstr "" msgid "Select Game Language:" msgstr "" #, fuzzy msgid "Select Language:" msgstr "Selecteer spreuk doelwit" msgid "Click to choose the selected language." msgstr "" msgid "%{name} has gained a level." msgstr "" msgid "%{skill} +1" msgstr "" msgid "You have learned %{skill}." msgstr "" msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "" msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" msgid "Min" msgstr "" msgid "Qty to trade" msgstr "" msgid "Trading Post" msgstr "" msgid "Your Resources" msgstr "" msgid "Available Trades" msgstr "" msgid "guarded by %{count} %{monster}" msgstr "" msgid "guarded by " msgstr "" msgid "(available: %{count})" msgstr "" msgid "(empty)" msgstr "" msgid "already learned" msgstr "" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Kennis" msgid "already claimed" msgstr "" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "" msgid "already has max skills" msgstr "" msgid "(already visited)" msgstr "" msgid "(not visited)" msgstr "" msgid "%{color} Barrier" msgstr "" msgid "(tent visited)" msgstr "" msgid "%{color} Tent" msgstr "" msgid "Road" msgstr "" msgid "(digging ok)" msgstr "" msgid "(no digging)" msgstr "" msgid "penalty: %{cost}" msgstr "" msgid "Defenders:" msgstr "" msgid "Unknown" msgstr "" msgid "heroQuickInfo|(Level %{level})" msgstr "" msgid "Attack:" msgstr "" msgid "Defense:" msgstr "" msgid "Spell Power:" msgstr "" msgid "Knowledge:" msgstr "" msgid "Spell Points:" msgstr "" msgid "Move Points:" msgstr "" msgid "Uncharted Territory" msgstr "" msgid "Cost per troop:" msgstr "" msgid "Available: %{count}" msgstr "" msgid "Number to buy:" msgstr "" msgid "Recruit selected monsters." msgstr "" msgid "Select maximum monsters to be recruited." msgstr "" msgid "Select only 1 monster to be recruited." msgstr "" msgid "Select this game resolution." msgstr "" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "" msgid "Click to apply the selected resolution." msgstr "" msgid "Click to apply the entered text." msgstr "" msgid "Click to open the Virtual Keyboard dialog." msgstr "" msgid "Open Virtual Keyboard" msgstr "" msgid "How many creatures do you wish to move?" msgstr "" msgid "Select how many units to separate into:" msgstr "" msgid "Map: " msgstr "" msgid "" "\n" "\n" "Month: " msgstr "" msgid ", Week: " msgstr "" msgid ", Day: " msgstr "" msgid "" "\n" "\n" "Location: " msgstr "" msgid "Are you sure you want to delete file:" msgstr "" msgid "Warning" msgstr "Waarschuuwing" msgid "Click to save the current game." msgstr "" msgid "Click to load a previously saved game." msgstr "" msgid "File to Save:" msgstr "" msgid "File to Load:" msgstr "" msgid "Terrain object" msgstr "" msgid "Accept the choice made." msgstr "" msgid "Select Skill:" msgstr "" msgid "Select Spell:" msgstr "" msgid "Select Artifact:" msgstr "" msgid "Select Monster:" msgstr "" msgid "Select Hero:" msgstr "" msgid "race|Random" msgstr "" msgid "Click to start placing the selected hero." msgstr "" #, fuzzy msgid "%{color} %{race}" msgstr "%{name} de %{race}" msgid "You will place" msgstr "" msgid "Click to select this class." msgstr "" msgid "Click to select this color." msgstr "" #, fuzzy msgid "Select Treasure:" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Select Ocean Object:" msgstr "Selecteer spreuk doelwit" msgid "Castle/town placing" msgstr "" msgid "doubleLinedRace|Neutral" msgstr "" msgid "Click to start placing the selected castle/town." msgstr "" msgid "Click to select town placing." msgstr "" msgid "Click to select castle placing." msgstr "" msgid "%{color} %{race} %{townOrCastle}" msgstr "" msgid "race|Neutral" msgstr "" #, fuzzy msgid "Select Dwelling:" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Select Landscape Object:" msgstr "Selecteer spreuk doelwit" msgid "Mine placing" msgstr "" msgid "" "Resource\n" "type:" msgstr "" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name} de %{race}" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" #, fuzzy msgid "Select Mountain Object:" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Select Rock Object:" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Select Tree Object:" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Select Power Up Object:" msgstr "Selecteer spreuk doelwit" #, fuzzy msgid "Select Adventure Object:" msgstr "Selecteer spreuk doelwit" msgid "Players Icon" msgstr "" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" msgid "Size Icon" msgstr "" msgid "Map Type" msgstr "" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" msgid "Map Type:\n" msgstr "" msgid "The Succession Wars" msgstr "" msgid "The Price of Loyalty" msgstr "De Prijs van Loyaliteit" msgid "Resurrection" msgstr "" msgid "" "\n" "\n" "Language:\n" msgstr "" msgid "Lose all your heroes and towns." msgstr "" msgid "Lose a specific town." msgstr "" msgid "Lose a specific hero." msgstr "" msgid "Run out of time. Fail to win by a certain point." msgstr "" msgid "Loss Condition" msgstr "" msgid "Defeat all enemy heroes and towns." msgstr "" msgid "Capture a specific town." msgstr "" msgid "Defeat a specific hero." msgstr "" msgid "Find a specific artifact." msgstr "" msgid "Your side must defeat the opposing side." msgstr "" msgid "Accumulate a large amount of gold." msgstr "" msgid "Victory Condition" msgstr "" msgid "Map difficulty:" msgstr "" msgid "N" msgstr "" msgid "No maps exist at that size." msgstr "" msgid "Small Maps" msgstr "" msgid "View only maps of size small (36 x 36)." msgstr "" msgid "Medium Maps" msgstr "" msgid "View only maps of size medium (72 x 72)." msgstr "" msgid "Large Maps" msgstr "" msgid "View only maps of size large (108 x 108)." msgstr "" msgid "Extra Large Maps" msgstr "" msgid "View only maps of size extra large (144 x 144)." msgstr "" msgid "All Maps" msgstr "" msgid "View all maps, regardless of size." msgstr "" msgid "Selected Name" msgstr "" msgid "The name of the currently selected map." msgstr "" msgid "Selected Map Difficulty" msgstr "" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" msgid "Selected Description" msgstr "" msgid "The description of the currently selected map." msgstr "" msgid "Jump" msgstr "" msgid "Hero Speed" msgstr "" msgid "Don't Show" msgstr "" msgid "Enemy Speed" msgstr "" msgid "Auto Resolve" msgstr "" msgid "Auto, No Spells" msgstr "" msgid "Battles" msgstr "" msgid "combatMode|Manual" msgstr "" msgid "Change the speed at which your heroes move on the main screen." msgstr "" msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" msgid "Change the interface settings of the game." msgstr "" msgid "Interface Settings" msgstr "" msgid "Toggle instant battle mode." msgstr "" msgid "Att." msgstr "" msgid "Def." msgstr "" msgid "Power" msgstr "" msgid "Knowl" msgstr "" msgid "1st" msgstr "" msgid "2nd" msgstr "" msgid "3rd" msgstr "" msgid "4th" msgstr "" msgid "5th" msgstr "" msgid "6th" msgstr "" msgid "Oracle: Player Rankings" msgstr "" msgid "Thieves' Guild: Player Rankings" msgstr "" msgid "Number of Towns:" msgstr "" msgid "Number of Castles:" msgstr "" msgid "Number of Heroes:" msgstr "" msgid "Gold in Treasury:" msgstr "" msgid "Wood & Ore:" msgstr "" msgid "Gems, Cr, Slf & Mer:" msgstr "" msgid "Obelisks Found:" msgstr "" msgid "Artifacts:" msgstr "" msgid "Total Army Strength:" msgstr "" msgid "Income:" msgstr "" msgid "Best Hero:" msgstr "" msgid "Best Hero Stats:" msgstr "" msgid "Personality:" msgstr "" msgid "Best Monster:" msgstr "" msgid "Random Castle Name" msgstr "" msgid "Random Town Name" msgstr "" msgid "Allow Castle build" msgstr "" msgid "Default Buildings" msgstr "" msgid "Default Army" msgstr "" msgid "Castle Army" msgstr "" #, fuzzy msgid "Town Army" msgstr "Held Scherm" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" msgid "Enter Castle name" msgstr "" msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Brichtenbalk" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Brichtenbalk" #, fuzzy msgid "Click to save the Event properties." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "No resources will be given as a reward." msgstr "" msgid "Resources" msgstr "" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Add Event" msgstr "" msgid "Add an additional event." msgstr "" msgid "Edit Event" msgstr "" msgid "Edit an existing event." msgstr "" msgid "Delete Event" msgstr "" msgid "Delete an existing event." msgstr "" msgid "Effects:" msgstr "" #, fuzzy msgid "Conditions:" msgstr "Annexatie" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" msgid "Set Experience value" msgstr "" msgid "Artifact" msgstr "" msgid "No artifact will be given by the event." msgstr "" msgid "Delete Artifact" msgstr "" msgid "Delete an artifact from the event." msgstr "" msgid "No Secondary Skill will be given by the event." msgstr "" msgid "Secondary Skill" msgstr "" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" msgid "%{objects} cannot be placed on water." msgstr "" msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" msgid "%{objects} must be placed on water." msgstr "" msgid "Objects cannot be placed outside the map." msgstr "" msgid "Action objects must be placed on clear tiles." msgstr "" msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" msgid "Editor" msgstr "" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "" "MAIN\n" "MENU" msgstr "" msgid "" "START\n" "MAP" msgstr "" msgid "Main Menu" msgstr "" msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" msgid "Start Map" msgstr "" msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" msgid "Create a new map from scratch." msgstr "" msgid "New Map" msgstr "" msgid "Load Map" msgstr "" msgid "Load an existing map." msgstr "" msgid "Save Map" msgstr "" msgid "Save the current map." msgstr "" msgid "Quit out of the map editor." msgstr "" #, fuzzy msgid "Return to the game's Main Menu." msgstr "Keer terug naar de strijd." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" msgid "Set Random Ultimate Artifact Radius" msgstr "" msgid "%{object} has no properties to change." msgstr "" msgid "This artifact" msgstr "" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "" msgid "Streams" msgstr "" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "" msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Het spiegelbeeld wordt gecreëerd." msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "" msgid "Unable to locate a directory to save the map." msgstr "" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Weet je zeker dat je het automatisch vechten wilt onderbreken?" msgid "Map saved to: " msgstr "" msgid "Failed to save the map." msgstr "" msgid "Used to place %{object}." msgstr "" #, fuzzy msgid "Select object type" msgstr "Selecteer spreuk doelwit" msgid "" "Click here to\n" "select a monster." msgstr "" #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Selecteer een andere held." msgid "" "Cell\n" "Details" msgstr "" msgid "Erase" msgstr "" msgid "Mountains" msgstr "" msgid "Rocks" msgstr "" msgid "Trees" msgstr "" msgid "Water Objects" msgstr "" msgid "Miscellaneous" msgstr "" msgid "Artifacts" msgstr "" msgid "Dwellings" msgstr "" msgid "Mines" msgstr "" #, fuzzy msgid "Power-ups" msgstr "Einde van de macht" msgid "Treasures" msgstr "" msgid "Heroes" msgstr "" msgid "Towns" msgstr "" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Selecteer spreuk doelwit" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" msgid "Small Brush" msgstr "" msgid "Medium Brush" msgstr "" msgid "Large Brush" msgstr "" msgid "Area Fill" msgstr "" msgid "Used to click and drag for filling in large areas." msgstr "" msgid "Clear Area" msgstr "" msgid "Used to click and drag for clearing large areas." msgstr "" msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" msgid "Traversable only by boat." msgstr "" msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" msgid "Used for special editing of action objects." msgstr "" msgid "Adventure Objects Mode" msgstr "" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" msgid "Kingdom Objects Mode" msgstr "" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "Monsters" msgid "Used to place monsters on the map." msgstr "" msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" msgid "Road Mode" msgstr "" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" msgid "Specifications" msgstr "" msgid "File Options" msgstr "" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" msgid "View the editor system options, which let you customize the editor." msgstr "" msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" msgid "Cancel back to the New Map menu." msgstr "" msgid "Cancel back to the main menu." msgstr "" msgid "From Scratch" msgstr "" msgid "Start from scratch with a blank map." msgstr "" msgid "Create a randomly generated map." msgstr "" msgid "Random" msgstr "" msgid "Cancel back to the Map Editor main menu." msgstr "" msgid "No maps available!" msgstr "" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{name} de %{race}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race1} %{name1}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{name} de %{race}" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{name} de %{race}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race1} %{name1}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{race1} %{name1}" #, fuzzy msgid "None." msgstr "Geen" #, fuzzy msgid "One side defeats another." msgstr "Selecteer een andere held." msgid "Accumulate gold." msgstr "" msgid "Run out of time." msgstr "" #, fuzzy msgid "alliance|1st" msgstr " alliantie" #, fuzzy msgid "alliance|2nd" msgstr " alliantie" #, fuzzy msgid "alliance|3rd" msgstr " alliantie" #, fuzzy msgid "alliance|4th" msgstr " alliantie" #, fuzzy msgid "alliance|5th" msgstr " alliantie" msgid "Special Loss Condition" msgstr "" msgid "Special Victory Condition" msgstr "" msgid "Allow standard victory conditions" msgstr "" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " alliantie" #, fuzzy msgid "{%number} alliance: " msgstr " alliantie" msgid "Gold:" msgstr "" msgid "Select a Town to capture to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Map Difficulty" msgstr "" msgid "Map Description" msgstr "" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" msgid "Change Map Description" msgstr "" #, fuzzy msgid "Click to accept the changes made." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" #, fuzzy msgid "Click to edit custom rumors." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Events" msgstr "" #, fuzzy msgid "Click to change the language of the map." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Click to change your map name." msgstr "" msgid "Map Name" msgstr "" #, fuzzy msgid "Click to change the description of the current map." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Indicates the player types in the scenario. Click to change." msgstr "" msgid "Player Type" msgstr "" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" msgid "editor|%{count} %{resource}" msgstr "" #, fuzzy msgid "Animation" msgstr "Annexatie" msgid "Passability" msgstr "" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Add Rumor" msgstr "" msgid "Add an additional rumor." msgstr "" msgid "Edit Rumor" msgstr "" msgid "Edit an existing rumor." msgstr "" msgid "Delete Rumor" msgstr "" msgid "Delete an existing rumor." msgstr "" msgid "" "\n" "\n" "Size: " msgstr "" msgid "" "\n" "\n" "Description: " msgstr "" msgid "Save Map:" msgstr "" #, fuzzy msgid "Click to save the current map." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "" msgid "difficulty|Normal" msgstr "" msgid "difficulty|Hard" msgstr "" msgid "difficulty|Expert" msgstr "" msgid "difficulty|Impossible" msgstr "" msgid "and more..." msgstr "" msgid "Easy" msgstr "" msgid "Normal" msgstr "" msgid "Hard" msgstr "" msgid "Campaign Difficulty" msgstr "" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" msgid "Start the selected scenario." msgstr "" msgid "View Intro" msgstr "" msgid "View the intro video for the current state of the campaign." msgstr "" msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" msgid "Restart the current scenario." msgstr "" msgid "Difficulty" msgstr "" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" msgid "Are you sure you want to restart this scenario?" msgstr "" msgid "Campaign Scenario loading failure" msgstr "" msgid "Please make sure that campaign files are correct and present." msgstr "" msgid "Days spent" msgstr "" msgid "The number of days spent on this campaign." msgstr "" msgid "Project Coordination and Core Development" msgstr "" msgid "Development" msgstr "" msgid "Visit us at " msgstr "" msgid "QA and Support" msgstr "" msgid "Dev and Support" msgstr "" msgid "Special Thanks to" msgstr "" msgid "and many-many other contributors and supporters!" msgstr "" msgid "Support us at" msgstr "" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "" msgid "Original project before 0.7" msgstr "" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "" msgid "Designed and Directed" msgstr "" msgid "Programming and Design" msgstr "" msgid "Executive Producer" msgstr "" msgid "Producer" msgstr "" msgid "Additional Design" msgstr "" msgid "Additional Programming" msgstr "" msgid "Musical Production" msgstr "" msgid "Music and Sound Design" msgstr "" msgid "Vocalists" msgstr "" msgid "Art Director" msgstr "" msgid "Assistant Art Director" msgstr "" msgid "Artists" msgstr "" msgid "QA Manager" msgstr "" msgid "QA" msgstr "" msgid "Writing" msgstr "" msgid "Manual and Helpfile" msgstr "" msgid "Scenarios" msgstr "" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "" msgid "Design Lead" msgstr "" msgid "Designers" msgstr "" msgid "Programming Lead" msgstr "" msgid "Art Lead" msgstr "" msgid "Playtesters" msgstr "" msgid "Designer" msgstr "" msgid "Producers" msgstr "" msgid "QA Managers" msgstr "" msgid "Sound Design" msgstr "" msgid "Town Themes" msgstr "" msgid "Alto Sax" msgstr "" msgid "Harpsichord and Piano" msgstr "" msgid "Basso Vocal" msgstr "" msgid "Soprano Vocal" msgstr "" msgid "Recorded at %{recordingStudio}" msgstr "" msgid "credits|Manual" msgstr "" msgid "German Consultant" msgstr "" msgid "Map Designers" msgstr "" msgid "Package Design" msgstr "" msgid "High Scores" msgstr "" msgid "Your Name" msgstr "" msgid "Unknown Hero" msgstr "" msgid "Standard" msgstr "" msgid "View High Scores for Standard Maps." msgstr "" msgid "Campaign" msgstr "" msgid "View High Scores for Campaigns." msgstr "" msgid "hotkey|default okay event" msgstr "" msgid "hotkey|default cancel event" msgstr "" msgid "hotkey|default left" msgstr "" msgid "hotkey|default right" msgstr "" msgid "hotkey|default up" msgstr "" msgid "hotkey|default down" msgstr "" msgid "hotkey|toggle fullscreen" msgstr "" msgid "hotkey|toggle text support mode" msgstr "" msgid "hotkey|toggle developer mode" msgstr "" msgid "hotkey|new game" msgstr "" msgid "hotkey|load game" msgstr "" msgid "hotkey|high scores" msgstr "" msgid "hotkey|credits" msgstr "" msgid "hotkey|standard game" msgstr "" msgid "hotkey|campaign game" msgstr "" msgid "hotkey|multi-player game" msgstr "" msgid "hotkey|settings" msgstr "" msgid "hotkey|quit" msgstr "" msgid "hotkey|select map" msgstr "" msgid "hotkey|select small map size" msgstr "" msgid "hotkey|select medium map size" msgstr "" msgid "hotkey|select large map size" msgstr "" msgid "hotkey|select extra large map size" msgstr "" msgid "hotkey|select all map sizes" msgstr "" #, fuzzy msgid "hotkey|hot seat game" msgstr "Systeem instellingen aanpassen" msgid "hotkey|battle only game" msgstr "" msgid "hotkey|choose the original campaign" msgstr "" msgid "hotkey|choose the expansion campaign" msgstr "" msgid "hotkey|map editor main menu" msgstr "" msgid "hotkey|new map menu" msgstr "" msgid "hotkey|load map menu" msgstr "" msgid "hotkey|new map from scratch" msgstr "" msgid "hotkey|new random map" msgstr "" #, fuzzy msgid "hotkey|undo last action" msgstr "Systeem instellingen aanpassen" #, fuzzy msgid "hotkey|redo last action" msgstr "Systeem instellingen aanpassen" #, fuzzy msgid "hotkey|open game main menu" msgstr "Systeem instellingen aanpassen" msgid "hotkey|toggle passability" msgstr "" msgid "hotkey|roland campaign" msgstr "" msgid "hotkey|archibald campaign" msgstr "" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "De Prijs van Loyaliteit" msgid "hotkey|voyage home campaign" msgstr "" msgid "hotkey|wizard's isle campaign" msgstr "" msgid "hotkey|descendants campaign" msgstr "" msgid "hotkey|select first campaign bonus" msgstr "" msgid "hotkey|select second campaign bonus" msgstr "" msgid "hotkey|select third campaign bonus" msgstr "" msgid "hotkey|view campaign intro" msgstr "" msgid "hotkey|select campaign difficulty" msgstr "" msgid "hotkey|restart campaign scenario" msgstr "" msgid "hotkey|world map left" msgstr "" msgid "hotkey|world map right" msgstr "" msgid "hotkey|world map up" msgstr "" msgid "hotkey|world map down" msgstr "" msgid "hotkey|world map up left" msgstr "" msgid "hotkey|world map up right" msgstr "" msgid "hotkey|world map down left" msgstr "" msgid "hotkey|world map down right" msgstr "" msgid "hotkey|save game" msgstr "" msgid "hotkey|next hero" msgstr "" msgid "hotkey|change to hero under cursor" msgstr "" msgid "hotkey|start hero movement" msgstr "" msgid "hotkey|cast adventure spell" msgstr "" msgid "hotkey|put hero to sleep" msgstr "" msgid "hotkey|next town" msgstr "" msgid "hotkey|end turn" msgstr "" msgid "hotkey|file options" msgstr "" msgid "hotkey|adventure options" msgstr "" msgid "hotkey|puzzle map" msgstr "" msgid "hotkey|scenario information" msgstr "" msgid "hotkey|dig for artifact" msgstr "" msgid "hotkey|view world" msgstr "" msgid "hotkey|kingdom summary" msgstr "" msgid "hotkey|default action" msgstr "" msgid "hotkey|open focus" msgstr "" #, fuzzy msgid "hotkey|system options" msgstr "Systeem instellingen aanpassen" msgid "hotkey|scroll left" msgstr "" msgid "hotkey|scroll right" msgstr "" msgid "hotkey|scroll up" msgstr "" msgid "hotkey|scroll down" msgstr "" msgid "hotkey|toggle control panel" msgstr "" msgid "hotkey|toggle radar" msgstr "" msgid "hotkey|toggle buttons" msgstr "" msgid "hotkey|toggle status" msgstr "" msgid "hotkey|toggle icons" msgstr "" msgid "hotkey|transfer control to ai" msgstr "" msgid "hotkey|retreat from battle" msgstr "" msgid "hotkey|surrender during battle" msgstr "" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Systeem instellingen aanpassen" msgid "hotkey|quick combat" msgstr "" msgid "hotkey|battle options" msgstr "" msgid "hotkey|skip turn in battle" msgstr "" msgid "hotkey|cast battle spell" msgstr "" msgid "hotkey|dwelling level 1" msgstr "" msgid "hotkey|dwelling level 2" msgstr "" msgid "hotkey|dwelling level 3" msgstr "" msgid "hotkey|dwelling level 4" msgstr "" msgid "hotkey|dwelling level 5" msgstr "" msgid "hotkey|dwelling level 6" msgstr "" msgid "hotkey|well" msgstr "" msgid "hotkey|marketplace" msgstr "" msgid "hotkey|mage guild" msgstr "" msgid "hotkey|shipyard" msgstr "" msgid "hotkey|thieves guild" msgstr "" msgid "hotkey|tavern" msgstr "" msgid "hotkey|construction screen" msgstr "" msgid "hotkey|buy all monsters in well" msgstr "" msgid "hotkey|split stack by half" msgstr "" msgid "hotkey|split stack by one" msgstr "" msgid "hotkey|join stacks" msgstr "" msgid "hotkey|upgrade troop" msgstr "" msgid "hotkey|dismiss hero or troop" msgstr "" msgid "hotkey|exchange all troops" msgstr "" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Wil je controle terug nemen van de AI? Het effect neemt alleen plaats\n" "de volgende ronde." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" msgid "Default Actions" msgstr "" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "" #, fuzzy msgid "Battle Screen" msgstr "Held Scherm" #, fuzzy msgid "Town Screen" msgstr "Held Scherm" msgid "Army Actions" msgstr "" #, fuzzy msgid "The save file is corrupted." msgstr "Het spiegelbeeld wordt gecreëerd." msgid "Unsupported save format: " msgstr "" msgid "Current game version: " msgstr "" msgid "Last supported version: " msgstr "" msgid "This file contains a save with an invalid game type." msgstr "" msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" msgid "This saved game is localized to '" msgstr "" msgid "' language, but the current language of the game is '" msgstr "" msgid "No save files to load." msgstr "" msgid "Hot Seat" msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "A single player game playing out a single map." msgstr "" msgid "Standard Game" msgstr "" msgid "A single player game playing through a series of maps." msgstr "" msgid "Campaign Game" msgstr "" msgid "Multi-Player Game" msgstr "" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" msgid "fheroes2 Resurrection Team presents" msgstr "" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" msgid "Greetings!" msgstr "" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" msgid "Credits" msgstr "" msgid "View the credits screen." msgstr "" msgid "View the high scores screen." msgstr "" msgid "Create new or modify existing maps." msgstr "" msgid "Change language, resolution and settings of the game." msgstr "" msgid "Game Settings" msgstr "" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" msgid "Original Campaign" msgstr "" msgid "Expansion Campaign" msgstr "" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" msgid "Loading video. Please wait..." msgstr "" msgid "Host" msgstr "" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" msgid "Guest" msgstr "" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" msgid "Battle Only" msgstr "" msgid "Setup and play a battle without loading any map." msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "2 Players" msgstr "" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" msgid "3 Players" msgstr "" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" msgid "4 Players" msgstr "" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" msgid "5 Players" msgstr "" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" msgid "6 Players" msgstr "" msgid "Play with 6 human players." msgstr "" msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" msgid "Ultimate Artifact" msgstr "" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" msgid "Victory!" msgstr "" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" msgid "You have been eliminated from the game!!!" msgstr "" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" #, fuzzy msgid "Defeat!" msgstr " verslagen" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" msgid "Your side defeats the opposing side." msgstr "" msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "" msgstr[1] "" msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" msgstr[1] "" msgid "Capture the castle '%{name}'." msgstr "" msgid "Capture the town '%{name}'." msgstr "" msgid "Defeat the hero '%{name}'." msgstr "" msgid "Find the ultimate artifact." msgstr "" msgid "Find the '%{name}' artifact." msgstr "" msgid "Accumulate %{count} gold." msgstr "" msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" msgid "Lose the castle '%{name}'." msgstr "" msgid "Lose the town '%{name}'." msgstr "" msgid "Lose the hero: %{name}." msgstr "" msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" msgid "%{color} player has been vanquished!" msgstr "" msgid "Major Event!" msgstr "" msgid "Scenario:" msgstr "" msgid "Game Difficulty:" msgstr "" msgid "Opponents:" msgstr "" msgid "Class:" msgstr "" msgid "Rating %{rating}%" msgstr "" msgid "Click here to select which scenario to play." msgstr "" msgid "Scenario" msgstr "" msgid "Game Difficulty" msgstr "" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" msgid "Difficulty Rating" msgstr "" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" msgid "Click to accept these settings and start a new game." msgstr "" msgid "Click to return to the main menu." msgstr "" msgid "Astrologers proclaim the Month of the %{name}." msgstr "" msgid "Astrologers proclaim the Week of the %{name}." msgstr "" msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" msgstr[1] "" msgid "%{monster} growth +%{count}." msgstr "" msgid " All populations are halved." msgstr "" msgid " All dwellings increase population." msgstr "" msgid "New Month!" msgstr "" msgid "New Week!" msgstr "" msgid "Beware!" msgstr "" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" msgid "%{color} player's turn." msgstr "" msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" msgid "Lord Kilburn" msgstr "" msgid "Tsabu" msgstr "" msgid "Sir Galant" msgstr "" msgid "Thundax" msgstr "" msgid "Lord Haart" msgstr "" msgid "Ariel" msgstr "" msgid "Rebecca" msgstr "" msgid "Sandro" msgstr "" msgid "Crodo" msgstr "" msgid "Barock" msgstr "" msgid "Antoine" msgstr "" msgid "Astra" msgstr "" msgid "Agar" msgstr "" msgid "Vatawna" msgstr "" msgid "Vesper" msgstr "" msgid "Ambrose" msgstr "" msgid "Troyan" msgstr "" msgid "Jojosh" msgstr "" msgid "Wrathmont" msgstr "" msgid "Maximus" msgstr "" msgid "Next Hero" msgstr "" msgid "Select the next Hero." msgstr "" #, fuzzy msgid "Hero Movement" msgstr "Schaduw Beweging" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "" msgid "View a summary of your Kingdom." msgstr "" msgid "Cast an adventure spell." msgstr "" msgid "End Turn" msgstr "" msgid "End your turn and let the computer take its turn." msgstr "" msgid "Adventure Options" msgstr "" msgid "Bring up the adventure options menu." msgstr "" msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" msgid "Are you sure you want to quit?" msgstr "" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" msgid "Are you sure you want to overwrite the save with this name?" msgstr "" msgid "Game saved successfully." msgstr "" msgid "There was an issue during saving." msgstr "" msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" msgid "Try looking on land!!!" msgstr "" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" msgid "Congratulations!" msgstr "" msgid "Nothing here. Where could it be?" msgstr "" msgid "Try searching on clear ground." msgstr "" msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" msgid "Month: %{month} Week: %{week}" msgstr "" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" msgid "Status Window" msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" msgid "Handicap" msgstr "" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" msgid "%{color} player" msgstr "" msgid "No Handicap" msgstr "" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" msgid "Mild Handicap" msgstr "" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" msgid "Severe Handicap" msgstr "" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Aanvalsvaardigheid instellen" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "" msgid "" "Default\n" "skill" msgstr "" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "" msgid "Kingdom Income per day." msgstr "" msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "Nederlands" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" #, fuzzy msgid "Vietnamese" msgstr "Zie %{name}" msgid "Slow" msgstr "" msgid "Fast" msgstr "" msgid "Very Fast" msgstr "" msgid "Evil" msgstr "" msgid "Good" msgstr "" msgid ", FPS: " msgstr "" msgid "shipAndGraveyard|%{object} robber" msgstr "" msgid "pyramid|%{object} raided" msgstr "" msgid "Ector" msgstr "" msgid "Gwenneth" msgstr "" msgid "Sir Gallant" msgstr "" msgid "Tyro" msgstr "" msgid "Dimitry" msgstr "" msgid "Ruby" msgstr "" msgid "Crag Hack" msgstr "" msgid "Fineous" msgstr "" msgid "Jezebel" msgstr "" msgid "Atlas" msgstr "" msgid "Ergon" msgstr "" msgid "Jaclyn" msgstr "" msgid "Gem" msgstr "" msgid "Natasha" msgstr "" msgid "Carlawn" msgstr "" msgid "Luna" msgstr "" msgid "Arie" msgstr "" msgid "Barok" msgstr "" msgid "Kastore" msgstr "" msgid "Falagar" msgstr "" msgid "Dawn" msgstr "" msgid "Flint" msgstr "" msgid "Halon" msgstr "" msgid "Myra" msgstr "" msgid "Myrini" msgstr "" msgid "Wilfrey" msgstr "" msgid "Mandigal" msgstr "" msgid "Sarakin" msgstr "" msgid "Charity" msgstr "" msgid "Darlana" msgstr "" msgid "Ranloo" msgstr "" msgid "Rialdo" msgstr "" msgid "Zam" msgstr "" msgid "Zom" msgstr "" msgid "Celia" msgstr "" msgid "Roxana" msgstr "" msgid "Lord Corlagon" msgstr "" msgid "Lord Halton" msgstr "" msgid "Sister Eliza" msgstr "" msgid "Brother Brax" msgstr "" msgid "Dainwin" msgstr "" msgid "Joseph" msgstr "" msgid "Mog" msgstr "" msgid "Solmyr" msgstr "" msgid "Ceallach" msgstr "" msgid "Drakonia" msgstr "" msgid "Elderian" msgstr "" msgid "Gallavant" msgstr "" msgid "Jarkonas" msgstr "" msgid "Martine" msgstr "" msgid " gives you maximum morale" msgstr "" msgid " gives you maximum luck" msgstr "" msgid "You cannot have multiple spell books." msgstr "" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" msgid "Do you wish to buy one?" msgstr "" msgid "%{count} / day" msgstr "" msgid "one" msgstr "" msgid "two" msgstr "" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" msgid "You come upon the remains of an unfortunate adventurer." msgstr "" msgid "Treasure" msgstr "" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" msgid "Searching through the tattered clothing, you find nothing." msgstr "" msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" msgid "Searching inside, you find the %{artifact}." msgstr "" msgid "Inside, you find some of the wagon's cargo still intact." msgstr "" msgid "You search through the flotsam, and find some wood and some gold." msgstr "" msgid "You search through the flotsam, and find some wood." msgstr "" msgid "You search through the flotsam, but find nothing." msgstr "" msgid "Shrine of the 1st Circle" msgstr "" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 2nd Circle" msgstr "" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 3rd Circle" msgstr "" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" msgid "You drink from the enchanted fountain, but nothing happens." msgstr "" msgid "You enter the faerie ring, but nothing happens." msgstr "" msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" msgid "A second drink at the well in one day will not help you." msgstr "" msgid "A drink from the well has restored your spell points to maximum." msgstr "" msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" msgid "Do you wish to buy this artifact?" msgstr "" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" msgid "You've found the artifact: " msgstr "" msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" msgid "Victorious, you take your prize, the %{art}." msgstr "" msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" msgid "You gain control of a %{name}." msgstr "" msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "" msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" msgid "No Fire Elementals approach you from the lava pool." msgstr "" msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" msgid "A face forms in the water for a moment, and then is gone." msgstr "" msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" msgid "This burial site is deathly still." msgstr "" msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" msgid "From the observation tower, you are able to see distant lands." msgstr "" msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" msgid " and " msgstr "" msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "" msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" msgid "You have already been to this obelisk." msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "" msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" msgid "(Just bury it around my roots.)" msgstr "" msgid "Tears brim in the eyes of the tree." msgstr "" msgid "\"I need %{count} %{res}.\"" msgstr "" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" msgstr[1] "" msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" msgstr[1] "" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" msgstr[1] "" msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" msgid "The Arena guards turn you away." msgstr "" msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" msgid "This eye seems to be intently studying its surroundings." msgstr "" msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" #, fuzzy msgid "No spell book is present." msgstr "Geen spreuken om uit te spreken." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" msgid "The spell was not found." msgstr "" msgid "Only heroes can cast this spell." msgstr "" msgid "This hero is not able to cast adventure spells." msgstr "" msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" msgid "This spell cannot be cast on a boat." msgstr "" msgid "This spell can only be cast near an ocean." msgstr "" msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" msgid "There are no boats available for this spell." msgstr "" #, fuzzy msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Er is geen open plek aangrenzend bij je held om een Elemental naar toe te " "oproepen." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" #, fuzzy msgid "This hero is already in a town, so this spell will have no effect." msgstr "Die spreuk zal niemand beïnvloeden!" msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" msgid "This spell is already in effect." msgstr "" msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" msgid "%{name} the %{race} (Level %{level})" msgstr "" msgid "Random hero (Level %{level})" msgstr "" msgid "Random %{race} hero (Level %{level})" msgstr "" #, fuzzy msgid "Hero race:" msgstr "Held Scherm" msgid "Are you sure you want to dismiss this Hero?" msgstr "" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Spreuk Punten" msgid "View Spell Points Info" msgstr "" msgid "Set patrol radius in tiles" msgstr "" msgid "Enter hero's name" msgstr "" msgid "Click to change race." msgstr "" msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" msgid "Exit Hero Screen" msgstr "" msgid "You cannot dismiss a hero in a castle" msgstr "" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "" msgid "Dismiss %{name} the %{race}" msgstr "" msgid "Show previous hero" msgstr "" msgid "Show next hero" msgstr "" msgid "Set army combat formation to 'Spread'" msgstr "" msgid "Set army combat formation to 'Grouped'" msgstr "" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "" "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" msgid "Blood Morale" msgstr "" msgid "%{morale} Morale" msgstr "" msgid "%{luck} Luck" msgstr "" msgid "Current Luck Modifiers:" msgstr "" msgid "Current Morale Modifiers:" msgstr "" msgid "Entire army is undead, so morale does not apply." msgstr "" msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" msgid "%{name1} meets %{name2}" msgstr "" msgid "Enemy heroes are now fully identifiable." msgstr "" msgid "Identify Hero" msgstr "" msgid "Select town to port to." msgstr "" msgid "Town Portal" msgstr "" msgid "The creatures are willing to join us!" msgstr "" msgid "All the creatures will join us..." msgstr "" msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "" msgstr[1] "" msgid "" "\n" " for a fee of %{gold} gold." msgstr "" msgid "These weak creatures will surely flee before us." msgstr "" msgid "I fear these creatures are in the mood for a fight." msgstr "" #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "elk met een +%{attack} bonus voor hun aanvalsvaardigheid." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" msgid "The hero's spell power determines the duration or power of a spell." msgstr "" msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" msgid "Current Modifiers:" msgstr "" msgid "skill|Basic" msgstr "" msgid "skill|Advanced" msgstr "" msgid "skill|Expert" msgstr "" msgid "Pathfinding" msgstr "" msgid "Archery" msgstr "" msgid "Logistics" msgstr "" msgid "Scouting" msgstr "" msgid "Diplomacy" msgstr "" msgid "Navigation" msgstr "" msgid "Leadership" msgstr "" msgid "Wisdom" msgstr "" msgid "Mysticism" msgstr "" msgid "Ballistics" msgstr "" msgid "Eagle Eye" msgstr "" msgid "Necromancy" msgstr "" msgid "Estates" msgstr "" msgid "Advanced Archery" msgstr "" msgid "Advanced Pathfinding" msgstr "" msgid "Basic Archery" msgstr "" msgid "Basic Pathfinding" msgstr "" msgid "Expert Pathfinding" msgstr "" msgid "Advanced Logistics" msgstr "" msgid "Basic Logistics" msgstr "" msgid "Basic Scouting" msgstr "" msgid "Expert Archery" msgstr "" msgid "Expert Logistics" msgstr "" msgid "Advanced Diplomacy" msgstr "" msgid "Advanced Scouting" msgstr "" msgid "Basic Diplomacy" msgstr "" msgid "Expert Diplomacy" msgstr "" msgid "Expert Scouting" msgstr "" msgid "Advanced Leadership" msgstr "" msgid "Advanced Navigation" msgstr "" msgid "Basic Leadership" msgstr "" msgid "Basic Navigation" msgstr "" msgid "Expert Navigation" msgstr "" msgid "Advanced Wisdom" msgstr "" msgid "Basic Mysticism" msgstr "" msgid "Basic Wisdom" msgstr "" msgid "Expert Leadership" msgstr "" msgid "Expert Wisdom" msgstr "" msgid "Advanced Luck" msgstr "" msgid "Advanced Mysticism" msgstr "" msgid "Basic Luck" msgstr "" msgid "Expert Luck" msgstr "" msgid "Expert Mysticism" msgstr "" msgid "Advanced Ballistics" msgstr "" msgid "Advanced Eagle Eye" msgstr "" msgid "Basic Ballistics" msgstr "" msgid "Basic Eagle Eye" msgstr "" msgid "Expert Ballistics" msgstr "" msgid "Advanced Necromancy" msgstr "" msgid "Basic Estates" msgstr "" msgid "Basic Necromancy" msgstr "" msgid "Expert Eagle Eye" msgstr "" msgid "Expert Necromancy" msgstr "" msgid "Advanced Estates" msgstr "" msgid "Expert Estates" msgstr "" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "" msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "" msgstr[1] "" msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" msgid "All of the creatures may offer to join the hero." msgstr "" msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "" msgid "%{skill} allows the hero to learn third level spells." msgstr "" msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" msgid "%{skill} allows the hero to learn fifth level spells." msgstr "" msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" msgstr[1] "" msgid "%{skill} increases the hero's luck by %{count}." msgstr "" msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" msgid "Blue" msgstr "" msgid "Green" msgstr "" msgid "Red" msgstr "" msgid "Yellow" msgstr "" msgid "Orange" msgstr "" msgid "Purple" msgstr "" msgid "barrier|Aqua" msgstr "" msgid "barrier|Blue" msgstr "" msgid "barrier|Brown" msgstr "" msgid "barrier|Gold" msgstr "" msgid "barrier|Green" msgstr "" msgid "barrier|Orange" msgstr "" msgid "barrier|Purple" msgstr "" msgid "barrier|Red" msgstr "" msgid "tent|Aqua" msgstr "" msgid "tent|Blue" msgstr "" msgid "tent|Brown" msgstr "" msgid "tent|Gold" msgstr "" msgid "tent|Green" msgstr "" msgid "tent|Orange" msgstr "" msgid "tent|Purple" msgstr "" msgid "tent|Red" msgstr "" msgid "Experience" msgstr "" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" msgid "Hero/Stats" msgstr "" msgid "Skills" msgstr "" msgid "Town/Castle" msgstr "" msgid "Garrison" msgstr "" msgid "Gold Per Day:" msgstr "" msgid "View Heroes." msgstr "" msgid "Towns/Castles" msgstr "" msgid "View Towns and Castles." msgstr "" msgid "luck|Cursed" msgstr "" msgid "luck|Awful" msgstr "" msgid "luck|Bad" msgstr "" msgid "luck|Normal" msgstr "" msgid "luck|Good" msgstr "" msgid "luck|Great" msgstr "" msgid "luck|Irish" msgstr "" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" msgid "morale|Treason" msgstr "" msgid "morale|Awful" msgstr "" msgid "morale|Poor" msgstr "" msgid "morale|Normal" msgstr "" msgid "morale|Good" msgstr "" msgid "morale|Great" msgstr "" msgid "morale|Blood!" msgstr "" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Een laag moreel zorgt ervoor dat het %{monster} in paniek bevriest." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Een laag moreel zorgt ervoor dat het %{monster} in paniek bevriest." msgid "Knight" msgstr "" msgid "Barbarian" msgstr "" msgid "Sorceress" msgstr "" msgid "Warlock" msgstr "" msgid "Wizard" msgstr "" msgid "Necromancer" msgstr "" msgid "Multi" msgstr "" msgid "doubleLined|Knight" msgstr "" msgid "doubleLined|Barbarian" msgstr "" msgid "doubleLined|Sorceress" msgstr "" msgid "doubleLined|Warlock" msgstr "" msgid "doubleLined|Wizard" msgstr "" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" msgid "doubleLinedRace|Multi" msgstr "" msgid "doubleLinedRace|Random" msgstr "" msgid "speed|Standing" msgstr "" msgid "speed|Crawling" msgstr "" msgid "speed|Very Slow" msgstr "" msgid "speed|Slow" msgstr "" msgid "speed|Average" msgstr "" msgid "speed|Fast" msgstr "" msgid "speed|Very Fast" msgstr "" msgid "speed|Ultra Fast" msgstr "" msgid "speed|Blazing" msgstr "" msgid "speed|Instant" msgstr "" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "" msgid "week|Rabbit" msgstr "" msgid "week|Gopher" msgstr "" msgid "week|Badger" msgstr "" msgid "week|Rat" msgstr "" msgid "week|Eagle" msgstr "" msgid "week|Weasel" msgstr "" msgid "week|Raven" msgstr "" msgid "week|Mongoose" msgstr "" msgid "week|Dog" msgstr "" msgid "week|Aardvark" msgstr "" msgid "week|Lizard" msgstr "" msgid "week|Tortoise" msgstr "" msgid "week|Hedgehog" msgstr "" msgid "week|Condor" msgstr "" msgid "week|Ant" msgstr "" msgid "week|Grasshopper" msgstr "" msgid "week|Dragonfly" msgstr "" msgid "week|Spider" msgstr "" msgid "week|Butterfly" msgstr "" msgid "week|Bumblebee" msgstr "" msgid "week|Locust" msgstr "" msgid "week|Earthworm" msgstr "" msgid "week|Hornet" msgstr "" msgid "week|Beetle" msgstr "" msgid "week|PLAGUE" msgstr "" msgid "week|Unnamed" msgstr "" msgid "Desert" msgstr "" msgid "Snow" msgstr "" msgid "Wasteland" msgstr "" msgid "Beach" msgstr "" msgid "Lava" msgstr "" msgid "Dirt" msgstr "" msgid "Grass" msgstr "" msgid "Ocean" msgstr "" msgid "maps|Small" msgstr "" msgid "maps|Medium" msgstr "" msgid "maps|Large" msgstr "" msgid "maps|Extra Large" msgstr "" msgid "maps|Custom Size" msgstr "" msgid "Ore Mine" msgstr "" msgid "Sulfur Mine" msgstr "" msgid "Crystal Mine" msgstr "" msgid "Gems Mine" msgstr "" msgid "Gold Mine" msgstr "" msgid "Mine" msgstr "" msgid "Burma shave." msgstr "" msgid "Next sign 50 miles." msgstr "" msgid "See Rock City." msgstr "" msgid "This space for rent." msgstr "" msgid "No object" msgstr "" msgid "Alchemist Lab" msgstr "" msgid "Sign" msgstr "" msgid "Buoy" msgstr "" msgid "Skeleton" msgstr "" msgid "Daemon Cave" msgstr "" msgid "Treasure Chest" msgstr "" msgid "Faerie Ring" msgstr "" msgid "Campfire" msgstr "" msgid "Fountain" msgstr "" msgid "Gazebo" msgstr "" msgid "Genie Lamp" msgstr "" msgid "Archer's House" msgstr "" msgid "Goblin Hut" msgstr "" msgid "Dwarf Cottage" msgstr "" msgid "Peasant Hut" msgstr "" msgid "Stables" msgstr "" msgid "Alchemist's Tower" msgstr "" msgid "Event" msgstr "" msgid "Dragon City" msgstr "" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "" msgstr[1] "" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "" msgstr[1] "" msgid "Monster" msgstr "" msgid "Obelisk" msgstr "" msgid "Oasis" msgstr "" msgid "Resource" msgstr "" msgid "Sawmill" msgstr "" msgid "Oracle" msgstr "" msgid "Shrine of the First Circle" msgstr "" msgid "Shipwreck" msgstr "" msgid "Sea Chest" msgstr "" msgid "Desert Tent" msgstr "" msgid "Stone Liths" msgstr "" msgid "Wagon Camp" msgstr "" msgid "Hut of the Magi" msgstr "" msgid "Whirlpool" msgstr "" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "" msgstr[1] "" msgid "Mermaid" msgstr "" msgid "Boat" msgstr "" msgid "Random Ultimate Artifact" msgstr "" msgid "Random Artifact" msgstr "" msgid "Random Resource" msgstr "" msgid "Random Monster" msgstr "" msgid "Random Town" msgstr "" msgid "Random Castle" msgstr "" msgid "Eye of the Magi" msgstr "" msgid "Random Monster - weak" msgstr "" msgid "Random Monster - medium" msgstr "" msgid "Random Monster - strong" msgstr "" msgid "Random Monster - very strong" msgstr "" msgid "Hero" msgstr "" msgid "Nothing Special" msgstr "" msgid "Mossy Rock" msgstr "" msgid "Watch Tower" msgstr "" msgid "Tree House" msgstr "" msgid "Tree City" msgstr "" msgid "Ruins" msgstr "" msgid "Fort" msgstr "" msgid "Abandoned Mine" msgstr "" msgid "Sirens" msgstr "" msgid "Standing Stones" msgstr "" msgid "Idol" msgstr "" msgid "Tree of Knowledge" msgstr "" msgid "Witch Doctor's Hut" msgstr "" msgid "Temple" msgstr "" msgid "Hill Fort" msgstr "" msgid "Halfling Hole" msgstr "" msgid "Mercenary Camp" msgstr "" msgid "Shrine of the Second Circle" msgstr "" msgid "Shrine of the Third Circle" msgstr "" msgid "City of the Dead" msgstr "" msgid "Sphinx" msgstr "" msgid "Wagon" msgstr "" msgid "Tar Pit" msgstr "" msgid "Artesian Spring" msgstr "" msgid "Troll Bridge" msgstr "" msgid "Watering Hole" msgstr "" msgid "Witch's Hut" msgstr "" msgid "Xanadu" msgstr "" msgid "Lean-To" msgstr "" msgid "Magellan's Maps" msgstr "" msgid "Flotsam" msgstr "" msgid "Derelict Ship" msgstr "" msgid "Shipwreck Survivor" msgstr "" msgid "Bottle" msgstr "" msgid "Magic Well" msgstr "" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "" msgstr[1] "" msgid "Observation Tower" msgstr "" msgid "Freeman's Foundry" msgstr "" msgid "Reefs" msgstr "" msgid "Volcano" msgstr "" msgid "Flowers" msgstr "" msgid "Rock" msgstr "" msgid "Water Lake" msgstr "" msgid "Mandrake" msgstr "" msgid "Dead Tree" msgstr "" msgid "Stump" msgstr "" msgid "Crater" msgstr "" msgid "Cactus" msgstr "" msgid "Mound" msgstr "" msgid "Dune" msgstr "" msgid "Lava Pool" msgstr "" msgid "Shrub" msgstr "" msgid "Barrow Mounds" msgstr "" msgid "Random Artifact - Treasure" msgstr "" msgid "Random Artifact - Minor" msgstr "" msgid "Random Artifact - Major" msgstr "" msgid "Barrier" msgstr "" msgid "Traveller's Tent" msgstr "" msgid "Jail" msgstr "" msgid "Fire Summoning Altar" msgstr "" msgid "Air Summoning Altar" msgstr "" msgid "Earth Summoning Altar" msgstr "" msgid "Water Summoning Altar" msgstr "" msgid "Swampy Lake" msgstr "" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "" msgid "Unknown Monster" msgstr "" msgid "Peasant" msgstr "" msgid "Peasants" msgstr "" msgid "Archer" msgstr "" msgid "Archers" msgstr "" msgid "Ranger" msgstr "" msgid "Rangers" msgstr "" msgid "Pikeman" msgstr "" msgid "Pikemen" msgstr "" msgid "Veteran Pikeman" msgstr "" msgid "Veteran Pikemen" msgstr "" msgid "Swordsman" msgstr "" msgid "Swordsmen" msgstr "" msgid "Master Swordsman" msgstr "" msgid "Master Swordsmen" msgstr "" msgid "Cavalries" msgstr "" msgid "Cavalry" msgstr "" msgid "Champion" msgstr "" msgid "Champions" msgstr "" msgid "Paladin" msgstr "" msgid "Paladins" msgstr "" msgid "Crusader" msgstr "" msgid "Crusaders" msgstr "" msgid "Goblin" msgstr "" msgid "Goblins" msgstr "" msgid "Orc" msgstr "" msgid "Orcs" msgstr "" msgid "Orc Chief" msgstr "" msgid "Orc Chiefs" msgstr "" msgid "Wolf" msgstr "" msgid "Wolves" msgstr "" msgid "Ogre" msgstr "" msgid "Ogres" msgstr "" msgid "Ogre Lord" msgstr "" msgid "Ogre Lords" msgstr "" msgid "Troll" msgstr "" msgid "Trolls" msgstr "" msgid "War Troll" msgstr "" msgid "War Trolls" msgstr "" msgid "Cyclopes" msgstr "" msgid "Cyclops" msgstr "" msgid "Sprite" msgstr "" msgid "Sprites" msgstr "" msgid "Dwarf" msgstr "" msgid "Dwarves" msgstr "" msgid "Battle Dwarf" msgstr "" msgid "Battle Dwarves" msgstr "" msgid "Elf" msgstr "" msgid "Elves" msgstr "" msgid "Grand Elf" msgstr "" msgid "Grand Elves" msgstr "" msgid "Druid" msgstr "" msgid "Druids" msgstr "" msgid "Greater Druid" msgstr "" msgid "Greater Druids" msgstr "" msgid "Unicorn" msgstr "" msgid "Unicorns" msgstr "" msgid "Phoenix" msgstr "" msgid "Phoenixes" msgstr "" msgid "Centaur" msgstr "" msgid "Centaurs" msgstr "" msgid "Gargoyle" msgstr "" msgid "Gargoyles" msgstr "" msgid "Griffin" msgstr "" msgid "Griffins" msgstr "" msgid "Minotaur" msgstr "" msgid "Minotaurs" msgstr "" msgid "Minotaur King" msgstr "" msgid "Minotaur Kings" msgstr "" msgid "Hydra" msgstr "" msgid "Hydras" msgstr "" msgid "Green Dragon" msgstr "" msgid "Green Dragons" msgstr "" msgid "Red Dragon" msgstr "" msgid "Red Dragons" msgstr "" msgid "Black Dragon" msgstr "" msgid "Black Dragons" msgstr "" msgid "Halfling" msgstr "" msgid "Halflings" msgstr "" msgid "Boar" msgstr "" msgid "Boars" msgstr "" msgid "Iron Golem" msgstr "" msgid "Iron Golems" msgstr "" msgid "Steel Golem" msgstr "" msgid "Steel Golems" msgstr "" msgid "Roc" msgstr "" msgid "Rocs" msgstr "" msgid "Mage" msgstr "" msgid "Magi" msgstr "" msgid "Archmage" msgstr "" msgid "Archmagi" msgstr "" msgid "Giant" msgstr "" msgid "Giants" msgstr "" msgid "Titan" msgstr "" msgid "Titans" msgstr "" msgid "Skeletons" msgstr "" msgid "Zombie" msgstr "" msgid "Zombies" msgstr "" msgid "Mutant Zombie" msgstr "" msgid "Mutant Zombies" msgstr "" msgid "Mummies" msgstr "" msgid "Mummy" msgstr "" msgid "Royal Mummies" msgstr "" msgid "Royal Mummy" msgstr "" msgid "Vampire" msgstr "" msgid "Vampires" msgstr "" msgid "Vampire Lord" msgstr "" msgid "Vampire Lords" msgstr "" msgid "Lich" msgstr "" msgid "Liches" msgstr "" msgid "Power Lich" msgstr "" msgid "Power Liches" msgstr "" msgid "Bone Dragon" msgstr "" msgid "Bone Dragons" msgstr "" msgid "Rogue" msgstr "" msgid "Rogues" msgstr "" msgid "Nomad" msgstr "" msgid "Nomads" msgstr "" msgid "Ghost" msgstr "" msgid "Ghosts" msgstr "" msgid "Genie" msgstr "" msgid "Genies" msgstr "" msgid "Medusa" msgstr "" msgid "Medusas" msgstr "" msgid "Earth Elemental" msgstr "" msgid "Earth Elementals" msgstr "" msgid "Air Elemental" msgstr "" msgid "Air Elementals" msgstr "" msgid "Fire Elemental" msgstr "" msgid "Fire Elementals" msgstr "" msgid "Water Elemental" msgstr "" msgid "Water Elementals" msgstr "" msgid "Random Monsters" msgstr "" msgid "Random Monster 1" msgstr "" msgid "Random Monsters 1" msgstr "" msgid "Random Monster 2" msgstr "" msgid "Random Monsters 2" msgstr "" msgid "Random Monster 3" msgstr "" msgid "Random Monsters 3" msgstr "" msgid "Random Monster 4" msgstr "" msgid "Random Monsters 4" msgstr "" msgid "Double shot" msgstr "" msgid "2-hex monster" msgstr "" msgid "Double strike" msgstr "" msgid "Double damage to Undead" msgstr "" msgid "% magic resistance" msgstr "" msgid "Immune to Mind spells" msgstr "" msgid "Immune to Elemental spells" msgstr "" msgid "Immune to Fire spells" msgstr "" msgid "Immune to Cold spells" msgstr "" msgid "Immune to " msgstr "" msgid "% immunity to %{spell} spell" msgstr "" msgid "% damage from Elemental spells" msgstr "" msgid "% damage from %{spell} spell" msgstr "" msgid "% chance to Dispel beneficial spells" msgstr "" msgid "% chance to Paralyze" msgstr "" msgid "% chance to Petrify" msgstr "" msgid "% chance to Blind" msgstr "" msgid "% chance to Curse" msgstr "" msgid "% chance to cast %{spell} spell" msgstr "" msgid "HP regeneration" msgstr "" msgid "Two hexes attack" msgstr "" msgid "Flyer" msgstr "" msgid "Always retaliates" msgstr "" msgid "Attacks all adjacent enemies" msgstr "" msgid "No melee penalty" msgstr "" msgid "Dragon" msgstr "" msgid "Undead" msgstr "" msgid "No enemy retaliation" msgstr "" msgid "HP drain" msgstr "" msgid "Cloud attack" msgstr "" msgid "Decreases enemy's morale by " msgstr "" msgid "% chance to halve enemy" msgstr "" msgid "Soul Eater" msgstr "" msgid "Elemental" msgstr "" msgid "No Morale" msgstr "" msgid "Earth creature" msgstr "" msgid "Air creature" msgstr "" msgid "Fire creature" msgstr "" msgid "Water creature" msgstr "" msgid "Double damage from Fire spells" msgstr "" msgid "Double damage from Cold spells" msgstr "" msgid "Double damage from Earth creatures" msgstr "" msgid "Double damage from Air creatures" msgstr "" msgid "Double damage from Fire creatures" msgstr "" msgid "Double damage from Water creatures" msgstr "" msgid "Lightning" msgstr "" msgid "% immunity to " msgstr "" msgid "% damage from " msgstr "" msgid "The three Anduran artifacts magically combine into one." msgstr "" msgid "View Spells" msgstr "" msgid "View %{name} Info" msgstr "" msgid "Move %{name}" msgstr "" msgid "Cannot move the Spellbook" msgstr "" msgid "This item can't be traded." msgstr "" msgid "Invalid Artifact" msgstr "" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "Ultimate Book of Knowledge" msgstr "" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "Ultimate Sword of Dominion" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "Ultimate Cloak of Protection" msgstr "" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "Ultimate Wand of Magic" msgstr "" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" msgid "Ultimate Shield" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "Ultimate Staff" msgstr "" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "" msgid "Ultimate Crown" msgstr "" msgid "Golden Goose" msgstr "" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "" msgid "Arcane Necklace of Magic" msgstr "" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" msgid "Caster's Bracelet of Magic" msgstr "" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" msgid "Mage's Ring of Power" msgstr "" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" msgid "Witch's Broach of Magic" msgstr "" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" msgid "Medal of Valor" msgstr "" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" msgid "Medal of Courage" msgstr "" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" msgid "Medal of Honor" msgstr "" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" msgid "Medal of Distinction" msgstr "" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" msgid "Fizbin of Misfortune" msgstr "" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "" msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" msgid "Thunder Mace of Dominion" msgstr "" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" msgid "Armored Gauntlets of Protection" msgstr "" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" msgid "Defender Helm of Protection" msgstr "" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" msgid "Giant Flail of Dominion" msgstr "" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" msgid "Ballista of Quickness" msgstr "" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" msgid "Stealth Shield of Protection" msgstr "" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" msgid "Dragon Sword of Dominion" msgstr "" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" msgid "Power Axe of Dominion" msgstr "" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" msgid "Divine Breastplate of Protection" msgstr "" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" msgid "Minor Scroll of Knowledge" msgstr "" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" msgid "Major Scroll of Knowledge" msgstr "" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" msgid "Superior Scroll of Knowledge" msgstr "" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" msgid "Foremost Scroll of Knowledge" msgstr "" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" msgid "Endless Sack of Gold" msgstr "" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" msgid "Endless Bag of Gold" msgstr "" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" msgid "Endless Purse of Gold" msgstr "" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" msgid "Nomad Boots of Mobility" msgstr "" msgid "The %{name} increase the hero's movement on land." msgstr "" msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" msgid "Traveler's Boots of Mobility" msgstr "" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" msgid "Lucky Rabbit's Foot" msgstr "" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" msgid "Golden Horseshoe" msgstr "" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" msgid "Gambler's Lucky Coin" msgstr "" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" msgid "Four-Leaf Clover" msgstr "" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" msgid "True Compass of Mobility" msgstr "" msgid "The %{name} increases the hero's movement on land and sea." msgstr "" msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" msgid "Sailor's Astrolabe of Mobility" msgstr "" msgid "The %{name} increases the hero's movement on sea." msgstr "" msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" msgid "Evil Eye" msgstr "" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" msgid "Enchanted Hourglass" msgstr "" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" msgid "Gold Watch" msgstr "" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "" msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" msgid "Skullcap" msgstr "" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" msgid "Ice Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" msgid "Fire Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" msgid "Lightning Helm" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" msgid "Evercold Icicle" msgstr "" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" msgid "Everhot Lava Rock" msgstr "" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" msgid "Lightning Rod" msgstr "" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" msgid "Snake-Ring" msgstr "" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" msgid "Ankh" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" msgid "Book of Elements" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" msgid "Elemental Ring" msgstr "" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" msgid "Holy Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" msgid "Pendant of Free Will" msgstr "" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" msgid "Pendant of Life" msgstr "" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "" msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" msgid "Serenity Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" msgid "Seeing-eye Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" msgid "Kinetic Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" msgid "Pendant of Death" msgstr "" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" msgid "Wand of Negation" msgstr "" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" msgid "Golden Bow" msgstr "" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" msgid "Telescope" msgstr "" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" msgid "Statesman's Quill" msgstr "" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" msgid "Wizard's Hat" msgstr "" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" msgid "Power Ring" msgstr "" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" msgid "Ammo Cart" msgstr "" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" msgid "Tax Lien" msgstr "" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" msgid "Hideous Mask" msgstr "" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" msgid "Endless Pouch of Sulfur" msgstr "" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "" msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" msgid "Endless Vial of Mercury" msgstr "" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "" msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" msgid "Endless Pouch of Gems" msgstr "" msgid "The %{name} provides %{count} unit of gems per day." msgstr "" msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" msgid "Endless Cord of Wood" msgstr "" msgid "The %{name} provides %{count} unit of wood per day." msgstr "" msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" msgid "Endless Cart of Ore" msgstr "" msgid "The %{name} provides %{count} unit of ore per day." msgstr "" msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" msgid "Endless Pouch of Crystal" msgstr "" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "" msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" msgid "Spiked Helm" msgstr "" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" msgid "Spiked Shield" msgstr "" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" msgid "White Pearl" msgstr "" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" msgid "Black Pearl" msgstr "" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" msgid "Magic Book" msgstr "" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "De %{name} weerstaat de spreuk!" msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "" msgid "The reserved artifact." msgstr "" msgid "Dummy 3" msgstr "" msgid "Dummy 4" msgstr "" msgid "Spell Scroll" msgstr "" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" msgid "Arm of the Martyr" msgstr "" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" msgid "Breastplate of Anduran" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" msgid "Broach of Shielding" msgstr "" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" msgid "Battle Garb of Anduran" msgstr "" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" msgid "Crystal Ball" msgstr "" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" msgid "Heart of Fire" msgstr "" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" msgid "Heart of Ice" msgstr "" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" msgid "Helmet of Anduran" msgstr "" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" msgid "Holy Hammer" msgstr "" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" msgid "Legendary Scepter" msgstr "" msgid "The %{name} adds %{count} points to all attributes." msgstr "" msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" msgid "Masthead" msgstr "" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" msgid "Sphere of Negation" msgstr "" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" msgid "Staff of Wizardry" msgstr "" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "De %{name} vuurt met de kracht van %{count} Boogschutters" msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" msgid "Sword Breaker" msgstr "" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "" msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" msgid "Sword of Anduran" msgstr "" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" msgid "Spade of Necromancy" msgstr "" msgid "The %{name} gives the hero increased necromancy skill." msgstr "" msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "" msgid "Mercury" msgstr "" msgid "Ore" msgstr "" msgid "Sulfur" msgstr "" msgid "Crystal" msgstr "" msgid "Gems" msgstr "" msgid "Gold" msgstr "" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" msgid "Fireball" msgstr "" msgid "Fireblast" msgstr "" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "" msgid "Lightning Bolt" msgstr "" msgid "Chain Lightning" msgstr "" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" msgid "Teleport" msgstr "" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" msgid "Cure" msgstr "" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" msgid "Mass Cure" msgstr "" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" msgid "Resurrect" msgstr "" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" msgid "Resurrect True" msgstr "" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" msgid "Haste" msgstr "" msgid "Increases the speed of any creature by %{count}." msgstr "" msgid "Increases the speed of all of your creatures by %{count}." msgstr "" msgid "Mass Haste" msgstr "" msgid "Slows target to half movement rate." msgstr "" msgid "spell|Slow" msgstr "" msgid "Mass Slow" msgstr "" msgid "Slows all enemies to half movement rate." msgstr "" msgid "spell|Blind" msgstr "" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" msgid "Bless" msgstr "" msgid "Causes the selected creatures to inflict maximum damage." msgstr "" msgid "Causes all of your units to inflict maximum damage." msgstr "" msgid "Mass Bless" msgstr "" msgid "Magically increases the defense skill of the selected creatures." msgstr "" msgid "Stoneskin" msgstr "" msgid "Steelskin" msgstr "" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" msgid "Causes the selected creatures to inflict minimum damage." msgstr "" msgid "Curse" msgstr "" msgid "Causes all enemy troops to inflict minimum damage." msgstr "" msgid "Mass Curse" msgstr "" msgid "Damages all undead in the battle." msgstr "" msgid "Holy Word" msgstr "" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" msgid "Holy Shout" msgstr "" msgid "Anti-Magic" msgstr "" msgid "Prevents any magic against the selected creatures." msgstr "" msgid "Dispel Magic" msgstr "" msgid "Removes all magic spells from a single target." msgstr "" msgid "Mass Dispel" msgstr "" msgid "Removes all magic spells from all creatures." msgstr "" msgid "Causes a magic arrow to strike the selected target." msgstr "" msgid "Magic Arrow" msgstr "" msgid "Berserker" msgstr "" msgid "Causes a creature to attack its nearest neighbor." msgstr "" msgid "Armageddon" msgstr "" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" msgid "Elemental Storm" msgstr "" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" msgid "Meteor Shower" msgstr "" msgid "Paralyze" msgstr "" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" msgid "Hypnotize" msgstr "" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" msgid "Cold Ray" msgstr "" msgid "Drains body heat from a single enemy unit." msgstr "" msgid "Cold Ring" msgstr "" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" msgid "Disrupting Ray" msgstr "" msgid "Reduces the defense rating of an enemy unit by three." msgstr "" msgid "Damages all living (non-undead) units in the battle." msgstr "" msgid "Death Ripple" msgstr "" msgid "Death Wave" msgstr "" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" msgid "Dragon Slayer" msgstr "" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "" msgid "Blood Lust" msgstr "" msgid "Increases a unit's attack skill." msgstr "" msgid "Animate Dead" msgstr "" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" msgid "Mirror Image" msgstr "" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" msgid "Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Mass Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Summon Earth Elemental" msgstr "" msgid "Summons Earth Elementals to fight for your army." msgstr "" msgid "Summon Air Elemental" msgstr "" msgid "Summons Air Elementals to fight for your army." msgstr "" msgid "Summon Fire Elemental" msgstr "" msgid "Summons Fire Elementals to fight for your army." msgstr "" msgid "Summon Water Elemental" msgstr "" msgid "Summons Water Elementals to fight for your army." msgstr "" msgid "Damages castle walls." msgstr "" msgid "Earthquake" msgstr "" msgid "Causes all mines across the land to become visible." msgstr "" msgid "View Mines" msgstr "" msgid "Causes all resources across the land to become visible." msgstr "" msgid "View Resources" msgstr "" msgid "Causes all artifacts across the land to become visible." msgstr "" msgid "View Artifacts" msgstr "" msgid "Causes all towns and castles across the land to become visible." msgstr "" msgid "View Towns" msgstr "" msgid "Causes all Heroes across the land to become visible." msgstr "" msgid "View Heroes" msgstr "" msgid "Causes the entire land to become visible." msgstr "" msgid "View All" msgstr "" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" msgid "Summon Boat" msgstr "" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" msgid "Allows the caster to magically transport to a nearby location." msgstr "" msgid "Dimension Door" msgstr "" msgid "Returns the caster to any town or castle currently owned." msgstr "" msgid "Town Gate" msgstr "" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" msgid "Visions" msgstr "" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" msgid "Haunt" msgstr "" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" msgid "Set Earth Guardian" msgstr "" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Air Guardian" msgstr "" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Fire Guardian" msgstr "" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Water Guardian" msgstr "" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" #, fuzzy msgid "Random Spell" msgstr "Spreuk uitspreken" msgid "Randomly selected spell of any level." msgstr "" msgid "Random 1st Level Spell" msgstr "" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" msgid "No spell to cast." msgstr "" msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "" msgid "View Adventure Spells" msgstr "" msgid "View Combat Spells" msgstr "" msgid "View previous page" msgstr "" msgid "View next page" msgstr "" msgid "Close Spellbook" msgstr "" msgid "View %{spell}" msgstr "" msgid "This spell does %{damage} points of damage." msgstr "" msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" msgid "This spell restores %{hp} HP." msgstr "" msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" msgid "The nearest town is %{town}." msgstr "" msgid "This town is occupied by your hero %{hero}." msgstr "" msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" msgid "The ultimate artifact is really the %{name}." msgstr "" msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" msgid "north-west" msgstr "" msgid "north" msgstr "" msgid "north-east" msgstr "" msgid "west" msgstr "" msgid "center" msgstr "" msgid "east" msgstr "" msgid "south-west" msgstr "" msgid "south" msgstr "" msgid "south-east" msgstr "" msgid "The truth is out there." msgstr "" msgid "The dark side is stronger." msgstr "" msgid "The end of the world is near." msgstr "" msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" msgid "A Black Dragon will take out a Titan any day of the week." msgstr "" msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" msgid "An unknown force is being resurrected..." msgstr "" msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" #~ msgid "Enable auto combat" #~ msgstr "Automatische gevechten inschakelen" #, fuzzy #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "" #~ "Weet je zeker dat je het gevecht in de automatische modus wilt beëindigen?" fheroes2-1.1.6+dfsg/files/lang/pl.po000066400000000000000000012001561476115357100171700ustar00rootroot00000000000000# Polish translation of fheroes2 # Copyright (C) 2021 - 2022 fheroes2 team # Copyright (C) 2009 Igor Orlov # Copyright (C) 2009 Andrey Afletdinov # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-07-20 23:19+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: https://discord.com/" "channels/733093692860137523/817386375888371772\n" "Language: pl\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==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2;\n" "X-Launchpad-Export-Date: 2013-10-09 02:01+0000\n" "X-Generator: Poedit 3.4.4\n" msgid "" "NEW\n" "GAME" msgstr "" "NOWA\n" "GRA" msgid "" "SAVE\n" "GAME" msgstr "" "ZAPISZ\n" "GRĘ" msgid "" "LOAD\n" "GAME" msgstr "" "WCZYTAJ\n" "GRĘ" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "WYJÅšCIE" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "NOWA\n" "GRA" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "ZAPISZ\n" "GRĘ" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "WCZYTAJ\n" "GRĘ" msgid "CANCEL" msgstr "ANULUJ" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "ZGÓDŹ SIĘ" msgid "DECLINE" msgstr "ODRZUĆ" msgid "LEARN" msgstr "NAUKA" msgid "TRADE" msgstr "WYMIEŃ" msgid "YES" msgstr "TAK" msgid "NO" msgstr "NIE" msgid "EXIT" msgstr "WYJÅšCIE" #, fuzzy msgid "smallerButton|EXIT" msgstr "OK" msgid "DISMISS" msgstr "ZWOLNIJ" msgid "UPGRADE" msgstr "ULEPSZ" msgid "RESTART" msgstr "OD NOWA" msgid "HEROES" msgstr "BOHATEROWIE" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "MIASTA/\n" "ZAMKI" msgid "S" msgstr "M" msgid "M" msgstr "Åš" msgid "L" msgstr "D" msgid "X-L" msgstr "BD" msgid "ALL" msgstr "M-BD" msgid "SELECT" msgstr "WYBIERZ" msgid "" "STANDARD\n" "GAME" msgstr "" "GRA\n" "STANDARDOWA" msgid "" "BATTLE\n" "ONLY" msgstr "" "TYLKO\n" "WALKA" msgid "" "CAMPAIGN\n" "GAME" msgstr "KAMPANIA" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "GRA\n" "DLA WIELU\n" "OSÓB" msgid "CONFIG" msgstr "KONFIGURACJA" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ORYGINALNA\n" "KAMPANIA" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "KAMPANIA Z\n" "ROZSZERZENIA" msgid "HOT SEAT" msgstr "" "ZMIANA\n" "MIEJSC" msgid "2 PLAYERS" msgstr "2 GRACZY" msgid "3 PLAYERS" msgstr "3 GRACZY" msgid "4 PLAYERS" msgstr "4 GRACZY" msgid "5 PLAYERS" msgstr "5 GRACZY" msgid "6 PLAYERS" msgstr "6 GRACZY" msgid "GIFT" msgstr "WYÅšLIJ" msgid "MAX" msgstr "MAKS" msgid "DIFFICULTY" msgstr "TRUDNOŚĆ" msgid "VIEW INTRO" msgstr "" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "" #, fuzzy msgid "START" msgstr "OD NOWA" msgid "TOWN" msgstr "" #, fuzzy msgid "CASTLE" msgstr "" "MIASTA/\n" "ZAMKI" #, fuzzy msgid "RESTRICT" msgstr "OD NOWA" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Wojownik" msgid "Builder" msgstr "Budowniczy" msgid "Explorer" msgstr "Badacz" msgid "None" msgstr "Brak" msgid "" "A few\n" "%{monster}" msgstr "" "MaÅ‚o\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "ParÄ™\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Grupa\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Mnóstwo\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Horda\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "TÅ‚um\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Mrowie\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Setki\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Legion\n" "%{monster}" msgid "army|Few" msgstr "MaÅ‚o" msgid "army|Several" msgstr "ParÄ™" msgid "army|Pack" msgstr "Grupa" msgid "army|Lots" msgstr "Mnóstwo" msgid "army|Horde" msgstr "Horda" msgid "army|Throng" msgstr "TÅ‚um" msgid "army|Swarm" msgstr "Mrowie" msgid "army|Zounds" msgstr "Setki" msgid "army|Legion" msgstr "Legion" msgid "All %{race} troops +1" msgstr "Wszystkie %{race} oddziaÅ‚y +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Neutralny" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Jednostki z %{count} różnych frakcji -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "Nieumarli w armii -1" #, fuzzy msgid "" "Default\n" "troop" msgstr "domyÅ›lna akcja" msgid "View %{name}" msgstr "Obejrzyj jednostkÄ™ (%{name})" msgid "Move the %{name} " msgstr "PrzenieÅ› %{name} " msgid "Move or right click to redistribute %{name}" msgstr "PrzenieÅ› lub kliknij prawym aby rozdzielić %{name}" msgid "Combine %{name} armies" msgstr "Połącz jednostki (%{name})" msgid "Exchange %{name2} with %{name}" msgstr "ZamieÅ„ pozycje jednostek: %{name2} i %{name}" msgid "Select %{name}" msgstr "Wybierz (%{name})" msgid "Cannot move last troop" msgstr "Nie można przenieść ostatniej jednostki" msgid "Move the %{name}" msgstr "PrzenieÅ› %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Strzelaj do %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} niszczy poÅ‚owÄ™ stworów wroga!" msgstr[1] "%{name} niszczÄ… poÅ‚owÄ™ stworów wroga!" msgstr[2] "%{name} niszczy poÅ‚owÄ™ stworów wroga!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} wyłączyÅ‚ automatycznÄ… walkÄ™" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} włączyÅ‚ automatycznÄ… walkÄ™" msgid "Spell failed!" msgstr "Czar nieudany!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "W czasie bitwy dziaÅ‚a artefakt o nazwie Kula Negacji, uniemożliwiajÄ…cy " "rzucenie wszelkich zaklęć bojowych." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "W tej rundzie zaklÄ™cie zostaÅ‚o już rzucone." msgid "That spell will have no effect!" msgstr "To zaklÄ™cie nie da żadnego efektu!" msgid "You may only summon one type of elemental per combat." msgstr "W czasie walki możesz przywoÅ‚ać tylko jeden rodzaj żywioÅ‚aka." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Obok twojego bohatera nie ma wolnego miejsca gdzie można by przywoÅ‚ać " "Å»ywioÅ‚aki." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Fosa zmniejsza współczynnik obrony o -%{count} oraz spowalnia jednostki o " "poÅ‚owÄ™." msgid "Speed: %{speed}" msgstr "Szybkość: %{speed}" msgid "Speed" msgstr "Szybkość" msgid "Off" msgstr "Wyłączone" msgid "On" msgstr "Włączone" #, fuzzy msgid "Turn Order" msgstr "Kolejność jednostek" msgid "Auto Spell Casting" msgstr "Auto. czary" msgid "Grid" msgstr "Siatka" msgid "Shadow Movement" msgstr "Cieniowanie pola" msgid "Shadow Cursor" msgstr "Cieniowanie kursora" msgid "Audio" msgstr "DźwiÄ™k" msgid "Settings" msgstr "Ustawienia" msgid "Configure" msgstr "Dostosuj" msgid "Hot Keys" msgstr "Skróty klaw." msgid "Damage Info" msgstr "Obrażenia" msgid "Set the speed of combat actions and animations." msgstr "Pozwala na ustawienie szybkoÅ›ci akcji i animacji w walce." #, fuzzy msgid "Toggle to display the turn order during the battle." msgstr "" "Ukrycie lub pokazanie kolejnoÅ›ci wykonywania akcji przez stwory w czasie " "walki." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Włączenie tej opcji sprawi, że komputer bÄ™dzie rzucaÅ‚ zaklÄ™cia w trybie " "walki automatycznej. (Uwaga: nie ma to wpÅ‚ywu na rzucanie zaklęć przez " "graczy komputerowych oraz na szybkÄ… walkÄ™.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Włączenie/wyłączenie siatki pól. Na siatce zawsze widoczna jest trasa ruchu " "jednostki." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Włączenie/wyłączenie cieniowania pól, na które może siÄ™ ruszyć twoja " "jednostka." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Włączenie/wyłączenie systemu cieniowania zaznaczajÄ…cego pola, nad którymi " "znajduje siÄ™ kursor." msgid "Change the audio settings of the game." msgstr "ZmieÅ„ ustawienia dźwiÄ™kowe gry." msgid "Check and configure all the hot keys present in the game." msgstr "Zobacz i skonfiguruj wszystkie skróty klawiszowe gry." msgid "Toggle to display damage information during the battle." msgstr "Włączenie/wyłączenie informacji o zadanych obrażeniach." msgid "Exit this menu." msgstr "Wyjdź z tego menu." msgid "Okay" msgstr "Ok" msgid "The enemy has surrendered!" msgstr "Przeciwnik siÄ™ poddaÅ‚!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Przeciwnik uciekÅ‚!" msgid "A glorious victory!" msgstr "WspaniaÅ‚e zwyciÄ™stwo!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Za odwagÄ™ w walce, %{name} otrzymuje %{exp} pkt. doÅ›wiadczenia." msgid "The cowardly %{name} flees from battle." msgstr "%{name} tchórzliwie ucieka z pola bitwy." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} poddaje siÄ™ wrogowi i odchodzi w haÅ„bie." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Twoje wojska ponoszÄ… dotkliwÄ… klÄ™skÄ™, a %{name} opuszcza ciÄ™." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Twoje wojska ponoszÄ… dotkliwÄ… klÄ™skÄ™." msgid "Battlefield Casualties" msgstr "Ofiary walki" msgid "Attacker" msgstr "AtakujÄ…cy" msgid "Defender" msgstr "ObroÅ„ca" #, fuzzy msgid "Click to leave the battle results." msgstr "Użyj wskazanej rozdzielczoÅ›ci." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Kliknij, aby wrócić do głównego menu." msgid "Restart" msgstr "Rozpocznij od nowa" msgid "You have captured an enemy artifact!" msgstr "UdaÅ‚o ci siÄ™ zdobyć artefakt przeciwnika!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Gdy siÄ™gasz po artefakt %{name}, przedmiot w tajemniczy sposób znika." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" "Gdy przeciwnik siÄ™ga po artefakt %{name}, przedmiot w tajemniczy sposób " "znika." msgid "Necromancy!" msgstr "Nekromancja!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "KorzystajÄ…c z mrocznej sztuki nekromancji, ożywiasz %{count} martwych " "przeciwników i wcielasz ich do swojej armii jako %{monster}." msgid "%{name} the %{race}" msgstr "%{name}, %{race}" msgid "Captain of %{name}" msgstr "Kapitan, %{name}" msgid "Attack" msgstr "Atak" msgid "Defense" msgstr "Obrona" msgid "Spell Power" msgstr "Moc zaklęć" msgid "Knowledge" msgstr "Wiedza" msgid "Morale" msgstr "Morale" msgid "Luck" msgstr "Szczęście" msgid "Spell Points" msgstr "Pkt. magii" msgid "Hero's Options" msgstr "Opcje bohatera" msgid "Cast Spell" msgstr "Rzuć zaklÄ™cie" msgid "Retreat" msgstr "Ucieczka" msgid "Surrender" msgstr "Kapitulacja" msgid "Cancel" msgstr "Anuluj" msgid "Hero Screen" msgstr "Ekran bohatera" msgid "Captain's Options" msgstr "Opcje kapitana" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Rzucanie magicznego zaklÄ™cia. Możesz rzucić tylko jedno zaklÄ™cie na rundÄ™ " "walki. Runda koÅ„czy siÄ™ gdy wszystkie stworzenia wykonajÄ… ruch." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Ucieczka bohatera i porzucenie wojsk. Bohatera bÄ™dzie można nająć ponownie, " "ale bÄ™dzie posiadać jedynie poczÄ…tkowe oddziaÅ‚y." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Za możliwość kapitulacji pÅ‚aci siÄ™ w zÅ‚ocie. JeÅ›li jednak zapÅ‚acisz okup, " "bÄ™dzie można nająć ponownie zarówno bohatera jak i ocalaÅ‚e jednostki." msgid "Open Hero Screen to view full information about the hero." msgstr "Otwórz ekran bohatera, aby zobaczyć peÅ‚ne informacje o nim." msgid "Return to the battle." msgstr "Powrót na pole bitwy." msgid "Not enough gold (%{gold})" msgstr "Brakuje zÅ‚ota (%{gold})" msgid "%{name} states:" msgstr "%{name} oznajmia:" msgid "Captain of %{name} states:" msgstr "Kapitan %{name} oznajmia:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "PrzyjmÄ™ twÄ… kapitulacjÄ™ i pozwolÄ™ ci odejść wraz z twÄ… armiÄ… za cenÄ™ " "%{price} szt. zÅ‚ota." msgid "View %{monster} info" msgstr "Informacje o jednostce: %{monster}" msgid "Fly %{monster} here" msgstr "PrzefruÅ„ jednostkÄ… (%{monster}) tutaj" msgid "Move %{monster} here" msgstr "Przemieść jednostkÄ™ (%{monster}) tutaj" msgid "Shoot %{monster}" msgstr "Strzelaj do %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(pozostaÅ‚ %{count} strzaÅ‚)" msgstr[1] "(pozostaÅ‚y %{count} strzaÅ‚y)" msgstr[2] "(pozostaÅ‚o %{count} strzałów)" msgid "Attack %{monster}" msgstr "Zaatakuj jednostkÄ™ (%{monster})" msgid "Turn %{turn}" msgstr "Tura %{turn}" msgid "Teleport here" msgstr "Teleportuj w to miejsce" msgid "Invalid teleport destination" msgstr "Teleportacja w to miejsce jest niemożliwa" msgid "Cast %{spell} on %{monster}" msgstr "Rzuć zaklÄ™cie: %{spell} na: %{monster}" msgid "Cast %{spell}" msgstr "Rzuć zaklÄ™cie: %{spell}" msgid "Select spell target" msgstr "Wybierz cel zaklÄ™cia" msgid "View Ballista info" msgstr "Informacje o baliÅ›cie" msgid "Ballista" msgstr "Balista" #, fuzzy msgid "Automatic combat modes" msgstr "Automatyczna Walka" #, fuzzy msgid "Automatic Combat Modes" msgstr "Automatyczna Walka" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Dostosuj ustawienia systemowe" msgid "Allows you to customize the combat screen." msgstr "Pozwala na zmianÄ™ wyglÄ…du ekranu walki." msgid "System Options" msgstr "Opcje systemowe" msgid "Skip this unit" msgstr "PomiÅ„ tÄ™ jednostkÄ™" msgid "Skip" msgstr "PomiÅ„" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Powoduje pominiÄ™cie aktualnej jednostki. Traci ona swojÄ… turÄ™ i może ruszyć " "siÄ™ ponownie dopiero w nastÄ™pnej rundzie." msgid "View Captain's options" msgstr "Opcje kapitana" msgid "View Hero's options" msgstr "Opcje bohatera" msgid "View opposing Captain" msgstr "Obejrzyj wrogiego kapitana" msgid "View opposing Hero" msgstr "Obejrzyj wrogiego bohatera" msgid "Hide logs" msgstr "Ukryj logi" msgid "Show logs" msgstr "Pokaż logi" msgid "Message Bar" msgstr "Pasek WiadomoÅ›ci" msgid "Shows the results of individual monster's actions." msgstr "Pokazuje rezultat akcji wykonanych przez indywidualnÄ… jednostkÄ™." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Czy na pewno chcesz włączyć automatycznÄ… walkÄ™?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Czy na pewno chcesz dokoÅ„czyć walkÄ™ w trybie automatycznym?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Pozwala komputerowi rozegrać walkÄ™ za ciebie." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Automatyczna Walka" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Automatyczna Walka" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} pomija turÄ™." msgstr[1] "%{name} pomija turÄ™." msgstr[2] "%{name} pomija turÄ™." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "Stworzenie %{attacker} zadaje %{damage} pkt. obrażeÅ„." msgstr[1] "Stworzenia %{attacker} zadajÄ… %{damage} pkt. obrażeÅ„." msgstr[2] "Stworzenia %{attacker} zadajÄ… %{damage} pkt. obrażeÅ„." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 stworzenie ginie." msgstr[1] "%{count} stworzenia ginÄ…." msgstr[2] "%{count} stworzeÅ„ ginie." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} ginie." msgstr[1] "%{count} %{defender} ginie." msgstr[2] "%{count} %{defender} ginie." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "%{count} dusza wchÅ‚oniÄ™ta." msgstr[1] "%{count} dusze wchÅ‚oniÄ™te." msgstr[2] "%{count} dusz wchÅ‚oniÄ™tych." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "%{count} %{unit} zmartwychwstaÅ‚(a)." msgstr[1] "%{count} %{unit} zmartwychwstaÅ‚o(y)." msgstr[2] "%{count} %{unit} zmartwychwstaÅ‚o(y)." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Przeniesiono %{monster} z: [%{src}] do [%{dst}]." #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} odpierajÄ… zaklÄ™cie!" msgstr[1] "%{name} odpierajÄ… zaklÄ™cie!" msgstr[2] "%{name} odpierajÄ… zaklÄ™cie!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} rzuca zaklÄ™cie '%{spell}' na: %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} rzuca zaklÄ™cie '%{spell}'." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "Czar %{spell} zadaje %{damage} pkt. obrażeÅ„ nieumarÅ‚ej istocie." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "Czar %{spell} zadaje %{damage} pkt. obrażeÅ„ każdej nieumarÅ‚ej istocie." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "Czar %{spell} zadaje %{damage} pkt. obrażeÅ„, %{count} stworzeÅ„ ginie." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} zadaje %{damage} pkt. obrażeÅ„." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} zadaje %{damage} pkt. obrażeÅ„ żywej istocie." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} zadaje %{damage} pkt. obrażeÅ„ każdej żywej istocie." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Atak %{attacker} oÅ›lepia %{target}!" msgstr[1] "Atak %{attacker} oÅ›lepia %{target}!" msgstr[2] "Atak %{attacker} oÅ›lepia %{target}!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "Spojrzenie %{attacker} zamienia %{target} w kamieÅ„!" msgstr[1] "Spojrzenie %{attacker} zamienia %{target} w kamieÅ„!" msgstr[2] "Spojrzenie %{attacker} zamienia %{target} w kamieÅ„!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "%{attacker} przeklina %{target}!" msgstr[1] "%{attacker} przeklina %{target}!" msgstr[2] "%{attacker} przeklina %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{target} zostaÅ‚ sparaliżowany przez %{attacker}!" msgstr[1] "%{target} zostaÅ‚ sparaliżowany przez %{attacker}!" msgstr[2] "%{target} zostaÅ‚ sparaliżowany przez %{attacker}!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "%{attacker} rozpraszajÄ… pozytywne zaklÄ™cia u %{target}!" msgstr[1] "%{attacker} rozpraszajÄ… pozytywne zaklÄ™cia u %{target}!" msgstr[2] "%{attacker} rozpraszajÄ… pozytywne zaklÄ™cia u %{target}!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} rzuca zaklÄ™cie %{spell} na %{target}!" msgstr[1] "%{attacker} rzuca zaklÄ™cie %{spell} na %{target}!" msgstr[2] "%{attacker} rzuca zaklÄ™cie %{spell} na %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Tej jednostce (%{attacker}) nie sprzyja los." msgid "Good luck shines on the %{attacker}." msgstr "Tej jednostce (%{attacker}) sprzyja szczęście." msgid "High morale enables the %{monster} to attack again." msgstr "Wysokie morale pozwala jednostce (%{monster}) na dodatkowy atak." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Niskie morale sprawia, że jednostka (%{monster}) zamiera w panice." msgid "%{tower} does %{damage} damage." msgstr "%{tower} zadaje %{damage} pkt. obrażeÅ„." msgid "The mirror image is created." msgstr "Stworzono lustrzane odbicie." msgid "The mirror image is destroyed!" msgstr "Zniszczono lustrzane odbicie!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Czy na pewno chcesz przerwać tryb automatyczny?" msgid "Error" msgstr "Błąd" msgid "No spells to cast." msgstr "Brak zaklęć." msgid "Are you sure you want to retreat?" msgstr "Czy na pewno chcesz siÄ™ wycofać?" msgid "Retreat disabled" msgstr "Ucieczka niemożliwa" msgid "Surrender disabled" msgstr "Kapitulacja niemożliwa" msgid "Damage: %{max}" msgstr "Obrażenia: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Obrażenia: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Zabici: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Zabici: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "DziÄ™ki swemu sokolemu wzrokowi, %{name} nauczyÅ‚ siÄ™ zaklÄ™cia '%{spell}'." msgid "Human" msgstr "CzÅ‚owiek" msgid "AI" msgstr "Komputer" #, fuzzy msgid "Start" msgstr "Rozpocznij od nowa" #, fuzzy msgid "Start the battle." msgstr "Powrót na pole bitwy." msgid "Exit" msgstr "WyjÅ›cie" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Wybierz innego bohatera." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "Spotkanie: %{name1} i %{name2}" msgid "Monsters" msgstr "Potwory" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Lewa wieżyczka" msgid "Right Turret" msgstr "Prawa wieżyczka" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} strzela z siłą %{count} Åuczników" msgid "each with a +%{attack} bonus to their attack skill." msgstr "z których każdy ma +%{attack} premii do siÅ‚y ataku." msgid "The %{name} is destroyed." msgstr "%{name} zostaÅ‚a zniszczona." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} powstaje z martwych!" msgstr[1] "%{count} %{name} powstaje z martwych!" msgstr[2] "%{count} %{name} powstaje z martwych!" msgid "Dwarven Alliance" msgstr "Przymierze Krasnolud." msgid "Sorceress Guild" msgstr "Gildia Czarodziejek" msgid "Necromancer Guild" msgstr "Gildia Nekromantów" msgid "Ogre Alliance" msgstr "Przymierze Ogrów" msgid "Dwarfbane" msgstr "Pogromca Krasnolud." msgid "Dragon Alliance" msgstr "Przymierze Smoków" msgid "Elven Alliance" msgstr "Przymierze Elfów" msgid "Kraeger defeated" msgstr "Kraeger pokonany" msgid "Wayward Son" msgstr "KrnÄ…brny Syn" msgid "Uncle Ivan" msgstr "Wuj Ivan" msgid "Annexation" msgstr "Aneksja" msgid "Force of Arms" msgstr "SiÅ‚a oręża" msgid "Save the Dwarves" msgstr "Uratuj Krasnoludy" msgid "Carator Mines" msgstr "Kopalnie Caratora" msgid "Turning Point" msgstr "Punkt Zwrotny" msgid "scenarioName|Defender" msgstr "ObroÅ„ca" msgid "Corlagon's Defense" msgstr "Obrona Corlagona" msgid "The Crown" msgstr "Korona" msgid "The Gauntlet" msgstr "RÄ™kawica" msgid "Betrayal" msgstr "Zdrada" msgid "Final Justice" msgstr "Ostateczna Sprawiedliwość" #, fuzzy msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Aby zacząć powstanie, Roland potrzebuje pomocy w pokonaniu lordów w pobliżu " "jego zamku. Lordowie ci nie sÄ… sprzymierzeni, wiÄ™c wiÄ™kszość czasu spÄ™dzÄ… na " "potyczkach miÄ™dzy sobÄ…. Zwyciężysz, gdy pokonasz wszystkich wrogich " "bohaterów oraz zdobÄ™dziesz ich zamki." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Miejscowi wÅ‚adcy odmawiajÄ… zÅ‚ożenia przysiÄ™gi lojalnoÅ›ci Rolandowi i muszÄ… " "zostać ujarzmieni. SÄ… potężni i bogaci, wiÄ™c przygotuj siÄ™ na ciężkÄ… walkÄ™. " "Aby wygrać, zdobÄ…dź wszystkie wrogie zamki." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Twoim zadaniem jest obrona Krasnoludów przed siÅ‚ami Archibalda. Aby " "zwyciężyć, zdobÄ…dź wszystkie zamki i miasta wroga oraz nie pozwól na utratÄ™ " "wszystkich osad krasnoludów, albo przeciwnik wygra." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Staniesz do walki o skarby i surowce z czterema sprzymierzonymi " "przeciwnikami. Aby zwyciężyć, zdobÄ…dź wszystkie wrogie miasta." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Twoi wrogowie sprzymierzyli siÄ™ przeciw tobie i zaczynajÄ… blisko twego " "zamku, wiÄ™c przygotuj siÄ™ na ostrÄ… walkÄ™. Aby zwyciężyć, trzeba bÄ™dzie " "zdobyć wszystkie cztery zamki w tej maÅ‚ej dolinie." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Gildia Czarodziejek z Norastonu poprosiÅ‚a o pomoc Rolanda w walce z " "sojusznikami Archibalda. ZdobÄ…dź wszystkie wrogie zamki i nie strać " "Norastonu, albo przegrasz. (Wskazówka: jeden z zamków wroga znajduje siÄ™ na " "wyspie wÅ›ród oceanu.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Zbierz armiÄ™ i w ciÄ…gu 8 tygodni zdobÄ…dź zamek wroga. Walczysz tylko z " "jednym przeciwnikiem, ale musisz pokonać dÅ‚ugÄ… drogÄ™, by dostać siÄ™ do jego " "zamku. Jednostki, które bÄ™dÄ… znajdować siÄ™ w twojej armii pod koniec " "scenariusza, bÄ™dÄ… walczyć w koÅ„cowej bitwie." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Znajdź koronÄ™ zanim zrobiÄ… to bohaterowie Archibalda. Roland bÄ™dzie " "potrzebowaÅ‚ jej w koÅ„cowej bitwie." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Na twej drodze do zwyciÄ™stwa stoi 3 sprzymierzonych wrogów, włączajÄ…c w to " "Lorda Carlagona. Roland jest w swoim zamku na pn/zach. i przegrasz, jeÅ›li " "zostanie pokonany. PamiÄ™taj, że schwytanie Lorda Carlagona sprawi, iż nie " "bÄ™dzie walczyÅ‚ w ostatnim scenariuszu." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "To ostatnia bitwa. Obie strony sÄ… uzbrojone po zÄ™by, a wszyscy sprzymierzyli " "siÄ™ przeciw tobie. Pokonaj Archibalda i zakoÅ„cz wojnÄ™!" #, fuzzy msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Po zmianie stron bÄ™dziesz mieć trzy zamki, a przeciwnik tylko jeden. To " "bÄ™dzie najÅ‚atwiejsza z czekajÄ…cych ciÄ™ bitew... zdrajco." msgid "Barbarian Wars" msgstr "Wojny BarbarzyÅ„ców" msgid "First Blood" msgstr "Pierwsza krew" msgid "Necromancers" msgstr "Nekromanci" msgid "Slay the Dwarves" msgstr "Zniszcz Krasnoludy" msgid "Country Lords" msgstr "Kraina WÅ‚adców" msgid "Dragon Master" msgstr "WÅ‚adca Smoków" msgid "Rebellion" msgstr "Bunt" msgid "Apocalypse" msgstr "Apokalipsa" msgid "Greater Glory" msgstr "WiÄ™ksza ChwaÅ‚a" #, fuzzy msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Król Archibald życzy sobie, abyÅ› pokonaÅ‚ jego trzech wrogów w tym rejonie. " "Nie sÄ… sprzymierzeni, wiÄ™c wiÄ™kszość czasu spÄ™dzÄ… na potyczkach miÄ™dzy sobÄ…. " "Wygrasz, jeÅ›li zdobÄ™dziesz wszystkie zamki i pokonasz wszystkich bohaterów " "przeciwników." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Musisz zjednoczyć plemiona barbarzyÅ„ców na północy, podbijajÄ…c je. Podobnie " "jak w poprzednich misjach, wrogowie nie sprzymierzyli siÄ™ przeciw tobie, ale " "majÄ… wiÄ™cej surowców do dyspozycji. Wygrasz jeÅ›li podbijesz wszystkie wrogie " "zamki i pokonasz wszystkich bohaterów." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Czarodzieje zajÄ™li zamek nekromantów. Musisz go odbić, aby zwyciężyć. " "PamiÄ™taj, że choć zaczynasz z potężnÄ… armiÄ…, nie masz wÅ‚asnego zamku i " "musisz jakiÅ› zdobyć w ciÄ…gu 7 dni, albo przegrasz. (Wskazówka: najbliższy " "zamek jest na poÅ‚udniowym wschodzie)." msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Należy podbić krasnoludy, zanim zdoÅ‚ajÄ… przeszkodzić w wykonaniu planów " "króla Archibalda. SiÅ‚y Rolanda posiadajÄ… od poczÄ…tku wiele miast i paru " "bohaterów, wiÄ™c przygotuj siÄ™ na ataki z kilku stron. Aby zwyciężyć, musisz " "zdobyć wszystkie wrogie miasta i zamki." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Musisz zdÅ‚awić bunt chÅ‚opów podżegany przez siÅ‚y Rolanda. Wszyscy " "sprzymierzyli siÄ™ przeciw tobie, ale pomaga ci Lord Corlagon - doÅ›wiadczony " "bohater. Aby wygrać, zdobÄ…dź wszystkie wrogie zamki." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "W tej misji czeka na ciebie dwóch sprzymierzonych przeciwników. Obaj majÄ… " "spore siÅ‚y i chcÄ… usunąć ciÄ™ z ich wyspy. Postaraj siÄ™ ich uniknąć i zdobÄ…dź " "Smocze Miasto, aby wygrać." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Masz rozkaz pokonać paru zaÅ›ciankowych lordów, którzy przysiÄ™gli sÅ‚użyć " "Rolandowi. Wszyscy przeciwnicy zjednoczyli siÄ™ przeciw tobie. Ponieważ " "zaczynasz bez zamku, musisz siÄ™ pospieszyć i opanować jakiÅ› przed koÅ„cem " "tygodnia. Aby wygrać, zdobÄ…dź wszystkie wrogie zamki." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Znajdź koronÄ™ zanim zrobiÄ… to bohaterowie Rolanda. Archibald bÄ™dzie " "potrzebowaÅ‚ jej w koÅ„cowej bitwie." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "To ostatnia bitwa. Obie strony sÄ… uzbrojone po zÄ™by, a wszyscy sprzymierzyli " "siÄ™ przeciw tobie. Schwytaj Rolanda i zakoÅ„cz wojnÄ™, ale dopilnuj tego, aby " "w walce nie stracić Archibalda!" msgid "Arrow's Flight" msgstr "Lot StrzaÅ‚y" msgid "Island of Chaos" msgstr "Wyspa Chaosu" msgid "The Abyss" msgstr "OtchÅ‚aÅ„" msgid "Uprising" msgstr "Powstanie" msgid "Aurora Borealis" msgstr "Zorza Polarna" msgid "Betrayal's End" msgstr "Kres Zdrady" msgid "Corruption's Heart" msgstr "Serce Zepsucia" msgid "The Giant's Pass" msgstr "Przełęcz Olbrzyma" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Podbij nieposÅ‚usznych lordów, aby zapewnić Imperium możliwość prowadzenia " "operacji w tym regionie." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "PozbÄ…dź siÄ™ wszystkich przeciwników na tym terenie, a pierwsza część " "artefaktu bÄ™dzie twoja." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Czarodziejki z północnego wschodu zaczęły siÄ™ buntować! Dla dobra Imperium, " "podczas podróży w góry, musisz zdÅ‚awić ich żaÅ‚osne powstanie." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Przygotowawszy siÄ™ na twe przybycie, Kraeger wspomógÅ‚ siÄ™ siÅ‚ami " "nekromantów. Nim nadejdzie pierwszy dzieÅ„ trzeciego tygodnia musisz zdobyć " "zamek Scabsdale, albo nekromanci bÄ™dÄ… zbyt silni dla ciebie." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "BarbarzyÅ„ski wÅ‚adca tego terytorium nie wie na razie o twej obecnoÅ›ci. Zanim " "ciÄ™ odkryje i zaatakuje, szybko wzmocnij swojÄ… armiÄ™! Zajmij region i " "pokonaj wszystkie siÅ‚y wroga." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "W tym regionie wpÅ‚ywy Imperium sÄ… sÅ‚abe. Nie uda ci siÄ™ caÅ‚kowicie podbić " "tego obszaru, wiÄ™c zdobÄ…dź ile możesz zanim nadejdzie odwet. PamiÄ™taj, że " "twoim prawdziwym celem jest zdobycie HeÅ‚mu Andurana." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Dla dobra Imperium pozbÄ…dź siÄ™ Kraegera." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Nareszcie masz okazjÄ™ i Å›rodki, by oczyÅ›cić Imperium z plugastwa " "nekromantów. Zniszcz ich caÅ‚kowicie, a o twym bohaterstwie bÄ™dzie siÄ™ " "Å›piewać przez wieki." msgid "Border Towns" msgstr "Miasta Graniczne" msgid "Conquer and Unify" msgstr "Zjednoczenie" msgid "Crazy Uncle Ivan" msgstr "Szalony Wuj Ivan" msgid "The Wayward Son" msgstr "KrnÄ…brny Syn" msgid "Ivory Gates" msgstr "Ivory Gates" msgid "The Elven Lands" msgstr "Krainy Elfów" msgid "The Epic Battle" msgstr "Epicka Bitwa" msgid "The Southern War" msgstr "Wojna na PoÅ‚udniu" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Podbij i zjednocz wszystkie wrogie plemiona. Nie wolno ci utracić Jarkonasa " "- przodka caÅ‚ej rodziny." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "RywalizujÄ…ce królestwo Harondale atakuje sÅ‚abe miasta przy twojej granicy! " "Wytrzymaj pierwsze uderzenie i caÅ‚kowicie zmiażdż wroga!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Znajdź swojego krnÄ…brnego syna, Josepha, który podobno żyje gdzieÅ› na " "pustkowiu. Dokonaj tego zanim nastanie pierwszy dzieÅ„ trzeciego miesiÄ…ca, " "albo twojej rodzinie już nic nie pomoże." #, fuzzy msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Uratuj swojego szalonego wuja Ivana. Znajdź go nim nadejdzie pierwszy dzieÅ„ " "czwartego miesiÄ…ca, albo nic nie pomoże już twemu królestwu." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Zniszcz barbarzyÅ„ców, którzy atakujÄ… poÅ‚udniowÄ… granicÄ™ naszego paÅ„stwa! " "Odbij stracone miasta, a nastÄ™pnie uderz na poÅ‚ożone w dżungli królestwo. " "Pokonaj wszystkich wrogów." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Odbij zamek Ivory Gates, który padÅ‚ z powodu zdrady." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Zyskaj przychylność elfów. Nie pozwalajÄ… one na Å›cinanie drzew, wiÄ™c co dwa " "tygodnie przysyÅ‚ać bÄ™dziemy drewno. Musisz wykonać swÄ… misjÄ™ przed pierwszym " "dniem siódmego miesiÄ…ca, albo nasze królestwo upadnie." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "To ostateczna bitwa przeciw wrogiemu królestwu Harondale. Pokonaj wszystkich " "i nie strać Jarkonasa VI." msgid "Fount of Wizardry" msgstr "ŹródÅ‚o Magii" msgid "Power's End" msgstr "Koniec PotÄ™gi" msgid "The Eternal Scrolls" msgstr "Wieczne Zwoje" msgid "The Shrouded Isles" msgstr "Zamglone Wyspy" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Twoja misja polega na pokonaniu walczÄ…cych magów na Zamglonych Wyspach. " "Wykonanie tego zadania da ci szansÄ™ w walce przeciw twoim rywalom." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "UdaÅ‚o siÄ™ odkryć miejsce poÅ‚ożenia biblioteki! Musisz do niej wyruszyć i " "zająć miasto Chronos, w którym siÄ™ znajduje." #, fuzzy msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Znajdź KulÄ™ Negacji, która podobno jest zakopana gdzieÅ› w tej krainie. Na " "kamiennych obeliskach znajdujÄ… siÄ™ wskazówki, które ciÄ™ do niej doprowadzÄ…. " "Znajdź KulÄ™ nim nastanie pierwszy dzieÅ„ szóstego miesiÄ…ca, albo twoi rywale " "zdobÄ™dÄ… jÄ… przed tobÄ…." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Musisz zająć zaklÄ™ty zamek, gdzie znajduje siÄ™ źródÅ‚o magii. Dokonaj tego, a " "odniesiesz wspaniaÅ‚e zwyciÄ™stwo." msgid "Blood is Thicker" msgstr "WiÄ™zy Krwi" msgid "King and Country" msgstr "Król i Kraj" msgid "Pirate Isles" msgstr "Wyspy Piratów" msgid "Stranded" msgstr "Rozbitek" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "ZdobÄ…dź miasto na wyspie, przy poÅ‚udniowo-wschodnim wybrzeżu, aby zbudować " "łódź mogÄ…cÄ… dopÅ‚ynąć z tobÄ… na kontynent. Nie wolno ci stracić bohatera o " "imieniu Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Znajdź i pokonaj Martina, przywódcÄ™ piratów, który przebywa w Zatoce " "Piratów. Nie wolno ci stracić Gallavanta, albo twoja przygoda siÄ™ skoÅ„czy." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Pokonaj wszystkie siÅ‚y sprzeciwiajÄ…ce siÄ™ rzÄ…dom Lorda Alberona. Gallavant " "nie może zginąć." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Obal monarchiÄ™ Lorda Alberona i zajmij caÅ‚y kraj w swoim imieniu. Gallavant " "nie może zginąć." msgid " bane" msgstr " pogromca" msgid " alliance" msgstr " sojusz" msgid "Carry-over forces" msgstr "Przeniesione siÅ‚y" msgid " bonus" msgstr " bonus" msgid " defeated" msgstr " pokonany" msgid " will always run away from your army." msgstr " zawsze ucieknie przed twojÄ… armiÄ…." msgid " will be willing to join your army." msgstr " zawsze dołączy do twojej armii." #, fuzzy msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" "Artefact \"%{artifact}\" zostanie przeniesiony do nastÄ™pnego scenariusza." #, fuzzy msgid "The army will be carried over in the campaign." msgstr "Armia zostanie przeniesiona do nastÄ™pnego scenariusza." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Królestwo otrzyma +%{count} %{resource} każdego dnia." #, fuzzy msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "ZaklÄ™cie \"%{spell}\" zostanie przeniesione do nastÄ™pnego scenariusza." #, fuzzy msgid "%{hero} can be hired during scenarios." msgstr "Bohater %{hero} może być zwerbowany w tym scenariuszu." #, fuzzy msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" "Pokonany bohater %{hero} nie bÄ™dzie dostÄ™pny w kolejnych scenariuszach." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Krasnoludy rozpoznajÄ… w tobie sojusznika i chÄ™tnie przyłączajÄ… siÄ™ do ciebie." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Ogry rozpoznajÄ… ciÄ™ jako PogromcÄ™ Krasnoludów i powoli zmierzajÄ… ku tobie, " "aby wesprzeć twoje siÅ‚y." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "WarczÄ…ce i burczÄ…ce smoki przystajÄ… na dołączenie do twojej armii." #, fuzzy msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Kiedy zbliżasz siÄ™ do grupy elfów, jej przywódca zwoÅ‚uje wszystkich i " "wykrzykuje, \"Kto jest na tyle odważny by dołączyć do naszego " "nieustraszonego sprzymierzeÅ„ca?\" CzÅ‚onkowie grupy wiwatujÄ… i biegnÄ… do " "ciebie by dołączyć do twoich szeregów." #, fuzzy msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "WitajÄ… ciÄ™ krasnoludy, \"Przyjaciel Rolanda jest naszym przyjacielem. Możesz " "przejść.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Ogry chrzÄ…kajÄ… na znak uznania, \"SprzymierzeÅ„cy Archibalda mogÄ… przejść.\"" #, fuzzy msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Smoki widzÄ… ciÄ™ i wykrzykujÄ…. \"Nasze przymierze z Archibaldem nakazuje nam " "przyłączyć siÄ™ do ciebie. Jednakże nie ma miejsca w twoich szeregach, co za " "szkoda!\". Smoki momentalnie siÄ™ rozpraszajÄ…." #, fuzzy msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Elfy stajÄ… na baczność, gdy siÄ™ zbliżasz. Ich przywódca woÅ‚a ciÄ™ i mówi, " "\"Nie bÄ™dziemy wchodzić ci w drogÄ™ towarzyszu! Ruszaj dalej i niech " "zwyciÄ™stwo bÄ™dzie twoje.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Pogromca Krasnoludów, ratuj siÄ™ kto może!!!\"" msgid "campaignBonus|Animate Dead" msgstr "Ożywienie Martwych" msgid "campaignBonus|Chain Lightning" msgstr "ÅaÅ„cuch Piorunów" msgid "campaignBonus|Fireblast" msgstr "Eksplozja Ognia" msgid "campaignBonus|Mass Curse" msgstr "Grupowa KlÄ…twa" msgid "campaignBonus|Mass Haste" msgstr "Grupowe Przyspieszenie" msgid "campaignBonus|Mirror Image" msgstr "Lustrzane Odbicie" msgid "campaignBonus|Resurrect" msgstr "Ożywienie" msgid "campaignBonus|Steelskin" msgstr "Stalowa Skóra" msgid "campaignBonus|Summon Earth" msgstr "Przyw. Ziemi" msgid "campaignBonus|View Heroes" msgstr "Pokaż Bohaterów" msgid "campaignBonus|Ballista" msgstr "Balista" msgid "campaignBonus|Black Pearl" msgstr "Czarna PerÅ‚a" msgid "campaignBonus|Caster's Bracelet" msgstr "Magiczna Bransol" msgid "campaignBonus|Defender Helm" msgstr "HeÅ‚m ObroÅ„cy" msgid "campaignBonus|Breastplate" msgstr "NapierÅ›nik" msgid "campaignBonus|Dragon Sword" msgstr "Smoczy Miecz" msgid "campaignBonus|Fizbin Medal" msgstr "Fizbin" msgid "campaignBonus|Foremost Scroll" msgstr "DoskonaÅ‚y Zwój" msgid "campaignBonus|Gauntlets" msgstr "RÄ™kawice" msgid "campaignBonus|Hideous Mask" msgstr "Potworna Maska" msgid "campaignBonus|Mage's Ring" msgstr "PierÅ›cieÅ„ Maga" msgid "campaignBonus|Major Scroll" msgstr "WiÄ™kszy Zwój" msgid "campaignBonus|Medal of Honor" msgstr "Medal Honoru" msgid "campaignBonus|Medal of Valor" msgstr "Medal MÄ™stwa" msgid "campaignBonus|Minor Scroll" msgstr "Pomniejszy Zwój" msgid "campaignBonus|Nomad Boots" msgstr "Buty Nomady" msgid "campaignBonus|Power Axe" msgstr "Potężny Topór" msgid "campaignBonus|Spiked Shield" msgstr "Rogata Tarcza" msgid "campaignBonus|Stealth Shield" msgstr "Maskuj. Tarcza" msgid "campaignBonus|Tax Lien" msgstr "Weksel Fiskalny" msgid "campaignBonus|Thunder Mace" msgstr "Grzm. KiÅ›cieÅ„" msgid "campaignBonus|Traveler's Boots" msgstr "Buty Podróżnika" msgid "campaignBonus|White Pearl" msgstr "BiaÅ‚a PerÅ‚a" msgid "campaignBonus|Basic Archery" msgstr "Podst. Å‚ucznictwo" msgid "campaignBonus|Advanced Archery" msgstr "Zaawan. Å‚ucznictwo" msgid "campaignBonus|Expert Archery" msgstr "Mistrz. Å‚ucznictwo" msgid "campaignBonus|Basic Ballistics" msgstr "Podst. balistyka" msgid "campaignBonus|Advanced Ballistics" msgstr "Zaawan. balistyka" msgid "campaignBonus|Expert Ballistics" msgstr "Mistrz. balistyka" msgid "campaignBonus|Basic Diplomacy" msgstr "Podst. dyplomacja" msgid "campaignBonus|Advanced Diplomacy" msgstr "Zaawan. dyplomacja" msgid "campaignBonus|Expert Diplomacy" msgstr "Mistrz. dyplomacja" msgid "campaignBonus|Basic Eagle Eye" msgstr "Podst. sokole oko" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Zaawan. sokole oko" msgid "campaignBonus|Expert Eagle Eye" msgstr "Mistrz. sokole oko" msgid "campaignBonus|Basic Estates" msgstr "Podstawowe finanse" msgid "campaignBonus|Advanced Estates" msgstr "Zaawan. finanse" msgid "campaignBonus|Expert Estates" msgstr "Mistrzowskie finanse" msgid "campaignBonus|Basic Leadership" msgstr "Podst. dowodzenie" msgid "campaignBonus|Advanced Leadership" msgstr "Zaawan. dowodzenie" msgid "campaignBonus|Expert Leadership" msgstr "Mistrz. dowodzenie" msgid "campaignBonus|Basic Logistics" msgstr "Podst. logistyka" msgid "campaignBonus|Advanced Logistics" msgstr "Zaawan. logistyka" msgid "campaignBonus|Expert Logistics" msgstr "Mistrz. logistyka" msgid "campaignBonus|Basic Luck" msgstr "Podst. szczęście" msgid "campaignBonus|Advanced Luck" msgstr "Zaawan. szczęście" msgid "campaignBonus|Expert Luck" msgstr "Mistrz. szczęście" msgid "campaignBonus|Basic Mysticism" msgstr "Podst. mistycyzm" msgid "campaignBonus|Advanced Mysticism" msgstr "Zaawan. mistycyzm" msgid "campaignBonus|Expert Mysticism" msgstr "Mistrz. mistycyzm" msgid "campaignBonus|Basic Navigation" msgstr "Podst. nawigacja" msgid "campaignBonus|Advanced Navigation" msgstr "Zaawan. nawigacja" msgid "campaignBonus|Expert Navigation" msgstr "Mistrz. nawigacja" msgid "campaignBonus|Basic Necromancy" msgstr "Podst. nekromancja" msgid "campaignBonus|Advanced Necromancy" msgstr "Zaawan. nekromancja" msgid "campaignBonus|Expert Necromancy" msgstr "Mistrz. nekromancja" msgid "campaignBonus|Basic Pathfinding" msgstr "Podst. znaj. drogi" msgid "campaignBonus|Advanced Pathfinding" msgstr "Zaawan. znaj. drogi" msgid "campaignBonus|Expert Pathfinding" msgstr "Mistrz. znaj. drogi" msgid "campaignBonus|Basic Scouting" msgstr "Podstawowy zwiad" msgid "campaignBonus|Advanced Scouting" msgstr "Zaawan. zwiad" msgid "campaignBonus|Expert Scouting" msgstr "Mistrzowski zwiad" msgid "campaignBonus|Basic Wisdom" msgstr "Podstawowa mÄ…drość" msgid "campaignBonus|Advanced Wisdom" msgstr "Zaawan. mÄ…drość" msgid "campaignBonus|Expert Wisdom" msgstr "Mistrzowska mÄ…drość" #, fuzzy msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" "Główny bohater otrzyma artefakt \"%{artifact}\" na starcie scenariusza." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Królestwo otrzyma dodatkowe %{amount} %{resource} na starcie scenariusza." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Królestwo otrzyma dodatkowe %{amount} mniej %{resource} na starcie " "scenariusza." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Główny bohater otrzyma %{count} %{monster} na starcie scenariusza." #, fuzzy msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "Główny bohater otrzyma zaklÄ™cie \"%{spell}\" na starcie scenariusza." #, fuzzy msgid "The starting alignment of the scenario will be %{race}." msgstr "PoczÄ…tkowÄ… rasÄ… w scenariuszu bÄ™dzie %{race}." #, fuzzy msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "Główny bohater otrzyma dodatkowe %{count} %{skill} na starcie scenariusza." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Główny bohater otrzyma %{skill} na starcie scenariusza." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" #, fuzzy msgid "Price of Loyalty" msgstr "Cena LojalnoÅ›ci" msgid "Voyage Home" msgstr "Podróż do Domu" msgid "Wizard's Isle" msgstr "Wyspa Czarodzieja" msgid "Descendants" msgstr "Potomkowie" msgid "Cannot build. You have already built here today." msgstr "Nie można budować. Już to robiono w tej turze." msgid "For this action it is necessary to build a castle first." msgstr "Najpierw trzeba zbudować zamek." msgid "The %{building} produces %{monster}." msgstr "%{building} - tu rekrutuje siÄ™: %{monster}." msgid "Requires:" msgstr "Wymagania:" msgid "Exit this menu without doing anything." msgstr "Wyjdź z menu nie wprowadzajÄ…c żadnych zmian." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "%{name} - nie można zbudować, zamek jest za daleko od wody." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "%{name} - nie stać ciÄ™ na ten budynek." #, fuzzy msgid "The %{name} is already built." msgstr "%{name} - ten budynek zostaÅ‚ już wzniesiony." #, fuzzy msgid "Cannot build the %{name}." msgstr "%{name} - nie można zbudować." msgid "Build %{name}." msgstr "Zbuduj: %{name}." msgid "Blackridge" msgstr "Blackridge" msgid "Hillstone" msgstr "Hillstone" msgid "Pinehurst" msgstr "Pinehurst" msgid "Whiteshield" msgstr "Whiteshield" msgid "Woodhaven" msgstr "Woodhaven" msgid "Blackwind" msgstr "Blackwind" msgid "Bloodreign" msgstr "Bloodreign" msgid "Dragontooth" msgstr "Dragontooth" msgid "Greywind" msgstr "Greywind" msgid "Portsmith" msgstr "Portsmith" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Middle Gate" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "Baywatch" msgid "Fountainhead" msgstr "Fountainhead" msgid "Vertigo" msgstr "Vertigo" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Winterkill" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Lakeside" msgid "Nightshadow" msgstr "Nightshadow" msgid "Olympus" msgstr "Olympus" msgid "Sandcaster" msgstr "Sandcaster" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "New Dawn" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Big Oak" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antioch" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Roc Haven" msgid "South Mill" msgstr "South Mill" msgid "Weed Patch" msgstr "Weed Patch" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Hilltop" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Westfork" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "Elk's Head" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Blackburn" msgid "Blacksford" msgstr "Blacksford" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Pig's Eye" msgid "Viper's Nest" msgstr "Viper's Nest" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Timberhill" msgid "Troy" msgstr "Troy" msgid "Forder Oaks" msgstr "Forder Oaks" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Quick Silver" msgid "Westmoor" msgstr "Westmoor" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Nie możesz rekrutować - w mieÅ›cie jest już bohater." msgid "Cannot recruit - you have too many Heroes." msgstr "Nie możesz rekrutować - masz za dużo bohaterów." #, fuzzy msgid "Cannot afford a Hero." msgstr "Nie stać ciÄ™ na bohatera" msgid "There is no room in the garrison for this army." msgstr "W garnizonie nie ma miejsca na dla tej jednostki." msgid "Fortifications" msgstr "Fortyfikacje" msgid "Farm" msgstr "Farma" msgid "Thatched Hut" msgstr "Chata kryta sÅ‚omÄ…" msgid "Archery Range" msgstr "Tor strzelecki" msgid "Upg. Archery Range" msgstr "Rozb. tor strzelecki" msgid "Blacksmith" msgstr "Kuźnia" msgid "Upg. Blacksmith" msgstr "Rozb. kuźnia" msgid "Armory" msgstr "Zbrojownia" msgid "Upg. Armory" msgstr "Rozb. zbrojownia" msgid "Jousting Arena" msgstr "Plac turniejowy" msgid "Upg. Jousting Arena" msgstr "Rozb. plac turniejowy" msgid "Cathedral" msgstr "Katedra" msgid "Upg. Cathedral" msgstr "Rozb. katedra" msgid "Coliseum" msgstr "Koloseum" msgid "Garbage Heap" msgstr "Sterta Å›mieci" msgid "Hut" msgstr "Chata" msgid "Stick Hut" msgstr "Chata z patyków" msgid "Upg. Stick Hut" msgstr "Rozb. chata z patyków" msgid "Den" msgstr "Legowisko" msgid "Adobe" msgstr "Lepianka" msgid "Upg. Adobe" msgstr "Rozb. lepianka" msgid "Bridge" msgstr "Most" msgid "Upg. Bridge" msgstr "Rozb. most" msgid "Pyramid" msgstr "Piramida" msgid "Rainbow" msgstr "TÄ™cza" msgid "Crystal Garden" msgstr "KrysztaÅ‚owy ogród" msgid "Treehouse" msgstr "Dom na drzewie" msgid "Cottage" msgstr "Domek" msgid "Upg. Cottage" msgstr "Rozb. domek" msgid "Stonehenge" msgstr "Kamienny krÄ…g" msgid "Upg. Stonehenge" msgstr "Rozb. kamienny krÄ…g" msgid "Fenced Meadow" msgstr "Ogrodzona łąka" msgid "sorceress|Red Tower" msgstr "Czerwona wieża" msgid "Dungeon" msgstr "Loch" msgid "Waterfall" msgstr "Wodospad" msgid "Cave" msgstr "Jaskinia" msgid "Crypt" msgstr "Krypta" msgid "Nest" msgstr "Gniazdo" msgid "Maze" msgstr "Labirynt" msgid "Upg. Maze" msgstr "Rozb. labirynt" msgid "Swamp" msgstr "Bagno" msgid "Green Tower" msgstr "Zielona wieża" msgid "warlock|Red Tower" msgstr "Czerwona wieża" msgid "Black Tower" msgstr "Czarna wieża" msgid "Library" msgstr "Biblioteka" msgid "Orchard" msgstr "Sad" msgid "Habitat" msgstr "Pagórek" msgid "Pen" msgstr "Zagroda" msgid "Foundry" msgstr "Odlewnia" msgid "Upg. Foundry" msgstr "Rozb. odlewnia" msgid "Cliff Nest" msgstr "Gniazdo na urwisku" msgid "Ivory Tower" msgstr "Wieża z koÅ›ci sÅ‚oniowej" msgid "Upg. Ivory Tower" msgstr "Rozb. wieża" msgid "Cloud Castle" msgstr "Zamek w chmurach" msgid "Upg. Cloud Castle" msgstr "Rozb. zamek w chmurach" msgid "Storm" msgstr "Wieczna burza" msgid "Skull Pile" msgstr "Stos czaszek" msgid "Excavation" msgstr "Wykopalisko" msgid "Graveyard" msgstr "Cmentarz" msgid "Upg. Graveyard" msgstr "Rozb. cmentarz" msgid "Upg. Pyramid" msgstr "Rozb. piramida" msgid "Mansion" msgstr "PosiadÅ‚ość" msgid "Upg. Mansion" msgstr "Rozb. posiadÅ‚ość" msgid "Mausoleum" msgstr "Mauzoleum" msgid "Upg. Mausoleum" msgstr "Rozb. mauzoleum" msgid "Laboratory" msgstr "Laboratorium" msgid "Shrine" msgstr "Kapliczka" #, fuzzy msgid "Special" msgstr "Nic specjalnego" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "NizioÅ‚ki" #, fuzzy msgid "Dwelling 2" msgstr "NizioÅ‚ki" #, fuzzy msgid "Upg. Dwelling 2" msgstr "NizioÅ‚ki" #, fuzzy msgid "Dwelling 3" msgstr "NizioÅ‚ki" #, fuzzy msgid "Upg. Dwelling 3" msgstr "NizioÅ‚ki" #, fuzzy msgid "Dwelling 4" msgstr "NizioÅ‚ki" #, fuzzy msgid "Upg. Dwelling 4" msgstr "NizioÅ‚ki" #, fuzzy msgid "Dwelling 5" msgstr "NizioÅ‚ki" #, fuzzy msgid "Upg. Dwelling 5" msgstr "NizioÅ‚ki" #, fuzzy msgid "Dwelling 6" msgstr "NizioÅ‚ki" #, fuzzy msgid "Upg. Dwelling 6" msgstr "NizioÅ‚ki" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Fortyfikacje wzmacniajÄ… mury, sprawiajÄ…c, że ich zniszczenie zajmuje wiÄ™cej " "czasu." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Farma zwiÄ™ksza przyrost ChÅ‚opów o %{count} tygodniowo." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "W Koloseum pokazywane sÄ… przedstawienia dla oddziałów obroÅ„ców, co zwiÄ™ksza " "ich morale w walce o dwa punkty." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Sterta Å›mieci zwiÄ™ksza przyrost Goblinów o %{count} tygodniowo." msgid "The Rainbow increases the luck of the defending units by two." msgstr "TÄ™cza zwiÄ™ksza szczęście oddziałów obroÅ„ców o dwa punkty." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "KrysztaÅ‚owy ogród zwiÄ™ksza przyrost RusaÅ‚ek o %{count} tygodniowo." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Loch zwiÄ™ksza dochody miasta o %{count} sztuk zÅ‚ota na dzieÅ„." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Wodospad zwiÄ™ksza przyrost Centaurów o %{count} tygodniowo." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Biblioteka zwiÄ™ksza liczbÄ™ zaklęć dostÄ™pnych w gildii o jedno na każdy jej " "poziom." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Sad zwiÄ™ksza przyrost NizioÅ‚ków o %{count} tygodniowo." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "Wieczna burza dodaje +2 do mocy zaklęć obroÅ„cy zamku." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Stos czaszek zwiÄ™ksza przyrost Szkieletów o %{count} tygodniowo." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Studnia zwiÄ™ksza przyrost populacji wszystkich stworzeÅ„ o %{count} jednostki " "tygodniowo." msgid "Thieves' Guild" msgstr "Gildia zÅ‚odziei" msgid "Tavern" msgstr "Karczma" msgid "Shipyard" msgstr "Stocznia" msgid "Well" msgstr "Studnia" msgid "Statue" msgstr "Statua" msgid "Marketplace" msgstr "Targowisko" msgid "Moat" msgstr "Fosa" msgid "Castle" msgstr "Zamek" msgid "Tent" msgstr "Namiot" msgid "Captain's Quarters" msgstr "Kwatera kapitana" msgid "Mage Guild, Level 1" msgstr "Gildia magów, poz. 1" msgid "Mage Guild, Level 2" msgstr "Gildia magów, poz. 2" msgid "Mage Guild, Level 3" msgstr "Gildia magów, poz. 3" msgid "Mage Guild, Level 4" msgstr "Gildia magów, poz. 4" msgid "Mage Guild, Level 5" msgstr "Gildia magów, poz. 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Kapliczka zwiÄ™ksza o 10 procent umiejÄ™tność nekromancji u wszystkich twoich " "nekromantów." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Gildia ZÅ‚odziei dostarcza dane na temat wrogich graczy, a także ich miast. " "Dodatkowe gildie rozszerzajÄ… zakres podawanych informacji." msgid "The Tavern increases morale for troops defending the castle." msgstr "Karczma zwiÄ™ksza morale oddziałów broniÄ…cych zamku." msgid "The Shipyard allows ships to be built." msgstr "W stoczni można budować statki." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Studnia zwiÄ™ksza przyrost populacji wszystkich stworzeÅ„ o %{count} jednostki " "tygodniowo." #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Statua zwiÄ™ksza dzienny przychód miasta o %{count} sztuk zÅ‚ota." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "Lewa wieżyczka zwiÄ™ksza możliwość ostrzaÅ‚u wroga podczas oblężenia zamku." msgid "The Right Turret provides extra firepower during castle combat." msgstr "" "Prawa wieżyczka zwiÄ™ksza możliwość ostrzaÅ‚u wroga podczas oblężenia zamku." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Targowisko pozwala na wymianÄ™ jednego typu surowca na inny. Im wiÄ™cej " "targowisk posiadasz tym lepszy kurs wymiany." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Fosa spowalnia atakujÄ…ce jednostki. Każdy oddziaÅ‚, który wejdzie do fosy, " "musi siÄ™ w niej zatrzymać i staje siÄ™ mniej odporny na ataki." #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Zamek poprawia obronÄ™ miasta i zwiÄ™ksza dzienny przychód o %{count} sztuk " "zÅ‚ota." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "W namiocie mieszkajÄ… robotnicy mogÄ…cy zbudować zamek, pod warunkiem, że " "dostÄ™pne jest zÅ‚oto i inne potrzebne materiaÅ‚y." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "W kwaterze mieszka kapitan, który dowodzi obronÄ… zamku gdy nie ma w nim " "bohatera." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "W gildii magów bohaterowie mogÄ… uczyć siÄ™ zaklęć i odzyskiwać punkty magii." msgid "Recruit %{name}" msgstr "Rekrutuj %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "MiesiÄ…c: %{month}, TydzieÅ„: %{week}, DzieÅ„: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Aby korzystać z gildii magów, musisz kupić KsiÄ™gÄ™ Zaklęć. W tej chwili nie " "masz jednak na niÄ… miejsca. Spróbuj przekazać jeden ze swoich artefaktów " "innemu bohaterowi." msgid "Click to show next town." msgstr "Kliknij aby przejść do nastÄ™pnego miasta." msgid "Show next town" msgstr "Pokaż nastÄ™pne miasto" msgid "Click to show previous town." msgstr "Kliknij aby przejść do poprzedniego miasta." msgid "Show previous town" msgstr "Pokaż poprzednie miasto" msgid "This town may not be upgraded to a castle." msgstr "Tego miasta nie można rozbudować do poziomu zamku." msgid "Town" msgstr "Miasto" msgid "Exit Castle" msgstr "WyjÅ›cie z zamku" msgid "Exit Town" msgstr "WyjÅ›cie z miasta" msgid "Show Income" msgstr "Pokaż przychód" msgid "View Hero" msgstr "Pokaż bohatera" msgid "The above spells are available here." msgstr "Tu sÄ… dostÄ™pne powyższe zaklÄ™cia." msgid "The spells the hero can learn have been added to their book." msgstr "" "ZaklÄ™cia, których bohater mógÅ‚ siÄ™ nauczyć, zostaÅ‚y dodane do jego KsiÄ™gi " "Zaklęć." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" "Dajesz karczmarzowi szczodry napiwek, a on w zamian przekazuje ci " "nastÄ™pujÄ…ce wieÅ›ci:" msgid "Recruit Hero" msgstr "Najmij bohatera" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} ma poziom %{value}. To %{race} " msgid "with %{count} artifacts." msgstr "z %{count} artefaktami." msgid "with 1 artifact." msgstr "z jednym artefaktem." msgid "without artifacts." msgstr "bez artefaktów." msgid "Recruit %{name} the %{race}" msgstr "Rekrutuj: %{name} %{race}" #, fuzzy msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Wybór luźnej formacji oznacza, że twoja wojska bÄ™dÄ… stać rozproszone wzdÅ‚uż " "pola bitwy, a pomiÄ™dzy oddziaÅ‚ami bÄ™dzie przynajmniej jedno wolne pole." #, fuzzy msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "Wybór zwartej formacji sprawia, że twoja armia zbierze siÄ™ razem poÅ›rodku " "twojej części pola bitwy." msgid "Spread Formation" msgstr "Luźna formacja" msgid "Grouped Formation" msgstr "Zwarta formacja" #, fuzzy msgid "Click to show the next town." msgstr "Kliknij aby przejść do nastÄ™pnego miasta." #, fuzzy msgid "Click to show the previous town." msgstr "Kliknij aby przejść do poprzedniego miasta." msgid "Set garrison combat formation to 'Spread'" msgstr "Ustaw szyk garnizonu na 'luźny'" msgid "Set garrison combat formation to 'Grouped'" msgstr "Ustaw szyk garnizonu na 'zwarty'" msgid "Exit Castle Options" msgstr "WyjÅ›cie z zamku" msgid "Castle Options" msgstr "Opcje zamku" msgid "Not enough resources to recruit creatures." msgstr "Brak zasobów aby kupić stworzenia." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Nie możesz teraz rekrutować, w twojej armii nie ma już miejsca." msgid "No creatures available for purchase." msgstr "Brak stworzeÅ„ do zakupienia." msgid "Recruit Creatures" msgstr "Rekrutuj stworzenia" msgid "Hire all creatures in the town." msgstr "Zwerbuj wszystkie jednostki w tym mieÅ›cie." msgid "Max" msgstr "Maks" msgid "Available" msgstr "DostÄ™pne" msgid "Town Population Information and Statistics" msgstr "Statystyki populacji miasta" msgid "Damage" msgstr "Obrażenia" msgid "HP" msgstr "PÅ»" msgid "Growth" msgstr "Przyrost" msgid "week" msgstr "tydzieÅ„" msgid "View World" msgstr "Pokaż Å›wiat" msgid "View the entire world." msgstr "Pokaż caÅ‚y Å›wiat." msgid "Puzzle" msgstr "Pokaż ukÅ‚adankÄ™" msgid "View the obelisk puzzle." msgstr "Pokaż wzór na obelisku." msgid "Scenario Information" msgstr "Informacje o scenariuszu" msgid "View information on the scenario you are currently playing." msgstr "Obejrzyj informacje na temat scenariusza, w który obecnie grasz." msgid "Dig for the Ultimate Artifact." msgstr "Kop w poszukiwaniu Najpotężniejszego Artefaktu." msgid "Digging" msgstr "Poszukiwanie" msgid "Arena" msgstr "Arena" #, fuzzy msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Wkraczasz na arenÄ™ i stajesz oko w oko z wÅ›ciekÅ‚ymi lwami. Przy gÅ‚oÅ›nym " "aplauzie gawiedzi pokonujesz je po zaciekÅ‚ej walce. Stary trener gladiatorów " "proponuje ci pomoc w rozwiniÄ™ciu wybranej przez ciebie umiejÄ™tnoÅ›ci." msgid "Attack Skill" msgstr "Atak" msgid "Defense Skill" msgstr "Obrona" msgid "Shots" msgstr "StrzaÅ‚y" msgid "Shots Left" msgstr "PozostaÅ‚e strzaÅ‚y" msgid "Hit Points" msgstr "Punkty życia" msgid "Hit Points Left" msgstr "Aktualne PÅ»" msgid "You can't afford to upgrade your troops!" msgstr "Nie stać ciÄ™ na ulepszenie oddziałów!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Możesz ulepszyć swoje oddziaÅ‚y, ale bÄ™dzie ciÄ™ to sÅ‚ono kosztować. Czy " "chcesz je ulepszyć?" msgid "Are you sure you want to dismiss this army?" msgstr "Czy na pewno chcesz zwolnić ten oddziaÅ‚?" msgid "Upgrade" msgstr "Ulepsz" msgid "Upgrade your troops." msgstr "Ulepsz oddziaÅ‚." msgid "Dismiss" msgstr "Zwolnij" msgid "Dismiss this army." msgstr "Zwolnij ten oddziaÅ‚." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "ChcÄ… siÄ™ do ciebie przyłączyć %{monster}, pragnÄ…c zyskać chwałę.\n" "Zgadzasz siÄ™?" msgid "Followers" msgstr "SprzymierzeÅ„cy" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} jest pod wrażeniem twej dyplomatycznej przemowy i proponuje, że " "przyłączy siÄ™ do twej armii za cenÄ™ %{gold} szt. zÅ‚ota. Zgadzasz siÄ™?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Przeciwnicy sÄ… pod wrażeniem twej dyplomatycznej przemowy i skÅ‚adajÄ… ci " "ofertÄ™:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} z %{total} %{monster} chce dołączyć do twojej armii, zaÅ› reszta " "zostawi ciÄ™ w spokoju za cenÄ™ %{gold} szt. zÅ‚ota.\n" "Zgadzasz siÄ™?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "%{offer} %{monster} chce dołączyć do twojej armii za cenÄ™ %{gold} szt. " "zÅ‚ota.\n" "Zgadzasz siÄ™?" msgid "(Rate: %{percent})" msgstr "(Przyłącza siÄ™ %{percent}% oddziaÅ‚u)" msgid "off" msgstr "wyłączone" msgid "Music" msgstr "Muzyka" msgid "Effects" msgstr "Efekty" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI z dodatku" msgid "External" msgstr "ZewnÄ™trzna" msgid "Music Type" msgstr "Rodzaj muzyki" msgid "3D Audio" msgstr "DźwiÄ™k 3D" msgid "Toggle ambient music level." msgstr "ZmieÅ„ poziom gÅ‚oÅ›noÅ›ci muzyki." msgid "Toggle foreground sounds level." msgstr "ZmieÅ„ poziom gÅ‚oÅ›noÅ›ci efektów." msgid "Change the type of music." msgstr "ZmieÅ„ rodzaj muzyki." #, fuzzy msgid "Toggle the 3D effect of foreground sounds." msgstr "Włącz lub wyłącz efekty dźwiÄ™kowe 3D." msgid "Build a new ship:" msgstr "Zbuduj nowy statek:" msgid "Resource cost:" msgstr "Koszt:" msgid "Total: " msgstr "Masz: " msgid "Need: " msgstr "Potrzeba: " msgid "New Game" msgstr "Nowa gra" msgid "Start a single or multi-player game." msgstr "Rozpocznij grÄ™ dla jednego lub wielu graczy." msgid "Load Game" msgstr "Wczytaj grÄ™" msgid "Load a previously saved game." msgstr "Wczytaj uprzednio zapisanÄ… grÄ™." msgid "Save Game" msgstr "Zapisz grÄ™" msgid "Save the current game." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Quit" msgstr "WyjÅ›cie" msgid "Quit out of Heroes of Might and Magic II." msgstr "ZakoÅ„czenie gry Heroes of Might and Magic II." msgid "Language" msgstr "JÄ™zyk" msgid "Graphics" msgstr "Grafika" msgid "Black & White" msgstr "Czarno-biaÅ‚y" msgid "Mouse Cursor" msgstr "Kursor myszki" msgid "Color" msgstr "Kolor" msgid "Text Support" msgstr "Dodatkowe informacje" msgid "Change the language of the game." msgstr "ZmieÅ„ jÄ™zyk gry." msgid "Select Game Language" msgstr "Wybierz jÄ™zyk gry" msgid "Change the graphics settings of the game." msgstr "ZmieÅ„ ustawienia grafiki gry." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" "ZmieÅ„ kursor na kolorowy lub czarno-biaÅ‚y. Wybór ma jedynie charakter " "estetyczny." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "Włącza lub wyłącza dodatkowe informacje o oknach i zdarzeniach w grze." msgid "" "Map\n" "Difficulty" msgstr "" "Trudność\n" "mapy" msgid "" "Game\n" "Difficulty" msgstr "" "Trudność\n" "gry" msgid "Rating" msgstr "Ocena" msgid "Map Size" msgstr "" "Wielkość\n" "mapy" msgid "Opponents" msgstr "Przeciwnicy" msgid "Class" msgstr "Klasa" msgid "" "Victory\n" "Conditions" msgstr "" "Warunki\n" "zwyciÄ™stwa" msgid "" "Loss\n" "Conditions" msgstr "" "Warunki\n" "przegranej" msgid "First select recipients!" msgstr "Wskaż najpierw odbiorców!" msgid "You cannot select %{resource}!" msgstr "Nie możesz wybrać %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Strzelaj do %{monster}" msgid "Select Recipients" msgstr "Wybierz odbiorcÄ™" msgid "Your Funds" msgstr "Twoje zasoby" msgid "Planned Gift" msgstr "Przekazujesz" msgid "Gift from %{name}" msgstr "Dar od %{name}" msgid "Resolution" msgstr "Rozdzielczość" msgid "Fullscreen" msgstr "PeÅ‚ny ekran" msgid "window|Mode" msgstr "Widok" msgid "Windowed" msgstr "W oknie" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Dodatkowe informacje" msgid "Change the resolution of the game." msgstr "ZmieÅ„ rozdzielczość gry." msgid "Select Game Resolution" msgstr "Wybierz rozdzielczość gry" msgid "Toggle between fullscreen and windowed modes." msgstr "Przełącz pomiÄ™dzy peÅ‚nym ekranem w widokiem w oknie." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "Włączenie V-Sync może rozwiÄ…zać problemy z migocÄ…cym ekranem." msgid "Show extra information such as FPS and current time." msgstr "Pokaż dodatkowe informacje jak na przykÅ‚ad FPS lub aktualnÄ… godzinÄ™." msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" #, fuzzy msgid "Event: " msgstr "Zdarzenie" msgid "Hot Keys:" msgstr "Skróty klawiszowe:" msgid "Hide" msgstr "Ukryj" msgid "Show" msgstr "Pokaż" msgid "Interface" msgstr "Interfejs" msgid "Interface Type" msgstr "Typ interfejsu" msgid "Toggle the type of interface you want to use." msgstr "ZmieÅ„ typ interfejsu." msgid "Toggle interface visibility." msgstr "ZmieÅ„ widoczność interfejsu." msgid "Scroll Speed" msgstr "PrÄ™dkość przewijania" msgid "Sets the speed at which you scroll the window." msgstr "ZmieÅ„ prÄ™dkość przewijania okna." msgid "Select Game Language:" msgstr "Wybierz jÄ™zyk gry:" #, fuzzy msgid "Select Language:" msgstr "Wybierz jÄ™zyk gry:" msgid "Click to choose the selected language." msgstr "Kliknij tutaj, aby ustawić wybrany jÄ™zyk." msgid "%{name} has gained a level." msgstr "%{name} zyskuje poziom." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "NauczyÅ‚eÅ› siÄ™ %{skill}." #, fuzzy msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "%{name} zyskuje poziom." #, fuzzy msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "Możesz nauczyć siÄ™:" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "nd." msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "ProszÄ™, zapoznaj siÄ™ z naszÄ… ofertÄ…. JeÅ›li masz zamiar handlować, kliknij na " "towarach które chcesz wymienić." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "UdaÅ‚o ci siÄ™ ubić niezÅ‚y interes. Chyba na tym nic nie zarobiÄ™. Może " "interesujÄ… ciÄ™ inne moje towary?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "MogÄ™ ci zaproponować %{count} za 1 szt. %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "MogÄ™ ci zaproponować 1 szt. %{resto} za %{count} szt. %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Ilość" msgid "Trading Post" msgstr "Faktoria handlowa" msgid "Your Resources" msgstr "Twoje surowce" msgid "Available Trades" msgstr "Oferta" msgid "guarded by %{count} %{monster}" msgstr "strzeżona przez %{count} %{monster}" msgid "guarded by " msgstr "strzeżone przez " msgid "(available: %{count})" msgstr "(dostÄ™pne: %{count})" msgid "(empty)" msgstr "(nie ma nikogo)" msgid "already learned" msgstr "już to umiesz" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Drzewo Wiedzy" #, fuzzy msgid "already claimed" msgstr "już to umiesz" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "już znasz tÄ™ umiejÄ™tność" msgid "already has max skills" msgstr "posiadasz maksimum umiejÄ™tnoÅ›ci" msgid "(already visited)" msgstr "(już odwiedzono)" msgid "(not visited)" msgstr "(nie odwiedzono)" msgid "%{color} Barrier" msgstr "Bariera - kolor %{color}" #, fuzzy msgid "(tent visited)" msgstr "(nie odwiedzono)" msgid "%{color} Tent" msgstr "%{color} namiot podróżnika" msgid "Road" msgstr "Droga" msgid "(digging ok)" msgstr "(można kopać)" msgid "(no digging)" msgstr "(nie można kopać)" msgid "penalty: %{cost}" msgstr "pkt. ruchu: %{cost}" msgid "Defenders:" msgstr "ObroÅ„cy:" msgid "Unknown" msgstr "Nieznany" msgid "heroQuickInfo|(Level %{level})" msgstr "(poziom %{level})" msgid "Attack:" msgstr "Atak:" msgid "Defense:" msgstr "Obrona:" msgid "Spell Power:" msgstr "Moc zaklęć:" msgid "Knowledge:" msgstr "Wiedza:" msgid "Spell Points:" msgstr "Pkt. magii:" msgid "Move Points:" msgstr "Pkt. ruchu:" msgid "Uncharted Territory" msgstr "Niezbadane terytorium" msgid "Cost per troop:" msgstr "Koszt jednostki:" msgid "Available: %{count}" msgstr "DostÄ™pne: %{count}" msgid "Number to buy:" msgstr "Rekrutuj:" msgid "Recruit selected monsters." msgstr "Rekrutuj wybrane stworzenia." msgid "Select maximum monsters to be recruited." msgstr "Ustaw maksymalnÄ… liczbÄ™ stworzeÅ„ możliwych do zrekrutowania." msgid "Select only 1 monster to be recruited." msgstr "Ustaw jedno stworzenie do zrekrutowania." #, fuzzy msgid "Select this game resolution." msgstr "Wybierz rozdzielczość gry" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Wybierz rozdzielczość gry:" msgid "Click to apply the selected resolution." msgstr "Użyj wskazanej rozdzielczoÅ›ci." msgid "Click to apply the entered text." msgstr "Zatwierdź podany tekst." msgid "Click to open the Virtual Keyboard dialog." msgstr "Kliknij, aby otworzyć wirtualnÄ… klawiaturÄ™." msgid "Open Virtual Keyboard" msgstr "Otwórz wirtualnÄ… klawiaturÄ™" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "Ile jednostek przenieść?" #, fuzzy msgid "Select how many units to separate into:" msgstr "Wybierz miasto docelowe." msgid "Map: " msgstr "Nazwa mapy: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "MiesiÄ…c: " msgid ", Week: " msgstr ", TydzieÅ„: " msgid ", Day: " msgstr ", DzieÅ„: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "PoÅ‚ożenie pliku: " msgid "Are you sure you want to delete file:" msgstr "Czy na pewno chcesz usunąć plik:" msgid "Warning" msgstr "Uwaga" msgid "Click to save the current game." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Click to load a previously saved game." msgstr "Wczytaj uprzednio zapisanÄ… grÄ™." msgid "File to Save:" msgstr "Zapisz plik:" msgid "File to Load:" msgstr "Wczytaj plik:" #, fuzzy msgid "Terrain object" msgstr "Brak obiektu" msgid "Accept the choice made." msgstr "Zastosuj wprowadzone zmiany." msgid "Select Skill:" msgstr "Wybierz umiejÄ™tność:" msgid "Select Spell:" msgstr "Wybierz zaklÄ™cie:" msgid "Select Artifact:" msgstr "Wybierz artefakt:" msgid "Select Monster:" msgstr "Wybierz potwora:" msgid "Select Hero:" msgstr "Wybierz bohatera:" msgid "race|Random" msgstr "Losowo" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Użyj wskazanej rozdzielczoÅ›ci." #, fuzzy msgid "%{color} %{race}" msgstr "%{color} gracz" msgid "You will place" msgstr "" #, fuzzy msgid "Click to select this class." msgstr "Kliknij tutaj, aby wybrać scenariusz, który chcesz rozegrać." #, fuzzy msgid "Click to select this color." msgstr "Kliknij tutaj, aby wybrać scenariusz, który chcesz rozegrać." #, fuzzy msgid "Select Treasure:" msgstr "Wybierz bohatera:" #, fuzzy msgid "Select Ocean Object:" msgstr "Wybierz artefakt:" #, fuzzy msgid "Castle/town placing" msgstr "Opcje zamku" msgid "doubleLinedRace|Neutral" msgstr "Neutralny" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "Użyj wskazanej rozdzielczoÅ›ci." #, fuzzy msgid "Click to select town placing." msgstr "Kliknij aby przejść do nastÄ™pnego miasta." #, fuzzy msgid "Click to select castle placing." msgstr "Kliknij tutaj, aby wybrać scenariusz, który chcesz rozegrać." #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} gracz" msgid "race|Neutral" msgstr "Neutralny" #, fuzzy msgid "Select Dwelling:" msgstr "Wybierz zaklÄ™cie:" #, fuzzy msgid "Select Landscape Object:" msgstr "Wybierz artefakt:" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "Surowiec" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name}, %{race}" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "Kliknij tutaj, aby wybrać scenariusz, który chcesz rozegrać." #, fuzzy msgid "Select Mountain Object:" msgstr "Wybierz artefakt:" #, fuzzy msgid "Select Rock Object:" msgstr "Wybierz artefakt:" #, fuzzy msgid "Select Tree Object:" msgstr "Wybierz artefakt:" #, fuzzy msgid "Select Power Up Object:" msgstr "Wybierz artefakt:" #, fuzzy msgid "Select Adventure Object:" msgstr "Wybierz artefakt:" msgid "Players Icon" msgstr "Ikona graczy" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Pokazuje ilu graczy bierze udziaÅ‚ w tym scenariuszu. Każde miejsce nie " "zajÄ™te przez ludzi, zostanie zajÄ™te przez komputer." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Wskazuje czy mapa jest maÅ‚a (36 x 36), Å›rednia (72 x 72), duża (108 x 108), " "czy też bardzo duża (144 x 144)." msgid "Size Icon" msgstr "Ikona wielkoÅ›ci" msgid "Map Type" msgstr "Typ mapy" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "Wskazuje czy mapa jest z Wojny o SukcesjÄ™ czy z Ceny LojalnoÅ›ci." msgid "Map Type:\n" msgstr "Typ Mapy:\n" msgid "The Succession Wars" msgstr "Wojna o SukcesjÄ™" msgid "The Price of Loyalty" msgstr "Cena LojalnoÅ›ci" #, fuzzy msgid "Resurrection" msgstr "Wskrzeszenie" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "JÄ™zyk" msgid "Lose all your heroes and towns." msgstr "Utrata wszystkich bohaterów i miast." msgid "Lose a specific town." msgstr "Utrata okreÅ›lonego miasta." msgid "Lose a specific hero." msgstr "Utrata okreÅ›lonego bohatera." msgid "Run out of time. Fail to win by a certain point." msgstr "UpÅ‚yw czasu. NieukoÅ„czenie gry w okreÅ›lonym czasie." msgid "Loss Condition" msgstr "Warunki porażki" msgid "Defeat all enemy heroes and towns." msgstr "Pokonaj wszystkich wrogów i miasta." msgid "Capture a specific town." msgstr "ZdobÄ…dź okreÅ›lone miasto." msgid "Defeat a specific hero." msgstr "Pokonaj okreÅ›lonego bohatera." msgid "Find a specific artifact." msgstr "Znajdź okreÅ›lony artefakt." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "Twoja strona pokonuje przeciwnÄ…." msgid "Accumulate a large amount of gold." msgstr "Zgromadź dużą ilość zÅ‚ota." msgid "Victory Condition" msgstr "Warunki zwyciÄ™stwa" msgid "Map difficulty:" msgstr "Poziom:" msgid "N" msgstr "N" #, fuzzy msgid "No maps exist at that size." msgstr "Brak map o tym rozmiarze" msgid "Small Maps" msgstr "MaÅ‚e mapy" msgid "View only maps of size small (36 x 36)." msgstr "Pokaż tylko maÅ‚e mapy (36 x 36)." msgid "Medium Maps" msgstr "Åšrednie mapy" msgid "View only maps of size medium (72 x 72)." msgstr "Pokaż tylko Å›rednie mapy (72 x 72)." msgid "Large Maps" msgstr "Duże mapy" msgid "View only maps of size large (108 x 108)." msgstr "Pokaż tylko duże mapy (108 x 108)." msgid "Extra Large Maps" msgstr "Bardzo duże mapy" msgid "View only maps of size extra large (144 x 144)." msgstr "Pokaż tylko bardzo duże mapy (144 x 144)." msgid "All Maps" msgstr "Wszystkie mapy" msgid "View all maps, regardless of size." msgstr "Pokaż wszystkie mapy, niezależnie od wielkoÅ›ci." msgid "Selected Name" msgstr "Wybrana nazwa" msgid "The name of the currently selected map." msgstr "Nazwa aktualnie wybranej mapy." msgid "Selected Map Difficulty" msgstr "Trudność wybranej mapy" #, fuzzy msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Poziom trudnoÅ›ci na aktualnie wybranej mapie, okreÅ›lony przez autora " "scenariusza. Na bardziej zÅ‚ożonych mapach mogÄ… wystÄ™pować silniejsi " "przeciwnicy, mniej zasobów lub inne specjalne warunki utrudniajÄ…ce rozgrywkÄ™." msgid "Selected Description" msgstr "Wybrany opis" msgid "The description of the currently selected map." msgstr "Opis aktualnie wybranej mapy." msgid "Jump" msgstr "Skok" msgid "Hero Speed" msgstr "Szybkość" msgid "Don't Show" msgstr "Nie pokazuj" msgid "Enemy Speed" msgstr "Szybk. wroga" msgid "Auto Resolve" msgstr "Automatyczna" msgid "Auto, No Spells" msgstr "Auto, bez zaklęć" msgid "Battles" msgstr "Walki" #, fuzzy msgid "combatMode|Manual" msgstr "RÄ™czna" msgid "Change the speed at which your heroes move on the main screen." msgstr "ZmieÅ„ szybkość z jakÄ… poruszajÄ… siÄ™ twoi bohaterowie na ekranie." #, fuzzy msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "ZmieÅ„ szybkość, z jakÄ… poruszajÄ… siÄ™ bohaterowie sterowani przez A.I. Możesz " "również wyłączyć podglÄ…d ruchów A.I." #, fuzzy msgid "Change the interface settings of the game." msgstr "ZmieÅ„ ustawienia grafiki gry." #, fuzzy msgid "Interface Settings" msgstr "Ustawienia gry" msgid "Toggle instant battle mode." msgstr "ZmieÅ„ tryb walki." msgid "Att." msgstr "Atk." msgid "Def." msgstr "Obr." msgid "Power" msgstr "Moc" msgid "Knowl" msgstr "Wiedz" msgid "1st" msgstr "1." msgid "2nd" msgstr "2." msgid "3rd" msgstr "3." msgid "4th" msgstr "4." msgid "5th" msgstr "5." msgid "6th" msgstr "6." msgid "Oracle: Player Rankings" msgstr "Wyrocznia - ranking graczy" msgid "Thieves' Guild: Player Rankings" msgstr "Gildia zÅ‚odziei - ranking graczy" msgid "Number of Towns:" msgstr "Liczba miast:" msgid "Number of Castles:" msgstr "Liczba zamków:" msgid "Number of Heroes:" msgstr "Liczba bohaterów:" msgid "Gold in Treasury:" msgstr "ZÅ‚oto w skarbcu:" msgid "Wood & Ore:" msgstr "Drewno i ruda:" msgid "Gems, Cr, Slf & Mer:" msgstr "Klejn., kr., siar. i rtęć:" msgid "Obelisks Found:" msgstr "Znalezione obeliski:" msgid "Artifacts:" msgstr "Artefakty:" msgid "Total Army Strength:" msgstr "CaÅ‚kowita siÅ‚a armii:" msgid "Income:" msgstr "Przychód:" msgid "Best Hero:" msgstr "Najlepszy bohater:" msgid "Best Hero Stats:" msgstr "Najlepsze cechy:" msgid "Personality:" msgstr "Osobowość:" msgid "Best Monster:" msgstr "Najlepszy potwór:" #, fuzzy msgid "Random Castle Name" msgstr "Losowy zamek" #, fuzzy msgid "Random Town Name" msgstr "Losowe miasto" #, fuzzy msgid "Allow Castle build" msgstr "Zamek w chmurach" #, fuzzy msgid "Default Buildings" msgstr "domyÅ›lna akcja" #, fuzzy msgid "Default Army" msgstr "domyÅ›lna akcja" #, fuzzy msgid "Castle Army" msgstr "Zamek" #, fuzzy msgid "Town Army" msgstr "Miasto" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Przegrywa bohater: %{name}." msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Pasek WiadomoÅ›ci" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Pasek WiadomoÅ›ci" #, fuzzy msgid "Click to save the Event properties." msgstr "Zapisz bieżącÄ… grÄ™." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "Surowiec" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "DzieÅ„: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Zapisz bieżącÄ… grÄ™." #, fuzzy msgid "Add Event" msgstr "Zdarzenie" #, fuzzy msgid "Add an additional event." msgstr "ProgramiÅ›ci" #, fuzzy msgid "Edit Event" msgstr "Zdarzenie" #, fuzzy msgid "Edit an existing event." msgstr "Wczytaj istniejÄ…cÄ… mapÄ™." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "Wczytaj istniejÄ…cÄ… mapÄ™." #, fuzzy msgid "Effects:" msgstr "Efekty" #, fuzzy msgid "Conditions:" msgstr "" "Warunki\n" "przegranej" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "DoÅ›wiadczenie" msgid "Artifact" msgstr "Artefakt" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Wybierz artefakt:" #, fuzzy msgid "Delete an artifact from the event." msgstr "Wczytaj istniejÄ…cÄ… mapÄ™." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Wybierz umiejÄ™tność:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "To zaklÄ™cie nie może być rzucone z Å‚odzi." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "To zaklÄ™cie nie może być rzucone z Å‚odzi." #, fuzzy msgid "%{objects} must be placed on water." msgstr "To zaklÄ™cie nie może być rzucone z Å‚odzi." #, fuzzy msgid "Objects cannot be placed outside the map." msgstr "To zaklÄ™cie nie może być rzucone z Å‚odzi." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "To zaklÄ™cie nie może być rzucone z Å‚odzi." #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Czy na pewno chcesz wczytać nowÄ… grÄ™? (aktualna rozgrywka zostanie przerwana)" msgid "Editor" msgstr "" #, fuzzy msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Czy na pewno chcesz wczytać nowÄ… grÄ™? (aktualna rozgrywka zostanie przerwana)" #, fuzzy msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Czy na pewno chcesz wczytać nowÄ… grÄ™? (aktualna rozgrywka zostanie przerwana)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "OD NOWA" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Czy na pewno chcesz wczytać nowÄ… grÄ™? (aktualna rozgrywka zostanie przerwana)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Rozpocznij od nowa" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Czy na pewno chcesz wczytać nowÄ… grÄ™? (aktualna rozgrywka zostanie przerwana)" #, fuzzy msgid "Create a new map from scratch." msgstr "nowa mapa od poczÄ…tku" msgid "New Map" msgstr "Nowa Mapa" msgid "Load Map" msgstr "Wczytaj MapÄ™" msgid "Load an existing map." msgstr "Wczytaj istniejÄ…cÄ… mapÄ™." #, fuzzy msgid "Save Map" msgstr "Zapisz grÄ™" #, fuzzy msgid "Save the current map." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Quit out of the map editor." msgstr "" #, fuzzy msgid "Return to the game's Main Menu." msgstr "Kliknij, aby wrócić do głównego menu." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Losowy najpotężniejszy artefakt" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "z jednym artefaktem." msgid "The total number of obelisks is %{count}." msgstr "" #, fuzzy msgid "Roads" msgstr "Droga" msgid "Streams" msgstr "" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "To zaklÄ™cie nie może być rzucone z Å‚odzi." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Plik z zapisanÄ… grÄ… jest uszkodzony." msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "" #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Zapisz plik:" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Czy na pewno chcesz zapisać stan gry z takÄ… samÄ… nazwÄ…?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "Zapisz plik:" #, fuzzy msgid "Used to place %{object}." msgstr "Znajdź najpotężniejszy artefakt." #, fuzzy msgid "Select object type" msgstr "Wybierz artefakt:" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Kliknij tutaj, aby wybrać scenariusz, który chcesz rozegrać." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Wybierz innego bohatera." msgid "" "Cell\n" "Details" msgstr "" msgid "Erase" msgstr "" msgid "Mountains" msgstr "Góry" #, fuzzy msgid "Rocks" msgstr "KamieÅ„" msgid "Trees" msgstr "Drzewa" #, fuzzy msgid "Water Objects" msgstr "WyschniÄ™ty" #, fuzzy msgid "Miscellaneous" msgstr "Fineous" msgid "Artifacts" msgstr "Artefakty" #, fuzzy msgid "Dwellings" msgstr "NizioÅ‚ki" msgid "Mines" msgstr "Kopalnia" #, fuzzy msgid "Power-ups" msgstr "Moc" msgid "Treasures" msgstr "Skarby" msgid "Heroes" msgstr "Bohaterowie" msgid "Towns" msgstr "Miasta" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Wybierz artefakt:" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" #, fuzzy msgid "Small Brush" msgstr "MaÅ‚e mapy" #, fuzzy msgid "Medium Brush" msgstr "Åšrednie mapy" #, fuzzy msgid "Large Brush" msgstr "Duże mapy" msgid "Area Fill" msgstr "" msgid "Used to click and drag for filling in large areas." msgstr "" msgid "Clear Area" msgstr "" msgid "Used to click and drag for clearing large areas." msgstr "" msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" msgid "Traversable only by boat." msgstr "" msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" #, fuzzy msgid "Used for special editing of action objects." msgstr "Pokonaj wszystkich wrogów i miasta." #, fuzzy msgid "Adventure Objects Mode" msgstr "Opcje przygody" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" #, fuzzy msgid "Kingdom Objects Mode" msgstr "Przychód" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "Potwory" #, fuzzy msgid "Used to place monsters on the map." msgstr "Znajdź najpotężniejszy artefakt." msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" #, fuzzy msgid "Road Mode" msgstr "Droga" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" #, fuzzy msgid "Specifications" msgstr "Zamiana w KamieÅ„" msgid "File Options" msgstr "Opcje plików" #, fuzzy msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Pokazuje menu z opcjami plików, pozwalajÄ…c na: wczytanie gry, zapisanie gry " "rozpoczÄ™cie nowej gry lub wyjÅ›cie z bieżącej gry." #, fuzzy msgid "View the editor system options, which let you customize the editor." msgstr "" "Pokazuje menu z opcjami systemowymi, pozwalajÄ…c na zmianÄ™ ustawieÅ„ gry." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Utwórz mapÄ™ o dÅ‚ugoÅ›ci %{size} i szerokoÅ›ci %{size}." msgid "Cancel back to the New Map menu." msgstr "Anuluj, aby wrócić do menu Nowa Mapa." msgid "Cancel back to the main menu." msgstr "Wróć do głównego menu." msgid "From Scratch" msgstr "Od poczÄ…tku" msgid "Start from scratch with a blank map." msgstr "Zacznij od poczÄ…tku pustÄ… mapÄ™." msgid "Create a randomly generated map." msgstr "Utwórz losowo wygenerowanÄ… mapÄ™." msgid "Random" msgstr "Losowa" msgid "Cancel back to the Map Editor main menu." msgstr "Anuluj, aby wrócić do głównego menu." msgid "No maps available!" msgstr "Mapy niedostÄ™pne!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{color} gracz" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "Spotkanie: %{name1} i %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{color} gracz" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{color} gracz" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "Spotkanie: %{name1} i %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "Spotkanie: %{name1} i %{name2}" #, fuzzy msgid "None." msgstr "Brak" #, fuzzy msgid "One side defeats another." msgstr "Wybierz innego bohatera." #, fuzzy msgid "Accumulate gold." msgstr "Zgromadź %{count} zÅ‚ota." msgid "Run out of time." msgstr "" #, fuzzy msgid "alliance|1st" msgstr " sojusz" #, fuzzy msgid "alliance|2nd" msgstr " sojusz" #, fuzzy msgid "alliance|3rd" msgstr " sojusz" #, fuzzy msgid "alliance|4th" msgstr " sojusz" #, fuzzy msgid "alliance|5th" msgstr " sojusz" #, fuzzy msgid "Special Loss Condition" msgstr "Warunki porażki" #, fuzzy msgid "Special Victory Condition" msgstr "Warunki zwyciÄ™stwa" #, fuzzy msgid "Allow standard victory conditions" msgstr "Warunki zwyciÄ™stwa" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " sojusz" #, fuzzy msgid "{%number} alliance: " msgstr " sojusz" #, fuzzy msgid "Gold:" msgstr "ZÅ‚oto" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Wybierz miasto docelowe." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Zapisz bieżącÄ… grÄ™." #, fuzzy msgid "Map Difficulty" msgstr "" "Trudność\n" "mapy" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "PoÅ‚ożenie pliku: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Wybrany opis" #, fuzzy msgid "Click to accept the changes made." msgstr "Kliknij aby przejść do nastÄ™pnego miasta." #, fuzzy msgid "Click to edit custom rumors." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Użyj wskazanej rozdzielczoÅ›ci." #, fuzzy msgid "Events" msgstr "Zdarzenie" #, fuzzy msgid "Click to change the language of the map." msgstr "ZmieÅ„ jÄ™zyk gry." #, fuzzy msgid "Click to change your map name." msgstr "Kliknij aby przejść do nastÄ™pnego miasta." #, fuzzy msgid "Map Name" msgstr "" "Wielkość\n" "mapy" #, fuzzy msgid "Click to change the description of the current map." msgstr "Opis aktualnie wybranej mapy." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Opis aktualnie wybranej mapy." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Opis aktualnie wybranej mapy." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Typ mapy" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Poziom trudnoÅ›ci na aktualnie wybranej mapie, okreÅ›lony przez autora " "scenariusza. Na bardziej zÅ‚ożonych mapach mogÄ… wystÄ™pować silniejsi " "przeciwnicy, mniej zasobów lub inne specjalne warunki utrudniajÄ…ce rozgrywkÄ™." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Wybierz ilość %{resource}:" #, fuzzy msgid "Animation" msgstr "Aneksja" #, fuzzy msgid "Passability" msgstr "Osobowość:" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "ProgramiÅ›ci" msgid "Edit Rumor" msgstr "" #, fuzzy msgid "Edit an existing rumor." msgstr "Wczytaj istniejÄ…cÄ… mapÄ™." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "Wczytaj istniejÄ…cÄ… mapÄ™." msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "PoÅ‚ożenie pliku: " #, fuzzy msgid "Save Map:" msgstr "Zapisz grÄ™" #, fuzzy msgid "Click to save the current map." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Zapisz bieżącÄ… grÄ™." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Åatwy" msgid "difficulty|Normal" msgstr "Normalny" msgid "difficulty|Hard" msgstr "Trudny" msgid "difficulty|Expert" msgstr "Ekspert" msgid "difficulty|Impossible" msgstr "Niemożliwy" msgid "and more..." msgstr "i wiÄ™cej..." msgid "Easy" msgstr "Åatwa" msgid "Normal" msgstr "Normalnie" msgid "Hard" msgstr "Trudna" msgid "Campaign Difficulty" msgstr "StopieÅ„ trudnoÅ›ci kampanii" #, fuzzy msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Wybierz tÄ™ opcjÄ™ jeÅ›li cenisz fabułę ponad wyzwanie. AI rozgrywa misje " "gorzej niż przy normalnym poziomie trudnoÅ›ci." #, fuzzy msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Wybierz tÄ™ opcjÄ™ by cieszyć siÄ™ kampaniÄ… zgodnie z jej oryginalnymi " "zaÅ‚ożeniami." #, fuzzy msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Wybierz tÄ™ opcjÄ™ jeÅ›li jesteÅ› gotów na wyzwania. AI rozgrywa misje lepiej " "niż przy normalnym poziomie trudnoÅ›ci." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Gratulacje!\n" "\n" "Liczba dni: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Trudność: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Wynik: %{score}\n" "\n" "Ranking:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Rozpocznij wybrany scenariusz." msgid "View Intro" msgstr "Zobacz Wprowadzenie" #, fuzzy msgid "View the intro video for the current state of the campaign." msgstr "Zobacz filmy wprowadzajÄ…ce dla obecnego stanu kampanii." #, fuzzy msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Wybierz stopieÅ„ trudnoÅ›ci. Tego ustawienia nie bÄ™dziesz mógÅ‚ później zmienić." msgid "Restart the current scenario." msgstr "Rozpocznij od nowa obecny scenariusz." #, fuzzy msgid "Difficulty" msgstr "" "Trudność\n" "mapy" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" msgid "Are you sure you want to restart this scenario?" msgstr "Czy na pewno chcesz rozpocząć od nowa obecny scenariusz?" msgid "Campaign Scenario loading failure" msgstr "Problem z uruchomieniem scenariusza kampanii" msgid "Please make sure that campaign files are correct and present." msgstr "Upewnij siÄ™, że pliki kampanii sÄ… poprawne." msgid "Days spent" msgstr "Ilość dni" msgid "The number of days spent on this campaign." msgstr "Ilość dni spÄ™dzonych na tej kampanii." msgid "Project Coordination and Core Development" msgstr "Koordynacja projektu i development" msgid "Development" msgstr "Development" msgid "Visit us at " msgstr "Odwiedź nas " msgid "QA and Support" msgstr "QA i wsparcie" msgid "Dev and Support" msgstr "Development i wsparcie" msgid "Special Thanks to" msgstr "Specjalnie podziÄ™kowania dla" #, fuzzy msgid "and many-many other contributors and supporters!" msgstr "i wielu, wielu innym!" msgid "Support us at" msgstr "Wesprzyj nas" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Odwiedź nas" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Potrzebujesz wsparcia?" msgid "Original project before 0.7" msgstr "Przed wersjÄ… 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Zespół gry Heroes of Might and Magic II: The Succesion Wars" msgid "Designed and Directed" msgstr "Projekt i kierownictwo projektu" msgid "Programming and Design" msgstr "Programowanie i Projektowanie" msgid "Executive Producer" msgstr "Producent wykonawczy" msgid "Producer" msgstr "Producent" msgid "Additional Design" msgstr "Dodatkowe projekty" msgid "Additional Programming" msgstr "ProgramiÅ›ci" msgid "Musical Production" msgstr "Produkcja muzyczna" msgid "Music and Sound Design" msgstr "Muzyka i projekt dźwiÄ™ku" msgid "Vocalists" msgstr "Partie wokalne" msgid "Art Director" msgstr "Kierownik artystyczny" msgid "Assistant Art Director" msgstr "Asystent kierownika artystycznego" msgid "Artists" msgstr "Graficy" msgid "QA Manager" msgstr "Kierownik kontroli jakoÅ›ci" msgid "QA" msgstr "Kontrola jakoÅ›ci" msgid "Writing" msgstr "Teksty" msgid "Manual and Helpfile" msgstr "Instrukcja i plik pomocy" msgid "Scenarios" msgstr "Scenariusze" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Zespół gry Heroes of Might and Magic II: The Price of Loyalty" msgid "Design Lead" msgstr "Kierownik projektowania" msgid "Designers" msgstr "Projektanci" msgid "Programming Lead" msgstr "Kierownik programowania" msgid "Art Lead" msgstr "Kierownik artystów" msgid "Playtesters" msgstr "Testerzy gry" msgid "Designer" msgstr "Projektant" msgid "Producers" msgstr "Produkcja" msgid "QA Managers" msgstr "Kierownicy kontroli jakoÅ›ci" msgid "Sound Design" msgstr "Projektowanie DźwiÄ™ku" msgid "Town Themes" msgstr "Motywy muzyczne miast" msgid "Alto Sax" msgstr "Saksofon altowy" msgid "Harpsichord and Piano" msgstr "Klawesyn i fortepian" msgid "Basso Vocal" msgstr "Bas (partie wokalne)" msgid "Soprano Vocal" msgstr "Sopran (partie wokalne)" msgid "Recorded at %{recordingStudio}" msgstr "Nagrano w %{recordingStudio}" msgid "credits|Manual" msgstr "Przewodnik" msgid "German Consultant" msgstr "Konsultant ds. j. niemieckiego" msgid "Map Designers" msgstr "Projektanci Map" msgid "Package Design" msgstr "Projekt opakowania" msgid "High Scores" msgstr "Najlepsze wyniki" msgid "Your Name" msgstr "Twoje imiÄ™" msgid "Unknown Hero" msgstr "Nieznany bohater" msgid "Standard" msgstr "Standard" msgid "View High Scores for Standard Maps." msgstr "Obejrzyj najlepsze wyniki dla pojedynczych scenariuszy." msgid "Campaign" msgstr "Kampania" msgid "View High Scores for Campaigns." msgstr "Obejrzyj najlepsze wyniki dla kampanii." msgid "hotkey|default okay event" msgstr "zatwierdź" msgid "hotkey|default cancel event" msgstr "anuluj" msgid "hotkey|default left" msgstr "w lewo" msgid "hotkey|default right" msgstr "w prawo" msgid "hotkey|default up" msgstr "w górÄ™" msgid "hotkey|default down" msgstr "w dół" msgid "hotkey|toggle fullscreen" msgstr "peÅ‚ny ekran/okno" msgid "hotkey|toggle text support mode" msgstr "wÅ‚./wyÅ‚. dodatkowe informacje" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "wÅ‚./wyÅ‚. dodatkowe informacje" msgid "hotkey|new game" msgstr "nowa gra" msgid "hotkey|load game" msgstr "wczytaj grÄ™" #, fuzzy msgid "hotkey|high scores" msgstr "najlepsze wyniki" msgid "hotkey|credits" msgstr "autorzy" msgid "hotkey|standard game" msgstr "gra standardowa" msgid "hotkey|campaign game" msgstr "kampania" msgid "hotkey|multi-player game" msgstr "gra dla wielu osób" msgid "hotkey|settings" msgstr "ustawienia" msgid "hotkey|quit" msgstr "wyjdź" msgid "hotkey|select map" msgstr "wybierz mapÄ™" msgid "hotkey|select small map size" msgstr "wybierz maÅ‚e mapy" msgid "hotkey|select medium map size" msgstr "wybierz Å›rednie mapy" msgid "hotkey|select large map size" msgstr "wybierz duże mapy" msgid "hotkey|select extra large map size" msgstr "wybierz bardzo duże mapy" msgid "hotkey|select all map sizes" msgstr "wybierz wszystkie mapy" #, fuzzy msgid "hotkey|hot seat game" msgstr "zmiana miejsc" msgid "hotkey|battle only game" msgstr "tylko walka" msgid "hotkey|choose the original campaign" msgstr "wybierz oryginalnÄ… kampaniÄ™" msgid "hotkey|choose the expansion campaign" msgstr "wybierz kampaniÄ™ z rozszerzenia" msgid "hotkey|map editor main menu" msgstr "edytor map główne menu" msgid "hotkey|new map menu" msgstr "nowa mapa" msgid "hotkey|load map menu" msgstr "wczytaj mapÄ™" msgid "hotkey|new map from scratch" msgstr "nowa mapa od poczÄ…tku" msgid "hotkey|new random map" msgstr "nowa losowa mapa" #, fuzzy msgid "hotkey|undo last action" msgstr "domyÅ›lna akcja" #, fuzzy msgid "hotkey|redo last action" msgstr "domyÅ›lna akcja" #, fuzzy msgid "hotkey|open game main menu" msgstr "nowa mapa" #, fuzzy msgid "hotkey|toggle passability" msgstr "pokaż/ukryj okno statusu" msgid "hotkey|roland campaign" msgstr "kampania Rolanda" msgid "hotkey|archibald campaign" msgstr "kampania Archibalda" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "kampania Cena LojalnoÅ›ci" msgid "hotkey|voyage home campaign" msgstr "kampania Podróż do Domu" msgid "hotkey|wizard's isle campaign" msgstr "kampania Wyspa Czarodzieja" msgid "hotkey|descendants campaign" msgstr "kampania Potomkowie" msgid "hotkey|select first campaign bonus" msgstr "pierwszy bonus w kampanii" msgid "hotkey|select second campaign bonus" msgstr "drugi bonus w kampanii" msgid "hotkey|select third campaign bonus" msgstr "trzeci bonus w kampanii" msgid "hotkey|view campaign intro" msgstr "obejrzyj intro kampanii" msgid "hotkey|select campaign difficulty" msgstr "stopieÅ„ trudnoÅ›ci kampanii" msgid "hotkey|restart campaign scenario" msgstr "rozpocznij od nowa scenariusz kampanii" msgid "hotkey|world map left" msgstr "porusz bohatera w lewo" msgid "hotkey|world map right" msgstr "porusz bohatera w prawo" msgid "hotkey|world map up" msgstr "porusz bohatera do góry" msgid "hotkey|world map down" msgstr "porusz bohatera w dów" msgid "hotkey|world map up left" msgstr "porusz bohatera do góry w lewo" msgid "hotkey|world map up right" msgstr "porusz bohatera do góry w prawo" msgid "hotkey|world map down left" msgstr "porusz bohatera w dół w lewo" msgid "hotkey|world map down right" msgstr "porusz bohatera w dół w prawo" msgid "hotkey|save game" msgstr "zapisz grÄ™" msgid "hotkey|next hero" msgstr "pokaż nastÄ™pnego bohatera" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "pokaż nastÄ™pnego bohatera" #, fuzzy msgid "hotkey|start hero movement" msgstr "kontynuuj ruch" msgid "hotkey|cast adventure spell" msgstr "rzuć zaklÄ™cie podróżne" msgid "hotkey|put hero to sleep" msgstr "uÅ›pij bohatera" msgid "hotkey|next town" msgstr "nastÄ™pne miasto" msgid "hotkey|end turn" msgstr "zakoÅ„cz turÄ™" msgid "hotkey|file options" msgstr "opcje plików" msgid "hotkey|adventure options" msgstr "opcje przygody" msgid "hotkey|puzzle map" msgstr "mapa puzzli z obelisków" msgid "hotkey|scenario information" msgstr "informacje o scenariuszu" msgid "hotkey|dig for artifact" msgstr "kop w poszukiwaniu Najpotężniejszego Artefaktu" msgid "hotkey|view world" msgstr "pokaż Å›wiat" msgid "hotkey|kingdom summary" msgstr "przeglÄ…d królestwa" msgid "hotkey|default action" msgstr "domyÅ›lna akcja" msgid "hotkey|open focus" msgstr "szczegóły bohatera lub zamku" msgid "hotkey|system options" msgstr "ustawienia systemowe" msgid "hotkey|scroll left" msgstr "skroluj w lewo" msgid "hotkey|scroll right" msgstr "skroluj w prawo" msgid "hotkey|scroll up" msgstr "skroluj w górÄ™" msgid "hotkey|scroll down" msgstr "skroluj w dół" msgid "hotkey|toggle control panel" msgstr "pokaż/ukryj panel sterowania" msgid "hotkey|toggle radar" msgstr "pokaż/ukryj minimapÄ™" msgid "hotkey|toggle buttons" msgstr "pokaż/ukryj przyciski" msgid "hotkey|toggle status" msgstr "pokaż/ukryj okno statusu" msgid "hotkey|toggle icons" msgstr "pokaż/ukryj ikony miast i bohaterów" msgid "hotkey|transfer control to ai" msgstr "przekaż kontrolÄ™ do AI" msgid "hotkey|retreat from battle" msgstr "ucieknij z walki" msgid "hotkey|surrender during battle" msgstr "poddaj walkÄ™" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "włącz/wyłącz automatyczny tryb walki" #, fuzzy msgid "hotkey|quick combat" msgstr "wyjdź" msgid "hotkey|battle options" msgstr "opcje walki" msgid "hotkey|skip turn in battle" msgstr "pomiÅ„ turÄ™ w walce" msgid "hotkey|cast battle spell" msgstr "rzuć zaklÄ™cie bojowe" msgid "hotkey|dwelling level 1" msgstr "siedlisko poziom 1" msgid "hotkey|dwelling level 2" msgstr "siedlisko poziom 2" msgid "hotkey|dwelling level 3" msgstr "siedlisko poziom 3" msgid "hotkey|dwelling level 4" msgstr "siedlisko poziom 4" msgid "hotkey|dwelling level 5" msgstr "siedlisko poziom 5" msgid "hotkey|dwelling level 6" msgstr "siedlisko poziom 6" msgid "hotkey|well" msgstr "studnia" msgid "hotkey|marketplace" msgstr "targowisko" msgid "hotkey|mage guild" msgstr "gildia magów" msgid "hotkey|shipyard" msgstr "stocznia" msgid "hotkey|thieves guild" msgstr "gildia zÅ‚odziei" msgid "hotkey|tavern" msgstr "tawerna" msgid "hotkey|construction screen" msgstr "ekran budowy zamku/miasta" msgid "hotkey|buy all monsters in well" msgstr "rekrutuj wszystkie stworzenia" msgid "hotkey|split stack by half" msgstr "podziel jednostki na pół" msgid "hotkey|split stack by one" msgstr "podziel jednostki po jednej" msgid "hotkey|join stacks" msgstr "połącz jednostki" msgid "hotkey|upgrade troop" msgstr "ulepsz stworzenie" msgid "hotkey|dismiss hero or troop" msgstr "zwolnij bohatera lub stworzenie" #, fuzzy msgid "hotkey|exchange all troops" msgstr "ulepsz stworzenie" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Czy chcesz odzyskać kontrolÄ™ z rÄ…k AI? Efekt zadziaÅ‚a tylko w nastÄ™pnej " "turze." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Czy chcesz przekazać AI kontrolÄ™? Efekt zadziaÅ‚a tylko w nastÄ™pnej turze." #, fuzzy msgid "Default Actions" msgstr "domyÅ›lna akcja" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Mapa Å›wiata" #, fuzzy msgid "Battle Screen" msgstr "Ekran bohatera" #, fuzzy msgid "Town Screen" msgstr "Ekran bohatera" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "Plik z zapisanÄ… grÄ… jest uszkodzony." msgid "Unsupported save format: " msgstr "Niewspierany format zapisanej gry: " msgid "Current game version: " msgstr "Aktualna wersja gry: " msgid "Last supported version: " msgstr "Ostatnia wspierana wersja: " msgid "This file contains a save with an invalid game type." msgstr "Ten plik zawiera zapis z nieprawidÅ‚owym typem gry." #, fuzzy msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Ten plik jest zapisany w wersji gry \"Cena LojalnoÅ›ci\".\n" "Nie można wczytać pliku - do wczytania potrzebujesz \"Ceny LojalnoÅ›ci\"." msgid "This saved game is localized to '" msgstr "Zapisana gra jest w jÄ™zyku '" msgid "' language, but the current language of the game is '" msgstr ", ale bieżący jÄ™zyk to '" msgid "No save files to load." msgstr "Brak zapisanych gier do wczytania." msgid "Hot Seat" msgstr "Na zmianÄ™" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Graj wraz z 2-6 graczami na jednym komputerze, zamieniajÄ…c siÄ™ miejscami gdy " "przychodzi wasza kolej." msgid "A single player game playing out a single map." msgstr "Gra dla jednej osoby na pojedynczej mapie." msgid "Standard Game" msgstr "Gra standardowa" msgid "A single player game playing through a series of maps." msgstr "Gra dla jednej osoby na wielu powiÄ…zanych mapach." msgid "Campaign Game" msgstr "Kampania" msgid "Multi-Player Game" msgstr "Gra dla wielu osób" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Gra dla wielu osób, gdzie kilku graczy walczy przeciw sobie na pojedynczej " "mapie." msgid "fheroes2 Resurrection Team presents" msgstr "fheroes2 Resurrection Team prezentuje" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Witamy w grze Heroes of Might and Magic II na silniku fheroes2! Przed " "rozpoczÄ™ciem wybierz rozdzielczość gry." msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Witamy w grze Heroes of Might and Magic II na silniku fheroes2! Przed " "rozpoczÄ™ciem wybierz rozdzielczość gry." msgid "Greetings!" msgstr "Witaj!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "ZakoÅ„cz grÄ™ Heroes of Might and Magic II i przejdź do systemu operacyjnego." msgid "Credits" msgstr "Autorzy" msgid "View the credits screen." msgstr "Obejrzyj autorów gry." msgid "View the high scores screen." msgstr "Obejrzyj najlepsze wyniki." #, fuzzy msgid "Create new or modify existing maps." msgstr "Wczytaj istniejÄ…cÄ… mapÄ™." msgid "Change language, resolution and settings of the game." msgstr "Wybierz jÄ™zyk, rozdzielczość i ustawienia gry." msgid "Game Settings" msgstr "Ustawienia gry" #, fuzzy msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Brakuje plików video wymaganych dla ekranu wyboru kampanii. Upewnij siÄ™, czy " "wszystkie niezbÄ™dne pliki sÄ… obecne w systemie." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "Kampania Rolanda lub Archibalda z podstawowej wersji gry." msgid "Original Campaign" msgstr "Oryginalna kampania" msgid "Expansion Campaign" msgstr "Kampania z rozszerzenia" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "Jedna z czterech kampani z rozszerzenia Cena LojalnoÅ›ci." msgid "Loading video. Please wait..." msgstr "WczytujÄ™ video. ProszÄ™ czekać..." msgid "Host" msgstr "Gospodarz" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Gospodarz ustala opcje gry. W grze sieciowej może być tylko jeden gospodarz." msgid "Guest" msgstr "Gość" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "Gość czeka, aż gospodarz rozpocznie grÄ™, a nastÄ™pnie włącza siÄ™ do niej " "automatycznie. W grze opartej na połączeniach TCP/IP może być wielu goÅ›ci." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" #, fuzzy msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Gra dla wielu osób, gdzie kilku graczy walczy przeciw sobie na pojedynczej " "mapie." msgid "Battle Only" msgstr "Tylko walka" msgid "Setup and play a battle without loading any map." msgstr "Ustaw i zagraj tylko walkÄ™ bez Å‚adowania mapy." #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Graj wraz z 2-6 graczami na jednym komputerze, zamieniajÄ…c siÄ™ miejscami gdy " "przychodzi wasza kolej." msgid "2 Players" msgstr "2 graczy" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Graj z 2 innymi osobami i opcjonalnie z 4 graczami sterowanymi przez " "komputer." msgid "3 Players" msgstr "3 graczy" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Graj z 3 innymi osobami i opcjonalnie z 3 graczami sterowanymi przez " "komputer." msgid "4 Players" msgstr "4 graczy" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Graj z 4 innymi osobami i opcjonalnie z 2 graczami sterowanymi przez " "komputer." msgid "5 Players" msgstr "5 graczy" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Graj z 5 innymi osobami i opcjonalnie z 1 graczem sterowanym przez komputer." msgid "6 Players" msgstr "6 graczy" msgid "Play with 6 human players." msgstr "Grajcie w sześć osób." #, fuzzy msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Smocze miasto upadÅ‚o! JesteÅ› teraz WÅ‚adcÄ… Smoków." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "UdaÅ‚o ci siÄ™ zdobyć miasto %{name}!\n" "Odnosisz zwyciÄ™stwo." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "UdaÅ‚o ci siÄ™ schwytać wrogiego bohatera - %{name}!\n" "Twoje zadanie zostaÅ‚o wypeÅ‚nione." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Odnajdujesz artefakt (%{name}).\n" "Twoja misja zakoÅ„czyÅ‚a siÄ™ sukcesem." msgid "Ultimate Artifact" msgstr "Najpotężniejszy artefakt" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Wróg zostaÅ‚ pobity.\n" "Twoje wojska tryumfujÄ…!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "W twoim skarbcu udaÅ‚o ci siÄ™ zebrać ponad %{count} szt. zÅ‚ota.\n" "Wszyscy przeciwnicy korzÄ… siÄ™ przed twym bogactwem i potÄ™gÄ…." msgid "Victory!" msgstr "ZwyciÄ™stwo!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "Wróg zdobyÅ‚ miasto %{name} i odnosi zwyciÄ™stwo." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Przeciwnik zebraÅ‚ ponad %{count} szt. zÅ‚ota w swoim skarbcu.\n" "Musisz ukorzyć siÄ™ przed jego bogactwem i potÄ™gÄ…." msgid "You have been eliminated from the game!!!" msgstr "Zostajesz wyeliminowany z gry!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Tracisz bohatera (%{name}).\n" "Nie udaje ci siÄ™ wypeÅ‚nić misji." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Nie udaje ci siÄ™ wypeÅ‚nić misji w okreÅ›lonym czasie. Wszystko stracone." msgid "Defeat!" msgstr "Pokonany!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Bazowy wynik: %{score}\n" "Trudność: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Pokonaj wszystkich bohaterów przeciwnika oraz zajmij wszystkie miasta i " "zamki wrogów." msgid "Your side defeats the opposing side." msgstr "Twoja strona pokonuje przeciwnÄ…." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "UpÅ‚yw czasu (nieukoÅ„czenie gry w okreÅ›lonym czasie.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Musisz pokonać %{enemies}." msgstr[1] "Musisz pokonać sprzymierzonych %{enemies}." msgstr[2] "Musisz pokonać sprzymierzonych %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "Musisz pokonać %{enemies}." msgstr[1] "Ty oraz %{allies} musicie pokonać %{enemies}." msgstr[2] "Ty oraz %{allies} musicie pokonać %{enemies}." msgid "Capture the castle '%{name}'." msgstr "Przejmij zamek '%{name}'." msgid "Capture the town '%{name}'." msgstr "Przejmij miasto '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Pokonaj bohatera '%{name}'." msgid "Find the ultimate artifact." msgstr "Znajdź najpotężniejszy artefakt." msgid "Find the '%{name}' artifact." msgstr "Znajdź '%{name}' artefakt." msgid "Accumulate %{count} gold." msgstr "Zgromadź %{count} zÅ‚ota." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", możesz także wygrać pokonujÄ…c wszystkich bohaterów wroga i zdobywajÄ…c " "wszystkie jego miasta i zamki." msgid "Lose the castle '%{name}'." msgstr "StraciÅ‚eÅ› zamek '%{name}'." msgid "Lose the town '%{name}'." msgstr "StraciÅ‚eÅ› miasto '%{name}'." msgid "Lose the hero: %{name}." msgstr "Przegrywa bohater: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Brak zwyciÄ™stwa do koÅ„ca miesiÄ…ca %{month}, tygodnia %{week}, dnia %{day}." msgid "%{color} player has been vanquished!" msgstr "%{color} gracz zostaje wygnany!" msgid "Major Event!" msgstr "Gracz wygnany!" msgid "Scenario:" msgstr "Scenariusz:" msgid "Game Difficulty:" msgstr "Poziom trudnoÅ›ci:" msgid "Opponents:" msgstr "Przeciwnicy:" msgid "Class:" msgstr "Klasa:" msgid "Rating %{rating}%" msgstr "Poziom %{rating}%" msgid "Click here to select which scenario to play." msgstr "Kliknij tutaj, aby wybrać scenariusz, który chcesz rozegrać." msgid "Scenario" msgstr "Scenariusz" msgid "Game Difficulty" msgstr "Trudność gry" #, fuzzy msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Pozwala ci zmienić poczÄ…tkowy poziom trudnoÅ›ci gry. Wyższy poziom trudnoÅ›ci " "oznacza rozpoczÄ™cie z mniejszÄ… iloÅ›ciÄ… zasobów oraz dodatkowo przekazanie " "dodatkowych surowców graczowi komputerowemu." msgid "Difficulty Rating" msgstr "Ocena trudnoÅ›ci" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Ocena trudnoÅ›ci odzwierciedla kombinacje różnorakich ustawieÅ„ gry. Wartość " "ta zostanie dodana do wyniku koÅ„cowego." msgid "Click to accept these settings and start a new game." msgstr "Kliknij, aby użyć tych ustawieÅ„ i rozpocząć nowÄ… grÄ™." msgid "Click to return to the main menu." msgstr "Kliknij, aby wrócić do głównego menu." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Astrologowie ogÅ‚aszajÄ…, że symbolem tego miesiÄ…ca bÄ™dzie %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Astrologowie ogÅ‚aszajÄ…, że symbolem tego tygodnia bÄ™dzie %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "DziÄ™ki naturalnemu przyrostowi, populacja %{monster} jest podwojona!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "DziÄ™ki naturalnemu przyrostowi populacja %{monster} zwiÄ™ksza siÄ™ o %{count} " "procent!" msgstr[1] "" "DziÄ™ki naturalnemu przyrostowi populacja %{monter} zwiÄ™ksza siÄ™ o %{count} " "procent!" msgstr[2] "" "DziÄ™ki naturalnemu przyrostowi populacja %{monter} zwiÄ™ksza siÄ™ o %{count} " "procent!" # literally, this wont work in Polish. I.e. single: "Feniks", plural "Feniksy", but "Populacja Feniksów zwiÄ™ksza siÄ™ o +3."... msgid "%{monster} growth +%{count}." msgstr "%{monster} zwiÄ™kszajÄ… populacjÄ™ o +%{count}." msgid " All populations are halved." msgstr " Ginie poÅ‚owa populacji królestwa." msgid " All dwellings increase population." msgstr " Populacja caÅ‚ego królestwa zwiÄ™ksza siÄ™." msgid "New Month!" msgstr "Nowy miesiÄ…c!" msgid "New Week!" msgstr "Nowy tydzieÅ„!" msgid "Beware!" msgstr "Uwaga!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color}, zostaÅ‚ ci tylko jeden dzieÅ„ na podbicie jakiegoÅ› miasta, albo " "dojdzie do twego wygnania z tej krainy." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color}, masz tylko %{day} dni na podbicie jakiegoÅ› miasta, albo dojdzie do " "twego wygnania z tej krainy." msgid "%{color} player's turn." msgstr "%{color} gracz - nowa tura." #, fuzzy msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color}, twoje ostatnie miasto zostaÅ‚o podbite. JeÅ›li nie zdoÅ‚asz zdobyć " "innego miasta w ciÄ…gu tygodnia, gra siÄ™ dla ciebie skoÅ„czy." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color}, twoi bohaterowie ciÄ™ opuszczajÄ… i zostajesz wygnany z tej krainy." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "NastÄ™pny bohater" msgid "Select the next Hero." msgstr "Wybierz nastÄ™pnego bohatera." #, fuzzy msgid "Hero Movement" msgstr "Cieniowanie pola" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "PrzeglÄ…d królestwa" #, fuzzy msgid "View a summary of your Kingdom." msgstr "Obejrzyj informacje na temat swego królestwa." msgid "Cast an adventure spell." msgstr "Rzuć zaklÄ™cie podróżne." msgid "End Turn" msgstr "Koniec tury" #, fuzzy msgid "End your turn and let the computer take its turn." msgstr "ZakoÅ„cz swojÄ… turÄ™ i pozwól ruszać siÄ™ komputerowi." msgid "Adventure Options" msgstr "Opcje przygody" msgid "Bring up the adventure options menu." msgstr "Pokazuje menu z opcjami przygody." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Pokazuje menu z opcjami plików, pozwalajÄ…c na: wczytanie gry, zapisanie gry " "rozpoczÄ™cie nowej gry lub wyjÅ›cie z bieżącej gry." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Pokazuje menu z opcjami systemowymi, pozwalajÄ…c na zmianÄ™ ustawieÅ„ gry." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Jeden lub wiÄ™cej bohaterów wciąż może siÄ™ ruszać. Czy na pewno chcesz " "zakoÅ„czyć turÄ™?" msgid "Are you sure you want to quit?" msgstr "Czy na pewno chcesz wyjść?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Czy na pewno chcesz rozpocząć od nowa? (aktualna rozgrywka zostanie " "przerwana)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Czy na pewno chcesz zapisać stan gry z takÄ… samÄ… nazwÄ…?" msgid "Game saved successfully." msgstr "Stan gry zapisany." msgid "There was an issue during saving." msgstr "WystÄ…piÅ‚ problem w czasie zapisu gry." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Czy na pewno chcesz wczytać nowÄ… grÄ™? (aktualna rozgrywka zostanie przerwana)" msgid "Try looking on land!!!" msgstr "Spróbuj na lÄ…dzie!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Poszukiwania Najpotężniejszego Artefaktu nie jest możliwe. Twój bohater nie " "utrzyma go nawet jeÅ›li go znajdzie - wszystkie sloty na artefakty sÄ… zajÄ™te." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Szukanie artefaktu zajmuje caÅ‚y dzieÅ„, spróbuj ponownie jutro." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "Po spÄ™dzeniu wielu godzin na kopaniu, odkryÅ‚eÅ› %{artifact}." msgid "Congratulations!" msgstr "Gratulacje!" msgid "Nothing here. Where could it be?" msgstr "Nic tu nie ma. Gdzie to może być?" msgid "Try searching on clear ground." msgstr "Spróbuj szukać na czystym terenie." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Miniaturowy obraz znanego Å›wiata. Kliknij lewym przyciskiem, aby przesunąć " "widoczny obszar." msgid "Month: %{month} Week: %{week}" msgstr "MiesiÄ…c: %{month} TydzieÅ„: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "Znajdujesz: %{resource}." msgid "Status Window" msgstr "Okno informacyjne" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "W tym oknie umieszczone sÄ… informacje na temat stanu twojego bohatera lub " "królestwa, a także aktualna data." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "W tym oknie umieszczone sÄ… informacje na temat stanu twojego bohatera lub " "królestwa, a także aktualna data. Kliknij tu lewym przyciskiem, aby " "przejrzeć kolejne informacje." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Opcja ta pozwala na zmianÄ™ barw i startowej pozycji gracza. Dany kolor " "zawsze bÄ™dzie rozpoczynać grÄ™ w okreÅ›lonym miejscu. Niektóre pozycje mogÄ… " "być zajÄ™te jedynie przez komputer, a inne tylko przez graczy - ludzi." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Pozwala ci zmienić klasÄ™ gracza. Opcja ta nie zawsze jest aktywna. W " "zależnoÅ›ci od scenariusza, gracz może otrzymać dodatkowe miasta oraz/lub " "bohaterów niezgodne z przynależnÄ… im klasÄ…." msgid "Handicap" msgstr "Utrudnienie" # #, fuzzy msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Tutaj można ustawić utrudnienia dla poszczególnych graczy. Tylko gracze-" "ludzie mogÄ… zostać obÅ‚ożeni utrudnieniami. Taki gracz zaczyna z mniejszÄ… " "iloÅ›ciÄ… zasobów, a także otrzymuje 15% lub 30% mniej zasobów co turÄ™, " "odpowiednio dla utrudnieÅ„ niewielkich i znacznych." msgid "%{color} player" msgstr "%{color} gracz" msgid "No Handicap" msgstr "Brak utrudnieÅ„" #, fuzzy msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Å»adnych ograniczeÅ„ w zasobach poczÄ…tkowych oraz otrzymywanych w każdej turze." msgid "Mild Handicap" msgstr "Niewielkie utrudnienie" # #, fuzzy msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Gracze z niewielkimi utrudnieniami zaczynajÄ… z mniejszÄ… iloÅ›ciÄ… zasobów oraz " "otrzymujÄ… 15% mniej zasobów co turÄ™." msgid "Severe Handicap" msgstr "Znaczne utrudnienia" # #, fuzzy msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Gracze ze znacznymi utrudnieniami zaczynajÄ… z mniejszÄ… iloÅ›ciÄ… zasobów oraz " "otrzymujÄ… o 30% mniej zasobów co turÄ™." msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Ustaw wartość Ataku" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "WyÅ›wietl informacje o %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Obrona" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "SPACJA" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Przychód" msgid "Kingdom Income per day." msgstr "Dzienny przychód królestwa." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Z każdÄ… kolejnÄ… latarniÄ… morskÄ…, która jest pod twojÄ… kontrolÄ…, zwiÄ™ksza siÄ™ " "zasiÄ™g twoich okrÄ™tów." msgid "English" msgstr "Angielski" msgid "French" msgstr "Francuski" msgid "Polish" msgstr "Polski" msgid "German" msgstr "Niemiecki" msgid "Russian" msgstr "Rosyjski" msgid "Italian" msgstr "WÅ‚oski" msgid "Czech" msgstr "Czeski" msgid "Norwegian" msgstr "Norweski" msgid "Belarusian" msgstr "BiaÅ‚oruski" msgid "Bulgarian" msgstr "BuÅ‚garski" msgid "Ukrainian" msgstr "UkraiÅ„ski" msgid "Romanian" msgstr "RumuÅ„ski" msgid "Spanish" msgstr "HiszpaÅ„ski" msgid "Swedish" msgstr "Szwedzki" msgid "Portuguese" msgstr "Portugalski" msgid "Turkish" msgstr "Turecki" msgid "Dutch" msgstr "Holenderski" msgid "Hungarian" msgstr "WÄ™gierski" msgid "Danish" msgstr "DuÅ„ski" msgid "Slovak" msgstr "SÅ‚owacki" msgid "Vietnamese" msgstr "Wietnamski" msgid "Slow" msgstr "Wolno" msgid "Fast" msgstr "Szybko" msgid "Very Fast" msgstr "Bardzo szybko" msgid "Evil" msgstr "ZÅ‚y" msgid "Good" msgstr "Dobry" msgid ", FPS: " msgstr ", FPS: " #, fuzzy msgid "shipAndGraveyard|%{object} robber" msgstr "RabuÅ› %{object}" #, fuzzy msgid "pyramid|%{object} raided" msgstr "SplÄ…drowana %{object}" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitri" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lorda Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Siostra Eliza" msgid "Brother Brax" msgstr "Brat Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " zapewnia ci maksymalne morale" msgid " gives you maximum luck" msgstr " zapewnia ci maksymalne szczęście" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Nie można przenieść KsiÄ™gi Zaklęć" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Nie możesz podnieść tego artefaktu, twój plecak jest peÅ‚ny!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Aby móc rzucać zaklÄ™cia, musisz najpierw kupić KsiÄ™gÄ™ Zaklęć za %{gold} " "sztuk zÅ‚ota." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" "Niestety wyglÄ…da na to, że w chwili obecnej brakuje ci trochÄ™ pieniÄ™dzy." msgid "Do you wish to buy one?" msgstr "Czy chcesz jÄ… kupić?" msgid "%{count} / day" msgstr "%{count} / dzieÅ„" msgid "one" msgstr "jeden" msgid "two" msgstr "dwa" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "Statek zostaje wciÄ…gniÄ™ty przez wir. Część twych wojsk wypada za pokÅ‚ad." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Przeciwnicy, obrażeni odrzuceniem ich propozycji, ruszajÄ… do ataku!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "%{monster} uciekajÄ… w trwodze przed potÄ™gÄ… twojej armii.\n" "Czy chcesz dogonić przeciwników i z nimi walczyć?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "PrzetrzÄ…sajÄ…c obóz wroga odnajdujesz ukrytÄ… skrzyniÄ™ ze skarbami." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "WÅ‚aÅ›ciciel mÅ‚yna oznajmia: \"Wasza dostojność, ciężko pracowaÅ‚em, aby zebrać " "te zasoby. Wróć proszÄ™ po wiÄ™cej w przyszÅ‚ym tygodniu.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "WÅ‚aÅ›ciciel mÅ‚yna oznajmia: \"Wasza dostojność, nie mam wiÄ™cej surowców. Wróć " "proszÄ™ w przyszÅ‚ym tygodniu.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "WÅ‚aÅ›ciciel mÅ‚yna oznajmia: \"Wasza dostojność, ciężko pracowaÅ‚em, aby zebrać " "to zÅ‚oto. Wróć proszÄ™ po wiÄ™cej w przyszÅ‚ym tygodniu.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "WÅ‚aÅ›ciciel mÅ‚yna oznajmia:\n" "\"Wasza dostojność, nie mam wiÄ™cej zÅ‚ota, wróć proszÄ™ w przyszÅ‚ym tygodniu.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Znajdujesz starÄ… szopÄ™.\n" "Przeszukujesz jÄ… i znajdujesz trochÄ™ przydatnych zasobów." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "Stara szopa jest opuszczona. Nie ma w niej nic wartoÅ›ciowego." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Åapiesz leprekauna, który nierozważnie zasnÄ…Å‚ na polu magicznych grzybów.\n" "W zamian za uwolnienie wskazuje ci miejsce ukrycia maÅ‚ego dzbana peÅ‚nego " "kosztownoÅ›ci." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Odnajdujesz magiczny ogród, w którym czÄ™sto bywajÄ… leprekauny i duszki, ale " "dziÅ› nikogo tu nie ma.\n" "Spróbuj przyjść tu za tydzieÅ„." msgid "You come upon the remains of an unfortunate adventurer." msgstr "DotarÅ‚eÅ› do szczÄ…tek pechowego poszukiwacza." msgid "Treasure" msgstr "Skarb" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Po przeszukaniu rozdartego ubrania, znajdujesz %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Nic nie znajdujesz w tym podartym ubraniu." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Odnajdujesz stary wóz pozostawiony przez kupca któremu nie udaÅ‚o siÄ™ dotrzeć " "na bezpieczny teren." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Niestety, inni odkryli go pierwsi przez co wóz jest pusty." msgid "Searching inside, you find the %{artifact}." msgstr "PrzeszukujÄ…c wnÄ™trze, znajdujesz %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "WewnÄ…trz, odkrywasz, że część Å‚adunku jest nadal nienaruszona." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Przeszukujesz wrak i znajdujesz trochÄ™ drewna i trochÄ™ zÅ‚ota." msgid "You search through the flotsam, and find some wood." msgstr "Przeszukujesz wrak i znajdujesz trochÄ™ drewna." msgid "You search through the flotsam, but find nothing." msgstr "Przeszukujesz wrak, lecz nie znajdujesz niczego." msgid "Shrine of the 1st Circle" msgstr "Kaplica pierwszego krÄ™gu" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Trafiasz do maÅ‚ej kaplicy, którÄ… opiekuje siÄ™ grupa akolitów.\n" "W zamian za ochronÄ™ proponujÄ… nauczyć ciÄ™ prostego zaklÄ™cia - '%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Kaplica drugiego krÄ™gu" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Trafiasz do bogato zdobionej kaplicy, którÄ… opiekuje siÄ™ grupa pulchnych " "mnichów.\n" "W zamian za ochronÄ™ proponujÄ… nauczyć ciÄ™ zaklÄ™cia - '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Kaplica trzeciego krÄ™gu" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Zbliżasz siÄ™ do urzÄ…dzonej z przepychem kaplicy, którÄ… opiekuje siÄ™ kilku " "wysokich rangÄ… kapÅ‚anów.\n" "W zamian za ochronÄ™ proponujÄ… nauczyć ciÄ™ skomplikowanego zaklÄ™cia - " "'%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Niestety, twoja mÄ…drość jest zbyt maÅ‚a, by móc zrozumieć to zaklÄ™cie i nie " "jesteÅ› w stanie siÄ™ go nauczyć." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Niestety, znasz już to zaklÄ™cie, wiÄ™c nie możesz nauczyć siÄ™ niczego nowego." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Niestety nie masz KsiÄ™gi Zaklęć, w której można zapisać zaklÄ™cie." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Wchodzisz do chaty i widzisz wiedźmÄ™ uczÄ…cÄ… umiejÄ™tnoÅ›ci %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Kiedy siÄ™ do niej zbliżasz, patrzy na ciebie szklanym okiem,\n" "\"Wiesz już wszystko, co możesz wiedzieć!\" skrzeczy wiedźma. \"A TERAZ " "WYNOCHA Z MOJEGO DOMU!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Kiedy siÄ™ do niej zbliżasz odwraca siÄ™ i mówi,\n" "\"Wiesz już wszystko, czego mogÅ‚am ciÄ™ nauczyć. Nie potrafiÄ™ ci w niczym " "pomóc.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Stara wiedźma mieszkajÄ…ca w chatce na kurzej Å‚apce z sobie tylko znanych " "powodów przekazuje ci wiedzÄ™ o umiejÄ™tnoÅ›ci %{skill}." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" "Pijesz sÅ‚odkÄ… wodÄ™ i czujesz, że w nastÄ™pnej bitwie dopisze ci szczęście." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Pijesz wodÄ™ z zaklÄ™tej fontanny ale nic siÄ™ nie dzieje." msgid "You enter the faerie ring, but nothing happens." msgstr "Wchodzisz do zaklÄ™tego krÄ™gu, ale nic siÄ™ nie dzieje." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Po wejÅ›ciu do tajemniczego zaklÄ™tego krÄ™gu, twoja armia zyskuje szczęście na " "czas kolejnej bitwy." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Odnajdujesz zwietrzaÅ‚y posÄ…g kamiennego bóstwa.\n" "Podobno pocaÅ‚owanie go przynosi szczęście, ale kiedy to czynisz, nic " "specjalnego siÄ™ nie dzieje." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Odnajdujesz zwietrzaÅ‚y posÄ…g kamiennego bóstwa.\n" "Podobno pocaÅ‚owanie go przynosi szczęście, czynisz wiÄ™c to. Kamienny posÄ…g " "jest bardzo zimny." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Syreny w ciszy zachÄ™cajÄ… ciÄ™, by wrócić do nich później po bÅ‚ogosÅ‚awieÅ„stwo." #, fuzzy msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Magiczna uroda syren oczarowuje ciebie i twojÄ… zaÅ‚ogÄ™.\n" "Zapominasz o wszystkich kÅ‚opotach cieszÄ…c siÄ™ chwilÄ….\n" "Na odchodne syreny bÅ‚ogosÅ‚awiÄ… twoje wojska, co ma przynieść ci szczęście " "podczas nastÄ™pnej bitwy." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Zbliżasz siÄ™ do piramidy zbudowanej ku chwale potężnego, starożytnego " "króla.\n" "Korci ciÄ™, by jÄ… przeszukać, ale stare legendy ostrzegajÄ… przed okropnymi " "klÄ…twami i nieumarÅ‚ymi strażnikami.\n" "Czy mimo to chcesz wejść do piramidy?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Pokonawszy potwory, odczytujesz prastary glif na Å›cianie, dziÄ™ki czemu " "poznajesz tajemne zaklÄ™cie - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Niestety nie masz KsiÄ™gi Zaklęć, w której można zapisać zaklÄ™cie." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Niestety, twoja mÄ…drość jest zbyt maÅ‚a, by móc zrozumieć to zaklÄ™cie i nie " "jesteÅ› w stanie siÄ™ go nauczyć." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Natrafiasz na piramidÄ™ zbudowanÄ… ku chwale potężnego, starożytnego króla.\n" "Przeszukujesz jÄ…, ale okazuje siÄ™, że jest zupeÅ‚nie pusta." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Åyk wody z magicznej studni może przywrócić ci wszystkie punkty magii, ale " "masz już ich maksymalnÄ… liczbÄ™." msgid "A second drink at the well in one day will not help you." msgstr "" "Ponowne napicie siÄ™ ze studni w ciÄ…gu jednego dnia nie przyniesie efektów." msgid "A drink from the well has restored your spell points to maximum." msgstr "Åyk wody z magicznej studni przywróciÅ‚ ci wszystkie punkty magii." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Wybacz panie,\" mówi dowódca żoÅ‚nierzy, \"ale wiesz już wszystko, co " "moglibyÅ›my ciÄ™ nauczyć.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "Å»oÅ‚nierze z fortu uczÄ… ciÄ™ kilku sztuczek przydatnych w obronie." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Trafiasz do obozu, w którym wÅ‚aÅ›nie trenujÄ… najemnicy. \"JesteÅ› dla nas zbyt " "trudnym przeciwnikiem,\" mówi ich dowódca. \"Nie nauczymy ciÄ™ niczego nowego." "\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Trafiasz do obozu, w którym wÅ‚aÅ›nie trenujÄ… najemnicy. Å»oÅ‚nierze z obozu " "witajÄ… ciÄ™ i zapraszajÄ… twoich ludzi do wspólnych ćwiczeÅ„." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Wynocha!\", warczy znachor, \"wiesz już wszystko to co ja.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Orkowy znachor mieszkajÄ…cy w tej chatce zwiÄ™ksza twojÄ… wiedzÄ™ na temat magii " "pokazujÄ…c ci, jak wróżyć z kamieni, odczytywać znaki i wieszczyć z " "wnÄ™trznoÅ›ci kurczaka." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Spotykasz grupÄ™ druidów odprawiajÄ…cych obrzÄ™dy przy jednej ze swych dziwnych " "kamiennych struktur. Druidzi w milczeniu odwracajÄ…c siÄ™ od ciebie, " "pokazujÄ…c, że nie mogÄ… nauczyć ciÄ™ niczego nowego." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Spotykasz grupÄ™ druidów odprawiajÄ…cych obrzÄ™dy przy jednej ze swych dziwnych " "kamiennych struktur. Druidzi w milczeniu uczÄ… ciÄ™ nowych sposobów rzucania " "zaklęć." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Ostrożnie zbliżasz siÄ™ do cmentarzyska pradawnych wojowników. Czy chcesz " "przeszukać groby?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "SpÄ™dzasz wiele godzin na przeszukiwaniu grobów, lecz nic nie znajdujesz. Ten " "akt profanacji obniża morale twojej armii." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "Po pokonaniu zombie przeszukujesz groby i znajdujesz coÅ› wartoÅ›ciowego!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "GnijÄ…cy kadÅ‚ub olbrzymiego statku pirackiego poskrzypuje z cicha ocierajÄ…c " "siÄ™ o przybrzeżne skaÅ‚y. Czy chcesz przeszukać wrak?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "SpÄ™dzasz wiele godzin na przeszukiwaniu wraku, lecz nic nie znajdujesz. Ten " "akt profanacji obniża morale twojej armii." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "Po pokonaniu Duchów przeszukujesz wrak i znajdujesz coÅ› wartoÅ›ciowego!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "GnijÄ…cy kadÅ‚ub olbrzymiego statku pirackiego poskrzypuje z cicha ocierajÄ…c " "siÄ™ o przybrzeżne skaÅ‚y. Czy chcesz przeszukać wrak?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "Po pokonaniu szkieletów przeszukujesz wrak i znajdujesz coÅ› wartoÅ›ciowego!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Twoi ludzie zauważajÄ… bojÄ™ nawigacyjnÄ…, co potwierdza, że pÅ‚yniecie dobrym " "kursem." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Twoi ludzie zauważajÄ… bojÄ™ nawigacyjnÄ…, co potwierdza, że pÅ‚yniecie dobrym " "kursem i zwiÄ™ksza ich morale." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Pijesz wodÄ™ w oazie, ale nic siÄ™ nie dzieje. Być może trzeba tu wrócić po " "najbliższej bitwie." #, fuzzy msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "OrzeźwiajÄ…ca woda z oazy wzmacnia ducha twoich żoÅ‚nierzy i dodaje im siÅ‚. " "Możesz dziÅ› jeszcze pokonać spory kawaÅ‚ek drogi." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Zimna woda orzeźwia twoich żoÅ‚nierzy, ale nie dzieje siÄ™ nic specjalnego. " "Może warto przyjść tutaj po walce." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Zimna woda orzeźwia twoich żoÅ‚nierzy i dodaje im siÅ‚. Dzisiaj możesz pokonać " "jeszcze sporo drogi." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Dwukrotna modlitwa przed bitwÄ… w niczym ci nie pomoże. Wróć tu po walce." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Wizyta i modlitwa w Å›wiÄ…tyni podnosi morale twoich oddziałów." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Na schodach altany staje sÄ™dziwy rycerz. \"Wasza dostojność wybaczy, ale " "nauczyÅ‚em jÄ… wszystkiego co umiem.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Na schodach altany staje sÄ™dziwy rycerz. \"Wasza dostojność, aby pomóc ci w " "twych podróżach, nauczÄ™ ciÄ™ wszystkiego co sam umiem.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "WyciÄ…gasz z wody wyczerpanego czÅ‚owieka ratujÄ…c go przed Å›mierciÄ… w zimnych " "wodach oceanu. WdziÄ™czny za ocalenie rozbitek mówi: \"Z chÄ™ciÄ… " "odwdziÄ™czyÅ‚bym siÄ™, dajÄ…c ci artefakt, ale widzÄ™, że nie masz już miejsca w " "swoim ekwipunku.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "UratowaÅ‚eÅ› rozbitka przed utoniÄ™ciem. W podziÄ™ce za uratowanie, dostajesz " "%{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "%{art} - leprekaun proponuje, że sprzeda ci ten artefakt za %{gold} sztuk " "zÅ‚ota." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "%{art} - leprekaun proponuje, że sprzeda ci ten artefakt za %{gold} sztuk " "zÅ‚ota i %{count} jednostki surowca (%{res})." msgid "Do you wish to buy this artifact?" msgstr "Czy chcesz go kupić?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Chcesz zapÅ‚acić leprekaunowi, ale zdajesz sobie sprawÄ™, że ciÄ™ na to nie " "stać. Leprekaun tupie ze zÅ‚oÅ›ciÄ… nóżkÄ… i postanawia ciÄ™ zignorować." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Obrażony odrzuceniem hojnej oferty leprekaun tupie ze zÅ‚oÅ›ciÄ… małą nóżkÄ… i " "postanawia ciÄ™ zignorować." msgid "You've found the artifact: " msgstr "Odnajdujesz artefakt: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Trafiasz do skromnego domku starego pustelnika. Pustelnik oznajmia, że " "%{art} bÄ™dzie należeć do pierwszej mÄ…drej osoby, która go odwiedzi." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Trafiasz do spartaÅ„skiej kwatery starego żoÅ‚nierza. Å»oÅ‚nierz oznajmia ci, że " "%{art} bÄ™dzie należeć do pierwszego prawdziwego dowódcy, który go odwiedzi..." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Napotykasz dziwnÄ… postać z kapeluszem, na którym siedzi sowa. Oznajmia on, " "że skÅ‚onny jest podarować Ci %{art} jeÅ›li masz %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Przypadkowo znajdujesz prastary artefakt. Gdy po niego siÄ™gasz, z krzaków " "wyskakuje banda rozbójników broniÄ…ca swego Å‚upu." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Na polanie zauważasz prastary artefakt. Niestety w pobliżu znajduje siÄ™ jego " "strażnik - %{monster}. Czy chcesz walczyć ze strażnikiem (%{monster}) o " "artefakt?" msgid "Victorious, you take your prize, the %{art}." msgstr "Zwyciężywszy zabierasz swojÄ… zdobycz. Jest to %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "RozsÄ…dek przeważa nad mÄ™stwem i uznajesz, że lepiej dziÅ› uniknąć tej walki." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "SpÄ™dziwszy wiele godzin na próbach wyÅ‚owienia skrzyni wciÄ…gasz jÄ… w koÅ„cu na " "pokÅ‚ad i odkrywasz, iż znajduje siÄ™ w niej %{gold} sztuk zÅ‚ota." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "SpÄ™dziwszy wiele godzin na próbach wyÅ‚owienia skrzyni wciÄ…gasz jÄ… w koÅ„cu na " "pokÅ‚ad i odkrywasz, iż znajduje siÄ™ w niej %{gold} sztuk zÅ‚ota oraz %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "SpÄ™dziwszy wiele godzin na próbach wyÅ‚owienia skrzyni wciÄ…gasz jÄ… w koÅ„cu na " "pokÅ‚ad i odkrywasz, iż jest ona kompletnie pusta." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "PrzeszukujÄ…c okolicÄ™ odnajdujesz ukrytÄ… skrzyniÄ™ ze skarbami. Możesz zabrać " "zÅ‚oto lub oddać je wieÅ›niakom zyskujÄ…c doÅ›wiadczenie. Czy chcesz zatrzymać " "zÅ‚oto?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "PrzeszukujÄ…c okolicÄ™ odnajdujesz ukrytÄ… skrzyniÄ™ zawierajÄ…cÄ… %{gold} sztuk " "zÅ‚ota." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "PrzeszukujÄ…c okolicÄ™ odnajdujesz ukrytÄ… skrzyniÄ™. Okazuje siÄ™, iż kufer " "zawiera starożytny artefakt - %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Znajdujesz wyszczerbionÄ… i zmatowiałą lampÄ™ na wpół zakopanÄ… w ziemi. Czy " "chcesz jÄ… potrzeć?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Przejmujesz kontrolÄ™ nad sklepem miejscowego alchemika. Dostarczać ci bÄ™dzie " "%{count} rtęć dziennie." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Przejmujesz kontrolÄ™ nad tartakiem. Dostarczać ci bÄ™dzie %{count} drewna " "dziennie." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Przejmujesz kontrolÄ™ nad kopalniÄ… rudy. Dostarczać ci bÄ™dzie %{count} rudy " "dziennie." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Przejmujesz kontrolÄ™ nad kopalniÄ… siarki. Dostarczać ci bÄ™dzie %{count} " "siarkÄ™ dziennie." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Przejmujesz kontrolÄ™ nad kopalniÄ… kryształów. Dostarczać ci bÄ™dzie %{count} " "krysztaÅ‚ dziennie." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Przejmujesz kontrolÄ™ nad kopalniÄ… klejnotów. Dostarczać ci bÄ™dzie %{count} " "klejnot dziennie." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Przejmujesz kontrolÄ™ nad kopalniÄ… zÅ‚ota. Dostarczać ci bÄ™dzie %{count} sztuk " "zÅ‚ota dziennie." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Latarnia morska jest teraz pod twojÄ… kontrolÄ… i twoje okrÄ™ty zwiÄ™kszajÄ… " "zasiÄ™g swego ruchu w każdej turze." msgid "You gain control of a %{name}." msgstr "Przejmujesz kontrolÄ™ nad %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Zbliżasz siÄ™ do opuszczonej kopalni zÅ‚ota. WyglÄ…da na to, że jest " "nawiedzona. Czy chcesz do niej wejść?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Pokonujesz Duchy i w kopalni ponownie może rozpocząć siÄ™ wydobycie." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Chce siÄ™ do ciebie dołączyć grupa stworzeÅ„ (%{monster}) pragnÄ…cych chwaÅ‚y. " "Zgadzasz siÄ™?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Gdy zbliżasz siÄ™ do domostwa, zauważasz, że nikogo tam nie ma." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Przeszukujesz ruiny, ale zamieszkujÄ…ce je Meduzy gdzieÅ› zniknęły. Może " "pojawiÄ… siÄ™ w przyszÅ‚ym tygodniu." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Odnajdujesz kilka Meduz żyjÄ…cych wÅ›ród ruin. Gotowe sÄ… dołączyć do twojej " "armii za odpowiedniÄ… cenÄ™. Czy chcesz nająć Meduzy?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Odnajdujesz Nadrzewne Miasto RusaÅ‚ek. Niestety żadna z mieszkajÄ…cych tu " "RusaÅ‚ek nie chce dołączyć do twojej armii. Może w przyszÅ‚ym tygodniu." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Część RusaÅ‚ek żyjÄ…cych w Nadrzewnym MieÅ›cie chce dołączyć za pewnÄ… cenÄ™ do " "twojej armii. Czy chcesz nająć RusaÅ‚ki?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Kolorowe cygaÅ„skie wozy sÄ… puste. Może Rozbójnicy zjawiÄ… siÄ™ tu później." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "DźwiÄ™ki muzyki i Å›miechy prowadzÄ… ciÄ™ do kolorowego taboru, w którym " "mieszkajÄ… Rozbójnicy. Czy chcesz, aby przyłączyli siÄ™ do ciebie?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Stoi tu kilka poszarpanych namiotów smaganych pustynnym wiatrem. SÄ… puste. " "Może Nomadowie przyjdÄ… tu później." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Stoi tu kilka poszarpanych namiotów smaganych pustynnym wiatrem. Czy chcesz, " "by przyłączyli siÄ™ do ciebie Nomadowie?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "W jamie przez chwile bulgocze bÅ‚oto po czym siÄ™ uspokaja." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Gdy zbliżasz siÄ™ do jamy peÅ‚nej bulgoczÄ…cego bÅ‚ota, wygrzebujÄ… siÄ™ z niej " "jakieÅ› istoty i ustawiajÄ… wokół. Jednym gÅ‚osem mówiÄ…: \"Matka Ziemia " "proponuje ci kilka z jej oddziałów. Czy chcesz nająć Å»ywioÅ‚aki Ziemi?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Wchodzisz pomiÄ™dzy biaÅ‚e kolumny, ale nic nie znajdujesz." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "BiaÅ‚e, kamienne kolumny podtrzymujÄ… dach siÄ™gajÄ…cy nieba. Gdy wchodzisz do " "Å›rodka uderza ciÄ™ podmuch powietrza, niemal wypychajÄ…c ciÄ™ na zewnÄ…trz. PrÄ…d " "powietrza materializuje siÄ™ w ledwie widocznÄ… postać. Istota zwraca siÄ™ do " "ciebie gÅ‚oÅ›nym szeptem: \"Po co tu przybywasz? Czy chcesz przywoÅ‚ać siÅ‚y " "powietrza?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Z sadzawki lawy nie wychodzi żaden Å»ywioÅ‚ak Ognia." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Pod konstrukcjÄ…, która sÅ‚uży do utrzymania ciepÅ‚a, widzisz Å»ywioÅ‚aki Ognia " "pÅ‚ywajÄ…ce w strumieniach lawy. Część z nich zbliża siÄ™ do ciebie proponujÄ…c " "swe usÅ‚ugi. Czy chcesz nająć Å»ywioÅ‚aki Ognia?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Przez chwilÄ™ w wodzie widoczna jest jakaÅ› twarz, po czym znika." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Krystaliczne struktury rzucajÄ… cienie na maÅ‚y staw przypominajÄ…cy taflÄ™ " "zwierciadÅ‚a. Patrzysz w wodÄ™ i widzisz odbicie nie swojej twarzy, która " "mówi: \"Czy chcesz przywoÅ‚ać moce wody?\"" msgid "This burial site is deathly still." msgstr "Na cmentarzysku panuje niczym niezmÄ…cona cisza." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "ChcÄ… siÄ™ do ciebie dołączyć niespokojne dusze martwych wojowników, którzy " "szukajÄ… miejsca ostatecznego spoczynku. Czy chcesz nająć Duchy?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "W MieÅ›cie UmarÅ‚ych nie ma życia, ale i Å›mierci tu nie widać. Może nieumarli " "pojawiÄ… siÄ™ tu w przyszÅ‚ym tygodniu." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Część mieszkajÄ…cych tu liszy chce dołączyć za pewnÄ… cenÄ™ do twojej armii. " "Czy chcesz nająć Lisze?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Odnajdujesz ruiny prastarego miasta, zamieszkaÅ‚ego obecnie jedynie przez " "nieumarÅ‚ych. Czy chcesz je przeszukać?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Część z ocalaÅ‚ych Liszy jest pod wrażeniem twojego zwyciÄ™stwa nad nimi i " "proponujÄ… siÄ™ do ciebie przyłączyć, za pewnÄ… cenÄ™. Czy chcesz nająć Lisze?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Odnajdujesz jeden z mostów, pod którymi tak lubiÄ… mieszkać Trolle, ale teraz " "nikogo tu nie ma. Może pojawiÄ… siÄ™ w przyszÅ‚ym tygodniu." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Część Trolli żyjÄ…cych pod mostem chce dołączyć za pewnÄ… cenÄ™ do twojej " "armii. Czy chcesz nająć Trolle?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Trolle żyjÄ…ce pod mostem rzucajÄ… ci wyzwanie. Czy bÄ™dziesz z nimi walczyć?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Pod mostem kuli siÄ™ kilka Trolli. ZbliżajÄ… siÄ™ do ciebie i proponujÄ… " "dołączyć siÄ™ do twojej armii jako najemnicy. Czy chcesz nająć Trolle?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "W tym tygodniu w Smoczym MieÅ›cie nie ma Smoków, które mogÅ‚yby siÄ™ do ciebie " "przyłączyć. Spróbuj ponownie w przyszÅ‚ym tygodniu." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Smocze Miasto zgadza siÄ™ przekazać kilka Smoków do twojej armii. Czy chcesz " "nająć Smoki?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Stoisz przed Smoczym Miastem, miejscem niedostÄ™pnym dla zwykÅ‚ych ludzi. Czy " "chcesz zÅ‚amać tÄ… zasadÄ™ i wyzwać Smoki na pojedynek?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Pokonawszy smoczych czempionów, przywódcy miasta zgadzajÄ… siÄ™ za pewnÄ… cenÄ™ " "przekazać kilka Smoków do twojej armii. Czy chcesz nająć Smoki?" msgid "From the observation tower, you are able to see distant lands." msgstr "Z wieży obserwacyjnej możesz zobaczyć odlegÅ‚e krainy." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Studnia wypeÅ‚nia siÄ™ tylko raz w tygodniu, a w tym tygodniu ktoÅ› już tu byÅ‚." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Napicie siÄ™ ze studni powinno dać ci dwa razy wiÄ™cej punktów magii niż " "zwykle posiadasz, ale już masz tyle punktów." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Åyk wody ze studni przepeÅ‚nia ciÄ™ magicznÄ… mocÄ…! Masz dwa razy wiÄ™cej " "punktów magii niż normalnie." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Lokaj rozpoznaje ciÄ™ i odmawia otwarcia drzwi. \"Mój pan,\" mówi, \"nigdy " "nie uczy dwukrotnie tej samej osoby.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Lokaj prowadzi ciÄ™ do pana tego domostwa, który uczy ciÄ™ czterech " "umiejÄ™tnoÅ›ci potrzebnych każdemu bohaterowi." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Lokaj otwiera drzwi i dokÅ‚adnie ci siÄ™ przyglÄ…da. \"Nie znasz siÄ™ na " "dyplomacji ani nie jesteÅ› na tyle sÅ‚awnym bohaterem, by móc spotkać siÄ™ z " "moim panem,\" mówi. \"Wróć kiedy uznasz, że na to zasÅ‚ugujesz.\"" msgid " and " msgstr " i " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Twoje jednostki, %{monsters}, przechodzÄ… szkolenie u mistrzów walki z tego " "fortu. W twojej armii sÄ… teraz %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Nietypowe przymierze Orków, Ogrów i Krasnoludów proponuje ci wyszkolenie " "(ulepszenie) jednostek, które tu przyprowadzisz. Niestety nie masz oddziałów " "tego typu." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "" "Twoje jednostki, %{monsters}, zostajÄ… ulepszone. W twojej armii sÄ… teraz " "%{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Kowal pracujÄ…cy w kuźni może ulepszyć bronie Pikinierów i Zbrojnych z " "żelaznych na stalowe. Twierdzi także, że zna metodÄ™ zamiany Å»elaznych " "Golemów w Golemy Stalowe. Niestety nie masz żadnej z tych jednostek w swojej " "armii, wiÄ™c nie może ci pomóc." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Kapitan spoglÄ…da na ciebie ze zdziwieniem i mówi:\n" "\"Masz już wszystkie znane przeze mnie mapy. A teraz daj mi poÅ‚owić w " "spokoju.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Emerytowany kapitan mieszkajÄ…cy na przebudowanej platformie rybackiej za " "1000 sztuk zÅ‚ota oferuje ci morskie mapy, które wykonaÅ‚ w czasach mÅ‚odoÅ›ci. " "Czy chcesz je kupić?" #, fuzzy msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Kapitan wzdycha. \"Nie masz dość pieniÄ™dzy, co? Nie myÅ›l sobie, że oddam ci " "moje mapy za darmo!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Natrafiasz na dziwny obelisk wykuty z nieznanego ci kamienia. OglÄ…dajÄ…c " "gÅ‚adkÄ… powierzchniÄ™, zauważasz, iż nieoczekiwanie pojawiajÄ… siÄ™ na niej " "jakieÅ› znaki ukÅ‚adajÄ…ce siÄ™ w mapÄ™. Szybko kopiujesz rysunek, który wkrótce " "znika tak nagle, jak siÄ™ pojawiÅ‚." msgid "You have already been to this obelisk." msgstr "Ten obelisk jest już ci znany." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Drzewo obserwuje twoje przybycie z wyraźnym zadowoleniem. \"Witaj, miÅ‚o ciÄ™ " "znowu widzieć. Mam nadziejÄ™, iż moja wiedza okazaÅ‚a siÄ™ przydatna.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Drzewo obserwuje twoje przybycie z wyraźnym zadowoleniem. \"Ach, strudzony " "podróżnik! Pozwól, że przekażę ci część mojej wielowiekowej wiedzy.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Drzewo obserwuje twoje przybycie z wyraźnym zadowoleniem." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ah, wÄ™drowiec! BÄ™dÄ™ szczęśliwy móc nauczyć CiÄ™ tego czego sam nauczyÅ‚em " "siÄ™ przez te wszystkie lata za drobne %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Zakop je po prostu pod moimi korzeniami.)" msgid "Tears brim in the eyes of the tree." msgstr "Do oczu drzewa napÅ‚ywajÄ… Å‚zy." msgid "\"I need %{count} %{res}.\"" msgstr "\"PotrzebujÄ™ %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "szepcze Å‚kajÄ…c. \"No cóż, wróć kiedy je zdobÄ™dziesz.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "PomiÄ™dzy drzewami siedzi niewidomy prorok. Gdy wyjaÅ›niasz mu cel swej " "podróży, prorok uaktywnia kryszczaÅ‚owÄ… kulÄ™, w której możesz zobaczyć sÅ‚abe " "i mocne punkty twych przeciwników." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "WejÅ›cie do jaskini jest czarne jak smoÅ‚a, a z ciemnoÅ›ci twych nozdrzy " "dochodzi ohydny, siarkowy odór. Czy chcesz wejść?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Jaskinia jest pusta, nie liczÄ…c Å›ladów po straszliwej walce." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "W jaskini znajdujesz potężnego i przerażajÄ…cego demona. \"DziÅ›,\" charczy " "demon, \"bÄ™dziesz walczyć i z pewnoÅ›ciÄ… zginiesz. Ale pozwolÄ™ ci wybrać " "rodzaj Å›mierci. Możesz walczyć ze mnÄ… lub z moimi sÅ‚ugami. Wolisz walczyć z " "moimi sÅ‚ugami?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Demon wydaje z siebie wyzywajÄ…cy okrzyk i atakuje! Po krótkiej bitwie, " "zabijasz potwora i otrzymjesz %{exp} punktów doÅ›wiadczenia." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Demon wykrzykujÄ…c wyzywa CiÄ™ na pojedynek po czym atakuje. Po krótkiej, " "rozpaczliwej walce, zabijasz potwora i otrzymujesz %{exp} punktów " "doÅ›wiadczenia i %{count} zÅ‚ota." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Demon ryczy i rusza do ataku! Po krótkiej i gwaÅ‚townej walce pokonujesz " "potwora, a w głębi jaskini znajdujesz artefakt - %{art}." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "WidzÄ…c, że nie masz %{count} zÅ‚ota, demon rozrywa CiÄ™ swoimi pazurami, a " "ostatniÄ… rzeczÄ… którÄ… widzisz jest czerwona mgieÅ‚ka." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Demon doskakuje do Ciebie i chwyta szponami za gardÅ‚o zanim zdążyÅ‚eÅ› " "wyciÄ…gnąć miecz. \"Twoje życie jest moje\", powiedziaÅ‚. \"Odsprzedam Ci je " "za %{count} zÅ‚ota.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Po pokonaniu sÅ‚ugusów demona, odnajdujesz ukrytÄ… skrzyniÄ™ z %{count} zÅ‚ota." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Gdy wchodzisz do Wieży Alchemika zbliża siÄ™ w TwojÄ… stronÄ™ kulejÄ…cy, " "posiwiaÅ‚y mężczyzna w brunatnej szacie." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Sprawdza twój plecak i zauważa że posiadasz 1 zaklÄ™ty przedmiot." msgstr[1] "" "Sprawdza twój plecak i zauważa że posiadasz %{count} zaklÄ™tych przedmiotów." msgstr[2] "" "Sprawdza twój plecak i zauważa że posiadasz %{count} zaklÄ™tych przedmiotów." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "Za %{gold} zÅ‚ota, alchemik usunie to za Ciebie. Czy chcesz zapÅ‚acić ?" msgstr[1] "" "Za %{gold} zÅ‚ota, alchemik usunie to za Ciebie. Czy chcesz zapÅ‚acić ?" msgstr[2] "" "Za %{gold} zÅ‚ota, alchemik usunie to za Ciebie. Czy chcesz zapÅ‚acić ?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Kiedy zgadasz siÄ™ zapÅ‚acić zażądanÄ… kwotÄ™ w zÅ‚ocie, alchemik chwyta " "przeklÄ™ty artefakt i wrzuca go do swego magicznego kotÅ‚a." msgstr[1] "" "Kiedy zgadasz siÄ™ zapÅ‚acić zażądanÄ… kwotÄ™ w zÅ‚ocie, alchemik chwyta " "przeklÄ™te artefakty i wrzuca je do swego magicznego kotÅ‚a." msgstr[2] "" "Kiedy zgadasz siÄ™ zapÅ‚acić zażądanÄ… kwotÄ™ w zÅ‚ocie, alchemik chwyta " "przeklÄ™te artefakty i wrzuca je do swego magicznego kotÅ‚a." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "SÅ‚yszysz gÅ‚os zza zamkniÄ™tych drzwi, \"Nie masz wystarczajÄ…cej iloÅ›ci zÅ‚ota " "aby zapÅ‚acić za moje usÅ‚ugi.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "SÅ‚yszysz gÅ‚os dobiegajÄ…cy z górnych piÄ™ter wieży: \"Odejdź! Nie mogÄ™ ci " "pomóc!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Główny koniuszy mówi do ciebie: \"Masz Å›wietnego rumaka. Obawiam siÄ™, że nie " "mogÄ™ dać ci lepszego, ale konie twojej kawalerii zdajÄ… siÄ™ pochodzić z nie " "najlepszej hodowli. Mamy wiele szkolony rumaków bojowych, które przydaÅ‚yby " "siÄ™ twoim jeźdźcom. Weź je, nalegam.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Gdy zbliżasz siÄ™ do stajni, wychodzi z niej główny koniuszy prowadzÄ…cy " "piÄ™knego konia bojowego. \"Ten rumak pomoże ci w czasie twych podróży. " "Niestety, po tygodniu jazdy siÄ™ zmÄ™czy. Pozwól, że dam ci również lepsze " "konie dla twych kawalerzystów, bo te wyglÄ…dajÄ… na dość marne.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Podchodzi do ciebie główny koniuszy i mówi. \"Masz już Å›wietnego konia i nie " "dowodzisz niedoÅ›wiadczonÄ… kawaleriÄ…, której mogÅ‚yby siÄ™ przydać nasze " "szkolone rumaki bojowe.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Gdy zbliżasz siÄ™ do stajni, wychodzi z niej główny koniuszy prowadzÄ…cy " "piÄ™knego konia bojowego. \"Ten rumak pomoże ci w czasie twych podróży. " "Niestety osÅ‚abnie w przypadku ciężkiej jazdy, wiÄ™c w przeciÄ…gu tygodnia " "musisz wrócić po nowego konia. Mamy także wiele rumaków bojowych, które " "byÅ‚yby dobre dla kawalerii, ale nie masz z sobÄ… takich oddziałów.\"" msgid "The Arena guards turn you away." msgstr "Strażnicy Areny każą ci odejść." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Zanim pieśń syren ma szansÄ™ dotrzeć do uszu twoich ludzi i zmusić ich do " "wskoczenia w odmÄ™ty, rozkazujesz, aby wszyscy zalepili uszy woskiem." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Chociaż pieśń syren brzmi niesamowicie, twojej zdeterminowanej zaÅ‚odze udaje " "siÄ™ pokonać obezwÅ‚adniajÄ…cÄ… chęć wyskoczenia za burtÄ™." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Nad wodÄ… niesie siÄ™ dziwna, pÅ‚aczliwa pieśń syren. Wielu czÅ‚onków twojej " "zaÅ‚ogi poddaje siÄ™ czarowi pieÅ›ni i skacze za burtÄ™, pogrążajÄ…c siÄ™ na " "zawsze w odmÄ™tach oceanu. To smutne doÅ›wiadczenie daje ci %{exp} pkt. " "doÅ›wiadczenia." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "W gwaÅ‚townym porywie odwagi wyważasz drzwi wiÄ™zienia i uwalniasz zamkniÄ™tego " "w nim bohatera, który w ramach wdziÄ™cznoÅ›ci przysiÄ™ga ci lojalność." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Dowodzisz już %{count} bohaterami, musisz wiÄ™c pozostawić więźnia w jego " "celi, skazujÄ…c go tym samym na powolnÄ… agoniÄ™ w udrÄ™ce." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Wchodzisz do prymitywnej chatki i spotykasz mieszkajÄ…cego w niej magika. " "Opowiada ci o różnych odlegÅ‚ych miejscach, co może okazać siÄ™ pomocne w " "czasie twych podróży." msgid "This eye seems to be intently studying its surroundings." msgstr "Oko wydaje siÄ™ dokÅ‚adnie studiować okolicÄ™." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Zbliżasz siÄ™ do wielkiego sfinksa, który tajemniczo milczy." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Mam dla ciebie zagadkÄ™,\" mówi Sfinks. \"JeÅ›li odpowiesz dobrze, dam ci " "nagrodÄ™. JeÅ›li odpowiesz źle, pożrÄ™ ciÄ™. Podejmujesz moje wyzwanie?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Sfinks zadaje ci nastÄ™pujÄ…cÄ… zagadkÄ™: \n" "\n" "'%{riddle}'\n" "\n" " Twoja odpowiedź?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Twoja odpowiedź jest błędna,\" mówi sfinks z uÅ›miechem. NastÄ™pnie powala " "ciÄ™ Å‚apÄ… i przyciska do ziemi. Po nastÄ™pnym ciosie Å›wiat ciemnieje ci przed " "oczami i nic wiÄ™cej nie pamiÄ™tasz." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Sfinks wyglÄ…da na rozczarowanego i wzdycha \"UdaÅ‚o ci siÄ™ odpowiedzieć na " "mojÄ… zagadkÄ™, wiÄ™c oto twoja nagroda. A teraz odejdź.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Przed tobÄ… wznosi siÄ™ magiczna bariera, blokujÄ…ca ci drogÄ™. Runiczny napis " "gÅ‚osi, \"Wypowiedz sÅ‚owo, a otworzy siÄ™ przejÅ›cie.\"\n" "Gdy wypowiadasz magiczne sÅ‚owo, lÅ›niÄ…ca bariera rozwiewa siÄ™ w powietrzu." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Przed tobÄ… wznosi siÄ™ magiczna bariera, blokujÄ…ca ci drogÄ™. Runiczny napis " "gÅ‚osi, \"Wypowiedz sÅ‚owo, a otworzy siÄ™ przejÅ›cie.\"\n" "Wypowiadasz sÅ‚owo, ale nic siÄ™ nie dzieje." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Wchodzisz do namiotu i widzisz staruszkÄ™ wpatrujÄ…cÄ… siÄ™ w magiczny klejnot. " "SpoglÄ…da na ciebie i mówi: \"W czasie mych podróży wielem siÄ™ dowiedziaÅ‚a o " "tajemnych sztukach magii. Wyrocznia przekazaÅ‚a mi swojÄ… wiedzÄ™. Znam " "odpowiedź, której szukasz.\"" #, fuzzy msgid "No spell book is present." msgstr "Nie posiadasz KsiÄ™gi Zaklęć." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "To zaklÄ™cie kosztuje %{mana} pkt. magii. Nie masz w ogóle many, wiÄ™c nie " "możesz go rzucić." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "To zaklÄ™cie kosztuje %{mana} pkt. magii. Masz tylko %{point} pkt. magii, " "wiÄ™c nie możesz go rzucić." msgid "The spell was not found." msgstr "ZaklÄ™cie nie zostaÅ‚o znalezione." msgid "Only heroes can cast this spell." msgstr "Tylko bohaterowie mogÄ… rzucać to zaklÄ™cie." msgid "This hero is not able to cast adventure spells." msgstr "Twój bohater nie może rzucić żadnego czaru podróżnego." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Twój bohater jest zbyt zmÄ™czony, by rzucić dziÅ› to zaklÄ™cie. Spróbuj " "ponownie jutro." msgid "This spell cannot be cast on a boat." msgstr "To zaklÄ™cie nie może być rzucone z Å‚odzi." msgid "This spell can only be cast near an ocean." msgstr "To zaklÄ™cie może być rzucone tylko przy wodzie." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Nie można rzucić zaklÄ™cia, ponieważ nie ma dostÄ™pnej Å‚odzi oraz nie ma " "miejsca blisko bohatera przy brzegu." msgid "There are no boats available for this spell." msgstr "Nie możesz rzucić zaklÄ™cia, ponieważ nie ma dostÄ™pnej Å‚odzi." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Nie możesz rzucić zaklÄ™cia, ponieważ nie ma miejsca koÅ‚o bohatera przy " "brzegu." #, fuzzy msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Nie posiadasz w tym momencie żadnego miasta lub zamku, z tego powodu nie " "możesz rzucić tego zaklÄ™cia." #, fuzzy msgid "This hero is already in a town, so this spell will have no effect." msgstr "Ten bohater znajduje siÄ™ już w zamku, wiÄ™c nie możesz rzucić zaklÄ™cia." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Najbliższym miastem jest %{town}.\n" "\n" "To miasto jest zajÄ™te przez twojego bohatera %{hero}." msgid "This spell is already in effect." msgstr "To zaklÄ™cie zostaÅ‚o już rzucone." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Å»aden przeciwnik nie ma ani nie może mieć bohatera. Użycie tego zaklÄ™cia nie " "da żadnego rezultatu." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Å»aden przeciwnik nie ma aktualnie bohatera. Użycie tego zaklÄ™cia nie da " "żadnego rezultatu." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Aby zaklÄ™cie 'Wizje' zadziaÅ‚aÅ‚o, musisz znajdować siÄ™ w zasiÄ™gu %{count} pól " "od przeciwnika." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Aby móc rzucić to zaklÄ™cie, musisz stać w wejÅ›ciu do kopalni (tartaki i " "laboratoria nie sÄ… brane pod uwagÄ™)." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "Aby rzucić ten czar, musisz najpierw pokonać duchy strzegÄ…ce kopalni." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Nie przywoÅ‚asz wiÄ™cej Å»ywioÅ‚aków, niż aktualnie strzeże kopalnii. Rzucenie " "tego zaklÄ™cia nie da żadnego rezultatu." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name}, %{race} (poziom %{level})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} (poziom %{level})" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{name}, %{race} (poziom %{level})" #, fuzzy msgid "Hero race:" msgstr "Ekran bohatera" msgid "Are you sure you want to dismiss this Hero?" msgstr "Czy na pewno chcesz zwolnić tego bohatera?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "DoÅ›wiadczenie - informacje" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Pkt. magii" msgid "View Spell Points Info" msgstr "Punkty magii - informacje" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Przegrywa bohater: %{name}." #, fuzzy msgid "Click to change race." msgstr "Kliknij aby przejść do nastÄ™pnego miasta." #, fuzzy msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Wybór luźnej formacji oznacza, że twoja wojska bÄ™dÄ… stać rozproszone wzdÅ‚uż " "pola bitwy, a pomiÄ™dzy oddziaÅ‚ami bÄ™dzie przynajmniej jedno wolne pole." #, fuzzy msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "Wybór zwartej formacji sprawia, że twoja armia zbierze siÄ™ razem poÅ›rodku " "twojej części pola bitwy." msgid "Exit Hero Screen" msgstr "WyjÅ›cie z ekranu bohatera" msgid "You cannot dismiss a hero in a castle" msgstr "Nie możesz zwolnić bohatera w zamku" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Zwolnienie %{name}, %{race}, jest zabronione w tym scenariuszu" msgid "Dismiss %{name} the %{race}" msgstr "Zwolnij bohatera: %{name}, %{race}" msgid "Show previous hero" msgstr "Pokaż poprzedniego bohatera" msgid "Show next hero" msgstr "Pokaż nastÄ™pnego bohatera" msgid "Set army combat formation to 'Spread'" msgstr "Ustaw armiÄ™ w luźnej formacji" msgid "Set army combat formation to 'Grouped'" msgstr "Ustaw armiÄ™ w zwartej formacji" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Kliknij tutaj, aby wybrać scenariusz, który chcesz rozegrać." msgid "Blood Morale" msgstr "Wysokie morale" msgid "%{morale} Morale" msgstr "%{morale} morale" msgid "%{luck} Luck" msgstr "%{luck} szczęście" msgid "Current Luck Modifiers:" msgstr "Obecne modyfikatory szczęścia:" msgid "Current Morale Modifiers:" msgstr "Obecne modyfikatory morale:" msgid "Entire army is undead, so morale does not apply." msgstr "Wszystkie oddziaÅ‚y to nieumarli, na których nie wpÅ‚ywa morale." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Obecne doÅ›wiadczenie %{exp1}.\n" " NastÄ™pny poziom %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Poziom %{level}" #, fuzzy msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} posiada obecnie %{point} pkt. magii z maksimum wynoszÄ…cego %{max}. " "Maksymalna liczba to wartość współczynnika wiedzy pomnożona razy 10. Czasami " "możliwe jest posiadanie wiÄ™kszej liczby punktów magii, dziÄ™ki specjalnym " "wydarzeniom." msgid "%{name1} meets %{name2}" msgstr "Spotkanie: %{name1} i %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Można już w peÅ‚ni zidentyfikować wrogich bohaterów." msgid "Identify Hero" msgstr "Identyfikacja bohatera" msgid "Select town to port to." msgstr "Wybierz miasto docelowe." msgid "Town Portal" msgstr "Miejski Portal" msgid "The creatures are willing to join us!" msgstr "Te stworzenia sÄ… chÄ™tne przyłączyć siÄ™ do nas!" msgid "All the creatures will join us..." msgstr "Wszystkie te stworzenia dołączÄ… do nas..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Jedno stworzenie dołączy do nas..." msgstr[1] "Część tych stworzeÅ„ (%{count}) dołączy do nas..." msgstr[2] "Część tych stworzeÅ„ (%{count}) dołączy do nas..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" " za zapÅ‚atÄ… %{gold} zÅ‚ota." msgid "These weak creatures will surely flee before us." msgstr "Te sÅ‚abowite stworzenia na pewno przed nami ucieknÄ…." msgid "I fear these creatures are in the mood for a fight." msgstr "Obawiam siÄ™, że te stworzenia sÄ… gotowe do walki." #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Twój współczynnik ataku stanowi premiÄ™ dodawanÄ… do ataku każdej jednostki." #, fuzzy msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Twój współczynnik obrony stanowi premiÄ™ dodawanÄ… do obrony każdej jednostki." #, fuzzy msgid "The hero's spell power determines the duration or power of a spell." msgstr "" "Od twojej mocy zaklęć zależy dÅ‚ugość i moc rzucanych przez ciebie czarów." #, fuzzy msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Od wiedzy zależy liczba punktów magii, jakie może posiadać bohater. W " "normalnych warunkach bohater ograniczony jest do 10 punktów magii na każdy " "poziom wiedzy." msgid "Current Modifiers:" msgstr "Aktualne modyfikatory:" msgid "skill|Basic" msgstr "Podstawowa" msgid "skill|Advanced" msgstr "Zaawansowana" msgid "skill|Expert" msgstr "Ekspert" msgid "Pathfinding" msgstr "Znaj. drogi" msgid "Archery" msgstr "Åucznictwo" msgid "Logistics" msgstr "Logistyka" msgid "Scouting" msgstr "Zwiad" msgid "Diplomacy" msgstr "Dyplomacja" msgid "Navigation" msgstr "Nawigacja" msgid "Leadership" msgstr "Dowodzenie" msgid "Wisdom" msgstr "MÄ…drość" msgid "Mysticism" msgstr "Mistycyzm" msgid "Ballistics" msgstr "Balistyka" msgid "Eagle Eye" msgstr "Sokole oko" msgid "Necromancy" msgstr "Nekromancja" msgid "Estates" msgstr "Finanse" msgid "Advanced Archery" msgstr "Zaawansowane Å‚ucznictwo" msgid "Advanced Pathfinding" msgstr "Zaawansowane znaj. drogi" msgid "Basic Archery" msgstr "Podstawowe Å‚ucznictwo" msgid "Basic Pathfinding" msgstr "Podstawowe znaj. drogi" msgid "Expert Pathfinding" msgstr "Mistrzowskie znaj. drogi" msgid "Advanced Logistics" msgstr "Zaawansowana logistyka" msgid "Basic Logistics" msgstr "Podstawowa logistyka" msgid "Basic Scouting" msgstr "Podstawowy zwiad" msgid "Expert Archery" msgstr "Mistrzowskie Å‚ucznictwo" msgid "Expert Logistics" msgstr "Mistrzowska logistyka" msgid "Advanced Diplomacy" msgstr "Zaawansowana dyplomacja" msgid "Advanced Scouting" msgstr "Zaawansowany zwiad" msgid "Basic Diplomacy" msgstr "Podstawowa dyplomacja" msgid "Expert Diplomacy" msgstr "Mistrzowska dyplomacja" msgid "Expert Scouting" msgstr "Mistrzowski zwiad" msgid "Advanced Leadership" msgstr "Zaawansowane dowodzenie" msgid "Advanced Navigation" msgstr "Zaawansowana nawigacja" msgid "Basic Leadership" msgstr "Podstawowe dowodzenie" msgid "Basic Navigation" msgstr "Podstawowa nawigacja" msgid "Expert Navigation" msgstr "Mistrzowska nawigacja" msgid "Advanced Wisdom" msgstr "Zaawansowana mÄ…drość" msgid "Basic Mysticism" msgstr "Podstawowy mistycyzm" msgid "Basic Wisdom" msgstr "Podstawowa mÄ…drość" msgid "Expert Leadership" msgstr "Mistrzowskie dowodzenie" msgid "Expert Wisdom" msgstr "Mistrzowska mÄ…drość" msgid "Advanced Luck" msgstr "Zaawansowane szczęście" msgid "Advanced Mysticism" msgstr "Zaawansowany mistycyzm" msgid "Basic Luck" msgstr "Podstawowe szczęście" msgid "Expert Luck" msgstr "Mistrzowskie szczęście" msgid "Expert Mysticism" msgstr "Mistrzowski mistycyzm" msgid "Advanced Ballistics" msgstr "Zaawansowana balistyka" msgid "Advanced Eagle Eye" msgstr "Zaawansowane sokole oko" msgid "Basic Ballistics" msgstr "Podstawowa balistyka" msgid "Basic Eagle Eye" msgstr "Podstawowe sokole oko" msgid "Expert Ballistics" msgstr "Mistrzowska balistyka" msgid "Advanced Necromancy" msgstr "Zaawansowana nekromancja" msgid "Basic Estates" msgstr "Podstawowe finanse" msgid "Basic Necromancy" msgstr "Podstawowa nekromancja" msgid "Expert Eagle Eye" msgstr "Mistrzowskie sokole oko" msgid "Expert Necromancy" msgstr "Mistrzowska nekromancja" msgid "Advanced Estates" msgstr "Zaawansowane finanse" msgid "Expert Estates" msgstr "Mistrzowskie finanse" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "O %{count} procent zmniejsza ograniczenie ruchu podczas poruszania siÄ™ po " "trudnym terenie." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "" "Eliminuje ograniczenie ruchu podczas poruszania siÄ™ po trudnym terenie." #, fuzzy msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} eliminuje %{count} procent kary dla twoich oddziałów strzelajÄ…cych " "przez przeszkody (np. zamkowe mury)" #, fuzzy msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "PowiÄ™ksza ilość punktów ruchu bohatera o %{count} percent." #, fuzzy msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "ZwiÄ™ksza pole widzenia bohatera o %{count}." msgstr[1] "ZwiÄ™ksza pole widzenia bohatera o %{count}." msgstr[2] "ZwiÄ™ksza pole widzenia bohatera o %{count}." #, fuzzy msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "Pozwala negocjować ze sÅ‚abszymi przeciwnikami. " #, fuzzy msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "OkoÅ‚o %{count} procent stworzeÅ„ zaproponuje dołączenie do twojej armii." #, fuzzy msgid "All of the creatures may offer to join the hero." msgstr "Wszystkie stworzenia mogÄ… zaproponować dołączenie do twojej armii." #, fuzzy msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "%{name} redukuje koszt kapitulacji do %{count} procent caÅ‚ego kosztu armii " "bÄ™dÄ…cej w posiadaniu." #, fuzzy msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "PowiÄ™ksza ilość punktów ruchu bohatera na wodzie o %{count} procent." #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "ZwiÄ™ksza morale wszystkich oddziałów bohatera o %{count}." #, fuzzy msgid "%{skill} allows the hero to learn third level spells." msgstr "" "Pozwala twojemu bohaterowi na zrozumienie i poznanie zaklęć trzeciego " "poziomu." #, fuzzy msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" "Pozwala twojemu bohaterowi na zrozumienie i poznanie zaklęć czwartego " "poziomu." #, fuzzy msgid "%{skill} allows the hero to learn fifth level spells." msgstr "Pozwala nauczyć siÄ™ twojemu bohaterowi zaklęć piÄ…tego poziomu." #, fuzzy msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} regeneruje %{count} punkt magii twojego bohatera na dzieÅ„." msgstr[1] "" "%{skill} regeneruje %{count} punkty magii twojego bohatera na dzieÅ„." msgstr[2] "" "%{skill} regeneruje %{count} punktów magii twojego bohatera na dzieÅ„." #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "ZwiÄ™ksza szczęście bohatera o %{count}." #, fuzzy msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "StrzaÅ‚y z katapulty majÄ… wiÄ™kszÄ… szansÄ… na trafienie i uszkodzenie zamkowych " "murów." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "Katapulta otrzymuje dodatkowy strzaÅ‚, a każdy ma wiÄ™kszÄ… szansÄ™ na trafienie " "i uszkodzenie zamkowych murów." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "Katapulta otrzymuje dodatkowy strzaÅ‚, a każdy automatycznie niszczy wszelkie " "mury, za wyjÄ…tkiem fortyfikacji w zamku Rycerza." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "Daje Twojemu bohaterowi %{count} procent szans na nauczenie siÄ™ dowolnego " "czaru 1-go i 2-go poziomu rzucanego przez przeciwnika." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "Daje Twojemu bohaterowi %{count} procent szans na nauczenie siÄ™ dowolnego " "czaru 3-go (lub poniżej) poziomu rzucanego przez przeciwnika." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "Daje Twojemu bohaterowi %{count} procent szans na nauczenie siÄ™ dowolnego " "czaru 4-go poziomu (lub poniżej) rzucanego przez przeciwnika." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "Pozwala wskrzesić w postaci Szkieletów %{count} procent polegÅ‚ych w walce " "stworzeÅ„." #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Każdej tury twój bohater dostarcza królestwu %{count} sztuk zÅ‚ota jako " "dochód z nieruchomoÅ›ci." msgid "Blue" msgstr "Niebieski" msgid "Green" msgstr "Zielony" msgid "Red" msgstr "Czerwony" msgid "Yellow" msgstr "Żółty" msgid "Orange" msgstr "PomaraÅ„czowy" msgid "Purple" msgstr "Fioletowy" msgid "barrier|Aqua" msgstr "seledynowy" msgid "barrier|Blue" msgstr "niebieski" msgid "barrier|Brown" msgstr "brÄ…zowy" msgid "barrier|Gold" msgstr "zÅ‚oty" msgid "barrier|Green" msgstr "zielony" msgid "barrier|Orange" msgstr "pomaraÅ„czowy" msgid "barrier|Purple" msgstr "fioletowy" msgid "barrier|Red" msgstr "czerwony" msgid "tent|Aqua" msgstr "Seledynowy" msgid "tent|Blue" msgstr "Niebieski" msgid "tent|Brown" msgstr "BrÄ…zowy" msgid "tent|Gold" msgstr "ZÅ‚oty" msgid "tent|Green" msgstr "Zielony" msgid "tent|Orange" msgstr "PomaraÅ„czowy" msgid "tent|Purple" msgstr "Fioletowy" msgid "tent|Red" msgstr "Czerwony" msgid "Experience" msgstr "DoÅ›wiadczenie" #, fuzzy msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "DoÅ›wiadczenie pozwala twoim bohaterom awansować na wyższe poziomy, i co za " "tym idzie, ulepszać ich umiejÄ™tnoÅ›ci." msgid "Hero/Stats" msgstr "Bohater/Statystyki" msgid "Skills" msgstr "UmiejÄ™tnoÅ›ci" msgid "Town/Castle" msgstr "Miasto/Zamek" msgid "Garrison" msgstr "Garnizon" msgid "Gold Per Day:" msgstr "ZÅ‚ota na dzieÅ„:" msgid "View Heroes." msgstr "Pokaż bohaterów." msgid "Towns/Castles" msgstr "Miasta/Zamki" msgid "View Towns and Castles." msgstr "Pokaż miasta i zamki." msgid "luck|Cursed" msgstr "Beznadziejne" msgid "luck|Awful" msgstr "Bardzo niskie" msgid "luck|Bad" msgstr "Niskie" msgid "luck|Normal" msgstr "Normalne" msgid "luck|Good" msgstr "Spore" msgid "luck|Great" msgstr "Wielkie" msgid "luck|Irish" msgstr "PrzysÅ‚owiowe" #, fuzzy msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Niskie szczęście na polu bitwy oznacza, że twoje jednostki zadawać bÄ™dÄ… " "poÅ‚owÄ™ obrażeÅ„." #, fuzzy msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Normalne szczęście oznacza, iż twoje jednostki nigdy nie bÄ™dÄ… otrzymywać " "premii na polu bitwy, ale też nie bÄ™dÄ… miaÅ‚y pecha." #, fuzzy msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Wysokie szczęście sprawia, że twoim oddziaÅ‚om czasami udaje siÄ™ zadać " "podwójne obrażenia." msgid "morale|Treason" msgstr "Tragiczne" msgid "morale|Awful" msgstr "Bardzo niskie" msgid "morale|Poor" msgstr "Niskie" msgid "morale|Normal" msgstr "ZwykÅ‚e" msgid "morale|Good" msgstr "Wysokie" msgid "morale|Great" msgstr "Bardzo wysokie" msgid "morale|Blood!" msgstr "Krwi!" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "Niskie morale może sprawić, że twoje oddziaÅ‚y zastygnÄ… w bezruchu podczas " "walki." #, fuzzy msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "ZwykÅ‚e morale oznacza, że twoje wojska nigdy nie otrzymajÄ… dodatkowego ataku " "ani też nie zastygnÄ… w bezruchu podczas walki." #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "Wysokie morale może sprawić, że twoje oddziaÅ‚y otrzymajÄ… dodatkowy atak " "podczas walki." msgid "Knight" msgstr "Rycerz" msgid "Barbarian" msgstr "BarbarzyÅ„ca" msgid "Sorceress" msgstr "Czarodziejka" msgid "Warlock" msgstr "Czarnoksiężnik" msgid "Wizard" msgstr "Czarodziej" msgid "Necromancer" msgstr "Nekromanta" msgid "Multi" msgstr "Różne" msgid "doubleLined|Knight" msgstr "Rycerz" msgid "doubleLined|Barbarian" msgstr "" "Barba-\n" "rzyÅ„ca" msgid "doubleLined|Sorceress" msgstr "" "Czaro-\n" "dziejka" msgid "doubleLined|Warlock" msgstr "" "Czarno-\n" "księżnik" msgid "doubleLined|Wizard" msgstr "Czarodziej" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Nekro-\n" "manta" msgid "doubleLinedRace|Multi" msgstr "Różne" msgid "doubleLinedRace|Random" msgstr "Losowo" msgid "speed|Standing" msgstr "Stoi" msgid "speed|Crawling" msgstr "PeÅ‚za" msgid "speed|Very Slow" msgstr "Bardzo niska" msgid "speed|Slow" msgstr "Niska" msgid "speed|Average" msgstr "Åšrednia" msgid "speed|Fast" msgstr "Duża" msgid "speed|Very Fast" msgstr "Bardzo duża" msgid "speed|Ultra Fast" msgstr "Super duża" msgid "speed|Blazing" msgstr "Ogromna" msgid "speed|Instant" msgstr "BÅ‚yskawica" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Wiewiórka" msgid "week|Rabbit" msgstr "Królik" msgid "week|Gopher" msgstr "Åšwistak" msgid "week|Badger" msgstr "Borsuk" msgid "week|Rat" msgstr "Szczur" msgid "week|Eagle" msgstr "OrzeÅ‚" msgid "week|Weasel" msgstr "Åasica" msgid "week|Raven" msgstr "Kruk" msgid "week|Mongoose" msgstr "Mangusta" msgid "week|Dog" msgstr "Pies" msgid "week|Aardvark" msgstr "Mrówkojad" msgid "week|Lizard" msgstr "Jaszczurka" msgid "week|Tortoise" msgstr "Żółw" msgid "week|Hedgehog" msgstr "Jeż" msgid "week|Condor" msgstr "Kondor" msgid "week|Ant" msgstr "Mrówka" msgid "week|Grasshopper" msgstr "Åšwierszcz" msgid "week|Dragonfly" msgstr "Ważka" msgid "week|Spider" msgstr "PajÄ…k" msgid "week|Butterfly" msgstr "Motyl" msgid "week|Bumblebee" msgstr "Trzmiel" msgid "week|Locust" msgstr "SzaraÅ„cza" msgid "week|Earthworm" msgstr "Dżdżownica" msgid "week|Hornet" msgstr "SzerszeÅ„" msgid "week|Beetle" msgstr "Å»uk" msgid "week|PLAGUE" msgstr "PLAGA" msgid "week|Unnamed" msgstr "Nieznane" msgid "Desert" msgstr "Pustynia" msgid "Snow" msgstr "Åšnieg" msgid "Wasteland" msgstr "WyschniÄ™ty" msgid "Beach" msgstr "Plaża" msgid "Lava" msgstr "Lawa" msgid "Dirt" msgstr "PyÅ‚" msgid "Grass" msgstr "Trawa" msgid "Ocean" msgstr "Ocean" msgid "maps|Small" msgstr "MaÅ‚e" msgid "maps|Medium" msgstr "Åšrednie" msgid "maps|Large" msgstr "Duże" msgid "maps|Extra Large" msgstr "Bardzo duże" msgid "maps|Custom Size" msgstr "Inny rozmiar" msgid "Ore Mine" msgstr "Kopalnia rudy" msgid "Sulfur Mine" msgstr "Kopalnia siarki" msgid "Crystal Mine" msgstr "Kopalnia kryształów" msgid "Gems Mine" msgstr "Kopalnia klejnotów" msgid "Gold Mine" msgstr "Kopalnia zÅ‚ota" msgid "Mine" msgstr "Kopalnia" msgid "Burma shave." msgstr "WuTeKa." msgid "Next sign 50 miles." msgstr "NastÄ™pny znak za 50 mil." msgid "See Rock City." msgstr "Zobacz miasto Roków." msgid "This space for rent." msgstr "Miejsce do wynajÄ™cia." msgid "No object" msgstr "Brak obiektu" msgid "Alchemist Lab" msgstr "Laboratorium" msgid "Sign" msgstr "Drogowskaz" msgid "Buoy" msgstr "Boja" msgid "Skeleton" msgstr "Szkielet" msgid "Daemon Cave" msgstr "Jaskinia demona" msgid "Treasure Chest" msgstr "Skrzynia ze skarbem" msgid "Faerie Ring" msgstr "ZaklÄ™ty krÄ…g" msgid "Campfire" msgstr "Obozowisko" msgid "Fountain" msgstr "Fontanna" msgid "Gazebo" msgstr "Altana" msgid "Genie Lamp" msgstr "Lampa dżinna" msgid "Archer's House" msgstr "Dom Å‚uczników" msgid "Goblin Hut" msgstr "Chata Goblinów" msgid "Dwarf Cottage" msgstr "Domek krasnoludów" msgid "Peasant Hut" msgstr "ChÅ‚opska chata" msgid "Stables" msgstr "Stajnie" msgid "Alchemist's Tower" msgstr "Wieża alchemika" msgid "Event" msgstr "Zdarzenie" msgid "Dragon City" msgstr "Smocze Miasto" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Latarnia morska" msgstr[1] "Latarnie morskie" msgstr[2] "Latarni morskich" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "MÅ‚yn wodny" msgstr[1] "MÅ‚yny wodne" msgstr[2] "MÅ‚ynów wodnych" msgid "Monster" msgstr "Potwór" msgid "Obelisk" msgstr "Obelisk" msgid "Oasis" msgstr "Oaza" msgid "Resource" msgstr "Surowiec" msgid "Sawmill" msgstr "Tartak" msgid "Oracle" msgstr "Wyrocznia" msgid "Shrine of the First Circle" msgstr "Kaplica pierwszego krÄ™g" msgid "Shipwreck" msgstr "Wrak" msgid "Sea Chest" msgstr "Skrzynia" msgid "Desert Tent" msgstr "Namiot na pustyni" msgid "Stone Liths" msgstr "GÅ‚azy" msgid "Wagon Camp" msgstr "Tabor" msgid "Hut of the Magi" msgstr "Chata maga" msgid "Whirlpool" msgstr "Wir" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Wiatrak" msgstr[1] "Wiatraki" msgstr[2] "Wiatraków" msgid "Mermaid" msgstr "Syrena" msgid "Boat" msgstr "Åódź" msgid "Random Ultimate Artifact" msgstr "Losowy najpotężniejszy artefakt" msgid "Random Artifact" msgstr "Losowy artefakt" msgid "Random Resource" msgstr "Losowe zasoby" msgid "Random Monster" msgstr "Losowy potwór" msgid "Random Town" msgstr "Losowe miasto" msgid "Random Castle" msgstr "Losowy zamek" msgid "Eye of the Magi" msgstr "Oko maga" msgid "Random Monster - weak" msgstr "Losowy potwór - sÅ‚aby" msgid "Random Monster - medium" msgstr "Losowy potwór - Å›redni" msgid "Random Monster - strong" msgstr "Losowy potwór - silny" msgid "Random Monster - very strong" msgstr "Losowy potwór - bardzo silny" #, fuzzy msgid "Hero" msgstr "Bohaterowie" msgid "Nothing Special" msgstr "Nic specjalnego" msgid "Mossy Rock" msgstr "MchÅ‚a skaÅ‚a" msgid "Watch Tower" msgstr "Wieża strażnicza" msgid "Tree House" msgstr "Dom na drzewie" msgid "Tree City" msgstr "Nadrzewne miasto" msgid "Ruins" msgstr "Ruiny" msgid "Fort" msgstr "Fort" msgid "Abandoned Mine" msgstr "Opuszczona kopalnia" msgid "Sirens" msgstr "Syreny" msgid "Standing Stones" msgstr "KrÄ…g kamieni" msgid "Idol" msgstr "Bożek" msgid "Tree of Knowledge" msgstr "Drzewo Wiedzy" msgid "Witch Doctor's Hut" msgstr "Chatka znachora" msgid "Temple" msgstr "ÅšwiÄ…tynia" msgid "Hill Fort" msgstr "Fort na wzgórzu" msgid "Halfling Hole" msgstr "Norka nizioÅ‚ków" msgid "Mercenary Camp" msgstr "Obóz najemników" msgid "Shrine of the Second Circle" msgstr "Kaplica drugiego krÄ™gu" msgid "Shrine of the Third Circle" msgstr "Kaplica trzeciego krÄ™gu" msgid "City of the Dead" msgstr "Miasto UmarÅ‚ych" msgid "Sphinx" msgstr "Sfinks" msgid "Wagon" msgstr "Wóz" msgid "Tar Pit" msgstr "SmoÅ‚a" msgid "Artesian Spring" msgstr "Studnia artezyjska" msgid "Troll Bridge" msgstr "Most trolli" msgid "Watering Hole" msgstr "ŹródÅ‚o" msgid "Witch's Hut" msgstr "Chatka wiedźmy" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Szopa" msgid "Magellan's Maps" msgstr "Mapy Magellana" msgid "Flotsam" msgstr "SzczÄ…tki statku" msgid "Derelict Ship" msgstr "Opuszczony statek" msgid "Shipwreck Survivor" msgstr "OcalaÅ‚y rozbitek" msgid "Bottle" msgstr "Butelka" msgid "Magic Well" msgstr "Magiczna studnia" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Magiczny ogród" msgstr[1] "Magiczne ogrody" msgstr[2] "Magicznych ogrodów" msgid "Observation Tower" msgstr "Wieża obserwacyjna" msgid "Freeman's Foundry" msgstr "Odlewnia" msgid "Reefs" msgstr "Rafy" msgid "Volcano" msgstr "Wulkan" msgid "Flowers" msgstr "Kwiaty" msgid "Rock" msgstr "KamieÅ„" msgid "Water Lake" msgstr "Jezioro" msgid "Mandrake" msgstr "Mandragora" msgid "Dead Tree" msgstr "Martwe drzewo" msgid "Stump" msgstr "Pieniek" msgid "Crater" msgstr "Krater" msgid "Cactus" msgstr "Kaktus" msgid "Mound" msgstr "Kopiec" msgid "Dune" msgstr "Wydma" msgid "Lava Pool" msgstr "Jezioro lawy" msgid "Shrub" msgstr "Krzak" msgid "Barrow Mounds" msgstr "Kurhany" msgid "Random Artifact - Treasure" msgstr "Losowy artefakt - skarb" msgid "Random Artifact - Minor" msgstr "Losowy artefakt - mniejszy" msgid "Random Artifact - Major" msgstr "Losowy artefakt - wiÄ™kszy" msgid "Barrier" msgstr "Bariera" msgid "Traveller's Tent" msgstr "Namiot podróżnika" msgid "Jail" msgstr "WiÄ™zienie" msgid "Fire Summoning Altar" msgstr "OÅ‚tarz Ognia" msgid "Air Summoning Altar" msgstr "OÅ‚tarz Powietrza" msgid "Earth Summoning Altar" msgstr "OÅ‚tarz Ziemi" msgid "Water Summoning Altar" msgstr "OÅ‚tarz Wody" #, fuzzy msgid "Swampy Lake" msgstr "Bagno" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "Nieznane potwory" msgid "Unknown Monster" msgstr "Nieznany potwór" msgid "Peasant" msgstr "ChÅ‚op" msgid "Peasants" msgstr "ChÅ‚opi" msgid "Archer" msgstr "Åucznik" msgid "Archers" msgstr "Åucznicy" msgid "Ranger" msgstr "Åowca" msgid "Rangers" msgstr "Åowcy" msgid "Pikeman" msgstr "Pikinier" msgid "Pikemen" msgstr "Pikinierzy" msgid "Veteran Pikeman" msgstr "Weteran" msgid "Veteran Pikemen" msgstr "Weterani" msgid "Swordsman" msgstr "Zbrojny" msgid "Swordsmen" msgstr "Zbrojni" msgid "Master Swordsman" msgstr "Mistrz Miecza" msgid "Master Swordsmen" msgstr "Mistrzowie Miecza" msgid "Cavalries" msgstr "Konni" msgid "Cavalry" msgstr "Konny" msgid "Champion" msgstr "Czempion" msgid "Champions" msgstr "Czempioni" msgid "Paladin" msgstr "Paladyn" msgid "Paladins" msgstr "Paladyni" msgid "Crusader" msgstr "Krzyżowiec" msgid "Crusaders" msgstr "Krzyżowcy" msgid "Goblin" msgstr "Goblin" msgid "Goblins" msgstr "Gobliny" msgid "Orc" msgstr "Ork" msgid "Orcs" msgstr "Orkowie" msgid "Orc Chief" msgstr "Ork Wojownik" msgid "Orc Chiefs" msgstr "Orkowie Wojownicy" msgid "Wolf" msgstr "Wilk" msgid "Wolves" msgstr "Wilki" msgid "Ogre" msgstr "Ogr" msgid "Ogres" msgstr "Ogry" msgid "Ogre Lord" msgstr "Wielki Ogr" msgid "Ogre Lords" msgstr "Wielkie Ogry" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Trolle" msgid "War Troll" msgstr "Troll Bojowy" msgid "War Trolls" msgstr "Trolle Bojowe" msgid "Cyclopes" msgstr "Cyklopy" msgid "Cyclops" msgstr "Cyklop" msgid "Sprite" msgstr "RusaÅ‚ka" msgid "Sprites" msgstr "RusaÅ‚ki" msgid "Dwarf" msgstr "Krasnolud" msgid "Dwarves" msgstr "Krasnoludy" msgid "Battle Dwarf" msgstr "Krasnolud Wojownik" msgid "Battle Dwarves" msgstr "Krasnoludzcy Wojownicy" msgid "Elf" msgstr "Elf" msgid "Elves" msgstr "Elfy" msgid "Grand Elf" msgstr "Wysoki Elf" msgid "Grand Elves" msgstr "Wysokie Elfy" msgid "Druid" msgstr "Druid" msgid "Druids" msgstr "Druidzi" msgid "Greater Druid" msgstr "Wielki Druid" msgid "Greater Druids" msgstr "Wielcy Druidzi" msgid "Unicorn" msgstr "Jednorożec" msgid "Unicorns" msgstr "Jednorożce" msgid "Phoenix" msgstr "Feniks" msgid "Phoenixes" msgstr "Feniksy" msgid "Centaur" msgstr "Centaur" msgid "Centaurs" msgstr "Centaury" msgid "Gargoyle" msgstr "Gargulec" msgid "Gargoyles" msgstr "Gargulce" msgid "Griffin" msgstr "Gryf" msgid "Griffins" msgstr "Gryfy" msgid "Minotaur" msgstr "Minotaur" msgid "Minotaurs" msgstr "Minotaury" msgid "Minotaur King" msgstr "Królewski Minotaur" msgid "Minotaur Kings" msgstr "Królewskie Minotaury" msgid "Hydra" msgstr "Hydra" msgid "Hydras" msgstr "Hydry" msgid "Green Dragon" msgstr "Zielony Smok" msgid "Green Dragons" msgstr "Zielone Smoki" msgid "Red Dragon" msgstr "Czerwony Smok" msgid "Red Dragons" msgstr "Czerwone Smoki" msgid "Black Dragon" msgstr "Czarny Smok" msgid "Black Dragons" msgstr "Czarne Smoki" msgid "Halfling" msgstr "NizioÅ‚ek" msgid "Halflings" msgstr "NizioÅ‚ki" msgid "Boar" msgstr "Dzik" msgid "Boars" msgstr "Dziki" msgid "Iron Golem" msgstr "Å»elazny Golem" msgid "Iron Golems" msgstr "Å»elazne Golemy" msgid "Steel Golem" msgstr "Stalowy Golem" msgid "Steel Golems" msgstr "Stalowe Golemy" msgid "Roc" msgstr "Rok" msgid "Rocs" msgstr "Roki" msgid "Mage" msgstr "Mag" msgid "Magi" msgstr "Magowie" msgid "Archmage" msgstr "Arcymag" msgid "Archmagi" msgstr "Arcymagowie" msgid "Giant" msgstr "Olbrzym" msgid "Giants" msgstr "Olbrzymy" msgid "Titan" msgstr "Tytan" msgid "Titans" msgstr "Tytani" msgid "Skeletons" msgstr "Szkielety" msgid "Zombie" msgstr "Zombie" msgid "Zombies" msgstr "Zombie" msgid "Mutant Zombie" msgstr "Zmutowany Zombie" msgid "Mutant Zombies" msgstr "Zmutowane Zombie" msgid "Mummies" msgstr "Mumie" msgid "Mummy" msgstr "Mumia" msgid "Royal Mummies" msgstr "Królewskie Mumie" msgid "Royal Mummy" msgstr "Królewska Mumia" msgid "Vampire" msgstr "Wampir" msgid "Vampires" msgstr "Wampiry" msgid "Vampire Lord" msgstr "Wampirzy Lord" msgid "Vampire Lords" msgstr "Wampirzy Lordowie" msgid "Lich" msgstr "Lisz" msgid "Liches" msgstr "Lisze" msgid "Power Lich" msgstr "Potężny Lisz" msgid "Power Liches" msgstr "Potężne Lisze" msgid "Bone Dragon" msgstr "KoÅ›ciany Smok" msgid "Bone Dragons" msgstr "KoÅ›ciane Smoki" msgid "Rogue" msgstr "Rozbójnik" msgid "Rogues" msgstr "Rozbójnicy" msgid "Nomad" msgstr "Nomada" msgid "Nomads" msgstr "Nomadowie" msgid "Ghost" msgstr "Duch" msgid "Ghosts" msgstr "Duchy" msgid "Genie" msgstr "Dżinn" msgid "Genies" msgstr "Dżinny" msgid "Medusa" msgstr "Meduza" msgid "Medusas" msgstr "Meduzy" msgid "Earth Elemental" msgstr "Å»ywioÅ‚ak Ziemi" msgid "Earth Elementals" msgstr "Å»ywioÅ‚aki Ziemi" msgid "Air Elemental" msgstr "Å»ywioÅ‚ak Powietrza" msgid "Air Elementals" msgstr "Å»ywioÅ‚aki Powietrza" msgid "Fire Elemental" msgstr "Å»ywioÅ‚ak Ognia" msgid "Fire Elementals" msgstr "Å»ywioÅ‚aki Ognia" msgid "Water Elemental" msgstr "Å»ywioÅ‚ak Wody" msgid "Water Elementals" msgstr "Å»ywioÅ‚aki Wody" msgid "Random Monsters" msgstr "Losowy potwór" msgid "Random Monster 1" msgstr "Losowy potwór - sÅ‚aby" msgid "Random Monsters 1" msgstr "Losowe potwory - sÅ‚abe" msgid "Random Monster 2" msgstr "Losowy potwór - Å›redni" msgid "Random Monsters 2" msgstr "Losowe potwory - Å›rednie" msgid "Random Monster 3" msgstr "Losowy potwór - silny" msgid "Random Monsters 3" msgstr "Losowe potwory - silne" msgid "Random Monster 4" msgstr "Losowy potwór - bardzo silny" msgid "Random Monsters 4" msgstr "Losowe potwory - bardzo silne" msgid "Double shot" msgstr "Podwójny strzaÅ‚" msgid "2-hex monster" msgstr "Rozmiar 2-hex" msgid "Double strike" msgstr "Podwójny atak" msgid "Double damage to Undead" msgstr "Podwójne obrażenia nieumarÅ‚ym" msgid "% magic resistance" msgstr "% odpornoÅ›ci magicznej" msgid "Immune to Mind spells" msgstr "Niewrażliwy na czary umysÅ‚u" msgid "Immune to Elemental spells" msgstr "Niewrażliwy na czary żywiołów" msgid "Immune to Fire spells" msgstr "Niewrażliwy na czary ognia" msgid "Immune to Cold spells" msgstr "Niewrażliwy na czary zimna" msgid "Immune to " msgstr "Niewrażliwy na " msgid "% immunity to %{spell} spell" msgstr "% odpornoÅ›ci na czar %{spell}" msgid "% damage from Elemental spells" msgstr "% odpornoÅ›ci na czary żywiołów" msgid "% damage from %{spell} spell" msgstr "% obrażeÅ„ od czaru %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% szans na Rozproszenie pozytywnych czarów" msgid "% chance to Paralyze" msgstr "% szans na Paraliż" msgid "% chance to Petrify" msgstr "% szans na zamianÄ™ w kamieÅ„" msgid "% chance to Blind" msgstr "% szans na OÅ›lepienie" msgid "% chance to Curse" msgstr "% szans na KlÄ…twÄ™" msgid "% chance to cast %{spell} spell" msgstr "% szans na rzucenie zaklÄ™cia %{spell}" msgid "HP regeneration" msgstr "Regeneruje siÄ™" msgid "Two hexes attack" msgstr "Atakuje dwa pola" msgid "Flyer" msgstr "LatajÄ…cy" msgid "Always retaliates" msgstr "Zawsze kontratakuje" msgid "Attacks all adjacent enemies" msgstr "Atakuje wszystkich przylegÅ‚ych przeciwników" msgid "No melee penalty" msgstr "Brak kar w walce wrÄ™cz" msgid "Dragon" msgstr "Smok" msgid "Undead" msgstr "NieumarÅ‚y" msgid "No enemy retaliation" msgstr "Powstrzymuje kontratak" msgid "HP drain" msgstr "Wysysa życie" msgid "Cloud attack" msgstr "Atak trujÄ…cÄ… chmurÄ…" msgid "Decreases enemy's morale by " msgstr "Obniża morale przeciwnika o " msgid "% chance to halve enemy" msgstr "% szans na unicestwienie poÅ‚owy atakowanego oddziaÅ‚u" msgid "Soul Eater" msgstr "Pożeracz Dusz" msgid "Elemental" msgstr "Å»ywioÅ‚ak" msgid "No Morale" msgstr "Neutralne morale" #, fuzzy msgid "Earth creature" msgstr "Rekrutuj stworzenia" #, fuzzy msgid "Air creature" msgstr "Rekrutuj stworzenia" #, fuzzy msgid "Fire creature" msgstr "Rekrutuj stworzenia" #, fuzzy msgid "Water creature" msgstr "Jezioro" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% obrażeÅ„ od czarów ognia" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% obrażeÅ„ od czarów zimna" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Przerywa dziaÅ‚anie wszelkich zaklęć rzuconych na wszystkie jednostki." #, fuzzy msgid "Double damage from Air creatures" msgstr "Podwójne obrażenia nieumarÅ‚ym" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% obrażeÅ„ od czarów ognia" #, fuzzy msgid "Double damage from Water creatures" msgstr "Przerywa dziaÅ‚anie wszelkich zaklęć rzuconych na wszystkie jednostki." msgid "Lightning" msgstr "bÅ‚yskawic" msgid "% immunity to " msgstr "% odpornoÅ›ci na " msgid "% damage from " msgstr "% obrażeÅ„ od " msgid "The three Anduran artifacts magically combine into one." msgstr "Trzy AnduriaÅ„skie artefakty magicznie połączone w jeden." msgid "View Spells" msgstr "Pokaż zaklÄ™cia" msgid "View %{name} Info" msgstr "Informacje o: %{name}" msgid "Move %{name}" msgstr "PrzenieÅ› %{name}" msgid "Cannot move the Spellbook" msgstr "Nie można przenieść KsiÄ™gi Zaklęć" msgid "This item can't be traded." msgstr "Nie można wymienić tego przedmiotu." msgid "Invalid Artifact" msgstr "NieprawidÅ‚owy artefakt" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} zwiÄ™ksza twojÄ… wiedzÄ™ o %{count}." msgid "Ultimate Book of Knowledge" msgstr "Najzn. KsiÄ™ga Wiedzy" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} zwiÄ™ksza twój atak o %{count}." msgid "Ultimate Sword of Dominion" msgstr "Najzn. Miecz Dominium" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} zwiÄ™ksza twojÄ… obronÄ™ o %{count}." msgid "Ultimate Cloak of Protection" msgstr "Najzn. PÅ‚aszcz Ochrony" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} zwiÄ™ksza twojÄ… moc o %{count}." msgid "Ultimate Wand of Magic" msgstr "Najzn. Różdżka Magii" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} zwiÄ™ksza twój atak i obronÄ™ o %{count} pkt." msgid "Ultimate Shield" msgstr "Najzn. Tarcza" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} zwiÄ™ksza twojÄ… moc i wiedzÄ™ o %{count} pkt." msgid "Ultimate Staff" msgstr "Najzn. Kostur" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} zwiÄ™ksza każdÄ… z twoich umiejÄ™tnoÅ›ci o %{count} punkty." msgid "Ultimate Crown" msgstr "Najzn. Korona" msgid "Golden Goose" msgstr "ZÅ‚ota Gęś" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} dodaje przychód w wysokoÅ›ci %{count} sztuk zÅ‚ota na turÄ™." msgid "Arcane Necklace of Magic" msgstr "Tajemny Naszyjnik Magii" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Po uratowaniu Czarodziejki z przeklÄ™tego grobowca, ta nagradza twój heroizm " "bogato zdobionym naszyjnikiem." msgid "Caster's Bracelet of Magic" msgstr "Magiczna Bransoleta Czarodzieja" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Podczas przeszukiwania gruzów po zapadniÄ™tej kopalni uwalniasz grupÄ™ " "uwiÄ™zionych Krasnoludów. W wyrazie wdziÄ™cznoÅ›ci ich przywódca ofiarowuje ci " "zÅ‚otÄ… bransoletÄ™." msgid "Mage's Ring of Power" msgstr "PierÅ›cieÅ„ Mocy Maga" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Okrzyki bólu prowadzÄ… ciÄ™ do Centaura, schwytanego w puÅ‚apkÄ™. Po uwolnieniu " "z niej, przekazuje ci niewielkÄ… sakiewkÄ™. PrzeglÄ…dajÄ…c jej zawartość " "znajdujesz skrzÄ…cy siÄ™ od klejnotów pierÅ›cieÅ„." msgid "Witch's Broach of Magic" msgstr "Wiedźmia Brosza Magii" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Tuż obok szczÄ…tek spalonej wiedźmy leży piÄ™kna, misternie wykonana brosza. " "PodchodzÄ…c do zwÅ‚ok z najwyższÄ… ostrożnoÅ›ciÄ…, dołączasz broszÄ™ do swego " "ekwipunku." msgid "Medal of Valor" msgstr "Medal MÄ™stwa" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} zwiÄ™ksza twoje morale o %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Po oswobodzeniu cnotliwej niewiasty z rÄ…k zÅ‚ego wÅ‚adyki zostajesz odznaczony " "przez królewskiego wysÅ‚annika Medalem MÄ™stwa." msgid "Medal of Courage" msgstr "Medal Odwagi" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Po uratowaniu mÅ‚odego chÅ‚opca przed watahÄ… wÅ›ciekÅ‚ych wilków, odprowadzasz " "go do posiadÅ‚oÅ›ci jego ojca. WdziÄ™czny szlachcic nagradza ciÄ™ Medalem Odwagi." msgid "Medal of Honor" msgstr "Medal Honoru" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Ratujesz księżniczkÄ™ z sÄ…siedniego królestwa z rÄ…k niegodziwych Å‚owców " "niewolników, w zamian wynagradza ciÄ™ ona Medalem Honoru." msgid "Medal of Distinction" msgstr "Medal Uznania" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Rozprawiasz siÄ™ z nÄ™kajÄ…cym okolicÄ™ zÅ‚owieszczym Minotaurem, który dla " "zabawy pożeraÅ‚ szlachetnych Rycerzy. Uhonorowano ciÄ™ w zamian Medalem " "Uznania." msgid "Fizbin of Misfortune" msgstr "Fizbin Nieszczęścia" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} znaczÄ…co zmniejsza twoje morale o %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Potykasz siÄ™ o odznaczenie, leżące samotnie ma pustej drodze. DołączajÄ…c " "order do swego ekwipunku zdajesz sobie sprawÄ™, że wszedÅ‚eÅ› w posiadanie " "niepożądanego Fizbinu Nieszczęścia, który znacznie obniża morale twoich " "oddziałów." msgid "Thunder Mace of Dominion" msgstr "GrzmiÄ…cy KiÅ›cieÅ„ Dominium" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Podczas gwaÅ‚townej burzy dostrzegasz jak bÅ‚yskawica uderza w drzewo, " "rozszczepiajÄ…c je na części. WewnÄ…trz drzewa znajdujesz tajemniczy kiÅ›cieÅ„." msgid "Armored Gauntlets of Protection" msgstr "Pancerne RÄ™kawice Ochrony" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} zwiÄ™kszajÄ… twojÄ… obronÄ™ o %{count}." #, fuzzy msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Na swej drodze napotykasz niesÅ‚awnego Czarnego Rycerza! Po wyczerpujÄ…cej " "walce, zakoÅ„czonej remisem, Rycerz, chcÄ…c okazać ci swój szacunek, " "ofiarowuje ci parÄ™ pancernych rÄ™kawic." msgid "Defender Helm of Protection" msgstr "Wzmocniony HeÅ‚m Ochrony" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Dostrzegasz migotliwy zÅ‚oty bÅ‚ysk. Po niewielkich poszukiwaniach znajdujesz " "zÅ‚oty heÅ‚m, ukryty wÅ›ród krzewów." msgid "Giant Flail of Dominion" msgstr "Olbrzymi Cep Bojowy Dominium" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Niezdarny Olbrzym powaliÅ‚ sam siebie przy pomocy swego wÅ‚asnego cepa " "bojowego. MajÄ…c ufność w swej biegÅ‚oÅ›ci w korzystaniu z takiej broni, pewnie " "zabierasz efektowny oręż powalonemu Olbrzymowi." msgid "Ballista of Quickness" msgstr "Balista SzybkoÅ›ci" #, fuzzy msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "%{name} pozwala twojej katapulcie strzelić jeden dodatkowy strzaÅ‚ na rundÄ™." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "PrzechadzajÄ…c siÄ™ wÅ›ród ruin starożytnego miasta, niegdyÅ› otoczonego murem, " "znajdujesz narzÄ™dzie, które sprowadziÅ‚o na miasto zagÅ‚adÄ™ - misternie " "wykonanÄ… balistÄ™." msgid "Stealth Shield of Protection" msgstr "MaskujÄ…ca Tarcza Ochrony" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Kamienny posÄ…g wojownika przytrzymuje srebrnÄ… tarczÄ™. Gdy zabierasz tarczÄ™, " "posÄ…g obraca siÄ™ w pyÅ‚." msgid "Dragon Sword of Dominion" msgstr "Smoczy Miecz Dominium" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "KroczÄ…c wÄ…skÄ… Å›cieżynÄ…, dostrzegasz jak pobliski krzew staje nagle w ogniu. " "Na twych oczach pÅ‚omienie przybierajÄ… postać piÄ™knej kobiety. Owa niewiasta " "wrÄ™cza ci wspaniaÅ‚y miecz." msgid "Power Axe of Dominion" msgstr "Potężny Topór Dominium" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Dostrzegasz srebrny topór wbity głęboko w ziemiÄ™. Po kliku nieskutecznych " "próbach wyciÄ…gniÄ™cia tego oręża przez twe oddziaÅ‚y, samemu Å›ciskasz stylisko " "topora i bez wysiÅ‚ku wyciÄ…gasz go." msgid "Divine Breastplate of Protection" msgstr "Boski NapierÅ›nik Ochrony" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Banda Rozbójników przeczesuje dobytek polegÅ‚ego wojownika. OdstraszajÄ…c " "szabrowników zauważasz, że Rozbójnicy przegapili przepiÄ™kny napierÅ›nik." msgid "Minor Scroll of Knowledge" msgstr "Pomniejszy Zwój Wiedzy" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Tuż przed tobÄ… materializuje siÄ™ szklana skrzynka, a w niej zwój, leżący na " "karmazynowej wyÅ›ciółce z aksamitu. DotknÄ…wszy wieka, te unosi siÄ™ a zwój " "szybuje wprost do twych oczekujÄ…cych dÅ‚oni." msgid "Major Scroll of Knowledge" msgstr "WiÄ™kszy Zwój Wiedzy" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "OdwiedzajÄ…c miejscowego mÄ™drca, opowiadasz mu o celu swej podróży. MÄ™drzec " "siÄ™ga do sakwy, wyciÄ…ga z niej pożółkÅ‚y zwój i podaje ci go." msgid "Superior Scroll of Knowledge" msgstr "WspaniaÅ‚y Zwój Wiedzy" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Napotykasz szczÄ…tki starożytnej Druidki. KoÅ›ci, pożółkÅ‚e ze staroÅ›ci, " "wystajÄ… z porwanych faÅ‚d jej szaty. PrzeszukujÄ…c pÅ‚aszcz odkrywasz ukryty za " "połą zwój." msgid "Foremost Scroll of Knowledge" msgstr "DoskonaÅ‚y Zwój Wiedzy" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Zmasakrowany szkielet, pożółkÅ‚y ze staroÅ›ci, wyziera zza porwanych szat " "martwego Druida. PrzeszukujÄ…c tÄ… szatÄ™ odnajdujesz ukryty weÅ„ zwój." msgid "Endless Sack of Gold" msgstr "Bezdenny Worek ZÅ‚ota" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} zapewnia ci %{count} zÅ‚ota na dzieÅ„." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Malutki leprekaun taÅ„czy radoÅ›nie wokół magicznego worka. WidzÄ…c, że " "nadchodzisz zatrzymuje siÄ™ w pół kroku. Niewielki czÅ‚owieczek z okrzykiem " "tupie nogÄ…, rozpÅ‚ywajÄ…c siÄ™ w powietrzu. PrzypominajÄ…c sobie stare " "powiedzenie leprekaunów \"znalezione - nie kradzione\" zabierasz worek i " "odchodzisz." msgid "Endless Bag of Gold" msgstr "Bezdenna Torba ZÅ‚ota" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Pewna szlachcianka, oddzieliwszy siÄ™ od swej Å›wity, prosi ciÄ™ o pomoc. " "Odprowadziwszy jÄ… do domu, zostajesz nagrodzony torbÄ… peÅ‚nÄ… zÅ‚ota." msgid "Endless Purse of Gold" msgstr "Bezdenna Sakiewka ZÅ‚ota" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Podczas swych podróży odnajdujesz sakiewkÄ™, wypeÅ‚nionÄ… zÅ‚otem, która niegdyÅ› " "należaÅ‚a do wielkiego króla i wojownika, który posiadÅ‚ umiejÄ™tność zamiany " "dowolnej nieożywionej materii w zÅ‚oto." msgid "Nomad Boots of Mobility" msgstr "Buty MobilnoÅ›ci Nomady" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "%{name} zwiÄ™kszajÄ… twój zasiÄ™g ruchu na lÄ…dzie." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Kupiec Nomada szuka ochrony przed plemieniem Goblinów. Za twÄ… pomoc " "podarowuje ci parÄ™ doskonaÅ‚ej jakoÅ›ci butów, wykonanych z najmiÄ™kszej skóry. " "Przy bliższych oglÄ™dzinach dostrzegasz fascynujÄ…ce antyczne tÅ‚oczenia na " "skórze." msgid "Traveler's Boots of Mobility" msgstr "Buty MobilnoÅ›ci Podróżnika" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Odkrywszy parÄ™ piÄ™knie zdobionych trzewików, wykonanych z najmiÄ™kszej i " "najprzedniejszej skóry, dziÄ™kujesz nieznanemu darczyÅ„cy i dołączasz buty do " "swego ekwipunku." msgid "Lucky Rabbit's Foot" msgstr "Szczęśliwa Królicza Åapka" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} zwiÄ™ksza twoje szczęście w walce o %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "WÄ™drowny kramarz oferuje ci króliczÄ… Å‚apkÄ™, wykonanÄ… ze lÅ›niÄ…cego srebrnego " "futerka, w zamian za bezpiecznÄ… przeprawÄ™. Kramarz wyjaÅ›nia, że talizman " "zwiÄ™kszy twe szczęście w potyczkach." msgid "Golden Horseshoe" msgstr "ZÅ‚ota Podkowa" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "SÅ‚yszysz peÅ‚ne strachu pojÄ™kiwanie usidlonego Jednorożca. MruczÄ…c kojÄ…ce " "sÅ‚owa, uwalniasz klacz z puÅ‚apki. ParskajÄ…c i bijÄ…c kopytem raz o ziemiÄ™, " "zwierzÄ™ odbiega. PatrzÄ…c w dół dostrzegasz zÅ‚otÄ… podkowÄ™." msgid "Gambler's Lucky Coin" msgstr "Szczęśliwa Moneta Hazardzisty" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Udaje ci siÄ™ schwytać psotnego chochlika, który terroryzowaÅ‚ okolicÄ™. W " "zamian za swÄ… wolność otrzymujesz od niego magicznÄ… monetÄ™." msgid "Four-Leaf Clover" msgstr "Czterolistna Koniczyna" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Ku swemu zaskoczeniu, poÅ›rodku kÄ™py martwych i pousychanych roÅ›lin " "odnajdujesz zieleniejÄ…cÄ… siÄ™ żywo czterolistnÄ… koniczynkÄ™." msgid "True Compass of Mobility" msgstr "Prawdziwy Kompas MobilnoÅ›ci" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} zwiÄ™ksza twój zasiÄ™g ruchu na lÄ…dzie i morzu." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Stary mężczyzna, który przedstawia siÄ™ jako wynalazca, prosi ciÄ™ o " "wypróbowanie jego najnowszego wynalazku. Ofiarowuje ci kompas." msgid "Sailor's Astrolabe of Mobility" msgstr "Å»eglarskie Astrolabium MobilnoÅ›ci" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} zwiÄ™ksza twój zasiÄ™g na morzu." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Banda Ogrów torturuje starego morskiego kapitana. Ratujesz go z opresji, a " "on w podziÄ™ce podarowuje ci cudowne narzÄ™dzie do pomiaru poÅ‚ożenia gwiazd." msgid "Evil Eye" msgstr "ZÅ‚e Oko" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} redukuje koszty klÄ…tw o poÅ‚owÄ™." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Podczas przeczesywania walÄ…cej siÄ™ chaÅ‚upki, znajdujesz Szkielet martwej od " "dawna wiedźmy. Badania szczÄ…tek pozwalajÄ… odkryć szklane oko krÄ™cÄ…ce siÄ™ " "wewnÄ…trz pustej czaszki." msgid "Enchanted Hourglass" msgstr "ZaklÄ™ta Klepsydra" #, fuzzy msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} zwiÄ™ksza czas trwania wszystkich twoich czarów o %{count} tury." #, fuzzy msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Podczas swych wÄ™drówek krajobraz nagle zmienia siÄ™, ukazujÄ…c makabrycznÄ… " "scenÄ™: sÄ™py żerujÄ…ce na pobojowisku straszliwej batalii. Szybkie oglÄ™dziny " "szczÄ…tek owocujÄ… znalezieniem zaczarowanej klepsydry." msgid "Gold Watch" msgstr "ZÅ‚oty Zegarek" #, fuzzy msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} podwaja efektywność twoich czarów hipnozy." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Za pomoc w wyciÄ…gniÄ™ciu wózka z rowu wÄ™drowny sprzedawca eliksirów ofiaruje " "ci \"magiczny\" zÅ‚oty zegarek. Nie zdawaÅ‚ sobie on jednak sprawy, że zegarek " "zaiste jest magiczny." msgid "Skullcap" msgstr "Czepiec" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "%{name} zmniejsza o poÅ‚owÄ™ koszty czarów wpÅ‚ywajÄ…cych na umysÅ‚." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Krótki postój w niespotykanie wiejskiej gospodzie zaowocowaÅ‚ wymianÄ… " "pieniÄ™dzy, opowieÅ›ci i przypadkowo także bagaży. WewnÄ…trz swego nowego " "plecaka znajdujesz magiczny czepiec." msgid "Ice Cloak" msgstr "Lodowy PÅ‚aszcz" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} zmniejsza o poÅ‚owÄ™ uszkodzenia od czarów zimna zadanych twoim " "oddziaÅ‚om." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "KierujÄ…c siÄ™ panicznymi okrzykami damy w opaÅ‚ach, zauważasz mÅ‚odÄ… kobietÄ™ " "uciekajÄ…cÄ… przed wygÅ‚odniaÅ‚ym niedźwiedziem. Zarzynasz bestiÄ™ w mgnieniu " "oka, a wdziÄ™czna Czarodziejka tka dla ciebie magiczny pÅ‚aszcz z jego skóry." msgid "Fire Cloak" msgstr "Ognisty PÅ‚aszcz" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} zmniejsza o poÅ‚owÄ™ uszkodzenia od czarów ognia zadanych twoim " "oddziaÅ‚om." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Wpadasz w sam Å›rodek walki pomiÄ™dzy NekromantÄ… a Paladynem. Nekromanta " "strzela w Paladyna ognistym pociskiem, a rycerz pada na kolana. DziaÅ‚asz " "szybko i rozpÅ‚atasz zÅ‚oczyÅ„cÄ™ nim ten zadaje ostateczny cios. WdziÄ™czny " "Paladyn daje ci w zamian ognisty pÅ‚aszcz, który go ochroniÅ‚." msgid "Lightning Helm" msgstr "HeÅ‚m BÅ‚yskawicy" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} zmniejsza o poÅ‚owÄ™ uszkodzenia od czarów burzy zadanych twoim " "oddziaÅ‚om." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "WÄ™drowny majsterkowicz, bÄ™dÄ…c pozbawiony zapasów, oferuje ci heÅ‚m zdobiony " "motywem bÅ‚yskawicy w zamian za strawÄ™ i wodÄ™. ZaciekawiÅ‚ ciÄ™ ów przedmiot i " "zgadzasz siÄ™, a nastÄ™pnie odkrywasz, że heÅ‚m ten ma magiczne wÅ‚aÅ›ciwoÅ›ci." msgid "Evercold Icicle" msgstr "Wiecznie Zimny Sopel" #, fuzzy msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "%{name} zwiÄ™ksza uszkodzenia twoich czarów zimna o %{count} procent." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "TwÄ… uwagÄ™ przykuwa sopel lodu, który zdaje siÄ™ opierać sÅ‚oÅ„cu Å›wiecÄ…cemu w " "samo poÅ‚udnie. Zaintrygowany, odÅ‚amujesz go i odkrywasz, że sopel ten nie " "topi siÄ™ w twej dÅ‚oni." msgid "Everhot Lava Rock" msgstr "NiestygnÄ…ca SkaÅ‚a Wulkaniczna" #, fuzzy msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "%{name} zwiÄ™ksza uszkodzenia twoich czarów ognia o %{count} procent." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Podczas swych podróży napotykasz plemiÄ™ maÅ‚poksztaÅ‚tnych istot, które używa " "magicznej skaÅ‚y wulkanicznej do rozniecania ognia. Å»al ci tych istot i " "uczysz ich jak rozpalać ogieÅ„ przy pomocy Å‚uku ogniowego. WierzÄ…c, że jesteÅ› " "boskÄ… istotÄ…, maÅ‚poludzie oddajÄ… ci swÄ… skałę." msgid "Lightning Rod" msgstr "Piorunochron" #, fuzzy msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "%{name} zwiÄ™ksza uszkodzenia twoich czarów burzy o %{count} procent." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Przeczekujesz burzÄ™ i nagle bÅ‚yskawica uderza w piorunochron pobliskiej " "chaÅ‚upy, topiÄ…c go i zrzucajÄ…c na ziemiÄ™. KoÅ„cówka piorunochronu jednakowoż " "przetrwaÅ‚a uderzenie pioruna, a gdy jej dotykasz, wÅ‚osy stajÄ… ci dÄ™ba. Hmm..." msgid "Snake-Ring" msgstr "Wężowy PierÅ›cieÅ„" #, fuzzy msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} zmniejsza o poÅ‚owÄ™ koszty wszystkich twoich czarów bÅ‚ogosÅ‚awieÅ„stwa." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Na palcu u dÅ‚oni dawno zmarÅ‚ego podróżnika odnajdujesz dziwnie uksztaÅ‚towany " "pierÅ›cieÅ„. Przypomina węża kÄ…sajÄ…cego swój wÅ‚asny ogon." msgid "Ankh" msgstr "Ankh" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} podwaja skuteczność wszystkich twoich czarów wskrzeszania i " "ożywiania." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Potężny huragan odkrywa wejÅ›cie do zakopanego grobowca. Twoje oglÄ™dziny " "ujawniajÄ…, że grobowiec byÅ‚ już plÄ…drowany, ale zÅ‚odzieje przeoczyli w " "ciemnoÅ›ci znak ankh na srebrnym Å‚aÅ„cuszku." msgid "Book of Elements" msgstr "KsiÄ™ga Å»ywiołów" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} podwaja skuteczność wszystkich twoich czarów przywoÅ‚ywania." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Napotykasz mÅ‚odego magika, który prosi o możliwość dołączenia do ciebie ze " "wzglÄ™du na czajÄ…ce siÄ™ wokół niebezpieczeÅ„stwa. Zgadzasz siÄ™, a on " "ofiarowuje ci jako zapÅ‚atÄ™ egzemplarz KsiÄ™gi Å»ywiołów." msgid "Elemental Ring" msgstr "PierÅ›cieÅ„ Å»ywiołów" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "%{name} zmniejsza o poÅ‚owÄ™ koszty wszystkich czarów przywoÅ‚ywania." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "WypoczywajÄ…c w trakcie postoju, dostrzegasz jak żbik wdrapuje siÄ™ na niskie " "drzewo, by dostać siÄ™ do kruczego gniazda. DziaÅ‚ajÄ…c pod wpÅ‚ywem impulsu, " "sam wdrapujesz siÄ™ na drzewo i odstraszasz dzikiego kota. W Å›rodku gniazda " "znajdujesz kolekcjÄ™ bÅ‚yszczÄ…cych kamieni oraz pierÅ›cieÅ„." msgid "Holy Pendant" msgstr "ÅšwiÄ™ty Medalion" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na czary klÄ…tw." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Podczas twoich wÄ™drówek natknÄ…Å‚eÅ› siÄ™ na pustelnika, mieszkajÄ…cego w maÅ‚ej, " "schludnej chaÅ‚upce. ZaimponowaÅ‚o mu podjÄ™cie przez ciebie twej misji, " "przewaÅ‚ wiÄ™c swÄ… medytacjÄ™ by dać ci swe bÅ‚ogosÅ‚awieÅ„stwo i podarować amulet " "przeciwdziaÅ‚ajÄ…cy klÄ…twom." msgid "Pendant of Free Will" msgstr "Medalion Wolnej Woli" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na czary hipnozy." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "ChcÄ…c odpowiedzieć na woÅ‚anie o pomoc, znajdujesz grupÄ™ rzecznych RusaÅ‚ek " "podtapiajÄ…cych dla zabawy starszego mężczyznÄ™. CzujÄ…c narastajÄ…cÄ… w tobie " "mÅ›ciwość, ratujesz starca i wyciÄ…gasz jednÄ… z RusaÅ‚ek na suchy lÄ…d. RusaÅ‚ka, " "czujÄ…c siÄ™ źle poza wodÄ…, oferuje ci magiczny medalion w zamian za " "puszczenie wolno." msgid "Pendant of Life" msgstr "Medalion Å»ycia" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na czary Å›mierci." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Krótkie spotkanie na poboczu z niewielkÄ… karawanÄ… i gra w koÅ›ci prowadzÄ… do " "wygranej magicznego medalionu. Jego poprzedni wÅ‚aÅ›ciciel twierdzi, że chroni " "on przed nekromanckimi zaklÄ™ciami Å›mierci." msgid "Serenity Pendant" msgstr "Medalion Spokoju" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na czary szaÅ‚u." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "OdgÅ‚osy walki prowadzÄ… ciÄ™ na miejsce pojedynku pomiÄ™dzy starym BarbarzyÅ„cÄ… " "a oÅ›miogÅ‚owÄ… HydrÄ…. Twoja rychÅ‚a interwencja przechyla szalÄ™ zwyciÄ™stwa na " "korzyść mężczyzny, a ten wynagradza ci to medalionem, którego zwykÅ‚ używać " "do kojenia swego umysÅ‚u przed bitwÄ…." msgid "Seeing-eye Pendant" msgstr "Medalion Wszystkowidzenia" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na czary " "oÅ›lepienia." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Spotykasz bardzo starÄ…, umierajÄ…cÄ… w samotnoÅ›ci kobietÄ™, której katarakta " "dawno już odebraÅ‚a wzrok. Postanawiasz speÅ‚nić jej ostatniÄ… proÅ›bÄ™ i " "obiecujesz jej stosowny pochówek. PrzepeÅ‚niona wdziÄ™cznoÅ›ciÄ…, kobieta " "obdarowuje ciÄ™ magicznym medalionem, ozdobionym stylizowanym symbolem oka. " "Pozwala ci on widzieć nawet z zamkniÄ™tymi oczyma." msgid "Kinetic Pendant" msgstr "Kinetyczny Medalion" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na czary " "paraliżu." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Na twej drodze staje golem noszÄ…cy lÅ›niÄ…cy medalion i blokuje ci przejÅ›cie. " "DziaÅ‚ajÄ…c instynktownie, odcinasz medalion z jego szyi. Pozbawiony źródÅ‚a " "swej mocy, golem przestaje dziaÅ‚ać, pozostawiajÄ…c ciÄ™ z magicznym medalionem." msgid "Pendant of Death" msgstr "Medalion Åšmierci" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na Å›wiÄ™te czary." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Krótka i Å›miercionoÅ›na walka z NekromantÄ… pozwala ci posiąść jego magiczny " "medalion. Później, Czarodziej wyjaÅ›nia ci, że medalion ów chroni " "kontrolowanych przez ciebie nieumarÅ‚ych przed Å›wiÄ™tymi zaklÄ™ciami." msgid "Wand of Negation" msgstr "Różdżka Negacji" #, fuzzy msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "%{name} sprawia, że wszystkie twoje oddziaÅ‚y sÄ… niewrażliwe na czary Å›mierci." #, fuzzy msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Spotykasz starego przyjaciela Czarodzieja, podróżujÄ…cego w przeciwnym " "kierunku. Obdarowuje ciÄ™ on podarkiem: różdżkÄ… zdolnÄ… ochronić twe oddziaÅ‚y " "przed zaklÄ™ciami rozproszenia magii." msgid "Golden Bow" msgstr "ZÅ‚oty Åuk" #, fuzzy msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} eliminuje %{count} procent kary dla twoich oddziałów strzelajÄ…cych " "przez przeszkody (np. zamkowe mury)" msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Przypadkowe spotkanie ze sÅ‚awnym Åucznikiem prowadzi ciÄ™ do rozgrywki w " "koÅ›ci, jego Å‚uk przeciwko twemu wierzchowcowi. Wygrywasz." msgid "Telescope" msgstr "Teleskop" #, fuzzy msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} zwiÄ™ksza ilość odsÅ‚anianego terenu podczas zwiedzania o %{count} " "dodatkowe pola." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Kupiec z odlegÅ‚ych krain dobija z tobÄ… targu i wymienia swój nowy wynalazek " "na suchy prowiant. Przedmiot sprawia, że odlegÅ‚e obiekty wydajÄ… siÄ™ bliższe, " "a nazwaÅ‚ on to urzÄ…dzenie...\n" "\n" "teleskopem." msgid "Statesman's Quill" msgstr "Pióro Dyplomaty" #, fuzzy msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} redukuje koszt kapitulacji do %{count} procent caÅ‚ego kosztu armii " "bÄ™dÄ…cej w posiadaniu." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Zatrzymujesz siÄ™ by pomóc emisariuszowi rozwiÄ…zać problem pÄ™kniÄ™tej osi. W " "dowodzie uznania ofiarowuje ci on pióro o magicznych wÅ‚aÅ›ciwoÅ›ciach - " "twierdzi, że \"pomaga innym postrzegać rzeczy po twojemu\"." msgid "Wizard's Hat" msgstr "Kapelusz Czarodzieja" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} zwiÄ™ksza czas trwania twoich czarów o %{count} tur." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Dostrzegasz uciekajÄ…cego przed Gryfem Czarodzieja, gnajÄ…cego niczym wiatr. " "Czarodziej otwiera portal i przejeżdża przezeÅ„, strÄ…cajÄ…c jednak swój " "kapelusz o krawÄ™dź magicznej bramy. Gryf podąża za nim, a brama siÄ™ zamyka. " "Podnosisz kapelusz, otrzepujesz z pyÅ‚u i zakÅ‚adasz na wÅ‚asnÄ… gÅ‚owÄ™." msgid "Power Ring" msgstr "PierÅ›cieÅ„ Mocy" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "%{name} przywraca twojemu bohaterowi dodatkowe %{count} punkty magii na " "dzieÅ„." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Odnajdujesz niewielkie drzewo, które niezwykle wrÄ™cz przypomina ci z wyglÄ…du " "wielkiego Czarnoksiężnika Carnaught'a, a na jednej z gałązek dostrzegasz " "pierÅ›cieÅ„. Porwane kawaÅ‚ki szat i przegniÅ‚a skóra sprawiajÄ…, że zaczynasz " "podejrzewać, iż to w istocie JEST Carnauth, jednak przemieniony. Jako, że i " "tak mu już nie pomożesz, zabierasz magiczny pierÅ›cieÅ„ ze sobÄ…." msgid "Ammo Cart" msgstr "Wóz z AmunicjÄ…" #, fuzzy msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} zapewnia nieskoÅ„czonÄ… amunicjÄ™ dla wszystkich twoich oddziałów " "strzelajÄ…cych." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "TwÄ… uwagÄ™ przykuwa pozostawiony na Å›rodku dawnego pola bitwy wóz z amunicjÄ…. " "OglÄ™dziny pozwalajÄ… ustalić, że jest on w caÅ‚kiem dobrym stanie, zabierasz " "go wiÄ™c ze sobÄ…." msgid "Tax Lien" msgstr "Weksel Fiskalny" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} kosztuje ciÄ™ %{count} zÅ‚ota na dzieÅ„." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Twa rozrzutność zrodziÅ‚a olbrzymie zadÅ‚użenie podatkowe, którego nijak nie " "możesz spÅ‚acić. Poborca podatkowy lituje siÄ™ nad tobÄ… i godzi siÄ™ na " "pobieranie z twego majÄ…tku marne 250 sztuki zÅ‚ota każdego dnia, przez resztÄ™ " "twego żywota." msgid "Hideous Mask" msgstr "Potworna Maska" #, fuzzy msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "%{name} zapobiega dołączaniu wszystkich \"wÄ™drownych\" armii do twojego " "bohatera." #, fuzzy msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "PrzeczesujÄ…c grób Sinfilasa Gardolada, sÅ‚ynnego zmiennoksztaÅ‚tnego " "Czarnoksiężnika, odkrywasz jego osÅ‚awionÄ… maskÄ™. Drżąc na caÅ‚ym ciele, " "zakÅ‚adasz jÄ…, a ta wykrÄ™ca twojÄ… twarz w okropnym grymasie! O nie! OkazaÅ‚o " "siÄ™, że to tak naprawdÄ™ jest Potworna Maska Gromluck'a Greene'a, a ty w niej " "utknÄ…Å‚eÅ› na dobre." msgid "Endless Pouch of Sulfur" msgstr "Bezdenna Sakiewka Siarki" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} zapewnia %{count} jednostkÄ™ siarki dziennie." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Odwiedzasz alchemika, który ujrzawszy towarzyszÄ…ce ci oddziaÅ‚y ulega " "prawoÅ›ci twojej sprawy. Åšwieżo upieczony lojalny podwÅ‚adny oddaje ci swÄ… " "bezdennÄ… sakiewkÄ™ siarki, by wspomóc ciÄ™ w wysiÅ‚ku wojennym." msgid "Endless Vial of Mercury" msgstr "Bezdenna Fiolka RtÄ™ci" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} zapewnia %{count} jednostkÄ™ rtÄ™ci dziennie." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Krótki postój w opuszczonej w najwyraźniej wielkim poÅ›piechu wieży " "Czarodzieja pozwala ci odkryć magicznÄ… fiolkÄ™ rtÄ™ci, na dnie której zawsze " "pozostaje resztka tej substancji. PotrafiÄ…c rozpoznać skarb, gdy ten leży " "przed tobÄ…, zatykasz fiolkÄ™ korkiem i wsuwasz do swej kieszeni." msgid "Endless Pouch of Gems" msgstr "Bezdenna Sakiewka Klejnotów" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} zapewnia %{count} jednostkÄ™ klejnotów dziennie." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Po krótkiej burzy na niebie pojawia siÄ™ tÄ™cza... a ty możesz dostrzec jej " "koniec. JadÄ…c szybko, zagarniasz znajdujÄ…cy siÄ™ tam garniec ze zÅ‚otem. " "Leprekaun, którego byÅ‚a to wÅ‚asność, nie mogÄ…c ciÄ™ powstrzymać przed " "zabraniem skarbu, oferuje ci bezdennÄ… sakiewkÄ™ z klejnotami w zamian za " "zwrot jego zÅ‚ota. Zgadzasz siÄ™ na te warunki." msgid "Endless Cord of Wood" msgstr "Niewyczerpany Stos Drewna" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} zapewnia %{count} jednostkÄ™ drewna dziennie." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "ZatrzymujÄ…c siÄ™ by odpocząć i rozpalić ogieÅ„ pod kocioÅ‚kiem, siÄ™gasz po " "bierwiono z pobliskiego stosu drewna. SiÄ™gajÄ…c po coraz to wiÄ™cej kawaÅ‚ków " "drzewa zauważasz, że stos ten siÄ™ nie zmniejsza. Dociera do ciebie, że " "drewno to musi być zaczarowane, wiÄ™c zabierasz je ze sobÄ…." msgid "Endless Cart of Ore" msgstr "Wiecznie PeÅ‚ny Wóz Rudy" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} zapewnia %{count} jednostkÄ™ rudy dziennie." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Odnajdujesz goblinich mieczników, kujÄ…cych broÅ„ przeznaczonÄ… do walki z " "ludźmi. Z grzmiÄ…cym okrzykiem ty i twe oddziaÅ‚y wpadacie do ich obozu i " "przepÄ™dzacie ich w sinÄ… dal. Przeszukanie obozu owocuje znalezieniem " "magicznego wózka rudy, który nigdy nie może zostać opróżniony." msgid "Endless Pouch of Crystal" msgstr "Bezdenna Sakiewka Kryształów" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} zapewnia %{count} jednostkÄ™ kryształów dziennie." #, fuzzy msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "ChroniÄ…c siÄ™ przed burzÄ… w maÅ‚ej jaskini, dostrzegasz niewielkÄ… formacjÄ™ " "kryształów w jednym z zakamarków pieczary. Wiedziony ciekawoÅ›ciÄ…, odÅ‚amujesz " "kawaÅ‚ek i zauważasz, że brakujÄ…cy fragment mineraÅ‚u odrasta na nowo. " "Decydujesz siÄ™ na zapakowanie caÅ‚ego krysztaÅ‚u do sakiewki i zabierasz go ze " "sobÄ…." msgid "Spiked Helm" msgstr "Rogaty HeÅ‚m" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Twoja armia wpada w zasadzkÄ™ niewielkiego szczepu dzikich (i niezbyt " "bystrych) Orków. Odpierasz ich z Å‚atwoÅ›ciÄ…, a ocaleni uciekajÄ… we wszystkich " "kierunkach. Jeden z Orków nosiÅ‚ wypolerowany rogaty heÅ‚m. Uznajesz, że " "bÄ™dzie to dobra pamiÄ…tka i zabierasz go ze sobÄ…." msgid "Spiked Shield" msgstr "Rogata Tarcza" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Natrafiasz na most spinajÄ…cy brzegi wyschniÄ™tego wÄ…wozu. Nim przechodzisz na " "drugÄ… stronÄ™, spod mostu wyÅ‚ania siÄ™ Troll i żąda od ciebie zapÅ‚aty nim " "pozwoli ci skorzystać z przejÅ›cia. Odmawiasz, a wtedy Troll szarżuje na " "ciebie, nie pozostawiajÄ…c ci innego wyjÅ›cia jak zaszlachtowanie go. Jako " "trofeum zabierasz jego rogatÄ… tarczÄ™." msgid "White Pearl" msgstr "BiaÅ‚a PerÅ‚a" #, fuzzy msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Spacer poprzez nieckÄ™ wyschniÄ™tego sÅ‚onego jeziora koÅ„czy siÄ™ niespodziewanÄ… " "nagrodÄ…: białą perłą skrytÄ… pomiÄ™dzy pokruszonymi muszlami i Å›mieciami." msgid "Black Pearl" msgstr "Czarna PerÅ‚a" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Plotki o Gryfie niespotykanych rozmiarów, żerujÄ…cym na okolicy, zaprowadziÅ‚y " "ciÄ™ do jego skalnego leża. Krótka, zaciÄ™ta walka przynosi kres bestii, a " "przeszukanie jego plugawego gniazda koÅ„czy siÄ™ znalezieniem wielkiej czarnej " "perÅ‚y." msgid "Magic Book" msgstr "KsiÄ™ga Zaklęć" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name} pozwala ci rzucać czary." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Artefakt 2" msgid "The reserved artifact." msgstr "Zarezerwowany artefakt." msgid "Dummy 3" msgstr "Artefakt 3" msgid "Dummy 4" msgstr "Artefakt 4" msgid "Spell Scroll" msgstr "Zwój z ZaklÄ™ciem" #, fuzzy msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Ten %{name} daje twojemu bohaterowi możliwość rzucania czaru %{spell} jeÅ›li " "bohater posiada KsiÄ™gÄ™ Zaklęć." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Odnajdujesz starÄ…, bogato zdobionÄ… szkatułę pokrytÄ… runami. Z ciekawoÅ›ci " "zaglÄ…dasz do Å›rodka i znajdujesz stary pergamin. WyciÄ…gasz go z " "niecierpliwoÅ›ciÄ… i nagle czujesz, jak twe ciaÅ‚o wypeÅ‚nia magiczna moc." msgid "Arm of the Martyr" msgstr "RamiÄ™ MÄ™czennika" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} zwiÄ™ksza twojÄ… Moc o %{count} ale również dodaje ujemne morale dla " "nieumarÅ‚ych." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Jeden z twoich mniej inteligentnych żoÅ‚nierzy podnosi z ziemi ramiÄ™. Pomimo " "tego, że jest odrÄ…bane od ciaÅ‚a, caÅ‚y czas siÄ™ rusza. Mimo że ramiÄ™ jest " "obrzydliwe, nie możesz siÄ™ zmusić, by je zostawić - ma chyba jakÄ…Å› magicznÄ… " "moc, która wpÅ‚ywa na podejmowanie przez ciebie decyzji." msgid "Breastplate of Anduran" msgstr "NapierÅ›nik Andurana" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} zwiÄ™ksza twojÄ… obronÄ™ o %{count}" msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Podchodzisz do znaku, na którym znajduje siÄ™ napis: \"Tutaj spoczywa ciaÅ‚o " "Andurana. SkÅ‚oÅ„ siÄ™ i przysiÄ™gnij mu wierność, a otrzymasz nagrodÄ™.\" " "Decydujesz siÄ™ to zrobić. Gdy wstajesz, czujesz coÅ› chÅ‚odnego na swoim " "ciele. SpoglÄ…dasz w dół i widzisz, że masz na sobie zdobiony napierÅ›nik." msgid "Broach of Shielding" msgstr "Brosza OsÅ‚ony" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} zapewnia %{count} procent ochrony od zaklÄ™cia Armageddon i Burza " "Å»ywiołów, ale obniża moc czarów o 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Pewna urocza czarodziejka uważa, że twojej armii przydaÅ‚oby siÄ™ magiczne " "wzmocnienie. Proponuje, że rzuci specjalne zaklÄ™cie na noszonÄ… przez ciebie " "broszÄ™, na co siÄ™ ochoczo zgadzasz." msgid "Battle Garb of Anduran" msgstr "Bitewny Strój Andurana" #, fuzzy msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} łączy moce trzech AnduriaÅ„skich artefaktów. Zapewnia maksymalne " "szczęście i morale dla oddziałów oraz dodaje czar Portal Miejski." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Z litoÅ›ci dla biednego wieÅ›niaka odkupujesz od niego skrzyniÄ™ peÅ‚nÄ… starych " "rupieci. Gdy później je przeglÄ…dasz, znajdujesz wÅ›ród nich 3 części " "legendarnego stroju Andurana!" msgid "Crystal Ball" msgstr "KrysztaÅ‚owa Kula" #, fuzzy msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} pozwala zdobyć bardziej szczegółowe informacje na temat potworów, " "wrogich armii i zamków znajdujÄ…cych siÄ™ w pobliżu bohatera który to nosi." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Trafiasz do taboru, w którym odbywa siÄ™ uczta. Cyganie woÅ‚ajÄ… ciÄ™ i mówiÄ…: " "\"Udowodnij, że potrafisz zataÅ„czyć Rama-Buta, a nagrodzimy ciÄ™.\" Nie " "wiesz, o jaki taniec chodzi, ale zgadzasz siÄ™. CaÅ‚y obóz Å›mieje siÄ™ widzÄ…c " "twoje podskoki, ale doceniajÄ…c twÄ… odwagÄ™ wrÄ™czajÄ… ci krysztaÅ‚owÄ… kulÄ™." msgid "Heart of Fire" msgstr "Serce Ognia" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} zapewnia %{count} procent ochrony od ognia, ale podwaja uszkodzeni " "otrzymane od zimna." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Wchodzisz na Å›wieżo wypalonÄ… łąkÄ™ i widzisz Å»ywioÅ‚aka Ognia, siedzÄ…cego na " "gÅ‚azie. SpoglÄ…da na ciebie z wyrazem ogromnego bólu na twarzy. NastÄ™pnie " "rzuca w ciebie jakimÅ› bÅ‚yszczÄ…cym przedmiotem. Podnosisz rÄ™ce, aby siÄ™ " "osÅ‚onić, ale przedmiot przelatuje ci przez dÅ‚onie i wtapia ci siÄ™ w pierÅ›." msgid "Heart of Ice" msgstr "Serce Lodu" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} zapewnia %{count} procent ochrony od zimna, ale podwaja uszkodzenia " "otrzymane od ognia." #, fuzzy msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Nagle, caÅ‚e twoje ciaÅ‚o ogarnia lodowate zimno i spadasz z konia. Po chwili " "ból ustÄ™puje, ale czujesz jakby caÅ‚y twój tułów byÅ‚ zamrożony. Gdy podnosisz " "siÄ™ z ziemi, sÅ‚yszysz jowialny Å›miech. Obracasz siÄ™ i widzisz Å›nieżnego " "olbrzyma, który wbiega do lasu i znika ci z oczu." msgid "Helmet of Anduran" msgstr "HeÅ‚m Andurana" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Zauważasz lÅ›niÄ…cy przedmiot wystajÄ…cy z ziemi. WysyÅ‚asz jednego ze swych " "ludzi, aby mu siÄ™ przyjrzaÅ‚. Po chwili wraca, trzymajÄ…c w rÄ™kach zÅ‚oty heÅ‚m. " "Zdajesz sobie sprawÄ™, że musi to być heÅ‚m legendarnego Andurana, jedynego " "znanego czÅ‚owieka, który nosiÅ‚ zbrojÄ™ ze szczerego zÅ‚ota." msgid "Holy Hammer" msgstr "ÅšwiÄ™ty MÅ‚ot" #, fuzzy msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Na polu bitwy znajdujesz paladyna, Å›miertelnie zranionego przez grupÄ™ " "zombie. Prosi ciÄ™ o wziÄ™cie jego mÅ‚ota i dokoÅ„czenie tego, co zaczÄ…Å‚. Gdy " "podnosisz mÅ‚ot, rozbrzmiewa dziwnym dźwiÄ™kiem, a po chwili wszystko " "rozmazuje ci siÄ™ przed oczami. Zombie leżą martwe, a z mÅ‚ota kapie krew." msgid "Legendary Scepter" msgstr "Legendarne BerÅ‚o" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} dodaje %{count} punktów do wszystkich atrybutów." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Wspinasz siÄ™ na wzgórze i zauważasz coÅ› bardzo zabawnego. RusaÅ‚ka próbuje " "unieść berÅ‚o, które jest niemal tak duże jak ona. StarajÄ…c siÄ™ nie wybuchnąć " "Å›miechem, pytasz: \"Może pomóc?\" RusaÅ‚ka spoglÄ…da na ciebie i odpowiada: " "\"Uważasz, że to Å›mieszne? Dobrze. Trzymaj, to dla ciebie.\"" msgid "Masthead" msgstr "Top Masztowy" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} zwiÄ™ksza twoje szczęście i morale o %{count} podczas walki na morzu." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Stary marynarz opowiada ci o zaklÄ™tym topie masztowym, za pomocÄ… którego " "mobilizowaÅ‚ swÄ… zaÅ‚ogÄ™ w przypadku niebezpieczeÅ„stwa. NastÄ™pnie wrÄ™cza ci " "pożółkłą mapÄ™, na której zaznaczyÅ‚ miejsce jego ukrycia. Po dÅ‚ugich " "poszukiwaniach odnajdujesz go na pobliskiej przystani." msgid "Sphere of Negation" msgstr "Kula Negacji" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} blokuje możliwość rzucania czarów dla obu stron w walce." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Zatrzymujesz siÄ™ aby pomóc wieÅ›niakowi zÅ‚apać uciekajÄ…cÄ… klacz. ChÅ‚op w " "podziÄ™ce wrÄ™cz ci maleÅ„kÄ… kulÄ™. Kiedy tylko bierzesz jÄ… do rÄ™ki, czujesz jak " "z twych czÅ‚onków uchodzi magiczna energia..." msgid "Staff of Wizardry" msgstr "Kostur Czarodziejstwa" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} zwiÄ™ksza moc magicznÄ… o %{count}" msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "PolujÄ…c na zwierzynÄ™ twoje oddziaÅ‚y znajdujÄ… tajemniczy kostur, unoszÄ…cy siÄ™ " "mniej wiÄ™cej metr nad ziemiÄ… i przynoszÄ… go do ciebie. Zauważasz inskrypcjÄ™, " "która gÅ‚osi: \"Magia lepsza jest od miecza, a od siÅ‚y umysÅ‚ jest ważniejszy. " "PamiÄ™taj o moich sÅ‚owach, a bÄ™dziesz najpotężniejszy.\"" msgid "Sword Breaker" msgstr "Åamacz Mieczy" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} zwiÄ™ksza twojÄ… obronÄ™ o %{count} i atak o 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "ByÅ‚y kapitan straży, peÅ‚en podziwu dla twej misji, wrÄ™cza ci zaklÄ™ty Åamacz " "Mieczy, którego używaÅ‚ w czasie swojej sÅ‚użby." msgid "Sword of Anduran" msgstr "Miecz Andurana" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Zatrzymuje ciÄ™ troll, który oznajmia: \"ZapÅ‚ać mi 5000 sztuk zÅ‚ota, albo " "zginiesz od Miecza Andurana.\" Odmawiasz. Troll chwyta za miecz wiszÄ…cy mu u " "pasa, krzyczy z bólu i ucieka. Podnosisz legendarny miecz, dziÄ™kujÄ…c że " "gÅ‚upie trolle czÄ™sto chwytajÄ… ostre przedmioty z niewÅ‚aÅ›ciwej strony." msgid "Spade of Necromancy" msgstr "Szpadel Nekromancji" #, fuzzy msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} zwiÄ™ksza twojÄ… umiejÄ™tność nekromancji." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "KtoÅ› wbiÅ‚ brudny szpadel w pobliski kopiec ziemi. Po dokÅ‚adniejszym zbadaniu " "przedmiotu odkrywasz, że jest to zaklÄ™ty szpadel Grabarzy, zaginiony dawno " "temu." msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Drewno" msgid "Mercury" msgstr "Rtęć" msgid "Ore" msgstr "Ruda" msgid "Sulfur" msgstr "Siarka" msgid "Crystal" msgstr "KrysztaÅ‚" msgid "Gems" msgstr "Klejnoty" msgid "Gold" msgstr "ZÅ‚oto" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "W Heroes 2 jest siedem surowców, używanych do budowy i ulepszania miast, " "kupowania jednostek i rekrutowania bohaterów. ZÅ‚oto jest najbardziej " "pospolitym surowcem i jest potrzebne praktycznie do wszystkiego. Drewno i " "ruda sÄ… używane do budowy wiÄ™kszoÅ›ci budynków. Klejnoty, rtęć, siarka i " "krysztaÅ‚y sÄ… rzadkimi magicznymi surowcami używanymi do budowy potężnych " "budynków i rekrutowania potężnych istot." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Tworzy wielkÄ… kulÄ™ ognia w wybranym obszarze uszkadzajÄ…c wszystkie pobliskie " "jednostki." msgid "Fireball" msgstr "Kula Ognia" msgid "Fireblast" msgstr "Eksplozja Ognia" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Wzmocniona wersja Kuli Ognia, Eksplozja oddziaÅ‚uje na dwa pola wokół punktu " "centralnego czaru, zamiast na jeden." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Uderza w wybrane stworzenie za pomocÄ… energii elektrycznej." msgid "Lightning Bolt" msgstr "BÅ‚yskawica" msgid "Chain Lightning" msgstr "ÅaÅ„cuch Piorunów" #, fuzzy msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Uderza w wybrane stworzenie za pomocÄ… energii elektrycznej nastÄ™pnie " "przeskakujÄ…c na kolejne stworzenie z poÅ‚owÄ… uszkodzeÅ„ i tak dalej dopóki " "energia siÄ™ nie wyczerpie.\n" "Uwaga: Czar może uszkodzić twoje stworzenia!" msgid "Teleport" msgstr "Teleportacja" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Teleportuje wybrane stworzenia do dowolnego miejsca na polu walki." msgid "Cure" msgstr "Leczenie" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Usuwa wszelkie negatywne efekty czarów z wybranej jednostki, i przywraca do " "%{count} punktów życia na poziom Mocy." msgid "Mass Cure" msgstr "Grupowe Leczenie" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Usuwa wszystkie negatywne efekty czarów z twoich jednostek i przywraca " "%{count} punktów życia na poziom Mocy, każdemu stworzeniu." msgid "Resurrect" msgstr "Wskrzeszenie" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Wskrzesza stworzenia z uszkodzonej lub martwej jednostki do koÅ„ca walki." msgid "Resurrect True" msgstr "Prawdziwe Wskrzeszenie" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Na staÅ‚e wskrzesza z uszkodzonej lub zniszczonej jednostki." msgid "Haste" msgstr "Przyspieszenie" msgid "Increases the speed of any creature by %{count}." msgstr "ZwiÄ™ksza szybkość wszystkich twoich jednostek o %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "ZwiÄ™ksza szybkość wszystkich twoich stworzeÅ„ o %{count}." msgid "Mass Haste" msgstr "Grupowe Przyspieszenie" msgid "Slows target to half movement rate." msgstr "" "Jednostka, na którÄ… rzucone zostanie zaklÄ™cie, bÄ™dzie mieć o poÅ‚owÄ™ " "zmniejszony ruch." msgid "spell|Slow" msgstr "Spowolnienie" msgid "Mass Slow" msgstr "Grupowe Spowolnienie" msgid "Slows all enemies to half movement rate." msgstr "Wszyscy przeciwnicy majÄ… o poÅ‚owÄ™ zmniejszony ruch." msgid "spell|Blind" msgstr "OÅ›lepienie" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "OÅ›lepia wybranÄ… jednostkÄ™ nie pozwalajÄ…c jej na ruch." msgid "Bless" msgstr "BÅ‚ogosÅ‚awieÅ„stwo" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Sprawia, że wybrane stworzenia zadajÄ… maksymalne obrażenia." msgid "Causes all of your units to inflict maximum damage." msgstr "" "Sprawia, że wszystkie twoje jednostki bÄ™dÄ… zadawać maksymalne obrażenia." msgid "Mass Bless" msgstr "Grupowe BÅ‚ogosÅ‚awieÅ„stwo" msgid "Magically increases the defense skill of the selected creatures." msgstr "Magicznie podnosi współczynnik obrony wybranych stworzeÅ„." msgid "Stoneskin" msgstr "Kamienna Skóra" msgid "Steelskin" msgstr "Stalowa Skóra" #, fuzzy msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Podnosi współczynnik obrony wybranych stworzeÅ„. ZaklÄ™cie to jest ulepszonÄ… " "wersjÄ… 'Kamiennej Skóry'." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Sprawia, że wybrane stworzenia zadajÄ… minimalne obrażenia." msgid "Curse" msgstr "KlÄ…twa" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Sprawia, że wszystkie wrogie oddziaÅ‚y zadajÄ… minimalne obrażenia." msgid "Mass Curse" msgstr "Grupowa KlÄ…twa" msgid "Damages all undead in the battle." msgstr "Zadaje obrażenia wszystkim nieumarÅ‚ym na polu bitwy." msgid "Holy Word" msgstr "ÅšwiÄ™te SÅ‚owo" #, fuzzy msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Zadaje obrażenia wszystkim nieumarÅ‚ym na polu bitwy. ZaklÄ™cie to jest " "ulepszonÄ… wersjÄ… 'ÅšwiÄ™tego SÅ‚owa'." msgid "Holy Shout" msgstr "ÅšwiÄ™te ZawoÅ‚anie" msgid "Anti-Magic" msgstr "Antymagia" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Neguje dziaÅ‚anie wszystkich zaklęć na wybranej jednostce." msgid "Dispel Magic" msgstr "Rozproszenie Magii" msgid "Removes all magic spells from a single target." msgstr "Przerywa dziaÅ‚anie wszystkich zaklęć rzuconych na jednostkÄ™." msgid "Mass Dispel" msgstr "Grupowe Rozproszenie" msgid "Removes all magic spells from all creatures." msgstr "Przerywa dziaÅ‚anie wszelkich zaklęć rzuconych na wszystkie jednostki." msgid "Causes a magic arrow to strike the selected target." msgstr "Tworzy magicznÄ… strzałę, która uderza w wybrany cel." msgid "Magic Arrow" msgstr "Magiczna StrzaÅ‚a" msgid "Berserker" msgstr "SzaÅ‚ Bitewny" msgid "Causes a creature to attack its nearest neighbor." msgstr "Sprawia, że jednostka atakuje najbliższy oddziaÅ‚." msgid "Armageddon" msgstr "Armagedon" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Na pole bitwy spada Å›wiÄ™ty kataklizm, który zadaje poważne obrażenia " "wszystkim stworzeniom." msgid "Elemental Storm" msgstr "Burza Å»ywiołów" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "Nad polem bitwy przetacza siÄ™ burza żywiołów, zadajÄ…ca obrażenia wszystkim " "stworzeniom." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "W wyznaczone miejsce pola bitwy uderza deszcz meteorów, raniÄ…c wszystkie " "stworzenia w pobliżu." msgid "Meteor Shower" msgstr "Deszcz Meteorów" msgid "Paralyze" msgstr "Paraliż" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "Stworzenia dotkniÄ™te dziaÅ‚aniem tego czaru zostajÄ… sparaliżowane. Nie mogÄ… " "siÄ™ ruszać ani kontratakować." msgid "Hypnotize" msgstr "Hipnoza" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Sprawia że wybrany oddziaÅ‚ przeciwnika dostaje siÄ™ pod twojÄ… kontrolÄ™, pod " "warunkiem że jego punkty życia sÄ… %{count} razy mniejsze niż moc rzucajÄ…cego " "zaklÄ™cie." msgid "Cold Ray" msgstr "PromieÅ„ Zimna" msgid "Drains body heat from a single enemy unit." msgstr "Wysysa ciepÅ‚o z pojedynczej wrogiej jednostki." msgid "Cold Ring" msgstr "KrÄ…g Zimna" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Wysysa ciepÅ‚o ze wszystkich jednostek wokół punktu rzucenia zaklÄ™cia, z " "pominiÄ™ciem wÅ‚aÅ›nie punktu centralnego." msgid "Disrupting Ray" msgstr "PromieÅ„ OsÅ‚abienia" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Zmniejsza współczynnik obrony wrogiej jednostki o trzy punkty." msgid "Damages all living (non-undead) units in the battle." msgstr "Zadaje obrażenia wszystkim żywym jednostkom na polu bitwy." msgid "Death Ripple" msgstr "Drgawki Åšmierci" msgid "Death Wave" msgstr "Fala Åšmierci" #, fuzzy msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Zadaje obrażenia wszystkim żywym jednostkom na polu bitwy. ZaklÄ™cie to jest " "ulepszonÄ… wersjÄ… 'Drgawek Åšmierci'." msgid "Dragon Slayer" msgstr "Zabójca Smoków" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Znacznie zwiÄ™ksza umiejÄ™tność ataku jednostki w walce ze smokami." msgid "Blood Lust" msgstr "Żądza Krwi" msgid "Increases a unit's attack skill." msgstr "ZwiÄ™ksza umiejÄ™tność ataku jednostki." msgid "Animate Dead" msgstr "Ożywienie Martwych" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "Na staÅ‚e 'wskrzesza' stworzenia z uszkodzonej lub zniszczonej jednostki " "nieumarÅ‚ych." msgid "Mirror Image" msgstr "Lustrzane Odbicie" #, fuzzy msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Tworzy iluzjÄ™ jednej z twoich istniejÄ…cych jednostek. Walczy tak samo jak " "oryginalna jednostka, ale znika po otrzymaniu jakichkolwiek obrażeÅ„." msgid "Shield" msgstr "Tarcza" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Zmniejsza o poÅ‚owÄ™ obrażenia, jakie otrzymuje jedno z twoich stworzeÅ„ z " "powodu ataków dystansowych. Nie zmienia obrażeÅ„ otrzymanych od wieżyczek." msgid "Mass Shield" msgstr "Grupowa Tarcza" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Zmniejsza o poÅ‚owÄ™ obrażenia, jakie otrzymujÄ… wszystkie twoje stworzenia z " "powodu ataków dystansowych. Nie dotyczy obrażeÅ„ otrzymywanych od wieżyczek." msgid "Summon Earth Elemental" msgstr "PrzywoÅ‚anie Å»ywioÅ‚aka Ziemi" msgid "Summons Earth Elementals to fight for your army." msgstr "PrzywoÅ‚uje Å»ywioÅ‚aki Ziemi, które walczÄ… po twojej stronie." msgid "Summon Air Elemental" msgstr "PrzywoÅ‚anie Å»ywioÅ‚aka Powietrza" msgid "Summons Air Elementals to fight for your army." msgstr "PrzywoÅ‚uje Å»ywioÅ‚aki Powietrza, które walczÄ… po twojej stronie." msgid "Summon Fire Elemental" msgstr "PrzywoÅ‚anie Å»ywioÅ‚aka Ognia" msgid "Summons Fire Elementals to fight for your army." msgstr "PrzywoÅ‚uje Å»ywioÅ‚aki Ognia, które walczÄ… po twojej stronie." msgid "Summon Water Elemental" msgstr "PrzywoÅ‚anie Å»ywioÅ‚aka Wody" msgid "Summons Water Elementals to fight for your army." msgstr "PrzywoÅ‚uje Å»ywioÅ‚aki Wody, które walczÄ… po twojej stronie." msgid "Damages castle walls." msgstr "Uszkadza mury zamku." msgid "Earthquake" msgstr "TrzÄ™sienie ziemi" msgid "Causes all mines across the land to become visible." msgstr "Czar ten sprawia, że wszystkie kopalnie w krainie stajÄ… siÄ™ widoczne." msgid "View Mines" msgstr "Pokaż Kopalnie" msgid "Causes all resources across the land to become visible." msgstr "Czar ten sprawia, że wszystkie zasoby w krainie stajÄ… siÄ™ widoczne." msgid "View Resources" msgstr "Pokaż Zasoby" msgid "Causes all artifacts across the land to become visible." msgstr "Czar ten sprawia, że wszystkie artefakty w krainie stajÄ… siÄ™ widoczne." msgid "View Artifacts" msgstr "Pokaż Artefakty" msgid "Causes all towns and castles across the land to become visible." msgstr "" "Czar ten sprawia, że wszystkie miasta i zamki w krainie stajÄ… siÄ™ widoczne." msgid "View Towns" msgstr "Pokaż Miasta" msgid "Causes all Heroes across the land to become visible." msgstr "Czar ten sprawia, że wszyscy bohaterowie w krainie stajÄ… siÄ™ widoczni." msgid "View Heroes" msgstr "Pokaż Bohaterów" msgid "Causes the entire land to become visible." msgstr "Czar ten sprawia, że widoczna staje siÄ™ caÅ‚a kraina." msgid "View All" msgstr "Pokaż Wszystko" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" "Pozwala osobie rzucajÄ…cej zaklÄ™cie zobaczyć szczegółowe informacje na temat " "bohaterów wroga." msgid "Summon Boat" msgstr "PrzywoÅ‚anie Åodzi" #, fuzzy msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "PrzywoÅ‚uje najbliższÄ…, niezajÄ™tÄ…, wÅ‚asnÄ… łódź na sÄ…siadujÄ…cy z tobÄ… fragment " "wybrzeża. WÅ‚asna łódź to taka, która zostaÅ‚a przez ciebie zbudowana, lub " "byÅ‚a ostatnio przez ciebie użytkowana." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Pozwala osobie rzucajÄ…cej zaklÄ™cie magicznie przenieść siÄ™ w inne, pobliskie " "miejsce." msgid "Dimension Door" msgstr "Brama miÄ™dzy Wymiarami" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Pozwala bohaterowi rzucajÄ…cemu zaklÄ™cie przenieść siÄ™ do najbliższego " "wÅ‚asnego miasta lub zamku." msgid "Town Gate" msgstr "Miejska Brama" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Przenosi bohatera do wybranego zamku lub miasta, znajdujÄ…cego siÄ™ pod twojÄ… " "kontrolÄ…." msgid "Visions" msgstr "Wizje" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "ZaklÄ™cie to pozwala przewidzieć prawdopodobny wynik starcia z neutralnÄ… " "armiÄ…." msgid "Haunt" msgstr "Nawiedzenie" #, fuzzy msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Sprawia, że jednÄ… z twych kopalni nawiedzajÄ… Duchy. Kopalnia zaprzestaje " "wydobycia. (JeÅ›li nie mogÄ™ jej mieć, to nikt jej mieć nie bÄ™dzie!)" msgid "Set Earth Guardian" msgstr "Ustawienie Strażnika Ziemi" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Wzywa Å»ywioÅ‚aki Ziemi, które pilnujÄ… kopalni przed wrogimi armiami." msgid "Set Air Guardian" msgstr "Ustawienie Strażnika Powietrza" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" "Wzywa Å»ywioÅ‚aki Powietrza, które pilnujÄ… kopalni przed wrogimi armiami." msgid "Set Fire Guardian" msgstr "Ustawienie Strażnika Ognia" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Wzywa Å»ywioÅ‚aki Ognia, które pilnujÄ… kopalni przed wrogimi armiami." msgid "Set Water Guardian" msgstr "Ustawienie Strażnika Wody" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Wzywa Å»ywioÅ‚aki Wody, które pilnujÄ… kopalni przed wrogimi armiami." #, fuzzy msgid "Random Spell" msgstr "Losowa" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "Losowy zamek" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "Zamiana w KamieÅ„" #, fuzzy msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Zmienia dotkniÄ™te stworzenie w kamieÅ„. SkamieniaÅ‚a jednostka otrzymuje " "poÅ‚owÄ™ obrażeÅ„ z ataku wrÄ™cz." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Nie posiadasz KsiÄ™gi Zaklęć, wiÄ™c nie możesz rzucić zaklÄ™cia." msgid "No spell to cast." msgstr "Brak zaklęć." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Twój bohater ma jeszcze %{point} pkt. magii." msgid "View Adventure Spells" msgstr "Obejrzyj zaklÄ™cia podróżne" msgid "View Combat Spells" msgstr "Obejrzyj zaklÄ™cia bojowe" msgid "View previous page" msgstr "Obejrzyj poprzedniÄ… stronÄ™" msgid "View next page" msgstr "Obejrzyj nastÄ™pnÄ… stronÄ™" msgid "Close Spellbook" msgstr "Zamknij KsiÄ™gÄ™ Zaklęć" msgid "View %{spell}" msgstr "Obejrzyj zaklÄ™cie %{spell}" msgid "This spell does %{damage} points of damage." msgstr "To zaklÄ™cie zada %{damage} pkt. obrażeÅ„." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Ten czar przywoÅ‚uje\n" "%{count} %{monster}" msgid "This spell restores %{hp} HP." msgstr "Ten czar przywróci %{hp} punktów życia." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Ten czar przywoÅ‚a %{count} %{monster} do pilnowania kopalni." msgid "The nearest town is %{town}." msgstr "Najbliższym miastem jest %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "To miasto jest zajÄ™te przez twojego bohatera %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "ZaklÄ™cie kontroluje do\n" "%{hp} punktów życia." msgid "The ultimate artifact is really the %{name}." msgstr "%{name} to naprawdÄ™ najpotężniejszy artefakt." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Najpotężniejszy artefakt można znaleźć w %{name} części Å›wiata." msgid "north-west" msgstr "północno-zachodniej" msgid "north" msgstr "północnej" msgid "north-east" msgstr "północno-wschodniej" msgid "west" msgstr "zachodniej" msgid "center" msgstr "centralnej" msgid "east" msgstr "wschodniej" msgid "south-west" msgstr "poÅ‚udniowo-zachodniej" msgid "south" msgstr "poÅ‚udniowej" msgid "south-east" msgstr "poÅ‚udniowo-wschodniej" msgid "The truth is out there." msgstr "GdzieÅ› tam jest prawda." msgid "The dark side is stronger." msgstr "Mroczna strona jest silniejsza." msgid "The end of the world is near." msgstr "Zbliża siÄ™ koniec Å›wiata." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "KoÅ›ci Lorda Slayera sÄ… zakopane w fundamentach areny." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Czarny smok pokona Tytana w dowolny dzieÅ„ tygodnia." #, fuzzy msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" "On powiedziaÅ‚: Yada yada yada... ona odpowiedziaÅ‚a: Blah, blah, blah..." msgid "An unknown force is being resurrected..." msgstr "Nieznana siÅ‚a jest wskrzeszana…" msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Możesz pobrać najnowszÄ… wersjÄ™ gry ze strony:\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Wybierz ilość %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Automatyczna walka" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "zakoÅ„cz walkÄ™ w automatycznym trybie walki" #~ msgid "Please Remember" #~ msgstr "PamiÄ™taj" # Needs extra whitespace to avoid yellow word splitting #, fuzzy #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Możesz zawsze zmienić rozdzielczość klikajÄ…c na\n" #~ " " #~ msgid "door" #~ msgstr "drzwi" #, fuzzy #~ msgid "NEW GAME" #~ msgstr "" #~ "NOWA\n" #~ "GRA" #~ msgid "Warning!" #~ msgstr "Uwaga!" #~ msgid "Dummy 1" #~ msgstr "Artefakt 1" fheroes2-1.1.6+dfsg/files/lang/pt.po000066400000000000000000012212751476115357100172050ustar00rootroot00000000000000# Brazilian Portuguese translation for fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-12-23 08:39-0300\n" "Last-Translator: fheroes2 team \n" "Language-Team: Brazilian Portuguese \n" "Language: pt_BR\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-Launchpad-Export-Date: 2010-05-27 09:12+0000\n" "X-Generator: Poedit 3.5\n" msgid "" "NEW\n" "GAME" msgstr "" "NOVO\n" "JOGO" msgid "" "SAVE\n" "GAME" msgstr "" "SALVAR\n" "JOGO" msgid "" "LOAD\n" "GAME" msgstr "" "CARREGAR\n" "JOGO" msgid "INFO" msgstr "INFO." msgid "QUIT" msgstr "SAIR" msgid "" "NEW\n" "MAP" msgstr "" "NOVO\n" "MAPA" msgid "" "SAVE\n" "MAP" msgstr "" "SALVAR\n" "MAPA" msgid "" "LOAD\n" "MAP" msgstr "" "CARREGAR\n" "MAPA" msgid "CANCEL" msgstr "CANCELAR" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "ACEITAR" msgid "DECLINE" msgstr "RECUSAR" msgid "LEARN" msgstr "APRENDER" msgid "TRADE" msgstr "TROCAR" msgid "YES" msgstr "SIM" msgid "NO" msgstr "NÃO" msgid "EXIT" msgstr "SAIR" msgid "smallerButton|EXIT" msgstr "SAIR" msgid "DISMISS" msgstr "DISPENSAR" msgid "UPGRADE" msgstr "MELHORAR" msgid "RESTART" msgstr "REINICIAR" msgid "HEROES" msgstr "HERÓIS" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "CIDADES/\n" "CASTELOS" msgid "S" msgstr "P" msgid "M" msgstr "M" msgid "L" msgstr "G" msgid "X-L" msgstr "GG" msgid "ALL" msgstr "TODOS" msgid "SELECT" msgstr "SELEC." msgid "" "STANDARD\n" "GAME" msgstr "" "JOGO\n" "PADRÃO" msgid "" "BATTLE\n" "ONLY" msgstr "" "APENAS\n" "BATALHA" msgid "" "CAMPAIGN\n" "GAME" msgstr "" "CAMPA-\n" "NHA" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "JOGO\n" "MULTI-\n" "JOGADOR" msgid "CONFIG" msgstr "AJUSTES" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "ORIGINAL" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "EXPANSÃO" msgid "HOT SEAT" msgstr "" "JOGO EM\n" "RODÃZIO" msgid "2 PLAYERS" msgstr "2 JOGADORES" msgid "3 PLAYERS" msgstr "3 JOGADORES" msgid "4 PLAYERS" msgstr "4 JOGADORES" msgid "5 PLAYERS" msgstr "5 JOGADORES" msgid "6 PLAYERS" msgstr "6 JOGADORES" msgid "GIFT" msgstr "PRESENTE" msgid "MAX" msgstr "MÃX" msgid "DIFFICULTY" msgstr "DIFICULDADE" msgid "VIEW INTRO" msgstr "VER INTRO" msgid "MIN" msgstr "MÃN." msgid "RESET" msgstr "REINICIAR" msgid "START" msgstr "INICIAR" msgid "TOWN" msgstr "CIDADE" msgid "CASTLE" msgstr "CASTELO" msgid "RESTRICT" msgstr "RESTRINGIR" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "D\n" "I\n" "S\n" "P\n" "E\n" "N\n" "S\n" "A\n" "R" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "S\n" "A\n" "I\n" "R" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "P\n" "A\n" "T\n" "R\n" "U\n" "L\n" "H\n" "A\n" "R" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "C\n" "A\n" "M\n" "P\n" "A\n" "N\n" "H\n" "A" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "P\n" "A\n" "D\n" "R\n" "Ã\n" "O" msgid "RUMORS" msgstr "RUMORES" msgid "EVENTS" msgstr "EVENTOS" msgid "LANGUAGE" msgstr "IDIOMA" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Guerreiro" msgid "Builder" msgstr "Construtor" msgid "Explorer" msgstr "Explorador" msgid "None" msgstr "Nenhum" msgid "" "A few\n" "%{monster}" msgstr "" "Alguns\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Vários\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Um grupo de\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Muitos\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Uma horda de\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Uma multidão de\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Um enxame de\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Um grande número de\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Uma legião de\n" "%{monster}" msgid "army|Few" msgstr "Alguns" msgid "army|Several" msgstr "Vários" msgid "army|Pack" msgstr "Um grupo" msgid "army|Lots" msgstr "Muitos" msgid "army|Horde" msgstr "Uma horda" msgid "army|Throng" msgstr "Uma multidão" msgid "army|Swarm" msgstr "Um enxame" msgid "army|Zounds" msgstr "Um grande número" msgid "army|Legion" msgstr "Uma legião" msgid "All %{race} troops +1" msgstr "+1 para todas as tropas de %{race}" msgid "NeutralRaceTroops|Neutral" msgstr "Neutra" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Tropas de %{count} alinhamentos -%{penalty}" msgid "Some undead in army -1" msgstr "Alguns mortos-vivos no exército -1" msgid "" "Default\n" "troop" msgstr "" "Tropa\n" "padrão" msgid "View %{name}" msgstr "Ver %{name}" msgid "Move the %{name} " msgstr "Mover %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Mova ou clique com o botão direito para redistribuir %{name}" msgid "Combine %{name} armies" msgstr "Combinar os exércitos de %{name}" msgid "Exchange %{name2} with %{name}" msgstr "Trocar %{name2} por %{name}" msgid "Select %{name}" msgstr "Selecionar %{name}" msgid "Cannot move last troop" msgstr "Não é possível mover a última tropa" msgid "Move the %{name}" msgstr "Mover %{name}" msgid "Set %{monster} Count" msgstr "Definir Quantidade de %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} destrói metade das tropas inimigas!" msgstr[1] "%{name} destroem metade das tropas inimigas!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} desativou a batalha automática" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} ativou a batalha automática" msgid "Spell failed!" msgstr "O feitiço falhou!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "O artefato Esfera da Negação está ativo para esta batalha, desativando todos " "os feitiços de combate." msgid "You cannot cast spells without a commanding hero." msgstr "Você não pode lançar feitiços sem um herói no comando." msgid "You have already cast a spell this round." msgstr "Você já lançou um feitiço neste turno." msgid "That spell will have no effect!" msgstr "Esse feitiço não terá efeito!" msgid "You may only summon one type of elemental per combat." msgstr "Você só pode invocar um tipo de elemental por combate." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Não há espaço aberto adjacente ao seu herói para onde você possa invocar um " "elemental." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "O fosso reduz a Habilidade de Defesa das tropas presas nele em %{count} e " "restringe seu raio de movimento." msgid "Speed: %{speed}" msgstr "Velocidade: %{speed}" msgid "Speed" msgstr "Velocidade" msgid "Off" msgstr "Desativar" msgid "On" msgstr "Ativar" msgid "Turn Order" msgstr "Ordem de Turno" msgid "Auto Spell Casting" msgstr "Auto Feitiço" msgid "Grid" msgstr "Grade" msgid "Shadow Movement" msgstr "Sombra de Movimento" msgid "Shadow Cursor" msgstr "Sombra do Cursor" msgid "Audio" msgstr "Ãudio" msgid "Settings" msgstr "Configurar" msgid "Configure" msgstr "Configurar" msgid "Hot Keys" msgstr "Atalhos" msgid "Damage Info" msgstr "Informação do Dano" msgid "Set the speed of combat actions and animations." msgstr "Definir a velocidade das ações de combate e animações." msgid "Toggle to display the turn order during the battle." msgstr "Alternar para exibir a ordem de turno durante a batalha." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Ativa ou desativa o lançamento de feitiços pelo computador quando o combate " "automático está ativado. (Nota: Isto não afeta o lançamento de feitiços para " "jogadores controlados pelo computador nem afeta o combate rápido)." msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Ativa ou desativa a grade hexagonal. A grade hexagonal está sempre " "subjacente ao movimento, mesmo se desativada. Esta opção apenas determina se " "a grade estará visível." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Ativa ou desativa as sombras que mostram onde suas criaturas podem se mover " "e atacar." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Ativa ou desativa uma sombra que mostra a localização atual do hexágono do " "cursor do mouse." msgid "Change the audio settings of the game." msgstr "Altera as configurações de áudio do jogo." msgid "Check and configure all the hot keys present in the game." msgstr "Verifica e configura todas as teclas de atalho do jogo." msgid "Toggle to display damage information during the battle." msgstr "" "Ativa ou desativa a exibição das informações de dano durante a batalha." msgid "Exit this menu." msgstr "Sair deste menu." msgid "Okay" msgstr "OK" msgid "The enemy has surrendered!" msgstr "O inimigo se rendeu!" msgid "Their cowardice costs them %{gold} gold." msgstr "A covardia deles lhes custa %{gold} de ouro." msgid "The enemy has fled!" msgstr "O inimigo fugiu!" msgid "A glorious victory!" msgstr "Uma vitória gloriosa!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Por sua coragem em combate, %{name} recebe %{exp} de experiência." msgid "The cowardly %{name} flees from battle." msgstr "%{name} se acovarda e foge da batalha." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} rende-se ao inimigo, e retira-se com vergonha." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Suas forças sofrem uma amarga derrota, e %{name} abandona sua causa." msgid "Your forces suffer a bitter defeat." msgstr "Suas forças sofrem uma amarga derrota." msgid "Battlefield Casualties" msgstr "Baixas no Campo de Batalha" msgid "Attacker" msgstr "Agressor" msgid "Defender" msgstr "Defensor" msgid "Click to leave the battle results." msgstr "Clique para sair dos resultados da batalha." msgid "Click to restart the battle in manual mode." msgstr "Clique para reiniciar a batalha no modo manual." msgid "Restart" msgstr "Reiniciar" msgid "You have captured an enemy artifact!" msgstr "Você capturou um artefato inimigo!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "À medida que você alcança %{name}, ele desaparece misteriosamente." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" "À medida que seu inimigo alcança %{name}, ele desaparece misteriosamente." msgid "Necromancy!" msgstr "Necromancia!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Praticando as artes negras da necromancia, você foi capaz de ressuscitar " "%{count} dos inimigos mortos para retornar sob seu serviço como %{monster}." msgid "%{name} the %{race}" msgstr "%{name}: %{race}" msgid "Captain of %{name}" msgstr "Capitão de %{name}" msgid "Attack" msgstr "Ataque" msgid "Defense" msgstr "Defesa" msgid "Spell Power" msgstr "Poder Mágico" msgid "Knowledge" msgstr "Conhecimento" msgid "Morale" msgstr "Moral" msgid "Luck" msgstr "Sorte" msgid "Spell Points" msgstr "Mana" msgid "Hero's Options" msgstr "Opções do Herói" msgid "Cast Spell" msgstr "Lançar Feitiço" msgid "Retreat" msgstr "Retirar-se" msgid "Surrender" msgstr "Render-se" msgid "Cancel" msgstr "Cancelar" msgid "Hero Screen" msgstr "Tela do Herói" msgid "Captain's Options" msgstr "Opções do Capitão" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Lança um feitiço mágico. Você só pode lançar um feitiço por turno de " "combate. O turno é reiniciado quando cada criatura tiver jogado um turno." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Bater em retirada com seu herói, abandonando as suas criaturas. Seu herói " "estará disponível para recrutar mais uma vez, no entanto, o herói terá " "apenas as tropas iniciais." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Render-se custa ouro. No entanto, se você pagar o resgate, o herói e todas " "as criaturas sobreviventes estarão disponíveis para recrutar novamente. O " "custo da rendição é a metade do custo total das tropas não temporárias " "restantes no exército." msgid "Open Hero Screen to view full information about the hero." msgstr "Abra a Tela do Herói para ver todas as informações sobre ele." msgid "Return to the battle." msgstr "Retornar à batalha." msgid "Not enough gold (%{gold})" msgstr "Ouro insuficiente (%{gold})" msgid "%{name} states:" msgstr "%{name} declara:" msgid "Captain of %{name} states:" msgstr "Capitão de %{name} declara:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Aceitarei sua rendição e concederei a você e a suas tropas uma passagem " "segura pelo preço de %{price} ouro.\"" msgid "View %{monster} info" msgstr "Ver informação de %{monster}" msgid "Fly %{monster} here" msgstr "Voar com %{monster} até aqui" msgid "Move %{monster} here" msgstr "Mover %{monster} até aqui" msgid "Shoot %{monster}" msgstr "Disparar em %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 disparo restante)" msgstr[1] "(%{count} disparos restantes)" msgid "Attack %{monster}" msgstr "Atacar %{monster}" msgid "Turn %{turn}" msgstr "Turno %{turn}" msgid "Teleport here" msgstr "Teletransportar-se até aqui" msgid "Invalid teleport destination" msgstr "Destino de teletransporte inválido" msgid "Cast %{spell} on %{monster}" msgstr "Lançar %{spell} em %{monster}" msgid "Cast %{spell}" msgstr "Lançar %{spell}" msgid "Select spell target" msgstr "Selecionar alvo do feitiço" msgid "View Ballista info" msgstr "Ver informações da Balista" msgid "Ballista" msgstr "Balista" #, fuzzy msgid "Automatic combat modes" msgstr "Combate Automático" #, fuzzy msgid "Automatic Combat Modes" msgstr "Combate Automático" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Personalizar opções do sistema" msgid "Allows you to customize the combat screen." msgstr "Permite personalizar a tela de combate." msgid "System Options" msgstr "Opções do Sistema" msgid "Skip this unit" msgstr "Pular o turno desta unidade" msgid "Skip" msgstr "Pular" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Pula a criatura atual. A criatura atual termina sua vez e não faz seu " "movimento até o próximo turno." msgid "View Captain's options" msgstr "Ver as opções do Capitão" msgid "View Hero's options" msgstr "Ver as opções do Herói" msgid "View opposing Captain" msgstr "Ver Capitão oponente" msgid "View opposing Hero" msgstr "Ver Herói oponente" msgid "Hide logs" msgstr "Ocultar registro" msgid "Show logs" msgstr "Mostrar registros" msgid "Message Bar" msgstr "Barra de Mensagem" msgid "Shows the results of individual monster's actions." msgstr "Mostra os resultados das ações individuais dos monstros." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Tem certeza de que deseja habilitar o combate automático?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Você tem certeza de que deseja terminar a batalha no modo automático?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Permite que o computador lute a batalha por você." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Combate Automático" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Combate Automático" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} pula sua vez." msgstr[1] "%{name} pulam sua vez." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} causa %{damage} de dano." msgstr[1] "%{damage} de dano de %{attacker}." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 criatura morreu." msgstr[1] "%{count} criaturas morreram." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} morreu." msgstr[1] "%{count} %{defender} morreram." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 alma é incorporada." msgstr[1] "%{count} almas são incorporadas." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} revive." msgstr[1] "%{count} %{unit} revivem." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Movimento de %{monster}: de [%{src}] para [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} resiste ao feitiço!" msgstr[1] "%{name} resistem ao feitiço!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} lança(m) %{spell} sobre %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} lança %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} causa %{damage} de dano a uma criatura morta-viva." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} causa %{damage} de dano a todas as criaturas mortas-vivas." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} causa %{damage} de dano, %{count} criaturas morreram." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} causa %{damage} de dano." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} causa %{damage} de dano a uma criatura viva." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} causa %{damage} de dano a todos as criaturas vivas." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "O ataque de %{attacker} cega %{target}!" msgstr[1] "O ataque dos %{attacker} cega %{target}!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "O olhar da %{attacker} transforma %{target} em pedra!" msgstr[1] "O olhar das %{attacker} transforma %{target} em pedra!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "A maldição da %{attacker} cai sobre %{target}!" msgstr[1] "A maldição das %{attacker} cai sobre %{target}!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{target} é paralisado por %{attacker}!" msgstr[1] "%{target} é paralisado pelos %{attacker}!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "O %{attacker} anula todos os feitiços bons em seu %{target}!" msgstr[1] "Os %{attacker} anulam todos os feitiços bons em seu %{target}!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} lança %{spell} em %{target}!" msgstr[1] "%{attacker} lançam %{spell} em %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "O azar recai em %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "A boa sorte recai em %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "A moral alta permite que %{monster} ataque novamente." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "A baixa moral faz com que %{monster} paralise em pânico." msgid "%{tower} does %{damage} damage." msgstr "%{tower} causa %{damage} de dano." msgid "The mirror image is created." msgstr "A imagem espelhada foi criada." msgid "The mirror image is destroyed!" msgstr "A imagem espelhada foi destruída!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Tem certeza de que deseja interromper o combate automático?" msgid "Error" msgstr "Erro" msgid "No spells to cast." msgstr "Sem feitiços para lançar." msgid "Are you sure you want to retreat?" msgstr "Você tem certeza de que deseja se retirar?" msgid "Retreat disabled" msgstr "Retirada desativada" msgid "Surrender disabled" msgstr "Rendição desativada" msgid "Damage: %{max}" msgstr "Dano: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Dano: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Morrem: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Morrem: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Através da observação com os olhos de águia, %{name} foi capaz de aprender o " "feitiço %{spell}." msgid "Human" msgstr "Humano" msgid "AI" msgstr "IA" msgid "Start" msgstr "Iniciar" msgid "Start the battle." msgstr "Iniciar a batalha." msgid "Exit" msgstr "Sair" msgid "Reset" msgstr "Restaurar" msgid "Reset to default settings." msgstr "Restaurar as configurações padrões." msgid "Please select another hero." msgstr "Por favor, selecione outro herói." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} vs %{race2} %{name2}" msgid "Monsters" msgstr "Monstros" msgid "N/A" msgstr "N/D" msgid "Left Turret" msgstr "Torre Esquerda" msgid "Right Turret" msgstr "Torre Direita" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} dispara com a força de %{count} Arqueiros" msgid "each with a +%{attack} bonus to their attack skill." msgstr "cada um com um bônus de +%{attack} para sua Habilidade de Ataque." msgid "The %{name} is destroyed." msgstr "%{name} foi destruído." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} se ergue dos mortos!" msgstr[1] "%{count} %{name} se erguem dos mortos!" msgid "Dwarven Alliance" msgstr "Aliança Anã" msgid "Sorceress Guild" msgstr "Guilda de Feiticeiras" msgid "Necromancer Guild" msgstr "Guilda de Necromantes" msgid "Ogre Alliance" msgstr "Aliança dos Ogros" msgid "Dwarfbane" msgstr "Flagelo Anão" msgid "Dragon Alliance" msgstr "Aliança dos Dragões" msgid "Elven Alliance" msgstr "Aliança Élfica" msgid "Kraeger defeated" msgstr "Kraeger derrotado" msgid "Wayward Son" msgstr "Filho Rebelde" msgid "Uncle Ivan" msgstr "Tio Ivan" msgid "Annexation" msgstr "Anexação" msgid "Force of Arms" msgstr "Força das Armas" msgid "Save the Dwarves" msgstr "Salve os Anões" msgid "Carator Mines" msgstr "Minas de Carator" msgid "Turning Point" msgstr "Momento Decisivo" msgid "scenarioName|Defender" msgstr "Defensor" msgid "Corlagon's Defense" msgstr "A Defesa de Corlagon" msgid "The Crown" msgstr "A Coroa" msgid "The Gauntlet" msgstr "A Corrida" msgid "Betrayal" msgstr "Traição" msgid "Final Justice" msgstr "Justiça Final" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland precisa que você derrote os lordes próximos ao seu castelo para " "começar sua guerra de rebelião contra seu irmão. Eles não são aliados entre " "si, então eles passarão a maior parte do tempo lutando um contra o outro. A " "vitória será sua quando você tiver derrotado todos os seus castelos e heróis." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Os lordes locais recusam-se a jurar fidelidade a Roland, e devem ser " "subjugados. Eles são ricos e poderosos, portanto esteja preparado para uma " "luta dura. Capture todos os castelos inimigos para vencer." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Sua tarefa é defender os Anões contra as forças de Archibald. Capture todas " "as cidades e castelos inimigos para ganhar, e certifique-se de não perder " "todas as cidades anãs de uma só vez, ou o inimigo vencerá." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Você enfrentará quatro inimigos aliados em uma luta direta por recursos e " "tesouros. Capture todos os castelos inimigos para vencer." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Seus inimigos são aliados contra você e começam por perto, portanto esteja " "pronto para sair lutando. Você precisará possuir todos os quatro castelos " "neste pequeno vale para vencer." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "A Guilda das Feiticeiras de Noraston solicitou a ajuda de Roland contra um " "ataque dos aliados de Archibald. Capture todos os castelos inimigos para " "ganhar, e não perca Noraston, ou você perderá o cenário. (Dica: Há um " "castelo inimigo em uma ilha no oceano)." msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Reúna o maior exército possível e capture o castelo inimigo em 8 semanas. " "Você se opõe a apenas um inimigo, mas deve percorrer um longo caminho para " "chegar ao castelo inimigo. Quaisquer tropas que você tenha em seu exército " "no final deste cenário estarão com você na batalha final." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Encontre a Coroa antes que os heróis de Archibald a encontrem. Roland vai " "precisar da Coroa para a batalha final contra Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Três inimigos aliados estão no seu caminho até a vitória, incluindo o Lorde " "Corlagon. Roland está em um castelo a noroeste, e você perderá se ele cair " "para o inimigo. Lembre-se de que capturar o Lorde Corlagon garantirá que ele " "não irá lutar contra você no cenário final." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Esta é a batalha final. Tanto você como seu inimigo estão armados até os " "dentes, e todos estão contra você. Capture Archibald para acabar com a " "guerra!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "A troca de lado deixa você com três castelos contra o do inimigo. Esta " "batalha será a mais fácil que você enfrentará durante o resto da guerra... " "traidor." msgid "Barbarian Wars" msgstr "Guerras Bárbaras" msgid "First Blood" msgstr "Sangue Primeiro" msgid "Necromancers" msgstr "Necromantes" msgid "Slay the Dwarves" msgstr "Matem os Anões" msgid "Country Lords" msgstr "Lordes das Terras" msgid "Dragon Master" msgstr "Mestre Dragão" msgid "Rebellion" msgstr "Rebelião" msgid "Apocalypse" msgstr "Apocalipse" msgid "Greater Glory" msgstr "Maior Glória" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "O Rei Archibald exige que você derrote os três inimigos nesta região. Eles " "não são aliados um do outro, por isso gastarão a maior parte de sua energia " "lutando entre si. Vocês vencerão quando forem donos de todos os castelos " "inimigos e não restar mais heróis para lutar." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "É preciso unificar as tribos bárbaras do norte, conquistando-as. Como na " "missão anterior, os inimigos não estão aliados contra você, mas eles têm " "mais recursos à sua disposição. Vocês vencerão quando forem donos de todos " "os castelos inimigos e não restar mais heróis para lutar." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Os magos do bem tomaram o castelo dos Necromantes. É preciso retomá-lo para " "alcançar a vitória. Lembre-se que enquanto você começa com um exército " "poderoso, você não tem castelo e deve tomar um dentro de 7 dias, ou perderá " "esta batalha. (Dica: O castelo mais próximo é o do sudeste)." msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Os anões precisam ser conquistados antes que possam interferir nos planos do " "Rei Archibald. As forças de Roland têm mais de um herói e muitas cidades por " "onde começar, portanto, esteja pronto para ataques de várias direções. Você " "deve capturar todas as cidades e castelos inimigos para reivindicar a " "vitória." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Você deve suprimir uma revolta de camponeses liderada pelas forças de " "Roland. Todos estão aliados contra você, mas você tem o Lorde Corlagon, um " "herói experiente, para ajudá-lo. Capture todos os castelos inimigos para " "vencer." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Há dois inimigos aliados contra você nesta missão. Ambos estão bem armados e " "procuram expulsá-lo de sua ilha. Evite-os e capture a Cidade Dragão para " "vencer." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Suas ordens são para conquistar os Lordes das Terras que juraram servir a " "Roland. Todos os castelos inimigos estão unificados contra vocês. Já que " "você começa sem castelo, você deve se apressar para capturar um antes do " "final da semana. Capture todos os castelos inimigos para obter a vitória." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Encontre a Coroa antes que os heróis de Roland a encontrem. Archibald vai " "precisar da Coroa para a batalha final contra Roland." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Esta é a batalha final. Tanto você quanto seu inimigo estão armados até os " "dentes, e todos estão aliados contra você. Capture Roland para ganhar a " "guerra, e não perca Archibald na luta!" msgid "Arrow's Flight" msgstr "Voo da Flecha" msgid "Island of Chaos" msgstr "Ilha do Caos" msgid "The Abyss" msgstr "O Abismo" msgid "Uprising" msgstr "Insurreição" msgid "Aurora Borealis" msgstr "Aurora Boreal" msgid "Betrayal's End" msgstr "Fim da Traição" msgid "Corruption's Heart" msgstr "Coração da Corrupção" msgid "The Giant's Pass" msgstr "O Passo do Gigante" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Subjugue os lordes locais indisciplinados a fim de proporcionar ao Império " "instalações para operar nesta região." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Elimine toda a oposição nessa área. Então, a primeira peça do artefato será " "sua." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "As feiticeiras do nordeste estão se rebelando! Para o bem do império, é " "preciso acabar com a frágil insurreição delas no seu caminho para as " "montanhas." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Tendo se preparado para sua chegada, Kraeger providenciou uma força de " "necromantes para frustrar sua missão. Você deve capturar o castelo de " "Scabsdale antes do primeiro dia da terceira semana, ou os Necromantes serão " "fortes demais para você." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "O déspota bárbaro nesta área ainda não sabe de sua presença. Rápido, " "fortaleça suas forças antes que você seja descoberto e atacado! Proteja a " "região, subjugando todas as forças inimigas." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "O Império é fraco nesta região. Você será incapaz de dominar completamente " "todas as forças nesta área, então pegue o que puder antes de atacar. Lembre-" "se, seu verdadeiro objetivo é reivindicar o Elmo de Anduran." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Para o bem do Império, elimine Kraeger." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Finalmente, você tem a oportunidade e as instalações para livrar o Império " "do mal Necromante. Erradique-os completamente, e você será eternamente " "entoado como um herói." msgid "Border Towns" msgstr "Cidades Fronteiriças" msgid "Conquer and Unify" msgstr "Conquistar e Unificar" msgid "Crazy Uncle Ivan" msgstr "Tio Ivan, o Louco" msgid "The Wayward Son" msgstr "O Filho Rebelde" msgid "Ivory Gates" msgstr "Portões de Marfim" msgid "The Elven Lands" msgstr "As Terras Élficas" msgid "The Epic Battle" msgstr "A Batalha Épica" msgid "The Southern War" msgstr "A Guerra do Sul" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Conquiste e unifique todas as tribos inimigas. Não perca o herói Jarkonas, o " "antepassado de todos os descendentes." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Seu rival, o Reino de Harondale, está atacando cidades fracas em sua " "fronteira! Recupere-se de seu primeiro ataque e esmague-os completamente!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Encontre seu filho Joseph, que dizem que está vivendo em terras desoladas. " "Faça isso antes do primeiro dia do terceiro mês ou não será de nenhuma ajuda " "para sua família." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Resgate seu tio louco, Ivan. Encontre-o antes do primeiro dia do quarto mês " "ou não será de grande ajuda para o seu reino." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Destrua os bárbaros que estão atacando a fronteira sul de seu reino! " "Recupere suas cidades caídas, e depois invada o reino da selva. Não deixe " "nenhum inimigo de pé." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Retome o castelo Portões de Marfim, que caiu devido à traição." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Ganhe o favor dos elfos. Eles não permitirão que as árvores sejam cortadas, " "então nós enviar-lhe-emos madeira a cada 2 semanas. Você deve completar sua " "missão antes do primeiro dia do sétimo mês, ou o reino certamente cairá." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Esta é a batalha final contra seu reino rival de Harondale. Elimine todos, e " "não perca o herói Jarkonas VI." msgid "Fount of Wizardry" msgstr "Fonte de Feitiçaria" msgid "Power's End" msgstr "Fim do Poder" msgid "The Eternal Scrolls" msgstr "Os Pergaminhos Eternos" msgid "The Shrouded Isles" msgstr "As Ilhas Nebulosas" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Sua missão é derrotar os magos em guerra nas mágicas Ilhas Nebulosas. A " "conclusão desta tarefa lhe dará uma chance de lutar contra seus rivais." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "A localização da grande biblioteca foi descoberta! É preciso ir até ela e " "recuperar a cidade de Chronos onde ela se encontra." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Encontre a Esfera da Negação, que dizem estar enterrada nesta terra. Há " "pistas inscritas em obeliscos de pedra que o ajudarão a chegar ao seu " "destino. Encontre a esfera antes do primeiro dia do sexto mês, ou seus " "rivais certamente chegarão antes de você." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Você deve tomar o controle do castelo da Mágica, onde se encontra a fonte da " "feitiçaria. Faça isso e sua vitória será suprema." msgid "Blood is Thicker" msgstr "O Sangue é Mais Espesso" msgid "King and Country" msgstr "Rei e Terras" msgid "Pirate Isles" msgstr "Ilhas Piratas" msgid "Stranded" msgstr "Encalhado" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Capture a cidade na ilha ao largo da costa sudeste, a fim de construir um " "barco e viajar de volta para o continente. Não perca o herói Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Encontre e derrote Martine, a líder pirata, que reside na Baía Pirata. Não " "perca Gallavant ou sua missão estará terminada." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Elimine todas as outras forças que se opõem ao governo do Lorde Alberon. " "Gallavant não deve morrer." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Derrube a monarquia entrincheirada de Lorde Alberon e reivindique todas as " "terras em seu nome. Gallavant não deve morrer." msgid " bane" msgstr " flagelo" msgid " alliance" msgstr " aliança" msgid "Carry-over forces" msgstr "Forças de transporte" msgid " bonus" msgstr " bônus" msgid " defeated" msgstr " derrotado" msgid " will always run away from your army." msgstr " sempre fugirá de seu exército." msgid " will be willing to join your army." msgstr " estará disposto a se alistar em seu exército." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "O artefato \"%{artifact}\" será transportado na campanha." msgid "The army will be carried over in the campaign." msgstr "O exército será transportado na campanha." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "O reino terá +%{count} de %{resource} por dia." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "O feitiço \"%{spell}\" será transportado na campanha." msgid "%{hero} can be hired during scenarios." msgstr "%{hero} pode ser recrutado durante os cenários." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "%{hero} foi derrotado e não aparecerá nos cenários seguintes." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "Os anões reconhecem seus aliados e juntam-se com prazer a suas forças." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "Os ogros o reconhecem como o Flagelo Anão e se juntam a você." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Os dragões, grunhindo e rosnando, concordam em unir forças com você, seus " "'Aliados'." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Ao se aproximar do grupo de elfos, seu líder chama a atenção de todos eles. " "Ele grita para eles: \"Quem de vocês tem coragem de se juntar a este nosso " "destemido aliado?\" O grupo irrompe com aplausos enquanto eles correm para " "se juntar a suas fileiras." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Os anões o saúdam: \"Qualquer amigo de Roland é um amigo nosso. Você pode " "passar.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Os ogros lhe dão um grunhido de reconhecimento: \"Os aliados de Archibald " "podem passar.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Os dragões o veem e chamam. \"Nossa aliança com Archibald nos obriga a nos " "unirmos a você. Infelizmente, você não tem espaço. É uma pena!\" Eles se " "dispersam rapidamente." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Os elfos ficam em sentido ao se aproximarem. O líder deles chama você e diz: " "\"Não vamos impedir seu progresso, aliado! Avance, e que a vitória seja sua." "\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"O Flagelo Anão!!!!, corram por suas vidas.\"" msgid "campaignBonus|Animate Dead" msgstr "Despertar Mortos" msgid "campaignBonus|Chain Lightning" msgstr "Relâmpagos" msgid "campaignBonus|Fireblast" msgstr "Rajada de Fogo" msgid "campaignBonus|Mass Curse" msgstr "Maldição Coletiva" msgid "campaignBonus|Mass Haste" msgstr "Azáfama Coletiva" msgid "campaignBonus|Mirror Image" msgstr "Imagem de Espelho" msgid "campaignBonus|Resurrect" msgstr "Ressuscitar" msgid "campaignBonus|Steelskin" msgstr "Couraça de Aço" msgid "campaignBonus|Summon Earth" msgstr "Invocar Terra" msgid "campaignBonus|View Heroes" msgstr "Ver Heróis" msgid "campaignBonus|Ballista" msgstr "Balista" msgid "campaignBonus|Black Pearl" msgstr "Pérola Negra" msgid "campaignBonus|Caster's Bracelet" msgstr "Bracelete do Conjurador" msgid "campaignBonus|Defender Helm" msgstr "Elmo do Defensor" msgid "campaignBonus|Breastplate" msgstr "Peitoral" msgid "campaignBonus|Dragon Sword" msgstr "Espada do Dragão" msgid "campaignBonus|Fizbin Medal" msgstr "Medalha Fizbin " msgid "campaignBonus|Foremost Scroll" msgstr "Pergaminho Definitivo" msgid "campaignBonus|Gauntlets" msgstr "Luvas" msgid "campaignBonus|Hideous Mask" msgstr "Máscara Hedionda" msgid "campaignBonus|Mage's Ring" msgstr "Anel do Mago" msgid "campaignBonus|Major Scroll" msgstr "Pergaminho Maior" msgid "campaignBonus|Medal of Honor" msgstr "Medalha de Honra" msgid "campaignBonus|Medal of Valor" msgstr "Medalha de Bravura" msgid "campaignBonus|Minor Scroll" msgstr "Pergaminho Menor" msgid "campaignBonus|Nomad Boots" msgstr "Botas Nômade" msgid "campaignBonus|Power Axe" msgstr "Machado de Força" msgid "campaignBonus|Spiked Shield" msgstr "Escudo Cravado" msgid "campaignBonus|Stealth Shield" msgstr "Escudo Furtivo" msgid "campaignBonus|Tax Lien" msgstr "Privilégio Fiscal" msgid "campaignBonus|Thunder Mace" msgstr "Maça do Trovão" msgid "campaignBonus|Traveler's Boots" msgstr "Botas do Viajante" msgid "campaignBonus|White Pearl" msgstr "Pérola Branca" msgid "campaignBonus|Basic Archery" msgstr "Arqueria Nv. Básico" msgid "campaignBonus|Advanced Archery" msgstr "Arqueria Nv. Avançado" msgid "campaignBonus|Expert Archery" msgstr "Arqueria Nv. Experiente" msgid "campaignBonus|Basic Ballistics" msgstr "Balística Nv. Básico" msgid "campaignBonus|Advanced Ballistics" msgstr "Balística Nv. Avançado" msgid "campaignBonus|Expert Ballistics" msgstr "Balística Nv. Experiente" msgid "campaignBonus|Basic Diplomacy" msgstr "Diplomacia Nv. Básico" msgid "campaignBonus|Advanced Diplomacy" msgstr "Diplomacia Nv. Avançado" msgid "campaignBonus|Expert Diplomacy" msgstr "Diplomacia Nv. Experiente" msgid "campaignBonus|Basic Eagle Eye" msgstr "Olho de Ãguia Nv. Básico" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Olho de Ãguia Nv. Avançado" msgid "campaignBonus|Expert Eagle Eye" msgstr "Olho de Ãguia Nv. Experiente" msgid "campaignBonus|Basic Estates" msgstr "Riqueza Nv. Básica" msgid "campaignBonus|Advanced Estates" msgstr "Riqueza Nv. Avançado" msgid "campaignBonus|Expert Estates" msgstr "Riqueza Nv. Experiente" msgid "campaignBonus|Basic Leadership" msgstr "Liderança Nv. Básico" msgid "campaignBonus|Advanced Leadership" msgstr "Liderança Nv. Avançado" msgid "campaignBonus|Expert Leadership" msgstr "Liderança Nv. Experiente" msgid "campaignBonus|Basic Logistics" msgstr "Logística Nv. Básico" msgid "campaignBonus|Advanced Logistics" msgstr "Logística Nv. Avançado" msgid "campaignBonus|Expert Logistics" msgstr "Logística Nv. Experiente" msgid "campaignBonus|Basic Luck" msgstr "Sorte Nv. Básico" msgid "campaignBonus|Advanced Luck" msgstr "Sorte Nv. Avançado" msgid "campaignBonus|Expert Luck" msgstr "Sorte Nv. Experiente" msgid "campaignBonus|Basic Mysticism" msgstr "Misticismo Nv. Básico" msgid "campaignBonus|Advanced Mysticism" msgstr "Misticismo Nv. Avançado" msgid "campaignBonus|Expert Mysticism" msgstr "Misticismo Nv. Experiente" msgid "campaignBonus|Basic Navigation" msgstr "Navegação Nv. Básico" msgid "campaignBonus|Advanced Navigation" msgstr "Navegação Nv. Avançado" msgid "campaignBonus|Expert Navigation" msgstr "Navegação Nv. Experiente" msgid "campaignBonus|Basic Necromancy" msgstr "Necromancia Nv. Básico" msgid "campaignBonus|Advanced Necromancy" msgstr "Necromancia Nv. Avançado" msgid "campaignBonus|Expert Necromancy" msgstr "Necromancia Nv. Experiente" msgid "campaignBonus|Basic Pathfinding" msgstr "Reconhecimento Nv. Básico" msgid "campaignBonus|Advanced Pathfinding" msgstr "Reconhecimento Nv. Avançado" msgid "campaignBonus|Expert Pathfinding" msgstr "Reconhecimento Nv. Experiente" msgid "campaignBonus|Basic Scouting" msgstr "Desbravamento Nv. Básico" msgid "campaignBonus|Advanced Scouting" msgstr "Desbravamento Nv. Avançado" msgid "campaignBonus|Expert Scouting" msgstr "Desbravamento Nv. Experiente" msgid "campaignBonus|Basic Wisdom" msgstr "Sabedoria Nv. Básico" msgid "campaignBonus|Advanced Wisdom" msgstr "Sabedoria Nv. Avançado" msgid "campaignBonus|Expert Wisdom" msgstr "Sabedoria Nv. Experiente" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" "O herói principal terá o artefato \"%{artifact}\" no início do cenário." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "O reino receberá um adicional de %{amount} de %{resource} no início do " "cenário." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "O reino terá %{amount} %{resource} a menos no início do cenário." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "O herói principal terá %{count} %{monster} no início do cenário." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "O herói principal terá o feitiço \"%{spell}\" no início do cenário." msgid "The starting alignment of the scenario will be %{race}." msgstr "O alinhamento inicial do cenário será %{race}." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "O herói principal receberá +%{count} em %{skill} no início do cenário." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "O principal herói terá %{skill} no início do cenário." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" msgid "Price of Loyalty" msgstr "Preço da Lealdade" msgid "Voyage Home" msgstr "Viagem para Casa" msgid "Wizard's Isle" msgstr "Ilha do Mago" msgid "Descendants" msgstr "Descendentes" msgid "Cannot build. You have already built here today." msgstr "Não é possível construir. Você já construiu aqui hoje." msgid "For this action it is necessary to build a castle first." msgstr "Para essa ação, é necessário construir primeiro um castelo." msgid "The %{building} produces %{monster}." msgstr "%{building} produz %{monster}." msgid "Requires:" msgstr "Requer:" msgid "Exit this menu without doing anything." msgstr "Sair do menu sem fazer nada." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Não é possível construir %{name}. O castelo está longe do oceano." msgid "This building has been disabled." msgstr "Esta edificação foi desativada." msgid "Cannot afford the %{name}." msgstr "Não é possível pagar por %{name}." msgid "The %{name} is already built." msgstr "%{name} já está construído." msgid "Cannot build the %{name}." msgstr "Não é possível construir %{name}." msgid "Build %{name}." msgstr "Construir %{name}." msgid "Blackridge" msgstr "Cume Negro" msgid "Hillstone" msgstr "Pedra da Colina" msgid "Pinehurst" msgstr "Hillstone" msgid "Whiteshield" msgstr "Escudo Branco" msgid "Woodhaven" msgstr "Paraíso Florestal" msgid "Blackwind" msgstr "Vento Negro" msgid "Bloodreign" msgstr "Reino de Sangue" msgid "Dragontooth" msgstr "Dente de Dragão" msgid "Greywind" msgstr "Vento Cinzento" msgid "Portsmith" msgstr "Ferraria do Porto" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Portão do Meio" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcânia" msgid "Baywatch" msgstr "Baía Vigia" msgid "Fountainhead" msgstr "Fonte Primordial" msgid "Vertigo" msgstr "Vertigem" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Morte de Inverno" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Beira do Lago" msgid "Nightshadow" msgstr "Sombra Noturna" msgid "Olympus" msgstr "Olimpo" msgid "Sandcaster" msgstr "Conjurador de Areia" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragoduna" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Presa Negra" msgid "New Dawn" msgstr "Novo Amanhecer" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Grande Carvalho" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antioquia" msgid "Avalon" msgstr "Ãvalon" msgid "Roc Haven" msgstr "Paraíso Roca" msgid "South Mill" msgstr "Moinho Sul" msgid "Weed Patch" msgstr "Campo de Ervas" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Topo da Colina" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Forquilha do Oeste" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "Cabeça de Alce" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Incêndio Negro" msgid "Blacksford" msgstr "Vau Negro" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Olho de Porco" msgid "Viper's Nest" msgstr "Ninho de Víbora" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Colina da Madeira" msgid "Troy" msgstr "Troia" msgid "Forder Oaks" msgstr "Carvalhos Forder" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Mercúrio" msgid "Westmoor" msgstr "Pântano Oeste" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburgo" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Impossível recrutar. Você já possui um herói na cidade." msgid "Cannot recruit - you have too many Heroes." msgstr "Impossível recrutar. Você tem muitos heróis." msgid "Cannot afford a Hero." msgstr "Não é possível pagar por um Herói." msgid "There is no room in the garrison for this army." msgstr "Não há espaço na guarnição para este exército." msgid "Fortifications" msgstr "Fortificações" msgid "Farm" msgstr "Fazenda" msgid "Thatched Hut" msgstr "Cabana de Palha" msgid "Archery Range" msgstr "Campo de Arqueiros" msgid "Upg. Archery Range" msgstr "Campo de Arqueiros Nv.2" msgid "Blacksmith" msgstr "Ferraria" msgid "Upg. Blacksmith" msgstr "Ferraria Nv.2" msgid "Armory" msgstr "Arsenal" msgid "Upg. Armory" msgstr "Arsenal Nv.2" msgid "Jousting Arena" msgstr "Arena de Justa" msgid "Upg. Jousting Arena" msgstr "Arena de Justa Nv.2" msgid "Cathedral" msgstr "Catedral" msgid "Upg. Cathedral" msgstr "Catedral Nv.2" msgid "Coliseum" msgstr "Coliseu" msgid "Garbage Heap" msgstr "Lixão" msgid "Hut" msgstr "Cabana" msgid "Stick Hut" msgstr "Cabana de Pau" msgid "Upg. Stick Hut" msgstr "Cabana de Pau Nv.2" msgid "Den" msgstr "Toca" msgid "Adobe" msgstr "Adobe" msgid "Upg. Adobe" msgstr "Adobe Nv.2" msgid "Bridge" msgstr "Ponte" msgid "Upg. Bridge" msgstr "Ponte Nv.2" msgid "Pyramid" msgstr "Pirâmide" msgid "Rainbow" msgstr "Arco-Ãris" msgid "Crystal Garden" msgstr "Jardim de Cristal" msgid "Treehouse" msgstr "Casa na Ãrvore" msgid "Cottage" msgstr "Chalé" msgid "Upg. Cottage" msgstr "Chalé Nv.2" msgid "Stonehenge" msgstr "Stonehenge" msgid "Upg. Stonehenge" msgstr "Stonehenge Nv.2" msgid "Fenced Meadow" msgstr "Campo Cercado" msgid "sorceress|Red Tower" msgstr "Torre Vermelha" msgid "Dungeon" msgstr "Masmorra" msgid "Waterfall" msgstr "Cachoeira" msgid "Cave" msgstr "Caverna" msgid "Crypt" msgstr "Cripta" msgid "Nest" msgstr "Ninho" msgid "Maze" msgstr "Labirinto" msgid "Upg. Maze" msgstr "Labirinto Nv.2" msgid "Swamp" msgstr "Pântano" msgid "Green Tower" msgstr "Torre Verde" msgid "warlock|Red Tower" msgstr "Torre Vermelha" msgid "Black Tower" msgstr "Torre Negra" msgid "Library" msgstr "Biblioteca" msgid "Orchard" msgstr "Pomar" msgid "Habitat" msgstr "Hábitat" msgid "Pen" msgstr "Curral" msgid "Foundry" msgstr "Fundição" msgid "Upg. Foundry" msgstr "Fundição Nv.2" msgid "Cliff Nest" msgstr "Ninho do Penhasco" msgid "Ivory Tower" msgstr "Torre de Marfim" msgid "Upg. Ivory Tower" msgstr "Torre de Marfim Nv.2" msgid "Cloud Castle" msgstr "Castelo Nebuloso" msgid "Upg. Cloud Castle" msgstr "Castelo Nebuloso Nv.2" msgid "Storm" msgstr "Tempestade" msgid "Skull Pile" msgstr "Pilha de Caveiras" msgid "Excavation" msgstr "Escavação" msgid "Graveyard" msgstr "Cemitério" msgid "Upg. Graveyard" msgstr "Cemitério Nv.2" msgid "Upg. Pyramid" msgstr "Pirâmide Nv.2" msgid "Mansion" msgstr "Mansão" msgid "Upg. Mansion" msgstr "Mansão Nv.2" msgid "Mausoleum" msgstr "Mausoléu" msgid "Upg. Mausoleum" msgstr "Mausoléu Nv.2" msgid "Laboratory" msgstr "Laboratório" msgid "Shrine" msgstr "Santuário" msgid "Special" msgstr "Especial" msgid "Horde Building" msgstr "Estrutura da Horda" msgid "Dwelling 1" msgstr "Moradia 1" msgid "Dwelling 2" msgstr "Moradia 2" msgid "Upg. Dwelling 2" msgstr "Moradia 2 Nv.2" msgid "Dwelling 3" msgstr "Moradia 3" msgid "Upg. Dwelling 3" msgstr "Moradia 3 Nv.2" msgid "Dwelling 4" msgstr "Moradia 4" msgid "Upg. Dwelling 4" msgstr "Moradia 4 Nv.2" msgid "Dwelling 5" msgstr "Moradia 5" msgid "Upg. Dwelling 5" msgstr "Moradia 5 Nv.2" msgid "Dwelling 6" msgstr "Moradia 6" msgid "Upg. Dwelling 6" msgstr "Moradia 6 Nv.2" msgid "2x Upg. Dwelling 6" msgstr "Moradia 6 Nv.3" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "As Fortificações aumentam a resistência das muralhas do castelo, aumentando " "o número de turnos necessários para derrubá-las." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "A Fazenda aumenta a produção de Camponeses em %{count} por semana." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "O Coliseu proporciona espetáculos inspiradores para as tropas defensoras, " "elevando a sua moral em dois durante o combate." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "O Lixão aumenta a produção de Goblins em %{count} por semana." msgid "The Rainbow increases the luck of the defending units by two." msgstr "O Arco-Ãris aumenta a sorte das tropas de defesa do castelo em 2." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" "O Jardim de Cristal aumenta a produção de Fadas em %{count} por semana." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "A Masmorra aumenta a renda da cidade em %{count} de ouro por dia." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "A Cachoeira aumenta a produção de Centauros em %{count} por semana." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "A Biblioteca aumenta o número de feitiços na Guilda dos Magos em um para " "cada nível." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "O Pomar aumenta a produção de Pequeninos em %{count} por semana." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" "A Tempestade adiciona +2 ao poder dos feitiços de um conjurador em defesa." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" "A Pilha de Caveiras aumenta a produção de esqueletos em %{count} por semana." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" "A estrutura Especial concede um bônus específico ao tipo de castelo " "escolhido." msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "A Estrutura da Horda aumenta a taxa de produção das criaturas de nível 1 em " "8 por semana." msgid "Thieves' Guild" msgstr "Guilda dos Ladrões" msgid "Tavern" msgstr "Taverna" msgid "Shipyard" msgstr "Estaleiro" msgid "Well" msgstr "Poço" msgid "Statue" msgstr "Estátua" msgid "Marketplace" msgstr "Mercado" msgid "Moat" msgstr "Fosso" msgid "Castle" msgstr "Castelo" msgid "Tent" msgstr "Tenda" msgid "Captain's Quarters" msgstr "Alojamento do Capitão" msgid "Mage Guild, Level 1" msgstr "Guilda dos Magos Nv.1" msgid "Mage Guild, Level 2" msgstr "Guilda dos Magos Nv.2" msgid "Mage Guild, Level 3" msgstr "Guilda dos Magos Nv.3" msgid "Mage Guild, Level 4" msgstr "Guilda dos Magos Nv.4" msgid "Mage Guild, Level 5" msgstr "Guilda dos Magos Nv.5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "O Santuário aumenta a habilidade de Necromancia para todos os necromantes em " "10%." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "A Guilda dos Ladrões fornece informações sobre os jogadores inimigos. A " "Guilda dos Ladrões também pode fornecer informações sobre as cidades " "inimigas. Guildas adicionais fornecem mais informações." msgid "The Tavern increases morale for troops defending the castle." msgstr "A Taverna aumenta a moral das tropas que estão defendendo o castelo." msgid "The Shipyard allows ships to be built." msgstr "O Estaleiro permite construir barcos." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "O Poço aumenta a taxa de produção de todas as moradias em %{count} criaturas " "por semana." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "A Estátua aumenta a renda da cidade em %{count} de ouro por dia." msgid "The Left Turret provides extra firepower during castle combat." msgstr "" "A Torre Esquerda prevê o poder de fogo extra durante o combate no castelo." msgid "The Right Turret provides extra firepower during castle combat." msgstr "" "A Torre Direita prevê o poder de fogo extra durante o combate no castelo." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "O Mercado pode ser usado para converter um tipo de recurso em outro. Quanto " "mais mercados você controla, melhor será a taxa de câmbio." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "O Fosso retarda unidades de ataque. Qualquer unidade que entrar no fosso " "deve terminar seu turno lá e se torna mais vulnerável a ataques." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "O Castelo melhora a defesa da cidade e aumenta sua renda para %{count} de " "ouro por dia." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "A Tenda fornece trabalhadores para construir um castelo, desde que os " "materiais e o ouro estejam disponíveis." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "O Alojamento do Capitão fornece um capitão para ajudar na defesa do castelo, " "quando o herói não está presente." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "A Guilda dos Magos permite que os heróis aprendam feitiços e reabasteçam sua " "mana." msgid "Recruit %{name}" msgstr "Recruta %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Mês: %{month}, Semana: %{week}, Dia: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Você deve comprar um grimório para usar a guilda dos magos, mas atualmente " "você não tem espaço para ele. Tente dar um de seus artefatos a outro herói." msgid "Click to show next town." msgstr "Clique para mostrar a próxima cidade." msgid "Show next town" msgstr "Mostrar a cidade seguinte" msgid "Click to show previous town." msgstr "Clique para mostrar a cidade anterior." msgid "Show previous town" msgstr "Mostrar cidade anterior" msgid "This town may not be upgraded to a castle." msgstr "Esta cidade não pode ser transformada em castelo." msgid "Town" msgstr "Cidade" msgid "Exit Castle" msgstr "Sair do Castelo" msgid "Exit Town" msgstr "Sair da Cidade" msgid "Show Income" msgstr "Mostrar Renda" msgid "View Hero" msgstr "Ver Herói" msgid "The above spells are available here." msgstr "Os feitiços acima estão disponíveis aqui." msgid "The spells the hero can learn have been added to their book." msgstr "Os feitiços que o herói pode aprender foram colocados no grimório." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "A gorjeta generosa para o barman rende o boato que se segue:" msgid "Recruit Hero" msgstr "Recrutar Herói" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} Nível: %{value} Classe: %{race} " msgid "with %{count} artifacts." msgstr "com %{count} artefatos." msgid "with 1 artifact." msgstr "com 1 artefato." msgid "without artifacts." msgstr "sem artefatos." msgid "Recruit %{name} the %{race}" msgstr "Recrutar %{name} da classe %{race}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "A formação de combate 'Aberta' espalha as unidades do castelo de cima para " "baixo do campo de batalha, com pelo menos um espaço vazio entre cada unidade." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "A formação de combate 'Fechada' agrupa as unidades do castelo no centro do " "lado do castelo no campo de batalha." msgid "Spread Formation" msgstr "Formação Aberta" msgid "Grouped Formation" msgstr "Formação Fechada" msgid "Click to show the next town." msgstr "Clique para mostrar a próxima cidade." msgid "Click to show the previous town." msgstr "Clique para mostrar a cidade anterior." msgid "Set garrison combat formation to 'Spread'" msgstr "Definir formação de combate da guarnição para 'Aberta'" msgid "Set garrison combat formation to 'Grouped'" msgstr "Definir formação de combate da guarnição para 'Fechada'" msgid "Exit Castle Options" msgstr "Sair das Opções do Castelo" msgid "Castle Options" msgstr "Opções do Castelo" msgid "Not enough resources to recruit creatures." msgstr "Não há recursos suficientes para recrutar criaturas." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Você não pode recrutar neste momento, suas fileiras estão cheias." msgid "No creatures available for purchase." msgstr "Nenhuma criatura disponível para comprar." msgid "Recruit Creatures" msgstr "Recrutar Criaturas" msgid "Hire all creatures in the town." msgstr "Recrutar todas as criaturas da cidade." msgid "Max" msgstr "Máx." msgid "Available" msgstr "Disponível" msgid "Town Population Information and Statistics" msgstr "Informações da População da Cidade e Estatísticas" msgid "Damage" msgstr "Dano" msgid "HP" msgstr "PV" msgid "Growth" msgstr "Produção" msgid "week" msgstr "semana" msgid "View World" msgstr "Ver Mundo" msgid "View the entire world." msgstr "Ver o mundo inteiro." msgid "Puzzle" msgstr "Quebra-Cabeça" msgid "View the obelisk puzzle." msgstr "Ver quebra-cabeça do obelisco." msgid "Scenario Information" msgstr "Informações do Cenário" msgid "View information on the scenario you are currently playing." msgstr "Ver informações sobre o cenário que você está jogando atualmente." msgid "Dig for the Ultimate Artifact." msgstr "Escavar em busca do Artefato Definitivo enterrado." msgid "Digging" msgstr "Cavar Tesouro" msgid "Arena" msgstr "Arena" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Você entra na arena e enfrenta um bando de leões ferozes. Você com agilidade " "derrotá-los, para os aplausos da multidão selvagem. Impressionado com sua " "habilidade, o velho treinador de gladiadores concorda em treiná-lo em uma " "habilidade de sua escolha." msgid "Attack Skill" msgstr "Ataque" msgid "Defense Skill" msgstr "Defesa" msgid "Shots" msgstr "Tiros" msgid "Shots Left" msgstr "Tiros Restantes" msgid "Hit Points" msgstr "Pts. de Vida" msgid "Hit Points Left" msgstr "Vida Restante" msgid "You can't afford to upgrade your troops!" msgstr "Você não pode melhorar suas tropas!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Suas tropas podem ser melhoradas, mas isso lhe custará muito caro. Você " "deseja melhorá-las?" msgid "Are you sure you want to dismiss this army?" msgstr "Você tem certeza de que deseja dispensar este exército?" msgid "Upgrade" msgstr "Melhorar" msgid "Upgrade your troops." msgstr "Melhorar suas tropas." msgid "Dismiss" msgstr "Dispensar" msgid "Dismiss this army." msgstr "Dispensar esse exército." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Um grupo de %{monster} com um desejo de grande glória deseja juntar-se a " "você.\n" "Você aceita?" msgid "Followers" msgstr "Seguidores" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} é influenciado por sua língua diplomática, e se oferece para se " "alistar ao seu exército pela soma de %{gold} peças de ouro.\n" "Você aceita?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "As criaturas são persuadidas por sua língua\n" "diplomática, e fazem uma oferta:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} de um total de %{total} %{monster} se juntarão ao seu exército, e o " "resto o deixará em paz, pela soma de %{gold} de ouro.\n" "Você aceita?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Todos %{offer} dos %{monster} vão se juntar ao seu exército pela soma de " "%{gold} de ouro.\n" "Você aceita?" msgid "(Rate: %{percent})" msgstr "(Nível: %{percent})" msgid "off" msgstr "desl." msgid "Music" msgstr "Música" msgid "Effects" msgstr "Efeitos" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "Expansão MIDI" msgid "External" msgstr "Externa" msgid "Music Type" msgstr "Tipo de Música" msgid "3D Audio" msgstr "Ãudio 3D" msgid "Toggle ambient music level." msgstr "Alternar o nível de música ambiente." msgid "Toggle foreground sounds level." msgstr "Alternar o nível de som em primeiro plano." msgid "Change the type of music." msgstr "Altera o tipo de música." msgid "Toggle the 3D effect of foreground sounds." msgstr "Alterne o efeito 3D dos sons de primeiro plano." msgid "Build a new ship:" msgstr "Construir um novo navio:" msgid "Resource cost:" msgstr "Custo de recursos:" msgid "Total: " msgstr "Total: " msgid "Need: " msgstr "Necessário: " msgid "New Game" msgstr "Novo Jogo" msgid "Start a single or multi-player game." msgstr "Iniciar um jogo em modo solo ou multijogador." msgid "Load Game" msgstr "Carregar Jogo" msgid "Load a previously saved game." msgstr "Carregar um jogo salvo anteriormente." msgid "Save Game" msgstr "Salvar Jogo" msgid "Save the current game." msgstr "Salvar o jogo atual." msgid "Quit" msgstr "Sair" msgid "Quit out of Heroes of Might and Magic II." msgstr "Sair do Heroes of Might and Magic II." msgid "Language" msgstr "Idioma" msgid "Graphics" msgstr "Gráficos" msgid "Black & White" msgstr "Preto e Branco" msgid "Mouse Cursor" msgstr "Cursor" msgid "Color" msgstr "Colorido" msgid "Text Support" msgstr "Suporte a Texto" msgid "Change the language of the game." msgstr "Altera o idioma do jogo." msgid "Select Game Language" msgstr "Selecionar Idioma do Jogo" msgid "Change the graphics settings of the game." msgstr "Altera as configurações gráficas do jogo." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" "Ativar ou desativar o cursor colorido. Essa é apenas uma opção estética." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Ativa ou desativa o modo de suporte de texto para emitir informações extras " "sobre janelas e eventos no jogo." msgid "" "Map\n" "Difficulty" msgstr "" "Dificuldade\n" "do Mapa" msgid "" "Game\n" "Difficulty" msgstr "" "Dificuldade\n" "do Jogo" msgid "Rating" msgstr "Nível" msgid "Map Size" msgstr "" "Tamanho\n" "do Mapa" msgid "Opponents" msgstr "Oponentes" msgid "Class" msgstr "Classes" msgid "" "Victory\n" "Conditions" msgstr "" "Condições\n" "de\n" "Vitória" msgid "" "Loss\n" "Conditions" msgstr "" "Condições\n" "de\n" "Derrota" msgid "First select recipients!" msgstr "Primeiro selecione o recipiente!" msgid "You cannot select %{resource}!" msgstr "Você não pode selecionar %{resource}!" msgid "Set %{resource-type} Count" msgstr "Definir Quantidade de %{resource-type}." msgid "Select Recipients" msgstr "Selecione os Recipientes" msgid "Your Funds" msgstr "Seu Dinheiro" msgid "Planned Gift" msgstr "Presente Planejado" msgid "Gift from %{name}" msgstr "Presente de %{name}" msgid "Resolution" msgstr "Resolução" msgid "Fullscreen" msgstr "Tela cheia" msgid "window|Mode" msgstr "Modo" msgid "Windowed" msgstr "Janela" msgid "V-Sync" msgstr "Sincronização vertical" msgid "FPS" msgstr "QPS" msgid "System Info" msgstr "Informações do Sistema" msgid "Change the resolution of the game." msgstr "Altera a resolução do jogo." msgid "Select Game Resolution" msgstr "Selecionar Resolução do Jogo" msgid "Toggle between fullscreen and windowed modes." msgstr "Alternar entre os modos de tela cheia e janela." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "A opção Sincronização Vertical pode ser ativada para resolver problemas de " "tremulação em alguns monitores." msgid "Show extra information such as FPS and current time." msgstr "Mostrar informações adicionais, como FPS e hora atual." msgid "Hotkey: " msgstr "Tecla de atalho: " msgid "Category: " msgstr "Categoria: " msgid "Event: " msgstr "Evento: " msgid "Hot Keys:" msgstr "Atalhos:" msgid "Hide" msgstr "Ocultar" msgid "Show" msgstr "Mostrar" msgid "Interface" msgstr "Aparência" msgid "Interface Type" msgstr "Tipo de Interface" msgid "Toggle the type of interface you want to use." msgstr "Alterne o tipo de interface que você deseja usar." msgid "Toggle interface visibility." msgstr "Alternar a visibilidade da interface." msgid "Scroll Speed" msgstr "" "Velocidade\n" "de Deslocamento" msgid "Sets the speed at which you scroll the window." msgstr "Defina a velocidade com a qual você rola a janela." msgid "Select Game Language:" msgstr "Selecionar Idioma do Jogo:" msgid "Select Language:" msgstr "Selecionar Idioma:" msgid "Click to choose the selected language." msgstr "Clique para escolher o idioma selecionado." msgid "%{name} has gained a level." msgstr "%{name} ganhou um nível." msgid "%{skill} +1" msgstr "+1 de %{skill}" msgid "You have learned %{skill}." msgstr "Você aprendeu %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} ganhou um nível.\n" "\n" "+1 de %{skill}" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Você pode aprender:\n" "%{skill1}\n" "ou\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/d" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Por favor, examine nossos excelentes produtos. Se quiser fazer uma troca, " "clique nos itens que deseja trocar e nos que deseja obter." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Você está conseguindo uma verdadeira pechincha, acho que não vou ganhar nada " "com esse negócio, há algo que eu possa lhe oferecer de qualquer um dos meus " "outros produtos?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Eu posso oferecer para você %{count} por 1 unidade de %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" "Eu posso oferecer para você 1 unidade de %{resto} por %{count} unidades de " "%{resfrom}." msgid "Min" msgstr "Mín." msgid "Qty to trade" msgstr "Qtd. a trocar" msgid "Trading Post" msgstr "Posto de Comércio" msgid "Your Resources" msgstr "Seus Recursos" msgid "Available Trades" msgstr "Trocas Disponíveis" msgid "guarded by %{count} %{monster}" msgstr "Guardado por %{count} %{monster}" msgid "guarded by " msgstr "Guardado por " msgid "(available: %{count})" msgstr "(Disponível: %{count})" msgid "(empty)" msgstr "(Vazio)" msgid "already learned" msgstr "Já aprendeu" msgid "treeOfKnowledge|free" msgstr "grátis" msgid "already claimed" msgstr "já reivindicado" msgid "not claimed" msgstr "não reivindicado" msgid "already knows this skill" msgstr "Já sabe essa habilidade" msgid "already has max skills" msgstr "Já tem o máximo de habilidades" msgid "(already visited)" msgstr "(Já visitado)" msgid "(not visited)" msgstr "(Não visitado)" msgid "%{color} Barrier" msgstr "Barreira Mágica %{color}" msgid "(tent visited)" msgstr "(tenda visitada)" msgid "%{color} Tent" msgstr "Tenda %{color}" msgid "Road" msgstr "Estrada" msgid "(digging ok)" msgstr "(Possível escavar)" msgid "(no digging)" msgstr "(Impossível escavar)" msgid "penalty: %{cost}" msgstr "Penalização: %{cost}" msgid "Defenders:" msgstr "Defensores:" msgid "Unknown" msgstr "Desconhecido" msgid "heroQuickInfo|(Level %{level})" msgstr "(Nível %{level})" msgid "Attack:" msgstr "Ataque:" msgid "Defense:" msgstr "Defesa:" msgid "Spell Power:" msgstr "Pod. Mágico:" msgid "Knowledge:" msgstr "Conhecimento:" msgid "Spell Points:" msgstr "Mana:" msgid "Move Points:" msgstr "Movimento:" msgid "Uncharted Territory" msgstr "Território Desconhecido" msgid "Cost per troop:" msgstr "Custo por tropa:" msgid "Available: %{count}" msgstr "Disponível: %{count}" msgid "Number to buy:" msgstr "Qtd. à comprar:" msgid "Recruit selected monsters." msgstr "Recrutar monstros selecionados." msgid "Select maximum monsters to be recruited." msgstr "Selecionar o máximo de monstros para serem recrutados." msgid "Select only 1 monster to be recruited." msgstr "Selecionar apenas 1 monstro para ser recrutado." msgid "Select this game resolution." msgstr "Selecionar esta resolução do jogo." msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" "Selecionar esta resolução definirá uma resolução que é escalada da resolução " "original (%{resolution}) multiplicando-a pelo número entre parênteses " "(%{scale}).\n" "\n" "Uma resolução com um número inteiro exato (2.0x, 3.0x etc.) geralmente terá " "uma aparência melhor, pois os pixels são ampliados de forma uniforme tanto " "na direção horizontal quanto na vertical." msgid "Select Game Resolution:" msgstr "Selecione a resolução do jogo:" msgid "Click to apply the selected resolution." msgstr "Clique para aplicar a resolução selecionada." msgid "Click to apply the entered text." msgstr "Clique para aplicar o texto inserido." msgid "Click to open the Virtual Keyboard dialog." msgstr "Clique para abrir o diálogo do Teclado Virtual" msgid "Open Virtual Keyboard" msgstr "Abrir o teclado virtual" msgid "How many creatures do you wish to move?" msgstr "Quantas criaturas você deseja mover?" msgid "Select how many units to separate into:" msgstr "Selecione quantas unidades serão separadas:" msgid "Map: " msgstr "Mapa: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "Mês: " msgid ", Week: " msgstr ", Semana: " msgid ", Day: " msgstr ", Dia: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Local: " msgid "Are you sure you want to delete file:" msgstr "Você tem certeza de que deseja apagar este arquivo:" msgid "Warning" msgstr "Aviso" msgid "Click to save the current game." msgstr "Clique para salvar o jogo atual." msgid "Click to load a previously saved game." msgstr "Clique para carregar o jogo salvo anteriormente." msgid "File to Save:" msgstr "Arquivo à ser salvo:" msgid "File to Load:" msgstr "Arquivo à ser carregado:" msgid "Terrain object" msgstr "Objeto do terreno" msgid "Accept the choice made." msgstr "Aceitar a escolha feita." msgid "Select Skill:" msgstr "Selecionar Habilidade:" msgid "Select Spell:" msgstr "Selecionar Feitiço:" msgid "Select Artifact:" msgstr "Selecionar Artefato:" msgid "Select Monster:" msgstr "Selecionar Monstro:" msgid "Select Hero:" msgstr "Selecionar Herói:" msgid "race|Random" msgstr "Aleatória" msgid "Click to start placing the selected hero." msgstr "Clique para começar a posicionar o herói selecionado." msgid "%{color} %{race}" msgstr "%{race} %{color}" msgid "You will place" msgstr "Você irá colocar" msgid "Click to select this class." msgstr "Clique para selecionar esta classe." msgid "Click to select this color." msgstr "Clique para selecionar esta cor." msgid "Select Treasure:" msgstr "Selecionar Tesouro:" msgid "Select Ocean Object:" msgstr "Selecionar Objeto Oceânico:" msgid "Castle/town placing" msgstr "Colocação de Castelo/Cidade" msgid "doubleLinedRace|Neutral" msgstr "Neutra" msgid "Click to start placing the selected castle/town." msgstr "Clique para começar a colocar o castelo/cidade selecionado." msgid "Click to select town placing." msgstr "Clique para selecionar a colocação da cidade." msgid "Click to select castle placing." msgstr "Clique para selecionar a colocação do castelo." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{townOrCastle} %{race} %{color}" msgid "race|Neutral" msgstr "Neutra" msgid "Select Dwelling:" msgstr "Selecionar Moradia:" msgid "Select Landscape Object:" msgstr "Selecionar Objeto de Paisagem:" msgid "Mine placing" msgstr "Colocação de Mina" msgid "" "Resource\n" "type:" msgstr "" "Tipo de\n" "recurso:" msgid "%{mineName} appearance:" msgstr "Aparência de %{mineName}:" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" "Clique para selecionar %{object} como o gerador de recurso a ser colocado." msgid "Select Mountain Object:" msgstr "Selecionar Objeto de Montanha:" msgid "Select Rock Object:" msgstr "Selecionar Objeto de Rocha:" msgid "Select Tree Object:" msgstr "Selecionar Objeto de Ãrvore:" msgid "Select Power Up Object:" msgstr "Selecionar Objeto de Aprimoramento:" msgid "Select Adventure Object:" msgstr "Selecionar Objeto de Aventura:" msgid "Players Icon" msgstr "Ãcone dos Jogadores" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Indica quantos jogadores ao todo estão no cenário. Quaisquer posições não " "ocupadas por jogadores humanos serão ocupadas por jogadores controlados pelo " "computador." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Indica se o mapa\n" "é pequeno (36 x 36), médio\n" "(72 x 72), grande (108 x 108),\n" "ou muito grande (144 x 144)." msgid "Size Icon" msgstr "Tamanho do Ãcone" msgid "Map Type" msgstr "Tipo de Mapa" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Indica se o mapa é feito para a versão \"As Guerras de Sucessão\", \"O Preço " "da Lealdade\" ou \"Ressurreição\" do jogo." msgid "Map Type:\n" msgstr "Tipo de Mapa:\n" msgid "The Succession Wars" msgstr "As Guerras de Sucessão" msgid "The Price of Loyalty" msgstr "O Preço da Lealdade" msgid "Resurrection" msgstr "Ressurreição" msgid "" "\n" "\n" "Language:\n" msgstr "" "\n" "\n" "Idioma:\n" msgid "Lose all your heroes and towns." msgstr "Perder todos os seus heróis e cidades." msgid "Lose a specific town." msgstr "Perder uma cidade específica." msgid "Lose a specific hero." msgstr "Perder um herói específico." msgid "Run out of time. Fail to win by a certain point." msgstr "" "O tempo está se esgotando. Impossibilitado de vencer de um certo ponto." msgid "Loss Condition" msgstr "Condição de Derrota" msgid "Defeat all enemy heroes and towns." msgstr "Vencer todos heróis e cidades inimigas." msgid "Capture a specific town." msgstr "Capturar cidade específica." msgid "Defeat a specific hero." msgstr "Derrotar um herói específico." msgid "Find a specific artifact." msgstr "Encontrar artefato específico." msgid "Your side must defeat the opposing side." msgstr "Seu lado deve vencer o oposto." msgid "Accumulate a large amount of gold." msgstr "Acumular uma grande quantidade de ouro." msgid "Victory Condition" msgstr "Condição de Vitória" msgid "Map difficulty:" msgstr "Dificuldade do Mapa:" msgid "N" msgstr "N" msgid "No maps exist at that size." msgstr "Não existem mapas com esse tamanho." msgid "Small Maps" msgstr "Mapas Pequenos" msgid "View only maps of size small (36 x 36)." msgstr "Veja apenas mapas de tamanho pequeno (36 x 36)." msgid "Medium Maps" msgstr "Mapas Médios" msgid "View only maps of size medium (72 x 72)." msgstr "Ver apenas mapas de tamanho médio (72 x 72)." msgid "Large Maps" msgstr "Mapas Grandes" msgid "View only maps of size large (108 x 108)." msgstr "Ver apenas mapas de tamanho grande (108 x 108)." msgid "Extra Large Maps" msgstr "Mapas Muito Grades" msgid "View only maps of size extra large (144 x 144)." msgstr "Ver apenas mapas de tamanho muito grande (144 x 144)." msgid "All Maps" msgstr "Todos os Mapas" msgid "View all maps, regardless of size." msgstr "Ver todos os mapas, independente do tamanho." msgid "Selected Name" msgstr "Nome Escolhido" msgid "The name of the currently selected map." msgstr "O nome do mapa atualmente selecionado." msgid "Selected Map Difficulty" msgstr "Dificuldade do Mapa Escolhido" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "A dificuldade do mapa atualmente selecionado. A dificuldade do mapa é " "determinada pelo projetista do cenário. Os mapas mais difíceis podem incluir " "mais inimigos, menos recursos ou outras condições especiais que tornem as " "coisas mais difíceis para o jogador humano." msgid "Selected Description" msgstr "Descrição Selecionada" msgid "The description of the currently selected map." msgstr "A descrição do mapa atualmente selecionado." msgid "Jump" msgstr "Saltar" msgid "Hero Speed" msgstr "Veloc. Herói" msgid "Don't Show" msgstr "Não Mostrar" msgid "Enemy Speed" msgstr "Veloc. Inimigo" msgid "Auto Resolve" msgstr "Auto Resolver" msgid "Auto, No Spells" msgstr "Auto, Sem Feitiços" msgid "Battles" msgstr "Batalhas" #, fuzzy msgid "combatMode|Manual" msgstr "Manual" msgid "Change the speed at which your heroes move on the main screen." msgstr "Altera a velocidade com que seus heróis se movem na tela principal." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Define a velocidade que os heróis controlados pelo computador se movem. Você " "também pode optar por não visualizar o movimento do computador." msgid "Change the interface settings of the game." msgstr "Alterar as configurações de interface do jogo." msgid "Interface Settings" msgstr "Configurações de Interface" msgid "Toggle instant battle mode." msgstr "Alternar o modo de batalha instantânea." msgid "Att." msgstr "Ata." msgid "Def." msgstr "Def." msgid "Power" msgstr "Poder" msgid "Knowl" msgstr "Conhec." msgid "1st" msgstr "1." msgid "2nd" msgstr "2." msgid "3rd" msgstr "3." msgid "4th" msgstr "4." msgid "5th" msgstr "5." msgid "6th" msgstr "6." msgid "Oracle: Player Rankings" msgstr "Oráculo: Classificação de Jogadores" msgid "Thieves' Guild: Player Rankings" msgstr "Guilda dos Ladrões: Classificação de Jogadores" msgid "Number of Towns:" msgstr "Número de Cidades:" msgid "Number of Castles:" msgstr "Número de Castelos:" msgid "Number of Heroes:" msgstr "Número de Heróis:" msgid "Gold in Treasury:" msgstr "Ouro Total:" msgid "Wood & Ore:" msgstr "Madeira & Minério:" msgid "Gems, Cr, Slf & Mer:" msgstr "Gemas, Crist, Enx & Mer:" msgid "Obelisks Found:" msgstr "Obeliscos Encontrados:" msgid "Artifacts:" msgstr "Artefatos:" msgid "Total Army Strength:" msgstr "Força Total do Exército:" msgid "Income:" msgstr "Renda:" msgid "Best Hero:" msgstr "Melhor Herói:" msgid "Best Hero Stats:" msgstr "Estatíst. do Melhor Herói:" msgid "Personality:" msgstr "Personalidade:" msgid "Best Monster:" msgstr "Melhor Criatura:" msgid "Random Castle Name" msgstr "Nome Aleat. (Castelo)" msgid "Random Town Name" msgstr "Nome Aleat. (Cidade)" msgid "Allow Castle build" msgstr "Permitir construção do Castelo" msgid "Default Buildings" msgstr "Estruturas Padrão" msgid "Default Army" msgstr "Exército Padrão" msgid "Castle Army" msgstr "Exército do Castelo" msgid "Town Army" msgstr "Exército da Cidade" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" "Clique para alterar o nome do castelo. Botão direito restaura o padrão." msgid "Enter Castle name" msgstr "Insira o nome do Castelo" msgid "Allow to build a castle in this town." msgstr "Permitir a construção de um castelo nessa cidade." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" "Alternar uso de estruturas padrão. Estruturas personalizadas serão " "redefinidas" msgid "Toggle building construction restriction mode." msgstr "Alternar modo de restrição de construção de estruturas" msgid "Restrict Building Construction" msgstr "Restringir Construção de Estruturas" msgid "Use default defenders army." msgstr "Usar exército de defensores padrão." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "Definir Exército personalizado. Botão direito para redefinir." msgid "Message Text:" msgstr "Texto da Mensagem:" msgid "Reward:" msgstr "Recompensa:" msgid "Player colors allowed to get event:" msgstr "As cores dos jogadores podem receber o evento:" msgid "Computer colors allowed to get event:" msgstr "As cores do computador podem ser usadas em eventos:" msgid "First day of occurrence:" msgstr "Primeiro dia de ocorrência" msgid "Repeat period (days):" msgstr "Período de repetição (dias):" msgid "Allow %{color} human player to get event" msgstr "Permitir que jogador humano %{color} obtenha o evento" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" "Se essa caixa de seleção estiver marcada, esse evento será acionado para o " "jogador %{color} se ele for controlado por um humano." msgid "Allow %{color} computer player to get event" msgstr "Permitir que jogador %{color} do computador obtenha o evento" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" "Se essa caixa de seleção estiver marcada, esse evento será acionado para o " "jogador %{color} se ele for controlado por um computador." msgid "Message:" msgstr "Mensagem:" msgid "Click to save the Event properties." msgstr "Clique para salvar as propriedades do Evento." msgid "No resources will be given as a reward." msgstr "Nenhum recurso será dado como recompensa." msgid "Resources" msgstr "Recursos" msgid "Resources will be given as a reward." msgstr "Recursos serão dados como recompensa." msgid "Click here to change the event message." msgstr "Clique aqui para alterar a mensagem do evento." msgid "Event Message Text" msgstr "Texto da Mensagem do Evento" msgid "Day: %{day}" msgstr "Dia: %{day}" msgid "Daily Events" msgstr "Eventos Diários" msgid "Click to save the events." msgstr "Clique para salvar os eventos." msgid "Add Event" msgstr "Adicionar Evento" msgid "Add an additional event." msgstr "Adiciona um evento adicional." msgid "Edit Event" msgstr "Editar Evento" msgid "Edit an existing event." msgstr "Edita um evento existente." msgid "Delete Event" msgstr "Excluir Evento" msgid "Delete an existing event." msgstr "Exclui um evento existente." #, fuzzy msgid "Effects:" msgstr "Efeitos" #, fuzzy msgid "Conditions:" msgstr "" "Condições\n" "de\n" "Derrota" msgid "Cancel event after first visit" msgstr "Cancelar evento após a primeira visita" #, fuzzy msgid "Computer colors allowed to get the event:" msgstr "As cores do computador podem ser usadas em eventos:" msgid "Set Experience value" msgstr "Definir o valor da Experiência" msgid "Artifact" msgstr "Artefato" #, fuzzy msgid "No artifact will be given by the event." msgstr "Nenhum artefato será dado como recompensa." msgid "Delete Artifact" msgstr "Apagar Artefato" #, fuzzy msgid "Delete an artifact from the event." msgstr "Apagar um artefato da recompensa." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Selecionar Habilidade:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" #, fuzzy msgid "No resources will be part of this event." msgstr "Nenhum recurso será dado como recompensa." #, fuzzy msgid "These resources will be a part of the event." msgstr "Nenhum recurso será dado como recompensa." msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" "Se essa caixa de seleção estiver marcada, o evento será acionado apenas uma " "vez. Se não estiver marcada, o evento será acionado toda vez que um dos " "jogadores especificados cruzar o bloco do evento." msgid "%{objects} cannot be placed on water." msgstr "%{objects} não podem ser colocados na água." msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" "O Artefato Definitivo só pode ser colocado em um terreno onde a escavação é " "possível." msgid "%{objects} must be placed on water." msgstr "%{objects} devem ser colocado na água." msgid "Objects cannot be placed outside the map." msgstr "Objetos não podem ser colocados fora do mapa." msgid "Action objects must be placed on clear tiles." msgstr "Objetos de ação devem ser colocados em ladrilhos livres." msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Deseja retornar ao Menu Principal do jogo? Todas as alterações não salvas " "serão perdidas." msgid "Editor" msgstr "Editor" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Tem certeza de que deseja carregar um novo mapa? (Todas as alterações não " "salvas no mapa atual serão perdidas.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Tem certeza de que deseja criar um novo mapa? (Todas as alterações não " "salvas no mapa atual serão perdidas.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "INICIAR" msgid "Main Menu" msgstr "Menu Principal" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Deseja retornar ao Menu Principal do jogo? Todas as alterações não salvas " "serão perdidas." msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Iniciar" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Tem certeza de que deseja carregar um novo mapa? (Todas as alterações não " "salvas no mapa atual serão perdidas.)" msgid "Create a new map from scratch." msgstr "Crie um novo mapa do zero." msgid "New Map" msgstr "Novo Mapa" msgid "Load Map" msgstr "Carregar Mapa" msgid "Load an existing map." msgstr "Carregar um mapa existente." msgid "Save Map" msgstr "Salvar Mapa" msgid "Save the current map." msgstr "Salvar o mapa atual." msgid "Quit out of the map editor." msgstr "Sair do editor de mapas." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Clique para retornar ao menu principal." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "Inserir texto de %{object}" msgid "Set Random Ultimate Artifact Radius" msgstr "Definir Raio do Artefato Definitivo Aleatório" msgid "%{object} has no properties to change." msgstr "%{object} não tem propriedades a serem alteradas." msgid "This artifact" msgstr "Esse artefato" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "Estradas" msgid "Streams" msgstr "Riachos" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "Um máximo de %{count} heróis da mesma cor pode ser colocado no mapa." msgid "Failed to update player information." msgstr "Falha ao atualizar informações do jogador." msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Apenas um Artefato Definitivo Aleatório pode ser colocado no mapa." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "É possível colocar no máximo %{count} obeliscos no mapa." msgid "The map is corrupted." msgstr "O mapa está corrompido." msgid "Unable to locate data directory to save the map." msgstr "Não foi possível localizar a pasta de dados para salvar o mapa." msgid "Unable to create a directory to save the map." msgstr "Não foi possível criar um diretório para salvar o mapa." msgid "Unable to locate a directory to save the map." msgstr "Não foi possível localizar um diretório para salvar o mapa." msgid "Are you sure you want to overwrite the existing map?" msgstr "Tem certeza de que deseja substituir o mapa existente?" msgid "Map saved to: " msgstr "Mapa salvo em: " msgid "Failed to save the map." msgstr "Falha ao salvar o mapa." msgid "Used to place %{object}." msgstr "Usado para colocar %{object}." msgid "Select object type" msgstr "Selec. tipo de objeto" msgid "" "Click here to\n" "select a monster." msgstr "" "Clique aqui para\n" "selecionar um monstro." msgid "" "Click here to\n" "select another monster." msgstr "" "Clique aqui para\n" "selecionar outro monstro." msgid "" "Cell\n" "Details" msgstr "" "Detalhes do\n" "Ladrilho" msgid "Erase" msgstr "Apagar" msgid "Mountains" msgstr "Montanhas" msgid "Rocks" msgstr "Rochas" msgid "Trees" msgstr "Ãrvores" msgid "Water Objects" msgstr "Objetos Aquáticos" msgid "Miscellaneous" msgstr "Diversos" msgid "Artifacts" msgstr "Artefatos" msgid "Dwellings" msgstr "Moradias" msgid "Mines" msgstr "Minas" msgid "Power-ups" msgstr "Intensificadores" msgid "Treasures" msgstr "Tesouros" msgid "Heroes" msgstr "Heróis" msgid "Towns" msgstr "Cidades" msgid "editorErasure|Landscape objects" msgstr "Objetos de paisagem" msgid "editorErasure|Adventure non pickable objects" msgstr "Objetos de aventura não selecionáveis" msgid "editorErasure|Castles" msgstr "Castelos" msgid "editorErasure|Adventure pickable objects" msgstr "Objetos selecionáveis de aventura" msgid "editorErasure|Monsters" msgstr "Monstros" msgid "editorErasure|Heroes" msgstr "Heróis" msgid "editorErasure|Roads" msgstr "Estradas" msgid "editorErasure|Streams" msgstr "Córregos" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Desenha terreno em\n" "%{size} por %{size} quadrados." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Apaga objetos em\n" "%{size} por %{size} quadrados." msgid "Small Brush" msgstr "Pincel Pequeno" msgid "Medium Brush" msgstr "Pincel Médio" msgid "Large Brush" msgstr "Pincel Grande" msgid "Area Fill" msgstr "Preenchimento de Ãrea" msgid "Used to click and drag for filling in large areas." msgstr "Usado para clicar e arrastar para preencher grandes áreas." msgid "Clear Area" msgstr "Limpar Ãrea" msgid "Used to click and drag for clearing large areas." msgstr "Usado para clicar e arrastar para limpar grandes áreas." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Custa %{rate} vezes o movimento normal para todos os heróis. (O " "Reconhecimento reduz ou elimina a penalidade.)" msgid "Traversable only by boat." msgstr "Apenas transitável por barco." msgid "No special modifiers." msgstr "Nenhum modificador especial." msgid "Toggle the erasure of %{type} objects." msgstr "Alternar a exclusão de objetos %{type}." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Os objetos deste tipo serão excluídos com a ferramenta de apagar. Clique com " "o botão esquerdo aqui para desmarcar este tipo. Pressione e segure este " "botão para desmarcar todos os outros tipos de objetos." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Os objetos deste tipo NÃO serão excluídos com a ferramenta de apagar. Clique " "com o botão esquerdo aqui para selecionar este tipo. Pressione e segure este " "botão para selecionar todos os outros tipos de objetos." msgid "Terrain Mode" msgstr "Modo de Terreno" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "Usado para desenhar a grama, terra, água, etc. no mapa." msgid "Landscape Objects Mode" msgstr "Modo de Objetos de Paisagem" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Usado para colocar objetos de paisagem (montanhas, rochas, árvores, etc.) no " "mapa." msgid "Detail Mode" msgstr "Modo Detalhe" msgid "Used for special editing of action objects." msgstr "Usado para edição especial de objetos de ação." msgid "Adventure Objects Mode" msgstr "Modo de Objetos de Aventura" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Usado para colocar objetos de aventura (artefatos, moradias, minas, " "tesouros, etc.) no mapa." msgid "Kingdom Objects Mode" msgstr "Modo de Objetos do Reino" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Usado para colocar objetos do reino (cidades, castelos e heróis) no mapa." msgid "Monsters Mode" msgstr "Modo de Monstros" msgid "Used to place monsters on the map." msgstr "Usado para colocar monstros no mapa." msgid "Allows you to draw streams by clicking and dragging." msgstr "Permite desenhar riachos clicando e arrastando." msgid "Stream Mode" msgstr "Modo de Riacho" msgid "Allows you to draw roads by clicking and dragging." msgstr "Permite desenhar estradas clicando e arrastando." msgid "Road Mode" msgstr "Modo de Estrada" msgid "Erase Mode" msgstr "Modo de Apagar" msgid "Used to erase objects from the map." msgstr "Usado para apagar objetos do mapa." msgid "Change between zoom and normal view." msgstr "Alternar entre zoom e visualização normal." msgid "Magnify" msgstr "Aumentar" msgid "Undo" msgstr "Desfazer" msgid "Undo your last action." msgstr "Desfazer sua última ação." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "Desfazer sua última ação." msgid "Edit map title, description, and other general information." msgstr "Editar título do mapa, descrição e outras informações gerais." msgid "Specifications" msgstr "Especificações" msgid "File Options" msgstr "Opções de Arquivo" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Abrir o menu de opções de arquivo, onde você pode salvar ou carregar mapas, " "ou sair do editor." msgid "View the editor system options, which let you customize the editor." msgstr "" "Visualizar as opções do sistema do editor, que permitem personalizar o " "editor." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" "Criar um mapa que tenha %{size} quadrados de largura e %{size} quadrados de " "altura." msgid "Cancel back to the New Map menu." msgstr "Cancelar e voltar para o menu Novo Mapa." msgid "Cancel back to the main menu." msgstr "Cancelar e voltar para o menu principal." msgid "From Scratch" msgstr "Do Zero" msgid "Start from scratch with a blank map." msgstr "Começar do zero com um mapa em branco." msgid "Create a randomly generated map." msgstr "Criar um mapa gerado aleatoriamente." msgid "Random" msgstr "Aleatório" msgid "Cancel back to the Map Editor main menu." msgstr "Cancelar e voltar para o menu principal do Editor de Mapa." msgid "No maps available!" msgstr "Nenhum mapa disponível!" msgid "[%{pos}]: %{race} hero" msgstr "[%{pos}]: herói %{race}" msgid "[%{pos}]: %{name}, %{race} hero" msgstr "[%{pos}]: %{name}, herói %{race}" msgid "[%{pos}]: %{race} town" msgstr "[%{pos}]: cidade %{race}" msgid "[%{pos}]: %{race} castle" msgstr "[%{pos}]: castelo %{race}" msgid "[%{pos}]: %{name}, %{race} town" msgstr "[%{pos}]: %{name}, cidade %{race}" msgid "[%{pos}]: %{name}, %{race} castle" msgstr "[%{pos}]: %{name}, castelo %{race}" msgid "None." msgstr "Nenhum." msgid "One side defeats another." msgstr "Um lado derrota o outro." msgid "Accumulate gold." msgstr "Acumular ouro." msgid "Run out of time." msgstr "Ficar sem tempo." msgid "alliance|1st" msgstr "1." msgid "alliance|2nd" msgstr "2." msgid "alliance|3rd" msgstr "3." msgid "alliance|4th" msgstr "4." msgid "alliance|5th" msgstr "5." msgid "Special Loss Condition" msgstr "Condição Especial de Derrota" msgid "Special Victory Condition" msgstr "Condição Especial de Vitória" msgid "Allow standard victory conditions" msgstr "Permitir condições de vitória padrão" msgid "Allow this condition also for AI" msgstr "Permitir essa condição também para IA" msgid "Set alliances:" msgstr "Definir alianças:" msgid "{%number} alliance: " msgstr "{%number} aliança: " msgid "Gold:" msgstr "Ouro:" msgid "Select a Town to capture to achieve victory" msgstr "Selecione uma cidade para capturar e alcançar a vitória" msgid "Click here to change the town needed to capture to achieve victory." msgstr "" "Clique aqui para alterar a cidade necessária para capturar e alcançar a " "vitória." msgid "Select a Hero to defeat to achieve victory" msgstr "Selecione um herói para derrotar e alcançar a vitória" msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "" "Clique aqui para alterar o herói necessário para derrotar e alcançar a " "vitória." msgid "Put %{color} player in the %{alliance} alliance" msgstr "Colocar o jogador %{color} na aliança %{alliance}" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" "Se essa caixa de seleção estiver marcada, o jogador %{color} estará na " "aliança %{alliance}." msgid "Days:" msgstr "Dias:" msgid "Select a Town to lose to suffer defeat" msgstr "Selecione uma cidade para perder e sofrer a derrota" msgid "Click here to change the town whose loss would mean defeat." msgstr "Clique aqui para alterar a cidade cuja perda significaria a derrota." msgid "Select a Hero to lose to suffer defeat" msgstr "Selecione um herói para perder e sofrer a derrota" msgid "Click here to change the hero whose loss would mean defeat." msgstr "Clique aqui para alterar o herói cuja perda significaria a derrota." msgid "Map Difficulty" msgstr "Dificuldade do Mapa" msgid "Map Description" msgstr "Descrição do Mapa" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" "A descrição do mapa inserida excede o máximo permitido de 5 linhas. Ela será " "reduzida para caber no campo de descrição do mapa." msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" "Você está prestes a alterar o idioma do mapa de %{oldLanguage} para " "%{newLanguage}. Alguns textos podem não ser exibidos corretamente depois " "disso. Deseja prosseguir?" msgid "Change Map Name" msgstr "Alterar o Nome do Mapa" msgid "Change Map Description" msgstr "Alterar Descrição do Mapa" msgid "Click to accept the changes made." msgstr "Clique para aceitar as alterações feitas." msgid "Click to edit custom rumors." msgstr "Clique para editar rumores personalizados." msgid "Rumors" msgstr "Rumores" msgid "Click to edit daily events." msgstr "Clique para editar eventos diários." msgid "Events" msgstr "Eventos" msgid "Click to change the language of the map." msgstr "Clique para alterar o idioma do mapa." msgid "Click to change your map name." msgstr "Clique para alterar o nome do mapa." msgid "Map Name" msgstr "Nome do Mapa" msgid "Click to change the description of the current map." msgstr "Clique para alterar a descrição do mapa atual." msgid "Click to change the victory condition of the current map." msgstr "Clique para alterar a condição de vitória do mapa atual." msgid "Click to change the loss condition of the current map." msgstr "Clique para alterar a condição de derrota do mapa atual." msgid "Indicates the player types in the scenario. Click to change." msgstr "Indica os tipos de jogadores no cenário. Clique para alterar." msgid "Player Type" msgstr "Tipo de Jogador" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Clique para definir a dificuldade do mapa. Os mapas mais difíceis podem " "incluir mais inimigos ou inimigos mais fortes, menos recursos ou outras " "condições especiais que tornam as coisas mais difíceis para o jogador humano." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Selecionar %{resource}:" msgid "Animation" msgstr "Animação" msgid "Passability" msgstr "Transitabilidade" msgid "Toggle animation of the objects." msgstr "Alternar animação dos objetos." msgid "Toggle display of objects' passability." msgstr "Alternar exibição da transitabilidade dos objetos." msgid "Rumor:" msgstr "Rumor:" msgid "Rumor" msgstr "Rumor" msgid "This rumor already exists in the list." msgstr "Esse rumor já existe na lista." msgid "Click to save the rumors." msgstr "Clique para salvar os rumores." msgid "Add Rumor" msgstr "Adicionar Rumor" msgid "Add an additional rumor." msgstr "Adiciona um rumor adicional." msgid "Edit Rumor" msgstr "Editar Rumor" msgid "Edit an existing rumor." msgstr "Edita um rumor existente." msgid "Delete Rumor" msgstr "Excluir rumor" msgid "Delete an existing rumor." msgstr "Exclui um rumor existente." msgid "" "\n" "\n" "Size: " msgstr "" "\n" "\n" "Tamanho: " msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Descrição: " msgid "Save Map:" msgstr "Salvar Mapa:" msgid "Click to save the current map." msgstr "Clique para salvar o mapa atual." msgid "Riddle:" msgstr "Enigma:" msgid "Answers:" msgstr "Respostas:" msgid "Answer:" msgstr "Resposta:" msgid "Answer" msgstr "Resposta" msgid "This answer exists in the list." msgstr "Essa resposta existe na lista." msgid "Click to save the Sphinx properties." msgstr "Clique para salvar as propriedades da Esfinge." msgid "Add Answer" msgstr "Adicionar Resposta" msgid "Add an additional answer for the question." msgstr "Adicione uma resposta adicional para a pergunta." msgid "Edit Answer" msgstr "Editar Resposta" msgid "Edit an existing answer for the question." msgstr "Editar uma resposta existente para a pergunta." msgid "Delete Answer" msgstr "Apagar Resposta" msgid "Delete an existing answer for the question." msgstr "Apagar uma resposta existente para a pergunta." msgid "No artifact will be given as a reward." msgstr "Nenhum artefato será dado como recompensa." msgid "Delete an artifact from the reward." msgstr "Apagar um artefato da recompensa." msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "Dia: %{day} Semana: %{week} Mês: %{month}" msgid "difficulty|Easy" msgstr "Fácil" msgid "difficulty|Normal" msgstr "Normal" msgid "difficulty|Hard" msgstr "Difícil" msgid "difficulty|Expert" msgstr "Experiente" msgid "difficulty|Impossible" msgstr "Impossível" msgid "and more..." msgstr "e mais..." msgid "Easy" msgstr "Fácil" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "Difícil" msgid "Campaign Difficulty" msgstr "Dificuldade da Campanha" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Escolha esta dificuldade para experimentar a história do jogo com menos " "desafio. A inteligência artificial será mais fraca do que na dificuldade " "Normal." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Escolha esta dificuldade para experimentar a campanha conforme o design " "original." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Escolha esta dificuldade se você deseja mais desafio. A inteligência " "artificial será mais forte do que na dificuldade Normal." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Parabéns!\n" "\n" "Dias: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Dificuldade: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Pontuação: %{score}\n" "\n" "Classificação:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Iniciar o cenário selecionado." msgid "View Intro" msgstr "Ver Introdução" msgid "View the intro video for the current state of the campaign." msgstr "Ver o vídeo de introdução para o estado atual da campanha." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Selecione a dificuldade da campanha. Ela pode ser reduzida a qualquer " "momento durante a campanha." msgid "Restart the current scenario." msgstr "Reiniciar o cenário atual." msgid "Difficulty" msgstr "Dificuldade" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Você mudou para uma dificuldade mais baixa para a campanha. Você não poderá " "reverter isso após este ponto. A pontuação final será calculada com base " "exclusivamente na nova dificuldade. Deseja continuar?" msgid "Are you sure you want to restart this scenario?" msgstr "Você tem certeza de que deseja reiniciar este cenário?" msgid "Campaign Scenario loading failure" msgstr "Falha ao carregar o Cenário da Campanha" msgid "Please make sure that campaign files are correct and present." msgstr "" "Por favor, certifique-se de que os arquivos de campanha estejam corretos e " "presentes." msgid "Days spent" msgstr "Dias passados" msgid "The number of days spent on this campaign." msgstr "O número de dias passados nesta campanha." msgid "Project Coordination and Core Development" msgstr "Coordenação do Projeto e Núcleo de Desenvolvimento" msgid "Development" msgstr "Desenvolvimento" msgid "Visit us at " msgstr "Nos visite em " msgid "QA and Support" msgstr "Controle de Qualidade e Suporte" msgid "Dev and Support" msgstr "Desenvolvimento e Suporte" msgid "Special Thanks to" msgstr "Agradecimentos Especiais para" msgid "and many-many other contributors and supporters!" msgstr "e muitos outros colaboradores e apoiadores!" msgid "Support us at" msgstr "Apoie-nos em" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Conecte-se conosco em" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Precisa de ajuda com o jogo?" msgid "Original project before 0.7" msgstr "Projeto original antes da versão 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Equipe de Heroes of Might and Magic II: As Guerras de Sucessão" msgid "Designed and Directed" msgstr "Projetado e Dirigido" msgid "Programming and Design" msgstr "Programação e Projeto" msgid "Executive Producer" msgstr "Produtor Executivo" msgid "Producer" msgstr "Produtor" msgid "Additional Design" msgstr "Projeto Adicional" msgid "Additional Programming" msgstr "Programação Adicional" msgid "Musical Production" msgstr "Produção Musical" msgid "Music and Sound Design" msgstr "Música e Projeto de Som" msgid "Vocalists" msgstr "Vocalistas" msgid "Art Director" msgstr "Diretores de Arte" msgid "Assistant Art Director" msgstr "Assistente do Diretor de Arte" msgid "Artists" msgstr "Artistas" msgid "QA Manager" msgstr "Gerente de Controle de Qualidade" msgid "QA" msgstr "Controle de Qualidade" msgid "Writing" msgstr "Roteirista" msgid "Manual and Helpfile" msgstr "Manual e Arquivo de Ajuda" msgid "Scenarios" msgstr "Cenários" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Equipe de Heroes of Might and Magic II: O Preço da Lealdade" msgid "Design Lead" msgstr "Líder de Design" msgid "Designers" msgstr "Designers" msgid "Programming Lead" msgstr "Líder de Programação" msgid "Art Lead" msgstr "Líder de Arte" msgid "Playtesters" msgstr "Testadores" msgid "Designer" msgstr "Designer" msgid "Producers" msgstr "Produtores" msgid "QA Managers" msgstr "Gerentes de QA" msgid "Sound Design" msgstr "Projeto de Som" msgid "Town Themes" msgstr "Temas das Cidades" msgid "Alto Sax" msgstr "Saxofone Alto" msgid "Harpsichord and Piano" msgstr "Cravo e Piano" msgid "Basso Vocal" msgstr "Vocal Baixo" msgid "Soprano Vocal" msgstr "Vocal Soprano" msgid "Recorded at %{recordingStudio}" msgstr "Gravado em %{recordingStudio}" msgid "credits|Manual" msgstr "Manual" msgid "German Consultant" msgstr "Consultor Alemão" msgid "Map Designers" msgstr "Designers de Mapa" msgid "Package Design" msgstr "Design da Embalagem" msgid "High Scores" msgstr "Melhores Pontuações" msgid "Your Name" msgstr "Seu Nome" msgid "Unknown Hero" msgstr "Herói Desconhecido" msgid "Standard" msgstr "Padrão" msgid "View High Scores for Standard Maps." msgstr "Veja as Melhores Pontuações para os Mapas Padrões." msgid "Campaign" msgstr "Campanha" msgid "View High Scores for Campaigns." msgstr "Veja as Melhores Pontuações para as Campanhas." msgid "hotkey|default okay event" msgstr "evento padrão de confirmação" msgid "hotkey|default cancel event" msgstr "evento padrão de cancelamento" msgid "hotkey|default left" msgstr "padrão para a esquerda" msgid "hotkey|default right" msgstr "padrão para a direita" msgid "hotkey|default up" msgstr "padrão para cima" msgid "hotkey|default down" msgstr "padrão para baixo" msgid "hotkey|toggle fullscreen" msgstr "alternar tela cheia" msgid "hotkey|toggle text support mode" msgstr "alternar modo de suporte a texto" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "alternar modo de suporte a texto" msgid "hotkey|new game" msgstr "novo jogo" msgid "hotkey|load game" msgstr "carregar jogo" msgid "hotkey|high scores" msgstr "melhores pontuações" msgid "hotkey|credits" msgstr "créditos" msgid "hotkey|standard game" msgstr "jogo padrão" msgid "hotkey|campaign game" msgstr "jogo de campanha" msgid "hotkey|multi-player game" msgstr "jogo multijogador" msgid "hotkey|settings" msgstr "configurações" msgid "hotkey|quit" msgstr "sair" msgid "hotkey|select map" msgstr "selecionar mapa" msgid "hotkey|select small map size" msgstr "selecionar mapa pequeno" msgid "hotkey|select medium map size" msgstr "selecionar mapa médio" msgid "hotkey|select large map size" msgstr "selecionar mapa grande" msgid "hotkey|select extra large map size" msgstr "selecionar mapa extra grande" msgid "hotkey|select all map sizes" msgstr "selecionar todos os mapa" msgid "hotkey|hot seat game" msgstr "jogo em rodízio" msgid "hotkey|battle only game" msgstr "jogo apenas de batalha" msgid "hotkey|choose the original campaign" msgstr "escolher a campanha original" msgid "hotkey|choose the expansion campaign" msgstr "escolher a campanha de expansão" msgid "hotkey|map editor main menu" msgstr "menu principal do editor de mapas" msgid "hotkey|new map menu" msgstr "menu novo de mapa" msgid "hotkey|load map menu" msgstr "menu de carregar mapa" msgid "hotkey|new map from scratch" msgstr "novo mapa do zero" msgid "hotkey|new random map" msgstr "novo mapa aleatório" msgid "hotkey|undo last action" msgstr "desfazer última ação" msgid "hotkey|redo last action" msgstr "refazer última ação" msgid "hotkey|open game main menu" msgstr "abrir menu principal do jogo" msgid "hotkey|toggle passability" msgstr "alternar transitabilidade" msgid "hotkey|roland campaign" msgstr "campanha de Roland" msgid "hotkey|archibald campaign" msgstr "campanha de Archibald" msgid "hotkey|price of loyalty campaign" msgstr "campanha Preço da Lealdade" msgid "hotkey|voyage home campaign" msgstr "campanha Viagem de Volta para Casa" msgid "hotkey|wizard's isle campaign" msgstr "campanha Ilha do Mago" msgid "hotkey|descendants campaign" msgstr "campanha Descendentes" msgid "hotkey|select first campaign bonus" msgstr "selecionar primeiro bônus da campanha" msgid "hotkey|select second campaign bonus" msgstr "selecionar segundo bônus da campanha" msgid "hotkey|select third campaign bonus" msgstr "selecionar terceiro bônus da campanha" msgid "hotkey|view campaign intro" msgstr "ver introdução da campanha" msgid "hotkey|select campaign difficulty" msgstr "selecionar dificuldade da campanha" msgid "hotkey|restart campaign scenario" msgstr "reiniciar cenário da campanha" msgid "hotkey|world map left" msgstr "mapa mundi para esquerda" msgid "hotkey|world map right" msgstr "mapa mundi para direita" msgid "hotkey|world map up" msgstr "mapa mundi para cima" msgid "hotkey|world map down" msgstr "mapa mundi para baixo" msgid "hotkey|world map up left" msgstr "mapa mundi para cima e esquerda" msgid "hotkey|world map up right" msgstr "mapa mundi para cima e direita" msgid "hotkey|world map down left" msgstr "mapa mundi para baixo e esquerda" msgid "hotkey|world map down right" msgstr "mapa mundi para baixo e direita" msgid "hotkey|save game" msgstr "salvar jogo" msgid "hotkey|next hero" msgstr "próximo herói" msgid "hotkey|change to hero under cursor" msgstr "mudar para o herói sob o cursor" msgid "hotkey|start hero movement" msgstr "iniciar movimento do herói" msgid "hotkey|cast adventure spell" msgstr "lançar feitiço de aventura" msgid "hotkey|put hero to sleep" msgstr "colocar herói para dormir" msgid "hotkey|next town" msgstr "próxima cidade" msgid "hotkey|end turn" msgstr "encerrar turno" msgid "hotkey|file options" msgstr "opções de arquivo" msgid "hotkey|adventure options" msgstr "opções de aventura" msgid "hotkey|puzzle map" msgstr "mapa de quebra-cabeça" msgid "hotkey|scenario information" msgstr "informações do cenário" msgid "hotkey|dig for artifact" msgstr "escavar por artefato" msgid "hotkey|view world" msgstr "visualizar mundo" msgid "hotkey|kingdom summary" msgstr "resumo do reino" msgid "hotkey|default action" msgstr "ação padrão" msgid "hotkey|open focus" msgstr "abrir foco" msgid "hotkey|system options" msgstr "opções do sistema" msgid "hotkey|scroll left" msgstr "rolar para a esquerda" msgid "hotkey|scroll right" msgstr "rolar para a direita" msgid "hotkey|scroll up" msgstr "rolar para cima" msgid "hotkey|scroll down" msgstr "rolar para baixo" msgid "hotkey|toggle control panel" msgstr "alternar painel de controle" msgid "hotkey|toggle radar" msgstr "alternar radar" msgid "hotkey|toggle buttons" msgstr "alternar botões" msgid "hotkey|toggle status" msgstr "alternar status" msgid "hotkey|toggle icons" msgstr "alternar ícones" msgid "hotkey|transfer control to ai" msgstr "transferir controle para IA" msgid "hotkey|retreat from battle" msgstr "retirar-se da batalha" msgid "hotkey|surrender during battle" msgstr "render-se durante a batalha" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "alternar modo de batalha automático" #, fuzzy msgid "hotkey|quick combat" msgstr "sair" msgid "hotkey|battle options" msgstr "opções de batalha" msgid "hotkey|skip turn in battle" msgstr "pular turno na batalha" msgid "hotkey|cast battle spell" msgstr "lançar feitiço de batalha" msgid "hotkey|dwelling level 1" msgstr "nível 1 da moradia" msgid "hotkey|dwelling level 2" msgstr "nível 2 da moradia" msgid "hotkey|dwelling level 3" msgstr "nível 3 da moradia" msgid "hotkey|dwelling level 4" msgstr "nível 4 da moradia" msgid "hotkey|dwelling level 5" msgstr "nível 5 da moradia" msgid "hotkey|dwelling level 6" msgstr "nível 6 da moradia" msgid "hotkey|well" msgstr "poço" msgid "hotkey|marketplace" msgstr "mercado" msgid "hotkey|mage guild" msgstr "guilda dos magos" msgid "hotkey|shipyard" msgstr "estaleiro" msgid "hotkey|thieves guild" msgstr "guilda dos ladrões" msgid "hotkey|tavern" msgstr "taverna" msgid "hotkey|construction screen" msgstr "tela de construção" msgid "hotkey|buy all monsters in well" msgstr "comprar todos os monstros no poço" msgid "hotkey|split stack by half" msgstr "dividir pilha pela metade" msgid "hotkey|split stack by one" msgstr "dividir pilha por um" msgid "hotkey|join stacks" msgstr "juntar pilhas" msgid "hotkey|upgrade troop" msgstr "atualizar tropa" msgid "hotkey|dismiss hero or troop" msgstr "dispensar herói ou tropa" #, fuzzy msgid "hotkey|exchange all troops" msgstr "atualizar tropa" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Você deseja recuperar o controle da IA? O efeito ocorrerá somente no próximo " "turno." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Deseja transferir seu controle para a IA? O efeito ocorrerá somente no " "próximo turno." msgid "Default Actions" msgstr "Ações Padrão" msgid "Global Actions" msgstr "Ações Globais" msgid "World Map" msgstr "Mapa-Múndi" msgid "Battle Screen" msgstr "Tela de Batalha" msgid "Town Screen" msgstr "Tela da Cidade" msgid "Army Actions" msgstr "Ações do Exército" msgid "The save file is corrupted." msgstr "O arquivo salvo está corrompido." msgid "Unsupported save format: " msgstr "Formato de salvamento não suportado: " msgid "Current game version: " msgstr "Versão atual do jogo: " msgid "Last supported version: " msgstr "Última versão suportada: " msgid "This file contains a save with an invalid game type." msgstr "Este arquivo contém um jogo salvo com um tipo de jogo inválido." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Este arquivo de salvamento requer ativos do jogo \"O Preço da Lealdade\", " "mas eles não foram fornecidos ao motor." msgid "This saved game is localized to '" msgstr "Este jogo salvo está localizado em '" msgid "' language, but the current language of the game is '" msgstr "' idioma, mas o idioma atual do jogo é '" msgid "No save files to load." msgstr "Sem arquivos salvos para carregar." msgid "Hot Seat" msgstr "Jogo em Rodízio" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Jogue um 'Jogo em Rodízio' onde de 2 a 6 jogadores jogam no mesmo computador " "por turnos." msgid "A single player game playing out a single map." msgstr "Um jogo com um único jogador." msgid "Standard Game" msgstr "Jogo Padrão" msgid "A single player game playing through a series of maps." msgstr "Um único jogador jogando em uma série de mapas." msgid "Campaign Game" msgstr "Campanha" msgid "Multi-Player Game" msgstr "Multijogador" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Um jogo multijogador, com vários jogadores humanos completando uns contra os " "outros em um único mapa." msgid "fheroes2 Resurrection Team presents" msgstr "A Equipe fheroes2 Resurrection apresenta" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "Bem-vindo ao Heroes of Might e Magic II movido pelo motor fheroes2!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" "\n" "\n" "Para simular um clique com o botão direito usando o toque para obter " "informações sobre vários itens, primeiro toque e mantenha o toque no item de " "interesse. Em seguida, toque em qualquer outro lugar na tela. Enquanto " "mantém o segundo dedo pressionado, você pode remover o primeiro dedo da tela " "e continuar visualizando as informações sobre o item." msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "\n" "\n" "Antes de iniciar o jogo, selecione uma resolução." msgid "Greetings!" msgstr "Parabéns!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Sair do Heroes of Might and Magic II e retornar ao sistema operacional." msgid "Credits" msgstr "Créditos" msgid "View the credits screen." msgstr "Ver tela dos créditos." msgid "View the high scores screen." msgstr "Ver a tela de melhores pontuações." msgid "Create new or modify existing maps." msgstr "Criar novos mapas ou modificar os existentes." msgid "Change language, resolution and settings of the game." msgstr "Altera o idioma, a resolução e as configurações do jogo." msgid "Game Settings" msgstr "Configurações do Jogo" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Os arquivos de vídeo necessários para a janela de seleção de campanha estão " "faltando. Certifique-se de que todos os arquivos necessários estejam " "presentes no sistema." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Tanto a campanha de Roland ou a campanha de Archibald do Heroes of Might and " "Magic II original." msgid "Original Campaign" msgstr "Campanha Original" msgid "Expansion Campaign" msgstr "Campanha da Expansão" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" "Uma das quatro novas campanhas do conjunto de expansão 'O Preço da Lealdade'." msgid "Loading video. Please wait..." msgstr "Carregando o vídeo. Por favor, aguarde..." msgid "Host" msgstr "Anfitrião" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "O anfitrião configura as opções de jogo. Só pode haver um anfitrião por jogo " "em rede." msgid "Guest" msgstr "Convidado" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "O convidado espera pelo anfitrião configurar o jogo, em seguida, é " "adicionado automaticamente dentro. Pode haver vários convidados para Jogos " "TCP/IP." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "O fheroes2 precisa dos arquivos de dados do Heroes of Might and Magic II " "original para funcionar. Parece que você está usando a versão de " "demonstração do Heroes of Might and Magic II para este fim. Por favor, note " "que apenas um cenário estará disponível nesta configuração." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Um jogo multijogador, com vários jogadores humanos competindo entre si em um " "único mapa." msgid "Battle Only" msgstr "Apenas Batalha" msgid "Setup and play a battle without loading any map." msgstr "Configure e jogue uma batalha sem carregar nenhum mapa." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Jogue um 'Jogo em Rodízio' onde de 2 a 6 jogadores jogam no mesmo " "dispositivo por turnos." msgid "2 Players" msgstr "2 Jogadores" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Jogue com 2 jogadores humanos e, opcionalmente, até 4 jogadores controlados " "pelo computador adicionais." msgid "3 Players" msgstr "3 Jogadores" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Jogue com 3 jogadores humanos e, opcionalmente, até 3 jogadores controlados " "pelo computador adicionais." msgid "4 Players" msgstr "4 Jogadores" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Jogue com 4 jogadores humanos, e opcionalmente, até 2 jogadores controlados " "pelo computador adicionais." msgid "5 Players" msgstr "5 Jogadores" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Jogue com 5 jogadores humanos, e opcionalmente, até 1 jogador controlado " "pelo computador adicional." msgid "6 Players" msgstr "6 Jogadores" msgid "Play with 6 human players." msgstr "Jogue com 6 jogadores humanos." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "A Cidade Dragão caiu! Agora você é o Mestre dos Dragões." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Você capturou %{name}!\n" "Você é o vitorioso." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Você capturou o herói inimigo %{name}!\n" "Sua missão está completa." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Você achou o %{name}.\n" "Sua missão está completa." msgid "Ultimate Artifact" msgstr "Artefato Definitivo" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "O inimigo foi derrotado.\n" "Seu lado triunfou!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Você tem acumulou o total %{count} de ouro.\n" "Todos os inimigos curvar-se diante de sua riqueza e poder." msgid "Victory!" msgstr "Vitória!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "O inimigo capturou %{name}!\n" "Eles triunfaram." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "O inimigo acumulou o total de %{count} de ouro.\n" "Você curvou-se diante do seu poder e riqueza." msgid "You have been eliminated from the game!!!" msgstr "Você foi eliminado do jogo!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Você perdeu o herói %{name}.\n" "Sua missão acabou." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Você não conseguiu concluir sua missão no tempo.\n" "Tudo está perdido." msgid "Defeat!" msgstr "Derrota!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Pontuação base: %{score}\n" "Dificuldade: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Derrotar todos os heróis inimigos e capturar todas as cidades e castelos " "inimigos." msgid "Your side defeats the opposing side." msgstr "Seu lado derrota o lado oposto." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" "Acabar o tempo. (Impossibilitado de vencer a partir de um certo ponto.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Você deve derrotar o inimigo %{enemies}." msgstr[1] "Você deve derrotar a aliança inimiga dos %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "A aliança composta por %{allies} e você deve derrotar o inimigo %{enemies}." msgstr[1] "" "A aliança composta por %{allies} e você deve derrotar a aliança inimiga dos " "%{enemies}." msgid "Capture the castle '%{name}'." msgstr "Capture o castelo '%{name}'." msgid "Capture the town '%{name}'." msgstr "Capture a cidade '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Derrote o herói '%{name}'." msgid "Find the ultimate artifact." msgstr "Encontre o artefato definitivo." msgid "Find the '%{name}' artifact." msgstr "Encontre o artefato '%{name}'." msgid "Accumulate %{count} gold." msgstr "Acumule %{count} de ouro." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", ou derrote todos os heróis inimigos e capture todas as cidades e castelos " "inimigos." msgid "Lose the castle '%{name}'." msgstr "Perda o castelo '%{name}'." msgid "Lose the town '%{name}'." msgstr "Perda a cidade '%{name}'." msgid "Lose the hero: %{name}." msgstr "Perda o herói: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "Não vença até o final do mês %{month}, semana %{week}, dia %{day}." msgid "%{color} player has been vanquished!" msgstr "O jogador %{color} foi derrotado!" msgid "Major Event!" msgstr "Evento Importante!" msgid "Scenario:" msgstr "Cenário:" msgid "Game Difficulty:" msgstr "Dificuldade do Jogo:" msgid "Opponents:" msgstr "Oponentes:" msgid "Class:" msgstr "Classe:" msgid "Rating %{rating}%" msgstr "Nível %{rating}%" msgid "Click here to select which scenario to play." msgstr "Clique aqui para selecionar o cenário a jogar." msgid "Scenario" msgstr "Cenário" msgid "Game Difficulty" msgstr "Dificuldade do Jogo" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Isso permite alterar a dificuldade inicial na qual você jogará. Níveis de " "dificuldade mais altos iniciam o jogo com menos recursos e, nas " "configurações mais altas, fornecem recursos extras ao computador." msgid "Difficulty Rating" msgstr "Nível de Dificuldade" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "O nível de dificuldade reflete uma combinação de várias definições para o " "seu jogo. Este número será aplicado à sua pontuação final." msgid "Click to accept these settings and start a new game." msgstr "Clique para aceitar estas configurações e começar um novo jogo." msgid "Click to return to the main menu." msgstr "Clique para retornar ao menu principal." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Os astrólogos proclamam o Mês de %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Os astrólogos proclamam a Semana de %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "Após uma produção regular, a população de %{monster} é duplicada!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Após uma produção regular, a população de %{monster} aumenta em %{count} por " "cento!" msgstr[1] "" "Após uma produção regular, a população de %{monster} aumenta em %{count} por " "cento!" msgid "%{monster} growth +%{count}." msgstr "Produção de +%{count} de %{monster}." msgid " All populations are halved." msgstr " Todas as populações foram reduzidas a metade." msgid " All dwellings increase population." msgstr " Todas as moradias aumentam de população." msgid "New Month!" msgstr "Novo Mês!" msgid "New Week!" msgstr "Nova Semana!" msgid "Beware!" msgstr "Cuidado!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "Jogador %{color}, este é o último dia para capturar uma cidade, ou você será " "banido desta terra." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "Jogador %{color}, você tem somente %{day} dias para capturar uma cidade, ou " "você será banido desta terra." msgid "%{color} player's turn." msgstr "Turno do jogador %{color}." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "Jogador %{color}, você perdeu sua última cidade. Se não conquistar outra " "cidade na próxima semana, você será eliminado." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "Jogador %{color}, seus heróis abandonaram você, e você foi banido de sua " "terra." msgid "Lord Kilburn" msgstr "Lorde Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lorde Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Máximus" msgid "Next Hero" msgstr "Próximo Herói" msgid "Select the next Hero." msgstr "Selecione o próximo Herói." msgid "Hero Movement" msgstr "Movimento do Herói" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "Iniciar o movimento do herói ao longo do caminho atual ou revisitar o objeto " "ocupado pelo herói. Pressione e segure este botão para redefinir o caminho " "do herói." msgid "Kingdom Summary" msgstr "Resumo do Reino" msgid "View a summary of your Kingdom." msgstr "Veja um resumo do seu Reino." msgid "Cast an adventure spell." msgstr "Lança um feitiço de aventura." msgid "End Turn" msgstr "Terminar Turno" msgid "End your turn and let the computer take its turn." msgstr "Termine o seu turno e deixe o computador fazer o seu turno." msgid "Adventure Options" msgstr "Opções de Aventura" msgid "Bring up the adventure options menu." msgstr "Acessa o menu de opções da aventura." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Acessa o menu de opções de arquivo, permitindo carregar, salvar, iniciar um " "novo jogo ou sair." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Acessa o menu de opções do sistema, permitindo que você personalize seu jogo." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Um ou mais heróis ainda podem se mover, você tem certeza de que deseja " "encerrar seu turno?" msgid "Are you sure you want to quit?" msgstr "Você tem certeza de que deseja sair?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Você tem certeza de que deseja reiniciar? (Seu jogo atual será perdido)." msgid "Are you sure you want to overwrite the save with this name?" msgstr "" "Você tem certeza de que deseja sobrescrever o jogo salvo com este nome?" msgid "Game saved successfully." msgstr "Jogo salvo com sucesso." msgid "There was an issue during saving." msgstr "Houve um problema durante o salvamento." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Você tem certeza de que deseja carregar um novo jogo? (Seu jogo atual será " "perdido)." msgid "Try looking on land!!!" msgstr "Tente olhar para a terra!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Procurar pelo Artefato Definitivo é inútil. Seu herói não poderia carregá-lo " "mesmo se o encontrasse - todos os seus espaços de artefato estão cheios." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" "Escavar em busca de artefatos requer um dia inteiro, tente novamente amanhã." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Após passar várias horas cavando aqui, você descobriu o artefato %{artifact}." msgid "Congratulations!" msgstr "Parabéns!" msgid "Nothing here. Where could it be?" msgstr "Nada aqui. Onde poderia estar?" msgid "Try searching on clear ground." msgstr "Tente escavar em um chão sem obstáculos." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Uma visão em miniatura do mundo conhecido. Clique no botão esquerdo para " "mover a área de visualização." msgid "Month: %{month} Week: %{week}" msgstr "Mês: %{month} Semana: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Você achou uma pequena\n" "quantidade de %{resource}." msgid "Status Window" msgstr "Janela de Status" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Esta janela fornece informações sobre o status do seu herói ou reino, e " "mostra a data." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Esta janela fornece informações sobre o status do seu herói ou reino, e " "mostra a data. Clique no botão esquerdo para alternar entra as janelas." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Isto permite mudar as posições iniciais e as cores dos jogadores. Uma " "determinada cor sempre começará em um determinado local. Algumas posições " "podem ser jogadas apenas por um jogador de computador ou apenas por um " "jogador humano." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Isto permite que você mude a classe de um jogador. As classes nem sempre são " "mutáveis. Dependendo do cenário, um jogador pode receber cidades adicionais " "ou heróis que não sejam de seu alinhamento primário." msgid "Handicap" msgstr "Desvantagem" msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Isso permite que você altere a desvantagem de um jogador específico. Apenas " "os jogadores humanos podem ter uma desvantagem. Os jogadores com desvantagem " "começam com menos recursos e ganham 15 ou 30% menos recursos por turno para " "desvantagens leves e graves, respectivamente." msgid "%{color} player" msgstr "Jogador %{color}" msgid "No Handicap" msgstr "Sem Desvantagem" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Sem restrições especiais nos recursos iniciais e na renda de recursos por " "turno." msgid "Mild Handicap" msgstr "Desvantagem Leve" msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Os jogadores com desvantagem leve começam com menos recursos e ganham 15% " "menos recursos por turno." msgid "Severe Handicap" msgstr "Desvantagem Severa" msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Os jogadores com desvantagem severa começam com menos recursos e ganham 30% " "menos recursos por turno." msgid "" "Default\n" "value" msgstr "" "Valor\n" "padrão" msgid "Set %{skill} Skill" msgstr "Definir %{skill}" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" "Definir valor base de %{skill}. Clique com o botão direito para redefinir " "todas as habilidades para o padrão." msgid "View %{skill} Info" msgstr "Ver informações de %{skill}" msgid "" "Default\n" "skill" msgstr "" "Habilidade\n" "padrão" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "ESPAÇO" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "O valor inserido é inválido." msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" "O valor inserido está fora do intervalo.\n" "Deve ser no mínimo %{minValue} e no máximo %{maxValue}." msgid "Kingdom Income" msgstr "Renda do Reino" msgid "Kingdom Income per day." msgstr "Renda diária do Reino." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Para cada farol controlado, seus navios se moverão mais longe a cada dia." msgid "English" msgstr "Inglês" msgid "French" msgstr "Francês" msgid "Polish" msgstr "Polonês" msgid "German" msgstr "Alemão" msgid "Russian" msgstr "Russo" msgid "Italian" msgstr "Italiano" msgid "Czech" msgstr "Tcheco" msgid "Norwegian" msgstr "Norueguês" msgid "Belarusian" msgstr "Bielorrusso" msgid "Bulgarian" msgstr "Búlgaro" msgid "Ukrainian" msgstr "Ucraniano" msgid "Romanian" msgstr "Romeno" msgid "Spanish" msgstr "Espanhol" msgid "Swedish" msgstr "Sueco" msgid "Portuguese" msgstr "Português" msgid "Turkish" msgstr "Turco" msgid "Dutch" msgstr "Neerlandês" msgid "Hungarian" msgstr "Húngaro" msgid "Danish" msgstr "Dinamarquês" msgid "Slovak" msgstr "Eslovaco" msgid "Vietnamese" msgstr "Vietnamita" msgid "Slow" msgstr "Lenta" msgid "Fast" msgstr "Rápida" msgid "Very Fast" msgstr "Muito Rápida" msgid "Evil" msgstr "Do Mal" msgid "Good" msgstr "Do Bem" msgid ", FPS: " msgstr ", QPS: " msgid "shipAndGraveyard|%{object} robber" msgstr "Ladrão de %{object}" msgid "pyramid|%{object} raided" msgstr "%{object} assaltada" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Rubi" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Célia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lorde Corlagon" msgid "Lord Halton" msgstr "Lorde Halton" msgid "Sister Eliza" msgstr "Irmã Eliza" msgid "Brother Brax" msgstr "Irmão Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " concede o máximo de moral" msgid " gives you maximum luck" msgstr " concede o máximo de sorte" msgid "You cannot have multiple spell books." msgstr "Você não pode ter vários grimórios." msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Não é possível pegar este artefato, você está sobrecarregado!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Para lançar feitiços, você deve primeiro comprar um grimório por %{gold} de " "ouro." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" "Infelizmente, você parece estar um pouco desprovido de dinheiro no momento." msgid "Do you wish to buy one?" msgstr "Você deseja comprar um?" msgid "%{count} / day" msgstr "%{count} por dia" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "Um redemoinho envolve seu navio. Parte de seu exército caiu ao mar." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Insultados pela sua recusa da oferta, os monstros atacam!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "Impressionados com o poder de suas forças, %{monster} começam a se " "dispersar.\n" "Você deseja persegui-los e atacá-los?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "Ao saquear um campo inimigo, você descobre um tesouros escondido." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "O responsável pelo moinho anuncia:\n" "\"Milorde, estou trabalhado muito para fornecer esses recursos para você, " "volte na próxima semana para mais.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "O responsável pelo moinho anuncia:\n" "\"Milorde, lamento, não há recursos disponíveis no momento. Por favor, tente " "novamente na próxima semana.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "O responsável pelo moinho anuncia:\n" "\"Milorde, estou trabalhado muito para fornecer este ouro para você, volte " "na próxima semana para mais.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "O responsável pelo moinho anuncia:\n" "\"Milorde, lamento, não há ouro atualmente disponível. Por favor, tente " "novamente na próxima semana.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Você encontrou um abrigo abandonado.\n" "Ao vasculhar, você descobre alguns recursos escondidos nas proximidades." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "O abrigo está abandonado há muito tempo. Não há nada de valor aqui." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Você captura um duende dormindo descuidadamente em meio a um grupo de " "cogumelos mágicos.\n" "Em troca de sua liberdade, ele o guia para um pequeno pote cheio de coisas " "preciosas." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Você encontrou um jardim mágico, o tipo de lugar que os duendes e as fadas " "gostam de se divertir, mas não há ninguém aqui hoje.\n" "Talvez você devesse tentar novamente na próxima semana." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Você encontra os restos mortais de um infeliz aventureiro." msgid "Treasure" msgstr "Tesouro" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Ao procurar nas roupas esfarrapadas, você encontra %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Ao procurar nas roupas esfarrapadas, você não encontra nada." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Você se depara com uma velha carroça deixada por um comerciante que não " "conseguiu chegar a um lugar seguro." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Infelizmente, outros encontraram primeiro, e a carroça está vazia." msgid "Searching inside, you find the %{artifact}." msgstr "Ao procurar dentro, você encontra %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "No interior, você encontra parte da carga da carroça ainda intacta." msgid "You search through the flotsam, and find some wood and some gold." msgstr "" "Você procura através dos destroços, e encontrar um pouco de madeira e um " "pouco de ouro." msgid "You search through the flotsam, and find some wood." msgstr "Você procura através dos destroços, e encontrar um pouco de madeira." msgid "You search through the flotsam, but find nothing." msgstr "Você procura através dos destroços, mas não acha nada." msgid "Shrine of the 1st Circle" msgstr "Santuário do 1o Ciclo" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Você encontra um pequeno santuário frequentado por um grupo de acólitos " "novatos.\n" "Em troca de sua proteção, eles concordam em ensinar-lhe o feitiço simples - " "'%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Santuário do 2o Ciclo" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Você se depara com um santuário ornamentado, frequentado por um grupo de " "frades rotundos.\n" "Em troca de sua proteção, eles concordam em lhe ensinar o feitiço - " "'%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Santuário do 3o Ciclo" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Você se depara com um santuário pródigo, frequentado por um grupo de sumos " "sacerdotes.\n" "Em troca de sua proteção, eles concordam em ensinar-lhe o feitiço avançado - " "'%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Infelizmente, você não tem a sabedoria para compreender o feitiço, e é " "incapaz de aprender." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Infelizmente, você já conhece este feitiço, portanto não há mais nada para " "ensinar." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Infelizmente, você não tem nenhum Grimório para gravar esse feitiço." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Você se aproxima da cabana e observa uma bruxa estudando um livro antigo " "sobre %{skill}.\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Enquanto você se aproxima, ela se vira e focaliza seu único olho de vidro em " "você.\n" "\"Você já sabe tudo o que merece aprender!\" a bruxa grita. \"AGORA SAI DA " "MINHA CASA!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Quando você se aproxima, ela se vira e fala.\n" "\"Você já sabe o que eu ia te ensinar. Eu não posso te ajudar mais.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Uma antiga e imortal bruxa que vive em uma cabana, ensina a você %{skill}, " "para seus inescrutáveis propósitos." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "Ao beber a água doce, você ganha sorte para sua próxima batalha." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Você bebe da fonte encantada, mas nada acontece." msgid "You enter the faerie ring, but nothing happens." msgstr "Você entra no círculo das fadas, mas nada acontece." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Ao entrar no círculo das fadas mística, o seu exército ganha sorte para a " "sua próxima batalha." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Você encontrou um ídolo de pedra antigo e desgastado.\n" "É para dar sorte aos visitantes, mas como as estrelas já estão sorrindo para " "você, ele não faz nada." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Você encontrou um ídolo de pedra antigo e desgastado.\n" "Supostamente ao beijá-lo você teria sorte, então você o beija. A pedra é " "muito fria ao toque." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "As sereias silenciosamente seduzem você a voltar mais tarde e ser abençoado " "novamente." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "A beleza mágica e reconfortante das sereias chega até você e sua " "tripulação.\n" "Por um momento, você esquece suas preocupações e se encanta com a beleza do " "momento.\n" "Os encantos das sereias o abençoam com mais sorte para seu próximo combate." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Você chega à pirâmide de um grande e antigo rei.\n" "Você é tentado a procurar por tesouros, mas todas as histórias antigas " "advertem sobre maldições terríveis e guardiões mortos-vivos.\n" "Deseja procurar?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Após derrotar as criaturas, você decifrar um hieróglifo antigo na parede, " "contando o segredo do feitiço - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Infelizmente, você não tem nenhum Grimório para gravar esse feitiço." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Infelizmente, você não tem a sabedoria para compreender o feitiço, e é " "incapaz de aprender." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Você chega à pirâmide de um grande e antigo rei.\n" "A exploração de rotina revela que a pirâmide está completamente vazia." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Supostamente ao beber do poço, sua mana seria restaurada, mas ela já está no " "máximo." msgid "A second drink at the well in one day will not help you." msgstr "Beber duas vezes da água do poço em um dia não vai te ajudar." msgid "A drink from the well has restored your spell points to maximum." msgstr "Ao beber do poço, você restaurou sua mana ao máximo." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Me desculpe senhor,\" O líder dos soldados diz, \"mas você já sabe tudo o " "que temos para ensinar.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Os soldados que vivem no forte lhe ensinam alguns novos truques de defesa." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Você encontrou um campo de mercenários praticando suas táticas. \"Você é " "muito avançado para nós\", diz o capitão mercenário. \"Não podemos ensinar " "mais nada.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Você encontrou um campo de mercenários praticando suas táticas. Os " "mercenários dão-lhe as boas-vindas e convidam-no a treinar com eles." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Vá embora!\", rosna o curandeiro, \"Você sabe tudo o que sei.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Um curandeiro Orc que vive na cabana, aumenta o seu conhecimento de magia, " "mostrando-lhe como lançar pedras, ler presságio e decifrar as vísceras de " "frango." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Você encontrou um grupo de Druidas adorando uma de suas estranhas estruturas " "de pedra. Silenciosamente, os Druidas o afastam, indicando que eles não têm " "nada de novo para lhe ensinar." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Você encontrou um grupo de Druidas venerando uma de suas estranhas " "estruturas de pedra. Silenciosamente, eles lhe ensinam novas maneiras de " "lançar feitiços." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Você se aproxima do cemitério dos antigos guerreiros. Deseja vasculhar os " "túmulos?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Você passa várias horas procurando nos túmulos e não encontra nada. Um ato " "tão desprezível reduz a moral de seu exército." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "Ao derrotar os Zumbis, você procura nos túmulos e encontra algo!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "O casco apodrecido de um grande navio pirata range assustadoramente ao ser " "empurrado contra as rochas. Você deseja vasculhar o navio naufragado?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Você passa várias horas vasculhando os escombros e não encontra nada. Um ato " "tão desprezível reduz a moral de seu exército." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "Ao derrotar os Fantasmas você vasculha os escombros e encontra algo!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "A podridão do casco de um navio pirata range assustadoramente grande quando " "ele é empurrado contra as rochas. Você deseja pesquisar o navio?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "Ao derrotar os Esqueletos você vasculha os escombros e encontra algo!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Seus homens avistam uma boia de navegação, confirmando que você está no rumo " "certo." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Seus homens avistam uma boia de navegação, confirmando que você está no rumo " "certo e aumentando a moral deles." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "A bebida no oásis é refrescante, mas não oferece mais nenhum benefício. O " "oásis pode ajudar novamente se você travar uma batalha primeiro." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Ao beber no oásis, suas tropas restauram a força e elevam seus ânimos. Hoje " "você pode viajar um pouco mais." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "A bebida na nascente é refrescante, mas não oferece mais benefícios. A " "nascente pode ajudar novamente se você voltar depois de uma batalha." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Ao beber desta nascente que flui água, suas tropas restauram as forças e " "elevam seus ânimos. Hoje você pode viajar um pouco mais." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Não ajuda rezar duas vezes antes de uma batalha. Volte depois de ter lutado." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Uma visita e uma oração no templo elevam a moral de suas tropas." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Um velho Cavaleiro aparece nos degraus do gazebo. \"Sinto muito, meu " "suserano, ensinei-lhe tudo o que pude.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Um velho Cavaleiro aparece nos degraus do gazebo. \"Meu suserano, eu lhe " "ensinarei tudo o que sei para auxiliá-lo em suas viagens.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Você tirou um sobrevivente de um naufrágio de uma morte certa em um oceano " "imperdoável. Grato, ele diz: \"Eu lhe daria um artefato como recompensa, mas " "vocês estão todos cheios.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Você tirou um sobrevivente de um naufrágio de uma morte certa em um oceano " "imperdoável. Agradecido, ele o recompensa por seu ato de bondade, dando-lhe " "o artefato %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "Um duende lhe oferece o artefato %{art} pelo pequeno preço de %{gold} de " "Ouro." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Um duende lhe oferece o artefato %{art} pelo pequeno preço de %{gold} de " "Ouro e %{count} de %{res}." msgid "Do you wish to buy this artifact?" msgstr "Você deseja comprar este artefato?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Você tenta pagar o duende, mas percebe que não tem dinheiro para isso. O " "duende bate o pé no chão e o ignora." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Insultado por sua recusa de sua generosa oferta, o duende bate o pé no chão " "e o ignora." msgid "You've found the artifact: " msgstr "Você encontrou o artefato: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Você encontrou a humilde morada de um ermitão debilitado. O ermitão lhe diz " "que está disposto a dar o artefato %{art} à primeira pessoa sábia que ele " "encontrar." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Você se deparou com os aposentos espartanos de um soldado aposentado. O " "soldado lhe diz que está disposto a dar o artefato %{art} para o primeiro " "verdadeiro líder que encontrar." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Você encontrou uma pessoa estranha com um chapéu e uma coruja em cima dele. " "Ele lhe diz que está disposto a dar o artefato %{art} se você tiver %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Você se depara com um artefato antigo. Ao alcançá-lo, um grupo de Bandidos " "saltou dos arbustos para guardar seu saque roubado." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Através de uma clareira, você observa um artefato antigo. Infelizmente, ele " "é guardado de perto por uma unidade %{monster}. Você deseja lutar contra a " "unidade %{monster} pelo artefato?" msgid "Victorious, you take your prize, the %{art}." msgstr "Vitorioso, você leva seu prêmio, %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "A discrição é a melhor parte da coragem, e você decide evitar esta luta por " "hoje." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Depois de passar horas tentando tirar o baú de fora do mar, você o abre e " "encontra %{gold} peças de ouro." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Depois de passar horas tentando tirar o baú do mar, você o abre e encontra " "%{gold} de ouro e o artefato %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Depois de passar horas tentando tirar o baú do mar, você o abre, apenas para " "encontrá-lo vazio." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Depois de vasculhar a área, você encontra um tesouro escondido. Você pode " "levar o ouro ou distribuí-lo entre os camponeses em troca de experiência. " "Você deseja ficar com o ouro?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Depois de vasculhar a área, você encontra um baú escondido, contendo %{gold} " "peças de ouro." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Depois de vasculhar a área, você encontra um baú escondido, contendo o " "artefato ancestral %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Você tropeça em uma lâmpada amassada e manchada alojada nas profundezas da " "terra. Você deseja esfregar a lâmpada?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Você tomou o controle da loja Alquimista local. Ela lhe fornecerá %{count} " "de Mercúrio por dia." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Você assumiu o controle de uma serraria. Ela lhe fornecerá %{count} de " "madeira por dia." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Você assumiu o controle de uma mina de minério. Ela lhe fornecerá %{count} " "de minério por dia." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Você assumiu o controle de uma mina de enxofre. Ela lhe fornecerá %{count} " "de enxofre por dia." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Você assumiu o controle de uma mina de cristal. Ela lhe fornecerá %{count} " "de cristal por dia." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Você assumiu o controle de uma mina de gema. Ela lhe fornecerá %{count} de " "gema por dia." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Você assumiu o controle de uma mina de ouro. Ela lhe fornecerá %{count} de " "ouro por dia." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "O farol está agora sob seu controle, e todos os seus navios irão agora se " "movimentar mais a cada dia." msgid "You gain control of a %{name}." msgstr "Você ganha o controle de %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Você se depara com uma mina de ouro abandonada. A mina parece estar " "assombrada. Você deseja entrar?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Você vence os Fantasmas e é capaz de restaurar a mina para a produção." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Um grupo de %{monster} com um desejo de maior glória deseja juntar-se a " "você. Você aceita?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Ao se aproximar da moradia, você percebe que não há ninguém." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Você procura nas ruínas, mas as Medusas que moravam aqui já não existem " "mais. Talvez haja mais na próxima semana." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Você encontrou algumas Medusas vivendo nas ruínas. Elas estão dispostas a se " "alistar em seu exército por um preço. Você quer recrutar as Medusas?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Você encontrou uma Cidade Ãrvore das Fadas. Infelizmente, nenhuma das Fadas " "que lá vivem deseja se alistar em um exército. Talvez na próxima semana." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Alguns das Fadas que vivem na cidade árvore estão dispostas a se alistar em " "seu exército por um preço. Você quer recrutar as Fadas?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Uma carroça colorida de Bandidos está vazia aqui. Talvez mais Bandidos " "estarão aqui mais tarde." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Sons distantes de música e risos atraem você para uma carroça colorida que " "abriga Bandidos. Você deseja que alguns Bandidos se alistem ao seu exército?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Um grupo de tendas precárias, que se espalham pelo vento arenoso, o atrai. " "As tendas estão desocupadas. Talvez mais Nômades estarão aqui mais tarde." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Um grupo de tendas precárias, que se espalham pelo vento arenoso, o atrai. " "Você deseja que alguns Nômades se juntem a você durante suas viagens?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "O poço de lama borbulha por um minuto e depois fica parado." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Ao se aproximar do poço borbulhante de lama, as criaturas começam a sair e " "se posicionar em torno dele. Em uníssono, eles dizem: \"A Mãe Terra gostaria " "de oferecer a você algumas de suas tropas. Você quer recrutar Elementais da " "Terra?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" "Você entra na estrutura de pilares de pedra branca, e não encontra nada." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Os pilares de pedra branca sustentam um telhado que se eleva até o céu. Ao " "entrar na estrutura, o vento morto do lado de fora dá lugar a uma rajada " "giratória que quase o empurra de volta para fora. A corrente de ar se " "materializa em uma forma pouco visível. A criatura pergunta, no que só pode " "ser descrito como um sussurro alto: \"Por que você veio? Você está aqui para " "convocar as forças do ar?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "" "Nenhum Elemental do Fogo se aproxima de você a partir da piscina de lava." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Sob uma estrutura que serve para manter o calor, os Elementais do Fogo se " "movimentam em uma piscina de lava derretida. Um grupo deles se aproxima de " "você e oferece seus serviços. Você gostaria de recrutar os Elementais do " "Fogo?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Uma face se forma na água por um momento, e depois desaparece." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Estruturas cristalinas projetam sombras sobre uma pequena piscina refletiva " "de água. Você espreita dentro da piscina, e um rosto que não é de seus " "companheiros olhar de volta. Ele pergunta: \"Você gostaria de invocar os " "poderes da água?\"" msgid "This burial site is deathly still." msgstr "Este local do sepultamento ainda é mortal." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Espíritos inquietos de guerreiros mortos há muito tempo em busca de seu " "lugar de descanso final se oferecem para juntar-se a vocês na esperança de " "encontrar a paz. Você deseja recrutar fantasmas?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "A Cidade dos Mortos está vazia de vida, e vazia de mortos-vivos também. " "Talvez alguns mortos-vivos se mudem na próxima semana." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Alguns Liches que vivem aqui estão dispostos a se alistar em seu exército " "por um preço. Você quer recrutar Liches?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Você encontrou as ruínas de uma cidade antiga, agora habitada apenas por " "mortos-vivos. Você vai fazer uma busca?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Alguns dos Liches sobreviventes estão impressionados com sua vitória sobre " "seus companheiros e se oferecem para se juntar a você por um preço. Você " "quer recrutar os Liches?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Você encontrou uma dessas pontes que os Trolls gostam tanto de viver " "debaixo, mas não há nenhum aqui. Talvez haja alguns na próxima semana." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Alguns Trolls que vivem debaixo de uma ponte estão dispostos a se alistar em " "seu exército, mas por um preço. Você quer recrutar os Trolls?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "Os Trolls que vivem debaixo da ponte o desafiam. Você irá combatê-los?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Alguns Trolls permanecem, assustados sob a ponte. Eles se aproximam de você " "e se oferecem para unir suas forças como mercenários. Você quer recrutar " "alguns Trolls?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "A Cidade Dragão não tem Dragões dispostos a se juntar a você esta semana. " "Talvez um Dragão esteja disponível na próxima semana." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "A Cidade Dragão está disposta a oferecer alguns Dragões para seu exército " "por um preço. Você deseja recrutar Dragões?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Você está diante da Cidade Dragão, um lugar fora dos limites para os meros " "humanos. Você deseja violar esta regra e desafiar os Dragões para uma luta?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Tendo derrotado os campeões dos Dragões, os líderes da cidade concordam em " "fornecer alguns Dragões ao seu exército por um preço. Você deseja recrutar " "Dragões?" msgid "From the observation tower, you are able to see distant lands." msgstr "Da torre de observação, é possível ver terras distantes." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "A fonte só recarrega uma vez por semana, e alguém já esteve aqui esta semana." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Ao beber da fonte seus pontos normais de mana se duplicam, mas você já está " "nesse nível." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Ao beber da fonte, o seu sangue se enche de magia! Você dobra sua reserva " "normal mana." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Ao reconhecê-lo, o criado se recusa a admiti-lo. \"O mestre\", diz ele, " "\"não verá o mesmo aluno duas vezes.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "O criado admite que você veja o mestre da casa. Ele o treina nas quatro " "habilidades que um herói deve conhecer." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "O criado abre a porta e o olha de cima a baixo. \"Você não é nem famoso nem " "diplomático o suficiente para ser admitido para ver meu mestre\", ele " "respira. \"Volte quando você se achar digno.\"" msgid " and " msgstr " e " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Todas as unidades %{monsters} que você tem em seu exército foram treinadas " "pelos mestres de batalha do forte. Seu exército agora contém %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Uma aliança incomum de Ogros, Orcs e Anões se oferece para treinar " "(melhorar) quaisquer tropas trazidas para eles. Infelizmente, você não tem " "nenhuma com você." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Todas as suas unidades %{monsters} foram melhoradas para %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Um ferreiro que trabalha na fundição se oferece para converter todas as " "armas de Piqueiros e Espadachins de ferro para aço. Ele também diz que " "conhece um processo que converterá os Golems de Ferro em Golems de Aço. " "Infelizmente, você não tem nenhuma dessas tropas em seu exército, então ele " "não pode ajudá-lo." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "O capitão olha para você com surpresa e diz:\n" "\"Você já tem todos os mapas que eu conheço. Deixe-me pescar em paz agora.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Um capitão aposentado que vive nesta plataforma de pesca reformada se " "oferece para vender-lhe mapas do mar que ele fez em seus tempos de juventude " "por 1.000 pelas de ouro. Você deseja comprar os mapas?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "O capitão suspira. \"Você não tem dinheiro suficiente, né? Você não pode " "esperar que eu dê meus mapas de graça!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Você se depara com um obelisco feito de um tipo de pedra que você nunca viu " "antes. Olhando intensamente para ele, a superfície lisa muda repentinamente " "para uma inscrição. A inscrição é um pedaço de um mapa antigo perdido. " "Rapidamente você copia o pedaço e a inscrição desaparece tão abruptamente " "quanto apareceu." msgid "You have already been to this obelisk." msgstr "Você já esteve neste obelisco." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Ao se aproximar, a árvore abre seus olhos em deleite. \"É bom ver você, meu " "aluno.\" Espero que meus ensinamentos o tenham ajudado.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Ao se aproximar, a árvore abre seus olhos em deleite. \"Ahh, um aventureiro! " "Permita-me ensinar-lhe um pouco do que aprendi ao longo dos tempos.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Ao se aproximar, a árvore abre seus olhos em deleite." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ahh, um aventureiro! Terei prazer em ensinar um pouco do que aprendi ao " "longo dos tempos por meros %{count} de %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Simplesmente enterrar o que eu peço em torno de minhas raízes.)" msgid "Tears brim in the eyes of the tree." msgstr "As lágrimas brotam nos olhos da árvore." msgid "\"I need %{count} %{res}.\"" msgstr "\"Eu preciso de %{count} de %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "ele sussurra. (sniff) \"Bem, volte quando puder me pagar.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "No meio das árvores, está um vidente cego. Após explicar a intenção de sua " "viagem, o vidente ativa sua bola de cristal, permitindo que você veja os " "pontos fortes e fracos de seus oponentes." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "A entrada da caverna é escura, e um cheiro fétido e sulfuroso sai da entrada " "da caverna. Deseja entrar?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Exceto por evidências de uma terrível batalha, a caverna está vazia." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Você encontra um Demônio poderoso e grotesco na caverna. \"Hoje, você lutará " "e certamente morrerá. Mas eu lhe darei uma escolha de mortes. Você pode " "lutar comigo, ou pode lutar com meus servos. Você prefere lutar contra meus " "servos?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "O Demônio grita seu desafio e ataca! Após uma batalha curta e desesperada, " "você mata o monstro e recebe %{exp} pontos de experiência." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "O Demônio grita seu desafio e ataca! Depois de uma batalha curta e " "desesperada, você mata o monstro e recebe %{exp} de pontos de experiência e " "%{count} de ouro." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "O Demônio grita seu desafio e ataca! Depois de uma batalha curta e " "desesperada, você mata o monstro e encontra o artefato %{art} no fundo da " "caverna." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Vendo que você não tem %{count} de ouro, o demônio te corta com suas garras, " "e a última coisa que você vê é uma névoa vermelha." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "O Demônio salta sobre você e coloca suas garras na sua garganta antes mesmo " "que você possa desembainhar sua espada. \"Sua vida é minha\", diz ele. \"Eu " "a venderei de volta a você por %{count} de ouro.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Ao derrotar os criados do demônio, você encontra um esconderijo escondido " "com %{count} de ouro." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Ao entrar na Torre dos Alquimistas, um homem manco e grisalho com um manto " "marrom vem em sua direção." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Ele verifica sua bolsa, e vê que você tem 1 item amaldiçoado." msgstr[1] "" "Ele verifica sua bolsa, e vê que você tem %{count} itens amaldiçoados." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "Por %{gold} de ouro, o alquimista removerá a maldição para você. Deseja paga?" msgstr[1] "" "Por %{gold} de ouro, o alquimista removerá as maldições para você. Deseja " "paga?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Depois que você consente em pagar a quantidade de ouro solicitada, o " "alquimista pega o artefato amaldiçoado e o joga em seu caldeirão mágico." msgstr[1] "" "Depois que você consente em pagar a quantidade de ouro solicitada, o " "alquimista pega todos os artefatos amaldiçoados e os joga em seu caldeirão " "mágico." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Você ouve uma voz por trás da porta trancada: \"Você não tem ouro suficiente " "para pagar pelos meus serviços.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Você ouve uma voz do alto da torre: \"Vá embora! Eu não posso ajudá-lo!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "O cavalariço fala com você: \"Esse é um cavalo de boa aparência que você " "tem. Mas receio que os cavalos que a sua cavalaria está montando sejam de " "baixa criação. Temos muitos cavalos de guerra treinados que ajudariam muito " "seus cavaleiros. Eu insisto que você levá-los." msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Ao se aproximar dos estábulos, aparece o cavalariço, conduzindo um belo " "cavalo de guerra. \"Este corcel o ajudará a acelerar suas viagens. " "Infelizmente, ele vai ficar cansado em uma semana. Você também deve me " "deixar fornecer cavalos melhores a seus soldados montados, seus cavalos " "parecem frágeis e fracos.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "O cavalariço se aproxima de você e fala: \"Você já tem um bom cavalo, e não " "tem nenhuma cavalaria inexperiente que possa fazer uso de nossos cavalos de " "guerra treinados.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Ao se aproximar dos estábulos, aparece o cavalariço, conduzindo um belo " "cavalo de guerra. \"Este corcel o ajudará a acelerar suas viagens. " "Infelizmente, sua resistência vai diminuir após muitas cavalgadas, e você " "deve voltar para uma nova montaria em uma semana. Também temos muitos " "cavalos de guerra excelentes que poderiam beneficiar os soldados montados, " "mas você não tem nenhum que possamos ajudar.\"" msgid "The Arena guards turn you away." msgstr "Os guardas da Arena o afastam." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Você faz sua tripulação tampar seus ouvidos com cera antes que o canto das " "sirenas tenha qualquer chance de atraí-los para uma sepultura aquática." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Enquanto as sirenas cantam seu canto sinistro, seu pequeno e determinado " "exército consegue superar o desejo de mergulhar de cabeça no mar." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Das sirenes empoleiradas nas rochas emana um canto sinistro de lamento. " "Muitos de seus tripulantes caem sob seu feitiço e mergulham na água onde se " "afogam. Agora você está mais sábio pela visita, e ganha %{exp} de " "experiência." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Em uma deslumbrante exibição de ousadia, você invade a cadeia local e " "liberta o herói preso ali, que, em troca, promete lealdade à sua causa." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Você já tem %{count} heróis, e lamentavelmente deve deixar o prisioneiro " "nesta prisão para definhar em agonia por dias incalculáveis." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Você entra numa frágil cabana e fala com o mágico que mora lá. Ele lhe fala " "de lugares próximos e distantes que podem lhe ajudar em suas viagens." msgid "This eye seems to be intently studying its surroundings." msgstr "Este olho parece estar estudando intensamente seus arredores." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" "Você se depara com uma Esfinge gigante. A Esfinge permanece estranhamente " "silenciosa." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Tenho um enigma para você,\" diz a Esfinge. \"Responda corretamente, e " "você será recompensado. Responda incorretamente, e você será devorado. Você " "aceita o desafio?\"" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "A Esfinge lhe pergunta o seguinte enigma:\n" "\n" "'" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" "'\n" "\n" "Sua resposta?" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Você errou,\" diz a Esfinge, sorrindo. A Esfinge te golpeia com uma pata, " "derrubando você no chão. Um outro golpe te faz você ver tudo escuro, e você " "perde os sentidos." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Parecendo um pouco decepcionada, a Esfinge suspira. \"Você respondeu ao meu " "enigma, então aqui está sua recompensa. Agora saia.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Uma barreira mágica se ergue diante de você, bloqueando seu caminho. Nas " "runas do arco está escrito:\n" "\"Fale a chave e você poderá passar.\"\n" "Enquanto você fala a palavra mágica, a barreira luminosa se dissolve em nada." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Uma barreira mágica se ergue diante de você, bloqueando seu caminho. Nas " "runas do arco está escrito:\n" "\"Fale a chave e você pode passar.\"\n" "Você fala, e nada acontece." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Você entra na tenda e vê uma velha mulher olhando para uma joia mágica. Ela " "olha para cima e diz,\n" "\"Em minhas viagens, aprendi muito no caminho da magia arcana. Um grande " "oráculo me ensinou sua habilidade. Eu tenho a resposta que você procura.\"" msgid "No spell book is present." msgstr "Nenhum grimório está presente." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Este feitiço custa %{mana} de mana. Você não tem de mana, então não pode " "lançá-lo." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Este feitiço custa %{mana} de mana. Você só tem %{point} de mana, então não " "pode lançá-lo." msgid "The spell was not found." msgstr "O feitiço não foi encontrado." msgid "Only heroes can cast this spell." msgstr "Somente os heróis podem lançar este feitiço." msgid "This hero is not able to cast adventure spells." msgstr "Esse herói não é capaz de lançar feitiços de aventura." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Seu herói está muito cansado para lançar este feitiço hoje. Tente novamente " "amanhã." msgid "This spell cannot be cast on a boat." msgstr "Esse feitiço não pode ser lançado em um barco." msgid "This spell can only be cast near an ocean." msgstr "Esse feitiço só pode ser lançado perto de um oceano." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Não há barcos disponíveis e nenhum oceano adjacente ao herói onde esse " "feitiço funcionará." msgid "There are no boats available for this spell." msgstr "Não há barcos disponíveis para esse feitiço." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "Não há nenhum oceano adjacente ao herói onde esse feitiço funcione." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Você não possui nenhuma cidade ou castelo que não esteja atualmente ocupado " "por um herói. Esse feitiço não terá efeito." msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Esse herói já está em uma cidade, portanto, esse feitiço não terá efeito." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "A cidade mais próxima é %{town}.\n" "\n" "Essa cidade é ocupada por seu herói %{hero}." msgid "This spell is already in effect." msgstr "Esse feitiço já está em vigor." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Nenhum oponente possui ou pode ter mais nenhum herói sob seu comando. Lançar " "este feitiço não terá efeito." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Nenhum oponente possui um herói sob seu comando no momento. Lançar este " "feitiço não terá efeito." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Você deve estar dentro de %{count} espaços de um monstro para que o feitiço " "Visões funcione." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Você deve estar de pé na entrada de uma mina (serrarias e laboratórios " "alquímicos não contam) para lançar este feitiço." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Você deve primeiro derrotar os fantasmas que guardam a mina para lançar este " "feitiço." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Já existem pelo menos tantos elementais guardando a mina quanto este herói " "pode gerar. Lançar este feitiço não terá efeito." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name} da Classe: %{race} (Nível: %{level})" msgid "Random hero (Level %{level})" msgstr "Herói aleatório (Nível %{level})" msgid "Random %{race} hero (Level %{level})" msgstr "Herói aleatório %{race} (Nível %{level})" msgid "Hero race:" msgstr "Raça do herói:" msgid "Are you sure you want to dismiss this Hero?" msgstr "Você tem certeza de que deseja dispensar este Herói?" msgid "Set custom Experience value. Current value is default." msgstr "Definir valor personalizado de Experiência. O valor atual é o padrão." msgid "Change Experience value. Right-click to reset to default value." msgstr "" "Alterar o valor da Experiência. Clique com o botão direito para redefinir " "para o valor padrão." msgid "View Experience Info" msgstr "Ver Informações Sobre a Experiência" msgid "Set custom Spell Points value. Current value is default." msgstr "Definir valor personalizado de Mana. O valor atual é o padrão." msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" "Alterar o valor da Mana. Clique com o botão direito para redefinir para o " "valor padrão." msgid "Set Spell Points value" msgstr "Definir o valor da Mana" msgid "View Spell Points Info" msgstr "Ver Informações Sobre a Mana" msgid "Set patrol radius in tiles" msgstr "Definir raio de patrulha em ladrilhos" msgid "Enter hero's name" msgstr "Insira o nome do herói" msgid "Click to change race." msgstr "Clique para alterar a raça." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Formação de combate \"Espalhada\" espalha seus exércitos a partir do topo " "ao fundo do campo de batalha, com pelo menos um espaço vazio entre cada " "exército." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "A formação de combate 'Fechada' agrupa o exército do herói no centro do seu " "lado do campo de batalha." msgid "Exit Hero Screen" msgstr "Sair da Tela do Herói" msgid "You cannot dismiss a hero in a castle" msgstr "Não é possível dispensar um herói em um castelo" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Não é permitido dispensar %{name} Classe: %{race} pelo cenário" msgid "Dismiss %{name} the %{race}" msgstr "Dispensar %{name} Classe: %{race}" msgid "Show previous hero" msgstr "Mostrar herói anterior" msgid "Show next hero" msgstr "Mostrar próximo herói" msgid "Set army combat formation to 'Spread'" msgstr "Definir formação de combate do exército para 'Aberta'" msgid "Set army combat formation to 'Grouped'" msgstr "Definir formação de combate do exército para 'Fechada'" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" "Definir Artefatos do herói. Clique com o botão direito para redefinir o " "Artefato." msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" "Definir Habilidades Secundárias do herói. Clique com o botão direito para " "redefinir a habilidade." msgid "Set hero's Army. Right-click to reset unit." msgstr "" "Definir Exército do herói. Clique com o botão direito para redefinir a " "unidade." msgid "Set hero's portrait. Right-click to reset to default." msgstr "" "Definir retrato do herói. Clique com o botão direito para redefinir para o " "padrão." msgid "Click to change hero's name. Right-click to reset to default." msgstr "" "Clique para alterar o nome do herói. Clique com o botão direito para " "redefinir para o padrão." msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" "O herói está em modo de patrulha em um raio de %{tiles} ladrilhos. Clique " "para desativá-lo." msgid "Click to enable hero's patrol mode." msgstr "Clique para ativar o modo de patrulha do herói." msgid "Blood Morale" msgstr "Moral Sangrenta" msgid "%{morale} Morale" msgstr "Moral %{morale}" msgid "%{luck} Luck" msgstr "Sorte %{luck}" msgid "Current Luck Modifiers:" msgstr "Modificadores Atuais de Sorte:" msgid "Current Morale Modifiers:" msgstr "Modificadores Atuais de Moral:" msgid "Entire army is undead, so morale does not apply." msgstr "Todo o exército é morto-vivo, portanto, a moral não se aplica." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Experiência atual: %{exp1}.\n" " Próximo nível em: %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Nível %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} atualmente tem %{point} de mana de um máximo de %{max}. O número " "máximo de mana é 10 vezes o Conhecimento do herói. Ocasionalmente, é " "possível que o herói tenha mais do que seus pontos de mana máximos por meio " "de eventos especiais." msgid "%{name1} meets %{name2}" msgstr "%{name1} se encontra com %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Os heróis inimigos são agora totalmente identificáveis." msgid "Identify Hero" msgstr "Identificar Herói" msgid "Select town to port to." msgstr "Selecione a cidade de destino." msgid "Town Portal" msgstr "Portal da Cidade" msgid "The creatures are willing to join us!" msgstr "As criaturas estão dispostas a se juntar a nós!" msgid "All the creatures will join us..." msgstr "Todas as criaturas se juntarão a nós..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "A criatura se juntará a nós..." msgstr[1] "%{count} das criaturas se juntarão a nós..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" " por uma taxa de %{gold} de ouro." msgid "These weak creatures will surely flee before us." msgstr "Estas criaturas fracas certamente fugirão diante de nós." msgid "I fear these creatures are in the mood for a fight." msgstr "Temo que estas criaturas estejam com disposição para uma luta." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "A Habilidade de Ataque do herói é um bônus adicionado à Habilidade de Ataque " "de cada unidade." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "A Habilidade de Defesa do herói é um bônus adicionado à Habilidade de Defesa " "de cada unidade." msgid "The hero's spell power determines the duration or power of a spell." msgstr "O Poder Mágico do herói determina a duração ou poder de um feitiço." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "O Conhecimento do herói determina quantos pontos de mana o herói pode ter. " "Sob circunstâncias normais, um herói está limitado a 10 pontos de mana por " "nível de Conhecimento." msgid "Current Modifiers:" msgstr "Modificadores Atuais:" msgid "skill|Basic" msgstr "(Básico)" msgid "skill|Advanced" msgstr "(Avançado)" msgid "skill|Expert" msgstr "(Experiente)" msgid "Pathfinding" msgstr "Reconhecer" msgid "Archery" msgstr "Arqueria" msgid "Logistics" msgstr "Logística" msgid "Scouting" msgstr "Desbravar" msgid "Diplomacy" msgstr "Diplomacia" msgid "Navigation" msgstr "Navegação" msgid "Leadership" msgstr "Liderança" msgid "Wisdom" msgstr "Sabedoria" msgid "Mysticism" msgstr "Misticismo" msgid "Ballistics" msgstr "Balística" msgid "Eagle Eye" msgstr "Olho de Ãguia" msgid "Necromancy" msgstr "Necromancia" msgid "Estates" msgstr "Riqueza" msgid "Advanced Archery" msgstr "Arqueria Nv. Avançado" msgid "Advanced Pathfinding" msgstr "Reconhecimento Nv. Avançado" msgid "Basic Archery" msgstr "Arqueria Nv. Básico" msgid "Basic Pathfinding" msgstr "Reconhecimento Nv. Básico" msgid "Expert Pathfinding" msgstr "Reconhecimento Nv. Experiente" msgid "Advanced Logistics" msgstr "Logística Nv. Avançado" msgid "Basic Logistics" msgstr "Logística Nv. Básico" msgid "Basic Scouting" msgstr "Desbravamento Nv. Básico" msgid "Expert Archery" msgstr "Arqueria Nv. Experiente" msgid "Expert Logistics" msgstr "Logística Nv. Experiente" msgid "Advanced Diplomacy" msgstr "Diplomacia Nv. Avançado" msgid "Advanced Scouting" msgstr "Desbravamento Nv. Avançado" msgid "Basic Diplomacy" msgstr "Diplomacia Nv. Básico" msgid "Expert Diplomacy" msgstr "Diplomacia Nv. Experiente" msgid "Expert Scouting" msgstr "Desbravamento Nv. Experiente" msgid "Advanced Leadership" msgstr "Liderança Nv. Avançado" msgid "Advanced Navigation" msgstr "Navegação Nv. Avançado" msgid "Basic Leadership" msgstr "Liderança Nv. Básico" msgid "Basic Navigation" msgstr "Navegação Nv. Básico" msgid "Expert Navigation" msgstr "Navegação Experiente" msgid "Advanced Wisdom" msgstr "Sabedoria Nv. Avançado" msgid "Basic Mysticism" msgstr "Misticismo Nv. Básico" msgid "Basic Wisdom" msgstr "Sabedoria Nv. Básico" msgid "Expert Leadership" msgstr "Liderança Nv. Experiente" msgid "Expert Wisdom" msgstr "Sabedoria Nv. Experiente" msgid "Advanced Luck" msgstr "Sorte Nv. Avançado" msgid "Advanced Mysticism" msgstr "Misticismo Nv. Avançado" msgid "Basic Luck" msgstr "Sorte Nv. Básico" msgid "Expert Luck" msgstr "Sorte Nv. Experiente" msgid "Expert Mysticism" msgstr "Misticismo Nv. Experiente" msgid "Advanced Ballistics" msgstr "Balística Nv. Avançado" msgid "Advanced Eagle Eye" msgstr "Olho de Ãguia Nv. Avançado" msgid "Basic Ballistics" msgstr "Balística Nv. Básico" msgid "Basic Eagle Eye" msgstr "Olho de Ãguia Nv. Básico" msgid "Expert Ballistics" msgstr "Balística Nv. Experiente" msgid "Advanced Necromancy" msgstr "Necromancia Nv. Avançado" msgid "Basic Estates" msgstr "Riqueza Nv. Básico" msgid "Basic Necromancy" msgstr "Necromancia Nv. Básico" msgid "Expert Eagle Eye" msgstr "Olho de Ãguia Nv. Experiente" msgid "Expert Necromancy" msgstr "Necromancia Nv. Experiente" msgid "Advanced Estates" msgstr "Riqueza Nv. Avançado" msgid "Expert Estates" msgstr "Riqueza Nv. Experiente" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} reduz a penalidade de movimento em terrenos acidentados em %{count} " "por cento." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} elimina a penalidade de movimento por terreno acidentado." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} aumenta o dano causado pelas criaturas de ataque à distância do " "herói em %{count} por cento e elimina a penalidade de %{penalty} por cento " "ao atirar através de obstáculos (por exemplo, muralhas do castelo)." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" "%{skill} aumenta os pontos de movimento do herói em %{count} por cento." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} aumenta a área visível do herói em um quadrado." msgstr[1] "%{skill} aumenta a área visível do herói em %{count} quadrados." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} permite ao herói negociar com monstros que são mais fracos do que " "seu exército e reduz o custo de rendição." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Aproximadamente %{count} por cento das criaturas podem se oferecer para se " "juntar ao herói." msgid "All of the creatures may offer to join the hero." msgstr "Todas as criaturas podem se oferecer para se juntar ao herói." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "O custo da rendição é reduzido para %{percent} por cento do custo total das " "tropas no exército." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "%{skill} aumenta os pontos de movimento do herói sobre a água em %{count} " "por cento." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} aumenta a moral das tropas do herói em %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} permite ao herói aprender feitiços de terceiro nível." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} permite ao herói aprender feitiços de quarto nível." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} permite ao herói aprender feitiços de quinto nível." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} regenera um ponto de mana adicional por dia para o herói." msgstr[1] "" "%{skill} regenera %{count} pontos de mana adicionais por dia para o herói." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} aumenta a sorte do herói em %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} dá aos tiros da catapulta do herói uma maior chance de acertar e " "causar danos às muralhas do castelo." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} dá à catapulta do herói um tiro extra, e cada tiro tem uma maior " "chance de acertar e causar danos às muralhas do castelo." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} dá à catapulta do herói um tiro extra, e cada tiro destrói " "automaticamente qualquer parede, exceto uma parede fortificada em um castelo " "de Cavaleiro." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} dá ao herói uma chance de %{count} por cento de aprender qualquer " "feitiço de primeiro ou segundo nível que tenha sido lançado por um inimigo " "durante o combate." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} dá ao herói uma chance de %{count} por cento de aprender qualquer " "feitiço de terceiro nível (ou abaixo) que tenha sido lançado por um inimigo " "durante o combate." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} dá ao herói uma chance de %{count} por cento de aprender qualquer " "feitiço de quarto nível (ou abaixo) que tenha sido lançado por um inimigo " "durante o combate." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} permite que %{count} por cento das criaturas mortas em combate " "sejam ressuscitadas como Esqueletos." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "O herói produz %{count} peças de ouro por dia como receita de impostos de " "propriedades." msgid "Blue" msgstr "Azul" msgid "Green" msgstr "Verde" msgid "Red" msgstr "Vermelho" msgid "Yellow" msgstr "Amarelo" msgid "Orange" msgstr "Laranja" msgid "Purple" msgstr "Roxo" msgid "barrier|Aqua" msgstr "Turquesa" msgid "barrier|Blue" msgstr "Azul" msgid "barrier|Brown" msgstr "Marrom" msgid "barrier|Gold" msgstr "Dourado" msgid "barrier|Green" msgstr "Verde" msgid "barrier|Orange" msgstr "Laranja" msgid "barrier|Purple" msgstr "Roxo" msgid "barrier|Red" msgstr "Vermelho" msgid "tent|Aqua" msgstr "Turquesa" msgid "tent|Blue" msgstr "Azul" msgid "tent|Brown" msgstr "Marrom" msgid "tent|Gold" msgstr "Dourado" msgid "tent|Green" msgstr "Verde" msgid "tent|Orange" msgstr "Laranja" msgid "tent|Purple" msgstr "Roxo" msgid "tent|Red" msgstr "Vermelho" msgid "Experience" msgstr "Experiência" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "A experiência permite que seus heróis ganhem níveis, aumentando suas " "habilidades primárias e secundárias." msgid "Hero/Stats" msgstr "Herói/Estatísticas" msgid "Skills" msgstr "Habilidades" msgid "Town/Castle" msgstr "Cidade/Castelo" msgid "Garrison" msgstr "Guarnição" msgid "Gold Per Day:" msgstr "Ouro por Dia:" msgid "View Heroes." msgstr "Ver Heróis." msgid "Towns/Castles" msgstr "Cidades/Castelos" msgid "View Towns and Castles." msgstr "Ver Cidades e Castelos." msgid "luck|Cursed" msgstr "Amaldiçoada" msgid "luck|Awful" msgstr "Péssima" msgid "luck|Bad" msgstr "Má" msgid "luck|Normal" msgstr "Neutra" msgid "luck|Good" msgstr "Boa" msgid "luck|Great" msgstr "Ótima" msgid "luck|Irish" msgstr "Máxima" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Sorte negativa às vezes afeta as unidades do herói em combate, fazendo com " "que seus ataques causem apenas metade do dano." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Sorte neutra significa que as unidades do herói nunca terão ataques de sorte " "ou azar no inimigo." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Sorte positiva às vezes permite que as unidades do herói obtenham ataques de " "sorte (dobro de força) em combate." msgid "morale|Treason" msgstr "Traição" msgid "morale|Awful" msgstr "Péssima" msgid "morale|Poor" msgstr "Ruim" msgid "morale|Normal" msgstr "Neutra" msgid "morale|Good" msgstr "Boa" msgid "morale|Great" msgstr "Ótima" msgid "morale|Blood!" msgstr "Sanguinária!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "Moral negativa pode fazer com que as unidades do herói congelem em combate." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Moral neutra significa que as unidades do herói nunca serão abençoadas com " "ataques extras ou ficarão paralisadas durante o combate." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "Moral positiva pode dar às unidades do herói ataques extras em combate." msgid "Knight" msgstr "Cavaleiro" msgid "Barbarian" msgstr "Bárbaro" msgid "Sorceress" msgstr "Feiticeira" msgid "Warlock" msgstr "Bruxo" msgid "Wizard" msgstr "Mago" msgid "Necromancer" msgstr "Necromante" msgid "Multi" msgstr "Multi" msgid "doubleLined|Knight" msgstr "Cavaleiro" msgid "doubleLined|Barbarian" msgstr "Bárbaro" msgid "doubleLined|Sorceress" msgstr "Feiticeira" msgid "doubleLined|Warlock" msgstr "Bruxo" msgid "doubleLined|Wizard" msgstr "Mago" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "Necromante" msgid "doubleLinedRace|Multi" msgstr "Multi" msgid "doubleLinedRace|Random" msgstr "Aleatória" msgid "speed|Standing" msgstr "Fixa" msgid "speed|Crawling" msgstr "Arrastando" msgid "speed|Very Slow" msgstr "Muito Lenta" msgid "speed|Slow" msgstr "Lenta" msgid "speed|Average" msgstr "Média" msgid "speed|Fast" msgstr "Rápida" msgid "speed|Very Fast" msgstr "Muito Rápida" msgid "speed|Ultra Fast" msgstr "Super Rápida" msgid "speed|Blazing" msgstr "Ultra Rápida" msgid "speed|Instant" msgstr "Instantânea" msgid "Click this button to adjust the level of zoom." msgstr "Clique neste botão para ajustar o nível de zoom." msgid "Zoom" msgstr "Zoom" msgid "week|Squirrel" msgstr "Esquilo" msgid "week|Rabbit" msgstr "Coelho" msgid "week|Gopher" msgstr "Marmota" msgid "week|Badger" msgstr "Texugo" msgid "week|Rat" msgstr "Rato" msgid "week|Eagle" msgstr "Ãguia" msgid "week|Weasel" msgstr "Doninha" msgid "week|Raven" msgstr "Corvo" msgid "week|Mongoose" msgstr "Mangusto" msgid "week|Dog" msgstr "Cão" msgid "week|Aardvark" msgstr "Tamanduá" msgid "week|Lizard" msgstr "Lagarto" msgid "week|Tortoise" msgstr "Tartaruga" msgid "week|Hedgehog" msgstr "Porco Espinho" msgid "week|Condor" msgstr "Condor" msgid "week|Ant" msgstr "Formiga" msgid "week|Grasshopper" msgstr "Gafanhoto" msgid "week|Dragonfly" msgstr "Libélula" msgid "week|Spider" msgstr "Aranha" msgid "week|Butterfly" msgstr "Borboleta" msgid "week|Bumblebee" msgstr "Abelhão" msgid "week|Locust" msgstr "Cigarra" msgid "week|Earthworm" msgstr "Minhoca" msgid "week|Hornet" msgstr "Vespa" msgid "week|Beetle" msgstr "Besouro" msgid "week|PLAGUE" msgstr "PRAGA" msgid "week|Unnamed" msgstr "Sem nome" msgid "Desert" msgstr "Deserto" msgid "Snow" msgstr "Neve" msgid "Wasteland" msgstr "Ermo" msgid "Beach" msgstr "Praia" msgid "Lava" msgstr "Lava" msgid "Dirt" msgstr "Terra" msgid "Grass" msgstr "Grama" msgid "Ocean" msgstr "Oceano" msgid "maps|Small" msgstr "Pequeno" msgid "maps|Medium" msgstr "Médio" msgid "maps|Large" msgstr "Grande" msgid "maps|Extra Large" msgstr "Muito Grande" msgid "maps|Custom Size" msgstr "Personalizado" msgid "Ore Mine" msgstr "Mina de Minério" msgid "Sulfur Mine" msgstr "Mina de Enxofre" msgid "Crystal Mine" msgstr "Mina de Cristal" msgid "Gems Mine" msgstr "Mina de Gemas" msgid "Gold Mine" msgstr "Mina de Ouro" msgid "Mine" msgstr "Mina" msgid "Burma shave." msgstr "Fiscalização eletrônica." msgid "Next sign 50 miles." msgstr "Próxima placa: 50 milhas." msgid "See Rock City." msgstr "Visite Rock City." msgid "This space for rent." msgstr "Espaço para alugar." msgid "No object" msgstr "Nenhum objeto" msgid "Alchemist Lab" msgstr "Lab. Alquimista" msgid "Sign" msgstr "Placa" msgid "Buoy" msgstr "Boia" msgid "Skeleton" msgstr "Esqueleto" msgid "Daemon Cave" msgstr "Caverna do Demônio" msgid "Treasure Chest" msgstr "Baú do Tesouro" msgid "Faerie Ring" msgstr "Círculo das Fadas" msgid "Campfire" msgstr "Acampamento" msgid "Fountain" msgstr "Fonte" msgid "Gazebo" msgstr "Gazebo" msgid "Genie Lamp" msgstr "Gênio da Lâmpada" msgid "Archer's House" msgstr "Casa do Arqueiro" msgid "Goblin Hut" msgstr "Cabana Goblim" msgid "Dwarf Cottage" msgstr "Chalé dos Anões" msgid "Peasant Hut" msgstr "Cabana dos Camponeses" msgid "Stables" msgstr "Estábulos" msgid "Alchemist's Tower" msgstr "Torre dos Alquimistas" msgid "Event" msgstr "Evento" msgid "Dragon City" msgstr "Cidade Dragão" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Farol" msgstr[1] "Faróis" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Roda D'Ãgua" msgstr[1] "Rodas D'Ãgua" msgid "Monster" msgstr "Monstro" msgid "Obelisk" msgstr "Obelisco" msgid "Oasis" msgstr "Oásis" msgid "Resource" msgstr "Recurso" msgid "Sawmill" msgstr "Serraria" msgid "Oracle" msgstr "Oráculo" msgid "Shrine of the First Circle" msgstr "Santuário do Primeiro Ciclo" msgid "Shipwreck" msgstr "Naufrágio" msgid "Sea Chest" msgstr "Baú no Mar" msgid "Desert Tent" msgstr "Tenda do Deserto" msgid "Stone Liths" msgstr "Monólitos" msgid "Wagon Camp" msgstr "Caravana" msgid "Hut of the Magi" msgstr "Cabana dos Magos" msgid "Whirlpool" msgstr "Redemoinho" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Moinho" msgstr[1] "Moinhos" msgid "Mermaid" msgstr "Sereia" msgid "Boat" msgstr "Barco" msgid "Random Ultimate Artifact" msgstr "Artefato Definitivo Aleatório" msgid "Random Artifact" msgstr "Artefato Aleatório" msgid "Random Resource" msgstr "Recurso Aleatório" msgid "Random Monster" msgstr "Monstro Aleatório" msgid "Random Town" msgstr "Cidade Aleatória" msgid "Random Castle" msgstr "Castelo Aleatório" msgid "Eye of the Magi" msgstr "Olho dos Magos" msgid "Random Monster - weak" msgstr "Monstro Aleatório - Fraco" msgid "Random Monster - medium" msgstr "Monstro Aleatório - Médio" msgid "Random Monster - strong" msgstr "Monstro Aleatório - Forte" msgid "Random Monster - very strong" msgstr "Monstro Aleatório - Muito Forte" msgid "Hero" msgstr "Herói" msgid "Nothing Special" msgstr "Nada Especial" msgid "Mossy Rock" msgstr "Pedra Musgosa" msgid "Watch Tower" msgstr "Torre de Vigia" msgid "Tree House" msgstr "Casa da Ãrvore" msgid "Tree City" msgstr "Cidade da Ãrvore" msgid "Ruins" msgstr "Ruínas" msgid "Fort" msgstr "Forte" msgid "Abandoned Mine" msgstr "Mina Abandonada" msgid "Sirens" msgstr "Sirenas" msgid "Standing Stones" msgstr "Menires" msgid "Idol" msgstr "Ãdolo" msgid "Tree of Knowledge" msgstr "Ãrvore do Conhecimento" msgid "Witch Doctor's Hut" msgstr "Cabana do Curandeiro" msgid "Temple" msgstr "Templo" msgid "Hill Fort" msgstr "Forte da Colina" msgid "Halfling Hole" msgstr "Toca dos Pequeninos" msgid "Mercenary Camp" msgstr "Campo Mercenário" msgid "Shrine of the Second Circle" msgstr "Santuário do Segundo Ciclo" msgid "Shrine of the Third Circle" msgstr "Santuário do Terceiro Ciclo" msgid "City of the Dead" msgstr "Cidade da Morte" msgid "Sphinx" msgstr "Esfinge" msgid "Wagon" msgstr "Carroça" msgid "Tar Pit" msgstr "Poço de Piche" msgid "Artesian Spring" msgstr "Fonte Artesiana" msgid "Troll Bridge" msgstr "Ponte dos Trolls" msgid "Watering Hole" msgstr "Nascente de Ãgua" msgid "Witch's Hut" msgstr "Cabana da Bruxa" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Abrigo" msgid "Magellan's Maps" msgstr "Mapas de Magalhães" msgid "Flotsam" msgstr "Destroços" msgid "Derelict Ship" msgstr "Navio Abandonado" msgid "Shipwreck Survivor" msgstr "Náufrago" msgid "Bottle" msgstr "Garrafa" msgid "Magic Well" msgstr "Poço Mágico" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Jardim Mágico" msgstr[1] "Jardins Mágicos" msgid "Observation Tower" msgstr "Torre de Observação" msgid "Freeman's Foundry" msgstr "Fundição" msgid "Reefs" msgstr "Arrecifes" msgid "Volcano" msgstr "Vulcão" msgid "Flowers" msgstr "Flores" msgid "Rock" msgstr "Rocha" msgid "Water Lake" msgstr "Lago" msgid "Mandrake" msgstr "Mandrágora" msgid "Dead Tree" msgstr "Ãrvore Morta" msgid "Stump" msgstr "Tronco" msgid "Crater" msgstr "Cratera" msgid "Cactus" msgstr "Cacto" msgid "Mound" msgstr "Monte" msgid "Dune" msgstr "Duna" msgid "Lava Pool" msgstr "Piscina de Lava" msgid "Shrub" msgstr "Arbusto" msgid "Barrow Mounds" msgstr "Túmulos" msgid "Random Artifact - Treasure" msgstr "Artefato Aleatório - Tesouro" msgid "Random Artifact - Minor" msgstr "Artefato Aleatório - Menor" msgid "Random Artifact - Major" msgstr "Artefato Aleatório - Maior" msgid "Barrier" msgstr "Barreira" msgid "Traveller's Tent" msgstr "Tenda do Viajante" msgid "Jail" msgstr "Prisão" msgid "Fire Summoning Altar" msgstr "Altar do Fogo" msgid "Air Summoning Altar" msgstr "Altar do Ar" msgid "Earth Summoning Altar" msgstr "Altar da Terra" msgid "Water Summoning Altar" msgstr "Altar da Ãgua" msgid "Swampy Lake" msgstr "Lago Pantanoso" msgid "Frozen Lake" msgstr "Lago Congelado" msgid "randomRace|level 1 creatures" msgstr "criaturas de nível 1" msgid "randomRace|level 2 creatures" msgstr "criaturas de nível 2" msgid "randomRace|level 3 creatures" msgstr "criaturas de nível 3" msgid "randomRace|level 4 creatures" msgstr "criaturas de nível 4" msgid "randomRace|level 5 creatures" msgstr "criaturas de nível 5" msgid "randomRace|level 6 creatures" msgstr "criaturas de nível 6" msgid "Unknown Monsters" msgstr "Monstros Desconhecidos" msgid "Unknown Monster" msgstr "Monstro Desconhecido" msgid "Peasant" msgstr "Camponês" msgid "Peasants" msgstr "Camponeses" msgid "Archer" msgstr "Arqueira" msgid "Archers" msgstr "Arqueiras" msgid "Ranger" msgstr "Guardião" msgid "Rangers" msgstr "Guardiões" msgid "Pikeman" msgstr "Piqueiro" msgid "Pikemen" msgstr "Piqueiros" msgid "Veteran Pikeman" msgstr "Piqueiro Veterano" msgid "Veteran Pikemen" msgstr "Piqueiros Veteranos" msgid "Swordsman" msgstr "Espadachim" msgid "Swordsmen" msgstr "Espadachins" msgid "Master Swordsman" msgstr "Mestre Espadachim" msgid "Master Swordsmen" msgstr "Mestres Espadachim" msgid "Cavalries" msgstr "Cavalarias" msgid "Cavalry" msgstr "Cavalaria" msgid "Champion" msgstr "Campeão" msgid "Champions" msgstr "Campeões" msgid "Paladin" msgstr "Paladino" msgid "Paladins" msgstr "Paladinos" msgid "Crusader" msgstr "Cruzado" msgid "Crusaders" msgstr "Cruzados" msgid "Goblin" msgstr "Goblin" msgid "Goblins" msgstr "Goblins" msgid "Orc" msgstr "Orc" msgid "Orcs" msgstr "Orcs" msgid "Orc Chief" msgstr "Chefe Orc" msgid "Orc Chiefs" msgstr "Chefes Orcs" msgid "Wolf" msgstr "Lobo" msgid "Wolves" msgstr "Lobos" msgid "Ogre" msgstr "Ogro" msgid "Ogres" msgstr "Ogros" msgid "Ogre Lord" msgstr "Lorde Ogro" msgid "Ogre Lords" msgstr "Lordes Ogros" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Trolls" msgid "War Troll" msgstr "Troll de Guerra" msgid "War Trolls" msgstr "Trolls de Guerra" msgid "Cyclopes" msgstr "Ciclopes" msgid "Cyclops" msgstr "Ciclope" msgid "Sprite" msgstr "Fada" msgid "Sprites" msgstr "Fadas" msgid "Dwarf" msgstr "Anão" msgid "Dwarves" msgstr "Anões" msgid "Battle Dwarf" msgstr "Anão de Combate" msgid "Battle Dwarves" msgstr "Anões de Combate" msgid "Elf" msgstr "Elfo" msgid "Elves" msgstr "Elfos" msgid "Grand Elf" msgstr "Grande Elfo" msgid "Grand Elves" msgstr "Grandes Elfos" msgid "Druid" msgstr "Druida" msgid "Druids" msgstr "Druidas" msgid "Greater Druid" msgstr "Grande Druida" msgid "Greater Druids" msgstr "Grandes Druidas" msgid "Unicorn" msgstr "Unicórnio" msgid "Unicorns" msgstr "Unicórnios" msgid "Phoenix" msgstr "Fênix" msgid "Phoenixes" msgstr "Fênix" msgid "Centaur" msgstr "Centauro" msgid "Centaurs" msgstr "Centauros" msgid "Gargoyle" msgstr "Gárgula" msgid "Gargoyles" msgstr "Gárgulas" msgid "Griffin" msgstr "Grifo" msgid "Griffins" msgstr "Grifos" msgid "Minotaur" msgstr "Minotauro" msgid "Minotaurs" msgstr "Minotauros" msgid "Minotaur King" msgstr "Rei Minotauro" msgid "Minotaur Kings" msgstr "Reis Minotauros" msgid "Hydra" msgstr "Hidra" msgid "Hydras" msgstr "Hidras" msgid "Green Dragon" msgstr "Dragão Verde" msgid "Green Dragons" msgstr "Dragões Verdes" msgid "Red Dragon" msgstr "Dragão Vermelho" msgid "Red Dragons" msgstr "Dragões Vermelhos" msgid "Black Dragon" msgstr "Dragão Negro" msgid "Black Dragons" msgstr "Dragões Negros" msgid "Halfling" msgstr "Pequenino" msgid "Halflings" msgstr "Pequeninos" msgid "Boar" msgstr "Javali" msgid "Boars" msgstr "Javalis" msgid "Iron Golem" msgstr "Golem de Ferro" msgid "Iron Golems" msgstr "Golems de Ferro" msgid "Steel Golem" msgstr "Golem de Aço" msgid "Steel Golems" msgstr "Golems de Aço" msgid "Roc" msgstr "Roca" msgid "Rocs" msgstr "Rocas" msgid "Mage" msgstr "Mago" msgid "Magi" msgstr "Magos" msgid "Archmage" msgstr "Arquimago" msgid "Archmagi" msgstr "Arquimagos" msgid "Giant" msgstr "Gigante" msgid "Giants" msgstr "Gigantes" msgid "Titan" msgstr "Titã" msgid "Titans" msgstr "Titãs" msgid "Skeletons" msgstr "Esqueletos" msgid "Zombie" msgstr "Zumbi" msgid "Zombies" msgstr "Zumbis" msgid "Mutant Zombie" msgstr "Zumbi Mutante" msgid "Mutant Zombies" msgstr "Zumbis Mutantes" msgid "Mummies" msgstr "Múmias" msgid "Mummy" msgstr "Múmia" msgid "Royal Mummies" msgstr "Múmias Reais" msgid "Royal Mummy" msgstr "Múmia Real" msgid "Vampire" msgstr "Vampiro" msgid "Vampires" msgstr "Vampiros" msgid "Vampire Lord" msgstr "Lorde Vampiro" msgid "Vampire Lords" msgstr "Lordes Vampiros" msgid "Lich" msgstr "Liche" msgid "Liches" msgstr "Liches" msgid "Power Lich" msgstr "Liche Poderoso" msgid "Power Liches" msgstr "Liches Poderosos" msgid "Bone Dragon" msgstr "Dragão-Esqueleto" msgid "Bone Dragons" msgstr "Dragões-Esqueletos" msgid "Rogue" msgstr "Bandido" msgid "Rogues" msgstr "Bandidos" msgid "Nomad" msgstr "Nômade" msgid "Nomads" msgstr "Nômades" msgid "Ghost" msgstr "Fantasma" msgid "Ghosts" msgstr "Fantasmas" msgid "Genie" msgstr "Gênio" msgid "Genies" msgstr "Gênios" msgid "Medusa" msgstr "Medusa" msgid "Medusas" msgstr "Medusas" msgid "Earth Elemental" msgstr "Elemental da Terra" msgid "Earth Elementals" msgstr "Elementais da Terra" msgid "Air Elemental" msgstr "Elemental do Ar" msgid "Air Elementals" msgstr "Elementais do Ar" msgid "Fire Elemental" msgstr "Elemental do Fogo" msgid "Fire Elementals" msgstr "Elementais do Fogo" msgid "Water Elemental" msgstr "Elemental da Ãgua" msgid "Water Elementals" msgstr "Elementais da Ãgua" msgid "Random Monsters" msgstr "Monstros Aleatório" msgid "Random Monster 1" msgstr "Monstro Aleatório 1" msgid "Random Monsters 1" msgstr "Monstros Aleatórios 1" msgid "Random Monster 2" msgstr "Monstro Aleatório 2" msgid "Random Monsters 2" msgstr "Monstros Aleatórios 2" msgid "Random Monster 3" msgstr "Monstro Aleatório 3" msgid "Random Monsters 3" msgstr "Monstros Aleatórios 3" msgid "Random Monster 4" msgstr "Monstro Aleatório 4" msgid "Random Monsters 4" msgstr "Monstros Aleatórios 4" msgid "Double shot" msgstr "Disparo duplo" msgid "2-hex monster" msgstr "Ocupa 2 hexágonos" msgid "Double strike" msgstr "Golpe duplo" msgid "Double damage to Undead" msgstr "Dobro de dano para Mortos-Vivos" msgid "% magic resistance" msgstr "% de resistência mágica" msgid "Immune to Mind spells" msgstr "Imune à feitiços da Mente" msgid "Immune to Elemental spells" msgstr "Imune à feitiços Elementais" msgid "Immune to Fire spells" msgstr "Imune à feitiços de Fogo" msgid "Immune to Cold spells" msgstr "Imune À feitiços Frios" msgid "Immune to " msgstr "Imune à " msgid "% immunity to %{spell} spell" msgstr "% imunidade à feitiços de %{spell}" msgid "% damage from Elemental spells" msgstr "% de dano para feitiços Elementais" msgid "% damage from %{spell} spell" msgstr "% de dano do feitiço %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% de chance de Dissipar feitiços benéficos" msgid "% chance to Paralyze" msgstr "% de chance de Paralisar" msgid "% chance to Petrify" msgstr "% de chance de Petrificar" msgid "% chance to Blind" msgstr "% de chance de Cegar" msgid "% chance to Curse" msgstr "% de chance de Amaldiçoar" msgid "% chance to cast %{spell} spell" msgstr "% de chance de lançar o feitiço %{spell}" msgid "HP regeneration" msgstr "Regeneração de PV" msgid "Two hexes attack" msgstr "Ataque de dois hexágonos" msgid "Flyer" msgstr "Voador" msgid "Always retaliates" msgstr "Sempre retaliar" msgid "Attacks all adjacent enemies" msgstr "Ataca todos os inimigos adjacentes" msgid "No melee penalty" msgstr "Sem penalidade no corpo a corpo" msgid "Dragon" msgstr "Dragão" msgid "Undead" msgstr "Morto-Vivo" msgid "No enemy retaliation" msgstr "Sem retaliação do inimigo" msgid "HP drain" msgstr "Drenagem de PV" msgid "Cloud attack" msgstr "Ataque de Névoa" msgid "Decreases enemy's morale by " msgstr "Diminui a moral do inimigo em " msgid "% chance to halve enemy" msgstr "% de chance de matar metade do pelotão inimigo" msgid "Soul Eater" msgstr "Comedor de Almas" msgid "Elemental" msgstr "Elemental" msgid "No Morale" msgstr "Sem Moral" msgid "Earth creature" msgstr "Criatura terrestre" msgid "Air creature" msgstr "Criatura aérea" msgid "Fire creature" msgstr "Criatura de fogo" msgid "Water creature" msgstr "Criatura aquática" msgid "Double damage from Fire spells" msgstr "Dano em dobro por feitiços de Fogo" msgid "Double damage from Cold spells" msgstr "Dano em dobro por feitiços Frios" msgid "Double damage from Earth creatures" msgstr "Dano em dobro por criaturas terrestres" msgid "Double damage from Air creatures" msgstr "Dano em dobro por criaturas de Ar" msgid "Double damage from Fire creatures" msgstr "Dano em dobro por criaturas de Fogo" msgid "Double damage from Water creatures" msgstr "Dano em dobro por criaturas aquáticas" msgid "Lightning" msgstr "Raio" msgid "% immunity to " msgstr "% imunidade à " msgid "% damage from " msgstr "% de dano de " msgid "The three Anduran artifacts magically combine into one." msgstr "Os três artefatos de Anduran se combinam magicamente em um." msgid "View Spells" msgstr "Ver Feitiços" msgid "View %{name} Info" msgstr "Ver informação de %{name}" msgid "Move %{name}" msgstr "Mover %{name}" msgid "Cannot move the Spellbook" msgstr "Não é possível mover o Grimório" msgid "This item can't be traded." msgstr "Este item não pode ser trocado." msgid "Invalid Artifact" msgstr "Artefato Inválido" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} aumenta o Conhecimento do herói em %{count}." msgid "Ultimate Book of Knowledge" msgstr "Livro do Conhecimento Definitivo" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} aumenta a Habilidade de Ataque do herói em %{count}." msgid "Ultimate Sword of Dominion" msgstr "Espada do Domínio Definitiva" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} aumenta a Habilidade de Defesa do herói em %{count}." msgid "Ultimate Cloak of Protection" msgstr "Manto da Proteção Definitivo" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} aumenta o Poder Mágico do herói em %{count}." msgid "Ultimate Wand of Magic" msgstr "Varinha de Condão Definitiva" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" "%{name} aumenta as Habilidades de Ataque e Defesa do herói em %{count} cada " "uma." msgid "Ultimate Shield" msgstr "Escudo Definitivo" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "" "%{name} aumenta o Poder Mágico e o Conhecimento do herói em %{count} cada um." msgid "Ultimate Staff" msgstr "Cajado Definitivo" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "" "%{name} aumenta cada uma das habilidades básicas do herói em %{count} pontos." msgid "Ultimate Crown" msgstr "Coroa Definitiva" msgid "Golden Goose" msgstr "Ganso de Ouro" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} gera uma renda de %{count} ouro por dia." msgid "Arcane Necklace of Magic" msgstr "Colar Arcano da Magia" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Depois de resgatar uma Feiticeira de um túmulo amaldiçoado, ela recompensa " "seu heroísmo com um belíssimo colar de joias." msgid "Caster's Bracelet of Magic" msgstr "Bracelete Mágico do Conjurador" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Ao procurar pelos escombros de uma mina desmoronada, você liberta um grupo " "de anões presos. Agradecido, o líder lhe dá um bracelete de ouro." msgid "Mage's Ring of Power" msgstr "Anel de Poder do Mago" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Um grito de dor o leva a um Centauro, preso em uma armadilha. Ao libertar a " "criatura, ele lhe entrega uma pequena bolsa. Esvaziando o conteúdo, você " "encontra um deslumbrante anel com joias." msgid "Witch's Broach of Magic" msgstr "Broche Mágico das Bruxas" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Ao lado dos restos de uma bruxa queimada jaz um belo broche, de formato " "intrincado. Aproximando-se do cadáver com cautela, você adiciona o broche ao " "seu inventário." msgid "Medal of Valor" msgstr "Medalha de Bravura" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} aumenta a moral do exército do herói em %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Libertando uma virtuosa donzela das garras de um soberano malvado, você " "recebe uma Medalha de Bravura pelo arauto do Rei." msgid "Medal of Courage" msgstr "Medalha da Coragem" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Depois de salvar um garoto de um grupo de lobos, você o devolve à mansão de " "seu pai. O nobre agradecido lhe concede uma Medalha da Coragem." msgid "Medal of Honor" msgstr "Medalha de Honra" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Depois de libertar uma princesa de um reino vizinho das garras malignas dos " "desprezíveis traficantes de escravos, ela concede a você uma Medalha de " "Honra." msgid "Medal of Distinction" msgstr "Medalha da Distinção" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Ao livrar o campo do hediondo Minotauro que comeu Cavaleiros nobres por " "esporte, você é honrado com a Medalha da Distinção." msgid "Fizbin of Misfortune" msgstr "Fizbin do Infortúnio" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "" "%{name} diminui consideravelmente a moral do exército do herói em %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Você tropeça em uma medalha ao longo de uma estrada vazia. Adicionando a " "medalha ao seu inventário, você se dá conta de que adquiriu a indesejável " "Fizbin do Infortúnio, diminuindo muito a moral do seu exército." msgid "Thunder Mace of Dominion" msgstr "Maça Trovejante do Domínio" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Durante uma súbita tempestade, um raio atinge uma árvore, rachando-a. Dentro " "da árvore, você encontra uma maça misteriosa." msgid "Armored Gauntlets of Protection" msgstr "Luvas Blindadas da Proteção" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} aumenta a Habilidade de Defesa do herói em %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Você encontra o infame Cavaleiro Negro! Após um duelo cansativo que terminou " "em um empate, o Cavaleiro, por respeito, oferece a você um par de manoplas " "blindadas." msgid "Defender Helm of Protection" msgstr "Elmo Defensor da Proteção" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Um brilho de luz dourada chama sua atenção. Após mais investigações, você " "encontra um elmo dourado escondido debaixo de um arbusto." msgid "Giant Flail of Dominion" msgstr "Mangual Gigante do Domínio" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Um gigante desajeitado se matou com seu próprio mangual. Conhecendo sua " "habilidade superior com esta arma, você remove com confiança o espetacular " "mangual do Gigante caído." msgid "Ballista of Quickness" msgstr "Balista da Rapidez" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "%{name} dá à catapulta do herói um tiro extra por turno de combate." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Caminhando através das ruínas de uma antiga cidade murada, você encontra o " "instrumento da destruição da cidade, uma balista meticulosamente construída." msgid "Stealth Shield of Protection" msgstr "Escudo Furtivo da Proteção" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Uma estátua de pedra de um guerreiro segurando um escudo prateado. Ao " "remover o escudo, a estátua se desfaz em pó." msgid "Dragon Sword of Dominion" msgstr "Espada do Dragão do Domínio" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Enquanto você caminha por um caminho estreito, um arbusto próximo de repente " "irrompe em chamas. Diante de seus olhos as chamas se tornam a imagem de uma " "bela mulher. Ela estende uma espada magnífica para você." msgid "Power Axe of Dominion" msgstr "Machado da Força do Domínio" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Você vê um machado de prata incrustado profundamente no chão. Depois de " "várias tentativas fracassadas de seu exército para remover o machado, você " "segura firmemente o cabo do machado e o puxa sem esforço." msgid "Divine Breastplate of Protection" msgstr "Peitoral Divino da Proteção" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Uma gangue de Bandidos está vasculhando os pertences dos guerreiros mortos. " "Ao assustar os necrófagos, você percebe que os Bandidos esqueceram um belo " "peitoral." msgid "Minor Scroll of Knowledge" msgstr "Pergaminho Menor do Conhecimento" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Diante de você aparece uma caixa de vidro levitando com um pergaminho, " "apoiada sobre uma almofada de veludo vermelho. Ao seu toque, a tampa se abre " "e o pergaminho flutua em suas mãos ansiosas." msgid "Major Scroll of Knowledge" msgstr "Pergaminho Maior do Conhecimento" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Ao visitar um sábio local, você explica a intenção de sua jornada. Ele pega " "um saco e retira um pergaminho amarelado e o entrega a você." msgid "Superior Scroll of Knowledge" msgstr "Pergaminho Superior do Conhecimento" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Você se depara com os restos de um antigo druida. Os ossos, amarelados com a " "idade, emergem das dobras esfarrapadas de sua túnica. Ao procurar na túnica, " "você descobre um pergaminho escondido." msgid "Foremost Scroll of Knowledge" msgstr "Pergaminho Definitivo do Conhecimento" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Ossos mutilados, amarelados pela idade, emergem das dobras esfarrapadas da " "túnica de um Druida morto. Ao procurar na sua túnica, você descobre um " "pergaminho escondido." msgid "Endless Sack of Gold" msgstr "Saco de Ouro Infinito" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} fornece ao herói %{count} de ouro por dia." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Um duendezinho dança alegremente ao redor de um saco mágico. Ao vê-lo se " "aproximar, ele para no meio do caminho. O homenzinho grita e bate seu pé no " "chão ferozmente, desaparecendo no ar. Você se lembra do velho provérbio de " "duendes 'Achado Não é Roubado', você pega o saco e vai embora." msgid "Endless Bag of Gold" msgstr "Bolsa de Ouro Infinito" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Uma nobre mulher, separada de seus companheiros de viagem, pede sua ajuda. " "Depois de acompanhá-la até sua casa, ela o recompensa com uma bolsa cheia de " "ouro." msgid "Endless Purse of Gold" msgstr "Bornal de Ouro Infinito" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Em suas viagens, você encontra um bornal de couro cheio de ouro que uma vez " "pertenceu a um grande rei guerreiro que tinha a capacidade de transformar " "qualquer objeto inanimado em ouro." msgid "Nomad Boots of Mobility" msgstr "Botas Nômade da Mobilidade" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} aumenta o movimento do herói em terra firme." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Um comerciante Nômade busca a proteção de uma tribo de Goblins. Para sua " "assistência, ele lhe dá um par de botas meticulosamente produzidas, feitas " "do couro mais macio. Olhando de perto, você vê fascinantes gravuras antigas " "gravadas no couro." msgid "Traveler's Boots of Mobility" msgstr "Botas do Viajante da Mobilidade" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Ao descobrir um lindo par de botas feitas do couro mais fino e macio, você " "agradece ao doador anônimo e adiciona as botas ao seu inventário." msgid "Lucky Rabbit's Foot" msgstr "Pé de Coelho da Sorte" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} aumenta a sorte do exército do herói em %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Um comerciante itinerante lhe oferece um pé de coelho, feito de pêlo " "prateado cintilante, por uma passagem segura. O comerciante explica que o " "encanto aumentará sua sorte em combate." msgid "Golden Horseshoe" msgstr "Ferradura de Ouro" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Um Unicórnio assustado fica preso. Você sussurra palavras calmantes para ela " "enquanto a liberta. De repente, ela relincha, dá um coice na sua frente, e " "depois galopa. Olhando para baixo, você encontra uma ferradura de ouro que " "caiu." msgid "Gambler's Lucky Coin" msgstr "Moeda da Sorte do Apostador" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Você capturou um diabrete que tem aterrorizado a região. Em troca de sua " "libertação, ele o recompensa com uma moeda mágica." msgid "Four-Leaf Clover" msgstr "Trevo-de-Quatro-Folhas" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "No meio de uma parte de vegetação morta e seca, para sua surpresa você " "encontra um trevo-de-quatro-folhas verde e saudável." msgid "True Compass of Mobility" msgstr "Bússola da Mobilidade" msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} aumenta o movimento do herói em terra e no mar." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Um velho que afirma ser um inventor pede que você experimente sua última " "invenção. Ele então lhe entrega uma bússola." msgid "Sailor's Astrolabe of Mobility" msgstr "Astrolábio do Marinheiro da Mobilidade" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} aumenta o movimento do herói no mar." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Um velho capitão de mar está sendo torturado por Ogros. Você o salva, e em " "troca ele o recompensa com um instrumento maravilhoso para medir a distância " "de uma estrela." msgid "Evil Eye" msgstr "Olho Maligno" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" "%{name} reduz pela metade o custo de lançamento de feitiços de maldição." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Ao aventurar-se em uma cabana decrépita, você encontra o esqueleto de uma " "bruxa morta há muito tempo. A investigação dos restos mortais revela um olho " "de vidro dentro do seu crânio vazio." msgid "Enchanted Hourglass" msgstr "Ampulheta Encantada" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} estende a duração de todos os feitiços do herói em %{count} turnos." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "A paisagem muda subitamente e você se encontra em meio a uma cena macabra: " "Abutres se alimentando dos restos de uma terrível batalha. Sua rápida busca " "nos corpos revela uma ampulheta encantada." msgid "Gold Watch" msgstr "Relógio de Ouro" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} duplica a eficácia dos feitiços de hipnotizar do herói." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Em recompensa por ajudar sua carroça a sair de uma vala, um vendedor de " "poção itinerante lhe dá um relógio \"mágico\" de ouro. Ele não sabia, mas o " "relógio é realmente mágico." msgid "Skullcap" msgstr "Capacete de Caveira" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} reduz pela metade o custo de lançamento de todos os feitiços que " "influenciam a mente." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Em uma breve parada na pousada, você acidentalmente troca as suas bagagens. " "Você encontra um capacete de caveira em sua nova mochila." msgid "Ice Cloak" msgstr "Manto de Gelo" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} reduz à metade todo o dano que as tropas do herói recebem dos " "feitiços de frio." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Respondendo aos gritos de pânico de uma donzela em apuros, você descobre uma " "jovem mulher fugindo de um urso faminto. Você mata a fera no momento certo, " "e a Feiticeira agradecida tece um manto mágico da pele do urso." msgid "Fire Cloak" msgstr "Manto de Fogo" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} reduz à metade todo o dano que as tropas do herói recebem dos " "feitiços de fogo." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Você se deparou com uma luta entre um Necromante e um Paladino. O Necromante " "acerta o Paladino com um raio de fogo, deixando-o de joelhos. Agindo " "rapidamente, você mata o demônio antes do golpe final. O grato Paladino lhe " "dá o manto de fogo que o salvou." msgid "Lightning Helm" msgstr "Elmo Relâmpago" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} reduz à metade todo o dano que as tropas do herói recebem dos " "feitiços de relâmpago." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Um funileiro viajante que precisa de suprimentos oferece um elmo com um " "formato de relâmpago no topo em troca de comida e água. Por curiosidade, " "você aceita, e mais tarde descobre que o elmo é mágico." msgid "Evercold Icicle" msgstr "Pingente Supergelado" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} faz com que os feitiços de gelo do herói causem %{count} por cento " "mais dano às tropas inimigas." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Um pingente de gelo que resiste até ao calor do sol ao meio-dia atrai sua " "atenção. Intrigado, você o pega e descobre que ele não derrete na sua mão." msgid "Everhot Lava Rock" msgstr "Pedra de Lava Superquente" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} faz com que os feitiços de fogo do herói causem %{count} por cento " "mais de dano às tropas inimigas." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Suas andanças o colocam em contato com uma tribo de seres semelhantes a " "macacos usando uma pedra mágica de lava que nunca esfria para acender suas " "fogueiras. Você tem piedade deles e os ensina a fazer fogo com paus. " "Acreditando que você é um deus, os macacos lhe dão sua pedra." msgid "Lightning Rod" msgstr "Haste Relâmpago" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} faz com que os feitiços de relâmpago do herói causem %{count} por " "cento a mais de dano às tropas inimigas." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Enquanto espera uma tempestade, um raio de luz atinge o para-raios de uma " "casa de campo próxima, que derrete e cai no chão. A ponta do para-raios, no " "entanto, sobrevive intacta e faz com que seus cabelos fiquem de pé quando " "você o toca. Hmm..." msgid "Snake-Ring" msgstr "Anel de Serpente" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} reduz pela metade o custo de conjuração de todos os feitiços de " "bênção do herói." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Você encontrou um anel de forma estranha no dedo de um viajante morto há " "muito tempo. O anel parece uma serpente mordendo sua própria cauda." msgid "Ankh" msgstr "Cruz Egípcia" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} duplica a eficácia de todos os feitiços de ressurreição e animação " "do herói." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Uma forte tempestade de vento revela a entrada de uma tumba enterrada. Sua " "investigação revela que a tumba já foi saqueada, mas os ladrões ignoraram " "uma cruz egípcia em uma corrente de prata no escuro." msgid "Book of Elements" msgstr "Livro dos Elementos" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} duplica a eficácia de todos os feitiços de invocação do herói." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Você se depara com um conjurador que implora para acompanhar você e seu " "exército por algum tempo por segurança. Você concorda, e ele oferece como " "pagamento uma cópia do livro dos elementos." msgid "Elemental Ring" msgstr "Anel Elemental" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" "%{name} reduz pela metade o custo do lançamento de todos os feitiços de " "invocação." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Enquanto faz uma pausa para descansar, você percebe um lince subindo em uma " "árvore curta para chegar ao ninho de corvo. Por impulso, você mesmo sobe na " "árvore e afugenta o gato. Quando você olha no ninho, encontra uma coleção de " "pedras brilhantes e um anel." msgid "Holy Pendant" msgstr "Pingente Sagrado" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} torna todas as tropas do herói imunes a feitiços de maldição." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Em suas andanças você encontra um ermitão que vive em uma pequena e arrumada " "cabana. Impressionado com sua missão, ele tira algum tempo de suas " "meditações para abençoá-lo e dar-lhe um encanto contra maldições." msgid "Pendant of Free Will" msgstr "Pingente do Livre-Arbítrio" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" "%{name} torna todas as tropas do herói imunes a feitiços de hipnotização." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Respondendo aos gritos de ajuda, você encontra Fadas do rio se divertindo ao " "afundar um homem velho. Sentindo-se revoltado, você resgata o homem e " "arrasta uma Fada para terra firme por um tempo. A Fada, desconfortável no " "ar, lhe dá um pingente mágico para deixá-la ir." msgid "Pendant of Life" msgstr "Pingente da Vida" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} torna todas as tropas do herói imunes a feitiços de morte." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Você encontra uma pequena caravana à beira da estrada e após algumas " "partidas de jogo da bugalha, você acaba ganhando um pingente mágico. Seu " "antigo dono diz que ele protege contra os feitiços da morte dos Necromantes." msgid "Serenity Pendant" msgstr "Pingente da Serenidade" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} torna todas as tropas do herói imunes a feitiços de fúria." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Os sons do combate o atraem para a cena de uma luta entre um velho bárbaro e " "uma Hidra de oito cabeças. Sua intervenção oportuna balança a batalha em " "favor do homem, e ele o recompensa com um pingente que costumava usar para " "acalmar sua mente para a batalha." msgid "Seeing-eye Pendant" msgstr "Pingente da Visão" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" "O %{name} torna todas as tropas do herói imunes a feitiços de cegueira." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Você encontra uma mulher muito velha, há muito tempo cega de cataratas e " "morrendo sozinha. Você cuida de suas necessidades finais e promete um " "enterro decente. Agradecida, ela lhe dá um pingente mágico com um olho " "estilizado. Ela permite que você veja com os olhos fechados." msgid "Kinetic Pendant" msgstr "Pingente Cinético" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name} torna todas as tropas do herói imunes a feitiços de paralisia." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Você se depara com um golem usando um pingente brilhante e bloqueando seu " "caminho. Seguindo um palpite, você corta o pingente de seu pescoço. " "Dependente de sua fonte de energia, o golem se quebra, deixando você com o " "pingente mágico." msgid "Pendant of Death" msgstr "Pingente da Morte" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} torna todas as tropas do herói imunes a feitiços sagrados." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Após uma batalha rápida e mortal com um Necromante, você ganha seu pingente " "mágico. Mais tarde, um Mago lhe diz que o pingente protege os mortos-vivos " "sob seu controle de feitiços sagradas." msgid "Wand of Negation" msgstr "Varinha da Negação" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "O %{name} torna todas as tropas do herói imunes a feitiços de dissipação " "mágica." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Você encontra um antigo amigo Mago seu viajando na direção oposta. Ele lhe " "presenteia com um presente: Uma varinha que impede o uso do feitiço de " "dissipação mágica em seus aliados." msgid "Golden Bow" msgstr "Arco Dourado" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} elimina a penalidade de %{count} por cento para as tropas do herói " "ao atirar além de obstáculos (por exemplo, muralhas do castelo)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Você se encontra casualmente com um famoso Arqueiro e começam a jogar " "bugalha. Você aposta seu cavalo contra o arco dele. Você ganha." msgid "Telescope" msgstr "Telescópio" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} aumenta a quantidade de terreno que o herói revela ao explorar em " "%{count} quadrado extra." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Um comerciante de terras longínquas negocia com você uma nova invenção de " "seu povo por suprimentos de viagem. Ele faz com que objetos distantes " "pareçam mais próximos, e ele o chama de...\n" "\n" "Telescópio." msgid "Statesman's Quill" msgstr "Pena do Estadista" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} reduz o custo de rendição para %{count} por cento do custo total das " "tropas que o herói possui em seu exército." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Você faz uma pausa para ajudar um diplomata com um eixo quebrado a resolver " "seu problema. Em agradecimento, ele lhe dá uma pena de escrita com " "propriedades mágicas que ele diz que \"ajudará as pessoas a verem as coisas " "do seu jeito\"." msgid "Wizard's Hat" msgstr "Chapéu de Mago" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} aumenta a duração dos feitiços do herói em %{count} turnos." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Você vê um Mago fugindo de um Grifo e cavalgando como o vento. O Mago abre " "um portal e passa por ele, tendo seu chapéu derrubado na borda do portal. O " "Grifo segue o Mago pelo portal e ele se fecha. Você pega o chapéu caído, " "tira o seu pó e o coloca." msgid "Power Ring" msgstr "Anel de Poder" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} retorna %{count} de mana extras por dia para o herói." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Você encontra uma pequena árvore que se parece muito com o grande Bruxo " "Carnauth com um anel em torno de um de seus galhos. Restos de roupa e couro " "podre levam você a suspeitar que é Carnauth, transformado. Como você não " "pode ajudá-lo, você pega o anel mágico." msgid "Ammo Cart" msgstr "Carroça de Munição" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} fornece munição infinita para todas as tropas do herói que atiram." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Uma carroça de munição no meio de um velho campo de batalha chama sua " "atenção. A inspeção mostra que ela está em boas condições de funcionamento, " "então você a leva junto." msgid "Tax Lien" msgstr "Privilégio Fiscal" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} custa ao herói %{count} peças de ouro por dia." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Seus enormes padrões de gastos lhe renderam uma enorme conta de impostos que " "você não pode pagar. O cobrador de impostos tem piedade e concorda em " "receber apenas 250 de ouro por dia de sua conta durante toda a vida. " "Assinale aqui se você quiser que um dólar vá para o fundo de campanha " "eleitoral presidencial." msgid "Hideous Mask" msgstr "Máscara Hedionda" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "%{name} impede que todos os exércitos 'errantes' se juntem ao herói." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Em seu saque ao túmulo de Sinfilas Gardolad, o famoso Bruxo metamorfo, você " "descobre sua lendária máscara. Tremendo, você a coloca e contorce seu rosto " "fazendo uma terrível careta! Oh não! Na verdade é a máscara hedionda de " "Gromluck Greene, e você está preso a ela." msgid "Endless Pouch of Sulfur" msgstr "Bolsa de Enxofre Infinita" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} fornece %{count} unidade(s) de enxofre por dia." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Você visita um alquimista que, ao ver seu exército, é influenciado pela " "justiça de sua causa. Ele lhe dá sua bolsa de enxofre infinita para ajudar " "no seu esforço de guerra." msgid "Endless Vial of Mercury" msgstr "Frasco de Mercúrio Infinito" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} fornece %{count} unidade(s) de mercúrio por dia." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Em uma breve parada na torre de um Mago, abandonada às pressas, você " "encontra um frasco mágico de mercúrio que sempre tem um pouco de mercúrio no " "fundo. Reconhecendo um tesouro quando o vê, você o tampa e o coloca no seu " "bolso." msgid "Endless Pouch of Gems" msgstr "Bolsa de Gema Infinita" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} fornece %{count} unidade de gema por dia." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Uma curta tempestade faz surgir um arco-íris... E você pode ver o fim dele. " "Cavalgando rapidamente, você pega o pote de ouro que se encontra lá. O " "duende proprietário do pote, incapaz de impedir que você o leve, oferece uma " "bolsa de gemas infinita pela devolução de seu ouro. Você aceita." msgid "Endless Cord of Wood" msgstr "Pilha de Madeira Infinita" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} fornece %{count} unidade de madeira por dia." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Ao parar para descansar e acender uma fogueira, você tira lenha de uma pilha " "de lenha próxima. Enquanto você continua tirando lenha da pilha, você " "percebe que ela não diminui. Você percebe para seu deleite que a madeira é " "encantada, então você a leva junto." msgid "Endless Cart of Ore" msgstr "Carroça de Minério Infinito" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} fornece %{count} de minério por dia." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Você encontrou um ferreiro de armas Goblin fazendo armas para serem usadas " "contra humanos. Com um tremendo grito, você e seu exército descem sobre o " "acampamento dele e os expulsa. Em uma busca, você encontra uma carroça " "mágica de minério que nunca fica sem ferro." msgid "Endless Pouch of Crystal" msgstr "Bolsa de Cristal Infinita" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} fornece %{count} de cristal por dia." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Abrigando-se de uma tempestade em uma pequena caverna, você percebe um " "pequeno pedaço de cristal em um canto. Curioso, você quebra um pedaço e " "percebe que o cristal original se reconstruiu. Você decide colocar o pedaço " "inteiro em uma bolsa e levá-lo com você." msgid "Spiked Helm" msgstr "Elmo com Espinhos" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Seu exército é emboscado por uma pequena tribo de Orcs selvagens. Você os " "afugenta facilmente e os sobreviventes fogem em todas as direções. Um dos " "Orcs estava usando um elmo com espinhos polido. Imaginando que ele seria uma " "boa lembrança, você o leva." msgid "Spiked Shield" msgstr "Escudo Cravado" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Você se depara com uma ponte que se estende por um desfiladeiro. Antes que " "você possa atravessar, um Troll sai de baixo da ponte e exige pagamento para " "permitir que você passe. Você se recusa, e o Troll o cobra novamente, " "forçando-o a matá-lo. Você leva seu escudo cravado como um troféu." msgid "White Pearl" msgstr "Pérola Branca" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Uma caminhada pelo leito de um seco lago de água salgada seca rende um " "prêmio improvável: Uma pérola branca em meio a cascas e escombros " "estilhaçados." msgid "Black Pearl" msgstr "Pérola Negra" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Os rumores de um Grifo de tamanho incomum que se abate sobre o campo o levam " "ao seu covil na caverna. Uma luta rápida e brutal despacha a besta, e uma " "busca em seu imundo ninho resulta em uma enorme pérola negra." msgid "Magic Book" msgstr "Grimório" msgid "The %{name} enables the hero to cast spells." msgstr "O %{name} permite que o herói lance feitiços." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" "Um jovem se aproxima de você: \"Meu Lorde, permita-me mostrar-lhe minha " "última invenção para disseminar o conhecimento!\" Você segue o homem até sua " "oficina e imediatamente observa um grande aparelho com alavancas e " "manivelas. \"É isso aqui!\", diz ele ansiosamente, \"A Prensa de " "Impressão\". E antes que você possa dizer uma palavra, ele lhe entrega um " "Grimório." msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "A vitória pode ser alcançada encontrando qualquer Artefato Definitivo." msgid "Dummy 2" msgstr "Fantoche 2" msgid "The reserved artifact." msgstr "O artefato reservado." msgid "Dummy 3" msgstr "Fantoche 3" msgid "Dummy 4" msgstr "Fantoche 4" msgid "Spell Scroll" msgstr "Pergaminho Mágico" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Este %{name} dá ao herói a habilidade de lançar o feitiço %{spell} se o " "herói tiver um Grimório." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Você encontra um recipiente elaborado que abriga um velho pergaminho de " "velino. As runas no recipiente são muito antigas e a arte com a qual foi " "montado é impressionante. Ao desenrolar o pergaminho, você se sente imbuído " "de um poder mágico." msgid "Arm of the Martyr" msgstr "Braço do Mártir" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} aumenta o Poder Mágico do herói em %{count}, mas adiciona a " "penalidade de moral dos mortos-vivos." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Um dos membros menos inteligentes de seu grupo pega um braço do chão. Apesar " "de faltar um corpo, ele ainda está em movimento. Suas tropas acham o braço " "desmembrado repulsivo, mas você não consegue se livrar dele: ele parece " "deter algum tipo de poder mágico que influencia sua tomada de decisão." msgid "Breastplate of Anduran" msgstr "Peitoral de Anduran" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} aumenta a defesa do herói em %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Você encontra um aviso. Nele se lê: \"Aqui jaz o corpo de Anduran. Curve-se " "e jure fidelidade, e você será recompensado\". Você decide fazer o que ele " "diz. Ao se levantar, você sente um frio em sua pele. Olhando para baixo, " "você descobre que de repente está vestindo um peitoral brilhante e " "ornamentado." msgid "Broach of Shielding" msgstr "Broche de Proteção" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} concede %{count} por cento de proteção contra o Armagedom e a " "Tempestade Elemental, mas diminui o Poder Mágico em 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Uma Feiticeira bondosa acha que as defesas de seu exército poderiam usar um " "impulso mágico. Ela se oferece para encantar o Broche que você usa em seu " "manto, e você aceita." msgid "Battle Garb of Anduran" msgstr "Traje de Batalha de Anduran" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} combina os poderes dos três artefatos de Anduran. Ele fornece máxima " "sorte e moral para as tropas do herói e dá ao herói o feitiço Portal da " "Cidade." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Por pena de um pobre camponês, você compra um baú com velhas sucatas que " "eles estão vendendo por muito ouro. Mais tarde, ao vasculhá-lo, você " "descobre que ele contém as 3 peças do lendário traje de batalha de Anduran!" msgid "Crystal Ball" msgstr "Bola de Cristal" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} permite que o herói obtenha informações mais específicas sobre " "monstros, heróis inimigos e castelos próximos ao herói." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Você se depara com uma caravana de ciganos que se banqueteiam e fortificam " "seus corpos com hidromel. Eles o chamam e dizem: \"Se você provar que pode " "dançar o Rama-Buta, nós o recompensaremos\". Você não sabe dançar, mas tenta " "assim mesmo. Eles riem histericamente, mas admiram sua bravura, dando-lhe " "uma Bola de Cristal." msgid "Heart of Fire" msgstr "Coração de Fogo" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} fornece %{count} por cento de proteção contra o fogo, mas duplica os " "danos causados pelo frio." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Você entra em uma clareira recentemente queimada e se depara com um " "Elemental do Fogo sentado em cima de uma rocha. Ele olha para cima, seu " "rosto flamejante contorcido em um olhar com grande dor. Em seguida, atira um " "objeto incandescente em você. Você levanta suas mãos para se defender, mas " "ele passa através das suas mãos e aparece no seu peito." msgid "Heart of Ice" msgstr "Coração de Gelo" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} fornece %{count} por cento de proteção contra o frio, mas duplica os " "danos causados pelo fogo." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "De repente, uma frieza cortante envolveu seu corpo. Você se apreende, caindo " "de seu cavalo. A dor diminui, mas você ainda sente como se seu peito " "estivesse congelado. À medida que se levanta do chão, você ouve risos " "calorosos. Você se vira a tempo de ver um Gigante de Gelo fugir para o " "bosque e desaparecer." msgid "Helmet of Anduran" msgstr "Elmo de Anduran" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Você observa um objeto reluzente que se levanta do chão. Você envia um " "membro de seu grupo para investigar. Ele retorna com um capacete dourado em " "suas mãos. Você percebe que deve ser o lendário elmo Anduran, o único homem " "que era conhecido por usar armadura de ouro maciço." msgid "Holy Hammer" msgstr "Martelo Sagrado" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Você se depara com uma batalha onde um Paladino foi mortalmente ferido por " "um grupo de Zumbis. Ele pede para você pegar seu martelo e terminar o que " "ele começou. Quando você o pega, ele começa a zumbir, e então tudo se torna " "um borrão. Os Zumbis estão mortos, e o martelo está pingando sangue. Você o " "prende ao seu cinto." msgid "Legendary Scepter" msgstr "Cetro Lendário" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} acrescenta %{count} pontos para todos os atributos." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Ao subir uma pequena colina, você se depara com uma visão ridícula. Uma Fada " "está tentando carregar um Cetro que é quase tão grande quanto ela. Tentando " "não rir, você pergunta: \"Precisa de ajuda?\". A Fada para você e responde: " "\"Você acha que isso é engraçado? Muito bem. Você pode levá-lo. Eu prefiro " "muito mais voar.\"" msgid "Masthead" msgstr "Mastro" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} aumenta a sorte e o moral das tropas do herói em %{count} cada um em " "combates no mar." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Um velho marinheiro lhe conta uma história de um mastro encantado que ele " "usou em sua juventude para mobilizar sua tripulação durante tempos de " "dificuldade. Ele então lhe entrega um mapa gasto que mostra onde ele o " "escondeu. Após muita exploração, você o encontra escondido debaixo de uma " "doca próxima." msgid "Sphere of Negation" msgstr "Esfera da Negação" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" "%{name} desativa todos os lançamentos de feitiços, para ambos os lados, em " "combate." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Você parou para ajudar um Camponês a pegar uma égua que fugiu. Para mostrar " "sua gratidão, ele lhe entrega uma esfera minúscula. Assim que você a segura, " "você sente a energia mágica drenar de seus braços." msgid "Staff of Wizardry" msgstr "Cajado da Feitiçaria" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} aumenta o Poder Mágico do herói em %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Suas tropas encontram um misterioso bastão levitando a cerca de um metro do " "chão. Eles o entregam a você, e você percebe uma inscrição. Que diz: \"A " "magia se mantém mais poderosa do que qualquer outra coisa. Ouça minhas " "palavras, e você ganhará todas as lutas.\"" msgid "Sword Breaker" msgstr "Quebra-Espada" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} aumenta a defesa do herói em %{count} e o ataque em 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Um ex-capitão da Guarda admira sua missão e oferece a você a Quebra-Espada " "encantada em que ele utilizava durante seus anos de serviço." msgid "Sword of Anduran" msgstr "Espada de Anduran" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Um Troll o detém e diz: \"Pague-me 5.000 peças de ouro, ou a Espada de " "Anduran o cortará onde estiver.\" Você se recusa. O troll pega a espada em " "seu cinto, grita de dor e foge. Ao pegar a lendária espada, você agradece " "que os Trolls mais idiotas tendem a segurar a ponta errada dos objetos " "afiados." msgid "Spade of Necromancy" msgstr "Pá da Necromancia" msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} aumenta a habilidade de necromancia do herói." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Uma pá suja foi enfiada em um monte de terra nas proximidades. Após " "investigação, descobriu-se que era a pá encantada dos Coveiros, há muito " "tempo perdida pelos mortais." msgid "spellBonus|selected by user" msgstr "selecionado pelo usuário" msgid "Wood" msgstr "Madeira" msgid "Mercury" msgstr "Mercúrio" msgid "Ore" msgstr "Minério" msgid "Sulfur" msgstr "Enxofre" msgid "Crystal" msgstr "Cristal" msgid "Gems" msgstr "Gemas" msgid "Gold" msgstr "Ouro" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Existem sete recursos em Heroes 2, utilizados para construir e melhorar " "castelos, comprar tropas e recrutar heróis. O ouro é o mais comum, " "necessário para praticamente tudo. Madeira e minério são usados para a " "maioria das construções. Gemas, Mercúrio, Enxofre e Cristal são recursos " "mágicos raros utilizados para as criaturas e estruturas mais poderosas." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Faz com que uma bola de fogo gigante atinja a área selecionada, causando " "danos a todas as criaturas próximas." msgid "Fireball" msgstr "Bola de Fogo" msgid "Fireblast" msgstr "Rajada de Fogo" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Uma versão melhorada da bola de fogo, a rajada de fogo afeta dois hexágonos " "ao redor do ponto central do feitiço, em vez de um." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Faz com que um raio de energia elétrica atinja a criatura selecionada." msgid "Lightning Bolt" msgstr "Raio Elétrico" msgid "Chain Lightning" msgstr "Relâmpagos" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Faz com que um raio de energia elétrica atinja uma criatura selecionada, " "depois atinja a criatura mais PRÓXIMA com metade do dano, depois atinja a " "criatura mais próxima com metade do dano, e assim por diante, até ficar " "muito fraca para ser prejudicial. Aviso: Este feitiço pode atingir suas " "próprias criaturas!" msgid "Teleport" msgstr "Teletransporte" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Teletransporta a criatura que você selecionou para qualquer posição aberta " "no campo de batalha." msgid "Cure" msgstr "Cura" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Remove todos os feitiços negativos lançados sobre uma de suas unidades e " "restaura até %{count} PV por nível de Poder Mágico." msgid "Mass Cure" msgstr "Cura Coletiva" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Remove todos os feitiços negativos lançados sobre suas forças e restaura até " "%{count} PV por nível de Poder Mágico, por criatura." msgid "Resurrect" msgstr "Ressuscitar" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Ressuscita criaturas de uma unidade atingida ou morta até o fim do combate." msgid "Resurrect True" msgstr "Ressurreição Definitiva" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" "Ressuscita as criaturas de uma unidade atingida ou morta permanentemente." msgid "Haste" msgstr "Azáfama" msgid "Increases the speed of any creature by %{count}." msgstr "Aumenta a velocidade de qualquer criatura em %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Aumenta a velocidade de todas as suas criaturas em %{count}" msgid "Mass Haste" msgstr "Azáfama Coletiva" msgid "Slows target to half movement rate." msgstr "Reduz a taxa de movimento pela metade." msgid "spell|Slow" msgstr "Lentidão" msgid "Mass Slow" msgstr "Lentidão Coletiva" msgid "Slows all enemies to half movement rate." msgstr "Reduz a velocidade de movimento de todos os inimigos pela metade." msgid "spell|Blind" msgstr "Cegar" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Embaça os olhos das criaturas afetadas, impedindo-as de se moverem." msgid "Bless" msgstr "Bênção" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Faz com que as criaturas selecionadas causem o dano máximo." msgid "Causes all of your units to inflict maximum damage." msgstr "Faz com que todas as suas unidades inflijam o dano máximo." msgid "Mass Bless" msgstr "Bênção Coletiva" msgid "Magically increases the defense skill of the selected creatures." msgstr "Aumenta magicamente a Habilidade de Defesa das criaturas selecionadas." msgid "Stoneskin" msgstr "Couraça de Pedra" msgid "Steelskin" msgstr "Couraça de Aço" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Aumenta a Habilidade de Defesa das criaturas alvo. Esta é uma versão " "melhorada da Couraça de Pedra." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Faz com que as criaturas selecionadas inflijam o dano mínimo." msgid "Curse" msgstr "Maldição" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Faz com que todas as tropas inimigas inflijam o dano mínimo." msgid "Mass Curse" msgstr "Maldição Coletiva" msgid "Damages all undead in the battle." msgstr "Causa danos a todos os mortos-vivos na batalha." msgid "Holy Word" msgstr "Palavra Sagrada" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Causa danos a todos os mortos-vivos na batalha. Esta é uma versão melhorada " "da Palavra Sagrada." msgid "Holy Shout" msgstr "Clamor Divino" msgid "Anti-Magic" msgstr "Anti-Magia" msgid "Prevents any magic against the selected creatures." msgstr "Impede qualquer magia contra as criaturas selecionadas." msgid "Dispel Magic" msgstr "Dissipar Magia" msgid "Removes all magic spells from a single target." msgstr "Remove todos os feitiços mágicos de um único alvo." msgid "Mass Dispel" msgstr "Dissipar Coletivo" msgid "Removes all magic spells from all creatures." msgstr "Remove todos os feitiços mágicos de todas as criaturas." msgid "Causes a magic arrow to strike the selected target." msgstr "Faz com que uma flecha mágica atinja o alvo selecionado." msgid "Magic Arrow" msgstr "Flecha Mágica" msgid "Berserker" msgstr "Furioso" msgid "Causes a creature to attack its nearest neighbor." msgstr "Faz com que uma criatura ataque seu vizinho mais próximo." msgid "Armageddon" msgstr "Armagedom" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "O santo terror ataca o campo de batalha, causando graves danos a todas as " "criaturas." msgid "Elemental Storm" msgstr "Tempestade Elemental" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "Elementos mágicos caem sobre o campo de batalha, causando danos a todas as " "criaturas." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Uma chuva de rochas atinge uma área do campo de batalha, causando danos a " "todas as criaturas próximas." msgid "Meteor Shower" msgstr "Chuva de Meteoros" msgid "Paralyze" msgstr "Paralisar" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "As criaturas alvos são paralisadas, incapazes de se mover ou revidar." msgid "Hypnotize" msgstr "Hipnotizar" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Coloca uma única unidade inimiga sob seu controle se os seus pontos de vida " "forem inferiores a %{count} vezes o Poder Mágico do conjurador." msgid "Cold Ray" msgstr "Raio Frio" msgid "Drains body heat from a single enemy unit." msgstr "Drena o calor corporal de uma única unidade inimiga." msgid "Cold Ring" msgstr "Anel Frio" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Drena o calor corporal de todas as unidades ao redor do ponto central, mas " "não incluindo o ponto central." msgid "Disrupting Ray" msgstr "Raio Degenerador" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Reduz o valor de defesa de uma unidade inimiga em três pontos." msgid "Damages all living (non-undead) units in the battle." msgstr "Causa danos a todas as unidades vivas (não mortos-vivos) na batalha." msgid "Death Ripple" msgstr "Onda de Morte" msgid "Death Wave" msgstr "Onda da Morte" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Causa danos a todas as unidades vivas (não mortos-vivos) na batalha. Este " "feitiço é uma versão melhorada da Onda de Morte." msgid "Dragon Slayer" msgstr "Matador de Dragão" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Aumenta muito a Habilidade de Ataque de uma unidade contra os Dragões." msgid "Blood Lust" msgstr "Sede de Sangue" msgid "Increases a unit's attack skill." msgstr "Aumenta a Habilidade de Ataque de uma unidade." msgid "Animate Dead" msgstr "Despertar Mortos" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "Ressuscita criaturas de uma unidade morta-viva que atingida ou morta " "permanentemente." msgid "Mirror Image" msgstr "Imagem Espelhada" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Cria uma unidade ilusória duplicada de uma de suas unidades existentes. Esta " "unidade ilusória causa os mesmos danos que a unidade original, mas " "desaparecerá se sofrer algum dano." msgid "Shield" msgstr "Escudo" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Reduz pela metade o dano recebido de ataques à distância para uma única " "unidade. Não afeta o dano recebido de Torres ou Balistas." msgid "Mass Shield" msgstr "Escudo Coletivo" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Reduz pela metade o dano recebido de ataques à distância para todas as suas " "unidades. Não afeta o dano recebido de Torres ou Balistas." msgid "Summon Earth Elemental" msgstr "Invocar Elemental da Terra" msgid "Summons Earth Elementals to fight for your army." msgstr "Invoca os Elementais da Terra para lutar por seu exército." msgid "Summon Air Elemental" msgstr "Invocar Elemental do Ar" msgid "Summons Air Elementals to fight for your army." msgstr "Invoca os Elementais do Ar para lutar pelo seu exército." msgid "Summon Fire Elemental" msgstr "Invocar Elemental do Fogo" msgid "Summons Fire Elementals to fight for your army." msgstr "Invoca os Elementais do Fogo para lutar pelo seu exército." msgid "Summon Water Elemental" msgstr "Invocar Elemental da Ãgua" msgid "Summons Water Elementals to fight for your army." msgstr "Invoca os Elementais de Ãgua para lutar pelo seu exército." msgid "Damages castle walls." msgstr "Causa danos nas muralhas do castelo." msgid "Earthquake" msgstr "Terremoto" msgid "Causes all mines across the land to become visible." msgstr "Faz com que todas as minas em toda a terra se tornem visíveis." msgid "View Mines" msgstr "Ver Minas" msgid "Causes all resources across the land to become visible." msgstr "Faz com que todos os recursos em toda a terra se tornem visíveis." msgid "View Resources" msgstr "Ver Recursos" msgid "Causes all artifacts across the land to become visible." msgstr "Faz com que todos os artefatos em toda a terra se tornem visíveis." msgid "View Artifacts" msgstr "Ver Artefatos" msgid "Causes all towns and castles across the land to become visible." msgstr "" "Faz com que todas as cidades e castelos em toda a terra se tornem visíveis." msgid "View Towns" msgstr "Ver Cidades" msgid "Causes all Heroes across the land to become visible." msgstr "Faz com que todos os Heróis em toda a terra se tornem visíveis." msgid "View Heroes" msgstr "Ver Heróis" msgid "Causes the entire land to become visible." msgstr "Faz com que toda a terra se torne visível." msgid "View All" msgstr "Ver Tudo" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" "Permite que o conjurador veja informações detalhadas sobre os Heróis " "inimigos." msgid "Summon Boat" msgstr "Invocar Barco" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Invoca o barco amigo desocupado mais próximo a um local costeiro mais " "próximo. Um barco amigo é aquele que você acabou de construir ou foi o " "jogador mais recente a ocupar." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Permite que o conjurador se transporte magicamente para um local próximo." msgid "Dimension Door" msgstr "Porta Dimensional" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Devolve o conjurador para qualquer cidade ou castelo que atualmente possui." msgid "Town Gate" msgstr "Portão da Cidade" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Devolve o herói à cidade ou castelo de sua escolha, desde que seja " "controlado por você." msgid "Visions" msgstr "Visões" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "O feitiço Visões prevê o provável resultado de um encontro com um " "acampamento de exército neutro." msgid "Haunt" msgstr "Assombrar" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Assombra uma mina que você controla com Fantasmas. Esta mina deixa de " "produzir recursos. (Se eu não puder mantê-la, ninguém a manterá!)" msgid "Set Earth Guardian" msgstr "Definir Guardião da Terra" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" "Define Elementais da Terra para proteger uma mina contra os exércitos " "inimigos." msgid "Set Air Guardian" msgstr "Definir Guardião do Ar" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" "Define Elementais do Ar para proteger uma mina contra os exércitos inimigos." msgid "Set Fire Guardian" msgstr "Definir Guardião do Fogo" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" "Define Elementais do Fogo para proteger uma mina contra os exércitos " "inimigos." msgid "Set Water Guardian" msgstr "Definir Guardião da Ãgua" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" "Define Elementais da Ãgua para proteger uma mina contra os exércitos " "inimigos." msgid "Random Spell" msgstr "Feitiço Aleatório" msgid "Randomly selected spell of any level." msgstr "Feitiço de qualquer nível selecionado aleatoriamente." msgid "Random 1st Level Spell" msgstr "Feitiço Aleatório de 1. Nível" msgid "Randomly selected 1st level spell." msgstr "Feitiço de 1. nível selecionado aleatoriamente." msgid "Random 2nd Level Spell" msgstr "Feitiço Aleatório de 2. Nível" msgid "Randomly selected 2nd level spell." msgstr "Feitiço de 2. nível selecionado aleatoriamente." msgid "Random 3rd Level Spell" msgstr "Feitiço Aleatório de 3. Nível" msgid "Randomly selected 3rd level spell." msgstr "Feitiço de 3. nível selecionado aleatoriamente." msgid "Random 4th Level Spell" msgstr "Feitiço Aleatório de 4. Nível" msgid "Randomly selected 4th level spell." msgstr "Feitiço de 4. nível selecionada aleatoriamente." msgid "Random 5th Level Spell" msgstr "Feitiço Aleatório de 5. Nível" msgid "Randomly selected 5th level spell." msgstr "Feitiço de 5. nível selecionado aleatoriamente." msgid "Petrification" msgstr "Petrificação" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Transforma a criatura afetada em pedra. Uma criatura petrificada recebe " "metade do dano de um ataque direto." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Você não tem um Grimório, então não pode lançar um feitiço." msgid "No spell to cast." msgstr "Sem feitiço para lançar." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Seu herói tem %{sp} de mana restante de %{max}." msgid "View Adventure Spells" msgstr "Ver Feitiços de Aventura" msgid "View Combat Spells" msgstr "Ver Feitiços de Combate" msgid "View previous page" msgstr "Ver página anterior" msgid "View next page" msgstr "Ver próxima página" msgid "Close Spellbook" msgstr "Fechar Grimório" msgid "View %{spell}" msgstr "Ver %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Este feitiço causa %{damage} pontos de dano." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Este feitiço invoca\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Este feitiço restaura %{hp} PV." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Este feitiço invoca %{count} %{monster} para guardar a mina." msgid "The nearest town is %{town}." msgstr "A cidade mais próxima é %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Esta cidade é ocupada pelo seu herói %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Este feitiço controla até\n" "%{hp} PV." msgid "The ultimate artifact is really the %{name}." msgstr "O artefato definitivo é realmente %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" "O artefato definitivo pode ser encontrado nas regiões de %{name} do mundo." msgid "north-west" msgstr "noroeste" msgid "north" msgstr "norte" msgid "north-east" msgstr "nordeste" msgid "west" msgstr "oeste" msgid "center" msgstr "centro" msgid "east" msgstr "leste" msgid "south-west" msgstr "sudoeste" msgid "south" msgstr "sul" msgid "south-east" msgstr "sudeste" msgid "The truth is out there." msgstr "A verdade está lá fora." msgid "The dark side is stronger." msgstr "O lado sombrio é mais forte." msgid "The end of the world is near." msgstr "O fim do mundo está próximo." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Os ossos do Lorde Caçador estão enterrados na fundação da arena." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Um Dragão Negro irá tirar um Titã em qualquer dia da semana." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" "Ele disse à ela: Yada yada yada... e então ela disse: Blah, blah, blah..." msgid "An unknown force is being resurrected..." msgstr "Uma força misteriosa está ressuscitando..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Verifique a mais nova versão do jogo em\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Selecionar %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Ativar combate automático" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "finalizar a batalha no modo automático" #~ msgid "Please Remember" #~ msgstr "Por favor, lembre-se" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Você sempre pode alterar o idioma, a resolução e as configurações do jogo " #~ "clicando na " #~ msgid "door" #~ msgstr "Porta" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " no lado esquerdo do Menu Principal ou em " #~ msgid " button from the " #~ msgstr " no menu de " #~ msgid "NEW GAME" #~ msgstr "NOVO JOGO" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ ". \n" #~ "\n" #~ "Aproveite o jogo!" #~ msgid "Warning!" #~ msgstr "Aviso!" #~ msgid "Dummy 1" #~ msgstr "Fantoche 1" fheroes2-1.1.6+dfsg/files/lang/ro.po000066400000000000000000006416611476115357100172060ustar00rootroot00000000000000# Romanian translation of fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2022-10-25 08:56+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: ro\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==1 ? 0 : n==0 || (n!=1 && n%100>=1 && " "n%100<=19) ? 1 : 2);\n" "X-Generator: Poedit 3.1.1\n" msgid "" "NEW\n" "GAME" msgstr "" "JOC\n" "NOU" msgid "" "SAVE\n" "GAME" msgstr "" "SALVEAZÄ‚\n" "JOCUL" msgid "" "LOAD\n" "GAME" msgstr "" "ÃŽNCARCÄ‚\n" "JOCUL" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "ÃŽNCHIDE" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "JOC\n" "NOU" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "SALVEAZÄ‚\n" "JOCUL" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "ÃŽNCARCÄ‚\n" "JOCUL" msgid "CANCEL" msgstr "RENUNȚĂ" msgid "OKAY" msgstr "OKAY" msgid "ACCEPT" msgstr "ACCEPTÄ‚" msgid "DECLINE" msgstr "REFUZÄ‚" msgid "LEARN" msgstr "ÃŽNVAȚĂ" msgid "TRADE" msgstr "TROC" msgid "YES" msgstr "DA" msgid "NO" msgstr "NU" msgid "EXIT" msgstr "EXIT" msgid "smallerButton|EXIT" msgstr "EXIT" msgid "DISMISS" msgstr "RENUNȚĂ" msgid "UPGRADE" msgstr "AMELIOREAZÄ‚" msgid "RESTART" msgstr "RESTART" msgid "HEROES" msgstr "EROI" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "ORAȘE/\n" "CASTELE" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "X-L" msgid "ALL" msgstr "TOT" msgid "SELECT" msgstr "SELECTEAZÄ‚" msgid "" "STANDARD\n" "GAME" msgstr "" "JOC\n" "STANDARD" msgid "" "BATTLE\n" "ONLY" msgstr "" "DOAR\n" "BÄ‚TÄ‚LIE" msgid "" "CAMPAIGN\n" "GAME" msgstr "CAMPANIE" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "JOC\n" "MULTI-\n" "PLAYER" msgid "CONFIG" msgstr "CONFIG" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "CAMPANIE\n" "ORIGINALÄ‚" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "CAMPANIE\n" "EXPANSIUNE" msgid "HOT SEAT" msgstr "" msgid "2 PLAYERS" msgstr "2 JUCÄ‚TORI" msgid "3 PLAYERS" msgstr "3 JUCÄ‚TORI" msgid "4 PLAYERS" msgstr "4 JUCÄ‚TORI" msgid "5 PLAYERS" msgstr "5 JUCÄ‚TORI" msgid "6 PLAYERS" msgstr "6 JUCÄ‚TORI" msgid "GIFT" msgstr "OFERÄ‚" msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "DIFICULTATE" msgid "VIEW INTRO" msgstr "VEZI INTRO" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "RESET" msgid "START" msgstr "START" msgid "TOWN" msgstr "ORAȘ" msgid "CASTLE" msgstr "CASTEL" #, fuzzy msgid "RESTRICT" msgstr "RESTART" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "R\n" "E\n" "N\n" "U\n" "N\n" "Èš\n" "Ä‚" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "E\n" "X\n" "I\n" "T" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "C\n" "A\n" "M\n" "P\n" "A\n" "N\n" "I\n" "E" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Războinic" msgid "Builder" msgstr "Constructor" msgid "Explorer" msgstr "Explorator" msgid "None" msgstr "Nimic" msgid "" "A few\n" "%{monster}" msgstr "" "Câțiva\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Mai mulÈ›i\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "O haită de\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "MulÈ›i\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "O hoardă de\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "O înghesuială de\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Un roi de\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Extrem de mulÈ›i\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "O legiune de\n" "%{monster}" msgid "army|Few" msgstr "(1-4)" msgid "army|Several" msgstr "(4-9)" msgid "army|Pack" msgstr "(10-19)" msgid "army|Lots" msgstr "(20-49)" msgid "army|Horde" msgstr "(50-99)" msgid "army|Throng" msgstr "(100-249)" msgid "army|Swarm" msgstr "(1000+)" msgid "army|Zounds" msgstr "(500-999)" msgid "army|Legion" msgstr "(250-499)" msgid "All %{race} troops +1" msgstr "Toate %{race} forÈ›ele +1" msgid "NeutralRaceTroops|Neutral" msgstr "" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Trupe cu %{count} aliniamente -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "NiÈ™te strigoi în grup -1" msgid "" "Default\n" "troop" msgstr "" msgid "View %{name}" msgstr "Vezi %{name}" msgid "Move the %{name} " msgstr "Mută %{name}" msgid "Move or right click to redistribute %{name}" msgstr "Mută sau fă click dreapta pentru a redistribui %{name} " msgid "Combine %{name} armies" msgstr "Combină %{name} armate" msgid "Exchange %{name2} with %{name}" msgstr "Schimbă %{name2} cu %{name}" msgid "Select %{name}" msgstr "Selectează %{name}" msgid "Cannot move last troop" msgstr "Nu poÈ›i muta ultima trupă" msgid "Move the %{name}" msgstr "Mută %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Trage în %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} distruge jumătate din trupele inamice!" msgstr[1] "%{name} distrug jumătate din trupele inamice!" msgstr[2] "%{name} distrug jumătate din trupele inamice!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} a oprit lupta automată" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} a pornit lupta automată" msgid "Spell failed!" msgstr "Vraja a eÈ™uat!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Artefactul Sfera de Negare este în vigoare pentru această bătălie, " "dezactivând toate vrăjile de luptă." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Ai aruncat deja o vrajă în această rundă." #, fuzzy msgid "That spell will have no effect!" msgstr "Vraja aceea nu va afecta pe nimeni!" msgid "You may only summon one type of elemental per combat." msgstr "PoÈ›i invoca doar un singur tip de elemental pe luptă." #, fuzzy msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Nu există niciun spaÈ›iu deschis adiacent eroului tău în care să invoci un " "elemental." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "ȘanÈ›ul reduce cu -%{count} abilitatea de apărare a oricărei unități È™i " "reduce la jumătate viteza de miÈ™care." msgid "Speed: %{speed}" msgstr "Viteză: %{speed}" msgid "Speed" msgstr "Viteză" msgid "Off" msgstr "Oprit" msgid "On" msgstr "Pornit" #, fuzzy msgid "Turn Order" msgstr "Ordin al armatei" msgid "Auto Spell Casting" msgstr "Aruncarea vrăjilor automata" msgid "Grid" msgstr "Grilă" msgid "Shadow Movement" msgstr "MiÈ™care a umbrelor" msgid "Shadow Cursor" msgstr "Cursor de umbră" msgid "Audio" msgstr "Audio" msgid "Settings" msgstr "Setări" msgid "Configure" msgstr "Configurare" msgid "Hot Keys" msgstr "Scurtături" msgid "Damage Info" msgstr "" msgid "Set the speed of combat actions and animations." msgstr "Setează viteza acÈ›iunilor de luptă È™i a animaÈ›iilor." #, fuzzy msgid "Toggle to display the turn order during the battle." msgstr "Comută pentru a afiÈ™a ordinea armatei în timpul bătăliei." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Comută dacă computerul va arunca sau nu vrăji pentru tine atunci când este " "activată lupta automată. (Notă: Acest lucru nu afectează în niciun fel " "aruncarea de vrăji pentru jucătorii computerului È™i nici nu afectează lupta " "rapidă)." msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Activează sau dezactivează grila hexagonală. Grila hexagonală se află " "întotdeauna la baza miÈ™cării, chiar dacă este dezactivată. Acest comutator " "determină doar dacă grila este vizibilă." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Activează sau dezactivează umbrele care arată unde se pot miÈ™ca È™i ataca " "creaturile tale." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Activează sau dezactivează o umbră care arată locaÈ›ia hexagonală curentă a " "cursorului mouse-ului." msgid "Change the audio settings of the game." msgstr "" msgid "Check and configure all the hot keys present in the game." msgstr "" #, fuzzy msgid "Toggle to display damage information during the battle." msgstr "Comută pentru a afiÈ™a ordinea armatei în timpul bătăliei." msgid "Exit this menu." msgstr "" msgid "Okay" msgstr "" msgid "The enemy has surrendered!" msgstr "Inamicul s-a predat!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Inamicul a fugit!" msgid "A glorious victory!" msgstr "O victorie glorioasă!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Pentru curaj în luptă, %{name} primeÈ™te %{exp} experiență." msgid "The cowardly %{name} flees from battle." msgstr "LaÈ™ul %{name} fuge de luptă." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} se predă inamicului È™i pleacă ruÈ™inat." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "ForÈ›ele tale suferă o înfrângere amară, iar %{name} îți abandonează cauza." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "ForÈ›a ta a suferit o înfrângere amară." msgid "Battlefield Casualties" msgstr "Victimele de pe câmpul de luptă" msgid "Attacker" msgstr "Atacator" msgid "Defender" msgstr "Apărător" msgid "Click to leave the battle results." msgstr "" msgid "Click to restart the battle in manual mode." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Restart" msgstr "" msgid "You have captured an enemy artifact!" msgstr "Ai capturat un artefact inamic!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Atunci când te apropii de %{name}, acesta dispare în mod misterios." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" "ÃŽn timp ce inamicul tău ajunge la %{name}, acesta dispare în mod misterios." msgid "Necromancy!" msgstr "NecromanÈ›ie!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Practicând artele întunecate ale necromanÈ›iei, eÈ™ti capabil să trezeÈ™ti " "%{numărul} de morÈ›i ai inamicului să se întoarcă în slujba ta ca %{monstru}." msgid "%{name} the %{race}" msgstr "%{name} cel %{race}" msgid "Captain of %{name}" msgstr "Căpitan al %{name}" msgid "Attack" msgstr "Atac" msgid "Defense" msgstr "Apărare" msgid "Spell Power" msgstr "Puterea vrăjii" msgid "Knowledge" msgstr "CunoÈ™tinÈ›e" msgid "Morale" msgstr "Moral" msgid "Luck" msgstr "Noroc" msgid "Spell Points" msgstr "Puncte de vrajă" msgid "Hero's Options" msgstr "OpÈ›iunile eroului" msgid "Cast Spell" msgstr "Aruncă vraja" msgid "Retreat" msgstr "Retragere" msgid "Surrender" msgstr "Predare" msgid "Cancel" msgstr "Anulează" msgid "Hero Screen" msgstr "Ecranul eroului" msgid "Captain's Options" msgstr "OpÈ›iunile căpitanului" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Aruncă o vrajă magică. PoÈ›i lansa doar o singură vrajă pe rundă de luptă. " "Runda se resetează atunci când fiecare creatură a avut o rundă." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Retrage-È›i eroul, abandonându-È›i creaturile. Eroul tău va fi disponibil " "pentru a fi recrutat din nou, însă eroul va avea doar forÈ›ele unui erou " "începător." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Predarea costă aur. Cu toate acestea, dacă plăteÈ™ti răscumpărarea, eroul È™i " "toate creaturile sale supravieÈ›uitoare vor fi disponibile pentru a fi " "recrutate din nou." msgid "Open Hero Screen to view full information about the hero." msgstr "" "Deschide ecranul eroului pentru a vedea informaÈ›ii complete despre erou." msgid "Return to the battle." msgstr "ÃŽntoarce-te la luptă." msgid "Not enough gold (%{gold})" msgstr "ÃŽntoarce-te la luptă.Nu este suficient aur (%{gold})" msgid "%{name} states:" msgstr "%{name} declară:" msgid "Captain of %{name} states:" msgstr "Căpitanul de stat %{name}:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Voi accepta capitularea ta È™i îți voi acorda È›ie È™i trupelor tale o " "trecere sigură pentru preÈ›ul de %{price} aur.\"" msgid "View %{monster} info" msgstr "Vezi %{monster} info" msgid "Fly %{monster} here" msgstr "Zboară %{monster} aici" msgid "Move %{monster} here" msgstr "Mută %{monster} aici" msgid "Shoot %{monster}" msgstr "Trage în %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(o lovitură ramasă)" msgstr[1] "(%{count} lovituri rămase)" msgstr[2] "(%{count} lovituri rămase)" msgid "Attack %{monster}" msgstr "Atacă %{monster}" msgid "Turn %{turn}" msgstr "Runda %{turn}" msgid "Teleport here" msgstr "Teleportează-te aici" msgid "Invalid teleport destination" msgstr "DestinaÈ›ie de teleportare invalidă" msgid "Cast %{spell} on %{monster}" msgstr "Aruncă %{spell} pe %{monster}" msgid "Cast %{spell}" msgstr "Aruncă %{spell}" msgid "Select spell target" msgstr "SelectaÈ›i È›inta vrăjii" msgid "View Ballista info" msgstr "Vezi informaÈ›ii despre Ballista" msgid "Ballista" msgstr "Ballista" #, fuzzy msgid "Automatic combat modes" msgstr "Luptă automată" #, fuzzy msgid "Automatic Combat Modes" msgstr "Luptă automată" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Personalizează opÈ›iunile sistemului" msgid "Allows you to customize the combat screen." msgstr "ÃŽÈ›i permite să personalizezi ecranul de luptă." msgid "System Options" msgstr "System Options" msgid "Skip this unit" msgstr "Sari peste această unitate" msgid "Skip" msgstr "Sari" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Trece peste creatura curentă. Creatura curentă își termină rândul È™i nu mai " "are posibilitatea de a merge din nou până în runda următoare." msgid "View Captain's options" msgstr "Vezi opÈ›iunile căpitanului" msgid "View Hero's options" msgstr "Vezi opÈ›iunile eroului" msgid "View opposing Captain" msgstr "Vezi căpitanul care se opune" msgid "View opposing Hero" msgstr "Vezi eroul care se opune" msgid "Hide logs" msgstr "Ascunde jurnalele" msgid "Show logs" msgstr "AfiÈ™ează jurnalele" msgid "Message Bar" msgstr "Bara de mesaje" msgid "Shows the results of individual monster's actions." msgstr "AfiÈ™ează rezultatele acÈ›iunilor individuale ale monÈ™trilor." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Sigur vreÈ›i să activaÈ›i lupta automată?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "EÈ™ti sigur că vrei să termini bătălia în modul automat?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Permite computerului să lupte în locul tău." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Luptă automată" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Luptă automată" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} È™i-a sărit rândul." msgstr[1] "%{name} È™i-a sărit rândul." msgstr[2] "%{name} È™i-a sărit rândul." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} provoacă %{damage} pagube." msgstr[1] "%{attacker} face %{damage} pagube." msgstr[2] "" msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 creatură piere." msgstr[1] "%{count} creaturi pier." msgstr[2] "%{count} creaturi pier." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} piere." msgstr[1] "%{count} %{defender} %{defender} piere." msgstr[2] "%{count} %{defender} %{defender} piere." #, fuzzy msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "Se creează o imagine în oglindă." msgstr[1] "Se creează o imagine în oglindă." msgstr[2] "Se creează o imagine în oglindă." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "%{monster} mutat: de la [%{src}] la [%{dst}]." #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} rezistă la vrajă!" msgstr[1] "%{name} rezistă la vrajă!" msgstr[2] "%{name} rezistă la vrajă!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} aruncă %{spell} asupra lui %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} aruncă %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "Vraja %{spell} provoacă daune %{damage} unei creaturi strigoi." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "Vraja %{spell} provoacă daune %{damage} tuturor creaturilor strigoi." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "Vraja %{spell} face daune %{damage}, %{count} creaturi pier." msgid "The %{spell} does %{damage} damage." msgstr "Vraja %{spell} face daune %{damage}." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "Vraja %{spell} provoacă daune %{damage} unei creaturi vii." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "Vraja %{spell} provoacă daune %{damage} tuturor creaturilor vii." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Atacul %{attacker}' îl orbeÈ™te pe %{target}!" msgstr[1] "Atacul %{attacker}' îl orbeÈ™te pe %{target}!" msgstr[2] "Atacul %{attacker}' îl orbeÈ™te pe %{target}!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "Privirea %{attacker}' îl transformă pe %{target} în piatră!" msgstr[1] "Privirea %{attacker}' îl transformă pe %{target} în piatră!" msgstr[2] "Privirea %{attacker}' îl transformă pe %{target} în piatră!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "Blestemul lui %{attacker}' cade asupra lui %{target}!" msgstr[1] "Blestemul lui %{attacker}' cade asupra lui %{target}!" msgstr[2] "Blestemul lui %{attacker}' cade asupra lui %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{target} sunt paralizaÈ›i de %{attacker}!" msgstr[1] "%{target} sunt paralizaÈ›i de %{attacker}!" msgstr[2] "%{target} sunt paralizaÈ›i de %{attacker}!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "%{attacker} risipeÈ™te toate vrăjile bune asupra %{target} tale!" msgstr[1] "%{attacker} risipeÈ™te toate vrăjile bune asupra %{target} tale!" msgstr[2] "%{attacker} risipeÈ™te toate vrăjile bune asupra %{target} tale!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} a aruncat %{spell} pe %{target}!" msgstr[1] "%{attacker} a aruncat %{spell} pe %{target}!" msgstr[2] "%{attacker} a aruncat %{spell} pe %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Ghinionul coboară asupra %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "Norocul străluceÈ™te asupra %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Un moral ridicat permite %{monster} să atace din nou." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Moralul scăzut face ca %{monster} să îngheÈ›e de panică." msgid "%{tower} does %{damage} damage." msgstr "%{tower} face %{damage} daune." msgid "The mirror image is created." msgstr "Se creează o imagine în oglindă." msgid "The mirror image is destroyed!" msgstr "Imaginea în oglindă este distrusă!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Sigur vreÈ›i să întrerupeÈ›i lupta automată?" msgid "Error" msgstr "Eroare" msgid "No spells to cast." msgstr "Nicio vrajă disponibilă." msgid "Are you sure you want to retreat?" msgstr "EÈ™ti sigur că vrei să te retragi?" msgid "Retreat disabled" msgstr "Retragerea oprită" msgid "Surrender disabled" msgstr "Predarea oprită" msgid "Damage: %{max}" msgstr "Daune: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Daune: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Fatalități: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Fatalități: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Printr-o observaÈ›ie cu ochi de vultur, %{name} este capabil să înveÈ›e vraja " "magică %{spell}." msgid "Human" msgstr "Om" msgid "AI" msgstr "AI" msgid "Start" msgstr "" #, fuzzy msgid "Start the battle." msgstr "ÃŽntoarce-te la luptă." msgid "Exit" msgstr "" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Te rog selectează un alt erou." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1}" msgid "Monsters" msgstr "MonÈ™tri" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Turela stângă" msgid "Right Turret" msgstr "Turela dreaptă" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "each with a +%{attack} bonus to their attack skill." msgstr "fiecare cu un bonus de +%{attack} la abilitatea lor de atac." #, fuzzy msgid "The %{name} is destroyed." msgstr "Imaginea în oglindă este distrusă!" #, fuzzy msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} învie din morÈ›i!" msgstr[1] "%{count} %{name} învie din morÈ›i!" msgstr[2] "%{count} %{name} învie din morÈ›i!" msgid "Dwarven Alliance" msgstr "AlianÈ›a Piticilor" msgid "Sorceress Guild" msgstr "Breasla Vrăjitoarelor" msgid "Necromancer Guild" msgstr "Breasla Necromancerilor" msgid "Ogre Alliance" msgstr "AlianÈ›a Ogrilor" msgid "Dwarfbane" msgstr "Blestemul Piticilor" msgid "Dragon Alliance" msgstr "AlianÈ›a Dragonilor" msgid "Elven Alliance" msgstr "AlianÈ›a Elfilor" msgid "Kraeger defeated" msgstr "Kraeger este învins" msgid "Wayward Son" msgstr "Fiul Rătăcitor" msgid "Uncle Ivan" msgstr "Unchiul Ivan" msgid "Annexation" msgstr "Anexare" msgid "Force of Arms" msgstr "ForÈ›a armelor" msgid "Save the Dwarves" msgstr "SalvaÈ›i piticii" msgid "Carator Mines" msgstr "Minele Carator" msgid "Turning Point" msgstr "Punct de cotitură" msgid "scenarioName|Defender" msgstr "" msgid "Corlagon's Defense" msgstr "Apărarea lui Corlagon" msgid "The Crown" msgstr "Coroane" msgid "The Gauntlet" msgstr "MănuÈ™a" msgid "Betrayal" msgstr "Trădare" msgid "Final Justice" msgstr "JustiÈ›ie finală" #, fuzzy msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland are nevoie de tine pentru a-i învinge pe lorzii din apropierea " "castelului său pentru a începe războiul de rebeliune împotriva fratelui " "său. Nu sunt aliaÈ›i între ei, aÈ™a că își vor petrece mare parte a timpului " "luptându-se unul cu celălalt. Victoria este a ta atunci când ai învins " "toate castelele È™i eroii lor." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Lorzii locali refuză să jure credință lui Roland È™i trebuie supuÈ™i. Sunt " "bogaÈ›i È™i puternici, aÈ™a că fii pregătit pentru o luptă grea. Capturează " "toate castelele inamice pentru a câștiga." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Sarcina ta este de a apăra Piticii împotriva forÈ›elor lui Archibald. " "Capturează toate oraÈ™ele È™i castelele inamice pentru a câștiga È™i asigură-te " "că nu pierzi toate oraÈ™ele piticilor deodată, altfel inamicul va câștiga." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Te vei confrunta cu patru inamici aliaÈ›i într-o luptă directă pentru resurse " "È™i comori. Capturează toate castelele inamice pentru a obÈ›ine victoria." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "DuÈ™manii tăi sunt aliaÈ›i împotriva ta È™i pornesc din apropiere, aÈ™a că " "pregăteÈ™te-te să ieÈ™i la luptă. Va trebui să deÈ›ii toate cele patru castele " "din această mică vale pentru a câștiga." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Breasla vrăjitoarelor din Noraston a cerut ajutorul lui Roland împotriva " "unui atac al aliaÈ›ilor lui Archibald. Capturează toate castelele inamice " "pentru a câștiga È™i nu pierde Noraston, altfel vei pierde scenariul. " "(Sugestie: există un castel inamic pe o insulă în ocean)." msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Adună o armată cât mai numeroasă È™i cucereÈ™te castelul inamic în termen de 8 " "săptămâni. Ai un singur inamic ca adversar, dar trebuie să parcurgi un drum " "lung pentru a ajunge la castelul inamic. Toate trupele pe care le ai în " "armată la sfârÈ™itul acestui scenariu vor fi alături de tine în bătălia " "finală." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "GăseÈ™te Coroana înainte ca eroii lui Archibald să o găsească. Roland va avea " "nevoie de Coroană pentru bătălia finală împotriva lui Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Trei inamici aliaÈ›i se află în faÈ›a ta È™i a victoriei, inclusiv Lordul " "Corlagon. Roland se află într-un castel din nord-vest, iar tu vei pierde " "dacă va cădea în mâinile inamicului. Nu uita că prin capturarea Lordului " "Corlagon te vei asigura că nu va lupta împotriva ta în scenariul final." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Aceasta este bătălia finală. Atât tu cât È™i inamicul tău sunteÈ›i înarmaÈ›i " "până în dinÈ›i È™i toÈ›i sunt aliaÈ›i împotriva ta. Capturează-l pe Archibald " "pentru a pune capăt războiului!" #, fuzzy msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Schimbarea taberei te lasă cu trei castele împotriva castelului inamicului. " "Această bătălie va fi cea mai uÈ™oară cu care te vei confrunta pentru tot " "restul războiului... trădătorule." msgid "Barbarian Wars" msgstr "" msgid "First Blood" msgstr "" msgid "Necromancers" msgstr "" msgid "Slay the Dwarves" msgstr "" msgid "Country Lords" msgstr "" msgid "Dragon Master" msgstr "" msgid "Rebellion" msgstr "" msgid "Apocalypse" msgstr "" msgid "Greater Glory" msgstr "" #, fuzzy msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Roland are nevoie de tine pentru a-i învinge pe lorzii din apropierea " "castelului său pentru a începe războiul de rebeliune împotriva fratelui " "său. Nu sunt aliaÈ›i între ei, aÈ™a că își vor petrece mare parte a timpului " "luptându-se unul cu celălalt. Victoria este a ta atunci când ai învins " "toate castelele È™i eroii lor." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" msgid "Arrow's Flight" msgstr "" msgid "Island of Chaos" msgstr "" msgid "The Abyss" msgstr "" msgid "Uprising" msgstr "" msgid "Aurora Borealis" msgstr "" msgid "Betrayal's End" msgstr "" msgid "Corruption's Heart" msgstr "" msgid "The Giant's Pass" msgstr "" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" msgid "For the good of the Empire, eliminate Kraeger." msgstr "" msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" msgid "Border Towns" msgstr "" msgid "Conquer and Unify" msgstr "" msgid "Crazy Uncle Ivan" msgstr "" msgid "The Wayward Son" msgstr "" msgid "Ivory Gates" msgstr "" msgid "The Elven Lands" msgstr "" msgid "The Epic Battle" msgstr "" msgid "The Southern War" msgstr "" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "" msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" msgid "Fount of Wizardry" msgstr "" msgid "Power's End" msgstr "" msgid "The Eternal Scrolls" msgstr "Pergamentele eterne" msgid "The Shrouded Isles" msgstr "" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" msgid "Blood is Thicker" msgstr "" msgid "King and Country" msgstr "" msgid "Pirate Isles" msgstr "" msgid "Stranded" msgstr "" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" msgid " bane" msgstr "" msgid " alliance" msgstr "" msgid "Carry-over forces" msgstr "" msgid " bonus" msgstr "" msgid " defeated" msgstr "" msgid " will always run away from your army." msgstr "" msgid " will be willing to join your army." msgstr "" msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" msgid "The army will be carried over in the campaign." msgstr "" msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" msgid "%{hero} can be hired during scenarios." msgstr "" msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "" msgid "campaignBonus|Animate Dead" msgstr "" msgid "campaignBonus|Chain Lightning" msgstr "" msgid "campaignBonus|Fireblast" msgstr "" msgid "campaignBonus|Mass Curse" msgstr "" msgid "campaignBonus|Mass Haste" msgstr "" msgid "campaignBonus|Mirror Image" msgstr "" msgid "campaignBonus|Resurrect" msgstr "" msgid "campaignBonus|Steelskin" msgstr "" msgid "campaignBonus|Summon Earth" msgstr "" msgid "campaignBonus|View Heroes" msgstr "" msgid "campaignBonus|Ballista" msgstr "" msgid "campaignBonus|Black Pearl" msgstr "" msgid "campaignBonus|Caster's Bracelet" msgstr "" msgid "campaignBonus|Defender Helm" msgstr "" msgid "campaignBonus|Breastplate" msgstr "" msgid "campaignBonus|Dragon Sword" msgstr "" msgid "campaignBonus|Fizbin Medal" msgstr "" msgid "campaignBonus|Foremost Scroll" msgstr "Pergament suprem" msgid "campaignBonus|Gauntlets" msgstr "" msgid "campaignBonus|Hideous Mask" msgstr "" msgid "campaignBonus|Mage's Ring" msgstr "" msgid "campaignBonus|Major Scroll" msgstr "Pergament major" msgid "campaignBonus|Medal of Honor" msgstr "" msgid "campaignBonus|Medal of Valor" msgstr "" msgid "campaignBonus|Minor Scroll" msgstr "Pergament minor" msgid "campaignBonus|Nomad Boots" msgstr "" msgid "campaignBonus|Power Axe" msgstr "" msgid "campaignBonus|Spiked Shield" msgstr "" msgid "campaignBonus|Stealth Shield" msgstr "" msgid "campaignBonus|Tax Lien" msgstr "" msgid "campaignBonus|Thunder Mace" msgstr "" msgid "campaignBonus|Traveler's Boots" msgstr "" msgid "campaignBonus|White Pearl" msgstr "" msgid "campaignBonus|Basic Archery" msgstr "" msgid "campaignBonus|Advanced Archery" msgstr "" msgid "campaignBonus|Expert Archery" msgstr "" msgid "campaignBonus|Basic Ballistics" msgstr "" msgid "campaignBonus|Advanced Ballistics" msgstr "" msgid "campaignBonus|Expert Ballistics" msgstr "" msgid "campaignBonus|Basic Diplomacy" msgstr "" msgid "campaignBonus|Advanced Diplomacy" msgstr "" msgid "campaignBonus|Expert Diplomacy" msgstr "" msgid "campaignBonus|Basic Eagle Eye" msgstr "" msgid "campaignBonus|Advanced Eagle Eye" msgstr "" msgid "campaignBonus|Expert Eagle Eye" msgstr "" msgid "campaignBonus|Basic Estates" msgstr "" msgid "campaignBonus|Advanced Estates" msgstr "" msgid "campaignBonus|Expert Estates" msgstr "" msgid "campaignBonus|Basic Leadership" msgstr "" msgid "campaignBonus|Advanced Leadership" msgstr "" msgid "campaignBonus|Expert Leadership" msgstr "" msgid "campaignBonus|Basic Logistics" msgstr "" msgid "campaignBonus|Advanced Logistics" msgstr "" msgid "campaignBonus|Expert Logistics" msgstr "" msgid "campaignBonus|Basic Luck" msgstr "" msgid "campaignBonus|Advanced Luck" msgstr "" msgid "campaignBonus|Expert Luck" msgstr "" msgid "campaignBonus|Basic Mysticism" msgstr "" msgid "campaignBonus|Advanced Mysticism" msgstr "" msgid "campaignBonus|Expert Mysticism" msgstr "" msgid "campaignBonus|Basic Navigation" msgstr "" msgid "campaignBonus|Advanced Navigation" msgstr "" msgid "campaignBonus|Expert Navigation" msgstr "" msgid "campaignBonus|Basic Necromancy" msgstr "" msgid "campaignBonus|Advanced Necromancy" msgstr "" msgid "campaignBonus|Expert Necromancy" msgstr "" msgid "campaignBonus|Basic Pathfinding" msgstr "" msgid "campaignBonus|Advanced Pathfinding" msgstr "" msgid "campaignBonus|Expert Pathfinding" msgstr "" msgid "campaignBonus|Basic Scouting" msgstr "" msgid "campaignBonus|Advanced Scouting" msgstr "" msgid "campaignBonus|Expert Scouting" msgstr "" msgid "campaignBonus|Basic Wisdom" msgstr "" msgid "campaignBonus|Advanced Wisdom" msgstr "" msgid "campaignBonus|Expert Wisdom" msgstr "" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" msgid "The starting alignment of the scenario will be %{race}." msgstr "" msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" msgid "The main hero will have %{skill} at the start of the scenario." msgstr "" msgid "Roland" msgstr "" msgid "Archibald" msgstr "" msgid "Price of Loyalty" msgstr "" msgid "Voyage Home" msgstr "" msgid "Wizard's Isle" msgstr "" msgid "Descendants" msgstr "" msgid "Cannot build. You have already built here today." msgstr "" msgid "For this action it is necessary to build a castle first." msgstr "" msgid "The %{building} produces %{monster}." msgstr "" msgid "Requires:" msgstr "" msgid "Exit this menu without doing anything." msgstr "" msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "" msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Mută %{name}" #, fuzzy msgid "The %{name} is already built." msgstr "Imaginea în oglindă este distrusă!" #, fuzzy msgid "Cannot build the %{name}." msgstr "Mută %{name}" msgid "Build %{name}." msgstr "" msgid "Blackridge" msgstr "" msgid "Hillstone" msgstr "" msgid "Pinehurst" msgstr "" msgid "Whiteshield" msgstr "" msgid "Woodhaven" msgstr "" msgid "Blackwind" msgstr "" msgid "Bloodreign" msgstr "" msgid "Dragontooth" msgstr "" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" msgid "Tundara" msgstr "" msgid "Vulcania" msgstr "" msgid "Baywatch" msgstr "" msgid "Fountainhead" msgstr "" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" msgid "Sandcaster" msgstr "" msgid "Alamar" msgstr "" msgid "Burlock" msgstr "" msgid "Dragadune" msgstr "" msgid "Kalindra" msgstr "" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" msgid "Blackfang" msgstr "" msgid "New Dawn" msgstr "" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" msgid "Antioch" msgstr "" msgid "Avalon" msgstr "" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" msgid "Weed Patch" msgstr "" msgid "Brownston" msgstr "" msgid "Hilltop" msgstr "" msgid "Weddington" msgstr "" msgid "Westfork" msgstr "" msgid "Whittingham" msgstr "" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "Elk's Head" msgid "Roscomon" msgstr "" msgid "Sherman" msgstr "" msgid "Yorksford" msgstr "" msgid "Blackburn" msgstr "" msgid "Blacksford" msgstr "" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "" msgid "Lankershire" msgstr "" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "" msgid "Troy" msgstr "" msgid "Forder Oaks" msgstr "" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "" msgid "Willow" msgstr "" msgid "Corackston" msgstr "" msgid "Sheltemburg" msgstr "" msgid "Cannot recruit - you already have a Hero in this town." msgstr "" msgid "Cannot recruit - you have too many Heroes." msgstr "" #, fuzzy msgid "Cannot afford a Hero." msgstr "Nu poÈ›i muta ultima trupă" msgid "There is no room in the garrison for this army." msgstr "" msgid "Fortifications" msgstr "" msgid "Farm" msgstr "" msgid "Thatched Hut" msgstr "" msgid "Archery Range" msgstr "" msgid "Upg. Archery Range" msgstr "" msgid "Blacksmith" msgstr "" msgid "Upg. Blacksmith" msgstr "" msgid "Armory" msgstr "" msgid "Upg. Armory" msgstr "" msgid "Jousting Arena" msgstr "" msgid "Upg. Jousting Arena" msgstr "" msgid "Cathedral" msgstr "" msgid "Upg. Cathedral" msgstr "" msgid "Coliseum" msgstr "" msgid "Garbage Heap" msgstr "" msgid "Hut" msgstr "" msgid "Stick Hut" msgstr "" msgid "Upg. Stick Hut" msgstr "" msgid "Den" msgstr "" msgid "Adobe" msgstr "" msgid "Upg. Adobe" msgstr "" msgid "Bridge" msgstr "" msgid "Upg. Bridge" msgstr "" msgid "Pyramid" msgstr "" msgid "Rainbow" msgstr "" msgid "Crystal Garden" msgstr "" msgid "Treehouse" msgstr "" msgid "Cottage" msgstr "" msgid "Upg. Cottage" msgstr "" msgid "Stonehenge" msgstr "" msgid "Upg. Stonehenge" msgstr "" msgid "Fenced Meadow" msgstr "" msgid "sorceress|Red Tower" msgstr "" msgid "Dungeon" msgstr "" msgid "Waterfall" msgstr "" msgid "Cave" msgstr "" msgid "Crypt" msgstr "" msgid "Nest" msgstr "" msgid "Maze" msgstr "" msgid "Upg. Maze" msgstr "" msgid "Swamp" msgstr "" msgid "Green Tower" msgstr "" msgid "warlock|Red Tower" msgstr "" msgid "Black Tower" msgstr "" msgid "Library" msgstr "" msgid "Orchard" msgstr "" msgid "Habitat" msgstr "" msgid "Pen" msgstr "" msgid "Foundry" msgstr "" msgid "Upg. Foundry" msgstr "" msgid "Cliff Nest" msgstr "" msgid "Ivory Tower" msgstr "" msgid "Upg. Ivory Tower" msgstr "" msgid "Cloud Castle" msgstr "" msgid "Upg. Cloud Castle" msgstr "" msgid "Storm" msgstr "" msgid "Skull Pile" msgstr "" msgid "Excavation" msgstr "" msgid "Graveyard" msgstr "" msgid "Upg. Graveyard" msgstr "" msgid "Upg. Pyramid" msgstr "" msgid "Mansion" msgstr "" msgid "Upg. Mansion" msgstr "" msgid "Mausoleum" msgstr "" msgid "Upg. Mausoleum" msgstr "" msgid "Laboratory" msgstr "" msgid "Shrine" msgstr "" msgid "Special" msgstr "" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Dwelling 2" msgstr "SelectaÈ›i È›inta vrăjii" msgid "Upg. Dwelling 2" msgstr "" #, fuzzy msgid "Dwelling 3" msgstr "SelectaÈ›i È›inta vrăjii" msgid "Upg. Dwelling 3" msgstr "" #, fuzzy msgid "Dwelling 4" msgstr "SelectaÈ›i È›inta vrăjii" msgid "Upg. Dwelling 4" msgstr "" #, fuzzy msgid "Dwelling 5" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Upg. Dwelling 5" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Dwelling 6" msgstr "SelectaÈ›i È›inta vrăjii" msgid "Upg. Dwelling 6" msgstr "" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" msgid "The Rainbow increases the luck of the defending units by two." msgstr "" msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "" msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" msgid "Thieves' Guild" msgstr "" msgid "Tavern" msgstr "" msgid "Shipyard" msgstr "" msgid "Well" msgstr "" msgid "Statue" msgstr "" msgid "Marketplace" msgstr "" msgid "Moat" msgstr "" msgid "Castle" msgstr "" msgid "Tent" msgstr "" msgid "Captain's Quarters" msgstr "" msgid "Mage Guild, Level 1" msgstr "" msgid "Mage Guild, Level 2" msgstr "" msgid "Mage Guild, Level 3" msgstr "" msgid "Mage Guild, Level 4" msgstr "" msgid "Mage Guild, Level 5" msgstr "" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" msgid "The Tavern increases morale for troops defending the castle." msgstr "" msgid "The Shipyard allows ships to be built." msgstr "" msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" msgid "The Statue increases the town's income by %{count} gold per day." msgstr "" msgid "The Left Turret provides extra firepower during castle combat." msgstr "" msgid "The Right Turret provides extra firepower during castle combat." msgstr "" msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" msgid "Recruit %{name}" msgstr "" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Luna: %{month}, Săptămâna: %{week}, Ziua: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" msgid "Click to show next town." msgstr "" msgid "Show next town" msgstr "" msgid "Click to show previous town." msgstr "" msgid "Show previous town" msgstr "" msgid "This town may not be upgraded to a castle." msgstr "" msgid "Town" msgstr "OraÈ™" msgid "Exit Castle" msgstr "" msgid "Exit Town" msgstr "" msgid "Show Income" msgstr "" msgid "View Hero" msgstr "" msgid "The above spells are available here." msgstr "" msgid "The spells the hero can learn have been added to their book." msgstr "" msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" msgid "Recruit Hero" msgstr "" msgid "%{name} is a level %{value} %{race} " msgstr "" msgid "with %{count} artifacts." msgstr "" msgid "with 1 artifact." msgstr "" msgid "without artifacts." msgstr "" msgid "Recruit %{name} the %{race}" msgstr "" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" msgid "Spread Formation" msgstr "" msgid "Grouped Formation" msgstr "" msgid "Click to show the next town." msgstr "" msgid "Click to show the previous town." msgstr "" msgid "Set garrison combat formation to 'Spread'" msgstr "" msgid "Set garrison combat formation to 'Grouped'" msgstr "" msgid "Exit Castle Options" msgstr "" msgid "Castle Options" msgstr "" msgid "Not enough resources to recruit creatures." msgstr "" msgid "You are unable to recruit at this time, your ranks are full." msgstr "" msgid "No creatures available for purchase." msgstr "" msgid "Recruit Creatures" msgstr "" msgid "Hire all creatures in the town." msgstr "" msgid "Max" msgstr "" msgid "Available" msgstr "" msgid "Town Population Information and Statistics" msgstr "" msgid "Damage" msgstr "" msgid "HP" msgstr "" msgid "Growth" msgstr "" msgid "week" msgstr "" msgid "View World" msgstr "" msgid "View the entire world." msgstr "" msgid "Puzzle" msgstr "" msgid "View the obelisk puzzle." msgstr "" msgid "Scenario Information" msgstr "" msgid "View information on the scenario you are currently playing." msgstr "" msgid "Dig for the Ultimate Artifact." msgstr "" msgid "Digging" msgstr "" msgid "Arena" msgstr "" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" msgid "Attack Skill" msgstr "" msgid "Defense Skill" msgstr "" msgid "Shots" msgstr "" msgid "Shots Left" msgstr "" msgid "Hit Points" msgstr "" msgid "Hit Points Left" msgstr "" msgid "You can't afford to upgrade your troops!" msgstr "" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" msgid "Are you sure you want to dismiss this army?" msgstr "" msgid "Upgrade" msgstr "" msgid "Upgrade your troops." msgstr "" msgid "Dismiss" msgstr "" msgid "Dismiss this army." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" msgid "Followers" msgstr "" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" msgid "(Rate: %{percent})" msgstr "" msgid "off" msgstr "" msgid "Music" msgstr "Muzică" msgid "Effects" msgstr "Efecte" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Expansiune" msgid "External" msgstr "Extern" msgid "Music Type" msgstr "Tip de Muzică" msgid "3D Audio" msgstr "Audio 3D" msgid "Toggle ambient music level." msgstr "" msgid "Toggle foreground sounds level." msgstr "" msgid "Change the type of music." msgstr "" msgid "Toggle the 3D effect of foreground sounds." msgstr "" msgid "Build a new ship:" msgstr "" msgid "Resource cost:" msgstr "Costul resursei:" msgid "Total: " msgstr "" msgid "Need: " msgstr "" msgid "New Game" msgstr "" msgid "Start a single or multi-player game." msgstr "" msgid "Load Game" msgstr "ÃŽncarcă jocul" msgid "Load a previously saved game." msgstr "" msgid "Save Game" msgstr "Salvează jocul" msgid "Save the current game." msgstr "" msgid "Quit" msgstr "ÃŽnchide" msgid "Quit out of Heroes of Might and Magic II." msgstr "" msgid "Language" msgstr "Limbă" msgid "Graphics" msgstr "Grafică" msgid "Black & White" msgstr "Alb & Negru" msgid "Mouse Cursor" msgstr "Cursor Mouse" msgid "Color" msgstr "Colorat" msgid "Text Support" msgstr "Suport Text" msgid "Change the language of the game." msgstr "" msgid "Select Game Language" msgstr "SelectaÈ›i Limba" msgid "Change the graphics settings of the game." msgstr "" msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" msgid "" "Map\n" "Difficulty" msgstr "" msgid "" "Game\n" "Difficulty" msgstr "" msgid "Rating" msgstr "Rată" msgid "Map Size" msgstr "" msgid "Opponents" msgstr "OponenÈ›i" msgid "Class" msgstr "Clasă" msgid "" "Victory\n" "Conditions" msgstr "" msgid "" "Loss\n" "Conditions" msgstr "" msgid "First select recipients!" msgstr "" msgid "You cannot select %{resource}!" msgstr "" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Trage în %{monster}" msgid "Select Recipients" msgstr "" msgid "Your Funds" msgstr "" msgid "Planned Gift" msgstr "" msgid "Gift from %{name}" msgstr "" msgid "Resolution" msgstr "RezoluÈ›ie" msgid "Fullscreen" msgstr "Ecran ÃŽntreg" msgid "window|Mode" msgstr "Mod" msgid "Windowed" msgstr "Fereastră" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "" msgid "System Info" msgstr "InformaÈ›ii Sistem" msgid "Change the resolution of the game." msgstr "" msgid "Select Game Resolution" msgstr "" msgid "Toggle between fullscreen and windowed modes." msgstr "" msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" msgid "Show extra information such as FPS and current time." msgstr "" msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" msgid "Event: " msgstr "" msgid "Hot Keys:" msgstr "Scurtături:" msgid "Hide" msgstr "Ascunde" msgid "Show" msgstr "Arată" msgid "Interface" msgstr "Interfață" msgid "Interface Type" msgstr "Tipul interfeÈ›ei" msgid "Toggle the type of interface you want to use." msgstr "" msgid "Toggle interface visibility." msgstr "" msgid "Scroll Speed" msgstr "Viteză de defilare" msgid "Sets the speed at which you scroll the window." msgstr "" msgid "Select Game Language:" msgstr "SelectaÈ›i Limba:" #, fuzzy msgid "Select Language:" msgstr "SelectaÈ›i Limba:" msgid "Click to choose the selected language." msgstr "" msgid "%{name} has gained a level." msgstr "" msgid "%{skill} +1" msgstr "" msgid "You have learned %{skill}." msgstr "" msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "" msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" msgid "Min" msgstr "" msgid "Qty to trade" msgstr "" msgid "Trading Post" msgstr "" msgid "Your Resources" msgstr "Resursele voastre" msgid "Available Trades" msgstr "" msgid "guarded by %{count} %{monster}" msgstr "" msgid "guarded by " msgstr "" msgid "(available: %{count})" msgstr "" msgid "(empty)" msgstr "" msgid "already learned" msgstr "" #, fuzzy msgid "treeOfKnowledge|free" msgstr "CunoÈ™tinÈ›e" msgid "already claimed" msgstr "" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "" msgid "already has max skills" msgstr "" msgid "(already visited)" msgstr "" msgid "(not visited)" msgstr "" msgid "%{color} Barrier" msgstr "" msgid "(tent visited)" msgstr "" msgid "%{color} Tent" msgstr "" msgid "Road" msgstr "" msgid "(digging ok)" msgstr "" msgid "(no digging)" msgstr "" msgid "penalty: %{cost}" msgstr "" msgid "Defenders:" msgstr "" msgid "Unknown" msgstr "" msgid "heroQuickInfo|(Level %{level})" msgstr "" msgid "Attack:" msgstr "" msgid "Defense:" msgstr "" msgid "Spell Power:" msgstr "" msgid "Knowledge:" msgstr "" msgid "Spell Points:" msgstr "" msgid "Move Points:" msgstr "" msgid "Uncharted Territory" msgstr "" msgid "Cost per troop:" msgstr "" msgid "Available: %{count}" msgstr "" msgid "Number to buy:" msgstr "" msgid "Recruit selected monsters." msgstr "" msgid "Select maximum monsters to be recruited." msgstr "" msgid "Select only 1 monster to be recruited." msgstr "" msgid "Select this game resolution." msgstr "" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "" msgid "Click to apply the selected resolution." msgstr "" msgid "Click to apply the entered text." msgstr "" msgid "Click to open the Virtual Keyboard dialog." msgstr "" msgid "Open Virtual Keyboard" msgstr "" msgid "How many creatures do you wish to move?" msgstr "" msgid "Select how many units to separate into:" msgstr "" msgid "Map: " msgstr "" msgid "" "\n" "\n" "Month: " msgstr "" msgid ", Week: " msgstr "" msgid ", Day: " msgstr "" msgid "" "\n" "\n" "Location: " msgstr "" msgid "Are you sure you want to delete file:" msgstr "" msgid "Warning" msgstr "AtenÈ›ie" msgid "Click to save the current game." msgstr "" msgid "Click to load a previously saved game." msgstr "" msgid "File to Save:" msgstr "" msgid "File to Load:" msgstr "ÃŽncarcă fiÈ™ierul:" msgid "Terrain object" msgstr "" msgid "Accept the choice made." msgstr "" msgid "Select Skill:" msgstr "" msgid "Select Spell:" msgstr "" msgid "Select Artifact:" msgstr "" msgid "Select Monster:" msgstr "" msgid "Select Hero:" msgstr "" msgid "race|Random" msgstr "Aleatorie" msgid "Click to start placing the selected hero." msgstr "" #, fuzzy msgid "%{color} %{race}" msgstr "%{name} cel %{race}" msgid "You will place" msgstr "" msgid "Click to select this class." msgstr "" msgid "Click to select this color." msgstr "" #, fuzzy msgid "Select Treasure:" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Select Ocean Object:" msgstr "SelectaÈ›i È›inta vrăjii" msgid "Castle/town placing" msgstr "" msgid "doubleLinedRace|Neutral" msgstr "" msgid "Click to start placing the selected castle/town." msgstr "" msgid "Click to select town placing." msgstr "" msgid "Click to select castle placing." msgstr "" msgid "%{color} %{race} %{townOrCastle}" msgstr "" msgid "race|Neutral" msgstr "" #, fuzzy msgid "Select Dwelling:" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Select Landscape Object:" msgstr "SelectaÈ›i È›inta vrăjii" msgid "Mine placing" msgstr "" msgid "" "Resource\n" "type:" msgstr "" "Tip de\n" "resursă:" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name} cel %{race}" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" #, fuzzy msgid "Select Mountain Object:" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Select Rock Object:" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Select Tree Object:" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Select Power Up Object:" msgstr "SelectaÈ›i È›inta vrăjii" #, fuzzy msgid "Select Adventure Object:" msgstr "SelectaÈ›i È›inta vrăjii" msgid "Players Icon" msgstr "" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" msgid "Size Icon" msgstr "" msgid "Map Type" msgstr "" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" msgid "Map Type:\n" msgstr "" msgid "The Succession Wars" msgstr "" msgid "The Price of Loyalty" msgstr "" msgid "Resurrection" msgstr "" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Limbă" msgid "Lose all your heroes and towns." msgstr "" msgid "Lose a specific town." msgstr "" msgid "Lose a specific hero." msgstr "" msgid "Run out of time. Fail to win by a certain point." msgstr "" msgid "Loss Condition" msgstr "" msgid "Defeat all enemy heroes and towns." msgstr "" msgid "Capture a specific town." msgstr "" msgid "Defeat a specific hero." msgstr "" msgid "Find a specific artifact." msgstr "" msgid "Your side must defeat the opposing side." msgstr "" msgid "Accumulate a large amount of gold." msgstr "" msgid "Victory Condition" msgstr "" msgid "Map difficulty:" msgstr "Dificultatea hărÈ›ii:" msgid "N" msgstr "" msgid "No maps exist at that size." msgstr "" msgid "Small Maps" msgstr "" msgid "View only maps of size small (36 x 36)." msgstr "" msgid "Medium Maps" msgstr "" msgid "View only maps of size medium (72 x 72)." msgstr "" msgid "Large Maps" msgstr "" msgid "View only maps of size large (108 x 108)." msgstr "" msgid "Extra Large Maps" msgstr "" msgid "View only maps of size extra large (144 x 144)." msgstr "" msgid "All Maps" msgstr "" msgid "View all maps, regardless of size." msgstr "" msgid "Selected Name" msgstr "" msgid "The name of the currently selected map." msgstr "" msgid "Selected Map Difficulty" msgstr "" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" msgid "Selected Description" msgstr "" msgid "The description of the currently selected map." msgstr "" msgid "Jump" msgstr "Instant" msgid "Hero Speed" msgstr "Viteza eroului" msgid "Don't Show" msgstr "" msgid "Enemy Speed" msgstr "Viteza inamicilor" msgid "Auto Resolve" msgstr "Auto, rezolvă" msgid "Auto, No Spells" msgstr "Auto, fără vrăji" msgid "Battles" msgstr "Bătălii" #, fuzzy msgid "combatMode|Manual" msgstr "Manuale" msgid "Change the speed at which your heroes move on the main screen." msgstr "" msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" msgid "Change the interface settings of the game." msgstr "" msgid "Interface Settings" msgstr "Setări interfață" msgid "Toggle instant battle mode." msgstr "" msgid "Att." msgstr "" msgid "Def." msgstr "" msgid "Power" msgstr "" msgid "Knowl" msgstr "" msgid "1st" msgstr "" msgid "2nd" msgstr "" msgid "3rd" msgstr "" msgid "4th" msgstr "" msgid "5th" msgstr "" msgid "6th" msgstr "" msgid "Oracle: Player Rankings" msgstr "" msgid "Thieves' Guild: Player Rankings" msgstr "" msgid "Number of Towns:" msgstr "" msgid "Number of Castles:" msgstr "" msgid "Number of Heroes:" msgstr "" msgid "Gold in Treasury:" msgstr "" msgid "Wood & Ore:" msgstr "" msgid "Gems, Cr, Slf & Mer:" msgstr "" msgid "Obelisks Found:" msgstr "" msgid "Artifacts:" msgstr "Artefacte:" msgid "Total Army Strength:" msgstr "" msgid "Income:" msgstr "" msgid "Best Hero:" msgstr "" msgid "Best Hero Stats:" msgstr "" msgid "Personality:" msgstr "" msgid "Best Monster:" msgstr "" msgid "Random Castle Name" msgstr "" msgid "Random Town Name" msgstr "" msgid "Allow Castle build" msgstr "" msgid "Default Buildings" msgstr "" msgid "Default Army" msgstr "" msgid "Castle Army" msgstr "" #, fuzzy msgid "Town Army" msgstr "OraÈ™" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" msgid "Enter Castle name" msgstr "" msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Bara de mesaje" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Bara de mesaje" #, fuzzy msgid "Click to save the Event properties." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "Resursă" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Ziua: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Add Event" msgstr "" #, fuzzy msgid "Add an additional event." msgstr "Programare suplimentară" msgid "Edit Event" msgstr "" msgid "Edit an existing event." msgstr "" msgid "Delete Event" msgstr "" msgid "Delete an existing event." msgstr "" #, fuzzy msgid "Effects:" msgstr "Efecte" #, fuzzy msgid "Conditions:" msgstr "Anexare" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" msgid "Set Experience value" msgstr "" msgid "Artifact" msgstr "Artifact" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Artifact" msgid "Delete an artifact from the event." msgstr "" msgid "No Secondary Skill will be given by the event." msgstr "" msgid "Secondary Skill" msgstr "" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" msgid "%{objects} cannot be placed on water." msgstr "" msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" msgid "%{objects} must be placed on water." msgstr "" msgid "Objects cannot be placed outside the map." msgstr "" msgid "Action objects must be placed on clear tiles." msgstr "" msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" msgid "Editor" msgstr "Editor" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "START" msgid "Main Menu" msgstr "" msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Salvează harta" msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" msgid "Create a new map from scratch." msgstr "" msgid "New Map" msgstr "" msgid "Load Map" msgstr "" msgid "Load an existing map." msgstr "" msgid "Save Map" msgstr "Salvează harta" msgid "Save the current map." msgstr "" msgid "Quit out of the map editor." msgstr "" #, fuzzy msgid "Return to the game's Main Menu." msgstr "ÃŽntoarce-te la luptă." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" msgid "Set Random Ultimate Artifact Radius" msgstr "" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "Artifact" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "" msgid "Streams" msgstr "" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "" msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Acest fiÈ™ier este corupt." msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "" msgid "Unable to locate a directory to save the map." msgstr "" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Sigur vreÈ›i să întrerupeÈ›i lupta automată?" msgid "Map saved to: " msgstr "" msgid "Failed to save the map." msgstr "" msgid "Used to place %{object}." msgstr "" #, fuzzy msgid "Select object type" msgstr "SelectaÈ›i È›inta vrăjii" msgid "" "Click here to\n" "select a monster." msgstr "" #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Te rog selectează un alt erou." msgid "" "Cell\n" "Details" msgstr "" msgid "Erase" msgstr "" msgid "Mountains" msgstr "" msgid "Rocks" msgstr "" msgid "Trees" msgstr "" msgid "Water Objects" msgstr "" msgid "Miscellaneous" msgstr "" msgid "Artifacts" msgstr "Artefacte" msgid "Dwellings" msgstr "" msgid "Mines" msgstr "" msgid "Power-ups" msgstr "" msgid "Treasures" msgstr "" msgid "Heroes" msgstr "" msgid "Towns" msgstr "" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "SelectaÈ›i È›inta vrăjii" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" msgid "Small Brush" msgstr "" msgid "Medium Brush" msgstr "" msgid "Large Brush" msgstr "" msgid "Area Fill" msgstr "" msgid "Used to click and drag for filling in large areas." msgstr "" msgid "Clear Area" msgstr "" msgid "Used to click and drag for clearing large areas." msgstr "" msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" msgid "Traversable only by boat." msgstr "" msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" msgid "Used for special editing of action objects." msgstr "" msgid "Adventure Objects Mode" msgstr "" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" msgid "Kingdom Objects Mode" msgstr "" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "MonÈ™tri" msgid "Used to place monsters on the map." msgstr "" msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" msgid "Road Mode" msgstr "" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" msgid "Specifications" msgstr "" msgid "File Options" msgstr "" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" msgid "View the editor system options, which let you customize the editor." msgstr "" msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" msgid "Cancel back to the New Map menu." msgstr "" msgid "Cancel back to the main menu." msgstr "" msgid "From Scratch" msgstr "" msgid "Start from scratch with a blank map." msgstr "" msgid "Create a randomly generated map." msgstr "" msgid "Random" msgstr "Aleatorie" msgid "Cancel back to the Map Editor main menu." msgstr "" msgid "No maps available!" msgstr "" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{name} cel %{race}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race1} %{name1}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{name} cel %{race}" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{name} cel %{race}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race1} %{name1}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{race1} %{name1}" #, fuzzy msgid "None." msgstr "Nimic" #, fuzzy msgid "One side defeats another." msgstr "Te rog selectează un alt erou." msgid "Accumulate gold." msgstr "" msgid "Run out of time." msgstr "" #, fuzzy msgid "alliance|1st" msgstr "Ballista" msgid "alliance|2nd" msgstr "" msgid "alliance|3rd" msgstr "" msgid "alliance|4th" msgstr "" msgid "alliance|5th" msgstr "" #, fuzzy msgid "Special Loss Condition" msgstr "MulÈ›umiri speciale către" msgid "Special Victory Condition" msgstr "" msgid "Allow standard victory conditions" msgstr "" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr "AlianÈ›a Ogrilor" # msgid "{%number} alliance: " msgstr "" #, fuzzy msgid "Gold:" msgstr "Aur" msgid "Select a Town to capture to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." #, fuzzy msgid "Map Difficulty" msgstr "Dificultatea hărÈ›ii:" #, fuzzy msgid "Map Description" msgstr "Designeri de hărÈ›i" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" msgid "Change Map Description" msgstr "" #, fuzzy msgid "Click to accept the changes made." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." #, fuzzy msgid "Click to edit custom rumors." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Events" msgstr "" #, fuzzy msgid "Click to change the language of the map." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Click to change your map name." msgstr "" msgid "Map Name" msgstr "" #, fuzzy msgid "Click to change the description of the current map." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Indicates the player types in the scenario. Click to change." msgstr "" msgid "Player Type" msgstr "" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" msgid "editor|%{count} %{resource}" msgstr "" #, fuzzy msgid "Animation" msgstr "Anexare" msgid "Passability" msgstr "" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "Programare suplimentară" #, fuzzy msgid "Edit Rumor" msgstr "Editor" msgid "Edit an existing rumor." msgstr "" msgid "Delete Rumor" msgstr "" msgid "Delete an existing rumor." msgstr "" msgid "" "\n" "\n" "Size: " msgstr "" msgid "" "\n" "\n" "Description: " msgstr "" #, fuzzy msgid "Save Map:" msgstr "Salvează harta" #, fuzzy msgid "Click to save the current map." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "DaÈ›i click pentru a reîncepe bătălia în mod manual." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "UÈ™or" msgid "difficulty|Normal" msgstr "Normal" msgid "difficulty|Hard" msgstr "Greu" msgid "difficulty|Expert" msgstr "Expert" msgid "difficulty|Impossible" msgstr "Imposibil" msgid "and more..." msgstr "" msgid "Easy" msgstr "UÈ™or" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "Greu" msgid "Campaign Difficulty" msgstr "Dificultatea campaniei" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" msgid "Start the selected scenario." msgstr "" msgid "View Intro" msgstr "" msgid "View the intro video for the current state of the campaign." msgstr "" msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" msgid "Restart the current scenario." msgstr "" msgid "Difficulty" msgstr "" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" msgid "Are you sure you want to restart this scenario?" msgstr "" msgid "Campaign Scenario loading failure" msgstr "" msgid "Please make sure that campaign files are correct and present." msgstr "" msgid "Days spent" msgstr "" msgid "The number of days spent on this campaign." msgstr "" msgid "Project Coordination and Core Development" msgstr "Coordonare de Proiect È™i Dezvoltare" msgid "Development" msgstr "Dezvoltare" msgid "Visit us at " msgstr "VizitaÈ›i-ne la " msgid "QA and Support" msgstr "QA È™i Suport" msgid "Dev and Support" msgstr "Dezvoltare È™i Suport" msgid "Special Thanks to" msgstr "MulÈ›umiri speciale către" msgid "and many-many other contributors and supporters!" msgstr "È™i mulÈ›i alÈ›i contributori È™i suporteri!" msgid "Support us at" msgstr "SprijiniÈ›i-ne pe" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "ConectaÈ›i-vă cu noi la" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "AveÈ›i nevoie de ajutor cu jocul?" msgid "Original project before 0.7" msgstr "Proiectul original înainte de 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Echipa Heroes of Might and Magic II: The Succession Wars" msgid "Designed and Directed" msgstr "Proiectat È™i regizat" msgid "Programming and Design" msgstr "Programare È™i design" msgid "Executive Producer" msgstr "Producător Executiv" msgid "Producer" msgstr "Producător" msgid "Additional Design" msgstr "Design suplimentar" msgid "Additional Programming" msgstr "Programare suplimentară" msgid "Musical Production" msgstr "ProducÈ›ie muzicală" msgid "Music and Sound Design" msgstr "Design de muzică È™i sunet" msgid "Vocalists" msgstr "VocaliÈ™ti" msgid "Art Director" msgstr "Director Artistic" msgid "Assistant Art Director" msgstr "Asistent Director Artistic" msgid "Artists" msgstr "ArtiÈ™ti" msgid "QA Manager" msgstr "Manager QA" msgid "QA" msgstr "QA" msgid "Writing" msgstr "Scriere" msgid "Manual and Helpfile" msgstr "Manual È™i fiÈ™ier de ajutor" msgid "Scenarios" msgstr "Scenarii" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Echipa Heroes of Might and Magic II: The Price of Loyalty" msgid "Design Lead" msgstr "Lider de design" msgid "Designers" msgstr "Designeri" msgid "Programming Lead" msgstr "Lider de programare" msgid "Art Lead" msgstr "Lider artistic" msgid "Playtesters" msgstr "Testori" msgid "Designer" msgstr "Designer" msgid "Producers" msgstr "" msgid "QA Managers" msgstr "Manageri QA" msgid "Sound Design" msgstr "Design sunet" msgid "Town Themes" msgstr "Tematici de oraÈ™e" msgid "Alto Sax" msgstr "Sax Alto" msgid "Harpsichord and Piano" msgstr "Clavecin È™i pian" msgid "Basso Vocal" msgstr "Bas (voce)" msgid "Soprano Vocal" msgstr "Soprano (voce)" msgid "Recorded at %{recordingStudio}" msgstr "ÃŽnregistrat la %{recordingStudio}" msgid "credits|Manual" msgstr "Manual" msgid "German Consultant" msgstr "Consultant germană" msgid "Map Designers" msgstr "Designeri de hărÈ›i" msgid "Package Design" msgstr "Design de ambalaj" msgid "High Scores" msgstr "" msgid "Your Name" msgstr "" msgid "Unknown Hero" msgstr "" msgid "Standard" msgstr "" msgid "View High Scores for Standard Maps." msgstr "" msgid "Campaign" msgstr "" msgid "View High Scores for Campaigns." msgstr "" msgid "hotkey|default okay event" msgstr "" msgid "hotkey|default cancel event" msgstr "" msgid "hotkey|default left" msgstr "" msgid "hotkey|default right" msgstr "" msgid "hotkey|default up" msgstr "" msgid "hotkey|default down" msgstr "" msgid "hotkey|toggle fullscreen" msgstr "" msgid "hotkey|toggle text support mode" msgstr "" msgid "hotkey|toggle developer mode" msgstr "" msgid "hotkey|new game" msgstr "" msgid "hotkey|load game" msgstr "" msgid "hotkey|high scores" msgstr "" msgid "hotkey|credits" msgstr "" msgid "hotkey|standard game" msgstr "" msgid "hotkey|campaign game" msgstr "" msgid "hotkey|multi-player game" msgstr "" msgid "hotkey|settings" msgstr "" msgid "hotkey|quit" msgstr "" msgid "hotkey|select map" msgstr "" msgid "hotkey|select small map size" msgstr "" msgid "hotkey|select medium map size" msgstr "" msgid "hotkey|select large map size" msgstr "" msgid "hotkey|select extra large map size" msgstr "" msgid "hotkey|select all map sizes" msgstr "" #, fuzzy msgid "hotkey|hot seat game" msgstr "Personalizează opÈ›iunile sistemului" msgid "hotkey|battle only game" msgstr "" msgid "hotkey|choose the original campaign" msgstr "" msgid "hotkey|choose the expansion campaign" msgstr "" msgid "hotkey|map editor main menu" msgstr "" msgid "hotkey|new map menu" msgstr "" msgid "hotkey|load map menu" msgstr "" msgid "hotkey|new map from scratch" msgstr "" msgid "hotkey|new random map" msgstr "" #, fuzzy msgid "hotkey|undo last action" msgstr "Personalizează opÈ›iunile sistemului" #, fuzzy msgid "hotkey|redo last action" msgstr "Personalizează opÈ›iunile sistemului" #, fuzzy msgid "hotkey|open game main menu" msgstr "Personalizează opÈ›iunile sistemului" msgid "hotkey|toggle passability" msgstr "" msgid "hotkey|roland campaign" msgstr "" msgid "hotkey|archibald campaign" msgstr "" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "Personalizează opÈ›iunile sistemului" msgid "hotkey|voyage home campaign" msgstr "" msgid "hotkey|wizard's isle campaign" msgstr "" msgid "hotkey|descendants campaign" msgstr "" msgid "hotkey|select first campaign bonus" msgstr "" msgid "hotkey|select second campaign bonus" msgstr "" msgid "hotkey|select third campaign bonus" msgstr "" msgid "hotkey|view campaign intro" msgstr "" msgid "hotkey|select campaign difficulty" msgstr "" msgid "hotkey|restart campaign scenario" msgstr "" msgid "hotkey|world map left" msgstr "" msgid "hotkey|world map right" msgstr "" msgid "hotkey|world map up" msgstr "" msgid "hotkey|world map down" msgstr "" msgid "hotkey|world map up left" msgstr "" msgid "hotkey|world map up right" msgstr "" msgid "hotkey|world map down left" msgstr "" msgid "hotkey|world map down right" msgstr "" msgid "hotkey|save game" msgstr "" msgid "hotkey|next hero" msgstr "" msgid "hotkey|change to hero under cursor" msgstr "" msgid "hotkey|start hero movement" msgstr "" msgid "hotkey|cast adventure spell" msgstr "" msgid "hotkey|put hero to sleep" msgstr "" msgid "hotkey|next town" msgstr "" msgid "hotkey|end turn" msgstr "" msgid "hotkey|file options" msgstr "" msgid "hotkey|adventure options" msgstr "" msgid "hotkey|puzzle map" msgstr "" msgid "hotkey|scenario information" msgstr "" msgid "hotkey|dig for artifact" msgstr "" msgid "hotkey|view world" msgstr "" msgid "hotkey|kingdom summary" msgstr "" msgid "hotkey|default action" msgstr "" msgid "hotkey|open focus" msgstr "" #, fuzzy msgid "hotkey|system options" msgstr "Personalizează opÈ›iunile sistemului" msgid "hotkey|scroll left" msgstr "" msgid "hotkey|scroll right" msgstr "" msgid "hotkey|scroll up" msgstr "" msgid "hotkey|scroll down" msgstr "" msgid "hotkey|toggle control panel" msgstr "" msgid "hotkey|toggle radar" msgstr "" msgid "hotkey|toggle buttons" msgstr "" msgid "hotkey|toggle status" msgstr "" msgid "hotkey|toggle icons" msgstr "" msgid "hotkey|transfer control to ai" msgstr "" msgid "hotkey|retreat from battle" msgstr "" msgid "hotkey|surrender during battle" msgstr "" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Personalizează opÈ›iunile sistemului" msgid "hotkey|quick combat" msgstr "" msgid "hotkey|battle options" msgstr "" msgid "hotkey|skip turn in battle" msgstr "" msgid "hotkey|cast battle spell" msgstr "" msgid "hotkey|dwelling level 1" msgstr "" msgid "hotkey|dwelling level 2" msgstr "" msgid "hotkey|dwelling level 3" msgstr "" msgid "hotkey|dwelling level 4" msgstr "" msgid "hotkey|dwelling level 5" msgstr "" msgid "hotkey|dwelling level 6" msgstr "" msgid "hotkey|well" msgstr "" msgid "hotkey|marketplace" msgstr "" msgid "hotkey|mage guild" msgstr "" msgid "hotkey|shipyard" msgstr "" msgid "hotkey|thieves guild" msgstr "" msgid "hotkey|tavern" msgstr "" msgid "hotkey|construction screen" msgstr "" msgid "hotkey|buy all monsters in well" msgstr "" msgid "hotkey|split stack by half" msgstr "" msgid "hotkey|split stack by one" msgstr "" msgid "hotkey|join stacks" msgstr "" msgid "hotkey|upgrade troop" msgstr "" msgid "hotkey|dismiss hero or troop" msgstr "" msgid "hotkey|exchange all troops" msgstr "" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "DoreÈ™ti să recâștigi controlul de la AI? Efectul va avea loc doar în " "următoarea rundă." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" msgid "Default Actions" msgstr "" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "" #, fuzzy msgid "Battle Screen" msgstr "Ecranul eroului" msgid "Town Screen" msgstr "Ecranul oraÈ™ului" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "Acest fiÈ™ier este corupt." msgid "Unsupported save format: " msgstr "" msgid "Current game version: " msgstr "" msgid "Last supported version: " msgstr "" msgid "This file contains a save with an invalid game type." msgstr "" msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" msgid "This saved game is localized to '" msgstr "" msgid "' language, but the current language of the game is '" msgstr "" msgid "No save files to load." msgstr "Nu există fiÈ™iere salvate." msgid "Hot Seat" msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "A single player game playing out a single map." msgstr "" msgid "Standard Game" msgstr "" msgid "A single player game playing through a series of maps." msgstr "" msgid "Campaign Game" msgstr "" msgid "Multi-Player Game" msgstr "" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" msgid "fheroes2 Resurrection Team presents" msgstr "Echipa fheroes2 Resurrection prezintă" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Bine aÈ›i venit în Heroes of Might and Magic II (îmbunătățit de motorul " "fheroes2)!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Bine aÈ›i venit în Heroes of Might and Magic II (îmbunătățit de motorul " "fheroes2)!\n" "ÃŽnainte de a începe jocul, selectaÈ›i rezoluÈ›ia dorită." msgid "Greetings!" msgstr "" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" msgid "Credits" msgstr "" msgid "View the credits screen." msgstr "" msgid "View the high scores screen." msgstr "" msgid "Create new or modify existing maps." msgstr "" msgid "Change language, resolution and settings of the game." msgstr "" msgid "Game Settings" msgstr "" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" msgid "Original Campaign" msgstr "" msgid "Expansion Campaign" msgstr "" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" msgid "Loading video. Please wait..." msgstr "" msgid "Host" msgstr "" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" msgid "Guest" msgstr "" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "fheroes2 are nevoie de fiÈ™ierele de date ale jocului original Heroes of " "Might and Magic II pentru a funcÈ›iona. Se pare că folosiÈ›i o versiune demo a " "Heroes of Might and Magic II pentru acest scop. ÃŽn această configuraÈ›ie, " "doar un singur scenariu va fi disponibil." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" msgid "Battle Only" msgstr "" msgid "Setup and play a battle without loading any map." msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "2 Players" msgstr "" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" msgid "3 Players" msgstr "" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" msgid "4 Players" msgstr "" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" msgid "5 Players" msgstr "" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" msgid "6 Players" msgstr "" msgid "Play with 6 human players." msgstr "" msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" msgid "Ultimate Artifact" msgstr "" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" msgid "Victory!" msgstr "" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" msgid "You have been eliminated from the game!!!" msgstr "" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" msgid "Defeat!" msgstr "" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" msgid "Your side defeats the opposing side." msgstr "" msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Capture the castle '%{name}'." msgstr "" msgid "Capture the town '%{name}'." msgstr "" msgid "Defeat the hero '%{name}'." msgstr "" msgid "Find the ultimate artifact." msgstr "" msgid "Find the '%{name}' artifact." msgstr "" msgid "Accumulate %{count} gold." msgstr "" msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" msgid "Lose the castle '%{name}'." msgstr "" msgid "Lose the town '%{name}'." msgstr "" msgid "Lose the hero: %{name}." msgstr "" msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" msgid "%{color} player has been vanquished!" msgstr "" msgid "Major Event!" msgstr "" msgid "Scenario:" msgstr "Scenariu:" msgid "Game Difficulty:" msgstr "Dificultatea jocului:" msgid "Opponents:" msgstr "OponenÈ›i:" msgid "Class:" msgstr "Clasă:" msgid "Rating %{rating}%" msgstr "Rată %{rating}%" msgid "Click here to select which scenario to play." msgstr "" msgid "Scenario" msgstr "Scenariu" msgid "Game Difficulty" msgstr "Dificultatea jocului" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" msgid "Difficulty Rating" msgstr "" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" msgid "Click to accept these settings and start a new game." msgstr "" msgid "Click to return to the main menu." msgstr "" msgid "Astrologers proclaim the Month of the %{name}." msgstr "" msgid "Astrologers proclaim the Week of the %{name}." msgstr "" msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "%{monster} growth +%{count}." msgstr "" msgid " All populations are halved." msgstr "" msgid " All dwellings increase population." msgstr "" msgid "New Month!" msgstr "" msgid "New Week!" msgstr "" msgid "Beware!" msgstr "" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" msgid "%{color} player's turn." msgstr "" msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" msgid "Lord Kilburn" msgstr "" msgid "Tsabu" msgstr "" msgid "Sir Galant" msgstr "" msgid "Thundax" msgstr "" msgid "Lord Haart" msgstr "" msgid "Ariel" msgstr "" msgid "Rebecca" msgstr "" msgid "Sandro" msgstr "" msgid "Crodo" msgstr "" msgid "Barock" msgstr "" msgid "Antoine" msgstr "" msgid "Astra" msgstr "" msgid "Agar" msgstr "" msgid "Vatawna" msgstr "" msgid "Vesper" msgstr "" msgid "Ambrose" msgstr "" msgid "Troyan" msgstr "" msgid "Jojosh" msgstr "" msgid "Wrathmont" msgstr "" msgid "Maximus" msgstr "" msgid "Next Hero" msgstr "" msgid "Select the next Hero." msgstr "" #, fuzzy msgid "Hero Movement" msgstr "MiÈ™care a umbrelor" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "" msgid "View a summary of your Kingdom." msgstr "" msgid "Cast an adventure spell." msgstr "" msgid "End Turn" msgstr "Termină tura" msgid "End your turn and let the computer take its turn." msgstr "" msgid "Adventure Options" msgstr "" msgid "Bring up the adventure options menu." msgstr "" msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Unul sau mai mulÈ›i dintre eroi se mai poate miÈ™ca, sigur doriÈ›i să vă " "terminaÈ›i tura?" msgid "Are you sure you want to quit?" msgstr "Sigur vreÈ›i să închideÈ›i?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" msgid "Are you sure you want to overwrite the save with this name?" msgstr "" msgid "Game saved successfully." msgstr "" msgid "There was an issue during saving." msgstr "" msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" msgid "Try looking on land!!!" msgstr "" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" msgid "Congratulations!" msgstr "" msgid "Nothing here. Where could it be?" msgstr "Nimic aici. Unde poate fi?" msgid "Try searching on clear ground." msgstr "" msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" msgid "Month: %{month} Week: %{week}" msgstr "Luna: %{month} Săptămâna: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" msgid "Status Window" msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" msgid "Handicap" msgstr "" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" msgid "%{color} player" msgstr "" msgid "No Handicap" msgstr "" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" msgid "Mild Handicap" msgstr "" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" msgid "Severe Handicap" msgstr "" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Setează abilitățile de atac" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "" msgid "" "Default\n" "skill" msgstr "" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "" msgid "Kingdom Income per day." msgstr "" msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "Română" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" #, fuzzy msgid "Vietnamese" msgstr "Vezi %{name}" msgid "Slow" msgstr "ÃŽncet" msgid "Fast" msgstr "Rapid" msgid "Very Fast" msgstr "Foarte rapid" msgid "Evil" msgstr "Rău" msgid "Good" msgstr "Bun" msgid ", FPS: " msgstr "" msgid "shipAndGraveyard|%{object} robber" msgstr "" msgid "pyramid|%{object} raided" msgstr "" msgid "Ector" msgstr "" msgid "Gwenneth" msgstr "" msgid "Sir Gallant" msgstr "" msgid "Tyro" msgstr "" msgid "Dimitry" msgstr "" msgid "Ruby" msgstr "" msgid "Crag Hack" msgstr "" msgid "Fineous" msgstr "" msgid "Jezebel" msgstr "" msgid "Atlas" msgstr "" msgid "Ergon" msgstr "" msgid "Jaclyn" msgstr "" msgid "Gem" msgstr "" msgid "Natasha" msgstr "" msgid "Carlawn" msgstr "" msgid "Luna" msgstr "" msgid "Arie" msgstr "" msgid "Barok" msgstr "" msgid "Kastore" msgstr "" msgid "Falagar" msgstr "" msgid "Dawn" msgstr "" msgid "Flint" msgstr "" msgid "Halon" msgstr "" msgid "Myra" msgstr "" msgid "Myrini" msgstr "" msgid "Wilfrey" msgstr "" msgid "Mandigal" msgstr "" msgid "Sarakin" msgstr "" msgid "Charity" msgstr "" msgid "Darlana" msgstr "" msgid "Ranloo" msgstr "" msgid "Rialdo" msgstr "" msgid "Zam" msgstr "" msgid "Zom" msgstr "" msgid "Celia" msgstr "" msgid "Roxana" msgstr "" msgid "Lord Corlagon" msgstr "" msgid "Lord Halton" msgstr "" msgid "Sister Eliza" msgstr "" msgid "Brother Brax" msgstr "" msgid "Dainwin" msgstr "" msgid "Joseph" msgstr "" msgid "Mog" msgstr "" msgid "Solmyr" msgstr "" msgid "Ceallach" msgstr "" msgid "Drakonia" msgstr "" msgid "Elderian" msgstr "" msgid "Gallavant" msgstr "" msgid "Jarkonas" msgstr "" msgid "Martine" msgstr "" msgid " gives you maximum morale" msgstr "" msgid " gives you maximum luck" msgstr "" msgid "You cannot have multiple spell books." msgstr "" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" msgid "Do you wish to buy one?" msgstr "" msgid "%{count} / day" msgstr "" msgid "one" msgstr "" msgid "two" msgstr "" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" msgid "You come upon the remains of an unfortunate adventurer." msgstr "" msgid "Treasure" msgstr "" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" msgid "Searching through the tattered clothing, you find nothing." msgstr "" msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" msgid "Searching inside, you find the %{artifact}." msgstr "" msgid "Inside, you find some of the wagon's cargo still intact." msgstr "" msgid "You search through the flotsam, and find some wood and some gold." msgstr "" msgid "You search through the flotsam, and find some wood." msgstr "" msgid "You search through the flotsam, but find nothing." msgstr "" msgid "Shrine of the 1st Circle" msgstr "" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 2nd Circle" msgstr "" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 3rd Circle" msgstr "" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" msgid "You drink from the enchanted fountain, but nothing happens." msgstr "" msgid "You enter the faerie ring, but nothing happens." msgstr "" msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" msgid "A second drink at the well in one day will not help you." msgstr "" msgid "A drink from the well has restored your spell points to maximum." msgstr "" msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" msgid "Do you wish to buy this artifact?" msgstr "" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" msgid "You've found the artifact: " msgstr "" msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" msgid "Victorious, you take your prize, the %{art}." msgstr "" msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" msgid "You gain control of a %{name}." msgstr "" msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "" msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" msgid "No Fire Elementals approach you from the lava pool." msgstr "" msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" msgid "A face forms in the water for a moment, and then is gone." msgstr "" msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" msgid "This burial site is deathly still." msgstr "" msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" msgid "From the observation tower, you are able to see distant lands." msgstr "" msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" msgid " and " msgstr "" msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "" msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" msgid "You have already been to this obelisk." msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "" msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" msgid "(Just bury it around my roots.)" msgstr "" msgid "Tears brim in the eyes of the tree." msgstr "" msgid "\"I need %{count} %{res}.\"" msgstr "" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" msgid "The Arena guards turn you away." msgstr "" msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" msgid "This eye seems to be intently studying its surroundings." msgstr "" msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" msgid "No spell book is present." msgstr "Cartea de vrăji nu este prezentă." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Această vrajă costă %{mana} puncte. Nu aveÈ›i suficiente puncte de vrăji, " "deci nu o puteÈ›i folosi." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" msgid "The spell was not found." msgstr "" msgid "Only heroes can cast this spell." msgstr "" msgid "This hero is not able to cast adventure spells." msgstr "" msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" msgid "This spell cannot be cast on a boat." msgstr "" msgid "This spell can only be cast near an ocean." msgstr "" msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" msgid "There are no boats available for this spell." msgstr "" #, fuzzy msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Nu există niciun spaÈ›iu deschis adiacent eroului tău în care să invoci un " "elemental." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Acest erou este deja într-un oraÈ™, deci această vrajă nu va avea niciun " "efect." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" msgid "This spell is already in effect." msgstr "" msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" msgid "%{name} the %{race} (Level %{level})" msgstr "" msgid "Random hero (Level %{level})" msgstr "" msgid "Random %{race} hero (Level %{level})" msgstr "" #, fuzzy msgid "Hero race:" msgstr "Ecranul eroului" msgid "Are you sure you want to dismiss this Hero?" msgstr "" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Puncte de vrajă" msgid "View Spell Points Info" msgstr "" msgid "Set patrol radius in tiles" msgstr "" msgid "Enter hero's name" msgstr "" msgid "Click to change race." msgstr "" msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" msgid "Exit Hero Screen" msgstr "" msgid "You cannot dismiss a hero in a castle" msgstr "" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "" msgid "Dismiss %{name} the %{race}" msgstr "" msgid "Show previous hero" msgstr "" msgid "Show next hero" msgstr "" msgid "Set army combat formation to 'Spread'" msgstr "" msgid "Set army combat formation to 'Grouped'" msgstr "" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "EÈ™ti sigur că vrei să termini bătălia în modul automat?" msgid "Blood Morale" msgstr "" msgid "%{morale} Morale" msgstr "" msgid "%{luck} Luck" msgstr "" msgid "Current Luck Modifiers:" msgstr "" msgid "Current Morale Modifiers:" msgstr "" msgid "Entire army is undead, so morale does not apply." msgstr "" msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" msgid "%{name1} meets %{name2}" msgstr "" msgid "Enemy heroes are now fully identifiable." msgstr "" msgid "Identify Hero" msgstr "" msgid "Select town to port to." msgstr "" msgid "Town Portal" msgstr "" msgid "The creatures are willing to join us!" msgstr "" msgid "All the creatures will join us..." msgstr "" msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "\n" " for a fee of %{gold} gold." msgstr "" msgid "These weak creatures will surely flee before us." msgstr "" msgid "I fear these creatures are in the mood for a fight." msgstr "" #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "fiecare cu un bonus de +%{attack} la abilitatea lor de atac." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" msgid "The hero's spell power determines the duration or power of a spell." msgstr "" msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" msgid "Current Modifiers:" msgstr "" msgid "skill|Basic" msgstr "" msgid "skill|Advanced" msgstr "" msgid "skill|Expert" msgstr "Expert" msgid "Pathfinding" msgstr "" msgid "Archery" msgstr "" msgid "Logistics" msgstr "" msgid "Scouting" msgstr "" msgid "Diplomacy" msgstr "" msgid "Navigation" msgstr "" msgid "Leadership" msgstr "" msgid "Wisdom" msgstr "" msgid "Mysticism" msgstr "" msgid "Ballistics" msgstr "" msgid "Eagle Eye" msgstr "" msgid "Necromancy" msgstr "" msgid "Estates" msgstr "" msgid "Advanced Archery" msgstr "" msgid "Advanced Pathfinding" msgstr "" msgid "Basic Archery" msgstr "" msgid "Basic Pathfinding" msgstr "" msgid "Expert Pathfinding" msgstr "" msgid "Advanced Logistics" msgstr "" msgid "Basic Logistics" msgstr "" msgid "Basic Scouting" msgstr "" msgid "Expert Archery" msgstr "" msgid "Expert Logistics" msgstr "" msgid "Advanced Diplomacy" msgstr "" msgid "Advanced Scouting" msgstr "" msgid "Basic Diplomacy" msgstr "" msgid "Expert Diplomacy" msgstr "" msgid "Expert Scouting" msgstr "" msgid "Advanced Leadership" msgstr "" msgid "Advanced Navigation" msgstr "" msgid "Basic Leadership" msgstr "" msgid "Basic Navigation" msgstr "" msgid "Expert Navigation" msgstr "" msgid "Advanced Wisdom" msgstr "" msgid "Basic Mysticism" msgstr "" msgid "Basic Wisdom" msgstr "" msgid "Expert Leadership" msgstr "" msgid "Expert Wisdom" msgstr "" msgid "Advanced Luck" msgstr "" msgid "Advanced Mysticism" msgstr "" msgid "Basic Luck" msgstr "" msgid "Expert Luck" msgstr "" msgid "Expert Mysticism" msgstr "" msgid "Advanced Ballistics" msgstr "" msgid "Advanced Eagle Eye" msgstr "" msgid "Basic Ballistics" msgstr "" msgid "Basic Eagle Eye" msgstr "" msgid "Expert Ballistics" msgstr "" msgid "Advanced Necromancy" msgstr "" msgid "Basic Estates" msgstr "" msgid "Basic Necromancy" msgstr "" msgid "Expert Eagle Eye" msgstr "" msgid "Expert Necromancy" msgstr "" msgid "Advanced Estates" msgstr "" msgid "Expert Estates" msgstr "" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "" msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" msgid "All of the creatures may offer to join the hero." msgstr "" msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "" msgid "%{skill} allows the hero to learn third level spells." msgstr "" msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" msgid "%{skill} allows the hero to learn fifth level spells." msgstr "" msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "%{skill} increases the hero's luck by %{count}." msgstr "" msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" msgid "Blue" msgstr "Albastru" msgid "Green" msgstr "Verde" msgid "Red" msgstr "RoÈ™u" msgid "Yellow" msgstr "Galben" msgid "Orange" msgstr "Portocaliu" msgid "Purple" msgstr "Mov" msgid "barrier|Aqua" msgstr "" msgid "barrier|Blue" msgstr "Albastru" msgid "barrier|Brown" msgstr "Maro" msgid "barrier|Gold" msgstr "Auriu" msgid "barrier|Green" msgstr "Verde" msgid "barrier|Orange" msgstr "Portocaliu" msgid "barrier|Purple" msgstr "Mov" msgid "barrier|Red" msgstr "RoÈ™u" msgid "tent|Aqua" msgstr "Turcoaz" msgid "tent|Blue" msgstr "Albastru" msgid "tent|Brown" msgstr "Maro" msgid "tent|Gold" msgstr "Auriu" msgid "tent|Green" msgstr "Verde" msgid "tent|Orange" msgstr "Portocaliu" msgid "tent|Purple" msgstr "Mov" msgid "tent|Red" msgstr "RoÈ™u" msgid "Experience" msgstr "" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" msgid "Hero/Stats" msgstr "Erou/Stats" msgid "Skills" msgstr "Abilități" msgid "Town/Castle" msgstr "" msgid "Garrison" msgstr "" msgid "Gold Per Day:" msgstr "Aur pe zi:" msgid "View Heroes." msgstr "" msgid "Towns/Castles" msgstr "OraÈ™e/Castele" msgid "View Towns and Castles." msgstr "" msgid "luck|Cursed" msgstr "" msgid "luck|Awful" msgstr "" msgid "luck|Bad" msgstr "" msgid "luck|Normal" msgstr "Normal" msgid "luck|Good" msgstr "" msgid "luck|Great" msgstr "" msgid "luck|Irish" msgstr "" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" msgid "morale|Treason" msgstr "" msgid "morale|Awful" msgstr "" msgid "morale|Poor" msgstr "" msgid "morale|Normal" msgstr "Normal" msgid "morale|Good" msgstr "" msgid "morale|Great" msgstr "" msgid "morale|Blood!" msgstr "" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Moralul scăzut face ca %{monster} să îngheÈ›e de panică." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Moralul scăzut face ca %{monster} să îngheÈ›e de panică." msgid "Knight" msgstr "Cavaler" msgid "Barbarian" msgstr "Barbar" msgid "Sorceress" msgstr "Vrăjitoare" msgid "Warlock" msgstr "Mag" msgid "Wizard" msgstr "Magician" msgid "Necromancer" msgstr "Necromant" msgid "Multi" msgstr "Multi" msgid "doubleLined|Knight" msgstr "Cavaler" msgid "doubleLined|Barbarian" msgstr "Barbar" msgid "doubleLined|Sorceress" msgstr "Vrăjitoare" msgid "doubleLined|Warlock" msgstr "Mag" msgid "doubleLined|Wizard" msgstr "Magician" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Necro-\n" "mant" msgid "doubleLinedRace|Multi" msgstr "Multi" msgid "doubleLinedRace|Random" msgstr "Aleatorie" msgid "speed|Standing" msgstr "" msgid "speed|Crawling" msgstr "" msgid "speed|Very Slow" msgstr "Foarte încet" msgid "speed|Slow" msgstr "ÃŽncet" msgid "speed|Average" msgstr "" msgid "speed|Fast" msgstr "Rapid" msgid "speed|Very Fast" msgstr "Foarte rapid" msgid "speed|Ultra Fast" msgstr "Ultra rapid" msgid "speed|Blazing" msgstr "" msgid "speed|Instant" msgstr "" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "" msgid "week|Rabbit" msgstr "" msgid "week|Gopher" msgstr "" msgid "week|Badger" msgstr "" msgid "week|Rat" msgstr "" msgid "week|Eagle" msgstr "" msgid "week|Weasel" msgstr "" msgid "week|Raven" msgstr "" msgid "week|Mongoose" msgstr "" msgid "week|Dog" msgstr "" msgid "week|Aardvark" msgstr "" msgid "week|Lizard" msgstr "" msgid "week|Tortoise" msgstr "" msgid "week|Hedgehog" msgstr "" msgid "week|Condor" msgstr "" msgid "week|Ant" msgstr "" msgid "week|Grasshopper" msgstr "" msgid "week|Dragonfly" msgstr "" msgid "week|Spider" msgstr "" msgid "week|Butterfly" msgstr "" msgid "week|Bumblebee" msgstr "" msgid "week|Locust" msgstr "" msgid "week|Earthworm" msgstr "" msgid "week|Hornet" msgstr "" msgid "week|Beetle" msgstr "" msgid "week|PLAGUE" msgstr "" msgid "week|Unnamed" msgstr "" msgid "Desert" msgstr "" msgid "Snow" msgstr "" msgid "Wasteland" msgstr "" msgid "Beach" msgstr "" msgid "Lava" msgstr "" msgid "Dirt" msgstr "" msgid "Grass" msgstr "" msgid "Ocean" msgstr "" msgid "maps|Small" msgstr "" msgid "maps|Medium" msgstr "" msgid "maps|Large" msgstr "" msgid "maps|Extra Large" msgstr "" msgid "maps|Custom Size" msgstr "" msgid "Ore Mine" msgstr "" msgid "Sulfur Mine" msgstr "" msgid "Crystal Mine" msgstr "" msgid "Gems Mine" msgstr "" msgid "Gold Mine" msgstr "" msgid "Mine" msgstr "mină" msgid "Burma shave." msgstr "" msgid "Next sign 50 miles." msgstr "" msgid "See Rock City." msgstr "" msgid "This space for rent." msgstr "" msgid "No object" msgstr "" msgid "Alchemist Lab" msgstr "" msgid "Sign" msgstr "" msgid "Buoy" msgstr "" msgid "Skeleton" msgstr "" msgid "Daemon Cave" msgstr "" msgid "Treasure Chest" msgstr "" msgid "Faerie Ring" msgstr "" msgid "Campfire" msgstr "" msgid "Fountain" msgstr "" msgid "Gazebo" msgstr "" msgid "Genie Lamp" msgstr "" msgid "Archer's House" msgstr "" msgid "Goblin Hut" msgstr "" msgid "Dwarf Cottage" msgstr "" msgid "Peasant Hut" msgstr "" msgid "Stables" msgstr "" msgid "Alchemist's Tower" msgstr "" msgid "Event" msgstr "" msgid "Dragon City" msgstr "" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Monster" msgstr "" msgid "Obelisk" msgstr "" msgid "Oasis" msgstr "" msgid "Resource" msgstr "Resursă" msgid "Sawmill" msgstr "" msgid "Oracle" msgstr "" msgid "Shrine of the First Circle" msgstr "" msgid "Shipwreck" msgstr "" msgid "Sea Chest" msgstr "" msgid "Desert Tent" msgstr "" msgid "Stone Liths" msgstr "" msgid "Wagon Camp" msgstr "" msgid "Hut of the Magi" msgstr "" msgid "Whirlpool" msgstr "" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Mermaid" msgstr "" msgid "Boat" msgstr "" msgid "Random Ultimate Artifact" msgstr "" msgid "Random Artifact" msgstr "" msgid "Random Resource" msgstr "Resursă aleatorie" msgid "Random Monster" msgstr "" msgid "Random Town" msgstr "" msgid "Random Castle" msgstr "" msgid "Eye of the Magi" msgstr "" msgid "Random Monster - weak" msgstr "" msgid "Random Monster - medium" msgstr "" msgid "Random Monster - strong" msgstr "" msgid "Random Monster - very strong" msgstr "" msgid "Hero" msgstr "Erou" msgid "Nothing Special" msgstr "" msgid "Mossy Rock" msgstr "" msgid "Watch Tower" msgstr "" msgid "Tree House" msgstr "" msgid "Tree City" msgstr "" msgid "Ruins" msgstr "" msgid "Fort" msgstr "" msgid "Abandoned Mine" msgstr "" msgid "Sirens" msgstr "" msgid "Standing Stones" msgstr "" msgid "Idol" msgstr "" msgid "Tree of Knowledge" msgstr "" msgid "Witch Doctor's Hut" msgstr "" msgid "Temple" msgstr "" msgid "Hill Fort" msgstr "" msgid "Halfling Hole" msgstr "" msgid "Mercenary Camp" msgstr "" msgid "Shrine of the Second Circle" msgstr "" msgid "Shrine of the Third Circle" msgstr "" msgid "City of the Dead" msgstr "" msgid "Sphinx" msgstr "" msgid "Wagon" msgstr "" msgid "Tar Pit" msgstr "" msgid "Artesian Spring" msgstr "" msgid "Troll Bridge" msgstr "" msgid "Watering Hole" msgstr "" msgid "Witch's Hut" msgstr "" msgid "Xanadu" msgstr "" msgid "Lean-To" msgstr "" msgid "Magellan's Maps" msgstr "" msgid "Flotsam" msgstr "" msgid "Derelict Ship" msgstr "" msgid "Shipwreck Survivor" msgstr "" msgid "Bottle" msgstr "" msgid "Magic Well" msgstr "" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgid "Observation Tower" msgstr "" msgid "Freeman's Foundry" msgstr "" msgid "Reefs" msgstr "" msgid "Volcano" msgstr "" msgid "Flowers" msgstr "" msgid "Rock" msgstr "" msgid "Water Lake" msgstr "" msgid "Mandrake" msgstr "" msgid "Dead Tree" msgstr "" msgid "Stump" msgstr "" msgid "Crater" msgstr "" msgid "Cactus" msgstr "" msgid "Mound" msgstr "" msgid "Dune" msgstr "" msgid "Lava Pool" msgstr "" msgid "Shrub" msgstr "" msgid "Barrow Mounds" msgstr "" msgid "Random Artifact - Treasure" msgstr "" msgid "Random Artifact - Minor" msgstr "" msgid "Random Artifact - Major" msgstr "" msgid "Barrier" msgstr "" msgid "Traveller's Tent" msgstr "" msgid "Jail" msgstr "" msgid "Fire Summoning Altar" msgstr "" msgid "Air Summoning Altar" msgstr "" msgid "Earth Summoning Altar" msgstr "" msgid "Water Summoning Altar" msgstr "" msgid "Swampy Lake" msgstr "" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "" msgid "Unknown Monster" msgstr "" msgid "Peasant" msgstr "" msgid "Peasants" msgstr "" msgid "Archer" msgstr "" msgid "Archers" msgstr "" msgid "Ranger" msgstr "" msgid "Rangers" msgstr "" msgid "Pikeman" msgstr "" msgid "Pikemen" msgstr "" msgid "Veteran Pikeman" msgstr "" msgid "Veteran Pikemen" msgstr "" msgid "Swordsman" msgstr "" msgid "Swordsmen" msgstr "" msgid "Master Swordsman" msgstr "" msgid "Master Swordsmen" msgstr "" msgid "Cavalries" msgstr "" msgid "Cavalry" msgstr "" msgid "Champion" msgstr "" msgid "Champions" msgstr "" msgid "Paladin" msgstr "" msgid "Paladins" msgstr "" msgid "Crusader" msgstr "" msgid "Crusaders" msgstr "" msgid "Goblin" msgstr "" msgid "Goblins" msgstr "" msgid "Orc" msgstr "" msgid "Orcs" msgstr "" msgid "Orc Chief" msgstr "" msgid "Orc Chiefs" msgstr "" msgid "Wolf" msgstr "" msgid "Wolves" msgstr "" msgid "Ogre" msgstr "" msgid "Ogres" msgstr "" msgid "Ogre Lord" msgstr "" msgid "Ogre Lords" msgstr "" msgid "Troll" msgstr "" msgid "Trolls" msgstr "" msgid "War Troll" msgstr "" msgid "War Trolls" msgstr "" msgid "Cyclopes" msgstr "" msgid "Cyclops" msgstr "" msgid "Sprite" msgstr "" msgid "Sprites" msgstr "" msgid "Dwarf" msgstr "" msgid "Dwarves" msgstr "" msgid "Battle Dwarf" msgstr "" msgid "Battle Dwarves" msgstr "" msgid "Elf" msgstr "" msgid "Elves" msgstr "" msgid "Grand Elf" msgstr "" msgid "Grand Elves" msgstr "" msgid "Druid" msgstr "" msgid "Druids" msgstr "" msgid "Greater Druid" msgstr "" msgid "Greater Druids" msgstr "" msgid "Unicorn" msgstr "" msgid "Unicorns" msgstr "" msgid "Phoenix" msgstr "" msgid "Phoenixes" msgstr "" msgid "Centaur" msgstr "" msgid "Centaurs" msgstr "" msgid "Gargoyle" msgstr "" msgid "Gargoyles" msgstr "" msgid "Griffin" msgstr "" msgid "Griffins" msgstr "" msgid "Minotaur" msgstr "" msgid "Minotaurs" msgstr "" msgid "Minotaur King" msgstr "" msgid "Minotaur Kings" msgstr "" msgid "Hydra" msgstr "" msgid "Hydras" msgstr "" msgid "Green Dragon" msgstr "" msgid "Green Dragons" msgstr "" msgid "Red Dragon" msgstr "" msgid "Red Dragons" msgstr "" msgid "Black Dragon" msgstr "" msgid "Black Dragons" msgstr "" msgid "Halfling" msgstr "" msgid "Halflings" msgstr "" msgid "Boar" msgstr "" msgid "Boars" msgstr "" msgid "Iron Golem" msgstr "" msgid "Iron Golems" msgstr "" msgid "Steel Golem" msgstr "" msgid "Steel Golems" msgstr "" msgid "Roc" msgstr "" msgid "Rocs" msgstr "" msgid "Mage" msgstr "" msgid "Magi" msgstr "" msgid "Archmage" msgstr "" msgid "Archmagi" msgstr "" msgid "Giant" msgstr "" msgid "Giants" msgstr "" msgid "Titan" msgstr "" msgid "Titans" msgstr "" msgid "Skeletons" msgstr "" msgid "Zombie" msgstr "" msgid "Zombies" msgstr "" msgid "Mutant Zombie" msgstr "" msgid "Mutant Zombies" msgstr "" msgid "Mummies" msgstr "" msgid "Mummy" msgstr "" msgid "Royal Mummies" msgstr "" msgid "Royal Mummy" msgstr "" msgid "Vampire" msgstr "" msgid "Vampires" msgstr "" msgid "Vampire Lord" msgstr "" msgid "Vampire Lords" msgstr "" msgid "Lich" msgstr "" msgid "Liches" msgstr "" msgid "Power Lich" msgstr "" msgid "Power Liches" msgstr "" msgid "Bone Dragon" msgstr "" msgid "Bone Dragons" msgstr "" msgid "Rogue" msgstr "" msgid "Rogues" msgstr "" msgid "Nomad" msgstr "" msgid "Nomads" msgstr "" msgid "Ghost" msgstr "" msgid "Ghosts" msgstr "" msgid "Genie" msgstr "" msgid "Genies" msgstr "" msgid "Medusa" msgstr "" msgid "Medusas" msgstr "" msgid "Earth Elemental" msgstr "" msgid "Earth Elementals" msgstr "" msgid "Air Elemental" msgstr "" msgid "Air Elementals" msgstr "" msgid "Fire Elemental" msgstr "" msgid "Fire Elementals" msgstr "" msgid "Water Elemental" msgstr "" msgid "Water Elementals" msgstr "" msgid "Random Monsters" msgstr "" msgid "Random Monster 1" msgstr "" msgid "Random Monsters 1" msgstr "" msgid "Random Monster 2" msgstr "" msgid "Random Monsters 2" msgstr "" msgid "Random Monster 3" msgstr "" msgid "Random Monsters 3" msgstr "" msgid "Random Monster 4" msgstr "" msgid "Random Monsters 4" msgstr "" msgid "Double shot" msgstr "" msgid "2-hex monster" msgstr "" msgid "Double strike" msgstr "" msgid "Double damage to Undead" msgstr "" msgid "% magic resistance" msgstr "" msgid "Immune to Mind spells" msgstr "" msgid "Immune to Elemental spells" msgstr "" msgid "Immune to Fire spells" msgstr "" msgid "Immune to Cold spells" msgstr "" msgid "Immune to " msgstr "" msgid "% immunity to %{spell} spell" msgstr "" msgid "% damage from Elemental spells" msgstr "" msgid "% damage from %{spell} spell" msgstr "" msgid "% chance to Dispel beneficial spells" msgstr "" msgid "% chance to Paralyze" msgstr "" msgid "% chance to Petrify" msgstr "" msgid "% chance to Blind" msgstr "" msgid "% chance to Curse" msgstr "" msgid "% chance to cast %{spell} spell" msgstr "" msgid "HP regeneration" msgstr "" msgid "Two hexes attack" msgstr "" msgid "Flyer" msgstr "" msgid "Always retaliates" msgstr "" msgid "Attacks all adjacent enemies" msgstr "" msgid "No melee penalty" msgstr "" msgid "Dragon" msgstr "" msgid "Undead" msgstr "" msgid "No enemy retaliation" msgstr "" msgid "HP drain" msgstr "" msgid "Cloud attack" msgstr "" msgid "Decreases enemy's morale by " msgstr "" msgid "% chance to halve enemy" msgstr "" msgid "Soul Eater" msgstr "" msgid "Elemental" msgstr "" msgid "No Morale" msgstr "" msgid "Earth creature" msgstr "" msgid "Air creature" msgstr "" msgid "Fire creature" msgstr "" msgid "Water creature" msgstr "" msgid "Double damage from Fire spells" msgstr "" msgid "Double damage from Cold spells" msgstr "" msgid "Double damage from Earth creatures" msgstr "" msgid "Double damage from Air creatures" msgstr "" msgid "Double damage from Fire creatures" msgstr "" msgid "Double damage from Water creatures" msgstr "" msgid "Lightning" msgstr "" msgid "% immunity to " msgstr "" msgid "% damage from " msgstr "" msgid "The three Anduran artifacts magically combine into one." msgstr "" msgid "View Spells" msgstr "" msgid "View %{name} Info" msgstr "" msgid "Move %{name}" msgstr "" msgid "Cannot move the Spellbook" msgstr "" msgid "This item can't be traded." msgstr "" msgid "Invalid Artifact" msgstr "" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "Ultimate Book of Knowledge" msgstr "" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "Ultimate Sword of Dominion" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "Ultimate Cloak of Protection" msgstr "" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "Ultimate Wand of Magic" msgstr "" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" msgid "Ultimate Shield" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "Ultimate Staff" msgstr "" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "" msgid "Ultimate Crown" msgstr "" msgid "Golden Goose" msgstr "" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "" msgid "Arcane Necklace of Magic" msgstr "" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" msgid "Caster's Bracelet of Magic" msgstr "" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" msgid "Mage's Ring of Power" msgstr "" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" msgid "Witch's Broach of Magic" msgstr "" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" msgid "Medal of Valor" msgstr "" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" msgid "Medal of Courage" msgstr "" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" msgid "Medal of Honor" msgstr "" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" msgid "Medal of Distinction" msgstr "" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" msgid "Fizbin of Misfortune" msgstr "" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "" msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" msgid "Thunder Mace of Dominion" msgstr "" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" msgid "Armored Gauntlets of Protection" msgstr "" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" msgid "Defender Helm of Protection" msgstr "" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" msgid "Giant Flail of Dominion" msgstr "" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" msgid "Ballista of Quickness" msgstr "" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" msgid "Stealth Shield of Protection" msgstr "" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" msgid "Dragon Sword of Dominion" msgstr "" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" msgid "Power Axe of Dominion" msgstr "" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" msgid "Divine Breastplate of Protection" msgstr "" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" msgid "Minor Scroll of Knowledge" msgstr "" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" msgid "Major Scroll of Knowledge" msgstr "" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" msgid "Superior Scroll of Knowledge" msgstr "" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" msgid "Foremost Scroll of Knowledge" msgstr "" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" msgid "Endless Sack of Gold" msgstr "" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" msgid "Endless Bag of Gold" msgstr "" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" msgid "Endless Purse of Gold" msgstr "" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" msgid "Nomad Boots of Mobility" msgstr "" msgid "The %{name} increase the hero's movement on land." msgstr "" msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" msgid "Traveler's Boots of Mobility" msgstr "" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" msgid "Lucky Rabbit's Foot" msgstr "" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" msgid "Golden Horseshoe" msgstr "" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" msgid "Gambler's Lucky Coin" msgstr "" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" msgid "Four-Leaf Clover" msgstr "" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" msgid "True Compass of Mobility" msgstr "" msgid "The %{name} increases the hero's movement on land and sea." msgstr "" msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" msgid "Sailor's Astrolabe of Mobility" msgstr "" msgid "The %{name} increases the hero's movement on sea." msgstr "" msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" msgid "Evil Eye" msgstr "" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" msgid "Enchanted Hourglass" msgstr "" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" msgid "Gold Watch" msgstr "" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "" msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" msgid "Skullcap" msgstr "" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" msgid "Ice Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" msgid "Fire Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" msgid "Lightning Helm" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" msgid "Evercold Icicle" msgstr "" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" msgid "Everhot Lava Rock" msgstr "" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" msgid "Lightning Rod" msgstr "" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" msgid "Snake-Ring" msgstr "" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" msgid "Ankh" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" msgid "Book of Elements" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" msgid "Elemental Ring" msgstr "" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" msgid "Holy Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" msgid "Pendant of Free Will" msgstr "" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" msgid "Pendant of Life" msgstr "" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "" msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" msgid "Serenity Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" msgid "Seeing-eye Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" msgid "Kinetic Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" msgid "Pendant of Death" msgstr "" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" msgid "Wand of Negation" msgstr "" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" msgid "Golden Bow" msgstr "" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" msgid "Telescope" msgstr "" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" msgid "Statesman's Quill" msgstr "" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" msgid "Wizard's Hat" msgstr "" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" msgid "Power Ring" msgstr "" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" msgid "Ammo Cart" msgstr "" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" msgid "Tax Lien" msgstr "" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" msgid "Hideous Mask" msgstr "" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" msgid "Endless Pouch of Sulfur" msgstr "" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "" msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" msgid "Endless Vial of Mercury" msgstr "" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "" msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" msgid "Endless Pouch of Gems" msgstr "" msgid "The %{name} provides %{count} unit of gems per day." msgstr "" msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" msgid "Endless Cord of Wood" msgstr "" msgid "The %{name} provides %{count} unit of wood per day." msgstr "" msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" msgid "Endless Cart of Ore" msgstr "" msgid "The %{name} provides %{count} unit of ore per day." msgstr "" msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" msgid "Endless Pouch of Crystal" msgstr "" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "" msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" msgid "Spiked Helm" msgstr "" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" msgid "Spiked Shield" msgstr "" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" msgid "White Pearl" msgstr "" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" msgid "Black Pearl" msgstr "" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" msgid "Magic Book" msgstr "" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name} rezistă la vrajă!" msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "" msgid "The reserved artifact." msgstr "" msgid "Dummy 3" msgstr "" msgid "Dummy 4" msgstr "" msgid "Spell Scroll" msgstr "Pergament magic" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" msgid "Arm of the Martyr" msgstr "" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" msgid "Breastplate of Anduran" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" msgid "Broach of Shielding" msgstr "" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" msgid "Battle Garb of Anduran" msgstr "" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" msgid "Crystal Ball" msgstr "" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" msgid "Heart of Fire" msgstr "" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" msgid "Heart of Ice" msgstr "" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" msgid "Helmet of Anduran" msgstr "" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" msgid "Holy Hammer" msgstr "" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" msgid "Legendary Scepter" msgstr "" msgid "The %{name} adds %{count} points to all attributes." msgstr "" msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" msgid "Masthead" msgstr "" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" msgid "Sphere of Negation" msgstr "" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" msgid "Staff of Wizardry" msgstr "" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} trage cu puterea de %{count} arcaÈ™i" msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" msgid "Sword Breaker" msgstr "" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "" msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" msgid "Sword of Anduran" msgstr "" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" msgid "Spade of Necromancy" msgstr "" msgid "The %{name} gives the hero increased necromancy skill." msgstr "" msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "" msgid "Mercury" msgstr "" msgid "Ore" msgstr "" msgid "Sulfur" msgstr "" msgid "Crystal" msgstr "" msgid "Gems" msgstr "" msgid "Gold" msgstr "Aur" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" msgid "Fireball" msgstr "" msgid "Fireblast" msgstr "" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "" msgid "Lightning Bolt" msgstr "" msgid "Chain Lightning" msgstr "" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" msgid "Teleport" msgstr "" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" msgid "Cure" msgstr "" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" msgid "Mass Cure" msgstr "" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" msgid "Resurrect" msgstr "" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" msgid "Resurrect True" msgstr "" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" msgid "Haste" msgstr "" msgid "Increases the speed of any creature by %{count}." msgstr "" msgid "Increases the speed of all of your creatures by %{count}." msgstr "" msgid "Mass Haste" msgstr "" msgid "Slows target to half movement rate." msgstr "" msgid "spell|Slow" msgstr "" msgid "Mass Slow" msgstr "" msgid "Slows all enemies to half movement rate." msgstr "" msgid "spell|Blind" msgstr "" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" msgid "Bless" msgstr "" msgid "Causes the selected creatures to inflict maximum damage." msgstr "" msgid "Causes all of your units to inflict maximum damage." msgstr "" msgid "Mass Bless" msgstr "" msgid "Magically increases the defense skill of the selected creatures." msgstr "" msgid "Stoneskin" msgstr "" msgid "Steelskin" msgstr "" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" msgid "Causes the selected creatures to inflict minimum damage." msgstr "" msgid "Curse" msgstr "" msgid "Causes all enemy troops to inflict minimum damage." msgstr "" msgid "Mass Curse" msgstr "" msgid "Damages all undead in the battle." msgstr "" msgid "Holy Word" msgstr "" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" msgid "Holy Shout" msgstr "" msgid "Anti-Magic" msgstr "" msgid "Prevents any magic against the selected creatures." msgstr "" msgid "Dispel Magic" msgstr "" msgid "Removes all magic spells from a single target." msgstr "" msgid "Mass Dispel" msgstr "" msgid "Removes all magic spells from all creatures." msgstr "" msgid "Causes a magic arrow to strike the selected target." msgstr "" msgid "Magic Arrow" msgstr "" msgid "Berserker" msgstr "" msgid "Causes a creature to attack its nearest neighbor." msgstr "" msgid "Armageddon" msgstr "" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" msgid "Elemental Storm" msgstr "" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" msgid "Meteor Shower" msgstr "" msgid "Paralyze" msgstr "" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" msgid "Hypnotize" msgstr "" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" msgid "Cold Ray" msgstr "" msgid "Drains body heat from a single enemy unit." msgstr "" msgid "Cold Ring" msgstr "" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" msgid "Disrupting Ray" msgstr "" msgid "Reduces the defense rating of an enemy unit by three." msgstr "" msgid "Damages all living (non-undead) units in the battle." msgstr "" msgid "Death Ripple" msgstr "" msgid "Death Wave" msgstr "" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" msgid "Dragon Slayer" msgstr "" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "" msgid "Blood Lust" msgstr "" msgid "Increases a unit's attack skill." msgstr "" msgid "Animate Dead" msgstr "" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" msgid "Mirror Image" msgstr "" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" msgid "Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Mass Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Summon Earth Elemental" msgstr "" msgid "Summons Earth Elementals to fight for your army." msgstr "" msgid "Summon Air Elemental" msgstr "" msgid "Summons Air Elementals to fight for your army." msgstr "" msgid "Summon Fire Elemental" msgstr "" msgid "Summons Fire Elementals to fight for your army." msgstr "" msgid "Summon Water Elemental" msgstr "" msgid "Summons Water Elementals to fight for your army." msgstr "" msgid "Damages castle walls." msgstr "" msgid "Earthquake" msgstr "" msgid "Causes all mines across the land to become visible." msgstr "" msgid "View Mines" msgstr "" msgid "Causes all resources across the land to become visible." msgstr "" msgid "View Resources" msgstr "" msgid "Causes all artifacts across the land to become visible." msgstr "" msgid "View Artifacts" msgstr "" msgid "Causes all towns and castles across the land to become visible." msgstr "" msgid "View Towns" msgstr "" msgid "Causes all Heroes across the land to become visible." msgstr "" msgid "View Heroes" msgstr "" msgid "Causes the entire land to become visible." msgstr "" msgid "View All" msgstr "" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" msgid "Summon Boat" msgstr "" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" msgid "Allows the caster to magically transport to a nearby location." msgstr "" msgid "Dimension Door" msgstr "" msgid "Returns the caster to any town or castle currently owned." msgstr "" msgid "Town Gate" msgstr "" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" msgid "Visions" msgstr "" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" msgid "Haunt" msgstr "" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" msgid "Set Earth Guardian" msgstr "" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Air Guardian" msgstr "" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Fire Guardian" msgstr "" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Water Guardian" msgstr "" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" msgid "Random Spell" msgstr "Vrajă aleatorie" msgid "Randomly selected spell of any level." msgstr "" msgid "Random 1st Level Spell" msgstr "" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" msgid "No spell to cast." msgstr "Nicio vrajă disponibilă." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "" msgid "View Adventure Spells" msgstr "" msgid "View Combat Spells" msgstr "" msgid "View previous page" msgstr "" msgid "View next page" msgstr "" msgid "Close Spellbook" msgstr "" msgid "View %{spell}" msgstr "" msgid "This spell does %{damage} points of damage." msgstr "" msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" msgid "This spell restores %{hp} HP." msgstr "" msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" msgid "The nearest town is %{town}." msgstr "" msgid "This town is occupied by your hero %{hero}." msgstr "" msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" msgid "The ultimate artifact is really the %{name}." msgstr "" msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" msgid "north-west" msgstr "" msgid "north" msgstr "" msgid "north-east" msgstr "" msgid "west" msgstr "" msgid "center" msgstr "" msgid "east" msgstr "" msgid "south-west" msgstr "" msgid "south" msgstr "" msgid "south-east" msgstr "" msgid "The truth is out there." msgstr "" msgid "The dark side is stronger." msgstr "" msgid "The end of the world is near." msgstr "" msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" msgid "A Black Dragon will take out a Titan any day of the week." msgstr "" msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" msgid "An unknown force is being resurrected..." msgstr "" msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "VerificaÈ›i cea mai nouă versiune a jocului la\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Enable auto combat" #~ msgstr "Activează lupta automată" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "terminaÈ›i lupta în mod automat" fheroes2-1.1.6+dfsg/files/lang/ru.po000066400000000000000000014762531476115357100172200ustar00rootroot00000000000000# Russian translation of fheroes2 # Copyright (C) 2021 - 2024 fheroes2 team # Copyright (C) 2009 Igor Orlov # Copyright (C) 2009 Andrey Afletdinov # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-12-27 20:34+0300\n" "Last-Translator: fheroes2 team \n" "Language-Team: <>\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-Launchpad-Export-Date: 2013-10-09 02:01+0000\n" "X-Generator: Poedit 3.5\n" msgid "" "NEW\n" "GAME" msgstr "" "ÐОВÐЯ\n" "ИГРÐ" msgid "" "SAVE\n" "GAME" msgstr "" " СОХРÐ-\n" "ÐИТЬ\n" "ИГРУ" msgid "" "LOAD\n" "GAME" msgstr "" " ЗÐГРУ-\n" "ЗИТЬ\n" "ИГРУ" msgid "INFO" msgstr "" " СЦЕÐÐ-\n" "РИЙ" msgid "QUIT" msgstr "ВЫЙТИ" msgid "" "NEW\n" "MAP" msgstr "" "ÐОВÐЯ\n" "КÐРТÐ" msgid "" "SAVE\n" "MAP" msgstr "" " СОХРÐ-\n" "ÐИТЬ\n" "КÐРТУ" msgid "" "LOAD\n" "MAP" msgstr "" " ЗÐГРУ-\n" "ЗИТЬ\n" "КÐРТУ" msgid "CANCEL" msgstr "ОТМЕÐÐ" msgid "OKAY" msgstr "ОК" msgid "ACCEPT" msgstr "ПРИÐЯТЬ" msgid "DECLINE" msgstr "ОТКЛОÐИТЬ" msgid "LEARN" msgstr "ИЗУЧИТЬ" msgid "TRADE" msgstr "МЕÐЯТЬ" msgid "YES" msgstr "ДÐ" msgid "NO" msgstr "ÐЕТ" msgid "EXIT" msgstr "ВЫЙТИ" msgid "smallerButton|EXIT" msgstr "ВЫЙТИ" msgid "DISMISS" msgstr "УВОЛИТЬ" msgid "UPGRADE" msgstr "УЛУЧШИТЬ" msgid "RESTART" msgstr "СÐÐЧÐЛÐ" msgid "HEROES" msgstr "ГЕРОИ" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "ГОРОДÐ/\n" "ЗÐМКИ" msgid "S" msgstr "М" msgid "M" msgstr "С" msgid "L" msgstr "Б" msgid "X-L" msgstr "О-Б" msgid "ALL" msgstr "ВСЕ" msgid "SELECT" msgstr "ВЫБОР" msgid "" "STANDARD\n" "GAME" msgstr "" "ОБЫЧÐÐЯ\n" "ИГРÐ" msgid "" "BATTLE\n" "ONLY" msgstr "БИТВÐ" msgid "" "CAMPAIGN\n" "GAME" msgstr "КÐМПÐÐИЯ" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "СОВМЕСТÐÐЯ\n" "ИГРÐ" msgid "CONFIG" msgstr "ÐÐСТРОЙКИ" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ВОЙÐЫ ЗÐ\n" "ПРЕСТОЛ" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "ЦЕÐÐ\n" "ВЕРÐОСТИ" msgid "HOT SEAT" msgstr "" "ЗРОДÐОЙ\n" "МÐШИÐОЙ" msgid "2 PLAYERS" msgstr "2 ИГРОКÐ" msgid "3 PLAYERS" msgstr "3 ИГРОКÐ" msgid "4 PLAYERS" msgstr "4 ИГРОКÐ" msgid "5 PLAYERS" msgstr "5 ИГРОКОВ" msgid "6 PLAYERS" msgstr "6 ИГРОКОВ" msgid "GIFT" msgstr "ОТДÐТЬ" msgid "MAX" msgstr "МÐКС" msgid "DIFFICULTY" msgstr "СЛОЖÐОСТЬ" msgid "VIEW INTRO" msgstr "ВСТУПЛЕÐИЕ" msgid "MIN" msgstr "МИÐ" msgid "RESET" msgstr "СБРОС" msgid "START" msgstr "ÐÐЧÐТЬ" msgid "TOWN" msgstr "ГОРОД" msgid "CASTLE" msgstr "ЗÐМОК" msgid "RESTRICT" msgstr "ЗÐПРЕТ" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "У\n" "Ð’\n" "О\n" "Л\n" "И\n" "Т\n" "Ь" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "Ð’\n" "Ы\n" "Й\n" "Т\n" "И" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "П\n" "Ð\n" "Т\n" "Р\n" "У\n" "Л\n" "Ь" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "К\n" "Ð\n" "М\n" "П\n" "Ð\n" "Ð\n" "И\n" "Я" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "О\n" "Б\n" "Ы\n" "Ч\n" "Ð\n" "Ð\n" "Я" msgid "RUMORS" msgstr "СЛУХИ" msgid "EVENTS" msgstr "СОБЫТИЯ" msgid "LANGUAGE" msgstr "ЯЗЫК" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Воин" msgid "Builder" msgstr "Строитель" msgid "Explorer" msgstr "Разведчик" msgid "None" msgstr "ОтÑутÑтвуют" msgid "" "A few\n" "%{monster}" msgstr "" "Мало\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "ÐеÑколько\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Группа\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Много\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Орда\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Сотни\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Туча\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Тьма\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Легион\n" "%{monster}" msgid "army|Few" msgstr "Мало" msgid "army|Several" msgstr "ÐеÑколько" msgid "army|Pack" msgstr "Группа" msgid "army|Lots" msgstr "Много" msgid "army|Horde" msgstr "Орда" msgid "army|Throng" msgstr "Сотни" msgid "army|Swarm" msgstr "Туча" msgid "army|Zounds" msgstr "Тьма" msgid "army|Legion" msgstr "Легион" msgid "All %{race} troops +1" msgstr "Ð’Ñе ÑущеÑтва одной фракции +1" msgid "NeutralRaceTroops|Neutral" msgstr "Ðейтральные" msgid "Troops of %{count} alignments -%{penalty}" msgstr "СущеÑтва %{count} разных фракций -%{penalty}" msgid "Some undead in army -1" msgstr "Ðежить в армии -1" msgid "" "Default\n" "troop" msgstr "" "ОтрÑд\n" "по умол-\n" "чанию" msgid "View %{name}" msgstr "ПроÑмотреть %{name}" msgid "Move the %{name} " msgstr "ПеремеÑтить %{name} " msgid "Move or right click to redistribute %{name}" msgstr "%{name}: перемеcтить или разделить (правой кнопкой)" msgid "Combine %{name} armies" msgstr "%{name}: объединить или разделить (правой кнопкой)" msgid "Exchange %{name2} with %{name}" msgstr "%{name2} и %{name}: поменÑть меÑтами" msgid "Select %{name}" msgstr "Выбрать %{name}" msgid "Cannot move last troop" msgstr "Ðевозможно перемеÑтить поÑледний отрÑд" msgid "Move the %{name}" msgstr "ПеремеÑтить %{name}" msgid "Set %{monster} Count" msgstr "%{monster}: введите количеÑтво" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} убивает половину вражеÑкого отрÑда!" msgstr[1] "%{name} убивают половину вражеÑкого отрÑда!" msgstr[2] "%{name} убивают половину вражеÑкого отрÑда!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} выключил автобитву" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} включил автобитву" msgid "Spell failed!" msgstr "Ðеудачный вызов магии!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Сфера ÐžÑ‚Ñ€Ð¸Ñ†Ð°Ð½Ð¸Ñ Ð»Ð¸ÑˆÐ¸Ð»Ð° возможноÑти иÑпользовать любые Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð² битве." msgid "You cannot cast spells without a commanding hero." msgstr "Ð’Ñ‹ не можете произноÑить Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð±ÐµÐ· Ð³ÐµÑ€Ð¾Ñ Ð½Ð° Вашей Ñтороне." msgid "You have already cast a spell this round." msgstr "Ð’Ñ‹ уже иÑпользовали магию на Ñтом ходу." msgid "That spell will have no effect!" msgstr "Это заклинание не подейÑтвует!" msgid "You may only summon one type of elemental per combat." msgstr "Ð’ Ñражении Ð’Ñ‹ можете призвать Ñлементалей только одного типа." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "Ð”Ð»Ñ Ð²Ñ‹Ð·Ð¾Ð²Ð° Ñлементалей у Ð’Ð°Ñ Ð½ÐµÑ‚ Ñвободного проÑтранÑтва возле героÑ." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Ров уменьшает на -%{count} навык обороны любого отрÑда и ограничивает " "дальноÑть его передвижениÑ." msgid "Speed: %{speed}" msgstr "СкороÑть: %{speed}" msgid "Speed" msgstr "СкороÑть" msgid "Off" msgstr "Выкл." msgid "On" msgstr "Вкл." msgid "Turn Order" msgstr "ПорÑдок дейÑтвий" msgid "Auto Spell Casting" msgstr "ÐœÐ°Ð³Ð¸Ñ Ð² автобитве" msgid "Grid" msgstr "Сетка" msgid "Shadow Movement" msgstr "Затенение Ñетки" msgid "Shadow Cursor" msgstr "КурÑор Ñ Ñ‚ÐµÐ½ÑŒÑŽ" msgid "Audio" msgstr "Звук" msgid "Settings" msgstr "ÐаÑтройки" msgid "Configure" msgstr "ÐаÑтроить" msgid "Hot Keys" msgstr "ГорÑчие клавиши" msgid "Damage Info" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ð± уроне" msgid "Set the speed of combat actions and animations." msgstr "УÑтановить ÑкороÑть дейÑтвий и анимации ÑущеÑтв в бою." msgid "Toggle to display the turn order during the battle." msgstr "Включить/выключить показ порÑдка дейÑтвий отрÑдов в бою." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Включить/выключить иÑпользование заклинаний компьютером в режиме автобитвы. " "(Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð½Ðµ влиÑет на иÑпользование заклинаний компьютерным игроком и на " "режим быÑтрой битвы.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Отобразить/Ñкрыть Ñетку Ð¿Ð¾Ð»Ñ Ð±Ð¾Ñ. Ð’Ñе Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð½Ð° поле Ð±Ð¾Ñ Ð¿Ñ€Ð¾Ð¸ÑходÑÑ‚ по " "гекÑагональной Ñетке. Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð²Ð»Ð¸Ñет лишь на внешний вид Ð¿Ð¾Ð»Ñ Ð±Ð¾Ñ." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Включить/выключить выделение облаÑти Ð¿Ð¾Ð»Ñ Ð±Ð¾Ñ, доÑтупной Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¸ " "атаки ÑущеÑтвом." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Включить/выключить отриÑовку тени под курÑором на гекÑагональной Ñетке." msgid "Change the audio settings of the game." msgstr "ÐаÑтроить параметры аудио." msgid "Check and configure all the hot keys present in the game." msgstr "Проверить и наÑтроить вÑе горÑчие клавиши, имеющиеÑÑ Ð² игре." msgid "Toggle to display damage information during the battle." msgstr "Включить/выключить отображение информации об уроне во Ð²Ñ€ÐµÐ¼Ñ Ð±Ð¸Ñ‚Ð²Ñ‹." msgid "Exit this menu." msgstr "Выход из меню." msgid "Okay" msgstr "ПринÑть" msgid "The enemy has surrendered!" msgstr "Враг капитулировал!" msgid "Their cowardice costs them %{gold} gold." msgstr "ТруÑоÑть Ñтоила противнику %{gold} золота." msgid "The enemy has fled!" msgstr "Враг Ñбежал!" msgid "A glorious victory!" msgstr "БлиÑÑ‚Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¿Ð¾Ð±ÐµÐ´Ð°!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "За доблеÑть в бою %{name} получает %{exp} опыта." msgid "The cowardly %{name} flees from battle." msgstr "СтруÑив, %{name} бежит Ñ Ð¿Ð¾Ð»Ñ Ð±Ð¸Ñ‚Ð²Ñ‹." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} ÑдаётÑÑ Ð²Ñ€Ð°Ð³Ñƒ и уходит Ñ Ð¿Ð¾Ð·Ð¾Ñ€Ð¾Ð¼." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Ваши войÑка потерпели поражение и %{name} покидает ВаÑ." msgid "Your forces suffer a bitter defeat." msgstr "Ваши войÑка потерпели поражение." msgid "Battlefield Casualties" msgstr "Потери на поле боÑ:" msgid "Attacker" msgstr "Ðападавший" msgid "Defender" msgstr "ОборонÑвшийÑÑ" msgid "Click to leave the battle results." msgstr "Ðажмите, чтобы закрыть результаты битвы." msgid "Click to restart the battle in manual mode." msgstr "Ðажмите, чтобы перезапуÑтить битву в ручном режиме." msgid "Restart" msgstr "Ðачать Ñначала" msgid "You have captured an enemy artifact!" msgstr "Ð’Ñ‹ захватили вражеÑкий артефакт!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "" "Когда Ð’Ñ‹ притрагиваетеÑÑŒ к артефакту %{name}, он таинÑтвенным образом " "иÑчезает." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "" "Когда Ваш враг притрагиваетÑÑ Ðº артефакту %{name}, тот таинÑтвенным образом " "иÑчезает." msgid "Necromancy!" msgstr "ÐекромантиÑ!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "ÐŸÑ€Ð°ÐºÑ‚Ð¸ÐºÑƒÑ Ñ‚Ñ‘Ð¼Ð½Ð¾Ðµ иÑкуÑÑтво некромантии, Ð’Ñ‹ оживлÑете\n" "%{count} мёртвых ÑущеÑтв противника, которые будут Ñлужить Вам как " "%{monster}." msgid "%{name} the %{race}" msgstr "%{name} %{race}" msgid "Captain of %{name}" msgstr "Капитан замка %{name}." msgid "Attack" msgstr "Ðтака" msgid "Defense" msgstr "Защита" msgid "Spell Power" msgstr "Сила магии" msgid "Knowledge" msgstr "ЗнаниÑ" msgid "Morale" msgstr "Мораль" msgid "Luck" msgstr "Удача" msgid "Spell Points" msgstr "Очки магии" msgid "Hero's Options" msgstr "ВозможноÑти героÑ" msgid "Cast Spell" msgstr "ПроизнеÑти заклинание" msgid "Retreat" msgstr "ОтÑтупить" msgid "Surrender" msgstr "СдатьÑÑ" msgid "Cancel" msgstr "Отмена" msgid "Hero Screen" msgstr "Экран героÑ" msgid "Captain's Options" msgstr "ВозможноÑти капитана замка" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "МагичеÑкое заклинание. Ð’Ñ‹ можете произноÑить только одно заклинание в " "течение раунда. Ðовый раунд начинаетÑÑ Ð¿Ð¾Ñле того, как каждое ÑущеÑтво " "Ñделает ход." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "ОтÑтупить героем, броÑив Ваших ÑущеÑтв на произвол Ñудьбы. Ð’Ñ‹ Ñможете нанÑть " "Ñтого Ð³ÐµÑ€Ð¾Ñ Ñнова, но Ñ Ð²Ð¾Ð¹Ñком, ÑоответÑтвующим герою-новичку." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "КапитулÑÑ†Ð¸Ñ Ñтоит золота. Однако, еÑли Ð’Ñ‹ заплатите выкуп, Ð³ÐµÑ€Ð¾Ñ Ð¼Ð¾Ð¶Ð½Ð¾ будет " "нанÑть вмеÑте Ñо вÑеми выжившими ÑущеÑтвами. СтоимоÑть капитулÑции " "ÑоÑтавлÑет половину ÑтоимоÑти ÑущеÑтв, оÑтающихÑÑ Ð² армии, за иÑключением " "призванных ÑущеÑтв." msgid "Open Hero Screen to view full information about the hero." msgstr "Открыть Ñкран Ñ Ð¿Ð¾Ð´Ñ€Ð¾Ð±Ð½Ð¾Ð¹ информацией о герое." msgid "Return to the battle." msgstr "ВернутьÑÑ Ðº Ñражению." msgid "Not enough gold (%{gold})" msgstr "Ðе хватает %{gold} золота" msgid "%{name} states:" msgstr "%{name} объÑвлÑет:" msgid "Captain of %{name} states:" msgstr "Капитан замка %{name} объÑвлÑет:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Я приму твою капитулÑцию и предоÑтавлю безопаÑный проход тебе и твоим " "войÑкам за %{price} золотом.\"" msgid "View %{monster} info" msgstr "Показать информацию Ð´Ð»Ñ %{monster}" msgid "Fly %{monster} here" msgstr "%{monster}: лететь Ñюда" msgid "Move %{monster} here" msgstr "%{monster}: идти Ñюда" msgid "Shoot %{monster}" msgstr "СтрелÑть в %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(ещё %{count} выÑтрел)" msgstr[1] "(ещё %{count} выÑтрела)" msgstr[2] "(ещё %{count} выÑтрелов)" msgid "Attack %{monster}" msgstr "Ðтаковать %{monster}" msgid "Turn %{turn}" msgstr "Раунд %{turn}" msgid "Teleport here" msgstr "ТелепортироватьÑÑ Ñюда" msgid "Invalid teleport destination" msgstr "ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñ†ÐµÐ»ÑŒ телепорта" msgid "Cast %{spell} on %{monster}" msgstr "Применить \"%{spell}\" (цель: %{monster})" msgid "Cast %{spell}" msgstr "ПроизнеÑти \"%{spell}\"" msgid "Select spell target" msgstr "Выберите цель заклинаниÑ" msgid "View Ballista info" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ баллиÑте" msgid "Ballista" msgstr "БаллиÑта" #, fuzzy msgid "Automatic combat modes" msgstr "Ðвтобитва" #, fuzzy msgid "Automatic Combat Modes" msgstr "Ðвтобитва" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Изменить наÑтройки ÑиÑтемы" msgid "Allows you to customize the combat screen." msgstr "ПозволÑет Вам наÑтраивать отображение боÑ." msgid "System Options" msgstr "Параметры ÑиÑтемы" msgid "Skip this unit" msgstr "ПропуÑтить ход" msgid "Skip" msgstr "ПропуÑтить" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "ПропуÑтить ход Ð´Ð»Ñ Ñ‚ÐµÐºÑƒÑ‰ÐµÐ³Ð¾ отрÑда. ОтрÑд пропуÑкает ход до начала " "Ñледующего раунда." msgid "View Captain's options" msgstr "ПоÑмотреть возможноÑти капитана" msgid "View Hero's options" msgstr "ПоÑмотреть возможноÑти героÑ" msgid "View opposing Captain" msgstr "ПоÑмотреть вражеÑкого капитана" msgid "View opposing Hero" msgstr "ПроÑмотреть вражеÑкого героÑ" msgid "Hide logs" msgstr "СпрÑтать журнал" msgid "Show logs" msgstr "Показать журнал" msgid "Message Bar" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¾Ð½Ð½Ð°Ñ Ñтрока" msgid "Shows the results of individual monster's actions." msgstr "ЗдеÑÑŒ отображаютÑÑ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ñ‹ дейÑтвий отдельных отрÑдов." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Ð’Ñ‹ дейÑтвительно хотите включить автобитву?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Ð’Ñ‹ уверены, что хотите закончить битву в авторежиме?" #, fuzzy msgid "The computer continues the combat for you." msgstr "ПозволÑет компьютеру ÑражатьÑÑ Ð·Ð° ВаÑ." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Ðвтобитва" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Ðвтобитва" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} пропуÑкает Ñвой ход." msgstr[1] "%{name} пропуÑкают Ñвой ход." msgstr[2] "%{name} пропуÑкают Ñвой ход." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} наноÑит %{damage} урона." msgstr[1] "%{attacker} наноÑÑÑ‚ %{damage} урона." msgstr[2] "%{attacker} наноÑÑÑ‚ %{damage} урона." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "%{count} ÑущеÑтво погибло." msgstr[1] "%{count} ÑущеÑтва погибли." msgstr[2] "%{count} ÑущеÑтв погибли." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "%{count} %{defender} погиб." msgstr[1] "%{count} %{defender} погибли." msgstr[2] "%{count} %{defender} погибли." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "%{count} душа поглощена." msgstr[1] "%{count} души поглощено." msgstr[2] "%{count} душ поглощено." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "%{count} %{unit} воÑкреÑ." msgstr[1] "%{count} %{unit} воÑкреÑли." msgstr[2] "%{count} %{unit} воÑкреÑли." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "%{monster}: перемещение Ñ [%{src}] на [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} ÑопротивлÑетÑÑ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸ÑŽ!" msgstr[1] "%{name} ÑопротивлÑÑŽÑ‚ÑÑ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸ÑŽ!" msgstr[2] "%{name} ÑопротивлÑÑŽÑ‚ÑÑ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸ÑŽ!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name}: наложение \"%{spell}\" на цель: %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name}: применение \"%{spell}\"." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "Заклинание \"%{spell}\" наноÑит %{damage} урона одной нежити." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "Заклинание \"%{spell}\" наноÑит %{damage} урона вÑей нежити." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "" "Заклинание \"%{spell}\" наноÑит %{damage} урона, %{count} ÑущеÑтв погибают." msgid "The %{spell} does %{damage} damage." msgstr "Заклинание \"%{spell}\" наноÑит %{damage} урона." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "" "Заклинание \"%{spell}\" наноÑит %{damage} урона одному живому ÑущеÑтву." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "Заклинание \"%{spell}\" наноÑит %{damage} урона вÑем живым ÑущеÑтвам." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "%{target} теперь под Ñффектом оÑлеплениÑ!" msgstr[1] "%{target} теперь под Ñффектом оÑлеплениÑ!" msgstr[2] "%{target} теперь под Ñффектом оÑлеплениÑ!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "%{target} теперь под Ñффектом окаменениÑ!" msgstr[1] "%{target} теперь под Ñффектом окаменениÑ!" msgstr[2] "%{target} теперь под Ñффектом окаменениÑ!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "%{target} теперь под влиÑнием проклÑтиÑ!" msgstr[1] "%{target} теперь под влиÑнием проклÑтиÑ!" msgstr[2] "%{target} теперь под влиÑнием проклÑтиÑ!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{target} теперь под Ñффектом паралича!" msgstr[1] "%{target} теперь под Ñффектом паралича!" msgstr[2] "%{target} теперь под Ñффектом паралича!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "СнÑты хорошие чары Ñ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð½Ð¸ÐºÐ° \"%{target}\"!" msgstr[1] "СнÑты хорошие чары Ñ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð½Ð¸ÐºÐ° \"%{target}\"!" msgstr[2] "СнÑты хорошие чары Ñ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð½Ð¸ÐºÐ° \"%{target}\"!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} накладывает \"%{spell}\" на цель ( %{target} )!" msgstr[1] "%{attacker} накладывают \"%{spell}\" на цель ( %{target} )!" msgstr[2] "%{attacker} накладывают \"%{spell}\" на цель ( %{target} )!" msgid "Bad luck descends on the %{attacker}." msgstr "Удача отвернулаÑÑŒ от %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "Удача улыбнулаÑÑŒ %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Ð‘Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ñ Ð²Ñ‹Ñокой морали %{monster} атакуют ещё раз." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Из-за низкой морали %{monster} заÑтыли в панике." msgid "%{tower} does %{damage} damage." msgstr "Ð‘Ð°ÑˆÐ½Ñ \"%{tower}\" наноÑит %{damage} урона." msgid "The mirror image is created." msgstr "Фантомный отрÑд Ñоздан!" msgid "The mirror image is destroyed!" msgstr "Фантомный отрÑд уничтожен!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Ð’Ñ‹ дейÑтвительно хотите прервать автобитву?" msgid "Error" msgstr "Ошибка" msgid "No spells to cast." msgstr "Ðет заклинаний." msgid "Are you sure you want to retreat?" msgstr "Ð’Ñ‹ дейÑтвительно хотите отÑтупить?" msgid "Retreat disabled" msgstr "ÐÐµÐ»ÑŒÐ·Ñ Ð¾Ñ‚Ñтупить" msgid "Surrender disabled" msgstr "ÐÐµÐ»ÑŒÐ·Ñ ÑдатьÑÑ" msgid "Damage: %{max}" msgstr "Урон: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Урон: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Погибнет: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Погибнет: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Ð‘Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ñ Ð¾Ñ€Ð»Ð¸Ð½Ð¾Ð¼Ñƒ взору, %{name} Ñмог выучить заклинание \"%{spell}\"." msgid "Human" msgstr "Человек" msgid "AI" msgstr "Компьютер" msgid "Start" msgstr "Ðачать" msgid "Start the battle." msgstr "Ðачать битву." msgid "Exit" msgstr "Закрыть" msgid "Reset" msgstr "СброÑить" msgid "Reset to default settings." msgstr "СброÑить до значений по умолчанию." msgid "Please select another hero." msgstr "ПожалуйÑта, выберите другого героÑ." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} против %{race2} %{name2}" msgid "Monsters" msgstr "СущеÑтва" msgid "N/A" msgstr "Ð/Д" msgid "Left Turret" msgstr "Ð›ÐµÐ²Ð°Ñ Ð±Ð°ÑˆÐ½Ñ" msgid "Right Turret" msgstr "ÐŸÑ€Ð°Ð²Ð°Ñ Ð±Ð°ÑˆÐ½Ñ" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} ÑтрелÑет Ñилой %{count} лучников" msgid "each with a +%{attack} bonus to their attack skill." msgstr "каждый Ñ Ð±Ð¾Ð½ÑƒÑом +%{attack} к Ñвоему навыку атаки." msgid "The %{name} is destroyed." msgstr "%{name} уничтожена!" msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} воÑкреÑает из мёртвых!" msgstr[1] "%{count} %{name} воÑкреÑают из мёртвых!" msgstr[2] "%{count} %{name} воÑкреÑают из мёртвых!" msgid "Dwarven Alliance" msgstr "ÐльÑÐ½Ñ Ð³Ð½Ð¾Ð¼Ð¾Ð²" msgid "Sorceress Guild" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð²Ð¾Ð»ÑˆÐµÐ±Ð½Ð¸Ñ†" msgid "Necromancer Guild" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚Ð¾Ð²" msgid "Ogre Alliance" msgstr "ÐльÑÐ½Ñ Ð¾Ð³Ñ€Ð¾Ð²" msgid "Dwarfbane" msgstr "Погибель гномов" msgid "Dragon Alliance" msgstr "ÐльÑÐ½Ñ Ð´Ñ€Ð°ÐºÐ¾Ð½Ð¾Ð²" msgid "Elven Alliance" msgstr "ÐльÑÐ½Ñ Ñльфов" msgid "Kraeger defeated" msgstr "Крейгер побеждён" msgid "Wayward Son" msgstr "Блудный Ñын" msgid "Uncle Ivan" msgstr "ДÑÐ´Ñ Ð’Ð°Ð½Ñ" msgid "Annexation" msgstr "ÐннекÑиÑ" msgid "Force of Arms" msgstr "Сила оружиÑ" msgid "Save the Dwarves" msgstr "СпаÑите гномов" msgid "Carator Mines" msgstr "Копи Каратора" msgid "Turning Point" msgstr "Переломный момент" msgid "scenarioName|Defender" msgstr "Защитник" msgid "Corlagon's Defense" msgstr "Защита Корлагона" msgid "The Crown" msgstr "Корона" msgid "The Gauntlet" msgstr "Перчатка" msgid "Betrayal" msgstr "ПредательÑтво" msgid "Final Justice" msgstr "Ðкт отчаÑниÑ" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Прежде чем поднÑть воÑÑтание против брата, Роланд хочет, чтобы Ð’Ñ‹ одержали " "победу над окреÑтными лордами. Между ними нет единÑтва, поÑтому большую " "чаÑть времени они будут занÑты Ñтычками друг Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¼. Победа будет Вашей, " "когда Ð’Ñ‹ захватите вÑе города." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Лорды пограничных земель отказываютÑÑ Ð¿Ñ€Ð¸Ð½ÐµÑти клÑтву верноÑти Роланду, а " "значит должны быть повержены. БогатÑтва и влаÑти им не занимать, поÑтому " "будьте готовы к нелёгкой борьбе. Чтобы победить, захватите вÑе вражеÑкие " "замки." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Ваша задача защитить гномов от Ñил Ðрчибальда. Захватите вÑе вражеÑкие " "города и замки, чтобы победить, и не дайте врагу захватить Ñразу вÑе города " "гномов, иначе он одержит победу." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Ð’Ñ‹ ÑтолкнетеÑÑŒ Ñ Ñ‡ÐµÑ‚Ñ‹Ñ€ÑŒÐ¼Ñ Ð²Ñ€Ð°Ð³Ð°Ð¼Ð¸-Ñоюзниками в прÑмой борьбе за реÑурÑÑ‹ и " "Ñокровища. Захватите вÑе вражеÑкие замки Ð´Ð»Ñ Ð¿Ð¾Ð±ÐµÐ´Ñ‹." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Ваши враги объединены против Ð’Ð°Ñ Ð¸ находÑÑ‚ÑÑ Ñ€Ñдом, так что будьте готовы к " "боевым дейÑтвиÑм. Вам нужно будет завладеть вÑеми Ñ‡ÐµÑ‚Ñ‹Ñ€ÑŒÐ¼Ñ Ð·Ð°Ð¼ÐºÐ°Ð¼Ð¸ в Ñтой " "маленькой долине, чтобы выиграть." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð²Ð¾Ð»ÑˆÐµÐ±Ð½Ð¸Ñ† ÐораÑтона обратилаÑÑŒ к Роланду Ñ Ð¿Ñ€Ð¾Ñьбой о помощи в " "защите от Ð½Ð°Ð¿Ð°Ð´ÐµÐ½Ð¸Ñ Ñоюзников Ðрчибальда. Захватите вÑе вражеÑкие замки, " "чтобы выиграть, и не потерÑйте ÐораÑтон, иначе Ð’Ñ‹ проиграете Ñценарий. " "(ПодÑказка: Ðа оÑтрове в океане еÑть вражеÑкий замок.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Соберите как можно больше армии, и захватите вражеÑкий замок в течение 8 " "недель. Вам противоÑтоит только один враг, но Вам нужно пройти долгий путь, " "чтобы добратьÑÑ Ð´Ð¾ вражеÑкого замка. Ð’Ñе войÑка в Вашей армии в конце Ñтого " "ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ Ñ Ð’Ð°Ð¼Ð¸ в финальной битве." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Ðайдите корону до того, как герои Ðрчибальда найдут её. Корона понадобитÑÑ " "Роланду Ð´Ð»Ñ Ñ„Ð¸Ð½Ð°Ð»ÑŒÐ½Ð¾Ð¹ битвы против Ðрчибальда." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Три объединённых врага ÑтоÑÑ‚ между Вами и победой, в их Ñ€Ñдах лорд Корлагон. " "Роланд находитÑÑ Ð² замке на Ñеверо-западе, и Ð’Ñ‹ проиграете, еÑли его возьмут " "в плен. Помните, что еÑли Ð’Ñ‹ одолеете лорда Корлагона, он не будет ÑражатьÑÑ " "против Ð’Ð°Ñ Ð² финальном Ñценарии." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Это поÑледнÑÑ Ð±Ð¸Ñ‚Ð²Ð°. И Ð’Ñ‹, и Ваш враг вооружены до зубов, и вÑе враги в " "Ñоюзе против ВаÑ. Захватите Ðрчибальда, чтобы положить конец войне!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "ПереметнётеÑÑŒ на Ñторону противника, и окажетеÑÑŒ Ñ Ñ‚Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¼ÐºÐ°Ð¼Ð¸ против " "одного. Эта битва будет Ñамой лёгкой из тех, что предÑтоÑÑ‚ до конца войны... " "изменник." msgid "Barbarian Wars" msgstr "Войны варваров" msgid "First Blood" msgstr "ÐŸÐµÑ€Ð²Ð°Ñ ÐºÑ€Ð¾Ð²ÑŒ" msgid "Necromancers" msgstr "Ðекроманты" msgid "Slay the Dwarves" msgstr "Уничтожь гномов" msgid "Country Lords" msgstr "Лорды провинций" msgid "Dragon Master" msgstr "Повелитель драконов" msgid "Rebellion" msgstr "Бунт" msgid "Apocalypse" msgstr "ÐпокалипÑиÑ" msgid "Greater Glory" msgstr "К вÑщей Ñлаве" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Король Ðрчибальд требует, чтобы Ð’Ñ‹ победили трёх врагов в Ñтом регионе. Они " "не в Ñоюзе друг Ñ Ð´Ñ€ÑƒÐ³Ð¾Ð¼, поÑтому будут тратить большую чаÑть Ñвоих Ñил на " "борьбу между Ñобой. Ð’Ñ‹ выиграете, когда захватите вÑе вражеÑкие замки и " "повергнете вÑех героев." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Ð’Ñ‹ должны объединить варварÑкие племена Ñевера, завоевав их. Как и в " "предыдущей миÑÑии, враги не объединены против ВаÑ, но в их раÑпорÑжении " "больше реÑурÑов. Ð’Ñ‹ выиграете, когда захватите вÑе вражеÑкие замки и " "повергнете вÑех героев." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Благодетели-волшебники взÑли замок некромантов. Ð’Ñ‹ должны вернуть его, чтобы " "добитьÑÑ Ð¿Ð¾Ð±ÐµÐ´Ñ‹. Помните, что хоть Ð’Ñ‹ начинаете Ñ Ð¼Ð¾Ñ‰Ð½Ð¾Ð¹ армией, у Ð’Ð°Ñ Ð½ÐµÑ‚ " "замка и Ð’Ñ‹ должны захватить его в течение 7 дней, или проиграете Ñту битву. " "(ПодÑказка: Ближайший замок находитÑÑ Ð½Ð° юго-воÑтоке.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Гномов нужно победить, прежде чем они поÑмеют вмешатьÑÑ Ð² планы ÐºÐ¾Ñ€Ð¾Ð»Ñ " "Ðрчибальда. Ð’ Ñ€Ñдах Роланда не один герой, а множеÑтво городов дают им " "возможноÑть начать атаку Ñ Ð½ÐµÑкольких направлений, поÑтому будьте начеку! Ð’Ñ‹ " "должны захватить вÑе вражеÑкие города и замки, чтобы претендовать на победу." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Ð’Ñ‹ должны положить конец креÑтьÑнÑкому воÑÑтанию во главе Ñ Ñилами Роланда. " "Ð’Ñе они объединилиÑÑŒ против ВаÑ, но Вам помогает опытный герой - лорд " "Корлагон. Захватите вÑе вражеÑкие замки, чтобы победить." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Ð’ Ñтой миÑÑии Вам противоÑтоÑÑ‚ два Ñоюзника. Оба хорошо вооружены и " "ÑтремÑÑ‚ÑÑ Ð¿Ñ€Ð¾Ð³Ð½Ð°Ñ‚ÑŒ Ð’Ð°Ñ Ñо Ñвоего оÑтрова. Избегайте их и захватите город " "драконов, чтобы победить." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Вам приказано захватить Ð²Ð»Ð°Ð´ÐµÐ½Ð¸Ñ Ð»Ð¾Ñ€Ð´Ð¾Ð², которые поклÑлиÑÑŒ Ñлужить Роланду. " "Ð’Ñе вражеÑкие замки объединены против ВаÑ. Так как Ð’Ñ‹ начинаете без замка, " "Ð’Ñ‹ должны Ñпешить, чтобы захватить Ñ…Ð¾Ñ‚Ñ Ð±Ñ‹ один до конца недели. Захватите " "вÑе вражеÑкие замки Ð´Ð»Ñ Ð¿Ð¾Ð±ÐµÐ´Ñ‹." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Ðайдите корону до того, как её найдут герои Роланда. Корона понадобитÑÑ " "Ðрчибальду Ð´Ð»Ñ Ñ„Ð¸Ð½Ð°Ð»ÑŒÐ½Ð¾Ð¹ битвы против Роланда." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Это поÑледнÑÑ Ð±Ð¸Ñ‚Ð²Ð°. И Ð’Ñ‹, и Ваши враги вооружены до зубов, и вÑе они в " "Ñоюзе против ВаÑ. Захватите Роланда, чтобы выиграть войну, и не забудьте, " "что Ðрчибальд должен оÑтатьÑÑ Ð² живых!" msgid "Arrow's Flight" msgstr "Полёт Ñтрелы" msgid "Island of Chaos" msgstr "ОÑтров хаоÑа" msgid "The Abyss" msgstr "Бездна" msgid "Uprising" msgstr "ВоÑÑтание" msgid "Aurora Borealis" msgstr "Северное ÑиÑние" msgid "Betrayal's End" msgstr "Конец предательÑтва" msgid "Corruption's Heart" msgstr "Сердце Ñкверны" msgid "The Giant's Pass" msgstr "Перевал гигантов" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "УÑмирите непокорных меÑтных лордов, Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ чтобы дать Империи возможноÑть " "обоÑноватьÑÑ Ð² Ñтом регионе." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Сокрушите вÑех врагов в Ñтой облаÑти. Тогда Ð¿ÐµÑ€Ð²Ð°Ñ Ñ‡Ð°Ñть артефакта будет " "Вашей." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Волшебницы на Ñеверо-воÑтоке поднÑли воÑÑтание! Ðа благо Империи Ð’Ñ‹ должны " "подавить их ничтожные очаги ÑÐ¾Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð»ÐµÐ½Ð¸Ñ Ð½Ð° пути в горы." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "ПодготовившиÑÑŒ к Вашему приезду, КрÑгер воззвал к Ñилам некромантов, чтобы " "Ñорвать Ваши поиÑки. Ð’Ñ‹ должны захватить замок СкабÑдейл до первого Ð´Ð½Ñ " "третьей недели, пока некроманты не Ñтали Ñлишком Ñильны Ð´Ð»Ñ Ð’Ð°Ñ." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "ВарварÑкий деÑпот в Ñтой облаÑти пока не знает о Вашем приÑутÑтвии. Как " "можно Ñкорее нараÑтите Ñвою мощь, прежде чем он обнаружит Ð’Ð°Ñ Ð¸ нападёт! Вам " "необходимо обезопаÑить Ñтот регион, покорив вÑе вражеÑкие Ñилы." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Ð˜Ð¼Ð¿ÐµÑ€Ð¸Ñ Ñлаба в Ñтом регионе. Ð’Ñ‹ не Ñможете единолично противодейÑтвовать " "вÑем Ñилам в Ñтой облаÑти, так что возьмите вÑÑ‘, что Ð’Ñ‹ Ñможете до того, как " "Ð’Ð°Ñ Ð½Ð°Ñтигнет возмездие. Помните, что Ваша иÑÑ‚Ð¸Ð½Ð½Ð°Ñ Ñ†ÐµÐ»ÑŒ ÑоÑтоит в том, " "чтобы получить шлем Ðндурана." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Ðа благо Империи уничтожьте КрÑгера." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Ðаконец, у Ð’Ð°Ñ ÐµÑть возможноÑть и ÑредÑтва, чтобы избавить Империю от зла " "некромантов. ИÑкорените их полноÑтью, и Ð’Ñ‹ будете воÑпеты, как герой на вÑе " "времена." msgid "Border Towns" msgstr "Пограничные города" msgid "Conquer and Unify" msgstr "Завоевать и объединить" msgid "Crazy Uncle Ivan" msgstr "Безумный дÑдÑ" msgid "The Wayward Son" msgstr "Блудный Ñын" msgid "Ivory Gates" msgstr "Ворота Слоновой КоÑти" msgid "The Elven Lands" msgstr "ЭльфийÑкие земли" msgid "The Epic Battle" msgstr "ЭпичеÑÐºÐ°Ñ Ð±Ð¸Ñ‚Ð²Ð°" msgid "The Southern War" msgstr "Ð®Ð¶Ð½Ð°Ñ Ð²Ð¾Ð¹Ð½Ð°" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Завоюйте и объедините вÑе вражеÑкие племена. Ðе потерÑйте Ð³ÐµÑ€Ð¾Ñ Ð”Ð¶Ð°Ñ€ÐºÐ¾Ð½Ð°Ñа, " "Ð¿Ñ€Ð°Ñ€Ð¾Ð´Ð¸Ñ‚ÐµÐ»Ñ Ð²Ñех потомков." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Ваш противник, КоролевÑтво Харондейл, атакует Ñлабые города на Вашей " "границе! ОправитеÑÑŒ от их первого удара и Ñокрушите их полноÑтью!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Отыщите Вашего блудного Ñына Джозефа, который, по Ñлухам, живёт в беÑплодных " "землÑÑ…. Сделайте Ñто за 8 недель, иначе будет поздно." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "СпаÑите Вашего ÑумаÑшедшего дÑдю Ивана. Ðайдите его до первого Ð´Ð½Ñ " "четвертого меÑÑца, иначе он не поможет Вашему королевÑтву." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Уничтожьте варваров, атакующих южные границы Вашего королевÑтва. Верните " "Ñвои города, затем завоюйте варварÑкие." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Верните замок Ворота Слоновой КоÑти, который пал из-за предательÑтва." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "ЗаÑлужите доверие Ñльфов. Они не позволÑÑ‚ Вам вырубать леÑ, но будут " "Ñнабжать Ð’Ð°Ñ Ð´Ñ€ÐµÐ²ÐµÑиной каждые две недели. Вам необходимо завершить миÑÑию " "до первого Ð´Ð½Ñ Ñедьмого меÑÑца, иначе королевÑтво обÑзательно падёт." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Это поÑледнÑÑ Ð±Ð¸Ñ‚Ð²Ð° против враждебного королевÑтва Харондейл. Уничтожьте " "вÑех и не потерÑйте Ð³ÐµÑ€Ð¾Ñ Ð”Ð¶Ð°Ñ€ÐºÐ¾Ð½Ð°Ñа VI." msgid "Fount of Wizardry" msgstr "ИÑточник волшебÑтва" msgid "Power's End" msgstr "Конец влаÑти" msgid "The Eternal Scrolls" msgstr "Вечные Ñвитки" msgid "The Shrouded Isles" msgstr "ОÑтрова чародеев" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Ваша миÑÑÐ¸Ñ - разгромить воинÑтвующих магов на волшебных Окутанных оÑтровах. " "Это увеличит Ваши шанÑÑ‹ в борьбе Ñ Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð½Ð¸ÐºÐ°Ð¼Ð¸." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "МеÑтонахождение великой библиотеки было обнаружено! Ð’Ñ‹ должны добратьÑÑ Ð´Ð¾ " "нее и вернуть Ñебе город ХроноÑ, в котором она находитÑÑ." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Ðайдите Сферу ОтрицаниÑ, котораÑ, как говорÑÑ‚, похоронена в Ñтой земле. Ðа " "каменных обелиÑках начертаны подÑказки, которые помогут Вам найти её. " "Ðайдите Ñферу до первого Ð´Ð½Ñ ÑˆÐµÑтого меÑÑца, иначе Ваши противники навернÑка " "доберутÑÑ Ð´Ð¾ иÑточника раньше ВаÑ." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Ð’Ñ‹ должны взÑть под контроль замок Магии, где находитÑÑ Ð¸Ñточник волшебÑтва. " "Сделайте Ñто, и Ваша победа будет окончательной." msgid "Blood is Thicker" msgstr "Кровные узы" msgid "King and Country" msgstr "Король и Ñтрана" msgid "Pirate Isles" msgstr "ПиратÑкие оÑтрова" msgid "Stranded" msgstr "Ðа мели" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Захватите город на оÑтрове к юго-западу от Ð¿Ð¾Ð±ÐµÑ€ÐµÐ¶ÑŒÑ Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, чтобы " "поÑтроить лодку, и вернитеÑÑŒ обратно на материк. Ðе потерÑйте Галаванта." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Ðайдите и победите Мартину, предводительницу пиратов, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¶Ð¸Ð²Ñ‘Ñ‚ в " "ПиратÑкой бухте. Ðе потерÑйте Галаванта, иначе Ваши поиÑки закончатÑÑ." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Уничтожьте вÑе другие Ñилы, выÑтупающие против Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð»Ð¾Ñ€Ð´Ð° Ðльберона. " "Галавант не должен погибнуть." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Свергните укоренившуюÑÑ Ð¼Ð¾Ð½Ð°Ñ€Ñ…Ð¸ÑŽ лорда Ðльберона и объÑвите вÑе земли " "Ñвоими. Галавант не должен умереть." msgid " bane" msgstr " Ñд" msgid " alliance" msgstr " Ñоюз" msgid "Carry-over forces" msgstr "ÐŸÐµÑ€ÐµÐ½Ð¾Ñ Ð²Ð¾Ð¹Ñк" msgid " bonus" msgstr " бонуÑ" msgid " defeated" msgstr " поражение" msgid " will always run away from your army." msgstr " будут вÑегда убегать от Вашей армии." msgid " will be willing to join your army." msgstr " будут желать вÑтупить в Вашу армию." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" "Ðртефакт \"%{artifact}\" будет доÑтупен в уÑловленных ÑценариÑÑ… данной " "кампании." msgid "The army will be carried over in the campaign." msgstr "ÐÑ€Ð¼Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ доÑтупна в уÑловленном Ñценарии данной кампании." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "КоролевÑтво ежедневно будет получать +%{count} %{resource}." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" "Заклинание \"%{spell}\" будет доÑтупно в уÑловленных ÑценариÑÑ… данной " "кампании." msgid "%{hero} can be hired during scenarios." msgstr "%{hero} может быть нанÑÑ‚ в уÑловленных ÑценариÑÑ… данной кампании." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" "%{hero} был повержен, и больше не будет доÑаждать Вам в Ñтом и поÑледующих " "ÑценариÑÑ…." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Гномы узнают Ñвоих Ñоюзников и Ñ Ñ€Ð°Ð´Ð¾Ñтью приÑоединÑÑŽÑ‚ÑÑ Ðº Вашим Ñилам." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Огры узнают в Ð’Ð°Ñ ÑƒÐ±Ð¸Ð¹Ñ†Ñƒ гномов и подходÑÑ‚, чтобы приÑоединитьÑÑ Ðº Вам." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Драконы, рыча и огрызаÑÑÑŒ, ÑоглашаютÑÑ Ð¾Ð±ÑŠÐµÐ´Ð¸Ð½Ð¸Ñ‚ÑŒ уÑÐ¸Ð»Ð¸Ñ Ñ Ð’Ð°Ð¼Ð¸, Ñвоим " "\"Ñоюзником\"." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Когда Ð’Ñ‹ приближаетеÑÑŒ к группе Ñльфов, их лидер окликает Ñвои Ñ€Ñды: \"Кто " "из Ð²Ð°Ñ Ð´Ð¾Ñтаточно храбр, чтобы приÑоединитьÑÑ Ðº нашему беÑÑтрашному Ñоюзнику?" "\". Эльфы взрываютÑÑ Ñ€Ð°Ð´Ð¾Ñтными возглаÑами и бегут, чтобы примкнуть к Вашим " "Ñ€Ñдам." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "Гномы приветÑтвуют ВаÑ: \"Друг Роланда - наш друг. Ð’Ñ‹ можете пройти\"." msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "Огры хрюкают в знак признаниÑ: \"Союзники Ðрчибальда могут пройти\"." msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Драконы видÑÑ‚ Ð’Ð°Ñ Ð¸ взывают: \"Ðаш Ñоюз Ñ Ðрчибальдом вынуждает Ð½Ð°Ñ " "приÑоединитьÑÑ Ðº Вам. К Ñожалению, в Вашей армии нет меÑта. Жаль!\" Взмахнув " "крыльÑми, они улетают прочь." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Эльфы замечают, как Ð’Ñ‹ приближаетеÑÑŒ. Их предводитель обращаетÑÑ Ðº Вам и " "говорит: \"Мы не будем препÑÑ‚Ñтвовать твоему продвижению, Ñоюзник! Проходи, " "и да пребудет Ñ Ñ‚Ð¾Ð±Ð¾Ð¹ победа.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Убийца гномов!!!!, ÑпаÑайтеÑÑŒ кто может!\"" msgid "campaignBonus|Animate Dead" msgstr "ПоднÑть нежить" msgid "campaignBonus|Chain Lightning" msgstr "Цепь молний" msgid "campaignBonus|Fireblast" msgstr "Огненный взрыв" msgid "campaignBonus|Mass Curse" msgstr "Общее проклÑтие" msgid "campaignBonus|Mass Haste" msgstr "Общее уÑкорение" msgid "campaignBonus|Mirror Image" msgstr "Фантом" msgid "campaignBonus|Resurrect" msgstr "Оживление" msgid "campaignBonus|Steelskin" msgstr "Ð¡Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð¶Ð°" msgid "campaignBonus|Summon Earth" msgstr "Элементаль" msgid "campaignBonus|View Heroes" msgstr "Показать героев" msgid "campaignBonus|Ballista" msgstr "БаллиÑта" msgid "campaignBonus|Black Pearl" msgstr "Чёрн. Жемчужина" msgid "campaignBonus|Caster's Bracelet" msgstr "Маг. БраÑлет" msgid "campaignBonus|Defender Helm" msgstr "Шлем Защитника" msgid "campaignBonus|Breastplate" msgstr "Защитный ДоÑпех" msgid "campaignBonus|Dragon Sword" msgstr "Драконий Меч" msgid "campaignBonus|Fizbin Medal" msgstr "Символ Ðеудачи" msgid "campaignBonus|Foremost Scroll" msgstr "Ð’Ñ‹Ñший Свиток" msgid "campaignBonus|Gauntlets" msgstr "Перчатки" msgid "campaignBonus|Hideous Mask" msgstr "УжаÑÐ½Ð°Ñ ÐœÐ°Ñка" msgid "campaignBonus|Mage's Ring" msgstr "Кольцо Мага" msgid "campaignBonus|Major Scroll" msgstr "Большой Свиток" msgid "campaignBonus|Medal of Honor" msgstr "Медаль ДоблеÑти" msgid "campaignBonus|Medal of Valor" msgstr "Медаль Отваги" msgid "campaignBonus|Minor Scroll" msgstr "Малый Свиток" msgid "campaignBonus|Nomad Boots" msgstr "Сапоги Кочевника" msgid "campaignBonus|Power Axe" msgstr "Топор ВлаÑти" msgid "campaignBonus|Spiked Shield" msgstr "Шипованный Щит" msgid "campaignBonus|Stealth Shield" msgstr "Ðезримый Щит" msgid "campaignBonus|Tax Lien" msgstr "ПодатнаÑ" msgid "campaignBonus|Thunder Mace" msgstr "Ð“Ñ€Ð¾Ð¼Ð¾Ð²Ð°Ñ ÐŸÐ°Ð»Ð¸Ñ†Ð°" msgid "campaignBonus|Traveler's Boots" msgstr "Сапоги Путника" msgid "campaignBonus|White Pearl" msgstr "Бел. Жемчужина" msgid "campaignBonus|Basic Archery" msgstr "Баз. Ñтрельба" msgid "campaignBonus|Advanced Archery" msgstr "Прод. Ñтрельба" msgid "campaignBonus|Expert Archery" msgstr "ЭкÑп. Ñтрельба" msgid "campaignBonus|Basic Ballistics" msgstr "Баз. баллиÑтика" msgid "campaignBonus|Advanced Ballistics" msgstr "Прод. баллиÑтика" msgid "campaignBonus|Expert Ballistics" msgstr "ЭкÑп. баллиÑтика" msgid "campaignBonus|Basic Diplomacy" msgstr "Баз. дипломатиÑ" msgid "campaignBonus|Advanced Diplomacy" msgstr "Прод. дипломатиÑ" msgid "campaignBonus|Expert Diplomacy" msgstr "ЭкÑп. дипломатиÑ" msgid "campaignBonus|Basic Eagle Eye" msgstr "Баз. орлиный взор" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Прод. орлиный взор" msgid "campaignBonus|Expert Eagle Eye" msgstr "ЭкÑп. орлиный взор" msgid "campaignBonus|Basic Estates" msgstr "Баз. казначей" msgid "campaignBonus|Advanced Estates" msgstr "Прод. казначей" msgid "campaignBonus|Expert Estates" msgstr "ЭкÑп. казначей" msgid "campaignBonus|Basic Leadership" msgstr "Баз. лидерÑтво" msgid "campaignBonus|Advanced Leadership" msgstr "Прод. лидерÑтво" msgid "campaignBonus|Expert Leadership" msgstr "ЭкÑп. лидерÑтво" msgid "campaignBonus|Basic Logistics" msgstr "Баз. логиÑтика" msgid "campaignBonus|Advanced Logistics" msgstr "Прод. логиÑтика" msgid "campaignBonus|Expert Logistics" msgstr "ЭкÑп. логиÑтика" msgid "campaignBonus|Basic Luck" msgstr "Баз. удача" msgid "campaignBonus|Advanced Luck" msgstr "Прод. удача" msgid "campaignBonus|Expert Luck" msgstr "ЭкÑп. удача" msgid "campaignBonus|Basic Mysticism" msgstr "Баз. миÑтицизм" msgid "campaignBonus|Advanced Mysticism" msgstr "Прод. миÑтицизм" msgid "campaignBonus|Expert Mysticism" msgstr "ЭкÑп. миÑтицизм" msgid "campaignBonus|Basic Navigation" msgstr "Баз. навигациÑ" msgid "campaignBonus|Advanced Navigation" msgstr "Прод. навигациÑ" msgid "campaignBonus|Expert Navigation" msgstr "ЭкÑп. навигациÑ" msgid "campaignBonus|Basic Necromancy" msgstr "Баз. некромантиÑ" msgid "campaignBonus|Advanced Necromancy" msgstr "Прод. некромантиÑ" msgid "campaignBonus|Expert Necromancy" msgstr "ЭкÑп. некромантиÑ" msgid "campaignBonus|Basic Pathfinding" msgstr "Баз. Ñледопыт" msgid "campaignBonus|Advanced Pathfinding" msgstr "Прод. Ñледопыт" msgid "campaignBonus|Expert Pathfinding" msgstr "ЭкÑп. Ñледопыт" msgid "campaignBonus|Basic Scouting" msgstr "Баз. разведка" msgid "campaignBonus|Advanced Scouting" msgstr "Прод. разведка" msgid "campaignBonus|Expert Scouting" msgstr "ЭкÑп. разведка" msgid "campaignBonus|Basic Wisdom" msgstr "Баз. мудроÑть" msgid "campaignBonus|Advanced Wisdom" msgstr "Прод. мудроÑть" msgid "campaignBonus|Expert Wisdom" msgstr "ЭкÑп. мудроÑть" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" "ОÑновной герой в начале ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ обладать артефактом \"%{artifact}\"." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "КоролевÑтво в начале ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ дополнительные реÑурÑÑ‹: %{resource} +" "%{amount} ед." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "КоролевÑтво в начале ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð¿Ð¾Ñ‚ÐµÑ€Ñет реÑурÑÑ‹: %{resource} -%{amount} ед." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" "Ðрмию оÑновного Ð³ÐµÑ€Ð¾Ñ Ð² начале ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð¿Ð¾Ð¿Ð¾Ð»Ð½ÑÑ‚ %{monster} отрÑдом в " "%{count} ед." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "ОÑновной герой в начале ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ иметь заклинание \"%{spell}\"." msgid "The starting alignment of the scenario will be %{race}." msgstr "ÐÐ°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ„Ñ€Ð°ÐºÑ†Ð¸Ñ ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ %{race}." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "ОÑновной герой в Ñтом Ñценарии получит дополнительно +%{count} к навыку " "\"%{skill}\"." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "ОÑновной герой в начале ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ иметь навык %{skill}." msgid "Roland" msgstr "Роланд" msgid "Archibald" msgstr "Ðрчибальд" msgid "Price of Loyalty" msgstr "Цена верноÑти" msgid "Voyage Home" msgstr "Дорога домой" msgid "Wizard's Isle" msgstr "ОÑтров чародеев" msgid "Descendants" msgstr "ÐаÑледники" msgid "Cannot build. You have already built here today." msgstr "Ðевозможно поÑтроить. Ð’Ñ‹ уже Ñтроили здеÑÑŒ ÑегоднÑ." msgid "For this action it is necessary to build a castle first." msgstr "Ð”Ð»Ñ Ñтого Вам нужно Ñперва поÑтроить замок." msgid "The %{building} produces %{monster}." msgstr "" "%{building} - жилище, в котором %{monster} доÑтупны Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ð° в Вашу армию." msgid "Requires:" msgstr "Требует:" msgid "Exit this menu without doing anything." msgstr "Выход, без изменений." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "%{name} невозможно поÑтроить - замок Ñлишком далеко от океана." msgid "This building has been disabled." msgstr "Эта поÑтройка отключена." msgid "Cannot afford the %{name}." msgstr "ÐедоÑтаточно реÑурÑов Ð´Ð»Ñ Ð¿Ð¾Ñтройки." msgid "The %{name} is already built." msgstr "Это здание уже поÑтроено." msgid "Cannot build the %{name}." msgstr "Ðевозможно поÑтроить: %{name}." msgid "Build %{name}." msgstr "ПоÑтроить %{name}." msgid "Blackridge" msgstr "БлÑкридж" msgid "Hillstone" msgstr "ХилÑтон" msgid "Pinehurst" msgstr "ПайнхёрÑÑ‚" msgid "Whiteshield" msgstr "Вайтшилд" msgid "Woodhaven" msgstr "Вудхавен" msgid "Blackwind" msgstr "БлÑквинд" msgid "Bloodreign" msgstr "Бладрейн" msgid "Dragontooth" msgstr "ДрагонтуÑ" msgid "Greywind" msgstr "Грейвинд" msgid "Portsmith" msgstr "ПортÑмит" msgid "Atlantium" msgstr "Ðтлантиум" msgid "Middle Gate" msgstr "Мидлгейт" msgid "Sansobar" msgstr "Занзобар" msgid "Tundara" msgstr "Тундара" msgid "Vulcania" msgstr "ВулканиÑ" msgid "Baywatch" msgstr "Байвоч" msgid "Fountainhead" msgstr "Фонтанхед" msgid "Vertigo" msgstr "Вертиго" msgid "Wildabar" msgstr "Вилдабар" msgid "Winterkill" msgstr "Винтеркил" msgid "Brindamoor" msgstr "Бриндамур" msgid "Lakeside" msgstr "ЛÑйкÑайд" msgid "Nightshadow" msgstr "ÐайтшÑдоу" msgid "Olympus" msgstr "ОлимпуÑ" msgid "Sandcaster" msgstr "СÑндкаÑтер" msgid "Alamar" msgstr "Ðламар" msgid "Burlock" msgstr "Бурлок" msgid "Dragadune" msgstr "Драгадун" msgid "Kalindra" msgstr "Калиндра" msgid "Xabran" msgstr "КÑабран" msgid "Algary" msgstr "Ðлгари" msgid "Basenji" msgstr "БеÑенджи" msgid "Blackfang" msgstr "БлÑкфанг" msgid "New Dawn" msgstr "Ðью-Давн" msgid "Sorpigal" msgstr "Сорпигал" msgid "Avone" msgstr "Ðвон" msgid "Big Oak" msgstr "Биг-Оук" msgid "Chandler" msgstr "Чандлер" msgid "Erliquin" msgstr "Эрликуин" msgid "Hampshire" msgstr "Хампшир" msgid "Antioch" msgstr "Ðнтиох" msgid "Avalon" msgstr "Ðвалон" msgid "Roc Haven" msgstr "Рокхавен" msgid "South Mill" msgstr "СауÑмил" msgid "Weed Patch" msgstr "Вид-Патч" msgid "Brownston" msgstr "БраунÑтон" msgid "Hilltop" msgstr "Хилтоп" msgid "Weddington" msgstr "Ведингтон" msgid "Westfork" msgstr "ВеÑтфорк" msgid "Whittingham" msgstr "Витингем" msgid "Cathcart" msgstr "Кеткарт" msgid "Elk's Head" msgstr "ЭлькÑ-Хед" msgid "Roscomon" msgstr "РоÑкомон" msgid "Sherman" msgstr "Шерман" msgid "Yorksford" msgstr "ЙоркÑфорд" msgid "Blackburn" msgstr "БлÑкбёрн" msgid "Blacksford" msgstr "БлÑкÑфорд" msgid "Burton" msgstr "Бёртон" msgid "Pig's Eye" msgstr "Пигз-Ðй" msgid "Viper's Nest" msgstr "Гнездо гадюк" msgid "Fenton" msgstr "Фентон" msgid "Lankershire" msgstr "Ланкершир" msgid "Lombard" msgstr "Ломбард" msgid "Timberhill" msgstr "Тимберхил" msgid "Troy" msgstr "ТроÑ" msgid "Forder Oaks" msgstr "Фордер-ОукÑ" msgid "Meramec" msgstr "Меремек" msgid "Quick Silver" msgstr "КвикÑильвер" msgid "Westmoor" msgstr "ВеÑтмур" msgid "Willow" msgstr "Вилоу" msgid "Corackston" msgstr "КоракÑтоун" msgid "Sheltemburg" msgstr "Шелтембург" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Ðайм невозможен. Ð’ замке уже еÑть герой." msgid "Cannot recruit - you have too many Heroes." msgstr "Ðайм невозможен. Ð’Ñ‹ уже имеете макÑимум героев." msgid "Cannot afford a Hero." msgstr "ÐедоÑтаточно ÑредÑтв Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ð° героÑ." msgid "There is no room in the garrison for this army." msgstr "Ðет Ñвободного меÑта в армии." msgid "Fortifications" msgstr "УкреплениÑ" msgid "Farm" msgstr "Ферма" msgid "Thatched Hut" msgstr "Мазанка" msgid "Archery Range" msgstr "Стрельбище" msgid "Upg. Archery Range" msgstr "Полигон" msgid "Blacksmith" msgstr "Кузница" msgid "Upg. Blacksmith" msgstr "МаÑтерÑкаÑ" msgid "Armory" msgstr "ОружейнаÑ" msgid "Upg. Armory" msgstr "ÐÑ€Ñенал" msgid "Jousting Arena" msgstr "Ðрена" msgid "Upg. Jousting Arena" msgstr "РиÑталище" msgid "Cathedral" msgstr "Собор" msgid "Upg. Cathedral" msgstr "Храм" msgid "Coliseum" msgstr "Колизей" msgid "Garbage Heap" msgstr "Свалка" msgid "Hut" msgstr "Хижина" msgid "Stick Hut" msgstr "Халупа" msgid "Upg. Stick Hut" msgstr "Хибара" msgid "Den" msgstr "Логово" msgid "Adobe" msgstr "Глинобитный дом" msgid "Upg. Adobe" msgstr "Саманный дом" msgid "Bridge" msgstr "МоÑÑ‚" msgid "Upg. Bridge" msgstr "Царь-моÑÑ‚" msgid "Pyramid" msgstr "Пирамида" msgid "Rainbow" msgstr "Радуга" msgid "Crystal Garden" msgstr "ХруÑтальный Ñад" msgid "Treehouse" msgstr "Дома на дереве" msgid "Cottage" msgstr "Избушка" msgid "Upg. Cottage" msgstr "Хоромы" msgid "Stonehenge" msgstr "Менгиры" msgid "Upg. Stonehenge" msgstr "Стоунхендж" msgid "Fenced Meadow" msgstr "ÐžÐ³Ð¾Ñ€Ð¾Ð¶ÐµÐ½Ð½Ð°Ñ Ð»ÑƒÐ¶Ð°Ð¹ÐºÐ°" msgid "sorceress|Red Tower" msgstr "ÐÐ»Ð°Ñ Ð±Ð°ÑˆÐ½Ñ" msgid "Dungeon" msgstr "Сокровищница" msgid "Waterfall" msgstr "Водопад" msgid "Cave" msgstr "Пещера" msgid "Crypt" msgstr "Склеп" msgid "Nest" msgstr "Гнездо" msgid "Maze" msgstr "Лабиринт" msgid "Upg. Maze" msgstr "Большой лабиринт" msgid "Swamp" msgstr "Болото" msgid "Green Tower" msgstr "Ð—ÐµÐ»Ñ‘Ð½Ð°Ñ Ð±Ð°ÑˆÐ½Ñ" msgid "warlock|Red Tower" msgstr "КраÑÐ½Ð°Ñ Ð±Ð°ÑˆÐ½Ñ" msgid "Black Tower" msgstr "Ð§Ñ‘Ñ€Ð½Ð°Ñ Ð±Ð°ÑˆÐ½Ñ" msgid "Library" msgstr "Библиотека" msgid "Orchard" msgstr "Фруктовый Ñад" msgid "Habitat" msgstr "Ðора" msgid "Pen" msgstr "Хлев" msgid "Foundry" msgstr "ЛитейнаÑ" msgid "Upg. Foundry" msgstr "Фабрика" msgid "Cliff Nest" msgstr "Гнездовье" msgid "Ivory Tower" msgstr "Ð‘Ð°ÑˆÐ½Ñ Ñлоновой коÑти" msgid "Upg. Ivory Tower" msgstr "Обитель магов" msgid "Cloud Castle" msgstr "ÐебеÑный замок" msgid "Upg. Cloud Castle" msgstr "ÐебеÑный чертог" msgid "Storm" msgstr "БурÑ" msgid "Skull Pile" msgstr "Груда черепов" msgid "Excavation" msgstr "РаÑкопки" msgid "Graveyard" msgstr "Кладбище" msgid "Upg. Graveyard" msgstr "ПогоÑÑ‚" msgid "Upg. Pyramid" msgstr "Ð’ÐµÐ»Ð¸ÐºÐ°Ñ Ð¿Ð¸Ñ€Ð°Ð¼Ð¸Ð´Ð°" msgid "Mansion" msgstr "ОÑобнÑк" msgid "Upg. Mansion" msgstr "ПомеÑтье" msgid "Mausoleum" msgstr "Мавзолей" msgid "Upg. Mausoleum" msgstr "Ðекрополь" msgid "Laboratory" msgstr "ЛабораториÑ" msgid "Shrine" msgstr "Ðлтарь" msgid "Special" msgstr "ОÑобое" msgid "Horde Building" msgstr "Здание орды" msgid "Dwelling 1" msgstr "Жилище 1 ур." msgid "Dwelling 2" msgstr "Жилище 2 ур." msgid "Upg. Dwelling 2" msgstr "Ул. жилище 2 ур." msgid "Dwelling 3" msgstr "Жилище 3 ур." msgid "Upg. Dwelling 3" msgstr "Ул. жилище 3 ур." msgid "Dwelling 4" msgstr "Жилище 4 ур." msgid "Upg. Dwelling 4" msgstr "Ул. жилище 4 ур." msgid "Dwelling 5" msgstr "Жилище 5 ур." msgid "Upg. Dwelling 5" msgstr "Ул. жилище 5 ур." msgid "Dwelling 6" msgstr "Жилище 6 ур." msgid "Upg. Dwelling 6" msgstr "Ул. жилище 6 ур." msgid "2x Upg. Dwelling 6" msgstr "2x Ул. жилище 6 ур." msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Ð£ÐºÑ€ÐµÐ¿Ð»ÐµÐ½Ð¸Ñ ÑƒÐ²ÐµÐ»Ð¸Ñ‡Ð¸Ð²Ð°ÑŽÑ‚ общую прочноÑть Ñтен, Ð´ÐµÐ»Ð°Ñ Ð¸Ñ… более уÑтойчивыми к " "разрушению." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Ферма увеличивает прироÑÑ‚ КреÑтьÑн на %{count} в неделю." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "ПредÑтавлениÑ, проводимые в колизее, увеличивают мораль защитников замка на " "2." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Свалка увеличивает прироÑÑ‚ Гоблинов на %{count} в неделю." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Радуга увеличивает удачу защитников замка на 2." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "ХруÑтальный Ñад увеличивает прироÑÑ‚ Фей на %{count} в неделю." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Сокровищница приноÑит в казну %{count} золотых ежедневно." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Водопад увеличивает прироÑÑ‚ Кентавров на %{count} в неделю." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Библиотека увеличивает чиÑло заклинаний, доÑтупных в гильдии магов, на одно " "заклинание Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ уровнÑ." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Фруктовый Ñад увеличивает прироÑÑ‚ ПолуроÑликов на %{count} в неделю." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "Ð‘ÑƒÑ€Ñ Ð´Ð¾Ð±Ð°Ð²Ð»Ñет 2 очка к Ñиле магии заклинателÑ, оборонÑющего замок." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Груда черепов увеличивает прироÑÑ‚ Скелетов на %{count} в неделю." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" "ОÑобое здание даёт преимущеÑтва в ÑоответÑтвии Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ñ‹Ð¼ типом замка." msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "Здание орды увеличивает прироÑÑ‚ ÑущеÑтв 1 ÑƒÑ€Ð¾Ð²Ð½Ñ Ð½Ð° 8 в неделю." msgid "Thieves' Guild" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð²Ð¾Ñ€Ð¾Ð²" msgid "Tavern" msgstr "Таверна" msgid "Shipyard" msgstr "Верфь" msgid "Well" msgstr "Колодец" msgid "Statue" msgstr "СтатуÑ" msgid "Marketplace" msgstr "Рынок" msgid "Moat" msgstr "Ров" msgid "Castle" msgstr "Замок" msgid "Tent" msgstr "Шатёр" msgid "Captain's Quarters" msgstr "КапитанÑкий штаб" msgid "Mage Guild, Level 1" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð¼Ð°Ð³Ð¾Ð² 1 ур." msgid "Mage Guild, Level 2" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð¼Ð°Ð³Ð¾Ð² 2 ур." msgid "Mage Guild, Level 3" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð¼Ð°Ð³Ð¾Ð² 3 ур." msgid "Mage Guild, Level 4" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð¼Ð°Ð³Ð¾Ð² 4 ур." msgid "Mage Guild, Level 5" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð¼Ð°Ð³Ð¾Ð² 5 ур." msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "Ðлтарь увеличивает навык некромантии вÑех Ваших некромантов на 10%." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð²Ð¾Ñ€Ð¾Ð² предоÑтавлÑет информацию об игроках и разведывательную " "информацию о вражеÑких городах. Дополнительные гильдии дают больше " "информации." msgid "The Tavern increases morale for troops defending the castle." msgstr "Таверна повышает мораль защитников замка на 1." msgid "The Shipyard allows ships to be built." msgstr "Верфь позволÑет Вам Ñтроить корабли." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "Колодец увеличивает прироÑÑ‚ вÑех ÑущеÑтв в замке на %{count} в неделю." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ñ€Ð¸Ð½Ð¾Ñит в казну %{count} золотых ежедневно." msgid "The Left Turret provides extra firepower during castle combat." msgstr "Ð›ÐµÐ²Ð°Ñ Ð±Ð°ÑˆÐ½Ñ Ð½Ð°Ð½Ð¾Ñит дополнительный урон врагу во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñады замка." msgid "The Right Turret provides extra firepower during castle combat." msgstr "ÐŸÑ€Ð°Ð²Ð°Ñ Ð±Ð°ÑˆÐ½Ñ Ð½Ð°Ð½Ð¾Ñит дополнительный урон врагу во Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñады замка." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Рынок иÑпользуетÑÑ Ð´Ð»Ñ Ð¾Ð±Ð¼ÐµÐ½Ð° одного типа реÑурÑов на другой. Чем больше " "рынков, тем ниже цены." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Ров замедлÑет наÑтупление войÑк. ОтрÑд, желающий переÑечь ров, будет " "вынужден завершить первый ход внутри рва, Ñтав уÑзвимее к атаке." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Замок улучшает оборону города и ежедневно приноÑит в казну дополнительные " "%{count} золотых." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "ЗдеÑÑŒ находÑÑ‚ÑÑ Ñ€Ð°Ð±Ð¾Ñ‡Ð¸Ðµ, которые могут возвеÑти замок." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "КапитанÑкий штаб позволÑет капитану руководить защитой замка, еÑли в нем " "отÑутÑтвует герой." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð¼Ð°Ð³Ð¾Ð² позволÑет героÑм учить Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¸ воÑполнÑть очки магии." msgid "Recruit %{name}" msgstr "ÐанÑть: %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "МеÑÑц: %{month}, ÐеделÑ: %{week}, День: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Чтобы Ð’Ð°Ñ Ð¿Ñ€Ð¾Ð¿ÑƒÑтили в гильдию магов, Ð’Ñ‹ должны купить книгу заклинаний, но " "к Ñожалению, Ваша Ñумка и так переполнена артефактами. Попробуйте передать " "один из Ваших артефактов другому герою." msgid "Click to show next town." msgstr "Ðажмите, чтобы показать Ñледующий город." msgid "Show next town" msgstr "Следующий город" msgid "Click to show previous town." msgstr "Ðажмите, чтобы показать предыдущий город." msgid "Show previous town" msgstr "Предыдущий город" msgid "This town may not be upgraded to a castle." msgstr "Ð’ Ñтом городе Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ð¾Ñтроить замок." msgid "Town" msgstr "Город" msgid "Exit Castle" msgstr "Покинуть замок" msgid "Exit Town" msgstr "Покинуть город" msgid "Show Income" msgstr "Показать доход" msgid "View Hero" msgstr "ПроÑмотреть героÑ" msgid "The above spells are available here." msgstr "ДоÑтупные заклинаниÑ." msgid "The spells the hero can learn have been added to their book." msgstr "ЗаклинаниÑ, доÑтупные герою, добавлены в Волшебную Книгу." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Щедрые чаевые вытÑнули из уÑÑ‚ трактирщика Ñледующий Ñлух:" msgid "Recruit Hero" msgstr "ÐанÑть героÑ" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} - %{race} ÑƒÑ€Ð¾Ð²Ð½Ñ %{value} " msgid "with %{count} artifacts." msgstr "Ñ %{count} артефактами." msgid "with 1 artifact." msgstr "Ñ 1 артефактом." msgid "without artifacts." msgstr "без артефактов." msgid "Recruit %{name} the %{race}" msgstr "ÐанÑть %{name}, %{race}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Разомкнутый боевой порÑдок предпиÑывает армии замка занÑть позиции по вÑей " "ширине Ñтартового раÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¾Ð¹Ñк в бою Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð²Ð°Ð»Ð°Ð¼Ð¸ между отрÑдами." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "Сомкнутый боевой порÑдок предпиÑывает отрÑдам армии замка организовать " "плотное поÑтроение поÑередине Ñтартового раÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¾Ð¹Ñк в бою." msgid "Spread Formation" msgstr "Разомкнутый Ñтрой" msgid "Grouped Formation" msgstr "Сомкнутый Ñтрой" msgid "Click to show the next town." msgstr "Ðажмите, чтобы показать Ñледующий город." msgid "Click to show the previous town." msgstr "Ðажмите, чтобы показать предыдущий город." msgid "Set garrison combat formation to 'Spread'" msgstr "Боевой порÑдок гарнизона - Разомкнутый" msgid "Set garrison combat formation to 'Grouped'" msgstr "Боевой порÑдок гарнизона - Сомкнутый" msgid "Exit Castle Options" msgstr "Закрыть ÐаÑтройки замка" msgid "Castle Options" msgstr "ÐаÑтройки замка" msgid "Not enough resources to recruit creatures." msgstr "ÐедоÑтаточно ÑредÑтв Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ð° ÑущеÑтв." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Ð”Ð»Ñ Ñтого отрÑда нет меÑта." msgid "No creatures available for purchase." msgstr "Ðет доÑтупных ÑущеÑтв Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ð°." msgid "Recruit Creatures" msgstr "ÐанÑть ÑущеÑтв" msgid "Hire all creatures in the town." msgstr "ÐанÑть вÑех ÑущеÑтв в городе." msgid "Max" msgstr "МакÑимум" msgid "Available" msgstr "ДоÑтупно" msgid "Town Population Information and Statistics" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ наÑелении города" msgid "Damage" msgstr "Урон" msgid "HP" msgstr "Здоровье" msgid "Growth" msgstr "ПрироÑÑ‚" msgid "week" msgstr "неделÑ" msgid "View World" msgstr "Обзор мира" msgid "View the entire world." msgstr "ОÑмотреть веÑÑŒ мир." msgid "Puzzle" msgstr "Головоломка" msgid "View the obelisk puzzle." msgstr "ПоÑмотреть найденные на обелиÑках фрагменты головоломки." msgid "Scenario Information" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñценарии" msgid "View information on the scenario you are currently playing." msgstr "ОпиÑание текущего ÑценариÑ." msgid "Dig for the Ultimate Artifact." msgstr "Копать в поиÑках великого артефакта." msgid "Digging" msgstr "Копать" msgid "Arena" msgstr "Ðрена" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Ð’Ñ‹ входите в арену и оказываетеÑÑŒ перед Ñтаей злобных львов. Ð’Ñ‹ ловко " "побеждаете их под дикие вопли толпы. Тренер гладиаторов, впечатлённый Вашим " "умением, ÑоглашаетÑÑ Ð¾Ð±ÑƒÑ‡Ð¸Ñ‚ÑŒ Ð’Ð°Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð¼Ñƒ навыку." msgid "Attack Skill" msgstr "Ðтака" msgid "Defense Skill" msgstr "Защита" msgid "Shots" msgstr "Ð’Ñ‹Ñтрелов" msgid "Shots Left" msgstr "Ð’Ñ‹Ñтрелов" msgid "Hit Points" msgstr "Здоровье" msgid "Hit Points Left" msgstr "Тек. здоровье" msgid "You can't afford to upgrade your troops!" msgstr "Ð’Ñ‹ не можете позволить Ñебе ÑƒÐ»ÑƒÑ‡ÑˆÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð’Ð°ÑˆÐµÐ¹ армии!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Ваши войÑка могут быть улучшены, но за Ñто придётÑÑ Ð·Ð°Ð¿Ð»Ð°Ñ‚Ð¸Ñ‚ÑŒ. Ð’Ñ‹ ÑоглаÑны?" msgid "Are you sure you want to dismiss this army?" msgstr "Ð’Ñ‹ уверены, что хотите раÑпуÑтить Ñтот отрÑд?" msgid "Upgrade" msgstr "Улучшить" msgid "Upgrade your troops." msgstr "Улучшить ваших ÑущеÑтв." msgid "Dismiss" msgstr "Уволить" msgid "Dismiss this army." msgstr "Уволить Ñтот отрÑд." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "%{monster} в поиÑках Ñлавы желают к Вам приÑоединитьÑÑ.\n" "Ð’Ñ‹ ÑоглаÑны?" msgid "Followers" msgstr "ПоÑледователи" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "ВоÑхищаÑÑÑŒ Вашими дипломатичеÑкими ÑпоÑобноÑÑ‚Ñми, %{monster} готовы вÑтупить " "в Вашу армию за %{gold} золотых.\n" "Ð’Ñ‹ ÑоглаÑны?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "ВоÑхищаÑÑÑŒ Вашими дипломатичеÑкими ÑпоÑобноÑÑ‚Ñми,\n" "%{monster} решили Ñделать Вам предложение:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "Из %{total} только %{offer} приÑоединÑÑ‚ÑÑ Ðº Вашей армии, а оÑтальные оÑтавÑÑ‚ " "Ð’Ð°Ñ Ð² покое за %{gold} золотых.\n" "Ð’Ñ‹ ÑоглаÑны?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "%{offer} %{monster} готовы приÑоединитьÑÑ Ðº Вашей армии за %{gold} золотых.\n" "Ð’Ñ‹ ÑоглаÑны?" msgid "(Rate: %{percent})" msgstr "%{percent}% от вÑех ÑущеÑтв" msgid "off" msgstr "выкл." msgid "Music" msgstr "Музыка" msgid "Effects" msgstr "Эффекты" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "РаÑширение MIDI" msgid "External" msgstr "Внешний" msgid "Music Type" msgstr "Тип музыки" msgid "3D Audio" msgstr "3D Звук" msgid "Toggle ambient music level." msgstr "Уровень музыки." msgid "Toggle foreground sounds level." msgstr "Уровень звуков." msgid "Change the type of music." msgstr "Изменить тип музыки." msgid "Toggle the 3D effect of foreground sounds." msgstr "Включить или выключить 3D Ñффекты Ð´Ð»Ñ Ð·Ð²ÑƒÐºÐ¾Ð² переднего плана." msgid "Build a new ship:" msgstr "ПоÑтроить новый корабль:" msgid "Resource cost:" msgstr "СтоимоÑть:" msgid "Total: " msgstr "Ð’ казне: " msgid "Need: " msgstr "Ðеобходимо: " msgid "New Game" msgstr "ÐÐ¾Ð²Ð°Ñ Ð¸Ð³Ñ€Ð°" msgid "Start a single or multi-player game." msgstr "Ðачало одиночной или Ñетевой игры." msgid "Load Game" msgstr "Загрузка игры" msgid "Load a previously saved game." msgstr "Загрузка ранее Ñохранённой игры." msgid "Save Game" msgstr "Сохранить игру" msgid "Save the current game." msgstr "Сохранить текущую игру." msgid "Quit" msgstr "Выход" msgid "Quit out of Heroes of Might and Magic II." msgstr "Выйти из игры Heroes of Might and Magic II." msgid "Language" msgstr "Язык" msgid "Graphics" msgstr "Графика" msgid "Black & White" msgstr "Чёрно-белый" msgid "Mouse Cursor" msgstr "КурÑор мыши" msgid "Color" msgstr "Цветной" msgid "Text Support" msgstr "ТекÑтовое Ñопровождение" msgid "Change the language of the game." msgstr "Изменить Ñзык интерфейÑа." msgid "Select Game Language" msgstr "Выберите Ñзык игры:" msgid "Change the graphics settings of the game." msgstr "ÐаÑтроить параметры графики." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Включить или выключить цветной курÑор. Это ÑÑтетичеÑкий выбор." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Режим текÑтовой поддержки, который выводит дополнительную информацию об " "окнах и ÑобытиÑÑ… в игре." msgid "" "Map\n" "Difficulty" msgstr "" "СложноÑть\n" "карты" msgid "" "Game\n" "Difficulty" msgstr "" "СложноÑть\n" "игры" msgid "Rating" msgstr "Рейтинг" msgid "Map Size" msgstr "" "Размер\n" "карты" msgid "Opponents" msgstr "Оппоненты" msgid "Class" msgstr "КлаÑÑ" msgid "" "Victory\n" "Conditions" msgstr "" "УÑловиÑ\n" "победы" msgid "" "Loss\n" "Conditions" msgstr "" "УÑловиÑ\n" "поражениÑ" msgid "First select recipients!" msgstr "Сначала выберите получателÑ!" msgid "You cannot select %{resource}!" msgstr "Ð’Ñ‹ не можете подарить %{resource}!" msgid "Set %{resource-type} Count" msgstr "%{resource-type}: введите количеÑтво" msgid "Select Recipients" msgstr "Выберите получателÑ" msgid "Your Funds" msgstr "Ваши реÑурÑÑ‹" msgid "Planned Gift" msgstr "Подарить" msgid "Gift from %{name}" msgstr "Дар от %{name}" msgid "Resolution" msgstr "Разрешение" msgid "Fullscreen" msgstr "ПолноÑкранный" msgid "window|Mode" msgstr "Режим" msgid "Windowed" msgstr "Ð’ окне" msgid "V-Sync" msgstr "Ð’ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð°Ñ ÑинхронизациÑ" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "СиÑÑ‚ÐµÐ¼Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ" msgid "Change the resolution of the game." msgstr "Изменить разрешение Ñкрана." msgid "Select Game Resolution" msgstr "Выбор Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñкрана" msgid "Toggle between fullscreen and windowed modes." msgstr "Переключение между полноÑкранным и оконным режимами." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "Ð’ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð°Ñ ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ быть включена Ð´Ð»Ñ ÑƒÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¼ÐµÑ€Ñ†Ð°Ð½Ð¸Ñ " "Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° некоторых мониторах." msgid "Show extra information such as FPS and current time." msgstr "" "Показать дополнительную информацию, такую как FPS (количеÑтво отображаемых " "кадров в Ñекунду) и текущее времÑ." msgid "Hotkey: " msgstr "ГорÑÑ‡Ð°Ñ ÐºÐ»Ð°Ð²Ð¸ÑˆÐ°: " msgid "Category: " msgstr "КатегориÑ: " msgid "Event: " msgstr "Событие: " msgid "Hot Keys:" msgstr "ГорÑчие клавиши:" msgid "Hide" msgstr "Скрыть" msgid "Show" msgstr "Показать" msgid "Interface" msgstr "ИнтерфейÑ" msgid "Interface Type" msgstr "ИнтерфейÑ" msgid "Toggle the type of interface you want to use." msgstr "Переключить тип интерфейÑа, который Ð’Ñ‹ хотите иÑпользовать." msgid "Toggle interface visibility." msgstr "Показать/Ñкрыть интерфейÑ." msgid "Scroll Speed" msgstr "СкороÑть прокрутки" msgid "Sets the speed at which you scroll the window." msgstr "УÑтанавливает ÑкороÑть прокрутки окна на карте мира." msgid "Select Game Language:" msgstr "Выберите Ñзык игры:" msgid "Select Language:" msgstr "Выберите Ñзык:" msgid "Click to choose the selected language." msgstr "Ðажмите, чтобы применить выбранный Ñзык интерфейÑа игры." msgid "%{name} has gained a level." msgstr "%{name} получает уровень." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Ð’Ñ‹ изучили %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} получает уровень.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Ð’Ñ‹ можете выучить:\n" "%{skill1}\n" "или\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "н/д" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "ПоÑмотрите на наши прекраÑные товары. ЕÑли Ð’Ð°Ñ Ñ‡Ñ‚Ð¾-то заинтереÑует, нажмите " "на нужный предмет и выберите, на что хотите поменÑть." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "ПоÑмотрите, Ñто довольно Ð²Ñ‹Ð³Ð¾Ð´Ð½Ð°Ñ Ñделка. Я не пытаюÑÑŒ нажитьÑÑ Ð½Ð° ней. Ð’Ð°Ñ " "интереÑует что-нибудь ещё из моих товаров?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Я дам Вам %{count} за одну единицу %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" "Я могу предложить Вам\n" "1 %{resto} за %{count} %{resfrom}." msgid "Min" msgstr "Минимум" msgid "Qty to trade" msgstr "Обмен" msgid "Trading Post" msgstr "Базар" msgid "Your Resources" msgstr "Ваши реÑурÑÑ‹" msgid "Available Trades" msgstr "ДоÑтупно к обмену" msgid "guarded by %{count} %{monster}" msgstr "охранÑет %{count} %{monster}" msgid "guarded by " msgstr "охранÑÐµÐ¼Ð°Ñ " msgid "(available: %{count})" msgstr "(ДоÑтупно: %{count})" msgid "(empty)" msgstr "(пуÑто)" msgid "already learned" msgstr "уже выучено" msgid "treeOfKnowledge|free" msgstr "беÑплатно" msgid "already claimed" msgstr "уже получены" msgid "not claimed" msgstr "не получены" msgid "already knows this skill" msgstr "уже изучено" msgid "already has max skills" msgstr "макÑимум навыков" msgid "(already visited)" msgstr "(поÑещено)" msgid "(not visited)" msgstr "(не поÑещено)" msgid "%{color} Barrier" msgstr "%{color} барьер" msgid "(tent visited)" msgstr "(шатёр поÑещён)" msgid "%{color} Tent" msgstr "" "%{color}\n" "шатёр путника" msgid "Road" msgstr "Дорога" msgid "(digging ok)" msgstr "(можно копать)" msgid "(no digging)" msgstr "(Ð½ÐµÐ»ÑŒÐ·Ñ ÐºÐ¾Ð¿Ð°Ñ‚ÑŒ)" msgid "penalty: %{cost}" msgstr "Штраф: %{cost}" msgid "Defenders:" msgstr "Защитники:" msgid "Unknown" msgstr "ÐеизвеÑтный" msgid "heroQuickInfo|(Level %{level})" msgstr "(Уровень %{level})" msgid "Attack:" msgstr "Ðтака:" msgid "Defense:" msgstr "Защита:" msgid "Spell Power:" msgstr "Сила магии:" msgid "Knowledge:" msgstr "ЗнаниÑ:" msgid "Spell Points:" msgstr "Очки магии:" msgid "Move Points:" msgstr "Ð—Ð°Ð¿Ð°Ñ Ñ…Ð¾Ð´Ð°:" msgid "Uncharted Territory" msgstr "ÐÐµÐ¸Ð·Ð²ÐµÐ´Ð°Ð½Ð½Ð°Ñ Ñ‚ÐµÑ€Ñ€Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ" msgid "Cost per troop:" msgstr "Цена за ÑущеÑтво:" msgid "Available: %{count}" msgstr "ДоÑтупно: %{count}" msgid "Number to buy:" msgstr "ÐанÑть:" msgid "Recruit selected monsters." msgstr "ÐанÑть выбранных ÑущеÑтв." msgid "Select maximum monsters to be recruited." msgstr "Выбрать макÑимальное количеÑтво ÑущеÑтв Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ð°." msgid "Select only 1 monster to be recruited." msgstr "Выбрать вÑего 1 ÑущеÑтво Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ð°." msgid "Select this game resolution." msgstr "Выбрать данное разрешение Ñкрана." msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" "Выбор данного Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñкрана уÑтановит увеличенное иÑходное разрешение " "(%{resolution}) в маÑштабе ÑоглаÑно множителю, указанному в Ñкобках " "(%{scale}).\n" "\n" "Разрешение Ñ Ñ†ÐµÐ»Ð¾Ñ‡Ð¸Ñленным множителем (2.0x, 3.0x и Ñ‚. д.) обычно ÑмотритÑÑ " "лучше, поÑкольку пикÑели кратно маÑштабируютÑÑ ÐºÐ°Ðº в горизонтальном, так и в " "вертикальном направлениÑÑ…." msgid "Select Game Resolution:" msgstr "Выбор Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ñкрана:" msgid "Click to apply the selected resolution." msgstr "Ðажмите, чтобы применить выбранное разрешение Ñкрана." msgid "Click to apply the entered text." msgstr "Ðажмите, чтобы принÑть введённый текÑÑ‚." msgid "Click to open the Virtual Keyboard dialog." msgstr "Ðижмите, чтобы открыть окно виртуальной клавиатуры." msgid "Open Virtual Keyboard" msgstr "Открыть виртуальную клавиатуру" msgid "How many creatures do you wish to move?" msgstr "Сколько ÑущеÑтв перенеÑти?" msgid "Select how many units to separate into:" msgstr "Выберите, на Ñколько отрÑдов разделить:" msgid "Map: " msgstr "Карта: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "МеÑÑц: " msgid ", Week: " msgstr ", ÐеделÑ: " msgid ", Day: " msgstr ", День: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Путь к файлу: " msgid "Are you sure you want to delete file:" msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить файл:" msgid "Warning" msgstr "Внимание" msgid "Click to save the current game." msgstr "Ðажмите, чтобы Ñохранить текущую игру." msgid "Click to load a previously saved game." msgstr "Ðажмите, чтобы загрузить Ñохранённую игру." msgid "File to Save:" msgstr "Сохранить файл:" msgid "File to Load:" msgstr "Загрузить файл:" msgid "Terrain object" msgstr "Объект ландшафта" msgid "Accept the choice made." msgstr "Подтвердить Ваш выбор." msgid "Select Skill:" msgstr "Выберите навык:" msgid "Select Spell:" msgstr "Выберите заклинание:" msgid "Select Artifact:" msgstr "Выберите артефакт:" msgid "Select Monster:" msgstr "Выберите ÑущеÑтво:" msgid "Select Hero:" msgstr "Выберите героÑ:" msgid "race|Random" msgstr "Случайно" msgid "Click to start placing the selected hero." msgstr "Ðажмите, чтобы раÑположить выбранного героÑ." msgid "%{color} %{race}" msgstr "%{color} герой - %{race}" msgid "You will place" msgstr "Ð’Ñ‹ будете размещать" msgid "Click to select this class." msgstr "Ðажмите Ñюда чтобы выбрать Ñту фракцию." msgid "Click to select this color." msgstr "Ðажмите Ñюда чтобы выбрать Ñтот цвет." msgid "Select Treasure:" msgstr "Выберите Ñокровище:" msgid "Select Ocean Object:" msgstr "Выберите объект Ð´Ð»Ñ Ð¾ÐºÐµÐ°Ð½Ð°:" msgid "Castle/town placing" msgstr "Размещение замка или города" msgid "doubleLinedRace|Neutral" msgstr "Ðейтральный" msgid "Click to start placing the selected castle/town." msgstr "Ðажмите, чтобы раÑположить выбранный замок или город." msgid "Click to select town placing." msgstr "Ðажмите, чтобы выбрать размещение городов." msgid "Click to select castle placing." msgstr "Ðажмите, чтобы выбрать размещение замков." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{townOrCastle} (%{race} )" msgid "race|Neutral" msgstr "Ðейтральный" msgid "Select Dwelling:" msgstr "Выберите жилище:" msgid "Select Landscape Object:" msgstr "Выберите объект ландшафта:" msgid "Mine placing" msgstr "Размещение иÑточника реÑурÑов" msgid "" "Resource\n" "type:" msgstr "" "Тип\n" "реÑурÑа:" msgid "%{mineName} appearance:" msgstr "%{mineName}, внешний вид:" msgid "Click to select %{object} as the resource generator to be placed." msgstr "Ðажмите, чтобы выбрать размещение иÑточника реÑурÑов - %{object}." msgid "Select Mountain Object:" msgstr "Выберите объект типа гора:" msgid "Select Rock Object:" msgstr "Выберите объект типа камень:" msgid "Select Tree Object:" msgstr "Выберите объект типа дерево:" msgid "Select Power Up Object:" msgstr "Выберите объект типа бонуÑ:" msgid "Select Adventure Object:" msgstr "Выберите интерактивный объект:" msgid "Players Icon" msgstr "Значок игроков" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Обозначает количеÑтво игроков в данном Ñценарии. При отÑутÑтвии игроков-" "людей их меÑта занимает компьютер." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Обозначает размер карты:\n" "Ð¼Ð°Ð»ÐµÐ½ÑŒÐºÐ°Ñ (36Ñ…36), ÑреднÑÑ\n" "(72Ñ…72), Ð±Ð¾Ð»ÑŒÑˆÐ°Ñ (108Ñ…108)\n" "или Ð¾Ð³Ñ€Ð¾Ð¼Ð½Ð°Ñ (144Ñ…144)." msgid "Size Icon" msgstr "Значок размера" msgid "Map Type" msgstr "Тип карты" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Указывает, Ñоздана ли карта Ð´Ð»Ñ Ð²ÐµÑ€Ñии игры \"Война за преÑтол\", \"Цена " "верноÑти\" или \"Возрождение\"." msgid "Map Type:\n" msgstr "Тип карты:\n" msgid "The Succession Wars" msgstr "Война за преÑтол" msgid "The Price of Loyalty" msgstr "Цена верноÑти" msgid "Resurrection" msgstr "Возрождение" msgid "" "\n" "\n" "Language:\n" msgstr "" "\n" "\n" "Язык:\n" msgid "Lose all your heroes and towns." msgstr "ПотерÑть вÑех героев и вÑе города." msgid "Lose a specific town." msgstr "ПотерÑть указанный город." msgid "Lose a specific hero." msgstr "ПотерÑть указанного героÑ." msgid "Run out of time. Fail to win by a certain point." msgstr "Ðе уÑпеть вовремÑ." msgid "Loss Condition" msgstr "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ð¾Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ" msgid "Defeat all enemy heroes and towns." msgstr "Победить вÑех противников и захватить вÑе города." msgid "Capture a specific town." msgstr "Захватить указанный город." msgid "Defeat a specific hero." msgstr "Победить указанного героÑ." msgid "Find a specific artifact." msgstr "Ðайти указанный артефакт." msgid "Your side must defeat the opposing side." msgstr "Победить вмеÑте Ñ Ñоюзником вÑех противников." msgid "Accumulate a large amount of gold." msgstr "Ðакопить крупные запаÑÑ‹ золота." msgid "Victory Condition" msgstr "УÑÐ»Ð¾Ð²Ð¸Ñ Ð¿Ð¾Ð±ÐµÐ´Ñ‹" msgid "Map difficulty:" msgstr "СложноÑть карты:" msgid "N" msgstr "N" msgid "No maps exist at that size." msgstr "Ðет карт такого размера." msgid "Small Maps" msgstr "Маленькие карты" msgid "View only maps of size small (36 x 36)." msgstr "ПроÑмотр только маленьких карт (36Ñ…36)." msgid "Medium Maps" msgstr "Средние карты" msgid "View only maps of size medium (72 x 72)." msgstr "ПроÑмотр только Ñредних карт (72Ñ…72)." msgid "Large Maps" msgstr "Большие карты" msgid "View only maps of size large (108 x 108)." msgstr "ПроÑмотр только больших карт (108Ñ…108)." msgid "Extra Large Maps" msgstr "Огромные карты" msgid "View only maps of size extra large (144 x 144)." msgstr "ПроÑмотр только огромных карт (144Ñ…144)." msgid "All Maps" msgstr "Ð’Ñе карты" msgid "View all maps, regardless of size." msgstr "ПроÑмотр вÑех карт, незавиÑимо от размера." msgid "Selected Name" msgstr "Ðазвание карты" msgid "The name of the currently selected map." msgstr "Ðазвание выбранной карты." msgid "Selected Map Difficulty" msgstr "СложноÑть игры" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "СложноÑть выбранной карты. Этот параметр задаётÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ карты в редакторе. " "Более Ñложные карты могут иметь больше (или более Ñильных) врагов, меньше " "реÑурÑов или другие оÑобые уÑловиÑ, оÑложнÑющие игру человеку." msgid "Selected Description" msgstr "ОпиÑание" msgid "The description of the currently selected map." msgstr "РаÑширенное опиÑание выбранной карты." msgid "Jump" msgstr "Прыжком" msgid "Hero Speed" msgstr "Скор. героев" msgid "Don't Show" msgstr "Скрыть" msgid "Enemy Speed" msgstr "Скор. врагов" msgid "Auto Resolve" msgstr "Ðвто, Ñ Ð¼Ð°Ð³Ð¸ÐµÐ¹" msgid "Auto, No Spells" msgstr "Ðвто, без магии" msgid "Battles" msgstr "Битвы" #, fuzzy msgid "combatMode|Manual" msgstr "Вручную" msgid "Change the speed at which your heroes move on the main screen." msgstr "" "Изменить ÑкороÑть, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ Ваши герои перемещаютÑÑ Ð½Ð° главном Ñкране." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "УÑтанавливает ÑкороÑть, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ двигаютÑÑ Ð³ÐµÑ€Ð¾Ð¸ под управлением " "компьютера. Ð’Ñ‹ также можете отключить проÑмотр хода игроков, управлÑемых " "компьютером." msgid "Change the interface settings of the game." msgstr "ÐаÑтроить параметры интерфейÑа игры." msgid "Interface Settings" msgstr "ÐаÑтройки интерфейÑа" msgid "Toggle instant battle mode." msgstr "Режим мгновенного боÑ." msgid "Att." msgstr "Ðтк." msgid "Def." msgstr "Защ." msgid "Power" msgstr "Сила м." msgid "Knowl" msgstr "Знан." msgid "1st" msgstr "1-ый" msgid "2nd" msgstr "2-ой" msgid "3rd" msgstr "3-ий" msgid "4th" msgstr "4-ый" msgid "5th" msgstr "5-ый" msgid "6th" msgstr "6-ой" msgid "Oracle: Player Rankings" msgstr "Оракул: Рейтинг Игроков" msgid "Thieves' Guild: Player Rankings" msgstr "Ð“Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð’Ð¾Ñ€Ð¾Ð²: Рейтинг Игроков" msgid "Number of Towns:" msgstr "Городов:" msgid "Number of Castles:" msgstr "Замков:" msgid "Number of Heroes:" msgstr "Героев:" msgid "Gold in Treasury:" msgstr "Золота в казне:" msgid "Wood & Ore:" msgstr "Дерево и руда:" msgid "Gems, Cr, Slf & Mer:" msgstr "Прочие реÑурÑÑ‹:" msgid "Obelisks Found:" msgstr "Ðайдено обелиÑков:" msgid "Artifacts:" msgstr "Ðртефакты:" msgid "Total Army Strength:" msgstr "ÐžÐ±Ñ‰Ð°Ñ Ñила армии:" msgid "Income:" msgstr "Доход:" msgid "Best Hero:" msgstr "Лучший герой:" msgid "Best Hero Stats:" msgstr "Параметры героÑ:" msgid "Personality:" msgstr "Характер:" msgid "Best Monster:" msgstr "Лучший отрÑд:" msgid "Random Castle Name" msgstr "Случайное название замка" msgid "Random Town Name" msgstr "Случайное название города" msgid "Allow Castle build" msgstr "Разрешить замок" msgid "Default Buildings" msgstr "Ð—Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾ умолч." msgid "Default Army" msgstr "ÐÑ€Ð¼Ð¸Ñ Ð¿Ð¾ умолч." msgid "Castle Army" msgstr "ÐÑ€Ð¼Ð¸Ñ Ð·Ð°Ð¼ÐºÐ°" msgid "Town Army" msgstr "ÐÑ€Ð¼Ð¸Ñ Ð³Ð¾Ñ€Ð¾Ð´Ð°" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "Ðажмите, чтобы изменить название замка. Правый клик - ÑброÑить." msgid "Enter Castle name" msgstr "Введите название замка" msgid "Allow to build a castle in this town." msgstr "Разрешить ÑтроительÑтво замка в данном городе." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "ИÑпользовать Ð·Ð´Ð°Ð½Ð¸Ñ Ð¿Ð¾ умолчанию. ПоÑтройки будут Ñброшены!" msgid "Toggle building construction restriction mode." msgstr "Переключить режим запрета поÑтройки зданий." msgid "Restrict Building Construction" msgstr "Запретить поÑтройку зданий" msgid "Use default defenders army." msgstr "ИÑпользовать армию защитников по умолчанию." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "УÑтановить армию замка. Правый клик - ÑÐ±Ñ€Ð¾Ñ Ð¾Ñ‚Ñ€Ñда." msgid "Message Text:" msgstr "ТекÑÑ‚ ÑообщениÑ:" msgid "Reward:" msgstr "Вознаграждение:" msgid "Player colors allowed to get event:" msgstr "Событие произойдёт Ð´Ð»Ñ Ð¸Ð³Ñ€Ð¾ÐºÐ¾Ð²-людей цвета:" msgid "Computer colors allowed to get event:" msgstr "Событие произойдёт Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð½Ñ‹Ñ… игроков цвета:" msgid "First day of occurrence:" msgstr "Первый день ÑобытиÑ:" msgid "Repeat period (days):" msgstr "Период Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð¸Ñ (в днÑÑ…):" msgid "Allow %{color} human player to get event" msgstr "Позволить Ñобытие Ð´Ð»Ñ Ð¸Ð³Ñ€Ð¾ÐºÐ°-человека цвета: %{color}" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" "ЕÑли Ñтот флажок уÑтановлен, то Ñто Ñобытие произойдёт Ð´Ð»Ñ Ð¸Ð³Ñ€Ð¾ÐºÐ°-человека, " "еÑли его цвет %{color}." msgid "Allow %{color} computer player to get event" msgstr "Позволить Ñобытие Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð½Ð¾Ð³Ð¾ игрока цвета: %{color}" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" "ЕÑли Ñтот флажок уÑтановлен, то Ñто Ñобытие произойдёт Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð½Ð¾Ð³Ð¾ " "игрока, еÑли его цвет %{color}." msgid "Message:" msgstr "Сообщение:" msgid "Click to save the Event properties." msgstr "Ðажмите, чтобы Ñохранить параметры ÑобытиÑ." msgid "No resources will be given as a reward." msgstr "Ð’ вознаграждении не будут выдаватьÑÑ Ñ€ÐµÑурÑÑ‹." msgid "Resources" msgstr "РеÑурÑÑ‹" msgid "Resources will be given as a reward." msgstr "Ð’ вознаграждении будут предоÑтавлены реÑурÑÑ‹." msgid "Click here to change the event message." msgstr "Ðажмите, чтобы изменить Ñообщение при Ñобытии." msgid "Event Message Text" msgstr "Сообщение при Ñобытии" msgid "Day: %{day}" msgstr "День: %{day}" msgid "Daily Events" msgstr "Календарные ÑобытиÑ" msgid "Click to save the events." msgstr "Ðажмите, чтобы Ñохранить ÑобытиÑ." msgid "Add Event" msgstr "Добавить Ñобытие" msgid "Add an additional event." msgstr "Добавить дополнительное Ñобытие." msgid "Edit Event" msgstr "Редактировать Ñобытие" msgid "Edit an existing event." msgstr "Редактировать выбранное Ñобытие." msgid "Delete Event" msgstr "Удалить Ñобытие" msgid "Delete an existing event." msgstr "Удалить выбранное Ñобытие." #, fuzzy msgid "Effects:" msgstr "Эффекты" #, fuzzy msgid "Conditions:" msgstr "" "УÑловиÑ\n" "поражениÑ" msgid "Cancel event after first visit" msgstr "Отменить поÑле поÑещениÑ" #, fuzzy msgid "Computer colors allowed to get the event:" msgstr "Событие произойдёт Ð´Ð»Ñ ÐºÐ¾Ð¼Ð¿ÑŒÑŽÑ‚ÐµÑ€Ð½Ñ‹Ñ… игроков цвета:" msgid "Set Experience value" msgstr "Введите величину опыта" msgid "Artifact" msgstr "Ðртефакт" #, fuzzy msgid "No artifact will be given by the event." msgstr "Ð’ вознаграждении не будет выдаватьÑÑ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚." msgid "Delete Artifact" msgstr "Удалить артефакт" #, fuzzy msgid "Delete an artifact from the event." msgstr "Удалить артефакт из вознаграждениÑ." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Выберите навык:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" #, fuzzy msgid "No resources will be part of this event." msgstr "Ð’ вознаграждении не будут выдаватьÑÑ Ñ€ÐµÑурÑÑ‹." #, fuzzy msgid "These resources will be a part of the event." msgstr "Ð’ вознаграждении не будут выдаватьÑÑ Ñ€ÐµÑурÑÑ‹." msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" "ЕÑли Ñтот флажок уÑтановлен, Ñобытие произойдёт только один раз. ЕÑли флажок " "не уÑтановлен, Ñобытие будет проиÑходить каждый раз, когда один из указанных " "игроков переÑечёт клетку ÑобытиÑ." msgid "%{objects} cannot be placed on water." msgstr "%{objects} Ð½ÐµÐ»ÑŒÐ·Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰Ð°Ñ‚ÑŒ на воде." msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" "Великий артефакт может быть размещён только на меÑтноÑти, где можно копать." msgid "%{objects} must be placed on water." msgstr "%{objects} можно размещать только на воде." msgid "Objects cannot be placed outside the map." msgstr "Объекты Ð½ÐµÐ»ÑŒÐ·Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰Ð°Ñ‚ÑŒ за пределами карты." msgid "Action objects must be placed on clear tiles." msgstr "Ðктивные объекты можно размещать только в Ñвободных клетках карты." msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Ð’Ñ‹ дейÑтвительно хотите вернутьÑÑ Ð² главное меню игры? Ð’Ñе неÑохранённые " "Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ потерÑны." msgid "Editor" msgstr "Редактор" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Ð’Ñ‹ дейÑтвительно хотите загрузить новую карту? (Любые неÑохранённые " "Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ карты будут потерÑны.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Ð’Ñ‹ дейÑтвительно хотите Ñоздать новую карту? (Любые неÑохранённые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ " "данной карты будут потерÑны.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "ÐÐЧÐТЬ" msgid "Main Menu" msgstr "Главное меню" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Ð’Ñ‹ дейÑтвительно хотите вернутьÑÑ Ð² главное меню игры? Ð’Ñе неÑохранённые " "Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±ÑƒÐ´ÑƒÑ‚ потерÑны." msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Ðачать" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Ð’Ñ‹ дейÑтвительно хотите загрузить новую карту? (Любые неÑохранённые " "Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ карты будут потерÑны.)" msgid "Create a new map from scratch." msgstr "Создать новую карту Ñ Ð½ÑƒÐ»Ñ." msgid "New Map" msgstr "ÐÐ¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°" msgid "Load Map" msgstr "Загрузить карту" msgid "Load an existing map." msgstr "Загрузить ÑущеÑтвующую карту." msgid "Save Map" msgstr "Сохранить карту" msgid "Save the current map." msgstr "Сохранить текущую карту." msgid "Quit out of the map editor." msgstr "Выйти из редактора карт." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Ðажмите Ð´Ð»Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‚Ð° в главное меню." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "%{object}: введите текÑÑ‚" msgid "Set Random Ultimate Artifact Radius" msgstr "УÑтановить Ñ€Ð°Ð´Ð¸ÑƒÑ Ð¿Ð¾ÑÐ²Ð»ÐµÐ½Ð¸Ñ Ð²ÐµÐ»Ð¸ÐºÐ¾Ð³Ð¾ артефакта" msgid "%{object} has no properties to change." msgstr "%{object}: нет ÑвойÑтв, которые можно было бы изменить." msgid "This artifact" msgstr "Этот артефакт" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "Дороги" msgid "Streams" msgstr "Реки" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "Ðа карте можно размеÑтить макÑимум %{count} героев одного цвета." msgid "Failed to update player information." msgstr "Ðе удалоÑÑŒ обновить информацию об игроке." msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Ðа одной карте можно размеÑтить только один великий артефакт." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "Ðа карте можно размеÑтить макÑимум %{count} обелиÑков." msgid "The map is corrupted." msgstr "Карта повреждена." msgid "Unable to locate data directory to save the map." msgstr "Ðе удалоÑÑŒ найти папку Ñ Ð´Ð°Ð½Ð½Ñ‹Ð¼Ð¸ Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ ÐºÐ°Ñ€Ñ‚Ñ‹." msgid "Unable to create a directory to save the map." msgstr "Ðевозможно Ñоздать папку Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ ÐºÐ°Ñ€Ñ‚Ñ‹." msgid "Unable to locate a directory to save the map." msgstr "Ðе удалоÑÑŒ найти папку Ð´Ð»Ñ ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ ÐºÐ°Ñ€Ñ‚Ñ‹." msgid "Are you sure you want to overwrite the existing map?" msgstr "Ð’Ñ‹ дейÑтвительно хотите перезапиÑать ÑущеÑтвующую карту?" msgid "Map saved to: " msgstr "Карта Ñохранена в: " msgid "Failed to save the map." msgstr "Ðе удалоÑÑŒ Ñохранить карту." msgid "Used to place %{object}." msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð² типа %{object}." msgid "Select object type" msgstr "Выберите подтип" msgid "" "Click here to\n" "select a monster." msgstr "" "Ðажмите здеÑÑŒ,\n" "чтобы выбрать\n" "ÑущеÑтво." msgid "" "Click here to\n" "select another monster." msgstr "" "Ðажмите здеÑÑŒ,\n" "чтобы выбрать\n" "другое ÑущеÑтво." msgid "" "Cell\n" "Details" msgstr "" "Детали\n" "объекта" msgid "Erase" msgstr "ЛаÑтик" msgid "Mountains" msgstr "Горы" msgid "Rocks" msgstr "Камни" msgid "Trees" msgstr "ДеревьÑ" msgid "Water Objects" msgstr "Объекты воды" msgid "Miscellaneous" msgstr "Прочие" msgid "Artifacts" msgstr "Ðртефакты" msgid "Dwellings" msgstr "Жилища" msgid "Mines" msgstr "ИÑточники реÑурÑов" msgid "Power-ups" msgstr "БонуÑÑ‹" msgid "Treasures" msgstr "Сокровища" msgid "Heroes" msgstr "Герои" msgid "Towns" msgstr "Города" msgid "editorErasure|Landscape objects" msgstr "Объекты ландшафта" msgid "editorErasure|Adventure non pickable objects" msgstr "СтатичеÑкие интерактивные объекты" msgid "editorErasure|Castles" msgstr "Замки" msgid "editorErasure|Adventure pickable objects" msgstr "Сокровища и артефакты" msgid "editorErasure|Monsters" msgstr "СущеÑтва" msgid "editorErasure|Heroes" msgstr "Герои" msgid "editorErasure|Roads" msgstr "Дороги" msgid "editorErasure|Streams" msgstr "Реки" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "ЗаполнÑет ландшафт в облаÑти %{size} x %{size}." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "Стирает объекты в облаÑти %{size} x %{size}." msgid "Small Brush" msgstr "ÐœÐ°Ð»Ð°Ñ ÐºÐ¸Ñть" msgid "Medium Brush" msgstr "СреднÑÑ ÐºÐ¸Ñть" msgid "Large Brush" msgstr "Ð‘Ð¾Ð»ÑŒÑˆÐ°Ñ ÐºÐ¸Ñть" msgid "Area Fill" msgstr "Заполнить облаÑть" msgid "Used to click and drag for filling in large areas." msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð²Ñей выделенной облаÑти." msgid "Clear Area" msgstr "ОчиÑтить облаÑть" msgid "Used to click and drag for clearing large areas." msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ Ð¾Ñ‡Ð¸Ñтки вÑей выделенной облаÑти." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Ð”Ð»Ñ Ð²Ñех героев очки Ð¿ÐµÑ€ÐµÐ´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ñ‚Ñ€Ð°Ñ‚ÑÑ‚ÑÑ Ð² %{rate} раза больше. (Ðавык " "\"Следопыт\" Ñнижает или игнорирует данный штраф.)" msgid "Traversable only by boat." msgstr "Передвижение возможно только на кораблÑÑ…." msgid "No special modifiers." msgstr "Ðет оÑобых модификаторов." msgid "Toggle the erasure of %{type} objects." msgstr "Удаление объектов типа: %{type}." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Объекты данного типа будут удалены инÑтрументом \"ЛаÑтик\". Ðажмите левую " "кнопку мыши, чтобы иÑключить удаление объектов данного типа. Ðажмите и " "удерживайте Ñту кнопку, чтобы инÑтрумент ÐЕ удалÑл объекты вÑех оÑтальных " "типов." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Объекты данного типа ÐЕ будут удалены инÑтрументом \"ЛаÑтик\". Ðажмите левую " "кнопку мыши, чтобы включить удаление объектов данного типа. Ðажмите и " "удерживайте Ñту кнопку, чтобы инÑтрумент удалÑл объекты вÑех оÑтальных типов." msgid "Terrain Mode" msgstr "Почва" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñ€ÐµÐ»ÑŒÐµÑ„Ð° карты (травы, грÑзи, воды и Ñ‚.п.)." msgid "Landscape Objects Mode" msgstr "Режим Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð² ландшафта" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "ИÑпользуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð½Ð° карте объектов ландшафта (гор, камней, " "деревьев и Ñ‚.п.)." msgid "Detail Mode" msgstr "ХарактериÑтики" msgid "Used for special editing of action objects." msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñпециальных параметров активных объектов." msgid "Adventure Objects Mode" msgstr "Режим Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ‹Ñ… объектов" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "ИÑпользуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð½Ð° карте интерактивных объектов (артефактов, " "жилищ, шахт, Ñокровищ и Ñ‚.п.)." msgid "Kingdom Objects Mode" msgstr "Режим Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð² королевÑтва" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "ИÑпользуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð½Ð° карте объектов королевÑтва (городов, замков и " "героев)." msgid "Monsters Mode" msgstr "Режим Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ ÑущеÑтв" msgid "Used to place monsters on the map." msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚Ñ€Ñдов ÑущеÑтв на карте." msgid "Allows you to draw streams by clicking and dragging." msgstr "ПозволÑет прокладывать руÑла рек." msgid "Stream Mode" msgstr "Реки" msgid "Allows you to draw roads by clicking and dragging." msgstr "ПозволÑет прокладывать дороги." msgid "Road Mode" msgstr "Дороги" msgid "Erase Mode" msgstr "ЛаÑтик" msgid "Used to erase objects from the map." msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±ÑŠÐµÐºÑ‚Ð¾Ð² Ñ ÐºÐ°Ñ€Ñ‚Ñ‹." msgid "Change between zoom and normal view." msgstr "Сменить обычный режим на маÑштабированный." msgid "Magnify" msgstr "Лупа" msgid "Undo" msgstr "Отменить" msgid "Undo your last action." msgstr "Отменить поÑледнее дейÑтвие." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "Отменить поÑледнее дейÑтвие." msgid "Edit map title, description, and other general information." msgstr "Изменить название карты, опиÑание и прочие параметры." msgid "Specifications" msgstr "ХарактериÑтики" msgid "File Options" msgstr "ÐаÑтройки файла карты" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Открывает меню, где Ð’Ñ‹ можете Ñоздать новую карту, загрузить или Ñохранить " "уже готовую, а также выйти из редактора." msgid "View the editor system options, which let you customize the editor." msgstr "Открывает окно ÑиÑтемных наÑтроек редактора карт." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Создать карту размером %{size}x%{size} клеток." msgid "Cancel back to the New Map menu." msgstr "ВернутьÑÑ Ð² меню ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð½Ð¾Ð²Ð¾Ð¹ карты." msgid "Cancel back to the main menu." msgstr "ВернутьÑÑ Ð² главное меню." msgid "From Scratch" msgstr "С нулÑ" msgid "Start from scratch with a blank map." msgstr "Создать карту Ñ Ð½ÑƒÐ»Ñ." msgid "Create a randomly generated map." msgstr "Создать Ñлучайную карту." msgid "Random" msgstr "Ð¡Ð»ÑƒÑ‡Ð°Ð¹Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°" msgid "Cancel back to the Map Editor main menu." msgstr "ВернутьÑÑ Ð² главное меню редактора карт." msgid "No maps available!" msgstr "Ðет доÑтупных карт!" msgid "[%{pos}]: %{race} hero" msgstr "[%{pos}]: герой - %{race}" msgid "[%{pos}]: %{name}, %{race} hero" msgstr "[%{pos}]: %{name}, герой - %{race}" msgid "[%{pos}]: %{race} town" msgstr "[%{pos}]: %{race} (город)" msgid "[%{pos}]: %{race} castle" msgstr "[%{pos}]: %{race} (замок)" msgid "[%{pos}]: %{name}, %{race} town" msgstr "[%{pos}]: %{name}, %{race} (город)" msgid "[%{pos}]: %{name}, %{race} castle" msgstr "[%{pos}]: %{name}, %{race} (замок)" msgid "None." msgstr "Ðет." msgid "One side defeats another." msgstr "Один Ñоюз побеждает других." msgid "Accumulate gold." msgstr "Ðакопить золото." msgid "Run out of time." msgstr "Ðе уÑпеть вовремÑ." msgid "alliance|1st" msgstr "1-ый" msgid "alliance|2nd" msgstr "2-ой" msgid "alliance|3rd" msgstr "3-ий" msgid "alliance|4th" msgstr "4-ый" msgid "alliance|5th" msgstr "5-ый" msgid "Special Loss Condition" msgstr "ОÑобое уÑловие поражениÑ" msgid "Special Victory Condition" msgstr "ОÑобое уÑловие победы" msgid "Allow standard victory conditions" msgstr "Разрешить обычную победу" msgid "Allow this condition also for AI" msgstr "ПрименÑть уÑловие и к ИИ" msgid "Set alliances:" msgstr "Задать Ñоюзы игроков:" msgid "{%number} alliance: " msgstr "{%number} Ñоюз: " msgid "Gold:" msgstr "Золото:" msgid "Select a Town to capture to achieve victory" msgstr "Выберите город, который Ñледует захватить" msgid "Click here to change the town needed to capture to achieve victory." msgstr "" "Ðажмите, чтобы Ñменить город, который необходимо захватить Ð´Ð»Ñ Ð´Ð¾ÑÑ‚Ð¸Ð¶ÐµÐ½Ð¸Ñ " "победы." msgid "Select a Hero to defeat to achieve victory" msgstr "Выберите героÑ, которого Ñледует победить" msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "" "Ðажмите, чтобы Ñменить героÑ, которого необходимо победить Ð´Ð»Ñ Ð´Ð¾ÑÑ‚Ð¸Ð¶ÐµÐ½Ð¸Ñ " "победы." msgid "Put %{color} player in the %{alliance} alliance" msgstr "ПомеÑтить игрока цвета %{color} в %{alliance} Ñоюз" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" "ЕÑли Ñтот флажок уÑтановлен, то в %{alliance} Ñоюз будет помещён %{color} " "игрок." msgid "Days:" msgstr "Дней:" msgid "Select a Town to lose to suffer defeat" msgstr "Выберите город, Ð¿Ð¾Ñ‚ÐµÑ€Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ - поражение" msgid "Click here to change the town whose loss would mean defeat." msgstr "" "Ðажмите, чтобы Ñменить город, Ð¿Ð¾Ñ‚ÐµÑ€Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ будет означать поражение." msgid "Select a Hero to lose to suffer defeat" msgstr "Выберите героÑ, Ð¿Ð¾Ñ‚ÐµÑ€Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ - поражение" msgid "Click here to change the hero whose loss would mean defeat." msgstr "" "Ðажмите, чтобы Ñменить героÑ, Ð¿Ð¾Ñ‚ÐµÑ€Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ будет означать поражение." msgid "Map Difficulty" msgstr "СложноÑть карты" msgid "Map Description" msgstr "ОпиÑание карты" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" "Введённое опиÑание карты превышает макÑимально допуÑтимый размер в 5 Ñтрок. " "Оно будет Ñокращено до размера текÑтового Ð¿Ð¾Ð»Ñ Ð¾Ð¿Ð¸ÑÐ°Ð½Ð¸Ñ ÐºÐ°Ñ€Ñ‚Ñ‹." msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" "Текущий Ñзык карты - %{oldLanguage}. Ð’Ñ‹ ÑобираетеÑÑŒ Ñменить его на " "%{newLanguage}, поÑле чего некоторые ÑÐ¾Ð¾Ð±Ñ‰ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³ÑƒÑ‚ отображатьÑÑ " "некорректно. Ð’Ñ‹ хотите продолжить?" msgid "Change Map Name" msgstr "Изменить название карты" msgid "Change Map Description" msgstr "Изменить опиÑание карты" msgid "Click to accept the changes made." msgstr "Ðажмите, чтобы применить внеÑённые изменениÑ." msgid "Click to edit custom rumors." msgstr "Ðажмите, чтобы отредактировать пользовательÑкие Ñлухи." msgid "Rumors" msgstr "Слухи" msgid "Click to edit daily events." msgstr "Ðажмите, чтобы отредактировать календарные ÑобытиÑ." msgid "Events" msgstr "СобытиÑ" msgid "Click to change the language of the map." msgstr "Изменить Ñзык, иÑпользуемый на карте." msgid "Click to change your map name." msgstr "Ðажмите, чтобы изменить название Вашей карты." msgid "Map Name" msgstr "Ðазвание карты" msgid "Click to change the description of the current map." msgstr "Ðажмите, чтобы изменить опиÑание текущей карты." msgid "Click to change the victory condition of the current map." msgstr "Ðажмите, чтобы изменить уÑловие победы на текущей карте." msgid "Click to change the loss condition of the current map." msgstr "Ðажмите, чтобы изменить уÑловие Ð¿Ð¾Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° текущей карте." msgid "Indicates the player types in the scenario. Click to change." msgstr "Обозначает типы игроков в Ñценарии. Ðажмите, чтобы изменить." msgid "Player Type" msgstr "Тип игрока" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Ðажмите, чтобы уÑтановить ÑложноÑть карты. Ð’ более Ñложных карах может быть " "больше врагов, либо враги могут быть более Ñильными. Такие карты могут " "Ñодержать меньше реÑурÑов или иметь прочие уÑловиÑ, уÑложнÑющие жизнь игроку-" "человеку." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Подарить %{resource}:" msgid "Animation" msgstr "ÐнимациÑ" msgid "Passability" msgstr "ПроходимоÑть" msgid "Toggle animation of the objects." msgstr "Включить или выключить анимацию объектов." msgid "Toggle display of objects' passability." msgstr "Включить или выключить отображение проходимоÑти объектов." msgid "Rumor:" msgstr "Слух:" msgid "Rumor" msgstr "Слух" msgid "This rumor already exists in the list." msgstr "Такой Ñлух уже еÑть в ÑпиÑке." msgid "Click to save the rumors." msgstr "Ðажмите, чтобы Ñохранить Ñлухи." msgid "Add Rumor" msgstr "Добавить Ñлух" msgid "Add an additional rumor." msgstr "Добавить дополнительные Ñлух." msgid "Edit Rumor" msgstr "Редактировать Ñлух" msgid "Edit an existing rumor." msgstr "Редактировать выбранный Ñлух." msgid "Delete Rumor" msgstr "Удалить Ñлух" msgid "Delete an existing rumor." msgstr "Удалить выбранный Ñлух." msgid "" "\n" "\n" "Size: " msgstr "" "\n" "\n" "Размер: " msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "ОпиÑание: " msgid "Save Map:" msgstr "Сохранить карту:" msgid "Click to save the current map." msgstr "Ðажмите, чтобы Ñохранить текущую карту." msgid "Riddle:" msgstr "Загадка:" msgid "Answers:" msgstr "Ответы:" msgid "Answer:" msgstr "Ответ:" msgid "Answer" msgstr "Ответ" msgid "This answer exists in the list." msgstr "Такой ответ уже еÑть в ÑпиÑке." msgid "Click to save the Sphinx properties." msgstr "Ðажмите, чтобы Ñохранить параметры загадки ÑфинкÑа." msgid "Add Answer" msgstr "Добавить ответ" msgid "Add an additional answer for the question." msgstr "Добавить дополнительные ответ на Ð²Ð¾Ð¿Ñ€Ð¾Ñ Ð·Ð°Ð³Ð°Ð´ÐºÐ¸." msgid "Edit Answer" msgstr "Изменить ответ" msgid "Edit an existing answer for the question." msgstr "Изменить имеющийÑÑ Ð¾Ñ‚Ð²ÐµÑ‚ на вопроÑ." msgid "Delete Answer" msgstr "Удалить ответ" msgid "Delete an existing answer for the question." msgstr "Удалить имеющийÑÑ Ð¾Ñ‚Ð²ÐµÑ‚ на вопроÑ." msgid "No artifact will be given as a reward." msgstr "Ð’ вознаграждении не будет выдаватьÑÑ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚." msgid "Delete an artifact from the reward." msgstr "Удалить артефакт из вознаграждениÑ." msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "День: %{day} ÐеделÑ: %{week} МеÑÑц: %{month}" msgid "difficulty|Easy" msgstr "ПроÑтаÑ" msgid "difficulty|Normal" msgstr "ÐормальнаÑ" msgid "difficulty|Hard" msgstr "СложнаÑ" msgid "difficulty|Expert" msgstr "ЭкÑперт" msgid "difficulty|Impossible" msgstr "ÐевозможнаÑ" msgid "and more..." msgstr "и Ñ‚.д." msgid "Easy" msgstr "ЛёгкаÑ" msgid "Normal" msgstr "ОбычнаÑ" msgid "Hard" msgstr "ТÑжёлаÑ" msgid "Campaign Difficulty" msgstr "СложноÑть кампании" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Выберите данный уровень ÑложноÑти, еÑли Ð’Ñ‹ предпочитаете Ñюжет, а не Ñложные " "ÑражениÑ. ИИ Ñлабее, чем обычно." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Выберите данный уровень ÑложноÑти, чтобы наÑладитьÑÑ ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸ÐµÐ¹, как она " "первоначально задумывалаÑÑŒ." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Выберите данный уровень ÑложноÑти, еÑли хотите Ñерьёзных Ñражений. ИИ " "Ñильнее, чем обычно." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "ПоздравлÑем!\n" "\n" "Дней: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "СложноÑть: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Очки: %{score}\n" "\n" "Рейтинг:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Ðачать выбранный Ñценарий." msgid "View Intro" msgstr "ПоÑмотреть вÑтупление" msgid "View the intro video for the current state of the campaign." msgstr "ПроÑмотреть вÑтупительное видео к текущему Ñценарию кампании." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "Выбор ÑложноÑти кампании. СложноÑть можно понизить в любой момент." msgid "Restart the current scenario." msgstr "Ðачать Ñначала текущий Ñценарий." msgid "Difficulty" msgstr "СложноÑть" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Ð’Ñ‹ понизили ÑложноÑть кампании и позже не Ñможете вернуть её обратно. " "Рейтинг за прохождение кампании будет раÑÑчитыватьÑÑ Ð¸Ñключительно на оÑнове " "новой ÑложноÑти. Ð’Ñ‹ хотите продолжить?" msgid "Are you sure you want to restart this scenario?" msgstr "Ð’Ñ‹ дейÑтвительно хотите начать Ñтот Ñценарий Ñначала?" msgid "Campaign Scenario loading failure" msgstr "Сбой загрузки ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ð¸" msgid "Please make sure that campaign files are correct and present." msgstr "ПожалуйÑта, убедитеÑÑŒ, что файлы кампании верны и приÑутÑтвуют." msgid "Days spent" msgstr "Затрачено дней" msgid "The number of days spent on this campaign." msgstr "КоличеÑтво дней, потраченных на Ñту кампанию." msgid "Project Coordination and Core Development" msgstr "Координатор проекта и оÑновной разработчик" msgid "Development" msgstr "Разработка" msgid "Visit us at " msgstr "ПоÑетите Ð½Ð°Ñ " msgid "QA and Support" msgstr "Контроль качеÑтва и поддержка" msgid "Dev and Support" msgstr "Разработка и поддержка" msgid "Special Thanks to" msgstr "ОÑÐ¾Ð±Ð°Ñ Ð±Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ð½Ð¾Ñть" msgid "and many-many other contributors and supporters!" msgstr "и многим другим, кто учаÑтвует в развитии и поддерживает проект!" msgid "Support us at" msgstr "Поддержите наÑ" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" "https://www.patreon.com/fheroes2\n" "https://boosty.to/fheroes2" msgid "Connect with us at" msgstr "ПриÑоединÑйтеÑÑŒ к нам" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" "https://vk.com/fheroes2\n" "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Вам нужна помощь по игре?" msgid "Original project before 0.7" msgstr "Разработчик до 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Разработчики Heroes of Might and Magic II: The Succession Wars" msgid "Designed and Directed" msgstr "Геймдизайнер" msgid "Programming and Design" msgstr "ПрограммиÑÑ‚ и дизайнер" msgid "Executive Producer" msgstr "ИÑполнительный продюÑер" msgid "Producer" msgstr "ПродюÑер" msgid "Additional Design" msgstr "Дополнительные дизайнеры" msgid "Additional Programming" msgstr "Дополнительные программиÑты" msgid "Musical Production" msgstr "Музыкальный продюÑер" msgid "Music and Sound Design" msgstr "Композиторы и звукорежиÑÑёры" msgid "Vocalists" msgstr "ВокалиÑты" msgid "Art Director" msgstr "Главный художник" msgid "Assistant Art Director" msgstr "Помощник главного художника" msgid "Artists" msgstr "Художники" msgid "QA Manager" msgstr "Менеджер по контролю качеÑтва" msgid "QA" msgstr "Контроль качеÑтва" msgid "Writing" msgstr "Главный ÑценариÑÑ‚" msgid "Manual and Helpfile" msgstr "Помощь и Ñправка" msgid "Scenarios" msgstr "Разработка карт" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Разработчики Heroes of Might and Magic II: The Price of Loyalty" msgid "Design Lead" msgstr "Ведущий дизайнер" msgid "Designers" msgstr "Дизайнеры" msgid "Programming Lead" msgstr "Ведущий программиÑÑ‚" msgid "Art Lead" msgstr "ХудожеÑтвенный руководитель" msgid "Playtesters" msgstr "ТеÑтеры игры" msgid "Designer" msgstr "Дизайнер" msgid "Producers" msgstr "ПродюÑеры" msgid "QA Managers" msgstr "Менеджеры по контролю качеÑтва" msgid "Sound Design" msgstr "Звуковое оформление" msgid "Town Themes" msgstr "Музыкальные темы городов" msgid "Alto Sax" msgstr "Ðльт-ÑакÑофон" msgid "Harpsichord and Piano" msgstr "КлавеÑин и фортепиано" msgid "Basso Vocal" msgstr "БаÑÑ Ð²Ð¾ÐºÐ°Ð»" msgid "Soprano Vocal" msgstr "Сопрано вокал" msgid "Recorded at %{recordingStudio}" msgstr "ЗапиÑано на %{recordingStudio}" msgid "credits|Manual" msgstr "РуководÑтво по игре" msgid "German Consultant" msgstr "Ðемецкий конÑультант" msgid "Map Designers" msgstr "Разработка карт" msgid "Package Design" msgstr "Дизайн упаковки" msgid "High Scores" msgstr "Рейтинги" msgid "Your Name" msgstr "Ваше имÑ" msgid "Unknown Hero" msgstr "ÐеизвеÑтный герой" msgid "Standard" msgstr "ÐžÐ±Ñ‹Ñ‡Ð½Ð°Ñ Ð¸Ð³Ñ€Ð°" msgid "View High Scores for Standard Maps." msgstr "ПоÑмотреть очки рейтинга за обычные игры." msgid "Campaign" msgstr "КампаниÑ" msgid "View High Scores for Campaigns." msgstr "ПоÑмотреть очки рейтинга за кампании." msgid "hotkey|default okay event" msgstr "нажать ок в диалоге" msgid "hotkey|default cancel event" msgstr "нажать отмена в диалоге" msgid "hotkey|default left" msgstr "клавиша влево" msgid "hotkey|default right" msgstr "клавиша вправо" msgid "hotkey|default up" msgstr "клавиша вверх" msgid "hotkey|default down" msgstr "клавиша вниз" msgid "hotkey|toggle fullscreen" msgstr "переключить полноÑкранный режим" msgid "hotkey|toggle text support mode" msgstr "текÑтовое Ñопровождение (вкл./выкл.)" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "текÑтовое Ñопровождение (вкл./выкл.)" msgid "hotkey|new game" msgstr "Ð½Ð¾Ð²Ð°Ñ Ð¸Ð³Ñ€Ð°" msgid "hotkey|load game" msgstr "загрузить игру" msgid "hotkey|high scores" msgstr "рейтинги" msgid "hotkey|credits" msgstr "авторы" msgid "hotkey|standard game" msgstr "Ð¾Ð±Ñ‹Ñ‡Ð½Ð°Ñ Ð¸Ð³Ñ€Ð°" msgid "hotkey|campaign game" msgstr "кампаниÑ" msgid "hotkey|multi-player game" msgstr "многопользовательÑÐºÐ°Ñ Ð¸Ð³Ñ€Ð°" msgid "hotkey|settings" msgstr "наÑтройки" msgid "hotkey|quit" msgstr "выйти из игры" msgid "hotkey|select map" msgstr "выбрать карту" msgid "hotkey|select small map size" msgstr "показать маленькие карты" msgid "hotkey|select medium map size" msgstr "показать Ñредние карты" msgid "hotkey|select large map size" msgstr "показать большие карты" msgid "hotkey|select extra large map size" msgstr "показать очень большие карты" msgid "hotkey|select all map sizes" msgstr "показать карты вÑех размеров" msgid "hotkey|hot seat game" msgstr "режим за одним компьютером" msgid "hotkey|battle only game" msgstr "режим битвы" msgid "hotkey|choose the original campaign" msgstr "выбрать кампанию: войны за преÑтол" msgid "hotkey|choose the expansion campaign" msgstr "выбрать кампании Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ñ†ÐµÐ½Ð° верноÑти" msgid "hotkey|map editor main menu" msgstr "меню редактора карт" msgid "hotkey|new map menu" msgstr "меню новой карты" msgid "hotkey|load map menu" msgstr "меню загрузки карты" msgid "hotkey|new map from scratch" msgstr "Ð½Ð¾Ð²Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° Ñ Ð½ÑƒÐ»Ñ" msgid "hotkey|new random map" msgstr "Ð½Ð¾Ð²Ð°Ñ ÑÐ»ÑƒÑ‡Ð°Ð¹Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð°" msgid "hotkey|undo last action" msgstr "отменить поÑледнее дейÑтвие" msgid "hotkey|redo last action" msgstr "повторить поÑледнее дейÑтвие" msgid "hotkey|open game main menu" msgstr "открыть главное меню" msgid "hotkey|toggle passability" msgstr "переключить отображение проходимоÑти" msgid "hotkey|roland campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð·Ð° роланда" msgid "hotkey|archibald campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ Ð·Ð° арчибальда" msgid "hotkey|price of loyalty campaign" msgstr "кампаниÑ: цена верноÑти" msgid "hotkey|voyage home campaign" msgstr "кампаниÑ: дорога домой" msgid "hotkey|wizard's isle campaign" msgstr "кампаниÑ: оÑтров чародеев" msgid "hotkey|descendants campaign" msgstr "кампаниÑ: наÑледники" msgid "hotkey|select first campaign bonus" msgstr "выбрать первый Ð±Ð¾Ð½ÑƒÑ ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ð¸" msgid "hotkey|select second campaign bonus" msgstr "выбрать второй Ð±Ð¾Ð½ÑƒÑ ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ð¸" msgid "hotkey|select third campaign bonus" msgstr "выбрать третий Ð±Ð¾Ð½ÑƒÑ ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ð¸" msgid "hotkey|view campaign intro" msgstr "поÑмотреть вÑтупление кампании" msgid "hotkey|select campaign difficulty" msgstr "выбрать ÑложноÑть кампании" msgid "hotkey|restart campaign scenario" msgstr "переиграть Ñценарий кампании" msgid "hotkey|world map left" msgstr "перемеÑтить карту мира влево" msgid "hotkey|world map right" msgstr "перемеÑтить карту мира вправо" msgid "hotkey|world map up" msgstr "перемеÑтить карту мира вверх" msgid "hotkey|world map down" msgstr "перемеÑтить карту мира вниз" msgid "hotkey|world map up left" msgstr "перемеÑтить карту мира влево-вверх" msgid "hotkey|world map up right" msgstr "перемеÑтить карту мира вправо-вверх" msgid "hotkey|world map down left" msgstr "перемеÑтить карту мира влево-вниз" msgid "hotkey|world map down right" msgstr "перемеÑтить карту мира вправо-вниз" msgid "hotkey|save game" msgstr "Ñохранить игру" msgid "hotkey|next hero" msgstr "Ñледующий герой" msgid "hotkey|change to hero under cursor" msgstr "переключитьÑÑ Ð½Ð° Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾Ð´ курÑором" msgid "hotkey|start hero movement" msgstr "начать движение героÑ" msgid "hotkey|cast adventure spell" msgstr "произнеÑти заклинание приключениÑ" msgid "hotkey|put hero to sleep" msgstr "уÑыпить/разбудить героÑ" msgid "hotkey|next town" msgstr "Ñледующий город" msgid "hotkey|end turn" msgstr "окончить ход" msgid "hotkey|file options" msgstr "дейÑÑ‚Ð²Ð¸Ñ Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð¼ карты" msgid "hotkey|adventure options" msgstr "игровые дейÑтвиÑ" msgid "hotkey|puzzle map" msgstr "карта-головоломка" msgid "hotkey|scenario information" msgstr "Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ Ñценарии" msgid "hotkey|dig for artifact" msgstr "выкопать артефакт" msgid "hotkey|view world" msgstr "обзор мира" msgid "hotkey|kingdom summary" msgstr "обзор королевÑтва" msgid "hotkey|default action" msgstr "дейÑтвие по умолчанию" msgid "hotkey|open focus" msgstr "открыть выбранный объект" msgid "hotkey|system options" msgstr "наÑтройки ÑиÑтемы" msgid "hotkey|scroll left" msgstr "прокрутка влево" msgid "hotkey|scroll right" msgstr "прокрутка вправо" msgid "hotkey|scroll up" msgstr "прокрутка вверх" msgid "hotkey|scroll down" msgstr "прокрутка вниз" msgid "hotkey|toggle control panel" msgstr "отображение панели ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ (при Ñкрытом интерфейÑе)" msgid "hotkey|toggle radar" msgstr "отображение мини-карты (при Ñкрытом интерфейÑе)" msgid "hotkey|toggle buttons" msgstr "отображение кнопок (при Ñкрытом интерфейÑе)" msgid "hotkey|toggle status" msgstr "отображение ÑтатуÑа (при Ñкрытом интерфейÑе)" msgid "hotkey|toggle icons" msgstr "отображение значков (при Ñкрытом интерфейÑе)" msgid "hotkey|transfer control to ai" msgstr "передать управление ии" msgid "hotkey|retreat from battle" msgstr "отÑтупление из битвы" msgid "hotkey|surrender during battle" msgstr "ÑдатьÑÑ Ð² битве" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "включить режим автобитвы" #, fuzzy msgid "hotkey|quick combat" msgstr "выйти из игры" msgid "hotkey|battle options" msgstr "наÑтройки битвы" msgid "hotkey|skip turn in battle" msgstr "пропуÑтить ход в битве" msgid "hotkey|cast battle spell" msgstr "произнеÑти боевое заклинание" msgid "hotkey|dwelling level 1" msgstr "поÑеление 1 уровнÑ" msgid "hotkey|dwelling level 2" msgstr "поÑеление 2 уровнÑ" msgid "hotkey|dwelling level 3" msgstr "поÑеление 3 уровнÑ" msgid "hotkey|dwelling level 4" msgstr "поÑеление 4 уровнÑ" msgid "hotkey|dwelling level 5" msgstr "поÑеление 5 уровнÑ" msgid "hotkey|dwelling level 6" msgstr "поÑеление 6 уровнÑ" msgid "hotkey|well" msgstr "колодец" msgid "hotkey|marketplace" msgstr "рынок" msgid "hotkey|mage guild" msgstr "Ð³Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð¼Ð°Ð³Ð¾Ð²" msgid "hotkey|shipyard" msgstr "верфь" msgid "hotkey|thieves guild" msgstr "Ð³Ð¸Ð»ÑŒÐ´Ð¸Ñ Ð²Ð¾Ñ€Ð¾Ð²" msgid "hotkey|tavern" msgstr "таверна" msgid "hotkey|construction screen" msgstr "Ñкран ÑтроительÑтва замка" msgid "hotkey|buy all monsters in well" msgstr "купить вÑех ÑущеÑтв в колодце" msgid "hotkey|split stack by half" msgstr "разделить отрÑд пополам" msgid "hotkey|split stack by one" msgstr "отделить от отрÑда одно ÑущеÑтво" msgid "hotkey|join stacks" msgstr "объединить отрÑды" msgid "hotkey|upgrade troop" msgstr "улучшить ÑущеÑтво" msgid "hotkey|dismiss hero or troop" msgstr "уволить Ð³ÐµÑ€Ð¾Ñ Ð¸Ð»Ð¸ ÑущеÑтво" #, fuzzy msgid "hotkey|exchange all troops" msgstr "улучшить ÑущеÑтво" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Хотите ли Ð’Ñ‹ вернуть Ñебе управление игрой? Возврат вÑтупит в Ñилу Ñо " "Ñледующего хода." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Хотите ли Ð’Ñ‹ передать управление ИИ? Передача вÑтупит в Ñилу Ñо Ñледующего " "хода." msgid "Default Actions" msgstr "Стандартные дейÑтвиÑ" msgid "Global Actions" msgstr "Общие дейÑтвиÑ" msgid "World Map" msgstr "Карта мира" msgid "Battle Screen" msgstr "Экран битвы" msgid "Town Screen" msgstr "Экран города" msgid "Army Actions" msgstr "ДейÑÑ‚Ð²Ð¸Ñ Ð°Ñ€Ð¼Ð¸Ð¸" msgid "The save file is corrupted." msgstr "Файл ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð²Ñ€ÐµÐ¶Ð´Ñ‘Ð½." msgid "Unsupported save format: " msgstr "Ðеподдерживаемый формат ÑохранениÑ: " msgid "Current game version: " msgstr "Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ð¸Ð³Ñ€Ñ‹: " msgid "Last supported version: " msgstr "ПоÑледнÑÑ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ð²ÐµÑ€ÑиÑ: " msgid "This file contains a save with an invalid game type." msgstr "Этот файл Ñодержит Ñохранение Ñ Ð½ÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ñ‹Ð¼ типом игры." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Ð”Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð³Ð¾ файла ÑÐ¾Ñ…Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ñ‚Ñ€ÐµÐ±ÑƒÑŽÑ‚ÑÑ Ñ€ÐµÑурÑÑ‹ Ð´Ð¾Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ \"Цена верноÑти\", " "но они не обнаружены." msgid "This saved game is localized to '" msgstr "Эта ÑÐ¾Ñ…Ñ€Ð°Ð½Ñ‘Ð½Ð½Ð°Ñ Ð¸Ð³Ñ€Ð° локализована на '" msgid "' language, but the current language of the game is '" msgstr "' Ñзыке, но текущий Ñзык игры - " msgid "No save files to load." msgstr "Ðет Ñохранённых игр." msgid "Hot Seat" msgstr "За одним компьютером" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Сыграть в игру в режиме \"ГорÑчий Ñтул\", когда от 2 до 6 игроков играют на " "одном уÑтройÑтве, ÑменÑÑ Ð´Ñ€ÑƒÐ³ друга, когда наÑтупает очередь их хода." msgid "A single player game playing out a single map." msgstr "ÐžÐ´Ð¸Ð½Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð³Ñ€Ð° на одиночной карте." msgid "Standard Game" msgstr "ÐžÐ±Ñ‹Ñ‡Ð½Ð°Ñ Ð¸Ð³Ñ€Ð°" msgid "A single player game playing through a series of maps." msgstr "ÐžÐ´Ð¸Ð½Ð¾Ñ‡Ð½Ð°Ñ Ð¸Ð³Ñ€Ð° на Ñерии карт." msgid "Campaign Game" msgstr "КампаниÑ" msgid "Multi-Player Game" msgstr "Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ Ð¸Ð³Ñ€Ð°" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "Ð¡ÐµÑ‚ÐµÐ²Ð°Ñ Ð¸Ð³Ñ€Ð° Ñ Ð½ÐµÑколькими игроками-людьми на одиночной карте." msgid "fheroes2 Resurrection Team presents" msgstr "Команда fheroes2 Resurrection предÑтавлÑет" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "Добро пожаловать в Heroes of Might and Magic II на движке fheroes2!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" "\n" "\n" "Чтобы Ñымитировать нажатие правой кнопки мыши на ÑенÑорном Ñкране, Ð´Ð»Ñ " "Ð¿Ð¾Ð»ÑƒÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ð¸ о различных объектах в игре, Вам нужно Ñначала нажать " "на интереÑующий объект, а затем, ÑƒÐ´ÐµÑ€Ð¶Ð¸Ð²Ð°Ñ Ð½Ð°Ð¶Ð°Ñ‚Ð¸Ðµ, коÑнутьÑÑ Ð»ÑŽÐ±Ð¾Ð³Ð¾ другого " "меÑта на Ñкране вторым пальцем. Ð£Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°Ñ Ð²Ñ‚Ð¾Ñ€Ð¾Ð¹ палец, вы можете убрать " "первый Ñ Ñкрана и продолжить проÑмотр информации об объекте." msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "\n" "\n" "Перед началом игры, пожалуйÑта, выберите разрешение Ñкрана." msgid "Greetings!" msgstr "Добро пожаловать!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "Завершить игру Heroes of Might and Magic II и вернутьÑÑ Ð² ÑиÑтему." msgid "Credits" msgstr "Ðвторы" msgid "View the credits screen." msgstr "ПроÑмотр окна авторов." msgid "View the high scores screen." msgstr "ПроÑмотр лучших результатов." msgid "Create new or modify existing maps." msgstr "Создать новую или изменить текущую карту." msgid "Change language, resolution and settings of the game." msgstr "Сменить Ñзык, разрешение и наÑтройки игры." msgid "Game Settings" msgstr "ÐаÑтройки игры" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "ОтÑутÑтвуют видеофайлы, необходимые Ð´Ð»Ñ Ð¾ÐºÐ½Ð° выбора кампании. ПожалуйÑта, " "убедитеÑÑŒ, что вÑе необходимые файлы приÑутÑтвуют в ÑиÑтеме." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "Кампании Роланда и Ðрчибальда из оригинальных Героев Меча и Магии II." msgid "Original Campaign" msgstr "Ð¡Ñ‚Ð°Ñ€Ð°Ñ ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ" msgid "Expansion Campaign" msgstr "ÐÐ¾Ð²Ð°Ñ ÐºÐ°Ð¼Ð¿Ð°Ð½Ð¸Ñ" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "Одна из четырёх новых кампаний из набора дополнений \"Цена верноÑти\"." msgid "Loading video. Please wait..." msgstr "Загрузка видео. ПожалуйÑта, подождите..." msgid "Host" msgstr "ХоÑÑ‚" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "ХоÑÑ‚ задаёт параметры игры. Ð’ одной Ñетевой игре может учаÑтвовать только " "один хоÑÑ‚." msgid "Guest" msgstr "ГоÑть" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "ГоÑть ждёт пока хоÑÑ‚ наÑтроит игру, а затем автоматичеÑки приÑоединитÑÑ Ðº " "ней. Ð”Ð»Ñ Ð¸Ð³Ñ€ по протоколу TCP/IP может быть неÑколько гоÑтей." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "Ð”Ð»Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ fheroes2 необходимы файлы данных от оригинальной игры Heroes of " "Might and Magic II. Ð¡ÑƒÐ´Ñ Ð¿Ð¾ вÑему, Ð’Ñ‹ иÑпользуете файлы от демо-верÑии " "Heroes of Might and Magic II. Учтите, что в таком Ñлучае Вам будет доÑтупен " "только один Ñценарий." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "МногопользовательÑÐºÐ°Ñ Ð¸Ð³Ñ€Ð°, в которой неÑколько игроков-людей Ñоперничают на " "одой карте." msgid "Battle Only" msgstr "ДуÑль" msgid "Setup and play a battle without loading any map." msgstr "ÐаÑтройте и играйте в битву без загрузки карты." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Сыграть в игру в режиме \"ГорÑчий Ñтул\", когда от 2 до 6 игроков играют на " "одном уÑтройÑтве, ÑменÑÑ Ð´Ñ€ÑƒÐ³ друга, когда наÑтупает очередь их хода." msgid "2 Players" msgstr "2 игрока" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "2 игрока, оÑтальными управлÑет компьютер." msgid "3 Players" msgstr "3 игрока" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "3 игрока, оÑтальными управлÑет компьютер." msgid "4 Players" msgstr "4 игрока" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "4 игрока, оÑтальными управлÑет компьютер." msgid "5 Players" msgstr "5 игроков" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "5 игроков и 1 компьютер." msgid "6 Players" msgstr "6 игроков" msgid "Play with 6 human players." msgstr "Ð’Ñе игроки - люди." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Город драконов пал! Теперь Ð’Ñ‹ повелитель драконов." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Ð’Ñ‹ захватили %{name}!\n" "Победа за вами." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Ð’Ñ‹ захватили вражеÑкого Ð³ÐµÑ€Ð¾Ñ %{name}!\n" "Ваше задание выполнено." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Ð’Ñ‹ нашли %{name}.\n" "Ваше задание выполнено." msgid "Ultimate Artifact" msgstr "Великий артефакт" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Враг повержен.\n" "Ð’Ñ‹ празднуете победу!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Ð’ вашей Ñокровищнице накопилоÑÑŒ более %{count} золота.\n" "Ваши враги преклонÑÑŽÑ‚ÑÑ Ð¿ÐµÑ€ÐµÐ´ Вашим богатÑтвом и могущеÑтвом." msgid "Victory!" msgstr "Победа!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Враг захватил %{name}!\n" "Ð’Ñ‹ проиграли." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Ð’ Ñокровищнице врага накопилоÑÑŒ более %{count} золота.\n" "Ð’Ñ‹ вынуждены преклонитьÑÑ Ð¿ÐµÑ€ÐµÐ´ его богатÑтвом и могущеÑтвом." msgid "You have been eliminated from the game!!!" msgstr "Ð’Ñ‹ были иÑключены из игры!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Ð’Ñ‹ потерÑли Ð³ÐµÑ€Ð¾Ñ %{name}.\n" "Ваше приключение окончено." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Ð’Ñ‹ не ÑправилиÑÑŒ Ñ Ð·Ð°Ð´Ð°Ð½Ð¸ÐµÐ¼ за отведённое времÑ.\n" "Ð’ÑÑ‘ кончено." msgid "Defeat!" msgstr "Поражение!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Базовые очки: %{score}\n" "СложноÑть: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Победите вÑех вражеÑких героев и захватите вÑе вражеÑкие города и замки." msgid "Your side defeats the opposing side." msgstr "Победить вмеÑте Ñ Ñоюзником вÑех противников." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Ðе уÑпеть вовремÑ." msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "" "Ваш единÑтвенный противник - %{enemies}. Одолейте его и победа будет Ваша!" msgstr[1] "%{enemies} в Ñоюзе против ВаÑ. Победите вÑех Ваших противников." msgstr[2] "%{enemies} в Ñоюзе против ВаÑ. Победите вÑех Ваших противников." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "%{allies} на Вашей Ñтороне, а %{enemies} - против ВаÑ. Одолейте Вашего " "противника." msgstr[1] "" "%{allies} на Вашей Ñтороне, а %{enemies} - против ВаÑ. Одолейте вражеÑкий " "альÑнÑ." msgstr[2] "" "%{allies} на Вашей Ñтороне, а %{enemies} - против ВаÑ. Одолейте вражеÑкий " "альÑнÑ." msgid "Capture the castle '%{name}'." msgstr "Захватить замок '%{name}'." msgid "Capture the town '%{name}'." msgstr "Захватить город '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Победить Ð³ÐµÑ€Ð¾Ñ '%{name}'." msgid "Find the ultimate artifact." msgstr "Ðайти великий артефакт." msgid "Find the '%{name}' artifact." msgstr "Ðайти артефакт '%{name}'." msgid "Accumulate %{count} gold." msgstr "Ðакопить %{count} золота." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", также Ð’Ñ‹ выигрываете еÑли победите вÑех героев или захватите вÑе города " "противника." msgid "Lose the castle '%{name}'." msgstr "ПотерÑть замок '%{name}'." msgid "Lose the town '%{name}'." msgstr "ПотерÑть город '%{name}'." msgid "Lose the hero: %{name}." msgstr "ПотерÑть Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ имени %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Ðе уÑпеть победить до указанной даты: меÑÑц %{month}, Ð½ÐµÐ´ÐµÐ»Ñ %{week}, день " "%{day}." msgid "%{color} player has been vanquished!" msgstr "%{color} игрок побеждён!" msgid "Major Event!" msgstr "Важное Ñобытие!" msgid "Scenario:" msgstr "Сценарий:" msgid "Game Difficulty:" msgstr "СложноÑть игры:" msgid "Opponents:" msgstr "Оппоненты:" msgid "Class:" msgstr "КлаÑÑ:" msgid "Rating %{rating}%" msgstr "Рейтинг %{rating}%" msgid "Click here to select which scenario to play." msgstr "Ðажмите Ñюда чтобы выбрать Ñценарий." msgid "Scenario" msgstr "Сценарий" msgid "Game Difficulty" msgstr "СложноÑть игры" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет уÑтанавливать Ñтартовый уровень ÑложноÑти игры. Чем выше " "уровень ÑложноÑти, тем Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ количеÑтвом реÑурÑов Ð’Ñ‹ начнёте игру, и тем " "больше реÑурÑов получают Ваши компьютерные противники." msgid "Difficulty Rating" msgstr "Рейтинг" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Рейтинг отражает Ñочетание различных игровых уÑтановок. Он иÑпользуетÑÑ Ð¿Ñ€Ð¸ " "раÑчёте конечного результата доÑтигнутого игроком." msgid "Click to accept these settings and start a new game." msgstr "Подтверждает заданные уÑтановки и начинает новую игру." msgid "Click to return to the main menu." msgstr "Ðажмите Ð´Ð»Ñ Ð²Ð¾Ð·Ð²Ñ€Ð°Ñ‚Ð° в главное меню." msgid "Astrologers proclaim the Month of the %{name}." msgstr "ÐÑтрологи объÑвили МеÑÑц %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "ÐÑтрологи объÑвили Ðеделю %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "ПоÑле обычного роÑта, %{monster} удваивает Ñвою популÑцию!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "ПоÑле обычного роÑта, популÑÑ†Ð¸Ñ %{monster} увеличиваетÑÑ Ð½Ð° %{count} процент!" msgstr[1] "" "ПоÑле обычного роÑта, популÑÑ†Ð¸Ñ %{monster} увеличиваетÑÑ Ð½Ð° %{count} " "процента!" msgstr[2] "" "ПоÑле обычного роÑта, популÑÑ†Ð¸Ñ %{monster} увеличиваетÑÑ Ð½Ð° %{count} " "процентов!" msgid "%{monster} growth +%{count}." msgstr "%{monster}: популÑÑ†Ð¸Ñ ÑƒÐ²ÐµÐ»Ð¸Ñ‡Ð¸Ð²Ð°ÐµÑ‚ÑÑ Ð½Ð° %{count}." msgid " All populations are halved." msgstr " Ð’ÑÑ‘ наÑеление уменьшилоÑÑŒ вдвое." msgid " All dwellings increase population." msgstr " ÐаÑеление вÑех жилищ возроÑло." msgid "New Month!" msgstr "Ðовый меÑÑц!" msgid "New Week!" msgstr "ÐÐ¾Ð²Ð°Ñ Ð½ÐµÐ´ÐµÐ»Ñ!" msgid "Beware!" msgstr "Внимание!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} игрок, у Ð’Ð°Ñ Ð¾ÑталÑÑ Ð¿Ð¾Ñледний день, чтобы захватить город, иначе " "Ð’Ñ‹ будете изгнаны из Ñтих земель." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} игрок, у Ð’Ð°Ñ Ð¾ÑталоÑÑŒ %{day} Ñуток, чтобы захватить город, иначе Ð’Ñ‹ " "будете изгнаны из Ñтих земель." msgid "%{color} player's turn." msgstr "Ход игрока: %{color}" msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} игрок, Ð’Ñ‹ потерÑли поÑледний город. ЕÑли Ð’Ñ‹ не захватите какой-либо " "город за неделю, то потерпите поражение." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} игрок, Ваши герои отвернулиÑÑŒ от ВаÑ, а Ð’Ñ‹ изгонÑетеÑÑŒ из Ñтих " "земель." msgid "Lord Kilburn" msgstr "Лорд Килбурн" msgid "Tsabu" msgstr "ТÑабу" msgid "Sir Galant" msgstr "СÑÑ€ Галант" msgid "Thundax" msgstr "ТандакÑ" msgid "Lord Haart" msgstr "Лорд Хаарт" msgid "Ariel" msgstr "ÐриÑль" msgid "Rebecca" msgstr "Ребекка" msgid "Sandro" msgstr "Сандро" msgid "Crodo" msgstr "Кродо" msgid "Barock" msgstr "Барок" msgid "Antoine" msgstr "Ðнтуан" msgid "Astra" msgstr "ÐÑтра" msgid "Agar" msgstr "Ðгар" msgid "Vatawna" msgstr "Ватавна" msgid "Vesper" msgstr "ВеÑпер" msgid "Ambrose" msgstr "ÐмброÑ" msgid "Troyan" msgstr "ТроÑн" msgid "Jojosh" msgstr "Йойош" msgid "Wrathmont" msgstr "Ратмонт" msgid "Maximus" msgstr "МакÑимуÑ" msgid "Next Hero" msgstr "Следующий герой" msgid "Select the next Hero." msgstr "Выбрать Ñледующего героÑ." msgid "Hero Movement" msgstr "Передвижение героÑ" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "Ðачать движение Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ намеченному пути или повторно поÑетить объект, " "перед которым находитÑÑ Ð³ÐµÑ€Ð¾Ð¹. Ðажмите и удерживайте Ñту кнопку, чтобы " "отменить намеченный путь." msgid "Kingdom Summary" msgstr "Обзор королевÑтва" msgid "View a summary of your Kingdom." msgstr "ОÑмотреть Ваши владениÑ." msgid "Cast an adventure spell." msgstr "ПроизнеÑти заклинание приключениÑ." msgid "End Turn" msgstr "Окончить ход" msgid "End your turn and let the computer take its turn." msgstr "Окончить ход и передать управление Ñледующему игроку." msgid "Adventure Options" msgstr "Игровые дейÑтвиÑ" msgid "Bring up the adventure options menu." msgstr "Открыть окно доÑтупных игровых дейÑтвий." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Открывает меню, где Ð’Ñ‹ можете загрузить, Ñохранить, начать новую игру или " "выйти из нее." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "Открывает окно ÑиÑтемных наÑтроек, позволÑющих наÑтроить игру." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Ðекоторые Ваши герои ещё могут ходить.\n" "Ð’Ñ‹ дейÑтвительно хотите закончить ход?" msgid "Are you sure you want to quit?" msgstr "Ð’Ñ‹ уверены, что хотите выйти?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "Ð’Ñ‹ дейÑтвительно хотите начать Ñначала? (Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð¸Ð³Ñ€Ð° будет потерÑна.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Ð’Ñ‹ хотите перезапиÑать файл игры?" msgid "Game saved successfully." msgstr "Игра уÑпешно Ñохранена." msgid "There was an issue during saving." msgstr "Возникла проблема при Ñохранении." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Ð’Ñ‹ дейÑтвительно хотите загрузить новую игру? (Ð¢ÐµÐºÑƒÑ‰Ð°Ñ Ð¸Ð³Ñ€Ð° будет потерÑна.)" msgid "Try looking on land!!!" msgstr "Попробуйте поиÑкать на земле!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "ПоиÑки великого артефакта будут беÑполезными. ЕÑли даже Ваш герой и найдёт " "его, то у него попроÑту нет меÑта, чтобы его унеÑти. ВеÑÑŒ инвентарь Ð³ÐµÑ€Ð¾Ñ " "занÑÑ‚." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "РаÑкопки артефакта занимают целый день. Попробуйте завтра." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "ПоÑле множеÑтва чаÑов, потраченных на раÑкопки, Ð’Ñ‹ обнаружили %{artifact}." msgid "Congratulations!" msgstr "ПоздравлÑем!" msgid "Nothing here. Where could it be?" msgstr "ЗдеÑÑŒ ничего. Где бы Ñто могло быть?" msgid "Try searching on clear ground." msgstr "Попробуйте копать на нормальной земле." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Мини-карта изученного мира. Ðажатием левой кнопки можно управлÑть проÑмотром." msgid "Month: %{month} Week: %{week}" msgstr "МеÑÑц: %{month} ÐеделÑ: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Ð’Ñ‹ нашли немного\n" "%{resource}." msgid "Status Window" msgstr "Окно ÑтатуÑа" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Это окно Ñообщает информацию о ÑоÑтоÑнии Вашего Ð³ÐµÑ€Ð¾Ñ Ð¸Ð»Ð¸ королевÑтва, а " "также показывает календарь." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Это окно Ñообщает информацию о ÑоÑтоÑнии Вашего Ð³ÐµÑ€Ð¾Ñ Ð¸Ð»Ð¸ королевÑтва, а " "также показывает календарь. Ðажмите левую кнопку мыши, чтобы проÑмотреть вÑÑŽ " "доÑтупную информацию." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет Вам задать цвет игрока и его Ñтартовую позицию. Каждому " "цвету ÑоответÑтвует Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ð°Ñ ÑÑ‚Ð°Ñ€Ñ‚Ð¾Ð²Ð°Ñ Ð¿Ð¾Ð·Ð¸Ñ†Ð¸Ñ. Ðекоторые цвета жёÑтко " "закреплены либо за компьютерными, либо за живыми игроками." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет Вам задавать клаÑÑ Ð¸Ð³Ñ€Ð¾ÐºÐ°. КлаÑÑÑ‹ не вÑегда можно " "изменÑть. Ð’ завиÑимоÑти от ÑÑ†ÐµÐ½Ð°Ñ€Ð¸Ñ Ð¸Ð³Ñ€Ð¾Ðº может получать дополнительные " "города и/или героев, направленноÑть которых изначально не Ñовпадает Ñ " "направленноÑтью игрока." msgid "Handicap" msgstr "Фора" msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Эта Ð¾Ð¿Ñ†Ð¸Ñ Ð¿Ð¾Ð·Ð²Ð¾Ð»Ñет любому игроку-человеку дать фору другим игрокам. ЕÑли " "игрок даёт другим фору, он начинает игру Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ количеÑтвом реÑурÑов и " "каждый ход получает на 15 или 30% меньше реÑурÑов, в завиÑимоÑти от его форы." msgid "%{color} player" msgstr "%{color} игрок" msgid "No Handicap" msgstr "Ðет форы" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Ðикаких оÑобых ограничений на начальные реÑурÑÑ‹ и их поÑтупление за ход." msgid "Mild Handicap" msgstr "ÐœÐ°Ð»Ð°Ñ Ñ„Ð¾Ñ€Ð°" msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Игроки Ñ Ð¼Ð°Ð»Ð¾Ð¹ форой начинают игру Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ количеÑтвом реÑурÑов и каждый " "ход получают на 15% меньше реÑурÑов." msgid "Severe Handicap" msgstr "Ð¡ÐµÑ€ÑŒÑ‘Ð·Ð½Ð°Ñ Ñ„Ð¾Ñ€Ð°" msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Игроки Ñ Ñерьёзной форой начинают игру Ñ Ð¼ÐµÐ½ÑŒÑˆÐ¸Ð¼ количеÑтвом реÑурÑов и " "каждый ход получают на 30% меньше реÑурÑов." msgid "" "Default\n" "value" msgstr "" "Значение\n" "по умол-\n" "чанию" msgid "Set %{skill} Skill" msgstr "%{skill}: введите уровень" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "%{skill}: ввеÑти базовое значение. Правый клик - ÑброÑить." msgid "View %{skill} Info" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ навыке %{skill}" msgid "" "Default\n" "skill" msgstr "" "Ðавык\n" "по\n" "умол-\n" "чанию" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "ПРОБЕЛ" msgid "Keyboard|ABC" msgstr "ÐБВ" msgid "The entered value is invalid." msgstr "Введено некорректное значение." msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" "Введённое значение находитÑÑ Ð·Ð° пределами допуÑтимого диапазона.\n" "Оно должно быть не менее %{minValue} и не более %{maxValue}." msgid "Kingdom Income" msgstr "Доход королевÑтва" msgid "Kingdom Income per day." msgstr "Ежедневный доход королевÑтва." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Чем больше количеÑтво маÑков, которыми вы владеете, тем дальше будут " "передвигатьÑÑ Ð’Ð°ÑˆÐ¸ корабли по морю." msgid "English" msgstr "ÐнглийÑкий" msgid "French" msgstr "ФранцузÑкий" msgid "Polish" msgstr "ПольÑкий" msgid "German" msgstr "Ðемецкий" msgid "Russian" msgstr "РуÑÑкий" msgid "Italian" msgstr "ИтальÑнÑкий" msgid "Czech" msgstr "ЧешÑкий" msgid "Norwegian" msgstr "ÐорвежÑкий" msgid "Belarusian" msgstr "БелоруÑÑкий" msgid "Bulgarian" msgstr "БолгарÑкий" msgid "Ukrainian" msgstr "УкраинÑкий" msgid "Romanian" msgstr "РумынÑкий" msgid "Spanish" msgstr "ИÑпанÑкий" msgid "Swedish" msgstr "ШведÑкий" msgid "Portuguese" msgstr "ПортугальÑкий" msgid "Turkish" msgstr "Турецкий" msgid "Dutch" msgstr "ГолландÑкий" msgid "Hungarian" msgstr "ВенгерÑкий" msgid "Danish" msgstr "ДатÑкий" msgid "Slovak" msgstr "Словацкий" msgid "Vietnamese" msgstr "ВьетнамÑкий" msgid "Slow" msgstr "МедленнаÑ" msgid "Fast" msgstr "БыÑтраÑ" msgid "Very Fast" msgstr "Очень быÑтраÑ" msgid "Evil" msgstr "Злой" msgid "Good" msgstr "Добрый" msgid ", FPS: " msgstr ", FPS: " msgid "shipAndGraveyard|%{object} robber" msgstr "%{object}: штраф за разграбление" msgid "pyramid|%{object} raided" msgstr "%{object}: штраф за раÑхищение" msgid "Ector" msgstr "Эктор" msgid "Gwenneth" msgstr "Гвинет" msgid "Sir Gallant" msgstr "СÑÑ€ Галант" msgid "Tyro" msgstr "Тиро" msgid "Dimitry" msgstr "Димитрий" msgid "Ruby" msgstr "Руби" msgid "Crag Hack" msgstr "КрÑг Ð¥Ñк" msgid "Fineous" msgstr "ФинеуÑ" msgid "Jezebel" msgstr "ИзабÑль" msgid "Atlas" msgstr "ÐтлаÑ" msgid "Ergon" msgstr "Эргон" msgid "Jaclyn" msgstr "Жаклин" msgid "Gem" msgstr "ДжÑм" msgid "Natasha" msgstr "Ðаташа" msgid "Carlawn" msgstr "Карлан" msgid "Luna" msgstr "Луна" msgid "Arie" msgstr "Эйри" msgid "Barok" msgstr "Барок" msgid "Kastore" msgstr "КаÑтор" msgid "Falagar" msgstr "Фалагар" msgid "Dawn" msgstr "Дан" msgid "Flint" msgstr "Флинт" msgid "Halon" msgstr "Хейлон" msgid "Myra" msgstr "Мира" msgid "Myrini" msgstr "Мирини" msgid "Wilfrey" msgstr "Уилфри" msgid "Mandigal" msgstr "Мандигал" msgid "Sarakin" msgstr "Саракин" msgid "Charity" msgstr "ЧÑрити" msgid "Darlana" msgstr "Дарлана" msgid "Ranloo" msgstr "РÑнлу" msgid "Rialdo" msgstr "Риальдо" msgid "Zam" msgstr "Зам" msgid "Zom" msgstr "Зом" msgid "Celia" msgstr "ЦелиÑ" msgid "Roxana" msgstr "РокÑана" msgid "Lord Corlagon" msgstr "Лорд Корлагон" msgid "Lord Halton" msgstr "Лорд Халтон" msgid "Sister Eliza" msgstr "СеÑтра Элиза" msgid "Brother Brax" msgstr "Брат БракÑ" msgid "Dainwin" msgstr "Дейнвин" msgid "Joseph" msgstr "Джозеф" msgid "Mog" msgstr "Моуг" msgid "Solmyr" msgstr "Сольмир" msgid "Ceallach" msgstr "Каллах" msgid "Drakonia" msgstr "ДракониÑ" msgid "Elderian" msgstr "Элдериан" msgid "Gallavant" msgstr "Галавант" msgid "Jarkonas" msgstr "ДжарконаÑ" msgid "Martine" msgstr "Мартина" msgid " gives you maximum morale" msgstr " повышает Вашу мораль до макÑимума" msgid " gives you maximum luck" msgstr " повышает Вашу удачу до макÑимума" msgid "You cannot have multiple spell books." msgstr "У Ð’Ð°Ñ Ð½Ðµ может быть неÑколько волшебных книг." msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Ð’Ñ‹ не можете забрать Ñтот артефакт, у Ð’Ð°Ñ Ð½ÐµÑ‚ Ñвободного меÑта!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Чтобы Ð’Ð°Ñ Ð¿Ñ€Ð¾Ð¿ÑƒÑтили в гильдию магов, Ð’Ñ‹ должны купить книгу заклинаний за " "%{gold} золотых." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "К Ñожалению, у Ð’Ð°Ñ Ð½Ðµ хватает денег." msgid "Do you wish to buy one?" msgstr "Желаете купить?" msgid "%{count} / day" msgstr "%{count} / день" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "Ваш корабль заÑоÑало в водоворот. ЧаÑть Вашей армии Ñмыло за борт." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "ОÑкорблённые Вашим отказом, они напали на ВаÑ!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "%{monster}, ÑтрашаÑÑŒ мощи Вашего воинÑтва, броÑилиÑÑŒ враÑÑыпную.\n" "Изволите преÑледовать их и заÑтавить дратьÑÑ?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "ОбыÑкав вражеÑкий лагерь, Ð’Ñ‹ находите ÑпрÑтанный клад." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Мельник обращаетÑÑ Ðº Вам Ñо Ñловами:\n" "\"Милорд, Ñ Ñ‚Ñ€ÑƒÐ´Ð¸Ð»ÑÑ Ð² поте лица и прошу Ð’Ð°Ñ Ð¿Ñ€Ð¸Ð½Ñть Ñти реÑурÑÑ‹. Приходите " "на Ñледующей неделе и получите ещё.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Мельник обращаетÑÑ Ðº Вам Ñо Ñловами:\n" "\"Сожалею, милорд, но ÑÐµÐ³Ð¾Ð´Ð½Ñ Ñƒ Ð¼ÐµÐ½Ñ Ð½ÐµÑ‚ реÑурÑов. Приходите на Ñледующей " "неделе.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Мельник обращаетÑÑ Ðº Вам Ñо Ñловами:\n" "\"Милорд, Ñ Ñ‚Ñ€ÑƒÐ´Ð¸Ð»ÑÑ Ð² поте лица и прошу Ð’Ð°Ñ Ð¿Ñ€Ð¸Ð½Ñть Ñто золото. Приходите " "на Ñледующей неделе и получите ещё.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Мельник обращаетÑÑ Ðº Вам Ñо Ñловами:\n" "\"Сожалею, милорд, но ÑÐµÐ³Ð¾Ð´Ð½Ñ Ð·Ð¾Ð»Ð¾Ñ‚Ð° у Ð¼ÐµÐ½Ñ Ð½ÐµÑ‚. Приходите на Ñледующей " "неделе.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Ð’Ñ‹ нашли заброшенный навеÑ.\n" "Ðемного поиÑкав, Ð’Ñ‹ обнаружили припрÑтанные Ñ€Ñдом реÑурÑÑ‹." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "ÐÐ°Ð²ÐµÑ Ð´Ð°Ð²Ð½Ð¾ заброшен. ЗдеÑÑŒ нет ничего ценного." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Ð’Ñ‹ поймали лепрекона, так беÑпечно заÑнувшего под шлÑпкой волшебного гриба.\n" "Ð’ обмен на Ñвою Ñвободу он раÑÑказал Вам, где лежит горшочек Ñ " "драгоценноÑÑ‚Ñми." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Ð’Ñ‹ забрели в волшебный Ñад. ЗдеÑÑŒ, обычно, так обожают резвитьÑÑ Ð»ÐµÐ¿Ñ€ÐµÐºÐ¾Ð½Ñ‹ Ñ " "феÑми. Ðо ÑÐµÐ³Ð¾Ð´Ð½Ñ Ð·Ð´ÐµÑÑŒ никого." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Ð’Ñ‹ обнаружили оÑтанки какого-то неÑчаÑтного путника." msgid "Treasure" msgstr "Сокровище" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "ПокопавшиÑÑŒ Ñреди лохмотьев, Ð’Ñ‹ нашли %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "ПокопавшиÑÑŒ Ñреди лохмотьев, Ð’Ñ‹ ничего не нашли." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Ð’Ñ‹ наткнулиÑÑŒ на брошенную торговую повозку, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ добралаÑÑŒ до " "безопаÑной меÑтноÑти." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "К неÑчаÑтью, кто-то здеÑÑŒ уже побывал, и в повозке ничего нет." msgid "Searching inside, you find the %{artifact}." msgstr "ПокопавшиÑÑŒ внутри, Ð’Ñ‹ нашли %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Внутри чаÑть груза оказалаÑÑŒ нетронутой." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Ð’Ñ‹ иÑÑледовали плавающие обломки и нашли немного древеÑины и золота." msgid "You search through the flotsam, and find some wood." msgstr "Ð’Ñ‹ иÑÑледовали плавающие обломки и нашли немного древеÑины." msgid "You search through the flotsam, but find nothing." msgstr "Ð’Ñ‹ иÑÑледовали плавающие обломки и ничего не нашли." msgid "Shrine of the 1st Circle" msgstr "СвÑтилище 1-го круга" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Ð’Ñ‹ набрели на маленькое ÑвÑтилище, где Ñлужат молодые Ð±Ñ€Ð°Ñ‚ÑŒÑ Ð²ÐµÑ€Ñ‹.\n" "Ð’ обмен на защиту они ÑоглаÑилиÑÑŒ научить Ð’Ð°Ñ Ð¿Ñ€Ð¾Ñтому заклинанию - " "'%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "СвÑтилище 2-го круга" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Ð’Ñ‹ набрели на богато раÑпиÑанное ÑвÑтилище, где Ñлужат доÑтойные Ð±Ñ€Ð°Ñ‚ÑŒÑ " "веры.\n" "Ð’ обмен на защиту они ÑоглаÑилиÑÑŒ научить Ð’Ð°Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸ÑŽ - '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "СвÑтилище 3-го круга" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Ð’Ñ‹ набрели на роÑкошное ÑвÑтилище, где Ñлужат верховные жрецы.\n" "Ð’ обмен на защиту они ÑоглаÑилиÑÑŒ научить Ð’Ð°Ñ Ð¿Ñ€ÐµÐ¼ÑƒÐ´Ñ€Ð¾Ð¼Ñƒ заклинанию - " "'%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "К Ñожалению, у Ð’Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно мудроÑти, чтобы понÑть заклинание, и Ð’Ñ‹ не в " "ÑоÑтоÑнии его изучить." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "К Ñожалению, Вам уже знакомо данное заклинание, так что им больше нечему Ð’Ð°Ñ " "учить." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "К Ñожалению, у Ð’Ð°Ñ Ð½ÐµÑ‚ Волшебной Книги, чтобы запиÑать заклинание в неё." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "ÐŸÐ¾Ð´Ð¾Ð¹Ð´Ñ Ðº хижине и заглÑнув в окно, Ð’Ñ‹ увидели ведьму, ÑклонившуюÑÑ Ð½Ð°Ð´ " "древней книгой под названием %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Когда Ð’Ñ‹ подходите, ведьма поворачиваетÑÑ Ð¸ Ñмотрит на Ð’Ð°Ñ Ñвоим ÑтеклÑнным " "глазом.\n" "\"Ты уже знаешь вÑÑ‘, что тебе положено знать!\" говорит она. \"РТЕПЕРЬ ВОР" "ИЗ МОЕГО ДОМÐ!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Когда Ð’Ñ‹ подходите к хижине, ведьма поворачиваетÑÑ Ð¸ говорит.\n" "\"Ты уже знаешь то, что знаю Ñ. Больше ничем помочь не могу.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "ДрÑхлаÑ, но беÑÑÐ¼ÐµÑ€Ñ‚Ð½Ð°Ñ Ð²ÐµÐ´ÑŒÐ¼Ð°, Ð¶Ð¸Ð²ÑƒÑ‰Ð°Ñ Ð² Ñтой избушке на курьих ножках, по " "каким-то непонÑтным ÑоображениÑм решила, что %{skill} Вам пригодитÑÑ." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "Выпив Ñвежей воды, Ð’Ñ‹ получаете Ð±Ð¾Ð½ÑƒÑ ÑƒÐ´Ð°Ñ‡Ð¸ в Ñледующем бою." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Ð’Ñ‹ пьёте из фонтана, но ничего не проиÑходит." msgid "You enter the faerie ring, but nothing happens." msgstr "Ð’Ñ‹ поÑетили кольцо фей, но ничего не произошло." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Ваше войÑко вÑтупает в кольцо фей, чары которого принеÑут Вам удачу в " "грÑдущем Ñражении." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Ð’Ñ‹ нашли древнего идола. ГоворÑÑ‚, он приноÑит удачу тем, кто его навещает, " "но поÑкольку звёзды и так покровительÑтвуют Вам, идол ничего нового Вам не " "дал." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Ð’Ñ‹ нашли древнего идола.\n" "ГоворÑÑ‚, еÑли его поцеловать, то Ñто принеÑёт удачу - Ð’Ñ‹ так и поÑтупили. " "Камень оказалÑÑ Ð¾Ñ‡ÐµÐ½ÑŒ холоден Ð´Ð»Ñ Ð³ÑƒÐ±." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "РуÑалки молчаливо дали Вам понÑть, чтобы Ð’Ñ‹ приходили в другой раз, тогда " "они благоÑловÑÑ‚ ВаÑ." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "ÐÐµÐ·ÐµÐ¼Ð½Ð°Ñ ÐºÑ€Ð°Ñота руÑалок очаровала Ð’Ð°Ñ Ð¸ Вашу команду.\n" "Ðа какой-то миг Ð’Ñ‹ позабыли о Ваших проблемах и наÑладилиÑÑŒ Ñтим мгновением " "краÑоты.\n" "Чары руÑалок благоÑловили Ð’Ð°Ñ Ð½Ð° удачу в Ñледующем бою." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Ð’Ñ‹ нашли пирамиду древнего великого царÑ.\n" "ИÑкушение поиÑкать в ней Ñокровища велико, но Ð’Ñ‹ Ñлышали вÑе Ñти Ñказки об " "ужаÑных проклÑтиÑÑ… и неупокоенных Ñтражах.\n" "Хотите обыÑкать пирамиду?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Одолев чудовищ, Ð’Ñ‹ раÑшифровали иероглифы на Ñтене, Ñодержащие Ñекрет " "Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "К Ñожалению Ð’Ñ‹ не имеете Волшебной Книги чтобы запиÑать заклинание." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "К Ñожалению, Вам не хватает мудроÑти чтобы понÑть и выучить заклинание." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Изучив внутренние Ð¿Ð¾Ð¼ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¿Ð¸Ñ€Ð°Ð¼Ð¸Ð´Ñ‹, Ð’Ñ‹ понимаете, что здеÑÑŒ ничего нет." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Глоток из колодца обычно воÑÑтанавливает магичеÑкую Ñнергию, но ÑÐµÐ¹Ñ‡Ð°Ñ Ð¾Ð½Ð° у " "Ð’Ð°Ñ Ð¸ так на пределе." msgid "A second drink at the well in one day will not help you." msgstr "Второй глоток за день Вам не поможет." msgid "A drink from the well has restored your spell points to maximum." msgstr "Глоток из колодца полноÑтью воÑÑтановил Вашу магичеÑкую Ñнергию." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"ПроÑтите, милорд\" - Ñказал предводитель воинов, - \"но Ð’Ñ‹ уже знаете вÑÑ‘, " "чему мы ÑпоÑобны научить.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "Воины, живущие в Ñтом форте, научили Ð’Ð°Ñ Ð¿Ð°Ñ€Ðµ новых защитных приёмов." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Ð’Ñ‹ пришли в лагерь наёмников, где воины оттачивают тактику. \"Ð”Ð»Ñ Ð½Ð°Ñ Ð’Ñ‹ " "Ñлишком умелый боец,\" - Ñказал капитан наёмников. - \"Больше мы ничему " "научить Ð’Ð°Ñ Ð½Ðµ можем.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Ð’Ñ‹ пришли в лагерь наёмников, отрабатывающих Ñвою тактику. Ðаёмники " "поприветÑтвовали Ð’Ð°Ñ Ð¸ приглаÑили позаниматьÑÑ Ð²Ð¼ÐµÑте Ñ Ð½Ð¸Ð¼Ð¸." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"УбирайÑÑ!\" - Ñ€Ñвкнул колдун, \"ты и так знаешь вÑÑ‘, что знаю Ñ.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Орочий колдун, живущий в Ñтой хижине, углубил Ваши Ð¿Ð¾Ð·Ð½Ð°Ð½Ð¸Ñ Ð² магии, " "показав, как гадать на камнÑÑ…, читать Ð·Ð½Ð°Ð¼ÐµÐ½Ð¸Ñ Ð¸ извлекать ÑущноÑть Ð±Ñ‹Ñ‚Ð¸Ñ Ð¸Ð· " "хитроÑÐ¿Ð»ÐµÑ‚ÐµÐ½Ð¸Ñ Ñ†Ñ‹Ð¿Ð»Ñчьих потрохов." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Ð’Ñ‹ заÑтали группу друидов за обрÑдом в одном из их диковинных каменных " "Ñооружений. Друиды, не Ð½Ð°Ñ€ÑƒÑˆÐ°Ñ Ð±ÐµÐ·Ð¼Ð¾Ð»Ð²Ð¸Ñ, показали жеÑтами, что им больше " "нечему Ð’Ð°Ñ ÑƒÑ‡Ð¸Ñ‚ÑŒ." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Ð’Ñ‹ заÑтали группу друидов за обрÑдом в одном из их диковинных каменных " "Ñооружений. Ðе Ð½Ð°Ñ€ÑƒÑˆÐ°Ñ Ð±ÐµÐ·Ð¼Ð¾Ð»Ð²Ð¸Ñ, они научили Ð’Ð°Ñ Ð½Ð¾Ð²Ñ‹Ð¼ ÑпоÑобам колдовÑтва." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Ð’Ñ‹ оÑторожно приближаетеÑÑŒ к захоронению древних воинов. Хотите обыÑкать их " "могилы?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Ð’Ñ‹ тратите неÑколько чаÑов, обыÑÐºÐ¸Ð²Ð°Ñ Ð¼Ð¾Ð³Ð¸Ð»Ñ‹, но ничего не находите. Сей " "презренный акт Ñнижает мораль Вашей армии." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "ПоÑле победы над зомби, Ð’Ñ‹ обыÑкиваете могилы и удалÑетеÑÑŒ Ñ Ð½Ð°Ñ…Ð¾Ð´ÐºÐ¾Ð¹!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Гниющий оÑтов огромного пиратÑкого ÐºÐ¾Ñ€Ð°Ð±Ð»Ñ Ð·Ð»Ð¾Ð²ÐµÑ‰Ðµ поÑкрипывает, " "покачиваемый прибоем на Ñкалах. Желаете обыÑкать обломки?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Ð’Ñ‹ тратите неÑколько чаÑов, обыÑÐºÐ¸Ð²Ð°Ñ Ð¾Ñтанки, но ничего не находите. Сей " "презренный акт Ñнижает мораль Вашей армии." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "Одолев призраков, Ð’Ñ‹ обыÑкали оÑтанки ÐºÐ¾Ñ€Ð°Ð±Ð»ÐµÐºÑ€ÑƒÑˆÐµÐ½Ð¸Ñ Ð¸ кое-что нашли!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Гниющий оÑтов огромного пиратÑкого ÐºÐ¾Ñ€Ð°Ð±Ð»Ñ Ð·Ð»Ð¾Ð²ÐµÑ‰Ðµ поÑкрипывает, " "покачиваемый прибоем на Ñкалах. Желаете обыÑкать корабль?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "Совладав Ñо Ñкелетами, Ð’Ñ‹ обыÑкали оÑтанки ÐºÐ¾Ñ€Ð°Ð±Ð»Ñ Ð¸ кое-что нашли!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "Ваши Ñпутники замечают морÑкой буй. Он указывает верный курÑ." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Ваши Ñпутники замечают морÑкой буй. Он указывает верный курÑ, и Ñто повышает " "их боевой дух." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Глоток воды в оазиÑе оÑвежает, но иной пользы не приноÑит. Этот оазиÑ, " "возможно, Ñнова поможет Вам поÑле Ñледующей битвы." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Глоток воды из оазиÑа наполнÑет Ваших воинов Ñилой и поднимает дух. Ð¡ÐµÐ³Ð¾Ð´Ð½Ñ " "Ð’Ñ‹ Ñможете пройти чуть больше." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "ОÑтановка на водопое оÑвежает, но иных благ не приноÑит. Водопой Ñнова " "поможет Вам поÑле Ñледующей битвы." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Добрый глоток иÑполнил Ваши войÑка Ñилы и поднÑл дух. Ð¡ÐµÐ³Ð¾Ð´Ð½Ñ Ð’Ñ‹ Ñможете " "пройти чуть дальше." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "Ð”Ð²Ð¾Ð¹Ð½Ð°Ñ Ð¼Ð¾Ð»Ð¸Ñ‚Ð²Ð° войне не подÑпорье. Заходите поÑле битвы." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "ПоÑещение храма и молитва поднÑли мораль Ваших войÑк." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Ðа ÑтупенÑÑ… беÑедки поÑвлÑетÑÑ Ñтарый рыцарь. \"Мне жаль храбрый воин, но Ñ " "уже научил Ñ‚ÐµÐ±Ñ Ð²Ñему, что знаю Ñам.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Ðа ÑтупенÑÑ… беÑедки поÑвлÑетÑÑ Ñтарый рыцарь. \"О храбрый воин, Ñ Ð½Ð°ÑƒÑ‡Ñƒ Ñ‚ÐµÐ±Ñ " "вÑему, что знаю Ñам: пуÑть мой опыт поможет тебе в твоих ÑтранÑтвиÑÑ….\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Ð’Ñ‹ ÑпаÑли выжившего поÑле ÐºÐ¾Ñ€Ð°Ð±Ð»ÐµÐºÑ€ÑƒÑˆÐµÐ½Ð¸Ñ Ð¾Ñ‚ неминуемой гибели в " "безжалоÑтном океане. ÐœÐ°Ñ‚Ñ€Ð¾Ñ Ñказал, \"За Ñвоё ÑпаÑение Ñ Ñ…Ð¾Ñ‚ÐµÐ» отблагодарить " "Ð’Ð°Ñ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚Ð¾Ð¼, но Ñ Ð²Ð¸Ð¶Ñƒ, что Ваша Ñумка и так переполнена.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Ð’Ñ‹ ÑпаÑли выжившего поÑле ÐºÐ¾Ñ€Ð°Ð±Ð»ÐµÐºÑ€ÑƒÑˆÐµÐ½Ð¸Ñ Ð¾Ñ‚ неминуемой гибели в " "безжалоÑтном океане. Ðаграда за вашу доброту - %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "Лепрекон предлагает Вам артефакт \"%{art}\" за Ñкромную цену в %{gold} " "золотых." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Лепрекон предлагает Вам артефакт \"%{art}\" за Ñкромную цену в %{gold} " "золотых и %{count} %{res}." msgid "Do you wish to buy this artifact?" msgstr "Ð’Ñ‹ хотите приобреÑти Ñтот артефакт?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Ð’Ñ‹ хотите заплатить лепрекону, но у Ð’Ð°Ñ Ð½Ðµ хватает ÑредÑтв. Лепрекон топает " "ножкой и демонÑтративно отворачиваетÑÑ Ð¾Ñ‚ ВаÑ." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "ОÑкорблённый Вашим отказом на его щедрое предложение, лепрекон топает ножкой " "и демонÑтративно отворачиваетÑÑ Ð¾Ñ‚ ВаÑ." msgid "You've found the artifact: " msgstr "Ð’Ñ‹ нашли артефакт: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Ð’Ñ‹ нашли Ñкромное жилище отшельника. Отшельник говорит Вам, что он готов " "отдать %{art} первому Мудрецу, которого вÑтретит." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Ð’Ñ‹ поÑетили ÑпартанÑкое жилище отÑтавного ветерана. Солдат говорит Вам, что " "он готов отдать %{art} первому Лидеру, которого он вÑтретит." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Ð’Ñ‹ ÑтолкнулиÑÑŒ Ñо Ñтранным человеком в шлÑпе, на которой Ñидит Ñова. Он " "говорит Вам, что готов отдать %{art}, еÑли у Ð’Ð°Ñ ÐµÑть %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Ð’Ñ‹ нашли древний артефакт. Как только Ð’Ñ‹ наклонилиÑÑŒ его подобрать, " "воÑпользовавшиÑÑŒ моментом, из заÑады выпрыгнула шайка разбойников..." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Ð’Ñ‹ заметили древний артефакт. К Ñожалению, Ñ€Ñдом притаилÑÑ %{monster}. " "Хотите ÑразитьÑÑ?" msgid "Victorious, you take your prize, the %{art}." msgstr "Победив в бою, Ð’Ñ‹ забираете награду - %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "ОÑмотрительноÑть - Ñто Ð»ÑƒÑ‡ÑˆÐ°Ñ Ñ‡ÐµÑ€Ñ‚Ð° доблеÑти, поÑему Ð’Ñ‹ решили избежать " "ÑÑ€Ð°Ð¶ÐµÐ½Ð¸Ñ ÑегоднÑ." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Потратив неÑколько чаÑов на попытки выловить Ñундук из воды, Ð’Ñ‹ наконец " "открыли его и нашли внутри %{gold} золотых." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Потратив неÑколько чаÑов на попытки выловить Ñундук из воды, Ð’Ñ‹ наконец " "открыли его и нашли внутри %{gold} золотых и %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Потратив неÑколько чаÑов на попытки выловить Ñундук из воды, Ð’Ñ‹ наконец " "открыли его, но он оказалÑÑ Ð¿ÑƒÑÑ‚." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "ИÑÑÐ»ÐµÐ´ÑƒÑ Ð¾ÐºÑ€ÐµÑтноÑти, Ð’Ñ‹ наткнулиÑÑŒ на древний ларец. Золото можно оÑтавить " "Ñебе или раздать креÑтьÑнам в обмен на опыт. ОÑтавите золото Ñебе?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "ИÑÑÐ»ÐµÐ´ÑƒÑ Ð¾ÐºÑ€ÐµÑтноÑти, Ð’Ñ‹ наткнулиÑÑŒ на древний ларец в котором лежит %{gold} " "золотых." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "ИÑÑÐ»ÐµÐ´ÑƒÑ Ð¾ÐºÑ€ÐµÑтноÑти, Ð’Ñ‹ наткнулиÑÑŒ на древний ларец в котором лежит древний " "артефакт - %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Ð’Ñ‹ находите заÑыпанную землёй помÑтую и закопчённую лампу. Хотите её " "потереть?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином лаборатории меÑтного алхимика. Она будет приноÑить Вам по " "%{count} мере ртути в день." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином леÑопилки. Она будет приноÑить Вам по %{count} меры " "древеÑины в день." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином рудной шахты. Она будет приноÑить Вам по %{count} меры " "руды в день." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином Ñерной шахты. Она будет приноÑить Вам по %{count} мере " "Ñеры в день." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином криÑтальной шахты. Она будет приноÑить Вам по %{count} " "мере криÑталлов в день." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином Ñамоцветной шахты. Она будет приноÑить Вам по %{count} " "мере Ñамоцветов в день." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином золотой шахты. Она будет приноÑить Вам по %{count} золотых " "в день." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Ð’Ñ‹ Ñтали хозÑином маÑка, теперь вÑе Ваши корабли будут передвигатьÑÑ Ð¿Ð¾ морю " "гораздо дальше." msgid "You gain control of a %{name}." msgstr "%{name} переходит под Ваш контроль." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Ð’Ñ‹ подошли к заброшенной шахте. Возможно в ней живут ПривидениÑ. Хотите " "войти и проверить Ñто?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Ð’Ñ‹ выгнали призраков из шахты и воÑÑтановили её работу." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "%{monster} в погоне за Ñлавой желают к Вам приÑоединитьÑÑ.\n" "Ð’Ñ‹ ÑоглаÑны?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "ПриближаÑÑÑŒ к жилищу, Ð’Ñ‹ замечаете что здеÑÑŒ никого нет." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Ð’Ñ‹ обыÑкали руины, но убедилиÑÑŒ, что жившие тут Медузы ушли. Может быть Вам " "повезет больше на Ñледующей неделе." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Ð’Ñ‹ обыÑкали руины и нашли неÑкольких Медуз, обитающих тут. Они ÑоглаÑны " "вÑтупить в Вашу армию за вознаграждение. Желаете нанÑть Медуз?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Ð’Ñ‹ нашли древеÑный город Фей. К Ñожалению, ни одна Ð¤ÐµÑ Ð½Ðµ захотела " "приÑоединитьÑÑ Ðº Вашей армии. Может быть на Ñледующей неделе они передумают." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "ÐеÑколько Фей, из города на деревьÑÑ…, желают вÑтупить в Вашу армию, за " "некоторое вознаграждение. Желаете нанÑть Фей?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Ð Ð°Ð·Ð½Ð¾Ñ†Ð²ÐµÑ‚Ð½Ð°Ñ Ð¿Ð¾Ð²Ð¾Ð·ÐºÐ° разбойников пуÑта. Пройдет времÑ, и, быть может, здеÑÑŒ " "обоÑнуетÑÑ Ð½Ð¾Ð²Ð°Ñ ÑˆÐ°Ð¹ÐºÐ°." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Вдалеке ÑлышитÑÑ Ð¼ÑƒÐ·Ñ‹ÐºÐ° и Ñмех. Ð’Ñ‹ идете на звуки и видите разноцветную " "повозку, в которой живут Разбойники. Ð’Ñ‹ хотите принÑть в Ваше войÑко " "Разбойников?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Ваше внимание привлек шатер, пологи которого трепещут на жарком ветру " "пуÑтыни. ЗдеÑÑŒ никого нет. Пройдет времÑ, и, быть может, Ñюда придет новый " "отрÑд Кочевников." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Ваше внимание привлек шатер, пологи которого трепещут на жарком ветру " "пуÑтыни. Ð’Ñ‹ хотите принÑть в Ваше войÑко Кочевников?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Яма клокочущей грÑзи вÑколыхнулаÑÑŒ и уÑпокоилаÑÑŒ." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Как только Ð’Ñ‹ подошли к Ñме клокочущей грÑзи из неё начали выползать " "ÑущеÑтва. Ð’Ñтав вокруг Ñмы, они в униÑон обратилиÑÑŒ к Вам: \"Мать Ð·ÐµÐ¼Ð»Ñ " "желает предложить Вам неÑкольких Ñвоих воинов. Желаете нанÑть Земных " "Ñлементалей?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" "Ð’Ñ‹ входите в Ñооружение из белых каменных Ñтолбов, и ничего не находите." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Белокаменные колонны подпирают крышу, уходÑщую в небеÑа. Едва Ð’Ñ‹ вошли " "внутрь, как Ñпокойный воздух превратилÑÑ Ð² мощный поток ветра, едва не " "вытолкнувший Ð’Ð°Ñ Ð½Ð°Ñ€ÑƒÐ¶Ñƒ. Воздух ÑгуÑтилÑÑ Ð² едва различимые формы. СущеÑтво " "обратилоÑÑŒ к Вам едва Ñлышным шёпотом: \"Зачем ты ÑвилÑÑ? Ты пришёл Ñюда " "иÑкать помощи Ñил воздуха?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "" "Ðи один из Огненных Ñлементалей не вышел Вам навÑтречу из огненного баÑÑейна." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Ð’ поÑтройке, удерживающей подземный жар, Ð’Ñ‹ видите Огненных Ñлементалей, " "движущихÑÑ Ð² потоках раÑкалённой лавы. ÐеÑколько из них приблизилиÑÑŒ к Вам и " "предложили Вам Ñвою Ñлужбу. Желаете нанÑть Огненных Ñлементалей?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Ðа мгновение в воде мелькнули черты чьих-то лиц, и иÑчезли." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "ХруÑтальные поÑтройки отбраÑывают зыбкие тени на небольшой Ñверкающий " "баÑÑейн. Ð’ воде поÑвилоÑÑŒ лицо, не Ваше отражение, которое обратилоÑÑŒ к Вам " "Ñо Ñловами: \"Желаешь обратитьÑÑ Ð·Ð° помощью к Ñилам воды?\"" msgid "This burial site is deathly still." msgstr "Это захоронение таит Ñмертельную тишину." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Ðеупокоенные духи давно погибших воинов ищут ÑƒÐ¿Ð¾ÐºÐ¾ÐµÐ½Ð¸Ñ Ð¸ ÑоглашаютÑÑ " "вÑтупить в армию Вашего Ð³ÐµÑ€Ð¾Ñ Ð² надежде найти упокоение. Желаете нанÑть " "Призраков?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "Ð’ Ñтом городе мертвецов жизни не наблюдаетÑÑ, нежити тоже. Быть может на " "Ñледующей неделе кто-то из нежити забредет Ñюда." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Кое-кто из Личей, обитающих здеÑÑŒ, желает вÑтупить в армию Вашего Ð³ÐµÑ€Ð¾Ñ Ð·Ð° " "плату. Желаете нанÑть Личей?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Ð’Ñ‹ нашли руины древнего города, ныне наÑеленного лишь нежитью. Желаете " "обÑледовать город?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Уцелевшие Личи прониклиÑÑŒ Вашей победой над их ÑобратьÑми и предложили Ñвои " "уÑлуги за плату. Желаете нанÑть Личей?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Ð’Ñ‹ нашли один из моÑтов, под которым обычно обитают Тролли, но тут никого " "нет. Возможно на Ñледующей неделе поÑвитÑÑ Ð½ÐµÑколько." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "ÐеÑколько Троллей, живущих под моÑтом, желают вÑтупить в армию Вашего героÑ, " "но не задаром. Ð’Ñ‹ хотите нанÑть Троллей?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "Тролли, живущие под моÑтом, вызывают Ð’Ð°Ñ Ð½Ð° бой. Ð’Ñ‹ ÑхватитеÑÑŒ Ñ Ð½Ð¸Ð¼Ð¸?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "ÐеÑколько Троллей уÑпели укрытьÑÑ Ð¿Ð¾Ð´ моÑтом. Они обратилиÑÑŒ к Вам Ñ " "предложением вÑтупить в армию Вашего героÑ. Ð’Ñ‹ хотите нанÑть Троллей?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "Ðа Ñтой неделе в городе нет Драконов, желающих примкнуть к Вам. Приходите на " "Ñледующей неделе." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Город драконов готов предложить войÑку Вашего Ð³ÐµÑ€Ð¾Ñ Ð”Ñ€Ð°ÐºÐ¾Ð½Ð¾Ð², не беÑплатно. " "Желаете нанÑть Драконов?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Ð’Ñ‹ Ñтоите перед Драконьим городом - меÑтом, запретным Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñтых Ñмертных. " "ОÑмелитеÑÑŒ ли Ð’Ñ‹ нарушить Ñто правило и броÑить вызов Драконам?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "ПоÑле победы над лучшими драконьими воинами отцы города ÑоглаÑилиÑÑŒ за плату " "предоÑтавить войÑку Вашего Ð³ÐµÑ€Ð¾Ñ Ð”Ñ€Ð°ÐºÐ¾Ð½Ð¾Ð². Желаете нанÑть Драконов?" msgid "From the observation tower, you are able to see distant lands." msgstr "С вершины обзорной башни Ð’Ñ‹ разглÑдели дальние земли." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Этот родник воÑполнÑетÑÑ Ñ€Ð°Ð· в неделю, а кто-то уже пил из него на Ñтой " "неделе." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Глоток из родника обычно удваивает магичеÑкую Ñнергию выпившего, однако у " "Ð’Ð°Ñ ÑƒÐ¶Ðµ удвоенный уровень." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Глоток из родника наполнÑет кровь Ð³ÐµÑ€Ð¾Ñ Ð¼Ð°Ð³Ð¸ÐµÐ¹! Теперь магичеÑкой Ñнергии у " "него в запаÑе вдвое больше обычного." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Узнав ВаÑ, лакей отказываетÑÑ Ð²Ð¿ÑƒÑтить в дом. \"Мой хозÑин не будет обучать " "Ð’Ð°Ñ Ð´Ð²Ð°Ð¶Ð´Ñ‹.\" - Ñказал он." msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Лакей приглаÑил Ð’Ð°Ñ Ð²ÑтретитьÑÑ Ñ Ñ…Ð¾Ð·Ñином. Тот обучил Ð’Ð°Ñ Ð²Ñем четырём " "первичным навыкам." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Лакей открыл дверь и оглÑдел Ð’Ð°Ñ Ñ Ð½Ð¾Ð³ до головы. \"Ð’Ñ‹ не так знамениты и не " "такой уж дипломат, чтобы мой хозÑин принÑл ВаÑ,\" - фыркнул он. - " "\"ВозвращайтеÑÑŒ, когда будете доÑтойны.\"" msgid " and " msgstr " и " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Ð’Ñе %{monsters} в армии Ð³ÐµÑ€Ð¾Ñ Ð±Ñ‹Ð»Ð¸ обучены маÑтерами форта. Теперь в армии " "Ð³ÐµÑ€Ð¾Ñ ÐµÑть %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Ðеобычный Ñоюз орков, огров и гномов предлагает герою потренировать " "(улучшить) любые подобные им войÑка. К Ñожалению, в армии Ð³ÐµÑ€Ð¾Ñ Ñ‚Ð°ÐºÐ¸Ñ… " "ÑущеÑтв нет." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Ð’Ñе %{monsters} в армии Ð³ÐµÑ€Ð¾Ñ Ð±Ñ‹Ð»Ð¸ улучшены до %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Кузнец при Ñтой литейной предлагает заменить оружие копейщиков и мечников Ñ " "железного на Ñтальное. Он также Ñказал, что владеет технологией переплавки " "железных големов в Ñтальные. К Ñожалению, никого из них нет в армии героÑ, и " "он не может Вам ничем помочь." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Капитан Ñмотрит на Ð’Ð°Ñ ÑƒÐ´Ð¸Ð²Ð»Ñ‘Ð½Ð½Ð¾ и говорит:\n" "\"У Ñ‚ÐµÐ±Ñ ÑƒÐ¶Ðµ еÑть вÑе карты, о которых Ñ Ð·Ð½Ð°ÑŽ. Дай мне теперь Ñпокойно " "порыбачить\"." msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Бывший капитан, живущий на Ñтом подновленном рыболовном причале, предлагает " "Вам карты, ÑоÑтавленные им в прежние дни, за 1000 золотых. Желаете их купить?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Капитан вздыхает. \"Вам не хватает денег, да? Ð’Ñ‹ же не думаете, что Ñ Ð¾Ñ‚Ð´Ð°Ð¼ " "Ñвои карты задаром?!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Перед Вами обелиÑк, выÑеченный из невиданного камнÑ. Ð’Ñ‹ вглÑдываетеÑÑŒ в его " "гладкую поверхноÑть и вдруг замечаете, что на ней начинают проÑтупать " "таинÑтвенные знаки. Знаки ÑкладываютÑÑ Ð²Ð¾ фрагмент древней карты. Ð’Ñ‹ " "торопливо ÑриÑовываете его, и знаки иÑчезают так же внезапно, как и " "поÑвилиÑÑŒ." msgid "You have already been to this obelisk." msgstr "Ð’Ñ‹ уже поÑещали Ñтот обелиÑк." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "При приближении Ð³ÐµÑ€Ð¾Ñ Ð´Ñ€ÐµÐ²ÐµÑные глаза заÑветилиÑÑŒ воÑторгом. \"Рад Ñнова " "Ñ‚ÐµÐ±Ñ Ð²Ð¸Ð´ÐµÑ‚ÑŒ, мой ученик. Я надеюÑÑŒ мои Ð·Ð½Ð°Ð½Ð¸Ñ Ñ‚ÐµÐ±Ðµ помогли.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "При приближении Ð³ÐµÑ€Ð¾Ñ Ð´Ñ€ÐµÐ²ÐµÑные глаза заÑветилиÑÑŒ воÑторгом. \"Ð, Ñтранник! " "Позволь преподать тебе малую толику того, что Ñ Ð²Ñ‹ÑƒÑ‡Ð¸Ð» за годы.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "При приближении Ð³ÐµÑ€Ð¾Ñ Ð´Ñ€ÐµÐ²ÐµÑные глаза заÑветилиÑÑŒ воÑторгом." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ооо, дорогой путник! Я буду ÑчаÑтлив научить Ñ‚ÐµÐ±Ñ Ð½ÐµÐ±Ð¾Ð»ÑŒÑˆÐ¾Ð¹ чаÑти моих " "знаний вÑего-лишь за %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(ПроÑто зарой их вокруг моих корней.)" msgid "Tears brim in the eyes of the tree." msgstr "Слёзы потекли по краÑм глаз дерева." msgid "\"I need %{count} %{res}.\"" msgstr "\"Мне нужно %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" "прошептало оно, вÑхлипнув. \"Ðу, возвращайÑÑ ÐºÐ¾Ð³Ð´Ð° Ñможешь мне заплатить.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Среди деревьев Ñидит Ñлепой провидец. Когда Ð’Ñ‹ объÑÑнили ему цель Ñвоего " "путешеÑтвиÑ, провидец активировал Ñвой хруÑтальный шар, позволив увидеть " "Ñильные и Ñлабые Ñтороны Ваших противников." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Вход в пещеру зиÑет чёрной дырой, из которой Ñ‚Ñнет тошнотворным ÑерниÑтым " "зловонием. ОтважитеÑÑŒ ли Ð’Ñ‹ войти?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "ЕÑли не Ñчитать Ñледов ужаÑной битвы, пещера пуÑта." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Ð’ пещере Ð’Ñ‹ обнаружили грозного до нелепоÑти демона. \"СегоднÑ,\" - прорычал " "он, - \"Ñ‚ÐµÐ±Ñ Ð¶Ð´ÑƒÑ‚ бой и Ð²ÐµÑ€Ð½Ð°Ñ Ñмерть, но Ñ Ð´Ð°Ð¼ тебе выбор. Ты можешь " "дратьÑÑ Ñо мной или же Ñ Ð¼Ð¾Ð¸Ð¼Ð¸ Ñлугами. Предпочитаешь ÑразитьÑÑ Ñ Ð¼Ð¾Ð¸Ð¼Ð¸ " "Ñлугами?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Демон жутко кричит и броÑаетÑÑ Ð² атаку! ПоÑле жеÑтокой, но короткой битвы Ð’Ñ‹ " "победили монÑтра и получили %{exp} очков опыта." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Демон жутко кричит и броÑаетÑÑ Ð² атаку! ПоÑле жеÑтокой, но короткой битвы Ð’Ñ‹ " "победили монÑтра и получили %{exp} очков опыта и %{count} золота." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Демон выкрикнул Ñвой вызов и броÑилÑÑ Ð² бой! ПоÑле краткой, но отчаÑнной " "Ñхватки Ð’Ñ‹ прикончили чудовище и нашли %{art} в глубине пещеры." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Даже %{count} жалких монет не наберетÑÑ Ñƒ ВаÑ. Демон Ñжимает когти и перед " "глазами вÑтает краÑÐ½Ð°Ñ Ð¿ÐµÐ»ÐµÐ½Ð°. Больше Ð’Ñ‹ ничего не видите..." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "\"Демон прыгает на Ð³ÐµÑ€Ð¾Ñ Ð¸ мгновенно вонзает когти в его глотку. \"Ð¢Ð²Ð¾Ñ " "жизнь в моих рукаххх,\" - шипит он. - \"давай золото, %{count} монет, и " "убирайÑÑ, пока Ñ Ð´Ð¾Ð±Ñ€Ñ‹Ð¹.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "ПоÑле победы над Ñлугами демона Ð’Ñ‹ обнаружили тайник Ñ Ð·Ð¾Ð»Ð¾Ñ‚Ð¾Ð¼ из %{count} " "монет." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Когда Ð’Ñ‹ входите в башню алхимика, хромаÑ, к Вам направлÑетÑÑ Ñедеющий " "Ñтарец в коричневом плаще." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Он проверÑет Ð’Ð°Ñ Ð¸ видит %{count} проклÑтый артефакт." msgstr[1] "Он проверÑет Ð’Ð°Ñ Ð¸ видит %{count} проклÑтых артефакта." msgstr[2] "Он проверÑет Ð’Ð°Ñ Ð¸ видит %{count} проклÑтых артефактов." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "За %{gold} золотом, алхимик поможет Вам уничтожить его. Ð’Ñ‹ заплатите?" msgstr[1] "" "За %{gold} золотом, алхимик поможет Вам уничтожить каждый. Ð’Ñ‹ заплатите?" msgstr[2] "" "За %{gold} золотом, алхимик поможет Вам уничтожить каждый. Ð’Ñ‹ заплатите?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "ПоÑле того, как Ð’Ñ‹ ÑоглаÑилиÑÑŒ заплатить запрошенную Ñумму золота, алхимик " "хватает проклÑтый артефакт и броÑает его в Ñвой волшебный котёл." msgstr[1] "" "ПоÑле того, как Ð’Ñ‹ ÑоглаÑилиÑÑŒ заплатить запрошенную Ñумму золота, алхимик " "хватает проклÑтые артефакты и броÑает их в Ñвой волшебный котёл." msgstr[2] "" "ПоÑле того, как Ð’Ñ‹ ÑоглаÑилиÑÑŒ заплатить запрошенную Ñумму золота, алхимик " "хватает проклÑтые артефакты и броÑает их в Ñвой волшебный котёл." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Ð’Ñ‹ Ñлышите Ð³Ð¾Ð»Ð¾Ñ Ð¸Ð·-за закрытой двери, \"Проходите мимо. У Ð’Ð°Ñ Ð½ÐµÐ´Ð¾Ñтаточно " "золота, чтобы заплатить за мои уÑлуги. \"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Ð’Ñ‹ уÑлышали Ð³Ð¾Ð»Ð¾Ñ Ñ Ð²ÐµÑ€ÑˆÐ¸Ð½Ñ‹ башни: \"УбирайтеÑÑŒ! Я не могу Вам помочь!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "К герою подошёл главный конюх. \"Какой у Ð’Ð°Ñ Ð¿Ñ€ÐµÐºÑ€Ð°Ñный конь. БоюÑÑŒ, Ñ Ð½Ðµ " "могу предложить Вам ничего лучше, но зато мы можем дать тренированных боевых " "коней Вашим вÑадникам.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Когда Ваш герой приблизилÑÑ Ðº конюшнÑм, поÑвилÑÑ Ð³Ð»Ð°Ð²Ð½Ñ‹Ð¹ конюх, ведущий " "краÑивого боевого Ñкакуна. \"Этот конь поможет Вам быÑтрее добратьÑÑ Ð´Ð¾ " "нужного меÑта, но его Ñил хватит на 7 дней. К тому же, мы можем дать новых " "коней и Вашим вÑадникам.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "ПоÑвилÑÑ Ñтарший конюх, ведущий краÑивого боевого Ñкакуна. \"У Ð’Ð°Ñ Ð¾Ñ‚Ð»Ð¸Ñ‡Ð½Ñ‹Ð¹ " "конь под Ñедлом, и в Вашей армии нет неопытных вÑадников, кого мы могли бы " "обучить иÑкуÑÑтву езды на тренированных боевых Ñкакунах.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Когда Ваш герой приблизилÑÑ Ðº конюшнÑм, поÑвилÑÑ Ð³Ð»Ð°Ð²Ð½Ñ‹Ð¹ конюх, ведущий " "краÑивого боевого Ñкакуна. \"Этот конь поможет Вам быÑтрее добратьÑÑ Ð´Ð¾ " "нужного меÑта, но его Ñил хватит на 7 дней. У Ð½Ð°Ñ Ñ‚Ð°ÐºÐ¶Ðµ много тренированных " "боевых коней, которые могли бы принеÑти пользу Вашим вÑадникам, но у Ð’Ð°Ñ Ð½ÐµÑ‚ " "никого, кому мы могли бы помочь. \"" msgid "The Arena guards turn you away." msgstr "Стража арены преградила Вам дорогу и не пропуÑтила внутрь." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Ð’Ñ‹ приказали Ñвоей команде залить уши воÑком, прежде чем подплыть к Ñиренам, " "чтобы поÑлушать их пение, которое запроÑто может погубить вÑех в морÑкой " "пучине." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Едва Ñирены затÑнули Ñвою ужаÑную пеÑню, как команда Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾Ñильнее налегла " "на вёÑла и увела корабль подальше в открытое море." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Ðад камнÑми разнеÑлаÑÑŒ Ð¶ÑƒÑ‚ÐºÐ°Ñ Ð¿ÐµÑÐ½Ñ Ñирен. Многие из команды Ð³ÐµÑ€Ð¾Ñ Ð±Ñ€Ð¾ÑилиÑÑŒ " "в воду под дейÑтвием Ñтих чар и утонули в морÑкой пучине. Ð”Ð»Ñ Ð³ÐµÑ€Ð¾Ñ Ñто был " "хороший урок, давший %{exp} очков опыта." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "С оÑлепительной отвагой Ð’Ñ‹ ворвалиÑÑŒ в меÑтную темницу и оÑвободили героÑ, " "томÑщегоÑÑ Ð·Ð´ÐµÑÑŒ. Ð’ благодарноÑть он поклÑлÑÑ Ñлужить Вам." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "У Ð’Ð°Ñ ÑƒÐ¶Ðµ %{count} героев. К Ñожалению, Вам придётÑÑ Ð¾Ñтавить томитьÑÑ Ñтого " "Ð³ÐµÑ€Ð¾Ñ Ð² темнице ещё неопределённое времÑ." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Герой зашёл в ветхую хибару и заговорил Ñ Ð¼Ð°Ð³Ð¾Ð¼, живущим тут. Маг поведал " "герою о меÑтах, которые ему доводилоÑÑŒ видеть. Это может пригодитÑÑ Ð’Ð°Ð¼ в " "Ваших путешеÑтвиÑÑ…." msgid "This eye seems to be intently studying its surroundings." msgstr "КажетÑÑ, Ñтот глаз внимательно изучает окреÑтноÑти." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Ð’Ñ‹ подошли к огромному СфинкÑу, но он даже не шелохнулÑÑ." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"ЕÑть у Ð¼ÐµÐ½Ñ Ð·Ð°Ð³Ð°Ð´ÐºÐ° Ð´Ð»Ñ Ñ‚ÐµÐ±Ñ,\" - Ñказал СфинкÑ. \"Ответишь верно - " "получишь награду. ОшибешьÑÑ - и Ñ Ñ‚ÐµÐ±Ñ Ñъем. Принимаешь ли ты мой вызов?" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Ð¡Ñ„Ð¸Ð½ÐºÑ Ð·Ð°Ð³Ð°Ð´Ð°Ð» Вам Ñледующую загадку:\n" "\n" "'" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" "'\n" "\n" "Ваш ответ?" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Ð¢Ð²Ð¾Ñ Ð´Ð¾Ð³Ð°Ð´ÐºÐ° ошибочна,\" - Ñказал, улыбаÑÑÑŒ, СфинкÑ. УхмылÑющийÑÑ Ð¡Ñ„Ð¸Ð½ÐºÑ " "повалил Ð’Ð°Ñ Ð½Ð° землю и мир окутала непроглÑÐ´Ð½Ð°Ñ Ñ‚ÑŒÐ¼Ð°." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "ÐеÑколько разочарованно Ð¡Ñ„Ð¸Ð½ÐºÑ Ð¿Ñ€Ð¾Ð¼Ð¾Ð»Ð²Ð¸Ð»: \"Ты дал верный ответ, вот Ñ‚Ð²Ð¾Ñ " "награда. Ртеперь убирайÑÑ.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Вам преграждает путь магичеÑкий барьер. Вдруг, на нём, магичеÑкими рунами, " "выÑветилаÑÑŒ надпиÑÑŒ:\n" " \"ПроизнеÑи волшебное Ñлово и Ñможешь пройти\"\n" " Ð’Ñ‹ произноÑите волшебное Ñлово и магичеÑкий барьер иÑчезает." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Вам преграждает путь магичеÑкий барьер. Вдруг, на нем, магичеÑкими рунами, " "выÑветилаÑÑŒ надпиÑÑŒ:\n" " \"ПроизнеÑи волшебное Ñлово и Ñможешь пройти\"\n" " Ð’Ñ‹ произноÑите разные Ñлова, но ничего не проиÑходит." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Ð’Ñ‹ входите в палатку и видите Ñтарую женщину, она приÑтально Ñмотрит в " "волшебный камень. Она Ñмотрит и говорит: \"Ð’ дальних Ñтранах Ñ Ð¾Ð±ÑƒÑ‡Ð°Ð»Ð°ÑÑŒ " "тайной магии. Сам великий оракул обучал Ð¼ÐµÐ½Ñ Ð´Ñ€ÐµÐ²Ð½Ð¸Ð¼ хитроÑÑ‚Ñм. У Ð¼ÐµÐ½Ñ ÐµÑть " "ответ, который Ð’Ñ‹ ищете.\"" msgid "No spell book is present." msgstr "Книга заклинаний отÑутÑтвует." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Заклинание требует %{mana} очков магии. У Ð’Ð°Ñ Ð½ÐµÑ‚ очков магии, поÑтому Ð’Ñ‹ не " "можете произнеÑти заклинание." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Заклинание требует %{mana} очков магии. У Ð’Ð°Ñ Ñ‚Ð¾Ð»ÑŒÐºÐ¾ %{point}, поÑтому Ð’Ñ‹ не " "можете произнеÑти заклинание." msgid "The spell was not found." msgstr "Заклинание не найдено." msgid "Only heroes can cast this spell." msgstr "Только герои могут колдовать данное заклинание." msgid "This hero is not able to cast adventure spells." msgstr "Ваш герой не может иÑпользовать Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð½Ð° карте." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Ваш герой очень уÑтал, и не Ñможет применÑть магию ÑегоднÑ. Попробуйте ещё " "раз завтра." msgid "This spell cannot be cast on a boat." msgstr "Это заклинание не дейÑтвует в море." msgid "This spell can only be cast near an ocean." msgstr "Это заклинание дейÑтвует только у воды." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Ðет Ñвободных кораблей и Ñ€Ñдом Ñ Ð³ÐµÑ€Ð¾ÐµÐ¼ нет океана или меÑта в океане, где " "Ñработает Ñто заклинание." msgid "There are no boats available for this spell." msgstr "ОтÑутÑтвуют Ñвободные корабли Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñтого заклинаниÑ." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "РÑдом Ñ Ð³ÐµÑ€Ð¾ÐµÐ¼ нет океана или меÑта в океане, где Ñработает Ñто заклинание." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "У Ð’Ð°Ñ Ð½ÐµÑ‚ ни одного Ñвободного города или замка. Потому Ñто заклинание не " "Ñработает." msgid "This hero is already in a town, so this spell will have no effect." msgstr "Этот герой уже в замке, поÑтому Ñто заклинание не Ñработает." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Ближайший к Вам город: %{town}.\n" "\n" "Ð’ Ñтом городе уже еÑть Ваш герой: %{hero}." msgid "This spell is already in effect." msgstr "Это заклинание уже дейÑтвует." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Ðет ни одного противника у которого еÑть или могли бы быть герои. Это " "заклинание не Ñработает." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Ð’ наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½Ð¸ у одного противника нет героев. Это заклинание не " "Ñработает." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Ð’Ñ‹ должны находитьÑÑ Ð½Ðµ далее %{count} ходов от армии ÑущеÑтв Ð´Ð»Ñ Ð¼Ð°Ð³Ð¸Ð¸ " "Видение." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñтого Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð’Ñ‹ должны подойти ко входу в шахту (на " "леÑопилки и лаборатории алхимика оно не дейÑтвует)." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Ð”Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð’Ð°Ð¼ необходимо Ñначала победить призраков, " "охранÑющих шахту." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Эту шахту уже охранÑет не меньшее чиÑло Ñлементалей, чем Ð’Ñ‹ можете призвать. " "Это заклинание не Ñработает." msgid "%{name} the %{race} (Level %{level})" msgstr "%{race} %{name} (уровень %{level})" msgid "Random hero (Level %{level})" msgstr "Случайный герой (Уровень %{level})" msgid "Random %{race} hero (Level %{level})" msgstr "%{race}, Ñлучайный герой (Уровень %{level})" msgid "Hero race:" msgstr "Ð¤Ñ€Ð°ÐºÑ†Ð¸Ñ Ð³ÐµÑ€Ð¾Ñ:" msgid "Are you sure you want to dismiss this Hero?" msgstr "Ð’Ñ‹ дейÑтвительно хотите уволить героÑ?" msgid "Set custom Experience value. Current value is default." msgstr "УÑтановить величину опыта. Ð¡ÐµÐ¹Ñ‡Ð°Ñ - по умолчанию." msgid "Change Experience value. Right-click to reset to default value." msgstr "Изменить величину опыта. Правый клик - ÑброÑить." msgid "View Experience Info" msgstr "Опыт" msgid "Set custom Spell Points value. Current value is default." msgstr "УÑтановить величину очков магии. Ð¡ÐµÐ¹Ñ‡Ð°Ñ - по умолчанию." msgid "Change Spell Points value. Right-click to reset to default value." msgstr "Изменить величину очков магии. Правый клик - ÑброÑить." msgid "Set Spell Points value" msgstr "Введите величину очков магии" msgid "View Spell Points Info" msgstr "Очки магии" msgid "Set patrol radius in tiles" msgstr "Введите Ñ€Ð°Ð´Ð¸ÑƒÑ Ð¿Ð°Ñ‚Ñ€ÑƒÐ»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² клетках" msgid "Enter hero's name" msgstr "Введите Ð¸Ð¼Ñ Ð³ÐµÑ€Ð¾Ñ" msgid "Click to change race." msgstr "Ðажмите, чтобы изменить фракцию." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Разомкнутый боевой порÑдок предпиÑывает армии Ð³ÐµÑ€Ð¾Ñ Ð·Ð°Ð½Ñть позиции по вÑей " "ширине Ñтартового раÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¾Ð¹Ñк в бою Ñ Ð¸Ð½Ñ‚ÐµÑ€Ð²Ð°Ð»Ð°Ð¼Ð¸ между отрÑдами." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "Сомкнутый боевой порÑдок предпиÑывает отрÑдам армии Ð³ÐµÑ€Ð¾Ñ Ð¾Ñ€Ð³Ð°Ð½Ð¸Ð·Ð¾Ð²Ð°Ñ‚ÑŒ " "плотное поÑтроение поÑередине Ñтартового раÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð²Ð¾Ð¹Ñк в бою." msgid "Exit Hero Screen" msgstr "Закрыть Экран ГероÑ" msgid "You cannot dismiss a hero in a castle" msgstr "ÐÐµÐ»ÑŒÐ·Ñ ÑƒÐ²Ð¾Ð»Ð¸Ñ‚ÑŒ Ð³ÐµÑ€Ð¾Ñ Ð² замке" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Увольнение %{name} %{race} запрещено Ñценарием" msgid "Dismiss %{name} the %{race}" msgstr "Уволить %{race} %{name}" msgid "Show previous hero" msgstr "Предыдущий герой" msgid "Show next hero" msgstr "Следующий герой" msgid "Set army combat formation to 'Spread'" msgstr "Разомкнутый Ñтрой" msgid "Set army combat formation to 'Grouped'" msgstr "Сомкнутый Ñтрой" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "Выбрать артефакты героÑ. Правый клик - ÑброÑить." msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "Выбрать вторичные навыки героÑ. Правый клик - ÑброÑить." msgid "Set hero's Army. Right-click to reset unit." msgstr "Выбрать ÑущеÑтво в армию героÑ. Правый клик - ÑброÑить." msgid "Set hero's portrait. Right-click to reset to default." msgstr "Выбрать портрет героÑ. Правый клик - ÑброÑить." msgid "Click to change hero's name. Right-click to reset to default." msgstr "Ðажмите Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ героÑ. Правый клик - ÑброÑить." msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" "Герой патрулирует облаÑть радиуÑом в %{tiles} клеток. Ðажмите Ð´Ð»Ñ Ð¾Ñ‚ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ." msgid "Click to enable hero's patrol mode." msgstr "Ðажмите, чтобы уÑтановить Ð³ÐµÑ€Ð¾Ñ Ð² режим патрулÑ." msgid "Blood Morale" msgstr "Ð’ Бой!" msgid "%{morale} Morale" msgstr "Мораль %{morale}" msgid "%{luck} Luck" msgstr "Удача %{luck}" msgid "Current Luck Modifiers:" msgstr "Текущие модификаторы удачи:" msgid "Current Morale Modifiers:" msgstr "Текущие модификаторы морали:" msgid "Entire army is undead, so morale does not apply." msgstr "Мораль неприменима к нежити." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Текущий опыт %{exp1}.\n" "Следующий уровень %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Уровень %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} имеет %{point} очков магии из макÑимальных %{max}. МакÑимальное " "чиÑло очков магии - количеÑтво очков навыка Ð·Ð½Ð°Ð½Ð¸Ñ Ð³ÐµÑ€Ð¾Ñ Ð² деÑÑтикратном " "размере. Иногда, поÑле поÑÐµÑ‰ÐµÐ½Ð¸Ñ Ñпециальных меÑÑ‚, герой может получить " "больше очков заклинаний, чем данное макÑимальное чиÑло." msgid "%{name1} meets %{name2}" msgstr "%{name1} вÑтретил %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Ð’Ñе вражеÑкие Герои опознаны." msgid "Identify Hero" msgstr "Опознать героÑ" msgid "Select town to port to." msgstr "Выберите, куда перенеÑтиÑÑŒ." msgid "Town Portal" msgstr "Портал города" msgid "The creatures are willing to join us!" msgstr "Эти ÑущеÑтва готовы приÑоединитьÑÑ!" msgid "All the creatures will join us..." msgstr "Ð’Ñе ÑущеÑтва приÑоединÑÑ‚ÑÑ Ðº армии героÑ..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "%{count} ÑущеÑтво приÑоединитÑÑ Ðº Вам..." msgstr[1] "%{count} ÑущеÑтва приÑоединитÑÑ Ðº Вам..." msgstr[2] "%{count} ÑущеÑтв приÑоединитÑÑ Ðº Вам..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "за плату %{gold} золотом." msgid "These weak creatures will surely flee before us." msgstr "Эта труÑÐ»Ð¸Ð²Ð°Ñ Ð°Ñ€Ð¼Ð¸Ñ ÑƒÐ±ÐµÐ¶Ð¸Ñ‚ от ВаÑ..." msgid "I fear these creatures are in the mood for a fight." msgstr "Скорее вÑего, Ñти ÑущеÑтва наÑтроены ÑражатьÑÑ." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Ðавык атаки Ð³ÐµÑ€Ð¾Ñ Ð´Ð°Ñ‘Ñ‚ Ð±Ð¾Ð½ÑƒÑ Ðº навыку атаки каждого ÑущеÑтва в его армии." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Ðавык защиты Ð³ÐµÑ€Ð¾Ñ Ð´Ð°Ñ‘Ñ‚ Ð±Ð¾Ð½ÑƒÑ Ðº навыку защиты каждого ÑущеÑтва в его армии." msgid "The hero's spell power determines the duration or power of a spell." msgstr "" "Ðавык Ñилы магии Ð³ÐµÑ€Ð¾Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñет длительноÑть дейÑÑ‚Ð²Ð¸Ñ Ð¸Ð»Ð¸ Ñилу " "применённого им заклинаниÑ." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Уровень знаний Ð³ÐµÑ€Ð¾Ñ Ð¾Ñ‚Ð²ÐµÑ‡Ð°ÐµÑ‚ за количеÑтво очков магии героÑ. Обычно, герой " "может получить 10 очков магии на каждый уровень знаний." msgid "Current Modifiers:" msgstr "Текущие модификаторы:" msgid "skill|Basic" msgstr "Базовый" msgid "skill|Advanced" msgstr "Продвинутый" msgid "skill|Expert" msgstr "ЭкÑперт" msgid "Pathfinding" msgstr "Следопыт" msgid "Archery" msgstr "Стрельба" msgid "Logistics" msgstr "ЛогиÑтика" msgid "Scouting" msgstr "Разведка" msgid "Diplomacy" msgstr "ДипломатиÑ" msgid "Navigation" msgstr "ÐавигациÑ" msgid "Leadership" msgstr "ЛидерÑтво" msgid "Wisdom" msgstr "МудроÑть" msgid "Mysticism" msgstr "МиÑтицизм" msgid "Ballistics" msgstr "БаллиÑтика" msgid "Eagle Eye" msgstr "Орлиный взор" msgid "Necromancy" msgstr "ÐекромантиÑ" msgid "Estates" msgstr "Казначей" msgid "Advanced Archery" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ñтрельба" msgid "Advanced Pathfinding" msgstr "Продвинутый Ñледопыт" msgid "Basic Archery" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ñтрельба" msgid "Basic Pathfinding" msgstr "Базовый Ñледопыт" msgid "Expert Pathfinding" msgstr "ЭкÑпертный Ñледопыт" msgid "Advanced Logistics" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ð»Ð¾Ð³Ð¸Ñтика" msgid "Basic Logistics" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ð»Ð¾Ð³Ð¸Ñтика" msgid "Basic Scouting" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ñ€Ð°Ð·Ð²ÐµÐ´ÐºÐ°" msgid "Expert Archery" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ñтрельба" msgid "Expert Logistics" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ð»Ð¾Ð³Ð¸Ñтика" msgid "Advanced Diplomacy" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ð´Ð¸Ð¿Ð»Ð¾Ð¼Ð°Ñ‚Ð¸Ñ" msgid "Advanced Scouting" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ñ€Ð°Ð·Ð²ÐµÐ´ÐºÐ°" msgid "Basic Diplomacy" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ð´Ð¸Ð¿Ð»Ð¾Ð¼Ð°Ñ‚Ð¸Ñ" msgid "Expert Diplomacy" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ð´Ð¸Ð¿Ð»Ð¾Ð¼Ð°Ñ‚Ð¸Ñ" msgid "Expert Scouting" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ñ€Ð°Ð·Ð²ÐµÐ´ÐºÐ°" msgid "Advanced Leadership" msgstr "Продвинутое лидерÑтво" msgid "Advanced Navigation" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ" msgid "Basic Leadership" msgstr "Базовое лидерÑтво" msgid "Basic Navigation" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ" msgid "Expert Navigation" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ð½Ð°Ð²Ð¸Ð³Ð°Ñ†Ð¸Ñ" msgid "Advanced Wisdom" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ð¼ÑƒÐ´Ñ€Ð¾Ñть" msgid "Basic Mysticism" msgstr "Базовый миÑтицизм" msgid "Basic Wisdom" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ð¼ÑƒÐ´Ñ€Ð¾Ñть" msgid "Expert Leadership" msgstr "ЭкÑпертное лидерÑтво" msgid "Expert Wisdom" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ð¼ÑƒÐ´Ñ€Ð¾Ñть" msgid "Advanced Luck" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ ÑƒÐ´Ð°Ñ‡Ð°" msgid "Advanced Mysticism" msgstr "Продвинутый миÑтицизм" msgid "Basic Luck" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ ÑƒÐ´Ð°Ñ‡Ð°" msgid "Expert Luck" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ ÑƒÐ´Ð°Ñ‡Ð°" msgid "Expert Mysticism" msgstr "ЭкÑпертный миÑтицизм" msgid "Advanced Ballistics" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ð±Ð°Ð»Ð»Ð¸Ñтика" msgid "Advanced Eagle Eye" msgstr "Продвинутый орлиный взор" msgid "Basic Ballistics" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ð±Ð°Ð»Ð»Ð¸Ñтика" msgid "Basic Eagle Eye" msgstr "Базовый орлиный взор" msgid "Expert Ballistics" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ð±Ð°Ð»Ð»Ð¸Ñтика" msgid "Advanced Necromancy" msgstr "ÐŸÑ€Ð¾Ð´Ð²Ð¸Ð½ÑƒÑ‚Ð°Ñ Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚Ð¸Ñ" msgid "Basic Estates" msgstr "Базовый казначей" msgid "Basic Necromancy" msgstr "Ð‘Ð°Ð·Ð¾Ð²Ð°Ñ Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚Ð¸Ñ" msgid "Expert Eagle Eye" msgstr "ЭкÑпертный орлиный взор" msgid "Expert Necromancy" msgstr "ЭкÑÐ¿ÐµÑ€Ñ‚Ð½Ð°Ñ Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚Ð¸Ñ" msgid "Advanced Estates" msgstr "Продвинутый казначей" msgid "Expert Estates" msgstr "ЭкÑперт казначей" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} уменьшает штраф при движении по переÑечённой меÑтноÑти на %{count} " "процентов." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} уÑтранÑет штраф при передвижении по переÑечённой меÑтноÑти." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} увеличивает урон от Ñтрелковых атак войÑк Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}% и " "уменьшает на %{penalty}% штраф при Ñтрельбе за преграды (например, Ñтены " "замка)." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} увеличивает очки Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ñ Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} процентов." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} увеличивает Ñ€Ð°Ð´Ð¸ÑƒÑ Ð¾Ð±Ð·Ð¾Ñ€Ð° Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} квадрат." msgstr[1] "%{skill} увеличивает Ñ€Ð°Ð´Ð¸ÑƒÑ Ð¾Ð±Ð·Ð¾Ñ€Ð° Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} квадрата." msgstr[2] "%{skill} увеличивает Ñ€Ð°Ð´Ð¸ÑƒÑ Ð¾Ð±Ð·Ð¾Ñ€Ð° Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} квадратов." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} позволÑет герою веÑти переговоры Ñ ÑущеÑтвами, которые Ñлабее его " "армии, и Ñнижает ÑтоимоÑть капитулÑции." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Примерно %{count} процентов ÑущеÑтв могут предложить приÑоединитьÑÑ Ðº армии " "героÑ." msgid "All of the creatures may offer to join the hero." msgstr "Ð’Ñе ÑущеÑтва могут предложить приÑоединитьÑÑ Ðº армии героÑ." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "СтоимоÑть капитулÑции Ñнижена до %{percent} процентов от общей ÑтоимоÑти " "войÑк в армии героÑ." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "%{skill} увеличивает передвижение Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ воде на %{count} процентов." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} увеличивает мораль войÑк Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} позволÑет герою изучать Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ 3-го круга." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} позволÑет герою изучать Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ 4-го круга." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} позволÑет герою изучать вÑе возможные заклинаниÑ." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} воÑÑтанавливает %{count} пункт магии Ð³ÐµÑ€Ð¾Ñ Ð² день." msgstr[1] "%{skill} воÑÑтанавливает %{count} пункта магии Ð³ÐµÑ€Ð¾Ñ Ð² день." msgstr[2] "%{skill} воÑÑтанавливает %{count} пунктов магии Ð³ÐµÑ€Ð¾Ñ Ð² день." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} увеличивает удачу войÑк Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} даёт выÑтрелам катапульты больший ÑˆÐ°Ð½Ñ Ð¿Ð¾Ñ€Ð°Ð·Ð¸Ñ‚ÑŒ и причинить вред " "Ñтенам замка." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} даёт катапульте Ñделать дополнительный выÑтрел, а также каждому " "выÑтрелу придаёт больший ÑˆÐ°Ð½Ñ Ð¿Ð¾Ñ€Ð°Ð·Ð¸Ñ‚ÑŒ и причинить вред Ñтенам замка." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} даёт катапульте Ñделать дополнительный выÑтрел, и каждый выÑтрел " "гарантированно разрушит любую Ñтену, за иÑключением укреплений в рыцарÑком " "замке." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} даёт герою %{count} процентов возможноÑти выучить заклинание 1-го " "или 2-го круга, применённое в бою противником." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} даёт герою %{count} процентов возможноÑти выучить заклинание 1-го, " "2-го или 3-го круга, применённое в бою противником." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} даёт герою %{count} процентов возможноÑти выучить заклинание 4-го " "круга и ниже, применённое в бою противником." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} может вернуть к жизни %{count} процентов ÑущеÑтв, убитых в " "Ñражении, в виде Скелетов." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Герой ежедневно Ñобирает налоги Ñо Ñвоих владений в размере %{count} золота." msgid "Blue" msgstr "Синий" msgid "Green" msgstr "Зелёный" msgid "Red" msgstr "КраÑный" msgid "Yellow" msgstr "Жёлтый" msgid "Orange" msgstr "Оранжевый" msgid "Purple" msgstr "Фиолетовый" msgid "barrier|Aqua" msgstr "Бирюзовый" msgid "barrier|Blue" msgstr "Синий" msgid "barrier|Brown" msgstr "Коричневый" msgid "barrier|Gold" msgstr "Жёлтый" msgid "barrier|Green" msgstr "Зелёный" msgid "barrier|Orange" msgstr "Оранжевый" msgid "barrier|Purple" msgstr "Фиолетовый" msgid "barrier|Red" msgstr "КраÑный" msgid "tent|Aqua" msgstr "Бирюзовый" msgid "tent|Blue" msgstr "Синий" msgid "tent|Brown" msgstr "Коричневый" msgid "tent|Gold" msgstr "Жёлтый" msgid "tent|Green" msgstr "Зелёный" msgid "tent|Orange" msgstr "Оранжевый" msgid "tent|Purple" msgstr "Фиолетовый" msgid "tent|Red" msgstr "КраÑный" msgid "Experience" msgstr "Опыт" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Опыт позволÑет Вашим героÑм повышать Ñвои уровни, Ñ€Ð°Ð·Ð²Ð¸Ð²Ð°Ñ Ñвои первичные и " "вторичные навыки." msgid "Hero/Stats" msgstr "Герой/ХарактериÑтика" msgid "Skills" msgstr "Ðавыки" msgid "Town/Castle" msgstr "Город/Замок" msgid "Garrison" msgstr "Гарнизон" msgid "Gold Per Day:" msgstr "Доход золота в день:" msgid "View Heroes." msgstr "ПроÑмотреть вÑех Ваших героев." msgid "Towns/Castles" msgstr "Города" msgid "View Towns and Castles." msgstr "ПроÑмотреть вÑе Ваши города и замки." msgid "luck|Cursed" msgstr "ПроклÑÑ‚!" msgid "luck|Awful" msgstr "УжаÑнаÑ" msgid "luck|Bad" msgstr "ПлохаÑ" msgid "luck|Normal" msgstr "ÐормальнаÑ" msgid "luck|Good" msgstr "ХорошаÑ" msgid "luck|Great" msgstr "ОтличнаÑ" msgid "luck|Irish" msgstr "Фортуна!" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "ÐžÑ‚Ñ€Ð¸Ñ†Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ ÑƒÐ´Ð°Ñ‡Ð° иногда поÑещает войÑка Ð³ÐµÑ€Ð¾Ñ Ð² бою, неудача вынуждает " "отрÑд атаковать только вполÑилы." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "ÐÐ¾Ñ€Ð¼Ð°Ð»ÑŒÐ½Ð°Ñ ÑƒÐ´Ð°Ñ‡Ð° подразумевает, что войÑка Ð³ÐµÑ€Ð¾Ñ Ð½Ðµ будут проводить как " "удачные, так и неудачные атаки." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "ÐŸÐ¾Ð»Ð¾Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ ÑƒÐ´Ð°Ñ‡Ð° иногда позволÑет отрÑдам Ð³ÐµÑ€Ð¾Ñ Ð¿Ñ€Ð¾Ð²Ð¾Ð´Ð¸Ñ‚ÑŒ удачные атаки в " "Ñражении, наноÑÑщие двойной урон." msgid "morale|Treason" msgstr "Ð’ панике!" msgid "morale|Awful" msgstr "УжаÑнаÑ" msgid "morale|Poor" msgstr "ПлохаÑ" msgid "morale|Normal" msgstr "ÐормальнаÑ" msgid "morale|Good" msgstr "ХорошаÑ" msgid "morale|Great" msgstr "ОтличнаÑ" msgid "morale|Blood!" msgstr "ЭйфориÑ!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "ÐžÑ‚Ñ€Ð¸Ñ†Ð°Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¼Ð¾Ñ€Ð°Ð»ÑŒ может заÑтавить отрÑд Ð³ÐµÑ€Ð¾Ñ Ð·Ð°Ñтыть на меÑте от ужаÑа." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "ÐžÐ±Ñ‹Ñ‡Ð½Ð°Ñ Ð¼Ð¾Ñ€Ð°Ð»ÑŒ подразумевает, что отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½Ðµ будут поощрÑтьÑÑ " "дополнительной атакой или пропуÑкать ход." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "ÐŸÐ¾Ð»Ð¾Ð¶Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¼Ð¾Ñ€Ð°Ð»ÑŒ может дать войÑкам Ð³ÐµÑ€Ð¾Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ñть дополнительной " "атаки в Ñражении." msgid "Knight" msgstr "Рыцарь" msgid "Barbarian" msgstr "Варвар" msgid "Sorceress" msgstr "КолдуньÑ" msgid "Warlock" msgstr "Чернокнижник" msgid "Wizard" msgstr "Чародей" msgid "Necromancer" msgstr "Ðекромант" msgid "Multi" msgstr "По Ñценарию" msgid "doubleLined|Knight" msgstr "Рыцарь" msgid "doubleLined|Barbarian" msgstr "Варвар" msgid "doubleLined|Sorceress" msgstr "КолдуньÑ" msgid "doubleLined|Warlock" msgstr "" "Черно-\n" "книжник" msgid "doubleLined|Wizard" msgstr "Чародей" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Ðекро-\n" "мант" msgid "doubleLinedRace|Multi" msgstr "" "По\n" "Ñценарию" msgid "doubleLinedRace|Random" msgstr "Случайно" msgid "speed|Standing" msgstr "Ðа меÑте" msgid "speed|Crawling" msgstr "ЧерепашьÑ" msgid "speed|Very Slow" msgstr "ПолзущаÑ" msgid "speed|Slow" msgstr "ÐизкаÑ" msgid "speed|Average" msgstr "СреднÑÑ" msgid "speed|Fast" msgstr "БыÑтраÑ" msgid "speed|Very Fast" msgstr "ШуÑтраÑ" msgid "speed|Ultra Fast" msgstr "СкороÑтнаÑ" msgid "speed|Blazing" msgstr "МолниеноÑнаÑ" msgid "speed|Instant" msgstr "МгновеннаÑ" msgid "Click this button to adjust the level of zoom." msgstr "Ðажмите Ñту кнопку, чтобы изменить коÑффициент маÑштабированиÑ." msgid "Zoom" msgstr "МаÑштаб" msgid "week|Squirrel" msgstr "Белки" msgid "week|Rabbit" msgstr "Кролика" msgid "week|Gopher" msgstr "СуÑлика" msgid "week|Badger" msgstr "БарÑука" msgid "week|Rat" msgstr "КрыÑÑ‹" msgid "week|Eagle" msgstr "Орла" msgid "week|Weasel" msgstr "Хорька" msgid "week|Raven" msgstr "Ворона" msgid "week|Mongoose" msgstr "МангуÑта" msgid "week|Dog" msgstr "Собаки" msgid "week|Aardvark" msgstr "Муравьеда" msgid "week|Lizard" msgstr "Ящера" msgid "week|Tortoise" msgstr "Черепахи" msgid "week|Hedgehog" msgstr "Ðжика" msgid "week|Condor" msgstr "Кондора" msgid "week|Ant" msgstr "МуравьÑ" msgid "week|Grasshopper" msgstr "Кузнечика" msgid "week|Dragonfly" msgstr "Стрекозы" msgid "week|Spider" msgstr "Паука" msgid "week|Butterfly" msgstr "Бабочки" msgid "week|Bumblebee" msgstr "ГуÑеницы" msgid "week|Locust" msgstr "Цикад" msgid "week|Earthworm" msgstr "ЗемлÑного червÑ" msgid "week|Hornet" msgstr "ШершнÑ" msgid "week|Beetle" msgstr "Жука" msgid "week|PLAGUE" msgstr "ЧУМЫ" msgid "week|Unnamed" msgstr "Без имени" msgid "Desert" msgstr "ПуÑтынÑ" msgid "Snow" msgstr "Снег" msgid "Wasteland" msgstr "ПуÑтошь" msgid "Beach" msgstr "Побережье" msgid "Lava" msgstr "Лава" msgid "Dirt" msgstr "ГрÑзь" msgid "Grass" msgstr "Трава" msgid "Ocean" msgstr "Океан" msgid "maps|Small" msgstr "МаленькаÑ" msgid "maps|Medium" msgstr "СреднÑÑ" msgid "maps|Large" msgstr "БольшаÑ" msgid "maps|Extra Large" msgstr "ОгромнаÑ" msgid "maps|Custom Size" msgstr "ОÑобый размер" msgid "Ore Mine" msgstr "Ð ÑƒÐ´Ð½Ð°Ñ ÑˆÐ°Ñ…Ñ‚Ð°" msgid "Sulfur Mine" msgstr "Ð¡ÐµÑ€Ð½Ð°Ñ ÑˆÐ°Ñ…Ñ‚Ð°" msgid "Crystal Mine" msgstr "КриÑÑ‚Ð°Ð»ÑŒÐ½Ð°Ñ ÑˆÐ°Ñ…Ñ‚Ð°" msgid "Gems Mine" msgstr "Ð¡Ð°Ð¼Ð¾Ñ†Ð²ÐµÑ‚Ð½Ð°Ñ ÑˆÐ°Ñ…Ñ‚Ð°" msgid "Gold Mine" msgstr "Ð—Ð¾Ð»Ð¾Ñ‚Ð°Ñ ÑˆÐ°Ñ…Ñ‚Ð°" msgid "Mine" msgstr "Шахта" msgid "Burma shave." msgstr "ЗдеÑÑŒ была Ñ€Ð¾Ð·Ð¾Ð²Ð°Ñ Ð¿Ð¾Ð½Ð¸." msgid "Next sign 50 miles." msgstr "Следующий знак в 50 милÑÑ…." msgid "See Rock City." msgstr "Тот, кто читает Ñту надпиÑÑŒ, у того Ñамые краÑивые глаза." msgid "This space for rent." msgstr "Герои Меча и Магии - интереÑÐ½Ð°Ñ Ð¸Ð³Ñ€Ð°, но отдыхать глазам тоже надо." msgid "No object" msgstr "Ðет объекта" msgid "Alchemist Lab" msgstr "Ð›Ð°Ð±Ð¾Ñ€Ð°Ñ‚Ð¾Ñ€Ð¸Ñ Ð°Ð»Ñ…Ð¸Ð¼Ð¸ÐºÐ°" msgid "Sign" msgstr "Указатель" msgid "Buoy" msgstr "Буй" msgid "Skeleton" msgstr "Скелет" msgid "Daemon Cave" msgstr "Пещера демона" msgid "Treasure Chest" msgstr "Ларец Ñ Ñокровищами" msgid "Faerie Ring" msgstr "Кольцо фей" msgid "Campfire" msgstr "КоÑтёр" msgid "Fountain" msgstr "Фонтан" msgid "Gazebo" msgstr "БеÑедка" msgid "Genie Lamp" msgstr "ДревнÑÑ Ð»Ð°Ð¼Ð¿Ð°" msgid "Archer's House" msgstr "Дом Ñтрелков" msgid "Goblin Hut" msgstr "Хибара гоблина" msgid "Dwarf Cottage" msgstr "Избушка гномов" msgid "Peasant Hut" msgstr "Мазанка креÑтьÑн" msgid "Stables" msgstr "Конюшни" msgid "Alchemist's Tower" msgstr "Ð‘Ð°ÑˆÐ½Ñ Ð°Ð»Ñ…Ð¸Ð¼Ð¸ÐºÐ°" msgid "Event" msgstr "Событие" msgid "Dragon City" msgstr "Драконий город" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "МаÑк" msgstr[1] "МаÑка" msgstr[2] "МаÑков" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "ВодÑное колеÑо" msgstr[1] "ВодÑных колеÑа" msgstr[2] "ВодÑных колёÑ" msgid "Monster" msgstr "ОтрÑд" msgid "Obelisk" msgstr "ОбелиÑк" msgid "Oasis" msgstr "ОазиÑ" msgid "Resource" msgstr "РеÑурÑ" msgid "Sawmill" msgstr "ЛеÑопилка" msgid "Oracle" msgstr "Оракул" msgid "Shrine of the First Circle" msgstr "СвÑтилище 1-го круга" msgid "Shipwreck" msgstr "Кораблекрушение" msgid "Sea Chest" msgstr "МорÑкой Ñундук" msgid "Desert Tent" msgstr "Шатёр" msgid "Stone Liths" msgstr "Монолиты" msgid "Wagon Camp" msgstr "Лагерь у фургонов" msgid "Hut of the Magi" msgstr "Лачуга волхва" msgid "Whirlpool" msgstr "Водоворот" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "ВетрÑÐ½Ð°Ñ Ð¼ÐµÐ»ÑŒÐ½Ð¸Ñ†Ð°" msgstr[1] "ВетрÑные мельницы" msgstr[2] "ВетрÑных мельниц" msgid "Mermaid" msgstr "РуÑалка" msgid "Boat" msgstr "Корабль" msgid "Random Ultimate Artifact" msgstr "Случайный великий артефакт" msgid "Random Artifact" msgstr "Случайный артефакт" msgid "Random Resource" msgstr "Случайный реÑурÑ" msgid "Random Monster" msgstr "Случайное ÑущеÑтво" msgid "Random Town" msgstr "Случайный город" msgid "Random Castle" msgstr "Случайный замок" msgid "Eye of the Magi" msgstr "Око волхва" msgid "Random Monster - weak" msgstr "Случайное Ñлабое ÑущеÑтво" msgid "Random Monster - medium" msgstr "Случайное Ñреднее ÑущеÑтво" msgid "Random Monster - strong" msgstr "Случайное Ñильное ÑущеÑтво" msgid "Random Monster - very strong" msgstr "Случайное великое ÑущеÑтво" msgid "Hero" msgstr "Герой" msgid "Nothing Special" msgstr "Ðичего оÑобенного" msgid "Mossy Rock" msgstr "МшиÑÑ‚Ð°Ñ Ñкала" msgid "Watch Tower" msgstr "Ð¡Ñ‚Ð¾Ñ€Ð¾Ð¶ÐµÐ²Ð°Ñ Ð²Ñ‹ÑˆÐºÐ°" msgid "Tree House" msgstr "Домик на дереве" msgid "Tree City" msgstr "Древо-город" msgid "Ruins" msgstr "Руины" msgid "Fort" msgstr "Форт" msgid "Abandoned Mine" msgstr "Ð—Ð°Ð±Ñ€Ð¾ÑˆÐµÐ½Ð½Ð°Ñ ÑˆÐ°Ñ…Ñ‚Ð°" msgid "Sirens" msgstr "Сирены" msgid "Standing Stones" msgstr "СтоÑчие камни" msgid "Idol" msgstr "Идол" msgid "Tree of Knowledge" msgstr "Древо знаний" msgid "Witch Doctor's Hut" msgstr "Хижина колдуна" msgid "Temple" msgstr "Храм" msgid "Hill Fort" msgstr "Форт на холме" msgid "Halfling Hole" msgstr "Ðора полуроÑликов" msgid "Mercenary Camp" msgstr "Лагерь наёмников" msgid "Shrine of the Second Circle" msgstr "СвÑтилище 2-го круга" msgid "Shrine of the Third Circle" msgstr "СвÑтилище 3-го круга" msgid "City of the Dead" msgstr "Город мёртвых" msgid "Sphinx" msgstr "СфинкÑ" msgid "Wagon" msgstr "Тележка" msgid "Tar Pit" msgstr "СмолÑÐ½Ð°Ñ Ñма" msgid "Artesian Spring" msgstr "ÐртезианÑкий иÑточник" msgid "Troll Bridge" msgstr "МоÑÑ‚ троллей" msgid "Watering Hole" msgstr "Промоина" msgid "Witch's Hut" msgstr "Хижина ведьмы" msgid "Xanadu" msgstr "КÑанаду" msgid "Lean-To" msgstr "ÐавеÑ" msgid "Magellan's Maps" msgstr "Магеллан" msgid "Flotsam" msgstr "Обломки" msgid "Derelict Ship" msgstr "Заброшенный корабль" msgid "Shipwreck Survivor" msgstr "Тонущий матроÑ" msgid "Bottle" msgstr "Бутылка" msgid "Magic Well" msgstr "Волшебный колодец" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Волшебный Ñад" msgstr[1] "Волшебных Ñада" msgstr[2] "Волшебных Ñадов" msgid "Observation Tower" msgstr "ÐžÐ±Ð·Ð¾Ñ€Ð½Ð°Ñ Ð±Ð°ÑˆÐ½Ñ" msgid "Freeman's Foundry" msgstr "ЛитейнаÑ" msgid "Reefs" msgstr "Рифы" msgid "Volcano" msgstr "Вулкан" msgid "Flowers" msgstr "Цветы" msgid "Rock" msgstr "Камень" msgid "Water Lake" msgstr "Озеро" msgid "Mandrake" msgstr "Мандрагора" msgid "Dead Tree" msgstr "Сушина" msgid "Stump" msgstr "Пень" msgid "Crater" msgstr "Кратер" msgid "Cactus" msgstr "КактуÑ" msgid "Mound" msgstr "Курган" msgid "Dune" msgstr "Дюна" msgid "Lava Pool" msgstr "Лавовый баÑÑейн" msgid "Shrub" msgstr "КуÑтарник" msgid "Barrow Mounds" msgstr "Могильные курганы" msgid "Random Artifact - Treasure" msgstr "Случайный артефакт-Ñокровище" msgid "Random Artifact - Minor" msgstr "Случайный малый артефакт" msgid "Random Artifact - Major" msgstr "Случайный Ñильный артефакт" msgid "Barrier" msgstr "Барьер" msgid "Traveller's Tent" msgstr "Шатёр путника" msgid "Jail" msgstr "Тюрьма" msgid "Fire Summoning Altar" msgstr "Ðлтарь ОгнÑ" msgid "Air Summoning Altar" msgstr "Ðлтарь Воздуха" msgid "Earth Summoning Altar" msgstr "Ðлтарь Земли" msgid "Water Summoning Altar" msgstr "Ðлтарь Воды" msgid "Swampy Lake" msgstr "БолотиÑтое озеро" msgid "Frozen Lake" msgstr "Замёрзшее озеро" msgid "randomRace|level 1 creatures" msgstr "ÑущеÑтва 1 уровнÑ" msgid "randomRace|level 2 creatures" msgstr "ÑущеÑтва 2 уровнÑ" msgid "randomRace|level 3 creatures" msgstr "ÑущеÑтва 3 уровнÑ" msgid "randomRace|level 4 creatures" msgstr "ÑущеÑтва 4 уровнÑ" msgid "randomRace|level 5 creatures" msgstr "ÑущеÑтва 5 уровнÑ" msgid "randomRace|level 6 creatures" msgstr "ÑущеÑтва 6 уровнÑ" msgid "Unknown Monsters" msgstr "ÐеизвеÑтные ÑущеÑтва" msgid "Unknown Monster" msgstr "ÐеизвеÑтное ÑущеÑтво" msgid "Peasant" msgstr "КреÑтьÑнин" msgid "Peasants" msgstr "КреÑтьÑне" msgid "Archer" msgstr "Стрелок" msgid "Archers" msgstr "Стрелки" msgid "Ranger" msgstr "Рейнджер" msgid "Rangers" msgstr "Рейнджеры" msgid "Pikeman" msgstr "Копейщик" msgid "Pikemen" msgstr "Копейщики" msgid "Veteran Pikeman" msgstr "Опытный копейщик" msgid "Veteran Pikemen" msgstr "Опытные копейщики" msgid "Swordsman" msgstr "Мечник" msgid "Swordsmen" msgstr "Мечники" msgid "Master Swordsman" msgstr "Опытный мечник" msgid "Master Swordsmen" msgstr "Опытные мечники" msgid "Cavalries" msgstr "Ð’Ñадники" msgid "Cavalry" msgstr "Ð’Ñадник" msgid "Champion" msgstr "Чемпион" msgid "Champions" msgstr "Чемпионы" msgid "Paladin" msgstr "Паладин" msgid "Paladins" msgstr "Паладины" msgid "Crusader" msgstr "КреÑтоноÑец" msgid "Crusaders" msgstr "КреÑтоноÑцы" msgid "Goblin" msgstr "Гоблин" msgid "Goblins" msgstr "Гоблины" msgid "Orc" msgstr "Орк" msgid "Orcs" msgstr "Орки" msgid "Orc Chief" msgstr "Вождь орков" msgid "Orc Chiefs" msgstr "Вожди орков" msgid "Wolf" msgstr "Волк" msgid "Wolves" msgstr "Волки" msgid "Ogre" msgstr "Огр" msgid "Ogres" msgstr "Огры" msgid "Ogre Lord" msgstr "Лорд огров" msgid "Ogre Lords" msgstr "Лорды огров" msgid "Troll" msgstr "Тролль" msgid "Trolls" msgstr "Тролли" msgid "War Troll" msgstr "Боевой тролль" msgid "War Trolls" msgstr "Боевые тролли" msgid "Cyclopes" msgstr "Циклопы" msgid "Cyclops" msgstr "Циклоп" msgid "Sprite" msgstr "ФеÑ" msgid "Sprites" msgstr "Феи" msgid "Dwarf" msgstr "Гном" msgid "Dwarves" msgstr "Гномы" msgid "Battle Dwarf" msgstr "Боевой гном" msgid "Battle Dwarves" msgstr "Боевые гномы" msgid "Elf" msgstr "Эльф" msgid "Elves" msgstr "Эльфы" msgid "Grand Elf" msgstr "Ð’Ñ‹Ñший Ñльф" msgid "Grand Elves" msgstr "Ð’Ñ‹Ñшие Ñльфы" msgid "Druid" msgstr "Друид" msgid "Druids" msgstr "Друиды" msgid "Greater Druid" msgstr "Старший друид" msgid "Greater Druids" msgstr "Старшие друиды" msgid "Unicorn" msgstr "Единорог" msgid "Unicorns" msgstr "Единороги" msgid "Phoenix" msgstr "ФеникÑ" msgid "Phoenixes" msgstr "ФеникÑÑ‹" msgid "Centaur" msgstr "Кентавр" msgid "Centaurs" msgstr "Кентавры" msgid "Gargoyle" msgstr "ГоргульÑ" msgid "Gargoyles" msgstr "Горгульи" msgid "Griffin" msgstr "Грифон" msgid "Griffins" msgstr "Грифоны" msgid "Minotaur" msgstr "Минотавр" msgid "Minotaurs" msgstr "Минотавры" msgid "Minotaur King" msgstr "Царь минотавров" msgid "Minotaur Kings" msgstr "Цари минотавров" msgid "Hydra" msgstr "Гидра" msgid "Hydras" msgstr "Гидры" msgid "Green Dragon" msgstr "Зелёный дракон" msgid "Green Dragons" msgstr "Зелёные драконы" msgid "Red Dragon" msgstr "КраÑный дракон" msgid "Red Dragons" msgstr "КраÑные драконы" msgid "Black Dragon" msgstr "Чёрный дракон" msgid "Black Dragons" msgstr "Чёрные драконы" msgid "Halfling" msgstr "ПолуроÑлик" msgid "Halflings" msgstr "ПолуроÑлики" msgid "Boar" msgstr "Вепрь" msgid "Boars" msgstr "Вепри" msgid "Iron Golem" msgstr "Железный голем" msgid "Iron Golems" msgstr "Железные големы" msgid "Steel Golem" msgstr "Стальной голем" msgid "Steel Golems" msgstr "Стальные големы" msgid "Roc" msgstr "Птица Рух" msgid "Rocs" msgstr "Птицы Рух" msgid "Mage" msgstr "Маг" msgid "Magi" msgstr "Маги" msgid "Archmage" msgstr "Ðрхимаг" msgid "Archmagi" msgstr "Ðрхимаги" msgid "Giant" msgstr "Гигант" msgid "Giants" msgstr "Гиганты" msgid "Titan" msgstr "Титан" msgid "Titans" msgstr "Титаны" msgid "Skeletons" msgstr "Скелеты" msgid "Zombie" msgstr "Зомби" msgid "Zombies" msgstr "Зомби" msgid "Mutant Zombie" msgstr "Зомби-мутант" msgid "Mutant Zombies" msgstr "Зомби-мутанты" msgid "Mummies" msgstr "Мумии" msgid "Mummy" msgstr "МумиÑ" msgid "Royal Mummies" msgstr "КоролевÑкие мумии" msgid "Royal Mummy" msgstr "КоролевÑÐºÐ°Ñ Ð¼ÑƒÐ¼Ð¸Ñ" msgid "Vampire" msgstr "Вампир" msgid "Vampires" msgstr "Вампиры" msgid "Vampire Lord" msgstr "Лорд вампиров" msgid "Vampire Lords" msgstr "Лорды вампиров" msgid "Lich" msgstr "Лич" msgid "Liches" msgstr "Личи" msgid "Power Lich" msgstr "Могучий лич" msgid "Power Liches" msgstr "Могучие личи" msgid "Bone Dragon" msgstr "КоÑÑ‚Ñной дракон" msgid "Bone Dragons" msgstr "КоÑÑ‚Ñные драконы" msgid "Rogue" msgstr "Разбойник" msgid "Rogues" msgstr "Разбойники" msgid "Nomad" msgstr "Кочевник" msgid "Nomads" msgstr "Кочевники" msgid "Ghost" msgstr "Призрак" msgid "Ghosts" msgstr "Призраки" msgid "Genie" msgstr "Джинн" msgid "Genies" msgstr "Джинны" msgid "Medusa" msgstr "Медуза" msgid "Medusas" msgstr "Медузы" msgid "Earth Elemental" msgstr "Земной Ñлементаль" msgid "Earth Elementals" msgstr "Земные Ñлементали" msgid "Air Elemental" msgstr "Воздушный Ñлементаль" msgid "Air Elementals" msgstr "Воздушные Ñлементали" msgid "Fire Elemental" msgstr "Огненный Ñлементаль" msgid "Fire Elementals" msgstr "Огненные Ñлементали" msgid "Water Elemental" msgstr "Водный Ñлементаль" msgid "Water Elementals" msgstr "Водные Ñлементали" msgid "Random Monsters" msgstr "Случайные ÑущеÑтва" msgid "Random Monster 1" msgstr "Случайное ÑущеÑтво 1" msgid "Random Monsters 1" msgstr "Случайные ÑущеÑтва 1" msgid "Random Monster 2" msgstr "Случайное ÑущеÑтво 2" msgid "Random Monsters 2" msgstr "Случайные ÑущеÑтва 2" msgid "Random Monster 3" msgstr "Случайное ÑущеÑтво 3" msgid "Random Monsters 3" msgstr "Случайные ÑущеÑтва 3" msgid "Random Monster 4" msgstr "Случайное ÑущеÑтво 4" msgid "Random Monsters 4" msgstr "Случайные ÑущеÑтва 4" msgid "Double shot" msgstr "Двойной выÑтрел" msgid "2-hex monster" msgstr "Занимает 2 клетки" msgid "Double strike" msgstr "Двойной удар" msgid "Double damage to Undead" msgstr "Двойной урон по нежити" msgid "% magic resistance" msgstr "% ÑÐ¾Ð¿Ñ€Ð¾Ñ‚Ð¸Ð²Ð»ÐµÐ½Ð¸Ñ Ðº магии" msgid "Immune to Mind spells" msgstr "ÐевоÑприимчивы к магии разума" msgid "Immune to Elemental spells" msgstr "ÐевоÑприимчивы к магии Ñтихий" msgid "Immune to Fire spells" msgstr "ÐевоÑприимчивы к магии огнÑ" msgid "Immune to Cold spells" msgstr "ÐевоÑприимчивы к магии холода" msgid "Immune to " msgstr "ÐевоÑприимчивы к " msgid "% immunity to %{spell} spell" msgstr "% уÑтойчивоÑти к заклинанию %{spell}" msgid "% damage from Elemental spells" msgstr "% урона от заклинаний Ñтихий" msgid "% damage from %{spell} spell" msgstr "% урона от Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% ÑˆÐ°Ð½Ñ Ñ€Ð°Ð·Ð²ÐµÑть полезные заклинаниÑ" msgid "% chance to Paralyze" msgstr "% ÑˆÐ°Ð½Ñ Ð¿Ð°Ñ€Ð°Ð»Ð¸Ð·Ð¾Ð²Ð°Ñ‚ÑŒ" msgid "% chance to Petrify" msgstr "% ÑˆÐ°Ð½Ñ Ð½Ð°Ð»Ð¾Ð¶Ð¸Ñ‚ÑŒ окаменение" msgid "% chance to Blind" msgstr "% ÑˆÐ°Ð½Ñ Ð¾Ñлепить" msgid "% chance to Curse" msgstr "% ÑˆÐ°Ð½Ñ Ð½Ð°Ð»Ð¾Ð¶Ð¸Ñ‚ÑŒ проклÑтие" msgid "% chance to cast %{spell} spell" msgstr "% ÑˆÐ°Ð½Ñ Ð½Ð°Ð»Ð¾Ð¶Ð¸Ñ‚ÑŒ заклинание %{spell}" msgid "HP regeneration" msgstr "Ð ÐµÐ³ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ð·Ð´Ð¾Ñ€Ð¾Ð²ÑŒÑ" msgid "Two hexes attack" msgstr "Ðтака на две клетки" msgid "Flyer" msgstr "Летает" msgid "Always retaliates" msgstr "Ð’Ñегда отвечает на удар" msgid "Attacks all adjacent enemies" msgstr "Ðтакует вÑех ÑоÑедних врагов" msgid "No melee penalty" msgstr "Ðет штрафа в ближнем бою" msgid "Dragon" msgstr "Дракон" msgid "Undead" msgstr "Ðежить" msgid "No enemy retaliation" msgstr "Враг не отвечает на атаку" msgid "HP drain" msgstr "Вампиризм" msgid "Cloud attack" msgstr "ÐžÐ±Ð»Ð°Ñ‡Ð½Ð°Ñ Ð°Ñ‚Ð°ÐºÐ°" msgid "Decreases enemy's morale by " msgstr "Снижает моральный дух противника на " msgid "% chance to halve enemy" msgstr "% ÑˆÐ°Ð½Ñ ÑƒÐ±Ð¸Ñ‚ÑŒ половину отрÑда" msgid "Soul Eater" msgstr "Пожиратель душ" msgid "Elemental" msgstr "Элементаль" msgid "No Morale" msgstr "Ðет морали" msgid "Earth creature" msgstr "Земное ÑущеÑтво" msgid "Air creature" msgstr "Воздушное ÑущеÑтво" msgid "Fire creature" msgstr "Огненное ÑущеÑтво" msgid "Water creature" msgstr "Водное ÑущеÑтво" msgid "Double damage from Fire spells" msgstr "Двойной урон от заклинаний огнÑ" msgid "Double damage from Cold spells" msgstr "Двойной урон от заклинаний холода" msgid "Double damage from Earth creatures" msgstr "Двойной урон от земных ÑущеÑтв" msgid "Double damage from Air creatures" msgstr "Двойной урон от воздушных ÑущеÑтв" msgid "Double damage from Fire creatures" msgstr "Двойной урон от огненных ÑущеÑтв" msgid "Double damage from Water creatures" msgstr "Двойной урон от водных ÑущеÑтв" msgid "Lightning" msgstr "МолниÑ" msgid "% immunity to " msgstr "% невоÑприимчивоÑти к " msgid "% damage from " msgstr "% урона от " msgid "The three Anduran artifacts magically combine into one." msgstr "Три магичеÑких артефакта Ðндурана, объединÑÑŽÑ‚ÑÑ Ð² один." msgid "View Spells" msgstr "ПроÑмотреть заклинаниÑ" msgid "View %{name} Info" msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ %{name}" msgid "Move %{name}" msgstr "ПеремеÑтить %{name}" msgid "Cannot move the Spellbook" msgstr "Ðевозможно перемеÑтить книгу заклинаний" msgid "This item can't be traded." msgstr "Эту вещь Ð½ÐµÐ»ÑŒÐ·Ñ Ð¿Ñ€Ð¾Ð´Ð°Ñ‚ÑŒ." msgid "Invalid Artifact" msgstr "Ðекорректный артефакт" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} увеличивает Ð·Ð½Ð°Ð½Ð¸Ñ Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Book of Knowledge" msgstr "Книга Ð’ÑезнаниÑ" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} увеличивает навык атаки Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Sword of Dominion" msgstr "Меч Ð’ÑевлаÑтиÑ" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} увеличивает навык защиты Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Cloak of Protection" msgstr "Ð—Ð°Ñ‰Ð¸Ñ‚Ð½Ð°Ñ Ðакидка" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} увеличивает Ñилу магии Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Wand of Magic" msgstr "Жезл Магии" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} увеличивает навыки атаки и защиты Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Shield" msgstr "Ð’Ñемогущий Щит" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} увеличивает Ñилу магии и Ð·Ð½Ð°Ð½Ð¸Ñ Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Staff" msgstr "Ð’Ñемогущий ПоÑох" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} увеличивает вÑе оÑновные параметры Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Crown" msgstr "Корона Ð’ÑевлаÑтиÑ" msgid "Golden Goose" msgstr "Золотой ГуÑÑŒ" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} приноÑит каждый день по %{count} золотых." msgid "Arcane Necklace of Magic" msgstr "Ожерелье Тайной Магии" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Волшебница, ÑпаÑÑ‘Ð½Ð½Ð°Ñ Ð¸Ð· проклÑтой гробницы, вознаграждает Ваш героизм " "изыÑканным ожерельем, украшенным драгоценными камнÑми." msgid "Caster's Bracelet of Magic" msgstr "МагичеÑкий БраÑлет" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Ð˜Ð·ÑƒÑ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð»Ñ‹ в заброшенной шахте, Ð’Ñ‹ ÑпаÑаете артель гномов, попавших в " "ловушку. Ð’ знак благодарноÑти их Ñтаршина дарит Вам золотой браÑлет." msgid "Mage's Ring of Power" msgstr "Кольцо Мага" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Ð’Ñ‹ Ñпешите на звук отчаÑнного Ð²Ð¾Ð¿Ð»Ñ Ð±Ð¾Ð»Ð¸ и видите кентавра, попавшего в " "западню. Ð’Ñ‹ помогаете ему оÑвободитьÑÑ, и он вручает Вам мешочек. ЗаглÑнув " "внутрь, Ð’Ñ‹ видите оÑлепительное бриллиантовое кольцо." msgid "Witch's Broach of Magic" msgstr "Брошь Ведьмы" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "РÑдом Ñ Ð¾Ñтанками Ñожжённой колдуньи лежит изÑÑ‰Ð½Ð°Ñ Ð±Ñ€Ð¾ÑˆÑŒ прекраÑной работы. " "ОÑторожно приблизившиÑÑŒ к обугленному трупу, Ð’Ñ‹ забираете брошь Ñебе." msgid "Medal of Valor" msgstr "Медаль Отваги" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} увеличивает мораль армии Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Ð’ награду за ÑпаÑение прекраÑной девы от поÑÑгательÑтв ненавиÑтного барона " "королевÑкий герольд вручает Вам Медаль Отваги." msgid "Medal of Courage" msgstr "Медаль МужеÑтва" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Ð’Ñ‹ ÑпаÑаете маленького мальчика от Ñтаи кровожадных волков и провожаете в " "имение его родителей. СчаÑтливый отец награждает Ð’Ð°Ñ ÐœÐµÐ´Ð°Ð»ÑŒÑŽ МужеÑтва." msgid "Medal of Honor" msgstr "Медаль ДоблеÑти" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Ð’Ñ‹ оÑвобождаете принцеÑÑу ÑоÑеднего королевÑтва из мерзких лап презренных " "работорговцев, и в награду за подвиг получаете Медаль ДоблеÑти." msgid "Medal of Distinction" msgstr "Медаль Почёта" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Ð’Ñ‹ избавлÑете округу от ужаÑного минотавра, добычей которому Ñлужили " "благородные рыцари, и ÑтановитеÑÑŒ кавалером Медали Почёта." msgid "Fizbin of Misfortune" msgstr "Символ Ðеудачи" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} значительно Ñнижает мораль армии Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Ðа обочине пуÑтынной дороги Ð’Ñ‹ замечаете медаль. Подобрав её, Ð’Ñ‹ оÑознаёте, " "что Ñтали неÑчаÑтным обладателем Символа Ðеудачи, который значительно " "Ñнижает мораль Вашей армии." msgid "Thunder Mace of Dominion" msgstr "Ð“Ñ€Ð¾Ð¼Ð¾Ð²Ð°Ñ ÐŸÐ°Ð»Ð¸Ñ†Ð°" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Во Ð²Ñ€ÐµÐ¼Ñ Ð¶ÑƒÑ‚ÐºÐ¾Ð¹ грозы Ð¼Ð¾Ð»Ð½Ð¸Ñ Ð±ÑŒÑ‘Ñ‚ в дерево, разноÑÑ ÐµÐ³Ð¾ на мелкие щепки. " "Среди обломков Ð’Ñ‹ обнаруживаете таинÑтвенную палицу." msgid "Armored Gauntlets of Protection" msgstr "Ð—Ð°Ñ‰Ð¸Ñ‚Ð½Ð°Ñ ÐŸÐµÑ€Ñ‡Ð°Ñ‚ÐºÐ°" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} увеличивает навык защиты Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Ð’Ñ‹ повÑтречали печально извеÑтного Чёрного РыцарÑ! Ваш поединок " "заканчиваетÑÑ Ð²Ð½Ð¸Ñ‡ÑŒÑŽ, и рыцарь в знак ÑƒÐ²Ð°Ð¶ÐµÐ½Ð¸Ñ Ð´Ð°Ñ€Ð¸Ñ‚ Вам пару латных " "перчаток." msgid "Defender Helm of Protection" msgstr "Шлем Защитника" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Краем глаза Ð’Ñ‹ замечаете золотиÑтый блеÑк Ñреди пышной зелени. ПриглÑдевшиÑÑŒ " "внимательнее, Ð’Ñ‹ находите под куÑтами великолепный золотой шлем." msgid "Giant Flail of Dominion" msgstr "ГигантÑкий Цеп" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Ðеуклюжий гигант Ð½Ð°Ð½Ñ‘Ñ Ñебе Ñмертельную рану ÑобÑтвенным боевым цепом. Ð’Ñ‹ " "прекраÑно владеете Ñтим оружием и Ñ ÑƒÐ²ÐµÑ€ÐµÐ½Ð½Ð¾Ñтью вынимаете цеп из мёртвых " "рук гиганта." msgid "Ballista of Quickness" msgstr "БаллиÑта" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "%{name} позволÑет произвеÑти один дополнительный выÑтрел из катапульты за " "ход." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "ПробираÑÑÑŒ через развалины древней крепоÑти, Ð’Ñ‹ находите орудие, которое " "превратило её в руины, удивительную баллиÑту замыÑловатой конÑтрукции." msgid "Stealth Shield of Protection" msgstr "Ðезримый Щит" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Ð’ руках у каменной Ñтатуи воина - великолепный ÑеребрÑный щит. Как только Ð’Ñ‹ " "забираете щит Ñебе, ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ€Ð°ÑÑыпаетÑÑ Ð² прах." msgid "Dragon Sword of Dominion" msgstr "Драконий Меч" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Ð’Ñ‹ пробираетеÑÑŒ узкой тропой, как вдруг ближайший куÑÑ‚ загораетÑÑ Ñрким " "пламенем. Ð’ огненном Ñмерче поÑвлÑетÑÑ Ð¿Ñ€ÐµÐºÑ€Ð°ÑÐ½Ð°Ñ Ð´Ð°Ð¼Ð°, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ñ€Ð¾Ñ‚Ñгивает " "Вам волшебный меч." msgid "Power Axe of Dominion" msgstr "Топор ВлаÑти" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Ð’Ñ‹ видите ÑеребрÑный топор, вогнанный в землю по Ñамую рукоÑть. Ваши воины " "пытаютÑÑ Ð²Ñ‹Ð´ÐµÑ€Ð½ÑƒÑ‚ÑŒ его, но уÑÐ¸Ð»Ð¸Ñ Ð¸Ñ… тщетны. Вам же хватило одного уÑÐ¸Ð»Ð¸Ñ Ð¸ " "топор у Ð’Ð°Ñ Ð² руках!" msgid "Divine Breastplate of Protection" msgstr "БожеÑтвенный ДоÑпех" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Шайка разбойников обыÑкивает тела мёртвых воинов. Ð’Ñ‹ разгонÑете мародёров и " "вдруг замечаете, что в Ñпешке они не заметили великолепный доÑпех." msgid "Minor Scroll of Knowledge" msgstr "Малый Свиток ЗнаниÑ" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Перед Вами возникает парÑщий в воздухе ÑтеклÑнный ларец Ñо Ñвитком внутри, " "лежащем на подушке из пурпурного бархата. От прикоÑÐ½Ð¾Ð²ÐµÐ½Ð¸Ñ ÐºÑ€Ñ‹ÑˆÐºÐ° ларца " "открываетÑÑ, и Ñвиток оказываетÑÑ Ñƒ Ð’Ð°Ñ Ð² руках." msgid "Major Scroll of Knowledge" msgstr "Большой Свиток ЗнаниÑ" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Ð’Ñ‹ навещаете меÑтного мудреца и раÑÑказываете о цели Вашего путешеÑтвиÑ. Он " "доÑтаёт из мешка пожелтевший Ñвиток и передаёт его Вам." msgid "Superior Scroll of Knowledge" msgstr "МогущеÑтвенный Свиток ЗнаниÑ" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Ð’Ñ‹ Ñтоите перед оÑтанками давно умершей жрицы друидов. Пожелтевшие от " "времени коÑти проглÑдывают через прорехи иÑтлевшего одеÑниÑ. Пошевелив груду " "ветоши, Ð’Ñ‹ находите древний Ñвиток." msgid "Foremost Scroll of Knowledge" msgstr "Свиток Ð’Ñ‹Ñшего ЗнаниÑ" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Груда пожелтевших коÑтей и обрывки иÑтлевшей материи - вот вÑÑ‘, что оÑталоÑÑŒ " "от жрицы друидов. Среди Ñтих оÑтанков Ð’Ñ‹ замечаете таинÑтвенный Ñвиток." msgid "Endless Sack of Gold" msgstr "Бездонный Мешок Золота" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} ежедневно приноÑит в казну дополнительные %{count} золотых." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Маленький лепрекон пританцовывает у волшебного мешка. Завидев ВаÑ, он " "замирает на меÑте, затем издаёт возмущённый возглаÑ, топает ножкой и " "раÑтворÑетÑÑ Ð² воздухе. Ð’Ñ‹ забираете мешок Ñебе." msgid "Endless Bag of Gold" msgstr "Ð‘ÐµÐ·Ð´Ð¾Ð½Ð½Ð°Ñ Ð¡ÑƒÐ¼Ð° Золота" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Ð‘Ð»Ð°Ð³Ð¾Ñ€Ð¾Ð´Ð½Ð°Ñ Ð¿ÑƒÑ‚ÐµÑˆÐµÑтвенница, отÑÑ‚Ð°Ð²ÑˆÐ°Ñ Ð¾Ñ‚ Ñпутников, проÑит Ð’Ð°Ñ Ð¾ помощи. " "Проводив её до дома, Ð’Ñ‹ получаете в награду Ñуму, полную золота." msgid "Endless Purse of Gold" msgstr "Бездонный Кошель" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Однажды Вам в руки попадает наполненный золотом кожаный кошель, " "принадлежавший великому королю, который умел превращать любой предмет в " "золото." msgid "Nomad Boots of Mobility" msgstr "Башмаки Кочевника" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} увеличивают передвижение Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ земле." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "БродÑчий торговец проÑит Ð’Ð°Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ð¸Ñ‚ÑŒ его от банды гоблинов. Ð’ награду он " "дарит Вам пару изÑщных башмаков, иÑпещрённых загадочными древними пиÑьменами." msgid "Traveler's Boots of Mobility" msgstr "Сапоги Путника" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Обнаружив пару замечательных башмаков, украшенных биÑером, Ð’Ñ‹ благодарите " "загадочного Ð±Ð»Ð°Ð³Ð¾Ð´ÐµÑ‚ÐµÐ»Ñ Ð¸ оÑтавлÑете их Ñебе." msgid "Lucky Rabbit's Foot" msgstr "ÐšÑ€Ð¾Ð»Ð¸Ñ‡ÑŒÑ Ð›Ð°Ð¿ÐºÐ°" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} увеличивает удачу армии Ð³ÐµÑ€Ð¾Ñ Ð² бою на %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Ð’ уплату за охрану в пути ÑтранÑтвующий торговец предлагает Вам лапку " "кролика. По его Ñловам, она принеÑёт Вам удачу в бою." msgid "Golden Horseshoe" msgstr "Ð—Ð¾Ð»Ð¾Ñ‚Ð°Ñ ÐŸÐ¾Ð´ÐºÐ¾Ð²Ð°" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Попавший в ловушку единорог иÑпуганно ржёт. Ð’Ñ‹ уÑпокаиваете его и " "оÑвобождаете от пут. Ð’Ñхрапнув и ударив копытом, он уноÑитÑÑ Ð¿Ñ€Ð¾Ñ‡ÑŒ. Там, где " "он только что ÑтоÑл, оÑталаÑÑŒ лежать Ð·Ð¾Ð»Ð¾Ñ‚Ð°Ñ Ð¿Ð¾Ð´ÐºÐ¾Ð²Ð°." msgid "Gambler's Lucky Coin" msgstr "СчаÑÑ‚Ð»Ð¸Ð²Ð°Ñ ÐœÐ¾Ð½ÐµÑ‚Ð°" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Ð’Ñ‹ поймали озорного беÑёнка, который не давал Ð¿Ð¾ÐºÐ¾Ñ Ð²Ñей округе. Ð’ обмен на " "Ñвободу он предлагает Вам волшебную монету." msgid "Four-Leaf Clover" msgstr "ЧетырёхлиÑтник" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "ПоÑреди мёртвой лощины, заполненной иÑÑохшей раÑтительноÑтью, Ð’Ñ‹, к Ñвоему " "удивлению, замечаете веÑёлый зелёный побег четырёхлиÑтного клевера." msgid "True Compass of Mobility" msgstr "КомпаÑ" msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} увеличивает передвижение Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ земле и воде." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Странноватый Ñтарикашка утверждает, что он - великий изобретатель, и проÑит " "Ð’Ð°Ñ Ð¸Ñпытать его новое творение. ÐадувшиÑÑŒ от важноÑти, он вручает Вам " "компаÑ." msgid "Sailor's Astrolabe of Mobility" msgstr "ÐÑтролÑбиÑ" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} увеличивает передвижение Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ воде." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Старый мореход Ñтал добычей людоедов. Ð’Ñ‹ ÑпаÑаете его, и в знак " "благодарноÑти он дарит Вам чудеÑный инÑтрумент, позволÑющий определÑть " "меÑтоположение по звёздам." msgid "Evil Eye" msgstr "Дурной Глаз" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} Ñнижает ÑтоимоÑть заклинаний проклÑÑ‚Ð¸Ñ Ð½Ð° половину." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Ð’ заброшенной хижине Ð’Ñ‹ находите Ñкелет давно почившей колдуньи. " "ПриглÑдевшиÑÑŒ, Ð’Ñ‹ замечаете, что в глазнице пожелтевшего черепа зловеще " "вращаетÑÑ ÑтеклÑнный глаз." msgid "Enchanted Hourglass" msgstr "Зачарованные ЧаÑÑ‹" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} увеличивает длительноÑть вÑех заклинаний Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} ход." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "За невыÑоким холмом перед Вами открываетÑÑ Ð·Ð»Ð¾Ð²ÐµÑ‰Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð¸Ð½Ð° - Ñтаи " "ÑтервÑтников пируют на поле недавней битвы. Среди тел поверженных воинов Ð’Ñ‹ " "находите волшебные пеÑочные чаÑÑ‹." msgid "Gold Watch" msgstr "Золотые ЧаÑÑ‹" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} удваивают Ñффект заклинаний гипноза." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Ð’Ñ‹ помогаете бродÑчему торговцу ÑнадобьÑми вытащить повозку из придорожной " "канавы. Ð’ знак благодарноÑти он вручает Вам золотые чаÑÑ‹. Он и не " "подозревал, что чаÑÑ‹ волшебные!" msgid "Skullcap" msgstr "Ермолка" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "%{name} Ñнижает вдвое ÑтоимоÑть вÑех заклинаний, влиÑющих на разум." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Ð’Ñ‹ делаете короткую оÑтановку в маленькой придорожной харчевне. Под звон " "монет проиÑходит обмен новоÑÑ‚Ñми, а то и редкими вещицами. Вот таким-то " "образом в Вашем багаже и оказываетÑÑ Ð²Ð¾Ð»ÑˆÐµÐ±Ð½Ð°Ñ ÑˆÐ°Ð¿Ð¾Ñ‡ÐºÐ°." msgid "Ice Cloak" msgstr "ЛедÑÐ½Ð°Ñ Ðакидка" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} Ñнижает вдвое веÑÑŒ урон нанеÑённый отрÑдам Ð³ÐµÑ€Ð¾Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñми холода." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Ð’Ñ‹ Ñпешите на отчаÑнные крики и видите очаровательную девушку, за которой " "гонитÑÑ Ñ€Ð°Ð·ÑŠÑрённый медведь. Через мгновение зверь повержен, и Ð±Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ð½Ð°Ñ " "волшебница шьёт Вам из его шкуры волшебный плащ." msgid "Fire Cloak" msgstr "ÐžÐ³Ð½ÐµÐ½Ð½Ð°Ñ Ðакидка" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} Ñнижает вдвое веÑÑŒ урон нанеÑённый отрÑдам Ð³ÐµÑ€Ð¾Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñми огнÑ." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "За поворотом дороги Ð’Ñ‹ видите ÑражающихÑÑ Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚Ð° и паладина. Ðекромант " "пытаетÑÑ Ñжечь паладина, но тот, отшатнувшиÑÑŒ, лишь падает на колени. Ð’Ñ‹ " "ÑпаÑаете жизнь паладину, ÑƒÐ±Ð¸Ð²Ð°Ñ ÐµÐ³Ð¾ врага, замахнувшегоÑÑ Ð´Ð»Ñ Ð¿Ð¾Ñледнего " "удара. Ð’ благодарноÑть паладин дарит Вам Ñвою огненно-краÑную накидку, " "ÑпаÑшую его от огнÑ." msgid "Lightning Helm" msgstr "Громовой Шлем" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} Ñнижает вдвое веÑÑŒ урон нанеÑённый отрÑдам Ð³ÐµÑ€Ð¾Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñми молний." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "БродÑчий медник, у которого кончилаÑÑŒ провизиÑ, предлагает Вам шлем Ñ " "гребнем в виде молнии в обмен на еду и питье. Ð’Ñ‹ ÑоглашаетеÑÑŒ на обмен, а " "вÑкоре обнаруживаете, что шлем обладает ещё и магичеÑкими ÑвойÑтвами." msgid "Evercold Icicle" msgstr "Ðетающий Лёд" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} увеличивает на %{count} процентов урон от заклинаний холода, " "произнеÑённых героем." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Ваше внимание привлекает ледÑÐ½Ð°Ñ ÑоÑулька, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð½Ðµ тает, неÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° " "полуденный зной. Ð’Ñ‹ отламываете её от карниза и Ñ ÑƒÐ´Ð¸Ð²Ð»ÐµÐ½Ð¸ÐµÐ¼ обнаруживаете, " "что даже тепло Ваших рук ей нипочём." msgid "Everhot Lava Rock" msgstr "ГорÑчий Камень" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} увеличивает на %{count} процентов урон от заклинаний огнÑ, " "произнеÑённых героем." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Ð’ дальней Ñтране Ð’Ñ‹ вÑтречаете Ð¿Ð»ÐµÐ¼Ñ Ð¿Ñ€Ð¸Ð¼Ð°Ñ‚Ð¾Ð². Они разжигают коÑтры при " "помощи волшебного куÑка лавы. Ð’Ñ‹ научили их добывать огонь обычным ÑпоÑобом. " "ОбезьÑны Ñчитают Ð’Ð°Ñ Ð±Ð¾Ð³Ð¾Ð¼ и дарÑÑ‚ Ñвой заветный куÑок лавы." msgid "Lightning Rod" msgstr "Жезл Молний" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} увеличивает на %{count} процентов урон от заклинаний молнии, " "произнеÑённых героем." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Во Ð²Ñ€ÐµÐ¼Ñ ÑƒÐ¶Ð°Ñной грозы на Ваших глазах в громоотвод дома бьёт молниÑ. " "Оплавленный громоотвод падает на землю, но его наконечник, похожий на жезл, " "оÑтаётÑÑ Ñ†ÐµÐ»Ñ‹Ð¼ и невредимым. Ваши волоÑÑ‹ вÑтают дыбом, когда к Ð’Ñ‹ к нему " "прикаÑаетеÑÑŒ. Хмм..." msgid "Snake-Ring" msgstr "Кольцо Змеи" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "%{name} Ñнижает ÑтоимоÑть вÑех заклинаний благоÑловениÑ." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Ðа пальце мёртвого Ñтранника Ð’Ñ‹ видите необычное кольцо. Оно имеет форму " "змеи, вцепившейÑÑ Ð·ÑƒÐ±Ð°Ð¼Ð¸ в ÑобÑтвенный хвоÑÑ‚." msgid "Ankh" msgstr "Символ Жизни" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} удваивает ÑффективноÑть вÑех заклинаний оживлениÑ, произнеÑённых " "героем." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "ПеÑÑ‡Ð°Ð½Ð°Ñ Ð±ÑƒÑ€Ñ Ð¾Ð±Ð½Ð°Ð¶Ð¸Ð»Ð° вход в подземную гробницу. Ð’Ñ‹ ÑпуÑкаетеÑÑŒ внутрь и " "обнаруживаете, что здеÑÑŒ уже побывали грабители, однако в темноте они не " "заметили Символ Жизни, виÑÑщий на ÑеребрÑной цепи." msgid "Book of Elements" msgstr "Книга Стихий" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" "%{name} удваивает ÑффективноÑть вÑех заклинаний призыва, произнеÑённых " "героем." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Ð’Ñ‹ вÑтречаете заклинателÑ, который проÑит разрешить ему воÑпользоватьÑÑ " "Вашим покровительÑтвом на опаÑном учаÑтке пути. Ð’Ñ‹ ÑоглашаетеÑÑŒ, и в награду " "он дарит Вам Книгу Стихий." msgid "Elemental Ring" msgstr "Кольцо Стихий" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" "%{name} Ñнижает наполовину ÑтоимоÑть вÑех заклинаний призыва, произнеÑённых " "героем." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "РаÑположившиÑÑŒ на отдых под невыÑоким деревом, Ð’Ñ‹ замечаете дикого кота, " "который подбираетÑÑ Ðº гнезду Ñороки. Ð’Ñ‹ прогонÑете кота и Ñ Ð»ÑŽÐ±Ð¾Ð¿Ñ‹Ñ‚Ñтвом " "заглÑдываете туда. Ð’ гнезде Ð’Ñ‹ обнаруживаете множеÑтво блеÑÑ‚Ñщих камушков, а " "также кольцо тонкой работы." msgid "Holy Pendant" msgstr "СвÑтой Кулон" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" "%{name} делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинаниÑм проклÑтиÑ." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "СтранÑÑ‚Ð²ÑƒÑ Ð¿Ð¾ дальним землÑм, Ð’Ñ‹ вÑтречаете отшельника, живущего в маленькой " "аккуратной хижине. Узнав о цели Ваших Ñкитаний, он прерывает Ñвои " "размышлениÑ, благоÑловлÑет Ð’Ð°Ñ Ð¸ дарит амулет, защищающий от злых чар." msgid "Pendant of Free Will" msgstr "ПодвеÑка Свободы" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" "%{name} воли делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинаниÑм гипноза." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Ð’Ñ‹ Ñлышите крики о помощи и, поÑпешив на берег реки, видите речных фей, " "потешающихÑÑ Ð½Ð°Ð´ Ñтариком, Ð¾ÐºÑƒÐ½Ð°Ñ ÐµÐ³Ð¾ в воду. Ð’Ñ‹ выручаете Ñтарика из беды и " "вытаÑкиваете одну фею на берег. Ð’ обмен на Ñвободу она отдаёт Вам волшебную " "подвеÑку." msgid "Pendant of Life" msgstr "Кулон Жизни" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинаниÑм Ñмерти." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Ð’ дороге Ð’Ñ‹ вÑтречаете небольшой караван. Сыграв Ñ Ñ…Ð¾Ð·Ñином каравана в " "коÑти, Ð’Ñ‹ выигрываете волшебную подвеÑку. Её прежний владелец утверждает, " "что она может противоÑтоÑть чарам Ñмерти некромантов." msgid "Serenity Pendant" msgstr "ПодвеÑка ПокоÑ" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" "%{name} делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинанию берÑерка." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Ð’Ñ‹ Ñпешите на шум ÑÑ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð¸ видите Ñтарика-варвара, который Ñ Ñ‚Ñ€ÑƒÐ´Ð¾Ð¼ " "отбиваетÑÑ Ð¾Ñ‚ гидры. Ваше неожиданное поÑвление отвлекает чудовище, и варвар " "оÑобо удачной атакой добивает его. Ð’ награду за помощь он дарит Вам " "волшебный кулон, которым обычно пользовалÑÑ Ð´Ð»Ñ ÑƒÑÐ¿Ð¾ÐºÐ¾ÐµÐ½Ð¸Ñ Ñ€Ð°Ð·ÑƒÐ¼Ð° перед " "битвой." msgid "Seeing-eye Pendant" msgstr "Ð’ÑевидÑщий Глаз" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" "%{name} делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинанию оÑлеплениÑ." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Ð’ хижине у дороги Ð’Ñ‹ находите Ñлепую Ñтаруху, умирающую в полном " "одиночеÑтве. Ð’Ñ‹ обещаете уÑтроить ей доÑтойные похороны. Ð’ знак " "благодарноÑти она дарит Вам волшебную подвеÑку." msgid "Kinetic Pendant" msgstr "Кулон СтремительноÑти" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" "%{name} делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинанию паралича." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Дорогу Вам преграждает голем, на шее которого Ñверкает кулон. Ð’Ñ‹ перерезаете " "шнурок, и он падает на землю. Голем раÑÑыпаетÑÑ Ñƒ Ð’Ð°Ñ Ð½Ð° глазах, а кулон " "доÑтаётÑÑ Ð’Ð°Ð¼." msgid "Pendant of Death" msgstr "Кулон Смерти" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" "%{name} делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинаниÑм Ð¸Ð·Ð³Ð½Ð°Ð½Ð¸Ñ " "нежити." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "ПоÑле короткой ожеÑточённой Ñхватки Ñ Ð½ÐµÐºÑ€Ð¾Ð¼Ð°Ð½Ñ‚Ð¾Ð¼ у Ð’Ð°Ñ Ð² руках оÑтаётÑÑ ÐµÐ³Ð¾ " "волшебный кулон. Знакомый чародей объÑÑнÑет Вам, что Ñтот кулон защищает " "нежить, ÑоÑтоÑщую в Вашей армии, от ÑвÑтого Ñлова." msgid "Wand of Negation" msgstr "ПоÑох ОтрицаниÑ" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "%{name} делает вÑе отрÑды Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ð¾Ñприимчивыми к заклинаниÑм ÑнÑÑ‚Ð¸Ñ Ñ‡Ð°Ñ€." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "ÐавÑтречу Вам попадаетÑÑ Ñтарый друг-чародей. Он вручает Вам подарок - " "волшебный жезл, который делает невозможным применение Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ ÑнÑÑ‚Ð¸Ñ Ñ‡Ð°Ñ€ " "против Ваших Ñоратников." msgid "Golden Bow" msgstr "Золотой Лук" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} уменьшает на %{count} процентов штраф при Ñтрельбе за преграды." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Ð’Ñ‹ Ñлучайно вÑтречаете знаменитого Ñтрелка и предлагаете ему Ñыграть в " "коÑти. Он ÑоглашаетÑÑ Ð¸ Ñтавит Ñвой лук против Вашего конÑ. Ð’Ñ‹ выигрываете." msgid "Telescope" msgstr "ТелеÑкоп" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "%{name} увеличивает Ñ€Ð°Ð´Ð¸ÑƒÑ Ð¾Ð±Ð·Ð¾Ñ€Ð° Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} клетку." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Торговец из далёких земель предлагает Вам новейшее изобретение Ñвоего народа " "в обмен на ÑъеÑтные припаÑÑ‹. Эту штуку, Ð±Ð»Ð°Ð³Ð¾Ð´Ð°Ñ€Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð¹ удалённые предметы " "кажутÑÑ Ð±Ð»Ð¸Ð¶Ðµ, он называет...\n" "\n" "телеÑкопом." msgid "Statesman's Quill" msgstr "Перо Дипломата" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} Ñнижает ÑтоимоÑть капитулÑции до %{count} процентов от общей " "ÑтоимоÑти войÑк в армии героÑ." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Ð’Ñ‹ помогаете дипломату починить Ñломанную оÑÑŒ в его Ñкипаже, и в знак " "благодарноÑти он дарит Вам перо. Он говорит, что Ñто перо заÑтавлÑет людей " "Ñмотреть на вещи глазами его обладателÑ." msgid "Wizard's Hat" msgstr "ШлÑпа Мага" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "" "%{name} увеличивает продолжительноÑть вÑех заклинаний Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} " "ходов." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Ð’Ñ‹ видите чародеÑ, который удирает от грифона. Вот он раÑпахнул портал и " "ринулÑÑ Ð²Ð½ÑƒÑ‚Ñ€ÑŒ, но при Ñтом зацепилÑÑ ÑˆÐ»Ñпой, и она упала на землю. Ð’Ñ‹ " "поднимаете шлÑпу, отрÑхиваете её от пыли и оÑтавлÑете Ñебе." msgid "Power Ring" msgstr "Кольцо Силы" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} воÑÑтанавливает %{count} очка магии в день." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Ð’Ñ‹ замечаете дерево, похожее на чернокнижника Карнота. Ðа одной из его веток " "Ñверкает кольцо. Ð’Ñ‹ вÑÑ‘ равно ничем не можете ему помочь, и поÑтому " "забираете кольцо Ñебе." msgid "Ammo Cart" msgstr "Оружейный Обоз" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} обеÑпечивает беÑконечными боеприпаÑами вÑех Ñтрелков в армии героÑ." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Ваше внимание привлекает повозка Ñ Ð±Ð¾ÐµÐ¿Ñ€Ð¸Ð¿Ð°Ñами, ÑтоÑÑ‰Ð°Ñ Ð¿Ð¾Ñреди полÑ, где " "когда-то гремела битва. УбедившиÑÑŒ, что она в хорошем ÑоÑтоÑнии, Ð’Ñ‹ " "приÑоединÑете её к Ñвоему обозу." msgid "Tax Lien" msgstr "Ð”Ð¾Ð»Ð³Ð¾Ð²Ð°Ñ Ð Ð°ÑпиÑка" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} Ñтоит герою %{count} золотых ежедневно." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Ваша любовь к большим тратам наградила Ð’Ð°Ñ Ð¾Ð³Ñ€Ð¾Ð¼Ð½Ñ‹Ð¼Ð¸ долгами, которые Ð’Ñ‹ " "можете и не мечтать оплатить. РоÑтовщик ÑжалилÑÑ Ð¸ ÑоглаÑилÑÑ Ð¿Ð¾Ð¶Ð¸Ð·Ð½ÐµÐ½Ð½Ð¾ " "Ñнимать только 250 золотых в день Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ Ñчёта. Этот договор впредь будет " "напоминать Вам о надлежащем иÑпользовании Ваших финанÑов." msgid "Hideous Mask" msgstr "УжаÑÐ½Ð°Ñ ÐœÐ°Ñка" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "%{name} не позволÑет нейтральным войÑкам вÑтупать в армию героÑ." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Ð’Ñ‹ вÑкрыли могилу Ð¡Ð¸Ð½Ñ„Ð¸Ð»Ð¸Ñ Ð“Ð°Ñ€Ð´Ð¾Ð»Ð°Ð´Ð°, знаменитого чернокнижника, и " "обнаружили его легендарную маÑку. Взволнованно Ð’Ñ‹ надеваете её, но она " "превращает Ваше лицо в ужаÑную гримаÑу. О нет! Ðа Ñамом деле Ñто " "Ð¾Ñ‚Ð²Ñ€Ð°Ñ‚Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¼Ð°Ñка Громлака Грина. Теперь от неё Вам не избавитьÑÑ!" msgid "Endless Pouch of Sulfur" msgstr "Бездонный Мешочек Серы" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} ежедневно приноÑит в казну дополнительно %{count} меру Ñеры." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Ð’Ñ‹ поÑещаете алхимика, который при виде Вашей армии незамедлительно признаёт " "Ð’Ð°Ñ Ð´Ð¾Ñтойнейшим из доÑтойных. Ðовый подданный дарит Вам Бездонный Мешочек " "Серы, который Вам очень даже пригодитÑÑ." msgid "Endless Vial of Mercury" msgstr "Ð‘ÐµÐ·Ð´Ð¾Ð½Ð½Ð°Ñ ÐšÐ¾Ð»Ð±Ð° Ртути" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} ежедневно приноÑит в казну дополнительно %{count} меру ртути." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Ð’Ñ‹ делаете короткий привал в башне чародеÑ, покинутой хозÑином, и находите " "волшебный ÑоÑуд Ñ Ñ€Ñ‚ÑƒÑ‚ÑŒÑŽ, Ñодержимое которого никогда не кончаетÑÑ. " "Безошибочно раÑпознав в нём Ñокровище, Ð’Ñ‹ хватаете его и кладёте в Ñвой " "карман." msgid "Endless Pouch of Gems" msgstr "Бездонный Мешочек Самоцветов" msgid "The %{name} provides %{count} unit of gems per day." msgstr "" "%{name} ежедневно приноÑит в казну дополнительно %{count} меру Ñамоцветов." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "ПоÑле короткого Ð»Ð¸Ð²Ð½Ñ Ð½Ð° небе поÑвлÑетÑÑ Ñ€Ð°Ð´ÑƒÐ³Ð°. Заметив меÑто, где она " "упираетÑÑ Ð² землю, Ð’Ñ‹ находите там горшок золота. Его хозÑин, маленький " "лепрекон, предлагает взамен Бездонный Мешочек Самоцветов. Ð’Ñ‹ его принимаете." msgid "Endless Cord of Wood" msgstr "ÐеÑÐºÐ¾Ð½Ñ‡Ð°ÐµÐ¼Ð°Ñ Ð’Ñзанка Дров" msgid "The %{name} provides %{count} unit of wood per day." msgstr "" "%{name} ежедневно приноÑит в казну дополнительно %{count} меру древеÑины." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Ð’Ñ‹ оÑтанавливаетеÑÑŒ на отдых и разводите коÑтёр. Ðеподалёку лежит куча дров. " "Ð’Ñ‹ берёте одно полено за другим, но куча не уменьшаетÑÑ. Ð’Ñ‹ Ñ Ñ€Ð°Ð´Ð¾Ñтью " "понимаете, что дрова зачарованы, и забираете их Ñебе." msgid "Endless Cart of Ore" msgstr "Ð‘ÐµÐ·Ð´Ð¾Ð½Ð½Ð°Ñ Ð’Ð°Ð³Ð¾Ð½ÐµÑ‚ÐºÐ° Руды" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} ежедневно приноÑит в казну дополнительно %{count} меру руды." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Ð’Ñ‹ находите кузницу гоблинов, где они куют оружие. С воинÑтвенным кличем, " "Ваши воины нападают на их лагерь и убивают вÑех врагов. ОÑмотрев трофеи, Ð’Ñ‹ " "обнаруживаете волшебную вагонетку Ñ Ñ€ÑƒÐ´Ð¾Ð¹." msgid "Endless Pouch of Crystal" msgstr "Бездонный Мешочек КриÑталлов" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "" "%{name} ежедневно приноÑит в казну дополнительно %{count} меру криÑталлов." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "УкрывшиÑÑŒ от бури в небольшой пещерке, Ð’Ñ‹ замечаете в углу друзу криÑталлов. " "Ð’Ñ‹ отламываете куÑок, а на его меÑте выраÑтает новый криÑталл. Ð’Ñ‹ прÑчете " "вÑÑ‘ в мешочек и забираете Ñто Ñокровище Ñ Ñобой." msgid "Spiked Helm" msgstr "Шипованный Шлем" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Ðебольшой отрÑд орков нападает на Вашу армию. Ð’Ñ‹ без труда отбиваете атаку. " "Ðа теле одного из нападавших Ð’Ñ‹ видите блеÑÑ‚Ñщий шлем Ñ ÑˆÐ¸Ð¿Ð°Ð¼Ð¸." msgid "Spiked Shield" msgstr "Шипованный Щит" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Ð’Ñ‹ приближаетеÑÑŒ к моÑту через глубокий овраг. Ðеожиданно из-под моÑта " "поÑвлÑетÑÑ Ñ‚Ñ€Ð¾Ð»Ð»ÑŒ и требует плату за проход. Получив отказ, тролль " "ÑамонадеÑнно нападает на ВаÑ. И теперь в Вашей коллекции новый трофей - его " "щит Ñ ÑˆÐ¸Ð¿Ð°Ð¼Ð¸." msgid "White Pearl" msgstr "Ð‘ÐµÐ»Ð°Ñ Ð–ÐµÐ¼Ñ‡ÑƒÐ¶Ð¸Ð½Ð°" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Ð’Ñ‹ переÑекаете переÑохшее ÑолÑное озеро, и вдруг Ñреди обломков ракушек и " "куÑков коралла замечаете великолепную белую жемчужину." msgid "Black Pearl" msgstr "Ð§Ñ‘Ñ€Ð½Ð°Ñ Ð–ÐµÐ¼Ñ‡ÑƒÐ¶Ð¸Ð½Ð°" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Слухи об огромном грифоне, нагонÑющем ÑƒÐ¶Ð°Ñ Ð½Ð° вÑÑŽ округу, приводÑÑ‚ Ð’Ð°Ñ Ð² его " "логово. ЖеÑÑ‚Ð¾ÐºÐ°Ñ Ñхватка заканчиваетÑÑ Ð’Ð°ÑˆÐµÐ¹ победой, и в опуÑтевшем гнезде " "Ð’Ñ‹ находите чёрную жемчужину." msgid "Magic Book" msgstr "Ð’Ð¾Ð»ÑˆÐµÐ±Ð½Ð°Ñ ÐšÐ½Ð¸Ð³Ð°" msgid "The %{name} enables the hero to cast spells." msgstr "%{name} позволÑет иÑпользовать заклинаниÑ." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" "К Вам подходит юноша: \"ГоÑподин, позвольте показать Вам моё изобретение Ð´Ð»Ñ " "раÑпроÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð·Ð½Ð°Ð½Ð¸Ð¹!\" Ð’Ñ‹ Ñледуете за ним в маÑтерÑкую и Ñразу замечаете " "большой аппарат Ñ Ñ€Ñ‹Ñ‡Ð°Ð³Ð°Ð¼Ð¸ и рукоÑтками. \"Вот оно!\", нетерпеливо говорит " "он, \"Печатный Ñтанок.\" Ð’Ñ‹ не уÑпеваете ничего Ñказать, как он вручвет Вам " "волшебную книгу." msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "Ðахождение любого великого артефакта будет означать победу." msgid "Dummy 2" msgstr "Болванка 2" msgid "The reserved artifact." msgstr "Забронированный артефакт." msgid "Dummy 3" msgstr "Болванка 3" msgid "Dummy 4" msgstr "Болванка 4" msgid "Spell Scroll" msgstr "Свиток ЗаклинаниÑ" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "%{name} позволÑет герою произноÑить заклинание %{spell}, еÑли он имеет " "Волшебную Книгу." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Ð’Ñ‹ находите замыÑловатый ÑоÑуд, в котором лежит Ñтарый пергаментный Ñвиток. " "Руны на нём очень древние, а маÑтерÑтво, Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ð¼ он был Ñобран, поражает " "воображение. Когда Ð’Ñ‹ доÑтаёте Ñвиток, Ð’Ñ‹ чувÑтвуете, что пропитаны " "магичеÑкой Ñилой." msgid "Arm of the Martyr" msgstr "Рука Мученика" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} увеличивает Ñилу магии Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}, но добавлÑет штраф к " "морали, как за нахождение нежити в отрÑде." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Один из менее Ñообразительных воинов поднимает Ñ Ð·ÐµÐ¼Ð»Ð¸ руку. ÐеÑÐ¼Ð¾Ñ‚Ñ€Ñ Ð½Ð° " "отÑутÑтвие тела, она вÑÑ‘ ещё двигаетÑÑ. Ваши Ñолдаты находÑÑ‚ отрубленную " "руку омерзительной, но Ð’Ñ‹ не можете заÑтавить ÑÐµÐ±Ñ Ð±Ñ€Ð¾Ñить её: кажетÑÑ, что " "она обладает какой-то магичеÑкой Ñилой, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð²Ð»Ð¸Ñет на принÑтие Вами " "решений." msgid "Breastplate of Anduran" msgstr "КираÑа Ðндурана" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} увеличивает навык защиты Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Указатель глаÑит: \"ЗдеÑÑŒ лежит тело Ðндурана. СклониÑÑŒ и поклÑниÑÑŒ в " "верноÑти и будешь вознагражден.\" Ð’Ñ‹ решили Ñделать точно также. Ð’Ñ‹ вÑтаете " "и чувÑтвуете холод на коже. ОÑÐ¼Ð°Ñ‚Ñ€Ð¸Ð²Ð°Ñ ÑебÑ, Ð’Ñ‹ обнаружили, что Ð’Ñ‹ ноÑите " "блеÑÑ‚Ñщую броню." msgid "Broach of Shielding" msgstr "Ð—Ð°Ñ‰Ð¸Ñ‚Ð½Ð°Ñ Ð‘Ñ€Ð¾ÑˆÑŒ" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} увеличивает защиту от 'Ðрмагеддона' и 'Бури Ñтихий' на %{count} " "процентов, но также уменьшает Ñилу магии на 2 пункта." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "ÐšÐ¾Ð»Ð´ÑƒÐ½ÑŒÑ Ñчитает, что Ð´Ð»Ñ Ð·Ð°Ñ‰Ð¸Ñ‚Ñ‹ Вашей армии можно иÑпользовать магичеÑкую " "поддержку. Она предлагает заколдовать брошь, что Ð’Ñ‹ ноÑите на Вашем плаще, и " "Ð’Ñ‹ ÑоглашаетеÑÑŒ." msgid "Battle Garb of Anduran" msgstr "Боевой ДоÑпех Ðндурана" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} Ñочетает в Ñебе Ñилу трёх артефактов Ðндурана. Он увеличивает удачу " "и мораль войÑк героÑ, а также даёт герою заклинание 'Портал города'." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Из жалоÑти к бедным креÑтьÑнам, Ð’Ñ‹ приобретаете груду ÑтарьÑ. Позже, Ð’Ñ‹ " "находите в нём 3 чаÑти легендарного боевого доÑпеха Ðндурана!" msgid "Crystal Ball" msgstr "КриÑтальный Шар" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} предоÑтавлÑет подробную информацию о ÑущеÑтвах, вражеÑких героÑÑ… и " "замках, Ñ€Ñдом Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ñ‹Ð¼Ð¸ Ñтоит герой." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Ð’Ñ‹ поÑетили караван цыган. У них идёт пирушка, пьÑные цыгане потерÑли Ñтрах, " "и Ð’Ð°Ñ Ð²Ñ‹Ð·Ñ‹Ð²Ð°ÑŽÑ‚: \"Докажешь, что ты танцуешь как Рама Бута, и мы наградим " "тебÑ.\"\n" "Ð’Ñ‹ решаете попробовать... Цыгане ÑмеютÑÑ Ð½Ð°Ð´ Вашими попытками, но воÑхищаÑÑÑŒ " "Вашим мужеÑтвом, отдают Вам 'КриÑтальный Шар'." msgid "Heart of Fire" msgstr "Сердце ОгнÑ" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} увеличивает защиту от магии Ð¾Ð³Ð½Ñ Ð½Ð° %{count} процентов, но также в " "два раза увеличивает урон от магии холода." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Ð’Ñ‹ поднимаетеÑÑŒ на вершину Ñкалы, где Ñидит Огненный Ñлементаль. Его " "пылающее лицо иÑкажено от Ñильной боли. Затем он броÑает ÑветÑщийÑÑ ÑгуÑток " "на ВаÑ. Ð’Ñ‹ делаете жеÑÑ‚ руками, чтобы заблокировать его, но ÑгуÑток проходит " "через Ваши руки и тело." msgid "Heart of Ice" msgstr "Сердце Льда" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} увеличивает защиту от магии холода на %{count} процентов, но также в " "два раза увеличивает урон от магии огнÑ." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Вдруг резкий холод охватывает Ваше тело, и Ð’Ñ‹ падаете Ñ Ð»Ð¾ÑˆÐ°Ð´Ð¸. Боль " "утихает, Ð’Ñ‹ поднимаетеÑÑŒ и Ñлышите Ñмех. Ð’Ñ‹ уÑпеваете обернутьÑÑ ÐºÐ°Ðº раз " "вовремÑ, чтобы увидеть ЛедÑного Гиганта ÑкрывающегоÑÑ Ð² леÑу." msgid "Helmet of Anduran" msgstr "Шлем Ðндурана" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Ð’Ñ‹ заметили блеÑÑ‚Ñщий объект недалеко в земле, и отправлÑете Ñвоего " "помощника раÑкопать его. Он возвращаетÑÑ Ñ Ð·Ð¾Ð»Ð¾Ñ‚Ñ‹Ð¼ шлемом в руках. Ð’Ñ‹ " "узнаёте легендарный шлем Ðндурана." msgid "Holy Hammer" msgstr "СвÑтой Молот" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Ð’Ñ‹ подъезжаете к полю боÑ. Паладин был Ñмертельно ранен группой Зомби. Он " "проÑит Ð’Ð°Ñ Ð·Ð°Ð±Ñ€Ð°Ñ‚ÑŒ его молот и закончить битву. Ð’Ñ‹ подбираете магичеÑкий " "молот, он начинает издавать мелодичные звуки, и потом вÑе вокруг рушитÑÑ. " "Ð’Ñе Зомби уничтожены. Залитый кровью молот Ð’Ñ‹ прицеплÑете к Ñвоему ремню." msgid "Legendary Scepter" msgstr "Легендарный Скипетр" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} увеличивает вÑе оÑновные параметры на %{count}." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Ðа небольшом холме, Ð’Ñ‹ видите Ñмешную Ñцену. Ð¤ÐµÑ Ð¿Ñ‹Ñ‚Ð°ÐµÑ‚ÑÑ Ð¿Ð¾Ð´Ð½Ñть большой " "Ñкипетр.\n" "СтараÑÑÑŒ не раÑÑмеÑтьÑÑ, Ð’Ñ‹ Ñпрашиваете: \"Возможно нужна помощь?\"\n" "Ð¤ÐµÑ Ñмотрит на Ð’Ð°Ñ Ð¸ отвечает: \"Ð’Ñ‹ думаете, Ñто Ñмешно? Хорошо. Забирайте " "его Ñебе, а Ñ ÑƒÐ»ÐµÑ‚Ð°ÑŽ.\"" msgid "Masthead" msgstr "Ðаконечник Мачты" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name}, при ÑражениÑÑ… на воде, увеличивает удачу и мораль войÑк Ð³ÐµÑ€Ð¾Ñ Ð½Ð° " "%{count}." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Старый морÑк раÑÑказал Вам иÑторию о заколдованной шлÑпе, которую он " "иÑпользовал во Ð²Ñ€ÐµÐ¼Ñ ÑˆÑ‚Ð¾Ñ€Ð¼Ð¾Ð². Затем он вручает Вам карту, на которой " "отмечено, где он ÑпрÑтал её. ПоÑле продолжительных поиÑков, Ð’Ñ‹ находите " "шлÑпу." msgid "Sphere of Negation" msgstr "Сфера ОтрицаниÑ" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} запрещает вÑем на поле Ð±Ð¾Ñ Ð¸Ñпользовать магию." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Ð’Ñ‹ оÑтановилиÑÑŒ помочь КреÑтьÑнам поймать Ñбежавшую лошадь. Чтобы выразить " "благодарноÑть, они вручают Вам крохотную Ñферу. Лишь только взÑв её, Ð’Ñ‹ " "чувÑтвуете, как магичеÑÐºÐ°Ñ ÑÐ½ÐµÑ€Ð³Ð¸Ñ Ð²Ñ‹ÑаÑываетÑÑ Ð¸Ð· Ваших рук." msgid "Staff of Wizardry" msgstr "Волшебный ПоÑох" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} увеличивает Ñилу магии Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Ð’Ñ‹ замечаете таинÑтвенный поÑох, парÑщий около трёх футов от земли, " "раÑпугавший вÑÑŽ дичь в округе. Ðа нём Ð’Ñ‹ заметили надпиÑÑŒ: \"Ум лучше " "муÑкулов, а Ð¼Ð°Ð³Ð¸Ñ Ð¿Ð¾Ð±ÐµÐ´Ð¸Ñ‚ Ñилу. Ð’Ñегда помни Ñто.\"" msgid "Sword Breaker" msgstr "Мечелом" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} увеличивает навык защиты Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}, и атаки на 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Бывший капитан Ñтражи воÑхищён Вашими приключениÑми и дарит Вам зачарованный " "Крушитель Клинков, на который он полагалÑÑ Ð²Ð¾ Ð²Ñ€ÐµÐ¼Ñ Ñлужбы." msgid "Sword of Anduran" msgstr "Меч Ðндурана" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Ð’Ð°Ñ Ð¾Ñтанавливает Тролль и говорит: \"Плати 5 тыÑÑч золотых или будешь убит " "на меÑте мечом Ðндурана\". Ð’Ñ‹ отказываетеÑÑŒ. Тролль выхватывает меч, " "ÑвиÑающий Ñ Ð¿Ð¾ÑÑа, вÑкрикивает от боли и убегает. ÐŸÐ¾Ð´Ð½Ð¸Ð¼Ð°Ñ Ð»ÐµÐ³ÐµÐ½Ð´Ð°Ñ€Ð½Ñ‹Ð¹ меч, " "Ð’Ñ‹ благодарите Ñудьбу за то, что недалекие Тролли имеют обыкновение хватать " "оÑтрые предметы не за тот конец." msgid "Spade of Necromancy" msgstr "Лопата Могильщика" msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} даёт герою повышенный навык некромантии." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "ГрÑÐ·Ð½Ð°Ñ Ð»Ð¾Ð¿Ð°Ñ‚Ð° торчала из могильного холма. ПоÑле иÑÑледованиÑ, оказалоÑÑŒ, " "что Ñто Ð·Ð°Ñ‡Ð°Ñ€Ð¾Ð²Ð°Ð½Ð½Ð°Ñ Ð»Ð¾Ð¿Ð°Ñ‚Ð° гробокопателей, ÑчитавшаÑÑÑ Ð´Ð°Ð²Ð½Ñ‹Ð¼-давно " "потерÑнной Ñмертными." msgid "spellBonus|selected by user" msgstr ", выбранное пользователем" msgid "Wood" msgstr "ДревеÑина" msgid "Mercury" msgstr "Ртуть" msgid "Ore" msgstr "Руда" msgid "Sulfur" msgstr "Сера" msgid "Crystal" msgstr "КриÑталлы" msgid "Gems" msgstr "Самоцветы" msgid "Gold" msgstr "Золото" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Ð’ Heroes II еÑть 7 типов реÑурÑов, иÑпользуемых Ð´Ð»Ñ Ð²Ð¾Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¿Ð¾Ñтроек, " "улучшений замков, покупки наиболее Ñильных ÑущеÑтв и героев. Самый " "раÑпроÑтранённый реÑÑƒÑ€Ñ - золото, необходимый практичеÑки везде. ДревеÑина и " "руда иÑпользуютÑÑ Ð´Ð»Ñ Ð²Ð¾Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð±Ð¾Ð»ÑŒÑˆÐ¸Ð½Ñтва поÑтроек. Самоцветы, ртуть, " "Ñера и криÑталлы - редкие магичеÑкие реÑурÑÑ‹, нужные Ð´Ð»Ñ Ð²Ð¾Ð·Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð»ÑƒÑ‡ÑˆÐ¸Ñ… " "поÑтроек и покупки Ñильных ÑущеÑтв." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Огромный огненный шар взрываетÑÑ Ð½Ð°Ð´ выбранной облаÑтью, Ð¿Ð¾Ñ€Ð°Ð¶Ð°Ñ Ð²Ñех, кого " "накрыло пламÑ." msgid "Fireball" msgstr "Огненный шар" msgid "Fireblast" msgstr "Огненный взрыв" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Огненный взрыв - Ñто ÑƒÐ»ÑƒÑ‡ÑˆÐµÐ½Ð½Ð°Ñ Ð²ÐµÑ€ÑÐ¸Ñ Ð¾Ð³Ð½ÐµÐ½Ð½Ð¾Ð³Ð¾ шара, Ð¿Ð¾Ñ€Ð°Ð¶Ð°ÑŽÑ‰Ð°Ñ Ð²Ñех на " "значительном раÑÑтоÑнии от Ñпицентра." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Мощный ÑлектричеÑкий разрÑд поражает выбранный отрÑд противника." msgid "Lightning Bolt" msgstr "МолниÑ" msgid "Chain Lightning" msgstr "Цепь молний" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Цепь молний поражает цель, а затем переÑкакивает на ближайший отрÑд, " "причинÑÑ Ð¿Ð¾Ð»Ð¾Ð²Ð¸Ð½Ñƒ урона от предыдущего, и так до 4-Ñ… отрÑдов. " "Предупреждение: Ñто заклинание может поразить Ваши ÑобÑтвенные отрÑды!" msgid "Teleport" msgstr "Телепорт" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Телепортирует выбранное ÑущеÑтво в любую Ñвободную точку на поле." msgid "Cure" msgstr "Лечение" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Убирает вÑе негативные Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ (кроме разрушающего луча) Ñ Ð’Ð°ÑˆÐµÐ³Ð¾ отрÑда " "и воÑÑтанавливает %{count}*SP здоровьÑ." msgid "Mass Cure" msgstr "Общее лечение" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Убирает вÑе негативные Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ (кроме разрушающего луча) Ñ Ð’Ð°ÑˆÐ¸Ñ… отрÑдов, " "и воÑÑтанавливает %{count}*SP здоровьÑ." msgid "Resurrect" msgstr "Оживление" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "До конца Ð±Ð¾Ñ Ð¾Ð¶Ð¸Ð²Ð»Ñет воинов в отрÑде, которому был нанеÑён урон или который " "был уничтожен." msgid "Resurrect True" msgstr "ВоÑкрешение" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" "ÐавÑегда оживлÑет воинов в отрÑде, которому был нанеÑён урон или который был " "уничтожен." msgid "Haste" msgstr "УÑкорение" msgid "Increases the speed of any creature by %{count}." msgstr "Увеличивает ÑкороÑть Вашего отрÑда на %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Увеличивает ÑкороÑть вÑех Ваших отрÑдов на %{count}." msgid "Mass Haste" msgstr "Общее уÑкорение" msgid "Slows target to half movement rate." msgstr "ЗамедлÑет вражеÑкий отрÑд на 2 Ñтупени." msgid "spell|Slow" msgstr "Замедление" msgid "Mass Slow" msgstr "Общее замедление" msgid "Slows all enemies to half movement rate." msgstr "ЗамедлÑет вÑе вражеÑкие отрÑды на 2 Ñтупени." msgid "spell|Blind" msgstr "Слепота" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" "ОÑлеплённый отрÑд пропуÑкает ходы до тех пор, пока не получит урон или не " "окончитÑÑ Ð´ÐµÐ¹Ñтвие заклинаниÑ." msgid "Bless" msgstr "БлагоÑловение" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Выбранный отрÑд будет наноÑить макÑимальный урон противнику." msgid "Causes all of your units to inflict maximum damage." msgstr "Ð’Ñе Ваши отрÑды будут наноÑить макÑимальный урон противнику." msgid "Mass Bless" msgstr "Общее благоÑловение" msgid "Magically increases the defense skill of the selected creatures." msgstr "МагичеÑки увеличивает защиту выбранного отрÑда на 3." msgid "Stoneskin" msgstr "ÐšÐ°Ð¼ÐµÐ½Ð½Ð°Ñ ÐºÐ¾Ð¶Ð°" msgid "Steelskin" msgstr "Ð¡Ñ‚Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð¶Ð°" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Увеличивает защиту выбранного отрÑда на 5. Это заклинание ÑвлÑетÑÑ Ð±Ð¾Ð»ÐµÐµ " "мощной верÑией Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ 'ÐšÐ°Ð¼ÐµÐ½Ð½Ð°Ñ ÐºÐ¾Ð¶Ð°'." msgid "Causes the selected creatures to inflict minimum damage." msgstr "ЗаÑтавлÑет вражеÑкий отрÑд при атаке наноÑить минимальный урон." msgid "Curse" msgstr "ПроклÑтие" msgid "Causes all enemy troops to inflict minimum damage." msgstr "ЗаÑтавлÑет вÑе вражеÑкие отрÑды при атаке наноÑить минимальный урон." msgid "Mass Curse" msgstr "Общее проклÑтие" msgid "Damages all undead in the battle." msgstr "ÐаноÑит урон вÑей нежити, находÑщейÑÑ Ð½Ð° поле боÑ." msgid "Holy Word" msgstr "СвÑтое Ñлово" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "УÑовершенÑтвованный вариант ÑвÑтого Ñлова, который причинÑет Ñильные " "Ð¿Ð¾Ð²Ñ€ÐµÐ¶Ð´ÐµÐ½Ð¸Ñ Ð²Ñей нежити, находÑщейÑÑ Ð½Ð° поле боÑ." msgid "Holy Shout" msgstr "Экзорцизм" msgid "Anti-Magic" msgstr "ÐнтимагиÑ" msgid "Prevents any magic against the selected creatures." msgstr "Защищает выбранный отрÑд от дейÑÑ‚Ð²Ð¸Ñ Ð²Ñех заклинаний." msgid "Dispel Magic" msgstr "СнÑтие чар" msgid "Removes all magic spells from a single target." msgstr "" "Снимает Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ отрÑда дейÑтвие вÑех заклинаний, как полезных, так и " "вредных." msgid "Mass Dispel" msgstr "Общее ÑнÑтие чар" msgid "Removes all magic spells from all creatures." msgstr "" "Снимает дейÑÑ‚Ð²Ð¸Ñ Ð²Ñех заклинаний, как полезных, так и вредных, Ñо вÑех " "приÑутÑтвующих на поле Ð±Ð¾Ñ Ð¾Ñ‚Ñ€Ñдов." msgid "Causes a magic arrow to strike the selected target." msgstr "Ð’Ð¾Ð»ÑˆÐµÐ±Ð½Ð°Ñ Ñтрела поражает отрÑд противника." msgid "Magic Arrow" msgstr "Ð’Ð¾Ð»ÑˆÐµÐ±Ð½Ð°Ñ Ñтрела" msgid "Berserker" msgstr "БерÑерк" msgid "Causes a creature to attack its nearest neighbor." msgstr "" "Выбранный отрÑд атакует любой ближайший к нему отрÑд, но поÑле атаки " "дейÑтвие Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰Ð°ÐµÑ‚ÑÑ." msgid "Armageddon" msgstr "Ðрмагеддон" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "Ð¥Ð°Ð¾Ñ Ð¾Ð±Ñ€ÑƒÑˆÐ¸Ð²Ð°ÐµÑ‚ÑÑ Ð½Ð° боле боÑ, причинÑÑ Ð²Ñем и вÑÑ Ð½ÐµÐ²ÐµÑ€Ð¾Ñтный урон." msgid "Elemental Storm" msgstr "Ð‘ÑƒÑ€Ñ Ñтихий" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "Силы Ñтихий обрушиваютÑÑ Ð½Ð° поле боÑ, Ð¿Ð¾Ñ€Ð°Ð¶Ð°Ñ Ð²Ñех учаÑтников ÑражениÑ." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Призывает дождь из камней, наноÑÑщий урон вÑем ÑущеÑтвам, находÑщимÑÑ Ð² поле " "дейÑÑ‚Ð²Ð¸Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ." msgid "Meteor Shower" msgstr "Камнепад" msgid "Paralyze" msgstr "Паралич" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "ОтрÑд, против которого направленно Ñто заклинание, Ñковывает паралич, и он " "терÑет ÑпоÑобноÑть передвигатьÑÑ Ð¸ отвечать на удары." msgid "Hypnotize" msgstr "Гипноз" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Выбранный вражеÑкий отрÑд переходит под Ваш полный контроль, еÑли его " "здоровье не превышает %{count}*SP." msgid "Cold Ray" msgstr "ЛедÑной луч" msgid "Drains body heat from a single enemy unit." msgstr "Ð’Ñ‹ÑаÑывает жизненное тепло из вражеÑкого отрÑда." msgid "Cold Ring" msgstr "ЛедÑное кольцо" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Ð’Ñ‹ÑаÑывает жизненное тепло из вражеÑких отрÑдов, находÑщихÑÑ Ð² зоне дейÑÑ‚Ð²Ð¸Ñ " "заклинаниÑ, за иÑключением его центра." msgid "Disrupting Ray" msgstr "Разрушающий луч" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Снижает защиту выбранного отрÑда на 3." msgid "Damages all living (non-undead) units in the battle." msgstr "ÐаноÑит урон вÑем живым ÑущеÑтвам на поле боÑ, кроме нежити." msgid "Death Ripple" msgstr "Дыхание Ñмерти" msgid "Death Wave" msgstr "Волна Ñмерти" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "ÐаноÑит значительный урон вÑем живым ÑущеÑтвам на поле боÑ, кроме нежити. " "Это заклинание ÑвлÑетÑÑ Ð±Ð¾Ð»ÐµÐµ мощной верÑией Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð¸Ñ 'Дыхание Ñмерти'." msgid "Dragon Slayer" msgstr "Убийца драконов" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Увеличивает атаку выбранного ÑущеÑтва в Ñхватке Ñ Ð´Ñ€Ð°ÐºÐ¾Ð½Ð°Ð¼Ð¸ на 5." msgid "Blood Lust" msgstr "Жажда крови" msgid "Increases a unit's attack skill." msgstr "Увеличивает атаку выбранного отрÑда на 3." msgid "Animate Dead" msgstr "ПоднÑть нежить" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "ÐавÑегда излечивает и поднимает павшую нежить." msgid "Mirror Image" msgstr "Фантом" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Создаёт дубликат одного из Ваших отрÑдов. Эта Ð¸Ð»Ð»ÑŽÐ·Ð¸Ñ Ð¼Ð¾Ð¶ÐµÑ‚ нанеÑти такой же " "урон как и оригинал, но будет развеÑна от малейшего повреждениÑ." msgid "Shield" msgstr "Щит" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Принимает на ÑÐµÐ±Ñ Ð¿Ð¾Ð»Ð¾Ð²Ð¸Ð½Ñƒ урона от вÑех Ñтрелковых атак врага, направленных " "на выбранный отрÑд. Ðе влиÑет на урон от замковых башен или баллиÑты." msgid "Mass Shield" msgstr "Общий щит" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Принимает на ÑÐµÐ±Ñ Ð¿Ð¾Ð»Ð¾Ð²Ð¸Ð½Ñƒ урона Ñтрелковых атак врага, направленных на вÑех " "Ваших ÑущеÑтв. Ðе влиÑет на урон от замковых башен или баллиÑты." msgid "Summon Earth Elemental" msgstr "Земной Ñлементаль" msgid "Summons Earth Elementals to fight for your army." msgstr "Призывает на поле Ð±Ð¾Ñ Ð—ÐµÐ¼Ð½Ñ‹Ñ… Ñлементалей ÑражатьÑÑ Ð½Ð° Вашей Ñтороне." msgid "Summon Air Elemental" msgstr "Воздушный Ñлементаль" msgid "Summons Air Elementals to fight for your army." msgstr "" "Призывает на поле Ð±Ð¾Ñ Ð’Ð¾Ð·Ð´ÑƒÑˆÐ½Ñ‹Ñ… Ñлементалей ÑражатьÑÑ Ð½Ð° Вашей Ñтороне." msgid "Summon Fire Elemental" msgstr "Огненный Ñлементаль" msgid "Summons Fire Elementals to fight for your army." msgstr "Призывает на поле Ð±Ð¾Ñ ÐžÐ³Ð½ÐµÐ½Ð½Ñ‹Ñ… Ñлементалей ÑражатьÑÑ Ð½Ð° Вашей Ñтороне." msgid "Summon Water Elemental" msgstr "Водный Ñлементаль" msgid "Summons Water Elementals to fight for your army." msgstr "Призывает на поле Ð±Ð¾Ñ Ð’Ð¾Ð´Ð½Ñ‹Ñ… Ñлементалей ÑражатьÑÑ Ð½Ð° Вашей Ñтороне." msgid "Damages castle walls." msgstr "ÐаноÑит урон Ñтенам замка." msgid "Earthquake" msgstr "ЗемлетрÑÑение" msgid "Causes all mines across the land to become visible." msgstr "Делает видимыми вÑе шахты, раÑположенные на карте." msgid "View Mines" msgstr "Показать шахты" msgid "Causes all resources across the land to become visible." msgstr "Делает видимыми вÑе реÑурÑÑ‹, раÑположенные на карте." msgid "View Resources" msgstr "Показать реÑурÑÑ‹" msgid "Causes all artifacts across the land to become visible." msgstr "Делает видимыми вÑе артефакты, раÑположенные на карте." msgid "View Artifacts" msgstr "Показать артефакты" msgid "Causes all towns and castles across the land to become visible." msgstr "Делает видимыми вÑе города и замки, раÑположенные на карте." msgid "View Towns" msgstr "Показать города" msgid "Causes all Heroes across the land to become visible." msgstr "Делает видимыми вÑех героев, раÑположенных на карте." msgid "View Heroes" msgstr "Показать героев" msgid "Causes the entire land to become visible." msgstr "Делает видимой вÑÑŽ карту." msgid "View All" msgstr "Показать вÑÑ‘" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "ПозволÑет получить подробную информацию о героÑÑ… противника." msgid "Summon Boat" msgstr "Призвать корабль" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Перемещает Ваш ближайший незанÑтый корабль в ближайшую точку побережьÑ. " "Корабль ÑчитаетÑÑ Ð’Ð°ÑˆÐ¸Ð¼, еÑли Ð’Ñ‹ его только что поÑтроили, или тот на " "котором Ð’Ñ‹ плавали поÑледним." msgid "Allows the caster to magically transport to a nearby location." msgstr "ПереноÑит Ð³ÐµÑ€Ð¾Ñ Ð² раÑположенную поблизоÑти точку на карте." msgid "Dimension Door" msgstr "Портал" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Возвращает Ð³ÐµÑ€Ð¾Ñ Ð² ближайший город или замок, еÑли там уже не находитÑÑ " "другой герой." msgid "Town Gate" msgstr "Врата в город" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "Возвращает Ð³ÐµÑ€Ð¾Ñ Ð² любой город или замок на выбор, еÑли там уже не находитÑÑ " "другой герой." msgid "Visions" msgstr "ВидениÑ" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "ПозволÑет видеть герою (не дальше 3-Ñ… шагов) количеÑтво ÑущеÑтв в " "нейтральном войÑке, а также их намерениÑ." msgid "Haunt" msgstr "ЗапуÑтение" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "ÐаводнÑет принадлежащую игроку шахту призраками, поÑле чего работа шахты " "прекращаетÑÑ. (Так не доÑтавайÑÑ Ð¶Ðµ ты никому!)" msgid "Set Earth Guardian" msgstr "Страж земли" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Призывает Земных Ñлементалей охранÑть Вашу шахту от врагов." msgid "Set Air Guardian" msgstr "Страж воздуха" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Призывает Воздушных Ñлементалей охранÑть Вашу шахту от врагов." msgid "Set Fire Guardian" msgstr "Страж огнÑ" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Призывает Огненных Ñлементалей охранÑть Вашу шахту от врагов." msgid "Set Water Guardian" msgstr "Страж воды" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Призывает Водных Ñлементалей охранÑть Вашу шахту от врагов." msgid "Random Spell" msgstr "Случайное заклинание" msgid "Randomly selected spell of any level." msgstr "Определённое Ñлучайным образом заклинание любого уровнÑ." msgid "Random 1st Level Spell" msgstr "Случайное заклинание 1-го уровнÑ" msgid "Randomly selected 1st level spell." msgstr "Определённое Ñлучайным образом заклинание 1-го уровнÑ." msgid "Random 2nd Level Spell" msgstr "Случайное заклинание 2-го уровнÑ" msgid "Randomly selected 2nd level spell." msgstr "Определённое Ñлучайным образом заклинание 2-го уровнÑ." msgid "Random 3rd Level Spell" msgstr "Случайное заклинание 3-го уровнÑ" msgid "Randomly selected 3rd level spell." msgstr "Определённое Ñлучайным образом заклинание 3-го уровнÑ." msgid "Random 4th Level Spell" msgstr "Случайное заклинание 4-го уровнÑ" msgid "Randomly selected 4th level spell." msgstr "Определённое Ñлучайным образом заклинание 4-го уровнÑ." msgid "Random 5th Level Spell" msgstr "Случайное заклинание 5-го уровнÑ" msgid "Randomly selected 5th level spell." msgstr "Определённое Ñлучайным образом заклинание 5-го уровнÑ." msgid "Petrification" msgstr "Окаменение" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Превращает поражённое ÑущеÑтво в камень. Окаменевшее ÑущеÑтво получает " "половину урона от прÑмой атаки." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "У Ð’Ð°Ñ Ð½ÐµÑ‚ Волшебной Книги, поÑтому Ð’Ñ‹ не можете применÑть заклинаниÑ." msgid "No spell to cast." msgstr "Ðет заклинаний Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "У Вашего Ð³ÐµÑ€Ð¾Ñ Ð¾ÑталоÑÑŒ %{sp} очков магии из %{max}." msgid "View Adventure Spells" msgstr "ПроÑмотр походных заклинаний" msgid "View Combat Spells" msgstr "ПроÑмотр боевых заклинаний" msgid "View previous page" msgstr "ÐŸÑ€ÐµÐ´Ñ‹Ð´ÑƒÑ‰Ð°Ñ Ñтраница" msgid "View next page" msgstr "Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтраница" msgid "Close Spellbook" msgstr "Закрыть книгу заклинаний" msgid "View %{spell}" msgstr "ПроÑмотреть %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Это заклинание наноÑит %{damage} урона." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Это заклинание призывает\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Это заклинание воÑÑтанавливает %{hp} здоровьÑ." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Это заклинание вызывает %{count} %{monster} Ð´Ð»Ñ Ð¾Ñ…Ñ€Ð°Ð½Ñ‹ шахты." msgid "The nearest town is %{town}." msgstr "Это заклинание перенеÑёт Ð³ÐµÑ€Ð¾Ñ Ð² %{town}" msgid "This town is occupied by your hero %{hero}." msgstr "Этот город занÑÑ‚ Вашим героем: %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Это заклинание позволÑет взÑть под контроль отрÑд,\n" "Ñуммарное здоровье которого не превышает\n" "%{hp} здоровьÑ." msgid "The ultimate artifact is really the %{name}." msgstr "Уникальный Ðртефакт - Ñто %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Уникальный Ðртефакт ÑпрÑтан на %{name}е." msgid "north-west" msgstr "Ñеверо-запад" msgid "north" msgstr "Ñевер" msgid "north-east" msgstr "Ñеверо-воÑток" msgid "west" msgstr "запад" msgid "center" msgstr "Ñередин" msgid "east" msgstr "воÑток" msgid "south-west" msgstr "юго-запад" msgid "south" msgstr "юг" msgid "south-east" msgstr "юго-воÑток" msgid "The truth is out there." msgstr "ИÑтина где-то Ñ€Ñдом." msgid "The dark side is stronger." msgstr "Ð¢Ñ‘Ð¼Ð½Ð°Ñ Ñторона Ñильнее." msgid "The end of the world is near." msgstr "Конец Ñвета близок." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "ОÑтанки лорда закопаны у оÑÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð°Ñ€ÐµÐ½Ñ‹." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Чёрный Дракон победит Титана в любой день недели." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "Он Ñказал ей: Бе бе бе... а потом она Ñказала: Бла, бла, бла..." msgid "An unknown force is being resurrected..." msgstr "ВозрождаетÑÑ Ð½ÐµÐ²ÐµÐ´Ð¾Ð¼Ð°Ñ Ñила..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Ðовую верÑию игры можно найти на Ñайте:\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Подарить %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Включить автобитву" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "закончить битву в авторежиме" #~ msgid "Please Remember" #~ msgstr "Запомните" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Ð’Ñ‹ вÑегда можете изменить Ñзык, разрешение Ñкрана или наÑтройки игры, " #~ "нажав на " #~ msgid "door" #~ msgstr "дверь" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " в левой чаÑти главного меню или Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ кнопки " #~ msgid " button from the " #~ msgstr ", раÑположенной в меню " #~ msgid "NEW GAME" #~ msgstr "ÐОВÐЯ ИГРÐ" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ ".\n" #~ "\n" #~ "Желаем Вам приÑтной игры!" #~ msgid "Warning!" #~ msgstr "Внимание!" #~ msgid "Dummy 1" #~ msgstr "Болванка 1" fheroes2-1.1.6+dfsg/files/lang/sk.po000066400000000000000000011715111476115357100171740ustar00rootroot00000000000000# Slovak translation of fheroes2 # Copyright (C) 2023 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2023-09-11 20:22+0200\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: sk\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 == 1 ) ? 0 : ( n >= 2 && n <= 4 ) ? " "1 : 2 );\n" "X-Generator: Poedit 3.3.2\n" msgid "" "NEW\n" "GAME" msgstr "" "NOVÃ\n" "HRA" msgid "" "SAVE\n" "GAME" msgstr "" "ULOŽIŤ\n" "HRU" msgid "" "LOAD\n" "GAME" msgstr "" "NA-\n" "HRAŤ\n" "HRU" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "" "OPUSŤ\n" "HRU" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "NOVÃ\n" "HRA" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "ULOŽIŤ\n" "HRU" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "NA-\n" "HRAŤ\n" "HRU" msgid "CANCEL" msgstr "ZRUÅ IŤ" msgid "OKAY" msgstr "OK" msgid "ACCEPT" msgstr "PRIJAŤ" msgid "DECLINE" msgstr "ODMIETNUŤ" msgid "LEARN" msgstr "UÄŒIŤ" msgid "TRADE" msgstr "VYMENIŤ" msgid "YES" msgstr "ÃNO" msgid "NO" msgstr "NIE" msgid "EXIT" msgstr "PREÄŒ" msgid "smallerButton|EXIT" msgstr "ODÃÄŽ" msgid "DISMISS" msgstr "PREPUSŤ" msgid "UPGRADE" msgstr "POVÃÅ " msgid "RESTART" msgstr "REÅ TART" msgid "HEROES" msgstr "" "HRDI-\n" "NOVIA" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "MESTÃ/\n" "HRADY" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "X-L" msgid "ALL" msgstr "CELÃ" msgid "SELECT" msgstr "ZVOĽ" msgid "" "STANDARD\n" "GAME" msgstr "" "BEŽNÃ\n" "HRA" msgid "" "BATTLE\n" "ONLY" msgstr "" "RÃCHLY\n" "BOJ" msgid "" "CAMPAIGN\n" "GAME" msgstr "KAMPAŇ" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "HRA\n" "VIAC\n" "HRÃÄŒOV" msgid "CONFIG" msgstr "NASTAV" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "PÔVODNÃ\n" "KAMPAŇ" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "KAMPAŇ\n" "EXPANZIE" msgid "HOT SEAT" msgstr "" "HORÚCE\n" "KRESLO" msgid "2 PLAYERS" msgstr "2 HRÃÄŒI" msgid "3 PLAYERS" msgstr "3 HRÃÄŒI" msgid "4 PLAYERS" msgstr "4 HRÃÄŒI" msgid "5 PLAYERS" msgstr "5 HRÃÄŒOV" msgid "6 PLAYERS" msgstr "6 HRÃÄŒOV" msgid "GIFT" msgstr "DARUJ" msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "OBTIAŽNOSŤ" msgid "VIEW INTRO" msgstr "ZOBRAZIŤ INTRO" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "" #, fuzzy msgid "START" msgstr "REÅ TART" msgid "TOWN" msgstr "" #, fuzzy msgid "CASTLE" msgstr "" "MESTÃ/\n" "HRADY" #, fuzzy msgid "RESTRICT" msgstr "REÅ TART" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "P\n" "R\n" "E\n" "P\n" "U\n" "S\n" "Ť" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "P\n" "R\n" "E\n" "ÄŒ" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "K\n" "A\n" "M\n" "P\n" "A\n" "Ň" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "Å \n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Bojovník" msgid "Builder" msgstr "Staviteľ" msgid "Explorer" msgstr "Prieskumník" msgid "None" msgstr "Žiadny" msgid "" "A few\n" "%{monster}" msgstr "" "%{monster}\n" "(málo)" msgid "" "Several\n" "%{monster}" msgstr "" "%{monster}\n" "(niekoľko)" msgid "" "A pack of\n" "%{monster}" msgstr "" "%{monster}\n" "(skupina)" msgid "" "Lots of\n" "%{monster}" msgstr "" "%{monster}\n" "(veľa)" msgid "" "A horde of\n" "%{monster}" msgstr "" "%{monster}\n" "(horda)" msgid "" "A throng of\n" "%{monster}" msgstr "" "%{monster}\n" "(zástup)" msgid "" "A swarm of\n" "%{monster}" msgstr "" "%{monster}\n" "(dav)" msgid "" "Zounds...\n" "%{monster}" msgstr "" "%{monster}\n" "(mraÄná)" msgid "" "A legion of\n" "%{monster}" msgstr "" "%{monster}\n" "(légia)" msgid "army|Few" msgstr "Málo" msgid "army|Several" msgstr "Niekoľko" msgid "army|Pack" msgstr "Skupina" msgid "army|Lots" msgstr "Veľa" msgid "army|Horde" msgstr "Horda" msgid "army|Throng" msgstr "Zástup" msgid "army|Swarm" msgstr "Dav" msgid "army|Zounds" msgstr "MraÄná" msgid "army|Legion" msgstr "Légia" msgid "All %{race} troops +1" msgstr "VÅ¡etky jednotky typu %{race} +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Neutrálna" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Jednotky %{count} zoskupení -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "NemÅ•tvi v skupine -1" #, fuzzy msgid "" "Default\n" "troop" msgstr "predvolená ÄinnosÅ¥" msgid "View %{name}" msgstr "Zobraz: %{name}" msgid "Move the %{name} " msgstr "Premiestni %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Pohyb alebo pravý klik prerozdelí: %{name}" msgid "Combine %{name} armies" msgstr "Skombinuj armádu: %{name}" msgid "Exchange %{name2} with %{name}" msgstr "Vymeň: %{name2} za: %{name}" msgid "Select %{name}" msgstr "Vyber: %{name}" msgid "Cannot move last troop" msgstr "Nemožné presunúť" msgid "Move the %{name}" msgstr "Premiestni: %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Streľ do: %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} zniÄil polovicu nepriateľov!" msgstr[1] "%{name} zniÄili polovicu nepriateľov!" msgstr[2] "%{name} zniÄili polovicu nepriateľov!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} vypol automatizovaný boj" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} zapol automatizovaný boj" msgid "Spell failed!" msgstr "Kúzlo zlyhalo!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Tento boj je ovplyvnený artefaktom Guľa negácie, ktorá znemožní kúzliÅ¥." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "V tomto kole už bolo použité kúzlo." msgid "That spell will have no effect!" msgstr "Kúzlo nikoho neovplyvní!" msgid "You may only summon one type of elemental per combat." msgstr "SmieÅ¡ vyvolaÅ¥ len jeden typ Elementála za boj." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "Vedľa hrdinu nie je voľné miesto pre vyvolanie Elementála." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Priekopa znižuje obranu každého o -%{count} a spomaľuje pohyb na polovicu." msgid "Speed: %{speed}" msgstr "RýchlosÅ¥: %{speed}" msgid "Speed" msgstr "RýchlosÅ¥" msgid "Off" msgstr "Vypnuté" msgid "On" msgstr "Zapnuté" msgid "Turn Order" msgstr "Poradie" msgid "Auto Spell Casting" msgstr "Kúzla poÄas auto boja" msgid "Grid" msgstr "Mriežka" msgid "Shadow Movement" msgstr "Tieň pohybu" msgid "Shadow Cursor" msgstr "Tieň kurzora" msgid "Audio" msgstr "Zvuk" msgid "Settings" msgstr "Nastavenie" msgid "Configure" msgstr "Nastav" msgid "Hot Keys" msgstr "Skratky" msgid "Damage Info" msgstr "Info Å¡kôd" msgid "Set the speed of combat actions and animations." msgstr "Nastav rýchlosÅ¥ bojových akcií a animácií." msgid "Toggle to display the turn order during the battle." msgstr "Prepni zobrazenie poradia armády poÄas boja." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Zmeň možnosÅ¥ kúzlenia poÄas automatizovaného boja. (ViÄ: Toto nemá vplyv na " "kúzlenie hráÄov ovládaných poÄítaÄom ani na rýchly boj.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Zmeň zobrazenie mriežky. Å esÅ¥hranná mriežka je vždy základom pohybu, aj keÄ " "je vypnutá. Toto nastavenie má vplyv len na viditeľnosÅ¥ mriežky." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Zapne alebo vypne tiene ukazujúce kde sa bojovníci smú pohnúť alebo útoÄiÅ¥." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "Zapne alebo vypne tieň zobrazujúci aktuálnu pozíciu kurzora v mriežke." msgid "Change the audio settings of the game." msgstr "Zmeň nastavenie zvuku hry." msgid "Check and configure all the hot keys present in the game." msgstr "Prezri a nastav vÅ¡etky klávesové skratky hry." msgid "Toggle to display damage information during the battle." msgstr "Zmeň zobrazenie informácie o poÅ¡kodení poÄas boja." msgid "Exit this menu." msgstr "OdÃ­Ä z menu." msgid "Okay" msgstr "Ok" msgid "The enemy has surrendered!" msgstr "Nepriateľ sa vzdal!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Nepriateľ utiekol!" msgid "A glorious victory!" msgstr "Slávne víťazstvo!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "Za odvahu v boji, %{name} získava %{exp} skúseností." msgid "The cowardly %{name} flees from battle." msgstr "%{name} zbabelo uteká z boja." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} sa vzdáva nepriateľovi a hanobne odchádza." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "Tvoje vojská sú porazené a %{name} Å¥a opúšťa." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Tvoje vojská sú porazené." msgid "Battlefield Casualties" msgstr "Obete boja" msgid "Attacker" msgstr "ÚtoÄník" msgid "Defender" msgstr "Obranca" #, fuzzy msgid "Click to leave the battle results." msgstr "Klikni pre výber zvoleného rozlíšenia." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Kliknutím sa vrátiÅ¡ do hlavnej ponuky." msgid "Restart" msgstr "ReÅ¡tart" msgid "You have captured an enemy artifact!" msgstr "Získal si nepriateľov artefakt!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Akonáhle siahaÅ¡ po %{name}, náhle mizne." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Akonáhle nepriateľ siaha po %{name}, náhle mizne." msgid "Necromancy!" msgstr "Nekromancia!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Praktizovaním temného umenia nekromancie dokážeÅ¡ vzkriesiÅ¥ %{count} z " "mÅ•tvych nepriateľa aby ti slúžili ako %{monster}." msgid "%{name} the %{race}" msgstr "%{race} %{name}" msgid "Captain of %{name}" msgstr "Kapitán: %{name}" msgid "Attack" msgstr "Útok" msgid "Defense" msgstr "Obrana" msgid "Spell Power" msgstr "Sila kúziel" msgid "Knowledge" msgstr "Vedomosti" msgid "Morale" msgstr "Morálka" msgid "Luck" msgstr "Šťastie" msgid "Spell Points" msgstr "Body kúziel" msgid "Hero's Options" msgstr "Ukáž hrdinu" msgid "Cast Spell" msgstr "Kúzli" msgid "Retreat" msgstr "UteÄ" msgid "Surrender" msgstr "Vzdaj sa" msgid "Cancel" msgstr "ZruÅ¡iÅ¥" msgid "Hero Screen" msgstr "Okno hrdinu" msgid "Captain's Options" msgstr "Možnosti kapitána" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "ÄŒarovaÅ¥ magické kúzlo. SmieÅ¡ zoslaÅ¥ len jedno kúzlo poÄas kola. Po skonÄení " "pohybu vÅ¡etkých bojovníkov je kolo obnovené." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Ustúp s hrdinom, Äo opustí tvoje jednotky. Hrdina bude k dispozícii na " "najatie, ale bude maÅ¥ len základné jednotky." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Vzdanie sa stojí zlato. AvÅ¡ak pokiaľ zaplatíš, hrdina a zostávajúce jednotky " "budú k dispozícii k nájmu." msgid "Open Hero Screen to view full information about the hero." msgstr "Otvor okno hrdinu pre zobrazenie informácií o hrdinovi." msgid "Return to the battle." msgstr "Späť do boja." msgid "Not enough gold (%{gold})" msgstr "Málo zlata (%{gold})" msgid "%{name} states:" msgstr "%{name} hovorí:" msgid "Captain of %{name} states:" msgstr "Kapitán hradu %{name} hovorí:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Prijmem tvoju kapituláciu a poskytnem tebe a tvojim jednotkám bezpeÄný " "odchod za %{price} zlata.\"" msgid "View %{monster} info" msgstr "Zobraz info: %{monster}" msgid "Fly %{monster} here" msgstr "LeÅ¥ sem s: %{monster}" msgid "Move %{monster} here" msgstr "Premiestni: %{monster}" msgid "Shoot %{monster}" msgstr "Streľ do: %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(ostáva posledná strela)" msgstr[1] "(ostávajú %{count} strely)" msgstr[2] "(ostáva %{count} striel)" msgid "Attack %{monster}" msgstr "Útok na: %{monster}" msgid "Turn %{turn}" msgstr "%{turn}. kolo" msgid "Teleport here" msgstr "Teleport sem" msgid "Invalid teleport destination" msgstr "Neplatný cieľ teleportu" msgid "Cast %{spell} on %{monster}" msgstr "Kúzli %{spell} na: %{monster}" msgid "Cast %{spell}" msgstr "Kúzli %{spell}" msgid "Select spell target" msgstr "UrÄi cieľ kúzla" msgid "View Ballista info" msgstr "Zobraz info o balistovi" msgid "Ballista" msgstr "Balista" #, fuzzy msgid "Automatic combat modes" msgstr "Auto boj" #, fuzzy msgid "Automatic Combat Modes" msgstr "Auto boj" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Nastav systémové možnosti" msgid "Allows you to customize the combat screen." msgstr "Umožní ti nastaviÅ¥ obrazovku boja." msgid "System Options" msgstr "Systémové nastavenia" msgid "Skip this unit" msgstr "PreskoÄ túto jednotku" msgid "Skip" msgstr "PreskoÄ" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "PreskoÄ bojovníka. Terajší bojovník ukonÄí svoje kolo a Äalej nebude k " "dispozícii do ÄalÅ¡ieho kola." msgid "View Captain's options" msgstr "Zobraz možnosti kapitána" msgid "View Hero's options" msgstr "Zobraz možnosti hrdinu" msgid "View opposing Captain" msgstr "Zobraz kapitána nepriateľa" msgid "View opposing Hero" msgstr "Zobraz hrdinu nepriateľa" msgid "Hide logs" msgstr "Skry zápis" msgid "Show logs" msgstr "Ukáž zápis" msgid "Message Bar" msgstr "Panel správ" msgid "Shows the results of individual monster's actions." msgstr "Ukáže výsledky Äinností jednotlivých bojovníkov." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "UrÄite chceÅ¡ povoliÅ¥ automatický boj?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "UrÄite chceÅ¡ dokonÄiÅ¥ boj v automatizovanom móde?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Umožní poÄítaÄu vybojovaÅ¥ boj za teba." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Auto boj" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Auto boj" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} vynecháva kolo." msgstr[1] "%{name} vynecháva kolo." msgstr[2] "%{name} vynecháva kolo." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} pôsobí %{damage} Å¡kôd." msgstr[1] "%{attacker} pôsobia %{damage} Å¡kôd." msgstr[2] "%{attacker} pôsobia %{damage} Å¡kôd." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "Jeden bojovník zahynul." msgstr[1] "%{count} bojovníci zahynuli." msgstr[2] "%{count} bojovníkov zahynulo." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} hynie." msgstr[1] "%{count} %{defender} zahynuli." msgstr[2] "%{defender} zahynuli (%{count})." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "Jedna duÅ¡a je zaÄlenená." msgstr[1] "%{count} duÅ¡e sú zaÄlenené." msgstr[2] "%{count} duší je zaÄlenených." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "Oživenie: 1 %{unit}." msgstr[1] "Oživenie: %{count} %{unit}." msgstr[2] "Oživenie: %{unit} (%{count} )." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Presun - %{monster}: od [%{src}] na [%{dst}]." #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "Jednotka %{name} odoláva kúzlu!" msgstr[1] "Jednotka %{name} odoláva kúzlu!" msgstr[2] "Jednotka %{name} odoláva kúzlu!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} kúzli %{spell} na: %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} kúzli %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "Kúzlo %{spell} pôsobí %{damage} poÅ¡kodenia nemÅ•tvej jednotke." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "Kúzlo %{spell} pôsobí %{damage} poÅ¡kodenia vÅ¡etkým nemÅ•tvym." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "Kúzlo %{spell} pôsobí %{damage} poÅ¡kodenia, %{count} jednotiek hynie." msgid "The %{spell} does %{damage} damage." msgstr "Kúzlo %{spell} pôsobí %{damage} poÅ¡kodenia." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "Kúzlo %{spell} pôsobí %{damage} poÅ¡kodenia živej jednotke." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "Kúzlo %{spell} pôsobí %{damage} poÅ¡kodenia vÅ¡etkým živým." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Útok od: %{attacker} oslepuje: %{target}!" msgstr[1] "Útok od: %{attacker} oslepuje: %{target}!" msgstr[2] "Útok od: %{attacker} oslepuje: %{target}!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "Pohľad od: %{attacker} mení: %{target} na kameň!" msgstr[1] "Pohľad od: %{attacker} mení: %{target} na kameň!" msgstr[2] "Pohľad od: %{attacker} mení: %{target} na kameň!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "Kliatba: %{attacker} padá na: %{target}!" msgstr[1] "Kliatba: %{attacker} padá na: %{target}!" msgstr[2] "Kliatba: %{attacker} padá na: %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "Útok od: %{attacker} paralyzuje: %{target}!" msgstr[1] "Útok od: %{attacker} paralyzuje: %{target}!" msgstr[2] "Útok od: %{attacker} paralyzuje: %{target}!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "Útok od: %{attacker} ruší vÅ¡etky dobré kúzla, ktoré má: %{target}!" msgstr[1] "Útok od: %{attacker} ruší vÅ¡etky dobré kúzla, ktoré má: %{target}!" msgstr[2] "Útok od: %{attacker} ruší vÅ¡etky dobré kúzla, ktoré má: %{target}!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} kúzli/a %{spell} na: %{target}!" msgstr[1] "%{attacker} kúzli/a %{spell} na: %{target}!" msgstr[2] "%{attacker} kúzli/a %{spell} na: %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Smola padá na: %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "Šťastie je na strane: %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Vysoká morálka umožňuje Å¥ahaÅ¥ znovu pre: %{monster}." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Nízka morálka spôsobuje, že jednotka %{monster} mrzne v panike." msgid "%{tower} does %{damage} damage." msgstr "%{tower} pôsobí %{damage} poÅ¡kodenia." msgid "The mirror image is created." msgstr "Zrkadlový obraz je vytvorený." msgid "The mirror image is destroyed!" msgstr "Zrkadlový obraz je zniÄený!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "UrÄite chceÅ¡ preruÅ¡iÅ¥ automatizovaný súboj?" msgid "Error" msgstr "Chyba" msgid "No spells to cast." msgstr "Žiadne kúzla na Äarovanie." msgid "Are you sure you want to retreat?" msgstr "UrÄite chceÅ¡ ustúpiÅ¥?" msgid "Retreat disabled" msgstr "Ústup znemožnený" msgid "Surrender disabled" msgstr "Vzdanie sa znemožnené" msgid "Damage: %{max}" msgstr "PoÅ¡kodenie: %{max}" msgid "Damage: %{min} - %{max}" msgstr "PoÅ¡kodenie: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Zahynie: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Zahynie: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "Pozorovaním orlím zrakom, %{name} sa dokáže nauÄiÅ¥ kúzlo %{spell}." msgid "Human" msgstr "ÄŒlovek" msgid "AI" msgstr "UI" #, fuzzy msgid "Start" msgstr "ReÅ¡tart" #, fuzzy msgid "Start the battle." msgstr "Späť do boja." msgid "Exit" msgstr "PreÄ" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Prosím zvoľ ÄalÅ¡ieho hrdinu." #, fuzzy msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{name1} a %{name2} sa stretávajú" msgid "Monsters" msgstr "Bojovníci" msgid "N/A" msgstr "nie je" msgid "Left Turret" msgstr "Ľavá veža" msgid "Right Turret" msgstr "Pravá veža" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} strieľa so silou %{count} lukostrelcov" msgid "each with a +%{attack} bonus to their attack skill." msgstr "s bonusom +%{attack} k ich zruÄnosti útoku." msgid "The %{name} is destroyed." msgstr "%{name} je zniÄený/á." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} vstáva z mÅ•tvych!" msgstr[1] "%{count} %{name} vstávajú z mÅ•tvych!" msgstr[2] "%{count} %{name} vstáva z mÅ•tvych!" msgid "Dwarven Alliance" msgstr "Aliancia trpaslíkov" msgid "Sorceress Guild" msgstr "Cech Äarodejníc" msgid "Necromancer Guild" msgstr "Cech nekromantov" msgid "Ogre Alliance" msgstr "Cech zlobrov" msgid "Dwarfbane" msgstr "TrpasliÄí zmar" msgid "Dragon Alliance" msgstr "DraÄia aliancia" msgid "Elven Alliance" msgstr "Aliancia elfov" msgid "Kraeger defeated" msgstr "Kraeger porazený" msgid "Wayward Son" msgstr "Spurný syn" msgid "Uncle Ivan" msgstr "Strýko Ivan" msgid "Annexation" msgstr "Anexia" msgid "Force of Arms" msgstr "Sila zbraní" msgid "Save the Dwarves" msgstr "Zachráň trpaslíkov" msgid "Carator Mines" msgstr "Karátorské bane" msgid "Turning Point" msgstr "Zvrat" msgid "scenarioName|Defender" msgstr "Obranca" msgid "Corlagon's Defense" msgstr "Corlagonova obrana" msgid "The Crown" msgstr "Koruna" msgid "The Gauntlet" msgstr "Výzva" msgid "Betrayal" msgstr "Zrada" msgid "Final Justice" msgstr "KoneÄná spravodlivosÅ¥" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland potrebuje, aby si porazil pánov v blízkosti jeho hradu a tým zaÄal " "povstaleckú vojnu proti svojmu bratovi. Nie sú navzájom spojencami, takže " "väÄÅ¡inu Äasu strávia bojom medzi sebou. Víťazstvo je tvoje, keÄ porazíš " "vÅ¡etky ich hrady a hrdinov." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Miestni lordi odmietajú prisahaÅ¥ vernosÅ¥ Rolandovi a musia byÅ¥ pokorení. Sú " "bohatí a mocní, takže sa priprav na tvrdý boj. Pre víťazstvo ovládni vÅ¡etky " "nepriateľské hrady." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Tvojou úlohou je ubrániÅ¥ trpaslíkov proti Archibaldovým silám. ObsaÄ vÅ¡etky " "nepriateľské mestá a hrady pre výhru, no uisti sa, že nestratíš vÅ¡etky " "trpasliÄie mestá naraz, inak nepriateľ vyhrá." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "V priamom boji o zdroje a poklady budeÅ¡ ÄeliÅ¥ Å¡tyrom nepriateľom v " "spojenectve. Pre víťazstvo ovládni vÅ¡etky nepriateľské hrady." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Tvoji nepriatelia sú proti tebe v spojení a zaÄínajú blízko, takže sa " "priprav vyraziÅ¥ do boja. Ak chceÅ¡ vyhraÅ¥, budeÅ¡ musieÅ¥ vlastniÅ¥ vÅ¡etky Å¡tyri " "hrady v tomto malom údolí." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Cech Äarodejníc z Norastonu požiadal Rolanda o pomoc proti útoku od " "Archibaldových spojencov. ObsaÄ vÅ¡etky nepriateľské hrady pre výhru a " "nestraÅ¥ Noraston, inak prehráš boj. (Tip: Na ostrove v oceáne je " "nepriateľský hrad.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Zhromaždi Äo najväÄÅ¡iu armádu a doby nepriateľský hrad do 8 týždňov. Proti " "tebe stojí iba jeden nepriateľ, ale musíš prejsÅ¥ dlhú cestu kým dorazíš do " "nepriateľského hradu. VÅ¡etky jednotky, ktoré máš vo svojej armáde na konci " "tohto scenára, budú s tebou v závereÄnom boji." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Nájdi Korunu skôr, ako ju nájdu Archibaldovi hrdinovia. Roland bude " "potrebovaÅ¥ Korunu na posledný boj proti Archibaldovi." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Pred tebou a víťazstvom stoja traja nepriatelia v spojenectve, vrátane lorda " "Corlagona. Roland je v hrade na severozápade a prehráš, ak padne do rúk " "nepriateľa. Pamätaj, že zajatie lorda Corlagona zabezpeÄí, že v koneÄnom " "scenári nebude bojovaÅ¥ proti tebe." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Toto je posledný boj. Ty aj tvoj nepriateľ ste po zuby ozbrojení a vÅ¡etci sú " "proti tebe v spojenectve. Zajmi Archibalda a ukonÄi vojnu!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Po zmene strany máš tri hrady proti jednému nepriateľskému. Táto bitka bude " "tou najľahÅ¡ou, ktorej budeÅ¡ do konca vojny ÄeliÅ¥... zradca." msgid "Barbarian Wars" msgstr "Barbarské vojny" msgid "First Blood" msgstr "Prvá krv" msgid "Necromancers" msgstr "Nekromanti" msgid "Slay the Dwarves" msgstr "Pobi trpaslíkov" msgid "Country Lords" msgstr "Vládcovia krajov" msgid "Dragon Master" msgstr "DraÄí majster" msgid "Rebellion" msgstr "Vzbura" msgid "Apocalypse" msgstr "Apokalypsa" msgid "Greater Glory" msgstr "VäÄÅ¡ia sláva" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Kráľ Archibald od teba vyžaduje víťazstvo nad tromi nepriateľmi v tejto " "oblasti. Nie sú medzi sebou spojencami, takže väÄÅ¡inu energie vynaložia na " "boj medzi sebou. Vyhráš, keÄ budeÅ¡ vlastniÅ¥ vÅ¡etky nepriateľské hrady a " "nezostane už žiadny hrdina, s ktorým by si mohol bojovaÅ¥." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Musíš zjednotiÅ¥ barbarské kmene na severe ich dobytím. Podobne ako v " "predchádzajúcej misii, nepriateľ nie je proti tebe v spojenectve, ale má k " "dispozícii viac zdrojov. Vyhráš, keÄ budeÅ¡ vlastniÅ¥ vÅ¡etky nepriateľské " "hrady a nezostane už žiadny hrdina, ktorý by mohol bojovaÅ¥." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Mágovia dobrodinci obsadili hrad Nekromantov. Musíš ho znovu dobyÅ¥, na " "dosiahnutie víťazstva. Pamätaj, že hoci zaÄínaÅ¡ so silnou armádou, nemáš " "žiadny hrad a musíš nejaký dobyÅ¥ do 7 dní, inak túto bitku prehráš. (Tip: " "Najbližší hrad je na juhovýchode.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Treba dobyÅ¥ trpaslíkov, kým budú môcÅ¥ zasiahnuÅ¥ do plánov kráľa Archibalda. " "Rolandove sily majú na zaÄiatok viac ako jedného hrdinu a veľa miest, takže " "buÄ v strehu a oÄakávaj útok z viacerých strán. Musíš dobyÅ¥ vÅ¡etky " "nepriateľské mestá a hrady pre zisk víťazstva." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Musíte potlaÄiÅ¥ roľnícku vzburu vedenú Rolandovými silami. VÅ¡etci sú proti " "tebe v spojení, ale máš na pomoc skúseného hrdinu, lorda Corlagona. Pre " "víťazstvo ovládni vÅ¡etky nepriateľské hrady." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "V tejto misii sú proti tebe v spojení dvaja nepriatelia. Obaja sú dobre " "vyzbrojení a snažia sa Å¥a vyhnaÅ¥ zo svojho ostrova. Vyhni sa im a doby " "DraÄie mesto, aby bola výhra dosiahnutá." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Máš splniÅ¥ rozkaz dobyÅ¥ vládcov krajiny, ktorí prisahali slúžiÅ¥ Rolandovi. " "VÅ¡etky nepriateľské hrady sú zjednotené proti tebe. KeÄže zaÄínaÅ¡ bez hradu, " "musíš sa poponáhľaÅ¥ s dobytím jedného z nich do konca týždňa. ObsaÄ vÅ¡etky " "nepriateľské hrady pre víťazstvo." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Nájdi Korunu skôr, ako ju nájdu Rolandovi hrdinovia. Archibald bude " "potrebovaÅ¥ Korunu na posledný boj proti Rolandovi." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Toto je posledný boj. Ty aj tvoj nepriateľ ste po zuby ozbrojení a vÅ¡etci sú " "proti tebe v spojenectve. Zajmi Rolanda, aby vojna bola vyhratá, a uisti sa, " "že nestratíš Archibalda v boji!" msgid "Arrow's Flight" msgstr "Let šípu" msgid "Island of Chaos" msgstr "Ostrov chaosu" msgid "The Abyss" msgstr "PriepasÅ¥" msgid "Uprising" msgstr "Povstanie" msgid "Aurora Borealis" msgstr "Polárna žiara" msgid "Betrayal's End" msgstr "Koniec zrady" msgid "Corruption's Heart" msgstr "Srdce korupcie" msgid "The Giant's Pass" msgstr "Obrov priesmyk" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Podmaň si neposluÅ¡ných miestnych lordov, aby bolo Impériu poskytnuté zázemie " "na pôsobenie v tomto regióne." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Odstráň protivníkov v tejto oblasti. Potom bude prvý kus artefaktu tvoj." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "ÄŒarodejnice na severovýchode sa búria! Pre dobro Impéria musíš potlaÄiÅ¥ ich " "slabé povstanie na tvojej ceste do hôr." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "S prípravou na tvoj príchod Kraeger zariadil, aby nekromanti prekazili tvoju " "výpravu. Musíš dobyÅ¥ hrad Scabsdale pred prvým dňom tretieho týždňa, inak " "budú na teba nekromanti príliÅ¡ silní." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Barbarský despota v tejto oblasti zatiaľ neuvažuje o tvojej prítomnosti. " "Rýchlo vybuduj svoje sily skôr, ako Å¥a objavia a zaútoÄia! ZabezpeÄ región " "podmanením vÅ¡etkých nepriateľských síl." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Impérium je v tomto regióne slabé. NebudeÅ¡ maÅ¥ schopnosÅ¥ úplne si podmaniÅ¥ " "vÅ¡etky sily v tejto oblasti, takže si vezmi, Äo môžeÅ¡, kým zaútoÄí odveta. " "Pamätaj, že tvojim skutoÄným cieľom je získaÅ¥ Anduranovu prilbu." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Pre dobro Impéria zlikviduj Kraegera." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "KoneÄne máš príležitosÅ¥ a možnosti zbaviÅ¥ Impérium nekromantovho zla. Úplne " "ho vyhub a budeÅ¡ navždy ospevovaný ako hrdina." msgid "Border Towns" msgstr "PohraniÄné mestá" msgid "Conquer and Unify" msgstr "DobyÅ¥ a zjednotiÅ¥" msgid "Crazy Uncle Ivan" msgstr "Bláznivý strýko Ivan" msgid "The Wayward Son" msgstr "Zblúdilý syn" msgid "Ivory Gates" msgstr "Slonovinové Brány" msgid "The Elven Lands" msgstr "Krajiny elfov" msgid "The Epic Battle" msgstr "Epický boj" msgid "The Southern War" msgstr "Južná vojna" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Doby a zjednoÅ¥ vÅ¡etky nepriateľské kmene. NestraÅ¥ hrdinu Jarkonasa, praotca " "vÅ¡etkých potomkov." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Tvoj súper, kráľovstvo Harondale, útoÄí na slabé mestá na tvojej hranici! " "Zotav sa z ich prvého úderu a rozdrv ich úplne!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Nájdi svojho neposluÅ¡ného syna Jozefa, o ktorom sa hovorí, že žije v pustých " "krajinách. Urob tak pred prvým dňom tretieho mesiaca, inak to tvojej rodine " "nepomôže." #, fuzzy msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Zachráň svojho bláznivého strýka Ivana. Nájdi ho pred prvým dňom Å¡tvrtého " "mesiaca, inak to tvojmu kráľovstvu nepomôže." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "ZniÄ barbarov, ktorí útoÄia na južnú hranicu tvojho kráľovstva! Obnov svoje " "padlé mestá a potom prepadni kráľovstvo džungle. Nenechaj žiadneho " "nepriateľa nažive." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Získaj späť hrad Ivory Gates, ktorý padol v dôsledku zrady." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Získaj si priazeň elfov. Stromy rúbaÅ¥ nedovolia, preto ti poÅ¡lú drevo každé " "2 týždne. Svoju misiu musíš dokonÄiÅ¥ pred prvým dňom siedmeho mesiaca, inak " "kráľovstvo urÄite padne." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Toto je posledný boj proti tvojmu súperiacemu kráľovstvu Harondale. " "ZneÅ¡kodni vÅ¡etkých a nestraÅ¥ hrdinu Jarkonasa VI." msgid "Fount of Wizardry" msgstr "Prameň Äarodejníctva" msgid "Power's End" msgstr "Koniec moci" msgid "The Eternal Scrolls" msgstr "VeÄné zvitky" msgid "The Shrouded Isles" msgstr "Zahalené ostrovy" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Tvojou úlohou je poraziÅ¥ bojujúcich mágov na Äarovných Zahalených ostrovoch. " "Splnenie tejto úlohy ti dá Å¡ancu bojovaÅ¥ proti tvojim súperom." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Poloha veľkej knižnice bola odhalená! Musíš sa k nej dostaÅ¥ a získaÅ¥ mesto " "Chronos, v ktorom leží." #, fuzzy msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Nájdi Orb negácie, ktorý je údajne zakopaný v tejto krajine. Na kamenných " "obeliskoch sú napísané stopy, ktoré Å¥a dovedú k tvojej cene. Nájdi orb pred " "prvým dňom Å¡iesteho mesiaca, inak sa tvoji súperi už urÄite dostali k nemu " "pred tebou." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Musíš prevziaÅ¥ kontrolu nad hradom mágie, kde leží prameň Äarodejníctva. " "Urob tak a tvoje víťazstvo bude mimoriadne." msgid "Blood is Thicker" msgstr "Krv je hustejÅ¡ia" msgid "King and Country" msgstr "Kráľ a krajina" msgid "Pirate Isles" msgstr "Pirátske ostrovy" msgid "Stranded" msgstr "Uviaznutý" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "ObsaÄ mesto na ostrove pri juhovýchodnom pobreží za úÄelom postaviÅ¥ loÄ a " "doplaviÅ¥ sa späť na pevninu. NestraÅ¥ hrdinu Gallavanta." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Nájdi a poraz Martine, pirátsku vodkyňu, ktorá sídli v Zátoke pirátov. " "NestraÅ¥ Gallavanta lebo tvoje pátranie sa skonÄí." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Zlikviduj vÅ¡etky ostatné sily, ktoré sú proti vláde lorda Alberona. " "Gallavant nesmie padnúť." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Zvrhni zakorenenú monarchiu lorda Alberona a získaj vÅ¡etku zem vo svojom " "mene. Gallavant nesmie padnúť." msgid " bane" msgstr " zmar" msgid " alliance" msgstr " aliancia" msgid "Carry-over forces" msgstr "Prenosné jednotky" msgid " bonus" msgstr " bonus" msgid " defeated" msgstr " porazený" msgid " will always run away from your army." msgstr " vždy uteÄú pred tvojou armádou." msgid " will be willing to join your army." msgstr " sa ochotne pridajú k tvojej armáde." #, fuzzy msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "Artefakt \"%{artifact}\" sa prenesie cez scenár." #, fuzzy msgid "The army will be carried over in the campaign." msgstr "Armáda sa prenesie cez scenár." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Kráľovstvo bude každý deň maÅ¥ zvýšené zásoby: +%{count} %{resource}." #, fuzzy msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "Kúzlo \"%{spell}\" sa prenesie cez scenár." #, fuzzy msgid "%{hero} can be hired during scenarios." msgstr "%{hero} bude k dispozícii v tomto scenári." #, fuzzy msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "%{hero} bol porazený a neobjaví sa v nasledujúcich scenároch." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Trpaslíci spoznávajú svojich spojencov a radi sa pridajú k tvojim silám." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Zlobri Å¥a poznajú ako TrpasliÄí zmar a pristupujú aby sa k tebe pridali." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "VrÄiaci draci súhlasia s pridaním sa k tvojim jednotkám, ich 'Spojencom'." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "KeÄ sa blížiÅ¡ k skupine elfov, ich vodca ich vÅ¡etkých zvolá do pozoru. " "ZakriÄí na nich: \"Kto z vás je dosÅ¥ odvážny, aby sa pridal k tomuto nášmu " "nebojácnemu spojencovi?\" Skupina prepuká v jasot, priÄom sa rozbehne, aby " "sa pridala do tvojich radov." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Trpaslíci Å¥a zdravia: \"Každý Rolandov priateľ je náš priateľ. SmieÅ¡ prejsÅ¥." "\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Zlobri na teba uznanlivo zavrÄia: \"Archibaldovi spojenci môžu prejsÅ¥.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Draci Å¥a uvidia a ozvú sa. \"NaÅ¡e spojenectvo s Archibaldom nás núti pridaÅ¥ " "sa k vám. Nanešťastie nemáte miesto. Å koda!\" Rýchlo sa rozptýlia." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Elfovia sa postavia do pozoru, keÄ sa blížiÅ¡. Ich vodca na teba zavolá a " "povie: \"Nebudeme ti brániÅ¥ v postupe, spojenec! PokraÄuj a nech je " "víťazstvo tvoje.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"TrpasliÄí zmar! Utekajte o život!\"" msgid "campaignBonus|Animate Dead" msgstr "Animácia mÅ•tvych" msgid "campaignBonus|Chain Lightning" msgstr "ReÅ¥azový blesk" msgid "campaignBonus|Fireblast" msgstr "Výbuch ohňa" msgid "campaignBonus|Mass Curse" msgstr "Hromadná kliatba" msgid "campaignBonus|Mass Haste" msgstr "Hromadný zhon" msgid "campaignBonus|Mirror Image" msgstr "Zrkadlový obraz" msgid "campaignBonus|Resurrect" msgstr "Vzkriesenie" msgid "campaignBonus|Steelskin" msgstr "Oceľová koža" msgid "campaignBonus|Summon Earth" msgstr "Vyvolaj zem" msgid "campaignBonus|View Heroes" msgstr "Zobraz hrdinov" msgid "campaignBonus|Ballista" msgstr "Balista" msgid "campaignBonus|Black Pearl" msgstr "ÄŒierna perla" msgid "campaignBonus|Caster's Bracelet" msgstr "ÄŒarodejov náramok" msgid "campaignBonus|Defender Helm" msgstr "Helma obrancu" msgid "campaignBonus|Breastplate" msgstr "Náprsné brnenie" msgid "campaignBonus|Dragon Sword" msgstr "DraÄí meÄ" msgid "campaignBonus|Fizbin Medal" msgstr "Fizbinova medaila" msgid "campaignBonus|Foremost Scroll" msgstr "Najprednejší zvitok" msgid "campaignBonus|Gauntlets" msgstr "Rukavice" msgid "campaignBonus|Hideous Mask" msgstr "Hnusná maska" msgid "campaignBonus|Mage's Ring" msgstr "Prsteň mága" msgid "campaignBonus|Major Scroll" msgstr "Hlavný zvitok" msgid "campaignBonus|Medal of Honor" msgstr "Medaila cti" msgid "campaignBonus|Medal of Valor" msgstr "Medaila za statoÄnosÅ¥" msgid "campaignBonus|Minor Scroll" msgstr "Menší zvitok" msgid "campaignBonus|Nomad Boots" msgstr "Nomádske Äižmy" msgid "campaignBonus|Power Axe" msgstr "Sekera moci" msgid "campaignBonus|Spiked Shield" msgstr "Ostnatý Å¡tít" msgid "campaignBonus|Stealth Shield" msgstr "Å tít prikrádania" msgid "campaignBonus|Tax Lien" msgstr "Daňové záložné právo" msgid "campaignBonus|Thunder Mace" msgstr "Palcát hromu" msgid "campaignBonus|Traveler's Boots" msgstr "Cestovateľove topánky" msgid "campaignBonus|White Pearl" msgstr "Biela perla" msgid "campaignBonus|Basic Archery" msgstr "Základná lukostreľba" msgid "campaignBonus|Advanced Archery" msgstr "PokroÄilá lukostreľba" msgid "campaignBonus|Expert Archery" msgstr "Expert lukostreľby" msgid "campaignBonus|Basic Ballistics" msgstr "Základná balistika" msgid "campaignBonus|Advanced Ballistics" msgstr "PokroÄilá balistika" msgid "campaignBonus|Expert Ballistics" msgstr "Expert balistiky" msgid "campaignBonus|Basic Diplomacy" msgstr "Základná diplomacia" msgid "campaignBonus|Advanced Diplomacy" msgstr "PokroÄilá diplomacia" msgid "campaignBonus|Expert Diplomacy" msgstr "Expert diplomacie" msgid "campaignBonus|Basic Eagle Eye" msgstr "Základný orlí zrak" msgid "campaignBonus|Advanced Eagle Eye" msgstr "PokroÄilý orlí zrak" msgid "campaignBonus|Expert Eagle Eye" msgstr "Expert orlieho zraku" msgid "campaignBonus|Basic Estates" msgstr "Základné statky" msgid "campaignBonus|Advanced Estates" msgstr "PokroÄilé statky" msgid "campaignBonus|Expert Estates" msgstr "Expert statkov" msgid "campaignBonus|Basic Leadership" msgstr "Základné vedenie" msgid "campaignBonus|Advanced Leadership" msgstr "PokroÄilé vedenie" msgid "campaignBonus|Expert Leadership" msgstr "Expert vedenia" msgid "campaignBonus|Basic Logistics" msgstr "Základná logistika" msgid "campaignBonus|Advanced Logistics" msgstr "PokroÄilá logistika" msgid "campaignBonus|Expert Logistics" msgstr "Expert logistiky" msgid "campaignBonus|Basic Luck" msgstr "Základné šťastie" msgid "campaignBonus|Advanced Luck" msgstr "PokroÄilé šťastie" msgid "campaignBonus|Expert Luck" msgstr "Expert šťastia" msgid "campaignBonus|Basic Mysticism" msgstr "Základná mystika" msgid "campaignBonus|Advanced Mysticism" msgstr "PokroÄilá mystika" msgid "campaignBonus|Expert Mysticism" msgstr "Expert mystiky" msgid "campaignBonus|Basic Navigation" msgstr "Základná navigácia" msgid "campaignBonus|Advanced Navigation" msgstr "PokroÄilá navigácia" msgid "campaignBonus|Expert Navigation" msgstr "Expert navigácie" msgid "campaignBonus|Basic Necromancy" msgstr "Základná nekromancia" msgid "campaignBonus|Advanced Necromancy" msgstr "PokroÄilá nekromancia" msgid "campaignBonus|Expert Necromancy" msgstr "Expert nekromancie" msgid "campaignBonus|Basic Pathfinding" msgstr "Základné hľadanie cesty" msgid "campaignBonus|Advanced Pathfinding" msgstr "PokroÄilé hľadanie cesty" msgid "campaignBonus|Expert Pathfinding" msgstr "Expert hľadania cesty" msgid "campaignBonus|Basic Scouting" msgstr "Základný prieskum" msgid "campaignBonus|Advanced Scouting" msgstr "PokroÄilý prieskum" msgid "campaignBonus|Expert Scouting" msgstr "Expert prieskumu" msgid "campaignBonus|Basic Wisdom" msgstr "Základná múdrosÅ¥" msgid "campaignBonus|Advanced Wisdom" msgstr "PokroÄilá múdrosÅ¥" msgid "campaignBonus|Expert Wisdom" msgstr "Expert múdrosti" #, fuzzy msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "Hlavný hrdina bude maÅ¥ artefakt \"%{artifact}\" na zaÄiatku scenára." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Kráľovstvo dostane na zaÄiatku scenára suroviny navyÅ¡e: + %{amount} " "%{resource}." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Kráľovstvu budú na zaÄiatku scenára odobrané suroviny: - %{amount} " "%{resource}." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" "Hlavný hrdina obdrží jednotky navyÅ¡e na zaÄiatku scenára: + %{count} " "%{monster}" #, fuzzy msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "Hlavný hrdina bude ovládaÅ¥ kúzlo \"%{spell}\" na zaÄiatku scenára." #, fuzzy msgid "The starting alignment of the scenario will be %{race}." msgstr "ZaÄiatoÄnou rasou scenára bude %{race}." #, fuzzy msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "Hlavný hrdina obdrží skúsenosÅ¥ navyÅ¡e na zaÄiatku scenára: + %{count} " "%{skill}" msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Hlavný hrdina bude ovládaÅ¥ %{skill} na zaÄiatku scenára." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" #, fuzzy msgid "Price of Loyalty" msgstr "Cena vernosti" msgid "Voyage Home" msgstr "Plavba domov" msgid "Wizard's Isle" msgstr "ÄŒarodejov ostrov" msgid "Descendants" msgstr "Potomkovia" msgid "Cannot build. You have already built here today." msgstr "Nedá sa stavaÅ¥. Dnes tu už bola budova postavená." msgid "For this action it is necessary to build a castle first." msgstr "Pre tento krok je potrebné najprv postaviÅ¥ hrad." msgid "The %{building} produces %{monster}." msgstr "%{building} produkuje: %{monster}." msgid "Requires:" msgstr "Potrebuje:" msgid "Exit this menu without doing anything." msgstr "Opusti túto ponuku bez vykonania akcie." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Nedá sa postaviÅ¥ %{name} pretože hrad je priÄaleko od vodnej plochy." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Budovu %{name} si nemôžeÅ¡ dovoliÅ¥." #, fuzzy msgid "The %{name} is already built." msgstr "Budova %{name} je už postavená." #, fuzzy msgid "Cannot build the %{name}." msgstr "Nedá sa postaviÅ¥ budovu %{name}." msgid "Build %{name}." msgstr "Postav budovu %{name}." msgid "Blackridge" msgstr "ÄŒierny Hrebeň" msgid "Hillstone" msgstr "Horský Kameň" msgid "Pinehurst" msgstr "Borovicový KopÄek" msgid "Whiteshield" msgstr "Biely Å tít" msgid "Woodhaven" msgstr "Drevený Prístav" msgid "Blackwind" msgstr "ÄŒierny Vietor" msgid "Bloodreign" msgstr "Krvomoc" msgid "Dragontooth" msgstr "DraÄí Zub" msgid "Greywind" msgstr "Sivý Vietor" msgid "Portsmith" msgstr "Kutý Prístav" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Stredná Brána" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulkánia" msgid "Baywatch" msgstr "Zálivná Stráž" msgid "Fountainhead" msgstr "Prameň" msgid "Vertigo" msgstr "Závrat" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Zimomor" msgid "Brindamoor" msgstr "BrindamoÄ" msgid "Lakeside" msgstr "Jazerné Brehy" msgid "Nightshadow" msgstr "NoÄný Tieň" msgid "Olympus" msgstr "Olymp" msgid "Sandcaster" msgstr "Pieskoval" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragaduna" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algária" msgid "Basenji" msgstr "Basendži" msgid "Blackfang" msgstr "ÄŒierny Tesák" msgid "New Dawn" msgstr "Nový Úsvit" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Zdravá Voda" msgid "Big Oak" msgstr "Veľký Dub" msgid "Chandler" msgstr "ÄŒendler" msgid "Erliquin" msgstr "Erlikín" msgid "Hampshire" msgstr "StudniÄka" msgid "Antioch" msgstr "Antiochia" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Rochovník" msgid "South Mill" msgstr "Južný Mlyn" msgid "Weed Patch" msgstr "Záhon Buriny" msgid "Brownston" msgstr "Hnedany" msgid "Hilltop" msgstr "Vrchol" msgid "Weddington" msgstr "BohuÅ¡ove Panstvo" msgid "Westfork" msgstr "Západné Rozcestie" msgid "Whittingham" msgstr "Vítova Ves" msgid "Cathcart" msgstr "Vozov" msgid "Elk's Head" msgstr "Losia Hlava" msgid "Roscomon" msgstr "Karolov Vŕšok" msgid "Sherman" msgstr "Å erman" msgid "Yorksford" msgstr "KanÄí Brod" msgid "Blackburn" msgstr "ÄŒernopal" msgid "Blacksford" msgstr "ÄŒernobrod" msgid "Burton" msgstr "Dvorná" msgid "Pig's Eye" msgstr "Svinské Oko" msgid "Viper's Nest" msgstr "Hniezdo Zmije" msgid "Fenton" msgstr "MoÄiarno" msgid "Lankershire" msgstr "Krivokraj" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Drevený Kopec" msgid "Troy" msgstr "Trója" msgid "Forder Oaks" msgstr "Dubobrod" msgid "Meramec" msgstr "Horká Voda" msgid "Quick Silver" msgstr "Ortutie" msgid "Westmoor" msgstr "Západný MoÄiar" msgid "Willow" msgstr "Vrbina" msgid "Corackston" msgstr "Starý Lom" msgid "Sheltemburg" msgstr "Å títnica" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Nedá sa najaÅ¥ - v tomto meste už máš hrdinu." msgid "Cannot recruit - you have too many Heroes." msgstr "Nedá sa najaÅ¥ - máš príliÅ¡ mnoho hrdinov." #, fuzzy msgid "Cannot afford a Hero." msgstr "Hrdinu si nemôžeÅ¡ dovoliÅ¥" msgid "There is no room in the garrison for this army." msgstr "V posádke nie je miesto pre túto armádu." msgid "Fortifications" msgstr "Opevnenia" msgid "Farm" msgstr "Farma" msgid "Thatched Hut" msgstr "Slamená chatrÄ" msgid "Archery Range" msgstr "Luková strelnica" msgid "Upg. Archery Range" msgstr "Pov. Luková strelnica" msgid "Blacksmith" msgstr "KováÄ" msgid "Upg. Blacksmith" msgstr "Pov. KováÄ" msgid "Armory" msgstr "Zbrojnica" msgid "Upg. Armory" msgstr "Pov. Zbrojnica" msgid "Jousting Arena" msgstr "Turnajová aréna" msgid "Upg. Jousting Arena" msgstr "Pov. Turnajová aréna" msgid "Cathedral" msgstr "Katedrála" msgid "Upg. Cathedral" msgstr "Pov. Katedrála" msgid "Coliseum" msgstr "Koloseum" msgid "Garbage Heap" msgstr "Smetisko" msgid "Hut" msgstr "ChatrÄ" msgid "Stick Hut" msgstr "Drevenica" msgid "Upg. Stick Hut" msgstr "Pov. Drevenica" msgid "Den" msgstr "Brloh" msgid "Adobe" msgstr "Tehlový dom" msgid "Upg. Adobe" msgstr "Pov. Tehlový dom" msgid "Bridge" msgstr "Most" msgid "Upg. Bridge" msgstr "Pov. Most" msgid "Pyramid" msgstr "Pyramída" msgid "Rainbow" msgstr "Dúha" msgid "Crystal Garden" msgstr "KriÅ¡táľová záhrada" msgid "Treehouse" msgstr "Dom na strome" msgid "Cottage" msgstr "Chalupa" msgid "Upg. Cottage" msgstr "Pov. Chalupa" msgid "Stonehenge" msgstr "Stonehenge" msgid "Upg. Stonehenge" msgstr "Pov. Stonehenge" msgid "Fenced Meadow" msgstr "Oplotená lúka" msgid "sorceress|Red Tower" msgstr "ÄŒervená veža" msgid "Dungeon" msgstr "Žalár" msgid "Waterfall" msgstr "Vodopád" msgid "Cave" msgstr "Jaskyňa" msgid "Crypt" msgstr "Krypta" msgid "Nest" msgstr "Hniezdo" msgid "Maze" msgstr "Labyrint" msgid "Upg. Maze" msgstr "Pov. Labyrint" msgid "Swamp" msgstr "MoÄiar" msgid "Green Tower" msgstr "Zelená veža" msgid "warlock|Red Tower" msgstr "ÄŒervená veža" msgid "Black Tower" msgstr "ÄŒierna veža" msgid "Library" msgstr "Knižnica" msgid "Orchard" msgstr "Ovocný sad" msgid "Habitat" msgstr "Habitát" msgid "Pen" msgstr "Ohrada" msgid "Foundry" msgstr "Zlievareň" msgid "Upg. Foundry" msgstr "Pov. Zlievareň" msgid "Cliff Nest" msgstr "Hniezdo na útese" msgid "Ivory Tower" msgstr "Veža zo slonoviny" msgid "Upg. Ivory Tower" msgstr "Pov. Veža zo slonoviny" msgid "Cloud Castle" msgstr "OblaÄné mesto" msgid "Upg. Cloud Castle" msgstr "Pov. OblaÄné mesto" msgid "Storm" msgstr "Búrka" msgid "Skull Pile" msgstr "Hromada lebiek" msgid "Excavation" msgstr "Vykopávka" msgid "Graveyard" msgstr "Cintorín" msgid "Upg. Graveyard" msgstr "Pov. Cintorín" msgid "Upg. Pyramid" msgstr "Pov. Pyramída" msgid "Mansion" msgstr "KaÅ¡tieľ" msgid "Upg. Mansion" msgstr "Pov. KaÅ¡tieľ" msgid "Mausoleum" msgstr "Mauzóleum" msgid "Upg. Mausoleum" msgstr "Pov. Mauzóleum" msgid "Laboratory" msgstr "Laboratórium" msgid "Shrine" msgstr "Svätyňa" #, fuzzy msgid "Special" msgstr "NiÄ zvláštne" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "PolÄíci" #, fuzzy msgid "Dwelling 2" msgstr "PolÄíci" #, fuzzy msgid "Upg. Dwelling 2" msgstr "PolÄíci" #, fuzzy msgid "Dwelling 3" msgstr "PolÄíci" #, fuzzy msgid "Upg. Dwelling 3" msgstr "PolÄíci" #, fuzzy msgid "Dwelling 4" msgstr "PolÄíci" #, fuzzy msgid "Upg. Dwelling 4" msgstr "PolÄíci" #, fuzzy msgid "Dwelling 5" msgstr "PolÄíci" #, fuzzy msgid "Upg. Dwelling 5" msgstr "PolÄíci" #, fuzzy msgid "Dwelling 6" msgstr "PolÄíci" #, fuzzy msgid "Upg. Dwelling 6" msgstr "PolÄíci" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Opevnenia zvyÅ¡ujú húževnatosÅ¥ múrov a zvyÅ¡ujú poÄet kôl potrebných na ich " "zbúranie." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Farma zvyÅ¡uje produkciu roľníkov o %{count} za týždeň." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Koloseum poskytuje obranným jednotkám inÅ¡piratívne predstavenie, ktoré poÄas " "boja zvýši ich morálku o dve." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Smetisko zvyÅ¡uje produkciu goblinov o %{count} za týždeň." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Dúha zvyÅ¡uje šťastie obranných jednotiek o dve." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "KriÅ¡táľová záhrada zvyÅ¡uje produkciu víl o %{count} za týždeň." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Žalár zvyÅ¡uje príjem mesta o %{count} zlata za deň." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Vodopád zvyÅ¡uje produkciu kentaurov o %{count} za týždeň." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "Knižnica zvyÅ¡uje poÄet kúziel v cechu o jedno za každú úroveň cechu." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Ovocný sad zvyÅ¡uje produkciu polÄíkov o %{count} za týždeň." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "Búrka pridáva +2 k sile kúziel brániaceho kúzelníka." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Hromada lebiek zvyÅ¡uje produkciu kostlivcov o %{count} za týždeň." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Studňa zvyÅ¡uje rýchlosÅ¥ nárastu bojovníkov vÅ¡etkých obydlí o %{count} za " "týždeň." msgid "Thieves' Guild" msgstr "Cech zlodejov" msgid "Tavern" msgstr "KrÄma" msgid "Shipyard" msgstr "Lodenica" msgid "Well" msgstr "Studňa" msgid "Statue" msgstr "Socha" msgid "Marketplace" msgstr "Trhovisko" msgid "Moat" msgstr "Priekopa" msgid "Castle" msgstr "Hrad" msgid "Tent" msgstr "Stan" msgid "Captain's Quarters" msgstr "Kapitánova ubytovňa" msgid "Mage Guild, Level 1" msgstr "Cech mágov, úroveň 1" msgid "Mage Guild, Level 2" msgstr "Cech mágov, úroveň 2" msgid "Mage Guild, Level 3" msgstr "Cech mágov, úroveň 3" msgid "Mage Guild, Level 4" msgstr "Cech mágov, úroveň 4" msgid "Mage Guild, Level 5" msgstr "Cech mágov, úroveň 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Svätyňa zvyÅ¡uje zruÄnosÅ¥ nekromancie vÅ¡etkých tvojich nekromantov o 10 " "percent." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Cech zlodejov poskytuje informácie o nepriateľských hráÄoch. Cech zlodejov " "tiež poskytuje prieskumné informácie o nepriateľských mestách. DodatoÄné " "cechy poskytnú viac informácií." msgid "The Tavern increases morale for troops defending the castle." msgstr "KrÄma zvyÅ¡uje morálku pre jednotky brániace hrad." msgid "The Shipyard allows ships to be built." msgstr "Lodenica umožňuje stavbu lodí." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Studňa zvyÅ¡uje rýchlosÅ¥ nárastu bojovníkov vÅ¡etkých obydlí o %{count} za " "týždeň." #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Socha zvyÅ¡uje príjem tvojho mesta o %{count} zlata za deň." msgid "The Left Turret provides extra firepower during castle combat." msgstr "Ľavá veža poskytuje palebnú silu navyÅ¡e poÄas boja o hrad." msgid "The Right Turret provides extra firepower during castle combat." msgstr "Pravá veža poskytuje palebnú silu navyÅ¡e poÄas boja o hrad." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Trhovisko možno použiÅ¥ na zámenu jedného typu zdroja za iný. Čím viac " "trhovísk vlastníš, tým lepší je výmenný kurz." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Priekopa spomaľuje útoÄiace jednotky. Každá jednotka, ktorá vstúpi do " "priekopy, tam musí svoj Å¥ah ukonÄiÅ¥ a stane sa zraniteľnejÅ¡ou voÄi útoku." #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "Hrad zlepÅ¡uje obranu mesta a zvyÅ¡uje príjem na %{count} zlata za deň." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Stan poskytuje robotníkov na stavbu hradu za predpokladu, že sú k dispozícii " "materiály a zlato." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Kapitánova ubytovňa poskytuje kapitána, ktorý pomáha pri obrane hradu, keÄ " "nie je prítomný žiadny hrdina." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "Cech mágov umožňuje hrdinom uÄiÅ¥ sa kúzla a dopĺňaÅ¥ si body kúziel." msgid "Recruit %{name}" msgstr "NajaÅ¥: %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Mesiac: %{month}, Týždeň: %{week}, Deň: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Ak chceÅ¡ používaÅ¥ cech mágov, musíš si kúpiÅ¥ knihu kúziel, ale momentálne " "nemáš miesto pre knihu kúziel. Skús daÅ¥ jeden zo svojich artefaktov inému " "hrdinovi." msgid "Click to show next town." msgstr "Kliknutím zobraz ÄalÅ¡ie mesto." msgid "Show next town" msgstr "Ukáž ÄalÅ¡ie mesto" msgid "Click to show previous town." msgstr "Kliknutím zobraz predoÅ¡lé mesto." msgid "Show previous town" msgstr "Ukáž predoÅ¡lé mesto" msgid "This town may not be upgraded to a castle." msgstr "Toto mesto nemôže byÅ¥ povýšené na hrad." msgid "Town" msgstr "Mesto" msgid "Exit Castle" msgstr "PreÄ z hradu" msgid "Exit Town" msgstr "PreÄ z mesta" msgid "Show Income" msgstr "Ukáž príjem" msgid "View Hero" msgstr "Ukáž hrdinu" msgid "The above spells are available here." msgstr "Vyššie uvedené kúzla sú tu dostupné." msgid "The spells the hero can learn have been added to their book." msgstr "Do knihy boli pridané kúzla, ktoré sa hrdina môže nauÄiÅ¥." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Å tedré prepitné pre barmana prináša nasledujúcu fámu:" msgid "Recruit Hero" msgstr "NajaÅ¥ hrdinu" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} je %{race} na úrovni %{value} " msgid "with %{count} artifacts." msgstr "s %{count} artefaktmi." msgid "with 1 artifact." msgstr "s jedným artefaktom." msgid "without artifacts." msgstr "bez artefaktov." msgid "Recruit %{name} the %{race}" msgstr "Najmi: %{race} %{name}" #, fuzzy msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Å iroká' bojová formácia rozprestiera tvoje armády zhora nadol na bojisko, " "priÄom medzi každou armádou je aspoň jedno prázdne miesto." #, fuzzy msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "'Zoskupená' bojová formácia spája tvoju armádu v strede tvojej strany " "bojiska." msgid "Spread Formation" msgstr "Å iroká formácia" msgid "Grouped Formation" msgstr "Zoskupená formácia" #, fuzzy msgid "Click to show the next town." msgstr "Kliknutím zobraz ÄalÅ¡ie mesto." #, fuzzy msgid "Click to show the previous town." msgstr "Kliknutím zobraz predoÅ¡lé mesto." msgid "Set garrison combat formation to 'Spread'" msgstr "NastaviÅ¥ bojovú formáciu posádky na 'Å iroká'" msgid "Set garrison combat formation to 'Grouped'" msgstr "NastaviÅ¥ bojovú formáciu posádky na 'Zoskupená'" msgid "Exit Castle Options" msgstr "PreÄ z možností hradu" msgid "Castle Options" msgstr "Možnosti hradu" msgid "Not enough resources to recruit creatures." msgstr "Nie je dostatok zdrojov na nábor bojovníkov." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Momentálne nemôžeÅ¡ robiÅ¥ nábor, tvoje rady sú plné." msgid "No creatures available for purchase." msgstr "Žiadni bojovníci nie sú k dispozícii na nákup." msgid "Recruit Creatures" msgstr "NajaÅ¥ bojovníkov" msgid "Hire all creatures in the town." msgstr "Najmi vÅ¡etkých bojovníkov v meste." msgid "Max" msgstr "Max" msgid "Available" msgstr "Dostupné" msgid "Town Population Information and Statistics" msgstr "Informácie o obyvateľstve a Å¡tatistika mesta" msgid "Damage" msgstr "PoÅ¡kodenie" msgid "HP" msgstr "Zdravie" msgid "Growth" msgstr "Nárast" msgid "week" msgstr "týždeň" msgid "View World" msgstr "Ukáž svet" msgid "View the entire world." msgstr "Ukáž celý svet." msgid "Puzzle" msgstr "Rébus" msgid "View the obelisk puzzle." msgstr "Ukáž rébus obeliskov." msgid "Scenario Information" msgstr "Informácie o hre" msgid "View information on the scenario you are currently playing." msgstr "Pozri si informácie o hre, ktorú práve hráš." msgid "Dig for the Ultimate Artifact." msgstr "Kop za ultimátnym artefaktom." msgid "Digging" msgstr "Kopanie" msgid "Arena" msgstr "Aréna" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Po vstupe do arény Äelíš svorke zúrivých levov. Za búrlivého povzbudzovania " "davu ich ľahko porazíš. Starý tréner gladiátorov, na ktorého urobili dojem " "tvoje schopnosti, súhlasí, že Å¥a vyÅ¡kolí v zruÄnosti podľa tvojho výberu." msgid "Attack Skill" msgstr "Útok" msgid "Defense Skill" msgstr "Obrana" msgid "Shots" msgstr "Strely" msgid "Shots Left" msgstr "Ostáva striel" msgid "Hit Points" msgstr "Zdravie max" msgid "Hit Points Left" msgstr "Zdravie teraz" msgid "You can't afford to upgrade your troops!" msgstr "NemôžeÅ¡ si dovoliÅ¥ povýšiÅ¥ svoje jednotky!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Tvoje jednotky môžu byÅ¥ vylepÅ¡ené, ale bude Å¥a to stáť draho. ChceÅ¡ ich " "povýšiÅ¥?" msgid "Are you sure you want to dismiss this army?" msgstr "UrÄite chceÅ¡ prepustiÅ¥ túto armádu?" msgid "Upgrade" msgstr "Povýš" msgid "Upgrade your troops." msgstr "Povýš svoje jednotky." msgid "Dismiss" msgstr "Prepusti" msgid "Dismiss this army." msgstr "Prepusti túto armádu." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "%{monster}, s túžbou po väÄÅ¡ej sláve, sa k tebe chcú pridaÅ¥.\n" "PrijímaÅ¡ ich?" msgid "Followers" msgstr "Nasledovníci" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} je ovplyvnený/á tvojim diplomatickým jazykom a ponúka ti vstup do " "tvojej armády za sumu %{gold} zlata.\n" "PrijímaÅ¡ ponuku?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Bojovníci sú pohnutí tvojim diplomatickým\n" "jazykom a ponúkajú:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster}, presnejÅ¡ie %{offer} z celkových %{total} sa pripoja k tvojej " "armáde a zvyÅ¡ok Å¥a nechá na pokoji za sumu %{gold} zlata.\n" "PrijímaÅ¡ ponuku?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Celá skupina - %{offer} %{monster}, sa pripojí k tvojej armáde za sumu " "%{gold} zlata.\n" "PrijímaÅ¡ ponuku?" msgid "(Rate: %{percent})" msgstr "%{percent}% vÅ¡etkých bojovníkov" msgid "off" msgstr "vypnuté" msgid "Music" msgstr "Hudba" msgid "Effects" msgstr "Zvukové efekty" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "Rozšírenie MIDI" msgid "External" msgstr "Externý" msgid "Music Type" msgstr "Typ hudby" msgid "3D Audio" msgstr "3D zvuk" msgid "Toggle ambient music level." msgstr "Zmeň úroveň zvukov okolia." msgid "Toggle foreground sounds level." msgstr "Zmeň úroveň zvukov popredia." msgid "Change the type of music." msgstr "Zmeň typ hudby." #, fuzzy msgid "Toggle the 3D effect of foreground sounds." msgstr "Zmeň 3D efekty zvukov popredia." msgid "Build a new ship:" msgstr "Postav novú loÄ:" msgid "Resource cost:" msgstr "Náklady:" msgid "Total: " msgstr "Celkovo: " msgid "Need: " msgstr "Potreba: " msgid "New Game" msgstr "Nová hra" msgid "Start a single or multi-player game." msgstr "ZaÄni hru jedného alebo viac hráÄov." msgid "Load Game" msgstr "Nahraj hru" msgid "Load a previously saved game." msgstr "Nahraj predtým uloženú hru." msgid "Save Game" msgstr "Ulož hru" msgid "Save the current game." msgstr "Ulož terajÅ¡iu hru." msgid "Quit" msgstr "Koniec" msgid "Quit out of Heroes of Might and Magic II." msgstr "OdÃ­Ä z Heroes of Might and Magic II." msgid "Language" msgstr "Jazyk" msgid "Graphics" msgstr "Grafika" msgid "Black & White" msgstr "ÄŒiernobiely" msgid "Mouse Cursor" msgstr "Kurzor myÅ¡i" msgid "Color" msgstr "Farebný" msgid "Text Support" msgstr "Podpora textu" msgid "Change the language of the game." msgstr "Zmeň jazyk hry." msgid "Select Game Language" msgstr "Vyber jazyk hry" msgid "Change the graphics settings of the game." msgstr "Zmeň nastavenie grafiky hry." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Zapnutie alebo vypnutie farebného kurzora. Ide len o estetickú voľbu." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Prepni režim podpory textu na výstup dodatoÄných informácií o oknách a " "udalostiach v hre." msgid "" "Map\n" "Difficulty" msgstr "" "ObtiažnosÅ¥\n" "mapy" msgid "" "Game\n" "Difficulty" msgstr "" "ObtiažnosÅ¥\n" "hry" msgid "Rating" msgstr "Hodnotenie" msgid "Map Size" msgstr "VeľkosÅ¥ mapy" msgid "Opponents" msgstr "Oponenti" msgid "Class" msgstr "Trieda" msgid "" "Victory\n" "Conditions" msgstr "" "Podmienky\n" "víťazstva" msgid "" "Loss\n" "Conditions" msgstr "" "Podmienky\n" "prehry" msgid "First select recipients!" msgstr "Najprv zvoľ príjemcov!" msgid "You cannot select %{resource}!" msgstr "NemôžeÅ¡ zvoliÅ¥ %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Streľ do: %{monster}" msgid "Select Recipients" msgstr "Zvoľ príjemcov" msgid "Your Funds" msgstr "Tvoj majetok" msgid "Planned Gift" msgstr "Plánovaný dar" msgid "Gift from %{name}" msgstr "Dar od: %{name}" msgid "Resolution" msgstr "Rozlíšenie" msgid "Fullscreen" msgstr "Celá obrazovka" msgid "window|Mode" msgstr "Mód" msgid "Windowed" msgstr "Okno" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Systémové info" msgid "Change the resolution of the game." msgstr "Zmeň rozlíšenie hry." msgid "Select Game Resolution" msgstr "Zvoľ rozlíšenie hry" msgid "Toggle between fullscreen and windowed modes." msgstr "Prepni medzi módom celej obrazovky a oknom." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "MožnosÅ¥ V-Sync dokáže vyrieÅ¡iÅ¥ problém s blikaním na niektorých monitoroch." msgid "Show extra information such as FPS and current time." msgstr "Ukáž informácie navyÅ¡e ako FPS a momentálny Äas." msgid "Hotkey: " msgstr "" msgid "Category: " msgstr "" #, fuzzy msgid "Event: " msgstr "UdalosÅ¥" msgid "Hot Keys:" msgstr "Skratky:" msgid "Hide" msgstr "Skry" msgid "Show" msgstr "Zobraz" msgid "Interface" msgstr "Rozhranie" msgid "Interface Type" msgstr "Typ rozhrania" msgid "Toggle the type of interface you want to use." msgstr "Prepni typ rozhrania, ktorý chceÅ¡ vidieÅ¥." msgid "Toggle interface visibility." msgstr "Prepni viditeľnosÅ¥ rozhrania." msgid "Scroll Speed" msgstr "RýchlosÅ¥ posunu" msgid "Sets the speed at which you scroll the window." msgstr "Nastaví rýchlosÅ¥, ktorou sa posúva okno." msgid "Select Game Language:" msgstr "Zvoľ jazyk hry:" #, fuzzy msgid "Select Language:" msgstr "Zvoľ jazyk hry:" msgid "Click to choose the selected language." msgstr "Klikni pre výber zvoleného jazyka." msgid "%{name} has gained a level." msgstr "%{name} získava úroveň." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "NauÄená zruÄnosÅ¥ %{skill}." #, fuzzy msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "%{name} získava úroveň." #, fuzzy msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "SmieÅ¡ sa nauÄiÅ¥ buÄ:" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "nie je" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Prosím, prezri si náš kvalitný tovar. Ak chceÅ¡ ponúknuÅ¥ výmenu, klikni na " "predmety, s ktorými chceÅ¡ obchodovaÅ¥." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Získali ste poriadne výhodnú ponuku. NeoÄakávam, že na tomto obchode " "zarobím. Môžem vám ponúknuÅ¥ nejaký Äalší tovar?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Ponúkam %{count} za 1 kus typu %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Ponúkam 1 kus typu %{resto} za %{count} kusov typu %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Množstvo" msgid "Trading Post" msgstr "Obchodník" msgid "Your Resources" msgstr "Tvoje zdroje" msgid "Available Trades" msgstr "Možné obchody" msgid "guarded by %{count} %{monster}" msgstr "strážené: %{monster} (%{count})" msgid "guarded by " msgstr "strážené: " msgid "(available: %{count})" msgstr "(dostupné: %{count})" msgid "(empty)" msgstr "(prázdne)" msgid "already learned" msgstr "už nauÄené" #, fuzzy msgid "treeOfKnowledge|free" msgstr "Strom poznania" #, fuzzy msgid "already claimed" msgstr "už nauÄené" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "už má túto zruÄnosÅ¥" msgid "already has max skills" msgstr "už má plno zruÄností" msgid "(already visited)" msgstr "(už navÅ¡tívené)" msgid "(not visited)" msgstr "(nenavÅ¡tívené)" msgid "%{color} Barrier" msgstr "%{color} bariéra" #, fuzzy msgid "(tent visited)" msgstr "(nenavÅ¡tívené)" msgid "%{color} Tent" msgstr "%{color} stan" msgid "Road" msgstr "Cesta" msgid "(digging ok)" msgstr "(dá sa kopaÅ¥)" msgid "(no digging)" msgstr "(nedá sa kopaÅ¥)" msgid "penalty: %{cost}" msgstr "penalta: %{cost}" msgid "Defenders:" msgstr "Obrancovia:" msgid "Unknown" msgstr "Neznáme" msgid "heroQuickInfo|(Level %{level})" msgstr "na úrovni %{level}" msgid "Attack:" msgstr "Útok:" msgid "Defense:" msgstr "Obrana:" msgid "Spell Power:" msgstr "Sila kúziel:" msgid "Knowledge:" msgstr "Vedomosti:" msgid "Spell Points:" msgstr "Body kúziel:" msgid "Move Points:" msgstr "Body pohybu:" msgid "Uncharted Territory" msgstr "Nepreskúmané územie" msgid "Cost per troop:" msgstr "Cena za jednotku:" msgid "Available: %{count}" msgstr "Dostupné: %{count}" msgid "Number to buy:" msgstr "PoÄet na nákup:" msgid "Recruit selected monsters." msgstr "Najmi zvolených bojovníkov." msgid "Select maximum monsters to be recruited." msgstr "Zvoľ najväÄší možný poÄet bojovníkov k nájmu." msgid "Select only 1 monster to be recruited." msgstr "Zvoľ iba jedného bojovníka k nájmu." #, fuzzy msgid "Select this game resolution." msgstr "Zvoľ rozlíšenie hry" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Zvoľ rozlíšenie hry:" msgid "Click to apply the selected resolution." msgstr "Klikni pre výber zvoleného rozlíšenia." msgid "Click to apply the entered text." msgstr "Klikni pre použitie zadaného textu." msgid "Click to open the Virtual Keyboard dialog." msgstr "Klikni pre otvorenie dialógu virtuálnej klávesnice." msgid "Open Virtual Keyboard" msgstr "Otvor virtuálnu klávesnicu" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "Koľko jednotiek na presun?" #, fuzzy msgid "Select how many units to separate into:" msgstr "Vyber mesto, do ktorého sa chceÅ¡ preniesÅ¥." msgid "Map: " msgstr "Mapa: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "Mesiac: " msgid ", Week: " msgstr ", Týždeň: " msgid ", Day: " msgstr ", Deň: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Umiestnenie: " msgid "Are you sure you want to delete file:" msgstr "UrÄite chceÅ¡ vymazaÅ¥ súbor:" msgid "Warning" msgstr "Pozor" msgid "Click to save the current game." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Click to load a previously saved game." msgstr "Klikni pre nahranie vopred uloženej hry." msgid "File to Save:" msgstr "UložiÅ¥ súbor:" msgid "File to Load:" msgstr "NahraÅ¥ súbor:" #, fuzzy msgid "Terrain object" msgstr "Režim terénu" msgid "Accept the choice made." msgstr "PrijaÅ¥ uskutoÄnený výber." msgid "Select Skill:" msgstr "Zvoľ zruÄnosÅ¥:" msgid "Select Spell:" msgstr "Zvoľ kúzlo:" msgid "Select Artifact:" msgstr "Zvoľ artefakt:" msgid "Select Monster:" msgstr "Zvoľ bojovníka:" msgid "Select Hero:" msgstr "Zvoľ hrdinu:" msgid "race|Random" msgstr "Náhodná" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Klikni pre výber zvoleného rozlíšenia." #, fuzzy msgid "%{color} %{race}" msgstr "%{color} hráÄ" msgid "You will place" msgstr "" #, fuzzy msgid "Click to select this class." msgstr "Klikni sem a vyber scenár, ktorý chceÅ¡ hraÅ¥." #, fuzzy msgid "Click to select this color." msgstr "Klikni sem a vyber scenár, ktorý chceÅ¡ hraÅ¥." #, fuzzy msgid "Select Treasure:" msgstr "Zvoľ hrdinu:" #, fuzzy msgid "Select Ocean Object:" msgstr "Objekty oceánu" #, fuzzy msgid "Castle/town placing" msgstr "Možnosti hradu" msgid "doubleLinedRace|Neutral" msgstr "Neutrálna" #, fuzzy msgid "Click to start placing the selected castle/town." msgstr "Klikni pre výber zvoleného rozlíšenia." #, fuzzy msgid "Click to select town placing." msgstr "Kliknutím zobraz ÄalÅ¡ie mesto." #, fuzzy msgid "Click to select castle placing." msgstr "Klikni sem a vyber scenár, ktorý chceÅ¡ hraÅ¥." #, fuzzy msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} hráÄ" msgid "race|Neutral" msgstr "Neutrálna" #, fuzzy msgid "Select Dwelling:" msgstr "Zvoľ kúzlo:" #, fuzzy msgid "Select Landscape Object:" msgstr "Objekty oceánu" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "Surovina" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{race} %{name}" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "Klikni sem a vyber scenár, ktorý chceÅ¡ hraÅ¥." #, fuzzy msgid "Select Mountain Object:" msgstr "Objekty oceánu" #, fuzzy msgid "Select Rock Object:" msgstr "Objekty oceánu" #, fuzzy msgid "Select Tree Object:" msgstr "Objekty oceánu" #, fuzzy msgid "Select Power Up Object:" msgstr "Objekty oceánu" #, fuzzy msgid "Select Adventure Object:" msgstr "Objekty oceánu" msgid "Players Icon" msgstr "Ikona hráÄa" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "ZnaÄí, koľko hráÄov je celkovo v scenári. Akékoľvek pozície, ktoré nie sú " "obsadené ľuÄmi, budú obsadené poÄítaÄovými hráÄmi." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "ZnaÄí, Äi je mapa malá (36 x 36), stredná (72 x 72), veľká (108 x 108), " "alebo extra veľká (144 x 144)." msgid "Size Icon" msgstr "Ikona veľkosti" msgid "Map Type" msgstr "Typ mapy" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "ZnaÄí, Äi je mapa tvorená pre verziu hry \"The Succession Wars\" alebo \"The " "Price of Loyalty\"." msgid "Map Type:\n" msgstr "Typ mapy:\n" msgid "The Succession Wars" msgstr "Vojna o dediÄstvo" msgid "The Price of Loyalty" msgstr "Cena vernosti" #, fuzzy msgid "Resurrection" msgstr "Vzkriesenie" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Jazyk" msgid "Lose all your heroes and towns." msgstr "StraÅ¥ vÅ¡etkých hrdinov a mestá." msgid "Lose a specific town." msgstr "StraÅ¥ konkrétne mesto." msgid "Lose a specific hero." msgstr "StraÅ¥ konkrétneho hrdinu." msgid "Run out of time. Fail to win by a certain point." msgstr "Po uplynutí urÄitej doby stále nevyhráš." msgid "Loss Condition" msgstr "Podmienka prehry" msgid "Defeat all enemy heroes and towns." msgstr "Poraz nepriateľských hrdinov a mestá." msgid "Capture a specific town." msgstr "Doby konkrétne mesto." msgid "Defeat a specific hero." msgstr "Poraz konkrétneho hrdinu." msgid "Find a specific artifact." msgstr "Nájdi konkrétny artefakt." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "Tvoja strana porazí opozíciu." msgid "Accumulate a large amount of gold." msgstr "NahromaÄ obrovské množstvo zlata." msgid "Victory Condition" msgstr "Podmienka výhry" msgid "Map difficulty:" msgstr "ObtiažnosÅ¥ mapy:" msgid "N" msgstr "N" #, fuzzy msgid "No maps exist at that size." msgstr "Mapy tejto veľkosti nie sú" msgid "Small Maps" msgstr "Malé mapy" msgid "View only maps of size small (36 x 36)." msgstr "Zobraz iba mapy malej veľkosti (36 x 36)." msgid "Medium Maps" msgstr "Stredné mapy" msgid "View only maps of size medium (72 x 72)." msgstr "Zobraz iba mapy strednej veľkosti (72 x 72)." msgid "Large Maps" msgstr "Veľké mapy" msgid "View only maps of size large (108 x 108)." msgstr "Zobraz iba mapy veľkej veľkosti (108 x 108)." msgid "Extra Large Maps" msgstr "Extra veľké mapy" msgid "View only maps of size extra large (144 x 144)." msgstr "Zobraz iba mapy extra veľkej veľkosti (144 x 144)." msgid "All Maps" msgstr "VÅ¡etky mapy" msgid "View all maps, regardless of size." msgstr "Zobraz vÅ¡etky mapy bez ohľadu na veľkosÅ¥." msgid "Selected Name" msgstr "Zvolené meno" msgid "The name of the currently selected map." msgstr "Názov momentálne zvolenej mapy." msgid "Selected Map Difficulty" msgstr "Zvolená obtiažnosÅ¥ mapy" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "ObtiažnosÅ¥ mapy aktuálne vybranej mapy. ObtiažnosÅ¥ mapy urÄuje tvorca " "scenára. Ťažšie mapy môžu obsahovaÅ¥ viac alebo silnejších nepriateľov, menej " "zdrojov alebo iné Å¡peciálne podmienky, ktoré sÅ¥ažujú situáciu pre ľudského " "hráÄa." msgid "Selected Description" msgstr "Zvolený opis" msgid "The description of the currently selected map." msgstr "Opis aktuálne zvolenej mapy." msgid "Jump" msgstr "Skok" msgid "Hero Speed" msgstr "RýchlosÅ¥ hrdinu" msgid "Don't Show" msgstr "Neukazuj" msgid "Enemy Speed" msgstr "RýchlosÅ¥ nepriateľa" msgid "Auto Resolve" msgstr "Automaticky" msgid "Auto, No Spells" msgstr "Auto bez kúziel" msgid "Battles" msgstr "Boje" #, fuzzy msgid "combatMode|Manual" msgstr "Manuálne" msgid "Change the speed at which your heroes move on the main screen." msgstr "Zmeň rýchlosÅ¥, ktorou sa tvoji hrdinovia pohybujú v hlavnom okne." #, fuzzy msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Nastaví rýchlosÅ¥, akou sa hýbu poÄítaÄom riadení hrdinovia. MôžeÅ¡ tiež " "nastaviÅ¥, aby sa tento pohyb vôbec nezobrazoval" msgid "Change the interface settings of the game." msgstr "Zmeň nastavenie rozhrania hry." msgid "Interface Settings" msgstr "Nastavenie rozhrania" msgid "Toggle instant battle mode." msgstr "Prepni mód rýchleho boja." msgid "Att." msgstr "Útok" msgid "Def." msgstr "Obr." msgid "Power" msgstr "Sila" msgid "Knowl" msgstr "Ved." msgid "1st" msgstr "Prvý" msgid "2nd" msgstr "Druhý" msgid "3rd" msgstr "Tretí" msgid "4th" msgstr "Å tvrtý" msgid "5th" msgstr "Piaty" msgid "6th" msgstr "Å iesty" msgid "Oracle: Player Rankings" msgstr "Prorok: RebríÄek hráÄov" msgid "Thieves' Guild: Player Rankings" msgstr "Cech zlodejov: RebríÄek hráÄov" msgid "Number of Towns:" msgstr "PoÄet miest:" msgid "Number of Castles:" msgstr "PoÄet hradov:" msgid "Number of Heroes:" msgstr "PoÄet hrdinov:" msgid "Gold in Treasury:" msgstr "Zlato v pokladnici:" msgid "Wood & Ore:" msgstr "Drevo a ruda:" msgid "Gems, Cr, Slf & Mer:" msgstr "Å peciálne suroviny:" msgid "Obelisks Found:" msgstr "Nájdených obeliskov:" msgid "Artifacts:" msgstr "Artefakty:" msgid "Total Army Strength:" msgstr "Celková sila armády:" msgid "Income:" msgstr "Príjem:" msgid "Best Hero:" msgstr "Najlepší hrdina:" msgid "Best Hero Stats:" msgstr "Vlastn. naj hrdinu:" msgid "Personality:" msgstr "OsobnosÅ¥:" msgid "Best Monster:" msgstr "Najlepší bojovník:" #, fuzzy msgid "Random Castle Name" msgstr "Náhodný hrad" #, fuzzy msgid "Random Town Name" msgstr "Náhodné mesto" #, fuzzy msgid "Allow Castle build" msgstr "OblaÄné mesto" #, fuzzy msgid "Default Buildings" msgstr "predvolená ÄinnosÅ¥" #, fuzzy msgid "Default Army" msgstr "predvolená ÄinnosÅ¥" #, fuzzy msgid "Castle Army" msgstr "Hrad" #, fuzzy msgid "Town Army" msgstr "Mesto" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Stratíš hrdinu '%{name}'." msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Panel správ" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Panel správ" #, fuzzy msgid "Click to save the Event properties." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "Surovina" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Deň: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Klikni pre uloženie terajÅ¡ej hry." #, fuzzy msgid "Add Event" msgstr "UdalosÅ¥" #, fuzzy msgid "Add an additional event." msgstr "DodatoÄné programovanie" #, fuzzy msgid "Edit Event" msgstr "UdalosÅ¥" #, fuzzy msgid "Edit an existing event." msgstr "NaÄítaÅ¥ existujúcu mapu." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "NaÄítaÅ¥ existujúcu mapu." #, fuzzy msgid "Effects:" msgstr "Zvukové efekty" #, fuzzy msgid "Conditions:" msgstr "" "Podmienky\n" "prehry" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "Skúsenosti" msgid "Artifact" msgstr "Artefakt" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Zvoľ artefakt:" #, fuzzy msgid "Delete an artifact from the event." msgstr "NaÄítaÅ¥ existujúcu mapu." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Zvoľ zruÄnosÅ¥:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Toto kúzlo nemožno použiÅ¥ na lodi." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Toto kúzlo nemožno použiÅ¥ na lodi." #, fuzzy msgid "%{objects} must be placed on water." msgstr "Toto kúzlo nemožno použiÅ¥ na lodi." #, fuzzy msgid "Objects cannot be placed outside the map." msgstr "Toto kúzlo nemožno použiÅ¥ na lodi." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Toto kúzlo nemožno použiÅ¥ na lodi." #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "UrÄite chceÅ¡ vytvoriÅ¥ novú mapu? (VÅ¡etky neuložené zmeny v aktuálnej mape sa " "stratia.)" msgid "Editor" msgstr "" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "UrÄite chceÅ¡ naÄítaÅ¥ novú mapu? (VÅ¡etky neuložené zmeny v aktuálnej mape sa " "stratia.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "UrÄite chceÅ¡ vytvoriÅ¥ novú mapu? (VÅ¡etky neuložené zmeny v aktuálnej mape sa " "stratia.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "REÅ TART" msgid "Main Menu" msgstr "" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "UrÄite chceÅ¡ vytvoriÅ¥ novú mapu? (VÅ¡etky neuložené zmeny v aktuálnej mape sa " "stratia.)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "ReÅ¡tart" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "UrÄite chceÅ¡ naÄítaÅ¥ novú mapu? (VÅ¡etky neuložené zmeny v aktuálnej mape sa " "stratia.)" #, fuzzy msgid "Create a new map from scratch." msgstr "nová mapa, od nuly" msgid "New Map" msgstr "Nová mapa" msgid "Load Map" msgstr "Nahraj mapu" msgid "Load an existing map." msgstr "NaÄítaÅ¥ existujúcu mapu." msgid "Save Map" msgstr "Ulož mapu" msgid "Save the current map." msgstr "UložiÅ¥ aktuálnu mapu." msgid "Quit out of the map editor." msgstr "UkonÄiÅ¥ prácu v editore máp." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Kliknutím sa vrátiÅ¡ do hlavnej ponuky." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Náhodný ultimátny artefakt" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "s jedným artefaktom." msgid "The total number of obelisks is %{count}." msgstr "" #, fuzzy msgid "Roads" msgstr "Cesta" #, fuzzy msgid "Streams" msgstr "Režim tokov" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Toto kúzlo nemožno použiÅ¥ na lodi." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Uložený súbor je poÅ¡kodený." msgid "Unable to locate data directory to save the map." msgstr "" #, fuzzy msgid "Unable to create a directory to save the map." msgstr "Slúži na vymazanie objektov z mapy." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Slúži na vymazanie objektov z mapy." #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Naozaj chceÅ¡ prepísaÅ¥ uložený súbor s týmto názvom?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "UložiÅ¥ súbor:" #, fuzzy msgid "Used to place %{object}." msgstr "Slúži na umiestnenie hrdinu." #, fuzzy msgid "Select object type" msgstr "Objekty oceánu" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Klikni sem a vyber scenár, ktorý chceÅ¡ hraÅ¥." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Prosím zvoľ ÄalÅ¡ieho hrdinu." msgid "" "Cell\n" "Details" msgstr "" #, fuzzy msgid "Erase" msgstr "Režim mazania" msgid "Mountains" msgstr "Hory" #, fuzzy msgid "Rocks" msgstr "Skala" msgid "Trees" msgstr "Stromy" #, fuzzy msgid "Water Objects" msgstr "Objekty pustatiny" #, fuzzy msgid "Miscellaneous" msgstr "Fineous" msgid "Artifacts" msgstr "Artefakty" #, fuzzy msgid "Dwellings" msgstr "PolÄíci" msgid "Mines" msgstr "Bane" #, fuzzy msgid "Power-ups" msgstr "Sila" msgid "Treasures" msgstr "Poklady" msgid "Heroes" msgstr "Hrdinovia" msgid "Towns" msgstr "Mestá" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Objekty oceánu" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Kreslí terén v\n" "%{size} krát %{size} Å¡tvorcových krokoch." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Maže terén v\n" "%{size} krát %{size} Å¡tvorcových krokoch." msgid "Small Brush" msgstr "Malý Å¡tetec" msgid "Medium Brush" msgstr "Stredný Å¡tetec" msgid "Large Brush" msgstr "Veľký Å¡tetec" msgid "Area Fill" msgstr "Výplň oblasti" msgid "Used to click and drag for filling in large areas." msgstr "Slúži na kliknutie a Å¥ahanie na vyplnenie veľkých plôch." msgid "Clear Area" msgstr "VyÄistiÅ¥ oblasÅ¥" msgid "Used to click and drag for clearing large areas." msgstr "Slúži na kliknutie a Å¥ahanie na vyÄistenie veľkých plôch." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Stojí %{rate} krát normálny pohyb pre vÅ¡etkých hrdinov. (Hľadanie cesty " "znižuje alebo odstraňuje tento postih.)" msgid "Traversable only by boat." msgstr "Prejazdné len loÄou." msgid "No special modifiers." msgstr "Žiadne zvláštne modifikátory." msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "Režim terénu" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "Slúži na kreslenie podkladovej trávy, hliny, vody atÄ. na mapu." #, fuzzy msgid "Landscape Objects Mode" msgstr "Objektový režim" #, fuzzy msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "Slúži na umiestnenie objektov (hôr, stromov, pokladov atÄ.) na mapu." msgid "Detail Mode" msgstr "Režim detailov" #, fuzzy msgid "Used for special editing of action objects." msgstr "Slúži na Å¡peciálne úpravy príšer, hrdinov a miest." #, fuzzy msgid "Adventure Objects Mode" msgstr "Možnosti hry" #, fuzzy msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "Slúži na umiestnenie objektov (hôr, stromov, pokladov atÄ.) na mapu." #, fuzzy msgid "Kingdom Objects Mode" msgstr "Objektový režim" #, fuzzy msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "Slúži na umiestnenie objektov (hôr, stromov, pokladov atÄ.) na mapu." #, fuzzy msgid "Monsters Mode" msgstr "Bojovníci" #, fuzzy msgid "Used to place monsters on the map." msgstr "" "Slúži na umiestnenie\n" "skupiny tvorov." msgid "Allows you to draw streams by clicking and dragging." msgstr "Umožňuje kresliÅ¥ toky kliknutím a Å¥ahaním." msgid "Stream Mode" msgstr "Režim tokov" msgid "Allows you to draw roads by clicking and dragging." msgstr "Umožňuje kresliÅ¥ cesty kliknutím a Å¥ahaním." msgid "Road Mode" msgstr "Cestný režim" msgid "Erase Mode" msgstr "Režim mazania" #, fuzzy msgid "Used to erase objects from the map." msgstr "Slúži na vymazanie objektov z mapy." msgid "Change between zoom and normal view." msgstr "Prepínanie medzi priblížením a normálnym zobrazením." msgid "Magnify" msgstr "ZväÄÅ¡iÅ¥" msgid "Undo" msgstr "VrátiÅ¥" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "UpraviÅ¥ názov mapy, popis a ÄalÅ¡ie vÅ¡eobecné informácie." msgid "Specifications" msgstr "Parametre" msgid "File Options" msgstr "Súborové menu" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Otvorte súborové menu, v ktorom môžete ukladaÅ¥ alebo naÄítavaÅ¥ mapy, " "prípadne ukonÄiÅ¥ prácu s editorom." msgid "View the editor system options, which let you customize the editor." msgstr "" "ZobraziÅ¥ systémové možnosti editora, ktoré umožňujú prispôsobiÅ¥ editor." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" "VytvoriÅ¥ mapu, ktorá má šírku %{size} Å¡tvorcov a výšku %{size} Å¡tvorcov." msgid "Cancel back to the New Map menu." msgstr "ZruÅ¡enie a návrat do ponuky Nová mapa." msgid "Cancel back to the main menu." msgstr "ZruÅ¡iÅ¥ a späť do hlavného menu." msgid "From Scratch" msgstr "Od nuly" msgid "Start from scratch with a blank map." msgstr "ZaÄaÅ¥ od nuly s prázdnou mapou." msgid "Create a randomly generated map." msgstr "VytvoriÅ¥ náhodne vygenerovanú mapu." msgid "Random" msgstr "Náhodná" msgid "Cancel back to the Map Editor main menu." msgstr "ZruÅ¡enie a návrat do hlavnej ponuky Editora máp." msgid "No maps available!" msgstr "Žiadne dostupné mapy!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{color} hráÄ" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{name1} a %{name2} sa stretávajú" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{color} hráÄ" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{color} hráÄ" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{name1} a %{name2} sa stretávajú" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{name1} a %{name2} sa stretávajú" #, fuzzy msgid "None." msgstr "Žiadny" #, fuzzy msgid "One side defeats another." msgstr "Prosím zvoľ ÄalÅ¡ieho hrdinu." #, fuzzy msgid "Accumulate gold." msgstr "NahromaÄ %{count} zlata." #, fuzzy msgid "Run out of time." msgstr "UkonÄiÅ¥ prácu v editore máp." #, fuzzy msgid "alliance|1st" msgstr " aliancia" #, fuzzy msgid "alliance|2nd" msgstr " aliancia" #, fuzzy msgid "alliance|3rd" msgstr " aliancia" #, fuzzy msgid "alliance|4th" msgstr " aliancia" #, fuzzy msgid "alliance|5th" msgstr " aliancia" #, fuzzy msgid "Special Loss Condition" msgstr "Podmienka prehry" #, fuzzy msgid "Special Victory Condition" msgstr "Podmienka výhry" #, fuzzy msgid "Allow standard victory conditions" msgstr "Podmienka výhry" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " aliancia" #, fuzzy msgid "{%number} alliance: " msgstr " aliancia" #, fuzzy msgid "Gold:" msgstr "Zlato" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Vyber mesto, do ktorého sa chceÅ¡ preniesÅ¥." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Klikni pre uloženie terajÅ¡ej hry." #, fuzzy msgid "Map Difficulty" msgstr "" "ObtiažnosÅ¥\n" "mapy" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "Umiestnenie: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Zvolený opis" #, fuzzy msgid "Click to accept the changes made." msgstr "Kliknutím zobraz ÄalÅ¡ie mesto." #, fuzzy msgid "Click to edit custom rumors." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Klikni pre výber zvoleného rozlíšenia." #, fuzzy msgid "Events" msgstr "UdalosÅ¥" #, fuzzy msgid "Click to change the language of the map." msgstr "Zmeň jazyk hry." #, fuzzy msgid "Click to change your map name." msgstr "Kliknutím zobraz ÄalÅ¡ie mesto." #, fuzzy msgid "Map Name" msgstr "VeľkosÅ¥ mapy" #, fuzzy msgid "Click to change the description of the current map." msgstr "Opis aktuálne zvolenej mapy." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Opis aktuálne zvolenej mapy." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Opis aktuálne zvolenej mapy." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Typ mapy" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "ObtiažnosÅ¥ mapy aktuálne vybranej mapy. ObtiažnosÅ¥ mapy urÄuje tvorca " "scenára. Ťažšie mapy môžu obsahovaÅ¥ viac alebo silnejších nepriateľov, menej " "zdrojov alebo iné Å¡peciálne podmienky, ktoré sÅ¥ažujú situáciu pre ľudského " "hráÄa." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Zvoľ poÄet - %{resource}:" #, fuzzy msgid "Animation" msgstr "Anexia" #, fuzzy msgid "Passability" msgstr "OsobnosÅ¥:" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "DodatoÄné programovanie" msgid "Edit Rumor" msgstr "" #, fuzzy msgid "Edit an existing rumor." msgstr "NaÄítaÅ¥ existujúcu mapu." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "NaÄítaÅ¥ existujúcu mapu." msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Umiestnenie: " #, fuzzy msgid "Save Map:" msgstr "Ulož mapu" #, fuzzy msgid "Click to save the current map." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Klikni pre uloženie terajÅ¡ej hry." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Ľahká" msgid "difficulty|Normal" msgstr "Normálna" msgid "difficulty|Hard" msgstr "Ťažká" msgid "difficulty|Expert" msgstr "Expertná" msgid "difficulty|Impossible" msgstr "Nemožná" msgid "and more..." msgstr "a viac..." msgid "Easy" msgstr "Ľahká" msgid "Normal" msgstr "Normálna" msgid "Hard" msgstr "Ťažká" msgid "Campaign Difficulty" msgstr "ObtiažnosÅ¥ kampane" #, fuzzy msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Zvoľ túto obtiažnosÅ¥ pokiaľ preferujeÅ¡ príbeh nad výzvou. PoÄítaÄ je slabší " "v porovnaní s normálnou obtiažnosÅ¥ou." #, fuzzy msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "Zvoľ túto obtiažnosÅ¥ pre pôžitok z pôvodne mieneného návrhu." #, fuzzy msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Zvoľ túto obtiažnosÅ¥ pokiaľ chceÅ¡ výzvu. PoÄítaÄ je silnejší v porovnaní s " "normálnou obtiažnosÅ¥ou." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Gratulujem!\n" "\n" "PoÄet dní: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "ObtiažnosÅ¥: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Skóre: %{score}\n" "\n" "HodnosÅ¥:\n" "%{rating}" msgid "Start the selected scenario." msgstr "ZaÄni zvolený scenár." msgid "View Intro" msgstr "Ukáž intro" #, fuzzy msgid "View the intro video for the current state of the campaign." msgstr "Ukáž intro video pre terajší stav kampane." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "Zvoľ obtiažnosÅ¥ kampane. Neskôr sa bude daÅ¥ kedykoľvek znížiÅ¥." msgid "Restart the current scenario." msgstr "ZaÄni terajší scenár od zaÄiatku." msgid "Difficulty" msgstr "ObtiažnosÅ¥" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "V kampani prechádzaÅ¡ na nižšiu obtiažnosÅ¥. Po tomto bode to už nebudete môcÅ¥ " "vrátiÅ¥ späť. NajlepÅ¡ie skóre sa vypoÄíta výluÄne na základe novej " "obtiažnosti. ChceÅ¡ pokraÄovaÅ¥?" msgid "Are you sure you want to restart this scenario?" msgstr "UrÄite chceÅ¡ zaÄaÅ¥ terajší scenár od zaÄiatku?" msgid "Campaign Scenario loading failure" msgstr "Chyba pri nahrávaní scenára kampane" msgid "Please make sure that campaign files are correct and present." msgstr "Uisti sa, že súbory kampane sú správne a sú prítomné." msgid "Days spent" msgstr "Strávené dni" msgid "The number of days spent on this campaign." msgstr "PoÄet dní strávených na tejto kampani." msgid "Project Coordination and Core Development" msgstr "Koordinácia projektu a hlavný vývoj" msgid "Development" msgstr "Vývoj" msgid "Visit us at " msgstr "NavÅ¡tív nás na " msgid "QA and Support" msgstr "ZabezpeÄenie kvality a podpora" msgid "Dev and Support" msgstr "Vývoj a podpora" msgid "Special Thanks to" msgstr "Å peciálne poÄakovanie pre" #, fuzzy msgid "and many-many other contributors and supporters!" msgstr "a mnoho Äalších podporovateľov!" msgid "Support us at" msgstr "Prispej na" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Spoj sa s nami na" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "PotrebujeÅ¡ pomoc s hrou?" msgid "Original project before 0.7" msgstr "Originálny projekt pred 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Heroes of Might and Magic II: The Succession Wars tím" msgid "Designed and Directed" msgstr "Navrhnuté a režírované" msgid "Programming and Design" msgstr "Programovanie a dizajn" msgid "Executive Producer" msgstr "Výkonný producent" msgid "Producer" msgstr "Producent" msgid "Additional Design" msgstr "DodatoÄný dizajn" msgid "Additional Programming" msgstr "DodatoÄné programovanie" msgid "Musical Production" msgstr "Hudobná produkcia" msgid "Music and Sound Design" msgstr "Hudobný a zvukový dizajn" msgid "Vocalists" msgstr "Vokalisti" msgid "Art Director" msgstr "Réžia umenia" msgid "Assistant Art Director" msgstr "Asistent réžii umenia" msgid "Artists" msgstr "Umelci" msgid "QA Manager" msgstr "Manažér zabezpeÄenia kvality" msgid "QA" msgstr "ZabezpeÄenie kvality" msgid "Writing" msgstr "Písanie" msgid "Manual and Helpfile" msgstr "Manuál a súbor pomoci" msgid "Scenarios" msgstr "Scenáre" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Heroes of Might and Magic II: The Price of Loyalty tím" msgid "Design Lead" msgstr "Vedenie dizajnu" msgid "Designers" msgstr "Dizajnéri" msgid "Programming Lead" msgstr "Vedenie programovania" msgid "Art Lead" msgstr "Vedenie umenia" msgid "Playtesters" msgstr "Testovanie hry" msgid "Designer" msgstr "Dizajnér" msgid "Producers" msgstr "Producenti" msgid "QA Managers" msgstr "Manažéri zabezpeÄenia kvality" msgid "Sound Design" msgstr "Zvukový dizajn" msgid "Town Themes" msgstr "Hudba miest" msgid "Alto Sax" msgstr "Alto Saxofón" msgid "Harpsichord and Piano" msgstr "ÄŒembalo a klavír" msgid "Basso Vocal" msgstr "Basso spev" msgid "Soprano Vocal" msgstr "Sopránový spev" msgid "Recorded at %{recordingStudio}" msgstr "Nahrané v %{recordingStudio}" msgid "credits|Manual" msgstr "Manuál" msgid "German Consultant" msgstr "Nemecký konzultant" msgid "Map Designers" msgstr "Návrhári máp" msgid "Package Design" msgstr "Dizajn balíkov" msgid "High Scores" msgstr "Najvyššie skóre" msgid "Your Name" msgstr "Tvoje meno" msgid "Unknown Hero" msgstr "Neznámy hrdina" msgid "Standard" msgstr "Å tandard" msgid "View High Scores for Standard Maps." msgstr "Zobraz najvyššie skóre pre Å¡tandardné mapy." msgid "Campaign" msgstr "Kampaň" msgid "View High Scores for Campaigns." msgstr "Zobraz najvyššie skóre pre kampane." msgid "hotkey|default okay event" msgstr "predvolené ok" msgid "hotkey|default cancel event" msgstr "predvolené zruÅ¡" msgid "hotkey|default left" msgstr "predvolené vľavo" msgid "hotkey|default right" msgstr "predvolené vpravo" msgid "hotkey|default up" msgstr "predvolené hore" msgid "hotkey|default down" msgstr "predvolené dole" msgid "hotkey|toggle fullscreen" msgstr "prepni celú obrazovku" msgid "hotkey|toggle text support mode" msgstr "prepni mód podpory textu" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "prepni mód podpory textu" msgid "hotkey|new game" msgstr "nová hra" msgid "hotkey|load game" msgstr "nahraj hru" #, fuzzy msgid "hotkey|high scores" msgstr "najvyššie skóre" msgid "hotkey|credits" msgstr "zásluhy" msgid "hotkey|standard game" msgstr "bežná hra" msgid "hotkey|campaign game" msgstr "kampaň" msgid "hotkey|multi-player game" msgstr "hra viacero hráÄov" msgid "hotkey|settings" msgstr "nastavenie" msgid "hotkey|quit" msgstr "ukonÄi" msgid "hotkey|select map" msgstr "zvoľ mapu" msgid "hotkey|select small map size" msgstr "zvoľ mapy veľkosti malá" msgid "hotkey|select medium map size" msgstr "zvoľ mapy veľkosti stredná" msgid "hotkey|select large map size" msgstr "zvoľ mapy veľkosti veľká" msgid "hotkey|select extra large map size" msgstr "zvoľ mapy veľkosti extra veľká" msgid "hotkey|select all map sizes" msgstr "zvoľ mapy vÅ¡etkých veľkostí" #, fuzzy msgid "hotkey|hot seat game" msgstr "horúce kreslo" msgid "hotkey|battle only game" msgstr "rýchly boj" msgid "hotkey|choose the original campaign" msgstr "zvoľ pôvodnú kampaň" msgid "hotkey|choose the expansion campaign" msgstr "zvoľ rozšírenú kampaň" msgid "hotkey|map editor main menu" msgstr "hlavné menu editora" msgid "hotkey|new map menu" msgstr "nová mapa" msgid "hotkey|load map menu" msgstr "nahraj mapu" msgid "hotkey|new map from scratch" msgstr "nová mapa, od nuly" msgid "hotkey|new random map" msgstr "nová mapa, náhodná" #, fuzzy msgid "hotkey|undo last action" msgstr "predvolená ÄinnosÅ¥" #, fuzzy msgid "hotkey|redo last action" msgstr "predvolená ÄinnosÅ¥" #, fuzzy msgid "hotkey|open game main menu" msgstr "nová mapa" #, fuzzy msgid "hotkey|toggle passability" msgstr "prepni status" msgid "hotkey|roland campaign" msgstr "kampaň roland" msgid "hotkey|archibald campaign" msgstr "kampaň archibald" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "kampaň cena vernosti" msgid "hotkey|voyage home campaign" msgstr "kampaň plavba domov" msgid "hotkey|wizard's isle campaign" msgstr "kampaň Äarodejov ostrov" msgid "hotkey|descendants campaign" msgstr "kampaň potomkovia" msgid "hotkey|select first campaign bonus" msgstr "zvoľ prvý bonus kampane" msgid "hotkey|select second campaign bonus" msgstr "zvoľ druhý bonus kampane" msgid "hotkey|select third campaign bonus" msgstr "zvoľ tretí bonus kampane" msgid "hotkey|view campaign intro" msgstr "ukáž intro kampane" msgid "hotkey|select campaign difficulty" msgstr "zvoľ obtiažnosÅ¥ kampane" msgid "hotkey|restart campaign scenario" msgstr "reÅ¡tartuj scenár kampane" msgid "hotkey|world map left" msgstr "mapa vľavo" msgid "hotkey|world map right" msgstr "mapa vpravo" msgid "hotkey|world map up" msgstr "mapa hore" msgid "hotkey|world map down" msgstr "mapa dole" msgid "hotkey|world map up left" msgstr "mapa vľavo hore" msgid "hotkey|world map up right" msgstr "mapa vpravo hore" msgid "hotkey|world map down left" msgstr "mapa vľavo dole" msgid "hotkey|world map down right" msgstr "mapa vpravo dole" msgid "hotkey|save game" msgstr "ulož hru" msgid "hotkey|next hero" msgstr "Äalší hrdina" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "Äalší hrdina" #, fuzzy msgid "hotkey|start hero movement" msgstr "pokraÄuj v pohybe hrdinom" msgid "hotkey|cast adventure spell" msgstr "vyÄaruj výpravné kúzlo" msgid "hotkey|put hero to sleep" msgstr "uspi hrdinu" msgid "hotkey|next town" msgstr "ÄalÅ¡ie mesto" msgid "hotkey|end turn" msgstr "ukonÄi kolo" msgid "hotkey|file options" msgstr "súborové menu" msgid "hotkey|adventure options" msgstr "možnosti výpravy" msgid "hotkey|puzzle map" msgstr "mapa rébusu" msgid "hotkey|scenario information" msgstr "informácie o scenári" msgid "hotkey|dig for artifact" msgstr "kop za artefaktom" msgid "hotkey|view world" msgstr "ukáž svet" msgid "hotkey|kingdom summary" msgstr "súhrn kráľovstva" msgid "hotkey|default action" msgstr "predvolená ÄinnosÅ¥" msgid "hotkey|open focus" msgstr "otvor zaostrenie" msgid "hotkey|system options" msgstr "systémové možnosti" msgid "hotkey|scroll left" msgstr "posun naľavo" msgid "hotkey|scroll right" msgstr "posun napravo" msgid "hotkey|scroll up" msgstr "posun nahor" msgid "hotkey|scroll down" msgstr "posun nadol" msgid "hotkey|toggle control panel" msgstr "prepni kontrolný panel" msgid "hotkey|toggle radar" msgstr "prepni radar" msgid "hotkey|toggle buttons" msgstr "prepni klávesy" msgid "hotkey|toggle status" msgstr "prepni status" msgid "hotkey|toggle icons" msgstr "prepni ikony" msgid "hotkey|transfer control to ai" msgstr "presuň kontrolu poÄítaÄu" msgid "hotkey|retreat from battle" msgstr "uteÄ z boja" msgid "hotkey|surrender during battle" msgstr "vzdaj sa poÄas boja" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "prepni boj do automatického módu" #, fuzzy msgid "hotkey|quick combat" msgstr "ukonÄi" msgid "hotkey|battle options" msgstr "možnosti boja" msgid "hotkey|skip turn in battle" msgstr "preskoÄ kolo v boji" msgid "hotkey|cast battle spell" msgstr "vyÄaruj bojové kúzlo" msgid "hotkey|dwelling level 1" msgstr "obydlie úrovne 1" msgid "hotkey|dwelling level 2" msgstr "obydlie úrovne 2" msgid "hotkey|dwelling level 3" msgstr "obydlie úrovne 3" msgid "hotkey|dwelling level 4" msgstr "obydlie úrovne 4" msgid "hotkey|dwelling level 5" msgstr "obydlie úrovne 5" msgid "hotkey|dwelling level 6" msgstr "obydlie úrovne 6" msgid "hotkey|well" msgstr "studňa" msgid "hotkey|marketplace" msgstr "trhovisko" msgid "hotkey|mage guild" msgstr "cech mágov" msgid "hotkey|shipyard" msgstr "lodenica" msgid "hotkey|thieves guild" msgstr "cech zlodejov" msgid "hotkey|tavern" msgstr "krÄma" msgid "hotkey|construction screen" msgstr "okno stavania" msgid "hotkey|buy all monsters in well" msgstr "kúp vÅ¡etkých v studni" msgid "hotkey|split stack by half" msgstr "rozdeľ skupinu na polovicu" msgid "hotkey|split stack by one" msgstr "rozdeľ skupinu po jednom" msgid "hotkey|join stacks" msgstr "zlÃºÄ skupinu" msgid "hotkey|upgrade troop" msgstr "povýš jednotku" msgid "hotkey|dismiss hero or troop" msgstr "prepusti jednotku alebo hrdinu" #, fuzzy msgid "hotkey|exchange all troops" msgstr "povýš jednotku" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "ChceÅ¡ prevziaÅ¥ kontrolu nad hráÄom? Efekt sa prejaví v ÄalÅ¡om kole." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "ChceÅ¡ preniesÅ¥ kontrolu z teba na umelú inteligenciu? ÚÄinok sa prejaví až " "od ÄalÅ¡ieho kola." #, fuzzy msgid "Default Actions" msgstr "predvolená ÄinnosÅ¥" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "Mapa sveta" #, fuzzy msgid "Battle Screen" msgstr "Okno hrdinu" #, fuzzy msgid "Town Screen" msgstr "Okno hrdinu" msgid "Army Actions" msgstr "" msgid "The save file is corrupted." msgstr "Uložený súbor je poÅ¡kodený." msgid "Unsupported save format: " msgstr "Nepodporovaný formát uloženia: " msgid "Current game version: " msgstr "Aktuálna verzia hry: " msgid "Last supported version: " msgstr "Posledná podporovaná verzia: " msgid "This file contains a save with an invalid game type." msgstr "Tento súbor obsahuje uloženie s neplatným typom hry." #, fuzzy msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Tento súbor bol uložený pre mapu pre \"The Price of Loyalty\", ale prísluÅ¡né " "herné prostriedky neboli enginu poskytnuté." msgid "This saved game is localized to '" msgstr "Táto uložená hra je zlokalizovaná na jazyk '" msgid "' language, but the current language of the game is '" msgstr "', ale aktuálny jazyk hry je '" msgid "No save files to load." msgstr "Žiadne uložené hry." msgid "Hot Seat" msgstr "Horúce kreslo" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Zahrajte si hru Horúce kreslo, v ktorej 2 až 6 hráÄi hrajú pri tom istom " "poÄítaÄi a keÄ sú na rade, prepnú sa do \"horúceho kresla\"." msgid "A single player game playing out a single map." msgstr "Hra pre jedného hráÄa na jednej mape." msgid "Standard Game" msgstr "Bežná hra" msgid "A single player game playing through a series of maps." msgstr "Hra pre jedného hráÄa so sériou máp." msgid "Campaign Game" msgstr "Kampaň" msgid "Multi-Player Game" msgstr "Hra viacero hráÄov" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Hra pre viacerých hráÄov, v ktorej proti sebe na jednej mape nastupuje " "niekoľko ľudských hráÄov." msgid "fheroes2 Resurrection Team presents" msgstr "Tím fheroes2 Resurrection uvádza" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "Vitaj v hre Heroes of Might and Magic II poháňanej enginom fheroes2!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Vitaj v hre Heroes of Might and Magic II poháňanej enginom fheroes2! Pred " "spustením hry si vyber rozlíšenie." msgid "Greetings!" msgstr "Zdravím Å¥a!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "UkonÄiÅ¥ hru Heroes of Might and Magic II a vrátiÅ¥ sa do operaÄného systému." msgid "Credits" msgstr "Zásluhy" msgid "View the credits screen." msgstr "Zobrazenie obrazovky so zásluhami." msgid "View the high scores screen." msgstr "Zobrazenie obrazovky s najvyššími výsledkami." #, fuzzy msgid "Create new or modify existing maps." msgstr "NaÄítaÅ¥ existujúcu mapu." msgid "Change language, resolution and settings of the game." msgstr "Zmena jazyka, rozlíšenia a nastavení hry." msgid "Game Settings" msgstr "Nastavenie hry" #, fuzzy msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Chýbajú požadované video súbory pre okno výberu kampane. Uisti sa prosím, že " "máš v systéme vÅ¡etky potrebné súbory." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "BuÄ Rolandova, alebo Archibaldova kampaň z pôvodnej hry Heroes of Might and " "Magic II." msgid "Original Campaign" msgstr "Pôvodná kampaň" msgid "Expansion Campaign" msgstr "Kampaň expanzie" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "Jedna zo Å¡tyroch nových kampaní z rozÅ¡irujúcej sady Price of Loyalty." msgid "Loading video. Please wait..." msgstr "NaÄítanie videa. Chvíľku vydrž, prosím..." msgid "Host" msgstr "Hostiteľ" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Hostiteľ nastaví možnosti hry. V jednej sieÅ¥ovej hre môže byÅ¥ len jeden " "hostiteľ." msgid "Guest" msgstr "HosÅ¥" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "HosÅ¥ poÄká, kým hostiteľ nastaví hru, a potom sa automaticky pridá do hry. " "Pri hrách cez TCP/IP môže byÅ¥ viacero hostí." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" #, fuzzy msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Hra pre viacerých hráÄov, v ktorej proti sebe na jednej mape nastupuje " "niekoľko ľudských hráÄov." msgid "Battle Only" msgstr "Rýchly boj" msgid "Setup and play a battle without loading any map." msgstr "NastaviÅ¥ a hraÅ¥ bitku bez naÄítania mapy." #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Zahrajte si hru Horúce kreslo, v ktorej 2 až 6 hráÄi hrajú pri tom istom " "poÄítaÄi a keÄ sú na rade, prepnú sa do \"horúceho kresla\"." msgid "2 Players" msgstr "2 hráÄi" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Hraj s 2 ľudskými hráÄmi a prípadne až so 4 Äalšími poÄítaÄovými hráÄmi." msgid "3 Players" msgstr "3 hráÄi" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Hraj s 3 ľudskými hráÄmi a prípadne až s 3 Äalšími poÄítaÄovými hráÄmi." msgid "4 Players" msgstr "4 hráÄi" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Hraj so 4 ľudskými hráÄmi a prípadne až s 2 Äalšími poÄítaÄovými hráÄmi." msgid "5 Players" msgstr "5 hráÄov" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "Hraj s 5 ľudskými hráÄmi a prípadne až s 1 Äalším poÄítaÄovým hráÄom." msgid "6 Players" msgstr "6 hráÄov" msgid "Play with 6 human players." msgstr "Hraj so 6 hráÄmi." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "DraÄie mesto padlo! Teraz si Majstrom drakov." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Dobyl/a si %{name}!\n" "Víťazíš." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Zajal/a si nepriateľského hrdinu %{name}!\n" "Tvoja úloha je splnená." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Podarilo sa ti nájsÅ¥ %{name}.\n" "Tvoja úloha je splnená." msgid "Ultimate Artifact" msgstr "Ultimátny artefakt" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Nepriateľ je porazený.\n" "Tvoja strana zvíťazila!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Vo svojej pokladnici si nahromadil viac ako %{count} zlata.\n" "VÅ¡etci nepriatelia sa skláňajú pred tvojím bohatstvom a mocou." msgid "Victory!" msgstr "Víťazstvo!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Nepriateľ obsadil %{name}!\n" "Triumfálne zvíťazili." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Nepriateľ si vo svojej pokladnici nahromadil viac ako %{count} zlata.\n" "Musíš sa porazene skloniÅ¥ pred jeho bohatstvom a mocou." msgid "You have been eliminated from the game!!!" msgstr "Bol/a si eliminovaný/á z hry!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Hrdina %{name} bol stratený.\n" "Tvoja výprava sa skonÄila." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Nepodarilo sa ti vÄas dokonÄiÅ¥ úlohu.\n" "VÅ¡etko je stratené." msgid "Defeat!" msgstr "Porážka!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Základné skóre: %{score}\n" "ObtiažnosÅ¥: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Poraz vÅ¡etkých nepriateľských hrdinov a získaj vÅ¡etky nepriateľské mestá a " "hrady." msgid "Your side defeats the opposing side." msgstr "Tvoja strana porazí opozíciu." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Vyprší ti Äas. (Nevyhráš do urÄitého bodu)." msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Musíš poraziÅ¥ nepriateľa: %{enemies}." msgstr[1] "Musíš poraziÅ¥ nepriateľskú alianciu: %{enemies}." msgstr[2] "Musíš poraziÅ¥ nepriateľskú alianciu: %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Aliancia pozostávajúca z %{allies} a teba musí poraziÅ¥ nepriateľa %{enemies}." msgstr[1] "" "Aliancia pozostávajúca z %{allies} a teba musí poraziÅ¥ alianciu z %{enemies}." msgstr[2] "" "Aliancia pozostávajúca z %{allies} a teba musí poraziÅ¥ alianciu z %{enemies}." msgid "Capture the castle '%{name}'." msgstr "ObsaÄ hrad '%{name}'." msgid "Capture the town '%{name}'." msgstr "ObsaÄ mesto '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Poraz hrdinu '%{name}'." msgid "Find the ultimate artifact." msgstr "Nájdi ultimátny artefakt." msgid "Find the '%{name}' artifact." msgstr "Nájdi artefakt '%{name}'." msgid "Accumulate %{count} gold." msgstr "NahromaÄ %{count} zlata." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" "alebo môžeÅ¡ vyhraÅ¥, ak porazíš vÅ¡etkých nepriateľských hrdinov a dobyjeÅ¡ " "vÅ¡etky nepriateľské mestá a hrady." msgid "Lose the castle '%{name}'." msgstr "Stratíš hrad '%{name}'." msgid "Lose the town '%{name}'." msgstr "Stratíš mesto '%{name}'." msgid "Lose the hero: %{name}." msgstr "Stratíš hrdinu '%{name}'." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Nepodarí sa ti vyhraÅ¥ do konca %{month}. mesiaca, %{week}. týždňa a %{day}. " "dňa." msgid "%{color} player has been vanquished!" msgstr "%{color} hrÃ¡Ä bol porazený!" msgid "Major Event!" msgstr "Významná udalosÅ¥!" msgid "Scenario:" msgstr "Scenár:" msgid "Game Difficulty:" msgstr "ObtiažnosÅ¥ hry:" msgid "Opponents:" msgstr "Súperi:" msgid "Class:" msgstr "Trieda:" msgid "Rating %{rating}%" msgstr "Hodnotenie: %{rating}%" msgid "Click here to select which scenario to play." msgstr "Klikni sem a vyber scenár, ktorý chceÅ¡ hraÅ¥." msgid "Scenario" msgstr "Scenár" msgid "Game Difficulty" msgstr "ObtiažnosÅ¥ hry" #, fuzzy msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Tu si môžeÅ¡ zmeniÅ¥ poÄiatoÄnú obtiažnosÅ¥, s ktorou budeÅ¡ hraÅ¥. Pri vyšších " "úrovniach obtiažnosti zaÄneÅ¡ s menším množstvom zdrojov a pri vyšších " "nastaveniach dostane ÄalÅ¡ie zdroje poÄítaÄ." msgid "Difficulty Rating" msgstr "Hodnotenie obtiažnosti" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Hodnotenie obtiažnosti odráža kombináciu rôznych nastavení pre tvoju hru. " "Toto Äíslo sa použije na tvoje koneÄné skóre." msgid "Click to accept these settings and start a new game." msgstr "Kliknutím akceptujeÅ¡ tieto nastavenia a spustíš novú hru." msgid "Click to return to the main menu." msgstr "Kliknutím sa vrátiÅ¡ do hlavnej ponuky." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Astrológovia vyhlasujú mesiac %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Astrológovia vyhlasujú týždeň %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "%{monster} budú maÅ¥ po bežnom raste dvojnásobnú populáciu!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "%{monster} budú maÅ¥ po bežnom raste nárast o %{count} percento!" msgstr[1] "%{monster} budú maÅ¥ po bežnom raste nárast o %{count} percentá!" msgstr[2] "%{monster} budú maÅ¥ po bežnom raste nárast o %{count} percent!" msgid "%{monster} growth +%{count}." msgstr "%{monster} vzrástli o %{count}." msgid " All populations are halved." msgstr " VÅ¡etky populácie sú znížené na polovicu." msgid " All dwellings increase population." msgstr " VÅ¡etky obydlia zvyÅ¡ujú poÄet obyvateľov." msgid "New Month!" msgstr "Nový mesiac!" msgid "New Week!" msgstr "Nový týždeň!" msgid "Beware!" msgstr "Pozor!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} hráÄ, toto je tvoj posledný deň na dobytie mesta, inak budeÅ¡ " "vyhnaný z tejto krajiny." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} hráÄ, máš už len %{day} dni na dobytie mesta, inak budeÅ¡ vyhostený " "z tejto krajiny." msgid "%{color} player's turn." msgstr "%{color} hrÃ¡Ä je na Å¥ahu." #, fuzzy msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} hráÄ, stratil si svoje posledné mesto. Ak v nasledujúcom týždni " "nedobyjeÅ¡ ÄalÅ¡ie mesto, budeÅ¡ eliminovaný." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} hráÄ, tvoji hrdinovia Å¥a opustili a ty si vyhostený z tejto krajiny." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "ÄŽalší hrdina" msgid "Select the next Hero." msgstr "VybraÅ¥ ÄalÅ¡ieho Hrdinu." #, fuzzy msgid "Hero Movement" msgstr "Tieň pohybu" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "Zhrnutie kráľovstva" #, fuzzy msgid "View a summary of your Kingdom." msgstr "Pozri si prehľad svojho kráľovstva." msgid "Cast an adventure spell." msgstr "ZoslaÅ¥ kúzlo." msgid "End Turn" msgstr "UkonÄiÅ¥ Å¥ah" #, fuzzy msgid "End your turn and let the computer take its turn." msgstr "UkonÄi svoj Å¥ah a nechaj tiahnuÅ¥ poÄítaÄ." msgid "Adventure Options" msgstr "Možnosti hry" msgid "Bring up the adventure options menu." msgstr "ZobraziÅ¥ menu dobrodružstva." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "ZobraziÅ¥ voľby pre uloženie a naÄítanie hry, spustenie novej hry alebo " "ukonÄenie hry." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "ZobraziÅ¥ ponuku systémových možností, ktorá umožňuje prispôsobiÅ¥ si hru." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Jeden alebo viac hrdinov sa eÅ¡te môže pohnúť, naozaj chceÅ¡ ukonÄiÅ¥ svoj Å¥ah?" msgid "Are you sure you want to quit?" msgstr "UrÄite chceÅ¡ skonÄiÅ¥?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "UrÄite chceÅ¡ reÅ¡tartovaÅ¥ hru? (Tvoja aktuálna hra sa stratí.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Naozaj chceÅ¡ prepísaÅ¥ uložený súbor s týmto názvom?" msgid "Game saved successfully." msgstr "Hra bola úspeÅ¡ne uložená." msgid "There was an issue during saving." msgstr "Pri ukladaní nastal problém." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "UrÄite chceÅ¡ naÄítaÅ¥ novú hru? (Tvoja aktuálna hra sa stratí.)" msgid "Try looking on land!!!" msgstr "Skús hľadaÅ¥ na súši!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Hľadanie ultimátneho artefaktu je márne. Tvoj hrdina by ho nemohol nosiÅ¥, " "ani keby ho naÅ¡iel - vÅ¡etky jeho sloty na artefakty sú plné." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Kopanie artefaktov si vyžaduje celý deň, skús to zajtra." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Po mnohých hodinách strávených kopaním na tomto mieste odkrývaÅ¡ %{artifact}." msgid "Congratulations!" msgstr "Gratulujem!" msgid "Nothing here. Where could it be?" msgstr "Tu niÄ nie je. Kde by to mohlo byÅ¥?" msgid "Try searching on clear ground." msgstr "Skús hľadaÅ¥ na Äistom teréne." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Miniatúrny pohľad na známy svet. Kliknutím ľavým tlaÄidlom myÅ¡i presunieÅ¡ " "oblasÅ¥ zobrazenia." msgid "Month: %{month} Week: %{week}" msgstr "Mesiac: %{month} Týždeň: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "NachádzaÅ¡ malé\n" "množstvo: %{resource}." msgid "Status Window" msgstr "Stavové okno" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Toto okno poskytuje informácie o stave tvojho hrdinu alebo kráľovstva a " "zobrazuje dátum." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Toto okno poskytuje informácie o stave tvojho hrdinu alebo kráľovstva a " "zobrazuje dátum. Kliknutím ľavým tlaÄidlom myÅ¡i tu môžeÅ¡ prechádzaÅ¥ týmito " "oknami." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Tu môžeÅ¡ meniÅ¥ poÄiatoÄné pozície a farby hráÄov. UrÄitá farba bude vždy " "zaÄínaÅ¥ na urÄitom mieste. Niektoré pozície môže hraÅ¥ iba poÄítaÄový hrÃ¡Ä " "alebo iba ľudský hráÄ." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Toto ti umožní zmeniÅ¥ triedu hráÄa. Triedy nie je vždy možné meniÅ¥. V " "závislosti od scenára môže hrÃ¡Ä získaÅ¥ ÄalÅ¡ie mestá a/alebo hrdinov, ktorí " "nepatria do jeho primárnej línie." msgid "Handicap" msgstr "Hendikep" # #, fuzzy msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Tu je možné zmeniÅ¥ hendikep konkrétneho hráÄa. Hendikep môžu maÅ¥ len ľudia. " "Hendikepovaní hráÄi zaÄínajú s menším množstvom zdrojov a získavajú o 15, " "resp. 30% menej zdrojov za Å¥ah v prípade mierneho a Å¥ažkého hendikepu." msgid "%{color} player" msgstr "%{color} hráÄ" msgid "No Handicap" msgstr "Bez hendikepu" #, fuzzy msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Žiadne osobitné obmedzenia týkajúce sa poÄiatoÄných zdrojov a ich získavania " "za Å¥ah." msgid "Mild Handicap" msgstr "Mierny hendikep" # #, fuzzy msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "HráÄi s miernym hendikepom zaÄínajú s menším poÄtom zdrojov a získavajú o " "15% menej zdrojov za Å¥ah." msgid "Severe Handicap" msgstr "Ťažký hendikep" # #, fuzzy msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "HráÄi s Å¥ažkým hendikepom zaÄínajú s menším poÄtom zdrojov a získavajú o 30% " "menej zdrojov za Å¥ah." msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Zvoľ zruÄnosÅ¥ útoku" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Zobraz info: %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Obrana" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "MEDZERNÃK" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Príjmy kráľovstva" msgid "Kingdom Income per day." msgstr "Denné príjmy kráľovstva." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "Za každý kontrolovaný maják sa tvoje lode každý deň dostanú Äalej." msgid "English" msgstr "Anglicky" msgid "French" msgstr "Francúzsky" msgid "Polish" msgstr "Poľsky" msgid "German" msgstr "Nemecky" msgid "Russian" msgstr "Rusky" msgid "Italian" msgstr "Taliansky" msgid "Czech" msgstr "ÄŒesky" msgid "Norwegian" msgstr "Nórsky" msgid "Belarusian" msgstr "Bielorusky" msgid "Bulgarian" msgstr "Bulharsky" msgid "Ukrainian" msgstr "Ukrajinsky" msgid "Romanian" msgstr "Rumunsky" msgid "Spanish" msgstr "Å panielsky" msgid "Swedish" msgstr "Å védsky" msgid "Portuguese" msgstr "Portugalsky" msgid "Turkish" msgstr "Turecky" msgid "Dutch" msgstr "Holandsky" msgid "Hungarian" msgstr "MaÄarsky" msgid "Danish" msgstr "Dánsky" msgid "Slovak" msgstr "Slovensky" msgid "Vietnamese" msgstr "Vietnamsky" msgid "Slow" msgstr "Pomalá" msgid "Fast" msgstr "Rýchla" msgid "Very Fast" msgstr "Veľmi rýchla" msgid "Evil" msgstr "Zlo" msgid "Good" msgstr "Dobro" msgid ", FPS: " msgstr ", FPS: " #, fuzzy msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} vykradnutý" #, fuzzy msgid "pyramid|%{object} raided" msgstr "%{object} vyplienená" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitri" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezabel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Zafíra" msgid "Natasha" msgstr "NataÅ¡a" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Sestra Eliza" msgid "Brother Brax" msgstr "Brat Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " dáva maximálnu morálku" msgid " gives you maximum luck" msgstr " dáva maximálne šťastie" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Kniha kúziel sa nedá presunúť" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Tento artefakt nemôžeÅ¡ zdvihnúť, už máš plný náklad!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Ak chceÅ¡ zosielaÅ¥ kúzla, musíš si najprv kúpiÅ¥ Knihu kúziel za %{gold} zlata." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Nanešťastie sa zdá, že momentálne nemáš dostatok hotovosti." msgid "Do you wish to buy one?" msgstr "ChceÅ¡ si jednu kúpiÅ¥?" msgid "%{count} / day" msgstr "%{count} / deň" msgid "one" msgstr "1" msgid "two" msgstr "2" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "Tvoju loÄ pohlcuje vír. ÄŒasÅ¥ tvojej armády padá cez palubu." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Bojovníci, urazení tvojím odmietnutím ich ponuky, zaútoÄia!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "%{monster} sa zaÄnú rozptyľovaÅ¥, ohromení silou tvojich vojsk.\n" "ChceÅ¡ ich prenasledovaÅ¥ a bojovaÅ¥ s nimi?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "Pri plienení nepriateľského tábora objavíš skrytú skrýšu s pokladmi." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Správca mlyna oznamuje:\n" "\"Milord, pracoval som veľmi tvrdo, aby som vám poskytol tieto suroviny, " "príÄte si na budúci týždeň pre ÄalÅ¡ie.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Správca mlyna oznamuje:\n" "\"Milord, je mi ľúto, ale momentálne nemáme k dispozícii žiadne zdroje. " "Prosím, skúste to znova budúci týždeň.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Správca mlyna oznamuje:\n" "\"Milord, pracoval som veľmi tvrdo, aby som vám zabezpeÄil toto zlato, " "príÄte si na budúci týždeň po ÄalÅ¡ie.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Správca mlyna oznamuje:\n" "\" Milord, je mi ľúto, ale momentálne nie je k dispozícii žiadne zlato. " "Prosím, skúste to znova o týždeň.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "NachádzaÅ¡ opustený prístreÅ¡ok.\n" "KeÄ sa okolo neho obzeráš, objavíš nejaké suroviny ukryté neÄaleko." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "PrístreÅ¡ok je už dávno opustený. Nenachádza sa tu niÄ cenné." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Prichytíš leprikóna, ktorý nerozumne zaspal uprostred skupinky Äarovných " "húb.\n" "Výmenou za svoju slobodu Å¥a dovedie k malému hrncu plného vzácnych vecí." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "NachádzaÅ¡ Äarovnú záhradu, v ktorej sa radi preháňajú leprikóny a víly, ale " "dnes tu nikto nie je.\n" "Možno bude lepÅ¡ie skúsiÅ¥ to znova na budúci týždeň." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Narazíš na pozostatky nešťastného dobrodruha." msgid "Treasure" msgstr "Poklad" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Pri prehľadávaní roztrhaného obleÄenia nájdeÅ¡ %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Pri prehľadávaní roztrhaného obleÄenia niÄ nenachádzaÅ¡." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Narazíš na starý voz, ktorý tu zanechal obchodník, ktorý sa úplne nedokázal " "dostaÅ¥ do bezpeÄia." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Bohužiaľ, ostatní ho naÅ¡li skôr a voz je prázdny." msgid "Searching inside, you find the %{artifact}." msgstr "Pri hľadaní vo vnútri nájdeÅ¡ %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Vnútri nájdeÅ¡ ÄasÅ¥ nákladu voza, ktorý je stále neporuÅ¡ený." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Prehľadáš vyhodený náklad a nájdeÅ¡ nejaké drevo a zlato." msgid "You search through the flotsam, and find some wood." msgstr "Prehľadáš vyhodený náklad a nájdeÅ¡ nejaké drevo." msgid "You search through the flotsam, but find nothing." msgstr "PrehľadávaÅ¡ vyhodený náklad, ale niÄ nenachádzaÅ¡." msgid "Shrine of the 1st Circle" msgstr "Svätyňa 1. kruhu" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Narazíš na malú svätyňu, ktorú navÅ¡tevuje skupina zaÄínajúcich akolytov.\n" "Výmenou za tvoju ochranu súhlasia, že Å¥a nauÄia jednoduché kúzlo - " "'%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Svätyňa 2. kruhu" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Narazíš na zdobenú svätyňu, ktorú navÅ¡tevuje skupina zavalitých mníchov.\n" "Výmenou za tvoju ochranu súhlasia, že Å¥a nauÄia kúzlo - '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Svätyňa 3. kruhu" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Narazíš na honosnú svätyňu, ktorú navÅ¡tevuje skupina veľkňazov.\n" "Výmenou za tvoju ochranu súhlasia, že Å¥a nauÄia zložité kúzlo - '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Nanešťastie nemáš dostatok múdrosti na pochopenie tohto kúzla a nedokážeÅ¡ sa " "ho nauÄiÅ¥." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Nanešťastie, toto kúzlo už ovládaÅ¡, takže Å¥a už nemajú Äo nauÄiÅ¥." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Nanešťastie nemáš Magickú knihu na zaznamenanie kúzla." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "PristúpiÅ¡ k chatrÄi a zbadáš Äarodejnicu, ako vo vnútri Å¡tuduje starobylý " "zväzok na tému %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "KeÄ sa blížiÅ¡, otoÄí sa a uprie na teba svoje jediné sklenené oko.\n" "\"Už vieÅ¡ vÅ¡etko, Äo si zaslúžiÅ¡ vedieÅ¥!\" vykríkne Äarodejnica. \"A TERAZ " "VYPADNI Z MÔJHO DOMU!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "KeÄ sa blížiÅ¡, otoÄí sa a prehovorí.\n" "\"To, Äo som Å¥a chcela nauÄiÅ¥, už vieÅ¡. Nemôžem ti už pomôcÅ¥.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Prastará a nesmrteľná Äarodejnica žijúca v domÄeku na vtáÄích nohách Å¥a uÄí " "%{skill} pre svoje vlastné nepochopiteľné úÄely." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "KeÄ sa napijeÅ¡ sladkej vody, získaÅ¡ šťastie do ÄalÅ¡ieho boja." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "NapijeÅ¡ sa zo zakliatej fontány, ale niÄ sa nestane." msgid "You enter the faerie ring, but nothing happens." msgstr "VstúpiÅ¡ do prsteňa víl, ale niÄ sa nedeje." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Po vstupe do mystického kruhu víl získava tvoja armáda šťastie do ÄalÅ¡ej " "bitky." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "NachádzaÅ¡ starobylú a zvetranú kamennú modlu.\n" "Mala by návÅ¡tevníkom prinášaÅ¥ šťastie, ale keÄže sa na teba už hviezdy " "usmievajú, niÄ nerobí." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "NachádzaÅ¡ starobylú a zvetranú kamennú modlu.\n" "Jej pobozkanie má priniesÅ¥ šťastie, a tak to aj urobíš. Kameň je na dotyk " "veľmi studený." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Morské panny Å¥a ticho lákajú, aby si sa neskôr vrátil a nechal sa znova " "požehnaÅ¥." #, fuzzy msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Magická, upokojujúca krása morských panien sa dostane k tebe a tvojej " "posádke.\n" "Na chvíľu zabúdaÅ¡ na svoje starosti a vychutnávaÅ¡ si krásu okamihu.\n" "ÄŒaro morských panien ti žehná väÄším šťastím do ÄalÅ¡ieho boja." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Narazíš na pyramídu veľkého a starobylého kráľa.\n" "Láka Å¥a hľadaÅ¥ v nej poklad, ale vÅ¡etky staré príbehy varujú pred straÅ¡nými " "kliatbami a nemÅ•tvymi strážcami.\n" "BudeÅ¡ hľadaÅ¥?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Po porážke príšer rozlúštiÅ¡ starodávny symbol na stene, ktorý ti prezradí " "tajomstvo kúzla - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "Nanešťastie vÅ¡ak nemáš Magickú knihu, do ktorej by sa dalo kúzlo zaznamenaÅ¥." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Nanešťastie nemáš dostatok múdrosti k pochopeniu tohto kúzla a nedokážeÅ¡ sa " "ho nauÄiÅ¥." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Narazíš na pyramídu veľkého a starobylého kráľa.\n" "Pri obvyklom prieskume sa ukáže, že pyramída je úplne prázdna." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "Pitie zo studne ti má obnoviÅ¥ body kúzliel, ale ty už máš maximum." msgid "A second drink at the well in one day will not help you." msgstr "Druhé pitie v studni v jeden deň ti nepomôže." msgid "A drink from the well has restored your spell points to maximum." msgstr "Pitie zo studne obnovilo tvoje body kúziel na maximum." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Je mi ľúto\" hovorí veliteľ vojakov, \"ale vy už viete vÅ¡etko, Äo vás " "môžeme nauÄiÅ¥.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "Vojaci žijúci v pevnosti Å¥a nauÄia niekoľko nových obranných trikov." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "NachádzaÅ¡ sa v tábore žoldnierov, ktorí si precviÄujú taktiku. \"Ste pre nás " "príliÅ¡ pokroÄilí,\" hovorí kapitán žoldnierov. \"Už vás nemôžeme niÄ nauÄiÅ¥." "\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "NachádzaÅ¡ sa v tábore žoldnierov, ktorí si precviÄujú taktiku. Žoldnieri " "vítajú teba a tvojich vojakov a pozývajú vás, aby ste s nimi trénovali." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Vypadni!\", vyÅ¡tekne lieÄiteľ, \"vieÅ¡ vÅ¡etko, Äo viem.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Orkský lieÄiteľ žijúci v chatrÄi prehĺbi tvoje znalosti mágie tým, že ti " "ukáže, ako hodiÅ¥ kameňmi, rozpoznaÅ¥ znamenia a rozlúštiÅ¥ zákutia kuracích " "vnútorností." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "NachádzaÅ¡ skupinu druidov, ktorí sa klaňajú v jednej zo svojich zvláštnych " "kamenných stavieb. Druidi Å¥a mlÄky odvrátia a naznaÄia, že Å¥a nemajú Äo nové " "nauÄiÅ¥." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "NachádzaÅ¡ skupinu druidov, ktorí sa klaňajú v jednej zo svojich zvláštnych " "kamenných stavieb. V tichosti Å¥a uÄia nové spôsoby zaklínania." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Neisto sa približujeÅ¡ k pohrebisku dávnych bojovníkov. ChceÅ¡ prehľadaÅ¥ hroby?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "StráviÅ¡ niekoľko hodín prehľadávaním hrobov a niÄ nenachádzaÅ¡. Takýto podlý " "Äin znižuje morálku tvojej armády." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "Po porážke Zombíkov prehľadáš hroby a nieÄo nájdeÅ¡!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Hnijúci trup veľkej pirátskej lode straÅ¡idelne vÅ•zga, tlaÄiac sa na skaly. " "ChceÅ¡ prehľadaÅ¥ vrak lode?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "StráviÅ¡ niekoľko hodín prehľadávaním trosiek a niÄ nenájdeÅ¡. Takýto podlý " "Äin znižuje morálku tvojej armády." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "Po porážke Duchov sa prehrabeÅ¡ troskami a nieÄo nájdeÅ¡!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Hnijúci trup veľkej pirátskej lode straÅ¡idelne vÅ•zga, tlaÄiac sa na skaly. " "ChceÅ¡ prehľadaÅ¥ loÄ?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "Po porážke Kostlivcov sa prehrabeÅ¡ troskami a nieÄo nájdeÅ¡!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Tvoji muži spozorujú navigaÄnú bóju, ktorá potvrdzuje, že ste na správnom " "kurze." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Tvoji muži spozorujú navigaÄnú bóju, ktorá potvrdzuje, že ste na správnom " "kurze, a zvyÅ¡uje ich morálku." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Nápoj v oáze je osviežujúci, ale neponúka žiadny Äalší úžitok. Oáza by mohla " "opäť pomôcÅ¥, ak by si najprv vybojoval/a bitku." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Pitie v oáze dodá tvojim vojakom silu a zdvihne im náladu. Dnes môžeÅ¡ " "cestovaÅ¥ o kúsok Äalej." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Pitie z napájadla je osviežujúce, ale neprináša žiadny Äalší úžitok. " "Napájadlo by mohlo opäť pomôcÅ¥, ak by si najprv vybojoval/a bitku." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Pitie z napájadla dodá tvojim vojakom silu a zdvihne im náladu. Dnes môžeÅ¡ " "cestovaÅ¥ o kúsok Äalej." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "Pred bitkou nepomáha modliÅ¥ sa dvakrát. Vráť sa až po boji." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "NávÅ¡teva a modlitba v chráme zvyÅ¡uje morálku tvojich vojakov." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Na schodoch altánku sa objaví starý Rytier. \"Je mi ľúto, môj pane, nauÄil " "som vás vÅ¡etko, Äo som mohol.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Na schodoch altánku sa objaví starý Rytier. \"Môj pane, nauÄím vás vÅ¡etko, " "Äo viem, aby som vám pomohol na vaÅ¡ich cestách.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Z istej smrti v neľútostnom oceáne vyÅ¥ahujeÅ¡ Äloveka, ktorý prežil " "stroskotanie lode. VÄaÄne ti povie: \"Dal by som vám za odmenu artefakt, ale " "už máte plno.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Z istej smrti v neľútostnom oceáne vyÅ¥ahujeÅ¡ Äloveka, ktorý prežil " "stroskotanie lode. VÄaÄne Å¥a za tvoj láskavý Äin odmení tým, že ti dá %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "Leprikón ti ponúka %{art} za malú cenu %{gold} zlatých." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Leprikón ti ponúka %{art} za malú cenu %{gold} zlatých a %{count} %{res}." msgid "Do you wish to buy this artifact?" msgstr "Želáš si tento artefakt kúpiÅ¥?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Snažíš sa leprikónovi zaplatiÅ¥, ale zisÅ¥ujeÅ¡, že si to nemôžeÅ¡ dovoliÅ¥. " "Leprikón si dupne nohou a ignoruje Å¥a." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Leprikón, urazený tvojím odmietnutím jeho veľkorysej ponuky, si dupne nohou " "a ignoruje Å¥a." msgid "You've found the artifact: " msgstr "NachádzaÅ¡ artefakt: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Podarilo sa ti nájsÅ¥ skromný príbytok zvädnutého pustovníka. Pustovník ti " "povie, že je ochotný daÅ¥ %{art} prvému múdremu Äloveku, ktorého stretne." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Narazíš na sparÅ¥anské priestory vyslúžilého vojaka. Vojak ti povie, že je " "ochotný odovzdaÅ¥ %{art} prvému skutoÄnému vodcovi, ktorého stretne." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "StretávaÅ¡ zvláštnu osobu v klobúku so sovou na vrchu. Povie ti, že je " "ochotný daÅ¥ ti %{art}, ak máš %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Natrafíš na starobylý artefakt. KeÄ sa poň naÄiahneÅ¡, z krovia vyskoÄí " "svorka Tulákov, ktorí si strážia ukradnutú korisÅ¥." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Cez mýtinu pozorujeÅ¡ starobylý artefakt. Nanešťastie ho stráži neÄaleký " "%{monster}. ChceÅ¡ s ním o artefakt bojovaÅ¥?" msgid "Victorious, you take your prize, the %{art}." msgstr "Víťazne si prevezmeÅ¡ svoju cenu, %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "ObozretnosÅ¥ je lepÅ¡ia ÄasÅ¥ statoÄnosti a rozhodneÅ¡ sa tomuto boju pre dneÅ¡ok " "vyhnúť." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Po hodinách strávených snahou vyloviÅ¥ truhlicu z mora ju otvoríš a nájdeÅ¡ " "%{gold} zlatých." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Po hodinách strávených snahou vyloviÅ¥ truhlicu z mora ju otvoríš a nájdeÅ¡ " "%{gold} zlatých a %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Po hodinách strávených snahou vyloviÅ¥ truhlicu z mora ju otvoríš a zistíš, " "že je prázdna." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Po prehľadaní oblasti narazíš na skrytú skrýšu s pokladom. Zlato si môžeÅ¡ " "vziaÅ¥ alebo ho rozdaÅ¥ sedliakom za skúsenosti. ChceÅ¡ si zlato nechaÅ¥?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Po prehľadaní oblasti narazíš na skrytú truhlicu, ktorá obsahuje %{gold} " "zlatých." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Po prehľadaní oblasti narazíš na skrytú truhlicu, ktorá obsahuje starobylý " "artefakt %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Narazíš na preliaÄenú a zneÄistenú lampu zapichnutú hlboko v zemi. ChceÅ¡ tú " "lampu poutieraÅ¥?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "ZískavaÅ¡ kontrolu nad miestnou alchymistickou dielňou. Bude ti poskytovaÅ¥ " "%{count} jednotku ortuti denne." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "ZískavaÅ¡ kontrolu nad pílou. Denne ti poskytne %{count} jednotky dreva.." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "ZískavaÅ¡ kontrolu nad rudnou baňou. Denne ti poskytne %{count} jednotky rudy." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "ZískavaÅ¡ kontrolu nad baňou na síru. Denne ti poskytne %{count} jednotku " "síry." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "ZískavaÅ¡ kontrolu nad kryÅ¡tálovou baňou. Denne ti poskytne %{count} jednotku " "kryÅ¡tálu." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "ZískavaÅ¡ kontrolu nad baňou na drahokamy. Denne ti poskytne %{count} " "jednotku drahokamov.." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "ZískavaÅ¡ kontrolu nad zlatou baňou. Denne ti poskytne %{count} zlatých." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Maják je teraz pod tvojou kontrolou a vÅ¡etky tvoje lode sa odteraz každý deň " "dostanú Äalej." msgid "You gain control of a %{name}." msgstr "%{name} je odteraz pod tvojou kontrolou." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Narazíš na opustenú zlatú baňu. Zdá sa, že v bani straší. ChceÅ¡ vstúpiÅ¥?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "PorážaÅ¡ Duchov a darí sa ti obnoviÅ¥ Å¥ažbu v bani." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "%{monster} s túžbou po väÄÅ¡ej sláve si želajú pripojiÅ¥ sa k tebe. PrijmeÅ¡ " "ich?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "KeÄ sa blížiÅ¡ k obydliu, vÅ¡imneÅ¡ si, že tu nikto nie je." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "PrehľadávaÅ¡ ruiny, ale Medúzy, ktoré tu kedysi žili, sú preÄ. Možno pribudnú " "na budúci týždeň." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "V ruinách nachádzaÅ¡ niekoľko Medúz, ktoré tu žijú. Sú ochotné pridaÅ¥ sa k " "tvojej armáde za urÄitú cenu. ChceÅ¡ naverbovaÅ¥ Medúzy?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Podarilo sa ti nájsÅ¥ Stromové mesto víl. Bohužiaľ, nikto z víl, ktoré tam " "žijú, sa nechce pridaÅ¥ k armáde. Možno na budúci týždeň." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Niektoré zo Å¡printov žijúcich v meste stromov sú ochotné pridaÅ¥ sa k tvojej " "armáde za urÄitú cenu. ChceÅ¡ naverbovaÅ¥ Víly?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Farebný voz Tulákov tu stojí prázdny. Možno sa tu neskôr nejakí Tuláci " "objavia." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Vzdialené zvuky hudby a smiechu Å¥a prilákajú k farebnému vozu, v ktorom sa " "zdržiavajú Tuláci. ChceÅ¡, aby sa niektorí Tuláci pridali k tvojmu vojsku?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Láka Å¥a skupina oÅ¡arpaných stanov, ktoré vejú v piesoÄnom vetre. Stany sú " "neobsadené. Možno tu neskôr budú Äalší Nomádi." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Láka Å¥a skupina oÅ¡arpaných stanov, ktoré vejú v piesoÄnom vetre. ChceÅ¡, aby " "sa k tebe na tvojich cestách pridali nejakí Nomádi?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Jama s bahnom chvíľu buble a potom zostane ležaÅ¥." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "KeÄ sa priblížiÅ¡ k bublajúcej jame s bahnom, zaÄnú z nej vyliezaÅ¥ tvory a " "rozmiestňovaÅ¥ sa okolo nej. Jednohlasne hovoria: \"Matka Zem by ti rada " "ponúkla niekoľko svojich vojakov. ChceÅ¡ naverbovaÅ¥ Zemských elementálov?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "VstúpiÅ¡ do stavby z bielych kamenných stĺpov a niÄ nenájdeÅ¡." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Biele kamenné stĺpy podopierajú strechu, ktorá sa dvíha k nebu. KeÄ vstúpiÅ¡ " "do stavby, bezvetrie vonkajÅ¡ka ustúpi vírivému vetru, ktorý Å¥a takmer " "vytlaÄí späť von. Prúd vzduchu sa zhmotní do sotva viditeľnej podoby. Tvor " "sa pýta nieÄím, Äo sa dá opísaÅ¥ len ako hlasný Å¡epot: \"PreÄo prichádzaÅ¡? Si " "tu, lebo chceÅ¡ privolaÅ¥ vzduÅ¡né sily?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Z lávového jazierka sa k tebe nepriblížia žiadni Ohniví elementáli." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Pod Å¡truktúrou, ktorá slúži na udržiavanie tepla, sa ohnivé živly pohybujú v " "ohnivej kaluži roztavenej lávy. Skupina týchto bytostí sa k tebe priblíži a " "ponúkne ti svoje služby. ChceÅ¡ naverbovaÅ¥ Ohnivých elementálov?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Vo vode sa na chvíľu objaví tvár a potom zmizne." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "KryÅ¡talické Å¡truktúry vrhajú tiene na malý odrazový bazén s vodou. Zahľadíš " "sa do bazéna a tvár, ktorá nie je tvoja, sa pozerá späť. Pýta sa: \"PrajeÅ¡ " "si privolaÅ¥ silu vody?\"" msgid "This burial site is deathly still." msgstr "Toto pohrebisko je mÅ•tvolne tiché." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Nepokojní duchovia dávno mÅ•tvych bojovníkov, ktorí hľadajú miesto svojho " "posledného odpoÄinku, sa k tebe pridajú v nádeji, že nájdu pokoj. Chcete " "naverbovaÅ¥ Duchov?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "Mesto mÅ•tvych je prázdne od života a prázdne aj od neživota. Možno sa sem na " "budúci týždeň nasÅ¥ahujú nejakí nemÅ•tvi." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Niektorí Kostejovia, ktorí tu žijú, sú ochotní pridaÅ¥ sa k tvojej armáde za " "odmenu. Chcete naverbovaÅ¥ Kostejov?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "NachádzaÅ¡ ruiny starobylého mesta, ktoré teraz obývajú výluÄne nemÅ•tvi. " "BudeÅ¡ pátraÅ¥?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Niektorí z preživších Kostejov sú ohromení tvojim víťazstvom nad svojimi " "druhmi a ponúknu ti, že sa k tebe za odmenu pridajú. ChceÅ¡ naverbovaÅ¥ " "Kostejov?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "NachádzaÅ¡ jeden z tých mostov, pod ktorými Trolovia tak radi žijú, ale tu " "žiadni nie sú. Možno sa nejakí objavia na budúci týždeň." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Niektorí Trolovia žijúci pod mostom sú ochotní pridaÅ¥ sa k tvojej armáde, " "ale za urÄitú cenu. ChceÅ¡ naverbovaÅ¥ Trolov?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "Trolovia žijúci pod mostom Å¥a vyzývajú. BudeÅ¡ s nimi bojovaÅ¥?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Stále zostáva zopár Trolov, ktorí sa skrývajú pod mostom. Pristúpia k tebe a " "ponúknu ti, že sa pridajú k tvojim jednotkám ako žoldnieri. ChceÅ¡ kúpiÅ¥ " "nejakých Trolov?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "V DraÄom meste nie sú draci, ktorí by sa k tebe chceli tento týždeň pridaÅ¥. " "Možno sa nejaký drak uvoľní budúci týždeň." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "DraÄie mesto je ochotné ponúknuÅ¥ niekoľko Drakov pre tvoju armádu za urÄitú " "cenu. ChceÅ¡ naverbovaÅ¥ Drakov?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Stojíš pred DraÄím mestom, miestom, ktoré je pre obyÄajných ľudí " "neprístupné. ChceÅ¡ toto pravidlo poruÅ¡iÅ¥ a vyzvaÅ¥ drakov na súboj?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Po porážke DraÄích Å¡ampiónov vodcovia mesta súhlasia s tým, že za odmenu " "dodajú niekoľko Drakov do tvojej armády. ChceÅ¡ naverbovaÅ¥ Drakov?" msgid "From the observation tower, you are able to see distant lands." msgstr "Z vyhliadkovej veže vidíš vzdialené konÄiny." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "Prameň sa obnovuje len raz týždenne a tento týždeň tu už niekto bol." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Pitie z prameňa ti má priniesÅ¥ dvojnásobok bežných bodov kúziel, ale ty ich " "už máš na tejto úrovni." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Pitie z prameňa naplní tvoju krv mágiou! V rezerve máš dvojnásobok svojich " "bežných bodov kúziel." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Majordómus Å¥a spoznáva, ale odmieta Å¥a prijaÅ¥. \"Pán,\" hovorí, \"neprijme " "dvakrát toho istého Å¡tudenta.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Majordómus Å¥a pustí k pánovi domu. Ten Å¥a zaÅ¡kolí v Å¡tyroch zruÄnostiach, " "ktoré by mal hrdina ovládaÅ¥." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Majordómus otvorí dvere a premeria si vás pohľadom. \"Nie ste ani dostatoÄne " "slávny, ani dostatoÄne diplomatický, aby ste boli prijatý k môjmu pánovi,\" " "odfrkne si. \"Vráťte sa, keÄ sa budete považovaÅ¥ za hodného.\"" msgid " and " msgstr " a " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "%{monsters}, v tvojej armáde, boli vycviÄení bojovými majstrami pevnosti. " "Teraz sú to už %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "NezvyÄajná aliancia Zlobrov, Orkov a Trpaslíkov ponúka výcvik (vylepÅ¡enie) " "vÅ¡etkých takýchto jednotiek, ktoré k nim privedieÅ¡. Nanešťastie so sebou " "žiadne nemáš." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "%{monsters} sa vylepÅ¡ili na %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "KovÃ¡Ä pracujúci v zlievarni sa ponúkne, že vÅ¡etky zbrane Kopijníkov a " "Å ermiarov, ktoré mu prinesieÅ¡, prerobí zo železa na oceľ. Tiež hovorí, že " "pozná postup, ktorý premení Železných golemov na Oceľových golemov. " "Bohužiaľ, vo svojej armáde nemáš ani jedného z týchto vojakov, takže ti " "nemôže pomôcÅ¥." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Kapitán sa na teba prekvapene pozrie a povie:\n" "\"Už máš vÅ¡etky mapy, o ktorých viem. Nechaj ma teraz v pokoji loviÅ¥ ryby.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Kapitán na dôchodku, ktorý žije na tejto zrekonÅ¡truovanej rybárskej ploÅ¡ine, " "ti za 1000 zlatých ponúkne na predaj mapy mora, ktoré vytvoril za svojich " "mladších Äias. ChceÅ¡ si tieto mapy kúpiÅ¥?" #, fuzzy msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Kapitán si vzdychne. \"Nemáš dosÅ¥ peňazí, Äo? NemôžeÅ¡ predsa oÄakávaÅ¥, že " "budem rozdávaÅ¥ svoje mapy zadarmo!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Narazíš na obelisk z kameňa, aký si nikdy predtým nevidel. Pozorne sa naň " "zadívaÅ¡ a hladký povrch sa zrazu zmení na rytinu. Nápis je kúskom stratenej " "prastarej mapy. Rýchlo si ten kúsok odkreslíš a rytina zmizne tak náhle, ako " "sa objavila." msgid "You have already been to this obelisk." msgstr "Pri tomto obelisku si už bol/a." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "KeÄ sa k nemu priblížiÅ¡, strom s radosÅ¥ou otvorí oÄi. \"Rád Å¥a opäť vidím, " "Å¡tudent/ka môj/moja. Dúfam, že ti moje uÄenie pomohlo.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "KeÄ sa k nemu priblížiÅ¡, strom s radosÅ¥ou otvorí oÄi. \"Ach, dobrodružný " "Älovek! Dovoľ mi, aby som Å¥a nauÄil nieÄo z toho, Äo som sa nauÄil za celé " "veky.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "KeÄ sa k nemu priblížiÅ¡, strom s radosÅ¥ou otvorí oÄi." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ach, dobrodružný Älovek! Rád Å¥a nauÄím nieÄo z toho, Äo som sa nauÄil za " "celé veky, len za %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Len to zakop okolo mojich koreňov.)" msgid "Tears brim in the eyes of the tree." msgstr "V oÄiach stromu sa zalesknú slzy." msgid "\"I need %{count} %{res}.\"" msgstr "\"Potrebujem %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "Å¡epká. (fňuk) \"No, vráť sa, keÄ mi budeÅ¡ môcÅ¥ zaplatiÅ¥.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Medzi stromami sedí slepý veÅ¡tec. KeÄ mu vysvetlíš zámer tvojej cesty, " "aktivuje svoju kriÅ¡táľovú guľu a umožní ti vidieÅ¥ silné a slabé stránky " "tvojich protivníkov." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Vchod do jaskyne je tmavý a z ústia jaskyne sa šíri nepríjemný sírny zápach. " "VstúpiÅ¡?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "Až na stopy po straÅ¡nej bitke je jaskyňa prázdna." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "V jaskyni nájdeÅ¡ mocného a ohavného démona. \"Dnes,\" zavrÄí, \"budeÅ¡ " "bojovaÅ¥ a urÄite zomrieÅ¡. Dám ti vÅ¡ak na výber z viacerých spôsobov smrti. " "MôžeÅ¡ bojovaÅ¥ so mnou, alebo s mojimi služobníkmi. Dáš prednosÅ¥ boju s " "mojimi sluhami?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Démon zakriÄí svoju výzvu a zaútoÄí! Po krátkom, zúfalom boji príšeru " "zabijeÅ¡ a získavaÅ¡ %{exp} skúsenostných bodov." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Démon zakriÄí svoju výzvu a zaútoÄí! Po krátkom, zúfalom boji príšeru " "zabijeÅ¡ a získavaÅ¡ %{exp} skúsenostných bodov a %{count} zlata." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Démon zakriÄí svoju výzvu a zaútoÄí! Po krátkom zúfalom boji príšeru zabijeÅ¡ " "a v zadnej Äasti jaskyne nájdeÅ¡ %{art}." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Vidiac, že nemáš %{count} zlata, démon Å¥a sekne svojimi pazúrmi a posledné, " "Äo vidíš, je Äervená hmla." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Démon na teba skoÄí a chňapne po tvojom hrdle skôr, ako stihneÅ¡ vytasiÅ¥ meÄ. " "\"Tvoj život je môj,\" hovorí. \"Predám ti ho späť za %{count} zlata.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Po porážke démonových služobníkov nájdeÅ¡ skrytú skrýšu s %{count} zlata." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "KeÄ vstupujeÅ¡ do Alchymistickej veže, približuje sa k tebe chromý, Å¡edivý " "muž v hnedom plášti." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "Skontroluje tvoj batoh a zistí, že máš jeden prekliaty predmet." msgstr[1] "Skontroluje tvoj batoh a zistí, že máš %{count} prekliate predmety." msgstr[2] "" "Skontroluje tvoj batoh a zistí, že máš %{count} prekliatych predmetov." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "Alchymista ti ho za %{gold} zlatých odstráni. Zaplatíš mu?" msgstr[1] "Alchymista ti ich za %{gold} zlatých odstráni. Zaplatíš mu?" msgstr[2] "Alchymista ti ich za %{gold} zlatých odstráni. Zaplatíš mu?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Po tom, Äo súhlasíš so zaplatením požadovanej sumy zlata, alchymista vezme " "prekliaty artefakt a hodí ho do svojho magického kotla." msgstr[1] "" "Po tom, Äo súhlasíš so zaplatením požadovanej sumy zlata, alchymista vezme " "prekliate artefakty a hodí ich do svojho magického kotla." msgstr[2] "" "Po tom, Äo súhlasíš so zaplatením požadovanej sumy zlata, alchymista vezme " "prekliate artefakty a hodí ich do svojho magického kotla." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Spoza zamknutých dverí poÄujeÅ¡ hlas: \"Nemáš dosÅ¥ zlata, aby si zaplatil za " "moje služby.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "Z veže poÄujeÅ¡ hlas: \"ChoÄ preÄ! Nemôžem ti pomôcÅ¥!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Hlavný koniar k tebe prehovorí: \"Máte pekného koňa. Obávam sa, že vám " "nemôžeme daÅ¥ lepÅ¡ieho, ale kone, na ktorých jazdí vaÅ¡a kavaléria, vyzerajú " "byÅ¥ zo zlého chovu. Máme veľa vycviÄených vojnových koní, ktoré by vaÅ¡im " "jazdcom veľmi pomohli. Trvám na tom, aby ste si ich vzali.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "KeÄ sa blížiÅ¡ k stajniam, objaví sa hlavný koniar, ktorý vedie pekne " "vyzerajúceho vojnového koňa. \"Tento kôň vám pomôže urýchliÅ¥ vaÅ¡e putovanie. " "Žiaľ, za týždeň sa unaví. Musíte mi tiež dovoliÅ¥, aby som vaÅ¡im jazdeckým " "vojakom dal lepÅ¡ie kone, ich kone vyzerajú chatrne a slabo.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Pristúpi k tebe hlavný koniar a prehovorí: \"Už máte pekného koňa a nemáte " "neskúsenú kavalériu, ktorá by mohla využiÅ¥ naÅ¡e vycviÄené vojnové kone.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "KeÄ sa blížiÅ¡ k stajniam, objaví sa hlavný koniar, ktorý vedie pekne " "vyzerajúceho vojnového koňa. \"Tento kôň vám pomôže urýchliÅ¥ vaÅ¡e cesty. " "Žiaľ, jeho výdrž sa pri Å¥ažkej jazde oslabí a o týždeň sa musíte vrátiÅ¥ pre " "nového koňa. Máme aj veľa pekných vojnových koní, ktoré by mohli byÅ¥ " "užitoÄné pre vojenských jazdcov, ale nemáte žiadneho, ktorému by sme mohli " "pomôcÅ¥.\"" msgid "The Arena guards turn you away." msgstr "Strážcovia arény Å¥a odvrátia." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "PrikážeÅ¡ svojej posádke, aby si zapchala uÅ¡i voskom skôr, než ich má " "straÅ¡idelná pieseň sirén Å¡ancu zlákaÅ¥ do ich vodného hrobu." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Kým sirény spievajú svoju hrôzostraÅ¡nú pieseň, tvoja malá, odhodlaná armáda " "dokáže prekonaÅ¥ nutkanie vrhnúť sa bezhlavo do mora." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Od sirén sediacich na skalách sa ozýva straÅ¡idelný kvílivý spev. Mnohí z " "tvojej posádky podľahnú ich kúzlu a ponoria sa do vody, kde sa utopia. Teraz " "si múdrejší a získavaÅ¡ %{exp} skúseností." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Oslnivo odvážne sa vlámeÅ¡ do miestneho žalára a oslobodíš tam uväzneného " "hrdinu, ktorý ti na oplátku sľúbi vernosÅ¥." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Už máš %{count} hrdinov a s poľutovaním musíš nechaÅ¥ väzňa v tomto žalári " "trápiÅ¥ sa po nespoÄetné dni." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "VstúpiÅ¡ do polorozpadnutej chatrÄe a porozprávaÅ¡ sa s kúzelníkom, ktorý tam " "žije. Povie ti o blízkych i vzdialených miestach, ktoré ti môžu pomôcÅ¥ na " "tvojich cestách." msgid "This eye seems to be intently studying its surroundings." msgstr "Zdá sa, že toto oko pozorne skúma svoje okolie." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Narazíš na obrovskú sfingu. Sfinga zostáva podivne tichá." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Mám pre teba hádanku,\" hovorí Sfinga. \"Odpovedz správne a dostane sa ti " "odmeny. Ak odpovieÅ¡ nesprávne, zjem Å¥a. PrijímaÅ¡ túto výzvu?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Sfinga ti položí nasledujúcu hádanku:\n" "\n" "'%{riddle}'\n" "\n" "Tvoja odpoveÄ?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Nesprávna odpoveÄ,\" povie Sfinga a usmeje sa. Sfinga po tebe Å¡vihne labou " "a zhodí Å¥a na zem. ÄŽalší úder spôsobí, že svet sÄernie, a ty už niÄ nevieÅ¡." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Sfinga si trochu sklamane povzdychne. \"Tvoja odpoveÄ na moju hádanku je " "správna, takže tu je tvoja odmena. Teraz odíÄ.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Pred tebou sa týÄi magická bariéra, ktorá ti blokuje cestu. Na oblúku je " "runami napísané,\n" "\"Vyslov kÄ¾ÃºÄ a môžeÅ¡ prejsÅ¥.\"\n" "KeÄ vyslovíš magické slovo, žiariaca bariéra sa rozplynie do niÄoty." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Pred tebou sa týÄi magická bariéra, ktorá ti blokuje cestu. Na oblúku je " "runami napísané,\n" "\"Vyslov kÄ¾ÃºÄ a môžeÅ¡ prejsÅ¥.\"\n" "Vyslovíš ho a niÄ sa nestane." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "VstúpiÅ¡ do stanu a uvidíš starú ženu, ktorá sa pozerá do Äarovného " "drahokamu. Pozrie sa hore a povie,\n" "\"Na svojich cestách som sa nauÄila veľa z oblasti tajomnej mágie. Moju " "schopnosÅ¥ ma nauÄil jeden veľký veÅ¡tec. Mám odpoveÄ, ktorú hľadáš.\"" msgid "No spell book is present." msgstr "Kniha kúziel nie je k dispozícii." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Toto kúzlo stojí %{mana} bodov kúziel. Nemáš žiadne body kúziel, takže ho " "nemôžeÅ¡ zoslaÅ¥." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Toto kúzlo stojí %{mana} bodov kúziel. Máš len %{point} bodov kúziel, takže " "ho nemôžeÅ¡ zoslaÅ¥." msgid "The spell was not found." msgstr "Zaklínadlo sa nenaÅ¡lo." msgid "Only heroes can cast this spell." msgstr "Toto kúzlo môžu zoslaÅ¥ len hrdinovia." msgid "This hero is not able to cast adventure spells." msgstr "Tento hrdina nie je schopný zosielaÅ¥ dobrodružné kúzla." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Tvoj hrdina je príliÅ¡ unavený na to, aby dnes toto kúzlo zoslal. Skús to " "opäť zajtra." msgid "This spell cannot be cast on a boat." msgstr "Toto kúzlo nemožno použiÅ¥ na lodi." msgid "This spell can only be cast near an ocean." msgstr "Toto kúzlo možno zoslaÅ¥ len v blízkosti oceánu." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "V blízkosti hrdinu nie sú k dispozícii žiadne lode ani oceán, kde by toto " "kúzlo fungovalo." msgid "There are no boats available for this spell." msgstr "Na zoslanie tohto kúzla už nie je k dispozícii žiadna loÄ." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "Vedľa hrdinu nie je miesto v oceáne, kde by toto kúzlo fungovalo." #, fuzzy msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Momentálne nevlastníš žiadne mesto ani hrad, takže toto kúzlo nemôžeÅ¡ zoslaÅ¥." #, fuzzy msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Tento hrdina sa už v meste nachádza, takže toto kúzlo nie je možné zoslaÅ¥." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Najbližšie mesto je %{town}.\n" "\n" "V tomto meste sa vÅ¡ak už nachádza hrdina %{hero}." msgid "This spell is already in effect." msgstr "Toto kúzlo je už v platnosti." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Žiadny protivník už nemá ani nemôže maÅ¥ pod svojím velením žiadneho hrdinu. " "Zoslanie tohto kúzla nebude maÅ¥ žiadny úÄinok." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Žiadny protivník nemá v tejto chvíli pod svojím velením hrdinu. Zoslanie " "tohto kúzla nebude maÅ¥ žiadny úÄinok." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Aby kúzlo Vízie fungovalo, musíš sa nachádzaÅ¥ do vzdialenosti %{count} " "políÄok od bojovníkov." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Na zoslanie tohto kúzla musíš stáť pri vchode do bane (píly a alchymistické " "laboratóriá sa nepoÄítajú)." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Aby sa toto kúzlo dalo použiÅ¥, musíš najprv poraziÅ¥ Duchov, ktorí strážia " "baňu." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "V bani už stráži minimálne toľko elementálov, koľko ich tento hrdina dokáže " "vygenerovaÅ¥. Zoslanie tohto kúzla nebude maÅ¥ žiadny úÄinok." msgid "%{name} the %{race} (Level %{level})" msgstr "%{race} %{name} (Úroveň %{level})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} na úrovni %{level}" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{race} %{name} (Úroveň %{level})" #, fuzzy msgid "Hero race:" msgstr "Okno hrdinu" msgid "Are you sure you want to dismiss this Hero?" msgstr "UrÄite chceÅ¡ tohto hrdinu prepustiÅ¥?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Zobraz info o skúsenostiach" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Body kúziel" msgid "View Spell Points Info" msgstr "Zobraz info o bodoch kúziel" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Stratíš hrdinu '%{name}'." #, fuzzy msgid "Click to change race." msgstr "Kliknutím zobraz ÄalÅ¡ie mesto." #, fuzzy msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Å iroká' bojová formácia rozprestiera tvoje armády zhora nadol na bojisko, " "priÄom medzi každou armádou je aspoň jedno prázdne miesto." #, fuzzy msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "'Zoskupená' bojová formácia spája tvoju armádu v strede tvojej strany " "bojiska." msgid "Exit Hero Screen" msgstr "ZavrieÅ¥ obrazovku hrdinu" msgid "You cannot dismiss a hero in a castle" msgstr "NemôžeÅ¡ prepustiÅ¥ hrdinu v hrade" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "%{race} %{name} nesmie byÅ¥ podľa scenára prepustený" msgid "Dismiss %{name} the %{race}" msgstr "PrepustiÅ¥: %{race} %{name}" msgid "Show previous hero" msgstr "Ukáž predoÅ¡lého hrdinu" msgid "Show next hero" msgstr "Ukáž ÄalÅ¡ieho hrdinu" msgid "Set army combat formation to 'Spread'" msgstr "NastaviÅ¥ bojovú formáciu na 'Å iroká'" msgid "Set army combat formation to 'Grouped'" msgstr "NastaviÅ¥ bojovú formáciu na 'Zoskupená'" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Klikni sem a vyber scenár, ktorý chceÅ¡ hraÅ¥." msgid "Blood Morale" msgstr "Krvná Morálka" msgid "%{morale} Morale" msgstr "%{morale} Morálka" msgid "%{luck} Luck" msgstr "%{luck} Šťastie" msgid "Current Luck Modifiers:" msgstr "Aktuálne modifikátory šťastia:" msgid "Current Morale Modifiers:" msgstr "Aktuálne modifikátory morálky:" msgid "Entire army is undead, so morale does not apply." msgstr "Celá armáda je nemÅ•tva, takže morálka sa na ňu nevzÅ¥ahuje." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "SúÄasné skúsenosti %{exp1}.\n" " ÄŽalÅ¡ia úroveň %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Úroveň %{level}" #, fuzzy msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} má v súÄasnosti %{point} bodov kúziel z maximálneho poÄtu %{max}. " "Maximálny poÄet bodov kúziel je 10-násobok tvojich znalostí. Príležitostne " "je možné maÅ¥ viac, ako je tvoj maximálny poÄet bodov kúziel, prostredníctvom " "Å¡peciálnych udalostí." msgid "%{name1} meets %{name2}" msgstr "%{name1} a %{name2} sa stretávajú" msgid "Enemy heroes are now fully identifiable." msgstr "Nepriateľskí hrdinovia sú teraz plne identifikovateľní." msgid "Identify Hero" msgstr "IdentifikovaÅ¥ hrdinu" msgid "Select town to port to." msgstr "Vyber mesto, do ktorého sa chceÅ¡ preniesÅ¥." msgid "Town Portal" msgstr "Mestský portál" msgid "The creatures are willing to join us!" msgstr "Bojovníci sú ochotní sa k nám pridaÅ¥!" msgid "All the creatures will join us..." msgstr "VÅ¡etci bojovníci sa k nám pridajú..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Bojovník sa k nám pridá..." msgstr[1] "%{count} bojovníci sa k nám pridajú..." msgstr[2] "%{count} bojovníkov sa k nám pridá..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" " za poplatok %{gold} zlata." msgid "These weak creatures will surely flee before us." msgstr "Títo slabí bojovníci pred nami urÄite uteÄú." msgid "I fear these creatures are in the mood for a fight." msgstr "Obávam sa, že títo bojovníci sú naladení na boj." #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Tvoja útoÄná schopnosÅ¥ je bonus pridaný k útoÄnej schopnosti každého " "bojovníka." #, fuzzy msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Tvoja obranná schopnosÅ¥ je bonus pridaný k obrannej schopnosti každého " "bojovníka." #, fuzzy msgid "The hero's spell power determines the duration or power of a spell." msgstr "Tvoja Sila kúziel urÄuje dĺžku alebo silu kúzla." #, fuzzy msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Tvoje vedomosti urÄujú, koľko bodov kúziel môže maÅ¥ tvoj hrdina. Za " "normálnych okolností je hrdina obmedzený na 10 bodov kúziel na úroveň " "vedomosti." msgid "Current Modifiers:" msgstr "SúÄasné modifikátory:" msgid "skill|Basic" msgstr "Základ" msgid "skill|Advanced" msgstr "PokroÄilý" msgid "skill|Expert" msgstr "Expert" msgid "Pathfinding" msgstr "Hľad. ciest" msgid "Archery" msgstr "Lukostreľba" msgid "Logistics" msgstr "Logistika" msgid "Scouting" msgstr "Prieskum" msgid "Diplomacy" msgstr "Diplomacia" msgid "Navigation" msgstr "Navigácia" msgid "Leadership" msgstr "Vedenie" msgid "Wisdom" msgstr "MúdrosÅ¥" msgid "Mysticism" msgstr "Mystika" msgid "Ballistics" msgstr "Balistika" msgid "Eagle Eye" msgstr "Orlí zrak" msgid "Necromancy" msgstr "Nekromancia" msgid "Estates" msgstr "Statky" msgid "Advanced Archery" msgstr "PokroÄilá lukostreľba" msgid "Advanced Pathfinding" msgstr "PokroÄilé hľadanie ciest" msgid "Basic Archery" msgstr "Základná lukostreľba" msgid "Basic Pathfinding" msgstr "Základné hľadanie ciest" msgid "Expert Pathfinding" msgstr "Expertné hľadanie ciest" msgid "Advanced Logistics" msgstr "PokroÄilá logistika" msgid "Basic Logistics" msgstr "Základná logistika" msgid "Basic Scouting" msgstr "Základný prieskum" msgid "Expert Archery" msgstr "Expertná lukostreľba" msgid "Expert Logistics" msgstr "Expertná logistika" msgid "Advanced Diplomacy" msgstr "PokroÄilá diplomacia" msgid "Advanced Scouting" msgstr "PokroÄilý prieskum" msgid "Basic Diplomacy" msgstr "Základná diplomacia" msgid "Expert Diplomacy" msgstr "Expertná diplomacia" msgid "Expert Scouting" msgstr "Expertný prieskum" msgid "Advanced Leadership" msgstr "PokroÄilé vedenie" msgid "Advanced Navigation" msgstr "PokroÄilá navigácia" msgid "Basic Leadership" msgstr "Základné vedenie" msgid "Basic Navigation" msgstr "Základná navigácia" msgid "Expert Navigation" msgstr "Expertná navigácia" msgid "Advanced Wisdom" msgstr "PokroÄilá múdrosÅ¥" msgid "Basic Mysticism" msgstr "Základná mystika" msgid "Basic Wisdom" msgstr "Základná múdrosÅ¥" msgid "Expert Leadership" msgstr "Expertné vedenie" msgid "Expert Wisdom" msgstr "Expertná múdrosÅ¥" msgid "Advanced Luck" msgstr "PokroÄilé šťastie" msgid "Advanced Mysticism" msgstr "PokroÄilá mystika" msgid "Basic Luck" msgstr "Základné šťastie" msgid "Expert Luck" msgstr "Expertné šťastie" msgid "Expert Mysticism" msgstr "Expertná mystika" msgid "Advanced Ballistics" msgstr "PokroÄilá balistika" msgid "Advanced Eagle Eye" msgstr "PokroÄilý orlí zrak" msgid "Basic Ballistics" msgstr "Základná balistika" msgid "Basic Eagle Eye" msgstr "Základný orlí zrak" msgid "Expert Ballistics" msgstr "Expertná balistika" msgid "Advanced Necromancy" msgstr "PokroÄilá nekromancia" msgid "Basic Estates" msgstr "Základné statky" msgid "Basic Necromancy" msgstr "Základná nekromancia" msgid "Expert Eagle Eye" msgstr "Expertný orlí zrak" msgid "Expert Necromancy" msgstr "Expertná nekromancia" msgid "Advanced Estates" msgstr "PokroÄilé statky" msgid "Expert Estates" msgstr "Expertné statky" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} znižuje postih za pohyb po nerovnom teréne o %{count} percent." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} eliminuje postih za pohyb po nerovnom teréne." #, fuzzy msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} odstraňuje %{count} percentnú penaltu tvojich jednotiek za streľbu " "spoza prekážok." #, fuzzy msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} zvýši pohybové body tvojho hrdinu o %{count} percent." #, fuzzy msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} zväÄší dohľadnú oblasÅ¥ tvojho hrdinu o jeden Å¡tvorec." msgstr[1] "%{skill} zväÄší dohľadnú oblasÅ¥ tvojho hrdinu o %{count} Å¡tvorce." msgstr[2] "%{skill} zväÄší dohľadnú oblasÅ¥ tvojho hrdinu o %{count} Å¡tvorcov." #, fuzzy msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} ti umožňuje vyjednávanie s príšerami, ktoré sú slabÅ¡ie ako tvoja " "skupina. " #, fuzzy msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Približne %{count} percent bojovníkov ti môže ponúknuÅ¥, že sa k tebe pridá." #, fuzzy msgid "All of the creatures may offer to join the hero." msgstr "VÅ¡etci bojovníci ti môžu ponúknuÅ¥, že sa k tebe pridajú." #, fuzzy msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "%{name} znižuje cenu vzdania sa o %{count} percent celkovej ceny jednotiek, " "ktoré máš v armáde." #, fuzzy msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "%{skill} zvýši pohybové body tvojho hrdinu po vode o %{count} percent." #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} zvýši morálku vojska tvojho hrdinu o %{count}." #, fuzzy msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} umožňuje tvojmu hrdinovi nauÄiÅ¥ sa kúzla tretej úrovne." #, fuzzy msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} umožňuje tvojmu hrdinovi nauÄiÅ¥ sa kúzla Å¡tvrtej úrovne." #, fuzzy msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} umožňuje tvojmu hrdinovi nauÄiÅ¥ sa kúzla piatej úrovne." #, fuzzy msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" "%{skill} regeneruje tvojmu hrdinovi o %{count} bod kúziel za deň viac." msgstr[1] "" "%{skill} regeneruje tvojmu hrdinovi o %{count} body kúziel za deň viac." msgstr[2] "" "%{skill} regeneruje tvojmu hrdinovi o %{count} bodov kúziel za deň viac." #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} zvyÅ¡uje šťastie tvojho hrdinu o %{count}." #, fuzzy msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} dáva výstrelom z katapultu tvojho hrdinu väÄÅ¡iu Å¡ancu zasiahnuÅ¥ a " "poÅ¡kodiÅ¥ hradné múry." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} dáva katapultu tvojho hrdinu jeden výstrel navyÅ¡e a každý výstrel " "má väÄÅ¡iu Å¡ancu zasiahnuÅ¥ a poÅ¡kodiÅ¥ hradné múry." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} dáva katapultu tvojho hrdinu jeden výstrel navyÅ¡e a každý výstrel " "automaticky zniÄí akúkoľvek stenu, okrem opevnenej steny v Rytierskom hrade." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} dáva tvojmu hrdinovi %{count}-percentnú Å¡ancu nauÄiÅ¥ sa akékoľvek " "kúzlo 1. alebo 2. úrovne, ktoré bolo zoslané nepriateľom poÄas boja." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} dáva tvojmu hrdinovi %{count}-percentnú Å¡ancu nauÄiÅ¥ sa akékoľvek " "kúzlo 3. úrovne (alebo nižšej), ktoré bolo zoslané nepriateľom poÄas boja." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} dáva tvojmu hrdinovi %{count}-percentnú Å¡ancu nauÄiÅ¥ sa akékoľvek " "kúzlo 4. úrovne (alebo nižšej), ktoré bolo zoslané nepriateľom poÄas boja." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} umožňuje, aby %{count} percent bojovníkov zabitých v boji vstalo z " "mÅ•tvych ako Kostlivci." #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Tvoj hrdina vyprodukuje %{count} zlata za deň ako daňový príjem z majetku." msgid "Blue" msgstr "Modrý" msgid "Green" msgstr "Zelený" msgid "Red" msgstr "ÄŒervený" msgid "Yellow" msgstr "Žltý" msgid "Orange" msgstr "Oranžový" msgid "Purple" msgstr "Fialový" msgid "barrier|Aqua" msgstr "Tyrkysová" msgid "barrier|Blue" msgstr "Modrá" msgid "barrier|Brown" msgstr "Hnedá" msgid "barrier|Gold" msgstr "Zlatá" msgid "barrier|Green" msgstr "Zelená" msgid "barrier|Orange" msgstr "Oranžová" msgid "barrier|Purple" msgstr "Fialová" msgid "barrier|Red" msgstr "ÄŒervená" msgid "tent|Aqua" msgstr "Tyrkysový" msgid "tent|Blue" msgstr "Modrý" msgid "tent|Brown" msgstr "Hnedý" msgid "tent|Gold" msgstr "Zlatý" msgid "tent|Green" msgstr "Zelený" msgid "tent|Orange" msgstr "Oranžový" msgid "tent|Purple" msgstr "Fialový" msgid "tent|Red" msgstr "ÄŒervený" msgid "Experience" msgstr "Skúsenosti" #, fuzzy msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Skúsenosti umožňujú hrdinom zvyÅ¡ovaÅ¥ úroveň, Äím sa zvyÅ¡ujú ich prvotné a " "druhotné zruÄnosti." msgid "Hero/Stats" msgstr "Hrdina/Å tatistika" msgid "Skills" msgstr "ZruÄnosti" msgid "Town/Castle" msgstr "Mesto/Hrad" msgid "Garrison" msgstr "Posádka" msgid "Gold Per Day:" msgstr "Zlato za deň:" msgid "View Heroes." msgstr "Ukáž hrdinov." msgid "Towns/Castles" msgstr "Mestá/Hrady" msgid "View Towns and Castles." msgstr "Ukáž mestá a hrady." msgid "luck|Cursed" msgstr "Prekliate" msgid "luck|Awful" msgstr "Hrozné" msgid "luck|Bad" msgstr "Zlé" msgid "luck|Normal" msgstr "Normálne" msgid "luck|Good" msgstr "Dobré" msgid "luck|Great" msgstr "Skvelé" msgid "luck|Irish" msgstr "Ãrske" #, fuzzy msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "V boji sa na tvoje vojsko niekedy obráti smola a jeho útoky spôsobia len " "poloviÄné poÅ¡kodenie." #, fuzzy msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Neutrálne šťastie znamená, že tvoje vojsko nikdy nebude maÅ¥ šťastie alebo " "smolu pri útokoch na nepriateľa." #, fuzzy msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Šťastie niekedy umožňuje tvojmu vojsku získaÅ¥ šťastné útoky (dvojnásobnú " "silu) v boji." msgid "morale|Treason" msgstr "Zrada" msgid "morale|Awful" msgstr "Hrozná" msgid "morale|Poor" msgstr "Slabá" msgid "morale|Normal" msgstr "Normálna" msgid "morale|Good" msgstr "Dobrá" msgid "morale|Great" msgstr "Skvelá" msgid "morale|Blood!" msgstr "Krvná!" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Zlá morálka môže spôsobiÅ¥, že sa tvoje vojsko v boji zastaví." #, fuzzy msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Neutrálna morálka znamená, že tvoje vojsko nebude nikdy obdarené extra " "útokmi ani nezamrzne v boji." #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Dobrá morálka môže tvojmu vojsku poskytnúť extra útoky v boji." msgid "Knight" msgstr "Rytier" msgid "Barbarian" msgstr "Barbar" msgid "Sorceress" msgstr "ZaklínaÄka" msgid "Warlock" msgstr "ÄŒernokňažník" msgid "Wizard" msgstr "Mág" msgid "Necromancer" msgstr "Nekromant" msgid "Multi" msgstr "Multi" msgid "doubleLined|Knight" msgstr "Rytier" msgid "doubleLined|Barbarian" msgstr "Barbar" msgid "doubleLined|Sorceress" msgstr "ZaklínaÄka" msgid "doubleLined|Warlock" msgstr "" "ÄŒerno-\n" "kňažník" msgid "doubleLined|Wizard" msgstr "Mág" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "Nekromant" msgid "doubleLinedRace|Multi" msgstr "Multi" msgid "doubleLinedRace|Random" msgstr "Náhodná" msgid "speed|Standing" msgstr "Stojaca" msgid "speed|Crawling" msgstr "Plaziaca" msgid "speed|Very Slow" msgstr "Veľmi pomalá" msgid "speed|Slow" msgstr "Pomalá" msgid "speed|Average" msgstr "Priemerná" msgid "speed|Fast" msgstr "Rýchla" msgid "speed|Very Fast" msgstr "Veľmi rýchla" msgid "speed|Ultra Fast" msgstr "Ultrarýchla" msgid "speed|Blazing" msgstr "Spaľujúca" msgid "speed|Instant" msgstr "Okamžitá" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Veverice" msgid "week|Rabbit" msgstr "Zajaca" msgid "week|Gopher" msgstr "Svišťa" msgid "week|Badger" msgstr "Jazveca" msgid "week|Rat" msgstr "Potkana" msgid "week|Eagle" msgstr "Orla" msgid "week|Weasel" msgstr "Lasice" msgid "week|Raven" msgstr "Havrana" msgid "week|Mongoose" msgstr "Mangusty" msgid "week|Dog" msgstr "Psa" msgid "week|Aardvark" msgstr "MravÄiara" msgid "week|Lizard" msgstr "JaÅ¡terice" msgid "week|Tortoise" msgstr "KorytnaÄky" msgid "week|Hedgehog" msgstr "Ježa" msgid "week|Condor" msgstr "Kondora" msgid "week|Ant" msgstr "Mravca" msgid "week|Grasshopper" msgstr "LúÄneho koníka" msgid "week|Dragonfly" msgstr "Vážky" msgid "week|Spider" msgstr "Pavúka" msgid "week|Butterfly" msgstr "Motýľa" msgid "week|Bumblebee" msgstr "ÄŒmeliaka" msgid "week|Locust" msgstr "Kobylky" msgid "week|Earthworm" msgstr "DážÄovky" msgid "week|Hornet" msgstr "Sršňa" msgid "week|Beetle" msgstr "Chrobáka" msgid "week|PLAGUE" msgstr "POHROMY" msgid "week|Unnamed" msgstr "Bez mena" msgid "Desert" msgstr "Púšť" msgid "Snow" msgstr "Sneh" msgid "Wasteland" msgstr "Pustatina" msgid "Beach" msgstr "Pláž" msgid "Lava" msgstr "Láva" msgid "Dirt" msgstr "Hlina" msgid "Grass" msgstr "Tráva" msgid "Ocean" msgstr "Oceán" msgid "maps|Small" msgstr "Malá" msgid "maps|Medium" msgstr "Stredná" msgid "maps|Large" msgstr "Veľká" msgid "maps|Extra Large" msgstr "Extra veľká" msgid "maps|Custom Size" msgstr "Vlastná veľkosÅ¥" msgid "Ore Mine" msgstr "Baňa na rudu" msgid "Sulfur Mine" msgstr "Baňa na síru" msgid "Crystal Mine" msgstr "KryÅ¡tálová baňa" msgid "Gems Mine" msgstr "Baňa na drahokamy" msgid "Gold Mine" msgstr "Zlatá baňa" msgid "Mine" msgstr "Baňa" msgid "Burma shave." msgstr "Barmské holenie." msgid "Next sign 50 miles." msgstr "ÄŽalÅ¡ia znaÄka o 50 míľ." msgid "See Rock City." msgstr "NavÅ¡tívte Rock City." msgid "This space for rent." msgstr "Tieto priestory na prenájom." msgid "No object" msgstr "NiÄ" msgid "Alchemist Lab" msgstr "Alchymistické laboratórium" msgid "Sign" msgstr "ZnaÄka" msgid "Buoy" msgstr "Bója" msgid "Skeleton" msgstr "Kostlivec" msgid "Daemon Cave" msgstr "Jaskyňa démona" msgid "Treasure Chest" msgstr "Truhlica s pokladom" msgid "Faerie Ring" msgstr "Vílý kruh" msgid "Campfire" msgstr "Táborák" msgid "Fountain" msgstr "Fontána" msgid "Gazebo" msgstr "Altánok" msgid "Genie Lamp" msgstr "Džinova lampa" msgid "Archer's House" msgstr "Lukostrelecký dom" msgid "Goblin Hut" msgstr "Chata Goblinov" msgid "Dwarf Cottage" msgstr "TrpasliÄia chalúpka" msgid "Peasant Hut" msgstr "Sedliacka chatrÄ" msgid "Stables" msgstr "Stajne" msgid "Alchemist's Tower" msgstr "Alchymistova veža" msgid "Event" msgstr "UdalosÅ¥" msgid "Dragon City" msgstr "DraÄie mesto" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Maják" msgstr[1] "Majáky" msgstr[2] "Majákov" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Vodné koleso" msgstr[1] "Vodné kolesá" msgstr[2] "Vodných kolies" msgid "Monster" msgstr "Tvor" msgid "Obelisk" msgstr "Obelisk" msgid "Oasis" msgstr "Oáza" msgid "Resource" msgstr "Surovina" msgid "Sawmill" msgstr "Píla" msgid "Oracle" msgstr "VeÅ¡tec" msgid "Shrine of the First Circle" msgstr "Svätyňa prvého kruhu" msgid "Shipwreck" msgstr "Lodný vrak" msgid "Sea Chest" msgstr "Morská truhlica" msgid "Desert Tent" msgstr "Púštny stan" msgid "Stone Liths" msgstr "Kamenné pylóny" msgid "Wagon Camp" msgstr "Vozový tábor" msgid "Hut of the Magi" msgstr "Chata mágov" msgid "Whirlpool" msgstr "Vodný vír" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Veterný mlyn" msgstr[1] "Veterné mlyny" msgstr[2] "Veterných mlynov" msgid "Mermaid" msgstr "Morská panna" msgid "Boat" msgstr "LoÄ" msgid "Random Ultimate Artifact" msgstr "Náhodný ultimátny artefakt" msgid "Random Artifact" msgstr "Náhodný artefakt" msgid "Random Resource" msgstr "Náhodná surovina" msgid "Random Monster" msgstr "Náhodný tvor" msgid "Random Town" msgstr "Náhodné mesto" msgid "Random Castle" msgstr "Náhodný hrad" msgid "Eye of the Magi" msgstr "Oko mágov" msgid "Random Monster - weak" msgstr "Náhodný tvor - slabý" msgid "Random Monster - medium" msgstr "Náhodný tvor - stredný" msgid "Random Monster - strong" msgstr "Náhodný tvor - silný" msgid "Random Monster - very strong" msgstr "Náhodný tvor - veľmi silný" #, fuzzy msgid "Hero" msgstr "Hrdinovia" msgid "Nothing Special" msgstr "NiÄ zvláštne" msgid "Mossy Rock" msgstr "Machový kameň" msgid "Watch Tower" msgstr "Strážna veža" msgid "Tree House" msgstr "Dom na strome" msgid "Tree City" msgstr "Stromové mesto" msgid "Ruins" msgstr "Ruiny" msgid "Fort" msgstr "PevnosÅ¥" msgid "Abandoned Mine" msgstr "Opustená baňa" msgid "Sirens" msgstr "Sirény" msgid "Standing Stones" msgstr "Stojace kamene" msgid "Idol" msgstr "Modla" msgid "Tree of Knowledge" msgstr "Strom poznania" msgid "Witch Doctor's Hut" msgstr "LieÄiteľova chatrÄ" msgid "Temple" msgstr "Chrám" msgid "Hill Fort" msgstr "Hradisko" msgid "Halfling Hole" msgstr "PolÄíÄia diera" msgid "Mercenary Camp" msgstr "Žoldniersky tábor" msgid "Shrine of the Second Circle" msgstr "Svätyňa druhého kruhu" msgid "Shrine of the Third Circle" msgstr "Svätyňa tretieho kruhu" msgid "City of the Dead" msgstr "Mesto mÅ•tvych" msgid "Sphinx" msgstr "Sfinga" msgid "Wagon" msgstr "Voz" msgid "Tar Pit" msgstr "Smolná jama" msgid "Artesian Spring" msgstr "Artézsky prameň" msgid "Troll Bridge" msgstr "Trolí most" msgid "Watering Hole" msgstr "Napájadlo" msgid "Witch's Hut" msgstr "Ježibabin domÄek" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "PrístreÅ¡ok" msgid "Magellan's Maps" msgstr "Magalhaesove mapy" msgid "Flotsam" msgstr "Vyhodený náklad" msgid "Derelict Ship" msgstr "Opustená loÄ" msgid "Shipwreck Survivor" msgstr "TroseÄník" msgid "Bottle" msgstr "FľaÅ¡a" msgid "Magic Well" msgstr "ÄŒarovná studňa" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "ÄŒarovná záhrada" msgstr[1] "ÄŒarovné záhrady" msgstr[2] "ÄŒarovných záhrad" msgid "Observation Tower" msgstr "Rozhľadňa" msgid "Freeman's Foundry" msgstr "Súkromná zlievareň" msgid "Reefs" msgstr "Útesy" msgid "Volcano" msgstr "Sopka" msgid "Flowers" msgstr "Kvety" msgid "Rock" msgstr "Skala" msgid "Water Lake" msgstr "Jazero s vodou" msgid "Mandrake" msgstr "Mandragora" msgid "Dead Tree" msgstr "Odumretý strom" msgid "Stump" msgstr "Peň" msgid "Crater" msgstr "Kráter" msgid "Cactus" msgstr "Kaktus" msgid "Mound" msgstr "Mohyla" msgid "Dune" msgstr "Duna" msgid "Lava Pool" msgstr "Lávové jazierko" msgid "Shrub" msgstr "Krík" msgid "Barrow Mounds" msgstr "Norné mohyly" msgid "Random Artifact - Treasure" msgstr "Náhodný artefakt - Poklad" msgid "Random Artifact - Minor" msgstr "Náhodný artefakt - Menší" msgid "Random Artifact - Major" msgstr "Náhodný artefakt - VäÄší" msgid "Barrier" msgstr "Bariéra" msgid "Traveller's Tent" msgstr "Cestovateľský stan" msgid "Jail" msgstr "Žalár" msgid "Fire Summoning Altar" msgstr "Oltár vyvolávania ohňa" msgid "Air Summoning Altar" msgstr "Oltár vyvolávania vzuchu" msgid "Earth Summoning Altar" msgstr "Oltár vyvolávania zeme" msgid "Water Summoning Altar" msgstr "Oltár vyvolávania vody" #, fuzzy msgid "Swampy Lake" msgstr "MoÄiar" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "Neznámi bojovníci" msgid "Unknown Monster" msgstr "Neznámy bojovník" msgid "Peasant" msgstr "Roľník" msgid "Peasants" msgstr "Roľníci" msgid "Archer" msgstr "Lukostrelec" msgid "Archers" msgstr "Lukostrelci" msgid "Ranger" msgstr "HraniÄiar" msgid "Rangers" msgstr "HraniÄiari" msgid "Pikeman" msgstr "Kopijník" msgid "Pikemen" msgstr "Kopijníci" msgid "Veteran Pikeman" msgstr "Veterán kopijník" msgid "Veteran Pikemen" msgstr "Veteráni kopijníci" msgid "Swordsman" msgstr "Å ermiar" msgid "Swordsmen" msgstr "Å ermiari" msgid "Master Swordsman" msgstr "Majster Å¡ermiar" msgid "Master Swordsmen" msgstr "Majstri Å¡ermiari" msgid "Cavalries" msgstr "Kavaléri" msgid "Cavalry" msgstr "Kavalér" msgid "Champion" msgstr "Å ampión" msgid "Champions" msgstr "Å ampióni" msgid "Paladin" msgstr "Paladín" msgid "Paladins" msgstr "Paladíni" msgid "Crusader" msgstr "Križiak" msgid "Crusaders" msgstr "Križiaci" msgid "Goblin" msgstr "Goblin" msgid "Goblins" msgstr "Goblini" msgid "Orc" msgstr "Ork" msgid "Orcs" msgstr "Orkovia" msgid "Orc Chief" msgstr "NáÄelník orkov" msgid "Orc Chiefs" msgstr "NáÄelníci orkov" msgid "Wolf" msgstr "Vlk" msgid "Wolves" msgstr "Vlky" msgid "Ogre" msgstr "Zlobor" msgid "Ogres" msgstr "Zlobri" msgid "Ogre Lord" msgstr "Lord zlobrov" msgid "Ogre Lords" msgstr "Lordi zlobrov" msgid "Troll" msgstr "Trol" msgid "Trolls" msgstr "Trolovia" msgid "War Troll" msgstr "Bojový trol" msgid "War Trolls" msgstr "Bojoví trolovia" msgid "Cyclopes" msgstr "Kyklopi" msgid "Cyclops" msgstr "Kyklop" msgid "Sprite" msgstr "Víla" msgid "Sprites" msgstr "Víly" msgid "Dwarf" msgstr "Trpaslík" msgid "Dwarves" msgstr "Trpaslíci" msgid "Battle Dwarf" msgstr "Bojový trpaslík" msgid "Battle Dwarves" msgstr "Bojoví trpaslíci" msgid "Elf" msgstr "Elf" msgid "Elves" msgstr "Elfovia" msgid "Grand Elf" msgstr "VzneÅ¡ený elf" msgid "Grand Elves" msgstr "VzneÅ¡ení elfovia" msgid "Druid" msgstr "Druid" msgid "Druids" msgstr "Druidi" msgid "Greater Druid" msgstr "Arcidruid" msgid "Greater Druids" msgstr "Arcidruidi" msgid "Unicorn" msgstr "Jednorožec" msgid "Unicorns" msgstr "Jednorožci" msgid "Phoenix" msgstr "Fénix" msgid "Phoenixes" msgstr "Fénixovia" msgid "Centaur" msgstr "Kentaur" msgid "Centaurs" msgstr "Kentauri" msgid "Gargoyle" msgstr "ChrliÄ" msgid "Gargoyles" msgstr "ChrliÄe" msgid "Griffin" msgstr "Gryf" msgid "Griffins" msgstr "Gryfy" msgid "Minotaur" msgstr "Minotaur" msgid "Minotaurs" msgstr "Minotauri" msgid "Minotaur King" msgstr "Minotaurí kráľ" msgid "Minotaur Kings" msgstr "Minotaurí králi" msgid "Hydra" msgstr "Hydra" msgid "Hydras" msgstr "Hydry" msgid "Green Dragon" msgstr "Zelený drak" msgid "Green Dragons" msgstr "Zelení draci" msgid "Red Dragon" msgstr "ÄŒervený drak" msgid "Red Dragons" msgstr "ÄŒervení draci" msgid "Black Dragon" msgstr "ÄŒierny drak" msgid "Black Dragons" msgstr "ÄŒierni draci" msgid "Halfling" msgstr "PolÄík" msgid "Halflings" msgstr "PolÄíci" msgid "Boar" msgstr "Kanec" msgid "Boars" msgstr "Kance" msgid "Iron Golem" msgstr "Železný golem" msgid "Iron Golems" msgstr "Železní golemovia" msgid "Steel Golem" msgstr "Oceľový golem" msgid "Steel Golems" msgstr "Oceľoví golemovia" msgid "Roc" msgstr "Roch" msgid "Rocs" msgstr "Rochy" msgid "Mage" msgstr "Mág" msgid "Magi" msgstr "Mágovia" msgid "Archmage" msgstr "Arcimág" msgid "Archmagi" msgstr "Arcimágovia" msgid "Giant" msgstr "Obor" msgid "Giants" msgstr "Obri" msgid "Titan" msgstr "Titán" msgid "Titans" msgstr "Titáni" msgid "Skeletons" msgstr "Kostlivci" msgid "Zombie" msgstr "Zombík" msgid "Zombies" msgstr "Zombíci" msgid "Mutant Zombie" msgstr "Zombík mutant" msgid "Mutant Zombies" msgstr "Zombíci mutanti" msgid "Mummies" msgstr "Múmie" msgid "Mummy" msgstr "Múmia" msgid "Royal Mummies" msgstr "Kráľovské múmie" msgid "Royal Mummy" msgstr "Kráľovská múmia" msgid "Vampire" msgstr "Upír" msgid "Vampires" msgstr "Upíri" msgid "Vampire Lord" msgstr "Upírí lord" msgid "Vampire Lords" msgstr "Upírí lordi" msgid "Lich" msgstr "Kostej" msgid "Liches" msgstr "Kostejovia" msgid "Power Lich" msgstr "Mocný kostej" msgid "Power Liches" msgstr "Mocní kostejovia" msgid "Bone Dragon" msgstr "Kostnatý drak" msgid "Bone Dragons" msgstr "Kostnatí draci" msgid "Rogue" msgstr "Tulák" msgid "Rogues" msgstr "Tuláci" msgid "Nomad" msgstr "Nomád" msgid "Nomads" msgstr "Nomádi" msgid "Ghost" msgstr "Duch" msgid "Ghosts" msgstr "Duchovia" msgid "Genie" msgstr "Džin" msgid "Genies" msgstr "Džinovia" msgid "Medusa" msgstr "Medúza" msgid "Medusas" msgstr "Medúzy" msgid "Earth Elemental" msgstr "Zemský elementál" msgid "Earth Elementals" msgstr "Zemskí elementáli" msgid "Air Elemental" msgstr "VzduÅ¡ný elementál" msgid "Air Elementals" msgstr "VzduÅ¡ní elementáli" msgid "Fire Elemental" msgstr "Ohnivý elementál" msgid "Fire Elementals" msgstr "Ohniví elementáli" msgid "Water Elemental" msgstr "Vodný elementál" msgid "Water Elementals" msgstr "Vodní elementáli" msgid "Random Monsters" msgstr "Náhodné tvory" msgid "Random Monster 1" msgstr "Náhodný tvor 1" msgid "Random Monsters 1" msgstr "Náhodné tvory 1" msgid "Random Monster 2" msgstr "Náhodný tvor 2" msgid "Random Monsters 2" msgstr "Náhodné tvory 2" msgid "Random Monster 3" msgstr "Náhodný tvor 3" msgid "Random Monsters 3" msgstr "Náhodné tvory 3" msgid "Random Monster 4" msgstr "Náhodný tvor 4" msgid "Random Monsters 4" msgstr "Náhodné tvory 4" msgid "Double shot" msgstr "Dvojitý výstrel" msgid "2-hex monster" msgstr "Bojovník zaberá 2 polia" msgid "Double strike" msgstr "Dvojitý úder" msgid "Double damage to Undead" msgstr "Dvojité poÅ¡kodenie nemÅ•tvym" msgid "% magic resistance" msgstr "% magická odolnosÅ¥" msgid "Immune to Mind spells" msgstr "Imunita voÄi kúzlam mysli" msgid "Immune to Elemental spells" msgstr "Imunita voÄi elementálnym kúzlam" msgid "Immune to Fire spells" msgstr "Imunita voÄi kúzlam ohňa" msgid "Immune to Cold spells" msgstr "Imunita voÄi kúzlam chladu" msgid "Immune to " msgstr "Imunita voÄi efektu " msgid "% immunity to %{spell} spell" msgstr "% imunity voÄi kúzlu %{spell}" msgid "% damage from Elemental spells" msgstr "% poÅ¡kodenia od elementálnych kúziel" msgid "% damage from %{spell} spell" msgstr "% poÅ¡kodenia od kúzla %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% Å¡anca na rozptýlenie prospeÅ¡ných kúziel" msgid "% chance to Paralyze" msgstr "% Å¡anca na paralyzovanie" msgid "% chance to Petrify" msgstr "% Å¡anca na vydesenie" msgid "% chance to Blind" msgstr "% Å¡anca na oslepenie" msgid "% chance to Curse" msgstr "% Å¡anca na prekliatie" msgid "% chance to cast %{spell} spell" msgstr "% Å¡anca na vyÄarovanie kúzla %{spell}" msgid "HP regeneration" msgstr "Regenerácia zdravia" msgid "Two hexes attack" msgstr "Útok cez dve polia" msgid "Flyer" msgstr "Lieta" msgid "Always retaliates" msgstr "Vždy vracia úder" msgid "Attacks all adjacent enemies" msgstr "ÚtoÄí na vÅ¡etkých susedných nepriateľov" msgid "No melee penalty" msgstr "Bez penalizácie na blízko" msgid "Dragon" msgstr "Drak" msgid "Undead" msgstr "NemÅ•tvy" msgid "No enemy retaliation" msgstr "Nepriateľ nevracia úder" msgid "HP drain" msgstr "ÄŒerpanie zdravia" msgid "Cloud attack" msgstr "Útok mraÄna" msgid "Decreases enemy's morale by " msgstr "Znižuje morálku nepriateľa o " msgid "% chance to halve enemy" msgstr "% Å¡anca na rozpolenie nepriateľa" msgid "Soul Eater" msgstr "HltaÄ duší" msgid "Elemental" msgstr "Elementál" msgid "No Morale" msgstr "Žiadna morálka" #, fuzzy msgid "Earth creature" msgstr "NajaÅ¥ bojovníkov" #, fuzzy msgid "Air creature" msgstr "NajaÅ¥ bojovníkov" #, fuzzy msgid "Fire creature" msgstr "NajaÅ¥ bojovníkov" #, fuzzy msgid "Water creature" msgstr "Jazero s vodou" #, fuzzy msgid "Double damage from Fire spells" msgstr "Dvojité poÅ¡kodenie od kúziel ohňa" #, fuzzy msgid "Double damage from Cold spells" msgstr "Dvojité poÅ¡kodenie od kúziel chladu" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Odstráni vÅ¡etky kúzla zo vÅ¡etkých tvorov." #, fuzzy msgid "Double damage from Air creatures" msgstr "Dvojité poÅ¡kodenie nemÅ•tvym" #, fuzzy msgid "Double damage from Fire creatures" msgstr "Dvojité poÅ¡kodenie od kúziel ohňa" #, fuzzy msgid "Double damage from Water creatures" msgstr "Odstráni vÅ¡etky kúzla zo vÅ¡etkých tvorov." msgid "Lightning" msgstr "Blesk" msgid "% immunity to " msgstr "% imunity voÄi: " msgid "% damage from " msgstr "% poÅ¡kodenie od: " msgid "The three Anduran artifacts magically combine into one." msgstr "Tri Anduranove artefakty sa Äarovne spojili do jedného." msgid "View Spells" msgstr "Zobraz kúzla" msgid "View %{name} Info" msgstr "Zobraz info: %{name}" msgid "Move %{name}" msgstr "Presuň %{name}" msgid "Cannot move the Spellbook" msgstr "Kniha kúziel sa nedá presunúť" msgid "This item can't be traded." msgstr "Tento predmet sa nedá zameniÅ¥." msgid "Invalid Artifact" msgstr "Neplatný artefakt" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} zvyÅ¡uje tvoje vedomosti o %{count}." msgid "Ultimate Book of Knowledge" msgstr "Ultimátna kniha vedomostí" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} zvyÅ¡uje tvoju útoÄnú zruÄnosÅ¥ o %{count}." msgid "Ultimate Sword of Dominion" msgstr "Ultimátny meÄ nadvlády" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} zvyÅ¡uje tvoju obrannú zruÄnosÅ¥ o %{count}." msgid "Ultimate Cloak of Protection" msgstr "Ultimátny plášť ochrany" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} zvyÅ¡uje tvoju silu kúziel o %{count}." msgid "Ultimate Wand of Magic" msgstr "Ultimátny Äarovný prútik" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} zvyÅ¡uje tvoju útoÄnú aj obrannú zruÄnosÅ¥ o %{count}." msgid "Ultimate Shield" msgstr "Ultimátny Å¡tít" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} zvyÅ¡uje tvoje vedomosti aj silu kúziel o %{count}." msgid "Ultimate Staff" msgstr "Ultimátna palica" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} zvyÅ¡uje vÅ¡etky tvoje zruÄnosti o %{count}." msgid "Ultimate Crown" msgstr "Ultimátna koruna" msgid "Golden Goose" msgstr "Zlatá hus" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} zvyÅ¡uje príjem o %{count} zlata za deň." msgid "Arcane Necklace of Magic" msgstr "Tajomný magický náhrdelník" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Po záchrane Äarodejnice z prekliatej hrobky odmení tvoje hrdinstvo nádherným " "Å¡perkovým náhrdelníkom." msgid "Caster's Bracelet of Magic" msgstr "ZaklínaÄov náramok mágie" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Pri prehľadávaní trosiek zavalenej bane oslobodíš skupinu uväznených " "Trpaslíkov. Ich vodca ti s vÄakou daruje zlatý náramok." msgid "Mage's Ring of Power" msgstr "ÄŒarodejov prsteň moci" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Výkrik bolesti Å¥a privedie ku Kentaurovi, ktorý sa chytil do pasce. KeÄ ho " "oslobodíš, podá ti malé vrecúško. VyprázdniÅ¡ obsah a nájdeÅ¡ oslnivý prsteň s " "drahokamami." msgid "Witch's Broach of Magic" msgstr "Bosorkina brošňa mágie" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Vedľa pozostatkov spálenej bosorky leží krásna brošňa so zložitým dizajnom. " "Opatrne sa priblížiÅ¡ k mÅ•tvole a pridáš brošňu do svojho inventára." msgid "Medal of Valor" msgstr "Medaila za statoÄnosÅ¥" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} zvyÅ¡uje tvoju morálku o %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Za oslobodenie cnostnej panny z pazúrov zlého vladára vám kráľovský herold " "udelí Medailu za statoÄnosÅ¥." msgid "Medal of Courage" msgstr "Medaila za odvahu" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Po záchrane malého chlapca pred zúrivou VlÄou svorkou ho vrátiÅ¡ na panstvo " "jeho otca. VÄaÄný šľachtic ti udelí Medailu za odvahu." msgid "Medal of Honor" msgstr "Medaila cti" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Po oslobodení princeznej susedného kráľovstva z pazúrov podlých otrokárov ti " "udelí Medailu cti." msgid "Medal of Distinction" msgstr "Medaila za zásluhy" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Zbavil/a si krajinu ohavného Minotaura, ktorý sa vyžíval v požieraní " "šľachtických rytierov a dostávaÅ¡ vyznamenanie Medaila za zásluhy." msgid "Fizbin of Misfortune" msgstr "Fizbin nešťastia" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} znižuje tvoju morálku o %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Narazíš na medailu, ktorá leží pri prázdnej ceste. KeÄ medailu pridáš do " "svojho inventára, zistíš, že si získal/a nežiaduci Fizbin nešťastia, ktorý " "výrazne znižuje morálku tvojej armády." msgid "Thunder Mace of Dominion" msgstr "Hromový palcát nadvlády" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "PoÄas náhlej búrky udrie blesk do stromu a rozÅ¡tiepi ho. Vo vnútri stromu " "nájdeÅ¡ záhadný palcát." msgid "Armored Gauntlets of Protection" msgstr "Obrnené ochranné rukavice" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} zvyÅ¡uje tvoju obrannú zruÄnosÅ¥ o %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "StretávaÅ¡ sa s neslávne známym ÄŒiernym rytierom! Po vyÄerpávajúcom súboji, " "ktorý sa skonÄil remízou, ti rytier z úcty ponúkne pár obrnených rukavíc." msgid "Defender Helm of Protection" msgstr "Ochranná prilba obrancu" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Do oÄí ti padne odlesk zlatého svetla. Pri ÄalÅ¡om skúmaní nájdeÅ¡ zlatú " "prilbu ukrytú pod kríkom." msgid "Giant Flail of Dominion" msgstr "Obrovský cep nadvlády" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Nemotorný Obor sa zabil vlastným cepom. KeÄže vieÅ¡, že s touto zbraňou vieÅ¡ " "narábaÅ¥ lepÅ¡ie, s istotou odoberieÅ¡ padlému Obrovi ten veľkolepý cep." msgid "Ballista of Quickness" msgstr "Balista rýchlosti" #, fuzzy msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "%{name} dáva tvojmu katapultu jednu strelu navyÅ¡e každé kolo boja." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Prechádzajúc ruinami starobylého opevneného mesta nájdeÅ¡ nástroj jeho " "zniÄenia, dômyselne vyrobenú balistu." msgid "Stealth Shield of Protection" msgstr "Ochranný Å¡tít prikrádania" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Kamenná socha bojovníka drží strieborný Å¡tít. KeÄ Å¡tít odstrániÅ¡, socha sa " "rozpadne na prach." msgid "Dragon Sword of Dominion" msgstr "DraÄí meÄ nadvlády" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "KeÄ kráÄaÅ¡ po úzkej cestiÄke, neÄaleký krík náhle vzplanie. Pred tvojimi " "oÄami sa z plameňov stane obraz krásnej ženy. Tá k tebe vystiera nádherný " "meÄ." msgid "Power Axe of Dominion" msgstr "Mocná sekera nadvlády" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Vidíš striebornú sekeru zaseknutú hlboko do zeme. Po niekoľkých neúspeÅ¡ných " "pokusoch tvojho vojska odstrániÅ¥ sekeru pevne uchopíš rukoväť sekery a bez " "námahy ju vytiahneÅ¡." msgid "Divine Breastplate of Protection" msgstr "Božský náprsník ochrany" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Banda Tulákov prehľadáva majetok mÅ•tvych bojovníkov. Odplašíš tých smetiarov " "a vÅ¡imneÅ¡ si, že Tuláci prehliadli krásny hrudný plát." msgid "Minor Scroll of Knowledge" msgstr "Menší zvitok vedomostí" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Pred tebou sa objaví levitujúca sklenená skrinka so zvitkom, posadená na " "posteli z karmínového zamatu. Na tvoj dotyk sa veko otvorí a zvitok sa " "vznesie do tvojich Äakajúcich rúk." msgid "Major Scroll of Knowledge" msgstr "Hlavný zvitok vedomostí" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Pri návÅ¡teve miestneho mudrca mu vysvetlíš zámer svojej cesty. Siahne do " "vreca, vytiahne zažltnutý zvitok a podá ti ho." msgid "Superior Scroll of Knowledge" msgstr "Nadradený zvitok vedomostí" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Narazíš na pozostatky starobylej Druidky. Z ošúchaných záhybov jej rúcha " "vykúkajú vekom zožltnuté kosti. Pri prehľadávaní rúcha objavíš zvitok ukrytý " "v záhyboch." msgid "Foremost Scroll of Knowledge" msgstr "Najprednejší zvitok vedomostí" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Z ošúchaných záhybov mÅ•tveho Druida vykúkajú vekom zožltnuté kosti. Pri " "prehľadávaní rúcha objavíš zvitok, ktorý je v ňom ukrytý." msgid "Endless Sack of Gold" msgstr "Bezodné vrecko zlata" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} ti poskytuje %{count} zlata za deň." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Malý leprikón veselo tancuje okolo Äarovného vreca. KeÄ Å¥a zbadá, zastaví sa " "uprostred kroku. Malý mužík skríkne, zúrivo dupne nohou a rozplynie sa vo " "vzduchu. SpomenieÅ¡ si na staré Å¡kriatkovské príslovie \"Kto si naÅ¡iel nech " "si nechá.\", chytíš vrece a odchádzaÅ¡." msgid "Endless Bag of Gold" msgstr "Bezodný meÅ¡ec zlata" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "ŠľachtiÄná, ktorá sa oddelila od svojich spoloÄníkov, Å¥a žiada o pomoc. Po " "tom, Äo ju odprevadíš domov, Å¥a odmení meÅ¡com plným zlata." msgid "Endless Purse of Gold" msgstr "Bezodné vrece zlata" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Na svojich cestách nájdeÅ¡ kožený meÅ¡ec plný zlata, ktorý kedysi patril " "veľkému kráľovi bojovníkovi, ktorý mal schopnosÅ¥ premeniÅ¥ akýkoľvek neživý " "predmet na zlato." msgid "Nomad Boots of Mobility" msgstr "Nomádske topánky mobility" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "%{name} zvyÅ¡ujú tvoj pohyb po súši." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Nomádsky obchodník hľadá ochranu pred kmeňom Goblinov. Za tvoju pomoc ti dá " "precízne vyrobený pár topánok z tej najjemnejÅ¡ej kože. Pri pozornom pohľade " "vidíš v koži vyryté fascinujúce starobylé rytiny." msgid "Traveler's Boots of Mobility" msgstr "Cestovateľove topánky mobility" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Objaviac pár nádherných topánok s koráľami vyrobených z najlepÅ¡ej a " "najjemnejÅ¡ej kože, poÄakujeÅ¡ anonymnému darcovi a pridáš topánky do svojho " "inventára." msgid "Lucky Rabbit's Foot" msgstr "ZajaÄia labka" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} zvyÅ¡uje tvoje šťastie v boji o %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Cestujúci obchodník ti ponúkne králiÄiu nohu z lesklej striebornej kožuÅ¡iny, " "aby si bezpeÄne preÅ¡iel. Obchodník ti vysvetľuje, že tento amulet ti " "prinesie viac šťastia v boji." msgid "Golden Horseshoe" msgstr "Zlatá podkova" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Chytený Jednorožec vystraÅ¡ene zakňuÄal. Å epkajúc upokojujúce slová ju " "vyslobodíš. Odfrkne si a raz dupne predným kopytom a odcvála. Pri pohľade " "dolu vidíš zlatú podkovu." msgid "Gambler's Lucky Coin" msgstr "Hazardérova šťastná minca" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Chytil/a si zákerného zloducha, ktorý terorizuje celý región. Výmenou za " "jeho prepustenie sa ti odvÄaÄí magickou mincou." msgid "Four-Leaf Clover" msgstr "Å tvorlístok" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Uprostred mÅ•tveho a suchého porastu nájdeÅ¡ na svoje prekvapenie zdravý " "zelený Å tvorlístok." msgid "True Compass of Mobility" msgstr "Kompas mobility" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} zlepÅ¡uje tvoj pohyb na súši aj na mori." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Starý muž, ktorý sa vyhlasuje za vynálezcu, Å¥a požiada, aby si vyskúšal jeho " "najnovší vynález. Potom ti podá kompas." msgid "Sailor's Astrolabe of Mobility" msgstr "Námorníkov astroláb mobility" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} zvyÅ¡uje tvoj pohyb na mori." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Starého námorného kapitána muÄia Zlobri. ZachrániÅ¡ ho a on Å¥a na oplátku " "odmení úchvatným prístrojom na meranie vzdialenosti hviezd." msgid "Evil Eye" msgstr "Zlé oko" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} znižuje cenu za Äarovanie zaklínadiel o polovicu." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Pri vstupe do schátranej chatrÄe nájdeÅ¡ kostru dávno mÅ•tvej bosorky. Pri " "skúmaní pozostatkov objavíš sklenené oko, ktoré sa váľa v prázdnej lebke." msgid "Enchanted Hourglass" msgstr "ZaÄarované presýpacie hodiny" #, fuzzy msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "%{name} predlžuje dobu trvania vÅ¡etkých tvojich kúziel o %{count} kôl." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Pri neÄakanej zákrute v krajine sa ocitneÅ¡ uprostred hrôzostraÅ¡nej scény: " "Supy si pochutnávajú na následkoch straÅ¡nej bitky. Pri zbežnom prehľadávaní " "pozostatkov objavíš ZaÄarované presýpacie hodiny." msgid "Gold Watch" msgstr "Zlaté hodinky" #, fuzzy msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} zdvojnásobujú efektivitu tvojich kúziel hypnózy." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Obchodník s elixírmi ti za pomoc pri vyÅ¥ahovaní vozíka z priekopy dáva " "\"Äarovné\" zlaté hodinky. Nevie vÅ¡ak, že hodinky sú naozaj Äarovné." msgid "Skullcap" msgstr "ÄŒiapka" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} znižuje cenu za Äarovanie kúziel ovplyvňujúcich myseľ o polovicu." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Krátka zastávka v nepredvídateľnom vidieckom hostinci prináša výmenu peňazí, " "príbehov a náhodou aj batožiny. Vo svojom novom batohu nájdeÅ¡ Äarovnú Äiapku." msgid "Ice Cloak" msgstr "Ľadový plášť" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} znižuje poÅ¡kodenie, ktoré tvoje jednotky utŕžia od kúziel chladu." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "PoÄujeÅ¡ panické výkriky dievÄiny v núdzi a objavíš mladú ženu, ktorá uteká " "pred hladným medveÄom. Zviera v okamihu zabijeÅ¡ a vÄaÄná ZaklínaÄka ti z " "medvedej kože utká magický plášť." msgid "Fire Cloak" msgstr "Ohnivý plášť" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} znižuje poÅ¡kodenie, ktoré tvoje jednotky utŕžia od kúziel ohňa." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Natrafíš na boj medzi Nekromantom a Paladinom. Nekromant zasiahne Paladina " "ohnivým bleskom a zrazí ho na kolená. Konáš rýchlo a pred posledným úderom " "zlosyna zabijeÅ¡. VÄaÄný paladin ti dá ohnivý plášť, ktorý ho zachránil." msgid "Lightning Helm" msgstr "Helma blesku" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} znižuje poÅ¡kodenie, ktoré tvoje jednotky utŕžia od kúziel blesku." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Potulný drotár, ktorý potrebuje zásoby, ti výmenou za jedlo a vodu ponúkne " "prilbu s motívom blesku na vrchu. Zo zvedavosti ju prijímaÅ¡ a neskôr zistíš, " "že prilba je magická." msgid "Evercold Icicle" msgstr "VeÄne chladný cencúľ" #, fuzzy msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} zapríÄiní, že tvoje kúzla chladu spôsobia o %{count} percent viac " "poÅ¡kodenia nepriateľským jednotkám." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Tvoju pozornosÅ¥ upúta cencúľ, ktorý odoláva plnému žiaru poludňajÅ¡ieho " "slnka. Zaujato ho odlomíš a zistíš, že sa ti v ruke neroztopí." msgid "Everhot Lava Rock" msgstr "VeÄne horúci lávový kameň" #, fuzzy msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} zapríÄiní, že tvoje kúzla ohňa spôsobia o %{count} percent viac " "poÅ¡kodenia nepriateľským jednotkám." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Tvoje putovanie Å¥a privedie do kontaktu s kmeňom ľudoopov, ktorí používajú " "magickú lávovú horninu, ktorá nikdy nevychladne, na zapaľovanie ohňa. " "ZľutujeÅ¡ sa nad nimi a nauÄíš ich rozkladaÅ¥ oheň pomocou palíc. Opice Å¥a " "považujú za boha a dajú ti svoj kameň." msgid "Lightning Rod" msgstr "Bleskozvod" #, fuzzy msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} zapríÄiní, že tvoje kúzla blesku spôsobia o %{count} percent viac " "poÅ¡kodenia nepriateľským jednotkám." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "PoÄas Äakania na koniec búrky udrie blesk do bleskozvodu neÄalekej chaty, " "ten sa roztopí a spadne na zem. Å piÄka bleskozvodu vÅ¡ak prežije neporuÅ¡ená a " "keÄ sa jej dotýkaÅ¡, vstávajú ti vlasy dupkom. Hmm..." msgid "Snake-Ring" msgstr "Hadí prsteň" #, fuzzy msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "%{name} znižuje cenu za Äarovanie kúziel žehnania o polovicu." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Na prste dávno mÅ•tveho cestovateľa nájdeÅ¡ prsteň zvláštneho tvaru. Prsteň " "vyzerá ako had, ktorý si hryzie vlastný chvost." msgid "Ankh" msgstr "Anch" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} zdvojnásobujú efektivitu tvojich kúziel vzkriesenia a oživenia." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Prudká víchrica odhalí vchod do zasypanej hrobky. Tvoje vyÅ¡etrovanie odhalí, " "že hrobka už bola vyrabovaná, ale zlodeji v tme prehliadli anch na " "striebornej retiazke." msgid "Book of Elements" msgstr "Kniha elementov" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} zdvojnásobujú efektivitu tvojich kúziel vyvolávania." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Narazíš na zaklínaÄa, ktorý Å¥a prosí, aby teba a tvoju armádu mohol, z " "dôvodu bezpeÄnosti, na nejaký Äas sprevádzaÅ¥. Súhlasíš a on ti ako odmenu " "ponúkne kópiu Knihy živlov." msgid "Elemental Ring" msgstr "Prsteň elementov" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "%{name} znižuje cenu za Äarovanie kúziel vyvolávania o polovicu." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "PoÄas odpoÄinku si vÅ¡imneÅ¡ rysa, ktorý vylieza na krátky strom, aby sa " "dostal k hniezdu vrany. Impulzívne vylezieÅ¡ na strom a toho rysa odplašíš. " "KeÄ sa pozrieÅ¡ do hniezda, nájdeÅ¡ zbierku lesklých kameňov a prsteň." msgid "Holy Pendant" msgstr "Svätý prívesok" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi kliatbam." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Na svojich potulkách narazíš na pustovníka, ktorý žije v malej upratanej " "chatrÄi. Zapôsobí naňho tvoje poslanie, a tak si nájde Äas na meditáciu, aby " "ti požehnal a dal amulet proti kliatbám." msgid "Pendant of Free Will" msgstr "Prívesok slobodnej vôle" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi kúzlam hypnózy." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "PoÄujeÅ¡ volanie o pomoc, a náchádzaÅ¡ rieÄne Víly, ako sa zabávajú namáÄaním " "starého muža. CítiÅ¡ sa pomstychtivo, zachrániÅ¡ muža a na chvíľu vytiahneÅ¡ " "Vílu na suchú zem. Víla, cítiaca sa vo vzduchu nepohodlne, ti dá Äarovný " "prívesok, aby si ju pustil." msgid "Pendant of Life" msgstr "Prívesok života" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi kúzlam smrti." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Krátke stretnutie s malou karavánou pri ceste a astragaly ti vyhrávajú " "Äarovný prívesok. Jeho bývalý majiteľ tvrdí, že chráni pred kúzlami smrti " "nekromantov." msgid "Serenity Pendant" msgstr "Prívesok pokoja" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi kúzlam Å¡ialenstva." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Zvuky boja Å¥a prilákajú na scénu boja medzi starým barbarom a osemhlavou " "hydrou. Tvoj vÄasný zásah zvráti bitku v prospech muža a ten sa ti odvÄaÄí " "príveskom, ktorý používal na upokojenie mysle v boji." msgid "Seeing-eye Pendant" msgstr "Prívesok vidiaceho oka" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi kúzlam slepoty." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Narazíš na veľmi starú ženu, ktorá už dávno oslepla na Å¡edý zákal a osamelo " "zomiera. Postaráš sa o jej posledné potreby a sľúbiÅ¡ jej riadny pohreb. " "VÄaÄne ti dá Äarovný prívesok so Å¡tylizovaným okom. Umožní ti vidieÅ¥ so " "zatvorenými oÄami." msgid "Kinetic Pendant" msgstr "Kinetický prívesok" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi kúzlam paralýzy." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Narazíš na golema so žiarivým príveskom, ktorý ti blokuje cestu. Na základe " "predtuchy mu prívesok z krku odrežeÅ¡. Golem sa rozpadne, keÄ príde o zdroj " "energie, a magický prívesok zostane tebe." msgid "Pendant of Death" msgstr "Prívesok smrti" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi svätým kúzlam." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Rýchly a smrtiaci súboj s Nekromantom ti prinesie jeho magický prívesok. " "Neskôr ti Mág povie, že prívesok chráni nemÅ•tvych pod tvojou kontrolou pred " "kúzlami svätého slova." msgid "Wand of Negation" msgstr "NegaÄný prútik" #, fuzzy msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "%{name} robí vÅ¡etky tvoje jednotky imúnnymi voÄi kúzlam smrti." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "StretneÅ¡ svojho starého priateľa-Äarodejníka, ktorý cestuje opaÄným smerom. " "Dá ti darÄek: Prútik, ktorý zabráni použitiu kúzla rozptýlenia mágie na " "tvojich spojencov." msgid "Golden Bow" msgstr "Zlatý luk" #, fuzzy msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} odstraňuje %{count} percentnú penaltu tvojich jednotiek za streľbu " "spoza prekážok." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Pri náhodnom stretnutí so slávnym lukostrelcom si zahráte astragaly o jeho " "luk proti tvojmu koňovi. Vyhráš." msgid "Telescope" msgstr "Teleskop" #, fuzzy msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} zvyÅ¡uje množstvo terénu, ktorý tvoj hrdina odhalí poÄas prechodu o " "%{count} polí navyÅ¡e." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Obchodník z Äalekých krajín ti vymení nový vynález svojho ľudu za cestovné " "zásoby. VÄaka nemu sa vzdialené predmety zdajú byÅ¥ bližšie a on ho " "nazýva...\n" "\n" "teleskop." msgid "Statesman's Quill" msgstr "Å tátnikovo brko" #, fuzzy msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} znižuje cenu vzdania sa o %{count} percent celkovej ceny jednotiek, " "ktoré máš v armáde." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Zastavíš sa na pomoc diplomatovi so zlomenou nápravou, a vyrieÅ¡iÅ¡ jeho " "problém. Z vÄaky ti dá brko na písanie s magickými vlastnosÅ¥ami, ktoré podľa " "neho \"pomôže ľuÄom vidieÅ¥ veci tak, ako ich vidíš ty\"." msgid "Wizard's Hat" msgstr "ÄŒarodejníkov klobúk" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} predlžuje dobu trvania tvojich kúziel o %{count} kôl." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Vidíš Mága, ktorý uteká pred Gryfom a uháňa ako vietor. Mág otvorí portál a " "prejde ním, priÄom mu okraj toho portálu zrazí klobúk z hlavy. Gryf ho " "nasleduje; portál sa zatvorí. ZdvihneÅ¡ klobúk, oprášiÅ¡ ho a nasadíš si ho." msgid "Power Ring" msgstr "Prsteň moci" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "%{name} vráti %{count} bodov kúziel za deň tvojmu hrdinovi." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "NájdeÅ¡ malý strom, ktorý sa veľmi podobá veľkému ÄŒernokňažníkovi Carnauthovi " "s prsteňom okolo jednej z jeho vetviÄiek. Úlomky obleÄenia a hnijúca koža Å¥a " "vedú k podozreniu, že to JE premenený Carnauth. KeÄže mu nemôžeÅ¡ pomôcÅ¥, " "vezmeÅ¡ si Äarovný prsteň." msgid "Ammo Cart" msgstr "MuniÄný vozík" #, fuzzy msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} poskytuje nekoneÄnú muníciu vÅ¡etkým tvojim jednotkám, ktoré " "strieľajú." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Upúta Å¥a vozík s muníciou uprostred starého bojiska. Kontrola ukáže, že je v " "dobrom stave, a tak ho beriete so sebou." msgid "Tax Lien" msgstr "Daňové záložné právo" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} Å¥a stojí %{count} zlata za deň." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Kvôli tvojim veľkým zvykom v oblasti míňania ti vznikol obrovský daňový " "úÄet, ktorý nedokážeÅ¡ zaplatiÅ¥. Daňový úradník sa zľutuje a súhlasí s tým, " "že si z tvojho úÄtu bude doživotne braÅ¥ len 250 zlatých denne. Tu oznaÄ, ak " "chceÅ¡, aby jeden dolár iÅ¡iel na volebný fond prezidentskej kampane." msgid "Hideous Mask" msgstr "Ohavná maska" #, fuzzy msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "%{name} zabraňuje vÅ¡etkým putovným jednotkám, aby sa pridali k tvojmu " "hrdinovi." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Pri vykrádaní hrobu Sinfilasa Gardolada, slávneho ÄŒernokňažníka meniaceho " "podobu, objavíš jeho legendárnu masku. Chvejúc sa, si ju nasadíš a ona ti " "skrúti tvár do straÅ¡nej grimasy! Ale nie! V skutoÄnosti je to ohavná maska " "Gromlucka Greena a ty si s ňou v pasci." msgid "Endless Pouch of Sulfur" msgstr "Bezodný meÅ¡ec síry" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} poskytuje %{count} jednotky síry za deň." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "NavÅ¡tíviÅ¡ alchymistu, ktorý sa pri pohľade na tvoju armádu presvedÄí o " "spravodlivosti tvojej veci. Nový lojálny poddaný ti dá svoj bezodný meÅ¡ec " "síry, aby ti pomohol s vojnovým úsilím." msgid "Endless Vial of Mercury" msgstr "NekoneÄná fľaÅ¡tiÄka s ortuÅ¥ou" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} poskytuje %{count} jednotky ortuti za deň." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Pri krátkej zastávke v narýchlo opustenej Magickej veži sa nájde Äarovná " "fľaÅ¡tiÄka s ortuÅ¥ou, v ktorej vždy zostane trochu na dne. HneÄ ako rozpoznáš " "poklad, uzavrieÅ¡ ju a strÄíš si ju do vrecka." msgid "Endless Pouch of Gems" msgstr "Bezodný meÅ¡ec drahokamov" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} poskytuje %{count} jednotky drahokamov za deň." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Krátky dÃ¡Å¾Ä prinesie dúhu... a ty môžeÅ¡ vidieÅ¥ jej koniec. Na koni sa rýchlo " "zmocníš hrnca zlata, ktorý tam nájdeÅ¡. Leprikón, ktorému patrí, ti nedokáže " "zabrániÅ¥, aby si si ho vzal, a za vrátenie zlata ti ponúka nekoneÄný meÅ¡ec " "drahokamov. Ty súhlasíš." msgid "Endless Cord of Wood" msgstr "NekoneÄná fúra dreva" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} poskytuje %{count} jednotky dreva za deň." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "PoÄas odpoÄinku a zakladania ohňa na varenie vytiahneÅ¡ drevo z neÄalekej " "hromady suchého dreva. Ako z hromady vyÅ¥ahujeÅ¡ drevo, vÅ¡imneÅ¡ si, že sa " "nezmenÅ¡uje. Na vlastnú radosÅ¥ si uvedomíš, že drevo je zaÄarované, a tak si " "ho vezmeÅ¡ so sebou." msgid "Endless Cart of Ore" msgstr "NekoneÄný vozík s rudou" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} poskytuje %{count} jednotky rudy za deň." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "NájdeÅ¡ Gobliniu kováÄsku dielňu, kdea sa vyrábajú zbrane na použitie proti " "ľuÄom. S mohutným krikom sa so svojou armádou spustíte na ich tábor a " "zaženiete ich preÄ. Pri pátraní nájdeÅ¡ Äarovný vozík na rudu, v ktorom nikdy " "nedochádza železo." msgid "Endless Pouch of Crystal" msgstr "MeÅ¡ec nekoneÄného kryÅ¡tálu" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} poskytuje %{count} jednotky kryÅ¡tálu za deň." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "KeÄ sa ukrývaÅ¡ pred búrkou v malej jaskyni, v jednom rohu si vÅ¡imneÅ¡ malý " "kúsok kryÅ¡tálu. Zo zvedavosti kúsok odlomíš a vÅ¡imneÅ¡ si, že pôvodný kryÅ¡tál " "dorastá späť. RozhodneÅ¡ sa celý kúsok vložiÅ¥ do vrecka a vziaÅ¥ si ho so " "sebou." msgid "Spiked Helm" msgstr "Ostnatá prilba" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Tvoju armádu prepadne malý kmeň divokých (a nie príliÅ¡ bystrých) Orkov. " "Ľahko ich odrazíte a tí, Äo prežili, utekajú na vÅ¡etky strany. Jeden z orkov " "mal na hlave vyleÅ¡tenú prilbu s ostňami. UsudzujeÅ¡, že to bude dobrý " "suvenír, a berieÅ¡ si ju." msgid "Spiked Shield" msgstr "Ostnatý Å¡tít" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Natrafíš na most, ktorý preklenuje suchú roklinu. Skôr ako sa ti podarí " "prejsÅ¥, spod mosta vystúpi Trol a žiada platbu, kým ti dovolí prejsÅ¥. KeÄ " "odmietneÅ¡, Trol na teba zaútoÄí a prinúti Å¥a ho zabiÅ¥. Jeho Å¡tít s ostňami " "si zoberieÅ¡ ako trofej." msgid "White Pearl" msgstr "Biela perla" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Prechádzka po vyschnutom dne slaného jazera prináša nepravdepodobnú cenu: " "Medzi rozbitými mušľami a troskami objavíš bielu perlu." msgid "Black Pearl" msgstr "ÄŒierna perla" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Zvesti o Gryfovi nezvyÄajnej veľkosti, ktorý loví na vidieku, Å¥a zavedú do " "jeho jaskynného brlohu. V rýchlom a brutálnom boji sa ti podarí Å¡elmu " "zlikvidovaÅ¥ a pri prehľadávaní jej ohavného hniezda nájdeÅ¡ obrovskú Äiernu " "perlu." msgid "Magic Book" msgstr "Kniha kúziel" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name} ti umožňuje zosielaÅ¥ kúzla." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Atrapa 2" msgid "The reserved artifact." msgstr "Vyhradený artefakt." msgid "Dummy 3" msgstr "Atrapa 3" msgid "Dummy 4" msgstr "Atrapa 4" msgid "Spell Scroll" msgstr "Zvitok s kúzlom" #, fuzzy msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Tento %{name} dáva tvojmu hrdinovi schopnosÅ¥ zoslaÅ¥ kúzlo %{spell}, ak má " "tvoj hrdina Magickú knihu." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "NájdeÅ¡ zložitú nádobu, v ktorej je starý pergamenový zvitok. Runy na nádobe " "sú veľmi staré a majstrovstvo, s akým bola nádoba zostavená, je ohromujúce. " "KeÄ zvitok vytiahneÅ¡, cítiÅ¡, že do teba preniká magická sila." msgid "Arm of the Martyr" msgstr "Paža muÄeníka" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} zvyÅ¡uje tvoju Silu kúziel o %{count}, ale pridáva postih morálky za " "nemÅ•tvych v skupine." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Jeden z menej inteligentných Älenov tvojej skupiny zdvihne zo zeme ruku. " "Napriek tomu, že jej chýba telo, stále sa hýbe. Tvoji vojaci považujú " "rozÅ¡tvrtenú ruku za odpudzujúcu, ale ty sa nemôžeÅ¡ prinútiÅ¥ ju pustiÅ¥: zdá " "sa, že má akúsi magickú moc, ktorá ovplyvňuje tvoje rozhodovanie." msgid "Breastplate of Anduran" msgstr "Anduranove prsné brnenie" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} zvyÅ¡uje tvoju obranu o %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Narazíš na znaÄku. Je na nej napísané: \"Tu leží Anduranovo telo. Pokloň sa " "a prisahaj vernosÅ¥ a budeÅ¡ odmenený.\" RozhodneÅ¡ sa urobiÅ¥ tak. KeÄ sa " "postavíš, pocítiÅ¡ na koži chlad. KeÄ sa pozrieÅ¡ dolu, zistíš, že zrazu máš " "na sebe lesklé, zdobené prsné brnenie." msgid "Broach of Shielding" msgstr "Brošňa ochrany" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} poskytuje %{count} percent ochrany pred Armagedonom a Búrkou živlov, " "ale znižuje Silu kúzliel o 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Láskavá ZaklínaÄka si myslí, že obrana tvojej armády by potrebovala magickú " "podporu. Ponúka ti, že ti oÄarí brošňu, ktorú nosíš na plášti, a ty súhlasíš." msgid "Battle Garb of Anduran" msgstr "Anduranov bojový odev" #, fuzzy msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} kombinuje sily troch Anduranových artefaktov. Poskytuje maximálne " "šťastie a morálku pre tvoje vojsko a dáva ti kúzlo Mestský portál." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Zo súcitu s chudobným sedliakom kúpiÅ¡ truhlicu starého haraburdia, ktoré " "predáva za príliÅ¡ veľa zlata. Neskôr, keÄ ju prehľadáš, zistíš, že obsahuje " "3 kusy legendárneho Anduranovho bojového odevu!" msgid "Crystal Ball" msgstr "KriÅ¡táľová guľa" #, fuzzy msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} umožňuje získaÅ¥ konkrétnejÅ¡ie informácie o bojovníkoch, " "nepriateľských hrdinoch a hradoch v blízkosti hrdinu, ktorý ju drží." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Narazíš na karavánu Rómov, ktorí hodujú a posilňujú sa medovinou. Zavolajú " "Å¥a a hovoria: \"Ak dokážeÅ¡, že vieÅ¡ tancovaÅ¥ Rama-Butu, odmeníme Å¥a.\" " "NevieÅ¡ to, ale aj tak to skúsiÅ¡. Hystericky sa zasmejú, ale obdivujú tvoju " "odvahu a dajú ti KriÅ¡táľovú guľu." msgid "Heart of Fire" msgstr "Ohnivé srdce" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} poskytuje %{count}-percentnú ochranu pred ohňom, ale zdvojnásobuje " "poÅ¡kodenie spôsobené chladom." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "VstúpiÅ¡ na nedávno vypálenú paseku a narazíš na Ohnivého elementála, ktorý " "sedí na vrchole skaly. Pozerá sa na teba a jeho ohnivá tvár je skreslená " "výrazom silnej bolesti. Potom na teba hodí žiariaci predmet. ZdvihneÅ¡ ruky, " "aby si ho zablokoval, ale prejde cez ne a zabodne sa ti do hrude." msgid "Heart of Ice" msgstr "Ľadové srdce" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} poskytuje %{count}-percentnú ochranu pred chladom, ale zdvojnásobuje " "poÅ¡kodenie spôsobené ohňom." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Tvoje telo zrazu pohltí Å¡tipľavý chlad. Zmocní sa Å¥a strach a spadneÅ¡ z " "koňa. BolesÅ¥ ustupuje, ale stále máš pocit, akoby ti zamrzol hrudník. KeÄ sa " "zdvihneÅ¡ zo zeme, poÄujeÅ¡ silný smiech. OtoÄíš sa práve vÄas, aby si videl, " "ako mrazivý obor uteká do lesa a mizne." msgid "Helmet of Anduran" msgstr "Anduranova prilba" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Zo zeme vyÄnieva lesklý predmet. PoÅ¡leÅ¡ jedného Älena svojej skupiny, aby to " "preskúmal. Vráti sa so zlatou prilbou v rukách. UvedomujeÅ¡ si, že to musí " "byÅ¥ prilba legendárneho Andurana, jediného Äloveka, o ktorom sa vedelo, že " "nosí zbroj z Äistého zlata." msgid "Holy Hammer" msgstr "Sväté kladivo" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Natrafíš na bitku, v ktorej skupina Zombíkov smrteľne zranila Paladína. " "Požiada o prevzatie jeho kladiva a dokonÄenie toho, Äo zaÄal. KeÄ ho " "zdvihneÅ¡, zaÄne huÄaÅ¥ a potom sa vÅ¡etko rozmazáva. Zombíci ležia mÅ•tvi a z " "kladiva kvapká krv. Pripevníš si ho k opasku." msgid "Legendary Scepter" msgstr "Legendárne žezlo" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} pridáva %{count} bodov ku vÅ¡etkým atribútom." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "KeÄ zdoláš menší kopec, uvidíš smieÅ¡ne vyzerajúci úkaz. Víla sa pokúša niesÅ¥ " "žezlo, ktoré je takmer také veľké ako ona sama. Snažíš sa nesmiaÅ¥ a pýtaÅ¡ " "sa: \"PotrebujeÅ¡ pomoc?\" Víla sa na teba pozrie a odpovie: \"Myslíš si, že " "je to smieÅ¡ne? Dobre. MôžeÅ¡ to niesÅ¥ ty. Aj tak mám radÅ¡ej lietanie.\"" msgid "Masthead" msgstr "Hrot sÅ¥ažňa" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "%{name} zvyÅ¡uje tvoje šťastie a morálku v námornom boji o %{count}." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Starý námorník ti rozpovie príbeh o zaÄarovanom sÅ¥ažni, ktorý v mladosti " "používal na zhromaždenie posádky v Å¥ažkých Äasoch. Potom ti podá vyblednutú " "mapu, ktorá ukazuje, kde ho ukryl. Po dlhom skúmaní ho nájdeÅ¡ ukrytý pod " "neÄalekým prístavom." msgid "Sphere of Negation" msgstr "Guľa negácie" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} znemožňuje obom stranám v boji zosielanie vÅ¡etkých kúziel." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Zastavíš, a pomôžeÅ¡ sedliakovi chytiÅ¥ zabehnutú kobylu. Na znak vÄaky ti " "podá malú guľôÄku. Len Äo ju uchopíš, pocítiÅ¡, ako ti z konÄatín vyprcháva " "magická energia..." msgid "Staff of Wizardry" msgstr "ÄŒarodejnícka palica" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} zvýši tvoju Silu kúziel o %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "PoÄas plaÅ¡enia zveri nájdu tvoji vojaci záhadnú palicu, ktorá levituje asi " "tri stopy nad zemou. Podajú ti ju a ty si vÅ¡imneÅ¡ nápis. Stojí na ňom: " "\"Mozog prekonáva silu a mágia poráža moc. PoÄúvaj moje slová a vyhráš každý " "boj.\"" msgid "Sword Breaker" msgstr "LámaÄ meÄov" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} zvyÅ¡uje tvoju obranu o %{count} a útok o 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Bývalý kapitán stráže obdivuje tvoju misiu a daruje ti zakliaty LamaÄ meÄov, " "na ktorý sa spoliehal poÄas svojej služby." msgid "Sword of Anduran" msgstr "Anduranov meÄ" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Zastaví Å¥a Trol a povie: \"ZaplaÅ¥ mi 5000 zlatých, inak Å¥a Anduranov meÄ " "zabije na mieste.\" OdmietneÅ¡. Trol chytí meÄ zavesený na opasku, skríkne od " "bolesti a uteÄie. ZdvihneÅ¡ bájny meÄ a poÄakujeÅ¡ sa, že polointeligentní " "trollovia majú tendenciu uchopiÅ¥ ostré predmety za nesprávny koniec." msgid "Spade of Necromancy" msgstr "Rýľ nekromancie" #, fuzzy msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} ti dáva zvýšenú schopnosÅ¥ nekromancie." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Do neÄalekej kopy hliny bola zapichnutá Å¡pinavá lopata. Po preskúmaní " "zistíš, že je to zakliata lopata Hrobárov, ktorú smrteľníci dlho považovali " "za stratenú." msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "Drevo" msgid "Mercury" msgstr "OrtuÅ¥" msgid "Ore" msgstr "Ruda" msgid "Sulfur" msgstr "Síra" msgid "Crystal" msgstr "KryÅ¡tál" msgid "Gems" msgstr "Drahokamy" msgid "Gold" msgstr "Zlato" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "V Heroes 2 je sedem zdrojov, ktoré sa používajú na stavbu a vylepÅ¡ovanie " "hradov, nákup jednotiek a nábor hrdinov. Zlato je najbežnejÅ¡ie, vyžaduje sa " "prakticky na vÅ¡etko. Na väÄÅ¡inu budov sa používa Drevo a Ruda. Drahokamy, " "OrtuÅ¥, Síra a KryÅ¡tál sú vzácne magické zdroje používané pre najmocnejÅ¡ie " "bytosti a budovy." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Spôsobí, že vybranú oblasÅ¥ zasiahne obrovská ohnivá guľa, ktorá poÅ¡kodí " "vÅ¡etky okolité tvory." msgid "Fireball" msgstr "Ohnivá guľa" msgid "Fireblast" msgstr "Výbuch ohňa" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "VylepÅ¡ená verzia ohnivej gule, ohnivý výbuch pôsobí na dva hexy okolo " "stredového bodu kúzla namiesto jedného." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Spôsobí, že vybraného tvora zasiahne výboj elektrickej energie." msgid "Lightning Bolt" msgstr "Blesk" msgid "Chain Lightning" msgstr "ReÅ¥azový blesk" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Spôsobí, že výboj elektrickej energie zasiahne vybraného tvora, potom " "zasiahne najbližšieho tvora s poloviÄným poÅ¡kodením, potom zasiahne ÄŽALÅ IEHO " "najbližšieho tvora opäť s poloviÄným poÅ¡kodením a tak Äalej, až kým nie je " "príliÅ¡ slabý na to, aby bol Å¡kodlivý. Varovanie: Toto kúzlo môže zasiahnuÅ¥ " "aj tvoje tvory!" msgid "Teleport" msgstr "Teleport" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Teleportuje vybranú bytosÅ¥ na ľubovoľné voľné miesto na bojisku." msgid "Cure" msgstr "LieÄenie" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Odstráni vÅ¡etky negatívne kúzla zoslané na jednu z vaÅ¡ich jednotiek a obnoví " "až %{count} zdravia za úroveň Sily kúziel." msgid "Mass Cure" msgstr "Hromadné lieÄenie" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Odstráni vÅ¡etky negatívne kúzla zoslané na tvoje vojsko a obnoví až %{count} " "zdravia na úroveň sily kúziel, na každého tvora." msgid "Resurrect" msgstr "Vzkriesenie" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "Oživuje bytosti z poÅ¡kodenej alebo mÅ•tvej jednotky až do konca boja." msgid "Resurrect True" msgstr "Vzkriesenie pravé" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Trvalo oživuje bytosti z poÅ¡kodenej alebo mÅ•tvej jednotky." msgid "Haste" msgstr "Zhon" msgid "Increases the speed of any creature by %{count}." msgstr "Zvýši rýchlosÅ¥ ľubovoľného tvora o %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "ZvyÅ¡uje rýchlosÅ¥ vÅ¡etkých tvojich bytostí o %{count}." msgid "Mass Haste" msgstr "Hromadný zhon" msgid "Slows target to half movement rate." msgstr "Spomalí cieľ na polovicu rýchlosti pohybu." msgid "spell|Slow" msgstr "Spomalenie" msgid "Mass Slow" msgstr "Hromadné spomalenie" msgid "Slows all enemies to half movement rate." msgstr "Spomaľuje vÅ¡etkých nepriateľov na polovicu rýchlosti pohybu." msgid "spell|Blind" msgstr "Slepota" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Zakryje oÄi postihnutých tvorov a zabráni im v pohybe." msgid "Bless" msgstr "Požehnanie" msgid "Causes the selected creatures to inflict maximum damage." msgstr "ZapríÄiní, že vybrané bytosti spôsobia maximálne poÅ¡kodenie." msgid "Causes all of your units to inflict maximum damage." msgstr "ZapríÄiní, že vÅ¡etky tvoje jednotky spôsobia maximálne poÅ¡kodenie." msgid "Mass Bless" msgstr "Hromadné požehnanie" msgid "Magically increases the defense skill of the selected creatures." msgstr "Magicky zvýši obrannú schopnosÅ¥ vybraných tvorov." msgid "Stoneskin" msgstr "Kamenná koža" msgid "Steelskin" msgstr "Oceľová koža" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "ZvyÅ¡uje obrannú schopnosÅ¥ cielených tvorov. Ide o vylepÅ¡enú verziu Kamennej " "kože." msgid "Causes the selected creatures to inflict minimum damage." msgstr "ZapríÄiní, že vybrané bytosti spôsobia minimálne poÅ¡kodenie." msgid "Curse" msgstr "Kliatba" msgid "Causes all enemy troops to inflict minimum damage." msgstr "ZapríÄiní, že vÅ¡etci nepriatelia spôsobia minimálne poÅ¡kodenie." msgid "Mass Curse" msgstr "Hromadná kliatba" msgid "Damages all undead in the battle." msgstr "PoÅ¡kodí vÅ¡etkých nemÅ•tvych v boji." msgid "Holy Word" msgstr "Sväté slovo" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "PoÅ¡kodí vÅ¡etkých nemÅ•tvych v boji. Toto je vylepÅ¡ená verzia Svätého slova." msgid "Holy Shout" msgstr "Svätý výkrik" msgid "Anti-Magic" msgstr "Protimágia" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Bráni Å¡kodlivým kúzlam proti vybraným tvorom." msgid "Dispel Magic" msgstr "RozptýliÅ¥ mágiu" msgid "Removes all magic spells from a single target." msgstr "Odstráni z jedného cieľa vÅ¡etky kúzla." msgid "Mass Dispel" msgstr "Hromadné rozptýlenie" msgid "Removes all magic spells from all creatures." msgstr "Odstráni vÅ¡etky kúzla zo vÅ¡etkých tvorov." msgid "Causes a magic arrow to strike the selected target." msgstr "Spôsobí, že magická strela zasiahne vybraný cieľ." msgid "Magic Arrow" msgstr "ÄŒarovný šíp" msgid "Berserker" msgstr "Amok" msgid "Causes a creature to attack its nearest neighbor." msgstr "Spôsobí, že tvor zaútoÄí na svojho najbližšieho suseda." msgid "Armageddon" msgstr "Armagedon" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Svätý teror zasiahne bojisko a spôsobí vážne poÅ¡kodenie vÅ¡etkým stvoreniam." msgid "Elemental Storm" msgstr "Búrka živlov" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Magické živly sa valia na bojisko a poÅ¡kodzujú vÅ¡etky bytosti." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Na oblasÅ¥ bojiska dopadne dÃ¡Å¾Ä kameňov, ktorý poÅ¡kodí vÅ¡etky okolité tvory." msgid "Meteor Shower" msgstr "Pád kameňov" msgid "Paralyze" msgstr "Paralýza" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "Cieľové bytosti sú paralyzované, neschopné pohybu alebo odvety." msgid "Hypnotize" msgstr "Hypnóza" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Privedie jednu nepriateľskú jednotku pod tvoju kontrolu, ak je jej HP menej " "ako %{count} násobok Sily kúziel zosielateľa." msgid "Cold Ray" msgstr "LÃºÄ chladu" msgid "Drains body heat from a single enemy unit." msgstr "OdÄerpá telesné teplo z jednej nepriateľskej jednotky." msgid "Cold Ring" msgstr "Prstenec chladu" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "OdÄerpá telesné teplo zo vÅ¡etkých jednotiek v okolí stredového bodu, ale nie " "z tohto bodu." msgid "Disrupting Ray" msgstr "NaruÅ¡ujúci lúÄ" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Zníži obranyschopnosÅ¥ nepriateľskej jednotky o tri." msgid "Damages all living (non-undead) units in the battle." msgstr "PoÅ¡kodí vÅ¡etky živé (nie nemÅ•tve) jednotky v bitke." msgid "Death Ripple" msgstr "Poryv smrti" msgid "Death Wave" msgstr "Vlna smrti" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "PoÅ¡kodí vÅ¡etky živé (nie nemÅ•tve) jednotky v bitke. Toto kúzlo je vylepÅ¡enou " "verziou Poryvu smrti." msgid "Dragon Slayer" msgstr "Drakobijec" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Výrazne zvyÅ¡uje útoÄné schopnosti jednotky proti drakom." msgid "Blood Lust" msgstr "KrvilaÄnosÅ¥" msgid "Increases a unit's attack skill." msgstr "ZvyÅ¡uje útoÄné schopnosti jednotky." msgid "Animate Dead" msgstr "Animácia mÅ•tvych" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "Trvalo oživí bytosti z poÅ¡kodenej alebo zabitej nemÅ•tvej jednotky." msgid "Mirror Image" msgstr "Zrkadlový obraz" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Vytvorí iluzórnu jednotku, ktorá duplikuje jednu z tvojich existujúcich " "jednotiek. Táto iluzórna jednotka spôsobuje rovnaké poÅ¡kodenie ako pôvodná " "jednotka, ale ak dostane akékoľvek poÅ¡kodenie, zmizne." msgid "Shield" msgstr "Å tít" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Znižuje poÅ¡kodenie z útokov na diaľku o polovicu pre jednu jednotku. " "Nechráni pred vežami a balistami." msgid "Mass Shield" msgstr "Hromadný Å¡tít" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "O polovicu znižuje poÅ¡kodenie spôsobené útokom na diaľku pre vÅ¡etky tvoje " "jednotky. Nechráni pred vežami a balistami." msgid "Summon Earth Elemental" msgstr "Vyvolaj Zemského elementála" msgid "Summons Earth Elementals to fight for your army." msgstr "Vyvolá Zemských elementálov, aby bojovali za tvoju armádu." msgid "Summon Air Elemental" msgstr "Vyvolaj VzduÅ¡ného elementála" msgid "Summons Air Elementals to fight for your army." msgstr "Vyvolá VzduÅ¡ných elementálov, aby bojovali za tvoju armádu." msgid "Summon Fire Elemental" msgstr "Vyvolaj Ohnivého elementála" msgid "Summons Fire Elementals to fight for your army." msgstr "Vyvolá Ohnivých elementálov, aby bojovali za tvoju armádu." msgid "Summon Water Elemental" msgstr "Vyvolaj Vodného elementála" msgid "Summons Water Elementals to fight for your army." msgstr "Vyvolá Vodných elementálov, aby bojovali za tvoju armádu." msgid "Damages castle walls." msgstr "PoÅ¡kodí hradné múry." msgid "Earthquake" msgstr "Zemetrasenie" msgid "Causes all mines across the land to become visible." msgstr "Spôsobí, že sa vÅ¡etky bane v krajine zviditeľnia." msgid "View Mines" msgstr "Ukáž bane" msgid "Causes all resources across the land to become visible." msgstr "Spôsobí, že sa vÅ¡etky suroviny v celej krajine zviditeľnia." msgid "View Resources" msgstr "Ukáž suroviny" msgid "Causes all artifacts across the land to become visible." msgstr "Spôsobí, že vÅ¡etky artefakty v krajine budú viditeľné." msgid "View Artifacts" msgstr "Ukáž artefakty" msgid "Causes all towns and castles across the land to become visible." msgstr "Spôsobí, že sa zviditeľnia vÅ¡etky mestá a hrady v celej krajine." msgid "View Towns" msgstr "Ukáž mestá" msgid "Causes all Heroes across the land to become visible." msgstr "Spôsobí, že sa vÅ¡etci hrdinovia v celej krajine zviditeľnia." msgid "View Heroes" msgstr "Ukáž hrdinov" msgid "Causes the entire land to become visible." msgstr "Spôsobí zviditeľnenie celej krajiny." msgid "View All" msgstr "Ukáž vÅ¡etko" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" "Umožňuje zosielateľovi zobraziÅ¥ podrobné informácie o nepriateľských " "hrdinoch." msgid "Summon Boat" msgstr "Vyvolaj loÄ" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Privolá najbližšiu neobsadenú priateľskú loÄ na priľahlé miesto na pobreží. " "Priateľská loÄ je loÄ, ktorú si práve postavil alebo si ju obsadil ako " "posledný hráÄ." msgid "Allows the caster to magically transport to a nearby location." msgstr "Umožňuje zaklínaÄovi magicky sa preniesÅ¥ na blízke miesto." msgid "Dimension Door" msgstr "Dimenzionálne dvere" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Vráti zosielateľa do ktoréhokoľvek mesta alebo hradu, ktorý práve vlastníš." msgid "Town Gate" msgstr "Mestská brána" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "Vráti hrdinu do vybraného mesta alebo hradu, ak ho ovládaÅ¡." msgid "Visions" msgstr "Vízie" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Vízie predpovedajú pravdepodobný výsledok stretnutia s táborom neutrálnej " "armády." msgid "Haunt" msgstr "ZakliaÅ¥ baňu" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Zakľaje baňu, ktorú ovládaÅ¡ pomocou Duchov. Táto baňa prestane produkovaÅ¥ " "suroviny. (Ak ju nebudem môcÅ¥ maÅ¥ ja, nebude ju maÅ¥ nikto!)" msgid "Set Earth Guardian" msgstr "NasadiÅ¥ zemskú stráž" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" "Nasadí Zemských elementálov, aby strážili baňu pred nepriateľskými armádami." msgid "Set Air Guardian" msgstr "NasadiÅ¥ vzduÅ¡nú stráž" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" "Nasadí VzduÅ¡ných elementálov, aby strážili baňu pred nepriateľskými armádami." msgid "Set Fire Guardian" msgstr "NasadiÅ¥ ohnivú stráž" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" "Nasadí Ohnivých elementálov, aby strážili baňu pred nepriateľskými armádami." msgid "Set Water Guardian" msgstr "NasadiÅ¥ vodnú stráž" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" "Nasadí Vodných elementálov, aby strážili baňu pred nepriateľskými armádami." #, fuzzy msgid "Random Spell" msgstr "Náhodná" msgid "Randomly selected spell of any level." msgstr "" #, fuzzy msgid "Random 1st Level Spell" msgstr "Náhodný hrad" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "Skamenenie" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Zmení zasiahnutého tvora na kameň. Skamenený tvor dostane poloviÄné " "poÅ¡kodenie od priameho útoku." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Nemáš knihu kúziel, takže nemôžeÅ¡ zosielaÅ¥ kúzla." msgid "No spell to cast." msgstr "Žiadne kúzla na zoslanie." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Tvojmu hrdinovi zostáva %{point} bodov kúziel." msgid "View Adventure Spells" msgstr "ZobraziÅ¥ dobrodružné kúzla" msgid "View Combat Spells" msgstr "ZobraziÅ¥ bojové kúzla" msgid "View previous page" msgstr "ZobraziÅ¥ predchádzajúcu stranu" msgid "View next page" msgstr "ZobraziÅ¥ ÄalÅ¡iu stranu" msgid "Close Spellbook" msgstr "ZavrieÅ¥ knihu kúziel" msgid "View %{spell}" msgstr "ZobraziÅ¥ %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Toto kúzlo spôsobí %{damage} bodov poÅ¡kodenia." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "Pomocou tohto kúzla povoláš %{count} bojovníkov (%{monster})." msgid "This spell restores %{hp} HP." msgstr "Toto kúzlo obnoví %{hp} zdravia." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" "Pomocou tohto kúzla povoláš %{count} bojovníkov (%{monster}), aby strážili " "baňu." msgid "The nearest town is %{town}." msgstr "Najbližšie mesto je %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Tvoj hrdina %{hero} obsadil toto mesto." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Toto kúzlo ovláda do\n" "%{hp} zdravia." msgid "The ultimate artifact is really the %{name}." msgstr "Ultimátny artefakt je v skutoÄnosti %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Ultimátny artefakt sa nachádza v regióne %{name}." msgid "north-west" msgstr "severozápad" msgid "north" msgstr "sever" msgid "north-east" msgstr "severovýchod" msgid "west" msgstr "západ" msgid "center" msgstr "stred" msgid "east" msgstr "východ" msgid "south-west" msgstr "juhozápad" msgid "south" msgstr "juh" msgid "south-east" msgstr "juhovýchod" msgid "The truth is out there." msgstr "Pravda je tam vonku." msgid "The dark side is stronger." msgstr "Temná sila je silnejÅ¡ia." msgid "The end of the world is near." msgstr "Koniec sveta sa blíži." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Kosti Lorda Slayera sú zahrabané v základoch arény." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "ÄŒierny drak zloží Titána aj o polnoci." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "Povedal jej: Jada jada jada... a ona na to že: Blá, blá, blá..." msgid "An unknown force is being resurrected..." msgstr "Neznáma sila je vzkriesená..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Pozri si najnovÅ¡iu verziu hry na\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Zvoľ poÄet - %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Povoľ automatizovaný boj" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "ukonÄi boj v automatickom móde" #~ msgid "Please Remember" #~ msgstr "Nezabudni, prosím" #, fuzzy #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "Rozlíšenie hry si vždy môžeÅ¡ zmeniÅ¥ kliknutím na " #~ msgid "door" #~ msgstr "dvere" #, fuzzy #~ msgid "NEW GAME" #~ msgstr "" #~ "NOVÃ\n" #~ "HRA" #~ msgid "Warning!" #~ msgstr "Pozor!" #~ msgid "Dummy 1" #~ msgstr "Atrapa 1" fheroes2-1.1.6+dfsg/files/lang/sv.po000066400000000000000000011756721476115357100172230ustar00rootroot00000000000000# Swedish translation for fheroes2 # Copyright (C) 2020 - 2025 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2025-02-07 18:12+0100\n" "Last-Translator: fheroes2 team \n" "Language-Team: Swedish \n" "Language: sv\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-Launchpad-Export-Date: 2013-10-09 02:01+0000\n" "X-Generator: Poedit 3.4.4\n" msgid "" "NEW\n" "GAME" msgstr "" "NYTT\n" "SPEL" msgid "" "SAVE\n" "GAME" msgstr "" "SPARA\n" "SPEL" msgid "" "LOAD\n" "GAME" msgstr "" "LADDA\n" "SPEL" msgid "INFO" msgstr "INFO" msgid "QUIT" msgstr "AVSLUT." msgid "" "NEW\n" "MAP" msgstr "" "NY\n" "KARTA" msgid "" "SAVE\n" "MAP" msgstr "" "SPARA\n" "KARTA" msgid "" "LOAD\n" "MAP" msgstr "" "LADDA\n" "KARTA" msgid "CANCEL" msgstr "AVBRYT" msgid "OKAY" msgstr "OKEJ" msgid "ACCEPT" msgstr "ACCEPTERA" msgid "DECLINE" msgstr "AVBÖJ" msgid "LEARN" msgstr "VÄLJ" msgid "TRADE" msgstr "HANDLA" msgid "YES" msgstr "JA" msgid "NO" msgstr "NEJ" msgid "EXIT" msgstr "LÄMNA" msgid "smallerButton|EXIT" msgstr "LÄMN." msgid "DISMISS" msgstr "AVSKEDA" msgid "UPGRADE" msgstr "UPPG." msgid "RESTART" msgstr "OMSTART" msgid "HEROES" msgstr "" "HJÄLT-\n" "AR" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "STÄDER/\n" "SLOTT" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "XL" msgid "ALL" msgstr "ALLA" msgid "SELECT" msgstr "VÄLJ" msgid "" "STANDARD\n" "GAME" msgstr "SOLOSPEL" msgid "" "BATTLE\n" "ONLY" msgstr "" "ENDAST\n" "STRID" msgid "" "CAMPAIGN\n" "GAME" msgstr "KAMPANJ" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "MULTI-\n" "SPEL" msgid "CONFIG" msgstr "" "INSTÄLL-\n" "NINGAR" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ORGINAL-\n" "KAMPANJ" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "EXPANSIONS-\n" "KAMPANJ" msgid "HOT SEAT" msgstr "HETA STOLEN" msgid "2 PLAYERS" msgstr "2 SPELARE" msgid "3 PLAYERS" msgstr "3 SPELARE" msgid "4 PLAYERS" msgstr "4 SPELARE" msgid "5 PLAYERS" msgstr "5 SPELARE" msgid "6 PLAYERS" msgstr "6 SPELARE" msgid "GIFT" msgstr "GÃ…VA" msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "SVÃ…RIGHETSGRAD" msgid "VIEW INTRO" msgstr "VISA INTRO" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "Ã…TERS." msgid "START" msgstr "STARTA" msgid "TOWN" msgstr "STAD" msgid "CASTLE" msgstr "SLOTT" msgid "RESTRICT" msgstr "BEGRÄNSA" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "A\n" "V\n" "S\n" "K\n" "E\n" "D\n" "A" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "L\n" "Ä\n" "M\n" "N\n" "A" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "P\n" "A\n" "T\n" "R\n" "U\n" "L\n" "L" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "K\n" "A\n" "M\n" "P\n" "A\n" "N\n" "J" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "S\n" "O\n" "L\n" "O\n" "S\n" "P\n" "E\n" "L" msgid "RUMORS" msgstr "RYKTEN" msgid "EVENTS" msgstr "HÄNDELSER" msgid "LANGUAGE" msgstr "SPRÃ…K" msgid "" "AUTO\n" "COMBAT" msgstr "" "AUTO.-\n" "STRID" msgid "" "QUICK\n" "COMBAT" msgstr "" "SNABB-\n" "STRID" msgid "Warrior" msgstr "Krigare" msgid "Builder" msgstr "Byggare" msgid "Explorer" msgstr "Utforskare" msgid "None" msgstr "Inga" msgid "" "A few\n" "%{monster}" msgstr "" "Ett par\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "NÃ¥gra\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "En flock\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Mängder av\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "En hord av\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Ett myller av\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "En svärm av\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "En skock\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "En legion av\n" "%{monster}" msgid "army|Few" msgstr "NÃ¥gra" msgid "army|Several" msgstr "Flera" msgid "army|Pack" msgstr "Flock" msgid "army|Lots" msgstr "Mängder" msgid "army|Horde" msgstr "Hord" msgid "army|Throng" msgstr "Myller" msgid "army|Swarm" msgstr "Svärm" msgid "army|Zounds" msgstr "Skock" msgid "army|Legion" msgstr "Legion" msgid "All %{race} troops +1" msgstr "Endast %{race}trupper +1" msgid "NeutralRaceTroops|Neutral" msgstr "Neutrala" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Armén bestÃ¥r av trupper frÃ¥n %{count} olika klasser, ger -%{penalty}" msgid "Some undead in army -1" msgstr "NÃ¥gra odöda i armén -1" msgid "" "Default\n" "troop" msgstr "" "Standard-\n" "trupper" msgid "View %{name}" msgstr "Visa %{name}" msgid "Move the %{name} " msgstr "Flytta %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Flytta eller högerklicka för att fördela %{name}" msgid "Combine %{name} armies" msgstr "Kombinera %{name} arméer" msgid "Exchange %{name2} with %{name}" msgstr "Byt ut %{name2} mot %{name}" msgid "Select %{name}" msgstr "Välj %{name}" msgid "Cannot move last troop" msgstr "Kan ej flytta sista truppen" msgid "Move the %{name}" msgstr "Flytta %{name}" msgid "Set %{monster} Count" msgstr "Ange antal %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} förgör hälften av fiendetrupperna!" msgstr[1] "%{name} förgör hälften av fiendetrupperna!" msgid "%{name} has turned off the auto combat" msgstr "%{name} har stängt av automatisk strid" msgid "%{name} has turned on the auto combat" msgstr "%{name} har aktiverat automatisk strid" msgid "Spell failed!" msgstr "Besvärjelse misslyckades!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Negationsklotsartefakten är i effekt för denna striden och inaktiverar alla " "stridsbesvärjelser." msgid "You cannot cast spells without a commanding hero." msgstr "Du kan inte kasta besvärjelser utan en hjälte." msgid "You have already cast a spell this round." msgstr "Du har redan kastat en besvärjelse denna runda." msgid "That spell will have no effect!" msgstr "Besvärjelsen har ingen effekt!" msgid "You may only summon one type of elemental per combat." msgstr "Du kan endast inkalla en elementtyp per strid." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Det finns ingen fri plats intill din hjälte för att inkalla ett elementväsen." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Vallgraven sänker en varelses Försvar med %{count} och halverar dennes " "hastighet." msgid "Speed: %{speed}" msgstr "Hastighet: %{speed}" msgid "Speed" msgstr "Hastighet" msgid "Off" msgstr "Av" msgid "On" msgstr "PÃ¥" msgid "Turn Order" msgstr "Turordning" msgid "Auto Spell Casting" msgstr "" "Autom.\n" "besvärj.kast." msgid "Grid" msgstr "Rutnät" msgid "Shadow Movement" msgstr "Skuggförflyttning" msgid "Shadow Cursor" msgstr "Skuggmarkör" msgid "Audio" msgstr "Ljud" msgid "Settings" msgstr "Inställningar" msgid "Configure" msgstr "Anpassa" msgid "Hot Keys" msgstr "" "Snabb-\n" "tangenter" msgid "Damage Info" msgstr "" "Skade-\n" "information" msgid "Set the speed of combat actions and animations." msgstr "Ange hastigheten för animationer pÃ¥ slagfältet." msgid "Toggle to display the turn order during the battle." msgstr "Visa varelsernas turordning pÃ¥ slagfältet." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "LÃ¥t datorn kasta besvärjelser för dig när automatisk strid är aktiverat. " "(Detta pÃ¥verkar inte fiendedatorns besvärjelsekastning, inte heller pÃ¥verkar " "det snabbstrid.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Visa rutnät. Rutnätet används alltid, denna inställning bestämmer bara om " "nätet ska vara synligt eller ej." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Välj om skuggförflyttning ska vara aktiverat. Skuggförflyttning visar var " "dina varelser kan flytta till och var de kan anfalla." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Välj om skuggmarkör skall vara aktiverat. Muspekaren visar en skugga pÃ¥ " "stridsfältets rutnät." msgid "Change the audio settings of the game." msgstr "Ändra spelets ljudinställningar." msgid "Check and configure all the hot keys present in the game." msgstr "Anpassa spelets snabbtangenter." msgid "Toggle to display damage information during the battle." msgstr "Visa skadeinformation under strid." msgid "Exit this menu." msgstr "Stäng menyn." msgid "Okay" msgstr "OK" msgid "The enemy has surrendered!" msgstr "Fienden har kapitulerat!" msgid "Their cowardice costs them %{gold} gold." msgstr "Deras feghet kostar dem %{gold} guld." msgid "The enemy has fled!" msgstr "Fienden har flytt!" msgid "A glorious victory!" msgstr "En ärorik seger!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "För sin tapperhet i strid erhÃ¥ller %{name} %{exp} erfarenhetspoäng." msgid "The cowardly %{name} flees from battle." msgstr "Fegisen %{name} flyr frÃ¥n striden." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} ger sig till fienden och ger sig av i skam." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "Dina trupper lider en bitter förlust och %{name} lämnar dig och dina trupper." msgid "Your forces suffer a bitter defeat." msgstr "Dina trupper lider en bitter förlust." msgid "Battlefield Casualties" msgstr "Slagfältsoffer" msgid "Attacker" msgstr "Angripare" msgid "Defender" msgstr "Försvarare" msgid "Click to leave the battle results." msgstr "Klicka här för att lämna stridsresultaten." msgid "Click to restart the battle in manual mode." msgstr "Klicka här för att omstarta striden manuellt." msgid "Restart" msgstr "Omstart" msgid "You have captured an enemy artifact!" msgstr "Du har tillfÃ¥ngatagit fiendens artefakt!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "När du försöker ta %{name}, sÃ¥ försvinner den plötsligt." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "När fienden försöker ta %{name}, sÃ¥ försvinner den plöstligt." msgid "Necromancy!" msgstr "Svartkonst!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Genom att utöva svartkonst, sÃ¥ Ã¥teruppväcker du %{count} av fiendens stupade " "som %{monster} för att tjäna dig." msgid "%{name} the %{race}" msgstr "%{race}n %{name}" msgid "Captain of %{name}" msgstr "Kapten över %{name}" msgid "Attack" msgstr "Anfall" msgid "Defense" msgstr "Försvar" msgid "Spell Power" msgstr "Trollkonst" msgid "Knowledge" msgstr "Kunskap" msgid "Morale" msgstr "Stridsmoral" msgid "Luck" msgstr "Tur" msgid "Spell Points" msgstr "Besvärjelsepoäng" msgid "Hero's Options" msgstr "Hjältealternativ" msgid "Cast Spell" msgstr "Kasta besvärjelse" msgid "Retreat" msgstr "Retirera" msgid "Surrender" msgstr "Kapitulera" msgid "Cancel" msgstr "Avbryt" msgid "Hero Screen" msgstr "Hjältevy" msgid "Captain's Options" msgstr "Kaptensalternativ" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Kasta en besvärjelse. Du kan endast kasta en besvärjelse per runda. Rundan " "nollställs när varje varelse har haft sin runda." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Retirera din hjälte, överge dina kreatur. Din hjälte kommer att vara " "tillgänglig för dig att rekrytera igen, men hjälten kommer endast att ha en " "novishjältes styrkor." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Att kapitulera kostar guld. Men om du betalar lösensumman kommer hjälten och " "alla dennes överlevande varelser kunna rekryteras igen. " "Kapitulationskostnaden är halva totalkostnaden av alla icke tillfälliga " "trupper i armén." msgid "Open Hero Screen to view full information about the hero." msgstr "Öppna Hjältevyn för att fÃ¥ full information om hjälten." msgid "Return to the battle." msgstr "Ã…tergÃ¥ till striden." msgid "Not enough gold (%{gold})" msgstr "För lite guld (%{gold})" msgid "%{name} states:" msgstr "%{name}s förklarar:" msgid "Captain of %{name} states:" msgstr "Kaptenen över %{name} förklarar:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Jag kommer att acceptera din kapitulation och bevilja dig och dina trupper " "en fri lejd för ett pris pÃ¥ %{price} guld.\"" msgid "View %{monster} info" msgstr "Visa information om %{monster}" msgid "Fly %{monster} here" msgstr "Flyg %{monster} hit" msgid "Move %{monster} here" msgstr "Flytta %{monster} hit" msgid "Shoot %{monster}" msgstr "Skjut %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 projektil kvar)" msgstr[1] "(%{count} projektiler kvar)" msgid "Attack %{monster}" msgstr "Anfall %{monster}" msgid "Turn %{turn}" msgstr "Runda %{turn}" msgid "Teleport here" msgstr "Teleportera hit" msgid "Invalid teleport destination" msgstr "Ogiltig teleporteringsdestination" msgid "Cast %{spell} on %{monster}" msgstr "Kasta %{spell} pÃ¥ %{monster}" msgid "Cast %{spell}" msgstr "Kasta %{spell}" msgid "Select spell target" msgstr "Välj besvärjelsemÃ¥l" msgid "View Ballista info" msgstr "Visa Ballistinformation" msgid "Ballista" msgstr "Ballist" msgid "Automatic combat modes" msgstr "Autom. Stridslägen" msgid "Automatic Combat Modes" msgstr "Autom. Stridslägen" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" "Välj mellan att fortsätta striden i automatiskt stridsläge eller i " "snabbstridsläge." msgid "Customize system options" msgstr "Skräddarsy systeminställningarna" msgid "Allows you to customize the combat screen." msgstr "TillÃ¥ter dig att skräddarsy stridsvyn." msgid "System Options" msgstr "Systemalternativ" msgid "Skip this unit" msgstr "Hoppa över denna enhet" msgid "Skip" msgstr "Hoppa över" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Hoppar över nuvarande varelse. Nuvarande varelse avslutar sin runda och " "fortsätter först vid sin nästa runda." msgid "View Captain's options" msgstr "Visa Kaptensalternativ" msgid "View Hero's options" msgstr "Visa Hjältealternativ" msgid "View opposing Captain" msgstr "Visa motstÃ¥ndarkapten" msgid "View opposing Hero" msgstr "Visa motstÃ¥ndarhjälte" msgid "Hide logs" msgstr "Dölj logg" msgid "Show logs" msgstr "Visa logg" msgid "Message Bar" msgstr "Textfält" msgid "Shows the results of individual monster's actions." msgstr "Visa resultaten av en varelses handlingar." msgid "Are you sure you want to enable the auto combat mode?" msgstr "Är du säker pÃ¥ att du vill aktivera automatisk strid?" msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Är du säker pÃ¥ att du vill avgöra striden med snabbstrid?" msgid "The computer continues the combat for you." msgstr "Datorn fortsätter striden Ã¥t dig." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" "Detta kan avbryta när som helst genom att klicka pÃ¥ snabbtangenten för " "automatisk strid, standardtangenten för Avbryt eller genom att vänster eller " "högerklicka varsomhelst pÃ¥ slagfältet." msgid "Auto Combat" msgstr "Autom. Strid" msgid "The combat is resolved from the current state." msgstr "Striden avgörs frÃ¥n nuvarande läge." msgid "quickCombat|This cannot be undone." msgstr "Detta kan inte göras ogjort." msgid "Quick Combat" msgstr "Snabbstrid" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} hoppar över rundan." msgstr[1] "%{name} hoppar över rundan." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} ger %{damage} skada." msgstr[1] "%{attacker} ger %{damage} skada." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "en varelse stupar." msgstr[1] "%{count} varelser stupar." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "en %{defender} stupar." msgstr[1] "%{count} %{defender} stupar." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 själ absorberas." msgstr[1] "%{count} själar absorberas." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} Ã¥teruppväcks." msgstr[1] "%{count} %{unit} Ã¥teruppväcks." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Flyttade %{monster}: frÃ¥n [%{src}] till [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} motstÃ¥r besvärjelsen!" msgstr[1] "%{name} motstÃ¥r besvärjelsen!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} kastar %{spell} pÃ¥ %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} kastar %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "Besvärjelsen %{spell} ger %{damage} skada till en odöd varelse." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "Besvärjelsen %{spell} ger %{damage} skada till alla odöda varelser." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "Besvärjelsen %{spell} ger %{damage} skada, %{count} varelser stupar." msgid "The %{spell} does %{damage} damage." msgstr "Besvärjelsen %{spell} ger %{damage} skada." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "Besvärjelsen %{spell} ger %{damage} skada till en levande varelse." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "Besvärjelsen %{spell} ger %{damage} skada till alla levande varelser." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "%{attacker}ens anfall förblindar %{target}na!" msgstr[1] "%{attacker}nas anfall förblindar %{target}na!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "%{attacker}ens blick förvandlar %{target} till sten!" msgstr[1] "%{attacker}nas blick förvandlar %{target} till sten!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "%{attacker}ens förbannelse drabbar %{target}" msgstr[1] "%{attacker}nas förbannelse drabbar %{target}" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{name} blev paralyserad av %{attacker}!" msgstr[1] "%{name} blev paralyserade av %{attacker}!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "%{attacker} skingrar alla godartade besvärjelser frÃ¥n %{target}!" msgstr[1] "%{attacker} skingrar alla godartade besvärjelser frÃ¥n %{target}!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} kastar %{spell} pÃ¥ %{target}!" msgstr[1] "%{attacker} kastar %{spell} pÃ¥ %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Otur drabbar %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "Turen skiner pÃ¥ %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Hög stridsmoral lÃ¥ter %{monster} attackera igen." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "LÃ¥g stridsmoral fÃ¥r %{monster} att stelna i panik." msgid "%{tower} does %{damage} damage." msgstr "%{tower} ger %{damage} skada." msgid "The mirror image is created." msgstr "Spegelbild skapas." msgid "The mirror image is destroyed!" msgstr "Spegelbilden förstörs!" msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Är du säker pÃ¥ att du vill avbryta den automatiska striden?" msgid "Error" msgstr "Fel" msgid "No spells to cast." msgstr "Inga besvärjelser att kasta." msgid "Are you sure you want to retreat?" msgstr "Är du säker pÃ¥ att du vill retirera?" msgid "Retreat disabled" msgstr "Retirering inaktiverat" msgid "Surrender disabled" msgstr "Kapitulation inaktiverat" msgid "Damage: %{max}" msgstr "Skada: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Skada: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Stupar: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Stupar: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "Genom sin falkblick sÃ¥ kan %{name} lära sig besvärjelsen %{spell}." msgid "Human" msgstr "Spelare" msgid "AI" msgstr "AI" msgid "Start" msgstr "Starta" msgid "Start the battle." msgstr "Starta striden." msgid "Exit" msgstr "Lämna staden" msgid "Reset" msgstr "Ã…terställ" msgid "Reset to default settings." msgstr "Ã…terställ till standardinställningar." msgid "Please select another hero." msgstr "Välj en annan hjälte." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} mot %{race2} %{name2}" msgid "Monsters" msgstr "Varelser" msgid "N/A" msgstr "Ingen" msgid "Left Turret" msgstr "Vänster Torn" msgid "Right Turret" msgstr "Höger Torn" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} avfyrar med styrkan av %{count} BÃ¥gskyttar" msgid "each with a +%{attack} bonus to their attack skill." msgstr "varje med en +%{attack} bonus till deras Anfall." msgid "The %{name} is destroyed." msgstr "%{name} förstörs." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} Ã¥teruppstÃ¥r frÃ¥n de döda!" msgstr[1] "%{count} %{name} Ã¥teruppstÃ¥r frÃ¥n de döda!" msgid "Dwarven Alliance" msgstr "Dvärgallians" msgid "Sorceress Guild" msgstr "Häxcirkel" msgid "Necromancer Guild" msgstr "" "Svartkonstnärnas\n" "kult" msgid "Ogre Alliance" msgstr "Jätteallians" msgid "Dwarfbane" msgstr "Dvärgdöd" msgid "Dragon Alliance" msgstr "Drakallians" msgid "Elven Alliance" msgstr "Alvallians" msgid "Kraeger defeated" msgstr "Kraeger besegrad" msgid "Wayward Son" msgstr "Egensinnige Sonen" msgid "Uncle Ivan" msgstr "Farbror Ivan" msgid "Annexation" msgstr "Annektering" msgid "Force of Arms" msgstr "Vapenmakt" msgid "Save the Dwarves" msgstr "Rädda dvärgarna" msgid "Carator Mines" msgstr "Caratorgruvorna" msgid "Turning Point" msgstr "Vändpunkt" msgid "scenarioName|Defender" msgstr "Försvararen" msgid "Corlagon's Defense" msgstr "Corgalons Försvar" msgid "The Crown" msgstr "Kronan" # Gauntlet as in race. msgid "The Gauntlet" msgstr "Gatloppet" msgid "Betrayal" msgstr "Förräderiet" msgid "Final Justice" msgstr "Slutlig Rättvisa" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland behöver dig för att besegra herrarna nära hans borg för att kunna " "pÃ¥börja upproret mot sin broder. De är inte allierade med varandra, sÃ¥ de " "kommer mest strida inbördes. Segern är din när du har besegrat alla deras " "hjältar och intagit deras borg." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "De lokala herrarna vägrar att alliera sig med Roland och mÃ¥ste kuvas. De är " "rika och mäktiga sÃ¥ var förberedd pÃ¥ hÃ¥rt motstÃ¥nd. \n" "Inta alla fiendeborgar för att vinna." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Din uppgift är att försvara Dvärgarna mot Archibalds styrkor. Inta alla " "fiendestäder och borgar för att vinna, och försäkra dig om att inte förlora " "kontrollen över samtliga dvärgstäder för i sÃ¥ fall har fienden vunnit." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Du kommer att möta fyra allierade fiender i en kamp om resurser och skatter. " "Inta alla fiendeborgar för seger." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Dina fiender har allierat sig emot dig och de börjar nära sÃ¥ var redo pÃ¥ " "strid. Du behöver kontrollera alla fyra borgar i den lilla dalen för att " "vinna." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Norastons Häxcirkel har begärt Rolands hjälp mot ett anfall frÃ¥n Arcibalds " "allierade. Inta alla fiendesborgar för att vinna. Förlora inte kontrollen " "över Noraston, för dÃ¥ förlorar du. (Tips: Det finns en fiendeborg pÃ¥ en ö i " "havet.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Ansamla en sÃ¥ stor armé som möjligt och inta fiendeborgen inom 8 veckor. Du " "har endast en motstÃ¥ndare, men du mÃ¥ste färdas lÃ¥ngt för att nÃ¥ " "fiendeborgen. Dina trupper som du har i scenariets slut följer med dig till " "slutstriden." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Finn Kronan före Archibalds hjältar hittar den. Roland behöver Kronan för " "slutstriden mot Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Tre allierade fiender, även Lord Corlagon, stÃ¥r mellan dig och segern. " "Roland befinner sig i en borg i nordväst, och du kommer förlora om han " "hamnar i fiendernas klor. Kom igÃ¥ng att om du tillfÃ¥ngatar Lord Corlagon sÃ¥ " "kommer han inte slÃ¥ss mot dig i slutstriden." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Det här är slutstriden. BÃ¥de du och dina fiender är beväpnade till tänderna " "och de har gÃ¥tt samman emot dig. TillfÃ¥ngata Archibald för att avsluta " "kriget!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Lojalitetsbyte lämnar dig med tre borgar mot fiendens enda. Denna strid " "kommer bli din enklaste strid för resten av kriget... förrädare." msgid "Barbarian Wars" msgstr "Barbarkrigen" msgid "First Blood" msgstr "Första Blodspillan" msgid "Necromancers" msgstr "Svartkonstnärer" msgid "Slay the Dwarves" msgstr "Dräp Dvärgarna" msgid "Country Lords" msgstr "Landshövdingar" msgid "Dragon Master" msgstr "Drakmästare" msgid "Rebellion" msgstr "Uppror" msgid "Apocalypse" msgstr "Apokalypsen" msgid "Greater Glory" msgstr "Större Ära" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Kung Archibald kräver att du besegrar tre fiender i denna regionen. De är " "inte allierade med varandra, sÃ¥ de kommer mest strida inbördes. Segern är " "din när du har besegrat alla deras hjältar och intagit deras borgar." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Du mÃ¥ste förena babarstammarna i norr genom att erövra dem. SÃ¥ som i " "föregÃ¥ende uppdrag sÃ¥ är inte fienderna allierade mer varandra, men de har " "mer resurser till sitt förfogande. Du vinner när du kontrollerar alla " "fiendeborgar och alla fiendehjältar är besegrade." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "De skenheliga trollkarlarna har tagit Svartkonstnärernas borg i besittning. " "Du mÃ¥ste Ã¥tererövra borgen för att uppnÃ¥ seger. Kom ihÃ¥g att du startar med " "en stark armé, men du har ingen borg och mÃ¥ste erövra ett inom 7 dagar, " "annars förlorar du. (Tips: Det närmaste borgen finns i sydost.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Dvärgarna behöver besegras innan de kan störa Kung Archibalds planer. " "Rolands styrkor startar mer fler än en hjälte och flera städer, sÃ¥ var " "beredd pÃ¥ angrepp pÃ¥ flera fronter. Du mÃ¥ste inta alla fiendestäder och " "borgar för att utropa seger." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Du mÃ¥ste slÃ¥ ner ett bondeuppror lett av Rolands styrkor. De är allierade " "mot dig, men du har Lord Corlagon, en erfaren hjälte till din hjälp. Erövra " "alla fiendeborgar för att vinna." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Det är tvÃ¥ fiender som har gÃ¥tt samman mot dig i detta uppdrag. BÃ¥da är väl " "rustade och vill driva bort dig frÃ¥n deras ö. Undvik dem och inta Drakstaden " "för att segra." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Dina order är att erövra de herrars land som svurit trohet till Roland. Alla " "fiendestäder har förenats emot dig. Eftersom du börjar utan en borg sÃ¥ mÃ¥ste " "du skynda dig erövra ett innan veckans slut. Erövra alla fiendeborgar för " "segern." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Finn Kronan innan Rolands hjältar hittar den. Archibald behöver Kronan för " "slutstriden mot Roland" msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Det här är slutstriden. BÃ¥de du och dina fiender är beväpnade till tänderna " "och de har gÃ¥tt samman emot dig. TillfÃ¥ngata Roland för att avsluta kriget, " "och försäkra dig om att inte förlora Archibald i strid!" msgid "Arrow's Flight" msgstr "Pilens Bana" msgid "Island of Chaos" msgstr "Kaosön" msgid "The Abyss" msgstr "Avgrunden" msgid "Uprising" msgstr "Upproret" msgid "Aurora Borealis" msgstr "Norrsken" msgid "Betrayal's End" msgstr "Förräderiet" msgid "Corruption's Heart" msgstr "Korruptionens Hjärta" msgid "The Giant's Pass" msgstr "Jättens Pass" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Kuva de bÃ¥ngstyriga lokala herrarna för att ge Imperiet Ã¥tkomst till " "anläggningar för att styra regionen." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Eliminera all opposition i omrÃ¥det, sÃ¥ blir den första delen av artefakten " "din." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Häxan i nordost gör uppror. För imperiets bästa sÃ¥ mÃ¥ste du kväsa deras veka " "uppror pÃ¥ din väg till bergen" msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Kraeger är förberedd inför din ankomst och har samlat en styrka med " "svartkonstnärer för att stoppa dig. Du mÃ¥ste inta borgen Scabsdale innan " "första dagen pÃ¥ tredje veckan, annars kommer Svartkonstnärerna ha blivit för " "starka." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "En barbardespot i omrÃ¥det är ovetandes om din närvaro. Bygg hastigt upp dina " "styrkor innan du är upptäckt och anfallen. Säkra regionen genom att besegra " "alla fiendestyrkor." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Imperiet är svagt i denna regionen. Du kommer inte kunna besegra alla " "fiender i omrÃ¥det sÃ¥ ta vad du kan innan vedergällningen kommer. Kom ihÃ¥g " "att ditt uppdrag är att finna Andurans Hjälm." msgid "For the good of the Empire, eliminate Kraeger." msgstr "För Imperiets bästa, utplÃ¥na Kraeger." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Till slut har du möjligheten och resurserna att rensa imperiet frÃ¥n " "Svartkonstnärernas ondska. Utrota dem helt och du kommer bli inskriven i " "historien som imperiets hjälte." msgid "Border Towns" msgstr "Gränsstäder" msgid "Conquer and Unify" msgstr "Erövra och Förena" msgid "Crazy Uncle Ivan" msgstr "Galne Farbror Ivan" msgid "The Wayward Son" msgstr "Den Egensinnige Sonen" msgid "Ivory Gates" msgstr "Elfenbensportarna" msgid "The Elven Lands" msgstr "Alvländerna" msgid "The Epic Battle" msgstr "Slutstriden" msgid "The Southern War" msgstr "Sydkriget" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Erövra och förena alla fienderstammar. Förlora inte hjälten Jarkonas, " "förfadern till alla ättlingar." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Din rival, kungariket Harondale, attackerer din svaga gränsstäder! Ã…terhämta " "dig frÃ¥n deras första slag och krossa dem helt!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Finn din egensinnige son Joseph som ryktas befinna sig i ensligt land. Finn " "honom innan den tredje mÃ¥nadens första dag annars är det för sent." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Rädda din farbror Ivan. Hitta honom inom 4 mÃ¥nader, annars kommer det inte " "vara till nÃ¥gon hjälp för ditt kungarike." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Förgör barbarerna som attackerar ditt rikes sydliga gräns. Ã…terta erövrade " "städer och invadera sedan djungelriket. Lämna inga fiender levande." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Ã…terta borgen Elfenbensportarna, som har fallit pÃ¥ grund av förräderi." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "FÃ¥ alvernas gunst. De tillÃ¥ter inte att träd huggs ner sÃ¥ vi kommer att " "förse dig med Trä varannan vecka. Du mÃ¥ste vara klar med ditt uppdrag innan " "första dagen pÃ¥ sjunde mÃ¥naden, annars sÃ¥ lär kungariket falla." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Det här är slutstriden mot det rivaliserande kungadömet Harondale. Utrota " "allihop och förlora inte hjälten Jarkonas VI." msgid "Fount of Wizardry" msgstr "Trollkonstens Källa" msgid "Power's End" msgstr "Maktens Slut" msgid "The Eternal Scrolls" msgstr "De Eviga Rullarna" msgid "The Shrouded Isles" msgstr "De Dolda Öarna" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Ditt uppdrag är att besegra de krigande trollkarlarna i de magiska Dolda " "Öarna. När uppdraget är gjort sÃ¥ kommer du ha en rimlig chans mot dina " "rivaler." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Det stora Bibliotekets plats har upptäckts. Du mÃ¥ste nÃ¥ fram till det och " "Ã¥terta staden Chronos som det ligger i." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Hitta Upphävningsklotet som sägs vara begravet nÃ¥gonstans i detta land. Det " "finns ledtrÃ¥dar inristade pÃ¥ stenobelisker som kan hjälpa dig finna det. " "Hitta Klotet innan första dagen pÃ¥ den sjätte mÃ¥naden, annars lär dina " "rivaler ha hittat det före dig." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Du mÃ¥ste ta kontroll över det Förtrollade borgen, där trollkonsten källa " "ligger. Gör detta och segern är din." msgid "Blood is Thicker" msgstr "Blod är Tjockare" msgid "King and Country" msgstr "Kung och Fosterland" msgid "Pirate Isles" msgstr "Piratöarna" msgid "Stranded" msgstr "Skeppsbruten" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Inta staden pÃ¥ ön pÃ¥ den sydöstra stranden för att kunna bygga ett skepp som " "tar dig tillbaka till fastlandet. Förlora inte hjälten Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Finn och besegra piratkaptenen Martine, som hÃ¥ller till i Piratviken. " "Förlora inte Gallavant för dÃ¥ har du förlorat." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Besegra alla styrkor som opponerar sig mot Lord Alberons styre. Gallavant " "fÃ¥r inte stupa." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Största den besuttna monarken Lord Alberon, och hävda din rätt att styra " "över landet. Gallavant fÃ¥r inte stupa." msgid " bane" msgstr "bane" msgid " alliance" msgstr "allians" msgid "Carry-over forces" msgstr "Medföljande Styrkor" msgid " bonus" msgstr " bonus" msgid " defeated" msgstr " besegrad" msgid " will always run away from your army." msgstr " kommer alltid att fly frÃ¥n din armé." msgid " will be willing to join your army." msgstr " är villiga att ansluta till din armé." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "\"%{artifact}\" kommer följa med i kampanjen." msgid "The army will be carried over in the campaign." msgstr "Armén kommer följa med i kampanjen." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Riket kommer fÃ¥ +%{count} %{resource} varje dag." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "%{spell}besvärjelsen kommer följa med i kampanjen." msgid "%{hero} can be hired during scenarios." msgstr "%{hero} kan rekryteras under scenarierna." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" "%{hero} har besegrats och kommer inte vara med i efterföljande scenarier." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Dvärgarna känner igen sina allierade och gladeligen ansluter till din armé." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Jättarna förstÃ¥r att du är den som kallas Dvärgdräparen och ansluter sig " "till dig." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Drakarna rytandes och frustandes gÃ¥r med pÃ¥ att ansluta sig till dig, som " "sin\"Allierade\"." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "När du närmar dig en grupp med alver, sÃ¥ ropar deras ledare. \"Vilka av er " "är modiga nog att ansluta er till denna orädde frände till oss?\" Gruppen " "utbrister glädje när de springer och ansluter sig till din armé." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "Dvärgarna hälsar dig, \"Rolands vän är vÃ¥ran vän. Du mÃ¥ passera.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "Jättarna brölar ut, \"Archibalds allierade mÃ¥ passera.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Drakarna ser dig och ropar. \"VÃ¥r allians med Archibald kräver att vi " "ansluter oss till dig. Tyvärr har du inte nog med plats för oss. Synd!\" De " "skringras sedan snabbt." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Alverna stÃ¥r givakt när du närmar dig. Deras ledare säger, \"LÃ¥t inte oss " "hindra din kamp, frände. Passera och segern mÃ¥ vara din.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Dvärgdräparen!!!! Spring för livet!\"" msgid "campaignBonus|Animate Dead" msgstr "Animera Död" msgid "campaignBonus|Chain Lightning" msgstr "Kedjeblixt" msgid "campaignBonus|Fireblast" msgstr "Eldexplosion" msgid "campaignBonus|Mass Curse" msgstr "" "Mass-\n" "förbannelse" msgid "campaignBonus|Mass Haste" msgstr "" "Mass-\n" "skyndning" msgid "campaignBonus|Mirror Image" msgstr "Spegelbild" msgid "campaignBonus|Resurrect" msgstr "Ã…teruppliva" msgid "campaignBonus|Steelskin" msgstr "StÃ¥lhud" msgid "campaignBonus|Summon Earth" msgstr "Framkalla Jordväsen" msgid "campaignBonus|View Heroes" msgstr "Visa Hjältar" msgid "campaignBonus|Ballista" msgstr "Ballist" msgid "campaignBonus|Black Pearl" msgstr "Svart Pärla" msgid "campaignBonus|Caster's Bracelet" msgstr "Besvärjarens Armband" msgid "campaignBonus|Defender Helm" msgstr "Livgardets Skyddshjälm" msgid "campaignBonus|Breastplate" msgstr "Bröstharnesk" msgid "campaignBonus|Dragon Sword" msgstr "Draksvärd" msgid "campaignBonus|Fizbin Medal" msgstr "Olycksfizbin" msgid "campaignBonus|Foremost Scroll" msgstr "Särskild Kunskapsrulle" msgid "campaignBonus|Gauntlets" msgstr "Skyddstridshandskar" msgid "campaignBonus|Hideous Mask" msgstr "Otäck mask" msgid "campaignBonus|Mage's Ring" msgstr "Trollkarlens Ring" msgid "campaignBonus|Major Scroll" msgstr "Större Kunskapsrulle" msgid "campaignBonus|Medal of Honor" msgstr "Hedersmedalj" msgid "campaignBonus|Medal of Valor" msgstr "Tapperhetsmedalj" msgid "campaignBonus|Minor Scroll" msgstr "Mindre Kunskapsrulle" msgid "campaignBonus|Nomad Boots" msgstr "Nomadens Kängor" msgid "campaignBonus|Power Axe" msgstr "Kraftyxa" msgid "campaignBonus|Spiked Shield" msgstr "Spiksköld" msgid "campaignBonus|Stealth Shield" msgstr "Skyddssköld" msgid "campaignBonus|Tax Lien" msgstr "Skuldebrev" msgid "campaignBonus|Thunder Mace" msgstr "Ã…skans Stridsgissel" msgid "campaignBonus|Traveler's Boots" msgstr "Vandrarens Kängor" msgid "campaignBonus|White Pearl" msgstr "Vit Pärla" msgid "campaignBonus|Basic Archery" msgstr "Basalt Skytte" msgid "campaignBonus|Advanced Archery" msgstr "Avancerat Skytte" msgid "campaignBonus|Expert Archery" msgstr "Expert Skytte" msgid "campaignBonus|Basic Ballistics" msgstr "Basal Ballistik" msgid "campaignBonus|Advanced Ballistics" msgstr "Avancerad Ballistik" msgid "campaignBonus|Expert Ballistics" msgstr "Expert Ballistik" msgid "campaignBonus|Basic Diplomacy" msgstr "Basal Diplomati" msgid "campaignBonus|Advanced Diplomacy" msgstr "Avancerad Diplomati" msgid "campaignBonus|Expert Diplomacy" msgstr "Expert Diplomati" msgid "campaignBonus|Basic Eagle Eye" msgstr "Basal Falkblick" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Avancerad Falkblick" msgid "campaignBonus|Expert Eagle Eye" msgstr "Expert Falkblick" msgid "campaignBonus|Basic Estates" msgstr "Basala Ägor" msgid "campaignBonus|Advanced Estates" msgstr "Avancerade Ägor" msgid "campaignBonus|Expert Estates" msgstr "Expert Ägor" msgid "campaignBonus|Basic Leadership" msgstr "Basalt Ledarskap" msgid "campaignBonus|Advanced Leadership" msgstr "Avancerat Ledarskap" msgid "campaignBonus|Expert Leadership" msgstr "Expert Ledarskap" msgid "campaignBonus|Basic Logistics" msgstr "Basal Logistik" msgid "campaignBonus|Advanced Logistics" msgstr "Avancerad Logistik" msgid "campaignBonus|Expert Logistics" msgstr "Expert Logistik" msgid "campaignBonus|Basic Luck" msgstr "Basal Tur" msgid "campaignBonus|Advanced Luck" msgstr "Avancerad Tur" msgid "campaignBonus|Expert Luck" msgstr "Expert Tur" msgid "campaignBonus|Basic Mysticism" msgstr "Basal Mystik" msgid "campaignBonus|Advanced Mysticism" msgstr "Avancerad Mystik" msgid "campaignBonus|Expert Mysticism" msgstr "Expert Mystik" msgid "campaignBonus|Basic Navigation" msgstr "Basal Navigering" msgid "campaignBonus|Advanced Navigation" msgstr "Avancerad Navigering" msgid "campaignBonus|Expert Navigation" msgstr "Expert Navigering" msgid "campaignBonus|Basic Necromancy" msgstr "Basal Svartkonst" msgid "campaignBonus|Advanced Necromancy" msgstr "Avancerad Svartkonst" msgid "campaignBonus|Expert Necromancy" msgstr "Expert Svartkonst" msgid "campaignBonus|Basic Pathfinding" msgstr "Basal Vägvisning" msgid "campaignBonus|Advanced Pathfinding" msgstr "Avancerad Vägvisning" msgid "campaignBonus|Expert Pathfinding" msgstr "Expert Vägvisning" msgid "campaignBonus|Basic Scouting" msgstr "Basal Spaning" msgid "campaignBonus|Advanced Scouting" msgstr "Avancerad Spaning" msgid "campaignBonus|Expert Scouting" msgstr "Expert Spaning" msgid "campaignBonus|Basic Wisdom" msgstr "Basal Visdom" msgid "campaignBonus|Advanced Wisdom" msgstr "Avancerad Visdom" msgid "campaignBonus|Expert Wisdom" msgstr "Expert Visdom" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "Huvudhjälten kommer ha \"%{artifact}\" i början av scenariet." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Riket kommer fÃ¥ ytterligare %{amount} %{resource} i början av scenariet." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "Riket kommer ha %{amount} mindre %{resource} i början av scenariet." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Huvudhjälten kommer ha %{count} %{monster} i början av scenariet." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" "Huvudhjälten kommer ha \"%{spell}\"-besvärjelsen i början av scenariet." msgid "The starting alignment of the scenario will be %{race}." msgstr "Scenariets startklass är %{race}." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" "Huvudhjälten kommer ha ytterligare %{count} i %{skill} i början av scenariet." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Huvudhjälten kommer ha %{skill} i början av scenariet." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" msgid "Price of Loyalty" msgstr "Lojalitetens Pris" msgid "Voyage Home" msgstr "Hemresan" msgid "Wizard's Isle" msgstr "Trollkarlsön" msgid "Descendants" msgstr "Ättlingar" msgid "Cannot build. You have already built here today." msgstr "Kan inte byggas. Du har redan byggt här idag." msgid "For this action it is necessary to build a castle first." msgstr "För denna Ã¥tgärd är det nödvändigt att först bygga en borg." msgid "The %{building} produces %{monster}." msgstr "%{building} producerar %{monster}." msgid "Requires:" msgstr "Kräver:" msgid "Exit this menu without doing anything." msgstr "Stäng denna meny utan att göra nÃ¥gonting." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Kan ej bygga %{name}. Slottet är för lÃ¥ngt borta frÃ¥n ett hav." msgid "This building has been disabled." msgstr "Byggnaden har inaktiverats." msgid "Cannot afford the %{name}." msgstr "Har inte rÃ¥d med %{name}." msgid "The %{name} is already built." msgstr "%{name} har redan byggts." msgid "Cannot build the %{name}." msgstr "Kan inte bygga %{name}." msgid "Build %{name}." msgstr "Bygg %{name}." msgid "Blackridge" msgstr "Blackridge" msgid "Hillstone" msgstr "Hillstone" msgid "Pinehurst" msgstr "Pinehurst" msgid "Whiteshield" msgstr "Whiteshield" msgid "Woodhaven" msgstr "Woodhaven" msgid "Blackwind" msgstr "Blackwind" msgid "Bloodreign" msgstr "Bloodreign" msgid "Dragontooth" msgstr "Dragontooth" msgid "Greywind" msgstr "Greywind" msgid "Portsmith" msgstr "Portsmith" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Middle Gate" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "Baywatch" msgid "Fountainhead" msgstr "Fountainhead" msgid "Vertigo" msgstr "Vertigo" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Winterkill" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Lakeside" msgid "Nightshadow" msgstr "Nightshadow" msgid "Olympus" msgstr "Olympus" msgid "Sandcaster" msgstr "Sandcaster" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "New Dawn" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Big Oak" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antioch" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Roc Haven" msgid "South Mill" msgstr "South Mill" msgid "Weed Patch" msgstr "Weed Patch" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Hilltop" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Westfork" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "Elk's Head" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Blackburn" msgid "Blacksford" msgstr "Blacksford" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Pig's Eye" msgid "Viper's Nest" msgstr "Viper's Nest" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Timberhill" msgid "Troy" msgstr "Troy" msgid "Forder Oaks" msgstr "Forder Oaks" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Quick Silver" msgid "Westmoor" msgstr "Westmoor" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Kan inte rekrytera - du har redan en Hjälte i denna stad." msgid "Cannot recruit - you have too many Heroes." msgstr "Kan inte rekrytera - du har för mÃ¥nga Hjältar." msgid "Cannot afford a Hero." msgstr "Har inte rÃ¥d med en Hjälte." msgid "There is no room in the garrison for this army." msgstr "Det finns ingen plats i garnisonen för denna armé." msgid "Fortifications" msgstr "Befästningar" msgid "Farm" msgstr "Farm" msgid "Thatched Hut" msgstr "Halmtäckt hydda" msgid "Archery Range" msgstr "BÃ¥gskyttebana" msgid "Upg. Archery Range" msgstr "Uppg. BÃ¥gskyttebana" msgid "Blacksmith" msgstr "Smedja" msgid "Upg. Blacksmith" msgstr "Uppg. Smedja" msgid "Armory" msgstr "Rustkammare" msgid "Upg. Armory" msgstr "Uppg. Rustkammare" msgid "Jousting Arena" msgstr "Turneringsarena" msgid "Upg. Jousting Arena" msgstr "Uppg. Turneringsarena" msgid "Cathedral" msgstr "Katedral" msgid "Upg. Cathedral" msgstr "Uppg. Katedral" msgid "Coliseum" msgstr "Kolosseum" msgid "Garbage Heap" msgstr "Kökkenmödding" msgid "Hut" msgstr "Hydda" msgid "Stick Hut" msgstr "Kvisthydda" msgid "Upg. Stick Hut" msgstr "Uppg. Kvisthydda" msgid "Den" msgstr "Lya" msgid "Adobe" msgstr "Adobe" msgid "Upg. Adobe" msgstr "Uppg. Adobe" msgid "Bridge" msgstr "Bro" msgid "Upg. Bridge" msgstr "Uppg. Bro" msgid "Pyramid" msgstr "Pyramid" msgid "Rainbow" msgstr "RegnbÃ¥ge" msgid "Crystal Garden" msgstr "KristallträdgÃ¥rd" msgid "Treehouse" msgstr "Trädhus" msgid "Cottage" msgstr "Stuga" msgid "Upg. Cottage" msgstr "Uppg. Stuga" msgid "Stonehenge" msgstr "Stonehenge" msgid "Upg. Stonehenge" msgstr "Uppg. Stonehenge" msgid "Fenced Meadow" msgstr "Inhägnad Äng" msgid "sorceress|Red Tower" msgstr "Rött Torn" msgid "Dungeon" msgstr "FängelsehÃ¥la" msgid "Waterfall" msgstr "Vattenfall" msgid "Cave" msgstr "Grotta" msgid "Crypt" msgstr "Krypta" msgid "Nest" msgstr "Näste" msgid "Maze" msgstr "Labyrint" msgid "Upg. Maze" msgstr "Uppg. Labyrint" msgid "Swamp" msgstr "Träsk" msgid "Green Tower" msgstr "Grönt Torn" msgid "warlock|Red Tower" msgstr "Rött Torn" msgid "Black Tower" msgstr "Svart Torn" msgid "Library" msgstr "Bibliotek" msgid "Orchard" msgstr "Fruktodling" msgid "Habitat" msgstr "HobhÃ¥la" msgid "Pen" msgstr "Hägn" msgid "Foundry" msgstr "Gjuteri" msgid "Upg. Foundry" msgstr "Uppg. Gjuteri" msgid "Cliff Nest" msgstr "Klippnäste" msgid "Ivory Tower" msgstr "Elfenbenstorn" msgid "Upg. Ivory Tower" msgstr "Uppg. Elfenbenstorn" msgid "Cloud Castle" msgstr "Molnslott" msgid "Upg. Cloud Castle" msgstr "Uppg. Molnslott" msgid "Storm" msgstr "Storm" msgid "Skull Pile" msgstr "Benhög" msgid "Excavation" msgstr "Utgrävning" msgid "Graveyard" msgstr "KyrkogÃ¥rd" msgid "Upg. Graveyard" msgstr "Uppg. KyrkogÃ¥rd" msgid "Upg. Pyramid" msgstr "Uppg. Pyramid" msgid "Mansion" msgstr "HerrgÃ¥rd" msgid "Upg. Mansion" msgstr "Uppg. HerrgÃ¥rd" msgid "Mausoleum" msgstr "Mausoleum" msgid "Upg. Mausoleum" msgstr "Uppg. Mausoleum" msgid "Laboratory" msgstr "Laboratorium" msgid "Shrine" msgstr "Helgedom" msgid "Special" msgstr "Särskild" msgid "Horde Building" msgstr "Hordbyggnad" msgid "Dwelling 1" msgstr "Boning 1" msgid "Dwelling 2" msgstr "Boning 2" msgid "Upg. Dwelling 2" msgstr "Uppg. Boning 2" msgid "Dwelling 3" msgstr "Boning 3" msgid "Upg. Dwelling 3" msgstr "Uppg. Boning 3" msgid "Dwelling 4" msgstr "Boning 4" msgid "Upg. Dwelling 4" msgstr "Uppg. Boning 4" msgid "Dwelling 5" msgstr "Boning 5" msgid "Upg. Dwelling 5" msgstr "Uppg. Boning 5" msgid "Dwelling 6" msgstr "Boning 6" msgid "Upg. Dwelling 6" msgstr "Uppg. Boning 6" msgid "2x Upg. Dwelling 6" msgstr "2x Uppg. Boning 6" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Befästningar ökar dina borgmurars styrka, ökar antal rundor det krävs för " "att riva dem." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Farmen ökar produktionen av Bönder med %{count} per vecka." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Kolosseum erbjuder spännande och inspirerande gladiatorspel Ã¥t de " "försvarande trupperna, och höjer stridsmoralen med 2." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Kökkenmöddingen ökar produktionen av Vättar med %{count} per vecka." msgid "The Rainbow increases the luck of the defending units by two." msgstr "RegnbÃ¥gen ökar turen hos försvarstrupperna med 2." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "KristallträdgÃ¥rden ökar produktionen av Féer med %{count} per vecka." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "FängelsehÃ¥lan ökar stadens inkomst med %{count} guld per dag." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Vattenfallet ökar produktionen av Kentaurer med %{count} per vecka." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Biblioteket ökar besvärjelser i Magisamfundet med ytterligare en för varje " "nivÃ¥." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Fruktodlingen ökar produktionen av Hober med %{count} per vecka." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "Stormen ökar Trollkonsten för en försvarande besvärjelsekastare med 2." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Benhögen ökar produktionen av Skelett med %{count} per vecka." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "Särskilda byggnaden ger en särskild bonus till den valda borgtypen." msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Hordbyggnaden ökar produktionen i alla nivÃ¥ 1-boningar med 8 varelser per " "vecka." msgid "Thieves' Guild" msgstr "Tjuvgille" msgid "Tavern" msgstr "Värdshus" msgid "Shipyard" msgstr "Skeppsvarv" msgid "Well" msgstr "Brunn" msgid "Statue" msgstr "Staty" msgid "Marketplace" msgstr "Marknad" msgid "Moat" msgstr "Vallgrav" msgid "Castle" msgstr "Slott" msgid "Tent" msgstr "Tält" msgid "Captain's Quarters" msgstr "Kaptensbostad" msgid "Mage Guild, Level 1" msgstr "Magisamfund, nivÃ¥ 1" msgid "Mage Guild, Level 2" msgstr "Magisamfund, nivÃ¥ 2" msgid "Mage Guild, Level 3" msgstr "Magisamfund, nivÃ¥ 3" msgid "Mage Guild, Level 4" msgstr "Magisamfund, nivÃ¥ 4" msgid "Mage Guild, Level 5" msgstr "Magisamfund, nivÃ¥ 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Helgedomen ökar SvartkonstförmÃ¥gan hos dina svartkonstnärer med 10 procent." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Tjuvgillet ger infomation om fiendespelare. Tjuvgillet erbjuder även " "spaningsinformation om fiendestäder. Fler Gillen ger bättre information." msgid "The Tavern increases morale for troops defending the castle." msgstr "Värdshuset höjer stridsmoralen för trupperna som försvarar borgen." msgid "The Shipyard allows ships to be built." msgstr "Skeppsvarvet bygger skepp." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Brunnen ökar produktionen i alla boningar med %{count} varelser per vecka." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Statyn ökar stadens inkomst med %{count} guld per dag." msgid "The Left Turret provides extra firepower during castle combat." msgstr "Vänster Torn ger extra mycket eldkraft under borgstrid." msgid "The Right Turret provides extra firepower during castle combat." msgstr "Höger Torn ger extra mycket eldkraft under borgstrid." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Marknaden används för att växla en resurs till en annan. Ju fler marknader " "du kontrollerar desto bättre växlingskurs." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Vallgraven saktar ner anfallande trupper. En varelse som kliver i vallgraven " "avslutar sin tur och blir lätt utsatt för ett anfall." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Slottet förbättrar stadens försvar och ökar dess inkomst till %{count} guld " "per dag." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Tältet lÃ¥ter arbetare bygga en borg, förutsatt att det finns tillräckligt " "med guld och resurser." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Kaptensbostaden tillÃ¥ter att en Kapten att assistera i borgens försvar när " "ingen hjälte är närvarande." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Magisamfundet lÃ¥ter hjältar att lära sig besvärjelser och Ã¥terhämta " "besvärjelsepoäng." msgid "Recruit %{name}" msgstr "Rekrytera %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "MÃ¥nad: %{month}, Vecka: %{week}, Dag: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Du mÃ¥ste köpa en Magibok för att fÃ¥ tillgÃ¥ng till Magikersamfundet. Tyvärr " "har du ingen plats för en Magibok. Försök ge en artefakt till en annan " "hjälte." msgid "Click to show next town." msgstr "Klicka för att visa nästa stad." msgid "Show next town" msgstr "Visa nästa stad" msgid "Click to show previous town." msgstr "Klicka för att visa föregÃ¥ende stad." msgid "Show previous town" msgstr "Visa föregÃ¥ende stad" msgid "This town may not be upgraded to a castle." msgstr "Denna stad kan inte uppgraderas till en borg." msgid "Town" msgstr "Stad" msgid "Exit Castle" msgstr "Lämna Slottet" msgid "Exit Town" msgstr "Lämna Staden" msgid "Show Income" msgstr "Visa Inkomst" msgid "View Hero" msgstr "Visa Hjälte" msgid "The above spells are available here." msgstr "OvanstÃ¥ende besvärjelser är tillgängliga här." msgid "The spells the hero can learn have been added to their book." msgstr "Besvärjelser som hjälten kan lära sig har lagts till dennes bok." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Ett generöst tips frÃ¥n bartendern som uppger detta rykte:" msgid "Recruit Hero" msgstr "Rekrytera Hjälte" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} är en nivÃ¥ %{value} %{race} " msgid "with %{count} artifacts." msgstr "med %{count} artefakter." msgid "with 1 artifact." msgstr "med 1 artefakt." msgid "without artifacts." msgstr "utan artefakter." msgid "Recruit %{name} the %{race}" msgstr "Rekrytera %{race}n %{name}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Utspridd' stridsformation sprider ut hjältens trupper över hela slagfältet " "med minst ett tomt mellanrum mellan varje trupp." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "'Grupperad' stridsformation buntar ihop hjältens trupper till mitten av " "dennes sida av slagfältet." msgid "Spread Formation" msgstr "Utspridd formation" msgid "Grouped Formation" msgstr "Grupperad formation" msgid "Click to show the next town." msgstr "Klicka för att visa nästa stad." msgid "Click to show the previous town." msgstr "Klicka för att visa föregÃ¥ende stad." msgid "Set garrison combat formation to 'Spread'" msgstr "Ändra granisonstruppernas stridsformation till 'Utspridd'" msgid "Set garrison combat formation to 'Grouped'" msgstr "Ändra granisonstruppernas stridsformation till 'Grupperad'" msgid "Exit Castle Options" msgstr "Lämna Slottsalternativ" msgid "Castle Options" msgstr "Slottalternativ" msgid "Not enough resources to recruit creatures." msgstr "För lite resurser för att rekrytera varelser." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Du kan inte rekrytera just nu. Dina led är fulla." msgid "No creatures available for purchase." msgstr "Inga varelser tillgängliga för köp." msgid "Recruit Creatures" msgstr "Rekrytera Varelser" msgid "Hire all creatures in the town." msgstr "Rekrytera alla varelser i staden." msgid "Max" msgstr "Maximalt" msgid "Available" msgstr "Tillgängligt" msgid "Town Population Information and Statistics" msgstr "Stadsbefolkning- och Statistikinfo." msgid "Damage" msgstr "Skada" msgid "HP" msgstr "HP" msgid "Growth" msgstr "Tillväxt" msgid "week" msgstr "vecka" msgid "View World" msgstr "Visa Karta" msgid "View the entire world." msgstr "Visa hela kartan." msgid "Puzzle" msgstr "Pussel" msgid "View the obelisk puzzle." msgstr "Visa obeliskpusslet." msgid "Scenario Information" msgstr "Scenarioinformation" msgid "View information on the scenario you are currently playing." msgstr "Visa information om scenariet som du spelar." msgid "Dig for the Ultimate Artifact." msgstr "Gräv efter den Främsta Artefakten." msgid "Digging" msgstr "Gräver" msgid "Arena" msgstr "Arena" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Du kliver in i arenan och möter en flock lejon. Du besegrar dem utan större " "ansträngning och publiken hurrar. Den Ã¥ldrade gladiatortränaren gÃ¥r med pÃ¥ " "att träna dig i en valfri färdighet." msgid "Attack Skill" msgstr "Anfall" msgid "Defense Skill" msgstr "Försvar" msgid "Shots" msgstr "Projektiler" msgid "Shots Left" msgstr "Projektiler kvar" msgid "Hit Points" msgstr "Hälsopoäng" msgid "Hit Points Left" msgstr "Hälsopoäng kvar" msgid "You can't afford to upgrade your troops!" msgstr "Du har inte rÃ¥d att upgradera dina trupper!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Dina trupper kan uppgraderas, men det kommer att bli dyrt. Vill du " "uppgradera dem?" msgid "Are you sure you want to dismiss this army?" msgstr "Är du säker pÃ¥ att du vill avskeda denna armé?" msgid "Upgrade" msgstr "Uppgradera" msgid "Upgrade your troops." msgstr "Uppgradera dina trupper." msgid "Dismiss" msgstr "Avskeda" msgid "Dismiss this army." msgstr "Avskeda armén." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "En grupp %{monster} med en längtan efter ära och berömmelse önskar att göra " "dig sällskap.\n" "Accepterar du?" msgid "Followers" msgstr "Anhängare" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "Alla %{monster} vill förena sig med din armé för en summa pÃ¥ %{gold} guld.\n" "Accepterar du det?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Varelserna är tagna av din diplomatiska förmÃ¥ga\n" "och kommer med ett förslag:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} av %{total} %{monster} förenar sig med din armé, resten lämnar dig " "ifred, för en summa pÃ¥ %{gold} guld.\n" "Accepterar du det?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Alla %{offer} %{monster} vill förena sig med din armé för en summa pÃ¥ " "%{gold} guld.\n" "Accepterar du det?" msgid "(Rate: %{percent})" msgstr "(Andel: %{percent} procent)" msgid "off" msgstr "av" msgid "Music" msgstr "Musik" msgid "Effects" msgstr "Effekter" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI-expansion" msgid "External" msgstr "Extern" msgid "Music Type" msgstr "Musiktyp" msgid "3D Audio" msgstr "3D-ljud" msgid "Toggle ambient music level." msgstr "Välj ljudnivÃ¥ för bakgrundsmusik." msgid "Toggle foreground sounds level." msgstr "Välj ljudnivÃ¥ för ljudeffekter." msgid "Change the type of music." msgstr "Ändra musiktyp." msgid "Toggle the 3D effect of foreground sounds." msgstr "Aktivera 3D-funktion för ljudeffekter." msgid "Build a new ship:" msgstr "Bygg ett nytt skepp:" msgid "Resource cost:" msgstr "Resurskostnad:" msgid "Total: " msgstr "Totalt: " msgid "Need: " msgstr "Behöver: " msgid "New Game" msgstr "Nytt Spel" msgid "Start a single or multi-player game." msgstr "Starta ett spel med en eller flera spelare." msgid "Load Game" msgstr "Ladda Spel" msgid "Load a previously saved game." msgstr "Ladda ett tidigare sparat spel." msgid "Save Game" msgstr "Spara Spel" msgid "Save the current game." msgstr "Spara nuvarande spel." msgid "Quit" msgstr "Avsluta" msgid "Quit out of Heroes of Might and Magic II." msgstr "Avsluta Heroes of Might and Magic II." msgid "Language" msgstr "SprÃ¥k" msgid "Graphics" msgstr "Grafik" msgid "Black & White" msgstr "Svart & Vitt" msgid "Mouse Cursor" msgstr "Muspekare" msgid "Color" msgstr "Färg" msgid "Text Support" msgstr "Texthjälp" msgid "Change the language of the game." msgstr "Ändra spelets sprÃ¥k" msgid "Select Game Language" msgstr "Välj spelsprÃ¥k" msgid "Change the graphics settings of the game." msgstr "Ändra spelets grafikinställningar" msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" "Välj färglagd eller svartvit muspekare. Detta är bara ett estetiskt val." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Aktivera textstöd för att visa ytterligare information om fönster och " "händelser i spelet." msgid "" "Map\n" "Difficulty" msgstr "" "Kartans\n" "SvÃ¥righet" msgid "" "Game\n" "Difficulty" msgstr "" "Spelets\n" "SvÃ¥righet" msgid "Rating" msgstr "Rang" msgid "Map Size" msgstr "Kartstorlek" msgid "Opponents" msgstr "MotstÃ¥ndare" msgid "Class" msgstr "Klass" msgid "" "Victory\n" "Conditions" msgstr "" "Seger-\n" "villkor" msgid "" "Loss\n" "Conditions" msgstr "" "Förlust-\n" "villkor" msgid "First select recipients!" msgstr "Först välj mottagare!" msgid "You cannot select %{resource}!" msgstr "Du kan inte välja %{resource}!" msgid "Set %{resource-type} Count" msgstr "Ange %{resource-type} antal" msgid "Select Recipients" msgstr "Välj mottagare" msgid "Your Funds" msgstr "Dina Resurser" msgid "Planned Gift" msgstr "GÃ¥va" msgid "Gift from %{name}" msgstr "GÃ¥va frÃ¥n %{name}" msgid "Resolution" msgstr "Upplösning" msgid "Fullscreen" msgstr "Fullskärm" msgid "window|Mode" msgstr "Fönsterläge" msgid "Windowed" msgstr "Fönsterläge" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Systeminfo." msgid "Change the resolution of the game." msgstr "Ändra spelets upplösning." msgid "Select Game Resolution" msgstr "Välj spelupplösning" msgid "Toggle between fullscreen and windowed modes." msgstr "Växla mellan fullskärmsläge och fönsterläge." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "V-Sync kan aktiveras för att lösa flimmerproblem pÃ¥ vissa skärmar." msgid "Show extra information such as FPS and current time." msgstr "Visa extra information som FPS och nuvarande tid." msgid "Hotkey: " msgstr "Snabbtangent: " msgid "Category: " msgstr "Kategori: " msgid "Event: " msgstr "Händelse: " msgid "Hot Keys:" msgstr "Snabbtangenter:" msgid "Hide" msgstr "Dölj" msgid "Show" msgstr "Visa" msgid "Interface" msgstr "Gränssnitt" msgid "Interface Type" msgstr "Gränssnittsstil" msgid "Toggle the type of interface you want to use." msgstr "Välj vilket gränssnitt du vill använda." msgid "Toggle interface visibility." msgstr "Aktivera gränssnittsynlighet." msgid "Scroll Speed" msgstr "" "Skroll-\n" "hastighet" msgid "Sets the speed at which you scroll the window." msgstr "Välj skrollhastigheten." msgid "Select Game Language:" msgstr "Välj spelsprÃ¥k:" msgid "Select Language:" msgstr "Välj sprÃ¥k:" msgid "Click to choose the selected language." msgstr "Klicka för att anta valt sprÃ¥k." msgid "%{name} has gained a level." msgstr "%{name} har gÃ¥tt upp en nivÃ¥." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Du har lärt dig %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} har gÃ¥tt upp en nivÃ¥.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Du kan lära dig antingen:\n" "%{skill1}\n" "eller\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "Välj %{secondary-skill}" msgid "n/a" msgstr "Inga" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Var god granska vÃ¥ra fina varor. Om du vill köpa nÃ¥gonting, klickar du pÃ¥ " "föremÃ¥let du vill köpa med och för." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Du har fÃ¥tt ett riktigt fynd. Jag förväntar mig inte att göra nÃ¥gon vinst pÃ¥ " "affären. Kan jag intressera dig med nÃ¥gra andra varor?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Jag kan erbjuda dig %{count} för 1 %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Jag kan erbjuda dig 1 %{resto} för %{count} %{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Byt antal" msgid "Trading Post" msgstr "Handelsstation" msgid "Your Resources" msgstr "Dina resurser" msgid "Available Trades" msgstr "Tillgänglig handel" msgid "guarded by %{count} %{monster}" msgstr "vaktas av %{count} %{monster}" msgid "guarded by " msgstr "vaktas av " msgid "(available: %{count})" msgstr "(tillgängligt: %{count})" msgid "(empty)" msgstr "(tom)" msgid "already learned" msgstr "redan inlärt" msgid "treeOfKnowledge|free" msgstr "Gratis" msgid "already claimed" msgstr "redan inlärt" msgid "not claimed" msgstr "inte inlärt" msgid "already knows this skill" msgstr "kan redan denna färdighet" msgid "already has max skills" msgstr "har redan maximalt antal färdigheter" msgid "(already visited)" msgstr "(redan besökt)" msgid "(not visited)" msgstr "(inte besökt)" msgid "%{color} Barrier" msgstr "%{color} Barriär" msgid "(tent visited)" msgstr "(tält besökt)" msgid "%{color} Tent" msgstr "%{color} Tält" msgid "Road" msgstr "Väg" msgid "(digging ok)" msgstr "(grävning okej)" msgid "(no digging)" msgstr "(ingen grävning)" msgid "penalty: %{cost}" msgstr "straff: %{cost}" msgid "Defenders:" msgstr "Försvarare:" msgid "Unknown" msgstr "Okänd" msgid "heroQuickInfo|(Level %{level})" msgstr "(nivÃ¥ %{level})" msgid "Attack:" msgstr "Anfall:" msgid "Defense:" msgstr "Försvar:" msgid "Spell Power:" msgstr "Trollkonst:" msgid "Knowledge:" msgstr "Kunskap:" msgid "Spell Points:" msgstr "Besvärjelsepoäng:" msgid "Move Points:" msgstr "Steg:" msgid "Uncharted Territory" msgstr "Outforskat OmrÃ¥de" msgid "Cost per troop:" msgstr "Kostnad per trupp:" msgid "Available: %{count}" msgstr "Tillgängligt: %{count}" msgid "Number to buy:" msgstr "Antal att köpa:" msgid "Recruit selected monsters." msgstr "Rekrytera valda varelser." msgid "Select maximum monsters to be recruited." msgstr "Välj maximalt antal varelser att rekrytera." msgid "Select only 1 monster to be recruited." msgstr "Välj endast 1 varelse att rekrytera." msgid "Select this game resolution." msgstr "Välj denna spelupplösningen." msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" "Denna upplösningen kommer att skala upplösningen frÃ¥n den ursprungliga " "upplösningen (%{resolution}) genom att multiplicera den med talet inom " "parentesen (%{scale}).\n" "\n" "En upplösning med heltal (2.0x, 3.0x etc.) kommer vanligtvis se bättre ut " "för att pixlarna skalas upp lika i bÃ¥de horisontal och vertikal riktning." msgid "Select Game Resolution:" msgstr "Ange Spelupplösning:" msgid "Click to apply the selected resolution." msgstr "Klicka här för att anta den valda upplösningen." msgid "Click to apply the entered text." msgstr "Klicka här för att anta den inmatade texten." msgid "Click to open the Virtual Keyboard dialog." msgstr "Klicka här för att öppna det virtuella tangentbordet." msgid "Open Virtual Keyboard" msgstr "Öppna virtuellt tangentbord." msgid "How many creatures do you wish to move?" msgstr "Hur mÃ¥nga varelser vill du flytta?" msgid "Select how many units to separate into:" msgstr "Välj hur mÃ¥nga enheter att dela till:" msgid "Map: " msgstr "Karta: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "MÃ¥nad: " msgid ", Week: " msgstr ", Vecka: " msgid ", Day: " msgstr ", Dag: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Plats: " msgid "Are you sure you want to delete file:" msgstr "Är du säker pÃ¥ att du vill radera filen:" msgid "Warning" msgstr "Varning" msgid "Click to save the current game." msgstr "Klicka för att spara nuvarande spel." msgid "Click to load a previously saved game." msgstr "Klicka för att ladda ett tidigare sparat spel." msgid "File to Save:" msgstr "Fil att Spara:" msgid "File to Load:" msgstr "Fil att Ladda:" msgid "Terrain object" msgstr "TerrängföremÃ¥l" msgid "Accept the choice made." msgstr "Acceptera alla ändringar." msgid "Select Skill:" msgstr "Välj FörmÃ¥ga:" msgid "Select Spell:" msgstr "Välj Besvärjelse" msgid "Select Artifact:" msgstr "Välj Artefakt:" msgid "Select Monster:" msgstr "Välj Varelse:" msgid "Select Hero:" msgstr "Välj Hjälte:" msgid "race|Random" msgstr "Slumpad" msgid "Click to start placing the selected hero." msgstr "Klicka här för att placera den valda hjälten." msgid "%{color} %{race}" msgstr "%{color} %{race}" msgid "You will place" msgstr "Du kommer placera" msgid "Click to select this class." msgstr "Klicka här för att välja denna klass." msgid "Click to select this color." msgstr "Klicka här för att välja denna färgen." msgid "Select Treasure:" msgstr "Välj Skatt:" msgid "Select Ocean Object:" msgstr "Välj HavsföremÃ¥l:" msgid "Castle/town placing" msgstr "Slott/stadsplacering" msgid "doubleLinedRace|Neutral" msgstr "Neutral" msgid "Click to start placing the selected castle/town." msgstr "Klicka här för att placera den valda borgen/staden." msgid "Click to select town placing." msgstr "Klicka för att välja stadsplacering." msgid "Click to select castle placing." msgstr "Klicka här för att välja borgplacering." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{race} %{townOrCastle}" msgid "race|Neutral" msgstr "Neutral" msgid "Select Dwelling:" msgstr "Välj Bostad:" msgid "Select Landscape Object:" msgstr "Välj LandskapsföremÃ¥l:" msgid "Mine placing" msgstr "Gruvplacering" msgid "" "Resource\n" "type:" msgstr "Resurstyp:" msgid "%{mineName} appearance:" msgstr "Utseende %{mineName}:" msgid "Click to select %{object} as the resource generator to be placed." msgstr "Klicka här för att välja %{object} som resursalstrare för placering." msgid "Select Mountain Object:" msgstr "Välj BergsföremÃ¥l:" msgid "Select Rock Object:" msgstr "Välj BlockföremÃ¥l:" msgid "Select Tree Object:" msgstr "Välj TrädföremÃ¥l:" msgid "Select Power Up Object:" msgstr "Välj KraftökningsföremÃ¥l:" msgid "Select Adventure Object:" msgstr "Välj ÄventyrsföremÃ¥l:" msgid "Players Icon" msgstr "Spelarikon" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Anger hur mÃ¥nga spelare totalt det är i kartan. Platser som inte upptas av " "en människa kommer spelas av datorkontrollerade spelare." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Anger om kartan är liten (36 x 36),\n" "medel (72 x 72), stor (108 x 108)\n" "eller extrastor (144 x 144)." msgid "Size Icon" msgstr "Ikonstorlek" msgid "Map Type" msgstr "Karttyp" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Visar om kartan är gjord för \"The Succession Wars-\", \"The Price of " "Loyalty-\" eller \"Resurrection\"-versionen av spelet." msgid "Map Type:\n" msgstr "Karttyp:\n" msgid "The Succession Wars" msgstr "Successionskrigen" msgid "The Price of Loyalty" msgstr "Lojalitetens Pris" msgid "Resurrection" msgstr "Resurrection" msgid "" "\n" "\n" "Language:\n" msgstr "" "\n" "\n" "SprÃ¥k:\n" msgid "Lose all your heroes and towns." msgstr "Förlora alla dina hjältar och städer." msgid "Lose a specific town." msgstr "Förlora en viss stad." msgid "Lose a specific hero." msgstr "Förlora en viss hjälte." msgid "Run out of time. Fail to win by a certain point." msgstr "FÃ¥ slut pÃ¥ tid. Vinn innan en viss tidpunkt." msgid "Loss Condition" msgstr "Förlustvillkor" msgid "Defeat all enemy heroes and towns." msgstr "Besegra alla fiendehjältar och städer." msgid "Capture a specific town." msgstr "Erövra en viss stad." msgid "Defeat a specific hero." msgstr "Besegra en viss hjälte." msgid "Find a specific artifact." msgstr "Hitta en viss artefakt." msgid "Your side must defeat the opposing side." msgstr "Din sida mÃ¥ste besegra motstÃ¥ndarsidan." msgid "Accumulate a large amount of gold." msgstr "Samla ihop en stor summa guld." msgid "Victory Condition" msgstr "Segervillkor" msgid "Map difficulty:" msgstr "KartsvÃ¥righet:" msgid "N" msgstr "N" msgid "No maps exist at that size." msgstr "Finns inga kartor av den storleken." msgid "Small Maps" msgstr "SmÃ¥ Kartor" msgid "View only maps of size small (36 x 36)." msgstr "Visa bara kartor med storleken (36 x 36)." msgid "Medium Maps" msgstr "Medelstora Kartor" msgid "View only maps of size medium (72 x 72)." msgstr "Visa bara kartor med storleken (72 x 72)." msgid "Large Maps" msgstr "Stora Kartor" msgid "View only maps of size large (108 x 108)." msgstr "Visa bara kartor med storleken (108 x 108)." msgid "Extra Large Maps" msgstr "Extrastora Kartor" msgid "View only maps of size extra large (144 x 144)." msgstr "Visa bara kartor med storleken (144 x 144)." msgid "All Maps" msgstr "Alla Kartor" msgid "View all maps, regardless of size." msgstr "Visa alla kartor, oavsett storlek." msgid "Selected Name" msgstr "Valt Namn" msgid "The name of the currently selected map." msgstr "Den valda kartans namn." msgid "Selected Map Difficulty" msgstr "Vald kartsvÃ¥righet" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "SvÃ¥righetsgraden för den valda kartan. Kartans svÃ¥righet bestäms av kartans " "kreatör. SvÃ¥rare kartor kan innehÃ¥ller fler och/eller starkare fienden, " "färre resurser eller andra specialvillkor som gör det svÃ¥rare för spelaren." msgid "Selected Description" msgstr "Vald beskrivning" msgid "The description of the currently selected map." msgstr "Den valda kartans beskrivning." msgid "Jump" msgstr "Hoppa" msgid "Hero Speed" msgstr "" "Hjälte-\n" "hastighet" msgid "Don't Show" msgstr "Visa ej" msgid "Enemy Speed" msgstr "" "Fiende-\n" "hastighet" msgid "Auto Resolve" msgstr "Snabbstrid" msgid "Auto, No Spells" msgstr "" "Snabbstrid, \n" "Inga Besvärjelser" msgid "Battles" msgstr "Strider" msgid "combatMode|Manual" msgstr "Manuell" msgid "Change the speed at which your heroes move on the main screen." msgstr "Ändra hastigheten för dina hjältars rörelser pÃ¥ kartan." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Välj hastigheten för datorns rörelser pÃ¥ kartan. Du kan välja inte visa " "datorns rörelser alls." msgid "Change the interface settings of the game." msgstr "Ändra spelets gränsnittsinställningar." msgid "Interface Settings" msgstr "Gränssnittsinställningar" msgid "Toggle instant battle mode." msgstr "Aktivera Snabbstrid." msgid "Att." msgstr "Anfall" msgid "Def." msgstr "Försv." msgid "Power" msgstr "Trollk." msgid "Knowl" msgstr "Kunskap" msgid "1st" msgstr "1:a" msgid "2nd" msgstr "2:a" msgid "3rd" msgstr "3:e" msgid "4th" msgstr "4:e" msgid "5th" msgstr "5:e" msgid "6th" msgstr "6:e" msgid "Oracle: Player Rankings" msgstr "Orakel: Spelarrang" msgid "Thieves' Guild: Player Rankings" msgstr "Tjuvgille: Spelarrang" msgid "Number of Towns:" msgstr "Antal Städer:" msgid "Number of Castles:" msgstr "Antal Slott:" msgid "Number of Heroes:" msgstr "Antal Hjältar:" msgid "Gold in Treasury:" msgstr "Guld i Skattkammaren:" msgid "Wood & Ore:" msgstr "Trä & Malm:" msgid "Gems, Cr, Slf & Mer:" msgstr "Andra Resurser:" msgid "Obelisks Found:" msgstr "Funna Obelisker:" msgid "Artifacts:" msgstr "Artefakter:" msgid "Total Army Strength:" msgstr "Total Arméstyrka:" msgid "Income:" msgstr "Inkomst:" msgid "Best Hero:" msgstr "Bästa Hjälte:" msgid "Best Hero Stats:" msgstr "Status för Bästa hjälte:" msgid "Personality:" msgstr "Personlighet:" msgid "Best Monster:" msgstr "Bästa Varelse:" msgid "Random Castle Name" msgstr "Slumpat Slottsnamn" msgid "Random Town Name" msgstr "Slumpat Stadsnamn" msgid "Allow Castle build" msgstr "TillÃ¥t Slottsbygge" msgid "Default Buildings" msgstr "Standardbyggnader" msgid "Default Army" msgstr "Standardarmé" msgid "Castle Army" msgstr "Slottsarmé" msgid "Town Army" msgstr "Stadsarmé" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" "Klicka för att ändra Slottsnamn. Högerklicka för att Ã¥terställa till " "standard." msgid "Enter Castle name" msgstr "Skriv Slottsnamn" msgid "Allow to build a castle in this town." msgstr "TillÃ¥t att en borg byggs i denna stad." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" "Aktivera för att använda standardbyggnader. Anpassade byggnader kommer att " "Ã¥terställas!" msgid "Toggle building construction restriction mode." msgstr "Aktivera begränsat byggnationsläge." msgid "Restrict Building Construction" msgstr "Begränsa Byggnadskonstruktion" msgid "Use default defenders army." msgstr "Använd försvararnas standardarmé." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "Ange anpassad Slottsarmé. Högerklicka för att Ã¥terställa enheten." msgid "Message Text:" msgstr "Meddelandetext:" msgid "Reward:" msgstr "Belöning:" msgid "Player colors allowed to get event:" msgstr "Spelarfärger som kan fÃ¥ händelsen:" msgid "Computer colors allowed to get event:" msgstr "Datorfärger som kan fÃ¥ händelsen:" msgid "First day of occurrence:" msgstr "Inträffar först dag:" msgid "Repeat period (days):" msgstr "Upprepa period (dagar):" msgid "Allow %{color} human player to get event" msgstr "TillÃ¥t %{color} spelare att fÃ¥ händelsen" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" "Om denna checkruta är ifylld sÃ¥ kommer händelsen bara aktiveras för %{color} " "spelare om de är styrda av en mänsklig spelare." msgid "Allow %{color} computer player to get event" msgstr "TillÃ¥t %{color} datorspelare att fÃ¥ händelsen" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" "Om denna checkruta är ifylld sÃ¥ kommer händelsen bara aktiveras för %{color} " "spelare om de är styrda av datorn." msgid "Message:" msgstr "Meddelande:" msgid "Click to save the Event properties." msgstr "Klicka för att spara Händelseegenskaperna." msgid "No resources will be given as a reward." msgstr "Inga resurser kommer att ges som belöning." msgid "Resources" msgstr "Resurser" msgid "Resources will be given as a reward." msgstr "Resurser kommer att ges som belöning." msgid "Click here to change the event message." msgstr "Klicka för att ändra händelsemeddelandet." msgid "Event Message Text" msgstr "Händelsetext" msgid "Day: %{day}" msgstr "Dag: %{day}" msgid "Daily Events" msgstr "Dagliga Händelser" msgid "Click to save the events." msgstr "Klicka för att spara händelserna." msgid "Add Event" msgstr "Lägg till Händelse" msgid "Add an additional event." msgstr "Lägg till en ytterligare händelse." msgid "Edit Event" msgstr "Redigera Händelse" msgid "Edit an existing event." msgstr "Redigera en existerande händelse." msgid "Delete Event" msgstr "Radera Händelse" msgid "Delete an existing event." msgstr "Radera en redan existerande händelse." #, fuzzy msgid "Effects:" msgstr "Effekter" #, fuzzy msgid "Conditions:" msgstr "" "Förlust-\n" "villkor" msgid "Cancel event after first visit" msgstr "Avbryt händelse efter första besök" #, fuzzy msgid "Computer colors allowed to get the event:" msgstr "Datorfärger som kan fÃ¥ händelsen:" msgid "Set Experience value" msgstr "Ange erfarenhetspoäng" msgid "Artifact" msgstr "Artefakt" #, fuzzy msgid "No artifact will be given by the event." msgstr "Ingen artefakt kommer att ges som belöning." msgid "Delete Artifact" msgstr "Radera Artefakt" #, fuzzy msgid "Delete an artifact from the event." msgstr "Ta bort en artefakt frÃ¥n belöningen." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Välj FörmÃ¥ga:" #, fuzzy msgid "Delete Secondary Skill" msgstr "Välj %{secondary-skill}" msgid "Delete the Secondary Skill from the event." msgstr "" #, fuzzy msgid "No resources will be part of this event." msgstr "Inga resurser kommer att ges som belöning." #, fuzzy msgid "These resources will be a part of the event." msgstr "Inga resurser kommer att ges som belöning." msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" "Om denna checkruta är ifylld sÃ¥ kommer händelsen bara aktiveras en gÃ¥ng. Om " "den inte är ifylld sÃ¥ kommer händelsen aktiveras när de valda spelarna " "kliver i rutan." msgid "%{objects} cannot be placed on water." msgstr "%{objects} kan inte placeras pÃ¥ vatten." msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Den Främsta Artefakten kan endast placeras pÃ¥ grävbar terräng." msgid "%{objects} must be placed on water." msgstr "%{objects} mÃ¥ste placeras pÃ¥ vatten." msgid "Objects cannot be placed outside the map." msgstr "FöremÃ¥l kan inte placeras utanför kartan." msgid "Action objects must be placed on clear tiles." msgstr "HändelseföremÃ¥l mÃ¥ste placeras pÃ¥ fria rutor." msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Är du säker pÃ¥ att du vill Ã¥tervända till Huvudmenyn? Osparade ändringar " "kommer att försvinna." msgid "Editor" msgstr "Redigerare" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Är du säker pÃ¥ att du vill ladda en ny karta? (Osparade ändringar för din " "nuvarande karta kommer försvinna.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Är du säker pÃ¥ att du vill skapa en ny karta? (Osparade ändringar för din " "nuvarande karta kommer försvinna.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "STARTA" msgid "Main Menu" msgstr "Huvudmeny" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Är du säker pÃ¥ att du vill Ã¥tervända till Huvudmenyn? Osparade ändringar " "kommer att försvinna." msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Starta" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Är du säker pÃ¥ att du vill ladda en ny karta? (Osparade ändringar för din " "nuvarande karta kommer försvinna.)" msgid "Create a new map from scratch." msgstr "Skapa en ny blank karta." msgid "New Map" msgstr "Ny Karta" msgid "Load Map" msgstr "Ladda Karta" msgid "Load an existing map." msgstr "Laddar en karta." msgid "Save Map" msgstr "Spara Karta" msgid "Save the current map." msgstr "Spara nuvarande karta." msgid "Quit out of the map editor." msgstr "Lämna kartredigeraren." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Klicka för att gÃ¥ tillbaka till huvudmenyn." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "Skriv in %{object} text" msgid "Set Random Ultimate Artifact Radius" msgstr "Ange slumpad radie för Främsta artefakt" msgid "%{object} has no properties to change." msgstr "%{object} har inga ändringsbara egenskaper." msgid "This artifact" msgstr "Denna artefakten" msgid "The total number of obelisks is %{count}." msgstr "Det totala antalet obelisker är %{count}." msgid "Roads" msgstr "Vägar" msgid "Streams" msgstr "Floder" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "Maximalt %{count} hjältar med samma färg kan placeras pÃ¥ kartan." msgid "Failed to update player information." msgstr "Misslyckades att uppdatera spelarinformation." msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Endast en Slumpad Främsta Artefakt kan placeras pÃ¥ kartan." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "Maximalt %{count} obelisker kan placeras pÃ¥ kartan." msgid "The map is corrupted." msgstr "Kartan är korrupt." msgid "Unable to locate data directory to save the map." msgstr "Kunde inte hitta sökvägen för att spara kartan." msgid "Unable to create a directory to save the map." msgstr "Kunde inte skapa en sökväg för att spara kartan." msgid "Unable to locate a directory to save the map." msgstr "Kunde inte hitta en sökväg för att spara kartan." msgid "Are you sure you want to overwrite the existing map?" msgstr "Är du säker pÃ¥ att du vill skriva över existerande karta?" msgid "Map saved to: " msgstr "Kartan sparades i:" msgid "Failed to save the map." msgstr "Misslyckades att spara kartan." msgid "Used to place %{object}." msgstr "Används för att placera %{object}." msgid "Select object type" msgstr "Välj föremÃ¥lstyp" msgid "" "Click here to\n" "select a monster." msgstr "" "Klicka här för att\n" "välja en varelse." msgid "" "Click here to\n" "select another monster." msgstr "" "Klicka här för att\n" "välja en annan varelse." msgid "" "Cell\n" "Details" msgstr "Rutdetaljer" msgid "Erase" msgstr "Radera" msgid "Mountains" msgstr "Berg" msgid "Rocks" msgstr "Block" msgid "Trees" msgstr "Träd" msgid "Water Objects" msgstr "HavsföremÃ¥l" msgid "Miscellaneous" msgstr "Diverse" msgid "Artifacts" msgstr "Artefakter" msgid "Dwellings" msgstr "Bostäder" msgid "Mines" msgstr "Gruvor" msgid "Power-ups" msgstr "Kraftökningar" msgid "Treasures" msgstr "Skatter" msgid "Heroes" msgstr "Hjältar" msgid "Towns" msgstr "Städer" msgid "editorErasure|Landscape objects" msgstr "LandskapsföremÃ¥l" msgid "editorErasure|Adventure non pickable objects" msgstr "Ej tagbara äventyrsföremÃ¥l" msgid "editorErasure|Castles" msgstr "Slott" msgid "editorErasure|Adventure pickable objects" msgstr "Tagbara äventyrsföremÃ¥l" msgid "editorErasure|Monsters" msgstr "Varelser" msgid "editorErasure|Heroes" msgstr "Hjältar" msgid "editorErasure|Roads" msgstr "Vägar" msgid "editorErasure|Streams" msgstr "Floder" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Ritar terräng i\n" "rutstorlek om %{size} gÃ¥nger %{size}." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Raderar terräng i\n" "rutstorlek om %{size} gÃ¥nger %{size}." msgid "Small Brush" msgstr "Liten Pensel" msgid "Medium Brush" msgstr "Medelstor Pensel" msgid "Large Brush" msgstr "Stor Pensel" msgid "Area Fill" msgstr "Fyll OmrÃ¥de" msgid "Used to click and drag for filling in large areas." msgstr "Används för att klicka och dra för att fylla stora omrÃ¥den." msgid "Clear Area" msgstr "Rensa OmrÃ¥de" msgid "Used to click and drag for clearing large areas." msgstr "Används för att klicka och dra för rensa stora omrÃ¥den." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Kostar %{rate} gÃ¥nger normal förflyttning för alla hjältar. (Vägvisning " "sänker eller tar bort handikappet.)" msgid "Traversable only by boat." msgstr "Endast farbar med skepp." msgid "No special modifiers." msgstr "Ger inget förflyttningsstraff." msgid "Toggle the erasure of %{type} objects." msgstr "Aktivera raderingen av %{type}." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "FöremÃ¥l av denna typ kommer raderas med Raderingsverktyget. Vänsterklicka " "här för att avmarkera denna föremÃ¥lstyp. Tryck och hÃ¥ll denna knapp för att " "avmarkera alla andra föremÃ¥lstyper." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "FöremÃ¥l av denna typ kommer INTE att raderas med Raderingsverktyget. " "Vänsterklicka här för att markera denna föremÃ¥lstyp. Tryck och hÃ¥ll denna " "knapp för att markera alla andra föremÃ¥lsyper." msgid "Terrain Mode" msgstr "Terrängläge" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "Används för att rita terrängen sÃ¥ som gräs, jord, hav osv pÃ¥ kartan." msgid "Landscape Objects Mode" msgstr "LandskapsföremÃ¥lsläge" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "Används för att placera landskapsföremÃ¥l (berg, block, träd osv) pÃ¥ kartan." msgid "Detail Mode" msgstr "Detaljläge" msgid "Used for special editing of action objects." msgstr "Används för särskild redigering av händelseföremÃ¥l." msgid "Adventure Objects Mode" msgstr "ÄventyrsföremÃ¥lsläge" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "Används för att placera äventyrsföremÃ¥l (artefakter, boningar, gruvor, " "skatter osv) pÃ¥ kartan." msgid "Kingdom Objects Mode" msgstr "RikesföremÃ¥lsläge" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "Används för att placera RikesföremÃ¥l (städer, borgar och hjältar) pÃ¥ kartan." msgid "Monsters Mode" msgstr "Varelseläge" msgid "Used to place monsters on the map." msgstr "Används för att placera varelser pÃ¥ kartan." msgid "Allows you to draw streams by clicking and dragging." msgstr "Används för att dra floder genom att klicka och dra." msgid "Stream Mode" msgstr "Flodläge" msgid "Allows you to draw roads by clicking and dragging." msgstr "Används för att dra vägar genom att klicka och dra." msgid "Road Mode" msgstr "Vägläge" msgid "Erase Mode" msgstr "Raderarläge" msgid "Used to erase objects from the map." msgstr "Används för att radera föremÃ¥l frÃ¥n kartan." msgid "Change between zoom and normal view." msgstr "Ändra mellan förstorad vy eller normal vy." msgid "Magnify" msgstr "Förstora" msgid "Undo" msgstr "Ã…ngra" msgid "Undo your last action." msgstr "Ã…ngra din sista Ã¥tgärd." msgid "Redo" msgstr "Gör om" msgid "Redo the last undone action." msgstr "Gör om senaste Ã¥tgärden." msgid "Edit map title, description, and other general information." msgstr "Redigera karttiteln, beskrivning och annan information." msgid "Specifications" msgstr "Specifikationer" msgid "File Options" msgstr "Filalternativ" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Tar fram filalternativsmenyn som lÃ¥ter dig spara eller ladda kartor eller " "lämna kartredigeraren." msgid "View the editor system options, which let you customize the editor." msgstr "" "Tar fram systemalternativsmenyn som lÃ¥ter dig skräddarsy kartredigeraren." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Skapa en karta som är %{size} rutor bred och %{size} rutor hög." msgid "Cancel back to the New Map menu." msgstr "Avbryt och gÃ¥ tillbaka till Ny Karta-menyn." msgid "Cancel back to the main menu." msgstr "Avbryt och gÃ¥ tillbaka till huvudmenyn." msgid "From Scratch" msgstr "Blank karta" msgid "Start from scratch with a blank map." msgstr "Starta med en blank karta." msgid "Create a randomly generated map." msgstr "Skapa en slumpmässigt genererad karta." msgid "Random" msgstr "Slumpad" msgid "Cancel back to the Map Editor main menu." msgstr "Avbryt och gÃ¥ tillbaka till kartredigerarens huvudmeny." msgid "No maps available!" msgstr "Inga kartor tillgängliga!" msgid "[%{pos}]: %{race} hero" msgstr "[%{pos}]: %{race}hjälte" msgid "[%{pos}]: %{name}, %{race} hero" msgstr "[%{pos}]: %{name}, %{race}hjälte" msgid "[%{pos}]: %{race} town" msgstr "[%{pos}]: %{race}stad" msgid "[%{pos}]: %{race} castle" msgstr "[%{pos}]: %{race}borg" msgid "[%{pos}]: %{name}, %{race} town" msgstr "[%{pos}]: %{name}, %{race}stad" msgid "[%{pos}]: %{name}, %{race} castle" msgstr "[%{pos}]: %{name}, %{race}borg" msgid "None." msgstr "Inga." msgid "One side defeats another." msgstr "En sida besegrar den andra." msgid "Accumulate gold." msgstr "Samla ihop guld." msgid "Run out of time." msgstr "FÃ¥ slut pÃ¥ tid." msgid "alliance|1st" msgstr "1:a" msgid "alliance|2nd" msgstr "2:a" msgid "alliance|3rd" msgstr "3:e" msgid "alliance|4th" msgstr "4:e" msgid "alliance|5th" msgstr "5:e" msgid "Special Loss Condition" msgstr "Särskilt Förlustvillkor" msgid "Special Victory Condition" msgstr "Särskilt Segervillkor" msgid "Allow standard victory conditions" msgstr "TillÃ¥t standardsegervillkor" msgid "Allow this condition also for AI" msgstr "TillÃ¥t detta villkor även för Datorn" msgid "Set alliances:" msgstr "Ange allianser:" msgid "{%number} alliance: " msgstr "{%number} allians: " msgid "Gold:" msgstr "Guld:" msgid "Select a Town to capture to achieve victory" msgstr "Välj en Stad att inta för att uppnÃ¥ seger" msgid "Click here to change the town needed to capture to achieve victory." msgstr "Klicka för att ändra Staden som mÃ¥ste intas för att uppnÃ¥ seger." msgid "Select a Hero to defeat to achieve victory" msgstr "Välj en Hjälte att besegra för att uppnÃ¥ seger" msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Klicka för att ändra Hjälten som mÃ¥ste besegras för att uppnÃ¥ seger." msgid "Put %{color} player in the %{alliance} alliance" msgstr "Lägg till %{color} spelare i %{alliance} allians." msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" "Om denna ruta är ifylld sÃ¥ kommer %{color} spelare vara med i %{alliance} " "allians." msgid "Days:" msgstr "Dagar:" msgid "Select a Town to lose to suffer defeat" msgstr "Välj en Stad att besegras för att förlora" msgid "Click here to change the town whose loss would mean defeat." msgstr "Klicka för att ändra Staden vars besegring innebär förlust." msgid "Select a Hero to lose to suffer defeat" msgstr "Välj en Hjälte att besegras för att förlora" msgid "Click here to change the hero whose loss would mean defeat." msgstr "Klicka för att ändra Hjälten vars besegring innebär förlust." msgid "Map Difficulty" msgstr "KartsvÃ¥righet" msgid "Map Description" msgstr "Kartbeskrivning" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" "Kartans beskrivning överstiger högsta tillÃ¥tna 5 rader. Beskrivningen kommer " "att nedkortas för att fÃ¥ plats i beskrivningsfältet." msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" "Du tänker ändra kartans sprÃ¥k frÃ¥n %{oldLanguage} till %{newLanguage}. En " "del texter kan eventuellt inte visas korrekt efter detta. Vill du " "fortfarande ändra sprÃ¥k?" msgid "Change Map Name" msgstr "Ändra Kartnamn" msgid "Change Map Description" msgstr "Ändra Kartbeskrivning" msgid "Click to accept the changes made." msgstr "Klicka för att acceptera ändringarna." msgid "Click to edit custom rumors." msgstr "Klicka för att redigera anpassade rykten." msgid "Rumors" msgstr "Rykten" msgid "Click to edit daily events." msgstr "Klicka för att redigera dagliga händelser." msgid "Events" msgstr "Händelser" msgid "Click to change the language of the map." msgstr "Klicka för att ändra kartans sprÃ¥k." msgid "Click to change your map name." msgstr "Klicka för att ändra kartans namn." msgid "Map Name" msgstr "Kartnamn" msgid "Click to change the description of the current map." msgstr "Klicka för att ändra nuvarande kartans beskrivning." msgid "Click to change the victory condition of the current map." msgstr "Klicka för att ändra segervillkor för nuvarande karta." msgid "Click to change the loss condition of the current map." msgstr "Klicka för att ändra förlustvillkor för nuvarande karta." msgid "Indicates the player types in the scenario. Click to change." msgstr "Visar spelartyperna i scenariot. Tryck för att ändra." msgid "Player Type" msgstr "Spelartyp" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Klicka för att ange kartsvÃ¥righet. SvÃ¥rare kartor kan inkludera fler och " "svÃ¥rare fiender, färre resurser eller andra särskilda villkor som gör det " "svÃ¥rare för en mänsklig spelare." msgid "editor|%{count} %{resource}" msgstr "%{count} %{resource}" msgid "Animation" msgstr "Animering" msgid "Passability" msgstr "" "Framkomlig-\n" "het" msgid "Toggle animation of the objects." msgstr "Aktivera animationen för föremÃ¥len." msgid "Toggle display of objects' passability." msgstr "Visa föremÃ¥lens framkomlighet." msgid "Rumor:" msgstr "Rykte:" msgid "Rumor" msgstr "Rykte" msgid "This rumor already exists in the list." msgstr "Detta rykte finns redan i listan." msgid "Click to save the rumors." msgstr "Klicka för att spara ryktena." msgid "Add Rumor" msgstr "Lägg till Rykte" msgid "Add an additional rumor." msgstr "Lägg till ett ytterligare rykte." msgid "Edit Rumor" msgstr "Redigera Rykte" msgid "Edit an existing rumor." msgstr "Redigera ett existerande rykte." msgid "Delete Rumor" msgstr "Radera Rykte" msgid "Delete an existing rumor." msgstr "Radera ett existerande rykte." msgid "" "\n" "\n" "Size: " msgstr "" "\n" "\n" "Storlek: " msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Beskrivning: " msgid "Save Map:" msgstr "Spara Karta:" msgid "Click to save the current map." msgstr "Klicka för att spara nuvarande karta." msgid "Riddle:" msgstr "GÃ¥ta:" msgid "Answers:" msgstr "Svar:" msgid "Answer:" msgstr "Svar:" msgid "Answer" msgstr "Svar" msgid "This answer exists in the list." msgstr "Detta svar finns i listan." msgid "Click to save the Sphinx properties." msgstr "Klicka för att spara Sphinxens egenskaper." msgid "Add Answer" msgstr "Lägg till Svar" msgid "Add an additional answer for the question." msgstr "Lägg till ett ytterligare svar för gÃ¥tan." msgid "Edit Answer" msgstr "Redigera Svar" msgid "Edit an existing answer for the question." msgstr "Redigera ett redan existerande svar till gÃ¥tan." msgid "Delete Answer" msgstr "Radera Svar" msgid "Delete an existing answer for the question." msgstr "Radera ett redan existerande svar till frÃ¥gan." msgid "No artifact will be given as a reward." msgstr "Ingen artefakt kommer att ges som belöning." msgid "Delete an artifact from the reward." msgstr "Ta bort en artefakt frÃ¥n belöningen." msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "Dag: %{day} Vecka: %{week} MÃ¥nad: %{month}" msgid "difficulty|Easy" msgstr "Lätt" msgid "difficulty|Normal" msgstr "Normal" msgid "difficulty|Hard" msgstr "SvÃ¥r" msgid "difficulty|Expert" msgstr "Professionell" msgid "difficulty|Impossible" msgstr "Omöjligt" msgid "and more..." msgstr "och mer..." msgid "Easy" msgstr "Lätt" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "SvÃ¥r" msgid "Campaign Difficulty" msgstr "KampanjsvÃ¥righet" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Välj denna svÃ¥righetsgrad om du föredrar att följa historien framför " "utmaningen. Datorn är svagare i jämförelse med normal svÃ¥righetsgrad." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Välj denna svÃ¥righetsgrad för att uppleva kampanjen som den ursprungligen är " "tänkt att upplevas." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Välj denna svÃ¥righetsgrad om du vill ha en utmaning. Datorn är starkare i " "jämförelse med normal svÃ¥righetsgrad." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Gratulerar!\n" "\n" "Dagar: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "SvÃ¥righetsgrad: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Poängställning: %{score}\n" "\n" "Rang:\n" "%{rating}" msgid "Start the selected scenario." msgstr "PÃ¥börja valt scenarie." msgid "View Intro" msgstr "Visa Intro" msgid "View the intro video for the current state of the campaign." msgstr "Visa introduktionsvideon för nuvarande kampanjscenarie." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Välj kampanjsvÃ¥righet. SvÃ¥righetsgraden kan sänkas senare under kampanjen." msgid "Restart the current scenario." msgstr "Omstarta nuvarande scenarie." msgid "Difficulty" msgstr "SvÃ¥righetsgrad" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Du har sänkt svÃ¥righetsgraden för kampanjen. Du kan inte ändra tillbaka " "senare. Poängställningen kommer enbart beräknas med den nya " "svÃ¥righetsgraden. Vill du fortsätta?" msgid "Are you sure you want to restart this scenario?" msgstr "Är du säker pÃ¥ att du vill omstarta detta scernaiot?" msgid "Campaign Scenario loading failure" msgstr "Ladda Kampanjscenariet misslyckades" msgid "Please make sure that campaign files are correct and present." msgstr "Kolla om Kampanjfilerna finns och är korrekta." msgid "Days spent" msgstr "GÃ¥ngna dagar" msgid "The number of days spent on this campaign." msgstr "Antal gÃ¥ngna dagar för denna kampanj." msgid "Project Coordination and Core Development" msgstr "Projektkoordination och huvudutveckling" msgid "Development" msgstr "Utveckling" msgid "Visit us at " msgstr "Besök oss pÃ¥ " msgid "QA and Support" msgstr "Kvalitétssäkring och Support" msgid "Dev and Support" msgstr "Utveckling och Support" msgid "Special Thanks to" msgstr "Extra Tack till" msgid "and many-many other contributors and supporters!" msgstr "och mÃ¥nga mÃ¥nga andra som gett sitt stöd!" msgid "Support us at" msgstr "Stöd oss pÃ¥" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Kontakta oss pÃ¥" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Behöver du hjälp med spelet?" msgid "Original project before 0.7" msgstr "Orginalprojekt före version 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Heroes of Might and Magic II: The Succession Wars teamet" msgid "Designed and Directed" msgstr "Design och Regi" msgid "Programming and Design" msgstr "Programmering och Formgivning" msgid "Executive Producer" msgstr "Chefsproducent" msgid "Producer" msgstr "Producent" msgid "Additional Design" msgstr "Övrig Formgivning" msgid "Additional Programming" msgstr "Övrig Programmering" msgid "Musical Production" msgstr "Musikproduktion" msgid "Music and Sound Design" msgstr "Musik och Ljuddesign" msgid "Vocalists" msgstr "Vocalister" msgid "Art Director" msgstr "Konstnärlig Ledare" msgid "Assistant Art Director" msgstr "Assisterande Konstnärlig Ledare" msgid "Artists" msgstr "Artister" msgid "QA Manager" msgstr "Koordinator för Kvalitétsäkring" msgid "QA" msgstr "Kvalitétsäkrare" msgid "Writing" msgstr "Manus" msgid "Manual and Helpfile" msgstr "Manual och Hjälpfil" msgid "Scenarios" msgstr "Scenarier" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Heroes of Might and Magic II: The Price of Loyalty teamet" msgid "Design Lead" msgstr "Huvuddesigner" msgid "Designers" msgstr "Formgivare" msgid "Programming Lead" msgstr "Huvudprogrammerare" msgid "Art Lead" msgstr "Grafisk Huvudformgivare" msgid "Playtesters" msgstr "Testspelare" msgid "Designer" msgstr "Formgivare" msgid "Producers" msgstr "Producenter" msgid "QA Managers" msgstr "Koordinatorer för Kvalitétsäkring" msgid "Sound Design" msgstr "Ljuddesign" msgid "Town Themes" msgstr "Stadsteman" msgid "Alto Sax" msgstr "Altsaxofon" msgid "Harpsichord and Piano" msgstr "Cembalo och Piano" msgid "Basso Vocal" msgstr "Basstämma" msgid "Soprano Vocal" msgstr "Sopranstämma" msgid "Recorded at %{recordingStudio}" msgstr "Inspelat i %{recordingStudio}" msgid "credits|Manual" msgstr "Manual" msgid "German Consultant" msgstr "Tyskkonsult" msgid "Map Designers" msgstr "Kartkreatörer" msgid "Package Design" msgstr "Paketdesign" msgid "High Scores" msgstr "Poänglistan" msgid "Your Name" msgstr "Ditt Namn" msgid "Unknown Hero" msgstr "Okänd Hjälte" msgid "Standard" msgstr "Standardspel" msgid "View High Scores for Standard Maps." msgstr "Visa Poänglistan för standardkartor." msgid "Campaign" msgstr "Kampanjspel" msgid "View High Scores for Campaigns." msgstr "Visa Poänglistan för kampanjer." msgid "hotkey|default okay event" msgstr "Standardhändelse: Okej" msgid "hotkey|default cancel event" msgstr "Standardhändelse: Avbryt" msgid "hotkey|default left" msgstr "Standard: Vänster" msgid "hotkey|default right" msgstr "Standard: Höger" msgid "hotkey|default up" msgstr "Standard: Upp" msgid "hotkey|default down" msgstr "Standard: Ner" msgid "hotkey|toggle fullscreen" msgstr "Visa fullskärm" msgid "hotkey|toggle text support mode" msgstr "Aktivera textstöd" msgid "hotkey|toggle developer mode" msgstr "Aktivera utvecklarläge" msgid "hotkey|new game" msgstr "Nytt spel" msgid "hotkey|load game" msgstr "Ladda spel" msgid "hotkey|high scores" msgstr "Poänglista" msgid "hotkey|credits" msgstr "Credits" msgid "hotkey|standard game" msgstr "Standardspel" msgid "hotkey|campaign game" msgstr "Kampanjspel" msgid "hotkey|multi-player game" msgstr "Flerspelarspel" msgid "hotkey|settings" msgstr "Inställningar" msgid "hotkey|quit" msgstr "Avsluta" msgid "hotkey|select map" msgstr "Välj karta" msgid "hotkey|select small map size" msgstr "Välj liten kartstorlek" msgid "hotkey|select medium map size" msgstr "Välj medel kartstorlek" msgid "hotkey|select large map size" msgstr "Välj stor kartstorlek" msgid "hotkey|select extra large map size" msgstr "Välj extra stor kartstorlek" msgid "hotkey|select all map sizes" msgstr "Välj alla kartstorlekar" msgid "hotkey|hot seat game" msgstr "Heta stolen" msgid "hotkey|battle only game" msgstr "Endast strid" msgid "hotkey|choose the original campaign" msgstr "Välj orginalkampanj" msgid "hotkey|choose the expansion campaign" msgstr "Välj expansionskampanj" msgid "hotkey|map editor main menu" msgstr "Kartredigerarens huvudmeny" msgid "hotkey|new map menu" msgstr "Nytt karta" msgid "hotkey|load map menu" msgstr "Ladda karta" msgid "hotkey|new map from scratch" msgstr "Ny blank karta" msgid "hotkey|new random map" msgstr "Ny slumpad karta" msgid "hotkey|undo last action" msgstr "Ã…ngra senaste Ã¥tgärden" msgid "hotkey|redo last action" msgstr "Gör om senaste Ã¥tgärden" msgid "hotkey|open game main menu" msgstr "öppna spelets huvudmeny" msgid "hotkey|toggle passability" msgstr "Aktivera framkomlighet" msgid "hotkey|roland campaign" msgstr "Rolands kampanj" msgid "hotkey|archibald campaign" msgstr "Archibalds kampanj" msgid "hotkey|price of loyalty campaign" msgstr "Lojalitetens pris-kampanj" msgid "hotkey|voyage home campaign" msgstr "Hemresekampanjen" msgid "hotkey|wizard's isle campaign" msgstr "Trollkarlsöarnakampanjen" msgid "hotkey|descendants campaign" msgstr "Ättlingarnas Kampanj" msgid "hotkey|select first campaign bonus" msgstr "Välj första kampanjbonusen" msgid "hotkey|select second campaign bonus" msgstr "Välj andra kampanjbonusen" msgid "hotkey|select third campaign bonus" msgstr "Välj tredje kampanjbonusen" msgid "hotkey|view campaign intro" msgstr "Visa kampanjintro" msgid "hotkey|select campaign difficulty" msgstr "Välj kampanjsvÃ¥righet" msgid "hotkey|restart campaign scenario" msgstr "Omstarta kampanjscenarie" msgid "hotkey|world map left" msgstr "Kartvy: Väster" msgid "hotkey|world map right" msgstr "Kartvy: Öster" msgid "hotkey|world map up" msgstr "Kartvy: Norr" msgid "hotkey|world map down" msgstr "Kartvy: Söder" msgid "hotkey|world map up left" msgstr "Kartvy: Nordväst" msgid "hotkey|world map up right" msgstr "Kartvy: Nordost" msgid "hotkey|world map down left" msgstr "Kartvy: Sydväst" msgid "hotkey|world map down right" msgstr "Kartvy: Sydost" msgid "hotkey|save game" msgstr "Spara spel" msgid "hotkey|next hero" msgstr "Nästa hjälte" msgid "hotkey|change to hero under cursor" msgstr "Byt till hjälte under muspekaren" msgid "hotkey|start hero movement" msgstr "PÃ¥börja hjälteförflyttning" msgid "hotkey|cast adventure spell" msgstr "Kasta en kartbesvärjelse." msgid "hotkey|put hero to sleep" msgstr "Söv hjälte" msgid "hotkey|next town" msgstr "Nästa stad" msgid "hotkey|end turn" msgstr "Avsluta runda" msgid "hotkey|file options" msgstr "Filalternativ" msgid "hotkey|adventure options" msgstr "Äventyrsinställningar" msgid "hotkey|puzzle map" msgstr "Pusselkarta" msgid "hotkey|scenario information" msgstr "Scenarioinformation" msgid "hotkey|dig for artifact" msgstr "Gräv efter artefakt" msgid "hotkey|view world" msgstr "Visa kartvy" msgid "hotkey|kingdom summary" msgstr "Rikessammanfattning" msgid "hotkey|default action" msgstr "StandardÃ¥tgärd" msgid "hotkey|open focus" msgstr "Öppna markerat" msgid "hotkey|system options" msgstr "Systeminställningar" msgid "hotkey|scroll left" msgstr "Skrolla vänster" msgid "hotkey|scroll right" msgstr "Skrolla höger" msgid "hotkey|scroll up" msgstr "Skrolla upp" msgid "hotkey|scroll down" msgstr "Skrolla ner" msgid "hotkey|toggle control panel" msgstr "Aktivera kontrollpanel" msgid "hotkey|toggle radar" msgstr "Aktivera radar" msgid "hotkey|toggle buttons" msgstr "Aktivera knappar" msgid "hotkey|toggle status" msgstr "Aktivera status" msgid "hotkey|toggle icons" msgstr "Aktivera ikoner" msgid "hotkey|transfer control to ai" msgstr "Överför kontrollen till datorn" msgid "hotkey|retreat from battle" msgstr "Retirera frÃ¥n strid" msgid "hotkey|surrender during battle" msgstr "Kapitulera under strid" msgid "hotkey|toggle auto combat mode" msgstr "Aktivera Automatiskt Stridsläge" msgid "hotkey|quick combat" msgstr "Snabbstrid" msgid "hotkey|battle options" msgstr "Stridsalternativ" msgid "hotkey|skip turn in battle" msgstr "Hoppa över runda i strid" msgid "hotkey|cast battle spell" msgstr "Kasta stridsbesvärjelse" msgid "hotkey|dwelling level 1" msgstr "Bostad, nivÃ¥ 1" msgid "hotkey|dwelling level 2" msgstr "Bostad, nivÃ¥ 2" msgid "hotkey|dwelling level 3" msgstr "Bostad, nivÃ¥ 3" msgid "hotkey|dwelling level 4" msgstr "Bostad, nivÃ¥ 4" msgid "hotkey|dwelling level 5" msgstr "Bostad, nivÃ¥ 5" msgid "hotkey|dwelling level 6" msgstr "Bostad, nivÃ¥ 6" msgid "hotkey|well" msgstr "Brunn" msgid "hotkey|marketplace" msgstr "Marknad" msgid "hotkey|mage guild" msgstr "Magisamfund" msgid "hotkey|shipyard" msgstr "Skeppsvarv" msgid "hotkey|thieves guild" msgstr "Tjuvgille" msgid "hotkey|tavern" msgstr "Värdshus" msgid "hotkey|construction screen" msgstr "Byggvy" msgid "hotkey|buy all monsters in well" msgstr "Rekrytera alla varelser i brunnen" msgid "hotkey|split stack by half" msgstr "Dela truppen till hälften" msgid "hotkey|split stack by one" msgstr "Dela truppen med ett" msgid "hotkey|join stacks" msgstr "Anslut trupper" msgid "hotkey|upgrade troop" msgstr "Uppgradera trupp" msgid "hotkey|dismiss hero or troop" msgstr "Avskeda hjälte eller varelse" msgid "hotkey|exchange all troops" msgstr "Växla alla enheter" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Vill du Ã¥terta kontrollen frÃ¥n AI:n? Denna effekt gäller bara under nästa " "runda." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Vill du ge datorn kontrollen? Denna effekt gäller bara för nästa runda." msgid "Default Actions" msgstr "StandardÃ¥tgärder" msgid "Global Actions" msgstr "Globala Ã…tgärder" msgid "World Map" msgstr "Världskarta" msgid "Battle Screen" msgstr "Stridsvy" msgid "Town Screen" msgstr "Stadsvy" msgid "Army Actions" msgstr "Arméåtgärder" msgid "The save file is corrupted." msgstr "Sparfilen är korrupt." msgid "Unsupported save format: " msgstr "Ostödda sparfilsformat: " msgid "Current game version: " msgstr "Nuvarande spelversion: " msgid "Last supported version: " msgstr "Senast stödda version: " msgid "This file contains a save with an invalid game type." msgstr "Denna fil innehÃ¥ller en sparning med en ogiltig speltyp." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Denna sparfil kräver \"The Price of Loyalty\"s speltillgÃ¥ngar, men de har " "inte tillhandahÃ¥llits till spelmotorn." msgid "This saved game is localized to '" msgstr "Denna spelomgÃ¥ng är översatt till '" msgid "' language, but the current language of the game is '" msgstr "' men nuvarande spelsprÃ¥k är " msgid "No save files to load." msgstr "Inga sparfiler att ladda." msgid "Hot Seat" msgstr "Heta stolen" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Spela Heta stolen, där 2 till 6 spelare spelar pÃ¥ samma dator och sätter sig " "i den 'Heta stolen' när det är sin tur." msgid "A single player game playing out a single map." msgstr "En ensam spelare gÃ¥r igenom en karta." msgid "Standard Game" msgstr "Standardspel" msgid "A single player game playing through a series of maps." msgstr "En ensam spelare gÃ¥r igenom en serie kartor." msgid "Campaign Game" msgstr "Kampanjspel" msgid "Multi-Player Game" msgstr "Flerspelarläge" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Ett spel med flera spelare, där flera mänskliga spelare som tävlar mot " "varandra pÃ¥ en karta." msgid "fheroes2 Resurrection Team presents" msgstr "fheroes2 Resurrection Team presenterar" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "Välkommen till Heroes of Might and Magic II genom fheroes2 spelmotor!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" "\n" "\n" "För att simulera högerklick med en pekskärm för att fÃ¥ information om olika " "objekt sÃ¥ mÃ¥ste du först peka och hÃ¥lla inne fingret pÃ¥ objektet för att " "sedan peka nÃ¥gon annanstans pÃ¥ pekskärmen. Medan du hÃ¥ller ditt andra finger " "pÃ¥ pekskärmen sÃ¥ kan du släppa ditt första finger frÃ¥n skärmen för att " "fortsätta se informationen om objektet." msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "\n" "\n" "Välj spelupplösning innan du börjar spelet." msgid "Greetings!" msgstr "Var Hälsad!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "Avsluta Heroes of Might and Magic II och Ã¥tergÃ¥ till operativsystemet." msgid "Credits" msgstr "Tack till" msgid "View the credits screen." msgstr "Visa \"Tack till\"-skärmen." msgid "View the high scores screen." msgstr "Visa Poänglistan." msgid "Create new or modify existing maps." msgstr "Skapa nya eller redigera existerande kartor." msgid "Change language, resolution and settings of the game." msgstr "Ändra spelets sprÃ¥k, upplösning och inställningar." msgid "Game Settings" msgstr "Spelinställningar" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "Videofilmerna som krävs för kampanjmenyn saknas. Kontrollera att samtliga " "nödvändiga filer finns i systemet." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Antingen Rolands eller Archibalds kampanj frÃ¥n original Heroes of Might and " "Magic II." msgid "Original Campaign" msgstr "Orginalkampanj" msgid "Expansion Campaign" msgstr "Expansionskampanj" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "En av de fyra nya kampanjer frÃ¥n Lojalitetens Pris expansionen." msgid "Loading video. Please wait..." msgstr "Laddar film. Vänta..." msgid "Host" msgstr "Värd" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Värden anger spelinställningarna. Det kan endast finnas en värd per " "nätverksspel." msgid "Guest" msgstr "Gäst" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "Gästen väntar pÃ¥ att värden ska sätta igÃ¥ng spelet, sen läggs till " "automatiskt. Det kan finnas flera gäster för TCP/IP-spel." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "fheroes2 behöver datafiler frÃ¥n originalspelet Heroes of Might and Magic II " "för att fungera. Du verkar använda dig av demoversionen av Heroes of Might " "and Magic II för detta, vilket innebär att endast ett scenarie kommer vara " "tillgängligt." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Ett spel med flera spelare, där flera mänskliga spelare som tävlar mot " "varandra pÃ¥ en karta." msgid "Battle Only" msgstr "Endast Strid" msgid "Setup and play a battle without loading any map." msgstr "Konfigurera och spela en strid utan nÃ¥gon karta." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Spela Heta stolen, där 2 till 6 spelare spelar pÃ¥ samma dator och sätter sig " "pÃ¥ den 'Heta stolen' när det är dennes tur." msgid "2 Players" msgstr "2 Spelare" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Spela med 2 mänskliga spelare, och eventuellt upp till 4 datorstyrda spelare." msgid "3 Players" msgstr "3 Spelare" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Spela med 3 mänskliga spelare, och eventuellt upp till 3 datorstyrda spelare." msgid "4 Players" msgstr "4 Spelare" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Spela med 4 mänskliga spelare, och eventuellt upp till 2 datorstyrda spelare." msgid "5 Players" msgstr "5 Spelare" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Spela med 5 mänskliga spelare, och eventuellt med 1 datorstyrd spelare." msgid "6 Players" msgstr "6 Spelare" msgid "Play with 6 human players." msgstr "Spela med 6 mänskliga spelare." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Drakstaden har fallit! Du är nu Drakmästaren." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Du fÃ¥ngade %{name}!\n" "Du segrar." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Du har fÃ¥ngat fiendehjälten %{name}!\n" "Ditt uppdrag är slutfört." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Du har hittat %{name}.\n" "Ditt uppdrag är slufört." msgid "Ultimate Artifact" msgstr "Den Främsta Artefakten" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Fienden är besegrad.\n" "Din sida segrar!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Du har byggt upp en förmögenhet pÃ¥ över %{count} i din skattkammare.\n" "Alla fiender bugar inför din rikedom och makt." msgid "Victory!" msgstr "Seger!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Fienden har tillfÃ¥ngatagit %{name}!\n" "Dem jublar." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Fienden har byggt upp en förmögenhet pÃ¥ över %{count} guld i sin " "skattkammare.\n" "Du mÃ¥ste buga i förlust inför deras rikedom och makt." msgid "You have been eliminated from the game!!!" msgstr "Du har blivit eliminerad frÃ¥n spelet!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Du har förlorat hjälten %{name}.\n" "Ditt uppdrag är över." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Du har misslyckats att slutföra ditt uppdrag i tid.\n" "Allting är förlorat." msgid "Defeat!" msgstr "Nederlag!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Grundpoängställning: %{score}\n" "SvÃ¥righetsgrad: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "Besegra alla fiendehjältar och inta alla fiendestäder och borgar." msgid "Your side defeats the opposing side." msgstr "Din sida besegrar motstÃ¥ndarsidan." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "FÃ¥ slut pÃ¥ tid. (Misslyckas att vinna vid en bestämd punkt.)" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Du mÃ¥ste besegra fienden %{enemies}." msgstr[1] "Du mÃ¥ste besegra fienderna %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Alliansen bestÃ¥r av %{allies} and du mÃ¥ste besegra fienden %{enemies}." msgstr[1] "" "Alliansen bestÃ¥r av %{allies} and du mÃ¥ste besegra fiendepakten som bestÃ¥r " "av %{enemies}." msgid "Capture the castle '%{name}'." msgstr "Erövra borgen '%{name}'." msgid "Capture the town '%{name}'." msgstr "Erövra staden '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Besegra hjälten '%{name}'." msgid "Find the ultimate artifact." msgstr "Hitta den Främsta Artefakten." msgid "Find the '%{name}' artifact." msgstr "Hitta artefakten '%{name}'." msgid "Accumulate %{count} gold." msgstr "Samla ihop %{count} guld." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", eller sÃ¥ kan du vinna genom att besegra alla fiendehjältar och inta alla " "fiendestäder och borgar." msgid "Lose the castle '%{name}'." msgstr "Förlora borgen '%{name}'." msgid "Lose the town '%{name}'." msgstr "Förlora staden '%{name}'." msgid "Lose the hero: %{name}." msgstr "Förlora hjälten: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Misslyckas att vinna vid slutet av mÃ¥naden %{month}, vecka %{week}, dag " "%{day}." msgid "%{color} player has been vanquished!" msgstr "%{color} har blivit besegrad!" msgid "Major Event!" msgstr "Stor Händelse!" msgid "Scenario:" msgstr "Scenario:" msgid "Game Difficulty:" msgstr "SpelsvÃ¥righet:" msgid "Opponents:" msgstr "MotstÃ¥ndare:" msgid "Class:" msgstr "Klass:" msgid "Rating %{rating}%" msgstr "Ranking %{rating}%" msgid "Click here to select which scenario to play." msgstr "Klicka här för att välja vilket scenarie som ska spelas." msgid "Scenario" msgstr "Scenario" msgid "Game Difficulty" msgstr "SpelsvÃ¥righet" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "LÃ¥ter dig ändra svÃ¥righetsgraden för spelet. Vid högre svÃ¥righetsgrad sÃ¥ " "startar du med färre resurser och vid ännu svÃ¥rare sÃ¥ fÃ¥r datorn mer " "resurser." msgid "Difficulty Rating" msgstr "SvÃ¥righetsgrad" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "SvÃ¥righetsgraden reflekterar en kombination av blandande inställningar för " "ditt spel. Denna siffra kommer att multipliceras till i dina slutpoäng." msgid "Click to accept these settings and start a new game." msgstr "Klicka för att acceptera dessa inställningar och starta ett nytt spel." msgid "Click to return to the main menu." msgstr "Klicka för att gÃ¥ tillbaka till huvudmenyn." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Astrologerna utropar %{name} mÃ¥nad." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Astrologerna utropar %{name} vecka." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "Efter en vanlig ökning har bestÃ¥ndet av %{monster} fördubblats!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Efter en vanlig ökning har bestÃ¥ndet av %{monster} ökat med %{count} procent!" msgstr[1] "" "Efter en vanlig ökning har bestÃ¥ndet av %{monster} ökat med %{count} procent!" msgid "%{monster} growth +%{count}." msgstr "Populationen av %{monster} ökar med +%{count}." msgid " All populations are halved." msgstr " Alla populationer är halverade." msgid " All dwellings increase population." msgstr " Alla boningar ökar sin population." msgid "New Month!" msgstr "Ny MÃ¥nad!" msgid "New Week!" msgstr "Ny Vecka!" msgid "Beware!" msgstr "Varsko!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} spelare, detta är din sista dag att erövra en stad, annars kommer " "du att bannlysas frÃ¥n detta land." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} spelare, du har %{day} dagar kvar att erövra en stad. Annars kommer " "du att bli bannlyst frÃ¥n detta land." msgid "%{color} player's turn." msgstr "%{color} spelares tur." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} spelare, du har förlorat din sista stad. Om du inte erövrar en stad " "nästa vecka sÃ¥ kommer du att bli eliminerad." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} spelare, dina hjältar överger dig och du utvisas frÃ¥n detta land." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Gallanth" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "Nästa Hjälte" msgid "Select the next Hero." msgstr "Välj nästa Hjälte." msgid "Hero Movement" msgstr "Hjälteförflyttning" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "PÃ¥börja Hjältens förflyttning längs den givna vägsträckan eller Ã¥terbesök " "ett föremÃ¥l som Hjälten stÃ¥r vid. Tryck och hÃ¥ll denna knapp för att " "Ã¥terställa Hjältens vägsträckning." msgid "Kingdom Summary" msgstr "Rikessammanfattning" msgid "View a summary of your Kingdom." msgstr "Visa en sammanfattning av ditt Rike." msgid "Cast an adventure spell." msgstr "Kasta en kartbesvärjelse." msgid "End Turn" msgstr "Avsluta Runda" msgid "End your turn and let the computer take its turn." msgstr "Avsluta din runda och lÃ¥t datorn göra sin runda." msgid "Adventure Options" msgstr "Äventyrsinställningar" msgid "Bring up the adventure options menu." msgstr "Visar menyn för äventyrinställningar." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Tar fram filalternativsmenyn som lÃ¥ter dig ladda, spara, starta ett nytt " "spel eller avsluta." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Tar fram systemalternativsmenyn som lÃ¥ter dig skräddarsy ditt spelande." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "En eller flera hjältar kan fortfarande flytta sig. Är du säker pÃ¥ att du " "vill avsluta din runda?" msgid "Are you sure you want to quit?" msgstr "Är du säker pÃ¥ att du vill avsluta?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Är du säker pÃ¥ att du vill starta om? (Ditt nuvarande spel kommer att " "förloras.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Är du säker pÃ¥ att du vill skriva över sparningen med detta namn?" msgid "Game saved successfully." msgstr "Sparning lyckades." msgid "There was an issue during saving." msgstr "Det uppstod ett problem under sparningen." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Är du säker pÃ¥ att du vill ladda ett nytt spel? (Ditt nuvarande spel kommer " "att försvinna.)" msgid "Try looking on land!!!" msgstr "Försök att titta pÃ¥ land!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Letandet efter den Främsta Artefakten är fruktlöst. Din hjälte kan inte ta " "en ens om hjälten fann den - hjältens packning är full." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Att gräva efter artefakter tar en hel dag. Försök igen imorgon." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" "Efter att ha spenderat mÃ¥nga timmar pÃ¥ att gräva här, har du avtäckt " "%{artifact}." msgid "Congratulations!" msgstr "Gratulerar!" msgid "Nothing here. Where could it be?" msgstr "Ingenting här. Var kan den vara?" msgid "Try searching on clear ground." msgstr "Försök att gräva pÃ¥ bar mark." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "En miniatyrvy av den kända världen. Vänsterklicka för att flytta " "visningsomrÃ¥det." msgid "Month: %{month} Week: %{week}" msgstr "MÃ¥nad: %{month} Vecka: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Du hittade en liten\n" "summa %{resource}." msgid "Status Window" msgstr "Statusfönster" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "Detta fönster visar datum och information om din hjälte och ditt rike." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Detta fönster visar datum och information om din hjälte och ditt rike. " "Vänsterklicka här för att bläddra genom dessa fönster." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Detta lÃ¥ter dig ändra spelarnas startpositioner och färger. En speciell färg " "startar alltid vid en viss plats. Vissa positioner kan endast spelas av en " "datorstyrd eller mänsklig spelare." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Detta lÃ¥ter dig ändra spelarnas startpositioner och färger. En speciell färg " "startar alltid vid en viss plats. Vissa positioner kan endast spelas av en " "datorstyrd eller mänsklig spelare." msgid "Handicap" msgstr "Handikapp" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Ändra spelarens handikapp. Bara spelare kontrollerade av en människa kan ha " "handikapp. Handikappade spelare startar med färre resurser och tjänar 15 % " "mindre för milt och 30 % mindre för gravt handikapp." msgid "%{color} player" msgstr "%{color} spelare" msgid "No Handicap" msgstr "Inget Handikapp" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "Inga restriktioner för startresurser eller resursintäkter per dag." msgid "Mild Handicap" msgstr "Milt Handikapp" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Spelare med milt handikapp startar med färre resurser och tjänar 15% färre " "resurser per dag." msgid "Severe Handicap" msgstr "Gravt Handikapp" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Spelare med gravt handikapp startar med färre resurser och tjänar 30% färre " "resurser per dag." msgid "" "Default\n" "value" msgstr "Standardvärde" msgid "Set %{skill} Skill" msgstr "Ange %{skill}sförmÃ¥ga" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" "Ange %{skill} grundvärde. Högerklicka för att Ã¥terställa till standard." msgid "View %{skill} Info" msgstr "Visa information om %{skill}" msgid "" "Default\n" "skill" msgstr "" "Standard-\n" "förmÃ¥ga" msgid "The available values range from %{min} to %{max}." msgstr "De möjliga värdena gÃ¥r frÃ¥n och med %{min} till och med %{max}." msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "MELLANSLAG" msgid "Keyboard|ABC" msgstr "ABC" msgid "The entered value is invalid." msgstr "Värdet är ogiltigt." msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" "Det inmatade värdet är ogiltigt.\n" "Värdet fÃ¥r vara inte mindre än %{minValue} och inte mer än %{maxValue}." msgid "Kingdom Income" msgstr "Inkomst" msgid "Kingdom Income per day." msgstr "Rikets Dagsinkomst." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "För varje fyrtorn du kontrollerar sÃ¥ kommer dina skepp segla längre per dag." msgid "English" msgstr "Engelska" msgid "French" msgstr "Franska" msgid "Polish" msgstr "Polska" msgid "German" msgstr "Tyska" msgid "Russian" msgstr "Ryska" msgid "Italian" msgstr "Italienska" msgid "Czech" msgstr "Tjeckiska" msgid "Norwegian" msgstr "Norska" msgid "Belarusian" msgstr "Vitryska" msgid "Bulgarian" msgstr "Bulgariska" msgid "Ukrainian" msgstr "Ukrainska" msgid "Romanian" msgstr "Rumänska" msgid "Spanish" msgstr "Spanska" msgid "Swedish" msgstr "Svenska" msgid "Portuguese" msgstr "Portugisiska" msgid "Turkish" msgstr "Turkiska" msgid "Dutch" msgstr "Nederländska" msgid "Hungarian" msgstr "Ungerska" msgid "Danish" msgstr "Danska" msgid "Slovak" msgstr "Slovakiska" msgid "Vietnamese" msgstr "Vietnamesiska" msgid "Slow" msgstr "LÃ¥ngsam" msgid "Fast" msgstr "Snabb" msgid "Very Fast" msgstr "Mkt. snabb" msgid "Evil" msgstr "Ond" msgid "Good" msgstr "God" msgid ", FPS: " msgstr ", FPS: " msgid "shipAndGraveyard|%{object} robber" msgstr "%{object}splundrare" msgid "pyramid|%{object} raided" msgstr "%{object} plundrat" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallanth" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Syster Eliza" msgid "Brother Brax" msgstr "Broder Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " ger dig maximalt med stridsmoral" msgid " gives you maximum luck" msgstr " ger dig maximalt med tur" msgid "You cannot have multiple spell books." msgstr "Hjälten kan inte ha flera besvärjelseböcker." msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" "Hjälten kan inte plocka upp denna artefakten. Hjälten har redan full " "packning!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "För att kasta besvärjelser mÃ¥ste Hjälten först och främst köpa en magibok " "för %{gold} guld." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Tyvärr verkar du för tillfället vara pÃ¥ grön kvist." msgid "Do you wish to buy one?" msgstr "Vill du köpa en?" msgid "%{count} / day" msgstr "%{count} / dag" msgid "one" msgstr "en" msgid "two" msgstr "tvÃ¥" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "En strömvirvel uppslukar ditt skepp. En del av din armé har ramlat överbord." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "" "Förolämpade av ditt avvisande av deras erbjudande, attackerar varelserna!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "Varelserna blir rädda för din armés styrka och skingras.\n" "Vill du förfölja och strida mot dem?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" "När du genomsöker ett fiendeläger hittar du ett gömt förrÃ¥d av skatter." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Kvarnens skötare meddelar:\n" "\"Herre, jag har jobbat hÃ¥rt för att förse dig med dessa resurser, kom " "tillbaka nästa vecka för mer.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Kvarnens skötare meddelar:\n" "\"Herre, jag är ledsen, det finns för tillfället inga resurser tillgänliga. " "Vänligen försök nästa vecka.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Kvarnens skötare meddelar:\n" "\"Herre, jag har jobbat hÃ¥rt för att förse dig med detta guld, kom tillbaka " "nästa vecka för mer.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Kvarnens skötare meddelar:\n" "\"Herre, jag är ledsen, det finns för tillfället inget guld tillgänligt. " "Vänligen försök nästa vecka.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Du har hittat ett övergivet skjul.\n" "Efter att ha kikat igenom hittar du nÃ¥gra gömda resurser i närheten." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" "Skjulet är övergivet sedan länge tillbaka. Det finns ingenting av värde här." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Du fÃ¥ngar en Pyssling som slumrat till i ett kluster av magiska svampar.\n" "I utbyte mot hans frihet sÃ¥ leder han dig till en kruka fylld med fina saker." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Du har stött pÃ¥ en förtrollad trädgÃ¥rd, den typ av plats som Pysslingar och " "Féer brukar befinna sig. Men du ser ingen här idag.\n" "Kanske bättre lycka nästa vecka," msgid "You come upon the remains of an unfortunate adventurer." msgstr "Du stöter pÃ¥ kvarlevorna av en olycklig äventyrare." msgid "Treasure" msgstr "Skatt" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "När du söker igenom de trasiga kläderna hittar du %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "När du söker igenom de trasiga kläderna hittar du ingenting." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Du stöter pÃ¥ en gammal vagn som har övergetts av en försäljare som inte " "riktig lyckades komma in pÃ¥ säker terräng." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Tyvärr har andra hittat den tidigare, och vagnen är tom." msgid "Searching inside, you find the %{artifact}." msgstr "När du söker igenom den, hittar du %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Inuti ser du att nÃ¥gra av vagnens packningar fortfarande är orörda." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Du söker igenom vrakgodset, du hittar lite ved och guld." msgid "You search through the flotsam, and find some wood." msgstr "Du söker igenom vrakgodset, du hittar lite ved." msgid "You search through the flotsam, but find nothing." msgstr "Du söker igenom vrakgodset, men du hittar ingenting." msgid "Shrine of the 1st Circle" msgstr "1:a kretsens tempel" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Du hittar ett litet tempel, bevistat av en grupp följeslagare.\n" "I utbyte mot ditt beskyddande gÃ¥r de med pÃ¥ att lära dig en komplicerad " "besvärjelse - '%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "2:a kretsens tempel" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Du hittar ett utsmyckat tempel, bevistat av en grupp runda munkar.\n" "I utbyte mot ditt beskyddande gÃ¥r de med pÃ¥ att lära dig en komplicerad " "besvärjelse - '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "3:e kretsens tempel" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Du hittar ett frikostigt tempel, bevistat av en grupp höga präster.\n" "I utbyte mot ditt beskyddande gÃ¥r de med pÃ¥ att lära dig en komplicerad " "besvärjelse - '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Tyvärr är du inte vis nog att förstÃ¥ besvärjelsen, sÃ¥ kan inte lära dig den." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Tyvärr har du redan lärt dig denna besvärjelse. De kan inte lära dig " "nÃ¥gonting mer." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Tyvärr har du ingen magibok att anteckna besvärjelsen med." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Du närmar dig hyddan och ser en häxa där inne som studerar en urÃ¥ldrig volym " "av %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "När du närmar dig, vänder hon sig om och stirrar med sitt glasöga pÃ¥ dig.\n" "\"Du kan redan allting du förtjänar att veta!\" tjuter häxan. \"UT FRÃ…N MITT " "HUS!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "När du närmar dig, vänder hon sig om och säger.\n" "\"Du kan redan allting som jag kan lära dig. Jag kan inte hjälpa dig vidare." "\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "En gammal och odödlig häxa bor i en hydda med fÃ¥gelben som styltor lär dig " "%{skill} för hennes egna gÃ¥tfulla ändamÃ¥l." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "När du dricker det söta vattnet, ökar din tur inför nästa strid." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Du dricker frÃ¥n den förtrollande fontänen, men ingenting händer." msgid "You enter the faerie ring, but nothing happens." msgstr "Du kliver in i häxringen, men ingenting händer." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "När du kliver in i den mystiska häxringen, ökar din armés tur inför nästa " "strid." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Du har hittat en urÃ¥ldrig och väderbiten stenavgud.\n" "Den är menad för att lyckoönska besökare, men eftersom stjärnorna redan ler " "Ã¥t dig gör den ingenting." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Du har hittat en gammal och vittrad stenuthuggen avgud.\n" "Om man kysser den ska den medföra lycka. Stenen är kall vid beröringen." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Sjöjungfrurna lockar dig tyst att komma tillbaka senare och bli välsignad " "igen." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "NÃ¥gra magiska och sköna Sjöjungfrur hälsar pÃ¥ dig och din besättning.\n" "För ett ögonblick sÃ¥ glömmer du bort dina bekymmer och njuter av en härlig " "stund.\n" "Sjöjungfrurna välsignar dig och din besättning med ökad tur i nästa strid." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Du stöter pÃ¥ pyramiden som har tillhört en stor och urÃ¥ldrig kung.\n" "Du frestas att gÃ¥ in och söka efter skatter, men alla gamla historier varnar " "om hemska förbannelser och odöda väktare.\n" "Vill du gÃ¥ in och söka?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Medan du besegrar monstren, dechiffrerar du en urÃ¥ldrig hieroglyf pÃ¥ väggen " "som berättar hemligheten om besvärjelsen - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Tyvärr har du ingen magibok att anteckna besvärjelsen med." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Tyvärr är du inte vis nog att förstÃ¥ besvärjelsen, sÃ¥ kan inte lära dig den." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Du stöter pÃ¥ en pyramid av en stor och gammal kung.\n" "En rutinerad utforskning avslöjar att pyramiden är helt tom." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "En klunk frÃ¥n brunnen ska Ã¥terställa dina besvärjelsepoäng, men du har redan " "maximalt antal besvärjelsepoäng." msgid "A second drink at the well in one day will not help you." msgstr "En andra klunk frÃ¥n brunnen pÃ¥ samma dag kommer inte att hjälpa dig." msgid "A drink from the well has restored your spell points to maximum." msgstr "En klunk frÃ¥n brunnen har Ã¥terställt dina besvärjelsepoäng till max." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Jag är ledsen herrn,\" säger legosoldatsledaren, \"du vet redan allt vi " "kan lära dig\"." msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "Soldaterna som bor i fortet lär dig nÃ¥gra nya försvarstricks." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Du har kommit fram till ett legosoldatsläger som tränar sina taktiker. \"Ni " "är för avancerade för oss,\" säger legosoldatskaptenen. \"Vi kan inte lära " "er nÃ¥gonting mer.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Du stöter pÃ¥ ett legoknektsläger där de övar pÃ¥ sin stridskonst. " "Legoknektarna välkomnar dig och dina trupper att öva med dem." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Ge dig iväg!\", ryter häxdoktorn, \"du vet allt jag vet.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "En orchisk häxdoktor som lever i hyddan, fördjupar dina kunskaper i " "trollkonst genom att visa dig hur du kastar stenar, läser järtecken och spÃ¥r " "i kycklingars inälvor." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Du har hittat en grupp druider som dyrkar en av deras mystiska " "stenbyggnader. Under tystnad avvisar de dig och pÃ¥pekar att de inte har " "nÃ¥gonting nytt att lära dig." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Du har hittat en grupp druider som dyrkar en av deras mystiska " "stenbyggnader. Under tystnad lär de dig nya sätt att kasta besvärjelser." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Du närmar dig försiktigt gravplatsen som tillhör en urÃ¥ldrig krigare. Vill " "du söka igenom gravarna?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Medan du besegrar Zombierna spenderar du nÃ¥gra timmar pÃ¥ att söka igenom " "gravarna och hittar ingenting! En sÃ¥dan föraktlig handling reducerar din " "armés moral." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "Medan du besegrar Zombierna söker du igenom gravarna och hittar nÃ¥gonting!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "De ruttnande skrovet frÃ¥n ett stort piratskepp knarrar när de slÃ¥s mot " "klipporna. Vill du genomsöka vraket?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Medan du besegrar Spökena spenderar du nÃ¥gra timmar pÃ¥ att söka igenom " "ruinerna och hittar ingenting! En sÃ¥dan föraktlig handling reducerar din " "armés moral." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" "Medan du besegrar Spökena kikar du igenom ruinerna och hittar nÃ¥gonting!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "De ruttnande skrovet frÃ¥n ett stort piratskepp knarrar när de slÃ¥s mot " "klipporna. Vill du genomsöka skeppet?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "Medan du besegrar Skeletten söker du igenom ruinerna och hittar nÃ¥gonting!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "Dina män hittar en navigeringsboj som bekräftar att du är pÃ¥ rätt väg." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Dina män hittar en navigeringsboj som bekräftar att du är pÃ¥ rätt väg och " "höjer deras moral." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "En klunk frÃ¥n oasen är uppfriskande, men den erbjuder ingen ytterligare " "förmÃ¥n. Oasen kan hjälpa till igen om du slÃ¥ss i en strid först." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "En klunk frÃ¥n oasen fyller din trupper med styrka och lyfter deras stämning. " "Du kan resa en bit till idag." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "En klunk frÃ¥n vattenhÃ¥let är uppfriskande, men den erbjuder ingen " "ytterligare förmÃ¥n. Oasen kan hjälpa till igen om du slÃ¥ss i en strid först." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "En klunk frÃ¥n vattenhÃ¥let fyller din trupper med styrka och lyfter deras " "stämning. Du kan resa en bit till idag." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Det hjälper inte att be tvÃ¥ gÃ¥nger före en strid. Kom tillbaka när du har " "stridit." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "Ett besök och en bön i templet höjer dina truppers moral." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "En gammal riddare dyker upp pÃ¥ lusthusets trapp. \"Jag är ledsen, min herre. " "Jag har lärt dig allt jag kan.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "En gammal riddare dyker upp pÃ¥ lusthusets trapp. \"Min herre, jag ska lära " "dig allt jag kan för att hjälpa dig pÃ¥ dina resor.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Du har dragit ut en skeppsbruten man frÃ¥n en säker död i en oförlÃ¥tande " "ocean. Han säger tacksamt, \"Jag skulle ge dig en artefakt som belöning, men " "du har ingen plats för den.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Du har dragit ut en skeppsbruten man frÃ¥n en säker död i en oförlÃ¥tande " "ocean. Tacksamt ger han dig %{art} för din vänlighet." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "En pyssling erbjuder dig en %{art} för en lite summa pÃ¥ %{gold} guld." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "En pyssling erbjuder dig en %{art} för en lite summa pÃ¥ %{gold} guld och " "%{count} %{res}." msgid "Do you wish to buy this artifact?" msgstr "Vill du köpa denna artefakt?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Du försöker att betala pysslingen, men du inser att du inte har rÃ¥d. " "Pysslingen stampar med sin fot och ignorerar dig." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Förolämpad av din vägran att neka hans generösa erbjudande, stampar " "pysslingen med sin fot och ignorerar dig." msgid "You've found the artifact: " msgstr "Du har hittat artefakten: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Du har funnit en enkel boning där en väderbiten eremit är bosatt. Eremiten " "berättar för dig att han är villig att ge %{art} till den fösta visa person " "som han träffar." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Du rider förbi ett spartanskt hus där det bor en pensionerad soldat. " "Soldaten berättar för dig att han tänker ge %{art} till den första riktiga " "ledaren han träffar." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Du stöter pÃ¥ en märklig hattklädd figur med en uggla pÃ¥ hatten. Han berättar " "att han kan ge dig %{art} om du besitter förmÃ¥gan %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Du stöter pÃ¥ en urÃ¥ldrig artefakt. När du närmar dig den dyker ett gäng " "Rövare upp frÃ¥n buskarna för att vakta deras stöldgods." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Genom en glänta ser du en urÃ¥ldrig artefakt. Tyvärr vaktas artefakten av en " "%{monster}. Vill du strida mot %{monster} för artefakten?" msgid "Victorious, you take your prize, the %{art}." msgstr "Segrande tar du ditt pris, %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "Det är bättre att fly än att illa fäkta, sÃ¥ du bestämmer dig för att undvika " "denna strid för idag." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Efter att ha spenderat flera timmar pÃ¥ att försöka fiska upp kistan ur sjön, " "öppnar du den och hittar %{gold} guldmynt." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Efter att ha spenderat flera timmar pÃ¥ att försöka fiska upp kistan ur sjön, " "öppnar du den och hittar %{gold} guld och %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Efter att ha spenderat timmar pÃ¥ att försöka fiska upp skattkistan ur sjön, " "öppnar du den, bara för att hitta den tom." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Efter att ha letat igenom omrÃ¥det hittar du en skattgömma. Du kan välja att " "beslagta skatten själv eller dela ut skatten med bönderna för erfarenhet.\n" "Vill du behÃ¥lla skatten själv?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Efter att ha renskrubbat omrÃ¥det, finner du en gömd kista som innehÃ¥ller de " "%{gold} guldmynten." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Efter att ha renskrubbat omrÃ¥det, finner du en gömd kista som innehÃ¥ller den " "antika artefakten %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Du stöter pÃ¥ en bucklig och matt lampa djupt ner i jorden. Vill du gnida " "lampan?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Du har tagit kontroll över den lokala Alkemistaffären. Den kommer att förse " "dig med %{count} enhet kvicksilver per dag." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Du tar kontroll över ett sÃ¥gverk. Den kommer att förse dig med %{count} " "enheter av ved per dag." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Du tar kontroll över en malmgruva. Den kommer att förse dig med %{count} " "enheter av malm per dag." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Du tar kontroll över en svavelgruva. Den kommer att förse dig med %{count} " "enhet av svavel per dag." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Du tar kontroll över en kristallgruva. Den kommer att förse dig med %{count} " "enhet av kristaller per dag." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Du tar kontroll över en ädelstensgruva. Den kommer att förse dig med " "%{count} enhet av ädelstenar per dag." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Du tar kontroll över en guldgruva. Den kommer att förse dig med %{count} " "guld per dag." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Fyrtornet är nu under din kontroll och alla dina skepp kommer nu förflytta " "sig längre per dag." msgid "You gain control of a %{name}." msgstr "Du fick kontroll över en %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Du stöter pÃ¥ en övergiven guldgruva. Gruvan verkar vara hemsökt. Vill du gÃ¥ " "in?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Du besegrade spökena och kan Ã¥terställa gruvans produktion." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "En grupp %{monster} med en önskan för större ära vill följa med dig. " "Accepterar du det?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "När du närmar dig boningen upptäcker du att det inte är nÃ¥gon där." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Du söker igenom ruinerna, men Medusorna som brukade bo här är borta. Kanske " "det kommer att finnas nÃ¥gra där nästa vecka." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Du har hittat nÃ¥gra Medusor som bor i ruinerna. Dem är beredd att förena sig " "med din armé för ett pris. Vill du rekrytera Medusorna?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Du har hittat ett Trädhus. Tyvärr, vill ingen av Féerna ansluta sig till din " "armé. Kanske bättre lycka nästa vecka." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "NÃ¥gra Féer som bor i en trädhusby vill ansluta sig till din armé för en " "kostnad. Vill du rekrytera Féerna?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "En färgglad Rövarvagn stÃ¥r tom här. Kanske det finns fler Rövare här senare." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Avlägsna ljud av musik och skratt som kommer frÃ¥n en färgglad Rövarvagn. " "Vill du rekrytera nÃ¥gra Rövare?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Du ser en lägerplats med slitna tält som fladdrar i vinden. Tälten är " "obebodda för tillfället. Kanske kommer Nomaderna tillbaka senare." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Du ser en lägerplats med slitna tält som fladdrar i vinden. En grupp Nomader " "som lever i tälten erbjuder sig sina tjänster. Vill du rekrytera Nomader?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Lerpölen bubblar för en stund innan den förblir stilla." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "När du närmar dig den bubblande lerpölen börjar varelser stiga upp och " "ställa sig runt den. I samklang säger de: \"Moder Jord vill erbjuda dig " "nÃ¥gra av hennes trupper. Vill du rekrytera Jordväsen?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Du kliver in i byggnaden av vita pelare, men du hittar ingenting." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Vita stenpelare stöder ett tak som stiger upp mot himmelen. När du gÃ¥r in sÃ¥ " "möts du av en kraftig vindpust som nästan fÃ¥r dig omkull. Vinden " "materialiserar sig inför dig i en halvt skenbar form. Varelsen frÃ¥gar dig " "med en röst som bäst kan beskrivas som en högljudd viskning: \"Varför har du " "kommit? Är du här för att framkalla vindens och luftens styrka?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Inga Eldväsen kommer upp ur lavapölen." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Du stöter pÃ¥ en krater med glödande lava och eld där Eldväsen hoppar i och " "ur en pöl med lava. En grupp av Eldväsen gÃ¥r fram till dig och erbjuder dig " "sina tjänster. Vill du rekrytera Eldväsen?" msgid "A face forms in the water for a moment, and then is gone." msgstr "" "Ett ansikte formar sig i vattnet för ett ögonblick, bara för att försvinna " "sen." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Kristallstrukturer kastar skuggor över en liten reflekterande vattenpöl. Du " "tittar ned i pölen och ett ansikte som inte är ditt tittar tillbaka. Den " "frÃ¥gar: \"Vill du kalla pÃ¥ vattnets krafter?\"" msgid "This burial site is deathly still." msgstr "Denna begravningsplats är dödstyst." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Rastlösa själar frÃ¥n döda krigare söker efter viloplats och erbjuder sig att " "ansluta sig till dig i hopp och att finna frid. Vill du rekrytera Spöken?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "Dödens Stad är tom pÃ¥ liv, den är även tom pÃ¥ dött liv. Kanske nästa vecka " "har det dykt upp nÃ¥gra odöda." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "NÃ¥gra Lichar som befinner sig är villiga att lÃ¥ta sig rekryteras för ett " "pris. Vill du rekrytera Lichar?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Du har hittat ruinerna av en antik stad, som nu är endast är bebodd av de " "odöda. Vill du söka?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "NÃ¥gra Lichar är imponerade över din seger över deras gelikar och erbjuder " "sig att ansluta till din armé för ett pris. Vill du rekrytera Lichar?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Du har hittat en av dem där broarna som Troll brukar bo under, men det finns " "inga där. Kanske det finns nÃ¥gra där nästa vecka." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "NÃ¥gra troll som bor under bron är beredd pÃ¥ att förena sig med din armé mot " "ett pris. Vill du rekrytera troll?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "Trollen som bor under bron utmanar dig. Vill du slÃ¥ss mot dem?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "NÃ¥gra fÃ¥ Troll kvarstÃ¥r som tagit skydd under bron. De gÃ¥r fram till dig och " "erbjuder sig att ansluta sig till din armé som legoknektar. Vill du köpa " "nÃ¥gra Troll till din armé?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "Drakstaden har inga Drakar som kan förena sig med dig denna vecka. Det " "kanske finns en tillgänglig Drake där nästa vecka." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Drakstaden är beredd att erbjuda nÃ¥gra drakar till din armé för ett pris. " "Vill du rekrytera drakar?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Du stÃ¥r inför Drakstaden, en plats pÃ¥ förbjudet omrÃ¥de för människor. Vill " "du strida mot denna regel och utmana drakarna i en strid?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Efter att ha besegrat Drakkrigarna gÃ¥r stadens ledare med pÃ¥ att förse nÃ¥gra " "Drakar till din armé till ett pris. Vill du rekrytera Drakar?" msgid "From the observation tower, you are able to see distant lands." msgstr "FrÃ¥n observationstornet kan du se avlägsna länder." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Källan fylls bara pÃ¥ en gÃ¥ng per vecka och nÃ¥gon har redan varit här denna " "vecka." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "En klunk frÃ¥n källan ska ge hjälten dubbelt sÃ¥ mÃ¥nga besvärjelsepoäng, men " "hjälten har redan sÃ¥ mÃ¥nga besvärjelsepoäng." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "En klunk frÃ¥n källan fyller ditt blod med magi! Du har nu dubbelt sÃ¥ fler " "besvärjelsepoäng." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Butlern känner igen dig och vägrar släpa in dig. \"Mästaren,\" säger han, " "\"vill inte se samma student tvÃ¥ gÃ¥nger.\"" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Butlern släpper in dig för att fÃ¥ träffa husets mästaren. Han tränar dig i " "de fyra färdigheterna som en hjälte borde veta." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Butlern öppnar dörren och tittar upp och ned pÃ¥ dig. \"Du är varken berömd " "eller diplomatisk nog för att bli insläppt och för att fÃ¥ se min mästare,\" " "han sniffar. \"Kom tillbaka när du tror att du är dig själv värdig.\"" msgid " and " msgstr " och " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Alla %{monsters} du har i din armé har tränats av stridsmästarna i fortet. " "Din armé innehÃ¥ller nu %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "En brokig allians av Jättar, Orcher och Dvärgar erbjuder att träna " "(uppgradera) om du har nÃ¥gra sÃ¥dana trupper i din armé. Tyvärr har du inga " "sÃ¥dana trupper." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Alla dina %{monsters} har blivit uppgraderade till %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "En smed som jobbar pÃ¥ gjuteriet erbjuder att konvertera Pikenerarnas och " "Svärdsmännens alla vapen frÃ¥n järn till stÃ¥l. Han säger även att han vet en " "process som konverterar Järngolems till StÃ¥lgolems. Olyckligtvis har du inte " "nÃ¥gon av dessa i dina arméer, sÃ¥ han kan inte hjälpa dig." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Kaptenen ser pÃ¥ dig med en överraskad blick och säger:\n" "\"Du har redan bättre kartor än vad jag har. LÃ¥t mig fÃ¥ fiska ifred nu.\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "En pensionerad kapten bor pÃ¥ denna renovererade fiskeplattform. Han erbjuder " "dig att köpa hans kartor, som han själv har gjort i hans yngre dagar, för " "1,000 guld. Vill du köpa kartorna?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Kaptenen suckar. \"Du har inte tillräckligt med pengar, va? Du kan inte " "förvänta mig att ge bort mina kartor gratis!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Du stöter pÃ¥ en obelisk gjord av en stentyp som du aldrig tidigare skÃ¥dat. " "När du stirrar pÃ¥ den lena ytan ändras den till en inskription. " "Inskriptionen är en del av en förlorad antik karta. Du kopierar snabbt av " "den och inskriptionen försvinner lika tvärt som den kom dit." msgid "You have already been to this obelisk." msgstr "Du har redan varit till denna obelisk." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "När du närmar dig öppnar trädet sina ögon i glädje. \"Vad kul att se dig, " "min student. Jag hoppas mina undervisningar har hjälpt dig.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "När du närmar dig öppnar trädet sina ögon i glädje. \"Ã…h, en äventyrare! LÃ¥t " "mig lära dig lite grann om vad jag har lärt mig under Ã¥ren.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "När du närmar dig öppnar trädet sina ögon i glädje." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Aha, en äventyrare! Jag skulle gladeligen lära dig lite om vad jag har " "lärt mig under alla Ã¥r för endast %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Begrav det bara under mina rötter.)" msgid "Tears brim in the eyes of the tree." msgstr "TÃ¥rar fyller trädets ögon." msgid "\"I need %{count} %{res}.\"" msgstr "\"Jag behöver %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "viskar den. (Sniff) \"NÃ¥ja, kom tillbaka när du kan betala mig.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Hukad inne bland nÃ¥gra träd sitter en blind sierska. När du förklarat ditt " "mÃ¥l med dina resor sÃ¥ tar sierskan fram sin kristallkula och lÃ¥ter dig se " "dina fienders styrkor och svagheter." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "IngÃ¥ngen till grottan är mörk och en otäck, svavelaktig lukt strömmar frÃ¥n " "grottans mynning. Vill du gÃ¥ in?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" "Förutom bevis pÃ¥ att det har varit ett förskräcklig strid här, är grottan " "tom." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Du finner en mäktig och grotesk Demon i en Grotta. \"Idag\" rasslar den till " "\"kommer du att strida och säkerligen dö. Men jag kommer ge dig valet för " "hur du vill dö. Du kan välja att möta mig eller mina undersÃ¥tar i strid. " "Föredrar du att slÃ¥ss mot mina undersÃ¥tar?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Demonen vrÃ¥lar och attackerar! Efter en kort intensiv strid sÃ¥ dräper du " "monstret och fÃ¥r %{exp} erfarenhetspoäng." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Demonen vrÃ¥lar och attackerar! Efter en kort intensiv strid sÃ¥ dräper du " "monstret och fÃ¥r %{exp} erfarenhetspoäng och %{count} guld." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Demonen vrÃ¥lar och attackerar! Efter en kort intensiv strid sÃ¥ dräper du " "monstret och finner artefakten %{art} i änden av grottan." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Demonen ser att du inte har %{count} guld och river dig med sina klor. Det " "sista du ser är en röd dimma." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Demonen hoppar pÃ¥ dig och har din hals i sina klor innan du ens hinner " "reagera. \"Ditt liv är mitt\" säger den. \"Jag kan sälja tillbaka ditt liv " "till dig för %{count} guld.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Medan du besegrar demonens underhuggare hittar du en dolt förrÃ¥d med " "%{count} guld." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "När du kliver in i Alkemistens Torn sÃ¥ träder en hukad och grÃ¥nad man i brun " "kappa fram och gÃ¥r emot dig." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" "Han kontrollerar din packning, och upptäcker att du har 1 förbannat föremÃ¥l." msgstr[1] "" "Han kontrollerar din packning, och upptäcker att du har %{count} förbannade " "föremÃ¥l." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "För %{gold} guld kan alkemisten ta bort den Ã¥t dig. Vill du betala?" msgstr[1] "För %{gold} guld kan alkemisten ta bort dom Ã¥t dig. Vill du betala?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Efter du kommit överens med att betala guldsumman, sÃ¥ tar alkemisten den " "förbannade artefakten och slänger ner den i hans magiska kittel." msgstr[1] "" "Efter du kommit överens med att betala guldsumman, sÃ¥ tar alkemisten de " "förbannade artefakterna och slänger ner de i hans magiska kittel." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Du hör en röst bakom den lÃ¥sta dörren, \"Du har inte tillräckligt mycket " "guld att betala mina tjänster.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Du hör en röst frÃ¥n högt ovan i tornet, \"Ge dig väg! Jag kan inte hjälpa " "dig!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Stallmästaren talar till dig, \"Det är en fin häst du har. Tyvärr är jag " "rädd att jag inte kan erbjuda nÃ¥gon bättre, men ditt kavalleris hästar har " "sett bättre dagar. Vi har mÃ¥nga tränade krigshästar som skulle vara " "behjälpliga dina ryttare. Jag insisterar att du tar dem.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "När du närmar dig stallet sÃ¥ dyker stallmästaren, upp ledandes en fin " "krigshäst. \"Denna hingst kommer hjälpa dig att pÃ¥ dina resor genom landet. " "Men han kommer bli trött efter en vecka. Du mÃ¥ste lÃ¥ta mig förse ditt " "rytteri med bättre och utvilade hästar.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Huvudhästskötaren närmar sig dig och säger, \"Du har redan en fin häst, och " "inget oerfaret kavalleri som kanske skulle kunna ha nytta av vÃ¥ra tränade " "stridshästar.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "När du närmar dig stallet sÃ¥ dyker stallmästaren, upp ledandes en fin " "krigshäst. \"Denna hingst kommer hjälpa dig att pÃ¥ dina resor genom landet. " "Men hans uthÃ¥llighet räcker bara en vecka men tung packning, sÃ¥ du fÃ¥r byta " "ut honom om en vecka. Vi har ocksÃ¥ mÃ¥nga fina krighästar som skulle hjälpa " "ditt rytteri men du har ingen som vi kan hjälpa.\"" msgid "The Arena guards turn you away." msgstr "Arenavakterna avvisar dig." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Du lÃ¥ter din besättning fylla sina öron med vax innan sirenernas sällsamma " "sÃ¥ng fÃ¥r nÃ¥gon chans att locka ner de i djupet." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "När sirenerna sjunger sin spökliga sÃ¥ng lyckas din din lilla beslutsamma " "armé överkomma uppmaningen att dyka med huvudet först i havet." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Du lÃ¥ter din besättning stoppa sina öron med vax innan sirenernas spökliga " "sÃ¥ng fÃ¥r tillfälle att lura dem in i en vattengrav. En spöklik jämrande sÃ¥ng " "kommer frÃ¥n sirenerna som balanserar pÃ¥ stenarna. MÃ¥nga i din besättning " "faller i trans och dyker i vattnet, där de drunknar. Du är nu klokare för " "besöket och tjänar %{exp} erfarenhet." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Genom en djärv inbrytning i det lokala fängelset sÃ¥ friger du en hjälte som " "är fängslad där. I utbyte mot friheten sÃ¥ lÃ¥ter sig hjälten tjäna dig under " "ditt fälttÃ¥g." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Du har redan %{count} hjältar och mÃ¥ste Ã¥ngerfullt lämna fÃ¥ngarna i detta " "fängelse för att tvina i smärta för outsägliga dagar." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Du gÃ¥r in i en ranglig hydda och talar med magikern som bor där. Han " "berättar om ställen när och fjärran som kan vara dig behjälpligt under dina " "resor." msgid "This eye seems to be intently studying its surroundings." msgstr "Detta öga verkar koncentrerat studera sin omgivning." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Du möter en gigantisk sfinx. Sfinxen kvarstÃ¥r ovanligt tyst." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Jag har en gÃ¥ta till dig,\" säger sfinxen. \"Om du svarar rätt, kommer du " "att bli belönad. Svarar du fel, kommer du att bli uppäten. Accepterar du " "utmaningen?\"" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Sfinxen ställer dig följande gÃ¥ta:\n" "\n" "'" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" "'\n" "\n" "Ditt svar?" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Du gissade fel,\" säger sfinxen med ett leende. Sfinxen slÃ¥r ned dig till " "marken med en tass. Ett till slag fÃ¥r världen att slockna och du vet inte av " "nÃ¥gonting mer." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "NÃ¥got besviken säger sfinxen. \"Du har svarat pÃ¥ min gÃ¥ta sÃ¥ här är din " "belöning. Ge sig av nu.\"." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "En magisk barriär stÃ¥r framför sig och blockerar din väg. Runor pÃ¥ valvet " "säger,\n" "\"Säg nyckeln och du kan passera.\"\n" "När du säger det magiska ordet tonar den glöder barriären bort." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "En magisk barriär stÃ¥r framför sig och blockerar din väg. Runor pÃ¥ valvet " "säger,\n" "\"Säg nyckeln och du kan passera.\"\n" "Du pratar, men ingenting händer." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Du kliver in i tältet och ser en gammal kvinna stirra pÃ¥ en magisk ädelsten. " "Hon tittar upp och säger,\n" "\"I mina resor har jag lärt mig mycket om mystisk magi. Ett stor orakel " "lärde mig denna färdighet. Jag har svaret du söker.\"" msgid "No spell book is present." msgstr "Det finns ingen Magibok." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Den besvärjelsen kostar %{mana} besvärjelsepoäng. Hjälten har slut pÃ¥ " "besvärjelsepoäng sÃ¥ denna kan inte kasta besvärjelsen." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Den besvärjelsen kostar %{mana} besvärjelsepoäng. Hjälten har bara %{point} " "besvärjelsepoäng, sÃ¥ hjälten kan inte kasta besvärjelsen." msgid "The spell was not found." msgstr "Besvärjelsen hittades ej." msgid "Only heroes can cast this spell." msgstr "Endast hjältar kan kasta denna besvärjelsen." msgid "This hero is not able to cast adventure spells." msgstr "Hjälten kan inte kasta kartbesvärjelser." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Din hjälte är för trött för att kasta en besvärjelse idag. Försök igen " "imorgon." msgid "This spell cannot be cast on a boat." msgstr "Denna besvärjelse kan inte kastas frÃ¥n skepp." msgid "This spell can only be cast near an ocean." msgstr "Denna besvärjelse kan bara kastas nära hav." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Det finns inget skepp tillgängligt och inget ledig strand i närheten för att " "hjälten skall kunna kasta denna besvärjelse." msgid "There are no boats available for this spell." msgstr "Det finns inget tillgängligt skepp för att kasta denna besvärjelsen." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "" "Det finns ingen ledig strand i närheten för att hjälten skall kunna kasta " "denna besvärjelse." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Du äger för närvarande inte nÃ¥gon stad eller borg som inte är upptaget. " "Besvärjelsen har ingen verkan." msgid "This hero is already in a town, so this spell will have no effect." msgstr "" "Hjälten är redan i en stad, sÃ¥ besvärjelsen kommer inte ha nÃ¥gon verkan." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Närmsta stad är %{town}.\n" "\n" "Denna stad besöks av din hjälte %{hero}." msgid "This spell is already in effect." msgstr "Denna besvärjelse används redan." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Ingen motstÃ¥ndare kan ha hjältar under dennes befäl längre. Att kasta denna " "besvärjelsen bringar ingen fördel." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Ingen motstÃ¥ndare har en hjälte under dennes befäl för tillfället. Att kasta " "denna besvärjelse bringar ingen fördel." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Hjälten mÃ¥ste befinna sig inom %{count} rutor frÃ¥n en varelse för att " "Synerbesvärjelsen ska ge effekt." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Hjälten mÃ¥ste stÃ¥ vid ingÃ¥ngen till en gruva (sÃ¥gverk och alkemistlabb " "räknas ej) för att kasta denna besvärjelse." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "DÃ¥ mÃ¥ste först besegra Spökena som vaktar gruvan för att hjälten ska kasta " "besvärjelsen." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Det finns redan minst sÃ¥ mÃ¥nga Elementväsen som vaktar gruvan som " "besvärjelsen kan frambringa. Att kasta denne besvärjelsen kommer inte ge " "nÃ¥gon ytterligare fördel." msgid "%{name} the %{race} (Level %{level})" msgstr "%{race}n %{name} (NivÃ¥ %{level})" msgid "Random hero (Level %{level})" msgstr "Slumpad hjälte (NivÃ¥ %{level})" msgid "Random %{race} hero (Level %{level})" msgstr "Slumpad %{race}hjälte (NivÃ¥ %{level})" msgid "Hero race:" msgstr "Hjälteklass" msgid "Are you sure you want to dismiss this Hero?" msgstr "Är du säker pÃ¥ att du vill avskeda denna Hjälte?" msgid "Set custom Experience value. Current value is default." msgstr "Ange erfarenhetspoäng. Nuvarande värde är standard." msgid "Change Experience value. Right-click to reset to default value." msgstr "Ändra erfarenhetspoäng. Högerklicka för att Ã¥terställa till standard." msgid "View Experience Info" msgstr "Visa information för erfarenhet" msgid "Set custom Spell Points value. Current value is default." msgstr "Ändra besvärjelsepoängen. Nuvarande värde är standard." msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" "Ändra besvärjelsepoängen. Högerklicka för att Ã¥terställa till standard." msgid "Set Spell Points value" msgstr "Ange Besvärjelsepoäng" msgid "View Spell Points Info" msgstr "Visa information för besvärjelsepoäng" msgid "Set patrol radius in tiles" msgstr "Ange patrullradie i antal rutor" msgid "Enter hero's name" msgstr "Ange hjältens namn" msgid "Click to change race." msgstr "Klicka för byta klass." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "'Utspridd' stridsformation sprider ut hjältens trupper över hela slagfältet " "med minst ett tomt mellanrum mellan varje trupp." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "'Grupperad' stridsformation buntar ihop hjältens trupper till mitten av " "dennes sida av slagfältet." msgid "Exit Hero Screen" msgstr "Lämna Hjältevyn" msgid "You cannot dismiss a hero in a castle" msgstr "Du kan inte avskeda en Hjälte i en borg." msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Avskedandet av %{race}n %{name} är förbjudet i detta scernario" msgid "Dismiss %{name} the %{race}" msgstr "Avskeda %{race}n %{name}" msgid "Show previous hero" msgstr "Visa föregÃ¥ende hjälte" msgid "Show next hero" msgstr "Visa nästa hjälte" msgid "Set army combat formation to 'Spread'" msgstr "Ställ in arméns stridsformation pÃ¥ 'Utspridd'" msgid "Set army combat formation to 'Grouped'" msgstr "Ställ in arméns stridsformation pÃ¥ 'Grupperad'" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "Välj hjältens Artefakter. Högerklicka för att Ã¥terställa Artefakt." msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" "Välj hjältens sekundära förmÃ¥gor. Högerklicka för att Ã¥terställa förmÃ¥ga." msgid "Set hero's Army. Right-click to reset unit." msgstr "Ange hjältens Armé. Högerklicka för att Ã¥terställa enhet." msgid "Set hero's portrait. Right-click to reset to default." msgstr "Välj hjälteporträtt. Högerklicka för att Ã¥terställa till standard." msgid "Click to change hero's name. Right-click to reset to default." msgstr "" "Klicka för att ändra hjältens namn. Högerklicka för att Ã¥terställa till " "standard." msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" "Hjälten är i patrulläge med %{tiles}-rutors radie. Klicka för inaktivera det." msgid "Click to enable hero's patrol mode." msgstr "Klicka här för att aktivera hjältens patrulläge." msgid "Blood Morale" msgstr "Blodtörst" msgid "%{morale} Morale" msgstr "%{morale} Stridsmoral" msgid "%{luck} Luck" msgstr "%{luck} Tur" msgid "Current Luck Modifiers:" msgstr "PÃ¥verkar Tur:" msgid "Current Morale Modifiers:" msgstr "PÃ¥verkar Stridsmoral:" msgid "Entire army is undead, so morale does not apply." msgstr "Hela armén är odöd, sÃ¥ stridsmoral gäller inte." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Nuvarande erfarenhet: %{exp1}. \n" "Nästa nivÃ¥: %{exp2}." msgid "million|M" msgstr "M" msgid "Level %{level}" msgstr "NivÃ¥ %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} har för närvarande %{point} besvärjelsepoäng av totalt %{max}. " "Maximalt antal besvärjelsepoäng är 10 gÃ¥nger hjältens KunskapssnivÃ¥. \n" "\n" "\n" "Det är möjligt att fÃ¥ mer än maximalt antal besvärjelsepoäng genom särskilda " "händelser." msgid "%{name1} meets %{name2}" msgstr "%{name1} möter %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Fiendehjältar är nu fullt identifierade." msgid "Identify Hero" msgstr "Identifiera Hjälte" msgid "Select town to port to." msgstr "Välj stad att teleportera till." msgid "Town Portal" msgstr "Stadsportal" msgid "The creatures are willing to join us!" msgstr "Varelserna är villiga att följa med oss!" msgid "All the creatures will join us..." msgstr "Alla varelserna vill följa med oss..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Varelsen vill följa med oss..." msgstr[1] "%{count} varelser vill följa med oss..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" "för en avgift pÃ¥ %{gold} guld." msgid "These weak creatures will surely flee before us." msgstr "Dessa svaga varelser kommer säkert att fly frÃ¥n oss." msgid "I fear these creatures are in the mood for a fight." msgstr "Jag är rädd för att dessa varelser är sugna pÃ¥ strid." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "Hjältens Anfall ger en bonus som läggs till pÃ¥ varje varelses Anfall." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "Hjältens Försvar ger en bonus till varje varelses Försvar." msgid "The hero's spell power determines the duration or power of a spell." msgstr "Hjältens Trollkonst bestämmer besvärjelsens längd eller styrka." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Hjältens Kunskap bestämmer hur mÃ¥nga besvärjelsepoäng hjälten kan ha. " "Vanligtvis är hjältens besvärjelsepoäng begränsad till 10 poäng per " "KunskapsnivÃ¥." msgid "Current Modifiers:" msgstr "PÃ¥verkan:" msgid "skill|Basic" msgstr "Basal" msgid "skill|Advanced" msgstr "Avancerad" msgid "skill|Expert" msgstr "Expert" msgid "Pathfinding" msgstr "Vägvisning" msgid "Archery" msgstr "Skytte" msgid "Logistics" msgstr "Logistik" msgid "Scouting" msgstr "Spaning" msgid "Diplomacy" msgstr "Diplomati" msgid "Navigation" msgstr "Navigering" msgid "Leadership" msgstr "Ledarskap" msgid "Wisdom" msgstr "Visdom" msgid "Mysticism" msgstr "Mystik" msgid "Ballistics" msgstr "Ballistik" msgid "Eagle Eye" msgstr "Falkblick" msgid "Necromancy" msgstr "Svartkonst" msgid "Estates" msgstr "Ägor" msgid "Advanced Archery" msgstr "Avancerat Skytte" msgid "Advanced Pathfinding" msgstr "Avancerad Vägvisning" msgid "Basic Archery" msgstr "Basalt Skytte" msgid "Basic Pathfinding" msgstr "Basal Vägvisning" msgid "Expert Pathfinding" msgstr "Expert Vägvisning" msgid "Advanced Logistics" msgstr "Avancerad Logistik" msgid "Basic Logistics" msgstr "Basal Logistik" msgid "Basic Scouting" msgstr "Basal Spaning" msgid "Expert Archery" msgstr "Expert Skytte" msgid "Expert Logistics" msgstr "Expert Logistik" msgid "Advanced Diplomacy" msgstr "Avancerad Diplomati" msgid "Advanced Scouting" msgstr "Avancerad Spaning" msgid "Basic Diplomacy" msgstr "Basal Diplomati" msgid "Expert Diplomacy" msgstr "Expert Diplomati" msgid "Expert Scouting" msgstr "Expert Spaning" msgid "Advanced Leadership" msgstr "Avancerat Ledarskap" msgid "Advanced Navigation" msgstr "Avancerad Navigering" msgid "Basic Leadership" msgstr "Basalt Ledarskap" msgid "Basic Navigation" msgstr "Basal Navigering" msgid "Expert Navigation" msgstr "Expert Navigation" msgid "Advanced Wisdom" msgstr "Avancerad Visdom" msgid "Basic Mysticism" msgstr "Basal Mystik" msgid "Basic Wisdom" msgstr "Basal Visdom" msgid "Expert Leadership" msgstr "Expert Ledarskap" msgid "Expert Wisdom" msgstr "Expert Visdom" msgid "Advanced Luck" msgstr "Avancerad Tur" msgid "Advanced Mysticism" msgstr "Avancerad Mystik" msgid "Basic Luck" msgstr "Basal Tur" msgid "Expert Luck" msgstr "Expert Tur" msgid "Expert Mysticism" msgstr "Expert Mystik" msgid "Advanced Ballistics" msgstr "Avancerad Ballistik" msgid "Advanced Eagle Eye" msgstr "Avancerad Falkblick" msgid "Basic Ballistics" msgstr "Basal Ballistik" msgid "Basic Eagle Eye" msgstr "Basal Falkblick" msgid "Expert Ballistics" msgstr "Expert Ballistik" msgid "Advanced Necromancy" msgstr "Avancerad Svartkonst" msgid "Basic Estates" msgstr "Basala Ägor" msgid "Basic Necromancy" msgstr "Basal Svartkonst" msgid "Expert Eagle Eye" msgstr "Expert Falkblick" msgid "Expert Necromancy" msgstr "Expert Svartkonst" msgid "Advanced Estates" msgstr "Avancerade Ägor" msgid "Expert Estates" msgstr "Expert Ägor" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} sänker hjältens förflyttningshandikapp för grov terräng med " "%{count} procent." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} tar bort hjältens förflyttningshandikapp för grov terräng." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} ökar skadan frÃ¥n hjältens skjutande varelser med %{count} procent " "och tar bort %{penalty} procent av straffet när projektiler passerar hinder, " "exempelvis borgmurar." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} ökar hjältens steg med %{count} procent." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} ökar hjältens siktradie med %{count} ruta." msgstr[1] "%{skill} ökar hjältens siktradie med %{count} rutor." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} lÃ¥ter hjälten förhandla med varelser som är svagare än dennes armé " "och sänker kapitulationskostnaden." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Uppskattningsvis sÃ¥ kan %{count} procent av varelserna välja att ansluta sig " "till hjälten." msgid "All of the creatures may offer to join the hero." msgstr "Alla varelserna kan ansluta sig till hjälten." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "%{percent} sänker kostnaden för kapitulation med %{count} procent av " "totalkostnaden för trupperna i hjältens armé." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "%{skill} ökar hjältens steg över vatten med %{count} procent." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} höjer hjältens truppers stridsmoral med %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} lÃ¥ter hjälten att lära sig %{count}:e nivÃ¥ns besvärjelser." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} lÃ¥ter hjälten att lära sig %{count}:e nivÃ¥ns besvärjelser." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} lÃ¥ter hjälten att lära sig %{count}:e nivÃ¥ns besvärjelser." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" "%{skill} Ã¥terhämtar ytterligare %{count} av hjältens besvärjelsepoäng per " "dag." msgstr[1] "" "%{skill} Ã¥terhämtar ytterligare %{count} av hjältens besvärjelsepoäng per " "dag." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} höjer hjältens tur med %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "%{skill} ökar katapultens sannolikhet att träffa och skada borgsmurar." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} ger katapulten en extra avfyrning, och varje avfyrning har en " "större chans att träffa och skada borgmurar." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} ger katapulten en extra avfyrning och varje avfyrning förstör muren " "förutom Riddarens uppgraderade borgmur." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} ger hjälten en %{count} procents chans att lära sig upp till 2:a " "nivÃ¥ns besvärjelser som kastas av fienden i strid." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} ger hjälten en %{count} procents chans att lära sig upp till 3:e " "nivÃ¥ns besvärjelser som kastas av fienden i strid." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} ger hjälten en %{count} procent schans att lära sig upp till 4:e " "nivÃ¥ns besvärjelser som kastas av fienden i strid." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} Ã¥teruppväcker %{count} procent av de stupade varelserna i strid som " "Skelett." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "Hjälten fÃ¥r %{count} guld per dag i skatteintäkter frÃ¥n sina ägor." msgid "Blue" msgstr "BlÃ¥" msgid "Green" msgstr "Grön" msgid "Red" msgstr "Röd" msgid "Yellow" msgstr "Gul" msgid "Orange" msgstr "Brandgul" msgid "Purple" msgstr "Lila" msgid "barrier|Aqua" msgstr "LjusblÃ¥" msgid "barrier|Blue" msgstr "BlÃ¥" msgid "barrier|Brown" msgstr "Brun" msgid "barrier|Gold" msgstr "Gyllene" msgid "barrier|Green" msgstr "Grön" msgid "barrier|Orange" msgstr "Brandgul" msgid "barrier|Purple" msgstr "Lila" msgid "barrier|Red" msgstr "Röd" msgid "tent|Aqua" msgstr "LjusblÃ¥tt" msgid "tent|Blue" msgstr "BlÃ¥" msgid "tent|Brown" msgstr "Brunt" msgid "tent|Gold" msgstr "Gyllene" msgid "tent|Green" msgstr "Grönt" msgid "tent|Orange" msgstr "Brandgult" msgid "tent|Purple" msgstr "Lila" msgid "tent|Red" msgstr "Rött" msgid "Experience" msgstr "Erfarenhet" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Erfarenhet lÃ¥ter hjälten öka i nivÃ¥ som höjer dennes primära och sekundära " "förmÃ¥gor." msgid "Hero/Stats" msgstr "Hjälte/Data" msgid "Skills" msgstr "FörmÃ¥gor" msgid "Town/Castle" msgstr "Stad/Slott" msgid "Garrison" msgstr "Garnison" msgid "Gold Per Day:" msgstr "Guld per Dag:" msgid "View Heroes." msgstr "Visa Hjältar." msgid "Towns/Castles" msgstr "Städer/Slott" msgid "View Towns and Castles." msgstr "Visa Städer och Slott" msgid "luck|Cursed" msgstr "Förhäxad" msgid "luck|Awful" msgstr "Fruktansvärd" msgid "luck|Bad" msgstr "DÃ¥lig" msgid "luck|Normal" msgstr "Normal" msgid "luck|Good" msgstr "Bra" msgid "luck|Great" msgstr "Fantastisk" msgid "luck|Irish" msgstr "Irländsk" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Otur drabbar ibland hjältens trupper i strid, som fÃ¥r de att bara gör " "hälften i skada." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Normal tur innebär att hjältens trupper kommer varken att fÃ¥ lyckosamma " "eller oturliga attacker." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Tursamhet lÃ¥ter hjältens trupper fÃ¥ tursamma attacker (dubbel styrka) ibland." msgid "morale|Treason" msgstr "Förräderi" msgid "morale|Awful" msgstr "Fruktansvärd" msgid "morale|Poor" msgstr "DÃ¥lig" msgid "morale|Normal" msgstr "Normal" msgid "morale|Good" msgstr "Bra" msgid "morale|Great" msgstr "Fantastisk" msgid "morale|Blood!" msgstr "Blod!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "LÃ¥g stridsmoral kan fÃ¥ hjältens trupper att lÃ¥sa sig i strid." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Neutral stridsmoral innebär att hjältens arméer aldrig kommer att bli " "välsignade eller lÃ¥sta i strid." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Hög stridsmoral kan ge hjältens trupper extra attacker i strid." msgid "Knight" msgstr "Riddare" msgid "Barbarian" msgstr "Barbar" msgid "Sorceress" msgstr "Häxa" msgid "Warlock" msgstr "Häxmästare" msgid "Wizard" msgstr "Trollkarl" msgid "Necromancer" msgstr "Svartkonstnär" msgid "Multi" msgstr "Flera" msgid "doubleLined|Knight" msgstr "Riddare" msgid "doubleLined|Barbarian" msgstr "Barbar" msgid "doubleLined|Sorceress" msgstr "Häxa" msgid "doubleLined|Warlock" msgstr "" "Häx-\n" "mästare" msgid "doubleLined|Wizard" msgstr "Trollkarl" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Svart-\n" "konstnär" msgid "doubleLinedRace|Multi" msgstr "Flera" msgid "doubleLinedRace|Random" msgstr "Slumpad" msgid "speed|Standing" msgstr "StÃ¥ende" msgid "speed|Crawling" msgstr "Krypande" msgid "speed|Very Slow" msgstr "Mkt. lÃ¥ngsam" msgid "speed|Slow" msgstr "LÃ¥ngsam" msgid "speed|Average" msgstr "Vanlig" msgid "speed|Fast" msgstr "Snabb" msgid "speed|Very Fast" msgstr "Mkt. snabb" msgid "speed|Ultra Fast" msgstr "Jättesnabb" msgid "speed|Blazing" msgstr "Blixtsnabb" msgid "speed|Instant" msgstr "Ögonblicklig" msgid "Click this button to adjust the level of zoom." msgstr "Klicka här för att justera förstoringen." msgid "Zoom" msgstr "Förstoring" msgid "week|Squirrel" msgstr "Ekorrens" msgid "week|Rabbit" msgstr "Harens" msgid "week|Gopher" msgstr "Siselns" msgid "week|Badger" msgstr "Grävlingens" msgid "week|Rat" msgstr "RÃ¥ttans" msgid "week|Eagle" msgstr "Örnens" msgid "week|Weasel" msgstr "Vesslans" msgid "week|Raven" msgstr "Korpens" msgid "week|Mongoose" msgstr "Mungons" msgid "week|Dog" msgstr "Hundens" msgid "week|Aardvark" msgstr "Jordsvinets" msgid "week|Lizard" msgstr "Ödlans" msgid "week|Tortoise" msgstr "Sköldpaddans" msgid "week|Hedgehog" msgstr "Igelkottens" msgid "week|Condor" msgstr "Kondorens" msgid "week|Ant" msgstr "Myrans" msgid "week|Grasshopper" msgstr "Gräshoppans" msgid "week|Dragonfly" msgstr "Trollsländans" msgid "week|Spider" msgstr "Spindelns" msgid "week|Butterfly" msgstr "Fjärilens" msgid "week|Bumblebee" msgstr "Humlans" msgid "week|Locust" msgstr "Vandringsgräshoppans" msgid "week|Earthworm" msgstr "Daggmaskens" msgid "week|Hornet" msgstr "BÃ¥lgetingens" msgid "week|Beetle" msgstr "Skalbaggens" msgid "week|PLAGUE" msgstr "FARSOTENS" msgid "week|Unnamed" msgstr "de Namnlösas" msgid "Desert" msgstr "Öken" msgid "Snow" msgstr "Snö" msgid "Wasteland" msgstr "Ödemark" msgid "Beach" msgstr "Strand" msgid "Lava" msgstr "Lava" msgid "Dirt" msgstr "Jord" msgid "Grass" msgstr "Gräs" msgid "Ocean" msgstr "Hav" msgid "maps|Small" msgstr "Liten" msgid "maps|Medium" msgstr "Medel" msgid "maps|Large" msgstr "Stor" msgid "maps|Extra Large" msgstr "Extrastor" msgid "maps|Custom Size" msgstr "Anpassad Storlek" msgid "Ore Mine" msgstr "Malmgruva" msgid "Sulfur Mine" msgstr "Svavelgruva" msgid "Crystal Mine" msgstr "Kristallgruva" msgid "Gems Mine" msgstr "Ädelstensgruva" msgid "Gold Mine" msgstr "Guldgruva" msgid "Mine" msgstr "Gruva" msgid "Burma shave." msgstr "LÃ¥ngbortistan" msgid "Next sign 50 miles." msgstr "Nästa skylt 50 km." msgid "See Rock City." msgstr "See Rock City." msgid "This space for rent." msgstr "Uthyres" msgid "No object" msgstr "Inget föremÃ¥l" msgid "Alchemist Lab" msgstr "Alkemistlabb" msgid "Sign" msgstr "Skylt" msgid "Buoy" msgstr "Boj" msgid "Skeleton" msgstr "Skelett" msgid "Daemon Cave" msgstr "Demongrotta" msgid "Treasure Chest" msgstr "Skattkista" msgid "Faerie Ring" msgstr "Häxring" msgid "Campfire" msgstr "Lägereld" msgid "Fountain" msgstr "Fontän" msgid "Gazebo" msgstr "Lusthus" msgid "Genie Lamp" msgstr "Andens Lampa" msgid "Archer's House" msgstr "BÃ¥gskyttens Hus" msgid "Goblin Hut" msgstr "Vätthydda" msgid "Dwarf Cottage" msgstr "Dvärgstuga" msgid "Peasant Hut" msgstr "Torp" msgid "Stables" msgstr "Stall" msgid "Alchemist's Tower" msgstr "Alkemistens Torn" msgid "Event" msgstr "Händelse" msgid "Dragon City" msgstr "Drakstad" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Fyr" msgstr[1] "Fyrar" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Vattenkvarn" msgstr[1] "Vattenkvarnar" msgid "Monster" msgstr "Varelse" msgid "Obelisk" msgstr "Obelisk" msgid "Oasis" msgstr "Oas" msgid "Resource" msgstr "Resurs" msgid "Sawmill" msgstr "SÃ¥gverk" msgid "Oracle" msgstr "Orakel" msgid "Shrine of the First Circle" msgstr "Första kretsens Helgedom" msgid "Shipwreck" msgstr "Skeppsvrak" msgid "Sea Chest" msgstr "Sjökista" msgid "Desert Tent" msgstr "Ökentält" msgid "Stone Liths" msgstr "Stenstoder" msgid "Wagon Camp" msgstr "Godsvagnläger" msgid "Hut of the Magi" msgstr "De vise männens stuga" msgid "Whirlpool" msgstr "Strömvirvel" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Väderkvarn" msgstr[1] "Väderkvarnar" msgid "Mermaid" msgstr "Sjöjungfru" msgid "Boat" msgstr "Skepp" msgid "Random Ultimate Artifact" msgstr "Slumpad Ultimat artefakt" msgid "Random Artifact" msgstr "Slumpad Artefakt" msgid "Random Resource" msgstr "Slumpad Resurs" msgid "Random Monster" msgstr "Slumpad Varelse" msgid "Random Town" msgstr "Slumpad Stad" msgid "Random Castle" msgstr "Slumpat Slott" msgid "Eye of the Magi" msgstr "De vise männens öga" msgid "Random Monster - weak" msgstr "Slumpad Varelse - svag" msgid "Random Monster - medium" msgstr "Slumpad Varelse - medel" msgid "Random Monster - strong" msgstr "Slumpad Varelse - starkt" msgid "Random Monster - very strong" msgstr "Slumpad Varelse - väldigt starkt" msgid "Hero" msgstr "Hjälte" msgid "Nothing Special" msgstr "Ingenting Speciellt" msgid "Mossy Rock" msgstr "Mossigt Stenblock" msgid "Watch Tower" msgstr "Vakttorn" msgid "Tree House" msgstr "Trädhus" msgid "Tree City" msgstr "Trädstad" msgid "Ruins" msgstr "Ruiner" msgid "Fort" msgstr "Fort" msgid "Abandoned Mine" msgstr "Övergiven gruva" msgid "Sirens" msgstr "Sirener" msgid "Standing Stones" msgstr "Stenblock" msgid "Idol" msgstr "Avgud" msgid "Tree of Knowledge" msgstr "Kunskapens Träd" msgid "Witch Doctor's Hut" msgstr "Häxdoktorns Hydda" msgid "Temple" msgstr "Tempel" msgid "Hill Fort" msgstr "Fornborg" msgid "Halfling Hole" msgstr "HobhÃ¥la" msgid "Mercenary Camp" msgstr "Legosoldatsläger" msgid "Shrine of the Second Circle" msgstr "Andra kretsens Helgedom" msgid "Shrine of the Third Circle" msgstr "Tredje kretsens Helgedom" msgid "City of the Dead" msgstr "Dödens Stad" msgid "Sphinx" msgstr "Sfinx" msgid "Wagon" msgstr "Godsvagn" msgid "Tar Pit" msgstr "TjärhÃ¥la" msgid "Artesian Spring" msgstr "Artesisk Källa" msgid "Troll Bridge" msgstr "Trollbro" msgid "Watering Hole" msgstr "VattenhÃ¥l" msgid "Witch's Hut" msgstr "Häxhydda" msgid "Xanadu" msgstr "Xanadu" msgid "Lean-To" msgstr "Vindskydd" msgid "Magellan's Maps" msgstr "Magellans Kartor" msgid "Flotsam" msgstr "Vrakgods" msgid "Derelict Ship" msgstr "Övergivet Skepp" msgid "Shipwreck Survivor" msgstr "Skeppsbruten Överlevare" msgid "Bottle" msgstr "Flaska" msgid "Magic Well" msgstr "Magisk Brunn" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Förtrollad TrädgÃ¥rd" msgstr[1] "Förtrollade TrädgÃ¥rdar" msgid "Observation Tower" msgstr "Observationstorn" msgid "Freeman's Foundry" msgstr "Hedersmedborgarnas gjuteri" msgid "Reefs" msgstr "Rev" msgid "Volcano" msgstr "Vulkan" msgid "Flowers" msgstr "Blommor" msgid "Rock" msgstr "Sten" msgid "Water Lake" msgstr "Sjö" msgid "Mandrake" msgstr "Alruna" msgid "Dead Tree" msgstr "Dött Träd" msgid "Stump" msgstr "Stubbe" msgid "Crater" msgstr "Krater" msgid "Cactus" msgstr "Kaktus" msgid "Mound" msgstr "Kulle" msgid "Dune" msgstr "Dyn" msgid "Lava Pool" msgstr "Lavapöl" msgid "Shrub" msgstr "Buske" msgid "Barrow Mounds" msgstr "Gravhög" msgid "Random Artifact - Treasure" msgstr "Slumpad Artefakt - Skatt" msgid "Random Artifact - Minor" msgstr "Slumpad Artefakt - Liten" msgid "Random Artifact - Major" msgstr "Slumpad Artefakt - Stor" msgid "Barrier" msgstr "Barriär" msgid "Traveller's Tent" msgstr "Resenärstält" msgid "Jail" msgstr "Fängelse" msgid "Fire Summoning Altar" msgstr "Eldaltare" msgid "Air Summoning Altar" msgstr "Luftaltare" msgid "Earth Summoning Altar" msgstr "Jordaltare" msgid "Water Summoning Altar" msgstr "Vattenaltare" msgid "Swampy Lake" msgstr "Träsksjö" msgid "Frozen Lake" msgstr "Frusen Sjö" msgid "randomRace|level 1 creatures" msgstr "nivÃ¥ 1 varelser" msgid "randomRace|level 2 creatures" msgstr "nivÃ¥ 2 varelser" msgid "randomRace|level 3 creatures" msgstr "nivÃ¥ 3 varelser" msgid "randomRace|level 4 creatures" msgstr "nivÃ¥ 4 varelser" msgid "randomRace|level 5 creatures" msgstr "nivÃ¥ 5 varelser" msgid "randomRace|level 6 creatures" msgstr "nivÃ¥ 6 varelser" msgid "Unknown Monsters" msgstr "Okända Varelser" msgid "Unknown Monster" msgstr "Okänd Varelse" msgid "Peasant" msgstr "Bonde" msgid "Peasants" msgstr "Bönder" msgid "Archer" msgstr "BÃ¥gskytt" msgid "Archers" msgstr "BÃ¥gskyttar" msgid "Ranger" msgstr "Vandringsman" msgid "Rangers" msgstr "Vandringsmän" msgid "Pikeman" msgstr "Pikenerare" msgid "Pikemen" msgstr "Pikenerare" msgid "Veteran Pikeman" msgstr "Veteranpikenerare" msgid "Veteran Pikemen" msgstr "Veteranpikenerare" msgid "Swordsman" msgstr "Svärdsman" msgid "Swordsmen" msgstr "Svärdsmän" msgid "Master Swordsman" msgstr "Mästersvärdsman" msgid "Master Swordsmen" msgstr "Mästersvärdsmän" msgid "Cavalries" msgstr "Kavallerister" msgid "Cavalry" msgstr "Kavalleri" msgid "Champion" msgstr "Lansiär" msgid "Champions" msgstr "Lansiärer" msgid "Paladin" msgstr "Paladin" msgid "Paladins" msgstr "Paladiner" msgid "Crusader" msgstr "Korsfarare" msgid "Crusaders" msgstr "Korsfarare" msgid "Goblin" msgstr "Vätte" msgid "Goblins" msgstr "Vättar" msgid "Orc" msgstr "Orch" msgid "Orcs" msgstr "Orcher" msgid "Orc Chief" msgstr "Orchhövding" msgid "Orc Chiefs" msgstr "Orchhövdingar" msgid "Wolf" msgstr "Varg" msgid "Wolves" msgstr "Vargar" msgid "Ogre" msgstr "Jätte" msgid "Ogres" msgstr "Jättar" msgid "Ogre Lord" msgstr "Jättehövding" msgid "Ogre Lords" msgstr "Jättehövdingar" msgid "Troll" msgstr "Troll" msgid "Trolls" msgstr "Troll" msgid "War Troll" msgstr "Krigstroll" msgid "War Trolls" msgstr "Krigstroll" msgid "Cyclopes" msgstr "Cykloper" msgid "Cyclops" msgstr "Cyklop" msgid "Sprite" msgstr "Fé" msgid "Sprites" msgstr "Féer" msgid "Dwarf" msgstr "Dvärg" msgid "Dwarves" msgstr "Dvärgar" msgid "Battle Dwarf" msgstr "Stridsdvärgar" msgid "Battle Dwarves" msgstr "Stridsdvärgar" msgid "Elf" msgstr "Alv" msgid "Elves" msgstr "Alver" msgid "Grand Elf" msgstr "Ärkealv" msgid "Grand Elves" msgstr "Ärkealver" msgid "Druid" msgstr "Druid" msgid "Druids" msgstr "Druider" msgid "Greater Druid" msgstr "Mästerdruid" msgid "Greater Druids" msgstr "Mästerdruider" msgid "Unicorn" msgstr "Enhörning" msgid "Unicorns" msgstr "Enhörningar" msgid "Phoenix" msgstr "Fenix" msgid "Phoenixes" msgstr "Fenixar" msgid "Centaur" msgstr "Kentaur" msgid "Centaurs" msgstr "Kentaurer" msgid "Gargoyle" msgstr "Stenstaty" msgid "Gargoyles" msgstr "Stenstatyer" msgid "Griffin" msgstr "Grip" msgid "Griffins" msgstr "Gripar" msgid "Minotaur" msgstr "Minotaur" msgid "Minotaurs" msgstr "Minotaurer" msgid "Minotaur King" msgstr "Minotaurkung" msgid "Minotaur Kings" msgstr "Minotaurkungar" msgid "Hydra" msgstr "Hydra" msgid "Hydras" msgstr "Hydror" msgid "Green Dragon" msgstr "Grön Drake" msgid "Green Dragons" msgstr "Gröna Drakar" msgid "Red Dragon" msgstr "Röd Drake" msgid "Red Dragons" msgstr "Röda Drakar" msgid "Black Dragon" msgstr "Svart Drake" msgid "Black Dragons" msgstr "Svarta Drakar" msgid "Halfling" msgstr "Hob" msgid "Halflings" msgstr "Hober" msgid "Boar" msgstr "Vildsvin" msgid "Boars" msgstr "Vildsvin" msgid "Iron Golem" msgstr "Järngolem" msgid "Iron Golems" msgstr "Järngolem" msgid "Steel Golem" msgstr "StÃ¥lgolem" msgid "Steel Golems" msgstr "StÃ¥lgolem" msgid "Roc" msgstr "RocfÃ¥gel" msgid "Rocs" msgstr "RocfÃ¥glar" msgid "Mage" msgstr "Magiker" msgid "Magi" msgstr "Magiker" msgid "Archmage" msgstr "Ärkemagiker" msgid "Archmagi" msgstr "Ärkemagiker" msgid "Giant" msgstr "Koloss" msgid "Giants" msgstr "Kolosser" msgid "Titan" msgstr "Titan" msgid "Titans" msgstr "Titaner" msgid "Skeletons" msgstr "Skelett" msgid "Zombie" msgstr "Zombie" msgid "Zombies" msgstr "Zombier" msgid "Mutant Zombie" msgstr "Mutantzombie" msgid "Mutant Zombies" msgstr "Mutantzombier" msgid "Mummies" msgstr "Mumier" msgid "Mummy" msgstr "Mumie" msgid "Royal Mummies" msgstr "Kungsmumier" msgid "Royal Mummy" msgstr "Kungsmumie" msgid "Vampire" msgstr "Vampyr" msgid "Vampires" msgstr "Vampyrer" msgid "Vampire Lord" msgstr "Vampyrbaron" msgid "Vampire Lords" msgstr "Vampyrbaroner" msgid "Lich" msgstr "Lich" msgid "Liches" msgstr "Licher" msgid "Power Lich" msgstr "Ärkelich" msgid "Power Liches" msgstr "Ärkelichar" msgid "Bone Dragon" msgstr "Bendrake" msgid "Bone Dragons" msgstr "Bendrakar" msgid "Rogue" msgstr "Rövare" msgid "Rogues" msgstr "Rövare" msgid "Nomad" msgstr "Nomad" msgid "Nomads" msgstr "Nomader" msgid "Ghost" msgstr "Spöke" msgid "Ghosts" msgstr "Spöken" msgid "Genie" msgstr "Ande" msgid "Genies" msgstr "Andar" msgid "Medusa" msgstr "Medusa" msgid "Medusas" msgstr "Medusor" msgid "Earth Elemental" msgstr "Jordväsen" msgid "Earth Elementals" msgstr "Jordväsen" msgid "Air Elemental" msgstr "Luftväsen" msgid "Air Elementals" msgstr "Luftväsen" msgid "Fire Elemental" msgstr "Eldväsen" msgid "Fire Elementals" msgstr "Eldväsen" msgid "Water Elemental" msgstr "Vattenväsen" msgid "Water Elementals" msgstr "Vattenväsen" msgid "Random Monsters" msgstr "Slumpade Varelser" msgid "Random Monster 1" msgstr "Slumpad Varelse 1" msgid "Random Monsters 1" msgstr "Slumpade Varelser 1" msgid "Random Monster 2" msgstr "Slumpad Varelse 2" msgid "Random Monsters 2" msgstr "Slumpade Varelser 2" msgid "Random Monster 3" msgstr "Slumpad Varelse 3" msgid "Random Monsters 3" msgstr "Slumpade Varelser 3" msgid "Random Monster 4" msgstr "Slumpad Varelse 4" msgid "Random Monsters 4" msgstr "Slumpade Varelser 4" msgid "Double shot" msgstr "Dubbel avfyrning" msgid "2-hex monster" msgstr "Stor varelse" msgid "Double strike" msgstr "Dubbelslag" msgid "Double damage to Undead" msgstr "Dubbel skada till Odöda" msgid "% magic resistance" msgstr "% besvärjelseresistens" msgid "Immune to Mind spells" msgstr "Immun mot Sinnesbesvärjelser" msgid "Immune to Elemental spells" msgstr "Immun mot Elementbesvärjelser" msgid "Immune to Fire spells" msgstr "Immun mot Eldbesvärjelser" msgid "Immune to Cold spells" msgstr "Immun mot Köldbesvärjelser" msgid "Immune to " msgstr "Immun mot " msgid "% immunity to %{spell} spell" msgstr "% resistens mot %{spell}besvärjelse" msgid "% damage from Elemental spells" msgstr "% skada frÃ¥n Elementbesvärjelser" msgid "% damage from %{spell} spell" msgstr "% skada frÃ¥n %{spell}besvärjelse" msgid "% chance to Dispel beneficial spells" msgstr "% chans att Skingra godartade besvärjelser" msgid "% chance to Paralyze" msgstr "% chans att Paralysera" msgid "% chance to Petrify" msgstr "% chans att Förstena" msgid "% chance to Blind" msgstr "% chans att Förblinda" msgid "% chance to Curse" msgstr "% chans att kasta Förbannelse" msgid "% chance to cast %{spell} spell" msgstr "% chans att kasta %{spell}besvärjelse" msgid "HP regeneration" msgstr "HälsoÃ¥terhämtning" msgid "Two hexes attack" msgstr "TvÃ¥-rutsanfall" msgid "Flyer" msgstr "Flygare" msgid "Always retaliates" msgstr "Vedergäller alltid" msgid "Attacks all adjacent enemies" msgstr "Anfaller alla närliggande fiender" msgid "No melee penalty" msgstr "Inget närstridshandikapp" msgid "Dragon" msgstr "Drake" msgid "Undead" msgstr "Odöd" msgid "No enemy retaliation" msgstr "Ingen fiendevedergällning" msgid "HP drain" msgstr "Suger hälsopoäng" msgid "Cloud attack" msgstr "Molnattack" msgid "Decreases enemy's morale by " msgstr "Sänker fiendens stridmoral med " msgid "% chance to halve enemy" msgstr "% chans att halvera fienden" msgid "Soul Eater" msgstr "Själslukare" msgid "Elemental" msgstr "Elementande" msgid "No Morale" msgstr "Ingen Stridsmoral" msgid "Earth creature" msgstr "Jordvarelse" msgid "Air creature" msgstr "Luftvarelse" msgid "Fire creature" msgstr "Eldvarelse" msgid "Water creature" msgstr "Vattenvarelse" msgid "Double damage from Fire spells" msgstr "Dubbel skada frÃ¥n Eldbesvärjelser" msgid "Double damage from Cold spells" msgstr "Dubbel skada frÃ¥n Köldbesvärjelser" msgid "Double damage from Earth creatures" msgstr "Dubbel skada frÃ¥n Jordvarelser" msgid "Double damage from Air creatures" msgstr "Dubbel skada frÃ¥n Luftvarelser" msgid "Double damage from Fire creatures" msgstr "Dubbel skada frÃ¥n Eldvaralser" msgid "Double damage from Water creatures" msgstr "Dubbel skada frÃ¥n Vattenvarelser" msgid "Lightning" msgstr "Blixt" msgid "% immunity to " msgstr "% resistens mot " msgid "% damage from " msgstr "% skada frÃ¥n " msgid "The three Anduran artifacts magically combine into one." msgstr "De tre Anduranartefakterna kombineras magiskt till en." msgid "View Spells" msgstr "Visa Besvärjelser" msgid "View %{name} Info" msgstr "Visa %{name}information" msgid "Move %{name}" msgstr "Flytta %{name}" msgid "Cannot move the Spellbook" msgstr "Kan inte flytta Magibok" msgid "This item can't be traded." msgstr "Detta föremÃ¥l kan inte bytas." msgid "Invalid Artifact" msgstr "Ogiltig Artefakt" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} ökar hjältens Kunskap med %{count}." msgid "Ultimate Book of Knowledge" msgstr "Främsta Kunskapsboken" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} höjer hjältens Anfall med %{count}." msgid "Ultimate Sword of Dominion" msgstr "Främsta Herraväldessvärdet" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} höjer hjältens Försvar med %{count}." msgid "Ultimate Cloak of Protection" msgstr "Främsta Skyddsmanteln" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} höjer hjältens Trollkonst med %{count}." msgid "Ultimate Wand of Magic" msgstr "Främsta Trollstaven" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} höjer hjältens Anfall- och Försvar med %{count} vardera." msgid "Ultimate Shield" msgstr "Främsta Skölden" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} höjer hjältens Trollkonst och Kunskap med %{count} vardera." msgid "Ultimate Staff" msgstr "Främsta Staven" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} höjer alla av hjältens primära förmÃ¥gor med %{count}." msgid "Ultimate Crown" msgstr "Främsta Kronan" msgid "Golden Goose" msgstr "Gyllene GÃ¥sen" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} inbringar en intäkt pÃ¥ %{count} guld per dag." msgid "Arcane Necklace of Magic" msgstr "Mystiskt Halsband" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Efter att ha räddat en Häxa ur en förbannad gravkista, belönar hon ditt " "hjältemod med ett utsökt juvelhalsband." msgid "Caster's Bracelet of Magic" msgstr "Besvärjarens Armband" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "När du genomsöker brÃ¥te vid en inrasad gruva, finner du en grupp Dvärgar som " "du räddar. Tacksam för din hjälp, ger dess ledare ett armband av guld." msgid "Mage's Ring of Power" msgstr "Trollkarlens Ring" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Ett plÃ¥gsamt rop leder dig till en kentaur, infÃ¥ngad i en fälla. När du " "släpper lös kentauren, räcker han dig en liten pung. Inuti hittar du en " "skimrande juvelring." msgid "Witch's Broach of Magic" msgstr "Magisk Häxbrosch" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "I askan av en bränd häxa ligger en vacker brosch oskadad av elden. Du lägger " "till den till din samling." msgid "Medal of Valor" msgstr "Tapperhetsmedalj" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} höjer hjältens armés stridsmoral med %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Genom fritagandet av en dygdig ungmö frÃ¥n en ond ärkeskurks fÃ¥ngenskap sÃ¥ " "blir du tilldelad en Tapperhetsmedalj av konungens härold." msgid "Medal of Courage" msgstr "Djärvhetsmedalj" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Efter att ha räddat en pojke frÃ¥n en flock glupska Vargar lämnar du av honom " "vid hans fars ägor. Den tacksamma adelsmannen tilldelar dig en " "Djärvhetsmedalj." msgid "Medal of Honor" msgstr "Hedersmedalj" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Efter att ha räddat en prinsessa frÃ¥n klorna av avskyvärda slavhandlare, sÃ¥ " "ger hon dig en Hedersmedalj." msgid "Medal of Distinction" msgstr "Utmärkelsemedalj" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Efter att ta rensat bygden frÃ¥n en hemsk minotaur som hade för vana att äta " "adelns riddare, blir du hedrad med en Utmärkelsemedalj." msgid "Fizbin of Misfortune" msgstr "Olycksfizbin" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} minskar kraftigt hjältens armés stridsmoral med %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Du fÃ¥r förbi en medalj som ligger bredvid vägen du gÃ¥r pÃ¥. Du plockar upp " "den och lägger den till din samling. Du inser att du precis plockat pÃ¥ dig " "den oönskade Olycksfizbin, som gravt sänker din armés stridsmoral." msgid "Thunder Mace of Dominion" msgstr "Ã…skans Stridsgissel" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Under ett plötsligt oväder sÃ¥ slÃ¥r en blixt ner i ett träd och delar det " "mitt i tu. Inuti trädet finner du ett mystiskt stridsgissel." msgid "Armored Gauntlets of Protection" msgstr "Skyddstridshandskar" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} ökar hjältens Försvar med %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Du stöter pÃ¥ den ökända Svarta Riddaren! Efter en ansträngande duell som " "slutar oavgjort, sÃ¥ skänker dig Riddaren sina Skyddstridshandskar utav " "respekt för bra duell." msgid "Defender Helm of Protection" msgstr "Livgardets Skyddshjälm" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "NÃ¥gonting glimmar till i ett tätt buskage. Vid närmare inspektion hittar du " "en gyllene hjälm glömd under busken." msgid "Giant Flail of Dominion" msgstr "Jättens Stridsgissel" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "En klumpig Jätte träffar sig själv i huvudet med sitt stridsgissel och " "faller ner död. Med dina överlägsna kunskaper i stridskonst sÃ¥ är du säker " "pÃ¥ att du kan hantera det mycket bättre. Du lossar gisslet som fastnat i " "Jättens huvud och provsvingar det lite." msgid "Ballista of Quickness" msgstr "Snabbhetens Ballist" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "%{name} lÃ¥ter hjälten att avfyra katapulten tvÃ¥ gÃ¥nger per runda." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Du vandrar runt i ruinerna av en urÃ¥ldrig stad med en förstörd ringmur. Du " "hittar svaret till stadens ödeläggelse, en intrikat konstruerad ballist." msgid "Stealth Shield of Protection" msgstr "Skyddssköld" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Du stöter pÃ¥ en stenstaty föreställande en krigare med en silversköld. När " "du tar skölden frÃ¥n statyn sÃ¥, rasar statyn ihop till grus och damm." msgid "Dragon Sword of Dominion" msgstr "Draksvärd" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "När du gÃ¥r längs med en smal stig sÃ¥ fattar plötsligt en buske i närheten " "eld. Inför dina ögon sÃ¥ tar eldflammorna formen av en vacker kvinna. Hon " "hÃ¥ller fram ett fint svärd Ã¥t dig." msgid "Power Axe of Dominion" msgstr "Kraftyxa" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Du ser en silveryxa djupt nergrävd i marken. Efter mÃ¥nga misslyckade försök " "av din armé att ta yxan, sÃ¥ försöker du själv ta den. Ett stadigt tag kring " "skaftet och utan ansträngning sÃ¥ drar du loss den." msgid "Divine Breastplate of Protection" msgstr "Gudomlig Bröstharnesk" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Ett gäng med Rövare söker igenom tillhörigheterna pÃ¥ nÃ¥gra döda krigare. Du " "skrämmer bort plundrarna och ser att Rövarna har missat en vacker glänsande " "bröstharnesk." msgid "Minor Scroll of Knowledge" msgstr "Mindre Kunskapsrulle" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Framför dig uppenbarar sig en svävande glaslÃ¥da pÃ¥ en mörkröd sammetskudde. " "Inuti glaslÃ¥dan finns en rulle. När du rör vid den sÃ¥ öppnar sig lÃ¥dan och " "rullen svävar genom luften och ner i dina händer." msgid "Major Scroll of Knowledge" msgstr "Större Kunskapsrulle" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Du besöker en lokal vis Ã¥ldersman som du förklarar syftet med dina resor. " "Han tar fram en gulblekt rulle ur en säck och ger den till dig." msgid "Superior Scroll of Knowledge" msgstr "Överordnad Kunskapsrulle" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Du gÃ¥r förbi lämningarna av en gammal Druid. Benen, gulnande av Ã¥lder, " "sticker ut genom resterna av hennes gamla kappa. Du söker igenom kappan och " "du finner en rulle med inskriptioner." msgid "Foremost Scroll of Knowledge" msgstr "Särskild Kunskapsrulle" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Vittrade ben, gulblekta av tidens tand sticker upp ut ur lämningarna av en " "död Druids kappa. Vid genomsökning av kappan finner du en besvärjelserulle." msgid "Endless Sack of Gold" msgstr "Bottenlös Guldsäck" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} förser hjälten med %{count} guld per dag." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "En liten pyssling dansar glatt kring en magisk säck. När han upptäcker dig, " "stannar han mitt i sin rörelse. Han skriker och stampar till med sin fot och " "försvinner upp i rök. Du minns det gamla pysslingsordsprÃ¥ket \"Funnet är " "vunnet\" och tar säcken och gÃ¥r." msgid "Endless Bag of Gold" msgstr "Bottenlös Guldväska" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "En adelskvinna som har kommit ifrÃ¥n sitt följe ber dig om din hjälp. Du " "eskorterar henne hem och hon belönar dig med en säck fylld med guld." msgid "Endless Purse of Gold" msgstr "Bottenlös Guldbörs" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Under dina resor sÃ¥ finner du en läderbörs fylld med guld. Den ägdes en gÃ¥ng " "i tiden av en stor Krigsherre som hade förmÃ¥gan att förvandla ting till det " "renaste guld." msgid "Nomad Boots of Mobility" msgstr "Nomadens Kängor" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} ökar hjältens förflyttning pÃ¥ mark." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "En handelsresande söker skydd frÃ¥n en stam med Vättar. För din hjälp ger han " "dig ett par fint sydda kängor gjorda av det mjukaste läder. Vid en närmare " "titt sÃ¥ ser du fascinerande urÃ¥ldriga inskriptioner pÃ¥ lädret." msgid "Traveler's Boots of Mobility" msgstr "Vandrarens Kängor" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Du fÃ¥r att par vackert sydda kängor gjorda av de finaste och mjukaste läder " "av en främmande man, innan du hinner tacka för gÃ¥van har mannen gett sig av." msgid "Lucky Rabbit's Foot" msgstr "Hartass" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} ökar hjältens armés Tur med %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "En handelsresande erbjuder dig en hartass av skimrande silverpäls för ditt " "skydd en passage. Handelsmannen förklarar att berlocken kommer ge dig tur i " "strid." msgid "Golden Horseshoe" msgstr "Gyllene Hästsko" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "En fastsnarad Enhörning gnäggar av fruktan. Med en lugnande röst sÃ¥ släpper " "du enhörningen fri. Enhörningen frustar och stampar med ena framhoven en " "gÃ¥ng innan den rusar iväg. Du blickar ner och ser en gyllende hästsko ligga " "pÃ¥ marken." msgid "Gambler's Lucky Coin" msgstr "Spelarens Turmynt" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Du har fÃ¥ngat en lilldjävul som har terroriserat regionen. I utbyte mot " "lilldjävulens frihet sÃ¥ erbjuder han dig ett förtrollat mynt." msgid "Four-Leaf Clover" msgstr "Fyrklöver" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "I mitten av en fläck med torr och död vegetation, sÃ¥ hittar du ett ensamt " "litet grönt och fint fyrklöver." msgid "True Compass of Mobility" msgstr "Mobilitetens Kompass" msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} ökar hjältens förflyttningskapacitet pÃ¥ bÃ¥de land och hav." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "En gammal man som pÃ¥stÃ¥r sig vara en uppfinnare, frÃ¥gar dig om du vill pröva " "hans senaste mackapär. Sen ger han dig en kompass." msgid "Sailor's Astrolabe of Mobility" msgstr "Seglarens mobila astrolabium" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} ökar hjältens förflyttning pÃ¥ havet." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "En gammal sjökapten blir torterad av nÃ¥gra Jättar. Du räddar honom och han " "belönar dig med ett fantastiskt instrument som kan mäta avstÃ¥ndet mellan " "stjärnor." msgid "Evil Eye" msgstr "Onda Ögat" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} sänker besvärjelsekostnaden för Förbannelser till hälften." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "När du träder i in i en skröplig stuga sÃ¥ finner du ett skelett frÃ¥n en " "sedan länge avliden häxa. Vid genomsökning av kvarlevorna hittar du ett " "glasöga som rullar runt inuti en skalle." msgid "Enchanted Hourglass" msgstr "Förtrollat Timglas" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} förlänger hjältens besvärjelsers varaktighet med %{count} rundor." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Plötsligt stöter du pÃ¥ en makaber scen: Gamar som hackar pÃ¥ resterna av en " "brutal strid. Vid en snabb genomsökning av resterna finner du ett förtrollat " "timglas." msgid "Gold Watch" msgstr "Guldklocka" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "" "%{name} fördubblar effektiviteten för hjältens Hynotiseringsbesvärjelser." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Som belöning för att hjälpt en kvacksalvande handelsmans kärra ut ur diket, " "ger han dig en \"förtrollad\" guldklocka. Han verkar dock inte inse att " "klockan faktiskt är förtrollad." msgid "Skullcap" msgstr "Hätta" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "%{name} halverar besvärjelsekostnaden för alla Sinnesbesvärjelser." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Vid ett kort stopp vid ett osannolikt gästgiveri byts det guld, historier " "och baggage. Du hittar en magisk hätta i din nya ryggsäck." msgid "Ice Cloak" msgstr "Ismantel" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "%{name} halverar skadan hjältens trupper fÃ¥r frÃ¥n Köldbesvärjelser." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Du hörsammar de panikartade ropen frÃ¥n en dam i nöd och finner en ung kvinna " "flyendes frÃ¥n en hungrig björn. Du dräper besten i sista stund och den " "tacksamma Häxan syr en magisk kappa frÃ¥n björnens fäll." msgid "Fire Cloak" msgstr "Eldmantel" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "%{name} halverar skadan hjältens trupper fÃ¥r frÃ¥n Eldbesvärjelser." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Du stöter pÃ¥ en strid mellan en Svartkonstnär och en Paladin. " "Svartkonstnären blästrar paladinen med ett eldklot och fÃ¥r honom pÃ¥ knä. " "Genom snabbt agerande sÃ¥ hugger du huvudet av svartkonstnären innan denne " "hinner dräpa Paladinen. Den tacksamme Paladinen ger dig hans Eldmantel som " "skyddade honom under striden." msgid "Lightning Helm" msgstr "Blixthjälm" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "%{name} halverar skadan hjältens trupper fÃ¥r frÃ¥n Blixtbesvärjelser." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "En gÃ¥rdsfarihandlare i nöd erbjuder dig en hjälm utsmyckad men en blixt i " "utbyte mot mat och vatten. Nyfiken sÃ¥ antar du budet och finner senare att " "hjälmen är förtrollad." msgid "Evercold Icicle" msgstr "Osmältbar Istapp" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} fÃ¥r hjältens köldbesvärjelser att göra %{count} procent mer skada " "till fiendetrupper." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "En istapp fÃ¥ngar ditt intresse, den verkar helt kunna motstÃ¥ " "eftermiddagsolens strÃ¥lar. Du bryter loss den och den verkar inte heller " "smälta frÃ¥n värmen i din hand." msgid "Everhot Lava Rock" msgstr "SkÃ¥llhet Lavasten" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} fÃ¥r hjältens eldbesvärjelser att orsaka %{count} procent mer skada " "till fiendetrupper." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Genom dina strövtÃ¥g sÃ¥ kommer du i kontakt med en klan av aplika varelser " "som använder sig av en aldrig avsvalnande lavasten för att göra upp eld. Du " "känner sympati för varelserna och lär dem att göra upp eld med hjälp av " "pinnar. I tron av att du är en gud sÃ¥ ger de dig sin sten." msgid "Lightning Rod" msgstr "Blixtstav" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} fÃ¥r hjältens blixtbesvärjelser att göra %{count} procent mer skada " "till fiendetrupper." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Väntandes ut en storm, sÃ¥ slÃ¥r en blixt ner i en närliggande stugas " "Ã¥skledare som smälter och faller till marken. Ã…skledarens topp är dock " "intakt och fÃ¥r ditt hÃ¥r att resa sig när du rör vid den. Hmm..." msgid "Snake-Ring" msgstr "Ormring" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name}en halverar kostnaden för alla hjältens välsignelsebesvärjelser." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Du hittar en annorlunda ring pÃ¥ ett fingerben av en för längesedan avliden " "äventyrare. Ringen har formen av en orm som biter sin egen svans." msgid "Ankh" msgstr "Ankh" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} dubblar styrkan för hjältens Ã…terupplivnings och Animera Död-" "besvärjelser." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "En kraftig storm uppenbarar en ingÃ¥ng till en gravkammare. Vid din " "undersökning av gravkammaren visar dig att den redan är plundrad, men " "plundrarna har glömt ett ankhkors hängades pÃ¥ en silverkedja i mörkret." msgid "Book of Elements" msgstr "Elementbok" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} dubblerar styrkan för hjältens Framkallningsbesvärjelser." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Du möter en trollkarl som ber dig om ditt beskydd för ett tag. Du gÃ¥r med pÃ¥ " "att ge honom skydd och han erbjuder sig att ge dig en kopia av Elementboken." msgid "Elemental Ring" msgstr "Elementring" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "%{name} halverar kostnaden för Framkallningsbesvärjelser." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Vid en rast ser du ett lodjur som klättrar i ett träd i ett försök att nÃ¥ " "ett krÃ¥kbo. Impulsivt sÃ¥ klättrar du själv upp i trädet och skrämmer bort " "lodjuret. När du blickar ner i krÃ¥kboet sÃ¥ finner du en liten samling " "glänsande stenar och en ring." msgid "Holy Pendant" msgstr "Heligt Hängsmycke" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} gör hjältens trupper immuna mot Förbannelsebesvärjelser." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Genom dina resor stöter du pÃ¥ en eremit som lever i en liten prydlig stuga. " "Imponerad av ditt uppdrag sÃ¥ ger han dig en amulett som skydd mot " "förbannelser och fortsätter sedan att meditera." msgid "Pendant of Free Will" msgstr "Fria Viljans Hängsmycke" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "%{name} gör hjältens trupper immuna mot Hynotiseringsbesvärjelser." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Vid svar pÃ¥ ett rop pÃ¥ hjälp, finner du nÃ¥gra älvféer som har som nöje att " "dränka en gammal herre. Vredgad sÃ¥ räddar du mannen och drar upp en fé pÃ¥ " "torra land. Féen känner sig obekväm pÃ¥ fast mark och ger dig ett magiskt " "hängsmycke om du släpper den fri." msgid "Pendant of Life" msgstr "Livsmycke" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name}t gör hjältens trupper immuna mot Dödsbesvärjelser." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Vid ett hastigt möte med en liten karavan sÃ¥ deltar du i ett parti tärning. " "Vinnaren fÃ¥r ett förtrollat smycke. Du vinner och den trumpne tidigare " "ägaren berättar att det skyddar mot svartkonstnärernas dödsbesvärjelser." msgid "Serenity Pendant" msgstr "Stillhetens Hängsmycke" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name}t gör hjältens trupper immuna mot Bärsärkbesvärjelser." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Ljudet frÃ¥n en strid söker dig till en strid mellan en gammal Barbar och en " "Ã¥ttahövdad hydra. Du ingriper till Barbarens favör och han belönar dig med " "ett hängsmycke som han brukar använda innan strid för att lugna sitt inre." msgid "Seeing-eye Pendant" msgstr "Seende Hängsmycke" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name}t gör hjältens trupper immuna mot Förblindningsbesvärjelser." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Du stöter pÃ¥ en mycket Ã¥lderstigen tant, sedan länge blind av grÃ¥starr och " "levandes sina sista dagar. Du hjälper henne med nÃ¥gra bestyr och lovar henne " "en riktig begravning. Tacksam sÃ¥ ger hon dig ett magiskt hängsmycke, " "dekorerat med ett stiliserat öga. Det lÃ¥ter dig se med dina ögon stängda." msgid "Kinetic Pendant" msgstr "Kinematiskt Hängsmycke" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "%{name}t gör hjältens trupper immuna mot Paralyseringsbesvärjelser." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Du stöter pÃ¥ en Golem bärandes ett lysande hängsmycke som blockerar din väg. " "Instinktivt sÃ¥ slÃ¥r du av smycket frÃ¥n dess nacke. I avsaknad frÃ¥n kraften " "frÃ¥n smycket sÃ¥ ramlar Golemen ner till grus och stoft. Du plockar pÃ¥ dig " "smycket." msgid "Pendant of Death" msgstr "Dödssmycke" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name}t gör hjältens trupper immuna mot Heliga besvärjelser." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Efter en snabb och dödlig batalj med en Svartkonstnär sÃ¥ tar du hans " "hängsmycke. Senare sÃ¥ berättar en Trollkarl att smycket skyddar dess bärares " "odöda undersÃ¥tar frÃ¥n heliga besvärjelser." msgid "Wand of Negation" msgstr "Upphävningstrollstav" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "%{name}t gör hjältens trupper immuna mot Skingringsbesvärjelser." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Du möter en gammal Trollkarlsvän som ska Ã¥t motsatt riktning. Han ger dig en " "gÃ¥va: en Trollstav som förhindrar att fienden kastar " "förskingringsbesvärjelser pÃ¥ dig och dina allierade." msgid "Golden Bow" msgstr "Gyllene BÃ¥ge" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} sänker handikappet med %{count} procent för hjältens varelsers " "projektiler när de passerar hinder, exempelvis borgmurar." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "I ett möte med en känd BÃ¥gskytt i ett parti benkastning föreslÃ¥r han att " "satsa sin pilbÃ¥ge mot din häst. Du vinner!" msgid "Telescope" msgstr "Teleskop" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "%{name} ökar radien som hjälten ser pÃ¥ kartan med %{count} ruta." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Med en handelsman frÃ¥n fjärran land byter du till en uppfinning frÃ¥n hans " "hemland. Den fÃ¥r ting i fjärran att tillsynes se närmare ut genom den. Han " "kallas den...\n" "\n" "ett teleskop." msgid "Statesman's Quill" msgstr "Statsmannens Fjäderpenna" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} sänker kostnaden för kapitulation med %{count} procent av " "totalkostnaden för trupperna hjälten har i sin armé." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Du stannar till för att hjälpa en diplomat med en bruten axel. Av tacksamhet " "skänker han dig en fjäderpenna med magiska egenskaper som han säger " "\"hjälper andra att se saker ur din synpunkt\"." msgid "Wizard's Hat" msgstr "Trollkarlshatt" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "" "%{name}en ökar varaktigheten för hjältens besvärjelser med %{count} rundor." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Du ser en Trollkarl som flyr genom luften frÃ¥n en Grip. Trollkarlen öppnar " "en portal och flyger igenom den. Hans hatt träffar portalens övre kant och " "faller av. Gripen följer efter genom portalen som sedan stängs. Du plockar " "upp hatten, borstar den rent frÃ¥n smuts och sätter den pÃ¥ ditt huvud." msgid "Power Ring" msgstr "Kraftring" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "%{name} Ã¥terhämtar %{count} extra besvärjelsepoäng per dag till hjälten." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Du finner ett träd som pÃ¥minner starkt om den store Häxmästaren Carnauth med " "en ring runt en av dess smÃ¥ grenar. Trasor av gamla kläder och ruttnade " "läder fÃ¥r dig att inse att trädet faktiskt är Carnauth som är förvandlad. " "Eftersom du inte kan hjälpa honom sÃ¥ tar du ringen, dÃ¥ du tycker att du har " "bättre nytta av den." msgid "Ammo Cart" msgstr "Ammunitionsvagn" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "%{name} förser hjältens trupper med oändligt antal projektiler." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "En vagn full med pilar och projektiler stÃ¥r övergiven mitt pÃ¥ ett gammalt " "slagfält. Vid en inspektion sÃ¥ verkar vagnen bara i fullt fungerande skick, " "sÃ¥ du tar med dig den." msgid "Tax Lien" msgstr "Skuldebrev" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} kostar hjälten -%{count} guld per dag." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Ditt slösaktiga beteende har gett din en stor skatteskuld som du inte klarar " "av att betala. Skattemasen känner sympati för dig och gÃ¥r med pÃ¥ att endast " "begära 250 guld per dag frÃ¥n dig... för resten av ditt liv." msgid "Hideous Mask" msgstr "Otäck Mask" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "%{name} förhindrar alla varelser pÃ¥ kartan att ansluta sig till hjältens " "armé." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Vid din plundring av den kände hamnskiftaren Sinfilas Gardolads grav finner " "du hans omskrivne mask. Skakande sÃ¥ sätter du pÃ¥ dig masken och den " "förvrider ditt anlete till en ful grimas. Oh nej! Det visar sig att det " "faktiskt är Gromluck Greenes otäcka mask och den sitter fast." msgid "Endless Pouch of Sulfur" msgstr "Bottenlös SvavelpÃ¥se" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} förser hjälten med %{count} enheter Svavel per dag." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Du besöker en alkemist som vid Ã¥synen av din armé övertalas av ditt fälttÃ¥gs " "rättfärdiga skäl. Alkemisten ger dig hans Bottenlösa SvavelpÃ¥se för att " "hjälpa dig med ditt krigsföretag." msgid "Endless Vial of Mercury" msgstr "Bottenlös Kvicksilverflaska" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} förser hjälten med %{count} enheter Kvicksilver per dag." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "En kort stopp vid ett övergivet Trollkarlstorn hittar du en liten flaska med " "Kvicksilver som alltid verkar ha lite kvar i botten, oavsett hur mycket man " "häller ur. Du inser värdet av ditt fynd och stoppar ner den i din ficka." msgid "Endless Pouch of Gems" msgstr "Bottenlös Ädelstenspung" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} förser hjälten med %{count} enheter Ädelstenar per dag." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "En kort regnskur frambringar en regnbÃ¥ge och du kan se var den slutar. Du " "rider snabbt dit och lägger beslag pÃ¥ en kruka med guld där. Pysslingen som " "äger den är oförmögen att stoppa dig och erbjuder dig en Bottenlös " "Ädelstenspung i utbyte mot hans guld. Du tar budet." msgid "Endless Cord of Wood" msgstr "Ändlös Trätrave" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} ger %{count} enheter med Trä per dag." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Vid ett uppehÃ¥ll för vila och mat sÃ¥ gör du upp en eld. När du sedan matar " "elden med vedträn taget frÃ¥n en trave i närheten, sÃ¥ upptäcker du att traven " "aldrig blir mindre. Du inser glatt att vedtraven är förtrollad sÃ¥ du lastar " "med dig vedtraven." msgid "Endless Cart of Ore" msgstr "Bottenlös Malmkärra" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} förser hjälten med %{count} enheter Malm per dag." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Du har hittat en vapensmedja med vättar som gör vapen för att använda mot " "människor. Med ett kraftfullt rop anfaller du med din armé mot smedjan och " "alla vättar flyr i skräck. Vid en genomletning sÃ¥ finner du en förtrollad " "malmkärra som aldrig blir tom pÃ¥ malm." msgid "Endless Pouch of Crystal" msgstr "Bottenlös Kristallpung" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} förser hjälten med %{count} enheter med Kristaller per dag." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Du har tagit skydd i en grotta undan en storm, i grottan ser du en liten bit " "kristall i ett hörn. Nyfiken sÃ¥ bryter du loss en bit och märker att " "kristallen växer tillbaka. Du väljer att bryta loss hela kristallen och ta " "den med dig." msgid "Spiked Helm" msgstr "Spikhjälm" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Din armé hamnar i ett bakhÃ¥ll för en stam med vilda (och dumma) Orcher. Det " "är ett enkelt motstÃ¥nd och de överlevande orcherna flyr i alla riktningar. " "En av orcherna bar en putsad Spikhjäm. Du tycker det blir en fin souvenir " "och tar den." msgid "Spiked Shield" msgstr "Spiksköld" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Du kommer fram till en bro som sträcker sig över en ravin. Innan du beträder " "bron sÃ¥ kommer ett Troll fram under bron och kräver tull innan du kan " "passera. Du vägrar och Trollet anfaller som tvingar dig att dräpa det. Du " "tar dess Spiksköld som en trofé." msgid "White Pearl" msgstr "Vit Pärla" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "En promenad tvärs över en gammal uttorkad sjöbotten belönas med att du " "hittar en Vit Pärla mitt bland snäckskal och brÃ¥te." msgid "Black Pearl" msgstr "Svart Pärla" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Rykten om att en ovanligt stor Grip som jagar pÃ¥ landsbygden fÃ¥r dig att " "leta upp dess bo. Efter en kort men brutal strid sÃ¥ avlivar du besten och " "söker igenom dess illaluktande bo och hittar en enorm Svart Pärla." msgid "Magic Book" msgstr "Magibok" msgid "The %{name} enables the hero to cast spells." msgstr "%{name}en lÃ¥ter hjälten att kasta besvärjelser." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" "En ung man närmar sig dig: \"Min Herre tillÃ¥t mig att visa er min senaste " "uppfinning för spridandet av kunskap!\" Du följer efter mannen i hans " "verkstad och ser en stor manick med vevhjul och spakar. \"Här är den\" säger " "han ivrigt, \"Tryckpressen\". Innan du hinner säga ett ord sÃ¥ ger han dig en " "Besvärjelsebok." msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "Seger uppnÃ¥s genom att hitta en Främsta Artefakt." msgid "Dummy 2" msgstr "Atrapp 2" msgid "The reserved artifact." msgstr "Reseverad artefakt." msgid "Dummy 3" msgstr "Atrapp 3" msgid "Dummy 4" msgstr "Atrapp 4" msgid "Spell Scroll" msgstr "Besvärjelserulle" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "%{name} ger hjälten förmÃ¥gan att kasta besvärjelsen %{spell} om hjälten har " "en Magibok." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Du finner en välbyggd lÃ¥da som innehÃ¥ller en gammal pergamentrulle. Runorna " "pÃ¥ lÃ¥dan är mycket gamla och hantverket är imponerande. När du tar ut rullen " "sÃ¥ känner du dess magiska krafter i handen." msgid "Arm of the Martyr" msgstr "Martyrens Arm" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} ökar hjältens Trollkonst med %{count}, men sänker stridsmoralen för " "dennes levande trupper." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "En av de mindre begÃ¥vade ur din armé plockar upp en avhuggen arm frÃ¥n " "marken. Trots att resten av kroppen saknas sÃ¥ rör den sig fortfarande. Dina " "trupper finner den avhuggna armen motbjudande. Men du kan inte förmÃ¥ dig " "själv att göra dig av med den eftersom den verkar besitta nÃ¥gon förtrollning " "som pÃ¥verkar din beslutsförmÃ¥ga." msgid "Breastplate of Anduran" msgstr "Andurans Bröstharnesk" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} ökar hjältens Försvar med %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Du stöter pÃ¥ en skylt där det stÃ¥r: \"Här ligger Andurans kropp. Buga dig " "och svär din trohet sÃ¥ ska du bli belönad.\" Du bestämmer att gör som det " "stÃ¥r. När du ställer dig upp känner du kyla mot din hud. Du upptäcker att du " "plötsligt bär ett skimrande utsmyckat bröstharnesk." msgid "Broach of Shielding" msgstr "Skyddsbrosch" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} ger %{count} procent skydd mot Harmageddon och Elementstorm " "besvärjelser, men sänker Trollkonsten för hjälten med 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "En vänlig häxa tycker att din armés försvar skulle kunna behöva en magisk " "förstärkning. Hon erbjuder sig att förtrolla broschen som du bär pÃ¥ din " "kappa och du accepterar erbjudandet." msgid "Battle Garb of Anduran" msgstr "Andurans Stridsrustning" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} förenar krafterna frÃ¥n Andurans tre artefakter. Den ger maximalt med " "tur och stridsmoral till hjältens trupper och ger hjälten förmÃ¥gan att kasta " "besvärjelsen Stadsportal." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Av medömkan för en fattig bonde sÃ¥ köper du en kista med bröte för alldeles " "för mycket guld. Senare när du kollar igenom kistan, finner du de tre delar " "av Andurans legendariska Stridsrustning." msgid "Crystal Ball" msgstr "Kristallkula" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} ger mer specifik information om varelser, fiendehjältar och borgar " "som befinner sig nära hjälten." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Du stöter pÃ¥ en karavan med zigenare som festar och stärker sina kroppar med " "mjöd. De ropar pÃ¥ dig och säger \"Om du kan bevisa att du kan dansa Rama-" "Buta sÃ¥ belönar vi dig.\" Det kan du inte men du försöker ändÃ¥. De skrattar " "hysteriskt, men de uppskattar ditt mod och ger dig en Kristallkula." msgid "Heart of Fire" msgstr "Eldhjärta" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} ger hjältens trupper %{count} procents skydd mot Eld, men dubblar " "skadan frÃ¥n Köld." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Du kliver in i en nyligen nerbrunnen glänta och stöter pÃ¥ ett Eldväsen " "sittandes pÃ¥ett stenblock. Den tittar pÃ¥ dig med en plÃ¥gad blick och kastar " "ett brinnande klot mot dig. Du försöker skydda dig med dina händer men du är " "för lÃ¥ngsam och eldklotet träffar dig mitt pÃ¥ bröstet." msgid "Heart of Ice" msgstr "Ishjärta" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} ger hjältens trupper %{count} procents skydd mot Köld, men dubblar " "skadan frÃ¥n Eld." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Plötsligt sÃ¥ drabbas din kropp av en isande kylda. Du försöker härda ut men " "du faller frÃ¥n din häst. Smärtan försvinner men du känner fortfarande som om " "ditt bröst är fruset. När du försöker resa dig upp hör du ett hjärtligt " "skratt. Du vänder dig om och hinner precis se skymten av en Frostjätte innan " "den springer in i skogen och försvinner." msgid "Helmet of Anduran" msgstr "Andurans Hjälm" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Du ser nÃ¥got glimmande föremÃ¥l sticka upp ur marken. Du skickar iväg en " "undersÃ¥te att kolla vad det är. Han kommer tillbaka med en gyllene hjälm i " "sina händer. Du inser att hjälmen mÃ¥ste vara frÃ¥n den legendariske Anduran, " "den enda mannen som var känd för att bära rustning i det renaste guld." msgid "Holy Hammer" msgstr "Helig Hammare" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Du stöter pÃ¥ en strid där en Paladin är dödligt sÃ¥rad frÃ¥n en grupp med " "Zombier. Han ber dig att ta hans stridshammare och avsluta det han pÃ¥börjat. " "När du tar hammaren sÃ¥ börjar den surra och sen blir allting en oklar dimma. " "Zombierna ligger döda och hammaren är blodstänkt. Du tar hammaren." msgid "Legendary Scepter" msgstr "Legendarisk Spira" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} ger hjälten %{count} till alla dennes primära förmÃ¥gor." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "När du är pÃ¥ väg upp till toppen av en liten kulle stöter du pÃ¥ en löjlig " "syn. En fe försöker att bära en spira som nästan är större än den själv. Du " "försöker lÃ¥ta bli att skratta när du frÃ¥gar, \"Behöver du hjälp?\" Fen " "blänger pÃ¥ dig och svarar: \"Tror du att det är roligt? Visst, du kan bära " "den själv. Jag föredrar ändÃ¥ att flyga.\"" msgid "Masthead" msgstr "Mastlykta" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} ökar hjältens truppers Tur och höjer deras Stridsmoral med %{count} " "i sjöstrider." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "En gammal sjöman berättar för dig om en förtrollad Mastlykta som han i sina " "yngre dagar samlade sin besättning kring i brÃ¥da tider. Sen visar han en " "gammal blekt karta och visar var han glömde den. Efter mycket letande hittar " "du den under en närliggande kaj." msgid "Sphere of Negation" msgstr "Upphävningsklot" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" "%{name} förhindrar all besvärjelsekastning i strid för hjälten och fiendens " "besvärjelsekastare." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Du stannar för att hjälpa en bonde att infÃ¥nga ett förrymt sto. För att visa " "sin uppskattning ger han dig en liten kula. När du tar den i din hand känner " "du hur dina magiska krafter rinner ur dig..." msgid "Staff of Wizardry" msgstr "Trollkonststav" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} ökar hjältens Trollkonst med %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "När dina trupper hÃ¥lla pÃ¥ att passa vild sÃ¥ finner de en mystisk stav sväva " "tre fot ovanför marken. De ger den till dig och du lägger märke till en " "inskription som lyder: \"Snille framför styrka och magi framför muskler. " "Lyssna till mina ord och du kommer aldrig förlora en strid.\"" msgid "Sword Breaker" msgstr "Svärdsbrytare" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} ökar hjältens Försvar med %{count} och dennes Anfall med 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "En föredetta kaptensvakt beundrar ditt företag och ger dig den förtrollade " "Svärdbrytaren som han bar under sin tjänstgöring." msgid "Sword of Anduran" msgstr "Andurans Svärd" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Ett troll stoppar dig och säger: \"Ge mig 5,000 guld, annars kommer Andurans " "svärd att dräpa dig där du stÃ¥r.\" Du nekar. Trollet tar tag i svärdet som " "hänger frÃ¥n bältet, skriker i smärta och springer iväg. Du plockar pÃ¥ det " "förtäljda svärdet och tackar det sinnessvaga trollets försök att ta tag i " "fel ände av det vassa objektet." msgid "Spade of Necromancy" msgstr "Svartkonstens spade" msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} ökar hjältens SvartkonstförmÃ¥ga." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "En skitig spade är nersatt bredvid en jordhög. Vid inspektion upptäcker du " "att det faktiskt är Dödgrävarnas förtrollande spade som sedan länge ansetts " "vara förlorad." msgid "spellBonus|selected by user" msgstr "vald av spelaren" msgid "Wood" msgstr "Trä" msgid "Mercury" msgstr "Kvicksilver" msgid "Ore" msgstr "Malm" msgid "Sulfur" msgstr "Svavel" msgid "Crystal" msgstr "Kristall" msgid "Gems" msgstr "Ädelstenar" msgid "Gold" msgstr "Guld" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Det finns 7 olika resurser i Heroes och Might and Magic 2 som används för " "att bygga och förbättra borgar, rekrytera trupper och hjältar. Guld är den " "vanligaste, som behövs till det mesta. Trä och Malm används mest till " "byggnader. Ädelstenar, Kvicksilver, Svavel och Kristaller är sällsynta " "magiska resurser som används till de mest kraftfulla varelser och byggnader." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Skapar ett stort eldklot som träffar ett utvalt omrÃ¥de och skadar alla " "varelser i närheten." msgid "Fireball" msgstr "Eldklot" msgid "Fireblast" msgstr "Eldexplosion" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "En förbättrad variant av Eldklot. Eldexplosion angriper tvÃ¥ hexagonaler " "runtomkring den centrala punkten, istället för en." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "FÃ¥r en blixt att slÃ¥ ned pÃ¥ vald varelse." msgid "Lightning Bolt" msgstr "Ljusblixt" msgid "Chain Lightning" msgstr "Kedjeblixt" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Framkallar en blixt av elektrisk energi som slÃ¥r ned pÃ¥ en vald varelse, " "sedan slÃ¥ ned pÃ¥ de närmaste varelserna med halverad skada, sedan slÃ¥ ned pÃ¥ " "de NÄST närmaste varelserna med halverad skada, o.s.v., tills den blir för " "svag för att skada. Varning: Denna besvärjelse kan träffa dina egna varelser!" msgid "Teleport" msgstr "Teleportera" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Teleporterar vald varelse till valfri fri position pÃ¥ slagfältet." msgid "Cure" msgstr "Hela" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Skingrar alla onda besvärjelser frÃ¥n en av dina varelser, Ã¥terställer upp " "till %{count} hälsopoäng per Trollkonststyrka." msgid "Mass Cure" msgstr "Masshelning" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Tar bort alla onda besvärjelser som har kastats pÃ¥ dina trupper och " "Ã¥terställer upp till %{count} hälsopoäng per Trollkonststyrka per varelse." msgid "Resurrect" msgstr "" "Ã…ter-\n" "upplivning" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Ã…terupplivar varelser frÃ¥n en skadad eller död enhet tills striden slutar." msgid "Resurrect True" msgstr "" "Äkta\n" "Ã…terupplivning" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Ã…terupplivar varelser frÃ¥n en skadad eller död varelse permanent." msgid "Haste" msgstr "Skynda" msgid "Increases the speed of any creature by %{count}." msgstr "Höjer en varelses hastighet med %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Höjer alla dina varelsers hastighet med %{count}." msgid "Mass Haste" msgstr "" "Mass-\n" "skyndning" msgid "Slows target to half movement rate." msgstr "Saktar ned varelsens hastighet till hälften." msgid "spell|Slow" msgstr "Förslöa" msgid "Mass Slow" msgstr "" "Mass-\n" "förslöelse" msgid "Slows all enemies to half movement rate." msgstr "Saktar ned alla fiendevarelser till hälften." msgid "spell|Blind" msgstr "Förblinda" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" "Grumlar varelsens ögon som förhindrar den frÃ¥n att röra sig och sänker " "skadan den ger vid vedergällning med %{count} procent." msgid "Bless" msgstr "Välsignelse" msgid "Causes the selected creatures to inflict maximum damage." msgstr "FÃ¥r en varelse att utdela maximal skada." msgid "Causes all of your units to inflict maximum damage." msgstr "FÃ¥r alla dina varelser att utdela maximal skada." msgid "Mass Bless" msgstr "" "Mass-\n" "-välsignelse" msgid "Magically increases the defense skill of the selected creatures." msgstr "Ökar vald varelses Försvar genom förtrollning." msgid "Stoneskin" msgstr "Stenhud" msgid "Steelskin" msgstr "StÃ¥lhud" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Ökar Försvaret för vald varelse. Detta är en förbättrad variant av Stenhud." msgid "Causes the selected creatures to inflict minimum damage." msgstr "FÃ¥r en varelse att utdela minimal skada." msgid "Curse" msgstr "Förbannelse" msgid "Causes all enemy troops to inflict minimum damage." msgstr "FÃ¥r alla fiendetrupper att utdela minimal skada." msgid "Mass Curse" msgstr "" "Mass-\n" "förbannelse" msgid "Damages all undead in the battle." msgstr "Skadar alla odöda i striden." msgid "Holy Word" msgstr "Heligt Ord" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Skadar alla odöda i striden. Det är en förbättrad version av Heligt Ord." msgid "Holy Shout" msgstr "Heligt Rop" msgid "Anti-Magic" msgstr "Antimagi" msgid "Prevents any magic against the selected creatures." msgstr "Förhindrar besvärjelser mot vald varelse." msgid "Dispel Magic" msgstr "Skingra Magi" msgid "Removes all magic spells from a single target." msgstr "Skingrar alla besvärjelser, goda som onda frÃ¥n en vald varelse." msgid "Mass Dispel" msgstr "" "Mass-\n" "skingring" msgid "Removes all magic spells from all creatures." msgstr "Tar bort alla magiska besvärjelser frÃ¥n alla varelser." msgid "Causes a magic arrow to strike the selected target." msgstr "Skjuter en magisk pil pÃ¥ valt mÃ¥l." msgid "Magic Arrow" msgstr "Magisk Pil" msgid "Berserker" msgstr "Bärsärk" msgid "Causes a creature to attack its nearest neighbor." msgstr "FÃ¥r en varelse att anfalla sin närmaste granne." msgid "Armageddon" msgstr "Harmageddon" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Gudomlig fasa drabbar slagfältet som orsakar stor skada till samtliga " "varelser." msgid "Elemental Storm" msgstr "" "Element-\n" "storm" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Magiska element vräker ned pÃ¥ slagfältet, skadar alla varelser." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Ett stenregn slÃ¥r ned pÃ¥ en omrÃ¥de pÃ¥ slagfältet och skadar alla varelser i " "närheten." msgid "Meteor Shower" msgstr "Meteorregn" msgid "Paralyze" msgstr "Paralysera" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "Valda varelser är paralyserade, de kan varken förflytta sig eller hämnas." msgid "Hypnotize" msgstr "Hypnotisera" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Du tar kontroll över en enhet om dess hälsopoäng är mindre än %{count} " "gÃ¥nger hjältens Trollkonst." msgid "Cold Ray" msgstr "KöldstrÃ¥le" msgid "Drains body heat from a single enemy unit." msgstr "Tömmer kroppsvärme frÃ¥n en enskild fiendetrupp." msgid "Cold Ring" msgstr "Köldring" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Tömmer kroppsvärme frÃ¥n omgivande enheter runt mittpunkten, exklusive " "mittpunkten." msgid "Disrupting Ray" msgstr "StörstrÃ¥le" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Sänker varelsens Försvar med tre enheter." msgid "Damages all living (non-undead) units in the battle." msgstr "Skadar alla levande (icke-odöda) varelser pÃ¥ slagfältet." msgid "Death Ripple" msgstr "Dödskrusning" msgid "Death Wave" msgstr "DödsvÃ¥g" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Skadar alla levande (icke-odöda) varelser pÃ¥ slagfältet. Denna besvärjelse " "är en förbättrad variant av Dödskrusningen." msgid "Dragon Slayer" msgstr "Drakdräpare" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Höjer kraftigt en varelses Anfall mot Drakar." msgid "Blood Lust" msgstr "Blodtörst" msgid "Increases a unit's attack skill." msgstr "Höjer en varelses Anfall." msgid "Animate Dead" msgstr "Animera Död" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "Ã…teruppväcker skadade eller stupade odöda varelser permanent." msgid "Mirror Image" msgstr "Spegelbild" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Skapar en illusorisk enhet som duplicerar en av dina existerande enheter. " "Denna illusoriska enhet ger lika mycket skada som originalet, men försvinner " "om de tar skada." msgid "Shield" msgstr "Sköld" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halverar skada frÃ¥n projektilsattacker för en varelse. Projektiler frÃ¥n torn " "och ballistor räknas ej." msgid "Mass Shield" msgstr "Massköld" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Halverar skadan till alla dina trupper frÃ¥n projektilattacker. Projektiler " "frÃ¥n torn och ballistor räknas ej." msgid "Summon Earth Elemental" msgstr "Framkalla Jordväsen" msgid "Summons Earth Elementals to fight for your army." msgstr "Kallar in Jordväsen för att strida för hjältens armé." msgid "Summon Air Elemental" msgstr "Framkalla Luftväsen" msgid "Summons Air Elementals to fight for your army." msgstr "Kallar in Luftväsen för att strida för hjältens armé." msgid "Summon Fire Elemental" msgstr "Framkalla Eldväsen" msgid "Summons Fire Elementals to fight for your army." msgstr "Kallar in Eldväsen för att strida för hjältens armé." msgid "Summon Water Elemental" msgstr "Framkalla Vattenväsen" msgid "Summons Water Elementals to fight for your army." msgstr "Kallar in Vattenväsen för att strida för hjältens armé." msgid "Damages castle walls." msgstr "Skadar borgmurar." msgid "Earthquake" msgstr "Jordbävning" msgid "Causes all mines across the land to become visible." msgstr "Gör alla gruvor synliga över hela landet." msgid "View Mines" msgstr "" "Visa\n" "Gruvor" msgid "Causes all resources across the land to become visible." msgstr "Gör alla resurser synliga över hela landet." msgid "View Resources" msgstr "Visa Resurser" msgid "Causes all artifacts across the land to become visible." msgstr "Gör alla artefakter synliga över hela landet." msgid "View Artifacts" msgstr "Visa Artefakter" msgid "Causes all towns and castles across the land to become visible." msgstr "Gör alla städer och borgar synliga över hela landet." msgid "View Towns" msgstr "Visa Städer" msgid "Causes all Heroes across the land to become visible." msgstr "Gör alla Hjältar synliga över hela landet." msgid "View Heroes" msgstr "" "Visa \n" "Hjältar" msgid "Causes the entire land to become visible." msgstr "Gör hela landet synligt." msgid "View All" msgstr "Visa Allt" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "LÃ¥ter kastaren fÃ¥ detaljerad information om fiendehjältar." msgid "Summon Boat" msgstr "" "Inkalla\n" "Skepp" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Framkallar närmsta lediga skepp till en närliggande strand. Bara skepp som " "du nyligen byggt eller var den senaste att kontrollera kan framkallas." msgid "Allows the caster to magically transport to a nearby location." msgstr "LÃ¥ter kastaren magiskt transportera sig till en närliggande plats." msgid "Dimension Door" msgstr "" "Dimensions-\n" "portal" msgid "Returns the caster to any town or castle currently owned." msgstr "För tillbaka Hjälten till nÃ¥gon stad eller borg som du kontrollerar." msgid "Town Gate" msgstr "Stadsport" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "För tillbaka Hjälten till valfri stad eller borg som du kontrollerar." msgid "Visions" msgstr "Syner" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Syner förutspÃ¥r det sannolika utfallet av en strid mot ett neutralt " "fiendeläger." msgid "Haunt" msgstr "Hemsök" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Hemsöker en gruva som du kontrollerar med Spöken. Denna gruva slutar att " "producera resurser. (Om inte jag kan behÃ¥lla den, kommer ingen att kunna " "det!)" msgid "Set Earth Guardian" msgstr "Placera Jordväktare" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Placerar Jordväsen att vakta en gruva mot fiendearméer." msgid "Set Air Guardian" msgstr "Placera Luftväktare" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Placerar Luftväsen att vakta en gruva mot fiendearméer." msgid "Set Fire Guardian" msgstr "Placera Eldväktare" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Placerar Eldväsen att vakta en gruva mot fiendearméer." msgid "Set Water Guardian" msgstr "Placera Vattenväktare" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Placerar Vattenväsen att vakta en gruva mot fiendearméer." msgid "Random Spell" msgstr "Slumpad Besvärjelse" msgid "Randomly selected spell of any level." msgstr "Slumpmässigt vald besvärjelse frÃ¥n alla nivÃ¥er." msgid "Random 1st Level Spell" msgstr "Slumpad NivÃ¥ 1-Besvärjelse" msgid "Randomly selected 1st level spell." msgstr "Slumpmässigt vald nivÃ¥ 1-besvärjelse." msgid "Random 2nd Level Spell" msgstr "Slumpad NivÃ¥ 2-Besvärjelse" msgid "Randomly selected 2nd level spell." msgstr "Slumpmässigt vald nivÃ¥ 2-besvärjelse." msgid "Random 3rd Level Spell" msgstr "Slumpad NivÃ¥ 3-Besvärjelse" msgid "Randomly selected 3rd level spell." msgstr "Slumpmässigt vald nivÃ¥ 3-besvärjelse." msgid "Random 4th Level Spell" msgstr "Slumpad NivÃ¥ 4-Besvärjelse" msgid "Randomly selected 4th level spell." msgstr "Slumpmässigt vald nivÃ¥ 4-besvärjelse." msgid "Random 5th Level Spell" msgstr "Slumpad NivÃ¥ 5-Besvärjelse" msgid "Randomly selected 5th level spell." msgstr "Slumpmässigt vald nivÃ¥ 5-besvärjelse." msgid "Petrification" msgstr "Förstening" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Förvandlar varelsen till sten. En förstenad varelse mottar bara hälften " "skada frÃ¥n en direktattack." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" "Hjälten har ingen Magibok, sÃ¥ hjälten kan inte kasta nÃ¥gon besvärjelse." msgid "No spell to cast." msgstr "Inga besvärjelser att kasta." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Hjälten har %{point} besvärjelsepoäng kvar av totalt %{max}." msgid "View Adventure Spells" msgstr "Visa Kartbesvärjelser" msgid "View Combat Spells" msgstr "Visa Stridsbesvärjelser" msgid "View previous page" msgstr "Visa föregÃ¥ende blad" msgid "View next page" msgstr "Visa nästa blad" msgid "Close Spellbook" msgstr "Stäng Magibok" msgid "View %{spell}" msgstr "Visa %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Denna besvärjelsen ger %{damage} skada." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Denna besvärjelse framkallar\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Denna besvärjelse Ã¥terställer %{hp} hälsopoäng." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Denna besvärjelse framkallar %{count} %{monster} för att vakta gruvan." msgid "The nearest town is %{town}." msgstr "Närmsta stad är %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Denna stad besöks av din hjälte %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Denna besvärjelse kontrollerar upp till\n" "%{hp} hälsopoäng." msgid "The ultimate artifact is really the %{name}." msgstr "Den Främsta Artefakten är den %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Den främsta artefakten finnes i %{name}-regionen." msgid "north-west" msgstr "nordväst" msgid "north" msgstr "norr" msgid "north-east" msgstr "nordost" msgid "west" msgstr "väst" msgid "center" msgstr "mitten" msgid "east" msgstr "öst" msgid "south-west" msgstr "sydväst" msgid "south" msgstr "syd" msgid "south-east" msgstr "sydost" msgid "The truth is out there." msgstr "Sanningen finns där ute." msgid "The dark side is stronger." msgstr "Den mörka sidan är starkare." msgid "The end of the world is near." msgstr "Världens undergÃ¥ng är nära." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Benen frÃ¥n Mästerdräparen är begravda i arenans grund." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "En Svart Drake spöar en Titan alla dagar i veckan." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "Han sa till henne: Jag bah... och hon svarade: Du bah..." msgid "An unknown force is being resurrected..." msgstr "En okänd kraft Ã¥teruppstÃ¥r..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Den senaste versionen av spelet finns pÃ¥:\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Välj antal %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Aktivera autom. strid" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "LÃ¥t datorn fortsätta striden" #~ msgid "Please Remember" #~ msgstr "Kom ihÃ¥g" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Du kan alltid ändra sprÃ¥k, spelupplösning och inställningar genom att " #~ "klicka pÃ¥ " #~ msgid "door" #~ msgstr "dörren" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " vid vänster om huvudmenyn eller med " #~ msgid " button from the " #~ msgstr " knappen i " #~ msgid "NEW GAME" #~ msgstr "" #~ "NYTT\n" #~ "SPEL" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ " menyn. \n" #~ "Spela pÃ¥!" #~ msgid "Warning!" #~ msgstr "Varning!" #~ msgid "Dummy 1" #~ msgstr "Atrapp 1" fheroes2-1.1.6+dfsg/files/lang/tr.po000066400000000000000000006503111476115357100172030ustar00rootroot00000000000000# Turkish translation for fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-12-01 16:37+0300\n" "Last-Translator: fheroes2 team \n" "Language-Team: Turkish \n" "Language: tr\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-Launchpad-Export-Date: 2010-05-27 09:12+0000\n" "X-Generator: Poedit 3.5\n" msgid "" "NEW\n" "GAME" msgstr "" "YENİ\n" "OYUN" msgid "" "SAVE\n" "GAME" msgstr "" "OYUNU\n" "KAYDET" msgid "" "LOAD\n" "GAME" msgstr "" "OYUNU\n" "YÜKLE" msgid "INFO" msgstr "BİLGİ" msgid "QUIT" msgstr "ÇIKIÅž" msgid "" "NEW\n" "MAP" msgstr "" "YENİ\n" "HARİTA" msgid "" "SAVE\n" "MAP" msgstr "" "HARİTAYI\n" "KAYDET" msgid "" "LOAD\n" "MAP" msgstr "" "HARİTAYI\n" "YÜKLE" msgid "CANCEL" msgstr "İPTAL" msgid "OKAY" msgstr "TAMAM" msgid "ACCEPT" msgstr "KABUL" msgid "DECLINE" msgstr "REDDET" msgid "LEARN" msgstr "ÖĞREN" msgid "TRADE" msgstr "TAKAS" msgid "YES" msgstr "EVET" msgid "NO" msgstr "HAYIR" msgid "EXIT" msgstr "ÇIKIÅž" msgid "smallerButton|EXIT" msgstr "ÇIKIÅž" msgid "DISMISS" msgstr "BIRAK" msgid "UPGRADE" msgstr "GELİŞTİR" msgid "RESTART" msgstr "TEKRARLA" msgid "HEROES" msgstr "KAHRAMANLAR" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "KASABALAR/\n" "KALELER" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "X-L" msgid "ALL" msgstr "HEPSİ" msgid "SELECT" msgstr "SEÇ" msgid "" "STANDARD\n" "GAME" msgstr "" "STANDART\n" "OYUN" msgid "" "BATTLE\n" "ONLY" msgstr "" "SADECE\n" "SAVAÅž" msgid "" "CAMPAIGN\n" "GAME" msgstr "" "HİKAYE\n" "OYUNU" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "ÇOK\n" "OYUNCULU\n" "OYUN" msgid "CONFIG" msgstr "AYARLAR" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ORİJİNAL\n" "HİKAYE" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "EKLENTİ\n" "HİKAYESİ" msgid "HOT SEAT" msgstr "SIRAYLA OYNAMA" msgid "2 PLAYERS" msgstr "2 OYUNCU" msgid "3 PLAYERS" msgstr "3 OYUNCU" msgid "4 PLAYERS" msgstr "4 OYUNCU" msgid "5 PLAYERS" msgstr "5 OYUNCU" msgid "6 PLAYERS" msgstr "6 OYUNCU" msgid "GIFT" msgstr "HEDİYE" msgid "MAX" msgstr "MAKS" msgid "DIFFICULTY" msgstr "ZORLUK" msgid "VIEW INTRO" msgstr "İNTROYU İZLE" msgid "MIN" msgstr "MİN" msgid "RESET" msgstr "SIFIRLA" msgid "START" msgstr "BAÅžLA" msgid "TOWN" msgstr "KASABA" msgid "CASTLE" msgstr "KALE" msgid "RESTRICT" msgstr "KISITLA" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "B\n" "I\n" "R\n" "A\n" "K" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "Ç\n" "I\n" "K\n" "I\n" "Åž" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "D\n" "E\n" "V\n" "R\n" "İ\n" "Y\n" "E" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "H\n" "İ\n" "K\n" "A\n" "Y\n" "E" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "T" msgid "RUMORS" msgstr "SÖYLENTİLER" msgid "EVENTS" msgstr "ETKİNLİKLER" msgid "LANGUAGE" msgstr "DİL" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Savaşçı" msgid "Builder" msgstr "İnÅŸaatçı" msgid "Explorer" msgstr "KaÅŸif" msgid "None" msgstr "Hiç" msgid "" "A few\n" "%{monster}" msgstr "" "Birkaç\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Birçok\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Bir yığın\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Fazla\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Bir sürü\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Çok fazla\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Bir tabur\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Aşırı fazla\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Bir lejyon\n" "%{monster}" msgid "army|Few" msgstr "Birkaç" msgid "army|Several" msgstr "Birçok" msgid "army|Pack" msgstr "Yığın" msgid "army|Lots" msgstr "Fazla" msgid "army|Horde" msgstr "Sürü" msgid "army|Throng" msgstr "Çok Fazla" msgid "army|Swarm" msgstr "Tabur" msgid "army|Zounds" msgstr "Aşırı" msgid "army|Legion" msgstr "Lejyon" msgid "All %{race} troops +1" msgstr "Bütün %{race} askerler +1" msgid "NeutralRaceTroops|Neutral" msgstr "Tarafsız" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Birlikleri %{count} hizala -%{penalty}" msgid "Some undead in army -1" msgstr "Gruptaki bazı undeadler -1" msgid "" "Default\n" "troop" msgstr "" "Varsayılan\n" "askerler" msgid "View %{name}" msgstr "Görünüm %{name}" msgid "Move the %{name} " msgstr "%{name} 'i hareket ettir " msgid "Move or right click to redistribute %{name}" msgstr "%{name} Yeniden dağıtmak için oynatın veya saÄŸ tıklayın" msgid "Combine %{name} armies" msgstr "%{name} orduları birleÅŸtir" msgid "Exchange %{name2} with %{name}" msgstr "%{name2} 'ı %{name} ile deÄŸiÅŸtir" msgid "Select %{name}" msgstr "%{name}'ı seç" msgid "Cannot move last troop" msgstr "Son birlik hareket ettirilemiyor" msgid "Move the %{name}" msgstr "%{name} 'i hareket ettir" msgid "Set %{monster} Count" msgstr "%{monster} sayısını ayarla" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} düşman birliklerinin yarısını yok etti!" msgstr[1] "%{name} düşman birliklerinin yarısını yok etti!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} otomatik savaşı kapattı" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} otomatik savaşı açtı" msgid "Spell failed!" msgstr "Büyü baÅŸarısız oldu!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Bu savaÅŸta İnkar Alanı Eseri aktif, bütün savaÅŸ büyülerini devre dışı " "bırakıyor." msgid "You cannot cast spells without a commanding hero." msgstr "Yöneten bir kahraman olmadan büyü kullanamazsın." msgid "You have already cast a spell this round." msgstr "Bu turda zaten bir büyü yaptın." msgid "That spell will have no effect!" msgstr "Bu büyünün etkisi olmayacak!" msgid "You may only summon one type of elemental per combat." msgstr "SavaÅŸ başına yalnızca bir tür elemental çağırabilirsiniz." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "Kahramanınızın yanında bir Elemental çağırmak için açık bir alan yok." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Hendek savunma becerisi herhangi bir birimin savunma becerisi ve hareket " "hızını %{count} düşürüyor." msgid "Speed: %{speed}" msgstr "Hız: %{speed}" msgid "Speed" msgstr "Hız" msgid "Off" msgstr "Kapalı" msgid "On" msgstr "Açık" msgid "Turn Order" msgstr "Sıra sırası" msgid "Auto Spell Casting" msgstr "Otomatik Büyü Yapma" msgid "Grid" msgstr "Izgara" msgid "Shadow Movement" msgstr "Gölge Hareketi" msgid "Shadow Cursor" msgstr "Gölge İmleci" msgid "Audio" msgstr "Ses" msgid "Settings" msgstr "Ayarlar" msgid "Configure" msgstr "Ayarla" msgid "Hot Keys" msgstr "Kısayollar" msgid "Damage Info" msgstr "Hasar Bilgisi" msgid "Set the speed of combat actions and animations." msgstr "SavaÅŸ eylemlerinin ve animasyonların hızını ayarlayın." msgid "Toggle to display the turn order during the battle." msgstr "SavaÅŸ sırasında sıra sırasını görüntülemek için aktif edin." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Otomatik savaÅŸ açıkken bilgisayarın sizin için büyü yapıp yapmayacağını " "deÄŸiÅŸtirin.(Not: Bu, bilgisayar oyuncuları için büyü yapmayı hiçbir ÅŸekilde " "etkilemez ve hızlı savaşı etkilemez.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Altıgen ızgarayı aç veya kapat.Altıgen ızgara, kapatılsa bile her zaman " "hareketin temelini oluÅŸturur. Bu anahtar yalnızca ızgaranın görünür olup " "olmadığını belirler." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Yaratıklarınızın nereye hareket edip saldırabileceÄŸini gösteren gölgeleri " "açın veya kapatın." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Fare imlecinin mevcut altıgen konumunu gösteren bir gölgeyi açın veya " "kapatın." msgid "Change the audio settings of the game." msgstr "Oyunun ses ayarını deÄŸiÅŸtir." msgid "Check and configure all the hot keys present in the game." msgstr "Oyunda bulunan tüm kısayol tuÅŸlarını kontrol edin ve yapılandırın." msgid "Toggle to display damage information during the battle." msgstr "SavaÅŸ sırasında hasar bilgisini görüntülemek için akif edin." msgid "Exit this menu." msgstr "Bu menüden çık." msgid "Okay" msgstr "Tamam" msgid "The enemy has surrendered!" msgstr "Düşman teslim oldu!" msgid "Their cowardice costs them %{gold} gold." msgstr "Korkaklıkları onlara %{gold} altına mal oldu." msgid "The enemy has fled!" msgstr "Düşman kaçtı!" msgid "A glorious victory!" msgstr "Åžanlı bir zafer!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "SavaÅŸ'taki cesareti için %{name} %{exp} tecrübe kazandı." msgid "The cowardly %{name} flees from battle." msgstr "Korkak %{name} savaÅŸtan kaçtı." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} düşmana teslim oldu, ve utanç içinde ayrıldı." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "BirliÄŸiniz acı bir yenilgiye uÄŸradı, ve %{name} sizi terk etti." msgid "Your forces suffer a bitter defeat." msgstr "BirliÄŸiniz acı bir yenilgiye uÄŸradı." msgid "Battlefield Casualties" msgstr "SavaÅŸ Alanı Kayıpları" msgid "Attacker" msgstr "Saldıran" msgid "Defender" msgstr "Savunan" msgid "Click to leave the battle results." msgstr "SavaÅŸ sonuçlarından çıkmak için tıklayın." msgid "Click to restart the battle in manual mode." msgstr "Savaşı manuel modda bbaÅŸlatmak için tıklayın." msgid "Restart" msgstr "Tekrarla" msgid "You have captured an enemy artifact!" msgstr "Bir düşman eseri ele geçirdiniz!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "%{name}' ye ulaÅŸtığınızda,gizemli bir ÅŸekilde kayboldu." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Düşman %{name}' ye ulaÅŸtığında,gizemli bir ÅŸekilde kayboldu." msgid "Necromancy!" msgstr "Ölü Büyücülüğü!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Karanlık büyücülük sanatlarını uygulayarak, %{monster} olarak hizmetinize " "geri dönmek için düşmanın ölülerinin %{count} kadarını çağırabilirsiniz." msgid "%{name} the %{race}" msgstr "%{name} %{race}" msgid "Captain of %{name}" msgstr "%{name} Kaptanı" msgid "Attack" msgstr "Saldırı" msgid "Defense" msgstr "Savunma" msgid "Spell Power" msgstr "Büyü Gücü" msgid "Knowledge" msgstr "Bilgi" msgid "Morale" msgstr "Moral" msgid "Luck" msgstr "Åžans" msgid "Spell Points" msgstr "Büyü Puanları" msgid "Hero's Options" msgstr "Kahramanın Seçenekleri" msgid "Cast Spell" msgstr "Yapılan Büyü" msgid "Retreat" msgstr "Geri Çekil" msgid "Surrender" msgstr "Teslim Olmak" msgid "Cancel" msgstr "Vazgeç" msgid "Hero Screen" msgstr "Kahraman Ekranı" msgid "Captain's Options" msgstr "Kaptanın Seçenekleri" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Bir büyü yap. Her savaÅŸ turunda yalnızca bir büyü yapabilirsiniz. Her " "yaratık bir sıra aldığında tur sıfırlanır." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Kahramanını geri çek, yaratıklarını terk et. Kahramanınız tekrar askere " "almanız için hazır olacak, ancak kahramanın yalnızca acemi bir kahramanın " "güçleri olacak." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Teslim olmak Altın'a mal olur. Ancak fidyeyi öderseniz, kahraman ve hayatta " "kalan tüm yaratıkları yeniden askere alınabilir. Teslim olmanın maliyeti, " "orduda kalan geçici olmayan birliklerin toplam maliyetinin yarısı kadardır." msgid "Open Hero Screen to view full information about the hero." msgstr "" "Kahraman hakkında tüm bilgileri görüntülemek için Kahraman Ekranını açın." msgid "Return to the battle." msgstr "SavaÅŸa geri dön." msgid "Not enough gold (%{gold})" msgstr "Yeterli altın yok (%{gold})" msgid "%{name} states:" msgstr "%{name} diyor:" msgid "Captain of %{name} states:" msgstr "%{name} Kaptanı diyor:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Teslim olmanızı kabul ediyorum ve %{price} altın karşılığında size ve " "birliklerinize güvenli geçiÅŸ izni veriyorum.\"" msgid "View %{monster} info" msgstr "%{monster} bilgisini görüntüle" msgid "Fly %{monster} here" msgstr "%{monster} Buraya uçur" msgid "Move %{monster} here" msgstr "%{monster} Buraya hareket ettir" msgid "Shoot %{monster}" msgstr "%{monster} vur" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(1 vuruÅŸ kaldı)" msgstr[1] "(%{count} vuruÅŸlar kaldı)" msgid "Attack %{monster}" msgstr "%{monster} Saldır" msgid "Turn %{turn}" msgstr "%{turn} Dön" msgid "Teleport here" msgstr "Buraya ışınlan" msgid "Invalid teleport destination" msgstr "Geçersiz ışınlanma hedefi" msgid "Cast %{spell} on %{monster}" msgstr "%{monster}'a %{spell} uygula" msgid "Cast %{spell}" msgstr "%{spell} uygula" msgid "Select spell target" msgstr "Büyü hedefini seç" msgid "View Ballista info" msgstr "Mancınık bilgilerini görüntüle" msgid "Ballista" msgstr "Mancınık" #, fuzzy msgid "Automatic combat modes" msgstr "Otomatik savaÅŸ" #, fuzzy msgid "Automatic Combat Modes" msgstr "Otomatik savaÅŸ" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Sistem seçeneklerini özelleÅŸtirin" msgid "Allows you to customize the combat screen." msgstr "SavaÅŸ ekranını özelleÅŸtirmenizi saÄŸlar." msgid "System Options" msgstr "Sistem Seçenekleri" msgid "Skip this unit" msgstr "Bu birimi geç" msgid "Skip" msgstr "Geç" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Mevcut yaratığı atlar. Mevcut yaratığın sırası sona erer ve bir sonraki tura " "kadar tekrar hareket edemez." msgid "View Captain's options" msgstr "Kaptanın seçeneklerini görüntüle" msgid "View Hero's options" msgstr "Kahramanın seçeneklerini görüntüle" msgid "View opposing Captain" msgstr "Rakip Kaptanı görüntüle" msgid "View opposing Hero" msgstr "Karşı Kahramanı görüntüle" msgid "Hide logs" msgstr "Günlükleri gizle" msgid "Show logs" msgstr "Günlükleri göster" msgid "Message Bar" msgstr "Mesaj ÇubuÄŸu" msgid "Shows the results of individual monster's actions." msgstr "Bireysel canavar eylemlerinin sonuçlarını gösterir." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Otomatik savaşı etkinleÅŸtirmek istediÄŸine emin misin?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Bilgisayarın sizin için savaÅŸmasına izin verir." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Otomatik savaÅŸ" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Otomatik savaÅŸ" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} sırasını geçti." msgstr[1] "%{name} sırasını geçti." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} %{damage} hasar verdi." msgstr[1] "%{attacker} %{damage} hasar verdi." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 yaratik yok oldu." msgstr[1] "%{count} yaratık yok oldu." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} yok oldu." msgstr[1] "%{count} %{defender} yok oldu." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 ruh dahil edildi." msgstr[1] "%{count} ruh dahil edildi." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "" msgstr[1] "" msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "%{monster}: [%{src}] buradan [%{dst}] buraya hareket ettirdi." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} büyüye direndi!" msgstr[1] "%{name} büyüye direndi!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} %{troop} 'a %{spell} uyguladı." msgid "%{name} casts %{spell}." msgstr "%{name} %{spell} uyguladı." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} büyüsü bir ölümsüz canavara %{damage} hasar verdi." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} büyüsü bütün ölümsüz canavarlara %{damage} hasar verdi." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} büyüsü %{damage} hasar verdi, %{count} canavarlar yok oldu." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} büyüsü %{damage} hasar verdi." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} büyüsü bir yaÅŸayan canavara %{damage} hasar verdi." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} büyüsü bütün yaÅŸayan canavarlara %{damage} hasar verdi." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "%{attacker}'ın saldırısı %{target}'ı kör etti!" msgstr[1] "%{attacker}'ların saldırısı %{target}'ı kör etti!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "%{attacker}'ın bakışları %{target}'ı taÅŸa çevirdi!" msgstr[1] "%{attacker}'ların bakışları %{target}'ı taÅŸa çevirdi!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "%{attacker}'ın laneti %{target}'in üzerine geldi!" msgstr[1] "%{attacker}'ların laneti %{target}'in üzerine geldi!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{attacker}'ın saldırısı %{target}'ı sakatladı!" msgstr[1] "%{attacker}'ın saldırısı %{target}'ları sakatladı!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "%{attacker} %{target} üzerindeki tüm iyi büyüleri yok etti!" msgstr[1] "%{attacker} %{target} üzerindeki tüm iyi büyüleri yok etti!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} %{target}'a %{spell} uyguladı!" msgstr[1] "%{attacker} %{target}'a %{spell} uyguladı!" msgid "Bad luck descends on the %{attacker}." msgstr "Kötü ÅŸans %{attacker} üzerine çöktü." msgid "Good luck shines on the %{attacker}." msgstr "İyi ÅŸans %{attacker} üzerine parladı." msgid "High morale enables the %{monster} to attack again." msgstr "Yüksek moral %{monster}'ın tekrar saldırmasını saÄŸlar." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Düşük moral %{monster}'ın panikten donmasına yol açtı." msgid "%{tower} does %{damage} damage." msgstr "%{tower} %{damage} hasar verir." msgid "The mirror image is created." msgstr "Ayna görüntüsü oluÅŸturuldu." msgid "The mirror image is destroyed!" msgstr "Ayna görüntüsü yok edildi!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Otomatik savaşı kesmek istediÄŸine emin misin?" msgid "Error" msgstr "Hata" msgid "No spells to cast." msgstr "Yapılacak büyü yok." msgid "Are you sure you want to retreat?" msgstr "Geri çekilmek istediÄŸine emin misin?" msgid "Retreat disabled" msgstr "Geri çekilme engellendi" msgid "Surrender disabled" msgstr "Teslim olma engellendi" msgid "Damage: %{max}" msgstr "Hasar: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Hasar: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Yok oldu: %{max}" msgid "Perish: %{min} - %{max}" msgstr "Yok oldu: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Kartal gözlü gözlem sayesinde, %{name} %{spell} sihirli büyüsünü öğrendi." msgid "Human" msgstr "İnsan" msgid "AI" msgstr "Bilgisayar" msgid "Start" msgstr "BaÅŸla" msgid "Start the battle." msgstr "Savaşı baÅŸlat." msgid "Exit" msgstr "Çıkış" msgid "Reset" msgstr "Sıfırla" msgid "Reset to default settings." msgstr "Varsayılan ayarlara sıfırla." msgid "Please select another hero." msgstr "Lütfen baÅŸka bir kahraman seç." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} vs %{race2} %{name2}" msgid "Monsters" msgstr "Canavarlar" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Sol Taret" msgid "Right Turret" msgstr "SaÄŸ Taret" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "each with a +%{attack} bonus to their attack skill." msgstr "her biri saldırı becerilerine +%{attack} bonusu ekler." msgid "The %{name} is destroyed." msgstr "%{name} yok edildi." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} tane %{name} ölümden uyandı!" msgstr[1] "%{count} tane %{name} ölümden uyandı!" msgid "Dwarven Alliance" msgstr "Cüce İttifakı" msgid "Sorceress Guild" msgstr "Büyücü Loncası" msgid "Necromancer Guild" msgstr "Ölüm Büyücüleri Loncası" msgid "Ogre Alliance" msgstr "Dev İttifakı" msgid "Dwarfbane" msgstr "Cücekaçıran" msgid "Dragon Alliance" msgstr "Ejderha İttifakı" msgid "Elven Alliance" msgstr "Elf İttifakı" msgid "Kraeger defeated" msgstr "Kraeger yenildi" msgid "Wayward Son" msgstr "Wayward OÄŸlu" msgid "Uncle Ivan" msgstr "Ivan Amca" msgid "Annexation" msgstr "İlhak" msgid "Force of Arms" msgstr "Silahların Gücü" msgid "Save the Dwarves" msgstr "Cüceleri Kurtar" msgid "Carator Mines" msgstr "Carator Madenleri" msgid "Turning Point" msgstr "Dönüm Noktası" msgid "scenarioName|Defender" msgstr "Savunucu" msgid "Corlagon's Defense" msgstr "Corlagon'un Savunması" msgid "The Crown" msgstr "Taç" msgid "The Gauntlet" msgstr "Eldiven" msgid "Betrayal" msgstr "İhanet" msgid "Final Justice" msgstr "Son Adalet" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland, kardeÅŸine karşı isyan savaşını baÅŸlatmak için kalesinin yakınındaki " "lordları yenmenize ihtiyaç duyuyor. Birbirleriyle müttefik deÄŸiller, bu " "yüzden zamanlarının çoÄŸunu birbirleriyle savaÅŸarak geçirecekler. Tüm " "kalelerini ve kahramanlarını yendiÄŸinizde zafer sizindir." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Yerel lordlar Roland'a baÄŸlılık yemini etmeyi reddediyor ve bastırılmaları " "gerekiyor. Zengin ve güçlüler, bu yüzden zorlu bir mücadeleye hazır olun. " "Kazanmak için tüm düşman kalelerini ele geçirin." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Göreviniz Cüceleri Archibald'ın güçlerine karşı savunmaktır. Kazanmak için " "tüm düşman kasabalarını ve kalelerini ele geçirin ve tüm cüce kasabalarını " "bir kerede kaybetmemeye dikkat edin, aksi takdirde düşman kazanmış olur." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Kaynaklar ve hazine için dört müttefik düşmanla düz bir mücadelede karşı " "karşıya geleceksin. Zafer için tüm düşman kalelerini ele geçir." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Düşmanlarınız size karşı müttefik ve yakınınızda baÅŸlıyor, bu yüzden " "savaÅŸmaya hazır olun. Kazanmak için bu küçük vadideki dört kalenin hepsini " "ele geçirmeniz gerekecek." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Noraston'daki Büyücüler Loncası, Archibald'ın müttefiklerinden gelen bir " "saldırıya karşı Roland'ın yardımını istedi. Kazanmak için tüm düşman " "kalelerini ele geçirin ve Noraston'u kaybetmeyin, yoksa senaryoyu " "kaybedersiniz. (İpucu: Okyanustaki bir adada düşman kalesi var.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Mümkün olduÄŸunca büyük bir ordu toplayın ve düşman kalesini 8 hafta içinde " "ele geçirin. Karşınızda yalnızca bir düşman var, ancak düşman kalesine " "ulaÅŸmak için uzun bir yol kat etmelisiniz. Bu senaryonun sonunda ordunuzda " "bulunan herhangi bir birlik, son savaÅŸta sizinle olacak." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Archibald'ın kahramanları bulmadan önce Tacı bulun. Roland, Archibald'a " "karşı son savaÅŸta Taca ihtiyaç duyacaktır." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Üç müttefik düşman önünüzde duruyor ve zafer, Lord Corlagon da dahil. Roland " "kuzeybatıdaki bir kalede ve düşmana yenilirse kaybedeceksiniz. Lord " "Corlagon'u yakalamanın, final senaryosunda size karşı savaÅŸmamasını " "saÄŸlayacağını unutmayın." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Bu son savaÅŸ. Hem siz hem de düşmanınız tepeden tırnaÄŸa silahlanmış " "durumdasınız ve hepsi size karşı müttefik. Savaşı bitirmek için Archibald'ı " "yakalayın!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Taraf deÄŸiÅŸtirmek, düşmanın kalesine karşı üç kale bırakır. Bu savaÅŸ, " "savaşın geri kalanında karşılaÅŸacağınız en kolay savaÅŸ olacak...hain." msgid "Barbarian Wars" msgstr "Barbar savaÅŸları" msgid "First Blood" msgstr "İlk Kan" msgid "Necromancers" msgstr "Nekromansörler" msgid "Slay the Dwarves" msgstr "Cüceleri öldür" msgid "Country Lords" msgstr "Ülke Lordları" msgid "Dragon Master" msgstr "Ejderha Ustası" msgid "Rebellion" msgstr "İsyan" msgid "Apocalypse" msgstr "Kıyamet" msgid "Greater Glory" msgstr "Büyük Zafer" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Kral Archibald, bu bölgedeki üç düşmanı yenmenizi istiyor. Birbirleriyle " "müttefik deÄŸiller, bu yüzden enerjilerinin çoÄŸunu kendi aralarında savaÅŸarak " "geçirecekler. Tüm düşman kalelerine sahip olduÄŸunuzda ve savaÅŸacak kahraman " "kalmadığında kazanacaksınız." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Kuzeydeki barbar kabileleri fethederek birleÅŸtirmelisiniz. Önceki görevde " "olduÄŸu gibi, düşman size karşı müttefik deÄŸil, ancak emrinde daha fazla " "kaynak var. Tüm düşman kalelerine sahip olduÄŸunuzda ve savaÅŸacak kahraman " "kalmadığında kazanacaksınız." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "İyiliksever büyücüler Necromancer'ların kalesini ele geçirdi. Zafere ulaÅŸmak " "için onu geri almalısınız. Güçlü bir orduyla baÅŸlasanız da, bir kalenizin " "olmadığını ve 7 gün içinde bir tane almanız gerektiÄŸini, aksi takdirde bu " "savaşı kaybedeceÄŸinizi unutmayın. (İpucu: En yakın kale güneydoÄŸudadır.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Cücelerin Kral Archibald'ın planlarına müdahale edebilmeleri için " "fethedilmeleri gerekiyor. Roland'ın güçlerinin birden fazla kahramanı ve " "baÅŸlamak için birçok kasabası var, bu yüzden birden fazla yönden saldırıya " "hazır olun. Zaferi elde etmek için tüm düşman kasabalarını ve kalelerini ele " "geçirmelisiniz." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Roland'ın güçlerinin önderlik ettiÄŸi bir köylü isyanını bastırmalısınız. " "Hepsi size karşı müttefik, ancak size yardım edecek deneyimli bir kahraman " "olan Lord Corlagon var. Kazanmak için tüm düşman kalelerini ele geçirin." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Bu görevde size karşı müttefik olan iki düşman var. İkisi de iyi silahlanmış " "ve sizi adalarından çıkarmaya çalışıyorlar. Onlardan kaçının ve kazanmak " "için Dragon City'yi ele geçirin." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Emriniz, Roland'a hizmet etmeye yemin etmiÅŸ olan ülke lordlarını " "fethetmektir. Tüm düşman kaleleri size karşı birleÅŸmiÅŸtir. Kaleniz olmadan " "baÅŸladığınız için, haftanın sonundan önce bir kale ele geçirmek için acele " "etmelisiniz. Zafer için tüm düşman kalelerini ele geçirin." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Roland'ın kahramanları bulmadan önce Tacı bulun. Archibald, Roland'a karşı " "son savaÅŸta Taç'a ihtiyaç duyacaktır." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Bu son savaÅŸ. Hem siz hem de düşmanınız tepeden tırnaÄŸa silahlanmış " "durumdasınız ve hepsi size karşı müttefik. Savaşı kazanmak için Roland'ı " "yakalayın ve Archibald'ı savaÅŸta kaybetmemeye dikkat edin!" msgid "Arrow's Flight" msgstr "Ok'un UçuÅŸu" msgid "Island of Chaos" msgstr "Kaos Adası" msgid "The Abyss" msgstr "BoÅŸluk" msgid "Uprising" msgstr "YükseliÅŸ" msgid "Aurora Borealis" msgstr "Kuzey Işıkları" msgid "Betrayal's End" msgstr "İhanet'in Sonu" msgid "Corruption's Heart" msgstr "YolsuzluÄŸun Kalbi" msgid "The Giant's Pass" msgstr "Dev'in GeçiÅŸi" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "İmparatorluÄŸa bu bölgede faaliyet gösterebilmesi için gerekli olanakları " "saÄŸlamak amacıyla, asi yerel beyleri kontrol altına alın." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Bu alandaki tüm muhalefeti ortadan kaldırın. Daha sonra eserin ilk parçası " "sizin olacak." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "KuzeydoÄŸudaki büyücüler isyan ediyor! İmparatorluÄŸun iyiliÄŸi için daÄŸlara " "giderken onların zayıf ayaklanmasını bastırmalısın." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Kraeger, sizin geliÅŸinize hazırlık yaptıktan sonra, görevinizi engellemek " "için bir nekromansör gücü ayarladı. Üçüncü haftanın ilk gününden önce " "Scabsdale kalesini ele geçirmelisiniz, aksi takdirde Nekromansörler sizin " "için çok güçlü olacak." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Bu bölgedeki barbar despot henüz sizin varlığınızdan habersiz. KeÅŸfedilmeden " "ve saldırıya uÄŸramadan önce hemen güçlerinizi toplayın! Tüm düşman güçlerini " "bastırarak bölgeyi güvence altına alın." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "İmparatorluk bu bölgede zayıf. Bu bölgedeki tüm güçleri tamamen alt " "edemeyeceksiniz, bu yüzden misilleme saldırıları baÅŸlamadan önce elinizden " "geleni alın. Unutmayın, gerçek amacınız Anduran MiÄŸferi'ni ele geçirmek." msgid "For the good of the Empire, eliminate Kraeger." msgstr "İmparatorluÄŸun iyiliÄŸi için Kraeger'ı ortadan kaldırın." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Sonunda, İmparatorluÄŸu nekromanserin kötülüğünden kurtarma fırsatına ve " "olanaklarına sahipsin. Onları tamamen yok et ve sonsuza dek bir kahraman " "olarak anılacaksın." msgid "Border Towns" msgstr "Sınır Kasabaları" msgid "Conquer and Unify" msgstr "Fethet ve BirleÅŸtir" msgid "Crazy Uncle Ivan" msgstr "Çılgın Amca Ivan" msgid "The Wayward Son" msgstr "Wayward oÄŸlu" msgid "Ivory Gates" msgstr "FildiÅŸi Kapılar" msgid "The Elven Lands" msgstr "Elf Diyarları" msgid "The Epic Battle" msgstr "Epik SavaÅŸ" msgid "The Southern War" msgstr "Güney Savaşı" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Tüm düşman kabileleri fethedin ve birleÅŸtirin. Tüm torunların atası olan " "kahraman Jarkonas'ı kaybetmeyin." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Rakibiniz Harondale Krallığı, sınırınızdaki zayıf kasabalara saldırıyor! İlk " "saldırılarından kurtulun ve onları tamamen ezin!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "İnatçı oÄŸlunuz Joseph'i bulun, onun ıssız topraklarda yaÅŸadığı söyleniyor. " "Üçüncü ayın ilk gününden önce yapın, aksi takdirde ailenize hiçbir faydası " "olmayacaktır." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Çılgın amcan Ivan'ı kurtar. Dördüncü ayın ilk gününden önce onu bul yoksa " "krallığına hiçbir faydası olmayacak." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Krallığınızın güney sınırına saldıran barbarları yok edin! Düşmüş " "kasabalarınızı kurtarın ve ardından orman krallığını istila edin. Hiçbir " "düşmanı ayakta bırakmayın." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "İhanet sonucu düşen FildiÅŸi Kapılar kalesini geri al." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Elflerin gözüne gir. AÄŸaçların kesilmesine izin vermeyecekler, bu yüzden " "sana her 2 haftada bir odun göndereceÄŸiz. Görevini yedinci ayın ilk gününden " "önce tamamlamalısın, yoksa krallık kesinlikle düşecek.Elflerin gözüne gir. " "AÄŸaçların kesilmesine izin vermeyecekler, bu yüzden sana her 2 haftada bir " "odun göndereceÄŸiz. Görevini yedinci ayın ilk gününden önce tamamlamalısın, " "yoksa krallık kesinlikle düşecek." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Bu, rakip krallığınız Harondale'e karşı son savaşınız. Herkesi ortadan " "kaldırın ve kahraman Jarkonas VI'yı kaybetmeyin." msgid "Fount of Wizardry" msgstr "Büyücülük Pınarı" msgid "Power's End" msgstr "Güç'ün Sonu" msgid "The Eternal Scrolls" msgstr "Ebedi Parşömenler" msgid "The Shrouded Isles" msgstr "Örtülü Adalar" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Göreviniz büyülü Shrouded Isles'daki savaÅŸan büyücüleri yenmektir. Bu görevi " "tamamlamak size rakiplerinize karşı bir mücadele ÅŸansı verecektir." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" msgid "Blood is Thicker" msgstr "" msgid "King and Country" msgstr "" msgid "Pirate Isles" msgstr "" msgid "Stranded" msgstr "" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" msgid " bane" msgstr "" msgid " alliance" msgstr "" msgid "Carry-over forces" msgstr "" msgid " bonus" msgstr "" msgid " defeated" msgstr " yenildi" msgid " will always run away from your army." msgstr "" msgid " will be willing to join your army." msgstr "" msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "" msgid "The army will be carried over in the campaign." msgstr "" msgid "The kingdom will have +%{count} %{resource} each day." msgstr "" msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "" msgid "%{hero} can be hired during scenarios." msgstr "" msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "" msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "" msgid "campaignBonus|Animate Dead" msgstr "" msgid "campaignBonus|Chain Lightning" msgstr "" msgid "campaignBonus|Fireblast" msgstr "" msgid "campaignBonus|Mass Curse" msgstr "" msgid "campaignBonus|Mass Haste" msgstr "" msgid "campaignBonus|Mirror Image" msgstr "" msgid "campaignBonus|Resurrect" msgstr "" msgid "campaignBonus|Steelskin" msgstr "" msgid "campaignBonus|Summon Earth" msgstr "" msgid "campaignBonus|View Heroes" msgstr "" msgid "campaignBonus|Ballista" msgstr "" msgid "campaignBonus|Black Pearl" msgstr "" msgid "campaignBonus|Caster's Bracelet" msgstr "" msgid "campaignBonus|Defender Helm" msgstr "" msgid "campaignBonus|Breastplate" msgstr "" msgid "campaignBonus|Dragon Sword" msgstr "" msgid "campaignBonus|Fizbin Medal" msgstr "" msgid "campaignBonus|Foremost Scroll" msgstr "" msgid "campaignBonus|Gauntlets" msgstr "Eldivenler" msgid "campaignBonus|Hideous Mask" msgstr "" msgid "campaignBonus|Mage's Ring" msgstr "" msgid "campaignBonus|Major Scroll" msgstr "" msgid "campaignBonus|Medal of Honor" msgstr "" msgid "campaignBonus|Medal of Valor" msgstr "" msgid "campaignBonus|Minor Scroll" msgstr "" msgid "campaignBonus|Nomad Boots" msgstr "" msgid "campaignBonus|Power Axe" msgstr "" msgid "campaignBonus|Spiked Shield" msgstr "" msgid "campaignBonus|Stealth Shield" msgstr "" msgid "campaignBonus|Tax Lien" msgstr "" msgid "campaignBonus|Thunder Mace" msgstr "Yıldırım Topuzu" msgid "campaignBonus|Traveler's Boots" msgstr "" msgid "campaignBonus|White Pearl" msgstr "" msgid "campaignBonus|Basic Archery" msgstr "" msgid "campaignBonus|Advanced Archery" msgstr "" msgid "campaignBonus|Expert Archery" msgstr "" msgid "campaignBonus|Basic Ballistics" msgstr "" msgid "campaignBonus|Advanced Ballistics" msgstr "" msgid "campaignBonus|Expert Ballistics" msgstr "" msgid "campaignBonus|Basic Diplomacy" msgstr "" msgid "campaignBonus|Advanced Diplomacy" msgstr "" msgid "campaignBonus|Expert Diplomacy" msgstr "" msgid "campaignBonus|Basic Eagle Eye" msgstr "" msgid "campaignBonus|Advanced Eagle Eye" msgstr "" msgid "campaignBonus|Expert Eagle Eye" msgstr "" msgid "campaignBonus|Basic Estates" msgstr "" msgid "campaignBonus|Advanced Estates" msgstr "" msgid "campaignBonus|Expert Estates" msgstr "" msgid "campaignBonus|Basic Leadership" msgstr "" msgid "campaignBonus|Advanced Leadership" msgstr "" msgid "campaignBonus|Expert Leadership" msgstr "" msgid "campaignBonus|Basic Logistics" msgstr "" msgid "campaignBonus|Advanced Logistics" msgstr "" msgid "campaignBonus|Expert Logistics" msgstr "" msgid "campaignBonus|Basic Luck" msgstr "" msgid "campaignBonus|Advanced Luck" msgstr "" msgid "campaignBonus|Expert Luck" msgstr "" msgid "campaignBonus|Basic Mysticism" msgstr "" msgid "campaignBonus|Advanced Mysticism" msgstr "" msgid "campaignBonus|Expert Mysticism" msgstr "" msgid "campaignBonus|Basic Navigation" msgstr "" msgid "campaignBonus|Advanced Navigation" msgstr "" msgid "campaignBonus|Expert Navigation" msgstr "" msgid "campaignBonus|Basic Necromancy" msgstr "" msgid "campaignBonus|Advanced Necromancy" msgstr "" msgid "campaignBonus|Expert Necromancy" msgstr "" msgid "campaignBonus|Basic Pathfinding" msgstr "" msgid "campaignBonus|Advanced Pathfinding" msgstr "" msgid "campaignBonus|Expert Pathfinding" msgstr "" msgid "campaignBonus|Basic Scouting" msgstr "" msgid "campaignBonus|Advanced Scouting" msgstr "" msgid "campaignBonus|Expert Scouting" msgstr "" msgid "campaignBonus|Basic Wisdom" msgstr "" msgid "campaignBonus|Advanced Wisdom" msgstr "" msgid "campaignBonus|Expert Wisdom" msgstr "" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "" msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "Krallık senaryonun başında ekstradan %{amount} %{resource} alacaktır." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "" msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "" msgid "The starting alignment of the scenario will be %{race}." msgstr "" msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "" msgid "The main hero will have %{skill} at the start of the scenario." msgstr "" msgid "Roland" msgstr "" msgid "Archibald" msgstr "" msgid "Price of Loyalty" msgstr "" msgid "Voyage Home" msgstr "" msgid "Wizard's Isle" msgstr "" msgid "Descendants" msgstr "" msgid "Cannot build. You have already built here today." msgstr "" msgid "For this action it is necessary to build a castle first." msgstr "" msgid "The %{building} produces %{monster}." msgstr "" msgid "Requires:" msgstr "" msgid "Exit this menu without doing anything." msgstr "" msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "" msgid "This building has been disabled." msgstr "" msgid "Cannot afford the %{name}." msgstr "%{name} karşılanamıyor." msgid "The %{name} is already built." msgstr "%{name} zaten inÅŸa edildi." msgid "Cannot build the %{name}." msgstr "%{name} inÅŸa edilemiyor." msgid "Build %{name}." msgstr "" msgid "Blackridge" msgstr "" msgid "Hillstone" msgstr "" msgid "Pinehurst" msgstr "" msgid "Whiteshield" msgstr "" msgid "Woodhaven" msgstr "" msgid "Blackwind" msgstr "" msgid "Bloodreign" msgstr "" msgid "Dragontooth" msgstr "" msgid "Greywind" msgstr "" msgid "Portsmith" msgstr "" msgid "Atlantium" msgstr "" msgid "Middle Gate" msgstr "" msgid "Sansobar" msgstr "" msgid "Tundara" msgstr "" msgid "Vulcania" msgstr "" msgid "Baywatch" msgstr "" msgid "Fountainhead" msgstr "" msgid "Vertigo" msgstr "" msgid "Wildabar" msgstr "" msgid "Winterkill" msgstr "" msgid "Brindamoor" msgstr "" msgid "Lakeside" msgstr "" msgid "Nightshadow" msgstr "" msgid "Olympus" msgstr "" msgid "Sandcaster" msgstr "" msgid "Alamar" msgstr "" msgid "Burlock" msgstr "" msgid "Dragadune" msgstr "" msgid "Kalindra" msgstr "" msgid "Xabran" msgstr "" msgid "Algary" msgstr "" msgid "Basenji" msgstr "" msgid "Blackfang" msgstr "" msgid "New Dawn" msgstr "" msgid "Sorpigal" msgstr "" msgid "Avone" msgstr "" msgid "Big Oak" msgstr "" msgid "Chandler" msgstr "" msgid "Erliquin" msgstr "" msgid "Hampshire" msgstr "" msgid "Antioch" msgstr "" msgid "Avalon" msgstr "" msgid "Roc Haven" msgstr "" msgid "South Mill" msgstr "" msgid "Weed Patch" msgstr "" msgid "Brownston" msgstr "" msgid "Hilltop" msgstr "" msgid "Weddington" msgstr "" msgid "Westfork" msgstr "" msgid "Whittingham" msgstr "" msgid "Cathcart" msgstr "" msgid "Elk's Head" msgstr "" msgid "Roscomon" msgstr "" msgid "Sherman" msgstr "" msgid "Yorksford" msgstr "" msgid "Blackburn" msgstr "" msgid "Blacksford" msgstr "" msgid "Burton" msgstr "" msgid "Pig's Eye" msgstr "" msgid "Viper's Nest" msgstr "" msgid "Fenton" msgstr "" msgid "Lankershire" msgstr "" msgid "Lombard" msgstr "" msgid "Timberhill" msgstr "" msgid "Troy" msgstr "" msgid "Forder Oaks" msgstr "" msgid "Meramec" msgstr "" msgid "Quick Silver" msgstr "" msgid "Westmoor" msgstr "" msgid "Willow" msgstr "" msgid "Corackston" msgstr "" msgid "Sheltemburg" msgstr "" msgid "Cannot recruit - you already have a Hero in this town." msgstr "" msgid "Cannot recruit - you have too many Heroes." msgstr "" msgid "Cannot afford a Hero." msgstr "Kahraman karşılanamıyor." msgid "There is no room in the garrison for this army." msgstr "" msgid "Fortifications" msgstr "" msgid "Farm" msgstr "" msgid "Thatched Hut" msgstr "" msgid "Archery Range" msgstr "" msgid "Upg. Archery Range" msgstr "" msgid "Blacksmith" msgstr "" msgid "Upg. Blacksmith" msgstr "" msgid "Armory" msgstr "" msgid "Upg. Armory" msgstr "" msgid "Jousting Arena" msgstr "" msgid "Upg. Jousting Arena" msgstr "" msgid "Cathedral" msgstr "" msgid "Upg. Cathedral" msgstr "" msgid "Coliseum" msgstr "" msgid "Garbage Heap" msgstr "" msgid "Hut" msgstr "" msgid "Stick Hut" msgstr "" msgid "Upg. Stick Hut" msgstr "" msgid "Den" msgstr "" msgid "Adobe" msgstr "" msgid "Upg. Adobe" msgstr "" msgid "Bridge" msgstr "Köprü" msgid "Upg. Bridge" msgstr "" msgid "Pyramid" msgstr "" msgid "Rainbow" msgstr "" msgid "Crystal Garden" msgstr "" msgid "Treehouse" msgstr "" msgid "Cottage" msgstr "" msgid "Upg. Cottage" msgstr "" msgid "Stonehenge" msgstr "" msgid "Upg. Stonehenge" msgstr "" msgid "Fenced Meadow" msgstr "" msgid "sorceress|Red Tower" msgstr "" msgid "Dungeon" msgstr "" msgid "Waterfall" msgstr "Åželale" msgid "Cave" msgstr "MaÄŸara" msgid "Crypt" msgstr "" msgid "Nest" msgstr "Yuva" msgid "Maze" msgstr "Labirent" msgid "Upg. Maze" msgstr "" msgid "Swamp" msgstr "Bataklık" msgid "Green Tower" msgstr "YeÅŸil Kule" msgid "warlock|Red Tower" msgstr "" msgid "Black Tower" msgstr "Kara Kule" msgid "Library" msgstr "Kütüphane" msgid "Orchard" msgstr "Meyve bahçesi" msgid "Habitat" msgstr "Habitat" msgid "Pen" msgstr "Ağıl" msgid "Foundry" msgstr "Dökümhane" msgid "Upg. Foundry" msgstr "Dökümhane GeliÅŸtir" msgid "Cliff Nest" msgstr "Uçurum Yuvası" msgid "Ivory Tower" msgstr "FildiÅŸi kule" msgid "Upg. Ivory Tower" msgstr "FildiÅŸi kule GeliÅŸtir" msgid "Cloud Castle" msgstr "Bulut Kalesi" msgid "Upg. Cloud Castle" msgstr "Bulut Kalesi GeliÅŸtir" msgid "Storm" msgstr "Yıldırım" msgid "Skull Pile" msgstr "Kafatası Yığını" msgid "Excavation" msgstr "Kazı" msgid "Graveyard" msgstr "Mezarlık" msgid "Upg. Graveyard" msgstr "Mezarlığı GeliÅŸtir" msgid "Upg. Pyramid" msgstr "" msgid "Mansion" msgstr "" msgid "Upg. Mansion" msgstr "" msgid "Mausoleum" msgstr "" msgid "Upg. Mausoleum" msgstr "" msgid "Laboratory" msgstr "" msgid "Shrine" msgstr "" msgid "Special" msgstr "" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Büyü hedefini seç" #, fuzzy msgid "Dwelling 2" msgstr "Büyü hedefini seç" msgid "Upg. Dwelling 2" msgstr "" #, fuzzy msgid "Dwelling 3" msgstr "Büyü hedefini seç" msgid "Upg. Dwelling 3" msgstr "" #, fuzzy msgid "Dwelling 4" msgstr "Büyü hedefini seç" msgid "Upg. Dwelling 4" msgstr "" #, fuzzy msgid "Dwelling 5" msgstr "Büyü hedefini seç" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Büyü hedefini seç" #, fuzzy msgid "Dwelling 6" msgstr "Büyü hedefini seç" msgid "Upg. Dwelling 6" msgstr "" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" msgid "The Farm increases production of Peasants by %{count} per week." msgstr "" msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "" msgid "The Rainbow increases the luck of the defending units by two." msgstr "" msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "" msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "" msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "" msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "" msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" msgid "Thieves' Guild" msgstr "Hırsızlar Loncası" msgid "Tavern" msgstr "Meyhane" msgid "Shipyard" msgstr "Liman" msgid "Well" msgstr "Su Kuyusu" msgid "Statue" msgstr "Heykel" msgid "Marketplace" msgstr "Market" msgid "Moat" msgstr "Hendek" msgid "Castle" msgstr "Kale" msgid "Tent" msgstr "Çadır" msgid "Captain's Quarters" msgstr "Kaptanın Karargahı" msgid "Mage Guild, Level 1" msgstr "Büyücü Loncası, Level 1" msgid "Mage Guild, Level 2" msgstr "Büyücü Loncası, Level 2" msgid "Mage Guild, Level 3" msgstr "Büyücü Loncası, Level 3" msgid "Mage Guild, Level 4" msgstr "Büyücü Loncası, Level 4" msgid "Mage Guild, Level 5" msgstr "Büyücü Loncası, Level 5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" msgid "The Tavern increases morale for troops defending the castle." msgstr "" msgid "The Shipyard allows ships to be built." msgstr "" msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" msgid "The Statue increases the town's income by %{count} gold per day." msgstr "" msgid "The Left Turret provides extra firepower during castle combat." msgstr "" msgid "The Right Turret provides extra firepower during castle combat." msgstr "" msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" msgid "Recruit %{name}" msgstr "" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" msgid "Click to show next town." msgstr "" msgid "Show next town" msgstr "" msgid "Click to show previous town." msgstr "" msgid "Show previous town" msgstr "" msgid "This town may not be upgraded to a castle." msgstr "" msgid "Town" msgstr "" msgid "Exit Castle" msgstr "" msgid "Exit Town" msgstr "" msgid "Show Income" msgstr "" msgid "View Hero" msgstr "" msgid "The above spells are available here." msgstr "" msgid "The spells the hero can learn have been added to their book." msgstr "" msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" msgid "Recruit Hero" msgstr "" msgid "%{name} is a level %{value} %{race} " msgstr "" msgid "with %{count} artifacts." msgstr "" msgid "with 1 artifact." msgstr "" msgid "without artifacts." msgstr "" msgid "Recruit %{name} the %{race}" msgstr "" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" msgid "Spread Formation" msgstr "" msgid "Grouped Formation" msgstr "" msgid "Click to show the next town." msgstr "" msgid "Click to show the previous town." msgstr "" msgid "Set garrison combat formation to 'Spread'" msgstr "" msgid "Set garrison combat formation to 'Grouped'" msgstr "" msgid "Exit Castle Options" msgstr "" msgid "Castle Options" msgstr "" msgid "Not enough resources to recruit creatures." msgstr "" msgid "You are unable to recruit at this time, your ranks are full." msgstr "" msgid "No creatures available for purchase." msgstr "" msgid "Recruit Creatures" msgstr "" msgid "Hire all creatures in the town." msgstr "" msgid "Max" msgstr "" msgid "Available" msgstr "" msgid "Town Population Information and Statistics" msgstr "" msgid "Damage" msgstr "" msgid "HP" msgstr "" msgid "Growth" msgstr "" msgid "week" msgstr "" msgid "View World" msgstr "" msgid "View the entire world." msgstr "" msgid "Puzzle" msgstr "" msgid "View the obelisk puzzle." msgstr "" msgid "Scenario Information" msgstr "" msgid "View information on the scenario you are currently playing." msgstr "" msgid "Dig for the Ultimate Artifact." msgstr "" msgid "Digging" msgstr "" msgid "Arena" msgstr "" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" msgid "Attack Skill" msgstr "" msgid "Defense Skill" msgstr "" msgid "Shots" msgstr "" msgid "Shots Left" msgstr "" msgid "Hit Points" msgstr "" msgid "Hit Points Left" msgstr "" msgid "You can't afford to upgrade your troops!" msgstr "" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" msgid "Are you sure you want to dismiss this army?" msgstr "" msgid "Upgrade" msgstr "" msgid "Upgrade your troops." msgstr "" msgid "Dismiss" msgstr "" msgid "Dismiss this army." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" msgid "Followers" msgstr "" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" msgid "(Rate: %{percent})" msgstr "" msgid "off" msgstr "" msgid "Music" msgstr "" msgid "Effects" msgstr "" msgid "MIDI" msgstr "" msgid "MIDI Expansion" msgstr "" msgid "External" msgstr "" msgid "Music Type" msgstr "" msgid "3D Audio" msgstr "" msgid "Toggle ambient music level." msgstr "" msgid "Toggle foreground sounds level." msgstr "" msgid "Change the type of music." msgstr "" msgid "Toggle the 3D effect of foreground sounds." msgstr "" msgid "Build a new ship:" msgstr "" msgid "Resource cost:" msgstr "" msgid "Total: " msgstr "" msgid "Need: " msgstr "" msgid "New Game" msgstr "Yeni Oyun" msgid "Start a single or multi-player game." msgstr "Tek yada Çoklu bir oyun baÅŸlat." msgid "Load Game" msgstr "Oyunu Yükle" msgid "Load a previously saved game." msgstr "Önceden kaydedilmiÅŸ bir oyunu yükle." msgid "Save Game" msgstr "Oyunu Kaydet" msgid "Save the current game." msgstr "Åžu anki oyunu kaydet." msgid "Quit" msgstr "Çıkış" msgid "Quit out of Heroes of Might and Magic II." msgstr "Heroes of Might and Magic II'den çık." msgid "Language" msgstr "Dil" msgid "Graphics" msgstr "Grafikler" msgid "Black & White" msgstr "Siyah & Beyaz" msgid "Mouse Cursor" msgstr "Fare İmleci" msgid "Color" msgstr "Renkli" msgid "Text Support" msgstr "Yazı DesteÄŸi" msgid "Change the language of the game." msgstr "Oyunun dilini deÄŸiÅŸtir." msgid "Select Game Language" msgstr "Oyunun dilini seç" msgid "Change the graphics settings of the game." msgstr "Oyunun grafik ayarlarını deÄŸiÅŸ." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Renkli imleci aç ya da kapat. Bu sadece estetik bir seçimdir." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Oyun içindeki pencereler ve olaylar hakkında ek bilgi çıkışı saÄŸlamak için " "metin desteÄŸi modunu açın/kapatın." msgid "" "Map\n" "Difficulty" msgstr "" "Harita\n" "ZorluÄŸu" msgid "" "Game\n" "Difficulty" msgstr "" "Oyun\n" "ZorluÄŸu" msgid "Rating" msgstr "Derecelendirme" msgid "Map Size" msgstr "Harita Boyu" msgid "Opponents" msgstr "Rakipler" msgid "Class" msgstr "Sınıf" msgid "" "Victory\n" "Conditions" msgstr "" "Zafer\n" "Åžartları" msgid "" "Loss\n" "Conditions" msgstr "" "Yenilgi\n" "Åžartları" msgid "First select recipients!" msgstr "Önce alıcıları seçin!" msgid "You cannot select %{resource}!" msgstr "%{resource} seçemezsin!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "%{monster} sayısını ayarla" msgid "Select Recipients" msgstr "Alıcıları Seçin" msgid "Your Funds" msgstr "Paranız" msgid "Planned Gift" msgstr "Planlanmış Hediye" msgid "Gift from %{name}" msgstr "%{name}'dan hediye" msgid "Resolution" msgstr "Çözünürlük" msgid "Fullscreen" msgstr "Tam Ekran" msgid "window|Mode" msgstr "Modu" msgid "Windowed" msgstr "Pencere" msgid "V-Sync" msgstr "Dikey EÅŸitleme" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Sistem Bilgisi" msgid "Change the resolution of the game." msgstr "Oyunun çözünürlüğünü deÄŸiÅŸ." msgid "Select Game Resolution" msgstr "Oyunun çözünürlüğünü seç" msgid "Toggle between fullscreen and windowed modes." msgstr "Tam ve pencereli ekran arasında geçiÅŸ yap." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "Dikey eÅŸitleme ayarı bazı monitörlerde yırtılma sorununu çözer." msgid "Show extra information such as FPS and current time." msgstr "FPS ve zaman hakkında ekstra bilgi göster." msgid "Hotkey: " msgstr "Kısayol: " msgid "Category: " msgstr "Kategori: " msgid "Event: " msgstr "Etkinlik: " msgid "Hot Keys:" msgstr "Kısayollar:" msgid "Hide" msgstr "Gizle" msgid "Show" msgstr "Göster" msgid "Interface" msgstr "Arayüz" msgid "Interface Type" msgstr "Arayüz Tipi" msgid "Toggle the type of interface you want to use." msgstr "Kullanmak istediÄŸiniz arayüz türünü deÄŸiÅŸtirin." msgid "Toggle interface visibility." msgstr "Arayüz görünürlüğünü deÄŸiÅŸtirin." msgid "Scroll Speed" msgstr "Kaydırma Hızı" msgid "Sets the speed at which you scroll the window." msgstr "Pencereyi kaydırma hızını ayarlar." msgid "Select Game Language:" msgstr "Oyunun dilini seç:" msgid "Select Language:" msgstr "Dil Seç:" msgid "Click to choose the selected language." msgstr "Seçili dili seçmek için tıklayın." msgid "%{name} has gained a level." msgstr "%{name} level kazandı." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "%{skill} öğrendin." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} level kazandı.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Ya %{skill1}\n" "ya da\n" "%{skill2} öğrenebilirsin." msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/a" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Lütfen kaliteli ürünlerimizi inceleyin. Bir takas teklif etmek isterseniz, " "takas etmek istediÄŸiniz ve takas etmek istediÄŸiniz ürünlere tıklayın." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "" msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" msgid "Min" msgstr "" msgid "Qty to trade" msgstr "" msgid "Trading Post" msgstr "" msgid "Your Resources" msgstr "" msgid "Available Trades" msgstr "" msgid "guarded by %{count} %{monster}" msgstr "" msgid "guarded by " msgstr "" msgid "(available: %{count})" msgstr "" msgid "(empty)" msgstr "" msgid "already learned" msgstr "" msgid "treeOfKnowledge|free" msgstr "ücretsiz" msgid "already claimed" msgstr "" msgid "not claimed" msgstr "" msgid "already knows this skill" msgstr "" msgid "already has max skills" msgstr "" msgid "(already visited)" msgstr "" msgid "(not visited)" msgstr "" msgid "%{color} Barrier" msgstr "" msgid "(tent visited)" msgstr "" msgid "%{color} Tent" msgstr "" msgid "Road" msgstr "" msgid "(digging ok)" msgstr "" msgid "(no digging)" msgstr "" msgid "penalty: %{cost}" msgstr "" msgid "Defenders:" msgstr "" msgid "Unknown" msgstr "" msgid "heroQuickInfo|(Level %{level})" msgstr "" msgid "Attack:" msgstr "" msgid "Defense:" msgstr "" msgid "Spell Power:" msgstr "" msgid "Knowledge:" msgstr "" msgid "Spell Points:" msgstr "" msgid "Move Points:" msgstr "" msgid "Uncharted Territory" msgstr "" msgid "Cost per troop:" msgstr "" msgid "Available: %{count}" msgstr "" msgid "Number to buy:" msgstr "" msgid "Recruit selected monsters." msgstr "" msgid "Select maximum monsters to be recruited." msgstr "" msgid "Select only 1 monster to be recruited." msgstr "" msgid "Select this game resolution." msgstr "" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "" msgid "Click to apply the selected resolution." msgstr "" msgid "Click to apply the entered text." msgstr "" msgid "Click to open the Virtual Keyboard dialog." msgstr "" msgid "Open Virtual Keyboard" msgstr "" msgid "How many creatures do you wish to move?" msgstr "" msgid "Select how many units to separate into:" msgstr "" msgid "Map: " msgstr "" msgid "" "\n" "\n" "Month: " msgstr "" msgid ", Week: " msgstr "" msgid ", Day: " msgstr "" msgid "" "\n" "\n" "Location: " msgstr "" msgid "Are you sure you want to delete file:" msgstr "" msgid "Warning" msgstr "Uyarı" msgid "Click to save the current game." msgstr "" msgid "Click to load a previously saved game." msgstr "" msgid "File to Save:" msgstr "" msgid "File to Load:" msgstr "" msgid "Terrain object" msgstr "" msgid "Accept the choice made." msgstr "" msgid "Select Skill:" msgstr "" msgid "Select Spell:" msgstr "" msgid "Select Artifact:" msgstr "" msgid "Select Monster:" msgstr "" msgid "Select Hero:" msgstr "" msgid "race|Random" msgstr "" msgid "Click to start placing the selected hero." msgstr "" msgid "%{color} %{race}" msgstr "%{color} %{race}" msgid "You will place" msgstr "" msgid "Click to select this class." msgstr "" msgid "Click to select this color." msgstr "" msgid "Select Treasure:" msgstr "Defineyi seç:" msgid "Select Ocean Object:" msgstr "Okyanus Hedefini Seç:" msgid "Castle/town placing" msgstr "" msgid "doubleLinedRace|Neutral" msgstr "" msgid "Click to start placing the selected castle/town." msgstr "" msgid "Click to select town placing." msgstr "" msgid "Click to select castle placing." msgstr "" msgid "%{color} %{race} %{townOrCastle}" msgstr "" msgid "race|Neutral" msgstr "" #, fuzzy msgid "Select Dwelling:" msgstr "Büyü hedefini seç" #, fuzzy msgid "Select Landscape Object:" msgstr "Büyü hedefini seç" msgid "Mine placing" msgstr "" msgid "" "Resource\n" "type:" msgstr "" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name} %{race}" msgid "Click to select %{object} as the resource generator to be placed." msgstr "" #, fuzzy msgid "Select Mountain Object:" msgstr "Büyü hedefini seç" #, fuzzy msgid "Select Rock Object:" msgstr "Büyü hedefini seç" #, fuzzy msgid "Select Tree Object:" msgstr "Büyü hedefini seç" #, fuzzy msgid "Select Power Up Object:" msgstr "Büyü hedefini seç" #, fuzzy msgid "Select Adventure Object:" msgstr "Büyü hedefini seç" msgid "Players Icon" msgstr "" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" msgid "Size Icon" msgstr "" msgid "Map Type" msgstr "" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" msgid "Map Type:\n" msgstr "" msgid "The Succession Wars" msgstr "" msgid "The Price of Loyalty" msgstr "" msgid "Resurrection" msgstr "" msgid "" "\n" "\n" "Language:\n" msgstr "" msgid "Lose all your heroes and towns." msgstr "" msgid "Lose a specific town." msgstr "" msgid "Lose a specific hero." msgstr "" msgid "Run out of time. Fail to win by a certain point." msgstr "" msgid "Loss Condition" msgstr "" msgid "Defeat all enemy heroes and towns." msgstr "" msgid "Capture a specific town." msgstr "" msgid "Defeat a specific hero." msgstr "" msgid "Find a specific artifact." msgstr "" msgid "Your side must defeat the opposing side." msgstr "" msgid "Accumulate a large amount of gold." msgstr "" msgid "Victory Condition" msgstr "" msgid "Map difficulty:" msgstr "" msgid "N" msgstr "" msgid "No maps exist at that size." msgstr "" msgid "Small Maps" msgstr "" msgid "View only maps of size small (36 x 36)." msgstr "" msgid "Medium Maps" msgstr "" msgid "View only maps of size medium (72 x 72)." msgstr "" msgid "Large Maps" msgstr "" msgid "View only maps of size large (108 x 108)." msgstr "" msgid "Extra Large Maps" msgstr "" msgid "View only maps of size extra large (144 x 144)." msgstr "" msgid "All Maps" msgstr "" msgid "View all maps, regardless of size." msgstr "" msgid "Selected Name" msgstr "" msgid "The name of the currently selected map." msgstr "" msgid "Selected Map Difficulty" msgstr "" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" msgid "Selected Description" msgstr "" msgid "The description of the currently selected map." msgstr "" msgid "Jump" msgstr "" msgid "Hero Speed" msgstr "" msgid "Don't Show" msgstr "" msgid "Enemy Speed" msgstr "" msgid "Auto Resolve" msgstr "" msgid "Auto, No Spells" msgstr "" msgid "Battles" msgstr "" msgid "combatMode|Manual" msgstr "" msgid "Change the speed at which your heroes move on the main screen." msgstr "" msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" msgid "Change the interface settings of the game." msgstr "" msgid "Interface Settings" msgstr "" msgid "Toggle instant battle mode." msgstr "" msgid "Att." msgstr "" msgid "Def." msgstr "" msgid "Power" msgstr "" msgid "Knowl" msgstr "" msgid "1st" msgstr "" msgid "2nd" msgstr "" msgid "3rd" msgstr "" msgid "4th" msgstr "" msgid "5th" msgstr "" msgid "6th" msgstr "" msgid "Oracle: Player Rankings" msgstr "" msgid "Thieves' Guild: Player Rankings" msgstr "" msgid "Number of Towns:" msgstr "" msgid "Number of Castles:" msgstr "" msgid "Number of Heroes:" msgstr "" msgid "Gold in Treasury:" msgstr "" msgid "Wood & Ore:" msgstr "" msgid "Gems, Cr, Slf & Mer:" msgstr "" msgid "Obelisks Found:" msgstr "" msgid "Artifacts:" msgstr "" msgid "Total Army Strength:" msgstr "" msgid "Income:" msgstr "" msgid "Best Hero:" msgstr "" msgid "Best Hero Stats:" msgstr "" msgid "Personality:" msgstr "" msgid "Best Monster:" msgstr "" msgid "Random Castle Name" msgstr "" msgid "Random Town Name" msgstr "" msgid "Allow Castle build" msgstr "" msgid "Default Buildings" msgstr "" msgid "Default Army" msgstr "" msgid "Castle Army" msgstr "" #, fuzzy msgid "Town Army" msgstr "Kahraman Ekranı" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" msgid "Enter Castle name" msgstr "" msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Mesaj ÇubuÄŸu" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Mesaj ÇubuÄŸu" #, fuzzy msgid "Click to save the Event properties." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "No resources will be given as a reward." msgstr "" msgid "Resources" msgstr "" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Add Event" msgstr "" msgid "Add an additional event." msgstr "" msgid "Edit Event" msgstr "" msgid "Edit an existing event." msgstr "" msgid "Delete Event" msgstr "" msgid "Delete an existing event." msgstr "" msgid "Effects:" msgstr "" #, fuzzy msgid "Conditions:" msgstr "" "Yenilgi\n" "Åžartları" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" msgid "Set Experience value" msgstr "" msgid "Artifact" msgstr "" msgid "No artifact will be given by the event." msgstr "" msgid "Delete Artifact" msgstr "" msgid "Delete an artifact from the event." msgstr "" msgid "No Secondary Skill will be given by the event." msgstr "" msgid "Secondary Skill" msgstr "" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" msgid "%{objects} cannot be placed on water." msgstr "" msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" msgid "%{objects} must be placed on water." msgstr "" msgid "Objects cannot be placed outside the map." msgstr "" msgid "Action objects must be placed on clear tiles." msgstr "" msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" msgid "Editor" msgstr "" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "BAÅžLA" msgid "Main Menu" msgstr "" msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "BaÅŸla" msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" msgid "Create a new map from scratch." msgstr "" msgid "New Map" msgstr "Yeni Harita" msgid "Load Map" msgstr "Harita Yükle" msgid "Load an existing map." msgstr "" msgid "Save Map" msgstr "" msgid "Save the current map." msgstr "" msgid "Quit out of the map editor." msgstr "" #, fuzzy msgid "Return to the game's Main Menu." msgstr "SavaÅŸa geri dön." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" msgid "Set Random Ultimate Artifact Radius" msgstr "" msgid "%{object} has no properties to change." msgstr "" msgid "This artifact" msgstr "" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "" msgid "Streams" msgstr "" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "" msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "Ayna görüntüsü oluÅŸturuldu." msgid "Unable to locate data directory to save the map." msgstr "" msgid "Unable to create a directory to save the map." msgstr "" msgid "Unable to locate a directory to save the map." msgstr "" #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Otomatik savaşı kesmek istediÄŸine emin misin?" msgid "Map saved to: " msgstr "" msgid "Failed to save the map." msgstr "" msgid "Used to place %{object}." msgstr "" #, fuzzy msgid "Select object type" msgstr "Büyü hedefini seç" msgid "" "Click here to\n" "select a monster." msgstr "" #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Lütfen baÅŸka bir kahraman seç." msgid "" "Cell\n" "Details" msgstr "" msgid "Erase" msgstr "" msgid "Mountains" msgstr "" msgid "Rocks" msgstr "" msgid "Trees" msgstr "AÄŸaçlar" msgid "Water Objects" msgstr "" msgid "Miscellaneous" msgstr "" msgid "Artifacts" msgstr "" msgid "Dwellings" msgstr "" msgid "Mines" msgstr "" msgid "Power-ups" msgstr "" msgid "Treasures" msgstr "" msgid "Heroes" msgstr "" msgid "Towns" msgstr "" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Büyü hedefini seç" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" msgid "Small Brush" msgstr "" msgid "Medium Brush" msgstr "" msgid "Large Brush" msgstr "" msgid "Area Fill" msgstr "" msgid "Used to click and drag for filling in large areas." msgstr "" msgid "Clear Area" msgstr "" msgid "Used to click and drag for clearing large areas." msgstr "" msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" msgid "Traversable only by boat." msgstr "" msgid "No special modifiers." msgstr "" msgid "Toggle the erasure of %{type} objects." msgstr "" msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" msgid "Terrain Mode" msgstr "" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" msgid "Landscape Objects Mode" msgstr "" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" msgid "Detail Mode" msgstr "" msgid "Used for special editing of action objects." msgstr "" msgid "Adventure Objects Mode" msgstr "" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" msgid "Kingdom Objects Mode" msgstr "" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" #, fuzzy msgid "Monsters Mode" msgstr "Canavarlar" msgid "Used to place monsters on the map." msgstr "" msgid "Allows you to draw streams by clicking and dragging." msgstr "" msgid "Stream Mode" msgstr "" msgid "Allows you to draw roads by clicking and dragging." msgstr "" msgid "Road Mode" msgstr "" msgid "Erase Mode" msgstr "" msgid "Used to erase objects from the map." msgstr "" msgid "Change between zoom and normal view." msgstr "" msgid "Magnify" msgstr "" msgid "Undo" msgstr "" msgid "Undo your last action." msgstr "" msgid "Redo" msgstr "" msgid "Redo the last undone action." msgstr "" msgid "Edit map title, description, and other general information." msgstr "" msgid "Specifications" msgstr "" msgid "File Options" msgstr "" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" msgid "View the editor system options, which let you customize the editor." msgstr "" msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" msgid "Cancel back to the New Map menu." msgstr "" msgid "Cancel back to the main menu." msgstr "" msgid "From Scratch" msgstr "" msgid "Start from scratch with a blank map." msgstr "" msgid "Create a randomly generated map." msgstr "" msgid "Random" msgstr "" msgid "Cancel back to the Map Editor main menu." msgstr "" msgid "No maps available!" msgstr "" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{name} %{race}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race1} %{name1}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{name} %{race}" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{name} %{race}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race1} %{name1}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{race1} %{name1}" #, fuzzy msgid "None." msgstr "Hiç" #, fuzzy msgid "One side defeats another." msgstr "Lütfen baÅŸka bir kahraman seç." msgid "Accumulate gold." msgstr "" msgid "Run out of time." msgstr "" #, fuzzy msgid "alliance|1st" msgstr "Mancınık" msgid "alliance|2nd" msgstr "" msgid "alliance|3rd" msgstr "" msgid "alliance|4th" msgstr "" msgid "alliance|5th" msgstr "" msgid "Special Loss Condition" msgstr "" msgid "Special Victory Condition" msgstr "" msgid "Allow standard victory conditions" msgstr "" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr "Dev İttifakı" # msgid "{%number} alliance: " msgstr "" msgid "Gold:" msgstr "" msgid "Select a Town to capture to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Map Difficulty" msgstr "" msgid "Map Description" msgstr "" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" msgid "Change Map Description" msgstr "" #, fuzzy msgid "Click to accept the changes made." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" #, fuzzy msgid "Click to edit custom rumors." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Events" msgstr "" #, fuzzy msgid "Click to change the language of the map." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Click to change your map name." msgstr "" msgid "Map Name" msgstr "" #, fuzzy msgid "Click to change the description of the current map." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Indicates the player types in the scenario. Click to change." msgstr "" msgid "Player Type" msgstr "" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" #, fuzzy msgid "editor|%{count} %{resource}" msgstr "%{resource} sayısını seç:" msgid "Animation" msgstr "" msgid "Passability" msgstr "" msgid "Toggle animation of the objects." msgstr "" msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Add Rumor" msgstr "" msgid "Add an additional rumor." msgstr "" msgid "Edit Rumor" msgstr "" msgid "Edit an existing rumor." msgstr "" msgid "Delete Rumor" msgstr "" msgid "Delete an existing rumor." msgstr "" msgid "" "\n" "\n" "Size: " msgstr "" msgid "" "\n" "\n" "Description: " msgstr "" msgid "Save Map:" msgstr "" #, fuzzy msgid "Click to save the current map." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "" msgid "difficulty|Normal" msgstr "" msgid "difficulty|Hard" msgstr "" msgid "difficulty|Expert" msgstr "" msgid "difficulty|Impossible" msgstr "" msgid "and more..." msgstr "" msgid "Easy" msgstr "" msgid "Normal" msgstr "Normal" msgid "Hard" msgstr "" msgid "Campaign Difficulty" msgstr "" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" msgid "Start the selected scenario." msgstr "" msgid "View Intro" msgstr "" msgid "View the intro video for the current state of the campaign." msgstr "" msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" msgid "Restart the current scenario." msgstr "" msgid "Difficulty" msgstr "" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" msgid "Are you sure you want to restart this scenario?" msgstr "" msgid "Campaign Scenario loading failure" msgstr "" msgid "Please make sure that campaign files are correct and present." msgstr "" msgid "Days spent" msgstr "Geçen Günler" msgid "The number of days spent on this campaign." msgstr "" msgid "Project Coordination and Core Development" msgstr "" msgid "Development" msgstr "" msgid "Visit us at " msgstr "" msgid "QA and Support" msgstr "" msgid "Dev and Support" msgstr "" msgid "Special Thanks to" msgstr "" msgid "and many-many other contributors and supporters!" msgstr "" msgid "Support us at" msgstr "" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "" msgid "Original project before 0.7" msgstr "" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "" msgid "Designed and Directed" msgstr "" msgid "Programming and Design" msgstr "" msgid "Executive Producer" msgstr "" msgid "Producer" msgstr "" msgid "Additional Design" msgstr "" msgid "Additional Programming" msgstr "" msgid "Musical Production" msgstr "" msgid "Music and Sound Design" msgstr "" msgid "Vocalists" msgstr "" msgid "Art Director" msgstr "" msgid "Assistant Art Director" msgstr "" msgid "Artists" msgstr "" msgid "QA Manager" msgstr "" msgid "QA" msgstr "" msgid "Writing" msgstr "" msgid "Manual and Helpfile" msgstr "" msgid "Scenarios" msgstr "" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "" msgid "Design Lead" msgstr "" msgid "Designers" msgstr "" msgid "Programming Lead" msgstr "" msgid "Art Lead" msgstr "" msgid "Playtesters" msgstr "" msgid "Designer" msgstr "" msgid "Producers" msgstr "" msgid "QA Managers" msgstr "" msgid "Sound Design" msgstr "" msgid "Town Themes" msgstr "" msgid "Alto Sax" msgstr "" msgid "Harpsichord and Piano" msgstr "" msgid "Basso Vocal" msgstr "" msgid "Soprano Vocal" msgstr "" msgid "Recorded at %{recordingStudio}" msgstr "" msgid "credits|Manual" msgstr "" msgid "German Consultant" msgstr "" msgid "Map Designers" msgstr "" msgid "Package Design" msgstr "" msgid "High Scores" msgstr "" msgid "Your Name" msgstr "" msgid "Unknown Hero" msgstr "" msgid "Standard" msgstr "" msgid "View High Scores for Standard Maps." msgstr "" msgid "Campaign" msgstr "" msgid "View High Scores for Campaigns." msgstr "" msgid "hotkey|default okay event" msgstr "" msgid "hotkey|default cancel event" msgstr "" msgid "hotkey|default left" msgstr "" msgid "hotkey|default right" msgstr "" msgid "hotkey|default up" msgstr "" msgid "hotkey|default down" msgstr "" msgid "hotkey|toggle fullscreen" msgstr "" msgid "hotkey|toggle text support mode" msgstr "" msgid "hotkey|toggle developer mode" msgstr "" msgid "hotkey|new game" msgstr "" msgid "hotkey|load game" msgstr "" msgid "hotkey|high scores" msgstr "" msgid "hotkey|credits" msgstr "" msgid "hotkey|standard game" msgstr "" msgid "hotkey|campaign game" msgstr "" msgid "hotkey|multi-player game" msgstr "" msgid "hotkey|settings" msgstr "" msgid "hotkey|quit" msgstr "" msgid "hotkey|select map" msgstr "" msgid "hotkey|select small map size" msgstr "" msgid "hotkey|select medium map size" msgstr "" msgid "hotkey|select large map size" msgstr "" msgid "hotkey|select extra large map size" msgstr "" msgid "hotkey|select all map sizes" msgstr "" #, fuzzy msgid "hotkey|hot seat game" msgstr "Sistem seçeneklerini özelleÅŸtirin" msgid "hotkey|battle only game" msgstr "sadece savaÅŸ oyunu" msgid "hotkey|choose the original campaign" msgstr "" msgid "hotkey|choose the expansion campaign" msgstr "" msgid "hotkey|map editor main menu" msgstr "" msgid "hotkey|new map menu" msgstr "" msgid "hotkey|load map menu" msgstr "" msgid "hotkey|new map from scratch" msgstr "" msgid "hotkey|new random map" msgstr "" #, fuzzy msgid "hotkey|undo last action" msgstr "Sistem seçeneklerini özelleÅŸtirin" #, fuzzy msgid "hotkey|redo last action" msgstr "Sistem seçeneklerini özelleÅŸtirin" #, fuzzy msgid "hotkey|open game main menu" msgstr "Sistem seçeneklerini özelleÅŸtirin" msgid "hotkey|toggle passability" msgstr "" msgid "hotkey|roland campaign" msgstr "" msgid "hotkey|archibald campaign" msgstr "" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "Sistem seçeneklerini özelleÅŸtirin" msgid "hotkey|voyage home campaign" msgstr "" msgid "hotkey|wizard's isle campaign" msgstr "" msgid "hotkey|descendants campaign" msgstr "" msgid "hotkey|select first campaign bonus" msgstr "" msgid "hotkey|select second campaign bonus" msgstr "" msgid "hotkey|select third campaign bonus" msgstr "" msgid "hotkey|view campaign intro" msgstr "" msgid "hotkey|select campaign difficulty" msgstr "" msgid "hotkey|restart campaign scenario" msgstr "" msgid "hotkey|world map left" msgstr "" msgid "hotkey|world map right" msgstr "" msgid "hotkey|world map up" msgstr "" msgid "hotkey|world map down" msgstr "" msgid "hotkey|world map up left" msgstr "" msgid "hotkey|world map up right" msgstr "" msgid "hotkey|world map down left" msgstr "" msgid "hotkey|world map down right" msgstr "" msgid "hotkey|save game" msgstr "" msgid "hotkey|next hero" msgstr "" msgid "hotkey|change to hero under cursor" msgstr "" msgid "hotkey|start hero movement" msgstr "" msgid "hotkey|cast adventure spell" msgstr "" msgid "hotkey|put hero to sleep" msgstr "" msgid "hotkey|next town" msgstr "" msgid "hotkey|end turn" msgstr "" msgid "hotkey|file options" msgstr "" msgid "hotkey|adventure options" msgstr "" msgid "hotkey|puzzle map" msgstr "" msgid "hotkey|scenario information" msgstr "" msgid "hotkey|dig for artifact" msgstr "" msgid "hotkey|view world" msgstr "" msgid "hotkey|kingdom summary" msgstr "" msgid "hotkey|default action" msgstr "" msgid "hotkey|open focus" msgstr "" #, fuzzy msgid "hotkey|system options" msgstr "Sistem seçeneklerini özelleÅŸtirin" msgid "hotkey|scroll left" msgstr "" msgid "hotkey|scroll right" msgstr "" msgid "hotkey|scroll up" msgstr "" msgid "hotkey|scroll down" msgstr "" msgid "hotkey|toggle control panel" msgstr "" msgid "hotkey|toggle radar" msgstr "" msgid "hotkey|toggle buttons" msgstr "" msgid "hotkey|toggle status" msgstr "" msgid "hotkey|toggle icons" msgstr "" msgid "hotkey|transfer control to ai" msgstr "" msgid "hotkey|retreat from battle" msgstr "" msgid "hotkey|surrender during battle" msgstr "" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "Sistem seçeneklerini özelleÅŸtirin" msgid "hotkey|quick combat" msgstr "" msgid "hotkey|battle options" msgstr "" msgid "hotkey|skip turn in battle" msgstr "" msgid "hotkey|cast battle spell" msgstr "" msgid "hotkey|dwelling level 1" msgstr "" msgid "hotkey|dwelling level 2" msgstr "" msgid "hotkey|dwelling level 3" msgstr "" msgid "hotkey|dwelling level 4" msgstr "" msgid "hotkey|dwelling level 5" msgstr "" msgid "hotkey|dwelling level 6" msgstr "" msgid "hotkey|well" msgstr "" msgid "hotkey|marketplace" msgstr "" msgid "hotkey|mage guild" msgstr "" msgid "hotkey|shipyard" msgstr "" msgid "hotkey|thieves guild" msgstr "" msgid "hotkey|tavern" msgstr "" msgid "hotkey|construction screen" msgstr "" msgid "hotkey|buy all monsters in well" msgstr "" msgid "hotkey|split stack by half" msgstr "" msgid "hotkey|split stack by one" msgstr "" msgid "hotkey|join stacks" msgstr "" msgid "hotkey|upgrade troop" msgstr "" msgid "hotkey|dismiss hero or troop" msgstr "" msgid "hotkey|exchange all troops" msgstr "" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Bilgisayardan kontrolü yeniden kazanmak istiyor musunuz? Etki bir sonraki " "tur'da gerçekleÅŸecek." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" msgid "Default Actions" msgstr "" msgid "Global Actions" msgstr "" msgid "World Map" msgstr "" #, fuzzy msgid "Battle Screen" msgstr "Kahraman Ekranı" #, fuzzy msgid "Town Screen" msgstr "Kahraman Ekranı" msgid "Army Actions" msgstr "" #, fuzzy msgid "The save file is corrupted." msgstr "Ayna görüntüsü oluÅŸturuldu." msgid "Unsupported save format: " msgstr "" msgid "Current game version: " msgstr "" msgid "Last supported version: " msgstr "" msgid "This file contains a save with an invalid game type." msgstr "" msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" msgid "This saved game is localized to '" msgstr "" msgid "' language, but the current language of the game is '" msgstr "" msgid "No save files to load." msgstr "" msgid "Hot Seat" msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "A single player game playing out a single map." msgstr "" msgid "Standard Game" msgstr "" msgid "A single player game playing through a series of maps." msgstr "" msgid "Campaign Game" msgstr "" msgid "Multi-Player Game" msgstr "" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" msgid "fheroes2 Resurrection Team presents" msgstr "" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" msgid "Greetings!" msgstr "" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" msgid "Credits" msgstr "" msgid "View the credits screen." msgstr "" msgid "View the high scores screen." msgstr "" msgid "Create new or modify existing maps." msgstr "" msgid "Change language, resolution and settings of the game." msgstr "" msgid "Game Settings" msgstr "" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" msgid "Original Campaign" msgstr "" msgid "Expansion Campaign" msgstr "" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "" msgid "Loading video. Please wait..." msgstr "" msgid "Host" msgstr "" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" msgid "Guest" msgstr "" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" msgid "Battle Only" msgstr "Sadece SavaÅŸ" msgid "Setup and play a battle without loading any map." msgstr "" msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" msgid "2 Players" msgstr "" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" msgid "3 Players" msgstr "" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" msgid "4 Players" msgstr "" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" msgid "5 Players" msgstr "" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" msgid "6 Players" msgstr "" msgid "Play with 6 human players." msgstr "" msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "" msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" msgid "Ultimate Artifact" msgstr "" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" msgid "Victory!" msgstr "" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" msgid "You have been eliminated from the game!!!" msgstr "" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" #, fuzzy msgid "Defeat!" msgstr " yenildi" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" msgid "Your side defeats the opposing side." msgstr "" msgid "Run out of time. (Fail to win by a certain point.)" msgstr "" msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "" msgstr[1] "" msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" msgstr[1] "" msgid "Capture the castle '%{name}'." msgstr "" msgid "Capture the town '%{name}'." msgstr "" msgid "Defeat the hero '%{name}'." msgstr "" msgid "Find the ultimate artifact." msgstr "" msgid "Find the '%{name}' artifact." msgstr "" msgid "Accumulate %{count} gold." msgstr "" msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" msgid "Lose the castle '%{name}'." msgstr "" msgid "Lose the town '%{name}'." msgstr "" msgid "Lose the hero: %{name}." msgstr "" msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" msgid "%{color} player has been vanquished!" msgstr "" msgid "Major Event!" msgstr "" msgid "Scenario:" msgstr "Senaryo:" msgid "Game Difficulty:" msgstr "" msgid "Opponents:" msgstr "" msgid "Class:" msgstr "" msgid "Rating %{rating}%" msgstr "" msgid "Click here to select which scenario to play." msgstr "" msgid "Scenario" msgstr "Senaryo" msgid "Game Difficulty" msgstr "" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" msgid "Difficulty Rating" msgstr "" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" msgid "Click to accept these settings and start a new game." msgstr "" msgid "Click to return to the main menu." msgstr "" msgid "Astrologers proclaim the Month of the %{name}." msgstr "" msgid "Astrologers proclaim the Week of the %{name}." msgstr "" msgid "After regular growth, the population of %{monster} is doubled!" msgstr "" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" msgstr[1] "" msgid "%{monster} growth +%{count}." msgstr "" msgid " All populations are halved." msgstr "" msgid " All dwellings increase population." msgstr "" msgid "New Month!" msgstr "" msgid "New Week!" msgstr "" msgid "Beware!" msgstr "" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" msgid "%{color} player's turn." msgstr "" msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" msgid "Lord Kilburn" msgstr "" msgid "Tsabu" msgstr "" msgid "Sir Galant" msgstr "" msgid "Thundax" msgstr "" msgid "Lord Haart" msgstr "" msgid "Ariel" msgstr "" msgid "Rebecca" msgstr "" msgid "Sandro" msgstr "" msgid "Crodo" msgstr "" msgid "Barock" msgstr "" msgid "Antoine" msgstr "" msgid "Astra" msgstr "" msgid "Agar" msgstr "" msgid "Vatawna" msgstr "" msgid "Vesper" msgstr "" msgid "Ambrose" msgstr "" msgid "Troyan" msgstr "" msgid "Jojosh" msgstr "" msgid "Wrathmont" msgstr "" msgid "Maximus" msgstr "" msgid "Next Hero" msgstr "" msgid "Select the next Hero." msgstr "" #, fuzzy msgid "Hero Movement" msgstr "Gölge Hareketi" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" msgid "Kingdom Summary" msgstr "" msgid "View a summary of your Kingdom." msgstr "" msgid "Cast an adventure spell." msgstr "" msgid "End Turn" msgstr "" msgid "End your turn and let the computer take its turn." msgstr "" msgid "Adventure Options" msgstr "" msgid "Bring up the adventure options menu." msgstr "" msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" msgid "Are you sure you want to quit?" msgstr "Çıkmak istediÄŸine emin misin?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" msgid "Are you sure you want to overwrite the save with this name?" msgstr "" msgid "Game saved successfully." msgstr "" msgid "There was an issue during saving." msgstr "" msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" msgid "Try looking on land!!!" msgstr "" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "" msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "" msgid "Congratulations!" msgstr "" msgid "Nothing here. Where could it be?" msgstr "" msgid "Try searching on clear ground." msgstr "" msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" msgid "Month: %{month} Week: %{week}" msgstr "" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" msgid "Status Window" msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" msgid "Handicap" msgstr "" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" msgid "%{color} player" msgstr "" msgid "No Handicap" msgstr "" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" msgid "Mild Handicap" msgstr "" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" msgid "Severe Handicap" msgstr "" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Saldırı Becerisini Ayarla" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "" msgid "" "Default\n" "skill" msgstr "" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "" msgid "Kingdom Income per day." msgstr "" msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "Türkçe" msgid "Dutch" msgstr "" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" #, fuzzy msgid "Vietnamese" msgstr "Görünüm %{name}" msgid "Slow" msgstr "YavaÅŸ" msgid "Fast" msgstr "Hızlı" msgid "Very Fast" msgstr "Çok Hızlı" msgid "Evil" msgstr "Åžeytani" msgid "Good" msgstr "İyi" msgid ", FPS: " msgstr "" msgid "shipAndGraveyard|%{object} robber" msgstr "" msgid "pyramid|%{object} raided" msgstr "" msgid "Ector" msgstr "" msgid "Gwenneth" msgstr "" msgid "Sir Gallant" msgstr "" msgid "Tyro" msgstr "" msgid "Dimitry" msgstr "" msgid "Ruby" msgstr "" msgid "Crag Hack" msgstr "" msgid "Fineous" msgstr "" msgid "Jezebel" msgstr "" msgid "Atlas" msgstr "" msgid "Ergon" msgstr "" msgid "Jaclyn" msgstr "" msgid "Gem" msgstr "" msgid "Natasha" msgstr "" msgid "Carlawn" msgstr "" msgid "Luna" msgstr "" msgid "Arie" msgstr "" msgid "Barok" msgstr "" msgid "Kastore" msgstr "" msgid "Falagar" msgstr "" msgid "Dawn" msgstr "" msgid "Flint" msgstr "" msgid "Halon" msgstr "" msgid "Myra" msgstr "" msgid "Myrini" msgstr "" msgid "Wilfrey" msgstr "" msgid "Mandigal" msgstr "" msgid "Sarakin" msgstr "" msgid "Charity" msgstr "" msgid "Darlana" msgstr "" msgid "Ranloo" msgstr "" msgid "Rialdo" msgstr "" msgid "Zam" msgstr "" msgid "Zom" msgstr "" msgid "Celia" msgstr "" msgid "Roxana" msgstr "" msgid "Lord Corlagon" msgstr "" msgid "Lord Halton" msgstr "" msgid "Sister Eliza" msgstr "" msgid "Brother Brax" msgstr "" msgid "Dainwin" msgstr "" msgid "Joseph" msgstr "" msgid "Mog" msgstr "" msgid "Solmyr" msgstr "" msgid "Ceallach" msgstr "" msgid "Drakonia" msgstr "" msgid "Elderian" msgstr "" msgid "Gallavant" msgstr "" msgid "Jarkonas" msgstr "" msgid "Martine" msgstr "" msgid " gives you maximum morale" msgstr "" msgid " gives you maximum luck" msgstr "" msgid "You cannot have multiple spell books." msgstr "" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "" msgid "Do you wish to buy one?" msgstr "" msgid "%{count} / day" msgstr "" msgid "one" msgstr "" msgid "two" msgstr "" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" msgid "You come upon the remains of an unfortunate adventurer." msgstr "" msgid "Treasure" msgstr "" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "" msgid "Searching through the tattered clothing, you find nothing." msgstr "" msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" msgid "Searching inside, you find the %{artifact}." msgstr "" msgid "Inside, you find some of the wagon's cargo still intact." msgstr "" msgid "You search through the flotsam, and find some wood and some gold." msgstr "" msgid "You search through the flotsam, and find some wood." msgstr "" msgid "You search through the flotsam, but find nothing." msgstr "" msgid "Shrine of the 1st Circle" msgstr "" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 2nd Circle" msgstr "" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" msgid "Shrine of the 3rd Circle" msgstr "" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "" msgid "You drink from the enchanted fountain, but nothing happens." msgstr "" msgid "You enter the faerie ring, but nothing happens." msgstr "" msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "" msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" msgid "A second drink at the well in one day will not help you." msgstr "" msgid "A drink from the well has restored your spell points to maximum." msgstr "" msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" msgid "Do you wish to buy this artifact?" msgstr "" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" msgid "You've found the artifact: " msgstr "" msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" msgid "Victorious, you take your prize, the %{art}." msgstr "" msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" msgid "You gain control of a %{name}." msgstr "" msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "" msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "" msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "" msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "" msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" msgid "No Fire Elementals approach you from the lava pool." msgstr "" msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" msgid "A face forms in the water for a moment, and then is gone." msgstr "" msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" msgid "This burial site is deathly still." msgstr "" msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" msgid "From the observation tower, you are able to see distant lands." msgstr "" msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" msgid " and " msgstr "" msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "" msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" msgid "You have already been to this obelisk." msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "" msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" msgid "(Just bury it around my roots.)" msgstr "" msgid "Tears brim in the eyes of the tree." msgstr "" msgid "\"I need %{count} %{res}.\"" msgstr "" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" msgstr[1] "" msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" msgstr[1] "" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" msgstr[1] "" msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" msgid "The Arena guards turn you away." msgstr "" msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" msgid "This eye seems to be intently studying its surroundings." msgstr "" msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" #, fuzzy msgid "No spell book is present." msgstr "Yapılacak büyü yok." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" msgid "The spell was not found." msgstr "" msgid "Only heroes can cast this spell." msgstr "" msgid "This hero is not able to cast adventure spells." msgstr "" msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" msgid "This spell cannot be cast on a boat." msgstr "" msgid "This spell can only be cast near an ocean." msgstr "" msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" msgid "There are no boats available for this spell." msgstr "" #, fuzzy msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "Kahramanınızın yanında bir Elemental çağırmak için açık bir alan yok." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" #, fuzzy msgid "This hero is already in a town, so this spell will have no effect." msgstr "Bu büyü hiç kimseyi etkilemeyecek!" msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" msgid "This spell is already in effect." msgstr "" msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" msgid "%{name} the %{race} (Level %{level})" msgstr "" msgid "Random hero (Level %{level})" msgstr "" msgid "Random %{race} hero (Level %{level})" msgstr "" #, fuzzy msgid "Hero race:" msgstr "Kahraman Ekranı" msgid "Are you sure you want to dismiss this Hero?" msgstr "" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Büyü Puanları" msgid "View Spell Points Info" msgstr "" msgid "Set patrol radius in tiles" msgstr "" msgid "Enter hero's name" msgstr "" msgid "Click to change race." msgstr "" msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" msgid "Exit Hero Screen" msgstr "" msgid "You cannot dismiss a hero in a castle" msgstr "" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "" msgid "Dismiss %{name} the %{race}" msgstr "" msgid "Show previous hero" msgstr "" msgid "Show next hero" msgstr "" msgid "Set army combat formation to 'Spread'" msgstr "" msgid "Set army combat formation to 'Grouped'" msgstr "" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" msgid "Blood Morale" msgstr "" msgid "%{morale} Morale" msgstr "" msgid "%{luck} Luck" msgstr "" msgid "Current Luck Modifiers:" msgstr "" msgid "Current Morale Modifiers:" msgstr "" msgid "Entire army is undead, so morale does not apply." msgstr "" msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" msgid "%{name1} meets %{name2}" msgstr "" msgid "Enemy heroes are now fully identifiable." msgstr "" msgid "Identify Hero" msgstr "" msgid "Select town to port to." msgstr "" msgid "Town Portal" msgstr "" msgid "The creatures are willing to join us!" msgstr "" msgid "All the creatures will join us..." msgstr "" msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "" msgstr[1] "" msgid "" "\n" " for a fee of %{gold} gold." msgstr "" msgid "These weak creatures will surely flee before us." msgstr "" msgid "I fear these creatures are in the mood for a fight." msgstr "" #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "her biri saldırı becerilerine +%{attack} bonusu ekler." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" msgid "The hero's spell power determines the duration or power of a spell." msgstr "" msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" msgid "Current Modifiers:" msgstr "" msgid "skill|Basic" msgstr "" msgid "skill|Advanced" msgstr "" msgid "skill|Expert" msgstr "" msgid "Pathfinding" msgstr "" msgid "Archery" msgstr "" msgid "Logistics" msgstr "" msgid "Scouting" msgstr "" msgid "Diplomacy" msgstr "" msgid "Navigation" msgstr "" msgid "Leadership" msgstr "" msgid "Wisdom" msgstr "" msgid "Mysticism" msgstr "" msgid "Ballistics" msgstr "" msgid "Eagle Eye" msgstr "" msgid "Necromancy" msgstr "" msgid "Estates" msgstr "" msgid "Advanced Archery" msgstr "" msgid "Advanced Pathfinding" msgstr "" msgid "Basic Archery" msgstr "" msgid "Basic Pathfinding" msgstr "" msgid "Expert Pathfinding" msgstr "" msgid "Advanced Logistics" msgstr "" msgid "Basic Logistics" msgstr "" msgid "Basic Scouting" msgstr "" msgid "Expert Archery" msgstr "" msgid "Expert Logistics" msgstr "" msgid "Advanced Diplomacy" msgstr "" msgid "Advanced Scouting" msgstr "" msgid "Basic Diplomacy" msgstr "" msgid "Expert Diplomacy" msgstr "" msgid "Expert Scouting" msgstr "" msgid "Advanced Leadership" msgstr "" msgid "Advanced Navigation" msgstr "" msgid "Basic Leadership" msgstr "" msgid "Basic Navigation" msgstr "" msgid "Expert Navigation" msgstr "" msgid "Advanced Wisdom" msgstr "" msgid "Basic Mysticism" msgstr "" msgid "Basic Wisdom" msgstr "" msgid "Expert Leadership" msgstr "" msgid "Expert Wisdom" msgstr "" msgid "Advanced Luck" msgstr "" msgid "Advanced Mysticism" msgstr "" msgid "Basic Luck" msgstr "" msgid "Expert Luck" msgstr "" msgid "Expert Mysticism" msgstr "" msgid "Advanced Ballistics" msgstr "" msgid "Advanced Eagle Eye" msgstr "" msgid "Basic Ballistics" msgstr "" msgid "Basic Eagle Eye" msgstr "" msgid "Expert Ballistics" msgstr "" msgid "Advanced Necromancy" msgstr "" msgid "Basic Estates" msgstr "" msgid "Basic Necromancy" msgstr "" msgid "Expert Eagle Eye" msgstr "" msgid "Expert Necromancy" msgstr "" msgid "Advanced Estates" msgstr "" msgid "Expert Estates" msgstr "" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "" msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "" msgstr[1] "" msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" msgid "All of the creatures may offer to join the hero." msgstr "" msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "" msgid "%{skill} allows the hero to learn third level spells." msgstr "" msgid "%{skill} allows the hero to learn fourth level spells." msgstr "" msgid "%{skill} allows the hero to learn fifth level spells." msgstr "" msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" msgstr[1] "" msgid "%{skill} increases the hero's luck by %{count}." msgstr "" msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" msgid "Blue" msgstr "" msgid "Green" msgstr "" msgid "Red" msgstr "" msgid "Yellow" msgstr "" msgid "Orange" msgstr "" msgid "Purple" msgstr "" msgid "barrier|Aqua" msgstr "" msgid "barrier|Blue" msgstr "" msgid "barrier|Brown" msgstr "" msgid "barrier|Gold" msgstr "" msgid "barrier|Green" msgstr "" msgid "barrier|Orange" msgstr "" msgid "barrier|Purple" msgstr "" msgid "barrier|Red" msgstr "" msgid "tent|Aqua" msgstr "" msgid "tent|Blue" msgstr "" msgid "tent|Brown" msgstr "" msgid "tent|Gold" msgstr "" msgid "tent|Green" msgstr "" msgid "tent|Orange" msgstr "" msgid "tent|Purple" msgstr "" msgid "tent|Red" msgstr "" msgid "Experience" msgstr "" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" msgid "Hero/Stats" msgstr "" msgid "Skills" msgstr "" msgid "Town/Castle" msgstr "" msgid "Garrison" msgstr "" msgid "Gold Per Day:" msgstr "" msgid "View Heroes." msgstr "" msgid "Towns/Castles" msgstr "" msgid "View Towns and Castles." msgstr "" msgid "luck|Cursed" msgstr "" msgid "luck|Awful" msgstr "" msgid "luck|Bad" msgstr "" msgid "luck|Normal" msgstr "" msgid "luck|Good" msgstr "" msgid "luck|Great" msgstr "" msgid "luck|Irish" msgstr "" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" msgid "morale|Treason" msgstr "" msgid "morale|Awful" msgstr "" msgid "morale|Poor" msgstr "" msgid "morale|Normal" msgstr "" msgid "morale|Good" msgstr "" msgid "morale|Great" msgstr "" msgid "morale|Blood!" msgstr "" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Düşük moral %{monster}'ın panikten donmasına yol açtı." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Düşük moral %{monster}'ın panikten donmasına yol açtı." msgid "Knight" msgstr "" msgid "Barbarian" msgstr "" msgid "Sorceress" msgstr "" msgid "Warlock" msgstr "" msgid "Wizard" msgstr "" msgid "Necromancer" msgstr "" msgid "Multi" msgstr "" msgid "doubleLined|Knight" msgstr "" msgid "doubleLined|Barbarian" msgstr "" msgid "doubleLined|Sorceress" msgstr "" msgid "doubleLined|Warlock" msgstr "" msgid "doubleLined|Wizard" msgstr "" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" msgid "doubleLinedRace|Multi" msgstr "" msgid "doubleLinedRace|Random" msgstr "" msgid "speed|Standing" msgstr "" msgid "speed|Crawling" msgstr "" msgid "speed|Very Slow" msgstr "" msgid "speed|Slow" msgstr "" msgid "speed|Average" msgstr "" msgid "speed|Fast" msgstr "" msgid "speed|Very Fast" msgstr "" msgid "speed|Ultra Fast" msgstr "" msgid "speed|Blazing" msgstr "" msgid "speed|Instant" msgstr "" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "" msgid "week|Rabbit" msgstr "" msgid "week|Gopher" msgstr "" msgid "week|Badger" msgstr "" msgid "week|Rat" msgstr "" msgid "week|Eagle" msgstr "" msgid "week|Weasel" msgstr "" msgid "week|Raven" msgstr "" msgid "week|Mongoose" msgstr "" msgid "week|Dog" msgstr "" msgid "week|Aardvark" msgstr "" msgid "week|Lizard" msgstr "" msgid "week|Tortoise" msgstr "" msgid "week|Hedgehog" msgstr "" msgid "week|Condor" msgstr "" msgid "week|Ant" msgstr "" msgid "week|Grasshopper" msgstr "" msgid "week|Dragonfly" msgstr "" msgid "week|Spider" msgstr "" msgid "week|Butterfly" msgstr "" msgid "week|Bumblebee" msgstr "" msgid "week|Locust" msgstr "" msgid "week|Earthworm" msgstr "" msgid "week|Hornet" msgstr "" msgid "week|Beetle" msgstr "" msgid "week|PLAGUE" msgstr "" msgid "week|Unnamed" msgstr "" msgid "Desert" msgstr "" msgid "Snow" msgstr "" msgid "Wasteland" msgstr "" msgid "Beach" msgstr "" msgid "Lava" msgstr "" msgid "Dirt" msgstr "" msgid "Grass" msgstr "" msgid "Ocean" msgstr "" msgid "maps|Small" msgstr "" msgid "maps|Medium" msgstr "" msgid "maps|Large" msgstr "" msgid "maps|Extra Large" msgstr "" msgid "maps|Custom Size" msgstr "" msgid "Ore Mine" msgstr "" msgid "Sulfur Mine" msgstr "" msgid "Crystal Mine" msgstr "" msgid "Gems Mine" msgstr "" msgid "Gold Mine" msgstr "" msgid "Mine" msgstr "" msgid "Burma shave." msgstr "" msgid "Next sign 50 miles." msgstr "" msgid "See Rock City." msgstr "" msgid "This space for rent." msgstr "" msgid "No object" msgstr "" msgid "Alchemist Lab" msgstr "" msgid "Sign" msgstr "" msgid "Buoy" msgstr "" msgid "Skeleton" msgstr "" msgid "Daemon Cave" msgstr "" msgid "Treasure Chest" msgstr "" msgid "Faerie Ring" msgstr "" msgid "Campfire" msgstr "" msgid "Fountain" msgstr "" msgid "Gazebo" msgstr "" msgid "Genie Lamp" msgstr "" msgid "Archer's House" msgstr "" msgid "Goblin Hut" msgstr "" msgid "Dwarf Cottage" msgstr "" msgid "Peasant Hut" msgstr "" msgid "Stables" msgstr "" msgid "Alchemist's Tower" msgstr "" msgid "Event" msgstr "" msgid "Dragon City" msgstr "" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "" msgstr[1] "" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "" msgstr[1] "" msgid "Monster" msgstr "" msgid "Obelisk" msgstr "" msgid "Oasis" msgstr "" msgid "Resource" msgstr "" msgid "Sawmill" msgstr "" msgid "Oracle" msgstr "" msgid "Shrine of the First Circle" msgstr "" msgid "Shipwreck" msgstr "" msgid "Sea Chest" msgstr "" msgid "Desert Tent" msgstr "" msgid "Stone Liths" msgstr "" msgid "Wagon Camp" msgstr "" msgid "Hut of the Magi" msgstr "" msgid "Whirlpool" msgstr "" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "" msgstr[1] "" msgid "Mermaid" msgstr "" msgid "Boat" msgstr "" msgid "Random Ultimate Artifact" msgstr "" msgid "Random Artifact" msgstr "" msgid "Random Resource" msgstr "" msgid "Random Monster" msgstr "" msgid "Random Town" msgstr "" msgid "Random Castle" msgstr "" msgid "Eye of the Magi" msgstr "" msgid "Random Monster - weak" msgstr "" msgid "Random Monster - medium" msgstr "" msgid "Random Monster - strong" msgstr "" msgid "Random Monster - very strong" msgstr "" msgid "Hero" msgstr "" msgid "Nothing Special" msgstr "" msgid "Mossy Rock" msgstr "" msgid "Watch Tower" msgstr "" msgid "Tree House" msgstr "" msgid "Tree City" msgstr "" msgid "Ruins" msgstr "" msgid "Fort" msgstr "" msgid "Abandoned Mine" msgstr "" msgid "Sirens" msgstr "" msgid "Standing Stones" msgstr "" msgid "Idol" msgstr "" msgid "Tree of Knowledge" msgstr "" msgid "Witch Doctor's Hut" msgstr "" msgid "Temple" msgstr "" msgid "Hill Fort" msgstr "" msgid "Halfling Hole" msgstr "" msgid "Mercenary Camp" msgstr "" msgid "Shrine of the Second Circle" msgstr "" msgid "Shrine of the Third Circle" msgstr "" msgid "City of the Dead" msgstr "" msgid "Sphinx" msgstr "" msgid "Wagon" msgstr "" msgid "Tar Pit" msgstr "" msgid "Artesian Spring" msgstr "" msgid "Troll Bridge" msgstr "" msgid "Watering Hole" msgstr "" msgid "Witch's Hut" msgstr "" msgid "Xanadu" msgstr "" msgid "Lean-To" msgstr "" msgid "Magellan's Maps" msgstr "" msgid "Flotsam" msgstr "" msgid "Derelict Ship" msgstr "" msgid "Shipwreck Survivor" msgstr "" msgid "Bottle" msgstr "" msgid "Magic Well" msgstr "" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "" msgstr[1] "" msgid "Observation Tower" msgstr "" msgid "Freeman's Foundry" msgstr "" msgid "Reefs" msgstr "" msgid "Volcano" msgstr "" msgid "Flowers" msgstr "" msgid "Rock" msgstr "" msgid "Water Lake" msgstr "" msgid "Mandrake" msgstr "" msgid "Dead Tree" msgstr "" msgid "Stump" msgstr "" msgid "Crater" msgstr "" msgid "Cactus" msgstr "" msgid "Mound" msgstr "" msgid "Dune" msgstr "" msgid "Lava Pool" msgstr "" msgid "Shrub" msgstr "" msgid "Barrow Mounds" msgstr "" msgid "Random Artifact - Treasure" msgstr "" msgid "Random Artifact - Minor" msgstr "" msgid "Random Artifact - Major" msgstr "" msgid "Barrier" msgstr "" msgid "Traveller's Tent" msgstr "" msgid "Jail" msgstr "" msgid "Fire Summoning Altar" msgstr "" msgid "Air Summoning Altar" msgstr "" msgid "Earth Summoning Altar" msgstr "" msgid "Water Summoning Altar" msgstr "" #, fuzzy msgid "Swampy Lake" msgstr "Bataklık" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "" msgid "Unknown Monster" msgstr "" msgid "Peasant" msgstr "" msgid "Peasants" msgstr "" msgid "Archer" msgstr "" msgid "Archers" msgstr "" msgid "Ranger" msgstr "" msgid "Rangers" msgstr "" msgid "Pikeman" msgstr "" msgid "Pikemen" msgstr "" msgid "Veteran Pikeman" msgstr "" msgid "Veteran Pikemen" msgstr "" msgid "Swordsman" msgstr "" msgid "Swordsmen" msgstr "" msgid "Master Swordsman" msgstr "" msgid "Master Swordsmen" msgstr "" msgid "Cavalries" msgstr "" msgid "Cavalry" msgstr "" msgid "Champion" msgstr "" msgid "Champions" msgstr "" msgid "Paladin" msgstr "" msgid "Paladins" msgstr "" msgid "Crusader" msgstr "" msgid "Crusaders" msgstr "" msgid "Goblin" msgstr "" msgid "Goblins" msgstr "" msgid "Orc" msgstr "" msgid "Orcs" msgstr "" msgid "Orc Chief" msgstr "" msgid "Orc Chiefs" msgstr "" msgid "Wolf" msgstr "" msgid "Wolves" msgstr "" msgid "Ogre" msgstr "" msgid "Ogres" msgstr "" msgid "Ogre Lord" msgstr "" msgid "Ogre Lords" msgstr "" msgid "Troll" msgstr "" msgid "Trolls" msgstr "" msgid "War Troll" msgstr "" msgid "War Trolls" msgstr "" msgid "Cyclopes" msgstr "" msgid "Cyclops" msgstr "" msgid "Sprite" msgstr "" msgid "Sprites" msgstr "" msgid "Dwarf" msgstr "" msgid "Dwarves" msgstr "" msgid "Battle Dwarf" msgstr "" msgid "Battle Dwarves" msgstr "" msgid "Elf" msgstr "" msgid "Elves" msgstr "" msgid "Grand Elf" msgstr "" msgid "Grand Elves" msgstr "" msgid "Druid" msgstr "" msgid "Druids" msgstr "" msgid "Greater Druid" msgstr "" msgid "Greater Druids" msgstr "" msgid "Unicorn" msgstr "" msgid "Unicorns" msgstr "" msgid "Phoenix" msgstr "" msgid "Phoenixes" msgstr "" msgid "Centaur" msgstr "" msgid "Centaurs" msgstr "" msgid "Gargoyle" msgstr "" msgid "Gargoyles" msgstr "" msgid "Griffin" msgstr "" msgid "Griffins" msgstr "" msgid "Minotaur" msgstr "" msgid "Minotaurs" msgstr "" msgid "Minotaur King" msgstr "" msgid "Minotaur Kings" msgstr "" msgid "Hydra" msgstr "" msgid "Hydras" msgstr "" msgid "Green Dragon" msgstr "" msgid "Green Dragons" msgstr "" msgid "Red Dragon" msgstr "" msgid "Red Dragons" msgstr "" msgid "Black Dragon" msgstr "" msgid "Black Dragons" msgstr "" msgid "Halfling" msgstr "" msgid "Halflings" msgstr "" msgid "Boar" msgstr "" msgid "Boars" msgstr "" msgid "Iron Golem" msgstr "" msgid "Iron Golems" msgstr "" msgid "Steel Golem" msgstr "" msgid "Steel Golems" msgstr "" msgid "Roc" msgstr "" msgid "Rocs" msgstr "" msgid "Mage" msgstr "" msgid "Magi" msgstr "" msgid "Archmage" msgstr "" msgid "Archmagi" msgstr "" msgid "Giant" msgstr "" msgid "Giants" msgstr "" msgid "Titan" msgstr "" msgid "Titans" msgstr "" msgid "Skeletons" msgstr "" msgid "Zombie" msgstr "" msgid "Zombies" msgstr "" msgid "Mutant Zombie" msgstr "" msgid "Mutant Zombies" msgstr "" msgid "Mummies" msgstr "" msgid "Mummy" msgstr "" msgid "Royal Mummies" msgstr "" msgid "Royal Mummy" msgstr "" msgid "Vampire" msgstr "" msgid "Vampires" msgstr "" msgid "Vampire Lord" msgstr "" msgid "Vampire Lords" msgstr "" msgid "Lich" msgstr "" msgid "Liches" msgstr "" msgid "Power Lich" msgstr "" msgid "Power Liches" msgstr "" msgid "Bone Dragon" msgstr "" msgid "Bone Dragons" msgstr "" msgid "Rogue" msgstr "" msgid "Rogues" msgstr "" msgid "Nomad" msgstr "" msgid "Nomads" msgstr "" msgid "Ghost" msgstr "" msgid "Ghosts" msgstr "" msgid "Genie" msgstr "" msgid "Genies" msgstr "" msgid "Medusa" msgstr "" msgid "Medusas" msgstr "" msgid "Earth Elemental" msgstr "" msgid "Earth Elementals" msgstr "" msgid "Air Elemental" msgstr "" msgid "Air Elementals" msgstr "" msgid "Fire Elemental" msgstr "" msgid "Fire Elementals" msgstr "" msgid "Water Elemental" msgstr "" msgid "Water Elementals" msgstr "" msgid "Random Monsters" msgstr "" msgid "Random Monster 1" msgstr "" msgid "Random Monsters 1" msgstr "" msgid "Random Monster 2" msgstr "" msgid "Random Monsters 2" msgstr "" msgid "Random Monster 3" msgstr "" msgid "Random Monsters 3" msgstr "" msgid "Random Monster 4" msgstr "" msgid "Random Monsters 4" msgstr "" msgid "Double shot" msgstr "" msgid "2-hex monster" msgstr "" msgid "Double strike" msgstr "" msgid "Double damage to Undead" msgstr "" msgid "% magic resistance" msgstr "" msgid "Immune to Mind spells" msgstr "" msgid "Immune to Elemental spells" msgstr "" msgid "Immune to Fire spells" msgstr "" msgid "Immune to Cold spells" msgstr "" msgid "Immune to " msgstr "" msgid "% immunity to %{spell} spell" msgstr "" msgid "% damage from Elemental spells" msgstr "" msgid "% damage from %{spell} spell" msgstr "" msgid "% chance to Dispel beneficial spells" msgstr "" msgid "% chance to Paralyze" msgstr "" msgid "% chance to Petrify" msgstr "" msgid "% chance to Blind" msgstr "" msgid "% chance to Curse" msgstr "" msgid "% chance to cast %{spell} spell" msgstr "" msgid "HP regeneration" msgstr "" msgid "Two hexes attack" msgstr "" msgid "Flyer" msgstr "" msgid "Always retaliates" msgstr "" msgid "Attacks all adjacent enemies" msgstr "" msgid "No melee penalty" msgstr "" msgid "Dragon" msgstr "" msgid "Undead" msgstr "" msgid "No enemy retaliation" msgstr "" msgid "HP drain" msgstr "" msgid "Cloud attack" msgstr "" msgid "Decreases enemy's morale by " msgstr "" msgid "% chance to halve enemy" msgstr "" msgid "Soul Eater" msgstr "" msgid "Elemental" msgstr "" msgid "No Morale" msgstr "" msgid "Earth creature" msgstr "" msgid "Air creature" msgstr "" msgid "Fire creature" msgstr "" msgid "Water creature" msgstr "" msgid "Double damage from Fire spells" msgstr "" msgid "Double damage from Cold spells" msgstr "" msgid "Double damage from Earth creatures" msgstr "" msgid "Double damage from Air creatures" msgstr "" msgid "Double damage from Fire creatures" msgstr "" msgid "Double damage from Water creatures" msgstr "" msgid "Lightning" msgstr "" msgid "% immunity to " msgstr "" msgid "% damage from " msgstr "" msgid "The three Anduran artifacts magically combine into one." msgstr "" msgid "View Spells" msgstr "" msgid "View %{name} Info" msgstr "" msgid "Move %{name}" msgstr "" msgid "Cannot move the Spellbook" msgstr "" msgid "This item can't be traded." msgstr "" msgid "Invalid Artifact" msgstr "" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "Ultimate Book of Knowledge" msgstr "" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "Ultimate Sword of Dominion" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "Ultimate Cloak of Protection" msgstr "" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "Ultimate Wand of Magic" msgstr "" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" msgid "Ultimate Shield" msgstr "" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "Ultimate Staff" msgstr "" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "" msgid "Ultimate Crown" msgstr "" msgid "Golden Goose" msgstr "" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "" msgid "Arcane Necklace of Magic" msgstr "" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" msgid "Caster's Bracelet of Magic" msgstr "" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" msgid "Mage's Ring of Power" msgstr "" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" msgid "Witch's Broach of Magic" msgstr "" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" msgid "Medal of Valor" msgstr "" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" msgid "Medal of Courage" msgstr "" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" msgid "Medal of Honor" msgstr "" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" msgid "Medal of Distinction" msgstr "" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" msgid "Fizbin of Misfortune" msgstr "" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "" msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" msgid "Thunder Mace of Dominion" msgstr "" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" msgid "Armored Gauntlets of Protection" msgstr "" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" msgid "Defender Helm of Protection" msgstr "" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" msgid "Giant Flail of Dominion" msgstr "" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" msgid "Ballista of Quickness" msgstr "" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" msgid "Stealth Shield of Protection" msgstr "" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" msgid "Dragon Sword of Dominion" msgstr "" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" msgid "Power Axe of Dominion" msgstr "" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" msgid "Divine Breastplate of Protection" msgstr "" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" msgid "Minor Scroll of Knowledge" msgstr "" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" msgid "Major Scroll of Knowledge" msgstr "" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" msgid "Superior Scroll of Knowledge" msgstr "" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" msgid "Foremost Scroll of Knowledge" msgstr "" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" msgid "Endless Sack of Gold" msgstr "" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" msgid "Endless Bag of Gold" msgstr "" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" msgid "Endless Purse of Gold" msgstr "" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" msgid "Nomad Boots of Mobility" msgstr "" msgid "The %{name} increase the hero's movement on land." msgstr "" msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" msgid "Traveler's Boots of Mobility" msgstr "" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" msgid "Lucky Rabbit's Foot" msgstr "" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" msgid "Golden Horseshoe" msgstr "" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" msgid "Gambler's Lucky Coin" msgstr "" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" msgid "Four-Leaf Clover" msgstr "" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" msgid "True Compass of Mobility" msgstr "" msgid "The %{name} increases the hero's movement on land and sea." msgstr "" msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" msgid "Sailor's Astrolabe of Mobility" msgstr "" msgid "The %{name} increases the hero's movement on sea." msgstr "" msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" msgid "Evil Eye" msgstr "" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "" msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" msgid "Enchanted Hourglass" msgstr "" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" msgid "Gold Watch" msgstr "" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "" msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" msgid "Skullcap" msgstr "" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" msgid "Ice Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" msgid "Fire Cloak" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" msgid "Lightning Helm" msgstr "" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" msgid "Evercold Icicle" msgstr "" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" msgid "Everhot Lava Rock" msgstr "" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" msgid "Lightning Rod" msgstr "" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" msgid "Snake-Ring" msgstr "" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" msgid "Ankh" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" msgid "Book of Elements" msgstr "" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" msgid "Elemental Ring" msgstr "" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" msgid "Holy Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "" msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" msgid "Pendant of Free Will" msgstr "" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" msgid "Pendant of Life" msgstr "" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "" msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" msgid "Serenity Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" msgid "Seeing-eye Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "" msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" msgid "Kinetic Pendant" msgstr "" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" msgid "Pendant of Death" msgstr "" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" msgid "Wand of Negation" msgstr "" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" msgid "Golden Bow" msgstr "" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" msgid "Telescope" msgstr "" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" msgid "Statesman's Quill" msgstr "" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" msgid "Wizard's Hat" msgstr "" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" msgid "Power Ring" msgstr "" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" msgid "Ammo Cart" msgstr "" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" msgid "Tax Lien" msgstr "" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" msgid "Hideous Mask" msgstr "" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" msgid "Endless Pouch of Sulfur" msgstr "" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "" msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" msgid "Endless Vial of Mercury" msgstr "" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "" msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" msgid "Endless Pouch of Gems" msgstr "" msgid "The %{name} provides %{count} unit of gems per day." msgstr "" msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" msgid "Endless Cord of Wood" msgstr "" msgid "The %{name} provides %{count} unit of wood per day." msgstr "" msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" msgid "Endless Cart of Ore" msgstr "" msgid "The %{name} provides %{count} unit of ore per day." msgstr "" msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" msgid "Endless Pouch of Crystal" msgstr "" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "" msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" msgid "Spiked Helm" msgstr "" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" msgid "Spiked Shield" msgstr "" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" msgid "White Pearl" msgstr "" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" msgid "Black Pearl" msgstr "" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" msgid "Magic Book" msgstr "" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name} büyüye direndi!" msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "" msgid "The reserved artifact." msgstr "" msgid "Dummy 3" msgstr "" msgid "Dummy 4" msgstr "" msgid "Spell Scroll" msgstr "" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" msgid "Arm of the Martyr" msgstr "" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" msgid "Breastplate of Anduran" msgstr "" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" msgid "Broach of Shielding" msgstr "" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" msgid "Battle Garb of Anduran" msgstr "" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" msgid "Crystal Ball" msgstr "" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" msgid "Heart of Fire" msgstr "" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" msgid "Heart of Ice" msgstr "" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" msgid "Helmet of Anduran" msgstr "" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" msgid "Holy Hammer" msgstr "" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" msgid "Legendary Scepter" msgstr "" msgid "The %{name} adds %{count} points to all attributes." msgstr "" msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" msgid "Masthead" msgstr "" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" msgid "Sphere of Negation" msgstr "" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" msgid "Staff of Wizardry" msgstr "" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} %{count} Okçu gücüyle ateÅŸ ediyor" msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" msgid "Sword Breaker" msgstr "" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "" msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" msgid "Sword of Anduran" msgstr "" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" msgid "Spade of Necromancy" msgstr "" msgid "The %{name} gives the hero increased necromancy skill." msgstr "" msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" msgid "spellBonus|selected by user" msgstr "" msgid "Wood" msgstr "" msgid "Mercury" msgstr "" msgid "Ore" msgstr "" msgid "Sulfur" msgstr "" msgid "Crystal" msgstr "" msgid "Gems" msgstr "" msgid "Gold" msgstr "" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" msgid "Fireball" msgstr "" msgid "Fireblast" msgstr "" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "" msgid "Lightning Bolt" msgstr "" msgid "Chain Lightning" msgstr "" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" msgid "Teleport" msgstr "" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" msgid "Cure" msgstr "" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" msgid "Mass Cure" msgstr "" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" msgid "Resurrect" msgstr "" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" msgid "Resurrect True" msgstr "" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "" msgid "Haste" msgstr "" msgid "Increases the speed of any creature by %{count}." msgstr "" msgid "Increases the speed of all of your creatures by %{count}." msgstr "" msgid "Mass Haste" msgstr "" msgid "Slows target to half movement rate." msgstr "" msgid "spell|Slow" msgstr "" msgid "Mass Slow" msgstr "" msgid "Slows all enemies to half movement rate." msgstr "" msgid "spell|Blind" msgstr "" msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "" msgid "Bless" msgstr "" msgid "Causes the selected creatures to inflict maximum damage." msgstr "" msgid "Causes all of your units to inflict maximum damage." msgstr "" msgid "Mass Bless" msgstr "" msgid "Magically increases the defense skill of the selected creatures." msgstr "" msgid "Stoneskin" msgstr "" msgid "Steelskin" msgstr "" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" msgid "Causes the selected creatures to inflict minimum damage." msgstr "" msgid "Curse" msgstr "" msgid "Causes all enemy troops to inflict minimum damage." msgstr "" msgid "Mass Curse" msgstr "" msgid "Damages all undead in the battle." msgstr "" msgid "Holy Word" msgstr "" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" msgid "Holy Shout" msgstr "" msgid "Anti-Magic" msgstr "" msgid "Prevents any magic against the selected creatures." msgstr "" msgid "Dispel Magic" msgstr "" msgid "Removes all magic spells from a single target." msgstr "" msgid "Mass Dispel" msgstr "" msgid "Removes all magic spells from all creatures." msgstr "" msgid "Causes a magic arrow to strike the selected target." msgstr "" msgid "Magic Arrow" msgstr "" msgid "Berserker" msgstr "" msgid "Causes a creature to attack its nearest neighbor." msgstr "" msgid "Armageddon" msgstr "" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" msgid "Elemental Storm" msgstr "" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" msgid "Meteor Shower" msgstr "" msgid "Paralyze" msgstr "" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" msgid "Hypnotize" msgstr "" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" msgid "Cold Ray" msgstr "" msgid "Drains body heat from a single enemy unit." msgstr "" msgid "Cold Ring" msgstr "" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" msgid "Disrupting Ray" msgstr "" msgid "Reduces the defense rating of an enemy unit by three." msgstr "" msgid "Damages all living (non-undead) units in the battle." msgstr "" msgid "Death Ripple" msgstr "" msgid "Death Wave" msgstr "" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" msgid "Dragon Slayer" msgstr "" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "" msgid "Blood Lust" msgstr "" msgid "Increases a unit's attack skill." msgstr "" msgid "Animate Dead" msgstr "" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" msgid "Mirror Image" msgstr "" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" msgid "Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Mass Shield" msgstr "" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" msgid "Summon Earth Elemental" msgstr "" msgid "Summons Earth Elementals to fight for your army." msgstr "" msgid "Summon Air Elemental" msgstr "" msgid "Summons Air Elementals to fight for your army." msgstr "" msgid "Summon Fire Elemental" msgstr "" msgid "Summons Fire Elementals to fight for your army." msgstr "" msgid "Summon Water Elemental" msgstr "" msgid "Summons Water Elementals to fight for your army." msgstr "" msgid "Damages castle walls." msgstr "" msgid "Earthquake" msgstr "" msgid "Causes all mines across the land to become visible." msgstr "" msgid "View Mines" msgstr "" msgid "Causes all resources across the land to become visible." msgstr "" msgid "View Resources" msgstr "" msgid "Causes all artifacts across the land to become visible." msgstr "" msgid "View Artifacts" msgstr "" msgid "Causes all towns and castles across the land to become visible." msgstr "" msgid "View Towns" msgstr "" msgid "Causes all Heroes across the land to become visible." msgstr "" msgid "View Heroes" msgstr "" msgid "Causes the entire land to become visible." msgstr "" msgid "View All" msgstr "" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "" msgid "Summon Boat" msgstr "" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" msgid "Allows the caster to magically transport to a nearby location." msgstr "" msgid "Dimension Door" msgstr "" msgid "Returns the caster to any town or castle currently owned." msgstr "" msgid "Town Gate" msgstr "" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" msgid "Visions" msgstr "" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" msgid "Haunt" msgstr "" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" msgid "Set Earth Guardian" msgstr "" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Air Guardian" msgstr "" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Fire Guardian" msgstr "" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "" msgid "Set Water Guardian" msgstr "" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "" #, fuzzy msgid "Random Spell" msgstr "Yapılan Büyü" msgid "Randomly selected spell of any level." msgstr "" msgid "Random 1st Level Spell" msgstr "" msgid "Randomly selected 1st level spell." msgstr "" msgid "Random 2nd Level Spell" msgstr "" msgid "Randomly selected 2nd level spell." msgstr "" msgid "Random 3rd Level Spell" msgstr "" msgid "Randomly selected 3rd level spell." msgstr "" msgid "Random 4th Level Spell" msgstr "" msgid "Randomly selected 4th level spell." msgstr "" msgid "Random 5th Level Spell" msgstr "" msgid "Randomly selected 5th level spell." msgstr "" msgid "Petrification" msgstr "" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" msgid "You have no Magic Book, so you cannot cast a spell." msgstr "" msgid "No spell to cast." msgstr "" msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "" msgid "View Adventure Spells" msgstr "" msgid "View Combat Spells" msgstr "" msgid "View previous page" msgstr "" msgid "View next page" msgstr "" msgid "Close Spellbook" msgstr "" msgid "View %{spell}" msgstr "" msgid "This spell does %{damage} points of damage." msgstr "" msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" msgid "This spell restores %{hp} HP." msgstr "" msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "" msgid "The nearest town is %{town}." msgstr "" msgid "This town is occupied by your hero %{hero}." msgstr "" msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" msgid "The ultimate artifact is really the %{name}." msgstr "" msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "" msgid "north-west" msgstr "" msgid "north" msgstr "kuzey" msgid "north-east" msgstr "kuzey-doÄŸu" msgid "west" msgstr "batı" msgid "center" msgstr "merkez" msgid "east" msgstr "doÄŸu" msgid "south-west" msgstr "güney-batı" msgid "south" msgstr "güney" msgid "south-east" msgstr "güney-doÄŸu" msgid "The truth is out there." msgstr "" msgid "The dark side is stronger." msgstr "" msgid "The end of the world is near." msgstr "" msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "" msgid "A Black Dragon will take out a Titan any day of the week." msgstr "" msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" msgid "An unknown force is being resurrected..." msgstr "" msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" #~ msgid "Select count %{resource}:" #~ msgstr "%{resource} sayısını seç:" #~ msgid "Enable auto combat" #~ msgstr "Otomatik savacı aç" #, fuzzy #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "Savaşı otomatik modda bitirmek istediÄŸinizden emin misiniz?" fheroes2-1.1.6+dfsg/files/lang/uk.po000066400000000000000000015052321476115357100171770ustar00rootroot00000000000000# Ukrainian translation of fheroes2 # Copyright (C) 2022 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-08-23 09:35+0300\n" "Last-Translator: fheroes2 team \n" "Language-Team: \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=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" "X-Generator: Poedit 3.2.2\n" msgid "" "NEW\n" "GAME" msgstr "" "ÐОВÐ\n" "ГРÐ" msgid "" "SAVE\n" "GAME" msgstr "" "ЗÐПИС\n" "ГРИ" msgid "" "LOAD\n" "GAME" msgstr "" "ЗÐÐ’ÐÐ-\n" "ТÐЖИТИ\n" "ГРУ" msgid "INFO" msgstr "ІÐФО" msgid "QUIT" msgstr "ВИЙТИ" msgid "" "NEW\n" "MAP" msgstr "" "ÐОВÐ\n" "МÐПÐ" msgid "" "SAVE\n" "MAP" msgstr "" "ЗБЕРЕГТИ\n" "МÐПУ" msgid "" "LOAD\n" "MAP" msgstr "" "ЗÐÐ’ÐÐ-\n" "ТÐЖИТИ\n" "МÐПУ" # СкаÑувати - правильний варіант перекладу Ñлова CANCEL # Відміна - відмінÑють лише дієÑлова Ñк чаÑтину мови. msgid "CANCEL" msgstr "СКÐСУВÐТИ" # Гаразд - це питоме колоритне українÑьке Ñлово, що позначає згоду або підтвердженнÑ. Слово "добре" Ñкоріше прикметник та епітет, Ñке менше підходить Ð´Ð»Ñ Ð·Ð³Ð¾Ð´Ð¸. msgid "OKAY" msgstr "ГÐРÐЗД" msgid "ACCEPT" msgstr "ПРИЙÐЯТИ" # Відхилити - Ñ” правильним перкладом. ДієÑлово, що позначає неприйнÑÑ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð¿Ð¾Ð·Ð¸Ñ†Ñ–Ñ—, змін тощо. # Відмінити - ÑтоÑуєтьÑÑ Ð»Ð¸ÑˆÐµ відміни дієÑлів Ñк чаÑтини мови. msgid "DECLINE" msgstr "ВІДХИЛИТИ" msgid "LEARN" msgstr "ВИВЧИТИ" msgid "TRADE" msgstr "ОБМІÐЯТИ" msgid "YES" msgstr "ТÐК" msgid "NO" msgstr "ÐІ" msgid "EXIT" msgstr "ВИХІД" msgid "smallerButton|EXIT" msgstr "ВИХІД" msgid "DISMISS" msgstr "ЗВІЛЬÐИТИ" msgid "UPGRADE" msgstr "ПОКРÐЩИТИ" msgid "RESTART" msgstr "РЕСТÐРТ" msgid "HEROES" msgstr "ГЕРОЇ" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "МІСТÐ/\n" "ЗÐМКИ" msgid "S" msgstr "М" msgid "M" msgstr "С" msgid "L" msgstr "Ð’" msgid "X-L" msgstr "ÐÐ’" msgid "ALL" msgstr "ВСІ" msgid "SELECT" msgstr "ОБРÐТИ" msgid "" "STANDARD\n" "GAME" msgstr "" "ЗВИЧÐЙÐÐ\n" "ГРÐ" msgid "" "BATTLE\n" "ONLY" msgstr "" "ЛИШЕ\n" "БИТВÐ" msgid "" "CAMPAIGN\n" "GAME" msgstr "КÐМПÐÐІЯ" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "ДЕКІЛЬКÐ\n" "ГРÐВЦІВ" msgid "CONFIG" msgstr "ПÐРÐМЕТРИ" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "ВІЙÐИ ЗÐ\n" "СПÐДЩИÐУ" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "КÐМПÐÐІЇ\n" "ДОПОВÐЕÐÐЯ" msgid "HOT SEAT" msgstr "" "ГÐРЯЧИЙ \n" "СТІЛЕЦЬ" msgid "2 PLAYERS" msgstr "2 ГРÐВЦІ" msgid "3 PLAYERS" msgstr "3 ГРÐВЦЯ" msgid "4 PLAYERS" msgstr "4 ГРÐВЦЯ" msgid "5 PLAYERS" msgstr "5 ГРÐВЦІВ" msgid "6 PLAYERS" msgstr "6 ГРÐВЦІВ" msgid "GIFT" msgstr "ДÐРУÐОК" msgid "MAX" msgstr "МÐКС" msgid "DIFFICULTY" msgstr "СКЛÐДÐІСТЬ" msgid "VIEW INTRO" msgstr "ПОВТОР ІÐТРО" msgid "MIN" msgstr "МІÐ" msgid "RESET" msgstr "СКИÐУТИ" msgid "START" msgstr "ПОЧÐТИ" msgid "TOWN" msgstr "МІСТО" msgid "CASTLE" msgstr "ЗÐМОК" msgid "RESTRICT" msgstr "ОБМЕЖИТИ" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "З\n" "Ð’\n" "І\n" "Л\n" "Ь\n" "Ð." msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "Ð’\n" "И\n" "Ð¥\n" "І\n" "Д" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" "П\n" "Ð\n" "Т\n" "Р\n" "У\n" "Л\n" "Ь" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "К\n" "Ð\n" "М\n" "П\n" "Ð\n" "Ð\n" "І\n" "Я" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "С\n" "Т\n" "Ð\n" "Ð\n" "Д\n" "Ð\n" "Р\n" "Т" msgid "RUMORS" msgstr "ЧУТКИ" msgid "EVENTS" msgstr "ПОДІЇ" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Воїн" msgid "Builder" msgstr "Будівник" msgid "Explorer" msgstr "Розвідник" msgid "None" msgstr "ВідÑутні" msgid "" "A few\n" "%{monster}" msgstr "" "Мало\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Кілька\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "ЗграÑ\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Багато\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Орда\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Ðатовп\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Купа\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Безліч\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Легіон\n" "%{monster}" msgid "army|Few" msgstr "Мало" msgid "army|Several" msgstr "Кілька" msgid "army|Pack" msgstr "ЗграÑ" msgid "army|Lots" msgstr "Багато" msgid "army|Horde" msgstr "Орда" msgid "army|Throng" msgstr "Ðатовп" # Swarm перекладаєтьÑÑ Ñк "Рій" msgid "army|Swarm" msgstr "Рій" msgid "army|Zounds" msgstr "Безліч" msgid "army|Legion" msgstr "Легіон" msgid "All %{race} troops +1" msgstr "УÑÑ– війÑька фракції %{race} +1" msgid "NeutralRaceTroops|Neutral" msgstr "Ðейтральні" msgid "Troops of %{count} alignments -%{penalty}" msgstr "ВійÑька з %{count} Ñ€Ð°Ñ - %{penalty}" msgid "Some undead in army -1" msgstr "ÐаÑвніÑть невмерлих в армії -1" msgid "" "Default\n" "troop" msgstr "ВійÑька за налаштуваннÑм" msgid "View %{name}" msgstr "ПереглÑнути %{name}" msgid "Move the %{name} " msgstr "ПереміÑтити загін %{name} " msgid "Move or right click to redistribute %{name}" msgstr "ПереміÑтити %{name}, правий клік щоб поділити" msgid "Combine %{name} armies" msgstr "%{name}: Поєднати загони" msgid "Exchange %{name2} with %{name}" msgstr "ОбмінÑти %{name2} на %{name}" msgid "Select %{name}" msgstr "Обрати %{name}" msgid "Cannot move last troop" msgstr "Ðе вдалоÑÑŒ переміÑтити оÑтанній загін" msgid "Move the %{name}" msgstr "ПереміÑтити: %{name}" msgid "Set %{monster} Count" msgstr "Задати кількіÑть %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} знищує половину ворожого загону!" msgstr[1] "%{name} знищують половину ворожого загону!" msgstr[2] "%{name} знищують половину ворожого загону!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} вимкнув автобій" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} увімкнув автобій" msgid "Spell failed!" msgstr "Чари не Ñпрацювали!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Ðа полі бою діє артефакт Сфера ЗапереченнÑ. ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð±Ð¾Ð¹Ð¾Ð²Ð¾Ñ— магії " "заборонене." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Ви вже викориÑтали чари у цьому раунді." msgid "That spell will have no effect!" msgstr "Це заклÑÑ‚Ñ‚Ñ Ð½Ðµ матиме ефекту!" msgid "You may only summon one type of elemental per combat." msgstr "Ви можете викликати елементалів лиш одного типу протÑгом битви." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "Ð‘Ñ–Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ герою нема вільного міÑÑ†Ñ Ð´Ð»Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÑƒ Елементалів." msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Рів зменшує захиÑну здатніÑть будь-Ñкого загону на -%{count} Ñ– обмежує їхню " "дальніÑть руху." msgid "Speed: %{speed}" msgstr "ШвидкіÑть: %{speed}" msgid "Speed" msgstr "ШвидкіÑть" msgid "Off" msgstr "Вимк" msgid "On" msgstr "Увімк" msgid "Turn Order" msgstr "ПорÑдок ходів" msgid "Auto Spell Casting" msgstr "Ðвтоматичне чаклуваннÑ" msgid "Grid" msgstr "Сітка" msgid "Shadow Movement" msgstr "Ð—Ð°Ñ‚Ñ–Ð½ÐµÐ½Ð½Ñ Ñітки" msgid "Shadow Cursor" msgstr "Тінь курÑора" msgid "Audio" msgstr "Ðудіо" msgid "Settings" msgstr "ÐалаштуваннÑ" msgid "Configure" msgstr "Ðалаштувати" msgid "Hot Keys" msgstr "ГарÑчі клавіші" msgid "Damage Info" msgstr "" "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾\n" "пошкодженнÑ" msgid "Set the speed of combat actions and animations." msgstr "Ð’Ñтановити швидкіÑть бойових дій та анімації." msgid "Toggle to display the turn order during the battle." msgstr "Перемкнути Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€Ð³Ð¾Ð²Ð¾Ñті ходів загонів під Ñ‡Ð°Ñ Ð±Ð¸Ñ‚Ð²Ð¸." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Перемкнути викориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð¿'ютером магії під Ñ‡Ð°Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾ проведених " "битв. (Примітка: Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð¶Ð¾Ð´Ð½Ð¸Ð¼ чином не впливає на викориÑÑ‚Ð°Ð½Ð½Ñ Ð¼Ð°Ð³Ñ–Ñ— " "комп'ютерними гравцÑми, а також не впливає на швидкий бій)." msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Перемкнути Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñітки Ð¿Ð¾Ð»Ñ Ð±Ð¾ÑŽ. Сітка з шеÑтигранних клітинок завжди " "визначає можливоÑті руху, навіть Ñкщо Ñ—Ñ— Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ðµ. Перемикач " "лише робить Ñ—Ñ— видимою." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Перемкнути Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð¾Ð½Ð¸, в межах Ñкої ваші Ñ–Ñтоти можуть переÑуватиÑÑ " "та атакувати." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "Перемкнути Ð·Ð°Ñ‚Ñ–Ð½ÐµÐ½Ð½Ñ ÐºÐ»Ñ–Ñ‚Ð¸Ð½Ð¸, на Ñку наведений курÑор миші." msgid "Change the audio settings of the game." msgstr "Змінити звукові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€Ð¸." msgid "Check and configure all the hot keys present in the game." msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÑÑ–Ñ… гарÑчих клавіш у грі." msgid "Toggle to display damage information during the battle." msgstr "" "Перемкнути Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— про Ð¿Ð¾ÑˆÐºÐ¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð±Ð¸Ñ‚Ð²Ð¸. Якщо " "Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ð¿Ñ€Ð°Ñ†ÑŽÑ”, наведіть курÑором на бажану ціль - через кілька Ñекунд " "вирине вікно з розрахунком можливих пошкоджень, що завдаÑть ваш загін." msgid "Exit this menu." msgstr "Вийти з цього меню." msgid "Okay" msgstr "Гаразд" msgid "The enemy has surrendered!" msgstr "Ворог капітулював!" msgid "Their cowardice costs them %{gold} gold." msgstr "Їхнє боÑгузтво коштує їм %{gold} золота." msgid "The enemy has fled!" msgstr "Ворог втік!" msgid "A glorious victory!" msgstr "Славетна перемога!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "За доблеÑть у бою, %{name} отримує %{exp} доÑвіду." msgid "The cowardly %{name} flees from battle." msgstr "БоÑгузливий %{name} тікає від бою." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} здаєтьÑÑ Ð²Ð¾Ñ€Ð¾Ð³Ñƒ та відходить з ганьбою." msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "Ваше війÑько зазнає гіркої поразки Ñ– %{name} відмовлÑєтьÑÑ Ð²Ñ–Ð´ вашої Ñправи." msgid "Your forces suffer a bitter defeat." msgstr "Ваше війÑько зазнає гіркої поразки." msgid "Battlefield Casualties" msgstr "Жертви на полі бою" msgid "Attacker" msgstr "Ðападник" msgid "Defender" msgstr "ЗахиÑник" msgid "Click to leave the battle results." msgstr "Тицьніть щоб вийти з результатів битви." msgid "Click to restart the battle in manual mode." msgstr "Тицьніть аби переграти битву у ручному режимі." msgid "Restart" msgstr "ПерезапуÑк" msgid "You have captured an enemy artifact!" msgstr "Ви заволоділи артефактом ворога!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "%{name} загадково щезає, щойно ви Ñпробували його забрати." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "%{name} загадково щезає, щойно ваш ворог Ñпробував його забрати." msgid "Necromancy!" msgstr "ÐекромантіÑ!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Практикуючи темне миÑтецтво некромантії, ви піднÑли %{count} мертвих " "ворогів, Ñкі тепер будуть Ñлугувати вам Ñк %{monster}." msgid "%{name} the %{race}" msgstr "%{name} %{race}" msgid "Captain of %{name}" msgstr "Капітан замку %{name}" msgid "Attack" msgstr "Ðтака" msgid "Defense" msgstr "ЗахиÑÑ‚" msgid "Spell Power" msgstr "Сила Магії" msgid "Knowledge" msgstr "ЗнаннÑ" msgid "Morale" msgstr "Мораль" msgid "Luck" msgstr "Удача" msgid "Spell Points" msgstr "Мана" msgid "Hero's Options" msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³ÐµÑ€Ð¾Ñ" msgid "Cast Spell" msgstr "ÐаклаÑти чари" msgid "Retreat" msgstr "ВідÑтупити" msgid "Surrender" msgstr "ЗдатиÑÑ" msgid "Cancel" msgstr "СкаÑувати" msgid "Hero Screen" msgstr "Вікно героÑ" msgid "Captain's Options" msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ°Ð¿Ñ–Ñ‚Ð°Ð½Ð°" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "ЗаÑтоÑувати магічне заклÑттÑ. Ви можете наÑлати лиш одне заклÑÑ‚Ñ‚Ñ ÐºÐ¾Ð¶ÐµÐ½ " "раунд. Ðовий раунд наÑтає щоразу, коли кожна Ñ–Ñтота робить (або пропуÑкає) " "Ñвій хід." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "ВідÑтупити героєм, кинувши війÑька напризволÑще. Вашого Ð³ÐµÑ€Ð¾Ñ Ð¼Ð¾Ð¶Ð½Ð° буде " "негайно найнÑти знову, однак, герой матиме такі ж війÑька, Ñк кожен " "новобранець." msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "КапітулÑÑ†Ñ–Ñ Ð²Ð°Ñ€Ñ‚ÑƒÑ” золота. Однак, Ñкщо ви Ñплатите викуп, герой разом з " "уÑіма Ñвоїми вцілілими війÑьками буде доÑтупний Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ð³Ð¾ найму. " "ВартіÑть капітулÑції Ñтановить половину від загальної вартоÑті нетимчаÑових " "війÑьк, що залишилиÑÑ Ð² армії." msgid "Open Hero Screen to view full information about the hero." msgstr "Відкрити Вікно Ð“ÐµÑ€Ð¾Ñ Ñ‰Ð¾Ð± переглÑнути повну інформацію про нього." msgid "Return to the battle." msgstr "ПовернутиÑÑ Ð´Ð¾ битви." msgid "Not enough gold (%{gold})" msgstr "ÐедоÑтатньо золота (%{gold})" msgid "%{name} states:" msgstr "%{name}, характериÑтики:" msgid "Captain of %{name} states:" msgstr "Капітан міÑта %{name}, характериÑтики:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Я прийму вашу капітулÑцію Ñ– дам безпечний прохід твоїм війÑькам за " "%{price} золота.\"" msgid "View %{monster} info" msgstr "ПереглÑнути інформацію про %{monster}" msgid "Fly %{monster} here" msgstr "%{monster}: перелетіти Ñюди" msgid "Move %{monster} here" msgstr "%{monster} переміÑÑ‚ÑтьÑÑ Ñюди" msgid "Shoot %{monster}" msgstr "Зробити поÑтріл у %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(ЗалишивÑÑ 1 поÑтріл)" msgstr[1] "(ЗалишилоÑÑ %{count} поÑтріла)" msgstr[2] "(ЗалишилоÑÑ %{count} поÑтрілів)" msgid "Attack %{monster}" msgstr "Ðтакувати %{monster}" msgid "Turn %{turn}" msgstr "Раунд %{turn}" msgid "Teleport here" msgstr "ТелепортуватиÑÑ Ñюди" msgid "Invalid teleport destination" msgstr "Ð¢ÐµÐ»ÐµÐ¿Ð¾Ñ€Ñ‚Ð°Ñ†Ñ–Ñ Ñюди неможлива" msgid "Cast %{spell} on %{monster}" msgstr "ÐаклаÑти %{spell} на %{monster}" msgid "Cast %{spell}" msgstr "ÐаклаÑти %{spell}" msgid "Select spell target" msgstr "Обрати ціль заклÑттÑ" msgid "View Ballista info" msgstr "Дані по БаліÑті" msgid "Ballista" msgstr "БаліÑта" #, fuzzy msgid "Automatic combat modes" msgstr "Ðвтобій" #, fuzzy msgid "Automatic Combat Modes" msgstr "Ðвтобій" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Ðалаштувати параметри ÑиÑтеми" msgid "Allows you to customize the combat screen." msgstr "ДозволÑÑ” налаштувати екран бою." msgid "System Options" msgstr "СиÑтемні Параметри" msgid "Skip this unit" msgstr "ПропуÑтити хід" msgid "Skip" msgstr "ПропуÑтити" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "ПропуÑтити хід Ñ–Ñтоти. Поточна Ñ–Ñтота закінчить хід та не ходитиме до " "наÑтупного раунду." msgid "View Captain's options" msgstr "Відкрити вікно дій Капітана" msgid "View Hero's options" msgstr "Відкрити вікно дій ГероÑ" msgid "View opposing Captain" msgstr "ПереглÑнути ворожого Капітана" msgid "View opposing Hero" msgstr "ПереглÑнути ворожого ГероÑ" msgid "Hide logs" msgstr "Сховати журнал" msgid "Show logs" msgstr "ДивитиÑÑ Ð¶ÑƒÑ€Ð½Ð°Ð»" msgid "Message Bar" msgstr "Табло повідомлень" msgid "Shows the results of individual monster's actions." msgstr "Відображує кожну дію та ефект, що мають міÑце на полі бою." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Ви впевнені, що хочете увімкнути автобитву?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Ви впевнені, що хочете завершити бій в автоматичному режимі?" #, fuzzy msgid "The computer continues the combat for you." msgstr "ДозволÑÑ” комп'ютеру веÑти битву за ваÑ." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Ðвтобій" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Ðвтобій" msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} пропуÑкають Ñвій хід." msgstr[1] "%{name} пропуÑкають Ñвій хід." msgstr[2] "%{name} пропуÑкають Ñвій хід." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} завдає %{damage} шкоди." msgstr[1] "%{attacker} завдають %{damage} шкоди." msgstr[2] "%{attacker} завдають %{damage} шкоди." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 Ñ–Ñтота загинула." msgstr[1] "%{count} Ñ–Ñтоти загинули." msgstr[2] "%{count} Ñ–Ñтот загинуло." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} загинув." msgstr[1] "%{count} %{defender} загинули." msgstr[2] "%{count} %{defender} загинуло." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "Одна душа поглинута." msgstr[1] "%{count} душі поглинуті." msgstr[2] "%{count} душ поглинуто." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} відродивÑÑ." msgstr[1] "%{count} %{unit} відродилоÑÑ." msgstr[2] "%{count} %{unit} відродилоÑÑ." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "%{monster}: ÐŸÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð· [%{src}] до [%{dst}]." msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "%{name} опираєтьÑÑ Ñ‡Ð°Ñ€Ð°Ð¼!" msgstr[1] "%{name} опираютьÑÑ Ñ‡Ð°Ñ€Ð°Ð¼!" msgstr[2] "%{name} опираютьÑÑ Ñ‡Ð°Ñ€Ð°Ð¼!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} чаклує %{spell} на %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} чаклує %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "%{spell} завдає %{damage} шкоди одній Ñ–Ñтоті невмерлих." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "%{spell} завдає %{damage} шкоди уÑім Ñ–Ñтотам невмерлих." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "%{spell} завдає %{damage} шкоди, %{count} Ñ–Ñтот загинуло." msgid "The %{spell} does %{damage} damage." msgstr "%{spell} завдає %{damage} шкоди." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "%{spell} завдає %{damage} шкоди одній живій Ñ–Ñтоті." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "%{spell} завдає %{damage} шкоди уÑім живим Ñ–Ñтотам." msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Ðтака %{attacker} оÑліплює %{target}!" msgstr[1] "Ðтака %{attacker} оÑліплює %{target}!" msgstr[2] "Ðтака %{attacker} оÑліплює %{target}!" msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "ПоглÑд %{attacker} перетворює %{target} на камінь!" msgstr[1] "ПоглÑд %{attacker} перетворює %{target} на камінь!" msgstr[2] "ПоглÑд %{attacker} перетворює %{target} на камінь!" msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "%{attacker} наÑилає проклÑÑ‚Ñ‚Ñ Ð½Ð° %{target}!" msgstr[1] "%{attacker} наÑилає проклÑÑ‚Ñ‚Ñ Ð½Ð° %{target}!" msgstr[2] "%{attacker} наÑилає проклÑÑ‚Ñ‚Ñ Ð½Ð° %{target}!" msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "%{attacker} паралізує %{target}!" msgstr[1] "%{attacker} паралізує %{target}!" msgstr[2] "%{attacker} паралізує %{target}!" msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" "%{attacker} розвіює вÑÑ– добрі чари, що були накладені на ваших %{target}!" msgstr[1] "" "%{attacker} розвіює вÑÑ– добрі чари, що були накладені на ваших %{target}!" msgstr[2] "" "%{attacker} розвіює вÑÑ– добрі чари, що були накладені на ваших %{target}!" msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "%{attacker} накладає заклÑÑ‚Ñ‚Ñ \"%{spell}\" на %{target}!" msgstr[1] "%{attacker} накладають заклÑÑ‚Ñ‚Ñ \"%{spell}\" на %{target}!" msgstr[2] "%{attacker} накладають заклÑÑ‚Ñ‚Ñ \"%{spell}\" на %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Удача відвернулаÑÑŒ від %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "Удача поÑміхнулаÑÑŒ %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "ЗавдÑки виÑокій моралі %{monster} атакує знову." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Через низьку мораль %{monster} завмер у паніці." msgid "%{tower} does %{damage} damage." msgstr "%{tower} завдає %{damage} шкоди." msgid "The mirror image is created." msgstr "Створено Дзеркального Фантома." msgid "The mirror image is destroyed!" msgstr "Фантомний загін знищений!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Ви впевнені, що хочете перервати автоматичний бій?" msgid "Error" msgstr "Помилка" msgid "No spells to cast." msgstr "Ðема чар Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтаннÑ." msgid "Are you sure you want to retreat?" msgstr "Ви впевнені, що хочете відÑтупити?" msgid "Retreat disabled" msgstr "ВідÑтуп неможливий" msgid "Surrender disabled" msgstr "КапітулÑÑ†Ñ–Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ð°" msgid "Damage: %{max}" msgstr "Шкода: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Шкода: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Загине %{max}" msgid "Perish: %{min} - %{max}" msgstr "Загине %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "ЗавдÑки орлиному зору %{name} зміг вивчити магічне заклÑÑ‚Ñ‚Ñ %{spell}." msgid "Human" msgstr "Людина" msgid "AI" msgstr "Комп'ютер" msgid "Start" msgstr "Почати" msgid "Start the battle." msgstr "Почати битву." msgid "Exit" msgstr "Вийти" msgid "Reset" msgstr "Скинути" # By default - перекладають Ñк "За замовчуваннÑм", але це калька з .... мови. # Мовознавець ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Reset to default settings." msgstr "Скинути до уÑталених налаштувань." msgid "Please select another hero." msgstr "Будь лаÑка, оберіть іншого героÑ." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} проти %{race2} %{name2}" msgid "Monsters" msgstr "МонÑтри" msgid "N/A" msgstr "Ð/Д" msgid "Left Turret" msgstr "Ліва Вежа" msgid "Right Turret" msgstr "Права Вежа" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} б'Ñ” із Ñилою %{count} Лучників" msgid "each with a +%{attack} bonus to their attack skill." msgstr "кожна з бонуÑом +%{attack} до Ð²Ð¼Ñ–Ð½Ð½Ñ Ðтаки." msgid "The %{name} is destroyed." msgstr "%{name} знищено." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} піднÑто з мертвих!" msgstr[1] "%{count} %{name} піднÑто з мертвих!" msgstr[2] "%{count} %{name} піднÑто з мертвих!" msgid "Dwarven Alliance" msgstr "ÐльÑÐ½Ñ Ð“Ð½Ð¾Ð¼Ñ–Ð²" msgid "Sorceress Guild" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð§Ð°Ñ€Ð¾Ð´Ñ–Ð¹Ð¾Ðº" msgid "Necromancer Guild" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ Ðекромантів" msgid "Ogre Alliance" msgstr "ÐльÑÐ½Ñ ÐžÐ³Ñ€Ñ–Ð²" msgid "Dwarfbane" msgstr "Гномогубець" msgid "Dragon Alliance" msgstr "ÐльÑÐ½Ñ Ð”Ñ€Ð°ÐºÐ¾Ð½Ñ–Ð²" msgid "Elven Alliance" msgstr "ЕльфійÑький ÐльÑнÑ" msgid "Kraeger defeated" msgstr "Краегер подоланий" msgid "Wayward Son" msgstr "Син Вейварда" msgid "Uncle Ivan" msgstr "ДÑдько Іван" msgid "Annexation" msgstr "ÐннекÑÑ–Ñ" msgid "Force of Arms" msgstr "Сила Зброї" msgid "Save the Dwarves" msgstr "ПорÑтунок Гномів" msgid "Carator Mines" msgstr "КараторÑькі Копальні" msgid "Turning Point" msgstr "Поворотний Момент" msgid "scenarioName|Defender" msgstr "Оборонець" msgid "Corlagon's Defense" msgstr "Оборона Корлагона" msgid "The Crown" msgstr "Корона" msgid "The Gauntlet" msgstr "РукавицÑ" msgid "Betrayal" msgstr "Зрада" msgid "Final Justice" msgstr "ОÑтаточне ПравоÑуддÑ" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Ви потрібні Роландові щоб перемогти лордів Ð±Ñ–Ð»Ñ Ð¹Ð¾Ð³Ð¾ замку, тим Ñамим " "почавши його повÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ‚Ð¸ брата. Вони не укладали Ñоюзу, то ж переважно " "воюватимуть одне з одним. Ви переможете, коли захопите вÑÑ– Ñ—Ñ… замки та " "переможете вÑÑ–Ñ… Ñ—Ñ… героїв." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "МіÑцеві лорди відмовилиÑÑŒ приÑÑгнути Роландові на вірніÑть, тому Ñ—Ñ… треба " "підкорити. Вони багаті та могутні, то ж приготуйтеÑÑŒ до запеклого Ñпротиву. " "Захопіть вÑÑ– Ñ—Ñ… замки, щоб перемогти." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Ваше Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ð»Ñгає у захиÑті Гномів від Ñил Ðрчибальда. Захопіть вÑÑ– " "ворожі міÑта та замки щоб перемогти, та переконайтеÑÑŒ, що ворог не " "володітиме вÑіма міÑтами гномів одночаÑно, інакше він виграє." msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Ви зітнетеÑÑŒ з чотирма об'єднаними ворогами у відкритому протиÑтоÑнні за " "реÑурÑи та Ñкарби. Захопіть вÑÑ– ворожі замки, щоб перемогти." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Ваші вороги об'єдналиÑÑŒ, та розташували Ñвої Ñили неподалік від ваÑ, то ж " "готуйтеÑÑŒ до запеклої боротьби. Вам треба захопити вÑÑ– чотири замки цієї " "маленької долини, щоб перемогти." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð§Ð°Ñ€Ð¾Ð´Ñ–Ð¹Ð¾Ðº ÐораÑтону надіÑлала Роландові запит про допомогу у " "боротьбі проти атакуючих Ñоюзників Ðрчибальда. Захопіть вÑÑ– ворожі замки щоб " "перемогти, та не втратьте ÐораÑтон, інакше програєте. (Підказка: Один з " "ворожих замків розташований в океані)." msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Зберіть Ñкомога більше війÑько та захопіть ворожий замок протÑгом 8 тижнів. " "Вам протиÑтоїть лише один ворог, однак ви маєте пройти довгий шлÑÑ…, щоб " "доÑÑгти його замку. Ð’ÑÑ– війÑька, що залишатьÑÑ Ð· вами піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ " "Ñценарію будуть з вами у фінальному Ñценарії." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Знайдіть Корону перш, ніж це зроблÑть герої Ðрчибальда. Роландові " "знадобитьÑÑ ÐšÐ¾Ñ€Ð¾Ð½Ð° Ð´Ð»Ñ Ñ„Ñ–Ð½Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ бою проти Ðрчибальда." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Три об'єднані Ñоюзом вороги ÑтоÑть між вами та перемогою. Серед них Ñ” Ñ– Лорд " "Корлагон. Роланд знаходитьÑÑ Ñƒ замку на північний захід, Ñ– ви програєте, " "Ñкщо він потрапить до ворожих рук. Пам'Ñтайте, що Ð·Ð°Ñ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ Ð›Ð¾Ñ€Ð´Ð° Корлагона " "не дозволить йому битиÑÑŒ проти Ð²Ð°Ñ Ñƒ фінальному Ñценарії." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Це фінальна битва. Як Ñ– ви, ваші вороги озброєні до зубів, Ñ– вÑÑ– вони у " "Ñоюзі проти ваÑ. Захопіть Ðрчибальда щоб Ñкінчити війну, та не втратьте " "Роланда у бою!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Перехід на інший бік залишив вашого ворога з одним замком проти ваших трьох. " "Ð¦Ñ Ð±Ð¸Ñ‚Ð²Ð° буде найлегшою з тих, що чекають на Ð²Ð°Ñ Ñƒ цій війні... зраднику." msgid "Barbarian Wars" msgstr "ВарварÑькі Війни" msgid "First Blood" msgstr "Перша Кров" msgid "Necromancers" msgstr "Ðекроманти" msgid "Slay the Dwarves" msgstr "Ð’Ð¸Ð½Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð“Ð½Ð¾Ð¼Ñ–Ð²" msgid "Country Lords" msgstr "Землі Володарів" msgid "Dragon Master" msgstr "Повелитель Драконів" msgid "Rebellion" msgstr "ПовÑтаннÑ" msgid "Apocalypse" msgstr "ÐпокаліпÑиÑ" msgid "Greater Glory" msgstr "Ðайбільша Слава" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Король Ðрчибальд вимагає, щоб ви здолали трьох ворогів у цьому регіоні. Вони " "не поєднані Ñоюзом, то ж більшу чаÑтину Ñвоїх Ñил витратÑть на боротьбу одне " "з одним. Ви переможете, коли заволодієте уÑіма ворожими замками, та не " "залишитьÑÑ Ð³ÐµÑ€Ð¾Ñ—Ð², з Ñкими можна битиÑÑ." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Ви муÑите об'єднати варварÑькі племена півночі, завоювавши Ñ—Ñ…. Як Ñ– в " "попередньому завданні, вороги не об'єднані проти ваÑ, однак у них в " "розпорÑдженні більше реÑурÑів. Ви переможете, коли заволодієте уÑіма " "ворожими замками, Ñ– коли не залишитьÑÑ Ð³ÐµÑ€Ð¾Ñ—Ð², з Ñкими можна битиÑÑ." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Добрі чарівники захопили замок Ðекромантів. Ви маєте повернути його, щоб " "доÑÑгти перемоги. Пам'Ñтайте, що хоча ви й починаєте з потужним війÑьком, у " "Ð²Ð°Ñ Ð½Ðµ буде замку, то ж ви муÑите захопити будь-Ñкий замок протÑгом 7 днів, " "інакше програєте. (Підказка: Ðайближчий замок знаходитьÑÑ Ð½Ð° північний Ñхід " "від ваÑ)." msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Гномів потрібно завоювати перш, ніж вони зможуть втрутитиÑÑŒ у плани ÐšÐ¾Ñ€Ð¾Ð»Ñ " "Ðрчибальда. Сили Роланда мають більше ніж одного героÑ, та починають з " "багатьма міÑтами, то ж будьте готові до нападів з різних напрÑмків. Ви " "муÑите захопити вÑÑ– ворожі міÑта та замки, щоб доÑÑгти перемоги." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Ви маєте поклаÑти край ÑелÑнÑькому повÑтанню, очоленому Ñилами Роланда. Ð’ÑÑ– " "об'єднані проти ваÑ, однак на вашому боці Лорд Корлагон, доÑвідчений герой, " "що допоможе вам. Захопіть вÑÑ– ворожі замки, щоб перемогти." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "У цьому завданні проти Ð²Ð°Ñ Ð¾Ð±'єдналиÑÑ Ð´Ð²Ð¾Ñ” ворогів. Обидва вони добре " "озброєні, та шукають ÑпоÑобу вигнати Ð²Ð°Ñ Ð· Ñ—Ñ… оÑтрова. Уникайте Ñ—Ñ…, та " "захопіть МіÑто Драконів щоб перемогти." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Вам наказано завоювати землі володарів, що поклÑлиÑÑ Ñлужити Роланду. Ð’ÑÑ– " "ворожі замки об'єднані проти ваÑ. ОÑкільки ви починаєте без замку, ви маєте " "поквапитиÑÑ Ñ‚Ð° захопити один перш, ніж мине тиждень. Захопіть вÑÑ– ворожі " "замки Ð·Ð°Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ð³Ð¸." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Знайдіть Корону перш, ніж це зроблÑть герої Роланда. Ðрчибальду знадобитьÑÑ " "Корона у фінальній битві проти Роланда." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Це фінальна битва. Як Ñ– ви, ваші вороги озброєні до зубів, Ñ– вÑÑ– вони у " "Ñоюзі проти ваÑ. Захопіть Роланда щоб Ñкінчити війну, та переконайтеÑÑŒ, що " "ви не загубите Ðрчибальда у битві!" msgid "Arrow's Flight" msgstr "Політ Стріли" msgid "Island of Chaos" msgstr "ОÑтрів ХаоÑу" msgid "The Abyss" msgstr "БезоднÑ" msgid "Uprising" msgstr "ПовÑтаннÑ" msgid "Aurora Borealis" msgstr "Північне СÑйво" msgid "Betrayal's End" msgstr "Кінець Зради" msgid "Corruption's Heart" msgstr "Серце Скверни" msgid "The Giant's Pass" msgstr "Перевал Велетнів" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Підкоріть непокірних міÑцевих лордів, щоб забезпечити Імперії можливоÑті Ð´Ð»Ñ " "діÑльноÑті у цьому регіоні." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "УÑуньте веÑÑŒ Ñпротив у цих землÑÑ…. Тоді ви заволодієте першою чаÑтиною " "артефакту." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Чаклунки на північний Ñхід повÑтали! Ð—Ð°Ð´Ð»Ñ Ð±Ð»Ð°Ð³Ð° вашої імперії ви маєте " "придушити Ñ—Ñ… дрібне повÑÑ‚Ð°Ð½Ð½Ñ Ð½Ð° шлÑху до гір." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "ПідготувавшиÑÑŒ до вашого прибуттÑ, Краегер зібрав Ñили некромантів щоб " "перешкодити вашим пошукам. Ви маєте захопити замок СкабÑдейл перш ніж " "наÑтане перший день третього тижнÑ, інакше Ðекроманти Ñтануть надто " "могутніми Ð´Ð»Ñ Ð²Ð°Ñ." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "ВарварÑький деÑпот, що править цими землÑми, доÑÑ– не знає про вашу " "приÑутніÑть. Якнайшвидше нароÑтіть Ñвої Ñили перш, ніж Ð²Ð°Ñ Ñ€Ð¾Ð·ÐºÑ€Ð¸ÑŽÑ‚ÑŒ та " "атакують! ЗахиÑтіть регіон, впокоривши вÑÑ– ворожі Ñили." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Ð†Ð¼Ð¿ÐµÑ€Ñ–Ñ Ñлабка у цьому регіоні. Ви не зможете здолати вÑÑ– наÑвні ворожі " "Ñили, тому хапайте вÑе, що зможете перш, ніж вам завдадуть удару у " "відповідь. Пам'Ñтайте, що ваша головна мета - заволодіти Шоломом Ðндурана." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Ðа благо Імперії знищте Краегера." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Ðарешті, у Ð²Ð°Ñ Ñ” можливіÑть та заÑоби щоб позбавити Імперію від зла " "некромантів. Викорініть Ñ—Ñ…, щоб Ñ– Ñліду не лишилоÑÑŒ, Ñ– Ð²Ð°Ñ Ð¾Ñпівуватимуть Ñк " "Ð³ÐµÑ€Ð¾Ñ Ð²ÑÑ–Ñ… чаÑів." msgid "Border Towns" msgstr "Прикордонні МіÑта" msgid "Conquer and Unify" msgstr "Завойовувати та Об'єднувати" msgid "Crazy Uncle Ivan" msgstr "Божевільний ДÑдько Іван" msgid "The Wayward Son" msgstr "Блудний Син" msgid "Ivory Gates" msgstr "Брама Слонової КіÑтки" msgid "The Elven Lands" msgstr "ЕльфійÑькі Землі" msgid "The Epic Battle" msgstr "Епічна Битва" msgid "The Southern War" msgstr "Південна Війна" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Завоюйте та об'єднайте ворожі племена. Ðе втратьте Ð³ÐµÑ€Ð¾Ñ Ð”Ð¶Ð°Ñ€ÐºÐ¾Ð½Ð°Ñа, " "прабатька вÑÑ–Ñ… нащадків." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Ваш Ñуперник, КоролівÑтво Харондейл, атакує Ñлабкі міÑта на ваших кордонах! " "ОговтайтеÑÑŒ від Ñ—Ñ… першого удару та розбийте Ñ—Ñ… вщент!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Знайдіть вашого блудного Ñина Джозефа, що, за чутками, живе у ÑпуÑтошених " "землÑÑ…. Зробіть це перш, ніж наÑтане перший день третього міÑÑцÑ, інакше " "вашій родині вже не можна буде допомогти." msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Ð’Ñ€Ñтуйте Ñвого божевільного дÑдька Івана. Знайдіть його до наÑÑ‚Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ " "Ð´Ð½Ñ Ñ‡ÐµÑ‚Ð²ÐµÑ€Ñ‚Ð¾Ð³Ð¾ міÑÑцÑ, інакше вашому королівÑтву вже не можна буде допомогти." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Знищте варварів, що атакують південні кордони вашого королівÑтва! Відновіть " "ваші захоплені міÑта, а тоді наÑтупайте на королівÑтво у джунглÑÑ…. Ðе " "лишайте жодного ворога в живих." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Поверніть замок Брама Слонової КіÑтки, що був втрачений через зраду." msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Завоюйте прихильніÑть ельфів. Вони не дозволÑють рубати дерева, тому ми " "надÑилатимемо вам деревину кожні 2 тижні. Ви маєте виконати Ñвою міÑÑ–ÑŽ до " "першого Ð´Ð½Ñ Ñьомого міÑÑцÑ, інакше королівÑтво неодмінно паде." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Це оÑÑ‚Ð°Ð½Ð½Ñ Ð±Ð¸Ñ‚Ð²Ð° проти вашого Ñуперника - королівÑтва Харондейл. Винищте " "уÑÑ–Ñ…, але не втратьте Ð³ÐµÑ€Ð¾Ñ Ð”Ð¶Ð°Ñ€ÐºÐ¾Ð½Ð°Ñа ШоÑтого." msgid "Fount of Wizardry" msgstr "Джерело Магії" msgid "Power's End" msgstr "Кінець МогутноÑті" msgid "The Eternal Scrolls" msgstr "Вічні Сувої" msgid "The Shrouded Isles" msgstr "Закутані ОÑтрови" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Ваше Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ - знищити ворогуючих магів на магічних Закутаних ОÑтровах. " "Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð´Ð°Ñть вам ÑˆÐ°Ð½Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ð³Ñ‚Ð¸ ваших Ñуперників." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "МіÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð²ÐµÐ»Ð¸ÐºÐ¾Ñ— бібліотеки розкрите! Ви маєте проклаÑти Ñвій шлÑÑ… " "до неї, та повернути міÑто ХроноÑ, в Ñкому вона розташована." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Знайдіть Сферу ЗапереченнÑ, що, Ñк кажуть, похована деÑÑŒ у цих землÑÑ…. Ðа " "кам'Ñних обеліÑках викарбувані підказки, Ñкі допоможуть вам знайти приз. " "Знайдіть Сферу раніше, ніж мине шоÑтий міÑÑць, інакше ваші Ñуперники напевно " "діÑтанутьÑÑ Ð´Ð¾ джерела раніше ваÑ." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Ви муÑите захопити замок МагіÑ, у Ñкому знаходитьÑÑ Ð”Ð¶ÐµÑ€ÐµÐ»Ð¾ Магії. Зробіть " "це, Ñ– ваша перемога буде оÑтаточною." msgid "Blood is Thicker" msgstr "Кров ГуÑтіша" msgid "King and Country" msgstr "Король та Країна" msgid "Pirate Isles" msgstr "ПіратÑькі ОÑтрови" msgid "Stranded" msgstr "Ðа Мілині" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Захопіть міÑто на оÑтрові Ð±Ñ–Ð»Ñ Ð¿Ñ–Ð²Ð´ÐµÐ½Ð½Ð¾-Ñхідного берега, щоб збудувати " "корабель та відбути назад на материк. Ðе втратьте Ð³ÐµÑ€Ð¾Ñ - Галлаванта." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Знайдіть та здолайте Мартіна, піратÑького ватага, що мешкає у ПіратÑькій " "Бухті. Ðе втратьте Галлаванта, інакше ваші пошуки завершатьÑÑ." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Знищте вÑÑ– Ñили, що протиÑтоÑть Лорду Ðльберону. Галлавант муÑить вціліти." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Поваліть уÑталену монархію Лорда Ðльберона, та захопіть цей край Ð´Ð»Ñ Ñебе. " "Галлавант муÑить вціліти." msgid " bane" msgstr " згуба" msgid " alliance" msgstr " альÑнÑ" msgid "Carry-over forces" msgstr "Збережені війÑька" msgid " bonus" msgstr " бонуÑ" msgid " defeated" msgstr " подоланий" msgid " will always run away from your army." msgstr " завжди тікатимуть від вашого війÑька." msgid " will be willing to join your army." msgstr " завжди волітимуть приєднатиÑÑŒ до вашого війÑька." msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "Ðртефакт \"%{artifact}\" буде перенеÑений до Ñценарію." msgid "The army will be carried over in the campaign." msgstr "ВійÑько буде перенеÑене до Ñценарію." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "КоролівÑтво отримає додатковий прибуток: + %{count} %{resource} щоднÑ." msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "ЗаклÑÑ‚Ñ‚Ñ \"%{spell}\" буде перенеÑено до Ñценарію." msgid "%{hero} can be hired during scenarios." msgstr "Герой %{hero} буде доÑтупним Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ñƒ у Ñценарії." msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "Герой %{hero} був подоланий та не з'ÑвитьÑÑ Ñƒ подальших ÑценаріÑÑ…." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Гноми розпізнали Ñвого Ñоюзника, та з радіÑтю приєднаютьÑÑ Ð´Ð¾ ваших Ñил." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "Огри впізнали у Ð²Ð°Ñ Ð“Ð½Ð¾Ð¼Ð¾Ð³ÑƒÐ±Ñ†Ñ, Ñ– воліють приєднатиÑÑŒ до ваÑ." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "З незадоволеним гарчаннÑм дракони погоджуютьÑÑ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑŒ до ваÑ, Ñ—Ñ… " "\"Ñоюзника\"." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Коли ви наближаєтеÑÑŒ до групи ельфів, Ñ—Ñ… лідер проÑить уваги та звертаєтьÑÑ " "до них: \"Хто з Ð²Ð°Ñ Ð´Ð¾Ñтатньо хоробрий, щоб приєднатиÑÑŒ до нашого " "безÑтрашного Ñоюзника?\" Група вибухає радіÑними вітаннÑми, вливаючиÑÑŒ до " "ваших лав." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "Гноми вітають ваÑ: \"Друзі Роланда - наші друзі. Ви можете пройти\"." msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Огри Ñхвально рохкають, впізнавши ваÑ: \"Союзники Ðрчібальда можуть пройти\"." msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Дракони, помітивши ваше війÑько, звернулиÑÑŒ до ваÑ: \"Ðаш альÑÐ½Ñ Ð· " "Ðрчібальдом змушує Ð½Ð°Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ñ‚Ð¸ÑÑŒ до ваÑ. Шкода, що у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” міÑцÑ. Як " "прикро!\" - з цими Ñловами вони швидко розлітаютьÑÑ Ð³ÐµÑ‚ÑŒ." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Ельфи уважно дивлÑтьÑÑ Ð½Ð° ваÑ, поки ви наближаєтеÑÑŒ. Їх лідер звернувÑÑ Ð´Ð¾ " "ваÑ: \"Ми не заважатимемо вашому проÑуванню, Ñоюзнику! Йдіть вперед, Ñ– нехай " "перемога буде за вами\"." msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Гномогубець!!!! РÑтуйтеÑÑŒ хто може!\"" msgid "campaignBonus|Animate Dead" msgstr "Оживити Мерців" msgid "campaignBonus|Chain Lightning" msgstr "Ланцюгова БлиÑкавка" msgid "campaignBonus|Fireblast" msgstr "ВогнÑний Вибух" msgid "campaignBonus|Mass Curse" msgstr "МаÑове ПроклÑттÑ" msgid "campaignBonus|Mass Haste" msgstr "МаÑовий ПоÑпіх" msgid "campaignBonus|Mirror Image" msgstr "Дзеркальний Фантом" # ВоÑкреÑÑ–Ð½Ð½Ñ - Resurection # ВоÑкреÑити - Resurrect msgid "campaignBonus|Resurrect" msgstr "ВоÑкреÑити" msgid "campaignBonus|Steelskin" msgstr "Сталева Шкіра" msgid "campaignBonus|Summon Earth" msgstr "Виклик Землі" msgid "campaignBonus|View Heroes" msgstr "ОглÑд Героїв" msgid "campaignBonus|Ballista" msgstr "БаліÑта" msgid "campaignBonus|Black Pearl" msgstr "Чорна Перлина" msgid "campaignBonus|Caster's Bracelet" msgstr "БраÑлет ЗаклинателÑ" msgid "campaignBonus|Defender Helm" msgstr "Шолом ЗахиÑника" msgid "campaignBonus|Breastplate" msgstr "Ðагрудник" msgid "campaignBonus|Dragon Sword" msgstr "Меч Дракона" msgid "campaignBonus|Fizbin Medal" msgstr "Медаль Фізбін" msgid "campaignBonus|Foremost Scroll" msgstr "Древній Сувій" msgid "campaignBonus|Gauntlets" msgstr "Рукавиці" msgid "campaignBonus|Hideous Mask" msgstr "Мерзенна МаÑка" # Mage's Ring - показує належніÑть перÑÑ‚Ð½Ñ Ð¼Ð°Ð³Ñƒ, а не Ñ” його характериÑтикою. # Mage's Ring - перÑтень мага # Magical Ring - магічний перÑтень msgid "campaignBonus|Mage's Ring" msgstr "ПерÑтень мага" msgid "campaignBonus|Major Scroll" msgstr "Великий Сувій" msgid "campaignBonus|Medal of Honor" msgstr "Медаль пошани" msgid "campaignBonus|Medal of Valor" msgstr "Медаль за Відвагу" msgid "campaignBonus|Minor Scroll" msgstr "Малий Сувій" msgid "campaignBonus|Nomad Boots" msgstr "Чоботи Кочівника" msgid "campaignBonus|Power Axe" msgstr "Силова Сокира" msgid "campaignBonus|Spiked Shield" msgstr "ШпичаÑтий Щит" msgid "campaignBonus|Stealth Shield" msgstr "Ðезримий Щит" msgid "campaignBonus|Tax Lien" msgstr "Податкова ЗаÑтава" msgid "campaignBonus|Thunder Mace" msgstr "Громова Булава" msgid "campaignBonus|Traveler's Boots" msgstr "Чоботи Мандрівника" msgid "campaignBonus|White Pearl" msgstr "Біла Перлина" msgid "campaignBonus|Basic Archery" msgstr "Базова Стрільба" msgid "campaignBonus|Advanced Archery" msgstr "ПроÑунута Стрільба" msgid "campaignBonus|Expert Archery" msgstr "ЕкÑпертна Стрільба" msgid "campaignBonus|Basic Ballistics" msgstr "Базова БаліÑтика" msgid "campaignBonus|Advanced Ballistics" msgstr "ПроÑунута БаліÑтика" msgid "campaignBonus|Expert Ballistics" msgstr "ЕкÑпертна БаліÑтика" msgid "campaignBonus|Basic Diplomacy" msgstr "Базова ДипломатіÑ" msgid "campaignBonus|Advanced Diplomacy" msgstr "ПроÑунута ДипломатіÑ" msgid "campaignBonus|Expert Diplomacy" msgstr "ЕкÑпертна ДипломатіÑ" msgid "campaignBonus|Basic Eagle Eye" msgstr "Базовий Орлиний Зір" msgid "campaignBonus|Advanced Eagle Eye" msgstr "ПроÑунутий Орлиний Зір" msgid "campaignBonus|Expert Eagle Eye" msgstr "ЕкÑпертний Орлиний Зір" # ЙдетьÑÑ Ð¼Ð¾Ð²Ð° про Ð¿Ñ€Ð¾Ñ†ÐµÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐºÐ¾ÑˆÑ‚Ñ–Ð², тому Маєтки (Ð²Ð¾Ð»Ð¾Ð´Ñ–Ð½Ð½Ñ Ð½Ð¸Ð¼Ð¸ та вигодонабуваннÑ) більш Ñлушне. Можливо навіть краще "Поміщництво" (Ñ” у тлумачному Ñловнику) msgid "campaignBonus|Basic Estates" msgstr "Базова Маєтки" msgid "campaignBonus|Advanced Estates" msgstr "ПроÑунута Маєтки" msgid "campaignBonus|Expert Estates" msgstr "ЕкÑпертна Маєтки" msgid "campaignBonus|Basic Leadership" msgstr "Базове ЛідерÑтво" msgid "campaignBonus|Advanced Leadership" msgstr "ПроÑунуте ЛідерÑтво" msgid "campaignBonus|Expert Leadership" msgstr "ЕкÑпертне ЛідерÑтво" msgid "campaignBonus|Basic Logistics" msgstr "Базова ЛогіÑтика" msgid "campaignBonus|Advanced Logistics" msgstr "ПроÑунута ЛогіÑтика" msgid "campaignBonus|Expert Logistics" msgstr "ЕкÑпертна ЛогіÑтика" msgid "campaignBonus|Basic Luck" msgstr "Базова Удача" msgid "campaignBonus|Advanced Luck" msgstr "ПроÑунута Удача" msgid "campaignBonus|Expert Luck" msgstr "ЕÑпертна Удача" msgid "campaignBonus|Basic Mysticism" msgstr "Базовий МіÑтицизм" msgid "campaignBonus|Advanced Mysticism" msgstr "ПроÑунутий МіÑтицизм" msgid "campaignBonus|Expert Mysticism" msgstr "ЕкÑпертний МіÑтицизм" msgid "campaignBonus|Basic Navigation" msgstr "Базова ÐавігаціÑ" msgid "campaignBonus|Advanced Navigation" msgstr "ПроÑунута ÐавігаціÑ" msgid "campaignBonus|Expert Navigation" msgstr "ЕкÑпертна ÐавігаціÑ" msgid "campaignBonus|Basic Necromancy" msgstr "Базова ÐекромантіÑ" msgid "campaignBonus|Advanced Necromancy" msgstr "ПроÑунута ÐекромантіÑ" msgid "campaignBonus|Expert Necromancy" msgstr "ЕкÑпертна ÐекромантіÑ" msgid "campaignBonus|Basic Pathfinding" msgstr "Базовий Пошук шлÑху" msgid "campaignBonus|Advanced Pathfinding" msgstr "ПроÑунутий Пошук шлÑху" msgid "campaignBonus|Expert Pathfinding" msgstr "ЕкÑпертний Пошук шлÑху" msgid "campaignBonus|Basic Scouting" msgstr "Базова Розвідка" msgid "campaignBonus|Advanced Scouting" msgstr "ПроÑунута Розвідка" msgid "campaignBonus|Expert Scouting" msgstr "ЕкÑпертна Розвідка" msgid "campaignBonus|Basic Wisdom" msgstr "Базова МудріÑть" msgid "campaignBonus|Advanced Wisdom" msgstr "ПроÑунута МудріÑть" msgid "campaignBonus|Expert Wisdom" msgstr "ЕкÑпертна МудріÑть" msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "Головний герой отримає артефакт \"%{artifact}\" на початку Ñценарію." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Ðа початку Ñценарію королівÑтво отримає на %{amount} од. більше реÑурÑу: " "%{resource}." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Ðа початку Ñценарію королівÑтво отримає на %{amount} од. менше реÑурÑу: " "%{resource}." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Головний герой отримає %{count} %{monster} на початку Ñценарію." msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "Головний герой буде знати чари \"%{spell}\" на початку Ñценарію." msgid "The starting alignment of the scenario will be %{race}." msgstr "Початковою раÑою Ñценарію буде %{race}." msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "Головний герой матиме додатково %{count} %{skill} на початку Ñценарію." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Головний герой матиме %{skill} на початку Ñценарію." msgid "Roland" msgstr "Роланд" msgid "Archibald" msgstr "Ðрчібальд" msgid "Price of Loyalty" msgstr "Ціна ВірноÑті" msgid "Voyage Home" msgstr "Подорож Додому" msgid "Wizard's Isle" msgstr "ОÑтрів Мага" msgid "Descendants" msgstr "Ðащадки" msgid "Cannot build. You have already built here today." msgstr "Ðеможливо будувати. Ви вже будували тут Ñьогодні." msgid "For this action it is necessary to build a castle first." msgstr "Ð”Ð»Ñ Ñ†Ñ–Ñ”Ñ— дії треба Ñпочатку побудувати замок." msgid "The %{building} produces %{monster}." msgstr "%{building} - житло, в Ñкому доÑтупні Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ñƒ %{monster}." msgid "Requires:" msgstr "Потрібно:" msgid "Exit this menu without doing anything." msgstr "Вийти з меню без змін." msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Ðеможливо побудувати %{name}, бо замок далеко від води." msgid "This building has been disabled." msgstr "Цю будівлю відключено." msgid "Cannot afford the %{name}." msgstr "Ðе можна дозволити %{name}." msgid "The %{name} is already built." msgstr "%{name} вже збудовано." msgid "Cannot build the %{name}." msgstr "%{name} - будівництво неможливе." msgid "Build %{name}." msgstr "Будувати: %{name}." msgid "Blackridge" msgstr "Блекрідж" msgid "Hillstone" msgstr "ХілÑтон" msgid "Pinehurst" msgstr "ПайнхерÑÑ‚" msgid "Whiteshield" msgstr "Вайтшилд" msgid "Woodhaven" msgstr "Вудхевен" msgid "Blackwind" msgstr "Блеквінд" msgid "Bloodreign" msgstr "Бладрейн" msgid "Dragontooth" msgstr "Драгонтуф" msgid "Greywind" msgstr "Грейвінд" msgid "Portsmith" msgstr "ПортÑміт" msgid "Atlantium" msgstr "Ðтлантіум" msgid "Middle Gate" msgstr "Мідлгейт" msgid "Sansobar" msgstr "Санзобар" msgid "Tundara" msgstr "Тундара" msgid "Vulcania" msgstr "ВулканіÑ" msgid "Baywatch" msgstr "Бейвотч" msgid "Fountainhead" msgstr "Фаунтейнхед" msgid "Vertigo" msgstr "Вертіго" msgid "Wildabar" msgstr "Вайлдабар" msgid "Winterkill" msgstr "Вінтеркілл" msgid "Brindamoor" msgstr "Бріндамур" msgid "Lakeside" msgstr "ЛейкÑайд" msgid "Nightshadow" msgstr "Ðайтшедоу" msgid "Olympus" msgstr "ОлімпуÑ" msgid "Sandcaster" msgstr "СендкаÑтер" msgid "Alamar" msgstr "Ðламар" msgid "Burlock" msgstr "Бурлок" msgid "Dragadune" msgstr "Драгадун" msgid "Kalindra" msgstr "Каліндра" msgid "Xabran" msgstr "КÑабран" msgid "Algary" msgstr "Ðлгарі" msgid "Basenji" msgstr "БаÑенджі" msgid "Blackfang" msgstr "Блекфанг" msgid "New Dawn" msgstr "Ðью-Давн" msgid "Sorpigal" msgstr "Сорпігал" msgid "Avone" msgstr "Ейвон" msgid "Big Oak" msgstr "Біг-Оук" msgid "Chandler" msgstr "Чандлер" msgid "Erliquin" msgstr "Ерліквін" msgid "Hampshire" msgstr "Гемпшир" msgid "Antioch" msgstr "Ðнтіох" msgid "Avalon" msgstr "Ðвалон" msgid "Roc Haven" msgstr "Рокхевен" msgid "South Mill" msgstr "Сауфмілл" msgid "Weed Patch" msgstr "Уідпатч" msgid "Brownston" msgstr "БраунÑтон" msgid "Hilltop" msgstr "Хіллтоп" msgid "Weddington" msgstr "Веддінгтон" msgid "Westfork" msgstr "ВеÑтфорк" msgid "Whittingham" msgstr "Уіттінгем" msgid "Cathcart" msgstr "Кеткарт" msgid "Elk's Head" msgstr "ЕлкÑхед" msgid "Roscomon" msgstr "РоÑкомон" msgid "Sherman" msgstr "Шерман" msgid "Yorksford" msgstr "ЙоркÑфорд" msgid "Blackburn" msgstr "Блекбурн" msgid "Blacksford" msgstr "БлекÑфорд" msgid "Burton" msgstr "Бьортон" msgid "Pig's Eye" msgstr "Пігз-Ðй" msgid "Viper's Nest" msgstr "ВайперÑнеÑÑ‚" msgid "Fenton" msgstr "Фентон" msgid "Lankershire" msgstr "Ланкершир" msgid "Lombard" msgstr "ЛомбардÑбург" msgid "Timberhill" msgstr "Тімберхілл" msgid "Troy" msgstr "ТроÑ" msgid "Forder Oaks" msgstr "ФордероукÑ" msgid "Meramec" msgstr "Мерамек" msgid "Quick Silver" msgstr "КвікÑілвер" msgid "Westmoor" msgstr "ВеÑтмур" msgid "Willow" msgstr "Віллоу" msgid "Corackston" msgstr "КоракÑтон" msgid "Sheltemburg" msgstr "Шелтембург" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Ðеможливо найнÑти - у Ð²Ð°Ñ Ð²Ð¶Ðµ Ñ” герой в цьому міÑті." msgid "Cannot recruit - you have too many Heroes." msgstr "Ðеможливо найнÑти - у Ð²Ð°Ñ Ð·Ð°Ð±Ð°Ð³Ð°Ñ‚Ð¾ героїв." msgid "Cannot afford a Hero." msgstr "Ðе можу дозволити Ñобі героÑ." msgid "There is no room in the garrison for this army." msgstr "Ð’ гарнізоні нема міÑÑ†Ñ Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— армії." msgid "Fortifications" msgstr "УкріпленнÑ" msgid "Farm" msgstr "Ферма" msgid "Thatched Hut" msgstr "Солом'Ñна Хата" msgid "Archery Range" msgstr "Стрільбище" msgid "Upg. Archery Range" msgstr "Полігон" msgid "Blacksmith" msgstr "МайÑтернÑ" msgid "Upg. Blacksmith" msgstr "МайÑÑ‚ÐµÑ€Ð½Ñ Ð’ÐµÑ‚ÐµÑ€Ð°Ð½Ñ–Ð²" msgid "Armory" msgstr "ЗброÑрнÑ" msgid "Upg. Armory" msgstr "ЗброÑÑ€Ð½Ñ Ð’ÐµÑ‚ÐµÑ€Ð°Ð½Ñ–Ð²" msgid "Jousting Arena" msgstr "Іподром" msgid "Upg. Jousting Arena" msgstr "Турнірна Ðрена" msgid "Cathedral" msgstr "Катедра" msgid "Upg. Cathedral" msgstr "Собор" msgid "Coliseum" msgstr "Колізей" msgid "Garbage Heap" msgstr "Сміттєва купа" msgid "Hut" msgstr "Хата" msgid "Stick Hut" msgstr "Хижка" msgid "Upg. Stick Hut" msgstr "Халупа" msgid "Den" msgstr "Лігво" msgid "Adobe" msgstr "ГлинÑнка" msgid "Upg. Adobe" msgstr "Мазанка" msgid "Bridge" msgstr "МіÑÑ‚" msgid "Upg. Bridge" msgstr "Великий МіÑÑ‚" msgid "Pyramid" msgstr "Піраміда" msgid "Rainbow" msgstr "Райдуга" msgid "Crystal Garden" msgstr "Кришталевий Ñад" msgid "Treehouse" msgstr "Хатинка на Дереві" msgid "Cottage" msgstr "Хатинка" msgid "Upg. Cottage" msgstr "Котедж" msgid "Stonehenge" msgstr "Кромлех" msgid "Upg. Stonehenge" msgstr "Стоунгендж" msgid "Fenced Meadow" msgstr "Огороджена ГалÑвина" msgid "sorceress|Red Tower" msgstr "Червона Вежа" msgid "Dungeon" msgstr "ПідземеллÑ" msgid "Waterfall" msgstr "ВодоÑпад" msgid "Cave" msgstr "Печера" msgid "Crypt" msgstr "Крипта" msgid "Nest" msgstr "Гніздо" msgid "Maze" msgstr "Лабіринт" msgid "Upg. Maze" msgstr "Лабіринт Королів" msgid "Swamp" msgstr "Болото" msgid "Green Tower" msgstr "Зелена Вежа" msgid "warlock|Red Tower" msgstr "Червона Вежа" msgid "Black Tower" msgstr "Чорна Вежа" msgid "Library" msgstr "Бібліотека" msgid "Orchard" msgstr "Фруктовий Сад" msgid "Habitat" msgstr "ОÑелÑ" msgid "Pen" msgstr "Хлів" msgid "Foundry" msgstr "ЛиварнÑ" msgid "Upg. Foundry" msgstr "Ливарний Завод" msgid "Cliff Nest" msgstr "Скельне Гніздо" msgid "Ivory Tower" msgstr "Вежа Магів" msgid "Upg. Ivory Tower" msgstr "Вежа Ðрхімагів" msgid "Cloud Castle" msgstr "Хмарна ФортецÑ" msgid "Upg. Cloud Castle" msgstr "Хмарний Замок" msgid "Storm" msgstr "Шторм" msgid "Skull Pile" msgstr "Купа Черепів" msgid "Excavation" msgstr "Розкопки" msgid "Graveyard" msgstr "Цвинтар" msgid "Upg. Graveyard" msgstr "Кладовище" msgid "Upg. Pyramid" msgstr "ПроклÑта Піраміда" msgid "Mansion" msgstr "Садиба" msgid "Upg. Mansion" msgstr "Маєток" msgid "Mausoleum" msgstr "Мавзолей" msgid "Upg. Mausoleum" msgstr "ПроклÑтий Мавзолей" msgid "Laboratory" msgstr "ЛабораторіÑ" msgid "Shrine" msgstr "СвÑтинÑ" msgid "Special" msgstr "ОÑобливе" msgid "Horde Building" msgstr "Ð‘ÑƒÐ´Ñ–Ð²Ð»Ñ Ð¾Ñ€Ð´Ð¸" msgid "Dwelling 1" msgstr "Житло 1 рівнÑ" msgid "Dwelling 2" msgstr "Житло 2 рівнÑ" msgid "Upg. Dwelling 2" msgstr "Поліпшене житло 2 рівнÑ" msgid "Dwelling 3" msgstr "Житло 3 рівнÑ" msgid "Upg. Dwelling 3" msgstr "Поліпшене житло 3 рівнÑ" msgid "Dwelling 4" msgstr "Житло 4 рівнÑ" msgid "Upg. Dwelling 4" msgstr "Поліпшене житло 4 рівнÑ" msgid "Dwelling 5" msgstr "Житло 5 рівнÑ" msgid "Upg. Dwelling 5" msgstr "Поліпшене житло 5 рівнÑ" msgid "Dwelling 6" msgstr "Житло 6 рівнÑ" msgid "Upg. Dwelling 6" msgstr "Поліпшене житло 6 рівнÑ" msgid "2x Upg. Dwelling 6" msgstr "Подвійно поліпшене житло 6 рівнÑ" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Ð£ÐºÑ€Ñ–Ð¿Ð»ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÑƒÑŽÑ‚ÑŒ міцніÑть Ñтін, збільшуючи кількіÑть ходів, необхідних " "Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб Ñ—Ñ… зруйнувати." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Ферма збільшує виробництво СелÑн на %{count} на тиждень." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Колізей надає надихаючі видовища війÑькам, що оборонÑютьÑÑ, піднімаючи їхній " "бойовий дух вдвічі під Ñ‡Ð°Ñ Ð±Ð¾ÑŽ." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Сміттєва купа збільшує виробництво Гоблінів на %{count} на тиждень." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Райдуга підвищує удачу захиÑників замоку вдвічі." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "Кришталевий Ñад збільшує виробництво Фей на %{count} в тиждень." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "ÐŸÑ–Ð´Ð·ÐµÐ¼ÐµÐ»Ð»Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÑƒÑ” прибуток міÑта на %{count} в день." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "ВодоÑпад підвищує приріÑÑ‚ Кентаврів на %{count} за тиждень." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Бібліотека підвищує кількіÑть заклинань в Гільдії на одне Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ Ñ€Ñ–Ð²Ð½Ñ " "гільдії." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "" "Фруктовий Ñад збільшує виробництво ÐапівроÑликів на %{count} в тиждень." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "Ð‘ÑƒÑ€Ñ Ð´Ð¾Ð´Ð°Ñ” +2 до Ñили магії заклинателÑ, що оборонÑєтьÑÑ." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Купа черепів збільшує виробництво Скелетів на %{count} в тиждень." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "ОÑоблива Ð±ÑƒÐ´Ñ–Ð²Ð»Ñ Ð½Ð°Ð´Ð°Ñ” певні бонуÑи Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ типу замку." msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Ð‘ÑƒÐ´Ñ–Ð²Ð»Ñ ÐžÑ€Ð´Ð¸ збільшує швидкіÑть прироÑту Ñ–Ñтот 1-го Ñ€Ñ–Ð²Ð½Ñ Ð½Ð° 8 в тиждень." msgid "Thieves' Guild" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð—Ð»Ð¾Ð´Ñ–Ñ—Ð²" msgid "Tavern" msgstr "Таверна" msgid "Shipyard" msgstr "Верф" msgid "Well" msgstr "КолодÑзь" msgid "Statue" msgstr "СтатуÑ" msgid "Marketplace" msgstr "Ринок" msgid "Moat" msgstr "Рів" msgid "Castle" msgstr "Замок" msgid "Tent" msgstr "Ðамет" msgid "Captain's Quarters" msgstr "ÐŸÐ¾Ð¼ÐµÑˆÐºÐ°Ð½Ð½Ñ ÐšÐ°Ð¿Ñ–Ñ‚Ð°Ð½Ð°" msgid "Mage Guild, Level 1" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ ÐœÐ°Ð³Ñ–Ð², 1 рівень" msgid "Mage Guild, Level 2" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ ÐœÐ°Ð³Ñ–Ð², 2 рівень" msgid "Mage Guild, Level 3" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ ÐœÐ°Ð³Ñ–Ð², 3 рівень" msgid "Mage Guild, Level 4" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ ÐœÐ°Ð³Ñ–Ð², 4 рівень" msgid "Mage Guild, Level 5" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ ÐœÐ°Ð³Ñ–Ð², 5 рівень" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "СвÑÑ‚Ð¸Ð½Ñ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÑƒÑ” Ð²Ð¼Ñ–Ð½Ð½Ñ Ðекромантії вÑÑ–Ñ… некромантів на 10 відÑотків." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð·Ð»Ð¾Ð´Ñ–Ñ—Ð² надає інформацію щодо ворожих гравців. Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð·Ð»Ð¾Ð´Ñ–Ñ—Ð² також " "надає розвідницьку інформацію про ворожі міÑта. Додаткові Гільдії надають " "більше інформації." msgid "The Tavern increases morale for troops defending the castle." msgstr "Таверна збільшує мораль захиÑників замка." msgid "The Shipyard allows ships to be built." msgstr "Верф дозволÑÑ” будувати кораблі." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "КолодÑзь підвищує приріÑÑ‚ в уÑÑ–Ñ… житлах на %{count} Ñ–Ñтот на тиждень." msgid "The Statue increases the town's income by %{count} gold per day." msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ñ–Ð´Ð²Ð¸Ñ‰ÑƒÑ” прибуток вашого міÑта на %{count} золота в день." msgid "The Left Turret provides extra firepower during castle combat." msgstr "Ліва Вежа завдає додаткову шкоду ворогові під Ñ‡Ð°Ñ Ð¾Ð±Ð»Ð¾Ð³Ð¸." msgid "The Right Turret provides extra firepower during castle combat." msgstr "Права Вежа завдає додаткову шкоду ворогу під Ñ‡Ð°Ñ Ð¾Ð±Ð»Ð¾Ð³Ð¸." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Ринок можна викориÑтовувати щоб обмінÑти один реÑÑƒÑ€Ñ Ð½Ð° інший. Чим більше " "ринків ви контролюєте, тим краще ÐºÑƒÑ€Ñ Ð¾Ð±Ð¼Ñ–Ð½Ñƒ." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Рів Ñповільнює ворожі загони. Кожний загін, що зайде у рів, завершить хід у " "ньому Ñ– Ñтане вразливішим до нападу." msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Замок покращує захиÑÑ‚ міÑта та підвищує прибуток на %{count} золота в день." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Ðамет надає робітників, що будуватимуть замок, Ñкщо надати матеріали та " "золото." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "КапітанÑький штаб надає капітана, що допомагає захищати замок за відÑутноÑті " "героÑ." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ ÐœÐ°Ð³Ñ–Ð² дозволÑÑ” героÑм вивчати чари та відновлювати ману." msgid "Recruit %{name}" msgstr "ÐайнÑти %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "МіÑÑць: %{month}, Тиждень: %{week}, День: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Ви маєте придбати книгу чарів, щоб викориÑтовувати гільдію магів, але наразі " "у Ð’Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” вільного міÑÑ†Ñ Ð¿Ñ–Ð´ книгу. Спробуйте передати один із артефактів " "іншому герою." msgid "Click to show next town." msgstr "ÐатиÑніть щоб побачити наÑтупне міÑто." msgid "Show next town" msgstr "Показати наÑтупне міÑто" msgid "Click to show previous town." msgstr "ÐатиÑніть щоб побачити попереднє міÑто." msgid "Show previous town" msgstr "Показати попереднє міÑто" msgid "This town may not be upgraded to a castle." msgstr "Це МіÑто не можна покращити до Замку." msgid "Town" msgstr "МіÑто" msgid "Exit Castle" msgstr "Вийти з замку" msgid "Exit Town" msgstr "Вийти з міÑта" msgid "Show Income" msgstr "Показати надходженнÑ" msgid "View Hero" msgstr "ОглÑнути героÑ" msgid "The above spells are available here." msgstr "Вищевказані Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупні тут." msgid "The spells the hero can learn have been added to their book." msgstr "ДоÑтупні Ð´Ð»Ñ Ð²Ð¸Ð²Ñ‡ÐµÐ½Ð½Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ð½Ð¾ в Книгу Заклинань." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "Щедрі чайові Ð´Ð»Ñ Ð±Ð°Ñ€Ð¼ÐµÐ½Ð° породжують такі чутки:" msgid "Recruit Hero" msgstr "ÐайнÑти героÑ" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} - %{race} Ñ€Ñ–Ð²Ð½Ñ %{value} " msgid "with %{count} artifacts." msgstr "з %{count} артефактами." msgid "with 1 artifact." msgstr "з одним артефактом." msgid "without artifacts." msgstr "без артефактів." msgid "Recruit %{name} the %{race}" msgstr "Завербувати %{name}, %{race}" msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Бойовий порÑдок \"РозоÑередженнÑ\" розподілÑÑ” юніти замку зверху донизу Ð¿Ð¾Ð»Ñ " "бою, при цьому між кожним юнітом має бути принаймні одне вільне міÑце." msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "Бойовий порÑдок \"ЗгуртованіÑть\" об'єднує підрозділи замку в центрі Ð¿Ð¾Ð»Ñ " "бою на Ñтороні замку." msgid "Spread Formation" msgstr "ПорÑдок РозоÑередженіÑть" msgid "Grouped Formation" msgstr "ПорÑдок ЗгуртованіÑть" msgid "Click to show the next town." msgstr "Тицьніть щоб показати наÑтупне міÑто." msgid "Click to show the previous town." msgstr "Тицьніть щоб показати попереднє міÑто." msgid "Set garrison combat formation to 'Spread'" msgstr "Ð’Ñтановити бойовий порÑдок \"РозоÑередженнÑ\"" msgid "Set garrison combat formation to 'Grouped'" msgstr "Ð’Ñтановити бойовий порÑдок \"ЗгуртованіÑть\"" msgid "Exit Castle Options" msgstr "Вийти з налаштувань замку" msgid "Castle Options" msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¼ÐºÑƒ" msgid "Not enough resources to recruit creatures." msgstr "ÐедоÑтатньо реÑурÑів Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ñƒ Ñ–Ñтот." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Ðаразі ви не можете набирати рекрутів, ваші лави переповнені." msgid "No creatures available for purchase." msgstr "Ðема Ñ–Ñтот доÑтупних Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ñƒ." msgid "Recruit Creatures" msgstr "ÐайнÑти Ñтворінь" msgid "Hire all creatures in the town." msgstr "ÐайнÑти уÑÑ–Ñ… Ñ–Ñтот в міÑті." msgid "Max" msgstr "МакÑ" msgid "Available" msgstr "ДоÑтупно" msgid "Town Population Information and Statistics" msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ñ‚Ð° ÑтатиÑтика по наÑеленню міÑÑ‚" msgid "Damage" msgstr "Шкода" msgid "HP" msgstr "Здоров'Ñ" msgid "Growth" msgstr "ПриріÑÑ‚" msgid "week" msgstr "тиждень" msgid "View World" msgstr "ОглÑнути Ñвіт" msgid "View the entire world." msgstr "ОглÑнути увеÑÑŒ Ñвіт." msgid "Puzzle" msgstr "Пазл" msgid "View the obelisk puzzle." msgstr "ПереглÑнути пазл обеліÑка." msgid "Scenario Information" msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ð¾ Ñценарію" msgid "View information on the scenario you are currently playing." msgstr "ПереглÑнути інформацію про поточний Ñценарій." msgid "Dig for the Ultimate Artifact." msgstr "Копайте Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ Легендарного артефакту." msgid "Digging" msgstr "Розкопки" msgid "Arena" msgstr "Ðрена" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Ви виходите на арену Ñ– ÑтикаєтеÑÑŒ зі зграєю лютих левів. Ви легко " "перемагаєте Ñ—Ñ… під дикі вигуки натовпу. Вражений вашою майÑтерніÑтю, Ñтарий " "тренер гладіаторів погоджуєтьÑÑ Ð½Ð°Ð²Ñ‡Ð¸Ñ‚Ð¸ Ð²Ð°Ñ Ð½Ð°Ð²Ð¸Ñ‡ÐºÐ°Ð¼ на ваш вибір." msgid "Attack Skill" msgstr "Ðтака" msgid "Defense Skill" msgstr "ЗахиÑÑ‚" msgid "Shots" msgstr "ПоÑтріли" msgid "Shots Left" msgstr "ПоÑтрілів лишилоÑÑŒ" msgid "Hit Points" msgstr "Очки здоров'Ñ" msgid "Hit Points Left" msgstr "Здоров'Ñ Ð»Ð¸ÑˆÐ¸Ð»Ð¾ÑÑŒ" msgid "You can't afford to upgrade your troops!" msgstr "Ви не можете дозволити Ñобі модернізувати Ñвої війÑька!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Ваші війÑька можна покращити, проте коштуватиме дорого. Бажаєте Ñ—Ñ… покращити?" msgid "Are you sure you want to dismiss this army?" msgstr "Ви впевнені, що хочете розпуÑтити цю армію?" msgid "Upgrade" msgstr "Поліпшити" msgid "Upgrade your troops." msgstr "Модернізувати ваші війÑька." msgid "Dismiss" msgstr "Звільнити" msgid "Dismiss this army." msgstr "Звільнити цю армію." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Група %{monster}, що прагне більшої Ñлави, бажає приєднатиÑÑ Ð´Ð¾ ваÑ.\n" "Ви згодні?" msgid "Followers" msgstr "ПоÑлідовники" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} піддалиÑÑ Ð½Ð° вашу дипломатичну мову Ñ– пропонує приєднатиÑÑ Ð´Ð¾ " "вашої армії за %{gold} золота.\n" "Приймаєте пропозицію?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "ІÑтоти піддалиÑÑ Ð²Ð°ÑˆÑ–Ð¹ дипломатії \n" "та пропонують вам:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} із %{total} %{monster} приєднаютьÑÑ Ð´Ð¾ вашої армії, а решта " "залишить Ð²Ð°Ñ Ñƒ Ñпокої, за %{gold} золота.\n" "Ви згодні?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Ð’ÑÑ– %{offer} із %{monster} приєднаютьÑÑ Ð´Ð¾ вашої армії за %{gold} золота.\n" "Ви згодні?" msgid "(Rate: %{percent})" msgstr "(Ставка: %{percent})" msgid "off" msgstr "вимк" msgid "Music" msgstr "Музика" msgid "Effects" msgstr "Ефекти" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI розширений" msgid "External" msgstr "Колонки" msgid "Music Type" msgstr "Тип музики" msgid "3D Audio" msgstr "3Д звук" msgid "Toggle ambient music level." msgstr "ГучніÑть музики." msgid "Toggle foreground sounds level." msgstr "ГучніÑть звуків." msgid "Change the type of music." msgstr "Змінити тип музики." msgid "Toggle the 3D effect of foreground sounds." msgstr "Перемикач 3Д ефектів звуків." msgid "Build a new ship:" msgstr "Побудувати новий корабель:" msgid "Resource cost:" msgstr "ВартіÑть реÑурÑу:" msgid "Total: " msgstr "Загалом: " msgid "Need: " msgstr "Потрібно: " msgid "New Game" msgstr "Ðова Гра" msgid "Start a single or multi-player game." msgstr "Почати одно або багато кориÑтувацьку гру." msgid "Load Game" msgstr "Завантажити Гру" msgid "Load a previously saved game." msgstr "Завантажити раніше збережену гру." msgid "Save Game" msgstr "Зберегти Гру" msgid "Save the current game." msgstr "Збережіть поточну гру." msgid "Quit" msgstr "Вихід" msgid "Quit out of Heroes of Might and Magic II." msgstr "Залишити Heroes of Might and Magic II." msgid "Language" msgstr "Мова" msgid "Graphics" msgstr "Графіка" msgid "Black & White" msgstr "Чорно-білий" msgid "Mouse Cursor" msgstr "Вказівник миші" msgid "Color" msgstr "Кольоровий" msgid "Text Support" msgstr "ТекÑтовий опиÑ" msgid "Change the language of the game." msgstr "Змінити мову гри." msgid "Select Game Language" msgstr "Обрати мову гри" msgid "Change the graphics settings of the game." msgstr "Змінити графічні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€Ð¸." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "Перемикає кольоровий/монохромний курÑор. Має лише еÑтетичний ефект." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Перемикач текÑтового опиÑу, що виводить додаткову інформацію про вікна та " "події в грі." msgid "" "Map\n" "Difficulty" msgstr "" "СкладніÑть\n" "Мапи" msgid "" "Game\n" "Difficulty" msgstr "" "СкладніÑть\n" "Гри" msgid "Rating" msgstr "Рейтинг" msgid "Map Size" msgstr "Розмір Мапи" msgid "Opponents" msgstr "Опоненти" msgid "Class" msgstr "КлаÑ" msgid "" "Victory\n" "Conditions" msgstr "Умови перемоги" msgid "" "Loss\n" "Conditions" msgstr "Умови поразки" msgid "First select recipients!" msgstr "Спершу виберіть отримувачів!" msgid "You cannot select %{resource}!" msgstr "Ðеможливо вибрати %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Задати кількіÑть %{monster}" msgid "Select Recipients" msgstr "Вибрати отримувачів" msgid "Your Funds" msgstr "Ваші Ñтатки" msgid "Planned Gift" msgstr "Запланований подарунок" msgid "Gift from %{name}" msgstr "Подарунок від %{name}" msgid "Resolution" msgstr "Роздільна здатніÑть" msgid "Fullscreen" msgstr "Повноекранний" msgid "window|Mode" msgstr "Режим" msgid "Windowed" msgstr "Віконний" msgid "V-Sync" msgstr "Вертикальна ÑинхронізаціÑ" msgid "FPS" msgstr "Кадри за Ñекунду" msgid "System Info" msgstr "СиÑтемні Параметри" msgid "Change the resolution of the game." msgstr "Змінити розділову здатніÑть гри." msgid "Select Game Resolution" msgstr "Вибрати роздільну здатніÑть" msgid "Toggle between fullscreen and windowed modes." msgstr "Змінює режим повноекранний чи віконний." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "Верт. Ñинхр. може уÑунути Ð¼ÐµÑ€ÐµÑ…Ñ‚Ñ–Ð½Ð½Ñ Ð½Ð° деÑких моніторах." msgid "Show extra information such as FPS and current time." msgstr "Відобразити додаткову інформацію Ñк FPS та поточний чаÑ." msgid "Hotkey: " msgstr "ГарÑча клавіша: " msgid "Category: " msgstr "КатегоріÑ: " msgid "Event: " msgstr "ПодіÑ: " msgid "Hot Keys:" msgstr "ГарÑчі клавіші:" msgid "Hide" msgstr "Сховати" msgid "Show" msgstr "Показати" msgid "Interface" msgstr "ІнтерфейÑ" msgid "Interface Type" msgstr "Тип ІнтерфейÑу" msgid "Toggle the type of interface you want to use." msgstr "Перемкнути тип інтерфейÑу, Ñкий хочете викориÑтовувати." msgid "Toggle interface visibility." msgstr "Перемкнути видиміÑть інтерфейÑу." msgid "Scroll Speed" msgstr "ШвидкіÑть прокрутки" msgid "Sets the speed at which you scroll the window." msgstr "Ð’Ñтановлює швидкіÑть Ð¿Ñ€Ð¾ÐºÑ€ÑƒÑ‡ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–ÐºÐ½Ð°." msgid "Select Game Language:" msgstr "Обрати мову гри:" #, fuzzy msgid "Select Language:" msgstr "Обрати мову гри:" msgid "Click to choose the selected language." msgstr "Тицніть, щоб вибрати мову." msgid "%{name} has gained a level." msgstr "%{name} здобув новий рівень." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Ви вивчили %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} доÑÑг нового рівнÑ.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Ви можете вивчити або:\n" "%{skill1}\n" "або\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "н/д" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Будь лаÑка, оглÑньте наші чудові товари. Якщо ви хочете запропонувати обмін, " "тицніть на товари, Ñкі бажаєте обмінÑти та на що." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Ви отримали доÑить вигідну пропозицію. Я не ÑподіваюÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ прибуток від " "цієї угоди. Можливо, Ð²Ð°Ñ Ð·Ð°Ñ†Ñ–ÐºÐ°Ð²Ð»Ñть інші мої товари?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Пропоную вам %{count} за 1 %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "Можу запропонувати 1 %{resto} за %{count} одиниць %{resfrom}." msgid "Min" msgstr "Мін" msgid "Qty to trade" msgstr "КількіÑть Ð´Ð»Ñ Ð¾Ð±Ð¼Ñ–Ð½Ñƒ" msgid "Trading Post" msgstr "Торгівельний пункт" msgid "Your Resources" msgstr "Ваші реÑурÑи" msgid "Available Trades" msgstr "ДоÑтупні реÑурÑи" msgid "guarded by %{count} %{monster}" msgstr "охоронÑєтьÑÑ %{count} %{monster}" msgid "guarded by " msgstr "охоронÑєтьÑÑ " msgid "(available: %{count})" msgstr "(доÑтупно: %{count})" msgid "(empty)" msgstr "(порожньо)" msgid "already learned" msgstr "вже вивчено" msgid "treeOfKnowledge|free" msgstr "вільно" msgid "already claimed" msgstr "вже проголошено" msgid "not claimed" msgstr "не проголошено" msgid "already knows this skill" msgstr "вже опанували це вміннÑ" msgid "already has max skills" msgstr "вже має найвищі показники" msgid "(already visited)" msgstr "(вже відвідано)" msgid "(not visited)" msgstr "(не відвідано)" msgid "%{color} Barrier" msgstr "%{color} бар'єр" msgid "(tent visited)" msgstr "(намет відвідано)" msgid "%{color} Tent" msgstr "%{color} намет" msgid "Road" msgstr "Дорога" msgid "(digging ok)" msgstr "(можна копати)" msgid "(no digging)" msgstr "(неможливо копати)" msgid "penalty: %{cost}" msgstr "штраф: %{cost}" msgid "Defenders:" msgstr "ЗахиÑники:" msgid "Unknown" msgstr "Ðевідомо" msgid "heroQuickInfo|(Level %{level})" msgstr "(Рівень %{level})" msgid "Attack:" msgstr "Ðтака:" msgid "Defense:" msgstr "ЗахиÑÑ‚:" msgid "Spell Power:" msgstr "Сила Чарів:" msgid "Knowledge:" msgstr "ЗнаннÑ:" msgid "Spell Points:" msgstr "Одиниці Мани:" msgid "Move Points:" msgstr "Очки Руху:" msgid "Uncharted Territory" msgstr "Ðезвідана територіÑ" msgid "Cost per troop:" msgstr "ВартіÑть однієї Ñ–Ñтоти:" msgid "Available: %{count}" msgstr "ДоÑтупно: %{count}" msgid "Number to buy:" msgstr "Скільки придбати:" msgid "Recruit selected monsters." msgstr "ÐайнÑти обраних монÑтрів." msgid "Select maximum monsters to be recruited." msgstr "Обрати макÑимально доÑтупну Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ñƒ кількіÑть монÑтрів." msgid "Select only 1 monster to be recruited." msgstr "Обрати лише одного монÑтра Ð´Ð»Ñ Ð½Ð°Ð¹Ð¼Ñƒ." #, fuzzy msgid "Select this game resolution." msgstr "Вибрати роздільну здатніÑть" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Обрати розділову здатніÑть:" msgid "Click to apply the selected resolution." msgstr "ÐатиÑніть, щоб вÑтановити обрану розділову здатніÑть." msgid "Click to apply the entered text." msgstr "ÐатиÑніть, щоб підтвердити введений текÑÑ‚." msgid "Click to open the Virtual Keyboard dialog." msgstr "ÐатиÑніть, щоб відкрити вікно Віртуальної Клавіатури." msgid "Open Virtual Keyboard" msgstr "Відкрити Віртуальну Клавіатуру" msgid "How many creatures do you wish to move?" msgstr "Скільки Ñ–Ñтот бажаєте переміÑтити?" msgid "Select how many units to separate into:" msgstr "Виберіть, Ñкільки монÑтрів відділити:" msgid "Map: " msgstr "Мапа: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "МіÑÑць: " msgid ", Week: " msgstr ", Тиждень: " msgid ", Day: " msgstr ", День: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "РозташуваннÑ: " msgid "Are you sure you want to delete file:" msgstr "Ви впевнені, що хочете видалити файл:" msgid "Warning" msgstr "ПопередженнÑ" msgid "Click to save the current game." msgstr "ÐатиÑніть, щоб зберегти поточну гру." msgid "Click to load a previously saved game." msgstr "ÐатиÑніть, щоб завантажити збережену гру." msgid "File to Save:" msgstr "Зберегти файли:" msgid "File to Load:" msgstr "Завантажити файли:" msgid "Terrain object" msgstr "Об'єкт міÑцевоÑті" msgid "Accept the choice made." msgstr "Підтвердити ваш вибір." msgid "Select Skill:" msgstr "Оберіть навичку:" msgid "Select Spell:" msgstr "Оберіть заклÑттÑ:" msgid "Select Artifact:" msgstr "Оберіть артефакт:" msgid "Select Monster:" msgstr "Оберіть монÑтра:" msgid "Select Hero:" msgstr "Оберіть героÑ:" msgid "race|Random" msgstr "Випадково" msgid "Click to start placing the selected hero." msgstr "Тицьніть Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ героÑ." msgid "%{color} %{race}" msgstr "%{color} %{race}" msgid "You will place" msgstr "РозміÑтити" msgid "Click to select this class." msgstr "Тицьніть щоб обрати цей клаÑ." msgid "Click to select this color." msgstr "Тицьніть щоб обрати цей колір." msgid "Select Treasure:" msgstr "Оберіть Ñкарб:" msgid "Select Ocean Object:" msgstr "Оберіть об'єкти океану:" msgid "Castle/town placing" msgstr "Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð¼ÐºÑƒ/міÑта" msgid "doubleLinedRace|Neutral" msgstr "Ðейтральний" msgid "Click to start placing the selected castle/town." msgstr "Тицьніть Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ замку/міÑта." msgid "Click to select town placing." msgstr "Тицьніть щоб вибрати Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ñ–Ñта." msgid "Click to select castle placing." msgstr "Тицьніть щоб вибрати Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð¼ÐºÑƒ." msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{race} %{townOrCastle}" msgid "race|Neutral" msgstr "Ðейтральний" msgid "Select Dwelling:" msgstr "Оберіть помешканнÑ:" msgid "Select Landscape Object:" msgstr "Вибрати об'єкт міÑцевоÑті:" msgid "Mine placing" msgstr "Ð Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑˆÐ°Ñ…Ñ‚Ð¸" msgid "" "Resource\n" "type:" msgstr "Тип реÑурÑу:" msgid "%{mineName} appearance:" msgstr "%{mineName} відображеннÑ:" msgid "Click to select %{object} as the resource generator to be placed." msgstr "Тицьніть, щоб вибрати Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ %{object} Ñк генератор реÑурÑів." msgid "Select Mountain Object:" msgstr "Вибрати об'єкт гора:" msgid "Select Rock Object:" msgstr "Виберіть об'єкт ÑкелÑ:" msgid "Select Tree Object:" msgstr "Виберіть об'єкт дерево:" msgid "Select Power Up Object:" msgstr "Виберіть об'єкт підÑилювач:" msgid "Select Adventure Object:" msgstr "Виберіть пригодницький об'єкт:" msgid "Players Icon" msgstr "КількіÑть гравців" msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Визначає, Ñк багато гравців приÑутні у Ñценарії. Ð’ÑÑ– Ñлоти, не зайнÑті " "гравцÑми-людьми, будуть зайнÑті комп'ютерними гравцÑми." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Визначає розмір мапи:\n" "маленькі (36 x 36), Ñередні\n" "(72 x 72), великі (108 x 108),\n" "надвеликі (144 x 144)." msgid "Size Icon" msgstr "Іконка розміру" msgid "Map Type" msgstr "Тип мапи" msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Вказує, чи Ñтворена мапа Ð´Ð»Ñ Ð²ÐµÑ€ÑÑ–Ñ— гри \"Війни за Ñпадщину\", \"Ціна " "вірноÑті\" або \"ВоÑкреÑіннÑ\"." msgid "Map Type:\n" msgstr "Тип мапи:\n" msgid "The Succession Wars" msgstr "Війни за Спадщину" msgid "The Price of Loyalty" msgstr "Ціна ВірноÑті" msgid "Resurrection" msgstr "ВоÑкреÑіннÑ" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Мова" msgid "Lose all your heroes and towns." msgstr "Втратити вÑÑ–Ñ… ваших героїв та міÑта." msgid "Lose a specific town." msgstr "Втратити певне міÑто." msgid "Lose a specific hero." msgstr "Втратити певного героÑ." msgid "Run out of time. Fail to win by a certain point." msgstr "Ðе вÑтигнути вчаÑно." msgid "Loss Condition" msgstr "Умови програшу" msgid "Defeat all enemy heroes and towns." msgstr "Здолати вÑÑ–Ñ… ворожих героїв та захопити вÑÑ– Ñ—Ñ… міÑта." msgid "Capture a specific town." msgstr "Захопити певне міÑто." msgid "Defeat a specific hero." msgstr "Перемогти певного героÑ." msgid "Find a specific artifact." msgstr "Знайти певний артефакт." msgid "Your side must defeat the opposing side." msgstr "Ваш Ñоюз муÑить перемогти ворожий." msgid "Accumulate a large amount of gold." msgstr "Ðакопичити велику кількіÑть золота." msgid "Victory Condition" msgstr "Умови перемоги" msgid "Map difficulty:" msgstr "СкладніÑть мапи:" msgid "N" msgstr "Ð" msgid "No maps exist at that size." msgstr "Ðемає мап такого розміру." msgid "Small Maps" msgstr "Маленькі Мапи" msgid "View only maps of size small (36 x 36)." msgstr "Показати лише мапи малого розміру (36 x 36)." msgid "Medium Maps" msgstr "Середні мапи" msgid "View only maps of size medium (72 x 72)." msgstr "Показати лише мапи Ñереднього розміру (72 x 72)." msgid "Large Maps" msgstr "Великі мапи" msgid "View only maps of size large (108 x 108)." msgstr "Показати лише мапи великого розміру (108 x 108)." msgid "Extra Large Maps" msgstr "Ðадвеликі Мапи" msgid "View only maps of size extra large (144 x 144)." msgstr "Показати лише мапи надвеликого розміру (144 x 144)." msgid "All Maps" msgstr "УÑÑ– мапи" msgid "View all maps, regardless of size." msgstr "Показати вÑÑ– мапи, незалежно від розміру." msgid "Selected Name" msgstr "Ðазва" msgid "The name of the currently selected map." msgstr "Ðазва обраної мапи." msgid "Selected Map Difficulty" msgstr "СкладніÑть обраної мапи" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "СкладніÑть обраної вами мапи. СкладніÑть визначаєтьÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼ Ñценарію. " "ВиÑока ÑкладніÑть мапи може передбачати Ñильніших ворогів, меншу кількіÑть " "реÑурÑів або додаткові умови, що можуть зробити гру Ñкладнішою Ð´Ð»Ñ Ð³Ñ€Ð°Ð²Ñ†Ñ-" "людини." msgid "Selected Description" msgstr "ОпиÑ" msgid "The description of the currently selected map." msgstr "ÐžÐ¿Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð½Ð¾Ñ— вами мапи." msgid "Jump" msgstr "Стрибками" msgid "Hero Speed" msgstr "ШвидкіÑть героїв" msgid "Don't Show" msgstr "Ðе показувати" msgid "Enemy Speed" msgstr "ШвидкіÑть ворогів" msgid "Auto Resolve" msgstr "Ðвтобитва" msgid "Auto, No Spells" msgstr "Ðвтобитва, без заклÑть" msgid "Battles" msgstr "Битви" #, fuzzy msgid "combatMode|Manual" msgstr "Вручну" msgid "Change the speed at which your heroes move on the main screen." msgstr "" "Змінює швидкіÑть, з Ñкою ваші герої переÑуватимутьÑÑ Ð¿Ð¾ Ñтратегічній мапі." msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Ð’Ñтановлює швидкіÑть, з Ñкою рухаютьÑÑ Ð²Ð¾Ñ€Ð¾Ð¶Ñ– герої. Ви також можете " "вимкнути переглÑд вÑÑ–Ñ… ворожих переміщень." msgid "Change the interface settings of the game." msgstr "Змінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñу гри." msgid "Interface Settings" msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñу" msgid "Toggle instant battle mode." msgstr "Перемикає режим миттєвої битви." msgid "Att." msgstr "Ðтк." msgid "Def." msgstr "Зах." msgid "Power" msgstr "Сила" msgid "Knowl" msgstr "ЗнаннÑ" msgid "1st" msgstr "1-ий" msgid "2nd" msgstr "2-ий" msgid "3rd" msgstr "3-ій" msgid "4th" msgstr "4-ий" msgid "5th" msgstr "5-ий" msgid "6th" msgstr "6-ий" msgid "Oracle: Player Rankings" msgstr "Оракул: рейтинги гравців" msgid "Thieves' Guild: Player Rankings" msgstr "Ð“Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð—Ð»Ð¾Ð´Ñ–Ñ—Ð²: рейтинги гравців" msgid "Number of Towns:" msgstr "КількіÑть міÑÑ‚:" msgid "Number of Castles:" msgstr "КількіÑть замків:" msgid "Number of Heroes:" msgstr "КількіÑть героїв:" msgid "Gold in Treasury:" msgstr "Золота у Ñкарбниці:" msgid "Wood & Ore:" msgstr "Дерево та Руда:" msgid "Gems, Cr, Slf & Mer:" msgstr "Цінні РеÑурÑи:" msgid "Obelisks Found:" msgstr "Знайдено обеліÑків:" msgid "Artifacts:" msgstr "Ðртефакти:" msgid "Total Army Strength:" msgstr "Загальна Ñила війÑька:" msgid "Income:" msgstr "Прибутки:" msgid "Best Hero:" msgstr "ÐайÑильніший герой:" msgid "Best Hero Stats:" msgstr "Хар-ки найÑильнішого героÑ:" msgid "Personality:" msgstr "ОÑобиÑтіÑть:" msgid "Best Monster:" msgstr "ÐайÑильніший монÑтр:" msgid "Random Castle Name" msgstr "Випадкова назва замку" msgid "Random Town Name" msgstr "Випадкова назва міÑта" msgid "Allow Castle build" msgstr "Дозволити будівництво замку" msgid "Default Buildings" msgstr "ÐаÑвні Ñпоруди" msgid "Default Army" msgstr "ÐаÑвна арміÑ" msgid "Castle Army" msgstr "Гарнізон замку" msgid "Town Army" msgstr "Гарнізон міÑта" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" "Тицьніть, щоб змінити назву замку. Тицьніть правою кнопкою миші, щоб " "відновити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° налаштуваннÑм." msgid "Enter Castle name" msgstr "ВвеÑти назву замку" msgid "Allow to build a castle in this town." msgstr "Дозволити будувати замок у цьому міÑті." msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" "Увімкнути викориÑÑ‚Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ñ–Ð²ÐµÐ»ÑŒ за налаштуваннÑм. КориÑтувацькі будівлі буде " "Ñкинуто!" msgid "Toggle building construction restriction mode." msgstr "Режим Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ñ–Ð²Ð½Ð¸Ñ†Ñ‚Ð²Ð° Ñпоруд." msgid "Restrict Building Construction" msgstr "Обмежити будівництво Ñпоруд." msgid "Use default defenders army." msgstr "ВикориÑтовувати армію захиÑників за налаштуваннÑм." msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" "Ð’Ñтановити влаÑну замкову армію. Тицьніть правою кнопкою миші, щоб Ñкинути " "кількіÑть." msgid "Message Text:" msgstr "ТекÑÑ‚ повідомленнÑ:" msgid "Reward:" msgstr "Ðагорода:" msgid "Player colors allowed to get event:" msgstr "Кольори гравців, Ñким дозволено отримати подію:" msgid "Computer colors allowed to get event:" msgstr "Кольори гравців-комп'ютерів, Ñким дозволено отримати подію:" msgid "First day of occurrence:" msgstr "Перший день поÑви:" msgid "Repeat period (days):" msgstr "Період Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð½Ñ (дні):" msgid "Allow %{color} human player to get event" msgstr "Дозволити %{color} гравцю-людині отримати подію" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" "Якщо цей прапорець вÑтановлено, Ñ†Ñ Ð¿Ð¾Ð´Ñ–Ñ Ñпрацює Ð´Ð»Ñ %{color} гравцÑ, Ñкщо " "ним керує людина." msgid "Allow %{color} computer player to get event" msgstr "Дозволити %{color} гравцю-комп'ютеру отримати подію" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" "Якщо цей прапорець вÑтановлено, Ñ†Ñ Ð¿Ð¾Ð´Ñ–Ñ Ñпрацює Ð´Ð»Ñ %{color} гравцÑ, Ñкщо " "ним керує комп'ютер." msgid "Message:" msgstr "ПовідомленнÑ:" msgid "Click to save the Event properties." msgstr "Тицьніть, щоб зберегти влаÑтивоÑті події." msgid "No resources will be given as a reward." msgstr "Жодних реÑурÑів не буде надано в ÑкоÑті винагороди." msgid "Resources" msgstr "РеÑурÑи" msgid "Resources will be given as a reward." msgstr "РеÑурÑи будуть надані в ÑкоÑті нагороди." msgid "Click here to change the event message." msgstr "Тицьніть Ñюди, щоб змінити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ñ—." msgid "Event Message Text" msgstr "ТекÑÑ‚ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ñ—" msgid "Day: %{day}" msgstr "День: %{day}" msgid "Daily Events" msgstr "Щоденні події" msgid "Click to save the events." msgstr "Тицьніть, щоб зберегти події." msgid "Add Event" msgstr "Додати подію" msgid "Add an additional event." msgstr "Додати додаткову подію." msgid "Edit Event" msgstr "Редагувати подію" msgid "Edit an existing event." msgstr "Редагувати Ñ–Ñнуючу подію." msgid "Delete Event" msgstr "Видалити подію" msgid "Delete an existing event." msgstr "Видалити Ñ–Ñнуючу подію." #, fuzzy msgid "Effects:" msgstr "Ефекти" #, fuzzy msgid "Conditions:" msgstr "Умови поразки" msgid "Cancel event after first visit" msgstr "СкаÑувати подію піÑÐ»Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ відвідуваннÑ" #, fuzzy msgid "Computer colors allowed to get the event:" msgstr "Кольори гравців-комп'ютерів, Ñким дозволено отримати подію:" msgid "Set Experience value" msgstr "Задати кількіÑть доÑвіду" msgid "Artifact" msgstr "Ðртефакт" #, fuzzy msgid "No artifact will be given by the event." msgstr "Жоден артефакт не буде виданий у ÑкоÑті винагороди." msgid "Delete Artifact" msgstr "Видалити артефакт:" #, fuzzy msgid "Delete an artifact from the event." msgstr "Видалити артефакт з винагороди." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Оберіть навичку:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" #, fuzzy msgid "No resources will be part of this event." msgstr "Жодних реÑурÑів не буде надано в ÑкоÑті винагороди." #, fuzzy msgid "These resources will be a part of the event." msgstr "Жодних реÑурÑів не буде надано в ÑкоÑті винагороди." msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" "Якщо цей прапорець вÑтановлено, Ð¿Ð¾Ð´Ñ–Ñ Ñпрацює лише один раз. Якщо прапорець " "не вÑтановлено, Ð¿Ð¾Ð´Ñ–Ñ Ñпрацьовуватиме щоразу, коли один із зазначених " "гравців перетинатиме мітку події." msgid "%{objects} cannot be placed on water." msgstr "%{objects} неможливо розміÑтити на воді." msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "" "Легендарний артефакт може бути розміщений тільки на міÑцевоÑті, де можливе " "копаннÑ." msgid "%{objects} must be placed on water." msgstr "%{objects} муÑÑть бути розміщені на воді." msgid "Objects cannot be placed outside the map." msgstr "Ðеможливо розміÑтити об'єкт поза мапою." msgid "Action objects must be placed on clear tiles." msgstr "Об'єкти дії мають бути розміщені на чиÑтому проÑторі." msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Бажаєте повернутиÑÑ Ñƒ головне меню гри? Ð’ÑÑ– незбережені зміни у поточній " "мапі будуть втрачені." msgid "Editor" msgstr "Редактор" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Ви певні, що хочете завантажити іншу мапу? (Ð’ÑÑ– незбережені зміни у поточній " "мапі будуть втрачені.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Ви певні, що хочете Ñтворити нову мапу? (Ð’ÑÑ– незбережені зміни у поточній " "мапі будуть втрачені.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "ПОЧÐТИ" msgid "Main Menu" msgstr "Головне меню" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Бажаєте повернутиÑÑ Ñƒ головне меню гри? Ð’ÑÑ– незбережені зміни у поточній " "мапі будуть втрачені." msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "Почати" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Ви певні, що хочете завантажити іншу мапу? (Ð’ÑÑ– незбережені зміни у поточній " "мапі будуть втрачені.)" msgid "Create a new map from scratch." msgstr "Створити нову мапу з чиÑтого аркуша." msgid "New Map" msgstr "Ðова мапа" msgid "Load Map" msgstr "Завантажити мапу" msgid "Load an existing map." msgstr "Завантажити Ñ–Ñнуючу мапу." msgid "Save Map" msgstr "Зберегти мапу" msgid "Save the current map." msgstr "Зберегти поточну мапу." msgid "Quit out of the map editor." msgstr "Вийти з редактора мап." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Тицьніть Ð´Ð»Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ð´Ð¾ головного меню." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "ВвеÑти %{object} текÑÑ‚" msgid "Set Random Ultimate Artifact Radius" msgstr "Ð’Ñтановити Ñ€Ð°Ð´Ñ–ÑƒÑ Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¾Ð³Ð¾ Легендарного Ðртефакту" msgid "%{object} has no properties to change." msgstr "%{object} не має влаÑтивоÑтей, Ñкі можна змінити." msgid "This artifact" msgstr "Цей артефакт" msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "Дороги" msgid "Streams" msgstr "Струмки" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "Ðа мапі можна розміÑтити макÑимум %{count} Ð³ÐµÑ€Ð¾Ñ Ð¾Ð´Ð½Ð°ÐºÐ¾Ð²Ð¾Ð³Ð¾ кольору." msgid "Failed to update player information." msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ інформацію по гравцю." msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Ðа мапі можна розміÑтити лише один випадковий Легендарний артефакт." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "Ðа мапі можна розміÑтити макÑимум %{count} обеліÑків." msgid "The map is corrupted." msgstr "Мапа пошкоджена." msgid "Unable to locate data directory to save the map." msgstr "Ðе вдаєтьÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ каталог даних Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¼Ð°Ð¿Ð¸." msgid "Unable to create a directory to save the map." msgstr "Ðе вдаєтьÑÑ Ñтворити теку Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¼Ð°Ð¿Ð¸." msgid "Unable to locate a directory to save the map." msgstr "Ðе вдаєтьÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ каталог Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¼Ð°Ð¿Ð¸." msgid "Are you sure you want to overwrite the existing map?" msgstr "Ви впевнені, що хочете перезапиÑати Ñ–Ñнуючу мапу?" msgid "Map saved to: " msgstr "Мапу збережено в: " msgid "Failed to save the map." msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ мапу." msgid "Used to place %{object}." msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ %{object}." msgid "Select object type" msgstr "Виберіть тип об'єкту" msgid "" "Click here to\n" "select a monster." msgstr "ÐатиÑніть щоб вибрати монÑтра." msgid "" "Click here to\n" "select another monster." msgstr "Тицьніть Ñюди щоб вибрати іншого монÑтра." msgid "" "Cell\n" "Details" msgstr "" "Стільник\n" "Деталі" msgid "Erase" msgstr "Стерти" msgid "Mountains" msgstr "Гори" msgid "Rocks" msgstr "Скелі" msgid "Trees" msgstr "Дерева" msgid "Water Objects" msgstr "Водні об'єкти" msgid "Miscellaneous" msgstr "Різне" msgid "Artifacts" msgstr "Ðртефакти" msgid "Dwellings" msgstr "Житла" msgid "Mines" msgstr "Копальні" msgid "Power-ups" msgstr "ПідÑилювачі" msgid "Treasures" msgstr "Скарби" msgid "Heroes" msgstr "Герої" msgid "Towns" msgstr "МіÑта" msgid "editorErasure|Landscape objects" msgstr "Ландшафтні об'єкти" msgid "editorErasure|Adventure non pickable objects" msgstr "Пригодницькі Ñтатичні об'єкти" msgid "editorErasure|Castles" msgstr "Замки" msgid "editorErasure|Adventure pickable objects" msgstr "Подорожні збиральні об'єкти" msgid "editorErasure|Monsters" msgstr "МонÑтри" msgid "editorErasure|Heroes" msgstr "Герої" msgid "editorErasure|Roads" msgstr "Дороги" msgid "editorErasure|Streams" msgstr "Струмки" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Заповнює територію в\n" "зоні розміром %{size} на %{size}" msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "ВидалÑÑ” об'єкти в\n" "зоні розміром %{size} на %{size}" msgid "Small Brush" msgstr "Маленька киÑть" msgid "Medium Brush" msgstr "Ð¡ÐµÑ€ÐµÐ´Ð½Ñ ÐºÐ¸Ñть" msgid "Large Brush" msgstr "Велика киÑть" msgid "Area Fill" msgstr "Заповнити зону" msgid "Used to click and drag for filling in large areas." msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ… зон." msgid "Clear Area" msgstr "ОчиÑтити зону" msgid "Used to click and drag for clearing large areas." msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð²ÐµÐ»Ð¸ÐºÐ¸Ñ… зон." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Витрачає в %{rate} рази більше очок руху Ð´Ð»Ñ Ð²ÑÑ–Ñ… героїв. (Пошук шлÑху " "зменшує або анулює штраф.)" msgid "Traversable only by boat." msgstr "Прохідний тільки на човні." msgid "No special modifiers." msgstr "ÐÑ–Ñких Ñпеціальних модифікаторів." msgid "Toggle the erasure of %{type} objects." msgstr "Видалити %{type}." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Об'єкти цього типу буде видалено за допомогою інÑтрумента \"Гумка\". " "Тицьніть тут лівою кнопкою миші, щоб знÑти позначку з цього типу. ÐатиÑніть " "Ñ– утримуйте цю кнопку, щоб знÑти Ð²Ð¸Ð´Ñ–Ð»ÐµÐ½Ð½Ñ Ð· уÑÑ–Ñ… інших типів об'єктів." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Об'єкти цього типу ÐЕ буде видалено за допомогою інÑтрумента \"Гумка\". " "Тицьніть тут лівою кнопкою миші, щоб вибрати цей тип. ÐатиÑніть Ñ– утримуйте " "цю кнопку, щоб вибрати вÑÑ– інші типи об'єктів." msgid "Terrain Mode" msgstr "Рельєф" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "" "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð½Ð°Ð½ÐµÑÐµÐ½Ð½Ñ Ð½Ð° мапу підÑтилаючої трави, багна, води тощо." msgid "Landscape Objects Mode" msgstr "Об'єкти ландшафту" msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "" "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð»Ð°Ð½Ð´ÑˆÐ°Ñ„Ñ‚Ð½Ð¸Ñ… об'єктів (гір, Ñкель, дерев " "тощо) на мапі." msgid "Detail Mode" msgstr "ДеталізаціÑ" msgid "Used for special editing of action objects." msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ñпеціального Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±'єктів дії." msgid "Adventure Objects Mode" msgstr "Пригодницькі об'єкти" msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "" "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð½Ð° мапі пригодницьких об'єктів (артефактів, " "житла, шахт, Ñкарбів тощо)." msgid "Kingdom Objects Mode" msgstr "Об'єкти королівÑтва" msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "" "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¾Ð±'єктів королівÑтва (міÑÑ‚, замків Ñ– героїв) " "на мапі." msgid "Monsters Mode" msgstr "МонÑтри" msgid "Used to place monsters on the map." msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¼Ð¾Ð½Ñтрів на мапі." msgid "Allows you to draw streams by clicking and dragging." msgstr "ДозволÑÑ” малювати річки за допомогою тицÑÐ½Ð½Ñ Ñ‚Ð° перетÑгуваннÑ." msgid "Stream Mode" msgstr "Річки" msgid "Allows you to draw roads by clicking and dragging." msgstr "ДозволÑÑ” малювати дороги за допомогою ÐºÐ»Ð°Ñ†Ð°Ð½Ð½Ñ Ñ‚Ð° перетÑгуваннÑ." msgid "Road Mode" msgstr "Дорога" msgid "Erase Mode" msgstr "СтираннÑ" msgid "Used to erase objects from the map." msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¾Ð±'єктів з мапи." msgid "Change between zoom and normal view." msgstr "ÐŸÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ð½Ð½Ñ Ð¼Ñ–Ð¶ маÑштабуваннÑм Ñ– звичайним видом." msgid "Magnify" msgstr "Збільшити" msgid "Undo" msgstr "СкаÑувати" msgid "Undo your last action." msgstr "СкаÑуйте оÑтанню дію." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "СкаÑуйте оÑтанню дію." msgid "Edit map title, description, and other general information." msgstr "Редагувати назву мапи, Ð¾Ð¿Ð¸Ñ Ñ‚Ð° іншу загальну інформацію." msgid "Specifications" msgstr "ÐалаштуваннÑ" msgid "File Options" msgstr "Параметри файлу" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Відкрийте меню параметрів файлу, де ви можете зберегти або завантажити мапу, " "або вийти з редактора." msgid "View the editor system options, which let you customize the editor." msgstr "" "ПереглÑд ÑиÑтемних параметрів редактора, за допомогою Ñких ви можете " "налаштувати редактор." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "" "Створити мапу розміром %{size} квадратів у ширину Ñ– %{size} квадратів у " "виÑоту." msgid "Cancel back to the New Map menu." msgstr "ПовернутиÑÑ Ð´Ð¾ меню Ðова Мапа." msgid "Cancel back to the main menu." msgstr "ПовернутиÑÑ Ð´Ð¾ головного меню." msgid "From Scratch" msgstr "З чиÑтого аркуша" msgid "Start from scratch with a blank map." msgstr "Почати з Ð½ÑƒÐ»Ñ Ð½Ð° чиÑтій мапі." msgid "Create a randomly generated map." msgstr "Створити випадково згенеровану мапу." msgid "Random" msgstr "Випадково" msgid "Cancel back to the Map Editor main menu." msgstr "ПовернутиÑÑ Ð´Ð¾ головного меню Редактора мап." msgid "No maps available!" msgstr "Ðема доÑтупних мап!" msgid "[%{pos}]: %{race} hero" msgstr "[%{pos}]: %{race} герой" msgid "[%{pos}]: %{name}, %{race} hero" msgstr "[%{pos}]: %{name}, %{race} герой" msgid "[%{pos}]: %{race} town" msgstr "[%{pos}]: %{race} міÑто" msgid "[%{pos}]: %{race} castle" msgstr "[%{pos}]: %{race} замок" msgid "[%{pos}]: %{name}, %{race} town" msgstr "[%{pos}]: %{name}, %{race} міÑто" msgid "[%{pos}]: %{name}, %{race} castle" msgstr "[%{pos}]: %{name}, %{race} замок" msgid "None." msgstr "Ðема." msgid "One side defeats another." msgstr "Одна Ñторона перемагає іншу." msgid "Accumulate gold." msgstr "Ðакопичити золота." msgid "Run out of time." msgstr "Ð’Ñтигнути у відведений чаÑ." msgid "alliance|1st" msgstr "1-й" msgid "alliance|2nd" msgstr "2-й" msgid "alliance|3rd" msgstr "3-й" msgid "alliance|4th" msgstr "4-й" msgid "alliance|5th" msgstr "5-й" msgid "Special Loss Condition" msgstr "ОÑобливі умови програшу" msgid "Special Victory Condition" msgstr "ОÑобливі умови перемоги" msgid "Allow standard victory conditions" msgstr "Дозволити Ñтандартні умови перемоги" msgid "Allow this condition also for AI" msgstr "Дозволити цю умову Ð´Ð»Ñ Ð¨Ð† тажок" msgid "Set alliances:" msgstr "Ð’Ñтановити альÑнÑ:" msgid "{%number} alliance: " msgstr "{%number} альÑнÑ: " msgid "Gold:" msgstr "Золото:" msgid "Select a Town to capture to achieve victory" msgstr "Виберіть міÑто, Ñке потрібно захопити, щоб доÑÑгти перемоги" msgid "Click here to change the town needed to capture to achieve victory." msgstr "" "Тицьніть Ñюди, щоб змінити міÑто, Ñке потрібно захопити Ð´Ð»Ñ Ð´Ð¾ÑÑÐ³Ð½ÐµÐ½Ð½Ñ " "перемоги." msgid "Select a Hero to defeat to achieve victory" msgstr "Виберіть героÑ, здолавши Ñкого, доÑÑгнете перемоги" msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "" "Тицьніть Ñюди, щоб змінити героÑ, Ñкого потрібно перемогти, Ð´Ð»Ñ Ð´Ð¾ÑÑÐ³Ð½ÐµÐ½Ð½Ñ " "перемоги." msgid "Put %{color} player in the %{alliance} alliance" msgstr "ПоміÑтити %{color} Ð³Ñ€Ð°Ð²Ñ†Ñ Ð² %{alliance} альÑнÑ" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" "Якщо цей прапорець вÑтановлено, %{color} гравець буде в %{alliance} альÑнÑÑ–." msgid "Days:" msgstr "Дні:" msgid "Select a Town to lose to suffer defeat" msgstr "Виберіть міÑто, Ñке потрібно втратити, щоб зазнати поразки" msgid "Click here to change the town whose loss would mean defeat." msgstr "Тицьніть тут Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ міÑто, втрата Ñкого означатиме поразку." msgid "Select a Hero to lose to suffer defeat" msgstr "Виберіть героÑ, втрата Ñкого означатиме поразку." msgid "Click here to change the hero whose loss would mean defeat." msgstr "Тицьніть Ñюди, щоб змінити героÑ, втрата Ñкого означатиме поразку." msgid "Map Difficulty" msgstr "" "СкладніÑть\n" "мапи" msgid "Map Description" msgstr "ÐžÐ¿Ð¸Ñ Ð¼Ð°Ð¿Ð¸" msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" "Введений Ð¾Ð¿Ð¸Ñ Ð¼Ð°Ð¿Ð¸ перевищує макÑимально дозволені 5 Ñ€Ñдків. Його буде " "Ñкорочено до розміру Ð¿Ð¾Ð»Ñ Ð¾Ð¿Ð¸Ñу мапи." msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "Змінити назву мапи" msgid "Change Map Description" msgstr "Змінити Ð¾Ð¿Ð¸Ñ Ð¼Ð°Ð¿Ð¸" msgid "Click to accept the changes made." msgstr "Тицьніть, щоб прийнÑти внеÑені зміни." msgid "Click to edit custom rumors." msgstr "Тицьніть, щоб редагувати влаÑні чутки." msgid "Rumors" msgstr "Чутки" msgid "Click to edit daily events." msgstr "Тицьніть Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‰Ð¾Ð´ÐµÐ½Ð½Ð¸Ñ… подій." msgid "Events" msgstr "Події" #, fuzzy msgid "Click to change the language of the map." msgstr "Змінити мову гри." msgid "Click to change your map name." msgstr "Тицьніть, щоб змінити назву вашої мапи." msgid "Map Name" msgstr "Ðазва мапи" msgid "Click to change the description of the current map." msgstr "Тицьніть, щоб змінити Ð¾Ð¿Ð¸Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¾Ñ— мапи." msgid "Click to change the victory condition of the current map." msgstr "Тицьніть, щоб змінити умови перемоги Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¾Ñ— мапи." msgid "Click to change the loss condition of the current map." msgstr "Тицьніть, щоб змінити умови поразки Ð´Ð»Ñ Ð¿Ð¾Ñ‚Ð¾Ñ‡Ð½Ð¾Ñ— мапи." msgid "Indicates the player types in the scenario. Click to change." msgstr "Показує типи гравців у Ñценарії. Тицьніть, щоб змінити." msgid "Player Type" msgstr "Тип гравцÑ" msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Тицьніть, щоб вÑтановити ÑкладніÑть мапи. Складніші мапи можуть міÑтити " "більше або Ñильніших ворогів, меншу кількіÑть реÑурÑів або інші додаткові " "умови, роблÑчи гру Ñкладнішою Ð´Ð»Ñ Ð³Ñ€Ð°Ð²Ñ†Ñ-людини." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Виберіть кількіÑть %{resource}:" msgid "Animation" msgstr "ÐнімаціÑ" msgid "Passability" msgstr "ПрохідніÑть" msgid "Toggle animation of the objects." msgstr "Ðнімації об'єктів умівк/вимк." msgid "Toggle display of objects' passability." msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ…Ñ–Ð´Ð½Ð¾Ñті об'єктів увімк/вимк." msgid "Rumor:" msgstr "Чутка:" msgid "Rumor" msgstr "Чутка" msgid "This rumor already exists in the list." msgstr "Ð¦Ñ Ñ‡ÑƒÑ‚ÐºÐ° вже Ñ” у ÑпиÑку." msgid "Click to save the rumors." msgstr "Тицьніть, щоб зберегти чутку." msgid "Add Rumor" msgstr "Додати чутку" msgid "Add an additional rumor." msgstr "Додати додаткову чутку." msgid "Edit Rumor" msgstr "Редагувати чутку" msgid "Edit an existing rumor." msgstr "Редагувати Ñ–Ñнуючу чутку." msgid "Delete Rumor" msgstr "Видалити чутку" msgid "Delete an existing rumor." msgstr "Видалити Ñ–Ñнуючу чутку." msgid "" "\n" "\n" "Size: " msgstr "" "\n" "\n" "Розмір: " msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "ОпиÑ: " msgid "Save Map:" msgstr "Зберегти мапу:" msgid "Click to save the current map." msgstr "Тицьніть, щоб зберегти поточну мапу." msgid "Riddle:" msgstr "Загадка:" msgid "Answers:" msgstr "Відповіді:" msgid "Answer:" msgstr "Відповідь:" msgid "Answer" msgstr "Відповідь" msgid "This answer exists in the list." msgstr "Ð¦Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´ÑŒ Ñ” у ÑпиÑку." msgid "Click to save the Sphinx properties." msgstr "Тицьніть, щоб зберегти влаÑтивоÑті СфінкÑа." msgid "Add Answer" msgstr "Додати відповідь" msgid "Add an additional answer for the question." msgstr "Додати додаткову відповідь на запитаннÑ." msgid "Edit Answer" msgstr "Редагувати відповідь" msgid "Edit an existing answer for the question." msgstr "Редагувати Ñ–Ñнуючу відповідь на запитаннÑ." msgid "Delete Answer" msgstr "Видалити відповідь" msgid "Delete an existing answer for the question." msgstr "Видалити Ñ–Ñнуючу відповідь на запитаннÑ." msgid "No artifact will be given as a reward." msgstr "Жоден артефакт не буде виданий у ÑкоÑті винагороди." msgid "Delete an artifact from the reward." msgstr "Видалити артефакт з винагороди." msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "День: %{day} Тиждень: %{week} МіÑÑць: %{month}" msgid "difficulty|Easy" msgstr "ПроÑта" msgid "difficulty|Normal" msgstr "Звичайна" msgid "difficulty|Hard" msgstr "Важка" msgid "difficulty|Expert" msgstr "ЕкÑпертна" msgid "difficulty|Impossible" msgstr "Ðеможлива" msgid "and more..." msgstr "Ñ– не тільки..." msgid "Easy" msgstr "Легко" msgid "Normal" msgstr "Звичайна" msgid "Hard" msgstr "Важко" msgid "Campaign Difficulty" msgstr "" "СкладніÑть\n" "Кампанії" msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Виберіть цю ÑкладніÑть, щоб відчути Ñ–Ñторію гри з меншими труднощами. ШІ " "буде Ñлабшим ніж на звичайній ÑкладноÑті." msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "" "Виберіть цю ÑкладніÑть, щоб пройти кампанію відповідно до початкового задуму." msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Виберіть цю ÑкладніÑть, Ñкщо хочете більше виклику. ШІ буде Ñильнішим, ніж " "на звичайній ÑкладноÑті." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "ВітаннÑ!\n" "\n" "Дні: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "СкладніÑть: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Очки: %{score}\n" "\n" "Рейтинг:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Почати вибраний Ñценарій." msgid "View Intro" msgstr "ПереглÑнути вÑтуп" msgid "View the intro video for the current state of the campaign." msgstr "ПереглÑнути вÑтупне відео поточного Ñценарію кампанії." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Виберіть ÑкладніÑть кампанії. Її можна знизити в будь-Ñкий момент під Ñ‡Ð°Ñ " "гри." msgid "Restart the current scenario." msgstr "ПерезапуÑтити поточний Ñценарій." msgid "Difficulty" msgstr "СкладніÑть" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Ви перейшли на нижчу ÑкладніÑть кампанії. ПіÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ви не зможете " "повернути цю зміну. Рекорд буде розраховано виключно на оÑнові нової " "ÑкладноÑті. Бажаєте продовжити?" msgid "Are you sure you want to restart this scenario?" msgstr "Ви впевнені, що хочете перезапуÑтити цей Ñценарій?" msgid "Campaign Scenario loading failure" msgstr "Помилка Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñценарію кампанії" msgid "Please make sure that campaign files are correct and present." msgstr "Будь лаÑка, переконайтеÑÑ, що файли кампанії правильні та приÑутні." msgid "Days spent" msgstr "Витрачено днів" msgid "The number of days spent on this campaign." msgstr "КількіÑть днів, витрачених на цю кампанію." msgid "Project Coordination and Core Development" msgstr "ÐšÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ та оÑновна розробка" msgid "Development" msgstr "Розробка" msgid "Visit us at " msgstr "Відвідайте Ð½Ð°Ñ Ð½Ð°" msgid "QA and Support" msgstr "ЧП та підтримка" msgid "Dev and Support" msgstr "Розробка та підтримка" msgid "Special Thanks to" msgstr "ОÑоблива подÑка" msgid "and many-many other contributors and supporters!" msgstr "та багато-багато інших допиÑувачів Ñ– підтримувачів!" msgid "Support us at" msgstr "Підтримайте Ð½Ð°Ñ Ð½Ð°Ñ " msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "https://www.patreon.com/fheroes2" msgid "Connect with us at" msgstr "Зв'ÑжітьÑÑ Ð· нами на" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "https://www.facebook.com/groups/fheroes2" msgid "Need help with the game?" msgstr "Потрібна допомога з грою грою?" msgid "Original project before 0.7" msgstr "Оригінальний проект до 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Команда розробки Героїв Меча та Магії 2: Війна за Спадщину" msgid "Designed and Directed" msgstr "Розроблено та зрежиÑовано" msgid "Programming and Design" msgstr "ÐŸÑ€Ð¾Ð³Ñ€Ð°Ð¼ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° дизайн" msgid "Executive Producer" msgstr "Виконавчий продюÑер" msgid "Producer" msgstr "ПродюÑер" msgid "Additional Design" msgstr "Додаткове оформленнÑ" msgid "Additional Programming" msgstr "Додаткове програмуваннÑ" msgid "Musical Production" msgstr "Музичне виробництво" msgid "Music and Sound Design" msgstr "Музика та звуковий дизайн" msgid "Vocalists" msgstr "ВокаліÑти" msgid "Art Director" msgstr "Художній керівник" msgid "Assistant Art Director" msgstr "Помічник художнього керівника" msgid "Artists" msgstr "Художники" msgid "QA Manager" msgstr "Менеджер з контролю ÑкоÑті" msgid "QA" msgstr "Контроль ÑкоÑті" msgid "Writing" msgstr "ПиÑьменницька творчіÑть" msgid "Manual and Helpfile" msgstr "ПоÑібник та довідка" msgid "Scenarios" msgstr "Сценарії" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Команда розробки Героїв Меча та Магії 2: Ціна ВірноÑті" msgid "Design Lead" msgstr "Керівник дизайну" msgid "Designers" msgstr "Дизанйнери" msgid "Programming Lead" msgstr "ПрограміÑÑ‚ керівник" msgid "Art Lead" msgstr "Художній керівник" msgid "Playtesters" msgstr "ТеÑтувальники" msgid "Designer" msgstr "Дизанйнер" msgid "Producers" msgstr "ПродюÑери" msgid "QA Managers" msgstr "Менеджери із Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ ÑкоÑті" msgid "Sound Design" msgstr "Звуковий дизайн" msgid "Town Themes" msgstr "Музичні теми в міÑтах" msgid "Alto Sax" msgstr "Ðльт ÑакÑофон" msgid "Harpsichord and Piano" msgstr "КлавеÑин Ñ– фортепіано" msgid "Basso Vocal" msgstr "БаÑовий вокал" msgid "Soprano Vocal" msgstr "Вокал Ñопрано" msgid "Recorded at %{recordingStudio}" msgstr "ЗапиÑано в %{recordingStudio}" msgid "credits|Manual" msgstr "ПоÑібник" msgid "German Consultant" msgstr "Ðімецький конÑультант" msgid "Map Designers" msgstr "Дизайнери мап" msgid "Package Design" msgstr "Дизайн упаковки" msgid "High Scores" msgstr "Рекорди" msgid "Your Name" msgstr "Ваше Ім'Ñ" msgid "Unknown Hero" msgstr "Ðевідомий Герой" msgid "Standard" msgstr "Стандарт" msgid "View High Scores for Standard Maps." msgstr "ПереглÑнути рекорди у Ñтандартних мап." msgid "Campaign" msgstr "КампаніÑ" msgid "View High Scores for Campaigns." msgstr "ПереглÑнути рекорди у кампаніÑÑ…." msgid "hotkey|default okay event" msgstr "підтвердити подію" msgid "hotkey|default cancel event" msgstr "ÑкаÑувати подію" msgid "hotkey|default left" msgstr "ліворуч" msgid "hotkey|default right" msgstr "праворуч" msgid "hotkey|default up" msgstr "вгору" msgid "hotkey|default down" msgstr "вниз" msgid "hotkey|toggle fullscreen" msgstr "повноекранний режим увімк/вимк" msgid "hotkey|toggle text support mode" msgstr "текÑтовий Ð¾Ð¿Ð¸Ñ ÑƒÐ²Ñ–Ð¼Ðº/вимк" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "текÑтовий Ð¾Ð¿Ð¸Ñ ÑƒÐ²Ñ–Ð¼Ðº/вимк" msgid "hotkey|new game" msgstr "нова гра" msgid "hotkey|load game" msgstr "завантажити гру" msgid "hotkey|high scores" msgstr "рекорди" msgid "hotkey|credits" msgstr "титри" msgid "hotkey|standard game" msgstr "звичайна гра" msgid "hotkey|campaign game" msgstr "кампаніÑ" msgid "hotkey|multi-player game" msgstr "багатокориÑтувацька гра" msgid "hotkey|settings" msgstr "налаштуваннÑ" msgid "hotkey|quit" msgstr "вийти" msgid "hotkey|select map" msgstr "вибрати мапу" msgid "hotkey|select small map size" msgstr "вибрати мапу малого розміру" msgid "hotkey|select medium map size" msgstr "вибрати мапу Ñереднього розміру" msgid "hotkey|select large map size" msgstr "вибрати мапу великого розміру" msgid "hotkey|select extra large map size" msgstr "вибрати мапу надвеликого розміру" msgid "hotkey|select all map sizes" msgstr "вибрати мапи уÑÑ–Ñ… розмірів" msgid "hotkey|hot seat game" msgstr "гарÑче ÑидіннÑ" msgid "hotkey|battle only game" msgstr "лише битва" msgid "hotkey|choose the original campaign" msgstr "вибрати оригінальну кампанію" msgid "hotkey|choose the expansion campaign" msgstr "вибрати кампанію доповненнÑ" msgid "hotkey|map editor main menu" msgstr "головне меню редактора мап" msgid "hotkey|new map menu" msgstr "нова гра" msgid "hotkey|load map menu" msgstr "завантажити гру" msgid "hotkey|new map from scratch" msgstr "нова мапа з чиÑтого аркуша" msgid "hotkey|new random map" msgstr "нова випадкова мапа" msgid "hotkey|undo last action" msgstr "відмінити оÑтанню дію" msgid "hotkey|redo last action" msgstr "повторити оÑтанню дію" msgid "hotkey|open game main menu" msgstr "відкрити головне меню гри" msgid "hotkey|toggle passability" msgstr "відобразити прохідніÑть" msgid "hotkey|roland campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ Ð Ð¾Ð»Ð°Ð½Ð´Ð°" msgid "hotkey|archibald campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ Ðрчібальда" msgid "hotkey|price of loyalty campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ Ð¦Ñ–Ð½Ð° ВірноÑті" msgid "hotkey|voyage home campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ ÐŸÐ¾Ð´Ð¾Ñ€Ð¾Ð¶ Додому" msgid "hotkey|wizard's isle campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ ÐžÑтрів ЧародіÑ" msgid "hotkey|descendants campaign" msgstr "ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ Ðащадки" msgid "hotkey|select first campaign bonus" msgstr "вибрати перший Ð±Ð¾Ð½ÑƒÑ ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ—" msgid "hotkey|select second campaign bonus" msgstr "вибрати другий Ð±Ð¾Ð½ÑƒÑ ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ—" msgid "hotkey|select third campaign bonus" msgstr "вибрати тртій Ð±Ð¾Ð½ÑƒÑ ÐºÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ—" msgid "hotkey|view campaign intro" msgstr "дивитиÑÑ Ð²Ñтуп кампанії" msgid "hotkey|select campaign difficulty" msgstr "обрати ÑкладніÑть кампанії" msgid "hotkey|restart campaign scenario" msgstr "перезапуÑк Ñценарію кампанії" msgid "hotkey|world map left" msgstr "Ñвітова мапа ліворуч" msgid "hotkey|world map right" msgstr "Ñвітова мапа праворуч" msgid "hotkey|world map up" msgstr "Ñвітова мапа вгору" msgid "hotkey|world map down" msgstr "Ñвітова мапа вниз" msgid "hotkey|world map up left" msgstr "Ñвітова мапа вгору й ліворуч" msgid "hotkey|world map up right" msgstr "Ñвітова мапа вгору й праворуч" msgid "hotkey|world map down left" msgstr "Ñвітова мапа донизу й ліворуч" msgid "hotkey|world map down right" msgstr "Ñвітова мапа донизу й праворуч" msgid "hotkey|save game" msgstr "зберегти гру" msgid "hotkey|next hero" msgstr "наÑтупний герой" msgid "hotkey|change to hero under cursor" msgstr "перейти на Ð³ÐµÑ€Ð¾Ñ Ð¿Ñ–Ð´ курÑором" msgid "hotkey|start hero movement" msgstr "почати рух героÑ" msgid "hotkey|cast adventure spell" msgstr "наклаÑти пригодницьке заклинаннÑ" msgid "hotkey|put hero to sleep" msgstr "приÑпати героÑ" msgid "hotkey|next town" msgstr "показати наÑтупне міÑто" msgid "hotkey|end turn" msgstr "завершити хід" msgid "hotkey|file options" msgstr "параметри файлу" msgid "hotkey|adventure options" msgstr "пригодницькі налаштуваннÑ" msgid "hotkey|puzzle map" msgstr "мапа-пазл" msgid "hotkey|scenario information" msgstr "Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ Ñценарій" msgid "hotkey|dig for artifact" msgstr "відкопати артефакт" msgid "hotkey|view world" msgstr "оглÑнути Ñвіт" msgid "hotkey|kingdom summary" msgstr "загальна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ð¾ королівÑтву" msgid "hotkey|default action" msgstr "дії за налаштуваннÑм" msgid "hotkey|open focus" msgstr "відкрити фокуÑ" msgid "hotkey|system options" msgstr "параметри ÑиÑтеми" msgid "hotkey|scroll left" msgstr "прокрутити ліворуч" msgid "hotkey|scroll right" msgstr "прокрутити праворуч" msgid "hotkey|scroll up" msgstr "прокрутити вгору" msgid "hotkey|scroll down" msgstr "прокрутити вниз" msgid "hotkey|toggle control panel" msgstr "відобразити панель керуваннÑ" msgid "hotkey|toggle radar" msgstr "відобразити радар" msgid "hotkey|toggle buttons" msgstr "відобразити кнопки" msgid "hotkey|toggle status" msgstr "відобразити ÑтатуÑ" msgid "hotkey|toggle icons" msgstr "відобразити іконки" msgid "hotkey|transfer control to ai" msgstr "передати ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¨Ð†" msgid "hotkey|retreat from battle" msgstr "відÑтупити з бою" msgid "hotkey|surrender during battle" msgstr "капітулювати під Ñ‡Ð°Ñ Ð±Ð¸Ñ‚Ð²Ð¸" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "увімкнути автоматичний бій" #, fuzzy msgid "hotkey|quick combat" msgstr "вийти" msgid "hotkey|battle options" msgstr "параметри бою" msgid "hotkey|skip turn in battle" msgstr "пропуÑтити хід у бою" msgid "hotkey|cast battle spell" msgstr "наклаÑти бойове заклинаннÑ" msgid "hotkey|dwelling level 1" msgstr "житло 1-го рівнÑ" msgid "hotkey|dwelling level 2" msgstr "житло 2-го рівнÑ" msgid "hotkey|dwelling level 3" msgstr "житло 3-го рівнÑ" msgid "hotkey|dwelling level 4" msgstr "житло 4-го рівнÑ" msgid "hotkey|dwelling level 5" msgstr "житло 5-го рівнÑ" msgid "hotkey|dwelling level 6" msgstr "житло 6-го рівнÑ" msgid "hotkey|well" msgstr "колодÑзь" msgid "hotkey|marketplace" msgstr "ринок" msgid "hotkey|mage guild" msgstr "Ð³Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð¼Ð°Ð³Ñ–Ñ—" msgid "hotkey|shipyard" msgstr "верф" msgid "hotkey|thieves guild" msgstr "Ð³Ñ–Ð»ÑŒÐ´Ñ–Ñ Ð·Ð»Ð¾Ð´Ñ–Ñ—Ð²" msgid "hotkey|tavern" msgstr "таверна" msgid "hotkey|construction screen" msgstr "екран будівництва" msgid "hotkey|buy all monsters in well" msgstr "придбати уÑÑ–Ñ… монÑтрів у колодÑзі" msgid "hotkey|split stack by half" msgstr "розділити загін навпіл" msgid "hotkey|split stack by one" msgstr "розділити загін по одному" msgid "hotkey|join stacks" msgstr "об'єднати загони" msgid "hotkey|upgrade troop" msgstr "поліпшити армію" msgid "hotkey|dismiss hero or troop" msgstr "звільнити Ð³ÐµÑ€Ð¾Ñ Ð°Ð±Ð¾ армію" #, fuzzy msgid "hotkey|exchange all troops" msgstr "поліпшити армію" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Хочете повернутиÑÑ Ð½Ð° ручний контроль? Ефект відбудетьÑÑ Ð»Ð¸ÑˆÐµ на наÑтупний " "хід." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Ви хочете передати ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð²Ñ–Ð´ Ð²Ð°Ñ Ð´Ð¾ ШІ? Ефект відбудетьÑÑ Ð»Ð¸ÑˆÐµ на " "наÑтупний хід." # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Default Actions" msgstr "Дії Ñк уÑталено" msgid "Global Actions" msgstr "Глобальні дії" msgid "World Map" msgstr "Мапа Ñвіту" msgid "Battle Screen" msgstr "Екран бою" msgid "Town Screen" msgstr "Вікно міÑта" msgid "Army Actions" msgstr "Дії армії" msgid "The save file is corrupted." msgstr "Файл Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾ÑˆÐºÐ¾Ð´Ð¶ÐµÐ½Ð¸Ð¹." msgid "Unsupported save format: " msgstr "Ðепідтримуваний формат збереженнÑ: " msgid "Current game version: " msgstr "Поточна верÑÑ–Ñ Ð³Ñ€Ð¸: " msgid "Last supported version: " msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÑƒÐ²Ð°Ð½Ð° верÑÑ–Ñ: " msgid "This file contains a save with an invalid game type." msgstr "Цей файл міÑтить Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð· хибим типом гри." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Цей файл Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ð¸Ð¼Ð°Ð³Ð°Ñ” ігрових реÑурÑів \"Ціна вірноÑті\", але вони не " "були надані рушію." msgid "This saved game is localized to '" msgstr "Ð¦Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð° гра знаходитьÑÑ Ð² '" msgid "' language, but the current language of the game is '" msgstr "' мовою, але поточна мова гри - це '" msgid "No save files to load." msgstr "Ðемає файлів Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ." msgid "Hot Seat" msgstr "ГарÑче ÑидіннÑ" msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Зіграйте в гру \"ГарÑче міÑце\", де від 2 до 6 гравців грають за одним " "комп'ютером, переÑідаючи на \"гарÑче міÑце\", коли наÑтає Ñ—Ñ…Ð½Ñ Ñ‡ÐµÑ€Ð³Ð°." msgid "A single player game playing out a single map." msgstr "Гра Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ Ð³Ñ€Ð°Ð²Ñ†Ñ Ð½Ð° одній мапі." msgid "Standard Game" msgstr "Стандартна Гра" msgid "A single player game playing through a series of maps." msgstr "Гра Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ гравцÑ, що проходить через Ñерію мап." msgid "Campaign Game" msgstr "КампаніÑ" msgid "Multi-Player Game" msgstr "БагатокориÑтувацька гра" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "БагатокориÑтувацька гра, в Ñкій кілька гравців змагаютьÑÑ Ð¾Ð´Ð¸Ð½ проти одного " "на одній мапі." msgid "fheroes2 Resurrection Team presents" msgstr "Команда fheroes2 Resurrection предÑтавлÑÑ”" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "ЛаÑкаво проÑимо до Героїв Меча та Магії 2 на оÑнові Ñ€ÑƒÑˆÑ–Ñ fheroes2!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "ЛаÑкаво проÑимо до Героїв Меча та Магії 2 на оÑнові Ñ€ÑƒÑˆÑ–Ñ fheroes2!\n" "Перед початком гри, будь лаÑка, виберіть роздільну здатніÑть екрану." msgid "Greetings!" msgstr "ВітаннÑ!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "" "Залишити Heroes of Might and Magic II Ñ– повернутиÑÑ Ð´Ð¾ операційної ÑиÑтеми." msgid "Credits" msgstr "Титри" msgid "View the credits screen." msgstr "ПереглÑнути титри." msgid "View the high scores screen." msgstr "ПереглÑд Ñторінки рекордів." msgid "Create new or modify existing maps." msgstr "Створити нову або змінити Ñ–Ñнуючу мапу." msgid "Change language, resolution and settings of the game." msgstr "Змінити мову, роздільну здатніÑть та Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€Ð¸." msgid "Game Settings" msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€Ð¸" msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "ВідÑутні необхідні відеофайли Ð´Ð»Ñ Ð²Ñ–ÐºÐ½Ð° вибору кампанії. Будь лаÑка, " "переконайтеÑÑ, що вÑÑ– необхідні файли приÑутні в ÑиÑтемі." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "ÐšÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ Ð Ð¾Ð»Ð°Ð½Ð´Ð° або Ðрчибальда з оригінальної Heroes of Might and Magic II." msgid "Original Campaign" msgstr "Оригінальна кампаніÑ" msgid "Expansion Campaign" msgstr "ÐšÐ°Ð¼Ð¿Ð°Ð½Ñ–Ñ Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "Одна з чотирьох нових кампаній з набору Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ \"Ціна вірноÑті\"." msgid "Loading video. Please wait..." msgstr "Відео завантажуєтьÑÑ. Будь лаÑка, зачекайте..." msgid "Host" msgstr "ГоÑподар" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "ГоÑподар вÑтановлює параметри гри. У кожній мережевій грі може бути лише " "один ведучий." msgid "Guest" msgstr "ГіÑть" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "ГіÑть чекає, поки гоÑподар налаштує гру, піÑÐ»Ñ Ñ‡Ð¾Ð³Ð¾ автоматично приєднуєтьÑÑ " "до неї. У TCP/IP-іграх може бути кілька гоÑтей." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" "Ð”Ð»Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ fheroes2 потрібні файли даних з оригінальної Heroes of Might and " "Magic II. Схоже, ви викориÑтовуєте Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ демо-верÑÑ–ÑŽ Heroes of Might and " "Magic II. Зверніть увагу, що у цій верÑÑ–Ñ— буде доÑтупний лише один Ñценарій." msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "БагатокориÑтувацька гра, в Ñкій кілька гравців змагаютьÑÑ Ð¾Ð´Ð¸Ð½ проти одного " "на одній мапі." msgid "Battle Only" msgstr "Лише битва" msgid "Setup and play a battle without loading any map." msgstr "Ðалаштуйте та зіграйте бій, не завантажуючи жодної мапи." msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "Зіграйте в гру \"ГарÑче міÑце\", де від 2 до 6 гравців грають за одним " "комп'ютером, переÑідаючи на \"гарÑче міÑце\", коли наÑтає Ñ—Ñ…Ð½Ñ Ñ‡ÐµÑ€Ð³Ð°." msgid "2 Players" msgstr "2 гравців" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "" "Грайте з 2 гравцÑми-людьми та за бажаннÑм до 4 додаткових комп'ютерних " "гравців." msgid "3 Players" msgstr "3 гравців" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "" "Грайте з 3 гравцÑми-людьми та за бажаннÑм до 3 додаткових комп'ютерних " "гравців." msgid "4 Players" msgstr "4 гравців" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "" "Грайте з 4 гравцÑми-людьми та за бажаннÑм до 2 додаткових комп'ютерних " "гравців." msgid "5 Players" msgstr "5 гравців" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "" "Грайте з 5 гравцÑми-людьми та за бажаннÑм до 1 додаткового комп'ютерного " "гравцÑ." msgid "6 Players" msgstr "6 гравців" msgid "Play with 6 human players." msgstr "Грайте з 6 гравцÑми-людьми." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "МіÑто Драконів впало! Тепер ви володар драконів." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Ви захопили %{name}!\n" "Ви переможець." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Ви захопили ворожого Ð³ÐµÑ€Ð¾Ñ %{name}!\n" "Ваш квеÑÑ‚ завершено." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Ви знайшли %{name}.\n" "Ваші пошуки завершено." msgid "Ultimate Artifact" msgstr "Легендарний Ðртефакт" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Ворог переможений.\n" "Ваша Ñторона перемогла!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Ви накопичили у Ñвоїй Ñкарбниці понад %{count} золота.\n" "Ð’ÑÑ– вороги ÑхилÑютьÑÑ Ð¿ÐµÑ€ÐµÐ´ вашим багатÑтвом Ñ– Ñилою." msgid "Victory!" msgstr "Перемога!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Ворог захопив %{name}!\n" "Вони тріумфують." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Ворог накопичив у Ñвоїй Ñкарбниці більше %{count} золота.\n" "Ви повинні ÑхилитиÑÑ Ð¿ÐµÑ€ÐµÐ´ його багатÑтвом Ñ– Ñилою, зазнавши поразки." msgid "You have been eliminated from the game!!!" msgstr "Ð’Ð°Ñ ÑƒÑунуто з гри!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Ви втратили Ð³ÐµÑ€Ð¾Ñ %{name}.\n" "Ваш похід завершено." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Ви не вÑтигли завершити Ñвій квеÑÑ‚ вчаÑно.\n" "Ð’Ñе втрачено." msgid "Defeat!" msgstr "Поразка!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Головний рахунок: %{score}\n" "СкладніÑть: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "Здолати вÑÑ–Ñ… ворожих героїв Ñ– захопите вÑÑ– ворожі міÑта та замки." msgid "Your side defeats the opposing side." msgstr "Ваша Ñторона перемагає протилежну." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "ЗакінчивÑÑ Ñ‡Ð°Ñ. (Ðе вÑтигнути перемогти до певного моменту)." msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Ви повинні здолати ворожий альÑÐ½Ñ Ð· %{enemies}." msgstr[1] "Ви повинні здолати ворожий альÑÐ½Ñ Ð· %{enemies}." msgstr[2] "Ви повинні здолати ворожий альÑÐ½Ñ Ð· %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "ÐльÑÐ½Ñ Ð¼Ñ–Ð¶ %{allies} та вами повинен здолати ворожий альÑÐ½Ñ Ð· %{enemies}." msgstr[1] "" "ÐльÑÐ½Ñ Ð¼Ñ–Ð¶ %{allies} та вами повинен здолати ворожий альÑÐ½Ñ Ð· %{enemies}." msgstr[2] "" "ÐльÑÐ½Ñ Ð¼Ñ–Ð¶ %{allies} та вами повинен здолати ворожий альÑÐ½Ñ Ð· %{enemies}." msgid "Capture the castle '%{name}'." msgstr "Захопити замок '%{name}'." msgid "Capture the town '%{name}'." msgstr "Захопити міÑто '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Здолати Ð³ÐµÑ€Ð¾Ñ '%{name}'." msgid "Find the ultimate artifact." msgstr "Знайти легендарний артефакт." msgid "Find the '%{name}' artifact." msgstr "Знайти '%{name}' артефакт." msgid "Accumulate %{count} gold." msgstr "Ðакопичити %{count} золота." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" "або ви можете перемогти, здолавши вÑÑ–Ñ… ворожих героїв Ñ– захопивши вÑÑ– ворожі " "міÑта та замки." msgid "Lose the castle '%{name}'." msgstr "Втрата замку '%{name}'." msgid "Lose the town '%{name}'." msgstr "Втрата міÑта '%{name}'." msgid "Lose the hero: %{name}." msgstr "Втрата героÑ: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "Ðе виграти до ÐºÑ–Ð½Ñ†Ñ %{month} міÑÑцÑ, %{week} тижнÑ, %{day} днÑ." msgid "%{color} player has been vanquished!" msgstr "%{color} Ð³Ñ€Ð°Ð²Ñ†Ñ Ð±ÑƒÐ»Ð¾ переможено!" msgid "Major Event!" msgstr "Велична подіÑ!" msgid "Scenario:" msgstr "Сценарій:" msgid "Game Difficulty:" msgstr "СкладніÑть гри:" msgid "Opponents:" msgstr "Опоненти:" msgid "Class:" msgstr "КлаÑ:" msgid "Rating %{rating}%" msgstr "Рейтинг %{rating}%" msgid "Click here to select which scenario to play." msgstr "Тицьніть Ñюди Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ Ñценарію Ð´Ð»Ñ Ð³Ñ€Ð¸." msgid "Scenario" msgstr "Сценарій" msgid "Game Difficulty" msgstr "СкладніÑть гри" msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Це дозволÑÑ” вам змінити початкову ÑкладніÑть, на Ñкій будете грати. Ðа вищих " "рівнÑÑ… ÑкладноÑті ви починаєте гру з меншою кількіÑтю реÑурÑів, а на вищих " "налаштуваннÑÑ… комп'ютер отримує додаткові реÑурÑи." msgid "Difficulty Rating" msgstr "Рейтинг ÑкладноÑті" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Рейтинг ÑкладноÑті відображає комбінацію різних налаштувань вашої гри. Це " "чиÑло буде заÑтоÑовано до вашого оÑтаточного результату." msgid "Click to accept these settings and start a new game." msgstr "Тицьніть, щоб прийнÑти ці Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ– почати нову гру." msgid "Click to return to the main menu." msgstr "Тицьніть Ð´Ð»Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÐµÐ½Ð½Ñ Ð´Ð¾ головного меню." msgid "Astrologers proclaim the Month of the %{name}." msgstr "ÐÑтрологи оголошують міÑÑць %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "ÐÑтрологи оголошують тиждень %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "ПіÑÐ»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¾Ð³Ð¾ прироÑту популÑÑ†Ñ–Ñ %{monster} подвоюєтьÑÑ!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "ПіÑÐ»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¾Ð³Ð¾ прироÑту, популÑÑ†Ñ–Ñ %{monster} збільшуєтьÑÑ Ð½Ð° %{count} " "відÑоток!" msgstr[1] "" "ПіÑÐ»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¾Ð³Ð¾ прироÑту, популÑÑ†Ñ–Ñ %{monster} збільшуєтьÑÑ Ð½Ð° %{count} " "відÑотки!" msgstr[2] "" "ПіÑÐ»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¾Ð³Ð¾ прироÑту, популÑÑ†Ñ–Ñ %{monster} збільшуєтьÑÑ Ð½Ð° %{count} " "відÑотків!" msgid "%{monster} growth +%{count}." msgstr "%{monster} приріÑÑ‚ +%{count}." msgid " All populations are halved." msgstr "Ð’Ñе наÑÐµÐ»ÐµÐ½Ð½Ñ Ð·Ð¼ÐµÐ½ÑˆÑƒÑ”Ñ‚ÑŒÑÑ Ð²Ð´Ð²Ñ–Ñ‡Ñ–." msgid " All dwellings increase population." msgstr "УÑÑ– житла збільшують кількіÑть мешканців." msgid "New Month!" msgstr "Ðовий міÑÑць!" msgid "New Week!" msgstr "Ðовий тиждень!" msgid "Beware!" msgstr "СтережітьÑÑ!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "%{color} гравцю, це ваш оÑтанній день щоб захопити міÑто, інакше Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ " "вигнано з цієї землі." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "%{color} гравцю, у Ð²Ð°Ñ Ð·Ð°Ð»Ð¸ÑˆÐ¸Ð»Ð¾ÑÑ Ð»Ð¸ÑˆÐµ %{day} днів, щоб захопити міÑто, " "інакше Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ вигнано з цієї землі." msgid "%{color} player's turn." msgstr "%{color} гравець ходить." msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "%{color} гравцю, ви втратили оÑтаннє міÑто. Якщо ви не завоюєте нове міÑто " "протÑгом наÑтупного тижнÑ, Ð²Ð°Ñ Ð±ÑƒÐ´Ðµ уÑунуто." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "%{color} гравцю, ваші герої покидають ваÑ, а Ð²Ð°Ñ Ñамих проганÑють з цієї " "землі." msgid "Lord Kilburn" msgstr "Лорд Кілбурн" msgid "Tsabu" msgstr "Цабу" msgid "Sir Galant" msgstr "Сір Галлант" msgid "Thundax" msgstr "ТундакÑ" msgid "Lord Haart" msgstr "Лорд Хаарт" msgid "Ariel" msgstr "Ðріель" msgid "Rebecca" msgstr "Ребека" msgid "Sandro" msgstr "Сандро" msgid "Crodo" msgstr "Кродо" msgid "Barock" msgstr "Барок" msgid "Antoine" msgstr "Ðнтуан" msgid "Astra" msgstr "ÐÑтра" msgid "Agar" msgstr "Ðґар" msgid "Vatawna" msgstr "Ватавна" msgid "Vesper" msgstr "ВеÑпер" msgid "Ambrose" msgstr "ÐмбрізіÑ" msgid "Troyan" msgstr "ТроÑн" msgid "Jojosh" msgstr "Джоджош" msgid "Wrathmont" msgstr "Вратмонт" msgid "Maximus" msgstr "МакÑімуÑ" msgid "Next Hero" msgstr "ÐаÑтупний герой" msgid "Select the next Hero." msgstr "Вибрати наÑтупного героÑ." msgid "Hero Movement" msgstr "Рух ГероÑ" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "Почати Рух Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ обраному шлÑху, або заново відвідати об'єкт, зайнÑтий " "Героєм. ЗатиÑніть та утримуйте цю клавішу, щоб Ñкинути маршрут ГероÑ." msgid "Kingdom Summary" msgstr "Загальна Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ð¾ королівÑтву" msgid "View a summary of your Kingdom." msgstr "ПереглÑнути загальну інформацію по королівÑтву." msgid "Cast an adventure spell." msgstr "ÐаклаÑти Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð³Ð¾Ð´." msgid "End Turn" msgstr "Завершити хід" msgid "End your turn and let the computer take its turn." msgstr "Завершити Ñвій хід Ñ– дозволити комп'ютеру зробити Ñвій." msgid "Adventure Options" msgstr "Параметри пригод" msgid "Bring up the adventure options menu." msgstr "Відкрити меню параметрів пригоди." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Викликає меню параметрів файлу, що дозволÑÑ” завантажити, зберегти, почати " "нову гру або вийти з неї." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "Відкрити меню ÑиÑтемних параметрів, що дозволÑÑ” вам налаштувати гру." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Один або кілька героїв вÑе ще можуть рухатиÑÑ. Ви впевнені, що хочете " "завершити Ñвій хід?" msgid "Are you sure you want to quit?" msgstr "Ви впевнені, що хочете вийти?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "Ви впевнені, що хочете перезапуÑтити гру? (Поточну гру буде втрачено)." msgid "Are you sure you want to overwrite the save with this name?" msgstr "Ви впевнені, що хочете перезапиÑати Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð· такою назвою?" msgid "Game saved successfully." msgstr "Гру збережено уÑпішно." msgid "There was an issue during saving." msgstr "Під Ñ‡Ð°Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ð¸Ð½Ð¸ÐºÐ»Ð° проблема." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Ви впевнені, що хочете завантажити нову гру? (Ваша поточна гра буде " "втрачена)." msgid "Try looking on land!!!" msgstr "Спробуйте шукати на Ñуходолі!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Пошуки Легендарного артефакту виÑвилиÑÑ Ð¼Ð°Ñ€Ð½Ð¸Ð¼Ð¸. Ваш герой не зміг би його " "неÑти, навіть Ñкби знайшов - вÑÑ– його Ñлоти Ð´Ð»Ñ Ð°Ñ€Ñ‚ÐµÑ„Ð°ÐºÑ‚Ñ–Ð² заповнені." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Ðа розкопки артефактів потрібен цілий день, Ñпробуйте ще раз завтра." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "Провівши багато годин на розкопках, ви знайшли %{artifact}." msgid "Congratulations!" msgstr "Вітаємо!" msgid "Nothing here. Where could it be?" msgstr "Тут нічого немає. Де б воно могло бути?" msgid "Try searching on clear ground." msgstr "Спробуйте шукати на відкритій міÑцевоÑті." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Мініатюрний поглÑд на відомий Ñвіт. Тицьніть лівою кнопкою миші, щоб " "переміÑтити облаÑть переглÑду." msgid "Month: %{month} Week: %{week}" msgstr "МіÑÑць: %{month} Тиждень: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Ви знайшли\n" "трішечки %{resource}." msgid "Status Window" msgstr "Вікно ÑтатуÑу" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Це вікно міÑтить інформацію про ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð³ÐµÑ€Ð¾Ñ Ð°Ð±Ð¾ королівÑтва, а також " "показує дату." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Це вікно надає інформацію про ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð³ÐµÑ€Ð¾Ñ Ð°Ð±Ð¾ королівÑтва, а також " "показує дату. Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ñƒ між цими вікнами, тицьніть лівою кнопкою миші тут." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Це дозволÑÑ” вам змінювати Ñтартові позиції та кольори гравців. Певний колір " "завжди починатиметьÑÑ Ð² певному міÑці. Ðа деÑких позиціÑÑ… може грати тільки " "комп'ютерний гравець або тільки гравець людина." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Це дозволÑÑ” вам змінювати ÐºÐ»Ð°Ñ Ð³Ñ€Ð°Ð²Ñ†Ñ. КлаÑи не завжди можна змінити. " "Залежно від Ñценарію, гравець може отримати додаткові міÑта та/або героїв не " "Ñвого клаÑу." msgid "Handicap" msgstr "ОбмеженнÑ" # msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Це дозволÑÑ” вам наклаÑти Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð½Ð° конкретного гравцÑ. Обмеженими можуть " "мати лише гравці-люди. Гравці з обмеженнÑми починають з меншою кількіÑтю " "реÑурÑів Ñ– зароблÑють на 15 або 30% менше реÑурÑів за хід Ð´Ð»Ñ Ð»ÐµÐ³ÐºÐ¸Ñ… Ñ– " "важких обмежень відповідно." msgid "%{color} player" msgstr "%{color} гравець" msgid "No Handicap" msgstr "Без обмежень" msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Ðемає Ñпеціальних обмежень на початкові реÑурÑи та прибуток від реÑурÑів за " "хід." msgid "Mild Handicap" msgstr "Помірні обмеженнÑ" # msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Гравці з легкими обмеженнÑми починають з меншою кількіÑтю реÑурÑів Ñ– " "зароблÑють на 15% менше реÑурÑів за хід." msgid "Severe Handicap" msgstr "Значні обмеженнÑ" # msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Гравці зі значим обмеженнÑми починають з меншою кількіÑтю реÑурÑів Ñ– " "зароблÑють на 30% менше реÑурÑів за хід." # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "" "Default\n" "value" msgstr "" "ЗначеннÑ\n" "Ñк уÑталено" msgid "Set %{skill} Skill" msgstr "Задати навичку %{skill}" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" "Задати базове Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ %{skill}. Тицьніть правою кнопкою миші, щоб Ñкинути " "вÑÑ– навички до значень Ñк уÑталено." msgid "View %{skill} Info" msgstr "ПереглÑнути %{skill} інформацію" msgid "" "Default\n" "skill" msgstr "" "УÑталена\n" "навичка" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "123" msgid "Keyboard|SPACE" msgstr "ПРОБІЛ" msgid "Keyboard|ABC" msgstr "ÐБВ" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Прибутки королівÑтва" msgid "Kingdom Income per day." msgstr "Прибутки королівÑтва за день." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "За кожен підконтрольний маÑк ваші кораблі Ñ‰Ð¾Ð´Ð½Ñ Ð¿Ñ€Ð¾ÑуватимутьÑÑ Ð´Ð°Ð»Ñ–." msgid "English" msgstr "" msgid "French" msgstr "" msgid "Polish" msgstr "" msgid "German" msgstr "" msgid "Russian" msgstr "" msgid "Italian" msgstr "" msgid "Czech" msgstr "" msgid "Norwegian" msgstr "" msgid "Belarusian" msgstr "" msgid "Bulgarian" msgstr "" msgid "Ukrainian" msgstr "УкраїнÑька" msgid "Romanian" msgstr "" msgid "Spanish" msgstr "" msgid "Swedish" msgstr "" msgid "Portuguese" msgstr "" msgid "Turkish" msgstr "" msgid "Dutch" msgstr "" msgid "Hungarian" msgstr "" msgid "Danish" msgstr "" msgid "Slovak" msgstr "" msgid "Vietnamese" msgstr "" msgid "Slow" msgstr "Повільно" msgid "Fast" msgstr "Швидко" msgid "Very Fast" msgstr "Дуже швидко" msgid "Evil" msgstr "Зло" msgid "Good" msgstr "Добро" msgid ", FPS: " msgstr ", кдр/Ñ:" msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} пограбовано" msgid "pyramid|%{object} raided" msgstr "%{object} розграбовано" msgid "Ector" msgstr "Ектор" msgid "Gwenneth" msgstr "Òвеннет" msgid "Sir Gallant" msgstr "Сір Галлант" msgid "Tyro" msgstr "Тіроль" msgid "Dimitry" msgstr "Дімітрій" msgid "Ruby" msgstr "Рубі" msgid "Crag Hack" msgstr "Креґ Хек" msgid "Fineous" msgstr "ФайнеоуÑ" msgid "Jezebel" msgstr "Джезебель" msgid "Atlas" msgstr "ÐтлаÑ" msgid "Ergon" msgstr "Ергон" msgid "Jaclyn" msgstr "Жаклін" msgid "Gem" msgstr "Джем" msgid "Natasha" msgstr "Ðаташа" msgid "Carlawn" msgstr "Карлоне" msgid "Luna" msgstr "Луна" msgid "Arie" msgstr "Ðрій" msgid "Barok" msgstr "Барок" msgid "Kastore" msgstr "КаÑтор" msgid "Falagar" msgstr "Фалагар" msgid "Dawn" msgstr "Дон" msgid "Flint" msgstr "Флінт" msgid "Halon" msgstr "Халон" msgid "Myra" msgstr "Міра" msgid "Myrini" msgstr "Міріні" msgid "Wilfrey" msgstr "Вілфрі" msgid "Mandigal" msgstr "Мандигал" msgid "Sarakin" msgstr "Саракін" msgid "Charity" msgstr "Черіті" msgid "Darlana" msgstr "Дарлане" msgid "Ranloo" msgstr "Ранлу" msgid "Rialdo" msgstr "Ріальдо" msgid "Zam" msgstr "Зам" msgid "Zom" msgstr "Зом" msgid "Celia" msgstr "СеліÑ" msgid "Roxana" msgstr "РокÑана" msgid "Lord Corlagon" msgstr "Лорд Корлагон" msgid "Lord Halton" msgstr "Лорд Хальтон" msgid "Sister Eliza" msgstr "СеÑтра Еліза" msgid "Brother Brax" msgstr "Брат БракÑ" msgid "Dainwin" msgstr "Дейнвін" msgid "Joseph" msgstr "Джозеф" msgid "Mog" msgstr "Моґ" msgid "Solmyr" msgstr "Солмир" msgid "Ceallach" msgstr "Сіллах" msgid "Drakonia" msgstr "ДраконіÑ" msgid "Elderian" msgstr "ЕлдраÑн" msgid "Gallavant" msgstr "Òалавант" msgid "Jarkonas" msgstr "ЯрконаÑ" msgid "Martine" msgstr "Мартін" msgid " gives you maximum morale" msgstr " надає макÑимальний бойовий дух" msgid " gives you maximum luck" msgstr " надає макÑимальну удачу" msgid "You cannot have multiple spell books." msgstr "Ви не можете мати кілька книг заклинань." msgid "You cannot pick up this artifact, you already have a full load!" msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð° вільного міÑÑ†Ñ Ñ‰Ð¾Ð± підібрати цей артефакт!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Щоб накладати чари, Ñпершу придбайте книгу заклинань за %{gold} золота." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Ðа жаль, в даний момент у ваÑ, Ñхоже, трохи не виÑтачає коштів." msgid "Do you wish to buy one?" msgstr "Бажаєте придбати екземплÑÑ€?" msgid "%{count} / day" msgstr "%{count} / день" msgid "one" msgstr "один " msgid "two" msgstr "два " msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "Вир поглинає ваш корабель. ЧаÑтина вашої армії випала за борт." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "Ображені вашою відмовою від їхньої пропозиції, монÑтри атакують!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "%{monster}, вражені могутніÑтю ваших Ñил, починають розбігатиÑÑ.\n" "Ви хочете переÑлідувати Ñ—Ñ… Ñ– вÑтупити в бій?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "Обшукуючи ворожий табір, ви знаходите Ñхованку зі Ñкарбами." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Сторож млина оголошує:\n" "\"Пане, Ñ Ð´ÑƒÐ¶Ðµ Ñ‚Ñжко працював, щоб забезпечити Ð²Ð°Ñ Ñ†Ð¸Ð¼Ð¸ реÑурÑами, " "повертайтеÑÑŒ наÑтупного Ñ‚Ð¸Ð¶Ð½Ñ Ð·Ð° добавкою\"." msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Сторож млина оголошує:\n" "\"Мілорде, вибачте, але на даний момент у Ð½Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” реÑурÑів. Будь лаÑка, " "приходьте наÑтупного тижнÑ\"." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Сторож млина оголошує:\n" "\"Пане, Ñ Ð´ÑƒÐ¶Ðµ важко працював, щоб забезпечити Ð²Ð°Ñ Ñ†Ð¸Ð¼ золотом, приходьте " "наÑтупного Ñ‚Ð¸Ð¶Ð½Ñ Ð·Ð° добавкою\"." msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "ДоглÑдач млина оголошує:\n" "\"Мілорде, вибачте, але зараз немає золота. Будь лаÑка, приходьте наÑтупного " "тижнÑ\"." msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Ви знайшли покинутий Ñхрон.\n" "Розкопавши його, ви знаходите деÑкі реÑурÑи, заховані неподалік." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "Схрон давно занедбаний. Тут немає нічого цінного." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Ви ловите лепрекона, Ñкий нерозумно Ñпить Ñеред ÑÐºÑƒÐ¿Ñ‡ÐµÐ½Ð½Ñ Ñ‡Ð°Ñ€Ñ–Ð²Ð½Ð¸Ñ… грибів.\n" "Ð’ обмін на Ñвою Ñвободу він веде Ð²Ð°Ñ Ð´Ð¾ маленького горщика, наповненого " "дорогоцінними речами." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Ви знайшли чарівний Ñад, міÑце, де люблÑть гулÑти лепрекони та феї, але " "Ñьогодні тут нікого немає.\n" "Можливо, вам варто Ñпробувати ще раз наÑтупного тижнÑ." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Ви натраплÑєте на оÑтанки нещаÑного шукача пригод." msgid "Treasure" msgstr "Скарб" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Перебираючи подертий одÑг, ви знаходите %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Перебираючи подертий одÑг, ви нічого не знаходите." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Ви натраплÑєте на Ñтарий віз, залишений торговцем, Ñкий не доїхав до " "безпечної території." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "Ðа жаль, інші знайшли його першими Ñ– вагон порожній." msgid "Searching inside, you find the %{artifact}." msgstr "Пошукавши вÑередині, ви знаходите %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "УÑередині вагону ви знаходите чаÑтину й доÑÑ– неушкодженого вантажу." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Перебираючи уламки, ви знаходите деревину Ñ– трохи золота." msgid "You search through the flotsam, and find some wood." msgstr "Ви перебираєте уламки Ñ– знаходите трохи деревину." msgid "You search through the flotsam, but find nothing." msgstr "Ви нічого не знайшли Ñеред уламків." msgid "Shrine of the 1st Circle" msgstr "СвÑÑ‚Ð¸Ð½Ñ 1-го кола" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Ви натраплÑєте на невелику ÑвÑтиню, Ñку відвідує група адептів-початківців.\n" "Ð’ обмін на ваш захиÑÑ‚ вони погоджуютьÑÑ Ð½Ð°Ð²Ñ‡Ð¸Ñ‚Ð¸ Ð²Ð°Ñ Ð¿Ñ€Ð¾Ñтого заклинанню - " "'%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "СвÑÑ‚Ð¸Ð½Ñ 2-го кола" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Ви натраплÑєте на прикрашену ÑвÑтиню, Ñку відвідує група огрÑдних монахів.\n" "Ð’ обмін на ваш захиÑÑ‚ вони погоджуютьÑÑ Ð½Ð°Ð²Ñ‡Ð¸Ñ‚Ð¸ Ð²Ð°Ñ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½ÑŽ - '%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "СвÑÑ‚Ð¸Ð½Ñ 3-го кола" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Ви натраплÑєте на розкішну ÑвÑтиню, Ñку відвідує група верховних жерців.\n" "Ð’ обмін на ваш захиÑÑ‚ вони погоджуютьÑÑ Ð½Ð°Ð²Ñ‡Ð¸Ñ‚Ð¸ Ð²Ð°Ñ Ñкладного Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ - " "'%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Ðа жаль, тобі не виÑтачає мудроÑті, щоб зрозуміти Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ñ– ти не можеш " "його вивчити." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Ðа жаль, ви вже знаєте це заклинаннÑ, тож їм нема чого Ð²Ð°Ñ Ð±Ñ–Ð»ÑŒÑˆÐµ вчити." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Ðажаль, ви не маєте Книги Магії щоб запиÑати це заклÑттÑ." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Ви підходите до хижини Ñ– бачите відьму, Ñка вивчає Ñтаровинний фоліант про " "%{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Коли ви наближаєтеÑÑŒ, вона повертаєтьÑÑ Ñ– фокуÑує на тобі Ñвоє єдине ÑклÑне " "око.\n" "\"Ти вже знаєш вÑе, що заÑлуговуєш знати!\" - кричить відьма. \"РТЕПЕР " "ЗÐБИРÐЙСЯ З МОГО ДОМУ!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Коли ви наближаєтеÑÑŒ, вона повертаєтьÑÑ Ñ– говорить.\n" "\"Ти вже знаєш те, чого Ñ Ð¼Ð¾Ð³Ð»Ð° б тебе навчити. Я не можу допомогти тобі " "більше\"." msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Ð¡Ñ‚Ð°Ñ€Ð¾Ð´Ð°Ð²Ð½Ñ Ñ– безÑмертна відьма, що живе в хатині з пташиними лапками заміÑть " "опор, навчає Ð²Ð°Ñ %{skill} Ð´Ð»Ñ Ñвоїх влаÑних незбагненних цілей." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "Коли ви п'єте Ñолодку воду, то отримаєте удачу в наÑтупній битві." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Ви п'єте з зачарованого фонтану, але нічого не відбуваєтьÑÑ." msgid "You enter the faerie ring, but nothing happens." msgstr "Ви входите у кільце фей, але нічого не відбуваєтьÑÑ." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Увійшовши в міÑтичне кільце фей, ваша Ð°Ñ€Ð¼Ñ–Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼ÑƒÑ” удачу Ð´Ð»Ñ Ð½Ð°Ñтупної " "битви." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Ви знайшли Ñтародавній та обвітрений кам'Ñний ідол.\n" "ВважаєтьÑÑ, що він приноÑить удачу відвідувачам, але оÑкільки зірки вже " "поÑміхаютьÑÑ Ð²Ð°Ð¼, він нічого не робить." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Ви знайшли древнього кам'Ñного ідола, що вивітрюєтьÑÑ.\n" "Поцілунок з ним приноÑить удачу, що ви Ñ– робите. Камінь дуже холодний на " "дотик." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "РуÑалки мовчки заманюють Ð²Ð°Ñ Ð¿Ð¾Ð²ÐµÑ€Ð½ÑƒÑ‚Ð¸ÑÑ Ð¿Ñ–Ð·Ð½Ñ–ÑˆÐµ Ñ– знову отримати " "благоÑловеннÑ." msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Чарівна, заÑпокійлива краÑа РуÑалок доÑÑгає Ð²Ð°Ñ Ñ– вашого екіпажу.\n" "Лише на мить ви забуваєте про Ñвої турботи Ñ– наÑолоджуєтеÑÑ ÐºÑ€Ð°Ñою моменту.\n" "Чари руÑалок благоÑловлÑють Ð²Ð°Ñ Ð½Ð° додаткову удачу в наÑтупному бою." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Перед вами піраміда великого Ñ– древнього царÑ.\n" "У Ð²Ð°Ñ Ð²Ð¸Ð½Ð¸ÐºÐ°Ñ” ÑпокуÑа обшукати Ñ—Ñ— Ð·Ð°Ð´Ð»Ñ Ñкарбів, але вÑÑ– Ñтарі Ñ–Ñторії " "попереджають про Ñтрашні проклÑÑ‚Ñ‚Ñ Ñ– немертвих охоронців.\n" "Чи зважитеÑÑŒ на це?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Здолавши монÑтрів, ви розшифровуєте Ñтародавній гліф на Ñтіні, що розкриває " "таємницю Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Ðа жаль, у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” Книги Магії, щоб запиÑати заклинаннÑ." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Ðа жаль, вам не виÑтачає мудроÑті, щоб зрозуміти заклинаннÑ, Ñ– ви не можете " "його вивчити." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Перед вами піраміда великого та древнього царÑ.\n" "Рутинне доÑÐ»Ñ–Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑ”, що піраміда абÑолютно порожнÑ." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Ðапій з криниці повинен відновити ваші очки заклинань, але у Ð²Ð°Ñ Ð²Ð¶Ðµ " "макÑимум." msgid "A second drink at the well in one day will not help you." msgstr "Друге Ð¿Ð¸Ñ‚Ñ‚Ñ Ð· криниці за один день вам не допоможе." msgid "A drink from the well has restored your spell points to maximum." msgstr "Ðапій з криниці відновив ваші очки заклинань до макÑимуму." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Вибачте, пане, - каже командир Ñолдатів, - але ви вже знаєте вÑе, чого ми " "маємо Ð²Ð°Ñ Ð½Ð°Ð²Ñ‡Ð¸Ñ‚Ð¸\"." msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Солдати, що живуть у форті, навчають Ð²Ð°Ñ ÐºÑ–Ð»ÑŒÐºÐ¾Ð¼ новим оборонним прийомам." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Ви підійшли до табору найманців, Ñкі відпрацьовують Ñвою тактику. \"Ви " "занадто доÑвідчені Ð´Ð»Ñ Ð½Ð°Ñ\", - каже капітан найманців. \"Ми більше нічому " "не можемо навчити\"." msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Перед вами табір найманців, Ñкі відпрацьовують Ñвою тактику. Ðайманці " "вітають Ð²Ð°Ñ Ñ– ваші війÑька та запрошують Ð²Ð°Ñ Ð¿Ð¾Ñ‚Ñ€ÐµÐ½ÑƒÐ²Ð°Ñ‚Ð¸ÑÑ Ñ€Ð°Ð·Ð¾Ð¼ з ними." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Йди геть!\", - кричить знахар, - \"ти знаєш вÑе, що знаю Ñ\"." msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "ОркÑький знахар, що мешкає в хатині, поглибить ваші Ð·Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ магію, " "навчивши Ð²Ð°Ñ ÐºÐ¸Ð´Ð°Ñ‚Ð¸ каміннÑ, читати прикмети Ñ– розшифровувати хитроÑÐ¿Ð»ÐµÑ‚Ñ–Ð½Ð½Ñ " "курÑчих нутрощів." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Ви знайшли групу друїдів, Ñкі поклонÑютьÑÑ Ð² одній з їхніх дивних кам'Ñних " "Ñпоруд. Друїди мовчки відвертаютьÑÑ Ð²Ñ–Ð´ ваÑ, даючи зрозуміти, що їм нема " "чого Ð²Ð°Ñ Ð½Ð°Ð²Ñ‡Ð¸Ñ‚Ð¸." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Ви знайшли групу друїдів, Ñкі поклонÑютьÑÑ Ð² одній зі Ñвоїх дивних кам'Ñних " "Ñпоруд. Мовчки вони навчають Ð²Ð°Ñ Ð½Ð¾Ð²Ð¸Ð¼ ÑпоÑобам накладати заклинаннÑ." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Ви обережно наближаєтеÑÑŒ до міÑÑ†Ñ Ð¿Ð¾Ñ…Ð¾Ð²Ð°Ð½Ð½Ñ Ð´Ð°Ð²Ð½Ñ–Ñ… воїнів. Ви хочете " "обшукати могили?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Витративши кілька годин на обшук могил, ви нічого не знаходите. Такий " "мерзенний вчинок знижує бойовий дух вашої армії." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "ПіÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ð³Ð¸ над зомбі ви обшукуєте могили Ñ– дещо знаходите!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Гнилий оÑтов великого піратÑького ÐºÐ¾Ñ€Ð°Ð±Ð»Ñ Ð¼Ð¾Ñ‚Ð¾Ñ€Ð¾ÑˆÐ½Ð¾ Ñкрипить, коли його б'Ñ” " "об Ñкелі. Бажаєте обшукати уламки кораблÑ?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Перебираючи уламки кілька годин, ви нічого не знаходите. Таке жалюгідне " "дійÑтво знижує бойовий дух вашої армії." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "ПіÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ð³Ð¸ над привидами ви перебираєте уламки Ñ– щоÑÑŒ знаходите!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Б'ючиÑÑŒ об Ñкелі, гниючий оÑтов великого піратÑького ÐºÐ¾Ñ€Ð°Ð±Ð»Ñ Ð¼Ð¾Ñ‚Ð¾Ñ€Ð¾ÑˆÐ½Ð¾ " "Ñкрипить. Бажаєте обшукати корабель?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "ПіÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ð³Ð¸ над Ñкелетами ви перебираєте уламки Ñ– щоÑÑŒ знаходите!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Ваші люди бачать навігаційний буй, Ñкий підтверджує, що ви на правильному " "курÑÑ–." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Ваші люди помічають навігаційний буй, що підтверджує правильніÑть курÑу та " "піднімає їхній бойовий дух." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Ðапій в оазиÑÑ– оÑвіжає, але не приноÑить ніÑкої кориÑті. ÐžÐ°Ð·Ð¸Ñ Ð¼Ð¾Ð¶Ðµ знову " "допомогти, Ñкщо ви Ñпочатку пройдете битву." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Ковток води з оазиÑу наповнює ваші війÑька Ñилою та піднімає їм наÑтрій. " "Сьогодні ви можете помандрувати трохи далі." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Водопій оÑвіжає, але не приноÑить ніÑкої кориÑті. Водопій міг би знову " "допомогти, Ñкби ви Ñпершу пройшли битву." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Водопій наповнює ваші війÑька Ñилою Ñ– піднімає їм наÑтрій. Сьогодні ви " "можете помандрувати трохи далі." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "Двічі молитиÑÑ Ð¿ÐµÑ€ÐµÐ´ битвою не допоможе. ПовертайÑÑ Ð¿Ñ–ÑÐ»Ñ Ð±Ð¸Ñ‚Ð²Ð¸." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" "Ð’Ñ–Ð´Ð²Ñ–Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ñ…Ñ€Ð°Ð¼Ñƒ Ñ– молитва в ньому піднімає бойовий дух ваших Ñолдатів." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Ðа Ñходах альтанки з'ÑвлÑєтьÑÑ Ñтарий лицар. \"Пробач, мій пане, Ñ Ð½Ð°Ð²Ñ‡Ð¸Ð² " "тебе вÑього, що міг\"." msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Ðа Ñходах альтанки з'ÑвлÑєтьÑÑ Ñтарий лицар. \"Мій пане, Ñ Ð½Ð°Ð²Ñ‡Ñƒ Ð²Ð°Ñ Ð²Ñьому, " "що знаю аби допомогти у ваших мандрах\"." msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Ви врÑтували вцілілого піÑÐ»Ñ ÐºÐ¾Ñ€Ð°Ð±Ð»ÐµÑ‚Ñ€Ð¾Ñ‰Ñ– від неминучої Ñмерті у " "невблаганному океані. ВдÑчний, він каже: \"Я б дав вам артефакт у " "винагороду, але у Ð²Ð°Ñ Ð²Ð¶Ðµ повно Ñкарбів\"." msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Ви врÑтували людину, що зазнала корабельної аварії, від неминучої Ñмерті у " "невблаганному океані. ВдÑчний, він винагороджує за добрий вчинок, даруючи " "вам артефакт %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "Лепрекон пропонує вам %{art} за невелику плату %{gold} золота." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Лепрекон пропонує вам %{art} за невелику плату %{gold} золота та %{count} " "%{res}." msgid "Do you wish to buy this artifact?" msgstr "Бажаєте придбати цей артефакт?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Ви намагаєтеÑÑ Ð·Ð°Ð¿Ð»Ð°Ñ‚Ð¸Ñ‚Ð¸ лепрекону, але розумієте, що не можете Ñобі цього " "дозволити. Лепрекон тупотить ногою та ігнорує ваÑ." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Ображений вашою відмовою від його щедрої пропозиції, лепрекон тупотить ногою " "Ñ– ігнорує ваÑ." msgid "You've found the artifact: " msgstr "Ви знайшли артефакт: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Ви знайшли Ñкромне житло змарнілого відлюдника. Він каже, що готовий " "передати %{art} першій мудрій людині, Ñку зуÑтріне." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Ви натрапили на ÑпартанÑьке житло Ñолдата у відÑтавці. Він каже, що готовий " "передати %{art} першому Ñправжньому лідеру, Ñкого зуÑтріне." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Ви зуÑтріли незнайому людину в капелюÑÑ–, на Ñкому Ñидить Ñова. Він каже вам, " "що готовий подарувати %{art} за умови наÑвноÑті %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Ви натрапили на Ñтародавній артефакт. Коли ви Ñ‚ÑгнетеÑÑ Ð´Ð¾ нього, з кущів " "виÑкакує Ð·Ð³Ñ€Ð°Ñ Ñ€Ð¾Ð·Ð±Ñ–Ð¹Ð½Ð¸ÐºÑ–Ð² щоб захиÑтити вкрадену річ." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Через галÑвину ви бачите Ñтародавній артефакт. Ðа жаль, його охоронÑÑ” " "%{monster}, що живе неподалік. Ви хочете битиÑÑ Ð· %{monster} за артефакт?" msgid "Victorious, you take your prize, the %{art}." msgstr "Переможцю, тримай Ñвій приз %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "РозÑудливіÑть - краща чаÑтина доблеÑті Ñ– ви вирішуєте уникнути цієї битви " "Ñьогодні." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Витративши кілька годин виловлюючи Ñкриню з морÑ, ви відкриваєте Ñ—Ñ— та " "знаходите в ній %{gold} золотих монет." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Витративши кілька годин намагаючиÑÑŒ виловити Ñкриню з морÑ, ви відкриваєте " "Ñ—Ñ— Ñ– знаходите %{gold} золота Ñ– %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Витративши кілька годин намагаючиÑÑŒ виловити Ñкриню з морÑ, ви відкриваєте, " "а там порожньо." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "ПрочеÑавши міÑцевіÑть, ви натраплÑєте на Ñхованку зі Ñкарбами. Можете " "забрати золото Ñобі або роздати його ÑелÑнам за доÑвід. Бажаєте лишити " "золото Ñобі?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "ПрочеÑавши міÑцевіÑть, ви натраплÑєте на Ñкриню із %{gold} шматками золота." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "ПрочеÑавши міÑцевіÑть, ви натраплÑєте на заховану Ñкриню, в Ñкій лежить " "древній артефакт %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Ви натраплÑєте на пом'Ñту та потьмÑнілу лампу, що заÑтрÑгла глибоко в землі. " "Хочете потерти лампу?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Ви отримали контроль над крамницею міÑцевого алхіміка. Вона даватиме по " "%{count} одиниці ртуті щоднÑ." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Ви отримали контроль над ліÑопилкою. Вона даватиме по %{count} одиниці " "деревини на день." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Ви отримали контроль над рудною шахтою. Вона даватиме по %{count} одиниці " "руди на день." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Ви отримали контроль над Ñірчаною шахтою. Вона даватиме по %{count} одиниці " "Ñірки на день." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Ви отримали контроль над криÑталічною шахтою. Вона даватиме по %{count} " "одиниці криÑталів на день." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Ви отримали контроль над копальнею дорогоцінних каменів. Вона даватиме по " "%{count} одиниці Ñамоцвітів на день." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Ви отримали контроль над золотою шахтою. Вона даватиме по %{count} одиниці " "золота на день." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "МаÑк тепер під вашим контролем Ñ– вÑÑ– ваші кораблі Ñ‰Ð¾Ð´Ð½Ñ Ð¿Ð»Ð°Ð²Ð°Ñ‚Ð¸Ð¼ÑƒÑ‚ÑŒ далі." msgid "You gain control of a %{name}." msgstr "Ви отримуєте контроль над %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Ви підходите до покинутої золотої шахти. ЗдаєтьÑÑ, вона наÑелена привидами. " "Бажаєте увійти?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Ви перемагаєте Привидів Ñ– можете відновити роботу шахти." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Група %{monster}, що прагне більшої Ñлави, бажає приєднатиÑÑ Ð´Ð¾ ваÑ. Ви " "згодні?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "ÐаближаючиÑÑŒ до помешканнÑ, ви помічаєте, що тут нікого немає." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Ви обшукуєте руїни, але Медуз, Ñкі тут жили, вже немає. Можливо, наÑтупного " "Ñ‚Ð¸Ð¶Ð½Ñ Ñ—Ñ… буде більше." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Ви знайшли кілька медуз, що живуть у руїнах. Вони готові приєднатиÑÑ Ð´Ð¾ " "вашої армії за певну плату. Хочете найнÑти медуз?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Ви знайшли МіÑто на дереві. Ðа жаль, жодна з Фей, що мешкають там, не бажає " "приєднатиÑÑ Ð´Ð¾ армії. Може, наÑтупного тижнÑ." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "ДеÑкі Феї, що живуть у МіÑті на дереві, готові приєднатиÑÑ Ð´Ð¾ вашої армії за " "певну плату. Ви хочете найнÑти Фей?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Тут Ñтоїть порожній барвиÑтий фургон розбійників. Можливо, пізніше в ньому " "з'ÑвлÑтьÑÑ Ñ€Ð¾Ð·Ð±Ñ–Ð¹Ð½Ð¸ÐºÐ¸." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Віддалені звуки музики та Ñміху приваблюють Ð²Ð°Ñ Ð´Ð¾ барвиÑтого вагончика, в " "Ñкому живуть розбійники. Бажаєте, аби хтоÑÑŒ із розбійників приєднавÑÑ Ð´Ð¾ " "вашої армії?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Група пошарпаних наметів, що розвіваютьÑÑ Ð½Ð° піщаному вітрі, вабить ваÑ. " "Ðамети порожні. Можливо, пізніше тут буде більше кочівників." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Група пошарпаних наметів, що розвіваютьÑÑ Ð½Ð° піщаному вітрі, вабить ваÑ. " "Бажаєте, щоб хтоÑÑŒ із Кочівників приєднавÑÑ Ð´Ð¾ вашої подорожі?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Яма з грÑзюкою хвилину булькає, а потім заÑтигає." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Коли ви наближаєтеÑÑŒ до Ñми з булькаючою багнюкою, Ñ–Ñтоти починають вилазити " "Ñ– розташовуватиÑÑ Ð½Ð°Ð²ÐºÐ¾Ð»Ð¾ неї. Вони говорÑть водночаÑ: \"Матінка-Ð—ÐµÐ¼Ð»Ñ Ñ…Ð¾Ñ‡Ðµ " "запропонувати вам кілька Ñвоїх воїнів. Хочете завербувати Земних Елементалів?" "\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Ви входите у Ñпоруду з білокам'Ñних колон Ñ– не знаходите нічого." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Білі кам'Ñні Ñтовпи підтримують дах, що здіймаєтьÑÑ Ð´Ð¾ неба. Коли ви входите " "до Ñпоруди, мертве Ð¿Ð¾Ð²Ñ–Ñ‚Ñ€Ñ Ð·Ð·Ð¾Ð²Ð½Ñ– поÑтупаєтьÑÑ Ð¼Ñ–Ñцем вихровому пориву, Ñкий " "майже виштовхує Ð²Ð°Ñ Ð½Ð°Ð·Ð°Ð´. ПовітрÑний потік матеріалізуєтьÑÑ Ñƒ ледь помітну " "форму. ІÑтота запитує, що можна опиÑати лише Ñк гучний шепіт: \"Ðавіщо ти " "прийшов? Ти тут, щоб прикликати Ñили повітрÑ?\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "З лавового баÑейну до Ð²Ð°Ñ Ð½Ðµ вийшов жоден ВогнÑний Елементаль." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Під Ñпорудою, Ñка Ñлугує Ð´Ð»Ñ ÑƒÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚ÐµÐ¿Ð»Ð°, у вогнÑному баÑейні " "розплавленої лави переÑуваютьÑÑ Ð’Ð¾Ð³Ð½Ñні Елементалі. Група з них наближаєтьÑÑ " "до Ð²Ð°Ñ Ñ– пропонує Ñвої поÑлуги. Чи хотіли б ви завербувати ВогнÑних " "Елементалів?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Ðа мить у воді з'ÑвлÑєтьÑÑ Ð¾Ð±Ð»Ð¸Ñ‡Ñ‡Ñ, а потім зникає." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "КриÑталічні Ñпоруди відкидають тіні на невеликий дзеркальний баÑейн. Ви " "вдивлÑєтеÑÑŒ у баÑейн, а на Ð²Ð°Ñ Ð´Ð¸Ð²Ð¸Ñ‚ÑŒÑÑ Ð¾Ð±Ð»Ð¸Ñ‡Ñ‡Ñ, Ñке не Ñ” вашим влаÑним. " "Воно запитує: \"Чи хочеш ти звернутиÑÑ Ð´Ð¾ Ñили води?\"" msgid "This burial site is deathly still." msgstr "Це міÑце Ð¿Ð¾Ñ…Ð¾Ð²Ð°Ð½Ð½Ñ Ñмертельно нерухоме." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Ðеупокоєні духи давно загиблих воїнів, Ñкі шукають Ñвого оÑтаннього " "притулку, пропонують приєднатиÑÑ Ð´Ð¾ Ð²Ð°Ñ Ñƒ надії знайти Ñпокій. Бажаєте " "завербувати привидів?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "МіÑто мертвих порожнє від життÑ, але й порожнє від нежиттÑ. Можливо, ÑкіÑÑŒ " "немертві переюдуть Ñюди наÑтупного тижнÑ." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "ДеÑкі Лічі, що живуть тут, готові приєднатиÑÑ Ð´Ð¾ вашої армії за певну плату. " "Хочеш завербувати Лічів?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Ви знайшли руїни Ñтародавнього міÑта, Ñке тепер наÑелÑють виключно мерці. " "Будете обшукувати?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "ДеÑкі з уцілілих Лічів, вражені вашою перемогою над їхніми побратимами Ñ– " "пропонують приєднатиÑÑ Ð´Ð¾ Ð²Ð°Ñ Ð·Ð° певну винагороду. Хочете завербувати Лічів?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Ви знайшли один з тих моÑтів, під Ñкими так люблÑть жити тролі, але тут Ñ—Ñ… " "немає. Можливо, з'ÑвлÑтьÑÑ Ð½Ð°Ñтупного тижнÑ." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "ДеÑкі тролі, що живуть під моÑтом, воліють приєднатиÑÑ Ð´Ð¾ вашої армії, але " "за певну плату. Ви хочете завербувати тролів?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Тролі, що живуть під моÑтом, кидають вам виклик. Чи будете ви битиÑÑ Ð· ними?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Кілька тролів залишилиÑÑ, причаївшиÑÑŒ під моÑтом. Вони підходÑть до Ð²Ð°Ñ Ñ– " "пропонують приєднатиÑÑ Ð´Ð¾ вашого війÑька в ÑкоÑті найманців. Ви хочете " "купити тролів?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "Цього Ñ‚Ð¸Ð¶Ð½Ñ Ñƒ ДраконÑчому міÑті немає Драконів, готових приєднатиÑÑ Ð´Ð¾ ваÑ. " "Можливо, з'ÑвитьÑÑ Ð½Ð°Ñтупного тижнÑ." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "МіÑто Драконів готове запропонувати кілька драконів Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— армії за певну " "ціну. Ви бажаєте найнÑти драконів?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Ви Ñтоїте перед МіÑтом Драконів. МіÑцем, куди звичайні люди не мають права " "заходити. Ви хочете порушити це правило Ñ– викликати драконів на бій?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "ПіÑÐ»Ñ Ð¿ÐµÑ€ÐµÐ¼Ð¾Ð³Ð¸ над чемпіонами драконів, лідери міÑта погоджуютьÑÑ Ð½Ð°Ð´Ð°Ñ‚Ð¸ " "кілька драконів Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— армії за певну ціну. Бажаєте завербувати драконів?" msgid "From the observation tower, you are able to see distant lands." msgstr "З оглÑдової вежі можна побачити далекі землі." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Джерело наповнюєтьÑÑ Ð»Ð¸ÑˆÐµ раз на тиждень, а цього Ñ‚Ð¸Ð¶Ð½Ñ Ñ‚ÑƒÑ‚ вже хтоÑÑŒ був." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Ковток з джерела мав би подвоїти очки заклинань, проте у Ð²Ð°Ñ Ð²Ð¶Ðµ вдоÑталь." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Ковток з джерела наповнює вашу кров магією! Ви маєте вдвічі більше очок " "заклинань у запаÑÑ–." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Впізнавши ваÑ, дворецький відмовлÑєтьÑÑ Ð²Ð¿ÑƒÑтити ваÑ. \"ГоÑподар, - каже " "він, - не хоче бачити одного й того ж ÑƒÑ‡Ð½Ñ Ð´Ð²Ñ–Ñ‡Ñ–\"." msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Дворецький проводить Ð²Ð°Ñ Ð´Ð¾ гоÑÐ¿Ð¾Ð´Ð°Ñ€Ñ Ð±ÑƒÐ´Ð¸Ð½ÐºÑƒ. Він навчає Ð²Ð°Ñ Ñ‡Ð¾Ñ‚Ð¸Ñ€ÑŒÐ¾Ð¼ " "навичкам, Ñкими повинен володіти герой." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Дворецький відчинÑÑ” двері й оглÑдає Ð²Ð°Ñ Ð· ніг до голови. \"Ви недоÑтатньо " "відомі й дипломатичні, щоб Ð²Ð°Ñ Ð´Ð¾Ð¿ÑƒÑтили до мого гоÑподарÑ\", - пирхає він. " "\"Приходьте, коли вважатимете Ñебе гідним\"." msgid " and " msgstr " Ñ– " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Ð’ÑÑ– %{monsters}, Ñкі Ñ” у вашій армії, були натреновані бойовими майÑтрами " "форту. Тепер у вашій армії Ñ” %{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Ðезвичайний альÑÐ½Ñ Ð›ÑŽÐ´Ð¾Ð¶ÐµÑ€Ñ–Ð², Орків Ñ– Гномів пропонує тренувати (поліпшити) " "війÑько такого ж типу. Ðа жаль, у Ð²Ð°Ñ Ð· Ñобою немає жодного з них." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Ð’ÑÑ– ваші %{monsters} були покращені до %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Коваль, що працює на ливарному заводі, пропонує перекувати вÑÑŽ зброю " "пікінерів Ñ– мечників, Ñку йому приноÑÑть, із заліза на Ñталь. Він також " "каже, що знає процеÑ, Ñкий перетворить Залізних Големів на Ñталевих. Ðа " "жаль, у вашій армії немає жодного з цих війÑьк, тому він не може вам " "допомогти." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Капітан здивовано дивитьÑÑ Ð½Ð° Ð²Ð°Ñ Ñ– каже:\n" "\"У Ð²Ð°Ñ Ð²Ð¶Ðµ Ñ” вÑÑ– мапи, про Ñкі Ñ Ð·Ð½Ð°ÑŽ. Дайте мені Ñпокійно порибалити\"." msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Капітан у відÑтавці, Ñкий живе на відремонтованій рибальÑькій платформі, " "пропонує вам продати мапи морÑ, Ñкі він Ñклав у молоді роки, за 1000 " "золотих. Бажаєте купити мапи?" msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Капітан зітхає. \"У Ð²Ð°Ñ Ð½Ðµ виÑтачає грошей, еге ж? Ви ж не очікуєте, що Ñ " "віддам Ñвої мапи безкоштовно!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Ви натраплÑєте на обеліÑк, зроблений з каменю, Ñкого ніколи раніше не " "бачили. Ви пильно вдивлÑєтеÑÑŒ у нього, аж раптом гладка Ð¿Ð¾Ð²ÐµÑ€Ñ…Ð½Ñ " "перетворюєтьÑÑ Ð½Ð° напиÑ. ÐÐ°Ð¿Ð¸Ñ - це шматок загубленої Ñтародавньої мапи. " "Швидко перемалювавши його, Ð½Ð°Ð¿Ð¸Ñ Ð·Ð½Ð¸ÐºÐ°Ñ” так Ñамо неÑподівано, Ñк Ñ– з'ÑвивÑÑ." msgid "You have already been to this obelisk." msgstr "Ви вже відвідували цей обеліÑк." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "З вашим наближеннÑм дерево радіÑно розплющує очі. \"Я радий тебе бачити, мій " "учню. СподіваюÑÑ, мої Ð²Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð»Ð¸ тобі\"." msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Коли ви наближаєтеÑÑŒ, дерево в захваті розплющує очі. \"Ð, шукач пригод! " "Дозволь навчити тебе дечому з того, чого Ñ Ð½Ð°Ð²Ñ‡Ð¸Ð»Ð°ÑÑ Ð¿Ñ€Ð¾Ñ‚Ñгом Ñтоліть\"." msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Коли ви наближаєтеÑÑŒ, дерево в захваті розплющує очі." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"Ð, шукач пригод! Я буду радий навчити тебе дечому з того, чого Ñ Ð½Ð°Ð²Ñ‡Ð¸Ð²ÑÑ " "протÑгом Ñтоліть, вÑього за %{count} %{res}\"." msgid "(Just bury it around my roots.)" msgstr "(ПроÑто закопайте його навколо мого коріннÑ.)" msgid "Tears brim in the eyes of the tree." msgstr "О очах дерева з'ÑвлÑютьÑÑ Ñльози." msgid "\"I need %{count} %{res}.\"" msgstr "\"Мені потрібно %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "Воно шепче шморгаючи \"Приходь, коли зможеш мені заплатити.\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Серед дерев Ñидить Ñліпий провидець. ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви поÑÑните мету Ñвоєї " "подорожі, провидець активує Ñвою кришталеву кулю, дозволÑючи вам побачити " "Ñильні та Ñлабкі Ñторони ваших опонентів." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Вхід до печери темний, а з Ñ—Ñ— гирла доноÑитьÑÑ Ð½ÐµÐ¿Ñ€Ð¸Ñ”Ð¼Ð½Ð¸Ð¹ Ñірчаний запах. Ви " "зайдете?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "За винÑтком доказів Ñтрашної битви, печера порожнÑ." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Ви знаходите в печері могутнього Ñ– гротеÑкного демона. \"Сьогодні, - вигукує " "він, - ти будеш битиÑÑ Ñ– неодмінно помреш. Ðле Ñ Ð´Ð°Ð¼ тобі вибір Ñмерті. Ви " "можете битиÑÑ Ð·Ñ– мною, або ви можете битиÑÑ Ð· моїми Ñлугами. Ви віддаєте " "перевагу битиÑÑ Ð· моїми Ñлугами?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Демон вигукує Ñвій клич Ñ– атакує! ПіÑÐ»Ñ ÐºÐ¾Ñ€Ð¾Ñ‚ÐºÐ¾Ñ—, відчайдушної битви ви " "вбиваєте монÑтра Ñ– отримуєте %{exp} очок доÑвіду." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Демон вигукує Ñвій клич Ñ– атакує! ПіÑÐ»Ñ ÐºÐ¾Ñ€Ð¾Ñ‚ÐºÐ¾Ñ—, відчайдушної битви ви " "долаєте монÑтра Ñ– отримуєте %{exp} очок доÑвіду та %{count} золота." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Демон вигукує Ñвій клич Ñ– нападає! ПіÑÐ»Ñ ÐºÐ¾Ñ€Ð¾Ñ‚ÐºÐ¾Ñ—, відчайдушної битви ви " "долаєте монÑтра Ñ– знаходите %{art} в глибині печери." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Побачивши, що у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” %{count} золота, демон ріже Ð²Ð°Ñ ÐºÑ–Ð³Ñ‚Ñми. ОÑтаннє, " "що ви бачите - червоний туман." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Демон Ñтрибає на Ð²Ð°Ñ Ñ– вчепивÑÑ Ð¿Ð°Ð·ÑƒÑ€Ð°Ð¼Ð¸ у ваше горло ще до того, Ñк ви " "вÑтигли витÑгнути меча. \"Твоє Ð¶Ð¸Ñ‚Ñ‚Ñ - моє\", - каже він. \"Я продам його " "тобі за %{count} золота\"." msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "Здолавши Ñлуг демона, ви знайдете Ñхованку з %{count} золота." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Коли ви входите до Вежі Ðлхіміка, назуÑтріч вам шкутильгає Ñивий чоловік у " "коричневому плащі." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" "Він перевірÑÑ” вашу Ñумку Ñ– бачить, що ви маєте %{count} проклÑтий предмет." msgstr[1] "" "Він перевірÑÑ” вашу Ñумку Ñ– бачить, що ви маєте %{count} проклÑтих предмети." msgstr[2] "" "Він перевірÑÑ” вашу Ñумку Ñ– бачить, що ви маєте %{count} проклÑтий предметів." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "За %{gold} золотих алхімік вилучить його у ваÑ. Будете платити?" msgstr[1] "За %{gold} золотих алхімік вилучить Ñ—Ñ… у ваÑ. Будете платити?" msgstr[2] "За %{gold} золотих алхімік вилучить Ñ—Ñ… у ваÑ. Будете платити?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви погоджуєтеÑÑ Ð·Ð°Ð¿Ð»Ð°Ñ‚Ð¸Ñ‚Ð¸ запитувану Ñуму золота, алхімік " "хапає проклÑтий артефакт Ñ– кидає його в Ñвій магічний казан." msgstr[1] "" "ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви погоджуєтеÑÑ Ð·Ð°Ð¿Ð»Ð°Ñ‚Ð¸Ñ‚Ð¸ запитувану Ñуму золота, алхімік " "хапає вÑÑ– проклÑті артефакти Ñ– кидає Ñ—Ñ… у Ñвій магічний казан." msgstr[2] "" "ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк ви погоджуєтеÑÑ Ð·Ð°Ð¿Ð»Ð°Ñ‚Ð¸Ñ‚Ð¸ запитувану Ñуму золота, алхімік " "хапає вÑÑ– проклÑтих артефактів Ñ– кидає Ñ—Ñ… у Ñвій магічний казан." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Ви чуєте Ð³Ð¾Ð»Ð¾Ñ Ð·-за зачинених дверей: \"У Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтатньо золота, щоб " "заплатити за мої поÑлуги\"." msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "Ви чуєте Ð³Ð¾Ð»Ð¾Ñ Ð· виÑоти вежі: \"Йди геть! Я не можу тобі допомогти!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Головний конюх каже вам: \"У Ð²Ð°Ñ Ð¿Ñ€ÐµÐºÑ€Ð°Ñний кінь. БоюÑÑ, що ми не можемо " "дати вам кращого, але коні, на Ñких їде ваша кавалеріÑ, виглÑдають погано. У " "Ð½Ð°Ñ Ñ” багато тренованих бойових коней, Ñкі б дуже допомогли вашим вершникам. " "Я наполÑгаю, щоб ви Ñ—Ñ… взÑли\"." msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Коли ви підходите до Ñтайні, з'ÑвлÑєтьÑÑ Ð³Ð¾Ð»Ð¾Ð²Ð½Ð¸Ð¹ конюх, Ñкий веде " "прекраÑного бойового конÑ. \"Цей кінь допоможе вам приÑкорити вашу подорож. " "Ðа жаль, за тиждень він втомитьÑÑ. Ви також повинні дозволити мені дати " "кращих коней вашим наїзиника, їхні коні виглÑдають погано Ñ– Ñлабко\"." msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "До Ð²Ð°Ñ Ð¿Ñ–Ð´Ñ…Ð¾Ð´Ð¸Ñ‚ÑŒ головний конюх Ñ– каже: \"У Ð²Ð°Ñ Ð²Ð¶Ðµ Ñ” чудовий кінь та немає " "недоÑвідченої кавалерії, Ñкі б мали зиÑк з наших вишколених бойових коней\"." msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Коли ви підходите до Ñтайні, з'ÑвлÑєтьÑÑ Ð³Ð¾Ð»Ð¾Ð²Ð½Ð¸Ð¹ конюх, Ñкий веде " "прекраÑного бойового конÑ. \"Цей кінь допоможе вам приÑкорити вашу подорож. " "Ðа жаль, його витриваліÑть зменшитьÑÑ Ð²Ñ–Ð´ важкої їзди, тому ви повинні " "повернутиÑÑ Ð·Ð° Ñвіжим конем через тиждень. У Ð½Ð°Ñ Ñ‚Ð°ÐºÐ¾Ð¶ Ñ” багато чудових " "бойових коней, Ñкі могли б принеÑти кориÑть кінним воїнам, але у Ð²Ð°Ñ Ñ‚Ð°ÐºÐ¸Ð¼ " "нема\"." msgid "The Arena guards turn you away." msgstr "Охоронці Ðрени проганÑють ваÑ." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Ваша команда має заткнути вуха воÑком, перш ніж моторошна піÑÐ½Ñ Ñирен " "вÑтигне заманити Ñ—Ñ… у водÑну могилу." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Поки Ñирени Ñпівають Ñвою моторошну піÑню, вашій маленькій, рішучій армії " "вдаєтьÑÑ Ð¿Ð¾Ð´Ð¾Ð»Ð°Ñ‚Ð¸ Ð±Ð°Ð¶Ð°Ð½Ð½Ñ Ð¿Ñ–Ñ€Ð½ÑƒÑ‚Ð¸ з головою в море." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Моторошне Ð²Ð¸Ñ‚Ñ‚Ñ Ð»ÑƒÐ½Ð°Ñ” від Ñирен, Ñкі ÑидÑть на ÑкелÑÑ…. Багато членів вашої " "команди потраплÑють під Ñ—Ñ… чари Ñ– пірнають у воду, де тонуть. Ви Ñтали " "мудрішими за цей візит Ñ– отримали %{exp} доÑвіду." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "У Ñліпучому проÑві ÑміливоÑті ви вриваєтеÑÑ Ð´Ð¾ міÑцевої в'Ñзниці Ñ– " "звільнÑєте ув'Ñзненого там героÑ, Ñкий, натоміÑть, приÑÑгає на вірніÑть " "вашій Ñправі." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "У Ð²Ð°Ñ Ð²Ð¶Ðµ Ñ” %{count} героїв, Ñ– ви, на жаль, муÑите залишити в'ÑÐ·Ð½Ñ Ñƒ цій " "в'Ñзниці, щоб він мучивÑÑ Ð² агонії незліченну кількіÑть днів." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Ви заходите до хиткої хатини Ñ– розмовлÑєте з чарівником, Ñкий там живе. Він " "розповідає вам про близькі та далекі міÑцÑ, Ñкі можуть допомогти вам у ваших " "подорожах." msgid "This eye seems to be intently studying its surroundings." msgstr "ЗдаєтьÑÑ, це око уважно вивчає навколишній проÑтір." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "Ви натраплÑєте на велетенÑького СфінкÑа. Він лишаєтьÑÑ Ð½Ð° диво тихим." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "\"Я маю Ð´Ð»Ñ Ñ‚ÐµÐ±Ðµ загадку, - каже СфінкÑ. \"Відповідай правильно Ñ– будеш " "винагороджений. ВідповіÑи неправильно - будеш з'їдений. Ти приймаєш виклик?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Ð¡Ñ„Ñ–Ð½ÐºÑ Ð·Ð°Ð´Ð°Ñ” вам наÑтупну загадку:\n" "\n" "'%{riddle}'\n" "\n" "Ваша відповідь?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Ти вгадав неправильно\", - поÑміхаючиÑÑŒ, каже СфінкÑ. Він б'Ñ” тебе лапою, " "збиваючи на землю. Ще один удар - Ñвіт занурюєтьÑÑ Ð² темрÑву Ñ– ви більше " "нічого не бачите." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "ВиглÑдаючи дещо розчарованим, Ð¡Ñ„Ñ–Ð½ÐºÑ Ð·Ñ–Ñ‚Ñ…Ð°Ñ”. \"Ти відгадав мою загадку, тож " "оÑÑŒ Ñ‚Ð²Ð¾Ñ Ð½Ð°Ð³Ð¾Ñ€Ð¾Ð´Ð°. Ртепер йди геть.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Магічний бар'єр виÑочіє перед вами, перегороджуючи вам шлÑÑ…. Ðа арці " "напиÑано рунами,\n" "\"Скажи ключ Ñ– зможеш пройти\".\n" "Коли ви вимовлÑєте магічне Ñлово, бар'єр, що ÑвітитьÑÑ, розчинÑєтьÑÑ Ð² " "небутті." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Магічний бар'єр виÑочіє перед вами, перегороджуючи вам шлÑÑ…. Руни на арці " "Ñвідчать,\n" "\"Скажи ключ Ñ– зможеш пройти\".\n" "Ви говорите, але нічого не відбуваєтьÑÑ." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Ви входите до намету Ñ– бачите Ñтару жінку, Ñка вдивлÑєтьÑÑ Ð² чарівний " "камінь. Вона піднімає голову Ñ– каже,\n" "\"У Ñвоїх мандрах Ñ Ð±Ð°Ð³Ð°Ñ‚Ð¾ чого дізналаÑÑ Ð¿Ñ€Ð¾ таємну магію. Великий оракул " "навчив мене Ñвоєї майÑтерноÑті. Я знаю відповідь, Ñку ти шукаєш\"." msgid "No spell book is present." msgstr "ВідÑÑƒÑ‚Ð½Ñ ÐºÐ½Ð¸Ð³Ð° магії." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Це заклÑÑ‚Ñ‚Ñ ÐºÐ¾ÑˆÑ‚ÑƒÑ” %{mana} очок мани. У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” очок заклинань, тому ви не " "можете його заÑтоÑувати." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Це заклÑÑ‚Ñ‚Ñ ÐºÐ¾ÑˆÑ‚ÑƒÑ” %{mana} очок мани. У Ð²Ð°Ñ Ñ” лише %{point}, тому ви не " "можете його заÑтоÑувати." msgid "The spell was not found." msgstr "ЗаклÑÑ‚Ñ‚Ñ Ð½Ðµ знайдено." msgid "Only heroes can cast this spell." msgstr "Тільки герої можуть накладати це заклинаннÑ." msgid "This hero is not able to cast adventure spells." msgstr "Цей герой не здатен викориÑтовувати подорожні заклинаннÑ." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Ваш герой занадто втомивÑÑ, щоб заÑтоÑувати це заклÑÑ‚Ñ‚Ñ Ñьогодні. Спробуйте " "завтра." msgid "This spell cannot be cast on a boat." msgstr "Це Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð½Ðµ можна заÑтоÑувати на човні." msgid "This spell can only be cast near an ocean." msgstr "Це Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶Ð½Ð° наклаÑти лише Ð±Ñ–Ð»Ñ Ð¾ÐºÐµÐ°Ð½Ñƒ." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Ð‘Ñ–Ð»Ñ Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ¼Ð°Ñ” ні човнів ні океану, де це Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð¼Ð¾Ð³Ð»Ð¾ б Ñпрацювати." msgid "There are no boats available for this spell." msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð½ÐµÐ¼Ð° доÑтупних човнів." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "Ð‘Ñ–Ð»Ñ Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ¼Ð°Ñ” океану, то ж ви не можете викориÑтати це заклÑттÑ." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Ви не володієте жодним міÑтом або замком, Ñкі не зайнÑті героєм. Це " "Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð½Ðµ матиме ніÑкого ефекту." msgid "This hero is already in a town, so this spell will have no effect." msgstr "Цей герой вже перебуває у міÑті, то ж заклÑÑ‚Ñ‚Ñ Ð½Ðµ матиме ефекту." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Ðайближче міÑто - %{town}.\n" "\n" "Це міÑто зайнÑте вашим героєм %{hero}." msgid "This spell is already in effect." msgstr "Це Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð²Ð¶Ðµ діє." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Жоден з опонентів не має Ñ– не може мати під Ñвоїм командуваннÑм будь-Ñкого " "героÑ. Дане Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð½Ðµ матиме жодного ефекту." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Жоден з опонентів не має Ð³ÐµÑ€Ð¾Ñ Ð¿Ñ–Ð´ Ñвоїм командуваннÑм в цей чаÑ. Дане " "Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð½Ðµ матиме жодного ефекту." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Щоб заклÑÑ‚Ñ‚Ñ Ð’Ð¸Ð´Ñ–Ð½Ð½Ñ Ñпрацювало, ви повинні знаходитиÑÑ Ð½Ð° відÑтані %{count} " "від монÑтра." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Щоб наклаÑти це заклинаннÑ, ви повинні ÑтоÑти Ð±Ñ–Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ в шахту (ліÑопилки " "та алхімічні лабораторії не рахуютьÑÑ)." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Щоб наклаÑти це заклинаннÑ, Ñпершу маєте здолати привидів, Ñкі охоронÑють " "шахту." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Шахту вже охоронÑÑ” щонайменше Ñтільки елементалів, Ñкільки може згенерувати " "цей герой. ЗаÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ заклÑÑ‚Ñ‚Ñ Ð½Ðµ матиме жодного ефекту." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name} %{race} (Рівень %{level})" msgid "Random hero (Level %{level})" msgstr "Випадковий герой (Рівень %{level})" msgid "Random %{race} hero (Level %{level})" msgstr "Випадковий %{race} герой (Рівень %{level})" msgid "Hero race:" msgstr "ÐšÐ»Ð°Ñ Ð³ÐµÑ€Ð¾Ñ:" msgid "Are you sure you want to dismiss this Hero?" msgstr "Ви впевнені, що хочете звільнити цього героÑ?" # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Set custom Experience value. Current value is default." msgstr "Задати певний обÑÑг доÑвіду. Поточна кількіÑть Ñк уÑталено." # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Change Experience value. Right-click to reset to default value." msgstr "" "Ð’Ñтановити обÑÑг доÑвіду. Тицьніть правою кнопкою миші, щоб відновити " "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñк уÑталено." msgid "View Experience Info" msgstr "ПереглÑнути інформацію про доÑвід" # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Set custom Spell Points value. Current value is default." msgstr "Задати влаÑну кількіÑть очок заклинань. Поточний обÑÑг Ñк уÑталено." # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" "Змінити Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¾Ñ‡Ð¾Ðº заклинань. Тицьніть правою кнопкою миші, щоб відновити " "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñк уÑталено." msgid "Set Spell Points value" msgstr "Задати кількіÑть очок мани" msgid "View Spell Points Info" msgstr "ПереглÑнути інформацію про очки магії" msgid "Set patrol radius in tiles" msgstr "Ð’Ñтановити Ñ€Ð°Ð´Ñ–ÑƒÑ Ð¿Ð°Ñ‚Ñ€ÑƒÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð² Ñтільниках" msgid "Enter hero's name" msgstr "ВвеÑти ім'Ñ Ð³ÐµÑ€Ð¾Ñ" msgid "Click to change race." msgstr "ÐатиÑніть Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ раÑи." msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "РозоÑереджений бойовий Ñтрій розÑтавлÑÑ” війÑько Ð³ÐµÑ€Ð¾Ñ Ð·Ð³Ð¾Ñ€Ð¸ донизу Ð¿Ð¾Ð»Ñ " "бою, залишаючи між кожним воїном принаймні одне вільне міÑце." msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "Згуртований бойовий порÑдок збирає війÑько Ð³ÐµÑ€Ð¾Ñ Ð² центрі Ñвоєї чаÑтини Ð¿Ð¾Ð»Ñ " "бою." msgid "Exit Hero Screen" msgstr "Вийти з екрану героÑ" msgid "You cannot dismiss a hero in a castle" msgstr "Ви не можете звільнити Ð³ÐµÑ€Ð¾Ñ Ð² замку" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Ð—Ð²Ñ–Ð»ÑŒÐ½ÐµÐ½Ð½Ñ %{name} %{race} заборонено Ñценарієм" msgid "Dismiss %{name} the %{race}" msgstr "Звільнити %{name} %{race}" msgid "Show previous hero" msgstr "Показати попереднього героÑ" msgid "Show next hero" msgstr "Показати наÑтупного героÑ" msgid "Set army combat formation to 'Spread'" msgstr "РозоÑередити війÑька" msgid "Set army combat formation to 'Grouped'" msgstr "Згуртувати війÑька" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" "Ð’Ñтановити артефакти героÑ. Тицьніть правою кнопкою миші, щоб Ñкинути " "артефакт." msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" "Ð’Ñтановити вторинні навички героÑ. Тицьніть правою кнопкою миші, щоб Ñкинути " "вміннÑ." msgid "Set hero's Army. Right-click to reset unit." msgstr "" "Ð’Ñтановити армію героÑ. Тицьніть правою кнопкою миші, щоб Ñкинути юніта." # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" "Ð’Ñтановити портрет героÑ. Тицьніть правою кнопкою миші, щоб відновити " "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñк уÑталено." # By default - перекладають Ñк "За замовчуваннÑм", але це калька з ... мови. # ОлекÑандр Ðвраменко надає коректний переклад: "Ñк уÑталено" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" "Тицьніть Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ імені героÑ. Тицьніть правою кнопкою миші, щоб відновити " "Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñк уÑталено." msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" "Герой перебуває в режимі Ð¿Ð°Ñ‚Ñ€ÑƒÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð² радіуÑÑ– %{tiles} Ñот. Тицьніть, щоб " "вимкнути його." msgid "Click to enable hero's patrol mode." msgstr "Тицьніть Ð´Ð»Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¿Ð°Ñ‚Ñ€ÑƒÐ»ÑŽÐ²Ð°Ð½Ð½Ñ Ð³ÐµÑ€Ð¾Ñ”Ð¼." msgid "Blood Morale" msgstr "Кровожерлива" msgid "%{morale} Morale" msgstr "%{morale} моралі" msgid "%{luck} Luck" msgstr "%{luck} вдачі" msgid "Current Luck Modifiers:" msgstr "Поточні модифікатори удачі:" msgid "Current Morale Modifiers:" msgstr "Поточні модифікатори моралі:" msgid "Entire army is undead, so morale does not apply." msgstr "Ð’ÑÑ Ð°Ñ€Ð¼Ñ–Ñ - немертві, тому мораль не діє." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Поточний доÑвід %{exp1}.\n" " ÐаÑтупний рівень %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Рівень %{level}" msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} наразі має %{point} з макÑимальної кількоÑті %{max}. МакÑимальна " "кількіÑть очок заклинань у 10 разів перевищує рівень знань героÑ. Іноді " "герой може мати більше очок заклинань, ніж передбачено, завдÑки Ñпеціальним " "подіÑм." msgid "%{name1} meets %{name2}" msgstr "%{name1} зуÑтрічає %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Ворожі герої тепер повніÑтю ідентифіковані." msgid "Identify Hero" msgstr "Ідентифікувати ГероÑ" msgid "Select town to port to." msgstr "Оберіть міÑто, в Ñке переміÑтитиÑÑ." msgid "Town Portal" msgstr "МіÑький Портал" msgid "The creatures are willing to join us!" msgstr "ІÑтоти воліють приєднатиÑÑ Ð´Ð¾ ваÑ!" msgid "All the creatures will join us..." msgstr "УÑÑ– Ñ–Ñтоти приєднаютьÑÑ Ð´Ð¾ наÑ..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "%{count} Ñ–Ñтота приєднаєтьÑÑ Ð´Ð¾ наÑ..." msgstr[1] "%{count} Ñ–Ñтоти приєднаєтьÑÑ Ð´Ð¾ наÑ..." msgstr[2] "%{count} Ñ–Ñтот приєднаєтьÑÑ Ð´Ð¾ наÑ..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" " за плату в %{gold} золота." msgid "These weak creatures will surely flee before us." msgstr "Ці Ñлабкі ÑÑ‚Ð²Ð¾Ñ€Ñ–Ð½Ð½Ñ Ð½Ð°Ð¿ÐµÐ²Ð½Ð¾ тікатимуть від наÑ." msgid "I fear these creatures are in the mood for a fight." msgstr "БоюÑÑŒ ці Ñ–Ñтоти налаштовані на бій." msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Ð’Ð¼Ñ–Ð½Ð½Ñ Ð°Ñ‚Ð°ÐºÐ¸ Ð³ÐµÑ€Ð¾Ñ - це бонуÑ, що додаєтьÑÑ Ð´Ð¾ Ð²Ð¼Ñ–Ð½Ð½Ñ Ð°Ñ‚Ð°ÐºÐ¸ кожного воїна." msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Ð’Ð¼Ñ–Ð½Ð½Ñ Ð·Ð°Ñ…Ð¸Ñту Ð³ÐµÑ€Ð¾Ñ - це бонуÑ, Ñкий додаєтьÑÑ Ð´Ð¾ Ð²Ð¼Ñ–Ð½Ð½Ñ Ð·Ð°Ñ…Ð¸Ñту кожного " "воїна." msgid "The hero's spell power determines the duration or power of a spell." msgstr "Сила Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð³ÐµÑ€Ð¾Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡Ð°Ñ” триваліÑть або потужніÑть заклинаннÑ." msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Ð—Ð½Ð°Ð½Ð½Ñ Ð³ÐµÑ€Ð¾Ñ Ð²Ð¸Ð·Ð½Ð°Ñ‡Ð°ÑŽÑ‚ÑŒ, Ñкільки очок магії може мати герой. За звичайних " "обÑтавин герой обмежений 10 очками за рівень знань." msgid "Current Modifiers:" msgstr "Поточні Модифікатори:" msgid "skill|Basic" msgstr "Базовий" msgid "skill|Advanced" msgstr "ПроÑунутий" msgid "skill|Expert" msgstr "ЕкÑпертний" msgid "Pathfinding" msgstr "Пошук шлÑху" msgid "Archery" msgstr "Стрільба" msgid "Logistics" msgstr "ЛогіÑтика" msgid "Scouting" msgstr "Розвідка" msgid "Diplomacy" msgstr "ДипломатіÑ" msgid "Navigation" msgstr "ÐавігаціÑ" msgid "Leadership" msgstr "ЛідерÑтво" msgid "Wisdom" msgstr "МудріÑть" msgid "Mysticism" msgstr "МіÑтицизм" msgid "Ballistics" msgstr "БаліÑтика" msgid "Eagle Eye" msgstr "Орлиний зір" msgid "Necromancy" msgstr "ÐекромантіÑ" msgid "Estates" msgstr "Маєтки" msgid "Advanced Archery" msgstr "ПроÑнута Стрільба" msgid "Advanced Pathfinding" msgstr "ПроÑунутий Пошук шлÑху" msgid "Basic Archery" msgstr "Базова Стрільба" msgid "Basic Pathfinding" msgstr "Базовий Пошук шлÑху" msgid "Expert Pathfinding" msgstr "ЕкÑпертний Пошук шлÑху" msgid "Advanced Logistics" msgstr "ПроÑунута ЛогіÑтика" msgid "Basic Logistics" msgstr "Базова ЛогіÑтика" msgid "Basic Scouting" msgstr "Базова Розвідка" msgid "Expert Archery" msgstr "ЕкÑпертна Стрільба" msgid "Expert Logistics" msgstr "ЕкÑпертна ЛогіÑтика" msgid "Advanced Diplomacy" msgstr "ПроÑунута ДипломатіÑ" msgid "Advanced Scouting" msgstr "ПроÑунута Розвідка" msgid "Basic Diplomacy" msgstr "Базова ДипломатіÑ" msgid "Expert Diplomacy" msgstr "ЕкÑпертна ДипломатіÑ" msgid "Expert Scouting" msgstr "ЕкÑпертна Розвідка" msgid "Advanced Leadership" msgstr "ПроÑунуте ЛідерÑтво" msgid "Advanced Navigation" msgstr "ПроÑунута ÐавігаціÑ" msgid "Basic Leadership" msgstr "Базове ЛідерÑтво" msgid "Basic Navigation" msgstr "Базова ÐавігаціÑ" msgid "Expert Navigation" msgstr "ЕкÑпертна ÐавігаціÑ" msgid "Advanced Wisdom" msgstr "ПроÑунута МудріÑть" msgid "Basic Mysticism" msgstr "Базовий МіÑтицизм" msgid "Basic Wisdom" msgstr "Базова МудріÑть" msgid "Expert Leadership" msgstr "ЕкÑпертне ЛідерÑтво" msgid "Expert Wisdom" msgstr "ЕкÑпертна МудріÑть" msgid "Advanced Luck" msgstr "ПроÑунута Удача" msgid "Advanced Mysticism" msgstr "ПроÑунутий МіÑтицизм" msgid "Basic Luck" msgstr "Базова Удача" msgid "Expert Luck" msgstr "ЕкÑпертна Удача" msgid "Expert Mysticism" msgstr "ЕкÑпертний МіÑтицизм" msgid "Advanced Ballistics" msgstr "ПроÑунута БаліÑтика" msgid "Advanced Eagle Eye" msgstr "ПроÑунутий Орлиний Зір" msgid "Basic Ballistics" msgstr "Базова БаліÑтика" msgid "Basic Eagle Eye" msgstr "Базовий Орлиний Зір" msgid "Expert Ballistics" msgstr "ЕкÑпертна БаліÑтика" msgid "Advanced Necromancy" msgstr "ПроÑунута ÐекромантіÑ" msgid "Basic Estates" msgstr "Базові Маєтки" msgid "Basic Necromancy" msgstr "Базова ÐекромантіÑ" msgid "Expert Eagle Eye" msgstr "ЕкÑпертний Орлиний Зір" msgid "Expert Necromancy" msgstr "ЕкÑпертна ÐекромантіÑ" msgid "Advanced Estates" msgstr "ПроÑунуті Маєтки" msgid "Expert Estates" msgstr "ЕкÑпертні Маєтки" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} знижує штраф за Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ð¾ нерівній території на %{count} " "відÑотків." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} уÑуває штраф за Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ð¾ нерівній території." msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{skill} збільшує шкоду, що наноÑитьÑÑ ÑтрільцÑми Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} " "відÑотків та уÑуває %{penalty} відÑотків штрафу під Ñ‡Ð°Ñ Ð¿Ð¾Ñтрілів через " "перепони (напр. замкові Ñтіни)." msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "%{skill} підвищує одиниці руху Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} відÑотків." msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "%{skill} підвищує Ñ€Ð°Ð´Ñ–ÑƒÑ Ð¾Ð³Ð»Ñду Ð³ÐµÑ€Ð¾Ñ Ð½Ð° один квадрат." msgstr[1] "%{skill} підвищує Ñ€Ð°Ð´Ñ–ÑƒÑ Ð¾Ð³Ð»Ñду Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} квадрати." msgstr[2] "%{skill} підвищує Ñ€Ð°Ð´Ñ–ÑƒÑ Ð¾Ð³Ð»Ñду Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} квадратів." msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} дозволÑÑ” герою домовлÑтиÑÑ Ð· монÑтрами, що Ñлабші за його війÑько " "та знижує вартіÑть здачі." msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "" "Приблизно %{count} відÑотків Ñ–Ñтот можуть запропонувати приєднатиÑÑŒ до героÑ." msgid "All of the creatures may offer to join the hero." msgstr "Ð’ÑÑ– Ñ–Ñтоти можуть запропонувати приєднатиÑÑŒ до героÑ." msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "ВартіÑть капітулÑції зменшено до %{percent} відÑотків від загальної вартоÑті " "війÑьк, що Ñ” у армії." msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "%{skill} підвищує одиниці руху Ð³ÐµÑ€Ð¾Ñ Ð¿Ð¾ воді на %{count} відÑотків." msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} підвищує мораль війÑьк Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} дозволÑÑ” герою вчити заклÑÑ‚Ñ‚Ñ Ñ‚Ñ€ÐµÑ‚ÑŒÐ¾Ð³Ð¾ рівнÑ." msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} дозволÑÑ” герою вчити заклÑÑ‚Ñ‚Ñ Ñ‡ÐµÑ‚Ð²ÐµÑ€Ñ‚Ð¾Ð³Ð¾ рівнÑ." msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} дозволÑÑ” герою вчити заклÑÑ‚Ñ‚Ñ Ð¿'Ñтого рівнÑ." msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "%{skill} відновлює одну додаткову одиницю мани Ð³ÐµÑ€Ð¾Ñ Ñ‰Ð¾Ð´Ð½Ñ." msgstr[1] "%{skill} відновлює %{count} додаткові одиниці мани Ð³ÐµÑ€Ð¾Ñ Ñ‰Ð¾Ð´Ð½Ñ." msgstr[2] "%{skill} відновлює %{count} додаткових одиниць мани Ð³ÐµÑ€Ð¾Ñ Ñ‰Ð¾Ð´Ð½Ñ." msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} підвищує удачу Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} надає катапульті Ð³ÐµÑ€Ð¾Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¸Ð¹ ÑˆÐ°Ð½Ñ Ð²Ð»ÑƒÑ‡Ð¸Ñ‚Ð¸ та пошкодити Ñтіни " "замка." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} надає катапульті Ð³ÐµÑ€Ð¾Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ð¹ поÑтріл, підвищуючи ÑˆÐ°Ð½Ñ Ð²Ð»ÑƒÑ‡Ð¸Ñ‚Ð¸ " "й пошкодити Ñтіни замка кожним поÑтрілом." msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} надає катапульті Ð³ÐµÑ€Ð¾Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ð¹ поÑтріл Ñ– кожен з них автоматично " "руйнує будь-Ñку Ñтіну, окрім укріплень ЛицарÑького замка." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} дає герою %{count}% ÑˆÐ°Ð½Ñ Ð²Ð¸Ð²Ñ‡Ð¸Ñ‚Ð¸ заклÑÑ‚Ñ‚Ñ 1-го та 2-го рівнÑ, Ñкі " "ворог викориÑтовував у бою." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} дає герою %{count}% ÑˆÐ°Ð½Ñ Ð²Ð¸Ð²Ñ‡Ð¸Ñ‚Ð¸ заклÑÑ‚Ñ‚Ñ 3-го (або нижчого рівнÑ), " "Ñкі ворог викориÑтовував у бою." msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} дає герою %{count}% ÑˆÐ°Ð½Ñ Ð²Ð¸Ð²Ñ‡Ð¸Ñ‚Ð¸ заклÑÑ‚Ñ‚Ñ 4-го (або нижчого рівнÑ), " "Ñкі ворог викориÑтовував у бою." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} дозволÑÑ” повернути %{count} відÑотків вбитих у бою Ñ–Ñтот у виглÑді " "Скелетів." msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Герой вироблÑÑ” %{count} золота в день Ñк податковий прибуток з маєтків щоднÑ." msgid "Blue" msgstr "Синій" msgid "Green" msgstr "Зелений" msgid "Red" msgstr "Червоний" msgid "Yellow" msgstr "Жовтий" msgid "Orange" msgstr "Помаранчевий" msgid "Purple" msgstr "Ліловий" msgid "barrier|Aqua" msgstr "Бірюзовий" msgid "barrier|Blue" msgstr "Синій" msgid "barrier|Brown" msgstr "Коричневий" msgid "barrier|Gold" msgstr "Золотий" msgid "barrier|Green" msgstr "Зелений" msgid "barrier|Orange" msgstr "Помаранчевий" msgid "barrier|Purple" msgstr "Фіолетовий" msgid "barrier|Red" msgstr "Червоний" msgid "tent|Aqua" msgstr "Бірюзовий" msgid "tent|Blue" msgstr "Синій" msgid "tent|Brown" msgstr "Коричневий" msgid "tent|Gold" msgstr "Золотий" msgid "tent|Green" msgstr "Зелений" msgid "tent|Orange" msgstr "Помаранчевий" msgid "tent|Purple" msgstr "Фіолетовий" msgid "tent|Red" msgstr "Червоний" msgid "Experience" msgstr "ДоÑвід" msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "ДоÑвід дозволÑÑ” вашим героÑм отримувати рівні, підвищуючи їхні первинні та " "вторинні навички." msgid "Hero/Stats" msgstr "Герой/СтатиÑтика" msgid "Skills" msgstr "Ðавички" msgid "Town/Castle" msgstr "МіÑто/Замок" msgid "Garrison" msgstr "Гарнізон" msgid "Gold Per Day:" msgstr "Золота на день:" msgid "View Heroes." msgstr "ДивитиÑÑŒ героїв." msgid "Towns/Castles" msgstr "МіÑта/Замки" msgid "View Towns and Castles." msgstr "ПереглÑнути міÑта Ñ– замки" msgid "luck|Cursed" msgstr "ПроклÑта" msgid "luck|Awful" msgstr "Жахлива" msgid "luck|Bad" msgstr "Погана" msgid "luck|Normal" msgstr "Звичайна" msgid "luck|Good" msgstr "Добра" msgid "luck|Great" msgstr "Чудова" msgid "luck|Irish" msgstr "ІрландÑька" msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Іноді, негативна удача Ñпіткає війÑька Ð³ÐµÑ€Ð¾Ñ Ð² бою, через що їхні атаки " "завдають лише половину шкоди." msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "Ðейтральна удача означає, що війÑька Ð³ÐµÑ€Ð¾Ñ Ð½Ñ–ÐºÐ¾Ð»Ð¸ не матимуть вдалі або " "невдалі атаки по ворогу." msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "Позитивна удача інколи дарує війÑькам Ð³ÐµÑ€Ð¾Ñ Ð²Ð´Ð°Ð»Ñƒ атаку (подвійна Ñила) в " "бою." msgid "morale|Treason" msgstr "Зрада" msgid "morale|Awful" msgstr "Жахлива" msgid "morale|Poor" msgstr "Погана" msgid "morale|Normal" msgstr "Звичайна" msgid "morale|Good" msgstr "Добра" msgid "morale|Great" msgstr "Чудова" msgid "morale|Blood!" msgstr "Кров!" msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "Ðегативна мораль може призвеÑти до заклÑÐºÐ°Ð½Ð½Ñ Ð²Ñ–Ð¹Ñьк Ð³ÐµÑ€Ð¾Ñ Ñƒ бою." msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Ðейтральна мораль означає, що війÑька Ð³ÐµÑ€Ð¾Ñ Ð½Ñ–ÐºÐ¾Ð»Ð¸ не будуть обдаровані " "додатковими атаками або завмирати в бою." msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "Позитивна мораль може надати війÑькам Ð³ÐµÑ€Ð¾Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ð¹ хід в бою." msgid "Knight" msgstr "Лицар" msgid "Barbarian" msgstr "Варвар" msgid "Sorceress" msgstr "Чародійка" msgid "Warlock" msgstr "Чорнокнижник" msgid "Wizard" msgstr "Чарівник" msgid "Necromancer" msgstr "Ðекромант" msgid "Multi" msgstr "Мульти" msgid "doubleLined|Knight" msgstr "Лицар" msgid "doubleLined|Barbarian" msgstr "Варвар" msgid "doubleLined|Sorceress" msgstr "Чародійка" msgid "doubleLined|Warlock" msgstr "Чаклун" msgid "doubleLined|Wizard" msgstr "Чарівник" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Ðекро-\n" "мант" msgid "doubleLinedRace|Multi" msgstr "Мульти" msgid "doubleLinedRace|Random" msgstr "Випадковий" msgid "speed|Standing" msgstr "Ðепорушна" msgid "speed|Crawling" msgstr "Повзуча" msgid "speed|Very Slow" msgstr "Дуже Повільна" msgid "speed|Slow" msgstr "Повільна" msgid "speed|Average" msgstr "СереднÑ" msgid "speed|Fast" msgstr "Швидка" msgid "speed|Very Fast" msgstr "Стрімка" msgid "speed|Ultra Fast" msgstr "Шалена" msgid "speed|Blazing" msgstr "БлиÑкавична" msgid "speed|Instant" msgstr "Миттєва" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Білки" msgid "week|Rabbit" msgstr "Кролика" msgid "week|Gopher" msgstr "Ховрашка" msgid "week|Badger" msgstr "БорÑука" msgid "week|Rat" msgstr "Пацюка" msgid "week|Eagle" msgstr "Орла" msgid "week|Weasel" msgstr "ЛаÑки" msgid "week|Raven" msgstr "Ворона" msgid "week|Mongoose" msgstr "МангуÑта" msgid "week|Dog" msgstr "Собаки" msgid "week|Aardvark" msgstr "Тхора" msgid "week|Lizard" msgstr "Ящірки" msgid "week|Tortoise" msgstr "Черепахи" msgid "week|Hedgehog" msgstr "Їжака" msgid "week|Condor" msgstr "Кондора" msgid "week|Ant" msgstr "Мурахи" msgid "week|Grasshopper" msgstr "Коника" msgid "week|Dragonfly" msgstr "Бабки" msgid "week|Spider" msgstr "Павука" msgid "week|Butterfly" msgstr "Метелика" msgid "week|Bumblebee" msgstr "ДжмелÑ" msgid "week|Locust" msgstr "Сарани" msgid "week|Earthworm" msgstr "Дощового Черв'Ñка" msgid "week|Hornet" msgstr "ШешрнÑ" msgid "week|Beetle" msgstr "Жука" msgid "week|PLAGUE" msgstr "ЧУМИ" msgid "week|Unnamed" msgstr "Безіменний" msgid "Desert" msgstr "ПуÑтелÑ" msgid "Snow" msgstr "Сніг" msgid "Wasteland" msgstr "ПуÑтка" msgid "Beach" msgstr "ПлÑж" msgid "Lava" msgstr "Лава" msgid "Dirt" msgstr "Багнюка" msgid "Grass" msgstr "Трава" msgid "Ocean" msgstr "Океан" msgid "maps|Small" msgstr "Мала" msgid "maps|Medium" msgstr "СереднÑ" msgid "maps|Large" msgstr "Велика" msgid "maps|Extra Large" msgstr "Ðадвелика" msgid "maps|Custom Size" msgstr "КориÑтувацький Розмір" msgid "Ore Mine" msgstr "Рудна КопальнÑ" msgid "Sulfur Mine" msgstr "Сірчана КопальнÑ" msgid "Crystal Mine" msgstr "Кришталева КопальнÑ" msgid "Gems Mine" msgstr "ÐšÐ¾Ð¿Ð°Ð»ÑŒÐ½Ñ Ð¡Ð°Ð¼Ð¾Ñ†Ð²Ñ–Ñ‚Ñ–Ð²" msgid "Gold Mine" msgstr "Золота КопальнÑ" msgid "Mine" msgstr "КопальнÑ" msgid "Burma shave." msgstr "Здоровенькі були" msgid "Next sign 50 miles." msgstr "ÐаÑтупний знак за 50 миль." msgid "See Rock City." msgstr "Ðехай щаÑтить." msgid "This space for rent." msgstr "Це міÑце Ð´Ð»Ñ Ð¾Ñ€ÐµÐ½Ð´Ð¸." msgid "No object" msgstr "Порожнє міÑце" msgid "Alchemist Lab" msgstr "Ðлхімічна ЛабораторіÑ" msgid "Sign" msgstr "Вказівник" msgid "Buoy" msgstr "Буй" msgid "Skeleton" msgstr "Скелет" msgid "Daemon Cave" msgstr "Печера Демона" msgid "Treasure Chest" msgstr "Скринька зі Скарбом" msgid "Faerie Ring" msgstr "Коло Фей" msgid "Campfire" msgstr "Вогнище" msgid "Fountain" msgstr "Фонтан" msgid "Gazebo" msgstr "Ðльтанка" msgid "Genie Lamp" msgstr "Лампа Джина" msgid "Archer's House" msgstr "Дім Лучників" msgid "Goblin Hut" msgstr "ГоблінÑька Хатина" msgid "Dwarf Cottage" msgstr "Хатинка Гнома" msgid "Peasant Hut" msgstr "СелÑнÑька Хата" msgid "Stables" msgstr "Стайні" msgid "Alchemist's Tower" msgstr "Вежа Ðлхіміка" msgid "Event" msgstr "ПодіÑ" msgid "Dragon City" msgstr "МіÑто Драконів" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "МаÑк" msgstr[1] "МаÑк" msgstr[2] "МаÑк" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "ВодÑне КолеÑо" msgstr[1] "ВодÑні КолеÑа" msgstr[2] "ВодÑні КолеÑа" msgid "Monster" msgstr "МонÑтр" msgid "Obelisk" msgstr "ОбеліÑк" msgid "Oasis" msgstr "Оаза" msgid "Resource" msgstr "РеÑурÑ" msgid "Sawmill" msgstr "Тартак" msgid "Oracle" msgstr "Оракул" msgid "Shrine of the First Circle" msgstr "CвÑÑ‚Ð¸Ð½Ñ 1-го Кола" msgid "Shipwreck" msgstr "Уламки КораблÑ" msgid "Sea Chest" msgstr "МорÑький Сундук" msgid "Desert Tent" msgstr "ПуÑтельний Ðамет" msgid "Stone Liths" msgstr "Моноліт" msgid "Wagon Camp" msgstr "Табір з Возів" msgid "Hut of the Magi" msgstr "Хатина Мага" msgid "Whirlpool" msgstr "Водоверть" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "ВітрÑк" msgstr[1] "ВітрÑки" msgstr[2] "ВітрÑки" msgid "Mermaid" msgstr "РуÑалка" msgid "Boat" msgstr "Човен" msgid "Random Ultimate Artifact" msgstr "Випадковий Унікальний Ðртефакт" msgid "Random Artifact" msgstr "Випадковий Ðртефакт" msgid "Random Resource" msgstr "Випадковий РеÑурÑ" msgid "Random Monster" msgstr "Випадковий МонÑтр" msgid "Random Town" msgstr "Випадкове МіÑто" msgid "Random Castle" msgstr "Випадковий Замок" msgid "Eye of the Magi" msgstr "Око Магів" msgid "Random Monster - weak" msgstr "Випадковий МонÑтр - Ñлабкий" msgid "Random Monster - medium" msgstr "Випадковий МонÑтр - Ñередній" msgid "Random Monster - strong" msgstr "Випадковий МонÑтр - Ñильний" msgid "Random Monster - very strong" msgstr "Випадковий МонÑтр - могутній" msgid "Hero" msgstr "Герой" msgid "Nothing Special" msgstr "Ðічого ОÑобливого" msgid "Mossy Rock" msgstr "Моховита ÑкелÑ" msgid "Watch Tower" msgstr "Вартова Вежа" msgid "Tree House" msgstr "Будинок на Дереві" msgid "Tree City" msgstr "МіÑто на Дереві" msgid "Ruins" msgstr "Руїни" msgid "Fort" msgstr "Форт" msgid "Abandoned Mine" msgstr "Покинута ШтольнÑ" msgid "Sirens" msgstr "Сирени" msgid "Standing Stones" msgstr "СтоÑчі Камені" msgid "Idol" msgstr "Ідол" msgid "Tree of Knowledge" msgstr "Дерево Знань" msgid "Witch Doctor's Hut" msgstr "Хатина ЗнахарÑ" msgid "Temple" msgstr "Храм" msgid "Hill Fort" msgstr "Форт на Пагорбі" msgid "Halfling Hole" msgstr "Ðора ÐапівроÑликів" msgid "Mercenary Camp" msgstr "Табір Ðайманців" msgid "Shrine of the Second Circle" msgstr "CвÑÑ‚Ð¸Ð½Ñ 2-го Кола" msgid "Shrine of the Third Circle" msgstr "CвÑÑ‚Ð¸Ð½Ñ 3-го Кола" msgid "City of the Dead" msgstr "МіÑто Мертвих" msgid "Sphinx" msgstr "СфінкÑ" msgid "Wagon" msgstr "Віз" msgid "Tar Pit" msgstr "СмолÑна Яма" msgid "Artesian Spring" msgstr "ÐртезіанÑьке Джерело" msgid "Troll Bridge" msgstr "Тролиний МіÑÑ‚" msgid "Watering Hole" msgstr "Джерело" msgid "Witch's Hut" msgstr "Хатина Відьми" msgid "Xanadu" msgstr "Занду" msgid "Lean-To" msgstr "Схрон" msgid "Magellan's Maps" msgstr "Мапи Магеллана" msgid "Flotsam" msgstr "Уламки" msgid "Derelict Ship" msgstr "Покинутий Корабель" msgid "Shipwreck Survivor" msgstr "Уцілілий з КораблÑ" msgid "Bottle" msgstr "ПлÑшка" msgid "Magic Well" msgstr "Чарівна КриницÑ" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Чарівний Сад" msgstr[1] "Чарівні Сади" msgstr[2] "Чарівних Садів" msgid "Observation Tower" msgstr "ОглÑдова Вежа" msgid "Freeman's Foundry" msgstr "ЛиварнÑ" msgid "Reefs" msgstr "Рифи" msgid "Volcano" msgstr "Вулкан" msgid "Flowers" msgstr "Квіти" msgid "Rock" msgstr "СкелÑ" msgid "Water Lake" msgstr "Озеро" msgid "Mandrake" msgstr "Мандрагора" msgid "Dead Tree" msgstr "Мертве Дерево" msgid "Stump" msgstr "Пень" msgid "Crater" msgstr "Кратер" msgid "Cactus" msgstr "КактуÑ" msgid "Mound" msgstr "Курган" msgid "Dune" msgstr "Дюна" msgid "Lava Pool" msgstr "Лавовий БаÑейн" msgid "Shrub" msgstr "Кущі" msgid "Barrow Mounds" msgstr "Могильні Кургани" msgid "Random Artifact - Treasure" msgstr "Випадковий артефакт - Скарб" msgid "Random Artifact - Minor" msgstr "Випадковий артефакт - Малий" msgid "Random Artifact - Major" msgstr "Випадковий артефакт - Великий" msgid "Barrier" msgstr "Бар'єр" msgid "Traveller's Tent" msgstr "Ðамет Мандрівника" msgid "Jail" msgstr "Ð’'ÑзницÑ" msgid "Fire Summoning Altar" msgstr "Вівтар Виклику Вогню" msgid "Air Summoning Altar" msgstr "Вівтар Виклику ПовітрÑ" msgid "Earth Summoning Altar" msgstr "Вівтар Виклику Землі" msgid "Water Summoning Altar" msgstr "Вівтар Виклику Води" msgid "Swampy Lake" msgstr "БолотиÑте озеро" msgid "Frozen Lake" msgstr "Замерзле озеро" msgid "randomRace|level 1 creatures" msgstr "Ñ–Ñтоти 1-го рівнÑ" msgid "randomRace|level 2 creatures" msgstr "Ñ–Ñтоти 2-го рівнÑ" msgid "randomRace|level 3 creatures" msgstr "Ñ–Ñтоти 3-го рівнÑ" msgid "randomRace|level 4 creatures" msgstr "Ñ–Ñтоти 4-го рівнÑ" msgid "randomRace|level 5 creatures" msgstr "Ñ–Ñтоти 5-го рівнÑ" msgid "randomRace|level 6 creatures" msgstr "Ñ–Ñтоти 6-го рівнÑ" msgid "Unknown Monsters" msgstr "Ðевідомі монÑтри" msgid "Unknown Monster" msgstr "Ðевідомий монÑтр" msgid "Peasant" msgstr "CелÑнин" msgid "Peasants" msgstr "CелÑни" msgid "Archer" msgstr "Лучник" msgid "Archers" msgstr "Лучники" msgid "Ranger" msgstr "Рейнджер" msgid "Rangers" msgstr "Рейнджери" msgid "Pikeman" msgstr "Пікенер" msgid "Pikemen" msgstr "Пікенери" msgid "Veteran Pikeman" msgstr "Пікенер-ветеран" msgid "Veteran Pikemen" msgstr "Пікенери-ветерани" msgid "Swordsman" msgstr "Мечник" msgid "Swordsmen" msgstr "Мечники" msgid "Master Swordsman" msgstr "МайÑтер-мечник" msgid "Master Swordsmen" msgstr "МайÑтри-мечники" msgid "Cavalries" msgstr "КавалеріÑ" msgid "Cavalry" msgstr "КавалериÑÑ‚" msgid "Champion" msgstr "Чемпіон" msgid "Champions" msgstr "Чемпіони" msgid "Paladin" msgstr "Паладин" msgid "Paladins" msgstr "Паладини" msgid "Crusader" msgstr "ХреÑтоноÑець" msgid "Crusaders" msgstr "ХреÑтоноÑці" msgid "Goblin" msgstr "Гоблін" msgid "Goblins" msgstr "Гобліни" msgid "Orc" msgstr "Орк" msgid "Orcs" msgstr "Орки" msgid "Orc Chief" msgstr "Вождь Орків" msgid "Orc Chiefs" msgstr "Вожді Орків" msgid "Wolf" msgstr "Вовк" msgid "Wolves" msgstr "Вовки" msgid "Ogre" msgstr "Огр" msgid "Ogres" msgstr "Огри" msgid "Ogre Lord" msgstr "Лорд Огрів" msgid "Ogre Lords" msgstr "Лорди Огрів" msgid "Troll" msgstr "Троль" msgid "Trolls" msgstr "Тролі" msgid "War Troll" msgstr "Бойовий Троль" msgid "War Trolls" msgstr "Бойові Тролі" msgid "Cyclopes" msgstr "Циклопи" msgid "Cyclops" msgstr "Циклоп" msgid "Sprite" msgstr "ФеÑ" msgid "Sprites" msgstr "Феї" msgid "Dwarf" msgstr "Гном" msgid "Dwarves" msgstr "Гноми" msgid "Battle Dwarf" msgstr "Бойовий Гном" msgid "Battle Dwarves" msgstr "Бойові Гноми" msgid "Elf" msgstr "Ельф" msgid "Elves" msgstr "Ельфи" msgid "Grand Elf" msgstr "Вищий Ельф" msgid "Grand Elves" msgstr "Вищі Ельфи" msgid "Druid" msgstr "Друїд" msgid "Druids" msgstr "Друїди" msgid "Greater Druid" msgstr "Старший Друїд" msgid "Greater Druids" msgstr "Старші Друїди" msgid "Unicorn" msgstr "Єдиноріг" msgid "Unicorns" msgstr "Єдинороги" msgid "Phoenix" msgstr "ФенікÑ" msgid "Phoenixes" msgstr "ФенікÑи" msgid "Centaur" msgstr "Кентавр" msgid "Centaurs" msgstr "Кентаври" msgid "Gargoyle" msgstr "ГоргульÑ" msgid "Gargoyles" msgstr "Горгульї" msgid "Griffin" msgstr "Грифон" msgid "Griffins" msgstr "Грифони" msgid "Minotaur" msgstr "Мінотавр" msgid "Minotaurs" msgstr "Мінотаври" msgid "Minotaur King" msgstr "Король Мінотаврів" msgid "Minotaur Kings" msgstr "Королі Мінотаврів" msgid "Hydra" msgstr "Гідра" msgid "Hydras" msgstr "Гідри" msgid "Green Dragon" msgstr "Зелений Дракон" msgid "Green Dragons" msgstr "Зелені Дракони" msgid "Red Dragon" msgstr "Червоний Дракон" msgid "Red Dragons" msgstr "Червоні Дракони" msgid "Black Dragon" msgstr "Чорний Дракон" msgid "Black Dragons" msgstr "Чорні Дракони" msgid "Halfling" msgstr "ÐапівроÑлик" msgid "Halflings" msgstr "ÐапівроÑлики" msgid "Boar" msgstr "Кабан" msgid "Boars" msgstr "Кабани" msgid "Iron Golem" msgstr "Залізний Голем" msgid "Iron Golems" msgstr "Залізні Големи" msgid "Steel Golem" msgstr "Сталевий Голем" msgid "Steel Golems" msgstr "Сталеві Големи" msgid "Roc" msgstr "Птах Рух" msgid "Rocs" msgstr "Птахи Рух" msgid "Mage" msgstr "Маг" msgid "Magi" msgstr "Маги" msgid "Archmage" msgstr "Ðрхімаг" msgid "Archmagi" msgstr "Ðрхімаги" msgid "Giant" msgstr "Гігант" msgid "Giants" msgstr "Гіганти" msgid "Titan" msgstr "Титан" msgid "Titans" msgstr "Титани" msgid "Skeletons" msgstr "Скелети" msgid "Zombie" msgstr "Зомбі" msgid "Zombies" msgstr "Зомбі" msgid "Mutant Zombie" msgstr "Зомбі-мутант" msgid "Mutant Zombies" msgstr "Зомбі-мутанти" msgid "Mummies" msgstr "Мумії" msgid "Mummy" msgstr "МуміÑ" msgid "Royal Mummies" msgstr "КоролівÑькі Мумії" msgid "Royal Mummy" msgstr "КоролівÑька МуміÑ" msgid "Vampire" msgstr "Вампір" msgid "Vampires" msgstr "Вампіри" msgid "Vampire Lord" msgstr "Лорд Вампірів" msgid "Vampire Lords" msgstr "Лорди Вампірів" msgid "Lich" msgstr "Ліч" msgid "Liches" msgstr "Лічі" msgid "Power Lich" msgstr "Могутній Ліч" msgid "Power Liches" msgstr "Могутні Лічі" msgid "Bone Dragon" msgstr "КіÑÑ‚Ñний Дракон" msgid "Bone Dragons" msgstr "КіÑÑ‚Ñні Дракони" msgid "Rogue" msgstr "Розбійник" msgid "Rogues" msgstr "Розбійники" msgid "Nomad" msgstr "Кочівник" msgid "Nomads" msgstr "Кочівники" msgid "Ghost" msgstr "Привид" msgid "Ghosts" msgstr "Привиди" msgid "Genie" msgstr "Джин" msgid "Genies" msgstr "Джини" msgid "Medusa" msgstr "Медуза" msgid "Medusas" msgstr "Медузи" msgid "Earth Elemental" msgstr "ЗемлÑний Елементаль" msgid "Earth Elementals" msgstr "ЗемлÑні Елементалі" msgid "Air Elemental" msgstr "ПовітрÑний Елементаль" msgid "Air Elementals" msgstr "ПовітрÑні Елементалі" msgid "Fire Elemental" msgstr "ВогнÑний Елементаль" msgid "Fire Elementals" msgstr "ВогнÑні Елементалі" msgid "Water Elemental" msgstr "Водний Елементаль" msgid "Water Elementals" msgstr "Водні Елементалі" msgid "Random Monsters" msgstr "Випадкові МонÑтри" msgid "Random Monster 1" msgstr "Випадковий МонÑтр 1" msgid "Random Monsters 1" msgstr "Випадкові МонÑтри 1" msgid "Random Monster 2" msgstr "Випадковий МонÑтр 2" msgid "Random Monsters 2" msgstr "Випадкові МонÑтри 2" msgid "Random Monster 3" msgstr "Випадковий МонÑтр 3" msgid "Random Monsters 3" msgstr "Випадкові МонÑтри 3" msgid "Random Monster 4" msgstr "Випадковий МонÑтр 4" msgid "Random Monsters 4" msgstr "Випадкові МонÑтри 4" msgid "Double shot" msgstr "Подвійний поÑтріл" # Клітина - це Ñтруктурно функціональна Ð¾Ð´Ð¸Ð½Ð¸Ñ†Ñ Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð¼Ñƒ. Ðе підходить # Клітка - металева конÑÑ‚Ñ€ÑƒÐºÑ†Ñ–Ñ Ð°Ð±Ð¾ в анатомії грудна клітка тощо. Теж не підходить # Стільник або Ñота - шеÑтигранна фігура. msgid "2-hex monster" msgstr "2-Ñтільниковий монÑтр" msgid "Double strike" msgstr "Подвійний удар" msgid "Double damage to Undead" msgstr "Подвійна шкода немертвим" msgid "% magic resistance" msgstr "% опору магії" msgid "Immune to Mind spells" msgstr "Імунітет до заклинань Розуму" msgid "Immune to Elemental spells" msgstr "Імунітет до заклинань Елементалей" msgid "Immune to Fire spells" msgstr "Імунітет до заклинань Вогню" msgid "Immune to Cold spells" msgstr "Імунітет до заклинань Холоду" msgid "Immune to " msgstr "Імунітет до " msgid "% immunity to %{spell} spell" msgstr "% імунітету до %{spell} заклинань" msgid "% damage from Elemental spells" msgstr "% шкоди від Елементальних заклинань" msgid "% damage from %{spell} spell" msgstr "% шкоди від %{spell} заклинаннÑ" msgid "% chance to Dispel beneficial spells" msgstr "% шанÑу знÑти позитивні чари" msgid "% chance to Paralyze" msgstr "% шанÑу паралізувати" msgid "% chance to Petrify" msgstr "% шанÑу закам'Ñніти" msgid "% chance to Blind" msgstr "% шанÑу оÑліпити" msgid "% chance to Curse" msgstr "% шанÑу проклÑÑти" msgid "% chance to cast %{spell} spell" msgstr "% chance to cast %{spell} spell" msgid "HP regeneration" msgstr "Відновлює здоров'Ñ" msgid "Two hexes attack" msgstr "Ðтакує два клітинки" msgid "Flyer" msgstr "Літаючий" msgid "Always retaliates" msgstr "Завжди наноÑить контрудар" msgid "Attacks all adjacent enemies" msgstr "Ðтакує вÑÑ–Ñ… ворогів поруч" msgid "No melee penalty" msgstr "ВідÑутній штраф в рукопашному бою" msgid "Dragon" msgstr "Дракон" msgid "Undead" msgstr "Ðемертві" msgid "No enemy retaliation" msgstr "Без ворожої помÑти" msgid "HP drain" msgstr "ВиÑмоктує життÑ" msgid "Cloud attack" msgstr "Ðтака по площі" msgid "Decreases enemy's morale by " msgstr "Зменшити ворожу мораль на " msgid "% chance to halve enemy" msgstr "% ÑˆÐ°Ð½Ñ Ð·Ð¼ÐµÐ½ÑˆÐ¸Ñ‚Ð¸ чиÑельніÑть ворога вдвічі" msgid "Soul Eater" msgstr "Пожирач Душ" msgid "Elemental" msgstr "Елементаль" msgid "No Morale" msgstr "Мораль відÑутнÑ" #, fuzzy msgid "Earth creature" msgstr "ÐайнÑти Ñтворінь" #, fuzzy msgid "Air creature" msgstr "ÐайнÑти Ñтворінь" #, fuzzy msgid "Fire creature" msgstr "ÐайнÑти Ñтворінь" #, fuzzy msgid "Water creature" msgstr "Озеро" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% шкоди від ВогнÑних заклинань" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% шкоди від Холодових заклинань" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Знімає вÑÑ– заклÑÑ‚Ñ‚Ñ Ð· уÑÑ–Ñ… Ñ–Ñтот." #, fuzzy msgid "Double damage from Air creatures" msgstr "Подвійна шкода немертвим" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% шкоди від ВогнÑних заклинань" #, fuzzy msgid "Double damage from Water creatures" msgstr "Знімає вÑÑ– заклÑÑ‚Ñ‚Ñ Ð· уÑÑ–Ñ… Ñ–Ñтот." msgid "Lightning" msgstr "БлиÑкавка" msgid "% immunity to " msgstr "% імунітету до " msgid "% damage from " msgstr "% шкоди від " msgid "The three Anduran artifacts magically combine into one." msgstr "Три артефакти Ðндурана магічним чином поєднуютьÑÑ Ð² один." msgid "View Spells" msgstr "ПереглÑнути заклинаннÑ" msgid "View %{name} Info" msgstr "ПереглÑнути інформацію по %{name}" msgid "Move %{name}" msgstr "ПереміÑтити %{name}" msgid "Cannot move the Spellbook" msgstr "Ðеможливо переміÑтити книгу заклинань" msgid "This item can't be traded." msgstr "Цю річ не підлÑгає продажу." msgid "Invalid Artifact" msgstr "ÐедійÑний артефакт" msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} підвищує Ð·Ð½Ð°Ð½Ð½Ñ Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Book of Knowledge" msgstr "Легендарна Книга Знань" msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} підвищує навичку атаки Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Sword of Dominion" msgstr "Легендарний Меч ПануваннÑ" msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} підвищує навичку захиÑту Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Cloak of Protection" msgstr "Легендарний Плащ ЗахиÑту" msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} збільшує Ñилу магії Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "Ultimate Wand of Magic" msgstr "Легендарна Паличка Магії" msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "%{name} підвищує навички атаки та захиÑту Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} кожну." msgid "Ultimate Shield" msgstr "Легендарний Щит" msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "%{name} збільшує Ñилу магії та Ð·Ð½Ð°Ð½Ð½Ñ Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} кожне." msgid "Ultimate Staff" msgstr "Легендарний ПоÑох" msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} збільшує кожну головну навичку Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} пунктів." msgid "Ultimate Crown" msgstr "Легендарна Корона" msgid "Golden Goose" msgstr "Золотий ГуÑак" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} дає прибуток у розмірі %{count} золота на день." msgid "Arcane Necklace of Magic" msgstr "Таємниче намиÑто магії" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Ð’Ñ€Ñтувавши чародійку з проклÑтої гробниці, вона винагороджує ваш героїзм " "вишуканим коштовним намиÑтом." msgid "Caster's Bracelet of Magic" msgstr "Магічний браÑлет заклинателÑ" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Під Ñ‡Ð°Ñ Ð¿Ð¾ÑˆÑƒÐºÑ–Ð² у завалах обваленої шахти ви звільнÑєте групу гномів, Ñкі " "опинилиÑÑ Ð² паÑтці. ВдÑчний ватажок дарує вам золотий браÑлет." msgid "Mage's Ring of Power" msgstr "Магічний ПерÑтень МогутноÑті" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Відчайдушний крик болю приводить Ð²Ð°Ñ Ð´Ð¾ Кентавра, що потрапив у паÑтку. Ви " "звільнÑєте його, Ñ– він дарує вам маленький мішечок. Спорожнивши його, ви " "знаходите Ñліпучий, прикрашений коштовним каміннÑм перÑтень." msgid "Witch's Broach of Magic" msgstr "ВідьомÑька магічна брошка" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "ПорÑд з оÑтанками Ñпаленої відьми лежить краÑива протÑжка, вигадливого " "дизайну. ÐаблизившиÑÑŒ до трупа з обережніÑтю, ви додаєте брошку до Ñвого " "інвентарю." msgid "Medal of Valor" msgstr "Медаль за Відвагу" msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} підвищує мораль війÑьк Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Звільнивши благородну леді з лещат злого володарÑ, ви отримуєте Медаль за " "Відвагу від королівÑького герольда." msgid "Medal of Courage" msgstr "Медаль за мужніÑть" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Ð’Ñ€Ñтувавши хлопчика від жорÑтокої зграї Вовків, ви повертаєте його до " "батьківÑького маєтку. ВдÑчний дворÑнин нагороджує Ð²Ð°Ñ Ð¼ÐµÐ´Ð°Ð»Ð»ÑŽ за хоробріÑть." msgid "Medal of Honor" msgstr "Медаль за ЧеÑть" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "ПіÑÐ»Ñ Ð·Ð²Ñ–Ð»ÑŒÐ½ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð½Ñ†ÐµÑи ÑуÑіднього королівÑтва із лабетів підлих " "работорговців, вона нагороджує Ð²Ð°Ñ ÐœÐµÐ´Ð°Ð»Ð»ÑŽ за ЧеÑть." msgid "Medal of Distinction" msgstr "Медаль за відзнаку" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Позбавивши ÑільÑьку міÑцевіÑть від огидного Мінотавра, Ñкий розважавÑÑ Ñ‚Ð¸Ð¼, " "що поїдав шлÑхетних лицарів, ви отримаєте медаль \"За відзнаку\"." msgid "Fizbin of Misfortune" msgstr "Фізбін нещаÑÑ‚Ñ" msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} Ñильно знижує мораль війÑьк Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Ви ÑпотикаєтеÑÑ Ð¾Ð± медаль, що лежить уздовж порожньої дороги. Додавши медаль " "до Ñвого інвентарю, ви уÑвідомлюєте, що отримали небажаний Фізбін ÐещаÑÑ‚Ñ, " "Ñкий значно знижує бойовий дух вашої армії." msgid "Thunder Mace of Dominion" msgstr "Громова Булава ПануваннÑ" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Під Ñ‡Ð°Ñ Ð½ÐµÑподіваного шторму блиÑкавка вдарÑÑ” у дерево, розколовши його. " "Ð’Ñередині ви знаходите загадкову булаву." msgid "Armored Gauntlets of Protection" msgstr "Броньована Ð ÑƒÐºÐ°Ð²Ð¸Ñ†Ñ Ð—Ð°Ñ…Ð¸Ñту" msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} підвищує захиÑÑ‚ Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Ви зуÑтрічаєтеÑÑŒ із ÑумнозвіÑним Чорним Лицарем! ПіÑÐ»Ñ Ð²Ð¸Ñнажливого " "поєдинку, що закінчивÑÑ Ð²Ð½Ñ–Ñ‡Ð¸ÑŽ, Лицар з поваги пропонує вам пару броньованих " "рукавичок." msgid "Defender Helm of Protection" msgstr "Шолом ЗахиÑника" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Золотий відблиÑк привертає вашу увагу. ПридивившиÑÑŒ уважніше, ви знаходите " "золотого шолома, що був Ñхований під кущем." msgid "Giant Flail of Dominion" msgstr "ВелетенÑький молот пануваннÑ" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Ðезграбний велетень убив Ñебе влаÑним ціпом. Знаючи, що ви чудово володієте " "цією зброєю, ви впевнено забираєте ефектний ціпок у вбитого велетнÑ." msgid "Ballista of Quickness" msgstr "БаліÑта ШвидкоÑті" msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "%{name} надає катапульті Ð³ÐµÑ€Ð¾Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¸Ð¹ поÑтріл у кожному раунді під Ñ‡Ð°Ñ " "облоги." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "ПрогулюючиÑÑŒ руїнами Ñтародавнього обнеÑеного мурами міÑта, ви знаходите " "знарÑÐ´Ð´Ñ Ð¹Ð¾Ð³Ð¾ Ñ€ÑƒÐ¹Ð½ÑƒÐ²Ð°Ð½Ð½Ñ - ретельно виготовлену баліÑту." msgid "Stealth Shield of Protection" msgstr "Ðезримий Щит ЗахиÑту" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Кам'Ñна ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð¾Ñ—Ð½Ð° тримає Ñрібного щита. Щойно ви забираєте щит, ÑÑ‚Ð°Ñ‚ÑƒÑ " "розпорошуєтьÑÑ Ð½Ð° пил." msgid "Dragon Sword of Dominion" msgstr "ДраконÑчий Меч ПануваннÑ" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Поки ви йдете вузькою Ñтежкою, кущ неподалік неÑподівано Ñпалахує вогнем. " "Перед вашими очима поÑтає образ вродливої жінки. Вона проÑÑ‚Ñгає вам чудового " "меча." msgid "Power Axe of Dominion" msgstr "Силова Сокира ПануваннÑ" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Ви бачите Ñрібну Ñокиру, глибоко занурену у землю. ПіÑÐ»Ñ ÐºÑ–Ð»ÑŒÐºÐ¾Ñ… невдалих " "Ñпроб ваших воїнів вийнÑти Ñ—Ñ—, ви міцно хапаєтеÑÑŒ за руків'Ñ Ñокири, та без " "зуÑиль виÑмикуєте Ñ—Ñ—." msgid "Divine Breastplate of Protection" msgstr "БожеÑтвений Ðагрудник ЗахиÑту" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Банда Розбійників копирÑаєтьÑÑ Ñƒ речах загиблих воїнів. ВідлÑкуючи " "мародерів, ви помічаєте, що Розбійники не помітили чудовий нагрудник." msgid "Minor Scroll of Knowledge" msgstr "Малий Сувій Знань" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Перед вами з'ÑвлÑєтьÑÑ Ð»ÐµÐ²Ñ–Ñ‚ÑƒÑŽÑ‡Ð¸Ð¹ ÑклÑний футлÑÑ€ із Ñувоєм, що лежить на " "підÑтилці з червоного окÑамиту. Від доторку футлÑÑ€ відкриваєтьÑÑ, а Ñувій " "лине до ваших проÑÑ‚Ñгнутих рук." msgid "Major Scroll of Knowledge" msgstr "Великий Сувій Знань" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Відвідавши міÑцевого мудрецÑ, ви поÑÑнюєте йому мету вашої подорожі. " "ПокопирÑавшиÑÑŒ у мішку, він витÑгає пожовклий Ñувій та проÑÑ‚Ñгає його вам." msgid "Superior Scroll of Knowledge" msgstr "Вищий Ñувій знань" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Ви проходите повз оÑтанок Ñтародавньої друїдки. З-поміж пожовклих від чаÑу " "кіÑток визирають пошарпані Ñкладки Ñ—Ñ— мантії. Обшукуючи мантію, ви знаходите " "захований у Ñкладках Ñувій." msgid "Foremost Scroll of Knowledge" msgstr "Древній Сувій ЗнаннÑ" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Пожовклі від чаÑу та понівечені кіÑтки визирають з-поміж пошарпаних Ñкладок " "мантії мертвого Друїда. Обшукуючи мантію, ви знаходите захований у ній Ñувій." msgid "Endless Sack of Gold" msgstr "ÐеÑкінченний мішок золота" msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} забезпечує %{count} в день." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Маленький лепрекон веÑело танцює навколо чарівного мішка. Побачивши, що ви " "наближаєтеÑÑŒ, він зупинÑєтьÑÑ Ð½Ð° півдорозі. Маленький чоловічок люто кричить " "Ñ– тупотить ногою, розчинÑючиÑÑŒ у повітрі. Пам'Ñтаючи Ñлова Ñтарого леприкона " "\"Хто знайшов, той влаÑник\", ви хапаєте мішок Ñ– йдете геть." msgid "Endless Bag of Gold" msgstr "ÐеÑкінченна Ñумка золота" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Знатна жінка, Ñка відділилаÑÑ Ð²Ñ–Ð´ Ñвоїх попутників, проÑить Ð²Ð°Ñ Ð¿Ñ€Ð¾ " "допомогу. Провівши Ñ—Ñ— додому, вона винагороджує Ð²Ð°Ñ Ð¼Ñ–ÑˆÐºÐ¾Ð¼, наповненим " "золотом." msgid "Endless Purse of Gold" msgstr "ÐеÑкінченний золотий гаманець" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "У Ñвоїх мандрах ви знаходите шкірÑний гаманець, наповнений золотом, Ñкий " "колиÑÑŒ належав великому королю-воїну, що мав здатніÑть перетворювати на " "золото будь-Ñкий неживий предмет." msgid "Nomad Boots of Mobility" msgstr "Чоботи Кочівника" msgid "The %{name} increase the hero's movement on land." msgstr "%{name} підвищує здатніÑть переÑÑƒÐ²Ð°Ð½Ð½Ñ Ð³ÐµÑ€Ð¾ÑŽ по Ñуходолу." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Кочівник-торговець шукає захиÑту від племені Гоблінів. За вашу допомогу він " "дає вам пару вишуканих чобіт, зроблених з найм'Ñкішої шкіри. ПридивившиÑÑŒ, " "ви помічаєте вражаюче Ñтаровинне Ñ€Ñ–Ð·ÑŒÐ±Ð»ÐµÐ½Ð½Ñ Ð½Ð° шкірі." msgid "Traveler's Boots of Mobility" msgstr "Чоботи Мандрівника" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Знайшовши пару прикрашених біÑером та зроблених з найкращої та найм'Ñкішої " "шкіри чобіт, ви дÑкуєте невідомому добродію та кладете чоботи до Ñвого " "інвентарÑ." msgid "Lucky Rabbit's Foot" msgstr "ЩаÑлива кролÑча лапка" msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} підвищує удачу армії Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Мандрівний купець пропонує вам кролÑчу лапку з блиÑкучого ÑріблÑÑтого хутра " "Ð´Ð»Ñ Ð±ÐµÐ·Ð¿ÐµÑ‡Ð½Ð¾Ð³Ð¾ переходу. Торговець поÑÑнює, що таліÑман збільшить вашу удачу " "в бою." msgid "Golden Horseshoe" msgstr "Золота підкова" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Єдиноріг, що потрапив у паÑтку, злÑкано Ñкиглить. Бурмочучи заÑпокійливі " "Ñлова, ви звільнÑєте його. Пирхнувши Ñ– тупнувши переднім копитом, вона мчить " "геть. ДивлÑчиÑÑŒ вниз, ви бачите золоту підкову." msgid "Gambler's Lucky Coin" msgstr "ЩаÑлива монета гравцÑ" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Ви захопили в полон біÑа, Ñкий тероризував регіон. Ð’ обмін на Ñвоє " "Ð·Ð²Ñ–Ð»ÑŒÐ½ÐµÐ½Ð½Ñ Ð²Ñ–Ð½ винагороджує Ð²Ð°Ñ Ð¼Ð°Ð³Ñ–Ñ‡Ð½Ð¾ÑŽ монетою." msgid "Four-Leaf Clover" msgstr "Конюшина чотирилиÑта" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "ПоÑеред ділÑнки мертвої та Ñухої роÑлинноÑті ви, на Ñвій подив, знаходите " "здорову зелену чотирилиÑту конюшину." msgid "True Compass of Mobility" msgstr "Справжній ÐºÐ¾Ð¼Ð¿Ð°Ñ Ð¼Ð¾Ð±Ñ–Ð»ÑŒÐ½Ð¾Ñті" msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} підвищує дальніÑть руху герою Ñуходолом та морем." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Старий чоловік, Ñкий називає Ñебе винахідником, проÑить Ð²Ð°Ñ Ð²Ð¸Ð¿Ñ€Ð¾Ð±ÑƒÐ²Ð°Ñ‚Ð¸ його " "оÑтанній винахід. Потім він дає вам компаÑ." msgid "Sailor's Astrolabe of Mobility" msgstr "ÐÑтролÑÐ±Ñ–Ñ Ð¼Ð¾Ð±Ñ–Ð»ÑŒÐ½Ð¾Ñті морÑка" msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} збільшує дальніÑть руху Ð³ÐµÑ€Ð¾Ñ Ð¼Ð¾Ñ€ÐµÐ¼." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Старого морÑького капітана катують огри. Ви Ñ€Ñтуєте його, а натоміÑть він " "нагороджує Ð²Ð°Ñ Ð´Ð¸Ð²Ð¾Ð²Ð¸Ð¶Ð½Ð¸Ð¼ інÑтрументом Ð´Ð»Ñ Ð²Ð¸Ð¼Ñ–Ñ€ÑŽÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñтані до зірки." msgid "Evil Eye" msgstr "Лихе Око" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} зменшує вартіÑть заклинань проклÑÑ‚Ñ‚Ñ Ð²Ð´Ð²Ñ–Ñ‡Ñ–." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Зазирнувши до напівзруйнованої хатини, ви знаходите Ñкелет давно померлої " "відьми. ДоÑÐ»Ñ–Ð´Ð¶ÐµÐ½Ð½Ñ Ð¾Ñтанків виÑвлÑÑ” ÑклÑне око, що обертаєтьÑÑ Ð²Ñередині " "порожнього черепа." msgid "Enchanted Hourglass" msgstr "Зачарований піÑочний годинник" msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "%{name} подовжує триваліÑть заклÑть Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} ходів." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "ÐеÑподіваний поворот ландшафту призводить до того, що ви опинÑєтеÑÑŒ поÑеред " "жахливої Ñцени: Стерв'Ñтники обнишпорюють наÑлідки жахливої битви. Під Ñ‡Ð°Ñ " "побіжного оглÑду решток ви знаходите зачарований піÑочний годинник." msgid "Gold Watch" msgstr "Золотий Годинник" msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} подвоює ефективніÑть заклинань гіпнозу героÑ." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "У нагороду за те, що ви витÑгли його віз із кювету, мандрівний продавець " "зіль дарує вам \"чарівний\" золотий годинник. Сам того не підозрюючи, " "годинник Ñправді чарівний." msgid "Skullcap" msgstr "Тюбетейка" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} вдвічі зменшує вартіÑть вÑÑ–Ñ… заклинань, що впливають на ÑвідоміÑть." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Коротка зупинка в неймовірному ÑільÑькому заїжджому дворі призводить до " "обміну грошима, Ñ–ÑторіÑми Ñ–, випадково, багажем. У новому рюкзаку ви " "знаходите чарівну тюбетейку." msgid "Ice Cloak" msgstr "Льодовий плащ" msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} вдвічі зменшує шкоду отриману війÑьками Ð³ÐµÑ€Ð¾Ñ Ð²Ñ–Ð´ заклинань льоду." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Ðа панічний крик дівчини, що потрапила в біду, ви виÑвлÑєте молоду жінку, " "Ñка тікає від голодного ведмедÑ. Ви вчаÑно вбиваєте звіра, а вдÑчна " "Ñ‡Ð°Ñ€Ñ–Ð²Ð½Ð¸Ñ†Ñ Ð¿Ð»ÐµÑ‚Ðµ з ведмежої шкури чарівний плащ." msgid "Fire Cloak" msgstr "ВогнÑний плащ" msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} вдвічі зменшує шкоду отриману війÑьками Ð³ÐµÑ€Ð¾Ñ Ð²Ñ–Ð´ заклинань вогню." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Ви потрапили на бій між некромантом Ñ– паладином. Ðекромант вражає паладина " "вогнÑною кулею, ÑтавлÑчи його на коліна. Діючи швидко, ви вÑтигаєте вбити " "нечиÑть до оÑтаннього удару. ВдÑчний паладин віддає вам вогнÑний плащ, Ñкий " "його врÑтував." msgid "Lightning Helm" msgstr "БлиÑкавичний шолом" msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} вдвічі знижує шкоду отримувану війÑьками Ð³ÐµÑ€Ð¾Ñ Ð²Ñ–Ð´ заклинань " "блиÑкавки." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Мандрівний реміÑник, Ñкому потрібні припаÑи, пропонує вам шолом із " "зображеннÑм блиÑкавки на верхівці в обмін на їжу та воду. З цікавоÑті ви " "погоджуєтеÑÑŒ, а згодом дізнаєтеÑÑŒ, що шолом чарівний." msgid "Evercold Icicle" msgstr "Вічно холодна бурулька" msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} забезпечує нанеÑÐµÐ½Ð½Ñ ÑˆÐºÐ¾Ð´Ð¸ льодÑними заклÑттÑми Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} " "відÑотків більше ворожим війÑькам." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Бурулька, що витримує Ñпеку полуденного ÑонцÑ, привертає вашу увагу. " "Заінтриговані, ви відламуєте Ñ—Ñ— Ñ– виÑвлÑєте, що вона не тане у вашій руці." msgid "Everhot Lava Rock" msgstr "Вічно гарÑчий лавовий камінь" msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} підвищує нанеÑÐµÐ½Ð½Ñ ÑˆÐºÐ¾Ð´Ð¸ вогнÑними заклÑттÑми Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} " "відÑотків більше ворожим війÑькам." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Ваші мандри приводÑть Ð²Ð°Ñ Ð´Ð¾ племені мавпоподібних Ñ–Ñтот, Ñкі викориÑтовують " "чарівний лавовий камінь, що ніколи не оÑтигає, Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¿Ð°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð²Ð¾Ð³Ð½Ð¸Ñ‰. Ви " "жалієте Ñ—Ñ… Ñ– навчаєте добувати вогонь за допомогою палиць. Вважаючи Ð²Ð°Ñ " "богом, мавпи віддають вам Ñвій камінь." msgid "Lightning Rod" msgstr "БлиÑкавковідвід" msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "The %{name} підвищує нанеÑÐµÐ½Ð½Ñ ÑˆÐºÐ¾Ð´Ð¸ від заклÑть блиÑкавки Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} " "відÑотків більше ворожим війÑькам." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Перечікуючи грозу, блиÑкавка влучає у громовідвід ÑуÑіднього котеджу, Ñкий " "плавитьÑÑ Ñ– падає на землю. Однак кінчик громовідводу залишаєтьÑÑ " "неушкодженим Ñ– змушує ваше волоÑÑÑ Ñтавати дибки, коли ви торкаєтеÑÑŒ його. " "Хм..." msgid "Snake-Ring" msgstr "Зміїний перÑтень" msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "The %{name} вдвічі зменшує вартіÑть уÑÑ–Ñ… заклинань благоÑÐ»Ð¾Ð²ÐµÐ½Ð½Ñ Ð³ÐµÑ€Ð¾Ñ." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Ви знайшли перÑтень дивної форми на пальці давно померлого мандрівника. " "ПерÑтень Ñхожий на змію, що куÑає влаÑний хвіÑÑ‚." msgid "Ankh" msgstr "Ðнк" msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "The %{name} подвоює ефективніÑть уÑÑ–Ñ… заклинань воÑкреÑÑ–Ð½Ð½Ñ Ñ‚Ð° Ð¾Ð¶Ð¸Ð²Ð»ÐµÐ½Ð½Ñ " "героÑ." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Сильний буревій відкриває вхід до заÑипаної гробниці. Ваше розÑÐ»Ñ–Ð´ÑƒÐ²Ð°Ð½Ð½Ñ " "показує, що Ð³Ñ€Ð¾Ð±Ð½Ð¸Ñ†Ñ Ð²Ð¶Ðµ була пограбована, але злодії в темрÑві не помітили " "анкх на Ñрібному ланцюжку." msgid "Book of Elements" msgstr "Книга Ñтихій" msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "%{name} подвоює ефективніÑть уÑÑ–Ñ… заклинань виклику героÑ." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Ви натраплÑєте на фокуÑника, Ñкий благає Ñупроводжувати Ð²Ð°Ñ Ñ– вашу армію " "деÑкий Ñ‡Ð°Ñ Ð·Ð°Ñ€Ð°Ð´Ð¸ безпеки. Ви погоджуєтеÑÑŒ, а він пропонує в ÑкоÑті оплати " "копію книги Ñтихій." msgid "Elemental Ring" msgstr "ПерÑтень Ñтихій" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "%{name} вдвічі зменшує вартіÑть уÑÑ–Ñ… заклинань призову." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "ЗупинившиÑÑŒ відпочити, ви помічаєте риÑÑŒ, Ñка лізе на невиÑоке дерево, щоб " "діÑтатиÑÑ Ð´Ð¾ воронÑчого гнізда. ПіддавшиÑÑŒ імпульÑу, ви Ñамі залазите на " "дерево Ñ– відлÑкуєте кота. Зазирнувши в гніздо, ви знаходите там колекцію " "блиÑкучих камінців Ñ– каблучку." msgid "Holy Pendant" msgstr "СвÑщенний кулон" msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} робить уÑÑ– війÑька Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¸Ð¼Ð¸ до проклÑть." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "У Ñвоїх мандрах ви натраплÑєте на відлюдника, що живе в маленькій, охайній " "хатині. Вражений вашою міÑією, він перериває Ñвої медитації, щоб " "благоÑловити Ð²Ð°Ñ Ñ– дати вам амулет від проклÑть." msgid "Pendant of Free Will" msgstr "Кулон Свободи Волі" msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "%{name} надає війÑькам Ð³ÐµÑ€Ð¾Ñ Ñ–Ð¼ÑƒÐ½Ñ–Ñ‚ÐµÑ‚ від заклинань гіпнозу." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "ВідгукнувшиÑÑŒ на крики про допомогу, ви бачите річкових фей, Ñкі " "розважаютьÑÑ Ñ‚Ð¸Ð¼, що топлÑть Ñтарого. Сповнені відчуттÑм помÑти, ви Ñ€Ñтуєте " "чоловіка Ñ– на деÑкий Ñ‡Ð°Ñ Ð²Ð¸Ñ‚Ñгуєте фею на Ñушу. ФеÑ, Ñкій незручно у " "повітрі, дає вам чарівний кулон, щоб ви Ñ—Ñ— відпуÑтили." msgid "Pendant of Life" msgstr "ПідвіÑка ЖиттÑ" msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} надає війÑькам Ð³ÐµÑ€Ð¾Ñ Ñ–Ð¼ÑƒÐ½Ñ–Ñ‚ÐµÑ‚ від заклинань Ñмерті." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Під Ñ‡Ð°Ñ ÐºÐ¾Ñ€Ð¾Ñ‚ÐºÐ¾Ñ— придорожньої зуÑтрічі з невеличким караваном Ñ– гри в коÑті " "виграєте магічний кулон. Його колишній влаÑник каже, що він захищає від " "Ñмертельних заклинань некромантів." msgid "Serenity Pendant" msgstr "Кулон Спокою" msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "%{name} робить вÑÑ– війÑька Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¸Ð¼Ð¸ до заклинань берÑерка." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Звуки бою притÑгують Ð²Ð°Ñ Ð´Ð¾ міÑÑ†Ñ Ð¿Ð¾Ñ”Ð´Ð¸Ð½ÐºÑƒ між Ñтарим варваром Ñ– " "воÑьмиголовою гідрою. Ваше вчаÑне Ð²Ñ‚Ñ€ÑƒÑ‡Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ»Ð°Ð¼ÑƒÑ” хід бою на кориÑть " "чоловіка. За це він нагороджує Ð²Ð°Ñ ÐºÑƒÐ»Ð¾Ð½Ð¾Ð¼, Ñкий раніше викориÑтовував Ð´Ð»Ñ " "заÑÐ¿Ð¾ÐºÐ¾Ñ”Ð½Ð½Ñ Ñ€Ð¾Ð·ÑƒÐ¼Ñƒ перед битвою." msgid "Seeing-eye Pendant" msgstr "ПідвіÑка Ð’ÑевидÑчого Ока" msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} робить уÑÑ– війÑька Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¸Ð¼Ð¸ до заклинань оÑліпленнÑ." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Ви зуÑтрічаєте дуже Ñтару жінку, Ñка давно оÑліпла від катаракти Ñ– помирає " "на Ñамоті. Ви задовольнÑєте Ñ—Ñ— оÑтанні потреби Ñ– обіцÑєте гідно поховати. Ðа " "знак подÑки вона дарує вам чарівний кулон прикрашений Ñтилізованим оком. Він " "дозволÑÑ” вам бачити із заплющеними очима." msgid "Kinetic Pendant" msgstr "Кінетичний кулон" msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" "%{name} робить уÑÑ– війÑька Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¸Ð¼Ð¸ до пралізуючих заклинань." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Ваш шлÑÑ… перегороджує голем, на Ñкому виÑить кулон, що ÑвітитьÑÑ. ДовірÑючи " "інтуїції, ви зрізаєте кулон з його шиї. Позбавлений джерела живленнÑ, голем " "падає, залишаючи вам магічний кулон." msgid "Pendant of Death" msgstr "ПідвіÑка Смерті" msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "%{name} робить уÑÑ– війÑька Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¸Ð¼Ð¸ до ÑвÑтих заклинань." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "У швидкій Ñ– Ñмертельній Ñутичці з некромантом ви виграєте його магічний " "кулон. Пізніше чарівник розповідає вам, що кулон захищає підконтрольних вам " "немертвих від заклинань ÑвÑтого Ñлова." msgid "Wand of Negation" msgstr "Жезл ЗапереченнÑ" msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "%{name} робить уÑÑ– війÑька Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÐ²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¸Ð¼Ð¸ до розÑÑ–ÑŽÐ²Ð°Ð½Ð½Ñ Ñ‡Ð°Ñ€Ñ–Ð²." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Ви зуÑтрічаєте Ñтарого друга-Чарівника, що подорожував у протилежному " "напрÑмку. Він дає вам подарунок: жезл, що не дозволÑÑ” знімати чари з ваших " "війÑьк." msgid "Golden Bow" msgstr "Золотий Лук" msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} уÑуває %{count} відÑотків штрафу війÑьк Ð³ÐµÑ€Ð¾Ñ Ð¿Ñ–Ð´ Ñ‡Ð°Ñ Ð¿Ð¾Ñтрілів " "через перепони (наприклад замкові мури)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "ПіÑÐ»Ñ Ð²Ð¸Ð¿Ð°Ð´ÐºÐ¾Ð²Ð¾Ñ— зуÑтрічі з відомим Лучником ви й не помітили, Ñк вже граєте " "з ним у коÑті. Його лук проти вашого конÑ. Ви виграли." msgid "Telescope" msgstr "ТелеÑкоп" msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} збільшує Ñ€Ð°Ð´Ñ–ÑƒÑ Ð¾Ð³Ð»Ñду території героєм на %{count} додаткову " "клітину." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Торговець з дальніх країв продає вам новий винахід його народу, кориÑний Ð´Ð»Ñ " "подорожей. З його допомогою віддалені об'єкти здаютьÑÑ Ð±Ð»Ð¸Ð¶Ñ‡Ð¸Ð¼Ð¸, Ñ– він " "називає цю річ...\n" "\n" "телеÑкопом." msgid "Statesman's Quill" msgstr "Перо Державника" msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} зменшує вартіÑть капітулÑції до %{count} відÑотків від загальної " "вартоÑті вÑÑ–Ñ… війÑьк, що Ñ” у армії героÑ." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Ви затримуєтеÑÑŒ, щоб допомогти дипломату полагодити колеÑо його карети. Ðа " "подÑку він дає вам перо з магічними влаÑтивоÑÑ‚Ñми, Ñке, за його Ñловами: " "\"допоможе людÑм приÑтати на ваше Ñлово\"." msgid "Wizard's Hat" msgstr "Капелюх Чарівника" msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "%{name} підвищує Ñ‡Ð°Ñ Ð´Ñ–Ñ— заклинань Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count} ходів." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Ви бачите, Ñк Чарівник верхи тікає від Грифона, обганÑючи вітер. Чарівник " "відкриває портал та проходить крізь нього, однак його капелюх чіплÑєтьÑÑ Ð¾Ð± " "край проходу та падає. Грифон пролітає Ñлідом, Ñ– брама зачинÑєтьÑÑ. Ви " "підіймаєте капелюха, обтрушуєте його, та надÑгаєте." msgid "Power Ring" msgstr "ПерÑтень МогутноÑті" msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "%{name} Ñ‰Ð¾Ð´Ð½Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÑŽÑ” очки мани Ð³ÐµÑ€Ð¾Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾ у кількоÑті: %{count} од." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Ви знаходите невеличке дерево з перÑтнем на гілці. РоÑлина підозріло нагадує " "великого Чаклуна Карнаута. Залишки одÑгу та зогнилої шкіри підтверджують " "ваші підозри, що це Ñ– Ñ” обернений на дерево Карнаут. Ви вже не зможете йому " "допомогти, то ж забираєте його магічного перÑтнÑ." msgid "Ammo Cart" msgstr "Візок з БоєприпаÑами" msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "" "%{name} забезпечує Ñтрілецькі війÑька Ð³ÐµÑ€Ð¾Ñ Ð½ÐµÑкінченними боєприпаÑами." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Ваш поглÑд затримуєтьÑÑ Ð½Ð° візку з боєприпаÑами, що Ñтоїть поÑеред Ñтарого " "бойовища. Перевірка вÑтановлює, що він придатний Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð·Ð° " "призначеннÑм, то ж ви забираєте його з Ñобою." msgid "Tax Lien" msgstr "Податкова ЗаÑтава" msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} коштує герою %{count} золотих щоднÑ." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Ваша ÑхильніÑть до надмірних витрат призводить до Ð²Ñ€ÑƒÑ‡ÐµÐ½Ð½Ñ Ð²Ð°Ð¼ великого " "податкового рахунку, Ñкий ви ніколи не зможете Ñплатити. Податківець " "зглÑнувÑÑ, та погодивÑÑ Ð´Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ‚Ð¸ вам тихеÑенько втекти в ліÑ, а потім " "ÑÑ‚Ñгувати з Ð²Ð°Ñ Ð»Ð¸Ñˆ по 250 золотих щоднÑ. ПідпишітьÑÑ Ñ‚ÑƒÑ‚, щоб передати " "чаÑтину цих грошей на Ð¿Ñ€Ð¸Ð´Ð±Ð°Ð½Ð½Ñ Ð³Ñ€ÐµÑ‡ÐºÐ¸ під наÑтупні вибори." msgid "Hideous Mask" msgstr "Мерзенна МаÑка" msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "%{name} не дозволÑÑ” вÑім \"нейтральним\" арміÑм приєднуватиÑÑŒ до героÑ." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Ви грабуєте могилу СінфілаÑа Гардолада, знаменитого Чаклуна-перевертнÑ, та " "діÑтаєте з-під землі його легендарну маÑку. Ледве Ñтримуючи тремтіннÑ, ви " "вдÑгаєте Ñ—Ñ—, Ñ– вона Ñпотворює ваше обличчÑ, перетворивши його на жахливу " "гримаÑу! О ні! ÐаÑправді це жахлива маÑка Громлука Гріна, Ñ– ви заÑтрÑгли в " "ній." msgid "Endless Pouch of Sulfur" msgstr "ÐеÑкінченний Мішечок з Сіркою" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} збільшує видобуток Ñірки на %{count} в день." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Ви відвідуєте алхіміка, Ñкий, побачивши ваше війÑько, захопивÑÑ Ð¿Ñ€Ð°Ð²ÐµÐ´Ð½Ñ–Ñтю " "вашої Ñправи. Ваш новий підданий віддає вам неÑкінченний мішечок з Ñіркою, " "щоб допомогти у війні." msgid "Endless Vial of Mercury" msgstr "ÐеÑкінченний Флакон з Ртуттю" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} збільшує видобуток ртуті на %{count} в день." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Коротка зупинка Ð±Ñ–Ð»Ñ Ð¿Ð¾Ñпіхом залишеної вежі Чарівника призводить до " "знахідки - флакон, в Ñкому завжди залишаєтьÑÑ Ñ‚Ñ€Ð¾Ñ…Ð¸ ртуті на дні. Зрозумівши " "що те, що ви найшли - це Ñкарб, ви закорковуєте його, та кладете до кишені." msgid "Endless Pouch of Gems" msgstr "ÐеÑкінченний Мішечок Самоцвітів" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} збільшує видобуток Ñамоцвітів на %{count} в день." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "ПіÑÐ»Ñ ÐºÐ¾Ñ€Ð¾Ñ‚ÐºÐ¾Ñ— зливи з'ÑвлÑєтьÑÑ Ñ€Ð°Ð¹Ð´ÑƒÐ³Ð°... Ñ– ви бачите, звідки вона " "починаєтьÑÑ. Швидко їдучи верхи, ви знаходите глечик з золотом у тому міÑці. " "Лепрекон, Ñкому належить горщик, не може завадити вам забрати його, то ж " "пропонує натоміÑть неÑкінченний мішечок з Ñамоцвітами. Ви погоджуєтеÑÑŒ." msgid "Endless Cord of Wood" msgstr "ÐеÑкінченна Ð’'Ñзанка Дров" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} збільшує видобуток дерева на %{count} в день." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "ЗупинившиÑÑŒ відпочити та запаливши багаттÑ, ви витÑгаєте шматок дерева з " "найближчої купи деревини. Підкидаючи дрова до багаттÑ, ви помічаєте, що купа " "деревини не зменшуєтьÑÑ. Ви з радіÑтю уÑвідомлюєте, що Ñ†Ñ Ð´ÐµÑ€ÐµÐ²Ð¸Ð½Ð° " "зачарована, то ж збираєте Ñ—Ñ— у в'Ñзанку, та забираєте з Ñобою." msgid "Endless Cart of Ore" msgstr "ÐеÑкінченний Візок Руди" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} збільшує видобуток руди на %{count} в день." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Ви знаходите ГоблінÑьку зброÑрню, де виготовлÑли зброю Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ " "проти людей. З гучним криком ви з вашим війÑьком налітаєте на Ñ—Ñ… табір, " "виганÑючи Ñ—Ñ… геть. Обшукавши табір, ви знаходите чарівний візок з рудою, в " "Ñкому ніколи не ÑкінчаєтьÑÑ Ð·Ð°Ð»Ñ–Ð·Ð¾." msgid "Endless Pouch of Crystal" msgstr "ÐеÑкінченний Мішечок КриÑталів" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} збільшує видобуток криÑталів на %{count} в день." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "ХоваючиÑÑŒ від буревію у маленькій печері, ви помічаєте в одному кутку " "невеличкий шматок криÑталу. ЗацікавившиÑÑŒ, ви відламуєте шматочок, та " "помічаєте, що на його міÑці одразу ж з'ÑвлÑєтьÑÑ Ð½Ð¾Ð²Ð¸Ð¹ криÑтал. Ви вирішуєте " "поклаÑти веÑÑŒ шматок у мішечок, та забрати його з Ñобою." msgid "Spiked Helm" msgstr "ШпичаÑтий Шолом" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Ваше війÑько втрапило у заÑідку невеличкого племені диких (та не надто " "розумних) Орків. Ви легко відбиваєте напад, вцілілі нападники розбігаютьÑÑ " "хто куди. Один з Орків ноÑив на Ñобі полірований шпичаÑтий шолом. Зробивши " "виÑновок, що він Ñтане чудовим Ñувеніром, ви забираєте його." msgid "Spiked Shield" msgstr "ШпичаÑтий Щит" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Ви приходите до моÑту, перекинутого через Ñухий ÑÑ€. Щойно ви збираєтеÑÑŒ " "перейти, з-під моÑту виходить Троль, та вимагає у Ð²Ð°Ñ Ð¿Ð»Ð°Ñ‚Ð½Ñ– за прохід. Ви " "відмовлÑєтеÑÑŒ, Ñ– Троль нападає на ваÑ. Ви не маєте іншого виходу ,окрім Ñк " "вбити його. Його шпичаÑтий щит ви забираєте Ñобі за трофей." msgid "White Pearl" msgstr "Біла Перлина" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "ПрогулÑнка по Ñухому Ñоленому озеру приноÑить вам неочікуваний подарунок: " "Білу перлину Ñеред розбитих мушель та уламків." msgid "Black Pearl" msgstr "Чорна Перлина" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Чутки про незвично великого Грифона, що полює на околицÑÑ…, приводÑть Ð²Ð°Ñ Ð´Ð¾ " "його печерного лігва. ПротÑгом швидкого, але жорÑтокого бою, ви вбиваєте " "монÑтра, а обшук його брудного гнізда приноÑить вам велику чорну перлину." msgid "Magic Book" msgstr "Книга Магії" msgid "The %{name} enables the hero to cast spells." msgstr "%{name} дозволÑÑ” герою викориÑтовувати заклÑттÑ." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" "До Ð²Ð°Ñ Ð¿Ñ–Ð´Ñ…Ð¾Ð´Ð¸Ñ‚ÑŒ молодий чоловік: \"Мій пане, дозвольте показати вам мій " "оÑтанній винахід Ð´Ð»Ñ Ð¿Ð¾ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ð½ÑŒ!\" Ви йдете за юнаком до його майÑтерні " "й одразу ж бачите великий апарат з важелÑми Ñ– кривошипами. \"Це він!\" - " "радіÑно каже він, - \"ДрукарÑький верÑтат\". І перш ніж ти вÑтигаєш Ñказати " "хоч Ñлово, він проÑÑ‚Ñгає тобі Чарівну Книгу." msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "Перемогти можна, знайшовши будь-Ñкий Легендарний артефакт." msgid "Dummy 2" msgstr "Заповнювач 2" msgid "The reserved artifact." msgstr "Зарезервований артефакт." msgid "Dummy 3" msgstr "Заповнювач 3" msgid "Dummy 4" msgstr "Заповнювач 4" msgid "Spell Scroll" msgstr "Чарівний Сувій" msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "Цей %{name} дозволÑÑ” герою викориÑтовувати заклÑÑ‚Ñ‚Ñ %{spell}, Ñкщо він має " "Книгу Магії." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Ви знаходите вишуканий контейнер, що міÑтить Ñтаровинний пергаментний Ñувій. " "Руни на контейнері дуже Ñтарі, а майÑтерніÑть, з Ñкою вони були нанеÑені - " "вражаюча. Щойно ви діÑтаєте Ñувій з контейнера, ви відчуваєте, Ñк Ð²Ð°Ñ " "Ñповнює магічна Ñила." msgid "Arm of the Martyr" msgstr "Рука Мученика" msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} збільшує Ñилу магії Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}, однак додає штраф до моралі " "за приÑутніÑть немертвих у його війÑьку." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Один не надто розумний приÑлужник підіймає з землі руку. Хоча й відрубана " "від тіла, вона доÑÑ– рухаєтьÑÑ. Ваші воїни відчувають відразу до відрізаної " "кінцівки, однак ви не можете змуÑити Ñебе наказати викинути Ñ—Ñ—. Схоже, вона " "має ÑкуÑÑŒ магічну Ñилу, що впливає на ваші рішеннÑ." msgid "Breastplate of Anduran" msgstr "Ðагрудник Ðндурана" msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} збільшує захиÑÑ‚ Ð³ÐµÑ€Ð¾Ñ Ð½Ð° %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Ви наштовхуєтеÑÑŒ на знак. Ðа ньому напиÑано: \"Тут лежить тіло Ðндурана. " "ВклонітьÑÑ Ñ‚Ð° приÑÑгніть на вірніÑть, Ñ– будете винагороджені\". Ви вирішуєте " "зробити так, Ñк Ñказано. Щойно ви Ñтаєте на ноги, ви відчуваєте холод на " "Ñвоїй шкірі. ПодивившиÑÑŒ донизу, ви помічаєте, що на Ð²Ð°Ñ Ð½Ð°Ð´Ñ–Ñ‚Ð¸Ð¹ ÑÑючий, " "багато прикрашений нагрудник." msgid "Broach of Shielding" msgstr "ЗахиÑна Брошка" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} надає %{count}-відÑотковий захиÑÑ‚ від заклÑть Ðрмагеддон та " "Стихійний Шторм, однак зменшує Силу Магії на 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Добра Чародійка вважає, що вашому війÑьку буде не зайвим додатковий магічний " "захиÑÑ‚. То ж вона пропонує вам зачаровану Брошку, Ñку можна ноÑити на Ñвоїй " "мантії. Ви приймаєте пропозицію." msgid "Battle Garb of Anduran" msgstr "Бойове Ð’Ð±Ñ€Ð°Ð½Ð½Ñ Ðндурана" msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} поєднує у Ñобі Ñилу трьох артефактів Ðндурана. Воно надає війÑькам " "Ð³ÐµÑ€Ð¾Ñ Ð¼Ð°ÐºÑимальну удачу та мораль, а також Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ ÐœÑ–Ñького Порталу." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "З жалю до бідного ÑелÑнина, ви придбали в нього Ñкриню Ñтарого лантуху, за " "Ñку він проÑив завелику кількіÑть золота. Згодом, обшукавши Ñ—Ñ—, ви знайшли " "три чаÑтини легендарного бойового ÑпорÑÐ´Ð¶ÐµÐ½Ð½Ñ Ðндурана!" msgid "Crystal Ball" msgstr "Кришталева КулÑ" msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} надає герою детальнішу інформацію про монÑтрів, ворожих героїв та " "замки, що знаходÑтьÑÑ Ð½ÐµÐ¿Ð¾Ð´Ð°Ð»Ñ–Ðº від влаÑника артефакту." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Ви натикаєтеÑÑŒ на табір циган, що ÑвÑткують та Ñмакують медовуху. Вони " "заохочують Ð²Ð°Ñ Ð¿Ñ–Ð´Ñ–Ð¹Ñ‚Ð¸, та кажуть: \"Якщо ви доведете, що можете Ñтанцювати " "\"Рама-Буту\", ми нагородимо тебе\". Ви понÑÑ‚Ñ‚Ñ Ð½Ðµ маєте, що це за танок, " "однак вÑе одно намагаєтеÑÑŒ щоÑÑŒ зобразити. ГлÑдачі падають зі Ñміху від " "побаченого, однак визнають вашу хоробріÑть, та дарують вам Кришталеву Кулю." msgid "Heart of Fire" msgstr "Полум'Ñне Серце" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} наділÑÑ” ваші війÑька %{count}-відÑотковим захиÑтом від вогню, однак " "збільшує вдвічі пошкодженнÑ, завдані холодом." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Ви входите до нещодавно випаленої галÑвини, та бачите ВогнÑного ЕлементалÑ, " "що Ñидить на Ñкелі. Він здіймає поглÑд, його полум'Ñне Ð¾Ð±Ð»Ð¸Ñ‡Ñ‡Ñ Ñпотворене " "виразом лютого болю. Тоді він кидає ÑÑючий предмет у ваÑ. Ви здіймаєте руки " "щоб захиÑтитиÑÑ, однак та річ проходить крізь них, та врізаєтьÑÑ Ñƒ ваші " "груди." msgid "Heart of Ice" msgstr "Крижане Серце" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} наділÑÑ” ваші війÑька %{count}-відÑотковим захиÑтом від холоду, однак " "збільшує вдвічі пошкодженнÑ, завдані вогнем." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Раптово ваше тіло охоплює пронизлива холоднеча. Ви ÑхоплюєтеÑÑŒ, падаючи з " "конÑ. Біль вщухає, та ви доÑÑ– почуваєтеÑÑŒ так, наче ваші груди заморожені. " "Коли ви вÑтаєте на ноги, ви чуєте оглушливий регіт. Ви обертаєтеÑÑŒ Ñкраз " "вчаÑно, щоб помітити, Ñк Крижаний Гігант втікає до ліÑу та зникає." msgid "Helmet of Anduran" msgstr "Шолом Ðндурана" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Ви помітили блиÑкучий предмет, що Ñтирчав з землі. Ви поÑлали одного зі " "Ñвоїх підручних обÑтежити його. Він повернувÑÑ Ñ–Ð· золотим шоломом у руках. " "Ви зрозуміли, що це, мабуть, Ñ– Ñ” той Ñамий шолом легендарного Ðндурана, що " "був відомий Ñвоїм обладунком з чиÑтого золота." msgid "Holy Hammer" msgstr "СвÑтий Молот" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Ðа Ñвоєму шлÑху ви натраплÑєте на бойовище, на Ñкому група Зомбі Ñмертельно " "поранили Паладина. Він попроÑив Ð²Ð°Ñ Ð·Ð°Ð±Ñ€Ð°Ñ‚Ð¸ його молот та завершити те, що " "він почав. Щойно ви взÑли його до рук, він почав дзижчати, а ваш поглÑд " "затуманивÑÑ. Зомбі знищені, а з молота Ñкрапує Ñ—Ñ… гнила кров. Ви чіплÑєте " "його до паÑка." msgid "Legendary Scepter" msgstr "Легендарний Скіпетр" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} додає %{count} очок до вÑÑ–Ñ… оÑновних параметрів." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Коли ви перетинали вершину невеличкого пагорба, вам відкрилоÑÑ Ð²ÐºÑ€Ð°Ð¹ Ñмішне " "видовище. Ð¤ÐµÑ Ð½Ð°Ð¼Ð°Ð³Ð°Ð»Ð°ÑÑ Ð¿Ñ–Ð´Ð½Ñти Скіпетр, що був завбільшки майже Ñк вона. " "ÐамагаючиÑÑŒ не заÑміÑтиÑÑ, ви питаєте: \"Потрібна допомога?\" Ð¤ÐµÑ " "витріщаєтьÑÑ Ð½Ð° Ð²Ð°Ñ Ñ‚Ð° відповідає: \"Гадаєш це Ñмішно? Гаразд. Можеш " "забирати Ñобі. Мені однаково значно більше до вподоби літати\"." msgid "Masthead" msgstr "Вершечок Щогли" msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "%{name} піднімає ваші удачу та мораль на %{count} у морÑьких битвах." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Старий морÑк розповідає вам Ñ–Ñторію про зачарований вершечок щогли, Ñкий він " "викориÑтовував щоб згуртувати команду у Ñ‡Ð°Ñ Ñкрути. Тоді він передає вам " "вицвілу мапу, де вказане Ñ—Ñ— міÑцезнаходженнÑ. Витративши чимало чаÑу на " "доÑлідженнÑ, ви знайшли Ñ—Ñ— у Ñховку під ÑуÑіднім доком." msgid "Sphere of Negation" msgstr "Сфера ЗапереченнÑ" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "%{name} заборонÑÑ” будь-Ñке заÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð°Ð³Ñ–Ñ— у бою." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Ви ÑпинилиÑÑ, щоб допомогти СелÑнину зловити кобилу-втікачку. Ðа знак подÑки " "він проÑÑ‚Ñгає вам невеличку Ñферу. Щойно ви взÑли Ñ—Ñ— до рук, ви відчули, Ñк " "магічна ÐµÐ½ÐµÑ€Ð³Ñ–Ñ Ð²Ð¸Ñ‚Ñ–ÐºÐ°Ñ” з ваших кінцівок..." msgid "Staff of Wizardry" msgstr "ÐŸÐ°Ñ‚ÐµÑ€Ð¸Ñ†Ñ Ð§Ð°ÐºÐ»ÑƒÐ½Ñтва" msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} поÑилює вашу Силу Магії на %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "ЗаганÑючи дичину, ваші війÑька знайшли таємничу патерицю, що левітувала " "майже у метрі над землею. Вони передали Ñ—Ñ— вам, Ñ– ви помітили примітку. Ð’ " "ній Ñказано: \"Мозок Ñильніший за м'Ñзи, а Ð¼Ð°Ð³Ñ–Ñ Ð¿ÐµÑ€ÐµÐ¼Ð°Ð³Ð°Ñ” меча. ДоÑлухайÑÑ " "до цих Ñлів, Ñ– перемагатимеш у кожному бою\"." msgid "Sword Breaker" msgstr "Мечолам" msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "%{name} збільшує ваш ЗахиÑÑ‚ на %{count} та Ðтаку на 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Колишній Капітан Варти захоплюєтьÑÑ Ð²Ð°ÑˆÐ¸Ð¼Ð¸ діÑннÑми, та дає вам зачарований " "Мечолам, на Ñкий він покладавÑÑ Ð½Ð° Ñлужбі." msgid "Sword of Anduran" msgstr "Меч Ðндурана" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Тролль ÑпинÑÑ” ваÑ, та каже: \"Плати мені 5,000 золотих, або Меч Ðндурана " "вб'Ñ” тебе на міÑці\". Ви відмовлÑєтеÑÑŒ. Троль хапає меча, що виÑить в нього " "на поÑÑÑ–, Ñкрикує від болю та тікає геть. Піднімаючи уÑлавленого меча, ви " "подумки дÑкуєте, що недоумкуваті тролі мають звичку хапати гоÑтрі предмети " "не за той кінець." msgid "Spade of Necromancy" msgstr "Лопата Ðекромантії" msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} збільшує навичку Ðекромантії героÑ." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Брудна лопата Ñтирчить з кургану неподалік. ОбÑтеживши Ñ—Ñ—, ви зрозуміли, що " "це зачарована лопата Гробарів, Ñку Ñмертні давно вважали втраченою." msgid "spellBonus|selected by user" msgstr "вибирає кориÑтувач" msgid "Wood" msgstr "Дерево" msgid "Mercury" msgstr "Ртуть" msgid "Ore" msgstr "Руда" msgid "Sulfur" msgstr "Сірка" msgid "Crystal" msgstr "КриÑтали" msgid "Gems" msgstr "Самоцвіти" msgid "Gold" msgstr "Золото" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "У ГероÑÑ… 2 Ñ–Ñнує Ñім видів реÑурÑів, що Ñ—Ñ… можна викориÑтати Ð´Ð»Ñ Ð·Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ñ‚Ð° " "Ð¿Ð¾ÐºÑ€Ð°Ñ‰ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ñ–Ð²ÐµÐ»ÑŒ у замках, Ð¿Ñ€Ð¸Ð´Ð±Ð°Ð½Ð½Ñ Ð²Ñ–Ð¹Ñьк та найму героїв. Золото - " "найбільш поширений реÑурÑ, потрібний практично Ð´Ð»Ñ Ð²Ñього. Дерево та Руда " "викориÑтовуютьÑÑ Ð´Ð»Ñ Ð·Ð²ÐµÐ´ÐµÐ½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆÐ¾Ñті будівель. Самоцвіти, Ртуть, Сірка та " "КриÑтали - це рідкіÑні магічні реÑурÑи, необхідні Ð´Ð»Ñ Ð½Ð°Ð¹Ð±Ñ–Ð»ÑŒÑˆ могутніх " "Ñ–Ñтот та будівель." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Велика вогнÑна ÐºÑƒÐ»Ñ Ð²Ñ€Ð°Ð¶Ð°Ñ” обрану облаÑть, завдаючи шкоди вÑім ÑтворіннÑм у " "полі дії." msgid "Fireball" msgstr "ВогнÑна КулÑ" msgid "Fireblast" msgstr "ВогнÑний Вибух" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Покращена верÑÑ–Ñ Ð’Ð¾Ð³Ð½Ñної Кулі, що завдає шкоду враженим загонам у радіуÑÑ– " "двох клітин довкола епіцентру, заміÑть однієї." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "ВдарÑÑ” обраний ворожий загін розрÑдом електричної енергії." msgid "Lightning Bolt" msgstr "БлиÑкавка" msgid "Chain Lightning" msgstr "Ланцюгова БлиÑкавка" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "ВдарÑÑ” розрÑдом електричної енергії обраний ворожий загін, піÑÐ»Ñ Ñ‡Ð¾Ð³Ð¾ удар " "перекидаєтьÑÑ Ð½Ð° наÑтупну найближчу Ñ–Ñтоту, завдаючи половину шкоди Ñ– так " "далі, загалом пошкоджуючи 4 цілі, аж доки блиÑкавка не Ñтане заÑлабкою, щоб " "комуÑÑŒ зашкодити. Увага: Це заклÑÑ‚Ñ‚Ñ Ð·Ð´Ð°Ñ‚Ð½Ðµ зачепити ваші влаÑні війÑька!" msgid "Teleport" msgstr "Телепорт" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "Телепортує обраний дружній загін в будь-Ñку вільну точку Ð¿Ð¾Ð»Ñ Ð±Ð¾ÑŽ." msgid "Cure" msgstr "ЗціленнÑ" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Знімає вÑÑ– негативні заклÑÑ‚Ñ‚Ñ Ð· обраного дружнього загону, відновлюючи по " "%{count} ОЗ за кожен рівень Сили Магії." msgid "Mass Cure" msgstr "МаÑове ЗціленнÑ" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Знімає вÑÑ– негативні заклÑÑ‚Ñ‚Ñ Ð· ваших війÑьк, відновлюючи у кожному загоні " "по %{count} ОЗ за кожен рівень Сили Магії." # Коректніший переклад: # - Resurrect - воÑкреÑити, дієÑлово # - Resurection - воÑкреÑіннÑ, іменник msgid "Resurrect" msgstr "ВоÑкреÑити" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "ВоÑкрешає Ñ–Ñтот у пошкодженому або знищеному загоні до ÐºÑ–Ð½Ñ†Ñ Ð±Ð¸Ñ‚Ð²Ð¸." msgid "Resurrect True" msgstr "ІÑтинне ВоÑкреÑіннÑ" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Ðазавжди воÑкрешає Ñ–Ñтот у пошкодженому або знищеному загоні." msgid "Haste" msgstr "ПоÑпіх" msgid "Increases the speed of any creature by %{count}." msgstr "Збільшує швидкіÑть обраного дружнього загону на %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Збільшує швидкіÑть вÑÑ–Ñ… ваших загонів на %{count}." msgid "Mass Haste" msgstr "МаÑовий ПоÑпіх" msgid "Slows target to half movement rate." msgstr "Сповільнює обраний ворожий загін вдвічі." msgid "spell|Slow" msgstr "УповільненнÑ" msgid "Mass Slow" msgstr "МаÑове УповільненнÑ" msgid "Slows all enemies to half movement rate." msgstr "Зменшує швидкіÑть переÑÑƒÐ²Ð°Ð½Ð½Ñ Ð²ÑÑ–Ñ… ворожих загонів вдвічі." msgid "spell|Blind" msgstr "Сліпота" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Затьмарює очі вражених Ñ–Ñтот, не дозволÑючи їм рухатиÑÑŒ." msgid "Bless" msgstr "БлагоÑловеннÑ" msgid "Causes the selected creatures to inflict maximum damage." msgstr "ДозволÑÑ” обраному дружньому загону завдавати макÑимальної шкоди." msgid "Causes all of your units to inflict maximum damage." msgstr "ДозволÑÑ” вÑім дружнім загонам завдавати макÑимальної шкоди." msgid "Mass Bless" msgstr "МаÑове БлагоÑловеннÑ" msgid "Magically increases the defense skill of the selected creatures." msgstr "Магічно збільшує навичку захиÑту обраного дружнього загону." msgid "Stoneskin" msgstr "Кам'Ñна Шкіра" msgid "Steelskin" msgstr "Сталева Шкіра" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Збільшує навичку захиÑту обраного дружнього загону. Це заклÑÑ‚Ñ‚Ñ - покращена " "верÑÑ–Ñ ÐšÐ°Ð¼'Ñної Шкіри." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Змушує обраний ворожий загон завдавати мінімальної шкоди." msgid "Curse" msgstr "ПроклÑттÑ" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Змушує вÑÑ– ворожі загони завдавати мінімальної шкоди." msgid "Mass Curse" msgstr "МаÑове ПроклÑттÑ" msgid "Damages all undead in the battle." msgstr "Завдає шкоди вÑім невмерлим на полі бою." msgid "Holy Word" msgstr "СвÑте Слово" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Завдає шкоди вÑім невмерлим на полі бою. Це заклÑÑ‚Ñ‚Ñ - покращена верÑÑ–Ñ " "СвÑтого Слова." msgid "Holy Shout" msgstr "СвÑтий Клич" msgid "Anti-Magic" msgstr "ÐнтимагіÑ" msgid "Prevents any magic against the selected creatures." msgstr "Запобігає заÑтоÑуванню будь-Ñкої магії проти вибраних Ñ–Ñтот." msgid "Dispel Magic" msgstr "РозÑÑ–ÑŽÐ²Ð°Ð½Ð½Ñ ÐœÐ°Ð³Ñ–Ñ—" msgid "Removes all magic spells from a single target." msgstr "Знімає вÑÑ– магічні ефекти з обраного загону." msgid "Mass Dispel" msgstr "МаÑове РозÑіюваннÑ" msgid "Removes all magic spells from all creatures." msgstr "Знімає вÑÑ– заклÑÑ‚Ñ‚Ñ Ð· уÑÑ–Ñ… Ñ–Ñтот." msgid "Causes a magic arrow to strike the selected target." msgstr "ЗапуÑкає магічну Ñтрілу в обраний ворожий загін." msgid "Magic Arrow" msgstr "Магічна Стріла" msgid "Berserker" msgstr "БерÑерк" msgid "Causes a creature to attack its nearest neighbor." msgstr "Змушує зачарованих Ñ–Ñтот атакувати найближчі до нього загони." msgid "Armageddon" msgstr "Ðрмагеддон" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "СвÑщенний жах вражає поле бою, завдаючи значної шкоди вÑім Ñ–Ñтотам." msgid "Elemental Storm" msgstr "Стихійний Шторм" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "Магічні Ñтихії проливаютьÑÑ Ð½Ð° поле бою, завдаючи шкоди вÑім Ñ–Ñтотам." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Потоки ÐºÐ°Ð¼Ñ–Ð½Ð½Ñ Ð²Ð´Ð°Ñ€Ñють по чаÑтині Ð¿Ð¾Ð»Ñ Ð±Ð¾ÑŽ, завдаючи шкоди вÑім Ñ–Ñтотам у " "полі дії." msgid "Meteor Shower" msgstr "Метеоритний Дощ" msgid "Paralyze" msgstr "Параліч" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "" "Паралізує вражених Ñ–Ñтот, не дозволÑючи їм рухатиÑÑŒ або завдавати удару в " "відповідь." msgid "Hypnotize" msgstr "Гіпноз" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "Переводить обраний ворожий загін під ваш контроль, Ñкщо кількіÑть його очок " "здоров'Ñ Ð¼ÐµÐ½Ñˆ ніж у %{count} разів перевищує Силу Магії заклинача." msgid "Cold Ray" msgstr "Крижаний Промінь" msgid "Drains body heat from a single enemy unit." msgstr "Ð’Ñотує тепло тіла з обраного ворожого загону." msgid "Cold Ring" msgstr "Крижане Коло" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Ð’Ñотує тепло тіла з уÑÑ–Ñ… загонів довкола обраної клітинки, не завдаючи шкоди " "на ній." msgid "Disrupting Ray" msgstr "Розриваючий Промінь" msgid "Reduces the defense rating of an enemy unit by three." msgstr "" "Зменшує показник захиÑту ворожого загону на 3 одиниці. ЗаклÑÑ‚Ñ‚Ñ Ð¼Ð¾Ð¶Ð½Ð° " "накладати багаторазово, його також неможливо знÑти до ÐºÑ–Ð½Ñ†Ñ Ð±Ð¸Ñ‚Ð²Ð¸ будь-Ñким " "чином." msgid "Damages all living (non-undead) units in the battle." msgstr "Пошкоджує вÑÑ– живі (не невмерлі) загони на полі бою." msgid "Death Ripple" msgstr "Смертельне ТремтіннÑ" msgid "Death Wave" msgstr "Смертельна ХвилÑ" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Пошкоджує вÑÑ– живі (не невмерлі) загони на полі бою. Це заклÑÑ‚Ñ‚Ñ - покращена " "верÑÑ–Ñ Ð¡Ð¼ÐµÑ€Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ð³Ð¾ ТремтіннÑ." msgid "Dragon Slayer" msgstr "ДраконовбивцÑ" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "" "Значно збільшує навичку атаки зачарованого загону у бою проти Драконів." msgid "Blood Lust" msgstr "КровожерливіÑть" msgid "Increases a unit's attack skill." msgstr "Збільшує навичку атаки обраного дружнього загону." msgid "Animate Dead" msgstr "Оживити мерців" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "Ðазавжди відновлює Ñ–Ñтот у пошкодженому або знищеному загоні невмерлих." msgid "Mirror Image" msgstr "Дзеркальний Фантом" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Створює ілюзорну копію обраного дружнього загону. Загін-Ñ–Ð»ÑŽÐ·Ñ–Ñ Ð·Ð°Ð²Ð´Ð°Ð²Ð°Ñ‚Ð¸Ð¼Ðµ " "тої ж шкоди, що й оригінал, однак щезне, отримавши будь-Ñке пошкодженнÑ." msgid "Shield" msgstr "Щит" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Зменшує вдвічі Ð¿Ð¾ÑˆÐºÐ¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ дальніх атак Ð´Ð»Ñ Ð¾Ð±Ñ€Ð°Ð½Ð¾Ð³Ð¾ дружнього загону. " "Ðе впливає на атаки з боку замкових веж." msgid "Mass Shield" msgstr "МаÑовий Щит" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Зменшує вдвічі Ð¿Ð¾ÑˆÐºÐ¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ дальніх атак Ð´Ð»Ñ Ð²ÑÑ–Ñ… ваших загонів. Ðе " "впливає на атаки з боку замкових веж." msgid "Summon Earth Elemental" msgstr "Виклик Земних Елементалів" msgid "Summons Earth Elementals to fight for your army." msgstr "Викликає дружніх Земних Елементалів на поле бою." msgid "Summon Air Elemental" msgstr "Виклик ПовітрÑних Елементалів" msgid "Summons Air Elementals to fight for your army." msgstr "Викликає дружніх ПовітрÑних Елементалів на поле бою." msgid "Summon Fire Elemental" msgstr "Виклик ВогнÑних Елементалів" msgid "Summons Fire Elementals to fight for your army." msgstr "Викликає дружніх ВогнÑних Елементалів на поле бою." msgid "Summon Water Elemental" msgstr "Виклик Водних Елементалів" msgid "Summons Water Elementals to fight for your army." msgstr "Викликає дружніх Водних Елементалів на поле бою." msgid "Damages castle walls." msgstr "Пошкоджує Ñтіни замку." msgid "Earthquake" msgstr "ЗемлетруÑ" msgid "Causes all mines across the land to become visible." msgstr "Показує Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… копалень на мапі." msgid "View Mines" msgstr "ОглÑд копалень" msgid "Causes all resources across the land to become visible." msgstr "Показує Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… реÑурÑів на мапі." msgid "View Resources" msgstr "ОглÑд реÑурÑів" msgid "Causes all artifacts across the land to become visible." msgstr "Показує Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… артефактів на мапі." msgid "View Artifacts" msgstr "ОглÑд артефактів" msgid "Causes all towns and castles across the land to become visible." msgstr "Показує Ð¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð½Ñ Ð²ÑÑ–Ñ… міÑÑ‚ на мапі." msgid "View Towns" msgstr "ОглÑд міÑÑ‚" msgid "Causes all Heroes across the land to become visible." msgstr "Показує вÑÑ–Ñ… героїв на мапі." msgid "View Heroes" msgstr "Показати героїв" msgid "Causes the entire land to become visible." msgstr "Відкриває вÑÑŽ мапу." msgid "View All" msgstr "Показати вÑе" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "ДозволÑÑ” заклиначу побачити повну інформацію про ворожих Героїв." msgid "Summon Boat" msgstr "Виклик кораблÑ" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Викликає найближчий дружній незайнÑтий корабель на розташовану поруч з " "героєм водойму. Корабель вважаєтьÑÑ Ð´Ñ€ÑƒÐ¶Ð½Ñ–Ð¼, Ñкщо він був збудований вами, " "або Ñкщо воÑтаннє ним кориÑтавÑÑ Ð²Ð°Ñˆ герой." msgid "Allows the caster to magically transport to a nearby location." msgstr "Магічно переноÑить заклинача на невелику відÑтань." msgid "Dimension Door" msgstr "ПроÑторова Брама" msgid "Returns the caster to any town or castle currently owned." msgstr "Повертає заклинача до будь-Ñкого міÑта або замку, що належить вам." msgid "Town Gate" msgstr "МіÑький Портал" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "Повертає Ð³ÐµÑ€Ð¾Ñ Ð´Ð¾ міÑта або замку на вибір, Ñкщо ви його контролюєте." msgid "Visions" msgstr "ВидіннÑ" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "Ð’Ð¸Ð´Ñ–Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´Ð±Ð°Ñ‡Ð°Ñ” ймовірний результат битви з нейтральною армією." msgid "Haunt" msgstr "ПроклÑта КопальнÑ" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Проклинає підконтрольну вам копальню, наÑелÑючи Ñ—Ñ— Привидами. Виробництво у " "копальні припинÑєтьÑÑ. (І Ñам не гам, Ñ– другому не дам!)" msgid "Set Earth Guardian" msgstr "Виклик Земних Вартових" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Викликає Земних Елементалів Ð´Ð»Ñ Ð¾Ñ…Ð¾Ñ€Ð¾Ð½Ð¸ копальні від ворожих війÑьк." msgid "Set Air Guardian" msgstr "Виклик ПовітрÑних Вартових" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "" "Викликає ПовітрÑних Елементалів Ð´Ð»Ñ Ð¾Ñ…Ð¾Ñ€Ð¾Ð½Ð¸ копальні від ворожих війÑьк." msgid "Set Fire Guardian" msgstr "Виклик ВогнÑних Вартових" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Викликає ВогнÑних Елементалів Ð´Ð»Ñ Ð¾Ñ…Ð¾Ñ€Ð¾Ð½Ð¸ копальні від ворожих війÑьк." msgid "Set Water Guardian" msgstr "Виклик Водних Вартових" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Викликає Водних Елементалів Ð´Ð»Ñ Ð¾Ñ…Ð¾Ñ€Ð¾Ð½Ð¸ копальні від ворожих війÑьк." msgid "Random Spell" msgstr "Випадкове заклинаннÑ" msgid "Randomly selected spell of any level." msgstr "Випадково обране Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ´ÑŒ-Ñкого рівнÑ." msgid "Random 1st Level Spell" msgstr "Випадкове Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 1 рівнÑ" msgid "Randomly selected 1st level spell." msgstr "Випадково обране Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 1 рівнÑ." msgid "Random 2nd Level Spell" msgstr "Випадкове Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 2 рівнÑ" msgid "Randomly selected 2nd level spell." msgstr "Випадково обране Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 2 рівнÑ." msgid "Random 3rd Level Spell" msgstr "Випадкове Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 3 рівнÑ" msgid "Randomly selected 3rd level spell." msgstr "Випадково обране Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 3 рівнÑ." msgid "Random 4th Level Spell" msgstr "Випадкове Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 4 рівнÑ" msgid "Randomly selected 4th level spell." msgstr "Випадково обране Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 4 рівнÑ." msgid "Random 5th Level Spell" msgstr "Випадкове Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 5 рівнÑ" msgid "Randomly selected 5th level spell." msgstr "Випадково обране Ð·Ð°ÐºÐ»Ð¸Ð½Ð°Ð½Ð½Ñ 5 рівнÑ." msgid "Petrification" msgstr "Скам'ÑніннÑ" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Обертає уражену Ñ–Ñтоту на камінь. Скам'Ñніла Ñ–Ñтота отримує половину " "ушкоджень від безпоÑередньої атаки." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” Книги Магії, то ж ви не можете вичаклувати заклÑттÑ." msgid "No spell to cast." msgstr "Ðемає чарів Ð´Ð»Ñ Ð·Ð°ÑтоÑуваннÑ." msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "У вашого Ð³ÐµÑ€Ð¾Ñ Ð·Ð°Ð»Ð¸ÑˆÐ¸Ð»Ð¾ÑÑŒ %{sp} оч. мани із %{max}." msgid "View Adventure Spells" msgstr "Показати Ðебойові ЗаклÑттÑ" msgid "View Combat Spells" msgstr "Показати Бойові ЗаклÑттÑ" msgid "View previous page" msgstr "Показати попередню Ñторінку" msgid "View next page" msgstr "Показати наÑтупну Ñторінку" msgid "Close Spellbook" msgstr "Закрити Книгу ЗаклÑть" msgid "View %{spell}" msgstr "ПереглÑнути %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Це заклÑÑ‚Ñ‚Ñ Ð·Ð°Ð²Ð´Ð°Ñ” %{damage} очок шкоди." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Це заклÑÑ‚Ñ‚Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°Ñ” \n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Це заклÑÑ‚Ñ‚Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÑŽÑ” %{hp} ОЗ." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Це заклÑÑ‚Ñ‚Ñ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°Ñ” %{count} %{monster} Ð´Ð»Ñ Ð¾Ñ…Ð¾Ñ€Ð¾Ð½Ð¸ шахти." msgid "The nearest town is %{town}." msgstr "Ðайближче міÑто - %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Це міÑто вже зайнÑте вашим героєм %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Це заклÑÑ‚Ñ‚Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÑÑ” керувати ворожим загоном, чиє Ñумарне здоров'Ñ Ð½Ðµ " "перевищує \n" "%{hp} ОЗ." msgid "The ultimate artifact is really the %{name}." msgstr "Унікальний Ðртефакт це Ñправді %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Унікальний Ðртефакт можна знайти там, де %{name}." msgid "north-west" msgstr "північний захід" msgid "north" msgstr "північ" msgid "north-east" msgstr "північний Ñхід" msgid "west" msgstr "захід" msgid "center" msgstr "центр" msgid "east" msgstr "Ñхід" msgid "south-west" msgstr "південний захід" msgid "south" msgstr "південь" msgid "south-east" msgstr "південний Ñхід" msgid "The truth is out there." msgstr "Правда деÑÑŒ там." msgid "The dark side is stronger." msgstr "Темна Ñторона Ñильніша." msgid "The end of the world is near." msgstr "Скоро наÑтане кінець Ñвіту." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "КіÑтки Лорда Слейера поховані у фундаменті арени." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Чорний Дракон залюбки здолає Титана." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" "Вона Ñказала йому: \"Бла-бла-бла...\" Ртоді він відповів: Я не кажу: \"Бла-" "бла-бла!\"." msgid "An unknown force is being resurrected..." msgstr "Ðевідома Ñила поÑтає знов..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Перевірити нову верÑÑ–ÑŽ гри на\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Виберіть кількіÑть %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Увімкнути автобій" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "завершити битву у автоматичному режимі" #~ msgid "Please Remember" #~ msgstr "Будь лаÑка, пам'Ñтайте" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "" #~ "Ви завжди можете змінити мову, роздільну здатніÑть та Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€Ð¸, " #~ "натиÑнувши на кнопку " #~ msgid "door" #~ msgstr "двері" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " в лівій чаÑтині головного меню або за допомогою " #~ msgid " button from the " #~ msgstr " кнопка з " #~ msgid "NEW GAME" #~ msgstr "" #~ "ÐОВÐ\n" #~ "ГРÐ" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ " меню. \n" #~ "\n" #~ "ÐаÑолоджуйтеÑÑŒ грою!" #~ msgid "Warning!" #~ msgstr "ПопередженнÑ!" #~ msgid "Dummy 1" #~ msgstr "Заповнювач 1" fheroes2-1.1.6+dfsg/files/lang/vi.po000066400000000000000000013132021476115357100171700ustar00rootroot00000000000000# Vietnamese translation of fheroes2 # Copyright (C) 2024 fheroes2 team # This file is distributed under the same license as the fheroes2 package. # msgid "" msgstr "" "Project-Id-Version: fheroes2\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-02-09 14:16+0000\n" "PO-Revision-Date: 2024-02-20 08:49+0700\n" "Last-Translator: fheroes2 team \n" "Language-Team: \n" "Language: vi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 3.4.2\n" msgid "" "NEW\n" "GAME" msgstr "" "TẠO\n" "GAME" msgid "" "SAVE\n" "GAME" msgstr "" "LƯU\n" "GAME" msgid "" "LOAD\n" "GAME" msgstr "" "TẢI\n" "GAME" msgid "INFO" msgstr "THÔNG TIN" msgid "QUIT" msgstr "RỜI KHỎI" #, fuzzy msgid "" "NEW\n" "MAP" msgstr "" "TẠO\n" "GAME" #, fuzzy msgid "" "SAVE\n" "MAP" msgstr "" "LƯU\n" "GAME" #, fuzzy msgid "" "LOAD\n" "MAP" msgstr "" "TẢI\n" "GAME" msgid "CANCEL" msgstr "TỪ BỎ" msgid "OKAY" msgstr "ÄÆ¯á»¢C" msgid "ACCEPT" msgstr "Äá»’NG Ã" msgid "DECLINE" msgstr "TỪ CHá»I" msgid "LEARN" msgstr "HỌC TẬP" msgid "TRADE" msgstr "TRAO Äá»”I" msgid "YES" msgstr "CÓ" msgid "NO" msgstr "KHÔNG" msgid "EXIT" msgstr "THOÃT" msgid "smallerButton|EXIT" msgstr "THOÃT" msgid "DISMISS" msgstr "GIẢI TÃN" msgid "UPGRADE" msgstr "NÂNG CẤP" msgid "RESTART" msgstr "LÀM LẠI" msgid "HEROES" msgstr "TƯỚNG" msgid "" "TOWNS/\n" "CASTLES" msgstr "" "THỊ TRẤN/\n" "LÂU ÄÀI" msgid "S" msgstr "S" msgid "M" msgstr "M" msgid "L" msgstr "L" msgid "X-L" msgstr "X-L" msgid "ALL" msgstr "TẤT CẢ" msgid "SELECT" msgstr "CHỌN" msgid "" "STANDARD\n" "GAME" msgstr "" "GAME\n" "THƯỜNG" msgid "" "BATTLE\n" "ONLY" msgstr "" "CHỈ\n" "CHIẾN ÄẤU" msgid "" "CAMPAIGN\n" "GAME" msgstr "" "CHIẾN\n" "DỊCH" msgid "" "MULTI-\n" "PLAYER\n" "GAME" msgstr "" "CHÆ I\n" "NHIỀU\n" "NGƯỜI" msgid "CONFIG" msgstr "ÄIỀU CHỈNH" msgid "" "ORIGINAL\n" "CAMPAIGN" msgstr "" "CHIẾN DỊCH\n" "THƯỜNG" msgid "" "EXPANSION\n" "CAMPAIGN" msgstr "" "CHIẾN DỊCH\n" "MỞ RỘNG" msgid "HOT SEAT" msgstr "GHẾ NÓNG" msgid "2 PLAYERS" msgstr "2 NGƯỜI CHÆ I" msgid "3 PLAYERS" msgstr "3 NGƯỜI CHÆ I" msgid "4 PLAYERS" msgstr "4 NGƯỜI CHÆ I" msgid "5 PLAYERS" msgstr "5 NGƯỜI CHÆ I" msgid "6 PLAYERS" msgstr "6 NGƯỜI CHÆ I" msgid "GIFT" msgstr "QUÀ" msgid "MAX" msgstr "MAX" msgid "DIFFICULTY" msgstr "ÄỘ KHÓ" msgid "VIEW INTRO" msgstr "XEM GIỚI THIỆU" msgid "MIN" msgstr "MIN" msgid "RESET" msgstr "CÀI LẠI" msgid "START" msgstr "LÀM LẠI" msgid "TOWN" msgstr "THỊ TRẤN" msgid "CASTLE" msgstr "LÂU ÄÀI" #, fuzzy msgid "RESTRICT" msgstr "LÀM LẠI" msgid "" "D\n" "I\n" "S\n" "M\n" "I\n" "S\n" "S" msgstr "" "G\n" "I\n" "Ả\n" "I\n" "T\n" "Ã\n" "N" msgid "" "E\n" "X\n" "I\n" "T" msgstr "" "T\n" "H\n" "O\n" "Ã\n" "T" msgid "" "P\n" "A\n" "T\n" "R\n" "O\n" "L" msgstr "" msgid "" "C\n" "A\n" "M\n" "P\n" "A\n" "I\n" "G\n" "N" msgstr "" "C\n" "H\n" "I\n" "Ế\n" "N\n" "D\n" "Ị\n" "C\n" "H" msgid "" "S\n" "T\n" "A\n" "N\n" "D\n" "A\n" "R\n" "D" msgstr "" "T\n" "H\n" "Ư\n" "Ờ\n" "N\n" "G" msgid "RUMORS" msgstr "" msgid "EVENTS" msgstr "" msgid "LANGUAGE" msgstr "" msgid "" "AUTO\n" "COMBAT" msgstr "" msgid "" "QUICK\n" "COMBAT" msgstr "" msgid "Warrior" msgstr "Chiến binh" msgid "Builder" msgstr "Thợ xây" msgid "Explorer" msgstr "Thám hiểm" msgid "None" msgstr "Không" msgid "" "A few\n" "%{monster}" msgstr "" "Má»™t vài\n" "%{monster}" msgid "" "Several\n" "%{monster}" msgstr "" "Má»™t số\n" "%{monster}" msgid "" "A pack of\n" "%{monster}" msgstr "" "Má»™t nhóm\n" "%{monster}" msgid "" "Lots of\n" "%{monster}" msgstr "" "Khá nhiá»u\n" "%{monster}" msgid "" "A horde of\n" "%{monster}" msgstr "" "Má»™t bầy\n" "%{monster}" msgid "" "A throng of\n" "%{monster}" msgstr "" "Má»™t bầy đàn\n" "%{monster}" msgid "" "A swarm of\n" "%{monster}" msgstr "" "Rất nhiá»u đàn\n" "%{monster}" msgid "" "Zounds...\n" "%{monster}" msgstr "" "Quy mô\n" "%{monster}" msgid "" "A legion of\n" "%{monster}" msgstr "" "Quân Ä‘oàn\n" "%{monster}" msgid "army|Few" msgstr "Má»™t vài" msgid "army|Several" msgstr "Má»™t số" msgid "army|Pack" msgstr "Má»™t nhóm" msgid "army|Lots" msgstr "Khá nhiá»u" msgid "army|Horde" msgstr "Má»™t bầy" msgid "army|Throng" msgstr "Má»™t bầy đàn" msgid "army|Swarm" msgstr "Rất nhiá»u đàn" msgid "army|Zounds" msgstr "Quy mô" msgid "army|Legion" msgstr "Quân Ä‘oàn" msgid "All %{race} troops +1" msgstr "Tất cả binh lính %{race} +1" #, fuzzy msgid "NeutralRaceTroops|Neutral" msgstr "Trung lập" msgid "Troops of %{count} alignments -%{penalty}" msgstr "Quân cá»§a %{count} sắp hàng -%{penalty}" #, fuzzy msgid "Some undead in army -1" msgstr "Trong đội có xác sống -1" #, fuzzy msgid "" "Default\n" "troop" msgstr "Hành động Mặc định" msgid "View %{name}" msgstr "Xem %{name}" msgid "Move the %{name} " msgstr "Di chuyển %{name} " msgid "Move or right click to redistribute %{name}" msgstr "Kéo %{name} hoặc nhấp chuá»™t phải để chia" msgid "Combine %{name} armies" msgstr "Gá»™p binh lính %{name}" msgid "Exchange %{name2} with %{name}" msgstr "Trao đổi %{name2} vá»›i %{name}" msgid "Select %{name}" msgstr "Chá»n %{name}" msgid "Cannot move last troop" msgstr "Không thể di chuyển quân cuối cùng" msgid "Move the %{name}" msgstr "Di chuyển %{name}" #, fuzzy msgid "Set %{monster} Count" msgstr "Bắn %{monster}" msgid "%{name} destroys half the enemy troops!" msgid_plural "%{name} destroy half the enemy troops!" msgstr[0] "%{name} tiêu diệt má»™t ná»­a quân địch!" #, fuzzy msgid "%{name} has turned off the auto combat" msgstr "%{name} đã tắt tá»± động chiến đấu" #, fuzzy msgid "%{name} has turned on the auto combat" msgstr "%{name} đã bật tá»± động chiến đấu" msgid "Spell failed!" msgstr "Niệm chú thất bại!" msgid "" "The Sphere of Negation artifact is in effect for this battle, disabling all " "combat spells." msgstr "" "Bảo vật Quả cầu Phá»§ định có hiệu lá»±c trong trận chiến này, vô hiệu hóa tất " "cả các phép thuật chiến đấu." msgid "You cannot cast spells without a commanding hero." msgstr "" msgid "You have already cast a spell this round." msgstr "Ngươi đã sá»­ dụng má»™t câu thần chú trong vòng này." msgid "That spell will have no effect!" msgstr "Phép này sẽ không ảnh hưởng đến ai!" msgid "You may only summon one type of elemental per combat." msgstr "Ngươi chỉ có thể triệu hồi má»™t loại nguyên tố trong má»—i trận chiến." msgid "" "There is no open space adjacent to your hero where you can summon an " "Elemental to." msgstr "" "Không có không gian trống nào gần tướng cá»§a ngươi để triệu hồi má»™t Nguyên tố." #, fuzzy msgid "" "The Moat reduces the defense skill of troops trapped in it by %{count} and " "restricts their movement range." msgstr "" "Hào giảm -%{count} kỹ năng phòng thá»§ cá»§a bất kỳ đơn vị nào và làm chậm má»™t " "ná»­a tốc độ di chuyển." msgid "Speed: %{speed}" msgstr "Tốc độ: %{speed}" msgid "Speed" msgstr "Tốc độ" msgid "Off" msgstr "Tắt" msgid "On" msgstr "Bật" msgid "Turn Order" msgstr "Thứ tá»± Xếp hàng" msgid "Auto Spell Casting" msgstr "Tá»± động Niệm Phép" msgid "Grid" msgstr "Lưới" msgid "Shadow Movement" msgstr "Bóng Di chuyển" msgid "Shadow Cursor" msgstr "Bóng Con trá»" msgid "Audio" msgstr "Âm thanh" msgid "Settings" msgstr "Cài đặt" msgid "Configure" msgstr "Cấu hình" msgid "Hot Keys" msgstr "Phím tắt" msgid "Damage Info" msgstr "Thông tin Thiệt hại" msgid "Set the speed of combat actions and animations." msgstr "Äặt tốc độ cá»§a hành động chiến đấu và hình ảnh động." msgid "Toggle to display the turn order during the battle." msgstr "Chuyển đổi để hiển thị thứ tá»± xếp hàng trong trận chiến." msgid "" "Toggle whether or not the computer will cast spells for you when auto combat " "is on. (Note: This does not affect spell casting for computer players in any " "way, nor does it affect quick combat.)" msgstr "" "Chuyển đổi xem máy tính có sá»­ dụng phép thuật cho ngươi khi bật chế độ tá»± " "động chiến đấu hay không. (Lưu ý: Äiá»u này không ảnh hưởng đến việc sá»­ dụng " "phép thuật cho ngưá»i chÆ¡i máy tính theo bất kỳ cách nào, cÅ©ng như không ảnh " "hưởng đến chiến đấu nhanh.)" msgid "" "Toggle the hex grid on or off. The hex grid always underlies movement, even " "if turned off. This switch only determines if the grid is visible." msgstr "" "Bật hoặc tắt lưới lục giác. Lưới lục giác luôn làm cÆ¡ sở cho chuyển động, " "ngay cả khi bị tắt. Công tắc này chỉ xác định xem lưới có hiển thị hay không." msgid "" "Toggle on or off shadows showing where your creatures can move and attack." msgstr "" "Bật hoặc tắt bóng hiển thị nÆ¡i sinh vật cá»§a ngươi có thể di chuyển và tấn " "công." msgid "" "Toggle on or off a shadow showing the current hex location of the mouse " "cursor." msgstr "" "Bật hoặc tắt bóng hiển thị vị trí cá»§a con trá» chuá»™t trên lưới lục giác." msgid "Change the audio settings of the game." msgstr "Thay đổi cài đặt âm thanh cá»§a trò chÆ¡i." msgid "Check and configure all the hot keys present in the game." msgstr "Kiểm tra và định cấu hình tất cả các phím nóng có trong trò chÆ¡i." msgid "Toggle to display damage information during the battle." msgstr "Chuyển đổi để hiển thị thông tin thiệt hại trong trận chiến." msgid "Exit this menu." msgstr "Thoát khá»i trình đơn này." msgid "Okay" msgstr "OK" msgid "The enemy has surrendered!" msgstr "Kẻ địch đã đầu hàng!" msgid "Their cowardice costs them %{gold} gold." msgstr "" msgid "The enemy has fled!" msgstr "Kẻ thù đã bá» chạy!" msgid "A glorious victory!" msgstr "Má»™t chiến thắng vinh quang!" msgid "For valor in combat, %{name} receives %{exp} experience." msgstr "" "Vá»›i lòng dÅ©ng cảm trong chiến đấu, %{name} nhận được %{exp} kinh nghiệm." msgid "The cowardly %{name} flees from battle." msgstr "Kẻ hèn nhát %{name} chạy trốn khá»i trận chiến." msgid "%{name} surrenders to the enemy, and departs in shame." msgstr "%{name} đầu hàng kẻ thù và nhục nhã ra Ä‘i." #, fuzzy msgid "Your forces suffer a bitter defeat, and %{name} abandons your cause." msgstr "" "Lá»±c lượng cá»§a ngươi bị thất bại nặng ná» và %{name} từ bá» chính nghÄ©a cá»§a " "ngươi." #, fuzzy msgid "Your forces suffer a bitter defeat." msgstr "Lá»±c lượng cá»§a ngươi bị thất bại nặng ná»." msgid "Battlefield Casualties" msgstr "Thương vong Chiến trưá»ng" msgid "Attacker" msgstr "Bên công" msgid "Defender" msgstr "Bên thá»§" #, fuzzy msgid "Click to leave the battle results." msgstr "Nhấp để áp dụng độ phân giải đã chá»n." #, fuzzy msgid "Click to restart the battle in manual mode." msgstr "Nhấp để quay lại màn hình chính." msgid "Restart" msgstr "ChÆ¡i lại" msgid "You have captured an enemy artifact!" msgstr "Ngươi đã chiếm được má»™t bảo vật cá»§a kẻ thù!" msgid "As you reach for the %{name}, it mysteriously disappears." msgstr "Khi ngươi chạm tá»›i %{name}, nó biến mất má»™t cách bí ẩn." msgid "As your enemy reaches for the %{name}, it mysteriously disappears." msgstr "Khi kẻ thù cá»§a ngươi chạm tá»›i %{name}, nó biến mất má»™t cách bí ẩn." msgid "Necromancy!" msgstr "Chiêu hồn!" msgid "" "Practicing the dark arts of necromancy, you are able to raise %{count} of " "the enemy's dead to return under your service as %{monster}." msgstr "" "Thi triển nghệ thuật chiêu hồn hắc ám, ngươi có thể hồi sinh %{count} kẻ thù " "đã chết để trở lại dưới sá»± phục vụ cá»§a ngươi vá»›i tư cách là %{monster}." msgid "%{name} the %{race}" msgstr "%{name} cái %{race}" msgid "Captain of %{name}" msgstr "Äá»™i trưởng cá»§a %{name}" msgid "Attack" msgstr "Công" msgid "Defense" msgstr "Thá»§" msgid "Spell Power" msgstr "Sức mạnh" msgid "Knowledge" msgstr "Trí thức" msgid "Morale" msgstr "Tinh thần" msgid "Luck" msgstr "May mắn" msgid "Spell Points" msgstr "Äiểm Phép thuật" msgid "Hero's Options" msgstr "Tùy chá»n Tướng" msgid "Cast Spell" msgstr "Niệm Chú" msgid "Retreat" msgstr "Bá» chạy" msgid "Surrender" msgstr "Äầu hàng" msgid "Cancel" msgstr "Từ bá»" msgid "Hero Screen" msgstr "Màn hình Tướng" msgid "Captain's Options" msgstr "Tùy chá»n Äá»™i trưởng" msgid "" "Cast a magical spell. You may only cast one spell per combat round. The " "round is reset when every creature has had a turn." msgstr "" "Niệm má»™t phép thuật kỳ diệu. Ngươi chỉ có thể niệm má»™t câu thần chú cho má»—i " "vòng chiến đấu. Vòng được đặt lại khi má»i sinh vật đã có má»™t lượt." msgid "" "Retreat your hero, abandoning your creatures. Your hero will be available " "for you to recruit again, however, the hero will have only a novice hero's " "forces." msgstr "" "Rút lui tướng cá»§a ngươi, từ bá» sinh vật cá»§a ngươi. Tướng cá»§a ngươi sẽ có sẵn " "để ngươi chiêu má»™ lại, tuy nhiên, tướng sẽ chỉ có lá»±c lượng cá»§a má»™t tướng " "má»›i." #, fuzzy msgid "" "Surrendering costs gold. However if you pay the ransom, the hero and all of " "his or her surviving creatures will be available to recruit again. The cost " "of surrender is half of the total cost of the non-temporary troops remaining " "in the army." msgstr "" "Äầu hàng tốn vàng. Tuy nhiên, nếu ngươi trả tiá»n chuá»™c, tướng và tất cả " "những sinh vật còn sống sót cá»§a anh ta hoặc cô ta sẽ sẵn sàng để chiêu má»™ " "lại." msgid "Open Hero Screen to view full information about the hero." msgstr "Mở Màn hình Tướng để xem thông tin đầy đủ vá» Tướng." msgid "Return to the battle." msgstr "Quay lại trận chiến." msgid "Not enough gold (%{gold})" msgstr "Không đủ vàng (%{gold})" msgid "%{name} states:" msgstr "%{name} phát biểu:" msgid "Captain of %{name} states:" msgstr "Phát biểu cá»§a đội trưởng %{name}:" msgid "" "\"I will accept your surrender and grant you and your troops safe passage " "for the price of %{price} gold.\"" msgstr "" "\"Ta sẽ chấp nhận sá»± đầu hàng cá»§a ngươi và cấp cho ngươi và quân đội cá»§a " "ngươi lối Ä‘i an toàn vá»›i giá %{price} vàng.\"" msgid "View %{monster} info" msgstr "Xem thông tin %{monster}" msgid "Fly %{monster} here" msgstr "Bay %{monster} tá»›i đây" msgid "Move %{monster} here" msgstr "Chuyển %{monster} tá»›i đây" msgid "Shoot %{monster}" msgstr "Bắn %{monster}" msgid "(1 shot left)" msgid_plural "(%{count} shots left)" msgstr[0] "(còn 1 phát nữa)" msgid "Attack %{monster}" msgstr "Tấn công %{monster}" msgid "Turn %{turn}" msgstr "Lượt %{turn}" msgid "Teleport here" msgstr "Dịch chuyển tá»›i đây" msgid "Invalid teleport destination" msgstr "Äiểm đến dịch chuyển tức thá»i không hợp lệ" msgid "Cast %{spell} on %{monster}" msgstr "Niệm %{spell} lên %{monster}" msgid "Cast %{spell}" msgstr "Niệm %{spell}" msgid "Select spell target" msgstr "Chá»n mục tiêu niệm chú" msgid "View Ballista info" msgstr "Xem thông tin Máy bắn đá" msgid "Ballista" msgstr "Máy bắn đá" #, fuzzy msgid "Automatic combat modes" msgstr "Tá»± động Chiến đấu" #, fuzzy msgid "Automatic Combat Modes" msgstr "Tá»± động Chiến đấu" msgid "" "Choose between proceeding the combat in auto combat mode or in quick combat " "mode." msgstr "" msgid "Customize system options" msgstr "Tùy chỉnh tùy chá»n hệ thống" msgid "Allows you to customize the combat screen." msgstr "Cho phép ngươi tùy chỉnh màn hình chiến đấu." msgid "System Options" msgstr "Tùy chá»n Hệ thống" msgid "Skip this unit" msgstr "Bá» qua đơn vị này" msgid "Skip" msgstr "Bá» qua" msgid "" "Skips the current creature. The current creature ends its turn and does not " "get to go again until the next round." msgstr "" "Bá» qua sinh vật hiện tại. Sinh vật hiện tại kết thúc lượt cá»§a nó và không " "được Ä‘i tiếp cho đến vòng tiếp theo." msgid "View Captain's options" msgstr "Xem tùy chá»n Äá»™i trưởng" msgid "View Hero's options" msgstr "Xem tùy chá»n Tướng" msgid "View opposing Captain" msgstr "Xem đội trưởng đối phương" msgid "View opposing Hero" msgstr "Xem Tướng địch" msgid "Hide logs" msgstr "Ẩn ghi chép" msgid "Show logs" msgstr "Hiện ghi chép" msgid "Message Bar" msgstr "Thanh Tin nhắn" msgid "Shows the results of individual monster's actions." msgstr "Hiển thị kết quả hành động cá»§a từng quái vật." #, fuzzy msgid "Are you sure you want to enable the auto combat mode?" msgstr "Ngươi có chắc chắn muốn bật chiến đấu tá»± động?" #, fuzzy msgid "Are you sure you want to resolve the battle in the quick combat mode?" msgstr "Ngươi có chắc chắn muốn kết thúc trận chiến ở chế độ tá»± động không?" #, fuzzy msgid "The computer continues the combat for you." msgstr "Cho phép máy tính chiến đấu thay ngươi." msgid "" "autoCombat|This can be interrupted at any moment by pressing the Auto Combat " "hotkey or the default Cancel key, or by performing a left or right click " "anywhere on the game screen." msgstr "" msgid "Auto Combat" msgstr "Tá»± động Chiến đấu" msgid "The combat is resolved from the current state." msgstr "" msgid "quickCombat|This cannot be undone." msgstr "" #, fuzzy msgid "Quick Combat" msgstr "Tá»± động Chiến đấu" #, fuzzy msgid "The %{name} skips their turn." msgid_plural "The %{name} skip their turn." msgstr[0] "%{name} bá» lượt." msgid "%{attacker} does %{damage} damage." msgid_plural "%{attacker} do %{damage} damage." msgstr[0] "%{attacker} gây %{damage} sát thương." msgid "1 creature perishes." msgid_plural "%{count} creatures perish." msgstr[0] "1 sinh vật bị tiêu diệt." msgid "1 %{defender} perishes." msgid_plural "%{count} %{defender} perish." msgstr[0] "1 %{defender} bị tiêu diệt." msgid "1 soul is incorporated." msgid_plural "%{count} souls are incorporated." msgstr[0] "1 linh hồn được kết hợp." msgid "1 %{unit} is revived." msgid_plural "%{count} %{unit} are revived." msgstr[0] "1 %{unit} được hồi sinh." msgid "Moved %{monster}: from [%{src}] to [%{dst}]." msgstr "Chuyển %{monster}: từ [%{src}] tá»›i [%{dst}]." #, fuzzy msgid "The %{name} resists the spell!" msgid_plural "The %{name} resist the spell!" msgstr[0] "Quái vật %{name} kháng phép này!" msgid "%{name} casts %{spell} on the %{troop}." msgstr "%{name} niệm phép %{spell} lên %{troop}." msgid "%{name} casts %{spell}." msgstr "%{name} niệm %{spell}." msgid "The %{spell} does %{damage} damage to one undead creature." msgstr "Phép %{spell} gây %{damage} sát thương cho má»™t sinh vật bất tá»­." msgid "The %{spell} does %{damage} damage to all undead creatures." msgstr "Phép %{spell} gây %{damage} sát thương cho tất cả sinh vật bất tá»­." msgid "The %{spell} does %{damage} damage, %{count} creatures perish." msgstr "Phép %{spell} gây %{damage} sát thương, %{count} sinh vật chết." msgid "The %{spell} does %{damage} damage." msgstr "Phép %{spell} gây %{damage} sát thương." msgid "The %{spell} does %{damage} damage to one living creature." msgstr "Phép %{spell} gây %{damage} sát thương cho má»™t sinh vật sống." msgid "The %{spell} does %{damage} damage to all living creatures." msgstr "Phép %{spell} gây %{damage} sát thương cho tất cả sinh vật sống." #, fuzzy msgid "The %{attacker}'s attack blinds the %{target}!" msgid_plural "The %{attacker}' attack blinds the %{target}!" msgstr[0] "Tướng %{attacker}' tấn công phép mù vào mục tiêu %{target}!" #, fuzzy msgid "The %{attacker}'s gaze turns the %{target} to stone!" msgid_plural "The %{attacker}' gaze turns the %{target} to stone!" msgstr[0] "Cái nhìn cá»§a %{attacker}' biến %{target} thành đá!" #, fuzzy msgid "The %{attacker}'s curse falls upon the %{target}!" msgid_plural "The %{attacker}' curse falls upon the %{target}!" msgstr[0] "Tướng %{attacker}' nguyá»n rá»§a lên tất cả %{target}!" #, fuzzy msgid "The %{target} is paralyzed by the %{attacker}!" msgid_plural "The %{target} are paralyzed by the %{attacker}!" msgstr[0] "Mục tiêu %{target} đã bị %{attacker} hóa đá!" #, fuzzy msgid "The %{attacker} dispels all good spells on your %{target}!" msgid_plural "The %{attacker} dispel all good spells on your %{target}!" msgstr[0] "" "Tên %{attacker} xua tan má»i phép thuật tốt trên quân %{target} cá»§a ngươi!" #, fuzzy msgid "The %{attacker} casts %{spell} on the %{target}!" msgid_plural "The %{attacker} cast %{spell} on the %{target}!" msgstr[0] "Tên %{attacker} niệm phép %{spell} lên %{target}!" msgid "Bad luck descends on the %{attacker}." msgstr "Vận rá»§i giáng xuống %{attacker}." msgid "Good luck shines on the %{attacker}." msgstr "May mắn tá»a sáng trên %{attacker}." msgid "High morale enables the %{monster} to attack again." msgstr "Tinh thần cao cho phép %{monster} tấn công lần nữa." msgid "Low morale causes the %{monster} to freeze in panic." msgstr "Tinh thần xuống thấp khiến %{monster} chết cứng vì hoảng loạn." msgid "%{tower} does %{damage} damage." msgstr "%{tower} thá»±c hiện %{damage} sát thương." msgid "The mirror image is created." msgstr "Hình ảnh phản chiếu được tạo ra." msgid "The mirror image is destroyed!" msgstr "Hình ảnh phản chiếu đã mất Ä‘i!" #, fuzzy msgid "Are you sure you want to interrupt the auto combat mode?" msgstr "Ngươi có chắc chắn muốn làm gián Ä‘oạn trận chiến tá»± động không?" msgid "Error" msgstr "Lá»—i" msgid "No spells to cast." msgstr "Không có phép thuật để niệm chú." msgid "Are you sure you want to retreat?" msgstr "Ngươi có chắc chắn muốn rút lui?" msgid "Retreat disabled" msgstr "Rút lui bị vô hiệu hóa" msgid "Surrender disabled" msgstr "Äầu hàng bị vô hiệu hóa" msgid "Damage: %{max}" msgstr "Sát thương: %{max}" msgid "Damage: %{min} - %{max}" msgstr "Sát thương: %{min} - %{max}" msgid "Perish: %{max}" msgstr "Chết %{max}" msgid "Perish: %{min} - %{max}" msgstr "Chết: %{min} - %{max}" msgid "" "Through eagle-eyed observation, %{name} is able to learn the magic spell " "%{spell}." msgstr "" "Thông qua khả năng quan sát bằng con mắt đại bàng, %{name} có thể há»c được " "phép thuật %{spell}." msgid "Human" msgstr "Con ngưá»i" msgid "AI" msgstr "AI" #, fuzzy msgid "Start" msgstr "ChÆ¡i lại" #, fuzzy msgid "Start the battle." msgstr "Quay lại trận chiến." msgid "Exit" msgstr "Thoát" msgid "Reset" msgstr "" msgid "Reset to default settings." msgstr "" msgid "Please select another hero." msgstr "Hãy chá»n má»™t tướng khác." msgid "%{race1} %{name1} vs %{race2} %{name2}" msgstr "%{race1} %{name1} vs %{race2} %{name2}" msgid "Monsters" msgstr "Quái vật" msgid "N/A" msgstr "N/A" msgid "Left Turret" msgstr "Tháp pháo Trái" msgid "Right Turret" msgstr "Tháp pháo Phải" msgid "The %{name} fires with the strength of %{count} Archers" msgstr "%{name} khai há»a vá»›i sức mạnh cá»§a %{count} Cung thá»§" msgid "each with a +%{attack} bonus to their attack skill." msgstr "má»—i ngưá»i có phần thưởng +%{attack} cho kỹ năng tấn công cá»§a há»." msgid "The %{name} is destroyed." msgstr "%{name} bị phá há»§y." msgid "%{count} %{name} rises from the dead!" msgid_plural "%{count} %{name} rise from the dead!" msgstr[0] "%{count} %{name} hồi sinh từ cõi chết!" msgid "Dwarven Alliance" msgstr "Liên minh Ngưá»i lùn" msgid "Sorceress Guild" msgstr "Há»™i Phù thá»§y" msgid "Necromancer Guild" msgstr "Há»™i Chiêu hồn" msgid "Ogre Alliance" msgstr "Liên minh Yêu tinh" msgid "Dwarfbane" msgstr "Há»a Ngưá»i lùn" msgid "Dragon Alliance" msgstr "Liên minh Rồng" msgid "Elven Alliance" msgstr "Liên minh Ma quá»·" msgid "Kraeger defeated" msgstr "Kraeger bị đánh bại" msgid "Wayward Son" msgstr "Äứa con Bướng bỉnh" msgid "Uncle Ivan" msgstr "Bác Ivan" msgid "Annexation" msgstr "Thôn tính" msgid "Force of Arms" msgstr "Lá»±c lượng VÅ© trang" msgid "Save the Dwarves" msgstr "Cứu Ngưá»i lùn" msgid "Carator Mines" msgstr "Má» Carator" msgid "Turning Point" msgstr "Bước Ngoặt" msgid "scenarioName|Defender" msgstr "Bên thá»§" msgid "Corlagon's Defense" msgstr "Phòng thá»§ Corlagon" msgid "The Crown" msgstr "Vương Miện" msgid "The Gauntlet" msgstr "Thách thức" msgid "Betrayal" msgstr "Sá»± phản bá»™i" msgid "Final Justice" msgstr "Công lý Cuối cùng" msgid "" "Roland needs you to defeat the lords near his castle to begin his war of " "rebellion against his brother. They are not allied with each other, so they " "will spend most of their time fighting with one another. Victory is yours " "when you have defeated all of their castles and heroes." msgstr "" "Roland cần ngươi đánh bại các lãnh chúa gần lâu đài cá»§a anh ta để bắt đầu " "cuá»™c chiến nổi dậy chống lại anh trai mình. Há» không liên minh vá»›i nhau, vì " "vậy há» sẽ dành phần lá»›n thá»i gian để chiến đấu vá»›i nhau. Chiến thắng là cá»§a " "ngươi khi ngươi đã đánh bại tất cả các lâu đài và tướng cá»§a há»." msgid "" "The local lords refuse to swear allegiance to Roland, and must be subdued. " "They are wealthy and powerful, so be prepared for a tough fight. Capture all " "enemy castles to win." msgstr "" "Các lãnh chúa địa phương từ chối thá» trung thành vá»›i Roland, và phải khuất " "phục. Há» giàu có và quyá»n lá»±c, vì vậy hãy chuẩn bị cho má»™t cuá»™c chiến khó " "khăn. Äánh chiếm tất cả các lâu đài cá»§a kẻ thù để giành chiến thắng." msgid "" "Your task is to defend the Dwarves against Archibald's forces. Capture all " "of the enemy towns and castles to win, and be sure not to lose all of the " "dwarf towns at once, or the enemy will have won." msgstr "" "Nhiệm vụ cá»§a ngươi là bảo vệ Ngưá»i lùn chống lại lá»±c lượng cá»§a Archibald. " "Äánh chiếm tất cả các thị trấn và lâu đài cá»§a kẻ thù để giành chiến thắng, " "đồng thá»i đảm bảo không để mất tất cả các thị trấn cá»§a ngưá»i lùn cùng má»™t " "lúc, nếu không kẻ thù sẽ chiến thắng." #, fuzzy msgid "" "You will face four allied enemies in a straightforward fight for resources " "and treasure. Capture all of the enemy castles for victory." msgstr "" "Ngươi sẽ đối mặt vá»›i bốn kẻ thù đồng minh trong má»™t cuá»™c chiến đơn giản để " "giành lấy tài nguyên và kho báu. Nắm bắt tất cả các lâu đài cá»§a kẻ thù để " "giành chiến thắng." msgid "" "Your enemies are allied against you and start close by, so be ready to come " "out fighting. You will need to own all four castles in this small valley to " "win." msgstr "" "Kẻ thù cá»§a ngươi Ä‘ang liên minh chống lại ngươi và bắt đầu áp sát, vì vậy " "hãy sẵn sàng chiến đấu. Ngươi sẽ cần phải sở hữu cả bốn lâu đài trong thung " "lÅ©ng nhá» này để giành chiến thắng." msgid "" "The Sorceress' guild of Noraston has requested Roland's aid against an " "attack from Archibald's allies. Capture all of the enemy castles to win, and " "don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy " "castle on an island in the ocean.)" msgstr "" "Há»™i phù thá»§y Noraston đã yêu cầu sá»± trợ giúp cá»§a Roland chống lại cuá»™c tấn " "công từ các đồng minh cá»§a Archibald. Äánh chiếm tất cả các lâu đài cá»§a kẻ " "thù để giành chiến thắng và đừng để mất Noraston, nếu không ngươi sẽ thua " "kịch bản. (Gợi ý: Có má»™t lâu đài cá»§a kẻ thù trên má»™t hòn đảo giữa đại dương.)" msgid "" "Gather as large an army as possible and capture the enemy castle within 8 " "weeks. You are opposed by only one enemy, but must travel a long way to get " "to the enemy castle. Any troops you have in your army at the end of this " "scenario will be with you in the final battle." msgstr "" "Tập hợp má»™t đội quân lá»›n nhất có thể và chiếm được lâu đài cá»§a kẻ thù trong " "vòng 8 tuần. Ngươi chỉ bị má»™t kẻ thù chống lại, nhưng phải Ä‘i má»™t quãng " "đưá»ng dài để đến được lâu đài cá»§a kẻ thù. Bất kỳ đội quân nào ngươi có trong " "quân đội cá»§a mình khi kết thúc kịch bản này sẽ ở bên ngươi trong trận chiến " "cuối cùng." msgid "" "Find the Crown before Archibald's heroes find it. Roland will need the Crown " "for the final battle against Archibald." msgstr "" "Tìm Vương miện trước khi các anh hùng cá»§a Archibald tìm thấy nó. Roland sẽ " "cần Vương miện cho trận chiến cuối cùng vá»›i Archibald." msgid "" "Three allied enemies stand before you and victory, including Lord Corlagon. " "Roland is in a castle to the northwest, and you will lose if he falls to the " "enemy. Remember that capturing Lord Corlagon will ensure that he will not " "fight against you in the final scenario." msgstr "" "Ba kẻ thù đồng minh đứng trước ngươi và chiến thắng, bao gồm cả Lord " "Corlagon. Roland Ä‘ang ở trong má»™t lâu đài ở phía tây bắc, và ngươi sẽ thua " "nếu anh ta rÆ¡i vào tay kẻ thù. Hãy nhá»› rằng việc bắt giữ Lord Corlagon sẽ " "đảm bảo rằng anh ta sẽ không chiến đấu chống lại ngươi trong kịch bản cuối " "cùng." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Archibald to end the war!" msgstr "" "Äây là trận chiến cuối cùng. Cả ngươi và kẻ thù cá»§a ngươi Ä‘á»u được trang bị " "tận răng, và tất cả Ä‘á»u liên minh chống lại ngươi. Bắt giữ Archibald để kết " "thúc chiến tranh!" msgid "" "Switching sides leaves you with three castles against the enemy's one. This " "battle will be the easiest one you will face for the rest of the war..." "traitor." msgstr "" "Äổi bên để lại cho ngươi ba lâu đài chống lại má»™t lâu đài cá»§a kẻ thù. Trận " "chiến này sẽ là trận chiến dá»… dàng nhất mà ngươi phải đối mặt trong phần còn " "lại cá»§a cuá»™c chiến...kẻ phản bá»™i." msgid "Barbarian Wars" msgstr "Chiến tranh Man rợ" msgid "First Blood" msgstr "Máu Äầu tiên" msgid "Necromancers" msgstr "Chiêu hồn" msgid "Slay the Dwarves" msgstr "Tiêu diệt Ngưá»i lùn" msgid "Country Lords" msgstr "Lãnh chúa Äất nước" msgid "Dragon Master" msgstr "Thá»§ lÄ©nh Rồng" msgid "Rebellion" msgstr "Nổi loạn" msgid "Apocalypse" msgstr "Tận thế" msgid "Greater Glory" msgstr "Vinh quang Lá»›n hÆ¡n" msgid "" "King Archibald requires you to defeat the three enemies in this region. They " "are not allied with one another, so they will spend most of their energy " "fighting amongst themselves. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Vua Archibald yêu cầu ngươi đánh bại ba kẻ thù trong khu vá»±c này. Há» không " "liên minh vá»›i nhau, vì vậy há» sẽ dành phần lá»›n năng lượng để chiến đấu vá»›i " "nhau. Ngươi sẽ giành chiến thắng khi sở hữu tất cả các lâu đài cá»§a kẻ thù và " "không còn anh hùng nào để chiến đấu." msgid "" "You must unify the barbarian tribes of the north by conquering them. As in " "the previous mission, the enemy is not allied against you, but they have " "more resources at their disposal. You will win when you own all of the enemy " "castles and there are no more heroes left to fight." msgstr "" "Ngươi phải thống nhất các bá»™ lạc man rợ ở phía bắc bằng cách chinh phục há». " "Như trong nhiệm vụ trước, kẻ thù không liên minh chống lại ngươi, nhưng " "chúng có nhiá»u tài nguyên hÆ¡n để sá»­ dụng. Ngươi sẽ giành chiến thắng khi sở " "hữu tất cả các lâu đài cá»§a kẻ thù và không còn anh hùng nào để chiến đấu." msgid "" "Do-gooder wizards have taken the Necromancers' castle. You must retake it to " "achieve victory. Remember that while you start with a powerful army, you " "have no castle and must take one within 7 days, or lose this battle. (Hint: " "The nearest castle is to the southeast.)" msgstr "" "Các pháp sư làm Ä‘iá»u tốt hÆ¡n đã chiếm lâu đài cá»§a các Necromancer. Ngươi " "phải chiếm lại nó để đạt được chiến thắng. Hãy nhá»› rằng trong khi ngươi bắt " "đầu vá»›i má»™t đội quân hùng mạnh, ngươi không có lâu đài nào và phải chiếm lấy " "má»™t lâu đài trong vòng 7 ngày, nếu không sẽ thua trận này. (Gợi ý: Lâu đài " "gần nhất nằm ở phía đông nam.)" msgid "" "The dwarves need conquering before they can interfere in King Archibald's " "plans. Roland's forces have more than one hero and many towns to start with, " "so be ready for attack from multiple directions. You must capture all of the " "enemy towns and castles to claim victory." msgstr "" "Những ngưá»i lùn cần chinh phục trước khi há» có thể can thiệp vào kế hoạch " "cá»§a Vua Archibald. Lá»±c lượng cá»§a Roland có nhiá»u hÆ¡n má»™t anh hùng và nhiá»u " "thị trấn để bắt đầu, vì vậy hãy sẵn sàng tấn công từ nhiá»u hướng. Ngươi phải " "chiếm được tất cả các thị trấn và lâu đài cá»§a kẻ thù để giành chiến thắng." msgid "" "You must put down a peasant revolt led by Roland's forces. All are allied " "against you, but you have Lord Corlagon, an experienced hero, to help you. " "Capture all enemy castles to win." msgstr "" "Ngươi phải dập tắt cuá»™c nổi dậy cá»§a nông dân do lá»±c lượng cá»§a Roland lãnh " "đạo. Tất cả Ä‘á»u liên minh chống lại ngươi, nhưng ngươi có Lord Corlagon, má»™t " "anh hùng giàu kinh nghiệm, để giúp ngươi. Äánh chiếm tất cả các lâu đài cá»§a " "kẻ thù để giành chiến thắng." msgid "" "There are two enemies allied against you in this mission. Both are well " "armed and seek to evict you from their island. Avoid them and capture Dragon " "City to win." msgstr "" "Có hai kẻ thù liên minh chống lại ngươi trong nhiệm vụ này. Cả hai Ä‘á»u được " "trang bị vÅ© khí tốt và tìm cách Ä‘uổi ngươi khá»i hòn đảo cá»§a há». Tránh chúng " "và chiếm Dragon City để giành chiến thắng." msgid "" "Your orders are to conquer the country lords that have sworn to serve " "Roland. All of the enemy castles are unified against you. Since you start " "without a castle, you must hurry to capture one before the end of the week. " "Capture all enemy castles for victory." msgstr "" "Mệnh lệnh cá»§a ngươi là chinh phục các lãnh chúa đất nước đã thá» phục vụ " "Roland. Tất cả các lâu đài cá»§a kẻ thù được thống nhất chống lại ngươi. Vì " "ngươi bắt đầu mà không có lâu đài, nên ngươi phải nhanh chóng chiếm được má»™t " "lâu đài trước cuối tuần. Nắm bắt tất cả các lâu đài cá»§a kẻ thù để giành " "chiến thắng." msgid "" "Find the Crown before Roland's heroes find it. Archibald will need the Crown " "for the final battle against Roland." msgstr "" "Tìm Vương miện trước khi các anh hùng cá»§a Roland tìm thấy nó. Archibald sẽ " "cần Vương miện cho trận chiến cuối cùng vá»›i Roland." msgid "" "This is the final battle. Both you and your enemy are armed to the teeth, " "and all are allied against you. Capture Roland to win the war, and be sure " "not to lose Archibald in the fight!" msgstr "" "Äây là trận chiến cuối cùng. Cả ngươi và kẻ thù cá»§a ngươi Ä‘á»u được trang bị " "tận răng, và tất cả Ä‘á»u liên minh chống lại ngươi. Bắt giữ Roland để giành " "chiến thắng trong cuá»™c chiến và đảm bảo không để thua Archibald trong cuá»™c " "chiến!" msgid "Arrow's Flight" msgstr "ÄÆ°á»ng Tên bay" msgid "Island of Chaos" msgstr "Äảo Há»—n loạn" msgid "The Abyss" msgstr "Vá»±c thẳm" msgid "Uprising" msgstr "Khởi nghÄ©a" msgid "Aurora Borealis" msgstr "Bình minh phương Bắc" msgid "Betrayal's End" msgstr "Kết thúc Phản bá»™i" msgid "Corruption's Heart" msgstr "Trái tim Tham nhÅ©ng" msgid "The Giant's Pass" msgstr "Äèo Cả" msgid "" "Subdue the unruly local lords in order to provide the Empire with facilities " "to operate in this region." msgstr "" "Khuất phục các lãnh chúa địa phương ngang ngược để cung cấp cho Äế chế các " "cÆ¡ sở hoạt động trong khu vá»±c này." msgid "" "Eliminate all opposition in this area. Then the first piece of the artifact " "will be yours." msgstr "" "Loại bá» tất cả các đối lập trong lÄ©nh vá»±c này. Phần đầu tiên cá»§a hiện vật sẽ " "là cá»§a ngươi." msgid "" "The sorceresses to the northeast are rebelling! For the good of the empire " "you must quash their feeble uprising on your way to the mountains." msgstr "" "Các phù thá»§y ở phía đông bắc Ä‘ang nổi dậy! Vì lợi ích cá»§a đế chế, ngươi phải " "dập tắt cuá»™c nổi dậy yếu á»›t cá»§a chúng trên đưá»ng đến vùng núi." msgid "" "Having prepared for your arrival, Kraeger has arranged for a force of " "necromancers to thwart your quest. You must capture the castle of Scabsdale " "before the first day of the third week, or the Necromancers will be too " "strong for you." msgstr "" "Sau khi chuẩn bị sẵn sàng cho sá»± xuất hiện cá»§a ngươi, Kraeger đã sắp xếp má»™t " "lá»±c lượng các pháp sư gá»i hồn để cản trở nhiệm vụ cá»§a ngươi. Ngươi phải " "chiếm được lâu đài Scabsdale trước ngày đầu tiên cá»§a tuần thứ ba, nếu không " "các Necromancer sẽ quá mạnh đối vá»›i ngươi." msgid "" "The barbarian despot in this area is, as yet, ignorant of your presence. " "Quickly, build up your forces before you are discovered and attacked! Secure " "the region by subduing all enemy forces." msgstr "" "Kẻ chuyên quyá»n man rợ trong khu vá»±c này vẫn không biết gì vá» sá»± hiện diện " "cá»§a ngươi. Nhanh chóng, xây dá»±ng lá»±c lượng cá»§a ngươi trước khi ngươi bị phát " "hiện và tấn công! Bảo vệ khu vá»±c bằng cách khuất phục tất cả các lá»±c lượng " "cá»§a kẻ thù." msgid "" "The Empire is weak in this region. You will be unable to completely subdue " "all forces in this area, so take what you can before reprisal strikes. " "Remember, your true goal is to claim the Helmet of Anduran." msgstr "" "Äế chế yếu trong khu vá»±c này. Ngươi sẽ không thể khuất phục hoàn toàn tất cả " "các lá»±c lượng trong khu vá»±c này, vì vậy hãy lấy những gì ngươi có thể trước " "khi tấn công trả đũa. Hãy nhá»› rằng, mục tiêu thá»±c sá»± cá»§a ngươi là giành được " "MÅ© bảo hiểm cá»§a Anduran." msgid "For the good of the Empire, eliminate Kraeger." msgstr "Vì lợi ích cá»§a Äế chế, hãy loại bá» Kraeger." msgid "" "At last, you have the opportunity and the facilities to rid the Empire of " "the necromancer's evil. Eradicate them completely, and you will be sung as a " "hero for all time." msgstr "" "Cuối cùng, ngươi có cÆ¡ há»™i và phương tiện để loại bá» Äế chế khá»i cái ác cá»§a " "kẻ phá hoại. Tiêu diệt chúng hoàn toàn, và ngươi sẽ được tôn vinh như má»™t " "anh hùng má»i thá»i đại." msgid "Border Towns" msgstr "Trấn Biên thùy" msgid "Conquer and Unify" msgstr "Chinh phục và Thống nhất" msgid "Crazy Uncle Ivan" msgstr "Ivan Äiên rồ" msgid "The Wayward Son" msgstr "Äứa con Bướng bỉnh" msgid "Ivory Gates" msgstr "Cổng Ngà" msgid "The Elven Lands" msgstr "Äảo Yêu quái" msgid "The Epic Battle" msgstr "Trận chiến Sá»­ thi" msgid "The Southern War" msgstr "Cuá»™c chiến phương Nam" msgid "" "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the " "forefather of all descendants." msgstr "" "Chinh phục và thống nhất tất cả các bá»™ lạc kẻ thù. Äừng đánh mất anh hùng " "Jarkonas, tổ tiên cá»§a tất cả con cháu." msgid "" "Your rival, the Kingdom of Harondale, is attacking weak towns on your " "border! Recover from their first strike and crush them completely!" msgstr "" "Äối thá»§ cá»§a ngươi, Vương quốc Harondale, Ä‘ang tấn công các thị trấn yếu ở " "biên giá»›i cá»§a ngươi! Phục hồi từ cuá»™c tấn công đầu tiên cá»§a há» và nghiá»n nát " "há» hoàn toàn!" msgid "" "Find your wayward son Joseph who is rumored to be living in the desolate " "lands. Do it before the first day of the third month or it will be of no " "help to your family." msgstr "" "Tìm đứa con trai bướng bỉnh Joseph cá»§a ngươi, ngưá»i được đồn đại là Ä‘ang " "sống ở những vùng đất hoang vắng. Hãy làm Ä‘iá»u đó trước ngày đầu tiên cá»§a " "tháng thứ ba nếu không nó sẽ chẳng giúp ích được gì cho gia đình ngươi." #, fuzzy msgid "" "Rescue your crazy uncle Ivan. Find him before the first day of the fourth " "month or it will be of no help to your kingdom." msgstr "" "Giải cứu chú Ivan Ä‘iên rồ cá»§a ngươi. Tìm anh ta trước ngày đầu tiên cá»§a " "tháng thứ tư, nếu không sẽ chẳng ích gì cho vương quốc cá»§a ngươi." msgid "" "Destroy the barbarians who are attacking the southern border of your " "kingdom! Recover your fallen towns, and then invade the jungle kingdom. " "Leave no enemy standing." msgstr "" "Tiêu diệt những kẻ man rợ Ä‘ang tấn công biên giá»›i phía nam vương quốc cá»§a " "ngươi! Khôi phục các thị trấn đã sụp đổ cá»§a ngươi, sau đó xâm chiếm vương " "quốc rừng rậm. Không để kẻ thù đứng yên." msgid "Retake the castle of Ivory Gates, which has fallen due to treachery." msgstr "Chiếm lại lâu đài Ivory Gates đã sụp đổ do bị phản bá»™i." #, fuzzy msgid "" "Gain the favor of the elves. They will not allow trees to be chopped down, " "so we will send you wood every 2 weeks. You must complete your mission " "before the first day of the seventh month, or the kingdom will surely fall." msgstr "" "Giành được sá»± ưu ái cá»§a yêu tinh. Há» sẽ không cho phép chặt cây, vì vậy há» " "sẽ gá»­i cho ngươi gá»— 2 tuần má»™t lần. Ngươi phải hoàn thành nhiệm vụ cá»§a mình " "trước ngày đầu tiên cá»§a tháng thứ bảy, nếu không vương quốc chắc chắn sẽ sụp " "đổ." msgid "" "This is the final battle against your rival kingdom of Harondale. Eliminate " "everyone, and don't lose the hero Jarkonas VI." msgstr "" "Äây là trận chiến cuối cùng chống lại vương quốc Harondale đối thá»§ cá»§a " "ngươi. Loại bá» tất cả má»i ngưá»i và đừng để mất anh hùng Jarkonas VI." msgid "Fount of Wizardry" msgstr "Suối nguồn Ma thuật" msgid "Power's End" msgstr "Chấm dứt Quyá»n lá»±c" msgid "The Eternal Scrolls" msgstr "Phép màu VÄ©nh cá»­u" msgid "The Shrouded Isles" msgstr "Quần đảo được Bao phá»§" msgid "" "Your mission is to vanquish the warring mages in the magical Shrouded Isles. " "The completion of this task will give you a fighting chance against your " "rivals." msgstr "" "Nhiệm vụ cá»§a ngươi là đánh bại các pháp sư Ä‘ang gây chiến trong Quần đảo " "được Bao phá»§ huyá»n diệu. Việc hoàn thành nhiệm vụ này sẽ cho ngươi cÆ¡ há»™i " "chiến đấu chống lại các đối thá»§ cá»§a mình." msgid "" "The location of the great library has been discovered! You must make your " "way to it, and reclaim the city of Chronos in which it lies." msgstr "" "Vị trí cá»§a thư viện tuyệt vá»i đã được phát hiện! ngươi phải tìm đưá»ng đến đó " "và giành lại thành phố Chronos nÆ¡i nó tá»a lạc." msgid "" "Find the Orb of negation, which is said to be buried in this land. There are " "clues inscribed on stone obelisks which will help lead you to your prize. " "Find the Orb before the first day of the sixth month, or your rivals will " "surely have gotten to the fount before you." msgstr "" "Tìm Quả cầu phá»§ định, được cho là bị chôn vùi ở vùng đất này. Có những manh " "mối được ghi trên các đài tưởng niệm bằng đá sẽ giúp dẫn ngươi đến mức giá " "cá»§a mình. Tìm Quả cầu trước ngày đầu tiên cá»§a tháng thứ sáu, nếu không các " "đối thá»§ cá»§a ngươi chắc chắn sẽ đến được nguồn trước ngươi." msgid "" "You must take control of the castle of Magic, where the fount of wizardry " "lies. Do this and your victory will be supreme." msgstr "" "Ngươi phải kiểm soát lâu đài Phép thuật, nÆ¡i khởi nguồn cá»§a phép thuật. Làm " "Ä‘iá»u này và chiến thắng cá»§a ngươi sẽ là tối cao." msgid "Blood is Thicker" msgstr "Máu Dầy hÆ¡n" msgid "King and Country" msgstr "Vua và Äất nước" msgid "Pirate Isles" msgstr "Äảo Hải tặc" msgid "Stranded" msgstr "Mắc kẹt" msgid "" "Capture the town on the island off the southeast shore in order to construct " "a boat and travel back towards the mainland. Do not lose the hero Gallavant." msgstr "" "Äánh chiếm thị trấn trên hòn đảo ngoài khÆ¡i bá» biển phía đông nam để đóng " "má»™t chiếc thuyá»n và quay trở lại đất liá»n. Äừng để mất anh hùng Gallavant." msgid "" "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do " "not lose Gallavant or your quest will be over." msgstr "" "Tìm và đánh bại Martine, thá»§ lÄ©nh cướp biển, cư trú tại Pirates Cove. Äừng " "để mất Gallavant nếu không nhiệm vụ cá»§a ngươi sẽ kết thúc." msgid "" "Eliminate all the other forces who oppose the rule of Lord Alberon. " "Gallavant must not die." msgstr "" "Loại bá» tất cả các lá»±c lượng khác chống lại sá»± cai trị cá»§a Chúa Alberon. " "Gallavant không được chết." msgid "" "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in " "your name. Gallavant must not die." msgstr "" "Lật đổ chế độ quân chá»§ cố thá»§ cá»§a Chúa Alberon và giành lấy toàn bá»™ đất Ä‘ai " "dưới tên cá»§a ngươi. Gallavant không được chết." msgid " bane" msgstr " tai ương" msgid " alliance" msgstr " đồng minh" msgid "Carry-over forces" msgstr "Lá»±c lượng chuyển giao" msgid " bonus" msgstr " thưởng" msgid " defeated" msgstr " bị đánh bại" msgid " will always run away from your army." msgstr " sẽ luôn chạy trốn khá»i quân đội cá»§a ngươi." msgid " will be willing to join your army." msgstr " sẽ sẵn sàng gia nhập quân đội cá»§a ngươi." #, fuzzy msgid "\"%{artifact}\" artifact will be carried over in the campaign." msgstr "\"%{artifact}\" bảo vật sẽ được chuyển qua màn tiếp theo." #, fuzzy msgid "The army will be carried over in the campaign." msgstr "Quân lính sẽ được chuyển qua màn tiếp theo." msgid "The kingdom will have +%{count} %{resource} each day." msgstr "Vương quốc sẽ có +%{count} %{resource} má»—i ngày." #, fuzzy msgid "The \"%{spell}\" spell will be carried over in the campaign." msgstr "\"%{spell}\" phép thuật sẽ được chuyển qua màn tiếp theo." #, fuzzy msgid "%{hero} can be hired during scenarios." msgstr "%{hero} có thể thuê ở màn này." #, fuzzy msgid "%{hero} has been defeated and will not appear in subsequent scenarios." msgstr "%{hero} đã chết và không thể xuất hiện ở các màn phụ." msgid "The dwarves recognize their allies and gladly join your forces." msgstr "" "Ngưá»i lùn nhận ra đồng minh cá»§a há» và sẵn sàng gia nhập lá»±c lượng cá»§a ngươi." msgid "The ogres recognize you as the Dwarfbane and lumber over to join you." msgstr "" "Yêu tinh nhận ra ngươi là Tai ương cá»§a Ngưá»i lùn và đến để tham gia cùng " "ngươi." msgid "" "The dragons, snarling and growling, agree to join forces with you, their " "'Ally'." msgstr "" "Những con rồng gầm gừ và gầm gừ đồng ý gia nhập lá»±c lượng vá»›i ngươi, 'Äồng " "minh' cá»§a chúng." msgid "" "As you approach the group of elves, their leader calls them all to " "attention. He shouts to them, \"Who of you is brave enough to join this " "fearless ally of ours?\" The group explodes with cheers as they run to join " "your ranks." msgstr "" "Khi ngươi đến gần nhóm yêu tinh, thá»§ lÄ©nh cá»§a há» sẽ kêu gá»i tất cả há» chú ý. " "Anh ta hét lên vá»›i há», \"Ai trong số các ngươi đủ can đảm để tham gia vào " "đồng minh dÅ©ng cảm này cá»§a chúng tôi?\" Cả nhóm bùng nổ vá»›i tiếng reo hò khi " "há» chạy đến gia nhập hàng ngÅ© cá»§a ngươi." msgid "" "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may " "pass.\"" msgstr "" "Những ngưá»i lùn chào đón ngươi, \"Bất kỳ ngưá»i bạn nào cá»§a Roland Ä‘á»u là " "ngươi cá»§a chúng tôi. Ngươi có thể vượt qua.\"" msgid "" "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" msgstr "" "Yêu tinh nhận ra ngươi và càu nhàu, \"Äồng minh cá»§a Archibald có thể vượt " "qua.\"" msgid "" "The dragons see you and call out. \"Our alliance with Archibald compels us " "to join you. Unfortunately you have no room. A pity!\" They quickly scatter." msgstr "" "Những con rồng nhìn thấy ngươi và gá»i ra. \"Liên minh cá»§a chúng tôi vá»›i " "Archibald buá»™c chúng tôi phải tham gia cùng ngươi. Thật không may, ngươi " "không có chá»—. Thật đáng tiếc!\" Há» nhanh chóng chạy tán loạn." msgid "" "The elves stand at attention as you approach. Their leader calls to you and " "says, \"Let us not impede your progress, ally! Move on, and may victory be " "yours.\"" msgstr "" "Yêu tinh đứng chú ý khi ngươi đến gần. Thá»§ lÄ©nh cá»§a há» gá»i cho ngươi và nói: " "\"Hãy để chúng tôi không cản trở bước tiến cá»§a ngươi, đồng minh! Hãy tiếp " "tục và có thể chiến thắng sẽ thuá»™c vá» ngươi.\"" msgid "\"The Dwarfbane!!!!, run for your lives.\"" msgstr "\"Tai ương Ngưá»i lùn!!!, chạy ngay Ä‘i.\"" msgid "campaignBonus|Animate Dead" msgstr "Sức sống Thần chết" msgid "campaignBonus|Chain Lightning" msgstr "Sét chuyá»n" msgid "campaignBonus|Fireblast" msgstr "Nổ lá»­a" msgid "campaignBonus|Mass Curse" msgstr "Nguyá»n rá»§a Rá»™ng" msgid "campaignBonus|Mass Haste" msgstr "Tăng tốc Rá»™ng" msgid "campaignBonus|Mirror Image" msgstr "Ảnh Gương" msgid "campaignBonus|Resurrect" msgstr "Hồi sinh" msgid "campaignBonus|Steelskin" msgstr "Da sắt" msgid "campaignBonus|Summon Earth" msgstr "Triệu hồi Äất" msgid "campaignBonus|View Heroes" msgstr "Xem Tướng" msgid "campaignBonus|Ballista" msgstr "Máy bắn đá" msgid "campaignBonus|Black Pearl" msgstr "Ngá»c trai Äen" msgid "campaignBonus|Caster's Bracelet" msgstr "Vòng tay Caster" msgid "campaignBonus|Defender Helm" msgstr "MÅ© Bảo vệ" msgid "campaignBonus|Breastplate" msgstr "Giáp ngá»±c" msgid "campaignBonus|Dragon Sword" msgstr "Kiếm Rồng" msgid "campaignBonus|Fizbin Medal" msgstr "Huân chương Fizbin" msgid "campaignBonus|Foremost Scroll" msgstr "Phép Äầu tiên" msgid "campaignBonus|Gauntlets" msgstr "Găng tay" msgid "campaignBonus|Hideous Mask" msgstr "Mặt nạ Gá»›m ghiếc" msgid "campaignBonus|Mage's Ring" msgstr "Nhẫn Ma thuật" msgid "campaignBonus|Major Scroll" msgstr "Phép Lá»›n" msgid "campaignBonus|Medal of Honor" msgstr "Huân chương Danh dá»±" msgid "campaignBonus|Medal of Valor" msgstr "Huân chương Can đảm" msgid "campaignBonus|Minor Scroll" msgstr "Phép Nhá»" msgid "campaignBonus|Nomad Boots" msgstr "Giầy Du mục" msgid "campaignBonus|Power Axe" msgstr "Rìu Sức mạnh" msgid "campaignBonus|Spiked Shield" msgstr "Khiên Gai" msgid "campaignBonus|Stealth Shield" msgstr "Khiên Tàng hình" msgid "campaignBonus|Tax Lien" msgstr "Giữ Thuế" msgid "campaignBonus|Thunder Mace" msgstr "Chùy Sấm sét" msgid "campaignBonus|Traveler's Boots" msgstr "Giầy Du khách" msgid "campaignBonus|White Pearl" msgstr "Ngá»c trai Trắng" msgid "campaignBonus|Basic Archery" msgstr "CÆ¡ bản Bắn cung" msgid "campaignBonus|Advanced Archery" msgstr "Nâng cao Bắn cung" msgid "campaignBonus|Expert Archery" msgstr "Chuyên gia Bắn cung" msgid "campaignBonus|Basic Ballistics" msgstr "CÆ¡ bản Máy bắn đá" msgid "campaignBonus|Advanced Ballistics" msgstr "Nâng cao Máy bắn đá" msgid "campaignBonus|Expert Ballistics" msgstr "Chuyên gia Máy bắn đá" msgid "campaignBonus|Basic Diplomacy" msgstr "CÆ¡ bản Ngoại giao" msgid "campaignBonus|Advanced Diplomacy" msgstr "Nâng cao Ngoại giao" msgid "campaignBonus|Expert Diplomacy" msgstr "Chuyên gia Ngoại giao" msgid "campaignBonus|Basic Eagle Eye" msgstr "CÆ¡ bản Mắt Äại bàng" msgid "campaignBonus|Advanced Eagle Eye" msgstr "Nâng cao Mắt Äại bàng" msgid "campaignBonus|Expert Eagle Eye" msgstr "Chuyên gia Mắt Äại bàng" msgid "campaignBonus|Basic Estates" msgstr "CÆ¡ bản Tài sàn" msgid "campaignBonus|Advanced Estates" msgstr "Nâng cao Tài sản" msgid "campaignBonus|Expert Estates" msgstr "Chuyên gia Tài sản" msgid "campaignBonus|Basic Leadership" msgstr "CÆ¡ bản Lãnh đạo" msgid "campaignBonus|Advanced Leadership" msgstr "Nâng cao Lãnh đạo" msgid "campaignBonus|Expert Leadership" msgstr "Chuyên gia Lãnh đạo" msgid "campaignBonus|Basic Logistics" msgstr "CÆ¡ bản Vận chuyển" msgid "campaignBonus|Advanced Logistics" msgstr "Nâng cao Vận chuyển" msgid "campaignBonus|Expert Logistics" msgstr "Chuyên gia Vận chuyển" msgid "campaignBonus|Basic Luck" msgstr "CÆ¡ bản May mắn" msgid "campaignBonus|Advanced Luck" msgstr "Nâng cao May mắn" msgid "campaignBonus|Expert Luck" msgstr "Chuyên gia May mắn" msgid "campaignBonus|Basic Mysticism" msgstr "CÆ¡ bản Thần bí" msgid "campaignBonus|Advanced Mysticism" msgstr "Nâng cao Thần bí" msgid "campaignBonus|Expert Mysticism" msgstr "Chuyên gia Thần bí" msgid "campaignBonus|Basic Navigation" msgstr "CÆ¡ bản Dẫn đưá»ng" msgid "campaignBonus|Advanced Navigation" msgstr "Nâng cao Dẫn đưá»ng" msgid "campaignBonus|Expert Navigation" msgstr "Chuyên gia Dẫn đưá»ng" msgid "campaignBonus|Basic Necromancy" msgstr "CÆ¡ bản Chiêu hồn" msgid "campaignBonus|Advanced Necromancy" msgstr "Nâng cao Chiêu hồn" msgid "campaignBonus|Expert Necromancy" msgstr "Chuyên gia Chiêu hồn" msgid "campaignBonus|Basic Pathfinding" msgstr "CÆ¡ bản Tìm đưá»ng" msgid "campaignBonus|Advanced Pathfinding" msgstr "Nâng cao Tìm đưá»ng" msgid "campaignBonus|Expert Pathfinding" msgstr "Chuyên gia Dẫn đưá»ng" msgid "campaignBonus|Basic Scouting" msgstr "CÆ¡ bản Do thám" msgid "campaignBonus|Advanced Scouting" msgstr "Nâng cao Do thám" msgid "campaignBonus|Expert Scouting" msgstr "Chuyên gia Do thám" msgid "campaignBonus|Basic Wisdom" msgstr "CÆ¡ bản Thông thái" msgid "campaignBonus|Advanced Wisdom" msgstr "Nâng cao Thông thái" msgid "campaignBonus|Expert Wisdom" msgstr "Chuyên gia Thông thái" #, fuzzy msgid "" "The main hero will have the \"%{artifact}\" artifact at the start of the " "scenario." msgstr "Tướng chính sẽ có bảo vật \"%{artifact}\" khi bắt đầu kịch bản." msgid "" "The kingdom will receive %{amount} additional %{resource} at the start of " "the scenario." msgstr "" "Vương quốc sẽ nhận được thêm má»™t khoản %{amount} tài nguyên %{resource} khi " "bắt đầu kịch bản." msgid "" "The kingdom will have %{amount} less %{resource} at the start of the " "scenario." msgstr "" "Vương quốc sẽ bị ít Ä‘i má»™t khoản %{amount} tài nguyên %{resource} khi bắt " "đầu kịch bản." msgid "" "The main hero will have %{count} %{monster} at the start of the scenario." msgstr "Tướng chính sẽ nhận %{count} quái %{monster} khi bắt đầu kịch bản." #, fuzzy msgid "" "The main hero will have the \"%{spell}\" spell at the start of the scenario." msgstr "Tướng chính sẽ có phép \"%{spell}\" khi bắt đầu kịch bản." #, fuzzy msgid "The starting alignment of the scenario will be %{race}." msgstr "Chá»§ng tá»™c cá»§a kịch bản sẽ là %{race}." #, fuzzy msgid "" "The main hero will receive a +%{count} to their %{skill} at the start of the " "scenario." msgstr "Tướng chính sẽ có thêm %{count} kỹ năng %{skill} khi bắt đầu kịch bản." msgid "The main hero will have %{skill} at the start of the scenario." msgstr "Tướng chính sẽ có kỹ năng %{skill} khi bắt đầu kịch bản." msgid "Roland" msgstr "Roland" msgid "Archibald" msgstr "Archibald" #, fuzzy msgid "Price of Loyalty" msgstr "Giá cá»§a Lòng Trung Thành" msgid "Voyage Home" msgstr "Trở vá» Nhà" msgid "Wizard's Isle" msgstr "Äảo phù thá»§y" msgid "Descendants" msgstr "Huậ duệ" msgid "Cannot build. You have already built here today." msgstr "Không thể xây dá»±ng. Ngươi đã xây dá»±ng ở đây ngày hôm nay." msgid "For this action it is necessary to build a castle first." msgstr "Äối vá»›i hành động này, trước tiên cần phải xây dá»±ng má»™t lâu đài." msgid "The %{building} produces %{monster}." msgstr "%{building} sinh ra %{monster}." msgid "Requires:" msgstr "Yêu cầu:" msgid "Exit this menu without doing anything." msgstr "Thoát khá»i trình đơn này và không làm gì cả." #, fuzzy msgid "Cannot build %{name}. The castle is too far away from an ocean." msgstr "Không thể xây %{name} vì lâu đài quá xa má»™t đại dương." msgid "This building has been disabled." msgstr "" #, fuzzy msgid "Cannot afford the %{name}." msgstr "Không đủ khả năng %{name}." #, fuzzy msgid "The %{name} is already built." msgstr "%{name} đã được xây." #, fuzzy msgid "Cannot build the %{name}." msgstr "Không thể xây %{name}." msgid "Build %{name}." msgstr "Xây %{name}." msgid "Blackridge" msgstr "Blackridge" msgid "Hillstone" msgstr "Hillstone" msgid "Pinehurst" msgstr "Pinehurst" msgid "Whiteshield" msgstr "Whiteshield" msgid "Woodhaven" msgstr "Woodhaven" msgid "Blackwind" msgstr "Blackwind" msgid "Bloodreign" msgstr "Bloodreign" msgid "Dragontooth" msgstr "Dragontooth" msgid "Greywind" msgstr "Greywind" msgid "Portsmith" msgstr "Portsmith" msgid "Atlantium" msgstr "Atlantium" msgid "Middle Gate" msgstr "Middle Gate" msgid "Sansobar" msgstr "Sansobar" msgid "Tundara" msgstr "Tundara" msgid "Vulcania" msgstr "Vulcania" msgid "Baywatch" msgstr "Baywatch" msgid "Fountainhead" msgstr "Fountainhead" msgid "Vertigo" msgstr "Vertigo" msgid "Wildabar" msgstr "Wildabar" msgid "Winterkill" msgstr "Winterkill" msgid "Brindamoor" msgstr "Brindamoor" msgid "Lakeside" msgstr "Lakeside" msgid "Nightshadow" msgstr "Nightshadow" msgid "Olympus" msgstr "Olympus" msgid "Sandcaster" msgstr "Sandcaster" msgid "Alamar" msgstr "Alamar" msgid "Burlock" msgstr "Burlock" msgid "Dragadune" msgstr "Dragadune" msgid "Kalindra" msgstr "Kalindra" msgid "Xabran" msgstr "Xabran" msgid "Algary" msgstr "Algary" msgid "Basenji" msgstr "Basenji" msgid "Blackfang" msgstr "Blackfang" msgid "New Dawn" msgstr "New Dawn" msgid "Sorpigal" msgstr "Sorpigal" msgid "Avone" msgstr "Avone" msgid "Big Oak" msgstr "Big Oak" msgid "Chandler" msgstr "Chandler" msgid "Erliquin" msgstr "Erliquin" msgid "Hampshire" msgstr "Hampshire" msgid "Antioch" msgstr "Antioch" msgid "Avalon" msgstr "Avalon" msgid "Roc Haven" msgstr "Roc Haven" msgid "South Mill" msgstr "South Mill" msgid "Weed Patch" msgstr "Weed Patch" msgid "Brownston" msgstr "Brownston" msgid "Hilltop" msgstr "Hilltop" msgid "Weddington" msgstr "Weddington" msgid "Westfork" msgstr "Westfork" msgid "Whittingham" msgstr "Whittingham" msgid "Cathcart" msgstr "Cathcart" msgid "Elk's Head" msgstr "Elk's Head" msgid "Roscomon" msgstr "Roscomon" msgid "Sherman" msgstr "Sherman" msgid "Yorksford" msgstr "Yorksford" msgid "Blackburn" msgstr "Blackburn" msgid "Blacksford" msgstr "Blacksford" msgid "Burton" msgstr "Burton" msgid "Pig's Eye" msgstr "Pig's Eye" msgid "Viper's Nest" msgstr "Viper's Nest" msgid "Fenton" msgstr "Fenton" msgid "Lankershire" msgstr "Lankershire" msgid "Lombard" msgstr "Lombard" msgid "Timberhill" msgstr "Timberhill" msgid "Troy" msgstr "Troy" msgid "Forder Oaks" msgstr "Forder Oaks" msgid "Meramec" msgstr "Meramec" msgid "Quick Silver" msgstr "Quick Silver" msgid "Westmoor" msgstr "Westmoor" msgid "Willow" msgstr "Willow" msgid "Corackston" msgstr "Corackston" msgid "Sheltemburg" msgstr "Sheltemburg" msgid "Cannot recruit - you already have a Hero in this town." msgstr "Không thể chiêu má»™ - ngươi Ä‘ang có má»™t Tướng trong thị trấn." msgid "Cannot recruit - you have too many Heroes." msgstr "Không thể chiêu má»™ - ngươi Ä‘ang có quá nhiá»u Tướng." #, fuzzy msgid "Cannot afford a Hero." msgstr "Không thể có được má»™t Tướng" msgid "There is no room in the garrison for this army." msgstr "Không có chá»— trong đồn trú cho đội quân này." msgid "Fortifications" msgstr "Công sá»±" msgid "Farm" msgstr "Ruá»™ng" msgid "Thatched Hut" msgstr "Lá»u Tranh" msgid "Archery Range" msgstr "Trưá»ng Bắn cung" msgid "Upg. Archery Range" msgstr "NC. Trưá»ng Bắn cung" msgid "Blacksmith" msgstr "Lò rèn" msgid "Upg. Blacksmith" msgstr "NC. Lò rèn" msgid "Armory" msgstr "Kho vÅ© khí" msgid "Upg. Armory" msgstr "NC. Kho vÅ© khí" msgid "Jousting Arena" msgstr "Trưá»ng Ä‘ua Ngá»±a" msgid "Upg. Jousting Arena" msgstr "NC. Trưá»ng Ä‘ua Ngá»±a" msgid "Cathedral" msgstr "Thánh đưá»ng" msgid "Upg. Cathedral" msgstr "NC. Thánh đưá»ng" msgid "Coliseum" msgstr "Äấu trưá»ng" msgid "Garbage Heap" msgstr "Äống Rác" msgid "Hut" msgstr "Lá»u cá»" msgid "Stick Hut" msgstr "Lá»u Cây" msgid "Upg. Stick Hut" msgstr "NC. Lá»u Cây" msgid "Den" msgstr "Hốc" msgid "Adobe" msgstr "Nhà đất" msgid "Upg. Adobe" msgstr "NC. Nhà đất" msgid "Bridge" msgstr "Cầu" msgid "Upg. Bridge" msgstr "NC. Cầu" msgid "Pyramid" msgstr "Kim tá»± tháp" msgid "Rainbow" msgstr "Cầu vồng" msgid "Crystal Garden" msgstr "Vưá»n Pha lê" msgid "Treehouse" msgstr "Nhà cây" msgid "Cottage" msgstr "Nhà tranh" msgid "Upg. Cottage" msgstr "NC. Nhà tranh" msgid "Stonehenge" msgstr "Bãi đá" msgid "Upg. Stonehenge" msgstr "NC. Bãi đá" msgid "Fenced Meadow" msgstr "Rào chắn Äồng cá»" msgid "sorceress|Red Tower" msgstr "Tháp Äá»" msgid "Dungeon" msgstr "Ngục tối" msgid "Waterfall" msgstr "Thác nước" msgid "Cave" msgstr "Hang" msgid "Crypt" msgstr "Nhà mồ" msgid "Nest" msgstr "Tổ" msgid "Maze" msgstr "Mê cung" msgid "Upg. Maze" msgstr "NC. Mê cung" msgid "Swamp" msgstr "Äầm lầy" msgid "Green Tower" msgstr "Tháp Xanh" msgid "warlock|Red Tower" msgstr "Tháp Äá»" msgid "Black Tower" msgstr "Tháp Äen" msgid "Library" msgstr "Thư viện" msgid "Orchard" msgstr "Vưá»n quả" msgid "Habitat" msgstr "Cư trú" msgid "Pen" msgstr "Chuồng trại" msgid "Foundry" msgstr "Xưởng đúc" msgid "Upg. Foundry" msgstr "NC. Xưởng đúc" msgid "Cliff Nest" msgstr "Tổ Chim" msgid "Ivory Tower" msgstr "Tháp Ngà" msgid "Upg. Ivory Tower" msgstr "NC. Tháp Ngà" msgid "Cloud Castle" msgstr "Lâu đài Mây" msgid "Upg. Cloud Castle" msgstr "NC. Lâu đài Mây" msgid "Storm" msgstr "Bão" msgid "Skull Pile" msgstr "Äống Äầu lâu" msgid "Excavation" msgstr "Huyệt" msgid "Graveyard" msgstr "NghÄ©a địa" msgid "Upg. Graveyard" msgstr "NC. NghÄ©a địa" msgid "Upg. Pyramid" msgstr "NC. Kim tá»± tháp" msgid "Mansion" msgstr "Biệt thá»±" msgid "Upg. Mansion" msgstr "NC. Biệt thá»±" msgid "Mausoleum" msgstr "Lăng mộ" msgid "Upg. Mausoleum" msgstr "NC. Lăng mộ" msgid "Laboratory" msgstr "Phòng thí nghiệm" msgid "Shrine" msgstr "Äá»n thá»" #, fuzzy msgid "Special" msgstr "Không có gì Äặc biệt" msgid "Horde Building" msgstr "" #, fuzzy msgid "Dwelling 1" msgstr "Chá»n Phép:" #, fuzzy msgid "Dwelling 2" msgstr "Chá»n Phép:" msgid "Upg. Dwelling 2" msgstr "" #, fuzzy msgid "Dwelling 3" msgstr "Chá»n Phép:" msgid "Upg. Dwelling 3" msgstr "" #, fuzzy msgid "Dwelling 4" msgstr "Chá»n Phép:" msgid "Upg. Dwelling 4" msgstr "" #, fuzzy msgid "Dwelling 5" msgstr "Chá»n Phép:" #, fuzzy msgid "Upg. Dwelling 5" msgstr "Chá»n Phép:" #, fuzzy msgid "Dwelling 6" msgstr "Chá»n Phép:" msgid "Upg. Dwelling 6" msgstr "" msgid "2x Upg. Dwelling 6" msgstr "" msgid "" "The Fortifications increase the toughness of the walls, increasing the " "number of turns it takes to knock them down." msgstr "" "Công sá»± tăng cưá»ng độ dẻo dai cá»§a các bức tưá»ng, tăng số lượt cần thiết để " "đánh sập chúng." msgid "The Farm increases production of Peasants by %{count} per week." msgstr "Ruá»™ng tăng sản lượng cá»§a Nông dân thêm %{count} má»—i tuần." msgid "" "The Coliseum provides inspiring spectacles to defending troops, raising " "their morale by two during combat." msgstr "" "Äấu trưá»ng La Mã cung cấp những cảnh tượng đầy cảm hứng cho quân phòng thá»§, " "nâng cao tinh thần cá»§a há» lên gấp đôi trong khi chiến đấu." msgid "The Garbage Heap increases production of Goblins by %{count} per week." msgstr "Äống rác tăng sản lượng Yêu tinh thêm %{count} má»—i tuần." msgid "The Rainbow increases the luck of the defending units by two." msgstr "Cầu vồng tăng gấp đôi may mắn cho các đơn vị phòng thá»§." msgid "" "The Crystal Garden increases production of Sprites by %{count} per week." msgstr "Vưá»n Pha lê tăng sản lượng Sprite thêm %{count} má»—i tuần." msgid "The Dungeon increases the income of the town by %{count} gold per day." msgstr "Hầm ngục tăng thu nhập cá»§a thị trấn thêm %{count} vàng má»—i ngày." msgid "The Waterfall increases production of Centaurs by %{count} per week." msgstr "Thác nước tăng sản lượng Nhân mã thêm %{count} má»—i tuần." msgid "" "The Library increases the number of spells in the Guild by one for each " "level of the guild." msgstr "" "Thư viện tăng số lượng phép thuật trong Bang há»™i lên má»™t cho má»—i cấp độ cá»§a " "Bang há»™i." msgid "The Orchard increases production of Halflings by %{count} per week." msgstr "Vưá»n quả tăng sản lượng Halflings thêm %{count} má»—i tuần." msgid "The Storm adds +2 to the power of spells of a defending spell caster." msgstr "" "Storm tăng thêm +2 vào sức mạnh phép thuật cá»§a ngưá»i sá»­ dụng phép thuật " "phòng thá»§." msgid "The Skull Pile increases production of Skeletons by %{count} per week." msgstr "Äống đầu lâu tăng sản lượng Xương thêm %{count} má»—i tuần." msgid "The Special building gives a specific bonus to the chosen castle type." msgstr "" #, fuzzy msgid "" "The Horde Building increases the growth rate of the level 1 creatures by 8 " "per week." msgstr "" "Giếng tăng tốc độ phát triển cá»§a tất cả các ngôi nhà thêm %{count} sinh vật " "má»—i tuần." msgid "Thieves' Guild" msgstr "Băng Cướp" msgid "Tavern" msgstr "Tá»­u quán" msgid "Shipyard" msgstr "Xưởng tàu" msgid "Well" msgstr "Giếng" msgid "Statue" msgstr "Tượng" msgid "Marketplace" msgstr "Chợ" msgid "Moat" msgstr "Hào" msgid "Castle" msgstr "Lâu đài" msgid "Tent" msgstr "Lá»u" msgid "Captain's Quarters" msgstr "Khu Äá»™i trưởng" msgid "Mage Guild, Level 1" msgstr "Há»™i pháp sư, L1" msgid "Mage Guild, Level 2" msgstr "Há»™i pháp sư, L2" msgid "Mage Guild, Level 3" msgstr "Há»™i pháp sư, L3" msgid "Mage Guild, Level 4" msgstr "Há»™i pháp sư, L4" msgid "Mage Guild, Level 5" msgstr "Há»™i pháp sư, L5" msgid "" "The Shrine increases the necromancy skill of all your necromancers by 10 " "percent." msgstr "" "Äá»n thá» tăng 10% kỹ năng chiêu hồn cá»§a tất cả các pháp sư chiêu hồn cá»§a " "ngươi." msgid "" "The Thieves' Guild provides information on enemy players. Thieves' Guilds " "can also provide scouting information on enemy towns. Additional Guilds " "provide more information." msgstr "" "Băng Cướp cung cấp thông tin vá» ngưá»i chÆ¡i cá»§a kẻ thù. Băng Cướp cÅ©ng có thể " "cung cấp thông tin trinh sát vá» các thị trấn cá»§a kẻ thù. Các Bang há»™i bổ " "sung cung cấp thêm thông tin." msgid "The Tavern increases morale for troops defending the castle." msgstr "Tá»­u quán nâng cao tinh thần cho binh lính bảo vệ lâu đài." msgid "The Shipyard allows ships to be built." msgstr "Xưởng đóng tàu cho phép đóng tàu." msgid "" "The Well increases the growth rate of all dwellings by %{count} creatures " "per week." msgstr "" "Giếng tăng tốc độ phát triển cá»§a tất cả các ngôi nhà thêm %{count} sinh vật " "má»—i tuần." #, fuzzy msgid "The Statue increases the town's income by %{count} gold per day." msgstr "" "Tượng tăng thu nhập cho thị trấn cá»§a ngươi thêm %{count} vàng má»—i ngày." msgid "The Left Turret provides extra firepower during castle combat." msgstr "Tháp pháo Trái cung cấp thêm há»a lá»±c khi chiến đấu trong lâu đài." msgid "The Right Turret provides extra firepower during castle combat." msgstr "Tháp pháo Phải cung cấp thêm há»a lá»±c khi chiến đấu trong lâu đài." msgid "" "The Marketplace can be used to convert one type of resource into another. " "The more marketplaces you control, the better the exchange rate." msgstr "" "Chợ có thể được sá»­ dụng để chuyển đổi má»™t loại tài nguyên thành má»™t loại tài " "nguyên khác. Ngươi càng kiểm soát nhiá»u chợ, tá»· giá hối Ä‘oái càng tốt." msgid "" "The Moat slows attacking units. Any unit entering the moat must end its turn " "there and becomes more vulnerable to attack." msgstr "" "Hào làm chậm các đơn vị tấn công. Bất kỳ đơn vị nào Ä‘i vào hào Ä‘á»u phải kết " "thúc lượt cá»§a mình ở đó và trở nên dá»… bị tấn công hÆ¡n." #, fuzzy msgid "" "The Castle improves the town's defense and increases its income to %{count} " "gold per day." msgstr "" "Lâu đài cải thiện khả năng phòng thá»§ cá»§a thị trấn và tăng thu nhập lên " "%{count} vàng má»—i ngày." msgid "" "The Tent provides workers to build a castle, provided the materials and the " "gold are available." msgstr "" "Lá»u cung cấp công nhân để xây dá»±ng lâu đài, miá»…n là có sẵn nguyên liệu và " "vàng." msgid "" "The Captain's Quarters provides a captain to assist in the castle's defense " "when no hero is present." msgstr "" "Khu Äá»™i trưởng cung cấp má»™t đội trưởng để há»— trợ việc bảo vệ lâu đài khi " "không có tướng nào." msgid "" "The Mage Guild allows heroes to learn spells and replenish their spell " "points." msgstr "" "Há»™i Pháp sư cho phép các tướng há»c phép thuật và bổ sung Ä‘iểm phép thuật cá»§a " "há»." msgid "Recruit %{name}" msgstr "Chiêu má»™ %{name}" msgid "Month: %{month}, Week: %{week}, Day: %{day}" msgstr "Tháng: %{month}, Tuần: %{week}, Ngày: %{day}" msgid "" "You must purchase a spell book to use the mage guild, but you currently have " "no room for a spell book. Try giving one of your artifacts to another hero." msgstr "" "Ngươi phải mua má»™t cuốn sách thần chú để sá»­ dụng há»™i pháp sư, nhưng hiện tại " "ngươi không có chá»— cho má»™t cuốn sách thần chú. Hãy thá»­ đưa má»™t trong những " "cổ vật cá»§a ngươi cho má»™t anh tướng khác." msgid "Click to show next town." msgstr "Nhấp để xem thị trấn sau." msgid "Show next town" msgstr "Xem thị trấn sau" msgid "Click to show previous town." msgstr "Nhấp để xem thị trấn trước." msgid "Show previous town" msgstr "Xem thị trấn trước" msgid "This town may not be upgraded to a castle." msgstr "Thị trấn này có thể không được nâng cấp thành lâu đài." msgid "Town" msgstr "Thị trấn" msgid "Exit Castle" msgstr "Thoát khá»i Lâu đài" msgid "Exit Town" msgstr "Thoát khá»i Thị trấn" msgid "Show Income" msgstr "Xem Thu nhập" msgid "View Hero" msgstr "Xem Tướng" msgid "The above spells are available here." msgstr "Các phép thuật trên có sẵn ở đây." msgid "The spells the hero can learn have been added to their book." msgstr "Các phép mà tướng có thể há»c đã được thêm vào cuốn sách cá»§a há»." msgid "A generous tip for the barkeep yields the following rumor:" msgstr "" "Má»™t khoản tiá»n boa hào phóng cho ngưá»i chá»§ quán rượu mang lại tin đồn như " "sau:" msgid "Recruit Hero" msgstr "Chiêu má»™ Tướng" msgid "%{name} is a level %{value} %{race} " msgstr "%{name} ở cấp độ %{value} %{race} " msgid "with %{count} artifacts." msgstr "vá»›i %{count} bảo vật." msgid "with 1 artifact." msgstr "vá»›i 1 bảo vật." msgid "without artifacts." msgstr "không có bảo vật." msgid "Recruit %{name} the %{race}" msgstr "Chiêu má»™ %{name} cá»§a chá»§ng tá»™c %{race}" #, fuzzy msgid "" "'Spread' combat formation spreads the castle's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Äá»™i hình chiến đấu 'Dàn trải' dàn quân cá»§a ngươi từ trên xuống dưới cá»§a " "chiến trưá»ng, vá»›i ít nhất má»™t khoảng trống giữa má»—i quân." #, fuzzy msgid "" "'Grouped' combat formation bunches the castle's units together in the center " "of the castle's side of the battlefield." msgstr "" "Äá»™i hình chiến đấu 'Tập trung' tập hợp quân đội cá»§a ngươi lại vá»›i nhau ở " "trung tâm cá»§a phe ngươi trên chiến trưá»ng." msgid "Spread Formation" msgstr "Äá»™i hình Dàn trải" msgid "Grouped Formation" msgstr "Äá»™i hình Tập trung" #, fuzzy msgid "Click to show the next town." msgstr "Nhấp để xem thị trấn sau." #, fuzzy msgid "Click to show the previous town." msgstr "Nhấp để xem thị trấn trước." msgid "Set garrison combat formation to 'Spread'" msgstr "Äặt đội hình chiến đấu đồn trú thành 'Dàn trải'" msgid "Set garrison combat formation to 'Grouped'" msgstr "Äặt đội hình chiến đấu đồn trú thành 'Tập trung'" msgid "Exit Castle Options" msgstr "Thoát khá»i Lá»±a chá»n Lâu đài" msgid "Castle Options" msgstr "Lá»±a chá»n Lâu đài" msgid "Not enough resources to recruit creatures." msgstr "Không đủ tài nguyên để chiêu má»™ sinh vật." msgid "You are unable to recruit at this time, your ranks are full." msgstr "Ngươi không thể chiêu má»™ lúc này, cấp độ ngươi đã đầy." msgid "No creatures available for purchase." msgstr "Không có sinh vật nào sẵn có để mua." msgid "Recruit Creatures" msgstr "Chiêu má»™ Quái" msgid "Hire all creatures in the town." msgstr "Thuê tất cả các sinh vật trong thị trấn." msgid "Max" msgstr "Max" msgid "Available" msgstr "Có sẵn" msgid "Town Population Information and Statistics" msgstr "Thông tin và Thống kê Dân số Thị trấn" msgid "Damage" msgstr "Sát thương" msgid "HP" msgstr "Máu" msgid "Growth" msgstr "Sinh trưởng" msgid "week" msgstr "tuần" msgid "View World" msgstr "Xem Thế giá»›i" msgid "View the entire world." msgstr "Xem toàn bá»™ thế giá»›i." msgid "Puzzle" msgstr "Câu đố" msgid "View the obelisk puzzle." msgstr "Xem bản đồ câu đố." msgid "Scenario Information" msgstr "Thông tin Kịch bản" msgid "View information on the scenario you are currently playing." msgstr "Xem thông tin vá» kịch bản ngươi Ä‘ang chÆ¡i." msgid "Dig for the Ultimate Artifact." msgstr "Äào kiếm Bảo vật Tối thượng." msgid "Digging" msgstr "Äang đào" msgid "Arena" msgstr "Äấu trưá»ng" msgid "" "You enter the arena and face a pack of vicious lions. You handily defeat " "them, to the wild cheers of the crowd. Impressed by your skill, the aged " "trainer of gladiators agrees to train you in a skill of your choice." msgstr "" "Ngươi bước vào đấu trưá»ng và đối mặt vá»›i má»™t bầy sư tá»­ hung ác. Ngươi dá»… " "dàng đánh bại há» trước sá»± cổ vÅ© cuồng nhiệt cá»§a đám đông. Ấn tượng vá»›i kỹ " "năng cá»§a ngươi, ngưá»i huấn luyện đấu sÄ© lâu năm đồng ý huấn luyện cho ngươi " "má»™t kỹ năng do ngươi lá»±a chá»n." msgid "Attack Skill" msgstr "Tấn công" msgid "Defense Skill" msgstr "Phòng thá»§" msgid "Shots" msgstr "Bắn" msgid "Shots Left" msgstr "Còn Bắn" msgid "Hit Points" msgstr "Máu" msgid "Hit Points Left" msgstr "Còn Máu" msgid "You can't afford to upgrade your troops!" msgstr "Ngươi không đủ khả năng để nâng cấp quân đội cá»§a mình!" msgid "" "Your troops can be upgraded, but it will cost you dearly. Do you wish to " "upgrade them?" msgstr "" "Quân đội cá»§a ngươi có thể được nâng cấp, nhưng ngươi sẽ phải trả giá đắt. " "Ngươi có muốn nâng cấp chúng?" msgid "Are you sure you want to dismiss this army?" msgstr "Ngươi có chắc chắn muốn giải tán đội quân này không?" msgid "Upgrade" msgstr "Nâng cấp" msgid "Upgrade your troops." msgstr "Nâng cấp quân đội cá»§a ngươi." msgid "Dismiss" msgstr "Giải tán" msgid "Dismiss this army." msgstr "Giải tán đội quân này." msgid "" "A group of %{monster} with a desire for greater glory wish to join you.\n" "Do you accept?" msgstr "" "Má»™t nhóm %{monster} khao khát đạt được vinh quang lá»›n hÆ¡n mong muốn được " "tham gia cùng ngươi.\n" "Ngươi có chấp nhận không?" msgid "Followers" msgstr "" msgid "" "The %{monster} is swayed by your diplomatic tongue, and offers to join your " "army for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{monster} bị dao động bởi cái lưỡi ngoại giao cá»§a ngươi, và đỠnghị gia " "nhập quân đội cá»§a ngươi vá»›i số tiá»n %{gold} vàng.\n" "Ngươi có chấp nhận không?" msgid "" "The creatures are swayed by your diplomatic\n" "tongue, and make you an offer:\n" "\n" msgstr "" "Các sinh vật bị ảnh hưởng bởi cái lưỡi ngoại giao\n" "cá»§a ngươi, và đưa ra lá»i đỠnghị cho ngươi:\n" "\n" msgid "" "%{offer} of the %{total} %{monster} will join your army, and the rest will " "leave you alone, for the sum of %{gold} gold.\n" "Do you accept?" msgstr "" "%{offer} cá»§a %{total} %{monster} sẽ gia nhập quân đội ngươi, và phần còn lại " "sẽ để ngươi yên, vá»›i tổng số là %{gold} vàng.\n" "Ngươi có chấp thuận không?" msgid "" "All %{offer} of the %{monster} will join your army for the sum of %{gold} " "gold.\n" "Do you accept?" msgstr "" "Tất cả %{offer} cá»§a %{monster} sẽ gia nhập quân đội cá»§a ngươi vá»›i giá là " "%{gold} vàng.\n" "Ngươi có chấp thuận không?" msgid "(Rate: %{percent})" msgstr "(Mức: %{percent})" msgid "off" msgstr "tắt" msgid "Music" msgstr "Âm nhạc" msgid "Effects" msgstr "Hiệu ứng" msgid "MIDI" msgstr "MIDI" msgid "MIDI Expansion" msgstr "MIDI Mở rá»™ng" msgid "External" msgstr "Bên ngoài" msgid "Music Type" msgstr "Loại nhạc" msgid "3D Audio" msgstr "Âm thanh 3D" msgid "Toggle ambient music level." msgstr "Chuyển đổi mức âm nhạc xung quanh." msgid "Toggle foreground sounds level." msgstr "Chuyển đổi mức âm thanh ná»n trước." msgid "Change the type of music." msgstr "Thay đổi loại nhạc." #, fuzzy msgid "Toggle the 3D effect of foreground sounds." msgstr "Chuyển đổi hiệu ứng 3D cá»§a âm thanh ná»n trước." msgid "Build a new ship:" msgstr "Äóng má»™t tàu má»›i:" msgid "Resource cost:" msgstr "Chi phí tài nguyên:" msgid "Total: " msgstr "Tổng: " msgid "Need: " msgstr "Cần: " msgid "New Game" msgstr "Trò chÆ¡i Má»›i" msgid "Start a single or multi-player game." msgstr "Bắt đầu má»™t trò chÆ¡i đơn hoặc nhiá»u ngưá»i chÆ¡i." msgid "Load Game" msgstr "Tải Trò chÆ¡i" msgid "Load a previously saved game." msgstr "Tải má»™t trò chÆ¡i đã lưu trước đó." msgid "Save Game" msgstr "Lưu Trò chÆ¡i" msgid "Save the current game." msgstr "Lưu trò chÆ¡i hiện tại." msgid "Quit" msgstr "Thoát" msgid "Quit out of Heroes of Might and Magic II." msgstr "Thoát khá»i Heroes of Might and Magic II." msgid "Language" msgstr "Ngôn ngữ" msgid "Graphics" msgstr "Äồ há»a" msgid "Black & White" msgstr "Äen & Trắng" msgid "Mouse Cursor" msgstr "Con trá» Chuá»™t" msgid "Color" msgstr "Màu" msgid "Text Support" msgstr "Há»— trợ Văn bản" msgid "Change the language of the game." msgstr "Thay đổi ngôn ngữ cá»§a trò chÆ¡i." msgid "Select Game Language" msgstr "Chá»n Ngôn ngữ Trò chÆ¡i" msgid "Change the graphics settings of the game." msgstr "Thay đổi đồ há»a cá»§a trò chÆ¡i." msgid "Toggle colored cursor on or off. This is only an aesthetic choice." msgstr "" "Chuyển đổi con trá» màu bật hoặc tắt. Äây chỉ là má»™t sá»± lá»±a chá»n thẩm mỹ." msgid "" "Toggle text support mode to output extra information about windows and " "events in the game." msgstr "" "Chuyển đổi chế độ há»— trợ văn bản để xuất thêm thông tin vá» các cá»­a sổ và sá»± " "kiện trong trò chÆ¡i." msgid "" "Map\n" "Difficulty" msgstr "" "Äá»™ khó\n" "Bản đồ" msgid "" "Game\n" "Difficulty" msgstr "" "Äá»™ khó\n" "Trò chÆ¡i" msgid "Rating" msgstr "Xếp hạng" msgid "Map Size" msgstr "Cỡ Bản đồ" msgid "Opponents" msgstr "Äối thá»§" msgid "Class" msgstr "Chá»§ng tá»™c" msgid "" "Victory\n" "Conditions" msgstr "" "Äiá»u kiện\n" "Chiến thắng" msgid "" "Loss\n" "Conditions" msgstr "" "Äiá»u kiện\n" "Thua" msgid "First select recipients!" msgstr "Äầu tiên chá»n ngưá»i nhận!" msgid "You cannot select %{resource}!" msgstr "Ngươi không thể chá»n %{resource}!" #, fuzzy msgid "Set %{resource-type} Count" msgstr "Bắn %{monster}" msgid "Select Recipients" msgstr "Chá»n Ngưá»i nhận" msgid "Your Funds" msgstr "Ngân quỹ cá»§a Ngươi" msgid "Planned Gift" msgstr "Dá»± tính Quà tặng" msgid "Gift from %{name}" msgstr "Quà từ %{name}" msgid "Resolution" msgstr "Phân giải" msgid "Fullscreen" msgstr "Toàn màn hình" msgid "window|Mode" msgstr "Chế độ" msgid "Windowed" msgstr "Cá»­a sổ" msgid "V-Sync" msgstr "V-Sync" msgid "FPS" msgstr "FPS" msgid "System Info" msgstr "Thông tin Hệ thống" msgid "Change the resolution of the game." msgstr "Thay đổi độ phân giải cá»§a trò chÆ¡i." msgid "Select Game Resolution" msgstr "Chá»n Äá»™ phân giải Trò chÆ¡i" msgid "Toggle between fullscreen and windowed modes." msgstr "Chuyển đổi giữa chế độ toàn màn hình và cá»­a sổ." msgid "" "The V-Sync option can be enabled to resolve flickering issues on some " "monitors." msgstr "" "Tùy chá»n V-Sync có thể được bật để giải quyết vấn đỠnhấp nháy trên má»™t số " "màn hình." msgid "Show extra information such as FPS and current time." msgstr "Hiển thị thêm thông tin như FPS và thá»i gian hiện tại." msgid "Hotkey: " msgstr "Phím nóng: " msgid "Category: " msgstr "Danh mục: " msgid "Event: " msgstr "Sá»± kiện: " msgid "Hot Keys:" msgstr "Phím tắt:" msgid "Hide" msgstr "Ẩn" msgid "Show" msgstr "Hiện" msgid "Interface" msgstr "Giao diện" msgid "Interface Type" msgstr "Kiểu Giao diện" msgid "Toggle the type of interface you want to use." msgstr "Chuyển đổi loại giao diện ngươi muốn sá»­ dụng." msgid "Toggle interface visibility." msgstr "Chuyển đổi khả năng hiển thị giao diện." msgid "Scroll Speed" msgstr "Tốc độ Cuá»™n" msgid "Sets the speed at which you scroll the window." msgstr "Äặt tốc độ cuá»™n cá»­a sổ." msgid "Select Game Language:" msgstr "Chá»n Ngôn ngữ Trò chÆ¡i:" #, fuzzy msgid "Select Language:" msgstr "Chá»n Ngôn ngữ Trò chÆ¡i:" msgid "Click to choose the selected language." msgstr "Bấm để chá»n ngôn ngữ đã chá»n." msgid "%{name} has gained a level." msgstr "%{name} đã đạt được má»™t mức độ." msgid "%{skill} +1" msgstr "%{skill} +1" msgid "You have learned %{skill}." msgstr "Ngươi đã há»c %{skill}." msgid "" "%{name} has gained a level.\n" "\n" "%{skill} +1" msgstr "" "%{name} đã đạt được má»™t mức độ.\n" "\n" "%{skill} +1" msgid "" "You may learn either:\n" "%{skill1}\n" "or\n" "%{skill2}" msgstr "" "Ngươi có thể há»c má»™t trong hai:\n" "%{skill1}\n" "hoặc\n" "%{skill2}" msgid "Learn %{secondary-skill}" msgstr "" msgid "n/a" msgstr "n/a" msgid "" "Please inspect our fine wares. If you feel like offering a trade, click on " "the items you wish to trade with and for." msgstr "" "Hãy kiểm tra đồ tốt cá»§a chúng tôi. Nếu ngươi muốn cung cấp má»™t giao dịch, " "hãy nhấp vào các mặt hàng ngươi muốn giao dịch." msgid "" "You have received quite a bargain. I expect to make no profit on the deal. " "Can I interest you in any of my other wares?" msgstr "" "Ngươi đã nhận được khá há»i. Ta hy vá»ng sẽ không kiếm được lợi nhuận từ thá»a " "thuận này. Ta có thể khiến ngươi quan tâm đến bất kỳ sản phẩm nào khác cá»§a " "ta?" msgid "I can offer you %{count} for 1 unit of %{resfrom}." msgstr "Ta có thế phục vụ ngươi %{count} cho 1 đơn vị cá»§a %{resfrom}." msgid "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." msgstr "" "Ta có thể phục vụ ngươi má»™t đơn vị cá»§a %{resto} cho %{count} đơn vị cá»§a " "%{resfrom}." msgid "Min" msgstr "Min" msgid "Qty to trade" msgstr "Số lượng trao đổi" msgid "Trading Post" msgstr "Trạm Giao dịch" msgid "Your Resources" msgstr "Tài nguyên cá»§a Ngươi" msgid "Available Trades" msgstr "Giao dịch Có sẵn" msgid "guarded by %{count} %{monster}" msgstr "bảo vệ bởi %{count} %{monster}" msgid "guarded by " msgstr "bảo vệ bởi " msgid "(available: %{count})" msgstr "(có sẵn: %{count})" msgid "(empty)" msgstr "(rá»—ng)" msgid "already learned" msgstr "đã há»c" msgid "treeOfKnowledge|free" msgstr "miá»…n phí" msgid "already claimed" msgstr "đã yêu cầu" msgid "not claimed" msgstr "chưa yêu cầu" msgid "already knows this skill" msgstr "đã biết kỹ năng này" msgid "already has max skills" msgstr "kỹ năng này đã tối Ä‘a" msgid "(already visited)" msgstr "(đã tá»›i)" msgid "(not visited)" msgstr "(chưa tá»›i)" msgid "%{color} Barrier" msgstr "%{color} Rào chắn" msgid "(tent visited)" msgstr "(lá»u đã tá»›i)" msgid "%{color} Tent" msgstr "%{color} Lá»u" msgid "Road" msgstr "ÄÆ°á»ng" msgid "(digging ok)" msgstr "(đào được)" msgid "(no digging)" msgstr "(không đào được)" msgid "penalty: %{cost}" msgstr "phạt: %{cost}" msgid "Defenders:" msgstr "Bên thá»§:" msgid "Unknown" msgstr "Không biết" msgid "heroQuickInfo|(Level %{level})" msgstr "(Cấp độ %{level})" msgid "Attack:" msgstr "Tấn công:" msgid "Defense:" msgstr "Phòng thá»§:" msgid "Spell Power:" msgstr "Sức mạnh Phép:" msgid "Knowledge:" msgstr "Trí thức:" msgid "Spell Points:" msgstr "Äiểm Phép thuật:" msgid "Move Points:" msgstr "Äiểm Di chuyển:" msgid "Uncharted Territory" msgstr "Lãnh thổ Chưa khám phá" msgid "Cost per troop:" msgstr "Giá má»—i quân:" msgid "Available: %{count}" msgstr "Hiện có: %{count}" msgid "Number to buy:" msgstr "Số lượng mua:" msgid "Recruit selected monsters." msgstr "Chiêu má»™ quái vật đã chá»n." msgid "Select maximum monsters to be recruited." msgstr "Chá»n tối Ä‘a quá vật để chiêu má»™." msgid "Select only 1 monster to be recruited." msgstr "Chỉ chá»n 1 quái vật để chiêu má»™." #, fuzzy msgid "Select this game resolution." msgstr "Chá»n Äá»™ phân giải Trò chÆ¡i" msgid "" "Selecting this resolution will set a resolution that is scaled from the " "original resolution (%{resolution}) by multiplying it with the number in the " "brackets (%{scale}).\n" "\n" "A resolution with a clean integer number (2.0x, 3.0x etc.) will usually look " "better because the pixels are upscaled evenly in both horizontal and " "vertical directions." msgstr "" msgid "Select Game Resolution:" msgstr "Chá»n Äá»™ phân giải:" msgid "Click to apply the selected resolution." msgstr "Nhấp để áp dụng độ phân giải đã chá»n." msgid "Click to apply the entered text." msgstr "Nhấp để áp dụng văn bản đã nhập." msgid "Click to open the Virtual Keyboard dialog." msgstr "Nhấp để mở Bàn phím Ảo." msgid "Open Virtual Keyboard" msgstr "Mở Bàn phím Ảo" #, fuzzy msgid "How many creatures do you wish to move?" msgstr "Bao nhiêu quân sẽ được di chuyển?" #, fuzzy msgid "Select how many units to separate into:" msgstr "Chá»n thị trấn để dịch chuyển tá»›i." msgid "Map: " msgstr "Bản đồ: " msgid "" "\n" "\n" "Month: " msgstr "" "\n" "\n" "Tháng: " msgid ", Week: " msgstr ", Tuần: " msgid ", Day: " msgstr ", Ngày: " msgid "" "\n" "\n" "Location: " msgstr "" "\n" "\n" "Vị trí: " msgid "Are you sure you want to delete file:" msgstr "Ngươi có chắc muốn xóa file:" msgid "Warning" msgstr "Cảnh báo" msgid "Click to save the current game." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Click to load a previously saved game." msgstr "Nhấp để tải chò trÆ¡i đã lưu trước đây." msgid "File to Save:" msgstr "Tệp để Lưu:" msgid "File to Load:" msgstr "Tệp để Tải:" msgid "Terrain object" msgstr "Äối tượng địa hình" msgid "Accept the choice made." msgstr "Chấp nhận sá»± lá»±a chá»n được thá»±c hiện." msgid "Select Skill:" msgstr "Chá»n Kỹ năng:" msgid "Select Spell:" msgstr "Chá»n Phép:" msgid "Select Artifact:" msgstr "Chá»n Bảo vật:" msgid "Select Monster:" msgstr "Chá»n Quái vật:" msgid "Select Hero:" msgstr "Chá»n Tướng:" msgid "race|Random" msgstr "Ngẫu nhiên" #, fuzzy msgid "Click to start placing the selected hero." msgstr "Nhấp để bắt đầu đặt lâu đài/thị trấn đã chá»n" #, fuzzy msgid "%{color} %{race}" msgstr "%{color} %{race} tướng" msgid "You will place" msgstr "Ngươi sẽ đặt" msgid "Click to select this class." msgstr "Nhấp để chá»n chá»§ng tá»™c." msgid "Click to select this color." msgstr "Nhấp để chá»n màu này." msgid "Select Treasure:" msgstr "Chá»n Kho báu:" msgid "Select Ocean Object:" msgstr "Chá»n Äối tượng Äại dương:" msgid "Castle/town placing" msgstr "Äặt Lâu đài/thị trấn" msgid "doubleLinedRace|Neutral" msgstr "Trung lập" msgid "Click to start placing the selected castle/town." msgstr "Nhấp để bắt đầu đặt lâu đài/thị trấn đã chá»n" msgid "Click to select town placing." msgstr "Nhấp để chá»n thị trấn đặt" msgid "Click to select castle placing." msgstr "Nhấp để chá»n lâu đài đặt" msgid "%{color} %{race} %{townOrCastle}" msgstr "%{color} %{race} %{townOrCastle}" msgid "race|Neutral" msgstr "Trung lập" #, fuzzy msgid "Select Dwelling:" msgstr "Chá»n Phép:" #, fuzzy msgid "Select Landscape Object:" msgstr "Chá»n Äối tượng Äại dương:" msgid "Mine placing" msgstr "" #, fuzzy msgid "" "Resource\n" "type:" msgstr "Tài nguyên" #, fuzzy msgid "%{mineName} appearance:" msgstr "%{name} cái %{race}" #, fuzzy msgid "Click to select %{object} as the resource generator to be placed." msgstr "Nhấp vào đây để chá»n kịch bản để chÆ¡i." #, fuzzy msgid "Select Mountain Object:" msgstr "Chá»n Äối tượng Äại dương:" #, fuzzy msgid "Select Rock Object:" msgstr "Chá»n Äối tượng Äại dương:" #, fuzzy msgid "Select Tree Object:" msgstr "Chá»n Äối tượng Äại dương:" #, fuzzy msgid "Select Power Up Object:" msgstr "Chá»n Äối tượng Äại dương:" #, fuzzy msgid "Select Adventure Object:" msgstr "Chá»n Äối tượng Äại dương:" msgid "Players Icon" msgstr "Biểu tượng Ngưá»i chÆ¡i" #, fuzzy msgid "" "Indicates how many players total are in the scenario. Any positions not " "occupied by human players will be occupied by computer players." msgstr "" "Cho biết tổng số ngưá»i chÆ¡i trong kịch bản. Bất kỳ vị trí nào không có con " "ngưá»i chiếm giữ sẽ do ngưá»i chÆ¡i máy tính chiếm giữ." msgid "" "Indicates whether the map\n" "is small (36 x 36), medium\n" "(72 x 72), large (108 x 108),\n" "or extra large (144 x 144)." msgstr "" "Cho biết bản đồ\n" "là nhá» (36 x 36), thưá»ng\n" "(72 x 72), lá»›n (108 x 108),\n" "hay cá»±c lá»›n (144 x 144)." msgid "Size Icon" msgstr "Cỡ Biểu tượng" msgid "Map Type" msgstr "Kiểu Bản đồ" #, fuzzy msgid "" "Indicates whether the map is made for \"The Succession Wars\", \"The Price " "of Loyalty\" or \"Resurrection\" version of the game." msgstr "" "Cho biết bản đồ được tạo cho phiên bản \"Cuá»™c chiến kế vị\" hay \"Cái giá " "cá»§a lòng trung thành\" cá»§a trò chÆ¡i." msgid "Map Type:\n" msgstr "Kiểu Bản đồ:\n" msgid "The Succession Wars" msgstr "Cuá»™c chiến Kế vị" msgid "The Price of Loyalty" msgstr "Giá cá»§a Lòng Trung Thành" msgid "Resurrection" msgstr "Hồi sinh" #, fuzzy msgid "" "\n" "\n" "Language:\n" msgstr "Ngôn ngữ" msgid "Lose all your heroes and towns." msgstr "Mất tất cả các tướng và thành." msgid "Lose a specific town." msgstr "Mất má»™t thành cụ thể." msgid "Lose a specific hero." msgstr "Mất má»™t tướng cụ thể." msgid "Run out of time. Fail to win by a certain point." msgstr "Hết thá»i gian. Không thể giành chiến thắng vá»›i thá»i gian nhất định." msgid "Loss Condition" msgstr "Äiá»u kiện Thua" msgid "Defeat all enemy heroes and towns." msgstr "Tiêu diệt tất cả các tướng và thành địch." msgid "Capture a specific town." msgstr "Chiếm má»™t thành cụ thể." msgid "Defeat a specific hero." msgstr "Tiêu diệt má»™t tướng cụ thể." msgid "Find a specific artifact." msgstr "Tìm má»™t bảo vật cụ thể." #, fuzzy msgid "Your side must defeat the opposing side." msgstr "Phe cá»§a ngươi đánh bại phe đối lập." msgid "Accumulate a large amount of gold." msgstr "Tích lÅ©y má»™t lượng lá»›n vàng." msgid "Victory Condition" msgstr "Äiá»u kiện Thắng" msgid "Map difficulty:" msgstr "Äá»™ khó bản đồ:" msgid "N" msgstr "N" #, fuzzy msgid "No maps exist at that size." msgstr "Không có bản đồ nào ở cỡ này" msgid "Small Maps" msgstr "Bản đồ Nhá»" msgid "View only maps of size small (36 x 36)." msgstr "Chỉ xem những bản đồ cỡ nhá» (36x36)." msgid "Medium Maps" msgstr "Bản đồ Thưá»ng" msgid "View only maps of size medium (72 x 72)." msgstr "Chỉ xem những bản đồ cỡ thưá»ng (72x72)." msgid "Large Maps" msgstr "Bản đồ Rá»™ng" msgid "View only maps of size large (108 x 108)." msgstr "Chỉ xem những bản đồ cỡ lá»›n (108x108)." msgid "Extra Large Maps" msgstr "Bản đồ Siêu rá»™ng" msgid "View only maps of size extra large (144 x 144)." msgstr "Chỉ xem những bản đồ cỡ siêu lá»›n (144x144)." msgid "All Maps" msgstr "Tất cả Bản đồ" msgid "View all maps, regardless of size." msgstr "Xem tất cả các bản đồ, bất kể kích thước." msgid "Selected Name" msgstr "Chá»n Tên" msgid "The name of the currently selected map." msgstr "Tên cá»§a bản đồ hiện được chá»n." msgid "Selected Map Difficulty" msgstr "Chá»n Äá»™ khó cá»§a Bản đồ" msgid "" "The map difficulty of the currently selected map. The map difficulty is " "determined by the scenario designer. More difficult maps might include more " "or stronger enemies, fewer resources, or other special conditions making " "things tougher for the human player." msgstr "" "Äá»™ khó bản đồ cá»§a bản đồ hiện được chá»n. Äá»™ khó cá»§a bản đồ được xác định bởi " "ngưá»i thiết kế kịch bản. Các bản đồ khó hÆ¡n có thể bao gồm nhiá»u kẻ thù hÆ¡n " "hoặc mạnh hÆ¡n, ít tài nguyên hÆ¡n hoặc các Ä‘iá»u kiện đặc biệt khác khiến má»i " "thứ trở nên khó khăn hÆ¡n đối vá»›i ngưá»i chÆ¡i." msgid "Selected Description" msgstr "Chá»n Mô tả" msgid "The description of the currently selected map." msgstr "Mô tả cá»§a bản đồ hiện được chá»n." msgid "Jump" msgstr "Nhảy" msgid "Hero Speed" msgstr "Tốc độ Tướng" msgid "Don't Show" msgstr "Không Hiện" msgid "Enemy Speed" msgstr "Tốc độ Äịch" msgid "Auto Resolve" msgstr "Tá»± động Giải quyết" msgid "Auto, No Spells" msgstr "Tá»± động, Không Phép" msgid "Battles" msgstr "Chiến trưá»ng" #, fuzzy msgid "combatMode|Manual" msgstr "Thá»§ công" msgid "Change the speed at which your heroes move on the main screen." msgstr "Thay đổi tốc độ di chuyển cá»§a các tướng trên màn hình chính." #, fuzzy msgid "" "Sets the speed that computer heroes move at. You can also elect not to view " "computer movement at all." msgstr "" "Äặt tốc độ mà tướng A.I. di chuyển. Ngươi cÅ©ng có thể chá»n không xem tướng A." "I. di chuyển." msgid "Change the interface settings of the game." msgstr "Thay đổi giao diện cá»§a trò chÆ¡i." msgid "Interface Settings" msgstr "Cài đặt Giao diện" msgid "Toggle instant battle mode." msgstr "Chuyển đổi chế độ chiến đấu ngay lập tức." msgid "Att." msgstr "Công." msgid "Def." msgstr "Thá»§." msgid "Power" msgstr "Sức" msgid "Knowl" msgstr "Trí" msgid "1st" msgstr "Số 1" msgid "2nd" msgstr "Số 2" msgid "3rd" msgstr "Số 3" msgid "4th" msgstr "Số 4" msgid "5th" msgstr "Số 5" msgid "6th" msgstr "Số 6" msgid "Oracle: Player Rankings" msgstr "Tiên tri: Thứ hạng Ngưá»i chÆ¡i" msgid "Thieves' Guild: Player Rankings" msgstr "Băng cướp: Xếp hạng Ngưá»i chÆ¡i" msgid "Number of Towns:" msgstr "Số Thị trấn:" msgid "Number of Castles:" msgstr "Số Lâu đài:" msgid "Number of Heroes:" msgstr "Số Tướng:" msgid "Gold in Treasury:" msgstr "Vàng trong Kho:" msgid "Wood & Ore:" msgstr "Gá»— & Äá:" msgid "Gems, Cr, Slf & Mer:" msgstr "Kim cương và các thứ khác:" msgid "Obelisks Found:" msgstr "Äài tưởng niệm Tìm được:" msgid "Artifacts:" msgstr "Bảo vật:" msgid "Total Army Strength:" msgstr "Tổng Sức mạnh Quân đội:" msgid "Income:" msgstr "Thu nhập:" msgid "Best Hero:" msgstr "Tướng Tốt nhất:" msgid "Best Hero Stats:" msgstr "Tình trạng Tướng Tốt nhất:" msgid "Personality:" msgstr "Nhân cách:" msgid "Best Monster:" msgstr "Quái vật Mạnh nhất:" #, fuzzy msgid "Random Castle Name" msgstr "Ngẫu nhiên Lâu đài" #, fuzzy msgid "Random Town Name" msgstr "Ngẫu nhiên Thị trấn" #, fuzzy msgid "Allow Castle build" msgstr "Lâu đài Mây" #, fuzzy msgid "Default Buildings" msgstr "Hành động Mặc định" #, fuzzy msgid "Default Army" msgstr "Hành động Mặc định" #, fuzzy msgid "Castle Army" msgstr "Lâu đài" #, fuzzy msgid "Town Army" msgstr "Thị trấn" msgid "Click to change the Castle name. Right-click to reset to default." msgstr "" #, fuzzy msgid "Enter Castle name" msgstr "Mất tướng: %{name}." msgid "Allow to build a castle in this town." msgstr "" msgid "Toggle the use of default buildings. Custom buildings will be reset!" msgstr "" msgid "Toggle building construction restriction mode." msgstr "" msgid "Restrict Building Construction" msgstr "" msgid "Use default defenders army." msgstr "" msgid "Set custom Castle Army. Right-click to reset unit." msgstr "" #, fuzzy msgid "Message Text:" msgstr "Thanh Tin nhắn" msgid "Reward:" msgstr "" msgid "Player colors allowed to get event:" msgstr "" msgid "Computer colors allowed to get event:" msgstr "" msgid "First day of occurrence:" msgstr "" msgid "Repeat period (days):" msgstr "" msgid "Allow %{color} human player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a human." msgstr "" msgid "Allow %{color} computer player to get event" msgstr "" msgid "" "If this checkbox is checked, this event will trigger for the %{color} player " "if they are controlled by a computer." msgstr "" #, fuzzy msgid "Message:" msgstr "Thanh Tin nhắn" #, fuzzy msgid "Click to save the Event properties." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "No resources will be given as a reward." msgstr "" #, fuzzy msgid "Resources" msgstr "Tài nguyên" msgid "Resources will be given as a reward." msgstr "" #, fuzzy msgid "Click here to change the event message." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Event Message Text" msgstr "" msgid "Day: %{day}" msgstr "Ngày: %{day}" msgid "Daily Events" msgstr "" #, fuzzy msgid "Click to save the events." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." #, fuzzy msgid "Add Event" msgstr "Sá»± kiện" #, fuzzy msgid "Add an additional event." msgstr "Lập trình Bổ sung" #, fuzzy msgid "Edit Event" msgstr "Sá»± kiện" #, fuzzy msgid "Edit an existing event." msgstr "Tải má»™t bản đồ đã có." msgid "Delete Event" msgstr "" #, fuzzy msgid "Delete an existing event." msgstr "Tải má»™t bản đồ đã có." #, fuzzy msgid "Effects:" msgstr "Hiệu ứng" #, fuzzy msgid "Conditions:" msgstr "" "Äiá»u kiện\n" "Thua" msgid "Cancel event after first visit" msgstr "" msgid "Computer colors allowed to get the event:" msgstr "" #, fuzzy msgid "Set Experience value" msgstr "Kinh nghiệm" msgid "Artifact" msgstr "Bảo vật" msgid "No artifact will be given by the event." msgstr "" #, fuzzy msgid "Delete Artifact" msgstr "Chá»n Bảo vật:" #, fuzzy msgid "Delete an artifact from the event." msgstr "Tải má»™t bản đồ đã có." msgid "No Secondary Skill will be given by the event." msgstr "" #, fuzzy msgid "Secondary Skill" msgstr "Chá»n Kỹ năng:" msgid "Delete Secondary Skill" msgstr "" msgid "Delete the Secondary Skill from the event." msgstr "" msgid "No resources will be part of this event." msgstr "" msgid "These resources will be a part of the event." msgstr "" msgid "" "If this checkbox is checked, the event will trigger only once. If not " "checked, the event will trigger every time one of the specified players " "crosses the event tile." msgstr "" #, fuzzy msgid "%{objects} cannot be placed on water." msgstr "Thị trấn không thể đặt trên nước." #, fuzzy msgid "" "The Ultimate Artifact can only be placed on terrain where digging is " "possible." msgstr "Bảo vật không thể đặt trên nước." #, fuzzy msgid "%{objects} must be placed on water." msgstr "Äối tượng đại dương phải đặt trên mặt nước." msgid "Objects cannot be placed outside the map." msgstr "Äối tượng không thể đặt ra ngoài bản đồ." #, fuzzy msgid "Action objects must be placed on clear tiles." msgstr "Äối tượng đại dương phải đặt trên mặt nước." #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? All unsaved changes will be " "lost." msgstr "" "Ngươi có chắc chắn muốn tạo bản đồ má»›i không? (Má»i thay đổi chưa được lưu " "đối vá»›i bản đồ hiện tại sẽ bị mất.)" msgid "Editor" msgstr "Biên tập" msgid "" "Are you sure you want to load a new map? (Any unsaved changes to the current " "map will be lost.)" msgstr "" "Ngươi có chắc chắn muốn tải bản đồ má»›i không? (Má»i thay đổi chưa được lưu " "đối vá»›i bản đồ hiện tại sẽ bị mất.)" msgid "" "Are you sure you want to create a new map? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Ngươi có chắc chắn muốn tạo bản đồ má»›i không? (Má»i thay đổi chưa được lưu " "đối vá»›i bản đồ hiện tại sẽ bị mất.)" msgid "" "MAIN\n" "MENU" msgstr "" #, fuzzy msgid "" "START\n" "MAP" msgstr "LÀM LẠI" msgid "Main Menu" msgstr "Trình đơn Chính" #, fuzzy msgid "" "Do you wish to return to the game's Main Menu? (Any unsaved changes to the " "current map will be lost.)" msgstr "" "Ngươi có chắc chắn muốn tạo bản đồ má»›i không? (Má»i thay đổi chưa được lưu " "đối vá»›i bản đồ hiện tại sẽ bị mất.)" msgid "Unsaved Changes" msgstr "" msgid "" "This map has either terrain changes, undo history or has not yet been saved " "to a file.\n" "\n" "Do you wish to save the current map?" msgstr "" msgid "Unplayable Map" msgstr "" msgid "" "This map is not playable. You need at least one human player for the map to " "be playable." msgstr "" #, fuzzy msgid "Start Map" msgstr "ChÆ¡i lại" #, fuzzy msgid "" "Do you wish to leave the Editor and start the map? (Any unsaved changes to " "the current map will be lost.)" msgstr "" "Ngươi có chắc chắn muốn tải bản đồ má»›i không? (Má»i thay đổi chưa được lưu " "đối vá»›i bản đồ hiện tại sẽ bị mất.)" #, fuzzy msgid "Create a new map from scratch." msgstr "bắt đầu bản đồ má»›i" msgid "New Map" msgstr "Bản đồ Má»›i" msgid "Load Map" msgstr "Tải Bản đồ" msgid "Load an existing map." msgstr "Tải má»™t bản đồ đã có." msgid "Save Map" msgstr "Lưu Bản đồ" msgid "Save the current map." msgstr "Lưu bản đồ hiện tại." msgid "Quit out of the map editor." msgstr "Thoát khá»i biên tập bản đồ." #, fuzzy msgid "Return to the game's Main Menu." msgstr "Nhấp để quay lại màn hình chính." msgid "Leave the Editor and play the map in the Standard Game mode." msgstr "" msgid "Input %{object} text" msgstr "" #, fuzzy msgid "Set Random Ultimate Artifact Radius" msgstr "Ngẫu nhiên Bảo vật Tối thượng" msgid "%{object} has no properties to change." msgstr "" #, fuzzy msgid "This artifact" msgstr "vá»›i 1 bảo vật." msgid "The total number of obelisks is %{count}." msgstr "" msgid "Roads" msgstr "ÄÆ°á»ng" msgid "Streams" msgstr "Suối" msgid "" "A maximum of %{count} heroes of the same color can be placed on the map." msgstr "" msgid "Failed to update player information." msgstr "" #, fuzzy msgid "Only one Random Ultimate Artifact can be placed on the map." msgstr "Bảo vật không thể đặt trên nước." msgid "A maximum of %{count} obelisks can be placed on the map." msgstr "" #, fuzzy msgid "The map is corrupted." msgstr "File lưu bị há»ng." msgid "Unable to locate data directory to save the map." msgstr "" #, fuzzy msgid "Unable to create a directory to save the map." msgstr "Dùng để xóa vật thể trên bản đồ." #, fuzzy msgid "Unable to locate a directory to save the map." msgstr "Dùng để xóa vật thể trên bản đồ." #, fuzzy msgid "Are you sure you want to overwrite the existing map?" msgstr "Ngươi có chắc chắn muốn ghi đè lưu bằng tên này không?" msgid "Map saved to: " msgstr "" #, fuzzy msgid "Failed to save the map." msgstr "Tệp để Lưu:" #, fuzzy msgid "Used to place %{object}." msgstr "Dùng để đặt má»™t tướng." #, fuzzy msgid "Select object type" msgstr "Chá»n Äối tượng Äại dương:" #, fuzzy msgid "" "Click here to\n" "select a monster." msgstr "Nhấp vào đây để chá»n kịch bản để chÆ¡i." #, fuzzy msgid "" "Click here to\n" "select another monster." msgstr "Hãy chá»n má»™t tướng khác." msgid "" "Cell\n" "Details" msgstr "" #, fuzzy msgid "Erase" msgstr "Chế độ Xóa" msgid "Mountains" msgstr "Núi" #, fuzzy msgid "Rocks" msgstr "Äá" msgid "Trees" msgstr "Cây" #, fuzzy msgid "Water Objects" msgstr "Äối tượng Äất hoang" #, fuzzy msgid "Miscellaneous" msgstr "Fineous" msgid "Artifacts" msgstr "Bảo vật" msgid "Dwellings" msgstr "" msgid "Mines" msgstr "Má»" #, fuzzy msgid "Power-ups" msgstr "Sức" msgid "Treasures" msgstr "Kho báu" msgid "Heroes" msgstr "Tướng" msgid "Towns" msgstr "Thị trấn" #, fuzzy msgid "editorErasure|Landscape objects" msgstr "Chá»n Äối tượng Äại dương:" msgid "editorErasure|Adventure non pickable objects" msgstr "" msgid "editorErasure|Castles" msgstr "" msgid "editorErasure|Adventure pickable objects" msgstr "" msgid "editorErasure|Monsters" msgstr "" msgid "editorErasure|Heroes" msgstr "" msgid "editorErasure|Roads" msgstr "" msgid "editorErasure|Streams" msgstr "" msgid "" "Draws terrain in\n" "%{size} by %{size} square increments." msgstr "" "Vẽ địa hình vá»›i nét\n" "%{size} bằng %{size} ô vuông." msgid "" "Erases objects in\n" "%{size} by %{size} square increments." msgstr "" "Xóa đối tượng vá»›i cỡ\n" "%{size} bằng %{size} ô vuông." msgid "Small Brush" msgstr "Nét Nhá»" msgid "Medium Brush" msgstr "Nét Thưá»ng" msgid "Large Brush" msgstr "Nét To" msgid "Area Fill" msgstr "Khu vá»±c Äiá»n vào" msgid "Used to click and drag for filling in large areas." msgstr "Nhấp và kéo để Ä‘iá»n vào các khu vá»±c rá»™ng lá»›n." msgid "Clear Area" msgstr "Khu vá»±c Xóa" msgid "Used to click and drag for clearing large areas." msgstr "Nhấp và kéo để xóa các khu vá»±c rá»™ng lá»›n." msgid "" "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or " "eliminates the penalty.)" msgstr "" "Tốn %{rate} lần di chuyển bình thưá»ng cho tất cả các tướng. (Tìm đưá»ng làm " "giảm hoặc loại bá» hình phạt.)" msgid "Traversable only by boat." msgstr "Chỉ có thể di chuyển bằng thuyá»n." msgid "No special modifiers." msgstr "Không có sá»­a đổi đặc biệt." msgid "Toggle the erasure of %{type} objects." msgstr "Chuyển đổi tính năng xóa đối tượng %{type}." msgid "" "Objects of this type will be deleted with the Erase tool. Left-click here to " "deselect this type. Press and hold this button to deselect all other object " "types." msgstr "" "Các đối tượng thuá»™c loại này sẽ bị xóa bằng công cụ Xóa. Nhấn chuá»™t trái vào " "đây để bá» chá»n loại này. Nhấn và giữ nút này để bá» chá»n tất cả các loại đối " "tượng khác." msgid "" "Objects of this type will NOT be deleted with the Erase tool. Left-click " "here to select this type. Press and hold this button to select all other " "object types." msgstr "" "Các đối tượng thuá»™c loại này sẽ KHÔNG bị xóa bằng công cụ Xóa. Nhấn chuá»™t " "trái vào đây để chá»n loại này. Nhấn và giữ nút này để chá»n tất cả các loại " "đối tượng khác." msgid "Terrain Mode" msgstr "Chế độ Äịa hình" msgid "Used to draw the underlying grass, dirt, water, etc. on the map." msgstr "Dùng để vẽ cá», bụi bẩn, nước, v.v. lên bản đồ." #, fuzzy msgid "Landscape Objects Mode" msgstr "Chế độ Vật thể" #, fuzzy msgid "" "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." msgstr "Dùng để đặt các vật thể (núi, cây, kho báu, v.v.v) lên bản đồ." msgid "Detail Mode" msgstr "Chế độ Chi tiết" #, fuzzy msgid "Used for special editing of action objects." msgstr "Dùng để hiệu chỉnh đặc biệt cho quái vật, tướng và thị trấn." #, fuzzy msgid "Adventure Objects Mode" msgstr "Tùy chá»n Khám phá" #, fuzzy msgid "" "Used to place adventure objects (artifacts, dwellings, mines, treasures, " "etc.) on the map." msgstr "Dùng để đặt các vật thể (núi, cây, kho báu, v.v.v) lên bản đồ." #, fuzzy msgid "Kingdom Objects Mode" msgstr "Chế độ Vật thể" #, fuzzy msgid "Used to place kingdom objects (towns, castles and heroes) on the map." msgstr "Dùng để đặt các vật thể (núi, cây, kho báu, v.v.v) lên bản đồ." #, fuzzy msgid "Monsters Mode" msgstr "Quái vật" #, fuzzy msgid "Used to place monsters on the map." msgstr "" "Dùng để đặt\n" "má»™t nhóm quái vật." msgid "Allows you to draw streams by clicking and dragging." msgstr "Cho phép vẽ suối bằng cách nhấp và kéo." msgid "Stream Mode" msgstr "Chế độ Suối" msgid "Allows you to draw roads by clicking and dragging." msgstr "Cho phép vẽ đưá»ng bằng cách nhấp và kéo." msgid "Road Mode" msgstr "Chế độ ÄÆ°á»ng" msgid "Erase Mode" msgstr "Chế độ Xóa" msgid "Used to erase objects from the map." msgstr "Dùng để xóa vật thể trên bản đồ." msgid "Change between zoom and normal view." msgstr "Thay đổi giữa chế độ nhìn phóng to và chế độ thưá»ng." msgid "Magnify" msgstr "Phóng đại" msgid "Undo" msgstr "Hoàn tác" msgid "Undo your last action." msgstr "Hoàn tác thao tác cuối cùng." msgid "Redo" msgstr "" #, fuzzy msgid "Redo the last undone action." msgstr "Hoàn tác thao tác cuối cùng." msgid "Edit map title, description, and other general information." msgstr "Chỉnh sá»­a tiêu đỠbản đồ, mô tả và thông tin chung khác." msgid "Specifications" msgstr "Thông số kỹ thuật" msgid "File Options" msgstr "Lá»±a chá»n Tệp" msgid "" "Open the file options menu, where you can save or load maps, or quit out of " "the editor." msgstr "" "Mở menu tùy chá»n tệp, nÆ¡i ngươi có thể lưu hoặc tải bản đồ hoặc thoát khá»i " "trình chỉnh sá»­a." msgid "View the editor system options, which let you customize the editor." msgstr "" "Xem các tùy chá»n hệ thống soạn thảo, cho phép ngươi tùy chỉnh trình chỉnh " "sá»­a." msgid "Create a map that is %{size} squares wide and %{size} squares high." msgstr "Tạo bản đồ rá»™ng %{size} ô vuông và cao %{size} ô vuông." msgid "Cancel back to the New Map menu." msgstr "Há»§y quay lại menu Bản đồ Má»›i." msgid "Cancel back to the main menu." msgstr "Há»§y quay lại menu chính." msgid "From Scratch" msgstr "Từ Äầu" msgid "Start from scratch with a blank map." msgstr "Bắt đầu từ đầu vá»›i má»™t bản đổ trống." msgid "Create a randomly generated map." msgstr "Tạo má»™t bản đồ được tạo ngẫu nhiên." msgid "Random" msgstr "Ngẫu nhiên" msgid "Cancel back to the Map Editor main menu." msgstr "Há»§y quay lại menu chính cá»§a Biên tập Bản đồ." msgid "No maps available!" msgstr "Không có bản đồ nào!" #, fuzzy msgid "[%{pos}]: %{race} hero" msgstr "%{color} %{race} tướng" #, fuzzy msgid "[%{pos}]: %{name}, %{race} hero" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{race} town" msgstr "%{color} %{race} tướng" #, fuzzy msgid "[%{pos}]: %{race} castle" msgstr "%{color} %{race} %{townOrCastle}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} town" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "[%{pos}]: %{name}, %{race} castle" msgstr "%{race1} %{name1} vs %{race2} %{name2}" #, fuzzy msgid "None." msgstr "Không" #, fuzzy msgid "One side defeats another." msgstr "Hãy chá»n má»™t tướng khác." #, fuzzy msgid "Accumulate gold." msgstr "Äạt được %{count} vàng." #, fuzzy msgid "Run out of time." msgstr "Thoát khá»i biên tập bản đồ." #, fuzzy msgid "alliance|1st" msgstr " đồng minh" #, fuzzy msgid "alliance|2nd" msgstr " đồng minh" #, fuzzy msgid "alliance|3rd" msgstr " đồng minh" #, fuzzy msgid "alliance|4th" msgstr " đồng minh" #, fuzzy msgid "alliance|5th" msgstr " đồng minh" #, fuzzy msgid "Special Loss Condition" msgstr "Äiá»u kiện Thua" #, fuzzy msgid "Special Victory Condition" msgstr "Äiá»u kiện Thắng" #, fuzzy msgid "Allow standard victory conditions" msgstr "Äiá»u kiện Thắng" msgid "Allow this condition also for AI" msgstr "" #, fuzzy msgid "Set alliances:" msgstr " đồng minh" #, fuzzy msgid "{%number} alliance: " msgstr " đồng minh" #, fuzzy msgid "Gold:" msgstr "Vàng" #, fuzzy msgid "Select a Town to capture to achieve victory" msgstr "Chá»n thị trấn để dịch chuyển tá»›i." #, fuzzy msgid "Click here to change the town needed to capture to achieve victory." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Select a Hero to defeat to achieve victory" msgstr "" #, fuzzy msgid "Click here to change the hero needed to defeat to achieve victory." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Put %{color} player in the %{alliance} alliance" msgstr "" msgid "" "If this checkbox is checked, the %{color} player will be in the %{alliance} " "alliance." msgstr "" msgid "Days:" msgstr "" msgid "Select a Town to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the town whose loss would mean defeat." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Select a Hero to lose to suffer defeat" msgstr "" #, fuzzy msgid "Click here to change the hero whose loss would mean defeat." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." #, fuzzy msgid "Map Difficulty" msgstr "" "Äá»™ khó\n" "Bản đồ" #, fuzzy msgid "Map Description" msgstr "" "\n" "\n" "Vị trí: " msgid "" "The entered map description exceeds the maximum allowed 5 rows. It will be " "shortened to fit the map description field." msgstr "" msgid "" "You are about to change the map's language from %{oldLanguage} to " "%{newLanguage}. Some texts might not be displayed properly after this. Do " "you want to proceed?" msgstr "" msgid "Change Map Name" msgstr "" #, fuzzy msgid "Change Map Description" msgstr "Chá»n Mô tả" #, fuzzy msgid "Click to accept the changes made." msgstr "Nhấp để xem thị trấn sau." #, fuzzy msgid "Click to edit custom rumors." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Rumors" msgstr "" #, fuzzy msgid "Click to edit daily events." msgstr "Nhấp để áp dụng độ phân giải đã chá»n." #, fuzzy msgid "Events" msgstr "Sá»± kiện" #, fuzzy msgid "Click to change the language of the map." msgstr "Thay đổi ngôn ngữ cá»§a trò chÆ¡i." #, fuzzy msgid "Click to change your map name." msgstr "Nhấp để xem thị trấn sau." #, fuzzy msgid "Map Name" msgstr "Tệp bản đồ" #, fuzzy msgid "Click to change the description of the current map." msgstr "Mô tả cá»§a bản đồ hiện được chá»n." #, fuzzy msgid "Click to change the victory condition of the current map." msgstr "Mô tả cá»§a bản đồ hiện được chá»n." #, fuzzy msgid "Click to change the loss condition of the current map." msgstr "Mô tả cá»§a bản đồ hiện được chá»n." msgid "Indicates the player types in the scenario. Click to change." msgstr "" #, fuzzy msgid "Player Type" msgstr "Kiểu Bản đồ" #, fuzzy msgid "" "Click to set map difficulty. More difficult maps might include more or " "stronger enemies, fewer resources, or other special conditions making things " "tougher for the human player." msgstr "" "Äá»™ khó bản đồ cá»§a bản đồ hiện được chá»n. Äá»™ khó cá»§a bản đồ được xác định bởi " "ngưá»i thiết kế kịch bản. Các bản đồ khó hÆ¡n có thể bao gồm nhiá»u kẻ thù hÆ¡n " "hoặc mạnh hÆ¡n, ít tài nguyên hÆ¡n hoặc các Ä‘iá»u kiện đặc biệt khác khiến má»i " "thứ trở nên khó khăn hÆ¡n đối vá»›i ngưá»i chÆ¡i." #, fuzzy msgid "editor|%{count} %{resource}" msgstr "Chá»n số lượng %{resource}:" #, fuzzy msgid "Animation" msgstr "Thôn tính" #, fuzzy msgid "Passability" msgstr "Nhân cách:" #, fuzzy msgid "Toggle animation of the objects." msgstr "Chuyển đổi tính năng xóa đối tượng %{type}." msgid "Toggle display of objects' passability." msgstr "" msgid "Rumor:" msgstr "" msgid "Rumor" msgstr "" msgid "This rumor already exists in the list." msgstr "" #, fuzzy msgid "Click to save the rumors." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Add Rumor" msgstr "" #, fuzzy msgid "Add an additional rumor." msgstr "Lập trình Bổ sung" #, fuzzy msgid "Edit Rumor" msgstr "Biên tập" #, fuzzy msgid "Edit an existing rumor." msgstr "Tải má»™t bản đồ đã có." msgid "Delete Rumor" msgstr "" #, fuzzy msgid "Delete an existing rumor." msgstr "Tải má»™t bản đồ đã có." msgid "" "\n" "\n" "Size: " msgstr "" #, fuzzy msgid "" "\n" "\n" "Description: " msgstr "" "\n" "\n" "Vị trí: " #, fuzzy msgid "Save Map:" msgstr "Lưu Bản đồ" #, fuzzy msgid "Click to save the current map." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Riddle:" msgstr "" msgid "Answers:" msgstr "" msgid "Answer:" msgstr "" msgid "Answer" msgstr "" msgid "This answer exists in the list." msgstr "" #, fuzzy msgid "Click to save the Sphinx properties." msgstr "Nhấp để lưu trò chÆ¡i hiện tại." msgid "Add Answer" msgstr "" msgid "Add an additional answer for the question." msgstr "" msgid "Edit Answer" msgstr "" msgid "Edit an existing answer for the question." msgstr "" msgid "Delete Answer" msgstr "" msgid "Delete an existing answer for the question." msgstr "" msgid "No artifact will be given as a reward." msgstr "" msgid "Delete an artifact from the reward." msgstr "" msgid "Day: %{day} Week: %{week} Month: %{month}" msgstr "" msgid "difficulty|Easy" msgstr "Dá»…" msgid "difficulty|Normal" msgstr "Thưá»ng" msgid "difficulty|Hard" msgstr "Khó" msgid "difficulty|Expert" msgstr "Chuyên gia" msgid "difficulty|Impossible" msgstr "Bất khả thi" msgid "and more..." msgstr "và hÆ¡n thế nữa..." msgid "Easy" msgstr "Dá»…" msgid "Normal" msgstr "Thưá»ng" msgid "Hard" msgstr "Khó" msgid "Campaign Difficulty" msgstr "Äá»™ khó Chiến dịch" #, fuzzy msgid "" "Choose this difficulty to experience the game's story with less challenge. " "The AI will be weaker than at Normal difficulty." msgstr "" "Chá»n độ khó này nếu ngươi muốn thích câu chuyện trò chÆ¡i hÆ¡n thá»­ thách. AI " "yếu hÆ¡n so vá»›i độ khó bình thưá»ng." #, fuzzy msgid "" "Choose this difficulty to experience the campaign as per the original design." msgstr "Chá»n độ khó này để tận hưởng chiến dịch theo thiết kế ban đầu." #, fuzzy msgid "" "Choose this difficulty if you want more challenge. The AI will be stronger " "than at Normal difficulty." msgstr "" "Chá»n độ khó này nếu ngươi muốn thá»­ thách. AI mạnh hÆ¡n so vá»›i độ khó bình " "thưá»ng." msgid "" "Congratulations!\n" "\n" "Days: %{days}\n" msgstr "" "Chúc mừng!\n" "\n" "Ngày: %{days}\n" msgid "" "\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "\n" "Äá»™ khó: %{difficulty}\n" "\n" msgid "" "Score: %{score}\n" "\n" "Rating:\n" "%{rating}" msgstr "" "Äiểm: %{score}\n" "\n" "Bậc:\n" "%{rating}" msgid "Start the selected scenario." msgstr "Bắt đầu kịch bản đã chá»n." msgid "View Intro" msgstr "Xem Giá»›i thiệu" #, fuzzy msgid "View the intro video for the current state of the campaign." msgstr "Xem video Giá»›i thiệu để biết trạng thái hiện tại cá»§a chiến dịch." msgid "" "Select the campaign difficulty. This can be lowered at any point during the " "campaign." msgstr "" "Chá»n độ khó cá»§a chiến dịch. Äiá»u này có thể được hạ xuống bất cứ lúc nào " "trong chiến dịch." msgid "Restart the current scenario." msgstr "ChÆ¡i lại kịch bản hiện tại." msgid "Difficulty" msgstr "Äá»™ khó" msgid "" "You have changed to a lower difficulty for the campaign. You will not be " "able to revert this after this point. The high score will be calculated " "based solely on the new difficulty. Do you want to proceed?" msgstr "" "Ngươi đã thay đổi độ khó thấp hÆ¡n cho chiến dịch. Ngươi sẽ không thể hoàn " "nguyên Ä‘iá»u này sau thá»i Ä‘iểm này. Äiểm cao sẽ được tính chỉ dá»±a trên độ khó " "má»›i. Ngươi có muốn tiếp tục?" msgid "Are you sure you want to restart this scenario?" msgstr "Ngươi có chắc muốn chÆ¡i lại kịch bản?" msgid "Campaign Scenario loading failure" msgstr "Kịch bản Chiến dịch tải thất bại" msgid "Please make sure that campaign files are correct and present." msgstr "Hãy đảm bảo tệp chiến dịch là đúng và hiện hữu." msgid "Days spent" msgstr "Ngày đã qua" msgid "The number of days spent on this campaign." msgstr "Số ngày đã qua trong chiến dịch này." msgid "Project Coordination and Core Development" msgstr "Äiá»u phối Dá»± án và Phát triển Lõi" msgid "Development" msgstr "Phát triển" msgid "Visit us at " msgstr "Tá»›i thăm chúng tôi tại " msgid "QA and Support" msgstr "QA và Há»— trợ" msgid "Dev and Support" msgstr "Phát triển và Há»— trợ" msgid "Special Thanks to" msgstr "Lá»i cảm Æ¡n Chân thành tá»›i" #, fuzzy msgid "and many-many other contributors and supporters!" msgstr "và nhiá»u - nhiá»u những ngưá»i há»— trợ khác!" msgid "Support us at" msgstr "Há»— trợ chúng tôi tại" msgid "local-donation-platform|https://www.patreon.com/fheroes2" msgstr "" msgid "Connect with us at" msgstr "Kết nối vá»›i chúng tôi tại" msgid "local-social-network|https://www.facebook.com/groups/fheroes2" msgstr "" msgid "Need help with the game?" msgstr "Cần sá»± giúp đỡ vá»›i trò chÆ¡i?" msgid "Original project before 0.7" msgstr "Dá»± án Gốc trước 0.7" msgid "Heroes of Might and Magic II: The Succession Wars team" msgstr "Heroes of Might and Magic II: The Succession Wars team" msgid "Designed and Directed" msgstr "Thiết kế và Chỉ đạo" msgid "Programming and Design" msgstr "Lập trình và Thiết kế" msgid "Executive Producer" msgstr "Äiá»u hành Sản xuất" msgid "Producer" msgstr "Sản xuất" msgid "Additional Design" msgstr "Thiết kế Bổ sung" msgid "Additional Programming" msgstr "Lập trình Bổ sung" msgid "Musical Production" msgstr "Sản xuất Âm nhạc" msgid "Music and Sound Design" msgstr "Thiết kế Nhạc và Âm" msgid "Vocalists" msgstr "Lồng tiếng" msgid "Art Director" msgstr "Chỉ đạo Nghệ thuật" msgid "Assistant Art Director" msgstr "Trợ lý Chỉ đạo Nghệ thuật" msgid "Artists" msgstr "Nghệ sỹ" msgid "QA Manager" msgstr "Quản lý QA" msgid "QA" msgstr "QA" msgid "Writing" msgstr "Kịch bản" msgid "Manual and Helpfile" msgstr "Hướng dẫn sá»­ dụng và Tệp trợ giúp" msgid "Scenarios" msgstr "Biên kịch" msgid "Heroes of Might and Magic II: The Price of Loyalty team" msgstr "Heroes of Might and Magic II: The Price of Loyalty team" msgid "Design Lead" msgstr "Thiết kế Trưởng" msgid "Designers" msgstr "Thiết kế" msgid "Programming Lead" msgstr "Trưởng Lập trình" msgid "Art Lead" msgstr "Trưởng Nghệ thuật" msgid "Playtesters" msgstr "ChÆ¡i thá»­" msgid "Designer" msgstr "Thiết kế" msgid "Producers" msgstr "Sản xuất" msgid "QA Managers" msgstr "Quản lý QA" msgid "Sound Design" msgstr "Thiết kế Âm thanh" msgid "Town Themes" msgstr "Chá»§ đỠThị trấn" msgid "Alto Sax" msgstr "Alto Sax" msgid "Harpsichord and Piano" msgstr "Harpsichord and Piano" msgid "Basso Vocal" msgstr "Basso Vocal" msgid "Soprano Vocal" msgstr "Soprano Vocal" msgid "Recorded at %{recordingStudio}" msgstr "Thu âm tại %{recordingStudio}" msgid "credits|Manual" msgstr "Thá»§ công" msgid "German Consultant" msgstr "Tư vấn Tiếng Äức" msgid "Map Designers" msgstr "Thiết kế Bản đồ" msgid "Package Design" msgstr "Thiết kế Äóng gói" msgid "High Scores" msgstr "Äiểm Cao" msgid "Your Name" msgstr "Tên cá»§a Ngươi" msgid "Unknown Hero" msgstr "Tướng Vô danh" msgid "Standard" msgstr "Tiêu chuẩn" msgid "View High Scores for Standard Maps." msgstr "Xem Äiểm cho chế độ Thưá»ng." msgid "Campaign" msgstr "Chiến dịch" msgid "View High Scores for Campaigns." msgstr "Xem Äiểm cho chế độ Chiến dịch." msgid "hotkey|default okay event" msgstr "sá»± kiện tốt mặc định" msgid "hotkey|default cancel event" msgstr "sá»± kiện há»§y mặc định" msgid "hotkey|default left" msgstr "mặc định trái" msgid "hotkey|default right" msgstr "mặc định phải" msgid "hotkey|default up" msgstr "mặc định lên" msgid "hotkey|default down" msgstr "mặc định xuống" msgid "hotkey|toggle fullscreen" msgstr "chuyển đổi chế độ toàn màn hình" msgid "hotkey|toggle text support mode" msgstr "chuyển đội chế độ há»— trợ văn bản" #, fuzzy msgid "hotkey|toggle developer mode" msgstr "chuyển đội chế độ há»— trợ văn bản" msgid "hotkey|new game" msgstr "trò chÆ¡i má»›i" msgid "hotkey|load game" msgstr "tải trò chÆ¡i" #, fuzzy msgid "hotkey|high scores" msgstr "Ä‘iểm cao" msgid "hotkey|credits" msgstr "công trạng" msgid "hotkey|standard game" msgstr "trò chÆ¡i tiêu chuẩn" msgid "hotkey|campaign game" msgstr "trò chÆ¡i chiến dịch" msgid "hotkey|multi-player game" msgstr "trò chÆ¡i nhiá»u ngưá»i" msgid "hotkey|settings" msgstr "thiết lập" msgid "hotkey|quit" msgstr "thoát" msgid "hotkey|select map" msgstr "chá»n bản đồ" msgid "hotkey|select small map size" msgstr "chá»n bản đồ cỡ nhá»" msgid "hotkey|select medium map size" msgstr "chá»n bản đồ cỡ vừa" msgid "hotkey|select large map size" msgstr "chá»n bản đồ cỡ lá»›n" msgid "hotkey|select extra large map size" msgstr "chá»n bản đồ cỡ siêu lá»›n" msgid "hotkey|select all map sizes" msgstr "chá»n tất cả các bản đồ" #, fuzzy msgid "hotkey|hot seat game" msgstr "trò chÆ¡i ghế nóng" msgid "hotkey|battle only game" msgstr "trò chÆ¡i chỉ chiến đấu" msgid "hotkey|choose the original campaign" msgstr "chá»n chiến dịch gốc" msgid "hotkey|choose the expansion campaign" msgstr "chá»n chiến dịch mở rá»™ng" msgid "hotkey|map editor main menu" msgstr "trình đơn biên tập bản đồ" msgid "hotkey|new map menu" msgstr "trình đơn bản đồ má»›i" msgid "hotkey|load map menu" msgstr "trình đơn tải bản đồ" msgid "hotkey|new map from scratch" msgstr "bắt đầu bản đồ má»›i" msgid "hotkey|new random map" msgstr "bản đồ má»›i ngẫu nhiên" msgid "hotkey|undo last action" msgstr "hoàn tác tác vụ cuối" msgid "hotkey|redo last action" msgstr "thá»±c hiện lại tác vụ cuối" #, fuzzy msgid "hotkey|open game main menu" msgstr "trình đơn bản đồ má»›i" #, fuzzy msgid "hotkey|toggle passability" msgstr "chuyển đổi trạng thái" msgid "hotkey|roland campaign" msgstr "chiến dịch roland" msgid "hotkey|archibald campaign" msgstr "chiến dịch archibald" #, fuzzy msgid "hotkey|price of loyalty campaign" msgstr "chiến dịch giá cá»§a lòng trung thành" msgid "hotkey|voyage home campaign" msgstr "chiến dịch đưá»ng vá» nhà" msgid "hotkey|wizard's isle campaign" msgstr "chiến dịch đảo phù thá»§y" msgid "hotkey|descendants campaign" msgstr "chiến dịch hậu duệ" msgid "hotkey|select first campaign bonus" msgstr "chá»n phần thưởng chiến dịch đầu tiên" msgid "hotkey|select second campaign bonus" msgstr "chá»n phần thưởng chiến dịch thứ 2" msgid "hotkey|select third campaign bonus" msgstr "chá»n phần thưởng chiến dịch thứ 3" msgid "hotkey|view campaign intro" msgstr "xem giá»›i thiệu chiến dịch" msgid "hotkey|select campaign difficulty" msgstr "chá»n độ khó chiến dịch" msgid "hotkey|restart campaign scenario" msgstr "khởi động lại kịch bản chiến dịch" msgid "hotkey|world map left" msgstr "bản đồ thế giá»›i trái" msgid "hotkey|world map right" msgstr "bản đồ thế giá»›i phải" msgid "hotkey|world map up" msgstr "bản đồ thế giá»›i trên" msgid "hotkey|world map down" msgstr "bản đồ thế giá»›i dưới" msgid "hotkey|world map up left" msgstr "bản đồ thế giá»›i trái trên" msgid "hotkey|world map up right" msgstr "bản đồ thế giá»›i phải trên" msgid "hotkey|world map down left" msgstr "bản đồ thế giá»›i trái dưới" msgid "hotkey|world map down right" msgstr "bản đồ thế giá»›i phải dưới" msgid "hotkey|save game" msgstr "lưu trò chÆ¡i" msgid "hotkey|next hero" msgstr "tướng tiếp theo" #, fuzzy msgid "hotkey|change to hero under cursor" msgstr "tướng tiếp theo" msgid "hotkey|start hero movement" msgstr "bắt đầu di chuyển tướng" msgid "hotkey|cast adventure spell" msgstr "niệm câu thần chú thám hiểm" msgid "hotkey|put hero to sleep" msgstr "cho tướng Ä‘i ngá»§" msgid "hotkey|next town" msgstr "thị trấn tiếp theo" msgid "hotkey|end turn" msgstr "kết thúc lượt" msgid "hotkey|file options" msgstr "lá»±a chá»n tệp" msgid "hotkey|adventure options" msgstr "tùy chá»n thám hiểm" msgid "hotkey|puzzle map" msgstr "bản đồ giải đố" msgid "hotkey|scenario information" msgstr "thông tin kịch bản" msgid "hotkey|dig for artifact" msgstr "đào bảo vật" msgid "hotkey|view world" msgstr "xem thế giá»›i" msgid "hotkey|kingdom summary" msgstr "tổng quát vương quốc" msgid "hotkey|default action" msgstr "hành động mặc định" msgid "hotkey|open focus" msgstr "mở tiêu Ä‘iểm" msgid "hotkey|system options" msgstr "tùy chá»n hệ thống" msgid "hotkey|scroll left" msgstr "cuá»™n trái" msgid "hotkey|scroll right" msgstr "cuá»™n phải" msgid "hotkey|scroll up" msgstr "cuá»™n lên" msgid "hotkey|scroll down" msgstr "cuá»™n xuống" msgid "hotkey|toggle control panel" msgstr "chuyển đổi bảng Ä‘iá»u khiển" msgid "hotkey|toggle radar" msgstr "chuyển đổi radar" msgid "hotkey|toggle buttons" msgstr "chuyển đổi nút bấm" msgid "hotkey|toggle status" msgstr "chuyển đổi trạng thái" msgid "hotkey|toggle icons" msgstr "chuyển đổi biểu tượng" msgid "hotkey|transfer control to ai" msgstr "chuyển Ä‘iá»u khiển cho AI" msgid "hotkey|retreat from battle" msgstr "rút lui khá»i trận chiến" msgid "hotkey|surrender during battle" msgstr "đầu hàng trong trận chiến" #, fuzzy msgid "hotkey|toggle auto combat mode" msgstr "chuyển đổi chế độ tá»± động chiến đấu" #, fuzzy msgid "hotkey|quick combat" msgstr "thoát" msgid "hotkey|battle options" msgstr "lá»±a chá»n trận chiến" msgid "hotkey|skip turn in battle" msgstr "bá» lượt trong trận chiến" msgid "hotkey|cast battle spell" msgstr "niệm chú trong trận chiến" msgid "hotkey|dwelling level 1" msgstr "nhà lính cấp 1" msgid "hotkey|dwelling level 2" msgstr "nhà lính cấp 2" msgid "hotkey|dwelling level 3" msgstr "nhà lính cấp 3" msgid "hotkey|dwelling level 4" msgstr "nhà lính cấp 4" msgid "hotkey|dwelling level 5" msgstr "nhà lính cấp 5" msgid "hotkey|dwelling level 6" msgstr "nhà lính cấp 6" msgid "hotkey|well" msgstr "giếng" msgid "hotkey|marketplace" msgstr "chợ" msgid "hotkey|mage guild" msgstr "há»™i phù thá»§y" msgid "hotkey|shipyard" msgstr "bến tàu" msgid "hotkey|thieves guild" msgstr "băng cướp" msgid "hotkey|tavern" msgstr "quán rượu" msgid "hotkey|construction screen" msgstr "màn hình xây dá»±ng" msgid "hotkey|buy all monsters in well" msgstr "mua tất cả các qoái vật trong giếng" msgid "hotkey|split stack by half" msgstr "chia đạo quân làm đôi" msgid "hotkey|split stack by one" msgstr "chia đạo quân thành má»™t" msgid "hotkey|join stacks" msgstr "nhập đạo quân" msgid "hotkey|upgrade troop" msgstr "nâng cấp quân đội" msgid "hotkey|dismiss hero or troop" msgstr "giải tán tướng hoặc quân" #, fuzzy msgid "hotkey|exchange all troops" msgstr "nâng cấp quân đội" msgid "" "Do you want to regain control from AI? The effect will take place only on " "the next turn." msgstr "" "Ngươi có muốn AI kiểm soát không? Hiệu quả sẽ bắt đầu ở lượt tiếp theo." msgid "" "Do you want to transfer control from you to the AI? The effect will take " "place only on the next turn." msgstr "" "Ngươi có muốn chuyển quyá»n kiểm soát sang cho AI không? Hiệu ứng sẽ chỉ diá»…n " "ra ở lượt tiếp theo." msgid "Default Actions" msgstr "Hành động Mặc định" msgid "Global Actions" msgstr "Hành động Toàn cầu" msgid "World Map" msgstr "Bản đồ Thế giá»›i" msgid "Battle Screen" msgstr "Màn hình Chiến đấu" msgid "Town Screen" msgstr "Màn hình Thị trấn" msgid "Army Actions" msgstr "Hành động Quân đội" msgid "The save file is corrupted." msgstr "File lưu bị há»ng." msgid "Unsupported save format: " msgstr "Äịnh dạng lưu không há»— trợ: " msgid "Current game version: " msgstr "Phiên bản trò chÆ¡i hiện tại: " msgid "Last supported version: " msgstr "Phiên bản há»— trợ cuối cùng: " msgid "This file contains a save with an invalid game type." msgstr "Tệp này chứa má»™t bản lưu có loại trò chÆ¡i không hợp lệ." msgid "" "This save file requires \"The Price of Loyalty\" game assets, but they have " "not been provided to the engine." msgstr "" "Tệp lưu này yêu cầu ná»™i dung trò chÆ¡i \"Cái giá cá»§a lòng trung thành\", " "nhưng chúng chưa được cung cấp cho công cụ." msgid "This saved game is localized to '" msgstr "Trò chÆ¡i đã lưu này được bản địa hóa thành '" msgid "' language, but the current language of the game is '" msgstr "' ngôn ngữ, nhưng ngôn ngữ hiện tại cá»§a trò chÆ¡i là '" msgid "No save files to load." msgstr "Không có tệp lưu để tải." msgid "Hot Seat" msgstr "Ghế Nóng" #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play around the same computer, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "ChÆ¡i chế độ Ghế nóng, trong đó 2 đến 6 ngưá»i chÆ¡i cùng chÆ¡i quanh má»™t máy " "tính, chuyển sang 'Ghế nóng' khi đến lượt cá»§a há»." msgid "A single player game playing out a single map." msgstr "Má»™t trò chÆ¡i má»™t ngưá»i chÆ¡i chÆ¡i trên má»™t bản đồ duy nhất." msgid "Standard Game" msgstr "Trò chÆ¡i Thưá»ng" msgid "A single player game playing through a series of maps." msgstr "Má»™t trò chÆ¡i má»™t ngưá»i chÆ¡i chÆ¡i qua má»™t loạt bản đồ." msgid "Campaign Game" msgstr "Trò chÆ¡i Chiến dịch" msgid "Multi-Player Game" msgstr "Trò chÆ¡i Nhiá»u ngưá»i" msgid "" "A multi-player game, with several human players completing against each " "other on a single map." msgstr "" "Má»™t trò chÆ¡i nhiá»u ngưá»i chÆ¡i, trong đó má»™t số ngưá»i chÆ¡i sẽ đấu vá»›i nhau " "trên má»™t bản đồ." msgid "fheroes2 Resurrection Team presents" msgstr "fheroes2 Resurrection Team giá»›i thiệu" msgid "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" msgstr "" "Chào mừng tá»›i Heroes of Might and Magic II cung cấp bởi mã nguồn fheroes2!" msgid "" "\n" "\n" "To simulate a right-click with a touch to get info on various items, you " "need to first touch and keep touching on the item of interest and then touch " "anywhere else on the screen. While holding the second finger, you can remove " "the first one from the screen and keep viewing the information on the item." msgstr "" #, fuzzy msgid "" "\n" "\n" "Before starting the game, please select a game resolution." msgstr "" "Chào mừng tá»›i Heroes of Might and Magic II cung cấp bởi mã nguồn fheroes2! " "Trước khi bắt đầu hãy chá»n độ phân giải cá»§a trò chÆ¡i." msgid "Greetings!" msgstr "Chào mừng!" msgid "Quit Heroes of Might and Magic II and return to the operating system." msgstr "Thoát khá»i Heroes of Might and Magic II và quay lại hệ Ä‘iá»u hành." msgid "Credits" msgstr "Công trạng" msgid "View the credits screen." msgstr "Xem màn hình giá»›i thiệu thông tin." msgid "View the high scores screen." msgstr "Xem màn hình Ä‘iểm cao." #, fuzzy msgid "Create new or modify existing maps." msgstr "Tải má»™t bản đồ đã có." msgid "Change language, resolution and settings of the game." msgstr "Thay đổi ngôn ngữ, độ phân giải và các cài đặt cá»§a trò chÆ¡i." msgid "Game Settings" msgstr "Cài đặt Trò chÆ¡i" #, fuzzy msgid "" "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." msgstr "" "File video cần thiết cho chiến dịch bị thiếu. Hãy đảm bảo tất cả các file " "cần thiết có sẵn trong hệ thống." msgid "" "Either Roland's or Archibald's campaign from the original Heroes of Might " "and Magic II." msgstr "" "Chiến dịch cá»§a Roland hoặc Archibald từ bản gốc Heroes of Might and Magic II." msgid "Original Campaign" msgstr "Chiến dịch Gốc" msgid "Expansion Campaign" msgstr "Chiến dịch Mở rá»™ng" msgid "One of the four new campaigns from the Price of Loyalty expansion set." msgstr "Má»™t trong bốn chiến dịch má»›i từ bản mở rá»™ng Giá cá»§a Lòng Trung thành." msgid "Loading video. Please wait..." msgstr "Äang tải video. Xin đợi..." msgid "Host" msgstr "Chá»§ nhà" msgid "" "The host sets up the game options. There can only be one host per network " "game." msgstr "" "Chá»§ nhà thiết lập các lá»±a chá»n trò chÆ¡i. Chỉ có thể có má»™t máy chá»§ cho má»—i " "trò chÆ¡i mạng." msgid "Guest" msgstr "Khách" msgid "" "The guest waits for the host to set up the game, then is automatically added " "in. There can be multiple guests for TCP/IP games." msgstr "" "Khách đợi chá»§ nhà thiết lập trò chÆ¡i, sau đó sẽ tá»± động được thêm vào. Có " "thể có nhiá»u khách cho trò chÆ¡i TCP/IP." msgid "" "fheroes2 needs data files from the original Heroes of Might and Magic II to " "operate. You appear to be using the demo version of Heroes of Might and " "Magic II for this purpose. Please note that only one scenario will be " "available in this setup." msgstr "" #, fuzzy msgid "" "A multi-player game, with several human players competing against each other " "on a single map." msgstr "" "Má»™t trò chÆ¡i nhiá»u ngưá»i chÆ¡i, trong đó má»™t số ngưá»i chÆ¡i sẽ đấu vá»›i nhau " "trên má»™t bản đồ." msgid "Battle Only" msgstr "Chỉ Chiến đấu" msgid "Setup and play a battle without loading any map." msgstr "" "Thiết lập và chÆ¡i má»™t trận chiến mà không cần phải tải bất cứ bản đồ nào." #, fuzzy msgid "" "Play a Hot Seat game, where 2 to 6 players play on the same device, " "switching into the 'Hot Seat' when it is their turn." msgstr "" "ChÆ¡i chế độ Ghế nóng, trong đó 2 đến 6 ngưá»i chÆ¡i cùng chÆ¡i quanh má»™t máy " "tính, chuyển sang 'Ghế nóng' khi đến lượt cá»§a há»." msgid "2 Players" msgstr "2 ngưá»i chÆ¡i" msgid "" "Play with 2 human players, and optionally, up to 4 additional computer " "players." msgstr "ChÆ¡i vá»›i 2 ngưá»i chÆ¡i và tùy chá»n, tối Ä‘a thêm 4 máy tính." msgid "3 Players" msgstr "3 ngưá»i chÆ¡i" msgid "" "Play with 3 human players, and optionally, up to 3 additional computer " "players." msgstr "ChÆ¡i vá»›i 3 ngưá»i chÆ¡i và tùy chá»n, tối Ä‘a thêm 3 máy tính." msgid "4 Players" msgstr "4 ngưá»i chÆ¡i" msgid "" "Play with 4 human players, and optionally, up to 2 additional computer " "players." msgstr "ChÆ¡i vá»›i 4 ngưá»i chÆ¡i và tùy chá»n, tối Ä‘a thêm 2 máy tính." msgid "5 Players" msgstr "5 ngưá»i chÆ¡i" msgid "" "Play with 5 human players, and optionally, up to 1 additional computer " "player." msgstr "ChÆ¡i vá»›i 5 ngưá»i chÆ¡i và tùy chá»n, tối Ä‘a thêm 1 máy tính." msgid "6 Players" msgstr "6 ngưá»i chÆ¡i" msgid "Play with 6 human players." msgstr "ChÆ¡i vá»›i 6 ngưá»i chÆ¡i." msgid "Dragon city has fallen! You are now the Master of the Dragons." msgstr "Thành phố rồng đã thất thá»§! Bây giá» ngươi đã là Bậc thầy cá»§a Rồng." msgid "" "You captured %{name}!\n" "You are victorious." msgstr "" "Ngươi chiếm được %{name}!\n" "Ngươi là ngưá»i chiến thắng." msgid "" "You have captured the enemy hero %{name}!\n" "Your quest is complete." msgstr "" "Ngươi đã bắt được tướng địch %{name}!\n" "Nhiệm vụ cá»§a ngươi đã hoàn tất." msgid "" "You have found the %{name}.\n" "Your quest is complete." msgstr "" "Ngươi đã tìm thấy %{name}.\n" "Nhiệm vụ cá»§a ngươi kết thúc." msgid "Ultimate Artifact" msgstr "Bảo vật Tối thượng" msgid "" "The enemy is beaten.\n" "Your side has triumphed!" msgstr "" "Äịch đã bị đánh bại.\n" "Phe ngươi đã chiến thắng!" msgid "" "You have built up over %{count} gold in your treasury.\n" "All enemies bow before your wealth and power." msgstr "" "Ngươi đã tích lÅ©y được hÆ¡n %{count} vàng trong kho bạc cá»§a mình.\n" "Tất cả kẻ thù Ä‘á»u cúi đầu trước sá»± giàu có và quyá»n lá»±c cá»§a ngươi." msgid "Victory!" msgstr "Chiến thắng!" msgid "" "The enemy has captured %{name}!\n" "They are triumphant." msgstr "" "Äịch đã chiếm được %{name}!\n" "Chúng đã chiến thắng." msgid "" "The enemy has built up over %{count} gold in his treasury.\n" "You must bow done in defeat before his wealth and power." msgstr "" "Kẻ thù đã tích lÅ©y được hÆ¡n %{count} vàng trong kho bạc cá»§a mình.\n" "Ngươi phải cúi đầu thất bại trước sá»± giàu có và quyá»n lá»±c cá»§a hắn ta." msgid "You have been eliminated from the game!!!" msgstr "Ngươi đã bị loại khá»i trò chÆ¡i!!!" msgid "" "You have lost the hero %{name}.\n" "Your quest is over." msgstr "" "Ngươi mất tướng %{name}.\n" "Nhiệm vụ cá»§a ngươi chấm dứt." msgid "" "You have failed to complete your quest in time.\n" "All is lost." msgstr "" "Ngươi đã không hoàn thành nhiệm vụ cá»§a mình đúng thá»i hạn.\n" "Tất cả bị mất." msgid "Defeat!" msgstr "Bị đánh bại!" msgid "" "Base score: %{score}\n" "Difficulty: %{difficulty}\n" "\n" msgstr "" "Äiểm: %{score}\n" "Khó: %{difficulty}\n" "\n" msgid "Defeat all enemy heroes and capture all enemy towns and castles." msgstr "" "Äánh bại tất cả tướng cá»§a kẻ thù và chiếm được tất cả các thị trấn và lâu " "đài cá»§a kẻ thù." msgid "Your side defeats the opposing side." msgstr "Phe cá»§a ngươi đánh bại phe đối lập." msgid "Run out of time. (Fail to win by a certain point.)" msgstr "Hết thá»i gian. Không thể giành chiến thắng vá»›i thá»i gian nhất định." msgid "You must defeat the enemy %{enemies}." msgid_plural "You must defeat the enemy alliance of %{enemies}." msgstr[0] "Ngươi phải đánh bại kẻ thù %{enemies}." msgid "" "The alliance consisting of %{allies} and you must defeat the enemy " "%{enemies}." msgid_plural "" "The alliance consisting of %{allies} and you must defeat the enemy alliance " "of %{enemies}." msgstr[0] "" "Liên minh bao gồm %{allies} và ngươi phải đánh bại kẻ thù %{enemies}." msgid "Capture the castle '%{name}'." msgstr "Chiếm được lâu đài '%{name}'." msgid "Capture the town '%{name}'." msgstr "Chiếm được thị trấn '%{name}'." msgid "Defeat the hero '%{name}'." msgstr "Diệt được tướng '%{name}'." msgid "Find the ultimate artifact." msgstr "Tìm được bảo vật tối thượng." msgid "Find the '%{name}' artifact." msgstr "Tìm bảo vật '%{name}'." msgid "Accumulate %{count} gold." msgstr "Äạt được %{count} vàng." msgid "" ", or you may win by defeating all enemy heroes and capturing all enemy towns " "and castles." msgstr "" ", hoặc ngươi có thể giành chiến thắng bằng cách đánh bại tất cả tướng cá»§a kẻ " "thù và chiếm được tất cả các thị trấn và lâu đài cá»§a kẻ thù." msgid "Lose the castle '%{name}'." msgstr "Mất lâu đài '%{name}'." msgid "Lose the town '%{name}'." msgstr "Mất thị trấn '%{name}'." msgid "Lose the hero: %{name}." msgstr "Mất tướng: %{name}." msgid "Fail to win by the end of month %{month}, week %{week}, day %{day}." msgstr "" "Không giành chiến thắng vào cuối tháng %{month}, tuần %{week}, ngày %{day}." msgid "%{color} player has been vanquished!" msgstr "ngưá»i chÆ¡i màu %{color} đã bị đánh bại !" msgid "Major Event!" msgstr "Sá»± kiện Chính!" msgid "Scenario:" msgstr "Kịch bản:" msgid "Game Difficulty:" msgstr "Äá»™ khó Trò chÆ¡i:" msgid "Opponents:" msgstr "Äối thá»§:" msgid "Class:" msgstr "Chá»§ng tá»™c:" msgid "Rating %{rating}%" msgstr "Xếp hạng %{rating}%" msgid "Click here to select which scenario to play." msgstr "Nhấp vào đây để chá»n kịch bản để chÆ¡i." msgid "Scenario" msgstr "Kịch bản" msgid "Game Difficulty" msgstr "Äá»™ khó Trò chÆ¡i" #, fuzzy msgid "" "This lets you change the starting difficulty at which you will play. Higher " "difficulty levels start you off with fewer resources, and at the higher " "settings, give extra resources to the computer." msgstr "" "Äiá»u này cho phép thay đổi độ khó ban đầu mà ngươi sẽ chÆ¡i. Mức độ khó cao " "hÆ¡n bắt đầu vá»›i ít tài nguyên hÆ¡n và ở cài đặt cao hÆ¡n, cung cấp thêm tài " "nguyên cho máy tính." msgid "Difficulty Rating" msgstr "Äánh giá Äá»™ khó" msgid "" "The difficulty rating reflects a combination of various settings for your " "game. This number will be applied to your final score." msgstr "" "Xếp hạng độ khó phản ánh sá»± kết hợp cá»§a nhiá»u cài đặt khác nhau cho trò chÆ¡i " "cá»§a ngươi. Con số này sẽ được áp dụng cho Ä‘iểm số cuối cùng cá»§a ngươi." msgid "Click to accept these settings and start a new game." msgstr "Nhấp để chấp nhận các cài đặt này và bắt đầu trò chÆ¡i má»›i." msgid "Click to return to the main menu." msgstr "Nhấp để quay lại màn hình chính." msgid "Astrologers proclaim the Month of the %{name}." msgstr "Các nhà chiêm tinh công bố Tháng cá»§a %{name}." msgid "Astrologers proclaim the Week of the %{name}." msgstr "Các nhà chiêm tinh công bố Tuần cá»§a %{name}." msgid "After regular growth, the population of %{monster} is doubled!" msgstr "Sau khi tăng trưởng Ä‘á»u đặn, dân số cá»§a %{monster} đã tăng gấp đôi!" msgid "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgid_plural "" "After regular growth, the population of %{monster} increases by %{count} " "percent!" msgstr[0] "" "Sau khi tăng trưởng Ä‘á»u đặn, dân số cá»§a %{monster} đã tăng %{count} phần " "trăm!" msgid "%{monster} growth +%{count}." msgstr "%{monster} tăng trưởng +%{count}." msgid " All populations are halved." msgstr " Tất cả dân số Ä‘á»u giảm má»™t ná»­a." msgid " All dwellings increase population." msgstr " Tất cả các nhà tăng dân số." msgid "New Month!" msgstr "Tháng Má»›i!" msgid "New Week!" msgstr "Tuần Má»›i!" msgid "Beware!" msgstr "Coi chừng!" msgid "" "%{color} player, this is your last day to capture a town, or you will be " "banished from this land." msgstr "" "Ngưá»i chÆ¡i màu %{color}, đây là ngày cuối cùng cá»§a ngươi để chiếm được má»™t " "thị trấn, nếu không ngươi sẽ bị trục xuất khá»i vùng đất này." msgid "" "%{color} player, you only have %{day} days left to capture a town, or you " "will be banished from this land." msgstr "" "Ngưá»i chÆ¡i màu %{color}, ngươi chỉ có %{day} để chiếm được má»™t thị trấn, nếu " "không ngươi sẽ bị trục xuất khá»i vùng đất này." msgid "%{color} player's turn." msgstr "Lượt ngưá»i chÆ¡i màu %{color}." #, fuzzy msgid "" "%{color} player, you have lost your last town. If you do not conquer another " "town in the next week, you will be eliminated." msgstr "" "Ngưá»i chÆ¡i %{color}, ngươi đã mất thị trấn cuối cùng cá»§a mình. Nếu ngươi " "không chinh phục được thị trấn khác vào tuần tá»›i, ngươi sẽ bị loại." msgid "" "%{color} player, your heroes abandon you, and you are banished from this " "land." msgstr "" "Ngưá»i chÆ¡i màu %{color}, các tướng đã bá» rÆ¡i ngươi và ngươi bị trục xuất " "khá»i vùng đất này." msgid "Lord Kilburn" msgstr "Lord Kilburn" msgid "Tsabu" msgstr "Tsabu" msgid "Sir Galant" msgstr "Sir Galant" msgid "Thundax" msgstr "Thundax" msgid "Lord Haart" msgstr "Lord Haart" msgid "Ariel" msgstr "Ariel" msgid "Rebecca" msgstr "Rebecca" msgid "Sandro" msgstr "Sandro" msgid "Crodo" msgstr "Crodo" msgid "Barock" msgstr "Barock" msgid "Antoine" msgstr "Antoine" msgid "Astra" msgstr "Astra" msgid "Agar" msgstr "Agar" msgid "Vatawna" msgstr "Vatawna" msgid "Vesper" msgstr "Vesper" msgid "Ambrose" msgstr "Ambrose" msgid "Troyan" msgstr "Troyan" msgid "Jojosh" msgstr "Jojosh" msgid "Wrathmont" msgstr "Wrathmont" msgid "Maximus" msgstr "Maximus" msgid "Next Hero" msgstr "Tướng Tiếp theo" msgid "Select the next Hero." msgstr "Chá»n Tướng tiếp theo." msgid "Hero Movement" msgstr "Tướng Di chuyển" msgid "" "Start the Hero's movement along the current path or re-visit the object " "occupied by the Hero. Press and hold this button to reset the Hero's path." msgstr "" "Bắt đầu di chuyển Tướng dá»c theo con đưá»ng hiện tại hoặc ghé thăm lại đối " "tượng mà Tướng chiếm giữ. Nhấn và giữ nút này để thiết lập lại đưá»ng Ä‘i cá»§a " "Tướng." msgid "Kingdom Summary" msgstr "Tổng quát Vương quốc" #, fuzzy msgid "View a summary of your Kingdom." msgstr "Xem Tổng quát vá» Vương quốc." msgid "Cast an adventure spell." msgstr "Niệm má»™t câu thần chú khám phá." msgid "End Turn" msgstr "Kết thúc Lượt" #, fuzzy msgid "End your turn and let the computer take its turn." msgstr "Kết thúc lượt cá»§a ngươi và để máy tính Ä‘i lượt cá»§a nó." msgid "Adventure Options" msgstr "Tùy chá»n Khám phá" msgid "Bring up the adventure options menu." msgstr "Hiển thị menu tùy chá»n khám phá." msgid "" "Bring up the file options menu, allowing you to load, save, start a new game " "or quit." msgstr "" "Hiển thị trình đơn tùy chá»n tệp, cho phép ngươi tải, lưu, bắt đầu trò chÆ¡i " "má»›i hoặc thoát." msgid "Bring up the system options menu, allowing you to customize your game." msgstr "" "Hiển thị trình đơn tùy chá»n hệ thống, cho phép ngươi tùy chỉnh trò chÆ¡i cá»§a " "mình." msgid "" "One or more heroes may still move, are you sure you want to end your turn?" msgstr "" "Má»™t hoặc nhiá»u tướng vẫn có thể di chuyển, ngươi có chắc chắn muốn kết thúc " "lượt cá»§a mình không?" msgid "Are you sure you want to quit?" msgstr "Ngươi có muốt thoát không?" msgid "Are you sure you want to restart? (Your current game will be lost.)" msgstr "" "Ngươi có chắc là ngươi muốn bắt đầu lại không? (Trò chÆ¡i hiện tại cá»§a ngươi " "sẽ bị mất.)" msgid "Are you sure you want to overwrite the save with this name?" msgstr "Ngươi có chắc chắn muốn ghi đè lưu bằng tên này không?" msgid "Game saved successfully." msgstr "Chò trÆ¡i được lưu thành công." msgid "There was an issue during saving." msgstr "Äã xảy ra sá»± cố trong quá trình lưu." msgid "" "Are you sure you want to load a new game? (Your current game will be lost.)" msgstr "" "Ngươi có chắc là ngươi muốn tải má»™t trò chÆ¡i má»›i không? (Trò chÆ¡i hiện tại " "cá»§a ngươi sẽ bị mất.)" msgid "Try looking on land!!!" msgstr "Thá»­ tìm kiếm trên mặt đất!!!" msgid "" "Searching for the Ultimate Artifact is fruitless. Your hero could not carry " "it even if he found it - all his artifact slots are full." msgstr "" "Việc tìm kiếm Bảo vật Tối thượng không có kết quả. Tướng cá»§a ngươi không thể " "mang nó ngay cả khi anh ta tìm thấy nó - tất cả các ô tạo tác cá»§a anh ta Ä‘á»u " "đã đầy." msgid "Digging for artifacts requires a whole day, try again tomorrow." msgstr "Äào báu vật cần cả má»™t ngày, hãy thá»­ lại vào ngày mai." msgid "" "After spending many hours digging here, you have uncovered the %{artifact}." msgstr "Sau nhiá»u giỠđào bá»›i ở đây, ngươi đã phát hiện được %{artifact}." msgid "Congratulations!" msgstr "Chúc mừng!" msgid "Nothing here. Where could it be?" msgstr "Không có gì ở đây. Nó có thể ở đâu?" msgid "Try searching on clear ground." msgstr "Hãy thá»­ tìm kiếm cẩn than trên mặt đất." msgid "A miniature view of the known world. Left click to move viewing area." msgstr "" "Má»™t cái nhìn thu nhá» vá» thế giá»›i đã biết. Nhấp chuá»™t trái để di chuyển khu " "vá»±c xem." msgid "Month: %{month} Week: %{week}" msgstr "Tháng: %{month} Tuần: %{week}" msgid "" "You find a small\n" "quantity of %{resource}." msgstr "" "Ngươi tìm thấy\n" "má»™t lượng nhá» %{resource}." msgid "Status Window" msgstr "Cá»­a sổ Trạng thái" msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date." msgstr "" "Cá»­a sổ này cung cấp thông tin vá» trạng thái tướng hoặc vương quốc cá»§a ngươi " "và hiển thị ngày tháng." msgid "" "This window provides information on the status of your hero or kingdom, and " "shows the date. Left click here to cycle through these windows." msgstr "" "Cá»­a sổ này cung cấp thông tin vá» trạng thái tướng hoặc vương quốc cá»§a ngươi " "và hiển thị ngày tháng. Nhấp chuá»™t trái vào đây để duyệt qua các cá»­a sổ này." msgid "" "This lets you change player starting positions and colors. A particular " "color will always start in a particular location. Some positions may only be " "played by a computer player or only by a human player." msgstr "" "Äiá»u này cho phép ngươi thay đổi vị trí và màu sắc bắt đầu cá»§a ngưá»i chÆ¡i. " "Má»™t màu cụ thể sẽ luôn bắt đầu ở má»™t vị trí cụ thể. Má»™t số vị trí chỉ có thể " "được chÆ¡i bởi ngưá»i chÆ¡i máy tính hoặc chỉ bởi ngưá»i chÆ¡i." msgid "" "This lets you change the class of a player. Classes are not always " "changeable. Depending on the scenario, a player may receive additional towns " "and/or heroes not of their primary alignment." msgstr "" "Äiá»u này cho phép ngươi thay đổi lá»›p cá»§a má»™t ngưá»i chÆ¡i. Các chá»§ng tá»™c không " "phải lúc nào cÅ©ng có thể thay đổi. Tùy thuá»™c vào kịch bản, ngưá»i chÆ¡i có thể " "nhận được các thị trấn và/hoặc tướng bổ sung không thuá»™c liên kết chính cá»§a " "há»." msgid "Handicap" msgstr "Chấp" #, fuzzy msgid "" "This lets you change the handicap of a particular player. Only human players " "may have a handicap. Handicapped players start with fewer resources and earn " "15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." msgstr "" "Äiá»u này cho phép ngươi thay đổi Ä‘iểm chấp cá»§a má»™t ngưá»i chÆ¡i cụ thể. Chỉ có " "con ngưá»i má»›i có thể bị khuyết tật. Ngưá»i chÆ¡i bị khuyết tật bắt đầu vá»›i ít " "tài nguyên hÆ¡n và kiếm được ít tài nguyên hÆ¡n 15 hoặc 30% má»—i lượt tương ứng " "đối vá»›i ngưá»i khuyết tật nhẹ và nặng." msgid "%{color} player" msgstr "ngưá»i chÆ¡i mầu %{color}" msgid "No Handicap" msgstr "Không Chấp" #, fuzzy msgid "" "No special restrictions on starting resources and resource income per turn." msgstr "" "Không có hạn chế đặc biệt nào vá» tài nguyên bắt đầu và kiếm chúng má»—i lượt." msgid "Mild Handicap" msgstr "Chấp Ãt" #, fuzzy msgid "" "Players with mild handicap start with fewer resources and earn 15% fewer " "resources per turn." msgstr "" "Ngưá»i chÆ¡i chấp ít bắt đầu vá»›i ít tài nguyên hÆ¡n và kiếm được ít tài nguyên " "hÆ¡n 15% má»—i lượt." msgid "Severe Handicap" msgstr "Chấp Nhiá»u" #, fuzzy msgid "" "Players with severe handicap start with fewer resources and earn 30% fewer " "resources per turn." msgstr "" "Ngưá»i chÆ¡i chấp nhiá»u bắt đầu vá»›i ít tài nguyên hÆ¡n và kiếm được ít tài " "nguyên hÆ¡n 30% má»—i lượt." msgid "" "Default\n" "value" msgstr "" #, fuzzy msgid "Set %{skill} Skill" msgstr "Chá»n Kỹ năng Tấn công" msgid "Set %{skill} base value. Right-click to reset all skills to default." msgstr "" msgid "View %{skill} Info" msgstr "Xem Thông tin %{skill}" #, fuzzy msgid "" "Default\n" "skill" msgstr "Phòng thá»§" msgid "The available values range from %{min} to %{max}." msgstr "" msgid "Keyboard|123" msgstr "" msgid "Keyboard|SPACE" msgstr "" msgid "Keyboard|ABC" msgstr "" msgid "The entered value is invalid." msgstr "" msgid "" "The entered value is out of range.\n" "It should be not less than %{minValue} and not more than %{maxValue}." msgstr "" msgid "Kingdom Income" msgstr "Thu nhập Vương quốc" msgid "Kingdom Income per day." msgstr "Thu nhập Vương quốc má»™t ngày." msgid "For every lighthouse controlled, your ships will move further each day." msgstr "" "Vá»›i má»—i ngá»n hải đăng được kiểm soát, tàu cá»§a ngươi sẽ di chuyển xa hÆ¡n má»—i " "ngày." msgid "English" msgstr "Tiếng Anh" msgid "French" msgstr "Tiếng Pháp" msgid "Polish" msgstr "Tiếng Ba Lan" msgid "German" msgstr "Tiếng Äức" msgid "Russian" msgstr "Tiếng Nga" msgid "Italian" msgstr "Tiếng Ã" msgid "Czech" msgstr "Tiếng Séc" msgid "Norwegian" msgstr "Tiếng Na Uy" msgid "Belarusian" msgstr "Tiếng Bê La Rút" msgid "Bulgarian" msgstr "Tiếng Bun Ga Ri" msgid "Ukrainian" msgstr "Tiếng U Cá» Rai Na" msgid "Romanian" msgstr "Tiếng Ru Ma Ni" msgid "Spanish" msgstr "Tiếng Tây Ban Nha" msgid "Swedish" msgstr "Tiếng Thụy Äiển" msgid "Portuguese" msgstr "Tiếng Bồ Äào Nha" msgid "Turkish" msgstr "Tiếng Thổ NhÄ© Kỳ" msgid "Dutch" msgstr "Tiếng Hà Lan" msgid "Hungarian" msgstr "Tiếng Hung Ga Ri" msgid "Danish" msgstr "Tiếng Äan Mạch" msgid "Slovak" msgstr "Tiếng Slovak" msgid "Vietnamese" msgstr "Tiếng Việt" msgid "Slow" msgstr "Chậm" msgid "Fast" msgstr "Nhanh" msgid "Very Fast" msgstr "Rất nhanh" msgid "Evil" msgstr "Xấu" msgid "Good" msgstr "Tốt" msgid ", FPS: " msgstr ", FPS: " #, fuzzy msgid "shipAndGraveyard|%{object} robber" msgstr "%{object} cướp" #, fuzzy msgid "pyramid|%{object} raided" msgstr "%{object} lính" msgid "Ector" msgstr "Ector" msgid "Gwenneth" msgstr "Gwenneth" msgid "Sir Gallant" msgstr "Sir Gallant" msgid "Tyro" msgstr "Tyro" msgid "Dimitry" msgstr "Dimitry" msgid "Ruby" msgstr "Ruby" msgid "Crag Hack" msgstr "Crag Hack" msgid "Fineous" msgstr "Fineous" msgid "Jezebel" msgstr "Jezebel" msgid "Atlas" msgstr "Atlas" msgid "Ergon" msgstr "Ergon" msgid "Jaclyn" msgstr "Jaclyn" msgid "Gem" msgstr "Gem" msgid "Natasha" msgstr "Natasha" msgid "Carlawn" msgstr "Carlawn" msgid "Luna" msgstr "Luna" msgid "Arie" msgstr "Arie" msgid "Barok" msgstr "Barok" msgid "Kastore" msgstr "Kastore" msgid "Falagar" msgstr "Falagar" msgid "Dawn" msgstr "Dawn" msgid "Flint" msgstr "Flint" msgid "Halon" msgstr "Halon" msgid "Myra" msgstr "Myra" msgid "Myrini" msgstr "Myrini" msgid "Wilfrey" msgstr "Wilfrey" msgid "Mandigal" msgstr "Mandigal" msgid "Sarakin" msgstr "Sarakin" msgid "Charity" msgstr "Charity" msgid "Darlana" msgstr "Darlana" msgid "Ranloo" msgstr "Ranloo" msgid "Rialdo" msgstr "Rialdo" msgid "Zam" msgstr "Zam" msgid "Zom" msgstr "Zom" msgid "Celia" msgstr "Celia" msgid "Roxana" msgstr "Roxana" msgid "Lord Corlagon" msgstr "Lord Corlagon" msgid "Lord Halton" msgstr "Lord Halton" msgid "Sister Eliza" msgstr "Sister Eliza" msgid "Brother Brax" msgstr "Brother Brax" msgid "Dainwin" msgstr "Dainwin" msgid "Joseph" msgstr "Joseph" msgid "Mog" msgstr "Mog" msgid "Solmyr" msgstr "Solmyr" msgid "Ceallach" msgstr "Ceallach" msgid "Drakonia" msgstr "Drakonia" msgid "Elderian" msgstr "Elderian" msgid "Gallavant" msgstr "Gallavant" msgid "Jarkonas" msgstr "Jarkonas" msgid "Martine" msgstr "Martine" msgid " gives you maximum morale" msgstr " cho ngươi tối Ä‘a tinh thần" msgid " gives you maximum luck" msgstr " cho ngươi tối Ä‘a may mắn" #, fuzzy msgid "You cannot have multiple spell books." msgstr "Không thể chuyển Sách phép" msgid "You cannot pick up this artifact, you already have a full load!" msgstr "Ngươi không thể nhặt bảo vật này, ngươi đã có đầy đủ!" msgid "To cast spells, you must first buy a spell book for %{gold} gold." msgstr "" "Äể có thể niệm chú, trước tiên ngươi phải mua má»™t quyển sách phép vá»›i giá " "%{gold} vàng." msgid "Unfortunately, you seem to be a little short of cash at the moment." msgstr "Thật không may, hiện tại ngươi có vẻ hÆ¡i thiếu tiá»n." msgid "Do you wish to buy one?" msgstr "Ngươi có muốn mua má»™t?" msgid "%{count} / day" msgstr "%{count} / ngày" msgid "one" msgstr "má»™t" msgid "two" msgstr "hai" msgid "A whirlpool engulfs your ship. Some of your army has fallen overboard." msgstr "" "Má»™t xoáy nước nhấn chìm con tàu cá»§a ngươi. Má»™t số quân đội cá»§a ngươi đã rÆ¡i " "xuống biển." msgid "Insulted by your refusal of their offer, the monsters attack!" msgstr "" "Bị xúc phạm bởi việc ngươi từ chối lá»i đỠnghị cá»§a há», lÅ© quái vật tấn công!" msgid "" "The %{monster}, awed by the power of your forces, begin to scatter.\n" "Do you wish to pursue and engage them?" msgstr "" "%{monster}, kinh hãi trước sức mạnh lá»±c lượng cá»§a ngươi, bắt đầu phân tán.\n" "Ngươi có muốn theo Ä‘uổi và thu phục há» không?" msgid "Ransacking an enemy camp, you discover a hidden cache of treasures." msgstr "Lục soát trại cá»§a kẻ thù, ngươi phát hiện ra má»™t kho báu ẩn giấu." msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with these resources, " "come back next week for more.\"" msgstr "" "Ngưá»i giữ cối xay thông báo:\n" "\"Thưa ngài, tôi đã rất cố gắng để cung cấp cho ngài những tài nguyên này, " "tuần sau hãy quay lại để lấy thêm.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there are no resources currently available. Please try " "again next week.\"" msgstr "" "Ngưá»i giữ cối xay thông báo:\n" "\"Thưa ngài, tôi xin lá»—i, hiện tại không có tài nguyên nào. Vui lòng thá»­ lại " "vào tuần tá»›i.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I have been working very hard to provide you with this gold, come " "back next week for more.\"" msgstr "" "Ngưá»i giữ cối xay thông báo:\n" "\"Thưa ngài, tôi đã làm việc rất chăm chỉ để cung cấp số vàng này cho ngài, " "tuần sau hãy quay lại để lấy thêm.\"" msgid "" "The keeper of the mill announces:\n" "\"Milord, I am sorry, there is no gold currently available. Please try again " "next week.\"" msgstr "" "Ngưá»i giữ cối xay thông báo:\n" "\"Thưa ngài, tôi xin lá»—i, hiện tại không có vàng. Vui lòng thá»­ lại vào tuần " "tá»›i.\"" msgid "" "You've found an abandoned lean-to.\n" "Poking about, you discover some resources hidden nearby." msgstr "" "Ngươi đã tìm thấy má»™t ngôi nhà bị bá» hoang.\n" "Khi khám phá, ngươi phát hiện ra má»™t số tài nguyên ẩn gần đó." msgid "The lean-to is long abandoned. There is nothing of value here." msgstr "" "Ngôi nhà dưá»ng như đã bị bá» hoang từ lâu. Chẳng có gì có giá trị ở đây cả." msgid "" "You catch a leprechaun foolishly sleeping amidst a cluster of magic " "mushrooms.\n" "In exchange for his freedom, he guides you to a small pot filled with " "precious things." msgstr "" "Ngươi bắt gặp má»™t con yêu tinh Ä‘ang ngá»§ say giữa má»™t đám nấm thần.\n" "Äể đổi lấy sá»± tá»± do cá»§a mình, anh ta dẫn ngươi đến má»™t chiếc bình nhá» chứa " "đầy những thứ quý giá." msgid "" "You've found a magic garden, the kind of place that leprechauns and faeries " "like to cavort in, but there is no one here today.\n" "Perhaps you should try again next week." msgstr "" "Ngươi đã tìm thấy má»™t khu vưá»n ma thuật, má»™t nÆ¡i mà các yêu tinh và thần " "tiên thích vui đùa, nhưng hôm nay không có ai ở đây cả.\n" "Có lẽ ngươi nên thá»­ lại vào tuần tá»›i." msgid "You come upon the remains of an unfortunate adventurer." msgstr "Ngươi tình cá» gặp hài cốt cá»§a má»™t nhà thám hiểm không may." msgid "Treasure" msgstr "Kho báu" msgid "Searching through the tattered clothing, you find the %{artifact}." msgstr "Lục lá»i trong bá»™ quần áo rách rưới, ngươi tìm thấy %{artifact}." msgid "Searching through the tattered clothing, you find nothing." msgstr "Lục lá»i trong bá»™ quần áo rách rưới, ngươi chẳng tìm được gì." msgid "" "You come across an old wagon left by a trader who didn't quite make it to " "safe terrain." msgstr "" "Ngươi bắt gặp má»™t toa xe cÅ© do má»™t thương nhân để lại, ngưá»i không thể đến " "được địa hình an toàn." msgid "Unfortunately, others have found it first, and the wagon is empty." msgstr "" "Thật không may, những kẻ khác đã tìm thấy nó trước và toa xe trống rá»—ng." msgid "Searching inside, you find the %{artifact}." msgstr "Tìm kiếm bên trong, ngươi tìm thấy %{artifact}." msgid "Inside, you find some of the wagon's cargo still intact." msgstr "Bên trong, ngươi thấy má»™t số hàng hóa cá»§a toa xe vẫn còn nguyên vẹn." msgid "You search through the flotsam, and find some wood and some gold." msgstr "Ngươi tìm kiếm khắp nÆ¡i và tìm thấy má»™t ít gá»— và má»™t ít vàng." msgid "You search through the flotsam, and find some wood." msgstr "Ngươi tìm kiếm khắp các vật trôi nổi và tìm thấy má»™t ít gá»—." msgid "You search through the flotsam, but find nothing." msgstr "Ngươi tìm kiếm khắp các vật trôi nổi, nhưng không tìm thấy gì." msgid "Shrine of the 1st Circle" msgstr "Äá»n thá» Vòng 1" msgid "" "You come across a small shrine attended by a group of novice acolytes.\n" "In exchange for your protection, they agree to teach you a simple spell - " "'%{spell}'." msgstr "" "Ngươi Ä‘i ngang qua má»™t ngôi Ä‘á»n nhá» có má»™t nhóm ngưá»i má»›i tập sá»± tham dá»±.\n" "Äể đổi lấy sá»± bảo vệ cá»§a ngươi, hỠđồng ý dạy ngươi má»™t câu thần chú đơn " "giản - '%{spell}'." msgid "Shrine of the 2nd Circle" msgstr "Äá»n thá» Vòng 2" msgid "" "You come across an ornate shrine attended by a group of rotund friars.\n" "In exchange for your protection, they agree to teach you a spell - " "'%{spell}'." msgstr "" "Ngươi Ä‘i ngang qua má»™t ngôi Ä‘á»n được trang trí công phu vá»›i sá»± tham dá»± cá»§a " "má»™t nhóm tu sÄ© tròn trịa.\n" "Äể đổi lấy sá»± bảo vệ cá»§a ngươi, hỠđồng ý dạy ngươi má»™t câu thần chú - " "'%{spell}'." msgid "Shrine of the 3rd Circle" msgstr "Äá»n thá» Vòng 3" msgid "" "You come across a lavish shrine attended by a group of high priests.\n" "In exchange for your protection, they agree to teach you a sophisticated " "spell - '%{spell}'." msgstr "" "Ngươi Ä‘i ngang qua má»™t ngôi Ä‘á»n xa hoa có sá»± tham dá»± cá»§a má»™t nhóm linh mục " "cao cấp.\n" "Äể đổi lấy sá»± bảo vệ cá»§a ngươi, hỠđồng ý dạy ngươi má»™t câu thần chú phức " "tạp - '%{spell}'." msgid "" "\n" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "\n" "Thật không may, ngươi không có trí tuệ để hiểu câu thần chú và ngươi không " "thể há»c được nó." msgid "" "\n" "Unfortunately, you already have knowledge of this spell, so there is nothing " "more for them to teach you." msgstr "" "\n" "Thật không may, ngươi đã có kiến thức vá» phép thuật này rồi nên há» không còn " "gì để dạy ngươi nữa." msgid "" "\n" "Unfortunately, you have no Magic Book to record the spell with." msgstr "" "\n" "Rất tiếc, ngươi không có Sách Phép để ghi lại lại những phép thuật." msgid "" "You approach the hut and observe a witch inside studying an ancient tome on " "%{skill}.\n" "\n" msgstr "" "Ngươi đến gần túp lá»u và quan sát má»™t phù thá»§y bên trong Ä‘ang nghiên cứu má»™t " "cuốn sách cổ vá» %{skill}.\n" "\n" msgid "" "As you approach, she turns and focuses her one glass eye on you.\n" "\"You already know everything you deserve to learn!\" the witch screeches. " "\"NOW GET OUT OF MY HOUSE!\"" msgstr "" "Khi ngươi đến gần, cô ấy quay lại và tập trung má»™t con mắt thá»§y tinh vào " "ngươi.\n" "\"Ngươi đã biết tất cả má»i thứ ngươi xứng đáng được há»c!\" mụ phù thá»§y rít " "lên. \"BÂY GIỜ RA KHỎI NHÀ CỦA TÔI!\"" msgid "" "As you approach, she turns and speaks.\n" "\"You already know that which I would teach you. I can help you no further.\"" msgstr "" "Khi ngươi đến gần, cô ấy quay lại và nói.\n" "\"Ngươi đã biết Ä‘iá»u tôi sẽ dạy cho ngươi. Tôi không thể giúp gì thêm cho " "ngươi nữa.\"" msgid "" "An ancient and immortal witch living in a hut with bird's legs for stilts " "teaches you %{skill} for her own inscrutable purposes." msgstr "" "Má»™t phù thá»§y cổ xưa và bất tá»­ sống trong má»™t túp lá»u có chân chim làm nhà " "sàn dạy ngươi %{skill} cho những mục đích khó hiểu cá»§a riêng bà ta." msgid "As you drink the sweet water, you gain luck for your next battle." msgstr "Khi uống nước ngá»t, ngươi sẽ gặp may mắn cho trận chiến tiếp theo." msgid "You drink from the enchanted fountain, but nothing happens." msgstr "Ngươi uống nước từ đài phun nước mê hoặc, nhưng không có gì xảy ra." msgid "You enter the faerie ring, but nothing happens." msgstr "Ngươi bước vào vòng tiên, nhưng không có gì xảy ra." msgid "" "Upon entering the mystical faerie ring, your army gains luck for its next " "battle." msgstr "" "Khi bước vào vòng tròn thần tiên, quân đội cá»§a ngươi sẽ gặp may mắn cho trận " "chiến tiếp theo." msgid "" "You've found an ancient and weathered stone idol.\n" "It is supposed to grant luck to visitors, but since the stars are already " "smiling upon you, it does nothing." msgstr "" "Ngươi đã tìm thấy má»™t tượng đá cổ xưa và bị phong hóa.\n" "Nó được cho là mang lại may mắn cho du khách, nhưng vì các ngôi sao đã mỉm " "cưá»i vá»›i ngươi nên nó chẳng mang lại tác dụng gì." msgid "" "You've found an ancient and weathered stone idol.\n" "Kissing it is supposed to be lucky, so you do. The stone is very cold to the " "touch." msgstr "" "Ngươi đã tìm thấy má»™t tượng đá cổ xưa và bị phong hóa.\n" "Hôn nó được cho là may mắn, ngươi cÅ©ng vậy. Äá rất lạnh khi chạm vào." msgid "The mermaids silently entice you to return later and be blessed again." msgstr "" "Các nàng tiên cá âm thầm dụ dá»— ngươi quay lại sau và được ban phước lần nữa." #, fuzzy msgid "" "The magical, soothing beauty of the Mermaids reaches you and your crew.\n" "Just for a moment, you forget your worries and bask in the beauty of the " "moment.\n" "The mermaids' charms bless you with increased luck for your next combat." msgstr "" "Vẻ đẹp huyá»n diệu, êm dịu cá»§a Nàng tiên cá sẽ đến vá»›i ngươi và phi hành Ä‘oàn " "cá»§a ngươi.\n" "Chỉ trong chốc lát, ngươi quên Ä‘i những lo lắng và đắm mình trong vẻ đẹp cá»§a " "khoảnh khắc đó.\n" "Bùa cá»§a nàng tiên cá sẽ giúp ngươi tăng thêm may mắn trong trận chiến tiếp " "theo." msgid "" "You come upon the pyramid of a great and ancient king.\n" "You are tempted to search it for treasure, but all the old stories warn of " "fearful curses and undead guardians.\n" "Will you search?" msgstr "" "Ngươi đến trên kim tá»± tháp cá»§a má»™t vị vua vÄ© đại và cổ xưa.\n" "Ngươi bị cám dá»— để tìm kiếm kho báu, nhưng tất cả những câu chuyện cổ Ä‘á»u " "cảnh báo vá» những lá»i nguyá»n đáng sợ và những ngưá»i bảo vệ bất tá»­.\n" "Ngươi sẽ tìm kiếm chứ?" msgid "" "Upon defeating the monsters, you decipher an ancient glyph on the wall, " "telling the secret of the spell - '" msgstr "" "Sau khi đánh bại lÅ© quái vật, ngươi giải mã được má»™t hình khắc cổ trên " "tưá»ng, nói lên bí mật cá»§a câu thần chú - '" msgid "Unfortunately, you have no Magic Book to record the spell with." msgstr "Rất tiếc, ngươi không có Sách Phép để ghi lại lại những phép thuật." msgid "" "Unfortunately, you do not have the wisdom to understand the spell, and you " "are unable to learn it." msgstr "" "Thật không may, ngươi không có trí tuệ để hiểu câu thần chú và ngươi không " "thể há»c được nó." msgid "" "You come upon the pyramid of a great and ancient king.\n" "Routine exploration reveals that the pyramid is completely empty." msgstr "" "Ngươi đến trên kim tá»± tháp cá»§a má»™t vị vua vÄ© đại và cổ xưa.\n" "Thăm dò định kỳ cho thấy kim tá»± tháp hoàn toàn trống rá»—ng." msgid "" "A drink at the well is supposed to restore your spell points, but you are " "already at maximum." msgstr "" "Äồ uống ở giếng được cho là sẽ khôi phục Ä‘iểm thần chú cá»§a ngươi, nhưng " "ngươi đã đạt mức tối Ä‘a rồi." msgid "A second drink at the well in one day will not help you." msgstr "" "Lần uống thứ hai bên giếng trong má»™t ngày sẽ không giúp ích được gì cho " "ngươi." msgid "A drink from the well has restored your spell points to maximum." msgstr "Äồ uống từ giếng đã khôi phục Ä‘iểm thần chú cá»§a ngươi lên mức tối Ä‘a." msgid "" "\"I'm sorry sir,\" The leader of the soldiers says, \"but you already know " "everything we have to teach.\"" msgstr "" "\"Tôi xin lá»—i thưa ngài,\" Ngưá»i chỉ huy nói, \"nhưng ngài đã biết tất cả " "những gì chúng tôi phải dạy rồi.\"" msgid "The soldiers living in the fort teach you a few new defensive tricks." msgstr "" "Những ngưá»i lính sống trong pháo đài sẽ dạy cho ngươi má»™t số thá»§ thuật phòng " "thá»§ má»›i." msgid "" "You've come upon a mercenary camp practicing their tactics. \"You're too " "advanced for us,\" the mercenary captain says. \"We can teach nothing more.\"" msgstr "" "Ngươi đã gặp má»™t trại lính đánh thuê Ä‘ang thá»±c hiện chiến thuật cá»§a há». " "\"Ngài quá tiến bá»™ so vá»›i chúng tôi,\" đội trưởng lính đánh thuê nói. " "\"Chúng tôi không thể dạy thêm gì nữa.\"" msgid "" "You've come upon a mercenary camp practicing their tactics. The mercenaries " "welcome you and your troops and invite you to train with them." msgstr "" "Ngươi đã gặp má»™t trại lính đánh thuê Ä‘ang thá»±c hành chiến thuật cá»§a há». " "Những ngưá»i lính đánh thuê chào đón ngươi và quân đội cá»§a ngươi và má»i ngươi " "huấn luyện cùng há»." msgid "\"Go 'way!\", the witch doctor barks, \"you know all I know.\"" msgstr "\"Äi Ä‘i!\", phù thá»§y gào lên, \"ngươi biết tất cả những gì Ta biết.\"" msgid "" "An Orcish witch doctor living in the hut deepens your knowledge of magic by " "showing you how to cast stones, read portents, and decipher the intricacies " "of chicken entrails." msgstr "" "Má»™t bác sÄ© phù thá»§y Orcish sống trong túp lá»u giúp ngươi đào sâu kiến thức " "vá» phép thuật bằng cách chỉ cho ngươi cách ném đá, Ä‘á»c Ä‘iá»m báo và giải mã " "sá»± phức tạp cá»§a ruá»™t gà." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, the Druids turn you away, indicating they have nothing " "new to teach you." msgstr "" "Ngươi đã tìm thấy má»™t nhóm Tu sÄ© Ä‘ang thá» cúng tại má»™t trong những dinh thá»± " "bằng đá kỳ lạ cá»§a há». Im lặng, các Tu sÄ© từ chối ngươi, cho thấy há» không có " "gì má»›i để dạy ngươi." msgid "" "You've found a group of Druids worshipping at one of their strange stone " "edifices. Silently, they teach you new ways to cast spells." msgstr "" "Ngươi đã tìm thấy má»™t nhóm Tu sÄ© Ä‘ang thá» cúng tại má»™t trong những dinh thá»± " "bằng đá kỳ lạ cá»§a há». HỠâm thầm dạy ngươi những cách má»›i để niệm phép." msgid "" "You tentatively approach the burial ground of ancient warriors. Do you want " "to search the graves?" msgstr "" "Ngươi ngập ngừng tiếp cận nÆ¡i chôn cất các chiến binh cổ xưa. Ngươi có muốn " "tìm kiếm những ngôi má»™?" msgid "" "You spend several hours searching the graves and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Ngươi dành vài giá» tìm kiếm các ngôi má»™ và không tìm thấy gì. Má»™t hành động " "hèn hạ như vậy làm giảm tinh thần quân đội cá»§a ngươi." msgid "Upon defeating the Zombies you search the graves and find something!" msgstr "" "Sau khi đánh bại các Thây ma, ngươi tìm kiếm các ngôi má»™ và tìm thấy thứ gì " "đó!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the shipwreck?" msgstr "" "Thân tàu mục nát cá»§a má»™t con tàu cướp biển lá»›n kêu cót két má»™t cách kỳ lạ " "khi nó bị đẩy vào những tảng đá. Ngươi có muốn tìm kiếm con tàu đắm?" msgid "" "You spend several hours sifting through the debris and find nothing. Such a " "despicable act reduces your army's morale." msgstr "" "Ngươi dành vài giỠđể sàng lá»c các mảnh vụn và không tìm thấy gì. Má»™t hành " "động hèn hạ như vậy làm giảm tinh thần quân đội cá»§a ngươi." msgid "" "Upon defeating the Ghosts you sift through the debris and find something!" msgstr "" "Sau khi đánh bại các Bóng ma, ngươi sàng lá»c các mảnh vỡ và tìm thấy thứ gì " "đó!" msgid "" "The rotting hulk of a great pirate ship creaks eerily as it is pushed " "against the rocks. Do you wish to search the ship?" msgstr "" "Thân tàu mục nát cá»§a má»™t con tàu cướp biển lá»›n kêu cót két má»™t cách kỳ lạ " "khi nó bị đẩy vào những tảng đá. Ngươi có muốn tìm kiếm con tàu?" msgid "" "Upon defeating the Skeletons you sift through the debris and find something!" msgstr "" "Sau khi đánh bại Bá»™ xương, ngươi sàng lá»c các mảnh vỡ và tìm thấy thứ gì đó!" msgid "Your men spot a navigational buoy, confirming that you are on course." msgstr "" "Ngưá»i cá»§a ngươi phát hiện ra má»™t chiếc phao định hướng, xác nhận rằng ngươi " "Ä‘ang Ä‘i đúng hướng." msgid "" "Your men spot a navigational buoy, confirming that you are on course and " "increasing their morale." msgstr "" "Ngưá»i cá»§a ngươi phát hiện ra má»™t chiếc phao định hướng, xác nhận rằng ngươi " "Ä‘ang Ä‘i đúng hướng và nâng cao tinh thần cá»§a há»." msgid "" "The drink at the oasis is refreshing, but offers no further benefit. The " "oasis might help again if you fought a battle first." msgstr "" "Äồ uống ở ốc đảo rất sảng khoái nhưng không mang lại lợi ích gì thêm. á»c đảo " "có thể giúp ích má»™t lần nữa nếu ngươi chiến đấu trước." msgid "" "A drink at the oasis fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Äồ uống tại ốc đảo sẽ tiếp thêm sức mạnh cho quân đội cá»§a ngươi và nâng cao " "tinh thần cá»§a há». Hôm nay ngươi có thể Ä‘i xa hÆ¡n má»™t chút." msgid "" "The drink at the watering hole is refreshing, but offers no further benefit. " "The watering hole might help again if you fought a battle first." msgstr "" "Äồ uống ở hố tưới nước có tác dụng giải khát nhưng không mang lại lợi ích gì " "thêm. Lá»— tưới nước có thể giúp ích má»™t lần nữa nếu ngươi chiến đấu trước." msgid "" "A drink at the watering hole fills your troops with strength and lifts their " "spirits. You can travel a bit further today." msgstr "" "Äồ uống tại hố tưới nước sẽ tiếp thêm sức mạnh cho quân đội cá»§a ngươi và " "nâng cao tinh thần cá»§a há». Hôm nay ngươi có thể Ä‘i xa hÆ¡n má»™t chút." msgid "" "It doesn't help to pray twice before a battle. Come back after you've fought." msgstr "" "Cầu nguyện hai lần trước trận chiến chẳng ích gì. Hãy quay lại sau khi chiến " "đấu xong." msgid "A visit and a prayer at the temple raises the morale of your troops." msgstr "" "Má»™t chuyến viếng thăm và cầu nguyện tại ngôi Ä‘á»n sẽ nâng cao tinh thần cho " "quân đội cá»§a ngươi." msgid "" "An old Knight appears on the steps of the gazebo. \"I am sorry, my liege, I " "have taught you all I can.\"" msgstr "" "Má»™t Hiệp sÄ© già xuất hiện trên bậc thá»m cá»§a vá»ng lâu. \"Tôi xin lá»—i, thưa bệ " "hạ, Tôi đã dạy ngài tất cả những gì có thể.\"" msgid "" "An old Knight appears on the steps of the gazebo. \"My liege, I will teach " "you all that I know to aid you in your travels.\"" msgstr "" "Má»™t Hiệp sÄ© già xuất hiện trên bậc thá»m cá»§a vá»ng lâu. \"Thưa bệ hạ, Tôi sẽ " "dạy cho ngài tất cả những gì tôi biết để há»— trợ ngài trong chuyến Ä‘i.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he says, \"I would give you an artifact as a reward, but " "you're all full.\"" msgstr "" "Ngươi đã cứu má»™t ngưá»i sống sót sau vụ đắm tàu khá»i cái chết nhất định trong " "má»™t đại dương khắc nghiệt. Biết Æ¡n, anh ấy nói, \"Tôi sẽ tặng ngài má»™t hiện " "vật như má»™t phần thưởng, nhưng ngài đã đầy túi rồi.\"" msgid "" "You've pulled a shipwreck survivor from certain death in an unforgiving " "ocean. Grateful, he rewards you for your act of kindness by giving you the " "%{art}." msgstr "" "Ngươi đã cứu má»™t ngưá»i sống sót sau vụ đắm tàu khá»i cái chết nhất định trong " "má»™t đại dương khắc nghiệt. Biết Æ¡n, anh ấy thưởng cho ngươi vì hành động tá»­ " "tế cá»§a ngươi bằng cách tặng ngươi %{art}." msgid "A leprechaun offers you the %{art} for the small price of %{gold} Gold." msgstr "" "Má»™t yêu tinh cung cấp cho ngươi %{art} vá»›i mức giá nhá» là %{gold} Vàng." msgid "" "A leprechaun offers you the %{art} for the small price of %{gold} Gold and " "%{count} %{res}." msgstr "" "Má»™t yêu tinh cung cấp cho ngươi %{art} vá»›i mức giá nhá» là %{gold} Vàng và " "%{count} %{res}." msgid "Do you wish to buy this artifact?" msgstr "Ngươi có chắc muốn mua bảo vật này?" msgid "" "You try to pay the leprechaun, but realize that you can't afford it. The " "leprechaun stamps his foot and ignores you." msgstr "" "Ngươi cố gắng trả tiá»n cho yêu tinh, nhưng nhận ra rằng ngươi không đủ khả " "năng chi trả. Yêu tinh dậm chân và phá»›t lá» ngươi." msgid "" "Insulted by your refusal of his generous offer, the leprechaun stamps his " "foot and ignores you." msgstr "" "Bị xúc phạm bởi sá»± từ chối lá»i đỠnghị hào phóng cá»§a ngươi, yêu tinh dậm " "chân và phá»›t lá» ngươi." msgid "You've found the artifact: " msgstr "Ngươi đã tìm thấy bảo vật: " msgid "" "You've found the humble dwelling of a withered hermit. The hermit tells you " "that he is willing to give the %{art} to the first wise person he meets." msgstr "" "Ngươi đã tìm thấy nÆ¡i ở khiêm tốn cá»§a má»™t ẩn sÄ© khô héo. Vị ẩn sÄ© nói vá»›i " "ngươi rằng ông ấy sẵn sàng trao %{art} cho ngưá»i thông thái đầu tiên mà ông " "ấy gặp." msgid "" "You've come across the spartan quarters of a retired soldier. The soldier " "tells you that he is willing to pass on the %{art} to the first true leader " "he meets." msgstr "" "Ngươi đã Ä‘i qua khu nhà Spartan cá»§a má»™t ngưá»i lính đã nghỉ hưu. Ngưá»i lính " "nói vá»›i ngươi rằng anh ta sẵn sàng truyá»n lại %{art} cho ngưá»i lãnh đạo thá»±c " "sá»± đầu tiên mà anh ta gặp." msgid "" "You've encountered a strange person with a hat and an owl on it. He tells " "you that he is willing to give %{art} if you have %{skill}." msgstr "" "Ngươi đã gặp má»™t ngưá»i lạ vá»›i má»™t chiếc mÅ© và má»™t con cú trên đó. Anh ấy nói " "vá»›i ngươi rằng anh ấy sẵn sàng tặng %{art} nếu ngươi có %{skill}." msgid "" "You come upon an ancient artifact. As you reach for it, a pack of Rogues " "leap out of the brush to guard their stolen loot." msgstr "" "Ngươi bắt gặp má»™t hiện vật cổ xưa. Khi ngươi vá»›i lấy nó, má»™t nhóm Lừa đảo " "nhảy ra khá»i bụi rậm để bảo vệ chiến lợi phẩm bị đánh cắp cá»§a chúng." msgid "" "Through a clearing you observe an ancient artifact. Unfortunately, it's " "guarded by a nearby %{monster}. Do you want to fight the %{monster} for the " "artifact?" msgstr "" "Thông qua má»™t khoảng trống, ngươi quan sát được má»™t hiện vật cổ xưa. Thật " "không may, nó được bảo vệ bởi má»™t %{monster} gần đó. Ngươi có muốn chiến đấu " "vá»›i %{monster} để giành cổ vật không?" msgid "Victorious, you take your prize, the %{art}." msgstr "Chiến thắng, ngươi nhận được giải thưởng cá»§a mình, %{art}." msgid "" "Discretion is the better part of valor, and you decide to avoid this fight " "for today." msgstr "" "Sá»± thận trá»ng là phần tốt hÆ¡n cá»§a lòng dÅ©ng cảm và ngươi quyết định tránh " "cuá»™c chiến này ngay hôm nay." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold pieces." msgstr "" "Sau hàng giá» cố gắng câu chiếc rương ngoài biển, ngươi mở nó ra và tìm thấy " "%{gold} vàng." msgid "" "After spending hours trying to fish the chest out of the sea, you open it " "and find %{gold} gold and the %{art}." msgstr "" "Sau hàng giá» cố gắng câu chiếc rương ngoài biển, ngươi mở nó ra và tìm thấy " "%{gold} vàng và %{art}." msgid "" "After spending hours trying to fish the chest out of the sea, you open it, " "only to find it empty." msgstr "" "Sau hàng giá» cố gắng câu chiếc rương ngoài biển, ngươi mở nó ra, và chỉ thấy " "nó trống rá»—ng." msgid "" "After scouring the area, you fall upon a hidden treasure cache. You may take " "the gold or distribute the gold to the peasants for experience. Do you wish " "to keep the gold?" msgstr "" "Sau khi lùng sục khắp khu vá»±c, ngươi sẽ phát hiện ra má»™t kho báu ẩn giấu. " "Ngươi có thể lấy vàng hoặc phân phát vàng cho nông dân để lấy kinh nghiệm. " "Ngươi có muốn giữ vàng không?" msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "%{gold} gold pieces." msgstr "" "Sau khi lùng sục khắp khu vá»±c, ngươi sẽ tìm thấy má»™t chiếc rương ẩn chứa " "những %{gold} miếng vàng." msgid "" "After scouring the area, you fall upon a hidden chest, containing the " "ancient artifact %{art}." msgstr "" "Sau khi lùng sục khắp khu vá»±c, ngươi sẽ tìm thấy má»™t chiếc rương ẩn chứa cổ " "vật %{art}." msgid "" "You stumble upon a dented and tarnished lamp lodged deep in the earth. Do " "you wish to rub the lamp?" msgstr "" "Ngươi vấp phải má»™t chiếc đèn bị móp và hoen ố nằm sâu trong lòng đất. Ngươi " "có muốn chà đèn không?" msgid "" "You have taken control of the local Alchemist shop. It will provide you with " "%{count} unit of Mercury per day." msgstr "" "Ngươi đã nắm quyá»n kiểm soát cá»­a hàng Nhà giả kim địa phương. Nó sẽ cung cấp " "cho ngươi %{count} đơn vị Thá»§y ngân má»—i ngày." msgid "" "You gain control of a sawmill. It will provide you with %{count} units of " "wood per day." msgstr "" "Ngươi giành được quyá»n kiểm soát má»™t xưởng cưa. Nó sẽ cung cấp cho ngươi " "%{count} đơn vị gá»— má»—i ngày." msgid "" "You gain control of an ore mine. It will provide you with %{count} units of " "ore per day." msgstr "" "Ngươi giành quyá»n kiểm soát má»™t má» quặng. Nó sẽ cung cấp cho ngươi %{count} " "đơn vị quặng má»—i ngày." msgid "" "You gain control of a sulfur mine. It will provide you with %{count} unit of " "sulfur per day." msgstr "" "Ngươi giành quyá»n kiểm soát má»™t má» lưu huỳnh. Nó sẽ cung cấp cho ngươi " "%{count} đơn vị lưu huỳnh má»—i ngày." msgid "" "You gain control of a crystal mine. It will provide you with %{count} unit " "of crystal per day." msgstr "" "Ngươi giành được quyá»n kiểm soát má»™t má» tinh thể. Nó sẽ cung cấp cho ngươi " "%{count} đơn vị pha lê má»—i ngày." msgid "" "You gain control of a gem mine. It will provide you with %{count} unit of " "gems per day." msgstr "" "Ngươi giành quyá»n kiểm soát má»™t mỠđá quý. Nó sẽ cung cấp cho ngươi %{count} " "đơn vị đá quý má»—i ngày." msgid "" "You gain control of a gold mine. It will provide you with %{count} gold per " "day." msgstr "" "Ngươi giành được quyá»n kiểm soát má»™t má» vàng. Nó sẽ cung cấp cho ngươi " "%{count} vàng má»—i ngày." msgid "" "The lighthouse is now under your control, and all of your ships will now " "move further each day." msgstr "" "Ngá»n hải đăng hiện nằm dưới sá»± kiểm soát cá»§a ngươi và tất cả các tàu cá»§a " "ngươi giỠđây sẽ di chuyển xa hÆ¡n má»—i ngày." msgid "You gain control of a %{name}." msgstr "Ngươi giành được quyá»n kiểm soát má»™t %{name}." msgid "" "You come upon an abandoned gold mine. The mine appears to be haunted. Do you " "wish to enter?" msgstr "" "Ngươi đến má»™t má» vàng bị bá» hoang. Khu má» dưá»ng như bị ma ám. Ngươi có muốn " "vào không?" msgid "You beat the Ghosts and are able to restore the mine to production." msgstr "Ngươi đánh bại các Bóng ma và có thể khôi phục mỠđể sản xuất." msgid "" "A group of %{monster} with a desire for greater glory wish to join you. Do " "you accept?" msgstr "" "Má»™t nhóm %{monster} khao khát đạt được vinh quang lá»›n hÆ¡n mong muốn được " "tham gia cùng ngươi. Ngươi có chấp nhận không?" msgid "As you approach the dwelling, you notice that there is no one here." msgstr "Khi ngươi đến gần ngôi nhà, ngươi nhận thấy rằng không có ai ở đây." msgid "" "You search the ruins, but the Medusas that used to live here are gone. " "Perhaps there will be more next week." msgstr "" "Ngươi tìm kiếm những tàn tích, nhưng Medusas từng sống ở đây đã biến mất. Có " "lẽ sẽ có nhiá»u hÆ¡n vào tuần tá»›i." msgid "" "You've found some Medusas living in the ruins. They are willing to join your " "army for a price. Do you want to recruit Medusas?" msgstr "" "Ngươi đã tìm thấy má»™t số Medusa sống trong đống đổ nát. Há» sẵn sàng gia nhập " "quân đội cá»§a ngươi vá»›i má»™t mức giá. Ngươi có muốn tuyển dụng Medusas?" msgid "" "You've found a Sprite Tree City. Unfortunately, none of the Sprites living " "there wish to join an army. Maybe next week." msgstr "" "Ngươi đã tìm thấy Sprite Tree City. Thật không may, không má»™t Sprite nào " "sống ở đó mong muốn gia nhập quân đội. Có thể là tuần sau." msgid "" "Some of the Sprites living in the tree city are willing to join your army " "for a price. Do you want to recruit Sprites?" msgstr "" "Má»™t số Sprites sống trong thành phố trên cây sẵn sàng gia nhập quân đội cá»§a " "ngươi vá»›i má»™t cái giá. Ngươi có muốn tuyển dụng Sprites?" msgid "" "A colorful Rogues' wagon stands empty here. Perhaps more Rogues will be here " "later." msgstr "" "Ở đây có má»™t toa xe đầy màu sắc cá»§a Lừa đảo trống rá»—ng. Có lẽ sau này sẽ có " "nhiá»u Lừa đảo hÆ¡n ở đây." msgid "" "Distant sounds of music and laughter draw you to a colorful wagon housing " "Rogues. Do you wish to have any Rogues join your army?" msgstr "" "Âm thanh xa xa cá»§a âm nhạc và tiếng cưá»i lôi kéo ngươi đến má»™t toa xe đầy " "màu sắc chứa Lừa đảo. Ngươi có muốn có bất kỳ Lừa đảo nào gia nhập quân đội " "cá»§a mình không?" msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. The " "tents are unoccupied. Perhaps more Nomads will be here later." msgstr "" "Má»™t nhóm lá»u rách nát cuồn cuá»™n trong gió cát Ä‘ang vẫy gá»i ngươi. Những căn " "lá»u không có ngưá»i ở. Có lẽ sau này sẽ có thêm nhiá»u ngưá»i du mục đến đây." msgid "" "A group of tattered tents, billowing in the sandy wind, beckons you. Do you " "wish to have any Nomads join you during your travels?" msgstr "" "Má»™t nhóm lá»u rách nát cuồn cuá»™n trong gió cát Ä‘ang vẫy gá»i ngươi. Ngươi có " "muốn có bất kỳ Ngưá»i du mục nào tham gia cùng ngươi trong chuyến du lịch cá»§a " "ngươi không?" msgid "The pit of mud bubbles for a minute and then lies still." msgstr "Hố bùn sá»§i bá»t má»™t phút rồi nằm yên." msgid "" "As you approach the bubbling pit of mud, creatures begin to climb out and " "position themselves around it. In unison they say: \"Mother Earth would like " "to offer you a few of her troops. Do you want to recruit Earth Elementals?\"" msgstr "" "Khi ngươi đến gần hố bùn sá»§i bá»t, các sinh vật bắt đầu trèo ra ngoài và định " "vị xung quanh nó. HỠđồng thanh nói: \"Mẹ Trái đất muốn cung cấp cho ngươi " "má»™t số quân cá»§a bà ấy. Ngươi có muốn chiêu má»™ các Nguyên tố Trái đất không?\"" msgid "You enter the structure of white stone pillars, and find nothing." msgstr "Ngươi bước vào cấu trúc cá»§a những cá»™t đá trắng và không tìm thấy gì." msgid "" "White stone pillars support a roof that rises up to the sky. As you enter " "the structure, the dead air of the outside gives way to a whirling gust that " "almost pushes you back out. The air current materializes into a barely " "visible form. The creature asks, in what can only be described as a loud " "whisper: \"Why have you come? Are you here to call upon the forces of the " "air?\"" msgstr "" "Những cá»™t đá trắng đỡ mái nhà vươn lên trá»i. Khi ngươi bước vào công trình, " "không khí chết chóc bên ngoài nhưá»ng chá»— cho má»™t cÆ¡n gió xoáy gần như đẩy " "ngươi ra ngoài. Dòng không khí hiện thá»±c hóa thành má»™t dạng khó nhìn thấy " "được. Sinh vật há»i, theo cách chỉ có thể được mô tả như má»™t lá»i thì thầm " "lá»›n: \"Tại sao ngươi lại đến? Ngươi đến đây để kêu gá»i lá»±c lượng trên không?" "\"" msgid "No Fire Elementals approach you from the lava pool." msgstr "Không có Nguyên tố Lá»­a nào tiếp cận ngươi từ hồ dung nham." msgid "" "Beneath a structure that serves to hold in heat, Fire Elementals move about " "in a fiery pool of molten lava. A group of them approach you and offer their " "services. Would you like to recruit Fire Elementals?" msgstr "" "Bên dưới má»™t cấu trúc dùng để giữ nhiệt, các Nguyên tố Lá»­a di chuyển trong " "má»™t hồ dung nham nóng chảy rá»±c lá»­a. Má»™t nhóm trong số há» tiếp cận ngươi và " "cung cấp dịch vụ cá»§a há». Ngươi có muốn chiêu má»™ Nguyên tố Lá»­a không?" msgid "A face forms in the water for a moment, and then is gone." msgstr "Má»™t khuôn mặt xuất hiện trong nước má»™t lúc rồi biến mất." msgid "" "Crystalline structures cast shadows over a small reflective pool of water. " "You peer into the pool, and a face that is not your own peers back. It asks: " "\"Would you like to call upon the powers of water?\"" msgstr "" "Các cấu trúc tinh thể đổ bóng lên má»™t hồ nước nhá» phản chiếu. Ngươi nhìn " "xuống hồ bÆ¡i, và má»™t khuôn mặt không phải là ngươi bè cá»§a ngươi quay lại. Nó " "há»i: \"Ngươi có muốn kêu gá»i sức mạnh cá»§a nước không?\"" msgid "This burial site is deathly still." msgstr "NÆ¡i chôn cất này vẫn còn chết chóc." msgid "" "Restless spirits of long dead warriors seeking their final resting place " "offer to join you in hopes of finding peace. Do you wish to recruit ghosts?" msgstr "" "Linh hồn không ngừng nghỉ cá»§a những chiến binh đã chết từ lâu Ä‘ang tìm kiếm " "nÆ¡i an nghỉ cuối cùng đỠnghị tham gia cùng ngươi vá»›i hy vá»ng tìm thấy hòa " "bình. Ngươi có muốn chiêu má»™ bóng ma không?" msgid "" "The City of the Dead is empty of life, and empty of unlife as well. Perhaps " "some undead will move in next week." msgstr "" "Thành phố cá»§a Ngưá»i chết không có sá»± sống và cÅ©ng không có sá»± sống. Có lẽ " "má»™t số xác sống sẽ chuyển đến vào tuần tá»›i." msgid "" "Some Liches living here are willing to join your army for a price. Do you " "want to recruit Liches?" msgstr "" "Má»™t số Lich sống ở đây sẵn sàng gia nhập quân đội cá»§a ngươi vá»›i má»™t cái giá. " "Ngươi có muốn tuyển dụng Liches không?" msgid "" "You've found the ruins of an ancient city, now inhabited solely by the " "undead. Will you search?" msgstr "" "Ngươi đã tìm thấy tàn tích cá»§a má»™t thành phố cổ, hiện chỉ có xác sống sinh " "sống. Ngươi sẽ tìm kiếm chứ?" msgid "" "Some of the surviving Liches are impressed by your victory over their " "fellows, and offer to join you for a price. Do you want to recruit Liches?" msgstr "" "Má»™t số Lich còn sống sót bị ấn tượng bởi chiến thắng cá»§a ngươi trước đồng " "đội cá»§a há» và đỠnghị tham gia cùng ngươi vá»›i má»™t mức giá. Ngươi có muốn " "tuyển dụng Liches không?" msgid "" "You've found one of those bridges that Trolls are so fond of living under, " "but there are none here. Perhaps there will be some next week." msgstr "" "Ngươi đã tìm thấy má»™t trong những cây cầu mà Trolls rất thích sống dưới đó, " "nhưng ở đây lại không có má»™t con nào cả. Có lẽ sẽ có má»™t số vào tuần tá»›i." msgid "" "Some Trolls living under a bridge are willing to join your army, but for a " "price. Do you want to recruit Trolls?" msgstr "" "Má»™t số Troll sống dưới cầu sẵn sàng gia nhập quân đội cá»§a ngươi nhưng phải " "trả giá. Ngươi có muốn tuyển dụng Troll không?" msgid "Trolls living under the bridge challenge you. Will you fight them?" msgstr "" "Troll sống dưới gầm cầu thách thức ngươi. Ngươi sẽ chiến đấu vá»›i chúng?" msgid "" "A few Trolls remain, cowering under the bridge. They approach you and offer " "to join your forces as mercenaries. Do you want to buy any Trolls?" msgstr "" "Má»™t vài con Troll vẫn còn ẩn nấp dưới gầm cầu. Há» tiếp cận ngươi và đỠnghị " "gia nhập lá»±c lượng cá»§a ngươi vá»›i tư cách là lính đánh thuê. Ngươi có muốn " "mua Troll không?" msgid "" "The Dragon city has no Dragons willing to join you this week. Perhaps a " "Dragon will become available next week." msgstr "" "Thành phố Rồng không có con Rồng nào sẵn sàng tham gia cùng ngươi trong tuần " "này. Có lẽ má»™t con Rồng sẽ có mặt vào tuần tá»›i." msgid "" "The Dragon city is willing to offer some Dragons for your army for a price. " "Do you wish to recruit Dragons?" msgstr "" "Thành phố Rồng sẵn sàng cung cấp má»™t số Rồng cho quân đội cá»§a ngươi vá»›i má»™t " "mức giá. Ngươi có muốn chiêu má»™ Rồng không?" msgid "" "You stand before the Dragon City, a place off-limits to mere humans. Do you " "wish to violate this rule and challenge the Dragons to a fight?" msgstr "" "Ngươi đứng trước Thành phố Rồng, má»™t nÆ¡i không có giá»›i hạn đối vá»›i con " "ngưá»i. Ngươi có muốn vi phạm quy tắc này và thách đấu vá»›i những con Rồng " "không?" msgid "" "Having defeated the Dragon champions, the city's leaders agree to supply " "some Dragons to your army for a price. Do you wish to recruit Dragons?" msgstr "" "Sau khi đánh bại các nhà vô địch Rồng, lãnh đạo thành phố đồng ý cung cấp " "má»™t số Rồng cho quân đội cá»§a ngươi vá»›i má»™t mức giá. Ngươi có muốn chiêu má»™ " "Rồng không?" msgid "From the observation tower, you are able to see distant lands." msgstr "Từ tháp quan sát, ngươi có thể nhìn thấy những vùng đất xa xôi." msgid "" "The spring only refills once a week, and someone's already been here this " "week." msgstr "" "Suối chỉ được nạp lại má»—i tuần má»™t lần, và tuần này đã có ngưá»i đến đây rồi." msgid "" "A drink at the spring is supposed to give you twice your normal spell " "points, but you are already at that level." msgstr "" "Uống nước ở suối được cho là sẽ mang lại cho ngươi gấp đôi Ä‘iểm thần chú " "bình thưá»ng, nhưng ngươi đã ở cấp độ đó rồi." msgid "" "A drink from the spring fills your blood with magic! You have twice your " "normal spell points in reserve." msgstr "" "Uống nước ở suối làm cho máu cá»§a ngươi tràn đầy ma thuật! Ngươi có gấp đôi " "số Ä‘iểm phép thuật bình thưá»ng để dá»± trữ." msgid "" "Recognizing you, the butler refuses to admit you. \"The master,\" he says, " "\"will not see the same student twice.\"" msgstr "" "Nhận ra ngươi, ngưá»i quản gia từ chối thừa nhận ngươi. Ông nói: \"Ngưá»i thầy " "sẽ không gặp má»™t há»c sinh hai lần\"." msgid "" "The butler admits you to see the master of the house. He trains you in the " "four skills a hero should know." msgstr "" "Ngưá»i quản gia cho phép ngươi đến gặp chá»§ nhân cá»§a ngôi nhà. Anh ấy huấn " "luyện ngươi bốn kỹ năng mà má»™t tướng nên biết." msgid "" "The butler opens the door and looks you up and down. \"You are neither " "famous nor diplomatic enough to be admitted to see my master,\" he sniffs. " "\"Come back when you think yourself worthy.\"" msgstr "" "Ngưá»i quản gia mở cá»­a và nhìn ngươi từ trên xuống dưới. \"Ngươi không đủ nổi " "tiếng cÅ©ng như không đủ tài ngoại giao để được nhận vào gặp chá»§ nhân cá»§a tôi," "\" anh khịt mÅ©i. \"Hãy quay lại khi ngươi thấy mình xứng đáng.\"" msgid " and " msgstr " và " msgid "" "All of the %{monsters} you have in your army have been trained by the battle " "masters of the fort. Your army now contains %{monsters2}." msgstr "" "Tất cả %{monsters} ngươi có trong quân đội cá»§a mình Ä‘á»u đã được huấn luyện " "bởi các bậc thầy chiến đấu cá»§a pháo đài. Quân đội cá»§a ngươi hiện có " "%{monsters2}." msgid "" "An unusual alliance of Ogres, Orcs, and Dwarves offer to train (upgrade) any " "such troops brought to them. Unfortunately, you have none with you." msgstr "" "Má»™t liên minh bất thưá»ng cá»§a Yêu tinh, Orc và Ngưá»i lùn đỠnghị huấn luyện " "(nâng cấp) bất kỳ đội quân nào như vậy được mang đến cho há». Thật không may, " "ngươi không có gì bên mình." msgid "All of your %{monsters} have been upgraded into %{monsters2}." msgstr "Tất cả %{monsters} cá»§a ngươi đã được nâng cấp thành %{monsters2}." msgid "" "A blacksmith working at the foundry offers to convert all Pikemen and " "Swordsmen's weapons brought to him from iron to steel. He also says that he " "knows a process that will convert Iron Golems into Steel Golems. " "Unfortunately, you have none of these troops in your army, so he can't help " "you." msgstr "" "Má»™t thợ rèn làm việc tại xưởng đúc đỠnghị chuyển đổi tất cả vÅ© khí cá»§a " "Pikemen và Swordsmen mang đến cho anh ta từ sắt thành thép. Anh ấy cÅ©ng nói " "rằng anh ấy biết má»™t quy trình sẽ chuyển đổi Golem sắt thành Golem thép. " "Thật không may, quân đội cá»§a ngươi không có những đội quân này nên anh ta " "không thể giúp ngươi." msgid "" "The captain looks at you with surprise and says:\n" "\"You already have all the maps I know about. Let me fish in peace now.\"" msgstr "" "Thuyá»n trưởng nhìn ngươi ngạc nhiên và nói:\n" "\"Ngươi đã có tất cả các bản đồ mà ta biết. Hãy để ta câu cá trong yên bình." "\"" msgid "" "A retired captain living on this refurbished fishing platform offers to sell " "you maps of the sea he made in his younger days for 1,000 gold. Do you wish " "to buy the maps?" msgstr "" "Má»™t thuyá»n trưởng đã nghỉ hưu sống trên giàn đánh cá đã được tân trang lại " "này đỠnghị bán cho ngươi những bản đồ biển mà ông ấy đã làm khi còn trẻ vá»›i " "giá 1.000 vàng. Ngươi có muốn mua bản đồ không?" #, fuzzy msgid "" "The captain sighs. \"You don't have enough money, eh? You can't expect me to " "give my maps away for free!\"" msgstr "" "Thuyá»n trưởng thở dài. \"Ngươi không có đủ tiá»n phải không? Ngươi không thể " "mong đợi tôi tặng bản đồ cá»§a mình miá»…n phí!\"" msgid "" "You come upon an obelisk made from a type of stone you have never seen " "before. Staring at it intensely, the smooth surface suddenly changes to an " "inscription. The inscription is a piece of a lost ancient map. Quickly you " "copy down the piece and the inscription vanishes as abruptly as it appeared." msgstr "" "Ngươi bắt gặp má»™t đài tưởng niệm được làm từ má»™t loại đá mà ngươi chưa từng " "thấy trước đây. Nhìn chăm chú vào nó, bá» mặt nhẵn nhụi đột nhiên biến thành " "má»™t dòng chữ. Dòng chữ là má»™t mảnh cá»§a má»™t bản đồ cổ bị thất lạc. Ngươi " "nhanh chóng sao chép tác phẩm xuống và dòng chữ biến mất đột ngá»™t như khi nó " "xuất hiện." msgid "You have already been to this obelisk." msgstr "Ngươi đã tá»›i đài tưởng niệm này." msgid "" "Upon your approach, the tree opens its eyes in delight. \"It is good to see " "you, my student. I hope my teachings have helped you.\"" msgstr "" "Khi ngươi đến gần, cái cây mở mắt vui mừng. \"Thật vui được gặp lại ngươi, " "há»c trò cá»§a ta. Ta hy vá»ng những lá»i dạy cá»§a ta đã giúp ích cho ngươi.\"" msgid "" "Upon your approach, the tree opens its eyes in delight. \"Ahh, an " "adventurer! Allow me to teach you a little of what I have learned over the " "ages.\"" msgstr "" "Khi ngươi đến gần, cái cây mở mắt vui mừng. \"À, má»™t nhà thám hiểm! Cho phép " "ta dạy cho ngươi má»™t chút vá» những gì ta đã há»c được qua nhiá»u thá»i đại.\"" msgid "Upon your approach, the tree opens its eyes in delight." msgstr "Khi ngươi đến gần, cái cây mở mắt vui mừng." msgid "" "\"Ahh, an adventurer! I will be happy to teach you a little of what I have " "learned over the ages for a mere %{count} %{res}.\"" msgstr "" "\"À, má»™t nhà thám hiểm! Cho phép ta dạy cho ngươi má»™t chút vá» những gì ta đã " "há»c được qua nhiá»u thá»i đại vá»›i chỉ %{count} %{res}.\"" msgid "(Just bury it around my roots.)" msgstr "(Hãy chôn nó quanh rá»… cá»§a tôi.)" msgid "Tears brim in the eyes of the tree." msgstr "Nước mắt giàn giụa trong mắt cây." msgid "\"I need %{count} %{res}.\"" msgstr "\"Ta cần %{count} %{res}.\"" msgid "it whispers. (sniff) \"Well, come back when you can pay me.\"" msgstr "" "nó thì thầm. (khịt mÅ©i) \"Chà, hãy quay lại khi ngươi có thể trả tiá»n cho ta." "\"" msgid "" "Nestled among the trees sits a blind seer. After you explain the intent of " "your journey, the seer activates his crystal ball, allowing you to see the " "strengths and weaknesses of your opponents." msgstr "" "Ẩn mình giữa những tán cây là má»™t nhà tiên tri mù. Sau khi ngươi giải thích " "mục đích chuyến hành trình cá»§a mình, nhà tiên tri sẽ kích hoạt quả cầu pha " "lê cá»§a mình, cho phép ngươi nhìn thấy Ä‘iểm mạnh và Ä‘iểm yếu cá»§a đối thá»§." msgid "" "The entrance to the cave is dark, and a foul, sulfurous smell issues from " "the cave mouth. Will you enter?" msgstr "" "Cá»­a hang tối om, miệng hang bốc ra mùi lưu huỳnh hôi thối. Ngươi sẽ vào chứ?" msgid "Except for evidence of a terrible battle, the cave is empty." msgstr "" "Ngoại trừ bằng chứng vá» má»™t trận chiến khá»§ng khiếp, hang động trống rá»—ng." msgid "" "You find a powerful and grotesque Demon in the cave. \"Today,\" it rasps, " "\"you will fight and surely die. But I will give you a choice of deaths. You " "may fight me, or you may fight my servants. Do you prefer to fight my " "servants?\"" msgstr "" "Ngươi tìm thấy má»™t con quá»· mạnh mẽ và kỳ cục trong hang động. \"Hôm nay,\" " "nó rít lên, \"ngươi sẽ chiến đấu và chắc chắn sẽ chết. Nhưng ta sẽ cho ngươi " "lá»±a chá»n cái chết. Ngươi có thể chiến đấu vá»›i ta, hoặc ngươi có thể chiến " "đấu vá»›i những ngưá»i hầu cá»§a ta. Ngươi thích chiến đấu vá»›i những ngưá»i hầu " "cá»§a ta hÆ¡n?\"" msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points." msgstr "" "Con quá»· hét lên thách thức và tấn công! Sau má»™t trận chiến ngắn ngá»§i và " "tuyệt vá»ng, ngươi tiêu diệt được quái vật và nhận được %{exp} Ä‘iểm kinh " "nghiệm." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and receive %{exp} experience points and " "%{count} gold." msgstr "" "Con quá»· hét lên thách thức và tấn công! Sau má»™t trận chiến ngắn ngá»§i và " "tuyệt vá»ng, ngươi tiêu diệt được quái vật và nhận được %{exp} Ä‘iểm kinh " "nghiệm và %{count} vàng." msgid "" "The Demon screams its challenge and attacks! After a short, desperate " "battle, you slay the monster and find the %{art} in the back of the cave." msgstr "" "Con quá»· hét lên thách thức và tấn công! Sau má»™t trận chiến ngắn ngá»§i và " "tuyệt vá»ng, ngươi tiêu diệt con quái vật và tìm thấy %{art} ở phía sau hang " "động." msgid "" "Seeing that you do not have %{count} gold, the demon slashes you with its " "claws, and the last thing you see is a red haze." msgstr "" "Thấy ngươi không có %{count} vàng, con quá»· dùng móng vuốt chém ngươi và Ä‘iá»u " "cuối cùng ngươi nhìn thấy là má»™t làn sương mù màu Ä‘á»." msgid "" "The Demon leaps upon you and has its claws at your throat before you can " "even draw your sword. \"Your life is mine,\" it says. \"I will sell it back " "to you for %{count} gold.\"" msgstr "" "Con quá»· lao vào ngươi và ngoạm móng vuốt vào cổ há»ng ngươi trước khi ngươi " "kịp rút kiếm. \"Cuá»™c sống cá»§a ngươi là cá»§a ta,\" nó nói. \"Ta sẽ bán lại cho " "ngươi vá»›i giá %{count} vàng.\"" msgid "" "Upon defeating the daemon's servants, you find a hidden cache with %{count} " "gold." msgstr "" "Sau khi đánh bại những ngưá»i hầu cá»§a quá»·, ngươi sẽ tìm thấy má»™t bá»™ đệm ẩn " "chứa %{count} vàng." msgid "" "As you enter the Alchemist's Tower, a hobbled, graying man in a brown cloak " "makes his way towards you." msgstr "" "Khi ngươi bước vào Tháp Nhà giả kim, má»™t ngưá»i đàn ông xám xịt, tập tá»…nh mặc " "áo choàng màu nâu tiến vá» phía ngươi." msgid "He checks your pack, and sees that you have 1 cursed item." msgid_plural "" "He checks your pack, and sees that you have %{count} cursed items." msgstr[0] "" "Anh ta kiểm tra túi cá»§a ngươi và thấy rằng ngươi có 1 vật phẩm bị nguyá»n rá»§a." msgid "For %{gold} gold, the alchemist will remove it for you. Do you pay?" msgid_plural "" "For %{gold} gold, the alchemist will remove them for you. Do you pay?" msgstr[0] "" "Vá»›i %{gold} vàng, nhà giả kim sẽ loại bá» nó cho ngươi. Ngươi có trả tiá»n " "không?" msgid "" "After you consent to pay the requested amount of gold, the alchemist grabs " "the cursed artifact and throws it into his magical cauldron." msgid_plural "" "After you consent to pay the requested amount of gold, the alchemist grabs " "all cursed artifacts and throws them into his magical cauldron." msgstr[0] "" "Sau khi ngươi đồng ý trả số vàng được yêu cầu, nhà giả kim lấy cổ vật bị " "nguyá»n rá»§a và ném nó vào chiếc vạc ma thuật cá»§a mình." msgid "" "You hear a voice from behind the locked door, \"You don't have enough gold " "to pay for my services.\"" msgstr "" "Ngươi nghe thấy má»™t giá»ng nói từ phía sau cánh cá»­a bị khóa, \"Ngươi không có " "đủ vàng để trả cho dịch vụ cá»§a ta.\"" msgid "" "You hear a voice from high above in the tower, \"Go away! I can't help you!\"" msgstr "" "Ngươi nghe thấy má»™t giá»ng nói từ trên cao trong tòa tháp, \"Biến Ä‘i! Ta " "không thể giúp ngươi!\"" msgid "" "The head groom speaks to you, \"That is a fine looking horse you have. I am " "afraid we can give you no better, but the horses your cavalry are riding " "look to be of poor breeding stock. We have many trained war horses which " "would aid your riders greatly. I insist you take them.\"" msgstr "" "Trưởng nhóm đầy tá»› nói vá»›i ngươi, \"Äó là má»™t con ngá»±a đẹp mà ngài có. Tôi e " "rằng chúng tôi không thể cho ngài tốt hÆ¡n, nhưng những con ngá»±a mà kỵ binh " "cá»§a ngài Ä‘ang cưỡi có vẻ là giống kém chất lượng. Chúng tôi có nhiá»u ngá»±a " "chiến đã được huấn luyện để có thể sá»­ dụng được.\" hãy há»— trợ các tay Ä‘ua " "cá»§a ngươi rất nhiá»u. Ta yêu cầu ngài phải đưa há» Ä‘i.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, he will " "grow tired in a week. You must also let me give better horses to your " "mounted soldiers, their horses look shoddy and weak.\"" msgstr "" "Khi ngươi đến gần chuồng ngá»±a, trưởng nhóm đầy tá»› xuất hiện, dẫn theo má»™t " "con ngá»±a chiến trông rất đẹp mắt. \"Con chiến mã này sẽ giúp ngài di chuyển " "nhanh hÆ¡n. Than ôi, nó sẽ mệt má»i trong má»™t tuần nữa. Ngài cÅ©ng phải để ta " "tặng những con ngá»±a tốt hÆ¡n cho những ngưá»i lính cưỡi ngá»±a cá»§a ngài, ngá»±a " "cá»§a há» trông kém chất lượng và yếu á»›t.\"" msgid "" "The head groom approaches you and speaks, \"You already have a fine horse, " "and have no inexperienced cavalry which might make use of our trained war " "horses.\"" msgstr "" "Trưởng nhóm đầy tá»› đến gần ngươi và nói: \"Ngài đã có má»™t con ngá»±a tốt và " "không có kỵ binh thiếu kinh nghiệm nào có thể sá»­ dụng những con ngá»±a chiến " "đã được huấn luyện cá»§a chúng tôi.\"" msgid "" "As you approach the stables, the head groom appears, leading a fine looking " "war horse. \"This steed will help speed you in your travels. Alas, his " "endurance will wane with a lot of heavy riding, and you must return for a " "fresh mount in a week. We also have many fine war horses which could benefit " "mounted soldiers, but you have none we can help.\"" msgstr "" "Khi ngươi đến gần chuồng ngá»±a, trưởng nhóm đầy tá»› xuất hiện, dẫn theo má»™t " "con ngá»±a chiến trông rất đẹp mắt. “Con chiến mã này sẽ giúp ngài tăng tốc " "trong hành trình. Than ôi, sức chịu đựng cá»§a nó sẽ giảm Ä‘i sau khi cưỡi quá " "nhiá»u, và ngài phải quay lại để lấy má»™t con ngá»±a má»›i trong má»™t tuần. Chúng " "tôi cÅ©ng có nhiá»u ngá»±a chiến tốt có thể mang lại lợi ích cho những ngưá»i " "lính cưỡi ngá»±a, nhưng ngài không có gì chúng tôi có thể giúp được.\"" msgid "The Arena guards turn you away." msgstr "Những ngưá»i bảo vệ Äấu trưá»ng Ä‘uổi ngươi Ä‘i." msgid "" "You have your crew stop up their ears with wax before the sirens' eerie song " "has any chance of luring them to a watery grave." msgstr "" "Ngươi yêu cầu Ä‘oàn cá»§a mình bịt tai bằng sáp trước khi bài hát kỳ lạ cá»§a còi " "báo động có cÆ¡ há»™i dụ há» xuống má»™t ngôi má»™ đầy nước." msgid "" "As the sirens sing their eerie song, your small, determined army manages to " "overcome the urge to dive headlong into the sea." msgstr "" "Khi còi báo động hát bài hát kỳ lạ cá»§a chúng, đội quân nhá» bé nhưng đầy " "quyết tâm cá»§a ngươi đã vượt qua được mong muốn lao thẳng xuống biển." msgid "" "An eerie wailing song emanates from the sirens perched upon the rocks. Many " "of your crew fall under its spell, and dive into the water where they drown. " "You are now wiser for the visit, and gain %{exp} experience." msgstr "" "Má»™t bài hát than khóc kỳ lạ phát ra từ còi báo động đậu trên những tảng đá. " "Nhiá»u ngưá»i trong số thá»§y thá»§ Ä‘oàn cá»§a ngươi rÆ¡i vào bùa chú cá»§a nó và lao " "xuống nước và chết Ä‘uối. Bây giá» ngươi đã khôn ngoan hÆ¡n khi tham quan và " "nhận được %{exp} kinh nghiệm." msgid "" "In a dazzling display of daring, you break into the local jail and free the " "hero imprisoned there, who, in return, pledges loyalty to your cause." msgstr "" "Trong má»™t màn thể hiện táo bạo rá»±c rỡ, ngươi đột nhập vào nhà tù địa phương " "và giải thoát tướng bị giam giữ ở đó, ngưá»i này đổi lại sẽ cam kết trung " "thành vá»›i chính nghÄ©a cá»§a ngươi." msgid "" "You already have %{count} heroes, and regretfully must leave the prisoner in " "this jail to languish in agony for untold days." msgstr "" "Ngươi đã có %{count} tướng rồi, và thật đáng tiếc phải để tù nhân trong nhà " "tù này mòn má»i trong Ä‘au khổ không biết bao ngày." msgid "" "You enter a rickety hut and talk to the magician who lives there. He tells " "you of places near and far which may aid you in your journeys." msgstr "" "Ngươi bước vào má»™t túp lá»u á»p ẹp và nói chuyện vá»›i nhà ảo thuật sống ở đó. " "Anh ấy cho ngươi biết vá» những địa Ä‘iểm gần xa có thể há»— trợ ngươi trong " "cuá»™c hành trình." msgid "This eye seems to be intently studying its surroundings." msgstr "Con mắt này dưá»ng như Ä‘ang chăm chú nghiên cứu môi trưá»ng xung quanh." msgid "You come across a giant Sphinx. The Sphinx remains strangely quiet." msgstr "" "Ngươi bắt gặp má»™t tượng Nhân sư khổng lồ. Tượng Nhân Sư vẫn im lặng má»™t cách " "kỳ lạ." msgid "" "\"I have a riddle for you,\" the Sphinx says. \"Answer correctly, and you " "shall be rewarded. Answer incorrectly, and you shall be eaten. Do you accept " "the challenge?\"" msgstr "" "“Ta có má»™t câu đố dành cho ngươi,†Nhân sư nói. \"Trả lá»i đúng sẽ được khen " "thưởng. Trả lá»i sai sẽ bị ăn thịt. Ngươi có chấp nhận thá»­ thách không?\"" #, fuzzy msgid "" "The Sphinx asks you the following riddle:\n" "\n" "'" msgstr "" "Nhân sư há»i ngươi câu đố sau:\n" " \n" "'%{riddle}'\n" " \n" "Câu trả lá»i cá»§a ngươi?" msgid "" "sphinx|'\n" "\n" "Your answer?" msgstr "" msgid "" "\"You guessed incorrectly,\" the Sphinx says, smiling. The Sphinx swipes at " "you with a paw, knocking you to the ground. Another blow makes the world go " "black, and you know no more." msgstr "" "\"Ngươi Ä‘oán sai rồi,\" Nhân sư mỉm cưá»i nói. Nhân sư dùng chân quẹt vào " "ngươi, khiến ngươi ngã xuống đất. Má»™t cú đánh nữa khiến thế giá»›i trở nên Ä‘en " "tối và ngươi không còn biết gì nữa." msgid "" "Looking somewhat disappointed, the Sphinx sighs. \"You've answered my riddle " "so here's your reward. Now begone.\"" msgstr "" "Trông có vẻ thất vá»ng, Nhân sư thở dài. \"Ngươi đã trả lá»i câu đố cá»§a tôi " "nên đây là phần thưởng cá»§a ngươi. Bây giá» hãy biến Ä‘i.\"" msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "As you speak the magic word, the glowing barrier dissolves into nothingness." msgstr "" "Má»™t rào cản ma thuật sừng sững trước mặt ngươi, chặn đưá»ng ngươi. Chữ trên " "vòm Ä‘á»c,\n" "\"Nói chìa khóa và ngươi có thể vượt qua.\"\n" "Khi ngươi nói từ ma thuật, rào cản phát sáng sẽ tan biến vào hư vô." msgid "" "A magical barrier stands tall before you, blocking your way. Runes on the " "arch read,\n" "\"Speak the key and you may pass.\"\n" "You speak, and nothing happens." msgstr "" "Má»™t rào cản ma thuật sừng sững trước mặt ngươi, chặn đưá»ng ngươi. Chữ trên " "vòm Ä‘á»c,\n" "\"Nói chìa khóa và ngươi có thể vượt qua.\"\n" "Ngươi trả lá»i, nhưng không có gì xảy ra." msgid "" "You enter the tent and see an old woman gazing into a magic gem. She looks " "up and says,\n" "\"In my travels, I have learned much in the way of arcane magic. A great " "oracle taught me his skill. I have the answer you seek.\"" msgstr "" "Ngươi bước vào lá»u và thấy má»™t bà già Ä‘ang nhìn chăm chú vào má»™t viên ngá»c " "ma thuật. Cô ấy nhìn lên và nói:\n" "\"Trong những chuyến Ä‘i cá»§a mình, tôi đã há»c được nhiá»u Ä‘iá»u vá» phép thuật " "phức tạp. Má»™t nhà tiên tri vÄ© đại đã dạy tôi kỹ năng cá»§a ông ấy. Ta có câu " "trả lá»i mà ngươi Ä‘ang tìm kiếm.\"" msgid "No spell book is present." msgstr "Không có cuốn sách thần chú nào hiện diện." msgid "" "This spell costs %{mana} spell points. You have no spell points, so you " "cannot cast it." msgstr "" "Phép thuật này tiêu tốn %{mana} Ä‘iểm phép thuật. Ngươi không có Ä‘iểm phép " "thuật nên không thể sá»­ dụng nó." msgid "" "This spell costs %{mana} spell points. You only have %{point} spell points, " "so you cannot cast it." msgstr "" "Phép thuật này tiêu tốn %{mana} Ä‘iểm phép thuật. Ngươi chỉ có %{point} Ä‘iểm " "phép thuật nên không thể sá»­ dụng nó." msgid "The spell was not found." msgstr "Không tìm thấy phép." msgid "Only heroes can cast this spell." msgstr "Chỉ có tướng má»›i có thể niệm phép này." msgid "This hero is not able to cast adventure spells." msgstr "Tướng này không thể sá»­ dụng phép thuật phiêu lưu." msgid "Your hero is too tired to cast this spell today. Try again tomorrow." msgstr "" "Tướng cá»§a ngươi đã quá mệt má»i để sá»­ dụng câu thần chú này ngày hôm nay. Hãy " "thá»­ lại vào ngày mai." msgid "This spell cannot be cast on a boat." msgstr "Phép này không thể dùng trên thuyá»n." msgid "This spell can only be cast near an ocean." msgstr "Phép này chỉ sá»­ dụng nÆ¡i gần đại dương." msgid "" "There are no boats available and no ocean adjacent to the hero where this " "spell will work." msgstr "" "Không có sẵn thuyá»n và không có đại dương gần tướng nÆ¡i phép thuật này sẽ " "hoạt động." msgid "There are no boats available for this spell." msgstr "Không có thuyá»n nào hiện hữu để cho phép này." msgid "There is no ocean adjacent to the hero where this spell will work." msgstr "Không có đại dương nào gần tướng để cho phép này thá»±c hiện." msgid "" "You do not own any town or castle that is not currently occupied by a hero. " "This spell will have no effect." msgstr "" "Ngươi không sở hữu bất kỳ thị trấn hoặc lâu đài nào hiện không có tướng " "chiếm giữ. Phép thuật này sẽ không có tác dụng." msgid "This hero is already in a town, so this spell will have no effect." msgstr "Tướng này đã ở trong thị trấn, nên phép này sẽ không có tác dụng." msgid "" "The nearest town is %{town}.\n" "\n" "This town is occupied by your hero %{hero}." msgstr "" "Thị trấn gần nhất là %{town}.\n" " \n" "Thị trấn này đã bị tướng %{hero} cá»§a ngươi chiếm đóng." msgid "This spell is already in effect." msgstr "Phép này đã có tác dụng rồi." msgid "" "No opponent neither has nor can have any hero under their command anymore. " "Casting this spell will have no effect." msgstr "" "Không có đối thá»§ nào có và không thể có bất kỳ anh hùng nào dưới sá»± chỉ huy " "cá»§a há» nữa. Sá»­ dụng phép thuật này sẽ không có tác dụng." msgid "" "No opponent has a hero under their command at this time. Casting this spell " "will have no effect." msgstr "" "Không có đối thá»§ nào có anh hùng dưới sá»± chỉ huy cá»§a há» vào thá»i Ä‘iểm này. " "Sá»­ dụng phép thuật này sẽ không có tác dụng." msgid "" "You must be within %{count} spaces of a monster for the Visions spell to " "work." msgstr "" "Ngươi phải ở trong khoảng cách %{count} cá»§a má»™t con quái vật để phép thuật " "Thấu thị hoạt động." msgid "" "You must be standing on the entrance to a mine (sawmills and alchemist labs " "do not count) to cast this spell." msgstr "" "Ngươi phải đứng ở lối vào má» (không tính xưởng cưa và phòng thí nghiệm cá»§a " "nhà giả kim) để thá»±c hiện phép thuật này." msgid "You must first defeat the ghosts guarding the mine to cast this spell." msgstr "" "Trước tiên, ngươi phải đánh bại những con ma canh giữ mỠđể sá»­ dụng phép " "thuật này." msgid "" "There are already at least as many elementals guarding the mine as this hero " "can generate. Casting this spell will have no effect." msgstr "" "Äã có ít nhất số lượng nguyên tố bảo vệ khu má» mà tướng này có thể tạo ra. " "Sá»­ dụng phép thuật này sẽ không có tác dụng." msgid "%{name} the %{race} (Level %{level})" msgstr "%{name} chá»§ng tá»™c %{race} (Cấp %{level})" #, fuzzy msgid "Random hero (Level %{level})" msgstr "%{name} (Cấp độ %{level})" #, fuzzy msgid "Random %{race} hero (Level %{level})" msgstr "%{name} chá»§ng tá»™c %{race} (Cấp %{level})" #, fuzzy msgid "Hero race:" msgstr "Màn hình Tướng" msgid "Are you sure you want to dismiss this Hero?" msgstr "Ngươi có chắc chắn muốn giải tán Tướng này không?" msgid "Set custom Experience value. Current value is default." msgstr "" msgid "Change Experience value. Right-click to reset to default value." msgstr "" msgid "View Experience Info" msgstr "Xem Thông tin Kinh nghiệm" msgid "Set custom Spell Points value. Current value is default." msgstr "" msgid "Change Spell Points value. Right-click to reset to default value." msgstr "" #, fuzzy msgid "Set Spell Points value" msgstr "Äiểm Phép thuật" msgid "View Spell Points Info" msgstr "Xem Thông tin Äiểm Phép thuật" msgid "Set patrol radius in tiles" msgstr "" #, fuzzy msgid "Enter hero's name" msgstr "Mất tướng: %{name}." #, fuzzy msgid "Click to change race." msgstr "Nhấp để xem thị trấn sau." #, fuzzy msgid "" "'Spread' combat formation spreads the hero's units from the top to the " "bottom of the battlefield, with at least one empty space between each unit." msgstr "" "Äá»™i hình chiến đấu 'Dàn trải' dàn quân cá»§a ngươi từ trên xuống dưới cá»§a " "chiến trưá»ng, vá»›i ít nhất má»™t khoảng trống giữa má»—i quân." #, fuzzy msgid "" "'Grouped' combat formation bunches the hero's army together in the center of " "their side of the battlefield." msgstr "" "Äá»™i hình chiến đấu 'Tập trung' tập hợp quân đội cá»§a ngươi lại vá»›i nhau ở " "trung tâm cá»§a phe ngươi trên chiến trưá»ng." msgid "Exit Hero Screen" msgstr "Thoát Màn hình Tướng" msgid "You cannot dismiss a hero in a castle" msgstr "Ngươi không thể giải tán má»™t tướng bên trong má»™t lâu đài" msgid "Dismissal of %{name} the %{race} is prohibited by scenario" msgstr "Giải tán %{name} chá»§ng tá»™c %{race} bị cấm theo kịch bản" msgid "Dismiss %{name} the %{race}" msgstr "Giải tán %{name} chá»§ng tá»™c %{race}" msgid "Show previous hero" msgstr "Xem tướng trước" msgid "Show next hero" msgstr "Xem tướng sau" msgid "Set army combat formation to 'Spread'" msgstr "Äặt đội hình chiến đấu cá»§a quân đội thành 'Dàn trải'" msgid "Set army combat formation to 'Grouped'" msgstr "Äặt đội hình chiến đấu cá»§a quân đội thành 'Tập trung'" msgid "Set hero's Artifacts. Right-click to reset Artifact." msgstr "" msgid "Set hero's Secondary Skills. Right-click to reset skill." msgstr "" msgid "Set hero's Army. Right-click to reset unit." msgstr "" msgid "Set hero's portrait. Right-click to reset to default." msgstr "" msgid "Click to change hero's name. Right-click to reset to default." msgstr "" msgid "Hero is in patrol mode in %{tiles} tiles radius. Click to disable it." msgstr "" #, fuzzy msgid "Click to enable hero's patrol mode." msgstr "Nhấp để chá»n màu này." msgid "Blood Morale" msgstr "Tinh thần Máu lá»­a" msgid "%{morale} Morale" msgstr "%{morale} Tinh thần" msgid "%{luck} Luck" msgstr "%{luck} May mắn" msgid "Current Luck Modifiers:" msgstr "Sá»­a đổi May mắn Hiện tại:" msgid "Current Morale Modifiers:" msgstr "Sá»­a đổi Tinh thần Hiện tại:" msgid "Entire army is undead, so morale does not apply." msgstr "Toàn bá»™ quân đội là xác sống, vì vậy tinh thần không có tác dụng." msgid "" "Current experience %{exp1}.\n" " Next level %{exp2}." msgstr "" "Kinh nghiệm hiện có %{exp1}.\n" " Cấp tiếp theo %{exp2}." msgid "million|M" msgstr "" msgid "Level %{level}" msgstr "Cấp bậc %{level}" #, fuzzy msgid "" "%{name} currently has %{point} spell points out of a maximum of %{max}. The " "maximum number of spell points is 10 times the hero's knowledge. It is " "occasionally possible for the hero to have more than their maximum spell " "points via special events." msgstr "" "%{name} hiện có %{point} Ä‘iểm phép thuật trong tổng số Ä‘iểm tối Ä‘a là " "%{max}. Số Ä‘iểm phép thuật tối Ä‘a gấp 10 lần kiến thức cá»§a ngươi. Äôi khi " "ngươi có thể nhận được nhiá»u hÆ¡n Ä‘iểm phép thuật tối Ä‘a thông qua các sá»± " "kiện đặc biệt." msgid "%{name1} meets %{name2}" msgstr "%{name1} gặp %{name2}" msgid "Enemy heroes are now fully identifiable." msgstr "Tướng địch bây giỠđã có thể nhận dạng đầy đủ." msgid "Identify Hero" msgstr "Nhận dạng Tướng" msgid "Select town to port to." msgstr "Chá»n thị trấn để dịch chuyển tá»›i." msgid "Town Portal" msgstr "Hồi Thành" msgid "The creatures are willing to join us!" msgstr "Sinh vật này sẽ tham gia cùng ta!" msgid "All the creatures will join us..." msgstr "Tất cả các sinh vật sẽ tham gia cùng ta..." msgid "The creature will join us..." msgid_plural "%{count} of the creatures will join us..." msgstr[0] "Sinh vật sẽ tham gia cùng ta..." msgid "" "\n" " for a fee of %{gold} gold." msgstr "" "\n" " vá»›i chi phí %{gold} vàng." msgid "These weak creatures will surely flee before us." msgstr "Những sinh vật yếu Ä‘uối này chắc chắn sẽ chạy trốn trước chúng ta." msgid "I fear these creatures are in the mood for a fight." msgstr "Tôi e rằng những sinh vật này Ä‘ang có tâm trạng muốn đánh nhau." #, fuzzy msgid "The hero's attack skill is a bonus added to each unit's attack skill." msgstr "" "Kỹ năng tấn công cá»§a ngươi là phần thưởng được thêm vào kỹ năng tấn công cá»§a " "má»—i sinh vật." #, fuzzy msgid "The hero's defense skill is a bonus added to each unit's defense skill." msgstr "" "Kỹ năng phòng thá»§ cá»§a ngươi là phần thưởng được thêm vào kỹ năng phòng thá»§ " "cá»§a má»—i sinh vật." #, fuzzy msgid "The hero's spell power determines the duration or power of a spell." msgstr "" "Sức mạnh phép thuật cá»§a ngươi quyết định độ dài hoặc sức mạnh cá»§a má»™t câu " "thần chú." #, fuzzy msgid "" "The hero's knowledge determines how many spell points the hero may have. " "Under normal circumstances, a hero is limited to 10 spell points per level " "of knowledge." msgstr "" "Kiến thức cá»§a ngươi quyết định số Ä‘iểm phép thuật mà tướng cá»§a ngươi có thể " "có. Trong trưá»ng hợp bình thưá»ng, má»™t tướng bị giá»›i hạn 10 Ä‘iểm phép thuật " "cho má»—i cấp độ kiến thức." msgid "Current Modifiers:" msgstr "Sá»­a đổi Hiện tại:" msgid "skill|Basic" msgstr "CÆ¡ bản" msgid "skill|Advanced" msgstr "Nâng cao" msgid "skill|Expert" msgstr "Chuyên gia" msgid "Pathfinding" msgstr "Tìm đưá»ng" msgid "Archery" msgstr "Bắn cung" msgid "Logistics" msgstr "Vận chuyển" msgid "Scouting" msgstr "Do thám" msgid "Diplomacy" msgstr "Ngoại giao" msgid "Navigation" msgstr "Dẫn đưá»ng" msgid "Leadership" msgstr "Lãnh đạo" msgid "Wisdom" msgstr "Thông thái" msgid "Mysticism" msgstr "Thần bí" msgid "Ballistics" msgstr "Máy bắn đá" msgid "Eagle Eye" msgstr "Mắt Äại bàng" msgid "Necromancy" msgstr "Chiêu hồn" msgid "Estates" msgstr "Tài sản" msgid "Advanced Archery" msgstr "Nâng cao Bắn cung" msgid "Advanced Pathfinding" msgstr "Nâng cao Tìm đưá»ng" msgid "Basic Archery" msgstr "CÆ¡ bản Bắn cung" msgid "Basic Pathfinding" msgstr "CÆ¡ bản Tìm đưá»ng" msgid "Expert Pathfinding" msgstr "Chuyên gia Tìm đưá»ng" msgid "Advanced Logistics" msgstr "Nâng cao Vận chuyển" msgid "Basic Logistics" msgstr "CÆ¡ bản Vận chuyển" msgid "Basic Scouting" msgstr "CÆ¡ bản Do thám" msgid "Expert Archery" msgstr "Chuyên gia Bắn cung" msgid "Expert Logistics" msgstr "Chuyên gia Vận chuyển" msgid "Advanced Diplomacy" msgstr "Nâng cao Ngoại giao" msgid "Advanced Scouting" msgstr "Nâng cao Do thám" msgid "Basic Diplomacy" msgstr "CÆ¡ bản Ngoại giao" msgid "Expert Diplomacy" msgstr "Chuyên gia Ngoại giao" msgid "Expert Scouting" msgstr "Chuyên gia Do thám" msgid "Advanced Leadership" msgstr "Nâng cao Lãnh đạo" msgid "Advanced Navigation" msgstr "Nâng cao Dẫn đưá»ng" msgid "Basic Leadership" msgstr "CÆ¡ bản Lãnh đạo" msgid "Basic Navigation" msgstr "CÆ¡ bản Dẫn đưá»ng" msgid "Expert Navigation" msgstr "Chuyên gia Dẫn đưá»ng" msgid "Advanced Wisdom" msgstr "Nâng cao Thông thái" msgid "Basic Mysticism" msgstr "CÆ¡ bản Thần bí" msgid "Basic Wisdom" msgstr "CÆ¡ bản Thông thái" msgid "Expert Leadership" msgstr "Chuyên gia Lãnh đạo" msgid "Expert Wisdom" msgstr "Chuyên gia Thông thái" msgid "Advanced Luck" msgstr "Nâng cao May mắn" msgid "Advanced Mysticism" msgstr "Nâng cao Thần bí" msgid "Basic Luck" msgstr "CÆ¡ bản May mắn" msgid "Expert Luck" msgstr "Chuyên gia May mắn" msgid "Expert Mysticism" msgstr "Chuyên gia Thần bí" msgid "Advanced Ballistics" msgstr "Nâng cao Máy bắn đá" msgid "Advanced Eagle Eye" msgstr "Nâng cao Mắt Äại bàng" msgid "Basic Ballistics" msgstr "CÆ¡ bản Máy bắn đá" msgid "Basic Eagle Eye" msgstr "CÆ¡ bản Mắt Äại bàng" msgid "Expert Ballistics" msgstr "Chuyên gia Máy bắn đá" msgid "Advanced Necromancy" msgstr "Nâng cao Chiêu hồn" msgid "Basic Estates" msgstr "CÆ¡ bản Tài sàn" msgid "Basic Necromancy" msgstr "CÆ¡ bản Chiêu hồn" msgid "Expert Eagle Eye" msgstr "Chuyên gia Mắt Äại bàng" msgid "Expert Necromancy" msgstr "Chuyên gia Chiêu hồn" msgid "Advanced Estates" msgstr "Nâng cao Tài sản" msgid "Expert Estates" msgstr "Chuyên gia Tài sản" msgid "" "%{skill} reduces the movement penalty for rough terrain by %{count} percent." msgstr "" "%{skill} giảm hình phạt di chuyển đối vá»›i địa hình gồ ghá» %{count} phần trăm." msgid "%{skill} eliminates the movement penalty for rough terrain." msgstr "%{skill} loại bá» hình phạt di chuyển đối vá»›i địa hình gồ ghá»." #, fuzzy msgid "" "%{skill} increases the damage done by the hero's range attacking creatures " "by %{count} percent, and eliminates the %{penalty} percent penalty when " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} loại bá» hình phạt %{count} phần trăm đối vá»›i quân cá»§a ngươi bắn qua " "chướng ngại vật (ví dụ: tưá»ng lâu đài)." #, fuzzy msgid "%{skill} increases the hero's movement points by %{count} percent." msgstr "" "%{skill} tăng Ä‘iểm di chuyển cá»§a anh hùng cá»§a ngươi thêm %{count} phần trăm." #, fuzzy msgid "%{skill} increases the hero's viewable area by one square." msgid_plural "%{skill} increases the hero's viewable area by %{count} squares." msgstr[0] "" "%{skill} tăng diện tích có thể xem cá»§a tướng cá»§a ngươi thêm má»™t ô vuông." #, fuzzy msgid "" "%{skill} allows the hero to negotiate with monsters who are weaker than " "their army, and reduces the cost of surrender." msgstr "" "%{skill} cho phép ngươi đàm phán vá»›i những quái vật yếu hÆ¡n nhóm cá»§a ngươi. " #, fuzzy msgid "" "Approximately %{count} percent of the creatures may offer to join the hero." msgstr "Khoảng %{count} phần trăm sinh vật có thể đỠnghị tham gia cùng ngươi." #, fuzzy msgid "All of the creatures may offer to join the hero." msgstr "Tất cả các sinh vật có thể đỠnghị tham gia cùng ngươi." #, fuzzy msgid "" "The cost of surrender is reduced to %{percent} percent of the total cost of " "troops in the army." msgstr "" "%{name} giảm chi phí đầu hàng xuống %{count} phần trăm tổng chi phí quân đội " "ngươi có trong quân đội cá»§a mình." #, fuzzy msgid "" "%{skill} increases the hero's movement points over water by %{count} percent." msgstr "" "%{skill} tăng Ä‘iểm di chuyển cá»§a anh hùng trên mặt nước thêm %{count} phần " "trăm." #, fuzzy msgid "%{skill} increases the hero's troops morale by %{count}." msgstr "%{skill} tăng tinh thần quân đội cá»§a tướng cá»§a ngươi lên %{count}." #, fuzzy msgid "%{skill} allows the hero to learn third level spells." msgstr "%{skill} cho phép tướng cá»§a ngươi há»c các phép thuật cấp ba." #, fuzzy msgid "%{skill} allows the hero to learn fourth level spells." msgstr "%{skill} cho phép tướng cá»§a ngươi há»c các phép thuật cấp bốn." #, fuzzy msgid "%{skill} allows the hero to learn fifth level spells." msgstr "%{skill} cho phép tướng cá»§a ngươi há»c các phép thuật cấp năm." #, fuzzy msgid "%{skill} regenerates one additional spell point per day to the hero." msgid_plural "" "%{skill} regenerates %{count} additional spell points per day to the hero." msgstr[0] "" "%{skill} tái tạo thêm má»™t Ä‘iểm phép thuật má»—i ngày cho tướng cá»§a ngươi." #, fuzzy msgid "%{skill} increases the hero's luck by %{count}." msgstr "%{skill} tăng may mắn cho tướng cá»§a ngươi thêm %{count}." #, fuzzy msgid "" "%{skill} gives the hero's catapult shots a greater chance to hit and do " "damage to castle walls." msgstr "" "%{skill} giúp các cú bắn bằng máy bắn đá cá»§a tướng cá»§a ngươi có cÆ¡ há»™i trúng " "đích cao hÆ¡n và gây sát thương lên tưá»ng lâu đài." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot has a " "greater chance to hit and do damage to castle walls." msgstr "" "%{skill} giúp máy bắn đá cá»§a tướng cá»§a ngươi có thêm má»™t phát bắn và má»—i " "phát bắn có cÆ¡ há»™i trúng đích và gây sát thương lên tưá»ng lâu đài cao hÆ¡n." #, fuzzy msgid "" "%{skill} gives the hero's catapult an extra shot, and each shot " "automatically destroys any wall, except a fortified wall in a Knight castle." msgstr "" "%{skill} cung cấp thêm cho máy bắn đá cá»§a tướng cá»§a ngươi má»™t phát bắn và " "má»—i phát bắn sẽ tá»± động phá há»§y bất kỳ bức tưá»ng nào, ngoại trừ bức tưá»ng " "kiên cố trong lâu đài Hiệp sÄ©." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 1st or " "2nd level spell that was cast by an enemy during combat." msgstr "" "%{skill} mang lại cho tướng cá»§a ngươi %{count} phần trăm cÆ¡ há»™i há»c bất kỳ " "phép thuật cấp 1 hoặc cấp 2 được sá»­ dụng bởi kẻ thù trong trận chiến." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 3rd " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} mang lại cho tướng cá»§a ngươi %{count} phần trăm cÆ¡ há»™i há»c bất kỳ " "phép thuật cấp 3 (hoặc thấp hÆ¡n) được sá»­ dụng bởi kẻ thù trong trận chiến." #, fuzzy msgid "" "%{skill} gives the hero a %{count} percent chance to learn any given 4th " "level spell (or below) that was cast by an enemy during combat." msgstr "" "%{skill} mang lại cho tướng cá»§a ngươi %{count} phần trăm cÆ¡ há»™i há»c bất kỳ " "phép thuật cấp 4 (hoặc thấp hÆ¡n) được sá»­ dụng bởi kẻ thù trong trận chiến." msgid "" "%{skill} allows %{count} percent of the creatures killed in combat to be " "brought back from the dead as Skeletons." msgstr "" "%{skill} cho phép %{count} phần trăm sinh vật bị giết trong trận chiến được " "hồi sinh từ cõi chết dưới dạng Bá»™ xương." #, fuzzy msgid "" "The hero produces %{count} gold pieces per day as tax revenue from estates." msgstr "" "Tướng cá»§a ngươi tạo ra %{count} miếng vàng má»—i ngày dưới dạng doanh thu thuế " "từ tài sản." msgid "Blue" msgstr "Lục" msgid "Green" msgstr "Xanh" msgid "Red" msgstr "Äá»" msgid "Yellow" msgstr "Vàng" msgid "Orange" msgstr "Cam" msgid "Purple" msgstr "Tím" msgid "barrier|Aqua" msgstr "Nước biển" msgid "barrier|Blue" msgstr "Lục" msgid "barrier|Brown" msgstr "Nâu" msgid "barrier|Gold" msgstr "Vàng" msgid "barrier|Green" msgstr "Xanh" msgid "barrier|Orange" msgstr "Cam" msgid "barrier|Purple" msgstr "Tím" msgid "barrier|Red" msgstr "Äá»" msgid "tent|Aqua" msgstr "Nước biển" msgid "tent|Blue" msgstr "Lục" msgid "tent|Brown" msgstr "Nâu" msgid "tent|Gold" msgstr "Vàng" msgid "tent|Green" msgstr "Xanh" msgid "tent|Orange" msgstr "Cam" msgid "tent|Purple" msgstr "Tím" msgid "tent|Red" msgstr "Äá»" msgid "Experience" msgstr "Kinh nghiệm" #, fuzzy msgid "" "Experience allows your heroes to gain levels, increasing their primary and " "secondary skills." msgstr "" "Kinh nghiệm cho phép các tướng cá»§a ngươi tăng cấp, tăng các kỹ năng chính và " "phụ." msgid "Hero/Stats" msgstr "Tướng/Tình trạng" msgid "Skills" msgstr "KÄ© năng" msgid "Town/Castle" msgstr "Thị trấn/Lâu đài" msgid "Garrison" msgstr "Äồn trú" msgid "Gold Per Day:" msgstr "Vàng Má»—i Ngày:" msgid "View Heroes." msgstr "Xem Tướng." msgid "Towns/Castles" msgstr "Thị trấn/Lâu đài" msgid "View Towns and Castles." msgstr "Xem Thị trấn và Lâu đài." msgid "luck|Cursed" msgstr "Nguyá»n rá»§a" msgid "luck|Awful" msgstr "Tồi tệ" msgid "luck|Bad" msgstr "Xấu" msgid "luck|Normal" msgstr "Thưá»ng" msgid "luck|Good" msgstr "Tốt" msgid "luck|Great" msgstr "Tuyệt" msgid "luck|Irish" msgstr "" #, fuzzy msgid "" "Negative luck sometimes falls on the hero's units in combat, causing their " "attacks to only do half damage." msgstr "" "Vận rá»§i đôi khi rÆ¡i vào quân đội cá»§a ngươi trong chiến đấu, khiến đòn tấn " "công cá»§a há» chỉ gây sát thương má»™t ná»­a." #, fuzzy msgid "" "Neutral luck means the hero's units will never get lucky or unlucky attacks " "on the enemy." msgstr "" "May mắn trung tính có nghÄ©a là quân đội cá»§a ngươi sẽ không bao giá» gặp may " "mắn hoặc xui xẻo tấn công kẻ thù." #, fuzzy msgid "" "Positive luck sometimes lets the hero's units get lucky attacks (double " "strength) in combat." msgstr "" "May mắn tốt đôi khi giúp quân đội cá»§a ngươi nhận được những đòn tấn công may " "mắn (sức mạnh gấp đôi) trong chiến đấu." msgid "morale|Treason" msgstr "Phản bá»™i" msgid "morale|Awful" msgstr "Khá»§ng hoảng" msgid "morale|Poor" msgstr "Chán nản" msgid "morale|Normal" msgstr "Bình thưá»ng" msgid "morale|Good" msgstr "Rất tốt" msgid "morale|Great" msgstr "Tuyệt vá»i" msgid "morale|Blood!" msgstr "Máu chiến!" #, fuzzy msgid "Negative morale may cause the hero's units to freeze in combat." msgstr "" "Tinh thần tồi tệ có thể khiến quân đội cá»§a ngươi tê liệt trong chiến đấu." #, fuzzy msgid "" "Neutral morale means the hero's units will never be blessed with extra " "attacks or freeze in combat." msgstr "" "Tinh thần trung lập có nghÄ©a là quân đội cá»§a ngươi sẽ không bao giỠđược ban " "phước vá»›i các cuá»™c tấn công bổ sung hoặc đóng băng trong chiến đấu." #, fuzzy msgid "Positive morale may give the hero's units extra attacks in combat." msgstr "" "Tinh thần tốt có thể mang lại cho quân đội cá»§a ngươi nhiá»u đòn tấn công hÆ¡n " "trong chiến đấu." msgid "Knight" msgstr "Hiệp sÄ©" msgid "Barbarian" msgstr "Man rợ" msgid "Sorceress" msgstr "Phù thá»§y" msgid "Warlock" msgstr "Pháp sư" msgid "Wizard" msgstr "Thuật sÄ©" msgid "Necromancer" msgstr "Chiêu hồn" msgid "Multi" msgstr "Nhiá»u" msgid "doubleLined|Knight" msgstr "Hiệp sÄ©" msgid "doubleLined|Barbarian" msgstr "Man rợ" msgid "doubleLined|Sorceress" msgstr "Phù thá»§y" msgid "doubleLined|Warlock" msgstr "Pháp sư" msgid "doubleLined|Wizard" msgstr "Thuật sÄ©" msgid "" "doubleLined|Necro-\n" "mancer" msgstr "" "Chiêu\n" "hồn" msgid "doubleLinedRace|Multi" msgstr "Nhiá»u" msgid "doubleLinedRace|Random" msgstr "Ngẫu nhiên" msgid "speed|Standing" msgstr "Äứng" msgid "speed|Crawling" msgstr "Bò" msgid "speed|Very Slow" msgstr "Rất Chậm" msgid "speed|Slow" msgstr "Chậm" msgid "speed|Average" msgstr "Trung bình" msgid "speed|Fast" msgstr "Nhanh" msgid "speed|Very Fast" msgstr "Rất nhanh" msgid "speed|Ultra Fast" msgstr "Cá»±c nhanh" msgid "speed|Blazing" msgstr "Tốc độ" msgid "speed|Instant" msgstr "Tức thì" msgid "Click this button to adjust the level of zoom." msgstr "" msgid "Zoom" msgstr "" msgid "week|Squirrel" msgstr "Sóc" msgid "week|Rabbit" msgstr "Thá»" msgid "week|Gopher" msgstr "Chuá»™t túi" msgid "week|Badger" msgstr "Lá»­ng" msgid "week|Rat" msgstr "Chuá»™t" msgid "week|Eagle" msgstr "Äại bàng" msgid "week|Weasel" msgstr "Chồn" msgid "week|Raven" msgstr "Quạ" msgid "week|Mongoose" msgstr "Cầy" msgid "week|Dog" msgstr "Chó" msgid "week|Aardvark" msgstr "Lợn" msgid "week|Lizard" msgstr "Thằn lằn" msgid "week|Tortoise" msgstr "Rùa" msgid "week|Hedgehog" msgstr "Nhím" msgid "week|Condor" msgstr "Ưng" msgid "week|Ant" msgstr "Kiến" msgid "week|Grasshopper" msgstr "Cào cào" msgid "week|Dragonfly" msgstr "Chuồn chuồn" msgid "week|Spider" msgstr "Nhện" msgid "week|Butterfly" msgstr "Bướm" msgid "week|Bumblebee" msgstr "Ong vò vẽ" msgid "week|Locust" msgstr "Châu chấu" msgid "week|Earthworm" msgstr "Giun đất" msgid "week|Hornet" msgstr "Ong bắp cày" msgid "week|Beetle" msgstr "Bá»" msgid "week|PLAGUE" msgstr "DỊCH BỆNH" msgid "week|Unnamed" msgstr "Không tên" msgid "Desert" msgstr "Sa mạc" msgid "Snow" msgstr "Tuyết" msgid "Wasteland" msgstr "Äất hoang" msgid "Beach" msgstr "Biển" msgid "Lava" msgstr "Nham thạch" msgid "Dirt" msgstr "Bùn" msgid "Grass" msgstr "Cá»" msgid "Ocean" msgstr "Äại dương" msgid "maps|Small" msgstr "Nhá»" msgid "maps|Medium" msgstr "Trung" msgid "maps|Large" msgstr "Lá»›n" msgid "maps|Extra Large" msgstr "Rất Lá»›n" msgid "maps|Custom Size" msgstr "Kích thước Khác" msgid "Ore Mine" msgstr "Má» Äá" msgid "Sulfur Mine" msgstr "Má» Lưu huỳnh" msgid "Crystal Mine" msgstr "Má» Thạch anh" msgid "Gems Mine" msgstr "Má» Kim cương" msgid "Gold Mine" msgstr "Má» Vàng" msgid "Mine" msgstr "Má»" msgid "Burma shave." msgstr "" msgid "Next sign 50 miles." msgstr "Chỉ dẫn kế tiếp cách 50 dặm." msgid "See Rock City." msgstr "" msgid "This space for rent." msgstr "Chá»— này cho thuê." msgid "No object" msgstr "Không có gì" msgid "Alchemist Lab" msgstr "Phòng thí nghiệm Hóa" msgid "Sign" msgstr "Chỉ dẫn" msgid "Buoy" msgstr "Phao" msgid "Skeleton" msgstr "Xương" msgid "Daemon Cave" msgstr "Hang Quá»·" msgid "Treasure Chest" msgstr "Rương Báu vật" msgid "Faerie Ring" msgstr "Vòng Tiên" msgid "Campfire" msgstr "Lá»­a trại" msgid "Fountain" msgstr "Äài nước" msgid "Gazebo" msgstr "" msgid "Genie Lamp" msgstr "Äèn Thần" msgid "Archer's House" msgstr "Nhà Cung" msgid "Goblin Hut" msgstr "Lá»u Yêu tinh" msgid "Dwarf Cottage" msgstr "Nhà Ngưá»i lùn" msgid "Peasant Hut" msgstr "Lá»u Nông dân" msgid "Stables" msgstr "Chuồng ngá»±a" msgid "Alchemist's Tower" msgstr "Tháp Giả kim" msgid "Event" msgstr "Sá»± kiện" msgid "Dragon City" msgstr "Thành phố Rồng" msgid "Lighthouse" msgid_plural "Lighthouses" msgstr[0] "Hải đăng" msgid "Water Wheel" msgid_plural "Water Wheels" msgstr[0] "Bánh xe Nước" msgid "Monster" msgstr "Quái vật" msgid "Obelisk" msgstr "Äài tưởng niệm" msgid "Oasis" msgstr "á»c đảo" msgid "Resource" msgstr "Tài nguyên" msgid "Sawmill" msgstr "Xưởng cưa" msgid "Oracle" msgstr "Tiên tri" msgid "Shrine of the First Circle" msgstr "Äiện thá» Vòng Má»™t" msgid "Shipwreck" msgstr "Tàu đắm" msgid "Sea Chest" msgstr "Rương Biển" msgid "Desert Tent" msgstr "Lá»u Xa mạc" msgid "Stone Liths" msgstr "Äá Phiến" msgid "Wagon Camp" msgstr "Toa xe" msgid "Hut of the Magi" msgstr "Lá»u Pháp sư" msgid "Whirlpool" msgstr "Xoáy nước" msgid "Windmill" msgid_plural "Windmills" msgstr[0] "Cối xay gió" msgid "Mermaid" msgstr "Tiên cá" msgid "Boat" msgstr "Thuyá»n" msgid "Random Ultimate Artifact" msgstr "Ngẫu nhiên Bảo vật Tối thượng" msgid "Random Artifact" msgstr "Ngẫu nhiên Bảo vật" msgid "Random Resource" msgstr "Ngẫu nhiên Tài nguyên" msgid "Random Monster" msgstr "Ngẫu nhiên Quái vật" msgid "Random Town" msgstr "Ngẫu nhiên Thị trấn" msgid "Random Castle" msgstr "Ngẫu nhiên Lâu đài" msgid "Eye of the Magi" msgstr "Mắt cá»§a Pháp sư" msgid "Random Monster - weak" msgstr "Ngẫu nhiên Quái vật - yếu" msgid "Random Monster - medium" msgstr "Ngẫu nhiên Quái vật - thưá»ng" msgid "Random Monster - strong" msgstr "Ngẫu nhiên Quái vật - mạnh" msgid "Random Monster - very strong" msgstr "Ngẫu nhiên Quái vật - rất mạnh" #, fuzzy msgid "Hero" msgstr "Tướng" msgid "Nothing Special" msgstr "Không có gì Äặc biệt" msgid "Mossy Rock" msgstr "Äá Rêu" msgid "Watch Tower" msgstr "Tháp Canh" msgid "Tree House" msgstr "Nhà trên Cây" msgid "Tree City" msgstr "Thành Cây" msgid "Ruins" msgstr "Tàn tích" msgid "Fort" msgstr "Pháo đài" msgid "Abandoned Mine" msgstr "Má» hoang" msgid "Sirens" msgstr "Nhân ngư" msgid "Standing Stones" msgstr "Äá Äứng" msgid "Idol" msgstr "Thần tượng" msgid "Tree of Knowledge" msgstr "Cây Tri thức" msgid "Witch Doctor's Hut" msgstr "Lá»u Bác há»c" msgid "Temple" msgstr "Ngôi Ä‘á»n" msgid "Hill Fort" msgstr "Pháo đài Trên đồi" msgid "Halfling Hole" msgstr "" msgid "Mercenary Camp" msgstr "Trại Lính đánh thuê" msgid "Shrine of the Second Circle" msgstr "Äiện thá» Vòng thứ Hai" msgid "Shrine of the Third Circle" msgstr "Äiện thá» Vòng thứ Ba" msgid "City of the Dead" msgstr "Thành phố Chết" msgid "Sphinx" msgstr "Nhân sư" msgid "Wagon" msgstr "Toa xe" msgid "Tar Pit" msgstr "Hố Hắc ín" msgid "Artesian Spring" msgstr "Suối Nguồn" msgid "Troll Bridge" msgstr "" msgid "Watering Hole" msgstr "Hố Nước" msgid "Witch's Hut" msgstr "" msgid "Xanadu" msgstr "" msgid "Lean-To" msgstr "" msgid "Magellan's Maps" msgstr "Bản đồ Magellan" msgid "Flotsam" msgstr "Vật trôi nổi" msgid "Derelict Ship" msgstr "Tàu Hoang" msgid "Shipwreck Survivor" msgstr "Nạn nhân Tàu đắm" msgid "Bottle" msgstr "Chai" msgid "Magic Well" msgstr "Giếng Thần" msgid "Magic Garden" msgid_plural "Magic Gardens" msgstr[0] "Vưá»n Thần" msgid "Observation Tower" msgstr "Äài Quan sát" msgid "Freeman's Foundry" msgstr "" msgid "Reefs" msgstr "Äá ngầm" msgid "Volcano" msgstr "Núi lá»­a" msgid "Flowers" msgstr "Hoa" msgid "Rock" msgstr "Äá" msgid "Water Lake" msgstr "Hồ Nước" msgid "Mandrake" msgstr "Khoai ma" msgid "Dead Tree" msgstr "Cây khô" msgid "Stump" msgstr "Gốc cây" msgid "Crater" msgstr "Miệng núi lá»­a" msgid "Cactus" msgstr "Xương rồng" msgid "Mound" msgstr "Gò đất" msgid "Dune" msgstr "Äụn cát" msgid "Lava Pool" msgstr "VÅ©ng nham thạch" msgid "Shrub" msgstr "Cây bụi" msgid "Barrow Mounds" msgstr "" msgid "Random Artifact - Treasure" msgstr "Bảo vật Ngẫu nhiên - Châu báu" msgid "Random Artifact - Minor" msgstr "Bảo vật Ngẫu nhiên - Nhá»" msgid "Random Artifact - Major" msgstr "Bảo vật Ngẫu nhiên - Lá»›n" msgid "Barrier" msgstr "Rào chắn" msgid "Traveller's Tent" msgstr "Lá»u Du khách" msgid "Jail" msgstr "Ngục" msgid "Fire Summoning Altar" msgstr "Bàn thá» Triệu hồi Lá»­a" msgid "Air Summoning Altar" msgstr "Bàn thá» Triệu hồi Khí" msgid "Earth Summoning Altar" msgstr "Bàn thá» Triệu hồi Äất" msgid "Water Summoning Altar" msgstr "Bàn thá» Triệu hồi Nước" #, fuzzy msgid "Swampy Lake" msgstr "Äầm lầy" msgid "Frozen Lake" msgstr "" msgid "randomRace|level 1 creatures" msgstr "" msgid "randomRace|level 2 creatures" msgstr "" msgid "randomRace|level 3 creatures" msgstr "" msgid "randomRace|level 4 creatures" msgstr "" msgid "randomRace|level 5 creatures" msgstr "" msgid "randomRace|level 6 creatures" msgstr "" msgid "Unknown Monsters" msgstr "Quái vật Vô danh" msgid "Unknown Monster" msgstr "Quái vật Vô danh" msgid "Peasant" msgstr "Nông dân" msgid "Peasants" msgstr "Nông dân" msgid "Archer" msgstr "Cung thá»§" msgid "Archers" msgstr "Cung thá»§" msgid "Ranger" msgstr "Kỵ binh" msgid "Rangers" msgstr "Kỵ binh" msgid "Pikeman" msgstr "Thương thá»§" msgid "Pikemen" msgstr "Thương thá»§" msgid "Veteran Pikeman" msgstr "Thương thá»§ Kỳ cá»±u" msgid "Veteran Pikemen" msgstr "Thương thá»§ Kỳ cá»±u" msgid "Swordsman" msgstr "Kiếm thá»§" msgid "Swordsmen" msgstr "Kiếm thá»§" msgid "Master Swordsman" msgstr "Kiếm thá»§ Bậc thầy" msgid "Master Swordsmen" msgstr "Kiếm thá»§ Bậc thầy" msgid "Cavalries" msgstr "Kỵ mã" msgid "Cavalry" msgstr "Kỵ mã" msgid "Champion" msgstr "Kỵ mã Bậc thầy" msgid "Champions" msgstr "Kỵ mã Bậc thầy" msgid "Paladin" msgstr "Hiệp sÄ©" msgid "Paladins" msgstr "Hiệp sÄ©" msgid "Crusader" msgstr "Hiệp sÄ© thập tá»±" msgid "Crusaders" msgstr "Hiệp sÄ© thập tá»±" msgid "Goblin" msgstr "Yêu tinh" msgid "Goblins" msgstr "Yêu tinh" msgid "Orc" msgstr "" msgid "Orcs" msgstr "" msgid "Orc Chief" msgstr "" msgid "Orc Chiefs" msgstr "" msgid "Wolf" msgstr "Sói" msgid "Wolves" msgstr "Sói" msgid "Ogre" msgstr "" msgid "Ogres" msgstr "" msgid "Ogre Lord" msgstr "" msgid "Ogre Lords" msgstr "" msgid "Troll" msgstr "Quá»· lùn" msgid "Trolls" msgstr "Quá»· lùn" msgid "War Troll" msgstr "Quá»· lùn Chiến" msgid "War Trolls" msgstr "Quá»· lùn Chiến" msgid "Cyclopes" msgstr "Äá»™c nhãn" msgid "Cyclops" msgstr "Äá»™c nhãn" msgid "Sprite" msgstr "Ma tiên" msgid "Sprites" msgstr "Ma tiên" msgid "Dwarf" msgstr "Ngưá»i lùn" msgid "Dwarves" msgstr "Ngưá»i lùn" msgid "Battle Dwarf" msgstr "Ngưá»i lùn Chiến" msgid "Battle Dwarves" msgstr "Ngưá»i lùn Chiến" msgid "Elf" msgstr "Tiên" msgid "Elves" msgstr "Tiên" msgid "Grand Elf" msgstr "Tiên Äại" msgid "Grand Elves" msgstr "Tiên Äại" msgid "Druid" msgstr "Tu sÄ©" msgid "Druids" msgstr "Tu sÄ©" msgid "Greater Druid" msgstr "Tu sÄ© Cả" msgid "Greater Druids" msgstr "Tu sÄ© Cả" msgid "Unicorn" msgstr "Kỳ lân" msgid "Unicorns" msgstr "Kỳ lân" msgid "Phoenix" msgstr "Phượng hoàng" msgid "Phoenixes" msgstr "Phượng hoàng" msgid "Centaur" msgstr "Nhân mã" msgid "Centaurs" msgstr "Nhân mã" msgid "Gargoyle" msgstr "" msgid "Gargoyles" msgstr "" msgid "Griffin" msgstr "Chim ưng" msgid "Griffins" msgstr "Chim ưng" msgid "Minotaur" msgstr "Nhân ngưu" msgid "Minotaurs" msgstr "Nhân ngưu" msgid "Minotaur King" msgstr "Nhân ngưu Vua" msgid "Minotaur Kings" msgstr "Nhân ngưu Vua" msgid "Hydra" msgstr "" msgid "Hydras" msgstr "" msgid "Green Dragon" msgstr "Rồng Xanh" msgid "Green Dragons" msgstr "Rồng Xanh" msgid "Red Dragon" msgstr "Rồng Äá»" msgid "Red Dragons" msgstr "Rồng Äá»" msgid "Black Dragon" msgstr "Rồng Äen" msgid "Black Dragons" msgstr "Rồng Äen" msgid "Halfling" msgstr "" msgid "Halflings" msgstr "" msgid "Boar" msgstr "Lợn rừng" msgid "Boars" msgstr "Lợn rừng" msgid "Iron Golem" msgstr "Yêu tinh Sắt" msgid "Iron Golems" msgstr "Yêu tinh Sắt" msgid "Steel Golem" msgstr "Yêu tinh Thép" msgid "Steel Golems" msgstr "Yêu tinh Thép" msgid "Roc" msgstr "" msgid "Rocs" msgstr "" msgid "Mage" msgstr "" msgid "Magi" msgstr "" msgid "Archmage" msgstr "" msgid "Archmagi" msgstr "" msgid "Giant" msgstr "To lá»›n" msgid "Giants" msgstr "To lá»›n" msgid "Titan" msgstr "Khổng lồ" msgid "Titans" msgstr "Khổng lồ" msgid "Skeletons" msgstr "Xương" msgid "Zombie" msgstr "Thây ma" msgid "Zombies" msgstr "Thây ma" msgid "Mutant Zombie" msgstr "Thây ma Äá»™t biến" msgid "Mutant Zombies" msgstr "Thây ma Äá»™t biến" msgid "Mummies" msgstr "Xác ướp" msgid "Mummy" msgstr "Xác ướp" msgid "Royal Mummies" msgstr "Xác ướp Hoàng gia" msgid "Royal Mummy" msgstr "Xác ướp Hoàng gia" msgid "Vampire" msgstr "Ma cà rồng" msgid "Vampires" msgstr "Ma cà rồng" msgid "Vampire Lord" msgstr "Ma cà rồng Chúa" msgid "Vampire Lords" msgstr "Ma cà rồng Chúa" msgid "Lich" msgstr "" msgid "Liches" msgstr "" msgid "Power Lich" msgstr "" msgid "Power Liches" msgstr "" msgid "Bone Dragon" msgstr "Rồng Xương" msgid "Bone Dragons" msgstr "Rồng Xương" msgid "Rogue" msgstr "Lưu manh" msgid "Rogues" msgstr "Lưu manh" msgid "Nomad" msgstr "Du mục" msgid "Nomads" msgstr "Du mục" msgid "Ghost" msgstr "Ma" msgid "Ghosts" msgstr "Ma" msgid "Genie" msgstr "Thần đèn" msgid "Genies" msgstr "Thần đèn" msgid "Medusa" msgstr "" msgid "Medusas" msgstr "" msgid "Earth Elemental" msgstr "Nguyên tố Äất" msgid "Earth Elementals" msgstr "Nguyên tố Äất" msgid "Air Elemental" msgstr "Nguyên tố Khí" msgid "Air Elementals" msgstr "Nguyên tố Khí" msgid "Fire Elemental" msgstr "Nguyên tố Lá»­a" msgid "Fire Elementals" msgstr "Nguyên tố Lá»­a" msgid "Water Elemental" msgstr "Nguyên tố Nước" msgid "Water Elementals" msgstr "Nguyên tố Nước" msgid "Random Monsters" msgstr "Quái vật Ngẫu nhiên" msgid "Random Monster 1" msgstr "Quái vật Ngẫu nhiên 1" msgid "Random Monsters 1" msgstr "Quái vật Ngẫu nhiên 1" msgid "Random Monster 2" msgstr "Quái vật Ngẫu nhiên 2" msgid "Random Monsters 2" msgstr "Quái vật Ngẫu nhiên 2" msgid "Random Monster 3" msgstr "Quái vật Ngẫu nhiên 3" msgid "Random Monsters 3" msgstr "Quái vật Ngẫu nhiên 3" msgid "Random Monster 4" msgstr "Quái vật Ngẫu nhiên 4" msgid "Random Monsters 4" msgstr "Quái vật Ngẫu nhiên 4" msgid "Double shot" msgstr "Bắn đúp" msgid "2-hex monster" msgstr "quái 2 ô lục giác" msgid "Double strike" msgstr "Tấn công kép" msgid "Double damage to Undead" msgstr "Gấp đôi sát thương cho Bất tá»­" msgid "% magic resistance" msgstr "% kháng phép" msgid "Immune to Mind spells" msgstr "Kháng các phép Tâm trí" msgid "Immune to Elemental spells" msgstr "Kháng các phép Nguyên tố" msgid "Immune to Fire spells" msgstr "Kháng phép Lá»­a" msgid "Immune to Cold spells" msgstr "Kháng các phép Lạnh" msgid "Immune to " msgstr "Kháng phép " msgid "% immunity to %{spell} spell" msgstr "% kháng phép %{spell}" msgid "% damage from Elemental spells" msgstr "% sát thương vá»›i phép Nguyên tố" msgid "% damage from %{spell} spell" msgstr "% sát thương từ phép %{spell}" msgid "% chance to Dispel beneficial spells" msgstr "% cÆ¡ há»™i Xua tan các phép thuật có lợi" msgid "% chance to Paralyze" msgstr "% cÆ¡ há»™i bị Tê liêt" msgid "% chance to Petrify" msgstr "% cÆ¡ há»™i bị Hóa đá" msgid "% chance to Blind" msgstr "% cÆ¡ há»™i bị Mù" msgid "% chance to Curse" msgstr "% cÆ¡ há»™i bị Nguyá»n rá»§a" msgid "% chance to cast %{spell} spell" msgstr "% cÆ¡ há»™i niệm phép %{spell}" msgid "HP regeneration" msgstr "Hồi máu" msgid "Two hexes attack" msgstr "Tấn công 2 ô lục giác" msgid "Flyer" msgstr "Loài bay" msgid "Always retaliates" msgstr "Luôn phản đòn" msgid "Attacks all adjacent enemies" msgstr "Tấn công tất cả kẻ thù lân cận" msgid "No melee penalty" msgstr "Không bị phạt cận chiến" msgid "Dragon" msgstr "Rồng" msgid "Undead" msgstr "Bất tá»­" msgid "No enemy retaliation" msgstr "Không có sá»± phản đòn cá»§a kẻ thù" msgid "HP drain" msgstr "Hút máu" msgid "Cloud attack" msgstr "Tấn công trên mây" msgid "Decreases enemy's morale by " msgstr "Làm giảm tinh thần cá»§a kẻ thù " msgid "% chance to halve enemy" msgstr "% cÆ¡ há»™i giảm má»™t ná»­a kẻ địch" msgid "Soul Eater" msgstr "Kẻ ăn Linh hồn" msgid "Elemental" msgstr "Nguyên tố" msgid "No Morale" msgstr "Mất Tinh thần" #, fuzzy msgid "Earth creature" msgstr "Chiêu má»™ Quái" #, fuzzy msgid "Air creature" msgstr "Chiêu má»™ Quái" #, fuzzy msgid "Fire creature" msgstr "Chiêu má»™ Quái" #, fuzzy msgid "Water creature" msgstr "Hồ Nước" #, fuzzy msgid "Double damage from Fire spells" msgstr "200% sát thương từ phép Lá»­a" #, fuzzy msgid "Double damage from Cold spells" msgstr "200% sát thương từ phép Lạnh" #, fuzzy msgid "Double damage from Earth creatures" msgstr "Loại bá» tất cả các phép thuật từ tất cả các sinh vật." #, fuzzy msgid "Double damage from Air creatures" msgstr "Gấp đôi sát thương cho Bất tá»­" #, fuzzy msgid "Double damage from Fire creatures" msgstr "200% sát thương từ phép Lá»­a" #, fuzzy msgid "Double damage from Water creatures" msgstr "Loại bá» tất cả các phép thuật từ tất cả các sinh vật." msgid "Lightning" msgstr "Sét" msgid "% immunity to " msgstr "% kháng lại " msgid "% damage from " msgstr "% sát thương từ " msgid "The three Anduran artifacts magically combine into one." msgstr "Ba bảo vật Anduran kết hợp má»™t cách kỳ diệu thành má»™t." msgid "View Spells" msgstr "Xem Phép" msgid "View %{name} Info" msgstr "Xem Thông tin %{name}" msgid "Move %{name}" msgstr "Chuyển %{name}" msgid "Cannot move the Spellbook" msgstr "Không thể chuyển Sách phép" msgid "This item can't be traded." msgstr "Vật này không thể trao đổi." msgid "Invalid Artifact" msgstr "Bảo vật Không hợp lệ" #, fuzzy msgid "The %{name} increases the hero's knowledge by %{count}." msgstr "%{name} nâng cao kiến thức cá»§a ngươi thêm %{count}." msgid "Ultimate Book of Knowledge" msgstr "Sách Kiến thức Tối thượng" #, fuzzy msgid "The %{name} increases the hero's attack skill by %{count}." msgstr "%{name} tăng kỹ năng tấn công cá»§a ngươi thêm %{count}." msgid "Ultimate Sword of Dominion" msgstr "Kiếm Thống trị Tối thượng" #, fuzzy msgid "The %{name} increases the hero's defense skill by %{count}." msgstr "%{name} tăng kỹ năng phòng thá»§ cá»§a ngươi thêm %{count}." msgid "Ultimate Cloak of Protection" msgstr "Ão Bảo vệ Tối thượng" #, fuzzy msgid "The %{name} increases the hero's spell power by %{count}." msgstr "%{name} tăng sức mạnh phép thuật cá»§a ngươi thêm %{count}." msgid "Ultimate Wand of Magic" msgstr "ÄÅ©a Phép Tối thượng" #, fuzzy msgid "" "The %{name} increases the hero's attack and defense skills by %{count} each." msgstr "" "%{name} tăng kỹ năng tấn công và phòng thá»§ cá»§a ngươi thêm %{count} má»—i kỹ " "năng." msgid "Ultimate Shield" msgstr "Khiên Tối thượng" #, fuzzy msgid "" "The %{name} increases the hero's spell power and knowledge by %{count} each." msgstr "" "%{name} tăng sức mạnh phép thuật và kiến thức cá»§a ngươi thêm %{count} má»—i " "thứ." msgid "Ultimate Staff" msgstr "Quyá»n trượng Tối thượng" #, fuzzy msgid "" "The %{name} increases each of the hero's basic skills by %{count} points." msgstr "%{name} tăng má»—i kỹ năng cÆ¡ bản cá»§a ngươi thêm %{count} Ä‘iểm." msgid "Ultimate Crown" msgstr "Vương miện Tối thượng" msgid "Golden Goose" msgstr "Ngá»—ng Vàng" msgid "The %{name} brings in an income of %{count} gold per day." msgstr "%{name} mang lại thu nhập %{count} vàng má»—i ngày." msgid "Arcane Necklace of Magic" msgstr "Vòng cổ Ma thuật Bí ẩn" msgid "" "After rescuing a Sorceress from a cursed tomb, she rewards your heroism with " "an exquisite jeweled necklace." msgstr "" "Sau khi giải cứu má»™t Nữ phù thá»§y khá»i ngôi má»™ bị nguyá»n rá»§a, cô ấy thưởng " "cho tướng cá»§a ngươi má»™t chiếc vòng cổ nạm ngá»c tinh xảo." msgid "Caster's Bracelet of Magic" msgstr "Vòng tay Ma thuật cá»§a Caster" msgid "" "While searching through the rubble of a caved-in mine, you free a group of " "trapped Dwarves. Grateful, the leader gives you a golden bracelet." msgstr "" "Trong khi tìm kiếm trong đống đổ nát cá»§a má»™t khu má» bị sập, ngươi giải thoát " "má»™t nhóm Ngưá»i lùn bị mắc kẹt. Biết Æ¡n, ngưá»i lãnh đạo tặng ngươi má»™t chiếc " "vòng tay vàng." msgid "Mage's Ring of Power" msgstr "Nhẫn Quyá»n lá»±c Pháp sư" msgid "" "A cry of pain leads you to a Centaur, caught in a trap. Upon setting the " "creature free, he hands you a small pouch. Emptying the contents, you find a " "dazzling jeweled ring." msgstr "" "Tiếng kêu Ä‘au đớn sẽ dẫn ngươi tá»›i chá»— Nhân Mã Ä‘ang mắc bẫy. Sau khi thả " "sinh vật ra, anh ta đưa cho ngươi má»™t chiếc túi nhá». Dá»n sạch ná»™i dung bên " "trong, ngươi tìm thấy má»™t chiếc nhẫn nạm ngá»c rá»±c rỡ." msgid "Witch's Broach of Magic" msgstr "Lá»i khuyên Phép thuật cá»§a Phù thá»§y" msgid "" "Alongside the remains of a burnt witch lies a beautiful broach, intricately " "designed. Approaching the corpse with caution, you add the broach to your " "inventory." msgstr "" "Bên cạnh hài cốt cá»§a má»™t phù thá»§y bị cháy là má»™t chiếc trâm cài đẹp đẽ, được " "thiết kế tinh xảo. Tiếp cận xác chết má»™t cách thận trá»ng, ngươi thêm chiếc " "chuốt vào kho cá»§a mình." msgid "Medal of Valor" msgstr "Huân chương DÅ©ng cảm" #, fuzzy msgid "The %{name} increases the morale of the hero's army by %{count}." msgstr "%{name} nâng cao tinh thần cá»§a ngươi lên %{count}." msgid "" "Freeing a virtuous maiden from the clutches of an evil overlord, you are " "granted a Medal of Valor by the King's herald." msgstr "" "Giải thoát má»™t thiếu nữ đức hạnh khá»i nanh vuốt cá»§a tên chúa tể độc ác, " "ngươi được sứ giả cá»§a Nhà vua trao tặng Huân chương DÅ©ng cảm." msgid "Medal of Courage" msgstr "Huân chương Cam đảm" msgid "" "After saving a young boy from a vicious pack of Wolves, you return him to " "his father's manor. The grateful nobleman awards you with a Medal of Courage." msgstr "" "Sau khi cứu má»™t cậu bé khá»i bầy Sói hung ác, ngươi đưa cậu bé vá» trang viên " "cá»§a cha cậu. Nhà quý tá»™c biết Æ¡n sẽ trao cho ngươi Huân chương Can đảm." msgid "Medal of Honor" msgstr "Huân chương Danh dá»±" msgid "" "After freeing a princess of a neighboring kingdom from the evil clutches of " "despicable slavers, she awards you with a Medal of Honor." msgstr "" "Sau khi giải phóng công chúa cá»§a má»™t vương quốc láng giá»ng khá»i nanh vuốt " "độc ác cá»§a những kẻ nô lệ hèn hạ, cô ấy sẽ trao cho ngươi Huân chương Danh " "dá»±." msgid "Medal of Distinction" msgstr "Huân chương Xuất chúng" msgid "" "Ridding the countryside of the hideous Minotaur who made a sport of eating " "noblemen's Knights, you are honored with the Medal of Distinction." msgstr "" "Thoát khá»i vùng nông thôn cá»§a Minotaur gá»›m ghiếc, kẻ chuyên ăn thịt các Hiệp " "sÄ© cá»§a quý tá»™c, ngươi được vinh danh vá»›i Huân chương Xuất chúng." msgid "Fizbin of Misfortune" msgstr "Huy chương Bất hạnh" #, fuzzy msgid "" "The %{name} greatly decreases the morale of the hero's army by %{count}." msgstr "%{name} làm giảm đáng kể tinh thần cá»§a ngươi %{count}." msgid "" "You stumble upon a medal lying alongside the empty road. Adding the medal to " "your inventory, you become aware that you have acquired the undesirable " "Fizbin of Misfortune, greatly decreasing your army's morale." msgstr "" "Ngươi tình cá» thấy má»™t chiếc huy chương nằm dá»c con đưá»ng vắng. Khi thêm huy " "chương vào kho đồ cá»§a mình, ngươi sẽ biết rằng mình đã có được Huy chương " "Bất hạnh không mong muốn, khiến tinh thần quân đội cá»§a ngươi giảm Ä‘i đáng kể." msgid "Thunder Mace of Dominion" msgstr "Chùy Sấm sét cá»§a sá»± Thống trị" msgid "" "During a sudden storm, a bolt of lightning strikes a tree, splitting it. " "Inside the tree you find a mysterious mace." msgstr "" "Trong má»™t cÆ¡n bão bất ngá», má»™t tia sét đánh vào má»™t cái cây, làm gãy nó. Bên " "trong cái cây ngươi tìm thấy má»™t cây chùy bí ẩn." msgid "Armored Gauntlets of Protection" msgstr "Găng tay Thép Bảo vệ" #, fuzzy msgid "The %{name} increase the hero's defense skill by %{count}." msgstr "%{name} tăng kỹ năng phòng thá»§ cá»§a ngươi thêm %{count}." msgid "" "You encounter the infamous Black Knight! After a grueling duel ending in a " "draw, the Knight, out of respect, offers you a pair of armored gauntlets." msgstr "" "Ngươi gặp phải Hiệp sÄ© Äen khét tiếng! Sau khi má»™t trận đấu tay đôi mệt má»i " "kết thúc vá»›i tá»· số hòa, Hiệp sÄ©, vì tôn trá»ng, sẽ tặng ngươi má»™t đôi găng " "tay bá»c thép." msgid "Defender Helm of Protection" msgstr "MÅ© Bảo vệ cá»§a Phòng thá»§" msgid "" "A glint of golden light catches your eye. Upon further investigation, you " "find a golden helm hidden under a bush." msgstr "" "Má»™t tia sáng vàng thu hút ánh nhìn cá»§a ngươi. Sau khi Ä‘iá»u tra sâu hÆ¡n, " "ngươi tìm thấy má»™t chiếc mÅ© bảo hiểm bằng vàng ẩn dưới bụi cây." msgid "Giant Flail of Dominion" msgstr "Chùy Thống trị Khổng lồ" msgid "" "A clumsy Giant has killed himself with his own flail. Knowing your superior " "skill with this weapon, you confidently remove the spectacular flail from " "the fallen Giant." msgstr "" "Má»™t gã khổng lồ vụng vỠđã tá»± sát bằng chính cây đập lúa cá»§a mình. Biết được " "kỹ năng vượt trá»™i cá»§a mình vá»›i loại vÅ© khí này, ngươi tá»± tin loại bá» cú đập " "cây ngoạn mục từ Ngưá»i khổng lồ đã ngã xuống." msgid "Ballista of Quickness" msgstr "Máy bắn đá Nhanh" #, fuzzy msgid "The %{name} gives the hero's catapult one extra shot per combat round." msgstr "" "%{name} giúp máy bắn đá cá»§a ngươi có thêm má»™t phát bắn má»—i vòng chiến đấu." msgid "" "Walking through the ruins of an ancient walled city, you find the instrument " "of the city's destruction, an elaborately crafted ballista." msgstr "" "Äi bá»™ qua đống đổ nát cá»§a má»™t thành phố cổ có tưá»ng bao quanh, ngươi tìm " "thấy công cụ há»§y diệt thành phố, má»™t chiếc ballista được chế tạo công phu." msgid "Stealth Shield of Protection" msgstr "Lá chắn Bảo vệ Tàng hình" msgid "" "A stone statue of a warrior holds a silver shield. As you remove the shield, " "the statue crumbles into dust." msgstr "" "Bức tượng đá cá»§a má»™t chiến binh cầm má»™t chiếc khiên bạc. Khi ngươi tháo tấm " "khiên ra, bức tượng sẽ vỡ vụn thành cát bụi." msgid "Dragon Sword of Dominion" msgstr "Kiếm Rồng Thống trị" msgid "" "As you are walking along a narrow path, a nearby bush suddenly bursts into " "flames. Before your eyes the flames become the image of a beautiful woman. " "She holds out a magnificent sword to you." msgstr "" "Khi ngươi Ä‘ang Ä‘i dá»c theo má»™t con đưá»ng hẹp, má»™t bụi cây gần đó bất ngá» bốc " "cháy. Trước mắt ngươi ngá»n lá»­a trở thành hình ảnh cá»§a má»™t ngưá»i phụ nữ xinh " "đẹp. Cô ấy đưa ra má»™t thanh kiếm tuyệt đẹp cho ngươi." msgid "Power Axe of Dominion" msgstr "Rìu Sức mạnh Thống trị" msgid "" "You see a silver axe embedded deeply in the ground. After several " "unsuccessful attempts by your army to remove the axe, you tightly grip the " "handle of the axe and effortlessly pull it free." msgstr "" "Ngươi nhìn thấy má»™t chiếc rìu bạc cắm sâu vào lòng đất. Sau nhiá»u ná»— lá»±c " "không thành công cá»§a quân đội để loại bá» chiếc rìu, ngươi nắm chặt cán rìu " "và dá»… dàng kéo nó ra." msgid "Divine Breastplate of Protection" msgstr "Giáp Bảo vệ Thần thánh" msgid "" "A gang of Rogues is sifting through the possessions of dead warriors. " "Scaring off the scavengers, you note the Rogues had overlooked a beautiful " "breastplate." msgstr "" "Má»™t nhóm Rogues Ä‘ang sàng lá»c tài sản cá»§a những chiến binh đã chết. Khiến " "những ngưá»i nhặt rác sợ hãi, ngươi lưu ý rằng Rogues đã bá» qua má»™t tấm giáp " "ngá»±c tuyệt đẹp." msgid "Minor Scroll of Knowledge" msgstr "Cuá»™n Kiến thức Nhá»" msgid "" "Before you appears a levitating glass case with a scroll, perched upon a bed " "of crimson velvet. At your touch, the lid opens and the scroll floats into " "your awaiting hands." msgstr "" "Trước khi ngươi xuất hiện má»™t chiếc há»™p thá»§y tinh bay lên vá»›i má»™t cuá»™n giấy, " "nằm trên má»™t chiếc giưá»ng nhung đỠthẫm. Khi ngươi chạm vào, nắp sẽ mở ra và " "cuá»™n giấy sẽ trôi vào tay ngươi Ä‘ang chỠđợi." msgid "Major Scroll of Knowledge" msgstr "Cuá»™n Kiến thức Lá»›n" msgid "" "Visiting a local wiseman, you explain the intent of your journey. He reaches " "into a sack and withdraws a yellowed scroll and hands it to you." msgstr "" "Äến thăm má»™t nhà thông thái địa phương, ngươi giải thích mục đích chuyến Ä‘i " "cá»§a mình. Anh ta thò tay vào bao tải và rút ra má»™t cuá»™n giấy màu vàng rồi " "đưa cho ngươi." msgid "Superior Scroll of Knowledge" msgstr "Cuá»™n Kiến thức Äại" msgid "" "You come across the remains of an ancient Druid. Bones, yellowed with age, " "peer from the ragged folds of her robe. Searching the robe, you discover a " "scroll hidden in the folds." msgstr "" "Ngươi tình cá» gặp hài cốt cá»§a má»™t Tu sÄ© cổ đại. Những bá»™ xương đã ố vàng " "theo thá»i gian lá»™ ra từ những nếp gấp rách rưới trên chiếc áo choàng cá»§a cô. " "Lục soát chiếc áo choàng, ngươi phát hiện ra má»™t cuá»™n giấy được giấu trong " "các nếp gấp." msgid "Foremost Scroll of Knowledge" msgstr "Cuá»™n Kiến thức Tối cao" msgid "" "Mangled bones, yellowed with age, peer from the ragged folds of a dead " "Druid's robe. Searching the robe, you discover a scroll hidden within." msgstr "" "Những bá»™ xương xiêu vẹo, ố vàng theo thá»i gian, lá»™ ra từ những nếp gấp rách " "rưới trên chiếc áo choàng cá»§a má»™t Tu sÄ© đã chết. Lục soát chiếc áo choàng, " "ngươi phát hiện ra má»™t cuá»™n giấy ẩn bên trong." msgid "Endless Sack of Gold" msgstr "Túi Vàng Vô tận" #, fuzzy msgid "The %{name} provides the hero with %{count} gold per day." msgstr "%{name} cung cấp cho ngươi %{count} vàng má»—i ngày." msgid "" "A little leprechaun dances gleefully around a magic sack. Seeing you " "approach, he stops in mid-stride. The little man screams and stamps his foot " "ferociously, vanishing into thin air. Remembering the old leprechaun saying " "'Finders Keepers', you grab the sack and leave." msgstr "" "Má»™t chú yêu tinh nhá» nhảy múa vui vẻ quanh chiếc bao ma thuật. Thấy ngươi " "đến gần, anh ta dừng lại giữa chừng. Ngưá»i đàn ông nhá» bé hét lên và giậm " "chân dữ dá»™i, biến mất trong không khí loãng. Nhá»› đến câu nói cá»§a yêu tinh " "già 'Ngưá»i giữ ngưá»i tìm kiếm', ngươi chá»™p lấy chiếc bao và rá»i Ä‘i." msgid "Endless Bag of Gold" msgstr "Bao Vàng Vô tận" msgid "" "A noblewoman, separated from her traveling companions, asks for your help. " "After escorting her home, she rewards you with a bag filled with gold." msgstr "" "Má»™t phụ nữ quý tá»™c bị tách khá»i những ngưá»i bạn đồng hành cá»§a mình và nhá» " "ngươi giúp đỡ. Sau khi há»™ tống cô ấy vá» nhà, cô ấy thưởng cho ngươi má»™t " "chiếc túi chứa đầy vàng." msgid "Endless Purse of Gold" msgstr "Ví Vàng Vô tận" msgid "" "In your travels, you find a leather purse filled with gold that once " "belonged to a great warrior king who had the ability to transform any " "inanimate object into gold." msgstr "" "Trong chuyến du hành cá»§a mình, ngươi tìm thấy má»™t chiếc ví da chứa đầy vàng " "từng thuá»™c vá» má»™t vị vua chiến binh vÄ© đại, ngưá»i có khả năng biến bất kỳ " "vật vô tri nào thành vàng." msgid "Nomad Boots of Mobility" msgstr "Giầy Du mục cá»§a Dịch chuyển" #, fuzzy msgid "The %{name} increase the hero's movement on land." msgstr "%{name} tăng khả năng di chuyển cá»§a ngươi trên đất liá»n." msgid "" "A Nomad trader seeks protection from a tribe of Goblins. For your " "assistance, he gives you a finely crafted pair of boots made from the " "softest leather. Looking closely, you see fascinating ancient carvings " "engraved on the leather." msgstr "" "Má»™t thương nhân du mục tìm kiếm sá»± bảo vệ từ bá»™ tá»™c Yêu tinh. Äể há»— trợ " "ngươi, anh ấy sẽ đưa cho ngươi má»™t đôi bốt được chế tác tinh xảo làm từ loại " "da má»m nhất. Nhìn kỹ, ngươi sẽ thấy những hình chạm khắc cổ xưa đầy hấp dẫn " "được khắc trên da." msgid "Traveler's Boots of Mobility" msgstr "Giầy Du lich cá»§a Dịch chuyển" msgid "" "Discovering a pair of beautifully beaded boots made from the finest and " "softest leather, you thank the anonymous donor and add the boots to your " "inventory." msgstr "" "Phát hiện ra má»™t đôi bốt đính cưá»m đẹp mắt được làm từ loại da má»m và đẹp " "nhất, ngươi cảm Æ¡n nhà tài trợ ẩn danh và thêm đôi bốt vào kho cá»§a mình." msgid "Lucky Rabbit's Foot" msgstr "Chân Thá» May mắn" #, fuzzy msgid "The %{name} increases the luck of the hero's army by %{count}." msgstr "%{name} tăng may mắn cá»§a ngươi trong chiến đấu lên %{count}." msgid "" "A traveling merchant offers you a rabbit's foot, made of gleaming silver " "fur, for safe passage. The merchant explains the charm will increase your " "luck in combat." msgstr "" "Má»™t thương gia du lịch tặng ngươi má»™t bàn chân thá», làm bằng lông bạc lấp " "lánh, để Ä‘i lại an toàn. Ngưá»i thương gia giải thích rằng bùa sẽ tăng may " "mắn cho ngươi trong chiến đấu." msgid "Golden Horseshoe" msgstr "Giầy ngá»±a Vàng" msgid "" "An ensnared Unicorn whinnies in fright. Murmuring soothing words, you set " "her free. Snorting and stamping her front hoof once, she gallops off. " "Looking down you see a golden horseshoe." msgstr "" "Má»™t con Kỳ lân bị mắc bẫy Ä‘ang rên rỉ vì sợ hãi. Thì thầm những lá»i êm dịu, " "ngươi thả cô ấy ra. Khịt mÅ©i và giậm mạnh móng trước má»™t lần, cô ấy phi nước " "đại. Nhìn xuống ngươi thấy má»™t chiếc móng ngá»±a màu vàng." msgid "Gambler's Lucky Coin" msgstr "Xu May mắn cá»§a Dân cá» bạc" msgid "" "You have captured a mischievous imp who has been terrorizing the region. In " "exchange for his release, he rewards you with a magical coin." msgstr "" "Ngươi đã bắt được má»™t tên tiểu quá»· tinh quái Ä‘ang khá»§ng bố khu vá»±c. Äể đổi " "lấy việc được thả, anh ta thưởng cho ngươi má»™t đồng xu ma thuật." msgid "Four-Leaf Clover" msgstr "Cá» Bốn Lá" msgid "" "In the middle of a patch of dead and dry vegetation, to your surprise you " "find a healthy green four-leaf clover." msgstr "" "Giữa má»™t thảm thá»±c vật khô và chết, ngươi ngạc nhiên khi tìm thấy má»™t cây cá» " "bốn lá xanh tươi khá»e mạnh." msgid "True Compass of Mobility" msgstr "La bàn Di động Äích thá»±c" #, fuzzy msgid "The %{name} increases the hero's movement on land and sea." msgstr "%{name} tăng khả năng di chuyển cá»§a ngươi trên đất liá»n và trên biển." msgid "" "An old man claiming to be an inventor asks you to try his latest invention. " "He then hands you a compass." msgstr "" "Má»™t ông già tá»± xưng là nhà phát minh yêu cầu ngươi thá»­ phát minh má»›i nhất " "cá»§a ông ấy. Sau đó anh ta đưa cho ngươi má»™t chiếc la bàn." msgid "Sailor's Astrolabe of Mobility" msgstr "Bản đồ Di chuyển cá»§a Thá»§y thá»§" #, fuzzy msgid "The %{name} increases the hero's movement on sea." msgstr "%{name} tăng khả năng di chuyển cá»§a ngươi trên biển." msgid "" "An old sea captain is being tortured by Ogres. You save him, and in return " "he rewards you with a wondrous instrument to measure the distance of a star." msgstr "" "Má»™t thuyá»n trưởng già Ä‘ang bị bá»n yêu tinh tra tấn. Ngươi cứu anh ta, và đổi " "lại anh ta thưởng cho ngươi má»™t công cụ kỳ diệu để Ä‘o khoảng cách cá»§a má»™t " "ngôi sao." msgid "Evil Eye" msgstr "Mắt Quá»·" msgid "The %{name} reduces the casting cost of curse spells by half." msgstr "%{name} giảm má»™t ná»­a chi phí sá»­ dụng bùa chú." msgid "" "While venturing into a decrepit hut you find the Skeleton of a long dead " "witch. Investigation of the remains reveals a glass eye rolling around " "inside an empty skull." msgstr "" "Trong khi mạo hiểm vào má»™t túp lá»u tồi tàn, ngươi tìm thấy Bá»™ xương cá»§a má»™t " "phù thá»§y đã chết từ lâu. Äiá»u tra hài cốt cho thấy má»™t con mắt thá»§y tinh lăn " "tròn bên trong há»™p sá» trống rá»—ng." msgid "Enchanted Hourglass" msgstr "Äồng hồ cát Mê hoặc" #, fuzzy msgid "" "The %{name} extends the duration of all the hero's spells by %{count} turns." msgstr "" "%{name} kéo dài thá»i lượng cá»§a tất cả các phép thuật cá»§a ngươi thêm %{count} " "lượt." msgid "" "A surprise turn in the landscape finds you in the midst of a grisly scene: " "Vultures picking at the aftermath of a terrible battle. Your cursory search " "of the remains turns up an enchanted hourglass." msgstr "" "Má»™t bước ngoặt bất ngá» trong khung cảnh đưa ngươi đến giữa má»™t khung cảnh " "rùng rợn: Ká»n ká»n Ä‘ang nhặt nhạnh sau má»™t trận chiến khá»§ng khiếp. Việc tìm " "kiếm nhanh chóng cá»§a ngươi vá» hài cốt sẽ cho ra má»™t chiếc đồng hồ cát đầy mê " "hoặc." msgid "Gold Watch" msgstr "Äồng hồ vàng" #, fuzzy msgid "The %{name} doubles the effectiveness of the hero's hypnotize spells." msgstr "%{name} tăng gấp đôi hiệu quả cá»§a phép thuật thôi miên cá»§a ngươi." msgid "" "In reward for helping his cart out of a ditch, a traveling potion salesman " "gives you a \"magic\" gold watch. Unbeknownst to him, the watch really is " "magical." msgstr "" "Äể thưởng cho việc giúp chiếc xe cá»§a mình thoát khá»i mương, má»™t ngưá»i bán " "thuốc du lịch sẽ tặng ngươi má»™t chiếc đồng hồ vàng \"ma thuật\". Anh ta " "không há» biết rằng chiếc đồng hồ thá»±c sá»± có phép thuật." msgid "Skullcap" msgstr "MÅ© đầu lâu" msgid "The %{name} halves the casting cost of all mind influencing spells." msgstr "" "%{name} giảm má»™t ná»­a chi phí thi triển cá»§a tất cả các phép thuật ảnh hưởng " "đến tâm trí." msgid "" "A brief stop at an improbable rural inn yields an exchange of money, tales, " "and accidentally, luggage. You find a magical skullcap in your new backpack." msgstr "" "Má»™t lần dừng chân ngắn ngá»§i tại má»™t quán trá» nông thôn không mấy chắc chắn " "sẽ mang lại sá»± trao đổi tiá»n bạc, những câu chuyện và vô tình là cả hành lý. " "Ngươi tìm thấy má»™t chiếc mÅ© đầu lâu thần kỳ trong chiếc ba lô má»›i cá»§a mình." msgid "Ice Cloak" msgstr "Ão Băng" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from cold spells." msgstr "" "%{name} giảm má»™t ná»­a tất cả thiệt hại mà quân cá»§a ngươi phải chịu từ các " "phép thuật lạnh." msgid "" "Responding to the panicked cries of a damsel in distress, you discover a " "young woman fleeing from a hungry bear. You slay the beast in the nick of " "time, and the grateful Sorceress weaves a magic cloak from the bear's hide." msgstr "" "Trước tiếng kêu hoảng loạn cá»§a má»™t cô gái gặp nạn, ngươi phát hiện ra má»™t " "phụ nữ trẻ Ä‘ang chạy trốn khá»i má»™t con gấu đói. Ngươi giết chết con quái vật " "đúng lúc và mụ phù thá»§y đầy lòng biết Æ¡n đã dệt nên má»™t chiếc áo choàng ma " "thuật từ da con gấu." msgid "Fire Cloak" msgstr "Ão Lá»­a" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from fire spells." msgstr "" "%{name} giảm má»™t ná»­a tổng thiệt hại mà quân cá»§a ngươi phải gánh chịu từ các " "phép thuật lá»­a." msgid "" "You've come upon a fight between a Necromancer and a Paladin. The " "Necromancer blasts the Paladin with a fire bolt, bringing him to his knees. " "Acting quickly, you slay the evil one before the final blow. The grateful " "Paladin gives you the fire cloak that saved him." msgstr "" "Ngươi đã chứng kiến cuá»™c chiến giữa Chiêu hồn và Tráng sÄ©. Chiêu hồn bắn " "tung Tráng sÄ© bằng má»™t tia lá»­a, khiến anh ta khuỵu gối. Hành động nhanh " "chóng, ngươi tiêu diệt kẻ ác trước đòn cuối cùng. Tráng sÄ© biết Æ¡n sẽ trao " "cho ngươi chiếc áo choàng lá»­a đã cứu anh ta." msgid "Lightning Helm" msgstr "MÅ© Sét" #, fuzzy msgid "" "The %{name} halves all damage the hero's troops receive from lightning " "spells." msgstr "" "%{name} giảm má»™t ná»­a tất cả sát thương mà quân cá»§a ngươi phải gánh chịu từ " "các phép thuật sét." msgid "" "A traveling tinker in need of supplies offers you a helm with a thunderbolt " "design on its top in exchange for food and water. Curious, you accept, and " "later find out that the helm is magical." msgstr "" "Má»™t ngưá»i thợ sá»­a chữa du lịch Ä‘ang cần đồ dùng sẽ cung cấp cho ngươi má»™t " "chiếc mÅ© bảo hiểm có thiết kế hình tia sét ở trên để đổi lấy thức ăn và nước " "uống. Tò mò, ngươi chấp nhận và sau đó phát hiện ra rằng chiếc mÅ© có phép " "thuật." msgid "Evercold Icicle" msgstr "Băng lạnh Bất tận" #, fuzzy msgid "" "The %{name} causes the hero's cold spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} khiến các phép thuật lạnh lùng cá»§a ngươi gây thêm %{count} phần trăm " "sát thương cho quân địch." msgid "" "An icicle withstanding the full heat of the noonday sun attracts your " "attention. Intrigued, you break it off, and find that it does not melt in " "your hand." msgstr "" "Má»™t cá»™t băng chịu được toàn bá»™ sức nóng cá»§a mặt trá»i giữa trưa sẽ thu hút sá»± " "chú ý cá»§a ngươi. Tò mò, ngươi bẻ nó ra và thấy rằng nó không tan chảy trong " "tay ngươi." msgid "Everhot Lava Rock" msgstr "Nham thạch nóng Vô tận" #, fuzzy msgid "" "The %{name} causes the hero's fire spells to do %{count} percent more damage " "to enemy troops." msgstr "" "%{name} khiến phép thuật lá»­a cá»§a ngươi gây thêm %{count} phần trăm sát " "thương cho quân địch." msgid "" "Your wanderings bring you into contact with a tribe of ape-like beings using " "a magical lava rock that never cools to light their fires. You take pity on " "them and teach them to make fire with sticks. Believing you to be a god, the " "apes give you their rock." msgstr "" "Những chuyến lang thang cá»§a ngươi sẽ đưa ngươi tiếp xúc vá»›i má»™t bá»™ tá»™c sinh " "vật giống vượn Ä‘ang sá»­ dụng má»™t tảng đá nham thạch kỳ diệu không bao giá» " "nguá»™i để thắp sáng ngá»n lá»­a cá»§a há». Ngươi thương hại chúng và dạy chúng đốt " "lá»­a bằng gậy. Tin rằng ngươi là má»™t vị thần, loài vượn đưa cho ngươi hòn đá " "cá»§a chúng." msgid "Lightning Rod" msgstr "Quyá»n trượng Sét" #, fuzzy msgid "" "The %{name} causes the hero's lightning spells to do %{count} percent more " "damage to enemy troops." msgstr "" "%{name} khiến phép thuật sét cá»§a ngươi gây thêm %{count} phần trăm sát " "thương cho quân địch." msgid "" "While waiting out a storm, a lighting bolt strikes a nearby cottage's " "lightning rod, which melts and falls to the ground. The tip of the rod, " "however, survives intact and makes your hair stand on end when you touch it. " "Hmm..." msgstr "" "Trong khi chá» bão tan, má»™t tia sét đánh trúng cá»™t thu lôi cá»§a má»™t ngôi nhà " "nhá» gần đó, khiến cá»™t thu lôi tan chảy và rÆ¡i xuống đất. Tuy nhiên, đầu que " "vẫn còn nguyên vẹn và khiến tóc ngươi dá»±ng đứng khi chạm vào. Ừm..." msgid "Snake-Ring" msgstr "Vòng Rắn" #, fuzzy msgid "The %{name} halves the casting cost of all of the hero's bless spells." msgstr "" "%{name} giảm má»™t ná»­a chi phí thi triển tất cả các phép thuật ban phước cá»§a " "ngươi." msgid "" "You've found an oddly shaped ring on the finger of a long dead traveler. The " "ring looks like a snake biting its own tail." msgstr "" "Ngươi đã tìm thấy má»™t chiếc nhẫn có hình dạng kỳ lạ trên ngón tay cá»§a má»™t du " "khách đã chết từ lâu. Chiếc nhẫn trông giống như con rắn tá»± cắn Ä‘uôi mình." msgid "Ankh" msgstr "" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's resurrect and " "animate spells." msgstr "" "%{name} tăng gấp đôi hiệu quả cá»§a tất cả các phép thuật hồi sinh và tái sinh " "cá»§a ngươi." msgid "" "A fierce windstorm reveals the entrance to a buried tomb. Your investigation " "reveals that the tomb has already been looted, but the thieves overlooked an " "ankh on a silver chain in the dark." msgstr "" "Má»™t cÆ¡n bão dữ dá»™i làm lá»™ ra lối vào má»™t ngôi má»™ bị chôn vùi. Cuá»™c Ä‘iá»u tra " "cá»§a ngươi cho thấy ngôi má»™ đã bị cướp phá, nhưng bá»n trá»™m đã bá» qua má»™t " "chiếc ankh trên dây chuyá»n bạc trong bóng tối." msgid "Book of Elements" msgstr "Sách Nguyên tố" #, fuzzy msgid "" "The %{name} doubles the effectiveness of all of the hero's summoning spells." msgstr "" "%{name} tăng gấp đôi hiệu quả cá»§a tất cả các phép thuật triệu hồi cá»§a ngươi." msgid "" "You come across a conjurer who begs to accompany you and your army awhile " "for safety. You agree, and he offers as payment a copy of the book of the " "elements." msgstr "" "Ngươi tình cá» gặp má»™t pháp sư cầu xin được Ä‘i cùng ngươi và quân đội cá»§a " "ngươi má»™t thá»i gian để được an toàn. Ngươi đồng ý và anh ta đưa ra má»™t bản " "sao cá»§a cuốn sách vá» các yếu tố để thanh toán." msgid "Elemental Ring" msgstr "Nhẫn Nguyên tố" msgid "The %{name} halves the casting cost of all summoning spells." msgstr "" "%{name} giảm má»™t ná»­a chi phí thi triển cá»§a tất cả các phép thuật triệu hồi." msgid "" "While pausing to rest, you notice a bobcat climbing a short tree to get at a " "crow's nest. On impulse, you climb the tree yourself and scare off the cat. " "When you look in the nest, you find a collection of shiny stones and a ring." msgstr "" "Trong khi dừng lại để nghỉ ngÆ¡i, ngươi nhận thấy má»™t con linh miêu Ä‘ang trèo " "lên má»™t cái cây thấp để đến tổ quạ. Trong cÆ¡n bốc đồng, ngươi tá»± mình trèo " "lên cây và dá»a con mèo. Khi nhìn vào tổ, ngươi sẽ thấy má»™t bá»™ sưu tập những " "viên đá sáng bóng và má»™t chiếc nhẫn." msgid "Holy Pendant" msgstr "Mặt dây Thánh" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to curse spells." msgstr "%{name} làm cho tất cả quân đội cá»§a ngươi miá»…n nhiá»…m vá»›i các bùa chú." msgid "" "In your wanderings you come across a hermit living in a small, tidy hut. " "Impressed with your mission, he takes time out from his meditations to bless " "and give you a charm against curses." msgstr "" "Trong chuyến lang thang cá»§a mình, ngươi tình cá» gặp má»™t ẩn sÄ© sống trong má»™t " "túp lá»u nhá», ngăn nắp. Ấn tượng vá»›i sứ mệnh cá»§a ngươi, anh ấy dành thá»i gian " "thiá»n định để ban phước và ban cho ngươi má»™t tấm bùa chống lại những lá»i " "nguyá»n." msgid "Pendant of Free Will" msgstr "Mặt dây à chí Tá»± do" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to hypnotize spells." msgstr "" "%{name} làm cho tất cả quân cá»§a ngươi miá»…n nhiá»…m vá»›i các phép thuật thôi " "miên." msgid "" "Responding to cries for help, you find river Sprites making a sport of " "dunking an old man. Feeling vengeful, you rescue the man and drag a Sprite " "onto dry land for awhile. The Sprite, uncomfortable in the air, gives you a " "magic pendant to let him go." msgstr "" "Äáp lại những tiếng kêu cứu, ngươi thấy các Sprites sông Ä‘ang thá»±c hiện má»™t " "trò chÆ¡i là dìm má»™t ông già xuống nước. Cảm thấy muốn trả thù, ngươi giải " "cứu ngưá»i đàn ông và kéo má»™t Sprite lên vùng đất khô ráo má»™t lúc. Sprite, " "không thoải mái khi ở trên không, đưa cho ngươi má»™t mặt dây chuyá»n ma thuật " "để thả anh ta Ä‘i." msgid "Pendant of Life" msgstr "Mặt dây cá»§a Sá»± sống" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to death spells." msgstr "%{name} làm cho tất cả quân cá»§a ngươi miá»…n nhiá»…m vá»›i bùa chết." msgid "" "A brief roadside encounter with a small caravan and a game of knucklebones " "wins a magic pendant. Its former owner says that it protects from " "Necromancers' death spells." msgstr "" "Cuá»™c chạm trán ngắn ngá»§i bên đưá»ng vá»›i má»™t Ä‘oàn lữ hành nhá» và trò chÆ¡i đánh " "đố sẽ giành được mặt dây chuyá»n ma thuật. Ngưá»i chá»§ cÅ© cá»§a nó nói rằng nó " "bảo vệ khá»i bùa chết cá»§a các Necromancer." msgid "Serenity Pendant" msgstr "Mặt dây Thanh thản" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to berserk spells." msgstr "" "%{name} làm cho tất cả quân cá»§a ngươi miá»…n nhiá»…m vá»›i các phép thuật Ä‘iên " "cuồng." msgid "" "The sounds of combat draw you to the scene of a fight between an old " "Barbarian and an eight-headed Hydra. Your timely intervention swings the " "battle in favor of the man, and he rewards you with a pendant he used to use " "to calm his mind for battle." msgstr "" "Âm thanh cá»§a trận chiến đưa ngươi đến hiện trưá»ng cuá»™c chiến giữa má»™t " "Barbarian già và má»™t con Hydra tám đầu. Sá»± can thiệp kịp thá»i cá»§a ngươi sẽ " "giúp trận chiến có lợi cho ngưá»i đàn ông và anh ta thưởng cho ngươi má»™t " "chiếc mặt dây chuyá»n mà anh ta dùng để giúp anh ta bình tÄ©nh trong trận " "chiến." msgid "Seeing-eye Pendant" msgstr "Mặt dây Mắt nhìn" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to blindness spells." msgstr "%{name} làm cho tất cả quân cá»§a ngưá»i miá»…n nhiá»…m vá»›i bùa mù." msgid "" "You come upon a very old woman, long blind from cataracts and dying alone. " "You tend to her final needs and promise a proper burial. Grateful, she gives " "you a magic pendant emblazoned with a stylized eye. It lets you see with " "your eyes closed." msgstr "" "Ngươi tình cá» gặp má»™t bà cụ già, bị mù từ lâu vì bệnh đục thá»§y tinh thể và " "Ä‘ang chết má»™t mình. Ngươi hướng tá»›i những nhu cầu cuối cùng cá»§a bà ấy và hứa " "sẽ chôn cất đàng hoàng. Biết Æ¡n, bà ấy tặng ngươi má»™t mặt dây chuyá»n ma " "thuật được trang trí bằng má»™t con mắt cách Ä‘iệu. Nó cho phép ngươi nhìn khi " "nhắm mắt lại." msgid "Kinetic Pendant" msgstr "Mặt dây Äá»™ng há»c" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to paralyze spells." msgstr "" "%{name} làm cho tất cả quân cá»§a ngươi miá»…n nhiá»…m vá»›i các phép thuật làm tê " "liệt." msgid "" "You come across a golem wearing a glowing pendant and blocking your way. " "Acting on a hunch, you cut the pendant from its neck. Deprived of its power " "source, the golem breaks down, leaving you with the magical pendant." msgstr "" "Ngươi bắt gặp má»™t con golem Ä‘eo mặt dây chuyá»n phát sáng và chặn đưá»ng " "ngươi. Theo linh cảm, ngươi cắt mặt dây chuyá»n khá»i cổ nó. Bị mất nguồn năng " "lượng, con golem bị há»ng, để lại cho ngươi chiếc mặt dây chuyá»n ma thuật." msgid "Pendant of Death" msgstr "Mặt dây Chết chóc" #, fuzzy msgid "The %{name} makes all of the hero's troops immune to holy spells." msgstr "" "%{name} làm cho tất cả quân đội cá»§a ngươi miá»…n nhiá»…m vá»›i các phép thuật thần " "thánh." msgid "" "A quick and deadly battle with a Necromancer wins you his magical pendant. " "Later, a Wizard tells you that the pendant protects undead under your " "control from holy word spells." msgstr "" "Má»™t trận chiến nhanh chóng và chết chóc vá»›i Necromancer sẽ giúp ngươi giành " "được mặt dây chuyá»n ma thuật cá»§a hắn. Sau đó, má»™t Pháp sư nói vá»›i ngươi rằng " "mặt dây chuyá»n bảo vệ xác sống dưới sá»± kiểm soát cá»§a ngươi khá»i các phép " "thuật từ thánh." msgid "Wand of Negation" msgstr "ÄÅ©a phép Phá»§ định" #, fuzzy msgid "" "The %{name} makes all of the hero's troops immune to dispel magic spells." msgstr "" "%{name} làm cho tất cả quân cá»§a ngươi miá»…n nhiá»…m vá»›i các phép thuật xua tan." msgid "" "You meet an old Wizard friend of yours traveling in the opposite direction. " "He presents you with a gift: A wand that prevents the use of the dispel " "magic spell on your allies." msgstr "" "Ngươi gặp má»™t ngưá»i bạn cÅ© cá»§a Pháp sư ngươi Ä‘ang Ä‘i theo hướng ngược lại. " "Anh ấy tặng ngươi má»™t món quà: Má»™t cây đũa phép ngăn cản việc sá»­ dụng phép " "thuật xua tan lên đồng minh cá»§a ngươi." msgid "Golden Bow" msgstr "Cung Vàng" #, fuzzy msgid "" "The %{name} eliminates the %{count} percent penalty for the hero's troops " "shooting past obstacles (e.g. castle walls)." msgstr "" "%{name} loại bá» hình phạt %{count} phần trăm đối vá»›i quân cá»§a ngươi bắn qua " "chướng ngại vật (ví dụ: tưá»ng lâu đài)." msgid "" "A chance meeting with a famous Archer finds you in a game of knucklebones " "pitting his bow against your horse. You win." msgstr "" "Má»™t cuá»™c gặp gỡ tình cá» vá»›i má»™t Cung thá»§ nổi tiếng sẽ đưa ngươi vào trò chÆ¡i " "đỠsức cung cá»§a anh ta vá»›i ngá»±a cá»§a ngươi. Ngươi thắng." msgid "Telescope" msgstr "Kính viá»…n vá»ng" #, fuzzy msgid "" "The %{name} increases the amount of terrain the hero reveals when " "adventuring by %{count} extra square." msgstr "" "%{name} tăng số lượng địa hình mà tướng cá»§a ngươi phát hiện khi phiêu lưu " "thêm %{count} ô vuông." msgid "" "A merchant from far away lands trades you a new invention of his people for " "traveling supplies. It makes distant objects appear closer, and he calls " "it...\n" "\n" "a telescope." msgstr "" "Má»™t thương gia từ những vùng đất xa xôi trao đổi vá»›i ngươi má»™t phát minh má»›i " "cá»§a ngưá»i dân anh ta để làm vật dụng Ä‘i du lịch. Nó làm cho những vật thể ở " "xa trông gần hÆ¡n, và ông gá»i nó là...\n" "\n" "má»™t kính viá»…n vá»ng." msgid "Statesman's Quill" msgstr "Bút lông cá»§a Statesman" #, fuzzy msgid "" "The %{name} reduces the cost of surrender to %{count} percent of the total " "cost of troops the hero has in their army." msgstr "" "%{name} giảm chi phí đầu hàng xuống %{count} phần trăm tổng chi phí quân đội " "ngươi có trong quân đội cá»§a mình." msgid "" "You pause to help a diplomat with a broken axle fix his problem. In " "gratitude, he gives you a writing quill with magical properties which he " "says will \"help people see things your way\"." msgstr "" "Ngươi dừng lại để giúp má»™t nhà ngoại giao bị gãy trục khắc phục sá»± cố cá»§a " "mình. Äể tá» lòng biết Æ¡n, anh ấy đưa cho ngươi má»™t chiếc bút lông có đặc " "tính kỳ diệu mà anh ấy nói sẽ \"giúp má»i ngưá»i nhìn má»i thứ theo cách cá»§a " "ngươi\"." msgid "Wizard's Hat" msgstr "MÅ© Phù thá»§y" #, fuzzy msgid "" "The %{name} increases the duration of the hero's spells by %{count} turns." msgstr "" "%{name} tăng thá»i lượng sá»­ dụng phép thuật cá»§a ngươi thêm %{count} lượt." msgid "" "You see a Wizard fleeing from a Griffin and riding like the wind. The Wizard " "opens a portal and rides through, getting his hat knocked off by the edge of " "the gate. The Griffin follows; the gate closes. You pick the hat up, dust it " "off, and put it on." msgstr "" "Ngươi thấy má»™t Pháp sư Ä‘ang chạy trốn khá»i má»™t con Griffin và phi như gió. " "Wizard mở má»™t cánh cổng và Ä‘i qua, chiếc mÅ© cá»§a anh ta bị hất văng ra mép " "cổng. Griffin theo sau; cánh cổng đóng lại. Ngươi nhặt chiếc mÅ© lên, phá»§i " "bụi rồi đội vào." msgid "Power Ring" msgstr "Nhẫn Sức mạnh" #, fuzzy msgid "The %{name} returns %{count} extra spell points per day to the hero." msgstr "" "%{name} phục hồi %{count} Ä‘iểm phép bổ sung má»—i ngày cho tướng cá»§a ngươi." msgid "" "You find a small tree that closely resembles the great Warlock Carnauth with " "a ring around one of its twigs. Scraps of clothing and rotting leather lead " "you to suspect that it IS Carnauth, transformed. Since you can't help him, " "you take the magic ring." msgstr "" "Ngươi tìm thấy má»™t cái cây nhá» gần giống vá»›i Warlock Carnauth vÄ© đại vá»›i má»™t " "vòng bao quanh má»™t trong những cành cây cá»§a nó. Những mảnh quần áo và da mục " "nát khiến ngươi nghi ngá» rằng đó LÀ Carnauth, đã biến hình. Vì không thể " "giúp anh ta nên ngươi lấy chiếc nhẫn ma thuật." msgid "Ammo Cart" msgstr "Xe Äạn" #, fuzzy msgid "" "The %{name} provides endless ammunition for all of the hero's troops that " "shoot." msgstr "%{name} cung cấp vô số đạn dược cho tất cả quân cá»§a ngươi bắn." msgid "" "An ammunition cart in the middle of an old battlefield catches your eye. " "Inspection shows it to be in good working order, so you take it along." msgstr "" "Má»™t xe chở đạn giữa chiến trưá»ng cÅ© thu hút sá»± chú ý cá»§a ngươi. Kiểm tra cho " "thấy nó Ä‘ang hoạt động tốt nên ngươi mang nó theo." msgid "Tax Lien" msgstr "Giữ Thuế" #, fuzzy msgid "The %{name} costs the hero %{count} gold pieces per day." msgstr "%{name} làm ngươi tốn %{count} vàng má»—i ngày." msgid "" "Your big spending habits have earned you a massive tax bill that you can't " "hope to pay. The tax man takes pity and agrees to only take 250 gold a day " "from your account for life. Check here if you want one dollar to go to the " "presidential campaign election fund." msgstr "" "Thói quen chi tiêu lá»›n cá»§a ngươi đã mang lại cho ngươi má»™t hóa đơn thuế " "khổng lồ mà ngươi không thể hy vá»ng trả được. Ngưá»i đóng thuế thương hại và " "đồng ý chỉ lấy 250 vàng má»—i ngày từ tài khoản cá»§a ngươi suốt Ä‘á»i. Äánh dấu " "vào đây nếu ngươi muốn má»™t đô la được chuyển vào quỹ bầu cá»­ chiến dịch tranh " "cá»­ tổng thống." msgid "Hideous Mask" msgstr "Mặt nạ Gá»›m ghiếc" #, fuzzy msgid "The %{name} prevents all 'wandering' armies from joining the hero." msgstr "" "%{name} ngăn chặn tất cả các đội quân 'lang thang' tham gia cùng tướng cá»§a " "ngươi." msgid "" "Your looting of the grave of Sinfilas Gardolad, the famous shapeshifting " "Warlock, unearths his fabled mask. Trembling, you put it on and it twists " "your visage into an awful grimace! Oh no! It's actually the hideous mask of " "Gromluck Greene, and you are stuck with it." msgstr "" "Việc ngươi cướp má»™ cá»§a Sinfilas Gardolad, Warlock biến hình nổi tiếng, đã " "khai quật được chiếc mặt nạ huyá»n thoại cá»§a anh ta. Run rẩy, ngươi Ä‘eo nó " "vào và nó làm khuôn mặt ngươi nhăn nhó khá»§ng khiếp! Ôi không! Äó thá»±c sá»± là " "chiếc mặt nạ gá»›m ghiếc cá»§a Gromluck Greene và ngươi bị mắc kẹt vá»›i nó." msgid "Endless Pouch of Sulfur" msgstr "Túi Lưu huỳnh Vô tận" msgid "The %{name} provides %{count} unit of sulfur per day." msgstr "%{name} cung cấp %{count} đơn vị lưu huỳnh má»—i ngày." msgid "" "You visit an alchemist who, upon seeing your army, is swayed by the " "righteousness of your cause. The newly loyal subject gives you his endless " "pouch of sulfur to help with the war effort." msgstr "" "Ngươi đến thăm má»™t nhà giả kim, ngưá»i khi nhìn thấy quân đội cá»§a ngươi đã bị " "ảnh hưởng bởi sá»± chính đáng cá»§a chính nghÄ©a cá»§a ngươi. Thần dân má»›i trung " "thành đưa cho ngươi túi lưu huỳnh vô tận cá»§a anh ta để giúp đỡ ná»— lá»±c chiến " "tranh." msgid "Endless Vial of Mercury" msgstr "Lá» Thá»§y ngân Vô tận" msgid "The %{name} provides %{count} unit of mercury per day." msgstr "%{name} cung cấp %{count} đơn vị thá»§y ngân má»—i ngày." msgid "" "A brief stop at a hastily abandoned Wizard's tower turns up a magical vial " "of mercury that always has a little left on the bottom. Recognizing a " "treasure when you see one, you cap it and slip it in your pocket." msgstr "" "Khi vá»™i vã dừng chân má»™t chút tại tòa tháp Pháp sư bị bá» hoang, ngươi sẽ " "thấy má»™t lá» thá»§y ngân kỳ diệu luôn còn sót lại má»™t ít ở đáy. Nhận ra má»™t kho " "báu khi ngươi nhìn thấy nó, ngươi đậy nắp nó lại và nhét nó vào túi." msgid "Endless Pouch of Gems" msgstr "Túi Äá quý Vô tận" msgid "The %{name} provides %{count} unit of gems per day." msgstr "%{name} cung cấp %{count} đơn vị đá quý má»—i ngày." msgid "" "A short rainstorm brings forth a rainbow...and you can see the end of it. " "Riding quickly, you seize the pot of gold you find there. The leprechaun who " "owns it, unable to stop you from taking it, offers an endless pouch of gems " "for the return of his gold. You accept." msgstr "" "Má»™t cÆ¡n mưa ngắn ngá»§i sẽ tạo ra cầu vồng...và ngươi có thể thấy được Ä‘iểm " "kết thúc cá»§a nó. Cưỡi ngá»±a nhanh chóng, ngươi nắm bắt được hÅ© vàng tìm thấy " "ở đó. Yêu tinh sở hữu nó, không thể ngăn cản ngươi lấy nó, đưa ra má»™t túi đá " "quý vô tận để trả lại số vàng cá»§a mình. Ngươi chấp nhận." msgid "Endless Cord of Wood" msgstr "Dây Gá»— Vô tận" msgid "The %{name} provides %{count} unit of wood per day." msgstr "%{name} cung cấp %{count} đơn vị gá»— má»—i ngày." msgid "" "Pausing to rest and light a cook fire, you pull wood out of a nearby pile of " "dead wood. As you keep pulling wood from the pile, you notice that it " "doesn't shrink. You realize to your delight that the wood is enchanted, so " "you take it along." msgstr "" "Dừng lại để nghỉ ngÆ¡i và đốt lá»­a nấu ăn, ngươi kéo cá»§i ra khá»i đống gá»— chết " "gần đó. Khi ngươi tiếp tục kéo gá»— ra khá»i đống, ngươi nhận thấy nó không há» " "co lại. Ngươi vui mừng nhận ra rằng gá»— bị mê hoặc nên ngươi mang nó theo." msgid "Endless Cart of Ore" msgstr "Xe Quặng Vô tận" msgid "The %{name} provides %{count} unit of ore per day." msgstr "%{name} cung cấp %{count} đơn vị quặng má»—i ngày." msgid "" "You've found a Goblin weapon smithy making weapons for use against humans. " "With a tremendous yell you and your army descend upon their camp and drive " "them away. A search finds a magic ore cart that never runs out of iron." msgstr "" "Ngươi đã tìm thấy má»™t lò rèn vÅ© khí yêu tinh chế tạo vÅ© khí để sá»­ dụng chống " "lại con ngưá»i. Vá»›i má»™t tiếng hét khá»§ng khiếp, ngươi và quân đội cá»§a ngươi " "tiến vào trại cá»§a há» và đánh Ä‘uổi há» Ä‘i. Má»™t cuá»™c tìm kiếm đã tìm thấy má»™t " "chiếc xe chở quặng ma thuật không bao giá» hết sắt." msgid "Endless Pouch of Crystal" msgstr "Túi Pha lê Vô tận" msgid "The %{name} provides %{count} unit of crystal per day." msgstr "%{name} cung cấp %{count} đơn vị pha lê má»—i ngày." msgid "" "Taking shelter from a storm in a small cave, you notice a small patch of " "crystal in one corner. Curious, you break a piece off and notice that the " "original crystal grows the lost piece back. You decide to stuff the entire " "patch into a pouch and take it with you." msgstr "" "Äang trú ẩn khá»i cÆ¡n bão trong má»™t hang động nhá», ngươi nhận thấy má»™t mảng " "pha lê nhỠở má»™t góc. Tò mò, ngươi bẻ má»™t mảnh ra và nhận thấy rằng viên pha " "lê ban đầu má»c lại mảnh bị mất. Ngươi quyết định nhét toàn bá»™ miếng dán vào " "má»™t cái túi và mang theo bên mình." msgid "Spiked Helm" msgstr "MÅ© Gai" msgid "" "Your army is ambushed by a small tribe of wild (and none too bright) Orcs. " "You fend them off easily and the survivors flee in all directions. One of " "the Orcs was wearing a polished spiked helm. Figuring it will make a good " "souvenir, you take it." msgstr "" "Quân đội cá»§a ngươi bị phục kích bởi má»™t bá»™ tá»™c nhá» Orc hoang dã (và không " "quá sáng sá»§a). Ngươi chống đỡ chúng má»™t cách dá»… dàng và những ngưá»i sống sót " "chạy trốn vá» má»i hướng. Má»™t trong những tên Orc Ä‘ang đội má»™t chiếc mÅ© nhá»n " "sáng bóng. NghÄ© rằng nó sẽ là má»™t món quà lưu niệm hay, ngươi hãy lấy nó." msgid "Spiked Shield" msgstr "Khiên Gai" msgid "" "You come upon a bridge spanning a dry gully. Before you can cross, a Troll " "steps out from under the bridge and demands payment before it will permit " "you to pass. You refuse, and the Troll charges, forcing you to slay it. You " "take its spiked shield as a trophy." msgstr "" "Ngươi Ä‘i đến má»™t cây cầu bắc qua má»™t rãnh nước khô cạn. Trước khi ngươi có " "thể băng qua, má»™t con Troll bước ra từ dưới cầu và yêu cầu thanh toán trước " "khi nó cho phép ngươi Ä‘i qua. Ngươi từ chối, và lÅ© Troll tấn công, buá»™c " "ngươi phải tiêu diệt nó. Ngươi lấy chiếc khiên có gai cá»§a nó làm chiến lợi " "phẩm." msgid "White Pearl" msgstr "Ngá»c trai Trắng" msgid "" "A walk across a dry saltwater lake bed yields an unlikely prize: A white " "pearl amidst shattered shells and debris." msgstr "" "Má»™t chuyến Ä‘i bá»™ qua lòng hồ nước mặn khô sẽ mang lại má»™t giải thưởng khó có " "thể xảy ra: Má»™t viên ngá»c trai trắng giữa những mảnh vá» và mảnh vụn vỡ vụn." msgid "Black Pearl" msgstr "Ngá»c trai Äen" msgid "" "Rumors of a Griffin of unusual size preying upon the countryside lead you to " "its cave lair. A quick, brutal fight dispatches the beast, and a search of " "its foul nest turns up a huge black pearl." msgstr "" "Tin đồn vá» má»™t con Griffin có kích thước bất thưá»ng Ä‘ang săn mồi ở vùng nông " "thôn sẽ dẫn ngươi đến hang ổ cá»§a nó. Má»™t cuá»™c chiến chóng vánh, tàn khốc đã " "tiêu diệt được con thú và khi tìm kiếm trong tổ hôi cá»§a nó, ngưá»i ta tìm " "thấy má»™t viên ngá»c trai Ä‘en khổng lồ." msgid "Magic Book" msgstr "Sách Phép" #, fuzzy msgid "The %{name} enables the hero to cast spells." msgstr "%{name} cho phép ngươi sá»­ dụng phép thuật." msgid "" "A young man approaches you: \"My Lord, allow me to show you my latest " "invention for spreading knowledge!\" You follow the man into his workshop " "and immediately observe a large apparatus with levers and cranks. \"This " "here is it!\" he says eagerly, \"The Printing Press.\" And before you get to " "say a word, he hands you a Magic Book." msgstr "" msgid "Victory can be achieved by finding any Ultimate Artifact." msgstr "" msgid "Dummy 2" msgstr "Bù nhìn 2" msgid "The reserved artifact." msgstr "Hiện vật được bảo lưu." msgid "Dummy 3" msgstr "Bù nhìn 3" msgid "Dummy 4" msgstr "Bù nhìn 4" msgid "Spell Scroll" msgstr "Sách Phép" #, fuzzy msgid "" "This %{name} gives the hero the ability to cast the %{spell} spell if the " "hero has a Magic Book." msgstr "" "%{name} này cung cấp cho tướng cá»§a ngươi khả năng sá»­ dụng phép thuật " "%{spell} nếu cho tướng cá»§a ngươi có Sách Phép." msgid "" "You find an elaborate container which houses an old vellum scroll. The runes " "on the container are very old, and the artistry with which it was put " "together is stunning. As you pull the scroll out, you feel imbued with " "magical power." msgstr "" "Ngươi tìm thấy má»™t chiếc há»™p đựng phức tạp chứa má»™t cuá»™n giấy da cÅ©. Những " "chữ rune trên há»™p đựng đã rất cÅ© và tính nghệ thuật khi ghép chúng lại vá»›i " "nhau thật tuyệt vá»i. Khi ngươi kéo cuá»™n giấy ra, ngươi sẽ cảm thấy tràn ngập " "sức mạnh ma thuật." msgid "Arm of the Martyr" msgstr "Cánh tay Liệt sÄ©" #, fuzzy msgid "" "The %{name} increases the hero's spell power by %{count} but adds the undead " "morale penalty." msgstr "" "%{name} tăng sức mạnh phép thuật cá»§a ngươi thêm %{count} nhưng lại thêm hình " "phạt vá» tinh thần cho xác sống." msgid "" "One of the less intelligent members of your party picks up an arm off of the " "ground. Despite its missing a body, it is still moving. Your troops find the " "dismembered arm repulsive, but you cannot bring yourself to drop it: it " "seems to hold some sort of magical power that influences your decision " "making." msgstr "" "Má»™t trong những thành viên kém thông minh hÆ¡n trong nhóm cá»§a ngươi nhấc má»™t " "cánh tay lên khá»i mặt đất. Mặc dù mất Ä‘i cÆ¡ thể nhưng nó vẫn di chuyển. Quân " "đội cá»§a ngươi nhận thấy cánh tay bị chặt rá»i thật đáng kinh tởm, nhưng ngươi " "không thể tá»± mình đánh rÆ¡i nó: nó dưá»ng như chứa má»™t loại sức mạnh ma thuật " "nào đó ảnh hưởng đến việc đưa ra quyết định cá»§a ngươi." msgid "Breastplate of Anduran" msgstr "Ão giáp cá»§a Anduran" #, fuzzy msgid "The %{name} increases the hero's defense by %{count}." msgstr "%{name} tăng khả năng phòng thá»§ cá»§a ngươi thêm %{count}." msgid "" "You come upon a sign. It reads: \"Here lies the body of Anduran. Bow and " "swear fealty, and you shall be rewarded.\" You decide to do as it says. As " "you stand up, you feel a coldness against your skin. Looking down, you find " "that you are suddenly wearing a gleaming, ornate breastplate." msgstr "" "Ngươi bắt gặp má»™t dấu hiệu. Nó viết: \"Äây là thi thể cá»§a Anduran. Hãy cúi " "đầu và thá» trung thành, và ngươi sẽ được khen thưởng.\" Ngươi quyết định làm " "như nó nói. Khi ngươi đứng lên, ngươi cảm thấy lạnh trên da. Nhìn xuống, " "ngươi chợt nhận ra mình Ä‘ang mặc má»™t tấm giáp ngá»±c được trang trí công phu, " "lấp lánh." msgid "Broach of Shielding" msgstr "Trâm Che chắn" msgid "" "The %{name} provides %{count} percent protection from Armageddon and " "Elemental Storm, but decreases spell power by 2." msgstr "" "%{name} cung cấp khả năng bảo vệ %{count} phần trăm khá»i Tận thế và Nguyên " "tố Bão, nhưng giảm sức mạnh phép thuật Ä‘i 2." msgid "" "A kindly Sorceress thinks that your army's defenses could use a magical " "boost. She offers to enchant the Broach that you wear on your cloak, and you " "accept." msgstr "" "Má»™t Nữ phù thá»§y tốt bụng nghÄ© rằng khả năng phòng thá»§ cá»§a quân đội ngươi có " "thể sá»­ dụng phép thuật tăng cưá»ng. Cô ấy đỠnghị phù phép cho Trâm cài áo " "trên áo choàng và ngươi chấp nhận." msgid "Battle Garb of Anduran" msgstr "Chiến Bào cá»§a Anduran" #, fuzzy msgid "" "The %{name} combines the powers of the three Anduran artifacts. It provides " "maximum luck and morale for the hero's troops and gives the hero the Town " "Portal spell." msgstr "" "%{name} kết hợp sức mạnh cá»§a ba hiện vật Anduran. Nó mang lại may mắn và " "tinh thần tối Ä‘a cho quân đội cá»§a ngươi và mang lại cho ngươi phép Cổng Thị " "trấn." msgid "" "Out of pity for a poor peasant, you purchase a chest of old junk they are " "hawking for too much gold. Later, as you search through it, you find it " "contains the 3 pieces of the legendary battle garb of Anduran!" msgstr "" "Vì thương hại má»™t ngưá»i nông dân nghèo, ngươi mua má»™t chiếc rương cÅ© mà há» " "Ä‘ang bán vá»›i giá quá cao. Sau đó, khi tìm kiếm, ngươi sẽ thấy nó chứa 3 mảnh " "trang phục chiến đấu huyá»n thoại cá»§a Anduran!" msgid "Crystal Ball" msgstr "Quả cầu Pha lê" #, fuzzy msgid "" "The %{name} lets the hero get more specific information about monsters, " "enemy heroes, and castles nearby the hero." msgstr "" "%{name} cho phép ngươi nhận được thông tin cụ thể hÆ¡n vá» quái vật, tướng cá»§a " "kẻ thù và lâu đài gần tướng nắm giữ nó." msgid "" "You come upon a caravan of gypsies who are feasting and fortifying their " "bodies with mead. They call you forward and say \"If you prove that you can " "dance the Rama-Buta, we will reward you.\" You don't know it, but try " "anyway. They laugh hysterically, but admire your bravery, giving you a " "Crystal Ball." msgstr "" "Ngươi bắt gặp má»™t Ä‘oàn lữ hành gồm những ngưá»i gypsies Ä‘ang ăn uống và bồi " "bổ cÆ¡ thể bằng đồng cá». Há» gá»i ngươi vá» phía trước và nói \"Nếu ngươi chứng " "minh được rằng ngươi có thể nhảy Rama-Buta, chúng tôi sẽ thưởng cho ngươi.\" " "Ngươi không biết Ä‘iá»u đó, nhưng dù sao hãy thá»­. Há» cưá»i má»™t cách cuồng loạn " "nhưng lại khâm phục sá»± dÅ©ng cảm cá»§a ngươi, tặng ngươi má»™t Quả cầu Pha lê." msgid "Heart of Fire" msgstr "Trái tim Lá»­a" msgid "" "The %{name} provides %{count} percent protection from fire, but doubles the " "damage taken from cold." msgstr "" "%{name} cung cấp khả năng bảo vệ %{count} phần trăm khá»i lá»­a nhưng tăng gấp " "đôi thiệt hại do lạnh." msgid "" "You enter a recently burned glade and come upon a Fire Elemental sitting " "atop a rock. It looks up, its flaming face contorted in a look of severe " "pain. It then tosses a glowing object at you. You put up your hands to block " "it, but it passes right through them and sears itself into your chest." msgstr "" "Ngươi bước vào má»™t khoảng trống vừa bị đốt cháy và gặp má»™t Nguyên tố Lá»­a " "Ä‘ang ngồi trên má»™t tảng đá. Nó ngước lên, khuôn mặt rá»±c lá»­a cá»§a nó nhăn nhó " "vá»›i vẻ Ä‘au đớn tá»™t độ. Sau đó nó ném má»™t vật thể phát sáng vào ngươi. Ngươi " "giÆ¡ tay lên để chặn nó, nhưng nó xuyên thẳng qua chúng và đâm vào ngá»±c ngươi." msgid "Heart of Ice" msgstr "Trái tim Băng" msgid "" "The %{name} provides %{count} percent protection from cold, but doubles the " "damage taken from fire." msgstr "" "%{name} cung cấp %{count} phần trăm bảo vệ khá»i cái lạnh, nhưng tăng gấp đôi " "thiệt hại do lá»­a gây ra." msgid "" "Suddenly, a biting coldness engulfs your body. You seize up, falling from " "your horse. The pain subsides, but you still feel as if your chest is " "frozen. As you pick yourself up off of the ground, you hear hearty laughter. " "You turn around just in time to see a Frost Giant run off into the woods and " "disappear." msgstr "" "Äá»™t nhiên, má»™t cảm giác lạnh buốt bao trùm lấy cÆ¡ thể ngươi. Ngươi đứng dậy, " "ngã ngá»±a. CÆ¡n Ä‘au giảm dần nhưng ngươi vẫn cảm thấy như ngá»±c mình bị đóng " "băng. Khi nhấc mình lên khá»i mặt đất, ngươi nghe thấy tiếng cưá»i sảng khoái. " "Ngươi quay lại đúng lúc để thấy Frost Giant chạy vào rừng và biến mất." msgid "Helmet of Anduran" msgstr "MÅ© cá»§a Anduran" msgid "" "You spy a gleaming object poking up out of the ground. You send a member of " "your party over to investigate. He comes back with a golden helmet in his " "hands. You realize that it must be the helmet of the legendary Anduran, the " "only man who was known to wear solid gold armor." msgstr "" "Ngươi phát hiện má»™t vật thể lấp lánh nhô lên khá»i mặt đất. Ngươi gá»­i má»™t " "thành viên trong nhóm cá»§a ngươi đến để Ä‘iá»u tra. Anh ta quay lại vá»›i chiếc " "mÅ© bảo hiểm vàng trên tay. Ngươi nhận ra rằng đó hẳn là chiếc mÅ© bảo hiểm " "cá»§a Anduran huyá»n thoại, ngưá»i đàn ông duy nhất được biết đến vá»›i bá»™ áo giáp " "bằng vàng nguyên khối." msgid "Holy Hammer" msgstr "Búa Thánh" msgid "" "You come upon a battle where a Paladin has been mortally wounded by a group " "of Zombies. He asks you to take his hammer and finish what he started. As " "you pick it up, it begins to hum, and then everything becomes a blur. The " "Zombies lie dead, the hammer dripping with blood. You strap it to your belt." msgstr "" "Ngươi bắt gặp má»™t trận chiến nÆ¡i má»™t Paladin bị trá»ng thương bởi má»™t nhóm " "Zombie. Anh ta yêu cầu ngươi lấy chiếc búa cá»§a anh ta và hoàn thành những gì " "anh ta đã bắt đầu. Khi ngươi nhặt nó lên, nó bắt đầu kêu vo vo và sau đó má»i " "thứ trở nên mỠảo. LÅ© Zombie nằm chết, chiếc búa rỉ máu. Ngươi buá»™c nó vào " "thắt lưng cá»§a ngươi." msgid "Legendary Scepter" msgstr "Vương trượng Huyá»n thoại" msgid "The %{name} adds %{count} points to all attributes." msgstr "%{name} thêm %{count} Ä‘iểm cho tất cả các thuá»™c tính." msgid "" "Upon cresting a small hill, you come upon a ridiculous looking sight. A " "Sprite is attempting to carry a Scepter that is almost as big as it is. " "Trying not to laugh, you ask, \"Need help?\" The Sprite glares at you and " "answers: \"You think this is funny? Fine. You can carry it. I much prefer " "flying anyway.\"" msgstr "" "Khi leo lên má»™t ngá»n đồi nhá», ngươi sẽ bắt gặp má»™t cảnh tượng trông thật lố " "bịch. Má»™t Sprite Ä‘ang cố gắng mang theo má»™t Scepter to gần bằng nó. Cố gắng " "không cưá»i, ngươi há»i: \"Cần giúp đỡ không?\" Sprite trừng mắt nhìn ngươi và " "trả lá»i: \"ngươi nghÄ© Ä‘iá»u này thật buồn cưá»i? Tốt thôi. Ngươi có thể mang " "nó. Dù sao thì tôi cÅ©ng thích bay hÆ¡n.\"" msgid "Masthead" msgstr "Tiêu Ä‘á»" #, fuzzy msgid "" "The %{name} boosts the hero's troops' luck and morale by %{count} each in " "sea combat." msgstr "" "%{name} tăng cưá»ng may mắn và tinh thần cá»§a ngươi thêm %{count} trong trận " "chiến trên biển." msgid "" "An old seaman tells you a tale of an enchanted masthead that he used in his " "youth to rally his crew during times of trouble. He then hands you a faded " "map that shows where he hid it. After much exploring, you find it stashed " "underneath a nearby dock." msgstr "" "Má»™t thá»§y thá»§ già kể cho ngươi nghe câu chuyện vá» má»™t chiếc cá»™t buồm bị phù " "phép mà ông đã sá»­ dụng khi còn trẻ để tập hợp thá»§y thá»§ Ä‘oàn cá»§a mình trong " "thá»i Ä‘iểm khó khăn. Sau đó anh ta đưa cho ngươi má»™t tấm bản đồ đã má» cho " "thấy nÆ¡i anh ta giấu nó. Sau nhiá»u lần khám phá, ngươi thấy nó được giấu bên " "dưới má»™t bến tàu gần đó." msgid "Sphere of Negation" msgstr "Quả cầu Phá»§ định" msgid "The %{name} disables all spell casting, for both sides, in combat." msgstr "" "%{name} vô hiệu hóa tất cả các phép thuật sá»­ dụng cho cả hai bên trong chiến " "đấu." msgid "" "You stop to help a Peasant catch a runaway mare. To show his gratitude, he " "hands you a tiny sphere. As soon as you grasp it, you feel the magical " "energy drain from your limbs..." msgstr "" "Ngươi dừng lại để giúp má»™t ngưá»i Nông dân bắt má»™t con ngá»±a cái Ä‘ang chạy " "trốn. Äể tá» lòng biết Æ¡n, anh ấy đưa cho ngươi má»™t quả cầu nhá». Ngay khi " "ngươi nắm lấy nó, ngươi sẽ cảm thấy năng lượng ma thuật rút cạn khá»i tay " "chân mình..." msgid "Staff of Wizardry" msgstr "Gậy Phù thá»§y" #, fuzzy msgid "The %{name} boosts the hero's spell power by %{count}." msgstr "%{name} tăng sức mạnh phép thuật cá»§a ngươi thêm %{count}." msgid "" "While out scaring up game, your troops find a mysterious staff levitating " "about three feet off of the ground. They hand it to you, and you notice an " "inscription. It reads: \"Brains best brawn and magic beats might. Heed my " "words, and you'll win every fight.\"" msgstr "" "Trong khi Ä‘ang hù dá»a trò chÆ¡i, quân cá»§a ngươi tìm thấy má»™t cây trượng bí ẩn " "Ä‘ang bay cách mặt đất khoảng 1 mét. HỠđưa nó cho ngươi và ngươi nhận thấy " "má»™t dòng chữ. Nó viết: \"Bá»™ não có sức mạnh tốt nhất và nhịp đập ma thuật. " "Hãy chú ý đến lá»i nói cá»§a tôi và ngươi sẽ thắng má»i cuá»™c chiến.\"" msgid "Sword Breaker" msgstr "Kẻ phá Kiếm" #, fuzzy msgid "The %{name} increases the hero's defense by %{count} and attack by 1." msgstr "" "%{name} tăng khả năng phòng thá»§ cá»§a ngươi thêm %{count} và tấn công thêm 1." msgid "" "A former Captain of the Guard admires your quest and gives you the enchanted " "Sword Breaker that he relied on during his tour of duty." msgstr "" "Má»™t cá»±u Äá»™i trưởng Äá»™i cận vệ ngưỡng má»™ nhiệm vụ cá»§a ngươi và trao cho ngươi " "Kẻ phá Kiếm đầy mê hoặc mà anh ta đã dá»±a vào trong chuyến công tác cá»§a mình." msgid "Sword of Anduran" msgstr "Kiếm cá»§a Anduran" msgid "" "A Troll stops you and says: \"Pay me 5,000 gold, or the Sword of Anduran " "will slay you where you stand.\" You refuse. The troll grabs the sword " "hanging from its belt, screams in pain, and runs away. Picking up the fabled " "sword, you give thanks that half-witted Trolls tend to grab the wrong end of " "sharp objects." msgstr "" "Má»™t con Quá»· lùn ngăn ngươi lại và nói: \"Trả cho tôi 5.000 vàng, nếu không " "Thanh kiếm Anduran sẽ giết ngươi ngay tại chá»—.\" Ngươi từ chối. Con quá»· lùn " "chá»™p lấy thanh kiếm treo trên thắt lưng, hét lên Ä‘au đớn rồi bá» chạy. Nhặt " "thanh kiếm huyá»n thoại, ngươi tạ Æ¡n vì lÅ© Quá»· lùn ná»­a vá»i có xu hướng tóm " "nhầm đầu cá»§a những vật sắc nhá»n." msgid "Spade of Necromancy" msgstr "Thuổng cá»§a Chiêu hồn" #, fuzzy msgid "The %{name} gives the hero increased necromancy skill." msgstr "%{name} giúp ngươi tăng kỹ năng chiêu hồn." msgid "" "A dirty shovel has been thrust into a dirt mound nearby. Upon investigation, " "you discover it to be the enchanted shovel of the Gravediggers, long thought " "lost by mortals." msgstr "" "Má»™t chiếc xẻng bẩn đã được đẩy vào má»™t ụ đất gần đó. Sau khi Ä‘iá»u tra, ngươi " "phát hiện ra đó là chiếc xẻng bị phù phép cá»§a Gravediggers, ngưá»i phàm tưởng " "đã thất lạc từ lâu." msgid "spellBonus|selected by user" msgstr "chá»n bởi ngưá»i dùng" msgid "Wood" msgstr "Gá»—" msgid "Mercury" msgstr "Thá»§y ngân" msgid "Ore" msgstr "Äá" msgid "Sulfur" msgstr "Lưu huỳnh" msgid "Crystal" msgstr "Thạch anh" msgid "Gems" msgstr "Ngá»c" msgid "Gold" msgstr "Vàng" msgid "" "There are seven resources in Heroes 2, used to build and improves castles, " "purchase troops and recruit heroes. Gold is the most common, required for " "virtually everything. Wood and ore are used for most buildings. Gems, " "Mercury, Sulfur and Crystal are rare magical resources used for the most " "powerful creatures and buildings." msgstr "" "Có bảy tài nguyên trong Heroes 2, được sá»­ dụng để xây dá»±ng và cải thiện lâu " "đài, mua quân và chiêu má»™ anh hùng. Vàng là thứ phổ biến nhất, cần thiết cho " "hầu hết má»i thứ. Gá»— và quặng được sá»­ dụng cho hầu hết các tòa nhà. Ngá»c, " "Thá»§y ngân, Lưu huỳnh và Pha lê là những tài nguyên ma thuật quý hiếm được sá»­ " "dụng cho những sinh vật và công trình mạnh mẽ nhất." msgid "" "Causes a giant fireball to strike the selected area, damaging all nearby " "creatures." msgstr "" "Tạo ra má»™t quả cầu lá»­a khổng lồ tấn công khu vá»±c đã chá»n, gây sát thương cho " "tất cả sinh vật gần đó." msgid "Fireball" msgstr "Cầu lá»­a" msgid "Fireblast" msgstr "Vụ nổ lá»­a" msgid "" "An improved version of fireball, fireblast affects two hexes around the " "center point of the spell, rather than one." msgstr "" "Má»™t phiên bản cải tiến cá»§a quả cầu lá»­a, vụ nổ lá»­a ảnh hưởng đến hai hình lục " "giác xung quanh Ä‘iểm trung tâm cá»§a câu thần chú, thay vì má»™t." msgid "Causes a bolt of electrical energy to strike the selected creature." msgstr "Tạo ra má»™t tia năng lượng Ä‘iện tấn công sinh vật được chá»n." msgid "Lightning Bolt" msgstr "Tia chá»›p" msgid "Chain Lightning" msgstr "Sét chuyá»n" msgid "" "Causes a bolt of electrical energy to strike a selected creature, then " "strike the nearest creature with half damage, then strike the NEXT nearest " "creature with half again damage, and so on, until it becomes too weak to be " "harmful. Warning: This spell can hit your own creatures!" msgstr "" "Tạo ra má»™t tia năng lượng Ä‘iện để tấn công má»™t sinh vật đã chá»n, sau đó tấn " "công sinh vật gần nhất vá»›i má»™t ná»­a sát thương, sau đó tấn công sinh vật gần " "nhất TIẾP THEO vá»›i má»™t ná»­a sát thương, v.v., cho đến khi nó trở nên quá yếu " "để có thể gây hại. Cảnh báo: Phép thuật này có thể tấn công sinh vật cá»§a " "chính ngươi!" msgid "Teleport" msgstr "Dịch chuyển" msgid "" "Teleports the creature you select to any open position on the battlefield." msgstr "" "Dịch chuyển sinh vật ngươi chá»n đến bất kỳ vị trí mở nào trên chiến trưá»ng." msgid "Cure" msgstr "Chữa trị" msgid "" "Removes all negative spells cast upon one of your units, and restores up to " "%{count} HP per level of spell power." msgstr "" "Loại bá» tất cả các phép thuật tiêu cá»±c được sá»­ dụng trên má»™t trong các đơn " "vị cá»§a ngươi và phục hồi tối Ä‘a %{count} HP cho má»—i cấp độ sức mạnh phép " "thuật." msgid "Mass Cure" msgstr "Chữa trị Rá»™ng" msgid "" "Removes all negative spells cast upon your forces, and restores up to " "%{count} HP per level of spell power, per creature." msgstr "" "Loại bá» tất cả các phép thuật tiêu cá»±c tác dụng lên lá»±c lượng cá»§a ngươi và " "phục hồi tối Ä‘a %{count} HP cho má»—i cấp sức mạnh phép thuật, cho má»—i sinh " "vật." msgid "Resurrect" msgstr "Hồi sinh" msgid "Resurrects creatures from a damaged or dead unit until end of combat." msgstr "" "Hồi sinh các sinh vật từ đơn vị bị thương tật hoặc chết cho đến khi kết thúc " "trận chiến." msgid "Resurrect True" msgstr "Hồi sinh Thá»±c" msgid "Resurrects creatures from a damaged or dead unit permanently." msgstr "Phục hồi vÄ©nh viá»…n các sinh vật từ má»™t đơn vị bị thương tật hoặc chết." msgid "Haste" msgstr "Tăng tốc" msgid "Increases the speed of any creature by %{count}." msgstr "Tăng tốc độ cá»§a bất kỳ sinh vật nào thêm %{count}." msgid "Increases the speed of all of your creatures by %{count}." msgstr "Tăng tốc độ cá»§a tất cả sinh vật cá»§a ngươi thêm %{count}." msgid "Mass Haste" msgstr "Tăng tốc Rá»™ng" msgid "Slows target to half movement rate." msgstr "Làm chậm mục tiêu xuống má»™t ná»­a tốc độ di chuyển." msgid "spell|Slow" msgstr "Chậm" msgid "Mass Slow" msgstr "Chậm Rá»™ng" msgid "Slows all enemies to half movement rate." msgstr "Làm chậm tất cả kẻ địch xuống má»™t ná»­a tốc độ di chuyển." msgid "spell|Blind" msgstr "Mù" #, fuzzy msgid "" "Clouds the affected creatures' eyes, preventing them from moving and reduces " "the damage when retaliating by %{count} percent." msgstr "Che má» mắt cá»§a sinh vật bị ảnh hưởng, ngăn chúng di chuyển." msgid "Bless" msgstr "Cầu nguyện" msgid "Causes the selected creatures to inflict maximum damage." msgstr "Khiến các sinh vật được chá»n gây sát thương tối Ä‘a." msgid "Causes all of your units to inflict maximum damage." msgstr "Khiến tất cả các đơn vị cá»§a ngươi gây sát thương tối Ä‘a." msgid "Mass Bless" msgstr "Cầu nguyện Rá»™ng" msgid "Magically increases the defense skill of the selected creatures." msgstr "Tăng kỹ năng phòng thá»§ cá»§a các sinh vật được chá»n má»™t cách kỳ diệu." msgid "Stoneskin" msgstr "Thạch bì" msgid "Steelskin" msgstr "Da sắt" msgid "" "Increases the defense skill of the targeted creatures. This is an improved " "version of Stoneskin." msgstr "" "Tăng kỹ năng phòng thá»§ cá»§a các sinh vật được nhắm mục tiêu. Äây là phiên bản " "cải tiến cá»§a Thạch Bì." msgid "Causes the selected creatures to inflict minimum damage." msgstr "Khiến các sinh vật được chá»n gây ra thiệt hại tối thiểu." msgid "Curse" msgstr "Nguyá»n rá»§a" msgid "Causes all enemy troops to inflict minimum damage." msgstr "Khiến tất cả quân địch gây sát thương tối thiểu." msgid "Mass Curse" msgstr "Nguyá»n rá»§a Rá»™ng" msgid "Damages all undead in the battle." msgstr "Gây sát thương cho tất cả xác sống trong trận chiến." msgid "Holy Word" msgstr "Thánh Ngữ" msgid "" "Damages all undead in the battle. This is an improved version of Holy Word." msgstr "" "Gây sát thương cho tất cả xác sống trong trận chiến. Äây là phiên bản cải " "tiến cá»§a Thánh Ngữ." msgid "Holy Shout" msgstr "Thánh Hét" msgid "Anti-Magic" msgstr "Phản Phép" #, fuzzy msgid "Prevents any magic against the selected creatures." msgstr "Ngăn chặn phép thuật có hại chống lại các sinh vật được chá»n." msgid "Dispel Magic" msgstr "Trừ Tà" msgid "Removes all magic spells from a single target." msgstr "Loại bá» tất cả phép thuật khá»i má»™t mục tiêu." msgid "Mass Dispel" msgstr "Trừ tà Rá»™ng" msgid "Removes all magic spells from all creatures." msgstr "Loại bá» tất cả các phép thuật từ tất cả các sinh vật." msgid "Causes a magic arrow to strike the selected target." msgstr "Tạo ra má»™t mÅ©i tên ma thuật tấn công mục tiêu đã chá»n." msgid "Magic Arrow" msgstr "MÅ©i tên Ma thuật" msgid "Berserker" msgstr "Kẻ Ä‘iên" msgid "Causes a creature to attack its nearest neighbor." msgstr "Khiến má»™t sinh vật tấn công ngưá»i hàng xóm gần nhất cá»§a nó." msgid "Armageddon" msgstr "Tận thế" msgid "" "Holy terror strikes the battlefield, causing severe damage to all creatures." msgstr "" "Thánh kinh khá»§ng bố tấn công chiến trưá»ng, gây ra thiệt hại nặng ná» cho má»i " "sinh vật." msgid "Elemental Storm" msgstr "Nguyên tố Bão" msgid "Magical elements pour down on the battlefield, damaging all creatures." msgstr "" "Các yếu tố ma thuật đổ xuống chiến trưá»ng, gây sát thương cho má»i sinh vật." msgid "" "A rain of rocks strikes an area of the battlefield, damaging all nearby " "creatures." msgstr "" "Má»™t cÆ¡n mưa đá tấn công má»™t khu vá»±c trên chiến trưá»ng, gây sát thương cho " "tất cả sinh vật gần đó." msgid "Meteor Shower" msgstr "Mưa Sao băng" msgid "Paralyze" msgstr "Hóa đá" msgid "The targeted creatures are paralyzed, unable to move or retaliate." msgstr "Các sinh vật mục tiêu bị tê liệt, không thể di chuyển hoặc phản kháng." msgid "Hypnotize" msgstr "Thôi miên" msgid "" "Brings a single enemy unit under your control if its hits are less than " "%{count} times the caster's spell power." msgstr "" "ÄÆ°a má»™t đơn vị kẻ thù vào tầm kiểm soát cá»§a ngươi nếu số lần tấn công cá»§a nó " "nhá» hÆ¡n %{count} lần sức mạnh phép thuật cá»§a ngưá»i thi triển." msgid "Cold Ray" msgstr "Tia Lạnh" msgid "Drains body heat from a single enemy unit." msgstr "Hút nhiệt cÆ¡ thể từ má»™t đơn vị kẻ địch." msgid "Cold Ring" msgstr "Vòng Lạnh" msgid "" "Drains body heat from all units surrounding the center point, but not " "including the center point." msgstr "" "Thoát nhiệt cÆ¡ thể từ tất cả các đơn vị xung quanh Ä‘iểm trung tâm, nhưng " "không bao gồm Ä‘iểm trung tâm." msgid "Disrupting Ray" msgstr "Tia Phá vỡ" msgid "Reduces the defense rating of an enemy unit by three." msgstr "Giảm chỉ số phòng thá»§ cá»§a đơn vị địch xuống ba." msgid "Damages all living (non-undead) units in the battle." msgstr "" "Gây sát thương cho tất cả các đơn vị sống (không phải xác sống) trong trận " "chiến." msgid "Death Ripple" msgstr "Gợn sóng Chết" msgid "Death Wave" msgstr "Sóng Chết" msgid "" "Damages all living (non-undead) units in the battle. This spell is an " "improved version of Death Ripple." msgstr "" "Gây sát thương cho tất cả các đơn vị sống (không phải xác sống) trong trận " "chiến. Phép thuật này là phiên bản cải tiến cá»§a Gợn sóng Chết." msgid "Dragon Slayer" msgstr "Kẻ giết Rồng" msgid "Greatly increases a unit's attack skill vs. Dragons." msgstr "Tăng đáng kể kỹ năng tấn công cá»§a đơn vị so vá»›i Rồng." msgid "Blood Lust" msgstr "Khát máu" msgid "Increases a unit's attack skill." msgstr "Tăng kỹ năng tấn công cá»§a má»™t đơn vị." msgid "Animate Dead" msgstr "Sức sống Thần chết" msgid "Resurrects creatures from a damaged or dead undead unit permanently." msgstr "" "Phục hồi vÄ©nh viá»…n các sinh vật từ má»™t đơn vị xác sống bị hư há»ng hoặc đã " "chết." msgid "Mirror Image" msgstr "Ảnh Gương" msgid "" "Creates an illusionary unit that duplicates one of your existing units. This " "illusionary unit does the same damages as the original, but will vanish if " "it takes any damage." msgstr "" "Tạo má»™t đơn vị ảo ảnh sao chép má»™t trong các đơn vị hiện có cá»§a ngươi. ÄÆ¡n " "vị ảo ảnh này gây sát thương tương tá»± như ban đầu, nhưng sẽ biến mất nếu " "nhận bất kỳ thiệt hại nào." msgid "Shield" msgstr "Khiên" msgid "" "Halves damage received from ranged attacks for a single unit. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Giảm má»™t ná»­a sát thương nhận được từ các đòn tấn công tầm xa cho má»™t đơn vị. " "Không ảnh hưởng đến sát thương nhận được từ Tháp pháo hoặc Cung máy." msgid "Mass Shield" msgstr "Khiên Rá»™ng" msgid "" "Halves damage received from ranged attacks for all of your units. Does not " "affect damage received from Turrets or Ballistae." msgstr "" "Giảm má»™t ná»­a sát thương nhận được từ các cuá»™c tấn công tầm xa cho tất cả các " "đơn vị cá»§a ngươi. Không ảnh hưởng đến sát thương nhận được từ Tháp pháo hoặc " "Cung máy." msgid "Summon Earth Elemental" msgstr "Triệu hồi Nguyên tố Äất" msgid "Summons Earth Elementals to fight for your army." msgstr "Triệu hồi Nguyên tố Äất tá»›i để chiến đấu cho quân đội ngươi." msgid "Summon Air Elemental" msgstr "Triệu hồi Nguyên tố Khí" msgid "Summons Air Elementals to fight for your army." msgstr "Triệu hồi Nguyên tố Khí tá»›i để chiến đấu cho quân đội ngươi." msgid "Summon Fire Elemental" msgstr "Triệu hồi Nguyên tố Lá»­a" msgid "Summons Fire Elementals to fight for your army." msgstr "Triệu hồi Nguyên tố Lá»­a tá»›i để chiến đấu cho quân đội ngươi." msgid "Summon Water Elemental" msgstr "Triệu hồi Nguyên tố Nước" msgid "Summons Water Elementals to fight for your army." msgstr "Triệu hồi Nguyên tố Nước tá»›i để chiến đấu cho quân đội ngươi." msgid "Damages castle walls." msgstr "Sát thương tưá»ng lâu đài." msgid "Earthquake" msgstr "Äá»™ng đất" msgid "Causes all mines across the land to become visible." msgstr "Làm cho tất cả các má» trên đất liá»n hiện rõ." msgid "View Mines" msgstr "Xem Má»" msgid "Causes all resources across the land to become visible." msgstr "Làm cho tất cả các tài nguyên trên đất liá»n trở nên hữu hình." msgid "View Resources" msgstr "Xem Tài nguyên" msgid "Causes all artifacts across the land to become visible." msgstr "Làm cho tất cả hiện vật trên khắp vùng đất có thể nhìn thấy được." msgid "View Artifacts" msgstr "Xem Bảo vật" msgid "Causes all towns and castles across the land to become visible." msgstr "Làm cho tất cả các thị trấn và lâu đài trên khắp vùng đất hiện rõ." msgid "View Towns" msgstr "Xem Thị trấn" msgid "Causes all Heroes across the land to become visible." msgstr "Làm cho tất cả các Anh hùng trên khắp vùng đất trở nên hữu hình." msgid "View Heroes" msgstr "Xem Tướng" msgid "Causes the entire land to become visible." msgstr "Làm cho toàn bá»™ vùng đất trở nên hữu hình." msgid "View All" msgstr "Xem Tất cả" msgid "Allows the caster to view detailed information on enemy Heroes." msgstr "Cho phép ngưá»i thi triển xem thông tin chi tiết vá» Tướng địch." msgid "Summon Boat" msgstr "Triệu hồi Thuyá»n" msgid "" "Summons the nearest unoccupied, friendly boat to an adjacent shore location. " "A friendly boat is one which you just built or were the most recent player " "to occupy." msgstr "" "Triệu tập chiếc thuyá»n thân thiện, trống gần nhất đến vị trí bá» biển liá»n " "ká». Má»™t chiếc thuyá»n thân thiện là chiếc thuyá»n mà ngươi vừa đóng hoặc là " "ngưá»i chÆ¡i gần đây nhất chiếm giữ." msgid "Allows the caster to magically transport to a nearby location." msgstr "" "Cho phép ngưá»i sá»­ dụng dịch chuyển má»™t cách kỳ diệu đến má»™t địa Ä‘iểm gần đó." msgid "Dimension Door" msgstr "Cá»­a Kích thước" msgid "Returns the caster to any town or castle currently owned." msgstr "" "Trả ngưá»i Ä‘iá»u khiển vá» bất kỳ thị trấn hoặc lâu đài nào hiện Ä‘ang sở hữu." msgid "Town Gate" msgstr "Cổng Thành" msgid "" "Returns the hero to the town or castle of choice, provided it is controlled " "by you." msgstr "" "ÄÆ°a anh hùng trở lại thị trấn hoặc lâu đài mà ngươi lá»±a chá»n, miá»…n là nó do " "ngươi Ä‘iá»u khiển." msgid "Visions" msgstr "Thấu thị" msgid "" "Visions predicts the likely outcome of an encounter with a neutral army camp." msgstr "" "Thấu thị dá»± Ä‘oán kết quả có thể xảy ra cá»§a cuá»™c chạm trán vá»›i trại quân " "trung lập." msgid "Haunt" msgstr "Ma ám" msgid "" "Haunts a mine you control with Ghosts. This mine stops producing resources. " "(If I can't keep it, nobody will!)" msgstr "" "Ãm má»™t má» mà ngươi Ä‘iá»u khiển bằng Bóng ma. Má» này ngừng sản xuất tài " "nguyên. (Nếu tôi không giữ được thì sẽ không có ai giữ được!)" msgid "Set Earth Guardian" msgstr "Äặt Ngưá»i bảo vệ Äất" msgid "Sets Earth Elementals to guard a mine against enemy armies." msgstr "Äặt các Nguyên tố Äất để bảo vệ má» chống lại quân địch." msgid "Set Air Guardian" msgstr "Äặt Ngưá»i bảo vệ Khí" msgid "Sets Air Elementals to guard a mine against enemy armies." msgstr "Äặt các Nguyên tố Khí để bảo vệ má» chống lại quân địch." msgid "Set Fire Guardian" msgstr "Äặt Ngưá»i bảo vệ Lá»­a" msgid "Sets Fire Elementals to guard a mine against enemy armies." msgstr "Äặt các Nguyên tố Lá»­a để bảo vệ má» chống lại quân địch." msgid "Set Water Guardian" msgstr "Äặt Ngưá»i bảo vệ Nước" msgid "Sets Water Elementals to guard a mine against enemy armies." msgstr "Äặt các Nguyên tố Nước để bảo vệ má» chống lại quân địch." msgid "Random Spell" msgstr "Ngẫu nhiên Phép" msgid "Randomly selected spell of any level." msgstr "Ngẫu nhiên lá»±a chá»n phép cá»§a các cấp." msgid "Random 1st Level Spell" msgstr "Ngẫu nhiên Phép Cấp 1" msgid "Randomly selected 1st level spell." msgstr "Ngẫu nhiên lá»±a chá»n pháp cấp 1." msgid "Random 2nd Level Spell" msgstr "Ngẫu nhiên Phép Cấp 2" msgid "Randomly selected 2nd level spell." msgstr "Ngẫu nhiên lá»±a chá»n pháp cấp 2." msgid "Random 3rd Level Spell" msgstr "Ngẫu nhiên Phép Cấp 3" msgid "Randomly selected 3rd level spell." msgstr "Ngẫu nhiên lá»±a chá»n pháp cấp 3." msgid "Random 4th Level Spell" msgstr "Ngẫu nhiên Phép Cấp 4" msgid "Randomly selected 4th level spell." msgstr "Ngẫu nhiên lá»±a chá»n pháp cấp 4." msgid "Random 5th Level Spell" msgstr "Ngẫu nhiên Phép Cấp 5" msgid "Randomly selected 5th level spell." msgstr "Ngẫu nhiên lá»±a chá»n pháp cấp 5." msgid "Petrification" msgstr "Hóa đá" msgid "" "Turns the affected creature into stone. A petrified creature receives half " "damage from a direct attack." msgstr "" "Biến sinh vật bị ảnh hưởng thành đá. Má»™t sinh vật hóa đá nhận má»™t ná»­a sát " "thương từ đòn tấn công trá»±c tiếp." msgid "You have no Magic Book, so you cannot cast a spell." msgstr "Ngươi không có Sách Phép, nên ngươi không thể niệm chú má»™t phép." msgid "No spell to cast." msgstr "Không có phép để niệm." #, fuzzy msgid "Your hero has %{sp} spell points remaining out of %{max}." msgstr "Tướng cá»§a ngươi còn có %{point} Ä‘iểm phép." msgid "View Adventure Spells" msgstr "Xem Phép Phiêu lưu" msgid "View Combat Spells" msgstr "Xem Phép Chiến đấu" msgid "View previous page" msgstr "Xem trang trước" msgid "View next page" msgstr "Xem trang sau" msgid "Close Spellbook" msgstr "Gấp sách phép" msgid "View %{spell}" msgstr "Xem %{spell}" msgid "This spell does %{damage} points of damage." msgstr "Phép thuật này gây %{damage} Ä‘iểm sát thương." msgid "" "This spell summons\n" "%{count} %{monster}." msgstr "" "Phép thuật này triệu hồi\n" "%{count} %{monster}." msgid "This spell restores %{hp} HP." msgstr "Phép thuật này hồi phục %{hp} MÃU." msgid "This spell summons %{count} %{monster} to guard the mine." msgstr "Phép thuật này triệu hồi %{count} %{monster} tá»›i canh má»." msgid "The nearest town is %{town}." msgstr "Thị trấn gần nhất là %{town}." msgid "This town is occupied by your hero %{hero}." msgstr "Thị trấn này đã bị tướng cá»§a ngươi chiếm đóng %{hero}." msgid "" "This spell controls up to\n" "%{hp} HP." msgstr "" "Phép thuật này Ä‘iá»u khiển tá»›i\n" "%{hp} MÃU." msgid "The ultimate artifact is really the %{name}." msgstr "Bảo vật tối thượng có tên thật là %{name}." msgid "The ultimate artifact may be found in the %{name} regions of the world." msgstr "Bảo vật tối thượng có thể tìm thấy ở vùng %{name} cá»§a thế giá»›i." msgid "north-west" msgstr "tây-bắc" msgid "north" msgstr "bắc" msgid "north-east" msgstr "đông-bắc" msgid "west" msgstr "tây" msgid "center" msgstr "trung tâm" msgid "east" msgstr "đông" msgid "south-west" msgstr "tây-nam" msgid "south" msgstr "nam" msgid "south-east" msgstr "đông-nam" msgid "The truth is out there." msgstr "Sá»± thật ngay ngoài kia." msgid "The dark side is stronger." msgstr "Lá»±c lượng bóng tối Ä‘ang lá»›n mạnh." msgid "The end of the world is near." msgstr "Kết thúc cá»§a thế giá»›i Ä‘ang đến gần." msgid "The bones of Lord Slayer are buried in the foundation of the arena." msgstr "Xương cá»§a Giết Chúa chôn vùi dưới móng cá»§a đấu trưá»ng." msgid "A Black Dragon will take out a Titan any day of the week." msgstr "Rồng Äen sẽ mang Khổng Lồ bất cứ ngày nào trong ngày." msgid "He told her: Yada yada yada... and then she said: Blah, blah, blah..." msgstr "" "á»”ng nói vá»›i bả: Yada yada yada... và sau đó bả nói: Blah, blah, blah..." msgid "An unknown force is being resurrected..." msgstr "Má»™t lá»±c lượng bóng tối Ä‘ang hồi sinh..." msgid "" "Check the newest version of the game at\n" "https://github.com/ihhub/\n" "fheroes2/releases" msgstr "" "Kiểm tra phiên bản má»›i nhất cá»§a trò chÆ¡i tại\n" "https://github.com/ihhub/\n" "fheroes2/releases" #~ msgid "Select count %{resource}:" #~ msgstr "Chá»n số lượng %{resource}:" #~ msgid "Enable auto combat" #~ msgstr "Kích hoạt tá»± động chiến đấu" #~ msgid "hotkey|finish the battle in auto mode" #~ msgstr "kết thúc trận chiến vá»›i chế độ tá»± động" #~ msgid "Please Remember" #~ msgstr "Hãy Nhá»›" #~ msgid "" #~ "You can always change the language, resolution and settings of the game " #~ "by clicking on the " #~ msgstr "Ngươi có thể thay đổi độ phân giải bằng cách nhấp vào " #~ msgid "door" #~ msgstr "cá»­a" #~ msgid " on the left side of the Main Menu, or with the " #~ msgstr " ở bên phía trái cá»§a Trình đơn Chính, hoặc vá»›i " #~ msgid " button from the " #~ msgstr " nút từ " #~ msgid "NEW GAME" #~ msgstr "TRÃ’ CHÆ I MỚI" #~ msgid "" #~ " menu. \n" #~ "\n" #~ "Enjoy the game!" #~ msgstr "" #~ " trình đơn.\n" #~ "\n" #~ "Hãy thưởng thức trò chÆ¡i!" #~ msgid "Warning!" #~ msgstr "Cảnh báo!" #~ msgid "Dummy 1" #~ msgstr "Bù nhìn 1" fheroes2-1.1.6+dfsg/files/soundfonts/000077500000000000000000000000001476115357100174715ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/soundfonts/GeneralUser-GS-LICENSE.txt000066400000000000000000000042631476115357100240420ustar00rootroot00000000000000*** GeneralUser GS v1.471 *** *** License v2.0 *** ** License of the complete work ** You may use GeneralUser GS without restriction for your own music creation, private or commercial. This SoundFont bank is provided to the community free of charge. Please feel free to use it in your software projects, and to modify the SoundFont bank or its packaging to suit your needs. ** License of contained samples ** GeneralUser GS inherits the usage rights of the samples contained within, all of which allow full use in music production, including the ability to make profit from musical recordings created with GeneralUser GS. Many of the samples are original, but some were taken from other banks freely (and legally) available on the Internet from various SoundFont websites. Because GeneralUser GS originated as a personal project with no intention for publication, I cannot be 100% sure where all of the samples originated, although I do know that none of them came from commercially published SoundFont packages or sample CDs. Regardless, many "free" SoundFonts available on the web may indeed contain samples of questionable origin. My understanding of the copyrights of all samples is only as good as the information provided by the original sources. If you become aware of any restricted samples being used in GeneralUser GS, please let me know so I can replace them. This uncertainty may concern you if you intend to use GeneralUser GS in a commercial software product. That being said, I have never received any complaint regarding sample ownership since I published the original GeneralUser GS back in 2000, and as far as I am aware, neither have any of the companies creating commercial software products using GeneralUser GS. ** More info ** If you plan to feature GeneralUser GS on your own website, please do not link directly to my download files. Either link to my website, or provide your own local copy instead. I hope you enjoy GeneralUser GS! This SoundFont bank is the product of many years of hard work. You can find updates to GeneralUser GS and more of my virtual instruments at: http://www.schristiancollins.com I can be reached at: s_chriscollins@hotmail.com. Thank you! -~Chris fheroes2-1.1.6+dfsg/files/soundfonts/GeneralUser-GS-README.txt000066400000000000000000000063011476115357100237100ustar00rootroot00000000000000********************************* *** GeneralUser GS v1.471 *** *** By S. Christian Collins *** *** 2/7/2017 *** ********************************* GeneralUser GS is a GM and GS compatible SoundFont bank for composing, playing MIDI files, and retro gaming. It features 259 instrument presets and 11 drum kits, all while possessing a very low memory footprint (less than 30 MB of RAM). Due to its clever, detailed sound programming, GeneralUser GS can sound as good or better than SoundFonts that are 2-3 times its size. I decided on the name "GeneralUser" because the bank was designed to sound well with all kinds of music rather than specializing in only a few styles, thereby benefiting the general user. It's not a great name, but that's what I came up with almost 20 years ago, and I haven't bothered to change it. +---------------+ | Compatibility | +---------------+ Although GeneralUser GS was originally designed for use with Sound Blaster audio cards, the most recent development has been focused on SoundFont-compatible software instead. The current version of GeneralUser GS requires a SoundFont synth with support for SoundFont 2.01 modulators. Compatible synths include FluidSynth 1.0.9 or later (and other software that uses FluidSynth such as Qsynth, LMMS, and ScummVM, just to name a few), MuseScore 2.0.3 or later, SynthFont2 2.0.3.0 or later, and VSTSynthFont 1.080 or later. While the current version of GeneralUser GS can be used with the hardware synthesizer found in many Sound Blaster audio cards, you will achieve better results using a version that was designed especially for this hardware (available at http://www.schristiancollins.com/generaluser.php). Most other SoundFont synths do not support all of the programming I have used in GeneralUser GS and will cause many of the presets to sound incorrect. For these unsupported SoundFont synths, you can download an older "SoftSynth" version of GeneralUser GS from my website that cuts out a lot of the special programming and is less likely to result in broken-sounding presets. +--------------+ | Installation | +--------------+ Please follow your synth/sound card's documentation for instructions on loading GeneralUser GS as the default GM/GS bank. This usually requires GeneralUser GS to be loaded into bank 0, and any other SoundFonts loaded into bank 0 to be removed prior. +---------------+ | Miscellaneous | +---------------+ Instrument list files are currently provided for Cakewalk SONAR (Windows) and Rosegarden (Linux) sequencers in the "instrument lists" folder. If you create an instrument list for any other sequencers, please e-mail them to me at s_chriscollins@hotmail.com and I will include them in the next release package. I have also provided some free MIDI files in the "demo MIDIs" folder for your listening enjoyment. Please feel free to send me more of those as well :) You can find updates to GeneralUser GS and more of my virtual instruments at http://www.schristiancollins.com. I can be reached at s_chriscollins@hotmail.com, but please don't send me questions that are easily answered by your sound hardware/software's documentation. I won't have time to answer every question that I receive. Thank you! -~Chris Collins fheroes2-1.1.6+dfsg/files/soundfonts/README.txt000066400000000000000000000007261476115357100211740ustar00rootroot00000000000000This directory contains SoundFont files for MIDI synthesizer. ====== fheroes2.sf3 - SoundFont for MIDI synthesizer based on the GeneralUser GS v1.471 by S. Christian Collins: http://www.schristiancollins.com/generaluser.php All samples, instruments and presets that were not used in the MIDI tracks of the original game were removed, the rest was converted to SF3 format using Polyphone 2.3.1. fheroes2-1.1.6+dfsg/files/timidity/000077500000000000000000000000001476115357100171235ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/timidity/instruments/000077500000000000000000000000001476115357100215165ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/files/timidity/instruments/README.txt000066400000000000000000000027551476115357100232250ustar00rootroot00000000000000There has been some interest in using this patch set commercially. I am flattered, but I'm not sure what to say here. I know that there are some patches that came from the ultrasnd mirrors which contained notices that they did not wish for them to be used commercially. Since I raided the ultrasnd archives many years ago, I couldn't remember which ones were covered by this, so I just flatly said that the whole set was for non-commercial use only. Since then, I have extracted the *.txt and read*.* files out of all the archives and grep'd them for "commercial". While several of them came up as only being for non-commercial use, there are only a few in my set to which this applies. These are: nearly the entire Analog drumset, drumset 25 pistol.pat pistol2.pat (not currently mapped in cfg files) machgun1.pat (not currently mapped in cfg files) So, basicly you can not use the analog drums or the pistol files in any commercial work. This is out of my hands. The rest of the patches are fully public domain as far as I know. It should not be hard to find another pistol which sounds almost as good. As for the analog drumset, just go buy yourself a real TR808 or some other product far superior to these patches. If you DO use this patch set in a commercial production, I'd like to hear about it. A free copy of the production might be nice too :) Eric A. Welsh ewelsh@gpc.ibc.wustl.edu Center for Molecular Design Institute for Biomedical Computing Washington University St. Louis, MO fheroes2-1.1.6+dfsg/files/timidity/timidity.cfg000066400000000000000000000051311476115357100214400ustar00rootroot00000000000000# # Set of GUS patches with MIDI instrument characteristics is taken from here: # http://www.libsdl.org/projects/mixer/timidity/timidity.tar.gz # bank 0 0 instruments/acpiano amp=125 6 instruments/hrpschrd amp=115 19 instruments/church 24 instruments/nyguitar amp=150 41 instruments/viola 42 instruments/cello 43 instruments/contraba amp=150 44 instruments/tremstr 45 instruments/pizzcato amp=85 46 instruments/harp 47 instruments/timpani 48 instruments/marcato 49 instruments/slowstr 51 instruments/synstr2 amp=125 52 instruments/choir 57 instruments/trombone amp=100 60 instruments/frenchrn amp=115 68 instruments/oboe 69 instruments/englhorn 70 instruments/bassoon 71 instruments/clarinet 72 instruments/piccolo 73 instruments/flute amp=100 92 instruments/bowglass amp=200 116 instruments/taiko amp=200 drumset 0 25 instruments/snarerol keep=env amp=225 note=60 26 instruments/snap note=65 27 instruments/highq amp=50 note=65 28 instruments/slap 29 instruments/scratch1 amp=30 30 instruments/scratch2 amp=30 31 instruments/sticks note=60 32 instruments/sqrclick note=60 33 instruments/metclick note=60 34 instruments/metbell keep=loop keep=env note=60 35 instruments/kick1 36 instruments/kick2 37 instruments/stickrim 38 instruments/snare1 39 instruments/claps strip=tail 40 instruments/snare2 41 instruments/tomlo2 42 instruments/hihatcl 43 instruments/tomlo1 44 instruments/hihatpd 45 instruments/tommid2 46 instruments/hihatop 47 instruments/tommid1 48 instruments/tomhi2 49 instruments/cymcrsh1 50 instruments/tomhi1 51 instruments/cymride1 note=60 52 instruments/cymchina 53 instruments/cymbell 54 instruments/tamborin note=60 55 instruments/cymsplsh 56 instruments/cowbell 57 instruments/cymcrsh2 58 instruments/vibslap 59 instruments/cymride2 note=60 60 instruments/bongohi 61 instruments/bongolo 62 instruments/congahi1 63 instruments/congahi2 note=62 64 instruments/congalo note=62 65 instruments/timbaleh note=60 66 instruments/timbalel note=60 67 instruments/agogohi note=60 68 instruments/agogolo note=60 69 instruments/cabasa 70 instruments/maracas note=60 71 instruments/whistle1 note=60 keep=loop keep=env 72 instruments/whistle2 note=60 keep=loop keep=env 73 instruments/guiro1 74 instruments/guiro2 note=60 keep=env 75 instruments/clave 76 instruments/woodblk1 note=60 77 instruments/woodblk2 note=60 78 instruments/cuica1 79 instruments/cuica2 80 instruments/triangl1 note=60 amp=40 81 instruments/triangl2 note=60 amp=40 82 instruments/shaker 83 instruments/jingles note=92 84 instruments/belltree keep=loop keep=env 85 instruments/castinet 86 instruments/surdo1 87 instruments/surdo2 fheroes2-1.1.6+dfsg/iwyu.map000066400000000000000000000014141476115357100156610ustar00rootroot00000000000000[ { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] }, { include: [ "", private, "", public ] } ] fheroes2-1.1.6+dfsg/script/000077500000000000000000000000001476115357100154715ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/README.md000066400000000000000000000001521476115357100167460ustar00rootroot00000000000000# Scripts This directory contains helper scripts needed for installation and compilation of the project. fheroes2-1.1.6+dfsg/script/agg/000077500000000000000000000000001476115357100162275ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/agg/README.md000066400000000000000000000001301476115357100175000ustar00rootroot00000000000000# AGG This directory contains helper scripts for extracting the contents of AGG files. fheroes2-1.1.6+dfsg/script/agg/extract_agg.bat000066400000000000000000000045711476115357100212160ustar00rootroot00000000000000:: ########################################################################### :: # fheroes2: https://github.com/ihhub/fheroes2 # :: # Copyright (C) 2023 # :: # # :: # This program is free software; you can redistribute it and/or modify # :: # it under the terms of the GNU General Public License as published by # :: # the Free Software Foundation; either version 2 of the License, or # :: # (at your option) any later version. # :: # # :: # This program is distributed in the hope that it will be useful, # :: # but WITHOUT ANY WARRANTY; without even the implied warranty of # :: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # :: # GNU General Public License for more details. # :: # # :: # You should have received a copy of the GNU General Public License # :: # along with this program; if not, write to the # :: # Free Software Foundation, Inc., # :: # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # :: ########################################################################### @echo off set PATH=%~dp0;%PATH% set EXIT_CODE=0 call :extract_icn || ^ set EXIT_CODE=1 if not "%CI%" == "true" ( pause ) exit /B %EXIT_CODE% :extract_icn extractor agg *.AGG *.agg || exit /B 1 pal2img agg\HEROES2\kb.pal palette.png || exit /B 1 82m2wav wav\HEROES2 agg\HEROES2\*.82m || exit /B 1 82m2wav wav\HEROES2X agg\HEROES2X\*.82m || exit /B 1 bin2txt txt\HEROES2 agg\HEROES2\*.bin || exit /B 1 bin2txt txt\HEROES2X agg\HEROES2X\*.bin || exit /B 1 icn2img icn\HEROES2 agg\HEROES2\kb.pal agg\HEROES2\*.icn || exit /B 1 icn2img icn\HEROES2X agg\HEROES2\kb.pal agg\HEROES2X\*.icn || exit /B 1 til2img til\HEROES2 agg\HEROES2\kb.pal agg\HEROES2\*.til || exit /B 1 til2img til\HEROES2X agg\HEROES2\kb.pal agg\HEROES2X\*.til || exit /B 1 xmi2midi midi\HEROES2 agg\HEROES2\*.xmi || exit /B 1 xmi2midi midi\HEROES2X agg\HEROES2X\*.xmi || exit /B 1 echo: echo Asset extraction completed successfully. exit /B fheroes2-1.1.6+dfsg/script/agg/extract_agg.sh000066400000000000000000000037061476115357100210610ustar00rootroot00000000000000#!/usr/bin/env bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### set -e -o pipefail PATH="$(dirname "$0"):$PATH" extractor agg *.AGG *.agg pal2img agg/*/kb.pal palette.png for DIR in agg/*; do if [[ ! -d "$DIR" ]]; then continue fi 82m2wav "wav/$(basename "$DIR")" "$DIR"/*.82m bin2txt "txt/$(basename "$DIR")" "$DIR"/*.bin icn2img "icn/$(basename "$DIR")" agg/*/kb.pal "$DIR"/*.icn til2img "til/$(basename "$DIR")" agg/*/kb.pal "$DIR"/*.til xmi2midi "midi/$(basename "$DIR")" "$DIR"/*.xmi done echo -e "\nAsset extraction completed successfully." fheroes2-1.1.6+dfsg/script/demo/000077500000000000000000000000001476115357100164155ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/demo/README.md000066400000000000000000000003041476115357100176710ustar00rootroot00000000000000# Demo This directory contains helper scripts to download and unpack demo version of original game. Downloading pirated or unlicensed version of the game is strictly prohibited by copyright law. fheroes2-1.1.6+dfsg/script/demo/download_demo_version.bat000066400000000000000000000030721476115357100234670ustar00rootroot00000000000000:: ########################################################################### :: # fheroes2: https://github.com/ihhub/fheroes2 # :: # Copyright (C) 2021 - 2023 # :: # # :: # This program is free software; you can redistribute it and/or modify # :: # it under the terms of the GNU General Public License as published by # :: # the Free Software Foundation; either version 2 of the License, or # :: # (at your option) any later version. # :: # # :: # This program is distributed in the hope that it will be useful, # :: # but WITHOUT ANY WARRANTY; without even the implied warranty of # :: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # :: # GNU General Public License for more details. # :: # # :: # You should have received a copy of the GNU General Public License # :: # along with this program; if not, write to the # :: # Free Software Foundation, Inc., # :: # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # :: ########################################################################### @echo off powershell -ExecutionPolicy Unrestricted -File "%~dp0\download_demo_version.ps1" fheroes2-1.1.6+dfsg/script/demo/download_demo_version.ps1000066400000000000000000000153121476115357100234240ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### $ErrorActionPreference = "Stop" $h2DemoURL = "https://archive.org/download/HeroesofMightandMagicIITheSuccessionWars_1020/h2demo.zip" $h2DemoSHA256 = "12048C8B03875C81E69534A3813AAF6340975E77B762DC1B79A4FF5514240E3C" try { function Get-FileViaHTTP { param ( [string]$URL, [string]$FilePath ) try { Invoke-WebRequest -Uri $URL -OutFile $FilePath } catch [System.Management.Automation.CommandNotFoundException] { if ($_.Exception.CommandName -Eq "Invoke-WebRequest") { $webClient = New-Object System.Net.WebClient $webClient.DownloadFile($URL, $FilePath) } else { throw } } } function Get-SHA256HashForFile { param ( [string]$Path ) try { return (Get-FileHash -Path $Path -Algorithm SHA256).Hash } catch [System.Management.Automation.CommandNotFoundException] { if ($_.Exception.CommandName -Eq "Get-FileHash") { try { $output = certutil.exe -hashfile $Path sha256 2>&1 return ($output | Select-String -Pattern "^[0-9A-Fa-f]{64}$").Line.ToUpper() } catch { Write-Host -ForegroundColor Yellow "WARNING: Neither the Get-FileHash cmdlet nor certutil.exe is supported on this system, the hash of the downloaded file cannot be verified" if ($null -Ne $output) { Write-Host -ForegroundColor Yellow (-Join("certutil.exe output: ", ($output | Out-String))) } return $false } } else { throw } } } # Reserve space for the Invoke-WebRequest progress indicator for ($i = 0; $i -Le 7; $i++) { Write-Host "" } Write-Host -ForegroundColor Green (-Join("This script will download the demo version of the original Heroes of Might and Magic II`r`n", ` "It may take a few minutes, please wait...`r`n")) Write-Host "[1/4] determining the destination directory" $destPath = $null if (Test-Path -Path "fheroes2.exe" -PathType Leaf) { $destPath = "." } elseif (Test-Path -Path "..\..\src" -PathType Container) { # Special hack for developers running this script from the source tree $destPath = "..\.." } try { if ($null -Eq $destPath) { throw } while ($true) { $randName = [System.IO.Path]::GetRandomFileName() if (-Not (Test-Path -Path "$destPath\$randName")) { [void](New-Item -Path "$destPath\$randName" -ItemType "directory") Remove-Item -Path "$destPath\$randName" break } } } catch { if ($null -Eq $Env:APPDATA) { Write-Host -ForegroundColor Red "FATAL ERROR: Unable to determine the destination directory" return } $destPath = "$Env:APPDATA\fheroes2" if (-Not (Test-Path -Path $destPath -PathType Container)) { [void](New-Item -Path $destPath -ItemType "directory") } } Write-Host -ForegroundColor Green (-Join("Destination directory: ", (Resolve-Path $destPath).Path)) Write-Host "[2/4] downloading the demo version" $demoPath = "$destPath\demo" if (-Not (Test-Path -Path $demoPath -PathType Container)) { [void](New-Item -Path $demoPath -ItemType "directory") } Get-FileViaHTTP -URL $h2DemoURL -FilePath "$demoPath\h2demo.zip" $result = Get-SHA256HashForFile -Path "$demoPath\h2demo.zip" if (-Not ($result -Is [Boolean]) -And ($result -Ne $h2DemoSHA256)) { Write-Host -ForegroundColor Red (-Join("FATAL ERROR: Invalid hash for HoMM2 demo archive`r`n", ` "Expected:`t$h2DemoSHA256`r`n", ` "Got:`t`t$result`r`n", ` "Installation aborted")) return } Write-Host "[3/4] unpacking archives" $shell = New-Object -ComObject "Shell.Application" $zip = $shell.NameSpace((Resolve-Path "$demoPath\h2demo.zip").Path) foreach ($item in $zip.Items()) { $shell.Namespace((Resolve-Path $demoPath).Path).CopyHere($item, 0x14) } Write-Host "[4/4] copying files" $dataPath = "$destPath\data" $mapsPath = "$destPath\maps" if (-Not (Test-Path -Path $dataPath -PathType Container)) { [void](New-Item -Path $dataPath -ItemType "directory") } if (-Not (Test-Path -Path $mapsPath -PathType Container)) { [void](New-Item -Path $mapsPath -ItemType "directory") } $data = $shell.NameSpace((Resolve-Path "$demoPath\DATA").Path) $maps = $shell.NameSpace((Resolve-Path "$demoPath\MAPS").Path) foreach ($item in $data.Items()) { $shell.Namespace((Resolve-Path $dataPath).Path).CopyHere($item, 0x14) } foreach ($item in $maps.Items()) { $shell.Namespace((Resolve-Path $mapsPath).Path).CopyHere($item, 0x14) } } catch { Write-Host -ForegroundColor Red (-Join("FATAL ERROR: ", ($_ | Out-String))) } finally { Write-Host "Press any key to exit..." [void][System.Console]::ReadKey($true) } fheroes2-1.1.6+dfsg/script/demo/download_demo_version.sh000066400000000000000000000070701476115357100233350ustar00rootroot00000000000000#!/usr/bin/env bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### set -e -o pipefail H2DEMO_URL="https://archive.org/download/HeroesofMightandMagicIITheSuccessionWars_1020/h2demo.zip" H2DEMO_SHA256="12048c8b03875c81e69534a3813aaf6340975e77b762dc1b79a4ff5514240e3c" function echo_red { echo -e "\033[0;31m$*\033[0m" } function echo_green { echo -e "\033[0;32m$*\033[0m" } function echo_stage { echo echo_green "$*" echo } echo_green "This script will download the demo version of the original Heroes of Might and Magic II" echo_green "It may take a few minutes, please wait..." echo_stage "[1/4] determining the destination directory" DEST_PATH="" if [[ -n "$1" ]]; then DEST_PATH="$1" elif [[ -f fheroes2 && -x fheroes2 ]]; then DEST_PATH="." elif [[ -d ../../src ]]; then # Special hack for developers running this script from the source tree DEST_PATH="../.." fi if [[ -z "$DEST_PATH" || ! -d "$DEST_PATH" || ! -w "$DEST_PATH" ]]; then if [[ "$(uname 2> /dev/null)" == "Linux" ]]; then DEST_PATH="${XDG_CONFIG_HOME:-$HOME/.local/share}/fheroes2" elif [[ -z "$1" ]]; then DEST_PATH="$HOME/.fheroes2" fi fi echo_green "Destination directory: $DEST_PATH" echo_stage "[2/4] downloading the demo version" [[ ! -d "$DEST_PATH/demo" ]] && mkdir -p "$DEST_PATH/demo" cd "$DEST_PATH/demo" if [[ -n "$(command -v wget)" ]]; then wget -O h2demo.zip "$H2DEMO_URL" elif [[ -n "$(command -v curl)" ]]; then curl -o h2demo.zip -L "$H2DEMO_URL" else echo_red "Neither wget nor curl were found in your system. Unable to download the demo version. Installation aborted." exit 1 fi echo "$H2DEMO_SHA256 *h2demo.zip" > checksums if [[ -n "$(command -v shasum)" ]]; then shasum --check --algorithm 256 checksums elif [[ -n "$(command -v sha256sum)" ]]; then sha256sum --check --strict checksums else echo_red "Neither shasum nor sha256sum were found in your system. Unable to verify the downloaded file. Installation aborted." exit 1 fi echo_stage "[3/4] unpacking archives" unzip -o h2demo.zip echo_stage "[4/4] copying files" [[ ! -d ../data ]] && mkdir ../data [[ ! -d ../maps ]] && mkdir ../maps cp -r DATA/* ../data cp -r MAPS/* ../maps fheroes2-1.1.6+dfsg/script/demo/download_demo_version_for_app_bundle.sh000066400000000000000000000032651476115357100263760ustar00rootroot00000000000000#!/bin/zsh ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### set -e PLATFORM_NAME="$(uname 2> /dev/null)" if [[ "${PLATFORM_NAME}" != "Darwin" ]]; then echo "This script must be run on a macOS host" exit 1 fi zsh "$(dirname "${(%):-%x}")/download_demo_version.sh" "${HOME}/Library/Application Support/fheroes2" fheroes2-1.1.6+dfsg/script/homm2/000077500000000000000000000000001476115357100165135ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/homm2/README.md000066400000000000000000000002131476115357100177660ustar00rootroot00000000000000# HoMM2 This directory contains helper scripts to extract and copy resources from the original Heroes of Might and Magic II distribution. fheroes2-1.1.6+dfsg/script/homm2/extract_homm2_resources.bat000066400000000000000000000030741476115357100240550ustar00rootroot00000000000000:: ########################################################################### :: # fheroes2: https://github.com/ihhub/fheroes2 # :: # Copyright (C) 2021 - 2023 # :: # # :: # This program is free software; you can redistribute it and/or modify # :: # it under the terms of the GNU General Public License as published by # :: # the Free Software Foundation; either version 2 of the License, or # :: # (at your option) any later version. # :: # # :: # This program is distributed in the hope that it will be useful, # :: # but WITHOUT ANY WARRANTY; without even the implied warranty of # :: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # :: # GNU General Public License for more details. # :: # # :: # You should have received a copy of the GNU General Public License # :: # along with this program; if not, write to the # :: # Free Software Foundation, Inc., # :: # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # :: ########################################################################### @echo off powershell -ExecutionPolicy Unrestricted -File "%~dp0\extract_homm2_resources.ps1" fheroes2-1.1.6+dfsg/script/homm2/extract_homm2_resources.ps1000066400000000000000000000225661476115357100240210ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### $ErrorActionPreference = "Stop" try { function Test-HoMM2DirectoryPath { param ( [string]$Path ) if ((Test-Path -Path "$Path\DATA\HEROES2.AGG" -PathType Leaf) -And (Test-Path -Path "$Path\MAPS" -PathType Container)) { return $true } return $false } Write-Host -ForegroundColor Green "This script will extract and copy game resources from the original distribution of Heroes of Might and Magic II`r`n" Write-Host "[1/3] determining the destination directory" $destPath = $null if (Test-Path -Path "fheroes2.exe" -PathType Leaf) { $destPath = "." } elseif (Test-Path -Path "..\..\src" -PathType Container) { # Special hack for developers running this script from the source tree $destPath = "..\.." } try { if ($null -Eq $destPath) { throw } while ($true) { $randName = [System.IO.Path]::GetRandomFileName() if (-Not (Test-Path -Path "$destPath\$randName")) { [void](New-Item -Path "$destPath\$randName" -ItemType "directory") Remove-Item -Path "$destPath\$randName" break } } } catch { if ($null -Eq $Env:APPDATA) { Write-Host -ForegroundColor Red "FATAL ERROR: Unable to determine the destination directory" return } $destPath = "$Env:APPDATA\fheroes2" if (-Not (Test-Path -Path $destPath -PathType Container)) { [void](New-Item -Path $destPath -ItemType "directory") } } Write-Host -ForegroundColor Green (-Join("Destination directory: ", (Resolve-Path $destPath).Path)) Write-Host "[2/3] determining the HoMM2 directory" $homm2Path = $null # Some legacy HoMM2 installation use a CD drive $homm2CD = $null foreach ($key in @("HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKEY_CURRENT_USER\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", # Legacy HoMM2 installation "HKEY_LOCAL_MACHINE\SOFTWARE\New World Computing\Heroes of Might and Magic 2", "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\New World Computing\Heroes of Might and Magic 2")) { if (-Not (Test-Path -Path "Microsoft.PowerShell.Core\Registry::$key" -PathType Container)) { continue } foreach ($subkey in (Get-ChildItem -Path "Microsoft.PowerShell.Core\Registry::$key")) { $path = $subkey.GetValue("InstallLocation") if ($null -Eq $path) { # From HKLM\SOFTWARE\New World Computing\Heroes of Might and Magic 2 $path = $subkey.GetValue("AppPath") } if ($null -Ne $path) { $path = $path.TrimEnd("\") if (Test-HoMM2DirectoryPath -Path $path) { $homm2Path = $path # From HKLM\SOFTWARE\New World Computing\Heroes of Might and Magic 2 $cdDrive = $subkey.GetValue("CDDrive") if ($null -Ne $cdDrive) { # If CDDrive is not a regular disk name (e.g. F:), then it is some path (absolute or relative), we need to try to resolve it if ($cdDrive -notmatch '^[A-Za-z]:$') { $currentPath = (Get-Location).Path # If it is a relative path, then it should be resolved against the HoMM2 installation path, therefore, we will temporarily # change the current directory to the HoMM2 installation directory try { Set-Location $homm2Path $cdDrive = (Resolve-Path $cdDrive).Path # If CDDrive eventually resolves to the HoMM2 installation directory, then ignore it, because there is no need to copy # the same files twice if ((Resolve-Path $homm2Path).Path -Eq $cdDrive) { throw } } catch { $cdDrive = $null } finally { Set-Location $currentPath } } if ($null -Ne $cdDrive) { $homm2CD = $cdDrive.TrimEnd("\") } } break } } } } if ($null -Eq $homm2Path) { Write-Host -ForegroundColor Yellow "WARNING: Unable to determine the HoMM2 directory" $homm2Path = Read-Host -Prompt "Please enter the full path to the HoMM2 directory (e.g. C:\GOG Games\HoMM 2 Gold)" if (-Not (Test-HoMM2DirectoryPath -Path $homm2Path)) { Write-Host -ForegroundColor Red "FATAL ERROR: Unable to find the HoMM2 directory" return } } Write-Host -ForegroundColor Green (-Join("HoMM2 directory: ", (Resolve-Path $homm2Path).Path)) if ($null -Ne $homm2CD) { Write-Host -ForegroundColor Green "HoMM2 CD drive: $homm2CD" } Write-Host "[3/3] copying game resources" $shell = New-Object -ComObject "Shell.Application" foreach ($homm2Dir in @($homm2Path, $homm2CD)) { if ($null -Eq $homm2Dir) { continue } if (-Not (Test-Path -Path "$homm2Dir\" -PathType Container)) { continue } # fheroes2 can be installed to the HoMM2 directory, there is no need to copy files in this case if ((Resolve-Path $homm2Dir).Path -Eq (Resolve-Path $destPath).Path) { continue } foreach ($srcDir in @("HEROES2\ANIM", "ANIM", "DATA", "MAPS", "MUSIC")) { if (-Not (Test-Path -Path "$homm2Dir\$srcDir" -PathType Container)) { continue } $destDir = (Split-Path $srcDir -Leaf).ToLower() if (-Not (Test-Path -Path "$destPath\$destDir" -PathType Container)) { [void](New-Item -Path "$destPath\$destDir" -ItemType "directory") } $content = $shell.NameSpace((Resolve-Path "$homm2Dir\$srcDir").Path) foreach ($item in $content.Items()) { $shell.Namespace((Resolve-Path "$destPath\$destDir").Path).CopyHere($item, 0x14) } } } # Special case - CD image from GOG if (Test-Path -Path "$homm2Path\homm2.gog" -PathType Leaf) { foreach ($dosboxExe in @("DOSBox.exe", "DOSBOX\DOSBox.exe")) { if (-Not (Test-Path -Path "$homm2Path\$dosboxExe" -PathType Leaf)) { continue } if (-Not (Test-Path -Path "$destPath\anim" -PathType Container)) { [void](New-Item -Path "$destPath\anim" -ItemType "directory") } Write-Host -ForegroundColor Green "Running DOSBOX to extract animation resources, please wait..." Start-Process -FilePath "$homm2Path\$dosboxExe" -ArgumentList @("-c", "`"imgmount D '$homm2Path\homm2.gog' -t iso -fs iso`"", ` "-c", "`"mount E '$destPath'`"", ` "-c", "`"copy D:\HEROES2\ANIM\*.* E:\ANIM`"", ` "-c", "exit") ` -Wait break } } } catch { Write-Host -ForegroundColor Red (-Join("FATAL ERROR: ", ($_ | Out-String))) } finally { Write-Host "Press any key to exit..." [void][System.Console]::ReadKey($true) } fheroes2-1.1.6+dfsg/script/homm2/extract_homm2_resources.sh000066400000000000000000000127141476115357100237220ustar00rootroot00000000000000#!/usr/bin/env bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### set -e -o pipefail function echo_red { echo -e "\033[0;31m$*\033[0m" } function echo_green { echo -e "\033[0;32m$*\033[0m" } function echo_yellow { echo -e "\033[0;33m$*\033[0m" } function echo_stage { echo echo_green "$*" echo } function verify_homm2_path { [[ -f "$1/DATA/HEROES2.AGG" && -d "$1/MAPS" ]] } echo_green "This script will extract and copy game resources from the original distribution of Heroes of Might and Magic II" echo_stage "[1/3] determining the destination directory" DEST_PATH="" if [[ -n "$2" ]]; then DEST_PATH="$2" elif [[ -f fheroes2 && -x fheroes2 ]]; then DEST_PATH="." elif [[ -d ../../src ]]; then # Special hack for developers running this script from the source tree DEST_PATH="../.." fi if [[ -z "$DEST_PATH" || ! -d "$DEST_PATH" || ! -w "$DEST_PATH" ]]; then if [[ "$(uname 2> /dev/null)" == "Linux" ]]; then DEST_PATH="${XDG_CONFIG_HOME:-$HOME/.local/share}/fheroes2" elif [[ -z "$2" ]]; then DEST_PATH="$HOME/.fheroes2" fi fi echo_green "Destination directory: $DEST_PATH" echo_stage "[2/3] determining the HoMM2 directory or installer package" if [[ "$#" -gt "0" ]]; then HOMM2_PATH="$1" else read -e -p "Please enter the full path to the HoMM2 directory or installer package (e.g. /home/user/homm2 or /tmp/installer.exe): " HOMM2_PATH fi if [[ -f "$HOMM2_PATH" ]]; then if [[ -z "$(command -v innoextract)" ]]; then echo_red "innoextract was not found in your system. Unable to extract the installer package. Installation aborted." exit 1 fi EXTRACT_DIR="$(mktemp -d)" echo_green "Verifying the installer package, please wait..." innoextract -e -s -d "$EXTRACT_DIR" -- "$HOMM2_PATH" for ITEM in "$EXTRACT_DIR" "$EXTRACT_DIR"/*; do if verify_homm2_path "$ITEM"; then echo_green "HoMM2 installer package: $HOMM2_PATH" HOMM2_PATH="$ITEM" break fi done if [[ -f "$HOMM2_PATH" ]]; then echo_red "Unable to find HoMM2 files in this installer package. Installation aborted." exit 1 fi elif verify_homm2_path "$HOMM2_PATH"; then echo_green "HoMM2 directory: $HOMM2_PATH" else echo_red "Unable to find the HoMM2 directory or installer package. Installation aborted." exit 1 fi echo_stage "[3/3] copying game resources" [[ ! -d "$DEST_PATH" ]] && mkdir -p "$DEST_PATH" cd "$DEST_PATH" [[ ! -d anim ]] && mkdir anim [[ ! -d data ]] && mkdir data [[ ! -d maps ]] && mkdir maps [[ ! -d music ]] && mkdir music [[ -d "$HOMM2_PATH/HEROES2/ANIM" ]] && cp -r "$HOMM2_PATH/HEROES2/ANIM"/* anim [[ -d "$HOMM2_PATH/ANIM" ]] && cp -r "$HOMM2_PATH/ANIM"/* anim [[ -d "$HOMM2_PATH/DATA" ]] && cp -r "$HOMM2_PATH/DATA"/* data [[ -d "$HOMM2_PATH/MAPS" ]] && cp -r "$HOMM2_PATH/MAPS"/* maps [[ -d "$HOMM2_PATH/MUSIC" ]] && cp -r "$HOMM2_PATH/MUSIC"/* music if [[ ! -f "$HOMM2_PATH/homm2.gog" ]]; then exit 0 fi # Special case - CD image from GOG if [[ -n "$(command -v python3)" ]]; then PYTHON="python3" elif [[ -n "$(command -v python2)" ]]; then PYTHON="python2" elif [[ -n "$(command -v python)" ]]; then PYTHON="python" else echo_yellow "python was not found in your system. Please install it and re-run this script to extract animation resources." exit 0 fi if [[ -z "$(command -v bsdtar)" ]]; then echo_yellow "bsdtar was not found in your system. Please install it and re-run this script to extract animation resources." exit 0 fi echo_green "Extracting animation resources, please wait..." "$PYTHON" - << EOF with open("$HOMM2_PATH/homm2.gog", "rb") as raw_file: with open("homm2.iso", "wb") as iso_file: while True: buf = raw_file.read(2352) if not buf: break if buf[15] == 2: iso_file.write(buf[24:2072]) else: iso_file.write(buf[16:2064]) EOF bsdtar -x -f homm2.iso -C anim --include "HEROES2/ANIM/*" --strip-components=2 rm -f homm2.iso fheroes2-1.1.6+dfsg/script/homm2/extract_homm2_resources_for_app_bundle.sh000066400000000000000000000036121476115357100267560ustar00rootroot00000000000000#!/bin/zsh ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### set -e PLATFORM_NAME="$(uname 2> /dev/null)" if [[ "${PLATFORM_NAME}" != "Darwin" ]]; then echo "This script must be run on a macOS host" exit 1 fi if [[ "$#" == "1" ]]; then HOMM2_PATH="$1" else read "HOMM2_PATH?Please enter the full path to the HoMM2 directory or installer package (e.g. /home/user/homm2 or /tmp/installer.exe): " fi zsh "$(dirname "${(%):-%x}")/extract_homm2_resources.sh" "$HOMM2_PATH" "${HOME}/Library/Application Support/fheroes2" fheroes2-1.1.6+dfsg/script/homm2/extract_homm2_resources_from_cd_image.sh000077500000000000000000000143541476115357100265620ustar00rootroot00000000000000#!/usr/bin/env bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### set -e -o pipefail function echo_red { echo -e "\033[0;31m$*\033[0m" } function echo_green { echo -e "\033[0;32m$*\033[0m" } function echo_stage { echo echo_green "$*" echo } echo_green "This script will extract and copy game resources from the original Heroes of Might and Magic II CD image." echo_stage "[1/4] determining the destination directory" DEST_PATH="" if [[ -n "$2" ]]; then DEST_PATH="$2" elif [[ -f fheroes2 && -x fheroes2 ]]; then DEST_PATH="." elif [[ -d ../../src ]]; then # Special hack for developers running this script from the source tree DEST_PATH="../.." fi if [[ -z "$DEST_PATH" || ( -d "$DEST_PATH" && ! -w "$DEST_PATH" ) ]]; then if [[ "$(uname 2> /dev/null)" == "Linux" ]]; then DEST_PATH="${XDG_CONFIG_HOME:-$HOME/.local/share}/fheroes2" elif [[ -z "$2" ]]; then DEST_PATH="$HOME/.fheroes2" fi fi echo_green "Destination directory: $DEST_PATH" echo_stage "[2/4] determining the path to the HoMM2 CD image" if [[ "$#" -gt "0" ]]; then HOMM2_CD_IMAGE_PATH="$1" else read -e -p "Please enter the full path to the HoMM2 CD image (e.g. /home/user/homm2.cue or /home/user/homm2.iso): " HOMM2_CD_IMAGE_PATH fi STAGE_PATH=$(mktemp -d) trap 'rm -rf "$STAGE_PATH"' EXIT function stage_iso_assets { if [[ -z "$(command -v fuseiso)" ]]; then echo_red "fuseiso was not found in your system. Unable to mount CD image. Installation aborted." exit 1 fi if [[ -z "$(command -v fusermount)" ]]; then echo_red "fusermount was not found in your system. Unable to unmount CD image. Installation aborted." exit 1 fi mkdir ROM fuseiso "$1" ROM trap 'fusermount -u ROM' RETURN HOMM2_DIR=$(find ROM -type d -iname heroes2) if [[ -z "$HOMM2_DIR" ]]; then echo_red "Unable to locate 'heroes2' directory in CD image." exit 1 fi copy_directory "$HOMM2_DIR" "ANIM" DATA_CAB_PATH=$(find "ROM" -type f -iname data1.cab) if [[ -n "$DATA_CAB_PATH" ]]; then if [[ -z "$(command -v unshield)" ]]; then echo_red "unshield was not found in your system. Unable to extract 'data1.cab'. Installation aborted." exit 1 fi unshield -d "CAB" x "$DATA_CAB_PATH" > /dev/null copy_directory "CAB" "MAPS" copy_directory "CAB" "DATA" rm -rf CAB else copy_directory "$HOMM2_DIR" "MAPS" copy_directory "$HOMM2_DIR" "DATA" fi fusermount -u ROM trap - RETURN rmdir ROM } function copy_directory() { BASE_DIR=$1 DIR_NAME=$2 DIR_PATH=$(find "$BASE_DIR" -type d -iname "$DIR_NAME") if [[ -n "$DIR_PATH" ]]; then mkdir "$DIR_NAME" cp -r "$DIR_PATH/." "$DIR_NAME" fi } echo_stage "[3/4] staging game resources" cd "$STAGE_PATH" CD_IMAGE_FILE_NAME=$(basename "$HOMM2_CD_IMAGE_PATH") CD_IMAGE_EXTENSION=${CD_IMAGE_FILE_NAME##*.} if [[ "${CD_IMAGE_EXTENSION^^}" == "CUE" ]]; then if [[ -z "$(command -v bchunk)" ]]; then echo_red "bchunk was not found in your system. Unable to rip CD audio. Installation aborted." exit 1 fi # Parse the path of the bin file directly from the CUE sheet, so that this # will continue to work even if the name of the cue sheet doesn't match the # name of the bin file. BIN_PATH="$(dirname "$HOMM2_CD_IMAGE_PATH")/$(cat "$HOMM2_CD_IMAGE_PATH" | grep FILE | grep -oE '"([^"]+)"' | tr -d '"')" bchunk -w "$BIN_PATH" "$HOMM2_CD_IMAGE_PATH" tmp_ > /dev/null if [[ -z "$(command -v flac)" ]]; then echo_red "flac was not found in your system. Unable to reencode CD audio. Installation aborted." exit 1 fi mkdir MUSIC for WAV_PATH in *.wav; do # The music ripped from the CD starts from index 2, since the first index # is occupied by the ISO data. However, the engine expects the music to # start from index zero, so we must subtract one from the index to meet # this expectation. WAV_FILE=$(basename "$WAV_PATH") OLD_TRACK_NUM=$(echo "${WAV_FILE%.*}" | cut -d'_' -f2) NEW_TRACK_NUM=$(printf '%02d' $((${OLD_TRACK_NUM#0}-1))) NEW_FILE_NAME="homm2_$NEW_TRACK_NUM.flac" # Flac generates a lot noise on the error stream, even when it's working # as expected. So we redirect the error output to quiet things down. flac --delete-input-file -8 "$WAV_PATH" -o "MUSIC/$NEW_FILE_NAME" 2> /dev/null echo_green "Completed ripping $NEW_FILE_NAME to 'MUSIC'." done stage_iso_assets "tmp_01.iso" rm "tmp_01.iso" elif [[ "${CD_IMAGE_EXTENSION^^}" == "ISO" ]]; then stage_iso_assets "$HOMM2_CD_IMAGE_PATH" else echo_red "Unsupported CD image extension '$CD_IMAGE_EXTENSION'." exit 1 fi echo_stage "[4/4] copying game resources" [[ ! -d "$DEST_PATH" ]] && mkdir -p "$DEST_PATH" cd "$DEST_PATH" cp -rf "$STAGE_PATH/." . fheroes2-1.1.6+dfsg/script/homm2/resource_extraction_toolset.bat000066400000000000000000000031051476115357100250420ustar00rootroot00000000000000:: ########################################################################### :: # fheroes2: https://github.com/ihhub/fheroes2 # :: # Copyright (C) 2021 - 2023 # :: # # :: # This program is free software; you can redistribute it and/or modify # :: # it under the terms of the GNU General Public License as published by # :: # the Free Software Foundation; either version 2 of the License, or # :: # (at your option) any later version. # :: # # :: # This program is distributed in the hope that it will be useful, # :: # but WITHOUT ANY WARRANTY; without even the implied warranty of # :: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # :: # GNU General Public License for more details. # :: # # :: # You should have received a copy of the GNU General Public License # :: # along with this program; if not, write to the # :: # Free Software Foundation, Inc., # :: # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # :: ########################################################################### @echo off powershell -ExecutionPolicy Unrestricted -Sta -File "%~dp0\resource_extraction_toolset.ps1" fheroes2-1.1.6+dfsg/script/homm2/resource_extraction_toolset.ps1000066400000000000000000000240531476115357100250040ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### $ErrorActionPreference = "Stop" try { function Test-DragDropFile { param ( [string[]]$FileDropList, [string]$AllowedExtension ) if ($FileDropList.Count -Ne 1) { return $false } if (-Not (Test-Path -Path $FileDropList[0] -PathType Leaf)) { return $false } $fileExtension = (Get-ChildItem $FileDropList[0]).Extension if ($null -Eq $fileExtension) { return $false } $fileExtension = $fileExtension.ToLower() if ($fileExtension -Ne $AllowedExtension) { return $false } return $true } function Copy-GOGMusic { param ( [string]$ArchiveName, [string]$DestPath ) Write-Host -ForegroundColor Green "Extracting GOG OST files, please wait..." $tempPath = $null while ($true) { $randName = [System.IO.Path]::GetRandomFileName() $tempPath = "$DestPath\$randName" if (-Not (Test-Path -Path $tempPath)) { [void](New-Item -Path $tempPath -ItemType "directory") break } } $shell = New-Object -ComObject "Shell.Application" $zip = $shell.NameSpace((Resolve-Path $ArchiveName).Path) foreach ($item in $zip.Items()) { $shell.Namespace((Resolve-Path $tempPath).Path).CopyHere($item, 0x14) } $tmpMusicPath = $null while ($true) { $randName = [System.IO.Path]::GetRandomFileName() $tmpMusicPath = "$DestPath\$randName" if (-Not (Test-Path -Path $tmpMusicPath)) { [void](New-Item -Path $tmpMusicPath -ItemType "directory") break } } if (-Not (Test-Path -Path $tmpMusicPath -PathType Container)) { [void](New-Item -Path $tmpMusicPath -ItemType "directory") } if (-Not (Test-Path -Path "$tmpMusicPath\pol" -PathType Container)) { [void](New-Item -Path "$tmpMusicPath\pol" -ItemType "directory") } if (-Not (Test-Path -Path "$tmpMusicPath\sw" -PathType Container)) { [void](New-Item -Path "$tmpMusicPath\sw" -ItemType "directory") } # Additional PoL soundtrack id -> SW soundtrack id $polSWMap = @{"44" = "05"; "45" = "06"; "46" = "07"; "47" = "08"; "48" = "09"; "49" = "10"} $musicType = $null foreach ($item in (Get-ChildItem -Path $tempPath -Recurse)) { if ($item.Name -notmatch "[0-9]{2}") { continue } $fileExtension = (Get-ChildItem $item.FullName).Extension if ($null -Eq $fileExtension) { continue } $fileExtension = $fileExtension.ToLower() if ($fileExtension -Eq ".flac") { $musicType = $fileExtension } elseif ($fileExtension -Eq ".mp3") { # An archive with FLAC can contain some MP3 files if ($null -Eq $musicType) { $musicType = $fileExtension } } else { continue } $trackNumber = ($item.Name | Select-String -Pattern "[0-9]{2}").Matches[0].Value # Castle soundtracks from the Succession Wars if ($polSWMap.Values -contains $trackNumber) { Copy-Item -Path $item.FullName -Destination "$tmpMusicPath\sw\Track$trackNumber$fileExtension" # Castle soundtracks from the Price of Loyalty expansion } elseif ($polSWMap.Keys -contains $trackNumber) { $trackNumber = $polSWMap[$trackNumber] Copy-Item -Path $item.FullName -Destination "$tmpMusicPath\pol\Track$trackNumber$fileExtension" } Copy-Item -Path $item.FullName -Destination "$tmpMusicPath\Track$trackNumber$fileExtension" } Remove-Item -Path $tempPath -Recurse if ($null -Eq $musicType) { Remove-Item -Path $tmpMusicPath -Recurse Write-Host -ForegroundColor Yellow "WARNING: No soundtracks were found" } else { $dirName = $null $uniqId = 0 while ($true) { if ($uniqId -Eq 0) { $dirName = "music$musicType" } else { $dirName = "music$musicType.$uniqId" } if (-Not (Test-Path -Path "$DestPath\$dirName")) { break } $uniqId++ } Rename-Item -Path $tmpMusicPath -NewName $dirName Write-Host -ForegroundColor Green (-Join("GOG OST directory: ", (Resolve-Path "$DestPath\$dirName").Path)) } } Write-Host -ForegroundColor Green "This script will run the extraction toolset to extract and copy additional game resources from the original distribution of Heroes of Might and Magic II`r`n" Write-Host "[1/2] determining the destination directory" $destPath = $null if (Test-Path -Path "fheroes2.exe" -PathType Leaf) { $destPath = "." } elseif (Test-Path -Path "..\..\src" -PathType Container) { # Special hack for developers running this script from the source tree $destPath = "..\.." } try { if ($null -Eq $destPath) { throw } while ($true) { $randName = [System.IO.Path]::GetRandomFileName() if (-Not (Test-Path -Path "$destPath\$randName")) { [void](New-Item -Path "$destPath\$randName" -ItemType "directory") Remove-Item -Path "$destPath\$randName" break } } } catch { if ($null -Eq $Env:APPDATA) { Write-Host -ForegroundColor Red "FATAL ERROR: Unable to determine the destination directory" return } $destPath = "$Env:APPDATA\fheroes2" if (-Not (Test-Path -Path $destPath -PathType Container)) { [void](New-Item -Path $destPath -ItemType "directory") } } Write-Host -ForegroundColor Green (-Join("Destination directory: ", (Resolve-Path $destPath).Path)) Write-Host "[2/2] running the resource extraction toolset" $commandToRun = $null [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") $mainForm = New-Object -TypeName "System.Windows.Forms.Form" -Property @{Text = "Resource Extraction Toolset"} $gogOSTExtractionGroupBox = New-Object -TypeName "System.Windows.Forms.GroupBox" -Property @{ Text = "Extract a GOG OST archive" Dock = "Fill" Padding = 32 AllowDrop = $true } $gogOSTExtractionGroupBox.Add_DragEnter({ if (Test-DragDropFile -FileDropList $_.Data.GetFileDropList() -AllowedExtension ".zip") { $_.Effect = [Windows.Forms.DragDropEffects]::Copy } else { $_.Effect = [Windows.Forms.DragDropEffects]::None } }) $gogOSTExtractionGroupBox.add_DragDrop({ $fileDropList = $_.Data.GetFileDropList() if (-Not (Test-DragDropFile -FileDropList $fileDropList -AllowedExtension ".zip")) { return } $global:commandToRun = {Copy-GOGMusic -ArchiveName $fileDropList[0] -DestPath $destPath}.GetNewClosure() $mainForm.Close() }) $mainForm.Controls.Add($gogOSTExtractionGroupBox) $gogOSTExtractionBrowseButton = New-Object -TypeName "System.Windows.Forms.Button" -Property @{ Text = "Choose an OST archive file..." Dock = "Top" } $gogOSTExtractionBrowseButton.Add_Click({ $fileDialog = New-Object -TypeName "System.Windows.Forms.OpenFileDialog" -Property @{ Filter = "ZIP Archives (*.zip)|*.zip" } [void]$fileDialog.ShowDialog() if ($fileDialog.FileName -Eq "") { return } $global:commandToRun = {Copy-GOGMusic -ArchiveName $fileDialog.FileName -DestPath $destPath}.GetNewClosure() $mainForm.Close() }) $gogOSTExtractionGroupBox.Controls.Add($gogOSTExtractionBrowseButton) $gogOSTExtractionDragLabel = New-Object -TypeName "System.Windows.Forms.Label" -Property @{ Text = "Or drag && drop an OST archive file here" Dock = "Bottom" TextAlign = "MiddleCenter" } $gogOSTExtractionGroupBox.Controls.Add($gogOSTExtractionDragLabel) [System.Windows.Forms.Application]::Run($mainForm) if ($null -Ne $commandToRun) { & $commandToRun } } catch { Write-Host -ForegroundColor Red (-Join("FATAL ERROR: ", ($_ | Out-String))) } finally { Write-Host "Press any key to exit..." [void][System.Console]::ReadKey($true) } fheroes2-1.1.6+dfsg/script/linux/000077500000000000000000000000001476115357100166305ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/linux/README.md000066400000000000000000000001001476115357100200760ustar00rootroot00000000000000# Linux This directory contains helper scripts to install SDL. fheroes2-1.1.6+dfsg/script/linux/SDL_mixer.ymp000066400000000000000000000037301476115357100212100ustar00rootroot00000000000000 games openSUSE Games https://en.opensuse.org/Games https://download.opensuse.org/repositories/games/openSUSE_Leap_15.2/ openSUSE:Leap:15.2:Update Online updates for openSUSE Leap:15.2 This project is releasing the official updates for openSUSE Leap:15.2. http://download.opensuse.org/update/leap/15.2/oss/ openSUSE:Leap:15.2:NonFree Non Free parts of openSUSE Leap 15.2 distribution. Non free or non open source parts of openSUSE Leap 15.2. http://download.opensuse.org/distribution/leap/15.2/repo/non-oss/ openSUSE:Leap:15.2 openSUSE Leap 15.2 openSUSE Leap borrows packages from SLE for the base system. Please refer to https://osrt.opensuse.org/web/origin-manager/#openSUSE:Leap:15.2 for origin information http://download.opensuse.org/distribution/leap/15.2/repo/oss/ SDL_mixer SDL sound mixer library A multichannel audio mixer. It supports four channels of 16-bit stereo audio, plus a single channel of music, mixed by the popular MikMod MOD, Timidity MIDI, and SMPEG MP3 libraries. fheroes2-1.1.6+dfsg/script/linux/install_sdl2.sh000066400000000000000000000030171476115357100215570ustar00rootroot00000000000000#!/bin/bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Install SDL2 sudo apt-get install -y libsdl2-2.0-0 libsdl2-image-2.0-0 libsdl2-mixer-2.0-0 fheroes2-1.1.6+dfsg/script/linux/install_sdl2_dev.sh000066400000000000000000000030641476115357100224170ustar00rootroot00000000000000#!/bin/bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2023 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Install development dependencies targeting SDL2 sudo apt-get install -y gettext libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev fheroes2-1.1.6+dfsg/script/packaging/000077500000000000000000000000001476115357100174155ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/packaging/common/000077500000000000000000000000001476115357100207055ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/packaging/common/fheroes2.desktop000066400000000000000000000003641476115357100240200ustar00rootroot00000000000000[Desktop Entry] Type=Application Name=fheroes2 Comment=Free remake of Heroes of Might and Magic II game engine Icon=fheroes2 TryExec=fheroes2 Exec=fheroes2 Terminal=false StartupNotify=false Categories=Game;StrategyGame; Keywords=heroes;homm2; fheroes2-1.1.6+dfsg/script/packaging/common/fheroes2.metainfo.xml000066400000000000000000006476061476115357100247700ustar00rootroot00000000000000 io.github.ihhub.Fheroes2 fheroes2.desktop CC0-1.0 GPL-2.0 fheroes2 fheroes2 Resurrection team fheroes2 is a recreation of the Heroes of Might and Magic II game engine

This open source multiplatform project, written from scratch, is designed to reproduce the original game with significant improvements to the gameplay, graphics and logic (including support for high-resolution graphics, improved AI, numerous fixes and UI improvements), breathing new life into one of the most addictive turn-based strategy games.

Game StrategyGame heroes2 homm2 https://ihhub.github.io/fheroes2/ https://github.com/ihhub/fheroes2/issues https://github.com/ihhub/fheroes2/wiki/F.A.Q. https://ihhub.github.io/fheroes2/INSTALL.html https://ihhub.github.io/fheroes2/TRANSLATION.html https://www.patreon.com/fheroes2 https://discord.gg/xF85vbZ https://github.com/ihhub/fheroes2 https://github.com/ihhub/fheroes2/blob/master/CONTRIBUTING.md mild mild keyboard pointing touch https://github.com/ihhub/fheroes2/releases/tag/1.1.6

Changes in v1.1.6 (16 February 2025):

  • fix Ultimate Artifact being erased for any action done on a map
  • fix Editor buttons not being translated
  • fix an assertion regarding maximum spell points
  • update the French translation
  • update the Czech translation
  • add return to the Main Menu and Play Map buttons to the Editor
  • replace "max" text with MIN and MAX buttons for integer input dialog
  • check Loss conditions before Victory conditions
  • expand the functionality of the Adventure map event
  • update the Swedish translation
  • show a proper icon for music and audio settings when they are off
  • rework rendering of experience indicator
  • increase the maximum allowed map name length from the original 17 characters to 50
  • show a range of available values in the input dialog
  • fix the interface not being updated in time in the Editor
  • show the total obelisk number while clicking on the Adventure Map object
  • update the Spanish translation
  • add a script to extract resources from CD images
  • fix rendering of text for several checkboxes
  • display monster count for the Monster object for the Editor
  • update the Hungarian translation
  • add more game options for the Editor
  • use a single button to switch between castle and town in the Editor dialog
  • make the "Week of Monster" deterministic
  • fix text rendering for the level-up dialog
  • display the chosen resource amount in the right-click popup info in the Editor
  • fix the Main Menu rendering after calling the Settings dialog
  • add a dialog pop-up when pressing standing horse
  • add button shine to engine-generated buttons
  • shorten hero name if name plus level is too long
  • add Undo and Redo icons in the Editor
  • show the Artifact description window when clicking on it in the Editor
  • add info about 50% retaliation damage to the Blind spell description
  • update Hero Movement button
  • fix Mine flag rendering on the Adventure Map
  • fix a crash in the View World mode for the Editor
  • add dialog to choose between Auto Combat and Quick Combat
  • fix the project version not being properly displayed in the PSV port of the engine
  • fix overlap of the FPS info and popup message in the Editor
  • fix selected Ore mine resetting in the Mine placement dialog
  • fix the Hideous Mask behavior causing neutral units to never flee
  • fix issues with pressed button states on the battle screen
  • improve morale UI for the undead army
  • update the background image for the PSV port of the engine
  • display spell name in the dialog for spell casting error
  • remove additional passability marks on the bottom part of tiles
  • improve side tile passability logic
  • modify Button layout to be similar to the original game
  • Android: gracefully handle errors when the system chooser does not start for some reason
  • add swap army and swap artifacts to the heroes meeting screen
  • expand Text Support mode for New Map selection dialogs
https://github.com/ihhub/fheroes2/releases/tag/1.1.5

Changes in v1.1.5 (30 December 2024):

  • add 3 new variants of the Observation Tower object
  • show Monster and Artifact names in the popup dialog of the Editor
  • show the minus sign for the numeric keypad only if a range allows the use of negative values
  • fix Spell Scroll artifact horizontal position on the Adventure Map
  • update the Portuguese translation
  • update the Swedish translation
  • fix the spell cost displayed in the quick info window when a hero has an artifact that reduces this cost
  • add the ability to set Secondary Skills in Witch's Hut inside the Editor
  • fix the mouse interaction in the Editor's spell selection and castle properties windows
  • fix cursor positioning with non-English characters and improve positioning at the end of the line
  • display a description of the mechanics of right-clicking on devices with touch input
  • fix assertion while loading different maps in the Editor
  • add the ability to edit spells in Pyramid inside the Editor
  • add the ability to set the amount in the Resource object in the Editor
  • add the ability to set spells in Shrine in the Editor
  • add a new variant of Stone Liths object
  • update the Russian translation
  • show a warning dialog upon map file loading failure
  • fix spell randomization logic for Artifacts and the Adventure Map objects
  • fix text input cursor setting for multi-line text input with many spaces at the line end
  • fix scrollbars being shifted while changing resolution on the Adventure Map
  • reset the damage info popup when spellcasting is cancelled
  • fix a bug when picking up an object whose type does not match its sprite on the map
  • update the Hungarian translation
  • add range values for default experience within the Editor
  • add missing CP1254 button letters
  • fix French and German ultimate staff sprite with PoL assets
  • updated the Czech translation
  • update the Turkish translation
  • improve the castle reinforcement logic for AI
  • synchronize the maximum allowed number of characters for input and the Virtual Keyboard
  • fix PS Vita touchpad usage
  • add file support for non-quite-POSIX-compliant filesystems (such as Amiga FS)
  • put several dialog box headers in order
  • enable the number input dialog for the recruitment window
  • use the platform-dependent byte order for the SDL audio format
https://github.com/ihhub/fheroes2/releases/tag/1.1.4

Changes in v1.1.4 (27 November 2024):

  • add Virtual Numpad support for integer inputs
  • add new Lean-To object variant
  • update the Czech translation
  • add Belarusian language support for the Virtual Keyboard
  • improve & speed up the translation-related logic
  • update the German translation related to the Price of Loyalty Campaign
  • update the Swedish translation
  • update initial passability logic
  • fix the attack value estimation for a Hypnotized unit with the ALL_ADJACENT_CELL_MELEE_ATTACK ability
  • improve the retreat logic for archers
  • update the Portuguese Translation
  • fix overlapping text in the High Scores dialog
  • add support of Evil interface for the Scenario Information dialog
  • fix the penalty calculation for enemy units that can evade the engagement during battle
  • fix passability for several objects on maps made the original Editor
  • center Magic Book artifact on the Adventure Map
  • speed up ICN image decoding
  • do not download the wing32.dll for HoMM2 demo version
  • add u with two dots to buttons and translate and improve German buttons
https://github.com/ihhub/fheroes2/releases/tag/1.1.3

Changes in v1.1.3 (23 October 2024):

  • fix invalid behavior and crash during interaction with whirlpools by heroes on boats
  • fix French small font i with circumflex
  • add Czech Virtual Keyboard support
  • fix rendering of overlapped UI elements
  • shorten map title when too long in several places
  • add missing popup dialogs to buttons within View World mode
  • update the Hungarian translation
  • speed up language switching I/O operations
  • update the Swedish translation
  • fix Sorceress Statue construction fade-in animation
  • fix map titles not being cleared when changing map
  • add language support for fh2m map format
  • update the Portuguese translation
  • use an original image to draw hexagons on the battlefield
  • improve Dismiss button for French and Spanish languages
  • fix event handling for dialogs in No Interface mode
  • improve error handling for I/O operations
  • increase most of object selection windows in the Editor by 50 pixels
  • update army information after battle before showing any dialogs
  • add missing sand animation for hourglass while waiting for a turn
  • speed up AI calculations on the Adventure Map
  • improve AI decision making while using Dimension Door spell
  • ease object requirements while erasing them in the Editor
  • split long phrases into two lines for battle log
  • fix blinking arrow cursor during scrolling in Editor
  • properly show damage info pop-up dialog for 2-hex monsters during battle
  • make default knowledge value for random hero 1
  • fix inability to erase monsters on the map under certain conditions within the Editor
  • fix the triggering of invalid drag events for the game area when casting certain spells
  • fix out of mini-map mouse dragging behavior in the Editor
  • update the Russian translation
  • add vertical gradient fonts
  • add a popup dialog to the list of resolutions
  • allow to resize vertical buttons for translations
  • fix issues with non-English path detection on Windows
  • center sprites and text in adventure map treasure chest dialog
  • do not discard area selection while moving mouse out of the map in the Editor
  • fix a crash while trying to distribute an army with 1 unit
https://github.com/ihhub/fheroes2/releases/tag/1.1.2

Changes in v1.1.2 (15 September 2024):

  • preserve the order of artifacts when adding the Spell Book to the artifacts bag
  • update the Portuguese translation
  • speed up MIDI file processing
  • update the German translation
  • update visited status for Tree of Knowledge object
  • update New Secondary Skill dialog
  • add an extra check to verify the game resources not being corrupted
  • update the Hungarian translation
  • limit the use of the Summon Boat by AI for the original maps
  • do not create an undo action in the Editor if nothing was changed for an object
  • allow to undo any castle modifications in the Editor
  • improve AI castle protection logic on the Adventure Map
  • render mirrored troop in dialog properly
  • update resources before showing construction animation inside castle dialog
  • update the Swedish translation
  • fix the audio playback and distance calculation in the 3D Audio mode
  • fix Cliff Nest glowing pixel
  • update Earthquake spell animation and improve its logic to allow bridge and nearby towers demolition
  • disable mouse popup for empty space in map selection window
  • fix AI heroes ignoring patrol limit
  • AI should determine best skill when leveling up heroes
  • update hero spell points indicator after the battle and before performing defeated opponent fade animation
  • fix creature and header overlap in recruit window
  • fix map special conditions render after drop list is closed
  • implement alliances in the Editor
  • fix original maps bottom layer (hacky) placed resources and artifacts
  • add Backslash character to normal and small fonts
  • add missed Small Cliff (Dirt terrain) to the Landscape Miscellaneous objects in the Editor
  • add Ukrainian language virtual keyboard
  • fix inability to save maps within the Editor for some installations
  • add monster statistics popup window inside the Editor monster information dialog
  • Android Toolset: add Russian translation for FH2M file manager
  • fix Anti-Magic spell description
  • update the Polish translation
  • fix mini-map updates while picking up certain objects on the Adventure Map
  • fix invalid animation while picking up an artifact hidden by another object on the Adventure Map
  • remove scouting & movement bonuses for AI-controlled players
  • fix rendering issues in mine selection dialog for the Editor
  • allow to input "/", "*", "-", "+" and "." from the keypad
  • add new River Deltas objects
  • add Slovak virtual keyboard support
  • update the Russian translation
  • fix lagging input controls on some devices
  • AI: properly evaluate the enemy heroes defending the castles
https://github.com/ihhub/fheroes2/releases/tag/1.1.1

Changes in v1.1.1 (13 July 2024):

  • update the Russian translation
  • properly set tile information upon placing a new object
  • update the Hungarian translation
  • implement special victory and loss conditions for heroes and towns
  • add Evil theme for ADD, EDIT and DELETE buttons in the Editor
  • fix object UID restoration after Redo operation in the Editor
  • add support for double click within Sphinx, Daily Events and Rumors lists
  • show date description for daily events
  • allow to disable any building in castles and towns in the Editor
  • add Find Artifact victory condition in Editor
  • add popup messages for right clicking on special map conditions
  • restrict obelisk placement to 48 objects
  • update logic related to human player selection for maps
  • fix crash when entering an empty line in text boxes
  • fix town placement over action objects
  • allow normal victory for "Accumulate gold" condition
  • fix the display of identical artifacts captured in battle
  • Magic Book window: show the maximum number of spell points
  • add "Out of Time" and "Accumulate Gold" map conditions within the Editor
  • add support of editing daily events within the Editor
  • show pressed monster button on Editor panel while clicking on it
  • add hotkey for passability within the Editor
  • add color names to Traveller's Tent and Barrier objects within object selection window
  • reduce castle area for mouse right clicking inside Editor's castle selection window
  • update map type popup message by right clicking to include Resurrection maps
  • add a new variation of Cave object on the Adventure Map
  • change hero selection dialog in the Editor
  • add an ability in the Editor to edit Rumors for maps
  • bring the logic of the Summon Boat spell for the human player in line with its logic of operation in the case of AI
  • AI: fix the assertion failure when visiting an object that is impossible to stand on
  • fix castle and hero radar rendering in the Editor
  • fix Magic Garden being shown without animation within the Editor
  • speed up save file loading and saving operations
  • add '?' symbol to Virtual Keyboard
  • properly check the Price of Loyalty resources in order to enable the Editor
  • move an existing object in front while trying to place an exact one on the same tile in the Editor
  • generate a random hero portrait for the Editor
  • fix crash when a hero is killed defending a castle
  • differentiate Random Castle and Town names in the Editor
  • update the Swedish translation
  • fix invalid logic for setting random artifacts
  • put the Graveyard object to the correct category, "hide" the alternative versions of Graveyard sprites
  • remove the AI unit growth bonuses and tune the income bonuses for different difficulty levels
  • limit the minimum slider length to 15 pixels
  • update the Portuguese translation
  • fix hero editing assertion
  • update the Ukrainian translation
  • fix random artifact types
  • implement the file manager for FH2M maps in Android
  • force use the non-typeable hotkeys for text input dialog and allow starting a new line in multiline texts
  • fix Editor instruments' buttons rendering
  • AI: properly handle the Spell Book artifacts on the Adventure Map
  • add missing checks for Miscellaneous objects in the Editor
  • add missing Sphinx part
  • fix text editing crash
  • fix crash when using quick switch to hero when castle is current object
  • fix the evaluation of the DOUBLE_SHOOTING and DOUBLE_MELEE_ATTACK abilities
https://github.com/ihhub/fheroes2/releases/tag/1.1.0

Changes in v1.1.0 (22 May 2024):

  • properly connect Streams and Deltas while placing Streams
  • do not allow placing Ultimate Artifact on non-diggable terrain in Editor
  • use golden color to highlight cells that are sometimes possible to edit
  • set the last edited map file as default for the new Standard game
  • allow picking-up the Magic Book artifact from the Adventure Map
  • show a warning message for no modification of normal artifacts
  • show a warning message that streams and roads cannot be placed on water
  • fix Editor interface items positions when Hide Interface mode is enabled in the engine
  • speed up object erasure in the Editor
  • allow only English to be used for text input within the Editor
  • add a general text for action objects with no metadata
  • display object coordinates in the right mouse click popup window
  • implement Event details window in the Editor
  • add generated buttons for map file dialog
  • make Editor panel buttons change good/evil interface
  • fix std::string serialization
  • implement base functions of Map Specifications dialog for the Editor
  • update the Swedish translation
  • add UI window to edit Sphinx properties
  • change a message while trying to get another Magic Book
  • fix the flickering of the map filter buttons in the map selection dialog
  • add an extra space between UI elements in the monster separation window
  • implement simple Save Map dialog for the Editor
  • properly handle objects while changing terrain in the Editor
  • properly connect roads and castles in the Editor
  • add a multi-line text editing feature to edit Sign and Bottle texts in the Editor
  • fix software cursor show delay
  • allow Events to be placed on Water within the Editor
  • remove Editor's beta flag
  • add Editor icon to the Main Menu
  • add a window to enter Random Ultimate Artifact radius
  • describe all Adventure Map objects used in the game
  • add relaxed requirements for object placement in the Editor
  • add a shortcut to go to the Main Menu from the Editor
  • allow river deltas to be placed anywhere in the Editor
  • implement Castle/Town details dialog in the Editor
  • add logic to handle victory and loss conditions for maps made by the Editor
  • fix typo in Hot Seat maximum players value
  • update the Russian translation
  • update the Portuguese translation
  • add a window to change Monster properties in the Editor
  • add the jailed hero details dialog in the Editor
  • implement hero details dialog in the Editor
  • do not add scaled resolutions for PS Vita
  • avoid extra I/O operations while changing game's settings
  • change the text in the monster separation window
  • introduce new object types: Swampy Lake and Frozen Lake
  • fix wrong name for Neutral race troops
  • update the Romanian translation
  • update the Ukrainian translation
  • use the AI pathfinder to assess the threat of enemy heroes instead of relying on the region database
  • update the Hungarian translation
  • fix hero battle info text X offset
  • make the default left and right hotkeys select skills in the level up dialog
  • add Editor related options
  • update the Spanish translation
https://github.com/ihhub/fheroes2/releases/tag/1.0.13

Changes in v1.0.13 (16 March 2024):

  • fix Sphinx title offset
  • add a window telling about demo version being used
  • add possibility to "draw" the attack angle between two hexes on touch screens
  • fix double daily resources award
  • fix rendering flaws of battle journal when using scroll bar
  • update the French translation
  • fix delayed cursor in campaign briefing dialog
  • add convenient list scrolling for touch screens
  • fix army split dialog text overflowing the dialog and add troops name
  • fix multiple objects and add missing ones in the Editor
  • fix a crash with AI hero animation
  • fix the troops carry over mechanics for campaign
  • update the Ukrainian translation
  • update the Swedish translation
  • update the Danish translation
  • kingdom Overview screen: automatically update status of castle dwellings that have just been built or upgraded
  • update the Vietnamese Translation
  • fix the mechanics of Genie special ability
  • add multiline stats in hero info window in battle
  • update the Hungarian translation
  • update the Spanish translation
  • fix many typos and improve English strings
  • add info about ranged penalty elimination to archery skill description
  • update combat disabling dialog text
  • adjust the difficulties of campaign scenarios that were hard-coded in the original game
  • update the resource panel immediately after a purchase in a castle
  • speed up application loading
  • add a feature to align the text non-uniformly
  • make several buttons text adapted and fix okay button redraw
  • add quick hero switch feature to the adventure map interface
  • cursor update code improvements
  • fix accidental map scrolling after exiting castle/hero screen
  • auto combat toggling improvements
https://github.com/ihhub/fheroes2/releases/tag/1.0.12

Changes in v1.0.12 (07 February 2024):

  • update the Russian translation
  • update the Spanish translation
  • correct icons alignment on the hero meeting screen
  • update the Polish translation
  • fix the retaliation of archers attacked by an ally under the influence of Berserker or Hypnotize spells, improve the AI usage of Hypnotize spell in general
  • fix incorrect Artesian Spring evaluation by the AI
  • make rules for AI surrender and retreat more unified
  • fix Oasis object passability
  • always offer one native hero at the beginning of a new week
  • puzzle and View World dialogs rendering improvements
  • implement Landscape Miscellaneous (non-action) objects placing in Editor
  • fix OKAY button translation for Interface Settings dialog after any setting change
  • make the AI not to know what objects contain
  • fix issue when Blind or Paralyze has been applied to a hypnotized unit during its turn
  • implement Adventure (action) Miscellaneous objects placing in Editor
  • tune the AI performance at different difficulty levels
  • add surrender cost to battle result dialog
  • improve overall image processing performance
  • update spell points, formations and artifacts descriptions
  • add infos on the cost of surrender
  • allow AI units covering an archer with the AREA_SHOT capability to attack neighboring units on their own
  • use proper name for PoL campaign in High Scores
  • use CP1257 code page for Lithaunian
  • offer the Wisdom skill to the heroes of "magic" classes on a mandatory basis at least once every three level-ups
  • implement Mountains, Rocks and Trees placing in the Editor
  • make the AI attack human heroes that have a greater chance to win than the AI heroes
  • implement Power-ups object placement in the Editor
  • allow AI units that ignore retaliatory strikes to attack neighboring enemy units while covering archers
  • avoid visiting Oasis and Watering Hole objects by AI heroes if they bring no benefit
  • make AI hero behavior depend on the time spent on the map
  • improve fog discovery by the AI heroes
  • adjust text in the skill popup dialog
  • implement Mines placing in the Editor
  • improve AI hero interaction with Witch's Hut object
  • allow the AI-controlled hero to surrender if his kingdom has sufficient gold reserves
  • add text width-adapted CANCEL button, change to StandardWindow for Resolution, Language, Adventure, File and Scenario Info dialogs
  • update Hungarian translation
  • add dwellings into the Editor
  • fix rare fog of war rendering issues
  • allow AI heroes to surrender if the conditions of retreat have been met, but it is impossible to retreat
  • implement the AI logic to transfer the slowest troops to the garrison at the end of the turn to try to get a movement bonus on the next turn
  • mark fheroes2 as DPI-aware on Windows
  • speed up image loading
  • speed up file loading and reduce memory usage on the Adventure Map
  • improve the AI logic for pay-to-hire dwellings on the Adventure Map
  • improve the AI heuristics of covering shooters when using defensive tactics
  • update buttons and add popup windows for them in Battle Only mode
  • use the "cautious offensive" tactics for AI only against melee-only armies without the distant attack potential (including damage spells)
  • update the Swedish translation
  • fix heroes with no names
  • add base code to load new map format files
  • use singular Mine form for the corresponding object
  • fix inaccurate Jail object removal
  • add missing rules for the plural in Hungarian language
  • restrict secondary skill name and level to the UI area
  • fix too wide text in quick hero info dialog
  • hide swap army/artifact buttons in the Battle Only mode
  • update several text descriptions
  • add Campfire object in the Editor
  • take into account SHIFT and CAPS LOCK being used at the same time
  • make radar rendering optimization
  • fix the AI spell damage estimation logic for units immune to the given spell
  • rework editor instrument groups: add new buttons, rework instrument panel, add evil interface
  • fix multiple spellbook-related issues in the Battle Only mode
  • update French translation
  • show an error when it is not possible to save a game on a hard disk
https://github.com/ihhub/fheroes2/releases/tag/1.0.11

Changes in v1.0.11 (23 December 2023):

  • improve the logic of AI defensive tactics
  • add Tree of Knowledge claimed and cost info to quick info dialog
  • add a different object popup window logic for the Editor
  • implement town and castle placing in the Editor
  • update the Spanish translation
  • update the French translation and add missing offset for an A with accent
  • update Bulgarian translation
  • increase width and height of the Campaign Difficulty selection dialog
  • make speed of fade-in & fade-out animations for AI-controlled heroes dependent on the AI speed setting
  • speed up battle pathfinder logic
  • update Spanish translation
  • add Spanish and Portuguese button font letters
  • fix invalid focus update after AI hero battle
  • update Danish translation
  • speed up the original map format reading
  • fix a crash with castle overlapping inside a map
  • add basic logic to load and save maps through Editor UI
  • add text rendering within a given ROI
  • do not show quick info for hidden buttons inside castle building info dialog
  • add missing AI team alliance to Evil campaign's 6th scenario
  • update Swedish translation
  • update Hungarian translation
  • update Vietnamese Translation
  • fix update of the morale/luck indicator when changing the hero in the Battle Only mode
  • add base map file format for the Editor
  • add Hotkeys categories for the future UI improvements
  • fix scroll location on file deletion
  • rework Battle Only mode
  • add cell selection in Details mode for the Editor
  • speed up map loading for New Game
  • allow application closure by close button if no resources available
  • fix multi-font text offset calculation
  • properly evaluate potential attack positions for wide units
  • correctly manage touch device events
  • add ability to place Ocean Objects within the Editor
https://github.com/ihhub/fheroes2/releases/tag/1.0.10

Changes in v1.0.10 (18 November 2023):

  • update Russian translation
  • rework Town Portal dialog
  • add artifact placement in the Editor
  • make Oracle dialog use selected interface mode (Good/Evil)
  • add treasure placement in the Editor
  • update hero status after digging on the Adventure Map
  • fix player names overlapping in Oracle and Thieves' Guild dialogs
  • fix dialog frames not being consistent for the same size windows
  • speed up monochrome cursors loading
  • fix rendering issue in Kingdom Overview dialog while dismissing a hero
  • fix castle and hero lists' updates after dismissing a hero in Kingdom Overview dialog
  • fix invalid attack positions from moat during battle
  • add support for right SHIFT, CTRL and ALT hotkeys
  • AI takes into account the spell immunity when calculating the effectiveness of mass damage spells
  • update Hungarian translation
  • fix incorrect AI estimation for moves during battle when a battlefield contains objects
  • update Vietnamese translation
  • fix several issues with loading ICN resources
  • add support for the future new heroes
  • fix the logic of purchasing a boat in a shipyard
  • increase the priority of those enemy units that have not yet got their turn, for proper AI decision making
  • add hero action button image
  • fix spelling in campaign text
  • display 0 shots during battle for archers with no shots left
  • fix random generator in normal and auto-combat modes
  • fix castle dialog rendering issues
  • adjust welcome window text at the first game launch
  • teach AI to use the marketplace to accelerate the development of their castles
  • update German translation
  • implement erase tool in the Editor
  • fix recruit dialog's MIN/MAX buttons when switching between creature upgrades
  • update Swedish translation
  • show proper Quick Info window for a hero during battle
  • fix troops' sprites overlapping in quick info
  • prioritize hiring those heroes whose portraits are not used by scenario specific heroes
https://github.com/ihhub/fheroes2/releases/tag/1.0.9

Changes in v1.0.9 (11 October 2023):

  • add "tent visited" info to barrier quick info dialog
  • update Vietnamese translation
  • rework Hot-Keys dialog
  • fix combat victory window creature position
  • Town Gate and Town Portal spells: use depersonalized wording
  • add an ability to place heroes in the Editor
  • add an ability to place Random Monsters in the Editor
  • fix rendering of very long scenario names in the campaign briefing dialog
  • disable the not implemented Random Map option in the Editor
  • update German translation
  • make a long press on the "continue movement" button to reset a hero's path
  • use the "continue movement" button to interact with an object a hero is standing on
  • make Grass the default terrain for new maps in the Editor
  • restrict heroes' meetings and army merging on Easy difficulty
  • AI should avoid splitting troops on Easy difficulty
  • add functionality to place monsters in the Editor
  • add a mirror image check during spell evaluation
  • teach battle AI to use shield spells
  • implement streams' placing in the Editor
  • adjust AI combat spell heuristics
  • fix rendering of long text in the Hero screen status bar
  • update Ukrainian translation
  • implement roads' placing in the Editor
  • fix the AI first strike logic
  • update Hungarian translation
  • fix battle AI protecting paralyzed archers
  • properly display player's name in the New Game window
  • fix memorizing the position in the map list when changing the map size filter
  • adjust the position of luck and morale icons in the hero info window
  • update the followers window to support text mode
  • fix the logic of ALWAYS_RETALIATE regarding paralyzed units
  • add historical changes support for the Editor
  • add the ability to confirm actions in battle for touch devices
  • update Russian translation
  • fix Editor Main Menu hotkeys
  • update Swedish translation
  • speed up overall rendering for cycling animation
  • do not render text beyond the info and status bars during battles
  • rework game settings on the Adventure Map
  • remove double spaces in translatable texts
  • update Bulgarian translation
  • update Slovak translation
  • update Czech translations
  • update Danish translation
  • use Home and End hotkeys to navigate among items within a list
  • always use the nearest cell to attack the nearby unit if a monster is under the Berserker spell
  • fix an assertion when a hero starts moving and a player immediately mouse left clicks on the Adventure Map
  • improve path calculations by AIWorldPathfinder in planning mode
  • Wand of Negation should grant immunity against the Mass Dispel spell
https://github.com/ihhub/fheroes2/releases/tag/1.0.8

Changes in v1.0.8 (11 September 2023):

  • fix number placeholders not being replaced in campaign spell bonus texts
  • fix spell rendering issues when words are divided in the middle
  • fix ? symbols appearing in single-line texts
  • generate vertical high scores buttons
  • display missing resource dialog for at least 5 seconds
  • show only skills that the hero does not already have in battle only skill selection list
  • show highscores after multiplayer game
  • improve the logic of kiting enemies with archers
  • update Vietnamese translation
  • update Hungarian Translation
  • adjust the description of the Eagle Eye skill
  • fix an empty gap in between lines in buttons font
  • update Russian translation
  • translate disabled buttons and reset them when changing languages
  • make vertical buttons translatable
  • implement terrain transitions in Editor
  • rework the Save/Load game dialog to allow variable dialog size and support Evil interface
  • change Army Order to Turn Order
  • Add Czech to original resource exception
  • do not close File options menu on cancelling load game dialog
  • fix foreign pixels on snow battlefield objects
  • do not try to scout the area if the hero is in jail and gets an artifact assigned using the map editor
  • update Slovak translation
  • cancel Hut of Magi reveal area animation when a player clicks any button
  • show the "You have been eliminated from the game" message in the multiplayer game
  • add small skill icons for Xanadu visit dialog
  • fix invalid logic for some objects on water
  • update Polish translation
  • speed up map, translation and save files loading
  • fix missing hero and town name in dialogs for non-English languages
  • fix Load/Save file title position and color
  • change Shipyard construction message
  • expand clickable area for settings in the Main Menu
  • shift text in Surrender window
  • show ... in Load/Save File dialog for long names
  • fix monster name position in monster info dialog
  • speed up rendering for specific buttons
  • fix multiple rendering issues in the Kingdom Overview dialog
  • adjust text for Quick Info dialogs
  • improve fading animation using Redmean color distance calculation
  • limit Dimension Door spell usage for AI heroes on lower difficulties
  • center text in hero battle info window
  • add A and O with diaereses to CP1252 button font
  • fix size of the button letter Æ
  • improve Mage guild status message for learnt spells
  • add "New Month!" title for new month
  • add "Victory!" title to victory dialog
  • update Danish translation
  • update Ukrainian translation
  • allow early exit from puzzle map during reveal animation
  • remember map filter selection until you quit the game
  • improve the distance estimation when an AI-controlled hero passes through objects on the map
  • update Swedish translation
  • AI heroes should decline battles if passing by
  • implement basic terrain draw in Map Editor
https://github.com/ihhub/fheroes2/releases/tag/1.0.7

Changes in v1.0.7 (15 August 2023):

  • properly update uncovered fog with all hero actions
  • fix an issue when AI hero "jumps back" during the fog discovery
  • AI heroes should not know what exactly a Treasure or Sea Chest contains
  • do not play simultaneous walk/fly sounds for battle speed 9 and 10
  • do not handle an event on the map twice
  • fix AI estimation of the castle garrison strength for priority tasks
  • rework "select from list" dialogs and also make all elements within dialogs right clickable
  • battle AI should switch to offense mode instead of passing turns
  • update Russian translation
  • add the ability to export and import save files in Android Toolset application
  • make many in-game buttons translatable
  • fix Army info button in level up dialog
  • update Ukrainian translation
  • update German translation
  • add Summon Boat spell support for AI
  • rephrase various game dialogs
  • add a dialog to confirm auto combat
  • add "Quit" title to quit dialog
  • fix Zounds grammar
  • update Norwegian Translation
  • the Shield spell should not affect the damage of the castle towers
  • apply AI growth bonus only on first AI player turn
  • show "cast down" animation for heroes on the battlefield
  • apply Cure & Mass Cure spells only if the target unit is either damaged or has negative magical effects
  • fix hero last frame delay after the spell casting animation
  • speed up several spell animations during battle
  • fix missing first animation frame of heroes on the battlefield
  • change heroes animation speed on the battlefield
  • fix puzzle screen exit button theme
  • reduce CPU usage while rendering castle's Well dialog
  • fix campaign buttons' rendering issues
  • make campaign buttons translatable
  • update Slovak translation
  • update Danish translation
  • update Swedish translation
  • disable Campaign button if no campaign resources are present
  • improve AI pathfinding logic regarding protected and guarded tiles
  • avoid engine execution with corrupted video files
  • add ability to select instrument brush and brush size in Editor UI
  • make thieves guild adapt background to chosen interface
  • fix a possible crash in Android toolset application
https://github.com/ihhub/fheroes2/releases/tag/1.0.6

Changes in v1.0.6 (15 July 2023):

  • allow to lower the campaign difficulty during playthrough
  • update Russian translation
  • reduce CPU usage while rendering High Score dialog
  • add some missing horizontal buttons to translations
  • fix missing redraw in Battle Only dialog after cancelling hero selection
  • fix last hotkey not showing up in the hotkey dialog
  • add Dismiss hotkey to hero screen
  • create basic Map Editor GUI
  • update Polish translation
  • add checks for object reachability when calculating their value for AI heroes
  • fix AI logic for visiting Shrines and Arena
  • correct spell value estimation for AI heroes
  • fix a case when a dead AI hero was trying to reinforce army in a castle
  • update priorities for AI heroes based on battle outcome and fog uncover events
  • rework the spell generation in castles' Mage Guilds
  • update Spanish translation
  • speed up Armageddon spell rendering
  • fix invalid pixels in multiple images from the original resources
  • speed up resource loading
  • update Slovak translation
  • do Main Menu fade-in before showing first game run
  • fix the fade effect on the "View World" screen
  • properly restore environment sounds and terrain music after opening a castle dialog from the Kingdom Overview screen
  • fix cases when false symbols appear after the blinking cursor in text input dialog
  • rework game credits to keep aspect ratio
  • add extra windows and greying out conditions for Summon Boat spell
  • fix several button text placements and button press rendering
https://github.com/ihhub/fheroes2/releases/tag/1.0.5

Changes in v1.0.5 (14 June 2023):

  • improve AI castle defensive strategy on Adventure Map
  • fix rating in campaign congratulations text in win video
  • update Danish translation
  • adjust battlefield Idle and Flag animation speed and avoid setting 0 animation delay for battlefield actions
  • show the currently selected bonus in the campaign scenario UI if the campaign scenario is already in progress
  • update Polish translation
  • add shadows for the Virtual Keyboard buttons
  • fix okay button not being redrawn in battle options dialog
  • improve army distribution in castles for AI players
  • make the text input cursor blink and add the ability to set the cursor position anywhere in the edited string
  • move jobless AI heroes into castles on a last day of a week
  • fix monster upgrade logic when AI was wasting resources for nothing
  • do not check whether a hero can cast a spell if spellcasting is prohibited in principle
  • fix AI heroes behavior ignoring empty castles with commanders
  • speed up AI decision making on Adventure Map
  • fix Magellan's Maps visit by AI heroes when discovered objects were not being added for exploration
  • fix missing logic for AI heroes to meet each other in the middle of a turn
  • reduce unit growth bonus for AI
  • do not play the same kill/wince sounds simultaneously
  • allow AI heroes to retreat when the kingdom has full house of heroes and when there are enough resources on the next turn
  • fix a crash when AI heroes capture a dwelling protected by monsters
  • add Editor Main Menu (only for development builds)
  • fix the Skeleton passability
  • fix the logic for defeated heroes in campaign scenarios
  • fix the logic of recognizing objects guarded by neighboring monsters
  • update hero's path after inspecting a castle
  • add Evil interface version of Monster recruitment dialog
  • update Bulgarian translation
  • add screen fade effect for transiting between game sections
  • add a check to avoid a crash for corrupted game resources
  • fix the rendering of the number of units during the castle siege
  • update Russian translation
  • speed up battlefield rendering
  • fix incorrect spell efficiency display for resurrection spells
  • set music type to MIDI if no MUSIC directory exist
  • fix cases with dropping audio volume when MUSIC directory is not present
  • fix crashes for Android devices due to using a buggy third-party package
  • fix cases when AI ignores some objects during path evaluation
  • use 22050 sound sample rate for PS Vita to fix high CPU load
  • add diacritic signs to CP-1250 button font
  • update Slovak translation
  • update Ukrainian translation
  • fix Android version for Android 7 or lower devices
  • do not reset castle or heroes scrollbars when hero moves
https://github.com/ihhub/fheroes2/releases/tag/1.0.4

Changes in v1.0.4 (13 May 2023):

  • add Polish and Russian languages support for Virtual Keyboard
  • fix absence of delay after animating creature wince and before making next move
  • make haunt, set elemental guardian, identify hero and visions spells gray out when cannot be used
  • do not stop hero's movement after the first Dimension Door jump
  • do not show that enemy town or castle has no garrison if kingdom has no Thieves' Guilds
  • fix idle animation lag while casting any spell
  • fix creature idle animation freeze during Blind / Paralyze spell casting
  • fix an issue that caused an AI-controlled hero standing next to Stone Liths to block the path of another AI-controlled hero standing on these Stone Liths
  • add checks to detect corrupted data resources
  • improve the resource value estimation algorithm for AI
  • fix logic and reward of Daemon Cave object for AI
  • add an ability to cancel waiting for the end of the pre-battle sound
  • update Polish translation
  • create small and large obstacles on the battlefield at the same time
  • do not make an empty text line at the end of phrase and fix text rendering in a wider area than given maximum width
  • fix Battlefield animations freeze while waiting for Good Luck sound to end
  • add popup windows for monster dialog buttons
  • fill main menu with background when we do not stretch the main menu main image
  • update Russian translation
  • fix not returning to load menu while switching between campaign scenarios
  • fix Shipwreck Survivor bonuses
  • fix AI pathfinding when Spell Scroll was considered as an artifact which requires to defeat an army
  • rework logic for all Adventure Map objects' metadata
  • fix adventure map fog reveal on campaign scenario restart and when loading a Hot Seat save made in the first game day
  • adjust spell info message when hero has zero (0) mana
  • fix calculation of castle towers strength for AI
  • improve dialog titles related to losing the game
  • update Bulgarian translation
  • strategic AI economy update
  • AI should check for castles and funds before retreat
  • fix software cursor freezes during certain fading animations
  • rework the search algorithm for available scaled resolutions
  • show map ratings in victory video, add subtitles and color fading animation
  • add extra checks to prevent loading renamed MX2 maps on demo version
  • add "End Turn" title to dialog when heroes can move and you are ending your turn
  • catapult and castle towers should still act, even if there are no troops in the respective armies capable of taking any action
  • update Vietnamese translation
  • fix the behavior of Berserk and Hypnotize spells
  • add language support for highscores
  • expand wide screen support
  • properly handle absolute and relative paths in the CDDrive registry key for Windows scripts
  • update Danish translation
  • update Swedish translation
  • reset battlefield grid cursor position after using the spell book
  • fix a crash on deleting last save file
  • update Czech translation
  • update Slovak translation
  • update Ukrainian translation
  • fix recurring global events
  • redraw the status window after the amount of kingdom resources has changed at the beginning of the day
  • do not render hero/boat over the bottom map border
  • add "New week!" title to dialog showing start of a new week
https://github.com/ihhub/fheroes2/releases/tag/1.0.3

Changes in v1.0.3 (11 April 2023):

  • update German translation
  • update Norwegian translation
  • preparations for Google Play Market release
  • add missing frame for hero information dialog when it is opened from hero meeting dialog
  • improve the destination indication for Teleport spell
  • translate more UI buttons within the game
  • fix endless jumping AI hero behavior while using Dimension Door spell
  • add Virtual Keyboard open button to Save Game and Player Name dialogs
  • add values to Morale and Luck stats within artifact description
  • show approximate information about the mine guardians to a non-owner player
  • adjust number of resources subtracted in event messages
  • fix projectile render position when hitting the target creature
  • reduce AI obsession with Wells
  • optimize object priority logic for AI heroes to prioritize more important locations
  • remove path icon after a hero/boat makes a turn, not before
  • show mirrored monster image in army order
  • make hotkey names translatable
  • improve AI fog discovery logic
  • fix a case when a hero has the same secondary skill but different levels of it set by an author of a map
  • add gold missing in Statue and Dungeon building description
  • add Vietnamese translation
  • fix the number of regenerated spell points with the Mysticism skill
  • focus on the AI hero before he disappears due to boarding a boat or using a Dimension Door or Town Portal spell
  • add legacy game detection on Windows x64
  • fix clicks in Android MIDI music
  • speed up Adventure Map rendering
  • fix AI hero animation being interrupted while moving inside a fog for the current player
  • fix Alchemist Lab flag and Ghosts from Abandoned Mine rendering while rest of the object is not visible on the screen
  • fix boat's shadow being rendered over a boat while sailing diagonally
  • adjust recruitment window position on castle well and kingdom overview
  • apply the commanding hero/captain bonuses to the castle towers
  • fix the number of raised skeletons by Necromancy after battle
  • update Polish translation
  • fix incorrect number of Ghosts present in Abandoned and Haunted Mines
  • add Slovak translation
  • properly handle the situation when wandering monsters and an AI hero eliminate each other
  • update battle log with special abilities of Vampire Lords and Ghosts
  • update Belarusian translation
  • add numeric speed of monsters in information window
  • fix quick info for non-action objects when their action tile is under fog
  • block Chain Lightning if first target unit resists the spell
  • fix cases when Road sprite is drawn over a hero
  • fix Hero shadow rendering on Adventure Map
  • update Russian translation
  • show Spell Points for spells in Magic Book popup dialogs
  • fix necromancy and calculation of casualties with mirrors
  • properly track the Mirror Image spell duration
  • update documentation about Android
  • update Czech translation
  • update Swedish translation
https://github.com/ihhub/fheroes2/releases/tag/1.0.2

Changes in v1.0.2 (12 March 2023):

  • fix display of Haunted Mines on mini-map and in View World
  • update the Norwegian translation
  • allow resurrected units to act on the current turn if they have not yet had their turn
  • add missing part of Captain's Quarter in Sorceress Town
  • allow to resurrect Elementals
  • fix the battle casualty report when non-true Resurrect spell was used during battle
  • redraw hero icons to display movement bar change before action dialog box is shown
  • fight the guardians on dwellings on Adventure Map only once per game
  • change the logic of reinforcement of the guest hero's army during the castle defence
  • do not show Dragon City on mini-map
  • summon boat spell will only summon friendly boats
  • allow the player to refuse to level up in the Tree of Knowledge even if this level up is for free
  • add virtual keyboard support for touch devices
  • grey out Summon Boat, Town Gate and Town Portal spells if they cannot be used
  • clean up AI priority tasks if attacker was killed
  • update sounds used while visiting dwellings on Adventure Map
  • add logic of AI heroes using town portal
  • add missing symbols to button font
  • update Polish translation
  • fix high CPU usage during battle while using highest animation speeds
  • fix battle AI tactics estimation
  • fix pathfinding not being updated after revealing the fog on visiting Magellan's Map
  • animate lighthouse in lighthouse dialog
  • fix the experience calculation for AI-controlled heroes while visiting Tree of Knowledge
  • add a frame for a hero portrait on the quick info dialog
  • add missing experience being displayed in the Tree of Knowledge window
  • fix music effects while visiting an empty object on Adventure Map
  • display the world date for save files
  • rework AI hero task priority logic
  • fix invalid popup window being displayed while clicking on an empty hero list area within Adventure Map
  • add Graphics option icon
  • fix corner cases of fog rendering
  • fix invalid calculation of AI path leading to a crash
  • show sleeping hero icon for hero's portrait within castle dialog
  • speed up rendering on Adventure Map
  • properly restore the screen after closing the hero dialog during combat
  • render background between HEROES and TOWNS/CASTLES buttons in Kingdom Overview window
  • fix possible random crashes during the gameplay
  • fix Iron and Steel Golems animation issues
  • show kingdom income when gold per day income is clicked within Kingdom Overview window
  • fix a crash while visiting a castle after an ally captured it
  • speed up file searching on Windows
  • fix the spell id calculation for a spell scroll while loading a map
  • fix puzzle map window position
  • fix View World default adventure map position
  • memorize zoom level of the View World screen
  • fix inability to move monsters after Good Morale event
  • fix unintended ability to upgrade troops during battle
  • fix huge CPU usage in hero window during battle
  • redevelop standard window generation logic
  • update Bulgarian translation
  • fix volcano sounds
  • update Russian translation (main menu and dialog buttons)
  • fix issue with the puzzle rendering
  • fix musical effects for various objects
  • fix stereo audio playing in SMK files
  • add letter "ÐŽ" and "’" sign to Cyrillic (cp1251) button font
  • add lighthouse information popup in kingdom overview
  • fix an invalid option for scenario 1 of Roland Campaign
  • optimize mini-map rendering
  • update Czech translation
  • add proper hotkeys option icon
  • fix title in German translation
  • optimize View World rendering
  • add tooltip damage info for single target attack spells during battle
https://github.com/ihhub/fheroes2/releases/tag/1.0.1

Changes in v1.0.1 (08 February 2023):

  • add the ambient sound for Abandoned Mine
  • add support for scaled resolutions
  • instantly update status bar in battle for hero's dialog options
  • fix invalid Kingdom income calculation
  • fix incorrect status bar update call
  • update Czech translation
  • add German and Russian translations of Android Toolset
  • Android Save File Manager: implement filtering of save files by type
  • fix scroll bar bottom position when dragging and fix high FPS rate when dragging scroll bar by mouse
  • make a narrower button font for cp-1251 (Cyrillic) characters
  • fix Druid projectile start position for shooting up
  • add PS Vita fixes and gamepad mapping improvements
  • add Danish translation
  • fix shooters projectile position during battle
  • fix high CPU load on Adventure map when Hero speed is set to Jump
  • Android toolset: add the ability to browse & delete save files
  • fix loss of the first frame in the after attack unit animation
  • update spell points for campaign heroes at the start of a scenario
  • uncover the fog during the hero's instantaneous movement only if the hero is actually moving
  • do not allow to dig for Ultimate Artifact second time
  • show spell effect animation so as not to cover the front troops
  • fix screen restoration after closing monster info dialog
  • fix the AI resurrect spell logic
  • fix the Dimension Door shadow on resolutions 640+x480 & 640x480+, temporarily hide auxiliary panels in "no interface" mode
  • rework pathfinding algorithm during battle to fix non-optimal paths for monsters
  • add Mossy Rock object which appears only on Swamp terrain while in the original game this object has no name
  • optimize Adventure Map rendering
  • do not do redundant redraws when dragging Adventure Map with the mouse
  • fix walking animations of certain monsters
  • fix the bridge operation when a wide friendly unit steps on it from the moat
  • fix creature wince animation for low morale and Lich cloud cases during battle
  • optimize Holy Shout spell effect rendering during battle
  • allow wide units to take a step back during battle
  • fix certain Peasant Huts being displayed as Thatched Huts with no ambient sounds on Adventure Map
  • update Polish translation
  • avoid excessing CPU usage for multiple windows in the game
  • set audio frequency to 44100 on Windows to avoid cracking sounds during playback
  • add fh2 toolset application on Android to help with setting up the main application
  • update French translation
  • reduce CPU usage in Select Language dialog
  • fix a case when external music was not being played on Ubuntu
  • fix incorrect logic for monster placement on Adventure Map
  • update German translation
  • do not lowercase creature name (or other string) when it is put first in phrase
  • fix forced Idle animation after switching to Static animation
  • fix screen flickering in SDL2
  • optimize Death Wave spell effect rendering during battle
  • automatically assemble artifacts sets if their parts were captured in the battle
  • fix controller support for PS Vita
  • add a full stop, A and E characters with accents for CP1252 button font
https://github.com/ihhub/fheroes2/releases/tag/1.0.0

Changes in v1.0.0 (21 December 2022):

  • add Ubuntu ARM support
  • update Polish translation
  • update the French translation
  • fix incorrect resource placements on certain maps
  • adjust "Battlefield Casualties" vertical position
  • fix bridge logic after morale event
  • enable the instant battle by default
  • optimize rendering in multiple places
  • update the Norwegian translation
  • add global hotkey to toggle the text support mode
  • make the regular small buttons translatable
  • make Trade button in Marketplace window disabled by default
  • add popup windows for monster recruit dialog
  • fix animation of slowed flying creatures
  • fix multiple hero related awards for campaigns
  • fix Death Wave, Holy Shout and Holy Word spell animations
  • do not mirror corpses of defeated troops during battle
  • fix rendering an extra empty line for specific texts
  • fix monster idling animation during battle
  • use logarithmic scale of sound volume
  • enable touch support for all devices
  • make separate hotkeys to cast battle & adventure spells
  • add the "Quit game" hotkey
  • handle hotkeys in the Adventure Map's File dialog
  • optimize defensive strategy for AI castles
  • fix black area not being rendering during video playback
  • reduce priority for bottles in sea for AI
  • make File Dialog and Adventure Dialog buttons translatable
  • do not stop object animation during AI turn
  • update Russian translation
  • fix text rendering for game option's names of certain translations
  • fix incorrect battlefield image restoration in the place of the previous damage popup
  • adjust several button font characters
  • rework the hotkeys concerning the hero movement
  • make the Main Menu's dialog buttons translatable for specific languages
  • display the amount of gold in the diplomacy dialog
  • show object animation during Hut of Magi visit
  • fix Dwarves death animation
  • fix very slow hero movement animation when moving a cursor with software cursor rendering
  • fix translated Cancel button in monster recruit dialog being switched to English
  • fix animation of bridge destruction during battle
  • fix the smoke animation when demolishing a castle building during battle
  • improve Adventure Map rendering performance
  • fix multiline word splitting for short phrases with a long first word
  • fix position of left barbarian's captain quarters part
  • reset the cursor position at the start of 'human turn'
  • add an option to toggle screen scaling type
  • recreate the original rainbow animation during battle
  • fix Scenario Info window elements
  • improve hexagon shading during battle
  • add Danish language option and font
  • improve rendering speed with software cursor rendering
  • fix French and Italian characters not being shown with their assets
  • set the minimum supported version to Android 5.1
  • introduce AI Scout role
  • fix fullscreen mode with DPI higher than 100% on Windows
  • fix multi-monitor fullscreen support on Windows
  • update Bulgarian Translation
  • add Android installation and usage documentation
  • fix the scenario info dialog position
  • generate resizable buttons for both interfaces
  • fix inability to toggle V-Sync option dynamically
  • do not show resolution dialog on handheld devices on the first startup
  • add mouse right click simulation on touchscreen devices
  • fix cursor being too small for certain resolutions
  • disable Adventure Map scrolling for handheld devices by default
  • change battlefield hexagon generation to match the original
  • make fullscreen mode as a default state for Android devices
  • implement all troops transfer between armies within castle dialog
  • scroll Adventure Map with mouse left button pressed
  • use parabolic catapult projectile flight trajectory
  • update credits page
  • always show the Ultimate Artifact behind one of the last four central pieces of the puzzle
  • update captain's mana on map load and when building the Captain's Quarters
  • remove and integrate the rest of experimental options
  • always center text when a maximum width is provided
  • fix UI elements for the unhired hero popup window
  • update Ballista and Turrets damage information when they are destroyed
  • correctly reflect the change of fullscreen mode in the graphics settings dialog when it was toggled using a hotkey
https://github.com/ihhub/fheroes2/releases/tag/0.9.21

Changes in v0.9.21 (12 November 2022):

  • fix audio playback issues on Windows OSes
  • do not show any hero status for AI heroes
  • add hotkeys for moving armies between heroes
  • update the Norwegian translation
  • fix monster upgrade cost formula
  • reset AI hero meeting flag every time if hero's strength has changed
  • add missing alliance conditions for the Succession Wars campaign last scenarios
  • add small optimizations for the pathfinding algorithm
  • fix incorrect evaluation of army strength where hero's abilities should not be taken into account
  • fix handicap income calculation
  • add right click quick info in more dialogs for hero and castle captain
  • fix possible assertion hit for campaign scenario info dialog
  • Luck / Morale related objects are now reset after meeting / battle for AI heroes
  • add a separate graphics options window
  • make more contrast for player objects on the minimap
  • do not override hero or castle selection focus on a game load
  • change language selection window to support many languages
  • improve the combat log's use of plural forms
  • draw the correct arrows for the paths on the adventure map
  • rework the troops arrangement mechanics for the castle defense
  • fix catapult's boulder animation
  • update position for text in difficulty selection dialog
  • add CP1252 French quotation marks
  • clear the kingdom's visited objects according to their lifetime, even if this kingdom has already been vanquished
  • update AI logic for monster distribution and recruitment
  • do not increase the number of upgraded creatures on Week Of/Month Of basic creatures
  • generate new MAX/MIN buttons for other languages
  • add Czech language option in game and add fonts
  • fix the troop splitting logic
  • include project's resource files into Android packages
  • translate language names in native language
  • add proper CP1250 font
  • update French translation
  • do not waste time to get useless monsters for an AI army
  • add audio support for Android devices
  • take Magic Book into account while visiting a castle by an AI hero
  • avoid using armies with 1 monster for AI heroes
  • lock the screen orientation to landscape for Android devices
  • fix campaign score sorting issue
  • fix an issue when kingdom overview scrollbar does not not remember last position
  • fix terrain colors on the minimap
  • memorize selected Scenario in Scenario Selection dialog
  • do not overwrite default platform's soundfonts if none is included into the package
  • update Hungarian translation
  • add Hungarian language option and font replacements
  • fix the shade used for mountains and trees
  • fix UI elements position in Select Scenario dialog
  • fix hero's fight cursor offset
  • fix heroes position on battle screen
  • add Android compilation
  • update Russian translation
  • redraw the castle's resource panel when a hero purchases the spellbook
  • add Dutch font and language option
  • update language dependent resources while changing language
  • update Bulgarian Translation
  • fix the Week Of / Month Of logic
  • update Belarusian translation
  • fix button font generation for original buttons
https://github.com/ihhub/fheroes2/releases/tag/0.9.20

Changes in v0.9.20 (10 October 2022):

  • add Russian and French button translations
  • update the Norwegian translation
  • recalculate the hero's path when the hero was selected with the mouse
  • fix stopped music in events of quickly closing dialogs with internal music
  • add proper logic for artifact exchange between AI heroes
  • add Dutch translation
  • do not let the archers perform a double attack if they are out of ammo
  • add Hotkey support for restarting Campaign's Scenario
  • AI heroes now use spells from scrolls
  • fix neutral town unit growth
  • display detailed information about the composition of alliances in the scenario info window
  • add date to logging for the future bug fixing
  • add turkish translation
  • make sure that there is a place for the Ultimate Artifact in the artifact bag before trying to dig it out
  • do not ask player's name if the score is too low for High score board
  • add Romanian translation
  • hide console window for Windows OSes and add log file for this platform
  • add Romanian font and language option
  • update Polish translation
  • add Turkish language option and CP1254 font
  • add proper icons for Petrification spell
  • speed up Adventure Map rendering
  • take into consideration a case with full artifact bag while checking AI hero's path
  • generate button fonts for different code pages
  • apply usual rules for unit growth in neutral towns/castles with custom troops
  • decrease monster growth bonus for AI
  • fix incorrect usage of Dimension Door by AI heroes
  • make logging for monster movement in battle more user-friendly
  • add UI improvements of the Settings dialog
  • fix logic of processing cells containing units available for possible AI unit attack
  • fix incorrect object evaluation for AI heroes on boats
  • add a feature to give human player control to AI (debug build only)
  • make creature names lowercased for certain dialogs
  • generate new Gift button
  • generate full button English alphabet and new Battle Only button
  • fix switching of terrain music in case of hero loss
  • update Bulgarian translation
  • add Handicap feature for single and multiplayer games
  • fix a case when a hidden scrollbar during battle is visible for one frame
  • fix sound volume for objects while using external music type
  • include rating calculation for Campaign's high score
  • fix incorrectly rendered monochrome cursor for campaign selection window
  • update French translation
https://github.com/ihhub/fheroes2/releases/tag/0.9.19

Changes in v0.9.19 (11 September 2022):

  • add popup dialogs for Well's buttons
  • generate MIN button based on newly added font
  • fix constantly moving AI heroes when they have nothing to do
  • update Polish translation
  • implement some improvements when exchanging an army between heroes
  • show intro videos like in the original game
  • fix messages displayed for captains during battle
  • update Bulgarian translation
  • correct start resources for AI players
  • add a popup dialog for Days spent info within campaign dialog
  • make Artifact evaluation for AI more granular
  • add Difficulty selection for Campaigns
  • add popup dialogs for mage guild and scenario info windows
  • fix rendering of Mine Guardians
  • do not show monsters and campfires on Puzzle screen
  • fix moving AI hero rendering
  • implement instant finishing of battles
  • update Norwegian translation
  • fix incorrect rendering of some icons in The Price of Loyalty campaign windows
  • make "Show terrain penalty" option the default
  • fix double income from captured objects
  • fix the distribution of Mutant Zombies in the Graveyard
  • fix the battle order after bad morale events
  • always use the current color of a unit when toggling auto battle (take the Hypnotize spell into account)
  • speed up file search on case-insensitive file systems
  • optimize Mini-map rendering
  • do not show boats on puzzle image
  • fix a possible crash in UI window
  • fix castle rendering on Mini-map
  • fix Ultimate Artifact placement conditions
  • fix rendering of towns for View Towns spell
  • fix tall object rendering
https://github.com/ihhub/fheroes2/releases/tag/0.9.18

Changes in v0.9.18 (10 August 2022):

  • speed up rendering of Mini Map area
  • fix missing shadows from path arrows when they are on the edge of screen
  • render correct digging holes for terrains
  • add monster fading animation when both wandering monsters and hero are dying after a battle
  • fix incorrect boat fading animation
  • do not show digging holes on Puzzle Map
  • fix out of view rendering of boats and heroes
  • fix Ultimate Artifact digging conditions
  • fix the logic of joining monsters for free and for money
  • do not draw objects over the map edge if they are in fog
  • fix cases of boats being shifted when a hero boards it
  • fix wrong rendering priority of Hero and Jail
  • do not render shadow of a tall monster over another monster nearby
  • properly render trees and Sawmill
  • fix Fountain being displayed over a moving hero, not under
  • fix certain shadows of objects being too dark
  • fix cases when hero's flag was not being displayed properly when a hero stands near a tall object
  • fix cases when some parts of heroes being displayed over other objects
  • fix monsters being displayed over mountains
  • draw a flag over Magic Garden object
  • draw Adventure Map decors in the same way as in the original game
  • fix flag rendering priority from Windmill
  • fix incorrect moving boat rendering in relation to other boats
  • fix boat being cut near Magellan Maps object
  • fix incorrect boat rendering priority
  • fix wasteland terrain object displayed over hero's sprite
  • fix Mine's flag being displayed over a hero
  • fix cases when a moving hero being drawn over other heroes
  • fix cases when some parts of a ship can be seen through terrain objects
  • fix cases when hero overlaps ship while passing nearby
  • hero does not step on route arrows anymore
  • fix the pre-battle arrangement of neutral troops
  • add separate sound font for SDL 2 builds
  • fix paused music being played with old music volume while restarting it
  • fix hero starting experience values
  • fix amount of experience from Tree of Knowledge
  • fix missing retaliation delay after last animation frame
  • fix music being too quiet while fast switching between music types (Windows OS)
  • fix crashes on Windows 8 using MIDI music
  • fix external audio not always returning to on after turning volume to zero (Windows OS)
  • fix horse's steps being faded while crossing terrain border using MIDI sound (Windows OS)
  • fix sound volume being lower during combat (Windows OS)
  • fix no sounds situation when music is off even when sounds are not (Windows OS)
  • show correct hero's level and experience on level up
  • fix incorrect castle's area leading to wrong castle's info
  • add missing window frame for hero's dialog during level up
  • fix number of ghosts and splitting for Shipwreck, Haunt and Abandoned Mine cases
  • update Bulgarian Translation
  • update treasure chest AI decision logic
  • fix a case when a hero got 2 Magic Books
  • update Russian and Hungarian translations
  • add support for loading of MIDI sound fonts
  • show upgraded monster images in Adventure Map objects upon a successful upgrade
  • fix redrawing of the status window in cases when the hero's army or the castle garrison change without changing focus
  • make best AI fighter as a champion
  • update Polish translation
https://github.com/ihhub/fheroes2/releases/tag/0.9.17

Changes in v0.9.17 (11 July 2022):

  • fix possible crashes during sound playback
  • always ask about rewriting an existing save file
  • allow to remap Hotkeys within the game
  • fix distance evaluation during Scouting
  • fix invalid logic when neutral monsters whose number was set in the Editor did not grow at all
  • add The Price of Loyalty team to credits
  • show a window stating about missing video files for campaigns
  • fix the class of a hero named Joseph
  • fix extra shadow being drawn for Hero Screen dialog on high resolutions
  • align File Options dialog position
  • fix Campaign Window button flickering
  • fix missing column of pixels in Map Scenario Info window
  • update French translation
  • allow different translations of "Red Tower"
  • implement AI courier hero role for better logistics
  • fix situation when MIDI music still continues to play during fast switching between music types
  • fix case when Adventure Map sounds are still being played while opening Main Menu
  • AI should keep some creatures in reserve for castle defence
  • update Ukrainian translation
  • update Norwegian translation
  • increase Genie special ability to 20% like it is done in the original game and correct log messages during battle
  • remember the last open page in Spell Book during battle
  • fix possible synchronization issues for audio playback
  • enhance AI logic towards defending its castles
  • improve usage of spell on Adventure Map by AI
  • fix displaying of negative resources in dialog
  • fix situations when AI was hiring too many heroes
  • respect the Ultimate Artifact's radius specified by the map creator
  • update Polish translation
  • fix the castle's well build logic for AI
  • align hero's button in level-up dialog
  • fix scenarios when ambient sounds from Adventure Map objects are still played while opening a castle's window
  • fix cases when Random Monsters appear from a different level due to invalid format of an object on the map
  • update Mine's sprite properly after defeating Ghosts in Abandoned Mine
  • fix multiple issues related to hero's info popup window and updating his position on a mini-map
  • update sounds and music before a hero making an action
  • add an environmental sound for Freeman's Foundry
  • add initial implementation of true "Evil" interface in the game
  • add missing Ultimate Artifact successful digging sound
  • do not play pre-battle sound if sounds are off
  • fix potential thread-access issues for Nintendo Switch
  • fix possible inter-thread race for Adventure Map Status window
  • fix a delay in game while crossing a terrain and playing MIDI music
https://github.com/ihhub/fheroes2/releases/tag/0.9.16

Changes in v0.9.16 (12 June 2022):

  • add Flatpak support
  • add Belarusian translation
  • swap spell icons for Death Wave and Death Ripple
  • make the "no interface" mode more usable
  • add music resume ability for MP3, OGG and FLAC formats
  • update translation guide
  • replace "C with cedilla" with "latin C" in the French translation
  • do not auto-save at the end of a turn if the player has been vanquished on that turn
  • fix Puzzle window exit button rendering
  • add sound for rocks in water with seagulls
  • fix Sorceress captain purchase building rendering
  • fix issues with Romanian translation
  • properly deal with human-only colors in single player mode
  • fix the invalid behavior of "no interface" mode
  • introduce 3D audio option
  • change adventure map environment sounds for every step hero moves
  • fix boats being considered as free tiles
  • if attacker is able to attack multiple targets at once and has a built-in spell, then this spell should be applied to any (but only one) of the targets
  • fix some typos in translation texts
  • take into account AI hero's role during meeting
  • fix false highscore entry while cancelling to continue a campaign
  • highlight latest highscore after completion scenario/campaign
  • show evil resolution icon for Evil interface
  • add truncated shadow to Scenario Information window
  • generate missing parts of Red Tower sprite
  • fix incorrect tiles being marked as road
  • fix multiple cases while using Mirror Image and Summon Elemental spells
  • fix the victory/defeat verification logic
  • update error message if hero tries to open a spell book and does not have one
  • improve status text if only one troop is selected
  • fix inability to add new entries with similar high scores
  • add Campaign high scores
  • fix dwelling popup window on adventure map
  • make AI to be aware about map conditions
  • fix incorrect hero icon in adventure interface
  • do not show languages with empty translations
  • add Swedish language option and font support
  • update Ukrainian translation
  • well MAX buy: add condition for not enough room, make recruitment happen in guest hero's army too, more text flexibility
  • add Portuguese language option and initial font generation
  • speed up AI turn
  • impose a limit of turns for an attacking AI-controlled hero
  • cache AI hero's and neutral monsters' strength during AI turn
  • add initial Spanish language support
  • make castle's flags for Knight and Wizard factions appear in a correct color
  • add window header for campaign awards and bonuses
  • update German translation
  • fix plural forms translation for some languages
  • fix character filtering when generating the save file name
  • update Polish translation
  • fix Red Tower rendering with Rainbow
  • expand Hotkey usage on adventure map
  • fix German font support
https://github.com/ihhub/fheroes2/releases/tag/0.9.15

Changes in v0.9.15 (07 May 2022):

  • add HotKey window and expand the list of system options
  • do not allow higher-level Mage Guilds to be built if the previous-level Mage Guild has not been built yet
  • Battle Only mode: always assign a random spell to the Spell Scroll
  • add initial support for Romanian language
  • add more conditions to define a blocking AI hero
  • fix incorrect video playback on Descendants campaign, scenario 5
  • change some descriptions of campaign awards and bonuses
  • do not auto save after the completion of the last scenario in a campaign
  • add images and full description of bonuses and awards by right mouse click
  • fix some incorrect campaign bonuses
  • display None if no awards available for the current scenario
  • add hot keys to select bonuses
  • fix rendering of campaign UI window as it was very slow on response on changing bonuses
  • fix missing kingdom income value for scenarios with additional bonus resources
  • game type interface for campaign window must be unique and should not depend on overall game interface
  • allow already selected scenario to appear in ALL scenarios list
  • improved Week of the creature window
  • changed town portal's text and condition to be similar to town gate
  • update Russian translation
  • properly extract animations from the GOG distribution of HoMM2 for Windows
  • update French translation
  • improve search for video files
  • add text truncation method to be used in campaign's choices and awards
  • encourage AI to explore more
  • redesign Hot Key event file handling
  • add double-lined headers to adventure map options
  • add Belarusian, Bulgarian and Ukrainian languages support
  • populate resolution list based till the lowest resolution
  • fix 1000 and 100000 short values display
  • update hero quick info popup dialog
  • disable Town Portal dialog OK button by default
  • changed AI's turn to be repeated multiple times for heroes
  • generate French 'MIN' button
  • generate French 'GIFT' button
  • add Translation Context for Secondary Skill Campaign Bonuses
  • add Ogre Alliance and Dwarfbane full strings for translation
  • fix the positioning of the damage info popup
  • update Norwegian translation
  • fix calculation of morale & luck modifiers for in-castle army without a commander
  • properly calculate the number of travel days to the destination tile for a hero
  • AI should replenish lost spell points more frequently
  • do not allow a hero to have multiple spell books in the "Battle Only" mode
  • fix rendering of the Arm of the Martyr's shadow
  • AI uses View All spell to scout fog
  • hero should have at least 69MP to cast Dimension Door, Town Gate and Town Portal spells
  • fix spacing of player squares in Select Recipients window and properly center resource icons for "Your Funds" and "Planned Gift" horizontally
  • fix French small font Cedilla c rendering
  • update Polish translation
  • reserve half of AI spell points for Dimension Door spell
  • hero should be able to cast spells that consume movement points if he is able to move from his current tile
  • fix MP3 support in Windows SDL1 packages
  • reset the mixer volume before playing video soundtracks
  • expand Test Support mode to cover all campaign related actions
  • add Black-White cursor support
  • add music control options to the configuration dialog
  • fix failing music file search
  • properly work with guardians on the objects that can be captured
  • fix call to get secondary skill name leading to a crash
  • fix multiple issues related to the interface settings
  • allow to change the auto battle settings if player's army doesn't have a commander
  • fix a crash when a hero tries to get a second magic book
  • always grab the mouse in fullscreen mode to properly support devices with notch
https://github.com/ihhub/fheroes2/releases/tag/0.9.14

Changes in v0.9.14 (09 April 2022):

  • generate Italian "Battle Only" button
  • fix line breaking in welcome message for various languages
  • update and improve Italian translation
  • generate Polish "Battle Only" button
  • fix switching fullscreen mode in Mac OS for certain resolutions
  • generate French "Battle Only" button
  • fix a crash due to an assertion failure when the shooter hits back at a unit under Berserk spell
  • fix scrolling in full-screen mode in case of an aspect ratio mismatch
  • fix rare cases for incorrect letters being generated while switching languages
  • add Norwegian language option and font generation
  • update French translation
  • add initial implementation of Dimension Door spell usage for AI
  • fix Gold Watch artifact invalid bonus
  • rework artifact logic with proper separation and calculations of artifact's bonuses and curses
  • play only one sound while getting ar artifact within an event
  • speed up castle and hero icons on adventure map
  • add "Battle Only" button generation for German version of the game
  • fix Mage Guild bottom status bar rendering
  • fix incorrect artifact discovery description
  • add in-game Italian language option and diacritics
  • fix army order option related crash
  • fix High Score Music after winning scenario
  • adjust AI spell estimates
  • fix rendering of bottom bar in Well dialog
  • update Polish translation
  • remove unnecessary call to play VICTORY music during Campaign intro
  • fix the calculation of the cost of surrender
  • fix Town Gate spell logic
  • prioritize AI castles further from enemy territory
  • take the weekly growth into account when calculating monthly population growth bonuses and fines
  • update minimap colors
  • optimize AI fighter hero priorities
  • add native macOS application generation
  • build player influence map to inform AI kingdom development decisions
  • speed up data reading from AGG files
  • update Norwegian translation
  • add a popup window for battle log
  • add a mandatory requirement of h2d file being present
  • fix incorrect logic for palette application function
  • fix position of armies for quick info window for both castle and enemy hero
  • set the direction for attacking and defending units in battle in a more OG-like way
  • fix incorrect popup monster window in Well
  • greatly speedup heavy video loading
  • do not render extra frame while playing an audio only video file
  • properly center the first sentence in the battle surrender dialog
  • dynamically update Game Language dialog
  • fix translation and UI in Tavern dialog
  • add MP3 file support
  • increase the number of sound channels to 32
  • allow a hero to surrender to the captain during the siege
  • fix rare case of Shipwreck having no battle
  • display experience amount for Tree of Knowledge
  • fix Witch's Hut message body
  • for Anduran assembly window show artifact name as a title
  • for hero level up window with one secondary skill make the skill right clickable
  • for hero level up window with no secondary skill display the primary skill icon
  • add search for FLAC files if OGG files aren't found
  • add popup dialogs for Arena's skill choices
https://github.com/ihhub/fheroes2/releases/tag/0.9.13

Changes in v0.9.13 (07 March 2022):

  • show captain quick info dialog in Kingdom Overview
  • add popup windows for campaign awards and bonuses
  • remove Map loading screen
  • add popup windows for campaign scenario dialog buttons
  • remember map size selection in New Game dialog
  • allow selecting options while restarting a campaign scenario
  • display the correct size of player-owned objects on mini-map
  • add base support for text mode
  • fix Sirens logic, AI interaction and UI
  • show missing last frame of wince animation
  • add dynamic generation of scrollbar slider
  • fix Sirens action dialogs
  • add missing artifact discovery event description
  • fix some French translations
  • fix directory and file detection on Windows
  • Kingdom Income window was changed to have Kingdom Income title and Kingdom Income per day to be more obvious for a player
  • events on land and sea now show artifact and resources in one window
  • most of objects related dialogs contain right mouse clickable icons
  • Pyramid visit outcome shows the correct horizontal position of icons and all icons are right mouse clickable
  • fix Artifact frame drawings
  • fix text if translation for a specific language was not found
  • update AI hero recruitment logic
  • allow a short name for all campaign bonus artifacts and spells
  • AI should save current unit if retreating
  • add Czech language support
  • fix monster strength heuristic regression
  • make AI more aggressive in losing situation
  • fix the logic of protecting tiles by neutral monsters
  • change music and surrounding sounds while jumping through Stone Liths
  • fix possible AI pathfinding issues while loading another scenario
  • fix battle grid and ballista info area
  • add popup dialogs for right mouse click in resolution dialog
  • fix hero name not being updated while switching languages
  • fix possible errors for translation related code
  • force to use only the original palette from the game
  • fix lowercase conversion of translations
  • AI archers should not ignore blinded units during battle
  • add missing take-off and landing sounds for Vampire and Vampire Lord
  • reset environment sounds and music theme at the beginning and at the end of the human turn only
  • fix player's allies configuration for 'Defeat the other side' victory condition
  • fix sounds of Lean-To and Skeleton objects
  • rename "Lean To" -> "Lean-To"
  • allow AI fog discovery only for teleport endpoints with reachability information
  • fix missing sounds for some objects on map
  • do not play castle's music if a terrain does not have its own music
  • fix missing sound of player's turn in Hot Seat mode
  • adjust monthly monster spawn
  • fix neutral monster growth formula
  • fix necromancer build order in castles for AI
  • allow a boat to move near the coast above the center of a town
https://github.com/ihhub/fheroes2/releases/tag/0.9.12

Changes in v0.9.12 (07 February 2022):

  • add a confirmation window for restarting a campaign scenario
  • fix wrong scenario order in "Voyage Home" campaign
  • add Betrayal missing for Roland and Archibald campaigns
  • fix logic for switching on and off Auto battle option
  • fix normal and retaliation attack of monsters with multi-cell attack abilities
  • fix missing logging during certain spell casts in battle
  • implement a heuristic for hiring heroes that does not allow to offer the same heroes for hire in several kingdoms at the same time, if there are enough free heroes
  • use 'r' key instead of Escape to Retreat during battle
  • fix Hydra behavior under Berserk or Hypnotize spell effect
  • add highlighting of cells attacked by a unit capable of attacking all neighboring cells
  • fix a penetrating attack made by a wide unit from the tail cell
  • fix attack cursor display during battle
  • fix cases when no monsters were spawned at the beginning of a month
  • display ? symbol instead of empty space for unrecognized symbols
  • fix crashes while rendering non-English text
  • fix rare cases of a screen being black on a startup of the application
  • make language area and campaign choice selection to cover text too
  • fix campaign text translation
  • modify army order setting
  • add German font generation
  • fix multiple issues related the hero recruitment process
  • update Russian translation
  • show monster info on right click in castle's well
  • fix cases when the last AI hero was blocking an entrance to Stone Liths
  • fix small font positioning for Polish GoG version
  • fix most of existing cases with passabilities
  • fix the display of properties for maps from the list in scenario selection dialog
  • update German translation
  • fix translation of saved default player names
  • improve the AI fog discovery logic
  • AI properly uses Whirlpools for path calculation
  • fix cases when a hero was able to create a path over another hero
  • display dead monster information during battle
  • fix Mass Dispel usage during battle
  • update Polish translation
  • fix Russian small k per in both fonts
  • AI heroes properly calculate paths through water
  • add translation context for color and syntax flexibility to Traveller's Tent and Barrier
  • fix Knowledge spite rendering for Arena
  • fix sounds after battle cases
  • fix missing Russian letters on Switch
  • changed captain's name spelling
  • adds missing "pourcent" in description of Golden Bow
  • fix cases when a hero was able to walk on water
  • update French translation
  • show in-game only players for Gift marketplace option
  • fix glowing red pixel in Warlock's Red Tower
  • improve AI behavior during castle defence
  • fix CPU player icon's extra color column
  • show proper language name for mismatched by language save files
  • add a spell title when no enough SP window appears
  • fix a possible crash in French letters generation
  • fix usage of plural/singular translations for map's objects
  • update the logic of re-calculating the paths of heroes on the adventure map
  • add support of Buka version of Anim2 directory for video playback
  • always enable autosave
  • generate proper Russian E with 2 dots on top
  • allow translation of "Cost per troop:" text
  • update UI elements in marketplace window
  • fix a crash during AI turn when AI army has an invalid monster slot
https://github.com/ihhub/fheroes2/releases/tag/0.9.11

Changes in v0.9.11 (23 December 2021):

  • add popup dialog for map information
  • fix hero's path not being updated properly after new monster month event
  • show available game languages in vertical order rather than horizontal
  • fix handling of national symbols in the paths to music files on Windows
  • improve AI behavior during castle defence
  • fix pressed buttons' background
  • fix incorrect output on console window for Windows users with non-English system language
  • add support of Russian language by default
  • update Polish translation
  • generate correct letters for French language
  • update Settings description to cover all actions
  • fix heroes meeting swap arrows
  • update PS Vita controls
  • fix crash for some systems after changing game resolution
  • add hotkey for settings in Main Menu
  • do not reset the hero's path in Sleeper mode, reset the Sleeper mode only with the beginning of the hero's movement
  • fix River being considered as a Road
  • allow to select player class using mouse wheel
  • add additional spell info for spells owned by a hero
  • fix button rendering artifacts after changing resolution
  • fix crash on Windows for some Archibald scenarios
  • always mark the entrance to the castle/town as a road, do not automatically mark the tile south of the entrance as a road
https://github.com/ihhub/fheroes2/releases/tag/0.9.10

Changes in v0.9.10 (05 December 2021):

  • update background music on the fly while changing it within settings
  • fix horizontal position of town name and town icon in town construction dialog
  • improve marketplace gift button placement
  • fix vertical text position in skill icon
  • fix Summon Boat logic
  • add video playback in the Price of Loyalty campaign selection window
  • play sound for visiting Observation Tower
  • fix vertical position of building construction name
  • add missing button shadows in dialogs
  • add popup window to OK button in game settings
  • play campaign music in campaign scenario selection screen
  • fix Enter button pressed state being passed from gift dialog
  • show credits at the end of campaign
  • fix passability for Dimension Door spell
  • add V-Sync option for SDL2
  • update troops split logic change
  • properly draw battle grid
  • use the OK button instead of YES button for the Tavern window
  • add Champion image for Stables object
  • play sounds from closest surrounding objects first
  • make consistent campaign info dialog
  • add default castle's name if none is specified by editor
  • show heroes on minimap
  • update Norwegian translation
  • show available creature count for the Price of Loyalty monster objects
  • fix Witch's Hut name
  • add Italian translation
  • properly handle the day-week-month routine
  • add titles for most of dialogs from map's objects
  • always mark Artesian Spring as visited, even if the hero was not able to drink from it
  • fix movement penalty calculation algorithm
  • implement last move logic for hero movement on the map
  • update hero movement points UI upon visiting multiple objects on the map
  • fix rendering for difficulty text in scenario info dialog
  • fix AI obsession with whirlpools and being always in sea
  • load palette from AGG file
  • fix monster recruit window position for multiple places
  • fix logic for Slow and Haste spell AI usage during battle
  • add random sign messages
  • fix maximum music and sound volume
  • use correct message in marketplace for first exchange when not enough resources
  • speed up for multiple image readings and for unit rendering during battle
  • allow to change Battle Speed using mouse wheel
  • update UI elements in Well's dialog
  • if a hero on the map has the custom empty army (OG editor bug/feature), give him a minimum army (one unit of level 1)
  • add translations for Battle Only mode texts
  • set correct starting army in Archibald 7 scenario
  • fix cases when AI creature doesn't move during battle
  • fix sound effects when receiving artifacts from world map
  • add hotkey to Okay button in Campaign select window
  • fix results on instant battle when Resurrect spell was being used
  • fix cases when opposing heroes still exist on the map after defeat
  • improve AI usage of Disrupting Ray spell during battle
  • add runtime language generation
  • fix terrain music being played during battle
  • fix water object passabilities
  • allow to use mouse wheel to change system options
  • set correct building requirements for Upgraded Jousting Arena and Upgraded Cathedral
  • update messages during battle
  • shorten artifacts names to be fit for campaign UI
  • always highlight the cell under the cursor in combat if the Shadow Cursor is enabled, even if this cell is not reachable by the current unit
https://github.com/ihhub/fheroes2/releases/tag/0.9.9

Changes in v0.9.9 (05 November 2021):

  • do not leak the hotkey state from the experimental settings dialog to the scenario info dialog
  • fix Stonehenge gold cost
  • fix Stonehenge building requirements
  • add buttons in castle construction window
  • fix rendering of Captain's Quarters in Warlock castle
  • fix Marketplace messaging
  • fix MIDI Expansion music option being always reset upon restarting the game
  • fix incorrect sounds while playing MIDI music in certain platforms
  • add credits to the original HoMM2 team
  • correct original Waterfall images to remove Cave
  • use original alignment for Rating, Map Size in gameinfo window
  • fix interaction passability with water objects
  • change Shipwreck, Graveyard and Derelict Ship messages
  • add the Resources Settings page to the Windows installer
  • fix passability for Reefs
  • fix invalid Stonelithts after Barrier removal
  • fix passabilities for diagonal moves
  • clear fog for allies upon visiting Magellan's maps
  • fix Archibald scenario 7 description
  • fix bad pixels on multiple images
  • verify Victory/Loss conditions after a static hero action
  • modify Magellan's maps logic and UI
  • fix monster count in Dragon City for Archibald scenario 7
  • update Victory message for Archibald scenario 7
  • fix possible crash for Russian version of the game
  • fix incorrect map description length
  • fix spell points in Battle Only mode
  • apply Bane and Alliance condition only for Human heroes
  • add extra empty line in New Month window
  • disable bonus choice for campaign scenario info window during scenario play
  • add Norwegian Translation
  • fix the position of campaign days spent text
  • close certain dialogs containing only one Exit button with Enter key
  • add Barbarian Captain Quarter's missing part
  • add hotkeys for selection of SW/PoL campaign
  • generate the default High Score values
  • fix "show damage" feature for blessed/cursed troops
  • fix high scores word
  • fix AI lust for Magellan Maps object
  • hide the OKAY button in campaign info window
  • handle default exit hotkey in Campaign scenario select / info
  • add Sphinx handling by AI
  • remove incorrect status message for hero portrait in hero screen
  • fix map size button states on hotkey press
  • restore environment music & ambient sounds after exiting from the campaign info screen to the adventure map
  • do not allow to use lower than original resolutions
  • freed from Jail AI hero starts movement at the same turn
  • add AI interaction with Alchemist Tower
  • fix incorrect visiting status of Magic Well, Stables, Artesian Spring and Bad Luck objects for AI
  • fix invalid assessment of Monster upgrade objects for AI
  • fix cases when AI hero ignores some objects while defeating an army just on the way to them
  • fix losing hero artifacts upon flee or surrender
  • enable a pressed state for View Intro button post-launch in Campaign screen
  • fix bonus artifact names in campaign screen
  • return to the Main Menu after cancelling campaign scenario
  • fix AI heroes being stuck on teleports
  • fix button rendering in Restart battle dialog
  • update Portuguese translation
  • fix inability to dig on a tile where monster was located
  • fix inability to apply Hypnotize spell on Dwarves
  • fix shooting penalty detection
  • add extra popup windows for UI elements in castle dialog
  • fix passability with shadow sprites
  • AI to use Hydra ability in battle
  • reinforce a AI hero standing in a castle at the start of turn
  • update status bar in castle screen dialog even during construction animation
  • fix incorrect active area of certain buildings in castle screen dialog due to invalid Z levels
  • hide cursor while opening a dwelling info in castle screen dialog by right mouse click
  • add Italian language support
  • update Polish translation
  • properly show the attack cursor when the attack square is located at the top of the castle sprite
  • fix infinite loop for AI trying to use Stoneliths
https://github.com/ihhub/fheroes2/releases/tag/0.9.8

Changes in v0.9.8 (05 October 2021):

  • fix a case when a hero loses his artifacts after retreat in multiplayer mode
  • fix monster position on World Map
  • correct resource position in castle window
  • new week status is not changed while reloading the same save file
  • add headers for all Daemon Cave dialogs
  • fix rewards in the Daemon Cave
  • fix Waterwheel incorrect visited status
  • fix spell points reduction while visiting a well with more than maximum spell points
  • add confirmation message in Alchemist Tower
  • add cell highlighting for monsters with double cell attack ability
  • add correct evaluation of an AI hero recruitment and meeting
  • fix artifact selection area
  • add a title to all artifact related windows
  • grey out experimental disabled option
  • show map type icons in New Map lists
  • do not place wandering troops on coast tile if there are no other coast tiles nearby
  • develop a castle during AI hero purchase
  • fix Altars' passabilities
  • fix AI hero being stuck on Stoneliths
  • fix passabilities of action objects
  • add Windows scripts to automatically copy & extract all necessary assets from original HoMM2 distributions
  • fix unresponsive application during AI turn while attacking an object with guards
  • fix active building area in castle construction window
  • AI can now visit Pyramids
  • fix scrollbar rendering in select lists
  • replace scrollbar in Experimental Settings dialog
  • unselect initial town in the Town Portal spell list
  • fix troop position in the Pyramid
  • fix bridge animation during battle
  • fix deterministic battle outcome
  • fix an empty list of heroes in the Kingdom Overview after the dismissal or loss of a hero
  • fix passability for tall objects
  • fix Roland campaign awards after ending scenarios 7 and 8
  • set 15 character limit when inputting player name in High Scores
  • correct battle speed change for monsters
  • fix incorrect level of Lightning Rod artifact
  • correct castle building' active area
  • fix passabilities related to cracks
  • align UI elements on artifact combat outcome dialog
  • add Spell description window in monster info dialog
  • fix scrollbar position after dismissing a hero
  • add logic for ENTER and SPACE keys for a hero on World Map
  • add hotkey for View World dialog
  • fix some cases with Tree passabilities
  • update Polish translation
  • fix post battle crash
  • fix incorrect rendering for game settings window with evil interface
  • fix appearance of sounds of the sea when a hero stands close to map's edge
  • display a message about Ultimate Artifact after the battle
  • fix adventure border rendering on higher resolutions
  • fix incrementing days spent value after reloading a campaign save
  • lock mouse within the window in multi-monitor setup
  • fix passability of mines
  • fix an ability to attack a monster through a barrier
  • allow hero to traverse Stone Liths and Whirlpools even if he has no movement points left
  • fix black edges in View World
  • fix passability for tiles with shadows only
https://github.com/ihhub/fheroes2/releases/tag/0.9.7

Changes in v0.9.7 (05 September 2021):

  • add popup dialogs for buttons in High Scores and save files manipulation windows
  • fix Faerie Ring passability
  • boat boarding animation speed doesn't depend on hero speed
  • add base support of German translation
  • fix medium size hero portraits
  • fix incorrect object info when a hero stands on it
  • remove flags from most of the captured objects for a lost player
  • fix alignment of scenario info window
  • fix boat froth drawing conditions
  • fix Battle Garb of Anduran missing assembly for The Price of Loyalty campaign
  • add monsters into High Score dialog
  • add short save file description window by right clicking
  • add base roles for AI heroes
  • restart of the battle should lead to the same results
  • fix logic in moral indicator
  • AI can capture Haunted mines
  • fix scrollbar position in Kingdom Overview dialog
  • allow guardian heroes upgrade their troops
  • add object count for weekly object income message
  • open game settings window while clicking on the main menu door
  • fix object passability nearby Hut of Magi
  • modify Necromancer Captain Quarters look
  • fix Radar appearance while right clicking on hero/castle
  • do not show file options window upon file saving
  • save Kingdom Overview UI selection in save files
  • add missing hotkey for Kingdom Overview
  • fix missing mine being drawn in View Mines
  • fix incorrect fading of some objects on World Map
  • fix AI behaviour during siege
  • fix cases of incorrect monster stack splitting logic
  • handle Escape/Enter keys in various settings dialogs
  • use distinct image for the "Swap heroes" button
  • properly restore captain's spell points after quick battle
  • remember UI position in Kingdom Overview dialog
  • add strict ordering of save files ignoring capitalization of letters
  • add popup dialogs in Kingdom Overview UI dialog
  • fix missing game resolutions on some machines
  • fix incorrect rendering on specific fog tile
  • display same name maps in the list of available maps
  • improve pathfinding algorithm for AI
  • place Ultimate artifact not always in the center of puzzle image
  • fix max ballista shots during battle
  • update French translation
  • add missing Farm sprite in Knight castle
  • update every scrollbar logic in the game
  • fix a crash while shooting from castle's tower during castle siege
  • fix Holy Shout being applied on Dwarves
  • properly handle cross-moat attacks during castle siege
  • do not let the player get a random artifact that allows him to win the game
  • allow player to immediately edit save file name without clicking on the input field
  • add few performance optimization in music and audio
  • update Polish translation
  • not visited obelisk remains not visited after the Ultimate Artifact has been found
  • fix polish translation encoding
  • game settings dialog: reset current language to English if game resources do not support other languages
https://github.com/ihhub/fheroes2/releases/tag/0.9.6

Changes in v0.9.6 (06 August 2021):

  • update status window if troops have fallen overboard
  • add direct preview of changes in system options dialog
  • update Polish translation
  • display the position of a hero or a castle on radar while right clicking on them
  • add titles to some dialogs
  • add translation support for missing places
  • fix monster joining logic with and without diplomacy
  • add Nintendo Switch build
  • make captured object event messages to contain yellow titles
  • fix a crash while AI uses Summon Elemental spell during battle
  • fix incorrect Alliance conditions for certain maps
  • fix a case when a hero in castle's tavern always changes after reloading a save file
  • fix incorrect icons for scenario information dialog
  • update skill order for new heroes
  • add normal Game settings dialog
  • fix inability to attack during battle
  • do not play ambient sounds during AI turn
  • add monster names, abilities and hero skills to translations
  • fix AI archer avoiding hand battle logic
  • fix UI defects in Kingdom castle view dialog
  • properly update resource and artifact sprites on World map
  • fix infinite loop after chain lightning spell
  • do not draw flags for puzzle image
  • highlight cells from where a monster will attack
  • restore background music after playing short-term music effects
  • add language selection window
  • fix Town's fog area unveiling
  • implement regular win/loss conditions for multiplayer mode
  • update View World while resizing the application
  • fix English phrasing and punctuation
  • fix simultaneous activation of buttons in hero meeting screen
  • add Town Screen and Well hotkeys
  • fix incorrect logic nearby castles when an attacking hero was actually defending the castle
  • improve win/loss checks of scenarios
  • make AI to use Lich's ability properly
  • update Russian and French translations
  • make fog discovery by AI more efficient
  • fix missing monster spell casting during battles
  • center fast separation buttons in Monster separation dialog
  • remove required spell points from scrolls in Mage Guilds
  • fix Next Hero selection logic
  • fix Wizards campaign scenario 3 with custom Ultimate Artifact
  • add 500 experience for conquering a town regardless of defending hero existence
  • change battlefield pathfinding algorithm to more stable version avoiding AI skipping some moves
  • align text evenly inside secondary skill window
  • display translated text in campaign dialog
  • fix a crash during Summon Boat spell usage
  • if the hero's army does not have any of the original troops left alive at the end of the battle, then the hero should lose
  • fix typo in Fizbin Medal
  • fix small font for Russian localization
  • fix town/castle passability for some cases
  • fix incorrect mouse cursor appearance during AI turn after a battle with Necromancy outcome
  • fix attacking monster sprite on World map
  • AI should check if an object is guarded while unveiling fog
  • add Alchemist Tower to the list of objects to be avoided by AI
  • fix a case when AI heroes did not ever capture empty castles
https://github.com/ihhub/fheroes2/releases/tag/0.9.5

Changes in v0.9.5 (04 July 2021):

  • do not hire AI heroes if no tasks exist for them
  • make AI be more aggressive if no tasks exist for them
  • all scrollbars support continuous scrolling
  • fix placement of creatures during Month of Monster event
  • add an option to restart Campaign scenario
  • do not show x marker for fully built castle icon
  • fix boat summoning logic in relation to some objects on a world map
  • do not show other types of save files on while saving or loading a save file on Windows
  • improve Sorceress castle building logic for AI
  • make AI to visit Lighthouse
  • fix displayed object info in popup dialogs
  • fix places where a hero could teleport for Dimension Door spell
  • fix passabilities of objects on World Map
  • fix multiple issues with castle music
  • fix disembarkation on coast during diagonal move
  • indicate the number of Ghost guarding Haunted and Abandoned Mines
  • add extra conditions for object visiting by AI
  • make AI to use Hut of Magi and Jail objects
  • AI heroes do not block way for other heroes anymore
  • use spacebar only for activating object
  • fix missing UI update in hero meeting dialog while moving artifacts within internal hero's dialog
  • speed up campaign game menu opening time
  • fix incorrect object rendering order on World Map
  • after loading a map and starting a new game the same map will be selected in the list of maps
  • improve AI logic to capture defendless castles
  • fix black screen for loading a campaign map without files
  • allow AI hero to revisit a castle more than once
  • fix a case of splitting monster stack for 2 monsters in stack
  • add monster descriptions
  • allow to visit Artesian Spring once a week
  • allow right click on captured artifact after battle
  • fix summoning boat logic in relation to AI
  • improve fog revealing algorithm for AI
  • fix Stables movement bonus
  • fix AI heroes interaction between each other (reset meeting flag if a hero updates an army)
  • AI heroes do not visit signs anymore
  • AI do not visit shrines for useless spells
  • fix AI spellcasting and army estimates
  • do not remove Sphere of Negation artifact while visiting Alchemist's Tower
  • fix the status of visited objects for a play with ally
  • make proper rendering of some of disabled buttons
  • fix AI behavior to visit Magellan Maps only once
  • center quickinfo dialog under mouse cursor
  • add more gamepad key mapping for PlayStation Vita
  • fix the displayed text in the army bar while splitting monster stack
  • do not let nearby monsters automatically attack hero if he moved to this location using Stone Lith, Whirlpool or Dimension Door
  • fix incorrect text position insertion while creating a save file
  • fix title background for recruit dialog
  • fix hero's mobility indicator for small number of move points
  • in scenario with random players random opponents are generated so that all races are present and different when possible
  • add new UI text rendering classes
  • fix issue when abandoned mine becomes OBJ_ZERO when captured by AI-controlled hero
  • fix missing road identification on broken by editor maps
  • make per-user config file as default option
  • allow attacking another hero located on a Temple
  • fix attacking monster sprite behavior
  • fix number of choices when splitting a troop into multiple troops
  • fix incorrect trading rate during battle
  • fix missing shadow removal of objects under a boat
  • show Dwarf's resistance message in the log only after spell completion
  • correct campaign bonuses' names
  • fix case when boat could be positioned over another boat over whirlpool
  • fix case of triggering Genie's special ability for a stack of 1 monster
  • fix the Price of Loyalty campaign missing rendering
https://github.com/ihhub/fheroes2/releases/tag/0.9.4

Changes in v0.9.4 (04 June 2021):

  • add Windows executable installers
  • use user profile directories to store files to allow multi-user access to the game
  • fix incorrect text splitting in some rare cases
  • fix crash in Roland campaign, scenario 10
  • add missing popup dialogs for system options and buttons
  • fix inaccurate object sorting by distance
  • fix multiple issues with AI and spell logic using distance evaluation
  • read campaign files in non-case sensitive manner
  • make fog uncovering task for AI more efficient
  • fix AI obsession over Observation Towers
  • fix missing path drawing while a hero moving through Whirlpool
  • mark resource generator objects as visited for allies
  • fix incorrect game ending during time loss condition
  • show extended shadow for 2-hex monsters in battle
  • do not show gray flag over Haunted mine
  • add configuration option for first game run
  • support PoL heroes and artifacts in "battle only" mode
  • fix inaccessible beach tiles
  • add hiding and showing cursor logic for SDL2
  • fix shadows for random resources and artifacts
  • draw correct castle icon in popup window
  • fix incorrect hero position facing left
  • remove unneeded AI hero animation under fog
  • do not clear morale modifiers too early for Tavern case
  • highlight the door in Main Menu for mouse over event
  • speed up and fix many places with cursor rendering
  • recruit an AI hero if none exists
  • fix cheating AI behavior for dwellings with defenders
  • add an option to replay Intro video for campaign
  • force display rendering on app activation
  • fix Stables, Alchemist's Tower and Water Wheel passabilities
  • fix puzzle drawings
  • avoid using useless spell during battle for AI
  • return to load screen after cancelling loaded campaign scenario
  • play hero's vanishing sound after AI vs human battle
  • make Ultimate Crown as artifact for campaign scenarios
  • fix incorrect hero receiving a bonus spell for campaign scenario
  • fix monster recruitment logic when a hero present in a castle
  • fix well's max button hiring logic
  • add an option to open Hero Screen within battle
  • fix move points and spell points replenishment logic for heroes from hero pool
  • set proper difficulty level for campaign scenarios
  • directly show next campaign scenario for end of scenario save
  • modernize and secure demo version installation scripts
  • add video playback for campaign scenarios
  • do not reset hero mana points to maximum in the beginning of a new week if they are above maximum
  • fix Roland, chapter 9 map conditions
  • fix Tower shooting logic during castle's siege
  • build Mage Guild before Special building for AI
  • do not count monsters under fog for Visions spell
  • mute sound by setting music and effects volume to zero instead of pausing them
  • speed up AI hero movement
  • add an option to hide AI movements
  • do not draw objects under the fog if they are far from a revealed area
  • add base code for the Price of Loyalty campaign support
  • add dismiss and upgrade hotkeys in unit dialog info
  • add shadow for Spell Book
  • unveil the fog at the start of hero's movement
  • fix extra place with hero's double shadow at adventure world
  • add extended cursor icons from 4+ to 7+
  • fix UI defect of selected creature appearing after closing meeting dialog
  • fix incorrect rendering of View World image
  • add Lose Sorceress Village Condition for The Succession Wars campaign
  • fix flags in Oracle/Thieves' Guild dialog
  • fix sound mute in background on MacOS with SDL1
  • add Home and End button support for save naming
  • fix elements layout for Oracle/Thieves dialogs
  • generate obstacles on battlefield based on the battle tile index
  • use non-plural name for 1 creature while viewing with Crystal Ball
  • add correct support of The Price of Loyalty add-on maps
  • fix double clicking between dialog in castle's window
  • speed up MIDI loading
  • fix bug with mouse cursor not visible after left-clicking on hero's secondary skill in Kingdom Overview
  • fix the "world: use unique artifacts for resource affecting" option
  • reduce CPU usage for video playback and puzzle revealing
  • fix Mix-up in Roland's Campaign Scenarios
  • fix issue when troop info window was not showing after moving a single unit between army bars using drag & drop method
  • simulate level-ups for campaign-specific heroes that start at a higher level
  • reset current music from the previous turn in the beginning of a new human turn
  • upgrade Rendering engine
  • fix broken behavior of scrollbars
  • do not offer to exchange artifact with spell book
  • disable controllers on non-console platforms
https://github.com/ihhub/fheroes2/releases/tag/0.9.3

Changes in v0.9.3 (04 May 2021):

  • add additional info to oracle dialog
  • check that unit is (im)movable after each unit action
  • save completed Campaign scenario to file
  • drop support of saves older than 0.9 version
  • remove incorrect battle background for Graveyard
  • fix catapult miss animation: show this animation near the actual target object
  • fix magic book behavior in inventory
  • fix spell indicator for hero's icon
  • add special Victory conditions for campaign scenarios
  • add initial support for Campaign Awards
  • allow switching heroes in hero dialog if it was opened from meeting dialog
  • fix issues with battles logs and sounds while Dwarves resist spell
  • fix inability to Teleport monster in battle for certain cases
  • add missing "Not enough gold (xxxx)" text in joining window with Diplomacy
  • do not generate Puzzle image on map loading
  • do not take Mage Guild level into account when calculating count of archers in castle towers
  • fix shadows for all monster mini sprites
  • allow the hero to retreat if, while in the castle, he attacks the hero outside the castle
  • show Mage Guild building always in center
  • add titles to Arena, Alchemist Tower and Stables dialogs
  • add World animation during Dimension door spell
  • show correct message for hero's option dialog buttons
  • fix bridge operation for flying units in instant battle
  • add letters for World View and View spells
  • properly handle filenames with dots
  • fix Main Menu UI redraw
  • do not run animation of lowering the bridge on bridge destruction if bridge is already lowered
  • fix the display of the army in the castle quick info window
  • display correct message when capturing abandoned mine
  • align columns and flags at oracle dialog
  • fix cursor during video playback
  • do not allow the player to scroll world map while hero is moving
  • add initial support of other languages: German, Polish, French and Russian
  • fix information displayed in castle quick info window
  • fix sphinx riddle dialogs
  • add swap buttons in hero meeting dialog
  • correct spells order in Magic Book
  • enable triggering of positive morale event after soft wait
  • fix saving scroll speed in the game config file
  • fix Artesian Springs logic
  • fix inability to use Stone Liths
  • fix incorrect heroes for surrender conditions
  • fix gold and experience dialog for the demon cave
  • remove exclamation mark in Hero info window for "Blood" morale
  • fix double shadow from heroes
  • preserve the order of catapult shots
  • highlight Lich's shot area
  • implement correct post-battle necromancy window
  • rename Coast to Beach
  • fix large object coverage in battles
  • add message when visiting Oracle
  • update hero's path while selecting next hero by an option button
  • fix Dragon City guardians
  • load correct video files to be played
  • implement the "faster monster of opposite army goes first" logic in the battle mode
  • fix excessive FPS issue in dialog of joining the army
  • fix game score calculation
  • reset the spell on tile when AI-controlled hero has successfully captured an object
  • immediately hide hero's path before executing the animation of the Dimension Door spell
  • fix Necromancy incorrect percentage output
  • fix ultimate artifact digging logic
  • speed up images loading from resource files
  • fix fading animation synchronization
  • fix a case of inability to confirm end turn while cursor is over options buttons
https://github.com/ihhub/fheroes2/releases/tag/0.9.2

Changes in v0.9.2 (04 April 2021):

  • fix full artifact bag message
  • add missing dot to sentences in few windows
  • display Lighthouse count in Kingdom Overview
  • add proper large obstacle generation for battlefields
  • fast AI units should try to get the first strike
  • fix Sphinx missing rewards
  • reset paralyze state when receiving spell damage
  • randomize attack position of AI monsters
  • fix missing hero paths after loading a save
  • fix incorrect window resolution in fullscreen mode for SDL 2
  • fix Choose Your Lord video sound
  • improve castle garrison estimation for AI
  • remove the mobility index sprite info from the hero Quick Info dialog
  • prohibit the guardian hero from casting adventure spells
  • fix merging of the castle guardian army
  • fix AI defensive unit behavior
  • add AI estimation of hero spell strength
  • force units into empty slots first during merge
  • do not always offer recruitment of heroes from the player's initial class, make recruitment more random
  • allow player to control the hero during the turn of a hypnotized enemy unit
  • archers should not lose shots when attacking in melee
  • check that the hero is able to move before focusing him and starting his movement
  • respect initial order of units (from top to bottom) when determining the order of unit moves in battle
  • add PlayStation Vita support
  • fix creature recruit window UI
  • fix rendering of Arm of the Martyr
  • fix blind spell logic
  • do not give additional 500 experience to the hero who won the battle if the opposing hero surrenders or flees
  • fix hypnotize spell behavior and the spell description
  • update positions of monster sprites and numbers on army status panel
  • fix possibly incorrect arrow direction from shooters
  • fix scrollbar position in multiple places
  • standartize icon position in town's dialog
  • fix Max/Min button position in monster recruit dialog
  • show the surrender dialog even if there is not enough gold to surrender
  • do not apply morale penalty to a hero if he wins a battle in a Graveyard, Shipwreck or Derelict Ship
  • add cross army drag split
  • reset player focus if focused hero or castle was removed
  • allow to switch players for multiplayer map selection
  • allow to use mouse wheel anywhere for split troop dialog
  • fix logic of placing monsters for a New Month
  • fix Kingdom Overview selection drawings
  • fix boat drawing issues
  • do not hide mouse cursor if the Skill Info dialog called from the Level Up dialog contains OK button
  • fix incorrect drawings for battle OKAY button
  • fix rendering of the Castle Captain's spell points bar
  • fix missing sounds within System dialog
  • fix interaction with the castle bridge for flying units
  • use rule of 9 for Ultimate Artifact placement
  • fix last focus option
  • fix incorrect cursor icon over ally's castle
  • add initial implementation of View spells
  • show normal monster names in Visions spell
  • show full 1-pixel black border for Show Interface option
  • show more detailed morale and luck description
  • AI predicts double cell attacks in combat
  • reset blind spell upon taking any damage
  • allow to place units in moat in front of the bridge
  • align spells in the magic book
  • add manual replay of battle if instant battle outcome is negative
  • sounds off when minimizing game window
  • fix playing background music during video playback on SDL1
  • change damage description log message for some mass spells
  • add executable file description and icon on Windows
  • fix pathfinding backwards move and penalty in battle
  • fix City of the dead incorrect monster info
  • update no data error message
  • do not allow to manage monsters in unhired hero dialog
  • AI supports additional harmful combat spells
  • do not open the hero screen in readonly mode if it was opened from the meeting screen, just disable the DISMISS button instead
  • do not show external music option with an absent folder
  • wait for user input at the end of winning video
  • fix double exit dialog appearance
  • fix missing cursor in Army Bar for SDL 1
  • ranged AI troops should move when blocked by a strong unit
  • if the unit attacks twice, apply the second attack to the same cell as the first attack
  • fix double hex attack target for AI troops
  • show the build window with the OKAY button disabled if there is not enough resources to build this building
  • AI uses mass damage spells in combat
  • improvements for AI wide unit pathfinding
  • fix the pathfinding near monsters: do not allow the hero to pass through the monster
  • fix MIN and MAX button drawings
  • do not give an extra day of life to a player without castles
  • preserve unit direction in battle if it moves strictly vertically
  • do not allow the visiting hero to learn Library spells if the Library hasn't been built yet
  • fix inability to reorganize troops in Kingdom View dialog
https://github.com/ihhub/fheroes2/releases/tag/0.9.1

Changes in v0.9.1 (04 March 2021):

  • add "Artifacts" category in Oracle Screen
  • add barrier fading animation
  • improve AI retreat condition
  • fix Split-related issues and implement some new techniques
  • disable retreat for auto battle mode
  • fix object's visited info and grammar
  • fix issues with path finding during combat to avoid being stopped by moat
  • fix incorrect names of Ballista and Turret during battle
  • add missing shadow for arrow cursor on SDL2
  • fix ACCEPT button font for Good Interface
  • fix AI wide units pathfinding and moat logic
  • allow to modify a hero during level up
  • fix summon boat logic
  • fix monster movement nearby moat
  • AI does not chase faster units during battle
  • fix hero shadow drawing on world map
  • fix missing animation frame for wince
  • fix object fading animation on world map
  • fix missing last lost hero condition reset
  • fix simultaneous animation of boat while during another building construction
  • change logic in monster hiring window
  • fix save loading crash for broken saves
  • add middle resolution status support
  • do not show waiting cursor for an exhausted hero
  • fix post Daemon Cave missing music
  • fix well's max button drawing
  • fix incorrect castle focus while visiting by a hero
  • fix fog drawings
  • reduce income window area in towns
  • fix autosave option logic
  • fix overlapped battleground objects
  • remember scenario difficulty while restarting or choosing a new scenario
  • fix multiple game freezes with MIDI music playback
  • add resizable window support on SDL2
  • make deterministic bonus for hero level-up
  • fix wrong controller pointer speed option name and touch coordinates translation
  • add auto battle resolve mode to the game
  • add logic to support video frame rescaling
  • optimize screen resolution logic
  • fix garrison strength estimation by AI
  • fix magic gardens priority if object capture is enabled
  • optimize AI's troop placement before the battle
  • use same colour for all battlegrounds
  • change text in map size hint, to be displayed in more pleasant manner
  • load game button from UI should lead to common load game logic
  • initial implementation of "View World"
  • fix application crash for drawings
  • change building status message for Dwellings
  • fix crash when entering ally castle
  • add Campaign continuation initial support
  • speed up rendering of World Map
  • fix spell book status on hovering
  • save fullscreen mode in configuration file while switching between modes
  • AI should avoid spellcasting if has advantage in battle
  • fix rendering with mouse emulation
  • fix extensive memory usage by dialog windows
https://github.com/ihhub/fheroes2/releases/tag/0.9.0

Changes in v0.9.0 (04 February 2021):

  • make AI to buy magic books in castles
  • fix infinite AI turns
  • optimize AI hero movements
  • do not visit useless objects by AI heroes
  • fix AI castle defence mechanics
  • restore cursor theme after HeroDialog or CastleDialog
  • do not show marketplace icon for joining creature dialog is no markets exist
  • allow to retreat for a hero with no castles
  • add more logic for AI jumping into whirlpools
  • do not block shooters with overpowered AI army
  • fix overlapped flag in Knight's castle
  • disable actions while buying a hero or during construction
  • change the text for the number of secondary skills in level up window
  • play music after showing New Week/Month dialog
  • reset hero direction when recruiting
  • align dates by left in the load file dialog
  • cap Necromancy bonus to 100% instead of 90%
  • fix multiple bugs in Kingdom View
  • fix Transcribe Spell Description Text
  • cancel spell selection with ESC button in combat
  • add a separate option for displaying terrain penalty
  • fix missing music for Load Game option
  • fix Scouting skill bugs and make crystal ball work
  • do not play dwarves' resist sound during mass spells
  • fix Berserk spell logic
  • fix Chain lightning spell logic
  • fix castle flag drawing for nearby hero
  • add empty line for visited info
  • allow Anti-magic spell on mirror-master creature
  • do not draw wall for destroyed bridge
  • fix pathfinding issues and missing path display
  • fix Kingdom overview crash
  • do no freeze building animation during construction or hero's hiring
  • show Spade of Necromancy artifact bonus in Necromancy Skill window
  • display troop counter only for static animations
  • show pointer cursor most of the time during combat
  • fix castle's object positions
  • display correct text when right-clicking on map tile
  • fix path selection for AI hero in patrol
  • fix town portal buttons in Good interface
  • add new standard window with shadow
  • fix events when AI was choosing to disembark on empty tiles
  • change highlighted cursor area for spells during battle
  • implement Alt hotkey to unite stacks of same type
  • implement CTRL split even with selected troop
  • add touchpad support
  • fix joining creature logic with the lack of gold
  • quick Info dialogs have fixed position when clicked from right bar
  • add a check for special objects that you can't move through
  • after AI loses to either castle or other player, center the view on them
  • fix animation order of creatures during combat
  • do not close File Save window while cancelling file overriding
  • fix marketplace button drawings in Surrender window
  • fix castle's battlefield drawings
  • hide Marketplace button for Surrender window
  • always draw troop counter at the top of monster sprites
  • fix a log message when a tower kills one creature
  • display battle grid for whole battlefield
  • fix object drawings on battlefield
  • Bone Dragon morale malus shows in battle and in dialog window
  • add PNG image saving support for SDL2
  • add palette support for SDL2
  • fix morale and luck sprites positioning in meeting screen
  • fix mouse cursor switching while navigating on hero or castle panel
  • always display the correct monster combat speed
  • fix Player Rankings message bar
  • add game controller support
  • add Gold version support for video playback
  • fix Earthquake spell animation
  • fix enemy castle capture action
  • speed up interface drawings for World map
  • fix Hydra's movement during battle
  • set correct size for spell point and experience point zone in hero window
  • fix income info clickable area at castle options window
  • add spells into Hero's book at the start of a map
  • add initial Nintendo Switch support
  • fix Battle Only mode UI
  • fix logic in mouse button press
  • make interface itemsbar adjustment while fixing some split logic
  • add FPS display support
  • fix clickable area for Heroes and Castles in their lists
  • differentiate save files based on game type
  • fix a crash while trying to get settings path on SDL 2
  • fix path calculation for 2-hex creatures in battle
  • add software emulation support for cursor
https://github.com/ihhub/fheroes2/releases/tag/0.8.4

Changes in v0.8.4 (23 December 2020):

  • speed up sprites allocation and deallocation (noticeable for low-profile devices)
  • add extra info in first game message about F4 key
  • fix moral and luck indicator messages
  • fix elements' layout at monster info dialog
  • disable monster attack using Dimension Door
  • remove click area around "exit" button in castle dialog
  • make elements gray for inactive game settings
  • fix cursor disappearance during resource collection on SDL 1
  • fix Summon Boat animation
  • fix Summon boat logic
  • fix popup message for Abandoned Mine
  • fix Select button movement in Scenario window
  • fix position of monsters in battle
  • modify monster upgrade window for 3 monsters
  • make proper calculation of movement points
  • fix Hide interface reset issue
  • show correct artifact transfer dialog after battle
  • fix impassable barrier
  • fix meeting hero update after exiting hero's dialog
  • adjust troop separation dialog position
  • fix incorrect hero values for Kingdom Overview screen
  • fix a crash in multiplayer game selection
  • fix Transcribing spell scrolls logic and UI
  • change info bar text at bottom of screen when mouse cursor positioned under spell book
  • fix starting unit values
  • implement smooth slider
  • add an option to reveal secondary skill info by right click
  • implement Stack split hotkeys (Ctrl and Shift)
  • fix Resurrect logic
  • ignore fog for dimension door
  • disable gift button for a single player
  • fix empty castle capture behavior
  • fix interaction with skeleton on map
  • persist random race for new games
  • fix road penalty text
  • fix incorrect town frames for evil town portal UI
  • speed up generation of few images
  • fix UI defect after closing hero meeting dialog
  • fix UI defect after using town portal spell
  • modify a message of joining 1 creature due to diplomacy
  • do not show income popup window for exit button in castle screen
  • change Tavern dialog caption color to yellow
  • fix rendering and mouse behavior for SDL2
  • fix elements layout for surrendering dialog
  • fix shadow under battle summary dialog
  • fix surrendering cost calculation
  • fix Wagon sounds
  • fix castle and hero interaction with mouse in Kingdom Overview
  • play sound only after a battle with a monster to grab an artifact
  • change window title font color to yellow
  • fix Pyramid bad luck position
  • correct few sprites of mini-monsters
  • add a popup message for View Hero button
  • remove spaces for Level messages
  • clear message log for retreat case
  • add missing Info word for artifact status bar
  • add popup messages for next/previous pages in spell book
  • use keypad Enter as a normal one
  • add magic book image to popup window for no gold case
  • add evil UI elements for "Town portal" spell window
  • show proper information about enemy based on Thieves Guild count
  • fix layout for campaign selection window
  • fix wrong title and wrong text for Freeman's Foundry window
  • fix battle log text layout
  • use Delete key to erase a part of save filename
  • fix post game conditions
  • do not reset army while moving a hero to castle
  • start battle instantly if sounds are off
  • add captain portraits in Kingdom Overview
  • correctly reduce hero army after whirlpool
  • fix Mine info dialog near hero
  • reset Adventure Options buttons when cursor move out
  • draw shadow for empty boat
  • do not show army formation with no captain
  • fix stack overflow when using spells
  • fix disappearing hero while attacking monsters standing on a barrier
  • select a hero with move points when the focus is on a castle
  • increase Meteor Shower spell animation
  • fix spell order in magic book
  • change Artesian spring logic
  • fix Alchemist Tower artifact manipulation logic
  • assemble Battle Garb of Anduran artifact for hero meeting
  • place a hero into castle at the start of game
  • change map size popup window text
  • fix primary skill frame color in hero meeting dialog
  • add a title for joining army dialog
  • fix battle false hex shadow
  • fix drawings for meeting hero dialog
  • fix map loading message typo
  • update hero availability pool after hero purchase
  • show hero's name in magic book related windows
  • fix scenario selection stuck condition
  • fix portraits/hero information display in battle only mode
  • fix normal moral icon image
  • fix enemy army threat check for AI
  • fix changing boat direction by AI at boarding
  • fix Sorceress castle background image
  • fix missing spell point digits
https://github.com/ihhub/fheroes2/releases/tag/0.8.3

Changes in v0.8.3 (04 November 2020):

  • protect higher value (based on buildings built) AI castles first
  • recruit AI heroes in castles other than the first one in the list
  • improve castle build order for AI (priority on gold income buildings)
  • improve castle monster recruitment
  • fix slowed flying creature movement
  • remember boat direction when a hero boarding it
  • update Town Portal dialog
  • fix "jump" flying animation when unit has to turn for attack
  • make one rumour per week in Taverns
  • fix a case of second attack on blinded creature
  • fix Monster Info dialog in evil interface
  • fix few castle icon sprites
  • speed up video loading
  • play sound on shipwreck pickup
  • fix Freeman Foundry UI
  • fix War Troll's stone sprite
  • fix Cavalry sprite
  • fix mage guild dialog message
  • change troop logic exchange during hero meeting
  • fix boat summoning animation
  • AI heroes are able to exchange armies and artifacts
  • add road connection drawings for Barbarian castle
  • fix castle defense trigger condition
  • do not show teleport animation in some AI cases
  • center Good and Evil interface windows
  • teach AI units to block enemy archers
  • show boat froth sprite when stationary
  • fix mine guardians sprites
  • fix battle only mode
  • improve army merge logic
  • fix lighthouse missing movement bonus
  • fix boat and hero positions
  • speed up drawings for World Map
  • fix pass image position on the world map
  • give at least 1 skeleton via necromancy after victory
  • fix Hero screen status bar message position
  • fix Hero meeting screen title position
  • change Pyramid Bad Luck message
  • fix Hero's portrait position in hiring window
  • fix town population status text position
  • fix boat animation and castle building rendering
  • fix troop counter window position
  • fix adjacent monsters when removing one
  • add after play animation
  • fix redraw order for unit count
  • use hero spell power when applying Earthquake
  • fix Lighthouse fog clearance
  • change Hut of the Magi behavior
  • add game resolution popup window
  • fix spelling in castle dialog
  • always show building requirements even if the building is already built
  • fix Knowledge message in Arena
  • five every magic guild a guaranteed damage and non-damage spell
  • fix OK button in joining army window
  • adjust few elements in resolution window
  • fix battle option text overlapping
  • adjust post battle shadowing
  • change main menu popup window descriptions
  • add a support of hero AI patrol mode set in scenario
  • make autosave with capital letters
  • disable spell animation after mine was cleared
  • save boat direction when disembarking
  • set parts of wide objects as visited
  • allow AI player to start it's move with action
  • use original difficulty bonuses for the game
  • check armies for validity before starting the battle
  • remove mud pool from cover object list
  • fix non-necro undead units decreasing morale in an all-undead army
  • remember Ghost number after the battle
  • AI is able to collect/capture multiple objects on the same move
  • adjust heuristics to make sure AI doesn't miss important objects
  • fix a bug where AI was able to buy boats in a castle without shipyard
  • fix the artifact spell damage modifiers
  • display a proper message for Sea Bottle
  • make AI more aggressive when dealing with archers during battle
  • replace "Ship Wreck" word with "Shipwreck"
  • set random starting experience for starting heroes
  • play flotsam disappearing sound after closing the UI window
  • fix income window drawings
  • when retreating, give the hero its default army instead of 1 T1 unit
  • stop battle after AI kills the last creature
  • use word 'one' instead of '1' in battle log
  • fix Thieves Guild background
  • fix visibility of AI hero moving close to fog
  • limit Player name text within given input box
  • show skip turn message during AI turns
  • allow to cast a spell with no move points
  • fix incorrect resurrected troops after battle
  • honor player count for Hot Seat mode
  • fix system options UI dialog
  • remove scrollbars from interface in battle only mode
  • add fading animation for defeated AI hero
  • fix time loss conditions in Info window
  • fix displaying of remaining move points
  • fix multiple text issues
  • modify messages for splitting army window
  • fix the clipped boat sprite
https://github.com/ihhub/fheroes2/releases/tag/0.8.2

Changes in v0.8.2 (04 October 2020):

  • make correct spawn of neutral monsters and their growth
  • display correct window while right clicking on a monster in Kingdom Overview
  • add a transition while boarding and off-boarding boats
  • make hero animation movement smooth
  • fix price of loyalty artifact selection
  • fix tents/barriers from Price of Loyalty
  • fix monster placement at the beginning of months
  • fix missing dialog box in some rare cases
  • do not show journal scrollbar when it's not open
  • fix second attack for blinded creatures
  • fix typo in description of "Knowledge" skill at hero screen
  • replace the original project AI with an enhanced version of AI (making it not that stupid)
  • save neutral army monsters after battle
  • always reduce moral for visited Graveyard and Ship Wreck
  • allow heroes to move last step with remaining move points
  • update village's shadow after a castle was built
  • fix drawing castle's shadows under roads
  • fix missing objects on puzzle map
  • fix empty puzzle map
  • fix Ultimate image on puzzle map
  • fix puzzle map color scheme
  • fix treasure location map doesn't update after visiting obelisk
  • fix amount of creatures position in monster information dialog
  • fix object and shadow drawings on the World Map
  • fix few hero's names
  • draw all dead troops on the battlefield
  • allow to open hero's dialog during heroes meeting
  • fix dialog frame generation
  • fix bookmark positions in Spell Book
  • fix text position in creature recruit window
  • add Information window by right click on buttons in File dialog
  • add the word "Skill" for "Attack Skill" and "Defense Skill" in monster window
  • fix font generation and its position
  • fix popup windows for Spell Book
  • fix cursor for Adandoned mine protected by monsters
  • fix scrollbar in Settings window
  • extend campaign support
  • add proper AI base code for battle
  • change hero's description in tavern
  • use single OKAY button for Config window
  • don't shift High Score background for high resolutions
  • shift second hero's portrait in town
  • change unit movement speed in battle under spells
  • add dynamic color for item selection
  • add a popup window for clicking on Income in castle construction screen
  • remember move points of surrendered/retreated hero
  • fix bottom-to-top scrolling issue by keyboard key
  • reset dismissed hero's army
  • focus on a new hired hero in a castle
  • check magic resistance against Chain Lighting spell
  • fix multiple UI issues in Hero's Screen
  • add proper credits
  • center Hero's Options dialog
  • display spell points in magic book from bottom to top
  • display Liches for the City of the Dead
  • fix hero button position for joining window
  • fix a crash for Mirror image creature
  • reset music after exiting a castle
  • fix Daemon Cave incorrect window
  • fix Blind spell name
  • fix victory message in battle
  • fix File Options window position
  • fix text color for joining window
  • fix monster info shadow position
  • remove extra wince animation for cold ray spell
  • fix some icon positions in hero's dialog
  • center spell point text in hero's dialog
  • add word 'player' for defeated player window
  • fix creature shadow contour issue
  • add button choice support for campaign
  • fix cycling colors for mirrored Genie
  • add external music support by default
  • fix "battle: show damage info" option
  • fix Bloodlust animation
  • speed up calculations for path finding algorithm
  • fix caption issue with map's objects
  • fix missing resolutions and black screen for SDL 1
  • add a dot at the end of multiple messages
  • fix few Phoenix frames
  • make scrollbar more user friendly in battle log
  • fix game info buttons
  • disable Next Hero button if none of heroes can move
  • fix multiplayer player count window position
  • fix graphical issues in big text font
  • fix creature animation going out of window
  • fix few scenario information window UI issues
  • optimize video playback
  • fix map size button state selection
  • fix New Game window UI elements
  • fix a crash while downgrading resolution in 8-bit mode
  • remove "castle: allow recruits special/expansion heroes" option
  • fix sky view status
  • fix generated window position
  • make Exit button disabled for popup windows in castle
  • fix Resurrection animation frame and moving dead units
https://github.com/ihhub/fheroes2/releases/tag/0.8.1

Changes in v0.8.1 (04 September 2020):

  • play video intro at the opening
  • set focus on a hero while opening spell book
  • set minimum Spell Power to be always 1
  • fix castle mini status icon
  • fix drawings of Mage Guilds in castles
  • remove multiple redundant / useless configuration settings
  • fix message dialog shadow
  • add proper support of configuration file
  • fix shift after opening and closing system options dialog
  • fix Gift button for evil interface
  • fix drawings of letters
  • fix Resurrect spell animation
  • add a support of disabled buttons
  • fix Air elemental drawings
  • remove "Manage creatures" button's shadow
  • add missing glowing effects of units in UI
  • fix screen dimming effects
  • change missing file message
  • fix Armageddon animation
  • update interface after exiting hero dialog
  • fix incorrect map extension crash
  • show diplomacy window always and fix marketplace button
  • add dot at the end of player's turn text
  • always center scenario window position
  • fix map difficulty text and its position
  • use proper config background window image
  • reset interface while changing its type
  • add game scenario dialog shadow
  • do not refocus after exiting castle's window
  • make Disabled Campaign button in High Score board
  • disable Campaign button if no files present
  • fix abandoned mine cursor
  • fix Sphinx message
  • modify Graveyard robber message
  • polish "battle only" button
  • show upgrade button if there's not enough money
  • fix lighthouse spelling
  • fix Dismiss button position in Hero's dialog
  • add missing title for graveyard message
  • fix graveyard message
  • fix marketplace text
  • show a dialog if a hero has no space for Spell Book
  • don't display artifact dialog for unknown artifact
  • fix an ability to skip button state by using a keyboard
  • apply Chain Lightning damage on allies as well
  • skip turn of resurrected troop
  • fix EXIT button position in creature window
  • fix AI turn crash
  • remove black background over army counter
  • don't show start and end position for monster log movement
  • add logic to handle inability to buy monsters in well
  • don't draw tent images in the castle window avoiding weird animation during castle construction
  • remove move penalty for visiting whirlpool/teleport
  • fix descriptions for Thief's Guild and for Pathfinding skill
  • fix logic of Town Gate spell
  • fix wrong OKAY button in System Options for Evil interface
  • skip heroes who do not have move points for move or sleep
https://github.com/ihhub/fheroes2/releases/tag/0.8

Changes in v0.8 (26 July 2020):

  • add in-game option to change resolution
  • add fade-in / fade-out animation for AI heroes
  • fix logic when all stone liths were connected to each other even with different types
  • fix logic for stone liths in regard to allies
  • fix flickering of status bar in castle
  • fix attack cursor while pointing a monster
  • fix wolf's low attack animation
  • fix monster attack and fade animation on the World Map
  • add boat building animation
  • adjust hero battle dialog to align text
  • display boat froth sprite only if away from the coast
  • use correct sprite for castle's exit button
  • do not play sounds in castle's window when restoring the application
  • fix cursor for empty enemy castle
  • fix incorrect popping window in tavern
  • fix delayed mouse click on a cell during battle
  • fix hero's level up window with single secondary skill
  • fix system menu OKAY button
  • add SMK video file support
  • reset sound only if battle is shown
  • add support for ogg music from GOG version
  • fix castle drawings on the World Map
  • add Holy Shout spell blur effect
  • fix pathfinding calculations
  • increase the amount of sound channels to 16
  • add death wave/ripple spell effect animation
  • fix Hypnotize and Berserk spell behaviors
  • correct battle hero animation
  • update elemental storm spell
  • "Summon boat" spell should not be used on a board
  • do not focus screen on a hero after adjusting scroll speed
  • fix Shipwreck empty battle
  • use only screen supported resolutions for the game
  • update focus logic for AI moving out of the fog
  • change mass spell icons
  • add frame border to highscore screen
  • reuse SDL2 texture for drawing speedup
  • adjust arena object dialog
  • set monster to static state after receiving a hit
  • fix mage guild window background
  • fix hero's status bar item locations
  • fix going out the battle window animation
  • shift battle log window by 1 pixel up
  • add a partial drawing support for disabled buttons
  • add Chain Lightning spell animation
  • add color cycling for active monster aura
  • fix incorrect hero's interaction with objects during movement
  • adjust flags animation with battle speed
  • make hero's movement smoother
  • show a proper status window message depending on resolution
  • fix last unit being hit 1 frame missing animation
  • remove Skill word from level up window text
  • add full animation in castles
  • update cursor while pointing over empty interface area
  • make "Next hero" button disable when no heroes exist
  • fix extra shifting upon landing for flying monsters
  • adjust music fade in effect and better sound selection
  • add monster animation on the World Map
  • fix fullscreen behavior in SDL 2
  • fix World Map drawings and screen jumping during hero movement
  • fix display drawing during mouse movement in SDL 2
  • fix ship shifting upon boarding it
  • add keyboard support for navigation in spell book
  • display different message in Mage Guild if no hero is in castle
  • fix text positioning in status bar
  • add lightning spell animation
  • do not run idle monster animation at every human's turn
  • fix marketplace window UI issues
  • fix creature contour drawing
  • add keyboard support for navigating between castles and heroes
  • add hero's flag animation in a world map
  • draw post attack animation in parallel so that battle animation does not look slow
  • add a flag to castle's captain
  • fix cursor offsets so that the cursor does not jump while changing its type
  • fix incorrect drawings for many interactive dialogs
  • make yellow frame for not available building info
  • fix hero hiring animation position
  • fix incorrect mouse cursor type during hero's movement by keyboard
  • add magic resist sound
  • add missing Skill word for Attack and Defense
  • fix fog drawings
  • multiple tweaks for AI
  • fix Spell Power naming in its icon and description
  • add animation of many objects on World Map
  • fix Mirror Image clone placement
  • add smooth screen scrolling during hero's movement
  • fix screen shifting when a hero initiates movement without movement points
  • complete hero's movement cell if an user clicks by mouse during hero's movement
  • add Stunning animation
  • fix Resurrect spell animation and logic
  • fix Armageddon and Earthquake animations
  • show gray text for spells which need more than current hero spell amount
  • set correct yellow and white font
  • fix BloodLust spell animation
  • fix incorrect stunning state rendering
  • add mirror image effect
  • fix puzzle view on high resolutions
  • remove Visual Studio 2015 Redistributable package dependency for 64-bit application on Windows
  • add F4 fullscreen hotkey support
  • set correct animation for Holy Word and Holy Shout spells
  • fix join/flee condition
  • fix castle siege logic
  • add an improved battle obstacle selection
  • fix multiple places with shadows while using alpha blending in SDL 1
  • hide World Map for next turn in hot seat mode
  • add an ability to use scroll by mouse in SDL 2
  • fix transparency on World Map and during Battle
  • fix message content and scrollbar for Town Portal spell
  • fix a crash during hero's dismiss
  • fix retaliation condition logic
  • fix a crash while checking hero with focused castle
  • change monster value heuristics for battle and strategic decisions
  • fix Mutant Zombie HP value
  • add color cycling for glowing effects on monsters during battle
  • show adventure map quick info by right click for dimension door spell
  • make hero's path visible after using a portal
  • add a log message for flying monsters
  • fix teleport and luck animation
  • fix ripple effect for disrupting ray and cold ray
  • update focus after hero's dismiss
  • add a condition to check down bridge for unit defense calculation
  • set World Map border size depending on resolution
  • add flag animation of neutral captain in a castle/town
  • do not move to current hero after closing hero's stats window
  • make interface background more uniform on high resolutions
  • add exit button during Dimension Door spell
  • update sounds and music upon teleport spell usage
  • add bad luck animation
  • fix blurred buttons in Adventure Panel
  • fix teleport delay in animation
  • sort spell icons by their duration in monster statistics window
  • fix defense formula for monster during battle
  • fix application exiting behavior (add support for Alt+F4 in Windows for SDL 2)
  • ignore bad spell status for Archmage attack
  • set correct post battle video sequence
  • fix hero fading animation
  • add min and max buttons for troop separation dialog
  • speed up rendering
  • fix hero's flag position in battle
  • fix inability to cast another spell upon cancellation teleport spell
  • play resource collection and sound after reading a dialog
  • fix monster frame jumps from multiple spells
  • fix medusa's stunning effect icon
  • fix Lich animation
  • fix monster count window position during battle
  • fix Archmage dispel post attack effect
  • fix Tower and Magic Arrow animation
  • fix the logic for Summon Boat spell
  • fix Identify Hero spell behavior
  • fix 0 monster count for Visions spell
  • add correct battle speed adjustment formula
  • show disable Dismiss button for a hero in a castle
  • fix idling condition check
  • add correct attacks and timing for monster animation during battle
  • give a control to an opponent over hypnotized monster
  • do not shift application window while loading a map for SDL 2
  • fix Haunt spell incorrect behavior
  • add shadows to most of dialogs
  • play animation of treasure chest after the collection
  • fix incorrect position of a stunned monster
  • remove red cross over town's icon
  • fix new dwelling building animation
  • fix an ability to continue movement after Town portal spell
  • fix quick info window position at world map
  • show reflected monster animation in a dialog for right-side monsters
  • do not auto disable dimension door spell nearby world map edges
  • remove tiny ship icon from hero's status
  • do not move a hero over a portal above another hero
  • add hero movement interruption by left click
  • use shadowing for end movement cell during battle
  • fix inability to move artifacts
  • show a message if not enough points for digging
  • fix monster attack at the start of a new game
  • add fading animation after battle
  • limit Dimension Door spell range
  • fix invisible hero's path after Dimension Door spell
  • fix landing from a ship event to attack a monster after landing
  • fix incorrectly mixed spells for hero's book
  • fix Mass Cure spell icon
  • fix spell icon size and position for monster's info
  • fix cursor behavior beyond world edge
  • set correct position of monster in dwelling info
  • fix minimap colors
  • add an option to switch music type in settings
  • fix incorrect map object naming
  • fix hero, castle and status army info
  • add support for swapping palettes
  • fix hero movement at low speeds
  • fix display info of resources with scouting
  • fix spell sorting crash and mage guild positioning
  • add an optional aspect ratio correction in full-screen mode
  • fix a crash for unhired hero
  • fix alignment of text in monster info dialog
  • fix shifted monster position in recruit window
  • fix negative resources in kingdom possession
  • rework of midi music and sounds
  • fix current unit animation freezing state during battle
  • draw main menu as a background for High Score window
  • fix a case when not destroyed castle gate remains opened after a troop from a castle crossed the bridge during battle
  • fix Phoenixes naming
  • fix EXIT button position in castle options
  • set a correct position for buttons in Configuration dialog
  • fix Genie special ability
  • fix surrender action during battle
  • fix UI value input selectors
  • fix hero animation in battle
  • fix hero position in battle
  • add monster animation in army's info dialog
  • add monster movement animation in Well
  • use BIN file information for correct monster animation
  • fix unit damage formula
  • fix morale and luck events
  • add *nix case insensitive file access
  • make Army Order window during battle optional
  • fix flying monster animation offset
  • fix a crash for hot seat game start
  • add quit dialog popup window and change File Options dialog behavior
  • fix incorrect position of recruit Creature Info window in higher than default resolutions
  • add scalable Sprites support
  • do not show text for hidden Dismiss button
  • fix multiple memory leaks
  • add double quotes to surrender dialog
https://github.com/ihhub/fheroes2/releases/tag/0.7

Changes in v0.7 (18 April 2020):

  • add an edge of the World Map
  • complete hero movement cell if a player stops it by any keyboard button
  • add hotkey 'N' to start a new game within the World Map like in the original game
  • fix crashes in multiple maps during map loading or during AI turns
  • fix game freezes during animation of resources collection
  • make human turn always first
  • do not show file save loading dialog if no saves exist
  • fix 'Adventure Options' button is being blurred after pressing it once on MacOS
  • cancel a dialog by pressing close window button
  • do not allow to move artifacts for not hired heroes in a castle
  • allow file selection by double-clicking on a list entry
  • fix MAX button state for monster change in recruitment window
  • update a cursor while stopping hero's movement
  • add monster animation in castle's well
  • set correct animation speed
  • fix scrolling behavior and add diagonal scrolling
  • display recruit monster window even for 0 creatures within castle's well
  • fix castle well UI elements
  • show hero movement arrow icons with proper colors
  • fix resizing of mini-map in fixed interface mode
  • do not show Necromancy window for 0 obtained skeletons
  • show an empty area instead of tavern building in Necromancer castle
  • fix a state of no information displayed in Signs
  • fix a crash after loading a save and starting any new game after
  • fix a crash during loading empty or newly saved configuration file
  • add initial campaign support (very early beta)
  • fix crystal resource position
  • fix hero path cursor display
  • add missing option's titles in Battle Option dialog
  • fix a popup messages for different types of resources at the World Map
  • fix application title disappearing after loading any map on SDL 2
  • fix disabled black surrender button in hero's options in SDL 2 mode
  • move creature window info to the top of the castle screen
  • make "Buy from well" as a default option
  • remove speed 0 for battle and the World Map
  • fix spell book is being displayed in semi transparent way
  • hero path is recalculated each time when an user chooses the hero
  • show creature information in recruitment building
  • fix incorrectly displayed shadows on the World Map for SDL 2
  • change AI behaviour for castle building strategy
  • fix positions of labels in in-game settings
  • remove 'Dismiss' button for a hero who is not hired yet in a castle
  • fix incorrectly shown message of found resources in the World Map bottom-right window
  • fix battle grid
  • add missing text in battle options dialog
  • fix World Map UI is being drawn inside castle options
  • fix shadow display in a battle
  • disable Spell button for castles
  • change font color for a creature's name
  • fix observation tower coverage area
  • hide dismiss button for monsters if a hero has only one stack of them
  • fix incorrect message for Shipyard by right click
  • fix missing battle hexagonal net was not appearing if enabled until next battle
  • display a warning message about missing files from the original game
  • disable Continue Movement button for a hero which does not have chosen path
  • required building names are displayed on a separate line each
  • fix no building image for already built building for right mouse click
  • fix incorrect image for Captains Quarters
  • renamed 'Free Heroes II' to 'fheroes2'
  • show disabled "Continue Movement" button for castle
  • fix number of monsters being displayed in a black box
  • add a script to download a demo version of the original game
  • set default display size to 640x480 pixels
  • add Windows build
https://github.com/ihhub/fheroes2/blob/master/docs/images/screenshots/screenshot_world_map.png?raw=true Map-Screen https://github.com/ihhub/fheroes2/blob/master/docs/images/screenshots/screenshot_castle.png?raw=true Castle-Screen https://github.com/ihhub/fheroes2/blob/master/docs/images/screenshots/screenshot_battle.png?raw=true Battle-Screen
fheroes2-1.1.6+dfsg/script/tools/000077500000000000000000000000001476115357100166315ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/tools/changelog_update_metainfo.py000066400000000000000000000071301476115357100243570ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2023 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # pylint: disable=missing-module-docstring import argparse import datetime import re import sys from xml.sax.saxutils import escape # # Appstream file can be validated using the following command: # appstream-util validate io.github.ihhub.Fheroes2.metainfo.xml # class CustomArgumentParser( argparse.ArgumentParser ): # pylint: disable=missing-class-docstring def error(self, message): self.print_usage(sys.stderr) self.exit( 1, "%(prog)s: error: %(message)s\n" % {"prog": self.prog, "message": message}, ) def parse_arguments(): # pylint: disable=missing-function-docstring parser = CustomArgumentParser() parser.add_argument("changelog_file", help="changelog.txt file") parser.add_argument("metainfo_file", help="*.metainfo.xml file") return parser.parse_args() def main(): # pylint: disable=missing-function-docstring args = parse_arguments() with open(args.changelog_file, encoding="utf-8") as changelog_file: changelog = changelog_file.read() with open(args.metainfo_file, encoding="utf-8") as metainfo_file: metainfo = metainfo_file.read() tpl = """ https://github.com/ihhub/fheroes2/releases/tag/{}

Changes in v{} ({}):

    {}
\n""".lstrip( "\r\n" ) tmp = "" regex = r"version ([\d.]+) \(([\w ]+)\)\n(.*?)\n{2}" for match in re.findall(regex, changelog, re.MULTILINE | re.DOTALL): tmp += tpl.format( datetime.datetime.strptime(match[1], "%d %B %Y").strftime("%Y-%m-%d"), match[0], match[0], match[0], match[1], re.sub(r"- (.*)", r"
  • \1
  • ", escape(match[2])), ) new_metainfo = re.sub( r"(.*?)", r"\n" + tmp + " ", metainfo, flags=re.MULTILINE | re.DOTALL, ) with open(args.metainfo_file, "w", encoding="utf-8") as metainfo_file: metainfo_file.write(new_metainfo) if __name__ == "__main__": main() fheroes2-1.1.6+dfsg/script/tools/check_code_format.sh000066400000000000000000000045721476115357100226140ustar00rootroot00000000000000#!/bin/bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2024 # # # # Copyright 2018 Google LLC # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Script to determine whether the source code in the Pull Request is formatted correctly. # Exits with a non-zero exit code if formatting is needed. # # It is assumed that this script is called from the project root directory. set -e -o pipefail FILES_TO_CHECK=$(git diff --name-only HEAD^ | (grep -E ".*\.(cpp|cc|c\+\+|cxx|c|h|hpp|java)$" || true) \ | (grep -v "^src/thirdparty/.*/.*" || true)) if [ -z "$FILES_TO_CHECK" ]; then echo "There is no source code to check the formatting." exit 0 fi if FORMAT_DIFF=$(git diff -U0 HEAD^ -- $FILES_TO_CHECK | clang-format-diff -p1 -style=file) && [ -z "$FORMAT_DIFF" ]; then echo "All the source code in the PR is formatted correctly." exit 0 else echo "Formatting errors found!" echo "$FORMAT_DIFF" exit 1 fi fheroes2-1.1.6+dfsg/script/tools/check_copyright_headers.py000066400000000000000000000126051476115357100240470ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # pylint: disable=missing-module-docstring import argparse import datetime import os import re import subprocess import sys CURRENT_YEAR = datetime.datetime.now().date().year class CustomArgumentParser( argparse.ArgumentParser ): # pylint: disable=missing-class-docstring def error(self, message): self.print_usage(sys.stderr) self.exit( 1, "%(prog)s: error: %(message)s\n" % {"prog": self.prog, "message": message}, ) def parse_arguments(): # pylint: disable=missing-function-docstring parser = CustomArgumentParser() parser.add_argument( "--handle-shebang", action="store_true", help="handle the shebang at the beginning of the source file(s)", ) parser.add_argument("full_header_file", help="full header file") parser.add_argument("header_template_file", help="header template file") parser.add_argument( "source_file", help="source files (at least one, can be multiple)", nargs="+" ) return parser.parse_args() def main(): # pylint: disable=missing-function-docstring,too-many-locals,too-many-branches args = parse_arguments() with open(args.full_header_file, "r", encoding="latin_1") as full_header_file: copyright_hdr_full = ( full_header_file.read().strip().replace("{YR}", f"{CURRENT_YEAR}") ) with open( args.header_template_file, "r", encoding="latin_1" ) as header_template_file: copyright_hdr_tmpl = header_template_file.read().strip() copyright_hdr_re_tmpl = copyright_hdr_tmpl for ch_to_replace in "*()": copyright_hdr_re_tmpl = copyright_hdr_re_tmpl.replace( ch_to_replace, "\\" + ch_to_replace ) copyright_hdr_year_re = re.compile( "^" + copyright_hdr_re_tmpl.replace("{Y1} - {Y2}", "([0-9]{4}) ") ) copyright_hdr_yrng_re = re.compile( "^" + copyright_hdr_re_tmpl.replace("{Y1}", "([0-9]{4})").replace( "{Y2}", "([0-9]{4})" ) ) for file_name in args.source_file: if not os.path.exists(file_name): continue with open(file_name, "r", encoding="latin_1") as src_file: src = src_file.read() if args.handle_shebang and src.startswith("#!"): partition = src.partition("\n") shebang = partition[0] src = partition[2].lstrip("\n") else: shebang = "" year_re_match = copyright_hdr_year_re.match(src) yrng_re_match = copyright_hdr_yrng_re.match(src) src_is_ok = False if year_re_match: if year_re_match.group(1) == f"{CURRENT_YEAR}": src_is_ok = True elif yrng_re_match: if yrng_re_match.group(2) == f"{CURRENT_YEAR}": src_is_ok = True if not src_is_ok: if year_re_match: hdr = copyright_hdr_tmpl.replace( "{Y1}", f"{year_re_match.group(1)}" ).replace("{Y2}", f"{CURRENT_YEAR}") src = copyright_hdr_year_re.sub(hdr, src) elif yrng_re_match: hdr = copyright_hdr_tmpl.replace( "{Y1}", f"{yrng_re_match.group(1)}" ).replace("{Y2}", f"{CURRENT_YEAR}") src = copyright_hdr_yrng_re.sub(hdr, src) else: src = copyright_hdr_full + "\n\n" + src.lstrip("\n") if shebang: src = shebang + "\n\n" + src with open(file_name + ".tmp", "x", encoding="latin_1") as tmp_file: tmp_file.write(src) with subprocess.Popen( ["diff", "-u", file_name, file_name + ".tmp"] ) as diff_proc: diff_proc.wait() os.remove(file_name + ".tmp") if __name__ == "__main__": main() fheroes2-1.1.6+dfsg/script/tools/check_copyright_headers.sh000066400000000000000000000104351476115357100240300ustar00rootroot00000000000000#!/bin/bash ########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # Script to determine whether the source code in the Pull Request has correct copyright headers. # Exits with a non-zero exit code if copyright headers need to be updated. # # It is assumed that this script is called from the project root directory. set -e -o pipefail SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") HEADERS_DIR="$SCRIPT_DIR/copyright_headers" C_LIKE_FILES_TO_CHECK=$(git diff --name-only HEAD^ | (grep -E ".*\.(cpp|cc|c\+\+|cxx|c|h|hpp|java|rc)$" || true) \ | (grep -v "^src/thirdparty/.*/.*" || true)) SCRIPT_FILES_TO_CHECK=$(git diff --name-only HEAD^ | (grep -E ".*(\.(sh|py|ps1)|CMakeLists.txt|Makefile[^/]*|Android.mk|Application.mk)$" || true) \ | (grep -v "^src/thirdparty/.*/.*" || true)) WINBAT_FILES_TO_CHECK=$(git diff --name-only HEAD^ | (grep -E ".*\.bat$" || true) \ | (grep -v "^android/gradlew.bat$" || true) \ | (grep -v "^src/thirdparty/.*/.*" || true)) if [ -z "$C_LIKE_FILES_TO_CHECK" ] && [ -z "$SCRIPT_FILES_TO_CHECK" ] && [ -z "$WINBAT_FILES_TO_CHECK" ]; then echo "There is no source code to check the correctness of the copyright headers." exit 0 fi if [ -n "$C_LIKE_FILES_TO_CHECK" ]; then C_LIKE_FORMAT_DIFF=$(python3 "$SCRIPT_DIR/check_copyright_headers.py" "$HEADERS_DIR/full_header_c_like.txt" \ "$HEADERS_DIR/header_template_c_like.txt" \ $C_LIKE_FILES_TO_CHECK) fi if [ -n "$SCRIPT_FILES_TO_CHECK" ]; then SCRIPT_FORMAT_DIFF=$(python3 "$SCRIPT_DIR/check_copyright_headers.py" --handle-shebang \ "$HEADERS_DIR/full_header_script.txt" \ "$HEADERS_DIR/header_template_script.txt" \ $SCRIPT_FILES_TO_CHECK) fi if [ -n "$WINBAT_FILES_TO_CHECK" ]; then WINBAT_FORMAT_DIFF=$(python3 "$SCRIPT_DIR/check_copyright_headers.py" "$HEADERS_DIR/full_header_winbat.txt" \ "$HEADERS_DIR/header_template_winbat.txt" \ $WINBAT_FILES_TO_CHECK) fi if [ -z "$C_LIKE_FORMAT_DIFF" ] && [ -z "$SCRIPT_FORMAT_DIFF" ] && [ -z "$WINBAT_FORMAT_DIFF" ]; then echo "All the source code in the PR has the correct copyright headers." exit 0 else echo "Invalid copyright headers found!" [ -n "$C_LIKE_FORMAT_DIFF" ] && echo "$C_LIKE_FORMAT_DIFF" [ -n "$SCRIPT_FORMAT_DIFF" ] && echo "$SCRIPT_FORMAT_DIFF" [ -n "$WINBAT_FORMAT_DIFF" ] && echo "$WINBAT_FORMAT_DIFF" exit 1 fi fheroes2-1.1.6+dfsg/script/tools/copyright_headers/000077500000000000000000000000001476115357100223345ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/script/tools/copyright_headers/full_header_c_like.txt000066400000000000000000000026701476115357100266620ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) {YR} * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ fheroes2-1.1.6+dfsg/script/tools/copyright_headers/full_header_script.txt000066400000000000000000000026441476115357100267410ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) {YR} # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### fheroes2-1.1.6+dfsg/script/tools/copyright_headers/full_header_winbat.txt000066400000000000000000000027351476115357100267220ustar00rootroot00000000000000:: ########################################################################### :: # fheroes2: https://github.com/ihhub/fheroes2 # :: # Copyright (C) {YR} # :: # # :: # This program is free software; you can redistribute it and/or modify # :: # it under the terms of the GNU General Public License as published by # :: # the Free Software Foundation; either version 2 of the License, or # :: # (at your option) any later version. # :: # # :: # This program is distributed in the hope that it will be useful, # :: # but WITHOUT ANY WARRANTY; without even the implied warranty of # :: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # :: # GNU General Public License for more details. # :: # # :: # You should have received a copy of the GNU General Public License # :: # along with this program; if not, write to the # :: # Free Software Foundation, Inc., # :: # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # :: ########################################################################### fheroes2-1.1.6+dfsg/script/tools/copyright_headers/header_template_c_like.txt000066400000000000000000000004641476115357100275320ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) {Y1} - {Y2} * * * fheroes2-1.1.6+dfsg/script/tools/copyright_headers/header_template_script.txt000066400000000000000000000004601476115357100276040ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) {Y1} - {Y2} # # # fheroes2-1.1.6+dfsg/script/tools/copyright_headers/header_template_winbat.txt000066400000000000000000000004741476115357100275710ustar00rootroot00000000000000:: ########################################################################### :: # fheroes2: https://github.com/ihhub/fheroes2 # :: # Copyright (C) {Y1} - {Y2} # :: # # fheroes2-1.1.6+dfsg/sonar-project.properties000066400000000000000000000021101476115357100210630ustar00rootroot00000000000000sonar.projectKey=ihhub_fheroes2 sonar.organization=ihhub # This is the name and version displayed in the SonarCloud UI. sonar.projectName=fheroes2 # CI will automatically replace this with the contents of the version.txt file. sonar.projectVersion=%{version} sonar.links.homepage=https://github.com/ihhub/fheroes2 sonar.links.ci=https://github.com/ihhub/fheroes2/actions sonar.links.scm=https://github.com/ihhub/fheroes2 sonar.links.issue=https://github.com/ihhub/fheroes2/issues # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. sonar.sources=. # Encoding of the source code. Default is default system encoding. #sonar.sourceEncoding=UTF-8 # List of files completely excluded from the analysis. sonar.exclusions=src/thirdparty/**/* # List of issues to ignore. sonar.issue.ignore.multicriteria=cppS106Tools # Ignore cpp:S106 (Standard outputs should not be used directly to log anything) for # command-line tools. sonar.issue.ignore.multicriteria.cppS106Tools.ruleKey=cpp:S106 sonar.issue.ignore.multicriteria.cppS106Tools.resourceKey=src/tools/*.cpp fheroes2-1.1.6+dfsg/src/000077500000000000000000000000001476115357100147545ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/CMakeLists.txt000066400000000000000000000036651476115357100175260ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### set( GNU_CC_WARN_OPTS -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wdouble-promotion -Wfloat-conversion -Wfloat-equal -Wredundant-decls -Wshadow -Wswitch-default -Wundef -Wunused ) set( GNU_CXX_WARN_OPTS ${GNU_CC_WARN_OPTS} -Wctor-dtor-privacy -Wextra-semi -Wmissing-declarations -Wold-style-cast -Woverloaded-virtual -Wsuggest-override ) set( MSVC_CC_WARN_OPTS /W4 ) add_subdirectory(thirdparty) add_subdirectory(engine) add_subdirectory(fheroes2) if(ENABLE_TOOLS) add_subdirectory(tools) endif(ENABLE_TOOLS) fheroes2-1.1.6+dfsg/src/dist/000077500000000000000000000000001476115357100157175ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/dist/Makefile000066400000000000000000000116351476115357100173650ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### # # Name of the main target executable file # TARGET := fheroes2 # # Common build options for fheroes2 and third-party libraries # # Common flags for both C and C++ compilers CCFLAGS := -fsigned-char -pthread # Flags for the C compiler CFLAGS := $(CFLAGS) # Flags for the C++ compiler CXXFLAGS := $(CXXFLAGS) # Flags for the preprocessor CPPFLAGS := $(CPPFLAGS) # Flags for the linker LDFLAGS := $(LDFLAGS) -pthread # Flags for additional libraries LDLIBS := $(LDLIBS) ifdef FHEROES2_WITH_DEBUG CCFLAGS := $(CCFLAGS) -O0 -g else CCFLAGS := $(CCFLAGS) -O3 endif ifneq ($(or $(FHEROES2_WITH_ASAN),$(FHEROES2_WITH_TSAN)),) SANITIZERS := undefined ifdef FHEROES2_WITH_ASAN SANITIZERS := $(SANITIZERS),address endif ifdef FHEROES2_WITH_TSAN SANITIZERS := $(SANITIZERS),thread endif CCFLAGS := $(CCFLAGS) -fsanitize=$(SANITIZERS) LDFLAGS := $(LDFLAGS) -fsanitize=$(SANITIZERS) endif # # Platform-specific build options # ifndef PLATFORM ifndef OS OS := $(shell uname) endif ifeq ($(OS),FreeBSD) PLATFORM := bsd endif ifeq ($(OS),Darwin) PLATFORM := osx endif ifeq ($(OS),Linux) PLATFORM := all endif ifeq ($(OS),Haiku) PLATFORM := all endif endif include Makefile.$(PLATFORM) # # Build options for third-party libraries # CCFLAGS_TP := $(CCFLAGS) CFLAGS_TP := $(CFLAGS) CXXFLAGS_TP := $(CXXFLAGS) CPPFLAGS_TP := $(CPPFLAGS) # # Build options for fheroes2 # # *FLAGS_FH2 can be passed from platform-specific Makefiles CCFLAGS := $(CCFLAGS) $(CCFLAGS_FH2) CFLAGS := $(CFLAGS) $(CFLAGS_FH2) CXXFLAGS := $(CXXFLAGS) $(CXXFLAGS_FH2) -std=c++17 CPPFLAGS := $(CPPFLAGS) $(CPPFLAGS_FH2) ifdef FHEROES2_WITH_SYSTEM_SMACKER LIBS := $(LIBS) -lsmacker endif LIBS := $(LIBS) -lz $(LDLIBS) ifdef FHEROES2_WITH_DEBUG CCFLAGS := $(CCFLAGS) -DWITH_DEBUG endif ifdef FHEROES2_WITH_IMAGE CCFLAGS := $(CCFLAGS) -DWITH_IMAGE endif ifdef FHEROES2_DATA CCFLAGS := $(CCFLAGS) -DFHEROES2_DATA="$(FHEROES2_DATA)" endif # TODO: Add -Wconversion -Wsign-conversion flags once we fix all the corresponding code smells CCWARNOPTS := -pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wdouble-promotion -Wfloat-conversion -Wfloat-equal \ -Wredundant-decls -Wshadow -Wswitch-default -Wundef -Wunused CFLAGS := $(CFLAGS) $(CCWARNOPTS) CXXFLAGS := $(CXXFLAGS) $(CCWARNOPTS) -Wctor-dtor-privacy -Wextra-semi -Wmissing-declarations -Wold-style-cast \ -Woverloaded-virtual -Wsuggest-override ifdef FHEROES2_STRICT_COMPILATION CCFLAGS := $(CCFLAGS) -Werror endif # # SDL-related build options # # SDL_FLAGS can already be defined in a platform-specific Makefile ifeq ($(origin SDL_FLAGS),undefined) SDL_FLAGS := $(shell sdl2-config --cflags) ifdef FHEROES2_WITH_IMAGE SDL_FLAGS := $(SDL_FLAGS) $(shell libpng-config --cflags) endif endif # SDL_LIBS can already be defined in a platform-specific Makefile ifeq ($(origin SDL_LIBS),undefined) SDL_LIBS := -lSDL2_mixer $(shell sdl2-config --libs) ifdef FHEROES2_WITH_IMAGE SDL_LIBS := $(SDL_LIBS) -lSDL2_image $(shell libpng-config --libs) endif endif CCFLAGS := $(CCFLAGS) $(SDL_FLAGS) LIBS := $(SDL_LIBS) $(LIBS) export CC CXX AR CCFLAGS CFLAGS CXXFLAGS CPPFLAGS LDFLAGS LIBS TARGET .PHONY: all clean all: ifndef FHEROES2_WITH_SYSTEM_SMACKER $(MAKE) -C thirdparty/libsmacker CCFLAGS="$(CCFLAGS_TP)" CFLAGS="$(CFLAGS_TP)" CXXFLAGS="$(CXXFLAGS_TP)" CPPFLAGS="$(CPPFLAGS_TP)" endif $(MAKE) -C engine $(MAKE) -C fheroes2 ifdef FHEROES2_WITH_TOOLS $(MAKE) -C tools endif clean: $(MAKE) -C thirdparty/libsmacker clean $(MAKE) -C engine clean $(MAKE) -C fheroes2 clean $(MAKE) -C tools clean fheroes2-1.1.6+dfsg/src/dist/Makefile.all000066400000000000000000000027011476115357100201260ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### ifndef CXX CXX := g++ endif fheroes2-1.1.6+dfsg/src/dist/Makefile.bsd000066400000000000000000000027401476115357100201310ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### AR := ar CXX := g++ LDFLAGS := $(LDFLAGS) -L/usr/local/lib fheroes2-1.1.6+dfsg/src/dist/Makefile.emscripten000066400000000000000000000051721476115357100215340ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### TARGET := fheroes2.js SDL2_MIXER_FORMATS := mid,mp3 CCFLAGS := $(CCFLAGS) \ --use-port=sdl2 \ --use-port=sdl2_mixer \ --use-port=zlib \ -sSDL2_MIXER_FORMATS=$(SDL2_MIXER_FORMATS) \ -sSTRICT LDFLAGS := $(LDFLAGS) \ --preload-file ../../../files/data/resurrection.h2d@/files/data/resurrection.h2d \ --preload-file ../../../files/lang/@/files/lang/ \ --preload-file ../../../files/timidity/@/etc/ \ -sALLOW_MEMORY_GROWTH \ -sASYNCIFY \ -sASYNCIFY_STACK_SIZE=65536 \ -sINCOMING_MODULE_JS_API=canvas,preRun,setStatus \ -sINITIAL_MEMORY=128mb \ -sMEMORY_GROWTH_LINEAR_STEP=32mb \ -sNO_DISABLE_EXCEPTION_CATCHING \ -sSDL2_MIXER_FORMATS=$(SDL2_MIXER_FORMATS) \ -sSTACK_SIZE=256kb \ -sSTRICT \ -lGL \ -lhtml5 \ -lidbfs.js ifdef FHEROES2_WITH_DEBUG CCFLAGS := $(CCFLAGS) -gsource-map LDFLAGS := $(LDFLAGS) -O0 -gsource-map else CCFLAGS := $(CCFLAGS) -flto LDFLAGS := $(LDFLAGS) -O3 -flto endif ifdef FHEROES2_WITH_THREADS LDFLAGS := $(LDFLAGS) \ -Wno-pthreads-mem-growth \ -sALLOW_BLOCKING_ON_MAIN_THREAD \ -sENVIRONMENT=web,worker \ -sPTHREAD_POOL_SIZE=8 else CCFLAGS := $(filter-out -pthread,$(CCFLAGS)) LDFLAGS := $(filter-out -pthread,$(LDFLAGS)) \ -sENVIRONMENT=web \ -sNO_ALLOW_BLOCKING_ON_MAIN_THREAD endif fheroes2-1.1.6+dfsg/src/dist/Makefile.osx000066400000000000000000000031131476115357100201650ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### AR := ar ifndef CXX CXX := g++ endif ifdef FHEROES2_MACOS_APP_BUNDLE CCFLAGS := $(CCFLAGS) -DMACOS_APP_BUNDLE LDFLAGS := $(LDFLAGS) -framework CoreFoundation endif fheroes2-1.1.6+dfsg/src/dist/Makefile.switch000066400000000000000000000036521476115357100206650ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### include $(DEVKITPRO)/libnx/switch_rules # Common flags (for both C and C++ compilers) for both third-party libraries and fheroes2 CCFLAGS := $(CCFLAGS) $(shell sdl2-config --cflags) -fPIE LDFLAGS := $(LDFLAGS) -specs=$(DEVKITPRO)/libnx/switch.specs # Common flags (for both C and C++ compilers) for fheroes2 only CCFLAGS_FH2 := -DTARGET_NINTENDO_SWITCH LIBS := $(LIBS) -lvorbisidec -lmodplug -lmpg123 -lopusfile -lopus -logg # Prevent sdl2-config --cflags from running once again in the main Makefile SDL_FLAGS := fheroes2-1.1.6+dfsg/src/dist/Makefile.vita000066400000000000000000000047171476115357100203320ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2024 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### AR := arm-vita-eabi-gcc-ar CC := arm-vita-eabi-gcc CXX := arm-vita-eabi-g++ # Common flags (for both C and C++ compilers) for both third-party libraries and fheroes2 CCFLAGS := $(CCFLAGS) -I$(VITASDK)/arm-vita-eabi/include -mcpu=cortex-a9 -mfpu=neon -fgraphite-identity -floop-nest-optimize -fno-lto -fno-tree-slp-vectorize LDFLAGS := $(LDFLAGS) -L$(VITASDK)/arm-vita-eabi/lib -L$(VITASDK)/lib -Wl,--sort-common -Wl,--whole-archive -Wl,--no-whole-archive -Wl,-q # Common flags (for both C and C++ compilers) for fheroes2 only CCFLAGS_FH2 := -DTARGET_PS_VITA SDL_FLAGS := -I$(VITASDK)/arm-vita-eabi/include/SDL2 SDL_LIBS := -L$(VITASDK)/arm-vita-eabi/lib -lSDL2_mixer -lSDL2 -lvita2d -lScePower_stub -lSceAudioIn_stub -lSceAudio_stub -lSceCtrl_stub -lSceHid_stub -lSceTouch_stub \ -lSceDisplay_stub -lSceGxm_stub -lSceAppMgr_stub -lSceSysmodule_stub -lSceCommonDialog_stub -lSceMotion_stub -lFLAC -lmikmod \ -lmodplug -lmpg123 -lvorbisfile -lvorbis -lopusfile -lopus -logg -lxmp fheroes2-1.1.6+dfsg/src/dist/engine/000077500000000000000000000000001476115357100171645ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/dist/engine/Makefile000066400000000000000000000034571476115357100206350ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### ifndef FHEROES2_WITH_SYSTEM_SMACKER CCFLAGS := $(CCFLAGS) -I../../thirdparty/libsmacker endif SOURCEDIR := ../../engine .PHONY: all clean all: libengine.a libengine.a: $(notdir $(patsubst %.cpp, %.o, $(wildcard $(SOURCEDIR)/*.cpp))) $(AR) crvs $@ $^ %.o: $(SOURCEDIR)/%.cpp $(CXX) -c -MD $< $(CCFLAGS) $(CXXFLAGS) $(CPPFLAGS) include $(wildcard *.d) clean: -rm -f *.d *.o libengine.a fheroes2-1.1.6+dfsg/src/dist/fheroes2/000077500000000000000000000000001476115357100174345ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/dist/fheroes2/Makefile000066400000000000000000000043741476115357100211040ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### DEPLIBS := ../engine/libengine.a CCFLAGS := $(CCFLAGS) -I../../engine ifndef FHEROES2_WITH_SYSTEM_SMACKER DEPLIBS := $(DEPLIBS) ../thirdparty/libsmacker/libsmacker.a CCFLAGS := $(CCFLAGS) -I../../thirdparty/libsmacker endif SOURCEROOT := ../../fheroes2 SOURCEDIRS := $(filter %/,$(wildcard $(SOURCEROOT)/*/)) SOURCES := $(wildcard $(SOURCEROOT)/*/*.cpp) VPATH := $(SOURCEDIRS) .PHONY: all pot clean all: $(TARGET) pot pot: fheroes2.pot $(TARGET): $(notdir $(patsubst %.cpp, %.o, $(SOURCES))) $(DEPLIBS) $(CXX) -o $@ $^ $(LIBS) $(LDFLAGS) fheroes2.pot: $(SOURCES) xgettext -d fheroes2 -C -F -k_ -k_n:1,2 -o fheroes2.pot $(sort $(SOURCES)) sed -i~ -e 's/, c-format//' fheroes2.pot %.o: %.cpp $(CXX) -c -MD $< $(addprefix -I, $(SOURCEDIRS)) $(CCFLAGS) $(CXXFLAGS) $(CPPFLAGS) include $(wildcard *.d) clean: -rm -f *.d *.o fheroes2 fheroes2.* fheroes2-1.1.6+dfsg/src/dist/thirdparty/000077500000000000000000000000001476115357100201115ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/dist/thirdparty/libsmacker/000077500000000000000000000000001476115357100222255ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/dist/thirdparty/libsmacker/Makefile000066400000000000000000000032321476115357100236650ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### .PHONY: all clean all: libsmacker.a libsmacker.a: smacker.o $(AR) crvs $@ $^ smacker.o: ../../../thirdparty/libsmacker/smacker.c $(CC) -c -MD $< $(CCFLAGS) $(CFLAGS) $(CPPFLAGS) include $(wildcard *.d) clean: -rm -f *.d *.o libsmacker.a fheroes2-1.1.6+dfsg/src/dist/tools/000077500000000000000000000000001476115357100170575ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/dist/tools/Makefile000066400000000000000000000033741476115357100205260ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2021 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### TARGETS := 82m2wav bin2txt extractor h2dmgr icn2img pal2img til2img xmi2midi .PHONY: all clean all: $(TARGETS) $(TARGETS): %: %.o ../engine/libengine.a $(CXX) -o $@ $^ $(LIBS) $(LDFLAGS) %.o: ../../tools/%.cpp $(CXX) -c -MD $< -I../../engine $(CCFLAGS) $(CXXFLAGS) $(CPPFLAGS) include $(wildcard *.d) clean: -rm -f *.d *.o $(TARGETS) fheroes2-1.1.6+dfsg/src/engine/000077500000000000000000000000001476115357100162215ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/engine/CMakeLists.txt000066400000000000000000000047531476115357100207720ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### file(GLOB_RECURSE LIBENGINE_SOURCES CONFIGURE_DEPENDS *.cpp) add_compile_options("$<$:${GNU_CC_WARN_OPTS}>") add_compile_options("$<$:${GNU_CXX_WARN_OPTS}>") add_compile_options("$<$,$>:${MSVC_CC_WARN_OPTS}>") add_library(engine STATIC ${LIBENGINE_SOURCES}) target_compile_definitions( engine PRIVATE # MSVC: suppress deprecation warnings $<$,$>:_CRT_SECURE_NO_WARNINGS> $<$:WITH_DEBUG> $<$:WITH_IMAGE> $<$:MACOS_APP_BUNDLE> ) target_include_directories( engine PUBLIC $ ) target_link_libraries( engine smacker ${USE_SDL_VERSION}::${USE_SDL_VERSION} ${USE_SDL_VERSION}_mixer::${USE_SDL_VERSION}_mixer $<$:${USE_SDL_VERSION}_image::${USE_SDL_VERSION}_image> $<$:PNG::PNG> Threads::Threads ZLIB::ZLIB ) fheroes2-1.1.6+dfsg/src/engine/agg_file.cpp000066400000000000000000000102331476115357100204610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "agg_file.h" #include #include #include #include namespace fheroes2 { bool AGGFile::open( const std::string & fileName ) { if ( !_stream.open( fileName, "rb" ) ) { return false; } const size_t size = _stream.size(); const size_t count = _stream.getLE16(); const size_t fileRecordSize = sizeof( uint32_t ) * 3; if ( count * ( fileRecordSize + _maxFilenameSize ) >= size ) { return false; } ROStreamBuf fileEntries = _stream.getStreamBuf( count * fileRecordSize ); const size_t nameEntriesSize = _maxFilenameSize * count; _stream.seek( size - nameEntriesSize ); ROStreamBuf nameEntries = _stream.getStreamBuf( nameEntriesSize ); for ( size_t i = 0; i < count; ++i ) { std::string name = nameEntries.getString( _maxFilenameSize ); // Check 32-bit filename hash. if ( fileEntries.getLE32() != calculateAggFilenameHash( name ) ) { // Hash check failed. AGG file is corrupted. _files.clear(); return false; } const uint32_t fileOffset = fileEntries.getLE32(); const uint32_t fileSize = fileEntries.getLE32(); _files.try_emplace( std::move( name ), std::make_pair( fileSize, fileOffset ) ); } if ( _files.size() != count ) { _files.clear(); return false; } return !_stream.fail(); } std::vector AGGFile::read( const std::string & fileName ) { auto it = _files.find( fileName ); if ( it == _files.end() ) { return {}; } const auto [fileSize, fileOffset] = it->second; if ( fileSize > 0 ) { _stream.seek( fileOffset ); return _stream.getRaw( fileSize ); } return {}; } uint32_t calculateAggFilenameHash( const std::string_view str ) { uint32_t hash = 0; uint32_t sum = 0; for ( auto iter = str.rbegin(); iter != str.rend(); ++iter ) { const unsigned char c = static_cast( std::toupper( static_cast( *iter ) ) ); hash = ( hash << 5 ) + ( hash >> 25 ); sum += c; hash += sum + c; } return hash; } } IStreamBase & operator>>( IStreamBase & stream, fheroes2::ICNHeader & icn ) { icn.offsetX = static_cast( stream.getLE16() ); icn.offsetY = static_cast( stream.getLE16() ); icn.width = stream.getLE16(); icn.height = stream.getLE16(); icn.animationFrames = stream.get(); icn.offsetData = stream.getLE32(); return stream; } fheroes2-1.1.6+dfsg/src/engine/agg_file.h000066400000000000000000000056351476115357100201400ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include "serialize.h" namespace fheroes2 { class AGGFile { public: bool isGood() const { return !_stream.fail() && !_files.empty(); } bool open( const std::string & fileName ); std::vector read( const std::string & fileName ); private: static const size_t _maxFilenameSize = 15; // 8.3 ASCIIZ file name + 2-bytes padding StreamFile _stream; std::map, std::less<>> _files; }; struct ICNHeader { int16_t offsetX{ 0 }; int16_t offsetY{ 0 }; uint16_t width{ 0 }; uint16_t height{ 0 }; // Used for adventure map animations, this can replace ICN::AnimationFrame. // The frames count is always a modulus of 32 (only 5 bits are used): for animations with more than 31 frames the value is ( totalFrames - 32 ). // TODO: Find a way to detect that 32 was deducted from the animationFrames value if it is possible. // When the 6th bit in animationFrames is set then it is Monochromatic ICN image. uint8_t animationFrames{ 0 }; uint32_t offsetData{ 0 }; }; uint32_t calculateAggFilenameHash( const std::string_view str ); } IStreamBase & operator>>( IStreamBase & stream, fheroes2::ICNHeader & icn ); fheroes2-1.1.6+dfsg/src/engine/audio.cpp000066400000000000000000001072561476115357100200410ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2008 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "audio.h" #include #include #include #include #include #include #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wswitch-default" #endif #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif #include "core.h" #include "dir.h" #include "logging.h" #include "system.h" #include "thread.h" #include "timing.h" namespace { struct AudioSpec { #if defined( TARGET_PS_VITA ) // Notice: The PS Vita sound resampler is CPU intensive if the value is not 22050. int frequency = 22050; #else // Notice: Value 22050 causes music distortion on Windows. int frequency = 44100; #endif // Signed 16-bit samples with platform-dependent byte order uint16_t format = AUDIO_S16SYS; // Stereo audio support int channels = 2; #if defined( ANDROID ) // Value greater than 1024 causes audio distortion on Android int chunkSize = 1024; #elif defined( __EMSCRIPTEN__ ) // When a WebAssembly app is running in a browser, no background threads (emulated by the web workers) have // access to the audio. The audio can only be accessed (and feeded) from the main thread (when yielding to // the browser's event loop). The chunk size should be large enough to avoid playback issues caused by other // activities performed on the main thread. On the other hand, it shouldn't be too big, because it is possible // to stop the audio playback only after the current chunk has been completely played. int chunkSize = 8192; #else int chunkSize = 2048; #endif }; std::atomic isInitialized{ false }; std::atomic mixerChannelCount{ 0 }; bool isMuted{ false }; int savedMixerVolume{ 0 }; int savedMusicVolume{ 0 }; int musicFadeInMs{ 0 }; // This mutex protects all operations with audio. In order to avoid deadlocks, it shouldn't // be acquired in any callback functions that can be called by SDL_Mixer. std::recursive_mutex audioMutex; class SoundSampleManager { public: SoundSampleManager() = default; SoundSampleManager( const SoundSampleManager & ) = delete; ~SoundSampleManager() { // Make sure that all sound samples have been eventually freed assert( std::all_of( _channelSamples.begin(), _channelSamples.end(), []( const auto & item ) { static const decltype( item.second ) nullQueue{ nullptr, nullptr }; return item.second == nullQueue; } ) ); } SoundSampleManager & operator=( const SoundSampleManager & ) = delete; void channelStarted( const int channelId, Mix_Chunk * sample ) { assert( channelId >= 0 && sample != nullptr ); const auto iter = _channelSamples.find( channelId ); if ( iter != _channelSamples.end() ) { auto & sampleQueue = iter->second; if ( sampleQueue.first == nullptr ) { sampleQueue.first = sample; } else if ( sampleQueue.second == nullptr ) { sampleQueue.second = sample; } else { // The sample queue is already full, this shouldn't happen assert( 0 ); } return; } const auto res = _channelSamples.try_emplace( channelId, std::make_pair( sample, nullptr ) ); if ( !res.second ) { assert( 0 ); } } // This method can be called from the SDL_Mixer callback (without acquiring the audioMutex) void channelFinished( const int channelId ) { assert( channelId >= 0 ); const std::scoped_lock lock( _channelsToCleanupMutex ); _channelsToCleanup.push_back( channelId ); } void clearFinishedSamples() { std::vector channelsToCleanup; { const std::scoped_lock lock( _channelsToCleanupMutex ); std::swap( channelsToCleanup, _channelsToCleanup ); } for ( const int channel : channelsToCleanup ) { const auto iter = _channelSamples.find( channel ); assert( iter != _channelSamples.end() ); auto & sampleQueue = iter->second; assert( sampleQueue.first != nullptr ); Mix_FreeChunk( sampleQueue.first ); // Shift the sample queue sampleQueue.first = sampleQueue.second; sampleQueue.second = nullptr; } } private: std::map> _channelSamples; std::vector _channelsToCleanup; // This mutex protects operations with _channelsToCleanup std::mutex _channelsToCleanupMutex; }; SoundSampleManager soundSampleManager; // This is the callback function set by Mix_ChannelFinished(). As a rule, it is called from // a SDL_Mixer internal thread. Calls of any SDL_Mixer functions are not allowed in callbacks. void SDLCALL channelFinished( const int channelId ) { // This callback function should never be called if audio is not initialized assert( isInitialized ); soundSampleManager.channelFinished( channelId ); } class MusicInfo { public: explicit MusicInfo( std::vector v ) : _source( std::move( v ) ) { // Do nothing } explicit MusicInfo( std::string file ) : _source( std::move( file ) ) { // Do nothing } MusicInfo( const MusicInfo & ) = delete; ~MusicInfo() = default; MusicInfo & operator=( const MusicInfo & ) = delete; // Mix_Music objects should never be cached because they store the state of the music decoder's backend, // and should be passed to functions like Mix_PlayMusic() only once, otherwise weird things can happen. std::unique_ptr createMusic() const { if ( std::holds_alternative>( _source ) ) { const std::vector & v = std::get>( _source ); const std::unique_ptr rwops( SDL_RWFromConstMem( v.data(), static_cast( v.size() ) ), SDL_FreeRW ); if ( !rwops ) { ERROR_LOG( "Failed to create a music track from memory. The error: " << SDL_GetError() ) return { nullptr, Mix_FreeMusic }; } std::unique_ptr result( Mix_LoadMUS_RW( rwops.get(), 0 ), Mix_FreeMusic ); if ( !result ) { ERROR_LOG( "Failed to create a music track from memory. The error: " << Mix_GetError() ) } return result; } if ( std::holds_alternative( _source ) ) { const std::string & file = std::get( _source ); std::unique_ptr result( Mix_LoadMUS( System::encLocalToUTF8( file ).c_str() ), Mix_FreeMusic ); if ( !result ) { ERROR_LOG( "Failed to create a music track from file " << file << ". The error: " << Mix_GetError() ) } return result; } assert( 0 ); return { nullptr, Mix_FreeMusic }; } double getPosition() const { return _position; } void setPosition( const double pos ) { _position = pos; } private: const std::variant, std::string> _source; double _position{ 0 }; }; class MusicTrackManager { public: MusicTrackManager() = default; MusicTrackManager( const MusicTrackManager & ) = delete; ~MusicTrackManager() { // Make sure that all music tracks have been eventually freed assert( _musicQueue == nullptr ); } MusicTrackManager & operator=( const MusicTrackManager & ) = delete; bool isTrackInMusicDB( const uint64_t musicUID ) const { return ( _musicDB.find( musicUID ) != _musicDB.end() ); } std::shared_ptr getTrackFromMusicDB( const uint64_t musicUID ) const { const auto iter = _musicDB.find( musicUID ); assert( iter != _musicDB.end() ); return iter->second; } void addTrackToMusicDB( const uint64_t musicUID, const std::shared_ptr & track ) { const auto res = _musicDB.try_emplace( musicUID, track ); if ( !res.second ) { assert( 0 ); } } void clearMusicDB() { _musicDB.clear(); } std::weak_ptr getCurrentTrack() const { return _currentTrack; } uint64_t getCurrentTrackUID() const { return _currentTrackUID; } Music::PlaybackMode getCurrentTrackPlaybackMode() const { return _currentTrackPlaybackMode; } // This method can be called from the SDL_Mixer callback (without acquiring the audioMutex) uint64_t getCurrentTrackChangeCounter() const { return _currentTrackChangeCounter; } double getCurrentTrackPosition() const { return _currentTrackTimer.getS(); } void updateCurrentTrack( const uint64_t musicUID, const Music::PlaybackMode trackPlaybackMode ) { _currentTrack = getTrackFromMusicDB( musicUID ); _currentTrackUID = musicUID; _currentTrackPlaybackMode = trackPlaybackMode; ++_currentTrackChangeCounter; } void resetCurrentTrack() { _currentTrack = {}; _currentTrackUID = 0; _currentTrackPlaybackMode = Music::PlaybackMode::PLAY_ONCE; ++_currentTrackChangeCounter; } void resetTimer() { _currentTrackTimer.reset(); } void musicStarted( Mix_Music * mus ) { // If the _musicQueue is not nullptr, then the music queue (consisting of only one music // track) is already full, this shouldn't happen assert( _musicQueue == nullptr ); _musicQueue = mus; } void clearFinishedMusic() { // This queue consists of only one music track if ( _musicQueue == nullptr ) { return; } Mix_FreeMusic( _musicQueue ); _musicQueue = nullptr; } private: std::map> _musicDB; std::weak_ptr _currentTrack; uint64_t _currentTrackUID{ 0 }; Music::PlaybackMode _currentTrackPlaybackMode{ Music::PlaybackMode::PLAY_ONCE }; // This counter should be incremented every time the current track or its playback mode changes std::atomic _currentTrackChangeCounter{ 0 }; fheroes2::Time _currentTrackTimer; Mix_Music * _musicQueue{ nullptr }; }; MusicTrackManager musicTrackManager; void playMusic( const uint64_t musicUID, Music::PlaybackMode playbackMode ); class MusicRestartManager final : public MultiThreading::AsyncManager { public: void restartCurrentMusicTrack() { const std::scoped_lock lock( _mutex ); _trackChangeCounter = musicTrackManager.getCurrentTrackChangeCounter(); notifyWorker(); } private: // This method is called by the worker thread and is protected by _mutex bool prepareTask() override { // Make a copy for the worker thread to ensure that this counter will // not be changed by another thread in the middle of executeTask() _taskTrackChangeCounter = _trackChangeCounter; return false; } // This method is called by the worker thread, but is not protected by _mutex void executeTask() override { const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } // The current track managed to change during the start of this task if ( _taskTrackChangeCounter != musicTrackManager.getCurrentTrackChangeCounter() ) { return; } // REWIND_AND_PLAY_INFINITE should be handled by the SDL_Mixer itself if ( musicTrackManager.getCurrentTrackPlaybackMode() != Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ) { return; } const std::shared_ptr currentTrack = musicTrackManager.getCurrentTrack().lock(); assert( currentTrack ); currentTrack->setPosition( 0 ); playMusic( musicTrackManager.getCurrentTrackUID(), musicTrackManager.getCurrentTrackPlaybackMode() ); } // This variable can be accessed by multiple threads and it is protected by _mutex uint64_t _trackChangeCounter{ 0 }; // This variable can be accessed only by the worker thread uint64_t _taskTrackChangeCounter{ 0 }; }; MusicRestartManager musicRestartManager; // This is the callback function set by Mix_HookMusicFinished(). As a rule, it is called from // a SDL_Mixer internal thread. Calls of any SDL_Mixer functions are not allowed in callbacks. void SDLCALL musicFinished() { // This callback function should never be called if audio is not initialized assert( isInitialized ); musicRestartManager.restartCurrentMusicTrack(); } bool isMusicResumeSupported( const Mix_Music * mus ) { assert( mus != nullptr ); const Mix_MusicType musicType = Mix_GetMusicType( mus ); return ( musicType == Mix_MusicType::MUS_OGG ) || ( musicType == Mix_MusicType::MUS_MP3 ) || ( musicType == Mix_MusicType::MUS_FLAC ); } void playMusic( const uint64_t musicUID, Music::PlaybackMode playbackMode ) { // This function should never be called if a music track is currently playing. // Thus we have a guarantee that the Mix_HookMusicFinished()'s callback will // not be called while we are modifying the current track information. assert( !Music::isPlaying() ); musicTrackManager.clearFinishedMusic(); const std::shared_ptr track = musicTrackManager.getTrackFromMusicDB( musicUID ); assert( track ); std::unique_ptr mus = track->createMusic(); if ( !mus ) { musicTrackManager.resetCurrentTrack(); return; } bool resumePlayback = false; bool autoLoop = false; if ( playbackMode == Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ) { if ( isMusicResumeSupported( mus.get() ) ) { resumePlayback = true; } else { // It is impossible to resume this track, let's reflect it by changing the playback mode playbackMode = Music::PlaybackMode::REWIND_AND_PLAY_INFINITE; autoLoop = true; } } else if ( playbackMode == Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ) { autoLoop = true; } // Update the current track information while the music playback is not yet started, so the // Mix_HookMusicFinished()'s callback cannot be called musicTrackManager.updateCurrentTrack( musicUID, playbackMode ); const int loopCount = autoLoop ? -1 : 0; int returnCode = -1; // Resume the music only if at least 1 second of the track has been played. if ( resumePlayback && track->getPosition() > 1 ) { returnCode = Mix_FadeInMusicPos( mus.get(), loopCount, musicFadeInMs, track->getPosition() ); if ( returnCode != 0 ) { ERROR_LOG( "Failed to resume the music track. The error: " << Mix_GetError() ) } } // Either there is no need to resume music playback, or the resumption failed. Let's try to // start the playback from the beginning. if ( returnCode != 0 ) { track->setPosition( 0 ); returnCode = Mix_FadeInMusic( mus.get(), loopCount, musicFadeInMs ); if ( returnCode != 0 ) { ERROR_LOG( "Failed to play the music track. The error: " << Mix_GetError() ) } } if ( returnCode != 0 ) { // Since the music playback failed, the Mix_HookMusicFinished()'s callback cannot be called // here, so we can safely reset the current track information musicTrackManager.resetCurrentTrack(); return; } // For better accuracy reset the timer right after the actual playback starts musicTrackManager.resetTimer(); // There can be no more than one element in the music queue - the current track, the previous // one should already be freed musicTrackManager.musicStarted( mus.release() ); } // By the Weber-Fechner law, humans subjective sound sensation is proportional logarithm of sound intensity. // So for linear changing sound intensity we have to change the volume exponential. // There is a good explanation at https://www.dr-lex.be/info-stuff/volumecontrols.html. // This function maps sound volumes in percents to SDL units with values [0..MIX_MAX_VOLUME] by exponential law. int normalizeToSDLVolume( const int volumePercentage ) { if ( volumePercentage < 0 ) { // Why are you passing a negative volume value? assert( 0 ); return 0; } if ( volumePercentage >= 100 ) { // Reserve an extra 0.5 dB for possible sound overloads in SDL_mixer, multiplying max volume by 50/53. return MIX_MAX_VOLUME * 50 / 53; } // MIX_MAX_VOLUME is divided by 10.6, not 10 to reserve an extra 0.5 dB for possible sound overloads in SDL_mixer. return static_cast( ( std::exp( std::log( 10 + 1 ) * volumePercentage / 100 ) - 1 ) / 10.6 * MIX_MAX_VOLUME ); } // Synchronizes the volume settings of all active mixer channels void syncChannelsVolume() { if ( Mix_AllocateChannels( -1 ) < 2 ) { return; } Mix_Volume( -1, Mix_Volume( 0, -1 ) ); } #ifndef NDEBUG // Checks whether the volume settings of all active mixer channels are synchronized bool checkChannelsVolumeSync() { const int channelsCount = Mix_AllocateChannels( -1 ); if ( channelsCount < 2 ) { return true; } const int vol = Mix_Volume( 0, -1 ); for ( int i = 1; i < channelsCount; ++i ) { if ( Mix_Volume( i, -1 ) != vol ) { return false; } } return true; } #endif } void Audio::Init() { const std::scoped_lock lock( audioMutex ); if ( isInitialized ) { // If this assertion blows up you are trying to initialize an already initialized system. assert( 0 ); return; } if ( !fheroes2::isComponentInitialized( fheroes2::SystemInitializationComponent::Audio ) ) { ERROR_LOG( "The audio subsystem was not initialized." ) return; } const int initializationFlags = MIX_INIT_FLAC | MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_MID; const int initializedFlags = Mix_Init( initializationFlags ); if ( ( initializedFlags & initializationFlags ) != initializationFlags ) { DEBUG_LOG( DBG_ENGINE, DBG_WARN, "Expected music initialization flags as " << initializationFlags << " but received " << ( initializedFlags & initializationFlags ) ) if ( ( initializedFlags & MIX_INIT_FLAC ) == 0 ) { DEBUG_LOG( DBG_ENGINE, DBG_WARN, "FLAC module failed to be initialized" ) } if ( ( initializedFlags & MIX_INIT_MP3 ) == 0 ) { DEBUG_LOG( DBG_ENGINE, DBG_WARN, "MP3 module failed to be initialized" ) } if ( ( initializedFlags & MIX_INIT_OGG ) == 0 ) { DEBUG_LOG( DBG_ENGINE, DBG_WARN, "OGG module failed to be initialized" ) } if ( ( initializedFlags & MIX_INIT_MID ) == 0 ) { DEBUG_LOG( DBG_ENGINE, DBG_WARN, "MID module failed to be initialized" ) } } const AudioSpec audioSpec; if ( Mix_OpenAudio( audioSpec.frequency, audioSpec.format, audioSpec.channels, audioSpec.chunkSize ) != 0 ) { ERROR_LOG( "Failed to initialize an audio device. The error: " << Mix_GetError() ) return; } int frequency = 0; uint16_t format = 0; int channels = 0; const int deviceInitCount = Mix_QuerySpec( &frequency, &format, &channels ); if ( deviceInitCount == 0 ) { ERROR_LOG( "Failed to query an audio device specs. The error: " << Mix_GetError() ) } if ( deviceInitCount != 1 ) { // The device must be opened only once. assert( 0 ); ERROR_LOG( "Trying to initialize an audio system that has been already initialized." ) } if ( audioSpec.frequency != frequency ) { // At least on Windows the standard frequency is 48000 Hz. Sounds in the game are 22500 Hz frequency. // However, resampling is done inside SDL so this is not exactly an error. DEBUG_LOG( DBG_ENGINE, DBG_WARN, "Audio frequency is initialized as " << frequency << " instead of " << audioSpec.frequency ) } if ( audioSpec.format != format ) { ERROR_LOG( "Audio format is initialized as " << format << " instead of " << audioSpec.format ) } if ( audioSpec.channels != channels ) { ERROR_LOG( "Number of audio channels is initialized as " << channels << " instead of " << audioSpec.channels ) } // Make sure that all mixer channels have the same volume settings. syncChannelsVolume(); // By default this value should be MIX_CHANNELS. mixerChannelCount = Mix_AllocateChannels( -1 ); isMuted = false; savedMixerVolume = 0; savedMusicVolume = 0; musicRestartManager.createWorker(); Mix_ChannelFinished( channelFinished ); Mix_HookMusicFinished( musicFinished ); isInitialized = true; } void Audio::Quit() { { const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { // Nothing to do. return; } if ( !fheroes2::isComponentInitialized( fheroes2::SystemInitializationComponent::Audio ) ) { // Something wrong with the logic! The component must be initialized. assert( 0 ); return; } Music::Stop(); Mixer::Stop(); Mix_ChannelFinished( nullptr ); Mix_HookMusicFinished( nullptr ); soundSampleManager.clearFinishedSamples(); musicTrackManager.clearFinishedMusic(); musicTrackManager.clearMusicDB(); Mix_CloseAudio(); Mix_Quit(); mixerChannelCount = 0; isInitialized = false; } // We can't hold the audioMutex here because if MusicRestartManager's working // thread is already waiting on it, then there will be a deadlock while waiting // for it to join. The Mix_HookMusicFinished()'s callback can no longer be called // at the moment because it has been already unregistered. musicRestartManager.stopWorker(); } void Audio::Mute() { const std::scoped_lock lock( audioMutex ); if ( isMuted || !isInitialized ) { return; } assert( Mix_AllocateChannels( -1 ) > 0 && checkChannelsVolumeSync() ); isMuted = true; // Mix_Volume( -1, X ) returns the average of all channels' volumes, but since they all have to have the same volume (and we just checked that their volume settings // are in sync) it is safe to use its result here. savedMixerVolume = Mix_Volume( -1, 0 ); savedMusicVolume = Mix_VolumeMusic( 0 ); } void Audio::Unmute() { const std::scoped_lock lock( audioMutex ); if ( !isMuted || !isInitialized ) { return; } assert( Mix_AllocateChannels( -1 ) > 0 && savedMixerVolume >= 0 && savedMusicVolume >= 0 ); isMuted = false; Mix_Volume( -1, savedMixerVolume ); Mix_VolumeMusic( savedMusicVolume ); } bool Audio::isValid() { return isInitialized; } void Mixer::SetChannels( const int num ) { if ( num <= 0 ) { // When trying to allocate zero channels, an attempt to call Mix_Volume( -1, X ) results in division by zero when calculating the average volume assert( 0 ); return; } const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } assert( checkChannelsVolumeSync() ); mixerChannelCount = Mix_AllocateChannels( num ); if ( num != mixerChannelCount ) { ERROR_LOG( "Failed to allocate the requested number of audio channels. The requested number of channels is " << num << ", the actual allocated number is " << mixerChannelCount ) } assert( mixerChannelCount > 0 ); if ( isMuted ) { // Make sure that all mixer channels (including the ones that have just been allocated) are muted. Mix_Volume( -1, 0 ); } else { // Make sure that all mixer channels (including the ones that have just been allocated) have the same volume settings. syncChannelsVolume(); } } int Mixer::getChannelCount() { return mixerChannelCount; } int Mixer::Play( const uint8_t * ptr, const uint32_t size, const bool loop, const std::optional> position /* = {} */ ) { if ( ptr == nullptr || size == 0 ) { // You are trying to play an empty sound. Check your logic! assert( 0 ); return -1; } const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return -1; } soundSampleManager.clearFinishedSamples(); const std::unique_ptr rwops( SDL_RWFromConstMem( ptr, static_cast( size ) ), SDL_FreeRW ); if ( !rwops ) { ERROR_LOG( "Failed to create an audio chunk from memory. The error: " << SDL_GetError() ) return -1; } std::unique_ptr sample( Mix_LoadWAV_RW( rwops.get(), 0 ), Mix_FreeChunk ); if ( !sample ) { ERROR_LOG( "Failed to create an audio chunk from memory. The error: " << Mix_GetError() ) return -1; } // SDL itself maintains all internal channel bookkeeping, so when using the "first free channel" // for playback, it is not known in advance which channel will be used. If additional channel // setup is needed, then, to avoid arbitrary volume fluctuations, we will temporarily mute the // audio chunk itself until we can properly adjust the channel parameters. const int chunkVolume = position ? Mix_VolumeChunk( sample.get(), 0 ) : 0; if ( chunkVolume < 0 ) { ERROR_LOG( "Failed to mute the audio chunk. The error: " << Mix_GetError() ) return -1; } const int channel = Mix_PlayChannel( -1, sample.get(), loop ? -1 : 0 ); if ( channel < 0 ) { ERROR_LOG( "Failed to play the audio chunk. The error: " << Mix_GetError() ) return channel; } if ( position ) { // Immediately pause the channel so as not to continue playing while it is being set up Mix_Pause( channel ); setPosition( channel, position->first, position->second ); // When restoring the volume of an audio chunk, the only correct result of the call is zero, // because this is exactly what the volume of the muted chunk should be if ( Mix_VolumeChunk( sample.get(), chunkVolume ) != 0 ) { ERROR_LOG( "Failed to restore the volume of the audio chunk for channel " << channel << ". The error: " << Mix_GetError() ) } // Resume the channel as soon as all its parameters are settled Mix_Resume( channel ); } // There can be a maximum of two items in the sample queue for a channel: // the previous sample (if it hasn't been freed yet) and the current one soundSampleManager.channelStarted( channel, sample.release() ); return channel; } void Mixer::setPosition( const int channelId, const int16_t angle, const uint8_t distance ) { const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } if ( Mix_SetPosition( channelId, angle, distance ) == 0 ) { ERROR_LOG( "Failed to set the position of channel " << channelId << ". The error: " << Mix_GetError() ) } } void Mixer::setVolume( const int volumePercentage ) { const int volume = normalizeToSDLVolume( volumePercentage ); const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } assert( Mix_AllocateChannels( -1 ) > 0 && checkChannelsVolumeSync() ); if ( isMuted ) { savedMixerVolume = volume; return; } Mix_Volume( -1, volume ); } void Mixer::Stop( const int channelId /* = -1 */ ) { const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } Mix_HaltChannel( channelId ); } bool Mixer::isPlaying( const int channelId ) { const std::scoped_lock lock( audioMutex ); return isInitialized && Mix_Playing( channelId ) > 0; } bool Music::Play( const uint64_t musicUID, const PlaybackMode playbackMode ) { const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return false; } if ( musicTrackManager.isTrackInMusicDB( musicUID ) ) { Stop(); playMusic( musicUID, playbackMode ); return true; } return false; } void Music::Play( const uint64_t musicUID, const std::vector & v, const PlaybackMode playbackMode ) { if ( v.empty() ) { return; } const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } musicTrackManager.addTrackToMusicDB( musicUID, std::make_shared( v ) ); Stop(); playMusic( musicUID, playbackMode ); } void Music::Play( const uint64_t musicUID, const std::string & file, const PlaybackMode playbackMode ) { if ( file.empty() ) { // Nothing to play, the file name is empty. return; } const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } musicTrackManager.addTrackToMusicDB( musicUID, std::make_shared( file ) ); Stop(); playMusic( musicUID, playbackMode ); } void Music::SetFadeInMs( const int timeMs ) { if ( timeMs < 0 ) { // Why are you even setting a negative value? assert( 0 ); return; } const std::scoped_lock lock( audioMutex ); musicFadeInMs = timeMs; } void Music::setVolume( const int volumePercentage ) { const int volume = normalizeToSDLVolume( volumePercentage ); const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } if ( isMuted ) { savedMusicVolume = volume; return; } Mix_VolumeMusic( volume ); } void Music::Stop() { const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } if ( musicTrackManager.getCurrentTrack().expired() ) { // Nothing to do. return; } // Always returns 0. After this call we have a guarantee that the Mix_HookMusicFinished()'s // callback will not be called while we are modifying the current track information. Mix_HaltMusic(); const std::shared_ptr currentTrack = musicTrackManager.getCurrentTrack().lock(); assert( currentTrack ); // We can and should reliably calculate the current playback position, let's remember it if ( musicTrackManager.getCurrentTrackPlaybackMode() == PlaybackMode::RESUME_AND_PLAY_INFINITE ) { currentTrack->setPosition( currentTrack->getPosition() + musicTrackManager.getCurrentTrackPosition() ); } // We either shouldn't (PLAY_ONCE) or can't (REWIND_AND_PLAY_INFINITE) reliably calculate the // current playback position, let's reset it to zero else { currentTrack->setPosition( 0 ); } musicTrackManager.resetCurrentTrack(); } bool Music::isPlaying() { const std::scoped_lock lock( audioMutex ); return !musicTrackManager.getCurrentTrack().expired() && Mix_PlayingMusic(); } void Music::SetMidiSoundFonts( const ListFiles & files ) { const std::scoped_lock lock( audioMutex ); if ( !isInitialized ) { return; } std::string filePaths; for ( const std::string & file : files ) { filePaths.append( file ); filePaths.push_back( ';' ); } // Remove the last semicolon if ( !filePaths.empty() ) { assert( filePaths.back() == ';' ); filePaths.pop_back(); } if ( Mix_SetSoundFonts( System::encLocalToUTF8( filePaths ).c_str() ) == 0 ) { ERROR_LOG( "Failed to set MIDI SoundFonts using paths " << filePaths << ". The error: " << Mix_GetError() ) } } fheroes2-1.1.6+dfsg/src/engine/audio.h000066400000000000000000000120551476115357100174760ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2008 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include struct ListFiles; namespace Audio { // Audio initialization and deinitialization functions are not designed to be called // concurrently from different threads. They should be called from the main thread only. void Init(); void Quit(); void Mute(); void Unmute(); bool isValid(); } namespace Mixer { void SetChannels( const int num ); int getChannelCount(); // Starts playback of the given sound with the ability of looping it, as well as (optionally) // the ability to specify the position of the sound source relative to the listener (the angle // of direction to the sound source in degrees and the distance to the sound source). int Play( const uint8_t * ptr, const uint32_t size, const bool loop, const std::optional> position = {} ); void setVolume( const int volumePercentage ); // Sets the position of the sound source relative to the listener (the angle of direction to // the sound source in degrees and the distance to the sound source) for the given channel. void setPosition( const int channelId, const int16_t angle, const uint8_t distance ); void Stop( const int channelId = -1 ); bool isPlaying( const int channelId ); } namespace Music { enum class PlaybackMode : uint8_t { // Play a music track once from the beginning, do not remember the position at which // playback of this track was stopped (rewind it to the beginning when playback stops) PLAY_ONCE, // Play a music track in an endless loop, starting from its previously remembered position // (or from the beginning if this track is being played for the first time) and remember // the position at which playback of this track was stopped RESUME_AND_PLAY_INFINITE, // Play a music track in an endless loop, starting from the beginning, do not remember // the position at which playback of this track was stopped (rewind it to the beginning // when playback stops) REWIND_AND_PLAY_INFINITE }; // Music UID is used to store metadata of music tracks in the music database. It is caller's // responsibility to generate them. This function searches for a music track with the specified // UID in the database and starts playback if it is found. Returns true if the music track was // found in the database, otherwise returns false. bool Play( const uint64_t musicUID, const PlaybackMode playbackMode ); // Adds a music track from the memory buffer to the music database and starts playback. A music // track with the specified UID should not already be present in the database. void Play( const uint64_t musicUID, const std::vector & v, const PlaybackMode playbackMode ); // Adds the music track available in the specified file to the music database and starts playback. // A music track with the specified UID should not already be present in the database. void Play( const uint64_t musicUID, const std::string & file, const PlaybackMode playbackMode ); void setVolume( const int volumePercentage ); void SetFadeInMs( const int timeMs ); void Stop(); bool isPlaying(); void SetMidiSoundFonts( const ListFiles & files ); std::vector Xmi2Mid( const std::vector & buf ); } fheroes2-1.1.6+dfsg/src/engine/audio_xmi2mid.cpp000066400000000000000000000602261476115357100214650ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2013 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "audio.h" // IWYU pragma: associated #include "logging.h" #include "serialize.h" #include "tools.h" // The original MIDI files are stored in XMI format which is not readable by SDL. // You can read about this format here: https://moddingwiki.shikadi.net/wiki/XMI_Format // // A conversion from XMI to MID files is required before playing files. // // MIDI format is described here: http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html // and here: https://en.wikipedia.org/wiki/General_MIDI namespace { #ifdef WITH_DEBUG const std::array instrumentDescription = { // // Piano ( 0 - 7 ) // "Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano", "Electric Piano 1 (Rhodes Piano)", "Electric Piano 2 (Chorused Piano)", "Harpsichord", "Clavinet", // // Chromatic Percussion ( 8 - 15 ) // "Celesta", "Glockenspiel", "Music Box", "Vibraphone", "Marimba", "Xylophone", "Tubular Bells", "Dulcimer (Santur)", // // Organ ( 16 - 23 ) // "Drawbar Organ (Hammond)", "Percussive Organ", "Rock Organ", "Church Organ", "Reed Organ", "Accordion (French)", "Harmonica", "Tango Accordion (Band neon)", // // Guitar ( 24 - 31 ) // "Acoustic Guitar (nylon)", "Acoustic Guitar (steel)", "Electric Guitar (jazz)", "Electric Guitar (clean)", "Electric Guitar (muted)", "Overdriven Guitar", "Distortion Guitar", "Guitar harmonics", // // Bass ( 32 - 39 ) // "Acoustic Bass", "Electric Bass (fingered)", "Electric Bass (picked)", "Fretless Bass", "Slap Bass 1", "Slap Bass 2", "Synth Bass 1", "Synth Bass 2", // // Strings ( 40 - 47 ) // "Violin", "Viola", "Cello", "Contrabass", "Tremolo Strings", "Pizzicato Strings", "Orchestral Harp", "Timpani", // // Strings ( 48 - 55 ) // "String Ensemble 1 (strings)", "String Ensemble 2 (slow strings)", "SynthStrings 1", "SynthStrings 2", "Choir Aahs", "Voice Oohs", "Synth Voice", "Orchestra Hit", // // Brass ( 56 - 63 ) // "Trumpet", "Trombone", "Tuba", "Muted Trumpet", "French Horn", "Brass Section", "SynthBrass 1", "SynthBrass 2", // // Reed ( 64 - 71 ) // "Soprano Sax", "Alto Sax", "Tenor Sax", "Baritone Sax", "Oboe", "English Horn", "Bassoon", "Clarinet", // // Pipe ( 72 - 79 ) // "Piccolo", "Flute", "Recorder", "Pan Flute", "Blown Bottle", "Shakuhachi", "Whistle", "Ocarina", // // Synth Lead ( 80 - 87 ) // "Lead 1 (square wave)", "Lead 2 (sawtooth wave)", "Lead 3 (calliope)", "Lead 4 (chiffer)", "Lead 5 (charang)", "Lead 6 (voice solo)", "Lead 7 (fifths)", "Lead 8 (bass + lead)", // // Synth Pad ( 88 - 95 ) // "Pad 1 (new age Fantasia)", "Pad 2 (warm)", "Pad 3 (polysynth)", "Pad 4 (choir space voice)", "Pad 5 (bowed glass)", "Pad 6 (metallic pro)", "Pad 7 (halo)", "Pad 8 (sweep)", // // Synth Effects ( 96 - 103 ) // "FX 1 (rain)", "FX 2 (soundtrack)", "FX 3 (crystal)", "FX 4 (atmosphere)", "FX 5 (brightness)", "FX 6 (goblins)", "FX 7 (echoes, drops)", "FX 8 (sci-fi, star theme)", // // Ethnic ( 104 - 111 ) // "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bag pipe", "Fiddle", "Shanai", // // Percussive ( 112 - 119 ) // "Tinkle Bell", "Agogo", "Steel Drums", "Woodblock", "Taiko Drum", "Melodic Tom", "Synth Drum", "Reverse Cymbal", // // Sound effects ( 120 - 127 ) // "Guitar Fret Noise", "Breath Noise", "Seashore", "Bird Tweet", "Telephone Ring", "Helicopter", "Applause", "Gunshot" }; // Some (but not all) commonly used MIDI drum kits are listed here: https://en.wikipedia.org/wiki/General_MIDI_Level_2#Drum_sounds const std::map drumKitDescription = { { 0, "Standard Kit" }, { 8, "Room Kit" }, { 16, "Power Kit" }, { 24, "Electronic Kit" }, { 25, "TR-808 Kit" }, { 32, "Jazz Kit" }, { 40, "Brush Kit" }, { 48, "Orchestral Kit" }, { 49, "Fix Room Kit" }, { 56, "Sound FX Kit" } }; #endif enum class Tag : uint32_t { FORM = 0x464F524D, XDIR = 0x58444952, INFO = 0x494E464F, CAT0 = 0x43415420, XMID = 0x584D4944, TIMB = 0x54494D42, EVNT = 0x45564E54, RBRN = 0x5242524E, MTHD = 0x4D546864, MTRK = 0x4D54726B }; // Some numbers in MIDI Files are represented in a form called VARIABLE-LENGTH QUANTITY. struct VariableLengthQuantity { uint32_t value{ 0 }; uint32_t lengthInBytes{ 0 }; }; bool readVariableLengthQuantity( const std::vector::const_iterator data, const std::vector::const_iterator dataEnd, VariableLengthQuantity & quantity ) { quantity = {}; auto iter = data; while ( iter < dataEnd && ( *iter ) > 127 ) { if ( ( iter - data ) >= 4 ) { // The largest number to read is 4 bytes. ERROR_LOG( "XMI parse error: the field size exceeds 4 bytes" ) return false; } quantity.value |= 0x0000007F & *iter; quantity.value <<= 7; ++iter; } if ( iter < dataEnd ) { quantity.value += *iter; } quantity.lengthInBytes = static_cast( iter - data ) + 1; return true; } std::vector packVariableLengthQuantity( const uint32_t delta ) { const uint8_t c1 = static_cast( delta & 0x0000007F ); uint8_t c2 = static_cast( ( delta & 0x00003F80 ) >> 7 ); uint8_t c3 = static_cast( ( delta & 0x001FC000 ) >> 14 ); uint8_t c4 = static_cast( ( delta & 0x0FE00000 ) >> 21 ); if ( c4 ) { c4 |= 0x80; c3 |= 0x80; c2 |= 0x80; return { c4, c3, c2, c1 }; } if ( c3 ) { c3 |= 0x80; c2 |= 0x80; return { c3, c2, c1 }; } if ( c2 ) { c2 |= 0x80; return { c2, c1 }; } return { c1 }; } struct IFFChunkHeader { // ASCII string 4 bytes long, padded with a space character 0x20 if necessary. Tag ID{ 0 }; // Big-endian. uint32_t length{ 0 }; IFFChunkHeader() = default; IFFChunkHeader( const Tag id, const uint32_t sz ) : ID( id ) , length( sz ) { // Do nothing. } // Returns the size in bytes that this structure will occupy in serialized binary form inside an XMI or MIDI file size_t sizeInBytes() const { // This header contains of two 4-byte integers. return sizeof( ID ) + sizeof( length ); } }; IStreamBase & operator>>( IStreamBase & stream, IFFChunkHeader & st ) { st.ID = static_cast( stream.getBE32() ); st.length = stream.getBE32(); return stream; } OStreamBase & operator<<( OStreamBase & stream, const IFFChunkHeader & st ) { stream.putBE32( static_cast>( st.ID ) ); stream.putBE32( st.length ); return stream; } struct GroupChunkHeader { // ASCII string 4 bytes long, padded with a space character 0x20 if necessary - either 'FORM', 'CAT ' or 'LIST'. Tag ID{ 0 }; // Big-endian. uint32_t length{ 0 }; // ASCII string 4 bytes long, padded with a space character 0x20 if necessary. Tag type{ 0 }; }; IStreamBase & operator>>( IStreamBase & stream, GroupChunkHeader & st ) { st.ID = static_cast( stream.getBE32() ); st.length = stream.getBE32(); st.type = static_cast( stream.getBE32() ); return stream; } struct VectorSubrange { std::vector::const_iterator data; const std::vector::const_iterator dataEnd; }; struct XMIData { VectorSubrange trackEvents; bool isValid{ false }; explicit XMIData( const std::vector & buf ) : trackEvents{ buf.cend(), buf.cend() } { // Please refer to https://moddingwiki.shikadi.net/wiki/XMI_Format#File_format ROStreamBuf sb( buf ); GroupChunkHeader group; sb >> group; if ( group.ID != Tag::FORM || group.type != Tag::XDIR ) { ERROR_LOG( "XMI parse error: invalid IFF root chunk 1 (FORM:XDIR)" ) return; } IFFChunkHeader iff; sb >> iff; if ( iff.ID != Tag::INFO || iff.length != 2 ) { ERROR_LOG( "XMI parse error: invalid TAG_INFO" ) return; } if ( const uint16_t numTracks = sb.getLE16(); numTracks != 1 ) { ERROR_LOG( "XMI parse error: the number of sequences should be 1 to be properly converted to MID format 0" ) return; } // CAT XMID sb >> group; if ( group.ID != Tag::CAT0 || group.type != Tag::XMID ) { ERROR_LOG( "XMI parse error: invalid IFF root chunk 2 (CAT:XMID)" ) return; } // FORM XMID sb >> group; if ( group.ID != Tag::FORM || group.type != Tag::XMID ) { ERROR_LOG( "XMI parse error: invalid form type (FORM:XMID)" ) return; } sb >> iff; // TIMB is not used in MIDI files. if ( iff.ID == Tag::TIMB ) { sb.skip( iff.length ); sb >> iff; } // [RBRN] if ( iff.ID == Tag::RBRN ) { sb.skip( iff.length ); sb >> iff; } // EVNT chunk if ( iff.ID != Tag::EVNT ) { ERROR_LOG( "XMI parse error: ID is not EVNT" ) return; } if ( sb.fail() ) { ERROR_LOG( "XMI parse error: I/O error" ) return; } // The single track XMI files does not have any data after the EVNT data. if ( sb.size() != iff.length ) { ERROR_LOG( "XMI parse error: EVNT data is out of range" ) return; } // Mark the beginning of the EVNT data. trackEvents.data = buf.cbegin() + static_cast( sb.tell() ); assert( trackEvents.dataEnd - trackEvents.data == static_cast( iff.length ) ); isValid = ( trackEvents.data != trackEvents.dataEnd ); } }; // codechecker_false_positive [core.uninitialized.Assign] Value assigned to field '_time' in implicit constructor is garbage or undefined struct MidiChunk { uint32_t _time{ 0 }; uint8_t _type{ 0 }; // _binaryTime is calculated only after all chunks are pushed and sorted. std::vector _binaryTime; std::vector _data; MidiChunk( const uint32_t time, const uint8_t type, const uint8_t data1 ) : _time( time ) , _type( type ) , _data( { data1 } ) { // Do nothing. } MidiChunk( const uint32_t time, const uint8_t type, const uint8_t data1, const uint8_t data2 ) : _time( time ) , _type( type ) , _data( { data1, data2 } ) { // Do nothing. } MidiChunk( const uint32_t time, const uint8_t meta, const uint8_t subType, const std::vector::const_iterator iter, const uint8_t metaLength ) : _time( time ) , _type( meta ) { _data.reserve( static_cast( 2 ) + metaLength ); _data.push_back( subType ); _data.push_back( metaLength ); for ( uint8_t i = 0; i < metaLength; ++i ) { _data.push_back( *( iter + i ) ); } } // Returns the size in bytes that this structure will occupy in serialized binary form inside a MIDI file size_t sizeInBytes() const { return _binaryTime.size() + sizeof( _type ) + _data.size(); } }; bool operator<( const MidiChunk & left, const MidiChunk & right ) { return left._time < right._time; } OStreamBase & operator<<( OStreamBase & stream, const MidiChunk & event ) { for ( const uint8_t binaryTimeByte : event._binaryTime ) { stream << binaryTimeByte; } stream << event._type; for ( const uint8_t dataByte : event._data ) { stream << dataByte; } return stream; } struct MidiEvents final : public std::vector { uint32_t trackTempo{ 0 }; MidiEvents() = default; explicit MidiEvents( const VectorSubrange & trackEvents ) { assert( trackEvents.data != trackEvents.dataEnd ); std::vector::const_iterator iter = trackEvents.data; auto checkDataPresence = [this, &trackEvents, &iter]( const int32_t requiredLength ) { assert( requiredLength > 0 ); if ( trackEvents.dataEnd - iter < requiredLength ) { emplace_back( 0, static_cast( 0xFF ), static_cast( 0x2F ), static_cast( 0x00 ) ); ERROR_LOG( "MIDI track: the data is truncated" ) return false; } return true; }; uint32_t time = 0; while ( iter < trackEvents.dataEnd ) { // XMI delay is 7 bit values summed together if ( *iter < 128 ) { time += *iter; ++iter; continue; } if ( *iter == 0xFF ) { if ( !checkDataPresence( 3 ) ) { break; } // Meta-Event, always starts from 0xFF. We skip it. ++iter; if ( *iter == 0x2F ) { if ( *( ++iter ) != 0x00 ) { ERROR_LOG( "MIDI track: End of Track sequence is incorrect" ) } emplace_back( time, static_cast( 0xFF ), static_cast( 0x2F ), static_cast( 0x00 ) ); break; } const uint8_t metaType = *( iter++ ); const uint8_t metaLength = *( iter++ ); if ( !checkDataPresence( metaLength ) ) { break; } emplace_back( time, static_cast( 0xFF ), metaType, iter, metaLength ); // Tempo switch if ( metaType == 0x51 && metaLength == 3 ) { // 24-bit big endian trackTempo = ( ( ( *iter << 8 ) | *( iter + 1 ) ) << 8 ) | *( iter + 2 ); } iter += metaLength; continue; } switch ( *iter >> 4 ) { // Polyphonic Key Pressure (Aftertouch). case 0x0A: // Control Change. case 0x0B: // Pitch Wheel Change. case 0x0E: if ( !checkDataPresence( 3 ) ) { break; } emplace_back( time, *iter, *( iter + 1 ), *( iter + 2 ) ); iter += 3; break; // XMI events do not have note off events. // Note On event. case 0x09: { if ( !checkDataPresence( 4 ) ) { break; } emplace_back( time, *iter, *( iter + 1 ), *( iter + 2 ) ); VariableLengthQuantity quantity; if ( !readVariableLengthQuantity( iter + 3, trackEvents.dataEnd, quantity ) ) { break; } // note off emplace_back( time + quantity.value, static_cast( *iter - 0x10 ), *( iter + 1 ), static_cast( 0x7F ) ); iter += 3 + quantity.lengthInBytes; break; } // Program Change: in other words which instrument is going to be played. case 0x0C: { if ( !checkDataPresence( 2 ) ) { break; } emplace_back( time, *iter, *( iter + 1 ) ); #ifdef WITH_DEBUG const int32_t channelId = *iter - 0xC0; // Drum sounds are only played in channel 9 if channel ID starts from 0, or 10 if channel ID starts from 1. In our case it starts from 0. if ( channelId == 9 ) { // It is a drum kit. const uint32_t drumKitId = *( iter + 1 ); const auto drumKitIter = drumKitDescription.find( drumKitId ); if ( drumKitIter != drumKitDescription.end() ) { DEBUG_LOG( DBG_ENGINE, DBG_TRACE, "MIDI channel " << channelId << ", drum kit ID " << drumKitId << ": " << drumKitIter->second ) } else { ERROR_LOG( "MIDI channel " << channelId << ": unknown drum kit ID " << drumKitId ) } } else { const uint32_t instrumentId = *( iter + 1 ); if ( instrumentId < instrumentDescription.size() ) { DEBUG_LOG( DBG_ENGINE, DBG_TRACE, "MIDI channel " << channelId << ", instrument ID " << instrumentId << ": " << instrumentDescription[instrumentId] ) } else { ERROR_LOG( "MIDI channel " << channelId << ": unknown instrument ID " << instrumentId ) } } #endif iter += 2; break; } // Channel Pressure (After-touch). case 0x0D: if ( !checkDataPresence( 2 ) ) { break; } emplace_back( time, *iter, *( iter + 1 ) ); iter += 2; break; // Unknown command. default: emplace_back( 0, static_cast( 0xFF ), static_cast( 0x2F ), static_cast( 0x00 ) ); ERROR_LOG( "MIDI track: unknown command: " << GetHexString( static_cast( *iter ), 2 ) << ", byte: " << static_cast( iter - trackEvents.data ) ) break; } } std::stable_sort( begin(), end() ); // Set binary time according to the sorted chunks order. time = 0; for ( MidiChunk & chunk : *this ) { chunk._binaryTime = packVariableLengthQuantity( chunk._time - time ); time = chunk._time; } } // Returns the size in bytes that this structure will occupy in serialized binary form inside a MIDI file size_t sizeInBytes() const { return std::accumulate( begin(), end(), static_cast( 0 ), []( const size_t total, const MidiChunk & chunk ) { return total + chunk.sizeInBytes(); } ); } }; OStreamBase & operator<<( OStreamBase & stream, const MidiEvents & st ) { for ( const MidiChunk & chunk : st ) { stream << chunk; } return stream; } struct MidTrack { MidiEvents events; IFFChunkHeader mtrk{ Tag::MTRK, 0 }; explicit MidTrack( const VectorSubrange & trackEvents ) : events( trackEvents ) , mtrk( Tag::MTRK, static_cast( events.sizeInBytes() ) ) { // Do nothing. } }; OStreamBase & operator<<( OStreamBase & stream, const MidTrack & st ) { stream << st.mtrk; stream << st.events; return stream; } struct MidData { IFFChunkHeader mthd{ Tag::MTHD, 6 }; uint16_t format{ 0 }; uint16_t ppqn{ 60 }; // MIDI format 0 can contain only one track. MidTrack track; explicit MidData( const VectorSubrange & trackEvents ) : track( trackEvents ) { // XMI files play MIDI at a fixed clock rate of 120 Hz if ( track.events.trackTempo > 0 ) { ppqn = static_cast( track.events.trackTempo * 3 / 25000 ); } } // Returns the size in bytes that this structure will occupy in serialized binary form inside a MIDI file size_t sizeInBytes() const { // The total MIDI data size is: MThd header and data length plus MTrk header and data length. return mthd.sizeInBytes() + mthd.length + track.mtrk.sizeInBytes() + track.mtrk.length; } }; OStreamBase & operator<<( OStreamBase & stream, const MidData & st ) { stream << st.mthd; stream.putBE16( st.format ); // Write that there is one track in midi file. stream.putBE16( static_cast( 1 ) ); stream.putBE16( st.ppqn ); stream << st.track; return stream; } } std::vector Music::Xmi2Mid( const std::vector & buf ) { const XMIData xmi( buf ); if ( !xmi.isValid ) { return {}; } const MidData mid( xmi.trackEvents ); // Create a buffer for the midi data. RWStreamBuf sb( mid.sizeInBytes() ); sb << mid; if ( sb.fail() ) { ERROR_LOG( "Error writing MIDI data to the buffer: I/O error" ); return {}; } return { sb.data(), sb.data() + sb.size() }; } fheroes2-1.1.6+dfsg/src/engine/core.cpp000066400000000000000000000135111476115357100176560ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "core.h" #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wswitch-default" #endif #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif #include "audio.h" #include "localevent.h" #include "logging.h" #if defined( TARGET_PS_VITA ) #include #include // PlayStation Vita requires definition of such global variable for memory usage. int _newlib_heap_size_user = 192 * 1024 * 1024; #endif namespace { #if defined( TARGET_PS_VITA ) void initHardwareInternally() { // CPU clock speed, MHz. Possible values: 41, 83, 111, 166, 222, 333, 444, 500 scePowerSetArmClockFrequency( 444 ); // CPU memory clock speed, MHz. Possible values: 55, 83, 111, 166, 222 scePowerSetBusClockFrequency( 222 ); // GPU clock speed, MHz. Possible values: 41, 55, 83, 111, 166, 222 scePowerSetGpuClockFrequency( 222 ); // GPU memory clock speed, MHz. Possible values: 83, 111, 166 scePowerSetGpuXbarClockFrequency( 166 ); } void freeHardwareInternally() { sceKernelExitProcess( 0 ); } #else void initHardwareInternally() { // Do nothing. } void freeHardwareInternally() { // Do nothing. } #endif uint32_t convertToSDLFlag( const fheroes2::SystemInitializationComponent component ) { switch ( component ) { case fheroes2::SystemInitializationComponent::Audio: return SDL_INIT_AUDIO; case fheroes2::SystemInitializationComponent::Video: return SDL_INIT_VIDEO; case fheroes2::SystemInitializationComponent::GameController: return SDL_INIT_GAMECONTROLLER; default: // Did you add a new component? assert( 0 ); break; } return 0; } uint32_t getSDLInitFlags( const std::set & components ) { uint32_t flags = 0; for ( const fheroes2::SystemInitializationComponent component : components ) { flags |= convertToSDLFlag( component ); } return flags; } // For now only SDL library is supported. bool initCoreInternally( const std::set & components ) { const uint32_t sdlFlags = getSDLInitFlags( components ); if ( SDL_Init( sdlFlags ) < 0 ) { ERROR_LOG( SDL_GetError() ) return false; } if ( components.count( fheroes2::SystemInitializationComponent::Audio ) > 0 ) { Audio::Init(); } if ( components.count( fheroes2::SystemInitializationComponent::GameController ) > 0 ) { LocalEvent::Get().initController(); } LocalEvent::initEventEngine(); return true; } void freeCoreInternally() { if ( fheroes2::isComponentInitialized( fheroes2::SystemInitializationComponent::GameController ) ) { LocalEvent::Get().CloseController(); } if ( fheroes2::isComponentInitialized( fheroes2::SystemInitializationComponent::Audio ) ) { Audio::Quit(); } SDL_Quit(); } bool isComponentInitializedInternally( const fheroes2::SystemInitializationComponent component ) { const uint32_t sdlFlag = convertToSDLFlag( component ); assert( sdlFlag != 0 ); return SDL_WasInit( sdlFlag ) != 0; } } namespace fheroes2 { HardwareInitializer::HardwareInitializer() { initHardwareInternally(); } HardwareInitializer::~HardwareInitializer() { freeHardwareInternally(); } CoreInitializer::CoreInitializer( const std::set & components ) { if ( !initCoreInternally( components ) ) { throw std::logic_error( "Core module initialization failed." ); } } CoreInitializer::~CoreInitializer() { freeCoreInternally(); } bool isComponentInitialized( const SystemInitializationComponent component ) { return isComponentInitializedInternally( component ); } } fheroes2-1.1.6+dfsg/src/engine/core.h000066400000000000000000000043731476115357100173310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace fheroes2 { enum class SystemInitializationComponent : int { Audio, Video, GameController }; class HardwareInitializer { public: HardwareInitializer(); HardwareInitializer( const HardwareInitializer & ) = delete; HardwareInitializer & operator=( const HardwareInitializer & ) = delete; ~HardwareInitializer(); }; class CoreInitializer { public: explicit CoreInitializer( const std::set & components ); CoreInitializer( const CoreInitializer & ) = delete; CoreInitializer & operator=( const CoreInitializer & ) = delete; ~CoreInitializer(); }; bool isComponentInitialized( const SystemInitializationComponent component ); } fheroes2-1.1.6+dfsg/src/engine/dir.cpp000066400000000000000000000142021476115357100175020ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dir.h" #include #if defined( TARGET_PS_VITA ) #include #else #include #include #endif #if defined( _WIN32 ) #include #else #include #endif #include "system.h" namespace { template bool nameFilter( const std::string & filename, const bool needExactMatch, const std::string & filter, const F & strCmp ) { if ( !needExactMatch && filter.empty() ) { return true; } if ( filename.length() < filter.length() ) { return false; } if ( needExactMatch && filename.length() != filter.length() ) { return false; } const char * filenamePtr = filename.c_str() + filename.length() - filter.length(); return ( strCmp( filenamePtr, filter.c_str() ) == 0 ); } void getFilesFromDirectory( const std::string & path, const std::string & filter, const bool needExactMatch, ListFiles & files ) { std::string correctedPath; if ( !System::GetCaseInsensitivePath( path, correctedPath ) ) { return; } #if defined( _WIN32 ) auto * const strCmp = _stricmp; #else auto * const strCmp = strcasecmp; #endif #if defined( TARGET_PS_VITA ) // On PS Vita, getting a list of files using std::filesystem for some reason works much slower than using the native file system API class SceUIDWrapper { public: SceUIDWrapper( const std::string & path ) : uid( sceIoDopen( path.c_str() ) ) {} SceUIDWrapper( const SceUIDWrapper & ) = delete; ~SceUIDWrapper() { if ( !isValid() ) { return; } sceIoDclose( uid ); } SceUIDWrapper & operator=( const SceUIDWrapper & ) = delete; bool isValid() const { return uid >= 0; } SceUID get() const { return uid; } private: const SceUID uid; }; const SceUIDWrapper uid( path ); if ( !uid.isValid() ) { return; } SceIoDirent entry; while ( sceIoDread( uid.get(), &entry ) > 0 ) { // Ensure that this directory entry is a regular file if ( !SCE_S_ISREG( entry.d_stat.st_mode ) ) { continue; } if ( !nameFilter( entry.d_name, needExactMatch, filter, strCmp ) ) { continue; } files.emplace_back( System::concatPath( path, entry.d_name ) ); } #else std::error_code ec; // Using the non-throwing overload for ( const std::filesystem::directory_entry & entry : std::filesystem::directory_iterator( correctedPath, ec ) ) { // Using the non-throwing overload if ( !entry.is_regular_file( ec ) ) { continue; } const std::filesystem::path & entryPath = entry.path(); if ( !nameFilter( System::fsPathToString( entryPath.filename() ), needExactMatch, filter, strCmp ) ) { continue; } files.emplace_back( System::fsPathToString( entryPath ) ); } #endif } } void ListFiles::Append( ListFiles && files ) { for ( std::string & file : files ) { emplace_back( std::move( file ) ); } } void ListFiles::ReadDir( const std::string & path, const std::string & filter ) { getFilesFromDirectory( path, filter, false, *this ); } void ListFiles::FindFileInDir( const std::string_view path, const std::string_view fileName ) { std::string correctedFilePath; // If the file system is case-sensitive, then here we will get the actual file path using the case-insensitive // search (if such a file exists). If the file system is case-insensitive, we will just get the passed path to // the file back intact. if ( !System::GetCaseInsensitivePath( System::concatPath( path, fileName ), correctedFilePath ) ) { return; } // In case the file system is case-insensitive, we additionally check the file for existence. if ( !System::IsFile( correctedFilePath ) ) { return; } emplace_back( std::move( correctedFilePath ) ); } bool ListFiles::IsEmpty( const std::string & path, const std::string & filter ) { ListFiles list; list.ReadDir( path, filter ); return list.empty(); } fheroes2-1.1.6+dfsg/src/engine/dir.h000066400000000000000000000046371476115357100171620ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include struct ListFiles : public std::list { void Append( ListFiles && files ); // Adds files from the 'path' directory ending in 'filter' to the list, case-insensitive. void ReadDir( const std::string & path, const std::string & filter ); // Adds the first found file from the 'path' directory with a name matching 'fileName' to the list, case-insensitive. void FindFileInDir( const std::string_view path, const std::string_view fileName ); // Returns true if there are no files in the 'path' directory with names ending in 'filter', case-insensitive, otherwise returns false. static bool IsEmpty( const std::string & path, const std::string & filter ); }; fheroes2-1.1.6+dfsg/src/engine/exception.h000066400000000000000000000031471476115357100203750ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace fheroes2 { class InvalidDataResources : public std::logic_error { using std::logic_error::logic_error; }; } fheroes2-1.1.6+dfsg/src/engine/h2d_file.cpp000066400000000000000000000166021476115357100204060ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "h2d_file.h" #include #include #include #include "image.h" namespace { // 4 bytes - file identifier // 4 bytes - number of files // 4 bytes - file offset // 4 bytes - file size // 5 bytes - file name const size_t minFileSize = 4 + 4 + 4 + 4 + 5 + 1; } namespace fheroes2 { bool H2DReader::open( const std::string & path ) { _fileNameAndOffset.clear(); _fileStream.close(); if ( !_fileStream.open( path, "rb" ) ) { return false; } const size_t fileSize = _fileStream.size(); if ( fileSize < minFileSize ) { return false; } if ( _fileStream.get() != 'H' ) { return false; } if ( _fileStream.get() != '2' ) { return false; } if ( _fileStream.get() != 'D' ) { return false; } if ( _fileStream.get() != '\0' ) { return false; } const uint32_t fileCount = _fileStream.getLE32(); if ( fileCount == 0 ) { return false; } for ( uint32_t i = 0; i < fileCount; ++i ) { const uint32_t offset = _fileStream.getLE32(); const uint32_t size = _fileStream.getLE32(); std::string name; _fileStream >> name; if ( size == 0 || offset + size > fileSize || name.empty() ) { continue; } _fileNameAndOffset.try_emplace( std::move( name ), std::make_pair( offset, size ) ); } return true; } std::vector H2DReader::getFile( const std::string & fileName ) { const auto it = _fileNameAndOffset.find( fileName ); if ( it == _fileNameAndOffset.end() ) { return std::vector(); } _fileStream.seek( it->second.first ); return _fileStream.getRaw( it->second.second ); } std::set> H2DReader::getAllFileNames() const { std::set> names; for ( const auto & value : _fileNameAndOffset ) { names.insert( value.first ); } return names; } bool H2DWriter::write( const std::string & path ) const { if ( _fileData.empty() ) { // Nothing to write. return false; } StreamFile fileStream; if ( !fileStream.open( path, "wb" ) ) { return false; } fileStream.put( 'H' ); fileStream.put( '2' ); fileStream.put( 'D' ); fileStream.put( '\0' ); fileStream.putLE32( static_cast( _fileData.size() ) ); // Calculate file info section size. size_t fileInfoSection = ( 4 + 4 ) * _fileData.size(); for ( const auto & data : _fileData ) { // 4 byte for string size. fileInfoSection += ( data.first.size() + 4 ); } size_t offset = fileInfoSection + 4 + 4; for ( const auto & data : _fileData ) { fileStream.putLE32( static_cast( offset ) ); fileStream.putLE32( static_cast( data.second.size() ) ); fileStream << data.first; offset += data.second.size(); } for ( const auto & data : _fileData ) { fileStream.putRaw( data.second.data(), data.second.size() ); } return true; } bool H2DWriter::add( const std::string & name, const std::vector & data ) { if ( name.empty() || data.empty() ) { return false; } _fileData[name] = data; return true; } bool H2DWriter::add( H2DReader & reader ) { const std::set> names = reader.getAllFileNames(); for ( const std::string & name : names ) { if ( !add( name, reader.getFile( name ) ) ) { return false; } } return true; } bool readImageFromH2D( H2DReader & reader, const std::string & name, Sprite & image ) { // TODO: Store in h2d images the 'isSingleLayer' state to disable and skip transform layer for such images. assert( !image.singleLayer() ); const std::vector & data = reader.getFile( name ); if ( data.size() < 4 + 4 + 4 + 4 + 1 ) { // Empty or invalid image. return false; } ROStreamBuf stream( data ); const int32_t width = static_cast( stream.getLE32() ); const int32_t height = static_cast( stream.getLE32() ); const int32_t x = static_cast( stream.getLE32() ); const int32_t y = static_cast( stream.getLE32() ); if ( static_cast( width * height * 2 + 4 + 4 + 4 + 4 ) != data.size() ) { return false; } const size_t size = static_cast( width * height ); image.resize( width, height ); memcpy( image.image(), data.data() + 4 + 4 + 4 + 4, size ); memcpy( image.transform(), data.data() + 4 + 4 + 4 + 4 + size, size ); image.setPosition( x, y ); return true; } bool writeImageToH2D( H2DWriter & writer, const std::string & name, const Sprite & image ) { // TODO: Store in h2d images the 'isSingleLayer' state to disable and skip transform layer for such images. assert( !image.empty() && !image.singleLayer() ); RWStreamBuf stream; stream.putLE32( static_cast( image.width() ) ); stream.putLE32( static_cast( image.height() ) ); stream.putLE32( static_cast( image.x() ) ); stream.putLE32( static_cast( image.y() ) ); const size_t imageSize = static_cast( image.width() ) * static_cast( image.height() ); stream.putRaw( image.image(), imageSize ); stream.putRaw( image.transform(), imageSize ); return writer.add( name, stream.getRaw( 0 ) ); } } fheroes2-1.1.6+dfsg/src/engine/h2d_file.h000066400000000000000000000061471476115357100200560ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include "serialize.h" namespace fheroes2 { class Sprite; // Heroes 2 Data (H2D) file format used for storing files needed for the project. This format is not a part of original HoMM II. class H2DReader { public: // Returns true if file opening is successful. bool open( const std::string & path ); // Returns non-empty vector if requested file exists. std::vector getFile( const std::string & fileName ); std::set> getAllFileNames() const; private: // Relationship between file name in non-capital letters and its offset from the start of the archive. std::map, std::less<>> _fileNameAndOffset; // Stream for reading h2d file. StreamFile _fileStream; }; // This class is not designed to be performance optimized as it will be used very rarely and out of game running session. class H2DWriter { public: // Returns true if file opening is successful. bool write( const std::string & path ) const; bool add( const std::string & name, const std::vector & data ); // Add all entries from a H2D reader. bool add( H2DReader & reader ); private: std::map, std::less<>> _fileData; }; bool readImageFromH2D( H2DReader & reader, const std::string & name, Sprite & image ); bool writeImageToH2D( H2DWriter & writer, const std::string & name, const Sprite & image ); } fheroes2-1.1.6+dfsg/src/engine/image.cpp000066400000000000000000004252341476115357100200210ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "image.h" #include #include #include #include #include #include #include "image_palette.h" namespace { // 0 in shadow part means no shadow, 1 means skip any drawings so to don't waste extra CPU cycles for ( tableId - 2 ) command we just add extra fake tables // Mirror palette was modified as it was containing 238, 238, 239, 240 values instead of 238, 239, 240, 241 const uint8_t transformTable[256 * 16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 62, 62, 62, 62, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 84, 84, 84, 84, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 107, 107, 107, 107, 107, 107, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 130, 130, 130, 130, 130, 130, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 151, 151, 151, 151, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 174, 174, 174, 174, 174, 174, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 197, 197, 197, 197, 197, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 213, 213, 213, 213, 214, 215, 216, 217, 218, 219, 220, 221, 225, 226, 227, 228, 229, 230, 230, 230, 230, 73, 75, 77, 79, 81, 76, 78, 74, 76, 78, 80, 244, 245, 245, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // First 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 62, 62, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 84, 84, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 107, 107, 107, 107, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 130, 130, 130, 130, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 151, 151, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 174, 174, 174, 174, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 197, 197, 197, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 213, 213, 213, 214, 215, 216, 217, 218, 219, 220, 221, 224, 225, 226, 227, 228, 229, 230, 230, 230, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 78, 244, 245, 245, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Second 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 84, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 107, 107, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 130, 130, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 151, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 174, 174, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 197, 197, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 213, 213, 214, 215, 216, 217, 218, 219, 220, 221, 223, 224, 225, 226, 227, 228, 229, 230, 230, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 243, 244, 245, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Third 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 107, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 130, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 174, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 197, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 213, 214, 215, 216, 217, 218, 219, 220, 221, 223, 224, 225, 226, 227, 228, 229, 230, 230, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 243, 244, 245, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Fourth 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 11, 11, 11, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 17, 17, 17, 18, 18, 19, 19, 20, 20, 20, 21, 21, 11, 37, 37, 37, 38, 38, 39, 39, 39, 40, 40, 41, 41, 41, 41, 42, 42, 19, 42, 20, 20, 20, 20, 20, 20, 21, 12, 131, 63, 63, 63, 64, 64, 64, 65, 65, 65, 65, 65, 242, 242, 242, 242, 242, 242, 242, 242, 242, 13, 14, 15, 15, 16, 85, 17, 85, 85, 85, 85, 19, 86, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 10, 108, 108, 109, 109, 109, 110, 110, 110, 110, 199, 40, 41, 41, 41, 41, 41, 42, 42, 42, 42, 20, 20, 11, 11, 131, 131, 132, 132, 132, 133, 133, 134, 134, 134, 135, 135, 18, 136, 19, 19, 20, 20, 20, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 15, 15, 15, 16, 17, 17, 17, 18, 18, 19, 19, 20, 20, 11, 175, 175, 176, 176, 38, 177, 177, 178, 178, 178, 179, 179, 179, 179, 180, 180, 180, 180, 180, 180, 21, 21, 108, 108, 38, 109, 38, 109, 39, 40, 40, 41, 41, 41, 42, 42, 42, 20, 199, 179, 180, 180, 110, 110, 40, 42, 110, 110, 86, 86, 86, 86, 18, 18, 19, 65, 65, 65, 66, 65, 66, 65, 152, 155, 65, 242, 15, 16, 17, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Fifth 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 37, 37, 38, 38, 39, 39, 40, 41, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 23, 24, 24, 24, 24, 24, 131, 63, 63, 64, 64, 65, 65, 66, 66, 242, 67, 67, 68, 68, 243, 243, 243, 243, 243, 243, 243, 243, 15, 15, 85, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 88, 89, 24, 90, 25, 25, 25, 25, 25, 25, 37, 108, 109, 109, 110, 110, 111, 111, 200, 200, 201, 201, 42, 43, 43, 44, 44, 44, 45, 45, 46, 46, 46, 11, 131, 132, 132, 132, 133, 133, 134, 135, 135, 136, 242, 137, 137, 138, 243, 243, 243, 243, 243, 24, 152, 152, 153, 153, 154, 154, 155, 156, 156, 157, 158, 158, 159, 18, 19, 19, 20, 20, 21, 22, 22, 23, 24, 37, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 46, 47, 47, 48, 25, 108, 109, 109, 109, 198, 199, 199, 201, 201, 42, 43, 43, 44, 45, 46, 46, 201, 181, 182, 183, 111, 111, 202, 45, 111, 111, 87, 88, 88, 88, 88, 21, 22, 66, 66, 68, 68, 67, 68, 68, 152, 157, 66, 69, 16, 18, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Sixth 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 11, 12, 13, 14, 14, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 23, 24, 24, 25, 26, 26, 27, 28, 29, 29, 37, 37, 38, 39, 40, 40, 41, 42, 42, 43, 44, 44, 45, 46, 46, 47, 47, 48, 48, 49, 50, 50, 27, 28, 28, 28, 63, 63, 64, 65, 65, 66, 67, 67, 68, 69, 69, 69, 70, 70, 70, 244, 71, 244, 244, 244, 244, 245, 16, 85, 85, 86, 87, 87, 88, 88, 89, 90, 90, 91, 91, 91, 92, 93, 93, 93, 29, 29, 29, 29, 29, 37, 109, 109, 110, 111, 111, 112, 113, 112, 112, 203, 203, 203, 44, 45, 46, 47, 47, 47, 48, 48, 49, 50, 131, 131, 132, 133, 133, 134, 135, 136, 136, 137, 137, 139, 139, 139, 141, 141, 141, 143, 143, 245, 245, 152, 152, 153, 154, 155, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, 163, 164, 165, 165, 166, 26, 26, 27, 175, 13, 176, 177, 178, 178, 179, 180, 181, 181, 182, 182, 183, 183, 183, 184, 184, 185, 185, 50, 50, 52, 52, 109, 109, 198, 199, 200, 201, 201, 202, 202, 44, 45, 46, 47, 48, 48, 49, 204, 205, 185, 185, 112, 112, 204, 47, 112, 113, 88, 89, 91, 92, 93, 93, 25, 66, 68, 69, 69, 68, 69, 69, 153, 159, 68, 71, 18, 242, 243, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Seventh 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 13, 14, 15, 16, 17, 17, 19, 19, 20, 21, 22, 23, 24, 24, 26, 26, 27, 28, 28, 30, 30, 31, 32, 37, 38, 39, 39, 40, 41, 42, 43, 43, 44, 45, 46, 46, 47, 48, 49, 50, 50, 51, 52, 52, 53, 54, 54, 30, 31, 63, 64, 64, 65, 66, 67, 68, 69, 69, 70, 71, 71, 71, 72, 72, 72, 73, 73, 73, 168, 168, 168, 85, 85, 86, 87, 88, 88, 89, 90, 91, 91, 92, 93, 93, 94, 95, 95, 96, 96, 96, 31, 32, 32, 32, 108, 109, 198, 110, 111, 112, 113, 113, 113, 116, 117, 118, 119, 120, 121, 47, 48, 50, 50, 51, 51, 52, 52, 131, 132, 132, 133, 134, 135, 136, 137, 137, 138, 139, 140, 141, 141, 143, 143, 144, 145, 146, 147, 30, 152, 153, 153, 154, 155, 156, 157, 158, 158, 159, 160, 161, 162, 163, 164, 165, 165, 166, 167, 168, 169, 28, 29, 175, 176, 177, 177, 178, 179, 180, 181, 182, 182, 183, 184, 185, 185, 185, 186, 186, 187, 50, 52, 52, 54, 55, 109, 198, 199, 200, 201, 202, 202, 204, 204, 205, 207, 47, 49, 50, 51, 52, 206, 206, 187, 188, 113, 113, 118, 49, 222, 222, 223, 224, 225, 226, 95, 227, 228, 67, 68, 70, 71, 69, 71, 70, 153, 65, 69, 73, 242, 22, 243, 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Eighth 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 11, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 242, 242, 22, 22, 23, 243, 243, 25, 244, 244, 244, 11, 37, 38, 38, 39, 40, 40, 41, 178, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 22, 23, 23, 23, 23, 24, 244, 63, 63, 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 70, 70, 70, 15, 15, 16, 85, 86, 18, 19, 19, 20, 159, 21, 21, 161, 22, 163, 163, 163, 23, 23, 165, 165, 244, 244, 37, 108, 38, 109, 109, 110, 199, 200, 199, 40, 41, 42, 42, 42, 43, 43, 44, 22, 22, 23, 23, 23, 23, 131, 131, 132, 132, 133, 133, 134, 134, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 141, 244, 152, 152, 153, 153, 154, 154, 155, 155, 156, 156, 157, 158, 158, 159, 242, 159, 161, 161, 243, 243, 243, 243, 164, 11, 175, 176, 176, 177, 177, 178, 179, 179, 180, 180, 181, 181, 182, 182, 182, 182, 183, 22, 23, 23, 23, 23, 108, 38, 38, 39, 39, 40, 40, 41, 178, 180, 42, 44, 45, 23, 23, 23, 180, 181, 181, 183, 110, 200, 42, 45, 85, 86, 87, 87, 87, 21, 22, 22, 23, 66, 66, 67, 68, 67, 68, 68, 153, 158, 67, 70, 64, 65, 242, 243, 159, 159, 159, 159, 159, 159, 159, 159, 159, 10, // Ninth 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 11, 12, 13, 14, 14, 15, 16, 16, 17, 18, 19, 19, 20, 242, 22, 22, 243, 243, 243, 244, 244, 244, 244, 245, 245, 37, 37, 38, 176, 39, 177, 41, 41, 42, 179, 20, 180, 45, 22, 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 63, 63, 64, 64, 65, 66, 67, 67, 68, 68, 69, 69, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 15, 85, 85, 86, 86, 87, 20, 88, 89, 22, 161, 162, 163, 163, 164, 164, 165, 165, 166, 166, 167, 167, 167, 37, 108, 109, 109, 110, 199, 111, 111, 200, 201, 41, 43, 43, 43, 44, 44, 46, 46, 24, 24, 25, 25, 25, 131, 131, 132, 132, 133, 134, 135, 135, 136, 136, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 143, 152, 152, 153, 153, 154, 155, 155, 156, 156, 157, 158, 158, 159, 159, 161, 161, 162, 162, 163, 164, 244, 244, 244, 175, 175, 176, 177, 177, 178, 179, 179, 180, 181, 181, 182, 182, 183, 183, 183, 184, 184, 184, 25, 25, 25, 25, 108, 109, 109, 39, 40, 41, 41, 42, 42, 43, 43, 45, 46, 47, 25, 25, 181, 182, 183, 185, 111, 111, 42, 46, 111, 87, 88, 88, 88, 22, 23, 24, 25, 66, 67, 68, 69, 68, 69, 69, 153, 0, 68, 71, 65, 242, 242, 243, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, // Tenth 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 11, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21, 21, 22, 23, 243, 25, 244, 244, 244, 28, 245, 245, 245, 31, 37, 38, 38, 39, 40, 41, 41, 42, 42, 180, 45, 46, 46, 47, 47, 25, 26, 26, 26, 26, 27, 27, 27, 27, 27, 245, 63, 63, 64, 65, 66, 66, 67, 68, 69, 69, 70, 70, 71, 71, 72, 72, 72, 72, 72, 73, 73, 73, 16, 85, 85, 86, 87, 88, 88, 90, 90, 91, 91, 163, 164, 164, 165, 166, 166, 167, 167, 168, 169, 169, 170, 37, 108, 109, 198, 199, 111, 112, 112, 201, 202, 202, 43, 44, 45, 45, 46, 46, 47, 48, 26, 27, 27, 27, 131, 131, 132, 133, 134, 135, 135, 136, 137, 137, 138, 139, 139, 140, 141, 141, 142, 143, 143, 144, 145, 152, 152, 153, 154, 155, 155, 156, 156, 158, 158, 159, 160, 160, 161, 162, 163, 164, 164, 165, 166, 166, 167, 167, 175, 176, 176, 177, 178, 178, 179, 180, 181, 182, 182, 183, 184, 184, 184, 185, 186, 186, 50, 51, 27, 27, 27, 109, 109, 109, 40, 40, 41, 42, 43, 43, 44, 45, 46, 47, 49, 27, 27, 182, 183, 184, 187, 112, 112, 43, 47, 112, 87, 89, 90, 91, 91, 24, 26, 26, 67, 68, 69, 70, 69, 70, 70, 153, 0, 0, 73, 65, 242, 243, 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, // Eleventh 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 23, 243, 24, 25, 244, 244, 27, 245, 245, 31, 170, 149, 149, 37, 38, 38, 39, 40, 41, 42, 42, 44, 45, 46, 46, 47, 48, 49, 50, 51, 28, 28, 28, 29, 29, 29, 29, 29, 30, 63, 64, 65, 65, 66, 67, 68, 69, 70, 70, 71, 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 76, 85, 85, 86, 87, 88, 89, 90, 91, 91, 92, 93, 93, 166, 166, 96, 168, 168, 169, 170, 170, 171, 171, 171, 37, 109, 109, 110, 200, 111, 112, 113, 202, 202, 203, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 29, 29, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 139, 140, 141, 142, 142, 144, 144, 145, 145, 146, 147, 152, 153, 153, 154, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 164, 164, 165, 166, 167, 168, 168, 168, 169, 175, 176, 177, 177, 178, 179, 180, 181, 182, 182, 183, 184, 185, 186, 186, 187, 187, 189, 189, 193, 193, 146, 146, 109, 109, 198, 199, 201, 201, 201, 44, 205, 45, 46, 47, 48, 50, 52, 29, 183, 185, 186, 189, 112, 112, 205, 49, 222, 88, 89, 91, 92, 93, 26, 27, 28, 67, 68, 70, 71, 69, 71, 71, 154, 0, 0, 75, 242, 242, 243, 244, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, // Twelfth 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 63, 63, 63, 63, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 85, 85, 85, 85, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 108, 108, 108, 108, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 131, 131, 131, 131, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 152, 152, 152, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 175, 175, 175, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 198, 198, 198, 198, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 242, 243, 244, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, // Mirror 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 188, 188, 188, 188, 118, 118, 118, 118, 222, 223, 224, 225, 226, 227, 228, 229, 230, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 // No cycle }; bool Validate( const fheroes2::Image & image, const int32_t x, const int32_t y, const int32_t width, const int32_t height ) { if ( image.empty() || width <= 0 || height <= 0 ) { // What's the reason to work with empty images? return false; } if ( x < 0 || y < 0 || x + width > image.width() || y + height > image.height() ) { return false; } return true; } bool Verify( const fheroes2::Image & image, int32_t & x, int32_t & y, int32_t & width, int32_t & height ) { if ( image.empty() || width <= 0 || height <= 0 ) { // What's the reason to work with empty images? return false; } const int32_t widthOut = image.width(); const int32_t heightOut = image.height(); if ( x < 0 ) { const int32_t offsetX = -x; if ( offsetX >= width ) { return false; } x = 0; width -= offsetX; } if ( y < 0 ) { const int32_t offsetY = -y; if ( offsetY >= height ) { return false; } y = 0; height -= offsetY; } if ( x > widthOut || y > heightOut ) { return false; } if ( x + width > widthOut ) { const int32_t offsetX = x + width - widthOut; if ( offsetX >= width ) { return false; } width -= offsetX; } if ( y + height > heightOut ) { const int32_t offsetY = y + height - heightOut; if ( offsetY >= height ) { return false; } height -= offsetY; } return true; } bool Verify( int32_t & inX, int32_t & inY, int32_t & outX, int32_t & outY, int32_t & width, int32_t & height, const int32_t widthIn, const int32_t heightIn, const int32_t widthOut, const int32_t heightOut ) { if ( widthIn <= 0 || heightIn <= 0 || widthOut <= 0 || heightOut <= 0 || width <= 0 || height <= 0 ) { // What's the reason to work with empty images? return false; } if ( inX < 0 || inY < 0 || inX > widthIn || inY > heightIn ) { return false; } if ( outX < 0 ) { const int32_t offsetX = -outX; if ( offsetX >= width ) { return false; } inX += offsetX; outX = 0; width -= offsetX; } if ( outY < 0 ) { const int32_t offsetY = -outY; if ( offsetY >= height ) { return false; } inY += offsetY; outY = 0; height -= offsetY; } if ( outX > widthOut || outY > heightOut ) { return false; } if ( inX + width > widthIn ) { const int32_t offsetX = inX + width - widthIn; if ( offsetX >= width ) { return false; } width -= offsetX; } if ( inY + height > heightIn ) { const int32_t offsetY = inY + height - heightIn; if ( offsetY >= height ) { return false; } height -= offsetY; } if ( outX + width > widthOut ) { const int32_t offsetX = outX + width - widthOut; if ( offsetX >= width ) { return false; } width -= offsetX; } if ( outY + height > heightOut ) { const int32_t offsetY = outY + height - heightOut; if ( offsetY >= height ) { return false; } height -= offsetY; } return true; } bool Verify( const fheroes2::Image & in, int32_t & inX, int32_t & inY, const fheroes2::Image & out, int32_t & outX, int32_t & outY, int32_t & width, int32_t & height ) { return Verify( inX, inY, outX, outY, width, height, in.width(), in.height(), out.width(), out.height() ); } uint8_t GetPALColorId( const uint8_t red, const uint8_t green, const uint8_t blue ) { static uint8_t rgbToId[64 * 64 * 64]; static bool isInitialized = false; if ( !isInitialized ) { isInitialized = true; const uint32_t size = 64 * 64 * 64; int32_t r = 0; int32_t g = 0; int32_t b = 0; const uint8_t * gamePalette = fheroes2::getGamePalette(); for ( uint32_t id = 0; id < size; ++id ) { r = static_cast( id % 64 ); g = static_cast( id >> 6 ) % 64; b = static_cast( id >> 12 ); int32_t minDistance = INT32_MAX; uint32_t bestPos = 0; // Use the "No cycle" palette. const uint8_t * correctorX = transformTable + 256 * 15; for ( uint32_t i = 0; i < 256; ++i, ++correctorX ) { const uint8_t * palette = gamePalette + static_cast( *correctorX ) * 3; const int32_t sumRed = static_cast( *palette ) + r; const int32_t offsetRed = static_cast( *palette ) - r; ++palette; const int32_t offsetGreen = static_cast( *palette ) - g; ++palette; const int32_t offsetBlue = static_cast( *palette ) - b; ++palette; // Based on "Redmean" color distance calculation (https://www.compuphase.com/cmetric.htm). const int32_t distance = ( 2 * 2 * 256 + sumRed ) * offsetRed * offsetRed + 4 * 2 * 256 * offsetGreen * offsetGreen + ( 2 * ( 2 * 256 + 255 ) - sumRed ) * offsetBlue * offsetBlue; if ( minDistance > distance ) { minDistance = distance; bestPos = *correctorX; } } rgbToId[id] = static_cast( bestPos ); // it's safe to cast } } return rgbToId[red + green * 64 + blue * 64 * 64]; } void ApplyRawPalette( const fheroes2::Image & in, int32_t inX, int32_t inY, fheroes2::Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const uint8_t * palette ) { if ( !Verify( in, inX, inY, out, outX, outY, width, height ) ) { return; } const int32_t widthIn = in.width(); const int32_t widthOut = out.width(); const uint8_t * imageInY = in.image() + static_cast( inY ) * widthIn + inX; uint8_t * imageOutY = out.image() + static_cast( outY ) * widthOut + outX; const uint8_t * imageInYEnd = imageInY + static_cast( height ) * widthIn; if ( in.singleLayer() ) { // All pixels in a single-layer image do not have any transform values so there is no need to check for them. for ( ; imageInY != imageInYEnd; imageInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageInXEnd = imageInX + width; for ( ; imageInX != imageInXEnd; ++imageInX, ++imageOutX ) { *imageOutX = palette[*imageInX]; } } } else { const uint8_t * transformInY = in.transform() + static_cast( inY ) * widthIn + inX; for ( ; imageInY != imageInYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageInXEnd = imageInX + width; for ( ; imageInX != imageInXEnd; ++imageInX, ++imageOutX, ++transformInX ) { if ( *transformInX == 0 ) { // only modify pixels with data *imageOutX = palette[*imageInX]; } } } } } } namespace fheroes2 { Image::Image( const int32_t width_, const int32_t height_ ) { Image::resize( width_, height_ ); } Image::Image( const Image & image_ ) { copy( image_ ); } Image::Image( Image && image_ ) noexcept : _data( std::move( image_._data ) ) { std::swap( _width, image_._width ); std::swap( _height, image_._height ); std::swap( _singleLayer, image_._singleLayer ); } Image & Image::operator=( const Image & image_ ) { if ( this == &image_ ) { return *this; } copy( image_ ); return *this; } Image & Image::operator=( Image && image_ ) noexcept { if ( this == &image_ ) { return *this; } std::swap( _width, image_._width ); std::swap( _height, image_._height ); std::swap( _data, image_._data ); std::swap( _singleLayer, image_._singleLayer ); return *this; } uint8_t * Image::image() { return _data.get(); } const uint8_t * Image::image() const { return _data.get(); } void Image::clear() { _data.reset(); _width = 0; _height = 0; } void Image::fill( const uint8_t value ) { if ( !empty() ) { const size_t totalSize = static_cast( _width ) * _height; memset( image(), value, totalSize ); memset( transform(), static_cast( 0 ), totalSize ); } } void Image::resize( const int32_t width_, const int32_t height_ ) { if ( width_ == _width && height_ == _height ) { return; } if ( width_ <= 0 || height_ <= 0 ) { clear(); return; } const size_t size = static_cast( width_ ) * height_ * 2; _data.reset( new uint8_t[size] ); _width = width_; _height = height_; } void Image::reset() { if ( !empty() ) { const size_t totalSize = static_cast( _width ) * _height; memset( image(), static_cast( 0 ), totalSize ); // Set the transform layer to skip all data. memset( transform(), static_cast( 1 ), totalSize ); } } void Image::copy( const Image & image ) { if ( !image._data ) { clear(); return; } const size_t size = static_cast( image._width ) * image._height * 2; _singleLayer = image._singleLayer; if ( image._width != _width || image._height != _height ) { _data.reset( new uint8_t[size] ); _width = image._width; _height = image._height; } memcpy( _data.get(), image._data.get(), size ); } Sprite::Sprite( const int32_t width_, const int32_t height_, const int32_t x_ /* = 0 */, const int32_t y_ /* = 0 */ ) : Image( width_, height_ ) , _x( x_ ) , _y( y_ ) { // Do nothing. } Sprite::Sprite( const Image & image, const int32_t x_ /* = 0 */, const int32_t y_ /* = 0 */ ) : Image( image ) , _x( x_ ) , _y( y_ ) { // Do nothing. } Sprite::Sprite( Sprite && sprite ) noexcept : Image( std::move( sprite ) ) { std::swap( _x, sprite._x ); std::swap( _y, sprite._y ); } Sprite & Sprite::operator=( const Sprite & sprite ) { if ( this == &sprite ) { return *this; } Image::operator=( sprite ); _x = sprite._x; _y = sprite._y; return *this; } Sprite & Sprite::operator=( Sprite && sprite ) noexcept { if ( this == &sprite ) { return *this; } Image::operator=( std::move( sprite ) ); std::swap( _x, sprite._x ); std::swap( _y, sprite._y ); return *this; } void Sprite::setPosition( const int32_t x_, const int32_t y_ ) { _x = x_; _y = y_; } ImageRestorer::ImageRestorer( Image & image ) : _image( image ) , _width( image.width() ) , _height( image.height() ) { _updateRoi(); if ( _image.singleLayer() ) { // The restorer is used to restore the image without the transform layer so we make a single-layer copy. _copy._disableTransformLayer(); } _copy.resize( _width, _height ); Copy( _image, 0, 0, _copy, 0, 0, _width, _height ); } ImageRestorer::ImageRestorer( Image & image, const int32_t x_, const int32_t y_, const int32_t width, const int32_t height ) : _image( image ) , _x( x_ ) , _y( y_ ) , _width( width ) , _height( height ) { _updateRoi(); if ( _image.singleLayer() ) { // The restorer is used to restore the image without the transform layer so we make a single-layer copy. _copy._disableTransformLayer(); } _copy.resize( _width, _height ); Copy( _image, _x, _y, _copy, 0, 0, _width, _height ); } ImageRestorer::~ImageRestorer() { if ( !_isRestored ) { restore(); } } void ImageRestorer::update( const int32_t x_, const int32_t y_, const int32_t width, const int32_t height ) { _isRestored = false; _x = x_; _y = y_; _width = width; _height = height; _updateRoi(); _copy.resize( _width, _height ); Copy( _image, _x, _y, _copy, 0, 0, _width, _height ); } void ImageRestorer::restore() { _isRestored = true; Copy( _copy, 0, 0, _image, _x, _y, _width, _height ); } void ImageRestorer::_updateRoi() { if ( _width < 0 ) { _width = 0; } if ( _height < 0 ) { _height = 0; } if ( _x < 0 ) { const int32_t offset = -_x; _x = 0; _width = _width < offset ? 0 : _width - offset; } if ( _y < 0 ) { const int32_t offset = -_y; _y = 0; _height = _height < offset ? 0 : _height - offset; } if ( _x >= _image.width() || _y >= _image.height() ) { _x = 0; _y = 0; _width = 0; _height = 0; return; } if ( _x + _width > _image.width() ) { const int32_t offsetX = _x + _width - _image.width(); if ( offsetX >= _width ) { _x = 0; _y = 0; _width = 0; _height = 0; return; } _width -= offsetX; } if ( _y + _height > _image.height() ) { const int32_t offsetY = _y + _height - _image.height(); if ( offsetY >= _height ) { _x = 0; _y = 0; _width = 0; _height = 0; return; } _height -= offsetY; } } void addGradientShadow( const Sprite & in, Image & out, const Point & outPos, const Point & shadowOffset ) { if ( in.empty() || out.empty() || ( shadowOffset.x == 0 && shadowOffset.y == 0 ) || ( outPos.x < 0 ) || ( outPos.y < 0 ) ) { return; } const int32_t outWidth = out.width(); const int32_t inWidth = in.width(); const int32_t inHeight = in.height(); const int32_t shadowOffsetX = std::min( shadowOffset.x, 0 ); const int32_t shadowOffsetY = std::min( shadowOffset.y, 0 ); const int32_t outStartOffset = outPos.x + shadowOffsetX + in.x() + ( outPos.y + shadowOffsetY + in.y() ) * outWidth; // The shadow should not be outside of 'out' image. assert( outStartOffset >= 0 && outWidth >= ( inWidth + outPos.x + std::max( shadowOffset.x, 0 ) ) && out.height() >= ( inHeight + outPos.y + std::max( shadowOffset.y, 0 ) ) ); const int32_t absOffsetX = std::abs( shadowOffset.x ); const int32_t absOffsetY = std::abs( shadowOffset.y ); std::vector shadowLine; shadowLine.reserve( std::max( absOffsetX, absOffsetY ) + 1 ); // Calculate shadow line from the object. if ( shadowOffset.x == 0 ) { const int32_t maxY = absOffsetY + shadowOffsetY; for ( int32_t y = shadowOffsetY; y <= maxY; ++y ) { shadowLine.emplace_back( 0, y ); } } else { const double slopeFactor = static_cast( shadowOffset.y ) / shadowOffset.x; if ( absOffsetX >= absOffsetY ) { const int32_t maxX = absOffsetX + shadowOffsetX; for ( int32_t x = shadowOffsetX; x <= maxX; ++x ) { shadowLine.emplace_back( x, static_cast( std::round( x * slopeFactor ) ) ); } } else { const int32_t maxY = absOffsetY + shadowOffsetY; for ( int32_t y = shadowOffsetY; y <= maxY; ++y ) { shadowLine.emplace_back( static_cast( std::round( y / slopeFactor ) ), y ); } } } const int32_t maxX = inWidth + absOffsetX; const int32_t maxY = inHeight + absOffsetY; // If image is single-layer then pointer to its transform layer is 'nullptr' const uint8_t * transformIn = in.singleLayer() ? nullptr : in.transform(); uint8_t * transformOut = out.singleLayer() ? nullptr : ( out.transform() + outStartOffset ); uint8_t * imageOut = out.image() + outStartOffset; const auto isTransparent = [inWidth, inHeight, transformIn]( const int32_t offsetX, const int32_t offsetY ) { if ( ( offsetX < 0 ) || ( offsetY < 0 ) || ( offsetX >= inWidth ) || ( offsetY >= inHeight ) ) { // The space out of image boundaries is considered as transparent. return true; } if ( transformIn == nullptr ) { // Single-layer images are non-transparent. return false; } // Image is transparent when its transform layer data is equal to 1. return ( *( transformIn + offsetX + static_cast( offsetY ) * inWidth ) == 1 ); }; for ( int32_t y = 0; y < maxY; ++y ) { const int32_t offsetY = y + shadowOffsetY; for ( int32_t x = 0; x < maxX; ++x ) { const int32_t offsetX = x + shadowOffsetX; if ( !isTransparent( offsetX, offsetY ) ) { // We add shadow only to visible parts of the background image. continue; } // There are 4 shadow tables: 2, 3, 4, 5. The strongest shadow is in table ID 2. uint8_t transformTableId = 6; for ( const Point & shadowLineOffset : shadowLine ) { const int32_t shadowLineOffsetX = offsetX - shadowLineOffset.x; const int32_t shadowLineOffsetY = offsetY - shadowLineOffset.y; if ( !isTransparent( shadowLineOffsetX, shadowLineOffsetY ) ) { // Increase the strength of shadow by reducing the table ID. --transformTableId; if ( transformTableId == 2 ) { // We reached the strongest shadow table ID. break; } } } if ( transformTableId == 6 ) { continue; } // The transformTableId is less than 6 so the shadow has to be applied. const int32_t outOffset = x + y * outWidth; if ( transformOut != nullptr ) { // 'out' is double-layer image because transformOut pointer is not `nullptr`. uint8_t * transformOutX = transformOut + outOffset; if ( *transformOutX == 0 ) { // Apply shadow transform to the out image. uint8_t * imageOutX = imageOut + outOffset; *imageOutX = *( transformTable + transformTableId * ptrdiff_t{ 256 } + *imageOutX ); } else if ( *transformOutX > 1 && *transformOutX < 6 ) { // Out image transform layer already has shadow data. We add the shadow strength by subtract the 'transformTableId', limited to 2. *transformOutX = ( *transformOutX < 2 + transformTableId ) ? 2 : ( *transformOutX - transformTableId ); } else { *transformOutX = transformTableId; } } else { // For single-layer 'out' image apply shadow transform to the image data. uint8_t * imageOutX = imageOut + outOffset; *imageOutX = *( transformTable + transformTableId * ptrdiff_t{ 256 } + *imageOutX ); } } } } Sprite addShadow( const Sprite & in, const Point & shadowOffset, const uint8_t transformId ) { if ( in.empty() || shadowOffset.x > 0 || shadowOffset.y < 0 ) { return in; } Sprite out = makeShadow( in, shadowOffset, transformId ); Blit( in, out, -shadowOffset.x, 0 ); return out; } void AddTransparency( Image & image, const uint8_t valueToReplace ) { ReplaceColorIdByTransformId( image, valueToReplace, 1 ); } void AlphaBlit( const Image & in, Image & out, const uint8_t alphaValue, const bool flip /* = false */ ) { AlphaBlit( in, 0, 0, out, 0, 0, in.width(), in.height(), alphaValue, flip ); } void AlphaBlit( const Image & in, Image & out, int32_t outX, int32_t outY, const uint8_t alphaValue, const bool flip /* = false */ ) { AlphaBlit( in, 0, 0, out, outX, outY, in.width(), in.height(), alphaValue, flip ); } void AlphaBlit( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const uint8_t alphaValue, const bool flip /* = false */ ) { if ( alphaValue == 0 ) { // There is nothing we need to do. return; } if ( alphaValue == 255 ) { Blit( in, inX, inY, out, outX, outY, width, height, flip ); return; } if ( !Verify( in, inX, inY, out, outX, outY, width, height ) ) { return; } const int32_t widthIn = in.width(); const int32_t widthOut = out.width(); const uint8_t behindValue = 255 - alphaValue; const uint8_t * gamePalette = getGamePalette(); if ( flip ) { const int32_t offsetInY = inY * widthIn + widthIn - 1 - inX; const uint8_t * imageInY = in.image() + offsetInY; const int32_t offsetOutY = outY * widthOut + outX; uint8_t * imageOutY = out.image() + offsetOutY; const uint8_t * imageOutYEnd = imageOutY + static_cast( height ) * widthOut; if ( in.singleLayer() ) { for ( ; imageOutY != imageOutYEnd; imageInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; for ( ; imageOutX != imageOutXEnd; --imageInX, ++imageOutX ) { const uint8_t * inPAL = gamePalette + static_cast( *imageInX ) * 3; const uint8_t * outPAL = gamePalette + static_cast( *imageOutX ) * 3; const uint32_t red = static_cast( *inPAL ) * alphaValue + static_cast( *outPAL ) * behindValue; const uint32_t green = static_cast( *( inPAL + 1 ) ) * alphaValue + static_cast( *( outPAL + 1 ) ) * behindValue; const uint32_t blue = static_cast( *( inPAL + 2 ) ) * alphaValue + static_cast( *( outPAL + 2 ) ) * behindValue; *imageOutX = GetPALColorId( static_cast( red / 255 ), static_cast( green / 255 ), static_cast( blue / 255 ) ); } } } else { const uint8_t * transformInY = in.transform() + offsetInY; for ( ; imageOutY != imageOutYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; for ( ; imageOutX != imageOutXEnd; --imageInX, --transformInX, ++imageOutX ) { if ( *transformInX == 1 ) { // skip pixel continue; } uint8_t inValue = *imageInX; if ( *transformInX > 1 ) { inValue = *( transformTable + static_cast( *transformInX ) * 256 + *imageOutX ); } const uint8_t * inPAL = gamePalette + static_cast( inValue ) * 3; const uint8_t * outPAL = gamePalette + static_cast( *imageOutX ) * 3; const uint32_t red = static_cast( *inPAL ) * alphaValue + static_cast( *outPAL ) * behindValue; const uint32_t green = static_cast( *( inPAL + 1 ) ) * alphaValue + static_cast( *( outPAL + 1 ) ) * behindValue; const uint32_t blue = static_cast( *( inPAL + 2 ) ) * alphaValue + static_cast( *( outPAL + 2 ) ) * behindValue; *imageOutX = GetPALColorId( static_cast( red / 255 ), static_cast( green / 255 ), static_cast( blue / 255 ) ); } } } } else { const int32_t offsetInY = inY * widthIn + inX; const uint8_t * imageInY = in.image() + offsetInY; uint8_t * imageOutY = out.image() + static_cast( outY ) * widthOut + outX; const uint8_t * imageInYEnd = imageInY + static_cast( height ) * widthIn; if ( in.singleLayer() ) { for ( ; imageInY != imageInYEnd; imageInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageInXEnd = imageInX + width; for ( ; imageInX != imageInXEnd; ++imageInX, ++imageOutX ) { const uint8_t * inPAL = gamePalette + static_cast( *imageInX ) * 3; const uint8_t * outPAL = gamePalette + static_cast( *imageOutX ) * 3; const uint32_t red = static_cast( *inPAL ) * alphaValue + static_cast( *outPAL ) * behindValue; const uint32_t green = static_cast( *( inPAL + 1 ) ) * alphaValue + static_cast( *( outPAL + 1 ) ) * behindValue; const uint32_t blue = static_cast( *( inPAL + 2 ) ) * alphaValue + static_cast( *( outPAL + 2 ) ) * behindValue; *imageOutX = GetPALColorId( static_cast( red / 255 ), static_cast( green / 255 ), static_cast( blue / 255 ) ); } } } else { const uint8_t * transformInY = in.transform() + offsetInY; for ( ; imageInY != imageInYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageInXEnd = imageInX + width; for ( ; imageInX != imageInXEnd; ++imageInX, ++transformInX, ++imageOutX ) { if ( *transformInX == 1 ) { // skip pixel continue; } uint8_t inValue = *imageInX; if ( *transformInX > 1 ) { inValue = *( transformTable + static_cast( *transformInX ) * 256 + *imageOutX ); } const uint8_t * inPAL = gamePalette + static_cast( inValue ) * 3; const uint8_t * outPAL = gamePalette + static_cast( *imageOutX ) * 3; const uint32_t red = static_cast( *inPAL ) * alphaValue + static_cast( *outPAL ) * behindValue; const uint32_t green = static_cast( *( inPAL + 1 ) ) * alphaValue + static_cast( *( outPAL + 1 ) ) * behindValue; const uint32_t blue = static_cast( *( inPAL + 2 ) ) * alphaValue + static_cast( *( outPAL + 2 ) ) * behindValue; *imageOutX = GetPALColorId( static_cast( red / 255 ), static_cast( green / 255 ), static_cast( blue / 255 ) ); } } } } } void ApplyPalette( Image & image, const std::vector & palette ) { ApplyPalette( image, image, palette ); } void ApplyPalette( const Image & in, Image & out, const std::vector & palette ) { if ( palette.size() != 256 ) { return; } ApplyRawPalette( in, 0, 0, out, 0, 0, in.width(), in.height(), palette.data() ); } void ApplyPalette( Image & image, const uint8_t paletteId ) { ApplyPalette( image, image, paletteId ); } void ApplyPalette( const Image & in, Image & out, const uint8_t paletteId ) { if ( paletteId > 15 ) { return; } ApplyRawPalette( in, 0, 0, out, 0, 0, in.width(), in.height(), transformTable + paletteId * 256 ); } void ApplyPalette( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, uint8_t paletteId ) { if ( paletteId > 15 ) { return; } ApplyRawPalette( in, inX, inY, out, outX, outY, width, height, transformTable + paletteId * 256 ); } void ApplyPalette( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const std::vector & palette ) { if ( palette.size() != 256 ) { return; } ApplyRawPalette( in, inX, inY, out, outX, outY, width, height, palette.data() ); } void ApplyAlpha( const Image & in, Image & out, const uint8_t alpha ) { ApplyAlpha( in, 0, 0, out, 0, 0, in.width(), in.height(), alpha ); } void ApplyAlpha( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const uint8_t alpha ) { std::vector palette( 256 ); const uint8_t * value = getGamePalette(); for ( uint32_t i = 0; i < 256; ++i ) { const uint32_t red = static_cast( *value ) * alpha / 255; ++value; const uint32_t green = static_cast( *value ) * alpha / 255; ++value; const uint32_t blue = static_cast( *value ) * alpha / 255; ++value; palette[i] = GetPALColorId( static_cast( red ), static_cast( green ), static_cast( blue ) ); } ApplyPalette( in, inX, inY, out, outX, outY, width, height, palette ); } void ApplyTransform( Image & image, int32_t x, int32_t y, int32_t width, int32_t height, const uint8_t transformId ) { if ( !Verify( image, x, y, width, height ) ) { return; } const int32_t imageWidth = image.width(); uint8_t * imageY = image.image() + y * imageWidth + x; const uint8_t * imageYEnd = imageY + height * imageWidth; if ( image.singleLayer() ) { for ( ; imageY != imageYEnd; imageY += imageWidth ) { uint8_t * imageX = imageY; const uint8_t * imageXEnd = imageX + width; for ( ; imageX != imageXEnd; ++imageX ) { *imageX = *( transformTable + transformId * 256 + *imageX ); } } } else { const uint8_t * transformY = image.transform() + y * imageWidth + x; for ( ; imageY != imageYEnd; imageY += imageWidth, transformY += imageWidth ) { uint8_t * imageX = imageY; const uint8_t * transformX = transformY; const uint8_t * imageXEnd = imageX + width; for ( ; imageX != imageXEnd; ++imageX, ++transformX ) { if ( *transformX == 0 ) { *imageX = *( transformTable + transformId * 256 + *imageX ); } } } } } void Blit( const Image & in, Image & out, const bool flip /* = false */ ) { Blit( in, 0, 0, out, 0, 0, in.width(), in.height(), flip ); } void Blit( const Image & in, Image & out, const Rect & outRoi, const bool flip /* = false */ ) { Blit( in, 0, 0, out, outRoi.x, outRoi.y, outRoi.width, outRoi.height, flip ); } void Blit( const Image & in, Image & out, int32_t outX, int32_t outY, const bool flip /* = false */ ) { Blit( in, 0, 0, out, outX, outY, in.width(), in.height(), flip ); } void Blit( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const bool flip /* = false */ ) { if ( in.singleLayer() && !flip ) { Copy( in, inX, inY, out, outX, outY, width, height ); return; } if ( !Verify( in, inX, inY, out, outX, outY, width, height ) ) { return; } const int32_t widthIn = in.width(); const int32_t widthOut = out.width(); if ( flip ) { const int32_t offsetInY = inY * widthIn + widthIn - 1 - inX; const uint8_t * imageInY = in.image() + offsetInY; const uint8_t * transformInY = in.transform() + offsetInY; const int32_t offsetOutY = outY * widthOut + outX; uint8_t * imageOutY = out.image() + offsetOutY; const uint8_t * imageOutYEnd = imageOutY + height * widthOut; if ( out.singleLayer() ) { assert( !in.singleLayer() ); for ( ; imageOutY != imageOutYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; for ( ; imageOutX != imageOutXEnd; --imageInX, --transformInX, ++imageOutX ) { if ( *transformInX > 0 ) { // apply a transformation if ( *transformInX != 1 ) { // skip pixel *imageOutX = *( transformTable + ( *transformInX ) * 256 + *imageOutX ); } } else { // copy a pixel *imageOutX = *imageInX; } } } } else { uint8_t * transformOutY = out.transform() + offsetOutY; for ( ; imageOutY != imageOutYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut, transformOutY += widthOut ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; uint8_t * imageOutX = imageOutY; uint8_t * transformOutX = transformOutY; const uint8_t * imageOutXEnd = imageOutX + width; for ( ; imageOutX != imageOutXEnd; --imageInX, --transformInX, ++imageOutX, ++transformOutX ) { if ( *transformInX == 1 ) { // skip pixel continue; } if ( *transformInX > 0 && *transformOutX == 0 ) { // apply a transformation *imageOutX = *( transformTable + ( *transformInX ) * 256 + *imageOutX ); } else { // copy a pixel *transformOutX = *transformInX; *imageOutX = *imageInX; } } } } } else { const int32_t offsetInY = inY * widthIn + inX; const uint8_t * imageInY = in.image() + offsetInY; const uint8_t * transformInY = in.transform() + offsetInY; const int32_t offsetOutY = outY * widthOut + outX; uint8_t * imageOutY = out.image() + offsetOutY; const uint8_t * imageInYEnd = imageInY + height * widthIn; if ( out.singleLayer() ) { assert( !in.singleLayer() ); for ( ; imageInY != imageInYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; uint8_t * imageOutX = imageOutY; const uint8_t * imageInXEnd = imageInX + width; for ( ; imageInX != imageInXEnd; ++imageInX, ++transformInX, ++imageOutX ) { if ( *transformInX > 0 ) { // apply a transformation if ( *transformInX != 1 ) { // skip pixel *imageOutX = *( transformTable + ( *transformInX ) * 256 + *imageOutX ); } } else { // copy a pixel *imageOutX = *imageInX; } } } } else { uint8_t * transformOutY = out.transform() + offsetOutY; for ( ; imageInY != imageInYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut, transformOutY += widthOut ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; uint8_t * imageOutX = imageOutY; uint8_t * transformOutX = transformOutY; const uint8_t * imageInXEnd = imageInX + width; for ( ; imageInX != imageInXEnd; ++imageInX, ++transformInX, ++imageOutX, ++transformOutX ) { if ( *transformInX == 1 ) { // skip pixel continue; } if ( *transformInX > 0 && *transformOutX == 0 ) { // apply a transformation *imageOutX = *( transformTable + ( *transformInX ) * 256 + *imageOutX ); } else { // copy a pixel *transformOutX = *transformInX; *imageOutX = *imageInX; } } } } } } void Blit( const Image & in, const Point & inPos, Image & out, const Point & outPos, const Size & size, const bool flip /* = false */ ) { if ( inPos.x < 0 || inPos.y < 0 ) { return; } Blit( in, inPos.x, inPos.y, out, outPos.x, outPos.y, size.width, size.height, flip ); } void Copy( const Image & in, Image & out ) { if ( !out.singleLayer() && !in.singleLayer() ) { // Both images have transform layer. Copy using the assignment operator. out = in; return; } const int32_t width = in.width(); const int32_t height = in.height(); out.resize( width, height ); // We do a full copy of an image. const size_t size = static_cast( width ) * height; if ( out.singleLayer() ) { // Copy only image layer. Input image can be single- or double-layer. memcpy( out.image(), in.image(), size ); } else { assert( in.singleLayer() ); // Copy image layer and set transform to non-transparent mode. memcpy( out.image(), in.image(), size ); memset( out.transform(), static_cast( 0 ), size ); } } void Copy( const Image & in, int32_t inX, int32_t inY, Image & out, const Rect & outRoi ) { Copy( in, inX, inY, out, outRoi.x, outRoi.y, outRoi.width, outRoi.height ); } void Copy( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height ) { if ( !Verify( in, inX, inY, out, outX, outY, width, height ) ) { return; } const int32_t widthIn = in.width(); const int32_t widthOut = out.width(); if ( inX == 0 && inY == 0 && outX == 0 && outY == 0 && width == widthIn && width == widthOut && height == in.height() && height == out.height() ) { // Both images have identical width and height and a full copy is requested. Copy( in, out ); return; } const int32_t offsetInY = inY * widthIn + inX; const uint8_t * imageInY = in.image() + offsetInY; const int32_t offsetOutY = outY * widthOut + outX; uint8_t * imageOutY = out.image() + offsetOutY; const uint8_t * imageOutYEnd = imageOutY + height * widthOut; if ( out.singleLayer() ) { for ( ; imageOutY != imageOutYEnd; imageInY += widthIn, imageOutY += widthOut ) { memcpy( imageOutY, imageInY, static_cast( width ) ); } } else if ( in.singleLayer() ) { uint8_t * transformOutY = out.transform() + offsetOutY; for ( ; imageOutY != imageOutYEnd; imageInY += widthIn, imageOutY += widthOut, transformOutY += widthOut ) { memcpy( imageOutY, imageInY, static_cast( width ) ); memset( transformOutY, static_cast( 0 ), width ); } } else { const uint8_t * transformInY = in.transform() + offsetInY; uint8_t * transformOutY = out.transform() + offsetOutY; for ( ; imageOutY != imageOutYEnd; imageInY += widthIn, transformInY += widthIn, imageOutY += widthOut, transformOutY += widthOut ) { memcpy( imageOutY, imageInY, static_cast( width ) ); memcpy( transformOutY, transformInY, static_cast( width ) ); } } } void CopyTransformLayer( const Image & in, Image & out ) { if ( in.empty() || out.empty() || in.singleLayer() || in.width() != out.width() || in.height() != out.height() ) { assert( 0 ); return; } if ( out.singleLayer() ) { // Add the transform layer. Image temp; Copy( out, temp ); out = std::move( temp ); } memcpy( out.transform(), in.transform(), in.width() * in.height() ); } Sprite CreateContour( const Image & image, const uint8_t value ) { if ( image.empty() || image.singleLayer() ) { // A contour can be created only for non-empty images with the transform layer. assert( 0 ); return {}; } const int32_t width = image.width(); const int32_t height = image.height(); Sprite contour( width, height ); contour.reset(); if ( width < 2 || height < 2 ) { return contour; } // This assertion is needed to convince SonarQube that we will not dereference the null pointer to 'contour' image data. assert( !contour.empty() ); const uint8_t * inY = image.transform(); uint8_t * outImageY = contour.image(); uint8_t * outTransformY = contour.transform(); const int32_t reducedWidth = width - 1; const int32_t reducedHeight = height - 1; for ( int32_t y = 0; y < height; ++y, inY += width, outImageY += width, outTransformY += width ) { const uint8_t * inX = inY; const bool isNotTopRow = ( y > 0 ); const bool isNotBottomRow = ( y < reducedHeight ); for ( int32_t x = 0; x < width; ++x, ++inX ) { // Draw contour only on transparent pixel ( 1 ) or shadow ( 2 - 5 ) if ( *inX > 0 && *inX < 6 && ( ( x > 0 && *( inX - 1 ) == 0 ) || ( x < reducedWidth && *( inX + 1 ) == 0 ) || ( isNotTopRow && *( inX - width ) == 0 ) || ( isNotBottomRow && *( inX + width ) == 0 ) ) ) { outImageY[x] = value; outTransformY[x] = 0; } } } return contour; } void CreateDitheringTransition( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const bool isVertical, const bool isReverse ) { if ( !Verify( in, inX, inY, out, outX, outY, width, height ) ) { return; } const int32_t widthIn = in.width(); const int32_t offsetIn = inY * widthIn + inX; const uint8_t * imageIn = in.image() + offsetIn; const uint8_t * transformIn = in.singleLayer() ? nullptr : in.transform() + offsetIn; const int32_t widthOut = out.width(); const int32_t offsetOut = outY * widthOut + outX; uint8_t * imageOut = out.image() + offsetOut; uint8_t * transformOut = out.singleLayer() ? nullptr : out.transform() + offsetOut; if ( isVertical ) { // We also go in a loop from the right part of the image to its center. const uint8_t * imageInRightPoint = imageIn + width - 1; uint8_t * imageOutRightPoint = imageOut + width - 1; // If image is single-layer then pointer to its transform layer is 'nullptr' const uint8_t * transformInRightPoint = ( transformIn == nullptr ) ? nullptr : transformIn + width - 1; uint8_t * transformOutRightPoint = ( transformOut == nullptr ) ? nullptr : transformOut + width - 1; const int32_t halfWidth = width / 2; // We make a symmetric transition and if width is odd we shift one line right. if ( ( width % 2 ) == 1 ) { if ( isReverse ) { --imageOutRightPoint; --imageInRightPoint; if ( transformOutRightPoint != nullptr ) { --transformOutRightPoint; } if ( transformInRightPoint != nullptr ) { --transformInRightPoint; } } else { ++imageOut; ++imageIn; if ( transformOut != nullptr ) { ++transformOut; } if ( transformIn != nullptr ) { ++transformIn; } } } for ( int32_t x = 0; x < halfWidth; ++x ) { // The step is 2 to the power, which decreases by 1 every second line and is 1 in the center. // We limit the step power to 30 to not overflow the 32 bit 'stepY'. const int32_t stepPower = std::min( 30, ( halfWidth - x ) / 2 + 1 ); const int32_t stepY = 1 << stepPower; // The point position in dithered pattern. const int32_t patternPoint = stepY / 2 * ( ( x + halfWidth ) % 2 ); for ( int32_t y = 0; y < height; ++y ) { const int32_t offsetOutX = y * widthOut; const int32_t offsetInX = y * widthIn; const int32_t offsetY = y % stepY; if ( isReverse == ( patternPoint != offsetY ) ) { if ( transformIn != nullptr && transformOut == nullptr && ( *( transformIn + offsetInX ) == 1 ) ) { // Skip pixel. continue; } // First part of transition: we copy single pixels. *( imageOut + offsetOutX ) = *( imageIn + offsetInX ); if ( transformOut == nullptr ) { continue; } if ( transformIn == nullptr ) { // Set the copied pixel visible. *( transformOut + offsetOutX ) = 0; } else { // 'in' and 'out' images have the transform layer. *( transformOut + offsetOutX ) = *( transformIn + offsetInX ); } } else { if ( transformInRightPoint != nullptr && transformOutRightPoint == nullptr && ( *( transformInRightPoint + offsetInX ) == 1 ) ) { // Skip pixel. continue; } // Second part of transition: we copy image excluding single pixels. *( imageOutRightPoint + offsetOutX ) = *( imageInRightPoint + offsetInX ); if ( transformOutRightPoint == nullptr ) { continue; } if ( transformInRightPoint == nullptr ) { // Set the copied pixel visible. *( transformOutRightPoint + offsetOutX ) = 0; } else { // 'in' and 'out' images have the transform layer. *( transformOutRightPoint + offsetOutX ) = *( transformInRightPoint + offsetInX ); } } } ++imageOut; --imageOutRightPoint; ++imageIn; --imageInRightPoint; if ( transformOut != nullptr ) { ++transformOut; --transformOutRightPoint; } if ( transformIn != nullptr ) { ++transformIn; --transformInRightPoint; } } } else { // We also go in a loop from the bottom part of the image to its center. const int32_t offsetInBottomOffset = ( height - 1 ) * widthIn; const int32_t offsetOutYBottomOffset = ( height - 1 ) * widthOut; const uint8_t * imageInBottomPoint = imageIn + offsetInBottomOffset; uint8_t * imageOutBottomPoint = imageOut + offsetOutYBottomOffset; // If image is single-layer then pointer to its transform layer is 'nullptr'. const uint8_t * transformInBottomPoint = ( transformIn == nullptr ) ? nullptr : transformIn + offsetInBottomOffset; uint8_t * transformOutBottomPoint = ( transformOut == nullptr ) ? nullptr : transformOut + offsetOutYBottomOffset; const int32_t halfHeight = height / 2; // We make a symmetric transition and if width is odd we shift one line down. if ( ( height % 2 ) == 1 ) { if ( isReverse ) { imageOutBottomPoint -= widthOut; imageInBottomPoint -= widthIn; if ( transformOutBottomPoint != nullptr ) { transformOutBottomPoint -= widthOut; } if ( transformInBottomPoint != nullptr ) { transformInBottomPoint -= widthIn; } } else { imageOut += widthOut; imageIn += widthIn; if ( transformOut != nullptr ) { transformOut += widthOut; } if ( transformIn != nullptr ) { transformIn += widthIn; } } } for ( int32_t y = 0; y < halfHeight; ++y ) { // The step is 2 to the power, which decreases by 1 every second line and is 1 in the center. // We limit the step power to 30 to not overflow the 32 bit 'stepX'. const int32_t stepPower = std::min( 30, ( halfHeight - y ) / 2 + 1 ); const int32_t stepX = 1 << stepPower; // The point position in dithered pattern. const int32_t patternPoint = stepX / 2 * ( ( y + halfHeight ) % 2 ); for ( int32_t x = 0; x < width; ++x ) { const int32_t offsetX = x % stepX; if ( isReverse == ( patternPoint != offsetX ) ) { if ( transformIn != nullptr && transformOut == nullptr && ( *( transformIn + x ) == 1 ) ) { // Skip pixel. continue; } // First part of transition: we copy single pixels. *( imageOut + x ) = *( imageIn + x ); if ( transformOut == nullptr ) { continue; } if ( transformIn == nullptr ) { // Set the copied pixel visible. *( transformOut + x ) = 0; } else { // 'in' and 'out' images have the transform layer. *( transformOut + x ) = *( transformIn + x ); } } else { if ( transformInBottomPoint != nullptr && transformOutBottomPoint == nullptr && ( *( transformInBottomPoint + x ) == 1 ) ) { // Skip pixel. continue; } // Second part of transition: we copy image excluding single pixels. *( imageOutBottomPoint + x ) = *( imageInBottomPoint + x ); if ( transformOutBottomPoint == nullptr ) { continue; } if ( transformInBottomPoint == nullptr ) { // Set the copied pixel visible. *( transformOutBottomPoint + x ) = 0; } else { // 'in' and 'out' images have the transform layer. *( transformOutBottomPoint + x ) = *( transformInBottomPoint + x ); } } } imageOut += widthOut; imageOutBottomPoint -= widthOut; imageIn += widthIn; imageInBottomPoint -= widthIn; if ( transformOut != nullptr ) { transformOut += widthOut; transformOutBottomPoint -= widthOut; } if ( transformIn != nullptr ) { transformIn += widthIn; transformInBottomPoint -= widthIn; } } } } Sprite Crop( const Image & image, int32_t x, int32_t y, int32_t width, int32_t height ) { if ( image.empty() || width <= 0 || height <= 0 ) { return {}; } if ( x < 0 ) { const int32_t offsetX = -x; if ( offsetX >= width ) { return {}; } x = 0; width -= offsetX; } if ( y < 0 ) { const int32_t offsetY = -y; if ( offsetY >= height ) { return {}; } y = 0; height -= offsetY; } if ( x > image.width() || y > image.height() ) { return {}; } if ( x + width > image.width() ) { const int32_t offsetX = x + width - image.width(); width -= offsetX; } if ( y + height > image.height() ) { const int32_t offsetY = y + height - image.height(); height -= offsetY; } Sprite out; if ( image.singleLayer() ) { // The result of Crop should have the same layers as the input image. out._disableTransformLayer(); } out.resize( width, height ); Copy( image, x, y, out, 0, 0, width, height ); out.setPosition( x, y ); return out; } void DrawBorder( Image & image, const uint8_t value, const uint32_t skipFactor /* =0 */ ) { if ( image.empty() || image.width() < 2 || image.height() < 2 ) { return; } const int32_t width = image.width(); const int32_t height = image.height(); uint8_t * dataPointer = image.image(); // If image is single-layer then pointer to its transform layer is 'nullptr'. uint8_t * transformPointer = image.singleLayer() ? nullptr : image.transform(); if ( skipFactor < 2 ) { // top side uint8_t * data = dataPointer; const uint8_t * dataEnd = data + width; if ( transformPointer == nullptr ) { for ( ; data != dataEnd; ++data ) { *data = value; } } else { uint8_t * transform = transformPointer; for ( ; data != dataEnd; ++data, ++transform ) { *data = value; *transform = 0; } } // bottom side data = dataPointer + width * static_cast( height - 1 ); dataEnd = data + width; if ( transformPointer == nullptr ) { for ( ; data != dataEnd; ++data ) { *data = value; } } else { uint8_t * transform = transformPointer + width * static_cast( height - 1 ); for ( ; data != dataEnd; ++data, ++transform ) { *data = value; *transform = 0; } } // left side data = dataPointer + width; dataEnd = data + width * ( height - 2 ); if ( transformPointer == nullptr ) { for ( ; data != dataEnd; data += width ) { *data = value; } } else { uint8_t * transform = transformPointer + width; for ( ; data != dataEnd; data += width, transform += width ) { *data = value; *transform = 0; } } // right side data = dataPointer + width + width - 1; dataEnd = data + width * ( height - 2 ); if ( transformPointer == nullptr ) { for ( ; data != dataEnd; data += width ) { *data = value; } } else { uint8_t * transform = transformPointer + width + width - 1; for ( ; data != dataEnd; data += width, transform += width ) { *data = value; *transform = 0; } } } else { uint32_t counter = 1; // top side uint8_t * data = dataPointer; const uint8_t * dataEnd = data + width; if ( transformPointer == nullptr ) { for ( ; data != dataEnd; ++data ) { if ( counter % skipFactor != 0 ) { *data = value; } ++counter; } } else { uint8_t * transform = transformPointer; for ( ; data != dataEnd; ++data, ++transform ) { if ( counter % skipFactor != 0 ) { *data = value; *transform = 0; } ++counter; } } // right side data = dataPointer + width + width - 1; dataEnd = data + width * ( height - 2 ); if ( transformPointer == nullptr ) { for ( ; data != dataEnd; data += width ) { if ( counter % skipFactor != 0 ) { *data = value; } ++counter; } } else { uint8_t * transform = transformPointer + width + width - 1; for ( ; data != dataEnd; data += width, transform += width ) { if ( counter % skipFactor != 0 ) { *data = value; *transform = 0; } ++counter; } } // bottom side data = dataPointer + width * static_cast( height - 1 ) + width - 1; dataEnd = data - width; if ( transformPointer == nullptr ) { for ( ; data != dataEnd; --data ) { if ( counter % skipFactor != 0 ) { *data = value; } ++counter; } } else { uint8_t * transform = transformPointer + width * static_cast( height - 1 ) + width - 1; for ( ; data != dataEnd; --data, --transform ) { if ( counter % skipFactor != 0 ) { *data = value; *transform = 0; } ++counter; } } // left side data = dataPointer + width * static_cast( height - 2 ); dataEnd = dataPointer; if ( transformPointer == nullptr ) { for ( ; data != dataEnd; data -= width ) { if ( counter % skipFactor != 0 ) { *data = value; } ++counter; } } else { uint8_t * transform = transformPointer + width * static_cast( height - 2 ); for ( ; data != dataEnd; data -= width, transform -= width ) { if ( counter % skipFactor != 0 ) { *data = value; *transform = 0; } ++counter; } } } } void DrawLine( Image & image, const Point & start, const Point & end, const uint8_t value, const Rect & roi /* = Rect() */ ) { if ( image.empty() ) { return; } const int32_t width = image.width(); const int32_t height = image.height(); int32_t x1 = start.x; int32_t y1 = start.y; const int32_t x2 = end.x; const int32_t y2 = end.y; const int32_t dx = std::abs( x2 - x1 ); const int32_t dy = std::abs( y2 - y1 ); const bool isValidRoi = roi.width > 0 && roi.height > 0; const int32_t minX = isValidRoi ? std::max( roi.x, 0 ) : 0; const int32_t minY = isValidRoi ? std::max( roi.y, 0 ) : 0; int32_t maxX = isValidRoi ? roi.x + roi.width : width; int32_t maxY = isValidRoi ? roi.y + roi.height : height; if ( minX >= width || minY >= height ) { return; } if ( maxX >= width ) { maxX = width; } if ( maxY >= height ) { maxY = height; } uint8_t * data = image.image(); if ( image.singleLayer() ) { if ( dx >= dy ) { int32_t ns = dx / 2; for ( int32_t i = 0; i <= dx; ++i ) { if ( x1 >= minX && x1 < maxX && y1 >= minY && y1 < maxY ) { const int32_t offset = x1 + y1 * width; *( data + offset ) = value; } x1 < x2 ? ++x1 : --x1; ns -= dy; if ( ns < 0 ) { y1 < y2 ? ++y1 : --y1; ns += dx; } } } else { int32_t ns = dy / 2; for ( int32_t i = 0; i <= dy; ++i ) { if ( x1 >= minX && x1 < maxX && y1 >= minY && y1 < maxY ) { const int32_t offset = x1 + y1 * width; *( data + offset ) = value; } y1 < y2 ? ++y1 : --y1; ns -= dx; if ( ns < 0 ) { x1 < x2 ? ++x1 : --x1; ns += dy; } } } } else { uint8_t * transform = image.transform(); if ( dx >= dy ) { int32_t ns = dx / 2; for ( int32_t i = 0; i <= dx; ++i ) { if ( x1 >= minX && x1 < maxX && y1 >= minY && y1 < maxY ) { const int32_t offset = x1 + y1 * width; *( data + offset ) = value; *( transform + offset ) = 0; } x1 < x2 ? ++x1 : --x1; ns -= dy; if ( ns < 0 ) { y1 < y2 ? ++y1 : --y1; ns += dx; } } } else { int32_t ns = dy / 2; for ( int32_t i = 0; i <= dy; ++i ) { if ( x1 >= minX && x1 < maxX && y1 >= minY && y1 < maxY ) { const int32_t offset = x1 + y1 * width; *( data + offset ) = value; *( transform + offset ) = 0; } y1 < y2 ? ++y1 : --y1; ns -= dx; if ( ns < 0 ) { x1 < x2 ? ++x1 : --x1; ns += dy; } } } } } void DrawRect( Image & image, const Rect & roi, const uint8_t value ) { if ( image.empty() || roi.width < 1 || roi.height < 1 ) { return; } DrawLine( image, { roi.x, roi.y }, { roi.x + roi.width, roi.y }, value, roi ); DrawLine( image, { roi.x, roi.y }, { roi.x, roi.y + roi.height }, value, roi ); DrawLine( image, { roi.x + roi.width - 1, roi.y }, { roi.x + roi.width - 1, roi.y + roi.height }, value, roi ); DrawLine( image, { roi.x, roi.y + roi.height - 1 }, { roi.x + roi.width, roi.y + roi.height - 1 }, value, roi ); } void DivideImageBySquares( const Point & spriteOffset, const Image & original, const int32_t squareSize, std::vector & outputSquareId, std::vector> & outputImageInfo ) { if ( original.empty() ) { return; } if ( squareSize <= 0 ) { assert( 0 ); return; } Point offset{ spriteOffset.x / squareSize, spriteOffset.y / squareSize }; // The start of a square must be before image offset so in case of negative offset we need to decrease the ID of the start square. if ( ( spriteOffset.x < 0 ) && ( offset.x * squareSize != spriteOffset.x ) ) { --offset.x; } if ( ( spriteOffset.y < 0 ) && ( offset.y * squareSize != spriteOffset.y ) ) { --offset.y; } const Point spriteRelativeOffset{ spriteOffset.x - offset.x * squareSize, spriteOffset.y - offset.y * squareSize }; const Point stepPerDirection{ ( original.width() + spriteRelativeOffset.x + squareSize - 1 ) / squareSize, ( original.height() + spriteRelativeOffset.y + squareSize - 1 ) / squareSize }; assert( stepPerDirection.x > 0 && stepPerDirection.y > 0 ); const Rect relativeROI( spriteRelativeOffset.x, spriteRelativeOffset.y, original.width(), original.height() ); for ( int32_t y = 0; y < stepPerDirection.y; ++y ) { for ( int32_t x = 0; x < stepPerDirection.x; ++x ) { const Rect roi( x * squareSize, y * squareSize, squareSize, squareSize ); const Rect intersection = relativeROI ^ roi; assert( intersection.width > 0 && intersection.height > 0 ); outputSquareId.emplace_back( offset + Point( x, y ) ); outputImageInfo.emplace_back( fheroes2::Point( intersection.x - roi.x, intersection.y - roi.y ), fheroes2::Rect( intersection.x - spriteRelativeOffset.x, intersection.y - spriteRelativeOffset.y, intersection.width, intersection.height ) ); } } } Image ExtractCommonPattern( const std::vector & input ) { if ( input.empty() ) { return {}; } assert( input.front() != nullptr ); if ( input.size() == 1 ) { return *input.front(); } if ( input.front()->empty() ) { return {}; } const int32_t inputFrontWidth = input.front()->width(); const int32_t inputFrontHeight = input.front()->height(); for ( const Image * image : input ) { assert( image != nullptr ); if ( image->width() != inputFrontWidth || image->height() != inputFrontHeight ) { return {}; } } std::vector imageIn( input.size() ); std::vector transformIn( input.size() ); for ( size_t i = 0; i < input.size(); ++i ) { imageIn[i] = input[i]->image(); transformIn[i] = input[i]->singleLayer() ? nullptr : input[i]->transform(); } Image out( inputFrontWidth, inputFrontHeight ); out.reset(); uint8_t * imageOut = out.image(); uint8_t * transformOut = out.transform(); const uint8_t * imageOutEnd = imageOut + out.width() * out.height(); bool isEqual = false; for ( ; imageOut != imageOutEnd; ++imageOut, ++transformOut ) { isEqual = true; for ( size_t i = 1; i < input.size(); ++i ) { if ( *imageIn[0] != *imageIn[i] || ( transformIn[0] != nullptr && transformIn[i] != nullptr && ( *transformIn[0] != *transformIn[i] ) ) ) { isEqual = false; break; } } if ( isEqual ) { *imageOut = *imageIn[0]; *transformOut = ( transformIn[0] == nullptr ) ? 0 : *transformIn[0]; } for ( size_t i = 0; i < input.size(); ++i ) { ++imageIn[i]; if ( transformIn[i] != nullptr ) { ++transformIn[i]; } } } return out; } void Fill( Image & image, int32_t x, int32_t y, int32_t width, int32_t height, const uint8_t colorId ) { if ( !Verify( image, x, y, width, height ) ) { return; } if ( image.width() == width && image.height() == height ) { // We fill the whole image. image.fill( colorId ); return; } const int32_t imageWidth = image.width(); uint8_t * imageY = image.image() + y * imageWidth + x; const uint8_t * imageYEnd = imageY + height * imageWidth; if ( image.singleLayer() ) { for ( ; imageY != imageYEnd; imageY += imageWidth ) { memset( imageY, colorId, width ); } } else { uint8_t * transformY = image.transform() + static_cast( y ) * imageWidth + x; for ( ; imageY != imageYEnd; imageY += imageWidth, transformY += imageWidth ) { memset( imageY, colorId, width ); memset( transformY, static_cast( 0 ), width ); } } } void FillTransform( Image & image, int32_t x, int32_t y, int32_t width, int32_t height, const uint8_t transformId ) { if ( !Verify( image, x, y, width, height ) || image.singleLayer() ) { return; } const int32_t imageWidth = image.width(); uint8_t * imageY = image.image() + y * imageWidth + x; uint8_t * transformY = image.transform() + y * imageWidth + x; const uint8_t * imageYEnd = imageY + height * imageWidth; for ( ; imageY != imageYEnd; imageY += imageWidth, transformY += imageWidth ) { memset( imageY, static_cast( 0 ), width ); memset( transformY, transformId, width ); } } Image FilterOnePixelNoise( const Image & input ) { if ( input.width() < 3 || input.height() < 3 ) { return input; } const int32_t width = input.width(); const int32_t height = input.height(); const bool isSingleLayer = input.singleLayer(); Image output; if ( isSingleLayer ) { output._disableTransformLayer(); } output.resize( width, height ); output.reset(); const uint8_t * imageInY = input.image(); uint8_t * imageOutY = output.image(); if ( isSingleLayer ) { for ( int32_t y = 0; y < height; ++y ) { for ( int32_t x = 0; x < width; ++x ) { if ( ( x == 0 || x == width - 1 ) && ( y == 0 || y == height - 1 ) ) { *( imageOutY + x ) = *( imageInY + x ); } } imageInY += width; imageOutY += width; } } else { const uint8_t * transformInY = input.transform(); uint8_t * transformOutY = output.transform(); for ( int32_t y = 0; y < height; ++y ) { const uint8_t * transformInX = transformInY; for ( int32_t x = 0; x < width; ++x ) { if ( *transformInX == 0 && ( x == 0 || x == width - 1 || *( transformInX - 1 ) == 0 || *( transformInX + 1 ) == 0 ) && ( y == 0 || y == height - 1 || *( transformInX - width ) == 0 || *( transformInX + width ) == 0 ) ) { *( transformOutY + x ) = 0; *( imageOutY + x ) = *( imageInY + x ); } ++transformInX; } imageInY += width; transformInY += width; imageOutY += width; transformOutY += width; } } return output; } bool FitToRoi( const Image & in, Point & inPos, const Image & out, Point & outPos, Size & outputSize, const Rect & outputRoi ) { if ( !Validate( out, outputRoi.x, outputRoi.y, outputRoi.width, outputRoi.height ) ) { return false; } outPos.x -= outputRoi.x; outPos.y -= outputRoi.y; if ( !Verify( inPos.x, inPos.y, outPos.x, outPos.y, outputSize.width, outputSize.height, in.width(), in.height(), outputRoi.width, outputRoi.height ) ) { return false; } outPos.x += outputRoi.x; outPos.y += outputRoi.y; return true; } Image Flip( const Image & in, const bool horizontally, const bool vertically ) { if ( in.empty() ) { return {}; } const int32_t width = in.width(); const int32_t height = in.height(); Image out; if ( in.singleLayer() ) { // Make the result of Flip to have the same layers as the input image. out._disableTransformLayer(); } out.resize( width, height ); if ( !horizontally && !vertically ) { Copy( in, out ); return out; } Flip( in, 0, 0, out, 0, 0, width, height, horizontally, vertically ); return out; } void Flip( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const bool horizontally, const bool vertically ) { if ( !Verify( in, inX, inY, out, outX, outY, width, height ) ) { return; } if ( !horizontally && !vertically ) { // No flip is required. Copy( in, inX, inY, out, outX, outY, width, height ); return; } // This assertion is needed to convince SonarQube that we will not dereference the null pointer to 'in' and 'out' images data. assert( !in.empty() && !out.empty() ); const int32_t widthIn = in.width(); const int32_t widthOut = out.width(); const int32_t offsetOut = outY * widthOut + outX; const int32_t offsetIn = inY * widthIn + inX; uint8_t * imageOutY = out.image() + offsetOut; const uint8_t * imageOutYEnd = imageOutY + static_cast( widthOut ) * height; // If image is single-layer then pointer to its transform layer is 'nullptr'. uint8_t * transformOutY = out.singleLayer() ? nullptr : out.transform() + offsetOut; if ( horizontally && !vertically ) { const uint8_t * imageInY = in.image() + offsetIn + width - 1; if ( in.singleLayer() ) { for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, imageInY += widthIn ) { uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; const uint8_t * imageInX = imageInY; for ( ; imageOutX != imageOutXEnd; ++imageOutX, --imageInX ) { *imageOutX = *imageInX; } if ( transformOutY != nullptr ) { // Set 'out' image transform data not to skip image data. memset( transformOutY, static_cast( 0 ), width ); transformOutY += widthOut; } } } else { const uint8_t * transformInY = in.transform() + offsetIn + width - 1; for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, imageInY += widthIn, transformInY += widthIn ) { uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; if ( transformOutY == nullptr ) { for ( ; imageOutX != imageOutXEnd; ++imageOutX, --imageInX, --transformInX ) { // Copy image data only for non-transparent pixels. if ( *transformInX == 0 ) { *imageOutX = *imageInX; } } } else { // 'in' and 'out' images are with transform layer. uint8_t * transformOutX = transformOutY; for ( ; imageOutX != imageOutXEnd; ++imageOutX, ++transformOutX, --imageInX, --transformInX ) { *imageOutX = *imageInX; *transformOutX = *transformInX; } transformOutY += widthOut; } } } } else if ( !horizontally && vertically ) { const uint8_t * imageInY = in.image() + offsetIn + static_cast( height - 1 ) * widthIn; if ( in.singleLayer() ) { for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, imageInY -= widthIn ) { memcpy( imageOutY, imageInY, static_cast( width ) ); if ( transformOutY != nullptr ) { // Set 'out' image transform data not to skip image data. memset( transformOutY, static_cast( 0 ), width ); transformOutY += widthOut; } } } else { const uint8_t * transformInY = in.transform() + offsetIn + static_cast( height - 1 ) * widthIn; if ( transformOutY == nullptr ) { for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, imageInY -= widthIn, transformInY -= widthIn ) { uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; for ( ; imageOutX != imageOutXEnd; ++imageOutX, ++imageInX, ++transformInX ) { // Copy image data only for non-transparent pixels. if ( *transformInX == 0 ) { *imageOutX = *imageInX; } } } } else { // 'in' and 'out' images are with transform layer. for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, transformOutY += widthOut, imageInY -= widthIn, transformInY -= widthIn ) { memcpy( imageOutY, imageInY, static_cast( width ) ); memcpy( transformOutY, transformInY, static_cast( width ) ); } } } } else { // Flip horizontally and vertically. if ( in.singleLayer() ) { const uint8_t * imageInY = in.image() + offsetIn + static_cast( height - 1 ) * widthIn + widthIn - 1; for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, imageInY -= widthIn ) { uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; const uint8_t * imageInX = imageInY; for ( ; imageOutX != imageOutXEnd; ++imageOutX, --imageInX ) { *imageOutX = *imageInX; } if ( transformOutY != nullptr ) { // 'in' image is double-layer: set transform data not to skip image data. memset( transformOutY, static_cast( 0 ), width ); transformOutY += widthOut; } } } else { const uint8_t * imageInY = in.image() + offsetIn + static_cast( height - 1 ) * widthIn + widthIn - 1; const uint8_t * transformInY = in.transform() + offsetIn + static_cast( height - 1 ) * widthIn + widthIn - 1; for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, imageInY -= widthIn, transformInY -= widthIn ) { uint8_t * imageOutX = imageOutY; const uint8_t * imageOutXEnd = imageOutX + width; const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; if ( transformOutY == nullptr ) { for ( ; imageOutX != imageOutXEnd; ++imageOutX, --imageInX, --transformInX ) { // Copy image data only for non-transparent pixels. if ( *transformInX == 0 ) { *imageOutX = *imageInX; } } } else { // 'in' and 'out' images are with transform layer. for ( uint8_t * transformOutX = transformOutY; imageOutX != imageOutXEnd; ++imageOutX, ++transformOutX, --imageInX, --transformInX ) { *imageOutX = *imageInX; *transformOutX = *transformInX; } transformOutY += widthOut; } } } } } Rect GetActiveROI( const Image & image, const uint8_t minTransformValue ) { if ( image.empty() || image.singleLayer() ) { return {}; } const int32_t width = image.width(); const int32_t height = image.height(); Rect area( -1, -1, -1, -1 ); // Top border const uint8_t * inY = image.transform(); for ( int32_t y = 0; y < height; ++y, inY += width ) { const uint8_t * inX = inY; for ( int32_t x = 0; x < width; ++x, ++inX ) { if ( *inX == 0 || *inX >= minTransformValue ) { area.y = y; break; } } if ( area.y >= 0 ) { break; } } if ( area.y < 0 ) { return {}; } // Bottom border inY = image.transform() + width * ( height - 1 ); for ( int32_t y = height - 1; y > area.y; --y, inY -= width ) { const uint8_t * inX = inY; for ( int32_t x = 0; x < width; ++x, ++inX ) { if ( *inX == 0 || *inX >= minTransformValue ) { area.height = y - area.y + 1; break; } } if ( area.height >= 0 ) { break; } } // Left border const uint8_t * inX = image.transform() + width * area.y; for ( int32_t x = 0; x < width; ++x, ++inX ) { inY = inX; for ( int32_t y = 0; y < area.height; ++y, inY += width ) { if ( *inY == 0 || *inY >= minTransformValue ) { area.x = x; break; } } if ( area.x >= 0 ) { break; } } // Right border inX = image.transform() + width * area.y + width - 1; for ( int32_t x = width - 1; x >= area.x; --x, --inX ) { inY = inX; for ( int32_t y = 0; y < area.height; ++y, inY += width ) { if ( *inY == 0 || *inY >= minTransformValue ) { area.width = x - area.x + 1; break; } } if ( area.width >= 0 ) { break; } } return area; } uint8_t GetColorId( const uint8_t red, const uint8_t green, const uint8_t blue ) { return GetPALColorId( red / 4, green / 4, blue / 4 ); } std::vector getTransformTable( const Image & in, const Image & out, int32_t x, int32_t y, int32_t width, int32_t height ) { std::vector table( 256 ); for ( size_t i = 0; i < table.size(); ++i ) { table[i] = static_cast( i ); } if ( !Verify( in, x, y, width, height ) || in.singleLayer() || out.singleLayer() ) { return table; } if ( in.width() != out.width() || in.height() != out.height() ) { return table; } const int32_t imageWidth = in.width(); const int32_t offset = y * imageWidth + x; const uint8_t * imageInY = in.image() + offset; const uint8_t * imageInYEnd = imageInY + height * imageWidth; const uint8_t * imageOutY = out.image() + offset; const uint8_t * transformInY = in.transform() + offset; const uint8_t * transformOutY = out.transform() + offset; for ( ; imageInY != imageInYEnd; imageInY += imageWidth, transformInY += imageWidth, imageOutY += imageWidth, transformOutY += imageWidth ) { const uint8_t * imageInX = imageInY; const uint8_t * transformInX = transformInY; const uint8_t * imageOutX = imageOutY; const uint8_t * transformOutX = transformOutY; const uint8_t * imageInXEnd = imageInX + width; for ( ; imageInX != imageInXEnd; ++imageInX, ++transformInX, ++imageOutX, ++transformOutX ) { if ( *transformInX != *transformOutX ) { continue; } if ( *transformInX != 0 ) { continue; } table[*imageInX] = *imageOutX; } } return table; } Sprite makeShadow( const Sprite & in, const Point & shadowOffset, const uint8_t transformId ) { if ( in.empty() || shadowOffset.x > 0 || shadowOffset.y < 0 ) { return {}; } const int32_t width = in.width(); const int32_t height = in.height(); // Shadow has (-x, +y) offset. Sprite out( width - shadowOffset.x, height + shadowOffset.y, in.x() + shadowOffset.x, in.y() ); out.reset(); assert( !out.empty() ); if ( in.singleLayer() ) { // In this case we add a shadow of the fully non-transparent rectangular 'in' image. FillTransform( out, 0, shadowOffset.y, width, height, transformId ); return out; } const int32_t widthOut = out.width(); const uint8_t * transformInY = in.transform(); const uint8_t * transformInYEnd = transformInY + width * height; uint8_t * transformOutY = out.transform() + shadowOffset.y * widthOut; for ( ; transformInY != transformInYEnd; transformInY += width, transformOutY += widthOut ) { const uint8_t * transformInX = transformInY; uint8_t * transformOutX = transformOutY; const uint8_t * transformInXEnd = transformInX + width; for ( ; transformInX != transformInXEnd; ++transformInX, ++transformOutX ) { if ( *transformInX == 0 ) { *transformOutX = transformId; } } } return out; } void MaskTransformLayer( const Image & mask, int32_t maskX, int32_t maskY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height ) { if ( !Verify( mask, maskX, maskY, out, outX, outY, width, height ) || mask.singleLayer() || out.singleLayer() ) { return; } const int32_t widthMask = mask.width(); const int32_t widthOut = out.width(); const uint8_t * imageMaskY = mask.transform() + maskY * widthMask + maskX; uint8_t * imageOutY = out.transform() + outY * widthOut + outX; const uint8_t * imageMaskYEnd = imageMaskY + height * widthMask; for ( ; imageMaskY != imageMaskYEnd; imageMaskY += widthMask, imageOutY += widthOut ) { const uint8_t * imageMaskX = imageMaskY; uint8_t * imageOutX = imageOutY; const uint8_t * imageMaskXEnd = imageMaskX + width; for ( ; imageMaskX != imageMaskXEnd; ++imageMaskX, ++imageOutX ) { if ( *imageMaskX == 0 ) { *imageOutX = 1; } } } } void ReplaceColorId( Image & image, const uint8_t oldColorId, const uint8_t newColorId ) { if ( image.empty() ) { return; } uint8_t * data = image.image(); const uint8_t * dataEnd = data + image.width() * image.height(); for ( ; data != dataEnd; ++data ) { if ( *data == oldColorId ) { *data = newColorId; } } } void ReplaceColorIdByTransformId( Image & image, const uint8_t colorId, const uint8_t transformId ) { if ( transformId > 15 || image.singleLayer() ) { return; } const int32_t width = image.width(); const int32_t height = image.height(); const uint8_t * imageIn = image.image(); uint8_t * transformIn = image.transform(); const uint8_t * imageInEnd = imageIn + height * width; for ( ; imageIn != imageInEnd; ++imageIn, ++transformIn ) { if ( *transformIn == 0 && *imageIn == colorId ) { // modify pixels with transform value 0 *transformIn = transformId; } } } void ReplaceTransformIdByColorId( Image & image, const uint8_t transformId, const uint8_t colorId ) { if ( image.empty() || image.singleLayer() ) { return; } const int32_t size = image.width() * image.height(); uint8_t * imageIn = image.image(); uint8_t * transformIn = image.transform(); const uint8_t * imageInEnd = imageIn + size; for ( ; imageIn != imageInEnd; ++imageIn, ++transformIn ) { if ( *transformIn == transformId ) { *transformIn = 0U; *imageIn = colorId; } } } void Resize( const Image & in, Image & out ) { if ( in.empty() || out.empty() ) { return; } Resize( in, 0, 0, in.width(), in.height(), out, 0, 0, out.width(), out.height() ); } void Resize( const Image & in, const int32_t inX, const int32_t inY, const int32_t widthRoiIn, const int32_t heightRoiIn, Image & out, const int32_t outX, const int32_t outY, const int32_t widthRoiOut, const int32_t heightRoiOut ) { if ( !Validate( in, inX, inY, widthRoiIn, heightRoiIn ) || !Validate( out, outX, outY, widthRoiOut, heightRoiOut ) ) { return; } if ( widthRoiIn == widthRoiOut && heightRoiIn == heightRoiOut ) { Copy( in, inX, inY, out, outX, outY, widthRoiIn, heightRoiIn ); return; } const int32_t widthIn = in.width(); const int32_t widthOut = out.width(); const int32_t offsetInY = inY * widthIn + inX; const int32_t offsetOutY = outY * widthOut + outX; const uint8_t * imageInY = in.image() + offsetInY; uint8_t * imageOutY = out.image() + offsetOutY; const uint8_t * imageOutYEnd = imageOutY + static_cast( widthOut ) * heightRoiOut; int32_t idY = 0; // Pre-calculation of X position std::vector positionX( widthRoiOut ); for ( int32_t x = 0; x < widthRoiOut; ++x ) { positionX[x] = ( x * widthRoiIn ) / widthRoiOut; } if ( in.singleLayer() ) { if ( !out.singleLayer() ) { // In this case we make the output image fully non-transparent in the given output area. uint8_t * transformY = out.transform() + static_cast( outY ) * widthOut + outX; const uint8_t * transformYEnd = transformY + static_cast( heightRoiOut ) * widthOut; for ( ; transformY != transformYEnd; transformY += widthOut ) { memset( transformY, static_cast( 0 ), widthRoiOut ); } } for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, ++idY ) { uint8_t * imageOutX = imageOutY; const int32_t offset = ( ( idY * heightRoiIn ) / heightRoiOut ) * widthIn; const uint8_t * imageInX = imageInY + offset; for ( const int32_t posX : positionX ) { *imageOutX = *( imageInX + posX ); ++imageOutX; } } } else if ( out.singleLayer() ) { const uint8_t * transformInY = in.transform() + offsetInY; for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, ++idY ) { uint8_t * imageOutX = imageOutY; const int32_t offset = ( ( idY * heightRoiIn ) / heightRoiOut ) * widthIn; const uint8_t * imageInX = imageInY + offset; const uint8_t * transformInX = transformInY + offset; for ( const int32_t posX : positionX ) { const uint8_t * transformIn = transformInX + posX; if ( *transformIn > 0 ) { if ( *transformIn != 1 ) { // Apply a transformation. *imageOutX = *( transformTable + static_cast( *transformIn ) * 256 + *imageOutX ); } } else { *imageOutX = *( imageInX + posX ); } ++imageOutX; } } } else { // Both 'in' and 'out' are double-layer. const uint8_t * transformInY = in.transform() + offsetInY; uint8_t * transformOutY = out.transform() + offsetOutY; for ( ; imageOutY != imageOutYEnd; imageOutY += widthOut, transformOutY += widthOut, ++idY ) { uint8_t * imageOutX = imageOutY; uint8_t * transformOutX = transformOutY; const int32_t offset = ( ( idY * heightRoiIn ) / heightRoiOut ) * widthIn; const uint8_t * imageInX = imageInY + offset; const uint8_t * transformInX = transformInY + offset; for ( const int32_t posX : positionX ) { *imageOutX = *( imageInX + posX ); *transformOutX = *( transformInX + posX ); ++imageOutX; ++transformOutX; } } } } void SetPixel( Image & image, const int32_t x, const int32_t y, const uint8_t value ) { if ( image.empty() || x >= image.width() || y >= image.height() || x < 0 || y < 0 ) { return; } const int32_t offset = y * image.width() + x; *( image.image() + offset ) = value; if ( !image.singleLayer() ) { *( image.transform() + offset ) = 0; } } void SetPixel( Image & image, const std::vector & points, const uint8_t value ) { if ( image.empty() ) { return; } const int32_t width = image.width(); const int32_t height = image.height(); const bool isDoubleLayer = !image.singleLayer(); for ( const Point & point : points ) { if ( point.x >= width || point.y >= height || point.x < 0 || point.y < 0 ) { continue; } const int32_t offset = point.y * width + point.x; *( image.image() + offset ) = value; if ( isDoubleLayer ) { *( image.transform() + offset ) = 0; } } } void SetTransformPixel( Image & image, const int32_t x, const int32_t y, const uint8_t value ) { if ( image.empty() || image.singleLayer() || x >= image.width() || y >= image.height() || x < 0 || y < 0 ) { return; } const int32_t offset = y * image.width() + x; *( image.image() + offset ) = 0; *( image.transform() + offset ) = value; } Image Stretch( const Image & in, int32_t inX, int32_t inY, int32_t widthIn, int32_t heightIn, const int32_t widthOut, const int32_t heightOut ) { if ( !Validate( in, inX, inY, widthIn, heightIn ) || widthOut <= 0 || heightOut <= 0 ) { return {}; } Image out; if ( in.singleLayer() ) { out._disableTransformLayer(); } out.resize( widthOut, heightOut ); const int32_t minWidth = widthIn < widthOut ? widthIn : widthOut; const int32_t minHeight = heightIn < heightOut ? heightIn : heightOut; const int32_t cornerWidth = minWidth / 3; const int32_t cornerHeight = minHeight / 3; const int32_t cornerX = inX + ( widthIn - cornerWidth ) / 2; const int32_t cornerY = inY + ( heightIn - cornerHeight ) / 2; const int32_t bodyWidth = minWidth - 2 * cornerWidth; const int32_t bodyHeight = minHeight - 2 * cornerHeight; const int32_t outX = ( widthOut - ( widthOut / bodyWidth ) * bodyWidth ) / 2; const int32_t outY = ( heightOut - ( heightOut / bodyHeight ) * bodyHeight ) / 2; // Create internal area if ( bodyWidth < widthOut && bodyHeight < heightOut ) { for ( int32_t y = 0; y < ( heightOut / bodyHeight ); ++y ) { for ( int32_t x = 0; x < ( widthOut / bodyWidth ); ++x ) { Copy( in, cornerX, cornerY, out, outX + x * bodyWidth, outY + y * bodyHeight, bodyWidth, bodyHeight ); } } } // Create sides // top and bottom side for ( int32_t x = 0; x < ( widthOut / bodyWidth ); ++x ) { const int32_t offsetX = outX + x * bodyWidth; Copy( in, cornerX, inY, out, offsetX, 0, bodyWidth, cornerHeight ); Copy( in, cornerX, inY + heightIn - cornerHeight, out, offsetX, heightOut - cornerHeight, bodyWidth, cornerHeight ); } // left and right sides for ( int32_t y = 0; y < ( heightOut / bodyHeight ); ++y ) { const int32_t offsetY = outY + y * bodyHeight; Copy( in, inX, cornerY, out, 0, offsetY, cornerWidth, bodyHeight ); Copy( in, inX + widthIn - cornerWidth, cornerY, out, widthOut - cornerWidth, offsetY, cornerWidth, bodyHeight ); } // Create corners // top-left corner Copy( in, inX, inY, out, 0, 0, cornerWidth, cornerHeight ); // top-right corner Copy( in, inX + widthIn - cornerWidth, inY, out, widthOut - cornerWidth, 0, cornerWidth, cornerHeight ); // bottom-left corner Copy( in, inX, inY + heightIn - cornerHeight, out, 0, heightOut - cornerHeight, cornerWidth, cornerHeight ); // bottom-right corner Copy( in, inX + widthIn - cornerWidth, inY + heightIn - cornerHeight, out, widthOut - cornerWidth, heightOut - cornerHeight, cornerWidth, cornerHeight ); return out; } void SubpixelResize( const Image & in, Image & out ) { if ( in.empty() || out.empty() ) { return; } SubpixelResize( in, 0, 0, in.width(), in.height(), out, 0, 0, out.width(), out.height() ); } void SubpixelResize( const Image & in, const int32_t inX, const int32_t inY, const int32_t widthRoiIn, const int32_t heightRoiIn, Image & out, const int32_t outX, const int32_t outY, const int32_t widthRoiOut, const int32_t heightRoiOut ) { if ( !Validate( in, inX, inY, widthRoiIn, heightRoiIn ) || !Validate( out, outX, outY, widthRoiOut, heightRoiOut ) ) { return; } if ( widthRoiIn == widthRoiOut && heightRoiIn == heightRoiOut ) { Copy( in, inX, inY, out, outX, outY, widthRoiIn, heightRoiIn ); return; } const int32_t widthIn = in.width(); const int32_t widthOut = out.width(); const int32_t offsetInY = inY * widthIn + inX; const int32_t offsetOutY = outY * widthOut + outX; const uint8_t * imageInY = in.image() + offsetInY; uint8_t * imageOutY = out.image() + offsetOutY; std::vector positionX( widthRoiOut ); for ( int32_t x = 0; x < widthRoiOut; ++x ) { positionX[x] = static_cast( x * widthRoiIn ) / widthRoiOut; } const uint8_t * gamePalette = getGamePalette(); if ( in.singleLayer() ) { if ( !out.singleLayer() ) { // In this case we make the output image fully non-transparent in the given output area. uint8_t * transformY = out.transform() + static_cast( outY ) * widthOut + outX; const uint8_t * transformYEnd = transformY + static_cast( heightRoiOut ) * widthOut; for ( ; transformY != transformYEnd; transformY += widthOut ) { memset( transformY, static_cast( 0 ), widthRoiOut ); } } for ( int32_t y = 0; y < heightRoiOut; ++y, imageOutY += widthOut ) { const double posY = static_cast( y * heightRoiIn ) / heightRoiOut; const int32_t startY = static_cast( posY ) * widthIn; const double coeffY = posY - static_cast( posY ); uint8_t * imageOutX = imageOutY; for ( int32_t x = 0; x < widthRoiOut; ++x, ++imageOutX ) { const double posX = positionX[x]; const int32_t startX = static_cast( posX ); const int32_t offsetIn = startY + startX; const uint8_t * imageInX = imageInY + offsetIn; if ( posX < widthRoiIn - 1 && posY < heightRoiIn - 1 ) { const double coeffX = posX - startX; const double coeff1 = ( 1 - coeffX ) * ( 1 - coeffY ); const double coeff2 = coeffX * ( 1 - coeffY ); const double coeff3 = ( 1 - coeffX ) * coeffY; const double coeff4 = coeffX * coeffY; const uint8_t * id1 = gamePalette + static_cast( *imageInX ) * 3; const uint8_t * id2 = gamePalette + static_cast( *( imageInX + 1 ) ) * 3; const uint8_t * id3 = gamePalette + static_cast( *( imageInX + widthIn ) ) * 3; const uint8_t * id4 = gamePalette + static_cast( *( imageInX + widthIn + 1 ) ) * 3; const double red = *id1 * coeff1 + *id2 * coeff2 + *id3 * coeff3 + *id4 * coeff4 + 0.5; const double green = *( id1 + 1 ) * coeff1 + *( id2 + 1 ) * coeff2 + *( id3 + 1 ) * coeff3 + *( id4 + 1 ) * coeff4 + 0.5; const double blue = *( id1 + 2 ) * coeff1 + *( id2 + 2 ) * coeff2 + *( id3 + 2 ) * coeff3 + *( id4 + 2 ) * coeff4 + 0.5; *imageOutX = GetPALColorId( static_cast( red ), static_cast( green ), static_cast( blue ) ); } else { *imageOutX = *imageInX; } } } } else { const uint8_t * transformInY = in.transform() + offsetInY; const bool isOutNotSingleLayer = !out.singleLayer(); uint8_t * transformOutY = isOutNotSingleLayer ? ( out.transform() + offsetOutY ) : nullptr; for ( int32_t y = 0; y < heightRoiOut; ++y, imageOutY += widthOut ) { const double posY = static_cast( y * heightRoiIn ) / heightRoiOut; const int32_t startY = static_cast( posY ) * widthIn; const double coeffY = posY - static_cast( posY ); uint8_t * imageOutX = imageOutY; uint8_t * transformOutX = transformOutY; for ( int32_t x = 0; x < widthRoiOut; ++x, ++imageOutX ) { const double posX = positionX[x]; const int32_t startX = static_cast( posX ); const int32_t offsetIn = startY + startX; const uint8_t * imageInX = imageInY + offsetIn; const uint8_t * transformInX = transformInY + offsetIn; if ( posX < widthIn - 1 && posY < heightRoiIn - 1 && *transformInX == 0 && *( transformInX + 1 ) == 0 && *( transformInX + widthRoiIn ) == 0 && *( transformInX + widthRoiIn + 1 ) == 0 ) { const double coeffX = posX - startX; const double coeff1 = ( 1 - coeffX ) * ( 1 - coeffY ); const double coeff2 = coeffX * ( 1 - coeffY ); const double coeff3 = ( 1 - coeffX ) * coeffY; const double coeff4 = coeffX * coeffY; const uint8_t * id1 = gamePalette + static_cast( *imageInX ) * 3; const uint8_t * id2 = gamePalette + static_cast( *( imageInX + 1 ) ) * 3; const uint8_t * id3 = gamePalette + static_cast( *( imageInX + widthIn ) ) * 3; const uint8_t * id4 = gamePalette + static_cast( *( imageInX + widthIn + 1 ) ) * 3; const double red = *id1 * coeff1 + *id2 * coeff2 + *id3 * coeff3 + *id4 * coeff4 + 0.5; const double green = *( id1 + 1 ) * coeff1 + *( id2 + 1 ) * coeff2 + *( id3 + 1 ) * coeff3 + *( id4 + 1 ) * coeff4 + 0.5; const double blue = *( id1 + 2 ) * coeff1 + *( id2 + 2 ) * coeff2 + *( id3 + 2 ) * coeff3 + *( id4 + 2 ) * coeff4 + 0.5; *imageOutX = GetPALColorId( static_cast( red ), static_cast( green ), static_cast( blue ) ); } else { if ( isOutNotSingleLayer || *transformInX == 0 ) { // Output image is double-layer or single-layer with non-transparent current pixel. *imageOutX = *imageInX; } else if ( *transformInX != 1 ) { // Apply a transformation. *imageOutX = *( transformTable + static_cast( *transformInX ) * 256 + *imageOutX ); } } if ( isOutNotSingleLayer ) { *transformOutX = *transformInX; ++transformOutX; } } if ( isOutNotSingleLayer ) { transformOutY += widthOut; } } } } void Transpose( const Image & in, Image & out ) { assert( !out.empty() ); if ( in.empty() || in.width() != out.height() || in.height() != out.width() ) { out.reset(); return; } const int32_t width = in.width(); const int32_t height = in.height(); const uint8_t * imageInY = in.image(); const uint8_t * imageInYEnd = imageInY + width * height; uint8_t * imageOutX = out.image(); if ( in.singleLayer() ) { if ( out.singleLayer() ) { for ( ; imageInY != imageInYEnd; imageInY += width, ++imageOutX ) { const uint8_t * imageInX = imageInY; const uint8_t * imageInXEnd = imageInX + width; uint8_t * imageOutY = imageOutX; for ( ; imageInX != imageInXEnd; ++imageInX, imageOutY += height ) { *imageOutY = *imageInX; } } } else { uint8_t * transformOutX = out.transform(); for ( ; imageInY != imageInYEnd; imageInY += width, ++imageOutX, ++transformOutX ) { const uint8_t * imageInX = imageInY; const uint8_t * imageInXEnd = imageInX + width; uint8_t * imageOutY = imageOutX; uint8_t * transformOutY = transformOutX; for ( ; imageInX != imageInXEnd; ++imageInX, imageOutY += height, transformOutY += height ) { *imageOutY = *imageInX; *transformOutY = 0; } } } } else { const uint8_t * transformInY = in.transform(); if ( out.singleLayer() ) { for ( ; imageInY != imageInYEnd; imageInY += width, transformInY += width, ++imageOutX ) { const uint8_t * imageInX = imageInY; const uint8_t * imageInXEnd = imageInX + width; uint8_t * imageOutY = imageOutX; const uint8_t * transformInX = transformInY; for ( ; imageInX != imageInXEnd; ++imageInX, ++transformInX, imageOutY += height ) { // Copy image data only for non-transparent pixels. if ( *transformInX == 0 ) { *imageOutY = *imageInX; } } } } else { uint8_t * transformOutX = out.transform(); for ( ; imageInY != imageInYEnd; imageInY += width, transformInY += width, ++imageOutX, ++transformOutX ) { const uint8_t * imageInX = imageInY; const uint8_t * imageInXEnd = imageInX + width; uint8_t * imageOutY = imageOutX; const uint8_t * transformInX = transformInY; uint8_t * transformOutY = transformOutX; for ( ; imageInX != imageInXEnd; ++imageInX, ++transformInX, imageOutY += height, transformOutY += height ) { *imageOutY = *imageInX; *transformOutY = *transformInX; } } } } } void updateShadow( Image & image, const Point & shadowOffset, const uint8_t transformId, const bool connectCorners ) { const int32_t imageWidth = image.width(); const int32_t imageHeight = image.height(); if ( image.empty() || image.singleLayer() || ( std::abs( shadowOffset.x ) >= imageWidth ) || ( std::abs( shadowOffset.y ) >= imageHeight ) || shadowOffset == Point() ) { return; } const int32_t width = imageWidth - std::abs( shadowOffset.x ); const int32_t height = imageHeight - std::abs( shadowOffset.y ); const uint8_t * transformInY = image.transform(); uint8_t * transformOutY = image.transform(); int32_t cornerOffsetX; int32_t cornerOffsetY; if ( shadowOffset.x > 0 ) { transformOutY += shadowOffset.x; cornerOffsetX = 1; } else { transformInY -= shadowOffset.x; cornerOffsetX = -1; } if ( shadowOffset.y > 0 ) { transformOutY += imageWidth * shadowOffset.y; cornerOffsetY = imageWidth; } else { transformInY -= imageWidth * shadowOffset.y; cornerOffsetY = -imageWidth; } const uint8_t * transformOutYEnd = transformOutY + imageWidth * height; for ( ; transformOutY != transformOutYEnd; transformInY += imageWidth, transformOutY += imageWidth ) { const uint8_t * transformInX = transformInY; uint8_t * transformOutX = transformOutY; const uint8_t * transformOutXEnd = transformOutX + width; for ( ; transformOutX != transformOutXEnd; ++transformInX, ++transformOutX ) { if ( *transformOutX == 1 && ( *transformInX == 0 || ( connectCorners && *( transformInX + cornerOffsetX ) == 0 && *( transformInX + cornerOffsetY ) == 0 ) ) ) { // If 'connectCorners' is 'true' and when there are two pixels adjacent diagonally, // we also create a "shadow" pixel in the corner that is closer to the image. // Doing so there will be no "empty" pixels between the image and its shadow (for 1 pixel offset case). *transformOutX = transformId; } } } } } fheroes2-1.1.6+dfsg/src/engine/image.h000066400000000000000000000344221476115357100174610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include "math_base.h" namespace fheroes2 { // Image always contains an image layer and if image is not a single-layer then also a transform layer. // - image layer contains visible pixels which are copy to a destination image // - transform layer is used to apply some transformation to an image on which we draw the current one. For example, shadowing class Image { public: Image() = default; Image( const int32_t width_, const int32_t height_ ); Image( const Image & image_ ); Image( Image && image_ ) noexcept; virtual ~Image() = default; Image & operator=( const Image & image_ ); Image & operator=( Image && image_ ) noexcept; virtual void resize( const int32_t width_, const int32_t height_ ); // It's safe to cast to uint32_t as width and height are always >= 0 int32_t width() const { return _width; } int32_t height() const { return _height; } virtual uint8_t * image(); virtual const uint8_t * image() const; uint8_t * transform() { return _data.get() + width() * height(); } const uint8_t * transform() const { return _data.get() + width() * height(); } bool empty() const { return !_data; } void reset(); // makes image fully transparent (transform layer is set to 1) void clear(); // makes the image empty // Fill 'image' layer with given value, setting 'transform' layer to 0. void fill( const uint8_t value ); // This is an optional indicator for image processing functions. // The whole image still consists of 2 layers but transform layer might be ignored in computations bool singleLayer() const { return _singleLayer; } // BE CAREFUL! This method disables transform layer usage. Use only for display / video related images which are for end rendering purposes! // The name of this method starts from _ on purpose to do not mix with other public methods. void _disableTransformLayer() { _singleLayer = true; } private: void copy( const Image & image ); int32_t _width{ 0 }; int32_t _height{ 0 }; std::unique_ptr _data; // holds 2 image layers // Only for images which are not used for any other operations except displaying on screen. bool _singleLayer{ false }; }; class Sprite : public Image { public: Sprite() = default; Sprite( const int32_t width_, const int32_t height_, const int32_t x_ = 0, const int32_t y_ = 0 ); Sprite( const Image & image, const int32_t x_ = 0, const int32_t y_ = 0 ); Sprite( const Sprite & sprite ) = default; Sprite( Sprite && sprite ) noexcept; ~Sprite() override = default; Sprite & operator=( const Sprite & sprite ); Sprite & operator=( Sprite && sprite ) noexcept; int32_t x() const { return _x; } int32_t y() const { return _y; } virtual void setPosition( const int32_t x_, const int32_t y_ ); private: int32_t _x{ 0 }; int32_t _y{ 0 }; }; // This class is used in situations when we draw a window within another window class ImageRestorer { public: explicit ImageRestorer( Image & image ); ImageRestorer( Image & image, const int32_t x_, const int32_t y_, const int32_t width, const int32_t height ); ImageRestorer( const ImageRestorer & ) = delete; // Restores the original image if necessary, see the implementation for details ~ImageRestorer(); void update( const int32_t x_, const int32_t y_, const int32_t width, const int32_t height ); int32_t x() const { return _x; } int32_t y() const { return _y; } int32_t width() const { return _width; } int32_t height() const { return _height; } Rect rect() const { return { _x, _y, _width, _height }; } void restore(); void reset() { _isRestored = true; } private: Image & _image; Image _copy; int32_t _x{ 0 }; int32_t _y{ 0 }; int32_t _width{ 0 }; int32_t _height{ 0 }; void _updateRoi(); bool _isRestored{ false }; }; // Apply shadow that gradually reduces strength using 'in' image shape. Shadow is applied to the 'out' image. void addGradientShadow( const Sprite & in, Image & out, const Point & outPos, const Point & shadowOffset ); // Generates a new image with a shadow of the shape of existing image. Shadow must have only (-x, +y) offset. Sprite addShadow( const Sprite & in, const Point & shadowOffset, const uint8_t transformId ); // Replace a particular pixel value by transparency value (transform layer value will be 1) void AddTransparency( Image & image, const uint8_t valueToReplace ); // make sure that output image's transform layer doesn't have skipping values (transform == 1) void AlphaBlit( const Image & in, Image & out, const uint8_t alphaValue, const bool flip = false ); void AlphaBlit( const Image & in, Image & out, int32_t outX, int32_t outY, const uint8_t alphaValue, const bool flip = false ); void AlphaBlit( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const uint8_t alphaValue, const bool flip = false ); // apply palette only for image layer, it doesn't affect transform part void ApplyPalette( Image & image, const std::vector & palette ); void ApplyPalette( const Image & in, Image & out, const std::vector & palette ); void ApplyPalette( Image & image, const uint8_t paletteId ); void ApplyPalette( const Image & in, Image & out, const uint8_t paletteId ); void ApplyPalette( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, uint8_t paletteId ); void ApplyPalette( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const std::vector & palette ); void ApplyAlpha( const Image & in, Image & out, const uint8_t alpha ); void ApplyAlpha( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const uint8_t alpha ); void ApplyTransform( Image & image, int32_t x, int32_t y, int32_t width, int32_t height, const uint8_t transformId ); // draw one image onto another void Blit( const Image & in, Image & out, const bool flip = false ); void Blit( const Image & in, Image & out, const Rect & outRoi, const bool flip = false ); void Blit( const Image & in, Image & out, int32_t outX, int32_t outY, const bool flip = false ); void Blit( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const bool flip = false ); // inPos must contain non-negative values void Blit( const Image & in, const Point & inPos, Image & out, const Point & outPos, const Size & size, bool flip = false ); void Copy( const Image & in, Image & out ); void Copy( const Image & in, int32_t inX, int32_t inY, Image & out, const Rect & outRoi ); void Copy( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height ); // Copies transform the layer from in to out. Both images must be of the same size. void CopyTransformLayer( const Image & in, Image & out ); Sprite CreateContour( const Image & image, const uint8_t value ); // Make a transition to "in" image from left to right or vertically - from top to bottom using dithering (https://en.wikipedia.org/wiki/Dither). // The direction of transition can be reversed. void CreateDitheringTransition( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const bool isVertical, const bool isReverse ); Sprite Crop( const Image & image, int32_t x, int32_t y, int32_t width, int32_t height ); // skipFactor is responsible for non-solid line. You can interpret it as skip every N pixel void DrawBorder( Image & image, const uint8_t value, const uint32_t skipFactor = 0 ); // roi is an optional parameter when you need to draw in a small than image area void DrawLine( Image & image, const Point & start, const Point & end, const uint8_t value, const Rect & roi = Rect() ); void DrawRect( Image & image, const Rect & roi, const uint8_t value ); void DivideImageBySquares( const Point & spriteOffset, const Image & original, const int32_t squareSize, std::vector & outputSquareId, std::vector> & outputImageInfo ); // Every image in the array must be the same size. Make sure that pointers aren't nullptr! Image ExtractCommonPattern( const std::vector & input ); // Please use GetColorId function if you want to use an RGB value void Fill( Image & image, int32_t x, int32_t y, int32_t width, int32_t height, const uint8_t colorId ); void FillTransform( Image & image, int32_t x, int32_t y, int32_t width, int32_t height, const uint8_t transformId ); Image FilterOnePixelNoise( const Image & input ); bool FitToRoi( const Image & in, Point & inPos, const Image & out, Point & outPos, Size & outputSize, const Rect & outputRoi ); Image Flip( const Image & in, const bool horizontally, const bool vertically ); void Flip( const Image & in, int32_t inX, int32_t inY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height, const bool horizontally, const bool vertically ); // Return ROI with pixels which are not skipped and not used for shadow creation. 1 is to skip, 2 - 5 types of shadows Rect GetActiveROI( const Image & image, const uint8_t minTransformValue = 6 ); // Returns a closest color ID from the original game's palette uint8_t GetColorId( const uint8_t red, const uint8_t green, const uint8_t blue ); std::vector getTransformTable( const Image & in, const Image & out, int32_t x, int32_t y, int32_t width, int32_t height ); Sprite makeShadow( const Sprite & in, const Point & shadowOffset, const uint8_t transformId ); void MaskTransformLayer( const Image & mask, int32_t maskX, int32_t maskY, Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height ); // This function does NOT check transform layer. If you intent to replace few colors at the same image please use ApplyPalette to be more efficient. void ReplaceColorId( Image & image, const uint8_t oldColorId, const uint8_t newColorId ); // Use this function only when you need to convert pixel value into transform layer void ReplaceColorIdByTransformId( Image & image, const uint8_t colorId, const uint8_t transformId ); // Use this function only when you need to convert transform value into non-transparent pixel with the given color. void ReplaceTransformIdByColorId( Image & image, const uint8_t transformId, const uint8_t colorId ); void Resize( const Image & in, Image & out ); void Resize( const Image & in, const int32_t inX, const int32_t inY, const int32_t widthRoiIn, const int32_t heightRoiIn, Image & out, const int32_t outX, const int32_t outY, const int32_t widthRoiOut, const int32_t heightRoiOut ); // Please use value from the main palette only void SetPixel( Image & image, const int32_t x, const int32_t y, const uint8_t value ); void SetPixel( Image & image, const std::vector & points, const uint8_t value ); // Please set value not bigger than 13! void SetTransformPixel( Image & image, const int32_t x, const int32_t y, const uint8_t value ); Image Stretch( const Image & in, int32_t inX, int32_t inY, int32_t widthIn, int32_t heightIn, const int32_t widthOut, const int32_t heightOut ); void SubpixelResize( const Image & in, Image & out ); void SubpixelResize( const Image & in, const int32_t inX, const int32_t inY, const int32_t widthRoiIn, const int32_t heightRoiIn, Image & out, const int32_t outX, const int32_t outY, const int32_t widthRoiOut, const int32_t heightRoiOut ); void Transpose( const Image & in, Image & out ); void updateShadow( Image & image, const Point & shadowOffset, const uint8_t transformId, const bool connectCorners ); } fheroes2-1.1.6+dfsg/src/engine/image_palette.cpp000066400000000000000000000171321476115357100215310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include "image_palette.h" namespace { const size_t paletteSize = 768; struct PaletteHolder { public: static PaletteHolder & instance() { static PaletteHolder paletteHolder; return paletteHolder; } std::array gamePalette; private: PaletteHolder() { // This is a temporary palette which is used ONLY for cursor and game startup error message. A real palette must be loaded from AGG file. gamePalette = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x35, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x1f, 0x1c, 0x1c, 0x1c, 0x1a, 0x1a, 0x1a, 0x17, 0x17, 0x17, 0x15, 0x15, 0x15, 0x12, 0x12, 0x12, 0x10, 0x10, 0x10, 0x0e, 0x0e, 0x0e, 0x0b, 0x0b, 0x0b, 0x09, 0x09, 0x09, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x3f, 0x3b, 0x37, 0x3c, 0x37, 0x32, 0x3a, 0x34, 0x2e, 0x38, 0x31, 0x2a, 0x36, 0x2e, 0x26, 0x34, 0x2a, 0x22, 0x32, 0x28, 0x1e, 0x30, 0x25, 0x1b, 0x2e, 0x22, 0x18, 0x2b, 0x1f, 0x15, 0x29, 0x1c, 0x12, 0x27, 0x1a, 0x0f, 0x25, 0x18, 0x0d, 0x23, 0x15, 0x0b, 0x21, 0x13, 0x08, 0x1f, 0x11, 0x07, 0x1d, 0x0f, 0x05, 0x1a, 0x0d, 0x04, 0x18, 0x0c, 0x03, 0x16, 0x0a, 0x02, 0x14, 0x09, 0x01, 0x12, 0x07, 0x01, 0x0f, 0x06, 0x00, 0x0d, 0x05, 0x00, 0x0b, 0x04, 0x00, 0x09, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3d, 0x34, 0x3e, 0x3a, 0x2b, 0x3d, 0x38, 0x23, 0x00, 0x00, 0x00, 0x3b, 0x35, 0x14, 0x3a, 0x33, 0x0d, 0x39, 0x32, 0x05, 0x38, 0x31, 0x00, 0x36, 0x2f, 0x08, 0x34, 0x2c, 0x07, 0x32, 0x28, 0x06, 0x2f, 0x26, 0x06, 0x2d, 0x23, 0x06, 0x2a, 0x1f, 0x05, 0x27, 0x1c, 0x04, 0x25, 0x19, 0x03, 0x22, 0x16, 0x03, 0x1f, 0x13, 0x02, 0x1d, 0x11, 0x02, 0x1a, 0x0f, 0x00, 0x18, 0x0c, 0x00, 0x15, 0x0a, 0x00, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x39, 0x27, 0x3e, 0x36, 0x23, 0x3d, 0x34, 0x1f, 0x3c, 0x31, 0x1c, 0x3b, 0x2e, 0x18, 0x3a, 0x2b, 0x14, 0x39, 0x28, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x12, 0x02, 0x20, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x12, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; } }; } namespace fheroes2 { const uint8_t * getGamePalette() { return PaletteHolder::instance().gamePalette.data(); } void setGamePalette( const std::vector & palette ) { assert( palette.size() == paletteSize ); if ( palette.size() != paletteSize ) { return; } std::copy_n( palette.begin(), paletteSize, PaletteHolder::instance().gamePalette.begin() ); } } fheroes2-1.1.6+dfsg/src/engine/image_palette.h000066400000000000000000000033251476115357100211750ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace fheroes2 { const uint8_t * getGamePalette(); // This function must be called only at the start of the application after loading AGG file content. void setGamePalette( const std::vector & palette ); } fheroes2-1.1.6+dfsg/src/engine/image_tool.cpp000066400000000000000000000407721476115357100210560ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wswitch-default" #endif #include #include #include #include #include #if defined( WITH_IMAGE ) #include #endif // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif #include "agg_file.h" #include "image_palette.h" #include "image_tool.h" #include "logging.h" #include "serialize.h" #include "system.h" namespace { bool isPNGFilePath( const std::string_view path ) { const std::string pngExtension( ".png" ); return path.size() >= pngExtension.size() && ( path.compare( path.size() - pngExtension.size(), pngExtension.size(), pngExtension ) == 0 ); } std::vector PALPalette() { const uint8_t * gamePalette = fheroes2::getGamePalette(); std::vector palette( 256 * 3 ); for ( size_t i = 0; i < palette.size(); ++i ) { palette[i] = gamePalette[i] << 2; } return palette; } #if defined( WITH_IMAGE ) bool SaveImage( const fheroes2::Image & image, const std::string & path ) #else bool SaveImage( const fheroes2::Image & image, std::string path ) #endif { const std::vector & palette = PALPalette(); const uint8_t * currentPalette = palette.data(); const int32_t width = image.width(); const int32_t height = image.height(); const std::unique_ptr surface( SDL_CreateRGBSurface( 0, width, height, 8, 0, 0, 0, 0 ), SDL_FreeSurface ); if ( !surface ) { ERROR_LOG( "Error while creating a SDL surface for an image to be saved under " << path << ". Error " << SDL_GetError() ) return false; } assert( surface->format->BitsPerPixel == 8 ); std::vector paletteSDL; paletteSDL.resize( 256 ); for ( int32_t i = 0; i < 256; ++i ) { const uint8_t * value = currentPalette + i * 3; SDL_Color & col = paletteSDL[i]; col.r = *value; col.g = *( value + 1 ); col.b = *( value + 2 ); col.a = 255; } SDL_SetPaletteColors( surface->format->palette, paletteSDL.data(), 0, 256 ); if ( surface->pitch != width ) { const uint8_t * imageIn = image.image(); for ( int32_t i = 0; i < height; ++i ) { memcpy( static_cast( surface->pixels ) + surface->pitch * i, imageIn + width * i, static_cast( width ) ); } } else { memcpy( surface->pixels, image.image(), static_cast( width * height ) ); } #if defined( WITH_IMAGE ) int res = 0; if ( isPNGFilePath( path ) ) { res = IMG_SavePNG( surface.get(), System::encLocalToUTF8( path ).c_str() ); } else { res = SDL_SaveBMP( surface.get(), System::encLocalToUTF8( path ).c_str() ); } #else if ( isPNGFilePath( path ) ) { memcpy( path.data() + path.size() - 3, "bmp", 3 ); } const int res = SDL_SaveBMP( surface.get(), System::encLocalToUTF8( path ).c_str() ); #endif return res == 0; } } namespace fheroes2 { bool Save( const Image & image, const std::string & path, const uint8_t background ) { if ( image.empty() || path.empty() ) return false; Image temp( image.width(), image.height() ); temp.fill( background ); Blit( image, temp ); return SaveImage( temp, path ); } bool Save( const Image & image, const std::string & path ) { if ( image.empty() || path.empty() ) return false; return SaveImage( image, path ); } bool Load( const std::string & path, Image & image ) { if ( image.singleLayer() ) { // Output image should be double-layer! assert( 0 ); return false; } std::unique_ptr surface( nullptr, SDL_FreeSurface ); std::unique_ptr loadedSurface( nullptr, SDL_FreeSurface ); #if defined( WITH_IMAGE ) loadedSurface.reset( IMG_Load( System::encLocalToUTF8( path ).c_str() ) ); #else loadedSurface.reset( SDL_LoadBMP( System::encLocalToUTF8( path ).c_str() ) ); #endif if ( !loadedSurface ) { return false; } // SDL_PIXELFORMAT_BGRA32 and other RGBA color variants are only supported starting with SDL 2.0.5 #if !SDL_VERSION_ATLEAST( 2, 0, 5 ) #error Minimal supported SDL version is 2.0.5. #endif // Image loading functions can theoretically return SDL_Surface in any supported color format, so we will convert it to a specific format for subsequent // processing const std::unique_ptr pixelFormat( SDL_AllocFormat( SDL_PIXELFORMAT_BGRA32 ), SDL_FreeFormat ); if ( !pixelFormat ) { return false; } surface.reset( SDL_ConvertSurface( loadedSurface.get(), pixelFormat.get(), 0 ) ); if ( !surface ) { return false; } assert( SDL_MUSTLOCK( surface.get() ) == SDL_FALSE && surface->format->BytesPerPixel == 4 ); image.resize( surface->w, surface->h ); image.reset(); const uint8_t * inY = static_cast( surface->pixels ); uint8_t * outY = image.image(); uint8_t * transformY = image.transform(); const uint8_t * inYEnd = inY + surface->h * surface->pitch; for ( ; inY != inYEnd; inY += surface->pitch, outY += surface->w, transformY += surface->w ) { const uint8_t * inX = inY; uint8_t * outX = outY; uint8_t * transformX = transformY; const uint8_t * inXEnd = inX + surface->w * 4; for ( ; inX != inXEnd; inX += 4, ++outX, ++transformX ) { const uint8_t alpha = *( inX + 3 ); if ( alpha < 255 ) { if ( alpha == 0 ) { *outX = 0; *transformX = 1; } else if ( *inX == 0 && *( inX + 1 ) == 0 && *( inX + 2 ) == 0 ) { *outX = 0; *transformX = 2; } else { *outX = GetColorId( *( inX + 2 ), *( inX + 1 ), *inX ); *transformX = 0; } } else { *outX = GetColorId( *( inX + 2 ), *( inX + 1 ), *inX ); *transformX = 0; } } } return true; } Sprite decodeICNSprite( const uint8_t * data, const uint8_t * dataEnd, const ICNHeader & icnHeader ) { Sprite sprite( icnHeader.width, icnHeader.height, icnHeader.offsetX, icnHeader.offsetY ); sprite.reset(); uint8_t * imageTransform = sprite.transform(); uint32_t posX = 0; // The need for a transform layer can only be determined during ICN decoding. bool noTransformLayer = true; // When the 6th bit in animationFrames is set then it is Monochromatic ICN image. const bool isMonochromatic = ( icnHeader.animationFrames & 0x20 ); if ( isMonochromatic ) { while ( data < dataEnd ) { if ( *data == 0 ) { // 0x00 - end of row reached, go to the first pixel of next row. noTransformLayer = noTransformLayer && ( static_cast( posX ) >= icnHeader.width ); imageTransform += icnHeader.width; posX = 0; ++data; } else if ( *data < 0x80 ) { // 0x01-0x7F - number of black pixels. // Image data is all already set to 0. Just set transform layer to 0. const uint8_t pixelCount = *data; memset( imageTransform + posX, static_cast( 0 ), pixelCount ); ++data; posX += pixelCount; } else if ( *data == 0x80 ) { // 0x80 - end of image. break; } else { // 0x81 to 0xFF - number of empty (transparent) pixels + 0x80. // The (n - 128) pixels are transparent. noTransformLayer = false; posX += *data - 0x80; ++data; } } } else { uint8_t * imageData = sprite.image(); while ( data < dataEnd ) { if ( *data == 0 ) { // 0x00 - end of row reached, go to the first pixel of next row. // All of remaining pixels of current line are transparent. noTransformLayer = noTransformLayer && ( static_cast( posX ) >= icnHeader.width ); imageData += icnHeader.width; imageTransform += icnHeader.width; posX = 0; ++data; } else if ( *data < 0x80 ) { // 0x01-0x7F - number N of sprite pixels. // The next N bytes are the colors of the next N pixels. const uint8_t pixelCount = *data; ++data; if ( data + pixelCount > dataEnd ) { // Image data is corrupted - we can not read data beyond dataEnd. break; } memcpy( imageData + posX, data, pixelCount ); memset( imageTransform + posX, static_cast( 0 ), pixelCount ); data += pixelCount; posX += pixelCount; } else if ( *data == 0x80 ) { // 0x80 - end of image noTransformLayer = noTransformLayer && ( static_cast( posX ) >= icnHeader.width ); break; } else if ( *data < 0xC0 ) { // 0x81 to 0xBF - number of empty (transparent) pixels + 0x80. The (n - 128) pixels are transparent. noTransformLayer = false; posX += *data - 0x80; ++data; } else if ( *data == 0xC0 ) { // 0xC0 - put here N transform layer pixels. // If the next byte modulo 4 is not null, N equals the next byte modulo 4, // otherwise N equals the second next byte. noTransformLayer = false; ++data; const uint8_t transformValue = *data; const uint32_t countValue = transformValue & 0x03; const uint32_t pixelCount = ( countValue != 0 ) ? countValue : *( ++data ); if ( transformValue & 0x40 ) { // Transform layer data types: // 0 - no transparency, // 1 - full transparency (to skip image data), // from 5 (light) to 2 (strong) - for darkening, // from 10 (light) to 6 (strong) - for lightening const uint8_t transformType = static_cast( ( ( transformValue & 0x3C ) >> 2 ) + 2 ); if ( transformType < 16 ) { memset( imageTransform + posX, transformType, pixelCount ); } } // TODO: Use ( transformValue & 0x80 ) to detect and store shining contour data bit. // It is used for units on the Battlefield and for icons in the View World. posX += pixelCount; ++data; } else { // 0xC1 - next byte stores the number of next pixels of same color, or // 0xC2 to 0xFF - the number of pixels of same color plus 0xC0. // Next byte is the color of these pixels. const uint32_t pixelCount = ( *data == 0xC1 ) ? *( ++data ) : *data - 0xC0; ++data; memset( imageData + posX, *data, pixelCount ); memset( imageTransform + posX, static_cast( 0 ), pixelCount ); posX += pixelCount; ++data; } } } if ( noTransformLayer ) { sprite._disableTransformLayer(); } return sprite; } void decodeTILImages( const uint8_t * data, const size_t imageCount, const int32_t width, const int32_t height, std::vector & output ) { assert( data != nullptr && imageCount > 0 && width > 0 && height > 0 ); output.resize( imageCount ); const size_t imageSize = static_cast( width ) * height; for ( size_t i = 0; i < imageCount; ++i ) { Image & tilImage = output[i]; tilImage._disableTransformLayer(); tilImage.resize( width, height ); memcpy( tilImage.image(), data + i * imageSize, imageSize ); } } Sprite decodeBMPFile( const std::vector & data ) { if ( data.size() < 6 ) { // It is an invalid BMP file. return {}; } ROStreamBuf imageStream( data ); const uint8_t blackColor = imageStream.get(); const uint8_t whiteColor = 11; // Skip the second byte imageStream.get(); const int32_t width = imageStream.getLE16(); const int32_t height = imageStream.getLE16(); if ( static_cast( data.size() ) != 6 + width * height ) { // It is an invalid BMP file. return {}; } fheroes2::Sprite output( width, height ); const uint8_t * input = data.data() + 6; uint8_t * image = output.image(); const uint8_t * imageEnd = image + static_cast( width ) * height; uint8_t * transform = output.transform(); for ( ; image != imageEnd; ++image, ++transform, ++input ) { if ( *input == 1 ) { *image = whiteColor; *transform = 0; } else if ( *input == 2 ) { *image = blackColor; *transform = 0; } else { *transform = 1; } } return output; } bool isPNGFormatSupported() { #if defined( WITH_IMAGE ) return true; #else return false; #endif } } fheroes2-1.1.6+dfsg/src/engine/image_tool.h000066400000000000000000000045621476115357100205200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include "image.h" namespace fheroes2 { struct ICNHeader; bool Save( const Image & image, const std::string & path ); // Save an image into file. 'background' represents palette index from the original palette. Recommended value is 23. bool Save( const Image & image, const std::string & path, const uint8_t background ); bool Load( const std::string & path, Image & image ); Sprite decodeICNSprite( const uint8_t * data, const uint8_t * dataEnd, const ICNHeader & icnHeader ); void decodeTILImages( const uint8_t * data, const size_t imageCount, const int32_t width, const int32_t height, std::vector & output ); // BMP files within AGG are not Bitmap images! Sprite decodeBMPFile( const std::vector & data ); // By default only Bitmap (.bmp) format is supported. bool isPNGFormatSupported(); } fheroes2-1.1.6+dfsg/src/engine/localevent.cpp000066400000000000000000002152061476115357100210670ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2008 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "localevent.h" #include #include #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wswitch-default" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif #include "audio.h" #include "image.h" #include "logging.h" #include "math_tools.h" #include "render_processor.h" #include "screen.h" namespace { const uint32_t globalLoopSleepTime{ 1 }; // If such or more ms has passed after pressing the mouse button, then this is a long press. const uint32_t mouseButtonLongPressTimeout{ 850 }; char getCharacterFromPressedKey( const fheroes2::Key key, int32_t mod ) { if ( ( mod & fheroes2::KeyModifier::KEY_MODIFIER_SHIFT ) && ( mod & fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) ) { mod = mod & ~( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ); } switch ( key ) { case fheroes2::Key::KEY_1: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '!' : '1' ); case fheroes2::Key::KEY_2: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '@' : '2' ); case fheroes2::Key::KEY_3: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '#' : '3' ); case fheroes2::Key::KEY_4: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '$' : '4' ); case fheroes2::Key::KEY_5: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '%' : '5' ); case fheroes2::Key::KEY_6: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '^' : '6' ); case fheroes2::Key::KEY_7: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '&' : '7' ); case fheroes2::Key::KEY_8: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '*' : '8' ); case fheroes2::Key::KEY_9: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '(' : '9' ); case fheroes2::Key::KEY_0: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? ')' : '0' ); case fheroes2::Key::KEY_KP_0: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '0'; break; case fheroes2::Key::KEY_KP_1: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '1'; break; case fheroes2::Key::KEY_KP_2: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '2'; break; case fheroes2::Key::KEY_KP_3: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '3'; break; case fheroes2::Key::KEY_KP_4: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '4'; break; case fheroes2::Key::KEY_KP_5: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '5'; break; case fheroes2::Key::KEY_KP_6: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '6'; break; case fheroes2::Key::KEY_KP_7: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '7'; break; case fheroes2::Key::KEY_KP_8: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '8'; break; case fheroes2::Key::KEY_KP_9: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '9'; break; case fheroes2::Key::KEY_KP_PERIOD: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '.'; break; case fheroes2::Key::KEY_KP_DIVIDE: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '/'; break; case fheroes2::Key::KEY_KP_MULTIPLY: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '*'; break; case fheroes2::Key::KEY_KP_MINUS: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '-'; break; case fheroes2::Key::KEY_KP_PLUS: if ( fheroes2::KeyModifier::KEY_MODIFIER_NUM & mod ) return '+'; break; case fheroes2::Key::KEY_MINUS: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '_' : '-' ); case fheroes2::Key::KEY_EQUALS: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '+' : '=' ); case fheroes2::Key::KEY_BACKSLASH: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '|' : '\\' ); case fheroes2::Key::KEY_LEFT_BRACKET: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '{' : '[' ); case fheroes2::Key::KEY_RIGHT_BRACKET: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '}' : ']' ); case fheroes2::Key::KEY_SEMICOLON: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? ':' : ';' ); case fheroes2::Key::KEY_QUOTE: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '"' : '\'' ); case fheroes2::Key::KEY_COMMA: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '<' : ',' ); case fheroes2::Key::KEY_PERIOD: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '>' : '.' ); case fheroes2::Key::KEY_SLASH: return ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT & mod ? '?' : '/' ); case fheroes2::Key::KEY_EXCLAIM: return '!'; case fheroes2::Key::KEY_AT: return '@'; case fheroes2::Key::KEY_HASH: return '#'; case fheroes2::Key::KEY_DOLLAR: return '$'; case fheroes2::Key::KEY_AMPERSAND: return '&'; case fheroes2::Key::KEY_ASTERISK: return '*'; case fheroes2::Key::KEY_LEFT_PARENTHESIS: return '('; case fheroes2::Key::KEY_RIGHT_PARENTHESIS: return ')'; case fheroes2::Key::KEY_DOUBLE_QUOTE: return '"'; case fheroes2::Key::KEY_PLUS: return '+'; case fheroes2::Key::KEY_COLON: return ':'; case fheroes2::Key::KEY_LESS: return '<'; case fheroes2::Key::KEY_GREATER: return '>'; case fheroes2::Key::KEY_QUESTION: return '?'; case fheroes2::Key::KEY_CARET: return '^'; case fheroes2::Key::KEY_UNDERSCORE: return '_'; case fheroes2::Key::KEY_SPACE: return ' '; case fheroes2::Key::KEY_A: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'A' : 'a' ); case fheroes2::Key::KEY_B: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'B' : 'b' ); case fheroes2::Key::KEY_C: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'C' : 'c' ); case fheroes2::Key::KEY_D: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'D' : 'd' ); case fheroes2::Key::KEY_E: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'E' : 'e' ); case fheroes2::Key::KEY_F: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'F' : 'f' ); case fheroes2::Key::KEY_G: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'G' : 'g' ); case fheroes2::Key::KEY_H: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'H' : 'h' ); case fheroes2::Key::KEY_I: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'I' : 'i' ); case fheroes2::Key::KEY_J: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'J' : 'j' ); case fheroes2::Key::KEY_K: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'K' : 'k' ); case fheroes2::Key::KEY_L: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'L' : 'l' ); case fheroes2::Key::KEY_M: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'M' : 'm' ); case fheroes2::Key::KEY_N: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'N' : 'n' ); case fheroes2::Key::KEY_O: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'O' : 'o' ); case fheroes2::Key::KEY_P: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'P' : 'p' ); case fheroes2::Key::KEY_Q: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'Q' : 'q' ); case fheroes2::Key::KEY_R: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'R' : 'r' ); case fheroes2::Key::KEY_S: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'S' : 's' ); case fheroes2::Key::KEY_T: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'T' : 't' ); case fheroes2::Key::KEY_U: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'U' : 'u' ); case fheroes2::Key::KEY_V: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'V' : 'v' ); case fheroes2::Key::KEY_W: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'W' : 'w' ); case fheroes2::Key::KEY_X: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'X' : 'x' ); case fheroes2::Key::KEY_Y: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'Y' : 'y' ); case fheroes2::Key::KEY_Z: return ( ( fheroes2::KeyModifier::KEY_MODIFIER_SHIFT | fheroes2::KeyModifier::KEY_MODIFIER_CAPS ) & mod ? 'Z' : 'z' ); default: break; } return 0; } } namespace EventProcessing { std::set eventTypeStatus; class EventEngine { public: static void initEvents() { // The list below is based on event types which require >= SDL 2.0.5. Is there a reason why you want to compile with an older SDL version? #if !SDL_VERSION_ATLEAST( 2, 0, 5 ) #error Minimal supported SDL version is 2.0.5. #endif // Full list of events and their requirements can be found at https://wiki.libsdl.org/SDL_EventType setEventProcessingState( SDL_QUIT, true ); // This is a very serious situation and we should handle it. setEventProcessingState( SDL_APP_LOWMEMORY, true ); setEventProcessingState( SDL_WINDOWEVENT, true ); setEventProcessingState( SDL_KEYDOWN, true ); setEventProcessingState( SDL_KEYUP, true ); // SDL_TEXTINPUT and SDL_TEXTEDITING are enabled and disabled by SDL_StartTextInput() and SDL_StopTextInput() functions. // Do not enable them here. setEventProcessingState( SDL_TEXTEDITING, false ); setEventProcessingState( SDL_TEXTINPUT, false ); setEventProcessingState( SDL_KEYMAPCHANGED, false ); // supported from SDL 2.0.4 setEventProcessingState( SDL_MOUSEMOTION, true ); setEventProcessingState( SDL_MOUSEBUTTONDOWN, true ); setEventProcessingState( SDL_MOUSEBUTTONUP, true ); setEventProcessingState( SDL_MOUSEWHEEL, true ); setEventProcessingState( SDL_JOYAXISMOTION, true ); setEventProcessingState( SDL_JOYBALLMOTION, true ); setEventProcessingState( SDL_JOYHATMOTION, true ); setEventProcessingState( SDL_JOYBUTTONDOWN, true ); setEventProcessingState( SDL_JOYBUTTONUP, true ); setEventProcessingState( SDL_JOYDEVICEADDED, true ); setEventProcessingState( SDL_JOYDEVICEREMOVED, true ); setEventProcessingState( SDL_CONTROLLERAXISMOTION, true ); setEventProcessingState( SDL_CONTROLLERBUTTONDOWN, true ); setEventProcessingState( SDL_CONTROLLERBUTTONUP, true ); setEventProcessingState( SDL_CONTROLLERDEVICEADDED, true ); setEventProcessingState( SDL_CONTROLLERDEVICEREMOVED, true ); setEventProcessingState( SDL_CONTROLLERDEVICEREMAPPED, true ); setEventProcessingState( SDL_FINGERDOWN, true ); setEventProcessingState( SDL_FINGERUP, true ); setEventProcessingState( SDL_FINGERMOTION, true ); // We do not support clipboard within the engine. setEventProcessingState( SDL_CLIPBOARDUPDATE, false ); // We do not support drag and drop capability for the application. setEventProcessingState( SDL_DROPFILE, false ); setEventProcessingState( SDL_DROPTEXT, false ); setEventProcessingState( SDL_DROPBEGIN, false ); // supported from SDL 2.0.5 setEventProcessingState( SDL_DROPCOMPLETE, false ); // supported from SDL 2.0.5 setEventProcessingState( SDL_RENDER_TARGETS_RESET, true ); // supported from SDL 2.0.2 setEventProcessingState( SDL_RENDER_DEVICE_RESET, true ); // supported from SDL 2.0.4 // We do not support custom user events as of now. setEventProcessingState( SDL_USEREVENT, false ); // TODO: verify why we disabled processing of these events. setEventProcessingState( SDL_SYSWMEVENT, false ); setEventProcessingState( SDL_DOLLARGESTURE, false ); setEventProcessingState( SDL_DOLLARRECORD, false ); setEventProcessingState( SDL_MULTIGESTURE, false ); setEventProcessingState( SDL_AUDIODEVICEADDED, false ); // supported from SDL 2.0.4 setEventProcessingState( SDL_AUDIODEVICEREMOVED, false ); // supported from SDL 2.0.4 setEventProcessingState( SDL_SENSORUPDATE, false ); // TODO: we don't process these events. Add the logic. setEventProcessingState( SDL_APP_TERMINATING, false ); setEventProcessingState( SDL_APP_WILLENTERBACKGROUND, false ); setEventProcessingState( SDL_APP_DIDENTERBACKGROUND, false ); setEventProcessingState( SDL_APP_WILLENTERFOREGROUND, false ); setEventProcessingState( SDL_APP_DIDENTERFOREGROUND, false ); setEventProcessingState( SDL_DISPLAYEVENT, false ); // SDL_LOCALECHANGED is supported from SDL 2.0.14 // SDL_CONTROLLERTOUCHPADDOWN is supported from SDL 2.0.14 // SDL_CONTROLLERTOUCHPADMOTION is supported from SDL 2.0.14 // SDL_CONTROLLERTOUCHPADUP is supported from SDL 2.0.14 // SDL_CONTROLLERSENSORUPDATE is supported from SDL 2.0.14 // SDL_TEXTEDITING_EXT is supported only from SDL 2.0.22 // SDL_POLLSENTINEL is supported from SDL 2.0.? } static int32_t getCurrentKeyModifiers() { return getKeyModifierFromSDL( SDL_GetModState() ); } static void initTouchpad() { #if SDL_VERSION_ATLEAST( 2, 0, 10 ) if ( SDL_SetHint( SDL_HINT_MOUSE_TOUCH_EVENTS, "0" ) != SDL_TRUE ) { ERROR_LOG( "Failed to set the " SDL_HINT_MOUSE_TOUCH_EVENTS " hint." ) } #endif #if SDL_VERSION_ATLEAST( 2, 0, 6 ) if ( SDL_SetHint( SDL_HINT_TOUCH_MOUSE_EVENTS, "0" ) != SDL_TRUE ) { ERROR_LOG( "Failed to set the " SDL_HINT_TOUCH_MOUSE_EVENTS " hint." ) } #endif if ( SDL_GetNumTouchDevices() <= 0 ) { return; } fheroes2::cursor().enableSoftwareEmulation( true ); } void initController() { const int joystickNumber = SDL_NumJoysticks(); if ( joystickNumber < 0 ) { ERROR_LOG( "Failed to get the number of joysticks. The error value: " << joystickNumber << ", description: " << SDL_GetError() ) return; } for ( int i = 0; i < joystickNumber; ++i ) { if ( SDL_IsGameController( i ) == SDL_TRUE ) { _gameController = SDL_GameControllerOpen( i ); if ( _gameController != nullptr ) { fheroes2::cursor().enableSoftwareEmulation( true ); break; } ERROR_LOG( "Failed to open a controller with ID " << i << ". Error description: " << SDL_GetError() ) } } } void closeController() { if ( SDL_GameControllerGetAttached( _gameController ) == SDL_TRUE ) { SDL_GameControllerClose( _gameController ); _gameController = nullptr; } } bool isControllerValid() const { return _gameController != nullptr; } static void sleep( const uint32_t milliseconds ) { SDL_Delay( milliseconds ); } bool handleEvents( LocalEvent & eventHandler, const bool allowExit, bool & updateDisplay ) { updateDisplay = false; SDL_Event event; while ( SDL_PollEvent( &event ) ) { // Most SDL events should be processed sequentially one event at a time, but for some // event types, the processing of intermediate events may be skipped in order to gain // overall event processing speed. bool processImmediately = true; switch ( event.type ) { case SDL_WINDOWEVENT: if ( event.window.event == SDL_WINDOWEVENT_CLOSE ) { if ( allowExit ) { // Try to perform clear exit to catch all memory leaks, for example. return false; } processImmediately = false; break; } if ( onWindowEvent( event.window ) ) { updateDisplay = true; } else { processImmediately = false; } break; case SDL_KEYDOWN: case SDL_KEYUP: onKeyboardEvent( eventHandler, event.key ); break; case SDL_MOUSEMOTION: onMouseMotionEvent( eventHandler, event.motion ); processImmediately = false; break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: onMouseButtonEvent( eventHandler, event.button ); break; case SDL_MOUSEWHEEL: onMouseWheelEvent( eventHandler, event.wheel ); break; case SDL_CONTROLLERDEVICEREMOVED: onControllerRemovedEvent( event.jdevice ); break; case SDL_CONTROLLERDEVICEADDED: onControllerAddedEvent( event.jdevice ); break; case SDL_JOYAXISMOTION: case SDL_JOYBALLMOTION: case SDL_JOYHATMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: case SDL_JOYDEVICEADDED: case SDL_JOYDEVICEREMOVED: case SDL_CONTROLLERDEVICEREMAPPED: // SDL requires joystick events to be enabled in order to handle controller events. // This is because the controller related code depends on the joystick related code. // See SDL_gamecontroller.c within SDL source code for implementation details. processImmediately = false; break; case SDL_CONTROLLERAXISMOTION: onControllerAxisEvent( eventHandler, event.caxis ); processImmediately = false; break; case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: onControllerButtonEvent( eventHandler, event.cbutton ); break; case SDL_FINGERDOWN: case SDL_FINGERUP: case SDL_FINGERMOTION: onTouchEvent( eventHandler, event.tfinger ); if ( event.type == SDL_FINGERMOTION ) { processImmediately = false; } break; case SDL_RENDER_TARGETS_RESET: // We need to just update the screen. This event usually happens when we switch between fullscreen and windowed modes. updateDisplay = true; break; case SDL_RENDER_DEVICE_RESET: onRenderDeviceResetEvent(); updateDisplay = true; break; case SDL_TEXTINPUT: // Keyboard events on Android should be processed here. Use event.text.text to extract text input. break; case SDL_TEXTEDITING: // An event when a user pressed a button on a keyboard. Not all buttons are supported. This event should be used mainly on Android devices. break; case SDL_QUIT: if ( allowExit ) { // Try to perform clear exit to catch all memory leaks, for example. return false; } processImmediately = false; break; case SDL_APP_LOWMEMORY: // According to SDL this event can only happen on Android or iOS. // We need to deallocate some memory but we need to be careful not to deallocate images that are in use at the moment. // As of now we have no logic for this so we at least log this event. DEBUG_LOG( DBG_ENGINE, DBG_WARN, "OS indicates low memory. Release some resources." ) break; default: // If this assertion blows up then we included an event type but we didn't add logic for it. assert( eventTypeStatus.count( event.type ) == 0 ); // This is a new event type which we do not handle. It might have been added in a newer version of SDL. processImmediately = false; break; } // If the current event does require immediate processing, then we need to return immediately. if ( processImmediately ) { break; } // Otherwise, we can process it later along with the newly received events, if any. } return true; } static const char * getKeyName( const fheroes2::Key key ) { return SDL_GetKeyName( static_cast( getSDLKey( key ) ) ); } private: SDL_GameController * _gameController{ nullptr }; static void setEventProcessingState( const uint32_t eventType, const bool enable ) { if ( const auto [dummy, inserted] = eventTypeStatus.emplace( eventType ); !inserted ) { assert( 0 ); } SDL_EventState( eventType, ( enable ? SDL_ENABLE : SDL_IGNORE ) ); } static int32_t getKeyModifierFromSDL( const int sdlModifier ) { int32_t modifier = fheroes2::KeyModifier::KEY_MODIFIER_NONE; if ( sdlModifier & KMOD_CTRL ) { modifier |= fheroes2::KeyModifier::KEY_MODIFIER_CTRL; } if ( sdlModifier & KMOD_SHIFT ) { modifier |= fheroes2::KeyModifier::KEY_MODIFIER_SHIFT; } if ( sdlModifier & KMOD_ALT ) { modifier |= fheroes2::KeyModifier::KEY_MODIFIER_ALT; } if ( sdlModifier & KMOD_CAPS ) { modifier |= fheroes2::KeyModifier::KEY_MODIFIER_CAPS; } if ( sdlModifier & KMOD_NUM ) { modifier |= fheroes2::KeyModifier::KEY_MODIFIER_NUM; } return modifier; } static int getSDLKey( const fheroes2::Key key ) { switch ( key ) { case fheroes2::Key::NONE: case fheroes2::Key::LAST_KEY: return SDLK_UNKNOWN; case fheroes2::Key::KEY_BACKSPACE: return SDLK_BACKSPACE; case fheroes2::Key::KEY_ENTER: return SDLK_RETURN; case fheroes2::Key::KEY_ESCAPE: return SDLK_ESCAPE; case fheroes2::Key::KEY_SPACE: return SDLK_SPACE; case fheroes2::Key::KEY_EXCLAIM: return SDLK_EXCLAIM; case fheroes2::Key::KEY_DOUBLE_QUOTE: return SDLK_QUOTEDBL; case fheroes2::Key::KEY_HASH: return SDLK_HASH; case fheroes2::Key::KEY_DOLLAR: return SDLK_DOLLAR; case fheroes2::Key::KEY_AMPERSAND: return SDLK_AMPERSAND; case fheroes2::Key::KEY_QUOTE: return SDLK_QUOTE; case fheroes2::Key::KEY_BACKQUOTE: return SDLK_BACKQUOTE; case fheroes2::Key::KEY_LEFT_PARENTHESIS: return SDLK_LEFTPAREN; case fheroes2::Key::KEY_RIGHT_PARENTHESIS: return SDLK_RIGHTPAREN; case fheroes2::Key::KEY_ASTERISK: return SDLK_ASTERISK; case fheroes2::Key::KEY_PLUS: return SDLK_PLUS; case fheroes2::Key::KEY_COMMA: return SDLK_COMMA; case fheroes2::Key::KEY_MINUS: return SDLK_MINUS; case fheroes2::Key::KEY_PERIOD: return SDLK_PERIOD; case fheroes2::Key::KEY_SLASH: return SDLK_SLASH; case fheroes2::Key::KEY_COLON: return SDLK_COLON; case fheroes2::Key::KEY_SEMICOLON: return SDLK_SEMICOLON; case fheroes2::Key::KEY_LESS: return SDLK_LESS; case fheroes2::Key::KEY_EQUALS: return SDLK_EQUALS; case fheroes2::Key::KEY_GREATER: return SDLK_GREATER; case fheroes2::Key::KEY_QUESTION: return SDLK_QUESTION; case fheroes2::Key::KEY_AT: return SDLK_AT; case fheroes2::Key::KEY_LEFT_BRACKET: return SDLK_LEFTBRACKET; case fheroes2::Key::KEY_BACKSLASH: return SDLK_BACKSLASH; case fheroes2::Key::KEY_RIGHT_BRACKET: return SDLK_RIGHTBRACKET; case fheroes2::Key::KEY_CARET: return SDLK_CARET; case fheroes2::Key::KEY_UNDERSCORE: return SDLK_UNDERSCORE; case fheroes2::Key::KEY_LEFT_ALT: return SDLK_LALT; case fheroes2::Key::KEY_RIGHT_ALT: return SDLK_RALT; case fheroes2::Key::KEY_LEFT_CONTROL: return SDLK_LCTRL; case fheroes2::Key::KEY_RIGHT_CONTROL: return SDLK_RCTRL; case fheroes2::Key::KEY_LEFT_SHIFT: return SDLK_LSHIFT; case fheroes2::Key::KEY_RIGHT_SHIFT: return SDLK_RSHIFT; case fheroes2::Key::KEY_TAB: return SDLK_TAB; case fheroes2::Key::KEY_DELETE: return SDLK_DELETE; case fheroes2::Key::KEY_PAGE_UP: return SDLK_PAGEUP; case fheroes2::Key::KEY_PAGE_DOWN: return SDLK_PAGEDOWN; case fheroes2::Key::KEY_F1: return SDLK_F1; case fheroes2::Key::KEY_F2: return SDLK_F2; case fheroes2::Key::KEY_F3: return SDLK_F3; case fheroes2::Key::KEY_F4: return SDLK_F4; case fheroes2::Key::KEY_F5: return SDLK_F5; case fheroes2::Key::KEY_F6: return SDLK_F6; case fheroes2::Key::KEY_F7: return SDLK_F7; case fheroes2::Key::KEY_F8: return SDLK_F8; case fheroes2::Key::KEY_F9: return SDLK_F9; case fheroes2::Key::KEY_F10: return SDLK_F10; case fheroes2::Key::KEY_F11: return SDLK_F11; case fheroes2::Key::KEY_F12: return SDLK_F12; case fheroes2::Key::KEY_LEFT: return SDLK_LEFT; case fheroes2::Key::KEY_RIGHT: return SDLK_RIGHT; case fheroes2::Key::KEY_UP: return SDLK_UP; case fheroes2::Key::KEY_DOWN: return SDLK_DOWN; case fheroes2::Key::KEY_0: return SDLK_0; case fheroes2::Key::KEY_1: return SDLK_1; case fheroes2::Key::KEY_2: return SDLK_2; case fheroes2::Key::KEY_3: return SDLK_3; case fheroes2::Key::KEY_4: return SDLK_4; case fheroes2::Key::KEY_5: return SDLK_5; case fheroes2::Key::KEY_6: return SDLK_6; case fheroes2::Key::KEY_7: return SDLK_7; case fheroes2::Key::KEY_8: return SDLK_8; case fheroes2::Key::KEY_9: return SDLK_9; case fheroes2::Key::KEY_A: return SDLK_a; case fheroes2::Key::KEY_B: return SDLK_b; case fheroes2::Key::KEY_C: return SDLK_c; case fheroes2::Key::KEY_D: return SDLK_d; case fheroes2::Key::KEY_E: return SDLK_e; case fheroes2::Key::KEY_F: return SDLK_f; case fheroes2::Key::KEY_G: return SDLK_g; case fheroes2::Key::KEY_H: return SDLK_h; case fheroes2::Key::KEY_I: return SDLK_i; case fheroes2::Key::KEY_J: return SDLK_j; case fheroes2::Key::KEY_K: return SDLK_k; case fheroes2::Key::KEY_L: return SDLK_l; case fheroes2::Key::KEY_M: return SDLK_m; case fheroes2::Key::KEY_N: return SDLK_n; case fheroes2::Key::KEY_O: return SDLK_o; case fheroes2::Key::KEY_P: return SDLK_p; case fheroes2::Key::KEY_Q: return SDLK_q; case fheroes2::Key::KEY_R: return SDLK_r; case fheroes2::Key::KEY_S: return SDLK_s; case fheroes2::Key::KEY_T: return SDLK_t; case fheroes2::Key::KEY_U: return SDLK_u; case fheroes2::Key::KEY_V: return SDLK_v; case fheroes2::Key::KEY_W: return SDLK_w; case fheroes2::Key::KEY_X: return SDLK_x; case fheroes2::Key::KEY_Y: return SDLK_y; case fheroes2::Key::KEY_Z: return SDLK_z; case fheroes2::Key::KEY_PRINT: return SDLK_PRINTSCREEN; case fheroes2::Key::KEY_KP_0: return SDLK_KP_0; case fheroes2::Key::KEY_KP_1: return SDLK_KP_1; case fheroes2::Key::KEY_KP_2: return SDLK_KP_2; case fheroes2::Key::KEY_KP_3: return SDLK_KP_3; case fheroes2::Key::KEY_KP_4: return SDLK_KP_4; case fheroes2::Key::KEY_KP_5: return SDLK_KP_5; case fheroes2::Key::KEY_KP_6: return SDLK_KP_6; case fheroes2::Key::KEY_KP_7: return SDLK_KP_7; case fheroes2::Key::KEY_KP_8: return SDLK_KP_8; case fheroes2::Key::KEY_KP_9: return SDLK_KP_9; case fheroes2::Key::KEY_KP_PERIOD: return SDLK_KP_PERIOD; case fheroes2::Key::KEY_KP_DIVIDE: return SDLK_KP_DIVIDE; case fheroes2::Key::KEY_KP_MULTIPLY: return SDLK_KP_MULTIPLY; case fheroes2::Key::KEY_KP_MINUS: return SDLK_KP_MINUS; case fheroes2::Key::KEY_KP_PLUS: return SDLK_KP_PLUS; case fheroes2::Key::KEY_KP_ENTER: return SDLK_KP_ENTER; case fheroes2::Key::KEY_KP_EQUALS: return SDLK_KP_EQUALS; case fheroes2::Key::KEY_HOME: return SDLK_HOME; case fheroes2::Key::KEY_END: return SDLK_END; default: // Did you add a new key? Add the logic above! assert( 0 ); break; } return SDLK_UNKNOWN; } static fheroes2::Key getKeyFromSDL( int sdlKey ) { // SDL interprets keyboard Numpad Enter as a separate key. However, in the game we should handle it in the same way as the normal Enter. if ( sdlKey == SDLK_KP_ENTER ) { sdlKey = SDLK_RETURN; } static std::map sdlValueToKey; if ( sdlValueToKey.empty() ) { // The map is empty let's populate it. for ( int32_t i = static_cast( fheroes2::Key::NONE ); i < static_cast( fheroes2::Key::LAST_KEY ); ++i ) { const fheroes2::Key key = static_cast( i ); sdlValueToKey.emplace( getSDLKey( key ), key ); } } auto iter = sdlValueToKey.find( sdlKey ); if ( iter == sdlValueToKey.end() ) { return fheroes2::Key::NONE; } return iter->second; } // Returns true if frame rendering is required. static bool onWindowEvent( const SDL_WindowEvent & event ) { if ( event.event == SDL_WINDOWEVENT_FOCUS_LOST ) { LocalEvent::StopSounds(); return false; } if ( event.event == SDL_WINDOWEVENT_FOCUS_GAINED ) { LocalEvent::ResumeSounds(); return true; } return ( event.event == SDL_WINDOWEVENT_RESIZED ); } static void onMouseMotionEvent( LocalEvent & eventHandler, const SDL_MouseMotionEvent & motion ) { eventHandler.onMouseMotionEvent( { motion.x, motion.y } ); } static void onMouseButtonEvent( LocalEvent & eventHandler, const SDL_MouseButtonEvent & button ) { // Not sure how it is possible to have something else for a button. assert( ( button.state == SDL_PRESSED ) || ( button.state == SDL_RELEASED ) ); LocalEvent::MouseButtonType buttonType = LocalEvent::MouseButtonType::MOUSE_BUTTON_UNKNOWN; switch ( button.button ) { case SDL_BUTTON_LEFT: buttonType = LocalEvent::MouseButtonType::MOUSE_BUTTON_LEFT; break; case SDL_BUTTON_MIDDLE: buttonType = LocalEvent::MouseButtonType::MOUSE_BUTTON_MIDDLE; break; case SDL_BUTTON_RIGHT: buttonType = LocalEvent::MouseButtonType::MOUSE_BUTTON_RIGHT; break; default: VERBOSE_LOG( "Unknown mouse button " << static_cast( button.button ) ) return; } eventHandler.onMouseButtonEvent( button.state == SDL_PRESSED, buttonType, { button.x, button.y } ); } static void onKeyboardEvent( LocalEvent & eventHandler, const SDL_KeyboardEvent & event ) { const fheroes2::Key key = getKeyFromSDL( event.keysym.sym ); if ( key == fheroes2::Key::NONE ) { // We do not process this key. return; } LocalEvent::KeyboardEventState state = LocalEvent::KeyboardEventState::KEY_UNKNOWN; switch ( event.type ) { case SDL_KEYDOWN: state = LocalEvent::KeyboardEventState::KEY_DOWN; break; case SDL_KEYUP: state = LocalEvent::KeyboardEventState::KEY_UP; break; default: // We don't handle other events for now. break; } eventHandler.onKeyboardEvent( key, getKeyModifierFromSDL( event.keysym.mod ), state ); } static void onMouseWheelEvent( LocalEvent & eventHandler, const SDL_MouseWheelEvent & wheel ) { eventHandler.onMouseWheelEvent( { wheel.x, wheel.y } ); } static void onControllerAxisEvent( LocalEvent & eventHandler, const SDL_ControllerAxisEvent & motion ) { LocalEvent::ControllerAxisType axisType = LocalEvent::ControllerAxisType::CONTROLLER_AXIS_UNKNOWN; switch ( motion.axis ) { case SDL_CONTROLLER_AXIS_LEFTX: axisType = LocalEvent::ControllerAxisType::CONTROLLER_AXIS_LEFT_X; break; case SDL_CONTROLLER_AXIS_LEFTY: axisType = LocalEvent::ControllerAxisType::CONTROLLER_AXIS_LEFT_Y; break; case SDL_CONTROLLER_AXIS_RIGHTX: axisType = LocalEvent::ControllerAxisType::CONTROLLER_AXIS_RIGHT_X; break; case SDL_CONTROLLER_AXIS_RIGHTY: axisType = LocalEvent::ControllerAxisType::CONTROLLER_AXIS_RIGHT_Y; break; default: // We don't process other axes. break; } eventHandler.onControllerAxisEvent( axisType, motion.value ); } static void onControllerButtonEvent( LocalEvent & eventHandler, const SDL_ControllerButtonEvent & button ) { // Not sure how it is possible to have something else for a button. assert( ( button.state == SDL_PRESSED ) || ( button.state == SDL_RELEASED ) ); LocalEvent::ControllerButtonType buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_UNKNOWN; switch ( button.button ) { case SDL_CONTROLLER_BUTTON_A: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_A; break; case SDL_CONTROLLER_BUTTON_B: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_B; break; case SDL_CONTROLLER_BUTTON_X: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_X; break; case SDL_CONTROLLER_BUTTON_Y: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_Y; break; case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_RIGHT_SHOULDER; break; case SDL_CONTROLLER_BUTTON_LEFTSHOULDER: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_LEFT_SHOULDER; break; case SDL_CONTROLLER_BUTTON_DPAD_UP: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_DPAD_UP; break; case SDL_CONTROLLER_BUTTON_DPAD_DOWN: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_DPAD_DOWN; break; case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_DPAD_RIGHT; break; case SDL_CONTROLLER_BUTTON_DPAD_LEFT: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_DPAD_LEFT; break; case SDL_CONTROLLER_BUTTON_BACK: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_BACK; break; case SDL_CONTROLLER_BUTTON_START: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_START; break; case SDL_CONTROLLER_BUTTON_GUIDE: buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_GUIDE; break; default: // We don't handle other buttons for now. break; } #if defined( TARGET_NINTENDO_SWITCH ) // Custom button mapping for Nintendo Switch if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_A ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_B; } else if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_B ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_A; } else if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_X ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_START; } else if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_Y ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_GUIDE; } else if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_RIGHT_SHOULDER ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_DPAD_RIGHT; } else if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_LEFT_SHOULDER ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_DPAD_LEFT; } else if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_BACK ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_X; } else if ( buttonType == LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_START ) { buttonType = LocalEvent::ControllerButtonType::CONTROLLER_BUTTON_Y; } #endif eventHandler.onControllerButtonEvent( button.state == SDL_PRESSED, buttonType ); } static void onTouchEvent( LocalEvent & eventHandler, const SDL_TouchFingerEvent & event ) { #if defined( TARGET_PS_VITA ) { // PS Vita has two touchpads: front and rear. The ID of the front touchpad must match the value of // 'SDL_TouchID' used in the 'SDL_AddTouch()' call in the 'VITA_InitTouch()' function in this SDL2 // source file: video/vita/SDL_vitatouch.c. constexpr SDL_TouchID frontTouchpadDeviceID { #if SDL_VERSION_ATLEAST( 2, 30, 7 ) 1 #else 0 #endif }; // Use only front touchpad on PS Vita. if ( event.touchId != frontTouchpadDeviceID ) { return; } } #endif LocalEvent::TouchFingerEventType fingerEventType = LocalEvent::TouchFingerEventType::FINGER_EVENT_UNKNOWN; switch ( event.type ) { case SDL_FINGERDOWN: fingerEventType = LocalEvent::TouchFingerEventType::FINGER_EVENT_DOWN; break; case SDL_FINGERUP: fingerEventType = LocalEvent::TouchFingerEventType::FINGER_EVENT_UP; break; case SDL_FINGERMOTION: fingerEventType = LocalEvent::TouchFingerEventType::FINGER_EVENT_MOTION; break; default: // We don't handle any other events. break; } eventHandler.onTouchFingerEvent( fingerEventType, event.touchId, event.fingerId, { event.x, event.y } ); } static void onRenderDeviceResetEvent() { LocalEvent::onRenderDeviceResetEvent(); } void onControllerRemovedEvent( const SDL_JoyDeviceEvent & event ) { if ( _gameController == nullptr ) { // Nothing to handle. return; } const SDL_GameController * removedController = SDL_GameControllerFromInstanceID( event.which ); if ( removedController == nullptr ) { ERROR_LOG( "Failed to remove a controller with ID " << event.which << ". Error description: " << SDL_GetError() ) return; } if ( removedController == _gameController ) { SDL_GameControllerClose( _gameController ); _gameController = nullptr; } } void onControllerAddedEvent( const SDL_JoyDeviceEvent & event ) { if ( _gameController == nullptr ) { _gameController = SDL_GameControllerOpen( event.which ); if ( _gameController != nullptr ) { fheroes2::cursor().enableSoftwareEmulation( true ); } else { ERROR_LOG( "Failed to open a controller with ID " << event.which << ". Error description: " << SDL_GetError() ) } } } }; } namespace fheroes2 { const char * KeySymGetName( const Key key ) { return EventProcessing::EventEngine::getKeyName( key ); } size_t InsertKeySym( std::string & res, size_t pos, const Key key, const int32_t mod ) { switch ( key ) { case fheroes2::Key::KEY_BACKSPACE: if ( !res.empty() && pos ) { if ( pos >= res.size() ) res.resize( res.size() - 1 ); else res.erase( pos - 1, 1 ); --pos; } break; case fheroes2::Key::KEY_DELETE: if ( pos < res.size() ) { res.erase( pos, 1 ); } break; case fheroes2::Key::KEY_LEFT: if ( pos ) --pos; break; case fheroes2::Key::KEY_RIGHT: if ( pos < res.size() ) ++pos; break; case fheroes2::Key::KEY_HOME: pos = 0; break; case fheroes2::Key::KEY_END: pos = res.size(); break; default: { char c = getCharacterFromPressedKey( key, mod ); if ( c ) { res.insert( pos, 1, c ); ++pos; } } } return pos; } } LocalEvent::LocalEvent() : _engine( std::make_unique() ) , _mouseButtonLongPressDelay( mouseButtonLongPressTimeout ) { // Do nothing. } void LocalEvent::initController() { _engine->initController(); } void LocalEvent::CloseController() { _engine->closeController(); } LocalEvent & LocalEvent::Get() { static LocalEvent le; return le; } bool LocalEvent::HandleEvents( const bool sleepAfterEventProcessing, const bool allowExit /* = false */ ) { // Event processing might be computationally heavy. // We want to make sure that we do not slow down by going into sleep mode when it is not needed. const fheroes2::Time eventProcessingTimer; // We can have more than one event which requires rendering. We must render only once and only when sleeping is excepted. fheroes2::Rect renderRoi; // Mouse area must be updated only once so we will use only the latest area for rendering. _mouseCursorRenderArea = {}; fheroes2::Display & display = fheroes2::Display::instance(); if ( fheroes2::RenderProcessor::instance().isCyclingUpdateRequired() ) { // To maintain color cycling animation we need to render the whole frame with an updated palette. renderRoi = { 0, 0, display.width(), display.height() }; } // We shouldn't reset the MOUSE_PRESSED and KEY_HOLD here because these are "ongoing" states resetStates( KEY_PRESSED ); resetStates( MOUSE_MOTION ); resetStates( MOUSE_RELEASED ); resetStates( MOUSE_WHEEL ); // MOUSE_PRESSED is an "ongoing" state, so we shouldn't reset the MOUSE_TOUCH while that state is active if ( !( _actionStates & MOUSE_PRESSED ) ) { resetStates( MOUSE_TOUCH ); } bool isDisplayRefreshRequired = false; if ( !_engine->handleEvents( *this, allowExit, isDisplayRefreshRequired ) ) { return false; } if ( isDisplayRefreshRequired ) { renderRoi = { 0, 0, display.width(), display.height() }; } if ( _engine->isControllerValid() ) { ProcessControllerAxisMotion(); } renderRoi = fheroes2::getBoundaryRect( renderRoi, _mouseCursorRenderArea ); static_assert( globalLoopSleepTime == 1, "Since you have changed the sleep time, make sure that the sleep does not last too long." ); if ( sleepAfterEventProcessing ) { if ( renderRoi != fheroes2::Rect() ) { display.render( renderRoi ); } #ifndef __EMSCRIPTEN__ // Make sure not to delay any further if the processing time within this function was more than the expected waiting time. if ( eventProcessingTimer.getMs() < globalLoopSleepTime ) { EventProcessing::EventEngine::sleep( globalLoopSleepTime ); } #endif } else { // Since rendering is going to be just after the call of this method we need to update rendering area only. if ( renderRoi != fheroes2::Rect() ) { display.updateNextRenderRoi( renderRoi ); } } #ifdef __EMSCRIPTEN__ // When a WebAssembly app is running in a browser, the sleep time is used to perform various "background" operations on the main thread (such // as feeding the audio streams) by yielding to the browser's event loop using the Emscripten Asyncify mechanism. Therefore, it is preferable // to always force the main thread to fall asleep, otherwise, for example, the following deadlock is possible: the main thread waits in a loop // for an audio playback to finish, but it never finishes because new chunks are not feeded to it, because the main thread never goes to sleep. EventProcessing::EventEngine::sleep( globalLoopSleepTime ); #endif return true; } void LocalEvent::StopSounds() { Audio::Mute(); } void LocalEvent::ResumeSounds() { Audio::Unmute(); } void LocalEvent::onMouseWheelEvent( fheroes2::Point position ) { setStates( MOUSE_WHEEL ); _mouseReleaseMiddlePos = _mouseCursorPos; _mouseWheelMovementOffset = position; } void LocalEvent::onTouchFingerEvent( const TouchFingerEventType eventType, const int64_t touchId, const int64_t fingerId, fheroes2::PointBase2D position ) { // ID of a finger here is a composite thing, and consists of a touch device id and a finger id. This // should allow gestures to be handled correctly even when using different touchpads for different // fingers. const auto eventFingerId = std::make_pair( touchId, fingerId ); switch ( eventType ) { case TouchFingerEventType::FINGER_EVENT_DOWN: if ( !_fingerIds.first ) { _fingerIds.first = eventFingerId; } else if ( !_fingerIds.second ) { _fingerIds.second = eventFingerId; } else { // Gestures of more than two fingers are not supported, ignore return; } break; case TouchFingerEventType::FINGER_EVENT_UP: case TouchFingerEventType::FINGER_EVENT_MOTION: if ( eventFingerId != _fingerIds.first && eventFingerId != _fingerIds.second ) { // An event from an unknown finger, ignore return; } break; default: // Unknown event, this should never happen assert( 0 ); return; } if ( eventFingerId == _fingerIds.first ) { const fheroes2::Display & display = fheroes2::Display::instance(); #if defined( TARGET_PS_VITA ) || defined( TARGET_NINTENDO_SWITCH ) // TODO: verify where it is even needed to do such weird woodoo magic for these targets. const fheroes2::Size screenResolution = fheroes2::engine().getCurrentScreenResolution(); // current resolution of screen const fheroes2::Rect windowRect = fheroes2::engine().getActiveWindowROI(); // scaled (logical) resolution assert( windowRect.width > 0 ); _emulatedPointerPos.x = static_cast( screenResolution.width * position.x - windowRect.x ) * ( static_cast( display.width() ) / windowRect.width ); _emulatedPointerPos.y = static_cast( screenResolution.height * position.y - windowRect.y ) * ( static_cast( display.height() ) / windowRect.height ); #else _emulatedPointerPos.x = static_cast( position.x ) * display.width(); _emulatedPointerPos.y = static_cast( position.y ) * display.height(); #endif _mouseCursorPos.x = static_cast( _emulatedPointerPos.x ); _mouseCursorPos.y = static_cast( _emulatedPointerPos.y ); setStates( MOUSE_MOTION ); setStates( MOUSE_TOUCH ); if ( _globalMouseMotionEventHook ) { _mouseCursorRenderArea = _globalMouseMotionEventHook( _mouseCursorPos.x, _mouseCursorPos.y ); } // If there is a two-finger gesture in progress, the first finger is only used to move the cursor. // The operation of the left mouse button is not simulated. if ( !_isTwoFingerGestureInProgress ) { if ( eventType == TouchFingerEventType::FINGER_EVENT_DOWN ) { _mousePressLeftPos = _mouseCursorPos; _mouseButtonLongPressDelay.reset(); setStates( MOUSE_PRESSED ); } else if ( eventType == TouchFingerEventType::FINGER_EVENT_UP ) { _mouseReleaseLeftPos = _mouseCursorPos; resetStates( MOUSE_PRESSED ); resetStates( DRAG_ONGOING ); setStates( MOUSE_RELEASED ); } _currentMouseButton = MouseButtonType::MOUSE_BUTTON_LEFT; } } else if ( eventFingerId == _fingerIds.second ) { if ( eventType == TouchFingerEventType::FINGER_EVENT_DOWN ) { _mousePressRightPos = _mouseCursorPos; _mouseButtonLongPressDelay.reset(); setStates( MOUSE_PRESSED ); setStates( MOUSE_TOUCH ); // When the second finger touches the screen, the two-finger gesture processing begins. This // gesture simulates the operation of the right mouse button and ends when both fingers are // removed from the screen. _isTwoFingerGestureInProgress = true; } else if ( eventType == TouchFingerEventType::FINGER_EVENT_UP ) { _mouseReleaseRightPos = _mouseCursorPos; resetStates( MOUSE_PRESSED ); resetStates( DRAG_ONGOING ); setStates( MOUSE_RELEASED ); setStates( MOUSE_TOUCH ); } _currentMouseButton = MouseButtonType::MOUSE_BUTTON_RIGHT; } // The finger no longer touches the screen, reset its state if ( eventType == TouchFingerEventType::FINGER_EVENT_UP ) { if ( eventFingerId == _fingerIds.first ) { _fingerIds.first.reset(); } else if ( eventFingerId == _fingerIds.second ) { _fingerIds.second.reset(); } else { // An event from an unknown finger, this should never happen assert( 0 ); } // Both fingers are removed from the screen, cancel the two-finger gesture if ( !_fingerIds.first && !_fingerIds.second ) { _isTwoFingerGestureInProgress = false; } } } void LocalEvent::onControllerAxisEvent( const ControllerAxisType axisType, const int16_t value ) { if ( axisType == ControllerAxisType::CONTROLLER_AXIS_LEFT_X ) { if ( std::abs( value ) > CONTROLLER_L_DEADZONE ) { _controllerLeftXAxis = value; } else { _controllerLeftXAxis = 0; } } else if ( axisType == ControllerAxisType::CONTROLLER_AXIS_LEFT_Y ) { if ( std::abs( value ) > CONTROLLER_L_DEADZONE ) { _controllerLeftYAxis = value; } else { _controllerLeftYAxis = 0; } } else if ( axisType == ControllerAxisType::CONTROLLER_AXIS_RIGHT_X ) { if ( std::abs( value ) > CONTROLLER_R_DEADZONE ) { _controllerRightXAxis = value; } else { _controllerRightXAxis = 0; } } else if ( axisType == ControllerAxisType::CONTROLLER_AXIS_RIGHT_Y ) { if ( std::abs( value ) > CONTROLLER_R_DEADZONE ) { _controllerRightYAxis = value; } else { _controllerRightYAxis = 0; } } } void LocalEvent::onControllerButtonEvent( const bool isPressed, const ControllerButtonType buttonType ) { if ( isPressed ) { setStates( KEY_PRESSED ); } else { resetStates( KEY_PRESSED ); } if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_A || buttonType == ControllerButtonType::CONTROLLER_BUTTON_B ) { if ( isAnyKeyPressed() ) { _mouseButtonLongPressDelay.reset(); setStates( MOUSE_PRESSED ); } else { resetStates( MOUSE_PRESSED ); resetStates( DRAG_ONGOING ); setStates( MOUSE_RELEASED ); } if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_A ) { if ( isAnyKeyPressed() ) { _mousePressLeftPos = _mouseCursorPos; } else { _mouseReleaseLeftPos = _mouseCursorPos; } _currentMouseButton = MouseButtonType::MOUSE_BUTTON_LEFT; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_B ) { if ( isAnyKeyPressed() ) { _mousePressRightPos = _mouseCursorPos; } else { _mouseReleaseRightPos = _mouseCursorPos; } _currentMouseButton = MouseButtonType::MOUSE_BUTTON_RIGHT; } resetStates( KEY_PRESSED ); } else if ( isAnyKeyPressed() ) { if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_RIGHT_SHOULDER ) { _controllerPointerSpeed *= _controllerTriggerCursorSpeedup; _currentKeyboardValue = fheroes2::Key::NONE; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_GUIDE ) { _currentKeyboardValue = fheroes2::Key::KEY_ESCAPE; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_DPAD_DOWN ) { _currentKeyboardValue = fheroes2::Key::KEY_SPACE; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_DPAD_LEFT ) { _currentKeyboardValue = fheroes2::Key::KEY_H; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_DPAD_RIGHT ) { _currentKeyboardValue = fheroes2::Key::KEY_T; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_X ) { _currentKeyboardValue = fheroes2::Key::KEY_E; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_Y ) { _currentKeyboardValue = fheroes2::Key::KEY_C; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_BACK ) { _currentKeyboardValue = fheroes2::Key::KEY_F; } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_START ) { _currentKeyboardValue = fheroes2::Key::KEY_ENTER; } else { _currentKeyboardValue = fheroes2::Key::NONE; } } else if ( buttonType == ControllerButtonType::CONTROLLER_BUTTON_RIGHT_SHOULDER ) { _controllerPointerSpeed /= _controllerTriggerCursorSpeedup; } } void LocalEvent::ProcessControllerAxisMotion() { const double deltaTime = _controllerTimer.getS() * 1000.0; _controllerTimer.reset(); if ( _controllerLeftXAxis != 0 || _controllerLeftYAxis != 0 ) { setStates( MOUSE_MOTION ); const int32_t xSign = ( _controllerLeftXAxis < 0 ) ? -1 : 1; const int32_t ySign = ( _controllerLeftYAxis < 0 ) ? -1 : 1; _emulatedPointerPos.x += pow( std::abs( _controllerLeftXAxis ), _controllerAxisSpeedup ) * xSign * deltaTime * _controllerPointerSpeed; _emulatedPointerPos.y += pow( std::abs( _controllerLeftYAxis ), _controllerAxisSpeedup ) * ySign * deltaTime * _controllerPointerSpeed; const fheroes2::Display & display = fheroes2::Display::instance(); if ( _emulatedPointerPos.x < 0 ) _emulatedPointerPos.x = 0; else if ( _emulatedPointerPos.x >= display.width() ) _emulatedPointerPos.x = display.width() - 1; if ( _emulatedPointerPos.y < 0 ) _emulatedPointerPos.y = 0; else if ( _emulatedPointerPos.y >= display.height() ) _emulatedPointerPos.y = display.height() - 1; _mouseCursorPos.x = static_cast( _emulatedPointerPos.x ); _mouseCursorPos.y = static_cast( _emulatedPointerPos.y ); if ( _globalMouseMotionEventHook ) { _mouseCursorRenderArea = _globalMouseMotionEventHook( _mouseCursorPos.x, _mouseCursorPos.y ); } } // map scroll with right stick if ( _controllerRightXAxis != 0 || _controllerRightYAxis != 0 ) { _controllerScrollActive = true; setStates( KEY_PRESSED ); if ( _controllerRightXAxis < 0 ) { _currentKeyboardValue = fheroes2::Key::KEY_LEFT; } else if ( _controllerRightXAxis > 0 ) { _currentKeyboardValue = fheroes2::Key::KEY_RIGHT; } else if ( _controllerRightYAxis < 0 ) { _currentKeyboardValue = fheroes2::Key::KEY_UP; } else if ( _controllerRightYAxis > 0 ) { _currentKeyboardValue = fheroes2::Key::KEY_DOWN; } } else if ( _controllerScrollActive ) { resetStates( KEY_PRESSED ); _controllerScrollActive = false; } } void LocalEvent::onRenderDeviceResetEvent() { // All textures has to be recreated. The only way to do it is to reset everything and render it back. fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Image temp; assert( display.singleLayer() ); temp._disableTransformLayer(); fheroes2::Copy( display, temp ); display.release(); fheroes2::Copy( temp, display ); } void LocalEvent::onKeyboardEvent( const fheroes2::Key key, const int32_t keyModifier, const KeyboardEventState keyState ) { if ( keyState == KeyboardEventState::KEY_DOWN ) { setStates( KEY_PRESSED ); setStates( KEY_HOLD ); if ( _globalKeyDownEventHook ) { _globalKeyDownEventHook( key, keyModifier ); } } else if ( keyState == KeyboardEventState::KEY_UP ) { resetStates( KEY_PRESSED ); resetStates( KEY_HOLD ); } _currentKeyboardValue = key; } void LocalEvent::onMouseMotionEvent( fheroes2::Point position ) { setStates( MOUSE_MOTION ); _mouseCursorPos = position; _emulatedPointerPos.x = _mouseCursorPos.x; _emulatedPointerPos.y = _mouseCursorPos.y; if ( _globalMouseMotionEventHook ) { _mouseCursorRenderArea = _globalMouseMotionEventHook( position.x, position.y ); } } void LocalEvent::onMouseButtonEvent( const bool isPressed, const MouseButtonType buttonType, fheroes2::Point position ) { if ( isPressed ) { _mouseButtonLongPressDelay.reset(); setStates( MOUSE_PRESSED ); } else { resetStates( MOUSE_PRESSED ); resetStates( DRAG_ONGOING ); setStates( MOUSE_RELEASED ); } _currentMouseButton = buttonType; _mouseCursorPos = position; _emulatedPointerPos.x = _mouseCursorPos.x; _emulatedPointerPos.y = _mouseCursorPos.y; if ( _actionStates & MOUSE_PRESSED ) { switch ( buttonType ) { case MouseButtonType::MOUSE_BUTTON_LEFT: _mousePressLeftPos = _mouseCursorPos; break; case MouseButtonType::MOUSE_BUTTON_MIDDLE: _mousePressMiddlePos = _mouseCursorPos; break; case MouseButtonType::MOUSE_BUTTON_RIGHT: _mousePressRightPos = _mouseCursorPos; break; default: assert( 0 ); break; } } // Mouse button has been released else { switch ( buttonType ) { case MouseButtonType::MOUSE_BUTTON_LEFT: _mouseReleaseLeftPos = _mouseCursorPos; break; case MouseButtonType::MOUSE_BUTTON_MIDDLE: _mouseReleaseMiddlePos = _mouseCursorPos; break; case MouseButtonType::MOUSE_BUTTON_RIGHT: _mouseReleaseRightPos = _mouseCursorPos; break; default: assert( 0 ); break; } } } bool LocalEvent::MouseClickLeft() { if ( !( _actionStates & MOUSE_RELEASED ) ) { return false; } if ( _currentMouseButton != MouseButtonType::MOUSE_BUTTON_LEFT ) { return false; } if ( _mouseButtonLongPressDelay.isTriggered() ) { return false; } resetStates( MOUSE_RELEASED ); return true; } bool LocalEvent::MouseClickLeft( const fheroes2::Rect & area ) { if ( !( _actionStates & MOUSE_RELEASED ) ) { return false; } if ( _currentMouseButton != MouseButtonType::MOUSE_BUTTON_LEFT ) { return false; } if ( !( area & _mousePressLeftPos ) || !( area & _mouseReleaseLeftPos ) ) { return false; } if ( _mouseButtonLongPressDelay.isTriggered() ) { return false; } resetStates( MOUSE_RELEASED ); return true; } bool LocalEvent::MouseClickMiddle() { if ( !( _actionStates & MOUSE_RELEASED ) ) { return false; } if ( _currentMouseButton != MouseButtonType::MOUSE_BUTTON_MIDDLE ) { return false; } if ( _mouseButtonLongPressDelay.isTriggered() ) { return false; } resetStates( MOUSE_RELEASED ); return true; } bool LocalEvent::MouseClickRight() { if ( !( _actionStates & MOUSE_RELEASED ) ) { return false; } if ( _currentMouseButton != MouseButtonType::MOUSE_BUTTON_RIGHT ) { return false; } if ( _mouseButtonLongPressDelay.isTriggered() ) { return false; } resetStates( MOUSE_RELEASED ); return true; } bool LocalEvent::MouseClickRight( const fheroes2::Rect & area ) { if ( !( _actionStates & MOUSE_RELEASED ) ) { return false; } if ( _currentMouseButton != MouseButtonType::MOUSE_BUTTON_RIGHT ) { return false; } if ( !( area & _mousePressRightPos ) || !( area & _mouseReleaseRightPos ) ) { return false; } if ( _mouseButtonLongPressDelay.isTriggered() ) { return false; } resetStates( MOUSE_RELEASED ); return true; } bool LocalEvent::MouseLongPressLeft( const fheroes2::Rect & rt ) { if ( !( _actionStates & MOUSE_PRESSED ) ) { return false; } if ( _currentMouseButton != MouseButtonType::MOUSE_BUTTON_LEFT ) { return false; } if ( !( rt & _mousePressLeftPos ) ) { return false; } if ( !_mouseButtonLongPressDelay.isPassed() ) { return false; } if ( _mouseButtonLongPressDelay.isTriggered() ) { return false; } _mouseButtonLongPressDelay.setTriggered(); return true; } int32_t LocalEvent::getCurrentKeyModifiers() { return EventProcessing::EventEngine::getCurrentKeyModifiers(); } void LocalEvent::initEventEngine() { EventProcessing::EventEngine::initEvents(); EventProcessing::EventEngine::initTouchpad(); } fheroes2-1.1.6+dfsg/src/engine/localevent.h000066400000000000000000000353521476115357100205360ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2008 by Josh Matthews * * Copyright (C) 2006 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include "math_base.h" #include "timing.h" namespace EventProcessing { class EventEngine; } namespace fheroes2 { enum class Key : int32_t { NONE, KEY_BACKSPACE, KEY_ENTER, // This is for both Enter keys on keyboards. Check getKeyFromSDL() function for explanation. KEY_ESCAPE, KEY_SPACE, KEY_EXCLAIM, KEY_DOUBLE_QUOTE, KEY_HASH, KEY_DOLLAR, KEY_AMPERSAND, KEY_QUOTE, KEY_BACKQUOTE, KEY_LEFT_PARENTHESIS, KEY_RIGHT_PARENTHESIS, KEY_ASTERISK, KEY_PLUS, KEY_COMMA, KEY_MINUS, KEY_PERIOD, KEY_SLASH, KEY_COLON, KEY_SEMICOLON, KEY_LESS, KEY_EQUALS, KEY_GREATER, KEY_QUESTION, KEY_AT, KEY_LEFT_BRACKET, KEY_BACKSLASH, KEY_RIGHT_BRACKET, KEY_CARET, KEY_UNDERSCORE, KEY_LEFT_ALT, KEY_RIGHT_ALT, KEY_LEFT_CONTROL, KEY_RIGHT_CONTROL, KEY_LEFT_SHIFT, KEY_RIGHT_SHIFT, KEY_TAB, KEY_DELETE, KEY_PAGE_UP, KEY_PAGE_DOWN, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12, KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_PRINT, KEY_KP_0, KEY_KP_1, KEY_KP_2, KEY_KP_3, KEY_KP_4, KEY_KP_5, KEY_KP_6, KEY_KP_7, KEY_KP_8, KEY_KP_9, KEY_KP_PERIOD, KEY_KP_DIVIDE, KEY_KP_MULTIPLY, KEY_KP_MINUS, KEY_KP_PLUS, KEY_KP_ENTER, KEY_KP_EQUALS, KEY_HOME, KEY_END, // Put all new keys before this line. LAST_KEY }; // Key modifier is used for key combination detection. enum KeyModifier : int32_t { KEY_MODIFIER_NONE = 0, KEY_MODIFIER_CTRL = ( 1 << 0 ), KEY_MODIFIER_SHIFT = ( 1 << 1 ), KEY_MODIFIER_ALT = ( 1 << 2 ), KEY_MODIFIER_CAPS = ( 1 << 3 ), KEY_MODIFIER_NUM = ( 1 << 4 ) }; const char * KeySymGetName( const Key key ); size_t InsertKeySym( std::string & res, size_t pos, const Key key, const int32_t mod ); } class LocalEvent { public: friend class EventProcessing::EventEngine; static LocalEvent & Get(); static void initEventEngine(); static int32_t getCurrentKeyModifiers(); // Only one instance of the class can exist. LocalEvent( const LocalEvent & ) = delete; LocalEvent & operator=( const LocalEvent & ) = delete; // Reset all previous event statuses. void reset() { _actionStates = 0; } void setGlobalMouseMotionEventHook( std::function hook ) { _globalMouseMotionEventHook = std::move( hook ); } void setGlobalKeyDownEventHook( std::function hook ) { _globalKeyDownEventHook = std::move( hook ); } // Return false when event handling should be stopped, true otherwise. bool HandleEvents( const bool sleepAfterEventProcessing = true, const bool allowExit = false ); bool hasMouseMoved() const { return ( _actionStates & MOUSE_MOTION ) == MOUSE_MOTION; } const fheroes2::Point & getMouseCursorPos() const { return _mouseCursorPos; } const fheroes2::Point & getMouseLeftButtonPressedPos() const { return _mousePressLeftPos; } bool MouseClickLeft(); bool MouseClickMiddle(); bool MouseClickRight(); bool MouseClickLeft( const fheroes2::Rect & area ); bool MouseClickRight( const fheroes2::Rect & area ); // The long press event is triggered only once. If this event was triggered (i.e. this method was called // and returned true), then after releasing the mouse button, the click event will not be triggered. bool MouseLongPressLeft( const fheroes2::Rect & rt ); bool isMouseWheelUp() const { return ( _actionStates & MOUSE_WHEEL ) && _mouseWheelMovementOffset.y > 0; } bool isMouseWheelDown() const { return ( _actionStates & MOUSE_WHEEL ) && _mouseWheelMovementOffset.y < 0; } bool isMouseLeftButtonPressed() const { return ( _actionStates & MOUSE_PRESSED ) && _currentMouseButton == MouseButtonType::MOUSE_BUTTON_LEFT; } bool isMouseLeftButtonPressedInArea( const fheroes2::Rect & area ) const { return isMouseLeftButtonPressed() && ( area & _mousePressLeftPos ); } bool isMouseRightButtonPressed() const { return ( _actionStates & MOUSE_PRESSED ) && _currentMouseButton == MouseButtonType::MOUSE_BUTTON_RIGHT; } bool isMouseRightButtonPressedInArea( const fheroes2::Rect & area ) const { return isMouseRightButtonPressed() && ( area & _mousePressRightPos ); } bool isMouseLeftButtonReleased() const { return ( _actionStates & MOUSE_RELEASED ) && _currentMouseButton == MouseButtonType::MOUSE_BUTTON_LEFT; } bool isMouseLeftButtonReleasedInArea( const fheroes2::Rect & area ) const { return isMouseLeftButtonReleased() && ( area & _mouseReleaseLeftPos ); } bool isMouseWheelUpInArea( const fheroes2::Rect & area ) const { return isMouseWheelUp() && ( area & _mouseCursorPos ); } bool isMouseWheelDownInArea( const fheroes2::Rect & area ) const { return isMouseWheelDown() && ( area & _mouseCursorPos ); } bool isMouseCursorPosInArea( const fheroes2::Rect & area ) const { return area & _mouseCursorPos; } // Returns true if the current mouse event is triggered by the touchpad and not the mouse (in other words, // this event is emulated using the touchpad). It is assumed that there is only one mouse in the system, // and touchpad events have priority in this sense - that is, as long as the touchpad emulates pressing any // mouse button, it is assumed that all mouse events are triggered by the touchpad. bool isMouseEventFromTouchpad() const { return _actionStates & MOUSE_TOUCH; } bool isAnyKeyPressed() const { return _actionStates & KEY_PRESSED; } bool isKeyPressed( const fheroes2::Key key ) const { return key == _currentKeyboardValue && ( _actionStates & KEY_PRESSED ); } bool isKeyBeingHold() const { return ( _actionStates & KEY_HOLD ) != 0; } fheroes2::Key getPressedKeyValue() const { return _currentKeyboardValue; } void initController(); void CloseController(); void SetControllerPointerSpeed( const int newSpeed ) { if ( newSpeed > 0 ) { _controllerPointerSpeed = newSpeed / _constrollerSpeedModifier; } } bool isDragInProgress() const { return _actionStates & DRAG_ONGOING; } void registerDrag() { setStates( DRAG_ONGOING ); } private: enum class MouseButtonType : uint8_t { MOUSE_BUTTON_UNKNOWN, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_RIGHT }; enum class KeyboardEventState : uint8_t { KEY_UNKNOWN, KEY_DOWN, KEY_UP }; enum class ControllerAxisType : uint8_t { CONTROLLER_AXIS_UNKNOWN, CONTROLLER_AXIS_LEFT_X, CONTROLLER_AXIS_LEFT_Y, CONTROLLER_AXIS_RIGHT_X, CONTROLLER_AXIS_RIGHT_Y }; enum class ControllerButtonType : uint8_t { CONTROLLER_BUTTON_UNKNOWN, CONTROLLER_BUTTON_A, CONTROLLER_BUTTON_B, CONTROLLER_BUTTON_X, CONTROLLER_BUTTON_Y, CONTROLLER_BUTTON_RIGHT_SHOULDER, CONTROLLER_BUTTON_LEFT_SHOULDER, CONTROLLER_BUTTON_DPAD_UP, CONTROLLER_BUTTON_DPAD_DOWN, CONTROLLER_BUTTON_DPAD_RIGHT, CONTROLLER_BUTTON_DPAD_LEFT, CONTROLLER_BUTTON_BACK, CONTROLLER_BUTTON_START, CONTROLLER_BUTTON_GUIDE }; enum class TouchFingerEventType : uint8_t { FINGER_EVENT_UNKNOWN, FINGER_EVENT_DOWN, FINGER_EVENT_UP, FINGER_EVENT_MOTION }; enum : uint32_t { NO_EVENT = 0, // Key on the keyboard has been pressed KEY_PRESSED = ( 1 << 0 ), // Mouse cursor has been moved MOUSE_MOTION = ( 1 << 1 ), // Mouse button is currently pressed MOUSE_PRESSED = ( 1 << 2 ), // Mouse button has just been released MOUSE_RELEASED = ( 1 << 3 ), // Mouse wheel has been rotated MOUSE_WHEEL = ( 1 << 4 ), // Current mouse event has been triggered by the touchpad MOUSE_TOUCH = ( 1 << 5 ), // Key on the keyboard is currently being held down KEY_HOLD = ( 1 << 6 ), // Some UI component registered the start of drag motion DRAG_ONGOING = ( 1 << 7 ), }; enum : int16_t { CONTROLLER_L_DEADZONE = 4000, CONTROLLER_R_DEADZONE = 25000 }; class LongPressDelay final : public fheroes2::TimeDelay { public: using TimeDelay::TimeDelay; void reset() { TimeDelay::reset(); _triggered = false; } bool isTriggered() const { return _triggered; } void setTriggered() { _triggered = true; } private: bool _triggered{ false }; }; std::unique_ptr _engine; uint32_t _actionStates{ NO_EVENT }; fheroes2::Key _currentKeyboardValue{ fheroes2::Key::NONE }; MouseButtonType _currentMouseButton{ MouseButtonType::MOUSE_BUTTON_UNKNOWN }; fheroes2::Point _mousePressLeftPos; fheroes2::Point _mousePressMiddlePos; fheroes2::Point _mousePressRightPos; fheroes2::Point _mouseReleaseLeftPos; fheroes2::Point _mouseReleaseMiddlePos; fheroes2::Point _mouseReleaseRightPos; fheroes2::Point _mouseCursorPos; fheroes2::Point _mouseWheelMovementOffset; LongPressDelay _mouseButtonLongPressDelay; std::function _globalMouseMotionEventHook; std::function _globalKeyDownEventHook; fheroes2::Rect _mouseCursorRenderArea; // used to convert user-friendly pointer speed values into more usable ones const double _constrollerSpeedModifier{ 2000000.0 }; double _controllerPointerSpeed{ 10.0 / _constrollerSpeedModifier }; fheroes2::PointBase2D _emulatedPointerPos; // bigger value corresponds to faster pointer movement speed with bigger stick axis values const double _controllerAxisSpeedup{ 1.03 }; const double _controllerTriggerCursorSpeedup{ 2.0 }; fheroes2::Time _controllerTimer; int16_t _controllerLeftXAxis{ 0 }; int16_t _controllerLeftYAxis{ 0 }; int16_t _controllerRightXAxis{ 0 }; int16_t _controllerRightYAxis{ 0 }; bool _controllerScrollActive{ false }; // IDs of currently active (touching the touchpad) fingers, if any. These IDs consist of a touch device id and a finger id. std::pair>, std::optional>> _fingerIds; // Is the two-finger gesture currently being processed bool _isTwoFingerGestureInProgress = false; static void StopSounds(); static void ResumeSounds(); static void onRenderDeviceResetEvent(); LocalEvent(); void onMouseMotionEvent( fheroes2::Point position ); void onMouseButtonEvent( const bool isPressed, const MouseButtonType buttonType, fheroes2::Point position ); void onKeyboardEvent( const fheroes2::Key key, const int32_t keyModifier, const KeyboardEventState keyState ); void onMouseWheelEvent( fheroes2::Point position ); void onControllerAxisEvent( const ControllerAxisType axisType, const int16_t value ); void onControllerButtonEvent( const bool isPressed, const ControllerButtonType buttonType ); void onTouchFingerEvent( const TouchFingerEventType eventType, const int64_t touchId, const int64_t fingerId, fheroes2::PointBase2D position ); void ProcessControllerAxisMotion(); void setStates( const uint32_t states ) { _actionStates |= states; } void resetStates( const uint32_t states ) { _actionStates &= ~states; } }; fheroes2-1.1.6+dfsg/src/engine/logging.cpp000066400000000000000000000121771476115357100203630ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #if defined( _WIN32 ) #define WIN32_LEAN_AND_MEAN #include #endif #if defined( MACOS_APP_BUNDLE ) #include #endif #include "logging.h" #include "system.h" namespace { int debugLevel = DBG_ALL_WARN; bool textSupportMode = false; #if defined( _WIN32 ) // Sets the Windows console codepage to the system codepage class ConsoleCPSwitcher { public: ConsoleCPSwitcher() : _consoleOutputCP( GetConsoleOutputCP() ) { if ( _consoleOutputCP > 0 ) { SetConsoleOutputCP( GetACP() ); } } ConsoleCPSwitcher( const ConsoleCPSwitcher & ) = delete; ~ConsoleCPSwitcher() { if ( _consoleOutputCP > 0 ) { SetConsoleOutputCP( _consoleOutputCP ); } } ConsoleCPSwitcher & operator=( const ConsoleCPSwitcher & ) = delete; private: const UINT _consoleOutputCP; }; const ConsoleCPSwitcher consoleCPSwitcher; #endif } namespace Logging { #if defined( TARGET_NINTENDO_SWITCH ) || defined( _WIN32 ) std::ofstream logFile; // This mutex protects operations with logFile std::mutex logMutex; #endif const char * GetDebugOptionName( const int name ) { if ( name & DBG_ENGINE ) return "DBG_ENGINE"; else if ( name & DBG_GAME ) return "DBG_GAME"; else if ( name & DBG_BATTLE ) return "DBG_BATTLE"; else if ( name & DBG_AI ) return "DBG_AI"; else if ( name & DBG_NETWORK ) return "DBG_NETWORK"; else if ( name & DBG_OTHER ) return "DBG_OTHER"; else if ( name & DBG_DEVEL ) return "DBG_DEVEL"; return ""; } std::string GetTimeString() { const tm tmi = System::GetTM( std::time( nullptr ) ); std::array buf; const size_t writtenBytes = std::strftime( buf.data(), buf.size(), "%d.%m.%Y %H:%M:%S", &tmi ); if ( writtenBytes == 0 ) { assert( 0 ); return ""; } return std::string( buf.data() ); } void InitLog() { #if defined( TARGET_NINTENDO_SWITCH ) const std::scoped_lock lock( logMutex ); logFile.open( "fheroes2.log", std::ofstream::out ); #elif defined( _WIN32 ) const std::scoped_lock lock( logMutex ); const std::string configDir = System::GetConfigDirectory( "fheroes2" ); System::MakeDirectory( configDir ); logFile.open( System::concatPath( configDir, "fheroes2.log" ), std::ofstream::out ); #elif defined( MACOS_APP_BUNDLE ) openlog( "fheroes2", LOG_CONS | LOG_NDELAY, LOG_USER ); setlogmask( LOG_UPTO( LOG_WARNING ) ); #endif } void setDebugLevel( const int level ) { debugLevel = level; } int getDebugLevel() { return debugLevel; } void setTextSupportMode( const bool enableTextSupportMode ) { textSupportMode = enableTextSupportMode; } bool isTextSupportModeEnabled() { return textSupportMode; } } bool IS_DEBUG( const int name, const int level ) { return ( ( DBG_ENGINE & name ) && ( ( DBG_ENGINE & debugLevel ) >> 2 ) >= level ) || ( ( DBG_GAME & name ) && ( ( DBG_GAME & debugLevel ) >> 4 ) >= level ) || ( ( DBG_BATTLE & name ) && ( ( DBG_BATTLE & debugLevel ) >> 6 ) >= level ) || ( ( DBG_AI & name ) && ( ( DBG_AI & debugLevel ) >> 8 ) >= level ) || ( ( DBG_NETWORK & name ) && ( ( DBG_NETWORK & debugLevel ) >> 10 ) >= level ) || ( ( DBG_DEVEL & name ) && ( ( DBG_DEVEL & debugLevel ) >> 12 ) >= level ); } fheroes2-1.1.6+dfsg/src/engine/logging.h000066400000000000000000000317451476115357100200320ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include // IWYU pragma: keep #include enum { DBG_WARN = 0x0001, DBG_INFO = 0x0002, DBG_TRACE = 0x0003, DBG_ENGINE = 0x000C, DBG_GAME = 0x0030, DBG_BATTLE = 0x00C0, DBG_AI = 0x0300, DBG_NETWORK = 0x0C00, DBG_OTHER = 0x3000, DBG_DEVEL = 0xC000, DBG_ENGINE_WARN = 0x0004, DBG_GAME_WARN = 0x0010, DBG_BATTLE_WARN = 0x0040, DBG_AI_WARN = 0x0100, DBG_NETWORK_WARN = 0x0400, DBG_OTHER_WARN = 0x1000, DBG_ENGINE_INFO = 0x0008, DBG_GAME_INFO = 0x0020, DBG_BATTLE_INFO = 0x0080, DBG_AI_INFO = 0x0200, DBG_NETWORK_INFO = 0x0800, DBG_OTHER_INFO = 0x2000, DBG_ENGINE_TRACE = DBG_ENGINE, DBG_GAME_TRACE = DBG_GAME, DBG_BATTLE_TRACE = DBG_BATTLE, DBG_AI_TRACE = DBG_AI, DBG_NETWORK_TRACE = DBG_NETWORK, DBG_OTHER_TRACE = DBG_OTHER, DBG_ALL = DBG_ENGINE | DBG_GAME | DBG_BATTLE | DBG_AI | DBG_NETWORK | DBG_OTHER, DBG_ALL_WARN = DBG_ENGINE_WARN | DBG_GAME_WARN | DBG_BATTLE_WARN | DBG_AI_WARN | DBG_NETWORK_WARN | DBG_OTHER_WARN, DBG_ALL_INFO = DBG_ENGINE_INFO | DBG_GAME_INFO | DBG_BATTLE_INFO | DBG_AI_INFO | DBG_NETWORK_INFO | DBG_OTHER_INFO, DBG_ALL_TRACE = DBG_ENGINE_TRACE | DBG_GAME_TRACE | DBG_BATTLE_TRACE | DBG_AI_TRACE | DBG_NETWORK_TRACE | DBG_OTHER_TRACE }; #if defined( TARGET_NINTENDO_SWITCH ) || defined( _WIN32 ) #include #include namespace Logging { extern std::ofstream logFile; // This mutex protects operations with logFile extern std::mutex logMutex; } #endif namespace Logging { const char * GetDebugOptionName( const int name ); std::string GetTimeString(); // Initialize logging. Some systems require writing logging information into a file. void InitLog(); void setDebugLevel( const int level ); int getDebugLevel(); void setTextSupportMode( const bool enableTextSupportMode ); bool isTextSupportModeEnabled(); } #if defined( _WIN32 ) && defined( WITH_DEBUG ) #define COUT( x ) \ { \ const std::scoped_lock _logfile_lock( Logging::logMutex ); /* The name was chosen on purpose to avoid name collisions with outer code blocks. */ \ \ Logging::logFile << x << std::endl; \ Logging::logFile.flush(); \ std::cerr << x << std::endl; \ } #elif defined( TARGET_NINTENDO_SWITCH ) || defined( _WIN32 ) #define COUT( x ) \ { \ const std::scoped_lock _logfile_lock( Logging::logMutex ); /* The name was chosen on purpose to avoid name collisions with outer code blocks. */ \ \ Logging::logFile << x << std::endl; \ Logging::logFile.flush(); \ } #elif defined( TARGET_PS_VITA ) #include #define COUT( x ) \ { \ std::ostringstream _log_strstream; /* The name was chosen on purpose to avoid name collisions with outer code blocks. */ \ _log_strstream << x << std::endl; \ sceClibPrintf( "%s", _log_strstream.str().c_str() ); \ } #elif defined( MACOS_APP_BUNDLE ) #include #define COUT( x ) \ { \ std::ostringstream _log_strstream; /* The name was chosen on purpose to avoid name collisions with outer code blocks. */ \ _log_strstream << x; \ syslog( LOG_WARNING, "fheroes2_log: %s", _log_strstream.str().c_str() ); \ } #elif defined( ANDROID ) #include #define COUT( x ) \ { \ std::ostringstream _log_strstream; /* The name was chosen on purpose to avoid name collisions with outer code blocks. */ \ _log_strstream << x; \ __android_log_print( ANDROID_LOG_INFO, "fheroes2", "%s", _log_strstream.str().c_str() ); \ } #elif defined( __EMSCRIPTEN__ ) #include #define COUT( x ) \ { \ std::ostringstream _log_strstream; /* The name was chosen on purpose to avoid name collisions with outer code blocks. */ \ _log_strstream << x; \ emscripten_out( _log_strstream.str().c_str() ); \ } #else // Default: log to stderr #define COUT( x ) \ { \ std::cerr << x << std::endl; \ } #endif #define VERBOSE_LOG( x ) \ { \ COUT( Logging::GetTimeString() << ": [VERBOSE]\t" << __FUNCTION__ << ": " << x ); \ } #define ERROR_LOG( x ) \ { \ COUT( Logging::GetTimeString() << ": [ERROR]\t" << __FUNCTION__ << ": " << x ); \ } #ifdef WITH_DEBUG #define DEBUG_LOG( x, y, z ) \ if ( IS_DEBUG( x, y ) ) { \ COUT( Logging::GetTimeString() << ": [" << Logging::GetDebugOptionName( x ) << "]\t" << __FUNCTION__ << ": " << z ); \ } #else #define DEBUG_LOG( x, y, z ) #endif #define IS_DEVEL() IS_DEBUG( DBG_DEVEL, DBG_INFO ) bool IS_DEBUG( const int name, const int level ); namespace Logging { // This structure simply adds text separators. It is used for Text Support Mode only. struct TextSupportLogger { TextSupportLogger(){ COUT( "----------" ) } TextSupportLogger( const TextSupportLogger & ) = delete; TextSupportLogger( const TextSupportLogger && ) = delete; TextSupportLogger & operator=( const TextSupportLogger & ) = delete; TextSupportLogger & operator=( const TextSupportLogger && ) = delete; ~TextSupportLogger() { COUT( "----------" ) } }; } // Put this macro at the beginning of code block (eg. function) which is responsible for text support mode output. #define START_TEXT_SUPPORT_MODE \ if ( !Logging::isTextSupportModeEnabled() ) { \ return; \ } \ const Logging::TextSupportLogger _temp_logger; // The name was chosen on purpose to avoid collisions with other variable names within a code block. fheroes2-1.1.6+dfsg/src/engine/math_base.h000066400000000000000000000177301476115357100203250ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif // Below source code was partially taken from https://github.com/ihhub/penguinv open source project namespace fheroes2 { // overload this function for floating types template bool isEqual( const _Type & value1, const _Type & value2 ) { return ( value1 == value2 ); } template struct PointBase2D { PointBase2D() : x( 0 ) , y( 0 ) {} PointBase2D( _Type _x, _Type _y ) : x( _x ) , y( _y ) {} bool operator==( const PointBase2D & point ) const { return isEqual( x, point.x ) && isEqual( y, point.y ); } bool operator!=( const PointBase2D & point ) const { return !( *this == point ); } PointBase2D & operator+=( const PointBase2D & point ) { x += point.x; y += point.y; return *this; } PointBase2D & operator-=( const PointBase2D & point ) { x -= point.x; y -= point.y; return *this; } PointBase2D operator+( const PointBase2D & point ) const { return PointBase2D( x + point.x, y + point.y ); } PointBase2D operator-( const PointBase2D & point ) const { return PointBase2D( x - point.x, y - point.y ); } bool operator<( const PointBase2D & point ) const { return x == point.x ? y < point.y : x < point.x; } _Type x; _Type y; }; template struct SizeBase2D { SizeBase2D() : width( 0 ) , height( 0 ) {} SizeBase2D( _Type _width, _Type _height ) : width( _width ) , height( _height ) {} bool operator==( const SizeBase2D & size ) const { return isEqual( width, size.width ) && isEqual( height, size.height ); } bool operator!=( const SizeBase2D & size ) const { return !( *this == size ); } bool operator<( const SizeBase2D & size ) const { return width < size.width || ( width == size.width && height < size.height ); } SizeBase2D & operator+=( const SizeBase2D & size ) { width += size.width; height += size.height; return *this; } SizeBase2D & operator-=( const SizeBase2D & size ) { width -= size.width; height -= size.height; return *this; } SizeBase2D operator+( const SizeBase2D & size ) const { return SizeBase2D( width + size.width, height + size.height ); } SizeBase2D operator-( const SizeBase2D & size ) const { return SizeBase2D( width - size.width, height - size.height ); } _Type width; _Type height; }; template struct RectBase2D { RectBase2D() : x( 0 ) , y( 0 ) , width( 0 ) , height( 0 ) {} RectBase2D( _TypePoint _x, _TypePoint _y, _TypeSize _width, _TypeSize _height ) : x( _x ) , y( _y ) , width( _width ) , height( _height ) {} RectBase2D( const PointBase2D<_TypePoint> & point, const SizeBase2D<_TypeSize> & size ) : x( point.x ) , y( point.y ) , width( size.width ) , height( size.height ) {} bool operator==( const RectBase2D & rect ) const { return isEqual( x, rect.x ) && isEqual( y, rect.y ) && isEqual( width, rect.width ) && isEqual( height, rect.height ); } bool operator!=( const RectBase2D & rect ) const { return !( *this == rect ); } RectBase2D & operator+=( const PointBase2D<_TypePoint> & point ) { x += point.x; y += point.y; return *this; } RectBase2D & operator-=( const PointBase2D<_TypePoint> & point ) { x -= point.x; y -= point.y; return *this; } RectBase2D operator+( const PointBase2D<_TypePoint> & point ) const { return RectBase2D( x + point.x, y + point.y, width, height ); } RectBase2D operator-( const PointBase2D<_TypePoint> & point ) const { return RectBase2D( x - point.x, y - point.y, width, height ); } // Check whether a point within the rectangle bool operator&( const PointBase2D<_TypePoint> & point ) const { return point.x >= x && point.y >= y && point.x < ( x + width ) && point.y < ( y + height ); } // Check whether rectangles are intersecting each other bool operator&( const RectBase2D & rect ) const { return x <= rect.x + rect.width && rect.x <= x + width && y <= rect.y + rect.height && rect.y <= y + height; } // Find intersection rectangle RectBase2D operator^( const RectBase2D & rect ) const { RectBase2D output = rect; if ( output.x < x ) { const _TypePoint diff = x - output.x; output.x = x; output.width -= diff; } if ( output.y < y ) { const _TypePoint diff = y - output.y; output.y = y; output.height -= diff; } if ( output.x > x + width || output.y > y + height ) return RectBase2D(); if ( output.x + output.width > x + width ) { const _TypePoint diff = output.x + output.width - ( x + width ); output.width -= diff; } if ( output.y + output.height > y + height ) { const _TypePoint diff = output.y + output.height - ( y + height ); output.height -= diff; } return output; } PointBase2D<_TypePoint> getPosition() const { return PointBase2D<_TypePoint>( x, y ); } _TypePoint x; _TypePoint y; _TypeSize width; _TypeSize height; }; using Point = PointBase2D; using Size = SizeBase2D; using Rect = RectBase2D; } fheroes2-1.1.6+dfsg/src/engine/math_tools.cpp000066400000000000000000000154001476115357100210760ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "math_tools.h" #include #include #include double fheroes2::GetAngle( const Point & start, const Point & target ) { const int dx = target.x - start.x; const int dy = target.y - start.y; double angle = atan2( -dy, dx ) * 180.0 / M_PI; // we only care about two quadrants, normalize if ( dx < 0 ) { angle = ( dy <= 0 ) ? 180 - angle : -angle - 180; } return angle; } std::vector fheroes2::GetEuclideanLine( const Point & pt1, const Point & pt2, const uint32_t step ) { const int dx = pt2.x - pt1.x; const int dy = pt2.y - pt1.y; const uint32_t dist = static_cast( std::hypot( dx, dy ) ); // Round up the integer division and avoid the division by zero in calculation of total line points. const uint32_t length = ( step > 0 ) ? ( dist + step / 2 ) / step : 0; std::vector line; if ( length < 2 ) { // If the length is equal to 0 than 'pt2' could be closer to 'pt1' than 'step'. // In this case we put 'pt1' as the start of the line. line.emplace_back( pt1 ); // And put 'pt2' as the end of the line only if 'pt1' is not equal to 'pt2'. if ( pt1 != pt2 ) { line.emplace_back( pt2 ); } } else { // Otherwise we calculate the euclidean line, using the determined parameters. const double moveX = dx / static_cast( length ); const double moveY = dy / static_cast( length ); line.reserve( length + 1 ); for ( uint32_t i = 0; i <= length; ++i ) { line.emplace_back( static_cast( pt1.x + i * moveX ), static_cast( pt1.y + i * moveY ) ); } } return line; } std::vector fheroes2::GetLinePoints( const Point & pt1, const Point & pt2, const int32_t step ) { std::vector res; const int32_t dx = std::abs( pt2.x - pt1.x ); const int32_t dy = std::abs( pt2.y - pt1.y ); int32_t ns = ( dx > dy ? dx : dy ) / 2; Point pt( pt1 ); for ( int32_t i = 0; i <= ( dx > dy ? dx : dy ); ++i ) { if ( dx > dy ) { pt.x < pt2.x ? ++pt.x : --pt.x; ns -= dy; } else { pt.y < pt2.y ? ++pt.y : --pt.y; ns -= dx; } if ( ns < 0 ) { if ( dx > dy ) { pt.y < pt2.y ? ++pt.y : --pt.y; ns += dx; } else { pt.x < pt2.x ? ++pt.x : --pt.x; ns += dy; } } if ( 0 == ( i % step ) ) res.push_back( pt ); } return res; } std::vector fheroes2::GetArcPoints( const Point & from, const Point & to, const int32_t arcHeight, const int32_t step ) { std::vector res; Point pt( from ); // The first projectile point is "from" res.push_back( pt ); // Calculate the number of projectile trajectory points const int32_t steps = ( to.x - from.x ) / step; // Trajectory start point coordinates const double x1 = from.x; const double y1 = from.y; // Distance to the destination point along the axes const double dx = to.x - x1; const double dy = to.y - y1; // The movement of the projectile is determined according to the parabolic // throwing approximation. The first two parabola points are "from" and // "to" with an exception that the second ("to") point is at the same // height as the start point. The parabola third point "y" coordinate is // set using the "arcHeight" parameter, which determines the height of the // parabola arc. And its "x" coordinate is taken equal to half the path // from the start point to the end point. Using this three point // coordinates, a system of three linear equations (y=a*x*x+b*x+c) in // three variables is solved by substituting these points "x" and "y". // Considering that on an isometric battlefield, the target location above // or below corresponds to a simple turn of the shooter to the left or // right, a linear movement from point "from" to point "to" is added to the // parabola ('dy/dx' in 'b' constant and '-x1*dy/dx' in 'c' constant). // Calculation of the parabola equation coefficients const double a = 4 * arcHeight / dx / dx; const double b = dy / dx - a * ( dx + 2 * x1 ); const double c = y1 + a * x1 * ( dx + x1 ) - x1 * dy / dx; for ( int32_t i = 1; i <= steps; ++i ) { pt.x += step; pt.y = static_cast( std::lround( a * pt.x * pt.x + b * pt.x + c ) ); res.push_back( pt ); } return res; } int32_t fheroes2::GetRectIndex( const std::vector & rects, const Point & pt ) { for ( size_t i = 0; i < rects.size(); ++i ) { if ( rects[i] & pt ) return static_cast( i ); } return -1; } fheroes2::Rect fheroes2::getBoundaryRect( const Rect & rt1, const Rect & rt2 ) { if ( rt2.width == 0 && rt2.height == 0 ) { return rt1; } if ( rt1.width == 0 && rt1.height == 0 ) { return rt2; } const int32_t x = std::min( rt1.x, rt2.x ); const int32_t y = std::min( rt1.y, rt2.y ); const int32_t width = std::max( rt1.x + rt1.width, rt2.x + rt2.width ) - x; const int32_t height = std::max( rt1.y + rt1.height, rt2.y + rt2.height ) - y; return { x, y, width, height }; } fheroes2-1.1.6+dfsg/src/engine/math_tools.h000066400000000000000000000040571476115357100205510ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "math_base.h" namespace fheroes2 { double GetAngle( const Point & start, const Point & target ); std::vector GetEuclideanLine( const Point & pt1, const Point & pt2, const uint32_t step ); std::vector GetLinePoints( const Point & pt1, const Point & pt2, const int32_t step ); std::vector GetArcPoints( const Point & from, const Point & to, const int32_t arcHeight, const int32_t step ); int32_t GetRectIndex( const std::vector & rects, const Point & pt ); Rect getBoundaryRect( const Rect & rt1, const Rect & rt2 ); } fheroes2-1.1.6+dfsg/src/engine/pal.cpp000066400000000000000000000541471476115357100175140ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pal.h" #include #include #include namespace { const size_t paletteSize = 256; const std::vector yellowTextTable = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 114, 115, 115, 116, 117, 117, 118, 119, 119, 120, 121, 121, 122, 123, 123, 124, 125, 125, 126, 127, 127, 128, 129, 129, 130, 130, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const std::vector whiteTextTable = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const std::vector grayTextTable = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const std::vector tanTable = { 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 200, 201, 203, 204, 206, 207, 208, 209, 210, 211, 213, 213, 213, 213, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 200, 201, 203, 204, 205, 207, 207, 209, 210, 211, 212, 198, 198, 198, 198, 198, 201, 203, 205, 207, 208, 210, 210, 211, 212, 212, 213, 213, 213, 213, 213, 213, 213, 198, 198, 198, 199, 201, 203, 204, 206, 207, 208, 209, 210, 211, 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 200, 201, 203, 204, 206, 207, 198, 198, 198, 198, 198, 198, 198, 198, 198, 200, 201, 203, 204, 206, 207, 208, 209, 210, 212, 213, 213, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 201, 203, 204, 206, 207, 208, 209, 211, 212, 213, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 201, 202, 204, 206, 207, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 199, 202, 205, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 198, 200, 203, 204, 207, 208, 209, 201, 203, 207, 209, 206, 209, 208, 198, 198, 207, 213, 198, 201, 206, 208, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213 }; const std::vector noCycleTable = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 188, 188, 188, 188, 118, 118, 118, 118, 222, 223, 224, 225, 226, 227, 228, 229, 230, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; const std::vector grayTable = { 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 20, 21, 22, 22, 23, 24, 25, 26, 26, 27, 28, 29, 31, 14, 16, 17, 18, 20, 21, 22, 24, 25, 26, 28, 28, 29, 30, 31, 32, 32, 33, 33, 33, 34, 34, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 32, 33, 34, 35, 35, 36, 36, 36, 11, 11, 11, 11, 11, 12, 12, 12, 13, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 22, 23, 24, 25, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 24, 24, 25, 26, 27, 28, 29, 31, 32, 32, 33, 11, 12, 12, 13, 14, 14, 16, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 32, 10, 11, 11, 12, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 10, 10, 11, 11, 11, 12, 12, 12, 12, 14, 16, 17, 18, 20, 22, 24, 17, 10, 12, 15, 19, 10, 10, 15, 17, 18, 20, 21, 22, 23, 25, 26, 27, 27, 24, 21, 22, 26, 26, 27, 36, 12, 18, 25, 19, 21, 24, 26, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36 }; const std::vector redTable = { 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 180, 182, 184, 186, 208, 209, 210, 210, 211, 211, 212, 213, 213, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 180, 180, 182, 182, 184, 186, 208, 209, 209, 210, 210, 210, 211, 211, 193, 212, 212, 213, 213, 196, 197, 197, 197, 197, 197, 197, 208, 209, 210, 211, 193, 212, 213, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 209, 210, 210, 211, 212, 212, 213, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 180, 180, 180, 180, 180, 182, 182, 183, 184, 185, 208, 188, 189, 190, 210, 191, 211, 193, 193, 194, 195, 196, 197, 182, 184, 208, 209, 209, 210, 211, 211, 212, 213, 213, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 209, 209, 210, 210, 211, 211, 193, 212, 213, 213, 213, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 180, 180, 180, 182, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 187, 211, 180, 180, 215, 191, 192, 193, 194, 213, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 211, 197, 211, 212, 196, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197 }; const std::vector brownTable = { 50, 42, 42, 42, 42, 50, 50, 50, 50, 53, 42, 43, 43, 44, 44, 45, 46, 46, 47, 47, 48, 49, 50, 51, 52, 52, 53, 54, 55, 56, 57, 58, 60, 62, 62, 62, 62, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 45, 46, 47, 48, 50, 51, 52, 54, 55, 56, 58, 58, 59, 60, 60, 61, 62, 62, 62, 62, 62, 62, 47, 48, 49, 50, 51, 52, 53, 54, 55, 57, 58, 58, 60, 60, 62, 62, 62, 62, 62, 62, 62, 62, 62, 43, 43, 44, 44, 44, 45, 45, 45, 46, 47, 48, 48, 49, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 44, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57, 58, 60, 62, 62, 43, 43, 44, 44, 45, 45, 46, 47, 47, 48, 49, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 43, 44, 46, 47, 48, 49, 50, 52, 53, 54, 55, 57, 58, 60, 60, 62, 62, 62, 62, 62, 62, 62, 62, 44, 44, 45, 45, 46, 47, 48, 49, 50, 51, 53, 54, 55, 57, 58, 59, 54, 58, 62, 62, 42, 45, 49, 55, 47, 49, 50, 51, 52, 53, 55, 56, 58, 51, 52, 55, 57, 54, 57, 56, 44, 48, 54, 62, 49, 51, 54, 57, 50, 50, 50, 50, 50, 50, 50, 50, 50, 42 }; const std::vector mirrorImageTable = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 63, 63, 63, 63, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 85, 85, 85, 85, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 108, 108, 108, 108, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 131, 131, 131, 131, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 152, 152, 152, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 175, 175, 175, 175, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 198, 198, 198, 198, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224, 225, 226, 227, 228, 229, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 242, 243, 244, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; const std::vector darkeningTable = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 36, 36, 36, 36, 36, 36, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 62, 62, 62, 62, 62, 62, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 84, 84, 84, 84, 84, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 107, 107, 107, 107, 107, 107, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 130, 130, 130, 130, 130, 130, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 151, 151, 151, 151, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 174, 174, 174, 174, 174, 174, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 197, 197, 197, 197, 197, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 213, 213, 213, 213, 214, 215, 216, 217, 218, 219, 220, 221, 225, 226, 227, 228, 229, 230, 230, 230, 230, 73, 75, 77, 79, 81, 76, 78, 74, 76, 78, 80, 244, 245, 245, 245, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const std::vector goodToEvilInterfaceTable = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 14, 15, 16, 17, 17, 18, 23, 23, 24, 25, 26, 26, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 36, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, }; const std::vector goodToEvilButtonTable = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 14, 15, 16, 17, 17, 18, 19, 22, 21, 22, 23, 24, 25, 26, 26, 27, 32, 29, 30, 31, 32, 58, 59, 60, 61, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, }; const std::vector purpleTable = { 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 131, 132, 133, 133, 134, 135, 136, 136, 137, 138, 139, 139, 140, 141, 142, 142, 143, 144, 145, 145, 146, 147, 148, 149, 149, 150, 151, 131, 132, 133, 134, 134, 135, 136, 137, 138, 138, 139, 140, 141, 142, 142, 143, 144, 145, 146, 146, 147, 148, 149, 150, 150, 151, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 151, 131, 132, 133, 135, 136, 137, 139, 140, 141, 143, 144, 145, 147, 148, 149, 151, 142, 142, 142, 142, 140, 140, 140, 140, 131, 133, 135, 137, 141, 143, 147, 149, 151, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 141, 144, 148, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151 }; struct CyclingColorSet { uint8_t start; uint8_t length; bool forward; }; } std::vector PAL::GetCyclingPalette( const uint32_t stepId ) { std::vector palette = PAL::GetPalette( PaletteType::STANDARD ); static const std::array cycleSet{ CyclingColorSet{ 214, 4, false }, CyclingColorSet{ 218, 4, false }, CyclingColorSet{ 231, 5, true }, CyclingColorSet{ 238, 4, false } }; for ( const CyclingColorSet & colorSet : cycleSet ) { for ( uint32_t id = 0; id < colorSet.length; ++id ) { uint32_t newColorID; if ( colorSet.forward ) { newColorID = colorSet.start + ( ( id + stepId ) % colorSet.length ); } else { const uint32_t lastColorID = colorSet.length - 1; newColorID = colorSet.start + lastColorID - ( ( lastColorID + stepId - id ) % colorSet.length ); } palette[colorSet.start + id] = static_cast( newColorID ); } } return palette; } const std::vector & PAL::GetPalette( const PaletteType type ) { switch ( type ) { case PaletteType::YELLOW_FONT: { assert( yellowTextTable.size() == paletteSize ); return yellowTextTable; } case PaletteType::WHITE_FONT: { assert( whiteTextTable.size() == paletteSize ); return whiteTextTable; } case PaletteType::GRAY_FONT: { assert( grayTextTable.size() == paletteSize ); return grayTextTable; } case PaletteType::RED: { assert( redTable.size() == paletteSize ); return redTable; } case PaletteType::GRAY: { assert( grayTable.size() == paletteSize ); return grayTable; } case PaletteType::BROWN: { assert( brownTable.size() == paletteSize ); return brownTable; } case PaletteType::TAN: { assert( tanTable.size() == paletteSize ); return tanTable; } case PaletteType::NO_CYCLE: { assert( noCycleTable.size() == paletteSize ); return noCycleTable; } case PaletteType::MIRROR_IMAGE: { assert( mirrorImageTable.size() == paletteSize ); return mirrorImageTable; } case PaletteType::DARKENING: { assert( darkeningTable.size() == paletteSize ); return darkeningTable; } case PaletteType::GOOD_TO_EVIL_INTERFACE: { assert( goodToEvilInterfaceTable.size() == paletteSize ); return goodToEvilInterfaceTable; } case PaletteType::GOOD_TO_EVIL_BUTTON: { assert( goodToEvilButtonTable.size() == paletteSize ); return goodToEvilButtonTable; } case PaletteType::PURPLE: { assert( purpleTable.size() == paletteSize ); return purpleTable; } case PaletteType::CUSTOM: assert( 0 ); break; case PaletteType::STANDARD: break; default: // Did you add a new palette type? Add the corresponding palette for it! assert( 0 ); break; } static std::vector standard; if ( standard.empty() ) { standard.resize( paletteSize, 0 ); for ( size_t i = 0; i < paletteSize; ++i ) { standard[i] = static_cast( i ); } } return standard; } std::vector PAL::CombinePalettes( const std::vector & first, const std::vector & second ) { if ( first.size() != paletteSize || second.size() != paletteSize ) { // Make sure that the sizes of your palettes are correct! assert( 0 ); return std::vector(); } std::vector combined( paletteSize, 0 ); for ( size_t i = 0; i < paletteSize; ++i ) { combined[i] = second[first[i]]; } return combined; } fheroes2-1.1.6+dfsg/src/engine/pal.h000066400000000000000000000045731476115357100171570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace PAL { enum class PaletteType : int { STANDARD, // default YELLOW_FONT, WHITE_FONT, GRAY_FONT, RED, // for Blood Lust spell animation GRAY, // for Petrify spell effect BROWN, TAN, // for Puzzle image generation NO_CYCLE, MIRROR_IMAGE, DARKENING, // for disabled buttons GOOD_TO_EVIL_INTERFACE, // a custom palette for converting Good Interface images into Evil Interface images. GOOD_TO_EVIL_BUTTON, // for converting Good style buttons into Evil style buttons. PURPLE, // For random object images. CUSTOM }; std::vector GetCyclingPalette( const uint32_t stepId ); const std::vector & GetPalette( const PaletteType type ); std::vector CombinePalettes( const std::vector & first, const std::vector & second ); } fheroes2-1.1.6+dfsg/src/engine/rand.cpp000066400000000000000000000072271476115357100176610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "rand.h" #include std::mt19937 & Rand::CurrentThreadRandomDevice() { thread_local std::random_device rd; thread_local std::mt19937 gen( rd() ); return gen; } uint32_t Rand::Get( uint32_t from, uint32_t to /* = 0 */ ) { if ( from > to ) { std::swap( from, to ); } std::uniform_int_distribution distrib( from, to ); return distrib( CurrentThreadRandomDevice() ); } uint32_t Rand::GetWithSeed( uint32_t from, uint32_t to, uint32_t seed ) { if ( from > to ) { std::swap( from, to ); } std::uniform_int_distribution distrib( from, to ); std::mt19937 seededGen( seed ); return distrib( seededGen ); } uint32_t Rand::GetWithGen( uint32_t from, uint32_t to, std::mt19937 & gen ) { if ( from > to ) { std::swap( from, to ); } std::uniform_int_distribution distrib( from, to ); return distrib( gen ); } int32_t Rand::Queue::Get( const std::function & randomFunc ) const { if ( empty() ) { return 0; } const uint32_t sum = std::accumulate( begin(), end(), static_cast( 0 ), []( const uint32_t total, const ValueWeight & vw ) { return total + vw.second; } ); assert( sum > 0 ); uint32_t rand = randomFunc( sum - 1 ); assert( rand < sum ); for ( const auto & [value, weight] : *this ) { if ( rand < weight ) { return value; } rand -= weight; } assert( 0 ); return 0; } Rand::DeterministicRandomGenerator::DeterministicRandomGenerator( const uint32_t initialSeed ) : _currentSeed( initialSeed ) {} uint32_t Rand::DeterministicRandomGenerator::GetSeed() const { return _currentSeed; } void Rand::DeterministicRandomGenerator::UpdateSeed( const uint32_t seed ) { _currentSeed = seed; } uint32_t Rand::DeterministicRandomGenerator::Get( const uint32_t from, const uint32_t to /* = 0 */ ) { ++_currentSeed; return Rand::GetWithSeed( from, to, _currentSeed ); } fheroes2-1.1.6+dfsg/src/engine/rand.h000066400000000000000000000121271476115357100173210ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include namespace Rand { std::mt19937 & CurrentThreadRandomDevice(); uint32_t Get( uint32_t from, uint32_t to = 0 ); template , bool> = true> T Get( const T from, const T to ) { return static_cast( Get( static_cast( from ), static_cast( to ) ) ); } uint32_t GetWithSeed( uint32_t from, uint32_t to, uint32_t seed ); template , bool> = true> T GetWithSeed( const T from, const T to, const uint32_t seed ) { return static_cast( GetWithSeed( static_cast( from ), static_cast( to ), seed ) ); } uint32_t GetWithGen( uint32_t from, uint32_t to, std::mt19937 & gen ); template void Shuffle( std::vector & vec ) { std::shuffle( vec.begin(), vec.end(), CurrentThreadRandomDevice() ); } template void ShuffleWithGen( std::vector & vec, std::mt19937 & gen ) { std::shuffle( vec.begin(), vec.end(), gen ); } template const T & Get( const std::vector & vec ) { assert( !vec.empty() ); const uint32_t id = Rand::Get( static_cast( vec.size() - 1 ) ); return vec[id]; } template const T & GetWithGen( const std::vector & vec, std::mt19937 & gen ) { assert( !vec.empty() ); const uint32_t id = Rand::GetWithGen( 0, static_cast( vec.size() - 1 ), gen ); return vec[id]; } using ValueWeight = std::pair; class Queue : private std::vector { public: explicit Queue( uint32_t size = 0 ) { reserve( size ); } void Push( const int32_t value, const uint32_t weight ) { if ( weight == 0 ) { return; } emplace_back( value, weight ); } size_t Size() const { return size(); } int32_t Get() const { return Get( []( const uint32_t max ) { return Rand::Get( 0, max ); } ); } int32_t GetWithSeed( const uint32_t seed ) const { return Get( [seed]( const uint32_t max ) { return Rand::GetWithSeed( 0, max, seed ); } ); } private: int32_t Get( const std::function & randomFunc ) const; }; // Specific random generator that keeps and update its state class DeterministicRandomGenerator { public: explicit DeterministicRandomGenerator( const uint32_t initialSeed ); DeterministicRandomGenerator( const DeterministicRandomGenerator & ) = delete; DeterministicRandomGenerator & operator=( const DeterministicRandomGenerator & ) = delete; uint32_t GetSeed() const; void UpdateSeed( const uint32_t seed ); uint32_t Get( const uint32_t from, const uint32_t to = 0 ); template const T & Get( const std::vector & vec ) { ++_currentSeed; std::mt19937 seededGen( _currentSeed ); return Rand::GetWithGen( vec, seededGen ); } private: uint32_t _currentSeed; }; } fheroes2-1.1.6+dfsg/src/engine/render_processor.cpp000066400000000000000000000053711476115357100223110ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "render_processor.h" #include #include "pal.h" namespace { // The maximum FPS the engine can handle is 125. // This means that a frame should be generated only every 8 ms. const uint64_t frameHalfInterval{ 4 }; } namespace fheroes2 { RenderProcessor & RenderProcessor::instance() { static RenderProcessor processor; return processor; } bool RenderProcessor::preRenderAction( std::vector & palette ) { if ( !_enableCycling ) { return false; } if ( _enableRenderers && _preRenderer ) { _preRenderer(); } if ( _cyclingTimer.getMs() < ( _cyclingInterval - frameHalfInterval ) ) { // If the current timer is less than cycling internal minus half of the frame generation then nothing is needed. return false; } // TODO: here we need to deduct possible time difference from the current time to have consistent FPS. _cyclingTimer.reset(); palette = PAL::GetCyclingPalette( _cyclingCounter ); ++_cyclingCounter; return true; } void RenderProcessor::postRenderAction() { _lastRenderCall.reset(); if ( _enableCycling && _enableRenderers && _postRenderer ) { _postRenderer(); } } } fheroes2-1.1.6+dfsg/src/engine/render_processor.h000066400000000000000000000061731476115357100217570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "timing.h" namespace fheroes2 { class RenderProcessor { public: RenderProcessor( const RenderProcessor & ) = delete; ~RenderProcessor() = default; RenderProcessor & operator=( const RenderProcessor & ) = delete; static RenderProcessor & instance(); void registerRenderers( const std::function & preRenderer, const std::function & postRenderer ) { _preRenderer = preRenderer; _postRenderer = postRenderer; } void unregisterRenderers() { _preRenderer = {}; _postRenderer = {}; } void enableRenderers() { _enableRenderers = true; } void disableRenderers() { _enableRenderers = false; } bool preRenderAction( std::vector & palette ); void postRenderAction(); void startColorCycling() { _enableCycling = true; } void stopColorCycling() { _enableCycling = false; } bool isCyclingUpdateRequired() const { return _enableCycling && _lastRenderCall.getMs() >= _cyclingInterval; } private: RenderProcessor() = default; std::function _preRenderer; std::function _postRenderer; fheroes2::Time _cyclingTimer; fheroes2::Time _lastRenderCall; uint32_t _cyclingCounter{ 0 }; bool _enableRenderers{ false }; bool _enableCycling{ false }; static const uint64_t _cyclingInterval{ 220 }; }; } fheroes2-1.1.6+dfsg/src/engine/screen.cpp000066400000000000000000001614231476115357100202130ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wswitch-default" #endif #include #include #include #include #include #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif #if defined( TARGET_PS_VITA ) #include #endif #include "image_palette.h" #include "logging.h" #include "math_tools.h" #include "screen.h" #include "system.h" namespace { // Returns nearest screen supported resolution fheroes2::ResolutionInfo GetNearestResolution( fheroes2::ResolutionInfo resolutionInfo, const std::vector & resolutions ) { if ( resolutions.empty() ) { return resolutionInfo; } if ( resolutionInfo.gameWidth < 1 ) { resolutionInfo.gameWidth = 1; } if ( resolutionInfo.gameHeight < 1 ) { resolutionInfo.gameHeight = 1; } if ( resolutionInfo.screenWidth < resolutionInfo.gameWidth ) { resolutionInfo.screenWidth = resolutionInfo.gameWidth; } if ( resolutionInfo.screenHeight < resolutionInfo.gameHeight ) { resolutionInfo.screenHeight = resolutionInfo.gameHeight; } const double gameX = resolutionInfo.gameWidth; const double gameY = resolutionInfo.gameHeight; const double screenX = resolutionInfo.screenWidth; const double screenY = resolutionInfo.screenHeight; std::vector similarity( resolutions.size(), 0 ); for ( size_t i = 0; i < resolutions.size(); ++i ) { similarity[i] = std::fabs( resolutions[i].gameWidth - gameX ) / gameX + std::fabs( resolutions[i].gameHeight - gameY ) / gameY + std::fabs( resolutions[i].screenWidth - screenX ) / screenX + std::fabs( resolutions[i].screenHeight - screenY ) / screenY; } const std::vector::difference_type id = std::distance( similarity.begin(), std::min_element( similarity.begin(), similarity.end() ) ); return resolutions[id]; } #if !defined( TARGET_PS_VITA ) bool IsLowerThanDefaultRes( const fheroes2::ResolutionInfo & value ) { return value.gameWidth < fheroes2::Display::DEFAULT_WIDTH || value.gameHeight < fheroes2::Display::DEFAULT_HEIGHT; } std::set FilterResolutions( const std::set & resolutionSet ) { static_assert( fheroes2::Display::DEFAULT_WIDTH == 640 && fheroes2::Display::DEFAULT_HEIGHT == 480, "Default resolution must be 640 x 480" ); if ( resolutionSet.empty() ) { return { { fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT } }; } std::set resolutions; for ( const fheroes2::ResolutionInfo & resolution : resolutionSet ) { if ( IsLowerThanDefaultRes( resolution ) ) { continue; } resolutions.emplace( resolution ); } if ( resolutions.empty() ) { return { { fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT } }; } { // TODO: add resolutions which are close to the current screen aspect ratio. // Some operating systems do not work well with SDL so they return very limited number of high resolutions. // Populate missing resolutions into the list. const std::set possibleResolutions = { { 640, 480 }, { 800, 600 }, { 1024, 768 }, { 1152, 864 }, { 1280, 600 }, { 1280, 720 }, { 1280, 768 }, { 1280, 960 }, { 1280, 1024 }, { 1360, 768 }, { 1400, 1050 }, { 1440, 900 }, { 1600, 900 }, { 1680, 1050 }, { 1920, 1080 } }; assert( !resolutions.empty() ); const fheroes2::ResolutionInfo lowestResolution = *( resolutions.begin() ); for ( const fheroes2::ResolutionInfo & resolution : possibleResolutions ) { if ( lowestResolution.gameWidth < resolution.gameWidth || lowestResolution.gameHeight < resolution.gameHeight || lowestResolution == resolution ) { continue; } resolutions.emplace( resolution ); } } std::set scaledResolutions; { // Widescreen devices support much higher resolutions but items on such resolutions are too tiny. In order to improve user // experience on these devices we are adding a special non-standard resolution with (potentially) non-integer scale. assert( !resolutions.empty() ); const fheroes2::ResolutionInfo biggestResolution = *( std::prev( resolutions.end() ) ); assert( biggestResolution.gameWidth == biggestResolution.screenWidth && biggestResolution.gameHeight == biggestResolution.screenHeight ); // This resolution should be really "widescreen" (or at least square), i.e. the width should be not less than the height, otherwise // the scaled resolution's in-game width will become less than DEFAULT_WIDTH if ( biggestResolution.gameWidth > fheroes2::Display::DEFAULT_WIDTH && biggestResolution.gameWidth >= biggestResolution.gameHeight ) { assert( biggestResolution.gameHeight >= fheroes2::Display::DEFAULT_HEIGHT ); scaledResolutions.emplace( biggestResolution.gameWidth * fheroes2::Display::DEFAULT_HEIGHT / biggestResolution.gameHeight, fheroes2::Display::DEFAULT_HEIGHT, biggestResolution.gameWidth, biggestResolution.gameHeight ); } } // Try to find and add scaled resolutions with integer scale (x2, x3, x4, etc) which correspond to existing "hardware" resolutions for ( const fheroes2::ResolutionInfo & resolution : resolutions ) { assert( resolution.gameWidth == resolution.screenWidth && resolution.gameHeight == resolution.screenHeight ); const int32_t maxScale = std::min( resolution.gameWidth / fheroes2::Display::DEFAULT_WIDTH, resolution.gameHeight / fheroes2::Display::DEFAULT_HEIGHT ); for ( int32_t scale = 2; scale <= maxScale; ++scale ) { if ( resolution.gameWidth % scale != 0 || resolution.gameHeight % scale != 0 ) { continue; } scaledResolutions.emplace( resolution.gameWidth / scale, resolution.gameHeight / scale, resolution.gameWidth, resolution.gameHeight ); } } resolutions.merge( scaledResolutions ); return resolutions; } #endif std::vector StandardPaletteIndexes() { std::vector indexes( 256 ); for ( uint32_t i = 0; i < 256; ++i ) { indexes[i] = static_cast( i ); } return indexes; } const uint8_t * PALPalette( const bool forceDefaultPaletteUpdate = false ) { static std::vector palette; if ( palette.empty() || forceDefaultPaletteUpdate ) { const uint8_t * gamePalette = fheroes2::getGamePalette(); palette.resize( 256 * 3 ); for ( size_t i = 0; i < palette.size(); ++i ) { palette[i] = gamePalette[i] << 2; } } return palette.data(); } bool getActiveArea( fheroes2::Rect & roi, const int32_t width, const int32_t height ) { if ( roi.width <= 0 || roi.height <= 0 || roi.x >= width || roi.y >= height ) return false; if ( roi.x < 0 ) { const int32_t offsetX = -roi.x; if ( offsetX >= roi.width ) return false; roi.x = 0; roi.width -= offsetX; } if ( roi.y < 0 ) { const int32_t offsetY = -roi.y; if ( offsetY >= roi.height ) return false; roi.y = 0; roi.height -= offsetY; } if ( roi.x + roi.width > width ) { const int32_t offsetX = roi.x + roi.width - width; if ( offsetX >= roi.width ) return false; roi.width -= offsetX; } if ( roi.y + roi.height > height ) { const int32_t offsetY = roi.y + roi.height - height; if ( offsetY >= roi.height ) return false; roi.height -= offsetY; } return true; } const uint8_t * currentPalette = PALPalette(); // If SDL library is used #if !defined( TARGET_PS_VITA ) class BaseSDLRenderer { protected: std::vector _palette32Bit; std::vector _palette8Bit; void copyImageToSurface( const fheroes2::Image & image, SDL_Surface * surface, const fheroes2::Rect & roi ) { assert( surface != nullptr && !image.empty() ); if ( SDL_MUSTLOCK( surface ) ) { const int returnCode = SDL_LockSurface( surface ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to lock surface. The error value: " << returnCode << ", description: " << SDL_GetError() ) } } const int32_t imageWidth = image.width(); const int32_t imageHeight = image.height(); const bool fullFrame = ( roi.width == imageWidth ) && ( roi.height == imageHeight ); const uint8_t * imageIn = image.image(); if ( fullFrame ) { if ( surface->format->BitsPerPixel == 32 ) { uint32_t * out = static_cast( surface->pixels ); const uint32_t * outEnd = out + imageWidth * imageHeight; const uint8_t * in = imageIn; const uint32_t * transform = _palette32Bit.data(); for ( ; out != outEnd; ++out, ++in ) *out = *( transform + *in ); } else if ( ( surface->format->BitsPerPixel == 8 ) && ( surface->pixels != imageIn ) ) { if ( imageWidth % 4 != 0 ) { const int32_t screenWidth = ( imageWidth / 4 ) * 4 + 4; for ( int32_t i = 0; i < imageHeight; ++i ) { memcpy( static_cast( surface->pixels ) + screenWidth * i, imageIn + imageWidth * i, static_cast( imageWidth ) ); } } else { memcpy( surface->pixels, imageIn, static_cast( imageWidth ) * imageHeight ); } } } else { if ( surface->format->BitsPerPixel == 32 ) { uint32_t * outY = static_cast( surface->pixels ); const uint32_t * outYEnd = outY + imageWidth * roi.height; const uint8_t * inY = imageIn + roi.x + roi.y * imageWidth; const uint32_t * transform = _palette32Bit.data(); for ( ; outY != outYEnd; outY += imageWidth, inY += imageWidth ) { uint32_t * outX = outY; const uint32_t * outXEnd = outX + roi.width; const uint8_t * inX = inY; for ( ; outX != outXEnd; ++outX, ++inX ) *outX = *( transform + *inX ); } } else if ( ( surface->format->BitsPerPixel == 8 ) && ( surface->pixels != imageIn ) ) { const int32_t screenWidth = ( imageWidth / 4 ) * 4 + 4; const int32_t screenOffset = roi.x + roi.y * screenWidth; const int32_t imageOffset = roi.x + roi.y * imageWidth; for ( int32_t i = 0; i < roi.height; ++i ) { memcpy( static_cast( surface->pixels ) + screenWidth * i + screenOffset, imageIn + imageOffset + imageWidth * i, static_cast( roi.width ) ); } } } if ( SDL_MUSTLOCK( surface ) ) SDL_UnlockSurface( surface ); } void generatePalette( const std::vector & colorIds, const SDL_Surface * surface ) { assert( surface != nullptr ); if ( surface->format->BitsPerPixel == 32 ) { _palette32Bit.resize( 256u ); if ( surface->format->Amask > 0 ) { for ( size_t i = 0; i < 256u; ++i ) { const uint8_t * value = currentPalette + colorIds[i] * 3; _palette32Bit[i] = SDL_MapRGBA( surface->format, *value, *( value + 1 ), *( value + 2 ), 255 ); } } else { for ( size_t i = 0; i < 256u; ++i ) { const uint8_t * value = currentPalette + colorIds[i] * 3; _palette32Bit[i] = SDL_MapRGB( surface->format, *value, *( value + 1 ), *( value + 2 ) ); } } } else if ( surface->format->BitsPerPixel == 8 ) { _palette8Bit.resize( 256 ); for ( uint32_t i = 0; i < 256; ++i ) { const uint8_t * value = currentPalette + colorIds[i] * 3; SDL_Color & col = _palette8Bit[i]; col.r = *value; col.g = *( value + 1 ); col.b = *( value + 2 ); } } else { // This is unsupported format. Please implement it. assert( 0 ); } } SDL_Surface * generateIconSurface( const fheroes2::Image & icon ) { if ( icon.empty() || icon.singleLayer() ) { // What are you trying to do? Icon should have not empty both image and transform layers. assert( 0 ); return nullptr; } SDL_Surface * surface = SDL_CreateRGBSurface( 0, icon.width(), icon.height(), 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 ); if ( surface == nullptr ) { ERROR_LOG( "Failed to create a surface of " << icon.width() << " x " << icon.height() << " size for cursor. The error: " << SDL_GetError() ) return nullptr; } const uint32_t width = icon.width(); const uint32_t height = icon.height(); uint32_t * out = static_cast( surface->pixels ); const uint32_t * outEnd = out + width * height; const uint8_t * in = icon.image(); const uint8_t * transform = icon.transform(); if ( surface->format->Amask > 0 ) { for ( ; out != outEnd; ++out, ++in, ++transform ) { if ( *transform == 0 ) { const uint8_t * value = currentPalette + *in * 3; *out = SDL_MapRGBA( surface->format, *value, *( value + 1 ), *( value + 2 ), 255 ); } } } else { for ( ; out != outEnd; ++out, ++in, ++transform ) { if ( *transform == 0 ) { const uint8_t * value = currentPalette + *in * 3; *out = SDL_MapRGB( surface->format, *value, *( value + 1 ), *( value + 2 ) ); } else { *out = SDL_MapRGB( surface->format, 0, 0, 0 ); } } } return surface; } }; #endif } namespace { class RenderCursor final : public fheroes2::Cursor { public: RenderCursor( const RenderCursor & ) = delete; ~RenderCursor() override { clear(); } RenderCursor & operator=( const RenderCursor & ) = delete; void show( const bool enable ) override { fheroes2::Cursor::show( enable ); if ( !_emulation ) { const int returnCode = SDL_ShowCursor( _show ? SDL_ENABLE : SDL_DISABLE ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set cursor. The error value: " << returnCode << ", description: " << SDL_GetError() ) } } } bool isVisible() const override { if ( _emulation ) return fheroes2::Cursor::isVisible(); else return fheroes2::Cursor::isVisible() && ( SDL_ShowCursor( SDL_QUERY ) == SDL_ENABLE ); } void update( const fheroes2::Image & image, int32_t offsetX, int32_t offsetY ) override { if ( image.empty() || image.singleLayer() ) { // What are you trying to do? Set an invisible cursor? Use hide() method! assert( 0 ); return; } if ( _emulation ) { fheroes2::Cursor::update( image, offsetX, offsetY ); return; } SDL_Surface * surface = SDL_CreateRGBSurface( 0, image.width(), image.height(), 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000 ); if ( surface == nullptr ) { ERROR_LOG( "Failed to create a surface of " << image.width() << " x " << image.height() << " size for cursor. The error: " << SDL_GetError() ) return; } const uint32_t width = image.width(); const uint32_t height = image.height(); uint32_t * out = static_cast( surface->pixels ); const uint32_t * outEnd = out + width * height; const uint8_t * in = image.image(); const uint8_t * transform = image.transform(); if ( surface->format->Amask > 0 ) { for ( ; out != outEnd; ++out, ++in, ++transform ) { if ( *transform == 0 ) { const uint8_t * value = currentPalette + *in * 3; *out = SDL_MapRGBA( surface->format, *value, *( value + 1 ), *( value + 2 ), 255 ); } else if ( *transform > 1 ) { // SDL2 uses RGBA image on OS level separately from frame rendering. // Here we are trying to simulate cursor's shadow as close as possible to the original game. *out = SDL_MapRGBA( surface->format, 0, 0, 0, 64 ); } } } else { for ( ; out != outEnd; ++out, ++in, ++transform ) { if ( *transform == 0 ) { const uint8_t * value = currentPalette + *in * 3; *out = SDL_MapRGB( surface->format, *value, *( value + 1 ), *( value + 2 ) ); } else { *out = SDL_MapRGB( surface->format, 0, 0, 0 ); } } } SDL_Cursor * tempCursor = SDL_CreateColorCursor( surface, offsetX, offsetY ); if ( tempCursor == nullptr ) { ERROR_LOG( "Failed to create a cursor. The error description: " << SDL_GetError() ) } else { SDL_SetCursor( tempCursor ); } const int returnCode = SDL_ShowCursor( _show ? SDL_ENABLE : SDL_DISABLE ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set cursor state. The error value: " << returnCode << ", description: " << SDL_GetError() ) } SDL_FreeSurface( surface ); if ( tempCursor != nullptr ) { clear(); std::swap( _cursor, tempCursor ); } } void enableSoftwareEmulation( const bool enable ) override { if ( enable == _emulation ) return; if ( enable ) { clear(); const int returnCode = SDL_ShowCursor( SDL_DISABLE ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to disable cursor. The error value: " << returnCode << ", description: " << SDL_GetError() ) } _emulation = true; } else { const int returnCode = SDL_ShowCursor( _show ? SDL_ENABLE : SDL_DISABLE ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set cursor state. The error value: " << returnCode << ", description: " << SDL_GetError() ) } _emulation = false; } if ( _cursorUpdater != nullptr ) _cursorUpdater(); } static RenderCursor * create() { return new RenderCursor; } private: SDL_Cursor * _cursor{ nullptr }; RenderCursor() { _emulation = false; const int returnCode = SDL_ShowCursor( _show ? SDL_ENABLE : SDL_DISABLE ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set cursor state. The error value: " << returnCode << ", description: " << SDL_GetError() ) } } void clear() { if ( _cursor != nullptr ) { SDL_FreeCursor( _cursor ); _cursor = nullptr; } } }; } namespace { #if defined( TARGET_PS_VITA ) class RenderEngine final : public fheroes2::BaseRenderEngine { public: RenderEngine( const RenderEngine & ) = delete; ~RenderEngine() override { clear(); } RenderEngine & operator=( const RenderEngine & ) = delete; void toggleFullScreen() override { BaseRenderEngine::toggleFullScreen(); const fheroes2::Display & display = fheroes2::Display::instance(); _calculateScreenScaling( display.width(), display.height(), isFullScreen() ); } static RenderEngine * create() { return new RenderEngine; } fheroes2::Rect getActiveWindowROI() const override { return _destRect; } fheroes2::Size getCurrentScreenResolution() const override { return { VITA_FULLSCREEN_WIDTH, VITA_FULLSCREEN_HEIGHT }; } std::vector getAvailableResolutions() const override { static const std::vector filteredResolutions = []() { std::set resolutionSet; resolutionSet.emplace( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ); resolutionSet.emplace( VITA_ASPECT_CORRECTED_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ); resolutionSet.emplace( VITA_FULLSCREEN_WIDTH, VITA_FULLSCREEN_HEIGHT ); return std::vector{ resolutionSet.rbegin(), resolutionSet.rend() }; }(); return filteredResolutions; } private: SDL_Window * _window{ nullptr }; SDL_Surface * _surface{ nullptr }; vita2d_texture * _texBuffer{ nullptr }; uint8_t * _palettedTexturePointer{ nullptr }; fheroes2::Rect _destRect; RenderEngine() = default; enum : int32_t { VITA_FULLSCREEN_WIDTH = 960, VITA_FULLSCREEN_HEIGHT = 544, VITA_ASPECT_CORRECTED_WIDTH = 848 }; void clear() override { if ( _window != nullptr ) { SDL_DestroyWindow( _window ); _window = nullptr; } if ( _surface != nullptr ) { SDL_FreeSurface( _surface ); _surface = nullptr; } vita2d_fini(); if ( _texBuffer != nullptr ) { vita2d_free_texture( _texBuffer ); _texBuffer = nullptr; } } bool allocate( fheroes2::ResolutionInfo & resolutionInfo, bool isFullScreen ) override { clear(); const std::vector resolutions = getAvailableResolutions(); assert( !resolutions.empty() ); if ( !resolutions.empty() ) { resolutionInfo = GetNearestResolution( resolutionInfo, resolutions ); } vita2d_init(); _window = SDL_CreateWindow( "", 0, 0, resolutionInfo.gameWidth, resolutionInfo.gameHeight, 0 ); if ( _window == nullptr ) { ERROR_LOG( "Failed to create an application window of " << resolutionInfo.gameWidth << " x " << resolutionInfo.gameHeight << " size. The error: " << SDL_GetError() ) clear(); return false; } _surface = SDL_CreateRGBSurface( 0, 1, 1, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 ); if ( _surface == nullptr || _surface->w <= 0 || _surface->h <= 0 ) { ERROR_LOG( "Failed to create a surface of " << resolutionInfo.gameWidth << " x " << resolutionInfo.gameHeight << " size. The error: " << SDL_GetError() ) clear(); return false; } vita2d_texture_set_alloc_memblock_type( SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW ); _texBuffer = vita2d_create_empty_texture_format( resolutionInfo.gameWidth, resolutionInfo.gameHeight, SCE_GXM_TEXTURE_FORMAT_P8_ABGR ); _palettedTexturePointer = static_cast( vita2d_texture_get_datap( _texBuffer ) ); memset( _palettedTexturePointer, 0, resolutionInfo.gameWidth * resolutionInfo.gameHeight * sizeof( uint8_t ) ); _createPalette(); _calculateScreenScaling( resolutionInfo.gameWidth, resolutionInfo.gameHeight, isFullScreen ); return true; } void render( const fheroes2::Display & display, const fheroes2::Rect & roi ) override { (void)roi; if ( _texBuffer == nullptr ) return; const int32_t width = display.width(); const int32_t height = display.height(); SDL_memcpy( _palettedTexturePointer, display.image(), width * height * sizeof( uint8_t ) ); vita2d_start_drawing(); vita2d_draw_rectangle( 0, 0, VITA_FULLSCREEN_WIDTH, VITA_FULLSCREEN_HEIGHT, 0xff000000 ); vita2d_draw_texture_scale( _texBuffer, _destRect.x, _destRect.y, static_cast( _destRect.width ) / width, static_cast( _destRect.height ) / height ); vita2d_end_drawing(); vita2d_swap_buffers(); } void updatePalette( const std::vector & colorIds ) override { if ( _surface == nullptr || colorIds.size() != 256 || _texBuffer == nullptr ) return; uint32_t palette32Bit[256u]; for ( size_t i = 0; i < 256u; ++i ) { const uint8_t * value = currentPalette + colorIds[i] * 3; palette32Bit[i] = SDL_MapRGBA( _surface->format, *value, *( value + 1 ), *( value + 2 ), 255 ); } memcpy( vita2d_texture_get_palette( _texBuffer ), palette32Bit, sizeof( uint32_t ) * 256 ); } bool isMouseCursorActive() const override { return true; } void _createPalette() { updatePalette( StandardPaletteIndexes() ); } void _calculateScreenScaling( const int32_t width_, const int32_t height_, const bool isFullScreen ) { _destRect.x = 0; _destRect.y = 0; _destRect.width = width_; _destRect.height = height_; if ( width_ == VITA_FULLSCREEN_WIDTH && height_ == VITA_FULLSCREEN_HEIGHT ) { // Nothing to do more. return; } if ( !isFullScreen ) { // Center game area. _destRect.x = ( VITA_FULLSCREEN_WIDTH - width_ ) / 2; _destRect.y = ( VITA_FULLSCREEN_HEIGHT - height_ ) / 2; return; } const SceGxmTextureFilter textureFilter = isNearestScaling() ? SCE_GXM_TEXTURE_FILTER_POINT : SCE_GXM_TEXTURE_FILTER_LINEAR; vita2d_texture_set_filters( _texBuffer, textureFilter, textureFilter ); if ( ( static_cast( VITA_FULLSCREEN_WIDTH ) / VITA_FULLSCREEN_HEIGHT ) >= ( static_cast( width_ ) / height_ ) ) { const float scale = static_cast( VITA_FULLSCREEN_HEIGHT ) / height_; _destRect.width = static_cast( static_cast( width_ ) * scale ); _destRect.height = VITA_FULLSCREEN_HEIGHT; _destRect.x = ( VITA_FULLSCREEN_WIDTH - _destRect.width ) / 2; } else { const float scale = static_cast( VITA_FULLSCREEN_WIDTH ) / width_; _destRect.width = VITA_FULLSCREEN_WIDTH; _destRect.height = static_cast( static_cast( height_ ) * scale ); _destRect.y = ( VITA_FULLSCREEN_HEIGHT - _destRect.height ) / 2; } } }; #else class RenderEngine final : public fheroes2::BaseRenderEngine, public BaseSDLRenderer { public: RenderEngine( const RenderEngine & ) = delete; ~RenderEngine() override { clear(); } RenderEngine & operator=( const RenderEngine & ) = delete; void toggleFullScreen() override { if ( _window == nullptr ) { BaseRenderEngine::toggleFullScreen(); return; } uint32_t flags = SDL_GetWindowFlags( _window ); if ( ( flags & SDL_WINDOW_FULLSCREEN ) == SDL_WINDOW_FULLSCREEN || ( flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) == SDL_WINDOW_FULLSCREEN_DESKTOP ) { flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; flags &= ~SDL_WINDOW_FULLSCREEN; } else { #if defined( _WIN32 ) if ( fheroes2::cursor().isSoftwareEmulation() ) { flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } else { flags |= SDL_WINDOW_FULLSCREEN; } #else flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; #endif SDL_GetWindowSize( _window, &_windowedSize.width, &_windowedSize.height ); const fheroes2::Display & display = fheroes2::Display::instance(); if ( display.width() != 0 && display.height() != 0 ) { assert( display.screenSize().width >= display.width() && display.screenSize().height >= display.height() ); SDL_SetWindowSize( _window, display.screenSize().width, display.screenSize().height ); } } const int returnCode = SDL_SetWindowFullscreen( _window, flags ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set fullscreen mode flags. The error value: " << returnCode << ", description: " << SDL_GetError() ) } _syncFullScreen(); if ( !isFullScreen() && _windowedSize.width != 0 && _windowedSize.height != 0 ) { SDL_SetWindowSize( _window, _windowedSize.width, _windowedSize.height ); } _retrieveWindowInfo(); _toggleMouseCaptureMode(); } bool isFullScreen() const override { if ( _window == nullptr ) return BaseRenderEngine::isFullScreen(); const uint32_t flags = SDL_GetWindowFlags( _window ); return ( flags & SDL_WINDOW_FULLSCREEN ) != 0 || ( flags & SDL_WINDOW_FULLSCREEN_DESKTOP ) != 0; } std::vector getAvailableResolutions() const override { static const std::vector filteredResolutions = []() { std::set resolutionSet; const int displayCount = SDL_GetNumVideoDisplays(); if ( displayCount >= 1 ) { const int displayModeCount = SDL_GetNumDisplayModes( 0 ); if ( displayModeCount >= 1 ) { for ( int i = 0; i < displayModeCount; ++i ) { SDL_DisplayMode videoMode; const int returnCode = SDL_GetDisplayMode( 0, i, &videoMode ); if ( returnCode != 0 ) { ERROR_LOG( "Failed to get display mode. The error value: " << returnCode << ", description: " << SDL_GetError() ) } else { resolutionSet.emplace( videoMode.w, videoMode.h ); } } } else { ERROR_LOG( "Failed to get the number of display modes. The error value: " << displayModeCount << ", description: " << SDL_GetError() ) } } else { ERROR_LOG( "Failed to get the number of displays. The error value: " << displayCount << ", description: " << SDL_GetError() ) } #if defined( TARGET_NINTENDO_SWITCH ) // Nintendo Switch supports arbitrary resolutions via the HW scaler // 848x480 is the smallest resolution supported by fheroes2 resolutionSet.emplace( 848, 480 ); #endif resolutionSet = FilterResolutions( resolutionSet ); return std::vector{ resolutionSet.rbegin(), resolutionSet.rend() }; }(); return filteredResolutions; } void setTitle( const std::string & title ) override { if ( _window == nullptr ) { return; } SDL_SetWindowTitle( _window, System::encLocalToUTF8( title ).c_str() ); } void setIcon( const fheroes2::Image & icon ) override { if ( _window == nullptr ) return; SDL_Surface * surface = generateIconSurface( icon ); if ( surface == nullptr ) return; SDL_SetWindowIcon( _window, surface ); SDL_FreeSurface( surface ); } fheroes2::Rect getActiveWindowROI() const override { return _activeWindowROI; } fheroes2::Size getCurrentScreenResolution() const override { return _currentScreenResolution; } static RenderEngine * create() { return new RenderEngine; } void setVSync( const bool enable ) override { _isVSyncEnabled = enable; if ( _window != nullptr ) { // We do not need to rebuild window but renderer only. if ( _texture != nullptr ) { SDL_DestroyTexture( _texture ); _texture = nullptr; } if ( _renderer != nullptr ) { SDL_DestroyRenderer( _renderer ); _renderer = nullptr; } const fheroes2::Display & display = fheroes2::Display::instance(); _createRenderer( display.width(), display.height() ); } } private: SDL_Window * _window{ nullptr }; SDL_Surface * _surface{ nullptr }; SDL_Renderer * _renderer{ nullptr }; SDL_Texture * _texture{ nullptr }; int _driverIndex{ -1 }; std::string _previousWindowTitle; fheroes2::Point _prevWindowPos{ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED }; fheroes2::Size _currentScreenResolution; fheroes2::Rect _activeWindowROI; fheroes2::Size _windowedSize; bool _isVSyncEnabled{ false }; RenderEngine() = default; void clear() override { if ( _texture != nullptr ) { SDL_DestroyTexture( _texture ); _texture = nullptr; } if ( _renderer != nullptr ) { SDL_DestroyRenderer( _renderer ); _renderer = nullptr; } if ( _window != nullptr ) { // Let's collect needed info about previous setup if ( !isFullScreen() ) { SDL_GetWindowPosition( _window, &_prevWindowPos.x, &_prevWindowPos.y ); } _previousWindowTitle = System::encUTF8ToLocal( SDL_GetWindowTitle( _window ) ); SDL_DestroyWindow( _window ); _window = nullptr; } if ( _surface != nullptr ) { SDL_FreeSurface( _surface ); _surface = nullptr; } _windowedSize = fheroes2::Size(); _driverIndex = -1; } void render( const fheroes2::Display & display, const fheroes2::Rect & roi ) override { if ( _surface == nullptr ) return; if ( _texture == nullptr ) { if ( _renderer != nullptr ) SDL_DestroyRenderer( _renderer ); // SDL_PIXELFORMAT_INDEX8 is not supported by SDL 2 even being available in the list of formats. _renderer = SDL_CreateRenderer( _window, _driverIndex, renderFlags() ); if ( _renderer == nullptr ) { ERROR_LOG( "Failed to create a window renderer. The error: " << SDL_GetError() ) } return; } copyImageToSurface( display, _surface, roi ); const bool fullFrame = ( roi.width == display.width() ) && ( roi.height == display.height() ); if ( fullFrame ) { const int returnCode = SDL_UpdateTexture( _texture, nullptr, _surface->pixels, _surface->pitch ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to update texture. The error value: " << returnCode << ", description: " << SDL_GetError() ) } } else { SDL_Rect area; area.x = roi.x; area.y = roi.y; area.w = roi.width; area.h = roi.height; const int returnCode = SDL_UpdateTexture( _texture, &area, _surface->pixels, _surface->pitch ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to update texture. The error value: " << returnCode << ", description: " << SDL_GetError() ) } } int returnCode = SDL_RenderClear( _renderer ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to clear renderer. The error value: " << returnCode << ", description: " << SDL_GetError() ) return; } returnCode = SDL_RenderCopy( _renderer, _texture, nullptr, nullptr ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to copy render.The error value: " << returnCode << ", description: " << SDL_GetError() ) return; } SDL_RenderPresent( _renderer ); } bool allocate( fheroes2::ResolutionInfo & resolutionInfo, bool isFullScreen ) override { clear(); const std::vector resolutions = getAvailableResolutions(); assert( !resolutions.empty() ); if ( !resolutions.empty() ) { resolutionInfo = GetNearestResolution( resolutionInfo, resolutions ); } #if defined( ANDROID ) // Same as ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE if ( SDL_SetHint( SDL_HINT_ORIENTATIONS, "LandscapeLeft LandscapeRight" ) == SDL_FALSE ) { ERROR_LOG( "Failed to set the " SDL_HINT_ORIENTATIONS " hint." ) } #endif uint32_t flags = SDL_WINDOW_SHOWN; if ( isFullScreen ) { #if defined( _WIN32 ) if ( fheroes2::cursor().isSoftwareEmulation() ) { flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; } else { flags |= SDL_WINDOW_FULLSCREEN; } #else flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; #endif } flags |= SDL_WINDOW_RESIZABLE; _window = SDL_CreateWindow( System::encLocalToUTF8( _previousWindowTitle ).c_str(), _prevWindowPos.x, _prevWindowPos.y, resolutionInfo.screenWidth, resolutionInfo.screenHeight, flags ); if ( _window == nullptr ) { ERROR_LOG( "Failed to create an application window of " << resolutionInfo.screenWidth << " x " << resolutionInfo.screenHeight << " size. The error: " << SDL_GetError() ) clear(); return false; } _syncFullScreen(); bool isPaletteModeSupported = false; SDL_RendererInfo rendererInfo; _driverIndex = -1; const uint32_t renderingFlags = renderFlags(); const int driverCount = SDL_GetNumRenderDrivers(); if ( driverCount >= 0 ) { for ( int driverId = 0; driverId < driverCount; ++driverId ) { int returnCode = SDL_GetRenderDriverInfo( driverId, &rendererInfo ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to get renderer driver info. The error value: " << returnCode << ", description: " << SDL_GetError() ) continue; } if ( ( renderingFlags & rendererInfo.flags ) != renderingFlags ) { continue; } for ( uint32_t i = 0; i < rendererInfo.num_texture_formats; ++i ) { if ( rendererInfo.texture_formats[i] == SDL_PIXELFORMAT_INDEX8 ) { // Bingo! This is the best driver and format. isPaletteModeSupported = true; _driverIndex = driverId; break; } } if ( isPaletteModeSupported ) { break; } if ( _driverIndex < 0 ) { _driverIndex = driverId; } } } else { ERROR_LOG( "Failed to get the number of render drivers. The error value: " << driverCount << ", description: " << SDL_GetError() ) } _surface = SDL_CreateRGBSurface( 0, resolutionInfo.gameWidth, resolutionInfo.gameHeight, isPaletteModeSupported ? 8 : 32, 0, 0, 0, 0 ); if ( _surface == nullptr ) { ERROR_LOG( "Failed to create a surface of " << resolutionInfo.gameWidth << " x " << resolutionInfo.gameHeight << " size. The error: " << SDL_GetError() ) clear(); return false; } if ( _surface->w <= 0 || _surface->h <= 0 || _surface->w != resolutionInfo.gameWidth || _surface->h != resolutionInfo.gameHeight ) { clear(); return false; } _createPalette(); return _createRenderer( resolutionInfo.gameWidth, resolutionInfo.gameHeight ); } void updatePalette( const std::vector & colorIds ) override { if ( _surface == nullptr || colorIds.size() != 256 ) return; generatePalette( colorIds, _surface ); if ( _surface->format->BitsPerPixel == 8 ) { const int returnCode = SDL_SetPaletteColors( _surface->format->palette, _palette8Bit.data(), 0, 256 ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set palette color. The error value: " << returnCode << ", description: " << SDL_GetError() ) } } } bool isMouseCursorActive() const override { return ( _window != nullptr ) && ( ( SDL_GetWindowFlags( _window ) & SDL_WINDOW_MOUSE_FOCUS ) == SDL_WINDOW_MOUSE_FOCUS ); } uint32_t renderFlags() const { if ( _isVSyncEnabled ) { return ( SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC ); } return SDL_RENDERER_ACCELERATED; } void _createPalette() { if ( _surface == nullptr ) return; updatePalette( StandardPaletteIndexes() ); if ( _surface->format->BitsPerPixel == 8 ) { if ( !SDL_MUSTLOCK( _surface ) ) { // copy the image from display buffer to SDL surface const fheroes2::Display & display = fheroes2::Display::instance(); if ( _surface->w == display.width() && _surface->h == display.height() ) { memcpy( _surface->pixels, display.image(), static_cast( display.width() * display.height() ) ); } // Display class doesn't have support for image pitch so we mustn't link display to surface if width is not divisible by 4. if ( _surface->w % 4 == 0 ) { linkRenderSurface( static_cast( _surface->pixels ) ); } } } } bool _retrieveWindowInfo() { assert( _window != nullptr ); const int displayIndex = SDL_GetWindowDisplayIndex( _window ); if ( displayIndex < 0 ) { ERROR_LOG( "Failed to get window display index. The error value: " << displayIndex << ", description: " << SDL_GetError() ) return false; } SDL_DisplayMode displayMode; const int returnCode = SDL_GetCurrentDisplayMode( displayIndex, &displayMode ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to retrieve current display mode. The error value: " << returnCode << ", description: " << SDL_GetError() ) return false; } _currentScreenResolution.width = displayMode.w; _currentScreenResolution.height = displayMode.h; #if defined( TARGET_NINTENDO_SWITCH ) // On a Nintendo Switch the game is always fullscreen _activeWindowROI = { 0, 0, _currentScreenResolution.width, _currentScreenResolution.height }; #else SDL_GetWindowPosition( _window, &_activeWindowROI.x, &_activeWindowROI.y ); SDL_GetWindowSize( _window, &_activeWindowROI.width, &_activeWindowROI.height ); #endif return true; } void _toggleMouseCaptureMode() { // To properly support fullscreen mode on devices with multiple displays or devices with notch, // it is important to lock the mouse in the application window area. if ( isFullScreen() ) { SDL_SetWindowGrab( _window, SDL_TRUE ); } else { SDL_SetWindowGrab( _window, SDL_FALSE ); } } bool _createRenderer( const int32_t width_, const int32_t height_ ) { const uint32_t renderingFlags = renderFlags(); // SDL_PIXELFORMAT_INDEX8 is not supported by SDL 2 even being available in the list of formats. _renderer = SDL_CreateRenderer( _window, _driverIndex, renderingFlags ); if ( _renderer == nullptr ) { ERROR_LOG( "Failed to create a window renderer of " << width_ << " x " << height_ << " size. The error: " << SDL_GetError() ) clear(); return false; } int returnCode = SDL_SetRenderDrawColor( _renderer, 0, 0, 0, SDL_ALPHA_OPAQUE ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set default color for renderer. The error value: " << returnCode << ", description: " << SDL_GetError() ) } returnCode = SDL_SetRenderTarget( _renderer, nullptr ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to set render target to window. The error value: " << returnCode << ", description: " << SDL_GetError() ) } if ( SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, ( isNearestScaling() ? "nearest" : "linear" ) ) == SDL_FALSE ) { ERROR_LOG( "Failed to set the " SDL_HINT_RENDER_SCALE_QUALITY " hint." ) } // Setting this hint prevents the window to regain focus after losing it in fullscreen mode. // It also fixes issues when SDL_UpdateTexture() calls fail because of refocusing. if ( SDL_SetHint( SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0" ) == SDL_FALSE ) { ERROR_LOG( "Failed to set the " SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS " hint." ) } returnCode = SDL_RenderSetLogicalSize( _renderer, width_, height_ ); if ( returnCode < 0 ) { ERROR_LOG( "Failed to create logical size of " << width_ << " x " << height_ << " size. The error value: " << returnCode << ", description: " << SDL_GetError() ) clear(); return false; } _texture = SDL_CreateTextureFromSurface( _renderer, _surface ); if ( _texture == nullptr ) { ERROR_LOG( "Failed to create a texture from a surface of " << width_ << " x " << height_ << " size. The error: " << SDL_GetError() ) clear(); return false; } if ( !_retrieveWindowInfo() ) { clear(); return false; } _toggleMouseCaptureMode(); return true; } void _syncFullScreen() { if ( isFullScreen() != BaseRenderEngine::isFullScreen() ) { BaseRenderEngine::toggleFullScreen(); assert( isFullScreen() == BaseRenderEngine::isFullScreen() ); } } }; #endif } namespace fheroes2 { void BaseRenderEngine::linkRenderSurface( uint8_t * surface ) const { Display::instance().linkRenderSurface( surface ); } Display::Display() : _engine( RenderEngine::create() ) , _cursor( RenderCursor::create() ) , _preprocessing( nullptr ) , _postprocessing( nullptr ) , _renderSurface( nullptr ) { _disableTransformLayer(); } void Display::resize( int32_t width_, int32_t height_ ) { assert( width_ == width() && height_ == height() ); #ifdef NDEBUG (void)width_; (void)height_; #endif } void Display::setResolution( ResolutionInfo info ) { if ( width() > 0 && height() > 0 && info.gameWidth == width() && info.gameHeight == height() && info.screenWidth == _screenSize.width && info.screenHeight == _screenSize.height ) // nothing to resize return; const bool isFullScreen = _engine->isFullScreen(); // deallocate engine resources _engine->clear(); _prevRoi = {}; // allocate engine resources if ( !_engine->allocate( info, isFullScreen ) ) { clear(); } Image::resize( info.gameWidth, info.gameHeight ); Image::reset(); _screenSize = { info.screenWidth, info.screenHeight }; } Display & Display::instance() { static Display display; return display; } void Display::render( const Rect & roi ) { Rect temp( roi ); if ( !getActiveArea( temp, width(), height() ) ) return; getActiveArea( _prevRoi, width(), height() ); if ( _cursor->isVisible() && _cursor->isSoftwareEmulation() && !_cursor->_image.empty() ) { const Sprite & cursorImage = _cursor->_image; const Sprite backup = Crop( *this, cursorImage.x(), cursorImage.y(), cursorImage.width(), cursorImage.height() ); Blit( cursorImage, *this, cursorImage.x(), cursorImage.y() ); if ( !backup.empty() ) { // ROI must include cursor's area as well, otherwise cursor won't be rendered. Rect cursorROI( cursorImage.x(), cursorImage.y(), cursorImage.width(), cursorImage.height() ); if ( getActiveArea( cursorROI, width(), height() ) ) { temp = getBoundaryRect( temp, cursorROI ); } } // Previous position of cursor must be updated as well to avoid ghost effect. _renderFrame( getBoundaryRect( temp, _prevRoi ) ); if ( _postprocessing ) { _postprocessing(); } Copy( backup, 0, 0, *this, backup.x(), backup.y(), backup.width(), backup.height() ); } else { _renderFrame( getBoundaryRect( temp, _prevRoi ) ); if ( _postprocessing ) { _postprocessing(); } } _prevRoi = temp; } void Display::updateNextRenderRoi( const Rect & roi ) { _prevRoi = getBoundaryRect( _prevRoi, roi ); } void Display::_renderFrame( const Rect & roi ) const { bool updateImage = true; if ( _preprocessing ) { std::vector palette; if ( _preprocessing( palette ) ) { _engine->updatePalette( palette ); // when we change a palette for 8-bit image we unwillingly call render so we don't need to re-render the same frame again updateImage = ( _renderSurface == nullptr ); if ( updateImage ) { // Pre-processing step is applied to the whole image so we forcefully render the full frame. _engine->render( *this, { 0, 0, width(), height() } ); return; } } } if ( updateImage ) { _engine->render( *this, roi ); } } uint8_t * Display::image() { return _renderSurface != nullptr ? _renderSurface : Image::image(); } const uint8_t * Display::image() const { return _renderSurface != nullptr ? _renderSurface : Image::image(); } void Display::release() { _engine->clear(); _cursor.reset(); clear(); _prevRoi = {}; } void Display::changePalette( const uint8_t * palette, const bool forceDefaultPaletteUpdate ) const { if ( currentPalette == palette || ( palette == nullptr && currentPalette == PALPalette() && !forceDefaultPaletteUpdate ) ) return; currentPalette = ( palette == nullptr ) ? PALPalette( forceDefaultPaletteUpdate ) : palette; _engine->updatePalette( StandardPaletteIndexes() ); } bool Cursor::isFocusActive() const { return engine().isMouseCursorActive(); } BaseRenderEngine & engine() { return *( Display::instance()._engine ); } Cursor & cursor() { return *( Display::instance()._cursor ); } } fheroes2-1.1.6+dfsg/src/engine/screen.h000066400000000000000000000221611476115357100176530ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include "image.h" #include "math_base.h" namespace fheroes2 { class Cursor; class Display; struct ResolutionInfo { ResolutionInfo() = default; ResolutionInfo( const int32_t gameWidth_, const int32_t gameHeight_ ) : gameWidth( gameWidth_ ) , gameHeight( gameHeight_ ) , screenWidth( gameWidth_ ) , screenHeight( gameHeight_ ) { // Do nothing. } ResolutionInfo( const int32_t gameWidth_, const int32_t gameHeight_, const int32_t screenWidth_, const int32_t screenHeight_ ) : gameWidth( gameWidth_ ) , gameHeight( gameHeight_ ) , screenWidth( screenWidth_ ) , screenHeight( screenHeight_ ) { // Do nothing. } bool operator==( const ResolutionInfo & info ) const { return gameWidth == info.gameWidth && gameHeight == info.gameHeight && screenWidth == info.screenWidth && screenHeight == info.screenHeight; } bool operator!=( const ResolutionInfo & info ) const { return !operator==( info ); } bool operator<( const ResolutionInfo & info ) const { return std::tie( gameWidth, gameHeight, screenWidth, screenHeight ) < std::tie( info.gameWidth, info.gameHeight, info.screenWidth, info.screenHeight ); } int32_t gameWidth{ 0 }; int32_t gameHeight{ 0 }; int32_t screenWidth{ 0 }; int32_t screenHeight{ 0 }; }; class BaseRenderEngine { public: friend class Cursor; friend class Display; virtual ~BaseRenderEngine() = default; virtual void toggleFullScreen() { _isFullScreen = !_isFullScreen; } virtual bool isFullScreen() const { return _isFullScreen; } virtual std::vector getAvailableResolutions() const { return {}; } virtual void setTitle( const std::string & ) { // Do nothing. } virtual void setIcon( const Image & ) { // Do nothing. } virtual Rect getActiveWindowROI() const { return {}; } virtual Size getCurrentScreenResolution() const { return {}; } virtual void setVSync( const bool ) { // Do nothing. } void setNearestScaling( const bool enable ) { _nearestScaling = enable; } bool isNearestScaling() const { return _nearestScaling; } protected: BaseRenderEngine() : _isFullScreen( false ) , _nearestScaling( false ) { // Do nothing. } virtual void clear() { // Do nothing. } virtual void render( const Display &, const Rect & ) { // Do nothing. } virtual bool allocate( ResolutionInfo & /*unused*/, bool /*unused*/ ) { return false; } virtual bool isMouseCursorActive() const { return false; } // To support color cycling we need to update palette. virtual void updatePalette( const std::vector & ) { // Do nothing. } void linkRenderSurface( uint8_t * surface ) const; // declaration of this method is in source file private: bool _isFullScreen; bool _nearestScaling; }; class Display : public Image { public: friend class BaseRenderEngine; enum : int32_t { DEFAULT_WIDTH = 640, DEFAULT_HEIGHT = 480 }; static Display & instance(); ~Display() override = default; // Render an entire frame on screen. void render() { render( { 0, 0, width(), height() } ); } // Render a part of frame on screen. void render( const Rect & roi ); // Update the area which will be rendered on the next render() call. void updateNextRenderRoi( const Rect & roi ); // Do not call this method. It serves as a patch over the basic class. void resize( int32_t width_, int32_t height_ ) override; void setResolution( ResolutionInfo info ); bool isDefaultSize() const { return width() == DEFAULT_WIDTH && height() == DEFAULT_HEIGHT; } // this function must return true if new palette has been generated using PreRenderProcessing = std::function & )>; using PostRenderProcessing = std::function; void subscribe( const PreRenderProcessing & preprocessing, const PostRenderProcessing & postprocessing ) { _preprocessing = preprocessing; _postprocessing = postprocessing; } // For 8-bit mode we return a pointer to direct surface which we draw on screen uint8_t * image() override; const uint8_t * image() const override; void release(); // to release all allocated resources. Should be used at the end of the application // Change the whole color representation on the screen. Make sure that palette exists all the time!!! // nullptr input parameter is used to reset palette to default one. void changePalette( const uint8_t * palette = nullptr, const bool forceDefaultPaletteUpdate = false ) const; Size screenSize() const { return _screenSize; } friend BaseRenderEngine & engine(); friend Cursor & cursor(); private: std::unique_ptr _engine; std::unique_ptr _cursor; PreRenderProcessing _preprocessing; PostRenderProcessing _postprocessing; uint8_t * _renderSurface; // Previous area drawn on the screen. Rect _prevRoi; Size _screenSize; // Only for cases of direct drawing on rendered 8-bit image. void linkRenderSurface( uint8_t * surface ) { _renderSurface = surface; } Display(); void _renderFrame( const Rect & roi ) const; // prepare and render a frame }; class Cursor { public: friend Display; virtual ~Cursor() = default; virtual void show( const bool enable ) { _show = enable; } virtual bool isVisible() const { return _show; } bool isFocusActive() const; virtual void update( const Image & image, int32_t offsetX, int32_t offsetY ) { _image = Sprite( image, offsetX, offsetY ); } void setPosition( const int32_t x, const int32_t y ) { _image.setPosition( x, y ); } // Default implementation of Cursor uses software emulation. virtual void enableSoftwareEmulation( const bool ) { // Do nothing. } bool isSoftwareEmulation() const { return _emulation; } void registerUpdater( void ( *cursorUpdater )() ) { _cursorUpdater = cursorUpdater; } protected: Sprite _image; bool _emulation; bool _show; void ( *_cursorUpdater )(); Cursor() : _emulation( true ) , _show( false ) , _cursorUpdater( nullptr ) {} }; BaseRenderEngine & engine(); Cursor & cursor(); } fheroes2-1.1.6+dfsg/src/engine/serialize.cpp000066400000000000000000000326161476115357100207240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "serialize.h" #include #include #include #include #include #ifdef __EMSCRIPTEN__ #include #include #include #include #include "tools.h" #endif #include "logging.h" namespace { const size_t minBufferCapacity = 1024; } void StreamBase::setBigendian( bool f ) { if ( f ) { _flags |= BIGENDIAN; } else { _flags &= ~BIGENDIAN; } } void StreamBase::setFail( bool f ) { if ( f ) { _flags |= FAILURE; } else { _flags &= ~FAILURE; } } uint16_t IStreamBase::get16() { return bigendian() ? getBE16() : getLE16(); } uint32_t IStreamBase::get32() { return bigendian() ? getBE32() : getLE32(); } IStreamBase & IStreamBase::operator>>( bool & v ) { v = ( get8() != 0 ); return *this; } IStreamBase & IStreamBase::operator>>( char & v ) { v = get8(); return *this; } IStreamBase & IStreamBase::operator>>( int8_t & v ) { v = static_cast( get8() ); return *this; } IStreamBase & IStreamBase::operator>>( uint8_t & v ) { v = get8(); return *this; } IStreamBase & IStreamBase::operator>>( int16_t & v ) { v = get16(); return *this; } IStreamBase & IStreamBase::operator>>( uint16_t & v ) { v = get16(); return *this; } IStreamBase & IStreamBase::operator>>( int32_t & v ) { v = get32(); return *this; } IStreamBase & IStreamBase::operator>>( uint32_t & v ) { v = get32(); return *this; } IStreamBase & IStreamBase::operator>>( std::string & v ) { v.resize( get32() ); std::for_each( v.begin(), v.end(), [this]( char & item ) { item = get8(); } ); return *this; } IStreamBase & IStreamBase::operator>>( fheroes2::Point & v ) { return *this >> v.x >> v.y; } void OStreamBase::put16( uint16_t v ) { bigendian() ? putBE16( v ) : putLE16( v ); } void OStreamBase::put32( uint32_t v ) { bigendian() ? putBE32( v ) : putLE32( v ); } OStreamBase & OStreamBase::operator<<( const bool v ) { put8( v ); return *this; } OStreamBase & OStreamBase::operator<<( const char v ) { put8( v ); return *this; } OStreamBase & OStreamBase::operator<<( const int8_t v ) { put8( static_cast( v ) ); return *this; } OStreamBase & OStreamBase::operator<<( const uint8_t v ) { put8( v ); return *this; } OStreamBase & OStreamBase::operator<<( const int16_t v ) { put16( v ); return *this; } OStreamBase & OStreamBase::operator<<( const uint16_t v ) { put16( v ); return *this; } OStreamBase & OStreamBase::operator<<( const int32_t v ) { put32( v ); return *this; } OStreamBase & OStreamBase::operator<<( const uint32_t v ) { put32( v ); return *this; } OStreamBase & OStreamBase::operator<<( const std::string_view v ) { put32( static_cast( v.size() ) ); // A string is a container of bytes so it doesn't matter which endianess is being used. putRaw( v.data(), v.size() ); return *this; } OStreamBase & OStreamBase::operator<<( const fheroes2::Point & v ) { return *this << v.x << v.y; } RWStreamBuf::RWStreamBuf( const size_t size ) { if ( size ) { reallocBuf( size ); } setBigendian( IS_BIGENDIAN ); } void RWStreamBuf::putBE16( uint16_t v ) { put8( v >> 8 ); put8( v & 0xFF ); } void RWStreamBuf::putLE16( uint16_t v ) { put8( v & 0xFF ); put8( v >> 8 ); } void RWStreamBuf::putBE32( uint32_t v ) { put8( v >> 24 ); put8( ( v >> 16 ) & 0xFF ); put8( ( v >> 8 ) & 0xFF ); put8( v & 0xFF ); } void RWStreamBuf::putLE32( uint32_t v ) { put8( v & 0xFF ); put8( ( v >> 8 ) & 0xFF ); put8( ( v >> 16 ) & 0xFF ); put8( v >> 24 ); } void RWStreamBuf::putRaw( const void * ptr, size_t size ) { if ( size == 0 ) { return; } if ( sizep() < size ) { if ( size < capacity() / 2 ) { reallocBuf( capacity() + capacity() / 2 ); } else { reallocBuf( capacity() + size ); } } if ( sizep() < size ) { assert( 0 ); return; } memcpy( _itput, ptr, size ); _itput = _itput + size; } void RWStreamBuf::put8( const uint8_t v ) { if ( sizep() < 1 ) { reallocBuf( capacity() + capacity() / 2 ); } if ( sizep() < 1 ) { assert( 0 ); return; } *_itput = v; ++_itput; } size_t RWStreamBuf::tellp() const { assert( _itbeg <= _itput ); return _itput - _itbeg; } size_t RWStreamBuf::sizep() const { assert( _itput <= _itend ); return _itend - _itput; } void RWStreamBuf::reallocBuf( size_t size ) { if ( !_buf ) { assert( ( []( const auto... args ) { return ( ( args == nullptr ) && ... ); }( _itbeg, _itget, _itput, _itend ) ) ); size = std::max( size, minBufferCapacity ); _buf = std::make_unique( size ); _itbeg = _buf.get(); _itend = _itbeg + size; _itput = _itbeg; _itget = _itbeg; return; } assert( ( []( const auto... args ) { return ( ( args != nullptr ) && ... ); }( _itbeg, _itget, _itput, _itend ) ) && _itbeg <= _itget && _itget <= _itput && _itput <= _itend ); if ( sizep() < size ) { size = std::max( size, minBufferCapacity ); std::unique_ptr newBuf = std::make_unique( size ); std::copy( _itbeg, _itput, newBuf.get() ); _itput = newBuf.get() + tellp(); _itget = newBuf.get() + tellg(); _buf = std::move( newBuf ); _itbeg = _buf.get(); _itend = _itbeg + size; } } ROStreamBuf::ROStreamBuf( const std::vector & buf ) { _itbeg = buf.data(); _itend = _itbeg + buf.size(); _itget = _itbeg; _itput = _itend; setBigendian( IS_BIGENDIAN ); } ROStreamBuf::ROStreamBuf( std::vector && buf ) : _buf( std::move( buf ) ) { _itbeg = _buf.data(); _itend = _itbeg + _buf.size(); _itget = _itbeg; _itput = _itend; setBigendian( IS_BIGENDIAN ); } std::pair ROStreamBuf::getRawView( const size_t size /* = 0 */ ) { const size_t remainSize = sizeg(); const size_t resultSize = size > 0 ? std::min( size, remainSize ) : remainSize; auto v = std::make_pair( _itget, resultSize ); _itget += resultSize; return v; } std::string_view ROStreamBuf::getStringView( const size_t size /* = 0 */ ) { const size_t remainSize = sizeg(); const size_t sizeToSkip = size > 0 ? std::min( size, remainSize ) : remainSize; const uint8_t * strBeg = _itget; _itget += sizeToSkip; const uint8_t * strEnd = std::find( strBeg, _itget, 0 ); assert( strBeg <= strEnd ); static_assert( std::is_same_v>, unsigned char> ); return { reinterpret_cast( strBeg ), static_cast( strEnd - strBeg ) }; } bool StreamFile::open( const std::string & fn, const std::string & mode ) { _file.reset( std::fopen( fn.c_str(), mode.c_str() ) ); if ( !_file ) { ERROR_LOG( "Error opening file " << fn ) } setFail( !_file ); return !fail(); } void StreamFile::close() { _file.reset(); } size_t StreamFile::size() { if ( !_file ) { return 0; } const long pos = std::ftell( _file.get() ); if ( pos < 0 ) { setFail(); return 0; } if ( std::fseek( _file.get(), 0, SEEK_END ) != 0 ) { setFail(); return 0; } const long len = std::ftell( _file.get() ); if ( len < 0 ) { setFail(); return 0; } if ( std::fseek( _file.get(), pos, SEEK_SET ) != 0 ) { setFail(); return 0; } return static_cast( len ); } size_t StreamFile::tell() { if ( !_file ) { return 0; } const long pos = std::ftell( _file.get() ); if ( pos < 0 ) { setFail(); return 0; } return static_cast( pos ); } void StreamFile::seek( const size_t pos ) { if ( !_file ) { return; } if ( std::fseek( _file.get(), static_cast( pos ), SEEK_SET ) != 0 ) { setFail(); } } size_t StreamFile::sizeg() { if ( !_file ) { return 0; } const long pos = std::ftell( _file.get() ); if ( pos < 0 ) { setFail(); return 0; } if ( std::fseek( _file.get(), 0, SEEK_END ) != 0 ) { setFail(); return 0; } const long len = std::ftell( _file.get() ); if ( len < 0 ) { setFail(); return 0; } if ( std::fseek( _file.get(), pos, SEEK_SET ) != 0 ) { setFail(); return 0; } // Something weird has happened if ( len < pos ) { setFail(); return 0; } return static_cast( len - pos ); } void StreamFile::skip( size_t size ) { if ( !_file ) { return; } if ( std::fseek( _file.get(), static_cast( size ), SEEK_CUR ) != 0 ) { setFail(); } } uint8_t StreamFile::get8() { return getUint(); } void StreamFile::put8( const uint8_t v ) { putUint( v ); } uint16_t StreamFile::getBE16() { return be16toh( getUint() ); } uint16_t StreamFile::getLE16() { return le16toh( getUint() ); } uint32_t StreamFile::getBE32() { return be32toh( getUint() ); } uint32_t StreamFile::getLE32() { return le32toh( getUint() ); } void StreamFile::putBE16( uint16_t v ) { putUint( htobe16( v ) ); } void StreamFile::putLE16( uint16_t v ) { putUint( htole16( v ) ); } void StreamFile::putBE32( uint32_t v ) { putUint( htobe32( v ) ); } void StreamFile::putLE32( uint32_t v ) { putUint( htole32( v ) ); } std::vector StreamFile::getRaw( const size_t size ) { const size_t chunkSize = size > 0 ? size : sizeg(); if ( chunkSize == 0 || !_file ) { return {}; } std::vector v( chunkSize, 0 ); if ( std::fread( v.data(), chunkSize, 1, _file.get() ) != 1 ) { setFail(); return {}; } return v; } void StreamFile::putRaw( const void * ptr, size_t size ) { if ( size == 0 ) { // Nothing to write. Ignore it. return; } if ( !_file ) { return; } if ( std::fwrite( ptr, size, 1, _file.get() ) != 1 ) { setFail(); } } ROStreamBuf StreamFile::getStreamBuf( const size_t size /* = 0 */ ) { return ROStreamBuf{ getRaw( size ) }; } std::string StreamFile::getString( const size_t size /* = 0 */ ) { const std::vector buf = getRaw( size ); return { buf.begin(), std::find( buf.begin(), buf.end(), 0 ) }; } int StreamFile::closeFile( std::FILE * f ) { #ifdef __EMSCRIPTEN__ const bool needSyncFS = [f]() { static_assert( CountBits( O_WRONLY ) == 1 && CountBits( O_RDWR ) == 1 ); const int fn = fileno( f ); if ( fn < 0 ) { ERROR_LOG( "fileno() error: " << errno ) return false; } const int flags = fcntl( fn, F_GETFL ); if ( flags < 0 ) { ERROR_LOG( "fcntl() error: " << errno ) return false; } return ( flags & O_WRONLY ) || ( flags & O_RDWR ); }(); #endif const int res = std::fclose( f ); #ifdef __EMSCRIPTEN__ if ( needSyncFS ) { #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wvariadic-macro-arguments-omitted" #endif EM_ASM( // The following code is not C++ code, but JavaScript code. // clang-format off FS.syncfs( err => err && console.warn( "FS.syncfs() error:", err ) ) // clang-format on ); #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif } #endif return res; } fheroes2-1.1.6+dfsg/src/engine/serialize.h000066400000000000000000000471411476115357100203700ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined( __FreeBSD__ ) || defined( __OpenBSD__ ) #include #elif defined( _WIN32 ) #include #define BIG_ENDIAN 4321 #define LITTLE_ENDIAN 1234 #define BYTE_ORDER LITTLE_ENDIAN #define htobe16( x ) _byteswap_ushort( x ) #define htole16( x ) ( x ) #define be16toh( x ) _byteswap_ushort( x ) #define le16toh( x ) ( x ) #define htobe32( x ) _byteswap_ulong( x ) #define htole32( x ) ( x ) #define be32toh( x ) _byteswap_ulong( x ) #define le32toh( x ) ( x ) #elif defined( __APPLE__ ) #include #define htobe16( x ) OSSwapHostToBigInt16( x ) #define htole16( x ) OSSwapHostToLittleInt16( x ) #define be16toh( x ) OSSwapBigToHostInt16( x ) #define le16toh( x ) OSSwapLittleToHostInt16( x ) #define htobe32( x ) OSSwapHostToBigInt32( x ) #define htole32( x ) OSSwapHostToLittleInt32( x ) #define be32toh( x ) OSSwapBigToHostInt32( x ) #define le32toh( x ) OSSwapLittleToHostInt32( x ) #elif defined( TARGET_PS_VITA ) #define BIG_ENDIAN 4321 #define LITTLE_ENDIAN 1234 #define BYTE_ORDER LITTLE_ENDIAN #define htobe16( x ) __builtin_bswap16( x ) #define htole16( x ) ( x ) #define be16toh( x ) __builtin_bswap16( x ) #define le16toh( x ) ( x ) #define htobe32( x ) __builtin_bswap32( x ) #define htole32( x ) ( x ) #define be32toh( x ) __builtin_bswap32( x ) #define le32toh( x ) ( x ) #elif defined( TARGET_NINTENDO_SWITCH ) #include #define LITTLE_ENDIAN _LITTLE_ENDIAN #define BIG_ENDIAN _BIG_ENDIAN #define BYTE_ORDER _BYTE_ORDER #define htobe16( x ) __bswap16( x ) #define htole16( x ) ( x ) #define be16toh( x ) __bswap16( x ) #define le16toh( x ) ( x ) #define htobe32( x ) __bswap32( x ) #define htole32( x ) ( x ) #define be32toh( x ) __bswap32( x ) #define le32toh( x ) ( x ) #else // POSIX 1003.1-2024 // https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/endian.h.html #include #endif #include "math_base.h" #define IS_BIGENDIAN ( BYTE_ORDER == BIG_ENDIAN ) // Base class for all I/O facilities class StreamBase { public: StreamBase( const StreamBase & ) = delete; virtual ~StreamBase() = default; StreamBase & operator=( const StreamBase & ) = delete; void setFail() { setFail( true ); } void setBigendian( bool f ); bool fail() const { return ( _flags & FAILURE ) != 0; } bool bigendian() const { return ( _flags & BIGENDIAN ) != 0; } protected: StreamBase() = default; void setFail( bool f ); private: enum : uint32_t { FAILURE = 0x00000001, BIGENDIAN = 0x00000002 }; uint32_t _flags{ 0 }; }; // Interface that declares the methods needed to read from a stream class IStreamBase : virtual public StreamBase { public: IStreamBase( const IStreamBase & ) = delete; ~IStreamBase() override = default; IStreamBase & operator=( const IStreamBase & ) = delete; virtual void skip( size_t ) = 0; virtual uint16_t getBE16() = 0; virtual uint16_t getLE16() = 0; virtual uint32_t getBE32() = 0; virtual uint32_t getLE32() = 0; // If a zero size is specified, then all still unread data is returned virtual std::vector getRaw( size_t ) = 0; uint16_t get16(); uint32_t get32(); uint8_t get() { return get8(); } IStreamBase & operator>>( bool & v ); IStreamBase & operator>>( char & v ); IStreamBase & operator>>( int8_t & v ); IStreamBase & operator>>( uint8_t & v ); IStreamBase & operator>>( int16_t & v ); IStreamBase & operator>>( uint16_t & v ); IStreamBase & operator>>( int32_t & v ); IStreamBase & operator>>( uint32_t & v ); IStreamBase & operator>>( std::string & v ); IStreamBase & operator>>( fheroes2::Point & v ); template , bool> = true> IStreamBase & operator>>( Type & v ) { std::underlying_type_t temp{}; *this >> temp; v = static_cast( temp ); return *this; } template IStreamBase & operator>>( std::pair & v ) { return *this >> v.first >> v.second; } template IStreamBase & operator>>( std::optional & v ) { bool hasValue{}; *this >> hasValue; if ( hasValue ) { Type temp{}; *this >> temp; v = std::move( temp ); } else { v = {}; } return *this; } template IStreamBase & operator>>( std::vector & v ) { v.resize( get32() ); std::for_each( v.begin(), v.end(), [this]( auto & item ) { *this >> item; } ); return *this; } template IStreamBase & operator>>( std::list & v ) { v.resize( get32() ); std::for_each( v.begin(), v.end(), [this]( auto & item ) { *this >> item; } ); return *this; } template IStreamBase & operator>>( std::map & v ) { const uint32_t size = get32(); v.clear(); for ( uint32_t i = 0; i < size; ++i ) { std::pair temp{}; *this >> temp; v.emplace( std::move( temp ) ); } return *this; } template IStreamBase & operator>>( std::array & v ) { const uint32_t size = get32(); if ( size != v.size() ) { setFail(); v = {}; return *this; } std::for_each( v.begin(), v.end(), [this]( auto & item ) { *this >> item; } ); return *this; } protected: IStreamBase() = default; virtual uint8_t get8() = 0; }; // Interface that declares the methods needed to write to a stream class OStreamBase : virtual public StreamBase { public: OStreamBase( const OStreamBase & ) = delete; ~OStreamBase() override = default; OStreamBase & operator=( const OStreamBase & ) = delete; virtual void putBE16( uint16_t ) = 0; virtual void putLE16( uint16_t ) = 0; virtual void putBE32( uint32_t ) = 0; virtual void putLE32( uint32_t ) = 0; virtual void putRaw( const void *, size_t ) = 0; void put16( uint16_t ); void put32( uint32_t ); void put( const uint8_t ch ) { put8( ch ); } OStreamBase & operator<<( const bool v ); OStreamBase & operator<<( const char v ); OStreamBase & operator<<( const int8_t v ); OStreamBase & operator<<( const uint8_t v ); OStreamBase & operator<<( const int16_t v ); OStreamBase & operator<<( const uint16_t v ); OStreamBase & operator<<( const int32_t v ); OStreamBase & operator<<( const uint32_t v ); OStreamBase & operator<<( const std::string_view v ); OStreamBase & operator<<( const fheroes2::Point & v ); template , bool> = true> OStreamBase & operator<<( const Type v ) { return *this << static_cast>( v ); } template OStreamBase & operator<<( const std::pair & v ) { return *this << v.first << v.second; } template OStreamBase & operator<<( const std::optional & v ) { const bool hasValue = v.has_value(); *this << hasValue; if ( hasValue ) { *this << *v; } return *this; } template OStreamBase & operator<<( const std::vector & v ) { put32( static_cast( v.size() ) ); std::for_each( v.begin(), v.end(), [this]( const auto & item ) { *this << item; } ); return *this; } template OStreamBase & operator<<( const std::list & v ) { put32( static_cast( v.size() ) ); std::for_each( v.begin(), v.end(), [this]( const auto & item ) { *this << item; } ); return *this; } template OStreamBase & operator<<( const std::map & v ) { put32( static_cast( v.size() ) ); std::for_each( v.begin(), v.end(), [this]( const auto & item ) { *this << item; } ); return *this; } template OStreamBase & operator<<( const std::array & v ) { put32( static_cast( v.size() ) ); std::for_each( v.begin(), v.end(), [this]( const auto & item ) { *this << item; } ); return *this; } protected: OStreamBase() = default; virtual void put8( const uint8_t ) = 0; }; // Interface that declares a stream with an in-memory storage backend that can be read from class IStreamBuf : public IStreamBase { public: virtual const uint8_t * data() const = 0; virtual size_t size() const = 0; protected: IStreamBuf() = default; }; // Class template for a stream with an in-memory storage backend that can store either const or non-const data as desired template || std::is_same_v, bool> = true> class StreamBufTmpl : public IStreamBuf { public: StreamBufTmpl( const StreamBufTmpl & ) = delete; ~StreamBufTmpl() override = default; StreamBufTmpl & operator=( const StreamBufTmpl & ) = delete; const uint8_t * data() const override { return _itget; } size_t size() const override { return sizeg(); } size_t tell() const { return tellg(); } void seek( const size_t pos ) { assert( _itbeg <= _itput ); const size_t putPos = _itput - _itbeg; _itget = ( pos < putPos ? _itbeg + pos : _itput ); } void skip( size_t size ) override { _itget += ( size < sizeg() ? size : sizeg() ); } uint16_t getBE16() override { uint16_t v = ( static_cast( get8() ) << 8 ); v |= get8(); return v; } uint16_t getLE16() override { uint16_t v = get8(); v |= ( static_cast( get8() ) << 8 ); return v; } uint32_t getBE32() override { uint32_t v = ( static_cast( get8() ) << 24 ); v |= ( static_cast( get8() ) << 16 ); v |= ( static_cast( get8() ) << 8 ); v |= get8(); return v; } uint32_t getLE32() override { uint32_t v = get8(); v |= ( static_cast( get8() ) << 8 ); v |= ( static_cast( get8() ) << 16 ); v |= ( static_cast( get8() ) << 24 ); return v; } // If a zero size is specified, then all still unread data is returned std::vector getRaw( size_t size ) override { const size_t remainSize = sizeg(); const size_t resultSize = size > 0 ? size : remainSize; const size_t sizeToCopy = std::min( resultSize, remainSize ); std::vector v( resultSize, 0 ); std::copy( _itget, _itget + sizeToCopy, v.data() ); _itget += sizeToCopy; return v; } // Reads no more than 'size' bytes of data (if a zero size is specified, then all still unread data // is read), forms a string that ends with the first null character found in this data (or includes // all data if this data does not contain null characters), and returns this string std::string getString( const size_t size = 0 ) { const size_t remainSize = sizeg(); const size_t sizeToSkip = size > 0 ? std::min( size, remainSize ) : remainSize; T * strBeg = _itget; _itget += sizeToSkip; return { strBeg, std::find( strBeg, _itget, 0 ) }; } protected: StreamBufTmpl() = default; size_t sizeg() const { assert( _itget <= _itput ); return _itput - _itget; } size_t tellg() const { assert( _itbeg <= _itget ); return _itget - _itbeg; } uint8_t get8() override { if ( sizeg() > 0 ) { return *( _itget++ ); } setFail(); return 0; } size_t capacity() const { assert( _itbeg <= _itend ); return _itend - _itbeg; } T * _itbeg{ nullptr }; T * _itget{ nullptr }; T * _itput{ nullptr }; T * _itend{ nullptr }; }; // Stream with a dynamically-sized in-memory storage backend that supports both reading and writing class RWStreamBuf final : public StreamBufTmpl, public OStreamBase { public: RWStreamBuf() : RWStreamBuf( 0 ) {} explicit RWStreamBuf( const size_t size ); RWStreamBuf( const RWStreamBuf & ) = delete; ~RWStreamBuf() override = default; RWStreamBuf & operator=( const RWStreamBuf & ) = delete; void putBE32( uint32_t v ) override; void putLE32( uint32_t v ) override; void putBE16( uint16_t v ) override; void putLE16( uint16_t v ) override; void putRaw( const void * ptr, size_t size ) override; private: void put8( const uint8_t v ) override; size_t sizep() const; size_t tellp() const; void reallocBuf( size_t size ); std::unique_ptr _buf; }; // Stream with read-only in-memory storage backed by a const vector instance (either internal or external, depending on the constructor used) class ROStreamBuf final : public StreamBufTmpl { public: // Creates a non-owning stream on top of an external buffer ("view mode") explicit ROStreamBuf( const std::vector & buf ); // Takes ownership of the given buffer (through the move operation) and creates a stream on top of it explicit ROStreamBuf( std::vector && buf ); ROStreamBuf( const ROStreamBuf & ) = delete; ~ROStreamBuf() override = default; ROStreamBuf & operator=( const ROStreamBuf & ) = delete; // If a zero size is specified, then a view of all still unread data is returned std::pair getRawView( const size_t size = 0 ); // Returns a string view of no more than 'size' bytes of data ending with the first null character found in // this data (or of all the data in the corresponding range if this data does not contain null characters). // If a zero size is specified, then the entire unread amount of data is considered. Advances the cursor // intended for reading data forward by the full amount of the data used (regardless of the presence of null // characters in this data). std::string_view getStringView( const size_t size = 0 ); private: // Buffer to which the transfer of ownership of the external buffer takes place. This buffer is not used in // the non-owning ("view") mode. const std::vector _buf; }; // Stream with a file storage backend that supports both reading and writing class StreamFile final : public IStreamBase, public OStreamBase { public: StreamFile() = default; StreamFile( const StreamFile & ) = delete; ~StreamFile() override = default; StreamFile & operator=( const StreamFile & ) = delete; size_t size(); size_t tell(); bool open( const std::string & fn, const std::string & mode ); void close(); // If a zero size is specified, then all still unread data is returned ROStreamBuf getStreamBuf( const size_t size = 0 ); void seek( const size_t pos ); void skip( size_t size ) override; uint16_t getBE16() override; uint16_t getLE16() override; uint32_t getBE32() override; uint32_t getLE32() override; void putBE16( uint16_t v ) override; void putLE16( uint16_t v ) override; void putBE32( uint32_t v ) override; void putLE32( uint32_t v ) override; // If a zero size is specified, then all still unread data is returned std::vector getRaw( const size_t size ) override; void putRaw( const void * ptr, size_t size ) override; // Reads no more than 'size' bytes of data (if a zero size is specified, then all still unread data // is read), forms a string that ends with the first null character found in this data (or includes // all data if this data does not contain null characters), and returns this string std::string getString( const size_t size = 0 ); private: size_t sizeg(); uint8_t get8() override; void put8( const uint8_t v ) override; template T getUint() { if ( !_file ) { return 0; } T v; if ( std::fread( &v, sizeof( T ), 1, _file.get() ) != 1 ) { setFail(); return 0; } return v; } template void putUint( const T v ) { if ( !_file ) { return; } if ( std::fwrite( &v, sizeof( T ), 1, _file.get() ) != 1 ) { setFail(); } } static int closeFile( std::FILE * f ); std::unique_ptr _file{ nullptr, closeFile }; }; namespace fheroes2 { // Get a value of type T in the system byte order from the buffer in which it was originally stored in the little-endian byte order template || std::is_floating_point_v, bool> = true> T getLEValue( const char * data, const size_t base, const size_t offset = 0 ) { const char * begin = data + base + offset * sizeof( T ); const char * end = begin + sizeof( T ); T v; #if defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && BYTE_ORDER == LITTLE_ENDIAN std::copy( begin, end, reinterpret_cast( &v ) ); #elif defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && BYTE_ORDER == BIG_ENDIAN std::reverse_copy( begin, end, reinterpret_cast( &v ) ); #else #error "Unknown byte order" #endif return v; } } fheroes2-1.1.6+dfsg/src/engine/smk_decoder.cpp000066400000000000000000000255171476115357100212160ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "smk_decoder.h" #include #include #include #include #include #include #include #include "exception.h" #include "image.h" #include "serialize.h" #include "smacker.h" namespace { const size_t audioHeaderSize = 44; void verifyVideoFile( const std::string & filePath ) { if ( filePath.empty() ) { // Why are you trying to even play a file from an empty path? assert( 0 ); return; } // Verify that the file is valid. We use C-code on purpose since libsmacker library does the same. const std::unique_ptr file( std::fopen( filePath.c_str(), "rb" ), []( std::FILE * f ) { return std::fclose( f ); } ); if ( !file ) { return; } std::fseek( file.get(), 0, SEEK_END ); const size_t fileSize = std::ftell( file.get() ); // According to https://wiki.multimedia.cx/index.php/Smacker the minimum size of a file must be 56 bytes. if ( fileSize < 56 ) { throw fheroes2::InvalidDataResources( "Video file " + filePath + " is being corrupted. Make sure that you own an official version of the game." ); } } } SMKVideoSequence::SMKVideoSequence( const std::string & filePath ) : _width( 0 ) , _height( 0 ) , _heightScaleFactor( 1 ) , _fps( 0 ) , _frameCount( 0 ) , _currentFrameId( 0 ) , _videoFile( nullptr ) { verifyVideoFile( filePath ); _videoFile = smk_open_file( filePath.c_str(), SMK_MODE_MEMORY ); if ( _videoFile == nullptr ) return; double usf = 0; const uint8_t audioChannelCount = 7; uint8_t trackMask = 0; uint8_t channelsPerTrack[audioChannelCount] = { 0 }; uint8_t audioBitDepth[audioChannelCount] = { 0 }; unsigned long audioRate[audioChannelCount] = { 0 }; std::array, audioChannelCount> soundBuffer; unsigned long width = 0; unsigned long height = 0; unsigned char scaledYMode = 1; smk_info_all( _videoFile, nullptr, &_frameCount, &usf ); smk_info_video( _videoFile, &width, &height, &scaledYMode ); _heightScaleFactor = scaledYMode; if ( _heightScaleFactor < 1 ) { // This is some corrupted video file. Let's still proceed with it. _heightScaleFactor = 1; } else if ( _heightScaleFactor > 2 ) { // None of formats supports scaling more than 2. _heightScaleFactor = 2; } _width = static_cast( width ); _height = static_cast( height ) * _heightScaleFactor; smk_info_audio( _videoFile, &trackMask, channelsPerTrack, audioBitDepth, audioRate ); if ( usf > 0 ) _fps = 1000000.0 / usf; else _fps = 15; // let's use as a default for ( uint8_t i = 0; i < audioChannelCount; ++i ) { if ( trackMask & ( 1 << i ) ) { smk_enable_audio( _videoFile, i, 1 ); } } smk_enable_video( _videoFile, 0 ); // disable video reading smk_first( _videoFile ); unsigned long currentFrame = 0; smk_info_all( _videoFile, ¤tFrame, nullptr, nullptr ); for ( uint8_t i = 0; i < audioChannelCount; ++i ) { if ( trackMask & ( 1 << i ) ) { const unsigned long length = smk_get_audio_size( _videoFile, i ); if ( length == 0 ) { continue; } if ( soundBuffer[i].empty() ) { soundBuffer[i].resize( audioHeaderSize ); } const uint8_t * data = smk_get_audio( _videoFile, i ); soundBuffer[i].insert( soundBuffer[i].end(), data, data + length ); } } for ( currentFrame = 1; currentFrame < _frameCount; ++currentFrame ) { smk_next( _videoFile ); for ( uint8_t i = 0; i < audioChannelCount; ++i ) { if ( trackMask & ( 1 << i ) ) { const unsigned long length = smk_get_audio_size( _videoFile, i ); if ( length == 0 ) { continue; } if ( soundBuffer[i].empty() ) { soundBuffer[i].resize( audioHeaderSize ); } const uint8_t * data = smk_get_audio( _videoFile, i ); soundBuffer[i].insert( soundBuffer[i].end(), data, data + length ); } } } size_t channelCount = 0; for ( size_t i = 0; i < soundBuffer.size(); ++i ) { if ( !soundBuffer[i].empty() ) { ++channelCount; } } _audioChannel.resize( channelCount ); channelCount = 0; // Compose the soundtrack for ( size_t i = 0; i < soundBuffer.size(); ++i ) { if ( !soundBuffer[i].empty() ) { std::vector & wavData = _audioChannel[channelCount]; std::swap( wavData, soundBuffer[i] ); const uint32_t originalSize = static_cast( wavData.size() - audioHeaderSize ); ++channelCount; RWStreamBuf wavHeader( audioHeaderSize ); wavHeader.putLE32( 0x46464952 ); // RIFF marker ("RIFF") wavHeader.putLE32( originalSize + 0x24 ); // Total size minus the size of this and previous fields wavHeader.putLE32( 0x45564157 ); // File type header ("WAVE") wavHeader.putLE32( 0x20746D66 ); // Format sub-chunk marker ("fmt ") wavHeader.putLE32( 0x10 ); // Size of the format sub-chunk wavHeader.putLE16( 0x01 ); // Audio format (1 for PCM) wavHeader.putLE16( channelsPerTrack[i] ); // Number of channels wavHeader.putLE32( audioRate[i] ); // Sample rate wavHeader.putLE32( audioRate[i] * audioBitDepth[i] * channelsPerTrack[i] / 8 ); // Byte rate wavHeader.putLE16( audioBitDepth[i] * channelsPerTrack[i] / 8 ); // Block align wavHeader.putLE16( audioBitDepth[i] ); // Bits per sample wavHeader.putLE32( 0x61746164 ); // Data sub-chunk marker ("data") wavHeader.putLE32( originalSize ); // Size of the data sub-chunk memcpy( wavData.data(), wavHeader.data(), audioHeaderSize ); } } smk_enable_video( _videoFile, 1 ); // enable video reading smk_first( _videoFile ); } SMKVideoSequence::~SMKVideoSequence() { if ( _videoFile != nullptr ) { smk_close( _videoFile ); } } int32_t SMKVideoSequence::width() const { return _width; } int32_t SMKVideoSequence::height() const { return _height; } double SMKVideoSequence::fps() const { return _fps; } unsigned long SMKVideoSequence::frameCount() const { return _frameCount; } void SMKVideoSequence::resetFrame() { if ( _videoFile == nullptr ) return; smk_first( _videoFile ); _currentFrameId = 0; } void SMKVideoSequence::getNextFrame( fheroes2::Image & image, const int32_t x, const int32_t y, int32_t & width, int32_t & height, std::vector & palette ) { if ( _videoFile == nullptr || image.empty() || x < 0 || y < 0 || x >= image.width() || y >= image.height() || !image.singleLayer() ) { width = 0; height = 0; return; } const uint8_t * data = smk_get_video( _videoFile ); const uint8_t * paletteData = smk_get_palette( _videoFile ); width = _width; height = _height; assert( _heightScaleFactor == 1 || _heightScaleFactor == 2 ); assert( ( _height % _heightScaleFactor ) == 0 ); if ( image.width() == _width && image.height() == _height && x == 0 && y == 0 ) { const size_t size = static_cast( _width ) * _height; if ( _heightScaleFactor == 2 ) { assert( ( height % _heightScaleFactor ) == 0 ); const uint8_t * inY = data; uint8_t * outY = image.image(); const uint8_t * outYEnd = outY + height * _width; for ( ; outY != outYEnd; outY += _heightScaleFactor * _width, inY += _width ) { std::copy( inY, inY + width, outY ); } } else { std::copy( data, data + size, image.image() ); } } else { if ( x + width > image.width() ) { width = image.width() - x; } if ( y + height > image.height() ) { height = image.height() - y; } const uint8_t * inY = data; const int32_t imageWidth = image.width(); uint8_t * outY = image.image() + x + y * imageWidth; const uint8_t * outYEnd = outY + ( height / _heightScaleFactor ) * _heightScaleFactor * imageWidth; if ( _heightScaleFactor == 2 ) { assert( ( height % _heightScaleFactor ) == 0 ); for ( ; outY != outYEnd; outY += _heightScaleFactor * imageWidth, inY += _width ) { std::copy( inY, inY + width, outY ); } } else { for ( ; outY != outYEnd; outY += imageWidth, inY += _width ) { std::copy( inY, inY + width, outY ); } } } palette.resize( 256 * 3 ); memcpy( palette.data(), paletteData, 256 * 3 ); ++_currentFrameId; if ( _currentFrameId < _frameCount ) { smk_next( _videoFile ); } } std::vector SMKVideoSequence::getCurrentPalette() const { const uint8_t * paletteData = smk_get_palette( _videoFile ); assert( paletteData != nullptr ); return std::vector( paletteData, paletteData + 256 * 3 ); } const std::vector> & SMKVideoSequence::getAudioChannels() const { return _audioChannel; } fheroes2-1.1.6+dfsg/src/engine/smk_decoder.h000066400000000000000000000054371476115357100206620ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include namespace fheroes2 { class Image; } class SMKVideoSequence { public: explicit SMKVideoSequence( const std::string & filePath ); ~SMKVideoSequence(); SMKVideoSequence( const SMKVideoSequence & ) = delete; SMKVideoSequence & operator=( const SMKVideoSequence & ) = delete; void resetFrame(); // Input image must be resized to accommodate the frame and also it must be a single layer image as video frames shouldn't have any transform-related information. // If the image is smaller than the frame then only a part of the frame will be drawn. void getNextFrame( fheroes2::Image & image, const int32_t x, const int32_t y, int32_t & width, int32_t & height, std::vector & palette ); std::vector getCurrentPalette() const; const std::vector> & getAudioChannels() const; int32_t width() const; int32_t height() const; double fps() const; unsigned long frameCount() const; unsigned long getCurrentFrame() const { return _currentFrameId; } private: std::vector> _audioChannel; int32_t _width; int32_t _height; int32_t _heightScaleFactor; double _fps; unsigned long _frameCount; unsigned long _currentFrameId; struct smk_t * _videoFile; }; fheroes2-1.1.6+dfsg/src/engine/system.cpp000066400000000000000000000450661476115357100202640ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "system.h" #include #include #include #include #include #include #include #if defined( _WIN32 ) #include #include "tools.h" #define WIN32_LEAN_AND_MEAN #include #elif defined( TARGET_PS_VITA ) #include #endif #if !defined( _WIN32 ) && !defined( ANDROID ) && !defined( TARGET_PS_VITA ) #include #include #endif // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wswitch-default" #endif #include #include #if defined( ANDROID ) #include #include #endif #if SDL_VERSION_ATLEAST( 2, 0, 1 ) && ( !defined( __linux__ ) || defined( ANDROID ) ) #include #include #endif // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif namespace { #if !defined( __linux__ ) || defined( ANDROID ) std::string GetHomeDirectory( const std::string_view appName ) { #if defined( TARGET_PS_VITA ) return System::concatPath( "ux0:data", appName ); #elif defined( TARGET_NINTENDO_SWITCH ) return System::concatPath( "/switch", appName ); #elif defined( ANDROID ) (void)appName; if ( const char * storagePath = SDL_AndroidGetExternalStoragePath(); storagePath != nullptr ) { return storagePath; } return {}; #endif { const char * homeEnvPath = getenv( "HOME" ); #if defined( MACOS_APP_BUNDLE ) if ( homeEnvPath != nullptr ) { return System::concatPath( System::concatPath( homeEnvPath, "Library/Preferences" ), appName ); } return {}; #endif if ( homeEnvPath != nullptr ) { return System::concatPath( homeEnvPath, std::string( "." ).append( appName ) ); } } if ( const char * dataEnvPath = getenv( "APPDATA" ); dataEnvPath != nullptr ) { return System::concatPath( dataEnvPath, appName ); } #if SDL_VERSION_ATLEAST( 2, 0, 1 ) if ( const std::unique_ptr path( SDL_GetPrefPath( "", System::encLocalToUTF8( std::string{ appName } ).c_str() ), SDL_free ); path ) { return System::encUTF8ToLocal( path.get() ); } #endif return {}; } #endif bool globMatch( const std::string_view string, const std::string_view wildcard ) { size_t stringIdx = 0; size_t wildcardIdx = 0; size_t fallbackStringIdx = std::string_view::npos; size_t fallbackWildcardIdx = std::string_view::npos; while ( stringIdx < string.length() ) { const bool isWildcardNotEnded = ( wildcardIdx < wildcard.length() ); if ( isWildcardNotEnded && wildcard[wildcardIdx] == '*' ) { ++wildcardIdx; fallbackStringIdx = stringIdx; fallbackWildcardIdx = wildcardIdx; } else if ( isWildcardNotEnded && ( wildcard[wildcardIdx] == '?' || wildcard[wildcardIdx] == string[stringIdx] ) ) { ++stringIdx; ++wildcardIdx; } else { if ( fallbackWildcardIdx == std::string_view::npos ) { return false; } assert( fallbackStringIdx != std::string_view::npos ); ++fallbackStringIdx; stringIdx = fallbackStringIdx; wildcardIdx = fallbackWildcardIdx; } } for ( ; wildcardIdx < wildcard.length(); ++wildcardIdx ) { if ( wildcard[wildcardIdx] != '*' ) { break; } } return wildcardIdx == wildcard.length(); } #if defined( _WIN32 ) enum class EncodingConversionDirection { ACPToUTF8, UTF8ToACP }; std::string convertBetweenACPAndUTF8( const std::string_view str, const EncodingConversionDirection dir ) { if ( str.empty() ) { return {}; } thread_local std::map>> resultsCache; if ( const auto dirIter = resultsCache.find( dir ); dirIter != resultsCache.end() ) { const auto & strMap = dirIter->second; if ( const auto strIter = strMap.find( str ); strIter != strMap.end() ) { return strIter->second; } } // In case of any issues, the original string will be returned, so let's put it to the cache right away const auto [resultIter, inserted] = resultsCache[dir].try_emplace( std::string{ str }, str ); if ( !inserted ) { assert( 0 ); } const auto strLen = fheroes2::checkedCast( str.size() ); if ( !strLen ) { // The size of this string does not fit into an int, so this string cannot be safely converted #ifdef WITH_DEBUG assert( 0 ); #endif return std::string{ str }; } const auto [mbCodePage, mbFlags, wcCodePage, wcFlags] = [dir]() -> std::tuple { switch ( dir ) { case EncodingConversionDirection::ACPToUTF8: return { CP_ACP, MB_ERR_INVALID_CHARS, CP_UTF8, WC_ERR_INVALID_CHARS }; case EncodingConversionDirection::UTF8ToACP: return { CP_UTF8, MB_ERR_INVALID_CHARS, CP_ACP, WC_NO_BEST_FIT_CHARS }; default: assert( 0 ); break; } return { CP_ACP, MB_ERR_INVALID_CHARS, CP_ACP, WC_NO_BEST_FIT_CHARS }; }(); const int wcLen = MultiByteToWideChar( mbCodePage, mbFlags, str.data(), *strLen, nullptr, 0 ); if ( wcLen <= 0 ) { #ifdef WITH_DEBUG assert( 0 ); #endif return std::string{ str }; } // The contents of this buffer will not be zero-terminated const std::unique_ptr wcStr( new wchar_t[wcLen] ); if ( MultiByteToWideChar( mbCodePage, mbFlags, str.data(), *strLen, wcStr.get(), wcLen ) != wcLen ) { #ifdef WITH_DEBUG assert( 0 ); #endif return std::string{ str }; } const int mbLen = WideCharToMultiByte( wcCodePage, wcFlags, wcStr.get(), wcLen, nullptr, 0, nullptr, nullptr ); if ( mbLen <= 0 ) { #ifdef WITH_DEBUG assert( 0 ); #endif return std::string{ str }; } // The contents of this buffer will not be zero-terminated const std::unique_ptr mbStr( new char[mbLen] ); if ( WideCharToMultiByte( wcCodePage, wcFlags, wcStr.get(), wcLen, mbStr.get(), mbLen, nullptr, nullptr ) != mbLen ) { #ifdef WITH_DEBUG assert( 0 ); #endif return std::string{ str }; } // The contents of this buffer is not zero-terminated std::string result( mbStr.get(), mbLen ); // Put the final result to the cache resultIter->second = result; return result; } #endif } bool System::isHandheldDevice() { #if defined( ANDROID ) return true; #else return false; #endif } bool System::isTouchInputAvailable() { return SDL_GetNumTouchDevices() > 0; } bool System::isVirtualKeyboardSupported() { #if defined( ANDROID ) || defined( TARGET_PS_VITA ) || defined( TARGET_NINTENDO_SWITCH ) return true; #else return false; #endif } bool System::isShellLevelGlobbingSupported() { #if defined( _WIN32 ) return false; #else return true; #endif } bool System::MakeDirectory( const std::string_view path ) { std::error_code ec; // Using the non-throwing overload return std::filesystem::create_directories( path, ec ); } bool System::Unlink( const std::string_view path ) { std::error_code ec; // Using the non-throwing overload return std::filesystem::remove( path, ec ); } std::string System::concatPath( const std::string_view left, const std::string_view right ) { return fsPathToString( std::filesystem::path{ left }.append( right ) ); } void System::appendOSSpecificDirectories( std::vector & directories ) { #if defined( TARGET_PS_VITA ) const char * path = "ux0:app/FHOMM0002"; if ( std::find( directories.begin(), directories.end(), path ) == directories.end() ) { directories.emplace_back( path ); } #else (void)directories; #endif } std::string System::GetConfigDirectory( const std::string_view appName ) { // Location of the app config directory, in theory, should not change while the app is running and can be cached thread_local std::map> resultsCache; if ( const auto iter = resultsCache.find( appName ); iter != resultsCache.end() ) { return iter->second; } std::string result = [&appName]() -> std::string { #if defined( __linux__ ) && !defined( ANDROID ) if ( const char * configEnv = getenv( "XDG_CONFIG_HOME" ); configEnv != nullptr ) { return concatPath( configEnv, appName ); } if ( const char * homeEnv = getenv( "HOME" ); homeEnv != nullptr ) { return concatPath( concatPath( homeEnv, ".config" ), appName ); } return {}; #else return GetHomeDirectory( appName ); #endif }(); if ( const auto [dummy, inserted] = resultsCache.try_emplace( std::string{ appName }, result ); !inserted ) { assert( 0 ); } return result; } std::string System::GetDataDirectory( const std::string_view appName ) { // Location of the app data directory, in theory, should not change while the app is running and can be cached thread_local std::map> resultsCache; if ( const auto iter = resultsCache.find( appName ); iter != resultsCache.end() ) { return iter->second; } std::string result = [&appName]() -> std::string { #if defined( __linux__ ) && !defined( ANDROID ) if ( const char * dataEnv = getenv( "XDG_DATA_HOME" ); dataEnv != nullptr ) { return concatPath( dataEnv, appName ); } if ( const char * homeEnv = getenv( "HOME" ); homeEnv != nullptr ) { return concatPath( concatPath( homeEnv, ".local/share" ), appName ); } return {}; #elif defined( MACOS_APP_BUNDLE ) if ( const char * homeEnv = getenv( "HOME" ); homeEnv != nullptr ) { return concatPath( concatPath( homeEnv, "Library/Application Support" ), appName ); } return {}; #else return GetHomeDirectory( appName ); #endif }(); if ( const auto [dummy, inserted] = resultsCache.try_emplace( std::string{ appName }, result ); !inserted ) { assert( 0 ); } return result; } std::string System::GetParentDirectory( std::string_view path ) { return fsPathToString( std::filesystem::path{ path }.parent_path() ); } std::string System::GetFileName( std::string_view path ) { return fsPathToString( std::filesystem::path{ path }.filename() ); } std::string System::GetStem( const std::string_view path ) { return fsPathToString( std::filesystem::path{ path }.stem() ); } bool System::IsFile( const std::string_view path ) { if ( path.empty() ) { // An empty path cannot be a file. return false; } std::string correctedPath; if ( !GetCaseInsensitivePath( path, correctedPath ) ) { return false; } std::error_code ec; // Using the non-throwing overload return std::filesystem::is_regular_file( correctedPath, ec ); } bool System::IsDirectory( const std::string_view path ) { if ( path.empty() ) { // An empty path cannot be a directory. return false; } std::string correctedPath; if ( !GetCaseInsensitivePath( path, correctedPath ) ) { return false; } std::error_code ec; // Using the non-throwing overload return std::filesystem::is_directory( correctedPath, ec ); } bool System::GetCaseInsensitivePath( const std::string_view path, std::string & correctedPath ) { #if !defined( _WIN32 ) && !defined( ANDROID ) && !defined( TARGET_PS_VITA ) // The following code is based on https://github.com/OneSadCookie/fcaseopen and assumes the use of POSIX IEEE Std 1003.1-2001 pathnames correctedPath.clear(); if ( path.empty() ) { return false; } constexpr char dirSep{ '/' }; std::unique_ptr dir( path.front() == dirSep ? opendir( "/" ) : opendir( "." ), closedir ); for ( const std::filesystem::path & pathItem : std::filesystem::path{ path } ) { if ( !dir ) { return false; } if ( !correctedPath.empty() && correctedPath.back() != dirSep ) { correctedPath += dirSep; } // Avoid directory traversal and try to probe directory name directly. // Speeds up file lookup when intermediate directories have a lot of // files. Example is NixOS where file layout is: // /nix/store/...-fheroes2-${ver}/share/fheroes2/files/lang // /nix/store/...-other-package-1/... // /nix/store/...-other-package-2/... // It's not uncommon for /nix/store to have tens of thousands files. // GetCaseInsensitivePath() calls become very expensive on such systems. // // The idea is to try to open the current path item as a directory and // avoid directory traversal altogether. Otherwise fall back to linear // case-insensitive search. { std::string tmpPath = correctedPath + pathItem.string(); if ( std::unique_ptr tmpDir( opendir( tmpPath.c_str() ), closedir ); tmpDir ) { correctedPath = std::move( tmpPath ); dir = std::move( tmpDir ); continue; } } const struct dirent * entry = readdir( dir.get() ); while ( entry != nullptr ) { if ( strcasecmp( pathItem.c_str(), entry->d_name ) == 0 ) { correctedPath += entry->d_name; dir.reset( opendir( correctedPath.c_str() ) ); break; } entry = readdir( dir.get() ); } if ( entry == nullptr ) { return false; } } #else correctedPath = path; #endif return !correctedPath.empty(); } void System::globFiles( const std::string_view glob, std::vector & fileNames ) { const std::filesystem::path globPath( glob ); std::filesystem::path dirPath = globPath.parent_path(); if ( dirPath.empty() ) { dirPath = std::filesystem::path{ "." }; } std::error_code ec; // Using the non-throwing overload if ( !std::filesystem::is_directory( dirPath, ec ) ) { fileNames.emplace_back( glob ); return; } const std::string pattern = globPath.filename().string(); if ( pattern.find( '*' ) == std::string_view::npos && pattern.find( '?' ) == std::string_view::npos ) { fileNames.emplace_back( glob ); return; } bool isNoMatches = true; // Using the non-throwing overload for ( const std::filesystem::directory_entry & entry : std::filesystem::directory_iterator( dirPath, ec ) ) { const std::filesystem::path & entryPath = entry.path(); if ( !globMatch( fsPathToString( entryPath.filename() ), pattern ) ) { continue; } fileNames.emplace_back( fsPathToString( entryPath ) ); isNoMatches = false; } if ( isNoMatches ) { fileNames.emplace_back( glob ); } } std::string System::encLocalToUTF8( const std::string_view str ) { #if defined( _WIN32 ) return convertBetweenACPAndUTF8( str, EncodingConversionDirection::ACPToUTF8 ); #else return std::string{ str }; #endif } std::string System::encUTF8ToLocal( const std::string_view str ) { #if defined( _WIN32 ) return convertBetweenACPAndUTF8( str, EncodingConversionDirection::UTF8ToACP ); #else return std::string{ str }; #endif } std::string System::fsPathToString( const std::filesystem::path & path ) { #if defined( _WIN32 ) // On Windows, std::filesystem::path::string() can throw an exception if path contains UTF-16 characters that // are non-representable in CP_ACP. However, converting a well-formed UTF-16 string to UTF-8 is always safe, // so we perform this conversion first, and then convert the resulting UTF-8 to CP_ACP using our conversion // function, which can never throw an exception. return encUTF8ToLocal( path.u8string() ); #else return path.string(); #endif } tm System::GetTM( const time_t time ) { tm result = {}; #if defined( _WIN32 ) errno_t res = localtime_s( &result, &time ); if ( res != 0 ) { assert( 0 ); } #else const tm * res = localtime_r( &time, &result ); if ( res == nullptr ) { assert( 0 ); } #endif return result; } fheroes2-1.1.6+dfsg/src/engine/system.h000066400000000000000000000116211476115357100177170ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2013 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include namespace System { bool isHandheldDevice(); // Returns true if the target platform supports touch input, otherwise returns false. bool isTouchInputAvailable(); bool isVirtualKeyboardSupported(); // Returns true if target platform supports shell-level globbing (Unix-like platforms with POSIX-compatible shells). // Otherwise returns false, which means that app need to resolve wildcard patterns itself (for example, on Windows). bool isShellLevelGlobbingSupported(); bool MakeDirectory( const std::string_view path ); bool Unlink( const std::string_view path ); std::string concatPath( const std::string_view left, const std::string_view right ); void appendOSSpecificDirectories( std::vector & directories ); // Returns the path to the app settings directory (usually some user-specific directory). An empty string can be returned, // which should be considered as the current directory. std::string GetConfigDirectory( const std::string_view appName ); // Returns the path to the app data directory (usually some user-specific directory). An empty string can be returned, // which should be considered as the current directory. std::string GetDataDirectory( const std::string_view appName ); std::string GetParentDirectory( std::string_view path ); std::string GetFileName( std::string_view path ); std::string GetStem( const std::string_view path ); bool IsFile( const std::string_view path ); bool IsDirectory( const std::string_view path ); bool GetCaseInsensitivePath( const std::string_view path, std::string & correctedPath ); // Resolves the wildcard pattern 'glob' and appends matching paths to 'fileNames'. Supported wildcards are '?' and '*'. // These wildcards are resolved only if they are in the last element of the path. For example, they will be resolved // in the case of the 'foo/b*r?' pattern, but they will be ignored (used as is) in the case of '*/bar' pattern. If there // are no files matching the pattern, it will be appended to the 'fileNames' as is. void globFiles( const std::string_view glob, std::vector & fileNames ); // Converts the given string from local encoding to UTF-8 encoding (used by SDL). It is used mainly on Windows, because on // Windows this app works with ANSI code page (CP_ACP). On all other systems, it is currently assumed that UTF-8 encoding // is used, and the original string is simply returned unchanged. std::string encLocalToUTF8( const std::string_view str ); // Converts the given string from UTF-8 encoding (used by SDL) to local encoding. It is used mainly on Windows, because on // Windows this app works with ANSI code page (CP_ACP). On all other systems, it is currently assumed that UTF-8 encoding // is used, and the original string is simply returned unchanged. std::string encUTF8ToLocal( const std::string_view str ); // Performs a safe conversion of an std::filesystem::path instance to a string. See the implementation for details. std::string fsPathToString( const std::filesystem::path & path ); tm GetTM( const time_t time ); } fheroes2-1.1.6+dfsg/src/engine/thread.cpp000066400000000000000000000110111476115357100201660ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "thread.h" #include #include #if defined( __EMSCRIPTEN__ ) && !defined( __EMSCRIPTEN_PTHREADS__ ) namespace { class MutexUnlocker { public: explicit MutexUnlocker( std::mutex & mutex ) : _mutex( mutex ) { _mutex.unlock(); } MutexUnlocker( const MutexUnlocker & ) = delete; ~MutexUnlocker() { _mutex.lock(); } MutexUnlocker & operator=( const MutexUnlocker & ) = delete; private: std::mutex & _mutex; }; } #endif namespace MultiThreading { void AsyncManager::createWorker() { #if !defined( __EMSCRIPTEN__ ) || defined( __EMSCRIPTEN_PTHREADS__ ) if ( !_worker ) { _runFlag = true; _worker = std::make_unique( AsyncManager::_workerThread, this ); { std::unique_lock lock( _mutex ); _masterNotification.wait( lock, [this] { return !_runFlag; } ); } } #endif } void AsyncManager::stopWorker() { #if defined( __EMSCRIPTEN__ ) && !defined( __EMSCRIPTEN_PTHREADS__ ) assert( !_worker ); #else if ( _worker ) { { const std::scoped_lock lock( _mutex ); _exitFlag = true; _runFlag = true; } _workerNotification.notify_all(); _worker->join(); _worker.reset(); } #endif } void AsyncManager::notifyWorker() { _runFlag = true; #if defined( __EMSCRIPTEN__ ) && !defined( __EMSCRIPTEN_PTHREADS__ ) assert( !_exitFlag ); while ( _runFlag ) { const bool moreTasks = prepareTask(); if ( !moreTasks ) { _runFlag = false; } { // In accordance with the contract, the _mutex should NOT be acquired while // calling the executeTask() - even if its acquisition is in fact a snake oil. MutexUnlocker unlocker( _mutex ); executeTask(); } } #else _workerNotification.notify_all(); #endif } void AsyncManager::_workerThread( AsyncManager * manager ) { assert( manager != nullptr ); { const std::scoped_lock lock( manager->_mutex ); manager->_runFlag = false; } manager->_masterNotification.notify_one(); while ( !manager->_exitFlag ) { { std::unique_lock lock( manager->_mutex ); manager->_workerNotification.wait( lock, [manager] { return manager->_runFlag; } ); } if ( manager->_exitFlag ) { break; } { const std::scoped_lock lock( manager->_mutex ); const bool moreTasks = manager->prepareTask(); if ( !moreTasks ) { manager->_runFlag = false; } } manager->executeTask(); } } } fheroes2-1.1.6+dfsg/src/engine/thread.h000066400000000000000000000060721476115357100176460ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include namespace MultiThreading { class AsyncManager { public: AsyncManager() = default; AsyncManager( const AsyncManager & ) = delete; virtual ~AsyncManager() = default; AsyncManager & operator=( const AsyncManager & ) = delete; // Create the worker thread if it doesn't exist yet. Both createWorker() and stopWorker() are not // designed to be executed concurrently. void createWorker(); // Stop and join the worker thread. This cannot be done in the destructor (directly or indirectly) due // to the potential race on the vptr since this class has virtual methods that could be called from the // worker thread. void stopWorker(); protected: std::mutex _mutex; // Notify the worker thread about a new task. The _mutex should be acquired while calling this method. void notifyWorker(); // Prepare the next task. The _mutex will be acquired while calling this method. Returns true if more tasks are available. virtual bool prepareTask() = 0; // Execute the next task. NOTE WELL: the _mutex will NOT be acquired while calling this method. virtual void executeTask() = 0; private: std::unique_ptr _worker; std::condition_variable _masterNotification; std::condition_variable _workerNotification; std::atomic _exitFlag{ false }; bool _runFlag{ false }; static void _workerThread( AsyncManager * manager ); }; } fheroes2-1.1.6+dfsg/src/engine/timing.cpp000066400000000000000000000057631476115357100202270ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "timing.h" namespace fheroes2 { Time::Time() : _startTime( std::chrono::steady_clock::now() ) {} void Time::reset() { _startTime = std::chrono::steady_clock::now(); } double Time::getS() const { const std::chrono::duration time = std::chrono::steady_clock::now() - _startTime; return time.count(); } uint64_t Time::getMs() const { const auto time = std::chrono::duration_cast( std::chrono::steady_clock::now() - _startTime ); return time.count(); } TimeDelay::TimeDelay( const uint64_t delayMs ) : _prevTime( std::chrono::steady_clock::now() ) , _delayMs( delayMs ) {} void TimeDelay::setDelay( const uint64_t delayMs ) { _delayMs = delayMs; } bool TimeDelay::isPassed() const { return isPassed( _delayMs ); } bool TimeDelay::isPassed( const uint64_t delayMs ) const { const auto time = std::chrono::duration_cast( std::chrono::steady_clock::now() - _prevTime ); const uint64_t passedMs = time.count(); return passedMs >= delayMs; } void TimeDelay::reset() { _prevTime = std::chrono::steady_clock::now(); } void TimeDelay::pass() { _prevTime = std::chrono::steady_clock::now() - std::chrono::milliseconds( 2 * _delayMs ); } void delayforMs( const uint32_t delayMs ) { std::this_thread::sleep_for( std::chrono::milliseconds( delayMs ) ); } } fheroes2-1.1.6+dfsg/src/engine/timing.h000066400000000000000000000054201476115357100176620ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace fheroes2 { // IMPORTANT!!! According to https://en.cppreference.com/w/cpp/chrono/high_resolution_clock we should never use high_resolution_clock for time internal measurements // because for high_resolution_clock the time may go backwards. class Time { public: Time(); void reset(); // Returns time in seconds. double getS() const; // Returns rounded time in milliseconds. uint64_t getMs() const; private: std::chrono::time_point _startTime; }; class TimeDelay { public: TimeDelay() = delete; explicit TimeDelay( const uint64_t delayMs ); void setDelay( const uint64_t delayMs ); uint64_t getDelay() const { return _delayMs; } bool isPassed() const; bool isPassed( const uint64_t delayMs ) const; // Reset delay by starting the count from the current time. void reset(); // Explicitly set delay to passed state. Can be used in cases when first call of isPassed() must return true. void pass(); private: std::chrono::time_point _prevTime; uint64_t _delayMs; }; void delayforMs( const uint32_t delayMs ); } fheroes2-1.1.6+dfsg/src/engine/tinyconfig.cpp000066400000000000000000000222261476115357100211020ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "tinyconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "logging.h" #include "serialize.h" #include "tools.h" namespace { std::string ModifyKey( const std::string & str ) { std::string key = StringTrim( StringLower( str ) ); // Replace consecutive space-like characters with only one such character key.erase( std::unique( key.begin(), key.end(), []( const unsigned char a, const unsigned char b ) { return std::isspace( a ) && std::isspace( b ); } ), key.end() ); // Replace all space-like characters with spaces std::replace_if( key.begin(), key.end(), []( const unsigned char c ) { return std::isspace( c ); }, '\x20' ); return key; } template , bool> = true> bool convertToInt( const std::string_view str, T & intValue ) { const char * first = str.data(); const char * last = str.data() + str.size(); const auto [ptr, ec] = std::from_chars( first, last, intValue ); return ( ptr == last && ec == std::errc() ); } } TinyConfig::TinyConfig( const char sep, const char com ) : separator( sep ) , comment( com ) {} bool TinyConfig::Load( const std::string & cfile ) { StreamFile sf; if ( !sf.open( cfile, "rb" ) ) { return false; } for ( const std::string & line : StringSplit( sf.getString(), '\n' ) ) { std::string str = StringTrim( line ); if ( str.empty() || str[0] == comment ) { continue; } size_t pos = str.find( separator ); if ( pos == std::string::npos ) { continue; } const std::string key = ModifyKey( StringTrim( str.substr( 0, pos ) ) ); const std::string val = StringTrim( str.substr( pos + 1, str.length() - pos - 1 ) ); if ( const auto [dummy, inserted] = emplace( key, val ); !inserted ) { ERROR_LOG( "Duplicate key '" << key << "' was found when reading the config file " << cfile ) } } return true; } int TinyConfig::IntParams( const std::string & key ) const { const_iterator it = find( ModifyKey( key ) ); if ( it == end() ) { return 0; } int result; if ( !convertToInt( it->second, result ) ) { return 0; } return result; } std::string TinyConfig::StrParams( const std::string & key ) const { const_iterator it = find( ModifyKey( key ) ); return it != end() ? it->second : ""; } fheroes2::Point TinyConfig::PointParams( const std::string & key, const fheroes2::Point & fallbackValue ) const { const const_iterator it = find( ModifyKey( key ) ); if ( it == end() ) { return fallbackValue; } static const std::regex pointRegex( "^\\[ *(-?[0-9]+) *, *(-?[0-9]+) *]$", std::regex_constants::extended ); std::smatch pointRegexMatch; if ( !std::regex_match( it->second, pointRegexMatch, pointRegex ) ) { return fallbackValue; } assert( pointRegexMatch.size() == 3 ); fheroes2::Point result; static_assert( std::is_integral::value && std::is_integral::value, "The type of result fields is not integer, check the logic of this method" ); if ( !convertToInt( pointRegexMatch[1].str(), result.x ) ) { return fallbackValue; } if ( !convertToInt( pointRegexMatch[2].str(), result.y ) ) { return fallbackValue; } return result; } fheroes2::ResolutionInfo TinyConfig::ResolutionParams( const std::string & key, const fheroes2::ResolutionInfo & fallbackValue ) const { const const_iterator it = find( ModifyKey( key ) ); if ( it == end() ) { return fallbackValue; } { // Current format: in-game width x in-game height : on-screen width x on-screen height static const std::regex resolutionRegex( "^ *([0-9]+) *x *([0-9]+) *: *([0-9]+) *x *([0-9]+) *$", std::regex_constants::extended ); std::smatch resolutionRegexMatch; if ( std::regex_match( it->second, resolutionRegexMatch, resolutionRegex ) ) { assert( resolutionRegexMatch.size() == 5 ); int32_t gameWidth{ 0 }; int32_t gameHeight{ 0 }; int32_t screenWidth{ 0 }; int32_t screenHeight{ 0 }; if ( !convertToInt( resolutionRegexMatch[1].str(), gameWidth ) ) { return fallbackValue; } if ( !convertToInt( resolutionRegexMatch[2].str(), gameHeight ) ) { return fallbackValue; } if ( !convertToInt( resolutionRegexMatch[3].str(), screenWidth ) ) { return fallbackValue; } if ( !convertToInt( resolutionRegexMatch[4].str(), screenHeight ) ) { return fallbackValue; } return { gameWidth, gameHeight, screenWidth, screenHeight }; } } { // Old format: in-game width x in-game height x on-screen multiplier static const std::regex resolutionRegex( "^ *([0-9]+) *x *([0-9]+) *x *([0-9]+) *$", std::regex_constants::extended ); std::smatch resolutionRegexMatch; if ( std::regex_match( it->second, resolutionRegexMatch, resolutionRegex ) ) { assert( resolutionRegexMatch.size() == 4 ); int32_t gameWidth{ 0 }; int32_t gameHeight{ 0 }; int32_t screenMultiplier{ 0 }; if ( !convertToInt( resolutionRegexMatch[1].str(), gameWidth ) ) { return fallbackValue; } if ( !convertToInt( resolutionRegexMatch[2].str(), gameHeight ) ) { return fallbackValue; } if ( !convertToInt( resolutionRegexMatch[3].str(), screenMultiplier ) ) { return fallbackValue; } assert( gameWidth >= 0 && gameHeight >= 0 && screenMultiplier >= 0 ); if ( screenMultiplier == 0 ) { return fallbackValue; } // Check for potential signed overflow on multiplication if ( gameWidth > std::numeric_limits::max() / screenMultiplier || gameHeight > std::numeric_limits::max() / screenMultiplier ) { return fallbackValue; } return { gameWidth, gameHeight, gameWidth * screenMultiplier, gameHeight * screenMultiplier }; } } { // Abbreviated format: in-game width x in-game height with on-screen multiplier 1 static const std::regex resolutionRegex( "^ *([0-9]+) *x *([0-9]+) *$", std::regex_constants::extended ); std::smatch resolutionRegexMatch; if ( std::regex_match( it->second, resolutionRegexMatch, resolutionRegex ) ) { assert( resolutionRegexMatch.size() == 3 ); int32_t gameWidth{ 0 }; int32_t gameHeight{ 0 }; if ( !convertToInt( resolutionRegexMatch[1].str(), gameWidth ) ) { return fallbackValue; } if ( !convertToInt( resolutionRegexMatch[2].str(), gameHeight ) ) { return fallbackValue; } return { gameWidth, gameHeight }; } } return fallbackValue; } bool TinyConfig::Exists( const std::string & key ) const { return end() != find( ModifyKey( key ) ); } fheroes2-1.1.6+dfsg/src/engine/tinyconfig.h000066400000000000000000000054021476115357100205440ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "math_base.h" #include "screen.h" class TinyConfig : private std::map> { public: TinyConfig( const char sep, const char com ); bool Load( const std::string & cfile ); bool Exists( const std::string & key ) const; int IntParams( const std::string & key ) const; std::string StrParams( const std::string & key ) const; // Tries to find and return a Point-type struct stored as a string "[ x, y ]" for a given key. // In case of any error, the fallback value is returned. fheroes2::Point PointParams( const std::string & key, const fheroes2::Point & fallbackValue ) const; // Tries to find and return a ResolutionInfo-type struct (multiple formats are supported, see the implementation for details) // for a given key. In case of any error, the fallback value is returned. fheroes2::ResolutionInfo ResolutionParams( const std::string & key, const fheroes2::ResolutionInfo & fallbackValue ) const; private: const char separator; const char comment; }; fheroes2-1.1.6+dfsg/src/engine/tools.cpp000066400000000000000000000142761476115357100200770ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "tools.h" #include #include #include #include #include #include #include #include #include std::string StringTrim( std::string str ) { if ( str.empty() ) { return str; } // left std::string::iterator iter = str.begin(); while ( iter != str.end() && std::isspace( static_cast( *iter ) ) ) { ++iter; } if ( iter == str.end() ) { // Do not erase anything if we reached the end of the string. Just immediately return an empty string. return {}; } if ( iter != str.begin() ) str.erase( str.begin(), iter ); // right iter = str.end() - 1; while ( iter != str.begin() && std::isspace( static_cast( *iter ) ) ) { --iter; } if ( iter != str.end() - 1 ) { str.erase( iter + 1, str.end() ); } return str; } std::string StringLower( std::string str ) { std::transform( str.begin(), str.end(), str.begin(), []( const unsigned char c ) { return static_cast( std::tolower( c ) ); } ); return str; } std::string StringUpper( std::string str ) { std::transform( str.begin(), str.end(), str.begin(), []( const unsigned char c ) { return static_cast( std::toupper( c ) ); } ); return str; } void StringReplace( std::string & dst, const char * pred, const std::string_view src ) { size_t pos; while ( std::string::npos != ( pos = dst.find( pred ) ) ) { dst.replace( pos, std::strlen( pred ), src ); } } std::vector StringSplit( const std::string_view str, const char sep ) { std::vector result; size_t startPos = 0; for ( size_t sepPos = str.find( sep ); sepPos != std::string::npos; sepPos = str.find( sep, startPos ) ) { assert( startPos < str.size() && sepPos < str.size() ); result.emplace_back( str.begin() + startPos, str.begin() + sepPos ); startPos = sepPos + 1; } assert( startPos <= str.size() ); result.emplace_back( str.begin() + startPos, str.end() ); return result; } std::string insertCharToString( const std::string & inputString, const size_t position, const char character ) { std::string outputString = inputString; if ( position >= inputString.size() ) { outputString.append( 1, character ); } else { outputString.insert( position, 1, character ); } return outputString; } int Sign( const int i ) { if ( i < 0 ) { return -1; } if ( i > 0 ) { return 1; } return 0; } namespace fheroes2 { uint32_t calculateCRC32( const uint8_t * data, const size_t length ) { if ( length > std::numeric_limits::max() ) { throw std:: system_error( std::make_error_code( std::errc::value_too_large ), "Too large `length` provided to `calculateCRC32`. Must be no larger than `std::numeric_limits::max()` (usually `(1 << 32) - 1`)." ); } return static_cast( crc32( 0, data, static_cast( length ) ) ); } void replaceStringEnding( std::string & output, const char * originalEnding, const char * correctedEnding ) { assert( originalEnding != nullptr && correctedEnding != nullptr ); const size_t originalEndingSize = strlen( originalEnding ); const size_t correctedEndingSize = strlen( correctedEnding ); if ( output.size() < originalEndingSize ) { // The original string is smaller than the ending. return; } if ( memcmp( output.data() + output.size() - originalEndingSize, originalEnding, originalEndingSize ) != 0 ) { // The string does not have the required ending. return; } output.replace( output.size() - originalEndingSize, originalEndingSize, correctedEnding, correctedEndingSize ); } std::string abbreviateNumber( const int num ) { if ( std::abs( num ) >= 1000000 ) { return std::to_string( num / 1000000 ) + 'M'; } if ( std::abs( num ) >= 1000 ) { return std::to_string( num / 1000 ) + 'K'; } return std::to_string( num ); } void appendModifierToString( std::string & str, const int mod ) { if ( mod < 0 ) { // The minus sign is already present str.append( " " ); } else if ( mod > 0 ) { str.append( " +" ); } str.append( std::to_string( mod ) ); } } fheroes2-1.1.6+dfsg/src/engine/tools.h000066400000000000000000000127731476115357100175440ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include template , bool> = true> std::string GetHexString( const T value, const int width = 8 ) { std::ostringstream stream; stream << "0x" << std::setw( width ) << std::setfill( '0' ) << std::hex << value; return stream.str(); } int Sign( const int i ); std::string StringTrim( std::string str ); std::string StringLower( std::string str ); std::string StringUpper( std::string str ); std::vector StringSplit( const std::string_view str, const char sep ); void StringReplace( std::string & dst, const char * pred, const std::string_view src ); template , bool> = true> void StringReplace( std::string & dst, const char * pred, const T value ) { StringReplace( dst, pred, std::to_string( value ) ); } // Returns the number of bits that are set in the number passed as an argument constexpr int CountBits( const uint32_t val ) { int res = 0; for ( uint32_t itr = 0x00000001; itr; itr <<= 1 ) { if ( val & itr ) { ++res; } } return res; } // Returns a new text string with the inserted character in the input string at the specified position. std::string insertCharToString( const std::string & inputString, const size_t position, const char character ); namespace fheroes2 { uint32_t calculateCRC32( const uint8_t * data, const size_t length ); template void hashCombine( uint32_t & seed, const T & v ) { std::hash hasher; seed ^= hasher( v ) + 0x9e3779b9 + ( seed << 6 ) + ( seed >> 2 ); } template std::bitset makeBitsetFromVector( const std::vector & vector ) { std::bitset result; for ( const int index : vector ) { result.set( index, true ); } return result; } void replaceStringEnding( std::string & output, const char * originalEnding, const char * correctedEnding ); std::string abbreviateNumber( const int num ); // Appends the given modifier to the end of the given string (e.g. "Coliseum +2") void appendModifierToString( std::string & str, const int mod ); // Performs a checked conversion of an integer value of type From to an integer type To. Returns an empty std::optional if // the source value does not fit into the target type. template && std::is_integral_v, bool> = true> constexpr std::optional checkedCast( const From from ) { // Both types have the same signedness if constexpr ( std::is_signed_v == std::is_signed_v ) { if ( from < std::numeric_limits::min() || from > std::numeric_limits::max() ) { return {}; } return static_cast( from ); } // From is signed, To is unsigned else if constexpr ( std::is_signed_v ) { if ( from < 0 ) { return {}; } const std::make_unsigned_t unsignedFrom = from; if ( unsignedFrom > std::numeric_limits::max() ) { return {}; } return static_cast( from ); } // From is unsigned, To is signed else { constexpr To maxTo = std::numeric_limits::max(); static_assert( maxTo >= 0 ); constexpr std::make_unsigned_t unsignedMaxTo = maxTo; if ( from > unsignedMaxTo ) { return {}; } return static_cast( from ); } } } fheroes2-1.1.6+dfsg/src/engine/translations.cpp000066400000000000000000001110421476115357100214450ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "translations.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "logging.h" #include "serialize.h" #include "tools.h" namespace { const char contextSeparator = '|'; // Character lookup table for custom tolower // Compatible with ASCII, custom French encoding, CP1250 and CP1251 const std::array tolowerLUT = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // Non-printable characters 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // SP ! " # $ % & ' ( ) * + , - . / (ASCII) // SP ! " ô û % ù ' ( ) â + , - . / (French, #$&* are ôûùâ) ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? (ASCII) // 0 1 2 3 4 5 6 7 8 9 : ; ï = î ? (French, <> are ïî) '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', // @ A→a B→b C→c D→d E→e F→f G→g H→h I→i J→j K→k L→l M→m N→n O→o (ASCII) // à A→a B→b C→c D→d E→e F→f G→g H→h I→i J→j K→k L→l M→m N→n O→o (French, @ is à) '@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // P→p Q→q R→r S→s T→t U→u V→v W→w X→x Y→y Z→z [ \ ] ^ _ (ASCII) // P→p Q→q R→r S→s T→t U→u V→v W→w X→x Y→y Z→z [ \ ] ç _ (French, ^ is ç) 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_', // ` a b c d e f g h i j k l m n o (ASCII) // è a b c d e f g h i j k l m n o (French, ` is è) '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', // p q r s t u v w x y z { | } ~ DEL (ASCII) // p q r s t u v w x y z { ê } é DEL (French, |~ are êé) 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~', 0x7F, // € ‚ „ … † ‡ ‰ Š→š ‹ Ś→ś Ť→ť Ž→ž Ź→ź (1250, except €) // Ђ→ђ Ѓ→ѓ ‚ Ñ“ „ … † ‡ € ‰ Љ→љ ‹ Њ→њ Ќ→ќ Ћ→ћ Ð→џ (1251) 0x90, 0x83, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x9A, 0x8B, 0x9C, 0x9D, 0x9E, 0x9F, // ‘ ’ “ †• – — â„¢ Å¡ › Å› Å¥ ž ź (1250) // Ñ’ ‘ ’ “ †• – — â„¢ Ñ™ › Ñš Ñœ Ñ› ÑŸ (1251) 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, // NBS ˇ ˘ Å→ł ¤ Ą→ą ¦ § ¨ © Ş→ş « ¬ SHY ® Ż→ż (1250 except ˇ¨) // NBP Ў→ў Ñž Ј ¤ Ò Â¦ § Ð→ё © Є→є « ¬ SHY ® Ї→ї (1251 except ЈÒ) 0xA0, 0xA2, 0xA2, 0xB3, 0xA4, 0xB9, 0xA6, 0xA7, 0xB8, 0xA9, 0xBA, 0xAB, 0xAC, 0xAD, 0xAE, 0xBF, // ° ± Ë› Å‚ ´ µ ¶ · ¸ Ä… ÅŸ » Ľ→ľ Ë Ä¾ ż (1250 except Ë›Ë) // ° ± І→і Ñ– Ò‘ µ ¶ · Ñ‘ â„– Ñ” » ј Ѕ→ѕ Ñ• Ñ— (1251 except ј) 0xB0, 0xB1, 0xB3, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBE, 0xBE, 0xBE, 0xBF, // Ŕ→ŕ Ã→á Â→â Ă→ă Ä→ä Ĺ→ĺ Ć→ć Ç→ç ÄŒâ†’Ä Ã‰â†’Ã© Ę→ę Ë→ë Ě→ě Ã→í Î→î ÄŽâ†’Ä (1250) // Ð→а Б→б В→в Г→г Д→д Е→е Ж→ж З→з И→и Й→й К→к Л→л М→м Ð→н О→о П→п (1251) 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, // Ä→đ Ń→ń Ň→ň Ó→ó Ô→ô Å→ő Ö→ö × Ř→ř Ů→ů Ú→ú Ű→ű Ü→ü Ã→ý Ţ→ţ ß (1250, except ×ß) // Р→р Ð¡â†’Ñ Ð¢â†’Ñ‚ У→у Ф→ф Х→х Ц→ц Ч→ч Ш→ш Щ→щ Ъ→ъ Ы→ы Ь→ь Ð­â†’Ñ Ð®â†’ÑŽ Ð¯â†’Ñ (1251) 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, // Å• á â ă ä ĺ ć ç Ä Ã© Ä™ ë Ä› í î Ä (1250) // а б в г д е ж з и й к л м н о п (1251) 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, // Ä‘ Å„ ň ó ô Å‘ ö ÷ Å™ ů ú ű ü ý Å£ Ë™ (1250) // Ñ€ Ñ Ñ‚ у Ñ„ Ñ… ц ч ш щ ÑŠ Ñ‹ ÑŒ Ñ ÑŽ Ñ (1251) 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; enum class LocaleType : int { LOCALE_EN, LOCALE_AF, LOCALE_AR, LOCALE_BE, LOCALE_BG, LOCALE_CA, LOCALE_CS, LOCALE_DE, LOCALE_DK, LOCALE_EL, LOCALE_ES, LOCALE_ET, LOCALE_EU, LOCALE_FI, LOCALE_FR, LOCALE_GL, LOCALE_HE, LOCALE_HR, LOCALE_HU, LOCALE_ID, LOCALE_IT, LOCALE_LA, LOCALE_LT, LOCALE_LV, LOCALE_MK, LOCALE_NB, LOCALE_NL, LOCALE_PL, LOCALE_PT, LOCALE_RO, LOCALE_RU, LOCALE_SK, LOCALE_SL, LOCALE_SR, LOCALE_SV, LOCALE_TR, LOCALE_UK, LOCALE_VI }; LocaleType langToLocale( const std::string_view langName ) { static const std::unordered_map langLocale{ // Afrikaans { "af", LocaleType::LOCALE_AF }, { "afrikaans", LocaleType::LOCALE_AF }, // Arabic { "ar", LocaleType::LOCALE_AR }, { "arabic", LocaleType::LOCALE_AR }, // Belarusian { "be", LocaleType::LOCALE_BE }, { "belarusian", LocaleType::LOCALE_BE }, // Bulgarian { "bg", LocaleType::LOCALE_BG }, { "bulgarian", LocaleType::LOCALE_BG }, // Catalan { "ca", LocaleType::LOCALE_CA }, { "catalan", LocaleType::LOCALE_CA }, // Czech { "cs", LocaleType::LOCALE_CS }, { "czech", LocaleType::LOCALE_CS }, // Danish { "dk", LocaleType::LOCALE_DK }, { "danish", LocaleType::LOCALE_DK }, // German { "de", LocaleType::LOCALE_DE }, { "german", LocaleType::LOCALE_DE }, // Greek { "el", LocaleType::LOCALE_EL }, { "greek", LocaleType::LOCALE_EL }, // Spanish { "es", LocaleType::LOCALE_ES }, { "spanish", LocaleType::LOCALE_ES }, // Estonian { "et", LocaleType::LOCALE_ET }, { "estonian", LocaleType::LOCALE_ET }, // Basque { "eu", LocaleType::LOCALE_EU }, { "basque", LocaleType::LOCALE_EU }, // Finnish { "fi", LocaleType::LOCALE_FI }, { "finnish", LocaleType::LOCALE_FI }, // French { "fr", LocaleType::LOCALE_FR }, { "french", LocaleType::LOCALE_FR }, // Galician { "gl", LocaleType::LOCALE_GL }, { "galician", LocaleType::LOCALE_GL }, // Hebrew { "he", LocaleType::LOCALE_HE }, { "hebrew", LocaleType::LOCALE_HE }, // Croatian { "hr", LocaleType::LOCALE_HR }, { "croatian", LocaleType::LOCALE_HR }, // Hungarian { "hu", LocaleType::LOCALE_HU }, { "hungarian", LocaleType::LOCALE_HU }, // Indonesian { "id", LocaleType::LOCALE_ID }, { "indonesian", LocaleType::LOCALE_ID }, // Italian { "it", LocaleType::LOCALE_IT }, { "italian", LocaleType::LOCALE_IT }, // Latin { "la", LocaleType::LOCALE_LA }, { "latin", LocaleType::LOCALE_LA }, // Lithuanian { "lt", LocaleType::LOCALE_LT }, { "lithuanian", LocaleType::LOCALE_LT }, // Latvian { "lv", LocaleType::LOCALE_LV }, { "latvian", LocaleType::LOCALE_LV }, // Macedonian { "mk", LocaleType::LOCALE_MK }, { "macedonian", LocaleType::LOCALE_MK }, // Norwegian { "nb", LocaleType::LOCALE_NB }, { "norwegian", LocaleType::LOCALE_NB }, // Dutch { "nl", LocaleType::LOCALE_NL }, { "dutch", LocaleType::LOCALE_NL }, // Polish { "pl", LocaleType::LOCALE_PL }, { "polish", LocaleType::LOCALE_PL }, // Portuguese { "pt", LocaleType::LOCALE_PT }, { "portuguese", LocaleType::LOCALE_PT }, // Romanian { "ro", LocaleType::LOCALE_RO }, { "romanian", LocaleType::LOCALE_RO }, // Russian { "ru", LocaleType::LOCALE_RU }, { "russian", LocaleType::LOCALE_RU }, // Slovak { "sk", LocaleType::LOCALE_SK }, { "slovak", LocaleType::LOCALE_SK }, // Slovenian { "sl", LocaleType::LOCALE_SL }, { "slovenian", LocaleType::LOCALE_SL }, // Serbian { "sr", LocaleType::LOCALE_SR }, { "serbian", LocaleType::LOCALE_SR }, // Swedish { "sv", LocaleType::LOCALE_SV }, { "swedish", LocaleType::LOCALE_SV }, // Turkish { "tr", LocaleType::LOCALE_TR }, { "turkish", LocaleType::LOCALE_TR }, // Ukrainian { "uk", LocaleType::LOCALE_UK }, { "ukrainian", LocaleType::LOCALE_UK }, // Vietnamese { "vi", LocaleType::LOCALE_VI }, { "vietnamese", LocaleType::LOCALE_VI } }; const auto iter = langLocale.find( langName ); if ( iter == langLocale.end() ) { assert( 0 ); return LocaleType::LOCALE_EN; } return iter->second; } uint32_t crc32b( const std::string_view str ) { uint32_t crc = 0xFFFFFFFF; for ( const char ch : str ) { crc ^= static_cast( ch ); for ( int bit = 0; bit < 8; ++bit ) { const uint32_t poly = ( crc & 1 ) ? 0xEDB88320 : 0x0; crc = ( crc >> 1 ) ^ poly; } } return ~crc; } bool getCharsetFromHeader( const std::string & hdr, std::string & charset ) { constexpr std::string_view hdrEntry{ "Content-Type:" }; constexpr std::string_view charsetDirective{ "charset=" }; if ( hdr.size() <= hdrEntry.size() + charsetDirective.size() ) { return false; } if ( hdr.rfind( hdrEntry, 0 ) != 0 ) { return false; } const size_t pos = hdr.find( charsetDirective ); if ( pos == std::string::npos ) { return false; } charset = hdr.substr( pos + charsetDirective.size() ); return true; } const char * stripContext( const char * str ) { const char * pos = std::strchr( str, contextSeparator ); return pos ? ++pos : str; } class MOFile { public: MOFile() = default; const char * ngettext( const char * str, const size_t plural ) const { if ( !_isValid ) { assert( 0 ); return stripContext( str ); } const auto iter = std::as_const( _translations ).find( crc32b( str ) ); if ( iter == _translations.cend() ) { return stripContext( str ); } const auto & [dummy, pluralFormTranslations] = *iter; if ( plural >= pluralFormTranslations.size() ) { return stripContext( str ); } const std::string & translatedStr = pluralFormTranslations[plural]; if ( translatedStr.empty() ) { return stripContext( str ); } return translatedStr.c_str(); } bool load( const std::string_view langName, const std::string & fileName ) { *this = {}; StreamFile sf; if ( !sf.open( fileName, "rb" ) ) { return false; } ROStreamBuf sb = sf.getStreamBuf(); if ( sf.fail() ) { ERROR_LOG( "I/O error when reading " << fileName ) return false; } sf.close(); { const uint32_t magicNumber = sb.getLE32(); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } switch ( magicNumber ) { case 0xde120495: sb.setBigendian( true ); DEBUG_LOG( DBG_ENGINE, DBG_TRACE, "Setting big-endian mode for " << fileName ) break; case 0x950412de: sb.setBigendian( false ); DEBUG_LOG( DBG_ENGINE, DBG_TRACE, "Setting little-endian mode for " << fileName ) break; default: ERROR_LOG( "Incorrect magic number " << GetHexString( magicNumber ) << " for " << fileName ) return false; } } { const uint16_t majorVersion = sb.get16(); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } if ( majorVersion != 0 ) { ERROR_LOG( "Incorrect major version " << GetHexString( majorVersion, 4 ) << " for " << fileName ) return false; } } // Skip the minor version sb.skip( 2 ); const uint32_t stringsCount = sb.get32(); if ( stringsCount == 0 ) { ERROR_LOG( "There are no translated strings in " << fileName ) return false; } const uint32_t originalStringsTableOffset = sb.get32(); const uint32_t translationsTableOffset = sb.get32(); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } // The hash table is optional and may be missing, and even if it is present, the actual hashing algorithm depends on the // specific implementation and is not documented. See https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html // for details. for ( uint32_t i = 0; i < stringsCount; ++i ) { sb.seek( originalStringsTableOffset + i * 8 ); const uint32_t origStrLen = sb.get32(); const uint32_t origStrOff = sb.get32(); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } if ( origStrLen == 0 ) { // This is an empty original string. Skip it. continue; } sb.seek( origStrOff ); const std::string_view origStr = sb.getStringView( origStrLen ); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } sb.seek( translationsTableOffset + i * 8 ); const uint32_t tranStrLen = sb.get32(); const uint32_t tranStrOff = sb.get32(); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } if ( tranStrLen == 0 ) { // This is an empty translation. Skip it. continue; } sb.seek( tranStrOff ); const auto [tranBufPtr, tranBufLen] = sb.getRawView( tranStrLen ); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } static_assert( std::is_same_v>, unsigned char> ); if ( const auto [dummy, inserted] = _translations.try_emplace( crc32b( origStr ), StringSplit( { reinterpret_cast( tranBufPtr ), tranBufLen }, '\0' ) ); !inserted ) { ERROR_LOG( "Hash collision detected for string \"" << origStr << "\"" ) } } if ( _translations.empty() ) { ERROR_LOG( "There are no translated strings in " << fileName ) return false; } _locale = langToLocale( langName ); // The empty line in the MO file goes first (since the original lines in it are sorted in increasing lexicographical order), // and its "translation" contains service information such as the encoding used and information about the plural form. See // https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html for details. // // TODO: parse the plural form information and use it in the code. { sb.seek( translationsTableOffset ); const uint32_t len = sb.get32(); const uint32_t off = sb.get32(); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } sb.seek( off ); const std::string_view str = sb.getStringView( len ); if ( sb.fail() ) { ERROR_LOG( "I/O error when parsing " << fileName ) return false; } for ( const std::string & hdr : StringSplit( str, '\n' ) ) { if ( getCharsetFromHeader( hdr, _encoding ) ) { break; } } } _isValid = true; return true; } LocaleType getLocale() const { return _locale; } bool isEncoding( const std::string_view encoding ) const { return ( _encoding == encoding ); } bool isValid() const { return _isValid; } private: LocaleType _locale{ LocaleType::LOCALE_EN }; std::unordered_map> _translations; std::string _encoding; bool _isValid{ false }; }; MOFile * current = nullptr; std::map> cache; } std::pair Translation::setLanguage( const std::string_view langName ) { assert( !langName.empty() ); if ( const auto iter = cache.find( langName ); iter != cache.end() ) { MOFile & item = iter->second; if ( item.isValid() ) { current = &item; } return { true, item.isValid() }; } return { false, false }; } bool Translation::setLanguage( const std::string & langName, const std::string_view fileName ) { assert( !langName.empty() ); const auto [cacheIter, inserted] = cache.try_emplace( langName ); MOFile & item = cacheIter->second; if ( !inserted ) { if ( item.isValid() ) { current = &item; } return item.isValid(); } if ( fileName.empty() || !item.load( langName, std::string{ fileName } ) ) { assert( !item.isValid() ); return false; } assert( item.isValid() ); current = &item; return true; } void Translation::reset() { current = nullptr; } const char * Translation::gettext( const std::string & str ) { return current ? current->ngettext( str.c_str(), 0 ) : stripContext( str.c_str() ); } const char * Translation::gettext( const char * str ) { return current ? current->ngettext( str, 0 ) : stripContext( str ); } const char * Translation::ngettext( const char * str, const char * plural, size_t n ) { if ( current ) switch ( current->getLocale() ) { case LocaleType::LOCALE_AF: case LocaleType::LOCALE_BG: case LocaleType::LOCALE_DE: case LocaleType::LOCALE_DK: case LocaleType::LOCALE_ES: case LocaleType::LOCALE_ET: case LocaleType::LOCALE_EU: case LocaleType::LOCALE_FI: case LocaleType::LOCALE_GL: case LocaleType::LOCALE_HE: case LocaleType::LOCALE_HU: case LocaleType::LOCALE_ID: case LocaleType::LOCALE_IT: case LocaleType::LOCALE_LA: case LocaleType::LOCALE_NB: case LocaleType::LOCALE_NL: case LocaleType::LOCALE_SV: case LocaleType::LOCALE_TR: return current->ngettext( str, ( n != 1 ) ); case LocaleType::LOCALE_EL: case LocaleType::LOCALE_FR: case LocaleType::LOCALE_PT: return current->ngettext( str, ( n > 1 ) ); case LocaleType::LOCALE_AR: return current->ngettext( str, ( n == 0 ? 0 : n == 1 ? 1 : n == 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5 ) ); case LocaleType::LOCALE_RO: return current->ngettext( str, ( n == 1 ? 0 : n == 0 || ( n != 1 && n % 100 >= 1 && n % 100 <= 19 ) ? 1 : 2 ) ); case LocaleType::LOCALE_SL: return current->ngettext( str, ( n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3 ) ); case LocaleType::LOCALE_SR: return current->ngettext( str, ( n == 1 ? 3 : n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 ) ); case LocaleType::LOCALE_CS: case LocaleType::LOCALE_SK: return current->ngettext( str, ( ( n == 1 ) ? 0 : ( n >= 2 && n <= 4 ) ? 1 : 2 ) ); case LocaleType::LOCALE_HR: case LocaleType::LOCALE_LV: case LocaleType::LOCALE_RU: return current->ngettext( str, ( n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 ) ); case LocaleType::LOCALE_LT: return current->ngettext( str, ( n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 ) ); case LocaleType::LOCALE_MK: return current->ngettext( str, ( n == 1 || n % 10 == 1 ? 0 : 1 ) ); case LocaleType::LOCALE_PL: return current->ngettext( str, ( n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 10 || n % 100 >= 20 ) ? 1 : 2 ) ); case LocaleType::LOCALE_BE: case LocaleType::LOCALE_UK: return current->ngettext( str, ( n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && ( n % 100 < 12 || n % 100 > 14 ) ? 1 : 2 ) ); default: break; } return stripContext( n == 1 ? str : plural ); } std::string Translation::StringLower( std::string str ) { if ( current ) { // With German, lowercasing strings does more harm than good if ( current->getLocale() == LocaleType::LOCALE_DE ) { return str; } // For CP1250/1251 codepages a custom lowercase LUT is implemented if ( current->isEncoding( "CP1250" ) || current->isEncoding( "CP1251" ) ) { std::transform( str.begin(), str.end(), str.begin(), []( const unsigned char c ) { return tolowerLUT[c]; } ); return str; } } return ::StringLower( str ); } void StringReplaceWithLowercase( std::string & workString, const char * pattern, const std::string & patternReplacement ) { if ( pattern == nullptr ) { return; } for ( size_t position = workString.find( pattern ); position != std::string::npos; position = workString.find( pattern ) ) { // To determine if the end of a sentence was before this word we parse the character before it // for the presence of full stop, question mark, or exclamation mark, skipping whitespace characters. const char prevWordEnd = [&workString, position]() { assert( position < workString.size() ); const auto iter = std::find_if_not( workString.rbegin() + static_cast( workString.size() - position ), workString.rend(), []( const unsigned char c ) { return std::isspace( c ); } ); if ( iter != workString.rend() ) { return *iter; } // Before 'position' there is nothing, or there are only spaces. return '\0'; }(); // Also if the insert 'position' equals zero, then it is the first word in a sentence. if ( position == 0 || prevWordEnd == '.' || prevWordEnd == '?' || prevWordEnd == '!' ) { // Also, 'patternReplacement' can consist of two words (for example, "Power Liches") and if // it is placed as the first word in sentence, then we have to lowercase only the second word. // To detect this, we look for a space mark in 'patternReplacement'. const size_t spacePosition = patternReplacement.find( ' ' ); // The first (and possibly only) word of 'patternReplacement' replaces 'pattern' in 'workString'. workString.replace( position, std::strlen( pattern ), patternReplacement.substr( 0, spacePosition ) ); // Check if a space mark was found to insert the rest part of 'patternReplacement' with lowercase applied. if ( spacePosition != std::string::npos ) { workString.insert( position + spacePosition, Translation::StringLower( patternReplacement.substr( spacePosition ) ) ); } } else { // For all other cases lowercase the 'patternReplacement' and replace the 'pattern' with it in 'workString'. workString.replace( position, std::strlen( pattern ), Translation::StringLower( patternReplacement ) ); } } } fheroes2-1.1.6+dfsg/src/engine/translations.h000066400000000000000000000072101476115357100211130ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include namespace Translation { // Sets the language with the given name as the current language if the translation for this language is // already cached and valid, otherwise does nothing. Returns a pair of two flags, the first of which is // set to true if the translation for the given language is already present in the cache (even if this // translation is invalid), and the second is set to true if the current language has been successfully // set. std::pair setLanguage( const std::string_view langName ); // Sets the language with the given name as the current language if the translation for this language is // already cached and valid. If this translation is not yet cached, then tries to load it from the given // file. If the load fails, then adds this language to the cache as invalid and does nothing else. Returns // true if the current language has been successfully set, otherwise returns false. bool setLanguage( const std::string & langName, const std::string_view fileName ); // Resets the current language to the default language (English). void reset(); const char * gettext( const char * str ); const char * gettext( const std::string & str ); const char * ngettext( const char * str, const char * plural, size_t num ); // Converts the given string to lowercase in a locale aware way std::string StringLower( std::string str ); } #define _( str ) Translation::gettext( str ) #define _n( str, plural, num ) Translation::ngettext( str, plural, num ) constexpr const char * gettext_noop( const char * s ) { return s; } // Replaces the pattern in workString with patternReplacement. The patternReplacement is converted to lowercase in a locale // aware way, except for the first word in a sentence. void StringReplaceWithLowercase( std::string & workString, const char * pattern, const std::string & patternReplacement ); fheroes2-1.1.6+dfsg/src/engine/zzlib.cpp000066400000000000000000000152501476115357100200620ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "zzlib.h" #include #include #include #include #include "logging.h" #include "serialize.h" namespace { constexpr uint16_t FORMAT_VERSION_0 = 0; } std::vector Compression::unzipData( const uint8_t * src, const size_t srcSize, size_t realSize /* = 0 */ ) { if ( src == nullptr || srcSize == 0 ) { return {}; } const uLong srcSizeULong = static_cast( srcSize ); if ( srcSizeULong != srcSize ) { ERROR_LOG( "The size of the compressed data is too large" ) return {}; } std::vector res( realSize ); if ( realSize == 0 ) { constexpr size_t sizeMultiplier = 7; if ( srcSize > res.max_size() / sizeMultiplier ) { // If the multiplicated size is too large, let's start with the original size and see how it goes realSize = srcSize; } else { realSize = srcSize * sizeMultiplier; } res.resize( realSize ); } uLong dstSizeULong = static_cast( res.size() ); if ( dstSizeULong != res.size() ) { ERROR_LOG( "The size of the decompressed data is too large" ) return {}; } int ret = Z_BUF_ERROR; while ( Z_BUF_ERROR == ( ret = uncompress( res.data(), &dstSizeULong, src, srcSizeULong ) ) ) { constexpr size_t sizeMultiplier = 2; // Avoid infinite loop due to unsigned overflow on multiplication if ( res.size() > res.max_size() / sizeMultiplier ) { ERROR_LOG( "The size of the decompressed data is too large" ) return {}; } res.resize( res.size() * sizeMultiplier ); dstSizeULong = static_cast( res.size() ); if ( dstSizeULong != res.size() ) { ERROR_LOG( "The size of the decompressed data is too large" ) return {}; } } if ( ret != Z_OK ) { ERROR_LOG( "zlib error: " << ret ) return {}; } res.resize( dstSizeULong ); return res; } std::vector Compression::zipData( const uint8_t * src, const size_t srcSize ) { if ( src == nullptr || srcSize == 0 ) { return {}; } const uLong srcSizeULong = static_cast( srcSize ); if ( srcSizeULong != srcSize ) { ERROR_LOG( "The size of the source data is too large" ) return {}; } std::vector res( compressBound( srcSizeULong ) ); uLong dstSizeULong = static_cast( res.size() ); if ( dstSizeULong != res.size() ) { ERROR_LOG( "The size of the compressed data is too large" ) return {}; } const int ret = compress( res.data(), &dstSizeULong, src, srcSizeULong ); if ( ret != Z_OK ) { ERROR_LOG( "zlib error: " << ret ) return {}; } res.resize( dstSizeULong ); return res; } bool Compression::unzipStream( IStreamBase & inputStream, OStreamBase & outputStream ) { const uint32_t rawSize = inputStream.get32(); const uint32_t zipSize = inputStream.get32(); if ( zipSize == 0 ) { return false; } const uint16_t version = inputStream.get16(); if ( version != FORMAT_VERSION_0 ) { return false; } inputStream.skip( 2 ); // Unused bytes const std::vector zip = inputStream.getRaw( zipSize ); const std::vector raw = unzipData( zip.data(), zip.size(), rawSize ); if ( raw.size() != rawSize ) { return false; } outputStream.putRaw( raw.data(), raw.size() ); return !outputStream.fail(); } bool Compression::zipStreamBuf( const IStreamBuf & inputStream, OStreamBase & outputStream ) { const std::vector zip = zipData( inputStream.data(), inputStream.size() ); if ( zip.empty() ) { return false; } outputStream.put32( static_cast( inputStream.size() ) ); outputStream.put32( static_cast( zip.size() ) ); outputStream.put16( FORMAT_VERSION_0 ); outputStream.put16( 0 ); // Unused bytes outputStream.putRaw( zip.data(), zip.size() ); return !outputStream.fail(); } fheroes2::Image Compression::CreateImageFromZlib( int32_t width, int32_t height, const uint8_t * imageData, size_t imageSize, bool doubleLayer ) { if ( imageData == nullptr || imageSize == 0 || width <= 0 || height <= 0 ) { return {}; } const std::vector & uncompressedData = unzipData( imageData, imageSize ); if ( doubleLayer && ( uncompressedData.size() & 1 ) == 1 ) { return {}; } const size_t uncompressedSize = doubleLayer ? uncompressedData.size() / 2 : uncompressedData.size(); if ( static_cast( width ) * height != uncompressedSize ) { return {}; } fheroes2::Image out; if ( !doubleLayer ) { out._disableTransformLayer(); } out.resize( width, height ); std::memcpy( out.image(), uncompressedData.data(), uncompressedSize ); if ( doubleLayer ) { std::memcpy( out.transform(), uncompressedData.data() + uncompressedSize, uncompressedSize ); } return out; } fheroes2-1.1.6+dfsg/src/engine/zzlib.h000066400000000000000000000062661476115357100175360ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "image.h" class IStreamBase; class OStreamBase; class IStreamBuf; namespace Compression { // Unzips the input data and returns the uncompressed data or an empty vector in case of an error. // The 'realSize' parameter represents the planned size of the decompressed data and is optional // (it is only used to speed up the decompression process). If this parameter is omitted or set to // zero, the size of the decompressed data will be determined automatically. std::vector unzipData( const uint8_t * src, const size_t srcSize, size_t realSize = 0 ); // Zips the input data and returns the compressed data or an empty vector in case of an error. std::vector zipData( const uint8_t * src, const size_t srcSize ); // Reads & unzips the zipped chunk from the given input stream and writes it to the given output // stream. Returns true on success or false on error. bool unzipStream( IStreamBase & inputStream, OStreamBase & outputStream ); // Zips the contents of the buffer from the current read position to the end of the buffer and writes // it to the given output stream. The current read position of the buffer does not change. Returns // true on success and false on error. bool zipStreamBuf( const IStreamBuf & inputStream, OStreamBase & outputStream ); fheroes2::Image CreateImageFromZlib( int32_t width, int32_t height, const uint8_t * imageData, size_t imageSize, bool doubleLayer ); } fheroes2-1.1.6+dfsg/src/fheroes2/000077500000000000000000000000001476115357100164715ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/CMakeLists.txt000066400000000000000000000101221476115357100212250ustar00rootroot00000000000000########################################################################### # fheroes2: https://github.com/ihhub/fheroes2 # # Copyright (C) 2022 - 2025 # # # # This program is free software; you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation; either version 2 of the License, or # # (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the # # Free Software Foundation, Inc., # # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ########################################################################### file(GLOB_RECURSE FHEROES2_SOURCES CONFIGURE_DEPENDS *.cpp) add_compile_options("$<$:${GNU_CC_WARN_OPTS}>") add_compile_options("$<$:${GNU_CXX_WARN_OPTS}>") add_compile_options("$<$,$>:${MSVC_CC_WARN_OPTS}>") if(MACOS_APP_BUNDLE) set(FHEROES2_ICON ${CMAKE_CURRENT_SOURCE_DIR}/../resources/fheroes2.icns) set_source_files_properties(${FHEROES2_ICON} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) add_executable(fheroes2 MACOSX_BUNDLE ${FHEROES2_ICON} ${FHEROES2_SOURCES} ${TRANSLATION_DATA}) target_compile_definitions( fheroes2 PRIVATE $<$:WITH_DEBUG> $<$:MACOS_APP_BUNDLE> ) target_link_libraries(fheroes2 "-framework CoreFoundation") set_target_properties(fheroes2 PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME ${CMAKE_PROJECT_NAME}) set_target_properties(fheroes2 PROPERTIES MACOSX_BUNDLE_BUNDLE_VERSION ${CMAKE_PROJECT_VERSION}) set_target_properties(fheroes2 PROPERTIES MACOSX_BUNDLE_EXECUTABLE_NAME fheroes2) set_target_properties(fheroes2 PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER org.fheroes2.${CMAKE_PROJECT_NAME}) set_target_properties(fheroes2 PROPERTIES MACOSX_BUNDLE_ICON_FILE fheroes2.icns) set_target_properties(fheroes2 PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/../resources/Info.plist.in) set_target_properties(fheroes2 PROPERTIES MACOSX_BUNDLE_SHORT_VERSION_STRING ${CMAKE_PROJECT_VERSION}) else(MACOS_APP_BUNDLE) cmake_path( ABSOLUTE_PATH FHEROES2_DATA BASE_DIRECTORY ${CMAKE_INSTALL_PREFIX} NORMALIZE OUTPUT_VARIABLE FHEROES2_DATA_ABSOLUTE ) add_executable( fheroes2 ${FHEROES2_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../resources/fheroes2.manifest ${CMAKE_CURRENT_SOURCE_DIR}/../resources/fheroes2.rc ) target_compile_definitions( fheroes2 PRIVATE # MSVC: suppress deprecation warnings $<$,$>:_CRT_SECURE_NO_WARNINGS> $<$:WITH_DEBUG> FHEROES2_DATA=${FHEROES2_DATA_ABSOLUTE} ) # Copy executable to root of the project. add_custom_command( TARGET fheroes2 POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${PROJECT_SOURCE_DIR}/$ ) install(TARGETS fheroes2 DESTINATION ${CMAKE_INSTALL_BINDIR}) endif(MACOS_APP_BUNDLE) target_include_directories( fheroes2 PRIVATE agg ai army audio battle campaign castle dialog editor game gui h2d heroes image kingdom maps monster resource spell system world ) target_link_libraries( fheroes2 engine ${USE_SDL_VERSION}::${USE_SDL_VERSION}main ) fheroes2-1.1.6+dfsg/src/fheroes2/agg/000077500000000000000000000000001476115357100172275ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/agg/agg.cpp000066400000000000000000000103321476115357100204700ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include "agg.h" #include "agg_file.h" #include "dir.h" #include "settings.h" #include "tools.h" namespace { fheroes2::AGGFile heroes2_agg; fheroes2::AGGFile heroes2x_agg; } std::vector AGG::getDataFromAggFile( const std::string & key, const bool ignoreExpansion ) { if ( !ignoreExpansion && heroes2x_agg.isGood() ) { // Make sure that the below container is not const and not a reference // so returning it from the function will invoke a move constructor instead of copy constructor. std::vector buf = heroes2x_agg.read( key ); if ( !buf.empty() ) return buf; } return heroes2_agg.read( key ); } AGG::AGGInitializer::AGGInitializer() { if ( init() ) { return; } throw std::logic_error( "No AGG data files found." ); } bool AGG::AGGInitializer::init() { const ListFiles aggFileNames = Settings::FindFiles( "data", ".agg", false ); if ( aggFileNames.empty() ) { return false; } const std::string heroes2AggFileName( "heroes2.agg" ); std::string heroes2AggFilePath; std::string aggLowerCaseFilePath; for ( const std::string & path : aggFileNames ) { if ( path.size() < heroes2AggFileName.size() ) { // Obviously this is not a correct file. continue; } std::string tempPath = StringLower( path ); if ( tempPath.compare( tempPath.size() - heroes2AggFileName.size(), heroes2AggFileName.size(), heroes2AggFileName ) == 0 ) { heroes2AggFilePath = path; aggLowerCaseFilePath = std::move( tempPath ); break; } } if ( heroes2AggFilePath.empty() ) { // The main game resource file was not found. return false; } if ( !heroes2_agg.open( heroes2AggFilePath ) ) { return false; } _originalAGGFilePath = std::move( heroes2AggFilePath ); // Find "heroes2x.agg" file. std::string heroes2XAggFilePath; fheroes2::replaceStringEnding( aggLowerCaseFilePath, ".agg", "x.agg" ); for ( const std::string & path : aggFileNames ) { const std::string tempPath = StringLower( path ); if ( tempPath == aggLowerCaseFilePath ) { heroes2XAggFilePath = path; break; } } if ( !heroes2XAggFilePath.empty() && heroes2x_agg.open( heroes2XAggFilePath ) ) { _expansionAGGFilePath = std::move( heroes2XAggFilePath ); } Settings::Get().EnablePriceOfLoyaltySupport( heroes2x_agg.isGood() ); return true; } fheroes2-1.1.6+dfsg/src/fheroes2/agg/agg.h000066400000000000000000000046761476115357100201530ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include namespace AGG { class AGGInitializer { public: AGGInitializer(); AGGInitializer( const AGGInitializer & ) = delete; AGGInitializer & operator=( const AGGInitializer & ) = delete; ~AGGInitializer() = default; const std::string & getOriginalAGGFilePath() const { return _originalAGGFilePath; } const std::string & getExpansionAGGFilePath() const { return _expansionAGGFilePath; } private: bool init(); std::string _originalAGGFilePath; std::string _expansionAGGFilePath; }; std::vector getDataFromAggFile( const std::string & key, const bool ignoreExpansion ); } fheroes2-1.1.6+dfsg/src/fheroes2/agg/agg_image.cpp000066400000000000000000007750411476115357100216510ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "agg_image.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "agg.h" #include "agg_file.h" #include "battle_cell.h" #include "exception.h" #include "game_language.h" #include "h2d.h" #include "icn.h" #include "image.h" #include "image_tool.h" #include "math_base.h" #include "pal.h" #include "rand.h" #include "screen.h" #include "serialize.h" #include "til.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_font.h" #include "ui_language.h" #include "ui_text.h" #include "ui_tool.h" namespace { const std::array tilFileName = { "UNKNOWN", "CLOF32.TIL", "GROUND32.TIL", "STON.TIL" }; std::vector> _icnVsSprite( ICN::LASTICN ); std::array>, TIL::LASTTIL> _tilVsImage; const fheroes2::Sprite errorImage; const uint32_t headerSize = 6; std::map> _icnVsScaledSprite; // Some resources are language dependent. These are mostly buttons with a text of them. // Once a user changes a language we have to update resources. To do this we need to clear the existing images. const std::set languageDependentIcnId{ ICN::BUTTON_WELL_MAX, ICN::BUTTON_NEW_GAME_GOOD, ICN::BUTTON_NEW_GAME_EVIL, ICN::BUTTON_SAVE_GAME_GOOD, ICN::BUTTON_SAVE_GAME_EVIL, ICN::BUTTON_LOAD_GAME_GOOD, ICN::BUTTON_LOAD_GAME_EVIL, ICN::BUTTON_INFO_GOOD, ICN::BUTTON_INFO_EVIL, ICN::BUTTON_QUIT_GOOD, ICN::BUTTON_QUIT_EVIL, ICN::BUTTON_NEW_MAP_EVIL, ICN::BUTTON_NEW_MAP_GOOD, ICN::BUTTON_SAVE_MAP_EVIL, ICN::BUTTON_SAVE_MAP_GOOD, ICN::BUTTON_LOAD_MAP_EVIL, ICN::BUTTON_LOAD_MAP_GOOD, ICN::BUTTON_SMALL_CANCEL_GOOD, ICN::BUTTON_SMALL_CANCEL_EVIL, ICN::BUTTON_SMALL_OKAY_GOOD, ICN::BUTTON_SMALL_OKAY_EVIL, ICN::BUTTON_SMALL_ACCEPT_GOOD, ICN::BUTTON_SMALL_ACCEPT_EVIL, ICN::BUTTON_SMALL_DECLINE_GOOD, ICN::BUTTON_SMALL_DECLINE_EVIL, ICN::BUTTON_SMALL_LEARN_GOOD, ICN::BUTTON_SMALL_LEARN_EVIL, ICN::BUTTON_SMALL_TRADE_GOOD, ICN::BUTTON_SMALL_TRADE_EVIL, ICN::BUTTON_SMALL_YES_GOOD, ICN::BUTTON_SMALL_YES_EVIL, ICN::BUTTON_SMALL_NO_GOOD, ICN::BUTTON_SMALL_NO_EVIL, ICN::BUTTON_SMALL_EXIT_GOOD, ICN::BUTTON_SMALL_EXIT_EVIL, ICN::BUTTON_EXIT_HEROES_MEETING, ICN::BUTTON_EXIT_TOWN, ICN::BUTTON_EXIT_PUZZLE_DIM_DOOR_GOOD, ICN::BUTTON_EXIT_PUZZLE_DIM_DOOR_EVIL, ICN::BUTTON_SMALL_DISMISS_GOOD, ICN::BUTTON_SMALL_DISMISS_EVIL, ICN::BUTTON_SMALL_UPGRADE_GOOD, ICN::BUTTON_SMALL_UPGRADE_EVIL, ICN::BUTTON_SMALL_RESTART_GOOD, ICN::BUTTON_SMALL_RESTART_EVIL, ICN::BUTTON_KINGDOM_EXIT, ICN::BUTTON_KINGDOM_HEROES, ICN::BUTTON_KINGDOM_TOWNS, ICN::BUTTON_MAPSIZE_SMALL, ICN::BUTTON_MAPSIZE_MEDIUM, ICN::BUTTON_MAPSIZE_LARGE, ICN::BUTTON_MAPSIZE_XLARGE, ICN::BUTTON_MAPSIZE_ALL, ICN::BUTTON_MAP_SELECT_GOOD, ICN::BUTTON_MAP_SELECT_EVIL, ICN::BUTTON_STANDARD_GAME, ICN::BUTTON_CAMPAIGN_GAME, ICN::BUTTON_MULTIPLAYER_GAME, ICN::BUTTON_LARGE_CANCEL, ICN::BUTTON_LARGE_CONFIG, ICN::BUTTON_ORIGINAL_CAMPAIGN, ICN::BUTTON_EXPANSION_CAMPAIGN, ICN::BUTTON_HOT_SEAT, ICN::BUTTON_2_PLAYERS, ICN::BUTTON_3_PLAYERS, ICN::BUTTON_4_PLAYERS, ICN::BUTTON_5_PLAYERS, ICN::BUTTON_6_PLAYERS, ICN::BTNBATTLEONLY, ICN::BUTTON_GIFT_GOOD, ICN::BUTTON_GIFT_EVIL, ICN::UNIFORM_EVIL_MAX_BUTTON, ICN::UNIFORM_EVIL_MIN_BUTTON, ICN::UNIFORM_GOOD_MAX_BUTTON, ICN::UNIFORM_GOOD_MIN_BUTTON, ICN::UNIFORM_GOOD_OKAY_BUTTON, ICN::UNIFORM_EVIL_OKAY_BUTTON, ICN::UNIFORM_GOOD_CANCEL_BUTTON, ICN::UNIFORM_EVIL_CANCEL_BUTTON, ICN::UNIFORM_GOOD_EXIT_BUTTON, ICN::UNIFORM_EVIL_EXIT_BUTTON, ICN::BUTTON_SMALL_MIN_GOOD, ICN::BUTTON_SMALL_MIN_EVIL, ICN::BUTTON_SMALL_MAX_GOOD, ICN::BUTTON_SMALL_MAX_EVIL, ICN::BUTTON_EXIT_GOOD, ICN::BUTTON_RESET_GOOD, ICN::BUTTON_START_GOOD, ICN::BUTTON_CASTLE_GOOD, ICN::BUTTON_CASTLE_EVIL, ICN::BUTTON_TOWN_GOOD, ICN::BUTTON_TOWN_EVIL, ICN::BUTTON_RESTRICT_GOOD, ICN::BUTTON_RESTRICT_EVIL, ICN::BUTTON_GUILDWELL_EXIT, ICN::GOOD_CAMPAIGN_BUTTONS, ICN::EVIL_CAMPAIGN_BUTTONS, ICN::POL_CAMPAIGN_BUTTONS, ICN::BUTTON_VIEWWORLD_EXIT_GOOD, ICN::BUTTON_VIEWWORLD_EXIT_EVIL, ICN::BUTTON_VERTICAL_DISMISS, ICN::BUTTON_VERTICAL_EXIT, ICN::BUTTON_VERTICAL_PATROL, ICN::BUTTON_HSCORES_VERTICAL_CAMPAIGN, ICN::BUTTON_HSCORES_VERTICAL_EXIT, ICN::BUTTON_HSCORES_VERTICAL_STANDARD, ICN::DISMISS_HERO_DISABLED_BUTTON, ICN::BUTTON_RUMORS_GOOD, ICN::BUTTON_RUMORS_EVIL, ICN::BUTTON_EVENTS_GOOD, ICN::BUTTON_EVENTS_EVIL, ICN::BUTTON_LANGUAGE_GOOD, ICN::BUTTON_LANGUAGE_EVIL, ICN::BUTTON_AUTO_COMBAT_GOOD, ICN::BUTTON_AUTO_COMBAT_EVIL, ICN::BUTTON_QUICK_COMBAT_GOOD, ICN::BUTTON_QUICK_COMBAT_EVIL }; bool isLanguageDependentIcnId( const int id ) { return languageDependentIcnId.count( id ) > 0; } bool useOriginalResources() { const fheroes2::SupportedLanguage currentLanguage = fheroes2::getCurrentLanguage(); const fheroes2::SupportedLanguage resourceLanguage = fheroes2::getResourceLanguage(); return ( currentLanguage == fheroes2::SupportedLanguage::English && resourceLanguage == fheroes2::SupportedLanguage::English ) || ( currentLanguage == fheroes2::SupportedLanguage::Czech && resourceLanguage == fheroes2::SupportedLanguage::Czech ) || ( currentLanguage == fheroes2::SupportedLanguage::Polish && resourceLanguage == fheroes2::SupportedLanguage::Polish ) || ( currentLanguage == fheroes2::SupportedLanguage::French && resourceLanguage == fheroes2::SupportedLanguage::French ) || ( currentLanguage == fheroes2::SupportedLanguage::German && resourceLanguage == fheroes2::SupportedLanguage::German ) || ( currentLanguage == fheroes2::SupportedLanguage::Russian && resourceLanguage == fheroes2::SupportedLanguage::Russian ); } bool IsValidICNId( int id ) { return id > ICN::UNKNOWN && static_cast( id ) < _icnVsSprite.size(); } bool IsValidTILId( int id ) { return id >= 0 && static_cast( id ) < _tilVsImage.size(); } fheroes2::Image createDigit( const int32_t width, const int32_t height, const std::vector & points, const uint8_t pixelColor ) { fheroes2::Image digit( width, height ); digit.reset(); fheroes2::SetPixel( digit, points, pixelColor ); fheroes2::Blit( fheroes2::CreateContour( digit, 35 ), digit ); return digit; } fheroes2::Image addDigit( const fheroes2::Sprite & original, const fheroes2::Image & digit, const fheroes2::Point & offset ) { fheroes2::Image combined( original.width() + digit.width() + offset.x, original.height() + ( offset.y < 0 ? 0 : offset.y ) ); combined.reset(); fheroes2::Copy( original, 0, 0, combined, 0, 0, original.width(), original.height() ); fheroes2::Blit( digit, 0, 0, combined, original.width() + offset.x, combined.height() - digit.height() + ( offset.y >= 0 ? 0 : offset.y ), digit.width(), digit.height() ); return combined; } void populateCursorIcons( std::vector & output, const fheroes2::Sprite & origin, const std::vector & digits, const fheroes2::Point & offset ) { output.emplace_back( origin ); for ( const fheroes2::Image & digit : digits ) { output.emplace_back( addDigit( origin, digit, offset ) ); output.back().setPosition( output.back().width() - origin.width(), output.back().height() - origin.height() ); } } void fillRandomPixelsFromImage( const fheroes2::Image & original, const fheroes2::Rect & originalRoi, fheroes2::Image & output, const fheroes2::Rect & outputRoi, std::mt19937 & seededGen ) { for ( int x = outputRoi.x; x < outputRoi.x + outputRoi.width; ++x ) { for ( int y = outputRoi.y; y < outputRoi.y + outputRoi.height; ++y ) { const fheroes2::Point pixelLocation{ static_cast( Rand::GetWithGen( originalRoi.x, originalRoi.x + originalRoi.width - 1, seededGen ) ), static_cast( Rand::GetWithGen( originalRoi.y, originalRoi.y + originalRoi.height - 1, seededGen ) ) }; fheroes2::Copy( original, pixelLocation.x, pixelLocation.y, output, x, y, 1, 1 ); } } } // This class serves the purpose of preserving the original alphabet which is loaded from AGG files for cases when we generate new language alphabet. class OriginalAlphabetPreserver { public: void preserve() { if ( _isPreserved ) { return; } fheroes2::AGG::GetICN( ICN::FONT, 0 ); fheroes2::AGG::GetICN( ICN::SMALFONT, 0 ); fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_RELEASED, 0 ); fheroes2::AGG::GetICN( ICN::BUTTON_GOOD_FONT_PRESSED, 0 ); fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_RELEASED, 0 ); fheroes2::AGG::GetICN( ICN::BUTTON_EVIL_FONT_PRESSED, 0 ); _normalFont = _icnVsSprite[ICN::FONT]; _smallFont = _icnVsSprite[ICN::SMALFONT]; _buttonGoodReleasedFont = _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED]; _buttonGoodPressedFont = _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED]; _buttonEvilReleasedFont = _icnVsSprite[ICN::BUTTON_EVIL_FONT_RELEASED]; _buttonEvilPressedFont = _icnVsSprite[ICN::BUTTON_EVIL_FONT_PRESSED]; _isPreserved = true; } void restore() const { if ( !_isPreserved ) { return; } // Restore the original font. _icnVsSprite[ICN::FONT] = _normalFont; _icnVsSprite[ICN::SMALFONT] = _smallFont; _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED] = _buttonGoodReleasedFont; _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED] = _buttonGoodPressedFont; _icnVsSprite[ICN::BUTTON_EVIL_FONT_RELEASED] = _buttonEvilReleasedFont; _icnVsSprite[ICN::BUTTON_EVIL_FONT_PRESSED] = _buttonEvilPressedFont; // Clear modified fonts. _icnVsSprite[ICN::YELLOW_FONT].clear(); _icnVsSprite[ICN::YELLOW_SMALLFONT].clear(); _icnVsSprite[ICN::GRAY_FONT].clear(); _icnVsSprite[ICN::GRAY_SMALL_FONT].clear(); _icnVsSprite[ICN::WHITE_LARGE_FONT].clear(); } bool isPreserved() const { return _isPreserved; } private: bool _isPreserved = false; std::vector _normalFont; std::vector _smallFont; std::vector _buttonGoodReleasedFont; std::vector _buttonGoodPressedFont; std::vector _buttonEvilReleasedFont; std::vector _buttonEvilPressedFont; }; OriginalAlphabetPreserver alphabetPreserver; // This class is used for situations when we need to remove letter-specific offsets, like when we display single letters in a row, // and then restore these offsets within the scope of the code class ButtonFontOffsetRestorer final { public: ButtonFontOffsetRestorer( std::vector & font, const int32_t offsetX ) : _font( font ) { _originalXOffsets.reserve( _font.size() ); for ( fheroes2::Sprite & characterSprite : _font ) { _originalXOffsets.emplace_back( characterSprite.x() ); characterSprite.setPosition( offsetX, characterSprite.y() ); } } ButtonFontOffsetRestorer( const ButtonFontOffsetRestorer & ) = delete; ~ButtonFontOffsetRestorer() { if ( _originalXOffsets.size() != _font.size() ) { // If this assertion blows up then something is wrong with the fonts as they must have the same size. assert( 0 ); return; } for ( size_t i = 0; i < _font.size(); ++i ) { _font[i].setPosition( _originalXOffsets[i], _font[i].y() ); } } ButtonFontOffsetRestorer & operator=( const ButtonFontOffsetRestorer & ) = delete; private: std::vector & _font; std::vector _originalXOffsets; }; void invertTransparency( fheroes2::Image & image ) { if ( image.singleLayer() ) { assert( 0 ); return; } uint8_t * transform = image.transform(); const uint8_t * transformEnd = transform + image.width() * image.height(); for ( ; transform != transformEnd; ++transform ) { if ( *transform == 0 ) { *transform = 1; } else if ( *transform == 1 ) { *transform = 0; } // Other transform values are not relevant for transparency checks. } } uint8_t getButtonFillingColor( const bool isReleasedState, const bool isGoodInterface = true ) { if ( isGoodInterface ) { return isReleasedState ? fheroes2::GetColorId( 216, 184, 152 ) : fheroes2::GetColorId( 184, 136, 96 ); } return isReleasedState ? fheroes2::GetColorId( 180, 180, 180 ) : fheroes2::GetColorId( 144, 144, 144 ); } void createNormalButton( fheroes2::Sprite & released, fheroes2::Sprite & pressed, const char * untranslatedText, const bool isEvilInterface, const int backgroundIcnId, fheroes2::Size buttonSize ) { // TODO: do not do translations for button generation. We shouldn't assume that we receive a non-translated string. const fheroes2::FontColor buttonFontColor = isEvilInterface ? fheroes2::FontColor::GRAY : fheroes2::FontColor::WHITE; const char * text = fheroes2::getSupportedText( untranslatedText, fheroes2::FontType{ fheroes2::FontSize::BUTTON_RELEASED, buttonFontColor } ); fheroes2::makeButtonSprites( released, pressed, text, buttonSize, isEvilInterface, backgroundIcnId ); } void createCampaignButtonSet( const int campaignSetIcnId, const std::array & texts ) { int emptyButtonIcnID = 0; int buttonBackgroundICN = ICN::UNKNOWN; switch ( campaignSetIcnId ) { case ICN::GOOD_CAMPAIGN_BUTTONS: emptyButtonIcnID = ICN::EMPTY_GOOD_BUTTON; buttonBackgroundICN = ICN::STONEBAK; break; case ICN::EVIL_CAMPAIGN_BUTTONS: emptyButtonIcnID = ICN::EMPTY_EVIL_BUTTON; buttonBackgroundICN = ICN::STONEBAK_EVIL; break; case ICN::POL_CAMPAIGN_BUTTONS: emptyButtonIcnID = ICN::EMPTY_POL_BUTTON; buttonBackgroundICN = ICN::STONEBAK_SMALL_POL; break; default: // Was a new set of buttons added? assert( 0 ); break; } for ( size_t i = 0; i < texts.size(); ++i ) { const size_t icnIndex = 2 * i; fheroes2::getTextAdaptedSprite( _icnVsSprite[campaignSetIcnId][icnIndex], _icnVsSprite[campaignSetIcnId][icnIndex + 1], texts[i], emptyButtonIcnID, buttonBackgroundICN ); } } void convertToEvilInterface( fheroes2::Sprite & image, const fheroes2::Rect & roi ) { fheroes2::ApplyPalette( image, roi.x, roi.y, image, roi.x, roi.y, roi.width, roi.height, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ) ); } // Sets the upper left (offset 3 pixels), upper right (offset 2 pixels), lower right (offset 3 pixels) corners transparent. void setButtonCornersTransparent( fheroes2::Sprite & buttonSprite ) { const ptrdiff_t imageWidth = buttonSprite.width(); const ptrdiff_t imageHeight = buttonSprite.height(); assert( imageWidth > 3 && imageHeight > 3 ); uint8_t * imageTransform = buttonSprite.transform(); const uint8_t transparencyValue = 1; std::fill( imageTransform, imageTransform + 4, transparencyValue ); std::fill( imageTransform + imageWidth - 2, imageTransform + imageWidth + 3, transparencyValue ); std::fill( imageTransform + 2 * imageWidth - 1, imageTransform + 2 * imageWidth + 2, transparencyValue ); *( imageTransform + 3 * imageWidth ) = transparencyValue; *( imageTransform + ( imageHeight - 3 ) * imageWidth - 1 ) = transparencyValue; std::fill( imageTransform + ( imageHeight - 2 ) * imageWidth - 2, imageTransform + ( imageHeight - 2 ) * imageWidth, transparencyValue ); std::fill( imageTransform + ( imageHeight - 1 ) * imageWidth - 3, imageTransform + ( imageHeight - 1 ) * imageWidth, transparencyValue ); std::fill( imageTransform + imageHeight * imageWidth - 4, imageTransform + imageHeight * imageWidth, transparencyValue ); } // Remove all shadows from the image and make them fully transparent. void setTransformLayerTransparent( fheroes2::Image & image ) { assert( !image.empty() && !image.singleLayer() ); uint8_t * transform = image.transform(); const uint8_t * transformEnd = transform + static_cast( image.width() ) * image.height(); for ( ; transform != transformEnd; ++transform ) { if ( *transform > 1 ) { *transform = 1U; } } } // Draw the given image in the center of the button images (released and pressed states) and add extra shading and brightening at the edges of the image. void drawImageOnButton( const fheroes2::Image & image, const int32_t maxImageWidth, const int32_t maxImageHeight, fheroes2::Image & releasedSprite, fheroes2::Image & pressedSprite ) { assert( !image.empty() && !releasedSprite.empty() && !pressedSprite.empty() ); fheroes2::Image newImage( std::min( maxImageWidth, image.width() + 4 ), std::min( maxImageHeight, image.height() + 4 ) ); newImage.reset(); fheroes2::Blit( image, 0, 0, newImage, 2, 2, 35, 25 ); // Remove shadow from the image. setTransformLayerTransparent( newImage ); // Add extra shading and brightening at the edges of the image. fheroes2::updateShadow( newImage, { 1, -1 }, 2U, false ); fheroes2::updateShadow( newImage, { 2, -2 }, 5U, false ); fheroes2::updateShadow( newImage, { -1, 1 }, 6U, false ); fheroes2::updateShadow( newImage, { -2, 2 }, 9U, false ); // Draw the image on the button. const int32_t offsetX = ( pressedSprite.width() - newImage.width() ) / 2; const int32_t offsetY = ( pressedSprite.height() - newImage.height() ) / 2; fheroes2::Blit( newImage, pressedSprite, offsetX + 1, offsetY ); fheroes2::ReplaceTransformIdByColorId( newImage, 6U, 10U ); fheroes2::Blit( newImage, releasedSprite, offsetX + 2, offsetY - 1 ); } void loadICN( const int id ); void replacePOLAssetWithSW( const int id, const int assetIndex ) { const std::vector & body = ::AGG::getDataFromAggFile( ICN::getIcnFileName( id ), true ); ROStreamBuf imageStream( body ); imageStream.seek( headerSize + assetIndex * 13 ); fheroes2::ICNHeader header1; imageStream >> header1; fheroes2::ICNHeader header2; imageStream >> header2; const uint32_t dataSize = header2.offsetData - header1.offsetData; const uint8_t * data = body.data() + headerSize + header1.offsetData; const uint8_t * dataEnd = data + dataSize; _icnVsSprite[id][assetIndex] = fheroes2::decodeICNSprite( data, dataEnd, header1 ); } void LoadOriginalICN( const int id ) { // If this assertion blows up then something wrong with your logic and you load resources more than once! assert( _icnVsSprite[id].empty() ); const std::vector & body = ::AGG::getDataFromAggFile( ICN::getIcnFileName( id ), false ); if ( body.empty() ) { return; } ROStreamBuf imageStream( body ); const uint32_t count = imageStream.getLE16(); const uint32_t blockSize = imageStream.getLE32(); if ( count == 0 || blockSize == 0 ) { return; } _icnVsSprite[id].resize( count ); for ( uint32_t i = 0; i < count; ++i ) { imageStream.seek( headerSize + i * 13 ); fheroes2::ICNHeader header1; imageStream >> header1; // There should be enough frames for ICNs with animation. When animationFrames is equal to 32 then it is a Monochromatic image assert( header1.animationFrames == 32 || header1.animationFrames <= count ); uint32_t dataSize = 0; if ( i + 1 != count ) { fheroes2::ICNHeader header2; imageStream >> header2; dataSize = header2.offsetData - header1.offsetData; } else { dataSize = blockSize - header1.offsetData; } if ( headerSize + header1.offsetData + dataSize > body.size() ) { // This is a corrupted AGG file. throw fheroes2::InvalidDataResources( "ICN Id " + std::to_string( id ) + ", index " + std::to_string( i ) + " is being corrupted. " "Make sure that you own an official version of the game." ); } const uint8_t * data = body.data() + headerSize + header1.offsetData; const uint8_t * dataEnd = data + dataSize; _icnVsSprite[id][i] = fheroes2::decodeICNSprite( data, dataEnd, header1 ); } } // Helper function for LoadModifiedICN void CopyICNWithPalette( const int icnId, const int originalIcnId, const PAL::PaletteType paletteType ) { assert( icnId != originalIcnId ); fheroes2::AGG::GetICN( originalIcnId, 0 ); // always avoid calling LoadOriginalICN directly _icnVsSprite[icnId] = _icnVsSprite[originalIcnId]; const std::vector & palette = PAL::GetPalette( paletteType ); for ( fheroes2::Sprite & sprite : _icnVsSprite[icnId] ) { ApplyPalette( sprite, palette ); } } void generateDefaultImages( const int id ) { switch ( id ) { case ICN::BUTTON_NEW_GAME_EVIL: case ICN::BUTTON_NEW_GAME_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_NEW_GAME_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 1 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "NEW\nGAME" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_SAVE_GAME_EVIL: case ICN::BUTTON_SAVE_GAME_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SAVE_GAME_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 4 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 5 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "SAVE\nGAME" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_LOAD_GAME_EVIL: case ICN::BUTTON_LOAD_GAME_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_LOAD_GAME_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 2 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 3 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "LOAD\nGAME" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_INFO_EVIL: case ICN::BUTTON_INFO_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_INFO_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::APANELE : ICN::APANEL, 4 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::APANELE : ICN::APANEL, 5 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "INFO" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_QUIT_EVIL: case ICN::BUTTON_QUIT_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_QUIT_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 6 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 7 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "QUIT" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_NEW_MAP_EVIL: case ICN::BUTTON_NEW_MAP_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_NEW_MAP_EVIL ); if ( useOriginalResources() && !isEvilInterface ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::ECPANEL, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::ECPANEL, 1 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "NEW\nMAP" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_SAVE_MAP_EVIL: case ICN::BUTTON_SAVE_MAP_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SAVE_MAP_EVIL ); if ( useOriginalResources() && !isEvilInterface ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::ECPANEL, 4 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::ECPANEL, 5 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "SAVE\nMAP" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_LOAD_MAP_EVIL: case ICN::BUTTON_LOAD_MAP_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_LOAD_MAP_EVIL ); if ( useOriginalResources() && !isEvilInterface ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::ECPANEL, 2 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::ECPANEL, 3 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "LOAD\nMAP" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 86, 56 } ); break; } case ICN::BUTTON_SMALL_CANCEL_GOOD: case ICN::BUTTON_SMALL_CANCEL_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_CANCEL_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 8 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CPANELE : ICN::CPANEL, 9 ); // To properly generate shadows and Blit the button we need to make transparent pixels in its released state the same as in the pressed state. CopyTransformLayer( _icnVsSprite[id][0], _icnVsSprite[id][1] ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "CANCEL" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_SMALL_OKAY_GOOD: case ICN::BUTTON_SMALL_OKAY_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_OKAY_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SPANBTNE : ICN::SPANBTN, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SPANBTNE : ICN::SPANBTN, 1 ); // To properly generate shadows and Blit the button we need to make transparent pixels in its released state the same as in the pressed state. CopyTransformLayer( _icnVsSprite[id][0], _icnVsSprite[id][1] ); break; } fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "OKAY" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_SMALL_ACCEPT_GOOD: case ICN::BUTTON_SMALL_ACCEPT_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_ACCEPT_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SURRENDE : ICN::SURRENDR, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SURRENDE : ICN::SURRENDR, 1 ); // To properly generate shadows and Blit the button we need to make transparent pixels in its released state the same as in the pressed state. CopyTransformLayer( _icnVsSprite[id][0], _icnVsSprite[id][1] ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "ACCEPT" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_SMALL_DECLINE_GOOD: case ICN::BUTTON_SMALL_DECLINE_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_DECLINE_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SURRENDE : ICN::SURRENDR, 2 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SURRENDE : ICN::SURRENDR, 3 ); // To properly generate shadows and Blit the button we need to make transparent pixels in its released state the same as in the pressed state. CopyTransformLayer( _icnVsSprite[id][0], _icnVsSprite[id][1] ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "DECLINE" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_SMALL_LEARN_GOOD: case ICN::BUTTON_SMALL_LEARN_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_LEARN_EVIL ); if ( useOriginalResources() ) { const int baseIcnID = isEvilInterface ? ICN::SYSTEME : ICN::SYSTEM; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( baseIcnID, 9 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( baseIcnID, 10 ); break; } fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "LEARN" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::BUTTON_SMALL_TRADE_GOOD: case ICN::BUTTON_SMALL_TRADE_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_TRADE_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::TRADPOSE : ICN::TRADPOST, 15 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::TRADPOSE : ICN::TRADPOST, 16 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "TRADE" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::BUTTON_SMALL_YES_GOOD: case ICN::BUTTON_SMALL_YES_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_YES_EVIL ); if ( useOriginalResources() ) { const int baseIcnID = isEvilInterface ? ICN::SYSTEME : ICN::SYSTEM; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( baseIcnID, 5 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( baseIcnID, 6 ); break; } fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "YES" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::BUTTON_SMALL_NO_GOOD: case ICN::BUTTON_SMALL_NO_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_NO_EVIL ); if ( useOriginalResources() ) { const int baseIcnID = isEvilInterface ? ICN::SYSTEME : ICN::SYSTEM; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( baseIcnID, 7 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( baseIcnID, 8 ); break; } fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "NO" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::BUTTON_SMALL_EXIT_GOOD: case ICN::BUTTON_SMALL_EXIT_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_EXIT_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::VIEWARME : ICN::VIEWARMY, 3 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::VIEWARME : ICN::VIEWARMY, 4 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "EXIT" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_EXIT_HEROES_MEETING: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::SWAPBTN, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::SWAPBTN, 1 ); // fix some wrong pixels in the original pressed state setButtonCornersTransparent( _icnVsSprite[id][1] ); break; } // The heroes meeting screen has an embedded shadow so the button needs to be fixed at the same size as the original one. // TODO: Remove the embedded shadow and button in the heroes meeting screen and use getTextAdaptedSprite() instead. createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "smallerButton|EXIT" ), false, ICN::STONEBAK, { 70, 25 } ); break; } case ICN::BUTTON_EXIT_TOWN: { std::vector & buttonStates = _icnVsSprite[id]; buttonStates.resize( 2 ); if ( useOriginalResources() ) { buttonStates[0] = fheroes2::AGG::GetICN( ICN::TREASURY, 1 ); buttonStates[1] = fheroes2::AGG::GetICN( ICN::TREASURY, 2 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "smallerButton|EXIT" ), false, ICN::BLACKBAK, { 70, 25 } ); break; } case ICN::BUTTON_EXIT_PUZZLE_DIM_DOOR_GOOD: case ICN::BUTTON_EXIT_PUZZLE_DIM_DOOR_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_EXIT_PUZZLE_DIM_DOOR_EVIL ); if ( useOriginalResources() ) { const int originalButtonICN = isEvilInterface ? ICN::LGNDXTRE : ICN::LGNDXTRA; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( originalButtonICN, 4 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( originalButtonICN, 5 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "smallerButton|EXIT" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 70, 25 } ); break; } case ICN::BUTTON_SMALL_DISMISS_GOOD: case ICN::BUTTON_SMALL_DISMISS_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_DISMISS_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::VIEWARME : ICN::VIEWARMY, 1 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::VIEWARME : ICN::VIEWARMY, 2 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "DISMISS" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_SMALL_UPGRADE_GOOD: case ICN::BUTTON_SMALL_UPGRADE_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_UPGRADE_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::VIEWARME : ICN::VIEWARMY, 5 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::VIEWARME : ICN::VIEWARMY, 6 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "UPGRADE" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_SMALL_RESTART_GOOD: case ICN::BUTTON_SMALL_RESTART_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_SMALL_RESTART_EVIL ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::NON_UNIFORM_EVIL_RESTART_BUTTON : ICN::NON_UNIFORM_GOOD_RESTART_BUTTON, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( isEvilInterface ? ICN::NON_UNIFORM_EVIL_RESTART_BUTTON : ICN::NON_UNIFORM_GOOD_RESTART_BUTTON, 1 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "RESTART" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_KINGDOM_EXIT: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::OVERVIEW, 4 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::OVERVIEW, 5 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "smallerButton|EXIT" ), false, ICN::BROWNBAK, { 89, 25 } ); break; } case ICN::BUTTON_KINGDOM_HEROES: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::OVERVIEW, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::OVERVIEW, 1 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "HEROES" ), false, ICN::BROWNBAK, { 89, 42 } ); break; } case ICN::BUTTON_KINGDOM_TOWNS: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::OVERVIEW, 2 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::OVERVIEW, 3 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "TOWNS/\nCASTLES" ), false, ICN::BROWNBAK, { 90, 42 } ); break; } case ICN::BUTTON_MAPSIZE_SMALL: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::REQUESTS, 9 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::REQUESTS, 10 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "S" ), false, ICN::STONEBAK, { 46, 25 } ); break; } case ICN::BUTTON_MAPSIZE_MEDIUM: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::REQUESTS, 11 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::REQUESTS, 12 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "M" ), false, ICN::STONEBAK, { 46, 25 } ); break; } case ICN::BUTTON_MAPSIZE_LARGE: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::REQUESTS, 13 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::REQUESTS, 14 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "L" ), false, ICN::STONEBAK, { 46, 25 } ); break; } case ICN::BUTTON_MAPSIZE_XLARGE: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::REQUESTS, 15 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::REQUESTS, 16 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "X-L" ), false, ICN::STONEBAK, { 46, 25 } ); break; } case ICN::BUTTON_MAPSIZE_ALL: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::REQUESTS, 17 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::REQUESTS, 18 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "ALL" ), false, ICN::STONEBAK, { 58, 25 } ); break; } case ICN::BUTTON_MAP_SELECT_GOOD: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::NGEXTRA, 64 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::NGEXTRA, 65 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "SELECT" ), ICN::EMPTY_MAP_SELECT_BUTTON, ICN::UNKNOWN ); break; } case ICN::BUTTON_MAP_SELECT_EVIL: { _icnVsSprite[id].resize( 2 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; const int buttonIcnID = ICN::BUTTON_MAP_SELECT_GOOD; released = fheroes2::AGG::GetICN( buttonIcnID, 0 ); pressed = fheroes2::AGG::GetICN( buttonIcnID, 1 ); const std::vector & goodToEvilPalette = PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ); fheroes2::ApplyPalette( released, goodToEvilPalette ); fheroes2::ApplyPalette( pressed, goodToEvilPalette ); break; } case ICN::BTNBATTLEONLY: case ICN::BUTTON_STANDARD_GAME: case ICN::BUTTON_CAMPAIGN_GAME: case ICN::BUTTON_MULTIPLAYER_GAME: case ICN::BUTTON_LARGE_CANCEL: case ICN::BUTTON_LARGE_CONFIG: case ICN::BUTTON_ORIGINAL_CAMPAIGN: case ICN::BUTTON_EXPANSION_CAMPAIGN: case ICN::BUTTON_HOT_SEAT: case ICN::BUTTON_2_PLAYERS: case ICN::BUTTON_3_PLAYERS: case ICN::BUTTON_4_PLAYERS: case ICN::BUTTON_5_PLAYERS: case ICN::BUTTON_6_PLAYERS: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() && id != ICN::BTNBATTLEONLY ) { int buttonIcnID = ICN::UNKNOWN; std::pair icnIndex; switch ( id ) { case ICN::BUTTON_CAMPAIGN_GAME: { buttonIcnID = ICN::BTNNEWGM; icnIndex = { 2, 3 }; break; } case ICN::BUTTON_MULTIPLAYER_GAME: { buttonIcnID = ICN::BTNNEWGM; icnIndex = { 4, 5 }; break; } case ICN::BUTTON_LARGE_CANCEL: { buttonIcnID = ICN::BTNNEWGM; icnIndex = { 6, 7 }; break; } case ICN::BUTTON_LARGE_CONFIG: { buttonIcnID = ICN::BTNDCCFG; icnIndex = { 4, 5 }; break; } case ICN::BUTTON_ORIGINAL_CAMPAIGN: { buttonIcnID = ICN::X_LOADCM; icnIndex = { 0, 1 }; break; } case ICN::BUTTON_EXPANSION_CAMPAIGN: { buttonIcnID = ICN::X_LOADCM; icnIndex = { 2, 3 }; break; } case ICN::BUTTON_HOT_SEAT: { buttonIcnID = ICN::BTNMP; icnIndex = { 0, 1 }; break; } case ICN::BUTTON_2_PLAYERS: { buttonIcnID = ICN::BTNHOTST; icnIndex = { 0, 1 }; break; } case ICN::BUTTON_3_PLAYERS: { buttonIcnID = ICN::BTNHOTST; icnIndex = { 2, 3 }; break; } case ICN::BUTTON_4_PLAYERS: { buttonIcnID = ICN::BTNHOTST; icnIndex = { 4, 5 }; break; } case ICN::BUTTON_5_PLAYERS: { buttonIcnID = ICN::BTNHOTST; icnIndex = { 6, 7 }; break; } case ICN::BUTTON_6_PLAYERS: { buttonIcnID = ICN::BTNHOTST; icnIndex = { 8, 9 }; break; } default: // All other buttons share the same settings. buttonIcnID = ICN::BTNNEWGM; icnIndex = { 0, 1 }; break; } _icnVsSprite[id][0] = fheroes2::AGG::GetICN( buttonIcnID, icnIndex.first ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( buttonIcnID, icnIndex.second ); if ( id == ICN::BUTTON_CAMPAIGN_GAME ) { // Fix the disabled state. const fheroes2::Sprite & released = fheroes2::AGG::GetICN( buttonIcnID, icnIndex.first ); const fheroes2::Sprite & pressed = fheroes2::AGG::GetICN( buttonIcnID, icnIndex.second ); fheroes2::Image common = fheroes2::ExtractCommonPattern( { &released, &pressed } ); common = fheroes2::FilterOnePixelNoise( common ); common = fheroes2::FilterOnePixelNoise( common ); common = fheroes2::FilterOnePixelNoise( common ); fheroes2::Blit( common, _icnVsSprite[id][0] ); } break; } const char * text = gettext_noop( "STANDARD\nGAME" ); switch ( id ) { case ICN::BTNBATTLEONLY: { text = gettext_noop( "BATTLE\nONLY" ); break; } case ICN::BUTTON_CAMPAIGN_GAME: { text = gettext_noop( "CAMPAIGN\nGAME" ); break; } case ICN::BUTTON_MULTIPLAYER_GAME: { text = gettext_noop( "MULTI-\nPLAYER\nGAME" ); break; } case ICN::BUTTON_LARGE_CANCEL: { text = gettext_noop( "CANCEL" ); break; } case ICN::BUTTON_LARGE_CONFIG: { text = gettext_noop( "CONFIG" ); break; } case ICN::BUTTON_ORIGINAL_CAMPAIGN: { text = gettext_noop( "ORIGINAL\nCAMPAIGN" ); break; } case ICN::BUTTON_EXPANSION_CAMPAIGN: { text = gettext_noop( "EXPANSION\nCAMPAIGN" ); break; } case ICN::BUTTON_HOT_SEAT: { text = gettext_noop( "HOT SEAT" ); break; } case ICN::BUTTON_2_PLAYERS: { text = gettext_noop( "2 PLAYERS" ); break; } case ICN::BUTTON_3_PLAYERS: { text = gettext_noop( "3 PLAYERS" ); break; } case ICN::BUTTON_4_PLAYERS: { text = gettext_noop( "4 PLAYERS" ); break; } case ICN::BUTTON_5_PLAYERS: { text = gettext_noop( "5 PLAYERS" ); break; } case ICN::BUTTON_6_PLAYERS: { text = gettext_noop( "6 PLAYERS" ); break; } default: break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], text, false, ICN::STONEBAK, { 117, 56 } ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; // Add original shadow. const fheroes2::Sprite & originalShadow = fheroes2::AGG::GetICN( ICN::BTNCOM, 0 ); fheroes2::Image temp( originalShadow.width(), originalShadow.height() ); Copy( released, 0, 0, temp, 5, 0, released.width(), released.height() ); fheroes2::Copy( originalShadow, 0, 0, temp, 0, 0, 5, originalShadow.height() ); fheroes2::Copy( originalShadow, 5, originalShadow.height() - 6, temp, 5, originalShadow.height() - 6, originalShadow.width() - 5, 6 ); fheroes2::Copy( temp, released ); Copy( pressed, 0, 0, temp, 5, 0, released.width(), released.height() ); fheroes2::Copy( originalShadow, 0, 0, temp, 0, 0, 5, originalShadow.height() ); fheroes2::Copy( originalShadow, 5, originalShadow.height() - 6, temp, 5, originalShadow.height() - 6, originalShadow.width() - 5, 6 ); fheroes2::Copy( temp, pressed ); break; } case ICN::BUTTON_GIFT_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_GIFT_EVIL ); fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "GIFT" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::BUTTON_GIFT_EVIL: { // To preserve language-specific generations from generateLanguageSpecificImages() we do a palette swap. _icnVsSprite[id].resize( 2 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( ICN::BUTTON_GIFT_GOOD, 0 ); released = originalReleased; pressed = fheroes2::AGG::GetICN( ICN::BUTTON_GIFT_GOOD, 1 ); ApplyPalette( released, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); ApplyPalette( pressed, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); fheroes2::makeTransparentBackground( released, pressed, ICN::UNIFORMBAK_EVIL ); break; } case ICN::BUTTON_WELL_MAX: { _icnVsSprite[id].resize( 2 ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "MAX" ), ICN::EMPTY_GUILDWELL_BUTTON, ICN::UNKNOWN ); break; } case ICN::BUTTON_GUILDWELL_EXIT: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::WELLXTRA, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::WELLXTRA, 1 ); break; } fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "EXIT" ), ICN::EMPTY_GUILDWELL_BUTTON, ICN::UNKNOWN ); break; } case ICN::BUTTON_VIEWWORLD_EXIT_GOOD: case ICN::BUTTON_VIEWWORLD_EXIT_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_VIEWWORLD_EXIT_EVIL ); if ( useOriginalResources() ) { const int originalIcnId = isEvilInterface ? ICN::LGNDXTRE : ICN::LGNDXTRA; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( originalIcnId, 2 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( originalIcnId, 3 ); break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "smallerButton|EXIT" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 70, 35 } ); break; } case ICN::GOOD_CAMPAIGN_BUTTONS: case ICN::EVIL_CAMPAIGN_BUTTONS: { _icnVsSprite[id].resize( 10 ); if ( useOriginalResources() ) { const bool isEvilInterface = id == ICN::EVIL_CAMPAIGN_BUTTONS; const int originalIcnId = isEvilInterface ? ICN::CAMPXTRE : ICN::CAMPXTRG; const int buttonBackground = isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK; // The evil buttons' released state are 2 pixels wider. const int offsetEvilX = isEvilInterface ? 2 : 0; // remove embedded shadows so that we can generate shadows with our own code later for ( uint32_t i = 0; i < 8; i += 2 ) { // released const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( originalIcnId, i ); fheroes2::Sprite & released = _icnVsSprite[id][i]; released.resize( originalReleased.width() - 6 + offsetEvilX, originalReleased.height() - 8 ); released.reset(); Copy( originalReleased, 6 - offsetEvilX, 0, released, 0, 0, originalReleased.width() - 1, originalReleased.height() - 8 ); // pressed const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( originalIcnId, i + 1 ); fheroes2::Sprite & pressed = _icnVsSprite[id][i + 1]; pressed.resize( originalPressed.width(), originalPressed.height() ); pressed.reset(); Copy( originalPressed, 0, 1, pressed, 0, 1, originalPressed.width() - 1, originalPressed.height() ); setButtonCornersTransparent( released ); fheroes2::makeTransparentBackground( released, pressed, buttonBackground ); } // Generate the DIFFICULTY button because it is not present in the original resources fheroes2::getTextAdaptedSprite( _icnVsSprite[id][8], _icnVsSprite[id][9], gettext_noop( "DIFFICULTY" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, buttonBackground ); break; } createCampaignButtonSet( id, { gettext_noop( "VIEW INTRO" ), gettext_noop( "RESTART" ), gettext_noop( "OKAY" ), gettext_noop( "CANCEL" ), gettext_noop( "DIFFICULTY" ) } ); break; } case ICN::POL_CAMPAIGN_BUTTONS: { _icnVsSprite[id].resize( 10 ); const int baseIcnId = ICN::X_CMPBTN; if ( useOriginalResources() ) { for ( uint32_t i = 0; i < 8; i += 2 ) { // released const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( baseIcnId, i ); fheroes2::Sprite & released = _icnVsSprite[id][i]; released.resize( originalReleased.width() + 1, originalReleased.height() + 1 ); released.reset(); Copy( originalReleased, 0, 0, released, 1, 0, originalReleased.width(), originalReleased.height() ); const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( baseIcnId, i + 1 ); // the released state is missing the darker borders of the pressed state Copy( originalPressed, 0, 0, released, 0, 1, 1, originalPressed.height() ); Copy( originalPressed, 0, 2, released, 0, originalPressed.height() - 1, 1, 2 ); Copy( originalPressed, 1, originalPressed.height() - 1, released, 1, originalPressed.height(), originalPressed.width(), 1 ); Copy( originalPressed, 0, 2, released, 1, originalPressed.height(), 1, 1 ); Copy( originalReleased, 0, 2, released, 1, originalPressed.height() - 2, 1, 1 ); Copy( originalReleased, 0, 2, released, 2, originalPressed.height() - 1, 1, 1 ); Copy( originalReleased, 0, 2, released, 1, originalPressed.height() - 1, 1, 1 ); Copy( originalReleased, 1, 2, released, 2, originalPressed.height() - 2, 1, 1 ); // pressed state fheroes2::Sprite & pressed = _icnVsSprite[id][i + 1]; pressed.resize( originalPressed.width() + 1, originalPressed.height() + 1 ); pressed.reset(); Copy( originalPressed, 0, 0, pressed, 0, 1, originalPressed.width(), originalPressed.height() ); // pressed state has incomplete lower left corner Copy( originalPressed, 0, 2, pressed, 0, originalPressed.height() - 1, 1, 2 ); Copy( originalPressed, 0, 2, pressed, 1, originalPressed.height(), 1, 1 ); Copy( originalPressed, 1, 2, pressed, 1, originalPressed.height() - 1, 1, 1 ); _icnVsSprite[id][i + 1].setPosition( 0, 0 ); fheroes2::makeTransparentBackground( released, pressed, ICN::STONEBAK_SMALL_POL ); } // generate the DIFFICULTY button as it is not present in the original resources fheroes2::getTextAdaptedSprite( _icnVsSprite[id][8], _icnVsSprite[id][9], gettext_noop( "DIFFICULTY" ), ICN::EMPTY_POL_BUTTON, ICN::STONEBAK_SMALL_POL ); break; } createCampaignButtonSet( id, { gettext_noop( "VIEW INTRO" ), gettext_noop( "RESTART" ), gettext_noop( "OKAY" ), gettext_noop( "CANCEL" ), gettext_noop( "DIFFICULTY" ) } ); break; } case ICN::BUTTON_SMALL_MIN_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = id == ICN::BUTTON_SMALL_MIN_EVIL; createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "MIN" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { fheroes2::AGG::GetICN( ICN::BUTTON_SMALL_MAX_GOOD, 0 ).width() - 10, 25 } ); break; } case ICN::BUTTON_SMALL_MAX_GOOD: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = id == ICN::BUTTON_SMALL_MAX_EVIL; if ( useOriginalResources() ) { // The original assets ICN contains button with shadow. We crop only the button. _icnVsSprite[id][0] = fheroes2::Crop( fheroes2::AGG::GetICN( ICN::RECRUIT, 4 ), 5, 0, 60, 25 ); _icnVsSprite[id][1] = fheroes2::Crop( fheroes2::AGG::GetICN( ICN::RECRUIT, 5 ), 5, 0, 60, 25 ); _icnVsSprite[id][0].setPosition( 0, 0 ); _icnVsSprite[id][1].setPosition( 0, 0 ); // To properly generate shadows and Blit the button we need to make some pixels transparent. for ( fheroes2::Sprite & image : _icnVsSprite[id] ) { setButtonCornersTransparent( image ); } if ( isEvilInterface ) { fheroes2::ApplyPalette( _icnVsSprite[id][0], PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); fheroes2::ApplyPalette( _icnVsSprite[id][1], PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); } break; } createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "MAX" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { 61, 25 } ); break; } case ICN::UNIFORM_GOOD_MIN_BUTTON: case ICN::UNIFORM_GOOD_MAX_BUTTON: { // To preserve language-specific generations from generateLanguageSpecificImages() we clean the non uniform button. _icnVsSprite[id].resize( 2 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; const bool maxButton = id == ICN::UNIFORM_GOOD_MAX_BUTTON; const int buttonIcnID = maxButton ? ICN::BUTTON_SMALL_MAX_GOOD : ICN::BUTTON_SMALL_MIN_GOOD; released = fheroes2::AGG::GetICN( buttonIcnID, 0 ); pressed = fheroes2::AGG::GetICN( buttonIcnID, 1 ); // Clean the borders of the pressed state. FillTransform( pressed, 4, 0, pressed.width() - 3, 1, 1 ); FillTransform( pressed, pressed.width() - 3, 1, 2, 1, 1 ); FillTransform( pressed, pressed.width() - 2, 2, 2, 1, 1 ); FillTransform( pressed, pressed.width() - 1, 3, 1, pressed.height() - 5, 1 ); fheroes2::makeTransparentBackground( released, pressed, ICN::UNIFORMBAK_GOOD ); break; } case ICN::UNIFORM_EVIL_MAX_BUTTON: case ICN::UNIFORM_EVIL_MIN_BUTTON: { // To preserve language-specific generations from generateLanguageSpecificImages() we do a palette swap. _icnVsSprite[id].resize( 2 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; const bool isMaxButton = id == ICN::UNIFORM_EVIL_MAX_BUTTON; const int buttonIcnID = isMaxButton ? ICN::UNIFORM_GOOD_MAX_BUTTON : ICN::UNIFORM_GOOD_MIN_BUTTON; released = fheroes2::AGG::GetICN( buttonIcnID, 0 ); pressed = fheroes2::AGG::GetICN( buttonIcnID, 1 ); ApplyPalette( released, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); ApplyPalette( pressed, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); break; } case ICN::BUTTON_SMALL_MAX_EVIL: case ICN::BUTTON_SMALL_MIN_EVIL: { // To preserve language-specific generations from generateLanguageSpecificImages() we do a palette swap. _icnVsSprite[id].resize( 2 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; const bool isMaxButton = id == ICN::BUTTON_SMALL_MAX_EVIL; const int buttonIcnID = isMaxButton ? ICN::BUTTON_SMALL_MAX_GOOD : ICN::BUTTON_SMALL_MIN_GOOD; released = fheroes2::AGG::GetICN( buttonIcnID, 0 ); pressed = fheroes2::AGG::GetICN( buttonIcnID, 1 ); ApplyPalette( released, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); ApplyPalette( pressed, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); break; } case ICN::BUTTON_EXIT_GOOD: { _icnVsSprite[id].resize( 2 ); fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "EXIT" ), ICN::EMPTY_GOOD_BUTTON, ICN::STONEBAK ); break; } case ICN::BUTTON_RESET_GOOD: { _icnVsSprite[id].resize( 2 ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "RESET" ), ICN::EMPTY_GOOD_BUTTON, ICN::STONEBAK ); break; } case ICN::BUTTON_START_GOOD: { _icnVsSprite[id].resize( 2 ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "START" ), ICN::EMPTY_GOOD_BUTTON, ICN::STONEBAK ); break; } case ICN::BUTTON_CASTLE_GOOD: case ICN::BUTTON_CASTLE_EVIL: { _icnVsSprite[id].resize( 2 ); // Town and Castle buttons must have the same width. // This is why we need to calculate text width for both buttons and then create a button with a needed width. const fheroes2::FontType releasedFont{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE }; const int32_t townTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "TOWN" ), releasedFont ), releasedFont }.width(); const int32_t castleTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "CASTLE" ), releasedFont ), releasedFont }.width(); // Normal button width is 80 pixels so if the overall length is smaller than 80 then set the default value. const int32_t width = std::max( 80, std::max( townTextWidth, castleTextWidth ) ); const bool isEvilInterface = id == ICN::BUTTON_CASTLE_EVIL; createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "CASTLE" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { width, 25 } ); break; } case ICN::BUTTON_TOWN_GOOD: case ICN::BUTTON_TOWN_EVIL: { _icnVsSprite[id].resize( 2 ); // Town and Castle buttons must have the same width. // This is why we need to calculate text width for both buttons and then create a button with a needed width. const fheroes2::FontType releasedFont{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE }; const int32_t townTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "TOWN" ), releasedFont ), releasedFont }.width(); const int32_t castleTextWidth = fheroes2::Text{ fheroes2::getSupportedText( _( "CASTLE" ), releasedFont ), releasedFont }.width(); // Normal button width is 80 pixels so if the overall length is smaller than 80 then set the default value. const int32_t width = std::max( 80, std::max( townTextWidth, castleTextWidth ) ); const bool isEvilInterface = id == ICN::BUTTON_TOWN_EVIL; createNormalButton( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "TOWN" ), isEvilInterface, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, { width, 25 } ); break; } case ICN::BUTTON_RESTRICT_GOOD: case ICN::BUTTON_RESTRICT_EVIL: { _icnVsSprite[id].resize( 2 ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "RESTRICT" ), id == ICN::BUTTON_RESTRICT_EVIL ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, id == ICN::BUTTON_RESTRICT_EVIL ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::UNIFORM_GOOD_OKAY_BUTTON: case ICN::UNIFORM_EVIL_OKAY_BUTTON: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::UNIFORM_EVIL_OKAY_BUTTON ); if ( useOriginalResources() ) { const int baseIcnId = isEvilInterface ? ICN::SYSTEME : ICN::SYSTEM; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( baseIcnId, 1 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( baseIcnId, 2 ); break; } fheroes2::getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "OKAY" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::UNIFORM_GOOD_CANCEL_BUTTON: case ICN::UNIFORM_EVIL_CANCEL_BUTTON: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::UNIFORM_EVIL_CANCEL_BUTTON ); if ( useOriginalResources() ) { const int baseIcnId = isEvilInterface ? ICN::SYSTEME : ICN::SYSTEM; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( baseIcnId, 3 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( baseIcnId, 4 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "CANCEL" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::UNIFORM_GOOD_EXIT_BUTTON: case ICN::UNIFORM_EVIL_EXIT_BUTTON: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::UNIFORM_EVIL_EXIT_BUTTON ); const int baseIcnId = isEvilInterface ? ICN::TRADPOSE : ICN::TRADPOST; if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( baseIcnId, 17 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( baseIcnId, 18 ); break; } getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "EXIT" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); break; } case ICN::BUTTON_VERTICAL_DISMISS: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { // The original DISMISS button has a broken transform layer and thinner pressed state than released state, // so we use our empty vertical button as a template _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::EMPTY_VERTICAL_GOOD_BUTTON, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::EMPTY_VERTICAL_GOOD_BUTTON, 1 ); // Copy the DISMISS text back from the original button const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( ICN::HSBTNS, 0 ); const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( ICN::HSBTNS, 1 ); Copy( originalReleased, 9, 2, _icnVsSprite[id][0], 5, 2, 21, 112 ); Copy( originalPressed, 9, 5, _icnVsSprite[id][1], 4, 5, 19, 111 ); fheroes2::makeTransparentBackground( _icnVsSprite[id][0], _icnVsSprite[id][1], ICN::REDBAK_SMALL_VERTICAL ); break; } // We need to temporarily remove the letter-specific X offsets in the font because if not the letters will // be off-centered when we are displaying one letter per line const ButtonFontOffsetRestorer fontReleased( _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], -1 ); const ButtonFontOffsetRestorer fontPressed( _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED], -1 ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "D\nI\nS\nM\nI\nS\nS" ), ICN::EMPTY_VERTICAL_GOOD_BUTTON, ICN::REDBAK_SMALL_VERTICAL ); break; } case ICN::BUTTON_VERTICAL_EXIT: { _icnVsSprite[id].resize( 2 ); if ( useOriginalResources() ) { // The original EXIT button has a broken transform layer and we need to remove the shadows, // so we use our empty vertical button as a template _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::EMPTY_VERTICAL_GOOD_BUTTON, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::EMPTY_VERTICAL_GOOD_BUTTON, 1 ); // Copy the EXIT text back from the original button const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( ICN::HSBTNS, 2 ); const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( ICN::HSBTNS, 3 ); Copy( originalReleased, 4, 2, _icnVsSprite[id][0], 5, 2, 21, 112 ); Copy( originalPressed, 3, 5, _icnVsSprite[id][1], 4, 5, 19, 111 ); fheroes2::makeTransparentBackground( _icnVsSprite[id][0], _icnVsSprite[id][1], ICN::REDBAK_SMALL_VERTICAL ); break; } // We need to temporarily remove the letter specific X offsets in the font because if not the letters will // be off-centered when we are displaying one letter per line const ButtonFontOffsetRestorer fontReleased( _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], -1 ); const ButtonFontOffsetRestorer fontPressed( _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED], -1 ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "E\nX\nI\nT" ), ICN::EMPTY_VERTICAL_GOOD_BUTTON, ICN::REDBAK_SMALL_VERTICAL ); break; } case ICN::BUTTON_VERTICAL_PATROL: { _icnVsSprite[id].resize( 2 ); // We need to temporarily remove the letter specific X offsets in the font because if not the letters will // be off-centered when we are displaying one letter per line const ButtonFontOffsetRestorer fontReleased( _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], -1 ); const ButtonFontOffsetRestorer fontPressed( _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED], -1 ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "P\nA\nT\nR\nO\nL" ), ICN::EMPTY_VERTICAL_GOOD_BUTTON, ICN::REDBAK_SMALL_VERTICAL ); break; } case ICN::BUTTON_HSCORES_VERTICAL_CAMPAIGN: case ICN::BUTTON_HSCORES_VERTICAL_EXIT: case ICN::BUTTON_HSCORES_VERTICAL_STANDARD: { _icnVsSprite[id].resize( 2 ); const int originalID = ICN::HISCORE; uint32_t originalICNIndex = 0; if ( id == ICN::BUTTON_HSCORES_VERTICAL_STANDARD ) { originalICNIndex = 2; } else if ( id == ICN::BUTTON_HSCORES_VERTICAL_EXIT ) { originalICNIndex = 4; } else { assert( id == ICN::BUTTON_HSCORES_VERTICAL_CAMPAIGN ); } if ( useOriginalResources() ) { _icnVsSprite[id][0] = fheroes2::AGG::GetICN( originalID, originalICNIndex ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( originalID, originalICNIndex + 1 ); break; } for ( size_t i = 0; i < _icnVsSprite[id].size(); ++i ) { const fheroes2::Sprite & originalButton = fheroes2::AGG::GetICN( originalID, originalICNIndex + static_cast( i ) ); fheroes2::Sprite & out = _icnVsSprite[id][i]; out = originalButton; // Clean the button Fill( out, 4 - static_cast( i ), 4 + static_cast( i ), 19, 123, getButtonFillingColor( i == 0 ) ); } const char * buttonText; if ( id == ICN::BUTTON_HSCORES_VERTICAL_CAMPAIGN ) { buttonText = gettext_noop( "C\nA\nM\nP\nA\nI\nG\nN" ); } else if ( id == ICN::BUTTON_HSCORES_VERTICAL_STANDARD ) { buttonText = gettext_noop( "S\nT\nA\nN\nD\nA\nR\nD" ); } else { buttonText = gettext_noop( "E\nX\nI\nT" ); } const ButtonFontOffsetRestorer fontRestorerReleased( _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], -1 ); const ButtonFontOffsetRestorer fontRestorerPressed( _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED], -1 ); const char * translatedText = fheroes2::getSupportedText( buttonText, fheroes2::FontType{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE } ); fheroes2::renderTextOnButton( _icnVsSprite[id][0], _icnVsSprite[id][1], translatedText, { 3, 4 }, { 2, 5 }, { 23, 133 }, fheroes2::FontColor::WHITE ); break; } case ICN::BUTTON_RUMORS_GOOD: case ICN::BUTTON_RUMORS_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_RUMORS_EVIL ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "RUMORS" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_EVENTS_GOOD: case ICN::BUTTON_EVENTS_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_EVENTS_EVIL ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "EVENTS" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_LANGUAGE_GOOD: case ICN::BUTTON_LANGUAGE_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_LANGUAGE_EVIL ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "LANGUAGE" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_AUTO_COMBAT_GOOD: case ICN::BUTTON_AUTO_COMBAT_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_AUTO_COMBAT_EVIL ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "AUTO\nCOMBAT" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::BUTTON_QUICK_COMBAT_GOOD: case ICN::BUTTON_QUICK_COMBAT_EVIL: { _icnVsSprite[id].resize( 2 ); const bool isEvilInterface = ( id == ICN::BUTTON_QUICK_COMBAT_EVIL ); getTextAdaptedSprite( _icnVsSprite[id][0], _icnVsSprite[id][1], gettext_noop( "QUICK\nCOMBAT" ), isEvilInterface ? ICN::EMPTY_EVIL_BUTTON : ICN::EMPTY_GOOD_BUTTON, isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK ); break; } case ICN::DISMISS_HERO_DISABLED_BUTTON: { _icnVsSprite[id].resize( 1 ); const int buttonIcnId = ICN::BUTTON_VERTICAL_DISMISS; const fheroes2::Sprite & released = fheroes2::AGG::GetICN( buttonIcnId, 0 ); const fheroes2::Sprite & pressed = fheroes2::AGG::GetICN( buttonIcnId, 1 ); fheroes2::Sprite & output = _icnVsSprite[id][0]; output = released; fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); fheroes2::Image common = fheroes2::ExtractCommonPattern( { &released, &pressed } ); common = fheroes2::FilterOnePixelNoise( common ); common = fheroes2::FilterOnePixelNoise( common ); common = fheroes2::FilterOnePixelNoise( common ); fheroes2::Blit( common, output ); break; } default: // You're calling this function for non-specified ICN id. Check your logic! // Did you add a new image for one language without generating a default // for other languages? assert( 0 ); break; } } bool generateGermanSpecificImages( const int id ) { switch ( id ) { case ICN::BTNBATTLEONLY: _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { fheroes2::Sprite & out = _icnVsSprite[id][i]; out = fheroes2::AGG::GetICN( ICN::BTNNEWGM, 6 + i ); // Clean the button Fill( out, 26 - i, 23 + i, 84, 11, getButtonFillingColor( i == 0 ) ); // Add 'K' Copy( fheroes2::AGG::GetICN( ICN::BTNDCCFG, 4 + i ), 34 - i, 23, out, 40 - i, 23, 12, 14 ); //'Add 'A' Copy( fheroes2::AGG::GetICN( ICN::BTNNEWGM, 4 + i ), 56 - i, 23, out, 52 - i, 23, 13, 14 ); Copy( out, 20, 20, out, 52 - i + 12, 25, 3, 3 ); // Add 'M' Copy( fheroes2::AGG::GetICN( ICN::BTNNEWGM, 4 + i ), 39 - i, 8, out, 65 - i, 23, 14, 14 ); // Add 'F' Copy( fheroes2::AGG::GetICN( ICN::BTNDCCFG, 4 + i ), 70 - i, 23, out, 87 - i, 23, 10, 14 ); // Add 'P' Copy( fheroes2::AGG::GetICN( ICN::BTNNEWGM, 4 + i ), 36 - i, 23, out, 78 - i, 23, 10, 14 ); } return true; default: break; } return false; } bool generateFrenchSpecificImages( const int id ) { switch ( id ) { case ICN::BTNBATTLEONLY: { _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { fheroes2::Sprite & out = _icnVsSprite[id][i]; out = fheroes2::AGG::GetICN( ICN::BTNNEWGM, 6 + i ); // Clean the button Fill( out, 32 - i, 21 + i, 77, 14, getButtonFillingColor( i == 0 ) ); const int32_t secondLine = 28; // Add 'MODE' Copy( fheroes2::AGG::GetICN( ICN::BTNNEWGM, 4 + i ), 40 - i, 13, out, 45 - i, 13, 50, 15 ); // Clean up 'MODE' Copy( fheroes2::AGG::GetICN( ICN::BTNEMAIN, 0 + i ), 114 - i, 18, out, 94 - i, 18, 1, 10 ); // Add 'BA' Copy( fheroes2::AGG::GetICN( ICN::BTNBAUD, 2 + i ), 42 - i, 28, out, 28 - i, secondLine, 22, 15 ); // Clean up 'BA' Copy( fheroes2::AGG::GetICN( ICN::BTNBAUD, 2 + i ), 42 - i, 31, out, 39 - i, secondLine, 1, 1 ); Copy( fheroes2::AGG::GetICN( ICN::BTNBAUD, 2 + i ), 39 - i, 31, out, 49 - i, secondLine + 4, 1, 2 ); // Add 'T' Copy( fheroes2::AGG::GetICN( ICN::BTNDC, 2 + i ), 89 - i, 21, out, 49 - i, secondLine, 12, 15 ); // Clean up 'AT' Copy( fheroes2::AGG::GetICN( ICN::BTNDC, 2 + i ), 89 - i, 18, out, 50 - i, secondLine, 1, 1 ); Copy( fheroes2::AGG::GetICN( ICN::BTNDC, 2 + i ), 92 - ( 5 * i ), 27 - i, out, 49 - i, secondLine + 4 + i, 1, 3 ); // Add 'AI'. Copy( fheroes2::AGG::GetICN( ICN::BTNMP, 6 + i ), 56 - i, 13, out, 62 - i, secondLine, 18, 15 ); // Clean up 'TA' Copy( fheroes2::AGG::GetICN( ICN::BTNBAUD, 2 + i ), 51 - i, 40, out, 60 - i, secondLine + 12, 3, 3 ); // Add 'LLE' Copy( fheroes2::AGG::GetICN( ICN::BTNEMAIN, 0 + i ), 85 - i, 13, out, 81 - i, secondLine, 31, 15 ); // Clean up "IL" Copy( fheroes2::AGG::GetICN( ICN::BTNEMAIN, 0 + i ), 85 - i, 18, out, 81 - i, secondLine + 7, 1, 1 ); Copy( fheroes2::AGG::GetICN( ICN::BTNEMAIN, 0 + i ), 94 - i, 17, out, 80 - i, secondLine + 4, 2, 2 ); Copy( fheroes2::AGG::GetICN( ICN::BTNEMAIN, 0 + i ), 93 - i, 25, out, 79 - i, secondLine + 12, 3, 3 ); Copy( fheroes2::AGG::GetICN( ICN::BTNDC, 4 + i ), 23 - i, 8, out, 79 - i, secondLine + 5, 1, 10 ); Copy( fheroes2::AGG::GetICN( ICN::BTNMP, 6 + i ), 73 - i, 22, out, 79 - i, secondLine + 9, 1, 1 ); } return true; } case ICN::BUTTON_GIFT_GOOD: { _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { fheroes2::Sprite & out = _icnVsSprite[id][i]; const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ); // We use this Copy function to make the pressed state not single layered like the original. Copy( original, out ); // Clean the button Fill( out, 33, 5, 31, 16, getButtonFillingColor( i == 0 ) ); const int32_t offsetY = 5; // Add 'D' const int32_t offsetXD = 14; Copy( fheroes2::AGG::GetICN( ICN::CPANEL, 4 + i ), 48 - i, 28 + i, out, offsetXD - i, offsetY + i, 10, 15 ); // Clean up 'D' and restore button ornament Copy( fheroes2::AGG::GetICN( ICN::CPANEL, 4 + i ), 48 - i, 36, out, offsetXD - 1 - i, offsetY + 4 + i, 1, 1 ); Copy( fheroes2::AGG::GetICN( ICN::CPANEL, 4 + i ), 48 - i, 35, out, offsetXD - i, offsetY + 9 + i, 1, 2 ); Copy( fheroes2::AGG::GetICN( ICN::CPANEL, 4 + i ), 48 - i, 35, out, offsetXD - 1 - i, offsetY + 13 + i, 1, 1 ); Fill( out, offsetXD + 9 - i, offsetY + 13 + i, 1, 1, getButtonFillingColor( i == 0 ) ); Copy( fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ), offsetXD, offsetY, out, offsetXD, offsetY, 1, 1 ); // Add 'O' const int32_t offsetXO = 10; Copy( fheroes2::AGG::GetICN( ICN::CAMPXTRG, i ), 40 - ( 7 * i ), 5 + i, out, offsetXD + offsetXO + 1 - i, offsetY + i, 13 - i, 15 ); // Clean up 'DO' Copy( fheroes2::AGG::GetICN( ICN::CPANEL, 4 + i ), 51 - i, 34, out, offsetXD + offsetXO - i, offsetY + 5, 2, 2 ); Copy( fheroes2::AGG::GetICN( ICN::CPANEL, 4 + i ), 51 - i, 34, out, offsetXD + offsetXO - i, offsetY + 7, 1, 1 + i ); Copy( fheroes2::AGG::GetICN( ICN::CPANEL, 4 + i ), 55 - i, 28 + i, out, offsetXD + 9 - i, offsetY + 2 + i, 3, 3 ); Fill( out, offsetXD + 11 - i, offsetY + i, 2, 2, getButtonFillingColor( i == 0 ) ); // Add 'N' const int32_t offsetXN = 13; Copy( fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ), 50 - i, 5, out, offsetXD + offsetXO + offsetXN - i, offsetY, 14, 15 ); // Clean up 'ON' Fill( out, offsetXD + offsetXO + offsetXN, offsetY, 1, 1, getButtonFillingColor( i == 0 ) ); Fill( out, offsetXD + offsetXO + offsetXN - i, offsetY + 9, 1, 1, getButtonFillingColor( i == 0 ) ); // Add 'N' Copy( fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ), 50 - i, 5, out, offsetXD + 10 + offsetXN + offsetXN - i, offsetY, 14, 15 ); // Clean up 'NN' Fill( out, offsetXD + offsetXO + offsetXN + offsetXN - i, offsetY + 9, 1, 1, getButtonFillingColor( i == 0 ) ); // Add 'ER' Copy( fheroes2::AGG::GetICN( ICN::CAMPXTRG, 2 + i ), 75 - ( 8 * i ), 5, out, offsetXD + offsetXO + offsetXN + offsetXN + offsetXN - ( 2 * i ), offsetY, 23, 15 ); // Restore button ornament Copy( fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ), offsetXD + offsetXO + offsetXN + offsetXN + offsetXN + 20, offsetY, out, offsetXD + offsetXO + offsetXN + offsetXN + offsetXN + 20, offsetY, 1, 1 ); Copy( fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ), offsetXD + offsetXO + offsetXN + offsetXN + offsetXN + 21, offsetY + 1, out, offsetXD + offsetXO + offsetXN + offsetXN + offsetXN + 21, offsetY + 1, 2, 3 ); Copy( fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ), offsetXD + offsetXO + offsetXN + offsetXN + offsetXN + 20, offsetY, out, offsetXD + offsetXO + offsetXN + offsetXN + offsetXN + 21, offsetY + 4, 1, 1 ); } return true; } case ICN::BUTTON_SMALL_MAX_GOOD: { _icnVsSprite[id].resize( 2 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( ICN::RECRUIT, 4 ); const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( ICN::RECRUIT, 5 ); released = originalReleased; pressed = originalPressed; // The original assets ICN contains button with shadow. We crop only the button. released = Crop( originalReleased, 5, 0, 60, 25 ); pressed = Crop( originalPressed, 5, 0, 60, 25 ); released.setPosition( 0, 0 ); pressed.setPosition( 0, 0 ); // Fill wrong transparent text pixels with color. fheroes2::Image whiteBackground( released.width(), released.height() ); Fill( whiteBackground, 0, 0, released.width(), released.height(), 10 ); Blit( released, whiteBackground ); released = whiteBackground; // To properly generate shadows and Blit the button we need to make some pixels transparent. for ( fheroes2::Sprite & image : _icnVsSprite[id] ) { setButtonCornersTransparent( image ); } fheroes2::Image common = fheroes2::ExtractCommonPattern( { &released, &pressed } ); common = FilterOnePixelNoise( common ); common = FilterOnePixelNoise( common ); common = FilterOnePixelNoise( common ); Blit( common, _icnVsSprite[id][0] ); return true; } case ICN::BUTTON_SMALL_MIN_GOOD: { _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { fheroes2::Sprite & out = _icnVsSprite[id][i]; out = fheroes2::AGG::GetICN( ICN::BUTTON_SMALL_MAX_GOOD, i ); // Clean the button and leave 'M' Fill( out, 26 - 2 * i, 5 + i, 25, 15, getButtonFillingColor( i == 0 ) ); Fill( out, 24 - 2 * i, 17 + i, 2, 2, getButtonFillingColor( i == 0 ) ); // Add 'I' Copy( fheroes2::AGG::GetICN( ICN::APANEL, 4 + i ), 25 - i, 19 + i, out, 27 - i, 4 + i, 7 - i, 15 ); Copy( fheroes2::AGG::GetICN( ICN::RECRUIT, 4 + i ), 28 - i, 7 + i, out, 31 - i, 7 + i, 3, 9 ); Fill( out, 32 - i, 16 + i, 2, 3, getButtonFillingColor( i == 0 ) ); // Add 'N' Copy( fheroes2::AGG::GetICN( ICN::TRADPOST, 17 + i ), 50 - i, 5, out, 36 - i, 5, 14, 15 ); Fill( out, 36 - i, 5, 1, 1, getButtonFillingColor( i == 0 ) ); Fill( out, 36 - i, 5 + 9, 1, 1, getButtonFillingColor( i == 0 ) ); } return true; } default: break; } return false; } bool generatePolishSpecificImages( const int id ) { switch ( id ) { case ICN::BTNBATTLEONLY: { _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { fheroes2::Sprite & out = _icnVsSprite[id][i]; out = fheroes2::AGG::GetICN( ICN::BTNNEWGM, 6 + i ); // clean the button Fill( out, 41 - i, 23 + i, 57, 11, getButtonFillingColor( i == 0 ) ); const int32_t offsetX = 46; const int32_t offsetY = 23; // Add 'BI' Copy( fheroes2::AGG::GetICN( ICN::BTNMCFG, 2 + i ), 58 - i, 29, out, offsetX - i, offsetY, 14, 11 ); // Add 'T' Copy( fheroes2::AGG::GetICN( ICN::BTNNEWGM, 0 + i ), 24 - i, 29, out, offsetX + 14 - i, offsetY, 9, 11 ); // Add 'WA' Copy( fheroes2::AGG::GetICN( ICN::BTNEMAIN, 0 + i ), 45 - i, 23, out, offsetX + 23 - i, offsetY, 24, 11 ); // Add pixel to 'W' Copy( fheroes2::AGG::GetICN( ICN::BTNEMAIN, 0 + i ), 47 - i, 23 + i, out, offsetX + 38 - i, offsetY + i, 1, 1 ); } return true; } case ICN::BUTTON_SMALL_MIN_GOOD: { _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { fheroes2::Sprite & out = _icnVsSprite[id][i]; const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::BUTTON_SMALL_MAX_GOOD, i ); out = original; // Wipe the button Fill( out, 9 - 2 * i, 7 + i, 46 + i, 10, getButtonFillingColor( i == 0 ) ); // 'M' Copy( original, 9 - i, 7 + i, out, 13 - i, 7 + i, 14, 10 ); // 'I' Copy( fheroes2::AGG::GetICN( ICN::BTNMCFG, 4 + i ), 53 - i, 23 + i, out, 28 - i, 7 + i, 5, 10 ); // 'N' Copy( fheroes2::AGG::GetICN( ICN::BTNMCFG, 0 + i ), 83 - i, 29 + i, out, 34 - i, 7 + i, 11, 10 ); // '.' Copy( original, 52 - i, 14 + i, out, 47 - i, 14 + i, 3, 3 ); fheroes2::Fill( out, 44 - i, 8 + i, 1, 9, getButtonFillingColor( i == 0 ) ); if ( i == 0 ) { fheroes2::ReplaceColorId( out, 56, 55 ); } if ( id == ICN::BUTTON_SMALL_MIN_EVIL ) { ApplyPalette( _icnVsSprite[id][0], PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); ApplyPalette( _icnVsSprite[id][1], PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_BUTTON ) ); } } return true; } default: break; } return false; } void generateLanguageSpecificImages( int id ) { assert( isLanguageDependentIcnId( id ) ); const fheroes2::SupportedLanguage resourceLanguage = fheroes2::getResourceLanguage(); // Language-specific image generators, may fail if ( fheroes2::getCurrentLanguage() == resourceLanguage ) { switch ( resourceLanguage ) { case fheroes2::SupportedLanguage::German: if ( generateGermanSpecificImages( id ) ) { return; } break; case fheroes2::SupportedLanguage::French: if ( generateFrenchSpecificImages( id ) ) { return; } break; case fheroes2::SupportedLanguage::Polish: if ( generatePolishSpecificImages( id ) ) { return; } break; default: break; } } // Image generator of a last resort, must provide the generation of the "default" variant // for all image ids for which this function can be called, and must not fail. generateDefaultImages( id ); } void generateGradientFont( const int fontId, const int originalFontId, const uint8_t gradientInnerColor, const uint8_t gradientOuterColor, const uint8_t contourInnerColor, const uint8_t contourOuterColor ) { assert( fontId != originalFontId ); fheroes2::AGG::GetICN( originalFontId, 0 ); const std::vector & original = _icnVsSprite[originalFontId]; _icnVsSprite[fontId].resize( original.size() ); for ( size_t i = 0; i < original.size(); ++i ) { const fheroes2::Sprite & in = original[i]; fheroes2::Sprite & out = _icnVsSprite[fontId][i]; out.resize( in.width() + 6, in.height() + 6 ); out.reset(); Copy( in, 0, 0, out, 3, 3, in.width(), in.height() ); out.setPosition( in.x() - 2, in.y() - 2 ); applyFontVerticalGradient( out, gradientInnerColor, gradientOuterColor ); Blit( CreateContour( out, contourInnerColor ), out ); Blit( CreateContour( out, 0 ), out ); Blit( CreateContour( out, contourOuterColor ), out ); } } // This function must return true is resources have been modified, false otherwise. bool LoadModifiedICN( const int id ) { // If this assertion blows up then you are calling this function in a recursion. Check your code! assert( _icnVsSprite[id].empty() ); // IMPORTANT!!! // Call LoadOriginalICN() function only if you are handling the same ICN. // If you need to load a different ICN use loadICN() function. // Some images contain text. This text should be adapted to a chosen language. if ( isLanguageDependentIcnId( id ) ) { generateLanguageSpecificImages( id ); return true; } switch ( id ) { case ICN::ROUTERED: CopyICNWithPalette( id, ICN::ROUTE, PAL::PaletteType::RED ); return true; case ICN::FONT: case ICN::SMALFONT: { LoadOriginalICN( id ); auto & imageArray = _icnVsSprite[id]; if ( imageArray.size() < 96 ) { // 96 symbols is the minimum requirement for English. throw std::logic_error( "The game resources are corrupted. Please use resources from a licensed version of Heroes of Might and Magic II." ); } // Compare '(' and ')' symbols. By size they are always the same. However, we play safe and fail if both dimensions are different. if ( ( imageArray[8].width() != imageArray[9].width() ) && ( imageArray[8].height() != imageArray[9].height() ) ) { // This is most likely a corrupted font or a pirated translation to a non-English language which causes all sorts of rendering issues. throw std::logic_error( "The game resources are corrupted. Please use resources from a licensed version of Heroes of Might and Magic II." ); } const std::vector & body = ::AGG::getDataFromAggFile( ICN::getIcnFileName( id ), false ); const uint32_t crc32 = fheroes2::calculateCRC32( body.data(), body.size() ); if ( id == ICN::SMALFONT ) { // Small font in official Polish GoG version has all letters shifted 1 pixel down. if ( crc32 == 0xE9EC7A63 ) { for ( fheroes2::Sprite & letter : imageArray ) { letter.setPosition( letter.x(), letter.y() - 1 ); } } modifyBaseSmallFont( _icnVsSprite[id] ); } else { assert( id == ICN::FONT ); // The original images contain an issue: image layer has value 50 which is '2' in UTF-8. We must correct these (only 3) places for ( fheroes2::Sprite & fontImage : imageArray ) { ReplaceColorIdByTransformId( fontImage, 50, 2 ); } modifyBaseNormalFont( _icnVsSprite[id] ); } // Some checks that we really have CP1251 font const int32_t verifiedFontWidth = ( id == ICN::FONT ) ? 19 : 12; if ( imageArray.size() == 162 && imageArray[121].width() == verifiedFontWidth ) { // Engine expects that letter indexes correspond to charcode - 0x20. // In case CP1251 font.icn contains sprites for chars 0x20-0x7F, 0xC0-0xDF, 0xA8, 0xE0-0xFF, 0xB8 (in that order). // We rearrange sprites array for corresponding sprite indexes to charcode - 0x20. const fheroes2::Sprite firstSprite{ imageArray[0] }; imageArray.insert( imageArray.begin() + 96, 64, firstSprite ); std::swap( imageArray[136], imageArray[192] ); // Move sprites for chars 0xA8 std::swap( imageArray[152], imageArray[225] ); // and 0xB8 to it's places. imageArray.pop_back(); imageArray.erase( imageArray.begin() + 192 ); } // German version uses CP1252 if ( crc32 == 0x04745D1D || crc32 == 0xD0F0D852 ) { const fheroes2::Sprite firstSprite{ imageArray[0] }; imageArray.insert( imageArray.begin() + 96, 124, firstSprite ); std::swap( imageArray[164], imageArray[224] ); std::swap( imageArray[182], imageArray[225] ); std::swap( imageArray[188], imageArray[226] ); std::swap( imageArray[191], imageArray[223] ); std::swap( imageArray[196], imageArray[220] ); std::swap( imageArray[214], imageArray[221] ); std::swap( imageArray[220], imageArray[222] ); imageArray.erase( imageArray.begin() + 221, imageArray.end() ); } // The French version replaces several ASCII special characters with language-specific characters. // In the engine we use CP1252 for the French translation but we have to preserve the homegrown encoding // of the original so that original French maps' texts are displayed correctly. if ( crc32 == 0xD9556567 || crc32 == 0x406967B9 ) { // The engine expects that letter indexes correspond to charcode - 0x20, but the original French // Price of Loyalty maps use 0x09 for lowercase i with circonflex. This is currently not supported // by the engine. const fheroes2::Sprite firstSprite{ imageArray[0] }; imageArray.insert( imageArray.begin() + 96, 128, firstSprite ); // Capital letters with accents aren't present in the original assets so we use unaccented letters. imageArray[192 - 32] = imageArray[33]; imageArray[199 - 32] = imageArray[35]; imageArray[201 - 32] = imageArray[37]; imageArray[202 - 32] = imageArray[37]; imageArray[224 - 32] = imageArray[32]; imageArray[226 - 32] = imageArray[10]; imageArray[231 - 32] = imageArray[62]; imageArray[232 - 32] = imageArray[64]; imageArray[233 - 32] = imageArray[94]; imageArray[234 - 32] = imageArray[92]; imageArray[239 - 32] = imageArray[91]; imageArray[244 - 32] = imageArray[3]; imageArray[249 - 32] = imageArray[6]; imageArray[251 - 32] = imageArray[4]; // The original small font has 1 letter at three indexes (30, 93, 95) that has an empty wide transparent // area that we need to remove. Plus we need to add a missing pixel. if ( id == ICN::SMALFONT && imageArray[93].width() > 19 ) { imageArray[238 - 32].resize( 4, 9 ); imageArray[238 - 32].reset(); Copy( imageArray[93], 0, 0, imageArray[238 - 32], 0, 1, 4, 8 ); Copy( imageArray[93], 1, 0, imageArray[238 - 32], 2, 0, 1, 1 ); imageArray[238 - 32].setPosition( 0, -1 ); fheroes2::updateShadow( imageArray[238 - 32], { -1, 1 }, 2, true ); // Copy the fixed sprite back. for ( const int charCode : { 30, 93, 95 } ) { imageArray[charCode] = imageArray[238 - 32]; } } else { imageArray[238 - 32] = imageArray[93]; } imageArray.erase( imageArray.begin() + 220, imageArray.end() ); } // Italian version uses CP1252 if ( crc32 == 0x219B3124 || crc32 == 0x1F3C3C74 ) { const fheroes2::Sprite firstSprite{ imageArray[0] }; imageArray.insert( imageArray.begin() + 101, 123, firstSprite ); imageArray[192 - 32] = imageArray[33]; imageArray[200 - 32] = imageArray[37]; imageArray[201 - 32] = imageArray[37]; imageArray[204 - 32] = imageArray[41]; imageArray[210 - 32] = imageArray[47]; imageArray[217 - 32] = imageArray[53]; imageArray[224 - 32] = imageArray[96]; imageArray[232 - 32] = imageArray[97]; imageArray[233 - 32] = imageArray[69]; imageArray[236 - 32] = imageArray[98]; imageArray[242 - 32] = imageArray[99]; imageArray[249 - 32] = imageArray[100]; imageArray.erase( imageArray.begin() + 218, imageArray.end() ); } return true; } case ICN::YELLOW_FONT: CopyICNWithPalette( id, ICN::FONT, PAL::PaletteType::YELLOW_FONT ); return true; case ICN::YELLOW_SMALLFONT: CopyICNWithPalette( id, ICN::SMALFONT, PAL::PaletteType::YELLOW_FONT ); return true; case ICN::GRAY_FONT: CopyICNWithPalette( id, ICN::FONT, PAL::PaletteType::GRAY_FONT ); return true; case ICN::GRAY_SMALL_FONT: CopyICNWithPalette( id, ICN::SMALFONT, PAL::PaletteType::GRAY_FONT ); return true; case ICN::GOLDEN_GRADIENT_FONT: generateGradientFont( id, ICN::FONT, 108, 133, 55, 62 ); return true; case ICN::GOLDEN_GRADIENT_LARGE_FONT: generateGradientFont( id, ICN::WHITE_LARGE_FONT, 108, 127, 55, 62 ); return true; case ICN::SILVER_GRADIENT_FONT: generateGradientFont( id, ICN::FONT, 10, 31, 29, 0 ); return true; case ICN::SILVER_GRADIENT_LARGE_FONT: generateGradientFont( id, ICN::WHITE_LARGE_FONT, 10, 26, 29, 0 ); return true; case ICN::SPELLS: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() != 60 ) { return true; } _icnVsSprite[id].resize( 73 ); for ( uint32_t i = 60; i < 66; ++i ) { // Mass Cure spell. ( when i == 60 ). size_t originalIndex = 6; if ( i == 61 ) { // Mass Haste spell. originalIndex = 14; } else if ( i == 62 ) { // Mass Slow spell. originalIndex = 1; } else if ( i == 63 ) { // Mass Bless spell. originalIndex = 7; } else if ( i == 64 ) { // Mass Curse spell. originalIndex = 3; } else if ( i == 65 ) { // Mass Shield spell. originalIndex = 15; } const fheroes2::Sprite & originalImage = _icnVsSprite[id][originalIndex]; fheroes2::Sprite & image = _icnVsSprite[id][i]; image.resize( originalImage.width() + 8, originalImage.height() + 8 ); image.setPosition( originalImage.x() + 4, originalImage.y() + 4 ); image.fill( 1 ); AlphaBlit( originalImage, image, 0, 0, 128 ); AlphaBlit( originalImage, image, 4, 4, 192 ); Blit( originalImage, image, 8, 8 ); AddTransparency( image, 1 ); } // The Petrification spell does not have its own icon in the original game. fheroes2::h2d::readImage( "petrification_spell_icon.image", _icnVsSprite[id][66] ); // Generate random spell image for Editor. { const fheroes2::Sprite & randomSpellImage = _icnVsSprite[id][2]; const int32_t imageWidth = randomSpellImage.width(); Copy( randomSpellImage, _icnVsSprite[id][67] ); // Add text on random spell images. for ( uint32_t i = 1; i < 6; ++i ) { fheroes2::Sprite & originalImage = _icnVsSprite[id][i + 67]; Copy( randomSpellImage, originalImage ); const fheroes2::Text text( std::to_string( i ), fheroes2::FontType::normalWhite() ); text.draw( ( imageWidth - text.width() ) / 2, 22, originalImage ); } } return true; case ICN::CSLMARKER: _icnVsSprite[id].resize( 3 ); for ( uint32_t i = 0; i < 3; ++i ) { _icnVsSprite[id][i] = fheroes2::AGG::GetICN( ICN::LOCATORS, 24 ); if ( i == 1 ) { ReplaceColorId( _icnVsSprite[id][i], 0x0A, 0xD6 ); } else if ( i == 2 ) { ReplaceColorId( _icnVsSprite[id][i], 0x0A, 0xDE ); } } return true; case ICN::PHOENIX: LoadOriginalICN( id ); // First sprite has cropped shadow. We copy missing part from another 'almost' identical frame if ( _icnVsSprite[id].size() >= 32 ) { const fheroes2::Sprite & in = _icnVsSprite[id][32]; Copy( in, 60, 73, _icnVsSprite[id][1], 60, 73, 14, 13 ); Copy( in, 56, 72, _icnVsSprite[id][30], 56, 72, 18, 9 ); } return true; case ICN::MONH0028: // phoenix LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 1 ) { const fheroes2::Sprite & correctFrame = fheroes2::AGG::GetICN( ICN::PHOENIX, 32 ); Copy( correctFrame, 60, 73, _icnVsSprite[id][0], 58, 70, 14, 13 ); } return true; case ICN::CAVALRYR: LoadOriginalICN( id ); // fheroes2::Sprite 23 has incorrect colors, we need to replace them if ( _icnVsSprite[id].size() >= 23 ) { fheroes2::Sprite & out = _icnVsSprite[id][23]; std::vector indexes( 256 ); std::iota( indexes.begin(), indexes.end(), static_cast( 0 ) ); indexes[69] = 187; indexes[71] = 195; indexes[73] = 188; indexes[74] = 190; indexes[75] = 193; indexes[76] = 191; indexes[77] = 195; indexes[80] = 195; indexes[81] = 196; indexes[83] = 196; indexes[84] = 197; indexes[151] = 197; ApplyPalette( out, indexes ); } return true; case ICN::TITANMSL: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 7 ) { // We need to shift Titan lightning arrow sprite position to correctly render it. _icnVsSprite[id][0].setPosition( _icnVsSprite[id][0].x(), _icnVsSprite[id][0].y() - 5 ); _icnVsSprite[id][1].setPosition( _icnVsSprite[id][1].x() - 5, _icnVsSprite[id][1].y() - 5 ); _icnVsSprite[id][2].setPosition( _icnVsSprite[id][2].x() - 10, _icnVsSprite[id][2].y() ); _icnVsSprite[id][3].setPosition( _icnVsSprite[id][3].x() - 15, _icnVsSprite[id][3].y() ); _icnVsSprite[id][4].setPosition( _icnVsSprite[id][4].x() - 10, _icnVsSprite[id][2].y() ); _icnVsSprite[id][5].setPosition( _icnVsSprite[id][5].x() - 5, _icnVsSprite[id][5].y() - 5 ); _icnVsSprite[id][6].setPosition( _icnVsSprite[id][6].x(), _icnVsSprite[id][6].y() - 5 ); } return true; case ICN::TROLLMSL: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 1 ) { fheroes2::Sprite & out = _icnVsSprite[id][0]; // The original sprite contains 2 pixels which are empty if ( out.width() * out.height() > 188 && out.transform()[147] == 1 && out.transform()[188] == 1 ) { out.transform()[147] = 0; out.image()[147] = 22; out.transform()[188] = 0; out.image()[188] = 24; } } return true; case ICN::TROLL2MSL: loadICN( ICN::TROLLMSL ); if ( _icnVsSprite[ICN::TROLLMSL].size() == 1 ) { _icnVsSprite[id].resize( 1 ); fheroes2::Sprite & out = _icnVsSprite[id][0]; out = _icnVsSprite[ICN::TROLLMSL][0]; // The original sprite contains 2 pixels which are empty if ( out.width() * out.height() > 188 && out.transform()[147] == 1 && out.transform()[188] == 1 ) { out.transform()[147] = 0; out.image()[147] = 22; out.transform()[188] = 0; out.image()[188] = 24; } std::vector indexes( 256 ); std::iota( indexes.begin(), indexes.end(), static_cast( 0 ) ); indexes[10] = 152; indexes[11] = 153; indexes[12] = 154; indexes[13] = 155; indexes[14] = 155; indexes[15] = 156; indexes[16] = 157; indexes[17] = 158; indexes[18] = 159; indexes[19] = 160; indexes[20] = 160; indexes[21] = 161; indexes[22] = 162; indexes[23] = 163; indexes[24] = 164; indexes[25] = 165; indexes[26] = 166; indexes[27] = 166; indexes[28] = 167; indexes[29] = 168; indexes[30] = 169; indexes[31] = 170; indexes[32] = 171; indexes[33] = 172; indexes[34] = 172; indexes[35] = 173; ApplyPalette( out, indexes ); } return true; case ICN::GOLEM: case ICN::GOLEM2: LoadOriginalICN( id ); // Original Golem ICN contains 40 frames. We make the corrections only for original sprite. if ( _icnVsSprite[id].size() == 40 ) { // Movement animation fix for Iron and Steel Golem: its 'MOVE_MAIN' animation is missing 1/4 of animation start. // The 'MOVE_START' (for first and one cell move) has this 1/4 of animation, but 'MOVE_TILE_START` is empty, // so we make a copy of 'MOVE_MAIN' frames to the end of sprite vector and correct their 'x' coordinate // to cover the whole cell except the last frame, that has correct coordinates. const size_t golemICNSize = _icnVsSprite[id].size(); // 'MOVE_MAIN' has 7 frames and we copy only first 6. const int32_t copyFramesNum = 6; _icnVsSprite[id].reserve( golemICNSize + copyFramesNum ); // 'MOVE_MAIN' frames starts from the 6th frame in Golem ICN sprites. size_t copyFrame = 6; for ( int32_t i = 0; i < copyFramesNum; ++i, ++copyFrame ) { // IMPORTANT: we MUST do a copy of a vector element if we want to insert it to the same vector. fheroes2::Sprite originalFrame = _icnVsSprite[id][copyFrame]; _icnVsSprite[id].emplace_back( std::move( originalFrame ) ); const size_t frameID = golemICNSize + i; // We have 7 'MOVE_MAIN' frames and 1/4 of cell to expand the horizontal movement, so we shift the first copied frame by // "6 * Battle::Cell::widthPx / ( 4 * 7 )" to the left and reduce this shift every next frame by "Battle::Cell::widthPx / ( 7 * 4 )". _icnVsSprite[id][frameID].setPosition( _icnVsSprite[id][frameID].x() - ( copyFramesNum - i ) * Battle::Cell::widthPx / 28, _icnVsSprite[id][frameID].y() ); } } return true; case ICN::LOCATORE: case ICN::LOCATORS: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 15 ) { if ( _icnVsSprite[id][12].width() == 47 ) { fheroes2::Sprite & out = _icnVsSprite[id][12]; out = Crop( out, 0, 0, out.width() - 1, out.height() ); } if ( _icnVsSprite[id][15].width() == 47 ) { fheroes2::Sprite & out = _icnVsSprite[id][15]; out = Crop( out, 0, 0, out.width() - 1, out.height() ); } } if ( _icnVsSprite[id].size() == 25 ) { // Add random town and castle icons for Editor. // A temporary solution: blurred Wizard castle/town in purple palette. _icnVsSprite[id].resize( 27 ); _icnVsSprite[id][25] = CreateHolyShoutEffect( _icnVsSprite[id][13], 1, 0 ); _icnVsSprite[id][26] = CreateHolyShoutEffect( _icnVsSprite[id][19], 1, 0 ); ApplyPalette( _icnVsSprite[id][25], PAL::GetPalette( PAL::PaletteType::PURPLE ) ); ApplyPalette( _icnVsSprite[id][26], PAL::GetPalette( PAL::PaletteType::PURPLE ) ); // Add the '?' mark above the image. const fheroes2::Text text( "? ? ?", fheroes2::FontType::normalWhite() ); text.draw( ( _icnVsSprite[id][25].width() - text.width() ) / 2, 6, _icnVsSprite[id][25] ); text.draw( ( _icnVsSprite[id][26].width() - text.width() ) / 2, 6, _icnVsSprite[id][26] ); } return true; case ICN::TOWNBKG2: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 1 ) { fheroes2::Sprite & out = _icnVsSprite[id][0]; // The first pixel of the original sprite has incorrect color. if ( !out.empty() ) { out._disableTransformLayer(); out.image()[0] = 10; } } return true; case ICN::HSICONS: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 7 ) { fheroes2::Sprite & out = _icnVsSprite[id][7]; if ( out.width() == 34 && out.height() == 19 ) { fheroes2::Sprite temp; std::swap( temp, out ); out.resize( temp.width() + 1, temp.height() ); out.reset(); Copy( temp, 0, 0, out, 1, 0, temp.width(), temp.height() ); Copy( temp, temp.width() - 1, 10, out, 0, 10, 1, 3 ); } } return true; case ICN::MONS32: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 4 ) { // Veteran Pikeman fheroes2::Sprite & modified = _icnVsSprite[id][4]; fheroes2::Sprite temp( modified.width(), modified.height() + 1 ); temp.reset(); Blit( modified, 0, 0, temp, 0, 1, modified.width(), modified.height() ); modified = std::move( temp ); Fill( modified, 7, 0, 4, 1, 36 ); } if ( _icnVsSprite[id].size() > 6 ) { // Master Swordsman fheroes2::Sprite & modified = _icnVsSprite[id][6]; fheroes2::Sprite temp( modified.width(), modified.height() + 1 ); temp.reset(); Blit( modified, 0, 0, temp, 0, 1, modified.width(), modified.height() ); modified = std::move( temp ); Fill( modified, 2, 0, 5, 1, 36 ); } if ( _icnVsSprite[id].size() > 8 ) { // Champion fheroes2::Sprite & modified = _icnVsSprite[id][8]; fheroes2::Sprite temp( modified.width(), modified.height() + 1 ); temp.reset(); Blit( modified, 0, 0, temp, 0, 1, modified.width(), modified.height() ); modified = std::move( temp ); Fill( modified, 12, 0, 5, 1, 36 ); } if ( _icnVsSprite[id].size() > 33 ) { // Minotaur King original mini sprite has blue armlets. We make them gold to correspond the ICN::MINOTAU2. fheroes2::Sprite & modified = _icnVsSprite[id][33]; if ( modified.width() == 20 && modified.height() == 36 ) { // We update these pixels: 6x16, 7x16, 8x16, 5x17, 6x17, 7x17, 8x17, 6x18, 7x18, 14x18, 14x19. for ( const uint32_t pixelNumber : { 326, 327, 328, 345, 346, 347, 348, 366, 367, 374, 394 } ) { // The gold color gradient has -42 offset from blue color gradient. modified.image()[pixelNumber] -= 42; } } } if ( _icnVsSprite[id].size() > 62 ) { const fheroes2::Point shadowOffset( -1, 2 ); for ( size_t i = 0; i < 62; ++i ) { fheroes2::Sprite & modified = _icnVsSprite[id][i]; const fheroes2::Point originalOffset( modified.x(), modified.y() ); fheroes2::Sprite temp = addShadow( modified, { -1, 2 }, 2 ); temp.setPosition( originalOffset.x - 1, originalOffset.y + 2 ); const fheroes2::Rect area = GetActiveROI( temp, 2 ); if ( area.x > 0 || area.height != temp.height() ) { const fheroes2::Point offset( temp.x() - area.x, temp.y() - temp.height() + area.y + area.height ); modified = Crop( temp, area.x, area.y, area.width, area.height ); modified.setPosition( offset.x, offset.y ); } else { modified = std::move( temp ); } } } if ( _icnVsSprite[id].size() > 63 && _icnVsSprite[id][63].width() == 19 && _icnVsSprite[id][63].height() == 37 ) { // Air Elemental fheroes2::Sprite & modified = _icnVsSprite[id][63]; modified.image()[19 * 9 + 9] = modified.image()[19 * 5 + 11]; modified.transform()[19 * 9 + 9] = modified.transform()[19 * 5 + 11]; } return true; case ICN::MONSTER_SWITCH_LEFT_ARROW: _icnVsSprite[id].resize( 2 ); for ( uint32_t i = 0; i < 2; ++i ) { const fheroes2::Sprite & source = fheroes2::AGG::GetICN( ICN::RECRUIT, i ); fheroes2::Sprite & out = _icnVsSprite[id][i]; out.resize( source.height(), source.width() ); Transpose( source, out ); out = Flip( out, false, true ); out.setPosition( source.y() - static_cast( i ), source.x() ); } return true; case ICN::MONSTER_SWITCH_RIGHT_ARROW: _icnVsSprite[id].resize( 2 ); for ( uint32_t i = 0; i < 2; ++i ) { const fheroes2::Sprite & source = fheroes2::AGG::GetICN( ICN::RECRUIT, i + 2 ); fheroes2::Sprite & out = _icnVsSprite[id][i]; out.resize( source.height(), source.width() ); Transpose( source, out ); out = Flip( out, false, true ); out.setPosition( source.y(), source.x() ); } return true; case ICN::SURRENDR: case ICN::SURRENDE: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 4 ) { if ( id == ICN::SURRENDR ) { // Fix incorrect font color on good ACCEPT button. ReplaceColorId( _icnVsSprite[id][0], 28, 56 ); } // Fix pressed buttons background. for ( const uint32_t i : { 0, 2 } ) { fheroes2::Sprite & out = _icnVsSprite[id][i + 1]; fheroes2::Sprite tmp( out.width(), out.height() ); tmp.reset(); Copy( out, 0, 1, tmp, 1, 0, tmp.width() - 1, tmp.height() - 1 ); CopyTransformLayer( _icnVsSprite[id][i], tmp ); out.reset(); Copy( tmp, 1, 0, out, 0, 1, tmp.width() - 1, tmp.height() - 1 ); } } return true; case ICN::NON_UNIFORM_GOOD_RESTART_BUTTON: _icnVsSprite[id].resize( 2 ); _icnVsSprite[id][0] = Crop( fheroes2::AGG::GetICN( ICN::CAMPXTRG, 2 ), 6, 0, 108, 25 ); _icnVsSprite[id][0].setPosition( 0, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::CAMPXTRG, 3 ); _icnVsSprite[id][1].setPosition( 0, 0 ); // fix transparent corners CopyTransformLayer( _icnVsSprite[id][1], _icnVsSprite[id][0] ); return true; case ICN::NON_UNIFORM_EVIL_RESTART_BUTTON: _icnVsSprite[id].resize( 2 ); _icnVsSprite[id][0] = Crop( fheroes2::AGG::GetICN( ICN::CAMPXTRE, 2 ), 4, 0, 108, 25 ); _icnVsSprite[id][0].setPosition( 0, 0 ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::CAMPXTRE, 3 ); _icnVsSprite[id][1].setPosition( 0, 0 ); // fix transparent corners CopyTransformLayer( _icnVsSprite[id][1], _icnVsSprite[id][0] ); return true; case ICN::WHITE_LARGE_FONT: { fheroes2::AGG::GetICN( ICN::FONT, 0 ); const std::vector & original = _icnVsSprite[ICN::FONT]; _icnVsSprite[id].resize( original.size() ); for ( size_t i = 0; i < _icnVsSprite[id].size(); ++i ) { const fheroes2::Sprite & in = original[i]; fheroes2::Sprite & out = _icnVsSprite[id][i]; out.resize( in.width() * 2, in.height() * 2 ); SubpixelResize( in, out ); out.setPosition( in.x() * 2, in.y() * 2 ); } return true; } case ICN::SWAP_ARROW_LEFT_TO_RIGHT: case ICN::SWAP_ARROW_RIGHT_TO_LEFT: { // Since the original game does not have such resources we could generate it from hero meeting sprite. const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); std::array input; const int32_t width = 45; const int32_t height = 20; for ( fheroes2::Image & image : input ) { image.resize( width, height ); } Copy( original, 295, 270, input[0], 0, 0, width, height ); Copy( original, 295, 291, input[1], 0, 0, width, height ); Copy( original, 295, 363, input[2], 0, 0, width, height ); Copy( original, 295, 384, input[3], 0, 0, width, height ); input[1] = Flip( input[1], true, false ); input[3] = Flip( input[3], true, false ); fheroes2::Image out = fheroes2::ExtractCommonPattern( { &input[0], &input[1], &input[2], &input[3] } ); // Here are 2 pixels which should be removed. if ( out.width() == width && out.height() == height ) { out.image()[40] = 0; out.transform()[40] = 1; out.image()[30 + 3 * width] = 0; out.transform()[30 + 3 * width] = 1; } _icnVsSprite[id].resize( 2 ); _icnVsSprite[id][0] = ( id == ICN::SWAP_ARROW_LEFT_TO_RIGHT ) ? out : Flip( out, true, false ); _icnVsSprite[id][1] = _icnVsSprite[id][0]; _icnVsSprite[id][1].setPosition( -1, 1 ); ApplyPalette( _icnVsSprite[id][1], 4 ); return true; } case ICN::SWAP_ARROWS_CIRCULAR: { const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::SWAP_ARROW_LEFT_TO_RIGHT, 0 ); const int32_t width = 47; const int32_t height = 42; fheroes2::Image out; out.resize( width, height ); out.reset(); // Rotate arrow heads. const int32_t arrowTipToShaftLength = 18; const int32_t arrowHeadWidth = 20; fheroes2::Image rotatedArrow; rotatedArrow.resize( arrowHeadWidth, arrowTipToShaftLength ); rotatedArrow.reset(); for ( int x = 0; x < arrowTipToShaftLength; ++x ) { for ( int y = 0; y < arrowHeadWidth; ++y ) { Copy( original, x + ( original.width() - arrowTipToShaftLength ), y, rotatedArrow, arrowHeadWidth - y - 1, arrowTipToShaftLength - x - 1, 1, 1 ); } } fheroes2::Copy( Flip( rotatedArrow, true, true ), 0, 0, out, 0, 5, arrowHeadWidth, arrowTipToShaftLength ); fheroes2::Copy( Flip( rotatedArrow, true, false ), 0, 0, out, 27, 19, arrowHeadWidth, arrowTipToShaftLength ); // Rotate arrow ends. const int32_t arrowEndHeight = 11; const int32_t arrowEndWidth = 9; rotatedArrow.resize( arrowEndWidth, arrowEndHeight ); rotatedArrow.reset(); for ( int x = 0; x < arrowEndHeight; ++x ) { for ( int y = 0; y < arrowEndWidth; ++y ) { Copy( original, x + 2, y + 5, rotatedArrow, arrowEndWidth - y - 1, arrowEndHeight - x - 1, 1, 1 ); } } // Clean black corner. fheroes2::Copy( original, 0, 0, rotatedArrow, 0, rotatedArrow.height() - 1, 1, 1 ); fheroes2::Copy( rotatedArrow, 0, 0, out, 32, 6, arrowEndWidth, arrowEndHeight ); fheroes2::Copy( Flip( rotatedArrow, false, true ), 0, 0, out, 5, 25, arrowEndWidth, arrowEndHeight ); // Add straight shafts. Copy( original, 5, 5, out, 13, 0, 21, 10 ); Copy( original, 5, 5, out, 12, 32, 22, 10 ); // Lower arrow. // Fix overlaps. fheroes2::SetPixel( out, out.width() - 9, out.height() - 5, 119 ); fheroes2::DrawLine( out, { out.width() - 13, out.height() - 6 }, { out.width() - 12, out.height() - 6 }, 109 ); fheroes2::SetPixel( out, 12, out.height() - 10, 119 ); fheroes2::SetPixel( out, out.width() - 14, out.height() - 10, 119 ); // Lower right corner. Copy( original, 5, 10, out, out.width() - 13, out.height() - 5, 4, 5 ); fheroes2::DrawLine( out, { out.width() - 6, out.height() - 4 }, { out.width() - 9, out.height() - 1 }, 59 ); fheroes2::DrawLine( out, { out.width() - 6, out.height() - 5 }, { out.width() - 9, out.height() - 2 }, 59 ); fheroes2::DrawLine( out, { out.width() - 7, out.height() - 5 }, { out.width() - 9, out.height() - 3 }, 129 ); fheroes2::DrawLine( out, { out.width() - 8, out.height() - 5 }, { out.width() - 9, out.height() - 4 }, 123 ); fheroes2::SetPixel( out, out.width() - 9, out.height() - 5, 119 ); fheroes2::SetPixel( out, out.width() - 11, out.height() - 6, 112 ); // Lower left corner. Copy( original, 5, 9, out, 9, out.height() - 6, 3, 6 ); Copy( rotatedArrow, 0, 0, out, 5, out.height() - 7, 4, 2 ); fheroes2::DrawLine( out, { 5, out.height() - 5 }, { 8, out.height() - 2 }, 129 ); fheroes2::DrawLine( out, { 6, out.height() - 5 }, { 8, out.height() - 3 }, 123 ); fheroes2::DrawLine( out, { 7, out.height() - 5 }, { 8, out.height() - 4 }, 119 ); fheroes2::SetPixel( out, 8, out.height() - 5, 116 ); fheroes2::SetPixel( out, 9, out.height() - 6, 112 ); // Fix shading. fheroes2::DrawLine( out, { 14, out.height() - 15 }, { 14, out.height() - 11 }, 59 ); // Upper arrow. // Upper left corner. fheroes2::Copy( out, 15, 0, out, 9, 0, 4, 5 ); fheroes2::Copy( out, 21, 5, out, 11, 5, 3, 2 ); fheroes2::DrawLine( out, { 8, 1 }, { 5, 4 }, 129 ); fheroes2::DrawLine( out, { 8, 2 }, { 6, 4 }, 119 ); fheroes2::DrawLine( out, { 8, 3 }, { 7, 4 }, 114 ); fheroes2::SetPixel( out, 8, 4, 112 ); fheroes2::SetPixel( out, 9, 4, 112 ); // Upper right corner. fheroes2::Copy( out, 21, 0, out, 33, 0, 3, 6 ); fheroes2::Copy( out, 36, 7, out, 36, 5, 5, 1 ); fheroes2::Copy( out, 37, 6, out, 37, 4, 3, 1 ); fheroes2::Copy( out, 37, 6, out, 37, 4, 3, 1 ); fheroes2::Copy( out, 34, 1, out, 36, 1, 1, 3 ); fheroes2::DrawLine( out, { 36, 0 }, { 40, 4 }, 129 ); fheroes2::DrawLine( out, { 37, 2 }, { 38, 3 }, 119 ); fheroes2::DrawLine( out, { 36, 4 }, { 37, 3 }, 113 ); // Fix overlap. fheroes2::DrawLine( out, { 33, 8 }, { 33, 9 }, 123 ); fheroes2::SetPixel( out, 32, 9, 129 ); fheroes2::SetPixel( out, 13, 9, 129 ); // Fix shading. fheroes2::DrawLine( out, { 10, 22 }, { 18, 14 }, 59 ); fheroes2::DrawLine( out, { 11, 22 }, { 19, 14 }, 59 ); fheroes2::DrawLine( out, { 34, 17 }, { 40, 17 }, 59 ); fheroes2::DrawLine( out, { 41, 5 }, { 41, 16 }, 59 ); fheroes2::SetPixel( out, 40, 16, 59 ); fheroes2::Copy( original, 0, 0, out, 1, 12, 4, 1 ); fheroes2::Copy( original, 0, 0, out, 15, 12, 5, 1 ); // Make pressed state. _icnVsSprite[id].resize( 2 ); _icnVsSprite[id][0] = out; _icnVsSprite[id][1] = _icnVsSprite[id][0]; _icnVsSprite[id][1].setPosition( -1, 1 ); ApplyPalette( _icnVsSprite[id][1], 4 ); return true; } case ICN::EDITBTNS: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 35 ) { // We add three buttons for new object groups: Adventure, Kingdom, Monsters. _icnVsSprite[id].resize( 45 ); // First make clean button sprites (pressed and released). fheroes2::Sprite released = fheroes2::AGG::GetICN( ICN::EDITBTNS, 4 ); fheroes2::Sprite pressed = fheroes2::AGG::GetICN( ICN::EDITBTNS, 5 ); // Clean the image from the button. Fill( released, 16, 6, 18, 24, 41U ); Fill( pressed, 16, 7, 17, 23, 46U ); for ( size_t i = 0; i < 8; i += 2 ) { _icnVsSprite[id][35 + i] = released; _icnVsSprite[id][35 + 1 + i] = pressed; } _icnVsSprite[id][43] = std::move( released ); _icnVsSprite[id][44] = std::move( pressed ); // Adventure objects button. drawImageOnButton( fheroes2::AGG::GetICN( ICN::X_LOC1, 0 ), 39, 29, _icnVsSprite[id][35], _icnVsSprite[id][36] ); // Kingdom objects button. drawImageOnButton( fheroes2::AGG::GetICN( ICN::OBJNARTI, 13 ), 39, 29, _icnVsSprite[id][37], _icnVsSprite[id][38] ); // Monsters objects button. drawImageOnButton( fheroes2::AGG::GetICN( ICN::MONS32, 11 ), 39, 29, _icnVsSprite[id][39], _icnVsSprite[id][40] ); // Undo and Redo buttons. fheroes2::Image undoImage( 19, 13 ); undoImage.reset(); const int mainColor = 56; fheroes2::SetPixel( undoImage, 0, 6, mainColor ); for ( int x = 1; x < 7; ++x ) { fheroes2::DrawLine( undoImage, { x, 6 - x }, { x, 6 + x }, mainColor ); } fheroes2::Fill( undoImage, 7, 4, 9, 5, mainColor ); fheroes2::SetPixel( undoImage, 16, 5, mainColor ); fheroes2::Fill( undoImage, 16, 6, 2, 4, mainColor ); fheroes2::Fill( undoImage, 17, 8, 2, 4, mainColor ); fheroes2::SetPixel( undoImage, 18, 12, mainColor ); drawImageOnButton( undoImage, 39, 29, _icnVsSprite[id][41], _icnVsSprite[id][42] ); drawImageOnButton( fheroes2::Flip( undoImage, true, false ), 39, 29, _icnVsSprite[id][43], _icnVsSprite[id][44] ); // Fix shadow pixels fheroes2::SetPixel( _icnVsSprite[id][43], 27, 11, 41 ); fheroes2::SetPixel( _icnVsSprite[id][44], 26, 12, 46 ); fheroes2::SetPixel( _icnVsSprite[id][43], 16, 17, 47 ); fheroes2::SetPixel( _icnVsSprite[id][44], 15, 18, 52 ); // Add aliasing fheroes2::SetPixel( _icnVsSprite[id][41], 32, 19, 52 ); fheroes2::DrawLine( _icnVsSprite[id][41], { 33, 20 }, { 33, 21 }, 52 ); fheroes2::SetPixel( _icnVsSprite[id][42], 31, 20, 53 ); fheroes2::DrawLine( _icnVsSprite[id][42], { 32, 21 }, { 32, 22 }, 53 ); } return true; case ICN::EDITBTNS_EVIL: { loadICN( ICN::EDITBTNS ); _icnVsSprite[id] = _icnVsSprite[ICN::EDITBTNS]; for ( auto & image : _icnVsSprite[id] ) { convertToEvilInterface( image, { 0, 0, image.width(), image.height() } ); } return true; } case ICN::DROPLISL_EVIL: { loadICN( ICN::DROPLISL ); _icnVsSprite[id] = _icnVsSprite[ICN::DROPLISL]; // To convert the yellow borders of the drop list the combination of good-to-evil and gray palettes is used here. const std::vector palette = PAL::CombinePalettes( PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ), PAL::GetPalette( PAL::PaletteType::GRAY ) ); for ( auto & image : _icnVsSprite[id] ) { fheroes2::ApplyPalette( image, 0, 0, image, 0, 0, image.width(), image.height(), palette ); } return true; } case ICN::CELLWIN_EVIL: { loadICN( ICN::CELLWIN ); if ( _icnVsSprite[ICN::CELLWIN].size() > 18 ) { // Convert to Evil only the first 19 images. The rest are not standard buttons and are player color related settings used in original editor. _icnVsSprite[ICN::CELLWIN_EVIL].resize( 19 ); std::copy( _icnVsSprite[ICN::CELLWIN].begin(), _icnVsSprite[ICN::CELLWIN].begin() + 19, _icnVsSprite[ICN::CELLWIN_EVIL].begin() ); // To convert the yellow borders of some items the combination of good-to-evil and gray palettes is used here. const std::vector palette = PAL::CombinePalettes( PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ), PAL::GetPalette( PAL::PaletteType::GRAY ) ); for ( fheroes2::Sprite & image : _icnVsSprite[ICN::CELLWIN_EVIL] ) { fheroes2::ApplyPalette( image, 0, 0, image, 0, 0, image.width(), image.height(), palette ); } } return true; } case ICN::EDITPANL: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 6 ) { _icnVsSprite[id].resize( 18 ); // Make empty buttons for object types. _icnVsSprite[id][6].resize( 27, 27 ); _icnVsSprite[id][6]._disableTransformLayer(); _icnVsSprite[id][6].reset(); Fill( _icnVsSprite[id][6], 1, 1, 24, 24, 65U ); for ( size_t i = 7; i < _icnVsSprite[id].size(); ++i ) { _icnVsSprite[id][i] = _icnVsSprite[id][6]; } // Make Mountains objects button. Blit( fheroes2::AGG::GetICN( ICN::MTNCRCK, 3 ), 4, 0, _icnVsSprite[id][6], 1, 1, 24, 24 ); // Make Rocks objects button. Blit( fheroes2::AGG::GetICN( ICN::OBJNGRAS, 41 ), 1, 0, _icnVsSprite[id][7], 1, 9, 23, 12 ); // Make Trees object button. Also used as erase terrain objects button image. Copy( fheroes2::AGG::GetICN( ICN::EDITBTNS, 2 ), 13, 4, _icnVsSprite[id][8], 1, 1, 24, 24 ); // Replace image contour colors with the background color. std::vector indexes( 256 ); std::iota( indexes.begin(), indexes.end(), static_cast( 0 ) ); indexes[10] = 65U; indexes[38] = 65U; indexes[39] = 65U; indexes[40] = 65U; indexes[41] = 65U; indexes[46] = 65U; ApplyPalette( _icnVsSprite[id][8], indexes ); // Make Landscape Water objects button. Blit( fheroes2::AGG::GetICN( ICN::OBJNWAT2, 0 ), 0, 3, _icnVsSprite[id][9], 5, 1, 13, 3 ); Blit( fheroes2::AGG::GetICN( ICN::OBJNWAT2, 2 ), 5, 0, _icnVsSprite[id][9], 1, 4, 24, 21 ); // Make Landscape Miscellaneous objects button. Blit( fheroes2::AGG::GetICN( ICN::OBJNDIRT, 73 ), 8, 0, _icnVsSprite[id][10], 1, 1, 24, 24 ); // Make Dwellings button image. Blit( fheroes2::AGG::GetICN( ICN::OBJNMULT, 114 ), 7, 0, _icnVsSprite[id][11], 1, 1, 24, 24 ); // Make Mines button image. Blit( fheroes2::AGG::GetICN( ICN::MTNMULT, 82 ), 8, 4, _icnVsSprite[id][12], 1, 1, 24, 24 ); // Make Power-ups button image. Blit( fheroes2::AGG::GetICN( ICN::OBJNMULT, 72 ), 0, 6, _icnVsSprite[id][13], 1, 1, 24, 24 ); // Make Adventure Water objects button. Blit( fheroes2::AGG::GetICN( ICN::OBJNWATR, 24 ), 3, 0, _icnVsSprite[id][14], 1, 1, 24, 24 ); // Make Adventure Miscellaneous objects button. Blit( fheroes2::AGG::GetICN( ICN::OBJNMUL2, 198 ), 2, 0, _icnVsSprite[id][15], 1, 1, 24, 24 ); // Make erase Roads button image. Blit( fheroes2::AGG::GetICN( ICN::ROAD, 2 ), 0, 0, _icnVsSprite[id][16], 1, 8, 24, 5 ); Blit( fheroes2::AGG::GetICN( ICN::ROAD, 1 ), 1, 0, _icnVsSprite[id][16], 1, 13, 24, 5 ); // Make erase Streams button image. Blit( fheroes2::AGG::GetICN( ICN::STREAM, 2 ), 0, 0, _icnVsSprite[id][17], 1, 8, 24, 11 ); } return true; case ICN::TWNWUP_5: case ICN::EDITOR: LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { // Fix the cycling colors in original editor main menu background and Red Tower (Warlock castle screen). ApplyPalette( _icnVsSprite[id].front(), PAL::GetPalette( PAL::PaletteType::NO_CYCLE ) ); } return true; case ICN::MINIHERO: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 42 ) { const auto & noCyclePalette = PAL::GetPalette( PAL::PaletteType::NO_CYCLE ); // Fix cycling colors on the Green heroes' flag for Knight, Sorceress and Warlock. ApplyPalette( _icnVsSprite[id][7], noCyclePalette ); ApplyPalette( _icnVsSprite[id][9], noCyclePalette ); ApplyPalette( _icnVsSprite[id][10], noCyclePalette ); // Fix cycling colors on the Yellow heroes' flag. for ( size_t i = 21; i < 28; ++i ) { ApplyPalette( _icnVsSprite[id][i], noCyclePalette ); } // Fix Blue Random hero flag. Copy( _icnVsSprite[id][5], 1, 4, _icnVsSprite[id][6], 1, 4, 17, 7 ); // Fix Orange Necromancer hero flag. Copy( _icnVsSprite[id][32], 5, 4, _icnVsSprite[id][33], 5, 4, 14, 7 ); // Fix Orange Random hero flag (in original assets he has a purple flag). Copy( _icnVsSprite[id][32], 2, 4, _icnVsSprite[id][34], 2, 4, 16, 7 ); // Fix Knight heroes missing 2 leftmost sprite columns. for ( size_t i = 0; i < 6; ++i ) { fheroes2::Sprite & kinght = _icnVsSprite[id][i * 7]; const fheroes2::Sprite & barbarian = _icnVsSprite[id][i * 7 + 1]; const int32_t width = kinght.width(); const int32_t height = kinght.height(); fheroes2::Sprite fixed( width + 2, height ); Copy( kinght, 1, 0, fixed, 3, 0, width, height ); fixed.setPosition( kinght.x(), kinght.y() ); Copy( barbarian, 0, 0, fixed, 0, 0, 3, height ); Copy( barbarian, 3, 28, fixed, 3, 28, 1, 1 ); kinght = std::move( fixed ); } } return true; case ICN::HEROES: LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; // This is the main menu image which shouldn't have any transform layer. original._disableTransformLayer(); if ( original.width() == 640 && original.height() == 480 ) { // Fix incorrect pixel at position 260x305. original.image()[195460] = 31; } // Since we cannot access game settings from here we are checking an existence // of one of POL resources as an indicator for this version. if ( !::AGG::getDataFromAggFile( ICN::getIcnFileName( ICN::X_TRACK1 ), false ).empty() ) { fheroes2::Sprite editorIcon; fheroes2::h2d::readImage( "main_menu_editor_icon.image", editorIcon ); Blit( editorIcon, 0, 0, original, editorIcon.x(), editorIcon.y(), editorIcon.width(), editorIcon.height() ); } } return true; case ICN::BTNSHNGL: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 20 ) { _icnVsSprite[id].resize( 23 ); fheroes2::h2d::readImage( "main_menu_editor_released_button.image", _icnVsSprite[id][20] ); fheroes2::h2d::readImage( "main_menu_editor_highlighted_button.image", _icnVsSprite[id][21] ); fheroes2::h2d::readImage( "main_menu_editor_pressed_button.image", _icnVsSprite[id][22] ); } return true; case ICN::TOWNBKG3: // Warlock town background image contains 'empty' pixels leading to appear them as black. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 640 && original.height() == 256 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[51945] = 17; imageData[61828] = 25; imageData[64918] = 164; imageData[77685] = 18; imageData[84618] = 19; } } return true; case ICN::MINIPORT: // Some heroes portraits have incorrect transparent pixels. LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 60 ) { fheroes2::Sprite & original = _icnVsSprite[id][60]; if ( original.width() == 30 && original.height() == 22 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[5] = 75; imageData[310] = 48; imageData[358] = 64; imageData[424] = 65; } } if ( _icnVsSprite[id].size() > 61 ) { fheroes2::Sprite & original = _icnVsSprite[id][61]; if ( original.width() == 30 && original.height() == 22 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[51] = 30; imageData[80] = 28; imageData[81] = 30; imageData[383] = 24; imageData[445] = 24; } } if ( _icnVsSprite[id].size() > 65 ) { fheroes2::Sprite & original = _icnVsSprite[id][65]; if ( original.width() == 30 && original.height() == 22 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[499] = 60; imageData[601] = 24; imageData[631] = 28; } } if ( _icnVsSprite[id].size() > 67 ) { fheroes2::Sprite & original = _icnVsSprite[id][67]; if ( original.width() == 30 && original.height() == 22 ) { original._disableTransformLayer(); original.image()[42] = 28; } } return true; case ICN::MINICAPT: // Barbarian captain mini icon has bad pixel at position 22x2. LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 1 ) { fheroes2::Sprite & original = _icnVsSprite[id][1]; if ( original.width() == 30 && original.height() == 22 ) { original._disableTransformLayer(); original.image()[82] = 244; } } return true; case ICN::PORT0091: // Barbarian captain has one bad pixel. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 101 && original.height() == 93 ) { original._disableTransformLayer(); original.image()[9084] = 77; } } return true; case ICN::PORT0090: // Knight captain has multiple bad pixels. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 101 && original.height() == 93 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[2314] = 70; imageData[5160] = 71; imageData[5827] = 18; imageData[7474] = 167; } } return true; case ICN::PORT0092: // Sorceress captain has two bad transparent pixels (8x20 and 8x66). LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 101 && original.height() == 93 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[2028] = 42; imageData[6674] = 100; } } return true; case ICN::PORT0095: // Necromancer captain have incorrect transparent pixel at position 8x22. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 101 && original.height() == 93 ) { original._disableTransformLayer(); original.image()[2230] = 212; } } return true; case ICN::CSTLWZRD: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 8 ) { // Statue image has bad pixels. fheroes2::Sprite & original = _icnVsSprite[id][7]; if ( original.width() == 135 && original.height() == 57 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[3687] = 50; imageData[5159] = 108; imageData[5294] = 108; } } if ( _icnVsSprite[id].size() > 22 ) { // Cliff nest image has a glowing pixel. ApplyPalette( _icnVsSprite[id][22], PAL::GetPalette( PAL::PaletteType::NO_CYCLE ) ); } if ( _icnVsSprite[id].size() > 28 ) { // Mage tower image has a bad pixel. for ( const uint32_t index : { 23, 28 } ) { fheroes2::Sprite & original = _icnVsSprite[id][index]; if ( original.width() == 135 && original.height() == 57 ) { original._disableTransformLayer(); original.image()[4333] = 23; } } } return true; case ICN::CSTLCAPK: // Knight captain has a bad pixel. LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 2 ) { fheroes2::Sprite & original = _icnVsSprite[id][1]; if ( original.width() == 84 && original.height() == 81 ) { original._disableTransformLayer(); original.image()[4934] = 18; } } return true; case ICN::CSTLCAPW: // Warlock captain quarters have bad pixels. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 84 && original.height() == 81 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[1692] = 26; imageData[2363] = 32; imageData[2606] = 21; imageData[2608] = 21; } } return true; case ICN::CSTLSORC: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 14 ) { // Rainbow has bad pixels. fheroes2::Sprite & original = _icnVsSprite[id][13]; if ( original.width() == 135 && original.height() == 57 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[2047] = 160; imageData[2052] = 159; imageData[2055] = 160; imageData[2060] = 67; imageData[2063] = 159; imageData[2067] = 67; imageData[2184] = 67; imageData[2192] = 158; imageData[3508] = 67; imageData[3641] = 67; imageData[3773] = 69; imageData[3910] = 67; imageData[4039] = 69; imageData[4041] = 67; imageData[4172] = 67; imageData[4578] = 69; } } if ( _icnVsSprite[id].size() >= 25 ) { // Red tower has bad pixels. fheroes2::Sprite & original = _icnVsSprite[id][24]; if ( original.width() == 135 && original.height() == 57 ) { original._disableTransformLayer(); uint8_t * imageData = original.image(); imageData[2830] = 165; imageData[3101] = 165; imageData[3221] = 69; } } return true; case ICN::COLOR_CURSOR_ADVENTURE_MAP: case ICN::MONO_CURSOR_ADVENTURE_MAP: { // Create needed digits. const std::vector twoPoints = { { 2, 1 }, { 3, 1 }, { 1, 2 }, { 4, 2 }, { 3, 3 }, { 2, 4 }, { 1, 5 }, { 2, 5 }, { 3, 5 }, { 4, 5 } }; const std::vector threePoints = { { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 2 }, { 1, 3 }, { 2, 3 }, { 3, 3 }, { 4, 4 }, { 1, 5 }, { 2, 5 }, { 3, 5 } }; const std::vector fourPoints = { { 1, 1 }, { 3, 1 }, { 1, 2 }, { 3, 2 }, { 1, 3 }, { 2, 3 }, { 3, 3 }, { 4, 3 }, { 3, 4 }, { 3, 5 } }; const std::vector fivePoints = { { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 1, 2 }, { 1, 3 }, { 2, 3 }, { 3, 3 }, { 4, 4 }, { 1, 5 }, { 2, 5 }, { 3, 5 } }; const std::vector sixPoints = { { 2, 1 }, { 3, 1 }, { 1, 2 }, { 1, 3 }, { 2, 3 }, { 3, 3 }, { 1, 4 }, { 4, 4 }, { 2, 5 }, { 3, 5 } }; const std::vector sevenPoints = { { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 4, 2 }, { 3, 3 }, { 2, 4 }, { 2, 5 } }; const std::vector plusPoints = { { 2, 1 }, { 1, 2 }, { 2, 2 }, { 3, 2 }, { 2, 3 } }; const bool isColorCursor = ( id == ICN::COLOR_CURSOR_ADVENTURE_MAP ); const uint8_t digitColor = isColorCursor ? 115 : 11; std::vector digits( 7 ); digits[0] = createDigit( 6, 7, twoPoints, digitColor ); digits[1] = createDigit( 6, 7, threePoints, digitColor ); digits[2] = createDigit( 6, 7, fourPoints, digitColor ); digits[3] = createDigit( 6, 7, fivePoints, digitColor ); digits[4] = createDigit( 6, 7, sixPoints, digitColor ); digits[5] = createDigit( 6, 7, sevenPoints, digitColor ); digits[6] = addDigit( digits[5], createDigit( 5, 5, plusPoints, digitColor ), { -1, -1 } ); _icnVsSprite[id].reserve( 7 * 8 ); const int originalCursorId = isColorCursor ? ICN::ADVMCO : ICN::MONO_CURSOR_ADVMBW; populateCursorIcons( _icnVsSprite[id], fheroes2::AGG::GetICN( originalCursorId, 4 ), digits, isColorCursor ? fheroes2::Point( -2, 1 ) : fheroes2::Point( -4, -6 ) ); populateCursorIcons( _icnVsSprite[id], fheroes2::AGG::GetICN( originalCursorId, 5 ), digits, isColorCursor ? fheroes2::Point( 1, 1 ) : fheroes2::Point( -6, -6 ) ); populateCursorIcons( _icnVsSprite[id], fheroes2::AGG::GetICN( originalCursorId, 6 ), digits, isColorCursor ? fheroes2::Point( 0, 1 ) : fheroes2::Point( -8, -7 ) ); populateCursorIcons( _icnVsSprite[id], fheroes2::AGG::GetICN( originalCursorId, 7 ), digits, isColorCursor ? fheroes2::Point( -2, 1 ) : fheroes2::Point( -15, -8 ) ); populateCursorIcons( _icnVsSprite[id], fheroes2::AGG::GetICN( originalCursorId, 8 ), digits, isColorCursor ? fheroes2::Point( 1, 1 ) : fheroes2::Point( -16, -11 ) ); populateCursorIcons( _icnVsSprite[id], fheroes2::AGG::GetICN( originalCursorId, 9 ), digits, isColorCursor ? fheroes2::Point( -6, 1 ) : fheroes2::Point( -8, -1 ) ); populateCursorIcons( _icnVsSprite[id], fheroes2::AGG::GetICN( originalCursorId, 28 ), digits, isColorCursor ? fheroes2::Point( 0, 1 ) : fheroes2::Point( -8, -7 ) ); return true; } case ICN::KNIGHT_CASTLE_RIGHT_FARM: { _icnVsSprite[id].resize( 1 ); fheroes2::Sprite & output = _icnVsSprite[id][0]; output = fheroes2::AGG::GetICN( ICN::TWNKWEL2, 0 ); ApplyPalette( output, 28, 21, output, 28, 21, 39, 1, 8 ); ApplyPalette( output, 0, 22, output, 0, 22, 69, 1, 8 ); ApplyPalette( output, 0, 23, output, 0, 23, 53, 1, 8 ); ApplyPalette( output, 0, 24, output, 0, 24, 54, 1, 8 ); ApplyPalette( output, 0, 25, output, 0, 25, 62, 1, 8 ); return true; } case ICN::KNIGHT_CASTLE_LEFT_FARM: _icnVsSprite[id].resize( 1 ); fheroes2::h2d::readImage( "knight_castle_left_farm.image", _icnVsSprite[id][0] ); return true; case ICN::BARBARIAN_CASTLE_CAPTAIN_QUARTERS_LEFT_SIDE: _icnVsSprite[id].resize( 1 ); fheroes2::h2d::readImage( "barbarian_castle_captain_quarter_left_side.image", _icnVsSprite[id][0] ); return true; case ICN::SORCERESS_CASTLE_CAPTAIN_QUARTERS_LEFT_SIDE: _icnVsSprite[id].resize( 1 ); fheroes2::h2d::readImage( "sorceress_castle_captain_quarter_left_side.image", _icnVsSprite[id][0] ); return true; case ICN::NECROMANCER_CASTLE_STANDALONE_CAPTAIN_QUARTERS: { _icnVsSprite[id].resize( 1 ); fheroes2::Sprite & output = _icnVsSprite[id][0]; const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::TWNNCAPT, 0 ); output = Crop( original, 21, 0, original.width() - 21, original.height() ); output.setPosition( original.x() + 21, original.y() ); for ( int32_t y = 47; y < output.height(); ++y ) { SetTransformPixel( output, 0, y, 1 ); } const fheroes2::Sprite & castle = fheroes2::AGG::GetICN( ICN::TWNNCSTL, 0 ); Copy( castle, 402, 123, output, 1, 56, 2, 11 ); return true; } case ICN::NECROMANCER_CASTLE_CAPTAIN_QUARTERS_BRIDGE: { _icnVsSprite[id].resize( 1 ); fheroes2::Sprite & output = _icnVsSprite[id][0]; const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::TWNNCAPT, 0 ); output = Crop( original, 0, 0, 23, original.height() ); output.setPosition( original.x(), original.y() ); return true; } case ICN::ESCROLL: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 4 ) { // fix missing black border on the right side of the "up" button fheroes2::Sprite & out = _icnVsSprite[id][4]; if ( out.width() == 16 && out.height() == 16 ) { out._disableTransformLayer(); Copy( out, 0, 0, out, 15, 0, 1, 16 ); } } return true; case ICN::MAP_TYPE_ICON: { _icnVsSprite[id].resize( 3 ); for ( fheroes2::Sprite & icon : _icnVsSprite[id] ) { icon._disableTransformLayer(); icon.resize( 17, 17 ); icon.fill( 0 ); } const fheroes2::Sprite & successionWarsIcon = fheroes2::AGG::GetICN( ICN::ARTFX, 6 ); const fheroes2::Sprite & priceOfLoyaltyIcon = fheroes2::AGG::GetICN( ICN::ARTFX, 90 ); const fheroes2::Sprite & resurrectionIcon = fheroes2::AGG::GetICN( ICN::ARTFX, 101 ); if ( !successionWarsIcon.empty() ) { Resize( successionWarsIcon, 0, 0, successionWarsIcon.width(), successionWarsIcon.height(), _icnVsSprite[id][0], 1, 1, 15, 15 ); } if ( !priceOfLoyaltyIcon.empty() ) { Resize( priceOfLoyaltyIcon, 0, 0, priceOfLoyaltyIcon.width(), priceOfLoyaltyIcon.height(), _icnVsSprite[id][1], 1, 1, 15, 15 ); } if ( !resurrectionIcon.empty() ) { Resize( resurrectionIcon, 0, 0, resurrectionIcon.width(), resurrectionIcon.height(), _icnVsSprite[id][2], 1, 1, 15, 15 ); } return true; } case ICN::TWNWWEL2: { LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 7 ) { if ( _icnVsSprite[id][0].width() == 122 && _icnVsSprite[id][0].height() == 226 ) { FillTransform( _icnVsSprite[id][0], 0, 57, 56, 62, 1 ); } for ( size_t i = 1; i < 7; ++i ) { fheroes2::Sprite & original = _icnVsSprite[id][i]; if ( original.width() == 121 && original.height() == 151 ) { FillTransform( original, 0, 0, 64, 39, 1 ); } } } return true; } case ICN::TWNWCAPT: { LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 118 && original.height() ) { // Remove shadow from left side. FillTransform( original, 85, 84, 33, 26, 1 ); // Remove extra terrain at the bottom. FillTransform( original, 0, 114, 40, 4, 1 ); FillTransform( original, 9, 112, 51, 2, 1 ); FillTransform( original, 35, 110, 47, 2, 1 ); FillTransform( original, 57, 108, 51, 2, 1 ); } } return true; } case ICN::GOOD_ARMY_BUTTON: case ICN::GOOD_MARKET_BUTTON: { _icnVsSprite[id].resize( 2 ); loadICN( ICN::ADVBTNS ); const int releasedIndex = ( id == ICN::GOOD_ARMY_BUTTON ) ? 0 : 4; Copy( fheroes2::AGG::GetICN( ICN::ADVBTNS, releasedIndex ), _icnVsSprite[id][0] ); Copy( fheroes2::AGG::GetICN( ICN::ADVBTNS, releasedIndex + 1 ), _icnVsSprite[id][1] ); // Make all black pixels transparent. AddTransparency( _icnVsSprite[id][0], 36 ); AddTransparency( _icnVsSprite[id][1], 36 ); AddTransparency( _icnVsSprite[id][1], 61 ); // remove the extra brown border return true; } case ICN::EVIL_ARMY_BUTTON: case ICN::EVIL_MARKET_BUTTON: { _icnVsSprite[id].resize( 2 ); loadICN( ICN::ADVEBTNS ); const int releasedIndex = ( id == ICN::EVIL_ARMY_BUTTON ) ? 0 : 4; Copy( fheroes2::AGG::GetICN( ICN::ADVEBTNS, releasedIndex ), _icnVsSprite[id][0] ); Copy( fheroes2::AGG::GetICN( ICN::ADVEBTNS, releasedIndex + 1 ), _icnVsSprite[id][1] ); // Make all black pixels transparent. AddTransparency( _icnVsSprite[id][0], 36 ); AddTransparency( _icnVsSprite[id][1], 36 ); // Add the bottom-left dark border. Fill( _icnVsSprite[id][1], 1, 4, 1, 30, 36 ); Fill( _icnVsSprite[id][1], 1, 34, 31, 1, 36 ); // Restore back black pixels in the middle of the image. Copy( _icnVsSprite[ICN::ADVEBTNS][releasedIndex], 9, 6, _icnVsSprite[id][0], 9, 6, 20, 22 ); Copy( _icnVsSprite[ICN::ADVEBTNS][releasedIndex + 1], 8, 7, _icnVsSprite[id][1], 8, 7, 20, 22 ); return true; } case ICN::SPANBTN: case ICN::SPANBTNE: case ICN::CSPANBTN: case ICN::CSPANBTE: { LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { // add missing part of the released button state on the left fheroes2::Sprite & out = _icnVsSprite[id][0]; fheroes2::Sprite released( out.width() + 1, out.height() ); released.reset(); const uint8_t color = id == ICN::SPANBTN || id == ICN::CSPANBTN ? 57 : 32; DrawLine( released, { 0, 3 }, { 0, out.height() - 1 }, color ); Blit( out, released, 1, 0 ); out = std::move( released ); } return true; } case ICN::TRADPOSE: { LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 19 ) { // fix background for TRADE and EXIT buttons for ( const uint32_t i : { 16, 18 } ) { fheroes2::Sprite pressed; std::swap( pressed, _icnVsSprite[id][i] ); AddTransparency( pressed, 25 ); // remove too dark background // take background from the empty system button _icnVsSprite[id][i] = fheroes2::AGG::GetICN( ICN::SYSTEME, 12 ); // put back dark-gray pixels in the middle of the button Fill( _icnVsSprite[id][i], 5, 5, 86, 17, 25 ); Blit( pressed, _icnVsSprite[id][i] ); } } return true; } case ICN::RECRUIT: { LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 10 ) { // fix transparent corners on released OKAY button CopyTransformLayer( _icnVsSprite[id][9], _icnVsSprite[id][8] ); } return true; } case ICN::NGEXTRA: { LoadOriginalICN( id ); std::vector & images = _icnVsSprite[id]; if ( images.size() != 82 ) { // The game assets are wrong, skip modifications. return true; } // Fix extra column at the end of AI controlled player. for ( size_t i = 27; i < 34; ++i ) { if ( images[i].width() == 62 && images[i].height() == 58 ) { Copy( images[i], 58, 44, images[i], 59, 44, 1, 11 ); } } for ( size_t i = 39; i < 45; ++i ) { if ( images[i].width() == 62 && images[i].height() == 58 ) { Copy( images[i], 58, 44, images[i], 59, 44, 1, 11 ); } } // fix transparent corners on pressed OKAY and CANCEL buttons CopyTransformLayer( images[66], images[67] ); CopyTransformLayer( images[68], images[69] ); // Add 6 special icons for the Editor. images.resize( 82 + 6 ); for ( size_t i = 0; i < 6; ++i ) { if ( images[i + 3].width() != 62 || images[i + 3].height() != 45 ) { continue; } fheroes2::Sprite & humonOrAiImage = images[i + 82]; Copy( images[i + 3], humonOrAiImage ); // Fill the icon with the player's color. Fill( humonOrAiImage, 15, 8, 32, 30, images[i + 82].image()[252] ); // Make a temporary image to cut human icon's background. fheroes2::Image temp( 33, 35 ); Copy( images[i + 9], 15, 5, temp, 0, 0, 33, 35 ); ReplaceColorIdByTransformId( temp, images[i + 82].image()[252], 1U ); Copy( images[i + 3], 15, 8, humonOrAiImage, 27, 8, 31, 30 ); Blit( temp, humonOrAiImage, 4, 5 ); } return true; } case ICN::DIFFICULTY_ICON_EASY: case ICN::DIFFICULTY_ICON_NORMAL: case ICN::DIFFICULTY_ICON_HARD: case ICN::DIFFICULTY_ICON_EXPERT: case ICN::DIFFICULTY_ICON_IMPOSSIBLE: { const int originalIcnId = ICN::NGHSBKG; const fheroes2::Sprite & originalBackground = fheroes2::AGG::GetICN( originalIcnId, 0 ); if ( !originalBackground.empty() ) { _icnVsSprite[id].resize( 2 ); int32_t iconOffsetX = 0; switch ( id ) { case ICN::DIFFICULTY_ICON_EASY: iconOffsetX = 24; break; case ICN::DIFFICULTY_ICON_NORMAL: iconOffsetX = 101; break; case ICN::DIFFICULTY_ICON_HARD: iconOffsetX = 177; break; case ICN::DIFFICULTY_ICON_EXPERT: iconOffsetX = 254; break; case ICN::DIFFICULTY_ICON_IMPOSSIBLE: iconOffsetX = 331; break; default: // Did you add a new difficulty? assert( 0 ); } const int32_t iconSideLength = 65; const int32_t iconOffsetY = 94; _icnVsSprite[id][0] = Crop( originalBackground, iconOffsetX, iconOffsetY, iconSideLength, iconSideLength ); _icnVsSprite[id][0].setPosition( 0, 0 ); // Generate Evil Icons _icnVsSprite[id][1] = _icnVsSprite[id][0]; const std::vector & goodToEvilPalette = PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ); fheroes2::ApplyPalette( _icnVsSprite[id][0], _icnVsSprite[id][1], goodToEvilPalette ); } return true; } case ICN::METALLIC_BORDERED_TEXTBOX_GOOD: { const int originalIcnId = ICN::NGHSBKG; const fheroes2::Sprite & originalBackground = fheroes2::AGG::GetICN( originalIcnId, 0 ); if ( !originalBackground.empty() ) { _icnVsSprite[id].resize( 1 ); const int32_t boxWidth = 371; const int32_t boxHeight = 30; const int32_t goodOriginalBoxOffsetX = 24; const int32_t goodOriginalBoxOffsetY = 40; _icnVsSprite[id][0] = Crop( originalBackground, goodOriginalBoxOffsetX, goodOriginalBoxOffsetY, boxWidth, boxHeight ); _icnVsSprite[id][0].setPosition( 0, 0 ); // Copy red pattern and cover up embedded button. const fheroes2::Sprite & redPart = fheroes2::Flip( Crop( originalBackground, 80, 45, 81, 19 ), true, false ); Copy( redPart, 0, 0, _icnVsSprite[id][0], 284, 5, 81, 19 ); } return true; } case ICN::METALLIC_BORDERED_TEXTBOX_EVIL: { const fheroes2::Sprite & originalEvilBackground = fheroes2::AGG::GetICN( ICN::CAMPBKGE, 0 ); if ( !originalEvilBackground.empty() ) { _icnVsSprite[id].resize( 1 ); const int32_t boxWidth = 371; const int32_t boxHeight = 30; _icnVsSprite[id][0].resize( boxWidth, boxHeight ); _icnVsSprite[id][0].reset(); const int32_t evilOriginalBoxOffsetX = 26; const int32_t evilOriginalBoxOffsetY = 27; const int32_t upperPartHeight = 20; // The metallic box frame in campbkge is slightly taller than the one in nghsbkg. The width is the same. Copy( originalEvilBackground, evilOriginalBoxOffsetX, evilOriginalBoxOffsetY, _icnVsSprite[id][0], 0, 0, boxWidth, upperPartHeight ); Copy( originalEvilBackground, evilOriginalBoxOffsetX, evilOriginalBoxOffsetY + upperPartHeight + 14, _icnVsSprite[id][0], 0, upperPartHeight, boxWidth, 10 ); // Copy red central part. const fheroes2::Sprite goodBox = fheroes2::AGG::GetICN( ICN::METALLIC_BORDERED_TEXTBOX_GOOD, 0 ); Copy( goodBox, 6, 5, _icnVsSprite[id][0], 6, 5, 359, 19 ); } return true; } case ICN::MONO_CURSOR_ADVMBW: { loadICN( ICN::ADVMCO ); _icnVsSprite[id].resize( _icnVsSprite[ICN::ADVMCO].size() ); for ( size_t i = 0; i < _icnVsSprite[id].size(); ++i ) { std::string digit; if ( i < 9 ) { digit += '0'; } digit += std::to_string( i + 1 ); _icnVsSprite[id][i] = fheroes2::decodeBMPFile( AGG::getDataFromAggFile( std::string( "ADVMBW" ) + digit + ".BMP", false ) ); } return true; } case ICN::MONO_CURSOR_SPELBW: { loadICN( ICN::SPELCO ); _icnVsSprite[id].resize( _icnVsSprite[ICN::SPELCO].size() ); for ( size_t i = 0; i < _icnVsSprite[id].size(); ++i ) { std::string digit; if ( i < 10 ) { digit += '0'; } digit += std::to_string( i ); _icnVsSprite[id][i] = fheroes2::decodeBMPFile( AGG::getDataFromAggFile( std::string( "SPELBW" ) + digit + ".BMP", false ) ); } return true; } case ICN::MONO_CURSOR_CMSSBW: { loadICN( ICN::CMSECO ); _icnVsSprite[id].resize( _icnVsSprite[ICN::CMSECO].size() ); for ( size_t i = 0; i < _icnVsSprite[id].size(); ++i ) { std::string digit; if ( i < 9 ) { digit += '0'; } digit += std::to_string( i + 1 ); _icnVsSprite[id][i] = fheroes2::decodeBMPFile( AGG::getDataFromAggFile( std::string( "CMSEBW" ) + digit + ".BMP", false ) ); } return true; } case ICN::ADVBTNS: case ICN::ADVEBTNS: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 16 && _icnVsSprite[id][2].width() == 36 && _icnVsSprite[id][2].height() == 36 && _icnVsSprite[id][3].width() == 36 && _icnVsSprite[id][3].height() == 36 ) { // Add hero action button and inactive button released and pressed. _icnVsSprite[id].resize( 20 ); const bool isGoodButton = id == ICN::ADVBTNS; const int emptyButtonId = isGoodButton ? ICN::EMPTY_INTERFACE_BUTTON_GOOD : ICN::EMPTY_INTERFACE_BUTTON_EVIL; // Get the action cursor and prepare it for button. We make it a little smaller. const fheroes2::Sprite & originalActionCursor = fheroes2::AGG::GetICN( ICN::ADVMCO, 9 ); const int32_t actionCursorWidth = originalActionCursor.width() - 1; const int32_t actionCursorHeight = originalActionCursor.height() - 3; fheroes2::Image buttonImage( actionCursorWidth, actionCursorHeight ); buttonImage.reset(); // Head. Copy( originalActionCursor, 19, 1, buttonImage, 17, 2, 8, 5 ); Copy( originalActionCursor, 16, 7, buttonImage, 14, 7, 12, 2 ); buttonImage.transform()[15 + 7 * actionCursorWidth] = 1U; // Tail. Copy( originalActionCursor, 1, 10, buttonImage, 1, 9, 12, 11 ); // Middle part. Copy( originalActionCursor, 14, 10, buttonImage, 13, 9, 1, 11 ); // Front legs. Copy( originalActionCursor, 16, 10, buttonImage, 14, 9, 13, 11 ); // Hind legs. Copy( originalActionCursor, 7, 22, buttonImage, 7, 19, 7, 7 ); // Get the button's icon colors. const uint8_t mainReleasedColor = _icnVsSprite[id][2].image()[7 * 36 + 26]; const uint8_t mainPressedColor = _icnVsSprite[id][3].image()[8 * 36 + 25]; // Make contour transparent and the horse figure filled with solid color. const int32_t actionCursorSize = actionCursorWidth * actionCursorHeight; for ( int32_t i = 0; i < actionCursorSize; ++i ) { if ( buttonImage.transform()[i] == 1U ) { // Skip transparent pixel. continue; } if ( buttonImage.image()[i] < 152U ) { // It is the contour color, make it transparent. buttonImage.transform()[i] = 1U; } else { buttonImage.image()[i] = mainPressedColor; } } // Add shadows to the horse image. updateShadow( buttonImage, { 1, -1 }, 2, true ); updateShadow( buttonImage, { -1, 1 }, 6, true ); updateShadow( buttonImage, { 2, -2 }, 4, true ); const fheroes2::Sprite & emptyButtonPressed = fheroes2::AGG::GetICN( emptyButtonId, 1 ); Copy( emptyButtonPressed, _icnVsSprite[id][17] ); Blit( buttonImage, _icnVsSprite[id][17], 4, 4 ); // Replace colors for the released button. for ( int32_t i = 0; i < actionCursorSize; ++i ) { if ( buttonImage.transform()[i] == 6U ) { // Disable whitening transform and set white color. buttonImage.transform()[i] = 0U; buttonImage.image()[i] = 10U; } } ReplaceColorId( buttonImage, mainPressedColor, mainReleasedColor ); const fheroes2::Sprite & emptyButtonReleased = fheroes2::AGG::GetICN( emptyButtonId, 0 ); Copy( emptyButtonReleased, _icnVsSprite[id][16] ); Blit( buttonImage, _icnVsSprite[id][16], 5, 3 ); // Generate inactive horse icon. fheroes2::Sprite & releasedInactiveHorse = _icnVsSprite[id][18]; Copy( emptyButtonReleased, releasedInactiveHorse ); const uint8_t mainShadingColor = isGoodButton ? 46 : 25; const uint8_t secondShadingColor = isGoodButton ? 43 : 18; const uint8_t thirdShadingColor = isGoodButton ? 39 : 15; const uint8_t fourthShadingColor = isGoodButton ? 42 : 16; const uint8_t fifthShadingColor = isGoodButton ? 38 : 14; // Upper body. Copy( _icnVsSprite[id][2], 22, 5, releasedInactiveHorse, 22, 4, 10, 10 ); fheroes2::SetPixel( releasedInactiveHorse, 31, 13, secondShadingColor ); Fill( releasedInactiveHorse, 12, 13, 15, 5, mainReleasedColor ); Fill( releasedInactiveHorse, 12, 18, 5, 2, mainReleasedColor ); Fill( releasedInactiveHorse, 22, 18, 5, 2, mainReleasedColor ); fheroes2::SetPixel( releasedInactiveHorse, 21, 12, mainReleasedColor ); // Copy one leg 4 times. Copy( _icnVsSprite[id][2], 13, 22, releasedInactiveHorse, 11, 22, 4, 6 ); fheroes2::SetPixel( releasedInactiveHorse, 11, 24, 10 ); fheroes2::SetPixel( releasedInactiveHorse, 14, 24, secondShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 14, 27, secondShadingColor ); Fill( releasedInactiveHorse, 12, 20, 2, 2, mainReleasedColor ); Copy( releasedInactiveHorse, 11, 21, releasedInactiveHorse, 21, 21, 4, 7 ); Copy( releasedInactiveHorse, 11, 21, releasedInactiveHorse, 24, 20, 4, 7 ); Copy( releasedInactiveHorse, 11, 21, releasedInactiveHorse, 14, 20, 4, 7 ); fheroes2::SetPixel( releasedInactiveHorse, 24, 27, fourthShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 17, 18, mainReleasedColor ); fheroes2::SetPixel( releasedInactiveHorse, 21, 18, mainReleasedColor ); fheroes2::DrawLine( releasedInactiveHorse, { 22, 20 }, { 23, 20 }, mainReleasedColor ); // Tail. fheroes2::DrawLine( releasedInactiveHorse, { 11, 14 }, { 10, 15 }, mainReleasedColor ); fheroes2::SetPixel( releasedInactiveHorse, 11, 15, mainReleasedColor ); Fill( releasedInactiveHorse, 9, 16, 2, 4, mainReleasedColor ); fheroes2::DrawLine( releasedInactiveHorse, { 7, 19 }, { 8, 19 }, mainReleasedColor ); fheroes2::DrawLine( releasedInactiveHorse, { 8, 20 }, { 9, 20 }, mainReleasedColor ); // Shading. fheroes2::DrawLine( releasedInactiveHorse, { 27, 13 }, { 27, 20 }, mainShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 21, 11 }, { 20, 12 }, mainShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 19, 12 }, { 17, 12 }, secondShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 20, 11, secondShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 16, 12 }, { 12, 12 }, mainShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 11, 12, secondShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 11, 13 }, { 9, 15 }, mainShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 10, 13, fifthShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 9, 14, 10 ); fheroes2::DrawLine( releasedInactiveHorse, { 8, 15 }, { 8, 18 }, 10 ); fheroes2::SetPixel( releasedInactiveHorse, 7, 18, secondShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 6, 19 }, { 8, 21 }, 10 ); fheroes2::DrawLine( releasedInactiveHorse, { 6, 20 }, { 7, 21 }, thirdShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 9, 21, 10 ); fheroes2::SetPixel( releasedInactiveHorse, 10, 20, thirdShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 11, 16, mainShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 11, 17, secondShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 11, 21, 10 ); fheroes2::DrawLine( releasedInactiveHorse, { 14, 20 }, { 14, 21 }, thirdShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 17, 19 }, { 17, 20 }, mainShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 18, 18 }, { 20, 18 }, mainShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 21, 19, mainShadingColor ); fheroes2::SetPixel( releasedInactiveHorse, 18, 19, thirdShadingColor ); fheroes2::DrawLine( releasedInactiveHorse, { 19, 19 }, { 20, 19 }, 10 ); fheroes2::DrawLine( releasedInactiveHorse, { 21, 20 }, { 21, 21 }, 10 ); fheroes2::SetPixel( releasedInactiveHorse, 24, 20, thirdShadingColor ); // Clean up button border. fheroes2::DrawLine( releasedInactiveHorse, { 23, 4 }, { 22, 5 }, 10 ); const uint8_t backgroundReleasedColor = isGoodButton ? 41 : 16; fheroes2::SetPixel( releasedInactiveHorse, 22, 4, backgroundReleasedColor ); // Make pressed state. // To keep the button's edge colors do all color manipulations on a temporary single-layer image. const int32_t pressedHorseImageWidth = 26; const int32_t pressedHorseImageHeight = 24; buttonImage._disableTransformLayer(); buttonImage.resize( pressedHorseImageWidth, pressedHorseImageHeight ); const uint8_t backgroundPressedColor = isGoodButton ? 45 : 22; Fill( buttonImage, 0, 0, pressedHorseImageWidth, pressedHorseImageHeight, backgroundPressedColor ); Copy( releasedInactiveHorse, 6, 11, buttonImage, 0, 7, 22, 17 ); Copy( releasedInactiveHorse, 24, 4, buttonImage, 18, 0, 8, 10 ); Copy( releasedInactiveHorse, 22, 8, buttonImage, 16, 4, 2, 3 ); fheroes2::ReplaceColorId( buttonImage, mainReleasedColor, mainPressedColor ); const uint8_t pressedColorOffset = isGoodButton ? 4 : 6; fheroes2::ReplaceColorId( buttonImage, backgroundReleasedColor, backgroundPressedColor ); fheroes2::ReplaceColorId( buttonImage, mainShadingColor, mainShadingColor + pressedColorOffset ); fheroes2::ReplaceColorId( buttonImage, secondShadingColor, secondShadingColor + pressedColorOffset ); fheroes2::ReplaceColorId( buttonImage, thirdShadingColor, thirdShadingColor + pressedColorOffset ); fheroes2::ReplaceColorId( buttonImage, fourthShadingColor, fourthShadingColor + pressedColorOffset ); fheroes2::ReplaceColorId( buttonImage, fifthShadingColor, fifthShadingColor + pressedColorOffset ); fheroes2::ReplaceColorId( buttonImage, 10, isGoodButton ? 40 : 14 ); Copy( emptyButtonPressed, _icnVsSprite[id][19] ); Copy( buttonImage, 0, 0, _icnVsSprite[id][19], 5, 5, pressedHorseImageWidth, pressedHorseImageHeight ); // Fix left border. if ( isGoodButton ) { fheroes2::DrawLine( _icnVsSprite[id][19], { 5, 5 }, { 5, 19 }, 44 ); fheroes2::DrawLine( _icnVsSprite[id][19], { 5, 21 }, { 5, 28 }, 44 ); } } return true; case ICN::ARTFX: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 82 ) { // Make a sprite for EDITOR_ANY_ULTIMATE_ARTIFACT used only in Editor for the special victory condition. // A temporary solution is below. const fheroes2::Sprite & originalImage = fheroes2::AGG::GetICN( ICN::ARTIFACT, 83 ); SubpixelResize( originalImage, _icnVsSprite[id][82] ); } return true; case ICN::ARTIFACT: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 99 ) { // This fixes "Arm of the Martyr" (#88) and " Sphere of Negation" (#99) artifacts rendering which initially has some incorrect transparent pixels. for ( const int32_t index : { 88, 99 } ) { fheroes2::Sprite & originalImage = _icnVsSprite[id][index]; fheroes2::Sprite temp( originalImage.width(), originalImage.height() ); temp.setPosition( originalImage.x(), originalImage.y() ); temp._disableTransformLayer(); temp.fill( 0 ); Blit( originalImage, temp ); originalImage = std::move( temp ); } // Make a sprite for EDITOR_ANY_ULTIMATE_ARTIFACT used only in Editor for the special victory condition. // A temporary solution: apply the blur effect originally used for the Holy Shout spell and the purple palette. fheroes2::Sprite & targetImage = _icnVsSprite[id][83]; targetImage = CreateHolyShoutEffect( _icnVsSprite[id][91], 1, 0 ); ApplyPalette( targetImage, PAL::GetPalette( PAL::PaletteType::PURPLE ) ); // The French and German Price of Loyalty assets contain a wrong artifact sprite at index 6. We replace it with the correct sprite from SW assets. const int assetIndex = 6; if ( _icnVsSprite[id][assetIndex].width() == 21 ) { replacePOLAssetWithSW( id, assetIndex ); } } return true; case ICN::OBJNARTI: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 206 ) { // These are the Price of Loyalty assets. // Spell Scroll has an invalid offset by X axis. if ( _icnVsSprite[id][173].width() == 21 ) { _icnVsSprite[id][173].setPosition( 2, _icnVsSprite[id][173].y() ); } // Make a map sprite for the Magic Book artifact. _icnVsSprite[id].resize( 208 ); // Magic book sprite shadow. fheroes2::Sprite shadow = _icnVsSprite[id][162]; FillTransform( shadow, 0, 0, 5, 1, 1U ); FillTransform( shadow, 0, 1, 2, 1, 1U ); FillTransform( shadow, 2, 1, 4, 1, 3U ); FillTransform( shadow, 0, 2, 3, 1, 3U ); FillTransform( shadow, 18, 1, 2, 1, 1U ); FillTransform( shadow, 17, 2, 3, 1, 3U ); FillTransform( shadow, 20, 2, 1, 1, 1U ); FillTransform( shadow, 19, 3, 2, 1, 3U ); // Magic Book main sprite. We use sprite from the info dialog to make the map sprite. fheroes2::Sprite body( 21, 32 ); Copy( fheroes2::AGG::GetICN( ICN::ARTFX, 81 ), 6, 0, body, 0, 0, 21, 32 ); FillTransform( body, 0, 0, 12, 1, 1U ); FillTransform( body, 15, 0, 6, 1, 1U ); FillTransform( body, 0, 1, 9, 1, 1U ); FillTransform( body, 16, 1, 5, 1, 1U ); FillTransform( body, 0, 2, 6, 1, 1U ); FillTransform( body, 20, 2, 1, 1, 1U ); FillTransform( body, 0, 4, 1, 1, 1U ); FillTransform( body, 0, 3, 3, 1, 1U ); FillTransform( body, 20, 25, 1, 1, 1U ); FillTransform( body, 18, 26, 3, 1, 1U ); FillTransform( body, 16, 27, 5, 1, 1U ); FillTransform( body, 14, 28, 9, 1, 1U ); FillTransform( body, 0, 29, 1, 1, 1U ); FillTransform( body, 12, 29, 11, 1, 1U ); FillTransform( body, 0, 30, 3, 1, 1U ); FillTransform( body, 10, 30, 13, 1, 1U ); FillTransform( body, 0, 31, 5, 1, 1U ); FillTransform( body, 8, 31, 15, 1, 1U ); const int32_t shadowOffset = ( 32 - body.width() ) / 2; _icnVsSprite[id][206].resize( shadow.width() - shadowOffset, shadow.height() ); Copy( shadow, 0, 0, _icnVsSprite[id][206], 0, 0, shadow.width(), shadow.height() ); _icnVsSprite[id][206].setPosition( shadow.x() + shadowOffset, shadow.y() ); _icnVsSprite[id][207].resize( 21 + shadowOffset, 32 ); _icnVsSprite[id][207].reset(); Copy( shadow, shadow.width() - shadowOffset, 0, _icnVsSprite[id][207], 0, shadow.y(), shadowOffset, shadow.height() ); Copy( body, 0, 0, _icnVsSprite[id][207], shadowOffset, 0, body.width(), body.height() ); } return true; case ICN::TWNSDW_5: LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() && _icnVsSprite[id][0].width() == 140 && _icnVsSprite[id][0].height() == 165 ) { fheroes2::Sprite & image = _icnVsSprite[id][0]; // Red Tower has multiple defects. // First one is the area between columns in middle of the Tower is prerendered. We need to remove it. const int32_t windowBottom = 88; FillTransform( image, 39, 68, 1, windowBottom - 68, 1 ); FillTransform( image, 40, 67, 1, windowBottom - 67, 1 ); FillTransform( image, 41, 66, 1, windowBottom - 66, 1 ); FillTransform( image, 42, 65, 1, windowBottom - 65, 1 ); FillTransform( image, 43, 66, 1, windowBottom - 66, 1 ); FillTransform( image, 44, 67, 1, windowBottom - 67, 1 ); FillTransform( image, 45, 71, 1, windowBottom - 71, 1 ); FillTransform( image, 49, 70, 1, windowBottom - 70, 1 ); FillTransform( image, 50, 68, 2, windowBottom - 68, 1 ); FillTransform( image, 52, 69, 1, windowBottom - 69, 1 ); FillTransform( image, 53, 74, 1, windowBottom - 74, 1 ); FillTransform( image, 57, 70, 1, windowBottom - 70, 1 ); FillTransform( image, 58, 67, 1, windowBottom - 67, 1 ); FillTransform( image, 59, 66, 1, windowBottom - 66, 1 ); FillTransform( image, 60, 65, 2, windowBottom - 65, 1 ); FillTransform( image, 62, 67, 1, windowBottom - 67, 1 ); FillTransform( image, 63, 69, 1, windowBottom - 69, 1 ); FillTransform( image, 64, 72, 1, windowBottom - 72, 1 ); // The lower part of the tower is truncated and blocked by partial castle's sprite. The fix is done in multiple stages. // Fix right red part of the building by copying a piece of the same wall. Copy( image, 67, 135, image, 67, 119, 1, 1 ); Copy( image, 67, 144, image, 67, 120, 2, 2 ); Copy( image, 67, 134, image, 67, 122, 3, 2 ); Copy( image, 67, 148, image, 67, 125, 1, 4 ); // Remove a part of the castle at the bottom left part of the image. FillTransform( image, 62, 157, 3, 8, 1 ); // Top part of the castle's tower touches Red Tower level separation part. Copy( image, 61, 101, image, 57, 101, 2, 1 ); Copy( image, 52, 100, image, 57, 100, 2, 1 ); // Generate programmatically the left part of the building. std::mt19937 seededGen( 751 ); // 751 is and ID of this sprite. To keep the changes constant we need to hardcode this value. fillRandomPixelsFromImage( image, { 33, 105, 4, 7 }, image, { 33, 117, 4, 39 }, seededGen ); fillRandomPixelsFromImage( image, { 41, 105, 5, 9 }, image, { 41, 121, 5, 36 }, seededGen ); fillRandomPixelsFromImage( image, { 46, 104, 4, 13 }, image, { 46, 118, 4, 39 }, seededGen ); Copy( image, 37, 113, image, 37, 115, 1, 2 ); Copy( image, 37, 104, image, 37, 117, 1, 2 ); Copy( image, 38, 104, image, 38, 118, 2, 1 ); Copy( image, 37, 113, image, 38, 117, 1, 1 ); // Create a temporary image to be a holder of pixels. fheroes2::Sprite temp( 4 * 2, 8 ); Copy( image, 33, 105, temp, 0, 0, 4, 8 ); Copy( image, 41, 105, temp, 4, 0, 4, 8 ); fillRandomPixelsFromImage( temp, { 0, 0, temp.width(), temp.height() }, image, { 37, 119, 4, 37 }, seededGen ); Copy( image, 35, 131, image, 35, 113, 2, 4 ); Copy( image, 43, 133, image, 43, 115, 3, 6 ); // Fix the main arc. Copy( image, 61, 102, image, 56, 102, 3, 1 ); // TODO: the distribution of light inside Red Tower is actually not uniform and follows the window on from th left. // However, generating such complex image requires a lot of code so we simply make the rest of the arc uniformed filled. fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 50, 110, 12, 47 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 52, 107, 9, 3 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 62, 111, 1, 46 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 63, 113, 1, 20 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 63, 141, 1, 16 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 64, 115, 1, 17 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 64, 152, 1, 5 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 65, 116, 1, 15 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 66, 118, 1, 12 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 51, 108, 1, 2 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 55, 103, 5, 4 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 61, 109, 1, 1 }, seededGen ); fillRandomPixelsFromImage( image, { 61, 104, 2, 3 }, image, { 52, 106, 1, 1 }, seededGen ); } return true; case ICN::SCENIBKG: LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() && _icnVsSprite[id][0].width() == 436 && _icnVsSprite[id][0].height() == 476 ) { const fheroes2::Sprite & helper = fheroes2::AGG::GetICN( ICN::CSPANBKE, 1 ); if ( !helper.empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; fheroes2::Sprite temp( original.width(), original.height() + 12 ); temp.reset(); Copy( original, 0, 0, temp, 0, 0, original.width(), original.height() ); Copy( helper, 0, helper.height() - 12, temp, 0, temp.height() - 12, 300, 12 ); Copy( helper, helper.width() - ( temp.width() - 300 ), helper.height() - 12, temp, 300 - 16, temp.height() - 12, temp.width() - 300, 12 ); original = std::move( temp ); } } return true; case ICN::CSTLCAPS: LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() && _icnVsSprite[id][0].width() == 84 && _icnVsSprite[id][0].height() == 81 ) { const fheroes2::Sprite & castle = fheroes2::AGG::GetICN( ICN::TWNSCSTL, 0 ); if ( !castle.empty() ) { Blit( castle, 206, 106, _icnVsSprite[id][0], 2, 2, 33, 67 ); } } return true; case ICN::LGNDXTRA: // Exit button is too huge due to 1 pixel presence at the bottom of the image. LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 6 ) { auto & original = _icnVsSprite[id]; if ( original[4].height() == 142 ) { const fheroes2::Point offset( original[4].x(), original[4].y() ); original[4] = Crop( original[4], 0, 0, original[4].width(), 25 ); original[4].setPosition( offset.x, offset.y ); } if ( original[5].height() == 142 ) { const fheroes2::Point offset( original[5].x(), original[5].y() ); original[5] = Crop( original[5], 0, 0, original[5].width(), 25 ); original[5].setPosition( offset.x, offset.y ); } } return true; case ICN::LGNDXTRE: // Exit button is too huge due to 1 pixel presence at the bottom of the image. LoadOriginalICN( id ); if ( _icnVsSprite[id].size() >= 6 ) { auto & original = _icnVsSprite[id]; if ( original[4].height() == 142 ) { const fheroes2::Point offset( original[4].x(), original[4].y() ); original[4] = Crop( original[4], 0, 0, original[4].width(), 25 ); original[4].setPosition( offset.x, offset.y ); } } return true; case ICN::OVERBACK: { LoadOriginalICN( id ); fheroes2::Sprite & background = _icnVsSprite[id][0]; // Fill button backgrounds. This bug was present in the original game too. Fill( background, 540, 361, 99, 83, 57 ); Fill( background, 540, 454, 99, 24, 57 ); fheroes2::Copy( fheroes2::AGG::GetICN( ICN::OVERBACK, 0 ), 540, 444, background, 540, 402, 99, 5 ); return true; } case ICN::ESPANBKG_EVIL: { _icnVsSprite[id].resize( 2 ); const fheroes2::Rect roi{ 28, 28, 265, 206 }; fheroes2::Sprite & output = _icnVsSprite[id][0]; _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::CSPANBKE, 0 ); Copy( fheroes2::AGG::GetICN( ICN::ESPANBKG, 0 ), roi.x, roi.y, output, roi.x, roi.y, roi.width, roi.height ); convertToEvilInterface( output, roi ); _icnVsSprite[id][1] = fheroes2::AGG::GetICN( ICN::ESPANBKG, 1 ); return true; } case ICN::STONEBAK_EVIL: { fheroes2::AGG::GetICN( ICN::STONEBAK, 0 ); _icnVsSprite[id] = _icnVsSprite[ICN::STONEBAK]; if ( !_icnVsSprite[id].empty() ) { const fheroes2::Rect roi( 0, 0, _icnVsSprite[id][0].width(), _icnVsSprite[id][0].height() ); convertToEvilInterface( _icnVsSprite[id][0], roi ); } return true; } case ICN::STONEBAK_SMALL_POL: { _icnVsSprite[id].resize( 1 ); const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::X_CMPBKG, 0 ); if ( !original.empty() ) { _icnVsSprite[id][0] = Crop( original, original.width() - 272, original.height() - 52, 244, 28 ); } return true; } case ICN::REDBAK_SMALL_VERTICAL: { _icnVsSprite[id].resize( 1 ); const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::HEROBKG, 0 ); if ( !original.empty() ) { _icnVsSprite[id][0] = Crop( original, 0, 0, 37, 230 ); } return true; } case ICN::BLACKBAK: { _icnVsSprite[id].resize( 1 ); fheroes2::Image & background = _icnVsSprite[id][0]; // This is enough to cover the largest buttons. background.resize( 200, 200 ); fheroes2::Fill( background, 0, 0, background.width(), background.height(), 9 ); return true; } case ICN::BROWNBAK: { _icnVsSprite[id].resize( 1 ); fheroes2::Image & background = _icnVsSprite[id][0]; // This is enough to cover the largest buttons. background.resize( 200, 200 ); fheroes2::Fill( background, 0, 0, background.width(), background.height(), 57 ); return true; } case ICN::UNIFORMBAK_GOOD: case ICN::UNIFORMBAK_EVIL: { _icnVsSprite[id].resize( 1 ); const bool isEvilInterface = ( id == ICN::UNIFORMBAK_EVIL ); const fheroes2::Sprite & original = fheroes2::AGG::GetICN( isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD, 1 ); if ( !original.empty() ) { _icnVsSprite[id][0].resize( 246, 45 ); _icnVsSprite[id][0].reset(); Copy( original, 0, 0, _icnVsSprite[id][0], 0, 0, 123, 45 ); Copy( original, 0, 0, _icnVsSprite[id][0], 123, 0, 123, 45 ); } return true; } case ICN::WELLBKG_EVIL: { fheroes2::AGG::GetICN( ICN::WELLBKG, 0 ); _icnVsSprite[id] = _icnVsSprite[ICN::WELLBKG]; if ( !_icnVsSprite[id].empty() ) { const fheroes2::Rect roi( 0, 0, _icnVsSprite[id][0].width(), _icnVsSprite[id][0].height() - 19 ); convertToEvilInterface( _icnVsSprite[id][0], roi ); } return true; } case ICN::CASLWIND_EVIL: { fheroes2::AGG::GetICN( ICN::CASLWIND, 0 ); _icnVsSprite[id] = _icnVsSprite[ICN::CASLWIND]; if ( !_icnVsSprite[id].empty() ) { const fheroes2::Rect roi( 0, 0, _icnVsSprite[id][0].width(), _icnVsSprite[id][0].height() ); convertToEvilInterface( _icnVsSprite[id][0], roi ); } return true; } case ICN::CASLXTRA_EVIL: { fheroes2::AGG::GetICN( ICN::CASLXTRA, 0 ); _icnVsSprite[id] = _icnVsSprite[ICN::CASLXTRA]; if ( !_icnVsSprite[id].empty() ) { const fheroes2::Rect roi( 0, 0, _icnVsSprite[id][0].width(), _icnVsSprite[id][0].height() ); convertToEvilInterface( _icnVsSprite[id][0], roi ); } return true; } case ICN::STRIP_BACKGROUND_EVIL: { _icnVsSprite[id].resize( 1 ); _icnVsSprite[id][0] = fheroes2::AGG::GetICN( ICN::STRIP, 11 ); const fheroes2::Rect roi( 0, 0, _icnVsSprite[id][0].width(), _icnVsSprite[id][0].height() - 7 ); convertToEvilInterface( _icnVsSprite[id][0], roi ); return true; } case ICN::B_BFLG32: case ICN::G_BFLG32: case ICN::R_BFLG32: case ICN::Y_BFLG32: case ICN::O_BFLG32: case ICN::P_BFLG32: LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 31 && _icnVsSprite[id][31].height() == 248 ) { fheroes2::Sprite & original = _icnVsSprite[id][31]; fheroes2::Sprite temp = Crop( original, 0, 0, original.width(), 4 ); temp.setPosition( original.x(), original.y() ); original = std::move( temp ); } return true; case ICN::FLAG32: { LoadOriginalICN( id ); auto & flagImages = _icnVsSprite[id]; if ( flagImages.size() == 49 ) { // Shift and crop the Lighthouse flags to properly render them on the Adventure map. flagImages.resize( 49 + 7 * 2 ); for ( size_t i = 42; i < 42 + 7; ++i ) { const fheroes2::Sprite & original = flagImages[i]; flagImages[i + 7] = Crop( original, 0, 0, -original.x(), original.height() ); flagImages[i + 7].setPosition( 32 + original.x(), original.y() ); flagImages[i + 7 + 7] = Crop( original, -original.x(), 0, original.width(), original.height() ); flagImages[i + 7 + 7].setPosition( 0, original.y() ); } } return true; } case ICN::SHADOW32: LoadOriginalICN( id ); // The shadow sprite of hero needs to be shifted to match the hero sprite. if ( _icnVsSprite[id].size() == 86 ) { // Direction: TOP (0-8), TOP_RIGHT (9-17), RIGHT (18-26), BOTTOM_RIGHT (27-35), BOTTOM (36-44) for ( int32_t i = 0; i < 45; ++i ) { fheroes2::Sprite & original = _icnVsSprite[id][i]; original.setPosition( original.x(), original.y() - 3 ); } // Direction:TOP_LEFT for ( int32_t i = 59; i < 68; ++i ) { fheroes2::Sprite & original = _icnVsSprite[id][i]; original.setPosition( original.x() + 1, original.y() - 3 ); } // Direction:LEFT for ( int32_t i = 68; i < 77; ++i ) { fheroes2::Sprite & original = _icnVsSprite[id][i]; original.setPosition( original.x() - 5, original.y() - 3 ); } // Direction:BOTTOM_LEFT for ( int32_t i = 77; i < 86; ++i ) { fheroes2::Sprite & original = _icnVsSprite[id][i]; if ( i == 80 ) { // This sprite needs extra fix. original.setPosition( original.x() - 5, original.y() - 3 ); } else { original.setPosition( original.x() - 10, original.y() - 3 ); } } } return true; case ICN::MINI_MONSTER_IMAGE: case ICN::MINI_MONSTER_SHADOW: { // It doesn't matter which image is being called. We are generating both of them at the same time. loadICN( ICN::MINIMON ); // Minotaur King original Adventure map sprite has blue armlets. We make them gold to correspond the ICN::MINOTAU2. if ( _icnVsSprite[ICN::MINIMON].size() > 303 ) { // The gold color gradient has -42 offset from blue color gradient. if ( _icnVsSprite[ICN::MINIMON][297].width() == 38 && _icnVsSprite[ICN::MINIMON][297].height() == 34 ) { // We update these pixels: 29x15, 30x15, 31x15, 30x16. for ( const uint32_t pixelNumber : { 599, 600, 601, 638 } ) { _icnVsSprite[ICN::MINIMON][297].image()[pixelNumber] -= 42; } } for ( uint32_t icnNumber = 298; icnNumber < 300; ++icnNumber ) { if ( _icnVsSprite[ICN::MINIMON][icnNumber].width() == 44 && _icnVsSprite[ICN::MINIMON][icnNumber].height() == 32 ) { // We update these pixels: 29x17, 30x17, 32x17, 30x18, 31x18, 38x18, 38x19, 38x20. for ( const uint32_t pixelNumber : { 777, 778, 780, 822, 823, 830, 874, 918 } ) { _icnVsSprite[ICN::MINIMON][icnNumber].image()[pixelNumber] -= 42; } } } if ( _icnVsSprite[ICN::MINIMON][300].width() == 45 && _icnVsSprite[ICN::MINIMON][300].height() == 32 ) { // We update these pixels: 30x17, 31x17, 33x17, 31x18, 32x18, 39x18, 39x19, 39x20 for ( const uint32_t pixelNumber : { 795, 796, 798, 841, 842, 849, 894, 939 } ) { _icnVsSprite[ICN::MINIMON][300].image()[pixelNumber] -= 42; } } if ( _icnVsSprite[ICN::MINIMON][301].width() == 45 && _icnVsSprite[ICN::MINIMON][301].height() == 32 ) { // We update these pixels: 29x17, 30x17, 32x17, 30x18, 31x18, 39x18, 39x19, 39x20 for ( const uint32_t pixelNumber : { 794, 795, 797, 840, 841, 849, 894, 939 } ) { _icnVsSprite[ICN::MINIMON][301].image()[pixelNumber] -= 42; } } if ( _icnVsSprite[ICN::MINIMON][302].width() == 45 && _icnVsSprite[ICN::MINIMON][302].height() == 32 ) { // We update these pixels: 35x16, 29x17, 30x17, 32x17, 33x17, 34x17, 30x18, 31x18, 31x19, 32x20. for ( const uint32_t pixelNumber : { 755, 794, 795, 797, 798, 799, 840, 841, 886, 932 } ) { _icnVsSprite[ICN::MINIMON][302].image()[pixelNumber] -= 42; } } if ( _icnVsSprite[ICN::MINIMON][303].width() == 44 && _icnVsSprite[ICN::MINIMON][303].height() == 32 ) { // We update these pixels: 29x17, 30x17, 30x18, 31x18, 31x19. for ( const uint32_t pixelNumber : { 777, 778, 822, 823, 867 } ) { _icnVsSprite[ICN::MINIMON][303].image()[pixelNumber] -= 42; } } } // TODO: optimize image sizes. _icnVsSprite[ICN::MINI_MONSTER_IMAGE] = _icnVsSprite[ICN::MINIMON]; _icnVsSprite[ICN::MINI_MONSTER_SHADOW] = _icnVsSprite[ICN::MINIMON]; for ( fheroes2::Sprite & image : _icnVsSprite[ICN::MINI_MONSTER_IMAGE] ) { uint8_t * transform = image.transform(); const uint8_t * transformEnd = transform + image.width() * image.height(); for ( ; transform != transformEnd; ++transform ) { if ( *transform > 1 ) { *transform = 1; } } } for ( fheroes2::Sprite & image : _icnVsSprite[ICN::MINI_MONSTER_SHADOW] ) { uint8_t * transform = image.transform(); const uint8_t * transformEnd = transform + image.width() * image.height(); for ( ; transform != transformEnd; ++transform ) { if ( *transform == 0 ) { *transform = 1; } } } return true; } case ICN::BUTTON_GOOD_FONT_RELEASED: case ICN::BUTTON_GOOD_FONT_PRESSED: case ICN::BUTTON_EVIL_FONT_RELEASED: case ICN::BUTTON_EVIL_FONT_PRESSED: { generateBaseButtonFont( _icnVsSprite[ICN::BUTTON_GOOD_FONT_RELEASED], _icnVsSprite[ICN::BUTTON_GOOD_FONT_PRESSED], _icnVsSprite[ICN::BUTTON_EVIL_FONT_RELEASED], _icnVsSprite[ICN::BUTTON_EVIL_FONT_PRESSED] ); return true; } case ICN::HISCORE: { LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 9 ) { // Campaign title bar needs to include rating. const int32_t imageHeight = _icnVsSprite[id][7].height(); const fheroes2::Sprite temp = Crop( _icnVsSprite[id][7], 215, 0, 300, imageHeight ); Copy( temp, 0, 0, _icnVsSprite[id][7], 215 - 57, 0, temp.width(), imageHeight ); Copy( _icnVsSprite[id][6], 324, 0, _icnVsSprite[id][7], 324, 0, _icnVsSprite[id][6].width() - 324, imageHeight ); } return true; } case ICN::SPELLINL: { LoadOriginalICN( id ); if ( _icnVsSprite[id].size() > 11 ) { // Replace petrification spell mini-icon. fheroes2::h2d::readImage( "petrification_spell_icon_mini.image", _icnVsSprite[id][11] ); } return true; } case ICN::EMPTY_GOOD_BUTTON: case ICN::EMPTY_EVIL_BUTTON: { const bool isGoodInterface = ( id == ICN::EMPTY_GOOD_BUTTON ); const int32_t originalId = isGoodInterface ? ICN::SYSTEM : ICN::SYSTEME; loadICN( originalId ); if ( _icnVsSprite[originalId].size() < 13 ) { return true; } _icnVsSprite[id].resize( 2 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; released = _icnVsSprite[originalId][11]; Fill( released, 8, 7, 1, 1, getButtonFillingColor( true, isGoodInterface ) ); const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( originalId, 12 ); if ( originalPressed.width() > 2 && originalPressed.height() > 2 ) { pressed.resize( originalPressed.width(), originalPressed.height() ); // Copy the original pressed button but add the missing darker left side border from the released state Copy( released, 0, 0, pressed, 0, 0, 1, released.height() ); Copy( originalPressed, 0, 0, pressed, 1, 0, originalPressed.width() - 1, originalPressed.height() ); // Make the background transparent. FillTransform( pressed, 1, 0, pressed.width() - 1, 1, 1 ); FillTransform( pressed, pressed.width() - 1, 1, 1, pressed.height() - 1, 1 ); FillTransform( pressed, 1, 1, 2, 1, 1 ); FillTransform( pressed, 1, 2, 1, 1, 1 ); FillTransform( pressed, pressed.width() - 3, 1, 2, 1, 1 ); FillTransform( pressed, pressed.width() - 2, 2, 1, 1, 1 ); FillTransform( pressed, pressed.width() - 4, pressed.height() - 1, 3, 1, 1 ); FillTransform( pressed, pressed.width() - 3, pressed.height() - 2, 2, 1, 1 ); FillTransform( pressed, pressed.width() - 2, pressed.height() - 3, 1, 1, 1 ); } Fill( pressed, 90, 5, 1, 1, getButtonFillingColor( false, isGoodInterface ) ); return true; } case ICN::EMPTY_POL_BUTTON: { const int originalID = ICN::X_CMPBTN; loadICN( originalID ); if ( _icnVsSprite[originalID].size() < 8 ) { return true; } _icnVsSprite[id].resize( 2 ); // move dark border to new released state from original pressed state button const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( originalID, 4 ); const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( originalID, 5 ); if ( originalReleased.width() != 94 && originalPressed.width() != 94 && originalReleased.height() < 5 && originalPressed.height() < 5 ) { return true; } fheroes2::Sprite & releasedWithDarkBorder = _icnVsSprite[id][0]; releasedWithDarkBorder.resize( originalReleased.width() + 2, originalReleased.height() + 1 ); releasedWithDarkBorder.reset(); Copy( originalReleased, 0, 0, releasedWithDarkBorder, 1, 0, originalReleased.width(), originalReleased.height() ); Copy( originalReleased, 0, 2, releasedWithDarkBorder, 1, 21, 1, 1 ); Copy( originalReleased, 0, 2, releasedWithDarkBorder, 2, 22, 1, 1 ); Copy( originalPressed, 0, 2, releasedWithDarkBorder, 0, 3, 1, 19 ); Copy( originalPressed, 0, originalPressed.height() - 1, releasedWithDarkBorder, 0, originalPressed.height(), originalPressed.width(), 1 ); Copy( originalPressed, 0, 2, releasedWithDarkBorder, 1, 22, 1, 1 ); // pressed state fheroes2::Sprite & pressed = _icnVsSprite[id][1]; pressed.resize( originalPressed.width() + 2, originalPressed.height() + 1 ); pressed.reset(); Copy( originalPressed, 0, 0, pressed, 0, 1, originalPressed.width(), originalPressed.height() ); // the empty buttons need to be widened by 1 px so that they can be evenly divided by 3 in resizeButton() in ui_tools.cpp Copy( originalReleased, originalReleased.width() - 5, 0, releasedWithDarkBorder, releasedWithDarkBorder.width() - 5, 0, 5, originalReleased.height() ); Copy( originalPressed, originalPressed.width() - 5, 0, pressed, pressed.width() - 6, 1, 5, originalPressed.height() ); const int32_t pixelPosition = 4 * 94 + 6; Fill( releasedWithDarkBorder, 5, 3, 88, 18, originalReleased.image()[pixelPosition] ); Fill( pressed, 4, 5, 87, 17, originalPressed.image()[pixelPosition] ); return true; } case ICN::EMPTY_GUILDWELL_BUTTON: { const int originalID = ICN::WELLXTRA; loadICN( originalID ); if ( _icnVsSprite[originalID].size() < 3 ) { return true; } _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { const fheroes2::Sprite & original = fheroes2::AGG::GetICN( originalID, 0 + i ); fheroes2::Sprite & out = _icnVsSprite[id][i]; // the empty button needs to shortened by 1 px so that when it is divided by 3 in resizeButton() in ui_tools.h it will give an integer result out.resize( original.width() - 1, original.height() ); Copy( original, 0, 0, out, 0, 0, original.width() - 4, original.height() ); Copy( original, original.width() - 3, 0, out, original.width() - 4, 0, 3, original.height() ); Fill( out, 7 - i * 2, 2 + i, 50 + i, 14, getButtonFillingColor( i == 0 ) ); } return true; } case ICN::EMPTY_VERTICAL_GOOD_BUTTON: { const int32_t originalId = ICN::HSBTNS; loadICN( originalId ); if ( _icnVsSprite[originalId].size() < 9 ) { return true; } _icnVsSprite[id].resize( 2 ); const fheroes2::Sprite & originalReleased = fheroes2::AGG::GetICN( originalId, 2 ); const fheroes2::Sprite & originalPressed = fheroes2::AGG::GetICN( originalId, 3 ); fheroes2::Sprite & released = _icnVsSprite[id][0]; fheroes2::Sprite & pressed = _icnVsSprite[id][1]; if ( originalReleased.width() > 2 && originalReleased.height() > 2 && originalPressed.width() > 2 && originalPressed.height() > 2 ) { released.resize( originalReleased.width() + 1, originalReleased.height() ); pressed.resize( originalPressed.width() + 1, originalPressed.height() ); released.reset(); pressed.reset(); // Shorten the button by 1 pixel in the height so that it is evenly divided by 5 in resizeButton() in ui_button.cpp Copy( originalReleased, 0, 0, released, 1, 0, originalReleased.width(), originalReleased.height() - 7 ); Copy( originalPressed, 0, 0, pressed, 1, 0, originalPressed.width(), originalPressed.height() - 7 ); Copy( originalReleased, 0, originalReleased.height() - 7, released, 1, originalReleased.height() - 8, originalReleased.width(), originalReleased.height() - 7 ); Copy( originalPressed, 0, originalPressed.height() - 7, pressed, 1, originalPressed.height() - 8, originalPressed.width(), originalPressed.height() - 7 ); FillTransform( released, 1, 4, 1, released.height() - 4, 1 ); // Fix the carried over broken transform layer of the original vertical button that is being used. fheroes2::Image exitCommonMask = fheroes2::ExtractCommonPattern( { &released, &pressed } ); // Fix wrong non-transparent pixels of the transform layer that ExtractCommonPattern() missed. FillTransform( exitCommonMask, 4, 2, 1, 114, 1 ); FillTransform( exitCommonMask, 5, 115, 1, 2, 1 ); FillTransform( exitCommonMask, 6, 116, 17, 1, 1 ); FillTransform( exitCommonMask, exitCommonMask.width() - 4, 113, 1, 2, 1 ); invertTransparency( exitCommonMask ); // Make the extended width and height lines transparent. FillTransform( exitCommonMask, 0, 0, 1, exitCommonMask.height(), 1 ); FillTransform( exitCommonMask, exitCommonMask.width() - 4, exitCommonMask.height() - 1, 4, 1, 1 ); CopyTransformLayer( exitCommonMask, released ); CopyTransformLayer( exitCommonMask, pressed ); // Restore dark-brown lines on the left and bottom borders of the button backgrounds. const fheroes2::Sprite & originalDismiss = fheroes2::AGG::GetICN( ICN::HSBTNS, 0 ); Copy( originalReleased, 0, 4, released, 1, 4, 1, originalReleased.height() - 4 ); Copy( originalDismiss, 6, originalDismiss.height() - 7, released, 2, originalReleased.height() - 1, 22, 1 ); Copy( originalPressed, 0, 4, pressed, 1, 4, 1, originalPressed.height() - 4 ); Copy( originalDismiss, 6, originalDismiss.height() - 7, pressed, 2, originalPressed.height() - 1, 22, 1 ); // Clean the button states' text areas. Fill( released, 6, 4, 18, 110, getButtonFillingColor( true ) ); Fill( pressed, 5, 5, 18, 110, getButtonFillingColor( false ) ); // Make the pressed background transparent by removing remaining red parts. FillTransform( pressed, 5, 0, 21, 1, 1 ); FillTransform( pressed, pressed.width() - 3, 1, 2, 1, 1 ); FillTransform( pressed, pressed.width() - 2, 2, 2, 1, 1 ); FillTransform( pressed, pressed.width() - 1, 3, 1, originalPressed.height() - 5, 1 ); } return true; } case ICN::EMPTY_MAP_SELECT_BUTTON: { const int32_t originalId = ICN::NGEXTRA; loadICN( originalId ); if ( _icnVsSprite[originalId].size() < 80 ) { return true; } _icnVsSprite[id].resize( 2 ); for ( int32_t i = 0; i < static_cast( _icnVsSprite[id].size() ); ++i ) { const fheroes2::Sprite & original = fheroes2::AGG::GetICN( originalId, 64 + i ); fheroes2::Sprite & out = _icnVsSprite[id][i]; // the empty button needs to widened by 1 px so that when it is divided by 3 in resizeButton() in ui_tools.h it will // give an integer result out.resize( original.width() + 1, original.height() ); Copy( original, 0, 0, out, 0, 0, original.width() - 5, original.height() ); Copy( original, original.width() - 6, 0, out, original.width() - 5, 0, 6, original.height() ); Fill( out, 6 - i, 2 + 2 * i, 72, 15 - i, getButtonFillingColor( i == 0 ) ); } return true; } case ICN::EMPTY_INTERFACE_BUTTON_GOOD: case ICN::EMPTY_INTERFACE_BUTTON_EVIL: { const int originalId = ( id == ICN::EMPTY_INTERFACE_BUTTON_GOOD ) ? ICN::ADVBTNS : ICN::ADVEBTNS; loadICN( originalId ); _icnVsSprite[id].resize( 2 ); Copy( _icnVsSprite[originalId][2], _icnVsSprite[id][0] ); Copy( _icnVsSprite[originalId][3], _icnVsSprite[id][1] ); // Get the button's icon colors. const uint8_t backgroundReleasedColor = _icnVsSprite[originalId][2].image()[1 * 36 + 5]; const uint8_t backgroundPressedColor = _icnVsSprite[originalId][3].image()[5 * 36 + 6]; // Clean-up the buttons' background Fill( _icnVsSprite[id][0], 23, 5, 8, 5, backgroundReleasedColor ); Fill( _icnVsSprite[id][0], 8, 10, 24, 8, backgroundReleasedColor ); Fill( _icnVsSprite[id][0], 6, 18, 24, 10, backgroundReleasedColor ); Fill( _icnVsSprite[id][1], 22, 6, 8, 5, backgroundPressedColor ); Fill( _icnVsSprite[id][1], 7, 11, 24, 8, backgroundPressedColor ); Fill( _icnVsSprite[id][1], 5, 19, 24, 10, backgroundPressedColor ); return true; } case ICN::BRCREST: { LoadOriginalICN( id ); // First sprite in this ICN has incorrect transparent pixel at position 30x5. if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 50 && original.height() == 47 ) { original._disableTransformLayer(); original.image()[280] = 117; } } // An extra image for the neutral color (for Editor). if ( _icnVsSprite[id].size() == 7 ) { fheroes2::Sprite neutralShield( fheroes2::AGG::GetICN( ICN::SPELLS, 15 ) ); if ( neutralShield.width() < 2 || neutralShield.height() < 2 ) { // We can not make a new image if there is no original shield image. return true; } // Make original shield image contour transparent. ReplaceColorIdByTransformId( neutralShield, neutralShield.image()[1], 1U ); fheroes2::Sprite neutralColorSprite( _icnVsSprite[id][0].width(), _icnVsSprite[id][0].height() ); neutralColorSprite.reset(); Blit( neutralShield, neutralColorSprite, 8, 4 ); // Make the background. uint8_t * imageData = neutralColorSprite.image(); const uint8_t * transformData = neutralColorSprite.transform(); const int32_t imageWidth = neutralColorSprite.width(); const int32_t imageHeight = neutralColorSprite.height(); const int32_t imageSize = imageWidth * imageHeight; const int32_t startValueX = 12 * imageWidth; const int32_t startValueY = 12 * imageHeight; for ( int32_t y = 0; y < imageHeight; ++y ) { const int32_t offsetY = y * imageWidth; const int32_t offsetValueY = y * startValueX; for ( int32_t x = 0; x < imageWidth; ++x ) { if ( transformData[x + offsetY] == 0U ) { // Skip pixels with image. continue; } const uint8_t colorValue = static_cast( 10 + ( offsetValueY + ( imageWidth - x ) * startValueY ) / imageSize + ( x + y ) % 2 ); imageData[x + offsetY] = ( ( imageWidth - x - 1 ) * imageHeight > offsetY ) ? colorValue : 44U - colorValue; } } // Make all image non-transparent. neutralColorSprite._disableTransformLayer(); // We add shadow twice to make it more dark. addGradientShadow( neutralShield, neutralColorSprite, { 8, 4 }, { -2, 5 } ); addGradientShadow( neutralShield, neutralColorSprite, { 8, 4 }, { -2, 5 } ); _icnVsSprite[id].push_back( std::move( neutralColorSprite ) ); } return true; } case ICN::CBKGWATR: { // Ship battlefield background has incorrect transparent pixel at position 125x36. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & original = _icnVsSprite[id][0]; if ( original.width() == 640 && original.height() == 443 ) { original._disableTransformLayer(); original.image()[23165] = 24; } } return true; } case ICN::SWAPWIN: case ICN::WELLBKG: { // Hero Meeting dialog and Castle Well images can be used with disabled transform layer. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { _icnVsSprite[id][0]._disableTransformLayer(); } return true; } case ICN::GAME_OPTION_ICON: { _icnVsSprite[id].resize( 2 ); fheroes2::h2d::readImage( "hotkeys_icon.image", _icnVsSprite[id][0] ); fheroes2::h2d::readImage( "graphics_icon.image", _icnVsSprite[id][1] ); return true; } case ICN::COVR0010: case ICN::COVR0011: case ICN::COVR0012: { // The original image contains some foreign pixels that do not belong to the image. LoadOriginalICN( id ); if ( !_icnVsSprite[id].empty() ) { fheroes2::Sprite & sprite = _icnVsSprite[id][0]; const uint8_t * image = sprite.image(); const uint8_t * imageEnd = image + static_cast( sprite.width() ) * sprite.height(); uint8_t * transform = sprite.transform(); for ( ; image != imageEnd; ++image, ++transform ) { // Mask all non white/black or brown pixels. if ( *transform == 0 && *image > 36 && ( *image < 108 || *image > 130 ) ) { *transform = 1; } } } return true; } case ICN::OBJNDSRT: { LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 131 ) { _icnVsSprite[id].resize( 132 ); fheroes2::h2d::readImage( "missing_sphinx_part.image", _icnVsSprite[id][131] ); } return true; } case ICN::OBJNGRAS: { LoadOriginalICN( id ); if ( _icnVsSprite[id].size() == 151 ) { _icnVsSprite[id].resize( 155 ); loadICN( ICN::OBJNSNOW ); if ( _icnVsSprite[ICN::OBJNSNOW].size() > 210 ) { fheroes2::Sprite temp; fheroes2::h2d::readImage( "adventure-map-grass-cave-diff-01.image", temp ); _icnVsSprite[id][151] = _icnVsSprite[ICN::OBJNSNOW][2]; Blit( temp, _icnVsSprite[id][151] ); ReplaceColorIdByTransformId( _icnVsSprite[id][151], 255, 1 ); fheroes2::h2d::readImage( "adventure-map-grass-cave-diff-02.image", temp ); _icnVsSprite[id][152] = _icnVsSprite[ICN::OBJNSNOW][3]; Blit( temp, _icnVsSprite[id][152] ); ReplaceColorIdByTransformId( _icnVsSprite[id][152], 255, 1 ); fheroes2::h2d::readImage( "lean-to-diff-part1.image", temp ); _icnVsSprite[id][153] = _icnVsSprite[ICN::OBJNSNOW][12]; Blit( temp, _icnVsSprite[id][153] ); ReplaceColorIdByTransformId( _icnVsSprite[id][153], 253, 1 ); ReplaceColorIdByTransformId( _icnVsSprite[id][153], 254, 2 ); ReplaceColorIdByTransformId( _icnVsSprite[id][153], 255, 3 ); fheroes2::h2d::readImage( "lean-to-diff-part2.image", temp ); _icnVsSprite[id][154] = _icnVsSprite[ICN::OBJNSNOW][13]; Blit( temp, _icnVsSprite[id][154] ); ReplaceColorIdByTransformId( _icnVsSprite[id][154], 253, 1 ); ReplaceColorIdByTransformId( _icnVsSprite[id][154], 254, 2 ); ReplaceColorIdByTransformId( _icnVsSprite[id][154], 255, 3 ); } } return true; } case ICN::OBJNMUL2: { LoadOriginalICN( id ); auto & images = _icnVsSprite[id]; if ( images.size() == 218 ) { // Expand the existing set of Adventure Map objects: // - 2 extra River Delta objects. Each object has 7 image parts. // - 1 new Stone Liths with 3 image parts. // - 3 new variants of Observation Tower object. In total, 6 new image parts. images.resize( 218 + ( 7 * 2 ) + 3 + 6 ); // 2 River Deltas. for ( size_t i = 0; i < 14; ++i ) { images[218 + i].resize( images[i].height(), images[i].width() ); fheroes2::Transpose( images[i], images[218 + i] ); images[218 + i].setPosition( images[i].y(), images[i].x() ); } // 1 Stone Liths. fheroes2::Sprite temp; fheroes2::h2d::readImage( "circular_stone_liths_center.image", temp ); images[232].resize( 32, 32 ); images[232].reset(); Copy( temp, 0, 0, images[232], 0, 0, temp.width(), temp.height() ); Copy( images[116], 0, temp.height(), images[232], 0, temp.height(), images[116].width(), images[116].height() - temp.height() ); fheroes2::h2d::readImage( "circular_stone_liths_left.image", images[233] ); fheroes2::h2d::readImage( "circular_stone_liths_top.image", images[234] ); // Generic Observation Tower. images[235] = images[201]; fheroes2::h2d::readImage( "observation_tower_generic_bottom_part.image", temp ); Blit( temp, 0, 0, images[235], 0, temp.y() - images[235].y(), temp.width(), temp.height() ); // Desert Observation Tower. images[236] = images[201]; fheroes2::h2d::readImage( "observation_tower_desert_bottom_part.image", temp ); Blit( temp, 0, 0, images[236], 0, temp.y() - images[236].y(), temp.width(), temp.height() ); fheroes2::h2d::readImage( "observation_tower_desert_right_part.image", images[237] ); // Snow Observation Tower. images[238] = images[201]; fheroes2::h2d::readImage( "observation_tower_snow_bottom_part.image", temp ); Blit( temp, 0, 0, images[238], 0, temp.y() - images[238].y(), temp.width(), temp.height() ); fheroes2::h2d::readImage( "observation_tower_snow_right_part.image", images[239] ); images[240] = images[198]; fheroes2::h2d::readImage( "observation_tower_snow_top_part.image", temp ); Blit( temp, 0, 0, images[240], 0, 0, temp.width(), temp.height() ); } return true; } case ICN::SCENIBKG_EVIL: { const int32_t originalId = ICN::SCENIBKG; loadICN( originalId ); if ( _icnVsSprite[originalId].size() != 1 ) { return true; } _icnVsSprite[id].resize( 1 ); const auto & originalImage = _icnVsSprite[originalId][0]; auto & outputImage = _icnVsSprite[id][0]; outputImage = originalImage; convertToEvilInterface( outputImage, { 0, 0, outputImage.width(), outputImage.height() } ); loadICN( ICN::METALLIC_BORDERED_TEXTBOX_EVIL ); if ( _icnVsSprite[ICN::METALLIC_BORDERED_TEXTBOX_EVIL].empty() ) { return true; } const auto & evilTextBox = _icnVsSprite[ICN::METALLIC_BORDERED_TEXTBOX_EVIL][0]; // The original text area is shorter than one we are using so we need to make 2 image copy operations to compensate this. const int32_t textWidth = 361; fheroes2::Copy( evilTextBox, 0, 0, outputImage, 46, 23, textWidth / 2, evilTextBox.height() ); fheroes2::Copy( evilTextBox, evilTextBox.width() - ( textWidth - textWidth / 2 ), 0, outputImage, 46 + textWidth / 2, 23, ( textWidth - textWidth / 2 ), evilTextBox.height() ); return true; } default: break; } return false; } void loadICN( const int id ) { if ( !_icnVsSprite[id].empty() ) { // The images have been loaded. return; } if ( !LoadModifiedICN( id ) ) { LoadOriginalICN( id ); } if ( _icnVsSprite[id].empty() ) { // This could happen by one reason: asking to render an ICN that simply doesn't exist within the resources. // In order to avoid subsequent attempts to get resources from this ICN we are making it as non-empty. _icnVsSprite[id].resize( 1 ); } } size_t GetMaximumICNIndex( int id ) { loadICN( id ); return _icnVsSprite[id].size(); } size_t GetMaximumTILIndex( const int id ) { auto & tilImages = _tilVsImage[id]; if ( tilImages.empty() ) { tilImages.resize( 4 ); // 4 possible sides const std::vector & data = ::AGG::getDataFromAggFile( tilFileName[id], false ); if ( data.size() < headerSize ) { // The important resource is absent! Make sure that you are using the correct version of the game. assert( 0 ); return 0; } ROStreamBuf buffer( data ); const size_t count = buffer.getLE16(); const int32_t width = buffer.getLE16(); const int32_t height = buffer.getLE16(); if ( count < 1 || width < 1 || height < 1 || ( headerSize + count * width * height ) != data.size() ) { return 0; } std::vector & originalTIL = tilImages[0]; decodeTILImages( data.data() + headerSize, count, width, height, originalTIL ); for ( uint32_t shapeId = 1; shapeId < 4; ++shapeId ) { tilImages[shapeId].resize( count ); } for ( size_t i = 0; i < count; ++i ) { for ( uint32_t shapeId = 1; shapeId < 4; ++shapeId ) { fheroes2::Image & image = tilImages[shapeId][i]; const bool horizontalFlip = ( shapeId & 2 ) != 0; const bool verticalFlip = ( shapeId & 1 ) != 0; image._disableTransformLayer(); image.resize( width, height ); Flip( originalTIL[i], 0, 0, image, 0, 0, width, height, horizontalFlip, verticalFlip ); } } } return tilImages[0].size(); } // We have few ICNs which we need to scale like some related to main screen bool IsScalableICN( const int id ) { switch ( id ) { case ICN::EDITOR: case ICN::HEROES: case ICN::BTNSHNGL: case ICN::SHNGANIM: return true; default: return false; } } const fheroes2::Sprite & GetScaledICN( const int icnId, const uint32_t index ) { const fheroes2::Sprite & originalIcn = _icnVsSprite[icnId][index]; const fheroes2::Display & display = fheroes2::Display::instance(); if ( display.width() == fheroes2::Display::DEFAULT_WIDTH && display.height() == fheroes2::Display::DEFAULT_HEIGHT ) { return originalIcn; } if ( _icnVsScaledSprite[icnId].empty() ) { _icnVsScaledSprite[icnId].resize( _icnVsSprite[icnId].size() ); } fheroes2::Sprite & resizedIcn = _icnVsScaledSprite[icnId][index]; if ( originalIcn.singleLayer() && !resizedIcn.singleLayer() ) { resizedIcn._disableTransformLayer(); } const double scaleFactorX = static_cast( display.width() ) / fheroes2::Display::DEFAULT_WIDTH; const double scaleFactorY = static_cast( display.height() ) / fheroes2::Display::DEFAULT_HEIGHT; const double scaleFactor = std::min( scaleFactorX, scaleFactorY ); const int32_t resizedWidth = static_cast( std::lround( originalIcn.width() * scaleFactor ) ); const int32_t resizedHeight = static_cast( std::lround( originalIcn.height() * scaleFactor ) ); const int32_t offsetX = static_cast( std::lround( display.width() - fheroes2::Display::DEFAULT_WIDTH * scaleFactor ) ) / 2; const int32_t offsetY = static_cast( std::lround( display.height() - fheroes2::Display::DEFAULT_HEIGHT * scaleFactor ) ) / 2; assert( offsetX >= 0 && offsetY >= 0 ); // Resize only if needed if ( resizedIcn.height() != resizedHeight || resizedIcn.width() != resizedWidth ) { resizedIcn.resize( resizedWidth, resizedHeight ); resizedIcn.setPosition( static_cast( std::lround( originalIcn.x() * scaleFactor ) ) + offsetX, static_cast( std::lround( originalIcn.y() * scaleFactor ) ) + offsetY ); Resize( originalIcn, resizedIcn ); } else { // No need to resize but we have to update the offset. resizedIcn.setPosition( static_cast( std::lround( originalIcn.x() * scaleFactor ) ) + offsetX, static_cast( std::lround( originalIcn.y() * scaleFactor ) ) + offsetY ); } return resizedIcn; } } namespace fheroes2::AGG { const Sprite & GetICN( int icnId, uint32_t index ) { if ( !IsValidICNId( icnId ) ) { return errorImage; } if ( index >= GetMaximumICNIndex( icnId ) ) { return errorImage; } if ( IsScalableICN( icnId ) ) { return GetScaledICN( icnId, index ); } return _icnVsSprite[icnId][index]; } uint32_t GetICNCount( int icnId ) { if ( !IsValidICNId( icnId ) ) { return 0; } return static_cast( GetMaximumICNIndex( icnId ) ); } const Image & GetTIL( int tilId, uint32_t index, uint32_t shapeId ) { if ( shapeId > 3 ) { return errorImage; } if ( !IsValidTILId( tilId ) ) { return errorImage; } const size_t maxTILIndex = GetMaximumTILIndex( tilId ); if ( index >= maxTILIndex ) { return errorImage; } return _tilVsImage[tilId][shapeId][index]; } void updateLanguageDependentResources( const SupportedLanguage language, const bool loadOriginalAlphabet ) { if ( loadOriginalAlphabet || !isAlphabetSupported( language ) ) { if ( !alphabetPreserver.isPreserved() ) { // This can happen when we try to change a language without loading assets. alphabetPreserver.preserve(); } else { alphabetPreserver.restore(); } } else { alphabetPreserver.preserve(); // Restore original letters when changing language to avoid changes to them being carried over. alphabetPreserver.restore(); generateAlphabet( language, _icnVsSprite ); } generateButtonAlphabet( language, _icnVsSprite ); // Clear language dependent resources. for ( const int id : languageDependentIcnId ) { _icnVsSprite[id].clear(); } } } fheroes2-1.1.6+dfsg/src/fheroes2/agg/agg_image.h000066400000000000000000000040201476115357100212740ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace fheroes2 { class Image; class Sprite; enum class SupportedLanguage : uint8_t; namespace AGG { const Sprite & GetICN( int icnId, uint32_t index ); uint32_t GetICNCount( int icnId ); // shapeId could be 0, 1, 2 or 3 only const Image & GetTIL( int tilId, uint32_t index, uint32_t shapeId ); // This function must be called only at the time of setting up a new language. void updateLanguageDependentResources( const SupportedLanguage language, const bool loadOriginalAlphabet ); } } fheroes2-1.1.6+dfsg/src/fheroes2/agg/bin_info.cpp000066400000000000000000000556671476115357100215410ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "bin_info.h" #include #include #include #include #include #include #include #include "agg.h" #include "battle_cell.h" #include "logging.h" #include "monster.h" #include "monster_info.h" #include "serialize.h" namespace { template T getValue( const uint8_t * data, const size_t base, const size_t offset = 0 ) { return fheroes2::getLEValue( reinterpret_cast( data ), base, offset ); } const char * GetFilename( const int monsterId ) { return fheroes2::getMonsterData( monsterId ).binFileName; } class MonsterAnimCache { public: Bin_Info::MonsterAnimInfo getAnimInfo( const int monsterID ) { auto mapIterator = _animMap.find( monsterID ); if ( mapIterator != _animMap.end() ) { return mapIterator->second; } Bin_Info::MonsterAnimInfo info( monsterID, AGG::getDataFromAggFile( GetFilename( monsterID ), false ) ); if ( info.isValid() ) { _animMap[monsterID] = info; return info; } DEBUG_LOG( DBG_GAME, DBG_WARN, "Missing BIN file data: " << GetFilename( monsterID ) << ", monster ID: " << monsterID ) return {}; } private: std::map _animMap; }; MonsterAnimCache _infoCache; } namespace Bin_Info { const size_t CORRECT_FRM_LENGTH = 821; // When base unit and its upgrade use the same FRM file (e.g. Archer and Ranger) // We modify animation speed value to make them go faster const double MOVE_SPEED_UPGRADE = 0.12; const double SHOOT_SPEED_UPGRADE = 0.08; const double RANGER_SHOOT_SPEED = 0.78; MonsterAnimInfo::MonsterAnimInfo( int monsterID, const std::vector & bytes ) : moveSpeed( 450 ) , shootSpeed( 0 ) , flightSpeed( 0 ) , troopCountOffsetLeft( 0 ) , troopCountOffsetRight( 0 ) , idleAnimationCount( 0 ) , idleAnimationDelay( 0 ) { if ( bytes.size() != Bin_Info::CORRECT_FRM_LENGTH ) { return; } const uint8_t * data = bytes.data(); eyePosition = { getValue( data, 1 ), getValue( data, 3 ) }; for ( size_t moveID = 0; moveID < 7; ++moveID ) { std::vector moveOffset; moveOffset.reserve( 16 ); for ( int frame = 0; frame < 16; ++frame ) { moveOffset.push_back( static_cast( getValue( data, 5 + moveID * 16, frame ) ) ); } frameXOffset.emplace_back( std::move( moveOffset ) ); } // Idle animations data idleAnimationCount = data[117]; if ( idleAnimationCount > 5u ) idleAnimationCount = 5u; // here we need to reset our object for ( uint32_t i = 0; i < idleAnimationCount; ++i ) idlePriority.push_back( getValue( data, 118, i ) ); for ( uint32_t i = 0; i < idleAnimationCount; ++i ) unusedIdleDelays.push_back( getValue( data, 138, i ) ); idleAnimationDelay = getValue( data, 158 ); // Monster speed data moveSpeed = getValue( data, 162 ); shootSpeed = getValue( data, 166 ); flightSpeed = getValue( data, 170 ); // Projectile data for ( size_t i = 0; i < 3; ++i ) { projectileOffset.emplace_back( getValue( data, 174 + ( i * 4 ) ), getValue( data, 176 + ( i * 4 ) ) ); } // We change all projectile start positions to match the last projectile position in shooting animation, // this position will be used to calculate the projectile path, but will not be used in rendering. if ( monsterID == Monster::ARCHER || monsterID == Monster::RANGER ) { projectileOffset[0].x -= 30; projectileOffset[0].y += 5; projectileOffset[1].x -= 46; projectileOffset[1].y -= 5; projectileOffset[2].x -= 30; projectileOffset[2].y -= 40; } if ( monsterID == Monster::ORC || monsterID == Monster::ORC_CHIEF ) { for ( fheroes2::Point & offset : projectileOffset ) { offset.x -= 20; offset.y = -36; } } if ( monsterID == Monster::TROLL || monsterID == Monster::WAR_TROLL ) { projectileOffset[0].x -= 30; projectileOffset[0].y -= 5; projectileOffset[1].x -= 14; --projectileOffset[1].y; projectileOffset[2].x -= 15; projectileOffset[2].y -= 19; } if ( monsterID == Monster::ELF || monsterID == Monster::GRAND_ELF ) { projectileOffset[0].x -= 19; projectileOffset[0].y += 22; projectileOffset[1].x -= 40; --projectileOffset[1].y; projectileOffset[2].x -= 19; // IMPORTANT: In BIN file Elves and Grand Elves have incorrect start Y position for lower shooting attack ( -1 ). projectileOffset[2].y = -54; } if ( monsterID == Monster::DRUID || monsterID == Monster::GREATER_DRUID ) { projectileOffset[0].x -= 12; projectileOffset[0].y += 23; projectileOffset[1].x -= 20; projectileOffset[2].x -= 7; projectileOffset[2].y -= 21; } if ( monsterID == Monster::CENTAUR ) { projectileOffset[0].x -= 24; projectileOffset[0].y += 31; projectileOffset[1].x -= 32; projectileOffset[1].y += 2; projectileOffset[2].x -= 24; projectileOffset[2].y -= 27; } if ( monsterID == Monster::HALFLING ) { projectileOffset[0].x -= 7; projectileOffset[0].y += 11; projectileOffset[1].x -= 21; projectileOffset[1].y += 10; projectileOffset[2].x -= 9; projectileOffset[2].y -= 14; } if ( monsterID == Monster::MAGE || monsterID == Monster::ARCHMAGE ) { projectileOffset[0].y -= 2; projectileOffset[2].y += 2; } if ( monsterID == Monster::TITAN ) { projectileOffset[0].x -= 10; projectileOffset[0].y += 22; projectileOffset[1].x -= 20; projectileOffset[1].y += 8; projectileOffset[2].x -= 15; projectileOffset[2].y -= 22; } if ( monsterID == Monster::LICH || monsterID == Monster::POWER_LICH ) { projectileOffset[0].x -= 5; projectileOffset[0].y += 6; projectileOffset[1].x -= 16; projectileOffset[1].y -= 9; projectileOffset[2].x -= 9; projectileOffset[2].y -= 7; } uint8_t projectileCount = data[186]; if ( projectileCount > 12u ) projectileCount = 12u; // here we need to reset our object for ( uint8_t i = 0; i < projectileCount; ++i ) projectileAngles.push_back( getValue( data, 187, i ) ); // Positional offsets for sprites & drawing troopCountOffsetLeft = getValue( data, 235 ); troopCountOffsetRight = getValue( data, 239 ); // Load animation sequences themselves for ( int idx = MOVE_START; idx <= SHOOT3_END; ++idx ) { std::vector anim; uint8_t count = data[243 + idx]; if ( count > 16 ) count = 16; // here we need to reset our object for ( uint8_t frame = 0; frame < count; ++frame ) { anim.push_back( static_cast( data[277 + idx * 16 + frame] ) ); } animationFrames.emplace_back( std::move( anim ) ); } if ( monsterID == Monster::WOLF ) { // Wolves have incorrect frame for lower attack animation if ( animationFrames[ATTACK3].size() == 3 && animationFrames[ATTACK3][0] == 16 ) { animationFrames[ATTACK3][0] = 2; } if ( animationFrames[ATTACK3_END].size() == 3 && animationFrames[ATTACK3_END][2] == 16 ) { animationFrames[ATTACK3_END][2] = 2; } } if ( monsterID == Monster::DWARF || monsterID == Monster::BATTLE_DWARF ) { // Dwarves and Battle Dwarves have incorrect death animation. if ( animationFrames[DEATH].size() == 8 ) { animationFrames[DEATH].clear(); for ( int frameId = 49; frameId <= 55; ++frameId ) { animationFrames[DEATH].push_back( frameId ); } } } // Modify AnimInfo for upgraded monsters without own FRM file int speedDiff = 0; switch ( monsterID ) { case Monster::RANGER: case Monster::VETERAN_PIKEMAN: case Monster::MASTER_SWORDSMAN: case Monster::CHAMPION: case Monster::CRUSADER: case Monster::ORC_CHIEF: case Monster::OGRE_LORD: case Monster::WAR_TROLL: case Monster::BATTLE_DWARF: case Monster::GRAND_ELF: case Monster::GREATER_DRUID: case Monster::MINOTAUR_KING: case Monster::STEEL_GOLEM: case Monster::ARCHMAGE: case Monster::MUTANT_ZOMBIE: case Monster::ROYAL_MUMMY: case Monster::VAMPIRE_LORD: case Monster::POWER_LICH: speedDiff = static_cast( Monster( monsterID ).GetSpeed() ) - Monster( monsterID - 1 ).GetSpeed(); break; case Monster::EARTH_ELEMENT: case Monster::AIR_ELEMENT: case Monster::WATER_ELEMENT: speedDiff = static_cast( Monster( monsterID ).GetSpeed() ) - Monster( Monster::FIRE_ELEMENT ).GetSpeed(); break; default: break; } if ( std::abs( speedDiff ) > 0 ) { moveSpeed = static_cast( ( 1 - MOVE_SPEED_UPGRADE * speedDiff ) * moveSpeed ); // Ranger is special since he gets double attack on upgrade if ( monsterID == Monster::RANGER ) { shootSpeed = static_cast( shootSpeed * RANGER_SHOOT_SPEED ); } else { shootSpeed = static_cast( ( 1 - SHOOT_SPEED_UPGRADE * speedDiff ) * shootSpeed ); } } if ( frameXOffset[MOVE_STOP][0] == 0 && frameXOffset[MOVE_TILE_END][0] != 0 ) frameXOffset[MOVE_STOP][0] = frameXOffset[MOVE_TILE_END][0]; for ( int idx = MOVE_START; idx <= MOVE_ONE; ++idx ) frameXOffset[idx].resize( animationFrames[idx].size(), 0 ); if ( frameXOffset[MOVE_STOP].size() == 1 && frameXOffset[MOVE_STOP][0] == 0 ) { if ( frameXOffset[MOVE_TILE_END].size() == 1 && frameXOffset[MOVE_TILE_END][0] != 0 ) frameXOffset[MOVE_STOP][0] = frameXOffset[MOVE_TILE_END][0]; else if ( frameXOffset[MOVE_TILE_START].size() == 1 && frameXOffset[MOVE_TILE_START][0] != 0 ) frameXOffset[MOVE_STOP][0] = 44 + frameXOffset[MOVE_TILE_START][0]; else frameXOffset[MOVE_STOP][0] = frameXOffset[MOVE_MAIN].back(); } // Movement animation fix for Iron and Steel Golem. Also check that the data sizes are correct. if ( ( monsterID == Monster::IRON_GOLEM || monsterID == Monster::STEEL_GOLEM ) && ( frameXOffset[MOVE_START].size() == 4 && frameXOffset[MOVE_MAIN].size() == 7 && animationFrames[MOVE_MAIN].size() == 7 ) ) { // the original golem info frameXOffset[MOVE_START][0] = 0; frameXOffset[MOVE_START][1] = Battle::Cell::widthPx * 1 / 8; frameXOffset[MOVE_START][2] = Battle::Cell::widthPx * 2 / 8 + 3; frameXOffset[MOVE_START][3] = Battle::Cell::widthPx * 3 / 8; // 'MOVE_MAIN' animation is missing 1/4 of animation start. 'MOVE_START' (for first and one cell move) has this 1/4 of animation, // but 'MOVE_TILE_START` (for movement after the first cell) is empty, so we move all frames except the last frame from 'MOVE_MAIN' // to the end of 'MOVE_START' animationFrames. And prepare 'MOVE_TILE_START' for new animation frame IDs. animationFrames[MOVE_TILE_START].resize( animationFrames[MOVE_TILE_START].size() + animationFrames[MOVE_MAIN].size() - 1 ); animationFrames[MOVE_START].insert( animationFrames[MOVE_START].end(), animationFrames[MOVE_MAIN].begin(), animationFrames[MOVE_MAIN].end() - 1 ); animationFrames[MOVE_MAIN].erase( animationFrames[MOVE_MAIN].begin(), animationFrames[MOVE_MAIN].end() - 1 ); // Do the same for 'x' offset vector and make a copy to 'MOVE_TILE_START'. frameXOffset[MOVE_START].insert( frameXOffset[MOVE_START].end(), frameXOffset[MOVE_MAIN].begin(), frameXOffset[MOVE_MAIN].end() - 1 ); frameXOffset[MOVE_TILE_START] = frameXOffset[MOVE_MAIN]; frameXOffset[MOVE_TILE_START].pop_back(); frameXOffset[MOVE_MAIN].erase( frameXOffset[MOVE_MAIN].begin(), frameXOffset[MOVE_MAIN].end() - 1 ); // Correct the 'x' offset by half of cell. frameXOffset[MOVE_MAIN][0] += Battle::Cell::widthPx / 2; for ( size_t id = 0; id < frameXOffset[MOVE_TILE_START].size(); ++id ) { frameXOffset[MOVE_START][id + 4] += Battle::Cell::widthPx / 2; // For 'MOVE_TILE_START' also include the correction, made in "agg_image.cpp". frameXOffset[MOVE_TILE_START][id] += Battle::Cell::widthPx / 2 - ( 6 - static_cast( id ) ) * Battle::Cell::widthPx / 28; // For 'MOVE_TILE_START' animation frames IDs use new frames, made in "agg_image.cpp", which starts from ID = 40. animationFrames[MOVE_TILE_START][id] = 40 + static_cast( id ); } } // The Ogre has a duplicate frame of the 'STATIC' animation at the start of the 'MOVE_MAIN' animation, making him to move non-smoothly. if ( ( monsterID == Monster::OGRE || monsterID == Monster::OGRE_LORD ) && frameXOffset[MOVE_MAIN].size() == 9 && animationFrames[MOVE_MAIN].size() == 9 ) { animationFrames[MOVE_MAIN].erase( animationFrames[MOVE_MAIN].begin() ); frameXOffset[MOVE_MAIN].erase( frameXOffset[MOVE_MAIN].begin() ); } // Some creatures needs their 'x' offset in moving animations to be bigger by 3px to avoid sprite shift in Well and during diagonal movement. if ( monsterID == Monster::ORC || monsterID == Monster::ORC_CHIEF || monsterID == Monster::OGRE || monsterID == Monster::OGRE_LORD || monsterID == Monster::DWARF || monsterID == Monster::BATTLE_DWARF || monsterID == Monster::UNICORN || monsterID == Monster::CENTAUR || monsterID == Monster::BOAR || monsterID == Monster::LICH || monsterID == Monster::POWER_LICH || monsterID == Monster::ROGUE ) { for ( const int animType : { MOVE_START, MOVE_TILE_START, MOVE_MAIN, MOVE_TILE_END, MOVE_STOP, MOVE_ONE } ) { for ( int & xOffset : frameXOffset[animType] ) { xOffset += 3; } } } // Archers/Rangers needs their 'x' offset in moving animations to be bigger by 1px to avoid sprite shift in Well and during diagonal movement. if ( monsterID == Monster::ARCHER || monsterID == Monster::RANGER ) { for ( const int animType : { MOVE_MAIN, MOVE_ONE } ) { for ( int & xOffset : frameXOffset[animType] ) { ++xOffset; } } } // Paladin/Crusader needs their 'x' offset in moving animations to be lower by 1px to avoid sprite shift in Well and during diagonal movement. if ( ( monsterID == Monster::PALADIN || monsterID == Monster::CRUSADER ) && frameXOffset[MOVE_MAIN].size() == 8 && animationFrames[MOVE_MAIN].size() == 8 ) { for ( const int animType : { MOVE_MAIN, MOVE_ONE } ) { for ( int & xOffset : frameXOffset[animType] ) { --xOffset; } // The 5th and 8th frames needs extra shift by 2 and 1 pixel. frameXOffset[animType][4] -= 2; --frameXOffset[animType][7]; } } // Goblins needs their 'x' offset in moving animations to be bigger by 6px to avoid sprite shift in Well and during diagonal movement. if ( monsterID == Monster::GOBLIN ) { for ( const int animType : { MOVE_TILE_START, MOVE_MAIN, MOVE_STOP, MOVE_ONE } ) { for ( int & xOffset : frameXOffset[animType] ) { xOffset += 6; } } } // Trolls needs their 'x' offset in moving animations to be bigger by 2px to avoid sprite shift in Well and during diagonal movement. if ( ( monsterID == Monster::TROLL || monsterID == Monster::WAR_TROLL ) && frameXOffset[MOVE_MAIN].size() == 14 && frameXOffset[MOVE_ONE].size() == 14 ) { for ( const int animType : { MOVE_MAIN, MOVE_ONE } ) { for ( int & xOffset : frameXOffset[animType] ) { xOffset += 2; } // The 7th and 14th frames needs extra shift by 1 px. ++frameXOffset[animType][6]; ++frameXOffset[animType][13]; } } // Giants/Titians needs their 'x' offset in moving animations to be corrected to avoid sprite shift in Well and during diagonal movement. if ( ( monsterID == Monster::GIANT || monsterID == Monster::TITAN ) && frameXOffset[MOVE_MAIN].size() == 7 && frameXOffset[MOVE_ONE].size() == 7 ) { for ( const int animType : { MOVE_MAIN, MOVE_ONE } ) { frameXOffset[animType][0] += 3; frameXOffset[animType][1] += 2; frameXOffset[animType][2] += 2; ++frameXOffset[animType][5]; ++frameXOffset[animType][6]; } } // Nomad needs their 'x' offset in moving animations to be corrected to avoid one sprite shift in Well and during diagonal movement. if ( monsterID == Monster::NOMAD && frameXOffset[MOVE_MAIN].size() == 8 && frameXOffset[MOVE_ONE].size() == 8 ) { for ( const int animType : { MOVE_MAIN, MOVE_ONE } ) { frameXOffset[animType][2] -= 2; } } // Nomad needs their 'x' offset in moving animations to be corrected to avoid one sprite shift in Well and during diagonal movement. if ( monsterID == Monster::MEDUSA && frameXOffset[MOVE_MAIN].size() == 15 && frameXOffset[MOVE_ONE].size() == 15 ) { for ( const int animType : { MOVE_MAIN, MOVE_ONE } ) { frameXOffset[animType][3] += 2; frameXOffset[animType][4] += 2; ++frameXOffset[animType][5]; ++frameXOffset[animType][9]; frameXOffset[animType][10] += 2; ++frameXOffset[animType][11]; ++frameXOffset[animType][14]; } } // Elementals needs their 'x' offset in moving animations to be corrected to avoid sprite shift in Well and during diagonal movement. if ( ( monsterID == Monster::EARTH_ELEMENT || monsterID == Monster::AIR_ELEMENT || monsterID == Monster::FIRE_ELEMENT || monsterID == Monster::WATER_ELEMENT ) && frameXOffset[MOVE_MAIN].size() == 8 && frameXOffset[MOVE_ONE].size() == 8 ) { for ( const int animType : { MOVE_MAIN, MOVE_ONE } ) { frameXOffset[animType][0] += 3; frameXOffset[animType][1] += 3; frameXOffset[animType][2] += 5; frameXOffset[animType][3] += 3; --frameXOffset[animType][5]; ++frameXOffset[animType][6]; --frameXOffset[animType][7]; } } // X offset fix for Swordsman. if ( ( monsterID == Monster::SWORDSMAN || monsterID == Monster::MASTER_SWORDSMAN ) && frameXOffset[MOVE_START].size() == 2 && frameXOffset[MOVE_STOP].size() == 1 ) { frameXOffset[MOVE_START][0] = 0; frameXOffset[MOVE_START][1] = Battle::Cell::widthPx * 1 / 8; for ( int & xOffset : frameXOffset[MOVE_MAIN] ) { xOffset += Battle::Cell::widthPx / 4 + 3; } frameXOffset[MOVE_STOP][0] = Battle::Cell::widthPx; } } bool MonsterAnimInfo::isValid() const { if ( animationFrames.size() != SHOOT3_END + 1 ) return false; // Absolute minimal set up const int essentialAnimations[7] = { MOVE_MAIN, STATIC, DEATH, WINCE_UP, ATTACK1, ATTACK2, ATTACK3 }; for ( int i = 0; i < 7; ++i ) { if ( animationFrames.at( essentialAnimations[i] ).empty() ) return false; } if ( idlePriority.size() != static_cast( idleAnimationCount ) ) return false; return true; } bool MonsterAnimInfo::hasAnim( int animID ) const { return animationFrames.size() == SHOOT3_END + 1 && !animationFrames.at( animID ).empty(); } size_t MonsterAnimInfo::getProjectileID( const double angle ) const { const std::vector & angles = projectileAngles; if ( angles.empty() ) return 0; for ( size_t id = 0u; id < angles.size() - 1; ++id ) { if ( angle >= static_cast( angles[id] + angles[id + 1] ) / 2.0 ) return id; } return angles.size() - 1; } MonsterAnimInfo GetMonsterInfo( uint32_t monsterID ) { return _infoCache.getAnimInfo( monsterID ); } } fheroes2-1.1.6+dfsg/src/fheroes2/agg/bin_info.h000066400000000000000000000077031476115357100211720ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include "math_base.h" namespace Bin_Info { struct MonsterAnimInfo { enum ANIM_TYPE { MOVE_START, // Start of the moving sequence on 1st animation cycle: flyers will fly up MOVE_TILE_START, // Supposed to be played at the beginning of 2nd+ move. MOVE_MAIN, // Core animation. Most units only have this one. MOVE_TILE_END, // Cavalry & wolf. Played at the end of the cycle (2nd tile to 3rd), but not at the last one MOVE_STOP, // End of the moving sequence when arrived: landing for example MOVE_ONE, // Used when moving 1 tile. LICH and POWER_LICH doesn't have this, use MOVE_MAIN TEMPORARY, // This is an empty placeholder for combined animation built from previous parts STATIC, // Frame 1 IDLE1, IDLE2, // Idle animations: picked at random with different probabilities, rarely all 5 present IDLE3, IDLE4, IDLE5, DEATH, WINCE_UP, WINCE_END, ATTACK1, // Attacks, number represents the angle: 1 is TOP, 2 is CENTER, 3 is BOTTOM ATTACK1_END, DOUBLEHEX1, DOUBLEHEX1_END, ATTACK2, ATTACK2_END, DOUBLEHEX2, DOUBLEHEX2_END, ATTACK3, ATTACK3_END, DOUBLEHEX3, DOUBLEHEX3_END, SHOOT1, SHOOT1_END, SHOOT2, SHOOT2_END, SHOOT3, SHOOT3_END }; std::vector> frameXOffset; uint32_t moveSpeed; uint32_t shootSpeed; uint32_t flightSpeed; fheroes2::Point eyePosition; int32_t troopCountOffsetLeft; int32_t troopCountOffsetRight; std::vector projectileOffset; std::vector projectileAngles; std::vector idlePriority; std::vector unusedIdleDelays; uint32_t idleAnimationCount; uint32_t idleAnimationDelay; std::vector> animationFrames; MonsterAnimInfo( int monsterID = 0, const std::vector & bytes = std::vector() ); bool hasAnim( int animID = MonsterAnimInfo::STATIC ) const; bool isValid() const; size_t getProjectileID( const double angle ) const; }; MonsterAnimInfo GetMonsterInfo( uint32_t monsterID ); } fheroes2-1.1.6+dfsg/src/fheroes2/agg/icn.cpp000066400000000000000000001370771476115357100205230ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "icn.h" #include #include #include "color.h" #include "heroes.h" #include "race.h" #include "settings.h" namespace { struct ICNMapItem { int type; const char * string; }; } namespace ICN { // Make sure that each item ID has exactly the same location ID! const std::array icnMap = { { { UNKNOWN, "UNKNOWN" }, { ADVBORDE, "ADVBORDE.ICN" }, { ADVBORD, "ADVBORD.ICN" }, { ADVBTNS, "ADVBTNS.ICN" }, { ADVEBTNS, "ADVEBTNS.ICN" }, { ADVMCO, "ADVMCO.ICN" }, { AELEM, "AELEM.ICN" }, { APANBKGE, "APANBKGE.ICN" }, { APANBKG, "APANBKG.ICN" }, { APANELE, "APANELE.ICN" }, { APANEL, "APANEL.ICN" }, { ARCHER2, "ARCHER2.ICN" }, { ARCHER, "ARCHER.ICN" }, { ARCH_MSL, "ARCH_MSL.ICN" }, { ART32, "ART32.ICN" }, { ARTFX, "ARTFX.ICN" }, { ARTIFACT, "ARTIFACT.ICN" }, { BARB32, "BARB32.ICN" }, { B_BFLG32, "B-BFLG32.ICN" }, { BERZERK, "BERZERK.ICN" }, { B_FLAG32, "B-FLAG32.ICN" }, { BIGBAR, "BIGBAR.ICN" }, { BLDGXTRA, "BLDGXTRA.ICN" }, { BLESS, "BLESS.ICN" }, { BLIND, "BLIND.ICN" }, { BLUEFIRE, "BLUEFIRE.ICN" }, { BOAR, "BOAR.ICN" }, { BOAT32, "BOAT32.ICN" }, { BOATSHAD, "BOATSHAD.ICN" }, { BOATWIND, "BOATWIND.ICN" }, { BOOK, "BOOK.ICN" }, { BORDEDIT, "BORDEDIT.ICN" }, { BOULDER, "BOULDER.ICN" }, { BRCREST, "BRCREST.ICN" }, { BROTHERS, "BROTHERS.ICN" }, { BTNBAUD, "BTNBAUD.ICN" }, { BTNCMPGN, "BTNCMPGN.ICN" }, { BTNCOM, "BTNCOM.ICN" }, { BTNDCCFG, "BTNDCCFG.ICN" }, { BTNDC, "BTNDC.ICN" }, { BTNEMAIN, "BTNEMAIN.ICN" }, { BTNENEW, "BTNENEW.ICN" }, { BTNESIZE, "BTNESIZE.ICN" }, { BTNHOTST, "BTNHOTST.ICN" }, { BTNMCFG, "BTNMCFG.ICN" }, { BTNMODEM, "BTNMODEM.ICN" }, { BTNMP, "BTNMP.ICN" }, { BTNNET2, "BTNNET2.ICN" }, { BTNNET, "BTNNET.ICN" }, { BTNNEWGM, "BTNNEWGM.ICN" }, { BTNSHNGL, "BTNSHNGL.ICN" }, { BUILDING, "BUILDING.ICN" }, { BUYBUILD, "BUYBUILD.ICN" }, { BUYBUILE, "BUYBUILE.ICN" }, { CAMPBKGE, "CAMPBKGE.ICN" }, { CAMPBKGG, "CAMPBKGG.ICN" }, { CAMPXTRE, "CAMPXTRE.ICN" }, { CAMPXTRG, "CAMPXTRG.ICN" }, { CAPTCOVR, "CAPTCOVR.ICN" }, { CASLBAR, "CASLBAR.ICN" }, { CASLWIND, "CASLWIND.ICN" }, { CASLXTRA, "CASLXTRA.ICN" }, { CASTBKGB, "CASTBKGB.ICN" }, { CASTBKGK, "CASTBKGK.ICN" }, { CASTBKGN, "CASTBKGN.ICN" }, { CASTBKGS, "CASTBKGS.ICN" }, { CASTBKGW, "CASTBKGW.ICN" }, { CASTBKGZ, "CASTBKGZ.ICN" }, { CASTLEB, "CASTLEB.ICN" }, { CASTLEK, "CASTLEK.ICN" }, { CASTLEN, "CASTLEN.ICN" }, { CASTLES, "CASTLES.ICN" }, { CASTLEW, "CASTLEW.ICN" }, { CASTLEZ, "CASTLEZ.ICN" }, { CATAPULT, "CATAPULT.ICN" }, { CAVALRYB, "CAVALRYB.ICN" }, { CAVALRYR, "CAVALRYR.ICN" }, { CBKGBEAC, "CBKGBEAC.ICN" }, { CBKGCRCK, "CBKGCRCK.ICN" }, { CBKGDIMT, "CBKGDIMT.ICN" }, { CBKGDITR, "CBKGDITR.ICN" }, { CBKGDSRT, "CBKGDSRT.ICN" }, { CBKGGRAV, "CBKGGRAV.ICN" }, { CBKGGRMT, "CBKGGRMT.ICN" }, { CBKGGRTR, "CBKGGRTR.ICN" }, { CBKGLAVA, "CBKGLAVA.ICN" }, { CBKGSNMT, "CBKGSNMT.ICN" }, { CBKGSNTR, "CBKGSNTR.ICN" }, { CBKGSWMP, "CBKGSWMP.ICN" }, { CBKGWATR, "CBKGWATR.ICN" }, { CELLWIN, "CELLWIN.ICN" }, { CENTAUR, "CENTAUR.ICN" }, { CFLGSMAL, "CFLGSMAL.ICN" }, { CLOP32, "CLOP32.ICN" }, { CLOUDLUK, "CLOUDLUK.ICN" }, { CMBTCAPB, "CMBTCAPB.ICN" }, { CMBTCAPK, "CMBTCAPK.ICN" }, { CMBTCAPN, "CMBTCAPN.ICN" }, { CMBTCAPS, "CMBTCAPS.ICN" }, { CMBTCAPW, "CMBTCAPW.ICN" }, { CMBTCAPZ, "CMBTCAPZ.ICN" }, { CMBTFLE1, "CMBTFLE1.ICN" }, { CMBTFLE2, "CMBTFLE2.ICN" }, { CMBTFLE3, "CMBTFLE3.ICN" }, { CMBTHROB, "CMBTHROB.ICN" }, { CMBTHROK, "CMBTHROK.ICN" }, { CMBTHRON, "CMBTHRON.ICN" }, { CMBTHROS, "CMBTHROS.ICN" }, { CMBTHROW, "CMBTHROW.ICN" }, { CMBTHROZ, "CMBTHROZ.ICN" }, { CMBTLOS1, "CMBTLOS1.ICN" }, { CMBTLOS2, "CMBTLOS2.ICN" }, { CMBTLOS3, "CMBTLOS3.ICN" }, { CMBTMISC, "CMBTMISC.ICN" }, { CMBTSURR, "CMBTSURR.ICN" }, { CMSECO, "CMSECO.ICN" }, { COBJ0000, "COBJ0000.ICN" }, { COBJ0001, "COBJ0001.ICN" }, { COBJ0002, "COBJ0002.ICN" }, { COBJ0003, "COBJ0003.ICN" }, { COBJ0004, "COBJ0004.ICN" }, { COBJ0005, "COBJ0005.ICN" }, { COBJ0006, "COBJ0006.ICN" }, { COBJ0007, "COBJ0007.ICN" }, { COBJ0008, "COBJ0008.ICN" }, { COBJ0009, "COBJ0009.ICN" }, { COBJ0010, "COBJ0010.ICN" }, { COBJ0011, "COBJ0011.ICN" }, { COBJ0012, "COBJ0012.ICN" }, { COBJ0013, "COBJ0013.ICN" }, { COBJ0014, "COBJ0014.ICN" }, { COBJ0015, "COBJ0015.ICN" }, { COBJ0016, "COBJ0016.ICN" }, { COBJ0017, "COBJ0017.ICN" }, { COBJ0018, "COBJ0018.ICN" }, { COBJ0019, "COBJ0019.ICN" }, { COBJ0020, "COBJ0020.ICN" }, { COBJ0021, "COBJ0021.ICN" }, { COBJ0022, "COBJ0022.ICN" }, { COBJ0023, "COBJ0023.ICN" }, { COBJ0024, "COBJ0024.ICN" }, { COBJ0025, "COBJ0025.ICN" }, { COBJ0026, "COBJ0026.ICN" }, { COBJ0027, "COBJ0027.ICN" }, { COBJ0028, "COBJ0028.ICN" }, { COBJ0029, "COBJ0029.ICN" }, { COBJ0030, "COBJ0030.ICN" }, { COBJ0031, "COBJ0031.ICN" }, { COLDRAY, "COLDRAY.ICN" }, { COLDRING, "COLDRING.ICN" }, { CONGRATS, "CONGRATS.ICN" }, { COVR0001, "COVR0001.ICN" }, { COVR0002, "COVR0002.ICN" }, { COVR0003, "COVR0003.ICN" }, { COVR0004, "COVR0004.ICN" }, { COVR0005, "COVR0005.ICN" }, { COVR0006, "COVR0006.ICN" }, { COVR0007, "COVR0007.ICN" }, { COVR0008, "COVR0008.ICN" }, { COVR0009, "COVR0009.ICN" }, { COVR0010, "COVR0010.ICN" }, { COVR0011, "COVR0011.ICN" }, { COVR0012, "COVR0012.ICN" }, { COVR0013, "COVR0013.ICN" }, { COVR0014, "COVR0014.ICN" }, { COVR0015, "COVR0015.ICN" }, { COVR0016, "COVR0016.ICN" }, { COVR0017, "COVR0017.ICN" }, { COVR0018, "COVR0018.ICN" }, { COVR0019, "COVR0019.ICN" }, { COVR0020, "COVR0020.ICN" }, { COVR0021, "COVR0021.ICN" }, { COVR0022, "COVR0022.ICN" }, { COVR0023, "COVR0023.ICN" }, { COVR0024, "COVR0024.ICN" }, { CPANBKGE, "CPANBKGE.ICN" }, { CPANBKG, "CPANBKG.ICN" }, { CPANELE, "CPANELE.ICN" }, { CPANEL, "CPANEL.ICN" }, { CREST, "CREST.ICN" }, { CSPANBKE, "CSPANBKE.ICN" }, { CSPANBKG, "CSPANBKG.ICN" }, { CSPANBTE, "CSPANBTE.ICN" }, { CSPANBTN, "CSPANBTN.ICN" }, { CSPANEL, "CSPANEL.ICN" }, { CSTLBARB, "CSTLBARB.ICN" }, { CSTLCAPB, "CSTLCAPB.ICN" }, { CSTLCAPK, "CSTLCAPK.ICN" }, { CSTLCAPN, "CSTLCAPN.ICN" }, { CSTLCAPS, "CSTLCAPS.ICN" }, { CSTLCAPW, "CSTLCAPW.ICN" }, { CSTLCAPZ, "CSTLCAPZ.ICN" }, { CSTLKNGT, "CSTLKNGT.ICN" }, { CSTLNECR, "CSTLNECR.ICN" }, { CSTLSORC, "CSTLSORC.ICN" }, { CSTLWRLK, "CSTLWRLK.ICN" }, { CSTLWZRD, "CSTLWZRD.ICN" }, { CTRACK00, "CTRACK00.ICN" }, { CTRACK01, "CTRACK01.ICN" }, { CTRACK02, "CTRACK02.ICN" }, { CTRACK03, "CTRACK03.ICN" }, { CTRACK04, "CTRACK04.ICN" }, { CTRACK05, "CTRACK05.ICN" }, { CTRACK06, "CTRACK06.ICN" }, { CURSE, "CURSE.ICN" }, { CYCLOPS, "CYCLOPS.ICN" }, { DISRRAY, "DISRRAY.ICN" }, { DRAGBLAK, "DRAGBLAK.ICN" }, { DRAGBONE, "DRAGBONE.ICN" }, { DRAGGREE, "DRAGGREE.ICN" }, { DRAGRED, "DRAGRED.ICN" }, { DRAGSLAY, "DRAGSLAY.ICN" }, { DROPLISL, "DROPLISL.ICN" }, { DROPLIST, "DROPLIST.ICN" }, { DRUID2, "DRUID2.ICN" }, { DRUID, "DRUID.ICN" }, { DRUIDMSL, "DRUIDMSL.ICN" }, { DUMMY, "DUMMY.ICN" }, { DWARF2, "DWARF2.ICN" }, { DWARF, "DWARF.ICN" }, { ECPANEL, "ECPANEL.ICN" }, { EDITBTNS, "EDITBTNS.ICN" }, { EDITOR, "EDITOR.ICN" }, { EDITPANL, "EDITPANL.ICN" }, { EELEM, "EELEM.ICN" }, { ELECTRIC, "ELECTRIC.ICN" }, { ELF2, "ELF2.ICN" }, { ELF, "ELF.ICN" }, { ELF__MSL, "ELF__MSL.ICN" }, { ESCROLL, "ESCROLL.ICN" }, { ESPANBKG, "ESPANBKG.ICN" }, { ESPANBTN, "ESPANBTN.ICN" }, { ESPANEL, "ESPANEL.ICN" }, { EVIW_ALL, "EVIW_ALL.ICN" }, { EVIWDDOR, "EVIWDDOR.ICN" }, { EVIWHROS, "EVIWHROS.ICN" }, { EVIWMINE, "EVIWMINE.ICN" }, { EVIWPUZL, "EVIWPUZL.ICN" }, { EVIWRSRC, "EVIWRSRC.ICN" }, { EVIWRTFX, "EVIWRTFX.ICN" }, { EVIWTWNS, "EVIWTWNS.ICN" }, { EVIWWRLD, "EVIWWRLD.ICN" }, { EXPMRL, "EXPMRL.ICN" }, { EXTRAOVR, "EXTRAOVR.ICN" }, { FELEM, "FELEM.ICN" }, { FIREBAL2, "FIREBAL2.ICN" }, { FIREBALL, "FIREBALL.ICN" }, { FLAG32, "FLAG32.ICN" }, { FONT, "FONT.ICN" }, { FRNG0001, "FRNG0001.ICN" }, { FRNG0002, "FRNG0002.ICN" }, { FRNG0003, "FRNG0003.ICN" }, { FRNG0004, "FRNG0004.ICN" }, { FRNG0005, "FRNG0005.ICN" }, { FRNG0006, "FRNG0006.ICN" }, { FRNG0007, "FRNG0007.ICN" }, { FRNG0008, "FRNG0008.ICN" }, { FRNG0009, "FRNG0009.ICN" }, { FRNG0010, "FRNG0010.ICN" }, { FRNG0011, "FRNG0011.ICN" }, { FRNG0012, "FRNG0012.ICN" }, { FRNG0013, "FRNG0013.ICN" }, { FROTH, "FROTH.ICN" }, { GARGOYLE, "GARGOYLE.ICN" }, { G_BFLG32, "G-BFLG32.ICN" }, { GENIE, "GENIE.ICN" }, { G_FLAG32, "G-FLAG32.ICN" }, { GHOST, "GHOST.ICN" }, { GOBLIN, "GOBLIN.ICN" }, { GOLEM2, "GOLEM2.ICN" }, { GOLEM, "GOLEM.ICN" }, { GRIFFIN, "GRIFFIN.ICN" }, { GROUND12, "GROUND12.ICN" }, { GROUND4, "GROUND4.ICN" }, { GROUND6, "GROUND6.ICN" }, { HALFLING, "HALFLING.ICN" }, { HALFLMSL, "HALFLMSL.ICN" }, { HASTE, "HASTE.ICN" }, { HEROBKG, "HEROBKG.ICN" }, { HEROES, "HEROES.ICN" }, { HEROEXTE, "HEROEXTE.ICN" }, { HEROEXTG, "HEROEXTG.ICN" }, { HEROFL00, "HEROFL00.ICN" }, { HEROFL01, "HEROFL01.ICN" }, { HEROFL02, "HEROFL02.ICN" }, { HEROFL03, "HEROFL03.ICN" }, { HEROFL04, "HEROFL04.ICN" }, { HEROFL05, "HEROFL05.ICN" }, { HEROFL06, "HEROFL06.ICN" }, { HEROLOGE, "HEROLOGE.ICN" }, { HEROLOGO, "HEROLOGO.ICN" }, { HISCORE, "HISCORE.ICN" }, { HOURGLAS, "HOURGLAS.ICN" }, { HSBKG, "HSBKG.ICN" }, { HSBTNS, "HSBTNS.ICN" }, { HSICONS, "HSICONS.ICN" }, { HYDRA, "HYDRA.ICN" }, { HYPNOTIZ, "HYPNOTIZ.ICN" }, { ICECLOUD, "ICECLOUD.ICN" }, { KEEP, "KEEP.ICN" }, { KNGT32, "KNGT32.ICN" }, { LETTER12, "LETTER12.ICN" }, { LETTER4, "LETTER4.ICN" }, { LETTER6, "LETTER6.ICN" }, { LGNDXTRA, "LGNDXTRA.ICN" }, { LGNDXTRE, "LGNDXTRE.ICN" }, { LICH2, "LICH2.ICN" }, { LICHCLOD, "LICHCLOD.ICN" }, { LICH, "LICH.ICN" }, { LICH_MSL, "LICH_MSL.ICN" }, { LISTBOX, "LISTBOX.ICN" }, { LISTBOXS, "LISTBOXS.ICN" }, { LOCATORE, "LOCATORE.ICN" }, { LOCATORS, "LOCATORS.ICN" }, { MAGE1, "MAGE1.ICN" }, { MAGE2, "MAGE2.ICN" }, { MAGEGLDB, "MAGEGLDB.ICN" }, { MAGEGLDK, "MAGEGLDK.ICN" }, { MAGEGLDN, "MAGEGLDN.ICN" }, { MAGEGLDS, "MAGEGLDS.ICN" }, { MAGEGLDW, "MAGEGLDW.ICN" }, { MAGEGLDZ, "MAGEGLDZ.ICN" }, { MAGIC01, "MAGIC01.ICN" }, { MAGIC02, "MAGIC02.ICN" }, { MAGIC03, "MAGIC03.ICN" }, { MAGIC04, "MAGIC04.ICN" }, { MAGIC06, "MAGIC06.ICN" }, { MAGIC07, "MAGIC07.ICN" }, { MAGIC08, "MAGIC08.ICN" }, { MANA, "MANA.ICN" }, { MEDUSA, "MEDUSA.ICN" }, { METEOR, "METEOR.ICN" }, { MINICAPT, "MINICAPT.ICN" }, { MINIHERO, "MINIHERO.ICN" }, { MINILKMR, "MINILKMR.ICN" }, { MINIMON, "MINIMON.ICN" }, { MINIPORT, "MINIPORT.ICN" }, { MINISS, "MINISS.ICN" }, { MINITOWN, "MINITOWN.ICN" }, { MINOTAU2, "MINOTAU2.ICN" }, { MINOTAUR, "MINOTAUR.ICN" }, { MISC12, "MISC12.ICN" }, { MISC4, "MISC4.ICN" }, { MISC6, "MISC6.ICN" }, { MOATPART, "MOATPART.ICN" }, { MOATWHOL, "MOATWHOL.ICN" }, { MOBILITY, "MOBILITY.ICN" }, { MONH0000, "MONH0000.ICN" }, { MONH0001, "MONH0001.ICN" }, { MONH0002, "MONH0002.ICN" }, { MONH0003, "MONH0003.ICN" }, { MONH0004, "MONH0004.ICN" }, { MONH0005, "MONH0005.ICN" }, { MONH0006, "MONH0006.ICN" }, { MONH0007, "MONH0007.ICN" }, { MONH0008, "MONH0008.ICN" }, { MONH0009, "MONH0009.ICN" }, { MONH0010, "MONH0010.ICN" }, { MONH0011, "MONH0011.ICN" }, { MONH0012, "MONH0012.ICN" }, { MONH0013, "MONH0013.ICN" }, { MONH0014, "MONH0014.ICN" }, { MONH0015, "MONH0015.ICN" }, { MONH0016, "MONH0016.ICN" }, { MONH0017, "MONH0017.ICN" }, { MONH0018, "MONH0018.ICN" }, { MONH0019, "MONH0019.ICN" }, { MONH0020, "MONH0020.ICN" }, { MONH0021, "MONH0021.ICN" }, { MONH0022, "MONH0022.ICN" }, { MONH0023, "MONH0023.ICN" }, { MONH0024, "MONH0024.ICN" }, { MONH0025, "MONH0025.ICN" }, { MONH0026, "MONH0026.ICN" }, { MONH0027, "MONH0027.ICN" }, { MONH0028, "MONH0028.ICN" }, { MONH0029, "MONH0029.ICN" }, { MONH0030, "MONH0030.ICN" }, { MONH0031, "MONH0031.ICN" }, { MONH0032, "MONH0032.ICN" }, { MONH0033, "MONH0033.ICN" }, { MONH0034, "MONH0034.ICN" }, { MONH0035, "MONH0035.ICN" }, { MONH0036, "MONH0036.ICN" }, { MONH0037, "MONH0037.ICN" }, { MONH0038, "MONH0038.ICN" }, { MONH0039, "MONH0039.ICN" }, { MONH0040, "MONH0040.ICN" }, { MONH0041, "MONH0041.ICN" }, { MONH0042, "MONH0042.ICN" }, { MONH0043, "MONH0043.ICN" }, { MONH0044, "MONH0044.ICN" }, { MONH0045, "MONH0045.ICN" }, { MONH0046, "MONH0046.ICN" }, { MONH0047, "MONH0047.ICN" }, { MONH0048, "MONH0048.ICN" }, { MONH0049, "MONH0049.ICN" }, { MONH0050, "MONH0050.ICN" }, { MONH0051, "MONH0051.ICN" }, { MONH0052, "MONH0052.ICN" }, { MONH0053, "MONH0053.ICN" }, { MONH0054, "MONH0054.ICN" }, { MONH0055, "MONH0055.ICN" }, { MONH0056, "MONH0056.ICN" }, { MONH0057, "MONH0057.ICN" }, { MONH0058, "MONH0058.ICN" }, { MONH0059, "MONH0059.ICN" }, { MONH0060, "MONH0060.ICN" }, { MONH0061, "MONH0061.ICN" }, { MONH0062, "MONH0062.ICN" }, { MONH0063, "MONH0063.ICN" }, { MONH0064, "MONH0064.ICN" }, { MONH0065, "MONH0065.ICN" }, { MONS32, "MONS32.ICN" }, { MORALEB, "MORALEB.ICN" }, { MORALEG, "MORALEG.ICN" }, { MTNCRCK, "MTNCRCK.ICN" }, { MTNDIRT, "MTNDIRT.ICN" }, { MTNDSRT, "MTNDSRT.ICN" }, { MTNGRAS, "MTNGRAS.ICN" }, { MTNLAVA, "MTNLAVA.ICN" }, { MTNMULT, "MTNMULT.ICN" }, { MTNSNOW, "MTNSNOW.ICN" }, { MTNSWMP, "MTNSWMP.ICN" }, { MUMMY2, "MUMMY2.ICN" }, { MUMMYW, "MUMMYW.ICN" }, { NECR32, "NECR32.ICN" }, { NETBOX, "NETBOX.ICN" }, { NGEXTRA, "NGEXTRA.ICN" }, { NGHSBKG, "NGHSBKG.ICN" }, { NGMPBKG, "NGMPBKG.ICN" }, { NGSPBKG, "NGSPBKG.ICN" }, { NOMAD, "NOMAD.ICN" }, { O_BFLG32, "O-BFLG32.ICN" }, { OBJNARTI, "OBJNARTI.ICN" }, { OBJNCRCK, "OBJNCRCK.ICN" }, { OBJNDIRT, "OBJNDIRT.ICN" }, { OBJNDSRT, "OBJNDSRT.ICN" }, { OBJNGRA2, "OBJNGRA2.ICN" }, { OBJNGRAS, "OBJNGRAS.ICN" }, { OBJNHAUN, "OBJNHAUN.ICN" }, { OBJNLAV2, "OBJNLAV2.ICN" }, { OBJNLAV3, "OBJNLAV3.ICN" }, { OBJNLAVA, "OBJNLAVA.ICN" }, { OBJNMUL2, "OBJNMUL2.ICN" }, { OBJNMULT, "OBJNMULT.ICN" }, { OBJNRSRC, "OBJNRSRC.ICN" }, { OBJNSNOW, "OBJNSNOW.ICN" }, { OBJNSWMP, "OBJNSWMP.ICN" }, { OBJNTOWN, "OBJNTOWN.ICN" }, { OBJNTWBA, "OBJNTWBA.ICN" }, { OBJNTWRD, "OBJNTWRD.ICN" }, { OBJNTWSH, "OBJNTWSH.ICN" }, { OBJNWAT2, "OBJNWAT2.ICN" }, { OBJNWATR, "OBJNWATR.ICN" }, { OBJNXTRA, "OBJNXTRA.ICN" }, { OBJPALET, "OBJPALET.ICN" }, { O_FLAG32, "O-FLAG32.ICN" }, { OGRE2, "OGRE2.ICN" }, { OGRE, "OGRE.ICN" }, { ORC2, "ORC2.ICN" }, { ORC, "ORC.ICN" }, { ORC__MSL, "ORC__MSL.ICN" }, { OVERBACK, "OVERBACK.ICN" }, { OVERLAY, "OVERLAY.ICN" }, { OVERVIEW, "OVERVIEW.ICN" }, { PALADIN2, "PALADIN2.ICN" }, { PALADIN, "PALADIN.ICN" }, { PARALYZE, "PARALYZE.ICN" }, { P_BFLG32, "P-BFLG32.ICN" }, { PEASANT, "PEASANT.ICN" }, { P_FLAG32, "P-FLAG32.ICN" }, { PHOENIX, "PHOENIX.ICN" }, { PHYSICAL, "PHYSICAL.ICN" }, { PIKEMAN2, "PIKEMAN2.ICN" }, { PIKEMAN, "PIKEMAN.ICN" }, { PORT0000, "PORT0000.ICN" }, { PORT0001, "PORT0001.ICN" }, { PORT0002, "PORT0002.ICN" }, { PORT0003, "PORT0003.ICN" }, { PORT0004, "PORT0004.ICN" }, { PORT0005, "PORT0005.ICN" }, { PORT0006, "PORT0006.ICN" }, { PORT0007, "PORT0007.ICN" }, { PORT0008, "PORT0008.ICN" }, { PORT0009, "PORT0009.ICN" }, { PORT0010, "PORT0010.ICN" }, { PORT0011, "PORT0011.ICN" }, { PORT0012, "PORT0012.ICN" }, { PORT0013, "PORT0013.ICN" }, { PORT0014, "PORT0014.ICN" }, { PORT0015, "PORT0015.ICN" }, { PORT0016, "PORT0016.ICN" }, { PORT0017, "PORT0017.ICN" }, { PORT0018, "PORT0018.ICN" }, { PORT0019, "PORT0019.ICN" }, { PORT0020, "PORT0020.ICN" }, { PORT0021, "PORT0021.ICN" }, { PORT0022, "PORT0022.ICN" }, { PORT0023, "PORT0023.ICN" }, { PORT0024, "PORT0024.ICN" }, { PORT0025, "PORT0025.ICN" }, { PORT0026, "PORT0026.ICN" }, { PORT0027, "PORT0027.ICN" }, { PORT0028, "PORT0028.ICN" }, { PORT0029, "PORT0029.ICN" }, { PORT0030, "PORT0030.ICN" }, { PORT0031, "PORT0031.ICN" }, { PORT0032, "PORT0032.ICN" }, { PORT0033, "PORT0033.ICN" }, { PORT0034, "PORT0034.ICN" }, { PORT0035, "PORT0035.ICN" }, { PORT0036, "PORT0036.ICN" }, { PORT0037, "PORT0037.ICN" }, { PORT0038, "PORT0038.ICN" }, { PORT0039, "PORT0039.ICN" }, { PORT0040, "PORT0040.ICN" }, { PORT0041, "PORT0041.ICN" }, { PORT0042, "PORT0042.ICN" }, { PORT0043, "PORT0043.ICN" }, { PORT0044, "PORT0044.ICN" }, { PORT0045, "PORT0045.ICN" }, { PORT0046, "PORT0046.ICN" }, { PORT0047, "PORT0047.ICN" }, { PORT0048, "PORT0048.ICN" }, { PORT0049, "PORT0049.ICN" }, { PORT0050, "PORT0050.ICN" }, { PORT0051, "PORT0051.ICN" }, { PORT0052, "PORT0052.ICN" }, { PORT0053, "PORT0053.ICN" }, { PORT0054, "PORT0054.ICN" }, { PORT0055, "PORT0055.ICN" }, { PORT0056, "PORT0056.ICN" }, { PORT0057, "PORT0057.ICN" }, { PORT0058, "PORT0058.ICN" }, { PORT0059, "PORT0059.ICN" }, { PORT0060, "PORT0060.ICN" }, { PORT0061, "PORT0061.ICN" }, { PORT0062, "PORT0062.ICN" }, { PORT0063, "PORT0063.ICN" }, { PORT0064, "PORT0064.ICN" }, { PORT0065, "PORT0065.ICN" }, { PORT0066, "PORT0066.ICN" }, { PORT0067, "PORT0067.ICN" }, { PORT0068, "PORT0068.ICN" }, { PORT0069, "PORT0069.ICN" }, { PORT0070, "PORT0070.ICN" }, { PORT0090, "PORT0090.ICN" }, { PORT0091, "PORT0091.ICN" }, { PORT0092, "PORT0092.ICN" }, { PORT0093, "PORT0093.ICN" }, { PORT0094, "PORT0094.ICN" }, { PORT0095, "PORT0095.ICN" }, { PORTCFLG, "PORTCFLG.ICN" }, { PORTMEDI, "PORTMEDI.ICN" }, { PORTXTRA, "PORTXTRA.ICN" }, { PRIMSKIL, "PRIMSKIL.ICN" }, { PUZZLE, "PUZZLE.ICN" }, { QWIKHERO, "QWIKHERO.ICN" }, { QWIKINFO, "QWIKINFO.ICN" }, { QWIKTOWN, "QWIKTOWN.ICN" }, { RADAR, "RADAR.ICN" }, { R_BFLG32, "R-BFLG32.ICN" }, { RECR2BKG, "RECR2BKG.ICN" }, { RECRBKG, "RECRBKG.ICN" }, { RECRUIT, "RECRUIT.ICN" }, { REDBACK, "REDBACK.ICN" }, { REDDEATH, "REDDEATH.ICN" }, { REDFIRE, "REDFIRE.ICN" }, { REQBKG, "REQBKG.ICN" }, { REQSBKG, "REQSBKG.ICN" }, { REQUEST, "REQUEST.ICN" }, { REQUESTS, "REQUESTS.ICN" }, { RESOURCE, "RESOURCE.ICN" }, { RESSMALL, "RESSMALL.ICN" }, { R_FLAG32, "R-FLAG32.ICN" }, { ROAD, "ROAD.ICN" }, { ROC, "ROC.ICN" }, { ROGUE, "ROGUE.ICN" }, { ROUTE, "ROUTE.ICN" }, { SCENIBKG, "SCENIBKG.ICN" }, { SCROLL2, "SCROLL2.ICN" }, { SCROLLCN, "SCROLLCN.ICN" }, { SCROLLE, "SCROLLE.ICN" }, { SCROLL, "SCROLL.ICN" }, { SECSKILL, "SECSKILL.ICN" }, { SHADOW32, "SHADOW32.ICN" }, { SHIELD, "SHIELD.ICN" }, { SHNGANIM, "SHNGANIM.ICN" }, { SKELETON, "SKELETON.ICN" }, { SMALCLOD, "SMALCLOD.ICN" }, { SMALFONT, "SMALFONT.ICN" }, { SMALLBAR, "SMALLBAR.ICN" }, { SORC32, "SORC32.ICN" }, { SPANBKGE, "SPANBKGE.ICN" }, { SPANBKG, "SPANBKG.ICN" }, { SPANBTNE, "SPANBTNE.ICN" }, { SPANBTN, "SPANBTN.ICN" }, { SPANEL, "SPANEL.ICN" }, { SPARKS, "SPARKS.ICN" }, { SPELCO, "SPELCO.ICN" }, { SPELLINF, "SPELLINF.ICN" }, { SPELLINL, "SPELLINL.ICN" }, { SPELLS, "SPELLS.ICN" }, { SPRITE, "SPRITE.ICN" }, { STELSKIN, "STELSKIN.ICN" }, { STONBACK, "STONBACK.ICN" }, { STONBAKE, "STONBAKE.ICN" }, { STONEBAK, "STONEBAK.ICN" }, { STONEBK2, "STONEBK2.ICN" }, { STONSKIN, "STONSKIN.ICN" }, { STORM, "STORM.ICN" }, { STREAM, "STREAM.ICN" }, { STRIP, "STRIP.ICN" }, { SUNMOONE, "SUNMOONE.ICN" }, { SUNMOON, "SUNMOON.ICN" }, { SURDRBKE, "SURDRBKE.ICN" }, { SURDRBKG, "SURDRBKG.ICN" }, { SURRENDE, "SURRENDE.ICN" }, { SURRENDR, "SURRENDR.ICN" }, { SWAPBTN, "SWAPBTN.ICN" }, { SWAPWIN, "SWAPWIN.ICN" }, { SWORDSM2, "SWORDSM2.ICN" }, { SWORDSMN, "SWORDSMN.ICN" }, { SYSTEME, "SYSTEME.ICN" }, { SYSTEM, "SYSTEM.ICN" }, { TAVWIN, "TAVWIN.ICN" }, { TENT, "TENT.ICN" }, { TERRAINS, "TERRAINS.ICN" }, { TEXTBACK, "TEXTBACK.ICN" }, { TEXTBAK2, "TEXTBAK2.ICN" }, { TEXTBAR, "TEXTBAR.ICN" }, { TITANBLA, "TITANBLA.ICN" }, { TITANBLU, "TITANBLU.ICN" }, { TITANMSL, "TITANMSL.ICN" }, { TOWNBKG0, "TOWNBKG0.ICN" }, { TOWNBKG1, "TOWNBKG1.ICN" }, { TOWNBKG2, "TOWNBKG2.ICN" }, { TOWNBKG3, "TOWNBKG3.ICN" }, { TOWNBKG4, "TOWNBKG4.ICN" }, { TOWNBKG5, "TOWNBKG5.ICN" }, { TOWNFIX, "TOWNFIX.ICN" }, { TOWNNAME, "TOWNNAME.ICN" }, { TOWNWIND, "TOWNWIND.ICN" }, { TRADPOSE, "TRADPOSE.ICN" }, { TRADPOST, "TRADPOST.ICN" }, { TREASURY, "TREASURY.ICN" }, { TREDECI, "TREDECI.ICN" }, { TREEVIL, "TREEVIL.ICN" }, { TREFALL, "TREFALL.ICN" }, { TREFIR, "TREFIR.ICN" }, { TREJNGL, "TREJNGL.ICN" }, { TRESNOW, "TRESNOW.ICN" }, { TROLL2, "TROLL2.ICN" }, { TROLL, "TROLL.ICN" }, { TROLLMSL, "TROLLMSL.ICN" }, { TWNBBOAT, "TWNBBOAT.ICN" }, { TWNBCAPT, "TWNBCAPT.ICN" }, { TWNBCSTL, "TWNBCSTL.ICN" }, { TWNBDOCK, "TWNBDOCK.ICN" }, { TWNBDW_0, "TWNBDW_0.ICN" }, { TWNBDW_1, "TWNBDW_1.ICN" }, { TWNBDW_2, "TWNBDW_2.ICN" }, { TWNBDW_3, "TWNBDW_3.ICN" }, { TWNBDW_4, "TWNBDW_4.ICN" }, { TWNBDW_5, "TWNBDW_5.ICN" }, { TWNBEXT0, "TWNBEXT0.ICN" }, { TWNBEXT1, "TWNBEXT1.ICN" }, { TWNBEXT2, "TWNBEXT2.ICN" }, { TWNBEXT3, "TWNBEXT3.ICN" }, { TWNBLTUR, "TWNBLTUR.ICN" }, { TWNBMAGE, "TWNBMAGE.ICN" }, { TWNBMARK, "TWNBMARK.ICN" }, { TWNBMOAT, "TWNBMOAT.ICN" }, { TWNBRTUR, "TWNBRTUR.ICN" }, { TWNBSPEC, "TWNBSPEC.ICN" }, { TWNBSTAT, "TWNBSTAT.ICN" }, { TWNBTENT, "TWNBTENT.ICN" }, { TWNBTHIE, "TWNBTHIE.ICN" }, { TWNBTVRN, "TWNBTVRN.ICN" }, { TWNBUP_1, "TWNBUP_1.ICN" }, { TWNBUP_3, "TWNBUP_3.ICN" }, { TWNBUP_4, "TWNBUP_4.ICN" }, { TWNBWEL2, "TWNBWEL2.ICN" }, { TWNBWELL, "TWNBWELL.ICN" }, { TWNKBOAT, "TWNKBOAT.ICN" }, { TWNKCAPT, "TWNKCAPT.ICN" }, { TWNKCSTL, "TWNKCSTL.ICN" }, { TWNKDOCK, "TWNKDOCK.ICN" }, { TWNKDW_0, "TWNKDW_0.ICN" }, { TWNKDW_1, "TWNKDW_1.ICN" }, { TWNKDW_2, "TWNKDW_2.ICN" }, { TWNKDW_3, "TWNKDW_3.ICN" }, { TWNKDW_4, "TWNKDW_4.ICN" }, { TWNKDW_5, "TWNKDW_5.ICN" }, { TWNKEXT0, "TWNKEXT0.ICN" }, { TWNKEXT1, "TWNKEXT1.ICN" }, { TWNKEXT2, "TWNKEXT2.ICN" }, { TWNKLTUR, "TWNKLTUR.ICN" }, { TWNKMAGE, "TWNKMAGE.ICN" }, { TWNKMARK, "TWNKMARK.ICN" }, { TWNKMOAT, "TWNKMOAT.ICN" }, { TWNKRTUR, "TWNKRTUR.ICN" }, { TWNKSPEC, "TWNKSPEC.ICN" }, { TWNKSTAT, "TWNKSTAT.ICN" }, { TWNKTENT, "TWNKTENT.ICN" }, { TWNKTHIE, "TWNKTHIE.ICN" }, { TWNKTVRN, "TWNKTVRN.ICN" }, { TWNKUP_1, "TWNKUP_1.ICN" }, { TWNKUP_2, "TWNKUP_2.ICN" }, { TWNKUP_3, "TWNKUP_3.ICN" }, { TWNKUP_4, "TWNKUP_4.ICN" }, { TWNKUP_5, "TWNKUP_5.ICN" }, { TWNKWEL2, "TWNKWEL2.ICN" }, { TWNKWELL, "TWNKWELL.ICN" }, { TWNNBOAT, "TWNNBOAT.ICN" }, { TWNNCAPT, "TWNNCAPT.ICN" }, { TWNNCSTL, "TWNNCSTL.ICN" }, { TWNNDOCK, "TWNNDOCK.ICN" }, { TWNNDW_0, "TWNNDW_0.ICN" }, { TWNNDW_1, "TWNNDW_1.ICN" }, { TWNNDW_2, "TWNNDW_2.ICN" }, { TWNNDW_3, "TWNNDW_3.ICN" }, { TWNNDW_4, "TWNNDW_4.ICN" }, { TWNNDW_5, "TWNNDW_5.ICN" }, { TWNNEXT0, "TWNNEXT0.ICN" }, { TWNNLTUR, "TWNNLTUR.ICN" }, { TWNNMAGE, "TWNNMAGE.ICN" }, { TWNNMARK, "TWNNMARK.ICN" }, { TWNNMOAT, "TWNNMOAT.ICN" }, { TWNNRTUR, "TWNNRTUR.ICN" }, { TWNNSPEC, "TWNNSPEC.ICN" }, { TWNNSTAT, "TWNNSTAT.ICN" }, { TWNNTENT, "TWNNTENT.ICN" }, { TWNNTHIE, "TWNNTHIE.ICN" }, { TWNNTVRN, "TWNNTVRN.ICN" }, { TWNNUP_1, "TWNNUP_1.ICN" }, { TWNNUP_2, "TWNNUP_2.ICN" }, { TWNNUP_3, "TWNNUP_3.ICN" }, { TWNNUP_4, "TWNNUP_4.ICN" }, { TWNNWEL2, "TWNNWEL2.ICN" }, { TWNNWELL, "TWNNWELL.ICN" }, { TWNSBOAT, "TWNSBOAT.ICN" }, { TWNSCAPT, "TWNSCAPT.ICN" }, { TWNSCSTL, "TWNSCSTL.ICN" }, { TWNSDOCK, "TWNSDOCK.ICN" }, { TWNSDW_0, "TWNSDW_0.ICN" }, { TWNSDW_1, "TWNSDW_1.ICN" }, { TWNSDW_2, "TWNSDW_2.ICN" }, { TWNSDW_3, "TWNSDW_3.ICN" }, { TWNSDW_4, "TWNSDW_4.ICN" }, { TWNSDW_5, "TWNSDW_5.ICN" }, { TWNSEXT0, "TWNSEXT0.ICN" }, { TWNSEXT1, "TWNSEXT1.ICN" }, { TWNSLTUR, "TWNSLTUR.ICN" }, { TWNSMAGE, "TWNSMAGE.ICN" }, { TWNSMARK, "TWNSMARK.ICN" }, { TWNSMOAT, "TWNSMOAT.ICN" }, { TWNSRTUR, "TWNSRTUR.ICN" }, { TWNSSPEC, "TWNSSPEC.ICN" }, { TWNSSTAT, "TWNSSTAT.ICN" }, { TWNSTENT, "TWNSTENT.ICN" }, { TWNSTHIE, "TWNSTHIE.ICN" }, { TWNSTVRN, "TWNSTVRN.ICN" }, { TWNSUP_1, "TWNSUP_1.ICN" }, { TWNSUP_2, "TWNSUP_2.ICN" }, { TWNSUP_3, "TWNSUP_3.ICN" }, { TWNSWEL2, "TWNSWEL2.ICN" }, { TWNSWELL, "TWNSWELL.ICN" }, { TWNWBOAT, "TWNWBOAT.ICN" }, { TWNWCAPT, "TWNWCAPT.ICN" }, { TWNWCSTL, "TWNWCSTL.ICN" }, { TWNWDOCK, "TWNWDOCK.ICN" }, { TWNWDW_0, "TWNWDW_0.ICN" }, { TWNWDW_1, "TWNWDW_1.ICN" }, { TWNWDW_2, "TWNWDW_2.ICN" }, { TWNWDW_3, "TWNWDW_3.ICN" }, { TWNWDW_4, "TWNWDW_4.ICN" }, { TWNWDW_5, "TWNWDW_5.ICN" }, { TWNWEXT0, "TWNWEXT0.ICN" }, { TWNWLTUR, "TWNWLTUR.ICN" }, { TWNWMAGE, "TWNWMAGE.ICN" }, { TWNWMARK, "TWNWMARK.ICN" }, { TWNWMOAT, "TWNWMOAT.ICN" }, { TWNWRTUR, "TWNWRTUR.ICN" }, { TWNWSPEC, "TWNWSPEC.ICN" }, { TWNWSTAT, "TWNWSTAT.ICN" }, { TWNWTENT, "TWNWTENT.ICN" }, { TWNWTHIE, "TWNWTHIE.ICN" }, { TWNWTVRN, "TWNWTVRN.ICN" }, { TWNWUP_3, "TWNWUP_3.ICN" }, { TWNWUP5B, "TWNWUP5B.ICN" }, { TWNWUP_5, "TWNWUP_5.ICN" }, { TWNWWEL2, "TWNWWEL2.ICN" }, { TWNWWELL, "TWNWWELL.ICN" }, { TWNZBOAT, "TWNZBOAT.ICN" }, { TWNZCAPT, "TWNZCAPT.ICN" }, { TWNZCSTL, "TWNZCSTL.ICN" }, { TWNZDOCK, "TWNZDOCK.ICN" }, { TWNZDW_0, "TWNZDW_0.ICN" }, { TWNZDW_1, "TWNZDW_1.ICN" }, { TWNZDW_2, "TWNZDW_2.ICN" }, { TWNZDW_3, "TWNZDW_3.ICN" }, { TWNZDW_4, "TWNZDW_4.ICN" }, { TWNZDW_5, "TWNZDW_5.ICN" }, { TWNZEXT0, "TWNZEXT0.ICN" }, { TWNZLTUR, "TWNZLTUR.ICN" }, { TWNZMAGE, "TWNZMAGE.ICN" }, { TWNZMARK, "TWNZMARK.ICN" }, { TWNZMOAT, "TWNZMOAT.ICN" }, { TWNZRTUR, "TWNZRTUR.ICN" }, { TWNZSPEC, "TWNZSPEC.ICN" }, { TWNZSTAT, "TWNZSTAT.ICN" }, { TWNZTENT, "TWNZTENT.ICN" }, { TWNZTHIE, "TWNZTHIE.ICN" }, { TWNZTVRN, "TWNZTVRN.ICN" }, { TWNZUP_2, "TWNZUP_2.ICN" }, { TWNZUP_4, "TWNZUP_4.ICN" }, { TWNZUP_5, "TWNZUP_5.ICN" }, { TWNZWEL2, "TWNZWEL2.ICN" }, { TWNZWELL, "TWNZWELL.ICN" }, { UNICORN, "UNICORN.ICN" }, { VAMPIRE2, "VAMPIRE2.ICN" }, { VAMPIRE, "VAMPIRE.ICN" }, { VGENBKGE, "VGENBKGE.ICN" }, { VGENBKG, "VGENBKG.ICN" }, { VIEW_ALL, "VIEW_ALL.ICN" }, { VIEWARME, "VIEWARME.ICN" }, { VIEWARMY, "VIEWARMY.ICN" }, { VIEWARSM, "VIEWARSM.ICN" }, { VIEWDDOR, "VIEWDDOR.ICN" }, { VIEWGEN, "VIEWGEN.ICN" }, { VIEWHROS, "VIEWHROS.ICN" }, { VIEWMINE, "VIEWMINE.ICN" }, { VIEWPUZL, "VIEWPUZL.ICN" }, { VIEWRSRC, "VIEWRSRC.ICN" }, { VIEWRTFX, "VIEWRTFX.ICN" }, { VIEWTWNS, "VIEWTWNS.ICN" }, { VIEWWRLD, "VIEWWRLD.ICN" }, { VWFLAG12, "VWFLAG12.ICN" }, { VWFLAG4, "VWFLAG4.ICN" }, { VWFLAG6, "VWFLAG6.ICN" }, { WELEM, "WELEM.ICN" }, { WELLBKG, "WELLBKG.ICN" }, { WELLXTRA, "WELLXTRA.ICN" }, { WINCMBBE, "WINCMBBE.ICN" }, { WINCMBTB, "WINCMBTB.ICN" }, { WINCMBT, "WINCMBT.ICN" }, { WINLOSEB, "WINLOSEB.ICN" }, { WINLOSEE, "WINLOSEE.ICN" }, { WINLOSE, "WINLOSE.ICN" }, { WOLF, "WOLF.ICN" }, { WRLK32, "WRLK32.ICN" }, { WZRD32, "WZRD32.ICN" }, { X_IVY, "X_IVY.ICN" }, { X_LOADCM, "X_LOADCM.ICN" }, { X_CMPBKG, "X_CMPBKG.ICN" }, { X_CMPBTN, "X_CMPBTN.ICN" }, { X_CMPEXT, "X_CMPEXT.ICN" }, { X_TRACK1, "X_TRACK1.ICN" }, { X_TRACK2, "X_TRACK2.ICN" }, { X_TRACK3, "X_TRACK3.ICN" }, { X_TRACK4, "X_TRACK4.ICN" }, { X_LOC1, "X_LOC1.ICN" }, { X_LOC2, "X_LOC2.ICN" }, { X_LOC3, "X_LOC3.ICN" }, { XPRIMARY, "XPRIMARY.ICN" }, { Y_BFLG32, "Y-BFLG32.ICN" }, { Y_FLAG32, "Y-FLAG32.ICN" }, { YINYANG, "YINYANG.ICN" }, { ZOMBIE2, "ZOMBIE2.ICN" }, { ZOMBIE, "ZOMBIE.ICN" } } }; } const char * ICN::getIcnFileName( const int icnId ) { return UNKNOWN <= icnId && icnId < LAST_VALID_FILE_ICN ? icnMap[icnId].string : "CUSTOM"; } uint32_t ICN::getAnimatedIcnIndex( const int icnId, const uint32_t startIndex, const uint32_t currentFrameNumber, const bool quantity /* = false */ ) { switch ( icnId ) { case TWNBBOAT: case TWNKBOAT: case TWNNBOAT: case TWNSBOAT: case TWNWBOAT: case TWNZBOAT: return 1 + currentFrameNumber % 9; case CMBTCAPB: case CMBTCAPK: case CMBTCAPN: case CMBTCAPS: case CMBTCAPW: case CMBTCAPZ: return 1 + currentFrameNumber % 10; case CMBTHROB: return 1 + currentFrameNumber % 18; case CMBTHROK: case CMBTHRON: return 1 + currentFrameNumber % 19; case CMBTHROS: case CMBTHROW: return 1 + currentFrameNumber % 16; case CMBTHROZ: return 1 + currentFrameNumber % 18; case HEROFL00: case HEROFL01: case HEROFL02: case HEROFL03: case HEROFL04: case HEROFL05: case HEROFL06: return currentFrameNumber % 5; case TWNBDOCK: case TWNKDOCK: case TWNNDOCK: case TWNSDOCK: case TWNWDOCK: case TWNZDOCK: case TWNBEXT0: case TWNKEXT0: case TWNNEXT0: case TWNSEXT0: case TWNWEXT0: case TWNZEXT0: case TWNBCAPT: case TWNBDW_3: case TWNBDW_4: case TWNBDW_5: case TWNBEXT1: case TWNBMOAT: case TWNBUP_3: case TWNBUP_4: case TWNKCSTL: case TWNKDW_0: case TWNKLTUR: case TWNKRTUR: case TWNKTHIE: case TWNKTVRN: case TWNNCSTL: case TWNNDW_2: case TWNNUP_2: case TWNSCAPT: case TWNSCSTL: case TWNSDW_0: case TWNSDW_1: case TWNSEXT1: case TWNSTHIE: case TWNSTVRN: case TWNSUP_1: case TWNSWEL2: case TWNWCAPT: case TWNWCSTL: case TWNWMOAT: case TWNZCSTL: case TWNZDW_0: case TWNZDW_2: case TWNZTHIE: case TWNZUP_2: return 1 + currentFrameNumber % 5; case TWNBCSTL: case TWNKDW_2: case TWNKUP_2: case TWNNDW_5: case TWNNWEL2: case TWNWDW_0: case TWNWWEL2: case TWNZTVRN: return 1 + currentFrameNumber % 6; case TWNKDW_4: case TWNKUP_4: return 1 + currentFrameNumber % 7; case TAVWIN: return 2 + currentFrameNumber % 20; case CMBTLOS1: return 1 + currentFrameNumber % 30; case CMBTLOS2: return 1 + currentFrameNumber % 29; case CMBTLOS3: return 1 + currentFrameNumber % 22; case CMBTFLE1: return 1 + currentFrameNumber % 43; case CMBTFLE2: return 1 + currentFrameNumber % 26; case CMBTFLE3: return 1 + currentFrameNumber % 25; case CMBTSURR: case WINCMBT: return 1 + currentFrameNumber % 20; case MINIMON: return startIndex + 1 + currentFrameNumber % 6; case TWNNMAGE: return startIndex + 1 + currentFrameNumber % 5; case TWNBMAGE: return 4 == startIndex ? startIndex + 1 + currentFrameNumber % 8 : 0; case SHNGANIM: return 1 + currentFrameNumber % 39; case BTNSHNGL: return startIndex + currentFrameNumber % 4; case OBJNHAUN: return currentFrameNumber % 15; case OBJNWATR: switch ( startIndex ) { // bottle case 0x00: // 'startIndex' is equal to 0 here so it is not used in the expression. return ( currentFrameNumber % 11 ) + 1; // shadow case 0x0C: // chest case 0x13: // shadow case 0x26: // flotsam case 0x2D: // Magellan's Maps building shadow. case 0x37: // Magellan's Maps building boat. case 0x3E: // Magellan's Maps building waves. case 0x45: // seaweed case 0x4C: case 0x53: case 0x5A: case 0x61: case 0x68: // sailor-man case 0x6F: // shadow case 0xBC: // buoy case 0xC3: // broken ship (right) case 0xE2: case 0xE9: case 0xF1: case 0xF8: return startIndex + ( currentFrameNumber % 6 ) + 1; // seagull on stones case 0x76: case 0x86: case 0x96: case 0xA6: return startIndex + ( currentFrameNumber % 15 ) + 1; // whirlpool case 0xCA: case 0xCE: case 0xD2: case 0xD6: case 0xDA: case 0xDE: return startIndex + ( currentFrameNumber % 3 ) + 1; default: return 0; } case OBJNWAT2: switch ( startIndex ) { // sail broken ship (left) case 0x03: case 0x0C: return startIndex + ( currentFrameNumber % 6 ) + 1; default: return 0; } case OBJNCRCK: switch ( startIndex ) { // pool of oil case 0x50: case 0x5B: case 0x66: case 0x71: case 0x7C: case 0x89: case 0x94: case 0x9F: case 0xAA: // smoke from chimney case 0xBE: // shadow smoke case 0xCA: return startIndex + ( currentFrameNumber % 10 ) + 1; default: return 0; } case OBJNDIRT: switch ( startIndex ) { // mill case 0x99: case 0x9D: case 0xA1: case 0xA5: case 0xA9: case 0xAD: case 0xB1: case 0xB5: case 0xB9: case 0xBD: return startIndex + ( currentFrameNumber % 3 ) + 1; default: return 0; } case OBJNDSRT: switch ( startIndex ) { // campfire case 0x36: case 0x3D: return startIndex + ( currentFrameNumber % 6 ) + 1; default: return 0; } case OBJNGRA2: switch ( startIndex ) { // mill case 0x17: case 0x1B: case 0x1F: case 0x23: case 0x27: case 0x2B: case 0x2F: case 0x33: case 0x37: case 0x3B: return startIndex + ( currentFrameNumber % 3 ) + 1; // smoke from chimney case 0x3F: case 0x46: case 0x4D: // Archer House case 0x54: // smoke from chimney case 0x5D: case 0x64: // shadow smoke case 0x6B: // Peasant Hut case 0x72: return startIndex + ( currentFrameNumber % 6 ) + 1; default: return 0; } case OBJNLAV2: switch ( startIndex ) { // middle volcano case 0x00: // shadow case 0x07: case 0x0E: // lava case 0x15: return startIndex + ( currentFrameNumber % 6 ) + 1; // small volcano // shadow case 0x21: case 0x2C: // lava case 0x37: case 0x43: return startIndex + ( currentFrameNumber % 10 ) + 1; default: return 0; } case OBJNLAV3: // big volcano switch ( startIndex ) { // smoke case 0x00: case 0x0F: case 0x1E: case 0x2D: case 0x3C: case 0x4B: case 0x5A: case 0x69: case 0x87: case 0x96: case 0xA5: // shadow case 0x78: case 0xB4: case 0xC3: case 0xD2: case 0xE1: return startIndex + ( currentFrameNumber % 14 ) + 1; default: return 0; } case OBJNLAVA: switch ( startIndex ) { // shadow of lava case 0x4E: case 0x58: case 0x62: return startIndex + ( currentFrameNumber % 9 ) + 1; default: return 0; } case OBJNMUL2: switch ( startIndex ) { // lighthouse case 0x3D: return startIndex + ( currentFrameNumber % 9 ) + 1; // Alchemist Tower case 0x1B: // watermill case 0x53: case 0x5A: case 0x62: case 0x69: // fire in Wagon Camp case 0x81: // smoke smithy (2 chimney) case 0xA6: // smoke smithy (1 chimney) case 0xAD: // shadow smoke case 0xB4: return startIndex + ( currentFrameNumber % 6 ) + 1; // magic garden case 0xBE: return quantity ? startIndex + ( currentFrameNumber % 6 ) + 1 : startIndex + 7; default: return 0; } case OBJNMULT: switch ( startIndex ) { // smoke case 0x05: // shadow case 0x0F: case 0x19: return startIndex + ( currentFrameNumber % 9 ) + 1; // smoke case 0x24: // shadow case 0x2D: return startIndex + ( currentFrameNumber % 8 ) + 1; // smoke case 0x5A: // shadow case 0x61: case 0x68: case 0x7C: // campfire case 0x83: return startIndex + ( currentFrameNumber % 6 ) + 1; default: return 0; } case OBJNSNOW: switch ( startIndex ) { // fire camp case 0x04: // Alchemist Tower case 0x97: // watermill case 0xA2: case 0xA9: case 0xB1: case 0xB8: return startIndex + ( currentFrameNumber % 6 ) + 1; // mill case 0x60: case 0x64: case 0x68: case 0x6C: case 0x70: case 0x74: case 0x78: case 0x7C: case 0x80: case 0x84: return startIndex + ( currentFrameNumber % 3 ) + 1; default: return 0; } case OBJNSWMP: switch ( startIndex ) { // shadow case 0x00: case 0x0E: case 0x2B: // smoke case 0x07: case 0x22: case 0x33: // light in window case 0x16: case 0x3A: case 0x43: case 0x4A: return startIndex + ( currentFrameNumber % 6 ) + 1; default: return 0; } // extra objects for loyalty version case X_LOC1: if ( Settings::Get().isPriceOfLoyaltySupported() ) switch ( startIndex ) { // alchemist tower case 0x04: case 0x0D: case 0x16: // arena case 0x1F: case 0x28: case 0x32: case 0x3B: // earth altar case 0x55: case 0x5E: case 0x67: return startIndex + ( currentFrameNumber % 8 ) + 1; default: return 0; } break; // extra objects for loyalty version case X_LOC2: if ( Settings::Get().isPriceOfLoyaltySupported() ) switch ( startIndex ) { // mermaid case 0x0A: case 0x13: case 0x1C: case 0x25: // sirens case 0x2F: case 0x38: case 0x41: case 0x4A: case 0x53: case 0x5C: case 0x66: return startIndex + ( currentFrameNumber % 8 ) + 1; default: return 0; } break; // extra objects for loyalty version case X_LOC3: if ( Settings::Get().isPriceOfLoyaltySupported() ) switch ( startIndex ) { // hut magi case 0x00: case 0x0A: case 0x14: // eye magi case 0x20: case 0x29: case 0x32: return startIndex + ( currentFrameNumber % 8 ) + 1; // barrier case 0x3C: case 0x42: case 0x48: case 0x4E: case 0x54: case 0x5A: case 0x60: case 0x66: return startIndex + ( currentFrameNumber % 4 ) + 1; default: return 0; } break; default: break; } return 0; } int ICN::getHeroPortraitIcnId( const int heroId ) { switch ( heroId ) { case Heroes::UNKNOWN: return ICN::UNKNOWN; case Heroes::LORDKILBURN: return ICN::PORT0000; case Heroes::SIRGALLANTH: return ICN::PORT0001; case Heroes::ECTOR: return ICN::PORT0002; case Heroes::GVENNETH: return ICN::PORT0003; case Heroes::TYRO: return ICN::PORT0004; case Heroes::AMBROSE: return ICN::PORT0005; case Heroes::RUBY: return ICN::PORT0006; case Heroes::MAXIMUS: return ICN::PORT0007; case Heroes::DIMITRY: return ICN::PORT0008; case Heroes::THUNDAX: return ICN::PORT0009; case Heroes::FINEOUS: return ICN::PORT0010; case Heroes::JOJOSH: return ICN::PORT0011; case Heroes::CRAGHACK: return ICN::PORT0012; case Heroes::JEZEBEL: return ICN::PORT0013; case Heroes::JACLYN: return ICN::PORT0014; case Heroes::ERGON: return ICN::PORT0015; case Heroes::TSABU: return ICN::PORT0016; case Heroes::ATLAS: return ICN::PORT0017; case Heroes::ASTRA: return ICN::PORT0018; case Heroes::NATASHA: return ICN::PORT0019; case Heroes::TROYAN: return ICN::PORT0020; case Heroes::VATAWNA: return ICN::PORT0021; case Heroes::REBECCA: return ICN::PORT0022; case Heroes::GEM: return ICN::PORT0023; case Heroes::ARIEL: return ICN::PORT0024; case Heroes::CARLAWN: return ICN::PORT0025; case Heroes::LUNA: return ICN::PORT0026; case Heroes::ARIE: return ICN::PORT0027; case Heroes::ALAMAR: return ICN::PORT0028; case Heroes::VESPER: return ICN::PORT0029; case Heroes::CRODO: return ICN::PORT0030; case Heroes::BAROK: return ICN::PORT0031; case Heroes::KASTORE: return ICN::PORT0032; case Heroes::AGAR: return ICN::PORT0033; case Heroes::FALAGAR: return ICN::PORT0034; case Heroes::WRATHMONT: return ICN::PORT0035; case Heroes::MYRA: return ICN::PORT0036; case Heroes::FLINT: return ICN::PORT0037; case Heroes::DAWN: return ICN::PORT0038; case Heroes::HALON: return ICN::PORT0039; case Heroes::MYRINI: return ICN::PORT0040; case Heroes::WILFREY: return ICN::PORT0041; case Heroes::SARAKIN: return ICN::PORT0042; case Heroes::KALINDRA: return ICN::PORT0043; case Heroes::MANDIGAL: return ICN::PORT0044; case Heroes::ZOM: return ICN::PORT0045; case Heroes::DARLANA: return ICN::PORT0046; case Heroes::ZAM: return ICN::PORT0047; case Heroes::RANLOO: return ICN::PORT0048; case Heroes::CHARITY: return ICN::PORT0049; case Heroes::RIALDO: return ICN::PORT0050; case Heroes::ROXANA: return ICN::PORT0051; case Heroes::SANDRO: return ICN::PORT0052; case Heroes::CELIA: return ICN::PORT0053; case Heroes::ROLAND: return ICN::PORT0054; case Heroes::CORLAGON: return ICN::PORT0055; case Heroes::ELIZA: return ICN::PORT0056; case Heroes::ARCHIBALD: return ICN::PORT0057; case Heroes::HALTON: return ICN::PORT0058; case Heroes::BRAX: return ICN::PORT0059; case Heroes::SOLMYR: return ICN::PORT0060; case Heroes::DAINWIN: return ICN::PORT0061; case Heroes::MOG: return ICN::PORT0062; case Heroes::UNCLEIVAN: return ICN::PORT0063; case Heroes::JOSEPH: return ICN::PORT0064; case Heroes::GALLAVANT: return ICN::PORT0065; case Heroes::ELDERIAN: return ICN::PORT0066; case Heroes::CEALLACH: return ICN::PORT0067; case Heroes::DRAKONIA: return ICN::PORT0068; case Heroes::MARTINE: return ICN::PORT0069; case Heroes::JARKONAS: return ICN::PORT0070; case Heroes::DEBUG_HERO: return ICN::PORT0059; default: // Did you add a new hero? Add the logic above! assert( 0 ); break; } return ICN::UNKNOWN; } int ICN::getCaptainIcnId( const int race ) { switch ( race ) { case Race::BARB: return CSTLCAPB; case Race::KNGT: return CSTLCAPK; case Race::NECR: return CSTLCAPN; case Race::SORC: return CSTLCAPS; case Race::WRLK: return CSTLCAPW; case Race::WZRD: return CSTLCAPZ; default: break; } return UNKNOWN; } int ICN::getBuildingIcnId( const int race ) { switch ( race ) { case Race::BARB: return CSTLBARB; case Race::KNGT: return CSTLKNGT; case Race::NECR: return CSTLNECR; case Race::SORC: return CSTLSORC; case Race::WRLK: return CSTLWRLK; case Race::WZRD: return CSTLWZRD; default: break; } return UNKNOWN; } int ICN::getCastleIcnId( const int race ) { switch ( race ) { case Race::BARB: return CASTLEB; case Race::KNGT: return CASTLEK; case Race::NECR: return CASTLEN; case Race::SORC: return CASTLES; case Race::WRLK: return CASTLEW; case Race::WZRD: return CASTLEZ; default: break; } return UNKNOWN; } int ICN::getFlagIcnId( const int color ) { switch ( color ) { case Color::BLUE: return ICN::HEROFL00; case Color::GREEN: return ICN::HEROFL01; case Color::RED: return ICN::HEROFL02; case Color::YELLOW: return ICN::HEROFL03; case Color::ORANGE: return ICN::HEROFL04; case Color::PURPLE: return ICN::HEROFL05; default: return ICN::HEROFL06; } } fheroes2-1.1.6+dfsg/src/fheroes2/agg/icn.h000066400000000000000000000570421476115357100201610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace ICN { enum : int { UNKNOWN, ADVBORDE, ADVBORD, ADVBTNS, ADVEBTNS, ADVMCO, AELEM, APANBKGE, APANBKG, APANELE, APANEL, ARCHER2, ARCHER, ARCH_MSL, ART32, ARTFX, ARTIFACT, BARB32, B_BFLG32, // blue hero flag on a boat BERZERK, B_FLAG32, // blue hero flag BIGBAR, BLDGXTRA, BLESS, BLIND, BLUEFIRE, BOAR, BOAT32, BOATSHAD, BOATWIND, BOOK, BORDEDIT, BOULDER, BRCREST, BROTHERS, BTNBAUD, BTNCMPGN, BTNCOM, BTNDCCFG, BTNDC, BTNEMAIN, BTNENEW, BTNESIZE, BTNHOTST, BTNMCFG, BTNMODEM, BTNMP, BTNNET2, BTNNET, BTNNEWGM, BTNSHNGL, BUILDING, BUYBUILD, BUYBUILE, CAMPBKGE, CAMPBKGG, CAMPXTRE, CAMPXTRG, CAPTCOVR, CASLBAR, CASLWIND, CASLXTRA, CASTBKGB, CASTBKGK, CASTBKGN, CASTBKGS, CASTBKGW, CASTBKGZ, CASTLEB, CASTLEK, CASTLEN, CASTLES, CASTLEW, CASTLEZ, CATAPULT, CAVALRYB, CAVALRYR, CBKGBEAC, CBKGCRCK, CBKGDIMT, CBKGDITR, CBKGDSRT, CBKGGRAV, CBKGGRMT, CBKGGRTR, CBKGLAVA, CBKGSNMT, CBKGSNTR, CBKGSWMP, CBKGWATR, CELLWIN, CENTAUR, CFLGSMAL, CLOP32, CLOUDLUK, CMBTCAPB, CMBTCAPK, CMBTCAPN, CMBTCAPS, CMBTCAPW, CMBTCAPZ, CMBTFLE1, CMBTFLE2, CMBTFLE3, CMBTHROB, CMBTHROK, CMBTHRON, CMBTHROS, CMBTHROW, CMBTHROZ, CMBTLOS1, CMBTLOS2, CMBTLOS3, CMBTMISC, CMBTSURR, CMSECO, COBJ0000, COBJ0001, COBJ0002, COBJ0003, COBJ0004, COBJ0005, COBJ0006, COBJ0007, COBJ0008, COBJ0009, COBJ0010, COBJ0011, COBJ0012, COBJ0013, COBJ0014, COBJ0015, COBJ0016, COBJ0017, COBJ0018, COBJ0019, COBJ0020, COBJ0021, COBJ0022, COBJ0023, COBJ0024, COBJ0025, COBJ0026, COBJ0027, COBJ0028, COBJ0029, COBJ0030, COBJ0031, COLDRAY, COLDRING, CONGRATS, COVR0001, COVR0002, COVR0003, COVR0004, COVR0005, COVR0006, COVR0007, COVR0008, COVR0009, COVR0010, COVR0011, COVR0012, COVR0013, COVR0014, COVR0015, COVR0016, COVR0017, COVR0018, COVR0019, COVR0020, COVR0021, COVR0022, COVR0023, COVR0024, CPANBKGE, CPANBKG, CPANELE, CPANEL, CREST, CSPANBKE, CSPANBKG, CSPANBTE, CSPANBTN, CSPANEL, CSTLBARB, CSTLCAPB, CSTLCAPK, CSTLCAPN, CSTLCAPS, CSTLCAPW, CSTLCAPZ, CSTLKNGT, CSTLNECR, CSTLSORC, CSTLWRLK, CSTLWZRD, CTRACK00, CTRACK01, CTRACK02, CTRACK03, CTRACK04, CTRACK05, CTRACK06, CURSE, CYCLOPS, DISRRAY, DRAGBLAK, DRAGBONE, DRAGGREE, DRAGRED, DRAGSLAY, DROPLISL, DROPLIST, DRUID2, DRUID, DRUIDMSL, DUMMY, DWARF2, DWARF, ECPANEL, EDITBTNS, EDITOR, EDITPANL, EELEM, ELECTRIC, ELF2, ELF, ELF__MSL, ESCROLL, ESPANBKG, ESPANBTN, ESPANEL, EVIW_ALL, EVIWDDOR, EVIWHROS, EVIWMINE, EVIWPUZL, EVIWRSRC, EVIWRTFX, EVIWTWNS, EVIWWRLD, EXPMRL, EXTRAOVR, FELEM, FIREBAL2, FIREBALL, FLAG32, FONT, FRNG0001, FRNG0002, FRNG0003, FRNG0004, FRNG0005, FRNG0006, FRNG0007, FRNG0008, FRNG0009, FRNG0010, FRNG0011, FRNG0012, FRNG0013, FROTH, GARGOYLE, G_BFLG32, // green hero flag on a boat GENIE, G_FLAG32, // green hero flag GHOST, GOBLIN, GOLEM2, GOLEM, GRIFFIN, GROUND12, GROUND4, GROUND6, HALFLING, HALFLMSL, HASTE, HEROBKG, HEROES, HEROEXTE, HEROEXTG, HEROFL00, HEROFL01, HEROFL02, HEROFL03, HEROFL04, HEROFL05, HEROFL06, HEROLOGE, HEROLOGO, HISCORE, HOURGLAS, HSBKG, HSBTNS, HSICONS, HYDRA, HYPNOTIZ, ICECLOUD, KEEP, KNGT32, LETTER12, LETTER4, LETTER6, LGNDXTRA, LGNDXTRE, LICH2, LICHCLOD, LICH, LICH_MSL, LISTBOX, LISTBOXS, LOCATORE, LOCATORS, MAGE1, MAGE2, MAGEGLDB, MAGEGLDK, MAGEGLDN, MAGEGLDS, MAGEGLDW, MAGEGLDZ, MAGIC01, MAGIC02, MAGIC03, MAGIC04, MAGIC06, MAGIC07, MAGIC08, MANA, MEDUSA, METEOR, MINICAPT, MINIHERO, MINILKMR, MINIMON, MINIPORT, MINISS, MINITOWN, MINOTAU2, MINOTAUR, MISC12, MISC4, MISC6, MOATPART, MOATWHOL, MOBILITY, MONH0000, MONH0001, MONH0002, MONH0003, MONH0004, MONH0005, MONH0006, MONH0007, MONH0008, MONH0009, MONH0010, MONH0011, MONH0012, MONH0013, MONH0014, MONH0015, MONH0016, MONH0017, MONH0018, MONH0019, MONH0020, MONH0021, MONH0022, MONH0023, MONH0024, MONH0025, MONH0026, MONH0027, MONH0028, MONH0029, MONH0030, MONH0031, MONH0032, MONH0033, MONH0034, MONH0035, MONH0036, MONH0037, MONH0038, MONH0039, MONH0040, MONH0041, MONH0042, MONH0043, MONH0044, MONH0045, MONH0046, MONH0047, MONH0048, MONH0049, MONH0050, MONH0051, MONH0052, MONH0053, MONH0054, MONH0055, MONH0056, MONH0057, MONH0058, MONH0059, MONH0060, MONH0061, MONH0062, MONH0063, MONH0064, MONH0065, MONS32, MORALEB, MORALEG, MTNCRCK, MTNDIRT, MTNDSRT, MTNGRAS, MTNLAVA, MTNMULT, MTNSNOW, MTNSWMP, MUMMY2, MUMMYW, NECR32, NETBOX, NGEXTRA, NGHSBKG, NGMPBKG, NGSPBKG, NOMAD, O_BFLG32, // orange hero flag on a boat OBJNARTI, OBJNCRCK, OBJNDIRT, OBJNDSRT, OBJNGRA2, OBJNGRAS, OBJNHAUN, OBJNLAV2, OBJNLAV3, OBJNLAVA, OBJNMUL2, OBJNMULT, OBJNRSRC, OBJNSNOW, OBJNSWMP, OBJNTOWN, OBJNTWBA, OBJNTWRD, OBJNTWSH, OBJNWAT2, OBJNWATR, OBJNXTRA, OBJPALET, O_FLAG32, // orange hero flag OGRE2, OGRE, ORC2, ORC, ORC__MSL, OVERBACK, OVERLAY, OVERVIEW, PALADIN2, PALADIN, PARALYZE, P_BFLG32, // purple hero flag on a boat PEASANT, P_FLAG32, // purple hero flag PHOENIX, PHYSICAL, PIKEMAN2, PIKEMAN, PORT0000, PORT0001, PORT0002, PORT0003, PORT0004, PORT0005, PORT0006, PORT0007, PORT0008, PORT0009, PORT0010, PORT0011, PORT0012, PORT0013, PORT0014, PORT0015, PORT0016, PORT0017, PORT0018, PORT0019, PORT0020, PORT0021, PORT0022, PORT0023, PORT0024, PORT0025, PORT0026, PORT0027, PORT0028, PORT0029, PORT0030, PORT0031, PORT0032, PORT0033, PORT0034, PORT0035, PORT0036, PORT0037, PORT0038, PORT0039, PORT0040, PORT0041, PORT0042, PORT0043, PORT0044, PORT0045, PORT0046, PORT0047, PORT0048, PORT0049, PORT0050, PORT0051, PORT0052, PORT0053, PORT0054, PORT0055, PORT0056, PORT0057, PORT0058, PORT0059, PORT0060, PORT0061, PORT0062, PORT0063, PORT0064, PORT0065, PORT0066, PORT0067, PORT0068, PORT0069, PORT0070, PORT0090, PORT0091, PORT0092, PORT0093, PORT0094, PORT0095, PORTCFLG, PORTMEDI, PORTXTRA, PRIMSKIL, PUZZLE, QWIKHERO, QWIKINFO, QWIKTOWN, RADAR, R_BFLG32, // red hero flag on a boat RECR2BKG, RECRBKG, RECRUIT, REDBACK, REDDEATH, REDFIRE, REQBKG, REQSBKG, REQUEST, REQUESTS, RESOURCE, RESSMALL, R_FLAG32, // red hero flag ROAD, ROC, ROGUE, ROUTE, SCENIBKG, SCROLL2, SCROLLCN, SCROLLE, SCROLL, SECSKILL, SHADOW32, SHIELD, SHNGANIM, SKELETON, SMALCLOD, SMALFONT, SMALLBAR, SORC32, SPANBKGE, SPANBKG, SPANBTNE, SPANBTN, SPANEL, SPARKS, SPELCO, SPELLINF, SPELLINL, SPELLS, SPRITE, STELSKIN, STONBACK, STONBAKE, STONEBAK, STONEBK2, STONSKIN, STORM, STREAM, STRIP, SUNMOONE, SUNMOON, SURDRBKE, SURDRBKG, SURRENDE, SURRENDR, SWAPBTN, SWAPWIN, SWORDSM2, SWORDSMN, SYSTEME, // contains an empty evil interface button in the last two sprites SYSTEM, // contains an empty good interface button in the last two sprites TAVWIN, TENT, TERRAINS, TEXTBACK, TEXTBAK2, TEXTBAR, TITANBLA, TITANBLU, TITANMSL, TOWNBKG0, TOWNBKG1, TOWNBKG2, TOWNBKG3, TOWNBKG4, TOWNBKG5, TOWNFIX, TOWNNAME, TOWNWIND, TRADPOSE, TRADPOST, TREASURY, TREDECI, TREEVIL, TREFALL, TREFIR, TREJNGL, TRESNOW, TROLL2, TROLL, TROLLMSL, TWNBBOAT, TWNBCAPT, TWNBCSTL, TWNBDOCK, TWNBDW_0, TWNBDW_1, TWNBDW_2, TWNBDW_3, TWNBDW_4, TWNBDW_5, TWNBEXT0, TWNBEXT1, TWNBEXT2, TWNBEXT3, TWNBLTUR, TWNBMAGE, TWNBMARK, TWNBMOAT, TWNBRTUR, TWNBSPEC, TWNBSTAT, TWNBTENT, TWNBTHIE, TWNBTVRN, TWNBUP_1, TWNBUP_3, TWNBUP_4, TWNBWEL2, TWNBWELL, TWNKBOAT, TWNKCAPT, TWNKCSTL, TWNKDOCK, TWNKDW_0, TWNKDW_1, TWNKDW_2, TWNKDW_3, TWNKDW_4, TWNKDW_5, TWNKEXT0, TWNKEXT1, TWNKEXT2, TWNKLTUR, TWNKMAGE, TWNKMARK, TWNKMOAT, TWNKRTUR, TWNKSPEC, TWNKSTAT, TWNKTENT, TWNKTHIE, TWNKTVRN, TWNKUP_1, TWNKUP_2, TWNKUP_3, TWNKUP_4, TWNKUP_5, TWNKWEL2, TWNKWELL, TWNNBOAT, TWNNCAPT, TWNNCSTL, TWNNDOCK, TWNNDW_0, TWNNDW_1, TWNNDW_2, TWNNDW_3, TWNNDW_4, TWNNDW_5, TWNNEXT0, TWNNLTUR, TWNNMAGE, TWNNMARK, TWNNMOAT, TWNNRTUR, TWNNSPEC, TWNNSTAT, TWNNTENT, TWNNTHIE, TWNNTVRN, TWNNUP_1, TWNNUP_2, TWNNUP_3, TWNNUP_4, TWNNWEL2, TWNNWELL, TWNSBOAT, TWNSCAPT, TWNSCSTL, TWNSDOCK, TWNSDW_0, TWNSDW_1, TWNSDW_2, TWNSDW_3, TWNSDW_4, TWNSDW_5, TWNSEXT0, TWNSEXT1, TWNSLTUR, TWNSMAGE, TWNSMARK, TWNSMOAT, TWNSRTUR, TWNSSPEC, TWNSSTAT, TWNSTENT, TWNSTHIE, TWNSTVRN, TWNSUP_1, TWNSUP_2, TWNSUP_3, TWNSWEL2, TWNSWELL, TWNWBOAT, TWNWCAPT, TWNWCSTL, TWNWDOCK, TWNWDW_0, TWNWDW_1, TWNWDW_2, TWNWDW_3, TWNWDW_4, TWNWDW_5, TWNWEXT0, TWNWLTUR, TWNWMAGE, TWNWMARK, TWNWMOAT, TWNWRTUR, TWNWSPEC, TWNWSTAT, TWNWTENT, TWNWTHIE, TWNWTVRN, TWNWUP_3, TWNWUP5B, TWNWUP_5, TWNWWEL2, TWNWWELL, TWNZBOAT, TWNZCAPT, TWNZCSTL, TWNZDOCK, TWNZDW_0, TWNZDW_1, TWNZDW_2, TWNZDW_3, TWNZDW_4, TWNZDW_5, TWNZEXT0, TWNZLTUR, TWNZMAGE, TWNZMARK, TWNZMOAT, TWNZRTUR, TWNZSPEC, TWNZSTAT, TWNZTENT, TWNZTHIE, TWNZTVRN, TWNZUP_2, TWNZUP_4, TWNZUP_5, TWNZWEL2, TWNZWELL, UNICORN, VAMPIRE2, VAMPIRE, VGENBKGE, VGENBKG, VIEW_ALL, VIEWARME, VIEWARMY, VIEWARSM, VIEWDDOR, VIEWGEN, VIEWHROS, VIEWMINE, VIEWPUZL, VIEWRSRC, VIEWRTFX, VIEWTWNS, VIEWWRLD, VWFLAG12, VWFLAG4, VWFLAG6, WELEM, WELLBKG, WELLXTRA, WINCMBBE, WINCMBTB, WINCMBT, WINLOSEB, WINLOSEE, WINLOSE, WOLF, WRLK32, WZRD32, X_IVY, X_LOADCM, X_CMPBKG, X_CMPBTN, X_CMPEXT, X_TRACK1, X_TRACK2, X_TRACK3, X_TRACK4, X_LOC1, X_LOC2, X_LOC3, XPRIMARY, Y_BFLG32, // yellow hero flag on a boat Y_FLAG32, // yellow hero flag YINYANG, ZOMBIE2, ZOMBIE, LAST_VALID_FILE_ICN, // Real ICNs need a special reference to ICN files. Put generated by application ICNs at the end of this enumeration. // system ROUTERED, YELLOW_FONT, YELLOW_SMALLFONT, BUTTON_WELL_MAX, BTNBATTLEONLY, BUTTON_GIFT_GOOD, BUTTON_GIFT_EVIL, CSLMARKER, GRAY_FONT, GRAY_SMALL_FONT, TROLL2MSL, MONSTER_SWITCH_LEFT_ARROW, MONSTER_SWITCH_RIGHT_ARROW, NON_UNIFORM_GOOD_RESTART_BUTTON, NON_UNIFORM_EVIL_RESTART_BUTTON, UNIFORM_GOOD_MAX_BUTTON, UNIFORM_GOOD_MIN_BUTTON, UNIFORM_EVIL_MAX_BUTTON, UNIFORM_EVIL_MIN_BUTTON, UNIFORM_GOOD_OKAY_BUTTON, UNIFORM_EVIL_OKAY_BUTTON, UNIFORM_GOOD_CANCEL_BUTTON, UNIFORM_EVIL_CANCEL_BUTTON, UNIFORM_GOOD_EXIT_BUTTON, UNIFORM_EVIL_EXIT_BUTTON, GOLDEN_GRADIENT_FONT, SILVER_GRADIENT_FONT, WHITE_LARGE_FONT, GOLDEN_GRADIENT_LARGE_FONT, SILVER_GRADIENT_LARGE_FONT, SWAP_ARROW_LEFT_TO_RIGHT, SWAP_ARROW_RIGHT_TO_LEFT, SWAP_ARROWS_CIRCULAR, COLOR_CURSOR_ADVENTURE_MAP, MONO_CURSOR_ADVENTURE_MAP, DISMISS_HERO_DISABLED_BUTTON, KNIGHT_CASTLE_RIGHT_FARM, KNIGHT_CASTLE_LEFT_FARM, NECROMANCER_CASTLE_STANDALONE_CAPTAIN_QUARTERS, NECROMANCER_CASTLE_CAPTAIN_QUARTERS_BRIDGE, MAP_TYPE_ICON, BARBARIAN_CASTLE_CAPTAIN_QUARTERS_LEFT_SIDE, SORCERESS_CASTLE_CAPTAIN_QUARTERS_LEFT_SIDE, GOOD_ARMY_BUTTON, GOOD_MARKET_BUTTON, EVIL_ARMY_BUTTON, EVIL_MARKET_BUTTON, MONO_CURSOR_ADVMBW, MONO_CURSOR_SPELBW, MONO_CURSOR_CMSSBW, ESPANBKG_EVIL, STONEBAK_EVIL, STONEBAK_SMALL_POL, UNIFORMBAK_GOOD, UNIFORMBAK_EVIL, REDBAK_SMALL_VERTICAL, BLACKBAK, BROWNBAK, WELLBKG_EVIL, CASLWIND_EVIL, CASLXTRA_EVIL, STRIP_BACKGROUND_EVIL, EDITBTNS_EVIL, DROPLISL_EVIL, CELLWIN_EVIL, GOOD_CAMPAIGN_BUTTONS, EVIL_CAMPAIGN_BUTTONS, POL_CAMPAIGN_BUTTONS, MINI_MONSTER_IMAGE, MINI_MONSTER_SHADOW, BUTTON_GOOD_FONT_RELEASED, BUTTON_GOOD_FONT_PRESSED, BUTTON_EVIL_FONT_RELEASED, BUTTON_EVIL_FONT_PRESSED, EMPTY_GOOD_BUTTON, EMPTY_EVIL_BUTTON, EMPTY_POL_BUTTON, EMPTY_GUILDWELL_BUTTON, EMPTY_VERTICAL_GOOD_BUTTON, EMPTY_MAP_SELECT_BUTTON, EMPTY_INTERFACE_BUTTON_GOOD, EMPTY_INTERFACE_BUTTON_EVIL, BUTTON_STANDARD_GAME, BUTTON_CAMPAIGN_GAME, BUTTON_MULTIPLAYER_GAME, BUTTON_LARGE_CANCEL, BUTTON_LARGE_CONFIG, BUTTON_ORIGINAL_CAMPAIGN, BUTTON_EXPANSION_CAMPAIGN, BUTTON_HOT_SEAT, BUTTON_2_PLAYERS, BUTTON_3_PLAYERS, BUTTON_4_PLAYERS, BUTTON_5_PLAYERS, BUTTON_6_PLAYERS, BUTTON_NEW_GAME_GOOD, BUTTON_NEW_GAME_EVIL, BUTTON_SAVE_GAME_GOOD, BUTTON_SAVE_GAME_EVIL, BUTTON_LOAD_GAME_GOOD, BUTTON_LOAD_GAME_EVIL, BUTTON_INFO_GOOD, BUTTON_INFO_EVIL, BUTTON_QUIT_GOOD, BUTTON_QUIT_EVIL, BUTTON_SMALL_CANCEL_GOOD, BUTTON_SMALL_CANCEL_EVIL, BUTTON_SMALL_OKAY_GOOD, BUTTON_SMALL_OKAY_EVIL, BUTTON_SMALL_ACCEPT_GOOD, BUTTON_SMALL_ACCEPT_EVIL, BUTTON_SMALL_DECLINE_GOOD, BUTTON_SMALL_DECLINE_EVIL, BUTTON_SMALL_LEARN_GOOD, BUTTON_SMALL_LEARN_EVIL, BUTTON_SMALL_TRADE_GOOD, BUTTON_SMALL_TRADE_EVIL, BUTTON_SMALL_YES_GOOD, BUTTON_SMALL_YES_EVIL, BUTTON_SMALL_NO_GOOD, BUTTON_SMALL_NO_EVIL, BUTTON_SMALL_EXIT_GOOD, BUTTON_SMALL_EXIT_EVIL, BUTTON_EXIT_HEROES_MEETING, BUTTON_EXIT_TOWN, BUTTON_EXIT_PUZZLE_DIM_DOOR_GOOD, BUTTON_EXIT_PUZZLE_DIM_DOOR_EVIL, BUTTON_SMALL_DISMISS_GOOD, BUTTON_SMALL_DISMISS_EVIL, BUTTON_SMALL_UPGRADE_GOOD, BUTTON_SMALL_UPGRADE_EVIL, BUTTON_SMALL_RESTART_GOOD, BUTTON_SMALL_RESTART_EVIL, BUTTON_SMALL_MIN_GOOD, BUTTON_SMALL_MIN_EVIL, BUTTON_SMALL_MAX_GOOD, BUTTON_SMALL_MAX_EVIL, BUTTON_EXIT_GOOD, BUTTON_RESET_GOOD, BUTTON_START_GOOD, BUTTON_CASTLE_GOOD, BUTTON_CASTLE_EVIL, BUTTON_TOWN_GOOD, BUTTON_TOWN_EVIL, BUTTON_RESTRICT_GOOD, BUTTON_RESTRICT_EVIL, BUTTON_KINGDOM_EXIT, BUTTON_KINGDOM_HEROES, BUTTON_KINGDOM_TOWNS, BUTTON_MAPSIZE_SMALL, BUTTON_MAPSIZE_MEDIUM, BUTTON_MAPSIZE_LARGE, BUTTON_MAPSIZE_XLARGE, BUTTON_MAPSIZE_ALL, BUTTON_MAP_SELECT_GOOD, BUTTON_MAP_SELECT_EVIL, BUTTON_GUILDWELL_EXIT, BUTTON_VIEWWORLD_EXIT_GOOD, BUTTON_VIEWWORLD_EXIT_EVIL, BUTTON_VERTICAL_DISMISS, BUTTON_VERTICAL_EXIT, BUTTON_VERTICAL_PATROL, BUTTON_HSCORES_VERTICAL_CAMPAIGN, BUTTON_HSCORES_VERTICAL_EXIT, BUTTON_HSCORES_VERTICAL_STANDARD, GAME_OPTION_ICON, DIFFICULTY_ICON_EASY, DIFFICULTY_ICON_NORMAL, DIFFICULTY_ICON_HARD, DIFFICULTY_ICON_EXPERT, DIFFICULTY_ICON_IMPOSSIBLE, METALLIC_BORDERED_TEXTBOX_GOOD, METALLIC_BORDERED_TEXTBOX_EVIL, BUTTON_NEW_MAP_EVIL, BUTTON_NEW_MAP_GOOD, BUTTON_SAVE_MAP_EVIL, BUTTON_SAVE_MAP_GOOD, BUTTON_LOAD_MAP_EVIL, BUTTON_LOAD_MAP_GOOD, BUTTON_RUMORS_GOOD, BUTTON_RUMORS_EVIL, BUTTON_EVENTS_GOOD, BUTTON_EVENTS_EVIL, BUTTON_LANGUAGE_GOOD, BUTTON_LANGUAGE_EVIL, BUTTON_AUTO_COMBAT_GOOD, BUTTON_AUTO_COMBAT_EVIL, BUTTON_QUICK_COMBAT_GOOD, BUTTON_QUICK_COMBAT_EVIL, SCENIBKG_EVIL, // IMPORTANT! Put any new entry just above this one. LASTICN }; const char * getIcnFileName( const int icnId ); uint32_t getAnimatedIcnIndex( const int icnId, const uint32_t startIndex, const uint32_t currentFrameNumber, const bool quantity = false ); int getHeroPortraitIcnId( const int heroId ); int getCaptainIcnId( const int race ); int getBuildingIcnId( const int race ); int getCastleIcnId( const int race ); int getFlagIcnId( const int color ); } fheroes2-1.1.6+dfsg/src/fheroes2/agg/m82.cpp000066400000000000000000000414151476115357100203460ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "m82.h" #include "maps_tiles.h" #include "mp2.h" #include "spell.h" namespace M82 { const struct { int type; const char * string; } m82map[] = { { AELMATTK, "AELMATTK.82M" }, { AELMKILL, "AELMKILL.82M" }, { AELMMOVE, "AELMMOVE.82M" }, { AELMWNCE, "AELMWNCE.82M" }, { ANTIMAGK, "ANTIMAGK.82M" }, { ARCHATTK, "ARCHATTK.82M" }, { ARCHKILL, "ARCHKILL.82M" }, { ARCHMOVE, "ARCHMOVE.82M" }, { ARCHSHOT, "ARCHSHOT.82M" }, { ARCHWNCE, "ARCHWNCE.82M" }, { ARMGEDN, "ARMGEDN.82M" }, { BADLUCK, "BADLUCK.82M" }, { BADMRLE, "BADMRLE.82M" }, { BERZERK, "BERZERK.82M" }, { BLESS, "BLESS.82M" }, { BLIND, "BLIND.82M" }, { BLOODLUS, "BLOODLUS.82M" }, { BOARATTK, "BOARATTK.82M" }, { BOARKILL, "BOARKILL.82M" }, { BOARMOVE, "BOARMOVE.82M" }, { BOARWNCE, "BOARWNCE.82M" }, { BONEATTK, "BONEATTK.82M" }, { BONEKILL, "BONEKILL.82M" }, { BONEMOVE, "BONEMOVE.82M" }, { BONEWNCE, "BONEWNCE.82M" }, { BUILDTWN, "BUILDTWN.82M" }, { CATSND00, "CATSND00.82M" }, { CATSND02, "CATSND02.82M" }, { CAVLATTK, "CAVLATTK.82M" }, { CAVLKILL, "CAVLKILL.82M" }, { CAVLMOVE, "CAVLMOVE.82M" }, { CAVLWNCE, "CAVLWNCE.82M" }, { CHAINLTE, "CHAINLTE.82M" }, { CNTRATTK, "CNTRATTK.82M" }, { CNTRKILL, "CNTRKILL.82M" }, { CNTRMOVE, "CNTRMOVE.82M" }, { CNTRSHOT, "CNTRSHOT.82M" }, { CNTRWNCE, "CNTRWNCE.82M" }, { COLDRAY, "COLDRAY.82M" }, { COLDRING, "COLDRING.82M" }, { CURE, "CURE.82M" }, { CURSE, "CURSE.82M" }, { CYCLATTK, "CYCLATTK.82M" }, { CYCLKILL, "CYCLKILL.82M" }, { CYCLMOVE, "CYCLMOVE.82M" }, { CYCLWNCE, "CYCLWNCE.82M" }, { DIGSOUND, "DIGSOUND.82M" }, { DIPMAGK, "DIPMAGK.82M" }, { DISRUPTR, "DISRUPTR.82M" }, { DRAWBRG, "DRAWBRG.82M" }, { DRGNATTK, "DRGNATTK.82M" }, { DRGNKILL, "DRGNKILL.82M" }, { DRGNMOVE, "DRGNMOVE.82M" }, { DRGNSLAY, "DRGNSLAY.82M" }, { DRGNWNCE, "DRGNWNCE.82M" }, { DRUIATTK, "DRUIATTK.82M" }, { DRUIKILL, "DRUIKILL.82M" }, { DRUIMOVE, "DRUIMOVE.82M" }, { DRUISHOT, "DRUISHOT.82M" }, { DRUIWNCE, "DRUIWNCE.82M" }, { DWRFATTK, "DWRFATTK.82M" }, { DWRFKILL, "DWRFKILL.82M" }, { DWRFMOVE, "DWRFMOVE.82M" }, { DWRFWNCE, "DWRFWNCE.82M" }, { EELMATTK, "EELMATTK.82M" }, { EELMKILL, "EELMKILL.82M" }, { EELMMOVE, "EELMMOVE.82M" }, { EELMWNCE, "EELMWNCE.82M" }, { ELF_ATTK, "ELF_ATTK.82M" }, { ELF_KILL, "ELF_KILL.82M" }, { ELF_MOVE, "ELF_MOVE.82M" }, { ELF_SHOT, "ELF_SHOT.82M" }, { ELF_WNCE, "ELF_WNCE.82M" }, { ERTHQUAK, "ERTHQUAK.82M" }, { EXPERNCE, "EXPERNCE.82M" }, { FELMATTK, "FELMATTK.82M" }, { FELMKILL, "FELMKILL.82M" }, { FELMMOVE, "FELMMOVE.82M" }, { FELMWNCE, "FELMWNCE.82M" }, { FIREBALL, "FIREBALL.82M" }, { GARGATTK, "GARGATTK.82M" }, { GARGKILL, "GARGKILL.82M" }, { GARGMOVE, "GARGMOVE.82M" }, { GARGWNCE, "GARGWNCE.82M" }, { GBLNATTK, "GBLNATTK.82M" }, { GBLNKILL, "GBLNKILL.82M" }, { GBLNMOVE, "GBLNMOVE.82M" }, { GBLNWNCE, "GBLNWNCE.82M" }, { GENIATTK, "GENIATTK.82M" }, { GENIKILL, "GENIKILL.82M" }, { GENIMOVE, "GENIMOVE.82M" }, { GENIWNCE, "GENIWNCE.82M" }, { GHSTATTK, "GHSTATTK.82M" }, { GHSTKILL, "GHSTKILL.82M" }, { GHSTMOVE, "GHSTMOVE.82M" }, { GHSTWNCE, "GHSTWNCE.82M" }, { GOLMATTK, "GOLMATTK.82M" }, { GOLMKILL, "GOLMKILL.82M" }, { GOLMMOVE, "GOLMMOVE.82M" }, { GOLMWNCE, "GOLMWNCE.82M" }, { GOODLUCK, "GOODLUCK.82M" }, { GOODMRLE, "GOODMRLE.82M" }, { GRIFATTK, "GRIFATTK.82M" }, { GRIFKILL, "GRIFKILL.82M" }, { GRIFMOVE, "GRIFMOVE.82M" }, { GRIFWNCE, "GRIFWNCE.82M" }, { H2MINE, "H2MINE.82M" }, { HALFATTK, "HALFATTK.82M" }, { HALFKILL, "HALFKILL.82M" }, { HALFMOVE, "HALFMOVE.82M" }, { HALFSHOT, "HALFSHOT.82M" }, { HALFWNCE, "HALFWNCE.82M" }, { HASTE, "HASTE.82M" }, { HYDRATTK, "HYDRATTK.82M" }, { HYDRKILL, "HYDRKILL.82M" }, { HYDRMOVE, "HYDRMOVE.82M" }, { HYDRWNCE, "HYDRWNCE.82M" }, { HYPNOTIZ, "HYPNOTIZ.82M" }, { KEEPSHOT, "KEEPSHOT.82M" }, { KILLFADE, "KILLFADE.82M" }, { LICHATTK, "LICHATTK.82M" }, { LICHEXPL, "LICHEXPL.82M" }, { LICHKILL, "LICHKILL.82M" }, { LICHMOVE, "LICHMOVE.82M" }, { LICHSHOT, "LICHSHOT.82M" }, { LICHWNCE, "LICHWNCE.82M" }, { LIGHTBLT, "LIGHTBLT.82M" }, { LOOP0000, "LOOP0000.82M" }, { LOOP0001, "LOOP0001.82M" }, { LOOP0002, "LOOP0002.82M" }, { LOOP0003, "LOOP0003.82M" }, { LOOP0004, "LOOP0004.82M" }, { LOOP0005, "LOOP0005.82M" }, { LOOP0006, "LOOP0006.82M" }, { LOOP0007, "LOOP0007.82M" }, { LOOP0008, "LOOP0008.82M" }, { LOOP0009, "LOOP0009.82M" }, { LOOP0010, "LOOP0010.82M" }, { LOOP0011, "LOOP0011.82M" }, { LOOP0012, "LOOP0012.82M" }, { LOOP0013, "LOOP0013.82M" }, { LOOP0014, "LOOP0014.82M" }, { LOOP0015, "LOOP0015.82M" }, { LOOP0016, "LOOP0016.82M" }, { LOOP0017, "LOOP0017.82M" }, { LOOP0018, "LOOP0018.82M" }, { LOOP0019, "LOOP0019.82M" }, { LOOP0020, "LOOP0020.82M" }, { LOOP0021, "LOOP0021.82M" }, { LOOP0022, "LOOP0022.82M" }, { LOOP0023, "LOOP0023.82M" }, { LOOP0024, "LOOP0024.82M" }, { LOOP0025, "LOOP0025.82M" }, { LOOP0026, "LOOP0026.82M" }, { LOOP0027, "LOOP0027.82M" }, { MAGCAROW, "MAGCAROW.82M" }, { MAGEATTK, "MAGEATTK.82M" }, { MAGEKILL, "MAGEKILL.82M" }, { MAGEMOVE, "MAGEMOVE.82M" }, { MAGESHOT, "MAGESHOT.82M" }, { MAGEWNCE, "MAGEWNCE.82M" }, { MASSBLES, "MASSBLES.82M" }, { MASSCURE, "MASSCURE.82M" }, { MASSCURS, "MASSCURS.82M" }, { MASSHAST, "MASSHAST.82M" }, { MASSSHIE, "MASSSHIE.82M" }, { MASSSLOW, "MASSSLOW.82M" }, { MEDSATTK, "MEDSATTK.82M" }, { MEDSKILL, "MEDSKILL.82M" }, { MEDSMOVE, "MEDSMOVE.82M" }, { MEDSWNCE, "MEDSWNCE.82M" }, { METEOR, "METEOR~1.82M" }, { MINOATTK, "MINOATTK.82M" }, { MINOKILL, "MINOKILL.82M" }, { MINOMOVE, "MINOMOVE.82M" }, { MINOWNCE, "MINOWNCE.82M" }, { MIRRORIM, "MIRRORIM.82M" }, { MNRDEATH, "MNRDEATH.82M" }, { MUMYATTK, "MUMYATTK.82M" }, { MUMYKILL, "MUMYKILL.82M" }, { MUMYMOVE, "MUMYMOVE.82M" }, { MUMYWNCE, "MUMYWNCE.82M" }, { NMADATTK, "NMADATTK.82M" }, { NMADKILL, "NMADKILL.82M" }, { NMADMOVE, "NMADMOVE.82M" }, { NMADWNCE, "NMADWNCE.82M" }, { NWHEROLV, "NWHEROLV.82M" }, { OGREATTK, "OGREATTK.82M" }, { OGREKILL, "OGREKILL.82M" }, { OGREMOVE, "OGREMOVE.82M" }, { OGREWNCE, "OGREWNCE.82M" }, { ORC_ATTK, "ORC_ATTK.82M" }, { ORC_KILL, "ORC_KILL.82M" }, { ORC_MOVE, "ORC_MOVE.82M" }, { ORC_SHOT, "ORC_SHOT.82M" }, { ORC_WNCE, "ORC_WNCE.82M" }, { PARALIZE, "PARALIZE.82M" }, { PHOEATTK, "PHOEATTK.82M" }, { PHOEKILL, "PHOEKILL.82M" }, { PHOEMOVE, "PHOEMOVE.82M" }, { PHOEWNCE, "PHOEWNCE.82M" }, { PICKUP01, "PICKUP01.82M" }, { PICKUP02, "PICKUP02.82M" }, { PICKUP03, "PICKUP03.82M" }, { PICKUP04, "PICKUP04.82M" }, { PICKUP05, "PICKUP05.82M" }, { PICKUP06, "PICKUP06.82M" }, { PICKUP07, "PICKUP07.82M" }, { PIKEATTK, "PIKEATTK.82M" }, { PIKEKILL, "PIKEKILL.82M" }, { PIKEMOVE, "PIKEMOVE.82M" }, { PIKEWNCE, "PIKEWNCE.82M" }, { PLDNATTK, "PLDNATTK.82M" }, { PLDNKILL, "PLDNKILL.82M" }, { PLDNMOVE, "PLDNMOVE.82M" }, { PLDNWNCE, "PLDNWNCE.82M" }, { PREBATTL, "PREBATTL.82M" }, { PROTECT, "PROTECT.82M" }, { PSNTATTK, "PSNTATTK.82M" }, { PSNTKILL, "PSNTKILL.82M" }, { PSNTMOVE, "PSNTMOVE.82M" }, { PSNTWNCE, "PSNTWNCE.82M" }, { RESURECT, "RESURECT.82M" }, { RESURTRU, "RESURTRU.82M" }, { ROC_ATTK, "ROC_ATTK.82M" }, { ROC_KILL, "ROC_KILL.82M" }, { ROC_MOVE, "ROC_MOVE.82M" }, { ROC_WNCE, "ROC_WNCE.82M" }, { ROGUATTK, "ROGUATTK.82M" }, { ROGUKILL, "ROGUKILL.82M" }, { ROGUMOVE, "ROGUMOVE.82M" }, { ROGUWNCE, "ROGUWNCE.82M" }, { RSBRYFZL, "RSBRYFZL.82M" }, { SHIELD, "SHIELD.82M" }, { SKELATTK, "SKELATTK.82M" }, { SKELKILL, "SKELKILL.82M" }, { SKELMOVE, "SKELMOVE.82M" }, { SKELWNCE, "SKELWNCE.82M" }, { SLOW, "SLOW.82M" }, { SPRTATTK, "SPRTATTK.82M" }, { SPRTKILL, "SPRTKILL.82M" }, { SPRTMOVE, "SPRTMOVE.82M" }, { SPRTWNCE, "SPRTWNCE.82M" }, { STELSKIN, "STELSKIN.82M" }, { STONESKI, "STONESKI.82M" }, { STONSKIN, "STONSKIN.82M" }, { STORM, "STORM.82M" }, { SUMNELM, "SUMNELM.82M" }, { SWDMATTK, "SWDMATTK.82M" }, { SWDMKILL, "SWDMKILL.82M" }, { SWDMMOVE, "SWDMMOVE.82M" }, { SWDMWNCE, "SWDMWNCE.82M" }, { TELEIN, "TELEIN.82M" }, { TELPTIN, "TELPTIN.82M" }, { TELPTOUT, "TELPTOUT.82M" }, { TITNATTK, "TITNATTK.82M" }, { TITNKILL, "TITNKILL.82M" }, { TITNMOVE, "TITNMOVE.82M" }, { TITNSHOT, "TITNSHOT.82M" }, { TITNWNCE, "TITNWNCE.82M" }, { TREASURE, "TREASURE.82M" }, { TRLLATTK, "TRLLATTK.82M" }, { TRLLKILL, "TRLLKILL.82M" }, { TRLLMOVE, "TRLLMOVE.82M" }, { TRLLSHOT, "TRLLSHOT.82M" }, { TRLLWNCE, "TRLLWNCE.82M" }, { UNICATTK, "UNICATTK.82M" }, { UNICKILL, "UNICKILL.82M" }, { UNICMOVE, "UNICMOVE.82M" }, { UNICWNCE, "UNICWNCE.82M" }, { VAMPATTK, "VAMPATTK.82M" }, { VAMPEXT1, "VAMPEXT1.82M" }, { VAMPEXT2, "VAMPEXT2.82M" }, { VAMPKILL, "VAMPKILL.82M" }, { VAMPMOVE, "VAMPMOVE.82M" }, { VAMPWNCE, "VAMPWNCE.82M" }, { WELMATTK, "WELMATTK.82M" }, { WELMKILL, "WELMKILL.82M" }, { WELMMOVE, "WELMMOVE.82M" }, { WELMWNCE, "WELMWNCE.82M" }, { WOLFATTK, "WOLFATTK.82M" }, { WOLFKILL, "WOLFKILL.82M" }, { WOLFMOVE, "WOLFMOVE.82M" }, { WOLFWNCE, "WOLFWNCE.82M" }, { WSND00, "WSND00.82M" }, { WSND01, "WSND01.82M" }, { WSND02, "WSND02.82M" }, { WSND03, "WSND03.82M" }, { WSND04, "WSND04.82M" }, { WSND05, "WSND05.82M" }, { WSND06, "WSND06.82M" }, { WSND10, "WSND10.82M" }, { WSND11, "WSND11.82M" }, { WSND12, "WSND12.82M" }, { WSND13, "WSND13.82M" }, { WSND14, "WSND14.82M" }, { WSND15, "WSND15.82M" }, { WSND16, "WSND16.82M" }, { WSND20, "WSND20.82M" }, { WSND21, "WSND21.82M" }, { WSND22, "WSND22.82M" }, { WSND23, "WSND23.82M" }, { WSND24, "WSND24.82M" }, { WSND25, "WSND25.82M" }, { WSND26, "WSND26.82M" }, { ZOMBATTK, "ZOMBATTK.82M" }, { ZOMBKILL, "ZOMBKILL.82M" }, { ZOMBMOVE, "ZOMBMOVE.82M" }, { ZOMBWNCE, "ZOMBWNCE.82M" }, { UNKNOWN, "UNKNOWN" } }; } const char * M82::GetString( int m82 ) { return AELMATTK <= m82 && UNKNOWN > m82 ? m82map[m82].string : m82map[UNKNOWN].string; } int M82::FromSpell( const int spellID ) { switch ( spellID ) { case Spell::FIREBALL: case Spell::FIREBLAST: return FIREBALL; case Spell::LIGHTNINGBOLT: return LIGHTBLT; case Spell::CHAINLIGHTNING: return CHAINLTE; case Spell::TELEPORT: return TELEIN; case Spell::CURE: return CURE; case Spell::MASSCURE: return MASSCURE; case Spell::RESURRECT: return RESURECT; case Spell::RESURRECTTRUE: return RESURTRU; case Spell::HASTE: return HASTE; case Spell::MASSHASTE: return MASSHAST; case Spell::SLOW: return SLOW; case Spell::MASSSLOW: return MASSSLOW; case Spell::BLIND: return BLIND; case Spell::BLESS: return BLESS; case Spell::MASSBLESS: return MASSBLES; case Spell::STONESKIN: return STONSKIN; case Spell::STEELSKIN: return STELSKIN; case Spell::CURSE: return CURSE; case Spell::MASSCURSE: return MASSCURS; case Spell::ANTIMAGIC: return ANTIMAGK; case Spell::DISPEL: case Spell::MASSDISPEL: return DIPMAGK; case Spell::ARROW: return MAGCAROW; case Spell::BERSERKER: return BERZERK; case Spell::ARMAGEDDON: return ARMGEDN; case Spell::ELEMENTALSTORM: return STORM; case Spell::METEORSHOWER: return METEOR; case Spell::PARALYZE: return PARALIZE; case Spell::HYPNOTIZE: return HYPNOTIZ; case Spell::COLDRAY: return COLDRAY; case Spell::COLDRING: return COLDRING; case Spell::DISRUPTINGRAY: return DISRUPTR; case Spell::DEATHRIPPLE: case Spell::DEATHWAVE: return MNRDEATH; case Spell::DRAGONSLAYER: return DRGNSLAY; case Spell::BLOODLUST: return BLOODLUS; case Spell::ANIMATEDEAD: return RESURECT; case Spell::MIRRORIMAGE: return MIRRORIM; case Spell::SHIELD: return SHIELD; case Spell::MASSSHIELD: return MASSSHIE; case Spell::SUMMONEELEMENT: case Spell::SUMMONAELEMENT: case Spell::SUMMONFELEMENT: case Spell::SUMMONWELEMENT: return SUMNELM; case Spell::EARTHQUAKE: return ERTHQUAK; case Spell::HAUNT: return H2MINE; case Spell::PETRIFY: return PARALIZE; default: break; } return UNKNOWN; } M82::SoundType M82::getAdventureMapTileSound( const Maps::Tile & tile ) { if ( tile.isStream() ) { return LOOP0014; } switch ( tile.getMainObjectType( false ) ) { case MP2::OBJ_BUOY: return LOOP0000; case MP2::OBJ_SHIPWRECK: case MP2::OBJ_DERELICT_SHIP: return LOOP0001; case MP2::OBJ_COAST: return LOOP0002; case MP2::OBJ_ORACLE: return LOOP0003; case MP2::OBJ_STONE_LITHS: return LOOP0004; case MP2::OBJ_VOLCANO: switch ( tile.getMainObjectPart().icnType ) { // Tile with volcanic steam only case MP2::OBJ_ICN_TYPE_UNKNOWN: return UNKNOWN; // Small volcanoes case MP2::OBJ_ICN_TYPE_OBJNLAVA: return LOOP0005; default: break; } // Other volcanoes return LOOP0027; case MP2::OBJ_LAVAPOOL: return LOOP0006; case MP2::OBJ_ALCHEMIST_LAB: return LOOP0007; case MP2::OBJ_WATER_WHEEL: return LOOP0009; case MP2::OBJ_CAMPFIRE: return LOOP0010; case MP2::OBJ_WINDMILL: return LOOP0011; case MP2::OBJ_ARTESIAN_SPRING: case MP2::OBJ_FOUNTAIN: return LOOP0012; case MP2::OBJ_WATER_LAKE: case MP2::OBJ_WATERING_HOLE: return LOOP0013; case MP2::OBJ_MINE: return LOOP0015; case MP2::OBJ_SAWMILL: return LOOP0016; case MP2::OBJ_DAEMON_CAVE: return LOOP0017; case MP2::OBJ_SHRINE_FIRST_CIRCLE: case MP2::OBJ_SHRINE_SECOND_CIRCLE: case MP2::OBJ_SHRINE_THIRD_CIRCLE: return LOOP0018; case MP2::OBJ_ROCK: // This sound should only be played for a specific sprite belonging to Rock if ( tile.containsSprite( MP2::OBJ_ICN_TYPE_OBJNWATR, 183 ) ) { return LOOP0019; } break; case MP2::OBJ_TAR_PIT: return LOOP0021; case MP2::OBJ_TRADING_POST: return LOOP0022; case MP2::OBJ_RUINS: return LOOP0024; case MP2::OBJ_PEASANT_HUT: case MP2::OBJ_DWARF_COTTAGE: case MP2::OBJ_ARCHER_HOUSE: return LOOP0025; case MP2::OBJ_ABANDONED_MINE: case MP2::OBJ_FREEMANS_FOUNDRY: return LOOP0026; default: break; } return UNKNOWN; } fheroes2-1.1.6+dfsg/src/fheroes2/agg/m82.h000066400000000000000000000176711476115357100200220ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace Maps { class Tile; } namespace M82 { enum SoundType : int { AELMATTK, AELMKILL, AELMMOVE, AELMWNCE, ANTIMAGK, ARCHATTK, ARCHKILL, ARCHMOVE, ARCHSHOT, ARCHWNCE, ARMGEDN, BADLUCK, BADMRLE, BERZERK, BLESS, BLIND, BLOODLUS, BOARATTK, BOARKILL, BOARMOVE, BOARWNCE, BONEATTK, BONEKILL, BONEMOVE, BONEWNCE, BUILDTWN, CATSND00, CATSND02, CAVLATTK, CAVLKILL, CAVLMOVE, CAVLWNCE, CHAINLTE, CNTRATTK, CNTRKILL, CNTRMOVE, CNTRSHOT, CNTRWNCE, COLDRAY, COLDRING, CURE, CURSE, CYCLATTK, CYCLKILL, CYCLMOVE, CYCLWNCE, DIGSOUND, DIPMAGK, DISRUPTR, DRAWBRG, DRGNATTK, DRGNKILL, DRGNMOVE, DRGNSLAY, DRGNWNCE, DRUIATTK, DRUIKILL, DRUIMOVE, DRUISHOT, DRUIWNCE, DWRFATTK, DWRFKILL, DWRFMOVE, DWRFWNCE, EELMATTK, EELMKILL, EELMMOVE, EELMWNCE, ELF_ATTK, ELF_KILL, ELF_MOVE, ELF_SHOT, ELF_WNCE, ERTHQUAK, EXPERNCE, FELMATTK, FELMKILL, FELMMOVE, FELMWNCE, FIREBALL, GARGATTK, GARGKILL, GARGMOVE, GARGWNCE, GBLNATTK, GBLNKILL, GBLNMOVE, GBLNWNCE, GENIATTK, GENIKILL, GENIMOVE, GENIWNCE, GHSTATTK, GHSTKILL, GHSTMOVE, GHSTWNCE, GOLMATTK, GOLMKILL, GOLMMOVE, GOLMWNCE, GOODLUCK, GOODMRLE, GRIFATTK, GRIFKILL, GRIFMOVE, GRIFWNCE, H2MINE, HALFATTK, HALFKILL, HALFMOVE, HALFSHOT, HALFWNCE, HASTE, HYDRATTK, HYDRKILL, HYDRMOVE, HYDRWNCE, HYPNOTIZ, KEEPSHOT, KILLFADE, LICHATTK, LICHEXPL, LICHKILL, LICHMOVE, LICHSHOT, LICHWNCE, LIGHTBLT, // These sounds are used for objects on Adventure Map. LOOP0000, LOOP0001, LOOP0002, LOOP0003, LOOP0004, LOOP0005, LOOP0006, LOOP0007, LOOP0008, // UNUSED: sounds of boiling hot liquid. Most likely magma or mercury. LOOP0009, LOOP0010, LOOP0011, LOOP0012, LOOP0013, LOOP0014, LOOP0015, LOOP0016, LOOP0017, LOOP0018, LOOP0019, // A sound with seagulls. It is used for rocks with seagulls. LOOP0020, // UNUSED: waves on a beach. LOOP0021, LOOP0022, LOOP0023, // UNUSED: a moving wooden structure with water. The most suitable for Water Wheel which uses LOOP0009. LOOP0024, LOOP0025, LOOP0026, // Moving (rusty?) mechanical parts, originally used for Abandoned Mine. In fheroes2, it is used also for Freeman's Foundry. LOOP0027, MAGCAROW, MAGEATTK, MAGEKILL, MAGEMOVE, MAGESHOT, MAGEWNCE, MASSBLES, MASSCURE, MASSCURS, MASSHAST, MASSSHIE, MASSSLOW, MEDSATTK, MEDSKILL, MEDSMOVE, MEDSWNCE, METEOR, MINOATTK, MINOKILL, MINOMOVE, MINOWNCE, MIRRORIM, MNRDEATH, MUMYATTK, MUMYKILL, MUMYMOVE, MUMYWNCE, NMADATTK, NMADKILL, NMADMOVE, NMADWNCE, NWHEROLV, OGREATTK, OGREKILL, OGREMOVE, OGREWNCE, ORC_ATTK, ORC_KILL, ORC_MOVE, ORC_SHOT, ORC_WNCE, PARALIZE, PHOEATTK, PHOEKILL, PHOEMOVE, PHOEWNCE, PICKUP01, PICKUP02, PICKUP03, PICKUP04, PICKUP05, PICKUP06, PICKUP07, PIKEATTK, PIKEKILL, PIKEMOVE, PIKEWNCE, PLDNATTK, PLDNKILL, PLDNMOVE, PLDNWNCE, PREBATTL, PROTECT, // UNUSED: some sort of magic. PSNTATTK, PSNTKILL, PSNTMOVE, PSNTWNCE, RESURECT, RESURTRU, ROC_ATTK, ROC_KILL, ROC_MOVE, ROC_WNCE, ROGUATTK, ROGUKILL, ROGUMOVE, ROGUWNCE, RSBRYFZL, SHIELD, SKELATTK, SKELKILL, SKELMOVE, SKELWNCE, SLOW, SPRTATTK, SPRTKILL, SPRTMOVE, SPRTWNCE, STELSKIN, STONESKI, // UNUSED. STONSKIN, STORM, SUMNELM, SWDMATTK, SWDMKILL, SWDMMOVE, SWDMWNCE, TELEIN, TELPTIN, TELPTOUT, TITNATTK, TITNKILL, TITNMOVE, TITNSHOT, TITNWNCE, TREASURE, TRLLATTK, TRLLKILL, TRLLMOVE, TRLLSHOT, TRLLWNCE, UNICATTK, UNICKILL, UNICMOVE, UNICWNCE, VAMPATTK, VAMPEXT1, VAMPEXT2, VAMPKILL, VAMPMOVE, VAMPWNCE, WELMATTK, WELMKILL, WELMMOVE, WELMWNCE, WOLFATTK, WOLFKILL, WOLFMOVE, WOLFWNCE, // Hero's movement sounds. WSND00, WSND01, WSND02, WSND03, WSND04, WSND05, WSND06, WSND10, WSND11, WSND12, WSND13, WSND14, WSND15, WSND16, WSND20, WSND21, WSND22, WSND23, WSND24, WSND25, WSND26, ZOMBATTK, ZOMBKILL, ZOMBMOVE, ZOMBWNCE, // Put all new sounds before this line. UNKNOWN }; const char * GetString( int m82 ); int FromSpell( const int spellID ); // Returns the ambient soundtrack for a given tile or M82::UNKNOWN if there is no track SoundType getAdventureMapTileSound( const Maps::Tile & tile ); } fheroes2-1.1.6+dfsg/src/fheroes2/agg/mus.cpp000066400000000000000000000214641476115357100205460ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2008 by Josh Matthews * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "mus.h" #include #include #include #include "ground.h" #include "race.h" #include "rand.h" namespace { struct MusMapItem { int type; const char * string; }; void addTrackId( std::string & output, const int musicTrackId ) { if ( musicTrackId < 10 ) { output += '0'; } output += std::to_string( musicTrackId ); } const std::array musmap = { { { MUS::UNUSED, "" }, { MUS::DATATRACK, "" }, { MUS::BATTLE1, "Battle 1" }, { MUS::BATTLE2, "Battle 2" }, { MUS::BATTLE3, "Battle 3" }, { MUS::SORCERESS_CASTLE, "Sorceress Castle" }, { MUS::WARLOCK_CASTLE, "Warlock Castle" }, { MUS::NECROMANCER_CASTLE, "Necromancer Castle" }, { MUS::KNIGHT_CASTLE, "Knight Castle" }, { MUS::BARBARIAN_CASTLE, "Barbarian Castle" }, { MUS::WIZARD_CASTLE, "Wizard Castle" }, { MUS::LAVA, "Lava Theme" }, { MUS::WASTELAND, "Wasteland Theme" }, { MUS::DESERT, "Desert Theme" }, { MUS::SNOW, "Snow Theme" }, { MUS::SWAMP, "Swamp Theme" }, { MUS::OCEAN, "Ocean Theme" }, { MUS::DIRT, "Dirt Theme" }, { MUS::GRASS, "Grass Theme" }, { MUS::LOSTGAME, "Lost Game" }, { MUS::NEW_WEEK, "New Week" }, { MUS::NEW_MONTH, "New Month" }, { MUS::ARCHIBALD_CAMPAIGN_SCREEN, "Archibald Campaign" }, { MUS::PUZZLE, "Map Puzzle" }, { MUS::ROLAND_CAMPAIGN_SCREEN, "Roland Campaign" }, { MUS::CARAVANS, "25" }, { MUS::CARAVANS_2, "26" }, { MUS::CARAVANS_3, "27" }, { MUS::COMPUTER_TURN, "AI Turn" }, { MUS::BATTLEWIN, "Battle Won" }, { MUS::BATTLELOSE, "Battle Lost" }, { MUS::DUNGEON, "Dungeon" }, { MUS::WATERSPRING, "Waterspring" }, { MUS::ARABIAN, "Arabian" }, { MUS::HILLFORT, "Hillfort" }, { MUS::TREEHOUSE, "Treehouse" }, { MUS::DEMONCAVE, "Demoncave" }, { MUS::EXPERIENCE, "Experience" }, { MUS::SKILL, "Skill" }, { MUS::WATCHTOWER, "Watchtower" }, { MUS::XANADU, "Xanadu" }, { MUS::ULTIMATE_ARTIFACT, "Ultimate Artifact" }, { MUS::MAINMENU, "Main Menu" }, { MUS::VICTORY, "Scenario Victory" }, { MUS::UNKNOWN, "UNKNOWN" } } }; } namespace MUS { std::string getFileName( const int musicTrackId, const ExternalMusicNamingScheme namingScheme, const char * fileExtension ) { assert( fileExtension != nullptr ); if ( musicTrackId <= UNUSED || musicTrackId > UNKNOWN ) { // You are passing an invalid music track ID! assert( 0 ); return {}; } if ( namingScheme == ExternalMusicNamingScheme::MAPPED ) { std::string output; addTrackId( output, musicTrackId ); output += ' '; output += musmap[musicTrackId].string; output += fileExtension; return output; } if ( namingScheme == ExternalMusicNamingScheme::DOS_VERSION ) { std::string output( "homm2_" ); // GOG version format, data track was ignored there so 02 becomes 01 addTrackId( output, musicTrackId - 1 ); output += fileExtension; return output; } if ( namingScheme == ExternalMusicNamingScheme::WIN_VERSION ) { std::string output( "Track" ); addTrackId( output, musicTrackId ); output += fileExtension; return output; } // Did you add a new type of music? assert( 0 ); return {}; } int FromGround( const int groundType ) { switch ( groundType ) { case Maps::Ground::DESERT: return DESERT; case Maps::Ground::SNOW: return SNOW; case Maps::Ground::SWAMP: return SWAMP; case Maps::Ground::WASTELAND: return WASTELAND; case Maps::Ground::BEACH: return OCEAN; case Maps::Ground::LAVA: return LAVA; case Maps::Ground::DIRT: return DIRT; case Maps::Ground::GRASS: return GRASS; case Maps::Ground::WATER: return OCEAN; default: // Did you add a new ground type? Add the track for it! assert( 0 ); break; } return UNKNOWN; } int FromRace( const int race ) { switch ( race ) { case Race::KNGT: return KNIGHT_CASTLE; case Race::BARB: return BARBARIAN_CASTLE; case Race::SORC: return SORCERESS_CASTLE; case Race::WRLK: return WARLOCK_CASTLE; case Race::WZRD: return WIZARD_CASTLE; case Race::NECR: return NECROMANCER_CASTLE; default: // Did you add a new race? Add an appropriate music theme for it! assert( 0 ); break; } return UNKNOWN; } int GetBattleRandom() { switch ( Rand::Get( 1, 3 ) ) { case 1: return BATTLE1; case 2: return BATTLE2; case 3: return BATTLE3; default: // How is it even possible? assert( 0 ); break; } return UNKNOWN; } } fheroes2-1.1.6+dfsg/src/fheroes2/agg/mus.h000066400000000000000000000061021476115357100202030ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2008 by Josh Matthews * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace MUS { enum MusicTrack : int { UNUSED, DATATRACK, // not in use BATTLE1, BATTLE2, BATTLE3, SORCERESS_CASTLE, WARLOCK_CASTLE, NECROMANCER_CASTLE, KNIGHT_CASTLE, BARBARIAN_CASTLE, WIZARD_CASTLE, LAVA, WASTELAND, DESERT, SNOW, SWAMP, OCEAN, DIRT, GRASS, LOSTGAME, NEW_WEEK, NEW_MONTH, ARCHIBALD_CAMPAIGN_SCREEN, PUZZLE, ROLAND_CAMPAIGN_SCREEN, CARAVANS, // not in use CARAVANS_2, // not in use CARAVANS_3, // not in use COMPUTER_TURN, BATTLEWIN, BATTLELOSE, DUNGEON, WATERSPRING, ARABIAN, HILLFORT, TREEHOUSE, DEMONCAVE, EXPERIENCE, SKILL, WATCHTOWER, XANADU, ULTIMATE_ARTIFACT, MAINMENU, VICTORY, // IMPORTANT!!! Put all new entries above this line. UNKNOWN }; enum class ExternalMusicNamingScheme : int { MAPPED, DOS_VERSION, WIN_VERSION }; std::string getFileName( const int musicTrackId, const ExternalMusicNamingScheme namingScheme, const char * fileExtension ); int FromGround( const int groundType ); int FromRace( const int race ); int GetBattleRandom(); } fheroes2-1.1.6+dfsg/src/fheroes2/agg/til.h000066400000000000000000000035451476115357100201770ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace TIL { enum { UNKNOWN, CLOF32, GROUND32, STON, // IMPORTANT! Put any new entry just above this one. LASTTIL }; } fheroes2-1.1.6+dfsg/src/fheroes2/agg/xmi.cpp000066400000000000000000000112521476115357100205310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2022 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "xmi.h" #include "mus.h" namespace XMI { const struct { int type; const char * string; } xmimap[] = { { UNKNOWN, "UNKNOWN" }, { MIDI0002, "MIDI0002.XMI" }, { MIDI0003, "MIDI0003.XMI" }, { MIDI0004, "MIDI0004.XMI" }, { MIDI0005, "MIDI0005.XMI" }, { MIDI0006, "MIDI0006.XMI" }, { MIDI0007, "MIDI0007.XMI" }, { MIDI0008, "MIDI0008.XMI" }, { MIDI0009, "MIDI0009.XMI" }, { MIDI0010, "MIDI0010.XMI" }, { MIDI0011, "MIDI0011.XMI" }, { MIDI0013, "MIDI0013.XMI" }, { MIDI0014, "MIDI0014.XMI" }, { MIDI0015, "MIDI0015.XMI" }, { MIDI0017, "MIDI0017.XMI" }, { MIDI0018, "MIDI0018.XMI" }, { MIDI0042, "MIDI0042.XMI" }, { MIDI0043, "MIDI0043.XMI" }, { MIDI_ORIGINAL_KNIGHT, "MIDI0009.XMI" }, // Knight theme was used by both Barbarian and Wizard castles, so we use either MIDI0009 or MIDI0010 { MIDI_ORIGINAL_BARBARIAN, "MIDI0007.XMI" }, // Barbarian intended theme is under MIDI0007 { MIDI_ORIGINAL_SORCERESS, "MIDI0005.XMI" }, // Sorceress doesn't have own track in OG release, Warlock theme was used { MIDI_ORIGINAL_WARLOCK, "MIDI0005.XMI" }, // Warlock theme was set to Sorceress so we use MIDI0005 { MIDI_ORIGINAL_WIZARD, "MIDI0008.XMI" }, // Wizard's and Knight's tracks were switched around, so we use MIDI0008 { MIDI_ORIGINAL_NECROMANCER, "MIDI0006.XMI" } // Necromancer theme has trickled down to Warlock so we use MIDI0006 }; } const char * XMI::GetString( int track ) { return UNKNOWN < track && MIDI_ORIGINAL_NECROMANCER >= track ? xmimap[track].string : xmimap[UNKNOWN].string; } // Due to a bug in Succession Wars/demo release (HEROES2.AGG) we have to remap original MIDI tracks to intended castles int XMI::FromMUS( int track, bool expansion ) { switch ( track ) { case MUS::BATTLE1: return MIDI0002; case MUS::BATTLE2: return MIDI0003; case MUS::BATTLE3: return MIDI0004; case MUS::SORCERESS_CASTLE: // Sorceress didn't have own XMI file in original release unfortunately return MIDI0005; case MUS::WARLOCK_CASTLE: return expansion ? MIDI0006 : MIDI_ORIGINAL_WARLOCK; case MUS::NECROMANCER_CASTLE: return expansion ? MIDI0007 : MIDI_ORIGINAL_NECROMANCER; case MUS::KNIGHT_CASTLE: return expansion ? MIDI0008 : MIDI_ORIGINAL_KNIGHT; case MUS::BARBARIAN_CASTLE: return expansion ? MIDI0009 : MIDI_ORIGINAL_BARBARIAN; case MUS::WIZARD_CASTLE: return expansion ? MIDI0010 : MIDI_ORIGINAL_WIZARD; case MUS::LAVA: return MIDI0011; case MUS::DESERT: return MIDI0013; case MUS::SNOW: return MIDI0014; case MUS::SWAMP: return MIDI0015; case MUS::DIRT: return MIDI0017; case MUS::GRASS: return MIDI0018; case MUS::MAINMENU: return MIDI0042; case MUS::VICTORY: return MIDI0043; default: break; } return UNKNOWN; } fheroes2-1.1.6+dfsg/src/fheroes2/agg/xmi.h000066400000000000000000000044601476115357100202010ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace XMI { enum { UNKNOWN, MIDI0002, MIDI0003, MIDI0004, MIDI0005, MIDI0006, MIDI0007, MIDI0008, MIDI0009, MIDI0010, MIDI0011, MIDI0013, MIDI0014, MIDI0015, MIDI0017, MIDI0018, MIDI0042, MIDI0043, MIDI_ORIGINAL_KNIGHT, MIDI_ORIGINAL_BARBARIAN, MIDI_ORIGINAL_SORCERESS, MIDI_ORIGINAL_WARLOCK, MIDI_ORIGINAL_WIZARD, MIDI_ORIGINAL_NECROMANCER }; const char * GetString( int track ); int FromMUS( int track, bool expansion ); } fheroes2-1.1.6+dfsg/src/fheroes2/ai/000077500000000000000000000000001476115357100170625ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_battle.cpp000066400000000000000000002522771476115357100215310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ai_battle.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "artifact.h" #include "artifact_info.h" #include "battle.h" #include "battle_arena.h" #include "battle_army.h" #include "battle_board.h" #include "battle_cell.h" #include "battle_command.h" #include "battle_tower.h" #include "battle_troop.h" #include "castle.h" #include "color.h" #include "difficulty.h" #include "game.h" #include "game_static.h" #include "heroes.h" #include "heroes_base.h" #include "kingdom.h" #include "logging.h" #include "monster_info.h" #include "resource.h" #include "settings.h" #include "skill.h" #include "speed.h" #include "spell.h" #include "spell_info.h" #include "spell_storage.h" namespace { const std::vector cellsUnderWallsIndexes = { 7, 28, 49, 72, 95 }; struct MeleeAttackOutcome { int32_t fromIndex = -1; double attackValue = INT32_MIN; double positionValue = INT32_MIN; bool canAttackImmediately = false; }; bool ValueHasImproved( double primary, double primaryMax, double secondary, double secondaryMax ) { return primaryMax < primary || ( secondaryMax < secondary && std::fabs( primaryMax - primary ) < 0.001 ); } bool IsOutcomeImproved( const MeleeAttackOutcome & newOutcome, const MeleeAttackOutcome & previous ) { // Composite priority criteria: // Primary - whether the enemy unit can be attacked during the current turn // Secondary - position value // Tertiary - enemy unit's threat return ( newOutcome.canAttackImmediately && !previous.canAttackImmediately ) || ( newOutcome.canAttackImmediately == previous.canAttackImmediately && ValueHasImproved( newOutcome.positionValue, previous.positionValue, newOutcome.attackValue, previous.attackValue ) ); } int32_t doubleCellAttackValue( const Battle::Unit & attacker, const Battle::Unit & target, const int32_t from, const int32_t targetCell ) { const Battle::Cell * behind = Battle::Board::GetCell( targetCell, Battle::Board::GetDirection( from, targetCell ) ); const Battle::Unit * secondaryTarget = ( behind != nullptr ) ? behind->GetUnit() : nullptr; if ( secondaryTarget && secondaryTarget->GetUID() != target.GetUID() && secondaryTarget->GetUID() != attacker.GetUID() ) { return secondaryTarget->evaluateThreatForUnit( attacker ); } return 0; } std::pair optimalAttackVector( const Battle::Unit & attacker, const Battle::Unit & target, const Battle::Position & attackPos ) { assert( attackPos.isValidForUnit( attacker ) ); assert( Battle::Board::CanAttackTargetFromPosition( attacker, target, attackPos.GetHead()->GetIndex() ) ); const Battle::Position & targetPos = target.GetPosition(); const std::array attackCells = { attackPos.GetHead(), attackPos.GetTail() }; const std::array targetCells = { targetPos.GetHead(), targetPos.GetTail() }; std::pair bestAttackVector{ -1, Battle::UNKNOWN }; double bestAttackValue = 0.0; for ( const Battle::Cell * attackCell : attackCells ) { if ( attackCell == nullptr ) { continue; } const int32_t attackCellIdx = attackCell->GetIndex(); if ( !Battle::Board::CanAttackFromCell( attacker, attackCellIdx ) ) { continue; } for ( const Battle::Cell * targetCell : targetCells ) { if ( targetCell == nullptr ) { continue; } const int32_t targetCellIdx = targetCell->GetIndex(); if ( !Battle::Board::isNearIndexes( attackCellIdx, targetCellIdx ) ) { continue; } if ( !attacker.isDoubleCellAttack() ) { return { targetCellIdx, Battle::Board::GetDirection( attackCellIdx, targetCellIdx ) }; } const double attackValue = doubleCellAttackValue( attacker, target, attackCellIdx, targetCellIdx ); if ( bestAttackVector.first == -1 || bestAttackValue < attackValue ) { bestAttackVector = { targetCellIdx, Battle::Board::GetDirection( attackCellIdx, targetCellIdx ) }; bestAttackValue = attackValue; } } } return bestAttackVector; } int32_t optimalAttackValue( const Battle::Unit & attacker, const Battle::Unit & target, const Battle::Position & attackPos ) { assert( attackPos.isValidForUnit( attacker ) ); if ( attacker.isAllAdjacentCellsAttack() ) { const Battle::Board * board = Battle::Arena::GetBoard(); std::set unitsUnderAttack; for ( const int32_t index : Battle::Board::GetAroundIndexes( attackPos ) ) { const Battle::Unit * unit = board->at( index ).GetUnit(); // Attacking unit can be under the influence of the Hypnotize spell if ( unit == nullptr || unit == &attacker || unit->GetColor() == attacker.GetCurrentColor() ) { continue; } unitsUnderAttack.insert( unit ); } return std::accumulate( unitsUnderAttack.begin(), unitsUnderAttack.end(), static_cast( 0 ), [&attacker]( const int32_t total, const Battle::Unit * unit ) { return total + unit->evaluateThreatForUnit( attacker ); } ); } int32_t attackValue = target.evaluateThreatForUnit( attacker ); // A double cell attack should only be considered if the attacker is actually able to attack the target from the given attack position. Otherwise, the attacker // can at least block the target if the target is a shooter, so this position can be valuable in any case. if ( attacker.isDoubleCellAttack() && Battle::Board::CanAttackTargetFromPosition( attacker, target, attackPos.GetHead()->GetIndex() ) ) { const auto [attackTargetIdx, attackDirection] = optimalAttackVector( attacker, target, attackPos ); assert( Battle::Board::isValidDirection( attackTargetIdx, Battle::Board::GetReflectDirection( attackDirection ) ) ); attackValue += doubleCellAttackValue( attacker, target, Battle::Board::GetIndexDirection( attackTargetIdx, Battle::Board::GetReflectDirection( attackDirection ) ), attackTargetIdx ); } return attackValue; } using PositionValues = std::map; PositionValues evaluatePotentialAttackPositions( Battle::Arena & arena, const Battle::Unit & attacker ) { // Attacking unit can be under the influence of the Hypnotize spell Battle::Units enemies( arena.getEnemyForce( attacker.GetCurrentColor() ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT, &attacker ); // For each position near enemy units, select the maximum attack value among neighboring enemy melee units, and then add the sum of the attack values of // neighboring enemy archers to encourage the use of attacking positions that block these archers std::sort( enemies.begin(), enemies.end(), []( const Battle::Unit * unit1, const Battle::Unit * unit2 ) { return !unit1->isArchers() && unit2->isArchers(); } ); PositionValues result; for ( const Battle::Unit * enemyUnit : enemies ) { assert( enemyUnit != nullptr && enemyUnit->isValid() ); std::set processedPositions; // Wide attacker can occupy positions from which it is able to block or attack several units at once, even if there are not one but two cells between // these units, e.g. like this: // // | | | |U| // | |A|A| | // |U| | | | // // It is necessary to correctly evaluate such a position as a position located "nearby" in relation to both units. for ( const int32_t idx : Battle::Board::GetDistanceIndexes( *enemyUnit, attacker.isWide() ? 2 : 1 ) ) { const Battle::Position pos = Battle::Position::GetPosition( attacker, idx ); if ( pos.GetHead() == nullptr ) { continue; } assert( pos.isValidForUnit( attacker ) ); const uint32_t dist = Battle::Board::GetDistance( pos, enemyUnit->GetPosition() ); assert( dist > 0 ); if ( dist != 1 ) { continue; } if ( !arena.isPositionReachable( attacker, pos, false ) ) { continue; } if ( const auto [dummy, inserted] = processedPositions.insert( pos ); !inserted ) { continue; } const int32_t attackValue = optimalAttackValue( attacker, *enemyUnit, pos ); if ( const auto [iter, inserted] = result.try_emplace( pos, attackValue ); !inserted ) { // If attacker is able to attack all adjacent cells, then the values of all units in adjacent cells (including archers) have already been taken into // account if ( attacker.isAllAdjacentCellsAttack() ) { assert( iter->second == attackValue ); } else if ( enemyUnit->isArchers() ) { iter->second += attackValue; } else { iter->second = std::max( iter->second, attackValue ); } } } } return result; } bool isUnitAbleToApproachPosition( const Battle::Unit * unit, const Battle::Position & pos ) { assert( unit != nullptr ); // Also consider the next turn, even if this unit has already acted during the current turn const uint32_t speed = unit->GetSpeed( false, true ); // Immovable unit is not taken into account, even if it is already near the given position if ( speed == Speed::STANDING ) { return false; } for ( const int32_t nearbyIdx : Battle::Board::GetAroundIndexes( pos ) ) { const Battle::Position nearbyPos = Battle::Position::GetReachable( *unit, nearbyIdx, speed ); if ( nearbyPos.GetHead() == nullptr ) { continue; } assert( nearbyPos.isValidForUnit( unit ) ); return true; } return false; } MeleeAttackOutcome BestAttackOutcome( const Battle::Unit & attacker, const Battle::Unit & defender, const PositionValues & valuesOfAttackPositions, const std::function & posFilter = {} ) { MeleeAttackOutcome bestOutcome; std::vector aroundDefender; aroundDefender.reserve( valuesOfAttackPositions.size() ); for ( const auto & [pos, dummy] : valuesOfAttackPositions ) { const uint32_t dist = Battle::Board::GetDistance( pos, defender.GetPosition() ); assert( dist > 0 ); if ( dist != 1 ) { continue; } aroundDefender.push_back( pos ); } // Prefer the positions closest to the current attacker's position std::sort( aroundDefender.begin(), aroundDefender.end(), [&attacker]( const Battle::Position & pos1, const Battle::Position & pos2 ) { return ( Battle::Board::GetDistance( attacker.GetPosition(), pos1 ) < Battle::Board::GetDistance( attacker.GetPosition(), pos2 ) ); } ); // Pick the best position to attack from for ( const Battle::Position & pos : aroundDefender ) { assert( pos.GetHead() != nullptr ); if ( posFilter && !posFilter( pos ) ) { continue; } const int32_t posHeadIdx = pos.GetHead()->GetIndex(); const auto posValueIter = valuesOfAttackPositions.find( pos ); assert( posValueIter != valuesOfAttackPositions.end() ); MeleeAttackOutcome current; current.attackValue = optimalAttackValue( attacker, defender, pos ); current.positionValue = posValueIter->second; current.canAttackImmediately = Battle::Board::CanAttackTargetFromPosition( attacker, defender, posHeadIdx ); // Pick target if either position has improved or unit is higher value at the same position value if ( IsOutcomeImproved( current, bestOutcome ) ) { bestOutcome.fromIndex = posHeadIdx; bestOutcome.attackValue = current.attackValue; bestOutcome.positionValue = current.positionValue; bestOutcome.canAttackImmediately = current.canAttackImmediately; } } return bestOutcome; } int32_t findOptimalPositionForSubsequentAttack( Battle::Arena & arena, const Battle::Indexes & path, const Battle::Unit & currentUnit, const Battle::Units & enemies ) { const Battle::Position & currentUnitPos = currentUnit.GetPosition(); std::vector> pathStepsThreatLevels; pathStepsThreatLevels.reserve( path.size() ); { Battle::Position stepPos = currentUnitPos; for ( const int32_t stepIdx : path ) { if ( currentUnit.isWide() ) { const Battle::Cell * stepPosTailCell = stepPos.GetTail(); assert( stepPosTailCell != nullptr ); // Reversal is not a movement if ( stepIdx == stepPosTailCell->GetIndex() ) { stepPos.Set( stepIdx, currentUnit.isWide(), !stepPos.isReflect() ); continue; } } stepPos.Set( stepIdx, currentUnit.isWide(), stepPos.isReflect() ); assert( arena.isPositionReachable( currentUnit, stepPos, true ) ); #ifdef NDEBUG (void)arena; #endif pathStepsThreatLevels.emplace_back( stepPos, 0.0 ); } } for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); // Archers and Flyers are always a threat if ( enemy->isFlying() || ( enemy->isArchers() && !enemy->isHandFighting() ) ) { continue; } for ( auto & [stepPos, stepThreatLevel] : pathStepsThreatLevels ) { if ( !isUnitAbleToApproachPosition( enemy, stepPos ) ) { continue; } // Rough estimate: the threat assessment is performed for the current position of the unit, not its new position at this step stepThreatLevel += enemy->evaluateThreatForUnit( currentUnit ); } } double lowestThreat = 0.0; int32_t targetIdx = -1; for ( const auto & [stepPos, stepThreatLevel] : pathStepsThreatLevels ) { // We need to get as close to the target as possible (taking into account the threat level) if ( targetIdx == -1 || stepThreatLevel < lowestThreat || std::fabs( stepThreatLevel - lowestThreat ) < 0.001 ) { assert( stepPos.isValidForUnit( currentUnit ) ); lowestThreat = stepThreatLevel; // When moving along the path, the direction of a wide unit at some steps may be reversed in relation to the target one. Detect this and use the proper // index. targetIdx = ( !currentUnit.isWide() || stepPos.isReflect() == currentUnitPos.isReflect() ) ? stepPos.GetHead()->GetIndex() : stepPos.GetTail()->GetIndex(); } } return targetIdx; } struct CellDistanceInfo { int32_t idx = -1; uint32_t dist = UINT32_MAX; }; CellDistanceInfo findNearestCellNextToUnit( Battle::Arena & arena, const Battle::Unit & currentUnit, const Battle::Unit & target ) { CellDistanceInfo result; for ( const int32_t idx : Battle::Board::GetDistanceIndexes( target, currentUnit.isWide() ? 2 : 1 ) ) { const Battle::Position pos = Battle::Position::GetPosition( currentUnit, idx ); if ( pos.GetHead() == nullptr ) { continue; } assert( pos.isValidForUnit( currentUnit ) ); const uint32_t dist = Battle::Board::GetDistance( pos, target.GetPosition() ); assert( dist > 0 ); if ( dist != 1 ) { continue; } if ( !arena.isPositionReachable( currentUnit, pos, false ) ) { continue; } const uint32_t moveDist = arena.CalculateMoveDistance( currentUnit, pos ); if ( result.idx == -1 || moveDist < result.dist ) { result = { idx, moveDist }; } } return result; } int32_t getUnitMovementTarget( Battle::Arena & arena, const Battle::Unit & currentUnit, const int32_t idx ) { // First try to find the position that is reachable on the current turn { const Battle::Position pos = Battle::Position::GetReachable( currentUnit, idx ); if ( pos.GetHead() != nullptr ) { assert( pos.isValidForUnit( currentUnit ) ); return pos.GetHead()->GetIndex(); } } // If there is no such position, then use the last position on the path to the cell with the specified index const Battle::Position dstPos = Battle::Position::GetPosition( currentUnit, idx ); assert( dstPos.isValidForUnit( currentUnit ) ); const Battle::Position pos = arena.getClosestReachablePosition( currentUnit, dstPos ); assert( pos.isValidForUnit( currentUnit ) ); return pos.GetHead()->GetIndex(); } bool isCommanderCanSpellcast( const Battle::Arena & arena, const HeroBase * commander ) { return commander && ( !commander->isControlHuman() || Settings::Get().BattleAutoSpellcast() ) && commander->HaveSpellBook() && !commander->Modes( Heroes::SPELLCASTED ) && !arena.isSpellcastDisabled(); } double commanderMaximumSpellDamageValue( const HeroBase & commander ) { double bestValue = 0; for ( const Spell & spell : commander.getAllSpells() ) { if ( !spell.isCombat() || !spell.isDamage() ) { continue; } if ( commander.GetSpellPoints() < spell.spellPoints() ) { continue; } bestValue = std::max( bestValue, static_cast( fheroes2::getSpellDamage( spell, commander.GetPower(), &commander ) ) ); } return bestValue; } Battle::Actions berserkTurn( Battle::Arena & arena, const Battle::Unit & currentUnit ) { assert( currentUnit.Modes( Battle::SP_BERSERKER ) ); Battle::Actions actions; Battle::Board * board = Battle::Arena::GetBoard(); assert( board != nullptr ); const uint32_t currentUnitUID = currentUnit.GetUID(); const std::vector nearestUnits = board->GetNearestTroops( ¤tUnit, {} ); assert( !nearestUnits.empty() ); // If the berserker is an archer, then just shoot at the nearest unit if ( currentUnit.isArchers() && !currentUnit.isHandFighting() ) { DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " under Berserk spell, will shoot" ) const Battle::Unit * targetUnit = nearestUnits.front(); assert( targetUnit != nullptr ); actions.emplace_back( Battle::Command::ATTACK, currentUnitUID, targetUnit->GetUID(), -1, -1, 0 ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " shooting at enemy " << targetUnit->GetName() ) return actions; } AI::BattleTargetPair targetInfo; // First, try to find a unit nearby that can be attacked on this turn for ( const Battle::Unit * nearbyUnit : nearestUnits ) { assert( nearbyUnit != nullptr ); const CellDistanceInfo nearestCellInfo = findNearestCellNextToUnit( arena, currentUnit, *nearbyUnit ); if ( nearestCellInfo.idx == -1 ) { continue; } if ( !Battle::Board::CanAttackTargetFromPosition( currentUnit, *nearbyUnit, nearestCellInfo.idx ) ) { continue; } targetInfo.cell = nearestCellInfo.idx; targetInfo.unit = nearbyUnit; break; } // If there is no unit to attack during this turn, then find the nearest one to try to attack it during subsequent turns if ( targetInfo.cell == -1 ) { for ( const Battle::Unit * nearbyUnit : nearestUnits ) { assert( nearbyUnit != nullptr ); const CellDistanceInfo nearestCellInfo = findNearestCellNextToUnit( arena, currentUnit, *nearbyUnit ); if ( nearestCellInfo.idx == -1 ) { continue; } targetInfo.cell = nearestCellInfo.idx; break; } } // There is no reachable unit in sight, skip the turn if ( targetInfo.cell == -1 ) { actions.emplace_back( Battle::Command::SKIP, currentUnitUID ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " skipping the turn" ) return actions; } DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " under Berserk spell, target cell: " << targetInfo.cell ) // The target cell of the movement must be the cell that the unit's head will occupy const int32_t moveTargetIdx = getUnitMovementTarget( arena, currentUnit, targetInfo.cell ); if ( targetInfo.unit ) { const Battle::Unit * targetUnit = targetInfo.unit; actions.emplace_back( Battle::Command::ATTACK, currentUnitUID, targetUnit->GetUID(), ( currentUnit.GetHeadIndex() == moveTargetIdx ? -1 : moveTargetIdx ), -1, -1 ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " attacking enemy " << targetUnit->GetName() << " from cell " << moveTargetIdx ) } else { actions.emplace_back( Battle::Command::MOVE, currentUnitUID, moveTargetIdx ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " moving to cell " << moveTargetIdx ) } return actions; } } AI::BattlePlanner & AI::BattlePlanner::Get() { static BattlePlanner ai; return ai; } void AI::BattlePlanner::battleBegins() { _currentTurnNumber = 0; _numberOfRemainingTurnsWithoutDeaths = MAX_TURNS_WITHOUT_DEATHS; _attackerForceNumberOfDead = 0; _defenderForceNumberOfDead = 0; } void AI::BattlePlanner::BattleTurn( Battle::Arena & arena, const Battle::Unit & currentUnit, Battle::Actions & actions ) { // Return immediately if our limit of turns has been exceeded if ( isLimitOfTurnsExceeded( arena, actions ) ) { return; } const Battle::Actions plannedActions = planUnitTurn( arena, currentUnit ); actions.insert( actions.end(), plannedActions.begin(), plannedActions.end() ); } bool AI::BattlePlanner::isLimitOfTurnsExceeded( const Battle::Arena & arena, Battle::Actions & actions ) { const int currentColor = arena.GetCurrentColor(); // Not the attacker's turn, no further checks if ( currentColor != arena.GetArmy1Color() ) { return false; } const uint32_t currentTurnNumber = arena.GetTurnNumber(); assert( currentTurnNumber > 0 ); // This is the beginning of a new turn and we still haven't gone beyond the limit on the number of turns without deaths if ( currentTurnNumber > _currentTurnNumber && _numberOfRemainingTurnsWithoutDeaths > 0 ) { auto prevNumbersOfDead = std::tie( _attackerForceNumberOfDead, _defenderForceNumberOfDead ); const auto currNumbersOfDead = std::make_tuple( arena.GetForce1().GetDeadCounts(), arena.GetForce2().GetDeadCounts() ); // Either we don't have numbers of dead units from the previous turn, or there were changes in these numbers compared // to the previous turn, reset the counter if ( _currentTurnNumber == 0 || currentTurnNumber - _currentTurnNumber != 1 || prevNumbersOfDead != currNumbersOfDead ) { prevNumbersOfDead = currNumbersOfDead; _numberOfRemainingTurnsWithoutDeaths = MAX_TURNS_WITHOUT_DEATHS; } // No changes in numbers of dead units compared to the previous turn, decrease the counter of the remaining turns else { _numberOfRemainingTurnsWithoutDeaths -= 1; } _currentTurnNumber = currentTurnNumber; } // We have gone beyond the limit on the number of turns without deaths and have to stop if ( _numberOfRemainingTurnsWithoutDeaths == 0 ) { // If this is an auto combat (and not a quick combat, because the battle UI is present), then turn it off until the end of the battle if ( arena.AutoCombatInProgress() && Battle::Arena::GetInterface() != nullptr ) { assert( arena.CanToggleAutoCombat() ); actions.emplace_back( Battle::Command::TOGGLE_AUTO_COMBAT, currentColor ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, Color::String( currentColor ) << " has used up the limit of turns without deaths, auto combat is turned off" ) } // Otherwise the attacker's hero should retreat else { assert( arena.CanRetreatOpponent( currentColor ) && arena.GetCurrentCommander() != nullptr ); actions.emplace_back( Battle::Command::RETREAT ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, Color::String( currentColor ) << " has used up the limit of turns without deaths, " << arena.GetCurrentCommander()->GetName() << " retreats" ) } return true; } return false; } Battle::Actions AI::BattlePlanner::planUnitTurn( Battle::Arena & arena, const Battle::Unit & currentUnit ) { if ( currentUnit.Modes( Battle::SP_BERSERKER ) ) { return berserkTurn( arena, currentUnit ); } Battle::Actions actions; // Step 1. Analyze current battle state and update variables analyzeBattleState( arena, currentUnit ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " begin the turn, color: " << Color::String( _myColor ) ) // Step 2. Check retreat/surrender condition const Heroes * actualHero = dynamic_cast( _commander ); if ( actualHero ) { enum class Outcome { ContinueBattle, Retreat, Surrender }; const Outcome outcome = [this, &arena, actualHero]() { if ( !_considerRetreat ) { return Outcome::ContinueBattle; } // Human-controlled heroes should not retreat or surrender during auto/quick combat if ( actualHero->isControlHuman() ) { return Outcome::ContinueBattle; } const int gameDifficulty = Game::getDifficulty(); // TODO: consider taking speed/turn order into account in the future if ( _myArmyStrength * Difficulty::getArmyStrengthRatioForAIRetreat( gameDifficulty ) >= _enemyArmyStrength ) { return Outcome::ContinueBattle; } const bool hasValuableArtifacts = [actualHero]() { const BagArtifacts & artifactsBag = actualHero->GetBagArtifacts(); return std::any_of( artifactsBag.begin(), artifactsBag.end(), []( const Artifact & art ) { const fheroes2::ArtifactData & artifactData = fheroes2::getArtifactData( art.GetID() ); return std::any_of( artifactData.bonuses.begin(), artifactData.bonuses.end(), []( const fheroes2::ArtifactBonus & bonus ) { return bonus.type != fheroes2::ArtifactBonusType::NONE; } ); } ); }(); const Kingdom & kingdom = actualHero->GetKingdom(); const bool isAbleToSurrender = [this, &arena, &kingdom]() { if ( !arena.CanSurrenderOpponent( _myColor ) ) { return false; } return kingdom.AllowPayment( { Resource::GOLD, arena.getForce( _myColor ).GetSurrenderCost() } ); }(); const bool isPossibleToReHire = [actualHero, &kingdom]() { // If the hero is not the last in his kingdom, then we will assume that there is a possibility of re-hiring - even if there are no castles in the // kingdom, one of the remaining heroes can capture an enemy castle const VecHeroes & heroes = kingdom.GetHeroes(); if ( heroes.size() > 1 ) { return true; } assert( heroes.size() == 1 && heroes.at( 0 ) == actualHero ); // Otherwise, if this hero is the last one, and there are no castles in the kingdom, then it will be impossible to re-hire this hero const VecCastles & castles = kingdom.GetCastles(); if ( castles.empty() ) { return false; } // Otherwise, if this hero is defending the last castle, then it will be impossible to re-hire this hero const Castle * castle = actualHero->inCastle(); if ( castle && castles.size() == 1 ) { assert( castles.at( 0 ) == castle ); return false; } // Otherwise, assume that there is a possibility of re-hiring return true; }(); const int minHeroTotalPrimarySkillLevelForRetreat = 10; if ( !arena.CanRetreatOpponent( _myColor ) ) { if ( !isAbleToSurrender ) { return Outcome::ContinueBattle; } // If the hero has valuable artifacts, he should surrender so that these artifacts do not end up at the disposal of the enemy, especially in the case // of an alliance war if ( hasValuableArtifacts ) { return Outcome::Surrender; } // Otherwise, if this hero cannot be rehired, then there is no point in surrendering if ( !isPossibleToReHire ) { return Outcome::ContinueBattle; } // Otherwise, if this hero is relatively experienced, then he should surrender so that he can be hired again later if ( actualHero->getTotalPrimarySkillLevel() >= minHeroTotalPrimarySkillLevelForRetreat ) { return Outcome::Surrender; } // Otherwise, there is no point in surrendering return Outcome::ContinueBattle; } // If the hero has valuable artifacts, he should retreat so that these artifacts do not end up at the disposal of the enemy, especially in the case of an // alliance war if ( hasValuableArtifacts ) { return Outcome::Retreat; } // Otherwise, if this hero cannot be rehired, then there is no point in retreating if ( !isPossibleToReHire ) { return Outcome::ContinueBattle; } // Otherwise, if this hero is relatively experienced, then he should retreat so that he can be hired again later if ( actualHero->getTotalPrimarySkillLevel() >= minHeroTotalPrimarySkillLevelForRetreat ) { return Outcome::Retreat; } // Otherwise, there is no point in retreating or surrendering return Outcome::ContinueBattle; }(); const auto farewellSpellcast = [this, &arena, ¤tUnit, &actions]() { if ( !isCommanderCanSpellcast( arena, _commander ) ) { return; } // Cast a spell with maximum damage const SpellSelection & bestSpell = selectBestSpell( arena, currentUnit, true ); if ( bestSpell.spellID == -1 ) { return; } actions.emplace_back( Battle::Command::SPELLCAST, bestSpell.spellID, bestSpell.cell ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, arena.GetCurrentCommander()->GetName() << " casts " << Spell( bestSpell.spellID ).GetName() << " on cell " << bestSpell.cell ) }; switch ( outcome ) { case Outcome::ContinueBattle: break; case Outcome::Retreat: farewellSpellcast(); actions.emplace_back( Battle::Command::RETREAT ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, arena.GetCurrentCommander()->GetName() << " retreats" ) return actions; case Outcome::Surrender: farewellSpellcast(); actions.emplace_back( Battle::Command::SURRENDER ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, arena.GetCurrentCommander()->GetName() << " surrenders" ) return actions; default: assert( 0 ); break; } } // Step 3. Calculate spell heuristics if ( isCommanderCanSpellcast( arena, _commander ) ) { const SpellSelection & bestSpell = selectBestSpell( arena, currentUnit, false ); if ( bestSpell.spellID != -1 ) { actions.emplace_back( Battle::Command::SPELLCAST, bestSpell.spellID, bestSpell.cell ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, arena.GetCurrentCommander()->GetName() << " casts " << Spell( bestSpell.spellID ).GetName() << " on cell " << bestSpell.cell ) return actions; } } // Step 4. Current unit decision tree const size_t actionsSize = actions.size(); if ( currentUnit.isArchers() ) { const Battle::Actions archerActions = archerDecision( arena, currentUnit ); actions.insert( actions.end(), archerActions.begin(), archerActions.end() ); } else { // Melee unit decision tree (both flyers and walkers) BattleTargetPair target; // Determine unit target or cell to move to if ( _defensiveTactics ) { target = meleeUnitDefense( arena, currentUnit ); } else { target = meleeUnitOffense( arena, currentUnit ); } // Melee unit final stage - add actions to the queue if ( target.cell != -1 ) { // The target cell of the movement must be the cell that the unit's head will occupy const int32_t moveTargetIdx = getUnitMovementTarget( arena, currentUnit, target.cell ); if ( target.unit ) { const Battle::Position attackPos = Battle::Position::GetReachable( currentUnit, moveTargetIdx ); assert( attackPos.isValidForUnit( currentUnit ) ); const auto [attackTargetIdx, attackDirection] = optimalAttackVector( currentUnit, *target.unit, attackPos ); actions.emplace_back( Battle::Command::ATTACK, currentUnit.GetUID(), target.unit->GetUID(), ( currentUnit.GetHeadIndex() == moveTargetIdx ? -1 : moveTargetIdx ), attackTargetIdx, attackDirection ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " attacking enemy " << target.unit->GetName() << " from cell " << moveTargetIdx << ", attack vector: " << Battle::Board::GetIndexDirection( attackTargetIdx, Battle::Board::GetReflectDirection( attackDirection ) ) << " -> " << attackTargetIdx << ", threat level: " << target.unit->evaluateThreatForUnit( currentUnit ) ) } else if ( currentUnit.GetHeadIndex() != moveTargetIdx ) { actions.emplace_back( Battle::Command::MOVE, currentUnit.GetUID(), moveTargetIdx ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " moving to cell " << moveTargetIdx ) } // Else skip the turn } // Else skip the turn } // No action was taken, skip the turn if ( actions.size() == actionsSize ) { actions.emplace_back( Battle::Command::SKIP, currentUnit.GetUID() ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " skipping the turn" ) } return actions; } void AI::BattlePlanner::analyzeBattleState( const Battle::Arena & arena, const Battle::Unit & currentUnit ) { _myColor = currentUnit.GetCurrentColor(); _commander = arena.getCommander( _myColor ); const Battle::Force & friendlyForce = arena.getForce( _myColor ); const Battle::Force & enemyForce = arena.getEnemyForce( _myColor ); // Friendly and enemy army analysis _myArmyStrength = 0; _enemyArmyStrength = 0; _myShootersStrength = 0; _enemyShootersStrength = 0; _myRangedUnitsOnly = 0; _enemyRangedUnitsOnly = 0; _myArmyAverageSpeed = 0; _enemyAverageSpeed = 0; _enemySpellStrength = 0; _attackingCastle = false; _defendingCastle = false; _considerRetreat = false; _defensiveTactics = false; _cautiousOffensive = false; if ( enemyForce.empty() ) { return; } double sumEnemyStr = 0.0; for ( const Battle::Unit * unit : enemyForce ) { assert( unit != nullptr ); if ( !unit->isValid() ) { continue; } const double unitStr = unit->GetStrength(); _enemyArmyStrength += unitStr; if ( unit->isArchers() && !unit->isImmovable() ) { _enemyRangedUnitsOnly += unitStr; } // The average speed is weighted by the troop strength _enemyAverageSpeed += unit->GetSpeed( false, true ) * unitStr; sumEnemyStr += unitStr; } _enemyShootersStrength = _enemyRangedUnitsOnly; if ( sumEnemyStr > 0.0 ) { _enemyAverageSpeed /= sumEnemyStr; } uint32_t initialUnitCount = 0; double sumArmyStr = 0.0; for ( const Battle::Unit * unit : friendlyForce ) { assert( unit != nullptr ); // Do not check isValid() here to handle dead troops const uint32_t count = unit->GetCount(); const uint32_t dead = unit->GetDead(); // Count all valid troops in army (both alive and dead) if ( count > 0 || dead > 0 ) { ++initialUnitCount; } const double unitStr = unit->GetStrength(); // The average speed is weighted by the troop strength _myArmyAverageSpeed += unit->GetSpeed( false, true ) * unitStr; sumArmyStr += unitStr; // Dead unit: trigger retreat condition and skip strength calculation if ( count == 0 && dead > 0 ) { _considerRetreat = true; continue; } _myArmyStrength += unitStr; if ( unit->isArchers() && !unit->isImmovable() ) { _myRangedUnitsOnly += unitStr; } } _myShootersStrength = _myRangedUnitsOnly; if ( sumArmyStr > 0.0 ) { _myArmyAverageSpeed /= sumArmyStr; } _considerRetreat = _considerRetreat || initialUnitCount < 4; // Add castle siege (and battle arena) modifiers const Castle * castle = Battle::Arena::GetCastle(); // Mark as castle siege only if any tower is present. If no towers present then nothing to defend and most likely all walls are destroyed as well. if ( castle && Battle::Arena::isAnyTowerPresent() ) { const bool attackerIgnoresCover = [&arena]() { const HeroBase * commander = arena.GetForce1().GetCommander(); assert( commander != nullptr ); if ( commander->GetBagArtifacts().isArtifactBonusPresent( fheroes2::ArtifactBonusType::NO_SHOOTING_PENALTY ) ) { return true; } if ( commander->GetLevelSkill( Skill::Secondary::ARCHERY ) != Skill::Level::NONE ) { return true; } return false; }(); const auto getTowerStrength = []( const Battle::Tower * tower ) { return ( tower && tower->isValid() ) ? tower->GetStrength() : 0; }; double towerStr = getTowerStrength( Battle::Arena::GetTower( Battle::TowerType::TWR_CENTER ) ); towerStr += getTowerStrength( Battle::Arena::GetTower( Battle::TowerType::TWR_LEFT ) ); towerStr += getTowerStrength( Battle::Arena::GetTower( Battle::TowerType::TWR_RIGHT ) ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Castle strength: " << towerStr ) // Tower strength can't be negative. If this assertion triggers something is wrong with the logic above. assert( towerStr >= 0 ); if ( _myColor == castle->GetColor() ) { _defendingCastle = true; _myShootersStrength += towerStr; if ( !attackerIgnoresCover ) { _enemyShootersStrength /= 1 + ( GameStatic::getCastleWallRangedPenalty() / 100.0 ); } } else { _attackingCastle = true; _enemyShootersStrength += towerStr; if ( !attackerIgnoresCover ) { _myShootersStrength /= 1 + ( GameStatic::getCastleWallRangedPenalty() / 100.0 ); } } } // Calculate each hero spell strength and add it to shooter values after castle modifiers were applied if ( _commander && _myShootersStrength > 1 ) { _myShootersStrength += commanderMaximumSpellDamageValue( *_commander ); } const HeroBase * enemyCommander = arena.getEnemyCommander( _myColor ); if ( enemyCommander ) { _enemySpellStrength = enemyCommander->GetMagicStrategicValue( _myArmyStrength ); _enemyShootersStrength += commanderMaximumSpellDamageValue( *enemyCommander ); } assert( _myArmyStrength > 0.0 && _enemyArmyStrength > 0.0 ); const double myArcherRatio = _myShootersStrength / _myArmyStrength; const double enemyArcherRatio = _enemyShootersStrength / _enemyArmyStrength; _defensiveTactics = [this, ¤tUnit, myArcherRatio, enemyArcherRatio]() { // Unit is already in the enemy half of the battlefield, just let it keep attacking if ( !isPositionLocatedInDefendedArea( currentUnit, currentUnit.GetPosition() ) ) { return false; } const double overPowerRatio = ( currentUnit.isFlying() ? 6 : 10 ); // When we have a X times stronger army than the enemy, then we are likely to win, there is no need to go on the defensive if ( _myArmyStrength > _enemyArmyStrength * overPowerRatio ) { return false; } // When we have fewer shooters than the enemy, it makes no sense to go on the defensive if ( _myShootersStrength < _enemyShootersStrength ) { return false; } // We have at least as many shooters as the enemy and we defend the castle under the protection of walls and towers, it makes sense to choose defensive // tactics if ( _defendingCastle ) { return true; } // If we have an unfavorable ratio of infantry and shooters for defense, then it is better to choose an offensive if ( myArcherRatio < 0.15 ) { return false; } // If the enemy has too many shooters, but not enough infantry to cover them, then it makes sense to choose an offensive if ( enemyArcherRatio > 0.66 ) { return false; } return true; }(); // If an offensive tactic is chosen, then this means that, most likely, the enemy has more shooters, which means that we should try to attack the enemy and // neutralize his shooters as quickly as possible. A cautious offensive tactics can be chosen only if our army is fighting an enemy army that has limited // distance attack capabilities. _cautiousOffensive = ( enemyArcherRatio < 0.15 ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, ( _defensiveTactics ? "Defensive" : ( _cautiousOffensive ? "Cautious offensive" : "Offensive" ) ) << " tactics have been chosen. Army strength: " << _myArmyStrength << ", shooters strength: " << _myShootersStrength << ", enemy army strength: " << _enemyArmyStrength << ", enemy shooters strength: " << _enemyShootersStrength ) } Battle::Actions AI::BattlePlanner::archerDecision( Battle::Arena & arena, const Battle::Unit & currentUnit ) const { Battle::Actions actions; // Current unit can be under the influence of the Hypnotize spell const Battle::Units enemies( arena.getEnemyForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT, ¤tUnit ); // Assess the current threat level and decide whether to retreat to another position const int32_t retreatPositionIndex = [&arena, ¤tUnit, &enemies]() { // There is no point in trying to retreat from flying units regardless of their speed if ( std::any_of( enemies.begin(), enemies.end(), []( const Battle::Unit * enemy ) { assert( enemy != nullptr ); return enemy->isFlying(); } ) ) { return -1; } struct PositionCharacteristics { // Indexes of the head cells of all enemy units that can potentially reach this position std::set threateningEnemiesIndexes; // Distance between this position and the nearest enemy unit uint32_t distanceToNearestEnemy{ UINT32_MAX }; }; const auto evaluatePotentialPositions = [¤tUnit, &enemies]( std::map & potentialPositions ) { class UnitRemover { public: explicit UnitRemover( const Battle::Unit & unitToRemove ) { const int32_t headIdx = unitToRemove.GetHeadIndex(); const int32_t tailIdx = unitToRemove.GetTailIndex(); assert( headIdx != -1 && ( unitToRemove.isWide() ? tailIdx != -1 : tailIdx == -1 ) ); unitToRestore = getUnitOnCell( headIdx ); assert( unitToRestore == &unitToRemove ); setUnitForCell( headIdx, nullptr ); if ( tailIdx != -1 ) { assert( unitToRestore == getUnitOnCell( tailIdx ) ); setUnitForCell( tailIdx, nullptr ); } } UnitRemover( const UnitRemover & ) = delete; ~UnitRemover() { assert( unitToRestore != nullptr ); const int32_t headIdx = unitToRestore->GetHeadIndex(); const int32_t tailIdx = unitToRestore->GetTailIndex(); assert( headIdx != -1 && ( unitToRestore->isWide() ? tailIdx != -1 : tailIdx == -1 ) ); setUnitForCell( headIdx, unitToRestore ); if ( tailIdx != -1 ) { setUnitForCell( tailIdx, unitToRestore ); } } UnitRemover & operator=( const UnitRemover & ) = delete; private: static Battle::Unit * getUnitOnCell( const int32_t idx ) { Battle::Cell * cell = Battle::Board::GetCell( idx ); assert( cell != nullptr ); return cell->GetUnit(); } static void setUnitForCell( const int32_t idx, Battle::Unit * unit ) { Battle::Cell * cell = Battle::Board::GetCell( idx ); assert( cell != nullptr ); cell->SetUnit( unit ); } Battle::Unit * unitToRestore = nullptr; }; // In order to correctly assess the safety of potential positions for the unit to be moved, we need // to temporarily remove this unit from the battlefield, otherwise, it can block the movement of enemy // units towards these new potential positions. const UnitRemover unitRemover( currentUnit ); for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); for ( auto & [position, characteristics] : potentialPositions ) { assert( position.GetHead() != nullptr ); const bool isPositionUnderEnemyThreat = [enemy]( const Battle::Position & pos ) { const uint32_t distanceToEnemy = Battle::Board::GetDistance( pos, enemy->GetPosition() ); assert( distanceToEnemy > 0 ); // Any position directly adjacent to an enemy (even an immovable one) is considered to be under // threat, because in such a position, archers will not be able to shoot if ( distanceToEnemy == 1 ) { return true; } // Archers who not blocked by enemy units generally threaten any position, but for the purpose // of this assessment, it is assumed that they threaten only in melee, that is, in positions // directly adjacent to them if ( enemy->isArchers() && !enemy->isHandFighting() ) { return false; } // The potential event of enemy's good morale is not taken into account here return isUnitAbleToApproachPosition( enemy, pos ); }( position ); if ( isPositionUnderEnemyThreat ) { characteristics.threateningEnemiesIndexes.insert( enemy->GetHeadIndex() ); } characteristics.distanceToNearestEnemy = std::min( characteristics.distanceToNearestEnemy, Battle::Board::GetDistance( position, enemy->GetPosition() ) ); assert( characteristics.distanceToNearestEnemy > 0 ); } } }; std::map potentialPositions; // The current position is also considered as a potential one potentialPositions.try_emplace( currentUnit.GetPosition() ); for ( const int32_t idx : arena.getAllAvailableMoves( currentUnit ) ) { potentialPositions.try_emplace( Battle::Position::GetReachable( currentUnit, idx ) ); } evaluatePotentialPositions( potentialPositions ); { const auto currentPositionIter = potentialPositions.find( currentUnit.GetPosition() ); assert( currentPositionIter != potentialPositions.end() ); const auto & [position, characteristics] = *currentPositionIter; // If the current position is not in danger, then nothing special should be done if ( characteristics.threateningEnemiesIndexes.empty() ) { return -1; } const uint32_t currentUnitSpeed = currentUnit.GetSpeed(); assert( currentUnitSpeed > Speed::STANDING ); // The current position is in danger, let's evaluate the possibility of a retreat const bool isItWorthTryingToRetreat = std::all_of( characteristics.threateningEnemiesIndexes.begin(), characteristics.threateningEnemiesIndexes.end(), [&arena, currentUnitSpeed]( const int32_t enemyIdx ) { const Battle::Unit * enemy = arena.GetTroopBoard( enemyIdx ); assert( enemy != nullptr && !enemy->isFlying() ); // Also consider the next turn, even if this unit has already acted during the current turn const uint32_t enemySpeed = enemy->GetSpeed( false, true ); // We can always retreat from an immovable enemy if ( enemySpeed == Speed::STANDING ) { return true; } // In order for it to make sense to try to retreat from the enemy, the enemy should be somewhat // slower return ( enemySpeed + 2 < currentUnitSpeed ); } ); if ( !isItWorthTryingToRetreat ) { return -1; } } // The current position is in danger, but there is an opportunity to retreat. Let's try to find a position to retreat. int32_t safestIdx = -1; // Distance to the nearest enemy unit (the more, the better) and inverse of the distance to the central cell of the battlefield (1/x, // i.e. the smaller the x the better). The idea is that corner cells should be avoided whenever possible when retreating because they // can easily be blocked by enemy units. std::pair safestParams{ 0, 0.0 }; for ( const auto & [position, characteristics] : potentialPositions ) { assert( position.GetHead() != nullptr && characteristics.distanceToNearestEnemy > 0 ); // Only completely safe positions are considered as candidates if ( !characteristics.threateningEnemiesIndexes.empty() ) { continue; } const int32_t idx = position.GetHead()->GetIndex(); const uint32_t distanceToBattlefieldCenter = Battle::Board::GetDistance( idx, Battle::Board::sizeInCells / 2 ); const auto idxParams = std::make_pair( characteristics.distanceToNearestEnemy, distanceToBattlefieldCenter == 0 ? 1.0 : 1.0 / distanceToBattlefieldCenter ); if ( safestParams < idxParams ) { safestIdx = idx; safestParams = idxParams; } } return safestIdx; }(); // The current position of the archers is not safe, but there is somewhere to retreat if ( retreatPositionIndex != -1 ) { DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " retreating from enemy, target cell: " << retreatPositionIndex ) // The target cell of the movement must be the cell that the unit's head will occupy const int32_t moveTargetIdx = getUnitMovementTarget( arena, currentUnit, retreatPositionIndex ); if ( currentUnit.GetHeadIndex() != moveTargetIdx ) { actions.emplace_back( Battle::Command::MOVE, currentUnit.GetUID(), moveTargetIdx ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " moving to cell " << moveTargetIdx ) } else { // It is impossible to "retreat" to the same position you are already in assert( 0 ); } } // Archers are blocked and there is nowhere to retreat, they are fighting in melee else if ( currentUnit.isHandFighting() ) { BattleTargetPair target; int32_t bestOutcome = INT32_MIN; for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); const uint32_t dist = Battle::Board::GetDistance( currentUnit.GetPosition(), enemy->GetPosition() ); assert( dist > 0 ); if ( dist != 1 ) { continue; } const int32_t archerMeleeDmg = [¤tUnit, enemy]() { if ( currentUnit.Modes( Battle::SP_CURSE ) ) { return currentUnit.CalculateMinDamage( *enemy ); } if ( currentUnit.Modes( Battle::SP_BLESS ) ) { return currentUnit.CalculateMaxDamage( *enemy ); } return ( currentUnit.CalculateMinDamage( *enemy ) + currentUnit.CalculateMaxDamage( *enemy ) ) / 2; }(); const int32_t retaliatoryDmg = enemy->EstimateRetaliatoryDamage( archerMeleeDmg ); const int32_t damageDiff = archerMeleeDmg - retaliatoryDmg; if ( bestOutcome < damageDiff ) { bestOutcome = damageDiff; target.unit = enemy; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Set melee attack priority on " << enemy->GetName() << ", value: " << damageDiff ) } } if ( target.unit ) { actions.emplace_back( Battle::Command::ATTACK, currentUnit.GetUID(), target.unit->GetUID(), -1, -1, -1 ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " attacking enemy " << target.unit->GetName() << " in melee, outcome: " << bestOutcome ) } } // Archers are able to shoot else { BattleTargetPair target; double highestPriority = INT32_MIN; for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); const auto updateBestTarget = [&target, &highestPriority, enemy]( const double priority, const int32_t targetIdx ) { if ( highestPriority < priority ) { highestPriority = priority; target.cell = targetIdx; target.unit = enemy; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Set shooting attack priority on " << enemy->GetName() << ", value: " << priority ) } }; if ( currentUnit.isAbilityPresent( fheroes2::MonsterAbilityType::AREA_SHOT ) ) { const auto calculateAreaShotAttackPriority = [&arena, ¤tUnit, enemy]( const int32_t targetIdx ) { double result = 0.0; // Indexes of the head cells of the units are used instead of pointers because the exact result of adding several // floating-point numbers may depend on the order of their addition, so the order of the elements must be deterministic. std::set affectedUnitsIndexes; affectedUnitsIndexes.insert( enemy->GetHeadIndex() ); for ( const int32_t cellIdx : Battle::Board::GetAroundIndexes( targetIdx ) ) { const Battle::Unit * unit = arena.GetTroopBoard( cellIdx ); if ( unit == nullptr ) { continue; } affectedUnitsIndexes.insert( unit->GetHeadIndex() ); } for ( const int32_t unitIdx : affectedUnitsIndexes ) { const Battle::Unit * unit = arena.GetTroopBoard( unitIdx ); assert( unit != nullptr ); result += unit->evaluateThreatForUnit( currentUnit ); } return result; }; const int32_t enemyHeadIdx = enemy->GetHeadIndex(); assert( enemyHeadIdx != -1 ); updateBestTarget( calculateAreaShotAttackPriority( enemyHeadIdx ), enemyHeadIdx ); if ( enemy->isWide() ) { const int32_t enemyTailIdx = enemy->GetTailIndex(); assert( enemyTailIdx != -1 ); updateBestTarget( calculateAreaShotAttackPriority( enemyTailIdx ), enemyTailIdx ); } continue; } updateBestTarget( enemy->evaluateThreatForUnit( currentUnit ), -1 ); } if ( target.unit ) { actions.emplace_back( Battle::Command::ATTACK, currentUnit.GetUID(), target.unit->GetUID(), -1, target.cell, 0 ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " shooting at enemy " << target.unit->GetName() << ", value: " << highestPriority ) } } return actions; } AI::BattleTargetPair AI::BattlePlanner::meleeUnitOffense( Battle::Arena & arena, const Battle::Unit & currentUnit ) const { BattleTargetPair target; const PositionValues valuesOfAttackPositions = evaluatePotentialAttackPositions( arena, currentUnit ); // Current unit can be under the influence of the Hypnotize spell const Battle::Units enemies( arena.getEnemyForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT, ¤tUnit ); // 1. Choose the best target within reach, if any { MeleeAttackOutcome bestOutcome; for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); const MeleeAttackOutcome outcome = BestAttackOutcome( currentUnit, *enemy, valuesOfAttackPositions ); if ( !outcome.canAttackImmediately ) { continue; } if ( IsOutcomeImproved( outcome, bestOutcome ) ) { bestOutcome = outcome; target.cell = outcome.fromIndex; target.unit = enemy; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Set attack priority on " << enemy->GetName() << ", attack value: " << outcome.attackValue << ", position value: " << outcome.positionValue ) } } if ( target.unit ) { DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " attacking " << target.unit->GetName() << " from cell " << target.cell ) return target; } } // 2. For units that don't have a target within reach, choose a target depending on distance-based priority { const auto chooseDistantTarget = [this, &arena, ¤tUnit, &target, &enemies]( const auto enemyPredicate ) { double maxPriority = std::numeric_limits::lowest(); for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); const CellDistanceInfo nearestCellInfo = findNearestCellNextToUnit( arena, currentUnit, *enemy ); if ( nearestCellInfo.idx == -1 ) { continue; } if ( !enemyPredicate( enemy ) ) { continue; } // If this distance was zero, it would mean that this enemy unit would have already been attacked by the current unit assert( nearestCellInfo.dist > 0 ); const double priority = static_cast( enemy->evaluateThreatForUnit( currentUnit ) ) / nearestCellInfo.dist; if ( priority < maxPriority ) { continue; } maxPriority = priority; const Battle::Position pos = Battle::Position::GetPosition( currentUnit, nearestCellInfo.idx ); assert( pos.isValidForUnit( currentUnit ) ); const Battle::Indexes path = arena.GetPath( currentUnit, pos ); assert( !path.empty() ); const Castle * castle = Battle::Arena::GetCastle(); const bool isMoatBuilt = castle && castle->isBuild( BUILD_MOAT ); // Unit rushes through the moat, step into the moat to get more freedom of action on the next turn if ( isMoatBuilt && Battle::Board::isMoatIndex( path.back(), currentUnit ) ) { target.cell = path.back(); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Going after target " << enemy->GetName() << ", stopping in the moat at cell " << target.cell ) } else if ( _cautiousOffensive ) { target.cell = findOptimalPositionForSubsequentAttack( arena, path, currentUnit, enemies ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Going after target " << enemy->GetName() << " using a cautious offensive, stopping at cell " << target.cell ) } else { target.cell = path.back(); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Going after target " << enemy->GetName() << ", stopping at cell " << target.cell ) } } }; // First, try to choose a target among the enemy units that will not be able to evade an engagement chooseDistantTarget( [¤tUnit]( const Battle::Unit * enemy ) { assert( enemy != nullptr ); // If the current unit was flying, then this enemy unit would have already been attacked by it assert( !currentUnit.isFlying() ); // Always try to get closer to the archers, even if they are faster, to try to block them more reliably in the future if ( enemy->isArchers() ) { return true; } const uint32_t enemySpeed = enemy->GetSpeed( false, true ); // If the enemy unit is immovable, then it will not be able to evade an engagement if ( enemySpeed == Speed::STANDING ) { return true; } // Flying unit, even inferior in speed, can move around the entire battlefield and easily evade an engagement if ( enemy->isFlying() ) { return false; } return enemySpeed < currentUnit.GetSpeed( false, true ); } ); if ( target.cell != -1 ) { return target; } // If there are no enemy units that could not evade an engagement, then try to choose a target among the enemy units that are reachable in principle chooseDistantTarget( []( const Battle::Unit * ) { return true; } ); if ( target.cell != -1 ) { return target; } } // 3. Try to get closer to the castle walls during the siege if ( _attackingCastle ) { uint32_t shortestDist = UINT32_MAX; for ( const int32_t cellIdx : cellsUnderWallsIndexes ) { const Battle::Position pos = Battle::Position::GetPosition( currentUnit, cellIdx ); if ( !arena.isPositionReachable( currentUnit, pos, false ) ) { continue; } assert( pos.isValidForUnit( currentUnit ) ); const uint32_t moveDist = arena.CalculateMoveDistance( currentUnit, pos ); if ( target.cell == -1 || moveDist < shortestDist ) { shortestDist = moveDist; target.cell = cellIdx; } } if ( target.cell != -1 ) { DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " moving towards castle walls, target cell: " << target.cell ) } } return target; } AI::BattleTargetPair AI::BattlePlanner::meleeUnitDefense( Battle::Arena & arena, const Battle::Unit & currentUnit ) const { BattleTargetPair target; const PositionValues valuesOfAttackPositions = evaluatePotentialAttackPositions( arena, currentUnit ); const Battle::Units friendly( arena.getForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT, ¤tUnit ); // Current unit can be under the influence of the Hypnotize spell const Battle::Units enemies( arena.getEnemyForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT, ¤tUnit ); // 1. Cover our archers and attack enemy units blocking them, if there are any. Units whose affiliation has been changed should not cover the archers, because // such units will block them instead of covering them. if ( currentUnit.GetArmyColor() == _myColor ) { const bool isAnyEnemyCanBeAttackedImmediately = std::any_of( enemies.begin(), enemies.end(), [¤tUnit, &valuesOfAttackPositions]( const Battle::Unit * enemy ) { assert( enemy != nullptr ); const MeleeAttackOutcome outcome = BestAttackOutcome( currentUnit, *enemy, valuesOfAttackPositions ); return outcome.canAttackImmediately; } ); // If the army has only one stack of archers, then there is no question about which stack to cover. If the army has three or more stacks of archers, then, // most likely, melee units will be able to cover these stacks only partially. In the case of two stacks of archers, the question arises: in which cases we // should try to cover both stacks, but partially, and in which cases we should cover just one stack, but completely. // // In the current implementation, if the value of one of these archer stacks is 2 or more times greater than the value of the other, then it is worth using // all melee units to create a more reliable cover for more powerful stack of archers. // // In the case of two stacks of archers, AI will tend to initially place them on the edges of the battlefield. Thus, for melee units, the maximum distance to // the stack of archers will be approximately 5 tiles. To fulfill the above condition, a distance of 5 tiles should give a penalty of 1/3 of the total value // of the archer stacks. // // For example, suppose we have one stack of archers with the value of 200 on the tile with the index of 0, and another stack of archers with the value of 100 // on the tile with the index of 88. In this case, a melee unit from the tile with the index of 66 should overcome about 5 tiles in order to reach the more // powerful stack of archers, but it should overcome just 1 tile to reach the less powerful stack. The penalty for each tile passed in its case will be // calculated as (200 + 100) / 15 = 20, and after the penalty is applied, the value of the more powerful stack of archers will be 200 - 20 * 5 = 100, and the // value of the less powerful stack will be 100 - 20 * 1 = 80, therefore, this melee unit will go to cover the more powerful stack of archers. // // However, if the strength of the archer stacks is comparable, for example, 150 vs 100, the penalty for each tile passed will be (150 + 100) / 15 = 16.66, // and after the penalty is applied, the value of the more powerful stack of archers will be 150 - 16.66 * 5 = 66,7, and the value of the less powerful stack // will be 100 - 16.66 * 1 = 83.34, therefore, this melee unit will go to cover the less powerful stack of archers, and both stacks will be only partially // covered. const double defenseDistanceModifier = _myRangedUnitsOnly / 15.0; double bestArcherValue = std::numeric_limits::lowest(); for ( const Battle::Unit * frnd : friendly ) { assert( frnd != nullptr ); if ( !frnd->isArchers() ) { continue; } const CellDistanceInfo bestCoverCellInfo = [&arena, ¤tUnit, frnd]() -> CellDistanceInfo { const Battle::Indexes nearbyIndexes = [¤tUnit, frnd]() { Battle::Indexes result; result.reserve( 8 ); const std::array priorityDirections = [¤tUnit, frnd]() -> std::array { const bool preferToCoverFromTheSide = [¤tUnit, frnd]() { // If the covering unit is not a wide unit, then using this unit to cover the shooter from the side does not give any advantage if ( !currentUnit.isWide() ) { return false; } // It is always better to use wide units to cover wide shooters from the sides if ( frnd->isWide() ) { return true; } assert( Battle::Board::isValidIndex( frnd->GetHeadIndex() ) ); // If an ordinary shooter is located on a tile that protrudes sideways, then using a wide unit to cover this shooter from the side does // not give any advantage if ( frnd->isReflect() ) { return ( ( frnd->GetHeadIndex() / Battle::Board::widthInCells ) % 2 == 1 ); } return ( ( frnd->GetHeadIndex() / Battle::Board::widthInCells ) % 2 == 0 ); }(); if ( preferToCoverFromTheSide ) { if ( frnd->isReflect() ) { return { Battle::TOP_LEFT, Battle::BOTTOM_LEFT, Battle::LEFT, Battle::TOP_RIGHT, Battle::BOTTOM_RIGHT, Battle::RIGHT }; } return { Battle::TOP_RIGHT, Battle::BOTTOM_RIGHT, Battle::RIGHT, Battle::TOP_LEFT, Battle::BOTTOM_LEFT, Battle::LEFT }; } if ( frnd->isReflect() ) { return { Battle::LEFT, Battle::TOP_LEFT, Battle::BOTTOM_LEFT, Battle::TOP_RIGHT, Battle::BOTTOM_RIGHT, Battle::RIGHT }; } return { Battle::RIGHT, Battle::TOP_RIGHT, Battle::BOTTOM_RIGHT, Battle::TOP_LEFT, Battle::BOTTOM_LEFT, Battle::LEFT }; }(); for ( const int32_t idx : std::array{ frnd->GetHeadIndex(), frnd->GetTailIndex() } ) { if ( !Battle::Board::isValidIndex( idx ) ) { continue; } for ( const int dir : priorityDirections ) { if ( !Battle::Board::isValidDirection( idx, dir ) ) { continue; } const int32_t nearbyIdx = Battle::Board::GetIndexDirection( idx, dir ); if ( std::find( result.begin(), result.end(), nearbyIdx ) != result.end() ) { continue; } result.push_back( nearbyIdx ); } } return result; }(); for ( const int32_t idx : nearbyIndexes ) { const Battle::Position pos = Battle::Position::GetPosition( currentUnit, idx ); if ( pos.GetHead() == nullptr ) { continue; } assert( pos.isValidForUnit( currentUnit ) ); assert( Battle::Board::GetDistance( pos, frnd->GetPosition() ) == 1 ); if ( !arena.isPositionReachable( currentUnit, pos, false ) ) { continue; } return { idx, arena.CalculateMoveDistance( currentUnit, pos ) }; } return {}; }(); const std::vector adjacentEnemies = [&enemies, frnd]() { std::vector result; result.reserve( enemies.size() ); for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); const uint32_t dist = Battle::Board::GetDistance( frnd->GetPosition(), enemy->GetPosition() ); assert( dist > 0 ); if ( dist != 1 ) { continue; } result.push_back( enemy ); } return result; }(); // If our archer is not blocked by enemy units, but the unit nevertheless cannot cover that archer, then ignore that archer if ( bestCoverCellInfo.idx == -1 && adjacentEnemies.empty() ) { continue; } // Either the unit can cover the friendly archer, or the archer is blocked by enemy units, which do not allow our unit to approach. As the distance to // estimate the archer's value, we take the smallest of the distance that must be overcome to cover the archer and the distance that must be overcome to // approach the nearest of the enemies blocking him. const auto [eitherFrndOrAdjEnemyIsReachable, dist] = [&arena, ¤tUnit, &bestCoverCellInfo, &adjacentEnemies]() { std::pair result{ bestCoverCellInfo.idx != -1, bestCoverCellInfo.dist }; for ( const Battle::Unit * enemy : adjacentEnemies ) { assert( enemy != nullptr ); const CellDistanceInfo nearestToEnemyCellInfo = findNearestCellNextToUnit( arena, currentUnit, *enemy ); if ( nearestToEnemyCellInfo.idx == -1 ) { continue; } if ( !result.first || nearestToEnemyCellInfo.dist < result.second ) { result = { true, nearestToEnemyCellInfo.dist }; } } return result; }(); // If the unit cannot cover the archer or approach any of the enemies blocking that archer, then ignore that archer if ( !eitherFrndOrAdjEnemyIsReachable ) { continue; } // If the unit cannot cover the archer or approach any of the enemies blocking that archer within two turns (according to a rough estimate), but there is // at least one enemy unit that can be immediately attacked by this unit, then ignore that archer. Very slow units (such as Hydra) should not waste time // covering archers far from them - especially if there are other enemy units nearby worthy of their attention. if ( isAnyEnemyCanBeAttackedImmediately && !currentUnit.isFlying() && dist > currentUnit.GetSpeed() * 2 ) { continue; } const double archerValue = frnd->GetStrength() - dist * defenseDistanceModifier; if ( archerValue < bestArcherValue ) { continue; } bestArcherValue = archerValue; target.cell = bestCoverCellInfo.idx; target.unit = nullptr; // If the archer is blocked by enemy units, it is necessary to attack them immediately, or at least take the best position to attack { MeleeAttackOutcome bestOutcome; for ( const Battle::Unit * enemy : adjacentEnemies ) { assert( enemy != nullptr ); const MeleeAttackOutcome outcome = BestAttackOutcome( currentUnit, *enemy, valuesOfAttackPositions ); if ( IsOutcomeImproved( outcome, bestOutcome ) ) { bestOutcome = outcome; target.cell = outcome.fromIndex; target.unit = outcome.canAttackImmediately ? enemy : nullptr; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Set attack priority on " << enemy->GetName() << ", attack value: " << outcome.attackValue << ", position value: " << outcome.positionValue ) } } } // If we have reached this point, then the unit should be able to either cover the archer or approach any of the enemies blocking that archer - although // perhaps without performing an immediate attack assert( Battle::Board::isValidIndex( target.cell ) ); // The unit is going to attack one of the enemy units that blocked the archer, nothing else needs to be done if ( target.unit != nullptr ) { continue; } // It makes sense for a unit that ignores retaliation to attack neighboring enemy units, even if it is covering an archer, since in this case it will not // receive unnecessary retaliatory damage (which could affect the duration of the cover). Also, archers with the ability to shoot at area may not always // attack enemy units in close proximity to friendly units due to fear of friendly fire, so covering friendly units should help by attacking enemy units // next to them. if ( !currentUnit.isIgnoringRetaliation() && !frnd->isAbilityPresent( fheroes2::MonsterAbilityType::AREA_SHOT ) ) { continue; } // If the decision is made to attack one of the neighboring enemy units (if any) while covering the archer, then we should choose the best target { int32_t bestAttackValue = 0; for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); if ( !Battle::Board::CanAttackTargetFromPosition( currentUnit, *enemy, target.cell ) ) { continue; } const Battle::Position pos = Battle::Position::GetReachable( currentUnit, target.cell ); assert( pos.isValidForUnit( currentUnit ) ); const int32_t attackValue = optimalAttackValue( currentUnit, *enemy, pos ); if ( bestAttackValue < attackValue ) { bestAttackValue = attackValue; target.unit = enemy; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Set attack priority on " << enemy->GetName() << ", attack value: " << attackValue ) } } } } } if ( target.cell != -1 ) { if ( target.unit ) { DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " attacking " << target.unit->GetName() << " from cell " << target.cell ) } else { DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " covering friendly archers, moving to cell " << target.cell ) } return target; } // 2. Otherwise, try to find a suitable target that can be attacked from our half of the battlefield { MeleeAttackOutcome bestOutcome; for ( const Battle::Unit * enemy : enemies ) { assert( enemy != nullptr ); const MeleeAttackOutcome outcome = BestAttackOutcome( currentUnit, *enemy, valuesOfAttackPositions, [this, ¤tUnit]( const Battle::Position & pos ) { return isPositionLocatedInDefendedArea( currentUnit, pos ); } ); if ( !Battle::Board::isValidIndex( outcome.fromIndex ) ) { continue; } if ( IsOutcomeImproved( outcome, bestOutcome ) ) { bestOutcome = outcome; target.cell = outcome.fromIndex; target.unit = outcome.canAttackImmediately ? enemy : nullptr; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "- Set attack priority on " << enemy->GetName() << ", attack value: " << outcome.attackValue << ", position value: " << outcome.positionValue ) } } if ( target.unit ) { DEBUG_LOG( DBG_BATTLE, DBG_INFO, currentUnit.GetName() << " attacking " << target.unit->GetName() << " from cell " << target.cell ) } } return target; } bool AI::BattlePlanner::isPositionLocatedInDefendedArea( const Battle::Unit & currentUnit, const Battle::Position & pos ) const { assert( pos.isReflect() == currentUnit.GetPosition().isReflect() && pos.GetHead() != nullptr ); // Units whose affiliation has been changed are still looking in the direction they originally looked const bool reflect = ( currentUnit.GetArmyColor() == _myColor ? currentUnit.isReflect() : !currentUnit.isReflect() ); const auto checkIdx = [this, reflect]( const int32_t idx ) { if ( _defendingCastle ) { return Battle::Board::isCastleIndex( idx ); } return ( Battle::Board::GetDistanceFromBoardEdgeAlongXAxis( idx, reflect ) <= Battle::Board::widthInCells / 2 ); }; if ( !checkIdx( pos.GetHead()->GetIndex() ) ) { return false; } if ( pos.GetTail() && !checkIdx( pos.GetTail()->GetIndex() ) ) { return false; } return true; } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_battle.h000066400000000000000000000137551476115357100211720ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "color.h" class HeroBase; class Spell; namespace Battle { class Actions; class Arena; class Position; class Unit; class Units; } namespace AI { struct BattleTargetPair { int cell = -1; const Battle::Unit * unit = nullptr; }; struct SpellSelection { int spellID = -1; int32_t cell = -1; double value = 0.0; }; struct SpellcastOutcome { int32_t cell = -1; double value = 0.0; void updateOutcome( const double potentialValue, const int32_t targetCell, const bool isMassEffect = false ) { if ( isMassEffect ) { value += potentialValue; } else if ( potentialValue > value ) { value = potentialValue; cell = targetCell; } } }; class BattlePlanner { public: static BattlePlanner & Get(); // Should be called at the beginning of the battle void battleBegins(); void BattleTurn( Battle::Arena & arena, const Battle::Unit & currentUnit, Battle::Actions & actions ); private: BattlePlanner() = default; // Checks whether the limit of turns is exceeded for the attacking AI-controlled // hero and inserts an appropriate action to the action list if necessary bool isLimitOfTurnsExceeded( const Battle::Arena & arena, Battle::Actions & actions ); Battle::Actions planUnitTurn( Battle::Arena & arena, const Battle::Unit & currentUnit ); void analyzeBattleState( const Battle::Arena & arena, const Battle::Unit & currentUnit ); Battle::Actions archerDecision( Battle::Arena & arena, const Battle::Unit & currentUnit ) const; BattleTargetPair meleeUnitOffense( Battle::Arena & arena, const Battle::Unit & currentUnit ) const; BattleTargetPair meleeUnitDefense( Battle::Arena & arena, const Battle::Unit & currentUnit ) const; bool isPositionLocatedInDefendedArea( const Battle::Unit & currentUnit, const Battle::Position & pos ) const; SpellSelection selectBestSpell( Battle::Arena & arena, const Battle::Unit & currentUnit, bool retreating ) const; SpellcastOutcome spellDamageValue( const Spell & spell, Battle::Arena & arena, const Battle::Unit & currentUnit, const Battle::Units & friendly, const Battle::Units & enemies, bool retreating ) const; SpellcastOutcome spellDispelValue( const Spell & spell, const Battle::Units & friendly, const Battle::Units & enemies ) const; SpellcastOutcome spellResurrectValue( const Spell & spell, const Battle::Arena & arena ) const; SpellcastOutcome spellSummonValue( const Spell & spell, const Battle::Arena & arena, const int heroColor ) const; SpellcastOutcome spellEffectValue( const Spell & spell, const Battle::Units & targets ) const; double spellEffectValue( const Spell & spell, const Battle::Unit & target, bool targetIsLast, bool forDispel ) const; double getSpellDisruptingRayRatio( const Battle::Unit & target ) const; double getSpellSlowRatio( const Battle::Unit & target ) const; double getSpellHasteRatio( const Battle::Unit & target ) const; int32_t spellDurationMultiplier( const Battle::Unit & target ) const; // When this limit of turns without deaths is exceeded for an attacking AI-controlled hero, // the auto combat should be interrupted (one way or another) static const uint32_t MAX_TURNS_WITHOUT_DEATHS = 50; // Member variables related to the logic of checking the limit of the number of turns uint32_t _currentTurnNumber = 0; uint32_t _numberOfRemainingTurnsWithoutDeaths = MAX_TURNS_WITHOUT_DEATHS; uint32_t _attackerForceNumberOfDead = 0; uint32_t _defenderForceNumberOfDead = 0; // Member variables with a lifetime in one turn const HeroBase * _commander = nullptr; int _myColor = Color::NONE; double _myArmyStrength = 0; double _enemyArmyStrength = 0; double _myShootersStrength = 0; double _enemyShootersStrength = 0; double _myRangedUnitsOnly = 0; double _enemyRangedUnitsOnly = 0; double _myArmyAverageSpeed = 0; double _enemyAverageSpeed = 0; double _enemySpellStrength = 0; bool _attackingCastle = false; bool _defendingCastle = false; bool _considerRetreat = false; bool _defensiveTactics = false; bool _cautiousOffensive = false; }; } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_battle_spell.cpp000066400000000000000000000603471476115357100227230ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include "ai_battle.h" // IWYU pragma: associated #include "army_troop.h" #include "artifact.h" #include "artifact_info.h" #include "battle.h" #include "battle_arena.h" #include "battle_army.h" #include "battle_board.h" #include "battle_cell.h" #include "battle_troop.h" #include "heroes_base.h" #include "logging.h" #include "monster.h" #include "speed.h" #include "spell.h" #include "spell_info.h" #include "spell_storage.h" namespace { const double antimagicLowLimit = 200.0; double ReduceEffectivenessByDistance( const Battle::Unit & unit ) { // Reduce spell effectiveness if unit already crossed the battlefield const uint32_t result = Battle::Board::GetDistanceFromBoardEdgeAlongXAxis( unit.GetHeadIndex(), unit.isReflect() ); assert( result > 0 ); return result; } bool isSpellcastUselessForUnit( const Battle::Unit & unit, const Spell & spell ) { const int spellID = spell.GetID(); if ( unit.isImmovable() && spellID != Spell::ANTIMAGIC ) { return true; } switch ( spellID ) { case Spell::BLESS: case Spell::MASSBLESS: return unit.Modes( Battle::SP_BLESS ); case Spell::BLOODLUST: return unit.Modes( Battle::SP_BLOODLUST ); case Spell::CURSE: case Spell::MASSCURSE: return unit.Modes( Battle::SP_CURSE ); case Spell::HASTE: case Spell::MASSHASTE: return unit.Modes( Battle::SP_HASTE ); case Spell::SHIELD: case Spell::MASSSHIELD: return unit.Modes( Battle::SP_SHIELD ); case Spell::SLOW: case Spell::MASSSLOW: return unit.Modes( Battle::SP_SLOW ); case Spell::STONESKIN: case Spell::STEELSKIN: return unit.Modes( Battle::SP_STONESKIN | Battle::SP_STEELSKIN ); case Spell::BLIND: case Spell::PARALYZE: case Spell::PETRIFY: return unit.Modes( Battle::SP_BLIND | Battle::SP_PARALYZE | Battle::SP_STONE ); case Spell::DRAGONSLAYER: return unit.Modes( Battle::SP_DRAGONSLAYER ); case Spell::ANTIMAGIC: return unit.Modes( Battle::SP_ANTIMAGIC ); case Spell::BERSERKER: return unit.Modes( Battle::SP_BERSERKER ); case Spell::HYPNOTIZE: return unit.Modes( Battle::SP_HYPNOTIZE ); case Spell::MIRRORIMAGE: return unit.Modes( Battle::CAP_MIRROROWNER ); case Spell::DISRUPTINGRAY: return unit.GetDefense() < spell.ExtraValue(); default: break; } return false; } } AI::SpellSelection AI::BattlePlanner::selectBestSpell( Battle::Arena & arena, const Battle::Unit & currentUnit, bool retreating ) const { SpellSelection bestSpell; if ( _commander == nullptr ) { assert( 0 ); return bestSpell; } const SpellStorage allSpells = _commander->getAllSpells(); const Battle::Units friendly( arena.getForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS ); const Battle::Units enemies( arena.getEnemyForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS ); const Battle::Units trueFriendly( arena.getForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS_AND_UNITS_THAT_CHANGED_SIDES ); const Battle::Units trueEnemies( arena.getEnemyForce( _myColor ).getUnits(), Battle::Units::REMOVE_INVALID_UNITS_AND_UNITS_THAT_CHANGED_SIDES ); // Hero should conserve spellpoints if already spent more than half or his army is stronger // Threshold is 0.04 when armies are equal (= 20% of single unit) double spellValueThreshold = _myArmyStrength * _myArmyStrength / _enemyArmyStrength * 0.04; if ( _enemyShootersStrength / _enemyArmyStrength > 0.5 ) { spellValueThreshold *= 0.5; } if ( _commander->GetSpellPoints() * 2 < _commander->GetMaxSpellPoints() ) { spellValueThreshold *= 2; } const auto checkSelectBestSpell = [this, retreating, spellValueThreshold, &bestSpell]( const Spell & spell, const SpellcastOutcome & outcome ) { // Diminish spell effectiveness based on spell point cost // 1. Divide cost by 3 to make level 1 spells a baseline (1:1) // 2. Use square root to make sure relationship isn't linear for high-level spells const double spellPointValue = retreating ? outcome.value : outcome.value / sqrt( spell.spellPoints( _commander ) / 3.0 ); const bool ignoreThreshold = retreating || spell.isResurrect(); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, spell.GetName() << " value is " << spellPointValue << ", best target is " << outcome.cell ) if ( spellPointValue > bestSpell.value && ( ignoreThreshold || spellPointValue > spellValueThreshold ) ) { bestSpell.spellID = spell.GetID(); bestSpell.cell = outcome.cell; bestSpell.value = spellPointValue; } }; for ( const Spell & spell : allSpells ) { if ( !spell.isCombat() || arena.isDisableCastSpell( spell ) || !_commander->CanCastSpell( spell ) || ( retreating && !spell.isDamage() ) ) { continue; } if ( spell.isDamage() ) { checkSelectBestSpell( spell, spellDamageValue( spell, arena, currentUnit, friendly, enemies, retreating ) ); } else if ( spell.isEffectDispel() ) { checkSelectBestSpell( spell, spellDispelValue( spell, friendly, enemies ) ); } else if ( spell.isSummon() ) { checkSelectBestSpell( spell, spellSummonValue( spell, arena, _commander->GetColor() ) ); } else if ( spell.isResurrect() ) { checkSelectBestSpell( spell, spellResurrectValue( spell, arena ) ); } else if ( spell.isApplyToFriends() ) { checkSelectBestSpell( spell, spellEffectValue( spell, trueFriendly ) ); } else if ( spell.isApplyToEnemies() ) { checkSelectBestSpell( spell, spellEffectValue( spell, trueEnemies ) ); } } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "Spell threshold is " << spellValueThreshold << ", unit ratio is " << ( spellValueThreshold * 5 / _myArmyStrength ) ) if ( bestSpell.spellID != -1 ) { DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "Best spell is " << Spell( bestSpell.spellID ).GetName() << ", value is " << bestSpell.value ) } return bestSpell; } AI::SpellcastOutcome AI::BattlePlanner::spellDamageValue( const Spell & spell, Battle::Arena & arena, const Battle::Unit & currentUnit, const Battle::Units & friendly, const Battle::Units & enemies, bool retreating ) const { if ( !spell.isDamage() ) { return {}; } const uint32_t spellDamage = fheroes2::getSpellDamage( spell, _commander->GetPower(), _commander ); const auto damageHeuristic = [this, spellDamage, &spell, retreating]( const Battle::Unit * unit, const double armyStrength, const double armySpeed ) { const uint32_t damage = spellDamage * ( 100 - unit->GetMagicResist( spell, _commander ) ) / 100; // If the unit is immune to this spell, then no one will be killed, no strength will be lost and the unit will not be woken up if it is disabled if ( damage == 0 ) { return 0.0; } // If we retreat, we are not interested in partial damage, but only in the number of units actually killed if ( retreating ) { return unit->GetMonsterStrength() * unit->HowManyWillBeKilled( damage ); } // If the unit will be completely destroyed, then use its full strength plus a bonus for destroying the stack const uint32_t hitpoints = unit->Modes( Battle::CAP_MIRRORIMAGE ) ? 1 : unit->GetHitPoints(); if ( damage >= hitpoints ) { const double bonus = ( unit->GetSpeed() > armySpeed ) ? 0.07 : 0.035; return unit->GetStrength() + armyStrength * bonus; } // Otherwise use the amount of strength lost (% of the total unit's strength) double unitPercentageLost = std::min( static_cast( damage ) / hitpoints, 1.0 ); // Penalty for waking up disabled unit (if you kill only 30%, the remaining 70% is your penalty) if ( unit->isImmovable() ) { unitPercentageLost += unitPercentageLost - 1.0; } return unitPercentageLost * unit->GetStrength(); }; SpellcastOutcome bestOutcome; if ( spell.isSingleTarget() ) { for ( const Battle::Unit * enemy : enemies ) { bestOutcome.updateOutcome( damageHeuristic( enemy, _enemyArmyStrength, _enemyAverageSpeed ), enemy->GetHeadIndex() ); } } else if ( spell.isApplyWithoutFocusObject() ) { double spellHeuristic = 0; for ( const Battle::Unit * enemy : enemies ) { spellHeuristic += damageHeuristic( enemy, _enemyArmyStrength, _enemyAverageSpeed ); } for ( const Battle::Unit * unit : friendly ) { const double valueLost = damageHeuristic( unit, _myArmyStrength, _myArmyAverageSpeed ); // check if we're retreating and will lose current unit if ( retreating && unit->isUID( currentUnit.GetUID() ) && std::fabs( valueLost - unit->GetStrength() ) < 0.001 ) { // avoid this spell and return early return bestOutcome; } spellHeuristic -= valueLost; } bestOutcome.updateOutcome( spellHeuristic, -1 ); } else { // Area of effect spells like Fireball const auto areaOfEffectCheck = [this, &damageHeuristic, &bestOutcome, ¤tUnit, retreating]( const Battle::TargetsInfo & targets, const int32_t index, int myColor ) { double spellHeuristic = 0; for ( const Battle::TargetInfo & target : targets ) { if ( target.defender->GetCurrentColor() == myColor ) { const double valueLost = damageHeuristic( target.defender, _myArmyStrength, _myArmyAverageSpeed ); // check if we're retreating and will lose current unit if ( retreating && target.defender->isUID( currentUnit.GetUID() ) && std::fabs( valueLost - target.defender->GetStrength() ) < 0.001 ) { // avoid this spell and return without updating the outcome return; } spellHeuristic -= valueLost; } else { spellHeuristic += damageHeuristic( target.defender, _enemyArmyStrength, _enemyAverageSpeed ); } } bestOutcome.updateOutcome( spellHeuristic, index ); }; if ( spell.GetID() == Spell::CHAINLIGHTNING ) { for ( const Battle::Unit * enemy : enemies ) { if ( !enemy->AllowApplySpell( spell, _commander ) ) { continue; } const int32_t index = enemy->GetHeadIndex(); areaOfEffectCheck( arena.GetTargetsForSpell( _commander, spell, index ), index, _myColor ); } } else { const Battle::Board & board = *Battle::Arena::GetBoard(); for ( const Battle::Cell & cell : board ) { const int32_t index = cell.GetIndex(); areaOfEffectCheck( arena.GetTargetsForSpell( _commander, spell, index ), index, _myColor ); } } } return bestOutcome; } int32_t AI::BattlePlanner::spellDurationMultiplier( const Battle::Unit & target ) const { const int32_t duration = _commander->GetPower() + _commander->GetBagArtifacts().getTotalArtifactEffectValue( fheroes2::ArtifactBonusType::EVERY_COMBAT_SPELL_DURATION ); if ( duration < 2 && target.Modes( Battle::TR_MOVED ) ) { return 0; } return 1; } double AI::BattlePlanner::getSpellDisruptingRayRatio( const Battle::Unit & target ) const { const double targetDefense = target.GetDefense(); if ( targetDefense <= 1 ) { // target is already at minimum defense: not useful to cast Disrupting Ray return 0.0; } double ratio = 0.2; if ( targetDefense <= Spell( Spell::DISRUPTINGRAY ).ExtraValue() ) { // disrupting ray can't have full effect const double actualDefenseChange = targetDefense - 1.0; ratio *= actualDefenseChange / Spell( Spell::DISRUPTINGRAY ).ExtraValue(); } const double targetStrength = target.GetStrength(); // if current army has much lower strength than target unit, we reduce the ratio to prioritize direct damage spells if ( _myArmyStrength < targetStrength ) { ratio *= _myArmyStrength / targetStrength; } return ratio; } double AI::BattlePlanner::getSpellSlowRatio( const Battle::Unit & target ) const { if ( target.isArchers() || _attackingCastle ) { // Slow is useless against archers or troops defending castle return 0.01; } const int currentSpeed = target.GetSpeed( false, true ); const int newSpeed = Speed::GetSlowSpeedFromSpell( currentSpeed ); const int lostSpeed = currentSpeed - newSpeed; // usually 2 double ratio = 0.1 * lostSpeed; if ( currentSpeed < _myArmyAverageSpeed ) { // Slow isn't useful if target is already slower than our army ratio /= 2; } if ( target.Modes( Battle::SP_HASTE ) ) { ratio *= 2; } else if ( !target.isFlying() ) { ratio /= ReduceEffectivenessByDistance( target ); } return ratio; } double AI::BattlePlanner::getSpellHasteRatio( const Battle::Unit & target ) const { const int currentSpeed = target.GetSpeed( false, true ); const int newSpeed = Speed::GetHasteSpeedFromSpell( currentSpeed ); const int gainedSpeed = newSpeed - currentSpeed; // usually 2 double ratio = 0.05 * gainedSpeed; if ( currentSpeed < _enemyAverageSpeed ) { // Haste is very useful if target is slower than army ratio *= 2; } if ( target.Modes( Battle::SP_SLOW ) ) { ratio *= 2; } // Reduce effectiveness if we don't have to move else if ( target.isArchers() || _defensiveTactics ) { ratio /= 2; } return ratio; } double AI::BattlePlanner::spellEffectValue( const Spell & spell, const Battle::Unit & target, bool targetIsLast, bool forDispel ) const { const int spellID = spell.GetID(); // Make sure that this spell makes sense to apply (skip this check to evaluate the effect of dispelling) if ( !forDispel && ( isSpellcastUselessForUnit( target, spell ) || !target.AllowApplySpell( spell, _commander ) ) ) { return 0.0; } double ratio = 0.0; switch ( spellID ) { case Spell::SLOW: case Spell::MASSSLOW: ratio = getSpellSlowRatio( target ); break; case Spell::BLIND: { if ( targetIsLast ) return 0.0; ratio = 0.8; break; } case Spell::CURSE: case Spell::MASSCURSE: ratio = 0.15; break; case Spell::BERSERKER: case Spell::PARALYZE: { if ( targetIsLast ) return 0.0; ratio = 0.85; break; } case Spell::HYPNOTIZE: { ratio = 1.5; break; } case Spell::DISRUPTINGRAY: ratio = getSpellDisruptingRayRatio( target ); break; case Spell::HASTE: case Spell::MASSHASTE: ratio = getSpellHasteRatio( target ); break; case Spell::BLOODLUST: ratio = 0.1; break; case Spell::BLESS: case Spell::MASSBLESS: { if ( target.GetDamageMax() == target.GetDamageMin() ) return 0.0; ratio = 0.15; break; } case Spell::STONESKIN: ratio = 0.1; break; case Spell::STEELSKIN: ratio = 0.2; break; // Following spell usefulness is conditional; ratio will be determined later case Spell::DRAGONSLAYER: case Spell::ANTIMAGIC: case Spell::MIRRORIMAGE: case Spell::SHIELD: case Spell::MASSSHIELD: ratio = 0.0; break; default: return 0.0; } if ( target.Modes( Battle::SP_BLESS ) && ( spellID == Spell::CURSE || spellID == Spell::MASSCURSE ) ) { ratio *= 2; } else if ( target.Modes( Battle::SP_CURSE ) && ( spellID == Spell::BLESS || spellID == Spell::MASSBLESS ) ) { ratio *= 2; } else if ( spellID == Spell::ANTIMAGIC && !target.Modes( Battle::IS_GOOD_MAGIC ) && _enemySpellStrength > antimagicLowLimit ) { double ratioLimit = 0.9; const SpellStorage spellList = _commander->getAllSpells(); for ( const Spell & otherSpell : spellList ) { if ( otherSpell.isResurrect() && _commander->HaveSpellPoints( otherSpell ) && target.AllowApplySpell( otherSpell, _commander ) ) { // Can resurrect unit in the future, limit the ratio ratioLimit = 0.35; break; } } // Convert 0...5000 range into 0.0 to 0.9 ratio and clamp it ratio = std::min( _enemySpellStrength / antimagicLowLimit * 0.036, ratioLimit ); // Hero is stronger than its army, possible hit and run tactic if ( _enemySpellStrength > _enemyArmyStrength ) { ratio *= 1.5; } if ( target.Modes( Battle::IS_BAD_MAGIC ) ) { ratio *= 2; } } else if ( spellID == Spell::MIRRORIMAGE ) { if ( target.isArchers() ) { ratio = 1.0; } else { ratio = target.isFlying() ? 0.55 : 0.33; } // Slow unit might be destroyed before taking its turn if ( target.GetSpeed() < _enemyAverageSpeed ) { ratio /= 5; } } else if ( spellID == Spell::BERSERKER && !target.isArchers() ) { ratio /= ReduceEffectivenessByDistance( target ); } else if ( spellID == Spell::SHIELD || spellID == Spell::MASSSHIELD ) { ratio = _enemyRangedUnitsOnly / _enemyArmyStrength * 0.3; if ( target.isArchers() ) { ratio *= 1.25; } } else if ( spellID == Spell::DRAGONSLAYER ) { // TODO: add logic to check if the enemy army contains a dragon. } return target.GetStrength() * ratio * spellDurationMultiplier( target ); } AI::SpellcastOutcome AI::BattlePlanner::spellEffectValue( const Spell & spell, const Battle::Units & targets ) const { const bool isSingleTargetLeft = targets.size() == 1; const bool isMassSpell = spell.isMassActions(); SpellcastOutcome bestOutcome; for ( const Battle::Unit * unit : targets ) { bestOutcome.updateOutcome( spellEffectValue( spell, *unit, isSingleTargetLeft, false ), unit->GetHeadIndex(), isMassSpell ); } return bestOutcome; } AI::SpellcastOutcome AI::BattlePlanner::spellDispelValue( const Spell & spell, const Battle::Units & friendly, const Battle::Units & enemies ) const { const int spellID = spell.GetID(); const bool isMassSpell = spell.isMassActions(); const bool isDispel = spellID == Spell::DISPEL || spellID == Spell::MASSDISPEL; SpellcastOutcome bestOutcome; for ( const Battle::Unit * unit : friendly ) { if ( !unit->Modes( Battle::IS_MAGIC ) ) { continue; } double unitValue = 0; const std::vector & spellList = unit->getCurrentSpellEffects(); for ( const Spell & spellOnFriend : spellList ) { const double effectValue = spellEffectValue( spellOnFriend, *unit, false, true ); if ( spellOnFriend.isApplyToEnemies() ) { unitValue += effectValue; } else if ( isDispel && spellOnFriend.isApplyToFriends() ) { unitValue -= effectValue; } } bestOutcome.updateOutcome( unitValue, unit->GetHeadIndex(), isMassSpell ); } if ( isDispel ) { const bool enemyLastUnit = enemies.size() == 1; for ( const Battle::Unit * unit : enemies ) { if ( !unit->Modes( Battle::IS_MAGIC ) ) continue; double unitValue = 0; const std::vector & spellList = unit->getCurrentSpellEffects(); for ( const Spell & spellOnEnemy : spellList ) { const double effectValue = spellEffectValue( spellOnEnemy, *unit, enemyLastUnit, true ); unitValue += spellOnEnemy.isApplyToFriends() ? effectValue : -effectValue; } bestOutcome.updateOutcome( unitValue, unit->GetHeadIndex(), isMassSpell ); } } return bestOutcome; } AI::SpellcastOutcome AI::BattlePlanner::spellResurrectValue( const Spell & spell, const Battle::Arena & arena ) const { const uint32_t hpRestored = fheroes2::getResurrectPoints( spell, _commander->GetPower(), _commander ); SpellcastOutcome bestOutcome; const auto updateBestOutcome = [this, &spell, &bestOutcome, hpRestored]( const Battle::Unit * unit ) { uint32_t missingHP = unit->GetMissingHitPoints(); missingHP = ( missingHP < hpRestored ) ? missingHP : hpRestored; double spellValue = missingHP * unit->GetMonsterStrength() / unit->Monster::GetHitPoints(); // if we are winning battle; permanent resurrect bonus if ( _myArmyStrength > _enemyArmyStrength && spell.GetID() != Spell::RESURRECT ) { spellValue *= 2; } bestOutcome.updateOutcome( spellValue, unit->GetHeadIndex() ); }; // First consider the still alive stacks for ( const Battle::Unit * unit : arena.getForce( _myColor ) ) { assert( unit != nullptr ); if ( !unit->isValid() ) { continue; } if ( !unit->AllowApplySpell( spell, _commander ) ) { continue; } updateBestOutcome( unit ); } // Then consider the stacks from the graveyard for ( const int32_t idx : arena.getCellsOccupiedByGraveyard() ) { if ( !arena.isAbleToResurrectFromGraveyard( idx, spell ) ) { continue; } const Battle::Unit * unit = arena.getLastResurrectableUnitFromGraveyard( idx, spell ); assert( unit != nullptr && !unit->isValid() ); updateBestOutcome( unit ); } return bestOutcome; } AI::SpellcastOutcome AI::BattlePlanner::spellSummonValue( const Spell & spell, const Battle::Arena & arena, const int heroColor ) const { if ( !spell.isSummon() ) { return {}; } if ( arena.GetFreePositionNearHero( heroColor ) < 0 ) { return {}; } const Troop summon( Monster( spell ), fheroes2::getSummonMonsterCount( spell, _commander->GetPower(), _commander ) ); SpellcastOutcome bestOutcome; bestOutcome.value = summon.GetStrengthWithBonus( _commander->GetAttack(), _commander->GetDefense() ); // Spell is less effective if we already winning this battle if ( _myArmyStrength > _enemyArmyStrength * 2 ) { bestOutcome.value /= 2; } return bestOutcome; } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_common.cpp000066400000000000000000000310301476115357100215240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ai_common.h" #include #include #include #include #include #include #include #include #include #include #include #include "army.h" #include "army_troop.h" #include "castle.h" #include "color.h" #include "difficulty.h" #include "game.h" #include "heroes.h" #include "kingdom.h" #include "logging.h" #include "payment.h" #include "resource.h" #include "resource_trading.h" bool AI::BuildIfPossible( Castle & castle, const BuildingType building ) { switch ( castle.CheckBuyBuilding( building ) ) { case BuildingStatus::LACK_RESOURCES: { const Funds payment = PaymentConditions::BuyBuilding( castle.GetRace(), building ); if ( !AI::tradeAtMarketplace( castle.GetKingdom(), payment ) ) { return false; } break; } case BuildingStatus::ALLOW_BUILD: break; default: return false; } const bool result = castle.BuyBuilding( building ); assert( result ); return result; } bool AI::BuildIfEnoughFunds( Castle & castle, const BuildingType building, const uint32_t fundsMultiplier ) { if ( fundsMultiplier < 1 || fundsMultiplier > 99 ) { return false; } const Kingdom & kingdom = castle.GetKingdom(); const Funds requiredFunds = PaymentConditions::BuyBuilding( castle.GetRace(), building ) * fundsMultiplier; // Perhaps the kingdom already has the necessary supply of resources if ( !kingdom.AllowPayment( requiredFunds ) ) { // Even if the kingdom does not have the necessary supply of these resources right now, there may be enough resources of another type available to get the // missing resources as a result of resource exchange if ( !AI::calculateMarketplaceTransaction( kingdom, requiredFunds ) ) { return false; } } return BuildIfPossible( castle, building ); } void AI::OptimizeTroopsOrder( Army & army ) { if ( !army.isValid() ) { return; } army.MergeSameMonsterTroops(); std::vector archers; std::vector others; for ( size_t slot = 0; slot < Army::maximumTroopCount; ++slot ) { const Troop * troop = army.GetTroop( slot ); if ( troop && troop->isValid() ) { if ( troop->isArchers() ) { archers.push_back( *troop ); } else { others.push_back( *troop ); } } } // Sort troops by tactical priority. For melee units, the order of comparison is as follows: // 1. Comparison by speed (faster units first); // 2. Comparison by type (flying units first); // 3. Comparison by strength. std::sort( others.begin(), others.end(), []( const Troop & left, const Troop & right ) { if ( left.GetSpeed() != right.GetSpeed() ) { return left.GetSpeed() < right.GetSpeed(); } if ( left.isFlying() != right.isFlying() ) { return right.isFlying(); } return left.GetStrength() < right.GetStrength(); } ); // Archers are sorted solely by strength std::sort( archers.begin(), archers.end(), []( const Troop & left, const Troop & right ) { return left.GetStrength() < right.GetStrength(); } ); std::array slotOrder = { 2, 1, 3, 0, 4 }; switch ( archers.size() ) { case 1: slotOrder = { 0, 2, 1, 3, 4 }; break; case 2: case 3: slotOrder = { 0, 4, 2, 1, 3 }; break; case 4: slotOrder = { 0, 4, 2, 3, 1 }; break; case 5: slotOrder = { 0, 4, 1, 2, 3 }; break; default: break; } army.Clean(); for ( const size_t slot : slotOrder ) { if ( !archers.empty() ) { army.GetTroop( slot )->Set( archers.back() ); archers.pop_back(); } else if ( !others.empty() ) { army.GetTroop( slot )->Set( others.back() ); others.pop_back(); } else { break; } } if ( Difficulty::allowAIToSplitWeakStacks( Game::getDifficulty() ) ) { // Complicate the task of a potential attacker army.splitStackOfWeakestUnitsIntoFreeSlots(); } } void AI::transferSlowestTroopsToGarrison( Heroes * hero, Castle * castle ) { assert( hero != nullptr && castle != nullptr ); Army & army = hero->GetArmy(); Army & garrison = castle->GetArmy(); // Make efforts to get free slots in the garrison to move troops there garrison.MergeSameMonsterTroops(); std::vector armyTroops; armyTroops.reserve( army.Size() ); for ( size_t i = 0; i < army.Size(); ++i ) { Troop * troop = army.GetTroop( i ); assert( troop != nullptr ); if ( troop->isEmpty() ) { continue; } armyTroops.push_back( troop ); } assert( !armyTroops.empty() ); // Move the slowest units first std::sort( armyTroops.begin(), armyTroops.end(), Army::SlowestTroop ); // At least one of the fastest units should remain in the hero's army armyTroops.pop_back(); for ( Troop * troop : armyTroops ) { if ( !garrison.JoinTroop( *troop ) ) { break; } troop->Reset(); } assert( army.isValid() ); } std::optional AI::calculateMarketplaceTransaction( const Kingdom & kingdom, const Funds & fundsToObtain ) { const uint32_t marketplaceCount = kingdom.GetCountMarketplace(); if ( marketplaceCount == 0 ) { return {}; } std::map plannedBalance; { const Funds fundsDiff = kingdom.GetFunds() - fundsToObtain; Resource::forEach( Resource::ALL, [&plannedBalance, &fundsDiff]( const int res ) { if ( const auto [dummy, inserted] = plannedBalance.try_emplace( res, fundsDiff.Get( res ) ); !inserted ) { assert( 0 ); } } ); assert( !plannedBalance.empty() ); } Funds plannedTransaction; const auto exchangeResources = [marketplaceCount, &plannedBalance, &plannedTransaction]( const int fromRes, const int toRes ) { assert( fromRes != toRes ); auto fromResBalanceIter = plannedBalance.find( fromRes ); auto toResBalanceIter = plannedBalance.find( toRes ); assert( fromResBalanceIter != plannedBalance.end() && toResBalanceIter != plannedBalance.end() ); auto & [fromResDummy, fromResBalanceAmount] = *fromResBalanceIter; auto & [toResDummy, toResBalanceAmount] = *toResBalanceIter; assert( fromResBalanceAmount > 0 && toResBalanceAmount < 0 ); const int32_t tradeCost = fheroes2::getTradeCost( marketplaceCount, fromRes, toRes ); assert( tradeCost > 0 ); int32_t * fromResTransactionAmount = plannedTransaction.GetPtr( fromRes ); int32_t * toResTransactionAmount = plannedTransaction.GetPtr( toRes ); assert( fromResTransactionAmount != nullptr && toResTransactionAmount != nullptr && fromResTransactionAmount != toResTransactionAmount ); // If resources are exchanged for gold, then by giving away one unit of the resource we get several units of gold if ( toRes == Resource::GOLD ) { fromResBalanceAmount -= 1; toResBalanceAmount += tradeCost; // Since the planned transaction must be deducted from the funds of the kingdom, the volume of exchanged resources should be positive, and the volume of // acquired resources should be negative *fromResTransactionAmount += 1; *toResTransactionAmount -= tradeCost; } // Otherwise (when exchanging gold for a resource or a resource for a resource) by giving away several units of a resource, we get only one unit of another // resource else { fromResBalanceAmount -= tradeCost; toResBalanceAmount += 1; // Since the planned transaction must be deducted from the funds of the kingdom, the volume of exchanged resources should be positive, and the volume of // acquired resources should be negative *fromResTransactionAmount += tradeCost; *toResTransactionAmount -= 1; } assert( fromResBalanceAmount >= 0 ); }; for ( const auto & [missingRes, missingResAmount] : plannedBalance ) { if ( missingResAmount >= 0 ) { continue; } while ( missingResAmount < 0 ) { // The exchange of resources takes place one unit at a time. Each time, the resource whose relative stock is currently maximum is selected for exchange // (that is, the resource whose current stock can be exchanged for the maximum amount of the target resource). int resToExchange = Resource::UNKNOWN; int32_t maxPotentialRevenue = 0; for ( const auto & [res, resAmount] : plannedBalance ) { if ( res == missingRes ) { continue; } if ( resAmount <= 0 ) { continue; } const int32_t tradeCost = fheroes2::getTradeCost( marketplaceCount, res, missingRes ); assert( tradeCost > 0 ); const int32_t potentialRevenue = ( missingRes == Resource::GOLD ? resAmount * tradeCost : resAmount / tradeCost ); if ( maxPotentialRevenue < potentialRevenue ) { resToExchange = res; maxPotentialRevenue = potentialRevenue; } } if ( resToExchange == Resource::UNKNOWN ) { return {}; } exchangeResources( resToExchange, missingRes ); } // If we exchange resources for gold, we can get a little more than the amount we need. In other cases, we should get exactly the amount we need. assert( missingRes == Resource::GOLD ? missingResAmount >= 0 : missingResAmount == 0 ); } // If the trade is successful, then we should not have any "debts" in the planned balance... assert( std::none_of( plannedBalance.cbegin(), plannedBalance.cend(), []( const auto & item ) { return ( item.second < 0 ); } ) ); // ... and the kingdom should be able to conduct the planned transaction assert( kingdom.AllowPayment( plannedTransaction ) ); return plannedTransaction; } bool AI::tradeAtMarketplace( Kingdom & kingdom, const Funds & fundsToObtain ) { const std::optional transaction = calculateMarketplaceTransaction( kingdom, fundsToObtain ); if ( !transaction ) { DEBUG_LOG( DBG_AI, DBG_TRACE, Color::String( kingdom.GetColor() ) << " having funds " << kingdom.GetFunds().String() << " failed to obtain funds " << fundsToObtain.String() ) return false; } assert( kingdom.AllowPayment( *transaction ) ); DEBUG_LOG( DBG_AI, DBG_INFO, Color::String( kingdom.GetColor() ) << " having funds " << kingdom.GetFunds().String() << " obtains funds " << fundsToObtain.String() << " through a transaction " << transaction->String() ) kingdom.OddFundsResource( *transaction ); return true; } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_common.h000066400000000000000000000072011476115357100211740ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include class Army; class Castle; class Heroes; class Kingdom; struct Funds; enum BuildingType : uint32_t; namespace AI { // Builds the given building in the given castle if possible. If possible and necessary, obtains the resources // that are missing for construction through trading on the marketplace. Returns true if the construction was // successful, otherwise returns false. bool BuildIfPossible( Castle & castle, const BuildingType building ); // Builds the given building in the given castle if possible and if there is a sufficient supply of resources // (see the implementation for details). If possible and necessary, obtains the resources that are missing for // construction through trading on the marketplace. Returns true if the construction was successful, otherwise // returns false. bool BuildIfEnoughFunds( Castle & castle, const BuildingType building, const uint32_t fundsMultiplier ); // Performs the pre-battle arrangement of the given army, see the implementation for details void OptimizeTroopsOrder( Army & army ); // Transfers the slowest troops from the hero's army to the garrison to try to get a movement bonus on the next turn void transferSlowestTroopsToGarrison( Heroes * hero, Castle * castle ); // Calculates a marketplace transaction, after which the kingdom would be able to make a payment in the amount of // at least 'fundsToObtain'. Returns the corresponding transaction if it was found, otherwise returns an empty // result. In order to receive the necessary funds, the returned transaction must be deducted from the funds of // the kingdom. std::optional calculateMarketplaceTransaction( const Kingdom & kingdom, const Funds & fundsToObtain ); // Performs operations on the marketplace necessary for the kingdom to be able to make a payment in the amount // of at least 'fundsToObtain'. If the necessary funds cannot be obtained as a result of trading, then the current // funds of the kingdom remain unchanged. Returns true if the trade was successful, otherwise returns false. bool tradeAtMarketplace( Kingdom & kingdom, const Funds & fundsToObtain ); } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_hero_action.cpp000066400000000000000000002414651476115357100225450ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ai_hero_action.h" #include #include #include #include #include #include #include #include "ai_common.h" #include "ai_planner.h" #include "army.h" #include "army_troop.h" #include "artifact.h" #include "audio_manager.h" #include "battle.h" #include "castle.h" #include "color.h" #include "direction.h" #include "game.h" #include "game_delays.h" #include "game_interface.h" #include "game_static.h" #include "heroes.h" #include "interface_base.h" #include "interface_gamearea.h" #include "kingdom.h" #include "localevent.h" #include "logging.h" #include "m82.h" #include "maps.h" #include "maps_objects.h" #include "maps_tiles.h" #include "maps_tiles_helper.h" #include "math_base.h" #include "monster.h" #include "mp2.h" #include "payment.h" #include "players.h" #include "puzzle.h" #include "race.h" #include "rand.h" #include "resource.h" #include "route.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "spell.h" #include "spell_info.h" #include "visit.h" #include "world.h" namespace { uint32_t AIGetAllianceColors() { // accumulate colors uint32_t colors = 0; if ( Settings::Get().GameType() & Game::TYPE_HOTSEAT ) { const Colors vcolors( Players::HumanColors() ); for ( const int color : vcolors ) { const Player * player = Players::Get( color ); if ( player ) colors |= player->GetFriends(); } } else { const Player * player = Players::Get( Players::HumanColors() ); if ( player ) colors = player->GetFriends(); } return colors; } // Never cache the value of this function as it depends on hero's path and location. bool AIIsShowAnimationForHero( const Heroes & hero, const uint32_t colors ) { if ( Settings::Get().AIMoveSpeed() == 0 ) { return false; } if ( colors == 0 ) { return false; } const int32_t indexFrom = hero.GetIndex(); if ( !Maps::isValidAbsIndex( indexFrom ) ) { return false; } // Show AI hero animation if he is visible (or barely visible) for human player. if ( world.getTile( indexFrom ).getFogDirection() != DIRECTION_ALL ) { return true; } const Route::Path & path = hero.GetPath(); // Show AI hero animation if any of the tiles next to the first tile in the path is visible for human player. if ( path.isValidForMovement() && ( world.getTile( path.GetFrontIndex() ).getFogDirection() != DIRECTION_ALL ) ) { return true; } return false; } bool AIIsShowAnimationForTile( const Maps::Tile & tile, const uint32_t colors ) { if ( Settings::Get().AIMoveSpeed() == 0 ) { return false; } if ( colors == 0 ) { return false; } // Show animation on this tile if it is visible (or barely visible) to the human player. return ( tile.getFogDirection() != DIRECTION_ALL ); } int AISelectSkillFromArena( const Heroes & hero ) { switch ( hero.GetRace() ) { case Race::KNGT: if ( hero.GetDefense() < 5 ) { return Skill::Primary::DEFENSE; } if ( hero.GetAttack() < 5 ) { return Skill::Primary::ATTACK; } if ( hero.GetPower() < 3 ) { return Skill::Primary::POWER; } break; case Race::BARB: if ( hero.GetAttack() < 5 ) { return Skill::Primary::ATTACK; } if ( hero.GetDefense() < 5 ) { return Skill::Primary::DEFENSE; } if ( hero.GetPower() < 3 ) { return Skill::Primary::POWER; } break; case Race::SORC: case Race::WZRD: if ( hero.GetPower() < 5 ) { return Skill::Primary::POWER; } if ( hero.GetDefense() < 3 ) { return Skill::Primary::DEFENSE; } if ( hero.GetAttack() < 3 ) { return Skill::Primary::ATTACK; } break; case Race::WRLK: case Race::NECR: if ( hero.GetPower() < 5 ) { return Skill::Primary::POWER; } if ( hero.GetAttack() < 3 ) { return Skill::Primary::ATTACK; } if ( hero.GetDefense() < 3 ) { return Skill::Primary::DEFENSE; } break; default: break; } switch ( Rand::Get( 1, 3 ) ) { case 1: return Skill::Primary::ATTACK; case 2: return Skill::Primary::DEFENSE; case 3: return Skill::Primary::POWER; default: assert( 0 ); break; } return Skill::Primary::UNKNOWN; } bool canMonsterJoinHero( const Troop & troop, Heroes & hero ) { if ( hero.GetArmy().HasMonster( troop.GetID() ) ) { return true; } if ( troop.GetStrength() < hero.getAIMinimumJoiningArmyStrength() ) { // No use to hire such a weak troop. return false; } if ( !hero.GetArmy().mergeWeakestTroopsIfNeeded() ) { // The army has no slots and we cannot rearrange it. return false; } return true; } void AITownPortal( Heroes & hero, const int32_t targetIndex ) { assert( Maps::isValidAbsIndex( targetIndex ) ); #if !defined( NDEBUG ) || defined( WITH_DEBUG ) const Castle * targetCastle = world.getCastleEntrance( Maps::GetPoint( targetIndex ) ); #endif assert( targetCastle && targetCastle->GetHero() == nullptr ); const Spell spellToUse = [&hero, targetIndex]() { const Castle * nearestCastle = fheroes2::getNearestCastleTownGate( hero ); assert( nearestCastle != nullptr ); if ( nearestCastle->GetIndex() == targetIndex && hero.CanCastSpell( Spell::TOWNGATE ) ) { return Spell::TOWNGATE; } return Spell::TOWNPORTAL; }(); assert( hero.CanCastSpell( spellToUse ) ); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( targetIndex ); hero.Move2Dest( targetIndex ); hero.SpellCasted( spellToUse ); hero.GetPath().Reset(); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } AI::Planner::Get().HeroesActionComplete( hero, targetIndex, hero.getObjectTypeUnderHero() ); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " used the " << spellToUse.GetName() << " to reach the " << targetCastle->GetName() ) } void AIBattleLose( Heroes & hero, const Battle::Result & res, bool attacker, const fheroes2::Point * centerOn = nullptr, const bool playSound = false ) { const uint32_t reason = attacker ? res.AttackerResult() : res.DefenderResult(); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { if ( centerOn != nullptr ) { Interface::AdventureMap::Get().getGameArea().SetCenter( *centerOn ); } if ( playSound ) { AudioManager::PlaySound( M82::KILLFADE ); hero.FadeOut(); } else { hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } } hero.Dismiss( reason ); } void AIMeeting( Heroes & left, Heroes & right ) { left.markHeroMeeting( right.GetID() ); right.markHeroMeeting( left.GetID() ); // A hero with a higher role must receive an army and artifacts from another hero. // In case of the same roles a more powerful hero will receive all benefits. bool rightToLeft = true; if ( left.getAIRole() < right.getAIRole() ) { rightToLeft = false; } else if ( left.getAIRole() == right.getAIRole() ) { rightToLeft = right.getStatsValue() < left.getStatsValue(); } Heroes & giver = rightToLeft ? right : left; Heroes & taker = rightToLeft ? left : right; Army & takerArmy = taker.GetArmy(); Army & giverArmy = giver.GetArmy(); // TODO: do not transfer the whole army from one hero to another. Add logic to leave a fast unit for Scout and Courier. Also 3-5 monsters are better than // having 1 Peasant in one stack which leads to an instant death if the hero is attacked by an opponent. takerArmy.JoinStrongestFromArmy( giverArmy ); AI::OptimizeTroopsOrder( takerArmy ); AI::OptimizeTroopsOrder( giverArmy ); BagArtifacts::exchangeArtifacts( taker, giver ); } void AIToCastle( Heroes & hero, const int32_t dstIndex ) { Castle * castle = world.getCastleEntrance( Maps::GetPoint( dstIndex ) ); if ( castle == nullptr ) { // This should never happen assert( 0 ); DEBUG_LOG( DBG_AI, DBG_WARN, hero.GetName() << " is trying to visit the castle on tile " << dstIndex << ", but there is no entrance to the castle on this tile" ) return; } if ( hero.GetColor() == castle->GetColor() ) { assert( hero.GetIndex() == dstIndex ); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " visits " << castle->GetName() ) castle->MageGuildEducateHero( hero ); hero.SetVisited( dstIndex ); return; } if ( hero.isFriends( castle->GetColor() ) ) { // This should never happen - hero should not be able to visit an allied castle assert( 0 ); DEBUG_LOG( DBG_AI, DBG_WARN, hero.GetName() << " is not allowed to visit the allied castle " << castle->GetName() ) return; } const auto captureCastle = [&hero, dstIndex, castle]() { castle->GetKingdom().RemoveCastle( castle ); hero.GetKingdom().AddCastle( castle ); world.CaptureObject( dstIndex, hero.GetColor() ); castle->Scout(); }; Army & army = castle->GetActualArmy(); // Hero is standing in front of the castle, which means that there must be an enemy army in the castle if ( hero.GetIndex() != dstIndex ) { assert( army.isValid() && army.GetColor() != hero.GetColor() ); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " attacks the enemy castle " << castle->GetName() ) Heroes * defender = castle->GetHero(); const bool isDefenderHuman = castle->isControlHuman(); if ( defender && ( defender->isControlHuman() != isDefenderHuman ) ) { assert( 0 ); if ( isDefenderHuman ) { DEBUG_LOG( DBG_AI, DBG_WARN, defender->GetName() << " the AI hero is protecting the human castle " << castle->GetName() ) } else { DEBUG_LOG( DBG_AI, DBG_WARN, defender->GetName() << " the human hero is protecting the AI castle " << castle->GetName() ) } } if ( isDefenderHuman ) { // Sometimes the battle action is performed without attacker movement if the defender is standing close to him. // Update the game area before the battle to show the dueling heroes. Interface::AdventureMap::Get().redraw( Interface::REDRAW_GAMEAREA ); } castle->ActionPreBattle(); const Battle::Result res = Battle::Loader( hero.GetArmy(), army, dstIndex ); // Human controlled castle or hero in this castle was in the battle. Update icons. Interface::AdventureMap::Get().renderWithFadeInOrPlanRender( Interface::REDRAW_ICONS ); castle->ActionAfterBattle( res.AttackerWins() ); // The defender was defeated if ( !res.DefenderWins() ) { if ( defender ) { AIBattleLose( *defender, res, false, nullptr, isDefenderHuman ); } if ( isDefenderHuman ) { // Update interface heroes and castles icons after the defeat. Interface::AdventureMap::Get().setRedraw( Interface::REDRAW_ICONS ); } } // The attacker was defeated if ( !res.AttackerWins() ) { AIBattleLose( hero, res, true, &( castle->GetCenter() ), isDefenderHuman ); } // The attacker won if ( res.AttackerWins() ) { captureCastle(); hero.IncreaseExperience( res.GetExperienceAttacker() ); } // The defender won else if ( res.DefenderWins() && defender ) { defender->IncreaseExperience( res.GetExperienceDefender() ); } return; } // If hero is already in the castle, then there must be his own army in the castle assert( army.isValid() && army.GetColor() == hero.GetColor() ); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " captures the enemy castle " << castle->GetName() ) captureCastle(); castle->MageGuildEducateHero( hero ); hero.SetVisited( dstIndex ); } void AIToHeroes( Heroes & hero, const int32_t dstIndex ) { Heroes * otherHero = world.getTile( dstIndex ).getHero(); if ( otherHero == nullptr ) { // This should never happen assert( 0 ); DEBUG_LOG( DBG_AI, DBG_WARN, hero.GetName() << " is trying to meet the hero on tile " << dstIndex << ", but there is no hero on this tile" ) return; } if ( hero.GetColor() == otherHero->GetColor() ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " meets " << otherHero->GetName() ) AIMeeting( hero, *otherHero ); return; } if ( hero.isFriends( otherHero->GetColor() ) ) { // This should never happen - hero should not be able to meet an allied hero assert( 0 ); DEBUG_LOG( DBG_AI, DBG_WARN, hero.GetName() << " is not allowed to meet the allied hero " << otherHero->GetName() ) return; } if ( otherHero->inCastle() ) { AIToCastle( hero, dstIndex ); return; } DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " attacks " << otherHero->GetName() ) const bool isDefenderHuman = otherHero->isControlHuman(); if ( isDefenderHuman ) { // Sometimes the battle action is performed without attacker movement if the defender is standing close to him. // Update the game area before the battle to show the dueling heroes. Interface::AdventureMap::Get().redraw( Interface::REDRAW_GAMEAREA ); } const Battle::Result res = Battle::Loader( hero.GetArmy(), otherHero->GetArmy(), dstIndex ); // Human controlled hero could be in the battle. Update icons. Interface::AdventureMap::Get().renderWithFadeInOrPlanRender( Interface::REDRAW_HEROES ); // The defender was defeated if ( !res.DefenderWins() ) { AIBattleLose( *otherHero, res, false, nullptr, isDefenderHuman ); if ( isDefenderHuman ) { // Update interface heroes and castles icons after the defeat. Interface::AdventureMap::Get().setRedraw( Interface::REDRAW_HEROES ); } } // The attacker was defeated if ( !res.AttackerWins() ) { AIBattleLose( hero, res, true, ( otherHero->isActive() ? &( otherHero->GetCenter() ) : nullptr ), isDefenderHuman ); } // The attacker won if ( res.AttackerWins() ) { hero.IncreaseExperience( res.GetExperienceAttacker() ); } // The defender won else if ( res.DefenderWins() ) { otherHero->IncreaseExperience( res.GetExperienceDefender() ); } } void AIToMonster( Heroes & hero, int32_t dst_index ) { bool destroy = false; Maps::Tile & tile = world.getTile( dst_index ); const Troop troop = getTroopFromTile( tile ); const NeutralMonsterJoiningCondition join = Army::GetJoinSolution( hero, tile, troop ); if ( join.reason == NeutralMonsterJoiningCondition::Reason::Alliance ) { if ( hero.GetArmy().CanJoinTroop( troop ) ) { DEBUG_LOG( DBG_AI, DBG_INFO, troop.GetName() << " join " << hero.GetName() << " as a part of alliance" ) hero.GetArmy().JoinTroop( troop ); } else { DEBUG_LOG( DBG_AI, DBG_INFO, troop.GetName() << " unblock way for " << hero.GetName() << " as a part of alliance" ) } destroy = true; } else if ( join.reason == NeutralMonsterJoiningCondition::Reason::Bane ) { DEBUG_LOG( DBG_AI, DBG_INFO, troop.GetName() << " run away from " << hero.GetName() << " as a part of bane" ) destroy = true; } else if ( join.reason == NeutralMonsterJoiningCondition::Reason::Free ) { DEBUG_LOG( DBG_AI, DBG_INFO, troop.GetName() << " join " << hero.GetName() ) // This condition must already be met if a group of monsters wants to join assert( hero.GetArmy().CanJoinTroop( troop ) ); hero.GetArmy().JoinTroop( troop ); destroy = true; } else if ( join.reason == NeutralMonsterJoiningCondition::Reason::ForMoney ) { const int32_t joiningCost = troop.GetTotalCost().gold; DEBUG_LOG( DBG_AI, DBG_INFO, join.monsterCount << " " << troop.GetName() << " join " << hero.GetName() << " for " << joiningCost << " gold" ) // These conditions must already be met if a group of monsters wants to join assert( hero.GetArmy().CanJoinTroop( troop ) && hero.GetKingdom().AllowPayment( Funds( Resource::GOLD, joiningCost ) ) ); hero.GetArmy().JoinTroop( troop.GetMonster(), join.monsterCount, false ); hero.GetKingdom().OddFundsResource( Funds( Resource::GOLD, joiningCost ) ); destroy = true; } else if ( join.reason == NeutralMonsterJoiningCondition::Reason::RunAway ) { DEBUG_LOG( DBG_AI, DBG_INFO, troop.GetName() << " run away from " << hero.GetName() ) // TODO: AI should still chase monsters which it can defeat without losses to get extra experience. destroy = true; } // Fight if ( !destroy ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " attacks monster " << troop.GetName() ) Army army( tile ); const Battle::Result res = Battle::Loader( hero.GetArmy(), army, dst_index ); if ( res.AttackerWins() ) { hero.IncreaseExperience( res.GetExperienceAttacker() ); destroy = true; } else { AIBattleLose( hero, res, true ); // The army can include both the original monsters and their upgraded version const uint32_t monstersLeft = army.getTotalCount(); #ifndef NDEBUG const Monster originalMonster = troop.GetMonster(); const Monster upgradedMonster = originalMonster.GetUpgrade(); if ( upgradedMonster == originalMonster ) { assert( monstersLeft == army.GetCountMonsters( originalMonster ) ); } else { assert( monstersLeft == army.GetCountMonsters( originalMonster ) + army.GetCountMonsters( upgradedMonster ) ); } #endif if ( monstersLeft > 0 ) { setMonsterCountOnTile( tile, monstersLeft ); if ( Maps::isMonsterOnTileJoinConditionFree( tile ) ) { Maps::setMonsterOnTileJoinCondition( tile, Monster::JOIN_CONDITION_MONEY ); } } else { destroy = true; } } } if ( destroy ) { removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); } } void AIToPickupResource( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) Maps::Tile & tile = world.getTile( dst_index ); if ( objectType != MP2::OBJ_BOTTLE ) { hero.GetKingdom().AddFundsResource( getFundsFromTile( tile ) ); } removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); hero.GetPath().Reset(); } void AIToTreasureChest( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::Tile & tile = world.getTile( dst_index ); const Funds funds = getFundsFromTile( tile ); assert( funds.gold > 0 || funds.GetValidItemsCount() == 0 ); uint32_t gold = funds.gold; Kingdom & kingdom = hero.GetKingdom(); if ( tile.isWater() ) { if ( gold ) { const Artifact & art = getArtifactFromTile( tile ); if ( art.isValid() && !hero.PickupArtifact( art ) ) gold = GoldInsteadArtifact( objectType ); } } else { const Artifact & art = getArtifactFromTile( tile ); if ( gold ) { const uint32_t experience = gold > 500 ? gold - 500 : 500; const Heroes::Role role = hero.getAIRole(); const int32_t kingdomGold = kingdom.GetFunds().gold; uint32_t chance = 0; if ( role == Heroes::Role::SCOUT || role == Heroes::Role::COURIER ) { // These roles usually don't choose experience. Make AI rich! if ( kingdomGold > 10000 && experience >= 1500 ) { chance = 10; } } else if ( role == Heroes::Role::CHAMPION ) { // If AI is extremely low on gold consider taking it if ( kingdomGold < 3000 ) { // Safeguard the calculation since we're working with unsigned values chance = ( std::max( experience, 500U ) - 500 ) / 15; } else { // Otherwise Champion always picks experience chance = 100; } } else if ( kingdomGold < 3000 ) { chance = ( role == Heroes::Role::FIGHTER && experience >= 1500 ) ? 10 : 0; } else { uint32_t value = ( experience > 500 ) ? experience - 500 : 0; if ( role == Heroes::Role::FIGHTER ) { value += 500; } chance = value / 15; // 33% for every 500 experience } if ( chance ) { const uint32_t randomRoll = Rand::Get( 1, 100 ); if ( randomRoll <= chance ) { gold = 0; hero.IncreaseExperience( experience ); } } } else if ( art.isValid() && !hero.PickupArtifact( art ) ) { gold = GoldInsteadArtifact( objectType ); } } if ( gold ) { kingdom.AddFundsResource( Funds( Resource::GOLD, gold ) ); } removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); } void AIToCaptureObject( Heroes & hero, const MP2::MapObjectType objectType, const int32_t dstIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " object: " << MP2::StringObject( objectType ) ) #ifndef WITH_DEBUG (void)objectType; #endif Maps::Tile & tile = world.getTile( dstIndex ); if ( !hero.isFriends( getColorFromTile( tile ) ) ) { const auto removeObjectProtection = [&tile]() { // Clear any metadata related to spells if ( tile.getMainObjectType( false ) == MP2::OBJ_MINE ) { removeMineSpellFromTile( tile ); } }; const auto captureObject = [&hero, &tile, &removeObjectProtection]() { removeObjectProtection(); setColorOnTile( tile, hero.GetColor() ); }; if ( isCaptureObjectProtected( tile ) ) { Army army( tile ); const Battle::Result result = Battle::Loader( hero.GetArmy(), army, dstIndex ); if ( result.AttackerWins() ) { hero.IncreaseExperience( result.GetExperienceAttacker() ); captureObject(); } else { // The army should include only the original monsters const uint32_t monstersLeft = army.getTotalCount(); assert( monstersLeft == army.GetCountMonsters( getMonsterFromTile( tile ) ) ); Troop & troop = world.GetCapturedObject( dstIndex ).GetTroop(); troop.SetCount( monstersLeft ); // If all the guards are defeated, but the hero has lost the battle, // just remove the protection from the object if ( monstersLeft == 0 ) { removeObjectProtection(); } AIBattleLose( hero, result, true ); } } else { captureObject(); } } } void AIToObjectResource( const Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) // TODO: remove this temporary assertion and 'defined( NDEBUG )' condition below assert( !MP2::isCaptureObject( objectType ) ); #if defined( NDEBUG ) && !defined( WITH_DEBUG ) (void)objectType; #endif Maps::Tile & tile = world.getTile( dst_index ); hero.GetKingdom().AddFundsResource( getFundsFromTile( tile ) ); resetObjectMetadata( tile ); hero.setVisitedForAllies( dst_index ); } void AIToSkeleton( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::Tile & tile = world.getTile( dst_index ); if ( doesTileContainValuableItems( tile ) ) { const Artifact & art = getArtifactFromTile( tile ); if ( !hero.PickupArtifact( art ) ) { const uint32_t gold = GoldInsteadArtifact( objectType ); hero.GetKingdom().AddFundsResource( Funds( Resource::GOLD, gold ) ); } resetObjectMetadata( tile ); } hero.SetVisitedWideTile( dst_index, objectType, Visit::GLOBAL ); } void AIToWagon( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::Tile & tile = world.getTile( dst_index ); if ( doesTileContainValuableItems( tile ) ) { const Artifact & art = getArtifactFromTile( tile ); if ( art.isValid() ) hero.PickupArtifact( art ); else hero.GetKingdom().AddFundsResource( getFundsFromTile( tile ) ); resetObjectMetadata( tile ); } hero.SetVisited( dst_index, Visit::GLOBAL ); } void AIToFlotSam( const Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::Tile & tile = world.getTile( dst_index ); hero.GetKingdom().AddFundsResource( getFundsFromTile( tile ) ); removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); } void AIToSign( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) hero.SetVisited( dst_index, Visit::GLOBAL ); } void AIToObservationTower( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::ClearFog( dst_index, GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::OBSERVATION_TOWER ), hero.GetColor() ); hero.SetVisited( dst_index, Visit::GLOBAL ); } void AIToMagellanMaps( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const Funds payment = PaymentConditions::getMagellansMapsPurchasePrice(); Kingdom & kingdom = hero.GetKingdom(); if ( !hero.isObjectTypeVisited( MP2::OBJ_MAGELLANS_MAPS, Visit::GLOBAL ) && kingdom.AllowPayment( payment ) ) { hero.SetVisited( dst_index, Visit::GLOBAL ); hero.setVisitedForAllies( dst_index ); world.ActionForMagellanMaps( hero.GetColor() ); if ( Players::isFriends( hero.GetColor(), Players::HumanColors() ) ) { // Fully update fog directions if AI player is an ally. Interface::GameArea::updateMapFogDirections(); } kingdom.OddFundsResource( payment ); } } void AIToTeleports( Heroes & hero, const int32_t startIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) assert( hero.GetPath().empty() ); const int32_t indexTo = world.NextTeleport( startIndex ); if ( startIndex == indexTo ) { DEBUG_LOG( DBG_AI, DBG_WARN, "AI hero " << hero.GetName() << " has nowhere to go through stone liths" ) return; } assert( world.getTile( indexTo ).getMainObjectType() != MP2::OBJ_HERO ); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { // AI-controlled hero cannot activate Stone Liths from the same tile, but should move to this tile from some // other tile first, so there is no need to re-center the game area on the hero before his disappearance hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( indexTo ); hero.Move2Dest( indexTo ); hero.GetPath().Reset(); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } hero.ActionNewPosition( false ); } void AIWhirlpoolTroopLoseEffect( Heroes & hero ) { Army & heroArmy = hero.GetArmy(); // Arrange the hero's army for the passage of the whirlpool first heroArmy.ArrangeForWhirlpool(); Troop * weakestTroop = heroArmy.GetWeakestTroop(); assert( weakestTroop != nullptr ); if ( weakestTroop == nullptr ) { return; } // Whirlpool effect affects heroes only with more than one creature in more than one slot if ( heroArmy.GetOccupiedSlotCount() == 1 && weakestTroop->GetCount() == 1 ) { return; } if ( 1 == Rand::Get( 1, 3 ) ) { if ( weakestTroop->GetCount() == 1 ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " lost " << weakestTroop->GetCount() << " " << weakestTroop->GetName() << " in the whirlpool" ) weakestTroop->Reset(); } else { const uint32_t newCount = Monster::GetCountFromHitPoints( weakestTroop->GetID(), weakestTroop->GetHitPoints() - weakestTroop->GetHitPoints() * Game::GetWhirlpoolPercent() / 100 ); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " lost " << weakestTroop->GetCount() - newCount << " " << weakestTroop->GetName() << " in the whirlpool" ) weakestTroop->SetCount( newCount ); } } } void AIToWhirlpools( Heroes & hero, const int32_t startIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) assert( hero.GetPath().empty() ); const int32_t indexTo = world.NextWhirlpool( startIndex ); if ( startIndex == indexTo ) { DEBUG_LOG( DBG_AI, DBG_WARN, "AI hero " << hero.GetName() << " has nowhere to go through the whirlpool" ) return; } if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { // AI-controlled hero cannot activate Whirlpool from the same tile, but should move to this tile from some // other tile first, so there is no need to re-center the game area on the hero before his disappearance hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( indexTo ); hero.Move2Dest( indexTo ); hero.GetPath().Reset(); AIWhirlpoolTroopLoseEffect( hero ); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } hero.ActionNewPosition( false ); } void AIToPrimarySkillObject( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) const Maps::Tile & tile = world.getTile( dst_index ); int skill = Skill::Primary::UNKNOWN; switch ( objectType ) { case MP2::OBJ_FORT: skill = Skill::Primary::DEFENSE; break; case MP2::OBJ_MERCENARY_CAMP: skill = Skill::Primary::ATTACK; break; case MP2::OBJ_WITCH_DOCTORS_HUT: skill = Skill::Primary::KNOWLEDGE; break; case MP2::OBJ_STANDING_STONES: skill = Skill::Primary::POWER; break; case MP2::OBJ_ARENA: skill = AISelectSkillFromArena( hero ); break; default: break; } if ( ( MP2::OBJ_ARENA == objectType && !hero.isObjectTypeVisited( objectType ) ) || !hero.isVisited( tile ) ) { // increase skill hero.IncreasePrimarySkill( skill ); hero.SetVisited( dst_index ); // fix double action tile hero.SetVisitedWideTile( dst_index, objectType ); } } void AIToExperienceObject( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) const Maps::Tile & tile = world.getTile( dst_index ); uint32_t exp = 0; switch ( objectType ) { case MP2::OBJ_GAZEBO: exp = 1000; break; default: break; } // check already visited if ( !hero.isVisited( tile ) && exp ) { hero.SetVisited( dst_index ); hero.IncreaseExperience( exp ); } } void AIToWitchsHut( Heroes & hero, const int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const Skill::Secondary & skill = getSecondarySkillFromWitchsHut( world.getTile( dst_index ) ); if ( skill.isValid() ) { if ( !hero.HasMaxSecondarySkill() && !hero.HasSecondarySkill( skill.Skill() ) ) { hero.LearnSkill( skill ); if ( skill.Skill() == Skill::Secondary::SCOUTING ) { hero.Scout( hero.GetIndex() ); } } } else { // A broken object? assert( 0 ); } // It is important to mark it globally so other heroes will know about the object. hero.SetVisited( dst_index, Visit::GLOBAL ); } void AIToShrine( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const Spell & spell = getSpellFromTile( world.getTile( dst_index ) ); assert( spell.isValid() ); if ( hero.HaveSpellBook() && !hero.HaveSpell( spell, true ) && // check valid level spell and wisdom skill !( 3 == spell.Level() && Skill::Level::NONE == hero.GetLevelSkill( Skill::Secondary::WISDOM ) ) ) { hero.AppendSpellToBook( spell ); } // All heroes will know which spell is here. hero.SetVisited( dst_index, Visit::GLOBAL ); } void AIToGoodLuckObject( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) hero.SetVisited( dst_index ); } void AIToGoodMoraleObject( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) uint32_t move = 0; switch ( objectType ) { case MP2::OBJ_OASIS: move = GameStatic::getMovementPointBonus( MP2::OBJ_OASIS ); break; case MP2::OBJ_WATERING_HOLE: move = GameStatic::getMovementPointBonus( MP2::OBJ_WATERING_HOLE ); break; default: break; } // check already visited if ( !hero.isObjectTypeVisited( objectType ) ) { // modify morale hero.SetVisited( dst_index ); if ( move ) hero.IncreaseMovePoints( move ); // fix double action tile hero.SetVisitedWideTile( dst_index, objectType ); } } void AIToMagicWell( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const uint32_t max = hero.GetMaxSpellPoints(); if ( hero.GetSpellPoints() < max && !hero.isObjectTypeVisited( MP2::OBJ_MAGIC_WELL ) ) { hero.SetSpellPoints( max ); } hero.SetVisited( dst_index ); } void AIToArtesianSpring( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const uint32_t max = hero.GetMaxSpellPoints(); if ( !world.isAnyKingdomVisited( objectType, dst_index ) && hero.GetSpellPoints() < max * 2 ) { hero.SetSpellPoints( max * 2 ); } hero.SetVisitedWideTile( dst_index, objectType, Visit::GLOBAL ); } void AIToXanadu( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const Maps::Tile & tile = world.getTile( dst_index ); if ( !hero.isVisited( tile ) && GameStatic::isHeroWorthyToVisitXanadu( hero ) ) { hero.IncreasePrimarySkill( Skill::Primary::ATTACK ); hero.IncreasePrimarySkill( Skill::Primary::DEFENSE ); hero.IncreasePrimarySkill( Skill::Primary::KNOWLEDGE ); hero.IncreasePrimarySkill( Skill::Primary::POWER ); hero.SetVisited( dst_index ); } } void AIToEvent( Heroes & hero, const int32_t tileIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) MapEvent * mapEvent = world.GetMapEvent( Maps::GetPoint( tileIndex ) ); if ( mapEvent == nullptr ) { DEBUG_LOG( DBG_AI, DBG_INFO, "Adventure Map event at index " << tileIndex << " is missing!" ) return; } if ( !mapEvent->isComputerPlayerAllowed || !mapEvent->isAllow( hero.GetColor() ) ) { return; } hero.GetKingdom().AddFundsResource( mapEvent->resources ); hero.PickupArtifact( mapEvent->artifact ); const auto & skill = mapEvent->secondarySkill; if ( skill.isValid() ) { bool addSkill = false; if ( hero.HasSecondarySkill( skill.Skill() ) ) { addSkill = ( hero.GetSecondarySkills().GetLevel( skill.Skill() ) < skill.Level() ); } else { addSkill = !hero.HasMaxSecondarySkill(); } if ( addSkill ) { hero.LearnSkill( skill ); if ( skill.Skill() == Skill::Secondary::SCOUTING ) { hero.Scout( hero.GetIndex() ); } } } if ( mapEvent->experience > 0 ) { hero.IncreaseExperience( static_cast( mapEvent->experience ) ); } mapEvent->SetVisited(); if ( mapEvent->isSingleTimeEvent ) { hero.setObjectTypeUnderHero( MP2::OBJ_NONE ); world.RemoveMapObject( mapEvent ); } } void AIToUpgradeArmyObject( Heroes & hero, const MP2::MapObjectType objectType, int32_t /*dst_index*/ ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) switch ( objectType ) { case MP2::OBJ_HILL_FORT: { Army & army = hero.GetArmy(); if ( army.HasMonster( Monster::DWARF ) ) { army.UpgradeMonsters( Monster::DWARF ); } if ( army.HasMonster( Monster::ORC ) ) { army.UpgradeMonsters( Monster::ORC ); } if ( army.HasMonster( Monster::OGRE ) ) { army.UpgradeMonsters( Monster::OGRE ); } break; } case MP2::OBJ_FREEMANS_FOUNDRY: { Army & army = hero.GetArmy(); if ( army.HasMonster( Monster::PIKEMAN ) ) { army.UpgradeMonsters( Monster::PIKEMAN ); } if ( army.HasMonster( Monster::SWORDSMAN ) ) { army.UpgradeMonsters( Monster::SWORDSMAN ); } if ( army.HasMonster( Monster::IRON_GOLEM ) ) { army.UpgradeMonsters( Monster::IRON_GOLEM ); } break; } default: break; } } void AIToPoorMoraleObject( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) assert( hero.GetIndex() == dst_index || MP2::isNeedStayFront( objectType ) ); if ( !AI::Planner::Get().isValidHeroObject( hero, dst_index, ( hero.GetIndex() == dst_index ) ) ) { if ( MP2::isNeedStayFront( objectType ) ) { // If we can't step on this tile, then we shouldn't be here at all, but we can still end up here due to inaccuracies in the hero's strength assessment at // the starting point of his path (for example, if the hero's starting point was in a castle, then the castle's bonuses could affect the assessment of his // strength) DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " does not interact with the object and ignores it" ) } else { // We're just passing through here, don't mess with this object DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " passes through without interacting with the object" ) } return; } Maps::Tile & tile = world.getTile( dst_index ); const Funds funds = getFundsFromTile( tile ); assert( funds.gold > 0 || funds.GetValidItemsCount() == 0 ); uint32_t gold = funds.gold; bool complete = false; if ( gold ) { Army army( tile ); const Battle::Result res = Battle::Loader( hero.GetArmy(), army, dst_index ); if ( res.AttackerWins() ) { hero.IncreaseExperience( res.GetExperienceAttacker() ); complete = true; Artifact art; if ( isArtifactObject( objectType ) ) { art = getArtifactFromTile( tile ); } if ( art.isValid() && !hero.PickupArtifact( art ) ) { gold = GoldInsteadArtifact( objectType ); } hero.GetKingdom().AddFundsResource( Funds( Resource::GOLD, gold ) ); } else { AIBattleLose( hero, res, true ); } } if ( complete ) { resetObjectMetadata( tile ); } else if ( 0 == gold && !hero.isObjectTypeVisited( objectType ) ) { // Modify morale hero.SetVisited( dst_index ); hero.SetVisited( dst_index, Visit::GLOBAL ); } } void AIToPyramid( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) assert( hero.GetIndex() == dst_index ); if ( !AI::Planner::Get().isValidHeroObject( hero, dst_index, ( hero.GetIndex() == dst_index ) ) ) { // We're just passing through here, don't mess with this object DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " passes through without interacting with the object" ) return; } Maps::Tile & tile = world.getTile( dst_index ); const Spell & spell = getSpellFromTile( tile ); if ( spell.isValid() ) { // battle Army army( tile ); const Battle::Result res = Battle::Loader( hero.GetArmy(), army, dst_index ); if ( res.AttackerWins() ) { hero.IncreaseExperience( res.GetExperienceAttacker() ); // check magic book if ( hero.HaveSpellBook() && // check skill level for wisdom Skill::Level::EXPERT == hero.GetLevelSkill( Skill::Secondary::WISDOM ) ) { hero.AppendSpellToBook( spell ); } resetObjectMetadata( tile ); hero.SetVisited( dst_index, Visit::GLOBAL ); } else { AIBattleLose( hero, res, true ); } } else { hero.SetVisited( dst_index, Visit::LOCAL ); hero.SetVisited( dst_index, Visit::GLOBAL ); } } void AIToObelisk( Heroes & hero, const Maps::Tile & tile ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) if ( !hero.isVisited( tile, Visit::GLOBAL ) ) { hero.SetVisited( tile.GetIndex(), Visit::GLOBAL ); Kingdom & kingdom = hero.GetKingdom(); kingdom.PuzzleMaps().Update( kingdom.CountVisitedObjects( MP2::OBJ_OBELISK ), world.CountObeliskOnMaps() ); // TODO: once any piece of the puzzle is open and the area is discovered and a hero has nothing to do make him dig around this area. // TODO: once all pieces are open add a special condition to make AI to dig the Ultimate artifact. // TODO: do not dig for an Ultimate artifact if the winning condition of the map is to find this artifact. } } void AIToTreeKnowledge( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const Maps::Tile & tile = world.getTile( dst_index ); if ( !hero.isVisited( tile ) ) { const Funds & payment = getTreeOfKnowledgeRequirement( tile ); if ( 0 == payment.GetValidItemsCount() || hero.GetKingdom().AllowPayment( payment ) ) { const int level = hero.GetLevel(); assert( level > 0 ); const uint32_t experience = Heroes::GetExperienceFromLevel( level ) - Heroes::GetExperienceFromLevel( level - 1 ); hero.GetKingdom().OddFundsResource( payment ); hero.SetVisited( dst_index ); hero.IncreaseExperience( experience ); } } } void AIToDaemonCave( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) assert( hero.GetIndex() == dst_index ); if ( !AI::Planner::Get().isValidHeroObject( hero, dst_index, ( hero.GetIndex() == dst_index ) ) ) { // We're just passing through here, don't mess with this object DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " passes through without interacting with the object" ) return; } Maps::Tile & tile = world.getTile( dst_index ); if ( doesTileContainValuableItems( tile ) ) { Army army( tile ); const Battle::Result res = Battle::Loader( hero.GetArmy(), army, dst_index ); if ( res.AttackerWins() ) { hero.IncreaseExperience( res.GetExperienceAttacker() ); // Daemon Cave always gives 2500 Gold after a battle hero.GetKingdom().AddFundsResource( Funds( Resource::GOLD, 2500 ) ); } else { AIBattleLose( hero, res, true ); } resetObjectMetadata( tile ); } } void AIToDwellingJoinMonster( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::Tile & tile = world.getTile( dst_index ); const Troop & troop = getTroopFromTile( tile ); if ( !troop.isValid() ) { return; } if ( !canMonsterJoinHero( troop, hero ) ) { return; } if ( !hero.GetArmy().JoinTroop( troop ) ) { // How is it possible that an army has free slots but monsters cannot join it? assert( 0 ); return; } setMonsterCountOnTile( tile, 0 ); } void AIToDwellingRecruitMonster( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) Maps::Tile & tile = world.getTile( dst_index ); const Troop & troop = getTroopFromTile( tile ); if ( !troop.isValid() ) { return; } Kingdom & kingdom = hero.GetKingdom(); const Funds singleMonsterCost = troop.GetCost(); uint32_t recruitTroopCount = kingdom.GetFunds().getLowestQuotient( singleMonsterCost ); if ( recruitTroopCount <= 0 ) { // We do not have resources to hire even a single creature. return; } const uint32_t availableTroopCount = troop.GetCount(); if ( recruitTroopCount > availableTroopCount ) { recruitTroopCount = availableTroopCount; } const Troop troopToHire{ troop.GetID(), recruitTroopCount }; if ( !canMonsterJoinHero( troopToHire, hero ) ) { return; } if ( !hero.GetArmy().JoinTroop( troopToHire ) ) { // How is it possible that an army has free slots but monsters cannot join it? assert( 0 ); return; } setMonsterCountOnTile( tile, availableTroopCount - recruitTroopCount ); kingdom.OddFundsResource( troopToHire.GetTotalCost() ); // Remove genie lamp sprite if no genies are available to hire. if ( MP2::OBJ_GENIE_LAMP == objectType && ( availableTroopCount == recruitTroopCount ) ) { removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); } } void AIToDwellingBattleMonster( Heroes & hero, const MP2::MapObjectType objectType, const int32_t tileIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ", object: " << MP2::StringObject( objectType ) ) assert( hero.GetIndex() == tileIndex ); if ( !AI::Planner::Get().isValidHeroObject( hero, tileIndex, ( hero.GetIndex() == tileIndex ) ) ) { // We're just passing through here, don't mess with this object DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " passes through without interacting with the object" ) return; } Maps::Tile & tile = world.getTile( tileIndex ); bool recruitmentAllowed = true; if ( getColorFromTile( tile ) == Color::NONE ) { Army army( tile ); const Battle::Result res = Battle::Loader( hero.GetArmy(), army, tileIndex ); if ( res.AttackerWins() ) { hero.IncreaseExperience( res.GetExperienceAttacker() ); // Set ownership of the dwelling to a Neutral (gray) player so that any player can recruit troops without a fight. setColorOnTile( tile, Color::UNUSED ); } else { AIBattleLose( hero, res, true ); recruitmentAllowed = false; } } if ( recruitmentAllowed ) { const Troop troop = getTroopFromTile( tile ); if ( troop.isValid() ) { AIToDwellingRecruitMonster( hero, objectType, tileIndex ); } hero.SetVisited( tileIndex, Visit::GLOBAL ); } } void AIToStables( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) if ( !hero.isObjectTypeVisited( objectType ) ) { hero.SetVisited( dst_index ); hero.IncreaseMovePoints( GameStatic::getMovementPointBonus( MP2::OBJ_STABLES ) ); } if ( hero.GetArmy().HasMonster( Monster::CAVALRY ) ) { hero.GetArmy().UpgradeMonsters( Monster::CAVALRY ); } } void AIToAbandonedMine( Heroes & hero, const int32_t dstIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) assert( hero.GetIndex() == dstIndex ); if ( !AI::Planner::Get().isValidHeroObject( hero, dstIndex, ( hero.GetIndex() == dstIndex ) ) ) { // We're just passing through here, don't mess with this object DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " passes through without interacting with the object" ) return; } Maps::Tile & tile = world.getTile( dstIndex ); Army army( tile ); const Battle::Result result = Battle::Loader( hero.GetArmy(), army, dstIndex ); if ( result.AttackerWins() ) { hero.IncreaseExperience( result.GetExperienceAttacker() ); Maps::restoreAbandonedMine( tile, Resource::GOLD ); hero.setObjectTypeUnderHero( MP2::OBJ_MINE ); setColorOnTile( tile, hero.GetColor() ); } else { AIBattleLose( hero, result, true ); } } void AIToBarrier( const Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::Tile & tile = world.getTile( dst_index ); const Kingdom & kingdom = hero.GetKingdom(); if ( kingdom.IsVisitTravelersTent( getColorFromTile( tile ) ) ) { removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); } } void AIToTravellersTent( const Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const Maps::Tile & tile = world.getTile( dst_index ); Kingdom & kingdom = hero.GetKingdom(); kingdom.SetVisitTravelersTent( getColorFromTile( tile ) ); } void AIToShipwreckSurvivor( Heroes & hero, const MP2::MapObjectType objectType, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) Maps::Tile & tile = world.getTile( dst_index ); if ( hero.IsFullBagArtifacts() ) hero.GetKingdom().AddFundsResource( Funds( Resource::GOLD, GoldInsteadArtifact( objectType ) ) ); else hero.PickupArtifact( getArtifactFromTile( tile ) ); removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); } void AIToArtifact( Heroes & hero, int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) if ( hero.IsFullBagArtifacts() ) { return; } Maps::Tile & tile = world.getTile( dst_index ); const Artifact art = getArtifactFromTile( tile ); if ( art.GetID() == Artifact::MAGIC_BOOK && hero.HaveSpellBook() ) { return; } const Maps::ArtifactCaptureCondition condition = getArtifactCaptureCondition( tile ); bool result = false; if ( condition == Maps::ArtifactCaptureCondition::PAY_2000_GOLD || condition == Maps::ArtifactCaptureCondition::PAY_2500_GOLD_AND_3_RESOURCES || condition == Maps::ArtifactCaptureCondition::PAY_3000_GOLD_AND_5_RESOURCES ) { const Funds payment = getArtifactResourceRequirement( tile ); if ( hero.GetKingdom().AllowPayment( payment ) ) { result = true; hero.GetKingdom().OddFundsResource( payment ); } } else if ( condition == Maps::ArtifactCaptureCondition::HAVE_WISDOM_SKILL || condition == Maps::ArtifactCaptureCondition::HAVE_LEADERSHIP_SKILL ) { // TODO: do we need to check this condition? result = true; } else if ( condition >= Maps::ArtifactCaptureCondition::FIGHT_50_ROGUES && condition <= Maps::ArtifactCaptureCondition::FIGHT_1_BONE_DRAGON ) { Army army( tile ); const Battle::Result res = Battle::Loader( hero.GetArmy(), army, dst_index ); if ( res.AttackerWins() ) { hero.IncreaseExperience( res.GetExperienceAttacker() ); result = true; } else { AIBattleLose( hero, res, true ); } } else { result = true; } if ( result && hero.PickupArtifact( art ) ) { removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); } } void AIToBoat( Heroes & hero, const int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) if ( hero.isShipMaster() ) { return; } hero.setLastGroundRegion( world.getTile( hero.GetIndex() ).GetRegion() ); // Get the direction of the boat so that the direction of the hero can be set to it after boarding Maps::Tile & destinationTile = world.getTile( dst_index ); const int boatDirection = destinationTile.getBoatDirection(); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); hero.FadeOut( Game::AIHeroAnimSpeedMultiplier(), Maps::GetPoint( dst_index ) - hero.GetCenter() ); } hero.Scout( dst_index ); hero.Move2Dest( dst_index ); hero.ResetMovePoints(); hero.GetPath().Reset(); // Set the direction of the hero to the one of the boat as the boat does not move when boarding it hero.setDirection( boatDirection ); // Remove boat object information from the tile. destinationTile.resetMainObjectPart(); // Update tile's object type if any object exists after removing the boat. destinationTile.updateObjectType(); // Set the newly updated object type to hero to remember it. // It is needed in case of moving out from this tile and restoring the tile's original object type. hero.setObjectTypeUnderHero( destinationTile.getMainObjectType( true ) ); // Set the tile's object type as Hero. destinationTile.setMainObjectType( MP2::OBJ_HERO ); hero.SetShipMaster( true ); // Boat is no longer empty so we reset color to default destinationTile.resetBoatOwnerColor(); } void AIToCoast( Heroes & hero, const int32_t dst_index ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) if ( !hero.isShipMaster() ) { return; } const int fromIndex = hero.GetIndex(); Maps::Tile & from = world.getTile( fromIndex ); // Calculate the offset before making the action. const fheroes2::Point prevPos = hero.GetCenter(); hero.Scout( dst_index ); hero.Move2Dest( dst_index ); hero.ResetMovePoints(); hero.GetPath().Reset(); from.setBoat( Maps::GetDirection( fromIndex, dst_index ), hero.GetColor() ); hero.SetShipMaster( false ); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( prevPos ); hero.FadeIn( Game::AIHeroAnimSpeedMultiplier(), Maps::GetPoint( dst_index ) - prevPos ); } hero.ActionNewPosition( true ); } void AIToJail( const Heroes & hero, const int32_t tileIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) const Kingdom & kingdom = hero.GetKingdom(); if ( kingdom.GetHeroes().size() < Kingdom::GetMaxHeroes() ) { Maps::Tile & tile = world.getTile( tileIndex ); removeMainObjectFromTile( tile ); resetObjectMetadata( tile ); Heroes * prisoner = world.FromJailHeroes( tileIndex ); if ( prisoner ) { prisoner->Recruit( hero.GetColor(), Maps::GetPoint( tileIndex ) ); AI::OptimizeTroopsOrder( prisoner->GetArmy() ); } } } void AIToHutMagi( Heroes & hero, const MP2::MapObjectType objectType, const int32_t tileIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) if ( !hero.isObjectTypeVisited( objectType, Visit::GLOBAL ) ) { hero.SetVisited( tileIndex, Visit::GLOBAL ); const auto & eyeMagiIndexes = world.getAllEyeOfMagiPositions(); const uint32_t distance = GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::MAGI_EYES ); for ( const int32_t index : eyeMagiIndexes ) { Maps::ClearFog( index, distance, hero.GetColor() ); } } } void AIToAlchemistTower( Heroes & hero ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) BagArtifacts & bag = hero.GetBagArtifacts(); const uint32_t cursed = static_cast( std::count_if( bag.begin(), bag.end(), []( const Artifact & art ) { return art.containsCurses(); } ) ); if ( cursed == 0 ) { return; } const Funds payment = PaymentConditions::ForAlchemist(); if ( hero.GetKingdom().AllowPayment( payment ) ) { hero.GetKingdom().OddFundsResource( payment ); for ( Artifact & artifact : bag ) { if ( artifact.containsCurses() ) { artifact = Artifact::UNKNOWN; } } } DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " removed " << cursed << " artifacts" ) } void AIToSirens( Heroes & hero, const MP2::MapObjectType objectType, const int32_t objectIndex ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) if ( hero.isObjectTypeVisited( objectType ) ) { return; } const uint32_t experience = hero.GetArmy().ActionToSirens(); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " got " << experience << " experience" ) hero.IncreaseExperience( experience ); hero.SetVisited( objectIndex ); } void AIToTradingPost( const Heroes & hero ) { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() ) #ifndef WITH_DEBUG (void)hero; #endif } } void AI::HeroesAction( Heroes & hero, const int32_t dst_index ) { const Heroes::AIHeroMeetingUpdater heroMeetingUpdater( hero ); const Maps::Tile & tile = world.getTile( dst_index ); const MP2::MapObjectType objectType = tile.getMainObjectType( dst_index != hero.GetIndex() ); const bool isActionObject = MP2::isInGameActionObject( objectType, hero.isShipMaster() ); if ( isActionObject ) hero.SetModes( Heroes::ACTION ); switch ( objectType ) { case MP2::OBJ_BOAT: AIToBoat( hero, dst_index ); break; case MP2::OBJ_COAST: // Coast is not an action object by definition but we need to do hero's animation. AIToCoast( hero, dst_index ); break; case MP2::OBJ_MONSTER: AIToMonster( hero, dst_index ); break; case MP2::OBJ_HERO: AIToHeroes( hero, dst_index ); break; case MP2::OBJ_CASTLE: AIToCastle( hero, dst_index ); break; // pickup object case MP2::OBJ_BOTTLE: case MP2::OBJ_CAMPFIRE: case MP2::OBJ_RESOURCE: AIToPickupResource( hero, objectType, dst_index ); break; case MP2::OBJ_SEA_CHEST: case MP2::OBJ_TREASURE_CHEST: AIToTreasureChest( hero, objectType, dst_index ); break; case MP2::OBJ_ARTIFACT: AIToArtifact( hero, dst_index ); break; case MP2::OBJ_LEAN_TO: case MP2::OBJ_MAGIC_GARDEN: case MP2::OBJ_WINDMILL: case MP2::OBJ_WATER_WHEEL: AIToObjectResource( hero, objectType, dst_index ); break; case MP2::OBJ_WAGON: AIToWagon( hero, dst_index ); break; case MP2::OBJ_SKELETON: AIToSkeleton( hero, objectType, dst_index ); break; case MP2::OBJ_FLOTSAM: AIToFlotSam( hero, dst_index ); break; case MP2::OBJ_ALCHEMIST_LAB: case MP2::OBJ_MINE: case MP2::OBJ_SAWMILL: case MP2::OBJ_LIGHTHOUSE: AIToCaptureObject( hero, objectType, dst_index ); break; case MP2::OBJ_ABANDONED_MINE: AIToAbandonedMine( hero, dst_index ); break; case MP2::OBJ_SHIPWRECK_SURVIVOR: AIToShipwreckSurvivor( hero, objectType, dst_index ); break; // event case MP2::OBJ_EVENT: AIToEvent( hero, dst_index ); break; case MP2::OBJ_SIGN: AIToSign( hero, dst_index ); break; // increase view case MP2::OBJ_OBSERVATION_TOWER: AIToObservationTower( hero, dst_index ); break; case MP2::OBJ_MAGELLANS_MAPS: AIToMagellanMaps( hero, dst_index ); break; // teleports case MP2::OBJ_STONE_LITHS: AIToTeleports( hero, dst_index ); break; case MP2::OBJ_WHIRLPOOL: AIToWhirlpools( hero, dst_index ); break; // primary skill modification case MP2::OBJ_FORT: case MP2::OBJ_MERCENARY_CAMP: case MP2::OBJ_WITCH_DOCTORS_HUT: case MP2::OBJ_STANDING_STONES: case MP2::OBJ_ARENA: AIToPrimarySkillObject( hero, objectType, dst_index ); break; // experience modification case MP2::OBJ_GAZEBO: AIToExperienceObject( hero, objectType, dst_index ); break; // Witch's hut case MP2::OBJ_WITCHS_HUT: AIToWitchsHut( hero, dst_index ); break; // shrine circle case MP2::OBJ_SHRINE_FIRST_CIRCLE: case MP2::OBJ_SHRINE_SECOND_CIRCLE: case MP2::OBJ_SHRINE_THIRD_CIRCLE: AIToShrine( hero, dst_index ); break; // luck modification case MP2::OBJ_FOUNTAIN: case MP2::OBJ_FAERIE_RING: case MP2::OBJ_IDOL: case MP2::OBJ_MERMAID: AIToGoodLuckObject( hero, dst_index ); break; // morale modification case MP2::OBJ_OASIS: case MP2::OBJ_TEMPLE: case MP2::OBJ_WATERING_HOLE: case MP2::OBJ_BUOY: AIToGoodMoraleObject( hero, objectType, dst_index ); break; case MP2::OBJ_OBELISK: AIToObelisk( hero, tile ); break; // magic point case MP2::OBJ_ARTESIAN_SPRING: AIToArtesianSpring( hero, objectType, dst_index ); break; case MP2::OBJ_MAGIC_WELL: AIToMagicWell( hero, dst_index ); break; // increase skill case MP2::OBJ_XANADU: AIToXanadu( hero, dst_index ); break; case MP2::OBJ_HILL_FORT: case MP2::OBJ_FREEMANS_FOUNDRY: AIToUpgradeArmyObject( hero, objectType, dst_index ); break; case MP2::OBJ_SHIPWRECK: case MP2::OBJ_GRAVEYARD: case MP2::OBJ_DERELICT_SHIP: AIToPoorMoraleObject( hero, objectType, dst_index ); break; case MP2::OBJ_PYRAMID: AIToPyramid( hero, dst_index ); break; case MP2::OBJ_DAEMON_CAVE: AIToDaemonCave( hero, dst_index ); break; case MP2::OBJ_TREE_OF_KNOWLEDGE: AIToTreeKnowledge( hero, dst_index ); break; // accept army case MP2::OBJ_WATCH_TOWER: case MP2::OBJ_EXCAVATION: case MP2::OBJ_CAVE: case MP2::OBJ_TREE_HOUSE: case MP2::OBJ_ARCHER_HOUSE: case MP2::OBJ_GOBLIN_HUT: case MP2::OBJ_DWARF_COTTAGE: case MP2::OBJ_HALFLING_HOLE: case MP2::OBJ_PEASANT_HUT: AIToDwellingJoinMonster( hero, dst_index ); break; // recruit army case MP2::OBJ_RUINS: case MP2::OBJ_TREE_CITY: case MP2::OBJ_WAGON_CAMP: case MP2::OBJ_DESERT_TENT: case MP2::OBJ_GENIE_LAMP: // loyalty version objects case MP2::OBJ_WATER_ALTAR: case MP2::OBJ_AIR_ALTAR: case MP2::OBJ_FIRE_ALTAR: case MP2::OBJ_EARTH_ALTAR: case MP2::OBJ_BARROW_MOUNDS: AIToDwellingRecruitMonster( hero, objectType, dst_index ); break; // recruit army (battle) case MP2::OBJ_DRAGON_CITY: case MP2::OBJ_CITY_OF_DEAD: case MP2::OBJ_TROLL_BRIDGE: AIToDwellingBattleMonster( hero, objectType, dst_index ); break; case MP2::OBJ_STABLES: AIToStables( hero, objectType, dst_index ); break; case MP2::OBJ_BARRIER: AIToBarrier( hero, dst_index ); break; case MP2::OBJ_TRAVELLER_TENT: AIToTravellersTent( hero, dst_index ); break; case MP2::OBJ_JAIL: AIToJail( hero, dst_index ); break; case MP2::OBJ_HUT_OF_MAGI: AIToHutMagi( hero, objectType, dst_index ); break; case MP2::OBJ_ALCHEMIST_TOWER: AIToAlchemistTower( hero ); break; case MP2::OBJ_TRADING_POST: AIToTradingPost( hero ); break; // AI has no advantage or knowledge to use these objects case MP2::OBJ_ORACLE: case MP2::OBJ_EYE_OF_MAGI: case MP2::OBJ_SPHINX: break; case MP2::OBJ_SIRENS: // AI must have some action even if it goes on this object by mistake. AIToSirens( hero, objectType, dst_index ); break; default: // AI should know what to do with this type of action object! Please add logic for it. assert( !isActionObject ); break; } if ( MP2::isNeedStayFront( objectType ) ) hero.GetPath().Reset(); // Ignore empty tiles if ( isActionObject ) { AI::Planner::Get().HeroesActionComplete( hero, dst_index, objectType ); } } void AI::HeroesMove( Heroes & hero ) { const Route::Path & path = hero.GetPath(); if ( path.isValidForTeleportation() ) { const int32_t targetIndex = path.GetFrontIndex(); // At the moment, this kind of movement using regular paths generated by AI pathfinder is only possible to the // towns/castles with the use of Town Gate or Town Portal spells assert( path.GetFrontFrom() != targetIndex && world.getTile( targetIndex ).getMainObjectType() == MP2::OBJ_CASTLE ); AITownPortal( hero, targetIndex ); // This is the end of a this hero's movement, even if the hero's full path doesn't end in this town or castle. // The further path of this hero will be re-planned by AI. return; } if ( !path.isValidForMovement() ) { return; } hero.SetMove( true ); Interface::AdventureMap & adventureMapInterface = Interface::AdventureMap::Get(); Interface::GameArea & gameArea = adventureMapInterface.getGameArea(); const Settings & conf = Settings::Get(); const uint32_t colors = AIGetAllianceColors(); bool recenterNeeded = true; int heroAnimationFrameCount = 0; fheroes2::Point heroAnimationOffset; int heroAnimationSpriteId = 0; const bool hideAIMovements = ( conf.AIMoveSpeed() == 0 ); const bool noMovementAnimation = ( conf.AIMoveSpeed() == 10 ); const std::vector delayTypes = { Game::CURRENT_AI_DELAY, Game::MAPS_DELAY }; fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( !hideAIMovements && Game::isDelayNeeded( delayTypes ) ) ) { if ( !hero.isActive() || !hero.isMoveEnabled() ) { break; } if ( hideAIMovements || !AIIsShowAnimationForHero( hero, colors ) ) { // A hero might have been moving with visible animation for humans till he reaches the area // where animation is not needed. This can be in the middle of movement between tiles. // In this case it is important to reset animation sprite to make sure that the hero is // ready for jump steps. hero.resetHeroSprite(); hero.Move( true ); recenterNeeded = true; // Render a frame only if there is a need to show one. if ( Game::validateAnimationDelay( Game::MAPS_DELAY ) ) { // Update Adventure Map objects' animation. Game::updateAdventureMapAnimationIndex(); adventureMapInterface.redraw( Interface::REDRAW_GAMEAREA | Interface::REDRAW_STATUS ); // If this assertion blows up it means that we are holding a RedrawLocker lock for rendering which should not happen. assert( adventureMapInterface.getRedrawMask() == 0 ); display.render(); } } else if ( Game::validateAnimationDelay( Game::CURRENT_AI_DELAY ) ) { // re-center in case hero appears from the fog if ( recenterNeeded ) { gameArea.SetCenter( hero.GetCenter() ); recenterNeeded = false; } bool resetHeroSprite = false; if ( heroAnimationFrameCount > 0 ) { const int32_t heroMovementSkipValue = Game::AIHeroAnimSpeedMultiplier(); gameArea.ShiftCenter( { heroAnimationOffset.x * heroMovementSkipValue, heroAnimationOffset.y * heroMovementSkipValue } ); gameArea.SetRedraw(); heroAnimationFrameCount -= heroMovementSkipValue; if ( ( heroAnimationFrameCount & 0x3 ) == 0 ) { // % 4 hero.SetSpriteIndex( heroAnimationSpriteId ); if ( heroAnimationFrameCount == 0 ) resetHeroSprite = true; else ++heroAnimationSpriteId; } const int offsetStep = ( ( 4 - ( heroAnimationFrameCount & 0x3 ) ) & 0x3 ); // % 4 hero.SetOffset( { heroAnimationOffset.x * offsetStep, heroAnimationOffset.y * offsetStep } ); } if ( heroAnimationFrameCount == 0 ) { if ( resetHeroSprite ) { hero.SetSpriteIndex( heroAnimationSpriteId - 1 ); } if ( hero.Move( noMovementAnimation ) ) { if ( AIIsShowAnimationForHero( hero, colors ) ) { gameArea.SetCenter( hero.GetCenter() ); } } else { const fheroes2::Point movement( hero.MovementDirection() ); if ( movement != fheroes2::Point() ) { // don't waste resources for no movement const int32_t heroMovementSkipValue = Game::AIHeroAnimSpeedMultiplier(); heroAnimationOffset = movement; gameArea.ShiftCenter( movement ); heroAnimationFrameCount = 32 - heroMovementSkipValue; heroAnimationSpriteId = hero.GetSpriteIndex(); if ( heroMovementSkipValue < 4 ) { hero.SetSpriteIndex( heroAnimationSpriteId - 1 ); hero.SetOffset( { heroAnimationOffset.x * heroMovementSkipValue, heroAnimationOffset.y * heroMovementSkipValue } ); } else { ++heroAnimationSpriteId; } } } } if ( Game::validateAnimationDelay( Game::MAPS_DELAY ) ) { // Update Adventure Map objects' animation. Game::updateAdventureMapAnimationIndex(); adventureMapInterface.setRedraw( Interface::REDRAW_STATUS ); } adventureMapInterface.redraw( Interface::REDRAW_GAMEAREA ); // If this assertion blows up it means that we are holding a RedrawLocker lock for rendering which should not happen. assert( adventureMapInterface.getRedrawMask() == 0 ); display.render(); } } hero.SetMove( false ); } void AI::HeroesCastDimensionDoor( Heroes & hero, const int32_t targetIndex ) { if ( !Maps::isValidAbsIndex( targetIndex ) || hero.isShipMaster() != world.getTile( targetIndex ).isWater() ) { return; } const Spell dimensionDoor( Spell::DIMENSIONDOOR ); if ( !hero.CanCastSpell( dimensionDoor ) ) { // How is it even possible to call this function if the hero does not have this spell? assert( 0 ); return; } if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); hero.FadeOut( Game::AIHeroAnimSpeedMultiplier() ); } hero.Scout( targetIndex ); hero.Move2Dest( targetIndex ); hero.SpellCasted( dimensionDoor ); hero.setDimensionDoorUsage( hero.getDimensionDoorUses() + 1 ); hero.GetPath().Reset(); if ( AIIsShowAnimationForHero( hero, AIGetAllianceColors() ) ) { Interface::AdventureMap::Get().getGameArea().SetCenter( hero.GetCenter() ); hero.FadeIn( Game::AIHeroAnimSpeedMultiplier() ); } hero.ActionNewPosition( false ); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " moved to " << targetIndex ) } int32_t AI::HeroesCastSummonBoat( Heroes & hero, const int32_t boatDestinationIndex ) { assert( !hero.isShipMaster() && Maps::isValidAbsIndex( boatDestinationIndex ) ); const Spell summonBoat( Spell::SUMMONBOAT ); assert( hero.CanCastSpell( summonBoat ) ); const int32_t boatSource = fheroes2::getSummonableBoat( hero ); // Player should have a summonable boat before calling this function. assert( Maps::isValidAbsIndex( boatSource ) ); hero.SpellCasted( summonBoat ); const int heroColor = hero.GetColor(); Interface::GameArea & gameArea = Interface::AdventureMap::Get().getGameArea(); Maps::Tile & tileSource = world.getTile( boatSource ); if ( AIIsShowAnimationForTile( tileSource, AIGetAllianceColors() ) ) { gameArea.SetCenter( Maps::GetPoint( boatSource ) ); gameArea.runSingleObjectAnimation( std::make_shared( tileSource.getMainObjectPart()._uid, boatSource, MP2::OBJ_BOAT ) ); } else { removeMainObjectFromTile( tileSource ); } Maps::Tile & tileDest = world.getTile( boatDestinationIndex ); assert( tileDest.getMainObjectType() == MP2::OBJ_NONE ); tileDest.setBoat( Direction::RIGHT, heroColor ); tileSource.resetBoatOwnerColor(); if ( AIIsShowAnimationForTile( tileDest, AIGetAllianceColors() ) ) { gameArea.SetCenter( Maps::GetPoint( boatDestinationIndex ) ); gameArea.runSingleObjectAnimation( std::make_shared( tileDest.getMainObjectPart()._uid, boatDestinationIndex, MP2::OBJ_BOAT ) ); } DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " summoned the boat from " << boatSource << " to " << boatDestinationIndex ) return boatSource; } bool AI::HeroesCastAdventureSpell( Heroes & hero, const Spell & spell ) { if ( !hero.CanCastSpell( spell ) ) { return false; } hero.SpellCasted( spell ); return true; } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_hero_action.h000066400000000000000000000044461476115357100222060ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include class Heroes; class Spell; namespace AI { void HeroesAction( Heroes & hero, const int32_t dst_index ); void HeroesMove( Heroes & hero ); // Makes it so that the 'hero' casts the Dimension Door spell to the 'targetIndex' void HeroesCastDimensionDoor( Heroes & hero, const int32_t targetIndex ); // Makes it so that the 'hero' casts the Summon Boat spell, summoning the boat at the 'boatDestinationIndex'. // Returns the index of the tile on which the boat was located before the summoning. It's the caller's // responsibility to make sure that 'hero' may cast this spell and there is a summonable boat on the map // before calling this function. int32_t HeroesCastSummonBoat( Heroes & hero, const int32_t boatDestinationIndex ); bool HeroesCastAdventureSpell( Heroes & hero, const Spell & spell ); } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_personality.cpp000066400000000000000000000037261476115357100226200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ai_personality.h" #include "rand.h" #include "translations.h" AI::Personality AI::getRandomPersonality() { return Rand::Get( Personality::WARRIOR, Personality::EXPLORER ); } std::string AI::getPersonalityString( const Personality personality ) { switch ( personality ) { case Personality::WARRIOR: return _( "Warrior" ); case Personality::BUILDER: return _( "Builder" ); case Personality::EXPLORER: return _( "Explorer" ); default: break; } return _( "None" ); } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_personality.h000066400000000000000000000033411476115357100222560ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace AI { enum class Personality : int32_t { NONE, WARRIOR, BUILDER, EXPLORER }; Personality getRandomPersonality(); std::string getPersonalityString( const Personality personality ); } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_planner.cpp000066400000000000000000000164021476115357100217010ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ai_planner.h" #include #include #include #include #include #include #include "army.h" #include "heroes.h" #include "kingdom.h" #include "maps_tiles.h" #include "mp2.h" #include "profit.h" #include "resource.h" #include "route.h" #include "world.h" #include "world_pathfinding.h" AI::Planner & AI::Planner::Get() { static Planner ai; return ai; } void AI::Planner::resetPathfinder() { _pathfinder.reset(); } void AI::Planner::revealFog( const Maps::Tile & tile, const Kingdom & kingdom ) { const MP2::MapObjectType object = tile.getMainObjectType(); if ( !MP2::isInGameActionObject( object ) ) { return; } updateMapActionObjectCache( tile.GetIndex() ); updatePriorityAttackTarget( kingdom, tile ); // If this is an action object and one of AI heroes is moving, // we have to stop him because the new object might be more valuable than the current target. const VecHeroes & heroes = kingdom.GetHeroes(); for ( Heroes * hero : heroes ) { if ( hero == nullptr ) { // How is it even possible? assert( 0 ); continue; } if ( hero->isMoveEnabled() ) { hero->GetPath().Truncate(); break; } } } double AI::Planner::getTileArmyStrength( const Maps::Tile & tile ) { const auto [iter, inserted] = _tileArmyStrengthValues.try_emplace( tile.GetIndex(), 0.0 ); if ( inserted ) { // Creating an Army instance is a relatively heavy operation, so cache it to speed up calculations static Army tileArmy; tileArmy.setFromTile( tile ); iter->second = tileArmy.GetStrength(); } return iter->second; } double AI::Planner::getResourcePriorityModifier( const int resource, const bool isMine ) const { // Not all resources are equally valuable: 1 gold does not have the same value as 1 gemstone, so we need to // normalize the value of various resources. // For mines, let's determine the default relative priority based on the ratio of the amount of resources // extracted by these mines. For example, if a gold mine produces 1000 gold per day, an ore mine produces 2 // units of ore per day, and a gem mine produces 1 gem per day, then the priority of one unit of ore will // correspond to the priority of 500 gold, and the priority of one gemstone will correspond to the priority // of 1000 gold. Evaluate the resources from mines in proportion to the amount of resources that these mines // bring in 2 days (mines should be more valuable than just resource piles). static const std::map minePriorities = []() { std::map result; const double goldMineIncome = ProfitConditions::FromMine( Resource::GOLD ).Get( Resource::GOLD ); assert( goldMineIncome > 0 ); Resource::forEach( Resource::ALL, [&result, goldMineIncome]( const int res ) { const int32_t resMineIncome = ProfitConditions::FromMine( res ).Get( res ); assert( resMineIncome > 0 ); if ( resMineIncome <= 0 ) { return; } result[res] = goldMineIncome / resMineIncome * 2; } ); return result; }(); // For one-time resource sources (such as piles, chests, campfires and so on), let's determine the default // relative priority based on the ratio of the usual amount of resources in these sources. static const std::map pilePriorities = { // The amount of gold on the map is usually ~500-1500 { Resource::GOLD, 1 }, // The amount of wood and ore on the map is usually ~5-10 { Resource::WOOD, 125 }, { Resource::ORE, 125 }, // The amount of other resources on the map is usually ~2-5 { Resource::MERCURY, 250 }, { Resource::SULFUR, 250 }, { Resource::CRYSTAL, 250 }, { Resource::GEMS, 250 } }; const std::map & resourcePriorities = isMine ? minePriorities : pilePriorities; double prio = 1.0; const auto prioIter = resourcePriorities.find( resource ); if ( prioIter != resourcePriorities.end() ) { prio = prioIter->second; } else { // This function has been called for an unknown resource, this should never happen assert( 0 ); } for ( const BudgetEntry & budget : _budget ) { if ( budget.resource != resource ) { continue; } if ( budget.recurringCost ) { prio *= 1.5; } return ( budget.priority ) ? prio * 2.0 : prio; } return prio; } double AI::Planner::getFundsValueBasedOnPriority( const Funds & funds ) const { double value = 0; Resource::forEach( funds.GetValidItems(), [this, &funds, &value]( const int res ) { const int amount = funds.Get( res ); if ( amount <= 0 ) { return; } value += amount * getResourcePriorityModifier( res, false ); } ); return value; } void AI::Planner::updateMapActionObjectCache( const int mapIndex ) { const MP2::MapObjectType objectType = world.getTile( mapIndex ).getMainObjectType(); if ( !MP2::isInGameActionObject( objectType ) ) { _mapActionObjects.erase( mapIndex ); return; } if ( const auto [iter, inserted] = _mapActionObjects.try_emplace( mapIndex, objectType ); !inserted ) { iter->second = objectType; } } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_planner.h000066400000000000000000000242051476115357100213460ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include "resource.h" #include "world_pathfinding.h" class Castle; class HeroBase; class Heroes; class Kingdom; struct VecCastles; struct VecHeroes; namespace MP2 { enum MapObjectType : uint16_t; } namespace Maps { class Tile; } namespace Skill { class Secondary; } namespace AI { // Although AI heroes are capable to find their own tasks strategic AI should be able to focus them on most critical tasks enum class PriorityTaskType : int { // AI will focus on siegeing or chasing the selected enemy castle or hero. ATTACK, // Target will usually be a friendly castle. AI will move heroes to defend and garrison it. DEFEND, // Target must be a friendly castle or hero. AI with such priority set should focus on bringing more troops to the target. REINFORCE }; // TODO: this structure is not being updated during AI heroes' actions. struct RegionStats { bool evaluated = false; double highestThreat = -1; int friendlyHeroes = 0; int friendlyCastles = 0; int enemyCastles = 0; int safetyFactor = 0; int spellLevel = 2; }; struct AICastle { Castle * castle = nullptr; bool underThreat = false; int safetyFactor = 0; int buildingValue = 0; AICastle( Castle * inCastle, bool inThreat, int inSafety, int inValue ) : castle( inCastle ) , underThreat( inThreat ) , safetyFactor( inSafety ) , buildingValue( inValue ) { assert( castle != nullptr ); } }; struct BudgetEntry { int resource = Resource::UNKNOWN; int missing = 0; bool priority = false; bool recurringCost = false; BudgetEntry( int type ) : resource( type ) {} void reset() { missing = 0; priority = false; recurringCost = false; } }; struct EnemyArmy { EnemyArmy() = default; EnemyArmy( const int32_t index_, const Heroes * hero_, const double strength_, const uint32_t movePoints_ ) : index( index_ ) , hero( hero_ ) , strength( strength_ ) , movePoints( movePoints_ ) {} int32_t index{ -1 }; const Heroes * hero{ nullptr }; double strength{ 0 }; uint32_t movePoints{ 0 }; }; struct PriorityTask { PriorityTask() = default; explicit PriorityTask( PriorityTaskType taskType ) : type( taskType ) {} PriorityTask( PriorityTaskType taskType, int secondaryTask ) : type( taskType ) { secondaryTaskTileId.insert( secondaryTask ); } PriorityTaskType type{ PriorityTaskType::ATTACK }; std::set secondaryTaskTileId; }; class Planner { public: static Planner & Get(); void KingdomTurn( Kingdom & kingdom ); // Implements the logic of transparent casting of the Summon Boat spell at the beginning of the hero's movement void HeroesBeginMovement( Heroes & hero ); // Implements the logic of transparent casting of the Summon Boat spell during the hero's movement void HeroesActionNewPosition( Heroes & hero ); void HeroesActionComplete( Heroes & hero, const int32_t tileIndex, const MP2::MapObjectType objectType ); void resetPathfinder(); void revealFog( const Maps::Tile & tile, const Kingdom & kingdom ); bool isValidHeroObject( const Heroes & hero, const int32_t index, const bool underHero ); double getObjectValue( const Heroes & hero, const int32_t index, const MP2::MapObjectType objectType, const double valueToIgnore, const uint32_t distanceToObject ) const; // Returns the strength of the army guarding the given tile. Note that the army is obtained by calling // Army::setFromTile(), so this method is not suitable for hero armies or castle garrisons. double getTileArmyStrength( const Maps::Tile & tile ); static void HeroesPreBattle( HeroBase & hero, bool isAttacking ); static void CastlePreBattle( Castle & castle ); static Skill::Secondary pickSecondarySkill( const Heroes & hero, const Skill::Secondary & left, const Skill::Secondary & right ); private: Planner() = default; void CastleTurn( Castle & castle, const bool defensiveStrategy ); // Upgrades & hires the maximum possible number of troops in the given castle, and also purposefully reinforces the castle's guest hero // (if there is one) by giving him the best available troops. void reinforceCastle( Castle & castle ); // Returns true if heroes can still do tasks but they have no move points. bool HeroesTurn( VecHeroes & heroes, uint32_t & currentProgressValue, uint32_t endProgressValue ); bool recruitHero( Castle & castle, bool buyArmy ); void evaluateRegionSafety(); std::vector getSortedCastleList( const VecCastles & castles, const std::set & castlesInDanger ); int getPriorityTarget( Heroes & hero, double & maxPriority ); double getGeneralObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const; double getFighterObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const; double getCourierObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const; double getScoutObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const; int getCourierMainTarget( const Heroes & hero, const double lowestPossibleValue ); double getResourcePriorityModifier( const int resource, const bool isMine ) const; double getFundsValueBasedOnPriority( const Funds & funds ) const; void updatePriorityTargets( Heroes & hero, const int32_t tileIndex, const MP2::MapObjectType objectType ); void updateKingdomBudget( const Kingdom & kingdom ); bool purchaseNewHeroes( const std::vector & sortedCastleList, const std::set & castlesInDanger, const int32_t availableHeroCount, const bool moreTasksForHeroes ); void updateMapActionObjectCache( const int mapIndex ); std::set findCastlesInDanger( const Kingdom & kingdom ); void updatePriorityForEnemyArmy( const Kingdom & kingdom, const EnemyArmy & enemyArmy ); void updatePriorityForCastle( const Castle & castle ); // Return true if the castle is in danger. // IMPORTANT!!! Do not call this method directly. Use other methods which call it internally. bool updateIndividualPriorityForCastle( const Castle & castle, const EnemyArmy & enemyArmy ); void removePriorityAttackTarget( const int32_t tileIndex ); void updatePriorityAttackTarget( const Kingdom & kingdom, const Maps::Tile & tile ); bool isPriorityTask( const int32_t index ) const { return _priorityTargets.find( index ) != _priorityTargets.end(); } bool isCriticalTask( const int32_t index ) const { const auto iter = _priorityTargets.find( index ); if ( iter == _priorityTargets.end() ) { return false; } return iter->second.type == PriorityTaskType::ATTACK || iter->second.type == PriorityTaskType::DEFEND; } // The following member variables should not be saved or serialized std::unordered_map _mapActionObjects; std::unordered_map _priorityTargets; std::unordered_map _enemyArmies; // Strength of the armies guarding the tiles (neutral monsters, guardians of dwellings, and so on) is constant for AI // during the same turn, but its calculation is a heavy operation, so it needs to be cached to speed up estimations. // It is important to update this cache after performing an action on the corresponding tile. std::unordered_map _tileArmyStrengthValues; std::vector _regions; std::array _budget = { Resource::WOOD, Resource::MERCURY, Resource::ORE, Resource::SULFUR, Resource::CRYSTAL, Resource::GEMS, Resource::GOLD }; AIWorldPathfinder _pathfinder; }; } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_planner_castle.cpp000066400000000000000000000605231476115357100232370ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include "ai_common.h" #include "ai_planner.h" // IWYU pragma: associated #include "army.h" #include "army_troop.h" #include "castle.h" #include "difficulty.h" #include "game.h" #include "heroes.h" #include "kingdom.h" #include "logging.h" #include "maps_tiles.h" #include "monster.h" #include "payment.h" #include "race.h" #include "resource.h" #include "world.h" #include "world_regions.h" namespace { struct BuildOrder { const BuildingType building = BUILD_NOTHING; const uint32_t priority = 1; BuildOrder() = default; BuildOrder( const BuildingType b, const uint32_t p ) : building( b ) , priority( p ) {} }; const std::vector defensiveStructures = { { BUILD_LEFTTURRET, 1 }, { BUILD_RIGHTTURRET, 1 }, { BUILD_MOAT, 1 }, { BUILD_CAPTAIN, 1 } }; const std::vector supportingDefensiveStructures = { { BUILD_MAGEGUILD1, 1 }, { BUILD_SPEC, 2 }, { BUILD_TAVERN, 1 } }; const std::vector & GetIncomeStructures( int type ) { static const std::vector standard = { { BUILD_CASTLE, 1 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 } }; static const std::vector warlock = { { BUILD_CASTLE, 1 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 }, { BUILD_SPEC, 1 } }; return ( type == Race::WRLK ) ? warlock : standard; } const std::vector & GetBuildOrder( int type ) { static const std::vector genericBuildOrder = { { BUILD_CASTLE, 2 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 }, { DWELLING_UPGRADE7, 1 }, { DWELLING_UPGRADE6, 1 }, { DWELLING_MONSTER6, 1 }, { DWELLING_UPGRADE5, 1 }, { DWELLING_MONSTER5, 1 }, { DWELLING_UPGRADE4, 1 }, { DWELLING_MONSTER4, 1 }, { DWELLING_UPGRADE3, 2 }, { DWELLING_MONSTER3, 2 }, { DWELLING_UPGRADE2, 3 }, { DWELLING_MONSTER2, 3 }, { DWELLING_MONSTER1, 4 }, { BUILD_MAGEGUILD1, 2 }, { BUILD_WEL2, 10 }, { BUILD_TAVERN, 5 }, { BUILD_THIEVESGUILD, 10 }, { BUILD_MAGEGUILD2, 3 }, { BUILD_MAGEGUILD3, 4 }, { BUILD_MAGEGUILD4, 5 }, { BUILD_MAGEGUILD5, 5 }, { BUILD_SHIPYARD, 4 } }; static const std::vector barbarianBuildOrder = { { BUILD_CASTLE, 2 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 }, { DWELLING_MONSTER6, 1 }, { DWELLING_UPGRADE5, 1 }, { DWELLING_MONSTER5, 1 }, { DWELLING_UPGRADE4, 1 }, { DWELLING_MONSTER4, 1 }, { DWELLING_MONSTER3, 1 }, { DWELLING_UPGRADE2, 2 }, { DWELLING_MONSTER2, 2 }, { DWELLING_MONSTER1, 4 }, { BUILD_MAGEGUILD1, 3 }, { BUILD_WEL2, 10 }, { BUILD_TAVERN, 5 }, { BUILD_THIEVESGUILD, 10 }, { BUILD_MAGEGUILD2, 4 }, { BUILD_MAGEGUILD3, 5 }, { BUILD_MAGEGUILD4, 6 }, { BUILD_MAGEGUILD5, 7 }, { BUILD_SHIPYARD, 4 } }; static const std::vector sorceressBuildOrder = { { BUILD_CASTLE, 2 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 }, { DWELLING_MONSTER6, 1 }, { DWELLING_MONSTER5, 1 }, { DWELLING_MONSTER4, 1 }, { BUILD_MAGEGUILD1, 1 }, { DWELLING_MONSTER3, 1 }, { DWELLING_UPGRADE4, 1 }, { DWELLING_UPGRADE3, 2 }, { DWELLING_UPGRADE2, 5 }, { DWELLING_MONSTER2, 2 }, { BUILD_TAVERN, 2 }, { DWELLING_MONSTER1, 4 }, { BUILD_WEL2, 10 }, { BUILD_THIEVESGUILD, 10 }, { BUILD_MAGEGUILD2, 3 }, { BUILD_MAGEGUILD3, 4 }, { BUILD_MAGEGUILD4, 5 }, { BUILD_MAGEGUILD5, 5 }, { BUILD_SHIPYARD, 4 } }; // De-prioritizing dwelling 5 (you can reach 6 without it), 1 and upgrades of 3 and 4 // Well, tavern and Archery upgrade are more important static const std::vector knightBuildOrder = { { BUILD_CASTLE, 2 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 }, { DWELLING_UPGRADE6, 2 }, { DWELLING_MONSTER6, 1 }, { DWELLING_UPGRADE5, 2 }, { DWELLING_MONSTER5, 2 }, { DWELLING_UPGRADE4, 2 }, { DWELLING_MONSTER4, 1 }, { DWELLING_UPGRADE3, 2 }, { DWELLING_MONSTER3, 1 }, { DWELLING_UPGRADE2, 1 }, { DWELLING_MONSTER2, 3 }, { DWELLING_MONSTER1, 4 }, { BUILD_WELL, 1 }, { BUILD_TAVERN, 1 }, { BUILD_MAGEGUILD1, 2 }, { BUILD_MAGEGUILD2, 3 }, { BUILD_MAGEGUILD3, 5 }, { BUILD_MAGEGUILD4, 5 }, { BUILD_MAGEGUILD5, 5 }, { BUILD_SPEC, 5 }, { BUILD_THIEVESGUILD, 10 }, { BUILD_WEL2, 20 }, { BUILD_SHIPYARD, 4 } }; // Priority on Dwellings 5/6 and Mage guild level 2 static const std::vector necromancerBuildOrder = { { BUILD_CASTLE, 2 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 }, { DWELLING_UPGRADE6, 1 }, { DWELLING_MONSTER6, 1 }, { DWELLING_UPGRADE5, 2 }, { DWELLING_MONSTER5, 1 }, { BUILD_MAGEGUILD1, 1 }, { DWELLING_UPGRADE4, 2 }, { DWELLING_MONSTER4, 1 }, { DWELLING_UPGRADE3, 3 }, { DWELLING_MONSTER3, 3 }, { DWELLING_UPGRADE2, 4 }, { DWELLING_MONSTER2, 2 }, { DWELLING_MONSTER1, 3 }, { BUILD_MAGEGUILD2, 2 }, { BUILD_THIEVESGUILD, 2 }, { BUILD_WEL2, 8 }, { BUILD_MAGEGUILD3, 4 }, { BUILD_MAGEGUILD4, 5 }, { BUILD_MAGEGUILD5, 5 }, { BUILD_SHRINE, 10 }, { BUILD_SHIPYARD, 4 } }; // Priority on Mage tower/guild and library static const std::vector wizardBuildOrder = { { BUILD_CASTLE, 2 }, { BUILD_STATUE, 1 }, { BUILD_MARKETPLACE, 1 }, { DWELLING_UPGRADE6, 1 }, { DWELLING_MONSTER6, 1 }, { DWELLING_UPGRADE5, 1 }, { DWELLING_MONSTER5, 1 }, { DWELLING_MONSTER4, 1 }, { DWELLING_MONSTER3, 1 }, { DWELLING_MONSTER2, 1 }, { DWELLING_MONSTER1, 1 }, { BUILD_MAGEGUILD1, 1 }, { DWELLING_UPGRADE3, 4 }, { BUILD_SPEC, 2 }, { BUILD_WEL2, 8 }, { BUILD_MAGEGUILD2, 3 }, { BUILD_MAGEGUILD3, 4 }, { BUILD_MAGEGUILD4, 4 }, { BUILD_MAGEGUILD5, 4 }, { BUILD_TAVERN, 10 }, { BUILD_THIEVESGUILD, 10 }, { BUILD_SHIPYARD, 4 } }; switch ( type ) { case Race::KNGT: return knightBuildOrder; case Race::NECR: return necromancerBuildOrder; case Race::WZRD: return wizardBuildOrder; case Race::SORC: return sorceressBuildOrder; case Race::BARB: return barbarianBuildOrder; default: break; } return genericBuildOrder; } bool Build( Castle & castle, const std::vector & buildOrderList, const uint32_t multiplier = 1 ) { const int gameDifficulty = Game::getDifficulty(); const bool isGameCampaign = Game::isCampaign(); for ( const BuildOrder & order : buildOrderList ) { if ( !Difficulty::allowAIToBuildCastleBuilding( gameDifficulty, isGameCampaign, order.building ) ) { continue; } const uint32_t fundsMultiplier = order.priority * multiplier; if ( fundsMultiplier == 1 ) { if ( AI::BuildIfPossible( castle, order.building ) ) { return true; } } else if ( AI::BuildIfEnoughFunds( castle, order.building, fundsMultiplier ) ) { return true; } } return false; } bool CastleDevelopment( Castle & castle, int safetyFactor, int spellLevel ) { if ( !Difficulty::allowAIToDevelopCastlesOnDay( Game::getDifficulty(), Game::isCampaign(), world.CountDay() ) ) { return false; } if ( castle.isCastle() && !castle.isBuild( BUILD_WELL ) && world.CountDay() > 6 ) { // If you can't build Well, you won't be able to build anything else return AI::BuildIfPossible( castle, BUILD_WELL ); } if ( Build( castle, GetIncomeStructures( castle.GetRace() ) ) ) { return true; } const size_t neighbourRegions = world.getRegion( world.getTile( castle.GetIndex() ).GetRegion() ).getNeighboursCount(); const bool islandOrPeninsula = neighbourRegions < 3; // Force building a shipyard, +1 to cost check since we can have 0 neighbours if ( islandOrPeninsula && AI::BuildIfEnoughFunds( castle, BUILD_SHIPYARD, static_cast( neighbourRegions + 1 ) ) ) { return true; } if ( Build( castle, GetBuildOrder( castle.GetRace() ) ) ) { return true; } if ( castle.GetLevelMageGuild() < spellLevel && safetyFactor > 0 ) { static const std::vector magicGuildUpgrades = { { BUILD_MAGEGUILD2, 2 }, { BUILD_MAGEGUILD3, 2 }, { BUILD_MAGEGUILD4, 1 }, { BUILD_MAGEGUILD5, 1 } }; if ( Build( castle, magicGuildUpgrades ) ) { return true; } } // Check whether it is worth buying a boat const bool buyBoat = [&castle, islandOrPeninsula]() { // Check if it is possible to build a boat in this castle at all (except for the solvency check) if ( !castle.AllowBuyBoat( false ) ) { return false; } Kingdom & kingdom = castle.GetKingdom(); // If there are no active heroes in the kingdom, then there will be no one to use the boat if ( kingdom.GetHeroes().empty() ) { return false; } // Perhaps the kingdom already has the necessary supply of resources const Funds requiredFunds = PaymentConditions::BuyBoat() * ( islandOrPeninsula ? 2 : 4 ); if ( kingdom.AllowPayment( requiredFunds ) ) { return true; } // Even if the kingdom does not have the necessary supply of these resources right now, there may be enough resources of another type available to get the // missing resources as a result of resource exchange if ( !AI::calculateMarketplaceTransaction( kingdom, requiredFunds ) ) { return false; } // There are resources available to buy a boat right now if ( kingdom.AllowPayment( PaymentConditions::BuyBoat() ) ) { return true; } // There are no available resources, but it is possible to make a resource exchange if ( AI::tradeAtMarketplace( kingdom, PaymentConditions::BuyBoat() ) ) { return true; } assert( 0 ); return false; }(); // If yes, then buy a boat if ( buyBoat ) { castle.BuyBoat(); } if ( Build( castle, defensiveStructures, 10 ) ) { return true; } return Build( castle, supportingDefensiveStructures, 10 ); } } void AI::Planner::CastlePreBattle( Castle & castle ) { Heroes * hero = world.GetHero( castle ); if ( hero == nullptr ) { return; } Army & army = hero->GetArmy(); if ( !army.ArrangeForCastleDefense( castle.GetArmy() ) ) { return; } // Optimization cannot be performed if we have not received any reinforcements from the garrison, otherwise the actual placement of units during the battle will // differ from that observed by the enemy player before the start of the battle OptimizeTroopsOrder( army ); } void AI::Planner::updateKingdomBudget( const Kingdom & kingdom ) { // clean up first for ( BudgetEntry & budgetEntry : _budget ) { budgetEntry.reset(); } const Funds & kindgomFunds = kingdom.GetFunds(); Funds requirements; for ( const Castle * castle : kingdom.GetCastles() ) { if ( !castle ) { continue; } const int race = castle->GetRace(); const std::vector & buildOrder = GetBuildOrder( race ); for ( const BuildOrder & order : buildOrder ) { const BuildingStatus status = castle->CheckBuyBuilding( order.building ); if ( status == BuildingStatus::LACK_RESOURCES ) { Funds missing = PaymentConditions::BuyBuilding( race, order.building ) - kindgomFunds; requirements = requirements.max( missing ); } } if ( castle->isBuild( DWELLING_MONSTER6 ) ) { Funds bestUnitCost = Monster( race, DWELLING_MONSTER6 ).GetUpgrade().GetCost(); for ( BudgetEntry & budgetEntry : _budget ) { if ( bestUnitCost.Get( budgetEntry.resource ) > 0 ) { budgetEntry.recurringCost = true; } } } } for ( BudgetEntry & budgetEntry : _budget ) { budgetEntry.missing = requirements.Get( budgetEntry.resource ); if ( budgetEntry.missing ) { budgetEntry.priority = true; } } } void AI::Planner::reinforceCastle( Castle & castle ) { assert( castle.isControlAI() ); const auto recruitMonster = [&castle]( const Troop & troop ) { // This method can hire a unit to both the castle garrison and the guest hero's army (depending on the availability of suitable slots) if ( castle.RecruitMonster( troop, false ) ) { DEBUG_LOG( DBG_AI, DBG_INFO, castle.GetName() << " hires " << troop.GetCount() << " " << troop.GetPluralName( troop.GetCount() ) ) return true; } return false; }; // First of all, upgrade the existing units in the garrison and in the guest hero's army (if there is one) and merge the same ones to free // up as much slots as possible for new units Army & garrison = castle.GetArmy(); garrison.UpgradeTroops( castle ); garrison.MergeSameMonsterTroops(); Heroes * guestHero = castle.GetHero(); if ( guestHero ) { assert( guestHero->isActive() && guestHero->isControlAI() && guestHero->GetColor() == castle.GetColor() ); Army & guestHeroArmy = guestHero->GetArmy(); guestHeroArmy.UpgradeTroops( castle ); guestHeroArmy.MergeSameMonsterTroops(); } // It is allowed to hire non-upgraded units even if an upgraded dwelling is built static const std::array castleDwellings{ DWELLING_UPGRADE7, DWELLING_UPGRADE6, DWELLING_MONSTER6, DWELLING_UPGRADE5, DWELLING_MONSTER5, DWELLING_UPGRADE4, DWELLING_MONSTER4, DWELLING_UPGRADE3, DWELLING_MONSTER3, DWELLING_UPGRADE2, DWELLING_MONSTER2, DWELLING_MONSTER1 }; for ( const uint32_t dwelling : castleDwellings ) { if ( !castle.isBuild( dwelling ) ) { continue; } const Monster monster( castle.GetRace(), dwelling ); const uint32_t count = castle.getRecruitLimit( monster, castle.GetKingdom().GetFunds() ); if ( count == 0 ) { continue; } const Troop troop( monster, count ); if ( recruitMonster( troop ) ) { continue; } Troop * weakestTroop = nullptr; if ( guestHero ) { Army & guestHeroArmy = guestHero->GetArmy(); // If there is a guest hero in the castle, and there is no slot for a new unit, then we can try to free up a slot by transferring some unit to the guest hero if ( [&castle = std::as_const( castle ), &garrison, &guestHero = std::as_const( *guestHero ), &guestHeroArmy]() { for ( size_t i = 0; i < garrison.Size(); ++i ) { Troop * garrisonTroop = garrison.GetTroop( i ); // All garrison slots should be occupied here because we just couldn't find a place for a new unit assert( garrisonTroop != nullptr && garrisonTroop->isValid() ); if ( guestHeroArmy.JoinTroop( *garrisonTroop ) ) { DEBUG_LOG( DBG_AI, DBG_TRACE, castle.GetName() << " transfers " << garrisonTroop->GetCount() << " " << garrisonTroop->GetPluralName( garrisonTroop->GetCount() ) << " to the army of the guest hero " << guestHero.GetName() ) #ifndef WITH_DEBUG (void)castle; (void)guestHero; #endif garrisonTroop->Reset(); return true; } } return false; }() ) { if ( !recruitMonster( troop ) ) { // We have just successfully transferred a unit from the garrison to the guest hero's army, but we still can't hire a new unit. This shouldn't happen. assert( 0 ); } continue; } weakestTroop = guestHeroArmy.GetWeakestTroop(); // All slots in the guest hero's army should be occupied here because we just couldn't find a place for a new unit assert( weakestTroop != nullptr ); } { Troop * weakestGarrisonTroop = garrison.GetWeakestTroop(); // All garrison slots should be occupied here because we just couldn't find a place for a new unit assert( weakestGarrisonTroop != nullptr ); // We need to compare a strength of troops themselves here (excluding commanding hero's stats) weakestTroop = weakestTroop && Troop( *weakestTroop ).GetStrength() < Troop( *weakestGarrisonTroop ).GetStrength() ? weakestTroop : weakestGarrisonTroop; } // If we still can't find a slot, let's try to dismiss the weakest unit of those that are present in the garrison and in the army of the guest hero - provided // that it is weaker than the unit to hire assert( weakestTroop != nullptr ); // We need to compare a strength of troops themselves here (excluding commanding hero's stats) if ( Troop( *weakestTroop ).GetStrength() > troop.GetStrength() ) { DEBUG_LOG( DBG_AI, DBG_TRACE, castle.GetName() << " skips hiring " << troop.GetCount() << " " << troop.GetPluralName( troop.GetCount() ) << " because the weakest unit consisting of " << weakestTroop->GetCount() << " " << weakestTroop->GetPluralName( weakestTroop->GetCount() ) << " is stronger" ) continue; } DEBUG_LOG( DBG_AI, DBG_TRACE, castle.GetName() << " dismisses " << weakestTroop->GetCount() << " " << weakestTroop->GetPluralName( weakestTroop->GetCount() ) ) weakestTroop->Reset(); if ( !recruitMonster( troop ) ) { // We have just successfully dismissed a unit, but we still can't hire a new unit. This shouldn't happen. assert( 0 ); } } if ( guestHero ) { Army & guestHeroArmy = guestHero->GetArmy(); // Transfer the best troops from the garrison to the guest hero guestHeroArmy.JoinStrongestFromArmy( garrison ); // Check if we should leave some troops in the garrison // TODO: amount of troops left could depend on region's safetyFactor if ( const uint32_t regionID = world.getTile( castle.GetIndex() ).GetRegion(); castle.isCastle() && _regions.at( regionID ).safetyFactor <= 100 && !garrison.isValid() ) { auto [troopForTransferToGarrison, transferHalf] = [guestHeroRole = guestHero->getAIRole(), &guestHeroArmy = std::as_const( guestHeroArmy )]() -> std::pair { const bool isFighterRole = ( guestHeroRole == Heroes::Role::FIGHTER || guestHeroRole == Heroes::Role::CHAMPION ); // We need to compare a strength of troops themselves here (excluding commanding hero's stats) const double troopsStrength = Troops( guestHeroArmy.getTroops() ).GetStrength(); const double significanceRatio = isFighterRole ? 20.0 : 10.0; { Troop * candidateTroop = guestHeroArmy.GetSlowestTroop(); assert( candidateTroop != nullptr ); // We need to compare a strength of troops themselves here (excluding commanding hero's stats) if ( Troop( *candidateTroop ).GetStrength() <= troopsStrength / significanceRatio ) { return { candidateTroop, false }; } } // if this is an important hero, then all his troops are significant if ( isFighterRole ) { return {}; } { Troop * candidateTroop = guestHeroArmy.GetWeakestTroop(); assert( candidateTroop != nullptr ); // We need to compare a strength of troops themselves here (excluding commanding hero's stats) if ( Troop( *candidateTroop ).GetStrength() <= troopsStrength / significanceRatio ) { return { candidateTroop, true }; } } return {}; }(); if ( troopForTransferToGarrison ) { assert( guestHeroArmy.GetOccupiedSlotCount() > 1 ); const uint32_t initialCount = troopForTransferToGarrison->GetCount(); const uint32_t countToTransfer = transferHalf ? initialCount / 2 : initialCount; if ( garrison.JoinTroop( troopForTransferToGarrison->GetMonster(), countToTransfer, true ) ) { if ( countToTransfer == initialCount ) { troopForTransferToGarrison->Reset(); } else { troopForTransferToGarrison->SetCount( initialCount - countToTransfer ); } } } } } OptimizeTroopsOrder( garrison ); if ( guestHero ) { OptimizeTroopsOrder( guestHero->GetArmy() ); } } void AI::Planner::CastleTurn( Castle & castle, const bool defensiveStrategy ) { if ( defensiveStrategy ) { // If the castle is potentially under threat, then it makes sense to try to hire the maximum number of troops so that the enemy cannot hire them even if he // captures the castle, therefore, it is worth starting with hiring. reinforceCastle( castle ); // Avoid building monster dwellings when defensive as they might fall into enemy's hands. Instead, try to build defensive structures if there is at least some // kind of garrison in the castle. if ( castle.GetActualArmy().getTotalCount() > 0 ) { Build( castle, defensiveStructures ); Build( castle, supportingDefensiveStructures ); } } else { const uint32_t regionID = world.getTile( castle.GetIndex() ).GetRegion(); const RegionStats & stats = _regions[regionID]; CastleDevelopment( castle, stats.safetyFactor, stats.spellLevel ); } } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_planner_hero.cpp000066400000000000000000003372361476115357100227310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ai_common.h" #include "ai_hero_action.h" #include "ai_planner.h" // IWYU pragma: associated #include "ai_planner_internals.h" #include "army.h" #include "army_troop.h" #include "artifact.h" #include "castle.h" #include "color.h" #include "difficulty.h" #include "direction.h" #include "game.h" #include "game_interface.h" #include "game_over.h" #include "game_static.h" #include "ground.h" #include "heroes.h" #include "heroes_base.h" #include "interface_status.h" #include "kingdom.h" #include "logging.h" #include "luck.h" #include "maps.h" #include "maps_fileinfo.h" #include "maps_tiles.h" #include "maps_tiles_helper.h" #include "monster.h" #include "morale.h" #include "mp2.h" #include "pairs.h" #include "payment.h" #include "players.h" #include "profit.h" #include "rand.h" #include "resource.h" #include "route.h" #include "settings.h" #include "skill.h" #include "spell.h" #include "visit.h" #include "world.h" #include "world_pathfinding.h" namespace { bool isHeroWhoseDefeatIsVictoryConditionForHumanInCastle( const Castle * castle ) { assert( castle != nullptr ); const Heroes * hero = castle->GetHero(); if ( hero && hero == world.GetHeroesCondWins() ) { return true; } return false; } bool isFindArtifactVictoryConditionForHuman( const Artifact & art ) { assert( art.isValid() ); const Maps::FileInfo & mapInfo = Settings::Get().getCurrentMapInfo(); if ( ( mapInfo.ConditionWins() & GameOver::WINS_ARTIFACT ) == 0 ) { return false; } if ( mapInfo.WinsFindUltimateArtifact() ) { return art.isUltimate(); } return ( art.GetID() == mapInfo.WinsFindArtifactID() ); } bool isCastleLossConditionForHuman( const Castle * castle ) { assert( castle != nullptr ); const Maps::FileInfo & mapInfo = Settings::Get().getCurrentMapInfo(); const bool isSinglePlayer = ( Colors( Players::HumanColors() ).size() == 1 ); if ( isSinglePlayer && ( mapInfo.ConditionLoss() & GameOver::LOSS_TOWN ) != 0 && castle->GetCenter() == mapInfo.LossMapsPositionObject() ) { // It is a loss town condition for human. return true; } if ( mapInfo.WinsCompAlsoWins() && ( mapInfo.ConditionWins() & GameOver::WINS_TOWN ) != 0 && castle->GetCenter() == mapInfo.WinsMapsPositionObject() ) { // It is a town capture winning condition for AI. return true; } return false; } bool shouldUseDimensionDoor( const uint32_t regularMovementDist, const uint32_t dimensionDoorDist ) { if ( dimensionDoorDist == 0 ) { return false; } return ( regularMovementDist == 0 || dimensionDoorDist < regularMovementDist / 2 ); } // Returns a pair consisting of a distance and a boolean value set to true if this distance was calculated // for the case of movement using the Dimension Door spell, otherwise this value is set to false std::pair getDistanceToTile( AIWorldPathfinder & pathfinder, const int32_t index ) { const uint32_t regularMovementDist = pathfinder.getDistance( index ); const std::list dimensionDoorPath = pathfinder.buildDimensionDoorPath( index ); if ( dimensionDoorPath.empty() ) { return { regularMovementDist, false }; } const uint32_t dimensionDoorDist = Route::calculatePathPenalty( dimensionDoorPath ); assert( dimensionDoorDist > 0 ); if ( shouldUseDimensionDoor( regularMovementDist, dimensionDoorDist ) ) { return { dimensionDoorDist, true }; } return { regularMovementDist, false }; } bool AIShouldVisitCastle( const Heroes & hero, int castleIndex, const double heroArmyStrength ) { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( castleIndex ) ); if ( castle == nullptr ) { // How is it possible that a castle does not exist? assert( 0 ); return false; } if ( hero.GetColor() == castle->GetColor() ) { return castle->GetHero() == nullptr; } if ( hero.isFriends( castle->GetColor() ) ) { return false; } // WINS_HERO victory condition does not apply to AI-controlled players, we have to ignore the castle with this hero // to keep him alive for the human player if ( isHeroWhoseDefeatIsVictoryConditionForHumanInCastle( castle ) ) { return false; } const double advantage = hero.isLosingGame() ? AI::ARMY_ADVANTAGE_DESPERATE : AI::ARMY_ADVANTAGE_MEDIUM; const double castleStrength = castle->GetGarrisonStrength( hero ) * advantage; return heroArmyStrength > castleStrength; } bool isHeroStrongerThan( const Maps::Tile & tile, AI::Planner & ai, const double heroArmyStrength, const double targetStrengthMultiplier ) { return heroArmyStrength > ai.getTileArmyStrength( tile ) * targetStrengthMultiplier; } bool isArmyValuableToObtain( const Troop & monster, double armyStrengthThreshold, const bool armyHasMonster ) { if ( armyHasMonster ) { // Since the army has the same monster the limit must be reduced. armyStrengthThreshold /= 2; } // Do not even care about this monster if it brings no visible advantage to the army. return monster.GetStrength() > armyStrengthThreshold; } bool isArmyValuableToHire( const Army & army, const Kingdom & kingdom, const Maps::Tile & tile, const double armyStrengthThreshold ) { const Troop & troop = getTroopFromTile( tile ); if ( !troop.isValid() ) { return false; } const bool armyHasMonster = army.HasMonster( troop.GetMonster() ); if ( !armyHasMonster && army.isFullHouse() && army.areAllTroopsUnique() ) { return false; } const Funds singleMonsterCost = troop.GetCost(); uint32_t recruitTroopCount = kingdom.GetFunds().getLowestQuotient( singleMonsterCost ); if ( recruitTroopCount == 0 ) { // We do not have resources to hire even a single creature. return false; } const uint32_t availableTroopCount = troop.GetCount(); if ( recruitTroopCount > availableTroopCount ) { recruitTroopCount = availableTroopCount; } const Troop troopToHire{ troop.GetID(), recruitTroopCount }; return isArmyValuableToObtain( troopToHire, armyStrengthThreshold, armyHasMonster ); } bool isSpellUsedByAI( const int spellId ) { // TODO: All these spells are not used by AI at the moment. switch ( spellId ) { case Spell::EARTHQUAKE: case Spell::HAUNT: case Spell::IDENTIFYHERO: case Spell::SETAGUARDIAN: case Spell::SETEGUARDIAN: case Spell::SETFGUARDIAN: case Spell::SETWGUARDIAN: case Spell::TELEPORT: case Spell::VIEWARTIFACTS: case Spell::VIEWHEROES: case Spell::VIEWMINES: case Spell::VIEWRESOURCES: case Spell::VIEWTOWNS: case Spell::VISIONS: return false; default: break; } return true; } bool HeroesValidObject( const Heroes & hero, const double heroArmyStrength, const int32_t index, AIWorldPathfinder & pathfinder, AI::Planner & ai, const double armyStrengthThreshold, const bool underHero ) { const Maps::Tile & tile = world.getTile( index ); const MP2::MapObjectType objectType = tile.getMainObjectType( !underHero ); // WINS_ARTIFACT victory condition does not apply to AI-controlled players, we should leave this artifact untouched for the human player if ( MP2::isArtifactObject( objectType ) ) { const Artifact art = getArtifactFromTile( tile ); if ( art.isValid() && isFindArtifactVictoryConditionForHuman( art ) ) { return false; } } const Army & army = hero.GetArmy(); const Kingdom & kingdom = hero.GetKingdom(); // If you add a new object to a group of objects sort them alphabetically. switch ( objectType ) { case MP2::OBJ_BOTTLE: case MP2::OBJ_CAMPFIRE: case MP2::OBJ_FLOTSAM: case MP2::OBJ_RESOURCE: case MP2::OBJ_SEA_CHEST: case MP2::OBJ_SHIPWRECK_SURVIVOR: case MP2::OBJ_TREASURE_CHEST: return true; case MP2::OBJ_BUOY: case MP2::OBJ_TEMPLE: return !hero.isObjectTypeVisited( objectType ) && hero.GetMorale() < Morale::BLOOD && !army.AllTroopsAreUndead(); case MP2::OBJ_MAGELLANS_MAPS: return !hero.isObjectTypeVisited( objectType, Visit::GLOBAL ) && kingdom.AllowPayment( PaymentConditions::getMagellansMapsPurchasePrice() ); case MP2::OBJ_ALCHEMIST_LAB: case MP2::OBJ_LIGHTHOUSE: case MP2::OBJ_MINE: case MP2::OBJ_SAWMILL: if ( !hero.isFriends( getColorFromTile( tile ) ) ) { if ( isCaptureObjectProtected( tile ) ) { return isHeroStrongerThan( tile, ai, heroArmyStrength, AI::ARMY_ADVANTAGE_SMALL ); } return true; } break; case MP2::OBJ_ABANDONED_MINE: return isHeroStrongerThan( tile, ai, heroArmyStrength, AI::ARMY_ADVANTAGE_LARGE ); case MP2::OBJ_LEAN_TO: case MP2::OBJ_MAGIC_GARDEN: case MP2::OBJ_SKELETON: case MP2::OBJ_WAGON: case MP2::OBJ_WATER_WHEEL: case MP2::OBJ_WINDMILL: return doesTileContainValuableItems( tile ); case MP2::OBJ_ARTIFACT: { if ( hero.IsFullBagArtifacts() ) { return false; } const Artifact art = getArtifactFromTile( tile ); assert( art.isValid() ); if ( art.GetID() == Artifact::MAGIC_BOOK && hero.HaveSpellBook() ) { return false; } const Maps::ArtifactCaptureCondition condition = getArtifactCaptureCondition( tile ); if ( condition == Maps::ArtifactCaptureCondition::PAY_2000_GOLD || condition == Maps::ArtifactCaptureCondition::PAY_2500_GOLD_AND_3_RESOURCES || condition == Maps::ArtifactCaptureCondition::PAY_3000_GOLD_AND_5_RESOURCES ) { return kingdom.AllowPayment( getArtifactResourceRequirement( tile ) ); } if ( condition == Maps::ArtifactCaptureCondition::HAVE_WISDOM_SKILL || condition == Maps::ArtifactCaptureCondition::HAVE_LEADERSHIP_SKILL ) { return hero.HasSecondarySkill( getArtifactSecondarySkillRequirement( tile ).Skill() ); } if ( condition >= Maps::ArtifactCaptureCondition::FIGHT_50_ROGUES && condition <= Maps::ArtifactCaptureCondition::FIGHT_1_BONE_DRAGON ) { return isHeroStrongerThan( tile, ai, heroArmyStrength, AI::ARMY_ADVANTAGE_LARGE ); } // No conditions to capture an artifact exist. return true; } case MP2::OBJ_OBSERVATION_TOWER: { const int32_t fogCountToUncoverByTower = Maps::getFogTileCountToBeRevealed( index, GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::OBSERVATION_TOWER ), hero.GetColor() ); return fogCountToUncoverByTower > 0; } case MP2::OBJ_OBELISK: // TODO: add the logic to dig an Ultimate artifact when a digging tile is visible. // But for now AI should not waste time visiting Obelisks. return false; case MP2::OBJ_BARRIER: return kingdom.IsVisitTravelersTent( getColorFromTile( tile ) ); case MP2::OBJ_TRAVELLER_TENT: return !kingdom.IsVisitTravelersTent( getColorFromTile( tile ) ); case MP2::OBJ_SHRINE_FIRST_CIRCLE: case MP2::OBJ_SHRINE_SECOND_CIRCLE: case MP2::OBJ_SHRINE_THIRD_CIRCLE: { const Spell & spell = getSpellFromTile( tile ); if ( !spell.isValid() ) { // The spell cannot be invalid! assert( 0 ); return false; } if ( !hero.HaveSpellBook() ) { return false; } if ( spell.Level() == 3 && hero.GetLevelSkill( Skill::Secondary::WISDOM ) == Skill::Level::NONE ) { // No reason to visit this shrine as the hero cannot learn this spell. return false; } if ( !hero.isVisited( tile, Visit::GLOBAL ) ) { // This shrine has not been visited by any hero. It's worth to do it. return true; } if ( hero.HaveSpell( spell, true ) || !isSpellUsedByAI( spell.GetID() ) ) { return false; } return true; } // Arena allows to visit only one time for the whole map. case MP2::OBJ_ARENA: return !hero.isObjectTypeVisited( objectType ); // On-time visit free Primary Skill or Experience object. case MP2::OBJ_FORT: case MP2::OBJ_GAZEBO: case MP2::OBJ_MERCENARY_CAMP: case MP2::OBJ_STANDING_STONES: case MP2::OBJ_WITCH_DOCTORS_HUT: return !hero.isVisited( tile ); // One time visit Secondary Skill object. case MP2::OBJ_WITCHS_HUT: { const Skill::Secondary & skill = getSecondarySkillFromWitchsHut( tile ); const int skillType = skill.Skill(); if ( !skill.isValid() ) { // How is it possible that no skill exist? assert( 0 ); return false; } if ( hero.HasMaxSecondarySkill() ) { return false; } if ( !hero.isVisited( tile, Visit::GLOBAL ) ) { // The AI heroes should not have prior knowledge what skill this object has. return true; } if ( hero.HasSecondarySkill( skillType ) ) { return false; } if ( army.AllTroopsAreUndead() && skillType == Skill::Secondary::LEADERSHIP ) { // For undead army it's pointless to have Leadership skill. return false; } if ( !hero.HaveSpellBook() && ( skillType == Skill::Secondary::MYSTICISM || skillType == Skill::Secondary::EAGLE_EYE ) ) { // It's useless to have Mysticism with no magic book in hands. return false; } return true; } case MP2::OBJ_TREE_OF_KNOWLEDGE: if ( !hero.isVisited( tile ) ) { const Funds & rc = getTreeOfKnowledgeRequirement( tile ); // If the payment is required do not waste all resources from the kingdom. Use them wisely. if ( rc.GetValidItemsCount() == 0 || kingdom.AllowPayment( rc * 5 ) ) { return true; } } break; // Objects increasing Luck. case MP2::OBJ_FAERIE_RING: case MP2::OBJ_FOUNTAIN: case MP2::OBJ_IDOL: case MP2::OBJ_MERMAID: return !hero.isObjectTypeVisited( objectType ) && hero.GetLuck() < Luck::IRISH; // Objects increasing Movement points and Morale. case MP2::OBJ_OASIS: case MP2::OBJ_WATERING_HOLE: { if ( hero.isObjectTypeVisited( objectType ) ) { return false; } const auto [distance, dummy] = getDistanceToTile( pathfinder, index ); if ( distance == 0 ) { return false; } const double movementPenalty = 2.0 * distance; return movementPenalty < GameStatic::getMovementPointBonus( objectType ) || hero.GetMorale() < Morale::BLOOD; } case MP2::OBJ_MAGIC_WELL: { if ( hero.isObjectTypeVisited( objectType ) ) { return false; } if ( !hero.HaveSpellBook() ) { return false; } if ( hero.GetSpellPoints() >= hero.GetMaxSpellPoints() ) { return false; } const auto [distance, dummy] = getDistanceToTile( pathfinder, index ); if ( distance == 0 ) { return false; } if ( distance > hero.GetMovePoints() && hero.getDailyRestoredSpellPoints() + hero.GetSpellPoints() >= hero.GetMaxSpellPoints() ) { // The Well is located at a distance which cannot be reached by the hero at the current turn. // But if the hero will restore all spell points by the next day there is no reason to even to visit the Well. return false; } return true; } case MP2::OBJ_ARTESIAN_SPRING: return !world.isAnyKingdomVisited( objectType, index ) && hero.HaveSpellBook() && hero.GetSpellPoints() < 2 * hero.GetMaxSpellPoints(); case MP2::OBJ_XANADU: return !hero.isVisited( tile ) && GameStatic::isHeroWorthyToVisitXanadu( hero ); // Dwellings with free army. case MP2::OBJ_ARCHER_HOUSE: case MP2::OBJ_CAVE: case MP2::OBJ_DWARF_COTTAGE: case MP2::OBJ_EXCAVATION: case MP2::OBJ_GOBLIN_HUT: case MP2::OBJ_HALFLING_HOLE: case MP2::OBJ_PEASANT_HUT: case MP2::OBJ_TREE_HOUSE: case MP2::OBJ_WATCH_TOWER: { const Troop & troop = getTroopFromTile( tile ); if ( !troop.isValid() ) { return false; } const bool armyHasMonster = army.HasMonster( troop.GetMonster() ); if ( !armyHasMonster && army.isFullHouse() && army.areAllTroopsUnique() ) { return false; } return isArmyValuableToObtain( troop, armyStrengthThreshold, armyHasMonster ); } // Dwellings where AI can recruit an army. case MP2::OBJ_AIR_ALTAR: case MP2::OBJ_BARROW_MOUNDS: case MP2::OBJ_DESERT_TENT: case MP2::OBJ_EARTH_ALTAR: case MP2::OBJ_FIRE_ALTAR: case MP2::OBJ_GENIE_LAMP: case MP2::OBJ_RUINS: case MP2::OBJ_TREE_CITY: case MP2::OBJ_WAGON_CAMP: case MP2::OBJ_WATER_ALTAR: return isArmyValuableToHire( army, kingdom, tile, armyStrengthThreshold ); // Dwellings where AI might fight monsters first before recruiting them. case MP2::OBJ_CITY_OF_DEAD: case MP2::OBJ_DRAGON_CITY: case MP2::OBJ_TROLL_BRIDGE: { if ( Color::NONE == getColorFromTile( tile ) ) { return isHeroStrongerThan( tile, ai, heroArmyStrength, AI::ARMY_ADVANTAGE_MEDIUM ); } return isArmyValuableToHire( army, kingdom, tile, armyStrengthThreshold ); } // Free army upgrade objects. case MP2::OBJ_FREEMANS_FOUNDRY: return army.HasMonster( Monster::PIKEMAN ) || army.HasMonster( Monster::SWORDSMAN ) || army.HasMonster( Monster::IRON_GOLEM ); case MP2::OBJ_HILL_FORT: return army.HasMonster( Monster::DWARF ) || army.HasMonster( Monster::ORC ) || army.HasMonster( Monster::OGRE ); // Free army upgrade and extra movement points for the rest of the week. case MP2::OBJ_STABLES: { if ( army.HasMonster( Monster::CAVALRY ) ) { return true; } if ( hero.isObjectTypeVisited( objectType ) ) { return false; } const auto [distance, dummy] = getDistanceToTile( pathfinder, index ); if ( distance == 0 ) { return false; } const int daysActive = numOfDaysPerWeek - world.GetDay() + 1; const double movementBonus = daysActive * GameStatic::getMovementPointBonus( objectType ) - 2.0 * distance; return movementBonus > 0; } // Objects that give goods but curse with bad morale when visiting them for subsequent times. case MP2::OBJ_DERELICT_SHIP: case MP2::OBJ_GRAVEYARD: case MP2::OBJ_SHIPWRECK: if ( !hero.isVisited( tile, Visit::GLOBAL ) && doesTileContainValuableItems( tile ) ) { Army enemy( tile ); return enemy.isValid() && isHeroStrongerThan( tile, ai, heroArmyStrength, 2 ); } break; case MP2::OBJ_PYRAMID: if ( !hero.isVisited( tile, Visit::GLOBAL ) && doesTileContainValuableItems( tile ) ) { Army enemy( tile ); return enemy.isValid() && Skill::Level::EXPERT == hero.GetLevelSkill( Skill::Secondary::WISDOM ) && isHeroStrongerThan( tile, ai, heroArmyStrength, AI::ARMY_ADVANTAGE_LARGE ); } break; case MP2::OBJ_DAEMON_CAVE: if ( doesTileContainValuableItems( tile ) ) { // AI always chooses to fight the demon's servants and doesn't roll the dice return isHeroStrongerThan( tile, ai, heroArmyStrength, AI::ARMY_ADVANTAGE_MEDIUM ); } break; case MP2::OBJ_MONSTER: return isHeroStrongerThan( tile, ai, heroArmyStrength, ( hero.isLosingGame() ? 1.0 : AI::ARMY_ADVANTAGE_MEDIUM ) ); case MP2::OBJ_HERO: { const Heroes * otherHero = tile.getHero(); assert( otherHero != nullptr ); const bool otherHeroInCastle = ( otherHero->inCastle() != nullptr ); if ( hero.GetColor() == otherHero->GetColor() ) { if ( hero.hasMetWithHero( otherHero->GetID() ) ) { return false; } return !otherHeroInCastle; } if ( hero.isFriends( otherHero->GetColor() ) ) { return false; } // WINS_HERO victory condition does not apply to AI-controlled players, we have to keep this hero alive for the human player if ( otherHero == world.GetHeroesCondWins() ) { return false; } if ( otherHeroInCastle ) { return AIShouldVisitCastle( hero, index, heroArmyStrength ); } return army.isStrongerThan( otherHero->GetArmy(), hero.isLosingGame() ? AI::ARMY_ADVANTAGE_DESPERATE : AI::ARMY_ADVANTAGE_SMALL ); } case MP2::OBJ_CASTLE: return AIShouldVisitCastle( hero, index, heroArmyStrength ); case MP2::OBJ_JAIL: return kingdom.GetHeroes().size() < Kingdom::GetMaxHeroes(); case MP2::OBJ_HUT_OF_MAGI: return !hero.isObjectTypeVisited( objectType, Visit::GLOBAL ) && Maps::doesObjectExistOnMap( MP2::OBJ_EYE_OF_MAGI ); case MP2::OBJ_ALCHEMIST_TOWER: { const BagArtifacts & bag = hero.GetBagArtifacts(); const uint32_t cursed = static_cast( std::count_if( bag.begin(), bag.end(), []( const Artifact & art ) { return art.containsCurses(); } ) ); if ( cursed == 0 ) { return false; } const Funds payment = PaymentConditions::ForAlchemist(); return kingdom.AllowPayment( payment ); } // AI should never consider a boat as a destination point. It uses them only to make a path. case MP2::OBJ_BOAT: // Eye of Magi is not an action object at all. case MP2::OBJ_EYE_OF_MAGI: // No use of these object for AI. case MP2::OBJ_ORACLE: // AI has no brains to do anything from sign messages. case MP2::OBJ_SIGN: // AI has no brains to handle Sirens object. case MP2::OBJ_SIRENS: // TODO: AI doesn't know how it use Sphinx object properly. case MP2::OBJ_SPHINX: // AI should never consider a stone lith as a destination point. It uses them only to make a path. case MP2::OBJ_STONE_LITHS: // TODO: AI doesn't know how it use Trading Post object properly. case MP2::OBJ_TRADING_POST: // AI should never consider a whirlpool as a destination point. It uses them only to make a path. case MP2::OBJ_WHIRLPOOL: return false; default: // Did you add a new action object but forget to add AI interaction for it? assert( 0 ); break; } return false; } void addHeroToMove( Heroes * hero, std::vector & availableHeroes ) { if ( hero->Modes( Heroes::PATROL ) && ( hero->GetPatrolDistance() == 0 ) ) { DEBUG_LOG( DBG_AI, DBG_TRACE, hero->GetName() << " stands still due to the patrol settings" ) return; } if ( hero->MayStillMove( false, false ) ) { availableHeroes.emplace_back( hero ); } } // Used for caching object validations per hero. class ObjectValidator { public: explicit ObjectValidator( const Heroes & hero, AIWorldPathfinder & pathfinder, AI::Planner & ai ) : _hero( hero ) , _pathfinder( pathfinder ) , _ai( ai ) , _heroArmyStrength( hero.GetArmy().GetStrength() ) , _armyStrengthThreshold( hero.getAIMinimumJoiningArmyStrength() ) { // Do nothing. } bool isValid( const int index ) { auto iter = _validObjects.find( index ); if ( iter != _validObjects.end() ) { return iter->second; } const bool valid = HeroesValidObject( _hero, _heroArmyStrength, index, _pathfinder, _ai, _armyStrengthThreshold, false ); _validObjects[index] = valid; return valid; } private: const Heroes & _hero; AIWorldPathfinder & _pathfinder; AI::Planner & _ai; // Hero's strength value is valid till any action is done. // Since an instance of this class is used only for evaluation of the future movement it is appropriate to cache the strength. const double _heroArmyStrength; // Army strength threshold is used to decide whether getting extra monsters is useful. const double _armyStrengthThreshold; std::map _validObjects; }; // Used for caching of object value estimation per hero. class ObjectValueStorage { public: ObjectValueStorage( const Heroes & hero, const AI::Planner & ai, const double ignoreValue ) : _hero( hero ) , _ai( ai ) , _ignoreValue( ignoreValue ) {} double value( const IndexObject & objectInfo, const uint32_t distance ) { const auto [iter, inserted] = _objectValue.try_emplace( objectInfo, 0.0 ); if ( inserted ) { iter->second = _ai.getObjectValue( _hero, objectInfo.first, objectInfo.second, _ignoreValue, distance ); } return iter->second; } private: const Heroes & _hero; const AI::Planner & _ai; const double _ignoreValue; std::map _objectValue; }; double getMonsterUpgradeValue( const Army & army, const int monsterId ) { const uint32_t monsterCount = army.GetCountMonsters( monsterId ); if ( monsterCount == 0 ) { // Nothing to upgrade. return 0; } const Monster currentMonster( monsterId ); const Monster upgradedMonster = currentMonster.GetUpgrade(); if ( upgradedMonster == currentMonster ) { // Monster has no upgrade. return 0; } return ( upgradedMonster.GetMonsterStrength() - currentMonster.GetMonsterStrength() ) * monsterCount; } // Multiply by this value if you are getting a FREE upgrade. const double freeMonsterUpgradeModifier = 3; // TODO: consider making this penalty dynamic const double dangerousTaskPenalty = 50000.0; const double fogDiscoveryBaseValue = -10000.0; double getDistanceModifier( const MP2::MapObjectType objectType ) { // The value above 1.0 means that the object is useful only if it is nearby. // The value below 1.0 means that the object should remain in focus even on greater distances. if ( !MP2::isInGameActionObject( objectType ) ) { return 1.0; } switch ( objectType ) { case MP2::OBJ_CASTLE: return 0.8; case MP2::OBJ_ALCHEMIST_LAB: case MP2::OBJ_ARTIFACT: case MP2::OBJ_HERO: case MP2::OBJ_MINE: case MP2::OBJ_SAWMILL: return 0.9; case MP2::OBJ_CAMPFIRE: case MP2::OBJ_FLOTSAM: case MP2::OBJ_GENIE_LAMP: case MP2::OBJ_RESOURCE: case MP2::OBJ_SEA_CHEST: case MP2::OBJ_TREASURE_CHEST: return 0.95; case MP2::OBJ_BUOY: case MP2::OBJ_TEMPLE: case MP2::OBJ_FAERIE_RING: case MP2::OBJ_FOUNTAIN: case MP2::OBJ_IDOL: case MP2::OBJ_MERMAID: // In most situations Luck and Morale modifier objects are useful to be visited when they are very close. return 1.1; default: break; } return 1.0; } double scaleWithDistanceAndTime( const double value, const uint32_t distance, const MP2::MapObjectType objectType ) { if ( distance == 0 ) { return value; } // Some objects do not loose their value drastically over distances. This allows AI heroes to keep focus on important targets. double correctedDistance = distance * getDistanceModifier( objectType ); // Distances should be corrected over time as AI heroes should focus on keeping important objects in focus. // This value shouldn't be big but very slowly increases over time. const double timeCorrectionCoeff = 1 - std::min( 0.5, world.CountDay() * 0.0001 ); correctedDistance *= timeCorrectionCoeff; // Scale non-linearly (more value lost as distance increases) return value - ( correctedDistance * std::log10( correctedDistance ) ); } double getFogDiscoveryValue( const Heroes & hero ) { switch ( hero.getAIRole() ) { case Heroes::Role::SCOUT: // Scouts do not have any penalty on map exploration as it is their main priority. return 0; case Heroes::Role::HUNTER: case Heroes::Role::FIGHTER: case Heroes::Role::CHAMPION: return fogDiscoveryBaseValue; case Heroes::Role::COURIER: return fogDiscoveryBaseValue * 2; default: // If you set a new type of a hero you must add the logic here. assert( 0 ); break; } return fogDiscoveryBaseValue; } double getSecondarySkillValue( const Heroes & hero, const Skill::Secondary & skill ) { const int type = skill.Skill(); const int level = skill.Level(); if ( hero.GetLevelSkill( type ) >= level ) { return 0; } switch ( type ) { case Skill::Secondary::WISDOM: // wouldn't check castles/spell availability since high wisdom drives building priority return level == Skill::Level::BASIC ? 2500.0 : 1000.0; case Skill::Secondary::LOGISTICS: return 1500.0; case Skill::Secondary::LEADERSHIP: return hero.GetArmy().AllTroopsAreUndead() ? 100.0 : 1000.0; case Skill::Secondary::NECROMANCY: return hero.GetArmy().AllTroopsAreUndead() ? 1000.0 : 100.0; case Skill::Secondary::LUCK: { const Heroes::Role role = hero.getAIRole(); if ( role == Heroes::Role::COURIER || role == Heroes::Role::SCOUT ) { return 100.0; } return 500.0; } case Skill::Secondary::BALLISTICS: { const Heroes::Role role = hero.getAIRole(); if ( role == Heroes::Role::COURIER || role == Heroes::Role::SCOUT ) { return 100.0; } return hero.GetArmy().isMeleeDominantArmy() ? 1250.0 : 250.0; } case Skill::Secondary::ARCHERY: { const Heroes::Role role = hero.getAIRole(); if ( role == Heroes::Role::COURIER || role == Heroes::Role::SCOUT ) { return 100.0; } return hero.GetArmy().isMeleeDominantArmy() ? 100.0 : 500.0; } case Skill::Secondary::ESTATES: { const Heroes::Role role = hero.getAIRole(); if ( role == Heroes::Role::CHAMPION || role == Heroes::Role::FIGHTER ) { return 0.0; } return 1000.0; } case Skill::Secondary::PATHFINDING: { const double roughness = world.getLandRoughness(); return ( roughness > 1.25 ) ? 1000.0 : ( roughness > 1.1 ) ? 250.0 : 100.0; } case Skill::Secondary::NAVIGATION: { const uint8_t waterPercentage = world.getWaterPercentage(); return ( waterPercentage > 60 ) ? 1000.0 : ( waterPercentage > 25 ) ? 100.0 : 0.0; } case Skill::Secondary::SCOUTING: { const Heroes::Role role = hero.getAIRole(); if ( role == Heroes::Role::CHAMPION || role == Heroes::Role::FIGHTER ) { return 0.0; } return hero.getAIRole() == Heroes::Role::SCOUT ? 1250.0 : 100.0; } case Skill::Secondary::MYSTICISM: return hero.HaveSpellBook() ? 500.0 : 100.0; case Skill::Secondary::EAGLE_EYE: return hero.HaveSpellBook() ? 250.0 : 0.0; case Skill::Secondary::DIPLOMACY: // discourage AI picking it up, but if it's already there prioritise leveling to save gold return level == Skill::Level::BASIC ? 100.0 : 1250.0; case Skill::Secondary::UNKNOWN: return 0; default: // If you make a new secondary skill don't forget to update this. assert( 0 ); break; } return 0; } uint32_t getTimeoutBeforeFogDiscoveryIntensification( const Heroes & hero ) { switch ( hero.getAIRole() ) { case Heroes::Role::SCOUT: return 30; case Heroes::Role::HUNTER: return 90; case Heroes::Role::FIGHTER: case Heroes::Role::CHAMPION: return 60; case Heroes::Role::COURIER: return 120; default: // If you set a new type of a hero you must add the logic here. assert( 0 ); break; } return 30; } } // TODO: In the future we need to come up with dynamic object value estimation based not only on a hero's role but on an outcome from movement at certain position. double AI::Planner::getGeneralObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const { // In the future these hardcoded values could be configured by the mod // 1 tile distance is 100.0 value approximately const Maps::Tile & tile = world.getTile( index ); const MP2::MapObjectType objectType = tile.getMainObjectType(); const std::function calculateCastleValue = [this, &hero, &calculateCastleValue]( const Castle * castle ) { assert( castle != nullptr ); double value = castle->getBuildingValue() * 150.0 + 3000; if ( hero.isLosingGame() ) { value += 15000; } if ( isCastleLossConditionForHuman( castle ) ) { value += 20000; } // This modifier shouldn't be too high to avoid players baiting AI in const double defenselessCastleModifier = 1.25; // This is our own castle in need of protection, evaluate it no worse than a similar defenseless enemy castle if ( hero.GetColor() == castle->GetColor() ) { value *= defenselessCastleModifier; } else { const int32_t castleIndex = castle->GetIndex(); // If this castle threatens our castles, then we should evaluate it no worse than the best of our castles that it threatens // (as if our best castle had to be taken back from the enemy). If a threatening castle can be attacked right now, it is // better to do it than wait until the hero hired in it captures one of our castles. if ( isCriticalTask( castleIndex ) ) { const auto iter = _priorityTargets.find( castleIndex ); assert( iter != _priorityTargets.end() ); const PriorityTask & attackTask = iter->second; assert( attackTask.type == PriorityTaskType::ATTACK ); for ( const int32_t secondaryTaskTileIdx : attackTask.secondaryTaskTileId ) { const Castle * castleUnderThreat = world.getCastleEntrance( Maps::GetPoint( secondaryTaskTileIdx ) ); if ( castleUnderThreat == nullptr ) { continue; } assert( hero.GetColor() == castleUnderThreat->GetColor() ); // Apply a bonus so that the AI prefers to eliminate the threat if possible instead of guarding its castle value = std::max( value, calculateCastleValue( castleUnderThreat ) * 2 ); } } // This castle is defenseless if ( !castle->GetActualArmy().isValid() ) { value *= defenselessCastleModifier; } } return value; }; switch ( objectType ) { case MP2::OBJ_CASTLE: { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( index ) ); if ( !castle ) { // How is it even possible? assert( 0 ); return valueToIgnore; } if ( hero.GetColor() == castle->GetColor() ) { // If our castle is in danger, then we should evaluate it not from the point of view of momentary benefits // for the hero (for example, the presence of reinforcements), but from the point of view of the castle, // which then will have to be taken back from the enemy, that is, according to approximately the same logic // as enemy castles if ( isCriticalTask( index ) ) { return calculateCastleValue( castle ); } double value = castle->getVisitValue( hero ); if ( !isPriorityTask( index ) && value < 500 ) { return valueToIgnore; } return value; } // Hero should never visit castles belonging to friendly kingdoms if ( hero.isFriends( castle->GetColor() ) ) { assert( 0 ); return -dangerousTaskPenalty; } // WINS_HERO victory condition does not apply to AI-controlled players, we have to ignore the castle with this hero // to keep him alive for the human player if ( isHeroWhoseDefeatIsVictoryConditionForHumanInCastle( castle ) ) { assert( 0 ); return -dangerousTaskPenalty; } return calculateCastleValue( castle ); } case MP2::OBJ_HERO: { const Heroes * otherHero = tile.getHero(); if ( !otherHero ) { // How is it even possible? assert( 0 ); return valueToIgnore; } if ( hero.GetColor() == otherHero->GetColor() ) { if ( hero.getAIRole() > otherHero->getAIRole() ) { // The other hero has a lower role. Do not waste time for meeting. Let him to come. return valueToIgnore; } if ( hero.getAIRole() == otherHero->getAIRole() && hero.getStatsValue() + Difficulty::getMinStatDiffForAIHeroesMeeting( Game::getDifficulty() ) > otherHero->getStatsValue() ) { // Either this hero is superior or approximately equal to another hero in terms of stats. Do not waste time for meeting. Let him come instead. return valueToIgnore; } const double value = hero.getMeetingValue( *otherHero ); // limit the max value of friendly hero meeting to 30 tiles return ( value < 250 ) ? valueToIgnore : std::min( value, 10000.0 ); } // Hero should never meet heroes from friendly kingdoms if ( hero.isFriends( otherHero->GetColor() ) ) { assert( 0 ); return -dangerousTaskPenalty; } // WINS_HERO victory condition does not apply to AI-controlled players, we have to keep this hero alive for the human player if ( otherHero == world.GetHeroesCondWins() ) { assert( 0 ); return -dangerousTaskPenalty; } double value = 5000; // If this hero threatens our castles, then we should evaluate him no worse than the best of our castles that he threatens // (as if it had to be taken back from the enemy). If a threatening hero can be attacked in an open field, it is better to // do it now than to attack him later in our castle occupied by him. if ( isCriticalTask( index ) ) { const auto iter = _priorityTargets.find( index ); assert( iter != _priorityTargets.end() ); const PriorityTask & attackTask = iter->second; assert( attackTask.type == PriorityTaskType::ATTACK ); for ( const int32_t secondaryTaskTileIdx : attackTask.secondaryTaskTileId ) { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( secondaryTaskTileIdx ) ); if ( castle == nullptr ) { continue; } assert( hero.GetColor() == castle->GetColor() ); // Apply a bonus so that the AI prefers to eliminate the threat if possible instead of guarding its castle value = std::max( value, calculateCastleValue( castle ) * 2 ); } } else { const Castle * castle = otherHero->inCastle(); if ( castle != nullptr ) { // If the enemy hero is in the castle, then after defeating this hero, AI will automatically capture his // castle, so it's worth adding the value of the castle to the value of the enemy hero value += calculateCastleValue( castle ); } else if ( otherHero->GetControl() == CONTROL_AI ) { // AI heroes should not attack other AI heroes so aggressively as human heroes. // This is done to avoid situations when human players just wait when AI heroes kill each other. value *= 0.8; } } return value; } case MP2::OBJ_MONSTER: { const Army monsters( tile ); if ( !monsters.isValid() ) { // How is it even possible? assert( 0 ); return -dangerousTaskPenalty; } // TODO: we should add logic to compare monsters and hero army strengths. return 1000.0 + monsters.getTotalHP() / 100.0; } case MP2::OBJ_ALCHEMIST_LAB: case MP2::OBJ_MINE: case MP2::OBJ_SAWMILL: case MP2::OBJ_ABANDONED_MINE: { int resourceType = Resource::UNKNOWN; int32_t resourceAmount = 0; // Abandoned mines are gold mines under the hood if ( objectType == MP2::OBJ_ABANDONED_MINE ) { resourceType = Resource::GOLD; resourceAmount = ProfitConditions::FromMine( Resource::GOLD ).Get( Resource::GOLD ); } else { if ( getColorFromTile( tile ) == hero.GetColor() ) { return valueToIgnore; // don't even attempt to go here } std::tie( resourceType, resourceAmount ) = getDailyIncomeObjectResources( tile ).getFirstValidResource(); } assert( resourceType != Resource::UNKNOWN && resourceAmount != 0 ); // Since mines constantly bring resources, they are valuable objects return resourceAmount * getResourcePriorityModifier( resourceType, true ); } case MP2::OBJ_ARTIFACT: case MP2::OBJ_SHIPWRECK_SURVIVOR: { const Artifact art = getArtifactFromTile( tile ); assert( art.isValid() ); // WINS_ARTIFACT victory condition does not apply to AI-controlled players, we should leave this artifact untouched for the human player if ( isFindArtifactVictoryConditionForHuman( art ) ) { assert( 0 ); return -dangerousTaskPenalty; } return 1000.0 * art.getArtifactValue(); } case MP2::OBJ_SEA_CHEST: case MP2::OBJ_TREASURE_CHEST: { const Artifact art = getArtifactFromTile( tile ); if ( art.isValid() && isFindArtifactVictoryConditionForHuman( art ) ) { // WINS_ARTIFACT victory condition does not apply to AI-controlled players, we should leave this object untouched for the human player. assert( 0 ); return -dangerousTaskPenalty; } // This is an average gold amount you can get from a treasure chest or sea chest. return getFundsValueBasedOnPriority( { Resource::GOLD, 1500 } ); } case MP2::OBJ_DAEMON_CAVE: { // If this cave is already empty, then we should never come here if ( !doesTileContainValuableItems( tile ) ) { assert( 0 ); return -dangerousTaskPenalty; } // Daemon Cave always gives 2500 Gold after a battle and AI always chooses to fight the demon's servants and doesn't roll the dice return getFundsValueBasedOnPriority( { Resource::GOLD, 2500 } ); } case MP2::OBJ_GRAVEYARD: case MP2::OBJ_SHIPWRECK: case MP2::OBJ_SKELETON: case MP2::OBJ_WAGON: { if ( !getArtifactFromTile( tile ).isValid() ) { // Don't waste time to go here. return -dangerousTaskPenalty; } const Artifact art = getArtifactFromTile( tile ); // WINS_ARTIFACT victory condition does not apply to AI-controlled players, we should leave this artifact untouched for the human player if ( isFindArtifactVictoryConditionForHuman( art ) ) { assert( 0 ); return -dangerousTaskPenalty; } return 1000.0 * art.getArtifactValue(); } case MP2::OBJ_BOTTLE: { // A bottle is useless to AI as it contains only a message but it might block path. return 0; } case MP2::OBJ_CAMPFIRE: { // A campfire has 4-6 random resources plus 400-600 gold so we use an average to get evaluation. // Since we should not expose the resource type let's assume that it gives 6 resources, 1 each and 400 gold. const Funds loot{ 1, 1, 1, 1, 1, 1, 400 }; const double value = getFundsValueBasedOnPriority( loot ); assert( value > 0 ); return value; } case MP2::OBJ_MAGIC_GARDEN: { // Magic Garden has visual representation whether it was visited so verify that is has resources. assert( doesTileContainValuableItems( tile ) ); // Magic Garden can have either 5 gems or 500 gold. Since, 5 is not divisible by 2, let's put 3 instead. const Funds loot{ 0, 0, 0, 0, 0, 3, 250 }; const double value = getFundsValueBasedOnPriority( loot ); assert( value > 0 ); return value; } case MP2::OBJ_RESOURCE: { const Funds loot = getFundsFromTile( tile ); // Resource object has visual representation of the type of resources. const auto & [resourceType, resourceCount] = loot.getFirstValidResource(); Funds estimatedResource; switch ( resourceType ) { case Resource::GOLD: estimatedResource = Funds( resourceType, 750 ); break; case Resource::WOOD: case Resource::ORE: estimatedResource = Funds( resourceType, 7 ); break; case Resource::MERCURY: case Resource::SULFUR: case Resource::CRYSTAL: case Resource::GEMS: estimatedResource = Funds( resourceType, 4 ); break; default: assert( 0 ); break; } const double value = getFundsValueBasedOnPriority( estimatedResource ); assert( value > 0 ); return value; } case MP2::OBJ_DERELICT_SHIP: case MP2::OBJ_LEAN_TO: case MP2::OBJ_WATER_WHEEL: case MP2::OBJ_WINDMILL: { const Funds loot = getFundsFromTile( tile ); const double value = getFundsValueBasedOnPriority( loot ); // This object could have already been visited if ( value < 1 ) { return valueToIgnore; } return value; } case MP2::OBJ_FLOTSAM: { // Flotsam has the following chances and resources: // - 25%: 500 gold + 10 wood // - 25%: 200 gold + 5 wood // - 25%: 5 wood // - 25%: empty // Therefore, use an average value as an estimation of a possible reward of picking this object. // The AI must not know precise reward from this object as it would be called cheating. // For all cases we have: 700 gold and 20 wood. So we divide by 4 to get an average number of resources. // In total, we should use 175 gold and 5 wood. const Funds loot{ 0, 5, 0, 0, 0, 0, 175 }; const double value = getFundsValueBasedOnPriority( loot ); assert( value > 0 ); return value; } case MP2::OBJ_LIGHTHOUSE: { // TODO: add more complex logic for cases when AI has boats. if ( getColorFromTile( tile ) == hero.GetColor() ) { return -dangerousTaskPenalty; // don't even attempt to go here } return 500; } case MP2::OBJ_XANADU: { return 3000; } case MP2::OBJ_SHRINE_FIRST_CIRCLE: case MP2::OBJ_SHRINE_SECOND_CIRCLE: case MP2::OBJ_SHRINE_THIRD_CIRCLE: { const Spell & spell = getSpellFromTile( tile ); return spell.getStrategicValue( hero.GetArmy().GetStrength(), hero.GetMaxSpellPoints(), hero.GetPower() ); } case MP2::OBJ_ARENA: case MP2::OBJ_FORT: case MP2::OBJ_MERCENARY_CAMP: case MP2::OBJ_STANDING_STONES: case MP2::OBJ_TREE_OF_KNOWLEDGE: case MP2::OBJ_WITCH_DOCTORS_HUT: case MP2::OBJ_WITCHS_HUT: { return 500.0; } // These are dwelling where monsters can be purchased. case MP2::OBJ_AIR_ALTAR: case MP2::OBJ_BARROW_MOUNDS: case MP2::OBJ_CITY_OF_DEAD: case MP2::OBJ_DESERT_TENT: case MP2::OBJ_DRAGON_CITY: case MP2::OBJ_EARTH_ALTAR: case MP2::OBJ_FIRE_ALTAR: case MP2::OBJ_GENIE_LAMP: case MP2::OBJ_RUINS: case MP2::OBJ_TREE_CITY: case MP2::OBJ_TROLL_BRIDGE: case MP2::OBJ_WAGON_CAMP: case MP2::OBJ_WATER_ALTAR: { const Troop & troop = getTroopFromTile( tile ); if ( !troop.isValid() ) { // This should not happen! The dwelling must have monsters to reach this code. assert( 0 ); return -dangerousTaskPenalty; } const Funds singleMonsterCost = troop.GetCost(); uint32_t recruitTroopCount = hero.GetKingdom().GetFunds().getLowestQuotient( singleMonsterCost ); if ( recruitTroopCount == 0 ) { // This can actually happen when AI spends some money in between visiting objects. return -dangerousTaskPenalty; } const uint32_t availableTroopCount = troop.GetCount(); if ( recruitTroopCount > availableTroopCount ) { recruitTroopCount = availableTroopCount; } return Troop{ troop.GetID(), recruitTroopCount }.GetStrength(); } // These are dwellings where monsters can be hired for free. case MP2::OBJ_ARCHER_HOUSE: case MP2::OBJ_CAVE: case MP2::OBJ_DWARF_COTTAGE: case MP2::OBJ_EXCAVATION: case MP2::OBJ_GOBLIN_HUT: case MP2::OBJ_HALFLING_HOLE: case MP2::OBJ_PEASANT_HUT: case MP2::OBJ_TREE_HOUSE: case MP2::OBJ_WATCH_TOWER: { return getTroopFromTile( tile ).GetStrength(); } case MP2::OBJ_STONE_LITHS: { // Stone lith is not considered by AI as an action object. If this assertion blows up something is wrong with the logic. assert( 0 ); return -dangerousTaskPenalty; } case MP2::OBJ_OBSERVATION_TOWER: { const int32_t fogCountToUncoverByTower = Maps::getFogTileCountToBeRevealed( index, GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::OBSERVATION_TOWER ), hero.GetColor() ); if ( fogCountToUncoverByTower == 0 ) { // Nothing to uncover. return -dangerousTaskPenalty; } return fogCountToUncoverByTower; } case MP2::OBJ_MAGELLANS_MAPS: { // Very valuable object. return 5000; } case MP2::OBJ_BOAT: case MP2::OBJ_COAST: case MP2::OBJ_WHIRLPOOL: { // Coast is not an object while Whirlpool and Boat are not considered by AI as an action object. // If this assertion blows up something is wrong with the logic. assert( 0 ); return -dangerousTaskPenalty; } case MP2::OBJ_ARTESIAN_SPRING: { if ( !hero.HaveSpellBook() || hero.GetSpellPoints() * 2 >= hero.GetMaxSpellPoints() ) { // No reason to visit Artesian Spring with no magic book or if no points will be gained. return -dangerousTaskPenalty; } return hero.isPotentSpellcaster() ? 1500 : 0; } case MP2::OBJ_MAGIC_WELL: { if ( !hero.HaveSpellBook() || hero.GetSpellPoints() >= hero.GetMaxSpellPoints() ) { // No reason to visit Magic Well with no magic book or if no points will be gained. return -dangerousTaskPenalty; } return hero.isPotentSpellcaster() ? 1500 : 0; } case MP2::OBJ_BUOY: case MP2::OBJ_TEMPLE: { if ( hero.GetArmy().AllTroopsAreUndead() ) { // All troops are undead, no use of Morale. return 0; } const int morale = hero.GetMorale(); if ( morale >= Morale::BLOOD ) { return -dangerousTaskPenalty; // No reason to visit with maximum morale } if ( morale == Morale::GREAT ) { return -4000; // Morale is good enough to avoid visiting this object } if ( morale == Morale::GOOD ) { return -2000; // Is it worth visiting this facility with a morale slightly better than neutral? } if ( morale == Morale::NORMAL ) { return 50; } return 100; } case MP2::OBJ_STABLES: { const int daysActive = numOfDaysPerWeek - world.GetDay() + 1; double movementBonus = daysActive * GameStatic::getMovementPointBonus( objectType ) - 2.0 * distanceToObject; const double upgradeValue = getMonsterUpgradeValue( hero.GetArmy(), Monster::CHAMPION ); if ( upgradeValue > 0.0001 ) { // Even if no movement bonus exist it is worth to visit just to upgrade monsters. return std::max( movementBonus, 0.0 ) + freeMonsterUpgradeModifier * upgradeValue; } if ( movementBonus < 0 ) { // Don't waste movement to even visit this object. return -dangerousTaskPenalty; } return movementBonus; } case MP2::OBJ_FREEMANS_FOUNDRY: { const double upgradePikemanValue = getMonsterUpgradeValue( hero.GetArmy(), Monster::PIKEMAN ); const double upgradeSwordsmanValue = getMonsterUpgradeValue( hero.GetArmy(), Monster::SWORDSMAN ); const double upgradeGolemValue = getMonsterUpgradeValue( hero.GetArmy(), Monster::IRON_GOLEM ); return freeMonsterUpgradeModifier * ( upgradePikemanValue + upgradeSwordsmanValue + upgradeGolemValue ); } case MP2::OBJ_HILL_FORT: { const double upgradeDwarfValue = getMonsterUpgradeValue( hero.GetArmy(), Monster::DWARF ); const double upgradeOrcValue = getMonsterUpgradeValue( hero.GetArmy(), Monster::ORC ); const double upgradeOgreValue = getMonsterUpgradeValue( hero.GetArmy(), Monster::OGRE ); return freeMonsterUpgradeModifier * ( upgradeDwarfValue + upgradeOrcValue + upgradeOgreValue ); } case MP2::OBJ_BARRIER: case MP2::OBJ_TRAVELLER_TENT: { // Most likely it'll lead to opening more land. return 1000; } case MP2::OBJ_OASIS: case MP2::OBJ_WATERING_HOLE: { const double movementBonus = GameStatic::getMovementPointBonus( objectType ) - 2.0 * distanceToObject; if ( movementBonus < 0 ) { // Don't waste movement to even visit this object. return -dangerousTaskPenalty; } return movementBonus; } case MP2::OBJ_JAIL: { // A free hero is always good and he could be very powerful. return 3000; } case MP2::OBJ_HUT_OF_MAGI: { const auto & eyeMagiIndexes = world.getAllEyeOfMagiPositions(); int fogCountToUncover = 0; const int heroColor = hero.GetColor(); const int eyeViewDistance = GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::MAGI_EYES ); for ( const int32_t eyeIndex : eyeMagiIndexes ) { fogCountToUncover += Maps::getFogTileCountToBeRevealed( eyeIndex, eyeViewDistance, heroColor ); } return fogCountToUncover; } case MP2::OBJ_GAZEBO: { // Free 1000 experience. We need to calculate value of this object based on hero's experience. The higher hero's level the less valuable this object is. const uint32_t heroExperience = hero.GetExperience(); const uint32_t nextLevelExperience = Heroes::GetExperienceFromLevel( Heroes::GetLevelFromExperience( heroExperience ) ); const uint32_t neededExperience = nextLevelExperience - heroExperience; if ( neededExperience < 1000 ) { // A new level. Have to visit. return 1000; } return 1000.0 * 1000.0 / neededExperience; } case MP2::OBJ_PYRAMID: { return 1500; } case MP2::OBJ_FAERIE_RING: case MP2::OBJ_FOUNTAIN: case MP2::OBJ_IDOL: case MP2::OBJ_MERMAID: { const int luck = hero.GetLuck(); if ( luck >= Luck::IRISH ) { return -dangerousTaskPenalty; // No reason to visit with maximum morale } if ( luck == Luck::GREAT ) { return -4000; // Morale is good enough to avoid visiting this object } if ( luck == Luck::GOOD ) { return -2000; // Is it worth visiting this facility with a morale slightly better than neutral? } if ( luck == Luck::NORMAL ) { return 50; } return 100; } case MP2::OBJ_ALCHEMIST_TOWER: { const BagArtifacts & bag = hero.GetBagArtifacts(); const uint32_t cursed = static_cast( std::count_if( bag.begin(), bag.end(), []( const Artifact & art ) { return art.containsCurses(); } ) ); if ( cursed == 0 ) { return -dangerousTaskPenalty; } // TODO: evaluate this object properly. return 0; } case MP2::OBJ_EYE_OF_MAGI: case MP2::OBJ_ORACLE: case MP2::OBJ_SIGN: { // These objects are useless for AI. return -dangerousTaskPenalty; } case MP2::OBJ_OBELISK: case MP2::OBJ_SIRENS: case MP2::OBJ_SPHINX: case MP2::OBJ_TRADING_POST: { // TODO: add logic to evaluate these objects. // As of now these objects should be avoided by AI as they are useless. return -dangerousTaskPenalty; } default: // Did you forget to add logic for an action object? assert( !MP2::isInGameActionObject( objectType ) ); break; } return 0; } double AI::Planner::getFighterObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const { // Fighters have higher priority for battles and smaller values for other objects. assert( hero.getAIRole() == Heroes::Role::FIGHTER || hero.getAIRole() == Heroes::Role::CHAMPION ); const Maps::Tile & tile = world.getTile( index ); const MP2::MapObjectType objectType = tile.getMainObjectType(); const std::function calculateCastleValue = [this, &hero, &calculateCastleValue]( const Castle * castle ) { assert( castle != nullptr ); double value = castle->getBuildingValue() * 500.0 + 15000; if ( hero.isLosingGame() ) { value += 15000; } if ( isCastleLossConditionForHuman( castle ) ) { value += 20000; } // This modifier shouldn't be too high to avoid players baiting AI in const double defenselessCastleModifier = 1.5; // This is our own castle in need of protection, evaluate it no worse than a similar defenseless enemy castle if ( hero.GetColor() == castle->GetColor() ) { value *= defenselessCastleModifier; } else { const int32_t castleIndex = castle->GetIndex(); // If this castle threatens our castles, then we should evaluate it no worse than the best of our castles that it threatens // (as if our best castle had to be taken back from the enemy). If a threatening castle can be attacked right now, it is // better to do it than wait until the hero hired in it captures one of our castles. if ( isCriticalTask( castleIndex ) ) { const auto iter = _priorityTargets.find( castleIndex ); assert( iter != _priorityTargets.end() ); const PriorityTask & attackTask = iter->second; assert( attackTask.type == PriorityTaskType::ATTACK ); for ( const int32_t secondaryTaskTileIdx : attackTask.secondaryTaskTileId ) { const Castle * castleUnderThreat = world.getCastleEntrance( Maps::GetPoint( secondaryTaskTileIdx ) ); if ( castleUnderThreat == nullptr ) { continue; } assert( hero.GetColor() == castleUnderThreat->GetColor() ); // Apply a bonus so that the AI prefers to eliminate the threat if possible instead of guarding its castle value = std::max( value, calculateCastleValue( castleUnderThreat ) * 2 ); } } // This castle is defenseless if ( !castle->GetActualArmy().isValid() ) { value *= defenselessCastleModifier; } } return value; }; switch ( objectType ) { case MP2::OBJ_CASTLE: { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( index ) ); if ( !castle ) { // How is it even possible? assert( 0 ); return valueToIgnore; } if ( hero.GetColor() == castle->GetColor() ) { // If our castle is in danger, then we should evaluate it not from the point of view of momentary benefits // for the hero (for example, the presence of reinforcements), but from the point of view of the castle, // which then will have to be taken back from the enemy, that is, according to approximately the same logic // as enemy castles if ( isCriticalTask( index ) ) { return calculateCastleValue( castle ); } double value = castle->getVisitValue( hero ); if ( !isPriorityTask( index ) && value < 500 ) { return valueToIgnore; } return value / 2; } // Hero should never visit castles belonging to friendly kingdoms if ( hero.isFriends( castle->GetColor() ) ) { assert( 0 ); return -dangerousTaskPenalty; } // WINS_HERO victory condition does not apply to AI-controlled players, we have to ignore the castle with this hero // to keep him alive for the human player if ( isHeroWhoseDefeatIsVictoryConditionForHumanInCastle( castle ) ) { assert( 0 ); return -dangerousTaskPenalty; } return calculateCastleValue( castle ); } case MP2::OBJ_HERO: { const Heroes * otherHero = tile.getHero(); if ( !otherHero ) { // How is it even possible? assert( 0 ); return valueToIgnore; } if ( hero.GetColor() == otherHero->GetColor() ) { if ( hero.getAIRole() > otherHero->getAIRole() ) { // The other hero has a lower role. Do not waste time for meeting. Let him to come. return valueToIgnore; } if ( hero.getAIRole() == otherHero->getAIRole() && hero.getStatsValue() + Difficulty::getMinStatDiffForAIHeroesMeeting( Game::getDifficulty() ) + 1 > otherHero->getStatsValue() ) { // Either this hero is superior or approximately equal to another hero in terms of stats. Do not waste time for meeting. Let him come instead. return valueToIgnore; } const double value = hero.getMeetingValue( *otherHero ); // limit the max value of friendly hero meeting to 30 tiles return ( value < 250 ) ? valueToIgnore : std::min( value, 5000.0 ); } // Hero should never meet heroes from friendly kingdoms if ( hero.isFriends( otherHero->GetColor() ) ) { assert( 0 ); return -dangerousTaskPenalty; } // WINS_HERO victory condition does not apply to AI-controlled players, we have to keep this hero alive for the human player if ( otherHero == world.GetHeroesCondWins() ) { assert( 0 ); return -dangerousTaskPenalty; } double value = 12000; // If this hero threatens our castles, then we should evaluate him no worse than the best of our castles that he threatens // (as if it had to be taken back from the enemy). If a threatening hero can be attacked in an open field, it is better to // do it now than to attack him later in our castle occupied by him. if ( isCriticalTask( index ) ) { const auto iter = _priorityTargets.find( index ); assert( iter != _priorityTargets.end() ); const PriorityTask & attackTask = iter->second; assert( attackTask.type == PriorityTaskType::ATTACK ); for ( const int32_t secondaryTaskTileIdx : attackTask.secondaryTaskTileId ) { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( secondaryTaskTileIdx ) ); if ( castle == nullptr ) { continue; } assert( hero.GetColor() == castle->GetColor() ); // Apply a bonus so that the AI prefers to eliminate the threat if possible instead of guarding its castle value = std::max( value, calculateCastleValue( castle ) * 2 ); } } else { const Castle * castle = otherHero->inCastle(); if ( castle != nullptr ) { // If the enemy hero is in the castle, then after defeating this hero, AI will automatically capture his // castle, so it's worth adding the value of the castle to the value of the enemy hero value += calculateCastleValue( castle ); } else if ( otherHero->GetControl() == CONTROL_AI ) { // AI heroes should not attack other AI heroes so aggressively as human heroes. // This is done to avoid situations when human players just wait when AI heroes kill each other. value *= 0.8; } } return value; } case MP2::OBJ_MONSTER: { const Army monsters( tile ); if ( !monsters.isValid() ) { // How is it even possible? assert( 0 ); return -dangerousTaskPenalty; } // TODO: we should add logic to compare monsters and hero army strengths. const bool anotherFriendlyHeroPresent = _regions[tile.GetRegion()].friendlyHeroes > 1; return ( anotherFriendlyHeroPresent ? 4000.0 : 1000.0 ) + monsters.getTotalHP() / 100.0; } case MP2::OBJ_ABANDONED_MINE: { return 5000.0; } case MP2::OBJ_ARTIFACT: { const Artifact art = getArtifactFromTile( tile ); assert( art.isValid() ); // WINS_ARTIFACT victory condition does not apply to AI-controlled players, we should leave this artifact untouched for the human player if ( isFindArtifactVictoryConditionForHuman( art ) ) { assert( 0 ); return -dangerousTaskPenalty; } return 1500.0 * art.getArtifactValue(); } case MP2::OBJ_CAMPFIRE: case MP2::OBJ_FLOTSAM: case MP2::OBJ_LEAN_TO: case MP2::OBJ_MAGIC_GARDEN: case MP2::OBJ_RESOURCE: case MP2::OBJ_WATER_WHEEL: case MP2::OBJ_WINDMILL: { const bool anotherFriendlyHeroPresent = _regions[tile.GetRegion()].friendlyHeroes > 1; if ( anotherFriendlyHeroPresent ) { return 100.0; } // fall through to the general value calculation break; } case MP2::OBJ_LIGHTHOUSE: { // TODO: add more complex logic for cases when AI has boats. if ( getColorFromTile( tile ) == hero.GetColor() ) { return -dangerousTaskPenalty; // don't even attempt to go here } return 250; } case MP2::OBJ_XANADU: { return 3500; } case MP2::OBJ_SHRINE_FIRST_CIRCLE: case MP2::OBJ_SHRINE_SECOND_CIRCLE: case MP2::OBJ_SHRINE_THIRD_CIRCLE: { const Spell & spell = getSpellFromTile( tile ); return spell.getStrategicValue( hero.GetArmy().GetStrength(), hero.GetMaxSpellPoints(), hero.GetPower() ) * 1.1; } case MP2::OBJ_ARENA: case MP2::OBJ_FORT: case MP2::OBJ_MERCENARY_CAMP: case MP2::OBJ_STANDING_STONES: case MP2::OBJ_TREE_OF_KNOWLEDGE: case MP2::OBJ_WITCH_DOCTORS_HUT: case MP2::OBJ_WITCHS_HUT: { return 1250.0; } case MP2::OBJ_OBSERVATION_TOWER: { return getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ) / 2; } case MP2::OBJ_ARTESIAN_SPRING: { if ( !hero.HaveSpellBook() || hero.GetSpellPoints() * 2 >= hero.GetMaxSpellPoints() ) { // No reason to visit Artesian Spring with no magic book or if no points will be gained. return -dangerousTaskPenalty; } return hero.isPotentSpellcaster() ? 2000 : 0; } case MP2::OBJ_MAGIC_WELL: { if ( !hero.HaveSpellBook() || hero.GetSpellPoints() >= hero.GetMaxSpellPoints() ) { // No reason to visit Magic Well with no magic book or if no points will be gained. return -dangerousTaskPenalty; } return hero.isPotentSpellcaster() ? 2000 : 0; } case MP2::OBJ_BUOY: case MP2::OBJ_TEMPLE: { if ( hero.GetArmy().AllTroopsAreUndead() ) { // All troops are undead, no use of Morale. return 0; } const int morale = hero.GetMorale(); if ( morale >= Morale::BLOOD ) { return -dangerousTaskPenalty; // No reason to visit with maximum morale } if ( morale == Morale::GREAT ) { return -4000; // Morale is good enough to avoid visiting this object } if ( morale == Morale::GOOD ) { return -2000; // Is it worth visiting this facility with a morale slightly better than neutral? } if ( morale == Morale::NORMAL ) { return 50; } return 200; } case MP2::OBJ_HUT_OF_MAGI: { return getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ) / 2; } case MP2::OBJ_PYRAMID: { return 10000; } default: break; } return getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ); } double AI::Planner::getCourierObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const { // Courier should focus on its main task and visit other objects only if it's close to the destination assert( hero.getAIRole() == Heroes::Role::COURIER ); // Values (n logn) for pre-defined distances where AI courier would consider taking a detour to visit those const double twoTiles = 500; const double fiveTiles = 1400; const double tenTiles = 3000; const Maps::Tile & tile = world.getTile( index ); const MP2::MapObjectType objectType = tile.getMainObjectType(); switch ( objectType ) { case MP2::OBJ_HERO: { const Heroes * otherHero = tile.getHero(); if ( !otherHero ) { // How is it even possible? assert( 0 ); return valueToIgnore; } if ( hero.GetColor() == otherHero->GetColor() ) { // Will be handled by the main task. return valueToIgnore; } // Hero should never meet heroes from friendly kingdoms if ( hero.isFriends( otherHero->GetColor() ) ) { assert( 0 ); return -dangerousTaskPenalty; } // WINS_HERO victory condition does not apply to AI-controlled players, we have to keep this hero alive for the human player if ( otherHero == world.GetHeroesCondWins() ) { assert( 0 ); return -dangerousTaskPenalty; } // This hero threatens our castles, use the general evaluation in this case if ( isCriticalTask( index ) ) { break; } return tenTiles; } case MP2::OBJ_MONSTER: { const Army monsters( tile ); if ( !monsters.isValid() ) { // How is it even possible? assert( 0 ); return -dangerousTaskPenalty; } // TODO: we should add logic to compare monsters and hero army strengths. return twoTiles + monsters.getTotalHP() / 100.0; } case MP2::OBJ_ALCHEMIST_LAB: case MP2::OBJ_MINE: case MP2::OBJ_SAWMILL: { if ( getColorFromTile( tile ) == hero.GetColor() ) { return -dangerousTaskPenalty; // don't even attempt to go here } return ( getDailyIncomeObjectResources( tile ).gold > 0 ) ? tenTiles : fiveTiles; } case MP2::OBJ_CAMPFIRE: case MP2::OBJ_FLOTSAM: case MP2::OBJ_GENIE_LAMP: case MP2::OBJ_RESOURCE: { return twoTiles; } case MP2::OBJ_SEA_CHEST: case MP2::OBJ_TREASURE_CHEST: { const Artifact art = getArtifactFromTile( tile ); if ( art.isValid() && isFindArtifactVictoryConditionForHuman( art ) ) { // WINS_ARTIFACT victory condition does not apply to AI-controlled players, we should leave this object untouched for the human player. assert( 0 ); return -dangerousTaskPenalty; } return twoTiles; } case MP2::OBJ_ARENA: case MP2::OBJ_FORT: case MP2::OBJ_MERCENARY_CAMP: case MP2::OBJ_STANDING_STONES: case MP2::OBJ_TREE_OF_KNOWLEDGE: case MP2::OBJ_WITCH_DOCTORS_HUT: case MP2::OBJ_WITCHS_HUT: case MP2::OBJ_XANADU: { return fiveTiles; } case MP2::OBJ_ARTESIAN_SPRING: { if ( !hero.HaveSpellBook() || hero.GetSpellPoints() * 2 >= hero.GetMaxSpellPoints() ) { // No reason to visit Artesian Spring with no magic book or if no points will be gained. return -dangerousTaskPenalty; } return hero.isPotentSpellcaster() ? fiveTiles : 0; } case MP2::OBJ_MAGIC_WELL: { if ( !hero.HaveSpellBook() || hero.GetSpellPoints() >= hero.GetMaxSpellPoints() ) { // No reason to visit Magic Well with no magic book or if no points will be gained. return -dangerousTaskPenalty; } return hero.isPotentSpellcaster() ? fiveTiles : 0; } default: break; } return getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ); } double AI::Planner::getScoutObjectValue( const Heroes & hero, const int32_t index, const double valueToIgnore, const uint32_t distanceToObject ) const { // Courier should focus on its main task and visit other objects only if it's close to the destination assert( hero.getAIRole() == Heroes::Role::SCOUT ); const Maps::Tile & tile = world.getTile( index ); const MP2::MapObjectType objectType = tile.getMainObjectType(); switch ( objectType ) { case MP2::OBJ_WITCHS_HUT: { if ( !hero.isVisited( tile, Visit::GLOBAL ) ) { // Since this object has not been visited use general value estimation. return getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ); } const Skill::Secondary & skill = getSecondarySkillFromWitchsHut( tile ); if ( !skill.isValid() || hero.HasMaxSecondarySkill() ) { // This mustn't happen as these checks are done prior this code. assert( 0 ); return -dangerousTaskPenalty; } const int skillType = skill.Skill(); if ( hero.HasSecondarySkill( skillType ) ) { // This mustn't happen as these checks are done prior this code. assert( 0 ); return -dangerousTaskPenalty; } double value = getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ); if ( skillType == Skill::Secondary::SCOUTING || skillType == Skill::Secondary::LOGISTICS ) { // Scouts should focus on scouting so these skills must have much higher priority. value = value * 3; } else if ( skillType == Skill::Secondary::PATHFINDING ) { value = value * 2; } return value; } default: break; } return getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ); } double AI::Planner::getObjectValue( const Heroes & hero, const int32_t index, const MP2::MapObjectType objectType, const double valueToIgnore, const uint32_t distanceToObject ) const { assert( objectType == world.getTile( index ).getMainObjectType() ); #ifdef NDEBUG (void)objectType; #endif switch ( hero.getAIRole() ) { case Heroes::Role::HUNTER: return getGeneralObjectValue( hero, index, valueToIgnore, distanceToObject ); case Heroes::Role::SCOUT: return getScoutObjectValue( hero, index, valueToIgnore, distanceToObject ); case Heroes::Role::CHAMPION: case Heroes::Role::FIGHTER: return getFighterObjectValue( hero, index, valueToIgnore, distanceToObject ); case Heroes::Role::COURIER: return getCourierObjectValue( hero, index, valueToIgnore, distanceToObject ); default: // If you set a new type of a hero you must add the logic here. assert( 0 ); break; } return 0; } int AI::Planner::getCourierMainTarget( const Heroes & hero, const double lowestPossibleValue ) { assert( hero.getAIRole() == Heroes::Role::COURIER ); int targetIndex = -1; const Kingdom & kingdom = hero.GetKingdom(); const VecHeroes & allHeroes = kingdom.GetHeroes(); // Check if we have army and should bring it to friendly hero first double bestTargetValue = lowestPossibleValue; for ( const Heroes * otherHero : allHeroes ) { if ( !otherHero || hero.GetID() == otherHero->GetID() ) { continue; } const Heroes::Role role = otherHero->getAIRole(); if ( role == Heroes::Role::COURIER || role == Heroes::Role::SCOUT ) { continue; } const int currentHeroIndex = otherHero->GetIndex(); const auto [dist, dummy] = getDistanceToTile( _pathfinder, currentHeroIndex ); if ( dist == 0 || hero.hasMetWithHero( otherHero->GetID() ) ) { continue; } double value = hero.getMeetingValue( *otherHero ); if ( value < 500 ) { continue; } if ( role == Heroes::Role::CHAMPION ) { value *= 2.5; } value -= dist; if ( value > bestTargetValue ) { bestTargetValue = value; targetIndex = currentHeroIndex; } } if ( targetIndex != -1 ) { return targetIndex; } // Reset the max value bestTargetValue = lowestPossibleValue; for ( const Castle * castle : kingdom.GetCastles() ) { if ( castle == nullptr || castle->GetHero() != nullptr ) { continue; } const int currentCastleIndex = castle->GetIndex(); const auto [dist, dummy] = getDistanceToTile( _pathfinder, currentCastleIndex ); if ( dist == 0 ) { continue; } double value = castle->getVisitValue( hero ); if ( value < 250 ) { continue; } const int safetyFactor = _regions[world.getTile( currentCastleIndex ).GetRegion()].safetyFactor; if ( safetyFactor > 100 ) { value *= 2; } else if ( safetyFactor < 0 ) { value /= 2; } // additional distance scaling is not required since Couriers are meant to travel far value -= dist; if ( value > bestTargetValue ) { bestTargetValue = value; targetIndex = currentCastleIndex; } } return targetIndex; } int AI::Planner::getPriorityTarget( Heroes & hero, double & maxPriority ) { DEBUG_LOG( DBG_AI, DBG_INFO, "Find Adventure Map target for hero " << hero.GetName() << " at current position " << hero.GetIndex() ) const double lowestPossibleValue = -1.0 * Maps::Ground::slowestMovePenalty * world.getSize(); int priorityTarget = -1; maxPriority = lowestPossibleValue; #ifdef WITH_DEBUG { std::set objectIndexes; for ( const auto & [idx, objType] : _mapActionObjects ) { if ( objType == MP2::OBJ_HERO ) { assert( world.getTile( idx ).getHero() != nullptr ); } if ( const auto [dummy, inserted] = objectIndexes.emplace( idx ); !inserted ) { assert( 0 ); } } } MP2::MapObjectType objectType = MP2::OBJ_NONE; #endif // Pre-calculate penalties for tiles where there is a threat of enemy attack const std::vector enemyThreatPenalties = [this, &hero = std::as_const( hero )]() { std::vector result( world.getSize(), 0.0 ); const AIWorldPathfinderStateRestorer pathfinderStateRestorer( _pathfinder ); // Use the "optimistic" pathfinder settings for enemy heroes - minimal army advantage, minimal reserve of spell points _pathfinder.setMinimalArmyStrengthAdvantage( ARMY_ADVANTAGE_DESPERATE ); _pathfinder.setSpellPointsReserveRatio( 0.0 ); const double heroStrength = hero.GetArmy().GetStrength(); for ( const auto & [dummy, enemyArmy] : _enemyArmies ) { // Only enemy heroes are taken into account if ( enemyArmy.hero == nullptr ) { continue; } // An enemy hero does not pose a threat if he is approximately equal in strength or weaker than our hero if ( heroStrength * ARMY_ADVANTAGE_SMALL >= enemyArmy.strength ) { continue; } // In theory, this should never be the case if ( enemyArmy.movePoints == 0 ) { assert( 0 ); continue; } // Safe tiles should not be located close to a tile accessible to an enemy hero, some margin is needed const uint32_t enemyArmyMovePointsThreshold = enemyArmy.movePoints + Maps::Ground::slowestMovePenalty * 2; // If the enemy hero can't cross paths with our hero anywhere, then it makes sense to use a rough but quick estimate. Otherwise, an accurate but // relatively slow estimate will be used. const bool useRoughEstimate = ( Maps::GetApproximateDistance( hero.GetIndex(), enemyArmy.index ) * Maps::Ground::fastestMovePenalty > hero.GetMovePoints() + enemyArmyMovePointsThreshold ); if ( !useRoughEstimate ) { // Pre-cache the pathfinder database for the enemy hero _pathfinder.reEvaluateIfNeeded( *enemyArmy.hero ); } for ( size_t i = 0; i < result.size(); ++i ) { const int32_t tileIdx = static_cast( i ); assert( Maps::isValidAbsIndex( tileIdx ) ); const auto [distToTile, isTileConsideredSafe] = [this, enemyArmyIdx = enemyArmy.index, enemyArmyMovePointsThreshold, useRoughEstimate, tileIdx]() { // The tile on which the enemy hero is located is always considered unsafe if ( tileIdx == enemyArmyIdx ) { return std::make_pair( static_cast( 0 ), false ); } if ( useRoughEstimate ) { const uint32_t dist = Maps::GetApproximateDistance( tileIdx, enemyArmyIdx ) * Maps::Ground::fastestMovePenalty; // When using a rough estimate, a tile is considered safe if the enemy hero cannot reach it within one turn, even if the path from the enemy // hero to this tile is straight and with a minimum movement penalty. The potential ability of the enemy hero to use spells to move to this // tile (for example, the Dimension Door or Town Portal) is not considered in this assessment. return std::make_pair( dist, dist > enemyArmyMovePointsThreshold ); } const uint32_t dist = _pathfinder.getDistance( tileIdx ); // When using an accurate estimate, a tile is considered safe if the enemy hero does not have access to it (in particular, if it is hidden from // him in the fog) or he cannot reach it within one turn. The potential ability of the enemy hero to use spells to move to this tile (for example, // the Dimension Door or Town Portal) is not considered in this assessment. return std::make_pair( dist, dist == 0 || dist > enemyArmyMovePointsThreshold ); }(); if ( isTileConsideredSafe ) { continue; } // The penalty is cumulative (i.e. this is the sum of the penalties from all threatening heroes), the penalty from each threatening hero increases // linearly as the distance to that hero decreases result[i] += dangerousTaskPenalty * ( 2.0 - static_cast( distToTile ) / static_cast( enemyArmyMovePointsThreshold ) ); } } return result; }(); // Pre-cache the pathfinder database for our hero _pathfinder.reEvaluateIfNeeded( hero ); ObjectValidator objectValidator( hero, _pathfinder, *this ); ObjectValueStorage valueStorage( hero, *this, lowestPossibleValue ); const auto getObjectValue = [this, &hero = std::as_const( hero ), &enemyThreatPenalties, &objectValidator, &valueStorage]( const int destination, uint32_t & distance, double & value, const MP2::MapObjectType type, const bool isDimensionDoor ) { // Dimension door path does not include any objects on the way. if ( !isDimensionDoor ) { for ( const IndexObject & pair : _pathfinder.getObjectsOnTheWay( destination ) ) { if ( !objectValidator.isValid( pair.first ) ) { continue; } if ( const auto iter = _mapActionObjects.find( pair.first ); iter == _mapActionObjects.end() || iter->second != pair.second ) { continue; } const double extraValue = valueStorage.value( pair, 0 ); if ( extraValue > 0 ) { // There is no need to reduce the quality of the object even if the path has others. value += extraValue; } } } const uint32_t heroMovePoints = hero.GetMovePoints(); const double enemyThreatPenalty = [&hero, &enemyThreatPenalties, destination, distance, type, heroMovePoints]() { if ( type == MP2::OBJ_CASTLE ) { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( destination ) ); assert( castle != nullptr ); // We should strive to defend our castles even if our hero is relatively weak (he can get reinforcements in the castle), so enemy threat // penalties should not apply if our hero is able to reach the castle within one turn. if ( castle->GetColor() == hero.GetColor() && distance <= heroMovePoints ) { return 0.0; } } assert( destination >= 0 && static_cast( destination ) < enemyThreatPenalties.size() ); return enemyThreatPenalties[destination]; }(); value -= enemyThreatPenalty; // Distant object which is out of reach for the current turn must have lower priority. if ( distance > heroMovePoints ) { distance = heroMovePoints + ( distance - heroMovePoints ) * 2; } value = scaleWithDistanceAndTime( value, distance, type ); }; // Set baseline target if it's a special role if ( hero.getAIRole() == Heroes::Role::COURIER ) { const int courierTarget = getCourierMainTarget( hero, lowestPossibleValue ); if ( courierTarget != -1 ) { // Anything with positive value can override the courier's main task (i.e. castle or mine capture on the way) maxPriority = 0; priorityTarget = courierTarget; #ifdef WITH_DEBUG objectType = world.getTile( courierTarget ).getMainObjectType(); #endif DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " is a courier with a main target tile at " << courierTarget ) } else { // If there's nothing to do as a Courier reset the role hero.setAIRole( Heroes::Role::HUNTER ); } } for ( const auto & [idx, objType] : _mapActionObjects ) { if ( !objectValidator.isValid( idx ) ) { continue; } auto [dist, useDimensionDoor] = getDistanceToTile( _pathfinder, idx ); if ( dist == 0 ) { continue; } double value = valueStorage.value( { idx, objType }, dist ); getObjectValue( idx, dist, value, objType, useDimensionDoor ); if ( dist > 0 && value > maxPriority ) { maxPriority = value; priorityTarget = idx; #ifdef WITH_DEBUG objectType = objType; #endif DEBUG_LOG( DBG_AI, DBG_TRACE, hero.GetName() << ": valid object at " << idx << " value is " << value << " (" << MP2::StringObject( objType ) << ")" ) } } double fogDiscoveryValue = getFogDiscoveryValue( hero ); // TODO: add logic to check fog discovery based on Dimension Door distance, not the nearest tile. const auto [fogDiscoveryTarget, isTerritoryExpansion] = _pathfinder.getFogDiscoveryTile( hero ); if ( fogDiscoveryTarget >= 0 ) { auto [distanceToFogDiscovery, useDimensionDoor] = getDistanceToTile( _pathfinder, fogDiscoveryTarget ); if ( isTerritoryExpansion ) { // Over time the AI should focus more on territory expansion. const uint32_t period = getTimeoutBeforeFogDiscoveryIntensification( hero ); assert( period > 0 ); if ( fogDiscoveryValue < 0 ) { // This is actually a very useful fog discovery action which might lead to finding of new objects. // Increase the value of this action. if ( world.CountDay() > period ) { fogDiscoveryValue = 0; } else { fogDiscoveryValue = fogDiscoveryValue / 2 * ( period - world.CountDay() ) / period; } } else { // Over time the AI should focus more on territory expansion. // Scouts must focus on expansion so they should reach maximum "attention" in a month. fogDiscoveryValue += std::min( 1000.0 * world.CountDay() / period, 1000.0 ); } } getObjectValue( fogDiscoveryTarget, distanceToFogDiscovery, fogDiscoveryValue, MP2::OBJ_NONE, useDimensionDoor ); } if ( priorityTarget != -1 ) { if ( fogDiscoveryTarget >= 0 && fogDiscoveryValue > maxPriority ) { priorityTarget = fogDiscoveryTarget; maxPriority = fogDiscoveryValue; DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ": selected target: " << priorityTarget << " value is " << maxPriority << " (fog discovery)" ) } else { DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << ": selected target: " << priorityTarget << " value is " << maxPriority << " (" << MP2::StringObject( objectType ) << ")" ) } } else { priorityTarget = fogDiscoveryTarget; DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " can't find an object. Scouting the fog of war at " << priorityTarget ) } return priorityTarget; } void AI::Planner::updatePriorityTargets( Heroes & hero, int32_t tileIndex, const MP2::MapObjectType objectType ) { if ( objectType != MP2::OBJ_CASTLE && objectType != MP2::OBJ_HERO ) { // Priorities are only for castles and heroes at the moment. return; } const auto updateTile = [this, &hero, tileIndex, objectType]() { const auto updateCastle = [this, &hero, tileIndex]() { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( tileIndex ) ); if ( castle == nullptr ) { // How is it possible? assert( 0 ); _enemyArmies.erase( tileIndex ); return; } if ( hero.isFriends( castle->GetColor() ) ) { _enemyArmies.erase( tileIndex ); updatePriorityForCastle( *castle ); } else { updatePriorityAttackTarget( hero.GetKingdom(), world.getTile( tileIndex ) ); } }; if ( objectType == MP2::OBJ_CASTLE ) { updateCastle(); } else if ( objectType == MP2::OBJ_HERO ) { const Maps::Tile & tile = world.getTile( tileIndex ); const Heroes * anotherHero = tile.getHero(); if ( anotherHero == nullptr ) { // Another hero lost the battle, but he could defend a castle if ( tile.getMainObjectType() == MP2::OBJ_CASTLE ) { updateCastle(); } else { _enemyArmies.erase( tileIndex ); } return; } if ( !hero.isFriends( anotherHero->GetColor() ) ) { updatePriorityAttackTarget( hero.GetKingdom(), tile ); } } else { // Unsupported object type! assert( 0 ); } }; auto iter = _priorityTargets.find( tileIndex ); if ( iter == _priorityTargets.end() ) { // If the object is not a priority we have to update it after the battle as it can become the one. // Especially, when the opposite army has grown Skeletons or Ghosts. updateTile(); // If the update did not add any priorities then nothing more to do. iter = _priorityTargets.find( tileIndex ); if ( iter == _priorityTargets.end() ) { return; } } const PriorityTaskType taskType = iter->second.type; switch ( taskType ) { case PriorityTaskType::DEFEND: case PriorityTaskType::REINFORCE: if ( hero.GetIndex() != tileIndex ) { // Either the castle has just been captured, or the hero meets the guest hero of a friendly castle. If any of these assertions blow up, then this is not // one of these cases. #ifndef NDEBUG const Maps::Tile & tile = world.getTile( tileIndex ); #endif assert( tile.getMainObjectType( false ) == MP2::OBJ_CASTLE && hero.GetColor() == Maps::getColorFromTile( tile ) ); assert( Maps::isValidDirection( tileIndex, Direction::BOTTOM ) && hero.GetIndex() == Maps::GetDirectionIndex( tileIndex, Direction::BOTTOM ) ); // In case the castle has just been captured, we need to update the information related to the object on the corresponding tile. updateTile(); // Since the hero has not yet reached the tile associated with the corresponding task, this task is not considered completed and should not be removed // yet. return; } // These tasks are only for castles at the moment! assert( objectType == MP2::OBJ_CASTLE ); // How is it even possible that a hero died while simply moving into a castle? assert( hero.isActive() ); hero.SetModes( Heroes::SLEEPER ); #ifdef WITH_DEBUG { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( tileIndex ) ); assert( castle != nullptr ); DEBUG_LOG( DBG_AI, DBG_INFO, hero.GetName() << " stays in " << castle->GetName() << " to " << ( taskType == PriorityTaskType::DEFEND ? "defend the castle" : "reinforce" ) ) } #endif _priorityTargets.erase( tileIndex ); break; case PriorityTaskType::ATTACK: removePriorityAttackTarget( tileIndex ); updateTile(); break; default: // Did you add a new type of priority task? Add the logic above! assert( 0 ); break; } } Skill::Secondary AI::Planner::pickSecondarySkill( const Heroes & hero, const Skill::Secondary & left, const Skill::Secondary & right ) { // heroes can get 1 or 0 skill choices depending on a level if ( !right.isValid() ) { // if both left and right are invalid returning either is fine return left; } const double leftValue = getSecondarySkillValue( hero, left ); const double rightValue = getSecondarySkillValue( hero, right ); DEBUG_LOG( DBG_AI, DBG_TRACE, hero.GetName() << " picking a skill: " << leftValue << " for " << left.String( left.first ) << " and " << rightValue << " for " << right.String( right.first ) ) if ( std::fabs( leftValue - rightValue ) < 0.001 ) { // If skill value is lower than the threshold then it's undesireable. Avoid learning it. if ( leftValue < 300.0 ) { return left.Level() == Skill::Level::BASIC ? right : left; } return left.Level() == Skill::Level::BASIC ? left : right; } return leftValue > rightValue ? left : right; } void AI::Planner::HeroesBeginMovement( Heroes & hero ) { assert( hero.isActive() ); const Route::Path & path = hero.GetPath(); if ( !path.isValidForMovement() ) { return; } const int32_t heroIdx = hero.GetIndex(); const int frontDirection = path.GetFrontDirection(); assert( Maps::isValidDirection( heroIdx, frontDirection ) ); const int32_t nextTileIdx = Maps::GetDirectionIndex( heroIdx, frontDirection ); const Maps::Tile & currTile = world.getTile( heroIdx ); const Maps::Tile & nextTile = world.getTile( nextTileIdx ); if ( currTile.isWater() || !nextTile.isWater() || nextTile.getMainObjectType() != MP2::OBJ_NONE ) { return; } // If the hero goes to the water tile, then this should be his last movement assert( path.size() == 1 ); const int32_t formerBoatIdx = HeroesCastSummonBoat( hero, nextTileIdx ); updateMapActionObjectCache( formerBoatIdx ); updateMapActionObjectCache( nextTileIdx ); } void AI::Planner::HeroesActionComplete( Heroes & hero, const int32_t tileIndex, const MP2::MapObjectType objectType ) { // This method is called upon action completion and the hero could no longer be available. // So it is to check if the hero is still present. if ( hero.isActive() ) { if ( Castle * castle = hero.inCastleMutable(); castle ) { reinforceCastle( *castle ); } else { OptimizeTroopsOrder( hero.GetArmy() ); } } _tileArmyStrengthValues.erase( tileIndex ); updatePriorityTargets( hero, tileIndex, objectType ); updateMapActionObjectCache( tileIndex ); } void AI::Planner::HeroesActionNewPosition( Heroes & hero ) { if ( !hero.isActive() ) { return; } Route::Path & path = hero.GetPath(); if ( !path.isValidForMovement() ) { return; } const int32_t heroIdx = hero.GetIndex(); assert( heroIdx == path.GetFrontIndex() ); const int nextStepDirection = path.GetNextStepDirection(); if ( !Maps::isValidDirection( heroIdx, nextStepDirection ) ) { return; } const int32_t nextTileIdx = Maps::GetDirectionIndex( heroIdx, nextStepDirection ); const Maps::Tile & currTile = world.getTile( heroIdx ); const Maps::Tile & nextTile = world.getTile( nextTileIdx ); if ( currTile.isWater() || !nextTile.isWater() || nextTile.getMainObjectType() != MP2::OBJ_NONE ) { return; } // If the hero goes to the water tile, then this should be his last movement // (not counting the current step, which is not yet completed at the moment) assert( path.size() == 2 ); // It may happen that although the hero at the beginning of his path had enough spell points to // summon a boat, but while moving through the guarded tiles, these spell points were spent. In // this case, just stop. if ( !hero.CanCastSpell( Spell::SUMMONBOAT ) ) { path.Reset(); hero.SetMove( false ); return; } const int32_t formerBoatIdx = HeroesCastSummonBoat( hero, nextTileIdx ); updateMapActionObjectCache( formerBoatIdx ); updateMapActionObjectCache( nextTileIdx ); } bool AI::Planner::isValidHeroObject( const Heroes & hero, const int32_t index, const bool underHero ) { return HeroesValidObject( hero, hero.GetArmy().GetStrength(), index, _pathfinder, *this, hero.getAIMinimumJoiningArmyStrength(), underHero ); } void AI::Planner::HeroesPreBattle( HeroBase & hero, bool isAttacking ) { if ( isAttacking ) { OptimizeTroopsOrder( hero.GetArmy() ); } } bool AI::Planner::HeroesTurn( VecHeroes & heroes, uint32_t & currentProgressValue, uint32_t endProgressValue ) { if ( heroes.empty() ) { // No heroes so we indicate that all heroes moved. return true; } std::vector availableHeroes; availableHeroes.reserve( heroes.size() ); for ( Heroes * hero : heroes ) { assert( hero != nullptr ); addHeroToMove( hero, availableHeroes ); } Interface::StatusPanel & status = Interface::AdventureMap::Get().getStatusPanel(); uint32_t heroesToMoveTotalCount = static_cast( availableHeroes.size() ); uint32_t startProgressValue = currentProgressValue; if ( endProgressValue - currentProgressValue >= heroesToMoveTotalCount * 2 ) { // An extra case when there is only one hero and we have more than 2 points to display the turn progress. // We increase the start value to display this progress after the pathfinder ends his work // and the next progress increase will be aster the hero makes his move. ++startProgressValue; } uint32_t turnProgressScale = 4 * ( endProgressValue - startProgressValue ); while ( !availableHeroes.empty() ) { const AIWorldPathfinderStateRestorer pathfinderStateRestorer( _pathfinder ); Heroes * bestHero = availableHeroes.front(); int bestTargetIndex = -1; { const bool isLosingGame = bestHero->isLosingGame(); static const std::vector> commonPathfinderConfigurations{ { ARMY_ADVANTAGE_LARGE, 0.5 }, { ARMY_ADVANTAGE_MEDIUM, 0.25 }, { ARMY_ADVANTAGE_SMALL, 0.0 } }; static const std::vector> emergencyPathfinderConfigurations{ { ARMY_ADVANTAGE_DESPERATE, 0.0 } }; for ( const auto & [minStrengthAdvantage, spReserveRatio] : isLosingGame ? emergencyPathfinderConfigurations : commonPathfinderConfigurations ) { _pathfinder.setMinimalArmyStrengthAdvantage( minStrengthAdvantage ); _pathfinder.setSpellPointsReserveRatio( spReserveRatio ); double maxPriority = 0; for ( Heroes * hero : availableHeroes ) { double priority = -1; const int targetIndex = getPriorityTarget( *hero, priority ); if ( targetIndex != -1 && ( priority > maxPriority || bestTargetIndex == -1 ) ) { maxPriority = priority; bestTargetIndex = targetIndex; bestHero = hero; } // This loop may take many time for computations, so pump the event queue and update the animation of the hourglass grains. status.drawAITurnProgress( currentProgressValue ); } if ( bestTargetIndex != -1 ) { break; } } } // Calculate turn progress taking into account that the current 'bestHero' most likely will end his turn // and will be removed from 'availableHeroes' vector: we add 3/4 (not 1/2) to help rounding the result. currentProgressValue = std::max( currentProgressValue, ( turnProgressScale * ( heroesToMoveTotalCount - static_cast( availableHeroes.size() ) ) + 3 * heroesToMoveTotalCount ) / ( 4 * heroesToMoveTotalCount ) + startProgressValue ); status.drawAITurnProgress( currentProgressValue ); if ( bestTargetIndex == -1 ) { // Possibly heroes have nothing to do because one of them is blocking the way. Move a random hero randomly and see what happens. Rand::Shuffle( availableHeroes ); for ( Heroes * hero : availableHeroes ) { // Skip heroes located in castles. if ( hero->inCastle() != nullptr ) { continue; } if ( !AIWorldPathfinder::isHeroPossiblyBlockingWay( *hero ) ) { continue; } const int targetIndex = _pathfinder.getNearestTileToMove( *hero ); if ( targetIndex != -1 ) { bestTargetIndex = targetIndex; bestHero = hero; DEBUG_LOG( DBG_AI, DBG_INFO, bestHero->GetName() << " may be blocking the way. Moving to " << bestTargetIndex ) break; } } } if ( bestTargetIndex == -1 ) { // Nothing to do. Stop everything. break; } const size_t heroesBefore = heroes.size(); _pathfinder.reEvaluateIfNeeded( *bestHero ); int prevHeroPosition = bestHero->GetIndex(); { std::list dimensionDoorPath = _pathfinder.buildDimensionDoorPath( bestTargetIndex ); uint32_t regularMovementDist = _pathfinder.getDistance( bestTargetIndex ); uint32_t dimensionDoorDist = Route::calculatePathPenalty( dimensionDoorPath ); if ( shouldUseDimensionDoor( regularMovementDist, dimensionDoorDist ) ) { while ( shouldUseDimensionDoor( regularMovementDist, dimensionDoorDist ) ) { assert( !dimensionDoorPath.empty() && bestHero->MayStillMove( false, false ) ); HeroesCastDimensionDoor( *bestHero, dimensionDoorPath.front().GetIndex() ); dimensionDoorDist -= dimensionDoorPath.front().GetPenalty(); _pathfinder.reEvaluateIfNeeded( *bestHero ); regularMovementDist = _pathfinder.getDistance( bestTargetIndex ); dimensionDoorPath.pop_front(); // Hero can jump straight into the fog using the Dimension Door spell, which triggers the mechanics of fog revealing for his new tile // and this results in inserting a new hero position into the action object cache. Perform the necessary updates. assert( bestHero->isActive() && bestHero->GetIndex() != prevHeroPosition ); updateMapActionObjectCache( prevHeroPosition ); updateMapActionObjectCache( bestHero->GetIndex() ); prevHeroPosition = bestHero->GetIndex(); } if ( dimensionDoorDist > 0 ) { // The rest of the path the hero should do by foot. bestHero->GetPath().setPath( _pathfinder.buildPath( bestTargetIndex ) ); HeroesMove( *bestHero ); } } else { bestHero->GetPath().setPath( _pathfinder.buildPath( bestTargetIndex ) ); HeroesMove( *bestHero ); } } if ( !bestHero->isActive() || bestHero->GetIndex() != prevHeroPosition ) { // The hero died or moved to another position. We have to update the action object cache. updateMapActionObjectCache( prevHeroPosition ); if ( bestHero->isActive() ) { // Hero moved to another position and is still alive. updateMapActionObjectCache( bestHero->GetIndex() ); } } // The size of heroes can be increased if a new hero is released from Jail. if ( heroes.size() > heroesBefore ) { const size_t availableHeroesBefore = availableHeroes.size(); addHeroToMove( heroes.back(), availableHeroes ); if ( availableHeroesBefore < availableHeroes.size() ) { ++heroesToMoveTotalCount; if ( endProgressValue < 8 ) { ++endProgressValue; turnProgressScale += 4; } } } availableHeroes.erase( std::remove_if( availableHeroes.begin(), availableHeroes.end(), []( const Heroes * hero ) { return !hero->MayStillMove( false, false ); } ), availableHeroes.end() ); currentProgressValue = std::max( currentProgressValue, ( turnProgressScale * ( heroesToMoveTotalCount - static_cast( availableHeroes.size() ) ) + heroesToMoveTotalCount ) / ( 4 * heroesToMoveTotalCount ) + startProgressValue ); status.drawAITurnProgress( currentProgressValue ); } status.drawAITurnProgress( endProgressValue ); return availableHeroes.empty(); } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_planner_internals.h000066400000000000000000000052411476115357100234240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include "world_pathfinding.h" namespace AI { const double ARMY_ADVANTAGE_DESPERATE = 0.8; const double ARMY_ADVANTAGE_SMALL = 1.3; const double ARMY_ADVANTAGE_MEDIUM = 1.5; const double ARMY_ADVANTAGE_LARGE = 1.8; class AIWorldPathfinderStateRestorer { public: explicit AIWorldPathfinderStateRestorer( AIWorldPathfinder & pathfinder ) : _pathfinder( pathfinder ) , _originalMinimalArmyStrengthAdvantage( _pathfinder.getMinimalArmyStrengthAdvantage() ) , _originalSpellPointsReserveRatio( _pathfinder.getSpellPointsReserveRatio() ) {} AIWorldPathfinderStateRestorer( const AIWorldPathfinderStateRestorer & ) = delete; ~AIWorldPathfinderStateRestorer() { _pathfinder.setMinimalArmyStrengthAdvantage( _originalMinimalArmyStrengthAdvantage ); _pathfinder.setSpellPointsReserveRatio( _originalSpellPointsReserveRatio ); } AIWorldPathfinderStateRestorer & operator=( const AIWorldPathfinderStateRestorer & ) = delete; private: AIWorldPathfinder & _pathfinder; const double _originalMinimalArmyStrengthAdvantage; const double _originalSpellPointsReserveRatio; }; } fheroes2-1.1.6+dfsg/src/fheroes2/ai/ai_planner_kingdom.cpp000066400000000000000000001036751476115357100234220ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "ai_common.h" #include "ai_hero_action.h" #include "ai_planner.h" // IWYU pragma: associated #include "ai_planner_internals.h" #include "army.h" #include "audio.h" #include "audio_manager.h" #include "castle.h" #include "color.h" #include "difficulty.h" #include "game.h" #include "game_interface.h" #include "ground.h" #include "heroes.h" #include "heroes_recruits.h" #include "interface_status.h" #include "kingdom.h" #include "logging.h" #include "maps.h" #include "maps_tiles.h" #include "mp2.h" #include "mus.h" #include "players.h" #include "resource.h" #include "skill.h" #include "spell.h" #include "world.h" #include "world_pathfinding.h" #include "world_regions.h" namespace { struct HeroValue { Heroes * hero = nullptr; double strength = 0.0; int stats = 0; HeroValue( Heroes * inHero, double inStrength, int inStats ) : hero( inHero ) , strength( inStrength ) , stats( inStats ) { // Do nothing. } }; class TemporaryHeroEraser { public: TemporaryHeroEraser() = delete; TemporaryHeroEraser( const TemporaryHeroEraser & ) = delete; TemporaryHeroEraser( TemporaryHeroEraser && ) = delete; explicit TemporaryHeroEraser( const std::vector & heroes ) { for ( Heroes * hero : heroes ) { assert( hero != nullptr && hero->isActive() ); Maps::Tile & tile = world.getTile( hero->GetIndex() ); if ( tile.getHero() == nullptr ) { // This could happen when a hero is moving. continue; } assert( tile.getHero() == hero ); _heroes.emplace_back( hero ); tile.setHero( nullptr ); } } ~TemporaryHeroEraser() { for ( Heroes * hero : _heroes ) { Maps::Tile & tile = world.getTile( hero->GetIndex() ); assert( tile.getHero() == nullptr ); tile.setHero( hero ); } } TemporaryHeroEraser & operator=( const TemporaryHeroEraser & ) = delete; TemporaryHeroEraser & operator=( TemporaryHeroEraser && ) = delete; private: std::vector _heroes; }; void setHeroRoles( VecHeroes & heroes, const int difficulty ) { if ( heroes.empty() ) { // No heroes exist. return; } if ( !Difficulty::areAIHeroRolesAllowed( difficulty ) ) { // All heroes are equal. for ( Heroes * hero : heroes ) { hero->setAIRole( Heroes::Role::HUNTER ); } return; } const Heroes * valuableHero = world.GetHeroesCondWins(); if ( heroes.size() == 1 ) { if ( valuableHero != nullptr && valuableHero == heroes[0] ) { heroes[0]->setAIRole( Heroes::Role::CHAMPION ); } else { // A single hero has no roles. heroes[0]->setAIRole( Heroes::Role::HUNTER ); } return; } // Set hero's roles. First calculate each hero strength and sort it in descending order. std::vector heroList; for ( Heroes * hero : heroes ) { // AI heroes set on patrol mode can only be fighters; ignore them otherwise if ( hero->Modes( Heroes::PATROL ) ) { hero->setAIRole( Heroes::Role::FIGHTER ); } else { heroList.emplace_back( hero, hero->GetArmy().GetStrength(), hero->getStatsValue() ); } } if ( heroList.empty() ) { // No more heroes. return; } // If there's plenty of heroes we can assign special roles if ( heroList.size() > 3 ) { std::sort( heroList.begin(), heroList.end(), []( const HeroValue & first, const HeroValue & second ) { return first.stats > second.stats; } ); if ( valuableHero == nullptr ) { heroList.front().hero->setAIRole( Heroes::Role::CHAMPION ); heroList.erase( heroList.begin() ); } // Assign the courier role and remove them so they aren't counted towards the median strength heroList.back().hero->setAIRole( Heroes::Role::COURIER ); heroList.pop_back(); if ( heroList.size() > 2 ) { // We still have a plenty of heroes. In this case lets create a Scout hero to uncover the fog. heroList.back().hero->setAIRole( Heroes::Role::SCOUT ); heroList.pop_back(); } } assert( !heroList.empty() ); std::sort( heroList.begin(), heroList.end(), []( const HeroValue & first, const HeroValue & second ) { return first.strength > second.strength; } ); const double medianStrength = heroList[heroList.size() / 2].strength; for ( HeroValue & object : heroList ) { if ( valuableHero != nullptr && object.hero == valuableHero ) { object.hero->setAIRole( Heroes::Role::CHAMPION ); continue; } if ( object.strength > medianStrength * 3 ) { object.hero->setAIRole( Heroes::Role::FIGHTER ); } else { object.hero->setAIRole( Heroes::Role::HUNTER ); } } } std::optional getEnemyArmyOnTile( const int kingdomColor, const Maps::Tile & tile ) { const MP2::MapObjectType object = tile.getMainObjectType(); const int32_t tileIndex = tile.GetIndex(); if ( object == MP2::OBJ_HERO ) { const Heroes * hero = tile.getHero(); // TODO: this function can be called when the game world is not fully initialized yet if ( hero == nullptr ) { return {}; } if ( hero->isFriends( kingdomColor ) ) { return {}; } // If the hero is standing in one place, then he does not pose a threat (as well as the castle in which he may be located) if ( hero->Modes( Heroes::PATROL ) && hero->GetPatrolDistance() == 0 ) { return {}; } const Castle * castle = hero->inCastle(); // Rough estimate - if the hero is in the castle, then we sum up the power of the castle garrison with the power of the hero's army const double threat = castle ? castle->GetArmy().GetStrength() + hero->GetArmy().GetStrength() : hero->GetArmy().GetStrength(); return AI::EnemyArmy( tileIndex, hero, threat, hero->GetMaxMovePoints() ); } if ( object == MP2::OBJ_CASTLE ) { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( tileIndex ) ); // TODO: this function can be called when the game world is not fully initialized yet if ( castle == nullptr ) { return {}; } // Neutral castles don't pose a threat because they can't hire heroes if ( castle->GetColor() == Color::NONE || castle->isFriends( kingdomColor ) ) { return {}; } // If it's just a town where there's no way to build a castle, then there's no way to hire heroes who might pose a threat if ( !castle->isCastle() && !castle->AllowBuyBuilding( BUILD_CASTLE ) ) { return {}; } const double threat = castle->GetArmy().GetStrength(); // 1500 is slightly more than a fresh hero's maximum move points hired in a castle. return AI::EnemyArmy( tileIndex, nullptr, threat, 1500 ); } return {}; } } bool AI::Planner::recruitHero( Castle & castle, bool buyArmy ) { Kingdom & kingdom = castle.GetKingdom(); const Recruits & rec = kingdom.GetRecruits(); Heroes * recruit = nullptr; // Re-hiring a hero related to any of the WINS_HERO or LOSS_HERO conditions is not allowed const auto heroesToIgnore = std::make_pair( world.GetHeroesCondWins(), world.GetHeroesCondLoss() ); const auto useIfPossible = [&heroesToIgnore]( Heroes * hero ) -> Heroes * { if ( std::apply( [hero]( const auto... heroToIgnore ) { return ( ( hero == heroToIgnore ) || ... ); }, heroesToIgnore ) ) { return nullptr; } return hero; }; Heroes * firstRecruit = useIfPossible( rec.GetHero1() ); Heroes * secondRecruit = useIfPossible( rec.GetHero2() ); if ( firstRecruit && secondRecruit ) { if ( secondRecruit->getRecruitValue() > firstRecruit->getRecruitValue() ) { recruit = castle.RecruitHero( secondRecruit ); } else { recruit = castle.RecruitHero( firstRecruit ); } } else if ( firstRecruit ) { recruit = castle.RecruitHero( firstRecruit ); } else if ( secondRecruit ) { recruit = castle.RecruitHero( secondRecruit ); } if ( recruit == nullptr ) { return false; } if ( buyArmy ) { reinforceCastle( castle ); } else { OptimizeTroopsOrder( recruit->GetArmy() ); } return true; } void AI::Planner::evaluateRegionSafety() { std::vector> regionsToCheck; size_t lastPositive = 0; for ( size_t regionID = 0; regionID < _regions.size(); ++regionID ) { RegionStats & stats = _regions[regionID]; if ( ( stats.friendlyCastles && stats.enemyCastles ) || ( stats.highestThreat > 0 && !stats.enemyCastles ) ) { // contested space OR enemy heroes invaded our region // TODO: assess army strength to get more accurate reading stats.safetyFactor = -50; stats.evaluated = true; regionsToCheck.emplace_back( regionID, -50 ); } else if ( stats.enemyCastles ) { // straight up enemy territory stats.safetyFactor = -100; stats.evaluated = true; regionsToCheck.emplace_back( regionID, -100 ); } else if ( stats.friendlyCastles ) { // our protected castle stats.safetyFactor = 100; stats.evaluated = true; regionsToCheck.emplace_back( regionID, 100 ); ++lastPositive; } else { stats.safetyFactor = 0; stats.evaluated = false; } } std::sort( regionsToCheck.begin(), regionsToCheck.end(), []( const std::pair & left, const std::pair & right ) { return left.second > right.second; } ); size_t currentEntry = 0; size_t batchStart = 0; size_t batchEnd = lastPositive + 1; while ( currentEntry < regionsToCheck.size() ) { const MapRegion & region = world.getRegion( regionsToCheck[currentEntry].first ); for ( uint32_t secondaryID : region._neighbours ) { RegionStats & adjacentStats = _regions[secondaryID]; if ( !adjacentStats.evaluated ) { adjacentStats.evaluated = true; regionsToCheck.emplace_back( secondaryID, adjacentStats.safetyFactor ); } if ( adjacentStats.safetyFactor != 0 ) { // losing precision due to integer division is intentional here, values should be reduced to 0 eventually regionsToCheck[currentEntry].second += adjacentStats.safetyFactor / static_cast( region.getNeighboursCount() ); } } // no neighbours means it is an island; they are usually safer (or more dangerous to explore) due to boat movement penalties if ( region.getNeighboursCount() == 0 ) regionsToCheck[currentEntry].second = regionsToCheck[currentEntry].second * 3 / 2; if ( currentEntry == batchEnd - 1 ) { // Apply the calculated value in batches for ( size_t idx = batchStart; idx < batchEnd; ++idx ) { const size_t regionID = regionsToCheck[idx].first; _regions[regionID].safetyFactor = regionsToCheck[idx].second; DEBUG_LOG( DBG_AI, DBG_TRACE, "Region " << regionID << " safety factor is " << _regions[regionID].safetyFactor ) } batchStart = batchEnd; batchEnd = regionsToCheck.size(); } ++currentEntry; } } std::vector AI::Planner::getSortedCastleList( const VecCastles & castles, const std::set & castlesInDanger ) { std::vector sortedCastleList; sortedCastleList.reserve( castles.size() ); for ( Castle * castle : castles ) { if ( castle == nullptr ) { continue; } const int32_t castleIndex = castle->GetIndex(); const uint32_t regionID = world.getTile( castleIndex ).GetRegion(); sortedCastleList.emplace_back( castle, castlesInDanger.count( castleIndex ) > 0, _regions[regionID].safetyFactor, castle->getBuildingValue() ); } std::sort( sortedCastleList.begin(), sortedCastleList.end(), []( const AICastle & left, const AICastle & right ) { if ( !left.underThreat && !right.underThreat ) { return left.safetyFactor > right.safetyFactor; } if ( left.underThreat && !right.underThreat ) { return true; } if ( !left.underThreat && right.underThreat ) { return false; } // We have a building value of a castle and its safety factor. The higher safety factor the lower priority to defend the castle. // Since we compare 2 castles we need to use safety factor of the opposite castle. return left.buildingValue * right.safetyFactor > right.buildingValue * left.safetyFactor; } ); return sortedCastleList; } std::set AI::Planner::findCastlesInDanger( const Kingdom & kingdom ) { std::set castlesInDanger; // Since we are estimating danger for a castle and we need to know if an enemy hero can reach it // if no our heroes exist. So we are temporary removing them from the map. const TemporaryHeroEraser heroEraser( kingdom.GetHeroes() ); const AIWorldPathfinderStateRestorer pathfinderStateRestorer( _pathfinder ); // Use the "optimistic" pathfinder settings for enemy armies - minimal army advantage, minimal reserve of spell points _pathfinder.setMinimalArmyStrengthAdvantage( ARMY_ADVANTAGE_DESPERATE ); _pathfinder.setSpellPointsReserveRatio( 0.0 ); for ( const auto & [dummy, enemyArmy] : _enemyArmies ) { for ( const Castle * castle : kingdom.GetCastles() ) { if ( castle == nullptr ) { // How is it even possible? Check the logic! assert( 0 ); continue; } if ( updateIndividualPriorityForCastle( *castle, enemyArmy ) ) { castlesInDanger.insert( castle->GetIndex() ); } } } return castlesInDanger; } void AI::Planner::updatePriorityForEnemyArmy( const Kingdom & kingdom, const EnemyArmy & enemyArmy ) { // Since we are estimating danger for a castle and we need to know if an enemy hero can reach it // if no our heroes exist. So we are temporary removing them from the map. const TemporaryHeroEraser heroEraser( kingdom.GetHeroes() ); const AIWorldPathfinderStateRestorer pathfinderStateRestorer( _pathfinder ); // Use the "optimistic" pathfinder settings for enemy armies - minimal army advantage, minimal reserve of spell points _pathfinder.setMinimalArmyStrengthAdvantage( ARMY_ADVANTAGE_DESPERATE ); _pathfinder.setSpellPointsReserveRatio( 0.0 ); for ( const Castle * castle : kingdom.GetCastles() ) { if ( castle == nullptr ) { // How is it even possible? Check the logic! assert( 0 ); continue; } updateIndividualPriorityForCastle( *castle, enemyArmy ); } } void AI::Planner::updatePriorityForCastle( const Castle & castle ) { // Since we are estimating danger for a castle and we need to know if an enemy hero can reach it // if no our heroes exist. So we are temporary removing them from the map. const TemporaryHeroEraser heroEraser( castle.GetKingdom().GetHeroes() ); const AIWorldPathfinderStateRestorer pathfinderStateRestorer( _pathfinder ); // Use the "optimistic" pathfinder settings for enemy armies - minimal army advantage, minimal reserve of spell points _pathfinder.setMinimalArmyStrengthAdvantage( ARMY_ADVANTAGE_DESPERATE ); _pathfinder.setSpellPointsReserveRatio( 0.0 ); for ( const auto & [dummy, enemyArmy] : _enemyArmies ) { updateIndividualPriorityForCastle( castle, enemyArmy ); } } bool AI::Planner::updateIndividualPriorityForCastle( const Castle & castle, const EnemyArmy & enemyArmy ) { // 30 tiles, roughly how much maxed out hero can move in a turn. const uint32_t threatDistanceLimit = 3000; const int32_t castleIndex = castle.GetIndex(); // Skip precise distance check if army is too far to be a threat if ( Maps::GetApproximateDistance( enemyArmy.index, castleIndex ) * Maps::Ground::fastestMovePenalty > threatDistanceLimit ) { return false; } // When estimating the distance using the pathfinder, it should be taken into account that although the enemy army may be close to the castle, the castle // may still be invisible to the enemy army due to the fog of war, therefore, it is necessary to use an assessment of the path from the castle owner's point // of view, who obviously sees both the castle and the enemy army at the same time. // // Of course, on the other hand, it may be the other way around - the enemy army may have access to some path that is not yet visible to the castle owner, // but since the castle owner doesn't know about this for sure, using this option smacks of cheating. const uint32_t dist = _pathfinder.getDistance( enemyArmy.index, castleIndex, castle.GetColor(), enemyArmy.strength ); if ( dist == 0 || dist >= threatDistanceLimit ) { return false; } uint32_t daysToReach = ( dist + enemyArmy.movePoints - 1 ) / enemyArmy.movePoints; if ( daysToReach > 3 ) { // It is too far away. Ignore it. return false; } DEBUG_LOG( DBG_AI, DBG_TRACE, castle.GetName() << " is threatened by enemy army at " << enemyArmy.index ) double enemyStrength = enemyArmy.strength; --daysToReach; while ( daysToReach > 0 ) { // Each day reduces enemy strength by 50%. If an enemy is too far away then there is no reason to panic. enemyStrength /= 2; --daysToReach; } if ( const auto [iter, inserted] = _priorityTargets.try_emplace( enemyArmy.index, PriorityTaskType::ATTACK, castleIndex ); !inserted ) { iter->second.secondaryTaskTileId.insert( castleIndex ); } if ( const auto [iter, inserted] = _priorityTargets.try_emplace( castleIndex, PriorityTaskType::DEFEND, enemyArmy.index ); !inserted ) { iter->second.secondaryTaskTileId.insert( enemyArmy.index ); } // If the castle guard (including the garrison and the guest hero) is weaker than the enemy, then the // castle is considered to be in danger if ( castle.GetGarrisonStrength( enemyArmy.hero ) < enemyStrength ) { return true; } // If the guest hero himself is not able to defeat a threatening enemy in an open field, then the castle // is considered to be in danger, and the guest hero should probably stay in it const Heroes * hero = castle.GetHero(); if ( hero && hero->GetArmy().GetStrength() <= enemyStrength * ARMY_ADVANTAGE_SMALL ) { return true; } return false; } void AI::Planner::removePriorityAttackTarget( const int32_t tileIndex ) { const auto it = _priorityTargets.find( tileIndex ); if ( it == _priorityTargets.end() ) { return; } const PriorityTask & attackTask = it->second; if ( attackTask.type != PriorityTaskType::ATTACK ) { return; } for ( const int32_t secondaryTaskId : attackTask.secondaryTaskTileId ) { // If this assertion blows then you are attacking and defending the same tile! assert( secondaryTaskId != tileIndex ); auto defenseTask = _priorityTargets.find( secondaryTaskId ); if ( defenseTask == _priorityTargets.end() ) { continue; } if ( defenseTask->second.type != PriorityTaskType::DEFEND ) { continue; } // check if a secondary task still present std::set & defenseSecondaries = defenseTask->second.secondaryTaskTileId; defenseSecondaries.erase( tileIndex ); if ( defenseSecondaries.empty() ) { // if no one else was threatening this then we no longer have to defend _priorityTargets.erase( secondaryTaskId ); } } _priorityTargets.erase( tileIndex ); } void AI::Planner::updatePriorityAttackTarget( const Kingdom & kingdom, const Maps::Tile & tile ) { const int32_t tileIndex = tile.GetIndex(); const auto enemyArmy = getEnemyArmyOnTile( kingdom.GetColor(), tile ); if ( !enemyArmy ) { _enemyArmies.erase( tileIndex ); return; } assert( enemyArmy->index == tileIndex ); if ( const auto [iter, inserted] = _enemyArmies.try_emplace( tileIndex, *enemyArmy ); !inserted ) { iter->second = *enemyArmy; } updatePriorityForEnemyArmy( kingdom, *enemyArmy ); } void AI::Planner::KingdomTurn( Kingdom & kingdom ) { #if defined( WITH_DEBUG ) class AIAutoControlModeCommitter { public: explicit AIAutoControlModeCommitter( const Kingdom & kingdom ) : _kingdomColor( kingdom.GetColor() ) {} AIAutoControlModeCommitter( const AIAutoControlModeCommitter & ) = delete; ~AIAutoControlModeCommitter() { Player * player = Players::Get( _kingdomColor ); assert( player != nullptr ); if ( player->isAIAutoControlMode() ) { player->commitAIAutoControlMode(); } } AIAutoControlModeCommitter & operator=( const AIAutoControlModeCommitter & ) = delete; private: const int _kingdomColor; }; const AIAutoControlModeCommitter aiAutoControlModeCommitter( kingdom ); #endif _mapActionObjects.clear(); _priorityTargets.clear(); _enemyArmies.clear(); // Clear the tile army strength cache because the strength of the respective armies might have changed since last time _tileArmyStrengthValues.clear(); _regions.clear(); _regions.resize( world.getRegionCount() ); const int myColor = kingdom.GetColor(); if ( kingdom.isLoss() || myColor == Color::NONE ) { kingdom.LossPostActions(); return; } // Reset the turn progress indicator Interface::StatusPanel & status = Interface::AdventureMap::Get().getStatusPanel(); status.drawAITurnProgress( 0 ); AudioManager::PlayMusicAsync( MUS::COMPUTER_TURN, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); VecHeroes & heroes = kingdom.GetHeroes(); const VecCastles & castles = kingdom.GetCastles(); DEBUG_LOG( DBG_AI, DBG_INFO, Color::String( myColor ) << " starts the turn: " << castles.size() << " castles, " << heroes.size() << " heroes" ) DEBUG_LOG( DBG_AI, DBG_INFO, "Funds: " << kingdom.GetFunds().String() ) // Step 1. Scan visible map (based on game difficulty), add goals and threats bool underViewSpell = false; int32_t availableHeroCount = 0; Heroes * bestHeroToViewAll = nullptr; for ( Heroes * hero : heroes ) { hero->ResetModes( Heroes::SLEEPER ); hero->setDimensionDoorUsage( 0 ); if ( !hero->Modes( Heroes::PATROL ) ) { ++availableHeroCount; } if ( hero->HaveSpell( Spell::VIEWALL ) && ( !bestHeroToViewAll || hero->HasSecondarySkill( Skill::Secondary::MYSTICISM ) ) ) { bestHeroToViewAll = hero; } } if ( bestHeroToViewAll && HeroesCastAdventureSpell( *bestHeroToViewAll, Spell::VIEWALL ) ) { underViewSpell = true; } const int mapSize = world.w() * world.h(); for ( int idx = 0; idx < mapSize; ++idx ) { const Maps::Tile & tile = world.getTile( idx ); MP2::MapObjectType objectType = tile.getMainObjectType(); const uint32_t regionID = tile.GetRegion(); if ( regionID >= _regions.size() ) { assert( 0 ); continue; } RegionStats & stats = _regions[regionID]; if ( !underViewSpell && tile.isFog( myColor ) ) { continue; } if ( !MP2::isInGameActionObject( objectType ) ) { continue; } if ( const auto [dummy, inserted] = _mapActionObjects.try_emplace( idx, objectType ); !inserted ) { assert( 0 ); } if ( objectType == MP2::OBJ_HERO ) { const Heroes * hero = tile.getHero(); assert( hero != nullptr ); if ( hero->GetColor() == myColor && !hero->Modes( Heroes::PATROL ) ) { ++stats.friendlyHeroes; const int wisdomLevel = hero->GetLevelSkill( Skill::Secondary::WISDOM ); if ( wisdomLevel + 2 > stats.spellLevel ) { stats.spellLevel = wisdomLevel + 2; } } // This hero can be in a castle objectType = tile.getMainObjectType( false ); } if ( objectType == MP2::OBJ_CASTLE ) { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( idx ) ); assert( castle != nullptr ); if ( castle->isFriends( myColor ) ) { ++stats.friendlyCastles; } else if ( castle->GetColor() != Color::NONE ) { ++stats.enemyCastles; } } const auto enemyArmy = getEnemyArmyOnTile( myColor, tile ); if ( enemyArmy ) { assert( enemyArmy->index == idx ); if ( const auto [dummy, inserted] = _enemyArmies.try_emplace( idx, *enemyArmy ); !inserted ) { assert( 0 ); } if ( stats.highestThreat < enemyArmy->strength ) { stats.highestThreat = enemyArmy->strength; } } } DEBUG_LOG( DBG_AI, DBG_TRACE, Color::String( myColor ) << " found " << _mapActionObjects.size() << " valid objects" ) evaluateRegionSafety(); updateKingdomBudget( kingdom ); uint32_t currentProgressValue = 1; status.drawAITurnProgress( currentProgressValue ); std::set castlesInDanger; std::vector sortedCastleList; while ( true ) { // Step 2. Do some hero stuff. // If a hero is standing in a castle most likely he has nothing to do so let's try to give him more army. for ( Heroes * hero : heroes ) { HeroesActionComplete( *hero, hero->GetIndex(), MP2::OBJ_NONE ); } // Step 3. Reassign heroes roles setHeroRoles( heroes, Game::getDifficulty() ); castlesInDanger = findCastlesInDanger( kingdom ); for ( Heroes * hero : heroes ) { if ( castlesInDanger.find( hero->GetIndex() ) != castlesInDanger.end() ) { // If a hero is in a castle and this castle is in danger then the hero is most likely not able to defeat // a threatening enemy in an open field. Therefore let's make him stay in the castle. // TODO: allow the hero to still do some actions but always return to the castle at the end of the turn. HeroesActionComplete( *hero, hero->GetIndex(), hero->getObjectTypeUnderHero() ); } } sortedCastleList = getSortedCastleList( castles, castlesInDanger ); // If AI has less than three heroes at the start of the turn we assume // that he will buy another one in this turn and allow progress to increase only for 2 points. uint32_t const endProgressValue = ( currentProgressValue == 1 ) ? std::min( static_cast( heroes.size() ) * 2U + 1U, 8U ) : std::min( currentProgressValue + 2U, 9U ); bool moreTaskForHeroes = HeroesTurn( heroes, currentProgressValue, endProgressValue ); // Step 4. Buy new heroes, adjust roles, sort heroes based on priority or strength if ( purchaseNewHeroes( sortedCastleList, castlesInDanger, availableHeroCount, moreTaskForHeroes ) ) { assert( !heroes.empty() && heroes.back() != nullptr ); updateMapActionObjectCache( heroes.back()->GetIndex() ); ++availableHeroCount; continue; } if ( !moreTaskForHeroes && world.LastDay() ) { // Heroes have nothing to do. In this case it is wise to move heroes to castles especially if it is the last day of a week. // So for the next day a hero will have a maximum amount of spell points as well as new troops. for ( const Castle * castle : castles ) { assert( castle != nullptr ); if ( castle->GetHero() == nullptr ) { if ( const auto [dummy, inserted] = _priorityTargets.try_emplace( castle->GetIndex(), PriorityTaskType::REINFORCE ); inserted ) { DEBUG_LOG( DBG_AI, DBG_INFO, castle->GetName() << " is designated as a priority target to reinforce nearby heroes" ) moreTaskForHeroes = true; } } } if ( moreTaskForHeroes ) { continue; } } break; } status.drawAITurnProgress( 9 ); // Sync the list of castles (if new ones were captured during the turn) if ( castles.size() != sortedCastleList.size() ) { evaluateRegionSafety(); castlesInDanger = findCastlesInDanger( kingdom ); sortedCastleList = getSortedCastleList( castles, castlesInDanger ); } // Step 5. Castle development according to kingdom budget for ( const AICastle & entry : sortedCastleList ) { if ( entry.castle != nullptr ) { CastleTurn( *entry.castle, entry.underThreat ); } } // For heroes in castles or towns, transfer their slowest troops to the garrison at the end of the turn to try to get a movement bonus on the next turn for ( Heroes * hero : heroes ) { Castle * castle = hero->inCastleMutable(); if ( castle == nullptr ) { continue; } transferSlowestTroopsToGarrison( hero, castle ); } status.resetAITurnProgress(); } bool AI::Planner::purchaseNewHeroes( const std::vector & sortedCastleList, const std::set & castlesInDanger, const int32_t availableHeroCount, const bool moreTasksForHeroes ) { const bool isEarlyGameWithSingleCastle = world.CountDay() < 5 && sortedCastleList.size() == 1; const int32_t heroLimit = isEarlyGameWithSingleCastle ? 2 : world.w() / Maps::SMALL + 2; if ( availableHeroCount >= heroLimit ) { return false; } Castle * recruitmentCastle = nullptr; double bestArmyAvailable = -1.0; // search for best castle to recruit hero from for ( const AICastle & entry : sortedCastleList ) { Castle * castle = entry.castle; if ( castle && castle->isCastle() ) { const Heroes * hero = castle->GetHero(); const int mapIndex = castle->GetIndex(); // Make sure there is no hero in castle already and we're not under threat while having other heroes. if ( hero != nullptr || ( availableHeroCount > 0 && castlesInDanger.find( mapIndex ) != castlesInDanger.end() ) ) continue; const uint32_t regionID = world.getTile( mapIndex ).GetRegion(); const int heroesInRegion = _regions[regionID].friendlyHeroes; if ( heroesInRegion > 1 ) continue; const size_t neighboursCount = world.getRegion( regionID ).getNeighboursCount(); // don't buy another hero if there's nothing to do or castle is on an island if ( heroesInRegion > 0 && ( !moreTasksForHeroes || ( sortedCastleList.size() > 1 && neighboursCount == 0 ) ) ) { continue; } const double availableArmy = castle->getArmyRecruitmentValue(); if ( recruitmentCastle == nullptr || availableArmy > bestArmyAvailable ) { recruitmentCastle = castle; bestArmyAvailable = availableArmy; } } } // target found, buy hero return recruitmentCastle && recruitHero( *recruitmentCastle, !isEarlyGameWithSingleCastle ); } fheroes2-1.1.6+dfsg/src/fheroes2/army/000077500000000000000000000000001476115357100174415ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/army/army.cpp000066400000000000000000001673501476115357100211310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "army.h" #include #include #include #include #include #include #include #include #include #include "army_troop.h" #include "army_ui_helper.h" #include "artifact.h" #include "artifact_info.h" #include "campaign_data.h" #include "campaign_savedata.h" #include "campaign_scenariodata.h" #include "castle.h" #include "color.h" #include "heroes.h" #include "heroes_base.h" #include "kingdom.h" #include "logging.h" #include "luck.h" #include "maps_tiles.h" #include "maps_tiles_helper.h" #include "morale.h" #include "mp2.h" #include "race.h" #include "rand.h" #include "resource.h" #include "screen.h" #include "serialize.h" #include "settings.h" #include "skill.h" #include "tools.h" #include "translations.h" #include "world.h" namespace fheroes2 { class Image; } namespace { enum class ArmySize : uint32_t { ARMY_FEW = 1, ARMY_SEVERAL = 5, ARMY_PACK = 10, ARMY_LOTS = 20, ARMY_HORDE = 50, ARMY_THRONG = 100, ARMY_SWARM = 250, ARMY_ZOUNDS = 500, ARMY_LEGION = 1000 }; ArmySize getArmySize( const uint32_t count ) { const ArmySize countAsEnum = static_cast( count ); if ( ArmySize::ARMY_LEGION <= countAsEnum ) { return ArmySize::ARMY_LEGION; } if ( ArmySize::ARMY_ZOUNDS <= countAsEnum ) { return ArmySize::ARMY_ZOUNDS; } if ( ArmySize::ARMY_SWARM <= countAsEnum ) { return ArmySize::ARMY_SWARM; } if ( ArmySize::ARMY_THRONG <= countAsEnum ) { return ArmySize::ARMY_THRONG; } if ( ArmySize::ARMY_HORDE <= countAsEnum ) { return ArmySize::ARMY_HORDE; } if ( ArmySize::ARMY_LOTS <= countAsEnum ) { return ArmySize::ARMY_LOTS; } if ( ArmySize::ARMY_PACK <= countAsEnum ) { return ArmySize::ARMY_PACK; } if ( ArmySize::ARMY_SEVERAL <= countAsEnum ) { return ArmySize::ARMY_SEVERAL; } return ArmySize::ARMY_FEW; } std::pair getNumberOfMonstersInStartingArmy( const Monster & monster ) { switch ( monster.GetMonsterLevel() ) { case 1: switch ( monster.GetID() ) { case Monster::PEASANT: return { 30, 50 }; case Monster::GOBLIN: return { 15, 25 }; case Monster::SPRITE: return { 10, 20 }; default: return { 6, 10 }; } case 2: switch ( monster.GetID() ) { case Monster::ARCHER: case Monster::ORC: return { 3, 5 }; default: return { 2, 4 }; } default: assert( 0 ); break; } return { 0, 0 }; } } std::string Army::TroopSizeString( const Troop & troop ) { std::string str; switch ( getArmySize( troop.GetCount() ) ) { case ArmySize::ARMY_FEW: str = _( "A few\n%{monster}" ); break; case ArmySize::ARMY_SEVERAL: str = _( "Several\n%{monster}" ); break; case ArmySize::ARMY_PACK: str = _( "A pack of\n%{monster}" ); break; case ArmySize::ARMY_LOTS: str = _( "Lots of\n%{monster}" ); break; case ArmySize::ARMY_HORDE: str = _( "A horde of\n%{monster}" ); break; case ArmySize::ARMY_THRONG: str = _( "A throng of\n%{monster}" ); break; case ArmySize::ARMY_SWARM: str = _( "A swarm of\n%{monster}" ); break; case ArmySize::ARMY_ZOUNDS: str = _( "Zounds...\n%{monster}" ); break; case ArmySize::ARMY_LEGION: str = _( "A legion of\n%{monster}" ); break; default: // Are you passing the correct value? assert( 0 ); break; } StringReplaceWithLowercase( str, "%{monster}", troop.GetMultiName() ); return str; } std::string Army::SizeString( uint32_t size ) { switch ( getArmySize( size ) ) { case ArmySize::ARMY_FEW: return _( "army|Few" ); case ArmySize::ARMY_SEVERAL: return _( "army|Several" ); case ArmySize::ARMY_PACK: return _( "army|Pack" ); case ArmySize::ARMY_LOTS: return _( "army|Lots" ); case ArmySize::ARMY_HORDE: return _( "army|Horde" ); case ArmySize::ARMY_THRONG: return _( "army|Throng" ); case ArmySize::ARMY_SWARM: return _( "army|Swarm" ); case ArmySize::ARMY_ZOUNDS: return _( "army|Zounds" ); case ArmySize::ARMY_LEGION: return _( "army|Legion" ); default: // Are you passing the correct value? assert( 0 ); break; } return {}; } Troops::Troops( const Troops & troops ) : std::vector() { reserve( troops.size() ); for ( const Troop * troop : troops ) { assert( troop != nullptr ); push_back( new Troop( *troop ) ); } } Troops::~Troops() { std::for_each( begin(), end(), []( Troop * troop ) { assert( troop != nullptr ); delete troop; } ); } void Troops::Assign( const Troop * troopsBegin, const Troop * troopsEnd ) { Clean(); for ( iterator iter = begin(); iter != end() && troopsBegin != troopsEnd; ++iter, ++troopsBegin ) { assert( *iter != nullptr && troopsBegin != nullptr ); if ( troopsBegin->isValid() ) { ( *iter )->Set( *troopsBegin ); } } } void Troops::Assign( const Troops & troops ) { Clean(); for ( auto [thisIter, troopsIter] = std::make_pair( begin(), troops.begin() ); thisIter != end() && troopsIter != troops.end(); ++thisIter, ++troopsIter ) { assert( *thisIter != nullptr && *troopsIter != nullptr ); if ( ( *troopsIter )->isValid() ) { ( *thisIter )->Set( **troopsIter ); } } } void Troops::Insert( const Troops & troops ) { for ( const Troop * troop : troops ) { assert( troop != nullptr ); push_back( new Troop( *troop ) ); } } void Troops::PushBack( const Monster & mons, const uint32_t count ) { push_back( new Troop( mons, count ) ); } void Troops::PopBack() { if ( empty() ) { return; } delete back(); pop_back(); } Troop * Troops::GetTroop( size_t pos ) { return pos < size() ? at( pos ) : nullptr; } const Troop * Troops::GetTroop( size_t pos ) const { return pos < size() ? at( pos ) : nullptr; } void Troops::UpgradeMonsters( const Monster & m ) { for ( iterator it = begin(); it != end(); ++it ) { if ( **it == m && ( *it )->isValid() ) { ( *it )->Upgrade(); } } } uint32_t Troops::GetCountMonsters( const Monster & mons ) const { const int monsterId = mons.GetID(); uint32_t result = 0; for ( const Troop * troop : *this ) { assert( troop != nullptr ); if ( troop->isValid() && troop->isMonster( monsterId ) ) { result += troop->GetCount(); } } return result; } double Troops::getReinforcementValue( const Troops & reinforcement ) const { // NB items that are added in this vector are all of Troop* type, and not ArmyTroop* type // So the GetStrength() computation will be done based on troop strength only (not based on hero bonuses) Troops combined( *this ); const double initialValue = combined.GetStrength(); combined.Insert( reinforcement.GetOptimized() ); combined.MergeSameMonsterTroops(); combined.SortStrongest(); while ( combined.Size() > Army::maximumTroopCount ) { combined.PopBack(); } return combined.GetStrength() - initialValue; } bool Troops::isValid() const { for ( const_iterator it = begin(); it != end(); ++it ) { if ( ( *it )->isValid() ) return true; } return false; } uint32_t Troops::GetOccupiedSlotCount() const { uint32_t total = 0; for ( const_iterator it = begin(); it != end(); ++it ) { if ( ( *it )->isValid() ) ++total; } return total; } bool Troops::areAllTroopsUnique() const { std::set monsterId; for ( const Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } if ( auto [dummy, inserted] = monsterId.emplace( troop->GetID() ); !inserted ) { return false; } } return true; } bool Troops::HasMonster( const Monster & mons ) const { const int monsterID = mons.GetID(); for ( const_iterator it = begin(); it != end(); ++it ) { if ( ( *it )->isValid() && ( *it )->isMonster( monsterID ) ) { return true; } } return false; } bool Troops::AllTroopsAreUndead() const { bool isValidArmy = false; for ( const_iterator it = begin(); it != end(); ++it ) { if ( ( *it )->isValid() ) { isValidArmy = true; if ( !( *it )->isUndead() ) { return false; } } } // If army has no units then the army cannot be marked as undead. return isValidArmy; } bool Troops::CanJoinTroop( const Monster & mons ) const { return std::any_of( begin(), end(), [&mons]( const Troop * troop ) { return troop->isMonster( mons.GetID() ); } ) || std::any_of( begin(), end(), []( const Troop * troop ) { return !troop->isValid(); } ); } bool Troops::JoinTroop( const Monster & mons, const uint32_t count, const bool emptySlotFirst ) { if ( !mons.isValid() || count == 0 ) { return false; } const auto findBestMatch = [this]( const auto higherPriorityPredicate, const auto lowerPriorityPredicate ) { const auto iter = std::find_if( begin(), end(), higherPriorityPredicate ); if ( iter != end() ) { return iter; } return std::find_if( begin(), end(), lowerPriorityPredicate ); }; const auto isSlotEmpty = []( const Troop * troop ) { assert( troop != nullptr ); return troop->isEmpty(); }; const auto isSameMonster = [&mons]( const Troop * troop ) { assert( troop != nullptr ); return troop->isValid() && troop->isMonster( mons.GetID() ); }; const auto iter = emptySlotFirst ? findBestMatch( isSlotEmpty, isSameMonster ) : findBestMatch( isSameMonster, isSlotEmpty ); if ( iter == end() ) { return false; } if ( ( *iter )->isValid() ) { ( *iter )->SetCount( ( *iter )->GetCount() + count ); } else { ( *iter )->Set( mons, count ); } return true; } bool Troops::JoinTroop( const Troop & troop ) { if ( !troop.isValid() ) { return false; } return JoinTroop( troop.GetMonster(), troop.GetCount(), false ); } bool Troops::AllTroopsAreTheSame() const { int firstMonsterId = Monster::UNKNOWN; for ( const Troop * troop : *this ) { if ( troop->isValid() ) { if ( firstMonsterId == Monster::UNKNOWN ) { firstMonsterId = troop->GetID(); } else if ( troop->GetID() != firstMonsterId ) { return false; } } } return true; } double Troops::GetStrength() const { double strength = 0; for ( const Troop * troop : *this ) { if ( troop && troop->isValid() ) strength += troop->GetStrength(); } return strength; } uint32_t Troops::getTotalHP() const { uint32_t hp = 0; for ( const Troop * troop : *this ) { if ( troop && troop->isValid() ) hp += troop->GetCount() * troop->GetHitPoints(); } return hp; } void Troops::Clean() { std::for_each( begin(), end(), []( Troop * troop ) { troop->Reset(); } ); } void Troops::UpgradeTroops( const Castle & castle ) const { for ( Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } if ( !troop->isAllowUpgrade() ) { continue; } if ( castle.GetRace() != troop->GetRace() ) { continue; } if ( !castle.isBuild( troop->GetUpgrade().GetDwelling() ) ) { continue; } Kingdom & kingdom = castle.GetKingdom(); const Funds payment = troop->GetTotalUpgradeCost(); if ( !kingdom.AllowPayment( payment ) ) { continue; } kingdom.OddFundsResource( payment ); troop->Upgrade(); } } Troop * Troops::GetFirstValid() const { if ( const const_iterator iter = std::find_if( begin(), end(), []( const Troop * troop ) { return troop->isValid(); } ); iter != end() ) { return *iter; } return nullptr; } Troop * Troops::getBestMatchToCondition( const std::function & condition ) const { const_iterator bestMatch = std::find_if( begin(), end(), []( const Troop * troop ) { assert( troop != nullptr ); return troop->isValid(); } ); if ( bestMatch == end() ) { return nullptr; } const_iterator iter = bestMatch + 1; while ( iter != end() ) { assert( *iter != nullptr ); if ( ( *iter )->isValid() && condition( *iter, *bestMatch ) ) { bestMatch = iter; } ++iter; } return *bestMatch; } Troop * Troops::GetWeakestTroop() const { return getBestMatchToCondition( Army::WeakestTroop ); } Troop * Troops::GetSlowestTroop() const { return getBestMatchToCondition( Army::SlowestTroop ); } void Troops::MergeSameMonsterTroops() { for ( size_t slot = 0; slot < size(); ++slot ) { Troop * troop = at( slot ); assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } const int monsterId = troop->GetID(); for ( size_t otherSlot = slot + 1; otherSlot < size(); ++otherSlot ) { Troop * otherTroop = at( otherSlot ); assert( otherTroop != nullptr ); if ( otherTroop->isValid() && otherTroop->isMonster( monsterId ) ) { troop->SetCount( troop->GetCount() + otherTroop->GetCount() ); otherTroop->Reset(); } } } } bool Troops::MergeSameMonsterOnce() { for ( size_t slot = 0; slot < size(); ++slot ) { Troop * troop = at( slot ); assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } const int monsterId = troop->GetID(); for ( size_t otherSlot = slot + 1; otherSlot < size(); ++otherSlot ) { Troop * otherTroop = at( otherSlot ); assert( otherTroop != nullptr ); if ( otherTroop->isValid() && otherTroop->isMonster( monsterId ) ) { troop->SetCount( troop->GetCount() + otherTroop->GetCount() ); otherTroop->Reset(); return true; } } } return false; } Troops Troops::GetOptimized() const { Troops result; result.reserve( size() ); for ( const Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } const int monsterId = troop->GetID(); const const_iterator iter = std::find_if( result.begin(), result.end(), [monsterId]( const Troop * resultTroop ) { return resultTroop->isMonster( monsterId ); } ); if ( iter == result.end() ) { result.push_back( new Troop( *troop ) ); } else { Troop * resultTroop = *iter; assert( resultTroop != nullptr ); resultTroop->SetCount( resultTroop->GetCount() + troop->GetCount() ); } } return result; } void Troops::SortStrongest() { std::sort( begin(), end(), Army::StrongestTroop ); } void Troops::JoinStrongest( Troops & giverArmy, const bool keepAtLeastOneSlotForGiver ) { if ( this == &giverArmy ) return; // validate the size (can be different from maximumTroopCount) if ( giverArmy.size() < size() ) giverArmy.resize( size() ); // first try to keep units in the same slots for ( size_t slot = 0; slot < size(); ++slot ) { Troop * leftTroop = at( slot ); Troop * rightTroop = giverArmy[slot]; if ( rightTroop && rightTroop->isValid() ) { assert( leftTroop != nullptr ); if ( !leftTroop->isValid() ) { // if slot is empty, simply move the unit leftTroop->Set( *rightTroop ); rightTroop->Reset(); } else if ( leftTroop->GetID() == rightTroop->GetID() ) { // check if we can merge them leftTroop->SetCount( leftTroop->GetCount() + rightTroop->GetCount() ); rightTroop->Reset(); } } } // there's still unmerged units left and there's empty room for them for ( size_t slot = 0; slot < giverArmy.size(); ++slot ) { Troop * rightTroop = giverArmy[slot]; if ( rightTroop && JoinTroop( rightTroop->GetMonster(), rightTroop->GetCount(), false ) ) { rightTroop->Reset(); } } // if there's more units than slots, start optimizing if ( giverArmy.GetOccupiedSlotCount() > 0 ) { Troops rightPriority = giverArmy.GetOptimized(); giverArmy.Clean(); // strongest at the end std::sort( rightPriority.begin(), rightPriority.end(), Army::WeakestTroop ); // 1. Merge any remaining stacks to free some space MergeSameMonsterTroops(); // 2. Fill empty slots with best troops (if there are any) size_t count = GetOccupiedSlotCount(); while ( count < Army::maximumTroopCount && !rightPriority.empty() ) { if ( !JoinTroop( *rightPriority.back() ) ) { // Something is wrong with calculation of free monster slots. Check the logic! assert( 0 ); } rightPriority.PopBack(); ++count; } // 3. Swap weakest and strongest unit until there's no left while ( !rightPriority.empty() ) { Troop * weakest = GetWeakestTroop(); if ( !weakest || Army::StrongestTroop( weakest, rightPriority.back() ) ) { // we're done processing if second army units are weaker break; } Army::SwapTroops( *weakest, *rightPriority.back() ); std::sort( rightPriority.begin(), rightPriority.end(), Army::WeakestTroop ); } // 4. The rest goes back to second army while ( !rightPriority.empty() ) { if ( !giverArmy.JoinTroop( *rightPriority.back() ) ) { // We somehow cannot give the same army back. assert( 0 ); } rightPriority.PopBack(); } } if ( !keepAtLeastOneSlotForGiver || giverArmy.isValid() ) { // Either the giver army does not need an extra army or it already has some. return; } Troop * weakest = GetWeakestTroop(); if ( weakest == nullptr || !weakest->isValid() ) { // How is possible that after we have merged 2 armies no monsters are present? assert( 0 ); return; } // First check if the weakest troop is actually worth to keep. const double weakestStrength = weakest->GetStrength(); const double totalArmyStrength = Troops::GetStrength(); assert( totalArmyStrength >= weakestStrength ); // The weakest army should not be more than 5% from the overall army strength. const double strengthLimit = totalArmyStrength / 20; if ( weakestStrength < strengthLimit ) { // The weakest troop is less than limit. Just kick this weakling out. if ( !giverArmy.JoinTroop( *weakest, weakest->GetCount(), false ) ) { // The army is empty and we cannot add more troops? assert( 0 ); } weakest->Reset(); } else { uint32_t acceptableCount = static_cast( strengthLimit / weakestStrength * weakest->GetCount() ); assert( acceptableCount <= weakest->GetCount() ); if ( acceptableCount > weakest->GetCount() / 2 ) { // No more than half. acceptableCount = weakest->GetCount() / 2; } if ( acceptableCount < 1 ) { acceptableCount = 1; } if ( !giverArmy.JoinTroop( *weakest, acceptableCount, false ) ) { // The army is empty and we cannot add more troops? assert( 0 ); } weakest->SetCount( weakest->GetCount() - acceptableCount ); } } void Troops::SplitTroopIntoFreeSlots( const Troop & troop, const Troop & selectedSlot, const uint32_t slots ) { const iterator selectedSlotIterator = std::find( begin(), end(), &selectedSlot ); // this means the selected slot is actually not part of the army, which is not the intended logic if ( selectedSlotIterator == end() ) { return; } addNewTroopsToFreeSlots( troop, slots ); } void Troops::addNewTroopsToFreeSlots( const Troop & troop, uint32_t maxSlots ) { if ( maxSlots < 1 || GetOccupiedSlotCount() >= Size() ) { assert( 0 ); return; } if ( maxSlots > Size() - GetOccupiedSlotCount() ) { maxSlots = static_cast( Size() ) - GetOccupiedSlotCount(); } const uint32_t chunk = troop.GetCount() / maxSlots; uint32_t remainingCount = troop.GetCount() % maxSlots; uint32_t remainingSlots = maxSlots; const auto TryCreateTroopChunk = [&remainingSlots, &remainingCount, chunk, &troop]( Troop & newTroop ) { if ( remainingSlots <= 0 ) return; if ( !newTroop.isValid() ) { newTroop.Set( troop.GetMonster(), remainingCount > 0 ? chunk + 1 : chunk ); --remainingSlots; if ( remainingCount > 0 ) --remainingCount; } }; for ( size_t i = 0; i < Size(); ++i ) { TryCreateTroopChunk( *GetTroop( i ) ); } } bool Troops::mergeWeakestTroopsIfNeeded() { if ( !isFullHouse() ) { return true; } std::map monsterIdVsSlotCount; std::map monsterIdVsStrength; for ( const Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } const int id = troop->GetID(); if ( monsterIdVsStrength.count( id ) > 0 ) { monsterIdVsStrength[id] += troop->GetStrength(); ++monsterIdVsSlotCount[id]; } else { monsterIdVsSlotCount.emplace( id, 1 ); monsterIdVsStrength.emplace( id, troop->GetStrength() ); } } if ( monsterIdVsStrength.size() == size() ) { return false; } assert( monsterIdVsSlotCount.size() == monsterIdVsStrength.size() ); std::vector> sortedMultiSlotMonsterIdVsStrength; for ( const auto & [id, slotCount] : monsterIdVsSlotCount ) { if ( slotCount > 1 ) { sortedMultiSlotMonsterIdVsStrength.emplace_back( id, monsterIdVsStrength[id] ); } } assert( !sortedMultiSlotMonsterIdVsStrength.empty() ); std::sort( sortedMultiSlotMonsterIdVsStrength.begin(), sortedMultiSlotMonsterIdVsStrength.end(), []( const auto & left, const auto & right ) { return left.second < right.second; } ); const int weakestMonsterToMerge = sortedMultiSlotMonsterIdVsStrength.front().first; // Reset the last slot. uint32_t monsterCount = 0; for ( Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } if ( troop->GetID() == weakestMonsterToMerge ) { monsterCount += troop->GetCount(); troop->Reset(); } } addNewTroopsToFreeSlots( Troop( weakestMonsterToMerge, monsterCount ), monsterIdVsSlotCount[weakestMonsterToMerge] - 1 ); return true; } void Troops::splitStackOfWeakestUnitsIntoFreeSlots() { const uint32_t occupiedSlotCount = GetOccupiedSlotCount(); if ( occupiedSlotCount == size() ) { // Nothing to do as all slots are being occupied. return; } // Look for a stack consisting of the weakest units Troop * stackOfWeakestUnits = nullptr; for ( Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } if ( stackOfWeakestUnits == nullptr || stackOfWeakestUnits->GetMonsterStrength() > troop->GetMonsterStrength() ) { stackOfWeakestUnits = troop; } } assert( stackOfWeakestUnits != nullptr ); assert( stackOfWeakestUnits->GetCount() > 0 ); const uint32_t count = std::min( static_cast( size() ) - occupiedSlotCount, stackOfWeakestUnits->GetCount() - 1 ); if ( count == 0 ) { return; } stackOfWeakestUnits->SetCount( stackOfWeakestUnits->GetCount() - count ); addNewTroopsToFreeSlots( { stackOfWeakestUnits->GetMonster(), count }, count ); } void Troops::AssignToFirstFreeSlot( const Troop & troopToAssign, const uint32_t count ) const { for ( Troop * troop : *this ) { assert( troop != nullptr ); if ( troop->isValid() ) { continue; } troop->Set( troopToAssign.GetMonster(), count ); break; } } void Troops::JoinAllTroopsOfType( const Troop & targetTroop ) const { const int troopID = targetTroop.GetID(); const int totalMonsterCount = GetCountMonsters( troopID ); for ( Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() || troop->GetID() != troopID ) { continue; } if ( troop == &targetTroop ) { troop->SetCount( totalMonsterCount ); } else { troop->Reset(); } } } Army::Army( HeroBase * cmdr /* = nullptr */ ) : commander( cmdr ) , _isSpreadCombatFormation( true ) , color( Color::NONE ) { reserve( maximumTroopCount ); for ( size_t i = 0; i < maximumTroopCount; ++i ) { push_back( new ArmyTroop( this ) ); } } Army::Army( const Maps::Tile & tile ) : commander( nullptr ) , _isSpreadCombatFormation( true ) , color( Color::NONE ) { reserve( maximumTroopCount ); for ( size_t i = 0; i < maximumTroopCount; ++i ) { push_back( new ArmyTroop( this ) ); } setFromTile( tile ); } const Troops & Army::getTroops() const { return *this; } void Army::setFromTile( const Maps::Tile & tile ) { assert( commander == nullptr ); Troops::Clean(); const bool isCaptureObject = MP2::isCaptureObject( tile.getMainObjectType( false ) ); if ( isCaptureObject ) { color = getColorFromTile( tile ); } else { color = Color::NONE; } switch ( tile.getMainObjectType( false ) ) { case MP2::OBJ_PYRAMID: at( 0 )->Set( Monster::VAMPIRE_LORD, 10 ); at( 1 )->Set( Monster::ROYAL_MUMMY, 10 ); at( 2 )->Set( Monster::ROYAL_MUMMY, 10 ); at( 3 )->Set( Monster::ROYAL_MUMMY, 10 ); at( 4 )->Set( Monster::VAMPIRE_LORD, 10 ); break; case MP2::OBJ_GRAVEYARD: at( 0 )->Set( Monster::MUTANT_ZOMBIE, 20 ); at( 1 )->Set( Monster::MUTANT_ZOMBIE, 20 ); at( 2 )->Set( Monster::MUTANT_ZOMBIE, 20 ); at( 3 )->Set( Monster::MUTANT_ZOMBIE, 20 ); at( 4 )->Set( Monster::MUTANT_ZOMBIE, 20 ); break; case MP2::OBJ_SHIPWRECK: { uint32_t count = 0; switch ( getShipwreckCaptureCondition( tile ) ) { case Maps::ShipwreckCaptureCondition::EMPTY: // Shipwreck guardians were defeated. return; case Maps::ShipwreckCaptureCondition::FIGHT_10_GHOSTS_AND_GET_1000_GOLD: count = 10; break; case Maps::ShipwreckCaptureCondition::FIGHT_15_GHOSTS_AND_GET_2000_GOLD: count = 15; break; case Maps::ShipwreckCaptureCondition::FIGHT_25_GHOSTS_AND_GET_5000_GOLD: count = 25; break; case Maps::ShipwreckCaptureCondition::FIGHT_50_GHOSTS_AND_GET_2000_GOLD_WITH_ARTIFACT: count = 50; break; default: assert( 0 ); break; } ArrangeForBattle( Monster::GHOST, count, tile.GetIndex(), false ); break; } case MP2::OBJ_DERELICT_SHIP: ArrangeForBattle( Monster::SKELETON, 200, tile.GetIndex(), false ); break; case MP2::OBJ_ARTIFACT: switch ( getArtifactCaptureCondition( tile ) ) { case Maps::ArtifactCaptureCondition::FIGHT_50_ROGUES: ArrangeForBattle( Monster::ROGUE, 50, tile.GetIndex(), false ); break; case Maps::ArtifactCaptureCondition::FIGHT_1_GENIE: ArrangeForBattle( Monster::GENIE, 1, tile.GetIndex(), false ); break; case Maps::ArtifactCaptureCondition::FIGHT_1_PALADIN: ArrangeForBattle( Monster::PALADIN, 1, tile.GetIndex(), false ); break; case Maps::ArtifactCaptureCondition::FIGHT_1_CYCLOPS: ArrangeForBattle( Monster::CYCLOPS, 1, tile.GetIndex(), false ); break; case Maps::ArtifactCaptureCondition::FIGHT_1_PHOENIX: ArrangeForBattle( Monster::PHOENIX, 1, tile.GetIndex(), false ); break; case Maps::ArtifactCaptureCondition::FIGHT_1_GREEN_DRAGON: ArrangeForBattle( Monster::GREEN_DRAGON, 1, tile.GetIndex(), false ); break; case Maps::ArtifactCaptureCondition::FIGHT_1_TITAN: ArrangeForBattle( Monster::TITAN, 1, tile.GetIndex(), false ); break; case Maps::ArtifactCaptureCondition::FIGHT_1_BONE_DRAGON: ArrangeForBattle( Monster::BONE_DRAGON, 1, tile.GetIndex(), false ); break; default: break; } break; case MP2::OBJ_CITY_OF_DEAD: at( 0 )->Set( Monster::ZOMBIE, 20 ); at( 1 )->Set( Monster::VAMPIRE_LORD, 5 ); at( 2 )->Set( Monster::POWER_LICH, 5 ); at( 3 )->Set( Monster::VAMPIRE_LORD, 5 ); at( 4 )->Set( Monster::ZOMBIE, 20 ); break; case MP2::OBJ_TROLL_BRIDGE: at( 0 )->Set( Monster::TROLL, 4 ); at( 1 )->Set( Monster::WAR_TROLL, 4 ); at( 2 )->Set( Monster::TROLL, 4 ); at( 3 )->Set( Monster::WAR_TROLL, 4 ); at( 4 )->Set( Monster::TROLL, 4 ); break; case MP2::OBJ_DRAGON_CITY: { uint32_t monsterCount = 1; if ( Settings::Get().isCampaignGameType() ) { const Campaign::ScenarioVictoryCondition victoryCondition = Campaign::getCurrentScenarioVictoryCondition(); if ( victoryCondition == Campaign::ScenarioVictoryCondition::CAPTURE_DRAGON_CITY ) { monsterCount = 2; } } at( 0 )->Set( Monster::GREEN_DRAGON, monsterCount ); at( 1 )->Set( Monster::GREEN_DRAGON, monsterCount ); at( 2 )->Set( Monster::GREEN_DRAGON, monsterCount ); at( 3 )->Set( Monster::RED_DRAGON, monsterCount ); at( 4 )->Set( Monster::BLACK_DRAGON, monsterCount ); break; } case MP2::OBJ_DAEMON_CAVE: at( 0 )->Set( Monster::EARTH_ELEMENT, 2 ); at( 1 )->Set( Monster::EARTH_ELEMENT, 2 ); at( 2 )->Set( Monster::EARTH_ELEMENT, 2 ); at( 3 )->Set( Monster::EARTH_ELEMENT, 2 ); break; default: if ( isCaptureObject ) { const Troop & troop = world.GetCapturedObject( tile.GetIndex() ).GetTroop(); if ( troop.isValid() ) { ArrangeForBattle( troop.GetMonster(), troop.GetCount(), tile.GetIndex(), false ); } } else { const Troop troop = getTroopFromTile( tile ); if ( troop.isValid() ) { ArrangeForBattle( troop.GetMonster(), troop.GetCount(), tile.GetIndex(), true ); } } break; } } int Army::GetColor() const { const HeroBase * currentCommander = GetCommander(); return currentCommander != nullptr ? currentCommander->GetColor() : color; } int Army::GetLuck() const { const HeroBase * currentCommander = GetCommander(); return currentCommander != nullptr ? currentCommander->GetLuck() : GetLuckModificator( nullptr ); } int Army::GetLuckModificator( std::string * strs ) const { int result = Luck::NORMAL; // check castle modificator const Castle * castle = inCastle(); if ( castle ) { result += castle->GetLuckModificator( strs ); } return result; } int Army::GetMorale() const { const HeroBase * currentCommander = GetCommander(); return currentCommander != nullptr ? currentCommander->GetMorale() : GetMoraleModificator( nullptr ); } int Army::GetMoraleModificator( std::string * strs ) const { // different race penalty std::set races; bool hasUndead = false; for ( const Troop * troop : *this ) if ( troop->isValid() ) { races.insert( troop->GetRace() ); hasUndead = hasUndead || troop->isUndead(); } int result = Morale::NORMAL; // check castle modificator const Castle * castle = inCastle(); if ( castle ) { result += castle->GetMoraleModificator( strs ); } // artifact "Arm of the Martyr" adds the undead morale penalty hasUndead = hasUndead || ( GetCommander() && GetCommander()->GetBagArtifacts().isArtifactCursePresent( fheroes2::ArtifactCurseType::UNDEAD_MORALE_PENALTY ) ); const int count = static_cast( races.size() ); switch ( count ) { case 0: case 2: break; case 1: if ( !hasUndead && !AllTroopsAreTheSame() ) { // presence of undead discards "All %{race} troops +1" bonus ++result; if ( strs ) { std::string str = _( "All %{race} troops +1" ); StringReplace( str, "%{race}", *races.begin() == Race::NONE ? _( "NeutralRaceTroops|Neutral" ) : Race::String( *races.begin() ) ); strs->append( str ); *strs += '\n'; } } break; default: const int penalty = count - 2; result -= penalty; if ( strs ) { std::string str = _( "Troops of %{count} alignments -%{penalty}" ); StringReplace( str, "%{count}", count ); StringReplace( str, "%{penalty}", penalty ); strs->append( str ); *strs += '\n'; } break; } // undead in life group if ( hasUndead ) { result -= 1; if ( strs ) { strs->append( _( "Some undead in army -1" ) ); *strs += '\n'; } } return result; } double Army::GetStrength() const { double result = 0; const uint32_t heroArchery = ( commander != nullptr ) ? commander->GetSecondarySkillValue( Skill::Secondary::ARCHERY ) : 0; const int bonusAttack = ( commander ? commander->GetAttack() : 0 ); const int bonusDefense = ( commander ? commander->GetDefense() : 0 ); const int armyMorale = GetMorale(); const int armyLuck = GetLuck(); bool troopsExist = false; for ( const Troop * troop : *this ) { assert( troop != nullptr ); if ( troop->isEmpty() ) { continue; } troopsExist = true; double strength = troop->GetStrengthWithBonus( bonusAttack, bonusDefense ); if ( heroArchery > 0 && troop->isArchers() ) { strength *= sqrt( 1 + static_cast( heroArchery ) / 100 ); } if ( troop->isAffectedByMorale() ) { strength *= 1 + ( ( armyMorale < 0 ) ? armyMorale / 12.0 : armyMorale / 24.0 ); } strength *= 1 + armyLuck / 24.0; result += strength; } if ( commander != nullptr && troopsExist ) { result += commander->GetMagicStrategicValue( result ); } return result; } void Army::Reset( const bool defaultArmy /* = false */ ) { Troops::Clean(); if ( commander == nullptr || !commander->isHeroes() ) { return; } const int race = commander->GetRace(); // Sometimes heroes created solely for the purpose of showing an avatar may not have a race if ( race == Race::NONE ) { return; } if ( !defaultArmy ) { JoinTroop( { race, DWELLING_MONSTER1 }, 1, false ); return; } const auto joinMonsters = [this]( const Monster & monster ) { const auto [min, max] = getNumberOfMonstersInStartingArmy( monster ); if ( !JoinTroop( monster, Rand::Get( min, max ), false ) ) { assert( 0 ); } }; joinMonsters( { race, DWELLING_MONSTER1 } ); if ( Rand::Get( 1, 10 ) == 1 ) { return; } joinMonsters( { race, DWELLING_MONSTER2 } ); } HeroBase * Army::GetCommander() { return ( !commander || ( commander->isCaptain() && !commander->isValid() ) ) ? nullptr : commander; } const Castle * Army::inCastle() const { return commander ? commander->inCastle() : nullptr; } const HeroBase * Army::GetCommander() const { return ( !commander || ( commander->isCaptain() && !commander->isValid() ) ) ? nullptr : commander; } int Army::GetControl() const { return commander ? commander->GetControl() : ( color == Color::NONE ? CONTROL_AI : Players::GetPlayerControl( color ) ); } uint32_t Army::getTotalCount() const { return std::accumulate( begin(), end(), static_cast( 0 ), []( const uint32_t count, const Troop * troop ) { return troop->isValid() ? count + troop->GetCount() : count; } ); } std::string Army::String() const { std::ostringstream os; os << "color(" << Color::String( GetColor() ) << "), strength(" << GetStrength() << "), "; if ( const HeroBase * cmdr = GetCommander(); cmdr != nullptr ) { os << "commander(" << GetCommander()->GetName() << ")"; } else { os << "commander(None)"; } os << ": "; for ( const Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } os << std::dec << troop->GetCount() << " " << troop->GetName() << ", "; } return os.str(); } void Army::JoinStrongestFromArmy( Army & giver ) { const bool saveLast = ( giver.commander != nullptr ) && giver.commander->isHeroes(); JoinStrongest( giver, saveLast ); } void Army::MoveTroops( Army & from, const int monsterIdToKeep ) { assert( this != &from ); // Combine troops of the same type in one slot to leave more room for new troops to join MergeSameMonsterTroops(); // Heroes need to have at least one occupied slot in their army, while garrisons do not need this const bool fromHero = from.GetCommander() && from.GetCommander()->isHeroes(); #ifndef NDEBUG const bool toHero = GetCommander() && GetCommander()->isHeroes(); #endif assert( ( !fromHero || from.isValid() ) && ( !toHero || isValid() ) ); if ( monsterIdToKeep != Monster::UNKNOWN ) { // Find a troop stack in the destination stack set consisting of monsters we need to keep const auto keepIter = std::find_if( begin(), end(), [monsterIdToKeep]( const Troop * troop ) { assert( troop != nullptr ); return troop->isValid() && troop->GetID() == monsterIdToKeep; } ); // Find a troop stack in the source stack set consisting of monsters of a different type than the monster we need to keep const auto xchgIter = std::find_if( from.begin(), from.end(), [monsterIdToKeep]( const Troop * troop ) { assert( troop != nullptr ); return troop->isValid() && troop->GetID() != monsterIdToKeep; } ); // If we found both, then exchange the monster to keep in the destination stack set with the found troop stack in the // source stack set to concentrate all the monsters to keep in the source stack set if ( keepIter != end() && xchgIter != from.end() ) { Troop * keep = *keepIter; Troop * xchg = *xchgIter; const uint32_t count = keep->GetCount(); keep->Reset(); if ( !JoinTroop( *xchg ) ) { assert( 0 ); } xchg->Reset(); if ( !from.JoinTroop( Monster( monsterIdToKeep ), count, false ) ) { assert( 0 ); } } } const auto moveTroops = [this, &from, monsterIdToKeep, fromHero]( const bool ignoreMonstersToKeep ) { uint32_t stacksLeft = from.GetOccupiedSlotCount(); for ( Troop * troop : from ) { assert( troop != nullptr ); if ( troop->isEmpty() ) { continue; } if ( ignoreMonstersToKeep && troop->GetID() == monsterIdToKeep ) { continue; } if ( fromHero ) { // If the source stack set belongs to a hero and this is the last valid troop stack in it, // then try to join all but one monsters from this stack and then stop in any case if ( stacksLeft == 1 ) { if ( JoinTroop( troop->GetMonster(), troop->GetCount() - 1, false ) ) { troop->SetCount( 1 ); } break; } assert( stacksLeft > 1 ); } if ( JoinTroop( *troop ) ) { troop->Reset(); --stacksLeft; } } }; // First of all, try to move all the troop stacks except the stacks of monsters that we need to keep moveTroops( true ); // Then, try to move as much of monsters to keep as we can (except the last one, if we are moving them // from the stack set that belongs to a hero), if there is still a place for them moveTroops( false ); } void Army::SwapTroops( Army & from ) { assert( this != &from ); // Heroes need to have at least one occupied slot in their army, so both armies should have at least one // occupied slot, even if the exchange of armies takes place between a castle garrison and a hero. assert( from.isValid() && isValid() ); const Troops temp = this->getTroops(); Assign( from ); from.Assign( temp ); } uint32_t Army::ActionToSirens() const { uint32_t experience = 0; for ( Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } const uint32_t troopCount = troop->GetCount(); if ( troopCount == 1 ) { // Sirens do not affect 1 troop stack. continue; } // 30% of stack troops will be gone. uint32_t troopToRemove = troopCount * 3 / 10; if ( troopToRemove == 0 ) { // At least one unit must go, even if it's more than 30%. troopToRemove = 1; } troop->SetCount( troopCount - troopToRemove ); experience += troopToRemove * static_cast( troop )->GetHitPoints(); } return experience; } bool Army::isStrongerThan( const Army & target, double safetyRatio /* = 1.0 */ ) const { if ( !target.isValid() ) { return true; } const double armyStrength = Army::GetStrength(); const double targetStrength = target.GetStrength() * safetyRatio; DEBUG_LOG( DBG_GAME, DBG_TRACE, "Comparing troops: " << armyStrength << " versus " << targetStrength ) return armyStrength > targetStrength; } bool Army::isMeleeDominantArmy() const { double meleeInfantry = 0; double other = 0; for ( const Troop * troop : *this ) { if ( troop != nullptr && troop->isValid() ) { if ( !troop->isArchers() && !troop->isFlying() ) { meleeInfantry += troop->GetStrength(); } else { other += troop->GetStrength(); } } } return meleeInfantry > other; } void Army::drawSingleDetailedMonsterLine( const Troops & troops, int32_t cx, int32_t cy, int32_t width ) { fheroes2::drawMiniMonsters( troops, cx, cy, width, 0, 0, false, true, false, 0, fheroes2::Display::instance() ); } void Army::drawMultipleMonsterLines( const Troops & troops, int32_t posX, int32_t posY, int32_t lineWidth, bool isCompact, const bool isDetailedView, const bool isGarrisonView /* = false */, const uint32_t thievesGuildsCount /* = 0 */ ) { const uint32_t count = troops.GetOccupiedSlotCount(); const int offsetX = lineWidth / 6; const int offsetY = isCompact ? 31 : 49; fheroes2::Image & output = fheroes2::Display::instance(); if ( count < 3 ) { fheroes2::drawMiniMonsters( troops, posX + offsetX, posY + offsetY / 2 + 1, lineWidth * 2 / 3, 0, 0, isCompact, isDetailedView, isGarrisonView, thievesGuildsCount, output ); } else { const int firstLineTroopCount = 2; const int secondLineTroopCount = count - firstLineTroopCount; const int secondLineWidth = secondLineTroopCount == 2 ? lineWidth * 2 / 3 : lineWidth; fheroes2::drawMiniMonsters( troops, posX + offsetX, posY, lineWidth * 2 / 3, 0, firstLineTroopCount, isCompact, isDetailedView, isGarrisonView, thievesGuildsCount, output ); fheroes2::drawMiniMonsters( troops, posX, posY + offsetY, secondLineWidth, firstLineTroopCount, secondLineTroopCount, isCompact, isDetailedView, isGarrisonView, thievesGuildsCount, output ); } } NeutralMonsterJoiningCondition Army::GetJoinSolution( const Heroes & hero, const Maps::Tile & tile, const Troop & troop ) { if ( !troop.isValid() ) { assert( 0 ); return { NeutralMonsterJoiningCondition::Reason::None, 0, nullptr, nullptr }; } // Check for creature alliance/bane campaign awards, campaign only and of course, for human players // creature alliance -> if we have an alliance with the appropriate creature (inc. players) they will join for free // creature curse/bane -> same as above but all of them will flee even if you have just 1 peasant if ( Settings::Get().isCampaignGameType() && hero.isControlHuman() ) { const std::vector campaignAwards = Campaign::CampaignSaveData::Get().getObtainedCampaignAwards(); for ( size_t i = 0; i < campaignAwards.size(); ++i ) { const bool isAlliance = campaignAwards[i]._type == Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE; const bool isCurse = campaignAwards[i]._type == Campaign::CampaignAwardData::TYPE_CREATURE_CURSE; if ( !isAlliance && !isCurse ) { continue; } Monster monster( campaignAwards[i]._subType ); while ( true ) { if ( troop.GetID() == monster.GetID() ) { if ( isAlliance ) { return { NeutralMonsterJoiningCondition::Reason::Alliance, troop.GetCount(), Campaign::CampaignAwardData::getAllianceJoiningMessage( monster.GetID() ), Campaign::CampaignAwardData::getAllianceFleeingMessage( monster.GetID() ) }; } else { return { NeutralMonsterJoiningCondition::Reason::Bane, troop.GetCount(), nullptr, Campaign::CampaignAwardData::getBaneFleeingMessage( monster.GetID() ) }; } } // Also check the upgraded variant(s) of the same monster if ( !monster.isAllowUpgrade() ) { break; } monster = monster.GetUpgrade(); } } } // Neutral monsters don't care about hero's stats. Ignoring hero's stats makes hero's army strength be smaller in eyes of neutrals and they won't join so often. const double armyStrengthRatio = Troops( hero.GetArmy().getTroops() ).GetStrength() / troop.GetStrength(); const bool canJoin = [&hero, &tile, &troop, armyStrengthRatio]() { if ( armyStrengthRatio <= 2 ) { return false; } // The ability to accept monsters (a free slot or a stack of monsters of the same type) is a mandatory condition for their joining in accordance with the // mechanics of the original game if ( !hero.GetArmy().CanJoinTroop( troop ) ) { return false; } if ( hero.GetBagArtifacts().isArtifactCursePresent( fheroes2::ArtifactCurseType::NO_JOINING_ARMIES ) ) { return false; } return !Maps::isMonsterOnTileJoinConditionSkip( tile ); }(); if ( canJoin ) { if ( Maps::isMonsterOnTileJoinConditionFree( tile ) ) { return { NeutralMonsterJoiningCondition::Reason::Free, troop.GetCount(), nullptr, nullptr }; } if ( hero.HasSecondarySkill( Skill::Secondary::DIPLOMACY ) ) { const uint32_t amountToJoin = Monster::GetCountFromHitPoints( troop, troop.GetHitPoints() * hero.GetSecondarySkillValue( Skill::Secondary::DIPLOMACY ) / 100 ); // The ability to immediately hire the entire stack of monsters is a mandatory condition for their joining due to hero's Diplomacy skill in accordance with // the mechanics of the original game if ( amountToJoin > 0 && hero.GetKingdom().AllowPayment( Funds( Resource::GOLD, troop.GetTotalCost().gold ) ) ) { return { NeutralMonsterJoiningCondition::Reason::ForMoney, amountToJoin, nullptr, nullptr }; } } } if ( armyStrengthRatio > 5 && !hero.isControlAI() ) { // ... will surely flee before us return { NeutralMonsterJoiningCondition::Reason::RunAway, 0, nullptr, nullptr }; } return { NeutralMonsterJoiningCondition::Reason::None, 0, nullptr, nullptr }; } bool Army::WeakestTroop( const Troop * t1, const Troop * t2 ) { return t1->GetStrength() < t2->GetStrength(); } bool Army::StrongestTroop( const Troop * t1, const Troop * t2 ) { return t1->GetStrength() > t2->GetStrength(); } bool Army::SlowestTroop( const Troop * t1, const Troop * t2 ) { return t1->GetSpeed() < t2->GetSpeed(); } bool Army::FastestTroop( const Troop * t1, const Troop * t2 ) { return t1->GetSpeed() > t2->GetSpeed(); } void Army::SwapTroops( Troop & t1, Troop & t2 ) { std::swap( t1, t2 ); } bool Army::SaveLastTroop() const { return commander && commander->isHeroes() && 1 == GetOccupiedSlotCount(); } Monster Army::GetStrongestMonster() const { Monster monster( Monster::UNKNOWN ); for ( const Troop * troop : *this ) { if ( troop->isValid() && troop->GetMonster().GetMonsterStrength() > monster.GetMonsterStrength() ) { monster = troop->GetID(); } } return monster; } void Army::resetInvalidMonsters() const { for ( Troop * troop : *this ) { if ( troop->GetID() != Monster::UNKNOWN && !troop->isValid() ) { troop->Set( Monster::UNKNOWN, 0 ); } } } bool Army::ArrangeForCastleDefense( Army & garrison ) { assert( this != &garrison ); assert( size() == maximumTroopCount && garrison.size() == maximumTroopCount ); // This method is designed to reinforce only the armies of heroes assert( commander != nullptr && commander->isHeroes() ); // This method is designed to take reinforcements only from the garrison, because // it can leave the garrison empty assert( garrison.commander == nullptr || garrison.commander->isCaptain() ); bool result = false; // If the guest hero's army is controlled by AI, then try to squeeze as many garrison troops in as possible if ( isControlAI() ) { // Create and fill a temporary container for convenient sorting of garrison troops std::vector garrisonTroops; garrisonTroops.reserve( garrison.Size() ); for ( Troop * troop : garrison ) { assert( troop != nullptr ); if ( troop->isValid() ) { garrisonTroops.push_back( troop ); } } // Sort the garrison troops by their strength (most powerful stacks first) std::sort( garrisonTroops.begin(), garrisonTroops.end(), StrongestTroop ); // Try to reinforce the guest hero's army with garrison troops (most powerful stacks first) for ( Troop * troop : garrisonTroops ) { if ( JoinTroop( *troop ) ) { troop->Reset(); result = true; continue; } // If there is no space for another garrison stack, we will try to combine some existing stacks... if ( MergeSameMonsterOnce() ) { // ... and try again if ( JoinTroop( *troop ) ) { troop->Reset(); result = true; } else { assert( 0 ); } } } assert( size() == maximumTroopCount ); return result; } // Otherwise, try to move the garrison troops to exactly the same slots of the guest hero's army, provided // that these slots are empty for ( size_t i = 0; i < maximumTroopCount; ++i ) { Troop * troop = GetTroop( i ); Troop * garrisonTroop = garrison.GetTroop( i ); assert( troop != nullptr && garrisonTroop != nullptr ); if ( !garrisonTroop->isValid() ) { continue; } if ( troop->isValid() ) { continue; } troop->Set( garrisonTroop->GetMonster(), garrisonTroop->GetCount() ); garrisonTroop->Reset(); result = true; } return result; } void Army::ArrangeForWhirlpool() { // Make an "optimized" version first (each unit type occupies just one slot) const Troops optimizedTroops = GetOptimized(); assert( optimizedTroops.Size() > 0 && optimizedTroops.Size() <= maximumTroopCount ); // Already a full house, there is no room for further optimization if ( optimizedTroops.Size() == maximumTroopCount ) { return; } Assign( optimizedTroops ); // Look for a troop consisting of the weakest units Troop * troopOfWeakestUnits = nullptr; for ( Troop * troop : *this ) { assert( troop != nullptr ); if ( !troop->isValid() ) { continue; } if ( troopOfWeakestUnits == nullptr || troopOfWeakestUnits->GetMonsterStrength() > troop->GetMonsterStrength() ) { troopOfWeakestUnits = troop; } } assert( troopOfWeakestUnits != nullptr ); assert( troopOfWeakestUnits->GetCount() > 0 ); // There is already just one unit in this troop, let's leave it as it is if ( troopOfWeakestUnits->GetCount() == 1 ) { return; } // Move one unit from this troop's slot... troopOfWeakestUnits->SetCount( troopOfWeakestUnits->GetCount() - 1 ); // To the separate slot auto emptySlot = std::find_if( begin(), end(), []( const Troop * troop ) { return troop->isEmpty(); } ); assert( emptySlot != end() ); ( *emptySlot )->Set( Monster( troopOfWeakestUnits->GetID() ), 1 ); } void Army::ArrangeForBattle( const Monster & monster, const uint32_t monstersCount, const uint32_t stacksCount ) { assert( stacksCount > 0 && stacksCount <= size() && size() == maximumTroopCount ); assert( std::all_of( begin(), end(), []( const Troop * troop ) { return troop->isEmpty(); } ) ); size_t stacks; for ( stacks = stacksCount; stacks > 0; --stacks ) { if ( monstersCount / stacks > 0 ) { break; } } assert( stacks > 0 ); const uint32_t quotient = monstersCount / static_cast( stacks ); const uint32_t remainder = monstersCount % static_cast( stacks ); assert( quotient > 0 ); const size_t shift = ( size() - stacksCount ) / 2; for ( size_t i = 0; i < stacks; ++i ) { at( i + shift )->Set( monster, i < remainder ? quotient + 1 : quotient ); } assert( std::accumulate( begin(), end(), static_cast( 0 ), []( const uint32_t count, const Troop * troop ) { return troop->isValid() ? count + troop->GetCount() : count; } ) == monstersCount ); } void Army::ArrangeForBattle( const Monster & monster, const uint32_t monstersCount, const int32_t tileIndex, const bool allowUpgrade ) { uint32_t stacksCount = 0; // Archers should always be divided into as many stacks as possible if ( monster.isArchers() ) { stacksCount = maximumTroopCount; } else { std::mt19937 seededGen( world.GetMapSeed() + static_cast( tileIndex ) ); stacksCount = Rand::GetWithGen( 3, 5, seededGen ); } ArrangeForBattle( monster, monstersCount, stacksCount ); if ( allowUpgrade ) { assert( size() % 2 == 1 ); // An upgraded stack can be located only in the center Troop * troopToUpgrade = at( size() / 2 ); assert( troopToUpgrade != nullptr ); if ( troopToUpgrade->isValid() && troopToUpgrade->isAllowUpgrade() ) { std::mt19937 seededGen( world.GetMapSeed() + static_cast( tileIndex ) + static_cast( monster.GetID() ) ); // 50% chance to get an upgraded stack if ( Rand::GetWithGen( 0, 1, seededGen ) == 1 ) { troopToUpgrade->Upgrade(); } } } } OStreamBase & operator<<( OStreamBase & stream, const Army & army ) { stream.put32( static_cast( army.size() ) ); std::for_each( army.begin(), army.end(), [&stream]( const Troop * troop ) { assert( troop != nullptr ); stream << *troop; } ); return stream << army._isSpreadCombatFormation << army.color; } IStreamBase & operator>>( IStreamBase & stream, Army & army ) { if ( const uint32_t size = stream.get32(); army.size() != size ) { // Most likely the save file is corrupted. stream.setFail(); std::for_each( army.begin(), army.end(), []( Troop * troop ) { assert( troop != nullptr ); troop->Reset(); } ); } else { std::for_each( army.begin(), army.end(), [&stream]( Troop * troop ) { assert( troop != nullptr ); stream >> *troop; } ); } stream >> army._isSpreadCombatFormation >> army.color; assert( std::all_of( army.begin(), army.end(), [&army]( const Troop * troop ) { const ArmyTroop * armyTroop = dynamic_cast( troop ); return armyTroop != nullptr && armyTroop->GetArmy() == &army; } ) ); // Will be set later by the owner (castle or hero) army.commander = nullptr; return stream; } fheroes2-1.1.6+dfsg/src/fheroes2/army/army.h000066400000000000000000000242051476115357100205650ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "monster.h" #include "players.h" class IStreamBase; class OStreamBase; class Castle; class HeroBase; class Heroes; class Troop; namespace Maps { class Tile; } class Troops : protected std::vector { public: Troops() = default; Troops( const Troops & troops ); Troops( Troops && ) = default; virtual ~Troops(); Troops & operator=( const Troops & ) = delete; void Assign( const Troop * troopsBegin, const Troop * troopsEnd ); void Assign( const Troops & troops ); void Insert( const Troops & troops ); void PushBack( const Monster & mons, const uint32_t count ); void PopBack(); size_t Size() const { return size(); } Troop * GetTroop( size_t ); const Troop * GetTroop( size_t ) const; void UpgradeMonsters( const Monster & ); uint32_t GetCountMonsters( const Monster & mons ) const; double getReinforcementValue( const Troops & reinforcement ) const; uint32_t GetOccupiedSlotCount() const; bool isValid() const; bool HasMonster( const Monster & ) const; bool areAllTroopsUnique() const; bool AllTroopsAreUndead() const; // Returns true if all valid troops have the same ID or if there are no troops, otherwise returns false bool AllTroopsAreTheSame() const; bool JoinTroop( const Troop & troop ); bool JoinTroop( const Monster & mons, const uint32_t count, const bool emptySlotFirst ); bool CanJoinTroop( const Monster & ) const; virtual double GetStrength() const; uint32_t getTotalHP() const; void Clean(); void UpgradeTroops( const Castle & castle ) const; Troop * GetFirstValid() const; Troop * GetWeakestTroop() const; Troop * GetSlowestTroop() const; void SortStrongest(); void SplitTroopIntoFreeSlots( const Troop & troop, const Troop & selectedSlot, const uint32_t slots ); void AssignToFirstFreeSlot( const Troop & troopToAssign, const uint32_t count ) const; void JoinAllTroopsOfType( const Troop & targetTroop ) const; void addNewTroopsToFreeSlots( const Troop & troop, uint32_t maxSlots ); bool isFullHouse() const { return GetOccupiedSlotCount() == size(); } // If the army has no slot find 2 or more slots of the same monster which is the weakest and merge them releasing one slot in troops. bool mergeWeakestTroopsIfNeeded(); // Splits the stack consisting of the weakest units into free slots (if any), 1 monster per free slot void splitStackOfWeakestUnitsIntoFreeSlots(); // Combines all stacks consisting of identical monsters void MergeSameMonsterTroops(); protected: void JoinStrongest( Troops & giverArmy, const bool keepAtLeastOneSlotForGiver ); // Combines two stacks consisting of identical monsters. Returns true if there was something to combine, otherwise returns false. bool MergeSameMonsterOnce(); // Returns an optimized version of this Troops instance, i.e. all stacks of identical monsters are combined and there are no empty slots Troops GetOptimized() const; private: // Returns the stack that best matches the specified condition or nullptr if there are no valid stacks Troop * getBestMatchToCondition( const std::function & condition ) const; }; struct NeutralMonsterJoiningCondition { enum class Reason : int { None, Free, ForMoney, RunAway, Alliance, Bane }; Reason reason; uint32_t monsterCount; // These messages are used only for Alliance and Bane reasons. const char * joiningMessage; const char * fleeingMessage; }; class Army final : public Troops, public Control { public: static const size_t maximumTroopCount = 5; static std::string SizeString( uint32_t ); static std::string TroopSizeString( const Troop & ); // Comparison functions static bool WeakestTroop( const Troop *, const Troop * ); static bool StrongestTroop( const Troop *, const Troop * ); static bool SlowestTroop( const Troop *, const Troop * ); static bool FastestTroop( const Troop *, const Troop * ); static void SwapTroops( Troop &, Troop & ); static NeutralMonsterJoiningCondition GetJoinSolution( const Heroes & hero, const Maps::Tile & tile, const Troop & troop ); static void drawSingleDetailedMonsterLine( const Troops & troops, int32_t cx, int32_t cy, int32_t width ); static void drawMultipleMonsterLines( const Troops & troops, int32_t posX, int32_t posY, int32_t lineWidth, bool isCompact, const bool isDetailedView, const bool isGarrisonView = false, const uint32_t thievesGuildsCount = 0 ); explicit Army( HeroBase * cmdr = nullptr ); explicit Army( const Maps::Tile & tile ); Army( const Army & ) = delete; ~Army() override = default; Army & operator=( const Army & ) = delete; const Troops & getTroops() const; // Resets the army. If the army doesn't have a commanding hero, then it makes the army empty. Otherwise, if 'defaultArmy' is set to true, then it creates a default // army of the commanding hero's faction (several units of level 1 and 2). Otherwise, a minimum army is created, consisting of exactly one monster of the first level // of the commanding hero's faction. void Reset( const bool defaultArmy = false ); void setFromTile( const Maps::Tile & tile ); int GetColor() const; int GetControl() const override; uint32_t getTotalCount() const; double GetStrength() const override; bool isStrongerThan( const Army & target, const double safetyRatio = 1.0 ) const; bool isMeleeDominantArmy() const; void SetColor( int cl ) { color = cl; } int GetMorale() const; int GetLuck() const; int GetMoraleModificator( std::string * strs ) const; int GetLuckModificator( std::string * strs ) const; uint32_t ActionToSirens() const; const HeroBase * GetCommander() const; HeroBase * GetCommander(); void SetCommander( HeroBase * c ) { commander = c; } const Castle * inCastle() const; std::string String() const; void JoinStrongestFromArmy( Army & giver ); // Implements the necessary logic to move unit stacks from army to army in the heroes meeting dialog and in the castle dialog void MoveTroops( Army & from, const int monsterIdToKeep ); // Implements the necessary logic to swap all unit stacks from an army to another army in the heroes meeting dialog and in the // castle dialog - provided that there is at least one occupied slot in the castle garrison. It's the caller's responsibility // to ensure that this is indeed the case. void SwapTroops( Army & from ); void SetSpreadFormation( const bool spread ) { _isSpreadCombatFormation = spread; } bool isSpreadFormation() const { return _isSpreadCombatFormation; } bool SaveLastTroop() const; Monster GetStrongestMonster() const; void resetInvalidMonsters() const; // Performs the pre-battle arrangement for the castle (or town) defense, trying to add reinforcements from the garrison. Returns // true if at least one unit from the garrison was moved to the army as reinforcements, otherwise returns false. The logic of // combining troops for the castle defense differs from the original game, see the implementation for details. bool ArrangeForCastleDefense( Army & garrison ); // Optimizes the arrangement of troops to pass through the whirlpool (moves one weakest unit to a separate slot, if possible) void ArrangeForWhirlpool(); private: friend OStreamBase & operator<<( OStreamBase & stream, const Army & army ); friend IStreamBase & operator>>( IStreamBase & stream, Army & army ); // Performs the pre-battle arrangement of given monsters in a given number, dividing them into a given number of stacks if possible void ArrangeForBattle( const Monster & monster, const uint32_t monstersCount, const uint32_t stacksCount ); // Performs the pre-battle arrangement of given monsters in a given number, dividing them into a random number of stacks (seeded by // the tile index) with a random chance to get an upgraded stack of monsters in the center (if allowed) void ArrangeForBattle( const Monster & monster, const uint32_t monstersCount, const int32_t tileIndex, const bool allowUpgrade ); HeroBase * commander; bool _isSpreadCombatFormation; int color; }; fheroes2-1.1.6+dfsg/src/fheroes2/army/army_bar.cpp000066400000000000000000000620311476115357100217430ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "army_bar.h" #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "army_troop.h" #include "castle.h" #include "dialog.h" #include "dialog_selectitems.h" #include "game_hotkeys.h" #include "heroes_base.h" #include "icn.h" #include "kingdom.h" #include "localevent.h" #include "monster.h" #include "pal.h" #include "race.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "ui_monster.h" #include "ui_text.h" #include "world.h" namespace { void RedistributeArmy( ArmyTroop & troopFrom, ArmyTroop & troopTarget, Army * armyTarget ) { const Army * armyFrom = troopFrom.GetArmy(); const bool saveLastTroop = armyFrom->SaveLastTroop() && armyFrom != armyTarget; const bool isSameTroopType = troopTarget.isValid() && troopFrom.GetID() == troopTarget.GetID(); const uint32_t overallCount = isSameTroopType ? troopFrom.GetCount() + troopTarget.GetCount() : troopFrom.GetCount(); assert( overallCount > 0 ); if ( overallCount == 1 ) { // Prevent units from moving between armies if this would result in no units remaining in the hero's army if ( saveLastTroop ) { return; } // It seems that we are just moving a single unit to an empty slot assert( !troopTarget.isValid() ); Army::SwapTroops( troopFrom, troopTarget ); } else if ( !troopTarget.isValid() && troopFrom.GetCount() == 2 ) { // Player splits a slot with two monsters into an empty slot; move one monster from the source slot to the target slot troopFrom.SetCount( 1 ); troopTarget.Set( troopFrom.GetMonster(), 1 ); } else if ( isSameTroopType && troopFrom.isValid() && troopFrom.GetCount() == 1 && troopTarget.isValid() && troopTarget.GetCount() == 1 ) { // Prevent units from moving between armies if this would result in no units remaining in the hero's army if ( saveLastTroop ) { return; } // Player splits a slot with just one monster into a slot with just one monster of the same type; add a monster from the source slot to the target slot troopFrom.Reset(); troopTarget.SetCount( 2 ); } else { int32_t freeSlots = static_cast( 1 + armyTarget->Size() - armyTarget->GetOccupiedSlotCount() ); if ( isSameTroopType ) { ++freeSlots; } const int32_t maxCount = static_cast( saveLastTroop ? troopFrom.GetCount() - 1 : troopFrom.GetCount() ); int32_t redistributeCount = isSameTroopType ? std::min( 1, maxCount ) : static_cast( troopFrom.GetCount() ) / 2; bool useFastSplit = !isSameTroopType; const int32_t slots = Dialog::ArmySplitTroop( ( freeSlots > static_cast( overallCount ) ? static_cast( overallCount ) : freeSlots ), maxCount, redistributeCount, useFastSplit, troopFrom.GetName() ); if ( slots < 2 || slots > 6 ) { return; } uint32_t totalSplitTroopCount = troopFrom.GetCount(); if ( !useFastSplit && slots == 2 ) { // This logic is used when splitting to a stack with the same unit if ( isSameTroopType ) { troopTarget.SetCount( troopTarget.GetCount() + static_cast( redistributeCount ) ); } else { troopTarget.Set( troopFrom, static_cast( redistributeCount ) ); } troopFrom.SetCount( totalSplitTroopCount - static_cast( redistributeCount ) ); } else { if ( isSameTroopType ) { totalSplitTroopCount += troopTarget.GetCount(); } const uint32_t troopFromSplitCount = ( totalSplitTroopCount + slots - 1 ) / slots; troopFrom.SetCount( troopFromSplitCount ); const uint32_t troopTargetSplitCount = ( totalSplitTroopCount + slots - 2 ) / slots; if ( !isSameTroopType ) { troopTarget.SetMonster( troopFrom.GetID() ); } troopTarget.SetCount( troopTargetSplitCount ); totalSplitTroopCount -= troopFromSplitCount; totalSplitTroopCount -= troopTargetSplitCount; if ( slots > 2 ) { armyTarget->SplitTroopIntoFreeSlots( Troop( troopFrom, totalSplitTroopCount ), troopTarget, slots - 2 ); } } } } void RedistributeTroopToFirstFreeSlot( ArmyTroop & troopFrom, const Army * armyTarget, const uint32_t count ) { // can't split up a stack with just 1 unit, and obviously on count == 0, there's no splitting at all if ( troopFrom.GetCount() <= 1 || count == 0 ) return; const size_t freeSlots = armyTarget->Size() - armyTarget->GetOccupiedSlotCount(); if ( freeSlots == 0 ) return; armyTarget->AssignToFirstFreeSlot( troopFrom, count ); troopFrom.SetCount( troopFrom.GetCount() - count ); } void RedistributeTroopByOne( ArmyTroop & troopFrom, const Army * armyTarget ) { RedistributeTroopToFirstFreeSlot( troopFrom, armyTarget, 1 ); } void RedistributeTroopEvenly( ArmyTroop & troopFrom, const Army * armyTarget ) { RedistributeTroopToFirstFreeSlot( troopFrom, armyTarget, troopFrom.GetCount() / 2 ); } bool IsSplitHotkeyUsed( ArmyTroop & troopFrom, const Army * armyTarget ) { if ( Game::HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SPLIT_STACK_BY_ONE ) ) { RedistributeTroopByOne( troopFrom, armyTarget ); return true; } if ( Game::HotKeyHoldEvent( Game::HotKeyEvent::ARMY_JOIN_STACKS ) ) { armyTarget->JoinAllTroopsOfType( troopFrom ); return true; } if ( Game::HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SPLIT_STACK_BY_HALF ) ) { RedistributeTroopEvenly( troopFrom, armyTarget ); return true; } return false; } } ArmyBar::ArmyBar( Army * ptr, const bool miniSprites, const bool readOnly, const bool isEditMode /* false */, const bool saveLastTroop /* true */ ) : spcursor( fheroes2::AGG::GetICN( ICN::STRIP, 1 ) ) , use_mini_sprite( miniSprites ) , read_only( readOnly ) , can_change( isEditMode ) , _saveLastTroop( saveLastTroop ) { if ( use_mini_sprite ) SetBackground( { 43, 43 }, fheroes2::GetColorId( 0, 45, 0 ) ); else { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::STRIP, 2 ); setSingleItemSize( { sprite.width(), sprite.height() } ); } SetArmy( ptr ); } void ArmyBar::SetArmy( Army * ptr ) { if ( _army && isSelected() ) ResetSelected(); _army = ptr; items.clear(); if ( ptr ) { for ( uint32_t ii = 0; ii < ptr->Size(); ++ii ) { ArmyTroop * troop = dynamic_cast( ptr->GetTroop( ii ) ); assert( troop != nullptr ); items.push_back( troop ); } } SetContentItems(); } bool ArmyBar::isValid() const { return _army != nullptr; } void ArmyBar::SetBackground( const fheroes2::Size & sz, const uint8_t fillColor ) { if ( !use_mini_sprite ) { // Nothing to draw. return; } setSingleItemSize( sz ); backsf._disableTransformLayer(); backsf.resize( sz.width, sz.height ); backsf.fill( fillColor ); fheroes2::DrawBorder( backsf, fheroes2::GetColorId( 0xd0, 0xc0, 0x48 ) ); spcursor.resize( sz.width, sz.height ); spcursor.reset(); fheroes2::DrawBorder( spcursor, 214 ); } void ArmyBar::RedrawBackground( const fheroes2::Rect & pos, fheroes2::Image & dstsf ) { if ( use_mini_sprite ) { fheroes2::Copy( backsf, 0, 0, dstsf, pos ); } else { if ( can_change && !_saveLastTroop && _army->GetOccupiedSlotCount() == 0 ) { // If none of army's slot is set within the Editor, then a default army will be applied at the game start. fheroes2::ApplyPalette( fheroes2::AGG::GetICN( ICN::STRIP, 2 ), 0, 0, dstsf, pos.x, pos.y, pos.width, pos.height, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); const fheroes2::Text text( _( "Default\ntroop" ), fheroes2::FontType::normalWhite() ); text.drawInRoi( pos.x, pos.y + pos.height / 2 - 17, pos.width, dstsf, pos ); } else { fheroes2::Copy( fheroes2::AGG::GetICN( ICN::STRIP, 2 ), 0, 0, dstsf, pos ); } } } void ArmyBar::RedrawItem( ArmyTroop & troop, const fheroes2::Rect & pos, bool selected, fheroes2::Image & dstsf ) { if ( !troop.isValid() ) { // Nothing to draw. return; } const fheroes2::Text text( std::to_string( troop.GetCount() ), use_mini_sprite ? fheroes2::FontType::smallWhite() : fheroes2::FontType::normalWhite() ); if ( use_mini_sprite ) { const fheroes2::Sprite & mons32 = fheroes2::AGG::GetICN( ICN::MONS32, troop.GetSpriteIndex() ); fheroes2::Rect srcrt( 0, 0, mons32.width(), mons32.height() ); if ( mons32.width() > pos.width ) { srcrt.x = ( mons32.width() - pos.width ) / 2; srcrt.width = pos.width; } if ( mons32.height() > pos.height ) { srcrt.y = ( mons32.height() - pos.height ) / 2; srcrt.height = pos.height; } fheroes2::Blit( mons32, srcrt.x, srcrt.y, dstsf, pos.x + ( pos.width - mons32.width() ) / 2, pos.y + pos.height - mons32.height() - 1, srcrt.width, srcrt.height ); text.draw( pos.x + pos.width - text.width() - 3, pos.y + pos.height - text.height() + 2, dstsf ); } else { fheroes2::renderMonsterFrame( troop, dstsf, pos.getPosition() ); text.draw( pos.x + pos.width - text.width() - 3, pos.y + pos.height - text.height() + 1, dstsf ); } if ( selected ) { spcursor.setPosition( pos.x, pos.y ); spcursor.show(); } } void ArmyBar::ResetSelected() { spcursor.hide(); Interface::ItemsActionBar::ResetSelected(); } void ArmyBar::Redraw( fheroes2::Image & dstsf ) { spcursor.hide(); Interface::ItemsActionBar::Redraw( dstsf ); } bool ArmyBar::ActionBarCursor( ArmyTroop & troop ) { if ( troop.isValid() && !read_only && LocalEvent::Get().MouseClickMiddle() ) { RedistributeTroopByOne( troop, _army ); return true; } if ( isSelected() ) { const ArmyTroop * troop2 = GetSelectedItem(); assert( troop2 != nullptr ); if ( &troop == troop2 ) { msg = _( "View %{name}" ); StringReplaceWithLowercase( msg, "%{name}", troop.GetName() ); } else if ( !troop.isValid() ) { if ( !read_only ) { if ( troop2->GetCount() == 1 ) { msg = _( "Move the %{name} " ); } else { msg = _( "Move or right click to redistribute %{name}" ); } StringReplaceWithLowercase( msg, "%{name}", troop2->GetName() ); } } else if ( troop.GetID() == troop2->GetID() ) { if ( !read_only ) { msg = _( "Combine %{name} armies" ); StringReplaceWithLowercase( msg, "%{name}", troop.GetName() ); } } else if ( !read_only ) { msg = _( "Exchange %{name2} with %{name}" ); StringReplaceWithLowercase( msg, "%{name}", troop.GetName() ); StringReplaceWithLowercase( msg, "%{name2}", troop2->GetName() ); } } else if ( troop.isValid() ) { msg = _( "Select %{name}" ); StringReplaceWithLowercase( msg, "%{name}", troop.GetName() ); } return false; } bool ArmyBar::ActionBarCursor( ArmyTroop & destTroop, ArmyTroop & selectedTroop ) { const bool saveLastTroop = _saveLastTroop && ( selectedTroop.GetArmy()->getTotalCount() <= 1 ) && selectedTroop.GetArmy()->SaveLastTroop(); if ( destTroop.isValid() ) { if ( destTroop.GetID() != selectedTroop.GetID() ) { msg = _( "Exchange %{name2} with %{name}" ); StringReplaceWithLowercase( msg, "%{name}", destTroop.GetName() ); StringReplaceWithLowercase( msg, "%{name2}", selectedTroop.GetName() ); } else if ( saveLastTroop ) { msg = _( "Cannot move last troop" ); } else { msg = _( "Combine %{name} armies" ); StringReplaceWithLowercase( msg, "%{name}", destTroop.GetName() ); } } else if ( saveLastTroop ) { msg = _( "Cannot move last troop" ); } else { if ( selectedTroop.GetCount() == 1 ) { msg = _( "Move the %{name}" ); } else { msg = _( "Move or right click to redistribute %{name}" ); } StringReplaceWithLowercase( msg, "%{name}", selectedTroop.GetName() ); } return false; } bool ArmyBar::ActionBarLeftMouseSingleClick( ArmyTroop & troop ) { if ( isSelected() ) { if ( read_only ) { return false; // reset cursor } ArmyTroop * selectedTroop = GetSelectedItem(); assert( selectedTroop != nullptr ); const bool isSameTroopType = troop.isValid() && troop.GetID() == selectedTroop->GetID(); // prioritize standard split via shift hotkey if ( ( !troop.isValid() || isSameTroopType ) && Game::HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SPLIT_STACK_BY_HALF ) ) { RedistributeArmy( *selectedTroop, troop, _army ); ResetSelected(); } else if ( selectedTroop && isSameTroopType ) { if ( IsSplitHotkeyUsed( troop, _army ) ) { return false; } else { // combine troop.SetCount( troop.GetCount() + selectedTroop->GetCount() ); selectedTroop->Reset(); } } // exchange else if ( selectedTroop ) { // count this as an attempt to split to a troop type that is not the same if ( Game::HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SPLIT_STACK_BY_HALF ) ) ResetSelected(); else if ( IsSplitHotkeyUsed( troop, _army ) ) return false; else Army::SwapTroops( troop, *selectedTroop ); } return false; // reset cursor } else if ( troop.isValid() ) { if ( !read_only ) // select { if ( IsSplitHotkeyUsed( troop, _army ) ) return false; spcursor.hide(); } } else { if ( can_change ) // add troop { int cur = Monster::UNKNOWN; if ( _army->GetCommander() ) switch ( _army->GetCommander()->GetRace() ) { case Race::KNGT: cur = Monster::PEASANT; break; case Race::BARB: cur = Monster::GOBLIN; break; case Race::SORC: cur = Monster::SPRITE; break; case Race::WRLK: cur = Monster::CENTAUR; break; case Race::WZRD: cur = Monster::HALFLING; break; case Race::NECR: cur = Monster::SKELETON; break; default: break; } const Monster mons = Dialog::selectMonster( cur ); if ( mons.isValid() ) { std::string str = _( "Set %{monster} Count" ); StringReplace( str, "%{monster}", mons.GetName() ); int32_t count = 1; const fheroes2::MonsterDialogElement monsUi{ mons }; if ( Dialog::SelectCount( std::move( str ), 1, 500000, count, 1, &monsUi ) ) { troop.Set( mons, static_cast( count ) ); } } } return false; } return true; } bool ArmyBar::ActionBarLeftMouseSingleClick( ArmyTroop & destTroop, ArmyTroop & selectedTroop ) { const bool isSameTroopType = destTroop.isValid() && destTroop.GetID() == selectedTroop.GetID(); // specifically for shift hotkey, handle this logic before anything else // this will ensure that clicking on a different troop type while shift key is pressed will not show the split dialog, which can be ambiguous if ( Game::HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SPLIT_STACK_BY_HALF ) ) { if ( destTroop.isEmpty() || isSameTroopType ) { RedistributeArmy( selectedTroop, destTroop, _army ); ResetSelected(); } return false; } if ( !destTroop.isEmpty() ) { // try to do hotkey-based splitting (except for shift, handled above) if ( IsSplitHotkeyUsed( destTroop, _army ) ) return false; if ( !isSameTroopType ) { Army::SwapTroops( destTroop, selectedTroop ); } // destination troop has units and both troops are the same creature type else { if ( _saveLastTroop && selectedTroop.GetArmy()->SaveLastTroop() ) { // this is their army's only troop // move all but one units to destination destTroop.SetCount( destTroop.GetCount() + selectedTroop.GetCount() - 1 ); // leave a single unit behind selectedTroop.SetCount( 1 ); } else { // source has other troops // move all troops to the destination slot destTroop.SetCount( destTroop.GetCount() + selectedTroop.GetCount() ); // empty the source slot selectedTroop.Reset(); } } } else { // destination troop is empty, source army would be emptied by moving all if ( _saveLastTroop && selectedTroop.GetArmy()->SaveLastTroop() ) { // move all but one units into the empty destination slot destTroop.Set( selectedTroop, selectedTroop.GetCount() - 1 ); selectedTroop.SetCount( 1 ); } // no risk of emptying selected troop's army, swap the troops else { Army::SwapTroops( destTroop, selectedTroop ); } } return false; // reset cursor } bool ArmyBar::ActionBarLeftMouseDoubleClick( ArmyTroop & troop ) { if ( troop.isValid() && !read_only && IsSplitHotkeyUsed( troop, _army ) ) { ResetSelected(); return true; } const ArmyTroop * troop2 = GetSelectedItem(); assert( troop2 != nullptr ); if ( &troop == troop2 ) { int flags = Dialog::BUTTONS; if ( !read_only ) { if ( !_saveLastTroop || !_army->SaveLastTroop() ) { flags |= Dialog::DISMISS; } if ( troop.isAllowUpgrade() ) { const Castle * castle = _army->inCastle(); if ( castle && castle->GetRace() == troop.GetRace() && castle->isBuild( troop.GetUpgrade().GetDwelling() ) ) { flags |= Dialog::UPGRADE; if ( !world.GetKingdom( _army->GetColor() ).AllowPayment( troop.GetTotalUpgradeCost() ) ) { flags |= Dialog::UPGRADE_DISABLE; } } } } switch ( Dialog::ArmyInfo( troop, flags, false, _troopWindowOffsetY ) ) { case Dialog::UPGRADE: // If this assertion blows up then you are executing this code for a monster which has no upgrades. assert( troop.isAllowUpgrade() ); world.GetKingdom( _army->GetColor() ).OddFundsResource( troop.GetTotalUpgradeCost() ); troop.Upgrade(); break; case Dialog::DISMISS: troop.Reset(); break; default: break; } } ResetSelected(); return true; } bool ArmyBar::ActionBarLeftMouseRelease( ArmyTroop & troop ) { if ( read_only ) { return true; } ArmyTroop * srcTroop = GetItem( LocalEvent::Get().getMouseLeftButtonPressedPos() ); if ( srcTroop == nullptr || !srcTroop->isValid() ) { return true; } if ( &troop == srcTroop ) { return true; } if ( troop.isValid() && troop.GetID() != srcTroop->GetID() ) { return true; } RedistributeArmy( *srcTroop, troop, _army ); if ( isSelected() ) { ResetSelected(); } return true; } bool ArmyBar::ActionBarLeftMouseRelease( ArmyTroop & destTroop, ArmyTroop & selectedTroop ) { assert( !read_only ); if ( isSelected() ) { ResetSelected(); } if ( !selectedTroop.isValid() ) { return false; } if ( destTroop.isValid() && selectedTroop.GetID() != destTroop.GetID() ) { return false; } assert( &selectedTroop != &destTroop ); RedistributeArmy( selectedTroop, destTroop, _army ); return true; } bool ArmyBar::ActionBarRightMouseHold( ArmyTroop & troop ) { // don't handle this event if we are going to call RedistributeArmy() on right mouse button click if ( AbleToRedistributeArmyOnRightMouseSingleClick( troop ) ) { return false; } if ( troop.isValid() ) { ResetSelected(); if ( can_change && ( !_saveLastTroop || !_army->SaveLastTroop() ) ) { troop.Reset(); } else { Dialog::ArmyInfo( troop, Dialog::ZERO, false, _troopWindowOffsetY ); } } return true; } bool ArmyBar::ActionBarRightMouseSingleClick( ArmyTroop & troop ) { if ( AbleToRedistributeArmyOnRightMouseSingleClick( troop ) ) { ArmyTroop * selectedTroop = GetSelectedItem(); assert( selectedTroop != nullptr ); RedistributeArmy( *selectedTroop, troop, _army ); ResetSelected(); return true; } return false; } bool ArmyBar::ActionBarRightMouseSingleClick( ArmyTroop & destTroop, ArmyTroop & selectedTroop ) { if ( !destTroop.isValid() || destTroop.GetID() == selectedTroop.GetID() ) { RedistributeArmy( selectedTroop, destTroop, _army ); ResetSelected(); } return true; } bool ArmyBar::QueueEventProcessing( std::string * str ) { msg.clear(); bool res = Interface::ItemsActionBar::QueueEventProcessing(); if ( str ) *str = msg; return res; } bool ArmyBar::QueueEventProcessing( ArmyBar & bar, std::string * str ) { msg.clear(); bool res = Interface::ItemsActionBar::QueueEventProcessing( bar ); if ( str ) *str = msg; return res; } bool ArmyBar::AbleToRedistributeArmyOnRightMouseSingleClick( const ArmyTroop & troop ) { if ( read_only ) { return false; } // try to redistribute troops if we have a selected troop if ( !isSelected() ) { return false; } const ArmyTroop * selectedTroop = GetSelectedItem(); assert( selectedTroop != nullptr ); // prevent troop from splitting into its own stack by checking against their pointers if ( &troop == selectedTroop ) { return false; } // we can redistribute troops either to an empty slot or to a slot containing the same creatures return !troop.isValid() || selectedTroop->GetID() == troop.GetID(); } fheroes2-1.1.6+dfsg/src/fheroes2/army/army_bar.h000066400000000000000000000075531476115357100214200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "image.h" #include "interface_itemsbar.h" #include "math_base.h" #include "ui_tool.h" class Army; class ArmyTroop; class ArmyBar : public Interface::ItemsActionBar { public: using Interface::ItemsActionBar::RedrawItem; using Interface::ItemsActionBar::ActionBarRightMouseHold; ArmyBar( Army *, const bool miniSprites, const bool readOnly, const bool isEditMode = false, const bool saveLastTroop = true ); void RedrawBackground( const fheroes2::Rect &, fheroes2::Image & ) override; void RedrawItem( ArmyTroop &, const fheroes2::Rect &, bool, fheroes2::Image & ) override; void SetBackground( const fheroes2::Size & sz, const uint8_t fillColor ); void SetArmy( Army * ); void setTroopWindowOffsetY( const int32_t offsetY ) { _troopWindowOffsetY = offsetY; } bool isValid() const; void ResetSelected(); void Redraw( fheroes2::Image & dstsf ); bool ActionBarLeftMouseSingleClick( ArmyTroop & troop ) override; bool ActionBarLeftMouseSingleClick( ArmyTroop & destTroop, ArmyTroop & selectedTroop ) override; bool ActionBarLeftMouseDoubleClick( ArmyTroop & troop ) override; bool ActionBarLeftMouseRelease( ArmyTroop & troop ) override; bool ActionBarLeftMouseRelease( ArmyTroop & destTroop, ArmyTroop & troop ) override; bool ActionBarRightMouseHold( ArmyTroop & troop ) override; bool ActionBarRightMouseSingleClick( ArmyTroop & troop ) override; bool ActionBarRightMouseSingleClick( ArmyTroop & destTroop, ArmyTroop & selectedTroop ) override; bool ActionBarCursor( ArmyTroop & ) override; bool ActionBarCursor( ArmyTroop &, ArmyTroop & ) override; bool QueueEventProcessing( std::string * = nullptr ); bool QueueEventProcessing( ArmyBar &, std::string * = nullptr ); protected: fheroes2::MovableSprite spcursor; private: bool AbleToRedistributeArmyOnRightMouseSingleClick( const ArmyTroop & troop ); Army * _army{ nullptr }; fheroes2::Image backsf; bool use_mini_sprite; bool read_only; bool can_change{ false }; bool _saveLastTroop{ true }; std::string msg; int32_t _troopWindowOffsetY{ 0 }; }; fheroes2-1.1.6+dfsg/src/fheroes2/army/army_troop.cpp000066400000000000000000000145601476115357100223460ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "army_troop.h" #include #include "army.h" #include "color.h" #include "heroes_base.h" #include "resource.h" #include "serialize.h" #include "speed.h" Troop::Troop() : Monster( Monster::UNKNOWN ) , _count( 0 ) {} Troop::Troop( const Monster & mons, const uint32_t count ) : Monster( mons ) , _count( count ) {} bool Troop::operator==( const Monster & mons ) const { return Monster::operator==( mons ); } bool Troop::isMonster( const int mons ) const { return GetID() == mons; } Monster Troop::GetMonster() const { return Monster( id ); } void Troop::Set( const Troop & troop ) { SetMonster( troop.GetMonster() ); SetCount( troop.GetCount() ); } void Troop::Set( const Monster & mons, const uint32_t count ) { Set( Troop( mons, count ) ); } void Troop::SetMonster( const Monster & mons ) { id = mons.GetID(); } void Troop::SetCount( const uint32_t count ) { _count = count; } void Troop::Reset() { id = Monster::UNKNOWN; _count = 0; } const char * Troop::GetName() const { return Monster::GetPluralName( _count ); } uint32_t Troop::GetCount() const { return _count; } uint32_t Troop::GetHitPoints() const { return Monster::GetHitPoints() * _count; } uint32_t Troop::GetDamageMin() const { return Monster::GetDamageMin() * _count; } uint32_t Troop::GetDamageMax() const { return Monster::GetDamageMax() * _count; } double Troop::GetStrength() const { return Monster::GetMonsterStrength() * _count; } double Troop::GetStrengthWithBonus( const int bonusAttack, const int bonusDefense ) const { assert( bonusAttack >= 0 && bonusDefense >= 0 ); return Monster::GetMonsterStrength( Monster::GetAttack() + bonusAttack, Monster::GetDefense() + bonusDefense ) * _count; } bool Troop::isValid() const { return Monster::isValid() && _count; } bool Troop::isEmpty() const { return !isValid(); } Funds Troop::GetTotalCost() const { return GetCost() * _count; } Funds Troop::GetTotalUpgradeCost() const { return GetUpgradeCost() * _count; } bool Troop::isBattle() const { return false; } bool Troop::isModes( uint32_t /* unused */ ) const { return false; } std::string Troop::GetAttackString() const { return std::to_string( GetAttack() ); } std::string Troop::GetDefenseString() const { return std::to_string( GetDefense() ); } std::string Troop::GetShotString() const { return std::to_string( GetShots() ); } std::string Troop::GetSpeedString() const { return GetSpeedString( GetSpeed() ); } std::string Troop::GetSpeedString( const uint32_t speed ) { std::string output( Speed::String( static_cast( speed ) ) ); output += " ("; output += std::to_string( speed ); output += ')'; return output; } uint32_t Troop::GetHitPointsLeft() const { return 0; } uint32_t Troop::GetSpeed() const { return Monster::GetSpeed(); } uint32_t Troop::GetAffectedDuration( uint32_t /* unused */ ) const { return 0; } ArmyTroop::ArmyTroop( const Army * army ) : _army( army ) {} ArmyTroop::ArmyTroop( const Army * army, const Troop & troop ) : Troop( troop ) , _army( army ) {} uint32_t ArmyTroop::GetAttack() const { return Troop::GetAttack() + ( _army && _army->GetCommander() ? _army->GetCommander()->GetAttack() : 0 ); } uint32_t ArmyTroop::GetDefense() const { return Troop::GetDefense() + ( _army && _army->GetCommander() ? _army->GetCommander()->GetDefense() : 0 ); } int ArmyTroop::GetColor() const { return _army ? _army->GetColor() : Color::NONE; } int ArmyTroop::GetMorale() const { return _army && isAffectedByMorale() ? _army->GetMorale() : Troop::GetMorale(); } int ArmyTroop::GetLuck() const { return _army ? _army->GetLuck() : Troop::GetLuck(); } void ArmyTroop::SetArmy( const Army & army ) { _army = &army; } const Army * ArmyTroop::GetArmy() const { return _army; } std::string ArmyTroop::GetAttackString() const { if ( Troop::GetAttack() == GetAttack() ) { return std::to_string( Troop::GetAttack() ); } std::string output( std::to_string( Troop::GetAttack() ) ); output += " ("; output += std::to_string( GetAttack() ); output += ')'; return output; } std::string ArmyTroop::GetDefenseString() const { if ( Troop::GetDefense() == GetDefense() ) { return std::to_string( Troop::GetDefense() ); } std::string output( std::to_string( Troop::GetDefense() ) ); output += " ("; output += std::to_string( GetDefense() ); output += ')'; return output; } OStreamBase & operator<<( OStreamBase & stream, const Troop & troop ) { return stream << troop.id << troop._count; } IStreamBase & operator>>( IStreamBase & stream, Troop & troop ) { return stream >> troop.id >> troop._count; } fheroes2-1.1.6+dfsg/src/fheroes2/army/army_troop.h000066400000000000000000000102661476115357100220120ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "monster.h" #include "resource.h" class IStreamBase; class OStreamBase; class Army; class Troop : public Monster { public: Troop(); Troop( const Monster & mons, const uint32_t count ); bool operator==( const Monster & mons ) const; void Set( const Troop & troop ); void Set( const Monster & mons, const uint32_t count ); void SetMonster( const Monster & mons ); void SetCount( const uint32_t count ); void Reset(); bool isMonster( const int mons ) const; const char * GetName() const; uint32_t GetCount() const; uint32_t GetHitPoints() const; Monster GetMonster() const; uint32_t GetDamageMin() const; uint32_t GetDamageMax() const; Funds GetTotalCost() const; // Returns the cost of an upgrade if a monster has an upgrade. Otherwise returns no resources. // IMPORTANT!!! Make sure that you call this method after checking by isAllowUpgrade() method. Funds GetTotalUpgradeCost() const; bool isEmpty() const; virtual bool isValid() const; virtual bool isBattle() const; virtual bool isModes( uint32_t ) const; virtual std::string GetAttackString() const; virtual std::string GetDefenseString() const; virtual std::string GetShotString() const; virtual std::string GetSpeedString() const; virtual uint32_t GetHitPointsLeft() const; virtual uint32_t GetSpeed() const; virtual uint32_t GetAffectedDuration( uint32_t ) const; double GetStrength() const; double GetStrengthWithBonus( const int bonusAttack, const int bonusDefense ) const; protected: static std::string GetSpeedString( const uint32_t speed ); private: friend OStreamBase & operator<<( OStreamBase & stream, const Troop & troop ); friend IStreamBase & operator>>( IStreamBase & stream, Troop & troop ); uint32_t _count; }; class ArmyTroop : public Troop { public: explicit ArmyTroop( const Army * army ); ArmyTroop( const Army * army, const Troop & troop ); ArmyTroop( const ArmyTroop & ) = delete; ~ArmyTroop() override = default; ArmyTroop & operator=( const ArmyTroop & ) = delete; uint32_t GetAttack() const override; uint32_t GetDefense() const override; int GetMorale() const override; int GetLuck() const override; int GetColor() const; void SetArmy( const Army & army ); const Army * GetArmy() const; std::string GetAttackString() const override; std::string GetDefenseString() const override; private: const Army * _army; }; fheroes2-1.1.6+dfsg/src/fheroes2/army/army_ui_helper.cpp000066400000000000000000000121721476115357100231540ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "army_ui_helper.h" #include #include #include #include #include "agg_image.h" #include "army.h" #include "army_troop.h" #include "game.h" #include "icn.h" #include "image.h" #include "ui_text.h" void fheroes2::drawMiniMonsters( const Troops & troops, int32_t cx, const int32_t cy, const int32_t width, uint32_t first, uint32_t count, const bool isCompact, const bool isDetailedView, const bool isGarrisonView, const uint32_t thievesGuildsCount, Image & output ) { if ( !troops.isValid() ) { return; } bool isRightToLeftRender = false; if ( count == 0 ) { // If this function was called with 'count == 0' than the count is determined by the number of troop slots. count = troops.GetOccupiedSlotCount(); if ( first == 0 ) { // This is the case when we render all the troops and do it from left to right. // It is done to make troop sprites overlapping more appealing when troops are close to each other. // This case may occur if many troops were killed during the battle (lots of summoned elementals and/or mirror image troops). isRightToLeftRender = true; } } const double chunk = width / static_cast( count ); if ( !isCompact ) { cx += static_cast( chunk / 2 ); } if ( !isRightToLeftRender ) { cx += width; } const size_t slots = troops.Size(); for ( size_t slot = 0; slot < slots; ++slot ) { if ( count == 0 ) { // We have rendered the given count of troops. There is nothing more to do. break; } const Troop * troop = troops.GetTroop( isRightToLeftRender ? ( slots - slot - 1 ) : slot ); if ( troop == nullptr || !troop->isValid() ) { continue; } if ( first != 0 ) { --first; continue; } std::string monstersCountRepresentation; if ( isDetailedView || !isGarrisonView ) { monstersCountRepresentation = Game::formatMonsterCount( troop->GetCount(), isDetailedView, isCompact ); } else { assert( thievesGuildsCount > 0 ); if ( thievesGuildsCount == 1 ) { monstersCountRepresentation = "???"; } else { monstersCountRepresentation = Army::SizeString( troop->GetCount() ); } } const fheroes2::Sprite & monster = fheroes2::AGG::GetICN( ICN::MONS32, troop->GetSpriteIndex() ); const fheroes2::Text text( std::move( monstersCountRepresentation ), fheroes2::FontType::smallWhite() ); const int32_t posX = isRightToLeftRender ? ( cx + static_cast( chunk * ( count - 1 ) ) ) : ( cx - static_cast( chunk * count ) ); // This is the drawing of army troops in compact form in the small info window beneath resources if ( isCompact ) { const int32_t offsetY = ( monster.height() < 37 ) ? 37 - monster.height() : 0; int32_t offset = ( static_cast( chunk ) - monster.width() - text.width() ) / 2; if ( offset < 0 ) { offset = 0; } fheroes2::Blit( monster, output, posX + offset, cy + offsetY + monster.y() ); text.draw( posX - text.width() - offset + static_cast( chunk ), cy + 23, output ); } else { const int32_t offsetY = 28 - monster.height() + monster.y(); fheroes2::Blit( monster, output, posX - monster.width() / 2 + monster.x() + 2, cy + offsetY ); text.draw( posX - text.width() / 2, cy + 29, output ); } --count; } } fheroes2-1.1.6+dfsg/src/fheroes2/army/army_ui_helper.h000066400000000000000000000034641476115357100226250ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include class Troops; namespace fheroes2 { class Image; void drawMiniMonsters( const Troops & troops, int32_t cx, const int32_t cy, const int32_t width, uint32_t first, uint32_t count, const bool isCompact, const bool isDetailedView, const bool isGarrisonView, const uint32_t thievesGuildsCount, Image & output ); } fheroes2-1.1.6+dfsg/src/fheroes2/audio/000077500000000000000000000000001476115357100175725ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/audio/audio_manager.cpp000066400000000000000000001011331476115357100230700ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "audio_manager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "agg_file.h" #include "audio.h" #include "dir.h" #include "logging.h" #include "m82.h" #include "mus.h" #include "serialize.h" #include "settings.h" #include "system.h" #include "thread.h" #include "tools.h" #include "xmi.h" namespace { struct MusicFileType { explicit MusicFileType( const MUS::ExternalMusicNamingScheme scheme ) : namingScheme( scheme ) { // Do nothing. } MUS::ExternalMusicNamingScheme namingScheme = MUS::ExternalMusicNamingScheme::WIN_VERSION; std::array extension{ ".ogg", ".mp3", ".flac" }; }; bool findMusicFile( const std::vector & directories, const std::string & fileName, std::string & fullPath ) { for ( const std::string & dir : directories ) { ListFiles musicFilePaths; musicFilePaths.ReadDir( dir, fileName ); if ( musicFilePaths.empty() ) { continue; } const std::string correctFilePath = StringLower( System::concatPath( dir, fileName ) ); for ( std::string & path : musicFilePaths ) { if ( StringLower( path ) != correctFilePath ) { continue; } // Avoid string copy. std::swap( fullPath, path ); return true; } } return false; } std::string getExternalMusicFile( const int musicTrackId ) { static const std::vector musicDirectories = []() { std::vector result; for ( const std::string & dir : Settings::GetRootDirs() ) { std::string fullDirectoryPath = System::concatPath( dir, "music" ); if ( System::IsDirectory( fullDirectoryPath ) ) { result.emplace_back( std::move( fullDirectoryPath ) ); } } return result; }(); if ( musicDirectories.empty() ) { // Nothing to search. return {}; } thread_local std::map musicTrackIdToFilePath; const auto iter = musicTrackIdToFilePath.find( musicTrackId ); if ( iter != musicTrackIdToFilePath.end() ) { return iter->second; } const auto tryMusicFileType = [musicTrackId]( MusicFileType & musicFileType ) -> std::string { std::string fullPath; std::string fileName = MUS::getFileName( musicTrackId, musicFileType.namingScheme, musicFileType.extension[0].c_str() ); if ( findMusicFile( musicDirectories, fileName, fullPath ) ) { return fullPath; } fheroes2::replaceStringEnding( fileName, musicFileType.extension[0].c_str(), musicFileType.extension[1].c_str() ); if ( findMusicFile( musicDirectories, fileName, fullPath ) ) { // Swap extensions to improve cache hit. std::swap( musicFileType.extension[0], musicFileType.extension[1] ); return fullPath; } fheroes2::replaceStringEnding( fileName, musicFileType.extension[1].c_str(), musicFileType.extension[2].c_str() ); if ( findMusicFile( musicDirectories, fileName, fullPath ) ) { // Swap extensions to improve cache hit. std::swap( musicFileType.extension[0], musicFileType.extension[2] ); return fullPath; } // Looks like music file does not exist. return {}; }; // To avoid extra I/O calls to data storage it might be useful to remember the last successful type of music and try to search for it next time. thread_local std::array musicFileTypes{ MusicFileType( MUS::ExternalMusicNamingScheme::DOS_VERSION ), MusicFileType( MUS::ExternalMusicNamingScheme::WIN_VERSION ), MusicFileType( MUS::ExternalMusicNamingScheme::MAPPED ) }; for ( size_t i = 0; i < musicFileTypes.size(); ++i ) { std::string filePath = tryMusicFileType( musicFileTypes[i] ); if ( filePath.empty() ) { continue; } if ( i > 0 ) { // Swap music types to improve cache hit. std::swap( musicFileTypes[0], musicFileTypes[i] ); } // Place the path to the cache musicTrackIdToFilePath.try_emplace( musicTrackId, filePath ); return filePath; } // Place the negative result to the cache musicTrackIdToFilePath.try_emplace( musicTrackId ); return {}; } struct ChannelAudioLoopEffectInfo : public AudioManager::AudioLoopEffectInfo { ChannelAudioLoopEffectInfo( const AudioLoopEffectInfo & info, const int chan ) : AudioLoopEffectInfo( info ) , channelId( chan ) { // Do nothing. } bool operator==( const AudioManager::AudioLoopEffectInfo & other ) const { return AudioManager::AudioLoopEffectInfo::operator==( other ); } int channelId{ -1 }; }; std::vector getDataFromAggFile( const std::string & key, const bool ignoreExpansion ); void LoadWAV( int m82, std::vector & v ) { DEBUG_LOG( DBG_GAME, DBG_TRACE, M82::GetString( m82 ) ) const std::vector & body = getDataFromAggFile( M82::GetString( m82 ), false ); if ( !body.empty() ) { RWStreamBuf wavHeader( 44 ); wavHeader.putLE32( 0x46464952 ); // RIFF marker ("RIFF") wavHeader.putLE32( static_cast( body.size() ) + 0x24 ); // Total size minus the size of this and previous fields wavHeader.putLE32( 0x45564157 ); // File type header ("WAVE") wavHeader.putLE32( 0x20746D66 ); // Format sub-chunk marker ("fmt ") wavHeader.putLE32( 0x10 ); // Size of the format sub-chunk wavHeader.putLE16( 0x01 ); // Audio format (1 for PCM) wavHeader.putLE16( 0x01 ); // Number of channels wavHeader.putLE32( 22050 ); // Sample rate wavHeader.putLE32( 22050 ); // Byte rate (SampleRate * BitsPerSample * NumberOfChannels) / 8 wavHeader.putLE16( 0x01 ); // Block align (BitsPerSample * NumberOfChannels) / 8 wavHeader.putLE16( 0x08 ); // Bits per sample wavHeader.putLE32( 0x61746164 ); // Data sub-chunk marker ("data") wavHeader.putLE32( static_cast( body.size() ) ); // Size of the data sub-chunk v.reserve( body.size() + 44 ); v.assign( wavHeader.data(), wavHeader.data() + 44 ); v.insert( v.begin() + 44, body.begin(), body.end() ); } } void LoadMID( int xmi, std::vector & v ) { DEBUG_LOG( DBG_GAME, DBG_TRACE, XMI::GetString( xmi ) ) const std::vector & body = getDataFromAggFile( XMI::GetString( xmi ), xmi >= XMI::MIDI_ORIGINAL_KNIGHT ); if ( !body.empty() ) { v = Music::Xmi2Mid( body ); } } std::map> wavDataCache; std::map> MIDDataCache; const std::vector & GetWAV( int m82 ) { std::vector & v = wavDataCache[m82]; if ( v.empty() ) { LoadWAV( m82, v ); } return v; } const std::vector & GetMID( int xmi ) { std::vector & v = MIDDataCache[xmi]; if ( v.empty() ) { LoadMID( xmi, v ); } return v; } // Returns the ID of the channel occupied by the sound being played, or a negative value (-1) in case of failure. int PlaySoundImpl( const int m82 ); void PlayMusicImpl( const int trackId, const MusicSource musicType, const Music::PlaybackMode playbackMode ); void playLoopSoundsImpl( std::map> soundEffects, const bool is3DAudioEnabled ); // SDL MIDI player is a single threaded library which requires a lot of time to start playing some long midi compositions. // This leads to a situation of a short application freeze while a hero crosses terrains or ending a battle. // The only way to avoid this is to fire MIDI requests asynchronously and synchronize them if needed. class AsyncSoundManager final : public MultiThreading::AsyncManager { public: void pushMusic( const int musicId, const MusicSource musicType, const Music::PlaybackMode playbackMode ) { createWorker(); const std::scoped_lock lock( _mutex ); _musicTask.emplace( musicId, musicType, playbackMode ); notifyWorker(); } void pushSound( const int m82Sound ) { createWorker(); const std::scoped_lock lock( _mutex ); _soundTasks.emplace_back( m82Sound ); notifyWorker(); } void pushLoopSound( std::map> effects, const bool is3DAudioEnabled ) { createWorker(); const std::scoped_lock lock( _mutex ); _loopSoundTask.emplace( std::move( effects ), is3DAudioEnabled ); notifyWorker(); } void removeMusicTask() { const std::scoped_lock lock( _mutex ); _musicTask.reset(); if ( _taskToExecute == TaskType::PlayMusic ) { _taskToExecute = TaskType::None; } } void removeSoundTasks() { const std::scoped_lock lock( _mutex ); _soundTasks.clear(); if ( _taskToExecute == TaskType::PlaySound ) { _taskToExecute = TaskType::None; } } void removeAllSoundTasks() { const std::scoped_lock lock( _mutex ); _soundTasks.clear(); _loopSoundTask.reset(); switch ( _taskToExecute ) { case TaskType::PlaySound: case TaskType::PlayLoopSound: _taskToExecute = TaskType::None; break; default: break; } } void removeAllTasks() { const std::scoped_lock lock( _mutex ); _musicTask.reset(); _soundTasks.clear(); _loopSoundTask.reset(); _taskToExecute = TaskType::None; } // This mutex protects operations with AudioManager's resources, such as AGG files, data caches, etc std::recursive_mutex & resourceMutex() { return _resourceMutex; } private: enum class TaskType : int { None, PlayMusic, PlaySound, PlayLoopSound }; struct MusicTask { MusicTask() = default; MusicTask( const int id, const MusicSource type, const Music::PlaybackMode mode ) : musicId( id ) , musicType( type ) , playbackMode( mode ) { // Do nothing. } int musicId{ 0 }; MusicSource musicType{ MUSIC_MIDI_ORIGINAL }; Music::PlaybackMode playbackMode{ Music::PlaybackMode::PLAY_ONCE }; }; struct SoundTask { SoundTask() = default; explicit SoundTask( const int m82 ) : m82Sound( m82 ) { // Do nothing. } int m82Sound{ 0 }; }; struct LoopSoundTask { LoopSoundTask() = default; LoopSoundTask( std::map> effects, const bool is3DAudioOn ) : soundEffects( std::move( effects ) ) , is3DAudioEnabled( is3DAudioOn ) { // Do nothing. } std::map> soundEffects; bool is3DAudioEnabled{ false }; }; std::optional _musicTask; std::deque _soundTasks; std::optional _loopSoundTask; MusicTask _currentMusicTask; SoundTask _currentSoundTask; LoopSoundTask _currentLoopSoundTask; std::atomic _taskToExecute{ TaskType::None }; std::recursive_mutex _resourceMutex; // This method is called by the worker thread and is protected by _mutex bool prepareTask() override { if ( _musicTask ) { std::swap( _currentMusicTask, *_musicTask ); _musicTask.reset(); _taskToExecute = TaskType::PlayMusic; return true; } if ( !_soundTasks.empty() ) { std::swap( _currentSoundTask, _soundTasks.front() ); _soundTasks.pop_front(); _taskToExecute = TaskType::PlaySound; return true; } if ( _loopSoundTask ) { std::swap( _currentLoopSoundTask, *_loopSoundTask ); _loopSoundTask.reset(); _taskToExecute = TaskType::PlayLoopSound; return true; } _taskToExecute = TaskType::None; return false; } // This method is called by the worker thread, but is not protected by _mutex void executeTask() override { // Do not allow the main thread to acquire this mutex in the interval between the // _taskToExecute was checked and the task was started executing. Release it only // when the task is fully completed. const std::scoped_lock lock( _resourceMutex ); switch ( _taskToExecute ) { case TaskType::None: // Nothing to do. return; case TaskType::PlayMusic: PlayMusicImpl( _currentMusicTask.musicId, _currentMusicTask.musicType, _currentMusicTask.playbackMode ); return; case TaskType::PlaySound: PlaySoundImpl( _currentSoundTask.m82Sound ); return; case TaskType::PlayLoopSound: playLoopSoundsImpl( std::move( _currentLoopSoundTask.soundEffects ), _currentLoopSoundTask.is3DAudioEnabled ); return; default: // How is it even possible? Did you add a new task? assert( 0 ); break; } } }; std::map> currentAudioLoopEffects; bool is3DAudioLoopEffectsEnabled{ false }; // The music track last requested to be played int lastRequestedMusicTrackId{ MUS::UNKNOWN }; // The music track that is currently being played int currentMusicTrackId{ MUS::UNKNOWN }; fheroes2::AGGFile g_midiHeroes2AGG; fheroes2::AGGFile g_midiHeroes2xAGG; std::vector getDataFromAggFile( const std::string & key, const bool ignoreExpansion ) { if ( !ignoreExpansion && g_midiHeroes2xAGG.isGood() ) { // Make sure that the below container is not const and not a reference // so returning it from the function will invoke a move constructor instead of copy constructor. std::vector buf = g_midiHeroes2xAGG.read( key ); if ( !buf.empty() ) return buf; } return g_midiHeroes2AGG.read( key ); } AsyncSoundManager g_asyncSoundManager; int PlaySoundImpl( const int m82 ) { const std::scoped_lock lock( g_asyncSoundManager.resourceMutex() ); DEBUG_LOG( DBG_GAME, DBG_TRACE, "Try to play sound " << M82::GetString( m82 ) ) const std::vector & v = GetWAV( m82 ); if ( v.empty() ) { return -1; } return Mixer::Play( v.data(), static_cast( v.size() ), false ); } uint64_t getMusicUID( const int trackId, const MusicSource musicType ) { static_assert( MUS::UNUSED == 0, "Why are you changing this value?" ); assert( trackId != MUS::UNUSED && trackId != MUS::UNKNOWN ); return ( static_cast( musicType ) << 32 ) + static_cast( trackId ); } void PlayMusicImpl( const int trackId, const MusicSource musicType, const Music::PlaybackMode playbackMode ) { // Make sure that the music track is valid. assert( trackId != MUS::UNUSED && trackId != MUS::UNKNOWN ); const uint64_t musicUID = getMusicUID( trackId, musicType ); const std::scoped_lock lock( g_asyncSoundManager.resourceMutex() ); if ( currentMusicTrackId == trackId && Music::isPlaying() ) { return; } // Check if the music track is already available in the music database. if ( Music::Play( musicUID, playbackMode ) ) { DEBUG_LOG( DBG_GAME, DBG_TRACE, "Play music track " << trackId ) currentMusicTrackId = trackId; return; } if ( musicType == MUSIC_EXTERNAL ) { const std::string filePath = getExternalMusicFile( trackId ); if ( filePath.empty() ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "Cannot find a file for " << trackId << " track." ) } else { Music::Play( musicUID, filePath, playbackMode ); currentMusicTrackId = trackId; DEBUG_LOG( DBG_GAME, DBG_TRACE, "Play music track " << MUS::getFileName( trackId, MUS::ExternalMusicNamingScheme::MAPPED, " " ) ) return; } } int xmi = XMI::UNKNOWN; // Check if music needs to be pulled from HEROES2X if ( musicType == MUSIC_MIDI_EXPANSION ) { xmi = XMI::FromMUS( trackId, g_midiHeroes2xAGG.isGood() ); } if ( XMI::UNKNOWN == xmi ) { xmi = XMI::FromMUS( trackId, false ); } if ( XMI::UNKNOWN != xmi ) { const std::vector & v = GetMID( xmi ); if ( !v.empty() ) { Music::Play( musicUID, v, playbackMode ); currentMusicTrackId = trackId; } } DEBUG_LOG( DBG_GAME, DBG_TRACE, "Play MIDI music track " << XMI::GetString( xmi ) ) } std::pair findPairOfClosestSoundEffects( const std::vector & effectsToAdd, const std::vector & effectsToReplace ) { assert( !effectsToAdd.empty() && !effectsToReplace.empty() ); std::pair result{ 0, 0 }; int bestAngleDiff = INT_MAX; int bestDistanceDiff = INT_MAX; for ( size_t effectToAddId = 0; effectToAddId < effectsToAdd.size(); ++effectToAddId ) { const AudioManager::AudioLoopEffectInfo & effectToAdd = effectsToAdd[effectToAddId]; for ( size_t effectToReplaceId = 0; effectToReplaceId < effectsToReplace.size(); ++effectToReplaceId ) { const ChannelAudioLoopEffectInfo & effectToReplace = effectsToReplace[effectToReplaceId]; const int angleDiff = std::abs( effectToAdd.angle - effectToReplace.angle ); const int distanceDiff = std::abs( static_cast( effectToAdd.distance ) - static_cast( effectToReplace.distance ) ); if ( bestAngleDiff < angleDiff ) { continue; } if ( bestAngleDiff == angleDiff && bestDistanceDiff < distanceDiff ) { continue; } bestAngleDiff = angleDiff; bestDistanceDiff = distanceDiff; result = { effectToAddId, effectToReplaceId }; } } return result; } void clearAllAudioLoopEffects() { for ( const auto & audioEffectPair : currentAudioLoopEffects ) { const std::vector & existingEffects = audioEffectPair.second; for ( const ChannelAudioLoopEffectInfo & info : existingEffects ) { if ( Mixer::isPlaying( info.channelId ) ) { Mixer::Stop( info.channelId ); } } } currentAudioLoopEffects.clear(); } void playLoopSoundsImpl( std::map> soundEffects, const bool is3DAudioEnabled ) { const std::scoped_lock lock( g_asyncSoundManager.resourceMutex() ); if ( is3DAudioLoopEffectsEnabled != is3DAudioEnabled ) { is3DAudioLoopEffectsEnabled = is3DAudioEnabled; clearAllAudioLoopEffects(); } std::map> tempAudioLoopEffects; std::swap( tempAudioLoopEffects, currentAudioLoopEffects ); // Remove all sounds which aren't currently played anymore. This may be the case if the sound playback was forcibly stopped. for ( auto iter = tempAudioLoopEffects.begin(); iter != tempAudioLoopEffects.end(); ) { auto & [dummy, effects] = *iter; effects.erase( std::remove_if( effects.begin(), effects.end(), []( const ChannelAudioLoopEffectInfo & effectInfo ) { return !Mixer::isPlaying( effectInfo.channelId ); } ), effects.end() ); if ( effects.empty() ) { iter = tempAudioLoopEffects.erase( iter ); } else { ++iter; } } // Try to reuse existing sounds. for ( auto iter = soundEffects.begin(); iter != soundEffects.end(); ) { auto & [soundType, effectsToAdd] = *iter; assert( !effectsToAdd.empty() ); auto soundTypeIter = tempAudioLoopEffects.find( soundType ); if ( soundTypeIter == tempAudioLoopEffects.end() ) { // There is no such sound, nothing to reuse. ++iter; continue; } std::vector & effectsToReplace = soundTypeIter->second; // Find existing sounds that have exactly the same distance and angle as the ones that should be added, and reuse these sounds as is. for ( auto effectToAddIter = effectsToAdd.begin(); effectToAddIter != effectsToAdd.end(); ) { auto effectToReplaceIter = std::find( effectsToReplace.begin(), effectsToReplace.end(), *effectToAddIter ); if ( effectToReplaceIter == effectsToReplace.end() ) { ++effectToAddIter; continue; } currentAudioLoopEffects[soundType].emplace_back( *effectToReplaceIter ); effectsToReplace.erase( effectToReplaceIter ); effectToAddIter = effectsToAdd.erase( effectToAddIter ); } // Find the existing sounds closest to those that should be added and reuse these sounds by adjusting their positions. { size_t effectsToReplaceCount = std::min( effectsToAdd.size(), effectsToReplace.size() ); while ( effectsToReplaceCount > 0 ) { --effectsToReplaceCount; { const auto [effectToAddId, effectToReplaceId] = findPairOfClosestSoundEffects( effectsToAdd, effectsToReplace ); const int channelId = effectsToReplace[effectToReplaceId].channelId; currentAudioLoopEffects[soundType].emplace_back( effectsToAdd[effectToAddId], channelId ); effectsToReplace.erase( effectsToReplace.begin() + static_cast( effectToReplaceId ) ); effectsToAdd.erase( effectsToAdd.begin() + static_cast( effectToAddId ) ); } const ChannelAudioLoopEffectInfo & effectInfo = currentAudioLoopEffects[soundType].back(); assert( is3DAudioEnabled || effectInfo.angle == 0 ); Mixer::setPosition( effectInfo.channelId, effectInfo.angle, effectInfo.distance ); } } if ( effectsToReplace.empty() ) { tempAudioLoopEffects.erase( soundTypeIter ); } if ( effectsToAdd.empty() ) { iter = soundEffects.erase( iter ); } else { ++iter; } } // Channels with sounds that could not be reused because such sounds are missing from the list of added ones should be stopped. { for ( const auto & [dummy, effects] : tempAudioLoopEffects ) { for ( const ChannelAudioLoopEffectInfo & effectInfo : effects ) { Mixer::Stop( effectInfo.channelId ); } } tempAudioLoopEffects.clear(); } // Add new sound effects. for ( const auto & [soundType, effects] : soundEffects ) { assert( !effects.empty() ); for ( const AudioManager::AudioLoopEffectInfo & effectInfo : effects ) { // This is a new sound effect. Register and play it. const std::vector & audioData = GetWAV( soundType ); if ( audioData.empty() ) { // Looks like nothing to play. Ignore it. continue; } assert( is3DAudioEnabled || effectInfo.angle == 0 ); const int channelId = Mixer::Play( audioData.data(), static_cast( audioData.size() ), true, std::pair{ effectInfo.angle, effectInfo.distance } ); if ( channelId < 0 ) { // Unable to play this sound. continue; } currentAudioLoopEffects[soundType].emplace_back( effectInfo, channelId ); DEBUG_LOG( DBG_GAME, DBG_TRACE, "Playing sound " << M82::GetString( soundType ) ) } } } } namespace AudioManager { AudioInitializer::AudioInitializer( const std::string & originalAGGFilePath, const std::string & expansionAGGFilePath, const ListFiles & midiSoundFonts ) { if ( Audio::isValid() ) { Mixer::SetChannels( 32 ); // Some platforms (e.g. Linux) may have their own predefined soundfonts, don't overwrite them if we don't have our own if ( !midiSoundFonts.empty() ) { Music::SetMidiSoundFonts( midiSoundFonts ); } Mixer::setVolume( 100 * Settings::Get().SoundVolume() / 10 ); Music::setVolume( 100 * Settings::Get().MusicVolume() / 10 ); Music::SetFadeInMs( 900 ); } assert( !originalAGGFilePath.empty() ); if ( !g_midiHeroes2AGG.open( originalAGGFilePath ) ) { VERBOSE_LOG( "Failed to open HEROES2.AGG file for audio playback." ) } if ( !expansionAGGFilePath.empty() && !g_midiHeroes2xAGG.open( expansionAGGFilePath ) ) { VERBOSE_LOG( "Failed to open HEROES2X.AGG file for audio playback." ) } } AudioInitializer::~AudioInitializer() { g_asyncSoundManager.removeAllTasks(); g_asyncSoundManager.stopWorker(); wavDataCache.clear(); MIDDataCache.clear(); currentAudioLoopEffects.clear(); } MusicRestorer::MusicRestorer() : _music( lastRequestedMusicTrackId ) { // Do nothing. } MusicRestorer::~MusicRestorer() { // It is assumed that the previous track was looped and should be resumed PlayMusicAsync( _music, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); } void playLoopSoundsAsync( std::map> soundEffects ) { if ( !Audio::isValid() ) { return; } g_asyncSoundManager.pushLoopSound( std::move( soundEffects ), Settings::Get().is3DAudioEnabled() ); } int PlaySound( const int m82 ) { if ( m82 == M82::UNKNOWN ) { return -1; } if ( !Audio::isValid() ) { return -1; } g_asyncSoundManager.removeSoundTasks(); return PlaySoundImpl( m82 ); } void PlaySoundAsync( const int m82 ) { if ( m82 == M82::UNKNOWN ) { return; } if ( !Audio::isValid() ) { return; } g_asyncSoundManager.pushSound( m82 ); } bool isExternalMusicFileAvailable( const int trackId ) { return !getExternalMusicFile( trackId ).empty(); } void PlayMusic( const int trackId, const Music::PlaybackMode playbackMode ) { if ( !Audio::isValid() ) { return; } lastRequestedMusicTrackId = trackId; if ( trackId == MUS::UNUSED || trackId == MUS::UNKNOWN ) { return; } g_asyncSoundManager.removeMusicTask(); PlayMusicImpl( trackId, Settings::Get().MusicType(), playbackMode ); } void PlayMusicAsync( const int trackId, const Music::PlaybackMode playbackMode ) { if ( !Audio::isValid() ) { return; } lastRequestedMusicTrackId = trackId; if ( trackId == MUS::UNUSED || trackId == MUS::UNKNOWN ) { return; } g_asyncSoundManager.pushMusic( trackId, Settings::Get().MusicType(), playbackMode ); } void PlayCurrentMusic() { if ( !Audio::isValid() ) { return; } g_asyncSoundManager.removeMusicTask(); const std::scoped_lock lock( g_asyncSoundManager.resourceMutex() ); if ( currentMusicTrackId == MUS::UNUSED || currentMusicTrackId == MUS::UNKNOWN ) { return; } const int trackId = std::exchange( currentMusicTrackId, MUS::UNKNOWN ); PlayMusicImpl( trackId, Settings::Get().MusicType(), Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); } void stopSounds() { if ( !Audio::isValid() ) { return; } g_asyncSoundManager.removeAllSoundTasks(); const std::scoped_lock lock( g_asyncSoundManager.resourceMutex() ); clearAllAudioLoopEffects(); Mixer::Stop(); } void ResetAudio() { if ( !Audio::isValid() ) { return; } g_asyncSoundManager.removeAllTasks(); const std::scoped_lock lock( g_asyncSoundManager.resourceMutex() ); clearAllAudioLoopEffects(); Music::Stop(); Mixer::Stop(); lastRequestedMusicTrackId = MUS::UNKNOWN; currentMusicTrackId = MUS::UNKNOWN; } } fheroes2-1.1.6+dfsg/src/fheroes2/audio/audio_manager.h000066400000000000000000000105451476115357100225430ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include struct ListFiles; namespace M82 { enum SoundType : int; } namespace Music { enum class PlaybackMode : uint8_t; } namespace AudioManager { class AudioInitializer { public: AudioInitializer() = delete; AudioInitializer( const std::string & originalAGGFilePath, const std::string & expansionAGGFilePath, const ListFiles & midiSoundFonts ); AudioInitializer( const AudioInitializer & ) = delete; AudioInitializer & operator=( const AudioInitializer & ) = delete; ~AudioInitializer(); }; // Useful for restoring background music after playing short-term music effects. // Please note that this class will attempt to restore playback of the music track // that was last requested to play at the time of initialization of an instance of // this class, which is not necessarily the same music track that was actually // playing at the time. class MusicRestorer { public: MusicRestorer(); MusicRestorer( const MusicRestorer & ) = delete; ~MusicRestorer(); MusicRestorer & operator=( const MusicRestorer & ) = delete; private: const int _music; }; struct AudioLoopEffectInfo { AudioLoopEffectInfo() = default; AudioLoopEffectInfo( const int16_t angle_, const uint8_t distance_ ) : angle( angle_ ) , distance( distance_ ) { // Do nothing. } bool operator==( const AudioLoopEffectInfo & other ) const { return other.angle == angle && other.distance == distance; } int16_t angle{ 0 }; uint8_t distance{ 0 }; }; void playLoopSoundsAsync( std::map> soundEffects ); // Returns the ID of the channel occupied by the sound being played, or a negative value (-1) in case of failure. int PlaySound( const int m82 ); void PlaySoundAsync( const int m82 ); // Returns true if an external music file is available for the music track with the specified ID, otherwise returns false. bool isExternalMusicFileAvailable( const int trackId ); void PlayMusic( const int trackId, const Music::PlaybackMode playbackMode ); void PlayMusicAsync( const int trackId, const Music::PlaybackMode playbackMode ); // Assumes that the current music track is looped and should be resumed. // // TODO: Is subject to a (minor) race condition when called while the playback // TODO: of a new music track is being started in the AsyncSoundManager's worker // TODO: thread. In this case, the wrong music track (the one that is actually // TODO: being played at the moment, and not the one that is being prepared by // TODO: the worker thread for playback) may be played. void PlayCurrentMusic(); void stopSounds(); void ResetAudio(); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/000077500000000000000000000000001476115357100177445ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle.h000066400000000000000000000106661476115357100214010ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include class Army; namespace Battle { class Unit; enum { RESULT_LOSS = 0x01, RESULT_RETREAT = 0x02, RESULT_SURRENDER = 0x04, RESULT_WINS = 0x80 }; struct Result { uint32_t army1{ 0 }; uint32_t army2{ 0 }; uint32_t exp1{ 0 }; uint32_t exp2{ 0 }; uint32_t killed{ 0 }; bool AttackerWins() const; bool DefenderWins() const; uint32_t AttackerResult() const; uint32_t DefenderResult() const; uint32_t GetExperienceAttacker() const; uint32_t GetExperienceDefender() const; }; Result Loader( Army &, Army &, int32_t ); struct TargetInfo { Unit * defender = nullptr; uint32_t damage = 0; uint32_t killed = 0; bool resist = false; TargetInfo() = default; explicit TargetInfo( Unit * def ) : defender( def ) {} static bool isFinishAnimFrame( const TargetInfo & info ); }; struct TargetsInfo : public std::vector {}; enum MonsterState : uint32_t { TR_RESPONDED = 0x00000001, TR_MOVED = 0x00000002, TR_SKIP = 0x00000004, // UNUSED = 0x00000008, LUCK_GOOD = 0x00000100, LUCK_BAD = 0x00000200, MORALE_GOOD = 0x00000400, MORALE_BAD = 0x00000800, CAP_TOWER = 0x00001000, CAP_SUMMONELEM = 0x00002000, CAP_MIRROROWNER = 0x00004000, CAP_MIRRORIMAGE = 0x00008000, // UNUSED = 0x00010000, SP_BLOODLUST = 0x00020000, SP_BLESS = 0x00040000, SP_HASTE = 0x00080000, SP_SHIELD = 0x00100000, SP_STONESKIN = 0x00200000, SP_DRAGONSLAYER = 0x00400000, SP_STEELSKIN = 0x00800000, SP_ANTIMAGIC = 0x01000000, SP_CURSE = 0x02000000, SP_SLOW = 0x04000000, SP_BERSERKER = 0x08000000, SP_HYPNOTIZE = 0x10000000, SP_BLIND = 0x20000000, SP_PARALYZE = 0x40000000, SP_STONE = 0x80000000, IS_GOOD_MAGIC = SP_BLOODLUST | SP_BLESS | SP_HASTE | SP_SHIELD | SP_STONESKIN | SP_DRAGONSLAYER | SP_STEELSKIN, IS_BAD_MAGIC = SP_CURSE | SP_SLOW | SP_BERSERKER | SP_HYPNOTIZE | SP_BLIND | SP_PARALYZE | SP_STONE, IS_MAGIC = IS_GOOD_MAGIC | IS_BAD_MAGIC | SP_ANTIMAGIC, IS_PARALYZE_MAGIC = SP_PARALYZE | SP_STONE, IS_MIND_MAGIC = SP_BERSERKER | SP_HYPNOTIZE | SP_BLIND | SP_PARALYZE, }; enum class CastleDefenseStructure : int { NONE = 0, WALL1 = 1, WALL2 = 2, WALL3 = 3, WALL4 = 4, TOWER1 = 5, TOWER2 = 6, BRIDGE = 7, CENTRAL_TOWER = 8, TOP_BRIDGE_TOWER = 9, BOTTOM_BRIDGE_TOWER = 10 }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_action.cpp000066400000000000000000001526741476115357100232770ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "battle.h" #include "battle_arena.h" // IWYU pragma: associated #include "battle_army.h" #include "battle_board.h" #include "battle_bridge.h" #include "battle_catapult.h" #include "battle_cell.h" #include "battle_command.h" #include "battle_interface.h" #include "battle_tower.h" #include "battle_troop.h" #include "color.h" #include "heroes.h" #include "heroes_base.h" #include "kingdom.h" #include "logging.h" #include "monster.h" #include "monster_info.h" #include "players.h" #include "rand.h" #include "resource.h" #include "spell.h" #include "spell_storage.h" #include "tools.h" #include "translations.h" #include "world.h" namespace { int32_t calculateAttackTarget( const Battle::Unit & attackingUnit, const Battle::Position & attackPosition, const Battle::Unit & defendingUnit ) { const int32_t attackPositionHeadIdx = attackPosition.GetHead() ? attackPosition.GetHead()->GetIndex() : -1; const int32_t attackPositionTailIdx = attackPosition.GetTail() ? attackPosition.GetTail()->GetIndex() : -1; assert( attackPositionHeadIdx != -1 && ( attackingUnit.isWide() ? attackPositionTailIdx != -1 : attackPositionTailIdx == -1 ) ); if ( Battle::Board::CanAttackFromCell( attackingUnit, attackPositionHeadIdx ) ) { // The defender's head cell is near the head cell of the attack position if ( Battle::Board::isNearIndexes( attackPositionHeadIdx, defendingUnit.GetHeadIndex() ) ) { return defendingUnit.GetHeadIndex(); } // The defender's tail cell is near the head cell of the attack position if ( defendingUnit.isWide() && Battle::Board::isNearIndexes( attackPositionHeadIdx, defendingUnit.GetTailIndex() ) ) { return defendingUnit.GetTailIndex(); } } if ( Battle::Board::CanAttackFromCell( attackingUnit, attackPositionTailIdx ) ) { // The defender's head cell is near the tail cell of the attack position if ( Battle::Board::isNearIndexes( attackPositionTailIdx, defendingUnit.GetHeadIndex() ) ) { return defendingUnit.GetHeadIndex(); } // The defender's tail cell is near the tail cell of the attack position if ( defendingUnit.isWide() && Battle::Board::isNearIndexes( attackPositionTailIdx, defendingUnit.GetTailIndex() ) ) { return defendingUnit.GetTailIndex(); } } // Attack position is not near the defender, this is most likely a shot return defendingUnit.GetHeadIndex(); } int calculateAttackDirection( const Battle::Unit & attackingUnit, const Battle::Position & attackPosition, const int32_t attackTargetIdx ) { const int32_t attackPositionHeadIdx = attackPosition.GetHead() ? attackPosition.GetHead()->GetIndex() : -1; const int32_t attackPositionTailIdx = attackPosition.GetTail() ? attackPosition.GetTail()->GetIndex() : -1; assert( attackPositionHeadIdx != -1 && ( attackingUnit.isWide() ? attackPositionTailIdx != -1 : attackPositionTailIdx == -1 ) ); // The target cell of the attack is near the head cell of the attack position if ( Battle::Board::CanAttackFromCell( attackingUnit, attackPositionHeadIdx ) && Battle::Board::isNearIndexes( attackPositionHeadIdx, attackTargetIdx ) ) { return Battle::Board::GetDirection( attackPositionHeadIdx, attackTargetIdx ); } // The target cell of the attack is near the tail cell of the attack position if ( Battle::Board::CanAttackFromCell( attackingUnit, attackPositionTailIdx ) && Battle::Board::isNearIndexes( attackPositionTailIdx, attackTargetIdx ) ) { return Battle::Board::GetDirection( attackPositionTailIdx, attackTargetIdx ); } // Attack position is not near the defender, this is most likely a shot return Battle::UNKNOWN; } bool checkMoveParams( const Battle::Unit * unit, const int32_t dst ) { assert( unit != nullptr && unit->isValid() ); // "Moving" a unit to its current position is not allowed if ( unit->GetHeadIndex() == dst ) { return false; } const Battle::Position pos = Battle::Position::GetReachable( *unit, dst ); if ( pos.GetHead() == nullptr ) { return false; } assert( pos.isValidForUnit( unit ) ); // Index of the destination cell should correspond to the index of the head cell of the target position and nothing else if ( pos.GetHead()->GetIndex() != dst ) { return false; } return true; } std::pair getEarthquakeDamageRange( const HeroBase * commander ) { const int spellPower = commander->GetPower(); if ( ( spellPower > 0 ) && ( spellPower < 3 ) ) { return { 0, 1 }; } else if ( ( spellPower >= 3 ) && ( spellPower < 6 ) ) { return { 0, 2 }; } else if ( ( spellPower >= 6 ) && ( spellPower < 10 ) ) { return { 0, 3 }; } else if ( spellPower >= 10 ) { return { 1, 3 }; } DEBUG_LOG( DBG_BATTLE, DBG_WARN, "unexpected spellPower value: " << spellPower << " for commander " << commander ) return { 0, 0 }; } } void Battle::Arena::BattleProcess( Unit & attacker, Unit & defender, int32_t tgt /* = -1 */, int dir /* = -1 */ ) { if ( tgt < 0 ) { tgt = calculateAttackTarget( attacker, attacker.GetPosition(), defender ); } if ( dir < 0 ) { dir = calculateAttackDirection( attacker, attacker.GetPosition(), tgt ); } // UNKNOWN attack direction is only allowed for archers assert( Unit::isHandFighting( attacker, defender ) ? dir > UNKNOWN : dir == UNKNOWN ); // This is a direct attack, update the direction for both the attacker and the defender if ( dir ) { const auto directionIsValidForAttack = []( const Unit & attackingUnit, const int32_t attackTgt, const int attackDir ) { assert( attackingUnit.isWide() ); const int32_t attackSrc = Board::GetIndexDirection( attackTgt, Board::GetReflectDirection( attackDir ) ); // Attacker should attack either from his head cell or from his tail cell, otherwise something strange happens assert( attackSrc == attackingUnit.GetHeadIndex() || attackSrc == attackingUnit.GetTailIndex() ); return attackSrc == attackingUnit.GetHeadIndex(); }; if ( attacker.isWide() ) { if ( !directionIsValidForAttack( attacker, tgt, dir ) ) { attacker.SetReflection( !attacker.isReflect() ); } } else { attacker.UpdateDirection( board[tgt].GetPos() ); } if ( !attacker.isIgnoringRetaliation() && defender.AllowResponse() ) { const int32_t responseTgt = calculateAttackTarget( defender, defender.GetPosition(), attacker ); const int responseDir = calculateAttackDirection( defender, defender.GetPosition(), responseTgt ); if ( defender.isWide() ) { if ( !directionIsValidForAttack( defender, responseTgt, responseDir ) ) { defender.SetReflection( !defender.isReflect() ); } } else { defender.UpdateDirection( board[responseTgt].GetPos() ); } } } // This is a shot, update the direction for the attacker only else { // For shooters we get the target position (not the 'tgt') to take into account the wide units. attacker.UpdateDirection( defender.GetRectPosition() ); } // Update the attacker's luck right before the attack attacker.SetRandomLuck( _randomGenerator ); // Do damage first TargetsInfo attackTargets = GetTargetsForDamage( attacker, defender, tgt, dir ); if ( _interface ) { _interface->RedrawActionAttackPart1( attacker, defender, attackTargets ); } uint32_t resurrected = 0; TargetsApplyDamage( attacker, attackTargets, resurrected ); if ( _interface ) { _interface->RedrawActionAttackPart2( attacker, defender, attackTargets, resurrected ); } // Then apply the attacker's built-in spell const Spell spell = attacker.GetSpellMagic( _randomGenerator ); if ( spell.isValid() ) { // Only single target spells and special built-in only spells are allowed assert( spell.isSingleTarget() || spell.isBuiltinOnly() ); TargetsInfo spellTargets; spellTargets.reserve( attackTargets.size() ); // Filter out invalid targets and targets to which the spell cannot be applied for ( const TargetInfo & attackTarget : attackTargets ) { assert( attackTarget.defender != nullptr ); if ( !attackTarget.defender->isValid() ) { continue; } if ( !attackTarget.defender->AllowApplySpell( spell, nullptr ) ) { continue; } spellTargets.emplace_back( attackTarget.defender ); } if ( !spellTargets.empty() ) { // The built-in spell can only be applied to one target. If there are multiple // targets eligible for this spell, then we should randomly select only one. if ( spellTargets.size() > 1 ) { const Unit * selectedUnit = _randomGenerator.Get( spellTargets ).defender; spellTargets.erase( std::remove_if( spellTargets.begin(), spellTargets.end(), [selectedUnit]( const TargetInfo & v ) { return v.defender != selectedUnit; } ), spellTargets.end() ); } assert( spellTargets.size() == 1 ); Unit * spellTargetUnit = spellTargets.front().defender; assert( spellTargetUnit != nullptr ); // The built-in dispel should only remove beneficial spells from the target unit if ( spell.GetID() != Spell::DISPEL || spellTargetUnit->Modes( IS_GOOD_MAGIC ) ) { if ( _interface ) { _interface->RedrawActionSpellCastStatus( spell, spellTargetUnit->GetHeadIndex(), attacker.GetName(), spellTargets ); _interface->RedrawActionSpellCastPart1( spell, spellTargetUnit->GetHeadIndex(), nullptr, spellTargets ); } if ( spell.GetID() == Spell::DISPEL ) { spellTargetUnit->removeAffection( IS_GOOD_MAGIC ); } else { // The unit's built-in spell efficiency does not depend on its commanding hero's skills TargetsApplySpell( nullptr, spell, spellTargets ); } if ( _interface ) { _interface->RedrawActionSpellCastPart2( spell, spellTargets ); _interface->RedrawActionMonsterSpellCastStatus( spell, attacker, spellTargets.front() ); } } } } attacker.PostAttackAction( defender ); } void Battle::Arena::moveUnit( Unit * unit, const int32_t dst ) { if ( dst == -1 ) { return; } assert( checkMoveParams( unit, dst ) ); Position pos = Position::GetReachable( *unit, dst ); assert( pos.isValidForUnit( unit ) ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, unit->String() << ", dst: " << dst << ", (head: " << pos.GetHead()->GetIndex() << ", tail: " << ( unit->isWide() ? pos.GetTail()->GetIndex() : -1 ) << ")" ) Position finalPos; if ( unit->isFlying() ) { unit->UpdateDirection( pos.GetRect() ); if ( unit->isReflect() != pos.isReflect() ) { pos.Swap(); } if ( _interface ) { _interface->RedrawActionFly( *unit, pos ); } else if ( _bridge ) { const int32_t dstHead = pos.GetHead()->GetIndex(); const int32_t dstTail = unit->isWide() ? pos.GetTail()->GetIndex() : -1; // Lower the bridge if the unit needs to land on it if ( _bridge->NeedDown( *unit, dstHead ) || ( unit->isWide() && _bridge->NeedDown( *unit, dstTail ) ) ) { _bridge->ActionDown(); } unit->SetPosition( pos ); // Raise the bridge if possible after the unit has completed its movement if ( _bridge->AllowUp() ) { _bridge->ActionUp(); } } finalPos = pos; } else { const int32_t initialHead = unit->GetHeadIndex(); const Indexes path = GetPath( *unit, pos ); assert( !path.empty() ); if ( _interface ) { _interface->RedrawActionMove( *unit, path ); } else if ( _bridge ) { for ( const int32_t idx : path ) { if ( _bridge->NeedDown( *unit, idx ) ) { _bridge->ActionDown(); } if ( unit->isWide() && unit->GetTailIndex() == idx ) { unit->SetReflection( !unit->isReflect() ); } else { unit->SetPosition( idx ); } if ( _bridge->AllowUp() ) { _bridge->ActionUp(); } } } if ( unit->isWide() ) { const int32_t dstHead = path.back(); const int32_t dstTail = path.size() > 1 ? path[path.size() - 2] : initialHead; finalPos.Set( dstHead, true, ( Board::GetDirection( dstHead, dstTail ) & RIGHT_SIDE ) != 0 ); } else { finalPos.Set( path.back(), false, unit->isReflect() ); } } unit->SetPosition( finalPos ); unit->UpdateDirection(); } void Battle::Arena::ApplyAction( Command & cmd ) { switch ( cmd.GetType() ) { case CommandType::SPELLCAST: ApplyActionSpellCast( cmd ); break; case CommandType::ATTACK: ApplyActionAttack( cmd ); break; case CommandType::MOVE: ApplyActionMove( cmd ); break; case CommandType::SKIP: ApplyActionSkip( cmd ); break; case CommandType::MORALE: ApplyActionMorale( cmd ); break; case CommandType::TOWER: ApplyActionTower( cmd ); break; case CommandType::CATAPULT: ApplyActionCatapult( cmd ); break; case CommandType::RETREAT: ApplyActionRetreat( cmd ); break; case CommandType::SURRENDER: ApplyActionSurrender( cmd ); break; case CommandType::TOGGLE_AUTO_COMBAT: ApplyActionToggleAutoCombat( cmd ); break; case CommandType::QUICK_COMBAT: ApplyActionQuickCombat( cmd ); break; default: break; } } void Battle::Arena::ApplyActionSpellCast( Command & cmd ) { const auto checkParameters = []( const Spell & spell, const HeroBase * commander ) { if ( !spell.isCombat() ) { return false; } const Arena * arena = GetArena(); assert( arena != nullptr ); if ( arena->isDisableCastSpell( spell ) ) { return false; } if ( commander == nullptr || !commander->CanCastSpell( spell ) ) { return false; } return true; }; const Spell spell( cmd.GetNextValue() ); HeroBase * commander = GetCurrentForce().GetCommander(); if ( !checkParameters( spell, commander ) ) { ERROR_LOG( "Invalid parameters: " << spell.GetName() ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, commander->GetName() << ", color: " << Color::String( commander->GetColor() ) << ", spell: " << spell.GetName() ) switch ( spell.GetID() ) { case Spell::TELEPORT: ApplyActionSpellTeleport( cmd ); break; case Spell::EARTHQUAKE: ApplyActionSpellEarthquake( cmd ); break; case Spell::MIRRORIMAGE: ApplyActionSpellMirrorImage( cmd ); break; case Spell::SUMMONEELEMENT: case Spell::SUMMONAELEMENT: case Spell::SUMMONFELEMENT: case Spell::SUMMONWELEMENT: ApplyActionSpellSummonElemental( cmd, spell ); break; default: ApplyActionSpellDefaults( cmd, spell ); break; } commander->SetModes( Heroes::SPELLCASTED ); commander->SpellCasted( spell ); // Save the spell for the Eagle Eye skill _usedSpells.Append( spell ); } void Battle::Arena::ApplyActionAttack( Command & cmd ) { const auto checkParameters = []( const Unit * attacker, const Unit * defender, const int32_t dst, int32_t tgt, int dir ) { if ( attacker == nullptr || !attacker->isValid() ) { return false; } if ( defender == nullptr || !defender->isValid() ) { return false; } if ( attacker->Modes( TR_MOVED ) ) { return false; } if ( attacker->GetCurrentColor() == defender->GetColor() ) { return false; } // Attacker can attack from his current position without performing a move (in this case, the index of the destination cell should be -1) if ( dst != -1 && !checkMoveParams( attacker, dst ) ) { return false; } if ( attacker->isArchers() && !attacker->isHandFighting() ) { // Non-blocked archer can only attack by shooting from his current position if ( dst != -1 ) { return false; } if ( tgt < 0 ) { tgt = calculateAttackTarget( *attacker, attacker->GetPosition(), *defender ); } if ( dir < 0 ) { dir = calculateAttackDirection( *attacker, attacker->GetPosition(), tgt ); } if ( !defender->GetPosition().contains( tgt ) ) { return false; } // Non-blocked archers cannot attack "from a direction" if ( dir != UNKNOWN ) { return false; } return true; } const Position attackPos = ( dst == -1 ? attacker->GetPosition() : Position::GetReachable( *attacker, dst ) ); if ( attackPos.GetHead() == nullptr ) { return false; } assert( attackPos.isValidForUnit( attacker ) ); if ( tgt < 0 ) { tgt = calculateAttackTarget( *attacker, attackPos, *defender ); } if ( dir < 0 ) { dir = calculateAttackDirection( *attacker, attackPos, tgt ); } if ( !defender->GetPosition().contains( tgt ) ) { return false; } // Melee attacks are only possible from a certain direction if ( dir == UNKNOWN ) { return false; } const int32_t attackIdx = ( Board::isValidDirection( tgt, Board::GetReflectDirection( dir ) ) ? Board::GetIndexDirection( tgt, Board::GetReflectDirection( dir ) ) : -1 ); if ( !attackPos.contains( attackIdx ) ) { return false; } // Attack from a specified cell may be prohibited - for example, if this cell belongs to a castle moat if ( !Board::CanAttackFromCell( *attacker, attackIdx ) ) { return false; } return true; }; const uint32_t attackerUID = cmd.GetNextValue(); const uint32_t defenderUID = cmd.GetNextValue(); const int32_t dst = cmd.GetNextValue(); const int32_t tgt = cmd.GetNextValue(); const int dir = cmd.GetNextValue(); Unit * attacker = GetTroopUID( attackerUID ); Unit * defender = GetTroopUID( defenderUID ); if ( !checkParameters( attacker, defender, dst, tgt, dir ) ) { ERROR_LOG( "Invalid parameters: " << "attacker uid: " << GetHexString( attackerUID ) << ", defender uid: " << GetHexString( defenderUID ) << ", dst: " << dst << ", tgt: " << tgt << ", dir: " << dir ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } moveUnit( attacker, dst ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, attacker->String() << " to " << defender->String() ) const bool handfighting = Unit::isHandFighting( *attacker, *defender ); const bool doubleAttack = attacker->isDoubleAttack(); defender->SetBlindRetaliation( defender->Modes( SP_BLIND ) ); BattleProcess( *attacker, *defender, tgt, dir ); if ( defender->isValid() ) { if ( handfighting && !attacker->isIgnoringRetaliation() && defender->AllowResponse() ) { BattleProcess( *defender, *attacker ); defender->SetResponse(); } if ( doubleAttack && attacker->isValid() && !attacker->isImmovable() ) { DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "double attack" ) BattleProcess( *attacker, *defender, tgt, dir ); } } defender->SetBlindRetaliation( false ); // Berserk and Hypnotize spells should only be removed after an attack initiated by this unit, but not after its retaliatory attack attacker->removeAffection( SP_BERSERKER | SP_HYPNOTIZE ); // Reflect attacker only if he is alive. if ( attacker->isValid() ) { attacker->UpdateDirection(); } // Reflect defender only if he is alive. if ( defender->isValid() ) { defender->UpdateDirection(); } attacker->SetModes( TR_MOVED ); } void Battle::Arena::ApplyActionMove( Command & cmd ) { const auto checkParameters = []( const Unit * unit, const int32_t dst ) { if ( unit == nullptr || !unit->isValid() ) { return false; } if ( unit->Modes( TR_MOVED ) ) { return false; } if ( !checkMoveParams( unit, dst ) ) { return false; } return true; }; const uint32_t uid = cmd.GetNextValue(); const int32_t dst = cmd.GetNextValue(); Unit * unit = GetTroopUID( uid ); if ( !checkParameters( unit, dst ) ) { ERROR_LOG( "Invalid parameters: " << "uid: " << GetHexString( uid ) << ", dst: " << dst ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } moveUnit( unit, dst ); unit->SetModes( TR_MOVED ); } void Battle::Arena::ApplyActionSkip( Command & cmd ) { const auto checkParameters = []( const Unit * unit ) { if ( unit == nullptr || !unit->isValid() ) { return false; } if ( unit->Modes( TR_MOVED ) ) { return false; } return true; }; const uint32_t uid = cmd.GetNextValue(); Unit * unit = GetTroopUID( uid ); if ( !checkParameters( unit ) ) { ERROR_LOG( "Invalid parameters: " << "uid: " << GetHexString( uid ) ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, unit->String() ) unit->SetModes( TR_SKIP ); unit->SetModes( TR_MOVED ); if ( _interface ) { _interface->RedrawActionSkipStatus( *unit ); } } void Battle::Arena::ApplyActionMorale( Command & cmd ) { const auto checkParameters = []( const Unit * unit, const bool morale ) { if ( unit == nullptr || !unit->isValid() ) { return false; } if ( morale ) { if ( !unit->AllModes( TR_MOVED | MORALE_GOOD ) ) { return false; } } else { if ( !unit->Modes( MORALE_BAD ) || unit->Modes( TR_MOVED ) ) { return false; } } return true; }; const uint32_t uid = cmd.GetNextValue(); const bool morale = cmd.GetNextValue(); Unit * unit = GetTroopUID( uid ); if ( !checkParameters( unit, morale ) ) { ERROR_LOG( "Invalid parameters: " << "uid: " << GetHexString( uid ) << ", morale: " << ( morale ? "good" : "bad" ) ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, ( morale ? "good" : "bad" ) << " to " << unit->String() ) // Good morale if ( morale ) { unit->ResetModes( TR_MOVED | MORALE_GOOD ); } // Bad morale else { unit->ResetModes( MORALE_BAD ); unit->SetModes( TR_MOVED ); } if ( _interface ) { _interface->RedrawActionMorale( *unit, morale != 0 ); } } void Battle::Arena::ApplyActionRetreat( const Command & /* cmd */ ) { const int currentColor = GetCurrentColor(); if ( !CanRetreatOpponent( currentColor ) ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "color: " << Color::String( currentColor ) ) if ( _army1->GetColor() == currentColor ) { result_game.army1 = RESULT_RETREAT; } else if ( _army2->GetColor() == currentColor ) { result_game.army2 = RESULT_RETREAT; } else { assert( 0 ); } } void Battle::Arena::ApplyActionSurrender( const Command & /* cmd */ ) { const auto checkPreconditions = []( const Funds & cost ) { const Arena * arena = GetArena(); assert( arena != nullptr ); if ( !arena->CanSurrenderOpponent( arena->GetCurrentColor() ) ) { return false; } if ( !world.GetKingdom( arena->GetCurrentColor() ).AllowPayment( cost ) ) { return false; } return true; }; const int currentColor = GetCurrentColor(); if ( _army1->GetColor() == currentColor ) { Funds cost; cost.gold = _army1->GetSurrenderCost(); if ( !checkPreconditions( cost ) ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "color: " << Color::String( currentColor ) ) world.GetKingdom( _army1->GetColor() ).OddFundsResource( cost ); world.GetKingdom( _army2->GetColor() ).AddFundsResource( cost ); result_game.army1 = RESULT_SURRENDER; } else if ( _army2->GetColor() == currentColor ) { Funds cost; cost.gold = _army2->GetSurrenderCost(); if ( !checkPreconditions( cost ) ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "color: " << Color::String( currentColor ) ) world.GetKingdom( _army2->GetColor() ).OddFundsResource( cost ); world.GetKingdom( _army1->GetColor() ).AddFundsResource( cost ); result_game.army2 = RESULT_SURRENDER; } else { assert( 0 ); } } void Battle::Arena::TargetsApplyDamage( Unit & attacker, TargetsInfo & targets, uint32_t & resurrected ) { DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "number of targets: " << targets.size() ) for ( TargetInfo & target : targets ) { assert( target.defender != nullptr ); uint32_t resurrectIncrease = 0; target.defender->ApplyDamage( attacker, target.damage, target.killed, &resurrectIncrease ); resurrected += resurrectIncrease; } } Battle::TargetsInfo Battle::Arena::GetTargetsForDamage( const Unit & attacker, Unit & defender, const int32_t dst, const int dir ) const { // The attacked unit should be located on the attacked cell assert( defender.GetHeadIndex() == dst || defender.GetTailIndex() == dst ); TargetsInfo targets; targets.reserve( 8 ); TargetInfo res; // first target res.defender = &defender; res.damage = attacker.GetDamage( defender, _randomGenerator ); // Genie special attack { const std::vector & attackerAbilities = fheroes2::getMonsterData( attacker.GetID() ).battleStats.abilities; if ( const auto abilityIter = std::find( attackerAbilities.begin(), attackerAbilities.end(), fheroes2::MonsterAbilityType::ENEMY_HALVING ); abilityIter != attackerAbilities.end() ) { const uint32_t halvingDamage = ( defender.GetCount() / 2 + defender.GetCount() % 2 ) * defender.Monster::GetHitPoints(); if ( halvingDamage > res.damage && _randomGenerator.Get( 1, 100 ) <= abilityIter->percentage ) { // Replaces damage, not adds extra damage res.damage = std::min( defender.GetHitPoints(), halvingDamage ); Interface * iface = GetInterface(); if ( iface ) { std::string str( _n( "%{name} destroys half the enemy troops!", "%{name} destroy half the enemy troops!", attacker.GetCount() ) ); StringReplace( str, "%{name}", attacker.GetName() ); iface->setStatus( str, true ); } } } } targets.push_back( res ); std::set consideredTargets{ &defender }; // long distance attack if ( attacker.isDoubleCellAttack() ) { Cell * cell = Board::GetCell( dst, dir ); Unit * enemy = cell ? cell->GetUnit() : nullptr; if ( enemy && consideredTargets.insert( enemy ).second ) { res.defender = enemy; res.damage = attacker.GetDamage( *enemy, _randomGenerator ); targets.push_back( res ); } } // attack of all adjacent cells else if ( attacker.isAllAdjacentCellsAttack() ) { for ( const int32_t nearbyIdx : Board::GetAroundIndexes( attacker ) ) { assert( Board::GetCell( nearbyIdx ) != nullptr ); Unit * enemy = Board::GetCell( nearbyIdx )->GetUnit(); if ( enemy && enemy->GetColor() != attacker.GetCurrentColor() && consideredTargets.insert( enemy ).second ) { res.defender = enemy; res.damage = attacker.GetDamage( *enemy, _randomGenerator ); targets.push_back( res ); } } } // lich cloud damage else if ( attacker.isAbilityPresent( fheroes2::MonsterAbilityType::AREA_SHOT ) && !Unit::isHandFighting( attacker, defender ) ) { for ( const int32_t nearbyIdx : Board::GetAroundIndexes( dst ) ) { assert( Board::GetCell( nearbyIdx ) != nullptr ); Unit * enemy = Board::GetCell( nearbyIdx )->GetUnit(); if ( enemy && consideredTargets.insert( enemy ).second ) { res.defender = enemy; res.damage = attacker.GetDamage( *enemy, _randomGenerator ); targets.push_back( res ); } } } return targets; } void Battle::Arena::TargetsApplySpell( const HeroBase * hero, const Spell & spell, TargetsInfo & targets ) { DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "number of targets: " << targets.size() ) for ( TargetInfo & target : targets ) { assert( target.defender != nullptr ); target.defender->ApplySpell( spell, hero, target ); } } std::vector Battle::Arena::FindChainLightningTargetIndexes( const HeroBase * hero, Unit * firstUnit, const bool applyRandomMagicResistance ) { std::vector result = { firstUnit }; std::vector ignoredTroops = { firstUnit }; std::vector foundTroops = board.GetNearestTroops( result.back(), ignoredTroops ); // Filter those which are fully immuned for ( size_t i = 0; i < foundTroops.size(); ) { if ( foundTroops[i]->GetMagicResist( Spell::CHAINLIGHTNING, hero ) >= 100 ) { ignoredTroops.push_back( foundTroops[i] ); foundTroops.erase( foundTroops.begin() + i ); } else { ++i; } } while ( result.size() != CHAIN_LIGHTNING_CREATURE_COUNT && !foundTroops.empty() ) { bool targetFound = false; for ( size_t i = 0; i < foundTroops.size(); ++i ) { const uint32_t resist = foundTroops[i]->GetMagicResist( Spell::CHAINLIGHTNING, hero ); assert( resist < 100 ); if ( !applyRandomMagicResistance || resist < _randomGenerator.Get( 1, 100 ) ) { ignoredTroops.push_back( foundTroops[i] ); result.push_back( foundTroops[i] ); foundTroops.erase( foundTroops.begin() + i ); targetFound = true; break; } } // All targets are resisted. Choosing the nearest one. if ( !targetFound ) { ignoredTroops.push_back( foundTroops.front() ); result.push_back( foundTroops.front() ); foundTroops.erase( foundTroops.begin() ); } if ( result.size() != CHAIN_LIGHTNING_CREATURE_COUNT ) { foundTroops = board.GetNearestTroops( result.back(), ignoredTroops ); } } return result; } Battle::TargetsInfo Battle::Arena::TargetsForChainLightning( const HeroBase * hero, const int32_t attackedTroopIndex, const bool applyRandomMagicResistance ) { Unit * unit = GetTroopBoard( attackedTroopIndex ); if ( unit == nullptr ) { assert( 0 ); return TargetsInfo(); } TargetsInfo targets; const uint32_t firstUnitResist = unit->GetMagicResist( Spell::CHAINLIGHTNING, hero ); if ( firstUnitResist >= 100 || ( applyRandomMagicResistance && firstUnitResist >= _randomGenerator.Get( 1, 100 ) ) ) { targets.emplace_back(); TargetInfo & res = targets.back(); res.defender = unit; res.resist = true; return targets; } const std::vector targetUnits = FindChainLightningTargetIndexes( hero, unit, applyRandomMagicResistance ); for ( size_t i = 0; i < targetUnits.size(); ++i ) { targets.emplace_back(); TargetInfo & res = targets.back(); res.defender = targetUnits[i]; // store temp priority for calculate damage res.damage = static_cast( i ); } return targets; } Battle::TargetsInfo Battle::Arena::GetTargetsForSpell( const HeroBase * hero, const Spell & spell, const int32_t dst, bool applyRandomMagicResistance, bool * playResistSound ) { TargetsInfo targets; targets.reserve( 8 ); if ( playResistSound ) { *playResistSound = true; } Unit * target = GetTroopBoard( dst ); switch ( spell.GetID() ) { case Spell::CHAINLIGHTNING: case Spell::COLDRING: target = nullptr; break; default: break; } std::set consideredTargets; TargetInfo res; if ( target && target->AllowApplySpell( spell, hero ) && consideredTargets.insert( target ).second ) { res.defender = target; targets.push_back( res ); } if ( target == nullptr && isAbleToResurrectFromGraveyard( dst, spell ) ) { target = getLastResurrectableUnitFromGraveyard( dst, spell ); assert( target != nullptr && !target->isValid() ); if ( consideredTargets.insert( target ).second ) { res.defender = target; targets.push_back( res ); } } else { switch ( spell.GetID() ) { case Spell::CHAINLIGHTNING: { for ( const TargetInfo & spellTarget : TargetsForChainLightning( hero, dst, applyRandomMagicResistance ) ) { assert( spellTarget.defender != nullptr ); if ( consideredTargets.insert( spellTarget.defender ).second ) { targets.push_back( spellTarget ); } else { // TargetsForChainLightning() should never return duplicates assert( 0 ); } } // Magic resistance has already been applied in the process of selecting targets for Chain Lightning applyRandomMagicResistance = false; // TODO: remove this temporary assertion if ( playResistSound ) { assert( *playResistSound ); } break; } case Spell::FIREBALL: case Spell::METEORSHOWER: case Spell::COLDRING: case Spell::FIREBLAST: { for ( const int32_t index : Board::GetDistanceIndexes( dst, ( spell == Spell::FIREBLAST ? 2 : 1 ) ) ) { Unit * targetUnit = GetTroopBoard( index ); if ( targetUnit && targetUnit->AllowApplySpell( spell, hero ) && consideredTargets.insert( targetUnit ).second ) { res.defender = targetUnit; targets.push_back( res ); } } if ( playResistSound ) { *playResistSound = false; } break; } case Spell::DEATHRIPPLE: case Spell::DEATHWAVE: case Spell::ELEMENTALSTORM: case Spell::HOLYWORD: case Spell::HOLYSHOUT: case Spell::ARMAGEDDON: case Spell::MASSBLESS: case Spell::MASSCURE: case Spell::MASSCURSE: case Spell::MASSDISPEL: case Spell::MASSHASTE: case Spell::MASSSHIELD: case Spell::MASSSLOW: { for ( Cell & cell : board ) { target = cell.GetUnit(); if ( target && target->AllowApplySpell( spell, hero ) && consideredTargets.insert( target ).second ) { res.defender = target; targets.push_back( res ); } } if ( playResistSound ) { *playResistSound = false; } break; } default: break; } } // Mark magically resistant troops for ( auto & tgt : targets ) { const uint32_t resist = tgt.defender->GetMagicResist( spell, hero ); assert( resist < 100 ); if ( applyRandomMagicResistance && resist >= _randomGenerator.Get( 1, 100 ) ) { tgt.resist = true; } } return targets; } void Battle::Arena::ApplyActionTower( Command & cmd ) { const auto checkParameters = []( const Tower * tower, const Unit * unit ) { if ( tower == nullptr || !tower->isValid() ) { return false; } if ( unit == nullptr || !unit->isValid() ) { return false; } return true; }; const uint32_t type = cmd.GetNextValue(); const uint32_t uid = cmd.GetNextValue(); Tower * tower = GetTower( static_cast( type ) ); Unit * unit = GetTroopUID( uid ); if ( !checkParameters( tower, unit ) ) { ERROR_LOG( "Invalid parameters: " << "tower: " << type << ", uid: " << GetHexString( uid ) ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "tower: " << type << ", target: " << unit->String() ) TargetInfo target; target.defender = unit; target.damage = tower->GetDamage( *unit, _randomGenerator ); if ( _interface ) { _interface->RedrawActionTowerPart1( *tower, *unit ); } unit->ApplyDamage( *tower, target.damage, target.killed, nullptr ); if ( _interface ) { _interface->RedrawActionTowerPart2( *tower, target ); } } void Battle::Arena::ApplyActionCatapult( Command & cmd ) { if ( _catapult == nullptr ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } const auto checkParameters = [this]( const CastleDefenseStructure target, const int damage ) { if ( damage <= 0 ) { return false; } const std::vector & allowedTargets = Catapult::getAllowedTargets(); if ( std::find( allowedTargets.begin(), allowedTargets.end(), target ) == allowedTargets.end() ) { return false; } return ( damage <= getCastleDefenseStructureCondition( target, SiegeWeaponType::Catapult ) ); }; uint32_t shots = cmd.GetNextValue(); while ( shots-- ) { const CastleDefenseStructure target = static_cast( cmd.GetNextValue() ); const int damage = cmd.GetNextValue(); const bool hit = ( cmd.GetNextValue() != 0 ); if ( target == CastleDefenseStructure::NONE ) { continue; } using TargetUnderlyingType = std::underlying_type_t; if ( !checkParameters( target, damage ) ) { ERROR_LOG( "Invalid parameters: " << "target: " << static_cast( target ) << ", damage: " << damage << ", hit: " << ( hit ? "yes" : "no" ) ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "target: " << static_cast( target ) << ", damage: " << damage << ", hit: " << ( hit ? "yes" : "no" ) ) if ( _interface ) { _interface->RedrawActionCatapultPart1( target, hit ); } if ( !hit ) { continue; } applyDamageToCastleDefenseStructure( target, damage ); if ( _interface ) { // Continue animating the smoke cloud after changing the "health" of the building. _interface->RedrawActionCatapultPart2( target ); } } } void Battle::Arena::ApplyActionToggleAutoCombat( Command & cmd ) { const auto checkParameters = []( const int color ) { const Arena * arena = GetArena(); assert( arena != nullptr ); if ( color != arena->GetArmy1Color() && color != arena->GetArmy2Color() ) { return false; } if ( arena->getForce( color ).GetControl() & CONTROL_AI ) { return false; } return true; }; const int color = cmd.GetNextValue(); if ( !checkParameters( color ) ) { ERROR_LOG( "Invalid parameters: " << "color: " << Color::String( color ) << " (" << color << ")" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } _autoCombatColors ^= color; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "color: " << Color::String( color ) << ", status: " << ( ( _autoCombatColors & color ) ? "on" : "off" ) ) if ( _interface ) { const Player * player = Players::Get( color ); assert( player ); std::string msg = ( _autoCombatColors & color ) ? _( "%{name} has turned on the auto combat" ) : _( "%{name} has turned off the auto combat" ); StringReplace( msg, "%{name}", player->GetName() ); _interface->setStatus( msg, true ); } } void Battle::Arena::ApplyActionQuickCombat( const Command & /* cmd */ ) { const int army1Control = GetForce1().GetControl(); const int army2Control = GetForce2().GetControl(); if ( !( army1Control & CONTROL_HUMAN ) && !( army2Control & CONTROL_HUMAN ) ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "finishing the battle" ) const int army1Color = GetArmy1Color(); const int army2Color = GetArmy2Color(); if ( army1Control & CONTROL_HUMAN ) { _autoCombatColors |= army1Color; } if ( army2Control & CONTROL_HUMAN ) { _autoCombatColors |= army2Color; } _interface.reset(); } void Battle::Arena::ApplyActionSpellSummonElemental( const Command & /* cmd */, const Spell & spell ) { const auto checkPreconditions = []() { const Arena * arena = GetArena(); assert( arena != nullptr ); if ( arena->GetCurrentCommander() == nullptr ) { return false; } const int32_t idx = arena->GetFreePositionNearHero( arena->GetCurrentColor() ); if ( !Board::isValidIndex( idx ) ) { return false; } return true; }; if ( !checkPreconditions() ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } Unit * elem = CreateElemental( spell ); assert( elem != nullptr ); if ( _interface ) { const HeroBase * commander = GetCurrentCommander(); assert( commander != nullptr ); _interface->RedrawActionSpellCastStatus( spell, -1, commander->GetName(), {} ); _interface->RedrawActionSummonElementalSpell( *elem ); } } void Battle::Arena::ApplyActionSpellDefaults( Command & cmd, const Spell & spell ) { const int32_t dst = cmd.GetNextValue(); const HeroBase * commander = GetCurrentCommander(); if ( commander == nullptr ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } bool playResistSound = false; TargetsInfo targets = GetTargetsForSpell( commander, spell, dst, true, &playResistSound ); TargetsInfo resistTargets; if ( _interface ) { _interface->RedrawActionSpellCastStatus( spell, dst, commander->GetName(), targets ); for ( const auto & target : targets ) { if ( target.resist ) { resistTargets.push_back( target ); } } } targets.erase( std::remove_if( targets.begin(), targets.end(), []( const TargetInfo & v ) { return v.resist; } ), targets.end() ); if ( _interface ) { _interface->RedrawActionSpellCastPart1( spell, dst, commander, targets ); for ( const TargetInfo & target : resistTargets ) { _interface->RedrawActionResistSpell( *target.defender, playResistSound ); } } TargetsApplySpell( commander, spell, targets ); if ( _interface ) { _interface->RedrawActionSpellCastPart2( spell, targets ); } } void Battle::Arena::ApplyActionSpellTeleport( Command & cmd ) { const auto checkParameters = []( const Unit * unit, const Cell * cell ) { if ( unit == nullptr || !unit->isValid() ) { return false; } if ( !cell->isPassableForUnit( *unit ) ) { return false; } const Arena * arena = GetArena(); assert( arena != nullptr ); if ( arena->GetCurrentCommander() == nullptr ) { return false; } return true; }; const int32_t src = cmd.GetNextValue(); const int32_t dst = cmd.GetNextValue(); Unit * unit = GetTroopBoard( src ); const Cell * cell = Board::GetCell( dst ); if ( !checkParameters( unit, cell ) ) { ERROR_LOG( "Invalid parameters: " << "src: " << src << ", dst: " << dst ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "src: " << src << ", dst: " << dst ) const Position pos = Position::GetPosition( *unit, dst ); assert( pos.isValidForUnit( unit ) ); if ( _interface ) { const HeroBase * commander = GetCurrentCommander(); assert( commander != nullptr ); TargetInfo targetInfo; targetInfo.defender = unit; TargetsInfo targetsInfo; targetsInfo.push_back( targetInfo ); _interface->RedrawActionSpellCastStatus( Spell( Spell::TELEPORT ), src, commander->GetName(), targetsInfo ); _interface->RedrawActionTeleportSpell( *unit, pos.GetHead()->GetIndex() ); } unit->SetPosition( pos ); } void Battle::Arena::ApplyActionSpellEarthquake( const Command & /* cmd */ ) { const HeroBase * commander = GetCurrentCommander(); if ( commander == nullptr ) { ERROR_LOG( "Preconditions were not met" ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } const auto [minDamage, maxDamage] = getEarthquakeDamageRange( commander ); std::map earthquakeDamage; for ( const CastleDefenseStructure target : { CastleDefenseStructure::WALL1, CastleDefenseStructure::WALL2, CastleDefenseStructure::WALL3, CastleDefenseStructure::WALL4, CastleDefenseStructure::TOWER1, CastleDefenseStructure::TOWER2, CastleDefenseStructure::BRIDGE, CastleDefenseStructure::TOP_BRIDGE_TOWER, CastleDefenseStructure::BOTTOM_BRIDGE_TOWER } ) { const int targetCondition = getCastleDefenseStructureCondition( target, SiegeWeaponType::EarthquakeSpell ); assert( targetCondition >= 0 ); if ( targetCondition == 0 ) { continue; } const int damage = [this, minDmg = minDamage, maxDmg = maxDamage, target]() { // Reduce the chance of bridge demolition by an extra 50% chance to "miss" it by the Earthquake spell. // It is done to be closer to the original game behavior where bridge demolition by this spell // is more rare than the demolition of the other structures. if ( target == CastleDefenseStructure::BRIDGE && _randomGenerator.Get( 0, 1 ) == 0 ) { return 0; } return static_cast( _randomGenerator.Get( minDmg, maxDmg ) ); }(); assert( damage >= 0 ); if ( damage == 0 ) { continue; } if ( const auto [dummy, inserted] = earthquakeDamage.try_emplace( target, std::min( damage, targetCondition ) ); !inserted ) { assert( 0 ); } } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "number of damaged targets: " << earthquakeDamage.size() ) std::vector earthquakeTargets; if ( _interface ) { earthquakeTargets.reserve( earthquakeDamage.size() ); for ( const auto & [target, dummy] : earthquakeDamage ) { earthquakeTargets.push_back( target ); } _interface->RedrawActionSpellCastStatus( Spell( Spell::EARTHQUAKE ), -1, commander->GetName(), {} ); _interface->redrawActionEarthquakeSpellPart1( earthquakeTargets ); } for ( const auto & [target, damage] : earthquakeDamage ) { applyDamageToCastleDefenseStructure( target, damage ); } if ( _interface ) { // Render a second part of blast animation after targets are damaged or even destroyed. _interface->redrawActionEarthquakeSpellPart2( earthquakeTargets ); } } void Battle::Arena::ApplyActionSpellMirrorImage( Command & cmd ) { const auto checkParameters = []( const Unit * unit ) { if ( unit == nullptr || !unit->isValid() ) { return false; } const Arena * arena = GetArena(); assert( arena != nullptr ); if ( arena->GetCurrentCommander() == nullptr ) { return false; } return true; }; const int32_t who = cmd.GetNextValue(); Unit * unit = GetTroopBoard( who ); if ( !checkParameters( unit ) ) { ERROR_LOG( "Invalid parameters: " << "who: " << who ) #ifdef WITH_DEBUG assert( 0 ); #endif return; } Indexes distances = Board::GetDistanceIndexes( unit->GetHeadIndex(), 4 ); const int32_t centerIndex = unit->GetHeadIndex(); std::sort( distances.begin(), distances.end(), [centerIndex]( const int32_t index1, const int32_t index2 ) { return Board::GetDistance( centerIndex, index1 ) < Board::GetDistance( centerIndex, index2 ); } ); Indexes::const_iterator it = std::find_if( distances.begin(), distances.end(), [unit]( const int32_t v ) { return Board::isValidMirrorImageIndex( v, unit ); } ); if ( it != distances.end() ) { const HeroBase * commander = GetCurrentCommander(); assert( commander != nullptr ); const Spell mirrorImageSpell( Spell::MIRRORIMAGE ); TargetInfo targetInfo; targetInfo.defender = unit; TargetsInfo targetsInfo; targetsInfo.push_back( targetInfo ); TargetsApplySpell( commander, mirrorImageSpell, targetsInfo ); Unit * mirrorUnit = CreateMirrorImage( *unit ); assert( mirrorUnit != nullptr ); const Position pos = Position::GetPosition( *mirrorUnit, *it ); assert( pos.isValidForUnit( mirrorUnit ) ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "set position: " << pos.GetHead()->GetIndex() ) if ( _interface ) { _interface->RedrawActionSpellCastStatus( mirrorImageSpell, who, commander->GetName(), targetsInfo ); _interface->RedrawActionMirrorImageSpell( *unit, pos ); } mirrorUnit->SetPosition( pos ); } else { DEBUG_LOG( DBG_BATTLE, DBG_WARN, "no suitable position found" ) if ( _interface ) { _interface->setStatus( _( "Spell failed!" ), true ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_animation.cpp000066400000000000000000000514671476115357100237770ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_animation.h" #include #include #include "logging.h" #include "monster.h" #include "monster_anim.h" #include "rand.h" RandomizedDelay::RandomizedDelay( const uint32_t delay ) : fheroes2::TimeDelay( delay ) , halfDelay( delay / 2 ) , timerIsSet( false ) {} bool RandomizedDelay::checkDelay() { if ( !timerIsSet ) { // Randomize delay as 0.75 to 1.25 original value setDelay( Rand::Get( 0, halfDelay ) + halfDelay * 3 / 2 ); timerIsSet = true; } const bool res = isPassed(); if ( res ) { reset(); timerIsSet = false; } return res; } AnimationSequence::AnimationSequence( const std::vector & seq ) : _seq( seq ) , _currentFrame( 0 ) {} AnimationSequence & AnimationSequence::operator=( const std::vector & rhs ) { _seq = rhs; _currentFrame = 0; return *this; } int AnimationSequence::playAnimation( bool loop ) { if ( !isValid() ) return 0; if ( isLastFrame() ) { if ( loop ) restartAnimation(); } else { ++_currentFrame; } return _seq[_currentFrame]; } int AnimationSequence::restartAnimation() { _currentFrame = 0; return getFrame(); } int AnimationSequence::getFrame() const { return isValid() ? _seq[_currentFrame] : 0; } size_t AnimationSequence::animationLength() const { return _seq.size(); } int AnimationSequence::firstFrame() const { return isValid() ? _seq.front() : 0; } double AnimationSequence::movementProgress() const { if ( !isValid() ) { return 0; } // We return the progress coefficient for moving creature sprite from one position to another. // At the start and the end of the path we also have creature's static position, // but there is no such position on the cells which creature path through. // So to make the movement start and end more smoothly we add 0.5 to the frame number (since it starts from zero). return ( static_cast( _currentFrame ) + 0.5 ) / static_cast( animationLength() ); } bool AnimationSequence::isLastFrame() const { return _currentFrame == _seq.size() - 1; } bool AnimationSequence::isValid() const { return !_seq.empty(); } AnimationReference::AnimationReference( int monsterID ) : _monsterID( monsterID ) { if ( monsterID < Monster::PEASANT || monsterID > Monster::WATER_ELEMENT ) return; _monsterInfo = Bin_Info::GetMonsterInfo( monsterID ); // STATIC is our default // appendFrames inserts to vector so ref is still valid if ( !appendFrames( _static, Bin_Info::MonsterAnimInfo::STATIC ) ) { // fall back to this, to avoid crashes _static.push_back( 1 ); } // Taking damage appendFrames( _wince, Bin_Info::MonsterAnimInfo::WINCE_UP ); appendFrames( _wince, Bin_Info::MonsterAnimInfo::WINCE_END ); // TODO: play it back together for now appendFrames( _winceUp, Bin_Info::MonsterAnimInfo::WINCE_UP ); appendFrames( _winceDown, Bin_Info::MonsterAnimInfo::WINCE_END ); appendFrames( _death, Bin_Info::MonsterAnimInfo::DEATH ); // Idle animations for ( uint32_t idx = Bin_Info::MonsterAnimInfo::IDLE1; idx < _monsterInfo.idleAnimationCount + Bin_Info::MonsterAnimInfo::IDLE1; ++idx ) { std::vector idleAnim; if ( appendFrames( idleAnim, idx ) ) { _idle.push_back( idleAnim ); } } // Movement sequences _offsetX = _monsterInfo.frameXOffset; // Every unit has MOVE_MAIN anim, use it as a base appendFrames( _moving, Bin_Info::MonsterAnimInfo::MOVE_TILE_START ); appendFrames( _moving, Bin_Info::MonsterAnimInfo::MOVE_MAIN ); appendFrames( _moving, Bin_Info::MonsterAnimInfo::MOVE_TILE_END ); if ( _monsterInfo.hasAnim( Bin_Info::MonsterAnimInfo::MOVE_ONE ) ) { appendFrames( _moveOneTile, Bin_Info::MonsterAnimInfo::MOVE_ONE ); } else { // If there is no animation for one tile movement (fix for LICH and POWER_LICH) // make it from sequent MOVE_START, MOVE_MAIN, MOVE_STOP. appendFrames( _moveOneTile, Bin_Info::MonsterAnimInfo::MOVE_START ); appendFrames( _moveOneTile, Bin_Info::MonsterAnimInfo::MOVE_MAIN ); appendFrames( _moveOneTile, Bin_Info::MonsterAnimInfo::MOVE_STOP ); } // First tile move: 1 + 3 + 4 appendFrames( _moveFirstTile, Bin_Info::MonsterAnimInfo::MOVE_START ); appendFrames( _moveFirstTile, Bin_Info::MonsterAnimInfo::MOVE_MAIN ); appendFrames( _moveFirstTile, Bin_Info::MonsterAnimInfo::MOVE_TILE_END ); // Last tile move: 2 + 3 + 5 appendFrames( _moveLastTile, Bin_Info::MonsterAnimInfo::MOVE_TILE_START ); appendFrames( _moveLastTile, Bin_Info::MonsterAnimInfo::MOVE_MAIN ); appendFrames( _moveLastTile, Bin_Info::MonsterAnimInfo::MOVE_STOP ); // Special for flyers appendFrames( _flying.start, Bin_Info::MonsterAnimInfo::MOVE_START ); appendFrames( _flying.end, Bin_Info::MonsterAnimInfo::MOVE_STOP ); // Attack sequences appendFrames( _melee[Monster_Info::TOP].start, Bin_Info::MonsterAnimInfo::ATTACK1 ); appendFrames( _melee[Monster_Info::TOP].end, Bin_Info::MonsterAnimInfo::ATTACK1_END ); appendFrames( _melee[Monster_Info::FRONT].start, Bin_Info::MonsterAnimInfo::ATTACK2 ); appendFrames( _melee[Monster_Info::FRONT].end, Bin_Info::MonsterAnimInfo::ATTACK2_END ); appendFrames( _melee[Monster_Info::BOTTOM].start, Bin_Info::MonsterAnimInfo::ATTACK3 ); appendFrames( _melee[Monster_Info::BOTTOM].end, Bin_Info::MonsterAnimInfo::ATTACK3_END ); // Use either shooting or breath attack animation as ranged if ( _monsterInfo.hasAnim( Bin_Info::MonsterAnimInfo::SHOOT2 ) ) { appendFrames( _ranged[Monster_Info::TOP].start, Bin_Info::MonsterAnimInfo::SHOOT1 ); appendFrames( _ranged[Monster_Info::TOP].end, Bin_Info::MonsterAnimInfo::SHOOT1_END ); appendFrames( _ranged[Monster_Info::FRONT].start, Bin_Info::MonsterAnimInfo::SHOOT2 ); appendFrames( _ranged[Monster_Info::FRONT].end, Bin_Info::MonsterAnimInfo::SHOOT2_END ); appendFrames( _ranged[Monster_Info::BOTTOM].start, Bin_Info::MonsterAnimInfo::SHOOT3 ); appendFrames( _ranged[Monster_Info::BOTTOM].end, Bin_Info::MonsterAnimInfo::SHOOT3_END ); } else if ( _monsterInfo.hasAnim( Bin_Info::MonsterAnimInfo::DOUBLEHEX2 ) ) { // Only 6 units should have this (in the original game) appendFrames( _ranged[Monster_Info::TOP].start, Bin_Info::MonsterAnimInfo::DOUBLEHEX1 ); appendFrames( _ranged[Monster_Info::TOP].end, Bin_Info::MonsterAnimInfo::DOUBLEHEX1_END ); appendFrames( _ranged[Monster_Info::FRONT].start, Bin_Info::MonsterAnimInfo::DOUBLEHEX2 ); appendFrames( _ranged[Monster_Info::FRONT].end, Bin_Info::MonsterAnimInfo::DOUBLEHEX2_END ); appendFrames( _ranged[Monster_Info::BOTTOM].start, Bin_Info::MonsterAnimInfo::DOUBLEHEX3 ); appendFrames( _ranged[Monster_Info::BOTTOM].end, Bin_Info::MonsterAnimInfo::DOUBLEHEX3_END ); } } bool AnimationReference::appendFrames( std::vector & target, int animID ) { if ( _monsterInfo.hasAnim( animID ) ) { target.insert( target.end(), _monsterInfo.animationFrames.at( animID ).begin(), _monsterInfo.animationFrames.at( animID ).end() ); return true; } return false; } const std::vector & AnimationReference::getAnimationVector( int animState ) const { switch ( animState ) { case Monster_Info::STAND_STILL: case Monster_Info::STATIC: return _static; case Monster_Info::IDLE: // Pick random animation if ( !_idle.empty() && _idle.size() == _monsterInfo.idlePriority.size() ) { Rand::Queue picker; for ( size_t i = 0; i < _idle.size(); ++i ) { picker.Push( static_cast( i ), static_cast( _monsterInfo.idlePriority[i] * 100 ) ); } // picker is expected to return at least 0 const size_t id = static_cast( picker.Get() ); return _idle[id]; } break; case Monster_Info::MOVE_START: return _moveFirstTile; case Monster_Info::MOVING: return _moving; case Monster_Info::MOVE_END: return _moveLastTile; case Monster_Info::MOVE_QUICK: return _moveOneTile; case Monster_Info::FLY_UP: return _flying.start; case Monster_Info::FLY_LAND: return _flying.end; case Monster_Info::MELEE_TOP: return _melee[Monster_Info::TOP].start; case Monster_Info::MELEE_TOP_END: return _melee[Monster_Info::TOP].end; case Monster_Info::MELEE_FRONT: return _melee[Monster_Info::FRONT].start; case Monster_Info::MELEE_FRONT_END: return _melee[Monster_Info::FRONT].end; case Monster_Info::MELEE_BOT: return _melee[Monster_Info::BOTTOM].start; case Monster_Info::MELEE_BOT_END: return _melee[Monster_Info::BOTTOM].end; case Monster_Info::RANG_TOP: return _ranged[Monster_Info::TOP].start; case Monster_Info::RANG_TOP_END: return _ranged[Monster_Info::TOP].end; case Monster_Info::RANG_FRONT: return _ranged[Monster_Info::FRONT].start; case Monster_Info::RANG_FRONT_END: return _ranged[Monster_Info::FRONT].end; case Monster_Info::RANG_BOT: return _ranged[Monster_Info::BOTTOM].start; case Monster_Info::RANG_BOT_END: return _ranged[Monster_Info::BOTTOM].end; case Monster_Info::WNCE_UP: return _winceUp; case Monster_Info::WNCE_DOWN: return _winceDown; case Monster_Info::WNCE: return _wince; case Monster_Info::KILL: return _death; default: break; } return _static; } std::vector AnimationReference::getAnimationOffset( int animState ) const { std::vector offset; switch ( animState ) { case Monster_Info::STAND_STILL: case Monster_Info::STATIC: offset.resize( _static.size(), 0 ); break; case Monster_Info::IDLE: offset.resize( _idle.front().size(), 0 ); break; case Monster_Info::MOVE_START: offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_START].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_START].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_END].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_END].end() ); break; case Monster_Info::MOVING: offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_START].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_START].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_END].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_END].end() ); break; case Monster_Info::MOVE_END: offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_START].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_TILE_START].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_STOP].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_STOP].end() ); break; case Monster_Info::MOVE_QUICK: offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_START].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_START].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_MAIN].end() ); offset.insert( offset.end(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_STOP].begin(), _offsetX[Bin_Info::MonsterAnimInfo::MOVE_STOP].end() ); break; case Monster_Info::FLY_UP: offset.resize( _flying.start.size(), 0 ); break; case Monster_Info::FLY_LAND: offset.resize( _flying.end.size(), 0 ); break; case Monster_Info::MELEE_TOP: offset.resize( _melee[Monster_Info::TOP].start.size(), 0 ); break; case Monster_Info::MELEE_TOP_END: offset.resize( _melee[Monster_Info::TOP].end.size(), 0 ); break; case Monster_Info::MELEE_FRONT: offset.resize( _melee[Monster_Info::FRONT].start.size(), 0 ); break; case Monster_Info::MELEE_FRONT_END: offset.resize( _melee[Monster_Info::FRONT].end.size(), 0 ); break; case Monster_Info::MELEE_BOT: offset.resize( _melee[Monster_Info::BOTTOM].start.size(), 0 ); break; case Monster_Info::MELEE_BOT_END: offset.resize( _melee[Monster_Info::BOTTOM].end.size(), 0 ); break; case Monster_Info::RANG_TOP: offset.resize( _ranged[Monster_Info::TOP].start.size(), 0 ); break; case Monster_Info::RANG_TOP_END: offset.resize( _ranged[Monster_Info::TOP].end.size(), 0 ); break; case Monster_Info::RANG_FRONT: offset.resize( _ranged[Monster_Info::FRONT].start.size(), 0 ); break; case Monster_Info::RANG_FRONT_END: offset.resize( _ranged[Monster_Info::FRONT].end.size(), 0 ); break; case Monster_Info::RANG_BOT: offset.resize( _ranged[Monster_Info::BOTTOM].start.size(), 0 ); break; case Monster_Info::RANG_BOT_END: offset.resize( _ranged[Monster_Info::BOTTOM].end.size(), 0 ); break; case Monster_Info::WNCE_UP: offset.resize( _winceUp.size(), 0 ); break; case Monster_Info::WNCE_DOWN: offset.resize( _winceDown.size(), 0 ); break; case Monster_Info::WNCE: offset.resize( _wince.size(), 0 ); break; case Monster_Info::KILL: offset.resize( _death.size(), 0 ); break; default: break; } return offset; } uint32_t AnimationReference::getMoveSpeed() const { return _monsterInfo.moveSpeed; } uint32_t AnimationReference::getFlightSpeed() const { return _monsterInfo.flightSpeed; } uint32_t AnimationReference::getShootingSpeed() const { return _monsterInfo.shootSpeed; } fheroes2::Point AnimationReference::getBlindOffset() const { return _monsterInfo.eyePosition; } int AnimationReference::getTroopCountOffset( bool isReflect ) const { return isReflect ? _monsterInfo.troopCountOffsetRight : _monsterInfo.troopCountOffsetLeft; } fheroes2::Point AnimationReference::getProjectileOffset( size_t direction ) const { if ( _monsterInfo.projectileOffset.size() > direction ) { return _monsterInfo.projectileOffset[direction]; } return fheroes2::Point(); } uint32_t AnimationReference::getIdleDelay() const { return _monsterInfo.idleAnimationDelay; } AnimationState::AnimationState( int monsterID ) : AnimationReference( monsterID ) , _animState( Monster_Info::STATIC ) , _currentSequence( _static ) {} bool AnimationState::switchAnimation( int animState, bool reverse ) { std::vector seq = getAnimationVector( animState ); if ( !seq.empty() ) { _animState = animState; if ( reverse ) std::reverse( seq.begin(), seq.end() ); _currentSequence = seq; _currentSequence.restartAnimation(); return true; } else { DEBUG_LOG( DBG_GAME, DBG_WARN, " AnimationState switched to invalid anim " << animState << " length " << _currentSequence.animationLength() ) } return false; } bool AnimationState::switchAnimation( const std::vector & animationList, bool reverse ) { std::vector combinedAnimation; for ( std::vector::const_iterator it = animationList.begin(); it != animationList.end(); ++it ) { const std::vector & seq = getAnimationVector( *it ); if ( !seq.empty() ) { _animState = *it; combinedAnimation.insert( combinedAnimation.end(), seq.begin(), seq.end() ); } } if ( !combinedAnimation.empty() ) { if ( reverse ) std::reverse( combinedAnimation.begin(), combinedAnimation.end() ); _currentSequence = combinedAnimation; _currentSequence.restartAnimation(); return true; } else { DEBUG_LOG( DBG_GAME, DBG_WARN, " AnimationState switched to invalid anim list of length " << animationList.size() ) } return false; } int AnimationState::getCurrentState() const { return _animState; } int AnimationState::playAnimation( bool loop ) { return _currentSequence.playAnimation( loop ); } int AnimationState::restartAnimation() { return _currentSequence.restartAnimation(); } int AnimationState::getFrame() const { return _currentSequence.getFrame(); } size_t AnimationState::animationLength() const { return _currentSequence.animationLength(); } int AnimationState::firstFrame() const { return _currentSequence.firstFrame(); } int32_t AnimationState::getCurrentFrameXOffset() const { // Return the horizontal frame offset to use in rendering. std::vector animSubsequences; // The animations consist of some subsequences. Put into vector the animation subsequences queue. switch ( _animState ) { case Monster_Info::MOVE_START: animSubsequences = { Bin_Info::MonsterAnimInfo::MOVE_START, Bin_Info::MonsterAnimInfo::MOVE_MAIN, Bin_Info::MonsterAnimInfo::MOVE_TILE_END }; break; case Monster_Info::MOVING: { animSubsequences = { Bin_Info::MonsterAnimInfo::MOVE_TILE_START, Bin_Info::MonsterAnimInfo::MOVE_MAIN, Bin_Info::MonsterAnimInfo::MOVE_TILE_END }; break; } case Monster_Info::MOVE_END: { animSubsequences = { Bin_Info::MonsterAnimInfo::MOVE_TILE_START, Bin_Info::MonsterAnimInfo::MOVE_MAIN, Bin_Info::MonsterAnimInfo::MOVE_STOP }; break; } case Monster_Info::MOVE_QUICK: { animSubsequences = { Bin_Info::MonsterAnimInfo::MOVE_START, Bin_Info::MonsterAnimInfo::MOVE_MAIN, Bin_Info::MonsterAnimInfo::MOVE_STOP }; break; } default: // If there is no horizontal offset data for current animation state, return 0 as offset. return 0; } // The frame number of current subsequence start. size_t subequenceStart = 0; // The frame number in the full animation sequence, which include subsequences. const size_t currentFrame = _currentSequence.getCurrentFrameId(); // Get frame offset from _offsetX, analyzing in which subsequence it is. for ( const int32_t animSubsequence : animSubsequences ) { // Get the current subsequence end (it is the frame number after the last subsequence frame). const size_t subequenceEnd = _offsetX[animSubsequence].size() + subequenceStart; if ( currentFrame < subequenceEnd ) { return _offsetX[animSubsequence][currentFrame - subequenceStart]; } subequenceStart = subequenceEnd; } // If there is no horizontal offset data for currentFrame, return 0 as offset. DEBUG_LOG( DBG_GAME, DBG_WARN, "Frame " << currentFrame << " is outside _offsetX [0 - " << subequenceStart << "] for animation state " << _animState ) return 0; } double AnimationState::movementProgress() const { return _currentSequence.movementProgress(); } bool AnimationState::isLastFrame() const { return _currentSequence.isLastFrame(); } bool AnimationState::isValid() const { return _currentSequence.isValid(); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_animation.h000066400000000000000000000121271476115357100234320ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "bin_info.h" #include "math_base.h" #include "timing.h" // This timer is used for randomized idle animation delays, automatically setting it in range of 75%-125% of the intended value class RandomizedDelay : protected fheroes2::TimeDelay { public: explicit RandomizedDelay( const uint32_t delay ); // This function triggers the current delay, returning true if it is passed and automatically resets the timer. bool checkDelay(); private: uint32_t halfDelay; bool timerIsSet; }; struct MonsterReturnAnim { std::vector start; std::vector end; }; class AnimationSequence final { public: explicit AnimationSequence( const std::vector & seq ); AnimationSequence( const AnimationSequence & ) = delete; ~AnimationSequence() = default; AnimationSequence & operator=( const AnimationSequence & ) = delete; AnimationSequence & operator=( const std::vector & rhs ); int playAnimation( bool loop = false ); int restartAnimation(); int getFrame() const; int firstFrame() const; size_t animationLength() const; double movementProgress() const; bool isLastFrame() const; bool isValid() const; size_t getCurrentFrameId() const { return _currentFrame; } private: std::vector _seq; size_t _currentFrame; }; class AnimationReference { public: explicit AnimationReference( int id ); AnimationReference( const AnimationReference & ) = delete; AnimationReference( AnimationReference && ) = default; virtual ~AnimationReference() = default; AnimationReference & operator=( const AnimationReference & ) = delete; AnimationReference & operator=( AnimationReference && ) = default; const std::vector & getAnimationVector( int animState ) const; std::vector getAnimationOffset( int animState ) const; uint32_t getMoveSpeed() const; uint32_t getFlightSpeed() const; uint32_t getShootingSpeed() const; fheroes2::Point getBlindOffset() const; fheroes2::Point getProjectileOffset( size_t direction ) const; int getTroopCountOffset( bool isReflect ) const; uint32_t getIdleDelay() const; protected: int _monsterID; Bin_Info::MonsterAnimInfo _monsterInfo; std::vector _static; std::vector _moveFirstTile; std::vector _moving; std::vector _moveLastTile; std::vector _moveOneTile; MonsterReturnAnim _flying; std::vector _winceUp; std::vector _winceDown; std::vector _wince; std::vector _death; MonsterReturnAnim _melee[3]; MonsterReturnAnim _ranged[3]; std::vector> _idle; std::vector> _offsetX; bool appendFrames( std::vector & target, int animID ); }; class AnimationState final : public AnimationReference { public: explicit AnimationState( int monsterID ); AnimationState( const AnimationState & ) = delete; ~AnimationState() override = default; AnimationState & operator=( const AnimationState & ) = delete; bool switchAnimation( int animstate, bool reverse = false ); bool switchAnimation( const std::vector & animationList, bool reverse = false ); int getCurrentState() const; // pass-down methods int playAnimation( bool loop = false ); int restartAnimation(); int getFrame() const; int firstFrame() const; int32_t getCurrentFrameXOffset() const; size_t animationLength() const; double movementProgress() const; bool isLastFrame() const; bool isValid() const; private: int _animState; AnimationSequence _currentSequence; }; fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_arena.cpp000066400000000000000000001376441476115357100231100ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_arena.h" #include #include #include #include #include #include #include #include #include #include #include "ai_battle.h" #include "army.h" #include "army_troop.h" #include "artifact.h" #include "artifact_info.h" #include "audio.h" #include "battle_army.h" #include "battle_bridge.h" #include "battle_catapult.h" #include "battle_cell.h" #include "battle_command.h" #include "battle_interface.h" #include "battle_tower.h" #include "battle_troop.h" #include "castle.h" #include "color.h" #include "ground.h" #include "heroes.h" #include "heroes_base.h" #include "icn.h" #include "localevent.h" #include "logging.h" #include "maps.h" #include "maps_tiles.h" #include "math_base.h" #include "math_tools.h" #include "monster.h" #include "players.h" #include "rand.h" #include "skill.h" #include "speed.h" #include "spell_info.h" #include "translations.h" #include "world.h" namespace { Battle::Arena * arena = nullptr; template Battle::Unit * getLastResurrectableUnitFromGraveyardTmpl( const Battle::Graveyard & graveyard, const HeroBase * commander, const int32_t index, const T & spells ) { if ( commander == nullptr ) { return nullptr; } // Declare this variable both constexpr and static because different compilers disagree on whether there is a need to capture it in lambda expressions or not static constexpr bool isSingleSpell{ std::is_same_v>, Spell> }; if constexpr ( isSingleSpell ) { if ( !spells.isResurrect() ) { return nullptr; } } else { if ( !std::all_of( spells.begin(), spells.end(), []( const Spell & spell ) { return spell.isResurrect(); } ) ) { return nullptr; } } const std::vector units = graveyard.getUnits( index ); const auto iter = std::find_if( units.rbegin(), units.rend(), [commander, &spells]( const Battle::Unit * unit ) { assert( unit != nullptr && !unit->isValid() ); if ( unit->GetArmyColor() != commander->GetColor() ) { return false; } if constexpr ( isSingleSpell ) { return unit->AllowApplySpell( spells, commander ); } else { return std::any_of( spells.begin(), spells.end(), [commander, unit]( const Spell & spell ) { return unit->AllowApplySpell( spell, commander ); } ); } } ); if ( iter == units.rend() ) { return nullptr; } return *iter; } int GetCovr( int ground, std::mt19937 & gen ) { std::vector covrs; covrs.reserve( 6 ); switch ( ground ) { case Maps::Ground::SNOW: covrs.push_back( ICN::COVR0007 ); covrs.push_back( ICN::COVR0008 ); covrs.push_back( ICN::COVR0009 ); covrs.push_back( ICN::COVR0010 ); covrs.push_back( ICN::COVR0011 ); covrs.push_back( ICN::COVR0012 ); break; case Maps::Ground::WASTELAND: covrs.push_back( ICN::COVR0019 ); covrs.push_back( ICN::COVR0020 ); covrs.push_back( ICN::COVR0021 ); covrs.push_back( ICN::COVR0022 ); covrs.push_back( ICN::COVR0023 ); covrs.push_back( ICN::COVR0024 ); break; case Maps::Ground::DIRT: covrs.push_back( ICN::COVR0013 ); covrs.push_back( ICN::COVR0014 ); covrs.push_back( ICN::COVR0015 ); covrs.push_back( ICN::COVR0016 ); covrs.push_back( ICN::COVR0017 ); covrs.push_back( ICN::COVR0018 ); break; case Maps::Ground::GRASS: covrs.push_back( ICN::COVR0001 ); covrs.push_back( ICN::COVR0002 ); covrs.push_back( ICN::COVR0003 ); covrs.push_back( ICN::COVR0004 ); covrs.push_back( ICN::COVR0005 ); covrs.push_back( ICN::COVR0006 ); break; default: break; } return covrs.empty() ? ICN::UNKNOWN : Rand::GetWithGen( covrs, gen ); } Battle::Unit * GetCurrentUnit( Battle::Units & units1, Battle::Units & units2, const bool units1GoFirst, const bool ordersMode ) { Battle::Unit * result = nullptr; const auto unitFilter = []( const Battle::Unit * unit ) { return unit->GetSpeed() > Speed::STANDING; }; Battle::Units::iterator it1 = std::find_if( units1.begin(), units1.end(), unitFilter ); Battle::Units::iterator it2 = std::find_if( units2.begin(), units2.end(), unitFilter ); if ( it1 != units1.end() && it2 != units2.end() ) { if ( ( *it1 )->GetSpeed() == ( *it2 )->GetSpeed() ) { result = units1GoFirst ? *it1 : *it2; } else { result = ( ( *it1 )->GetSpeed() > ( *it2 )->GetSpeed() ) ? *it1 : *it2; } } else if ( it1 != units1.end() ) { result = *it1; } else if ( it2 != units2.end() ) { result = *it2; } if ( result && ordersMode ) { if ( it1 != units1.end() && result == *it1 ) { units1.erase( it1 ); } else if ( it2 != units2.end() && result == *it2 ) { units2.erase( it2 ); } } return result; } Battle::Unit * GetCurrentUnit( const Battle::Force & army1, const Battle::Force & army2, const int preferredColor ) { Battle::Units units1( army1.getUnits(), Battle::Units::REMOVE_INVALID_UNITS ); Battle::Units units2( army2.getUnits(), Battle::Units::REMOVE_INVALID_UNITS ); units1.SortFastest(); units2.SortFastest(); Battle::Unit * result = GetCurrentUnit( units1, units2, preferredColor != army2.GetColor(), false ); if ( result == nullptr ) { return result; } assert( result->isValid() ); return result; } void UpdateOrderOfUnits( const Battle::Force & army1, const Battle::Force & army2, const Battle::Unit * currentUnit, int preferredColor, const Battle::Units & orderHistory, Battle::Units & orderOfUnits ) { orderOfUnits.assign( orderHistory.begin(), orderHistory.end() ); Battle::Units units1( army1.getUnits(), Battle::Units::REMOVE_INVALID_UNITS ); Battle::Units units2( army2.getUnits(), Battle::Units::REMOVE_INVALID_UNITS ); units1.SortFastest(); units2.SortFastest(); while ( true ) { Battle::Unit * unit = GetCurrentUnit( units1, units2, preferredColor != army2.GetColor(), true ); if ( unit == nullptr ) { break; } assert( unit->isValid() ); if ( unit == currentUnit ) { continue; } preferredColor = ( unit->GetArmyColor() == army1.GetColor() ) ? army2.GetColor() : army1.GetColor(); orderOfUnits.push_back( unit ); } } size_t getPositionOfCastleDefenseStructure( const Battle::CastleDefenseStructure structure ) { switch ( structure ) { case Battle::CastleDefenseStructure::BRIDGE: return Battle::Arena::CASTLE_GATE_POS; case Battle::CastleDefenseStructure::TOWER1: return Battle::Arena::CASTLE_TOP_ARCHER_TOWER_POS; case Battle::CastleDefenseStructure::TOWER2: return Battle::Arena::CASTLE_BOTTOM_ARCHER_TOWER_POS; case Battle::CastleDefenseStructure::WALL1: return Battle::Arena::CASTLE_FIRST_TOP_WALL_POS; case Battle::CastleDefenseStructure::WALL2: return Battle::Arena::CASTLE_SECOND_TOP_WALL_POS; case Battle::CastleDefenseStructure::WALL3: return Battle::Arena::CASTLE_THIRD_TOP_WALL_POS; case Battle::CastleDefenseStructure::WALL4: return Battle::Arena::CASTLE_FOURTH_TOP_WALL_POS; case Battle::CastleDefenseStructure::TOP_BRIDGE_TOWER: return Battle::Arena::CASTLE_TOP_GATE_TOWER_POS; case Battle::CastleDefenseStructure::BOTTOM_BRIDGE_TOWER: return Battle::Arena::CASTLE_BOTTOM_GATE_TOWER_POS; default: assert( 0 ); break; } return 0; } } Battle::Arena * Battle::GetArena() { return arena; } const Castle * Battle::Arena::GetCastle() { assert( arena != nullptr ); return arena->castle; } Battle::Bridge * Battle::Arena::GetBridge() { assert( arena != nullptr ); return arena->_bridge.get(); } Battle::Board * Battle::Arena::GetBoard() { assert( arena != nullptr ); return &arena->board; } Battle::Graveyard * Battle::Arena::GetGraveyard() { assert( arena != nullptr ); return &arena->_graveyard; } Battle::Interface * Battle::Arena::GetInterface() { assert( arena != nullptr ); return arena->_interface.get(); } Battle::Tower * Battle::Arena::GetTower( const TowerType type ) { assert( arena != nullptr ); switch ( type ) { case TowerType::TWR_LEFT: return arena->_towers[0].get(); case TowerType::TWR_CENTER: return arena->_towers[1].get(); case TowerType::TWR_RIGHT: return arena->_towers[2].get(); default: break; } return nullptr; } bool Battle::Arena::isAnyTowerPresent() { assert( arena != nullptr ); return std::any_of( arena->_towers.begin(), arena->_towers.end(), []( const auto & twr ) { return twr && twr->isValid(); } ); } Battle::Arena::Arena( Army & army1, Army & army2, const int32_t tileIndex, const bool isShowInterface, Rand::DeterministicRandomGenerator & randomGenerator ) : castle( world.getCastleEntrance( Maps::GetPoint( tileIndex ) ) ) , _isTown( castle != nullptr ) , _randomGenerator( randomGenerator ) { _usedSpells.reserve( 20 ); assert( arena == nullptr ); arena = this; _army1 = std::make_unique( army1, false, _uidGenerator ); _army2 = std::make_unique( army2, true, _uidGenerator ); // If this is a siege of a town, then there is in fact no castle if ( castle && !castle->isCastle() ) { castle = nullptr; } if ( isShowInterface ) { _interface = std::make_unique( *this, tileIndex ); board.SetArea( _interface->GetArea() ); _orderOfUnits = std::make_shared(); _orderOfUnits->reserve( 25 ); _interface->SetOrderOfUnits( _orderOfUnits ); } else { // There is no interface - force the auto combat mode for the human player if ( army1.isControlHuman() ) { _autoCombatColors |= army1.GetColor(); } if ( army2.isControlHuman() ) { _autoCombatColors |= army2.GetColor(); } } if ( castle ) { if ( castle->isBuild( BUILD_LEFTTURRET ) ) { _towers[0] = std::make_unique( *castle, TowerType::TWR_LEFT, _uidGenerator.GetUnique() ); } _towers[1] = std::make_unique( *castle, TowerType::TWR_CENTER, _uidGenerator.GetUnique() ); if ( castle->isBuild( BUILD_RIGHTTURRET ) ) { _towers[2] = std::make_unique( *castle, TowerType::TWR_RIGHT, _uidGenerator.GetUnique() ); } if ( _army1->GetCommander() ) { _catapult = std::make_unique( *_army1->GetCommander() ); } _bridge = std::make_unique(); // catapult cell board[CATAPULT_POS].SetObject( 1 ); // wall (3,2,1,0) const int wallObject = castle->isFortificationBuilt() ? 3 : 2; board[CASTLE_FIRST_TOP_WALL_POS].SetObject( wallObject ); board[CASTLE_SECOND_TOP_WALL_POS].SetObject( wallObject ); board[CASTLE_THIRD_TOP_WALL_POS].SetObject( wallObject ); board[CASTLE_FOURTH_TOP_WALL_POS].SetObject( wallObject ); // NOTE: All towers can be destroyed but can not be passable. // Initially their condition is 2 and becomes 1 after their upper part is destroyed. // The tower's condition should not be 0 to keep them non-passable by the troops. // Towers near the bridge. Does not shoot arrows. Can be damaged only by the Earthquake spell. board[CASTLE_TOP_GATE_TOWER_POS].SetObject( 2 ); board[CASTLE_BOTTOM_GATE_TOWER_POS].SetObject( 2 ); // Turret towers with small ballista. board[CASTLE_TOP_ARCHER_TOWER_POS].SetObject( 2 ); board[CASTLE_BOTTOM_ARCHER_TOWER_POS].SetObject( 2 ); // bridge board[CASTLE_GATE_POS].SetObject( 1 ); } else // set obstacles { std::mt19937 seededGen( world.GetMapSeed() + static_cast( tileIndex ) ); _covrIcnId = Rand::GetWithGen( 0, 99, seededGen ) < 40 ? GetCovr( world.getTile( tileIndex ).GetGround(), seededGen ) : ICN::UNKNOWN; if ( _covrIcnId != ICN::UNKNOWN ) { board.SetCovrObjects( _covrIcnId ); } board.SetCobjObjects( world.getTile( tileIndex ), seededGen ); } AI::BattlePlanner::Get().battleBegins(); if ( _interface ) { _interface->fullRedraw(); // Wait for the end of M82::PREBATTL playback. Make sure that we check the music status first as HandleEvents() call is not instant. LocalEvent & le = LocalEvent::Get(); while ( Mixer::isPlaying( -1 ) && le.HandleEvents() ) { if ( le.isKeyPressed( fheroes2::Key::KEY_ESCAPE ) || le.MouseClickMiddle() || le.MouseClickRight() ) { // Cancel waiting for M82::PREBATTL to over and start the battle. break; } } } } Battle::Arena::~Arena() { assert( arena == this ); arena = nullptr; } void Battle::Arena::UnitTurn( const Units & orderHistory ) { assert( _currentUnit && _currentUnit->isValid() ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, _currentUnit->String( true ) ) if ( _currentUnit->isAffectedByMorale() ) { _currentUnit->SetRandomMorale( _randomGenerator ); } assert( !_currentUnit->AllModes( MORALE_GOOD | MORALE_BAD ) ); bool endOfTurn = false; while ( !endOfTurn ) { // There should be no dead units on the board at the beginning of each iteration assert( std::all_of( board.begin(), board.end(), []( const Cell & cell ) { return ( cell.GetUnit() == nullptr || cell.GetUnit()->isValid() ); } ) ); Actions actions; if ( _interface ) { _interface->getPendingActions( actions ); } if ( !actions.empty() ) { // Pending actions from the user interface (such as toggling the auto combat on/off) have "already occurred" // and therefore should be handled first, before any other actions. Just skip the rest of the branches. } else if ( _currentUnit->GetSpeed() == Speed::STANDING ) { // Unit has either finished its turn, is dead, or has become immovable due to some spell. Even if the // unit died or has become immovable during its turn without performing any action, its turn is still // considered completed. _currentUnit->SetModes( TR_MOVED ); endOfTurn = true; } else if ( _currentUnit->Modes( MORALE_BAD ) ) { actions.emplace_back( Command::MORALE, _currentUnit->GetUID(), false ); } else { // This unit will certainly perform at least one full-fledged action _lastActiveUnitArmyColor = _currentUnit->GetArmyColor(); if ( _bridge ) { _bridge->SetPassability( *_currentUnit ); } if ( ( _currentUnit->GetCurrentControl() & CONTROL_AI ) || ( _currentUnit->GetCurrentColor() & _autoCombatColors ) ) { AI::BattlePlanner::Get().BattleTurn( *this, *_currentUnit, actions ); } else { assert( _interface != nullptr ); _interface->HumanTurn( *_currentUnit, actions ); } } const uint32_t newSeed = std::accumulate( actions.cbegin(), actions.cend(), _randomGenerator.GetSeed(), []( const uint32_t seed, const Command & cmd ) { return cmd.updateSeed( seed ); } ); _randomGenerator.UpdateSeed( newSeed ); while ( !actions.empty() ) { ApplyAction( actions.front() ); actions.pop_front(); board.removeDeadUnits(); if ( _orderOfUnits ) { // Applied action could kill someone or affect the speed of some unit, update the order of units UpdateOrderOfUnits( *_army1, *_army2, _currentUnit, GetOppositeColor( _currentUnit->GetArmyColor() ), orderHistory, *_orderOfUnits ); } if ( !BattleValid() ) { endOfTurn = true; break; } if ( _currentUnit->AllModes( TR_MOVED | MORALE_GOOD ) && !_currentUnit->Modes( TR_SKIP ) && _currentUnit->GetSpeed( false, true ) > Speed::STANDING ) { actions.emplace_back( Command::MORALE, _currentUnit->GetUID(), true ); } } // There should be no dead units on the board at the end of each iteration assert( std::all_of( board.begin(), board.end(), []( const Cell & cell ) { return ( cell.GetUnit() == nullptr || cell.GetUnit()->isValid() ); } ) ); } } bool Battle::Arena::BattleValid() const { return _army1->isValid() && _army2->isValid() && 0 == result_game.army1 && 0 == result_game.army2; } void Battle::Arena::Turns() { ++_turnNumber; DEBUG_LOG( DBG_BATTLE, DBG_TRACE, _turnNumber ) if ( _interface ) { _interface->RedrawActionNewTurn(); } _army1->NewTurn(); _army2->NewTurn(); // History of unit order on the current turn Units orderHistory; if ( _orderOfUnits ) { orderHistory.reserve( 25 ); // Build the initial order of units UpdateOrderOfUnits( *_army1, *_army2, nullptr, GetOppositeColor( _lastActiveUnitArmyColor ), orderHistory, *_orderOfUnits ); } { bool towersActed = false; bool catapultActed = false; while ( BattleValid() ) { // We can get the nullptr here if there are no units left waiting for their turn _currentUnit = GetCurrentUnit( *_army1, *_army2, GetOppositeColor( _lastActiveUnitArmyColor ) ); if ( _orderOfUnits ) { // Add unit to the history if ( _currentUnit ) { orderHistory.push_back( _currentUnit ); } // Update the order of units UpdateOrderOfUnits( *_army1, *_army2, _currentUnit, GetOppositeColor( _currentUnit ? _currentUnit->GetArmyColor() : _lastActiveUnitArmyColor ), orderHistory, *_orderOfUnits ); } if ( castle ) { // Catapult acts either during the turn of the first unit from the attacking army, or at the end of the // turn if none of the units from the attacking army are able to act (for example, all are blinded) if ( !catapultActed && ( _currentUnit == nullptr || _currentUnit->GetColor() == _army1->GetColor() ) ) { CatapultAction(); catapultActed = true; } // Castle towers act either during the turn of the first unit from the defending army, or at the end of // the turn if none of the units from the defending army are able to act (for example, all are blinded) if ( !towersActed && ( _currentUnit == nullptr || _currentUnit->GetColor() == _army2->GetColor() ) ) { const auto towerAction = [this, &orderHistory]( const size_t idx ) { assert( idx < std::size( _towers ) ); if ( _towers[idx] == nullptr || !_towers[idx]->isValid() ) { return; } TowerAction( *_towers[idx] ); if ( _orderOfUnits ) { // Tower could kill someone, update the order of units UpdateOrderOfUnits( *_army1, *_army2, _currentUnit, GetOppositeColor( _currentUnit ? _currentUnit->GetArmyColor() : _lastActiveUnitArmyColor ), orderHistory, *_orderOfUnits ); } }; towerAction( 1 ); towerAction( 0 ); towerAction( 2 ); towersActed = true; // If the towers have killed the last enemy unit, the battle is over if ( !BattleValid() ) { break; } } } if ( _currentUnit == nullptr ) { // There are no units left waiting for their turn break; } UnitTurn( orderHistory ); } } // Check if the battle is over if ( !_army1->isValid() || ( result_game.army1 & ( RESULT_RETREAT | RESULT_SURRENDER ) ) ) { result_game.army1 |= RESULT_LOSS; // Check if any of the original troops in the army2 are still alive result_game.army2 = _army2->isValid( false ) ? RESULT_WINS : RESULT_LOSS; } else if ( !_army2->isValid() || ( result_game.army2 & ( RESULT_RETREAT | RESULT_SURRENDER ) ) ) { result_game.army2 |= RESULT_LOSS; // Check if any of the original troops in the army1 are still alive result_game.army1 = _army1->isValid( false ) ? RESULT_WINS : RESULT_LOSS; } // If the battle is over, calculate the experience and the number of units killed if ( result_game.army1 || result_game.army2 ) { result_game.exp1 = _army2->GetDeadHitPoints(); result_game.exp2 = _army1->GetDeadHitPoints(); const HeroBase * army1Commander = _army1->GetCommander(); const HeroBase * army2Commander = _army2->GetCommander(); // Attacker (or defender) gets an experience bonus if the enemy army was under the command of a hero who was defeated (i.e. did not retreat or surrender) if ( army1Commander && army1Commander->isHeroes() && !( result_game.army1 & ( RESULT_RETREAT | RESULT_SURRENDER ) ) ) { result_game.exp2 += 500; } if ( army2Commander && army2Commander->isHeroes() && !( result_game.army2 & ( RESULT_RETREAT | RESULT_SURRENDER ) ) ) { result_game.exp1 += 500; } // Attacker gets an additional experience bonus after successfully besieging a town or castle if ( _isTown ) { result_game.exp1 += 500; } const Force * army_loss = ( result_game.army1 & RESULT_LOSS ? _army1.get() : ( result_game.army2 & RESULT_LOSS ? _army2.get() : nullptr ) ); result_game.killed = army_loss ? army_loss->GetDeadCounts() : 0; } } void Battle::Arena::TowerAction( const Tower & twr ) { // There should be no dead units on the board at this moment assert( std::all_of( board.begin(), board.end(), []( const Cell & cell ) { return ( cell.GetUnit() == nullptr || cell.GetUnit()->isValid() ); } ) ); // Target unit and its threat level std::pair targetInfo{ nullptr, INT32_MIN }; for ( const Cell & cell : board ) { const Unit * unit = cell.GetUnit(); if ( unit == nullptr || unit->GetColor() == twr.GetColor() || ( unit->isWide() && unit->GetTailIndex() == cell.GetIndex() ) ) { continue; } const int32_t unitThreatLevel = unit->evaluateThreatForUnit( twr ); if ( targetInfo.first == nullptr || targetInfo.second < unitThreatLevel ) { targetInfo = { unit, unitThreatLevel }; } } if ( targetInfo.first == nullptr ) { DEBUG_LOG( DBG_BATTLE, DBG_INFO, "No target found for the tower" ) return; } using TowerGetTypeUnderlyingType = typename std::underlying_type_t; static_assert( std::is_same_v ); Command cmd( Command::TOWER, static_cast( twr.GetType() ), targetInfo.first->GetUID() ); ApplyAction( cmd ); board.removeDeadUnits(); } void Battle::Arena::CatapultAction() { if ( !_catapult ) { return; } uint32_t shots = _catapult->GetShots(); std::map stateOfCatapultTargets; for ( const CastleDefenseStructure target : Catapult::getAllowedTargets() ) { if ( const auto [dummy, inserted] = stateOfCatapultTargets.try_emplace( target, getCastleDefenseStructureCondition( target, SiegeWeaponType::Catapult ) ); !inserted ) { assert( 0 ); } } Command cmd( Command::CATAPULT ); cmd << shots; while ( shots-- ) { const CastleDefenseStructure target = Catapult::GetTarget( stateOfCatapultTargets, _randomGenerator ); const int damage = std::min( _catapult->GetDamage( _randomGenerator ), stateOfCatapultTargets[target] ); const bool hit = _catapult->IsNextShotHit( _randomGenerator ); using TargetUnderlyingType = std::underlying_type_t; cmd << static_cast( target ) << damage << ( hit ? 1 : 0 ); if ( hit ) { stateOfCatapultTargets[target] -= damage; } } // Preserve the order of shots - command arguments will be extracted in reverse order std::reverse( cmd.begin(), cmd.end() ); ApplyAction( cmd ); } Battle::Indexes Battle::Arena::GetPath( const Unit & unit, const Position & position ) { const Indexes result = _battlePathfinder.buildPath( unit, position ); if ( IS_DEBUG( DBG_BATTLE, DBG_TRACE ) && !result.empty() ) { std::string pathStr; pathStr.reserve( Speed::INSTANT * 4 ); std::for_each( result.begin(), result.end(), [&pathStr]( const int32_t item ) { pathStr += std::to_string( item ); pathStr += ", "; } ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, pathStr ) } return result; } Battle::Unit * Battle::Arena::GetTroopBoard( int32_t index ) { return Board::isValidIndex( index ) ? board[index].GetUnit() : nullptr; } const Battle::Unit * Battle::Arena::GetTroopBoard( int32_t index ) const { return Board::isValidIndex( index ) ? board[index].GetUnit() : nullptr; } HeroBase * Battle::Arena::GetCommander1() const { return _army1->GetCommander(); } HeroBase * Battle::Arena::GetCommander2() const { return _army2->GetCommander(); } int Battle::Arena::GetArmy1Color() const { return _army1->GetColor(); } int Battle::Arena::GetArmy2Color() const { return _army2->GetColor(); } int Battle::Arena::GetCurrentColor() const { // This method should never be called in cases where there may not be an active unit if ( _currentUnit == nullptr ) { assert( 0 ); return Color::NONE; } return _currentUnit->GetCurrentOrArmyColor(); } int Battle::Arena::GetOppositeColor( const int col ) const { return col == GetArmy1Color() ? GetArmy2Color() : GetArmy1Color(); } Battle::Unit * Battle::Arena::GetTroopUID( uint32_t uid ) { if ( const auto iter = std::find_if( _army1->begin(), _army1->end(), [uid]( const Unit * unit ) { return unit->isUID( uid ); } ); iter != _army1->end() ) { return *iter; } if ( const auto iter = std::find_if( _army2->begin(), _army2->end(), [uid]( const Unit * unit ) { return unit->isUID( uid ); } ); iter != _army2->end() ) { return *iter; } return nullptr; } const Battle::Unit * Battle::Arena::GetTroopUID( uint32_t uid ) const { if ( const auto iter = std::find_if( _army1->begin(), _army1->end(), [uid]( const Unit * unit ) { return unit->isUID( uid ); } ); iter != _army1->end() ) { return *iter; } if ( const auto iter = std::find_if( _army2->begin(), _army2->end(), [uid]( const Unit * unit ) { return unit->isUID( uid ); } ); iter != _army2->end() ) { return *iter; } return nullptr; } void Battle::Arena::FadeArena( bool clearMessageLog ) const { if ( !_interface ) { return; } _interface->FadeArena( clearMessageLog ); } const SpellStorage & Battle::Arena::GetUsedSpells() const { return _usedSpells; } int32_t Battle::Arena::GetFreePositionNearHero( const int heroColor ) const { std::vector cellIds; if ( _army1->GetColor() == heroColor ) { cellIds = { 11, 22, 33 }; } else if ( _army2->GetColor() == heroColor ) { cellIds = { 21, 32, 43 }; } else { // Some third color? return -1; } assert( !cellIds.empty() ); for ( const int cellId : cellIds ) { if ( board[cellId].isPassable( true ) ) { // TODO: remove this temporary assertion assert( board[cellId].GetUnit() == nullptr ); return cellId; } } return -1; } bool Battle::Arena::CanSurrenderOpponent( int color ) const { const HeroBase * hero = getCommander( color ); const HeroBase * enemyHero = getEnemyCommander( color ); return hero && hero->isHeroes() && enemyHero && ( enemyHero->isHeroes() || enemyHero->isCaptain() ); } bool Battle::Arena::CanRetreatOpponent( int color ) const { const HeroBase * hero = getCommander( color ); return hero && hero->isHeroes() && ( color == _army1->GetColor() || hero->inCastle() == nullptr ); } bool Battle::Arena::isSpellcastDisabled() const { const HeroBase * hero1 = _army1->GetCommander(); if ( hero1 != nullptr && hero1->GetBagArtifacts().isArtifactBonusPresent( fheroes2::ArtifactBonusType::DISABLE_ALL_SPELL_COMBAT_CASTING ) ) { return true; } const HeroBase * hero2 = _army2->GetCommander(); if ( hero2 != nullptr && hero2->GetBagArtifacts().isArtifactBonusPresent( fheroes2::ArtifactBonusType::DISABLE_ALL_SPELL_COMBAT_CASTING ) ) { return true; } return false; } bool Battle::Arena::isDisableCastSpell( const Spell & spell, std::string * msg /* = nullptr */ ) const { if ( isSpellcastDisabled() ) { if ( msg ) { *msg = _( "The Sphere of Negation artifact is in effect for this battle, disabling all combat spells." ); } return true; } const HeroBase * commander = GetCurrentCommander(); if ( commander == nullptr ) { // This should not normally happen, but there are places where the ability to "basically" // cast a spell is checked before checking for the presence of a commanding hero. if ( msg ) { *msg = _( "You cannot cast spells without a commanding hero." ); } return true; } if ( commander->Modes( Heroes::SPELLCASTED ) ) { if ( msg ) { *msg = _( "You have already cast a spell this round." ); } return true; } // An empty spell can be used to test the ability to cast spells in principle if ( !spell.isValid() ) { return false; } if ( spell == Spell::EARTHQUAKE ) { if ( castle == nullptr ) { if ( msg ) { *msg = _( "That spell will have no effect!" ); } return true; } return false; } if ( spell.isSummon() ) { const Monster mons( spell ); assert( mons.isValid() && mons.isElemental() ); const Unit * elem = GetCurrentForce().FindMode( CAP_SUMMONELEM ); if ( elem && elem->GetID() != mons.GetID() ) { if ( msg ) { *msg = _( "You may only summon one type of elemental per combat." ); } return true; } if ( GetFreePositionNearHero( GetCurrentColor() ) < 0 ) { if ( msg ) { *msg = _( "There is no open space adjacent to your hero where you can summon an Elemental to." ); } return true; } return false; } for ( const Cell & cell : board ) { if ( const Battle::Unit * unit = cell.GetUnit(); unit != nullptr ) { if ( unit->AllowApplySpell( spell, commander ) ) { return false; } continue; } if ( isAbleToResurrectFromGraveyard( cell.GetIndex(), spell ) ) { return false; } } if ( msg ) { *msg = _( "That spell will have no effect!" ); } return true; } bool Battle::Arena::isAbleToResurrectFromGraveyard( const int32_t index, const Spell & spell ) const { if ( !spell.isResurrect() ) { return false; } const HeroBase * hero = GetCurrentCommander(); if ( hero == nullptr ) { return false; } const Unit * unit = getLastResurrectableUnitFromGraveyard( index, spell ); if ( unit == nullptr ) { return false; } if ( !unit->AllowApplySpell( spell, hero ) ) { return false; } const int headIndex = unit->GetHeadIndex(); assert( Board::isValidIndex( headIndex ) ); // No other unit should stand on a corpse if ( Board::GetCell( headIndex )->GetUnit() != nullptr ) { return false; } if ( !unit->isWide() ) { return true; } const int tailIndex = unit->GetTailIndex(); assert( Board::isValidIndex( tailIndex ) ); // No other unit should stand on a corpse if ( Board::GetCell( tailIndex )->GetUnit() != nullptr ) { return false; } return true; } const Battle::Unit * Battle::Arena::getLastUnitFromGraveyard( const int32_t index ) const { return _graveyard.getLastUnit( index ); } const Battle::Unit * Battle::Arena::getLastResurrectableUnitFromGraveyard( const int32_t index ) const { static const std::vector resurrectionSpells = []() { std::vector result; for ( int spellId = Spell::NONE; spellId < Spell::SPELL_COUNT; ++spellId ) { const Spell spell( spellId ); if ( !spell.isResurrect() ) { continue; } result.push_back( spell ); } return result; }(); return getLastResurrectableUnitFromGraveyardTmpl( _graveyard, GetCurrentCommander(), index, resurrectionSpells ); } Battle::Unit * Battle::Arena::getLastResurrectableUnitFromGraveyard( const int32_t index, const Spell & spell ) const { return getLastResurrectableUnitFromGraveyardTmpl( _graveyard, GetCurrentCommander(), index, spell ); } std::vector Battle::Arena::getGraveyardUnits( const int32_t index ) const { const std::vector units = _graveyard.getUnits( index ); return { units.begin(), units.end() }; } Battle::Indexes Battle::Arena::getCellsOccupiedByGraveyard() const { return _graveyard.getOccupiedCells(); } void Battle::Arena::applyDamageToCastleDefenseStructure( const CastleDefenseStructure target, const int damage ) { assert( castle != nullptr ); switch ( target ) { // Sections of the castle wall can be completely destroyed and it will be possible to pass through the corresponding cells. case CastleDefenseStructure::WALL1: case CastleDefenseStructure::WALL2: case CastleDefenseStructure::WALL3: case CastleDefenseStructure::WALL4: { const size_t position = getPositionOfCastleDefenseStructure( target ); const int condition = board[position].GetObject(); assert( damage > 0 && damage <= condition ); board[position].SetObject( condition - damage ); break; } // Tete-de-pont towers can be damaged, but not fully demolished (it is still impossible to pass through the corresponding cells). case CastleDefenseStructure::TOP_BRIDGE_TOWER: case CastleDefenseStructure::BOTTOM_BRIDGE_TOWER: { const size_t position = getPositionOfCastleDefenseStructure( target ); const int condition = board[position].GetObject(); assert( damage == 1 && damage < condition ); board[position].SetObject( condition - damage ); break; } // Wall towers (with or without built turret) can be damaged (and they will stop shooting in this case), but not fully demolished // (it is still impossible to pass through the corresponding cells). case CastleDefenseStructure::TOWER1: case CastleDefenseStructure::TOWER2: case CastleDefenseStructure::CENTRAL_TOWER: { const size_t towerIdx = [target]() -> size_t { switch ( target ) { case CastleDefenseStructure::TOWER1: return 0; case CastleDefenseStructure::TOWER2: return 2; case CastleDefenseStructure::CENTRAL_TOWER: return 1; default: assert( 0 ); break; } return 0; }(); assert( ( [this, target, damage, towerIdx]() { if ( damage != 1 ) { return false; } if ( target == CastleDefenseStructure::CENTRAL_TOWER ) { return _towers[towerIdx] && _towers[towerIdx]->isValid(); } const size_t position = getPositionOfCastleDefenseStructure( target ); const int condition = board[position].GetObject(); if ( damage >= condition ) { return false; } if ( !_towers[towerIdx] ) { return ( condition == 1 || condition == 2 ); } if ( _towers[towerIdx]->isValid() ) { return condition == 2; } return condition == 1; }() ) ); if ( _towers[towerIdx] ) { _towers[towerIdx]->SetDestroyed(); break; } const size_t position = getPositionOfCastleDefenseStructure( target ); const int condition = board[position].GetObject(); board[position].SetObject( condition - damage ); break; } // Castle bridge can be completely destroyed and it will be possible to pass through the corresponding cell. case CastleDefenseStructure::BRIDGE: { assert( damage == 1 && _bridge && _bridge->isValid() ); _bridge->SetDestroyed(); break; } default: assert( 0 ); break; } } int Battle::Arena::getCastleDefenseStructureCondition( const CastleDefenseStructure target, const SiegeWeaponType siegeWeapon ) const { assert( castle != nullptr ); switch ( target ) { case CastleDefenseStructure::WALL1: case CastleDefenseStructure::WALL2: case CastleDefenseStructure::WALL3: case CastleDefenseStructure::WALL4: { const size_t position = getPositionOfCastleDefenseStructure( target ); const int condition = board[position].GetObject(); assert( condition >= 0 ); return condition; } case CastleDefenseStructure::TOP_BRIDGE_TOWER: case CastleDefenseStructure::BOTTOM_BRIDGE_TOWER: { assert( siegeWeapon == SiegeWeaponType::EarthquakeSpell ); const size_t position = getPositionOfCastleDefenseStructure( target ); const int condition = board[position].GetObject(); assert( condition == 1 || condition == 2 ); return condition - 1; } case CastleDefenseStructure::TOWER1: case CastleDefenseStructure::TOWER2: case CastleDefenseStructure::CENTRAL_TOWER: { const size_t towerIdx = [target]() -> size_t { switch ( target ) { case CastleDefenseStructure::TOWER1: return 0; case CastleDefenseStructure::TOWER2: return 2; case CastleDefenseStructure::CENTRAL_TOWER: return 1; default: assert( 0 ); break; } return 0; }(); assert( ( [this, target, siegeWeapon, towerIdx]() { if ( target == CastleDefenseStructure::CENTRAL_TOWER ) { return ( siegeWeapon == SiegeWeaponType::Catapult ); } const size_t position = getPositionOfCastleDefenseStructure( target ); const int condition = board[position].GetObject(); if ( !_towers[towerIdx] ) { return ( condition == 1 || condition == 2 ); } if ( _towers[towerIdx]->isValid() ) { return condition == 2; } return condition == 1; }() ) ); switch ( siegeWeapon ) { case SiegeWeaponType::Catapult: return _towers[towerIdx] && _towers[towerIdx]->isValid() ? 1 : 0; case SiegeWeaponType::EarthquakeSpell: return board[getPositionOfCastleDefenseStructure( target )].GetObject() - 1; default: assert( 0 ); break; } break; } case CastleDefenseStructure::BRIDGE: { assert( _bridge ); return _bridge->isValid() ? 1 : 0; } default: assert( 0 ); break; } return 0; } const HeroBase * Battle::Arena::getCommander( const int color ) const { return ( _army1->GetColor() == color ) ? _army1->GetCommander() : _army2->GetCommander(); } const HeroBase * Battle::Arena::getEnemyCommander( const int color ) const { return ( _army1->GetColor() == color ) ? _army2->GetCommander() : _army1->GetCommander(); } const HeroBase * Battle::Arena::GetCurrentCommander() const { return getCommander( GetCurrentColor() ); } Battle::Unit * Battle::Arena::CreateElemental( const Spell & spell ) { // TODO: this assertion is here to thoroughly check all the complex limitations of the Summon Elemental spell assert( !isDisableCastSpell( spell ) ); const HeroBase * hero = GetCurrentCommander(); assert( hero != nullptr ); const int32_t idx = GetFreePositionNearHero( GetCurrentColor() ); assert( Board::isValidIndex( idx ) ); const Monster mons( spell ); assert( mons.isValid() && mons.isElemental() && !mons.isWide() ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, mons.GetName() << ", position: " << idx ) const bool reflect = ( hero == _army2->GetCommander() ); const uint32_t count = fheroes2::getSummonMonsterCount( spell, hero->GetPower(), hero ); Position pos; pos.Set( idx, mons.isWide(), reflect ); // An elemental could not be a wide unit assert( pos.GetHead() != nullptr && pos.GetTail() == nullptr ); Unit * elem = new Unit( Troop( mons, count ), pos, reflect, _uidGenerator.GetUnique() ); elem->SetModes( CAP_SUMMONELEM ); elem->SetArmy( hero->GetArmy() ); GetCurrentForce().push_back( elem ); return elem; } Battle::Unit * Battle::Arena::CreateMirrorImage( Unit & unit ) { Unit * mirrorUnit = new Unit( unit, {}, unit.isReflect(), _uidGenerator.GetUnique() ); mirrorUnit->SetArmy( *unit.GetArmy() ); mirrorUnit->SetMirror( &unit ); mirrorUnit->SetModes( CAP_MIRRORIMAGE ); unit.SetMirror( mirrorUnit ); unit.SetModes( CAP_MIRROROWNER ); GetCurrentForce().push_back( mirrorUnit ); return mirrorUnit; } bool Battle::Arena::IsShootingPenalty( const Unit & attacker, const Unit & defender ) const { // no castle - no castle walls, penalty does not apply if ( castle == nullptr ) { return false; } // penalty does not apply to towers if ( defender.Modes( CAP_TOWER ) || attacker.Modes( CAP_TOWER ) ) return false; // penalty does not apply if the attacker's hero has certain artifacts or skills const HeroBase * hero = attacker.GetCommander(); if ( hero ) { // golden bow artifact if ( hero->GetBagArtifacts().isArtifactBonusPresent( fheroes2::ArtifactBonusType::NO_SHOOTING_PENALTY ) ) return false; // archery skill if ( hero->GetLevelSkill( Skill::Secondary::ARCHERY ) != Skill::Level::NONE ) return false; } // penalty does not apply if the attacking unit (be it a castle attacker or a castle defender) is inside the castle walls if ( !attacker.isOutOfCastleWalls() ) { return false; } // penalty does not apply if both units are on the same side relative to the castle walls if ( attacker.isOutOfCastleWalls() == defender.isOutOfCastleWalls() ) { return false; } // penalty does not apply if the target unit is exposed due to the broken castle wall const std::vector points = GetLinePoints( attacker.GetBackPoint(), defender.GetBackPoint(), Cell::widthPx / 3 ); for ( std::vector::const_iterator it = points.begin(); it != points.end(); ++it ) { if ( ( 0 == board[CASTLE_FIRST_TOP_WALL_POS].GetObject() && ( board[CASTLE_FIRST_TOP_WALL_POS].GetPos() & *it ) ) || ( 0 == board[CASTLE_SECOND_TOP_WALL_POS].GetObject() && ( board[CASTLE_SECOND_TOP_WALL_POS].GetPos() & *it ) ) || ( 0 == board[CASTLE_THIRD_TOP_WALL_POS].GetObject() && ( board[CASTLE_THIRD_TOP_WALL_POS].GetPos() & *it ) ) || ( 0 == board[CASTLE_FOURTH_TOP_WALL_POS].GetObject() && ( board[CASTLE_FOURTH_TOP_WALL_POS].GetPos() & *it ) ) ) return false; } return true; } Battle::Force & Battle::Arena::GetForce1() const { return *_army1; } Battle::Force & Battle::Arena::GetForce2() const { return *_army2; } Battle::Force & Battle::Arena::getForce( const int color ) const { return ( _army1->GetColor() == color ) ? *_army1 : *_army2; } Battle::Force & Battle::Arena::getEnemyForce( const int color ) const { return ( _army1->GetColor() == color ) ? *_army2 : *_army1; } Battle::Force & Battle::Arena::GetCurrentForce() const { return getForce( GetCurrentColor() ); } Battle::Result & Battle::Arena::GetResult() { return result_game; } bool Battle::Arena::AutoCombatInProgress() const { if ( _currentUnit == nullptr ) { return false; } if ( _autoCombatColors & GetCurrentColor() ) { // Auto combat mode cannot be enabled for a player controlled by the AI assert( !( GetCurrentForce().GetControl() & CONTROL_AI ) ); return true; } return false; } bool Battle::Arena::EnemyOfAIHasAutoCombatInProgress() const { if ( _currentUnit == nullptr ) { return false; } if ( !( GetCurrentForce().GetControl() & CONTROL_AI ) ) { return false; } const Force & enemyForce = getEnemyForce( GetCurrentColor() ); if ( enemyForce.GetControl() & CONTROL_AI ) { return false; } return ( _autoCombatColors & enemyForce.GetColor() ); } bool Battle::Arena::CanToggleAutoCombat() const { if ( _currentUnit == nullptr ) { return false; } return !( GetCurrentForce().GetControl() & CONTROL_AI ); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_arena.h000066400000000000000000000373751476115357100225550ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include "battle.h" #include "battle_board.h" #include "battle_cell.h" #include "battle_command.h" #include "battle_grave.h" #include "battle_pathfinding.h" #include "icn.h" #include "spell.h" #include "spell_storage.h" class Army; class Artifact; class Castle; class HeroBase; namespace Rand { class DeterministicRandomGenerator; } namespace Battle { class Bridge; class Catapult; class Force; class Interface; class Status; class Tower; class Unit; class Units; enum class TowerType : uint8_t; enum class SiegeWeaponType { Catapult, EarthquakeSpell }; class Actions : public std::list {}; class TroopsUidGenerator { public: TroopsUidGenerator() = default; TroopsUidGenerator( const TroopsUidGenerator & ) = delete; TroopsUidGenerator & operator=( const TroopsUidGenerator & ) = delete; uint32_t GetUnique() { return _id++; } private: uint32_t _id{ 1 }; }; class Arena { public: Arena( Army & army1, Army & army2, const int32_t tileIndex, const bool isShowInterface, Rand::DeterministicRandomGenerator & randomGenerator ); Arena( const Arena & ) = delete; Arena( Arena && ) = delete; ~Arena(); Arena & operator=( const Arena & ) = delete; Arena & operator=( Arena && ) = delete; void Turns(); bool BattleValid() const; bool AutoCombatInProgress() const; bool EnemyOfAIHasAutoCombatInProgress() const; bool CanToggleAutoCombat() const; uint32_t GetTurnNumber() const { return _turnNumber; } Result & GetResult(); HeroBase * GetCommander1() const; HeroBase * GetCommander2() const; const HeroBase * getCommander( const int color ) const; const HeroBase * getEnemyCommander( const int color ) const; const HeroBase * GetCurrentCommander() const; Force & GetForce1() const; Force & GetForce2() const; Force & getForce( const int color ) const; Force & getEnemyForce( const int color ) const; Force & GetCurrentForce() const; int GetArmy1Color() const; int GetArmy2Color() const; int GetCurrentColor() const; // Returns the color of the army opposite to the army of the given color. If there is no army of the given color, // returns the color of the attacking army. int GetOppositeColor( const int col ) const; Unit * GetTroopBoard( int32_t ); const Unit * GetTroopBoard( int32_t ) const; Unit * GetTroopUID( uint32_t ); const Unit * GetTroopUID( uint32_t ) const; const SpellStorage & GetUsedSpells() const; bool DialogBattleSummary( const Result & res, const std::vector & artifacts, const bool allowToRestart ) const; int DialogBattleHero( HeroBase & hero, const bool buttons, Status & status ) const; static void DialogBattleNecromancy( const uint32_t raiseCount ); void FadeArena( bool clearMessageLog ) const; // Checks whether the given position is reachable for the given unit, either on the current turn or in principle bool isPositionReachable( const Unit & unit, const Position & position, const bool isOnCurrentTurn ) { return _battlePathfinder.isPositionReachable( unit, position, isOnCurrentTurn ); } // Returns the cost of moving to the given position for the given unit. It's the caller's responsibility to make // sure that this position is reachable before calling this method. uint32_t CalculateMoveCost( const Unit & unit, const Position & position ) { return _battlePathfinder.getCost( unit, position ); } // Returns the distance to the given position (i.e. the number of movements that need to be performed to get to // this position, the reversal of a wide unit is not considered as a movement) for the given unit. For flying // units, this distance is estimated as the straight line distance to the given position. It's the caller's // responsibility to make sure that this position is reachable before calling this method. uint32_t CalculateMoveDistance( const Unit & unit, const Position & position ) { return _battlePathfinder.getDistance( unit, position ); } // Returns the path (or its part) for the given unit to the given position that can be traversed during the // current turn. If this position is unreachable by this unit, then an empty path is returned. Indexes GetPath( const Unit & unit, const Position & position ); // Returns the indexes of all cells that can be occupied by the given unit's head on the current turn Indexes getAllAvailableMoves( const Unit & unit ) { return _battlePathfinder.getAllAvailableMoves( unit ); } // Returns the position on the path for the given unit to the given position, which is reachable on the current // turn and is as close as possible to the destination (excluding the current position of the unit). If the given // position is unreachable by the given unit, then an empty Position object is returned. Position getClosestReachablePosition( const Unit & unit, const Position & position ) { return _battlePathfinder.getClosestReachablePosition( unit, position ); } void ApplyAction( Command & ); // Returns a list of targets that will be affected by the given spell casted by the given hero and applied // to a cell with a given index. This method can be used by external code to evaluate the applicability of // a spell, and does not use probabilistic mechanisms to determine units resisting the given spell. TargetsInfo GetTargetsForSpell( const HeroBase * hero, const Spell & spell, const int32_t dst ) { return GetTargetsForSpell( hero, spell, dst, false, nullptr ); } bool isSpellcastDisabled() const; bool isDisableCastSpell( const Spell & spell, std::string * msg = nullptr ) const; bool isAbleToResurrectFromGraveyard( const int32_t index, const Spell & spell ) const; Indexes getCellsOccupiedByGraveyard() const; std::vector getGraveyardUnits( const int32_t index ) const; // Returns the unit that died last on the cell with the given index, or nullptr if there is no such unit. const Unit * getLastUnitFromGraveyard( const int32_t index ) const; // Returns the last dead unit on the cell with the given index, which can be potentially affected by any resurrection // spell during the current turn, or nullptr if there is no such unit. const Unit * getLastResurrectableUnitFromGraveyard( const int32_t index ) const; // Returns the last dead unit on the cell with the given index, which can be affected by the given resurrection spell // during the current turn, or nullptr if there is no such unit. Unit * getLastResurrectableUnitFromGraveyard( const int32_t index, const Spell & spell ) const; bool CanSurrenderOpponent( int color ) const; bool CanRetreatOpponent( int color ) const; bool IsShootingPenalty( const Unit &, const Unit & ) const; int GetICNCovr() const { return _covrIcnId; } int32_t GetFreePositionNearHero( const int heroColor ) const; static Board * GetBoard(); static Tower * GetTower( const TowerType type ); static Bridge * GetBridge(); static const Castle * GetCastle(); static Interface * GetInterface(); static Graveyard * GetGraveyard(); static bool isAnyTowerPresent(); enum { CATAPULT_POS = 77, CASTLE_GATE_POS = 50, CASTLE_FIRST_TOP_WALL_POS = 8, CASTLE_SECOND_TOP_WALL_POS = 29, CASTLE_THIRD_TOP_WALL_POS = 73, CASTLE_FOURTH_TOP_WALL_POS = 96, CASTLE_TOP_ARCHER_TOWER_POS = 19, CASTLE_BOTTOM_ARCHER_TOWER_POS = 85, CASTLE_TOP_GATE_TOWER_POS = 40, CASTLE_BOTTOM_GATE_TOWER_POS = 62 }; private: void UnitTurn( const Units & orderHistory ); void TowerAction( const Tower & ); void CatapultAction(); // Returns the remaining number of hitpoints of the given castle defense structure from the point of view of the given siege weapon. int getCastleDefenseStructureCondition( const CastleDefenseStructure target, const SiegeWeaponType siegeWeapon ) const; // Applies the specified damage to the given castle defense structure. It's the caller's responsibility to make sure that this defense // structure still has enough hitpoints. void applyDamageToCastleDefenseStructure( const CastleDefenseStructure target, const int damage ); TargetsInfo GetTargetsForDamage( const Unit & attacker, Unit & defender, const int32_t dst, const int dir ) const; TargetsInfo GetTargetsForSpell( const HeroBase * hero, const Spell & spell, const int32_t dst, bool applyRandomMagicResistance, bool * playResistSound ); static void TargetsApplyDamage( Unit & attacker, TargetsInfo & targets, uint32_t & resurrected ); static void TargetsApplySpell( const HeroBase * hero, const Spell & spell, TargetsInfo & targets ); TargetsInfo TargetsForChainLightning( const HeroBase * hero, const int32_t attackedTroopIndex, const bool applyRandomMagicResistance ); std::vector FindChainLightningTargetIndexes( const HeroBase * hero, Unit * firstUnit, const bool applyRandomMagicResistance ); void ApplyActionRetreat( const Command & cmd ); void ApplyActionSurrender( const Command & cmd ); void ApplyActionAttack( Command & cmd ); void ApplyActionMove( Command & cmd ); void ApplyActionSkip( Command & cmd ); void ApplyActionMorale( Command & cmd ); void ApplyActionSpellCast( Command & cmd ); void ApplyActionTower( Command & cmd ); void ApplyActionCatapult( Command & cmd ); void ApplyActionToggleAutoCombat( Command & cmd ); void ApplyActionQuickCombat( const Command & cmd ); void ApplyActionSpellSummonElemental( const Command & cmd, const Spell & spell ); void ApplyActionSpellMirrorImage( Command & cmd ); void ApplyActionSpellTeleport( Command & cmd ); void ApplyActionSpellEarthquake( const Command & cmd ); void ApplyActionSpellDefaults( Command & cmd, const Spell & spell ); // Moves the given unit to a position where the index of the head cell is equal to 'dst'. If 'dst' is -1, // then this method does nothing. Otherwise, it's the caller's responsibility to make sure that this position // is reachable for the given unit on the current turn before calling this method. void moveUnit( Unit * unit, const int32_t dst ); // Performs an actual attack of one unit (defender) by another unit (attacker), applying the attacker's // built-in magic, if necessary. If the specified index of the target cell of the attack (tgt) is negative, // then an attempt will be made to calculate it automatically based on the adjacency of the unit cells. If // the specified direction of the attack (dir) is negative, then an attempt will be made to calculate it // automatically. When an attack is made by firing a shot, the dir should be UNKNOWN (zero). void BattleProcess( Unit & attacker, Unit & defender, int32_t tgt = -1, int dir = -1 ); // Creates and returns a fully combat-ready elemental, which will be already placed on the board. It's // the caller's responsibility to make sure that a given spell is capable of creating an elemental // before calling this method. Unit * CreateElemental( const Spell & spell ); // Creates and returns a mirror image of a given unit. The returned mirror image will have an invalid // position, which should be updated separately. Unit * CreateMirrorImage( Unit & unit ); std::unique_ptr _army1; std::unique_ptr _army2; std::shared_ptr _orderOfUnits; // The unit that is currently active. Please note that some battle actions (e.g. catapult or castle tower shots) can be performed without an active unit. Unit * _currentUnit{ nullptr }; // The color of the army of the last unit that performed a full-fledged action (skipping a turn due to // bad morale is not considered as such). int _lastActiveUnitArmyColor{ -1 }; const Castle * castle; // Is the battle taking place in a town or a castle const bool _isTown; std::array, 3> _towers; std::unique_ptr _catapult; std::unique_ptr _bridge; std::unique_ptr _interface; Result result_game; Graveyard _graveyard; SpellStorage _usedSpells; Board board; BattlePathfinder _battlePathfinder; int _covrIcnId{ ICN::UNKNOWN }; uint32_t _turnNumber{ 0 }; // A set of colors of players for whom the auto combat mode is enabled int _autoCombatColors{ 0 }; // This random number generator should only be used in code that is equally used by both AI and the human // player - that is, in code related to the processing of battle commands. It cannot be safely used in other // places (for example, in code that performs situation assessment or AI decision-making) because in this // case the battles performed by AI will not be reproducible by a human player when performing exactly the // same actions. Rand::DeterministicRandomGenerator & _randomGenerator; TroopsUidGenerator _uidGenerator; enum { CHAIN_LIGHTNING_CREATURE_COUNT = 4 }; }; Arena * GetArena(); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_army.cpp000066400000000000000000000233521476115357100227600ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_army.h" #include #include #include "army_troop.h" #include "artifact.h" #include "artifact_info.h" #include "battle_arena.h" #include "battle_cell.h" #include "battle_troop.h" #include "heroes.h" #include "heroes_base.h" #include "monster_anim.h" #include "resource.h" #include "skill.h" namespace { const size_t unitSizeCapacity = 16; } Battle::Units::Units() { reserve( unitSizeCapacity ); } void Battle::Units::SortFastest() { // It is important to maintain the initial order of units having the same speed for the proper operation of the unit turn queue std::stable_sort( begin(), end(), Army::FastestTroop ); } Battle::Unit * Battle::Units::FindUID( const uint32_t uid ) const { const auto iter = std::find_if( begin(), end(), [uid]( const Unit * unit ) { return unit->isUID( uid ); } ); return iter == end() ? nullptr : *iter; } Battle::Unit * Battle::Units::FindMode( const uint32_t mod ) const { const auto iter = std::find_if( begin(), end(), [mod]( const Unit * unit ) { return unit->Modes( mod ); } ); return iter == end() ? nullptr : *iter; } Battle::Force::Force( Army & parent, bool opposite, TroopsUidGenerator & generator ) : army( parent ) { uids.reserve( army.Size() ); for ( size_t i = 0; i < army.Size(); ++i ) { const Troop * troop = army.GetTroop( i ); if ( troop == nullptr || !troop->isValid() ) { uids.push_back( 0 ); continue; } int32_t idx = army.isSpreadFormation() ? static_cast( i ) * 22 : 22 + static_cast( i ) * 11; if ( opposite ) { idx += ( troop->isWide() ? 9 : 10 ); } else if ( troop->isWide() ) { idx += 1; } Position pos; pos.Set( idx, troop->isWide(), opposite ); assert( pos.GetHead() != nullptr && ( troop->isWide() ? pos.GetTail() != nullptr : pos.GetTail() == nullptr ) ); push_back( new Unit( *troop, pos, opposite, generator.GetUnique() ) ); back()->SetArmy( army ); uids.push_back( back()->GetUID() ); } } Battle::Force::~Force() { std::for_each( begin(), end(), []( Unit * unit ) { assert( unit != nullptr ); delete unit; } ); } const HeroBase * Battle::Force::GetCommander() const { return army.GetCommander(); } HeroBase * Battle::Force::GetCommander() { return army.GetCommander(); } const Battle::Units & Battle::Force::getUnits() const { return *this; } int Battle::Force::GetColor() const { return army.GetColor(); } int Battle::Force::GetControl() const { return army.GetControl(); } bool Battle::Force::isValid( const bool considerBattlefieldArmy /* = true */ ) const { // Consider the state of the army on the battlefield (including resurrected units, summoned units, etc) if ( considerBattlefieldArmy ) { return std::any_of( begin(), end(), []( const Unit * unit ) { return unit->isValid(); } ); } // Consider only the state of the original army for ( size_t index = 0; index < army.Size(); ++index ) { const Troop * troop = army.GetTroop( index ); if ( troop == nullptr || !troop->isValid() ) { continue; } const Unit * unit = FindUID( uids.at( index ) ); if ( unit == nullptr || unit->GetDead() >= unit->GetInitialCount() ) { continue; } return true; } return false; } uint32_t Battle::Force::GetSurrenderCost() const { double result = 0.0; // Consider only the units from the original army for ( size_t index = 0; index < army.Size(); ++index ) { const Troop * troop = army.GetTroop( index ); if ( troop == nullptr || !troop->isValid() ) { continue; } const Unit * unit = FindUID( uids.at( index ) ); if ( unit == nullptr || !unit->isValid() ) { continue; } result += unit->GetSurrenderCost().gold; } const HeroBase * commander = GetCommander(); if ( commander ) { const std::vector costReductionPercent = commander->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::SURRENDER_COST_REDUCTION_PERCENT ); double mod = 0.5; if ( !costReductionPercent.empty() ) { mod = 1; for ( const int32_t value : costReductionPercent ) { mod = mod * value / 100; } } const int diplomacyLevel = commander->GetLevelSkill( Skill::Secondary::DIPLOMACY ); if ( diplomacyLevel > Skill::Level::NONE ) { // The modifier is always multiplied by two, normally to negate the 0.5 modifier from regular surrender, but also when there are // artifacts present, even if the 0.5 modifier for normal surrender already has been negated by setting mod = 1. mod *= 2; mod *= ( Skill::GetDiplomacySurrenderCostDiscount( commander->GetLevelSkill( Skill::Secondary::DIPLOMACY ) ) / 100.0 ); } result *= mod; } // Total cost should always be at least 1 gold return result >= 1 ? static_cast( result + 0.5 ) : 1; } void Battle::Force::NewTurn() { if ( GetCommander() ) GetCommander()->ResetModes( Heroes::SPELLCASTED ); std::for_each( begin(), end(), []( Unit * unit ) { unit->NewTurn(); } ); } Troops Battle::Force::GetKilledTroops() const { Troops result; for ( const Unit * unit : *this ) { assert( unit != nullptr ); result.PushBack( *unit, std::min( unit->GetInitialCount(), unit->GetDead() ) ); } return result; } bool Battle::Force::animateIdleUnits() const { bool redrawNeeded = false; for ( Unit * unit : *this ) { // Check if unit is alive. if ( unit->isValid() ) { if ( unit->isIdling() ) { // Go to 'STATIC' animation state if idle animation is over or if unit is blinded or paralyzed. if ( unit->isFinishAnimFrame() || unit->isImmovable() ) { redrawNeeded = unit->SwitchAnimation( Monster_Info::STATIC ) || redrawNeeded; } else { unit->IncreaseAnimFrame(); redrawNeeded = true; } } // checkIdleDelay() sets and checks unit's internal timer if we're ready to switch to next one. // Do not start idle animations for paralyzed or blinded units. else if ( unit->GetAnimationState() == Monster_Info::STATIC && !unit->isImmovable() && unit->checkIdleDelay() ) { redrawNeeded = unit->SwitchAnimation( Monster_Info::IDLE ) || redrawNeeded; } } } return redrawNeeded; } void Battle::Force::resetIdleAnimation() const { for ( Unit * unit : *this ) { // Check if unit is alive, not paralyzed or blinded and is in 'STATIC' animation state. if ( unit->isValid() && unit->GetAnimationState() == Monster_Info::STATIC && !unit->isImmovable() ) { unit->checkIdleDelay(); } } } bool Battle::Force::HasMonster( const Monster & mons ) const { return std::any_of( begin(), end(), [&mons]( const Unit * unit ) { return unit->isMonster( mons.GetID() ); } ); } uint32_t Battle::Force::GetDeadCounts() const { uint32_t res = 0; for ( const_iterator it = begin(); it != end(); ++it ) res += ( *it )->GetDead(); return res; } uint32_t Battle::Force::GetDeadHitPoints() const { uint32_t res = 0; for ( const_iterator it = begin(); it != end(); ++it ) { res += static_cast( *it )->GetHitPoints() * ( *it )->GetDead(); } return res; } void Battle::Force::SyncArmyCount() { for ( uint32_t index = 0; index < army.Size(); ++index ) { Troop * troop = army.GetTroop( index ); if ( troop == nullptr || !troop->isValid() ) { continue; } const Unit * unit = FindUID( uids.at( index ) ); if ( unit == nullptr ) { continue; } troop->SetCount( unit->GetDead() > unit->GetInitialCount() ? 0 : unit->GetInitialCount() - unit->GetDead() ); } } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_army.h000066400000000000000000000137021476115357100224230ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include "army.h" #include "battle_troop.h" #include "bitmodes.h" #include "monster.h" class HeroBase; namespace Battle { class TroopsUidGenerator; class Units : public std::vector { public: enum class FilterType { REMOVE_INVALID_UNITS, REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT, REMOVE_INVALID_UNITS_AND_UNITS_THAT_CHANGED_SIDES }; static constexpr std::integral_constant REMOVE_INVALID_UNITS{}; static constexpr std::integral_constant REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT{}; static constexpr std::integral_constant REMOVE_INVALID_UNITS_AND_UNITS_THAT_CHANGED_SIDES{}; Units(); // Creates a shallow copy of 'units' (only pointers are copied) by applying a filter according to the specified tag template Units( const Units & units, std::integral_constant /* tag */, const Types... params ) { reserve( units.size() ); const auto filterPredicateGenerator = []( const auto... filterParams ) { if constexpr ( filterType == FilterType::REMOVE_INVALID_UNITS ) { static_assert( sizeof...( filterParams ) == 0 ); return []( const Unit * unit ) { assert( unit != nullptr ); return unit->isValid(); }; } else if constexpr ( filterType == FilterType::REMOVE_INVALID_UNITS_AND_SPECIFIED_UNIT ) { static_assert( sizeof...( filterParams ) == 1 ); return [unitToRemove = std::get<0>( std::tie( filterParams... ) )]( const Unit * unit ) { assert( unit != nullptr ); return unit->isValid() && unit != unitToRemove; }; } else if constexpr ( filterType == FilterType::REMOVE_INVALID_UNITS_AND_UNITS_THAT_CHANGED_SIDES ) { static_assert( sizeof...( filterParams ) == 0 ); return []( const Unit * unit ) { assert( unit != nullptr ); return unit->isValid() && unit->GetColor() == unit->GetCurrentColor(); }; } else { // The build should fail because this lambda does not meet the requirements of UnaryPredicate return []() { assert( 0 ); }; } }; std::copy_if( units.begin(), units.end(), std::back_inserter( *this ), filterPredicateGenerator( params... ) ); } Units( const Units & ) = delete; virtual ~Units() = default; Units & operator=( const Units & ) = delete; Unit * FindMode( const uint32_t mod ) const; Unit * FindUID( const uint32_t uid ) const; void SortFastest(); }; class Force : public Units, public BitModes { public: Force( Army & parent, bool opposite, TroopsUidGenerator & generator ); Force( const Force & ) = delete; ~Force() override; Force & operator=( const Force & ) = delete; HeroBase * GetCommander(); const HeroBase * GetCommander() const; const Units & getUnits() const; bool isValid( const bool considerBattlefieldArmy = true ) const; bool HasMonster( const Monster & ) const; uint32_t GetDeadHitPoints() const; uint32_t GetDeadCounts() const; int GetColor() const; int GetControl() const; // Returns the cost of surrender (in units of gold) for the current army on the battlefield uint32_t GetSurrenderCost() const; Troops GetKilledTroops() const; bool animateIdleUnits() const; void resetIdleAnimation() const; void NewTurn(); void SyncArmyCount(); private: Army & army; std::vector uids; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_board.cpp000066400000000000000000000722021476115357100230750ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_board.h" #include #include #include #include #include #include #include #include "battle_arena.h" #include "battle_bridge.h" #include "battle_troop.h" #include "castle.h" #include "game_static.h" #include "ground.h" #include "icn.h" #include "maps_tiles.h" #include "mp2.h" #include "rand.h" #include "tools.h" #include "translations.h" namespace { uint32_t GetRandomObstaclePosition( std::mt19937 & gen ) { return Rand::GetWithGen( 2, 8, gen ) + ( 11 * Rand::GetWithGen( 0, 8, gen ) ); } bool isTwoHexObject( const int icnId ) { switch ( icnId ) { case ICN::COBJ0004: case ICN::COBJ0005: case ICN::COBJ0007: case ICN::COBJ0011: case ICN::COBJ0014: case ICN::COBJ0015: case ICN::COBJ0017: case ICN::COBJ0018: case ICN::COBJ0019: case ICN::COBJ0020: case ICN::COBJ0022: case ICN::COBJ0030: case ICN::COBJ0031: return true; default: break; } return false; } bool isTallObject( const int icnId ) { switch ( icnId ) { case ICN::COBJ0002: case ICN::COBJ0009: case ICN::COBJ0013: case ICN::COBJ0021: case ICN::COBJ0027: case ICN::COBJ0028: case ICN::COBJ0031: return true; default: break; } return false; } } Battle::Board::Board() { reserve( sizeInCells ); for ( int i = 0; i < sizeInCells; ++i ) { emplace_back( i ); } } void Battle::Board::SetArea( const fheroes2::Rect & area ) { std::for_each( begin(), end(), [&area]( Cell & cell ) { cell.SetArea( area ); } ); } void Battle::Board::removeDeadUnits() { for ( Cell & cell : *this ) { Unit * unit = cell.GetUnit(); if ( unit && !unit->isValid() ) { unit->PostKilledAction(); } } } uint32_t Battle::Board::GetDistance( const int32_t index1, const int32_t index2 ) { if ( !isValidIndex( index1 ) || !isValidIndex( index2 ) ) { return 0; } const int32_t x1 = index1 % widthInCells; const int32_t y1 = index1 / widthInCells; const int32_t x2 = index2 % widthInCells; const int32_t y2 = index2 / widthInCells; const int32_t du = y2 - y1; const int32_t dv = ( x2 + y2 / 2 ) - ( x1 + y1 / 2 ); if ( ( du >= 0 && dv >= 0 ) || ( du < 0 && dv < 0 ) ) { return std::max( std::abs( du ), std::abs( dv ) ); } return std::abs( du ) + std::abs( dv ); } uint32_t Battle::Board::GetDistance( const Position & pos1, const Position & pos2 ) { if ( pos1.GetHead() == nullptr || pos2.GetHead() == nullptr ) { return 0; } const int32_t head1Idx = pos1.GetHead()->GetIndex(); const int32_t tail1Idx = pos1.GetTail() ? pos1.GetTail()->GetIndex() : -1; const int32_t head2Idx = pos2.GetHead()->GetIndex(); const int32_t tail2Idx = pos2.GetTail() ? pos2.GetTail()->GetIndex() : -1; uint32_t distance = Board::GetDistance( head1Idx, head2Idx ); if ( tail2Idx != -1 ) { distance = std::min( distance, Board::GetDistance( head1Idx, tail2Idx ) ); } if ( tail1Idx != -1 ) { distance = std::min( distance, Board::GetDistance( tail1Idx, head2Idx ) ); if ( tail2Idx != -1 ) { distance = std::min( distance, Board::GetDistance( tail1Idx, tail2Idx ) ); } } return distance; } uint32_t Battle::Board::GetDistance( const Position & pos, const int32_t index ) { if ( pos.GetHead() == nullptr || !isValidIndex( index ) ) { return 0; } const int32_t headIdx = pos.GetHead()->GetIndex(); const int32_t tailIdx = pos.GetTail() ? pos.GetTail()->GetIndex() : -1; uint32_t distance = Board::GetDistance( headIdx, index ); if ( tailIdx != -1 ) { distance = std::min( distance, Board::GetDistance( tailIdx, index ) ); } return distance; } std::vector Battle::Board::GetNearestTroops( const Unit * startUnit, const std::vector & blackList ) { std::vector> foundUnits; for ( Cell & cell : *this ) { Unit * cellUnit = cell.GetUnit(); if ( cellUnit == nullptr || startUnit == cellUnit || cell.GetIndex() != cellUnit->GetHeadIndex() ) { continue; } const bool isBlackListed = std::find( blackList.begin(), blackList.end(), cellUnit ) != blackList.end(); if ( !isBlackListed ) { foundUnits.emplace_back( cellUnit, GetDistance( startUnit->GetPosition(), cellUnit->GetPosition() ) ); } } std::sort( foundUnits.begin(), foundUnits.end(), []( const std::pair & first, const std::pair & second ) { return first.second < second.second; } ); std::vector units; units.reserve( foundUnits.size() ); for ( const auto & foundUnit : foundUnits ) { units.push_back( foundUnit.first ); } return units; } int Battle::Board::GetDirection( const int32_t index1, const int32_t index2 ) { if ( !isValidIndex( index1 ) || !isValidIndex( index2 ) ) { return UNKNOWN; } if ( index1 == index2 ) { return CENTER; } for ( CellDirection dir = TOP_LEFT; dir < CENTER; ++dir ) { if ( isValidDirection( index1, dir ) && index2 == GetIndexDirection( index1, dir ) ) { return dir; } } return UNKNOWN; } bool Battle::Board::isNearIndexes( const int32_t index1, const int32_t index2 ) { return index1 != index2 && UNKNOWN != GetDirection( index1, index2 ); } int Battle::Board::GetReflectDirection( const int dir ) { switch ( dir ) { case TOP_LEFT: return BOTTOM_RIGHT; case TOP_RIGHT: return BOTTOM_LEFT; case LEFT: return RIGHT; case RIGHT: return LEFT; case BOTTOM_LEFT: return TOP_RIGHT; case BOTTOM_RIGHT: return TOP_LEFT; default: break; } return UNKNOWN; } uint32_t Battle::Board::GetDistanceFromBoardEdgeAlongXAxis( const int32_t index, const bool fromRightEdge ) { assert( isValidIndex( index ) ); const uint32_t x = index % widthInCells; return ( fromRightEdge ? widthInCells - x : x + 1 ); } bool Battle::Board::isValidDirection( const int32_t index, const int dir ) { if ( !isValidIndex( index ) ) { return false; } const int32_t x = index % widthInCells; const int32_t y = index / widthInCells; switch ( dir ) { case CENTER: return true; case TOP_LEFT: return !( 0 == y || ( 0 == x && ( y % 2 ) ) ); case TOP_RIGHT: return !( 0 == y || ( ( widthInCells - 1 ) == x && !( y % 2 ) ) ); case LEFT: return !( 0 == x ); case RIGHT: return !( ( widthInCells - 1 ) == x ); case BOTTOM_LEFT: return !( ( heightInCells - 1 ) == y || ( 0 == x && ( y % 2 ) ) ); case BOTTOM_RIGHT: return !( ( heightInCells - 1 ) == y || ( ( widthInCells - 1 ) == x && !( y % 2 ) ) ); default: break; } return false; } int32_t Battle::Board::GetIndexDirection( const int32_t index, const int dir ) { if ( !isValidIndex( index ) ) { return -1; } const int32_t y = index / widthInCells; switch ( dir ) { case CENTER: return index; case TOP_LEFT: return index - ( ( y % 2 ) ? widthInCells + 1 : widthInCells ); case TOP_RIGHT: return index - ( ( y % 2 ) ? widthInCells : widthInCells - 1 ); case LEFT: return index - 1; case RIGHT: return index + 1; case BOTTOM_LEFT: return index + ( ( y % 2 ) ? widthInCells - 1 : widthInCells ); case BOTTOM_RIGHT: return index + ( ( y % 2 ) ? widthInCells : widthInCells + 1 ); default: break; } return -1; } int32_t Battle::Board::GetIndexAbsPosition( const fheroes2::Point & pt ) const { const_iterator it = begin(); for ( ; it != end(); ++it ) if ( ( *it ).isPositionIncludePoint( pt ) ) break; return it != end() ? ( *it ).GetIndex() : -1; } bool Battle::Board::isValidIndex( const int32_t index ) { return 0 <= index && index < sizeInCells; } bool Battle::Board::isCastleIndex( const int32_t index ) { return ( ( 8 <= index && index <= 10 ) || ( 19 < index && index <= 21 ) || ( 29 <= index && index <= 32 ) || ( 40 < index && index <= 43 ) || ( 50 < index && index <= 54 ) || ( 62 < index && index <= 65 ) || ( 73 <= index && index <= 76 ) || ( 85 < index && index <= 87 ) || ( 96 <= index && index <= 98 ) ); } bool Battle::Board::isOutOfWallsIndex( const int32_t index ) { return ( ( index <= 8 ) || ( 11 <= index && index <= 19 ) || ( 22 <= index && index <= 29 ) || ( 33 <= index && index <= 40 ) || ( 44 <= index && index <= 50 ) || ( 55 <= index && index <= 62 ) || ( 66 <= index && index <= 73 ) || ( 77 <= index && index <= 85 ) || ( 88 <= index && index <= 96 ) ); } bool Battle::Board::isMoatIndex( const int32_t index, const Unit & unit ) { switch ( index ) { case 7: case 18: case 28: case 39: case 61: case 72: case 84: case 95: return true; case 49: { const Bridge * bridge = Arena::GetBridge(); return unit.isFlying() || bridge == nullptr || !bridge->isPassable( unit ); } default: break; } return false; } void Battle::Board::SetCobjObjects( const Maps::Tile & tile, std::mt19937 & gen ) { std::vector objs; if ( tile.getMainObjectType( false ) == MP2::OBJ_GRAVEYARD ) { objs.push_back( ICN::COBJ0000 ); objs.push_back( ICN::COBJ0001 ); objs.push_back( ICN::COBJ0025 ); } else { switch ( tile.GetGround() ) { case Maps::Ground::DESERT: objs.push_back( ICN::COBJ0009 ); objs.push_back( ICN::COBJ0024 ); break; case Maps::Ground::SNOW: objs.push_back( ICN::COBJ0022 ); objs.push_back( ICN::COBJ0026 ); break; case Maps::Ground::SWAMP: objs.push_back( ICN::COBJ0005 ); objs.push_back( ICN::COBJ0006 ); objs.push_back( ICN::COBJ0007 ); objs.push_back( ICN::COBJ0008 ); objs.push_back( ICN::COBJ0011 ); objs.push_back( ICN::COBJ0012 ); objs.push_back( ICN::COBJ0014 ); objs.push_back( ICN::COBJ0015 ); objs.push_back( ICN::COBJ0016 ); objs.push_back( ICN::COBJ0017 ); objs.push_back( ICN::COBJ0027 ); break; case Maps::Ground::BEACH: objs.push_back( ICN::COBJ0005 ); objs.push_back( ICN::COBJ0011 ); objs.push_back( ICN::COBJ0017 ); break; case Maps::Ground::DIRT: objs.push_back( ICN::COBJ0002 ); objs.push_back( ICN::COBJ0005 ); objs.push_back( ICN::COBJ0007 ); objs.push_back( ICN::COBJ0011 ); objs.push_back( ICN::COBJ0014 ); objs.push_back( ICN::COBJ0019 ); objs.push_back( ICN::COBJ0027 ); break; case Maps::Ground::GRASS: objs.push_back( ICN::COBJ0002 ); objs.push_back( ICN::COBJ0004 ); objs.push_back( ICN::COBJ0005 ); objs.push_back( ICN::COBJ0008 ); objs.push_back( ICN::COBJ0011 ); objs.push_back( ICN::COBJ0012 ); objs.push_back( ICN::COBJ0014 ); objs.push_back( ICN::COBJ0015 ); objs.push_back( ICN::COBJ0019 ); objs.push_back( ICN::COBJ0027 ); objs.push_back( ICN::COBJ0028 ); break; case Maps::Ground::WASTELAND: objs.push_back( ICN::COBJ0009 ); objs.push_back( ICN::COBJ0013 ); objs.push_back( ICN::COBJ0018 ); objs.push_back( ICN::COBJ0020 ); objs.push_back( ICN::COBJ0021 ); objs.push_back( ICN::COBJ0024 ); break; case Maps::Ground::LAVA: objs.push_back( ICN::COBJ0007 ); objs.push_back( ICN::COBJ0029 ); objs.push_back( ICN::COBJ0031 ); break; case Maps::Ground::WATER: objs.push_back( ICN::COBJ0003 ); objs.push_back( ICN::COBJ0010 ); objs.push_back( ICN::COBJ0023 ); break; default: break; } } Rand::ShuffleWithGen( objs, gen ); const auto largeObstacleHexCount = std::count_if( begin(), end(), []( const Cell & cell ) { return cell.GetObject() == 0x40; } ); uint8_t maxSmallObstacleCount = 0; uint8_t maxTwoHexObstacleCount = 0; if ( largeObstacleHexCount == 0 ) { maxSmallObstacleCount = 6; maxTwoHexObstacleCount = 3; } else if ( largeObstacleHexCount <= 7 ) { maxSmallObstacleCount = 4; maxTwoHexObstacleCount = 2; } else if ( largeObstacleHexCount <= 13 ) { maxSmallObstacleCount = 3; maxTwoHexObstacleCount = 2; } else { maxSmallObstacleCount = 2; maxTwoHexObstacleCount = 1; } // Limit the number of two-hex obstacles to maxTwoHexObstacleCount uint8_t twoHexCount = 0; for ( auto iter = objs.begin(); iter != objs.end(); ) { if ( isTwoHexObject( *iter ) ) { ++twoHexCount; if ( twoHexCount > maxTwoHexObstacleCount ) { iter = objs.erase( iter ); continue; } } ++iter; } const size_t objectsToPlace = std::min( objs.size(), static_cast( Rand::GetWithGen( 0, maxSmallObstacleCount, gen ) ) ); for ( size_t i = 0; i < objectsToPlace; ++i ) { // two-hex obstacles are not allowed on column 8 as they would cover column 9 which is reserved for units const bool checkRightCell = isTwoHexObject( objs[i] ); // tall obstacles like trees should not be placed on top 2 rows const bool isTallObstacle = isTallObject( objs[i] ); uint32_t dest; do { dest = GetRandomObstaclePosition( gen ); } while ( at( dest ).GetObject() != 0 || ( checkRightCell && ( at( dest + 1 ).GetObject() != 0 || ( dest % widthInCells ) == 8 ) ) || ( isTallObstacle && dest < ( widthInCells * 2 ) ) ); SetCobjObject( objs[i], dest ); } } void Battle::Board::SetCobjObject( const int icn, const uint32_t dst ) { at( dst ).SetObject( 0x80 + ( icn - ICN::COBJ0000 ) ); if ( isTwoHexObject( icn ) ) { assert( at( dst + 1 ).GetObject() == 0 ); at( dst + 1 ).SetObject( 0x40 ); } } void Battle::Board::SetCovrObjects( int icn ) { switch ( icn ) { case ICN::COVR0001: case ICN::COVR0007: case ICN::COVR0013: case ICN::COVR0019: at( 25 ).SetObject( 0x40 ); at( 26 ).SetObject( 0x40 ); at( 27 ).SetObject( 0x40 ); at( 28 ).SetObject( 0x40 ); at( 40 ).SetObject( 0x40 ); at( 51 ).SetObject( 0x40 ); break; case ICN::COVR0002: case ICN::COVR0008: case ICN::COVR0014: case ICN::COVR0020: at( 47 ).SetObject( 0x40 ); at( 48 ).SetObject( 0x40 ); at( 49 ).SetObject( 0x40 ); at( 50 ).SetObject( 0x40 ); at( 51 ).SetObject( 0x40 ); break; case ICN::COVR0003: case ICN::COVR0015: case ICN::COVR0021: at( 35 ).SetObject( 0x40 ); at( 41 ).SetObject( 0x40 ); at( 46 ).SetObject( 0x40 ); at( 47 ).SetObject( 0x40 ); at( 48 ).SetObject( 0x40 ); at( 49 ).SetObject( 0x40 ); at( 50 ).SetObject( 0x40 ); at( 51 ).SetObject( 0x40 ); break; case ICN::COVR0009: at( 35 ).SetObject( 0x40 ); at( 40 ).SetObject( 0x40 ); at( 46 ).SetObject( 0x40 ); at( 47 ).SetObject( 0x40 ); at( 48 ).SetObject( 0x40 ); at( 49 ).SetObject( 0x40 ); at( 50 ).SetObject( 0x40 ); break; case ICN::COVR0004: case ICN::COVR0010: case ICN::COVR0016: case ICN::COVR0022: at( 41 ).SetObject( 0x40 ); at( 51 ).SetObject( 0x40 ); at( 58 ).SetObject( 0x40 ); at( 59 ).SetObject( 0x40 ); at( 60 ).SetObject( 0x40 ); at( 61 ).SetObject( 0x40 ); at( 62 ).SetObject( 0x40 ); break; case ICN::COVR0005: case ICN::COVR0017: at( 24 ).SetObject( 0x40 ); at( 25 ).SetObject( 0x40 ); at( 26 ).SetObject( 0x40 ); at( 27 ).SetObject( 0x40 ); at( 28 ).SetObject( 0x40 ); at( 29 ).SetObject( 0x40 ); at( 30 ).SetObject( 0x40 ); at( 58 ).SetObject( 0x40 ); at( 59 ).SetObject( 0x40 ); at( 60 ).SetObject( 0x40 ); at( 61 ).SetObject( 0x40 ); at( 62 ).SetObject( 0x40 ); at( 63 ).SetObject( 0x40 ); at( 68 ).SetObject( 0x40 ); at( 74 ).SetObject( 0x40 ); break; case ICN::COVR0006: case ICN::COVR0018: at( 14 ).SetObject( 0x40 ); at( 15 ).SetObject( 0x40 ); at( 16 ).SetObject( 0x40 ); at( 17 ).SetObject( 0x40 ); at( 18 ).SetObject( 0x40 ); at( 24 ).SetObject( 0x40 ); at( 68 ).SetObject( 0x40 ); at( 80 ).SetObject( 0x40 ); at( 81 ).SetObject( 0x40 ); at( 82 ).SetObject( 0x40 ); at( 83 ).SetObject( 0x40 ); at( 84 ).SetObject( 0x40 ); break; case ICN::COVR0011: case ICN::COVR0023: at( 15 ).SetObject( 0x40 ); at( 25 ).SetObject( 0x40 ); at( 36 ).SetObject( 0x40 ); at( 51 ).SetObject( 0x40 ); at( 62 ).SetObject( 0x40 ); at( 71 ).SetObject( 0x40 ); at( 72 ).SetObject( 0x40 ); break; case ICN::COVR0012: case ICN::COVR0024: at( 18 ).SetObject( 0x40 ); at( 29 ).SetObject( 0x40 ); at( 41 ).SetObject( 0x40 ); at( 59 ).SetObject( 0x40 ); at( 70 ).SetObject( 0x40 ); at( 82 ).SetObject( 0x40 ); at( 83 ).SetObject( 0x40 ); break; default: break; } } Battle::Cell * Battle::Board::GetCell( const int32_t position, const int dir /* = CENTER */ ) { if ( !isValidDirection( position, dir ) ) { return nullptr; } Board * board = Arena::GetBoard(); assert( board != nullptr ); const int32_t idx = GetIndexDirection( position, dir ); assert( isValidIndex( idx ) ); return &board->at( idx ); } Battle::Indexes Battle::Board::GetMoveWideIndexes( const int32_t head, const bool reflect ) { if ( !isValidIndex( head ) ) { return {}; } Indexes result; result.reserve( 4 ); if ( isValidDirection( head, LEFT ) ) { result.push_back( GetIndexDirection( head, LEFT ) ); } if ( isValidDirection( head, RIGHT ) ) { result.push_back( GetIndexDirection( head, RIGHT ) ); } if ( reflect ) { if ( isValidDirection( head, TOP_LEFT ) ) { result.push_back( GetIndexDirection( head, TOP_LEFT ) ); } if ( isValidDirection( head, BOTTOM_LEFT ) ) { result.push_back( GetIndexDirection( head, BOTTOM_LEFT ) ); } } else { if ( isValidDirection( head, TOP_RIGHT ) ) { result.push_back( GetIndexDirection( head, TOP_RIGHT ) ); } if ( isValidDirection( head, BOTTOM_RIGHT ) ) { result.push_back( GetIndexDirection( head, BOTTOM_RIGHT ) ); } } return result; } Battle::Indexes Battle::Board::GetAroundIndexes( const int32_t center ) { if ( !isValidIndex( center ) ) { return {}; } Indexes result; result.reserve( 6 ); for ( CellDirection dir = TOP_LEFT; dir < CENTER; ++dir ) { if ( !isValidDirection( center, dir ) ) { continue; } result.push_back( GetIndexDirection( center, dir ) ); } return result; } Battle::Indexes Battle::Board::GetAroundIndexes( const Unit & unit ) { return GetAroundIndexes( unit.GetPosition() ); } Battle::Indexes Battle::Board::GetAroundIndexes( const Position & pos ) { if ( pos.GetHead() == nullptr ) { return {}; } const int32_t headIdx = pos.GetHead()->GetIndex(); if ( pos.GetTail() == nullptr ) { return GetAroundIndexes( headIdx ); } const int32_t tailIdx = pos.GetTail()->GetIndex(); if ( !isValidIndex( headIdx ) || !isValidIndex( tailIdx ) ) { return {}; } Indexes result; result.reserve( 8 ); // Traversing cells in a clockwise direction if ( headIdx > tailIdx ) { if ( isValidDirection( tailIdx, TOP_LEFT ) ) { result.push_back( GetIndexDirection( tailIdx, TOP_LEFT ) ); } if ( isValidDirection( tailIdx, TOP_RIGHT ) ) { result.push_back( GetIndexDirection( tailIdx, TOP_RIGHT ) ); } if ( isValidDirection( headIdx, TOP_RIGHT ) ) { result.push_back( GetIndexDirection( headIdx, TOP_RIGHT ) ); } if ( isValidDirection( headIdx, RIGHT ) ) { result.push_back( GetIndexDirection( headIdx, RIGHT ) ); } if ( isValidDirection( headIdx, BOTTOM_RIGHT ) ) { result.push_back( GetIndexDirection( headIdx, BOTTOM_RIGHT ) ); } if ( isValidDirection( tailIdx, BOTTOM_RIGHT ) ) { result.push_back( GetIndexDirection( tailIdx, BOTTOM_RIGHT ) ); } if ( isValidDirection( tailIdx, BOTTOM_LEFT ) ) { result.push_back( GetIndexDirection( tailIdx, BOTTOM_LEFT ) ); } if ( isValidDirection( tailIdx, LEFT ) ) { result.push_back( GetIndexDirection( tailIdx, LEFT ) ); } } else if ( headIdx < tailIdx ) { if ( isValidDirection( headIdx, TOP_LEFT ) ) { result.push_back( GetIndexDirection( headIdx, TOP_LEFT ) ); } if ( isValidDirection( headIdx, TOP_RIGHT ) ) { result.push_back( GetIndexDirection( headIdx, TOP_RIGHT ) ); } if ( isValidDirection( tailIdx, TOP_RIGHT ) ) { result.push_back( GetIndexDirection( tailIdx, TOP_RIGHT ) ); } if ( isValidDirection( tailIdx, RIGHT ) ) { result.push_back( GetIndexDirection( tailIdx, RIGHT ) ); } if ( isValidDirection( tailIdx, BOTTOM_RIGHT ) ) { result.push_back( GetIndexDirection( tailIdx, BOTTOM_RIGHT ) ); } if ( isValidDirection( headIdx, BOTTOM_RIGHT ) ) { result.push_back( GetIndexDirection( headIdx, BOTTOM_RIGHT ) ); } if ( isValidDirection( headIdx, BOTTOM_LEFT ) ) { result.push_back( GetIndexDirection( headIdx, BOTTOM_LEFT ) ); } if ( isValidDirection( headIdx, LEFT ) ) { result.push_back( GetIndexDirection( headIdx, LEFT ) ); } } return result; } Battle::Indexes Battle::Board::GetDistanceIndexes( const int32_t center, const uint32_t radius ) { if ( !isValidIndex( center ) ) { return {}; } const int32_t centerX = center % widthInCells; const int32_t centerY = center / widthInCells; // Axial coordinates const int32_t centerQ = centerX - ( centerY + ( centerY % 2 ) ) / 2; const int32_t centerR = centerY; Indexes result; result.reserve( 3 * radius * ( radius + 1 ) + 1 ); const int32_t intRadius = radius; for ( int32_t dq = -intRadius; dq <= intRadius; ++dq ) { for ( int32_t dr = std::max( -intRadius, -intRadius - dq ); dr <= std::min( intRadius, intRadius - dq ); ++dr ) { // Center should not be included if ( dq == 0 && dr == 0 ) { continue; } const int32_t q = centerQ + dq; const int32_t r = centerR + dr; const int32_t x = q + ( r + ( r % 2 ) ) / 2; const int32_t y = r; if ( x < 0 || x >= widthInCells || y < 0 || y >= heightInCells ) { continue; } const int32_t idx = y * widthInCells + x; assert( isValidIndex( idx ) ); result.push_back( idx ); } } return result; } Battle::Indexes Battle::Board::GetDistanceIndexes( const Position & pos, const uint32_t radius ) { const std::array posIndexes = { pos.GetHead() ? pos.GetHead()->GetIndex() : -1, pos.GetTail() ? pos.GetTail()->GetIndex() : -1 }; std::set boardIndexes; for ( const int32_t posIdx : posIndexes ) { if ( !Board::isValidIndex( posIdx ) ) { continue; } for ( const int32_t idx : Board::GetDistanceIndexes( posIdx, radius ) ) { assert( Board::isValidIndex( idx ) ); if ( std::find( posIndexes.begin(), posIndexes.end(), idx ) != posIndexes.end() ) { continue; } boardIndexes.insert( idx ); } } Indexes result; result.reserve( boardIndexes.size() ); result.assign( boardIndexes.begin(), boardIndexes.end() ); return result; } Battle::Indexes Battle::Board::GetDistanceIndexes( const Unit & unit, const uint32_t radius ) { return GetDistanceIndexes( unit.GetPosition(), radius ); } bool Battle::Board::isValidMirrorImageIndex( const int32_t index, const Unit * unit ) { if ( unit == nullptr ) { return false; } const Position mirrorPos = Position::GetPosition( *unit, index ); if ( !mirrorPos.isValidForUnit( unit ) ) { return false; } if ( unit->GetPosition().contains( mirrorPos.GetHead()->GetIndex() ) ) { return false; } if ( unit->isWide() && unit->GetPosition().contains( mirrorPos.GetTail()->GetIndex() ) ) { return false; } return true; } bool Battle::Board::CanAttackFromCell( const Unit & unit, const int32_t from ) { const Position pos = Position::GetReachable( unit, from ); // Target unit cannot be attacked if out of reach if ( pos.GetHead() == nullptr ) { return false; } assert( pos.isValidForUnit( unit ) ); const Castle * castle = Arena::GetCastle(); // No moat - no further restrictions if ( !castle || !castle->isBuild( BUILD_MOAT ) ) { return true; } // Target unit isn't attacked from the moat if ( !isMoatIndex( from, unit ) ) { return true; } // The moat doesn't stop flying units if ( unit.isFlying() ) { return true; } // Attacker is already near the target if ( from == unit.GetHeadIndex() || ( unit.isWide() && from == unit.GetTailIndex() ) ) { return true; } // In all other cases, the attack is prohibited return false; } bool Battle::Board::CanAttackTargetFromPosition( const Unit & attacker, const Unit & target, const int32_t dst ) { // Get the actual position of the attacker before attacking const Position pos = Position::GetReachable( attacker, dst ); // Check that the attacker is actually capable of attacking the target from this position const std::array cells = { pos.GetHead(), pos.GetTail() }; for ( const Cell * cell : cells ) { if ( cell == nullptr ) { continue; } const int32_t cellIdx = cell->GetIndex(); if ( Board::GetDistance( target.GetPosition(), cellIdx ) > 1 ) { continue; } if ( !CanAttackFromCell( attacker, cellIdx ) ) { continue; } return true; } return false; } std::string Battle::Board::GetMoatInfo() { std::string msg = _( "The Moat reduces the defense skill of troops trapped in it by %{count} and restricts their movement range." ); StringReplace( msg, "%{count}", GameStatic::GetBattleMoatReduceDefense() ); return msg; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_board.h000066400000000000000000000147641476115357100225530ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "battle_cell.h" #include "math_base.h" namespace Maps { class Tile; } namespace Battle { class Unit; inline CellDirection & operator++( CellDirection & d ) { return d = ( CENTER == d ? TOP_LEFT : CellDirection( d << 1 ) ); } inline CellDirection & operator--( CellDirection & d ) { return d = ( TOP_LEFT == d ? CENTER : CellDirection( d >> 1 ) ); } using Indexes = std::vector; class Board : public std::vector { public: // Width of the battlefield, measured in cells static constexpr int widthInCells{ 11 }; // Height of the battlefield, measured in cells static constexpr int heightInCells{ 9 }; // Total number of cells on the battlefield static constexpr int sizeInCells{ widthInCells * heightInCells }; Board(); Board( const Board & ) = delete; Board & operator=( const Board & ) = delete; void removeDeadUnits(); void SetArea( const fheroes2::Rect & ); int32_t GetIndexAbsPosition( const fheroes2::Point & ) const; std::vector GetNearestTroops( const Unit * startUnit, const std::vector & blackList ); void SetCobjObjects( const Maps::Tile & tile, std::mt19937 & gen ); void SetCovrObjects( int icn ); static std::string GetMoatInfo(); static Cell * GetCell( const int32_t position, const int dir = CENTER ); static bool isNearIndexes( const int32_t index1, const int32_t index2 ); static bool isValidIndex( const int32_t index ); // Returns true if the given index is considered to be inside the castle from the point of view of castle defense, // otherwise returns false. Indexes of destructible walls are considered to be located inside the castle. static bool isCastleIndex( const int32_t index ); static bool isMoatIndex( const int32_t index, const Unit & unit ); static bool isOutOfWallsIndex( const int32_t index ); static int GetReflectDirection( const int dir ); static int GetDirection( const int32_t index1, const int32_t index2 ); // Returns the distance to the cell with the given index from the given edge of the battlefield along the X axis. The // distance from the edges of the battlefield to the cells closest to them is counted as one. static uint32_t GetDistanceFromBoardEdgeAlongXAxis( const int32_t index, const bool fromRightEdge ); // Returns the distance between two cells with the given indexes. If any of the indexes is not valid, then returns 0. static uint32_t GetDistance( const int32_t index1, const int32_t index2 ); // Returns the distance between two given positions. This distance is calculated as the distance between the cells of // both positions closest to each other. If any of the positions is not valid, then returns 0. static uint32_t GetDistance( const Position & pos1, const Position & pos2 ); // Returns the distance between the given position and the cell with the given index. The distance is calculated as // the distance between the cell with the given index and the cell closest to it, which is part of the given position. // If either the position or the index is not valid, then returns 0. static uint32_t GetDistance( const Position & pos, const int32_t index ); static bool isValidDirection( const int32_t index, const int dir ); static int32_t GetIndexDirection( const int32_t index, const int dir ); static Indexes GetDistanceIndexes( const int32_t center, const uint32_t radius ); static Indexes GetDistanceIndexes( const Unit & unit, const uint32_t radius ); static Indexes GetDistanceIndexes( const Position & pos, const uint32_t radius ); static Indexes GetAroundIndexes( const int32_t center ); static Indexes GetAroundIndexes( const Unit & unit ); static Indexes GetAroundIndexes( const Position & pos ); static Indexes GetMoveWideIndexes( const int32_t head, const bool reflect ); static bool isValidMirrorImageIndex( const int32_t index, const Unit * unit ); // Checks whether a given unit is (in principle) capable of attacking in melee during the current turn from a cell with // a given index static bool CanAttackFromCell( const Unit & unit, const int32_t from ); // Checks whether the attacker is able to attack the target in melee during the current turn from a position corresponding // to the given index static bool CanAttackTargetFromPosition( const Unit & attacker, const Unit & target, const int32_t dst ); private: void SetCobjObject( const int icn, const uint32_t dst ); }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_bridge.cpp000066400000000000000000000104411476115357100232370ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_bridge.h" #include "battle_arena.h" #include "battle_board.h" #include "battle_cell.h" #include "battle_grave.h" #include "battle_interface.h" #include "battle_troop.h" #include "castle.h" bool Battle::Bridge::isOccupied() { const Battle::Graveyard * graveyard = Arena::GetGraveyard(); assert( graveyard != nullptr ); // Yes if there are any troops (alive or dead) on CELL_MOAT and CELL_GATES tiles return Board::GetCell( CELL_MOAT )->GetUnit() || Board::GetCell( CELL_GATES )->GetUnit() || graveyard->getLastUnit( CELL_MOAT ) || graveyard->getLastUnit( CELL_GATES ); } bool Battle::Bridge::NeedDown( const Unit & unit, const int32_t dstIdx ) const { // No if bridge is destroyed or already lowered or unit does not belong to the castle or there are any troops (alive or dead) on or under the bridge if ( !isValid() || isDown() || unit.GetColor() != Arena::GetCastle()->GetColor() || isOccupied() ) { return false; } if ( unit.isFlying() ) { return dstIdx == CELL_GATES; } const int32_t headIdx = unit.GetHeadIndex(); if ( dstIdx == CELL_GATES && ( headIdx == CELL_AFTER_GATES || headIdx == CELL_BELOW_BRIDGE || headIdx == CELL_ABOVE_BRIDGE ) ) { return true; } if ( dstIdx == CELL_MOAT && headIdx != CELL_GATES ) { return true; } if ( unit.isWide() ) { const int32_t tailIdx = unit.GetTailIndex(); if ( dstIdx == CELL_BEFORE_MOAT && ( tailIdx == CELL_BELOW_BRIDGE || tailIdx == CELL_ABOVE_BRIDGE ) ) { return true; } } return false; } bool Battle::Bridge::isPassable( const Unit & unit ) const { // Yes if bridge is lowered (or destroyed), or unit belongs to the castle and there are no any troops (alive or dead) on or under the bridge return isDown() || ( unit.GetColor() == Arena::GetCastle()->GetColor() && !isOccupied() ); } void Battle::Bridge::SetDestroyed() { _isDestroyed = true; _isDown = true; Board::GetCell( CELL_GATES )->SetObject( 0 ); } void Battle::Bridge::SetPassability( const Unit & unit ) const { if ( isPassable( unit ) ) { Board::GetCell( CELL_GATES )->SetObject( 0 ); } else { Board::GetCell( CELL_GATES )->SetObject( 1 ); } } void Battle::Bridge::ActionUp() { assert( AllowUp() ); if ( Arena::GetInterface() ) { Arena::GetInterface()->RedrawBridgeAnimation( false ); } _isDown = false; } void Battle::Bridge::ActionDown() { assert( isValid() && !isDown() && !isOccupied() ); if ( Arena::GetInterface() ) { Arena::GetInterface()->RedrawBridgeAnimation( true ); } _isDown = true; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_bridge.h000066400000000000000000000060671476115357100227150ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace Battle { class Unit; class Bridge final { public: Bridge() = default; Bridge( const Bridge & ) = delete; ~Bridge() = default; Bridge & operator=( const Bridge & ) = delete; void ActionUp(); void ActionDown(); void SetDestroyed(); void SetPassability( const Unit & unit ) const; bool AllowUp() const { // Yes if not destroyed and lowered and there are no any troops (alive or dead) on or under the bridge return isValid() && isDown() && !isOccupied(); } bool NeedDown( const Unit & unit, const int32_t dstIdx ) const; bool isPassable( const Unit & unit ) const; bool isValid() const { return !_isDestroyed; } bool isDestroyed() const { return _isDestroyed; } bool isDown() const { assert( !_isDestroyed || _isDown ); return _isDown; } private: static bool isOccupied(); bool _isDestroyed{ false }; bool _isDown{ false }; enum { CELL_ABOVE_BRIDGE = 39, CELL_BEFORE_MOAT = 48, CELL_MOAT = 49, CELL_GATES = 50, CELL_AFTER_GATES = 51, CELL_BELOW_BRIDGE = 61 }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_catapult.cpp000066400000000000000000000162051476115357100236240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_catapult.h" #include #include #include #include #include #include "artifact.h" #include "artifact_info.h" #include "heroes_base.h" #include "logging.h" #include "rand.h" #include "skill.h" Battle::Catapult::Catapult( const HeroBase & hero ) : catShots( 1 ) , doubleDamageChance( 25 ) , canMiss( true ) { switch ( hero.GetLevelSkill( Skill::Secondary::BALLISTICS ) ) { case Skill::Level::BASIC: doubleDamageChance = 50; canMiss = false; break; case Skill::Level::ADVANCED: doubleDamageChance = 50; catShots += 1; canMiss = false; break; case Skill::Level::EXPERT: doubleDamageChance = 100; catShots += 1; canMiss = false; break; default: break; } catShots += hero.GetBagArtifacts().getTotalArtifactEffectValue( fheroes2::ArtifactBonusType::EXTRA_CATAPULT_SHOTS ); } int Battle::Catapult::GetDamage( Rand::DeterministicRandomGenerator & randomGenerator ) const { if ( doubleDamageChance == 100 || doubleDamageChance >= randomGenerator.Get( 1, 100 ) ) { DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "Catapult dealt double damage! (" << doubleDamageChance << "% chance)" ) return 2; } return 1; } const std::vector & Battle::Catapult::getAllowedTargets() { static const std::vector allowedTargets{ CastleDefenseStructure::WALL1, CastleDefenseStructure::WALL2, CastleDefenseStructure::WALL3, CastleDefenseStructure::WALL4, CastleDefenseStructure::TOWER1, CastleDefenseStructure::TOWER2, CastleDefenseStructure::BRIDGE, CastleDefenseStructure::CENTRAL_TOWER }; return allowedTargets; } fheroes2::Point Battle::Catapult::GetTargetPosition( const CastleDefenseStructure target, const bool hit ) { switch ( target ) { case CastleDefenseStructure::WALL1: return hit ? fheroes2::Point( 475, 45 ) : fheroes2::Point( 495, 105 ); case CastleDefenseStructure::WALL2: return hit ? fheroes2::Point( 420, 115 ) : fheroes2::Point( 460, 175 ); case CastleDefenseStructure::WALL3: return hit ? fheroes2::Point( 415, 280 ) : fheroes2::Point( 455, 280 ); case CastleDefenseStructure::WALL4: return hit ? fheroes2::Point( 490, 390 ) : fheroes2::Point( 530, 390 ); case CastleDefenseStructure::TOWER1: return hit ? fheroes2::Point( 430, 40 ) : fheroes2::Point( 490, 120 ); case CastleDefenseStructure::TOWER2: return hit ? fheroes2::Point( 430, 300 ) : fheroes2::Point( 490, 340 ); case CastleDefenseStructure::BRIDGE: return hit ? fheroes2::Point( 400, 195 ) : fheroes2::Point( 450, 235 ); case CastleDefenseStructure::CENTRAL_TOWER: return hit ? fheroes2::Point( 580, 160 ) : fheroes2::Point( 610, 320 ); case CastleDefenseStructure::TOP_BRIDGE_TOWER: return hit ? fheroes2::Point( 395, 152 ) : fheroes2::Point( 445, 202 ); case CastleDefenseStructure::BOTTOM_BRIDGE_TOWER: return hit ? fheroes2::Point( 395, 240 ) : fheroes2::Point( 445, 290 ); default: break; } return {}; } Battle::CastleDefenseStructure Battle::Catapult::GetTarget( const std::map & stateOfCatapultTargets, Rand::DeterministicRandomGenerator & randomGenerator ) { const auto checkTargetState = [&stateOfCatapultTargets]( const CastleDefenseStructure target ) { const auto iter = stateOfCatapultTargets.find( target ); assert( iter != stateOfCatapultTargets.end() ); return ( iter->second > 0 ); }; std::vector targets; targets.reserve( 4 ); // Walls if ( checkTargetState( CastleDefenseStructure::WALL1 ) ) { targets.push_back( CastleDefenseStructure::WALL1 ); } if ( checkTargetState( CastleDefenseStructure::WALL2 ) ) { targets.push_back( CastleDefenseStructure::WALL2 ); } if ( checkTargetState( CastleDefenseStructure::WALL3 ) ) { targets.push_back( CastleDefenseStructure::WALL3 ); } if ( checkTargetState( CastleDefenseStructure::WALL4 ) ) { targets.push_back( CastleDefenseStructure::WALL4 ); } // Right/left towers if ( targets.empty() ) { if ( checkTargetState( CastleDefenseStructure::TOWER1 ) ) { targets.push_back( CastleDefenseStructure::TOWER1 ); } if ( checkTargetState( CastleDefenseStructure::TOWER2 ) ) { targets.push_back( CastleDefenseStructure::TOWER2 ); } } // Bridge if ( targets.empty() ) { if ( checkTargetState( CastleDefenseStructure::BRIDGE ) ) { targets.push_back( CastleDefenseStructure::BRIDGE ); } } // Central tower if ( targets.empty() ) { if ( checkTargetState( CastleDefenseStructure::CENTRAL_TOWER ) ) { targets.push_back( CastleDefenseStructure::CENTRAL_TOWER ); } } if ( !targets.empty() ) { return randomGenerator.Get( targets ); } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "no target was found" ) return CastleDefenseStructure::NONE; } bool Battle::Catapult::IsNextShotHit( Rand::DeterministicRandomGenerator & randomGenerator ) const { // Miss chance is 25% return !( canMiss && randomGenerator.Get( 1, 20 ) < 6 ); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_catapult.h000066400000000000000000000054761476115357100233010ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "battle.h" #include "math_base.h" class HeroBase; namespace Rand { class DeterministicRandomGenerator; } namespace Battle { class Catapult { public: explicit Catapult( const HeroBase & hero ); Catapult( const Catapult & ) = delete; Catapult & operator=( const Catapult & ) = delete; static const std::vector & getAllowedTargets(); static CastleDefenseStructure GetTarget( const std::map & stateOfCatapultTargets, Rand::DeterministicRandomGenerator & randomGenerator ); static fheroes2::Point GetTargetPosition( const CastleDefenseStructure target, const bool hit ); uint32_t GetShots() const { return catShots; } int GetDamage( Rand::DeterministicRandomGenerator & randomGenerator ) const; bool IsNextShotHit( Rand::DeterministicRandomGenerator & randomGenerator ) const; private: uint32_t catShots; uint32_t doubleDamageChance; bool canMiss; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_cell.cpp000066400000000000000000000305011476115357100227210ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_cell.h" #include #include "battle_arena.h" #include "battle_board.h" #include "battle_troop.h" #include "math_tools.h" namespace { bool inABC( const fheroes2::Point & base, const fheroes2::Point & pt1, const fheroes2::Point & pt2, const fheroes2::Point & pt3 ) { const int32_t a = ( pt1.x - base.x ) * ( pt2.y - pt1.y ) - ( pt2.x - pt1.x ) * ( pt1.y - base.y ); const int32_t b = ( pt2.x - base.x ) * ( pt3.y - pt2.y ) - ( pt3.x - pt2.x ) * ( pt2.y - base.y ); const int32_t c = ( pt3.x - base.x ) * ( pt1.y - pt3.y ) - ( pt1.x - pt3.x ) * ( pt3.y - base.y ); return ( ( a >= 0 && b >= 0 && c >= 0 ) || ( a < 0 && b < 0 && c < 0 ) ); } const int32_t cellHeightVerSide = 32; const int32_t infl = 12; } void Battle::Position::Set( const int32_t head, const bool wide, const bool reflect ) { first = Board::GetCell( head ); if ( first && wide ) { second = Board::GetCell( first->GetIndex(), reflect ? RIGHT : LEFT ); } else { second = nullptr; } } void Battle::Position::Swap() { if ( first == nullptr || second == nullptr ) { return; } std::swap( first, second ); } fheroes2::Rect Battle::Position::GetRect() const { if ( first == nullptr ) { return {}; } return second ? getBoundaryRect( first->GetPos(), second->GetPos() ) : first->GetPos(); } Battle::Position Battle::Position::GetPosition( const Unit & unit, const int32_t dst ) { Position result; if ( unit.isWide() ) { const auto checkCells = [&unit]( Cell * headCell, Cell * tailCell ) { Position pos; if ( headCell == nullptr || ( !unit.GetPosition().contains( headCell->GetIndex() ) && !headCell->isPassable( true ) ) ) { return pos; } if ( tailCell == nullptr || ( !unit.GetPosition().contains( tailCell->GetIndex() ) && !tailCell->isPassable( true ) ) ) { return pos; } pos.first = headCell; pos.second = tailCell; return pos; }; const int tailDirection = unit.isReflect() ? RIGHT : LEFT; if ( Board::isValidDirection( dst, tailDirection ) ) { Cell * headCell = Board::GetCell( dst ); Cell * tailCell = Board::GetCell( Board::GetIndexDirection( dst, tailDirection ) ); result = checkCells( headCell, tailCell ); } if ( result.GetHead() == nullptr || result.GetTail() == nullptr ) { const int headDirection = unit.isReflect() ? LEFT : RIGHT; if ( Board::isValidDirection( dst, headDirection ) ) { Cell * headCell = Board::GetCell( Board::GetIndexDirection( dst, headDirection ) ); Cell * tailCell = Board::GetCell( dst ); result = checkCells( headCell, tailCell ); } } } else { Cell * headCell = Board::GetCell( dst ); if ( headCell != nullptr && ( unit.GetPosition().contains( headCell->GetIndex() ) || headCell->isPassable( true ) ) ) { result.first = headCell; } } return result; } Battle::Position Battle::Position::GetReachable( const Unit & unit, const int32_t dst, const std::optional speed /* = {} */ ) { Arena * arena = GetArena(); assert( arena != nullptr ); const auto checkReachability = [&unit, speed, arena]( const Position & pos ) -> Position { if ( speed ) { if ( arena->isPositionReachable( unit, pos, false ) && arena->CalculateMoveCost( unit, pos ) <= *speed ) { return pos; } } else if ( arena->isPositionReachable( unit, pos, true ) ) { return pos; } return {}; }; if ( unit.isWide() ) { const auto checkCells = [&checkReachability]( Cell * headCell, Cell * tailCell ) -> Position { if ( headCell == nullptr || tailCell == nullptr ) { return {}; } Position pos; pos.first = headCell; pos.second = tailCell; return checkReachability( pos ); }; const auto tryHead = [&unit, dst, &checkCells]() -> Position { const int tailDirection = unit.isReflect() ? RIGHT : LEFT; if ( Board::isValidDirection( dst, tailDirection ) ) { Cell * headCell = Board::GetCell( dst ); Cell * tailCell = Board::GetCell( Board::GetIndexDirection( dst, tailDirection ) ); return checkCells( headCell, tailCell ); } return {}; }; const auto tryTail = [&unit, dst, &checkCells]() -> Position { const int headDirection = unit.isReflect() ? LEFT : RIGHT; if ( Board::isValidDirection( dst, headDirection ) ) { Cell * headCell = Board::GetCell( Board::GetIndexDirection( dst, headDirection ) ); Cell * tailCell = Board::GetCell( dst ); return checkCells( headCell, tailCell ); } return {}; }; Position headPos = tryHead(); if ( headPos.GetHead() != nullptr && headPos.GetTail() != nullptr ) { return headPos; } return tryTail(); } Cell * headCell = Board::GetCell( dst ); if ( headCell == nullptr ) { return {}; } Position pos; pos.first = headCell; return checkReachability( pos ); } bool Battle::Position::isReflect() const { return first && second && first->GetIndex() < second->GetIndex(); } bool Battle::Position::contains( const int32_t idx ) const { return ( first && first->GetIndex() == idx ) || ( second && second->GetIndex() == idx ); } bool Battle::Position::isEmpty() const { if ( first != nullptr ) { return false; } assert( second == nullptr ); return true; } bool Battle::Position::isValidForUnit( const Unit & unit ) const { if ( first == nullptr ) { return false; } return unit.isWide() ? second != nullptr : second == nullptr; } bool Battle::Position::operator<( const Position & other ) const { assert( first == nullptr || Board::isValidIndex( first->GetIndex() ) ); assert( second == nullptr || Board::isValidIndex( second->GetIndex() ) ); assert( other.first == nullptr || Board::isValidIndex( other.first->GetIndex() ) ); assert( other.second == nullptr || Board::isValidIndex( other.second->GetIndex() ) ); // It is necessary to guarantee a stable order of positions, it should depend on the indexes of cells, and not on the values of pointers to these cells const auto theseIndexes = std::make_pair( first ? first->GetIndex() : -1, second ? second->GetIndex() : -1 ); const auto otherIndexes = std::make_pair( other.first ? other.first->GetIndex() : -1, other.second ? other.second->GetIndex() : -1 ); return theseIndexes < otherIndexes; } Battle::Cell::Cell( const int32_t idx ) : _index( idx ) , _object( 0 ) , _unit( nullptr ) { SetArea( fheroes2::Rect() ); } void Battle::Cell::SetArea( const fheroes2::Rect & area ) { _pos.x = area.x + 89 - ( ( ( _index / Board::widthInCells ) % 2 ) ? widthPx / 2 : 0 ) + widthPx * ( _index % Board::widthInCells ); _pos.y = area.y + 62 + ( ( heightPx - ( heightPx - cellHeightVerSide ) / 2 ) * ( _index / Board::widthInCells ) ); _pos.width = widthPx; _pos.height = heightPx; // center _coord[0] = { infl * _pos.x + infl * _pos.width / 2, infl * _pos.y + infl * _pos.height / 2 }; // coordinates _coord[1] = { infl * _pos.x, infl * _pos.y + infl * ( _pos.height - cellHeightVerSide ) / 2 }; _coord[2] = { infl * _pos.x + infl * _pos.width / 2, infl * _pos.y }; _coord[3] = { infl * _pos.x + infl * _pos.width, infl * _pos.y + infl * ( _pos.height - cellHeightVerSide ) / 2 }; _coord[4] = { infl * _pos.x + infl * _pos.width, infl * _pos.y + infl * _pos.height - infl * ( _pos.height - cellHeightVerSide ) / 2 }; _coord[5] = { infl * _pos.x + infl * _pos.width / 2, infl * _pos.y + infl * _pos.height }; _coord[6] = { infl * _pos.x, infl * _pos.y + infl * _pos.height - infl * ( _pos.height - cellHeightVerSide ) / 2 }; } Battle::CellDirection Battle::Cell::GetTriangleDirection( const fheroes2::Point & dst ) const { const fheroes2::Point pt( infl * dst.x, infl * dst.y ); if ( pt == _coord[0] ) { return CENTER; } if ( inABC( pt, _coord[0], _coord[1], _coord[2] ) ) { return TOP_LEFT; } if ( inABC( pt, _coord[0], _coord[2], _coord[3] ) ) { return TOP_RIGHT; } if ( inABC( pt, _coord[0], _coord[3], _coord[4] ) ) { return RIGHT; } if ( inABC( pt, _coord[0], _coord[4], _coord[5] ) ) { return BOTTOM_RIGHT; } if ( inABC( pt, _coord[0], _coord[5], _coord[6] ) ) { return BOTTOM_LEFT; } if ( inABC( pt, _coord[0], _coord[1], _coord[6] ) ) { return LEFT; } return UNKNOWN; } bool Battle::Cell::isPositionIncludePoint( const fheroes2::Point & pt ) const { return UNKNOWN != GetTriangleDirection( pt ); } int32_t Battle::Cell::GetIndex() const { return _index; } void Battle::Cell::SetObject( const int object ) { _object = object; } int Battle::Cell::GetObject() const { return _object; } const fheroes2::Rect & Battle::Cell::GetPos() const { return _pos; } const Battle::Unit * Battle::Cell::GetUnit() const { return _unit; } Battle::Unit * Battle::Cell::GetUnit() { return _unit; } void Battle::Cell::SetUnit( Unit * unit ) { _unit = unit; } bool Battle::Cell::isPassableFromAdjacent( const Unit & unit, const Cell & adjacent ) const { assert( Board::isNearIndexes( _index, adjacent._index ) ); if ( unit.isWide() ) { const int dir = Board::GetDirection( adjacent._index, _index ); switch ( dir ) { case BOTTOM_RIGHT: case TOP_RIGHT: case BOTTOM_LEFT: case TOP_LEFT: { const bool reflect = ( ( BOTTOM_LEFT | TOP_LEFT ) & dir ) != 0; const Cell * tail = Board::GetCell( _index, reflect ? RIGHT : LEFT ); return tail && tail->isPassable( true ) && isPassable( true ); } case LEFT: case RIGHT: return isPassable( true ) || _index == unit.GetTailIndex(); default: break; } } return isPassable( true ); } bool Battle::Cell::isPassableForUnit( const Unit & unit ) const { const Position unitPos = Position::GetPosition( unit, _index ); if ( unitPos.GetHead() == nullptr ) { return false; } assert( unitPos.isValidForUnit( unit ) ); return true; } bool Battle::Cell::isPassable( const bool checkForUnit ) const { return _object == 0 && ( !checkForUnit || _unit == nullptr ); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_cell.h000066400000000000000000000131321476115357100223670ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include "math_base.h" namespace Battle { class Unit; enum CellDirection : int { UNKNOWN = 0x00, TOP_LEFT = 0x01, TOP_RIGHT = 0x02, RIGHT = 0x04, BOTTOM_RIGHT = 0x08, BOTTOM_LEFT = 0x10, LEFT = 0x20, CENTER = 0x40, RIGHT_SIDE = TOP_RIGHT | RIGHT | BOTTOM_RIGHT, LEFT_SIDE = TOP_LEFT | LEFT | BOTTOM_LEFT, AROUND = RIGHT_SIDE | LEFT_SIDE }; class Cell final { public: // Width of the rendered cell in pixels static constexpr int widthPx{ 44 }; // Height of the rendered cell in pixels static constexpr int heightPx{ 52 }; explicit Cell( const int32_t idx ); Cell( const Cell & ) = delete; Cell( Cell && ) = default; ~Cell() = default; Cell & operator=( const Cell & ) = delete; Cell & operator=( Cell && ) = delete; int32_t GetIndex() const; const fheroes2::Rect & GetPos() const; int GetObject() const; const Unit * GetUnit() const; Unit * GetUnit(); CellDirection GetTriangleDirection( const fheroes2::Point & dst ) const; bool isPositionIncludePoint( const fheroes2::Point & pt ) const; void SetArea( const fheroes2::Rect & area ); void SetObject( const int object ); void SetUnit( Unit * unit ); // Checks that the cell is passable for a given unit located in a certain adjacent cell bool isPassableFromAdjacent( const Unit & unit, const Cell & adjacent ) const; // Checks that the cell is passable for a given unit, i.e. unit can occupy it with his head or tail bool isPassableForUnit( const Unit & unit ) const; // Checks that the cell is passable, i.e. does not contain an obstacle or (optionally) a unit bool isPassable( const bool checkForUnit ) const; private: int32_t _index; fheroes2::Rect _pos; int _object; Unit * _unit; std::array _coord; }; class Position final : protected std::pair { public: Position() : std::pair( nullptr, nullptr ) {} void Set( const int32_t head, const bool wide, const bool reflect ); void Swap(); bool isReflect() const; bool contains( const int32_t idx ) const; // Returns the position that a given unit would occupy after moving to the cell // with a given index (without taking into account the pathfinder's info) or an // empty Position object if this index is unreachable in principle for this unit. static Position GetPosition( const Unit & unit, const int32_t dst ); // Returns the reachable position for a given unit, which corresponds to a given // index, or an empty Position object if this index is unreachable for this unit // on the current turn. if 'speed' is set, then this value will be used to check // the position reachability instead of the speed returned by 'unit'. static Position GetReachable( const Unit & unit, const int32_t dst, const std::optional speed = {} ); bool isEmpty() const; bool isValidForUnit( const Unit & unit ) const; bool isValidForUnit( const Unit * unit ) const { if ( unit == nullptr ) { return false; } return isValidForUnit( *unit ); } fheroes2::Rect GetRect() const; const Cell * GetHead() const { return first; } const Cell * GetTail() const { return second; } Cell * GetHead() { return first; } Cell * GetTail() { return second; } bool operator<( const Position & other ) const; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_command.cpp000066400000000000000000000064031476115357100234240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_command.h" #include #include "tools.h" int Battle::Command::GetNextValue() { int val = 0; *this >> val; return val; } uint32_t Battle::Command::updateSeed( uint32_t seed ) const { switch ( _type ) { case CommandType::ATTACK: assert( size() == 5 ); fheroes2::hashCombine( seed, _type ); // Use only cell index to move and attacker & defender UIDs, because cell index to attack and attack direction may differ depending on whether the AI or the human // player gives the command fheroes2::hashCombine( seed, at( 2 ) ); fheroes2::hashCombine( seed, at( 3 ) ); fheroes2::hashCombine( seed, at( 4 ) ); break; case CommandType::MOVE: case CommandType::SPELLCAST: case CommandType::MORALE: case CommandType::CATAPULT: case CommandType::TOWER: case CommandType::RETREAT: case CommandType::SURRENDER: case CommandType::SKIP: fheroes2::hashCombine( seed, _type ); std::for_each( begin(), end(), [&seed]( const int param ) { fheroes2::hashCombine( seed, param ); } ); break; // These commands should never affect the seed generation case CommandType::TOGGLE_AUTO_COMBAT: case CommandType::QUICK_COMBAT: break; default: assert( 0 ); break; } return seed; } Battle::Command & Battle::Command::operator<<( const int val ) { push_back( val ); return *this; } Battle::Command & Battle::Command::operator>>( int & val ) { if ( !empty() ) { val = back(); pop_back(); } return *this; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_command.h000066400000000000000000000146771476115357100231050ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include "spell.h" namespace Battle { enum class CommandType : int32_t { MOVE, ATTACK, SPELLCAST, MORALE, CATAPULT, TOWER, RETREAT, SURRENDER, SKIP, TOGGLE_AUTO_COMBAT, QUICK_COMBAT }; class Command final : public std::vector { public: static constexpr std::integral_constant MOVE{}; static constexpr std::integral_constant ATTACK{}; static constexpr std::integral_constant SPELLCAST{}; static constexpr std::integral_constant MORALE{}; static constexpr std::integral_constant CATAPULT{}; static constexpr std::integral_constant TOWER{}; static constexpr std::integral_constant RETREAT{}; static constexpr std::integral_constant SURRENDER{}; static constexpr std::integral_constant SKIP{}; static constexpr std::integral_constant TOGGLE_AUTO_COMBAT{}; static constexpr std::integral_constant QUICK_COMBAT{}; template explicit Command( std::integral_constant /* tag */, const Types... params ) : _type( cmd ) { if constexpr ( cmd == CommandType::MOVE ) { // UID, cell index static_assert( sizeof...( params ) == 2 ); } else if constexpr ( cmd == CommandType::ATTACK ) { // Attacker UID, defender UID, cell index to move, cell index to attack, attack direction static_assert( sizeof...( params ) == 5 ); } else if constexpr ( cmd == CommandType::SPELLCAST ) { static_assert( sizeof...( params ) > 0 ); const int spellId = std::get<0>( std::make_tuple( params... ) ); if ( spellId == Spell::MIRRORIMAGE ) { // Spell, UID assert( sizeof...( params ) == 2 ); } else if ( spellId == Spell::TELEPORT ) { // Spell, src index, dst index assert( sizeof...( params ) == 3 ); } else { // Spell, cell index assert( sizeof...( params ) == 2 ); } } else if constexpr ( cmd == CommandType::MORALE ) { // UID, morale static_assert( sizeof...( params ) == 2 ); } else if constexpr ( cmd == CommandType::TOWER ) { // Tower type, UID static_assert( sizeof...( params ) == 2 ); } else if constexpr ( cmd == CommandType::SKIP ) { // UID static_assert( sizeof...( params ) == 1 ); } else if constexpr ( cmd == CommandType::TOGGLE_AUTO_COMBAT ) { // Color static_assert( sizeof...( params ) == 1 ); } else { static_assert( sizeof...( params ) == 0 ); } if constexpr ( sizeof...( params ) > 0 ) { reserve( sizeof...( params ) ); // Put the elements of the parameter pack in reverse order using the right-to-left sequencing of the assignment operator int dummy = 0; (void)( ( *this << params, dummy ) = ... ); } } CommandType GetType() const { return _type; } int GetNextValue(); // Updates the specified seed using the contents of this command. Returns the updated seed (or the original seed if this command is not suitable for seed update). uint32_t updateSeed( uint32_t seed ) const; Command & operator<<( const int val ); private: Command & operator>>( int & val ); CommandType _type; }; } namespace std { template <> struct hash { std::size_t operator()( const Battle::CommandType key ) const noexcept { using BattleCommandTypeUnderlyingType = std::underlying_type_t; const std::hash hasher; return hasher( static_cast( key ) ); } }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_dialogs.cpp000066400000000000000000001542321476115357100234340ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "artifact.h" #include "audio.h" #include "audio_manager.h" #include "battle.h" #include "battle_arena.h" // IWYU pragma: associated #include "battle_army.h" #include "battle_interface.h" // IWYU pragma: associated #include "color.h" #include "cursor.h" #include "dialog.h" #include "dialog_audio.h" #include "dialog_hotkeys.h" #include "game.h" #include "game_delays.h" #include "game_hotkeys.h" #include "heroes.h" #include "heroes_base.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "luck.h" #include "math_base.h" #include "monster.h" #include "morale.h" #include "mus.h" #include "players.h" #include "race.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_option_item.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" namespace { // DialogBattleSummary text related values const int bsTextWidth = 303; const int bsTextYOffset = 160; const int bsTextIndent = 30; class LoopedAnimation { public: explicit LoopedAnimation( int icnId = 0, bool loop = false ) : _icnId( icnId ) , _frameId( 0 ) , _counter( 0 ) , _finished( false ) , _loop( loop ) { _frameId = ICN::getAnimatedIcnIndex( _icnId, 1, _counter ); } uint32_t frameId() { if ( _finished ) return _frameId; ++_counter; uint32_t nextId = ICN::getAnimatedIcnIndex( _icnId, 1, _counter ); if ( nextId < _frameId ) { if ( _loop ) { _counter = 0; nextId = ICN::getAnimatedIcnIndex( _icnId, 1, _counter ); std::swap( nextId, _frameId ); return nextId; } else { _finished = true; } } else { std::swap( nextId, _frameId ); return nextId; } return _frameId; } bool isFinished() const { return _finished; } int id() const { return _icnId; } private: int _icnId; uint32_t _frameId; uint32_t _counter; bool _finished; bool _loop; }; class LoopedAnimationSequence { public: void push( int icnId, bool loop ) { _queue.push( LoopedAnimation( icnId, loop ) ); } uint32_t frameId() { if ( isFinished() ) return 0; return _queue.front().frameId(); } bool nextFrame() // returns true only if there is some frames left { if ( !_queue.empty() && _queue.front().isFinished() ) _queue.pop(); return _queue.empty(); } bool isFinished() const { return _queue.empty(); } int id() const { if ( isFinished() ) return 0; return _queue.front().id(); } private: std::queue _queue; }; void setupAnimation( fheroes2::Display & display, const fheroes2::Rect & animationRoi, LoopedAnimationSequence & sequence ) { sequence.push( ICN::WINCMBT, true ); // needs specific for battle summary const fheroes2::Sprite & sequenceBase = fheroes2::AGG::GetICN( sequence.id(), 0 ); const fheroes2::Sprite & sequenceStart = fheroes2::AGG::GetICN( sequence.id(), 1 ); Copy( sequenceBase, 0, 0, display, animationRoi.x, animationRoi.y, sequenceBase.width(), sequenceBase.height() ); fheroes2::Blit( sequenceStart, display, animationRoi.x + sequenceStart.x(), animationRoi.y + sequenceStart.y() ); } void updateAnimation( fheroes2::Display & display, int & lastSequence, LoopedAnimationSequence & sequence, const fheroes2::Rect & animationRoi ) { if ( Game::validateAnimationDelay( Game::BATTLE_DIALOG_DELAY ) && !sequence.nextFrame() ) { if ( lastSequence != sequence.id() ) { lastSequence = sequence.id(); const fheroes2::Sprite & base = fheroes2::AGG::GetICN( lastSequence, 0 ); Copy( base, 0, 0, display, animationRoi.x + base.x(), animationRoi.y + base.y(), base.width(), base.height() ); } const fheroes2::Sprite & sequenceCurrent = fheroes2::AGG::GetICN( sequence.id(), sequence.frameId() ); fheroes2::Blit( sequenceCurrent, display, animationRoi.x + sequenceCurrent.x(), animationRoi.y + sequenceCurrent.y() ); display.render( animationRoi ); } } enum class DialogAction : int { Open, AudioSettings, HotKeys, Close }; void RedrawBattleSettings( const std::vector & areas ) { assert( areas.size() == 9 ); const Settings & conf = Settings::Get(); int speed = conf.BattleSpeed(); std::string str = _( "Speed: %{speed}" ); StringReplace( str, "%{speed}", speed ); uint32_t speedIcnIndex = 0; if ( speed >= 8 ) { speedIcnIndex = 2; } else if ( speed >= 5 ) { speedIcnIndex = 1; } const fheroes2::Sprite & speedIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, speedIcnIndex ); fheroes2::drawOption( areas[0], speedIcon, _( "Speed" ), str, fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const bool isShowTurnOrderEnabled = conf.BattleShowTurnOrder(); const fheroes2::Sprite & turnOrderIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, isShowTurnOrderEnabled ? 4 : 3 ); fheroes2::drawOption( areas[1], turnOrderIcon, _( "Turn Order" ), isShowTurnOrderEnabled ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const bool isBattleAudoSpellCastEnabled = conf.BattleAutoSpellcast(); const fheroes2::Sprite & battleAutoSpellCastIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, isBattleAudoSpellCastEnabled ? 7 : 6 ); fheroes2::drawOption( areas[2], battleAutoSpellCastIcon, _( "Auto Spell Casting" ), isBattleAudoSpellCastEnabled ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const bool isShowBattleGridEnabled = conf.BattleShowGrid(); const fheroes2::Sprite & battleGridIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, isShowBattleGridEnabled ? 9 : 8 ); fheroes2::drawOption( areas[3], battleGridIcon, _( "Grid" ), isShowBattleGridEnabled ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const bool isShowMoveShadowEnabled = conf.BattleShowMoveShadow(); const fheroes2::Sprite & moveShadowIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, isShowMoveShadowEnabled ? 11 : 10 ); fheroes2::drawOption( areas[4], moveShadowIcon, _( "Shadow Movement" ), isShowMoveShadowEnabled ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const bool isShowMouseShadowEnabled = conf.BattleShowMouseShadow(); const fheroes2::Sprite & mouseShadowIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, isShowMouseShadowEnabled ? 13 : 12 ); fheroes2::drawOption( areas[5], mouseShadowIcon, _( "Shadow Cursor" ), isShowMouseShadowEnabled ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const fheroes2::Sprite & audioSettingsIcon = fheroes2::AGG::GetICN( ICN::SPANEL, 1 ); fheroes2::drawOption( areas[6], audioSettingsIcon, _( "Audio" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const fheroes2::Sprite & hotkeysIcon = fheroes2::AGG::GetICN( ICN::GAME_OPTION_ICON, 0 ); fheroes2::drawOption( areas[7], hotkeysIcon, _( "Hot Keys" ), _( "Configure" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); const bool isShowBattleDamageInfoEnabled = conf.isBattleShowDamageInfoEnabled(); const fheroes2::Sprite & damageInfoIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, isShowBattleDamageInfoEnabled ? 4 : 3 ); fheroes2::drawOption( areas[8], damageInfoIcon, _( "Damage Info" ), isShowBattleDamageInfoEnabled ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } DialogAction openBattleOptionDialog( bool & saveConfiguration ) { fheroes2::Display & display = fheroes2::Display::instance(); // Set the cursor image. This dialog is called from the battlefield and does not require a cursor restorer. // Battlefield event processor will set the appropriate cursor after this dialog is closed. Cursor::Get().SetThemes( Cursor::POINTER ); fheroes2::StandardWindow background( 289, 382, true, display ); const fheroes2::Rect windowRoi = background.activeArea(); Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Button buttonOk; const int buttonOkIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcnId, 0, 1, { 0, 5 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); fheroes2::ImageRestorer emptyDialogRestorer( display, windowRoi.x, windowRoi.y, windowRoi.width, windowRoi.height ); const fheroes2::Sprite & panelSprite = fheroes2::AGG::GetICN( ICN::CSPANEL, 0 ); const int32_t panelWidth = panelSprite.width(); const int32_t panelHeight = panelSprite.height(); const fheroes2::Point optionOffset( windowRoi.x + 20, windowRoi.y + 31 ); const fheroes2::Point optionStep( 92, 110 ); std::vector optionAreas; optionAreas.reserve( 9 ); for ( int32_t y = 0; y < 3; ++y ) { for ( int32_t x = 0; x < 3; ++x ) { optionAreas.emplace_back( optionOffset.x + x * optionStep.x, optionOffset.y + y * optionStep.y, panelWidth, panelHeight ); } } RedrawBattleSettings( optionAreas ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); bool redrawScreen = false; if ( le.isMouseWheelUpInArea( optionAreas[0] ) ) { conf.SetBattleSpeed( conf.BattleSpeed() + 1 ); Game::UpdateGameSpeed(); redrawScreen = true; } else if ( le.isMouseWheelDownInArea( optionAreas[0] ) ) { conf.SetBattleSpeed( conf.BattleSpeed() - 1 ); Game::UpdateGameSpeed(); redrawScreen = true; } else if ( le.MouseClickLeft( optionAreas[0] ) ) { conf.SetBattleSpeed( conf.BattleSpeed() % 10 + 1 ); Game::UpdateGameSpeed(); redrawScreen = true; } else if ( le.MouseClickLeft( optionAreas[1] ) ) { conf.setBattleShowTurnOrder( !conf.BattleShowTurnOrder() ); redrawScreen = true; } else if ( le.MouseClickLeft( optionAreas[2] ) ) { conf.setBattleAutoSpellcast( !conf.BattleAutoSpellcast() ); redrawScreen = true; } else if ( le.MouseClickLeft( optionAreas[3] ) ) { conf.SetBattleGrid( !conf.BattleShowGrid() ); redrawScreen = true; } else if ( le.MouseClickLeft( optionAreas[4] ) ) { conf.SetBattleMovementShaded( !conf.BattleShowMoveShadow() ); redrawScreen = true; } else if ( le.MouseClickLeft( optionAreas[5] ) ) { conf.SetBattleMouseShaded( !conf.BattleShowMouseShadow() ); redrawScreen = true; } else if ( le.MouseClickLeft( optionAreas[6] ) ) { return DialogAction::AudioSettings; } if ( le.MouseClickLeft( optionAreas[7] ) ) { return DialogAction::HotKeys; } if ( le.MouseClickLeft( optionAreas[8] ) ) { conf.setBattleDamageInfo( !conf.isBattleShowDamageInfoEnabled() ); redrawScreen = true; } else if ( le.isMouseRightButtonPressedInArea( optionAreas[0] ) ) { fheroes2::showStandardTextMessage( _( "Speed" ), _( "Set the speed of combat actions and animations." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[1] ) ) { fheroes2::showStandardTextMessage( _( "Turn Order" ), _( "Toggle to display the turn order during the battle." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[2] ) ) { fheroes2::showStandardTextMessage( _( "Auto Spell Casting" ), _( "Toggle whether or not the computer will cast spells for you when auto combat is on. (Note: This does not affect spell casting for computer players in any way, nor does it affect quick combat.)" ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[3] ) ) { fheroes2::showStandardTextMessage( _( "Grid" ), _( "Toggle the hex grid on or off. The hex grid always underlies movement, even if turned off. This switch only determines if the grid is visible." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[4] ) ) { fheroes2::showStandardTextMessage( _( "Shadow Movement" ), _( "Toggle on or off shadows showing where your creatures can move and attack." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[5] ) ) { fheroes2::showStandardTextMessage( _( "Shadow Cursor" ), _( "Toggle on or off a shadow showing the current hex location of the mouse cursor." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[6] ) ) { fheroes2::showStandardTextMessage( _( "Audio" ), _( "Change the audio settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[7] ) ) { fheroes2::showStandardTextMessage( _( "Hot Keys" ), _( "Check and configure all the hot keys present in the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( optionAreas[8] ) ) { fheroes2::showStandardTextMessage( _( "Damage Info" ), _( "Toggle to display damage information during the battle." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } if ( Game::HotKeyCloseWindow() || le.MouseClickLeft( buttonOk.area() ) ) { break; } if ( redrawScreen ) { emptyDialogRestorer.restore(); RedrawBattleSettings( optionAreas ); display.render( emptyDialogRestorer.rect() ); saveConfiguration = true; } } return DialogAction::Close; } } namespace Battle { void GetSummaryParams( const uint32_t res1, const uint32_t res2, const HeroBase * hero, const uint32_t exp, const uint32_t surrenderCost, LoopedAnimationSequence & sequence, std::string & title, std::string & surrenderText, std::string & outcomeText ); } void Battle::DialogBattleSettings() { // We should make file writing only once. bool saveConfiguration = false; const Settings & conf = Settings::Get(); DialogAction action = DialogAction::Open; while ( action != DialogAction::Close ) { switch ( action ) { case DialogAction::Open: action = openBattleOptionDialog( saveConfiguration ); break; case DialogAction::AudioSettings: saveConfiguration |= Dialog::openAudioSettingsDialog( false ); action = DialogAction::Open; break; case DialogAction::HotKeys: fheroes2::openHotkeysDialog(); action = DialogAction::Open; break; default: break; } } if ( saveConfiguration ) { conf.Save( Settings::configFileName ); } } void Battle::GetSummaryParams( const uint32_t res1, const uint32_t res2, const HeroBase * hero, const uint32_t exp, const uint32_t surrenderCost, LoopedAnimationSequence & sequence, std::string & title, std::string & surrenderText, std::string & outcomeText ) { if ( res1 & RESULT_WINS ) { sequence.push( ICN::WINCMBT, true ); if ( res2 & RESULT_SURRENDER ) { title.append( _( "The enemy has surrendered!" ) ); surrenderText.append( _( "Their cowardice costs them %{gold} gold." ) ); StringReplace( surrenderText, "%{gold}", surrenderCost ); } else if ( res2 & RESULT_RETREAT ) { title.append( _( "The enemy has fled!" ) ); } else { title.append( _( "A glorious victory!" ) ); } if ( hero && hero->isHeroes() ) { outcomeText.append( _( "For valor in combat, %{name} receives %{exp} experience." ) ); StringReplace( outcomeText, "%{name}", hero->GetName() ); StringReplace( outcomeText, "%{exp}", exp ); } } else if ( res1 & RESULT_RETREAT ) { assert( hero != nullptr ); sequence.push( ICN::CMBTFLE1, false ); sequence.push( ICN::CMBTFLE2, false ); sequence.push( ICN::CMBTFLE3, false ); title.append( _( "The cowardly %{name} flees from battle." ) ); StringReplace( title, "%{name}", hero->GetName() ); } else if ( res1 & RESULT_SURRENDER ) { assert( hero != nullptr ); sequence.push( ICN::CMBTSURR, true ); title.append( _( "%{name} surrenders to the enemy, and departs in shame." ) ); StringReplace( title, "%{name}", hero->GetName() ); } else { sequence.push( ICN::CMBTLOS1, false ); sequence.push( ICN::CMBTLOS2, false ); sequence.push( ICN::CMBTLOS3, true ); if ( hero && hero->isHeroes() ) { title.append( _( "Your forces suffer a bitter defeat, and %{name} abandons your cause." ) ); StringReplace( title, "%{name}", hero->GetName() ); } else { title.append( _( "Your forces suffer a bitter defeat." ) ); } } } // Returns true if player wants to restart the battle bool Battle::Arena::DialogBattleSummary( const Result & res, const std::vector & artifacts, const bool allowToRestart ) const { const bool attackerIsHuman = _army1->GetControl() & CONTROL_HUMAN; const bool defenderIsHuman = _army2->GetControl() & CONTROL_HUMAN; if ( !attackerIsHuman && !defenderIsHuman ) { // AI vs AI battle, this dialog should not be shown assert( 0 ); return false; } fheroes2::Display & display = fheroes2::Display::instance(); // Set the cursor image. After this dialog the Game Area or the Battlefield will be shown, so it does not require a cursor restorer. Cursor::Get().SetThemes( Cursor::POINTER ); fheroes2::StandardWindow background( bsTextWidth + 32, 424, true, display ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & originalBorderImage = fheroes2::AGG::GetICN( isEvilInterface ? ICN::WINLOSEE : ICN::WINLOSE, 0 ); const fheroes2::Rect animationBorderRoi{ 43, 32, 231, 133 }; const fheroes2::Rect & roi( background.activeArea() ); const fheroes2::Rect animationRoi( roi.x + ( ( roi.width - animationBorderRoi.width ) / 2 ) + 4, roi.y + 21, animationBorderRoi.width, animationBorderRoi.height ); Copy( originalBorderImage, animationBorderRoi.x, animationBorderRoi.y, display, animationRoi.x - 4, animationRoi.y - 4, animationRoi.width, animationRoi.height ); // Setup summary texts according to results and get the corresponding animation sequence. std::string surrenderText; std::string outcomeText; std::string title; LoopedAnimationSequence sequence; fheroes2::FontType summaryTitleFont = fheroes2::FontType::normalWhite(); if ( ( res.army1 & RESULT_WINS ) && attackerIsHuman ) { GetSummaryParams( res.army1, res.army2, _army1->GetCommander(), res.exp1, _army2->GetSurrenderCost(), sequence, title, surrenderText, outcomeText ); summaryTitleFont = fheroes2::FontType::normalYellow(); AudioManager::PlayMusic( MUS::BATTLEWIN, Music::PlaybackMode::PLAY_ONCE ); } else if ( ( res.army2 & RESULT_WINS ) && defenderIsHuman ) { GetSummaryParams( res.army2, res.army1, _army2->GetCommander(), res.exp2, _army1->GetSurrenderCost(), sequence, title, surrenderText, outcomeText ); summaryTitleFont = fheroes2::FontType::normalYellow(); AudioManager::PlayMusic( MUS::BATTLEWIN, Music::PlaybackMode::PLAY_ONCE ); } else if ( attackerIsHuman ) { GetSummaryParams( res.army1, res.army2, _army1->GetCommander(), res.exp1, 0, sequence, title, surrenderText, outcomeText ); AudioManager::PlayMusic( MUS::BATTLELOSE, Music::PlaybackMode::PLAY_ONCE ); } else if ( defenderIsHuman ) { GetSummaryParams( res.army2, res.army1, _army2->GetCommander(), res.exp2, 0, sequence, title, surrenderText, outcomeText ); AudioManager::PlayMusic( MUS::BATTLELOSE, Music::PlaybackMode::PLAY_ONCE ); } if ( sequence.isFinished() ) { // This shouldn't happen assert( 0 ); sequence.push( ICN::UNKNOWN, false ); } setupAnimation( display, animationRoi, sequence ); const fheroes2::Rect summaryRoi( roi.x + 11, roi.y + bsTextYOffset, roi.width - 22, roi.height - bsTextYOffset ); fheroes2::ImageRestorer summaryBackground( display, summaryRoi.x, summaryRoi.y, roi.width, summaryRoi.height ); const int32_t casualtiesOffsetY = summaryRoi.y + 96; int32_t summaryBodyOffset = summaryRoi.y; int32_t remainingSummaryBodyHeight = casualtiesOffsetY - summaryBodyOffset; // Draw texts if ( !title.empty() ) { fheroes2::Text box( title, summaryTitleFont ); box.setUniformVerticalAlignment( false ); box.draw( summaryRoi.x, summaryBodyOffset, summaryRoi.width, display ); summaryBodyOffset += box.height( summaryRoi.width ); remainingSummaryBodyHeight -= box.height( summaryRoi.width ); } const fheroes2::FontType bodyFont = fheroes2::FontType::normalWhite(); if ( !outcomeText.empty() ) { if ( !surrenderText.empty() ) { // Divide the main text area evenly between the two texts bodies by splitting it into 3 equal parts. fheroes2::Text upperText( surrenderText, bodyFont ); fheroes2::Text lowerText( outcomeText, bodyFont ); const int32_t inbetweenSpace = ( remainingSummaryBodyHeight - upperText.height( summaryRoi.width ) - lowerText.height( summaryRoi.width ) ) / 3; upperText.setUniformVerticalAlignment( false ); lowerText.setUniformVerticalAlignment( false ); upperText.draw( summaryRoi.x, summaryBodyOffset + inbetweenSpace, summaryRoi.width, display ); lowerText.draw( summaryRoi.x, summaryBodyOffset + upperText.height( summaryRoi.width ) + inbetweenSpace * 2, summaryRoi.width, display ); } else { fheroes2::Text upperText( outcomeText, bodyFont ); upperText.setUniformVerticalAlignment( false ); upperText.draw( summaryRoi.x, summaryBodyOffset + remainingSummaryBodyHeight / 2 - ( upperText.height( summaryRoi.width ) / 2 ), summaryRoi.width, display ); } } else if ( !surrenderText.empty() ) { const fheroes2::Text upperText( surrenderText, bodyFont ); upperText.draw( summaryRoi.x, summaryBodyOffset + remainingSummaryBodyHeight / 2 - ( upperText.height( summaryRoi.width ) / 2 ), summaryRoi.width, display ); } // Battlefield casualties const fheroes2::FontType casualtiesFont = fheroes2::FontType::smallWhite(); fheroes2::Text text( _( "Battlefield Casualties" ), casualtiesFont ); text.draw( summaryRoi.x + ( summaryRoi.width - text.width() ) / 2, casualtiesOffsetY, display ); // Attacker text.set( _( "Attacker" ), casualtiesFont ); text.draw( summaryRoi.x + ( summaryRoi.width - text.width() ) / 2, casualtiesOffsetY + 15, display ); const Troops killed1 = _army1->GetKilledTroops(); const Troops killed2 = _army2->GetKilledTroops(); if ( killed1.isValid() ) { Army::drawSingleDetailedMonsterLine( killed1, summaryRoi.x + 13, casualtiesOffsetY + 36, roi.width - 47 ); } else { text.set( _( "None" ), casualtiesFont ); text.draw( summaryRoi.x + ( summaryRoi.width - text.width() ) / 2, casualtiesOffsetY + 30, display ); } // defender text.set( _( "Defender" ), casualtiesFont ); text.draw( summaryRoi.x + ( summaryRoi.width - text.width() ) / 2, casualtiesOffsetY + 75, display ); if ( killed2.isValid() ) { Army::drawSingleDetailedMonsterLine( killed2, summaryRoi.x + 13, casualtiesOffsetY + 96, roi.width - 47 ); } else { text.set( _( "None" ), casualtiesFont ); text.draw( summaryRoi.x + ( summaryRoi.width - text.width() ) / 2, casualtiesOffsetY + 90, display ); } int32_t buttonHorizontalMargin = 0; const int32_t buttonVerticalMargin = 5; std::unique_ptr buttonRestart; if ( allowToRestart ) { buttonRestart = std::make_unique(); buttonHorizontalMargin = 23; background.renderButton( *buttonRestart, isEvilInterface ? ICN::BUTTON_SMALL_RESTART_EVIL : ICN::BUTTON_SMALL_RESTART_GOOD, 0, 1, { buttonHorizontalMargin, buttonVerticalMargin }, fheroes2::StandardWindow::Padding::BOTTOM_RIGHT ); } const int buttonOkICN = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; fheroes2::Button buttonOk; const fheroes2::StandardWindow::Padding buttonOkPadding = allowToRestart ? fheroes2::StandardWindow::Padding::BOTTOM_LEFT : fheroes2::StandardWindow::Padding::BOTTOM_CENTER; background.renderButton( buttonOk, buttonOkICN, 0, 1, { buttonHorizontalMargin, buttonVerticalMargin }, buttonOkPadding ); if ( Game::validateDisplayFadeIn() ) { fheroes2::fadeInDisplay(); } else { display.render( background.totalArea() ); } LocalEvent & le = LocalEvent::Get(); int sequenceId = sequence.id(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( allowToRestart ) { buttonRestart->drawOnState( le.isMouseLeftButtonPressedInArea( buttonRestart->area() ) ); } if ( Game::HotKeyCloseWindow() || le.MouseClickLeft( buttonOk.area() ) ) { break; } if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to leave the battle results." ), Dialog::ZERO ); } else if ( allowToRestart ) { if ( le.MouseClickLeft( buttonRestart->area() ) ) { // Skip artifact transfer and return to restart the battle in manual mode return true; } if ( le.isMouseRightButtonPressedInArea( buttonRestart->area() ) ) { fheroes2::showStandardTextMessage( _( "Restart" ), _( "Click to restart the battle in manual mode." ), Dialog::ZERO ); } } updateAnimation( display, sequenceId, sequence, animationRoi ); } // Free memory because RESTART button is not used more. if ( allowToRestart ) { buttonRestart.reset(); } if ( !artifacts.empty() ) { const HeroBase * winner = ( res.army1 & RESULT_WINS ? _army1->GetCommander() : ( res.army2 & RESULT_WINS ? _army2->GetCommander() : nullptr ) ); const HeroBase * loser = ( res.army1 & RESULT_LOSS ? _army1->GetCommander() : ( res.army2 & RESULT_LOSS ? _army2->GetCommander() : nullptr ) ); // Cannot transfer artifacts if ( winner == nullptr || loser == nullptr ) { return false; } const bool isWinnerHuman = winner && winner->isControlHuman(); // Nothing to do if the AI won and there are no Ultimate Artifacts. if ( !isWinnerHuman && !loser->GetBagArtifacts().ContainUltimateArtifact() ) { return false; } summaryBackground.restore(); background.renderButton( buttonOk, buttonOkICN, 0, 1, { 0, buttonVerticalMargin }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); const fheroes2::Sprite & border = fheroes2::AGG::GetICN( ICN::WINLOSEB, 0 ); const fheroes2::Rect artifactArea( summaryRoi.x + ( summaryRoi.width - border.width() ) / 2, casualtiesOffsetY + 38, border.width(), border.height() ); Copy( border, 0, 0, display, artifactArea.x, artifactArea.y, artifactArea.width, artifactArea.height ); fheroes2::ImageRestorer artifactHeader( display, summaryRoi.x, summaryRoi.y, summaryRoi.width, 66 ); fheroes2::ImageRestorer artifactName( display, summaryRoi.x, artifactArea.y + artifactArea.height, summaryRoi.width, 18 ); std::string artMsg; display.render( summaryRoi ); bool needHeaderRedraw = false; int prevArtifactId = -1; for ( const Artifact & art : artifacts ) { // Only the Ultimate Artifacts are shown for both the winner and loser's dialogs. Skip if it is a regular artifact and the AI won. if ( !isWinnerHuman && !art.isUltimate() ) { continue; } // If two identical artifacts go in a row, then we do not need to redraw anything, but only play the sound if necessary. if ( prevArtifactId == art.GetID() ) { // Sound is never played for Ultimate Artifact messages. if ( isWinnerHuman && !art.isUltimate() ) { Game::PlayPickupSound(); } } else { const char * const artName = art.GetName(); if ( !art.isUltimate() ) { // Only draw the regular artifact header once. if ( !needHeaderRedraw ) { artMsg = _( "You have captured an enemy artifact!" ); const fheroes2::Text box( artMsg, fheroes2::FontType::normalYellow() ); box.draw( summaryRoi.x, summaryRoi.y, summaryRoi.width, display ); needHeaderRedraw = true; } Game::PlayPickupSound(); } else { // Ultimate artifacts are always displayed after all the regular artifacts. if ( needHeaderRedraw ) { artifactHeader.restore(); } if ( isWinnerHuman ) { artMsg = _( "As you reach for the %{name}, it mysteriously disappears." ); } else { artMsg = _( "As your enemy reaches for the %{name}, it mysteriously disappears." ); } StringReplace( artMsg, "%{name}", artName ); const fheroes2::Text box( artMsg, fheroes2::FontType::normalYellow() ); box.draw( summaryRoi.x, summaryRoi.y, summaryRoi.width, display ); needHeaderRedraw = true; } const fheroes2::Sprite & artifact = fheroes2::AGG::GetICN( ICN::ARTIFACT, art.IndexSprite64() ); Copy( artifact, 0, 0, display, artifactArea.x + 8, artifactArea.y + 8, artifact.width(), artifact.height() ); artifactName.restore(); const fheroes2::Text artNameText( artName, fheroes2::FontType::smallWhite() ); artNameText.draw( summaryRoi.x, artifactArea.y + border.height() + 7, summaryRoi.width, display ); prevArtifactId = art.GetID(); display.render( summaryRoi ); } while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); // Display captured artifact info on right click if ( le.isMouseRightButtonPressedInArea( artifactArea ) ) { fheroes2::ArtifactDialogElement( art ).showPopup( Dialog::ZERO ); } else if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), Dialog::ZERO ); } updateAnimation( display, sequenceId, sequence, animationRoi ); } } } return false; } void Battle::Arena::DialogBattleNecromancy( const uint32_t raiseCount ) { // Set the cursor image. This dialog does not require a cursor restorer. Cursor::Get().SetThemes( Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 287, 424, true, display ); // Animation border const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & originalBorderImage = fheroes2::AGG::GetICN( isEvilInterface ? ICN::WINLOSEE : ICN::WINLOSE, 0 ); const fheroes2::Rect animationBorderRoi{ 43, 32, 231, 133 }; const fheroes2::Rect & roi( background.activeArea() ); const fheroes2::Rect animationRoi( roi.x + ( ( roi.width - animationBorderRoi.width ) / 2 ) + 4, roi.y + 20, animationBorderRoi.width, animationBorderRoi.height ); Copy( originalBorderImage, animationBorderRoi.x, animationBorderRoi.y, display, animationRoi.x - 4, animationRoi.y - 4, animationRoi.width, animationRoi.height ); LoopedAnimationSequence sequence; setupAnimation( display, animationRoi, sequence ); // Text stuff int yOffset = animationRoi.y + animationRoi.height + 8; const fheroes2::Text titleBox( _( "Necromancy!" ), fheroes2::FontType::normalYellow() ); titleBox.draw( roi.x, yOffset, roi.width, display ); const Monster mons( Monster::SKELETON ); std::string msg = _( "Practicing the dark arts of necromancy, you are able to raise %{count} of the enemy's dead to return under your service as %{monster}." ); StringReplace( msg, "%{count}", raiseCount ); StringReplace( msg, "%{monster}", mons.GetPluralName( raiseCount ) ); const fheroes2::Text messageBox( msg, fheroes2::FontType::normalWhite() ); yOffset += bsTextIndent; const int32_t messageWidth = roi.width - 22; messageBox.draw( roi.x + 11, yOffset, messageWidth, display ); const fheroes2::Sprite & monsterSprite = fheroes2::AGG::GetICN( ICN::MONS32, mons.GetSpriteIndex() ); yOffset += messageBox.height( messageWidth ) + monsterSprite.height() - 2; fheroes2::Blit( monsterSprite, display, ( display.width() - monsterSprite.width() ) / 2, yOffset ); fheroes2::Text raiseCountText( std::to_string( raiseCount ), fheroes2::FontType::smallWhite() ); raiseCountText.fitToOneRow( roi.width ); yOffset += 30; raiseCountText.draw( ( display.width() - raiseCountText.width() ) / 2, yOffset + 2, display ); Game::PlayPickupSound(); // Button const int buttonICN = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; fheroes2::Button buttonOk; background.renderButton( buttonOk, buttonICN, 0, 1, { 0, 5 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); display.render( roi ); LocalEvent & le = LocalEvent::Get(); int sequenceId = sequence.id(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( Game::HotKeyCloseWindow() || le.MouseClickLeft( buttonOk.area() ) ) { break; } updateAnimation( display, sequenceId, sequence, animationRoi ); } } int Battle::Arena::DialogBattleHero( HeroBase & hero, const bool buttons, Status & status ) const { const Settings & conf = Settings::Get(); Cursor & cursor = Cursor::Get(); cursor.SetThemes( Cursor::POINTER ); const int currentColor = GetCurrentColor(); const bool readonly = ( currentColor != hero.GetColor() || !buttons ); const fheroes2::Sprite & dialog = fheroes2::AGG::GetICN( ( conf.isEvilInterfaceEnabled() ? ICN::VGENBKGE : ICN::VGENBKG ), 0 ); const fheroes2::Point dialogShadow( 15, 15 ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Rect pos_rt( ( display.width() - dialog.width() - dialogShadow.x ) / 2, ( display.height() - dialog.height() - dialogShadow.y ) / 2, dialog.width(), dialog.height() ); fheroes2::ImageRestorer back( display, pos_rt.x, pos_rt.y, pos_rt.width, pos_rt.height ); fheroes2::Blit( dialog, display, pos_rt.x, pos_rt.y ); // first 15 pixels in the dialog is left shadow, skip pos_rt.x += dialogShadow.x; pos_rt.width -= dialogShadow.x; const fheroes2::Rect portraitArea( pos_rt.x + 7, pos_rt.y + 35, 113, 108 ); hero.PortraitRedraw( pos_rt.x + 12, pos_rt.y + 42, PORT_BIG, display ); int col = ( Color::NONE == hero.GetColor() ? 1 : Color::GetIndex( hero.GetColor() ) + 1 ); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::VIEWGEN, col ), display, pos_rt.x + 133, pos_rt.y + 36 ); std::string str = hero.isCaptain() ? _( "Captain of %{name}" ) : _( "%{name} the %{race}" ); StringReplace( str, "%{name}", hero.GetName() ); StringReplace( str, "%{race}", Race::String( hero.GetRace() ) ); fheroes2::Text text( str, fheroes2::FontType::smallWhite() ); fheroes2::Point tp{ pos_rt.x + ( pos_rt.width - text.width() ) / 2, pos_rt.y + 11 }; text.draw( tp.x, tp.y + 2, display ); const int32_t letterShadowCompensation = 1; const fheroes2::Point statsTextOffset{ pos_rt.x + 133 + letterShadowCompensation, pos_rt.y + 40 }; const int32_t maxStatsTextWidth{ 109 }; const int32_t statsTextRowHeight{ 11 }; str = _( "Attack" ) + std::string( ": " ) + std::to_string( hero.GetAttack() ); text.set( str, fheroes2::FontType::smallWhite() ); tp.x = statsTextOffset.x + ( maxStatsTextWidth - text.width() ) / 2; tp.y = statsTextOffset.y; text.draw( tp.x, tp.y + 2, display ); str = _( "Defense" ) + std::string( ": " ) + std::to_string( hero.GetDefense() ); text.set( str, fheroes2::FontType::smallWhite() ); tp.x = statsTextOffset.x + ( maxStatsTextWidth - text.width() ) / 2; tp.y += statsTextRowHeight; text.draw( tp.x, tp.y + 2, display ); str = _( "Spell Power" ) + std::string( ": " ) + std::to_string( hero.GetPower() ); text.set( str, fheroes2::FontType::smallWhite() ); tp.x = statsTextOffset.x + ( maxStatsTextWidth - text.width() ) / 2; tp.y += statsTextRowHeight; text.draw( tp.x, tp.y + 2, display ); str = _( "Knowledge" ) + std::string( ": " ) + std::to_string( hero.GetKnowledge() ); text.set( str, fheroes2::FontType::smallWhite() ); tp.x = statsTextOffset.x + ( maxStatsTextWidth - text.width() ) / 2; tp.y += statsTextRowHeight; text.draw( tp.x, tp.y + 2, display ); str = _( "Morale" ) + std::string( ": " ) + Morale::String( hero.GetMorale() ); text.set( str, fheroes2::FontType::smallWhite() ); tp.x = statsTextOffset.x; tp.y += statsTextRowHeight; text.setUniformVerticalAlignment( false ); text.draw( tp.x, tp.y + 2, maxStatsTextWidth, display ); tp.y += text.height( maxStatsTextWidth ); str = _( "Luck" ) + std::string( ": " ) + Luck::String( hero.GetLuck() ); text.set( str, fheroes2::FontType::smallWhite() ); tp.x = statsTextOffset.x; text.draw( tp.x, tp.y + 2, maxStatsTextWidth, display ); tp.y += text.height( maxStatsTextWidth ); str = _( "Spell Points" ) + std::string( ": " ) + std::to_string( hero.GetSpellPoints() ) + "/" + std::to_string( hero.GetMaxSpellPoints() ); text.set( str, fheroes2::FontType::smallWhite() ); tp.x = statsTextOffset.x; // By default the spell points should have one line of space between it and the Luck, but if there isn't // any space due to morale and luck taking up four lines, then move it down to the lowest line. const int32_t compensation = ( tp.y - ( statsTextOffset.y + 88 ) ) == 0 ? 11 : 0; text.draw( tp.x, statsTextOffset.y + 79 + compensation, maxStatsTextWidth, display ); fheroes2::Button btnCast( pos_rt.x + 15, pos_rt.y + 148, ICN::VIEWGEN, 9, 10 ); fheroes2::Button btnRetreat( pos_rt.x + 74, pos_rt.y + 148, ICN::VIEWGEN, 11, 12 ); fheroes2::Button btnSurrender( pos_rt.x + 133, pos_rt.y + 148, ICN::VIEWGEN, 13, 14 ); fheroes2::Button btnClose( pos_rt.x + 192, pos_rt.y + 148, ICN::VIEWGEN, 15, 16 ); if ( readonly || !hero.HaveSpellBook() || hero.Modes( Heroes::SPELLCASTED ) ) { btnCast.disable(); } if ( readonly || !CanRetreatOpponent( hero.GetColor() ) ) { btnRetreat.disable(); } if ( readonly || !CanSurrenderOpponent( hero.GetColor() ) ) { btnSurrender.disable(); } btnCast.draw(); btnRetreat.draw(); btnSurrender.draw(); int result = 0; LocalEvent & le = LocalEvent::Get(); if ( !buttons ) { // This is a case when this dialog was called by the right mouse button press. btnClose.disable(); btnClose.draw(); display.render( pos_rt ); while ( le.HandleEvents() ) { if ( !le.isMouseRightButtonPressed() ) { break; } } return result; } btnClose.draw(); display.render( pos_rt ); // The Hero Screen is available for a Hero only (not Captain) and only when the corresponding player has a turn. Heroes * heroForHeroScreen = ( currentColor == hero.GetColor() ) ? dynamic_cast( &hero ) : nullptr; std::string statusMessage = _( "Hero's Options" ); while ( le.HandleEvents() && !result ) { if ( btnCast.isEnabled() ) { btnCast.drawOnState( le.isMouseLeftButtonPressedInArea( btnCast.area() ) ); } if ( btnRetreat.isEnabled() ) { btnRetreat.drawOnState( le.isMouseLeftButtonPressedInArea( btnRetreat.area() ) ); } if ( btnSurrender.isEnabled() ) { btnSurrender.drawOnState( le.isMouseLeftButtonPressedInArea( btnSurrender.area() ) ); } btnClose.drawOnState( le.isMouseLeftButtonPressedInArea( btnClose.area() ) ); // The Cast Spell is available for a hero and a captain. if ( le.isMouseCursorPosInArea( btnCast.area() ) && currentColor == hero.GetColor() ) { statusMessage = _( "Cast Spell" ); } // The retreat is available during a player's turn only. A captain cannot retreat. else if ( le.isMouseCursorPosInArea( btnRetreat.area() ) && currentColor == hero.GetColor() && !hero.isCaptain() ) { statusMessage = _( "Retreat" ); } // The surrender is available during a player's turn only. A captain cannot surrender. else if ( le.isMouseCursorPosInArea( btnSurrender.area() ) && currentColor == hero.GetColor() && !hero.isCaptain() ) { statusMessage = _( "Surrender" ); } else if ( le.isMouseCursorPosInArea( btnClose.area() ) ) { statusMessage = _( "Cancel" ); } // The Hero Screen is available for a Hero only (not Captain) and only when the corresponding player has a turn. else if ( le.isMouseCursorPosInArea( portraitArea ) && heroForHeroScreen != nullptr ) { statusMessage = _( "Hero Screen" ); } else if ( hero.isCaptain() ) { statusMessage = _( "Captain's Options" ); } else { statusMessage = _( "Hero's Options" ); } if ( Game::HotKeyCloseWindow() || le.MouseClickLeft( btnClose.area() ) ) { break; } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_CAST_SPELL ) || ( btnCast.isEnabled() && le.MouseClickLeft( btnCast.area() ) ) ) { result = 1; } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_RETREAT ) || ( btnRetreat.isEnabled() && le.MouseClickLeft( btnRetreat.area() ) ) ) { result = 2; } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_SURRENDER ) || ( btnSurrender.isEnabled() && le.MouseClickLeft( btnSurrender.area() ) ) ) { result = 3; } if ( le.MouseClickLeft( portraitArea ) && heroForHeroScreen != nullptr ) { LocalEvent::Get().reset(); heroForHeroScreen->OpenDialog( true, true, true, true, false, false, fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() ) ); // Fade-in to restore the screen after closing the hero dialog. fheroes2::fadeInDisplay( _interface->GetInterfaceRoi(), !display.isDefaultSize() ); } if ( le.isMouseRightButtonPressedInArea( btnCast.area() ) && currentColor == hero.GetColor() ) { fheroes2::showStandardTextMessage( _( "Cast Spell" ), _( "Cast a magical spell. You may only cast one spell per combat round. The round is reset when every creature has had a turn." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( btnRetreat.area() ) && currentColor == hero.GetColor() && !hero.isCaptain() ) { fheroes2::showStandardTextMessage( _( "Retreat" ), _( "Retreat your hero, abandoning your creatures. Your hero will be available for you to recruit again, however, the hero will have only a novice hero's forces." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( btnSurrender.area() ) && currentColor == hero.GetColor() && !hero.isCaptain() ) { fheroes2::showStandardTextMessage( _( "Surrender" ), _( "Surrendering costs gold. However if you pay the ransom, the hero and all of his or her surviving creatures will be available to recruit again. The cost of surrender is half of the total cost of the non-temporary troops remaining in the army." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( portraitArea ) && heroForHeroScreen != nullptr ) { fheroes2::showStandardTextMessage( _( "Hero Screen" ), _( "Open Hero Screen to view full information about the hero." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( btnClose.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Return to the battle." ), Dialog::ZERO ); } if ( statusMessage != status.getMessage() ) { status.setMessage( statusMessage, false ); status.redraw( display ); display.render( status ); } } return result; } bool Battle::DialogBattleSurrender( const HeroBase & hero, uint32_t cost, Kingdom & kingdom ) { if ( kingdom.GetColor() == hero.GetColor() ) { // This is weird. You're surrendering to yourself! assert( 0 ); return false; } fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); const Settings & conf = Settings::Get(); // Set the cursor image. After this dialog the Game Area or the Battlefield will be shown, so it does not require a cursor restorer. Cursor::Get().SetThemes( Cursor::POINTER ); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const fheroes2::Sprite & dialog = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SURDRBKE : ICN::SURDRBKG, 0 ); fheroes2::Rect pos_rt( ( display.width() - dialog.width() + 16 ) / 2, ( display.height() - dialog.height() + 16 ) / 2, dialog.width(), dialog.height() ); fheroes2::Blit( dialog, display, pos_rt.x, pos_rt.y ); const int icnAccept = isEvilInterface ? ICN::BUTTON_SMALL_ACCEPT_EVIL : ICN::BUTTON_SMALL_ACCEPT_GOOD; const int icnDecline = isEvilInterface ? ICN::BUTTON_SMALL_DECLINE_EVIL : ICN::BUTTON_SMALL_DECLINE_GOOD; const int icnMarket = isEvilInterface ? ICN::EVIL_MARKET_BUTTON : ICN::GOOD_MARKET_BUTTON; fheroes2::ButtonSprite btnAccept = fheroes2::makeButtonWithShadow( pos_rt.x + 91, pos_rt.y + 152, fheroes2::AGG::GetICN( icnAccept, 0 ), fheroes2::AGG::GetICN( icnAccept, 1 ), display ); fheroes2::ButtonSprite btnDecline = fheroes2::makeButtonWithShadow( pos_rt.x + 295, pos_rt.y + 152, fheroes2::AGG::GetICN( icnDecline, 0 ), fheroes2::AGG::GetICN( icnDecline, 1 ), display ); fheroes2::ButtonSprite btnMarket = fheroes2::makeButtonWithShadow( pos_rt.x + ( pos_rt.width - 16 ) / 2, pos_rt.y + 145, fheroes2::AGG::GetICN( icnMarket, 0 ), fheroes2::AGG::GetICN( icnMarket, 1 ), display ); if ( !kingdom.AllowPayment( Funds( Resource::GOLD, cost ) ) ) { btnAccept.disable(); } if ( kingdom.GetCountMarketplace() ) { if ( kingdom.AllowPayment( Funds( Resource::GOLD, cost ) ) ) { btnMarket.disable(); } else { btnMarket.draw(); } } else { btnMarket.disable(); } btnAccept.draw(); btnDecline.draw(); const auto drawGoldMsg = [cost, &kingdom, &display]( const fheroes2::Rect & btnAcceptArea ) { std::string str = _( "Not enough gold (%{gold})" ); StringReplace( str, "%{gold}", cost - kingdom.GetFunds().gold ); const fheroes2::Text text( str, fheroes2::FontType::smallWhite() ); // Since button area includes 3D effect on the left side we need to shift the text by X axis to center it in relation to the button. text.draw( btnAcceptArea.x + ( btnAcceptArea.width - text.width() ) / 2 + 2, btnAcceptArea.y - 13, display ); }; const int icn = isEvilInterface ? ICN::SURRENDE : ICN::SURRENDR; const fheroes2::Sprite & window = fheroes2::AGG::GetICN( icn, 4 ); fheroes2::Blit( window, display, pos_rt.x + 55, pos_rt.y + 32 ); hero.PortraitRedraw( pos_rt.x + 60, pos_rt.y + 38, PORT_BIG, display ); std::string str = hero.isCaptain() ? _( "Captain of %{name} states:" ) : _( "%{name} states:" ); StringReplace( str, "%{name}", hero.GetName() ); const fheroes2::Text text( str, fheroes2::FontType::normalWhite() ); text.draw( pos_rt.x + 312 - text.width() / 2, pos_rt.y + 32, display ); str = _( "\"I will accept your surrender and grant you and your troops safe passage for the price of %{price} gold.\"" ); StringReplace( str, "%{price}", cost ); fheroes2::Text box( str, fheroes2::FontType::normalWhite() ); box.draw( pos_rt.x + 175, pos_rt.y + 52, 275, display ); fheroes2::ImageRestorer back( display, pos_rt.x, pos_rt.y, pos_rt.width, pos_rt.height ); if ( !kingdom.AllowPayment( Funds( Resource::GOLD, cost ) ) ) { drawGoldMsg( btnAccept.area() ); } display.render(); bool result = false; while ( le.HandleEvents() && !result ) { if ( btnAccept.isEnabled() ) { btnAccept.drawOnState( le.isMouseLeftButtonPressedInArea( btnAccept.area() ) ); } btnDecline.drawOnState( le.isMouseLeftButtonPressedInArea( btnDecline.area() ) ); if ( btnMarket.isEnabled() ) { btnMarket.drawOnState( le.isMouseLeftButtonPressedInArea( btnMarket.area() ) ); } if ( btnAccept.isEnabled() && ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( btnAccept.area() ) ) ) { result = true; } if ( btnMarket.isEnabled() && le.MouseClickLeft( btnMarket.area() ) ) { Dialog::Marketplace( kingdom, false ); back.restore(); if ( kingdom.AllowPayment( Funds( Resource::GOLD, cost ) ) ) { btnAccept.enable(); } else { btnAccept.disable(); drawGoldMsg( btnAccept.area() ); } btnAccept.draw(); display.render(); } // exit if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( btnDecline.area() ) ) break; } return result; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_grave.cpp000066400000000000000000000074301476115357100231130ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_grave.h" #include #include #include #include "battle_troop.h" Battle::Indexes Battle::Graveyard::getOccupiedCells() const { Indexes result; result.reserve( size() ); for ( const auto & [idx, units] : *this ) { if ( units.empty() ) { continue; } result.push_back( idx ); } return result; } void Battle::Graveyard::addUnit( Unit * unit ) { assert( unit != nullptr && Board::isValidIndex( unit->GetHeadIndex() ) && ( unit->isWide() ? Board::isValidIndex( unit->GetTailIndex() ) : !Board::isValidIndex( unit->GetTailIndex() ) ) ); Graveyard & graveyard = *this; graveyard[unit->GetHeadIndex()].push_back( unit ); if ( unit->isWide() ) { graveyard[unit->GetTailIndex()].push_back( unit ); } } void Battle::Graveyard::removeUnit( Unit * unit ) { assert( unit != nullptr && Board::isValidIndex( unit->GetHeadIndex() ) && ( unit->isWide() ? Board::isValidIndex( unit->GetTailIndex() ) : !Board::isValidIndex( unit->GetTailIndex() ) ) ); const auto removeFromIndex = [this, unit]( const int32_t idx ) { const auto graveyardIter = find( idx ); if ( graveyardIter == end() ) { return; } auto & [dummy, units] = *graveyardIter; const auto unitsIter = std::find( units.begin(), units.end(), unit ); if ( unitsIter == units.end() ) { return; } units.erase( unitsIter ); }; removeFromIndex( unit->GetHeadIndex() ); if ( unit->isWide() ) { removeFromIndex( unit->GetTailIndex() ); } } Battle::Unit * Battle::Graveyard::getLastUnit( const int32_t index ) const { const auto iter = find( index ); if ( iter == end() ) { return nullptr; } const auto & [dummy, units] = *iter; if ( units.empty() ) { return nullptr; } return units.back(); } std::vector Battle::Graveyard::getUnits( const int32_t index ) const { const auto iter = find( index ); if ( iter == end() ) { return {}; } return iter->second; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_grave.h000066400000000000000000000044471476115357100225650ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "battle_board.h" namespace Battle { class Unit; class Graveyard : public std::map> { public: Graveyard() = default; Graveyard( const Graveyard & ) = delete; ~Graveyard() = default; Graveyard & operator=( const Graveyard & ) = delete; Indexes getOccupiedCells() const; void addUnit( Unit * unit ); void removeUnit( Unit * unit ); Unit * getLastUnit( const int32_t index ) const; std::vector getUnits( const int32_t index ) const; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_interface.cpp000066400000000000000000010116051476115357100237470ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_interface.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "audio.h" #include "audio_manager.h" #include "battle.h" // IWYU pragma: associated #include "battle_arena.h" #include "battle_army.h" #include "battle_bridge.h" #include "battle_catapult.h" #include "battle_cell.h" #include "battle_command.h" #include "battle_tower.h" #include "battle_troop.h" #include "bin_info.h" #include "castle.h" #include "color.h" #include "game.h" #include "game_delays.h" #include "game_hotkeys.h" #include "ground.h" #include "heroes_base.h" #include "interface_list.h" #include "localevent.h" #include "logging.h" #include "m82.h" #include "maps.h" #include "maps_tiles.h" #include "math_tools.h" #include "monster.h" #include "monster_anim.h" #include "monster_info.h" #include "mp2.h" #include "mus.h" #include "pal.h" #include "players.h" #include "race.h" #include "rand.h" #include "settings.h" #include "spell_book.h" #include "timing.h" #include "tools.h" #include "translations.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_scrollbar.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" class Kingdom; namespace { const int32_t cellYOffset = -9; const int32_t turnOrderMonsterIconSize = 43; // in both directions. // The parameters of castle buildings destruction by a catapult: // Smoke cloud frame number, after which the building should be drawn as destroyed. const int32_t castleBuildingDestroyFrame = 5; // Bridge demolition second smoke cloud offset from the first one after the catapult attack. const fheroes2::Point bridgeDestroySmokeOffset( -45, 65 ); // Smoke cloud frame number, after which the bridge should be drawn as destroyed. const int32_t bridgeDestroyFrame = 6; // The number of frames the second smoke cloud is delayed by. const int32_t bridgeDestroySmokeDelay = 2; const int32_t offsetForTextBar{ 32 }; const int32_t maxElementsInBattleLog{ 6 }; // This value must be equal to the height of Normal font. const int32_t battleLogElementHeight{ 17 }; const int32_t battleLogLastElementOffset{ 4 }; const int32_t battleLogElementWidth{ fheroes2::Display::DEFAULT_WIDTH - 32 - 16 }; struct LightningPoint { explicit LightningPoint( const fheroes2::Point & p = fheroes2::Point(), const int32_t thick = 1 ) : point( p ) , thickness( thick ) { // Do nothing. } fheroes2::Point point; int32_t thickness; }; double getDistance( const fheroes2::Point & p1, const fheroes2::Point & p2 ) { return std::hypot( p1.x - p2.x, p1.y - p2.y ); } fheroes2::Point rotate( const fheroes2::Point & point, double angle ) { const double sinValue = sin( angle ); const double cosValue = cos( angle ); return { static_cast( std::round( point.x * cosValue - point.y * sinValue ) ), static_cast( std::round( point.x * sinValue + point.y * cosValue ) ) }; } double getAngle( const fheroes2::Point & start, const fheroes2::Point & end ) { return std::atan2( end.y - start.y, end.x - start.x ); } std::vector> GenerateLightning( const fheroes2::Point & src, const fheroes2::Point & dst ) { int32_t distance = static_cast( std::round( getDistance( src, dst ) ) ); const double angle = getAngle( src, dst ); const int32_t iterationCount = std::clamp( ( distance + 50 ) / 100, 3, 5 ); std::vector> lines; lines.emplace_back( LightningPoint( { 0, 0 }, 5 ), LightningPoint( { distance, 0 }, 3 ) ); for ( int step = 0; step < iterationCount; ++step ) { std::vector> oldLines; std::swap( lines, oldLines ); for ( const auto & [firstPoint, secondPoint] : oldLines ) { fheroes2::Point middle( firstPoint.point + secondPoint.point ); middle.x /= 2; middle.y /= 2; const bool isPositive = ( Rand::Get( 1, 2 ) == 1 ); int32_t offsetY = std::max( 1, static_cast( Rand::Get( 1, 10 ) ) * distance / 100 ); middle.y += isPositive ? offsetY : -offsetY; const int32_t middleThickness = ( firstPoint.thickness + secondPoint.thickness ) / 2; const LightningPoint middlePoint( middle, middleThickness ); lines.emplace_back( firstPoint, middlePoint ); lines.emplace_back( middlePoint, secondPoint ); if ( Rand::Get( 1, 4 ) == 1 ) { // 25% offsetY = static_cast( Rand::Get( 1, 10 ) ) * distance / 100; const int32_t x = static_cast( ( middle.x - firstPoint.point.x ) * 0.7 ) + middle.x; const int32_t y = static_cast( ( middle.y - firstPoint.point.y ) * 0.7 ) + middle.y + ( isPositive ? offsetY : -offsetY ); lines.emplace_back( middlePoint, LightningPoint( { x, y }, 1 ) ); } } distance /= 2; } for ( auto & [firstPoint, secondPoint] : lines ) { firstPoint.point = rotate( firstPoint.point, angle ) + src; secondPoint.point = rotate( secondPoint.point, angle ) + src; } return lines; } void RedrawLightning( const std::vector> & lightning, const uint8_t color, fheroes2::Image & surface, const fheroes2::Rect & roi = fheroes2::Rect() ) { for ( const auto & [firstPoint, secondPoint] : lightning ) { const fheroes2::Point & first = firstPoint.point; const fheroes2::Point & second = secondPoint.point; const bool isHorizontal = std::abs( first.x - second.x ) >= std::abs( first.y - second.y ); fheroes2::DrawLine( surface, first, second, color, roi ); for ( int32_t thickness = 1; thickness < secondPoint.thickness; ++thickness ) { const bool isUpper = ( ( thickness % 2 ) == 1 ); const int32_t offset = isUpper ? ( thickness + 1 ) / 2 : -( thickness + 1 ) / 2; if ( isHorizontal ) { fheroes2::DrawLine( surface, { first.x, first.y + offset }, { second.x, second.y + offset }, color, roi ); } else { fheroes2::DrawLine( surface, { first.x + offset, first.y }, { second.x + offset, second.y }, color, roi ); } } for ( int32_t thickness = secondPoint.thickness; thickness < firstPoint.thickness; ++thickness ) { const bool isUpper = ( ( thickness % 2 ) == 1 ); const int32_t offset = isUpper ? ( thickness + 1 ) / 2 : -( thickness + 1 ) / 2; if ( isHorizontal ) { fheroes2::DrawLine( surface, { first.x, first.y + offset }, second, color, roi ); } else { fheroes2::DrawLine( surface, { first.x + offset, first.y }, second, color, roi ); } } } } void GetHalfArc( std::vector & arc, int32_t width, const int32_t height, const int32_t pow1, const int32_t pow2, const double pow2Ratio ) { // For positive width the arc will start from y = 0, for negative it will end at y = 0. const int32_t x0 = ( width < 0 ) ? width : 0; // For positive height the arc top will be y = 0, for negative - arc will be flipped for 'y' coordinate. // TODO: consider height offset from previous arc part. const int32_t y0 = ( height < 0 ) ? height : 0; // Coefficients for multipliers of 'pow1' and 'pow2' degrees. const double k1 = ( height * ( 1 - pow2Ratio ) ) / std::pow( width, pow1 ); const double k2 = ( height * pow2Ratio ) / std::pow( width, pow2 ); width = std::abs( width ); // Calculate 'y' coordinates for the arc: y = k1*(x-x0)^pow1+k2*(x-x0)^pow2 and push it to the 'arc' vector. for ( int32_t x = 0; x < width; ++x ) { arc.push_back( static_cast( k1 * std::pow( ( x + x0 ), pow1 ) + k2 * std::pow( ( x + x0 ), pow2 ) - y0 ) ); } } fheroes2::Image DrawRainbow( const std::vector & rainbowArc, const int32_t rainbowThickness, const bool isVertical, const bool flipHorizontally ) { // Rainbow image size should include the arc size plus the thickness of the rainbow. const int32_t rainbowWidth = static_cast( rainbowArc.size() ); std::vector::const_iterator pnt = rainbowArc.begin(); const std::vector::const_iterator pntEnd = rainbowArc.end(); const int32_t rainbowHeight = *std::max_element( pnt, pntEnd ) + rainbowThickness; // If the rainbow is vertical - swap width and height. const int32_t rainbowImgWidth = isVertical ? rainbowHeight : rainbowWidth; const int32_t rainbowImgHeight = isVertical ? rainbowWidth : rainbowHeight; fheroes2::Image rainbow( rainbowImgWidth, rainbowImgHeight ); rainbow.reset(); // Get the original good luck sprite, since it has a rainbow image which will be used to get line. const fheroes2::Sprite & luckSprite = fheroes2::AGG::GetICN( ICN::EXPMRL, 0 ); // Get a single rainbow line from the center of the luckSprite. fheroes2::Image croppedRainbow( 1, rainbowThickness ); croppedRainbow._disableTransformLayer(); fheroes2::Copy( luckSprite, luckSprite.width() / 2, 0, croppedRainbow, 0, 0, 1, rainbowThickness ); fheroes2::Image rainbowLine; if ( isVertical ) { rainbowLine = fheroes2::Image( croppedRainbow.height(), croppedRainbow.width() ); rainbowLine._disableTransformLayer(); // For a vertical rainbow orientation the line needs to be transposed. fheroes2::Transpose( croppedRainbow, rainbowLine ); if ( !flipHorizontally ) { rainbowLine = fheroes2::Flip( rainbowLine, true, false ); } } else { rainbowLine = std::move( croppedRainbow ); } const int32_t rainbowLineWidth = rainbowLine.width(); const int32_t rainbowLineHeight = rainbowLine.height(); // Draw a rainbow image for each 'x' coordinate and corresponding '*pnt' value. for ( int32_t x = 0; pnt != pntEnd; ++x, ++pnt ) { // Set the 'x' and 'y' coordinates of the current rainbow pixel in the resulting rainbow image according to the rainbow direction. const int32_t imgX = isVertical ? ( flipHorizontally ? *pnt : rainbowImgWidth - *pnt - rainbowThickness ) : ( flipHorizontally ? rainbowImgWidth - x : x ); const int32_t imgY = isVertical ? x : *pnt; // Insert a rainbow line at the current arc position. fheroes2::Copy( rainbowLine, 0, 0, rainbow, imgX, imgY, rainbowLineWidth, rainbowLineHeight ); } return rainbow; } int32_t GetAbsoluteICNHeight( int icnId ) { const uint32_t frameCount = fheroes2::AGG::GetICNCount( icnId ); if ( frameCount == 0 ) { return 0; } int32_t height = 0; for ( uint32_t i = 0; i < frameCount; ++i ) { const int32_t offset = -fheroes2::AGG::GetICN( icnId, i ).y(); if ( offset > height ) { height = offset; } } return height; } fheroes2::Point CalculateSpellPosition( const Battle::Unit & target, const int spellICN, const fheroes2::Sprite & spellSprite ) { const fheroes2::Rect & pos = target.GetRectPosition(); // Get the sprite for the first frame, so its center won't shift if the creature is animating (instead of target.GetFrame()). const fheroes2::Sprite & unitSprite = fheroes2::AGG::GetICN( target.GetMonsterSprite(), target.animation.firstFrame() ); // Bottom-left corner (default) position with spell offset applied fheroes2::Point result( pos.x + spellSprite.x(), pos.y + pos.height + cellYOffset + spellSprite.y() ); switch ( spellICN ) { case ICN::SHIELD: // in front of the unit result.x += target.isReflect() ? -pos.width / ( target.isWide() ? 2 : 1 ) : pos.width; result.y += unitSprite.y() / 2; break; case ICN::BLIND: { // unit's eyes const fheroes2::Point & offset = target.animation.getBlindOffset(); // calculate OG Heroes2 unit position to apply offset to const int32_t rearCenterX = ( target.isWide() && target.isReflect() ) ? pos.width * 3 / 4 : Battle::Cell::widthPx / 2; // Overwrite result with custom blind value result.x += rearCenterX + ( target.isReflect() ? -offset.x : offset.x ); result.y += offset.y; break; } case ICN::STONSKIN: case ICN::STELSKIN: // bottom center point result.x += pos.width / 2; break; case ICN::REDDEATH: // Shift spell sprite position for a wide creature to its head. result.x += pos.width / 2 + ( target.isReflect() ? ( 1 - spellSprite.width() - 2 * spellSprite.x() - pos.width / 8 ) : ( pos.width / 8 ) ); result.y -= pos.height - 4; break; case ICN::MAGIC08: // Position shifts for the Holy Shout spell to be closer to OG. result.x += pos.width / 2 + ( target.isReflect() ? 12 : 0 ); result.y += unitSprite.y() / 2 - 1; break; default: // center point of the unit result.x += pos.width / 2; result.y += unitSprite.y() / 2; break; } if ( result.y < 0 ) { const int maximumY = GetAbsoluteICNHeight( spellICN ); result.y = maximumY + spellSprite.y(); } return result; } int matchHeroType( const HeroBase * base ) { if ( base->isCaptain() ) { return Battle::CAPTAIN; } switch ( base->GetRace() ) { case Race::KNGT: return Battle::KNIGHT; case Race::BARB: return Battle::BARBARIAN; case Race::SORC: return Battle::SORCERESS; case Race::WRLK: return Battle::WARLOCK; case Race::WZRD: return Battle::WIZARD; case Race::NECR: return Battle::NECROMANCER; default: break; } // Have you added a new race? Update the logic above! assert( 0 ); return Battle::KNIGHT; } const std::vector & getHeroAnimation( const HeroBase * hero, int animation ) { static const std::vector staticAnim{ 1 }; if ( !hero || animation == Battle::OP_STATIC ) { return staticAnim; } const int heroType = matchHeroType( hero ); if ( animation == Battle::OP_SORROW ) { static const std::vector sorrowAnim{ 2, 3, 4, 5, 4, 5, 4, 3, 2 }; return ( heroType == Battle::CAPTAIN ) ? staticAnim : sorrowAnim; } static const std::vector heroTypeAnim[7][9]{ // JOY CAST_MASS CAST_UP CAST_DOWN IDLE { { 6, 7, 8, 9, 8, 9, 8, 7, 6 }, { 10, 11 }, { 10 }, { 6, 12, 13 }, { 12, 6 }, { 2, 14 }, { 2 }, { 15, 16, 17 }, { 18, 19 } }, // KNIGHT { { 6, 7, 8, 9, 9, 8, 7, 6 }, { 6, 10, 11 }, { 10, 6 }, { 6, 12, 13 }, { 12, 6 }, { 6, 14 }, { 6 }, { 15, 16, 17 }, { 18 } }, // BARBARIAN { { 6, 7, 8, 7, 6 }, { 6, 7, 9 }, { 7, 6 }, { 6, 10, 11 }, { 10, 6 }, { 6, 12 }, { 6 }, { 13, 14, 15 }, { 16 } }, // SORCERESS { { 6, 7, 8, 9, 10, 9, 8, 7, 6 }, { 6, 7, 11, 12 }, { 11, 6 }, { 6, 7, 13 }, { 6 }, { 6, 14 }, { 6 }, { 15, 16 }, { 6 } }, // WARLOCK { { 6, 7, 8, 9, 8, 7, 6 }, { 6, 10, 11, 12, 13 }, { 12, 11, 10, 6 }, { 6, 14 }, { 6 }, { 6, 15 }, { 6 }, { 16, 17 }, { 18 } }, // WIZARD { { 6, 7, 6, 7, 6, 7 }, { 7, 8, 9, 10, 11 }, { 10, 9, 7 }, { 7, 12, 13, 14, 15 }, { 7 }, { 7, 12, 13, 14, 16 }, { 7 }, { 17 }, { 18, 19 } }, // NECROMANCER { { 1 }, { 2, 3, 4 }, { 3, 2 }, { 5, 6 }, { 5 }, { 5, 7 }, { 5 }, { 8, 9 }, { 10 } } // CAPTAIN }; return heroTypeAnim[heroType][animation]; } bool CursorAttack( uint32_t theme ) { switch ( theme ) { case Cursor::WAR_ARROW: case Cursor::WAR_BROKENARROW: case Cursor::SWORD_TOPRIGHT: case Cursor::SWORD_RIGHT: case Cursor::SWORD_BOTTOMRIGHT: case Cursor::SWORD_BOTTOMLEFT: case Cursor::SWORD_LEFT: case Cursor::SWORD_TOPLEFT: case Cursor::SWORD_TOP: case Cursor::SWORD_BOTTOM: return true; default: break; } return false; } fheroes2::Image DrawHexagon( const uint8_t colorId ) { const fheroes2::Sprite & originalGrid = fheroes2::AGG::GetICN( ICN::CMBTMISC, 0 ); // Move hexagon by 1 pixel down to match the original game's grid. fheroes2::Image hexagonSprite( originalGrid.width(), originalGrid.height() + 1 ); // Make the upper image line transparent. The other part will be filled with the copied image. fheroes2::FillTransform( hexagonSprite, 0, 0, originalGrid.width(), 1, 1 ); fheroes2::Copy( originalGrid, 0, 0, hexagonSprite, 0, 1, originalGrid.width(), originalGrid.height() ); fheroes2::ReplaceColorId( hexagonSprite, 0, colorId ); return hexagonSprite; } fheroes2::Image DrawHexagonShadow( const uint8_t alphaValue, const int32_t horizSpace ) { const int32_t l = 13; const int32_t w = Battle::Cell::widthPx; const int32_t h = Battle::Cell::heightPx; fheroes2::Image sf( w, h ); sf.reset(); fheroes2::Rect rt( horizSpace, l - 1, w + 1 - horizSpace * 2, 2 * l + 4 ); for ( int32_t i = 0; i < w / 2; i += 2 ) { for ( int32_t x = 0; x < rt.width; ++x ) { for ( int32_t y = 0; y < rt.height; ++y ) { fheroes2::SetTransformPixel( sf, rt.x + x, rt.y + y, alphaValue ); } } --rt.y; rt.height += 2; rt.x += ( i == 0 ) ? 1 : 2; rt.width -= ( i == 0 ) ? 2 : 4; } return sf; } fheroes2::Point GetTroopPosition( const Battle::Unit & unit, const fheroes2::Sprite & sprite ) { const fheroes2::Rect & rt = unit.GetRectPosition(); int32_t offsetX = 0; if ( unit.isReflect() ) { if ( unit.isWide() ) { offsetX = rt.x + ( rt.width / 2 + rt.width / 4 ) - sprite.width() - sprite.x() + 1; } else { offsetX = rt.x + ( rt.width / 2 ) - sprite.width() - sprite.x() + 1; } } else { if ( unit.isWide() ) { offsetX = rt.x + ( rt.width / 4 ) + sprite.x(); } else { offsetX = rt.x + ( rt.width / 2 ) + sprite.x(); } } const int32_t offsetY = rt.y + rt.height + sprite.y() + cellYOffset; return { offsetX, offsetY }; } int GetIndexIndicator( const Battle::Unit & unit ) { if ( unit.Modes( Battle::IS_GOOD_MAGIC | Battle::SP_ANTIMAGIC ) ) { if ( unit.Modes( Battle::IS_BAD_MAGIC ) ) { // ICN::TEXTBAR index for yellow indicator background color. return 13; } // ICN::TEXTBAR index for green indicator background color. return 12; } if ( unit.Modes( Battle::IS_BAD_MAGIC ) ) { // ICN::TEXTBAR index for red indicator background color. return 14; } // ICN::TEXTBAR index for purple indicator background color. return 10; } int GetCursorFromSpell( const int spell ) { switch ( spell ) { case Spell::SLOW: return Cursor::SP_SLOW; case Spell::CURSE: return Cursor::SP_CURSE; case Spell::CURE: return Cursor::SP_CURE; case Spell::BLESS: return Cursor::SP_BLESS; case Spell::FIREBALL: return Cursor::SP_FIREBALL; case Spell::FIREBLAST: return Cursor::SP_FIREBLAST; case Spell::TELEPORT: return Cursor::SP_TELEPORT; case Spell::RESURRECT: return Cursor::SP_RESURRECT; case Spell::HASTE: return Cursor::SP_HASTE; case Spell::SHIELD: return Cursor::SP_SHIELD; case Spell::ARMAGEDDON: return Cursor::SP_ARMAGEDDON; case Spell::ANTIMAGIC: return Cursor::SP_ANTIMAGIC; case Spell::BERSERKER: return Cursor::SP_BERSERKER; case Spell::PARALYZE: return Cursor::SP_PARALYZE; case Spell::BLIND: return Cursor::SP_BLIND; case Spell::LIGHTNINGBOLT: return Cursor::SP_LIGHTNINGBOLT; case Spell::CHAINLIGHTNING: return Cursor::SP_CHAINLIGHTNING; case Spell::ELEMENTALSTORM: return Cursor::SP_ELEMENTALSTORM; case Spell::RESURRECTTRUE: return Cursor::SP_RESURRECTTRUE; case Spell::DISPEL: return Cursor::SP_DISPEL; case Spell::HOLYWORD: return Cursor::SP_HOLYWORD; case Spell::HOLYSHOUT: return Cursor::SP_HOLYSHOUT; case Spell::METEORSHOWER: return Cursor::SP_METEORSHOWER; case Spell::ANIMATEDEAD: return Cursor::SP_ANIMATEDEAD; case Spell::MIRRORIMAGE: return Cursor::SP_MIRRORIMAGE; case Spell::BLOODLUST: return Cursor::SP_BLOODLUST; case Spell::DEATHRIPPLE: return Cursor::SP_DEATHRIPPLE; case Spell::DEATHWAVE: return Cursor::SP_DEATHWAVE; case Spell::STEELSKIN: return Cursor::SP_STEELSKIN; case Spell::STONESKIN: return Cursor::SP_STONESKIN; case Spell::DRAGONSLAYER: return Cursor::SP_DRAGONSLAYER; case Spell::EARTHQUAKE: return Cursor::SP_EARTHQUAKE; case Spell::DISRUPTINGRAY: return Cursor::SP_DISRUPTINGRAY; case Spell::COLDRING: return Cursor::SP_COLDRING; case Spell::COLDRAY: return Cursor::SP_COLDRAY; case Spell::HYPNOTIZE: return Cursor::SP_HYPNOTIZE; case Spell::ARROW: return Cursor::SP_ARROW; default: break; } return Cursor::WAR_NONE; } int GetSwordCursorDirection( const int direction ) { switch ( direction ) { case Battle::BOTTOM_RIGHT: return Cursor::SWORD_TOPLEFT; case Battle::BOTTOM_LEFT: return Cursor::SWORD_TOPRIGHT; case Battle::RIGHT: return Cursor::SWORD_LEFT; case Battle::TOP_RIGHT: return Cursor::SWORD_BOTTOMLEFT; case Battle::TOP_LEFT: return Cursor::SWORD_BOTTOMRIGHT; case Battle::LEFT: return Cursor::SWORD_RIGHT; default: break; } return 0; } int GetDirectionFromCursorSword( const uint32_t sword ) { switch ( sword ) { case Cursor::SWORD_TOPLEFT: return Battle::BOTTOM_RIGHT; case Cursor::SWORD_TOPRIGHT: return Battle::BOTTOM_LEFT; case Cursor::SWORD_LEFT: return Battle::RIGHT; case Cursor::SWORD_BOTTOMLEFT: return Battle::TOP_RIGHT; case Cursor::SWORD_BOTTOMRIGHT: return Battle::TOP_LEFT; case Cursor::SWORD_RIGHT: return Battle::LEFT; default: break; } return Battle::UNKNOWN; } } namespace Battle { class StatusListBox final : public ::Interface::ListBox { public: using ::Interface::ListBox::ActionListDoubleClick; using ::Interface::ListBox::ActionListSingleClick; using ::Interface::ListBox::ActionListPressRight; void SetPosition( int32_t px, int32_t py ) { assert( px >= 0 && py >= 0 ); const int32_t totalElementHeight = maxElementsInBattleLog * battleLogElementHeight - battleLogLastElementOffset; _border.SetPosition( px, py - totalElementHeight - 32, fheroes2::Display::DEFAULT_WIDTH - 32, totalElementHeight ); const fheroes2::Rect & area = _border.GetArea(); SetTopLeft( area.getPosition() ); SetAreaMaxItems( maxElementsInBattleLog ); const int32_t ax = area.x + area.width - 12; SetScrollButtonUp( ICN::DROPLISL, 6, 7, fheroes2::Point( ax, area.y - 10 ) ); SetScrollButtonDn( ICN::DROPLISL, 8, 9, fheroes2::Point( ax, area.y + area.height - 11 ) ); const fheroes2::Rect & buttonPgUpArea = _buttonPgUp.area(); _scrollbarSliderAreaLength = _buttonPgDn.area().y - ( buttonPgUpArea.y + buttonPgUpArea.height ) - 7; setScrollBarArea( { ax + 5, buttonPgUpArea.y + buttonPgUpArea.height + 3, 12, _scrollbarSliderAreaLength } ); const fheroes2::Sprite & originalSlider = fheroes2::AGG::GetICN( ICN::DROPLISL, 13 ); const fheroes2::Image scrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, false, _scrollbarSliderAreaLength, VisibleItemCount(), static_cast( _messages.size() ), { 0, 0, originalSlider.width(), 4 }, { 0, 4, originalSlider.width(), 8 } ); setScrollBarImage( scrollbarSlider ); _scrollbar.hide(); SetAreaItems( { area.x, area.y, area.width - 16, area.height + battleLogLastElementOffset } ); SetListContent( _messages ); } const fheroes2::Rect & GetArea() const { return _border.GetRect(); } void AddMessage( std::string str ) { // Check if message string fits the log width. fheroes2::Text text( str, fheroes2::FontType::normalWhite() ); size_t pos = std::string::npos; while ( text.width() > battleLogElementWidth ) { // Find the maximum allowed phrase to fit the line. We assume that all words are separated by a space. pos = str.rfind( ' ', pos - 1 ); // Theoretically there could be such a large word that did not fit the log width. if ( pos == std::string::npos ) { // Find the next word in this phrase. pos = str.find( ' ' ); // Cut this long word with the trailing '...'. text.fitToOneRow( battleLogElementWidth ); if ( pos == std::string::npos ) { // This is the only word in the phrase. str = text.text(); } else { _messages.push_back( text.text() ); // Put the rest of the phrase to the next line. str = str.substr( pos + 1 ); // There is no need to split this phrase any more. pos = std::string::npos; } break; } text.set( str.substr( 0, pos ), fheroes2::FontType::normalWhite() ); } if ( pos == std::string::npos ) { _messages.push_back( std::move( str ) ); } else { // If a phrase does not fit the log width we split it into two lines. _messages.push_back( str.substr( 0, pos ) ); _messages.push_back( str.substr( pos + 1 ) ); } if ( !_isLogOpened ) { _scrollbar.hide(); } SetListContent( _messages ); // Update the scrollbar image. const fheroes2::Sprite & originalSlider = fheroes2::AGG::GetICN( ICN::DROPLISL, 13 ); const fheroes2::Image scrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, false, _scrollbarSliderAreaLength, VisibleItemCount(), static_cast( _messages.size() ), { 0, 0, originalSlider.width(), 4 }, { 0, 4, originalSlider.width(), 8 } ); setScrollBarImage( scrollbarSlider ); SetCurrent( _messages.size() - 1 ); } void RedrawItem( const std::string & str, int32_t px, int32_t py, bool /* unused */ ) override { const fheroes2::Text text( str, fheroes2::FontType::normalWhite() ); text.draw( px, py, fheroes2::Display::instance() ); } void RedrawBackground( const fheroes2::Point & /* unused*/ ) override { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Rect & buttonPgUpArea = _buttonPgUp.area(); const int32_t buttonPgUpBottom = buttonPgUpArea.y + buttonPgUpArea.height; const int32_t buttonPgDnAreaY = _buttonPgDn.area().y; const int32_t ax = buttonPgUpArea.x; const int32_t ah = buttonPgDnAreaY - buttonPgUpBottom; const fheroes2::Rect & borderRect = _border.GetRect(); Dialog::FrameBorder::RenderOther( fheroes2::AGG::GetICN( ICN::TEXTBAK2, 0 ), borderRect ); const fheroes2::Sprite & sp3 = fheroes2::AGG::GetICN( ICN::DROPLISL, 11 ); for ( int32_t i = 0; i < ( ah / sp3.height() ); ++i ) { fheroes2::Copy( sp3, 0, 0, display, ax, buttonPgUpBottom + ( sp3.height() * i ), sp3.width(), sp3.height() ); } const fheroes2::Sprite & sp1 = fheroes2::AGG::GetICN( ICN::DROPLISL, 10 ); const fheroes2::Sprite & sp2 = fheroes2::AGG::GetICN( ICN::DROPLISL, 12 ); fheroes2::Copy( sp1, 0, 0, display, ax, buttonPgUpBottom, sp1.width(), sp1.height() ); fheroes2::Copy( sp2, 0, 0, display, ax, buttonPgDnAreaY - sp2.height(), sp2.width(), sp2.height() ); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListDoubleClick( std::string & /* unused */ ) override { // Do nothing. } void ActionListSingleClick( std::string & /* unused */ ) override { // Do nothing. } void ActionListPressRight( std::string & /* unused */ ) override { // Do nothing. } void SetOpenLog( const bool opened ) { _isLogOpened = opened; } bool isOpenLog() const { return _isLogOpened; } private: Dialog::FrameBorder _border; std::vector _messages; int32_t _scrollbarSliderAreaLength{ 0 }; bool _isLogOpened{ false }; }; } bool Battle::TargetInfo::isFinishAnimFrame( const TargetInfo & info ) { return info.defender && info.defender->isFinishAnimFrame(); } Battle::OpponentSprite::OpponentSprite( const fheroes2::Rect & area, HeroBase * hero, const bool isReflect ) : _heroBase( hero ) , _currentAnim( getHeroAnimation( hero, OP_STATIC ) ) , _isFlippedHorizontally( isReflect ) , _offset( area.x, area.y ) { const bool isCaptain = hero->isCaptain(); switch ( hero->GetRace() ) { case Race::KNGT: _heroIcnId = isCaptain ? ICN::CMBTCAPK : ICN::CMBTHROK; break; case Race::BARB: _heroIcnId = isCaptain ? ICN::CMBTCAPB : ICN::CMBTHROB; break; case Race::SORC: _heroIcnId = isCaptain ? ICN::CMBTCAPS : ICN::CMBTHROS; break; case Race::WRLK: _heroIcnId = isCaptain ? ICN::CMBTCAPW : ICN::CMBTHROW; break; case Race::WZRD: _heroIcnId = isCaptain ? ICN::CMBTCAPZ : ICN::CMBTHROZ; break; case Race::NECR: _heroIcnId = isCaptain ? ICN::CMBTCAPN : ICN::CMBTHRON; break; default: // Did you add a new faction? Add the logic here. assert( 0 ); break; } const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( _heroIcnId, _currentAnim.getFrame() ); _area.width = sprite.width(); _area.height = sprite.height(); if ( _isFlippedHorizontally ) { _area.x = _offset.x + fheroes2::Display::DEFAULT_WIDTH - RIGHT_HERO_X_OFFSET - ( sprite.x() + _area.width ); _area.y = _offset.y + RIGHT_HERO_Y_OFFSET + sprite.y(); } else { _area.x = _offset.x + LEFT_HERO_X_OFFSET + sprite.x(); _area.y = _offset.y + LEFT_HERO_Y_OFFSET + sprite.y(); } if ( isCaptain ) { if ( _isFlippedHorizontally ) { _area.x += CAPTAIN_X_OFFSET; } else { _area.x -= CAPTAIN_X_OFFSET; } _area.y += CAPTAIN_Y_OFFSET; } } void Battle::OpponentSprite::IncreaseAnimFrame() { _currentAnim.playAnimation( false ); } void Battle::OpponentSprite::SetAnimation( const int rule ) { _animationType = rule; _currentAnim = getHeroAnimation( _heroBase, rule ); } fheroes2::Point Battle::OpponentSprite::GetCastPosition() const { const bool isCaptain = _heroBase->isCaptain(); fheroes2::Point offset; switch ( _heroBase->GetRace() ) { case Race::KNGT: offset.x = isCaptain ? 0 : 13; offset.y = isCaptain ? 3 : -7; break; case Race::BARB: offset.x = isCaptain ? 0 : 16; offset.y = isCaptain ? 3 : -15; break; case Race::SORC: offset.x = isCaptain ? 0 : 11; offset.y = isCaptain ? 3 : -8; break; case Race::WRLK: offset.x = isCaptain ? 2 : 9; offset.y = isCaptain ? 5 : -11; break; case Race::WZRD: offset.x = isCaptain ? 5 : 1; offset.y = isCaptain ? 8 : -9; break; case Race::NECR: offset.x = isCaptain ? 5 : 13; offset.y = isCaptain ? 6 : -7; break; default: break; } return { _area.x + ( _isFlippedHorizontally ? offset.x : _area.width - offset.x ), _area.y + _area.height / 2 + offset.y }; } void Battle::OpponentSprite::Redraw( fheroes2::Image & dst ) const { const fheroes2::Sprite & hero = fheroes2::AGG::GetICN( _heroIcnId, _currentAnim.getFrame() ); fheroes2::Point offset( _offset ); if ( _heroBase->isCaptain() ) { if ( _isFlippedHorizontally ) { offset.x += CAPTAIN_X_OFFSET; } else { offset.x -= CAPTAIN_X_OFFSET; } offset.y += CAPTAIN_Y_OFFSET; } if ( _isFlippedHorizontally ) { fheroes2::Blit( hero, dst, offset.x + fheroes2::Display::DEFAULT_WIDTH - RIGHT_HERO_X_OFFSET - ( hero.x() + hero.width() ), offset.y + RIGHT_HERO_Y_OFFSET + hero.y(), _isFlippedHorizontally ); } else { fheroes2::Blit( hero, dst, offset.x + LEFT_HERO_X_OFFSET + hero.x(), offset.y + LEFT_HERO_Y_OFFSET + hero.y() ); } } bool Battle::OpponentSprite::updateAnimationState() { if ( _currentAnim.isLastFrame() ) { if ( _animationType != OP_STATIC ) { if ( _animationType != OP_CAST_MASS && _animationType != OP_CAST_UP && _animationType != OP_CAST_DOWN ) { SetAnimation( OP_STATIC ); return true; } } else if ( _idleTimer.checkDelay() ) { SetAnimation( ( Rand::Get( 1, 3 ) < 2 ) ? OP_IDLE2 : OP_IDLE ); return true; } return false; } _currentAnim.playAnimation( false ); return true; } Battle::Status::Status() : _upperBackground( fheroes2::AGG::GetICN( ICN::TEXTBAR, 8 ) ) , _lowerBackground( fheroes2::AGG::GetICN( ICN::TEXTBAR, 9 ) ) { width = _upperBackground.width(); height = _upperBackground.height() + _lowerBackground.height(); } void Battle::Status::setMessage( std::string messageString, const bool top ) { if ( top ) { _upperText.set( messageString, fheroes2::FontType::normalWhite() ); // The text cannot go beyond the text area so it is important to truncate it when necessary. _upperText.fitToOneRow( _upperBackground.width() - offsetForTextBar * 2 ); if ( _battleStatusLog ) { _battleStatusLog->AddMessage( std::move( messageString ) ); } } else if ( messageString != _lastMessage ) { _lowerText.set( messageString, fheroes2::FontType::normalWhite() ); // The text cannot go beyond the text area so it is important to truncate it when necessary. _lowerText.fitToOneRow( _upperBackground.width() - offsetForTextBar * 2 ); _lastMessage = std::move( messageString ); } } void Battle::Status::redraw( fheroes2::Image & output ) const { fheroes2::Copy( _upperBackground, 0, 0, output, x, y, _upperBackground.width(), _upperBackground.height() ); fheroes2::Copy( _lowerBackground, 0, 0, output, x, y + _upperBackground.height(), _lowerBackground.width(), _lowerBackground.height() ); if ( !_upperText.empty() ) { _upperText.draw( x + ( _upperBackground.width() - _upperText.width() ) / 2, y + 4, output ); } if ( !_lowerText.empty() ) { _lowerText.draw( x + ( _lowerBackground.width() - _lowerText.width() ) / 2, y + _upperBackground.height(), output ); } } void Battle::Status::clear() { _upperText.set( "", fheroes2::FontType::normalWhite() ); _lowerText.set( "", fheroes2::FontType::normalWhite() ); _lastMessage = ""; } void Battle::TurnOrder::queueEventProcessing( std::string & msg, const fheroes2::Point & offset ) const { LocalEvent & le = LocalEvent::Get(); for ( const auto & [unit, unitPos] : _rects ) { assert( unit != nullptr ); const fheroes2::Rect unitRoi = unitPos + offset; if ( le.isMouseCursorPosInArea( unitRoi ) ) { msg = _( "View %{monster} info" ); StringReplaceWithLowercase( msg, "%{monster}", unit->GetName() ); } if ( le.MouseClickLeft( unitRoi ) ) { Dialog::ArmyInfo( *unit, Dialog::BUTTONS, unit->isReflect() ); } else if ( le.isMouseRightButtonPressedInArea( unitRoi ) ) { Dialog::ArmyInfo( *unit, Dialog::ZERO, unit->isReflect() ); } } } void Battle::TurnOrder::_redrawUnit( const fheroes2::Rect & pos, const Battle::Unit & unit, const bool revert, const bool isCurrentUnit, const uint8_t currentUnitColor, fheroes2::Image & output ) const { // Render background. const fheroes2::Sprite & backgroundOriginal = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); fheroes2::Copy( backgroundOriginal, 37, 268, output, pos.x + 1, pos.y + 1, pos.width - 2, pos.height - 2 ); // Draw a monster's sprite. const fheroes2::Sprite & monsterSprite = fheroes2::AGG::GetICN( ICN::MONS32, unit.GetSpriteIndex() ); const int32_t monsterSpriteHeight = monsterSprite.height(); if ( unit.Modes( Battle::CAP_MIRRORIMAGE ) ) { fheroes2::Sprite mirroredMonster = monsterSprite; fheroes2::ApplyPalette( mirroredMonster, PAL::GetPalette( PAL::PaletteType::MIRROR_IMAGE ) ); fheroes2::Blit( mirroredMonster, output, pos.x + ( pos.width - monsterSprite.width() ) / 2, pos.y + pos.height - monsterSpriteHeight - ( monsterSpriteHeight + 3 < pos.height ? 3 : 0 ), revert ); } else { fheroes2::Blit( monsterSprite, output, pos.x + ( pos.width - monsterSprite.width() ) / 2, pos.y + pos.height - monsterSpriteHeight - ( monsterSpriteHeight + 3 < pos.height ? 3 : 0 ), revert ); } const fheroes2::Text number( fheroes2::abbreviateNumber( static_cast( unit.GetCount() ) ), fheroes2::FontType::smallWhite() ); number.drawInRoi( pos.x + 2, pos.y + 4, output, pos ); if ( isCurrentUnit ) { fheroes2::DrawRect( output, pos, currentUnitColor ); } else { uint8_t color = ARMY_COLOR_GRAY; switch ( unit.GetCurrentColor() ) { case -1: // Berserkers color = ARMY_COLOR_BLACK; break; case Color::BLUE: color = ARMY_COLOR_BLUE; break; case Color::GREEN: color = ARMY_COLOR_GREEN; break; case Color::RED: color = ARMY_COLOR_RED; break; case Color::YELLOW: color = ARMY_COLOR_YELLOW; break; case Color::ORANGE: color = ARMY_COLOR_ORANGE; break; case Color::PURPLE: color = ARMY_COLOR_PURPLE; break; case Color::NONE: break; default: assert( 0 ); // Did you add another player color? break; } fheroes2::DrawRect( output, pos, color ); if ( unit.Modes( Battle::TR_MOVED ) ) { fheroes2::ApplyPalette( output, pos.x, pos.y, output, pos.x, pos.y, turnOrderMonsterIconSize, turnOrderMonsterIconSize, PAL::GetPalette( PAL::PaletteType::GRAY ) ); fheroes2::ApplyPalette( output, pos.x, pos.y, output, pos.x, pos.y, turnOrderMonsterIconSize, turnOrderMonsterIconSize, 3 ); } } } void Battle::TurnOrder::redraw( const Unit * current, const uint8_t currentUnitColor, fheroes2::Image & output ) { if ( _orderOfUnits.expired() ) { // Nothing to show. return; } const std::shared_ptr unitsOrder = _orderOfUnits.lock(); const int32_t validUnitCount = static_cast( std::count_if( unitsOrder->begin(), unitsOrder->end(), []( const Unit * unit ) { assert( unit != nullptr ); return unit->isValid(); } ) ); const int32_t unitsToDraw = std::min( _area.width / turnOrderMonsterIconSize, validUnitCount ); if ( _rects.size() != static_cast( unitsToDraw ) ) { // Update units icons positions. width = turnOrderMonsterIconSize * unitsToDraw; int32_t offsetX = ( _area.width - width ) / 2; x = _area.x + offsetX; y = _area.y; height = turnOrderMonsterIconSize; _rects.clear(); _rects.reserve( unitsToDraw ); for ( int32_t index = 0; index < unitsToDraw; ++index ) { // Just for now place 'nullptr' instead of a pointer to unit. // These pointers will be updated in the next loop. _rects.emplace_back( nullptr, fheroes2::Rect( offsetX, 0, turnOrderMonsterIconSize, turnOrderMonsterIconSize ) ); offsetX += turnOrderMonsterIconSize; } } int32_t unitRectIndex = 0; int32_t unitsProcessed = 0; for ( const Unit * unit : *unitsOrder ) { if ( unitRectIndex == unitsToDraw ) { break; } assert( unit != nullptr ); if ( !unit->isValid() ) { continue; } if ( unit->Modes( Battle::TR_MOVED ) && ( validUnitCount - unitsProcessed > unitsToDraw ) ) { ++unitsProcessed; continue; } _rects[unitRectIndex].first = unit; _redrawUnit( _rects[unitRectIndex].second, *unit, unit->GetColor() == _opponentColor, current == unit, currentUnitColor, output ); ++unitRectIndex; ++unitsProcessed; } } Battle::Interface::Interface( Arena & battleArena, const int32_t tileIndex ) : arena( battleArena ) { Cursor::Get().SetThemes( Cursor::WAR_POINTER ); // border const fheroes2::Display & display = fheroes2::Display::instance(); _interfacePosition = { ( display.width() - fheroes2::Display::DEFAULT_WIDTH ) / 2, ( display.height() - fheroes2::Display::DEFAULT_HEIGHT ) / 2, _surfaceInnerArea.width, _surfaceInnerArea.height }; border.SetPosition( _interfacePosition.x - fheroes2::borderWidthPx, _interfacePosition.y - fheroes2::borderWidthPx, fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ); // damage info popup popup.setBattleUIRect( _interfacePosition ); // cover const bool trees = !Maps::ScanAroundObject( tileIndex, MP2::OBJ_TREES ).empty(); const Maps::Tile & tile = world.getTile( tileIndex ); const int groundType = tile.GetGround(); _brightLandType = ( groundType == Maps::Ground::SNOW || groundType == Maps::Ground::DESERT || groundType == Maps::Ground::WASTELAND || groundType == Maps::Ground::BEACH ); if ( _brightLandType ) { _contourColor = 108; } switch ( groundType ) { case Maps::Ground::DESERT: _battleGroundIcn = ICN::CBKGDSRT; _borderObjectsIcn = ICN::FRNG0004; break; case Maps::Ground::SNOW: _battleGroundIcn = trees ? ICN::CBKGSNTR : ICN::CBKGSNMT; _borderObjectsIcn = trees ? ICN::FRNG0006 : ICN::FRNG0007; break; case Maps::Ground::SWAMP: _battleGroundIcn = ICN::CBKGSWMP; _borderObjectsIcn = ICN::FRNG0008; break; case Maps::Ground::WASTELAND: _battleGroundIcn = ICN::CBKGCRCK; _borderObjectsIcn = ICN::FRNG0003; break; case Maps::Ground::BEACH: _battleGroundIcn = ICN::CBKGBEAC; _borderObjectsIcn = ICN::FRNG0002; break; case Maps::Ground::LAVA: _battleGroundIcn = ICN::CBKGLAVA; _borderObjectsIcn = ICN::FRNG0005; break; case Maps::Ground::DIRT: _battleGroundIcn = trees ? ICN::CBKGDITR : ICN::CBKGDIMT; _borderObjectsIcn = trees ? ICN::FRNG0010 : ICN::FRNG0009; break; case Maps::Ground::GRASS: _battleGroundIcn = trees ? ICN::CBKGGRTR : ICN::CBKGGRMT; _borderObjectsIcn = trees ? ICN::FRNG0011 : ICN::FRNG0012; break; case Maps::Ground::WATER: _battleGroundIcn = ICN::CBKGWATR; _borderObjectsIcn = ICN::FRNG0013; break; default: break; } // hexagon _hexagonGrid = DrawHexagon( fheroes2::GetColorId( 0x68, 0x8C, 0x04 ) ); // Shadow under the cursor: the first parameter is the shadow strength (smaller is stronger), the second is the distance between the hexagonal shadows. _hexagonCursorShadow = DrawHexagonShadow( 2, 1 ); // Hexagon shadow for the case when grid is disabled. _hexagonShadow = DrawHexagonShadow( 4, 2 ); // Shadow that fits the hexagon grid. _hexagonGridShadow = DrawHexagonShadow( 4, 1 ); _buttonAuto.setICNInfo( ICN::TEXTBAR, 4, 5 ); _buttonSettings.setICNInfo( ICN::TEXTBAR, 6, 7 ); // opponents if ( HeroBase * opponent = arena.GetCommander1(); opponent != nullptr ) { _opponent1 = std::make_unique( _surfaceInnerArea, opponent, false ); } if ( HeroBase * opponent = arena.GetCommander2(); opponent != nullptr ) { _opponent2 = std::make_unique( _surfaceInnerArea, opponent, true ); } if ( Arena::GetCastle() ) { _ballistaTowerRect = fheroes2::Rect{ _interfacePosition.x + 570, _interfacePosition.y + 145, 70, 160 }; } const fheroes2::Rect & area = border.GetArea(); const fheroes2::Rect & settingsRect = _buttonSettings.area(); const int32_t satusOffsetY = area.y + area.height - settingsRect.height - _buttonAuto.area().height; _buttonAuto.setPosition( area.x, satusOffsetY ); _buttonSettings.setPosition( area.x, area.y + area.height - settingsRect.height ); _buttonSkip.setICNInfo( ICN::TEXTBAR, 0, 1 ); _buttonSkip.setPosition( area.x + area.width - _buttonSkip.area().width, area.y + area.height - _buttonSkip.area().height ); status.setPosition( area.x + settingsRect.width, satusOffsetY ); listlog = std::make_unique(); const int32_t battlefieldHeight = area.height - status.height; if ( listlog ) { listlog->SetPosition( area.x, area.y + battlefieldHeight ); } status.setLogs( listlog.get() ); // As `_battleGround` and '_mainSurface' are used to prepare battlefield screen to render on display they do not need to have a transform layer. _battleGround._disableTransformLayer(); _mainSurface._disableTransformLayer(); // Battlefield area excludes the lower part where the status log is located. _mainSurface.resize( area.width, battlefieldHeight ); _battleGround.resize( area.width, battlefieldHeight ); AudioManager::ResetAudio(); } Battle::Interface::~Interface() { AudioManager::ResetAudio(); // Fade-out battlefield. const bool isDefaultScreenSize = fheroes2::Display::instance().isDefaultSize(); fheroes2::fadeOutDisplay( _background->activeArea(), !isDefaultScreenSize ); // For 640x480 resolution we do screen fade-in. if ( isDefaultScreenSize ) { // Reset the battlefield dialog window to restore the previous display image from screen restorer. // We have multiple return places after the battle: the adventure map, Main Menu (from Battle only), // the battle results screen (if the battle was quick ended). _background.reset(); Game::setDisplayFadeIn(); } } void Battle::Interface::SetOrderOfUnits( const std::shared_ptr & units ) { _turnOrder.set( _interfacePosition, units, arena.GetArmy2Color() ); } fheroes2::Point Battle::Interface::getRelativeMouseCursorPos() const { return LocalEvent::Get().getMouseCursorPos() - _interfacePosition.getPosition(); } void Battle::Interface::setStatus( const std::string & message, const bool top ) { status.setMessage( message, top ); if ( top ) { status.setMessage( "", false ); } humanturn_redraw = true; } void Battle::Interface::UpdateContourColor() { ++_contourCycle; if ( _brightLandType ) { static const std::array contourColorTable = { 108, 115, 122, 129, 122, 115 }; _contourColor = contourColorTable[_contourCycle % sizeof( contourColorTable )]; } else { static const std::array contourColorTable = { 110, 114, 118, 122, 126, 122, 118, 114 }; _contourColor = contourColorTable[_contourCycle % sizeof( contourColorTable )]; } } void Battle::Interface::fullRedraw() { if ( !_background ) { _background = std::make_unique( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, false ); } fheroes2::Display & display = fheroes2::Display::instance(); // Fade-out game screen only for 640x480 resolution. const bool isDefaultScreenSize = display.isDefaultSize(); if ( isDefaultScreenSize ) { fheroes2::fadeOutDisplay(); } // Don't waste time playing the pre-battle sound if the game sounds are turned off if ( Settings::Get().SoundVolume() > 0 ) { _preBattleSoundChannelId = AudioManager::PlaySound( M82::PREBATTL ); } // Prepare the Battlefield ground. _redrawBattleGround(); RedrawPartialStart(); // We do not render battlefield display image to properly fade-in it. redrawPreRender(); // Fade-in battlefield. if ( !isDefaultScreenSize ) { // We need to expand the ROI for the next render to properly render window borders and shadow. display.updateNextRenderRoi( _background->totalArea() ); } fheroes2::fadeInDisplay( _background->activeArea(), !isDefaultScreenSize ); } void Battle::Interface::Redraw() { // Check that the pre-battle sound is over to start playing the battle music. // IMPORTANT: This implementation may suffer from the race condition as the pre-battle sound channel may be reused // by new sounds if they are played (one way or another) after the end of the pre-battle sound, but before calling // this method. Although in this case here it will not lead to serious problems as in the worst case, the launch of // battle music will be postponed for some time. if ( _preBattleSoundChannelId && ( _preBattleSoundChannelId < 0 || !Mixer::isPlaying( _preBattleSoundChannelId.value() ) ) && !Music::isPlaying() ) { // Reset the value of _preBattleSoundChannelId to skip isPlaying() checks in future as these checks could freeze // the game for some time in certain cases (e.g. slow MIDI backend). _preBattleSoundChannelId.reset(); AudioManager::PlayMusicAsync( MUS::GetBattleRandom(), Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ); } RedrawPartialStart(); RedrawPartialFinish(); } void Battle::Interface::RedrawPartialStart() { RedrawCover(); RedrawArmies(); } void Battle::Interface::RedrawPartialFinish() { redrawPreRender(); fheroes2::Display::instance().render( _interfacePosition ); } void Battle::Interface::redrawPreRender() { if ( Settings::Get().BattleShowTurnOrder() ) { _turnOrder.redraw( _currentUnit, _contourColor, _mainSurface ); } #ifdef WITH_DEBUG if ( IS_DEVEL() ) { const Board * board = Arena::GetBoard(); assert( board != nullptr ); for ( const Cell & cell : *board ) { const fheroes2::Text text( std::to_string( cell.GetIndex() ), fheroes2::FontType::smallWhite() ); text.draw( cell.GetPos().x + 20, cell.GetPos().y + 24, _mainSurface ); } } #endif fheroes2::Copy( _mainSurface, 0, 0, fheroes2::Display::instance(), _interfacePosition.x, _interfacePosition.y, _mainSurface.width(), _mainSurface.height() ); RedrawInterface(); } void Battle::Interface::RedrawInterface() { status.redraw( fheroes2::Display::instance() ); _buttonAuto.draw(); _buttonSettings.draw(); _buttonSkip.draw(); popup.redraw(); if ( listlog && listlog->isOpenLog() ) { listlog->Redraw(); } } void Battle::Interface::RedrawArmies() { // Continue the idle animation for all troops on the battlefield: update idle animation frames before rendering the troops. IdleTroopsAnimation(); const Castle * castle = Arena::GetCastle(); std::array wallCellIds{ Arena::CASTLE_FIRST_TOP_WALL_POS, Arena::CASTLE_TOP_ARCHER_TOWER_POS, Arena::CASTLE_SECOND_TOP_WALL_POS, Arena::CASTLE_TOP_GATE_TOWER_POS, Arena::CASTLE_GATE_POS, Arena::CASTLE_BOTTOM_GATE_TOWER_POS, Arena::CASTLE_THIRD_TOP_WALL_POS, Arena::CASTLE_BOTTOM_ARCHER_TOWER_POS, Arena::CASTLE_FOURTH_TOP_WALL_POS }; if ( castle == nullptr ) { RedrawKilled(); } for ( int32_t cellRowId = 0; cellRowId < Board::heightInCells; ++cellRowId ) { // Redraw objects. for ( int32_t cellColumnId = 0; cellColumnId < Board::widthInCells; ++cellColumnId ) { const int32_t cellId = cellRowId * Board::widthInCells + cellColumnId; RedrawHighObjects( cellId ); } if ( castle != nullptr ) { // Redraw main tower. if ( cellRowId == 5 ) { RedrawCastleMainTower( *castle ); } else if ( cellRowId == 7 ) { // Redraw catapult. RedrawCastle( *castle, Arena::CATAPULT_POS ); } std::vector deadTroopBeforeWall; std::vector deadTroopAfterWall; std::vector troopCounterBeforeWall; std::vector troopCounterAfterWall; std::vector troopBeforeWall; std::vector troopAfterWall; std::vector movingTroopBeforeWall; std::vector movingTroopAfterWall; // Overlay sprites for troops (i.e. spell effect animation) should be rendered after rendering all troops // for current row so the next troop will not be rendered over the overlay sprite. std::vector troopOverlaySpriteBeforeWall; std::vector troopOverlaySpriteAfterWall; const int32_t wallCellId = wallCellIds[cellRowId]; for ( int32_t cellColumnId = 0; cellColumnId < Board::widthInCells; ++cellColumnId ) { const int32_t cellId = cellRowId * Board::widthInCells + cellColumnId; bool isCellBefore = true; if ( cellRowId < 5 ) { isCellBefore = cellId < wallCellId; } else { isCellBefore = cellId > wallCellId; if ( ( wallCellId == Arena::CASTLE_THIRD_TOP_WALL_POS || wallCellId == Arena::CASTLE_FOURTH_TOP_WALL_POS ) && Board::GetCell( wallCellId )->GetObject() == 0 ) { isCellBefore = false; } } for ( const Unit * deadUnit : arena.getGraveyardUnits( cellId ) ) { if ( deadUnit && cellId != deadUnit->GetTailIndex() ) { if ( isCellBefore ) { deadTroopBeforeWall.emplace_back( deadUnit ); // Check for overlay sprites of dead units (i.e. Resurrect spell). for ( const Battle::UnitSpellEffectInfo & overlaySprite : _unitSpellEffectInfos ) { if ( overlaySprite.unitId == deadUnit->GetUID() ) { troopOverlaySpriteBeforeWall.emplace_back( &overlaySprite ); } } } else { deadTroopAfterWall.emplace_back( deadUnit ); // Check for overlay sprites of dead units (i.e. Resurrect spell). for ( const Battle::UnitSpellEffectInfo & overlaySprite : _unitSpellEffectInfos ) { if ( overlaySprite.unitId == deadUnit->GetUID() ) { troopOverlaySpriteAfterWall.emplace_back( &overlaySprite ); } } } } } const Unit * unitOnCell = Board::GetCell( cellId )->GetUnit(); if ( unitOnCell == nullptr || _flyingUnit == unitOnCell || cellId == unitOnCell->GetTailIndex() ) { continue; } if ( _movingUnit != unitOnCell && unitOnCell->isValid() ) { const int unitAnimState = unitOnCell->GetAnimationState(); const bool isStaticUnit = unitAnimState == Monster_Info::STATIC || unitAnimState == Monster_Info::IDLE; if ( isCellBefore ) { if ( isStaticUnit ) { troopCounterBeforeWall.emplace_back( unitOnCell ); } troopBeforeWall.emplace_back( unitOnCell ); } else { if ( isStaticUnit ) { troopCounterAfterWall.emplace_back( unitOnCell ); } troopAfterWall.emplace_back( unitOnCell ); } } else { if ( isCellBefore ) { movingTroopBeforeWall.emplace_back( unitOnCell ); } else { movingTroopAfterWall.emplace_back( unitOnCell ); } } // Check for overlay sprites for 'unitOnCell'. for ( const Battle::UnitSpellEffectInfo & overlaySprite : _unitSpellEffectInfos ) { if ( overlaySprite.unitId == unitOnCell->GetUID() ) { if ( isCellBefore ) { troopOverlaySpriteBeforeWall.emplace_back( &overlaySprite ); } else { troopOverlaySpriteAfterWall.emplace_back( &overlaySprite ); } } } } for ( const Unit * unit : deadTroopBeforeWall ) { RedrawTroopSprite( *unit ); } for ( const Unit * unit : troopBeforeWall ) { RedrawTroopSprite( *unit ); } for ( const Unit * unit : troopCounterBeforeWall ) { RedrawTroopCount( *unit ); } for ( const Unit * unit : movingTroopBeforeWall ) { RedrawTroopSprite( *unit ); } // Render the overlay sprite for units in current cell row above all units in this and upper rows. for ( const Battle::UnitSpellEffectInfo * overlaySprite : troopOverlaySpriteBeforeWall ) { assert( overlaySprite->icnId != ICN::UNKNOWN ); const fheroes2::Sprite & spellSprite = fheroes2::AGG::GetICN( overlaySprite->icnId, overlaySprite->icnIndex ); fheroes2::Blit( spellSprite, _mainSurface, overlaySprite->position.x, overlaySprite->position.y, overlaySprite->isReflectedImage ); } RedrawCastle( *castle, wallCellId ); for ( const Unit * unit : deadTroopAfterWall ) { RedrawTroopSprite( *unit ); } for ( const Unit * unit : troopAfterWall ) { RedrawTroopSprite( *unit ); } for ( const Unit * unit : troopCounterAfterWall ) { RedrawTroopCount( *unit ); } for ( const Unit * unit : movingTroopAfterWall ) { RedrawTroopSprite( *unit ); } // Render the overlay sprite for units in current cell row above all units in this and upper rows. for ( const Battle::UnitSpellEffectInfo * overlaySprite : troopOverlaySpriteAfterWall ) { assert( overlaySprite->icnId != ICN::UNKNOWN ); const fheroes2::Sprite & spellSprite = fheroes2::AGG::GetICN( overlaySprite->icnId, overlaySprite->icnIndex ); fheroes2::Blit( spellSprite, _mainSurface, overlaySprite->position.x, overlaySprite->position.y, overlaySprite->isReflectedImage ); } } else { std::vector troopCounter; std::vector troop; std::vector movingTroop; std::vector troopOverlaySprite; // Redraw monsters. for ( int32_t cellColumnId = 0; cellColumnId < Board::widthInCells; ++cellColumnId ) { const int32_t cellId = cellRowId * Board::widthInCells + cellColumnId; // Check for overlay sprites of dead units (i.e. Resurrect spell). for ( const Unit * deadUnit : arena.getGraveyardUnits( cellId ) ) { for ( const Battle::UnitSpellEffectInfo & overlaySprite : _unitSpellEffectInfos ) { if ( overlaySprite.unitId == deadUnit->GetUID() ) { troopOverlaySprite.emplace_back( &overlaySprite ); } } } const Unit * unitOnCell = Board::GetCell( cellId )->GetUnit(); if ( unitOnCell == nullptr || _flyingUnit == unitOnCell || cellId == unitOnCell->GetTailIndex() ) { continue; } if ( _movingUnit != unitOnCell && unitOnCell->isValid() ) { const int unitAnimState = unitOnCell->GetAnimationState(); const bool isStaticUnit = unitAnimState == Monster_Info::STATIC || unitAnimState == Monster_Info::IDLE; if ( isStaticUnit ) { troopCounter.emplace_back( unitOnCell ); } troop.emplace_back( unitOnCell ); } else { movingTroop.emplace_back( unitOnCell ); } // Check for overlay sprites for 'unitOnCell'. for ( const Battle::UnitSpellEffectInfo & overlaySprite : _unitSpellEffectInfos ) { if ( overlaySprite.unitId == unitOnCell->GetUID() ) { troopOverlaySprite.emplace_back( &overlaySprite ); } } } // Redraw monster counters. for ( const Unit * unit : troop ) { RedrawTroopSprite( *unit ); } for ( const Unit * unit : troopCounter ) { RedrawTroopCount( *unit ); } for ( const Unit * unit : movingTroop ) { RedrawTroopSprite( *unit ); } // Render the overlay sprite for units in current cell row above all units in this and upper rows. for ( const Battle::UnitSpellEffectInfo * overlaySprite : troopOverlaySprite ) { assert( overlaySprite->icnId != ICN::UNKNOWN ); const fheroes2::Sprite & spellSprite = fheroes2::AGG::GetICN( overlaySprite->icnId, overlaySprite->icnIndex ); fheroes2::Blit( spellSprite, _mainSurface, overlaySprite->position.x, overlaySprite->position.y, overlaySprite->isReflectedImage ); } } // Redraw heroes. if ( cellRowId == 2 ) { RedrawOpponents(); } } if ( _flyingUnit ) { RedrawTroopSprite( *_flyingUnit ); } } void Battle::Interface::RedrawOpponents() { if ( _opponent1 ) _opponent1->Redraw( _mainSurface ); if ( _opponent2 ) _opponent2->Redraw( _mainSurface ); RedrawOpponentsFlags(); } void Battle::Interface::RedrawOpponentsFlags() { if ( _opponent1 ) { int icn = ICN::UNKNOWN; switch ( arena.GetArmy1Color() ) { case Color::BLUE: icn = ICN::HEROFL00; break; case Color::GREEN: icn = ICN::HEROFL01; break; case Color::RED: icn = ICN::HEROFL02; break; case Color::YELLOW: icn = ICN::HEROFL03; break; case Color::ORANGE: icn = ICN::HEROFL04; break; case Color::PURPLE: icn = ICN::HEROFL05; break; default: icn = ICN::HEROFL06; break; } const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( icn, ICN::getAnimatedIcnIndex( icn, 0, animation_flags_frame ) ); fheroes2::Blit( flag, _mainSurface, _opponent1->Offset().x + OpponentSprite::LEFT_HERO_X_OFFSET + flag.x(), _opponent1->Offset().y + OpponentSprite::LEFT_HERO_Y_OFFSET + flag.y() ); } if ( _opponent2 ) { int icn = ICN::UNKNOWN; switch ( arena.GetForce2().GetColor() ) { case Color::BLUE: icn = ICN::HEROFL00; break; case Color::GREEN: icn = ICN::HEROFL01; break; case Color::RED: icn = ICN::HEROFL02; break; case Color::YELLOW: icn = ICN::HEROFL03; break; case Color::ORANGE: icn = ICN::HEROFL04; break; case Color::PURPLE: icn = ICN::HEROFL05; break; default: icn = ICN::HEROFL06; break; } const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( icn, ICN::getAnimatedIcnIndex( icn, 0, animation_flags_frame ) ); const fheroes2::Point offset = _opponent2->Offset(); fheroes2::Blit( flag, _mainSurface, offset.x + fheroes2::Display::DEFAULT_WIDTH - OpponentSprite::RIGHT_HERO_X_OFFSET - ( flag.x() + flag.width() ), offset.y + OpponentSprite::RIGHT_HERO_Y_OFFSET + flag.y(), true ); } } void Battle::Interface::RedrawTroopSprite( const Unit & unit ) { if ( b_current_sprite && _currentUnit == &unit ) { drawTroopSprite( unit, *b_current_sprite ); } else if ( unit.Modes( SP_STONE ) ) { // Current monster can't be active if it's under Stunning effect. const int monsterIcnId = unit.GetMonsterSprite(); fheroes2::Sprite monsterSprite = fheroes2::AGG::GetICN( monsterIcnId, unit.GetFrame() ); fheroes2::ApplyPalette( monsterSprite, PAL::GetPalette( PAL::PaletteType::GRAY ) ); drawTroopSprite( unit, monsterSprite ); } else if ( unit.Modes( CAP_MIRRORIMAGE ) ) { fheroes2::Sprite monsterSprite; if ( _currentUnit == &unit && b_current_sprite != nullptr ) { monsterSprite = *b_current_sprite; } else { const int monsterIcnId = unit.GetMonsterSprite(); monsterSprite = fheroes2::AGG::GetICN( monsterIcnId, unit.GetFrame() ); } fheroes2::ApplyPalette( monsterSprite, PAL::GetPalette( PAL::PaletteType::MIRROR_IMAGE ) ); const fheroes2::Point drawnPosition = drawTroopSprite( unit, monsterSprite ); if ( _currentUnit == &unit && b_current_sprite == nullptr ) { // Current unit's turn which is idling. const fheroes2::Sprite & monsterContour = fheroes2::CreateContour( monsterSprite, _contourColor ); fheroes2::Blit( monsterContour, _mainSurface, drawnPosition.x, drawnPosition.y, unit.isReflect() ); } } else { const int monsterIcnId = unit.GetMonsterSprite(); const bool isCurrentMonsterAction = ( _currentUnit == &unit && b_current_sprite != nullptr ); const fheroes2::Sprite & monsterSprite = isCurrentMonsterAction ? *b_current_sprite : fheroes2::AGG::GetICN( monsterIcnId, unit.GetFrame() ); const fheroes2::Point drawnPosition = drawTroopSprite( unit, monsterSprite ); if ( _currentUnit == &unit && b_current_sprite == nullptr ) { // Current unit's turn which is idling. const fheroes2::Sprite & monsterContour = fheroes2::CreateContour( monsterSprite, _contourColor ); fheroes2::Blit( monsterContour, _mainSurface, drawnPosition.x, drawnPosition.y, unit.isReflect() ); } } } fheroes2::Point Battle::Interface::drawTroopSprite( const Unit & unit, const fheroes2::Sprite & troopSprite ) { const fheroes2::Rect & unitPosition = unit.GetRectPosition(); // Get the sprite rendering offset. fheroes2::Point offset = GetTroopPosition( unit, troopSprite ); if ( _movingUnit == &unit ) { // Monster is moving. // Unit coordinates relevant to its position are set in Sprite coordinates 'x' and 'y' (some values may be set incorrectly). // The offset data from BIN file is used in Monster info dialog and to correct horizontal movement range when moving diagonally. // IMPORTANT: The 'x' offset from BIN file cannot be used in horizontal movement animation as // it does not take into account the uneven movement during the step. Use sprite 'x' coordinate for this purpose. if ( _movingUnit->animation.animationLength() ) { // Get the horizontal and vertical movement projections. const int32_t moveX = _movingPos.x - unitPosition.x; const int32_t moveY = _movingPos.y - unitPosition.y; // If it is a slowed flying creature, then it should smoothly move horizontally. if ( _movingUnit->isAbilityPresent( fheroes2::MonsterAbilityType::FLYING ) ) { const double movementProgress = _movingUnit->animation.movementProgress(); offset.x += static_cast( movementProgress * moveX ); offset.y += static_cast( movementProgress * moveY ); } // If the creature has to move diagonally. else if ( moveY != 0 ) { offset.x -= Sign( moveX ) * ( _movingUnit->animation.getCurrentFrameXOffset() ) / 2; offset.y += static_cast( _movingUnit->animation.movementProgress() * moveY ); } } } else if ( _flyingUnit == &unit ) { // Monster is flying. // Get the horizontal and vertical movement projections. const int32_t moveX = _flyingPos.x - unitPosition.x; const int32_t moveY = _flyingPos.y - unitPosition.y; const double movementProgress = _flyingUnit->animation.movementProgress(); offset.x += moveX + static_cast( ( _movingPos.x - _flyingPos.x ) * movementProgress ); offset.y += moveY + static_cast( ( _movingPos.y - _flyingPos.y ) * movementProgress ); } fheroes2::AlphaBlit( troopSprite, _mainSurface, offset.x, offset.y, unit.GetCustomAlpha(), unit.isReflect() ); return offset; } void Battle::Interface::RedrawTroopCount( const Unit & unit ) { const fheroes2::Rect & rt = unit.GetRectPosition(); const fheroes2::Sprite & bar = fheroes2::AGG::GetICN( ICN::TEXTBAR, GetIndexIndicator( unit ) ); const bool isReflected = unit.isReflect(); const int32_t monsterIndex = unit.GetHeadIndex(); const int tileInFront = Board::GetIndexDirection( monsterIndex, isReflected ? Battle::LEFT : Battle::RIGHT ); const bool isValidFrontMonster = ( monsterIndex / Board::widthInCells ) == ( tileInFront == Board::widthInCells ); int32_t sx = rt.x + ( isReflected ? -7 : rt.width - 13 ); const int32_t sy = rt.y + rt.height - bar.height() - ( isReflected ? 21 : 9 ); int xOffset = unit.animation.getTroopCountOffset( isReflected ); // check if has unit standing in front if ( xOffset > 0 && isValidFrontMonster && Board::isValidIndex( tileInFront ) && Board::GetCell( tileInFront )->GetUnit() != nullptr ) xOffset = 0; sx += isReflected ? -xOffset : xOffset; fheroes2::Copy( bar, 0, 0, _mainSurface, sx, sy, bar.width(), bar.height() ); const fheroes2::Text text( fheroes2::abbreviateNumber( static_cast( unit.GetCount() ) ), fheroes2::FontType::smallWhite() ); text.draw( sx + ( bar.width() - text.width() ) / 2, sy + 2, _mainSurface ); } void Battle::Interface::RedrawCover() { _redrawCoverStatic(); const Bridge * bridge = Arena::GetBridge(); if ( bridge && ( bridge->isDown() || _bridgeAnimation.animationIsRequired ) ) { uint32_t spriteIndex = bridge->isDestroyed() ? BridgeMovementAnimation::DESTROYED : BridgeMovementAnimation::DOWN_POSITION; if ( _bridgeAnimation.animationIsRequired ) { spriteIndex = _bridgeAnimation.currentFrameId; } const fheroes2::Sprite & bridgeImage = fheroes2::AGG::GetICN( ICN::getCastleIcnId( Arena::GetCastle()->GetRace() ), spriteIndex ); fheroes2::Blit( bridgeImage, _mainSurface, bridgeImage.x(), bridgeImage.y() ); } const Cell * cell = Board::GetCell( _curentCellIndex ); const int cursorType = Cursor::Get().Themes(); if ( cell && _currentUnit && Settings::Get().BattleShowMouseShadow() ) { std::set highlightedCells; if ( humanturn_spell.isValid() ) { switch ( humanturn_spell.GetID() ) { case Spell::COLDRING: { for ( const int32_t & around : Board::GetAroundIndexes( _curentCellIndex ) ) { const Cell * nearbyCell = Board::GetCell( around ); if ( nearbyCell != nullptr ) { highlightedCells.emplace( nearbyCell ); } } break; } case Spell::FIREBALL: case Spell::METEORSHOWER: { highlightedCells.emplace( cell ); for ( const int32_t & around : Board::GetAroundIndexes( _curentCellIndex ) ) { const Cell * nearbyCell = Board::GetCell( around ); if ( nearbyCell != nullptr ) { highlightedCells.emplace( nearbyCell ); } } break; } case Spell::FIREBLAST: { highlightedCells.emplace( cell ); for ( const int32_t & around : Board::GetDistanceIndexes( _curentCellIndex, 2 ) ) { const Cell * nearbyCell = Board::GetCell( around ); if ( nearbyCell != nullptr ) { highlightedCells.emplace( nearbyCell ); } } break; } case Spell::TELEPORT: { switch ( cursorType ) { case Cursor::WAR_NONE: highlightedCells.emplace( cell ); break; case Cursor::SP_TELEPORT: if ( Board::isValidIndex( _teleportSpellSrcIdx ) ) { const Unit * unitToTeleport = arena.GetTroopBoard( _teleportSpellSrcIdx ); assert( unitToTeleport != nullptr ); const Position pos = Position::GetPosition( *unitToTeleport, _curentCellIndex ); assert( pos.GetHead() != nullptr ); highlightedCells.emplace( pos.GetHead() ); if ( unitToTeleport->isWide() ) { assert( pos.GetTail() != nullptr ); highlightedCells.emplace( pos.GetTail() ); } } else { highlightedCells.emplace( cell ); } break; default: // This should never happen assert( 0 ); break; } break; } default: highlightedCells.emplace( cell ); break; } } else if ( _currentUnit->isAbilityPresent( fheroes2::MonsterAbilityType::AREA_SHOT ) && ( cursorType == Cursor::WAR_ARROW || cursorType == Cursor::WAR_BROKENARROW ) ) { highlightedCells.emplace( cell ); for ( const int32_t & around : Board::GetAroundIndexes( _curentCellIndex ) ) { const Cell * nearbyCell = Board::GetCell( around ); if ( nearbyCell != nullptr ) { highlightedCells.emplace( nearbyCell ); } } } else if ( _currentUnit->isWide() && ( cursorType == Cursor::WAR_MOVE || cursorType == Cursor::WAR_FLY ) ) { const Position pos = Position::GetReachable( *_currentUnit, _curentCellIndex ); assert( pos.GetHead() != nullptr ); assert( pos.GetTail() != nullptr ); highlightedCells.emplace( pos.GetHead() ); highlightedCells.emplace( pos.GetTail() ); } else if ( cursorType == Cursor::SWORD_TOPLEFT || cursorType == Cursor::SWORD_TOPRIGHT || cursorType == Cursor::SWORD_BOTTOMLEFT || cursorType == Cursor::SWORD_BOTTOMRIGHT || cursorType == Cursor::SWORD_LEFT || cursorType == Cursor::SWORD_RIGHT ) { highlightedCells.emplace( cell ); int direction = 0; if ( cursorType == Cursor::SWORD_TOPLEFT ) { direction = BOTTOM_RIGHT; } else if ( cursorType == Cursor::SWORD_TOPRIGHT ) { direction = BOTTOM_LEFT; } else if ( cursorType == Cursor::SWORD_BOTTOMLEFT ) { direction = TOP_RIGHT; } else if ( cursorType == Cursor::SWORD_BOTTOMRIGHT ) { direction = TOP_LEFT; } else if ( cursorType == Cursor::SWORD_LEFT ) { direction = RIGHT; } else if ( cursorType == Cursor::SWORD_RIGHT ) { direction = LEFT; } else { assert( 0 ); } const Position pos = Position::GetReachable( *_currentUnit, Board::GetIndexDirection( _curentCellIndex, direction ) ); assert( pos.GetHead() != nullptr ); highlightedCells.emplace( pos.GetHead() ); if ( _currentUnit->isWide() ) { assert( pos.GetTail() != nullptr ); highlightedCells.emplace( pos.GetTail() ); } if ( _currentUnit->isDoubleCellAttack() ) { const Cell * secondAttackedCell = Board::GetCell( _curentCellIndex, Board::GetReflectDirection( direction ) ); if ( secondAttackedCell ) { highlightedCells.emplace( secondAttackedCell ); } } else if ( _currentUnit->isAllAdjacentCellsAttack() ) { for ( const int32_t nearbyIdx : Board::GetAroundIndexes( pos ) ) { // Should already be highlighted if ( nearbyIdx == _curentCellIndex ) { continue; } const Cell * nearbyCell = Board::GetCell( nearbyIdx ); assert( nearbyCell != nullptr ); const Unit * nearbyUnit = nearbyCell->GetUnit(); if ( nearbyUnit && nearbyUnit->GetColor() != _currentUnit->GetCurrentColor() ) { highlightedCells.emplace( nearbyCell ); } } } } else { highlightedCells.emplace( cell ); } assert( !highlightedCells.empty() ); const HeroBase * currentCommander = arena.GetCurrentCommander(); for ( const Cell * highlightedCell : highlightedCells ) { assert( highlightedCell != nullptr ); bool isApplicable = highlightedCell->isPassable( false ); if ( isApplicable ) { const Unit * highlightedUnit = highlightedCell->GetUnit(); isApplicable = highlightedUnit == nullptr || !humanturn_spell.isValid() || highlightedUnit->AllowApplySpell( humanturn_spell, currentCommander ); } if ( isApplicable ) { fheroes2::Blit( _hexagonCursorShadow, _mainSurface, highlightedCell->GetPos().x, highlightedCell->GetPos().y ); } } } } void Battle::Interface::_redrawBattleGround() { // Battlefield background image. if ( _battleGroundIcn != ICN::UNKNOWN ) { const fheroes2::Sprite & cbkg = fheroes2::AGG::GetICN( _battleGroundIcn, 0 ); fheroes2::Copy( cbkg, _battleGround ); } // Objects near the left and right borders of the Battlefield. if ( _borderObjectsIcn != ICN::UNKNOWN ) { const fheroes2::Sprite & frng = fheroes2::AGG::GetICN( _borderObjectsIcn, 0 ); fheroes2::Blit( frng, _battleGround, frng.x(), frng.y() ); } // Big obstacles in the center of the Battlefield. if ( arena.GetICNCovr() != ICN::UNKNOWN ) { const fheroes2::Sprite & cover = fheroes2::AGG::GetICN( arena.GetICNCovr(), 0 ); fheroes2::Blit( cover, _battleGround, cover.x(), cover.y() ); } const Castle * castle = Arena::GetCastle(); int castleBackgroundIcnId = ICN::UNKNOWN; if ( castle != nullptr ) { // Castle ground. switch ( castle->GetRace() ) { case Race::BARB: castleBackgroundIcnId = ICN::CASTBKGB; break; case Race::KNGT: castleBackgroundIcnId = ICN::CASTBKGK; break; case Race::NECR: castleBackgroundIcnId = ICN::CASTBKGN; break; case Race::SORC: castleBackgroundIcnId = ICN::CASTBKGS; break; case Race::WRLK: castleBackgroundIcnId = ICN::CASTBKGW; break; case Race::WZRD: castleBackgroundIcnId = ICN::CASTBKGZ; break; default: // Did you add a new race? Add the appropriate logic for it. assert( 0 ); break; } const fheroes2::Sprite & castleBackground = fheroes2::AGG::GetICN( castleBackgroundIcnId, 1 ); fheroes2::Blit( castleBackground, _battleGround, castleBackground.x(), castleBackground.y() ); // Moat. if ( castle->isBuild( BUILD_MOAT ) ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::MOATWHOL, 0 ); fheroes2::Blit( sprite, _battleGround, sprite.x(), sprite.y() ); } } // Battlefield grid. if ( Settings::Get().BattleShowGrid() ) { const Board & board = *Arena::GetBoard(); for ( const Cell & cell : board ) { fheroes2::Blit( _hexagonGrid, _battleGround, cell.GetPos().x, cell.GetPos().y ); } } // Ground obstacles. for ( int32_t cellId = 0; cellId < Board::sizeInCells; ++cellId ) { RedrawLowObjects( cellId ); } // Castle top wall. if ( castle != nullptr ) { const fheroes2::Sprite & sprite2 = fheroes2::AGG::GetICN( castleBackgroundIcnId, castle->isFortificationBuilt() ? 4 : 3 ); fheroes2::Blit( sprite2, _battleGround, sprite2.x(), sprite2.y() ); } } void Battle::Interface::_redrawCoverStatic() { fheroes2::Copy( _battleGround, _mainSurface ); const Settings & conf = Settings::Get(); // Movement shadow. if ( !_movingUnit && conf.BattleShowMoveShadow() && _currentUnit && !( _currentUnit->GetCurrentControl() & CONTROL_AI ) ) { const fheroes2::Image & shadowImage = conf.BattleShowGrid() ? _hexagonGridShadow : _hexagonShadow; const Board & board = *Arena::GetBoard(); for ( const Cell & cell : board ) { const Position pos = Position::GetReachable( *_currentUnit, cell.GetIndex() ); if ( pos.GetHead() != nullptr ) { assert( pos.isValidForUnit( _currentUnit ) ); fheroes2::Blit( shadowImage, _mainSurface, cell.GetPos().x, cell.GetPos().y ); } } } } void Battle::Interface::RedrawCastle( const Castle & castle, const int32_t cellId ) { const int castleIcnId = ICN::getCastleIcnId( castle.GetRace() ); if ( Arena::CATAPULT_POS == cellId ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::CATAPULT, catapult_frame ); fheroes2::Blit( sprite, _mainSurface, 22 + sprite.x(), 390 + sprite.y() ); } else if ( Arena::CASTLE_GATE_POS == cellId ) { const Bridge * bridge = Arena::GetBridge(); assert( bridge != nullptr ); if ( bridge != nullptr && !bridge->isDestroyed() ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( castleIcnId, 4 ); fheroes2::Blit( sprite, _mainSurface, sprite.x(), sprite.y() ); } } else if ( Arena::CASTLE_FIRST_TOP_WALL_POS == cellId || Arena::CASTLE_SECOND_TOP_WALL_POS == cellId || Arena::CASTLE_THIRD_TOP_WALL_POS == cellId || Arena::CASTLE_FOURTH_TOP_WALL_POS == cellId ) { uint32_t index = 0; switch ( cellId ) { case Arena::CASTLE_FIRST_TOP_WALL_POS: index = 5; break; case Arena::CASTLE_SECOND_TOP_WALL_POS: index = 6; break; case Arena::CASTLE_THIRD_TOP_WALL_POS: index = 7; break; case Arena::CASTLE_FOURTH_TOP_WALL_POS: index = 8; break; default: break; } if ( castle.isFortificationBuilt() ) { switch ( Board::GetCell( cellId )->GetObject() ) { case 0: index += 31; break; case 1: index += 35; break; case 2: index += 27; break; case 3: index += 23; break; default: break; } } else { switch ( Board::GetCell( cellId )->GetObject() ) { case 0: index += 8; break; case 1: index += 4; break; case 2: index += 0; break; default: break; } } const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( castleIcnId, index ); fheroes2::Blit( sprite, _mainSurface, sprite.x(), sprite.y() ); } else if ( Arena::CASTLE_TOP_ARCHER_TOWER_POS == cellId ) { const Tower * ltower = Arena::GetTower( TowerType::TWR_LEFT ); uint32_t index = 17; if ( castle.isBuild( BUILD_LEFTTURRET ) && ltower ) { index = ltower->isValid() ? 18 : 19; } else if ( Board::GetCell( cellId )->GetObject() == 1 ) { // Tower without built turret can be damaged by the Earthquake spell. index = 19; } const fheroes2::Sprite & towerSprite = fheroes2::AGG::GetICN( castleIcnId, index ); fheroes2::Blit( towerSprite, _mainSurface, 443 + towerSprite.x(), 153 + towerSprite.y() ); } else if ( Arena::CASTLE_BOTTOM_ARCHER_TOWER_POS == cellId ) { const Tower * rtower = Arena::GetTower( TowerType::TWR_RIGHT ); uint32_t index = 17; if ( castle.isBuild( BUILD_RIGHTTURRET ) && rtower ) { index = rtower->isValid() ? 18 : 19; } else if ( Board::GetCell( cellId )->GetObject() == 1 ) { // Tower without built turret can be damaged by the Earthquake spell. index = 19; } const fheroes2::Sprite & towerSprite = fheroes2::AGG::GetICN( castleIcnId, index ); fheroes2::Blit( towerSprite, _mainSurface, 443 + towerSprite.x(), 405 + towerSprite.y() ); } else if ( Arena::CASTLE_TOP_GATE_TOWER_POS == cellId ) { const int index = ( Board::GetCell( cellId )->GetObject() == 1 ) ? 19 : 17; const fheroes2::Sprite & towerSprite = fheroes2::AGG::GetICN( castleIcnId, index ); fheroes2::Blit( towerSprite, _mainSurface, 399 + towerSprite.x(), 237 + towerSprite.y() ); } else if ( Arena::CASTLE_BOTTOM_GATE_TOWER_POS == cellId ) { const int index = ( Board::GetCell( cellId )->GetObject() == 1 ) ? 19 : 17; const fheroes2::Sprite & towerSprite = fheroes2::AGG::GetICN( castleIcnId, index ); fheroes2::Blit( towerSprite, _mainSurface, 399 + towerSprite.x(), 321 + towerSprite.y() ); } } void Battle::Interface::RedrawCastleMainTower( const Castle & castle ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::getCastleIcnId( castle.GetRace() ), ( Arena::GetTower( TowerType::TWR_CENTER )->isValid() ? 20 : 26 ) ); fheroes2::Blit( sprite, _mainSurface, sprite.x(), sprite.y() ); } void Battle::Interface::RedrawLowObjects( const int32_t cellId ) { const Cell * cell = Board::GetCell( cellId ); if ( cell == nullptr ) return; const int cellObjectId = cell->GetObject(); if ( cellObjectId == 0 ) { // No object exists. return; } int objectIcnId = 0; switch ( cellObjectId ) { case 0x84: objectIcnId = ICN::COBJ0004; break; case 0x87: objectIcnId = ICN::COBJ0007; break; case 0x90: objectIcnId = ICN::COBJ0016; break; case 0x9E: objectIcnId = ICN::COBJ0030; break; case 0x9F: objectIcnId = ICN::COBJ0031; break; default: return; } const fheroes2::Sprite & objectSprite = fheroes2::AGG::GetICN( objectIcnId, 0 ); const fheroes2::Rect & pt = cell->GetPos(); fheroes2::Blit( objectSprite, _battleGround, pt.x + pt.width / 2 + objectSprite.x(), pt.y + pt.height + objectSprite.y() + cellYOffset ); } void Battle::Interface::RedrawHighObjects( const int32_t cellId ) { const Cell * cell = Board::GetCell( cellId ); if ( cell == nullptr ) return; const int cellObjectId = cell->GetObject(); if ( cellObjectId == 0 ) { // No object exists. return; } int objectIcnId = 0; switch ( cellObjectId ) { case 0x80: objectIcnId = ICN::COBJ0000; break; case 0x81: objectIcnId = ICN::COBJ0001; break; case 0x82: objectIcnId = ICN::COBJ0002; break; case 0x83: objectIcnId = ICN::COBJ0003; break; case 0x85: objectIcnId = ICN::COBJ0005; break; case 0x86: objectIcnId = ICN::COBJ0006; break; case 0x88: objectIcnId = ICN::COBJ0008; break; case 0x89: objectIcnId = ICN::COBJ0009; break; case 0x8A: objectIcnId = ICN::COBJ0010; break; case 0x8B: objectIcnId = ICN::COBJ0011; break; case 0x8C: objectIcnId = ICN::COBJ0012; break; case 0x8D: objectIcnId = ICN::COBJ0013; break; case 0x8E: objectIcnId = ICN::COBJ0014; break; case 0x8F: objectIcnId = ICN::COBJ0015; break; case 0x91: objectIcnId = ICN::COBJ0017; break; case 0x92: objectIcnId = ICN::COBJ0018; break; case 0x93: objectIcnId = ICN::COBJ0019; break; case 0x94: objectIcnId = ICN::COBJ0020; break; case 0x95: objectIcnId = ICN::COBJ0021; break; case 0x96: objectIcnId = ICN::COBJ0022; break; case 0x97: objectIcnId = ICN::COBJ0023; break; case 0x98: objectIcnId = ICN::COBJ0024; break; case 0x99: objectIcnId = ICN::COBJ0025; break; case 0x9A: objectIcnId = ICN::COBJ0026; break; case 0x9B: objectIcnId = ICN::COBJ0027; break; case 0x9C: objectIcnId = ICN::COBJ0028; break; case 0x9D: objectIcnId = ICN::COBJ0029; break; default: return; } const fheroes2::Sprite & objectSprite = fheroes2::AGG::GetICN( objectIcnId, 0 ); const fheroes2::Rect & pt = cell->GetPos(); fheroes2::Blit( objectSprite, _mainSurface, pt.x + pt.width / 2 + objectSprite.x(), pt.y + pt.height + objectSprite.y() + cellYOffset ); } void Battle::Interface::RedrawKilled() { // Redraw killed troops. for ( const int32_t & cell : arena.getCellsOccupiedByGraveyard() ) { for ( const Unit * unit : arena.getGraveyardUnits( cell ) ) { if ( unit && cell != unit->GetTailIndex() ) { RedrawTroopSprite( *unit ); } } } } int Battle::Interface::GetBattleCursor( std::string & statusMsg ) const { statusMsg.clear(); const Cell * cell = Board::GetCell( _curentCellIndex ); if ( cell && _currentUnit ) { const auto formatViewInfoMsg = []( const Unit * unit ) { assert( unit != nullptr ); std::string msg = _( "View %{monster} info" ); StringReplaceWithLowercase( msg, "%{monster}", unit->GetMultiName() ); return msg; }; const Unit * unit = cell->GetUnit(); if ( unit == nullptr || _currentUnit == unit ) { const Position pos = Position::GetReachable( *_currentUnit, _curentCellIndex ); if ( pos.GetHead() != nullptr ) { assert( pos.isValidForUnit( _currentUnit ) ); if ( pos.GetHead()->GetIndex() == _currentUnit->GetHeadIndex() ) { assert( !_currentUnit->isWide() || pos.GetTail()->GetIndex() == _currentUnit->GetTailIndex() ); statusMsg = formatViewInfoMsg( _currentUnit ); return Cursor::WAR_INFO; } statusMsg = _currentUnit->isFlying() ? _( "Fly %{monster} here" ) : _( "Move %{monster} here" ); StringReplaceWithLowercase( statusMsg, "%{monster}", _currentUnit->GetName() ); return _currentUnit->isFlying() ? Cursor::WAR_FLY : Cursor::WAR_MOVE; } } else { if ( _currentUnit->GetCurrentColor() == unit->GetColor() ) { statusMsg = formatViewInfoMsg( unit ); return Cursor::WAR_INFO; } if ( _currentUnit->isArchers() && !_currentUnit->isHandFighting() ) { statusMsg = _( "Shoot %{monster}" ); statusMsg.append( " " ); statusMsg.append( _n( "(1 shot left)", "(%{count} shots left)", _currentUnit->GetShots() ) ); StringReplaceWithLowercase( statusMsg, "%{monster}", unit->GetMultiName() ); StringReplace( statusMsg, "%{count}", _currentUnit->GetShots() ); return arena.IsShootingPenalty( *_currentUnit, *unit ) ? Cursor::WAR_BROKENARROW : Cursor::WAR_ARROW; } // Find all possible directions where the current monster can attack. std::set availableAttackDirection; for ( const int direction : { BOTTOM_RIGHT, BOTTOM_LEFT, RIGHT, TOP_RIGHT, TOP_LEFT, LEFT } ) { if ( Board::isValidDirection( _curentCellIndex, direction ) && Board::CanAttackFromCell( *_currentUnit, Board::GetIndexDirection( _curentCellIndex, direction ) ) ) { availableAttackDirection.emplace( direction ); } } if ( !availableAttackDirection.empty() ) { int currentDirection = cell->GetTriangleDirection( getRelativeMouseCursorPos() ); if ( currentDirection == UNKNOWN ) { // This could happen when another window has popped up and the user moved the mouse. currentDirection = CENTER; } if ( availableAttackDirection.count( currentDirection ) == 0 ) { // This direction is not valid. Find the nearest one. if ( availableAttackDirection.size() == 1 ) { currentDirection = *availableAttackDirection.begin(); } else { // First search clockwise. CellDirection clockWiseDirection = static_cast( currentDirection ); CellDirection antiClockWiseDirection = static_cast( currentDirection ); while ( true ) { ++clockWiseDirection; if ( availableAttackDirection.count( clockWiseDirection ) > 0 ) { currentDirection = clockWiseDirection; break; } --antiClockWiseDirection; if ( availableAttackDirection.count( antiClockWiseDirection ) > 0 ) { currentDirection = antiClockWiseDirection; break; } } } } const int cursor = GetSwordCursorDirection( currentDirection ); statusMsg = _( "Attack %{monster}" ); StringReplaceWithLowercase( statusMsg, "%{monster}", unit->GetName() ); return cursor; } } } statusMsg = _( "Turn %{turn}" ); StringReplace( statusMsg, "%{turn}", arena.GetTurnNumber() ); return Cursor::WAR_NONE; } int Battle::Interface::GetBattleSpellCursor( std::string & statusMsg ) const { statusMsg.clear(); const Cell * cell = Board::GetCell( _curentCellIndex ); const Spell & spell = humanturn_spell; if ( cell && _currentUnit && spell.isValid() ) { const Unit * unitOnCell = cell->GetUnit(); // Cursor is over some dead unit that we can resurrect if ( unitOnCell == nullptr && arena.isAbleToResurrectFromGraveyard( _curentCellIndex, spell ) ) { unitOnCell = arena.getLastResurrectableUnitFromGraveyard( _curentCellIndex, spell ); assert( unitOnCell != nullptr && !unitOnCell->isValid() ); } // Check the Teleport spell first if ( Board::isValidIndex( _teleportSpellSrcIdx ) ) { const Unit * unitToTeleport = arena.GetTroopBoard( _teleportSpellSrcIdx ); assert( unitToTeleport != nullptr ); if ( unitOnCell == nullptr && cell->isPassableForUnit( *unitToTeleport ) ) { statusMsg = _( "Teleport here" ); return Cursor::SP_TELEPORT; } statusMsg = _( "Invalid teleport destination" ); return Cursor::WAR_NONE; } if ( unitOnCell && unitOnCell->AllowApplySpell( spell, _currentUnit->GetCurrentOrArmyCommander() ) ) { statusMsg = _( "Cast %{spell} on %{monster}" ); StringReplace( statusMsg, "%{spell}", spell.GetName() ); StringReplaceWithLowercase( statusMsg, "%{monster}", unitOnCell->GetName() ); return GetCursorFromSpell( spell.GetID() ); } if ( !spell.isApplyToFriends() && !spell.isApplyToEnemies() && !spell.isApplyToAnyTroops() ) { statusMsg = _( "Cast %{spell}" ); StringReplace( statusMsg, "%{spell}", spell.GetName() ); return GetCursorFromSpell( spell.GetID() ); } } statusMsg = _( "Select spell target" ); return Cursor::WAR_NONE; } void Battle::Interface::getPendingActions( Actions & actions ) { if ( _interruptAutoCombatForColor ) { actions.emplace_back( Command::TOGGLE_AUTO_COMBAT, _interruptAutoCombatForColor ); _interruptAutoCombatForColor = 0; } } void Battle::Interface::HumanTurn( const Unit & unit, Actions & actions ) { Cursor::Get().SetThemes( Cursor::WAR_POINTER ); // Reset the cursor position to avoid forcing the cursor shadow to be drawn at the last position of the previous turn. _curentCellIndex = -1; _currentUnit = &unit; humanturn_redraw = false; humanturn_exit = false; catapult_frame = 0; // in case we moved the window _interfacePosition = border.GetArea(); popup.reset(); // Wait for previously set and not passed delays before rendering a new frame. WaitForAllActionDelays(); ResetIdleTroopAnimation(); Redraw(); std::string msg; animation_flags_frame = 0; // TODO: update delay types within the loop to avoid rendering slowdown. const std::vector delayTypes{ Game::BATTLE_FLAGS_DELAY }; const Board * board = Arena::GetBoard(); LocalEvent & le = LocalEvent::Get(); while ( !humanturn_exit && le.HandleEvents( Game::isDelayNeeded( delayTypes ) ) ) { // move cursor int32_t indexNew = -1; if ( le.isMouseCursorPosInArea( { _interfacePosition.x, _interfacePosition.y, _interfacePosition.width, _interfacePosition.height - status.height } ) ) { indexNew = board->GetIndexAbsPosition( getRelativeMouseCursorPos() ); } if ( _curentCellIndex != indexNew ) { _curentCellIndex = indexNew; humanturn_redraw = true; } if ( humanturn_spell.isValid() ) { HumanCastSpellTurn( unit, actions, msg ); } else { HumanBattleTurn( unit, actions, msg ); } // update status if ( msg != status.getMessage() ) { status.setMessage( msg, false ); humanturn_redraw = true; } // animation troops if ( IdleTroopsAnimation() ) { humanturn_redraw = true; } CheckGlobalEvents( le ); // redraw arena if ( humanturn_redraw ) { Redraw(); humanturn_redraw = false; } else if ( listlog && listlog->IsNeedRedraw() ) { listlog->Redraw(); fheroes2::Display::instance().render( listlog->GetArea() ); } } popup.reset(); _currentUnit = nullptr; } void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, std::string & msg ) { Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); const Settings & conf = Settings::Get(); BoardActionIntentUpdater boardActionIntentUpdater( _boardActionIntent, le.isMouseEventFromTouchpad() ); _buttonAuto.drawOnState( le.isMouseLeftButtonPressedInArea( _buttonAuto.area() ) ); _buttonSettings.drawOnState( le.isMouseLeftButtonPressedInArea( _buttonSettings.area() ) ); _buttonSkip.drawOnState( le.isMouseLeftButtonPressedInArea( _buttonSkip.area() ) ); if ( le.isAnyKeyPressed() ) { // Skip the turn if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_SKIP ) ) { actions.emplace_back( Command::SKIP, unit.GetUID() ); humanturn_exit = true; } // Battle options else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_OPTIONS ) ) { EventShowOptions(); } // Switch the auto combat mode on else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_TOGGLE_AUTO_COMBAT ) ) { EventStartAutoCombat( unit, actions ); } // Resolve the combat in quick combat mode else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_QUICK_COMBAT ) ) { EventQuickCombat( actions ); } // Cast the spell else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_CAST_SPELL ) ) { ProcessingHeroDialogResult( 1, actions ); } // Retreat else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_RETREAT ) ) { ProcessingHeroDialogResult( 2, actions ); } // Surrender else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_SURRENDER ) ) { ProcessingHeroDialogResult( 3, actions ); } } // Add offsets to inner objects fheroes2::Rect battleFieldRect{ _interfacePosition.x, _interfacePosition.y, _interfacePosition.width, _interfacePosition.height - status.height }; // Swipe attack motion finished, but the destination was outside the arena. We need to clear the swipe attack state. if ( !le.isDragInProgress() && Board::isValidIndex( _swipeAttack.srcCellIndex ) && !Board::isValidIndex( _curentCellIndex ) ) { _swipeAttack = {}; } bool doListlogProcessing = listlog && listlog->isOpenLog(); if ( doListlogProcessing ) { const fheroes2::Rect & lislogRect = listlog->GetArea(); battleFieldRect.height -= lislogRect.height; // Do battle log event processing only if mouse pointer is over it. doListlogProcessing = le.isMouseCursorPosInArea( lislogRect ) || le.isMouseLeftButtonPressedInArea( lislogRect ); } if ( doListlogProcessing ) { cursor.SetThemes( Cursor::WAR_POINTER ); // Hide the possibly shown Damage Info pop-up dialog. popup.reset(); listlog->QueueEventProcessing(); } else if ( Arena::GetTower( TowerType::TWR_CENTER ) && le.isMouseCursorPosInArea( _ballistaTowerRect ) ) { cursor.SetThemes( Cursor::WAR_INFO ); msg = _( "View Ballista info" ); if ( le.MouseClickLeft( _ballistaTowerRect ) || le.isMouseRightButtonPressedInArea( _ballistaTowerRect ) ) { const Castle * cstl = Arena::GetCastle(); std::string ballistaMessage = Tower::GetInfo( *cstl ); if ( cstl->isBuild( BUILD_MOAT ) ) { ballistaMessage.append( "\n\n" ); ballistaMessage.append( Battle::Board::GetMoatInfo() ); } fheroes2::showStandardTextMessage( _( "Ballista" ), ballistaMessage, le.isMouseRightButtonPressed() ? Dialog::ZERO : Dialog::OK ); } } else if ( conf.BattleShowTurnOrder() && le.isMouseCursorPosInArea( _turnOrder ) ) { cursor.SetThemes( Cursor::POINTER ); _turnOrder.queueEventProcessing( msg, _interfacePosition.getPosition() ); } else if ( le.isMouseCursorPosInArea( _buttonAuto.area() ) ) { cursor.SetThemes( Cursor::WAR_POINTER ); msg = _( "Automatic combat modes" ); if ( le.MouseClickLeft( _buttonAuto.area() ) ) { OpenAutoModeDialog( unit, actions ); } else if ( le.isMouseRightButtonPressed() ) { fheroes2::showStandardTextMessage( _( "Automatic Combat Modes" ), _( "Choose between proceeding the combat in auto combat mode or in quick combat mode." ), Dialog::ZERO ); } } else if ( le.isMouseCursorPosInArea( _buttonSettings.area() ) ) { cursor.SetThemes( Cursor::WAR_POINTER ); msg = _( "Customize system options" ); if ( le.MouseClickLeft( _buttonSettings.area() ) ) { _openBattleSettingsDialog(); humanturn_redraw = true; } else if ( le.isMouseRightButtonPressed() ) { fheroes2::showStandardTextMessage( _( "System Options" ), _( "Allows you to customize the combat screen." ), Dialog::ZERO ); } } else if ( le.isMouseCursorPosInArea( _buttonSkip.area() ) ) { cursor.SetThemes( Cursor::WAR_POINTER ); msg = _( "Skip this unit" ); if ( le.MouseClickLeft( _buttonSkip.area() ) ) { assert( _currentUnit != nullptr ); actions.emplace_back( Command::SKIP, _currentUnit->GetUID() ); humanturn_exit = true; } else if ( le.isMouseRightButtonPressed() ) { fheroes2::showStandardTextMessage( _( "Skip" ), _( "Skips the current creature. The current creature ends its turn and does not get to go again until the next round." ), Dialog::ZERO ); } } else if ( _opponent1 && le.isMouseCursorPosInArea( _opponent1->GetArea() + _interfacePosition.getPosition() ) ) { const fheroes2::Rect opponent1Area = _opponent1->GetArea() + _interfacePosition.getPosition(); if ( arena.GetCurrentColor() == arena.GetArmy1Color() ) { if ( _opponent1->GetHero()->isCaptain() ) { msg = _( "View Captain's options" ); } else { msg = _( "View Hero's options" ); } cursor.SetThemes( Cursor::WAR_HERO ); if ( le.MouseClickLeft( opponent1Area ) ) { ProcessingHeroDialogResult( arena.DialogBattleHero( *_opponent1->GetHero(), true, status ), actions ); humanturn_redraw = true; } } else { if ( _opponent1->GetHero()->isCaptain() ) { msg = _( "View opposing Captain" ); } else { msg = _( "View opposing Hero" ); } cursor.SetThemes( Cursor::WAR_INFO ); if ( le.MouseClickLeft( opponent1Area ) ) { arena.DialogBattleHero( *_opponent1->GetHero(), true, status ); humanturn_redraw = true; } } if ( le.isMouseRightButtonPressedInArea( opponent1Area ) ) { arena.DialogBattleHero( *_opponent1->GetHero(), false, status ); humanturn_redraw = true; } } else if ( _opponent2 && le.isMouseCursorPosInArea( _opponent2->GetArea() + _interfacePosition.getPosition() ) ) { const fheroes2::Rect opponent2Area = _opponent2->GetArea() + _interfacePosition.getPosition(); if ( arena.GetCurrentColor() == arena.GetForce2().GetColor() ) { if ( _opponent2->GetHero()->isCaptain() ) { msg = _( "View Captain's options" ); } else { msg = _( "View Hero's options" ); } cursor.SetThemes( Cursor::WAR_HERO ); if ( le.MouseClickLeft( opponent2Area ) ) { ProcessingHeroDialogResult( arena.DialogBattleHero( *_opponent2->GetHero(), true, status ), actions ); humanturn_redraw = true; } } else { if ( _opponent2->GetHero()->isCaptain() ) { msg = _( "View opposing Captain" ); } else { msg = _( "View opposing Hero" ); } cursor.SetThemes( Cursor::WAR_INFO ); if ( le.MouseClickLeft( opponent2Area ) ) { arena.DialogBattleHero( *_opponent2->GetHero(), true, status ); humanturn_redraw = true; } } if ( le.isMouseRightButtonPressedInArea( opponent2Area ) ) { arena.DialogBattleHero( *_opponent2->GetHero(), false, status ); humanturn_redraw = true; } } else if ( le.isMouseCursorPosInArea( battleFieldRect ) ) { int themes = GetBattleCursor( msg ); if ( _swipeAttack.isValid() ) { // The swipe attack motion is either in progress or has finished. if ( _curentCellIndex == _swipeAttack.dstCellIndex ) { // The cursor is above the stored destination, we should display the stored attack theme. themes = _swipeAttack.dstTheme; } else { // The cursor has left the destination. Abort the swipe attack. _swipeAttack = {}; _boardActionIntent = {}; } } else if ( _swipeAttack.isValidDestination( themes, _curentCellIndex ) ) { // Valid swipe attack target cell. Calculate the attack angle based on destination and source cells. themes = GetSwordCursorDirection( Board::GetDirection( _curentCellIndex, _swipeAttack.srcCellIndex ) ); // Remember the swipe destination cell and theme. _swipeAttack.setDst( themes, _curentCellIndex ); // Clear any pending intents. We don't want to confirm previous actions by performing swipe attack motion. _boardActionIntent = {}; } cursor.SetThemes( themes ); const Cell * cell = Board::GetCell( _curentCellIndex ); if ( cell ) { if ( CursorAttack( themes ) ) { popup.setAttackInfo( _currentUnit, cell->GetUnit() ); } else { popup.reset(); } boardActionIntentUpdater.setIntent( { themes, _curentCellIndex } ); if ( le.MouseClickLeft( battleFieldRect ) ) { const bool isConfirmed = boardActionIntentUpdater.isConfirmed(); if ( isConfirmed ) { // Intent is confirmed, it is safe to clear the swipe state (regardless of the intent and the input method). _swipeAttack = {}; } MouseLeftClickBoardAction( themes, *cell, isConfirmed, actions ); } else if ( le.isMouseRightButtonPressed() ) { MousePressRightBoardAction( *cell ); } else if ( le.isMouseLeftButtonPressedInArea( battleFieldRect ) ) { if ( !le.isDragInProgress() && !_swipeAttack.isValid() ) { le.registerDrag(); // Remember the swipe source cell and theme. _swipeAttack = {}; _swipeAttack.setSrc( themes, _curentCellIndex, _currentUnit ); } } } else { le.MouseClickLeft(); le.MouseClickRight(); // Reset the shown Damage Info pop-up when the cursor is moved out of the cells area. popup.reset(); } } else if ( le.isMouseCursorPosInArea( status ) ) { // Hide the possibly shown Damage Info pop-up dialog. popup.reset(); if ( listlog ) { msg = ( listlog->isOpenLog() ? _( "Hide logs" ) : _( "Show logs" ) ); if ( le.MouseClickLeft( status ) ) { listlog->SetOpenLog( !listlog->isOpenLog() ); } else if ( le.isMouseRightButtonPressedInArea( status ) ) { fheroes2::showStandardTextMessage( _( "Message Bar" ), _( "Shows the results of individual monster's actions." ), Dialog::ZERO ); } } cursor.SetThemes( Cursor::WAR_POINTER ); } else { cursor.SetThemes( Cursor::WAR_NONE ); le.MouseClickLeft(); le.MouseClickRight(); } } void Battle::Interface::HumanCastSpellTurn( const Unit & /* unused */, Actions & actions, std::string & msg ) { Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); BoardActionIntentUpdater boardActionIntentUpdater( _boardActionIntent, le.isMouseEventFromTouchpad() ); // Cancel the spellcast if ( le.isMouseRightButtonPressed() || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { popup.reset(); humanturn_spell = Spell::NONE; _teleportSpellSrcIdx = -1; } else if ( le.isMouseCursorPosInArea( _interfacePosition ) && humanturn_spell.isValid() ) { const int themes = GetBattleSpellCursor( msg ); cursor.SetThemes( themes ); if ( const Cell * cell = Board::GetCell( _curentCellIndex ); cell && _currentUnit && cell->GetUnit() ) { popup.setSpellAttackInfo( _currentUnit->GetCurrentOrArmyCommander(), cell->GetUnit(), humanturn_spell ); } else { popup.reset(); } boardActionIntentUpdater.setIntent( { themes, _curentCellIndex } ); if ( le.MouseClickLeft() && Cursor::WAR_NONE != cursor.Themes() && boardActionIntentUpdater.isConfirmed() ) { if ( !Board::isValidIndex( _curentCellIndex ) ) { DEBUG_LOG( DBG_BATTLE, DBG_WARN, "Spell destination is out of range: " << _curentCellIndex ) return; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, humanturn_spell.GetName() << ", dst: " << _curentCellIndex ) if ( Cursor::SP_TELEPORT == cursor.Themes() ) { if ( _teleportSpellSrcIdx < 0 ) { _teleportSpellSrcIdx = _curentCellIndex; } else { actions.emplace_back( Command::SPELLCAST, Spell::TELEPORT, _teleportSpellSrcIdx, _curentCellIndex ); humanturn_spell = Spell::NONE; humanturn_exit = true; _teleportSpellSrcIdx = -1; } } else if ( Cursor::SP_MIRRORIMAGE == cursor.Themes() ) { actions.emplace_back( Command::SPELLCAST, Spell::MIRRORIMAGE, _curentCellIndex ); humanturn_spell = Spell::NONE; humanturn_exit = true; } else { actions.emplace_back( Command::SPELLCAST, humanturn_spell.GetID(), _curentCellIndex ); humanturn_spell = Spell::NONE; humanturn_exit = true; } } } else { cursor.SetThemes( Cursor::WAR_NONE ); } } void Battle::Interface::FadeArena( const bool clearMessageLog ) { AudioManager::ResetAudio(); fheroes2::Display & display = fheroes2::Display::instance(); if ( clearMessageLog ) { status.clear(); status.redraw( display ); } Redraw(); const fheroes2::Rect srt = border.GetArea(); fheroes2::Image top; top._disableTransformLayer(); top.resize( srt.width, srt.height ); fheroes2::Copy( display, srt.x, srt.y, top, 0, 0, srt.width, srt.height ); fheroes2::FadeDisplayWithPalette( top, srt.getPosition(), 5, 300, 5 ); display.render(); } void Battle::Interface::_openBattleSettingsDialog() { const Settings & conf = Settings::Get(); const bool showGrid = conf.BattleShowGrid(); DialogBattleSettings(); if ( showGrid != conf.BattleShowGrid() ) { // The grid setting has changed. Update for the Battlefield ground. _redrawBattleGround(); } } void Battle::Interface::EventShowOptions() { _buttonSettings.drawOnPress(); _openBattleSettingsDialog(); _buttonSettings.drawOnRelease(); humanturn_redraw = true; } bool Battle::Interface::EventStartAutoCombat( const Unit & unit, Actions & actions ) { // TODO: remove these temporary assertions assert( arena.CanToggleAutoCombat() ); assert( !arena.AutoCombatInProgress() ); if ( fheroes2::showStandardTextMessage( {}, _( "Are you sure you want to enable the auto combat mode?" ), Dialog::YES | Dialog::NO ) != Dialog::YES ) { return false; } actions.emplace_back( Command::TOGGLE_AUTO_COMBAT, unit.GetCurrentOrArmyColor() ); humanturn_redraw = true; humanturn_exit = true; return true; } bool Battle::Interface::EventQuickCombat( Actions & actions ) { if ( fheroes2::showStandardTextMessage( {}, _( "Are you sure you want to resolve the battle in the quick combat mode?" ), Dialog::YES | Dialog::NO ) != Dialog::YES ) { return false; } actions.emplace_back( Command::QUICK_COMBAT ); humanturn_redraw = true; humanturn_exit = true; return true; } void Battle::Interface::OpenAutoModeDialog( const Unit & unit, Actions & actions ) { Cursor::Get().SetThemes( Cursor::POINTER ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int autoCombatButtonICN = isEvilInterface ? ICN::BUTTON_AUTO_COMBAT_EVIL : ICN::BUTTON_AUTO_COMBAT_GOOD; const int quickCombatButtonICN = isEvilInterface ? ICN::BUTTON_QUICK_COMBAT_EVIL : ICN::BUTTON_QUICK_COMBAT_GOOD; const int cancelButtonICN = isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD; const fheroes2::Sprite & quickCombatButtonReleased = fheroes2::AGG::GetICN( quickCombatButtonICN, 0 ); const fheroes2::Sprite & autoCombatButtonReleased = fheroes2::AGG::GetICN( autoCombatButtonICN, 0 ); const fheroes2::Sprite & cancelButtonReleased = fheroes2::AGG::GetICN( cancelButtonICN, 0 ); const int32_t autoButtonsXOffset = 20; const int32_t autoButtonsYOffset = 15; const int32_t titleYOffset = 16; const int32_t buttonSeparation = 37; const fheroes2::Text title( _( "Automatic Combat Modes" ), { fheroes2::FontSize::NORMAL, fheroes2::FontColor::YELLOW } ); const int32_t backgroundWidth = autoButtonsXOffset * 2 + quickCombatButtonReleased.width() + buttonSeparation + autoCombatButtonReleased.width(); const int32_t backgroundHeight = titleYOffset + title.height( backgroundWidth ) + quickCombatButtonReleased.height() + cancelButtonReleased.height() + autoButtonsYOffset + 28; fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( backgroundWidth, backgroundHeight, true, display ); fheroes2::Button buttonAutoCombat; fheroes2::Button buttonQuickCombat; fheroes2::Button buttonCancel; background.renderButton( buttonAutoCombat, isEvilInterface ? ICN::BUTTON_AUTO_COMBAT_EVIL : ICN::BUTTON_AUTO_COMBAT_GOOD, 0, 1, { autoButtonsXOffset, 0 }, fheroes2::StandardWindow::Padding::CENTER_LEFT ); background.renderButton( buttonQuickCombat, isEvilInterface ? ICN::BUTTON_QUICK_COMBAT_EVIL : ICN::BUTTON_QUICK_COMBAT_GOOD, 0, 1, { autoButtonsXOffset, 0 }, fheroes2::StandardWindow::Padding::CENTER_RIGHT ); background.renderButton( buttonCancel, isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); const fheroes2::Rect roiArea = background.activeArea(); title.draw( roiArea.x, roiArea.y + titleYOffset, backgroundWidth, display ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonAutoCombat.drawOnState( le.isMouseLeftButtonPressedInArea( buttonAutoCombat.area() ) ); buttonQuickCombat.drawOnState( le.isMouseLeftButtonPressedInArea( buttonQuickCombat.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return; } if ( ( le.MouseClickLeft( buttonAutoCombat.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_TOGGLE_AUTO_COMBAT ) ) && EventStartAutoCombat( unit, actions ) ) { return; } if ( ( le.MouseClickLeft( buttonQuickCombat.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_QUICK_COMBAT ) ) && EventQuickCombat( actions ) ) { return; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonAutoCombat.area() ) ) { std::string msg = _( "The computer continues the combat for you." ); msg += "\n\n"; msg += _( "autoCombat|This can be interrupted at any moment by pressing the Auto Combat hotkey or the default Cancel key, or by performing a left or right click anywhere on the game screen." ); fheroes2::showStandardTextMessage( _( "Auto Combat" ), msg, Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonQuickCombat.area() ) ) { std::string msg = _( "The combat is resolved from the current state." ); msg += "\n\n"; msg += _( "quickCombat|This cannot be undone." ); fheroes2::showStandardTextMessage( _( "Quick Combat" ), msg, Dialog::ZERO ); } } } void Battle::Interface::MousePressRightBoardAction( const Cell & cell ) const { const auto getUnit = [this, &cell]() -> const Unit * { if ( const Unit * unit = cell.GetUnit(); unit != nullptr ) { return unit; } if ( const Unit * unit = arena.getLastResurrectableUnitFromGraveyard( cell.GetIndex() ); unit != nullptr ) { return unit; } if ( const Unit * unit = arena.getLastUnitFromGraveyard( cell.GetIndex() ); unit != nullptr ) { return unit; } return nullptr; }; if ( const Unit * unit = getUnit(); unit != nullptr ) { Dialog::ArmyInfo( *unit, Dialog::ZERO, unit->isReflect() ); } } void Battle::Interface::MouseLeftClickBoardAction( const int themes, const Cell & cell, const bool isConfirmed, Actions & actions ) { const auto fixupDestinationCell = []( const Unit & unit, const int32_t dst ) { // Only wide units may need this fixup if ( !unit.isWide() ) { return dst; } const Position pos = Position::GetReachable( unit, dst ); assert( pos.GetHead() != nullptr && pos.GetTail() != nullptr ); return pos.GetHead()->GetIndex(); }; const int32_t index = cell.GetIndex(); const Unit * unitOnCell = cell.GetUnit(); if ( _currentUnit ) { switch ( themes ) { case Cursor::WAR_FLY: case Cursor::WAR_MOVE: if ( !isConfirmed ) { break; } actions.emplace_back( Command::MOVE, _currentUnit->GetUID(), fixupDestinationCell( *_currentUnit, index ) ); humanturn_exit = true; break; case Cursor::SWORD_TOPLEFT: case Cursor::SWORD_TOPRIGHT: case Cursor::SWORD_RIGHT: case Cursor::SWORD_BOTTOMRIGHT: case Cursor::SWORD_BOTTOMLEFT: case Cursor::SWORD_LEFT: { if ( !isConfirmed ) { break; } const int dir = GetDirectionFromCursorSword( themes ); if ( unitOnCell && Board::isValidDirection( index, dir ) ) { const int32_t move = fixupDestinationCell( *_currentUnit, Board::GetIndexDirection( index, dir ) ); actions.emplace_back( Command::ATTACK, _currentUnit->GetUID(), unitOnCell->GetUID(), ( _currentUnit->GetHeadIndex() == move ? -1 : move ), index, Board::GetReflectDirection( dir ) ); humanturn_exit = true; } break; } case Cursor::WAR_BROKENARROW: case Cursor::WAR_ARROW: { if ( !isConfirmed ) { break; } if ( unitOnCell ) { actions.emplace_back( Command::ATTACK, _currentUnit->GetUID(), unitOnCell->GetUID(), -1, index, 0 ); humanturn_exit = true; } break; } case Cursor::WAR_INFO: { if ( unitOnCell ) { Dialog::ArmyInfo( *unitOnCell, Dialog::BUTTONS, unitOnCell->isReflect() ); humanturn_redraw = true; } break; } default: break; } } } void Battle::Interface::WaitForAllActionDelays() { LocalEvent & le = LocalEvent::Get(); // The array of possible delays of previous battlefield actions. const std::vector unitDelays{ Game::DelayType::BATTLE_FRAME_DELAY, Game::DelayType::BATTLE_MISSILE_DELAY, Game::DelayType::BATTLE_SPELL_DELAY, Game::DelayType::BATTLE_DISRUPTING_DELAY, Game::DelayType::BATTLE_CATAPULT_CLOUD_DELAY, Game::DelayType::BATTLE_BRIDGE_DELAY, Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY }; // Wait for the delay after previous render and only after it render a new frame and proceed to the rest of this function. while ( le.HandleEvents( Game::isDelayNeeded( unitDelays ) ) ) { CheckGlobalEvents( le ); if ( Game::hasEveryDelayPassed( unitDelays ) ) { break; } } } void Battle::Interface::AnimateUnitWithDelay( Unit & unit, const bool skipLastFrameRender /* = false */ ) { if ( unit.isFinishAnimFrame() && unit.animation.animationLength() != 1 ) { // If it is the last frame in the animation sequence with more than one frame or if we have no frames. return; } LocalEvent & le = LocalEvent::Get(); // In the loop below we wait for the delay and then display the next frame. while ( le.HandleEvents( Game::isDelayNeeded( { Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY } ) ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY ) ) { Redraw(); if ( unit.isFinishAnimFrame() ) { // We have reached the end of animation and rendered the last frame. break; } unit.IncreaseAnimFrame(); if ( skipLastFrameRender && unit.isFinishAnimFrame() ) { // We have reached the last animation frame and do not render it. break; } } } } void Battle::Interface::AnimateOpponents( OpponentSprite * hero ) { if ( hero == nullptr ) { return; } // Render the first animation frame. We do it here not to skip small animations with duration for 1 frame. // For such (one frame) animations we are already ad the end of animation and `isFinishFrame()` always will return true. Redraw(); LocalEvent & le = LocalEvent::Get(); // We need to wait this delay before rendering the first frame of hero animation. Game::AnimateResetDelay( Game::DelayType::BATTLE_OPPONENTS_DELAY ); // 'BATTLE_OPPONENTS_DELAY' is different than 'BATTLE_IDLE_DELAY', so we handle the idle animation separately in this loop. while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_OPPONENTS_DELAY, Game::BATTLE_IDLE_DELAY } ) ) ) { // Animate the idling units. if ( IdleTroopsAnimation() ) { Redraw(); } if ( Game::validateAnimationDelay( Game::BATTLE_OPPONENTS_DELAY ) ) { if ( hero->isFinishFrame() ) { // We have reached the end of animation. break; } hero->IncreaseAnimFrame(); // Render the next frame and then wait a delay before checking if it is the last frame in the animation. Redraw(); } } } void Battle::Interface::RedrawTroopDefaultDelay( Unit & unit ) { if ( unit.isFinishAnimFrame() ) { // Nothing to animate. return; } LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_FRAME_DELAY } ) ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_FRAME_DELAY ) ) { Redraw(); if ( unit.isFinishAnimFrame() ) { // We have reached the end of animation. break; } unit.IncreaseAnimFrame(); } } } void Battle::Interface::RedrawActionSkipStatus( const Unit & unit ) { std::string msg = _n( "The %{name} skips their turn.", "The %{name} skip their turn.", unit.GetCount() ); StringReplaceWithLowercase( msg, "%{name}", unit.GetName() ); setStatus( msg, true ); } void Battle::Interface::RedrawMissileAnimation( const fheroes2::Point & startPos, const fheroes2::Point & endPos, const double angle, const uint32_t monsterID ) { LocalEvent & le = LocalEvent::Get(); const bool reverse = startPos.x > endPos.x; const bool isMage = ( monsterID == Monster::MAGE || monsterID == Monster::ARCHMAGE ); fheroes2::Sprite missile; fheroes2::Point endPosShift{ 0, 0 }; // Mage is channeling the bolt; doesn't have missile sprite if ( isMage ) { fheroes2::delayforMs( Game::ApplyBattleSpeed( 115 ) ); } else { missile = fheroes2::AGG::GetICN( static_cast( Monster::GetMissileICN( monsterID ) ), static_cast( Bin_Info::GetMonsterInfo( monsterID ).getProjectileID( angle ) ) ); // The projectile has to hit the target but not go through it so its end position is shifted in the direction to the shooter. endPosShift.x = reverse ? ( missile.width() / 2 ) : -( missile.width() / 2 ); endPosShift.y = ( startPos.y > endPos.y ) ? ( missile.height() / 2 ) : -( missile.height() / 2 ); } // Lich/Power lich has projectile speed of 25 const std::vector points = GetEuclideanLine( startPos, endPos + endPosShift, isMage ? 50 : std::max( missile.width(), 25 ) ); std::vector::const_iterator pnt = points.begin(); // For most shooting creatures we do not render the first missile position to better imitate start position change depending on shooting angle. if ( !isMage && ( monsterID != Monster::TROLL ) && ( monsterID != Monster::WAR_TROLL ) ) { ++pnt; } // Shooter projectile rendering offset uses 'x' and 'y' from sprite data. const fheroes2::Point missileOffset( reverse ? ( -missile.width() - missile.x() ) : missile.x(), ( angle > 0 ) ? ( -missile.height() - missile.y() ) : missile.y() ); // Wait for previously set and not passed delays before rendering a new frame. WaitForAllActionDelays(); // convert the following code into a function/event service while ( le.HandleEvents( false ) && pnt != points.end() ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_MISSILE_DELAY ) ) { RedrawPartialStart(); if ( isMage ) { fheroes2::DrawLine( _mainSurface, { startPos.x, startPos.y - 2 }, { pnt->x, pnt->y - 2 }, 0x77 ); fheroes2::DrawLine( _mainSurface, { startPos.x, startPos.y - 1 }, { pnt->x, pnt->y - 1 }, 0xB5 ); fheroes2::DrawLine( _mainSurface, startPos, *pnt, 0xBC ); fheroes2::DrawLine( _mainSurface, { startPos.x, startPos.y + 1 }, { pnt->x, pnt->y + 1 }, 0xB5 ); fheroes2::DrawLine( _mainSurface, { startPos.x, startPos.y + 2 }, { pnt->x, pnt->y + 2 }, 0x77 ); } else { // Coordinates in 'pnt' corresponds to the front side of the projectile (arrowhead). fheroes2::Blit( missile, _mainSurface, pnt->x + missileOffset.x, pnt->y + missileOffset.y, reverse ); } RedrawPartialFinish(); ++pnt; } } } void Battle::Interface::RedrawActionNewTurn() const { if ( listlog == nullptr ) { return; } std::string msg = _( "Turn %{turn}" ); StringReplace( msg, "%{turn}", arena.GetTurnNumber() ); listlog->AddMessage( std::move( msg ) ); } void Battle::Interface::RedrawActionAttackPart1( Unit & attacker, const Unit & defender, const TargetsInfo & targets ) { Cursor::Get().SetThemes( Cursor::WAR_POINTER ); _currentUnit = nullptr; _movingUnit = &attacker; _movingPos = attacker.GetRectPosition().getPosition(); // Unit 'Position' is position of the tile he's standing at const fheroes2::Rect & pos1 = attacker.GetRectPosition(); const fheroes2::Rect & pos2 = defender.GetRectPosition(); const bool archer = attacker.isArchers() && !Unit::isHandFighting( attacker, defender ); const bool isDoubleCell = attacker.isDoubleCellAttack() && 2 == targets.size(); // redraw luck animation if ( attacker.Modes( LUCK_GOOD | LUCK_BAD ) ) { RedrawActionLuck( attacker ); } AudioManager::PlaySound( attacker.M82Attk( defender ) ); // long distance attack animation if ( archer ) { // Reset the delay to wait till the next frame if is not already waiting. if ( !Game::isDelayNeeded( { Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY } ) ) { Game::AnimateResetDelay( Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY ); } const fheroes2::Sprite & attackerSprite = fheroes2::AGG::GetICN( attacker.GetMonsterSprite(), attacker.GetFrame() ); const fheroes2::Point attackerPos = GetTroopPosition( attacker, attackerSprite ); // For shooter position we need bottom center position of rear tile // Use cell coordinates for X because sprite width is very inconsistent (e.g. Halfling) const int rearCenterX = ( attacker.isWide() && attacker.isReflect() ) ? pos1.width * 3 / 4 : Cell::widthPx / 2; const fheroes2::Point shooterPos( pos1.x + rearCenterX, attackerPos.y - attackerSprite.y() ); // Use the front one to calculate the angle, then overwrite fheroes2::Point offset = attacker.GetStartMissileOffset( Monster_Info::FRONT ); const fheroes2::Point targetPos = defender.GetCenterPoint(); double angle = GetAngle( fheroes2::Point( shooterPos.x + offset.x, shooterPos.y + offset.y ), targetPos ); // This check is made only for situations when a target stands on the same row as shooter. if ( attacker.GetHeadIndex() / Board::widthInCells == defender.GetHeadIndex() / Board::widthInCells ) { angle = 0; } // Angles are used in Heroes2 as 90 (TOP) -> 0 (FRONT) -> -90 (BOT) degrees const int direction = angle >= 25.0 ? Monster_Info::TOP : ( angle <= -25.0 ) ? Monster_Info::BOTTOM : Monster_Info::FRONT; if ( direction != Monster_Info::FRONT ) { offset = attacker.GetStartMissileOffset( direction ); } // redraw archer attack animation if ( attacker.SwitchAnimation( Monster_Info::RANG_TOP + direction * 2 ) ) { // Set the delay between shooting animation frames. Game::setCustomUnitMovementDelay( Game::ApplyBattleSpeed( attacker.animation.getShootingSpeed() ) / attacker.animation.animationLength() ); // We do not render the last frame of shooting animation as all frames besides this contains the projectile. // The last frame will be rendered in RedrawMissileAnimation() function with the render of projectile. AnimateUnitWithDelay( attacker, true ); } const fheroes2::Point missileStart( shooterPos.x + ( attacker.isReflect() ? -offset.x : offset.x ), shooterPos.y + offset.y ); // draw missile animation RedrawMissileAnimation( missileStart, targetPos, angle, attacker.GetID() ); } else { int attackAnim = isDoubleCell ? Monster_Info::RANG_FRONT : Monster_Info::MELEE_FRONT; if ( pos2.y < pos1.y ) { attackAnim -= 2; } else if ( pos2.y > pos1.y ) { attackAnim += 2; } // redraw melee attack animation if ( attacker.SwitchAnimation( attackAnim ) ) { // Reset the delay to wait till the next frame. Game::AnimateResetDelay( Game::DelayType::BATTLE_FRAME_DELAY ); RedrawTroopDefaultDelay( attacker ); } } } void Battle::Interface::RedrawActionAttackPart2( Unit & attacker, const Unit & defender, const TargetsInfo & targets, const uint32_t resurrects ) { // Reset the delay to wait till the next frame. if ( !Game::isDelayNeeded( { Game::DelayType::BATTLE_FRAME_DELAY } ) ) { Game::AnimateResetDelay( Game::DelayType::BATTLE_FRAME_DELAY ); } // post attack animation int attackStart = attacker.animation.getCurrentState(); if ( attackStart >= Monster_Info::MELEE_TOP && attackStart <= Monster_Info::RANG_BOT ) { ++attackStart; attacker.SwitchAnimation( attackStart ); } // targets damage animation RedrawActionWincesKills( targets, &attacker, &defender ); RedrawTroopDefaultDelay( attacker ); attacker.SwitchAnimation( Monster_Info::STATIC ); const bool isMirror = targets.size() == 1 && targets.front().defender->isModes( CAP_MIRRORIMAGE ); // draw status for first defender if ( !isMirror && !targets.empty() ) { std::string msg( _n( "%{attacker} does %{damage} damage.", "%{attacker} do %{damage} damage.", attacker.GetCount() ) ); StringReplaceWithLowercase( msg, "%{attacker}", attacker.GetName() ); if ( 1 < targets.size() ) { uint32_t killed = 0; uint32_t damage = 0; for ( const TargetInfo & target : targets ) { if ( !target.defender->isModes( CAP_MIRRORIMAGE ) ) { killed += target.killed; damage += target.damage; } } StringReplace( msg, "%{damage}", damage ); if ( killed ) { msg.append( " " ); msg.append( _n( "1 creature perishes.", "%{count} creatures perish.", killed ) ); StringReplace( msg, "%{count}", killed ); } } else { const TargetInfo & target = targets.front(); StringReplace( msg, "%{damage}", target.damage ); if ( target.killed ) { msg.append( " " ); msg.append( _n( "1 %{defender} perishes.", "%{count} %{defender} perish.", target.killed ) ); StringReplace( msg, "%{count}", target.killed ); StringReplaceWithLowercase( msg, "%{defender}", target.defender->GetPluralName( target.killed ) ); } } setStatus( msg, true ); if ( resurrects != 0 ) { const auto updateStatusBar = [this]( std::string & localMsg, const uint32_t localRes, const char * localUnit ) { StringReplace( localMsg, "%{count}", localRes ); StringReplaceWithLowercase( localMsg, "%{unit}", localUnit ); setStatus( localMsg, true ); }; if ( attacker.isAbilityPresent( fheroes2::MonsterAbilityType::SOUL_EATER ) ) { msg = _n( "1 soul is incorporated.", "%{count} souls are incorporated.", resurrects ); updateStatusBar( msg, resurrects, attacker.GetPluralName( resurrects ) ); } else if ( attacker.isAbilityPresent( fheroes2::MonsterAbilityType::HP_DRAIN ) ) { msg = _n( "1 %{unit} is revived.", "%{count} %{unit} are revived.", resurrects ); updateStatusBar( msg, resurrects, attacker.GetPluralName( resurrects ) ); } } } _movingUnit = nullptr; } void Battle::Interface::RedrawActionWincesKills( const TargetsInfo & targets, Unit * attacker /* = nullptr */, const Unit * defender /* = nullptr */ ) { // Reset the delay to wait till the next frame. if ( !Game::isDelayNeeded( { Game::DelayType::BATTLE_FRAME_DELAY } ) ) { Game::AnimateResetDelay( Game::DelayType::BATTLE_FRAME_DELAY ); } LocalEvent & le = LocalEvent::Get(); // Number of targets to be animated with a wince or kill animation. ptrdiff_t animatingTargets = 0; int32_t deathColor = Color::UNUSED; std::vector mirrorImages; std::set resistantTarget; std::set unitSounds; // If this was a Lich attack, we should render an explosion cloud over the target unit immediately after the projectile hits the target, // along with the unit kill/wince animation. const bool drawLichCloud = ( attacker != nullptr ) && ( defender != nullptr ) && attacker->isArchers() && !Unit::isHandFighting( *attacker, *defender ) && attacker->isAbilityPresent( fheroes2::MonsterAbilityType::AREA_SHOT ); // Play sound only if it is not already playing. const auto playSoundIfNotPlaying = [&unitSounds]( const int unitSound ) { const auto [dummy, isUnique] = unitSounds.insert( unitSound ); if ( isUnique ) { AudioManager::PlaySound( unitSound ); } }; for ( const Battle::TargetInfo & target : targets ) { Unit * unit = target.defender; if ( unit == nullptr ) { continue; } if ( unit->isModes( CAP_MIRRORIMAGE ) ) { mirrorImages.push_back( unit ); } // kill animation if ( !unit->isValid() ) { // destroy linked mirror if ( unit->isModes( CAP_MIRROROWNER ) ) { mirrorImages.push_back( unit->GetMirror() ); } unit->SwitchAnimation( Monster_Info::KILL ); playSoundIfNotPlaying( unit->M82Kill() ); ++animatingTargets; deathColor = unit->GetArmyColor(); } else if ( target.damage ) { // wince animation if ( drawLichCloud ) { // The Lich cloud causes units to freeze for some time in the maximum wince state. // So we will divide the wince animation. First part: the creature stands for a couple of frames before wincing. unit->SwitchAnimation( Monster_Info::STAND_STILL ); } else { unit->SwitchAnimation( Monster_Info::WNCE ); playSoundIfNotPlaying( unit->M82Wnce() ); } ++animatingTargets; } else { // have immunity resistantTarget.insert( target.defender ); playSoundIfNotPlaying( M82::RSBRYFZL ); } } SetHeroAnimationReactionToTroopDeath( deathColor ); uint32_t lichCloudFrame = 0; const uint32_t lichCloudMaxFrame = fheroes2::AGG::GetICNCount( ICN::LICHCLOD ); // Wince animation under the Lich cloud, second part: the frame number after which the target animation will be switched to 'WNCE_UP'. const uint32_t wnceUpStartFrame = 1; // Wince animation under the Lich cloud, third part: the frame number after which the target animation will be switched to 'WNCE_DOWN'. const uint32_t wnceDownStartFrame = lichCloudMaxFrame - 3; if ( drawLichCloud ) { // Lich cloud sound. AudioManager::PlaySound( attacker->M82Expl() ); } while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_FRAME_DELAY } ) ) ) { CheckGlobalEvents( le ); if ( !Game::validateAnimationDelay( Game::BATTLE_FRAME_DELAY ) ) { continue; } RedrawPartialStart(); // Render a Lich cloud above the target unit if it is a Lich attack and if the cloud animation is not already finished. if ( drawLichCloud && lichCloudFrame < lichCloudMaxFrame ) { const fheroes2::Sprite & spellSprite = fheroes2::AGG::GetICN( ICN::LICHCLOD, lichCloudFrame ); const fheroes2::Point & pos = CalculateSpellPosition( *defender, ICN::LICHCLOD, spellSprite ); fheroes2::Blit( spellSprite, _mainSurface, pos.x, pos.y, false ); ++lichCloudFrame; } RedrawPartialFinish(); // Make a check if all animation sequences are over (after rendering the last frame) to break this render loop. const ptrdiff_t finishedAnimationCount = std::count_if( targets.begin(), targets.end(), [&resistantTarget]( const TargetInfo & info ) { if ( info.defender == nullptr ) { return false; } if ( resistantTarget.count( info.defender ) > 0 ) { return false; } const int animationState = info.defender->GetAnimationState(); if ( animationState == Monster_Info::WNCE || animationState == Monster_Info::WNCE_UP || animationState == Monster_Info::WNCE_DOWN || animationState == Monster_Info::STAND_STILL ) { return false; } if ( animationState != Monster_Info::KILL ) { return true; } return TargetInfo::isFinishAnimFrame( info ); } ); // There should not be more finished animations than when we started. assert( finishedAnimationCount <= animatingTargets ); // There should not be more Lich cloud animation frames than in the corresponding ICN. assert( lichCloudFrame <= lichCloudMaxFrame ); // IMPORTANT: The game engine can change STATIC animation to IDLE, especially for Ghosts and Zombies, // so we need also to check for IDLE where we check for STATIC. if ( ( animatingTargets == finishedAnimationCount ) && ( !drawLichCloud || ( lichCloudFrame == lichCloudMaxFrame ) ) && ( ( attacker == nullptr ) || ( attacker->animation.getCurrentState() == Monster_Info::STATIC ) || ( attacker->animation.getCurrentState() == Monster_Info::IDLE ) ) ) { // All unit animation frames are rendered and if it was a Lich attack then also its cloud frames are rendered too. break; } // Progress all units animations. if ( attacker != nullptr ) { if ( attacker->isFinishAnimFrame() ) { attacker->SwitchAnimation( Monster_Info::STATIC ); } else { attacker->IncreaseAnimFrame(); } } for ( const Battle::TargetInfo & target : targets ) { if ( target.defender ) { if ( target.defender->isFinishAnimFrame() && ( target.defender->GetAnimationState() == Monster_Info::WNCE || target.defender->GetAnimationState() == Monster_Info::WNCE_DOWN ) ) { target.defender->SwitchAnimation( Monster_Info::STATIC ); } else if ( drawLichCloud && lichCloudFrame == wnceUpStartFrame && ( target.defender->GetAnimationState() == Monster_Info::STAND_STILL ) ) { target.defender->SwitchAnimation( Monster_Info::WNCE_UP ); playSoundIfNotPlaying( target.defender->M82Wnce() ); } else if ( drawLichCloud && lichCloudFrame == wnceDownStartFrame && ( target.defender->GetAnimationState() == Monster_Info::WNCE_UP ) ) { target.defender->SwitchAnimation( Monster_Info::WNCE_DOWN ); } else { target.defender->IncreaseAnimFrame(); } } } } // Fade away animation for destroyed mirror images if ( !mirrorImages.empty() ) { RedrawActionRemoveMirrorImage( mirrorImages ); } } void Battle::Interface::SetHeroAnimationReactionToTroopDeath( const int32_t deathColor ) const { if ( deathColor == Color::UNUSED ) { return; } const bool attackersTurn = ( deathColor == arena.GetArmy2Color() ); OpponentSprite * attackingHero = attackersTurn ? _opponent1.get() : _opponent2.get(); OpponentSprite * defendingHero = attackersTurn ? _opponent2.get() : _opponent1.get(); // 60% of joyful animation if ( attackingHero && Rand::Get( 1, 5 ) < 4 ) { attackingHero->SetAnimation( OP_JOY ); } // 80% of sorrow animation otherwise else if ( defendingHero && Rand::Get( 1, 5 ) < 5 ) { defendingHero->SetAnimation( OP_SORROW ); } } void Battle::Interface::RedrawActionMove( Unit & unit, const Indexes & path ) { // If the path is empty there is no movement and so nothing to render. if ( path.empty() ) { return; } // Reset the delay to wait till the next frame if is not already waiting. if ( !Game::isDelayNeeded( { Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY } ) ) { Game::AnimateResetDelay( Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY ); } Cursor::Get().SetThemes( Cursor::WAR_POINTER ); Indexes::const_iterator dst = path.begin(); Bridge * bridge = Arena::GetBridge(); // Get the time to animate movement for one cell. uint32_t frameDelay = Game::ApplyBattleSpeed( unit.animation.getMoveSpeed() ); if ( unit.Modes( SP_HASTE ) && frameDelay > 1 ) { frameDelay = frameDelay * 65 / 100; // by 35% faster } else if ( unit.Modes( SP_SLOW ) ) { frameDelay = frameDelay * 150 / 100; // by 50% slower } // Set the delay between movement animation frames. This delay will be used for all types of movement animations. unit.SwitchAnimation( Monster_Info::MOVING ); Game::setCustomUnitMovementDelay( frameDelay / unit.animation.animationLength() ); std::string msg = _( "Moved %{monster}: from [%{src}] to [%{dst}]." ); StringReplaceWithLowercase( msg, "%{monster}", unit.GetName() ); StringReplace( msg, "%{src}", std::to_string( ( unit.GetHeadIndex() / Board::widthInCells ) + 1 ) + ", " + std::to_string( ( unit.GetHeadIndex() % Board::widthInCells ) + 1 ) ); assert( _movingUnit == nullptr && _flyingUnit == nullptr ); _currentUnit = nullptr; _movingUnit = &unit; // If it is a flying creature that acts like walking one when it is under the Slow spell. const bool canFly = unit.isAbilityPresent( fheroes2::MonsterAbilityType::FLYING ); // If it is a wide creature (cache this boolean to use in the loop). const bool isWide = unit.isWide(); const Indexes::const_iterator pathEnd = path.end(); const Indexes::const_iterator finalStep = pathEnd - 1; const bool isOneStepPath = [&unit, &path]() { if ( path.size() == 1 ) { return true; } if ( !unit.isWide() ) { return false; } // If wide unit performs 3 movements and the first movement is a turn back, then it's // path consists of only one "real" movement, because... if ( path.size() == 3 && path[0] == unit.GetTailIndex() ) { // ... its last movement should be a return to the normal position. assert( Board::GetDirection( path[1], path[2] ) == ( unit.isReflect() ? LEFT : RIGHT ) ); return true; } return false; }(); // TODO: make an analytic check with checks for wide creatures back step: is one step left before/after the bridge action. // Slowed flying creature has to fly off. if ( canFly ) { // If a flying creature has to cross the bridge during its path we have to open it before the creature flies up. // Otherwise it will freeze during the movement, waiting for the bridge to open. So we have to go the whole path // to analyze if the bridge needs to open for this creature. if ( bridge ) { const Position startPosition = unit.GetPosition(); while ( dst != pathEnd ) { if ( bridge->NeedDown( unit, *dst ) ) { // Restore the initial creature position before rendering the whole battlefield with the bridge animation. unit.SetPosition( startPosition ); bridge->ActionDown(); break; } // Fix for wide flyers - go the whole path with reflections to check the bridge. if ( isWide && ( unit.GetTailIndex() == *dst ) ) { unit.SetReflection( !unit.isReflect() ); } unit.SetPosition( *dst ); ++dst; } // If there was no bridge on the path then restore the initial creature position. if ( dst == pathEnd ) { unit.SetPosition( startPosition ); } // Restore the initial path pointer state. dst = path.begin(); } // The destination of fly off is same as the current creature position. _movingPos = unit.GetRectPosition().getPosition(); const bool isFromRightArmy = unit.isReflect(); const bool isFlyToRight = ( _movingPos.x < Board::GetCell( *dst )->GetPos().x ); // Reflect the creature if it has to fly back. unit.SetReflection( !isFlyToRight ); // For creatures, that has no 'FLY_UP' animation, like Ghosts, we check if the animation was correctly set. if ( unit.SwitchAnimation( Monster_Info::FLY_UP ) ) { AudioManager::PlaySound( unit.M82Tkof() ); AnimateUnitWithDelay( unit ); } // If a wide flyer returns back it should skip one path position (its head becomes its tail - it is already one move). if ( isWide && ( isFlyToRight == isFromRightArmy ) ) { ++dst; } // Switch animation to MOVING before going through the path. unit.SwitchAnimation( Monster_Info::MOVING ); } else { // Every ground unit should start its movement from the special 'MOVE_START' animation // or if it moves only for one cell its animation must be 'MOVE_QUICK'. So a check for 1 cell path is made. if ( isOneStepPath ) { unit.SwitchAnimation( Monster_Info::MOVE_QUICK ); } else { unit.SwitchAnimation( Monster_Info::MOVE_START ); } } // For Battle speed 9 and 10 we play one sound at a time without any simultaneous playbacks // because on these speeds the unit will end its movement before the sound is finished. const bool playSoundBySound = Settings::Get().BattleSpeed() > 8; int soundStatus = -1; const int walkSoundId = unit.M82Move(); while ( dst != pathEnd ) { // Check if a wide unit changes its horizontal direction. if ( isWide && unit.GetTailIndex() == *dst ) { // We must not reflect the flyers at the and of the path (just before the landing). if ( !canFly || ( dst != finalStep ) ) { unit.SetReflection( !unit.isReflect() ); } // After changing the direction go to the next step in the path. ++dst; continue; } const Cell * cell = Board::GetCell( *dst ); _movingPos = cell->GetPos().getPosition(); if ( !isWide ) { // Check for change the horizontal direction. Only for non-wide units, the wide units use their own algorithm. unit.UpdateDirection( cell->GetPos() ); } if ( bridge && bridge->NeedDown( unit, *dst ) ) { _movingUnit = nullptr; unit.SwitchAnimation( Monster_Info::STAND_STILL ); bridge->ActionDown(); _movingUnit = &unit; if ( dst == finalStep ) { // There is only one cell left to move after standing. unit.SwitchAnimation( Monster_Info::MOVE_QUICK ); } else { // If the path has more than one step after the bridge action then begin the movement. unit.SwitchAnimation( Monster_Info::MOVE_START ); } } // If a wide flyer is flying to the right its visual horizontal destination should be shifted to the left by one cell. if ( canFly && isWide && !unit.isReflect() ) { _movingPos.x -= Cell::widthPx; } // TODO: adjust sounds calls and synchronize them with frames. Take into account that some sounds (like for Cavalry) consists of a sequence of steps. if ( playSoundBySound ) { // Start unit move sound only if it is not already playing. if ( soundStatus < 0 || !Mixer::isPlaying( soundStatus ) ) { soundStatus = AudioManager::PlaySound( walkSoundId ); } } else { AudioManager::PlaySound( walkSoundId ); } AnimateUnitWithDelay( unit ); unit.SetPosition( *dst ); ++dst; // Do a post-move check for the bridge action and set the animation the movement to the next cell in the path. if ( canFly ) { // The animation for the next step in the path of slowed flying creatures is always "MOVING". unit.SwitchAnimation( Monster_Info::MOVING ); } else { // Check for possible bridge close action, after walking unit's end of movement to the next cell. // This check should exclude the flying creature because it can't 'hang' here to wait // for bridge to close. For this creature, the bridge should close after it lands. if ( bridge && bridge->AllowUp() ) { _movingUnit = nullptr; unit.SwitchAnimation( Monster_Info::STAND_STILL ); bridge->ActionUp(); _movingUnit = &unit; if ( dst == finalStep ) { // There is only one cell left to move after standing. unit.SwitchAnimation( Monster_Info::MOVE_QUICK ); } else { // If the path has more than one step after the bridge action then begin the movement. unit.SwitchAnimation( Monster_Info::MOVE_START ); } } else if ( dst == finalStep ) { // There is only one cell left to move. unit.SwitchAnimation( Monster_Info::MOVE_END ); } else { unit.SwitchAnimation( Monster_Info::MOVING ); } } } // Slowed flying creature has to land. if ( canFly ) { // IMPORTANT: do not combine into vector animations with the STATIC at the end: the game could randomly switch it to IDLE this way. unit.SwitchAnimation( { Monster_Info::FLY_LAND, Monster_Info::STAND_STILL } ); AudioManager::PlaySound( unit.M82Land() ); AnimateUnitWithDelay( unit ); // Close the bridge only after the creature lands. if ( bridge && bridge->AllowUp() ) { bridge->ActionUp(); } } _movingUnit = nullptr; unit.SwitchAnimation( Monster_Info::STATIC ); StringReplace( msg, "%{dst}", std::to_string( ( unit.GetHeadIndex() / Board::widthInCells ) + 1 ) + ", " + std::to_string( ( unit.GetHeadIndex() % Board::widthInCells ) + 1 ) ); status.setMessage( msg, true ); assert( _currentUnit == nullptr && _movingUnit == nullptr && _flyingUnit == nullptr ); } void Battle::Interface::RedrawActionFly( Unit & unit, const Position & pos ) { const int32_t destIndex = pos.GetHead()->GetIndex(); const int32_t destTailIndex = unit.isWide() ? pos.GetTail()->GetIndex() : -1; // check if we're already there if ( unit.GetPosition().contains( destIndex ) ) { return; } // Reset the delay to wait till the next frame if is not already waiting. if ( !Game::isDelayNeeded( { Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY } ) ) { Game::AnimateResetDelay( Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY ); } Cursor::Get().SetThemes( Cursor::WAR_POINTER ); const fheroes2::Point destPos = unit.GetRectPosition().getPosition(); fheroes2::Point targetPos = Board::GetCell( destIndex )->GetPos().getPosition(); if ( unit.isWide() && targetPos.x > destPos.x ) { targetPos.x -= Cell::widthPx; // this is needed to avoid extra cell shifting upon landing when we move to right side } std::string msg = _( "Moved %{monster}: from [%{src}] to [%{dst}]." ); StringReplaceWithLowercase( msg, "%{monster}", unit.GetName() ); StringReplace( msg, "%{src}", std::to_string( ( unit.GetHeadIndex() / Board::widthInCells ) + 1 ) + ", " + std::to_string( ( unit.GetHeadIndex() % Board::widthInCells ) + 1 ) ); const uint32_t step = unit.animation.getFlightSpeed(); uint32_t frameDelay = Game::ApplyBattleSpeed( unit.animation.getMoveSpeed() ); if ( unit.Modes( SP_HASTE ) && frameDelay > 1 ) { frameDelay = frameDelay * 8 / 10; // 20% faster } else if ( unit.Modes( SP_SLOW ) ) { frameDelay = frameDelay * 12 / 10; // 20% slower } // Set the delay between movement animation frames. This delay will be used for all types of movement animations. unit.SwitchAnimation( Monster_Info::MOVING ); Game::setCustomUnitMovementDelay( frameDelay / unit.animation.animationLength() ); const std::vector points = GetEuclideanLine( destPos, targetPos, step ); std::vector::const_iterator currentPoint = points.begin(); Bridge * bridge = Arena::GetBridge(); // Lower the bridge if the unit needs to land on it if ( bridge && ( bridge->NeedDown( unit, destIndex ) || ( unit.isWide() && bridge->NeedDown( unit, destTailIndex ) ) ) ) { bridge->ActionDown(); } assert( _movingUnit == nullptr && _flyingUnit == nullptr ); // Jump up _currentUnit = nullptr; _movingUnit = &unit; _movingPos = currentPoint != points.end() ? *currentPoint : destPos; // For creatures, that has no 'FLY_UP' animation, like Ghosts, we check if the animation was correctly set. if ( unit.SwitchAnimation( Monster_Info::FLY_UP ) ) { AudioManager::PlaySound( unit.M82Tkof() ); AnimateUnitWithDelay( unit ); } _movingUnit = nullptr; _flyingUnit = &unit; _flyingPos = _movingPos; if ( currentPoint != points.end() ) { ++currentPoint; } // For Battle speeds 9 and 10 we play one sound at a time without any simultaneous playbacks // because on these speeds the unit will end its movement before the sound is finished. const bool playSoundBySound = Settings::Get().BattleSpeed() > 8; int soundStatus = -1; const int flySoundId = unit.M82Move(); unit.SwitchAnimation( Monster_Info::MOVING ); while ( currentPoint != points.end() ) { _movingPos = *currentPoint; if ( playSoundBySound ) { // Start unit move sound only if it is not already playing. if ( soundStatus < 0 || !Mixer::isPlaying( soundStatus ) ) { soundStatus = AudioManager::PlaySound( flySoundId ); } } else { AudioManager::PlaySound( flySoundId ); } unit.animation.restartAnimation(); AnimateUnitWithDelay( unit ); _flyingPos = _movingPos; ++currentPoint; } unit.SetPosition( destIndex ); // Landing _flyingUnit = nullptr; _movingUnit = &unit; _movingPos = targetPos; // IMPORTANT: do not combine into vector animations with the STATIC at the end: the game could randomly switch it to IDLE this way. unit.SwitchAnimation( { Monster_Info::FLY_LAND, Monster_Info::STAND_STILL } ); AudioManager::PlaySound( unit.M82Land() ); AnimateUnitWithDelay( unit ); unit.SwitchAnimation( Monster_Info::STATIC ); _movingUnit = nullptr; // Raise the bridge if possible after the unit has completed its movement if ( bridge && bridge->AllowUp() ) { bridge->ActionUp(); } StringReplace( msg, "%{dst}", std::to_string( ( unit.GetHeadIndex() / Board::widthInCells ) + 1 ) + ", " + std::to_string( ( unit.GetHeadIndex() % Board::widthInCells ) + 1 ) ); status.setMessage( msg, true ); assert( _currentUnit == nullptr && _movingUnit == nullptr && _flyingUnit == nullptr ); } void Battle::Interface::RedrawActionResistSpell( const Unit & target, const bool playSound ) { if ( playSound ) { AudioManager::PlaySound( M82::RSBRYFZL ); } std::string str( _n( "The %{name} resists the spell!", "The %{name} resist the spell!", target.GetCount() ) ); StringReplaceWithLowercase( str, "%{name}", target.GetName() ); setStatus( str, true ); } void Battle::Interface::RedrawActionSpellCastStatus( const Spell & spell, int32_t dst, const std::string & name, const TargetsInfo & targets ) { const Unit * target = !targets.empty() ? targets.front().defender : nullptr; std::string msg; if ( target && ( target->GetHeadIndex() == dst || ( target->isWide() && target->GetTailIndex() == dst ) ) ) { msg = _( "%{name} casts %{spell} on the %{troop}." ); StringReplaceWithLowercase( msg, "%{troop}", target->GetName() ); } else { msg = _( "%{name} casts %{spell}." ); } if ( !msg.empty() ) { StringReplace( msg, "%{name}", name ); StringReplace( msg, "%{spell}", spell.GetName() ); setStatus( msg, true ); } } void Battle::Interface::RedrawActionSpellCastPart1( const Spell & spell, int32_t dst, const HeroBase * caster, const TargetsInfo & targets ) { // Reset the idle animation delay timer to prevent the target unit from starting the idle animation. for ( const TargetInfo & spellTarget : targets ) { spellTarget.defender->checkIdleDelay(); } Unit * target = !targets.empty() ? targets.front().defender : nullptr; const bool isMassSpell = spell.isApplyWithoutFocusObject(); bool isCastDown = false; OpponentSprite * opponent = nullptr; // set spell cast animation if ( caster ) { const bool isLeftOpponent = caster->GetColor() == arena.GetArmy1Color(); opponent = isLeftOpponent ? _opponent1.get() : _opponent2.get(); if ( opponent != nullptr ) { if ( isMassSpell ) { opponent->SetAnimation( OP_CAST_MASS ); } else { // The cast down is applied below the 2rd battlefield row (count is started from 0) // and for the (rowNumber - 2) columns starting from the side of the hero. isCastDown = isLeftOpponent ? ( ( dst % 11 ) < dst / 11 - 2 ) : ( ( 10 - ( dst % 11 ) ) < dst / 11 - 2 ); opponent->SetAnimation( isCastDown ? OP_CAST_DOWN : OP_CAST_UP ); } AnimateOpponents( opponent ); } } // without object switch ( spell.GetID() ) { case Spell::FIREBALL: RedrawTargetsWithFrameAnimation( dst, targets, ICN::FIREBALL, M82::FromSpell( spell.GetID() ) ); break; case Spell::FIREBLAST: RedrawTargetsWithFrameAnimation( dst, targets, ICN::FIREBAL2, M82::FromSpell( spell.GetID() ) ); break; case Spell::METEORSHOWER: RedrawTargetsWithFrameAnimation( dst, targets, ICN::METEOR, M82::FromSpell( spell.GetID() ), 1 ); break; case Spell::COLDRING: RedrawActionColdRingSpell( dst, targets ); break; case Spell::MASSSHIELD: RedrawTargetsWithFrameAnimation( targets, ICN::SHIELD, M82::FromSpell( spell.GetID() ), false ); break; case Spell::MASSCURE: RedrawTargetsWithFrameAnimation( targets, ICN::MAGIC01, M82::FromSpell( spell.GetID() ), false ); break; case Spell::MASSHASTE: RedrawTargetsWithFrameAnimation( targets, ICN::HASTE, M82::FromSpell( spell.GetID() ), false ); break; case Spell::MASSSLOW: RedrawTargetsWithFrameAnimation( targets, ICN::MAGIC02, M82::FromSpell( spell.GetID() ), false ); break; case Spell::MASSBLESS: RedrawTargetsWithFrameAnimation( targets, ICN::BLESS, M82::FromSpell( spell.GetID() ), false ); break; case Spell::MASSCURSE: RedrawTargetsWithFrameAnimation( targets, ICN::CURSE, M82::FromSpell( spell.GetID() ), false ); break; case Spell::MASSDISPEL: RedrawTargetsWithFrameAnimation( targets, ICN::MAGIC07, M82::FromSpell( spell.GetID() ), false ); break; case Spell::DEATHRIPPLE: RedrawActionDeathWaveSpell( 7 ); break; case Spell::DEATHWAVE: RedrawActionDeathWaveSpell( 14 ); break; case Spell::HOLYWORD: RedrawActionHolyShoutSpell( 16 ); break; case Spell::HOLYSHOUT: RedrawActionHolyShoutSpell( 24 ); break; case Spell::ELEMENTALSTORM: RedrawActionElementalStormSpell( targets ); break; case Spell::ARMAGEDDON: RedrawActionArmageddonSpell(); // hit everything break; default: break; } // with object if ( target ) { if ( spell.isResurrect() ) RedrawActionResurrectSpell( *target, spell ); else switch ( spell.GetID() ) { // simple spell animation case Spell::BLESS: RedrawTroopWithFrameAnimation( *target, ICN::BLESS, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::BLIND: RedrawTroopWithFrameAnimation( *target, ICN::BLIND, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::CURE: RedrawTroopWithFrameAnimation( *target, ICN::MAGIC01, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::SLOW: RedrawTroopWithFrameAnimation( *target, ICN::MAGIC02, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::SHIELD: RedrawTroopWithFrameAnimation( *target, ICN::SHIELD, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::HASTE: RedrawTroopWithFrameAnimation( *target, ICN::HASTE, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::CURSE: RedrawTroopWithFrameAnimation( *target, ICN::CURSE, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::ANTIMAGIC: RedrawTroopWithFrameAnimation( *target, ICN::MAGIC06, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::DISPEL: RedrawTroopWithFrameAnimation( *target, ICN::MAGIC07, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::STONESKIN: RedrawTroopWithFrameAnimation( *target, ICN::STONSKIN, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::STEELSKIN: RedrawTroopWithFrameAnimation( *target, ICN::STELSKIN, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::PARALYZE: RedrawTroopWithFrameAnimation( *target, ICN::PARALYZE, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::HYPNOTIZE: RedrawTroopWithFrameAnimation( *target, ICN::HYPNOTIZ, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::DRAGONSLAYER: RedrawTroopWithFrameAnimation( *target, ICN::DRAGSLAY, M82::FromSpell( spell.GetID() ), NONE ); break; case Spell::BERSERKER: RedrawTroopWithFrameAnimation( *target, ICN::BERZERK, M82::FromSpell( spell.GetID() ), NONE ); break; // uniq spell animation case Spell::LIGHTNINGBOLT: RedrawActionLightningBoltSpell( *target ); break; case Spell::CHAINLIGHTNING: RedrawActionChainLightningSpell( targets ); break; case Spell::ARROW: RedrawActionArrowSpell( *target ); break; case Spell::COLDRAY: RedrawActionColdRaySpell( *target ); break; case Spell::DISRUPTINGRAY: RedrawActionDisruptingRaySpell( *target ); break; case Spell::BLOODLUST: RedrawActionBloodLustSpell( *target ); break; case Spell::PETRIFY: RedrawActionStoneSpell( *target ); break; default: break; } } if ( opponent != nullptr ) { if ( isMassSpell ) { opponent->SetAnimation( OP_CAST_MASS_RETURN ); } else { opponent->SetAnimation( isCastDown ? OP_CAST_DOWN_RETURN : OP_CAST_UP_RETURN ); } AnimateOpponents( opponent ); // Return to the static animation of hero. opponent->SetAnimation( OP_STATIC ); } } void Battle::Interface::RedrawActionSpellCastPart2( const Spell & spell, const TargetsInfo & targets ) { if ( spell.isDamage() ) { uint32_t killed = 0; uint32_t totalDamage = 0; uint32_t maximumDamage = 0; uint32_t damagedMonsters = 0; for ( const TargetInfo & target : targets ) { if ( !target.defender->isModes( CAP_MIRRORIMAGE ) ) { killed += target.killed; ++damagedMonsters; totalDamage += target.damage; if ( maximumDamage < target.damage ) { maximumDamage = target.damage; } } } // targets damage animation switch ( spell.GetID() ) { // For some spells the damage animation is done during the flame animation after the spell animation. case Spell::DEATHRIPPLE: case Spell::DEATHWAVE: RedrawTargetsWithFrameAnimation( targets, ICN::REDDEATH, M82::UNKNOWN, true ); break; case Spell::HOLYWORD: case Spell::HOLYSHOUT: RedrawTargetsWithFrameAnimation( targets, ICN::MAGIC08, M82::UNKNOWN, true ); break; default: RedrawActionWincesKills( targets ); break; } if ( totalDamage > 0 ) { assert( damagedMonsters > 0 ); std::string msg; if ( spell.isUndeadOnly() ) { if ( damagedMonsters == 1 ) { msg = _( "The %{spell} does %{damage} damage to one undead creature." ); StringReplace( msg, "%{spell}", spell.GetName() ); StringReplace( msg, "%{damage}", totalDamage ); status.setMessage( msg, true ); if ( killed > 0 ) { msg = _n( "1 creature perishes.", "%{count} creatures perish.", killed ); StringReplace( msg, "%{count}", killed ); status.setMessage( msg, true ); } } else { msg = _( "The %{spell} does %{damage} damage to all undead creatures." ); StringReplace( msg, "%{spell}", spell.GetName() ); StringReplace( msg, "%{damage}", maximumDamage ); status.setMessage( msg, true ); if ( killed > 0 ) { msg = _( "The %{spell} does %{damage} damage, %{count} creatures perish." ); StringReplace( msg, "%{count}", killed ); } else { msg = _( "The %{spell} does %{damage} damage." ); } StringReplace( msg, "%{spell}", spell.GetName() ); StringReplace( msg, "%{damage}", totalDamage ); status.setMessage( msg, true ); } } else if ( spell.isAliveOnly() ) { if ( damagedMonsters == 1 ) { msg = _( "The %{spell} does %{damage} damage to one living creature." ); StringReplace( msg, "%{spell}", spell.GetName() ); StringReplace( msg, "%{damage}", totalDamage ); status.setMessage( msg, true ); if ( killed > 0 ) { msg = _n( "1 creature perishes.", "%{count} creatures perish.", killed ); StringReplace( msg, "%{count}", killed ); status.setMessage( msg, true ); } } else { msg = _( "The %{spell} does %{damage} damage to all living creatures." ); StringReplace( msg, "%{spell}", spell.GetName() ); StringReplace( msg, "%{damage}", maximumDamage ); status.setMessage( msg, true ); if ( killed > 0 ) { msg = _( "The %{spell} does %{damage} damage, %{count} creatures perish." ); StringReplace( msg, "%{count}", killed ); } else { msg = _( "The %{spell} does %{damage} damage." ); } StringReplace( msg, "%{spell}", spell.GetName() ); StringReplace( msg, "%{damage}", totalDamage ); status.setMessage( msg, true ); } } else { msg = _( "The %{spell} does %{damage} damage." ); StringReplace( msg, "%{spell}", spell.GetName() ); StringReplace( msg, "%{damage}", totalDamage ); status.setMessage( msg, true ); if ( killed > 0 ) { msg = _n( "1 creature perishes.", "%{count} creatures perish.", killed ); StringReplace( msg, "%{count}", killed ); status.setMessage( msg, true ); } } } } status.setMessage( " ", false ); // TODO: remove this temporary assertion assert( _movingUnit == nullptr ); } void Battle::Interface::RedrawActionMonsterSpellCastStatus( const Spell & spell, const Unit & attacker, const TargetInfo & target ) { std::string msg; const uint32_t attackerCount = attacker.GetCount(); switch ( spell.GetID() ) { case Spell::BLIND: msg = _n( "The %{attacker}'s attack blinds the %{target}!", "The %{attacker}' attack blinds the %{target}!", attackerCount ); break; case Spell::PETRIFY: msg = _n( "The %{attacker}'s gaze turns the %{target} to stone!", "The %{attacker}' gaze turns the %{target} to stone!", attackerCount ); break; case Spell::CURSE: msg = _n( "The %{attacker}'s curse falls upon the %{target}!", "The %{attacker}' curse falls upon the %{target}!", attackerCount ); break; case Spell::PARALYZE: msg = _n( "The %{target} is paralyzed by the %{attacker}!", "The %{target} are paralyzed by the %{attacker}!", target.defender->GetCount() ); break; case Spell::DISPEL: msg = _n( "The %{attacker} dispels all good spells on your %{target}!", "The %{attacker} dispel all good spells on your %{target}!", attackerCount ); break; default: // Did you add a new monster spell casting ability? Add the logic above! assert( 0 ); msg = _n( "The %{attacker} casts %{spell} on the %{target}!", "The %{attacker} cast %{spell} on the %{target}!", attackerCount ); StringReplace( msg, "%{spell}", spell.GetName() ); break; } StringReplaceWithLowercase( msg, "%{attacker}", attacker.GetName() ); StringReplaceWithLowercase( msg, "%{target}", target.defender->GetName() ); setStatus( msg, true ); } void Battle::Interface::RedrawActionLuck( const Unit & unit ) { // Reset the delay to wait till the next frame if is not already waiting. if ( !Game::isDelayNeeded( { Game::DelayType::BATTLE_MISSILE_DELAY } ) ) { Game::AnimateResetDelay( Game::DelayType::BATTLE_MISSILE_DELAY ); } LocalEvent & le = LocalEvent::Get(); const bool isGoodLuck = unit.Modes( LUCK_GOOD ); const fheroes2::Rect & pos = unit.GetRectPosition(); std::string msg = isGoodLuck ? _( "Good luck shines on the %{attacker}." ) : _( "Bad luck descends on the %{attacker}." ); StringReplaceWithLowercase( msg, "%{attacker}", unit.GetName() ); setStatus( msg, true ); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); if ( isGoodLuck ) { const fheroes2::Rect & battleArea = border.GetArea(); const fheroes2::Point rainbowDescendPoint( pos.x + pos.width / 2, pos.y - pos.height / 2 ); // If the creature is low on the battleboard - the rainbow will be from the top (in the original game the threshold is about 140 pixels). const bool isVerticalRainbow = ( rainbowDescendPoint.y > 140 ); // Set the rainbow animation direction to match the army side. // Also, if the creature is under effect of the Berserker spell (or similar), then check its original color. bool isRainbowFromRight = ( unit.GetCurrentColor() < 0 ) ? ( unit.GetColor() == arena.GetArmy2Color() ) : ( unit.GetCurrentColor() == arena.GetArmy2Color() ); // The distance from the right or left battlefield border to the 'lucky' creature in the direction from the beginning of the animation to its end. const int32_t borderDistance = isRainbowFromRight ? battleArea.width - rainbowDescendPoint.x : rainbowDescendPoint.x; // The rainbow thickness in pixels: it must be 15 pixels to match the rainbow thickness from original sprite 'ICN::EXPMRL'. const int32_t rainbowThickness = 15; // Declare rainbow generation parameters and set default values: // Rainbow arc parameters for: y = (1-pow2ratio)*k1*(x-x0)^pow1+pow2ratio*k2*(x-x0)^pow2. // Parameters pow3, pow4, pow4ratio are the same as pow1, pow2, pow2ratio, but for the second part of the arc. const int32_t pow1{ 2 }; int32_t pow2{ 10 }; double pow2ratio{ 0.16 }; const int32_t pow3{ 2 }; int32_t pow4{ 2 }; double pow4ratio{ 0.77 }; // The distance from the start to the end of the rainbow in direction of animation (in pixels). int32_t rainbowLength{ rainbowDescendPoint.y }; // The distance from the start to the end (the 'lucky' creature) of the rainbow orthogonal to the direction of animation (in pixels). int32_t rainbowAscend{ 75 }; // The distance from the top to the end (the 'lucky' creature) of the rainbow orthogonal to the direction of animation (in pixels). int32_t rainbowDescend{ 10 }; // The coordinate where the rainbow arc changes its direction. int32_t rainbowTop{ 50 }; // Rainbow image offset from battlefield zero coordinates to "fall" onto the 'lucky' creature. int32_t drawOffset{ 10 }; // Set rainbow generation parameters. if ( isVerticalRainbow ) { rainbowAscend = static_cast( 0.4845 * rainbowLength + 156.2 ); // If the rainbow doesn't fit on the screen, then change its horizontal direction. if ( ( borderDistance + rainbowThickness / 2 ) < rainbowAscend ) { isRainbowFromRight = !isRainbowFromRight; } rainbowDescend = std::max( 1, static_cast( 0.0342 * rainbowLength - 4.868 ) ); rainbowTop = static_cast( 0.8524 * rainbowLength + 17.7 ); drawOffset = isRainbowFromRight ? ( rainbowDescendPoint.x - rainbowDescend - rainbowThickness / 2 ) : ( rainbowDescendPoint.x - rainbowDescend - rainbowAscend ); } else { pow2 = 0; pow4 = 5; pow2ratio = 0.0; pow4ratio = 0.5; rainbowLength = borderDistance; rainbowDescend = std::max( 1, static_cast( 0.1233 * rainbowLength + 0.7555 ) ); rainbowTop = static_cast( 0.6498 * rainbowLength + 11.167 ); drawOffset = std::max( 10, rainbowDescendPoint.y - rainbowDescend ); } const fheroes2::Size rainbowArcBegin( rainbowTop, rainbowDescend + rainbowAscend ); const fheroes2::Size rainbowArcEnd( rainbowLength - rainbowTop, rainbowDescend ); std::vector rainbowArc; GetHalfArc( rainbowArc, -rainbowArcBegin.width, rainbowArcBegin.height, pow1, pow2, pow2ratio ); GetHalfArc( rainbowArc, rainbowArcEnd.width, rainbowArcEnd.height, pow3, pow4, pow4ratio ); const fheroes2::Image luckSprite = DrawRainbow( rainbowArc, rainbowThickness, isVerticalRainbow, isRainbowFromRight ); const int32_t rainbowDrawSteps = 30; // Rainbow animation draw step (in original game it is random and about 7-11 pixels). // We set the constant animation time for all rainbows: rainbowLength/30 fits the rainbow sound duration on '1' speed. const double drawStep = static_cast( rainbowLength ) / rainbowDrawSteps; // Don't waste time waiting for Good Luck sound if the game sounds are turned off const bool soundOn = Settings::Get().SoundVolume() > 0; if ( soundOn ) { AudioManager::PlaySound( M82::GOODLUCK ); } // If sound is turned off we still wait for the GOODLUCK sound to over but no more the twice the rainbow animation time. // So we start counting steps from '-rainbowDrawSteps' to 'rainbowDrawSteps'. int32_t step = -rainbowDrawSteps; double x = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_MISSILE_DELAY } ) ) && ( ( ( soundOn || step < rainbowDrawSteps ) && Mixer::isPlaying( -1 ) ) || x < rainbowLength ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_MISSILE_DELAY ) ) { // Reset all units idle animation delay during rainbow animation not to start new idle animations. // This does not affect Zombies, Genies, Medusas and Ghosts as they have permanent idle animations. ResetIdleTroopAnimation(); RedrawPartialStart(); if ( x < rainbowLength ) { x += drawStep; } const int32_t drawWidth = x > rainbowLength ? rainbowLength : static_cast( x ); // For different rainbow types use appropriate animation direction. if ( isVerticalRainbow ) { fheroes2::Blit( luckSprite, 0, 0, _mainSurface, drawOffset, 0, luckSprite.width(), drawWidth ); } else { if ( isRainbowFromRight ) { fheroes2::Blit( luckSprite, rainbowLength - drawWidth, 0, _mainSurface, battleArea.width - drawWidth, drawOffset, drawWidth, luckSprite.height() ); } else { fheroes2::Blit( luckSprite, 0, 0, _mainSurface, 0, drawOffset, drawWidth, luckSprite.height() ); } } RedrawPartialFinish(); ++step; } } } else { const int maxHeight = GetAbsoluteICNHeight( ICN::CLOUDLUK ); int y = pos.y + pos.height + cellYOffset; // move drawing position if it will clip outside of the battle window if ( y - maxHeight < 0 ) y = maxHeight; AudioManager::PlaySound( M82::BADLUCK ); int frameId = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_MISSILE_DELAY } ) ) && Mixer::isPlaying( -1 ) ) { CheckGlobalEvents( le ); if ( frameId < 8 && Game::validateAnimationDelay( Game::BATTLE_MISSILE_DELAY ) ) { RedrawPartialStart(); const fheroes2::Sprite & luckSprite = fheroes2::AGG::GetICN( ICN::CLOUDLUK, frameId ); fheroes2::Blit( luckSprite, _mainSurface, pos.x + pos.width / 2 + luckSprite.x(), y + luckSprite.y() ); RedrawPartialFinish(); ++frameId; } } } } void Battle::Interface::RedrawActionMorale( Unit & unit, const bool isGoodMorale ) { std::string msg; // Reset the idle animation delay timer to prevent the unit from starting the idle animation. unit.checkIdleDelay(); if ( isGoodMorale ) { msg = _( "High morale enables the %{monster} to attack again." ); StringReplaceWithLowercase( msg, "%{monster}", unit.GetName() ); setStatus( msg, true ); RedrawTroopWithFrameAnimation( unit, ICN::MORALEG, M82::GOODMRLE, NONE ); } else { msg = _( "Low morale causes the %{monster} to freeze in panic." ); StringReplaceWithLowercase( msg, "%{monster}", unit.GetName() ); setStatus( msg, true ); RedrawTroopWithFrameAnimation( unit, ICN::MORALEB, M82::BADMRLE, WINCE ); } } void Battle::Interface::RedrawActionTowerPart1( const Tower & tower, const Unit & defender ) { Cursor::Get().SetThemes( Cursor::WAR_POINTER ); _currentUnit = nullptr; const fheroes2::Point missileStart = tower.GetPortPosition(); const fheroes2::Point targetPos = defender.GetCenterPoint(); const double angle = GetAngle( missileStart, targetPos ); AudioManager::PlaySound( M82::KEEPSHOT ); // Keep missile == Orc missile RedrawMissileAnimation( missileStart, targetPos, angle, Monster::ORC ); } void Battle::Interface::RedrawActionTowerPart2( const Tower & tower, const TargetInfo & target ) { TargetsInfo targets; targets.push_back( target ); const bool isMirror = target.defender->isModes( CAP_MIRRORIMAGE ); // targets damage animation RedrawActionWincesKills( targets ); // draw status for first defender std::string msg = _( "%{tower} does %{damage} damage." ); StringReplace( msg, "%{tower}", tower.GetName() ); StringReplace( msg, "%{damage}", target.damage ); if ( target.killed ) { msg += ' '; msg.append( _n( "1 %{defender} perishes.", "%{count} %{defender} perish.", target.killed ) ); StringReplace( msg, "%{count}", target.killed ); StringReplaceWithLowercase( msg, "%{defender}", target.defender->GetPluralName( target.killed ) ); } if ( !isMirror ) { setStatus( msg, true ); } // TODO: remove this temporary assertion assert( _movingUnit == nullptr ); } void Battle::Interface::RedrawActionCatapultPart1( const CastleDefenseStructure catapultTarget, const bool isHit ) { // Reset the delay before rendering the first frame of catapult animation. Game::AnimateResetDelay( Game::DelayType::BATTLE_CATAPULT_DELAY ); LocalEvent & le = LocalEvent::Get(); const fheroes2::Rect & area = GetArea(); AudioManager::PlaySound( M82::CATSND00 ); // catapult animation while ( le.HandleEvents( false ) && catapult_frame < 5 ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_CATAPULT_DELAY ) ) { Redraw(); ++catapult_frame; } } // Reset the delay before rendering the first frame of catapult boulder animation. Game::AnimateResetDelay( Game::DelayType::BATTLE_CATAPULT_BOULDER_DELAY ); // boulder animation fheroes2::Point pt1( 30, 290 ); fheroes2::Point pt2 = Catapult::GetTargetPosition( catapultTarget, isHit ); const int32_t boulderArcStep = ( pt2.x - pt1.x ) / 30; // set the projectile arc height for each castle target and a formula for an unknown target int32_t boulderArcHeight; switch ( catapultTarget ) { case CastleDefenseStructure::WALL1: boulderArcHeight = 220; break; case CastleDefenseStructure::WALL2: case CastleDefenseStructure::BRIDGE: boulderArcHeight = 216; break; case CastleDefenseStructure::WALL3: boulderArcHeight = 204; break; case CastleDefenseStructure::WALL4: boulderArcHeight = 208; break; case CastleDefenseStructure::TOWER1: case CastleDefenseStructure::TOWER2: boulderArcHeight = 206; break; case CastleDefenseStructure::CENTRAL_TOWER: boulderArcHeight = 290; break; default: boulderArcHeight = static_cast( std::lround( 0.55 * getDistance( pt1, pt2 ) ) ); } pt1.x += area.x; pt2.x += area.x; pt1.y += area.y; pt2.y += area.y; const std::vector points = GetArcPoints( pt1, pt2, boulderArcHeight, boulderArcStep ); std::vector::const_iterator pnt = points.begin(); uint32_t boulderFrameId = 0; const uint32_t boulderFramesCount = fheroes2::AGG::GetICNCount( ICN::BOULDER ); while ( le.HandleEvents( false ) && pnt != points.end() ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_CATAPULT_BOULDER_DELAY ) ) { if ( catapult_frame < 9 ) ++catapult_frame; RedrawPartialStart(); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::BOULDER, boulderFrameId ), _mainSurface, pnt->x, pnt->y ); RedrawPartialFinish(); ++pnt; ++boulderFrameId; if ( boulderFrameId >= boulderFramesCount ) { boulderFrameId = 0; } } } // Reset the delay before rendering the catapult cloud. Game::AnimateResetDelay( Game::DelayType::BATTLE_CATAPULT_CLOUD_DELAY ); // draw cloud const int32_t icn = isHit ? ICN::LICHCLOD : ICN::SMALCLOD; uint32_t frame = 0; // If the building is hit, end the animation on the 5th frame to change the building state (when the smoke cloud is largest). uint32_t maxFrame = isHit ? castleBuildingDestroyFrame : fheroes2::AGG::GetICNCount( icn ); const bool isBridgeDestroyed = isHit && ( catapultTarget == CastleDefenseStructure::BRIDGE ); // If the bridge is destroyed - prepare parameters for the second smoke cloud. if ( isBridgeDestroyed ) { pt1 = pt2 + bridgeDestroySmokeOffset; // Increase maxFrame to get bigger second smoke cloud. maxFrame = bridgeDestroyFrame; } AudioManager::PlaySound( M82::CATSND02 ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_CATAPULT_CLOUD_DELAY } ) ) && frame < maxFrame ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_CATAPULT_CLOUD_DELAY ) ) { RedrawPartialStart(); // Start animation of the second smoke cloud only for the bridge and after 2 frames of the first smoke cloud. if ( isBridgeDestroyed && frame >= bridgeDestroySmokeDelay ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icn, frame - bridgeDestroySmokeDelay ); fheroes2::Blit( sprite, _mainSurface, pt1.x + sprite.x(), pt1.y + sprite.y() ); } const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icn, frame ); fheroes2::Blit( sprite, _mainSurface, pt2.x + sprite.x(), pt2.y + sprite.y() ); RedrawPartialFinish(); ++frame; } } if ( !isHit ) { catapult_frame = 0; } } void Battle::Interface::RedrawActionCatapultPart2( const CastleDefenseStructure catapultTarget ) { // Finish the smoke cloud animation after the building's state has changed after the hit and it is drawn as demolished. const fheroes2::Point pt1 = Catapult::GetTargetPosition( catapultTarget, true ) + GetArea().getPosition(); fheroes2::Point pt2; // Continue the smoke cloud animation from the 6th frame. const int32_t icnId = ICN::LICHCLOD; uint32_t frame = castleBuildingDestroyFrame; const uint32_t maxFrame = fheroes2::AGG::GetICNCount( icnId ); uint32_t maxAnimationFrame = maxFrame; const bool isBridgeDestroyed = ( catapultTarget == CastleDefenseStructure::BRIDGE ); // If the bridge is destroyed - prepare parameters for the second smoke cloud. if ( isBridgeDestroyed ) { pt2 = pt1 + bridgeDestroySmokeOffset; // Increase maxAnimationFrame to finish the second smoke animation. maxAnimationFrame += bridgeDestroySmokeDelay; // Bridge smoke animation should continue from the 7th frame. frame = bridgeDestroyFrame; } LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_CATAPULT_CLOUD_DELAY } ) ) && frame < maxAnimationFrame ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_CATAPULT_CLOUD_DELAY ) ) { RedrawPartialStart(); // Draw animation of the second smoke cloud only for the bridge. if ( isBridgeDestroyed ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icnId, frame - bridgeDestroySmokeDelay ); fheroes2::Blit( sprite, _mainSurface, pt2.x + sprite.x(), pt2.y + sprite.y() ); } // Don't draw the smoke cloud after its animation has ended (in case the second smoke cloud is still animating). if ( frame <= maxFrame ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icnId, frame ); fheroes2::Blit( sprite, _mainSurface, pt1.x + sprite.x(), pt1.y + sprite.y() ); } RedrawPartialFinish(); ++frame; } } catapult_frame = 0; } void Battle::Interface::RedrawActionArrowSpell( const Unit & target ) { const HeroBase * caster = arena.GetCurrentCommander(); if ( caster ) { const fheroes2::Point missileStart = caster == _opponent1->GetHero() ? _opponent1->GetCastPosition() : _opponent2->GetCastPosition(); const fheroes2::Point targetPos = target.GetCenterPoint(); const double angle = GetAngle( missileStart, targetPos ); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); AudioManager::PlaySound( M82::MAGCAROW ); // Magic arrow == Archer missile RedrawMissileAnimation( missileStart, targetPos, angle, Monster::ARCHER ); } } void Battle::Interface::RedrawActionTeleportSpell( Unit & target, const int32_t dst ) { LocalEvent & le = LocalEvent::Get(); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); uint8_t currentAlpha = target.GetCustomAlpha(); const uint8_t alphaStep = 15; AudioManager::PlaySound( M82::TELPTOUT ); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && Mixer::isPlaying( -1 ) ) { CheckGlobalEvents( le ); if ( currentAlpha >= alphaStep && Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { currentAlpha -= alphaStep; target.SetCustomAlpha( currentAlpha ); Redraw(); } } currentAlpha = 0; Redraw(); target.SetPosition( dst ); AudioManager::PlaySound( M82::TELPTIN ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && Mixer::isPlaying( -1 ) ) { CheckGlobalEvents( le ); if ( currentAlpha <= ( 255 - alphaStep ) && Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { currentAlpha += alphaStep; target.SetCustomAlpha( currentAlpha ); Redraw(); } } target.SetCustomAlpha( 255 ); } void Battle::Interface::RedrawActionSummonElementalSpell( Unit & target ) { LocalEvent & le = LocalEvent::Get(); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); uint8_t currentAlpha = 0; const uint8_t alphaStep = 20; AudioManager::PlaySound( M82::SUMNELM ); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && currentAlpha <= ( 255 - alphaStep ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { currentAlpha += alphaStep; target.SetCustomAlpha( currentAlpha ); Redraw(); } } target.SetCustomAlpha( 255 ); } void Battle::Interface::RedrawActionMirrorImageSpell( const Unit & target, const Position & pos ) { LocalEvent & le = LocalEvent::Get(); fheroes2::Sprite sprite = fheroes2::AGG::GetICN( target.GetMonsterSprite(), target.GetFrame() ); fheroes2::ApplyPalette( sprite, PAL::GetPalette( PAL::PaletteType::MIRROR_IMAGE ) ); const fheroes2::Rect & rt1 = target.GetRectPosition(); const fheroes2::Rect & rt2 = pos.GetRect(); const std::vector points = GetLinePoints( rt1.getPosition(), rt2.getPosition(), 5 ); std::vector::const_iterator pnt = points.begin(); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); AudioManager::PlaySound( M82::MIRRORIM ); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && pnt != points.end() ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { const fheroes2::Point & sp = GetTroopPosition( target, sprite ); RedrawPartialStart(); fheroes2::Blit( sprite, _mainSurface, sp.x - rt1.x + ( *pnt ).x, sp.y - rt1.y + ( *pnt ).y, target.isReflect() ); RedrawPartialFinish(); ++pnt; } } setStatus( _( "The mirror image is created." ), true ); } void Battle::Interface::RedrawLightningOnTargets( const std::vector & points, const fheroes2::Rect & drawRoi ) { if ( points.size() < 2 ) return; const fheroes2::Point roiOffset( drawRoi.x, drawRoi.y ); LocalEvent & le = LocalEvent::Get(); Cursor & cursor = Cursor::Get(); cursor.SetThemes( Cursor::WAR_POINTER ); AudioManager::PlaySound( points.size() > 2 ? M82::CHAINLTE : M82::LIGHTBLT ); for ( size_t i = 1; i < points.size(); ++i ) { const fheroes2::Point & startingPos = points[i - 1]; const fheroes2::Point & endPos = points[i]; const std::vector> & lightningBolt = GenerateLightning( startingPos + roiOffset, endPos + roiOffset ); fheroes2::Rect roi; const bool isHorizontalBolt = std::abs( startingPos.x - endPos.x ) > std::abs( startingPos.y - endPos.y ); const bool isForwardDirection = isHorizontalBolt ? ( endPos.x > startingPos.x ) : ( endPos.y > startingPos.y ); const int animationStep = 100; if ( isHorizontalBolt ) { roi.height = drawRoi.height; if ( isForwardDirection ) { roi.x = 0; roi.width = startingPos.x; } else { roi.x = startingPos.x; roi.width = drawRoi.width - startingPos.x; } } else { roi.width = drawRoi.width; if ( isForwardDirection ) { roi.y = 0; roi.height = startingPos.y; } else { roi.y = startingPos.y; roi.height = drawRoi.height - startingPos.y; } } while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_DISRUPTING_DELAY } ) ) && ( ( isHorizontalBolt && roi.width < drawRoi.width ) || ( !isHorizontalBolt && roi.height < drawRoi.height ) ) ) { if ( Game::validateAnimationDelay( Game::BATTLE_DISRUPTING_DELAY ) ) { if ( isHorizontalBolt ) { if ( isForwardDirection ) { roi.width += animationStep; } else { roi.width += animationStep; roi.x -= animationStep; } if ( roi.x < 0 ) roi.x = 0; if ( roi.width > drawRoi.width ) roi.width = drawRoi.width; } else { if ( isForwardDirection ) { roi.height += animationStep; } else { roi.height += animationStep; roi.y -= animationStep; } if ( roi.y < 0 ) roi.y = 0; if ( roi.height > drawRoi.height ) roi.height = drawRoi.height; } RedrawPartialStart(); RedrawLightning( lightningBolt, fheroes2::GetColorId( 0xff, 0xff, 0 ), _mainSurface, { roi.x + roiOffset.x, roi.y + roiOffset.y, roi.width, roi.height } ); fheroes2::ApplyPalette( _mainSurface, 7 ); RedrawPartialFinish(); } } } // small delay to display fully drawn lightning fheroes2::delayforMs( 100 ); uint32_t frame = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_DISRUPTING_DELAY } ) ) && frame < fheroes2::AGG::GetICNCount( ICN::SPARKS ) ) { CheckGlobalEvents( le ); if ( ( frame == 0 ) || Game::validateAnimationDelay( Game::BATTLE_DISRUPTING_DELAY ) ) { RedrawPartialStart(); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::SPARKS, frame ); const int32_t spriteWidth = sprite.width(); for ( size_t i = 1; i < points.size(); ++i ) { const fheroes2::Point pt = points[i] - fheroes2::Point( spriteWidth / 2, 0 ) + roiOffset; fheroes2::Blit( sprite, _mainSurface, pt.x, pt.y ); } RedrawPartialFinish(); ++frame; } } } void Battle::Interface::RedrawActionLightningBoltSpell( const Unit & target ) { _currentUnit = nullptr; const fheroes2::Point startingPos = arena.GetCurrentCommander() == _opponent1->GetHero() ? _opponent1->GetCastPosition() : _opponent2->GetCastPosition(); const fheroes2::Rect & pos = target.GetRectPosition(); const fheroes2::Point endPos( pos.x + pos.width / 2, pos.y ); const std::vector points{ startingPos, endPos }; RedrawLightningOnTargets( points, _surfaceInnerArea ); } void Battle::Interface::RedrawActionChainLightningSpell( const TargetsInfo & targets ) { const fheroes2::Point startingPos = arena.GetCurrentCommander() == _opponent1->GetHero() ? _opponent1->GetCastPosition() : _opponent2->GetCastPosition(); std::vector points; points.reserve( size( targets ) + 1 ); points.push_back( startingPos ); for ( const TargetInfo & target : targets ) { const fheroes2::Rect & pos = target.defender->GetRectPosition(); points.emplace_back( pos.x + pos.width / 2, pos.y ); } RedrawLightningOnTargets( points, _surfaceInnerArea ); } void Battle::Interface::RedrawActionBloodLustSpell( const Unit & target ) { LocalEvent & le = LocalEvent::Get(); fheroes2::Sprite unitSprite = fheroes2::AGG::GetICN( target.GetMonsterSprite(), target.GetFrame() ); std::vector> originalPalette; if ( target.Modes( SP_STONE ) ) { originalPalette.push_back( PAL::GetPalette( PAL::PaletteType::GRAY ) ); } else if ( target.Modes( CAP_MIRRORIMAGE ) ) { originalPalette.push_back( PAL::GetPalette( PAL::PaletteType::MIRROR_IMAGE ) ); } if ( !originalPalette.empty() ) { for ( size_t i = 1; i < originalPalette.size(); ++i ) { originalPalette[0] = PAL::CombinePalettes( originalPalette[0], originalPalette[i] ); } fheroes2::ApplyPalette( unitSprite, originalPalette[0] ); } std::vector convert = PAL::GetPalette( PAL::PaletteType::RED ); if ( !originalPalette.empty() ) { convert = PAL::CombinePalettes( PAL::GetPalette( PAL::PaletteType::GRAY ), convert ); } fheroes2::Sprite bloodlustEffect( unitSprite ); fheroes2::ApplyPalette( bloodlustEffect, convert ); fheroes2::Sprite mixSprite( unitSprite ); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); _currentUnit = ⌖ b_current_sprite = &mixSprite; const uint32_t bloodlustDelay = 1800 / 20; // duration is 1900ms AudioManager::PlaySound( M82::BLOODLUS ); uint32_t alpha = 0; uint32_t frame = 0; // Immediately indicate that the delay has passed to render first frame immediately. Game::passCustomAnimationDelay( bloodlustDelay ); // Make sure that the first run is passed immediately. assert( !Game::isCustomDelayNeeded( bloodlustDelay ) ); while ( le.HandleEvents( Game::isCustomDelayNeeded( bloodlustDelay ) ) && Mixer::isPlaying( -1 ) ) { CheckGlobalEvents( le ); if ( frame < 20 && Game::validateCustomAnimationDelay( bloodlustDelay ) ) { mixSprite = unitSprite; fheroes2::AlphaBlit( bloodlustEffect, mixSprite, static_cast( alpha ) ); Redraw(); alpha += ( frame < 10 ) ? 20 : -20; ++frame; } } _currentUnit = nullptr; b_current_sprite = nullptr; } void Battle::Interface::RedrawActionStoneSpell( const Unit & target ) { LocalEvent & le = LocalEvent::Get(); const fheroes2::Sprite & unitSprite = fheroes2::AGG::GetICN( target.GetMonsterSprite(), target.GetFrame() ); fheroes2::Sprite stoneEffect( unitSprite ); fheroes2::ApplyPalette( stoneEffect, PAL::GetPalette( PAL::PaletteType::GRAY ) ); fheroes2::Sprite mixSprite( unitSprite ); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); _currentUnit = ⌖ b_current_sprite = &mixSprite; AudioManager::PlaySound( M82::PARALIZE ); uint32_t alpha = 0; uint32_t frame = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && Mixer::isPlaying( -1 ) ) { CheckGlobalEvents( le ); if ( frame < 25 && Game::validateCustomAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { mixSprite = fheroes2::Sprite( unitSprite ); fheroes2::AlphaBlit( stoneEffect, mixSprite, static_cast( alpha ) ); Redraw(); alpha += 10; ++frame; } } _currentUnit = nullptr; b_current_sprite = nullptr; } void Battle::Interface::RedrawActionResurrectSpell( Unit & target, const Spell & spell ) { if ( !target.isValid() ) { // Restore direction of the creature, since it could be killed when it was reflected. target.UpdateDirection(); Redraw(); target.IncreaseAnimFrame(); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { if ( target.isFinishAnimFrame() ) { // We have reached the end of animation. break; } Redraw(); target.IncreaseAnimFrame(); } } } AudioManager::PlaySound( M82::FromSpell( spell.GetID() ) ); RedrawTroopWithFrameAnimation( target, ICN::YINYANG, M82::UNKNOWN, target.GetHitPoints() == 0 ? RESURRECT : NONE ); } void Battle::Interface::RedrawActionColdRaySpell( Unit & target ) { RedrawRaySpell( target, ICN::COLDRAY, M82::COLDRAY, 18 ); RedrawTroopWithFrameAnimation( target, ICN::ICECLOUD, M82::UNKNOWN, NONE ); } void Battle::Interface::RedrawRaySpell( const Unit & target, const int spellICN, const int spellSound, const int32_t size ) { Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); // Casting hero position const fheroes2::Point startingPos = arena.GetCurrentCommander() == _opponent1->GetHero() ? _opponent1->GetCastPosition() : _opponent2->GetCastPosition(); const fheroes2::Point targetPos = target.GetCenterPoint(); const std::vector path = GetEuclideanLine( startingPos, targetPos, size ); const uint32_t spriteCount = fheroes2::AGG::GetICNCount( spellICN ); cursor.SetThemes( Cursor::WAR_POINTER ); AudioManager::PlaySound( spellSound ); size_t i = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_DISRUPTING_DELAY } ) ) && i < path.size() ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_DISRUPTING_DELAY ) ) { const uint32_t frame = static_cast( i * spriteCount / path.size() ); // it's safe to do such as i <= path.size() const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( spellICN, frame ); fheroes2::Blit( sprite, _mainSurface, path[i].x - sprite.width() / 2, path[i].y - sprite.height() / 2 ); RedrawPartialFinish(); ++i; } } } void Battle::Interface::RedrawActionDisruptingRaySpell( const Unit & target ) { LocalEvent & le = LocalEvent::Get(); RedrawRaySpell( target, ICN::DISRRAY, M82::DISRUPTR, 24 ); // Part 2 - ripple effect const fheroes2::Sprite & unitSprite = fheroes2::AGG::GetICN( target.GetMonsterSprite(), target.GetFrame() ); fheroes2::Sprite rippleSprite; const Unit * old_current = _currentUnit; _currentUnit = ⌖ _movingPos = { 0, 0 }; int32_t frame = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_DISRUPTING_DELAY } ) ) && frame < 60 ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_DISRUPTING_DELAY ) ) { rippleSprite = fheroes2::CreateRippleEffect( unitSprite, frame ); rippleSprite.setPosition( unitSprite.x(), unitSprite.y() ); b_current_sprite = &rippleSprite; Redraw(); frame += 2; } } _currentUnit = old_current; b_current_sprite = nullptr; } void Battle::Interface::RedrawActionDeathWaveSpell( const int32_t strength ) { Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); _currentUnit = nullptr; cursor.SetThemes( Cursor::WAR_POINTER ); // Set all non-dead troops animation to static and redraw the '_mainSurface'. SwitchAllUnitsAnimation( Monster_Info::STATIC ); Redraw(); fheroes2::Rect area = GetArea(); // Cut out the battle log image so we don't use it in the death wave effect. area.height -= status.height; // And if listlog is open, then cut off it too. if ( listlog && listlog->isOpenLog() ) { area.height -= listlog->GetArea().height; } fheroes2::Image battleFieldCopy; battleFieldCopy._disableTransformLayer(); battleFieldCopy.resize( area.width, area.height ); fheroes2::Copy( _mainSurface, 0, 0, battleFieldCopy, 0, 0, area.width, area.height ); // The death wave horizontal length in pixels. const int32_t waveLength = 38; const int32_t waveStep = 5; // A death wave parameter that limits the curve to one cosine period. const double waveLimit = waveLength / M_PI / 2; std::vector deathWaveCurve; deathWaveCurve.reserve( waveLength ); // Calculate the "Death Wave" curve as one period of cosine, which starts from 0 with an amplitude of 1/2 and shifted down by 0.5. // So we get a smooth hill, which is the multiplied with 'strength' and shifted after that by -1px. // (The "Death Wave" curve has to shift the image and cosine starts from 0 so we add extra 1px). for ( int32_t posX = 0; posX < waveLength; ++posX ) { deathWaveCurve.push_back( static_cast( std::round( strength * ( cos( posX / waveLimit ) / 2 - 0.5 ) ) ) - 1 ); } // Take into account that the Death Wave starts outside the battle screen. area.x -= waveLength; // The first frame of spell effect must have a part of the spell, so we start from its first position. int32_t position = waveStep; fheroes2::Display & display = fheroes2::Display::instance(); // Prepare the blank image for the Death Wave spell effect. fheroes2::Image spellEffect; spellEffect._disableTransformLayer(); spellEffect.resize( waveLength, area.height ); AudioManager::PlaySound( M82::MNRDEATH ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_DISRUPTING_DELAY } ) ) && position < area.width + waveLength ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_DISRUPTING_DELAY ) ) { const int32_t wavePositionX = ( area.x + position < 0 ) ? 0 : ( area.x + position ); const int32_t waveWidth = position > waveLength ? ( position > area.width ? ( waveLength - position + area.width ) : waveLength ) : position; const int32_t restorePositionX = ( wavePositionX < waveStep ) ? 0 : ( wavePositionX - waveStep ); const int32_t restoreWidth = wavePositionX < waveStep ? wavePositionX : waveStep; const fheroes2::Rect renderArea( _interfacePosition.x + restorePositionX, _interfacePosition.y + area.y, waveWidth + restoreWidth, area.height ); // Place a copy of the original image where the Death Wave effect was on the previous frame. fheroes2::Copy( battleFieldCopy, restorePositionX, area.y, display, renderArea.x, renderArea.y, restoreWidth, renderArea.height ); // Place the Death Wave effect to its new position. fheroes2::CreateDeathWaveEffect( spellEffect, battleFieldCopy, position, deathWaveCurve ); fheroes2::Copy( spellEffect, 0, 0, display, renderArea.x + restoreWidth, renderArea.y, waveWidth, area.height ); // Render only the changed screen area. display.render( renderArea ); position += waveStep; } } SwitchAllUnitsAnimation( Monster_Info::STATIC ); } void Battle::Interface::RedrawActionColdRingSpell( const int32_t dst, const TargetsInfo & targets ) { LocalEvent & le = LocalEvent::Get(); const int icn = ICN::COLDRING; const int m82 = M82::FromSpell( Spell::COLDRING ); uint32_t frame = 0; const fheroes2::Rect & center = Board::GetCell( dst )->GetPos(); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); // set WNCE _currentUnit = nullptr; for ( const TargetInfo & target : targets ) { if ( target.defender && target.damage ) { target.defender->SwitchAnimation( Monster_Info::WNCE ); } } AudioManager::PlaySound( m82 ); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && frame < fheroes2::AGG::GetICNCount( icn ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { RedrawPartialStart(); const fheroes2::Sprite & sprite1 = fheroes2::AGG::GetICN( icn, frame ); fheroes2::Blit( sprite1, _mainSurface, center.x + center.width / 2 + sprite1.x(), center.y + center.height / 2 + sprite1.y() ); const fheroes2::Sprite & sprite2 = fheroes2::AGG::GetICN( icn, frame ); fheroes2::Blit( sprite2, _mainSurface, center.x + center.width / 2 - sprite2.width() - sprite2.x(), center.y + center.height / 2 + sprite2.y(), true ); RedrawPartialFinish(); for ( const TargetInfo & target : targets ) { if ( target.defender && target.damage ) { target.defender->IncreaseAnimFrame( false ); } } ++frame; } } for ( const TargetInfo & target : targets ) { if ( target.defender ) { target.defender->SwitchAnimation( Monster_Info::STATIC ); _currentUnit = nullptr; } } } void Battle::Interface::RedrawActionHolyShoutSpell( const uint8_t strength ) { Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); cursor.SetThemes( Cursor::WAR_POINTER ); // Set all non-dead troops animation to static and redraw the '_mainSurface'. SwitchAllUnitsAnimation( Monster_Info::STATIC ); Redraw(); fheroes2::Rect area = GetArea(); // Cut out the battle log image so we don't use it in the death wave effect. area.height -= status.height; // And if listlog is open, then cut off it too. if ( listlog && listlog->isOpenLog() ) { area.height -= listlog->GetArea().height; } fheroes2::Image battleFieldCopy; battleFieldCopy._disableTransformLayer(); battleFieldCopy.resize( area.width, area.height ); fheroes2::Copy( _mainSurface, 0, 0, battleFieldCopy, 0, 0, area.width, area.height ); _currentUnit = nullptr; const uint32_t maxFrame = 20; const uint32_t halfMaxFrame = maxFrame / 2; // A vector of frames to animate the increase of the spell effect. The decrease will be shown in reverse frames order. // Initialize a vector with copies of battle field to use them in making the spell effect increase animation. std::vector spellEffect; static_assert( halfMaxFrame > 1 ); spellEffect.reserve( halfMaxFrame ); const uint32_t spellEffectLastFrame = halfMaxFrame - 1; // The similar frames number is smaller than size by 1 as the last frame will be different. while ( spellEffect.size() < spellEffectLastFrame ) { spellEffect.push_back( battleFieldCopy ); } // The last frame is the full power of spell effect. It will be used to produce other frames. spellEffect.emplace_back( fheroes2::CreateHolyShoutEffect( battleFieldCopy, 4, strength ) ); const uint32_t spellcastDelay = Game::ApplyBattleSpeed( 3000 ) / maxFrame; uint32_t frame = 0; uint8_t alpha = 30; const uint8_t alphaStep = 25; fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Rect renderArea( _interfacePosition.x + area.x, _interfacePosition.y + area.y, area.width, area.height ); // Immediately indicate that the delay has passed to render first frame immediately. Game::passCustomAnimationDelay( spellcastDelay ); // Make sure that the first run is passed immediately. assert( !Game::isCustomDelayNeeded( spellcastDelay ) ); AudioManager::PlaySound( M82::MASSCURS ); while ( le.HandleEvents( Game::isCustomDelayNeeded( spellcastDelay ) ) && frame < maxFrame ) { CheckGlobalEvents( le ); if ( Game::validateCustomAnimationDelay( spellcastDelay ) ) { // Display the maximum spell effect for 1 more 'spellcastDelay' without rendering a frame. if ( frame != halfMaxFrame ) { // If the spell effect is increasing we generate the frame for it in the vector to use it later in decreasing animation. if ( frame < spellEffectLastFrame ) { fheroes2::AlphaBlit( spellEffect[spellEffectLastFrame], spellEffect[frame], alpha ); alpha += alphaStep; } const uint32_t spellEffectFrame = ( frame < halfMaxFrame ) ? frame : ( maxFrame - frame - 1 ); fheroes2::Copy( spellEffect[spellEffectFrame], area.x, area.y, display, renderArea.x, renderArea.y, renderArea.width, renderArea.height ); display.render( renderArea ); } ++frame; } } } void Battle::Interface::RedrawActionElementalStormSpell( const TargetsInfo & targets ) { LocalEvent & le = LocalEvent::Get(); const int icn = ICN::STORM; const int m82 = M82::FromSpell( Spell::ELEMENTALSTORM ); const int spriteSize = 54; const uint32_t icnCount = fheroes2::AGG::GetICNCount( icn ); std::vector spriteCache; spriteCache.reserve( icnCount ); for ( uint32_t i = 0; i < icnCount; ++i ) { spriteCache.push_back( fheroes2::AGG::GetICN( icn, i ) ); } Cursor::Get().SetThemes( Cursor::WAR_POINTER ); _currentUnit = nullptr; for ( const TargetInfo & target : targets ) { if ( target.defender && target.damage ) { target.defender->SwitchAnimation( Monster_Info::WNCE ); } } AudioManager::PlaySound( m82 ); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); uint32_t frame = 0; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && frame < 60 ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { RedrawPartialStart(); if ( icnCount > 0 ) { for ( int x = 0; x * spriteSize < _surfaceInnerArea.width; ++x ) { const int idX = frame + x * 3; const int offsetX = x * spriteSize; for ( int y = 0; y * spriteSize < _surfaceInnerArea.height; ++y ) { const fheroes2::Sprite & sprite = spriteCache[( idX + y ) % icnCount]; fheroes2::Blit( sprite, _mainSurface, offsetX + sprite.x(), y * spriteSize + sprite.y() ); } } } RedrawPartialFinish(); for ( const TargetInfo & target : targets ) { if ( target.defender && target.damage ) { target.defender->IncreaseAnimFrame( false ); } } ++frame; } } for ( const TargetInfo & target : targets ) { if ( target.defender ) { target.defender->SwitchAnimation( Monster_Info::STATIC ); _currentUnit = nullptr; } } } void Battle::Interface::RedrawActionArmageddonSpell() { Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); fheroes2::Rect area = GetArea(); area.height -= status.height; // Hide Turn Order for the Armageddon animation original image not to shake it together with the land. Settings & settings = Settings::Get(); const bool isTurnOrderShown = settings.BattleShowTurnOrder(); if ( isTurnOrderShown ) { settings.setBattleShowTurnOrder( false ); } // Set all non-dead troops animation to static and redraw the '_mainSurface'. SwitchAllUnitsAnimation( Monster_Info::STATIC ); RedrawPartialStart(); // Restore the Turn Order rendering if it was enabled. if ( isTurnOrderShown ) { settings.setBattleShowTurnOrder( true ); } fheroes2::Image spriteWhitening; spriteWhitening._disableTransformLayer(); spriteWhitening.resize( area.width, area.height ); fheroes2::Copy( _mainSurface, area.x, area.y, spriteWhitening, 0, 0, area.width, area.height ); fheroes2::Image spriteReddish = spriteWhitening; fheroes2::ApplyPalette( spriteReddish, PAL::GetPalette( PAL::PaletteType::RED ) ); cursor.SetThemes( Cursor::WAR_POINTER ); _currentUnit = nullptr; AudioManager::PlaySound( M82::ARMGEDN ); uint32_t alpha = 10; Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && alpha < 100 ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { fheroes2::ApplyPalette( spriteWhitening, 9 ); fheroes2::Copy( spriteWhitening, 0, 0, _mainSurface, area.x, area.y, area.width, area.height ); RedrawPartialFinish(); alpha += 10; } } fheroes2::Copy( spriteReddish, 0, 0, _mainSurface, area.x, area.y, area.width, area.height ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && Mixer::isPlaying( -1 ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { const int32_t offsetX = static_cast( Rand::Get( 0, 28 ) ) - 14; const int32_t offsetY = static_cast( Rand::Get( 0, 22 ) ) - 11; fheroes2::Copy( spriteReddish, std::max( 0, -offsetX ), std::max( 0, -offsetY ), _mainSurface, std::max( 0, offsetX ), std::max( 0, offsetY ), area.width - std::abs( offsetX ), area.height - std::abs( offsetY ) ); RedrawPartialFinish(); } } } void Battle::Interface::redrawActionEarthquakeSpellPart1( const std::vector & targets ) { Cursor::Get().SetThemes( Cursor::WAR_POINTER ); fheroes2::Rect area = GetArea(); area.height -= status.height; // Hide Turn Order for the Earthquake animation original image not to shake it together with the land. Settings & settings = Settings::Get(); const bool isTurnOrderShown = settings.BattleShowTurnOrder(); if ( isTurnOrderShown ) { settings.setBattleShowTurnOrder( false ); } // Set all non-dead troops animation to static and redraw the '_mainSurface'. SwitchAllUnitsAnimation( Monster_Info::STATIC ); RedrawPartialStart(); // Restore the Turn Order rendering if it was enabled. if ( isTurnOrderShown ) { settings.setBattleShowTurnOrder( true ); } fheroes2::Image battlefieldImage; battlefieldImage._disableTransformLayer(); battlefieldImage.resize( area.width, area.height ); fheroes2::Copy( _mainSurface, area.x, area.y, battlefieldImage, area ); _currentUnit = nullptr; AudioManager::PlaySound( M82::ERTHQUAK ); LocalEvent & le = LocalEvent::Get(); uint32_t frame = 0; Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); // Draw earth quake animation. while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && frame < 18 ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { const int32_t offsetX = static_cast( Rand::Get( 0, 28 ) ) - 14; const int32_t offsetY = static_cast( Rand::Get( 0, 22 ) ) - 11; fheroes2::Copy( battlefieldImage, std::max( 0, -offsetX ), std::max( 0, -offsetY ), _mainSurface, std::max( 0, offsetX ), std::max( 0, offsetY ), area.width - std::abs( offsetX ), area.height - std::abs( offsetY ) ); RedrawPartialFinish(); ++frame; } } // draw cloud const int icn = ICN::LICHCLOD; const uint32_t maxFrame = fheroes2::AGG::GetICNCount( icn ) / 2; frame = 0; AudioManager::PlaySound( M82::CATSND02 ); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && frame < maxFrame ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { RedrawPartialStart(); for ( const CastleDefenseStructure target : targets ) { const fheroes2::Point pt2 = Catapult::GetTargetPosition( target, true ); if ( target == CastleDefenseStructure::BRIDGE && frame >= bridgeDestroySmokeDelay ) { // When a bridge is demolished, there is one additional smoke explosion at the point where the bridge falls. const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icn, frame - bridgeDestroySmokeDelay ); fheroes2::Blit( sprite, _mainSurface, pt2.x + bridgeDestroySmokeOffset.x + sprite.x(), pt2.y + bridgeDestroySmokeOffset.y + sprite.y() ); } const fheroes2::Sprite & spriteCloud = fheroes2::AGG::GetICN( icn, frame ); fheroes2::Blit( spriteCloud, _mainSurface, pt2.x + spriteCloud.x(), pt2.y + spriteCloud.y() ); } RedrawPartialFinish(); ++frame; } } } void Battle::Interface::redrawActionEarthquakeSpellPart2( const std::vector & targets ) { Cursor::Get().SetThemes( Cursor::WAR_POINTER ); LocalEvent & le = LocalEvent::Get(); const int icn = ICN::LICHCLOD; uint32_t maxFrame = fheroes2::AGG::GetICNCount( icn ); uint32_t frame = maxFrame / 2; const bool isBridgeDestroyed = std::any_of( targets.begin(), targets.end(), []( const CastleDefenseStructure target ) { return target == CastleDefenseStructure::BRIDGE; } ); if ( isBridgeDestroyed ) { maxFrame += bridgeDestroySmokeDelay - 1; } Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && frame < maxFrame ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { RedrawPartialStart(); for ( const CastleDefenseStructure target : targets ) { const fheroes2::Point pt2 = Catapult::GetTargetPosition( target, true ); if ( target == CastleDefenseStructure::BRIDGE ) { // When a bridge is demolished, there is one additional smoke explosion at the point where the bridge falls. const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icn, frame - bridgeDestroySmokeDelay + 1 ); fheroes2::Blit( sprite, _mainSurface, pt2.x + bridgeDestroySmokeOffset.x + sprite.x(), pt2.y + bridgeDestroySmokeOffset.y + sprite.y() ); } const fheroes2::Sprite & spriteCloud = fheroes2::AGG::GetICN( icn, frame ); fheroes2::Blit( spriteCloud, _mainSurface, pt2.x + spriteCloud.x(), pt2.y + spriteCloud.y() ); } RedrawPartialFinish(); ++frame; } } } void Battle::Interface::RedrawActionRemoveMirrorImage( const std::vector & mirrorImages ) { if ( mirrorImages.empty() ) // nothing to animate return; // Reset the delay to wait till the next frame if is not already waiting. if ( !Game::isDelayNeeded( { Game::DelayType::BATTLE_FRAME_DELAY } ) ) { Game::AnimateResetDelay( Game::DelayType::BATTLE_FRAME_DELAY ); } LocalEvent & le = LocalEvent::Get(); uint8_t frameId = 10; const uint8_t alphaStep = 25; while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_FRAME_DELAY } ) ) && frameId > 0 ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_FRAME_DELAY ) ) { const uint8_t alpha = frameId * alphaStep; for ( Unit * unit : mirrorImages ) { if ( unit != nullptr ) { unit->SetCustomAlpha( alpha ); } } Redraw(); --frameId; } } setStatus( _( "The mirror image is destroyed!" ), true ); } void Battle::Interface::RedrawTargetsWithFrameAnimation( const int32_t dst, const TargetsInfo & targets, const int icn, const int m82, int repeatCount /* = 0 */ ) { LocalEvent & le = LocalEvent::Get(); uint32_t frame = 0; const fheroes2::Rect & center = Board::GetCell( dst )->GetPos(); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); _currentUnit = nullptr; for ( const TargetInfo & target : targets ) { if ( target.defender && target.damage ) { target.defender->SwitchAnimation( Monster_Info::WNCE ); } } AudioManager::PlaySound( m82 ); uint32_t frameCount = fheroes2::AGG::GetICNCount( icn ); Game::passAnimationDelay( Game::BATTLE_SPELL_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && frame < frameCount ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { RedrawPartialStart(); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icn, frame ); fheroes2::Blit( sprite, _mainSurface, center.x + center.width / 2 + sprite.x(), center.y + center.height / 2 + sprite.y() ); RedrawPartialFinish(); for ( const TargetInfo & target : targets ) { if ( target.defender && target.damage ) { target.defender->IncreaseAnimFrame( false ); } } ++frame; if ( frame == frameCount && repeatCount > 0 ) { --repeatCount; frame = 0; } } } for ( const TargetInfo & target : targets ) { if ( target.defender ) { target.defender->SwitchAnimation( Monster_Info::STATIC ); _currentUnit = nullptr; } } } void Battle::Interface::RedrawTargetsWithFrameAnimation( const TargetsInfo & targets, const int icn, const int m82, const bool wnce ) { LocalEvent & le = LocalEvent::Get(); // A vector for creatures made by Mirror Image spell which will be destroyed by current spell. std::vector mirrorImages; Cursor::Get().SetThemes( Cursor::WAR_POINTER ); _currentUnit = nullptr; if ( wnce ) { int32_t deathColor = Color::UNUSED; std::set unitSounds; const auto playSoundIfNotPlaying = [&unitSounds]( const int unitSound ) { const auto [dummy, isUnique] = unitSounds.insert( unitSound ); if ( isUnique ) { AudioManager::PlaySound( unitSound ); } }; for ( const TargetInfo & target : targets ) { Unit * defender = target.defender; if ( defender == nullptr ) { continue; } if ( defender->isModes( CAP_MIRRORIMAGE ) ) { mirrorImages.push_back( defender ); } // If the creature was killed set its death animation. if ( !defender->isValid() ) { // Destroy linked mirror to a dead creature. if ( defender->isModes( CAP_MIRROROWNER ) ) { mirrorImages.push_back( defender->GetMirror() ); } defender->SwitchAnimation( Monster_Info::KILL ); playSoundIfNotPlaying( defender->M82Kill() ); // Set the color of the dead creature to tell heroes about it. deathColor = defender->GetArmyColor(); } // If the creature is damaged but is still alive set its wince animation. else if ( target.damage ) { defender->SwitchAnimation( Monster_Info::WNCE_UP ); playSoundIfNotPlaying( defender->M82Wnce() ); } SetHeroAnimationReactionToTroopDeath( deathColor ); } } // For certain spells reflect the spell sprite if the creature is reflected. const bool isReflectICN = ( icn == ICN::SHIELD || icn == ICN::REDDEATH || icn == ICN::MAGIC08 ); size_t overlaySpriteCount = _unitSpellEffectInfos.size(); _unitSpellEffectInfos.reserve( overlaySpriteCount + targets.size() ); for ( const Battle::TargetInfo & target : targets ) { if ( target.defender ) { _unitSpellEffectInfos.emplace_back( target.defender->GetUID(), icn, ( isReflectICN && target.defender->isReflect() ) ); } } overlaySpriteCount = _unitSpellEffectInfos.size() - overlaySpriteCount; const std::vector::iterator overlaySpriteEnd = _unitSpellEffectInfos.end(); const std::vector::iterator overlaySpriteBegin = overlaySpriteEnd - static_cast( overlaySpriteCount ); // Set the defender wince animation state. bool isDefenderAnimating = wnce; const uint32_t maxFrame = fheroes2::AGG::GetICNCount( icn ); uint32_t frame = 0; // Wait for previously set and not passed delays before rendering a new frame. WaitForAllActionDelays(); AudioManager::PlaySound( m82 ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && ( frame < maxFrame || isDefenderAnimating ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { if ( frame < maxFrame ) { std::vector::iterator overlaySpriteIter = overlaySpriteBegin; const fheroes2::Sprite & spellSprite = fheroes2::AGG::GetICN( icn, frame ); for ( const Battle::TargetInfo & target : targets ) { if ( target.defender ) { overlaySpriteIter->position = CalculateSpellPosition( *target.defender, icn, spellSprite ); overlaySpriteIter->icnIndex = frame; ++overlaySpriteIter; } } } Redraw(); // Reset the defender wince animation state. isDefenderAnimating = false; if ( wnce ) { for ( const TargetInfo & target : targets ) { if ( target.defender == nullptr ) { continue; } // Fully animate creature death. if ( !target.defender->isValid() ) { target.defender->IncreaseAnimFrame( false ); // If the death animation is still in process then set isDefenderAnimating to false. isDefenderAnimating |= !target.defender->isFinishAnimFrame(); } else if ( target.damage ) { // If the target has taken damage and is not killed. // Check if the current animation is not finished. if ( !target.defender->isFinishAnimFrame() ) { target.defender->IncreaseAnimFrame( false ); } else if ( frame >= ( maxFrame - 1 ) && target.defender->GetAnimationState() == Monster_Info::WNCE_UP ) { // If the main spell sprite animation and WNCE_UP are finished then switch unit animation to WNCE_DOWN. target.defender->SwitchAnimation( Monster_Info::WNCE_DOWN ); } else if ( target.defender->GetAnimationState() == Monster_Info::WNCE_DOWN ) { // If the WNCE_DOWN animation is finished, then set STATIC animation to the target. target.defender->SwitchAnimation( Monster_Info::STATIC ); } // If not all damaged (and not killed) units are set to STATIC animation then set isDefenderAnimating to false. // IMPORTANT: The game engine can change STATIC animation to IDLE, especially for Ghosts and Zombies, // so we need to check IDLE where we check for STATIC. const int unitAnimState = target.defender->GetAnimationState(); isDefenderAnimating |= ( unitAnimState != Monster_Info::STATIC ) && ( unitAnimState != Monster_Info::IDLE ); } } } ++frame; // Remove all overlay sprites when the animation is finished. if ( frame == maxFrame ) { _unitSpellEffectInfos.erase( overlaySpriteBegin, overlaySpriteEnd ); } } } // TODO: When there is a need to display some permanent effects with '_unitSpellEffectInfos' - remove this assertion. assert( _unitSpellEffectInfos.empty() ); if ( !mirrorImages.empty() ) { // Fade away animation for destroyed mirror images. RedrawActionRemoveMirrorImage( mirrorImages ); } } void Battle::Interface::RedrawTroopWithFrameAnimation( Unit & unit, const int icn, const int m82, const CreatureSpellAnimation animation ) { LocalEvent & le = LocalEvent::Get(); uint32_t frame = 0; const bool reflect = ( icn == ICN::SHIELD && unit.isReflect() ); Cursor::Get().SetThemes( Cursor::WAR_POINTER ); if ( animation == WINCE ) { _currentUnit = nullptr; unit.SwitchAnimation( Monster_Info::WNCE_UP ); } else if ( animation == RESURRECT ) { _currentUnit = nullptr; unit.SwitchAnimation( Monster_Info::KILL, true ); } _unitSpellEffectInfos.emplace_back( unit.GetUID(), icn, reflect ); // Wait for previously set and not passed delays before rendering a new frame. WaitForAllActionDelays(); const uint32_t maxICNFrame = fheroes2::AGG::GetICNCount( icn ); AudioManager::PlaySound( m82 ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_SPELL_DELAY } ) ) && ( frame < maxICNFrame || unit.GetAnimationState() == Monster_Info::WNCE_DOWN ) ) { CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_SPELL_DELAY ) ) { if ( frame < maxICNFrame ) { _unitSpellEffectInfos.back().position = CalculateSpellPosition( unit, icn, fheroes2::AGG::GetICN( icn, frame ) ); _unitSpellEffectInfos.back().icnIndex = frame; } Redraw(); if ( animation != NONE ) { if ( ( animation == RESURRECT || unit.GetAnimationState() == Monster_Info::WNCE_DOWN ) && unit.isFinishAnimFrame() ) { unit.SwitchAnimation( Monster_Info::STAND_STILL ); } unit.IncreaseAnimFrame( false ); if ( frame == maxICNFrame - 1 && animation == WINCE ) { unit.SwitchAnimation( Monster_Info::WNCE_DOWN ); } } ++frame; if ( frame == maxICNFrame ) { // Spell animation is finished, so delete the overlay sprite from unit. _unitSpellEffectInfos.pop_back(); } } } // TODO: When there is a need to display some permanent effects with '_unitSpellEffectInfos' - remove this assertion. assert( _unitSpellEffectInfos.empty() ); if ( animation != NONE ) { unit.SwitchAnimation( Monster_Info::STATIC ); _currentUnit = nullptr; } } void Battle::Interface::RedrawBridgeAnimation( const bool bridgeDownAnimation ) { // Wait for previously set and not passed delays before rendering a new frame. WaitForAllActionDelays(); LocalEvent & le = LocalEvent::Get(); _bridgeAnimation.animationIsRequired = true; _bridgeAnimation.currentFrameId = bridgeDownAnimation ? BridgeMovementAnimation::UP_POSITION : BridgeMovementAnimation::DOWN_POSITION; if ( bridgeDownAnimation ) AudioManager::PlaySound( M82::DRAWBRG ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::BATTLE_BRIDGE_DELAY } ) ) ) { if ( bridgeDownAnimation ) { if ( _bridgeAnimation.currentFrameId < BridgeMovementAnimation::DOWN_POSITION ) { break; } } else { if ( _bridgeAnimation.currentFrameId > BridgeMovementAnimation::UP_POSITION ) { break; } } CheckGlobalEvents( le ); if ( Game::validateAnimationDelay( Game::BATTLE_BRIDGE_DELAY ) ) { Redraw(); if ( bridgeDownAnimation ) { --_bridgeAnimation.currentFrameId; } else { ++_bridgeAnimation.currentFrameId; } } } _bridgeAnimation.animationIsRequired = false; if ( !bridgeDownAnimation ) { AudioManager::PlaySound( M82::DRAWBRG ); } } bool Battle::Interface::IdleTroopsAnimation() const { if ( Game::validateAnimationDelay( Game::BATTLE_IDLE_DELAY ) ) { const bool redrawNeeded = arena.GetForce1().animateIdleUnits(); return arena.GetForce2().animateIdleUnits() || redrawNeeded; } return false; } void Battle::Interface::ResetIdleTroopAnimation() const { arena.GetForce1().resetIdleAnimation(); arena.GetForce2().resetIdleAnimation(); } void Battle::Interface::SwitchAllUnitsAnimation( const int32_t animationState ) const { for ( Battle::Unit * unit : arena.GetForce1() ) { if ( unit->isValid() ) { unit->SwitchAnimation( animationState ); } } for ( Battle::Unit * unit : arena.GetForce2() ) { if ( unit->isValid() ) { unit->SwitchAnimation( animationState ); } } } void Battle::Interface::CheckGlobalEvents( LocalEvent & le ) { // Animation of the currently active unit's contour if ( Game::validateAnimationDelay( Game::BATTLE_SELECTED_UNIT_DELAY ) ) { UpdateContourColor(); } // Animation of flags and heroes idle. if ( Game::validateAnimationDelay( Game::BATTLE_FLAGS_DELAY ) ) { ++animation_flags_frame; humanturn_redraw = true; // Perform heroes idle animation only if heroes are not performing any other animation (e.g. spell casting). if ( Game::hasEveryDelayPassed( { Game::BATTLE_OPPONENTS_DELAY } ) ) { if ( _opponent1 && _opponent1->updateAnimationState() ) { humanturn_redraw = true; } if ( _opponent2 && _opponent2->updateAnimationState() ) { humanturn_redraw = true; } } } // Check if auto combat interruption was requested. InterruptAutoCombatIfRequested( le ); } void Battle::Interface::InterruptAutoCombatIfRequested( LocalEvent & le ) { // Interrupt only if automation is currently on. if ( !arena.AutoCombatInProgress() && !arena.EnemyOfAIHasAutoCombatInProgress() ) { return; } if ( !le.MouseClickLeft() && !le.MouseClickRight() && !Game::HotKeyPressEvent( Game::HotKeyEvent::BATTLE_TOGGLE_AUTO_COMBAT ) && !Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return; } // Identify which color requested the auto combat interruption. int color = arena.GetCurrentColor(); if ( arena.GetCurrentForce().GetControl() & CONTROL_AI ) { color = arena.GetOppositeColor( color ); } // The battle interruption is already scheduled, no need for the dialog. if ( color == _interruptAutoCombatForColor ) { return; } // Right now there should be no pending auto combat interruptions. assert( _interruptAutoCombatForColor == 0 ); const int interrupt = fheroes2::showStandardTextMessage( {}, _( "Are you sure you want to interrupt the auto combat mode?" ), Dialog::YES | Dialog::NO ); if ( interrupt == Dialog::YES ) { _interruptAutoCombatForColor = color; } } void Battle::Interface::ProcessingHeroDialogResult( const int result, Actions & actions ) { switch ( result ) { // cast case 1: { const HeroBase * hero = _currentUnit->GetCurrentOrArmyCommander(); if ( hero ) { if ( hero->HaveSpellBook() ) { std::string msg; if ( arena.isDisableCastSpell( Spell::NONE, &msg ) ) { fheroes2::showStandardTextMessage( "", msg, Dialog::OK ); } else { const std::function statusCallback = [this]( const std::string & statusStr ) { setStatus( statusStr, false ); status.redraw( fheroes2::Display::instance() ); }; const Spell spell = hero->OpenSpellBook( SpellBook::Filter::CMBT, true, true, statusCallback ); // Reset battlefield grid cursor position after closing the spell book. _curentCellIndex = -1; if ( spell.isValid() ) { assert( spell.isCombat() ); if ( arena.isDisableCastSpell( spell, &msg ) ) { fheroes2::showStandardTextMessage( spell.GetName(), msg, Dialog::OK ); } else { std::string error; if ( hero->CanCastSpell( spell, &error ) ) { if ( spell.isApplyWithoutFocusObject() ) { actions.emplace_back( Command::SPELLCAST, spell.GetID(), -1 ); humanturn_redraw = true; humanturn_exit = true; } else { humanturn_spell = spell; } } else { fheroes2::showStandardTextMessage( _( "Error" ), error, Dialog::OK ); } } } } } else fheroes2::showStandardTextMessage( "", _( "No spells to cast." ), Dialog::OK ); } break; } // retreat case 2: { if ( arena.CanRetreatOpponent( _currentUnit->GetCurrentOrArmyColor() ) ) { if ( Dialog::YES == fheroes2::showStandardTextMessage( "", _( "Are you sure you want to retreat?" ), Dialog::YES | Dialog::NO ) ) { actions.emplace_back( Command::RETREAT ); humanturn_exit = true; } } else { fheroes2::showStandardTextMessage( "", _( "Retreat disabled" ), Dialog::OK ); } break; } // surrender case 3: { if ( arena.CanSurrenderOpponent( _currentUnit->GetCurrentOrArmyColor() ) ) { const HeroBase * enemy = arena.getEnemyCommander( arena.GetCurrentColor() ); if ( enemy ) { const int32_t cost = arena.GetCurrentForce().GetSurrenderCost(); Kingdom & kingdom = world.GetKingdom( arena.GetCurrentColor() ); if ( DialogBattleSurrender( *enemy, cost, kingdom ) ) { actions.emplace_back( Command::SURRENDER ); humanturn_exit = true; } } } else { fheroes2::showStandardTextMessage( "", _( "Surrender disabled" ), Dialog::OK ); } break; } default: break; } } bool Battle::PopupDamageInfo::_setDamageInfoBase( const Unit * defender ) { if ( defender == nullptr || ( defender == _defender ) ) { return false; } if ( !Settings::Get().isBattleShowDamageInfoEnabled() ) { return false; } // When pop-up is hidden: _cell is nullptr. Before showing pop-up if ( _needDelay ) { Game::AnimateResetDelay( Game::BATTLE_POPUP_DELAY ); _needDelay = false; return false; } if ( !Game::hasEveryDelayPassed( { Game::BATTLE_POPUP_DELAY } ) ) { return false; } _defender = defender; return true; } void Battle::PopupDamageInfo::setAttackInfo( const Unit * attacker, const Unit * defender ) { if ( attacker == nullptr || !_setDamageInfoBase( defender ) ) { return; } if ( attacker->Modes( SP_BLESS ) ) { _maxDamage = attacker->CalculateMaxDamage( *defender ); _minDamage = _maxDamage; } else if ( attacker->Modes( SP_CURSE ) ) { _minDamage = attacker->CalculateMinDamage( *defender ); _maxDamage = _minDamage; } else { _minDamage = attacker->CalculateMinDamage( *defender ); _maxDamage = attacker->CalculateMaxDamage( *defender ); } _makeDamageImage(); _redraw = true; } void Battle::PopupDamageInfo::setSpellAttackInfo( const HeroBase * hero, const Unit * defender, const Spell & spell ) { assert( hero != nullptr ); // TODO: Currently, this functionality only supports a simple single-target spell case // We should refactor this to apply to all cases if ( !spell.isSingleTarget() || !spell.isDamage() ) { return; } // If defender unit immune to magic, do not show the tooltip if ( !defender->AllowApplySpell( spell, hero ) ) { return; } if ( !_setDamageInfoBase( defender ) ) { return; } const int spellPoints = hero ? hero->GetPower() : fheroes2::spellPowerForBuiltinMonsterSpells; _minDamage = defender->CalculateSpellDamage( spell, spellPoints, hero, 0, true ); _maxDamage = _minDamage; _makeDamageImage(); _redraw = true; } void Battle::PopupDamageInfo::reset() { if ( !_redraw ) { return; } _redraw = false; _needDelay = true; _defender = nullptr; _damageImage.clear(); } void Battle::PopupDamageInfo::_makeDamageImage() { assert( _defender != nullptr ); std::string str = _minDamage == _maxDamage ? _( "Damage: %{max}" ) : _( "Damage: %{min} - %{max}" ); StringReplace( str, "%{min}", std::to_string( _minDamage ) ); StringReplace( str, "%{max}", std::to_string( _maxDamage ) ); const fheroes2::Text damageText( str, fheroes2::FontType::smallWhite() ); const uint32_t minNumKilled = _defender->HowManyWillBeKilled( _minDamage ); const uint32_t maxNumKilled = _defender->HowManyWillBeKilled( _maxDamage ); assert( minNumKilled <= _defender->GetCount() && maxNumKilled <= _defender->GetCount() ); str = minNumKilled == maxNumKilled ? _( "Perish: %{max}" ) : _( "Perish: %{min} - %{max}" ); StringReplace( str, "%{min}", std::to_string( minNumKilled ) ); StringReplace( str, "%{max}", std::to_string( maxNumKilled ) ); const fheroes2::Text killedText( str, fheroes2::FontType::smallWhite() ); const fheroes2::Rect & unitRect = _defender->GetRectPosition(); // Get the border width and set the popup parameters. const int borderWidth = BorderWidth(); const int x = _battleUIRect.x + unitRect.x + unitRect.width; const int y = _battleUIRect.y + unitRect.y; const int w = std::max( damageText.width(), killedText.width() ) + 2 * borderWidth; const int h = damageText.height() + killedText.height() + 2 * borderWidth; // If the damage info popup doesn't fit the battlefield draw surface, then try to place it on the left side of the cell const bool isLeftSidePopup = ( unitRect.x + unitRect.width + w ) > _battleUIRect.width; const fheroes2::Rect borderRect( isLeftSidePopup ? ( x - w - unitRect.width - borderWidth ) : x, y, w, h ); const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( ICN::CELLWIN, 1 ); _damageImage = fheroes2::Stretch( backgroundImage, 0, 0, backgroundImage.width(), backgroundImage.height(), borderRect.width, borderRect.height ); _damageImage.setPosition( borderRect.x, borderRect.y ); _damageImage._disableTransformLayer(); damageText.draw( borderWidth, borderWidth + 2, _damageImage ); killedText.draw( borderWidth, borderRect.height / 2 + 2, _damageImage ); } void Battle::PopupDamageInfo::redraw() const { if ( !_redraw ) { return; } assert( !_damageImage.empty() ); fheroes2::Copy( _damageImage, 0, 0, fheroes2::Display::instance(), _damageImage.x(), _damageImage.y(), _damageImage.width(), _damageImage.height() ); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_interface.h000066400000000000000000000535771476115357100234310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include "battle_animation.h" #include "battle_board.h" #include "battle_troop.h" #include "cursor.h" #include "dialog.h" #include "icn.h" #include "image.h" #include "math_base.h" #include "screen.h" #include "spell.h" #include "ui_button.h" #include "ui_text.h" class Castle; class HeroBase; class Kingdom; class LocalEvent; namespace fheroes2 { class StandardWindow; } namespace Battle { class Actions; class Arena; class Cell; class Position; class StatusListBox; class Tower; class Units; struct TargetInfo; struct TargetsInfo; enum class CastleDefenseStructure : int; void DialogBattleSettings(); bool DialogBattleSurrender( const HeroBase & hero, uint32_t cost, Kingdom & kingdom ); enum HeroAnimation : uint32_t { OP_JOY, OP_CAST_MASS, OP_CAST_MASS_RETURN, OP_CAST_UP, OP_CAST_UP_RETURN, OP_CAST_DOWN, OP_CAST_DOWN_RETURN, OP_IDLE, OP_IDLE2, OP_STATIC, OP_SORROW }; enum BattleHeroType { KNIGHT, BARBARIAN, SORCERESS, WARLOCK, WIZARD, NECROMANCER, CAPTAIN }; // Sprite data to render over the unit (spell effect animation) struct UnitSpellEffectInfo { UnitSpellEffectInfo( const uint32_t setUnitId, const int32_t setIcnId, const bool setReflectedImage ) : unitId( setUnitId ) , icnId( setIcnId ) , isReflectedImage( setReflectedImage ) {} uint32_t unitId{ 0 }; int32_t icnId{ ICN::UNKNOWN }; uint32_t icnIndex{ 0 }; fheroes2::Point position; bool isReflectedImage{ false }; }; class OpponentSprite { public: OpponentSprite( const fheroes2::Rect & area, HeroBase * hero, const bool isReflect ); OpponentSprite( const OpponentSprite & ) = delete; OpponentSprite & operator=( const OpponentSprite & ) = delete; const fheroes2::Rect & GetArea() const { return _area; } fheroes2::Point GetCastPosition() const; void Redraw( fheroes2::Image & dst ) const; // Return true is animation state was changed. bool updateAnimationState(); void SetAnimation( const int rule ); void IncreaseAnimFrame(); bool isFinishFrame() const { return _currentAnim.isLastFrame(); } HeroBase * GetHero() const { return _heroBase; } fheroes2::Point Offset() const { return _offset; } enum { RIGHT_HERO_X_OFFSET = 29, LEFT_HERO_X_OFFSET = 30, LEFT_HERO_Y_OFFSET = 183, RIGHT_HERO_Y_OFFSET = 148, CAPTAIN_X_OFFSET = 6, CAPTAIN_Y_OFFSET = -13 }; private: HeroBase * _heroBase; AnimationSequence _currentAnim; int _animationType{ OP_STATIC }; RandomizedDelay _idleTimer{ 8000 }; int _heroIcnId{ ICN::UNKNOWN }; bool _isFlippedHorizontally; fheroes2::Rect _area; fheroes2::Point _offset; }; class Status final : public fheroes2::Rect { public: Status(); Status( const Status & ) = delete; ~Status() = default; Status & operator=( const Status & ) = delete; void setPosition( const int32_t cx, const int32_t cy ) { x = cx; y = cy; } void setLogs( StatusListBox * logs ) { _battleStatusLog = logs; } void setMessage( std::string messageString, const bool top ); void redraw( fheroes2::Image & output ) const; const std::string & getMessage() const { return _lastMessage; } void clear(); private: fheroes2::Text _upperText; fheroes2::Text _lowerText; const fheroes2::Sprite & _upperBackground; const fheroes2::Sprite & _lowerBackground; std::string _lastMessage; StatusListBox * _battleStatusLog{ nullptr }; }; class TurnOrder final : public fheroes2::Rect { public: TurnOrder() = default; TurnOrder( const TurnOrder & ) = delete; ~TurnOrder() = default; TurnOrder & operator=( const TurnOrder & ) = delete; void set( const fheroes2::Rect & roi, const std::shared_ptr & units, const int opponentColor ) { _area = roi; _orderOfUnits = units; _opponentColor = opponentColor; } void redraw( const Unit * current, const uint8_t currentUnitColor, fheroes2::Image & output ); void queueEventProcessing( std::string & msg, const fheroes2::Point & offset ) const; private: enum ArmyColor : uint8_t { ARMY_COLOR_BLACK = 0x00, ARMY_COLOR_BLUE = 0x47, ARMY_COLOR_GREEN = 0x67, ARMY_COLOR_RED = 0xbd, ARMY_COLOR_YELLOW = 0x70, ARMY_COLOR_ORANGE = 0xcd, ARMY_COLOR_PURPLE = 0x87, ARMY_COLOR_GRAY = 0x10 }; using UnitPos = std::pair; void _redrawUnit( const fheroes2::Rect & pos, const Battle::Unit & unit, const bool revert, const bool isCurrentUnit, const uint8_t currentUnitColor, fheroes2::Image & output ) const; std::weak_ptr _orderOfUnits; int _opponentColor{ 0 }; fheroes2::Rect _area; std::vector _rects; }; class PopupDamageInfo : public Dialog::FrameBorder { public: PopupDamageInfo() : Dialog::FrameBorder( 5 ) { // Do nothing. } PopupDamageInfo( const PopupDamageInfo & ) = delete; PopupDamageInfo & operator=( const PopupDamageInfo & ) = delete; void setBattleUIRect( const fheroes2::Rect & battleUIRect ) { _battleUIRect = battleUIRect; } void setAttackInfo( const Unit * attacker, const Unit * defender ); void setSpellAttackInfo( const HeroBase * hero, const Unit * defender, const Spell & spell ); void reset(); void redraw() const; private: bool _setDamageInfoBase( const Unit * defender ); void _makeDamageImage(); fheroes2::Sprite _damageImage; fheroes2::Rect _battleUIRect; const Battle::Unit * _defender{ nullptr }; uint32_t _minDamage{ 0 }; uint32_t _maxDamage{ 0 }; bool _redraw{ false }; bool _needDelay{ true }; }; class Interface { public: Interface( Arena & battleArena, const int32_t tileIndex ); Interface( const Interface & ) = delete; ~Interface(); Interface & operator=( const Interface & ) = delete; void fullRedraw(); // only at the start of the battle void Redraw(); void RedrawPartialStart(); void RedrawPartialFinish(); void getPendingActions( Actions & actions ); void HumanTurn( const Unit & unit, Actions & actions ); const fheroes2::Rect & GetArea() const { return _surfaceInnerArea; } // Battlefield interface ROI. const fheroes2::Rect & GetInterfaceRoi() const { return _interfacePosition; } fheroes2::Point getRelativeMouseCursorPos() const; void setStatus( const std::string & message, const bool top ); void SetOrderOfUnits( const std::shared_ptr & units ); void FadeArena( const bool clearMessageLog ); void RedrawActionNewTurn() const; void RedrawActionAttackPart1( Unit & attacker, const Unit & defender, const TargetsInfo & targets ); void RedrawActionAttackPart2( Unit & attacker, const Unit & defender, const TargetsInfo & targets, const uint32_t resurrects ); void RedrawActionSpellCastStatus( const Spell & spell, int32_t dst, const std::string & name, const TargetsInfo & targets ); void RedrawActionSpellCastPart1( const Spell & spell, int32_t dst, const HeroBase * caster, const TargetsInfo & targets ); void RedrawActionSpellCastPart2( const Spell & spell, const TargetsInfo & targets ); void RedrawActionResistSpell( const Unit & target, const bool playSound ); void RedrawActionMonsterSpellCastStatus( const Spell & spell, const Unit & attacker, const TargetInfo & target ); void RedrawActionMove( Unit & unit, const Indexes & path ); void RedrawActionFly( Unit & unit, const Position & pos ); void RedrawActionMorale( Unit & unit, const bool isGoodMorale ); void RedrawActionLuck( const Unit & unit ); void RedrawActionTowerPart1( const Tower & tower, const Unit & defender ); void RedrawActionTowerPart2( const Tower & tower, const TargetInfo & target ); void RedrawActionCatapultPart1( const CastleDefenseStructure catapultTarget, const bool isHit ); void RedrawActionCatapultPart2( const CastleDefenseStructure catapultTarget ); void RedrawActionTeleportSpell( Unit & target, const int32_t dst ); void redrawActionEarthquakeSpellPart1( const std::vector & targets ); void redrawActionEarthquakeSpellPart2( const std::vector & targets ); void RedrawActionSummonElementalSpell( Unit & target ); void RedrawActionMirrorImageSpell( const Unit & target, const Position & pos ); void RedrawActionSkipStatus( const Unit & unit ); void RedrawActionRemoveMirrorImage( const std::vector & mirrorImages ); void RedrawBridgeAnimation( const bool bridgeDownAnimation ); void RedrawMissileAnimation( const fheroes2::Point & startPos, const fheroes2::Point & endPos, const double angle, const uint32_t monsterID ); private: enum CreatureSpellAnimation { NONE, WINCE, RESURRECT }; void HumanBattleTurn( const Unit & unit, Actions & actions, std::string & msg ); void HumanCastSpellTurn( const Unit & /* unused */, Actions & actions, std::string & msg ); void RedrawCover(); void _redrawBattleGround(); void _redrawCoverStatic(); void RedrawLowObjects( const int32_t cellId ); void RedrawHighObjects( const int32_t cellId ); void RedrawCastle( const Castle & castle, const int32_t cellId ); void RedrawCastleMainTower( const Castle & castle ); void RedrawKilled(); void RedrawInterface(); void RedrawOpponents(); void RedrawOpponentsFlags(); void redrawPreRender(); void RedrawArmies(); void RedrawTroopSprite( const Unit & unit ); fheroes2::Point drawTroopSprite( const Unit & unit, const fheroes2::Sprite & troopSprite ); void RedrawTroopCount( const Unit & unit ); void RedrawActionWincesKills( const TargetsInfo & targets, Unit * attacker = nullptr, const Unit * defender = nullptr ); void RedrawActionArrowSpell( const Unit & target ); void RedrawActionColdRaySpell( Unit & target ); void RedrawActionDisruptingRaySpell( const Unit & target ); void RedrawActionBloodLustSpell( const Unit & target ); void RedrawActionStoneSpell( const Unit & target ); void RedrawActionColdRingSpell( const int32_t dst, const TargetsInfo & targets ); void RedrawActionElementalStormSpell( const TargetsInfo & targets ); void RedrawActionArmageddonSpell(); void RedrawActionHolyShoutSpell( const uint8_t strength ); void RedrawActionResurrectSpell( Unit & target, const Spell & spell ); void RedrawActionDeathWaveSpell( const int32_t strength ); void RedrawActionLightningBoltSpell( const Unit & target ); void RedrawActionChainLightningSpell( const TargetsInfo & targets ); void RedrawLightningOnTargets( const std::vector & points, const fheroes2::Rect & drawRoi ); // helper function void RedrawRaySpell( const Unit & target, const int spellICN, const int spellSound, const int32_t size ); // Wait for all possible battlefield action delays that could be set in previous functions to pass. // Use this if a function may be called from other functions with different render delay types. void WaitForAllActionDelays(); void AnimateOpponents( OpponentSprite * hero ); void AnimateUnitWithDelay( Unit & unit, const bool skipLastFrameRender = false ); void RedrawTroopDefaultDelay( Unit & unit ); void RedrawTroopWithFrameAnimation( Unit & unit, const int icn, const int m82, const CreatureSpellAnimation animation ); void RedrawTargetsWithFrameAnimation( const int32_t dst, const TargetsInfo & targets, const int icn, const int m82, int repeatCount = 0 ); void RedrawTargetsWithFrameAnimation( const TargetsInfo & targets, const int icn, const int m82, const bool wnce ); bool IdleTroopsAnimation() const; void ResetIdleTroopAnimation() const; void SwitchAllUnitsAnimation( const int32_t animationState ) const; void UpdateContourColor(); void CheckGlobalEvents( LocalEvent & ); void InterruptAutoCombatIfRequested( LocalEvent & le ); void SetHeroAnimationReactionToTroopDeath( const int32_t deathColor ) const; void ProcessingHeroDialogResult( const int result, Actions & actions ); void _openBattleSettingsDialog(); bool EventStartAutoCombat( const Unit & unit, Actions & actions ); bool EventQuickCombat( Actions & actions ); void OpenAutoModeDialog( const Unit & unit, Actions & actions ); void EventShowOptions(); void MouseLeftClickBoardAction( const int themes, const Cell & cell, const bool isConfirmed, Actions & actions ); void MousePressRightBoardAction( const Cell & cell ) const; int GetBattleCursor( std::string & statusMsg ) const; int GetBattleSpellCursor( std::string & statusMsg ) const; Arena & arena; Dialog::FrameBorder border; fheroes2::Rect _interfacePosition; fheroes2::Rect _surfaceInnerArea{ 0, 0, fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT }; fheroes2::Image _mainSurface; fheroes2::Image _battleGround; fheroes2::Image _hexagonGrid; fheroes2::Image _hexagonShadow; fheroes2::Image _hexagonGridShadow; fheroes2::Image _hexagonCursorShadow; int _battleGroundIcn{ ICN::UNKNOWN }; int _borderObjectsIcn{ ICN::UNKNOWN }; fheroes2::Button _buttonAuto; fheroes2::Button _buttonSettings; fheroes2::Button _buttonSkip; Status status; std::unique_ptr _opponent1; std::unique_ptr _opponent2; Spell humanturn_spell{ Spell::NONE }; bool humanturn_exit{ true }; bool humanturn_redraw{ true }; uint32_t animation_flags_frame{ 0 }; int catapult_frame{ 0 }; int _interruptAutoCombatForColor{ 0 }; // The Channel ID of pre-battle sound. Used to check it is over to start the battle music. std::optional _preBattleSoundChannelId{ -1 }; uint8_t _contourColor{ 110 }; // True if background is bright. It is done to determine current unit contour cycling colors. bool _brightLandType{ false }; uint32_t _contourCycle{ 0 }; const Unit * _currentUnit{ nullptr }; const Unit * _movingUnit{ nullptr }; const Unit * _flyingUnit{ nullptr }; const fheroes2::Sprite * b_current_sprite{ nullptr }; fheroes2::Point _movingPos; fheroes2::Point _flyingPos; int32_t _curentCellIndex{ -1 }; // Index of the cell selected as the source for the Teleport spell int32_t _teleportSpellSrcIdx{ -1 }; fheroes2::Rect _ballistaTowerRect; std::unique_ptr listlog; PopupDamageInfo popup; TurnOrder _turnOrder; std::unique_ptr _background; struct BridgeMovementAnimation { enum AnimationStatusId : uint32_t { DOWN_POSITION = 21, UP_POSITION = 23, DESTROYED = 24 }; bool animationIsRequired; uint32_t currentFrameId; }; BridgeMovementAnimation _bridgeAnimation{ false, BridgeMovementAnimation::UP_POSITION }; struct SwipeAttack { void setSrc( int theme, int32_t index, const Unit * unit ) { currentUnit = unit; srcTheme = theme; srcCellIndex = index; } void setDst( int theme, int32_t index ) { dstTheme = theme; dstCellIndex = index; } bool isValidDestination( int theme, int32_t index ) const { if ( !currentUnit ) { return false; } if ( !Board::isNearIndexes( srcCellIndex, index ) ) { return false; } if ( theme < Cursor::SWORD_TOPRIGHT || theme > Cursor::SWORD_BOTTOM ) { return false; } if ( srcTheme != Cursor::WAR_MOVE && srcTheme != Cursor::WAR_FLY && srcCellIndex != currentUnit->GetHeadIndex() && srcCellIndex != currentUnit->GetTailIndex() ) { return false; } return true; } bool isValid() const { return isValidDestination( dstTheme, dstCellIndex ); } const Unit * currentUnit{ nullptr }; int32_t srcCellIndex{ -1 }; int32_t dstCellIndex{ -1 }; int srcTheme{ Cursor::NONE }; int dstTheme{ Cursor::NONE }; }; SwipeAttack _swipeAttack; // TODO: While currently we don't need to persist 'UnitSpellEffectInfos' between render functions, // this may be needed in the future (for example, in expansion) to display some sprites over // troops for some time (e.g. long duration spell effects or other permanent effects). std::vector _unitSpellEffectInfos; struct BoardActionIntent { int cursorTheme = Cursor::NONE; int32_t cellIndex = -1; bool operator==( const BoardActionIntent & other ) const { return cursorTheme == other.cursorTheme && cellIndex == other.cellIndex; } }; // Intents are used to confirm actions in combat performed using touch gestures BoardActionIntent _boardActionIntent; class BoardActionIntentUpdater { public: BoardActionIntentUpdater( BoardActionIntent & storedIntent, const bool isFromTouchpad ) : _storedIntent( storedIntent ) , _isFromTouchpad( isFromTouchpad ) {} BoardActionIntentUpdater( const BoardActionIntentUpdater & ) = delete; ~BoardActionIntentUpdater() { // Do not remember intermediate touch gestures as intents if ( _isFromTouchpad ) { return; } _storedIntent = _intent.value_or( BoardActionIntent{} ); } BoardActionIntentUpdater & operator=( const BoardActionIntentUpdater & ) = delete; void setIntent( const BoardActionIntent & intent ) { _intent = intent; } bool isConfirmed() { // If the mouse event has been triggered by the touchpad, it should be considered confirmed only if this event orders to // perform the same action that is already indicated on the battle board with the mouse cursor. return ( !_isFromTouchpad || _storedIntent == _intent ); } private: BoardActionIntent & _storedIntent; const bool _isFromTouchpad; std::optional _intent; }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_main.cpp000066400000000000000000000436021476115357100227340ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "ai_planner.h" #include "army.h" #include "army_troop.h" #include "artifact.h" #include "battle.h" // IWYU pragma: associated #include "battle_arena.h" #include "battle_army.h" #include "campaign_savedata.h" #include "captain.h" #include "dialog.h" #include "game.h" #include "heroes.h" #include "heroes_base.h" #include "kingdom.h" #include "logging.h" #include "monster.h" #include "players.h" #include "rand.h" #include "resource.h" #include "settings.h" #include "skill.h" #include "spell.h" #include "spell_storage.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "world.h" namespace { std::vector planArtifactTransfer( const BagArtifacts & winnerBag, const BagArtifacts & loserBag ) { std::vector artifacts; // Calculate how many free slots the winner has in his bag. size_t availableArtifactSlots = 0; for ( const Artifact & artifact : winnerBag ) { if ( !artifact.isValid() ) { ++availableArtifactSlots; } } for ( const Artifact & artifact : loserBag ) { if ( availableArtifactSlots == 0 ) { break; } if ( artifact.isValid() && artifact.GetID() != Artifact::MAGIC_BOOK && !artifact.isUltimate() ) { artifacts.push_back( artifact ); --availableArtifactSlots; } } // One more pass to put all the ultimate artifacts at the end. for ( const Artifact & artifact : loserBag ) { if ( artifact.isUltimate() ) { artifacts.push_back( artifact ); } } return artifacts; } void transferArtifacts( BagArtifacts & winnerBag, const std::vector & artifacts ) { size_t artifactPos = 0; for ( Artifact & artifact : winnerBag ) { if ( artifact.isValid() ) { continue; } for ( ; artifactPos < artifacts.size(); ++artifactPos ) { if ( !artifacts[artifactPos].isUltimate() ) { artifact = artifacts[artifactPos]; ++artifactPos; break; } } if ( artifactPos >= artifacts.size() ) { break; } } } void clearArtifacts( BagArtifacts & bag ) { for ( Artifact & artifact : bag ) { if ( artifact.isValid() && artifact.GetID() != Artifact::MAGIC_BOOK ) { artifact = Artifact::UNKNOWN; } } } uint32_t computeBattleSeed( const int32_t mapIndex, const uint32_t mapSeed, const Army & army1, const Army & army2 ) { uint32_t seed = static_cast( mapIndex ) + mapSeed; for ( size_t i = 0; i < army1.Size(); ++i ) { const Troop * troop = army1.GetTroop( i ); if ( troop->isValid() ) { fheroes2::hashCombine( seed, troop->GetID() ); fheroes2::hashCombine( seed, troop->GetCount() ); } else { fheroes2::hashCombine( seed, 0 ); } } for ( size_t i = 0; i < army2.Size(); ++i ) { const Troop * troop = army2.GetTroop( i ); if ( troop->isValid() ) { fheroes2::hashCombine( seed, troop->GetID() ); fheroes2::hashCombine( seed, troop->GetCount() ); } else { fheroes2::hashCombine( seed, 0 ); } } return seed; } uint32_t getBattleResult( const uint32_t army ) { if ( army & Battle::RESULT_SURRENDER ) return Battle::RESULT_SURRENDER; if ( army & Battle::RESULT_RETREAT ) return Battle::RESULT_RETREAT; if ( army & Battle::RESULT_LOSS ) return Battle::RESULT_LOSS; if ( army & Battle::RESULT_WINS ) return Battle::RESULT_WINS; return 0; } void eagleEyeSkillAction( HeroBase & hero, const SpellStorage & spells, bool local, Rand::DeterministicRandomGenerator & randomGenerator ) { if ( spells.empty() || !hero.HaveSpellBook() ) return; SpellStorage new_spells; new_spells.reserve( 10 ); const Skill::Secondary eagleeye( Skill::Secondary::EAGLE_EYE, hero.GetLevelSkill( Skill::Secondary::EAGLE_EYE ) ); // filter spells for ( const Spell & sp : spells ) { if ( hero.HaveSpell( sp ) ) { continue; } switch ( eagleeye.Level() ) { case Skill::Level::BASIC: // 20% if ( 3 > sp.Level() && eagleeye.GetValue() >= randomGenerator.Get( 1, 100 ) ) new_spells.push_back( sp ); break; case Skill::Level::ADVANCED: // 30% if ( 4 > sp.Level() && eagleeye.GetValue() >= randomGenerator.Get( 1, 100 ) ) new_spells.push_back( sp ); break; case Skill::Level::EXPERT: // 40% if ( 5 > sp.Level() && eagleeye.GetValue() >= randomGenerator.Get( 1, 100 ) ) new_spells.push_back( sp ); break; default: break; } } // add new spell if ( local ) { for ( const Spell & sp : new_spells ) { std::string msg = _( "Through eagle-eyed observation, %{name} is able to learn the magic spell %{spell}." ); StringReplace( msg, "%{name}", hero.GetName() ); StringReplace( msg, "%{spell}", sp.GetName() ); Game::PlayPickupSound(); const fheroes2::SpellDialogElement spellUI( sp, &hero ); fheroes2::showStandardTextMessage( {}, std::move( msg ), Dialog::OK, { &spellUI } ); } } hero.AppendSpellsToBook( new_spells, true ); } void necromancySkillAction( HeroBase & hero, const uint32_t enemyTroopsKilled, const bool isControlHuman ) { Army & army = hero.GetArmy(); if ( 0 == enemyTroopsKilled || ( army.isFullHouse() && !army.HasMonster( Monster::SKELETON ) ) ) return; const uint32_t necromancyPercent = GetNecromancyPercent( hero ); uint32_t raiseCount = std::max( enemyTroopsKilled * necromancyPercent / 100, 1U ); army.JoinTroop( Monster::SKELETON, raiseCount, false ); if ( isControlHuman ) { Battle::Arena::DialogBattleNecromancy( raiseCount ); } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, "raise: " << raiseCount << " skeletons" ) } Kingdom * getKingdomOfCommander( const HeroBase * commander ) { if ( commander == nullptr ) { return nullptr; } if ( commander->isHeroes() ) { const Heroes * hero = dynamic_cast( commander ); assert( hero != nullptr ); return &hero->GetKingdom(); } if ( commander->isCaptain() ) { const Captain * captain = dynamic_cast( commander ); assert( captain != nullptr ); return &world.GetKingdom( captain->GetColor() ); } assert( 0 ); return nullptr; } void restoreFundsOfCommandersKingdom( const HeroBase * commander, const Funds & initialFunds ) { Kingdom * kingdom = getKingdomOfCommander( commander ); assert( kingdom != nullptr ); const Funds fundsDiff = kingdom->GetFunds() - initialFunds; assert( kingdom->AllowPayment( fundsDiff ) ); kingdom->OddFundsResource( fundsDiff ); assert( kingdom->GetFunds() == initialFunds ); } } Battle::Result Battle::Loader( Army & army1, Army & army2, int32_t mapsindex ) { Result result; // Validate the arguments - check if battle should even load if ( !army1.isValid() || !army2.isValid() ) { // Check second army first so attacker would win by default if ( !army2.isValid() ) { result.army1 = RESULT_WINS; DEBUG_LOG( DBG_BATTLE, DBG_WARN, "Invalid battle detected! Index " << mapsindex << ", Army: " << army2.String() ) } else { result.army2 = RESULT_WINS; DEBUG_LOG( DBG_BATTLE, DBG_WARN, "Invalid battle detected! Index " << mapsindex << ", Army: " << army1.String() ) } return result; } HeroBase * commander1 = army1.GetCommander(); if ( commander1 ) { commander1->ActionPreBattle(); if ( army1.isControlAI() ) { AI::Planner::HeroesPreBattle( *commander1, true ); } } const uint32_t initialSpellPoints1 = [commander1]() -> uint32_t { if ( commander1 == nullptr ) { return 0; } return commander1->GetSpellPoints(); }(); const Funds initialFunds1 = [commander1]() -> Funds { const Kingdom * kingdom = getKingdomOfCommander( commander1 ); if ( kingdom == nullptr ) { return {}; } return kingdom->GetFunds(); }(); HeroBase * commander2 = army2.GetCommander(); if ( commander2 ) { commander2->ActionPreBattle(); if ( army2.isControlAI() ) { AI::Planner::HeroesPreBattle( *commander2, false ); } } const uint32_t initialSpellPoints2 = [commander2]() -> uint32_t { if ( commander2 == nullptr ) { return 0; } return commander2->GetSpellPoints(); }(); const Funds initialFunds2 = [commander2]() -> Funds { const Kingdom * kingdom = getKingdomOfCommander( commander2 ); if ( kingdom == nullptr ) { return {}; } return kingdom->GetFunds(); }(); const bool isHumanBattle = army1.isControlHuman() || army2.isControlHuman(); const Settings & conf = Settings::Get(); bool showBattle = !conf.BattleAutoResolve() && isHumanBattle; #ifdef WITH_DEBUG if ( !showBattle ) { // The battle is always shown either in battle debugging mode ... if ( IS_DEBUG( DBG_BATTLE, DBG_TRACE ) ) { showBattle = true; } // ... or when any of the participating human players are controlled by AI else { const Player * player1 = Players::Get( army1.GetColor() ); const Player * player2 = Players::Get( army2.GetColor() ); if ( ( player1 != nullptr && player1->isAIAutoControlMode() ) || ( player2 != nullptr && player2->isAIAutoControlMode() ) ) { showBattle = true; } } } #endif const uint32_t battleSeed = computeBattleSeed( mapsindex, world.GetMapSeed(), army1, army2 ); while ( true ) { Rand::DeterministicRandomGenerator randomGenerator( battleSeed ); Arena arena( army1, army2, mapsindex, showBattle, randomGenerator ); DEBUG_LOG( DBG_BATTLE, DBG_INFO, "army1 " << army1.String() ) DEBUG_LOG( DBG_BATTLE, DBG_INFO, "army2 " << army2.String() ) while ( arena.BattleValid() ) { arena.Turns(); } result = arena.GetResult(); HeroBase * const winnerHero = ( result.army1 & RESULT_WINS ? commander1 : ( result.army2 & RESULT_WINS ? commander2 : nullptr ) ); HeroBase * const loserHero = ( result.army1 & RESULT_LOSS ? commander1 : ( result.army2 & RESULT_LOSS ? commander2 : nullptr ) ); const uint32_t lossResult = result.army1 & RESULT_LOSS ? result.army1 : result.army2; const bool loserAbandoned = !( ( RESULT_RETREAT | RESULT_SURRENDER ) & lossResult ); const std::vector artifactsToTransfer = winnerHero && loserHero && loserAbandoned && winnerHero->isHeroes() && loserHero->isHeroes() ? planArtifactTransfer( winnerHero->GetBagArtifacts(), loserHero->GetBagArtifacts() ) : std::vector(); if ( showBattle ) { const bool clearMessageLog = ( result.army1 & ( RESULT_RETREAT | RESULT_SURRENDER ) ) || ( result.army2 & ( RESULT_RETREAT | RESULT_SURRENDER ) ); arena.FadeArena( clearMessageLog ); } if ( isHumanBattle && arena.DialogBattleSummary( result, artifactsToTransfer, !showBattle ) ) { // If dialog returns true we will restart battle in manual mode showBattle = true; // Reset the state of army commanders and the state of their kingdoms' finances (one of them could spend gold to surrender, and the other could accept this // gold). Please note that heroes can also surrender to castle captains. if ( commander1 ) { commander1->SetSpellPoints( initialSpellPoints1 ); restoreFundsOfCommandersKingdom( commander1, initialFunds1 ); } if ( commander2 ) { commander2->SetSpellPoints( initialSpellPoints2 ); restoreFundsOfCommandersKingdom( commander2, initialFunds2 ); } continue; } if ( loserHero != nullptr && loserAbandoned ) { // If a hero lost the battle and didn't flee or surrender, they lose all artifacts clearArtifacts( loserHero->GetBagArtifacts() ); // If the other army also had a hero, some artifacts may be captured by them if ( winnerHero != nullptr ) { BagArtifacts & bag = winnerHero->GetBagArtifacts(); transferArtifacts( bag, artifactsToTransfer ); const auto assembledArtifacts = bag.assembleArtifactSetIfPossible(); if ( winnerHero->isControlHuman() ) { std::for_each( assembledArtifacts.begin(), assembledArtifacts.end(), Dialog::ArtifactSetAssembled ); } } if ( loserHero->isControlAI() ) { const Heroes * loserAdventureHero = dynamic_cast( loserHero ); if ( loserAdventureHero != nullptr && conf.isCampaignGameType() ) { Campaign::CampaignSaveData::Get().setEnemyDefeatedAward( loserAdventureHero->GetID() ); } } } arena.GetForce1().SyncArmyCount(); arena.GetForce2().SyncArmyCount(); if ( commander1 ) { commander1->ActionAfterBattle(); } if ( commander2 ) { commander2->ActionAfterBattle(); } if ( winnerHero && loserHero && winnerHero->GetLevelSkill( Skill::Secondary::EAGLE_EYE ) && loserHero->isHeroes() ) { eagleEyeSkillAction( *winnerHero, arena.GetUsedSpells(), winnerHero->isControlHuman(), randomGenerator ); } if ( winnerHero && winnerHero->GetLevelSkill( Skill::Secondary::NECROMANCY ) ) { necromancySkillAction( *winnerHero, result.killed, winnerHero->isControlHuman() ); } break; } DEBUG_LOG( DBG_BATTLE, DBG_INFO, "army1 " << army1.String() ) DEBUG_LOG( DBG_BATTLE, DBG_INFO, "army2 " << army2.String() ) army1.resetInvalidMonsters(); army2.resetInvalidMonsters(); // Reset the hero's army to the minimum army if the hero retreated or was defeated if ( commander1 && commander1->isHeroes() && ( !army1.isValid() || ( result.army1 & RESULT_RETREAT ) ) ) { army1.Reset( false ); } if ( commander2 && commander2->isHeroes() && ( !army2.isValid() || ( result.army2 & RESULT_RETREAT ) ) ) { army2.Reset( false ); } DEBUG_LOG( DBG_BATTLE, DBG_INFO, "army1: " << ( result.army1 & RESULT_WINS ? "wins" : "loss" ) << ", army2: " << ( result.army2 & RESULT_WINS ? "wins" : "loss" ) ) return result; } uint32_t Battle::Result::AttackerResult() const { return getBattleResult( army1 ); } uint32_t Battle::Result::DefenderResult() const { return getBattleResult( army2 ); } uint32_t Battle::Result::GetExperienceAttacker() const { return exp1; } uint32_t Battle::Result::GetExperienceDefender() const { return exp2; } bool Battle::Result::AttackerWins() const { return ( army1 & RESULT_WINS ) != 0; } bool Battle::Result::DefenderWins() const { return ( army2 & RESULT_WINS ) != 0; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_only.cpp000066400000000000000000000557471476115357100230060ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2011 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_only.h" #include #include #include #include #include #include #include "agg_image.h" #include "army_bar.h" #include "army_troop.h" #include "battle.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "dialog_selectitems.h" #include "game_hotkeys.h" #include "heroes.h" #include "heroes_base.h" #include "heroes_indicator.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "monster.h" #include "race.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "skill_bar.h" #include "spell_book.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_window.h" #include "world.h" namespace { const std::array playerColor{ Color::BLUE, Color::RED }; const std::array moraleAndLuckOffsetX{ 34, 571 }; const std::array primarySkillOffsetX{ 216, 389 }; const std::array secondarySkillOffsetX{ 22, 353 }; const std::array artifactOffsetX{ 23, 367 }; const std::array armyOffsetX{ 36, 381 }; } void Battle::ControlInfo::Redraw() const { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Sprite & cell = fheroes2::AGG::GetICN( ICN::CELLWIN, 1 ); const fheroes2::Sprite & mark = fheroes2::AGG::GetICN( ICN::CELLWIN, 2 ); fheroes2::Blit( cell, display, rtLocal.x, rtLocal.y ); if ( result & CONTROL_HUMAN ) fheroes2::Blit( mark, display, rtLocal.x + 3, rtLocal.y + 2 ); fheroes2::Text text( _( "Human" ), fheroes2::FontType::smallWhite() ); text.draw( rtLocal.x + cell.width() + 5, rtLocal.y + 5, display ); fheroes2::Blit( cell, display, rtAI.x, rtAI.y ); if ( result & CONTROL_AI ) fheroes2::Blit( mark, display, rtAI.x + 3, rtAI.y + 2 ); text.set( _( "AI" ), fheroes2::FontType::smallWhite() ); text.draw( rtAI.x + cell.width() + 5, rtAI.y + 5, display ); } Battle::Only::Only() { armyInfo[1].armyId = 1; for ( auto & info : armyInfo ) { info.monster.GetTroop( 0 )->Set( Monster::PEASANT, 100 ); info.monsterBackup.Assign( info.monster ); } armyInfo[0].controlType = CONTROL_HUMAN; armyInfo[0].player.SetControl( armyInfo[0].controlType ); armyInfo[0].player.SetColor( playerColor[0] ); armyInfo[1].controlType = CONTROL_AI; armyInfo[1].player.SetControl( armyInfo[1].controlType ); armyInfo[1].player.SetColor( playerColor[1] ); } bool Battle::Only::setup( const bool allowBackup, bool & reset ) { reset = false; fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::StandardWindow frameborder( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, false ); const fheroes2::Point cur_pt( frameborder.activeArea().x, frameborder.activeArea().y ); armyInfo[0].portraitRoi = { cur_pt.x + 93, cur_pt.y + 72, 101, 93 }; armyInfo[1].portraitRoi = { cur_pt.x + 445, cur_pt.y + 72, 101, 93 }; armyInfo[0].player.SetControl( armyInfo[0].controlType ); armyInfo[1].player.SetControl( armyInfo[1].controlType ); for ( auto & info : armyInfo ) { info.hero = nullptr; info.monster.Reset(); info.monster.GetTroop( 0 )->Set( Monster::PEASANT, 100 ); if ( !_backupCompleted || !allowBackup ) { continue; } if ( info.isHeroPresent ) { info.hero = world.GetHeroes( info.heroBackup.GetID() ); info.hero->GetSecondarySkills().FillMax( Skill::Secondary() ); copyHero( info.heroBackup, *info.hero ); } else { info.monster.Assign( info.monsterBackup ); } } if ( !_backupCompleted || !allowBackup ) { armyInfo[0].hero = world.GetHeroes( Heroes::LORDKILBURN ); armyInfo[0].isHeroPresent = true; } const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); fheroes2::Copy( background, 0, 0, display, cur_pt.x, cur_pt.y, background.width(), background.height() ); redrawOpponents( cur_pt ); redrawOpponentsStats( cur_pt ); for ( auto & info : armyInfo ) { if ( info.hero != nullptr ) { info.hero->GetSecondarySkills().FillMax( Skill::Secondary() ); updateHero( info, cur_pt ); } else { info.ui.army = std::make_unique( &info.monster, true, false, true ); info.ui.army->setTableSize( { 5, 1 } ); info.ui.army->setRenderingOffset( { cur_pt.x + armyOffsetX[info.armyId], cur_pt.y + 267 } ); info.ui.army->setInBetweenItemsOffset( { 2, 0 } ); } } if ( armyInfo[1].hero != nullptr ) { attackedArmyControlInfo = std::make_unique( fheroes2::Point{ cur_pt.x + 500, cur_pt.y + 425 }, armyInfo[1].player.GetControl() ); } for ( const auto & info : armyInfo ) { info.ui.redraw( display ); } if ( attackedArmyControlInfo ) { attackedArmyControlInfo->Redraw(); } // hide the swap army/artifact arrows const fheroes2::Sprite & stoneBackground = fheroes2::AGG::GetICN( ICN::STONEBAK, 0 ); fheroes2::Copy( stoneBackground, 292, 270, display, cur_pt.x + 292, cur_pt.y + 270, 48, 44 ); fheroes2::Copy( stoneBackground, 292, 363, display, cur_pt.x + 292, cur_pt.y + 363, 48, 44 ); // hide the shadow from the original EXIT button const fheroes2::Sprite buttonOverride = fheroes2::Crop( fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ), 122, 428, 84, 32 ); fheroes2::Copy( buttonOverride, 0, 0, display, cur_pt.x + 276, cur_pt.y + 428, 84, 32 ); fheroes2::Button buttonReset( cur_pt.x + 30, cur_pt.y + 428, ICN::BUTTON_RESET_GOOD, 0, 1 ); fheroes2::Button buttonStart( cur_pt.x + 178, cur_pt.y + 428, ICN::BUTTON_START_GOOD, 0, 1 ); fheroes2::Button buttonExit( cur_pt.x + 366, cur_pt.y + 428, ICN::BUTTON_EXIT_GOOD, 0, 1 ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( ICN::BUTTON_RESET_GOOD, 0 ), display, buttonReset.area().getPosition(), { -5, 5 } ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( ICN::BUTTON_START_GOOD, 0 ), display, buttonStart.area().getPosition(), { -5, 5 } ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( ICN::BUTTON_EXIT_GOOD, 0 ), display, buttonExit.area().getPosition(), { -5, 5 } ); buttonStart.draw(); buttonExit.draw(); buttonReset.draw(); display.render(); bool result = false; while ( le.HandleEvents() ) { bool updateSpellPoints = false; bool needRender = false; bool needRedrawOpponentsStats = false; bool needRedrawControlInfo = false; if ( buttonStart.isEnabled() ) { buttonStart.drawOnState( le.isMouseLeftButtonPressedInArea( buttonStart.area() ) ); } if ( buttonExit.isEnabled() ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); } if ( buttonReset.isEnabled() ) { buttonReset.drawOnState( le.isMouseLeftButtonPressedInArea( buttonReset.area() ) ); } if ( ( buttonStart.isEnabled() && le.MouseClickLeft( buttonStart.area() ) ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) { result = true; break; } if ( le.MouseClickLeft( buttonReset.area() ) ) { reset = true; result = true; break; } if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { break; } if ( le.isMouseRightButtonPressedInArea( buttonStart.area() ) ) { fheroes2::showStandardTextMessage( _( "Start" ), _( "Start the battle." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonReset.area() ) ) { fheroes2::showStandardTextMessage( _( "Reset" ), _( "Reset to default settings." ), 0 ); } for ( const auto & [firstId, secondId] : { std::pair( 0, 1 ), std::pair( 1, 0 ) } ) { ArmyInfo & first = armyInfo[firstId]; const ArmyInfo & second = armyInfo[secondId]; if ( le.MouseClickLeft( first.portraitRoi ) ) { const int hid = Dialog::selectHeroes( first.hero ? first.hero->GetID() : Heroes::UNKNOWN ); if ( second.hero && hid == second.hero->GetID() ) { fheroes2::showStandardTextMessage( _( "Error" ), _( "Please select another hero." ), Dialog::OK ); } else if ( Heroes::UNKNOWN != hid ) { first.hero = world.GetHeroes( hid ); if ( first.hero ) { first.hero->GetSecondarySkills().FillMax( Skill::Secondary() ); } updateHero( first, cur_pt ); } redrawOpponents( cur_pt ); first.needRedraw = true; needRedrawOpponentsStats = true; // User can not click two hero portraits at the same time so we can break the loop. break; } } if ( attackedArmyControlInfo == nullptr && armyInfo[1].hero != nullptr ) { attackedArmyControlInfo = std::make_unique( fheroes2::Point{ cur_pt.x + 500, cur_pt.y + 425 }, armyInfo[1].player.GetControl() ); needRedrawControlInfo = true; } for ( const auto & [firstId, secondId] : { std::pair{ 0, 1 }, std::pair{ 1, 0 } } ) { const ArmyUI & firstUI = armyInfo[firstId].ui; const ArmyUI & secondUI = armyInfo[secondId].ui; if ( firstUI.army != nullptr && le.isMouseCursorPosInArea( firstUI.army->GetArea() ) && firstUI.army->QueueEventProcessing() ) { if ( firstUI.artifact != nullptr && firstUI.artifact->isSelected() ) { firstUI.artifact->ResetSelected(); } if ( secondUI.artifact != nullptr && secondUI.artifact->isSelected() ) { secondUI.artifact->ResetSelected(); } if ( secondUI.army != nullptr && secondUI.army->isSelected() ) { secondUI.army->ResetSelected(); } armyInfo[firstId].needRedraw = true; } else if ( firstUI.artifact != nullptr && le.isMouseCursorPosInArea( firstUI.artifact->GetArea() ) && firstUI.artifact->QueueEventProcessing() ) { if ( firstUI.army != nullptr && firstUI.army->isSelected() ) { firstUI.army->ResetSelected(); } if ( secondUI.artifact != nullptr && secondUI.artifact->isSelected() ) { secondUI.artifact->ResetSelected(); } if ( secondUI.army != nullptr && secondUI.army->isSelected() ) { secondUI.army->ResetSelected(); } armyInfo[firstId].needRedraw = true; updateSpellPoints = true; needRedrawOpponentsStats = true; } else if ( firstUI.morale != nullptr && le.isMouseCursorPosInArea( firstUI.morale->GetArea() ) ) { MoraleIndicator::QueueEventProcessing( *firstUI.morale ); } else if ( firstUI.luck != nullptr && le.isMouseCursorPosInArea( firstUI.luck->GetArea() ) ) { LuckIndicator::QueueEventProcessing( *firstUI.luck ); } else if ( firstUI.primarySkill != nullptr && le.isMouseCursorPosInArea( firstUI.primarySkill->GetArea() ) ) { if ( firstUI.primarySkill->QueueEventProcessing() ) { updateSpellPoints = true; needRedrawOpponentsStats = true; } } else if ( firstUI.secondarySkill != nullptr && le.isMouseCursorPosInArea( firstUI.secondarySkill->GetArea() ) && firstUI.secondarySkill->QueueEventProcessing() ) { armyInfo[firstId].needRedraw = true; } } if ( attackedArmyControlInfo ) { assert( armyInfo[1].hero ); if ( le.MouseClickLeft( attackedArmyControlInfo->rtLocal ) && armyInfo[1].player.isControlAI() ) { attackedArmyControlInfo->result = CONTROL_HUMAN; armyInfo[1].player.SetControl( CONTROL_HUMAN ); needRedrawControlInfo = true; } else if ( le.MouseClickLeft( attackedArmyControlInfo->rtAI ) && armyInfo[1].player.isControlHuman() ) { attackedArmyControlInfo->result = CONTROL_AI; armyInfo[1].player.SetControl( CONTROL_AI ); needRedrawControlInfo = true; } } if ( updateSpellPoints ) { for ( Heroes * hero : { armyInfo[0].hero, armyInfo[1].hero } ) { if ( hero == nullptr ) { continue; } hero->SetSpellPoints( hero->GetMaxSpellPoints() ); } } if ( needRedrawOpponentsStats ) { redrawOpponentsStats( cur_pt ); needRender = true; } for ( const int32_t i : { 0, 1 } ) { if ( armyInfo[i].needRedraw ) { armyInfo[i].ui.redraw( display ); armyInfo[i].needRedraw = false; needRender = true; } } if ( needRedrawControlInfo ) { assert( attackedArmyControlInfo != nullptr ); attackedArmyControlInfo->Redraw(); needRender = true; } if ( needRender ) { display.render(); } } armyInfo[0].ui = {}; armyInfo[1].ui = {}; attackedArmyControlInfo.reset(); return result; } void Battle::Only::updateHero( ArmyInfo & info, const fheroes2::Point & offset ) { info.ui.resetForNewHero(); if ( info.hero == nullptr ) { return; } updateArmyUI( info.ui, info.hero, offset, info.armyId ); } void Battle::Only::redrawOpponents( const fheroes2::Point & top ) const { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); const fheroes2::Rect textRoi( top.x + 89, top.y + 27, 462, 17 ); fheroes2::Copy( background, 89, 27, display, textRoi ); std::string message = _( "%{race1} %{name1} vs %{race2} %{name2}" ); if ( armyInfo[0].hero ) { StringReplace( message, "%{name1}", armyInfo[0].hero->GetName() ); StringReplace( message, "%{race1}", std::string( Race::String( armyInfo[0].hero->GetRace() ) ) ); } else { StringReplace( message, "%{race1}", "" ); StringReplace( message, " %{name1}", _( "Monsters" ) ); } if ( armyInfo[1].hero ) { StringReplace( message, "%{name2}", armyInfo[1].hero->GetName() ); StringReplace( message, "%{race2}", std::string( Race::String( armyInfo[1].hero->GetRace() ) ) ); } else { StringReplace( message, "%{race2}", "" ); StringReplace( message, " %{name2}", _( "Monsters" ) ); } fheroes2::Text text( std::move( message ), fheroes2::FontType::normalWhite() ); text.drawInRoi( top.x + 320 - text.width() / 2, top.y + 29, display, textRoi ); for ( const size_t idx : { 0, 1 } ) { if ( armyInfo[idx].hero ) { const fheroes2::Sprite & port1 = armyInfo[idx].hero->GetPortrait( PORT_BIG ); if ( !port1.empty() ) { fheroes2::Copy( port1, 0, 0, display, armyInfo[idx].portraitRoi ); } } else { fheroes2::Fill( display, armyInfo[idx].portraitRoi.x, armyInfo[idx].portraitRoi.y, armyInfo[idx].portraitRoi.width, armyInfo[idx].portraitRoi.height, 0 ); text.set( _( "N/A" ), fheroes2::FontType::normalWhite() ); text.draw( armyInfo[idx].portraitRoi.x + ( armyInfo[idx].portraitRoi.width - text.width() ) / 2, armyInfo[idx].portraitRoi.y + armyInfo[idx].portraitRoi.height / 2 - 8, display ); } } } void Battle::Only::redrawOpponentsStats( const fheroes2::Point & top ) const { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); fheroes2::Copy( background, 262, 61, display, top.x + 262, top.y + 61, 115, 109 ); fheroes2::RedrawPrimarySkillInfo( top, armyInfo[0].ui.primarySkill.get(), armyInfo[1].ui.primarySkill.get() ); } void Battle::Only::StartBattle() { assert( armyInfo[0].hero != nullptr ); Settings & conf = Settings::Get(); conf.GetPlayers().Init( armyInfo[0].player.GetColor() | armyInfo[1].player.GetColor() ); world.InitKingdoms(); conf.SetCurrentColor( armyInfo[0].player.GetColor() ); for ( const int32_t idx : { 0, 1 } ) { Players::SetPlayerRace( armyInfo[idx].player.GetColor(), armyInfo[idx].player.GetRace() ); Players::SetPlayerControl( armyInfo[idx].player.GetColor(), armyInfo[idx].player.GetControl() ); armyInfo[idx].controlType = armyInfo[idx].player.GetControl(); armyInfo[idx].isHeroPresent = ( armyInfo[idx].hero != nullptr ); if ( !armyInfo[idx].isHeroPresent ) { armyInfo[idx].monsterBackup.Assign( armyInfo[idx].monster ); continue; } armyInfo[idx].hero->SetSpellPoints( armyInfo[idx].hero->GetMaxSpellPoints() ); armyInfo[idx].hero->Recruit( armyInfo[idx].player.GetColor(), { idx, idx } ); copyHero( *armyInfo[idx].hero, armyInfo[idx].heroBackup ); armyInfo[idx].monster.Reset(); armyInfo[idx].monster.GetTroop( 0 )->Set( Monster::PEASANT, 100 ); armyInfo[idx].monsterBackup.Assign( armyInfo[idx].monster ); } _backupCompleted = true; Battle::Loader( ( armyInfo[0].hero ? armyInfo[0].hero->GetArmy() : armyInfo[0].monster ), ( armyInfo[1].hero ? armyInfo[1].hero->GetArmy() : armyInfo[1].monster ), 1 ); conf.SetCurrentColor( Color::NONE ); } void Battle::Only::reset() { armyInfo[0].reset(); armyInfo[1].reset(); attackedArmyControlInfo.reset(); } void Battle::Only::copyHero( const Heroes & in, Heroes & out ) { out.attack = in.attack; out.defense = in.defense; out.knowledge = in.knowledge; out.power = in.power; out._id = in._id; out.portrait = in.portrait; out._race = in._race; out.secondary_skills.ToVector() = in.secondary_skills.ToVector(); out.army.Assign( in.army ); out.bag_artifacts = in.bag_artifacts; out.spell_book = in.spell_book; out.SetSpellPoints( out.GetMaxSpellPoints() ); } void Battle::Only::updateArmyUI( ArmyUI & ui, Heroes * hero, const fheroes2::Point & offset, const uint8_t armyId ) { assert( hero != nullptr ); ui.morale = std::make_unique( hero ); ui.morale->SetPos( { offset.x + moraleAndLuckOffsetX[armyId], offset.y + 75 } ); ui.luck = std::make_unique( hero ); ui.luck->SetPos( { offset.x + moraleAndLuckOffsetX[armyId], offset.y + 115 } ); ui.primarySkill = std::make_unique( hero, true, true, false ); ui.primarySkill->setTableSize( { 1, 4 } ); ui.primarySkill->setInBetweenItemsOffset( { 0, -1 } ); ui.primarySkill->SetTextOff( armyId == 0 ? 70 : -70, -25 ); ui.primarySkill->setRenderingOffset( { offset.x + primarySkillOffsetX[armyId], offset.y + 51 } ); ui.secondarySkill = std::make_unique( *hero, true, true ); ui.secondarySkill->setTableSize( { 8, 1 } ); ui.secondarySkill->setInBetweenItemsOffset( { -1, 0 } ); ui.secondarySkill->SetContent( hero->GetSecondarySkills().ToVector() ); ui.secondarySkill->setRenderingOffset( { offset.x + secondarySkillOffsetX[armyId], offset.y + 199 } ); ui.artifact = std::make_unique( hero, true, false, true, true, nullptr ); ui.artifact->setTableSize( { 7, 2 } ); ui.artifact->setInBetweenItemsOffset( { 2, 2 } ); ui.artifact->SetContent( hero->GetBagArtifacts() ); ui.artifact->setRenderingOffset( { offset.x + artifactOffsetX[armyId], offset.y + 347 } ); ui.army = std::make_unique( &hero->GetArmy(), true, false, true ); ui.army->setTableSize( { 5, 1 } ); ui.army->setRenderingOffset( { offset.x + armyOffsetX[armyId], offset.y + 267 } ); ui.army->setInBetweenItemsOffset( { 2, 0 } ); } void Battle::Only::ArmyUI::redraw( fheroes2::Image & output ) const { if ( morale ) { morale->Redraw(); } if ( luck ) { luck->Redraw(); } if ( primarySkill ) { primarySkill->Redraw( output ); } if ( secondarySkill ) { secondarySkill->Redraw( output ); } if ( artifact ) { artifact->Redraw( output ); } if ( army ) { army->Redraw( output ); } } void Battle::Only::ArmyUI::resetForNewHero() { if ( morale ) { morale->redrawOnlyBackground(); } if ( luck ) { luck->redrawOnlyBackground(); } *this = {}; } void Battle::Only::ArmyInfo::reset() { ui = {}; hero = nullptr; monster.Reset(); monster.GetTroop( 0 )->Set( Monster::PEASANT, 100 ); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_only.h000066400000000000000000000104121476115357100224270ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "army.h" #include "army_bar.h" #include "artifact.h" #include "heroes.h" #include "heroes_indicator.h" #include "math_base.h" #include "players.h" #include "skill_bar.h" namespace fheroes2 { class Image; } namespace Battle { struct ControlInfo { ControlInfo( const fheroes2::Point & pt, int ctrl ) : result( ctrl ) , rtLocal( pt.x, pt.y, 24, 24 ) , rtAI( pt.x + 75, pt.y, 24, 24 ) { // Do nothing. } ControlInfo( const ControlInfo & ) = delete; ControlInfo & operator=( const ControlInfo & ) = delete; void Redraw() const; int result; const fheroes2::Rect rtLocal; const fheroes2::Rect rtAI; }; class Only { public: Only(); Only( const Only & ) = delete; Only & operator=( const Only & ) = delete; bool setup( const bool allowBackup, bool & reset ); void StartBattle(); void reset(); private: struct ArmyUI { std::unique_ptr morale; std::unique_ptr luck; std::unique_ptr primarySkill; std::unique_ptr secondarySkill; std::unique_ptr artifact; std::unique_ptr army; void redraw( fheroes2::Image & output ) const; // Resets the state to empty and removes the morale & luck indicators from the screen void resetForNewHero(); }; struct ArmyInfo { Heroes * hero{ nullptr }; Player player; int controlType{ CONTROL_HUMAN }; Army monster; Heroes heroBackup; Army monsterBackup; bool isHeroPresent{ false }; ArmyUI ui; fheroes2::Rect portraitRoi; uint8_t armyId{ 0 }; bool needRedraw{ false }; void reset(); }; std::array armyInfo; std::unique_ptr attackedArmyControlInfo; bool _backupCompleted{ false }; void redrawOpponents( const fheroes2::Point & top ) const; void redrawOpponentsStats( const fheroes2::Point & top ) const; static void updateHero( ArmyInfo & info, const fheroes2::Point & offset ); static void updateArmyUI( ArmyUI & ui, Heroes * hero, const fheroes2::Point & offset, const uint8_t armyId ); static void copyHero( const Heroes & in, Heroes & out ); }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_pathfinding.cpp000066400000000000000000000415331476115357100243040ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_pathfinding.h" #include #include #include #include #include #include #include #include #include "battle_arena.h" #include "battle_cell.h" #include "battle_troop.h" #include "castle.h" #include "speed.h" namespace { const uint32_t MOAT_PENALTY = UINT16_MAX; } namespace Battle { void BattlePathfinder::reEvaluateIfNeeded( const Unit & unit ) { assert( unit.GetHeadIndex() != -1 && ( unit.isWide() ? unit.GetTailIndex() != -1 : unit.GetTailIndex() == -1 ) ); const Board * board = Arena::GetBoard(); assert( board != nullptr ); // Passability of the board cells can change during the unit's turn even without its intervention (for example, because of a hero's spell cast), // we need to keep track of this std::array boardStatus{}; for ( const Cell & cell : *board ) { const int32_t cellIdx = cell.GetIndex(); assert( Board::isValidIndex( cellIdx ) ); boardStatus[cellIdx] = cell.isPassable( true ); } auto currentSettings = std::tie( _pathStart, _speed, _isWide, _isFlying, _color, _boardStatus ); const auto newSettings = std::make_tuple( BattleNodeIndex{ unit.GetHeadIndex(), unit.GetTailIndex() }, unit.GetSpeed(), unit.isWide(), unit.isFlying(), unit.GetColor(), std::cref( boardStatus ) ); // If all the current parameters match the parameters for which the current cache was built, then there is no need to rebuild it if ( currentSettings == newSettings ) { return; } currentSettings = newSettings; const Castle * castle = Arena::GetCastle(); const bool isMoatBuilt = castle && castle->isBuild( BUILD_MOAT ); _cache.clear(); _cache.try_emplace( _pathStart ); // Flying units can land wherever they can fit if ( _isFlying ) { for ( const Cell & cell : *board ) { const Position pos = Position::GetPosition( unit, cell.GetIndex() ); if ( pos.GetHead() == nullptr ) { continue; } assert( pos.isValidForUnit( unit ) ); const int32_t headCellIdx = pos.GetHead()->GetIndex(); const int32_t tailCellIdx = pos.GetTail() ? pos.GetTail()->GetIndex() : -1; if ( const auto [iter, inserted] = _cache.try_emplace( { headCellIdx, tailCellIdx } ); inserted ) { // Wide units can occupy overlapping positions, the distance between which is actually zero, // but since the movement takes place, we will consider the distance equal to 1 in this case const uint32_t distance = std::max( Board::GetDistance( unit.GetPosition(), pos ), 1U ); iter->second.update( _pathStart, 1, distance ); } } return; } // The index of that of the cells of the initial unit's position, which is located // in the moat (-1, if there is none) const int32_t pathStartMoatCellIdx = [this, &unit, isMoatBuilt]() { if ( !isMoatBuilt ) { return -1; } assert( _pathStart.first != -1 ); if ( Board::isMoatIndex( _pathStart.first, unit ) ) { return _pathStart.first; } if ( _isWide ) { assert( _pathStart.second != -1 ); if ( Board::isMoatIndex( _pathStart.second, unit ) ) { return _pathStart.second; } } return -1; }(); std::vector nodesToExplore; nodesToExplore.reserve( Board::sizeInCells * 2 ); nodesToExplore.push_back( _pathStart ); for ( size_t nodesToExploreIdx = 0; nodesToExploreIdx < nodesToExplore.size(); ++nodesToExploreIdx ) { const BattleNodeIndex currentNodeIdx = nodesToExplore[nodesToExploreIdx]; const BattleNode & currentNode = _cache[currentNodeIdx]; if ( _isWide ) { assert( currentNodeIdx.first != -1 && currentNodeIdx.second != -1 ); const auto [currentHeadCellIdx, currentTailCellIdx] = currentNodeIdx; const BattleNodeIndex flippedCurrentNodeIdx = { currentTailCellIdx, currentHeadCellIdx }; const Cell * currentHeadCell = Board::GetCell( currentHeadCellIdx ); assert( currentHeadCell != nullptr ); const bool isCurrentLeftDirection = ( ( Board::GetDirection( currentTailCellIdx, currentHeadCellIdx ) & LEFT_SIDE ) != 0 ); // The moat restrictions can be ignored if the wide unit originally occupied a moat cell, and at the current step any part // of this unit occupies the same moat cell const bool isIgnoreMoat = ( currentHeadCellIdx == pathStartMoatCellIdx || currentTailCellIdx == pathStartMoatCellIdx ); const bool isInMoat = isMoatBuilt && ( Board::isMoatIndex( currentHeadCellIdx, unit ) || Board::isMoatIndex( currentTailCellIdx, unit ) ); const uint32_t movementPenalty = ( !isIgnoreMoat && isInMoat ) ? MOAT_PENALTY : 1; for ( const int32_t headCellIdx : Board::GetMoveWideIndexes( currentHeadCellIdx, isCurrentLeftDirection ) ) { const Cell * cell = Board::GetCell( headCellIdx ); assert( cell != nullptr ); if ( !cell->isPassableFromAdjacent( unit, *currentHeadCell ) ) { continue; } const int32_t tailCellIdx = ( Board::GetDirection( currentHeadCellIdx, headCellIdx ) & LEFT_SIDE ) ? headCellIdx + 1 : headCellIdx - 1; const BattleNodeIndex newNodeIdx = { headCellIdx, tailCellIdx }; if ( newNodeIdx == _pathStart ) { continue; } // Reversal is not a movement const uint32_t cost = currentNode._cost + ( newNodeIdx == flippedCurrentNodeIdx ? 0 : movementPenalty ); const uint32_t distance = currentNode._distance + ( newNodeIdx == flippedCurrentNodeIdx ? 0 : 1 ); BattleNode & newNode = _cache[newNodeIdx]; if ( newNode._from == BattleNodeIndex{ -1, -1 } || newNode._cost > cost ) { newNode.update( currentNodeIdx, cost, distance ); nodesToExplore.push_back( newNodeIdx ); } } } else { assert( currentNodeIdx.first != -1 && currentNodeIdx.second == -1 ); const auto [currentCellIdx, dummy] = currentNodeIdx; const Cell * currentCell = Board::GetCell( currentCellIdx ); assert( currentCell != nullptr ); // The moat restrictions can be ignored at the first step if the unit starts its movement from the moat const bool isIgnoreMoat = ( currentCellIdx == pathStartMoatCellIdx ); const bool isInMoat = isMoatBuilt && Board::isMoatIndex( currentCellIdx, unit ); const uint32_t movementPenalty = ( !isIgnoreMoat && isInMoat ) ? MOAT_PENALTY : 1; for ( const int32_t cellIdx : Board::GetAroundIndexes( currentCellIdx ) ) { const Cell * cell = Board::GetCell( cellIdx ); assert( cell != nullptr ); if ( !cell->isPassableFromAdjacent( unit, *currentCell ) ) { continue; } const BattleNodeIndex newNodeIdx = { cellIdx, -1 }; if ( newNodeIdx == _pathStart ) { continue; } const uint32_t cost = currentNode._cost + movementPenalty; const uint32_t distance = currentNode._distance + 1; BattleNode & newNode = _cache[newNodeIdx]; if ( newNode._from == BattleNodeIndex{ -1, -1 } || newNode._cost > cost ) { newNode.update( currentNodeIdx, cost, distance ); nodesToExplore.push_back( newNodeIdx ); } } } } } bool BattlePathfinder::isPositionReachable( const Unit & unit, const Position & position, const bool isOnCurrentTurn ) { // Invalid positions are allowed here, but they are always unreachable if ( position.GetHead() == nullptr ) { return false; } reEvaluateIfNeeded( unit ); const BattleNodeIndex nodeIdx = { position.GetHead()->GetIndex(), position.GetTail() ? position.GetTail()->GetIndex() : -1 }; const auto iter = _cache.find( nodeIdx ); if ( iter == _cache.end() ) { return false; } const auto & [index, node] = *iter; return ( index == _pathStart || node._from != BattleNodeIndex{ -1, -1 } ) && ( !isOnCurrentTurn || node._cost <= _speed ); } uint32_t BattlePathfinder::getCost( const Unit & unit, const Position & position ) { assert( position.GetHead() != nullptr ); reEvaluateIfNeeded( unit ); const BattleNodeIndex nodeIdx = { position.GetHead()->GetIndex(), position.GetTail() ? position.GetTail()->GetIndex() : -1 }; const auto iter = _cache.find( nodeIdx ); assert( iter != _cache.end() ); const auto & [index, node] = *iter; // MSVC 2017 fails to properly expand the assert() macro without additional parentheses assert( ( index == _pathStart || node._from != BattleNodeIndex{ -1, -1 } ) ); return node._cost; } uint32_t BattlePathfinder::getDistance( const Unit & unit, const Position & position ) { assert( position.GetHead() != nullptr ); reEvaluateIfNeeded( unit ); const BattleNodeIndex nodeIdx = { position.GetHead()->GetIndex(), position.GetTail() ? position.GetTail()->GetIndex() : -1 }; const auto iter = _cache.find( nodeIdx ); assert( iter != _cache.end() ); const auto & [index, node] = *iter; // MSVC 2017 fails to properly expand the assert() macro without additional parentheses assert( ( index == _pathStart || node._from != BattleNodeIndex{ -1, -1 } ) ); return node._distance; } Indexes BattlePathfinder::getAllAvailableMoves( const Unit & unit ) { reEvaluateIfNeeded( unit ); std::set boardIndexes; for ( const auto & [index, node] : _cache ) { if ( index == _pathStart || node._from == BattleNodeIndex{ -1, -1 } || node._cost > _speed ) { continue; } assert( index.first != -1 ); boardIndexes.insert( index.first ); } Indexes result; result.reserve( boardIndexes.size() ); result.assign( boardIndexes.begin(), boardIndexes.end() ); return result; } Indexes BattlePathfinder::buildPath( const Unit & unit, const Position & position ) { assert( position.GetHead() != nullptr ); reEvaluateIfNeeded( unit ); Indexes result; result.reserve( Speed::INSTANT ); BattleNodeIndex lastReachableNodeIdx{ -1, -1 }; BattleNodeIndex nodeIdx = { position.GetHead()->GetIndex(), position.GetTail() ? position.GetTail()->GetIndex() : -1 }; for ( auto iter = _cache.find( nodeIdx ); iter != _cache.end(); iter = _cache.find( nodeIdx ) ) { const auto & [index, node] = *iter; if ( index == _pathStart ) { break; } // MSVC 2017 fails to properly expand the assert() macro without additional parentheses assert( ( node._from != BattleNodeIndex{ -1, -1 } ) ); nodeIdx = node._from; // A given position may be reachable in principle, but is not reachable on the current turn. // Skip the steps that are not reachable on this turn. if ( node._cost > _speed ) { continue; } if ( _isWide && lastReachableNodeIdx == BattleNodeIndex{ -1, -1 } ) { assert( index.first != -1 && index.second != -1 ); lastReachableNodeIdx = index; } result.push_back( index.first ); } std::reverse( result.begin(), result.end() ); // If a given position is not reachable on the current turn, then the last reachable position of // a wide unit may be reversed in regard to the target one. Detect this and add an extra U-turn. if ( _isWide && !result.empty() ) { assert( lastReachableNodeIdx.first != -1 && lastReachableNodeIdx.second != -1 ); const bool isReflect = lastReachableNodeIdx.first < lastReachableNodeIdx.second; if ( isReflect != position.isReflect() ) { // The last reachable position should not be a reversed version of the target position assert( !position.contains( lastReachableNodeIdx.first ) || !position.contains( lastReachableNodeIdx.second ) ); result.push_back( lastReachableNodeIdx.second ); } } return result; } Position BattlePathfinder::getClosestReachablePosition( const Unit & unit, const Position & position ) { assert( position.GetHead() != nullptr ); reEvaluateIfNeeded( unit ); BattleNodeIndex nodeIdx = { position.GetHead()->GetIndex(), position.GetTail() ? position.GetTail()->GetIndex() : -1 }; for ( auto iter = _cache.find( nodeIdx ); iter != _cache.end(); iter = _cache.find( nodeIdx ) ) { const auto & [index, node] = *iter; if ( index == _pathStart ) { break; } // MSVC 2017 fails to properly expand the assert() macro without additional parentheses assert( ( node._from != BattleNodeIndex{ -1, -1 } ) ); nodeIdx = node._from; // A given position may be reachable in principle, but is not reachable on the current turn. // Skip the steps that are not reachable on this turn. if ( node._cost > _speed ) { continue; } Position result; if ( _isWide ) { assert( index.first != -1 && index.second != -1 ); const bool isReflect = index.first < index.second; result.Set( index.first, true, isReflect ); assert( result.GetHead() != nullptr && result.GetHead()->GetIndex() == index.first && result.GetTail() != nullptr && result.GetTail()->GetIndex() == index.second ); // If a given position is not reachable on the current turn, then the last reachable position of // a wide unit may be reversed in regard to the target one. Detect this and turn it over. if ( isReflect != position.isReflect() ) { // The last reachable position should not be a reversed version of the target position assert( !position.contains( index.first ) || !position.contains( index.second ) ); result.Swap(); } } else { result.Set( index.first, false, false ); } return result; } return {}; } } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_pathfinding.h000066400000000000000000000133671476115357100237550ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "battle_board.h" namespace Battle { class Position; class Unit; using BattleNodeIndex = std::pair; struct BattleNodeIndexHash final { std::size_t operator()( const BattleNodeIndex & index ) const noexcept { const uint64_t f = index.first; const uint64_t s = index.second; std::hash hasher; return hasher( ( f << 32 ) + s ); } }; struct BattleNode final { BattleNodeIndex _from{ -1, -1 }; // Cost of moving to this node. May differ from _distance due to penalties (e.g. moat penalty) and // also in the case of flying units. uint32_t _cost{ 0 }; // Distance to this node, measured in the number of movements that need to be performed to get here. // The reversal of a wide unit is not considered as a movement. For flying units, this distance is // estimated as the straight line distance to the position corresponding to this node. uint32_t _distance{ 0 }; BattleNode() = default; void update( BattleNodeIndex from, const uint32_t cost, const uint32_t distance ) { _from = std::move( from ); _cost = cost; _distance = distance; } }; class BattlePathfinder final { public: BattlePathfinder() = default; BattlePathfinder( const BattlePathfinder & ) = delete; ~BattlePathfinder() = default; BattlePathfinder & operator=( const BattlePathfinder & ) = delete; // Checks whether the given position is reachable for the given unit, either on the current turn or in principle bool isPositionReachable( const Unit & unit, const Position & position, const bool isOnCurrentTurn ); // Returns the cost of moving to the given position for the given unit. It's the caller's responsibility to make // sure that this position is reachable before calling this method. uint32_t getCost( const Unit & unit, const Position & position ); // Returns the distance to the given position (i.e. the number of movements that need to be performed to get to // this position, the reversal of a wide unit is not considered as a movement) for the given unit. For flying // units, this distance is estimated as the straight line distance to the given position. It's the caller's // responsibility to make sure that this position is reachable before calling this method. uint32_t getDistance( const Unit & unit, const Position & position ); // Builds and returns the path (or its part) for the given unit to the given position that can be traversed during // the current turn. If this position is unreachable by this unit, then an empty path is returned. Indexes buildPath( const Unit & unit, const Position & position ); // Returns the indexes of all cells that can be occupied by the given unit's head on the current turn Indexes getAllAvailableMoves( const Unit & unit ); // Returns the position on the path for the given unit to the given position, which is reachable on the current // turn and is as close as possible to the destination (excluding the current position of the unit). If the given // position is unreachable by the given unit, then an empty Position object is returned. Position getClosestReachablePosition( const Unit & unit, const Position & position ); private: // Rebuilds the graph of available positions for the given unit if necessary (if it is not already cached) void reEvaluateIfNeeded( const Unit & unit ); std::unordered_map _cache; // Parameters of the unit for which the current cache is created BattleNodeIndex _pathStart{ -1, -1 }; uint32_t _speed{ 0 }; bool _isWide{ false }; bool _isFlying{ false }; // The unit's color (or rather, the unit's army color) affects the ability to pass the castle bridge int _color{ 0 }; // Board cells passability status at the time of current cache creation std::array _boardStatus{}; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_tower.cpp000066400000000000000000000140771476115357100231540ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_tower.h" #include #include #include #include "army_troop.h" #include "battle.h" #include "battle_arena.h" #include "battle_board.h" #include "battle_cell.h" #include "castle.h" #include "monster.h" #include "tools.h" #include "translations.h" Battle::Tower::Tower( const Castle & castle, const TowerType type, const uint32_t uid ) : Unit( Troop( Monster::ARCHER, std::min( castle.CountBuildings(), 20U ) ), {}, false, uid ) , _towerType( type ) , _attackBonus( castle.GetLevelMageGuild() ) , _isValid( true ) { SetCount( std::max( _towerType == TowerType::TWR_CENTER ? GetCount() : GetCount() / 2, 1U ) ); // Virtual archers shooting from this tower should receive bonuses // to their attack skill from the commanding hero (if present) SetArmy( castle.GetActualArmy() ); SetModes( CAP_TOWER ); } const char * Battle::Tower::GetName() const { switch ( _towerType ) { case TowerType::TWR_LEFT: return _( "Left Turret" ); case TowerType::TWR_RIGHT: return _( "Right Turret" ); case TowerType::TWR_CENTER: return _( "Ballista" ); default: // This is not a valid Tower type! assert( 0 ); break; } return nullptr; } bool Battle::Tower::isValid() const { return _isValid; } Battle::TowerType Battle::Tower::GetType() const { return _towerType; } uint32_t Battle::Tower::GetAttackBonus() const { return _attackBonus; } uint32_t Battle::Tower::GetAttack() const { return Unit::GetAttack() + _attackBonus; } fheroes2::Point Battle::Tower::GetPortPosition() const { switch ( _towerType ) { case TowerType::TWR_LEFT: return { 410, 70 }; case TowerType::TWR_RIGHT: return { 410, 320 }; case TowerType::TWR_CENTER: return { 560, 170 }; default: break; } return {}; } void Battle::Tower::SetDestroyed() { switch ( _towerType ) { case TowerType::TWR_LEFT: Board::GetCell( Arena::CASTLE_TOP_ARCHER_TOWER_POS )->SetObject( 1 ); break; case TowerType::TWR_RIGHT: Board::GetCell( Arena::CASTLE_BOTTOM_ARCHER_TOWER_POS )->SetObject( 1 ); break; default: break; } _isValid = false; } std::string Battle::Tower::GetInfo( const Castle & castle ) { if ( !castle.isBuild( BUILD_CASTLE ) ) { return {}; } std::vector towerTypes; towerTypes.push_back( TowerType::TWR_CENTER ); if ( castle.isBuild( BUILD_LEFTTURRET ) ) { towerTypes.push_back( TowerType::TWR_LEFT ); } if ( castle.isBuild( BUILD_RIGHTTURRET ) ) { towerTypes.push_back( TowerType::TWR_RIGHT ); } // This method can be called both during combat and outside of it. In the // former case, we have to check if the tower was destroyed during the siege. const auto isTowerValid = []( const TowerType towerType ) { // If the siege is in progress, we need to check the current state of the tower if ( GetArena() ) { const Tower * tower = Arena::GetTower( towerType ); assert( tower != nullptr ); return tower->isValid(); } return true; }; std::string msg; for ( std::vector::const_iterator it = towerTypes.begin(); it != towerTypes.end(); ++it ) { const TowerType towerType = *it; if ( isTowerValid( towerType ) ) { const Tower tower( castle, towerType, 0 ); msg.append( _( "The %{name} fires with the strength of %{count} Archers" ) ); StringReplace( msg, "%{name}", tower.GetName() ); StringReplace( msg, "%{count}", std::to_string( tower.GetCount() ) ); if ( tower.GetAttackBonus() ) { msg.append( ", " ); msg.append( _( "each with a +%{attack} bonus to their attack skill." ) ); StringReplace( msg, "%{attack}", std::to_string( tower.GetAttackBonus() ) ); } else { msg += '.'; } } else { assert( GetArena() != nullptr ); const Tower * tower = Arena::GetTower( towerType ); assert( tower != nullptr ); msg.append( _( "The %{name} is destroyed." ) ); StringReplace( msg, "%{name}", tower->GetName() ); } if ( ( it + 1 ) != towerTypes.end() ) { msg.append( "\n\n" ); } } return msg; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_tower.h000066400000000000000000000054671476115357100226240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "battle_troop.h" #include "math_base.h" class Castle; namespace Battle { enum class TowerType : uint8_t { TWR_LEFT, TWR_CENTER, TWR_RIGHT }; class Tower : public Unit { public: Tower( const Castle & castle, const TowerType type, const uint32_t uid ); Tower( const Tower & ) = delete; Tower & operator=( const Tower & ) = delete; bool isValid() const override; TowerType GetType() const; uint32_t GetAttackBonus() const; uint32_t GetAttack() const override; const char * GetName() const; fheroes2::Point GetPortPosition() const; void SetDestroyed(); // Returns a text description of the parameters of the towers of a given castle. Can be // called both during combat and outside of it. In the former case, the current state of // the towers destroyed during the siege will be reflected. static std::string GetInfo( const Castle & castle ); private: TowerType _towerType; uint32_t _attackBonus; bool _isValid; }; } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_troop.cpp000066400000000000000000001542471476115357100231630ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "battle_troop.h" #include #include #include #include "agg_image.h" #include "army.h" #include "artifact.h" #include "artifact_info.h" #include "battle.h" #include "battle_arena.h" #include "battle_army.h" #include "battle_board.h" #include "battle_cell.h" #include "battle_grave.h" #include "battle_interface.h" #include "battle_tower.h" #include "castle.h" #include "color.h" #include "game_static.h" #include "heroes_base.h" #include "image.h" #include "logging.h" #include "m82.h" #include "monster.h" #include "monster_anim.h" #include "monster_info.h" #include "morale.h" #include "rand.h" #include "resource.h" #include "skill.h" #include "speed.h" #include "spell.h" #include "spell_info.h" #include "tools.h" #include "translations.h" namespace { Artifact getImmunityArtifactForSpell( const HeroBase * hero, const Spell & spell ) { if ( hero == nullptr ) { return { Artifact::UNKNOWN }; } switch ( spell.GetID() ) { case Spell::CURSE: case Spell::MASSCURSE: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::CURSE_SPELL_IMMUNITY ); case Spell::HYPNOTIZE: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::HYPNOTIZE_SPELL_IMMUNITY ); case Spell::DEATHRIPPLE: case Spell::DEATHWAVE: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::DEATH_SPELL_IMMUNITY ); case Spell::BERSERKER: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::BERSERK_SPELL_IMMUNITY ); case Spell::BLIND: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::BLIND_SPELL_IMMUNITY ); case Spell::PARALYZE: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::PARALYZE_SPELL_IMMUNITY ); case Spell::HOLYWORD: case Spell::HOLYSHOUT: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::HOLY_SPELL_IMMUNITY ); case Spell::DISPEL: case Spell::MASSDISPEL: return hero->GetBagArtifacts().getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::DISPEL_SPELL_IMMUNITY ); default: break; } return { Artifact::UNKNOWN }; } } Battle::ModeDuration::ModeDuration( uint32_t mode, uint32_t duration ) : std::pair( mode, duration ) {} bool Battle::ModeDuration::isMode( uint32_t mode ) const { return ( first & mode ) != 0; } bool Battle::ModeDuration::isZeroDuration() const { return 0 == second; } void Battle::ModeDuration::DecreaseDuration() { if ( second ) { --second; } } Battle::ModesAffected::ModesAffected() { reserve( 3 ); } uint32_t Battle::ModesAffected::GetMode( uint32_t mode ) const { const_iterator it = std::find_if( begin(), end(), [mode]( const Battle::ModeDuration & v ) { return v.isMode( mode ); } ); return it == end() ? 0 : it->second; } void Battle::ModesAffected::AddMode( uint32_t mode, uint32_t duration ) { iterator it = std::find_if( begin(), end(), [mode]( const Battle::ModeDuration & v ) { return v.isMode( mode ); } ); if ( it == end() ) { emplace_back( mode, duration ); } else { it->second = duration; } } void Battle::ModesAffected::RemoveMode( uint32_t mode ) { erase( std::remove_if( begin(), end(), [mode]( const Battle::ModeDuration & v ) { return v.isMode( mode ); } ), end() ); } void Battle::ModesAffected::DecreaseDuration() { std::for_each( begin(), end(), []( Battle::ModeDuration & v ) { v.DecreaseDuration(); } ); } uint32_t Battle::ModesAffected::FindZeroDuration() const { const_iterator it = std::find_if( begin(), end(), []( const Battle::ModeDuration & v ) { return v.isZeroDuration(); } ); return it == end() ? 0 : ( *it ).first; } Battle::Unit::Unit( const Troop & troop, const Position & pos, const bool ref, const uint32_t uid ) : ArmyTroop( nullptr, troop ) , animation( id ) , _uid( uid ) , hp( troop.GetHitPoints() ) , _initialCount( troop.GetCount() ) , dead( 0 ) , shots( troop.GetShots() ) , _disruptingRaysNum( 0 ) , reflect( ref ) , mirror( nullptr ) , idleTimer( animation.getIdleDelay() ) , _blindRetaliation( false ) , customAlphaMask( 255 ) { SetPosition( pos ); } void Battle::Unit::SetPosition( const int32_t idx ) { if ( position.GetHead() ) { position.GetHead()->SetUnit( nullptr ); } if ( position.GetTail() ) { position.GetTail()->SetUnit( nullptr ); } position.Set( idx, isWide(), reflect ); if ( position.GetHead() ) { position.GetHead()->SetUnit( this ); } if ( position.GetTail() ) { position.GetTail()->SetUnit( this ); } } void Battle::Unit::SetPosition( const Position & pos ) { // Position may be empty if this unit is a castle tower assert( pos.isValidForUnit( this ) || pos.isEmpty() ); if ( position.GetHead() ) { position.GetHead()->SetUnit( nullptr ); } if ( position.GetTail() ) { position.GetTail()->SetUnit( nullptr ); } position = pos; if ( position.GetHead() ) { position.GetHead()->SetUnit( this ); } if ( position.GetTail() ) { position.GetTail()->SetUnit( this ); } if ( isWide() && position.GetHead() && position.GetTail() ) { reflect = GetHeadIndex() < GetTailIndex(); } } void Battle::Unit::SetReflection( bool r ) { if ( reflect != r ) position.Swap(); reflect = r; } void Battle::Unit::UpdateDirection() { const Arena * arena = GetArena(); assert( arena != nullptr ); SetReflection( arena->GetArmy1Color() != GetArmyColor() ); } bool Battle::Unit::UpdateDirection( const fheroes2::Rect & pos ) { bool need = position.GetRect().x == pos.x ? reflect : position.GetRect().x > pos.x; if ( need != reflect ) { SetReflection( need ); return true; } return false; } bool Battle::Unit::isBattle() const { return true; } bool Battle::Unit::isModes( uint32_t v ) const { return Modes( v ); } std::string Battle::Unit::GetShotString() const { if ( Troop::GetShots() == GetShots() ) return std::to_string( Troop::GetShots() ); std::string output( std::to_string( Troop::GetShots() ) ); output += " ("; output += std::to_string( GetShots() ); output += ')'; return output; } std::string Battle::Unit::GetSpeedString() const { const uint32_t speed = GetSpeed( true, false ); return Troop::GetSpeedString( speed ); } uint32_t Battle::Unit::GetInitialCount() const { return _initialCount; } uint32_t Battle::Unit::GetDead() const { return dead; } uint32_t Battle::Unit::GetHitPointsLeft() const { return GetHitPoints() - ( GetCount() - 1 ) * Monster::GetHitPoints(); } uint32_t Battle::Unit::GetMissingHitPoints() const { const uint32_t totalHitPoints = _initialCount * Monster::GetHitPoints(); assert( totalHitPoints > hp ); return totalHitPoints - hp; } uint32_t Battle::Unit::GetAffectedDuration( uint32_t mod ) const { return affected.GetMode( mod ); } uint32_t Battle::Unit::GetSpeed() const { return GetSpeed( false, false ); } int Battle::Unit::GetMorale() const { const Arena * arena = GetArena(); assert( arena != nullptr ); int armyTroopMorale = ArmyTroop::GetMorale(); // enemy Bone dragons affect morale if ( isAffectedByMorale() && arena->getEnemyForce( GetArmyColor() ).HasMonster( Monster::BONE_DRAGON ) && armyTroopMorale > Morale::TREASON ) { --armyTroopMorale; } return armyTroopMorale; } int32_t Battle::Unit::GetHeadIndex() const { return position.GetHead() ? position.GetHead()->GetIndex() : -1; } int32_t Battle::Unit::GetTailIndex() const { return position.GetTail() ? position.GetTail()->GetIndex() : -1; } void Battle::Unit::SetRandomMorale( Rand::DeterministicRandomGenerator & randomGenerator ) { const int morale = GetMorale(); if ( morale > 0 && static_cast( randomGenerator.Get( 1, 24 ) ) <= morale ) { SetModes( MORALE_GOOD ); } else if ( morale < 0 && static_cast( randomGenerator.Get( 1, 12 ) ) <= -morale ) { if ( isControlHuman() ) { SetModes( MORALE_BAD ); } // AI is given a cheeky 25% chance to avoid it - because they build armies from random troops else if ( randomGenerator.Get( 1, 4 ) != 1 ) { SetModes( MORALE_BAD ); } } } void Battle::Unit::SetRandomLuck( Rand::DeterministicRandomGenerator & randomGenerator ) { const int32_t luck = GetLuck(); const int32_t chance = static_cast( randomGenerator.Get( 1, 24 ) ); if ( luck > 0 && chance <= luck ) { SetModes( LUCK_GOOD ); } else if ( luck < 0 && chance <= -luck ) { SetModes( LUCK_BAD ); } // Bless, Curse and Luck do stack } bool Battle::Unit::isFlying() const { return ArmyTroop::isFlying() && !Modes( SP_SLOW ); } bool Battle::Unit::isOutOfCastleWalls() const { return Board::isOutOfWallsIndex( GetHeadIndex() ) || ( isWide() && Board::isOutOfWallsIndex( GetTailIndex() ) ); } bool Battle::Unit::isHandFighting() const { assert( isValid() ); // Towers never fight in close combat if ( Modes( CAP_TOWER ) ) { return false; } for ( const int32_t nearbyIdx : Board::GetAroundIndexes( *this ) ) { const Unit * nearbyUnit = Board::GetCell( nearbyIdx )->GetUnit(); if ( nearbyUnit == nullptr ) { continue; } if ( nearbyUnit->GetColor() == GetCurrentColor() ) { continue; } return true; } return false; } bool Battle::Unit::isHandFighting( const Unit & attacker, const Unit & defender ) { assert( attacker.isValid() ); // Towers never fight in close combat if ( attacker.Modes( CAP_TOWER ) || defender.Modes( CAP_TOWER ) ) { return false; } const uint32_t distance = Board::GetDistance( attacker.GetPosition(), defender.GetPosition() ); assert( distance > 0 ); // If the attacker and the defender are next to each other, then this is a melee attack, otherwise it's a shot return ( distance == 1 ); } bool Battle::Unit::isIdling() const { return GetAnimationState() == Monster_Info::IDLE; } void Battle::Unit::NewTurn() { if ( isRegenerating() ) { hp = ArmyTroop::GetHitPoints(); } ResetModes( TR_RESPONDED ); ResetModes( TR_MOVED ); ResetModes( TR_SKIP ); ResetModes( LUCK_GOOD ); ResetModes( LUCK_BAD ); ResetModes( MORALE_GOOD ); ResetModes( MORALE_BAD ); affected.DecreaseDuration(); for ( uint32_t mode = affected.FindZeroDuration(); mode != 0; mode = affected.FindZeroDuration() ) { assert( Modes( mode ) ); if ( mode == CAP_MIRROROWNER ) { assert( mirror != nullptr && mirror->Modes( CAP_MIRRORIMAGE ) && mirror->mirror == this ); if ( Arena::GetInterface() ) { Arena::GetInterface()->RedrawActionRemoveMirrorImage( { mirror } ); } mirror->hp = 0; mirror->SetCount( 0 ); // Affection will be removed here mirror->PostKilledAction(); } else { removeAffection( mode ); } } } uint32_t Battle::Unit::GetSpeed( const bool skipStandingCheck, const bool skipMovedCheck ) const { if ( !skipStandingCheck ) { uint32_t modesToCheck = SP_BLIND | IS_PARALYZE_MAGIC; if ( !skipMovedCheck ) { modesToCheck |= TR_MOVED; } if ( GetCount() == 0 || Modes( modesToCheck ) ) { return Speed::STANDING; } } const uint32_t speed = Monster::GetSpeed(); if ( Modes( SP_HASTE ) ) { return Speed::GetHasteSpeedFromSpell( speed ); } if ( Modes( SP_SLOW ) ) { return Speed::GetSlowSpeedFromSpell( speed ); } return speed; } uint32_t Battle::Unit::EstimateRetaliatoryDamage( const uint32_t damageTaken ) const { // The entire unit is destroyed, no retaliation if ( damageTaken >= hp ) { return 0; } // Mirror images are destroyed anyway and hypnotized units never respond to an attack if ( Modes( TR_RESPONDED | CAP_MIRRORIMAGE | SP_HYPNOTIZE ) ) { return 0; } // Units with this ability retaliate even when under the influence of paralyzing spells if ( Modes( IS_PARALYZE_MAGIC ) && !isAbilityPresent( fheroes2::MonsterAbilityType::ALWAYS_RETALIATE ) ) { return 0; } const uint32_t unitsLeft = GetCountFromHitPoints( *this, hp - damageTaken ); assert( unitsLeft > 0 ); const uint32_t damagePerUnit = [this]() { if ( Modes( SP_CURSE ) ) { return Monster::GetDamageMin(); } if ( Modes( SP_BLESS ) ) { return Monster::GetDamageMax(); } return ( Monster::GetDamageMin() + Monster::GetDamageMax() ) / 2; }(); const uint32_t retaliatoryDamage = unitsLeft * damagePerUnit; if ( !Modes( SP_BLIND ) ) { return retaliatoryDamage; } // The retaliatory damage of a blinded unit is reduced const uint32_t reductionPercent = Spell( Spell::BLIND ).ExtraValue(); assert( reductionPercent <= 100 ); return retaliatoryDamage * ( 100 - reductionPercent ) / 100; } uint32_t Battle::Unit::CalculateMinDamage( const Unit & enemy ) const { return CalculateDamageUnit( enemy, ArmyTroop::GetDamageMin() ); } uint32_t Battle::Unit::CalculateMaxDamage( const Unit & enemy ) const { return CalculateDamageUnit( enemy, ArmyTroop::GetDamageMax() ); } uint32_t Battle::Unit::CalculateDamageUnit( const Unit & enemy, double dmg ) const { if ( isArchers() ) { // Melee penalty can be applied either if the archer is blocked by enemy units and cannot shoot, // or if he is not blocked, but was attacked by a friendly unit (for example, in the case of using // Berserk or Hypnotize spells) and deals retaliatory damage if ( !isHandFighting() && !isHandFighting( *this, enemy ) ) { // Hero's Archery skill may increase damage if ( GetCommander() ) { dmg += ( dmg * GetCommander()->GetSecondarySkillValue( Skill::Secondary::ARCHERY ) / 100 ); } const Arena * arena = GetArena(); assert( arena != nullptr ); // Penalty for damage to castle defenders behind the castle walls if ( arena->IsShootingPenalty( *this, enemy ) ) { dmg *= 1 - ( GameStatic::getCastleWallRangedPenalty() / 100.0 ); } // The Shield spell does not affect the damage of the castle towers if ( !Modes( CAP_TOWER ) && enemy.Modes( SP_SHIELD ) ) { dmg /= Spell( Spell::SHIELD ).ExtraValue(); } } else if ( !isAbilityPresent( fheroes2::MonsterAbilityType::NO_MELEE_PENALTY ) ) { dmg /= 2; } } // The retaliatory damage of a blinded unit is reduced if ( _blindRetaliation ) { // Petrified units cannot attack, respectively, there should be no retaliation assert( !enemy.Modes( SP_STONE ) ); const uint32_t reductionPercent = Spell( Spell::BLIND ).ExtraValue(); assert( reductionPercent <= 100 ); dmg = dmg * ( 100 - reductionPercent ) / 100; } // A petrified unit takes only half of the damage if ( enemy.Modes( SP_STONE ) ) { // Petrified units cannot attack, respectively, there should be no retaliation assert( !_blindRetaliation ); dmg /= 2; } // If multiple options are suitable at the same time, the damage should be doubled only once if ( ( isAbilityPresent( fheroes2::MonsterAbilityType::DOUBLE_DAMAGE_TO_UNDEAD ) && enemy.isAbilityPresent( fheroes2::MonsterAbilityType::UNDEAD ) ) || ( isAbilityPresent( fheroes2::MonsterAbilityType::EARTH_CREATURE ) && enemy.isWeaknessPresent( fheroes2::MonsterWeaknessType::DOUBLE_DAMAGE_FROM_EARTH_CREATURES ) ) || ( isAbilityPresent( fheroes2::MonsterAbilityType::AIR_CREATURE ) && enemy.isWeaknessPresent( fheroes2::MonsterWeaknessType::DOUBLE_DAMAGE_FROM_AIR_CREATURES ) ) || ( isAbilityPresent( fheroes2::MonsterAbilityType::FIRE_CREATURE ) && enemy.isWeaknessPresent( fheroes2::MonsterWeaknessType::DOUBLE_DAMAGE_FROM_FIRE_CREATURES ) ) || ( isAbilityPresent( fheroes2::MonsterAbilityType::WATER_CREATURE ) && enemy.isWeaknessPresent( fheroes2::MonsterWeaknessType::DOUBLE_DAMAGE_FROM_WATER_CREATURES ) ) ) { dmg *= 2; } int r = GetAttack() - enemy.GetDefense(); if ( enemy.isDragons() && Modes( SP_DRAGONSLAYER ) ) { r += Spell( Spell::DRAGONSLAYER ).ExtraValue(); } // Attack bonus is 20% to 300% dmg *= 1 + ( 0 < r ? 0.1 * std::min( r, 20 ) : 0.05 * std::max( r, -16 ) ); return static_cast( dmg ) < 1 ? 1 : static_cast( dmg ); } uint32_t Battle::Unit::GetDamage( const Unit & enemy, Rand::DeterministicRandomGenerator & randomGenerator ) const { uint32_t res = 0; if ( Modes( SP_BLESS ) ) res = CalculateMaxDamage( enemy ); else if ( Modes( SP_CURSE ) ) res = CalculateMinDamage( enemy ); else res = randomGenerator.Get( CalculateMinDamage( enemy ), CalculateMaxDamage( enemy ) ); if ( Modes( LUCK_GOOD ) ) res = res * 2; else if ( Modes( LUCK_BAD ) ) res = res / 2; return res; } uint32_t Battle::Unit::HowManyWillBeKilled( const uint32_t dmg ) const { if ( Modes( CAP_MIRRORIMAGE ) ) { return GetCount(); } return dmg >= hp ? GetCount() : GetCount() - Monster::GetCountFromHitPoints( *this, hp - dmg ); } uint32_t Battle::Unit::ApplyDamage( const uint32_t dmg ) { assert( !AllModes( CAP_MIRROROWNER | CAP_MIRRORIMAGE ) ); if ( dmg == 0 || GetCount() == 0 ) { return 0; } const uint32_t killed = HowManyWillBeKilled( dmg ); DEBUG_LOG( DBG_BATTLE, DBG_TRACE, dmg << " to " << String() << " and killed: " << killed ) if ( Modes( IS_PARALYZE_MAGIC ) ) { // Units with this ability retaliate even when under the influence of paralyzing spells if ( !isAbilityPresent( fheroes2::MonsterAbilityType::ALWAYS_RETALIATE ) ) { SetModes( TR_RESPONDED ); } SetModes( TR_MOVED ); removeAffection( IS_PARALYZE_MAGIC ); } if ( Modes( SP_BLIND ) ) { SetModes( TR_MOVED ); removeAffection( SP_BLIND ); } if ( killed >= GetCount() ) { dead += GetCount(); SetCount( 0 ); } else { dead += killed; SetCount( GetCount() - killed ); } if ( Modes( CAP_MIRRORIMAGE ) ) { hp = 0; } else { hp -= std::min( hp, dmg ); } if ( Modes( CAP_MIRROROWNER ) && !isValid() ) { assert( mirror != nullptr && mirror->Modes( CAP_MIRRORIMAGE ) && mirror->mirror == this ); mirror->ApplyDamage( mirror->hp ); } return killed; } void Battle::Unit::PostKilledAction() { assert( !AllModes( CAP_MIRROROWNER | CAP_MIRRORIMAGE ) ); if ( Modes( CAP_MIRROROWNER ) ) { assert( mirror != nullptr && mirror->Modes( CAP_MIRRORIMAGE ) && mirror->mirror == this ); mirror = nullptr; removeAffection( CAP_MIRROROWNER ); } if ( Modes( CAP_MIRRORIMAGE ) ) { // CAP_MIRROROWNER may have already been removed from the mirror owner, // since this method may already have been called for it assert( mirror != nullptr ); // But we still need to remove it if it is present if ( mirror->Modes( CAP_MIRROROWNER ) ) { assert( mirror->mirror == this ); mirror->mirror = nullptr; mirror->removeAffection( CAP_MIRROROWNER ); } mirror = nullptr; } // Remove all spells removeAffection( IS_MAGIC ); assert( affected.empty() ); // Save to the graveyard if possible if ( !Modes( CAP_MIRRORIMAGE ) && !isElemental() ) { Graveyard * graveyard = Arena::GetGraveyard(); assert( graveyard != nullptr ); graveyard->addUnit( this ); } Cell * head = position.GetHead(); assert( head != nullptr ); head->SetUnit( nullptr ); if ( isWide() ) { Cell * tail = position.GetTail(); assert( tail != nullptr ); tail->SetUnit( nullptr ); } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, String() ) } uint32_t Battle::Unit::Resurrect( const uint32_t points, const bool allowToExceedInitialCount, const bool isTemporary ) { uint32_t resurrect = Monster::GetCountFromHitPoints( *this, hp + points ) - GetCount(); SetCount( GetCount() + resurrect ); hp += points; if ( allowToExceedInitialCount ) { if ( _initialCount < GetCount() ) { _initialCount = GetCount(); } } else if ( GetCount() > _initialCount ) { resurrect -= GetCount() - _initialCount; SetCount( _initialCount ); hp = ArmyTroop::GetHitPoints(); } if ( !isTemporary ) { dead -= ( resurrect < dead ? resurrect : dead ); } return resurrect; } bool Battle::Unit::isImmovable() const { return Modes( SP_BLIND | IS_PARALYZE_MAGIC ); } uint32_t Battle::Unit::ApplyDamage( Unit & enemy, const uint32_t dmg, uint32_t & killed, uint32_t * ptrResurrected ) { killed = ApplyDamage( dmg ); if ( killed == 0 ) { if ( ptrResurrected != nullptr ) { *ptrResurrected = 0; } return killed; } uint32_t resurrected = 0; if ( enemy.isAbilityPresent( fheroes2::MonsterAbilityType::SOUL_EATER ) ) { resurrected = enemy.Resurrect( killed * enemy.Monster::GetHitPoints(), true, false ); } else if ( enemy.isAbilityPresent( fheroes2::MonsterAbilityType::HP_DRAIN ) ) { resurrected = enemy.Resurrect( killed * Monster::GetHitPoints(), false, false ); } if ( resurrected > 0 ) { DEBUG_LOG( DBG_BATTLE, DBG_TRACE, String() << ", enemy: " << enemy.String() << ", resurrected: " << resurrected ) } if ( ptrResurrected != nullptr ) { *ptrResurrected = resurrected; } return killed; } bool Battle::Unit::AllowApplySpell( const Spell & spell, const HeroBase * applyingHero, const bool forceApplyToAlly /* = false */ ) const { if ( Modes( CAP_MIRRORIMAGE ) && ( spell == Spell::ANTIMAGIC || spell == Spell::MIRRORIMAGE ) ) { return false; } if ( Modes( CAP_MIRROROWNER ) && spell == Spell::MIRRORIMAGE ) { return false; } if ( applyingHero && spell.isApplyToFriends() && GetColor() != applyingHero->GetColor() ) { return false; } if ( applyingHero && spell.isApplyToEnemies() && GetColor() == applyingHero->GetColor() && !forceApplyToAlly ) { return false; } return ( GetMagicResist( spell, applyingHero ) < 100 ); } bool Battle::Unit::ApplySpell( const Spell & spell, const HeroBase * applyingHero, TargetInfo & target ) { // HACK!!! Chain lightning is the only spell which can't be cast on allies but could be applied on them const bool isForceApply = ( spell.GetID() == Spell::CHAINLIGHTNING ); if ( !AllowApplySpell( spell, applyingHero, isForceApply ) ) { return false; } DEBUG_LOG( DBG_BATTLE, DBG_TRACE, spell.GetName() << " to " << String() ) const uint32_t spoint = applyingHero ? applyingHero->GetPower() : fheroes2::spellPowerForBuiltinMonsterSpells; if ( spell.isDamage() ) { SpellApplyDamage( spell, spoint, applyingHero, target ); } else if ( spell.isRestore() || spell.isResurrect() ) { SpellRestoreAction( spell, spoint, applyingHero ); } else { SpellModesAction( spell, spoint, applyingHero ); } return true; } std::vector Battle::Unit::getCurrentSpellEffects() const { std::vector spellList; if ( Modes( SP_BLESS ) ) { spellList.emplace_back( Spell::BLESS ); } if ( Modes( SP_CURSE ) ) { spellList.emplace_back( Spell::CURSE ); } if ( Modes( SP_HASTE ) ) { spellList.emplace_back( Spell::HASTE ); } if ( Modes( SP_SLOW ) ) { spellList.emplace_back( Spell::SLOW ); } if ( Modes( SP_SHIELD ) ) { spellList.emplace_back( Spell::SHIELD ); } if ( Modes( SP_BLOODLUST ) ) { spellList.emplace_back( Spell::BLOODLUST ); } if ( Modes( SP_STONESKIN ) ) { spellList.emplace_back( Spell::STONESKIN ); } if ( Modes( SP_STEELSKIN ) ) { spellList.emplace_back( Spell::STEELSKIN ); } if ( Modes( SP_BLIND ) ) { spellList.emplace_back( Spell::BLIND ); } if ( Modes( SP_PARALYZE ) ) { spellList.emplace_back( Spell::PARALYZE ); } if ( Modes( SP_STONE ) ) { spellList.emplace_back( Spell::PETRIFY ); } if ( Modes( SP_DRAGONSLAYER ) ) { spellList.emplace_back( Spell::DRAGONSLAYER ); } if ( Modes( SP_BERSERKER ) ) { spellList.emplace_back( Spell::BERSERKER ); } if ( Modes( SP_HYPNOTIZE ) ) { spellList.emplace_back( Spell::HYPNOTIZE ); } if ( Modes( CAP_MIRROROWNER ) ) { spellList.emplace_back( Spell::MIRRORIMAGE ); } return spellList; } std::string Battle::Unit::String( bool more ) const { std::stringstream ss; ss << "Unit: " << "[ " << // info GetCount() << " " << GetName() << ", " << Color::String( GetColor() ) << ", pos: " << GetHeadIndex() << ", " << GetTailIndex() << ( reflect ? ", reflect" : "" ); if ( more ) ss << ", mode(" << GetHexString( modes ) << ")" << ", uid(" << GetHexString( _uid ) << ")" << ", speed(" << Speed::String( GetSpeed() ) << ", " << static_cast( GetSpeed() ) << ")" << ", hp(" << hp << ")" << ", died(" << dead << ")"; ss << " ]"; return ss.str(); } bool Battle::Unit::AllowResponse() const { // Hypnotized units never respond to an attack if ( Modes( SP_HYPNOTIZE ) ) { return false; } // Blindness can be cast by an attacking unit. There should never be any retaliation in this case. if ( Modes( SP_BLIND ) && !_blindRetaliation ) { return false; } // Paralyzing magic can be cast by an attacking unit. There should never be any retaliation in this case. if ( Modes( IS_PARALYZE_MAGIC ) ) { return false; } return ( !Modes( TR_RESPONDED ) ); } void Battle::Unit::SetResponse() { if ( isAbilityPresent( fheroes2::MonsterAbilityType::ALWAYS_RETALIATE ) ) { return; } SetModes( TR_RESPONDED ); } void Battle::Unit::PostAttackAction( const Unit & enemy ) { if ( isArchers() && !isHandFighting( *this, enemy ) ) { const HeroBase * hero = GetCommander(); if ( hero == nullptr || !hero->GetBagArtifacts().isArtifactBonusPresent( fheroes2::ArtifactBonusType::ENDLESS_AMMUNITION ) ) { assert( !Modes( CAP_TOWER ) && shots > 0 ); --shots; } } ResetModes( LUCK_GOOD | LUCK_BAD ); } void Battle::Unit::SetBlindRetaliation( const bool value ) { _blindRetaliation = value; } uint32_t Battle::Unit::GetAttack() const { uint32_t res = ArmyTroop::GetAttack(); if ( Modes( SP_BLOODLUST ) ) { res += Spell( Spell::BLOODLUST ).ExtraValue(); } return res; } uint32_t Battle::Unit::GetDefense() const { uint32_t res = ArmyTroop::GetDefense(); if ( Modes( SP_STONESKIN ) ) { res += Spell( Spell::STONESKIN ).ExtraValue(); } else if ( Modes( SP_STEELSKIN ) ) { res += Spell( Spell::STEELSKIN ).ExtraValue(); } if ( _disruptingRaysNum ) { const uint32_t step = _disruptingRaysNum * Spell( Spell::DISRUPTINGRAY ).ExtraValue(); if ( step >= res ) { res = 1; } else { res -= step; } } const Castle * castle = Arena::GetCastle(); if ( castle && castle->isBuild( BUILD_MOAT ) && ( Board::isMoatIndex( GetHeadIndex(), *this ) || Board::isMoatIndex( GetTailIndex(), *this ) ) ) { const uint32_t step = GameStatic::GetBattleMoatReduceDefense(); if ( step >= res ) { res = 1; } else { res -= step; } } return res; } int32_t Battle::Unit::evaluateThreatForUnit( const Unit & defender ) const { const Unit & attacker = *this; const uint32_t attackerDamageToDefender = [&defender, &attacker]() { if ( attacker.Modes( SP_CURSE ) ) { return attacker.CalculateMinDamage( defender ); } if ( attacker.Modes( SP_BLESS ) ) { return attacker.CalculateMaxDamage( defender ); } return ( attacker.CalculateMinDamage( defender ) + attacker.CalculateMaxDamage( defender ) ) / 2; }(); double attackerThreat = attackerDamageToDefender; { const double distanceModifier = [&defender, &attacker]() { if ( defender.Modes( CAP_TOWER ) ) { return 1.0; } if ( attacker.isFlying() || attacker.isArchers() ) { return 1.0; } const uint32_t attackerSpeed = attacker.GetSpeed( true, false ); assert( attackerSpeed > Speed::STANDING ); const uint32_t attackRange = attackerSpeed + 1; const uint32_t distance = Board::GetDistance( attacker.GetPosition(), defender.GetPosition() ); assert( distance > 0 ); if ( distance <= attackRange ) { return 1.0; } return 1.5 * static_cast( distance ) / static_cast( attackerSpeed ); }(); attackerThreat /= distanceModifier; } if ( attacker.isDoubleAttack() ) { // The following logic of accounting for potential retaliatory damage is intended only for the case when one unit directly attacks another, and will not work in // cases where one unit attacks several units at once assert( !attacker.isAbilityPresent( fheroes2::MonsterAbilityType::TWO_CELL_MELEE_ATTACK ) && !attacker.isAbilityPresent( fheroes2::MonsterAbilityType::ALL_ADJACENT_CELL_MELEE_ATTACK ) && !attacker.isAbilityPresent( fheroes2::MonsterAbilityType::AREA_SHOT ) ); const uint32_t retaliatoryDamage = [&defender, &attacker, attackerDamageToDefender]() -> uint32_t { if ( defender.Modes( CAP_TOWER ) ) { return 0; } if ( attacker.isIgnoringRetaliation() ) { return 0; } if ( attacker.isArchers() && !attacker.isHandFighting() ) { return 0; } return defender.EstimateRetaliatoryDamage( attackerDamageToDefender ); }(); // If the defender is able to retaliate the attacker after his first attack, then the attacker's second attack can cause less damage than the first if ( retaliatoryDamage > 0 ) { assert( attacker.GetHitPoints() > 0 ); // Rough but quick estimate attackerThreat += attackerThreat * ( 1.0 - std::min( static_cast( retaliatoryDamage ) / static_cast( attacker.GetHitPoints() ), 1.0 ) ); } // Otherwise, estimate the second attack as approximately equal to the first in damage else { attackerThreat *= 2; } } if ( attacker.isAbilityPresent( fheroes2::MonsterAbilityType::ENEMY_HALVING ) ) { attackerThreat *= 2; } if ( attacker.isAbilityPresent( fheroes2::MonsterAbilityType::SOUL_EATER ) ) { attackerThreat *= 3; } if ( attacker.isAbilityPresent( fheroes2::MonsterAbilityType::HP_DRAIN ) ) { attackerThreat *= 1.3; } { const std::vector & attackerAbilities = fheroes2::getMonsterData( id ).battleStats.abilities; if ( const auto abilityIter = std::find( attackerAbilities.begin(), attackerAbilities.end(), fheroes2::MonsterAbilityType::SPELL_CASTER ); abilityIter != attackerAbilities.end() ) { const auto getDefenderDamage = [&defender]() { if ( defender.Modes( SP_CURSE ) ) { return defender.GetDamageMin(); } if ( defender.Modes( SP_BLESS ) ) { return defender.GetDamageMax(); } return ( defender.GetDamageMin() + defender.GetDamageMax() ) / 2; }; switch ( abilityIter->value ) { case Spell::BLIND: case Spell::PARALYZE: case Spell::PETRIFY: // Creature's built-in magic resistance (not 100% immunity but resistance, as, for example, with Dwarves) never works against the built-in magic of // another creature (for example, Unicorn's Blind ability). Only the probability of triggering the built-in magic matters. if ( defender.AllowApplySpell( abilityIter->value, nullptr ) ) { attackerThreat += static_cast( getDefenderDamage() ) * abilityIter->percentage / 100.0; } break; case Spell::DISPEL: // TODO: add the logic to evaluate this spell value. break; case Spell::CURSE: // Creature's built-in magic resistance (not 100% immunity but resistance, as, for example, with Dwarves) never works against the built-in magic of // another creature (for example, Unicorn's Blind ability). Only the probability of triggering the built-in magic matters. if ( defender.AllowApplySpell( abilityIter->value, nullptr ) ) { attackerThreat += static_cast( getDefenderDamage() ) * abilityIter->percentage / 100.0 / 10.0; } break; default: // Did you add a new spell casting ability? Add the logic above! assert( 0 ); break; } } } // Give the mirror images a higher priority, as they can be destroyed in 1 hit if ( attacker.Modes( CAP_MIRRORIMAGE ) ) { attackerThreat *= 10; } // Heavy penalty for hitting our own units if ( attacker.GetColor() == defender.GetCurrentColor() ) { // TODO: remove this temporary assertion assert( dynamic_cast( this ) == nullptr ); attackerThreat *= -2; } // Negative value of units that changed the side else if ( attacker.GetColor() != attacker.GetCurrentColor() ) { attackerThreat *= -1; } // Ignore disabled enemy units else if ( attacker.isImmovable() ) { attackerThreat = 0; } // Reduce the priority of those enemy units that have already got their turn else if ( attacker.Modes( TR_MOVED ) ) { attackerThreat /= 1.25; } return static_cast( attackerThreat * 100 ); } uint32_t Battle::Unit::GetHitPoints() const { return hp; } Funds Battle::Unit::GetSurrenderCost() const { // Resurrected (not truly resurrected) units should not be taken into account when calculating the cost of surrender return GetCost() * ( GetDead() > GetInitialCount() ? 0 : GetInitialCount() - GetDead() ); } int Battle::Unit::GetControl() const { return !GetArmy() ? CONTROL_AI : GetArmy()->GetControl(); } void Battle::Unit::SpellModesAction( const Spell & spell, uint32_t duration, const HeroBase * applyingHero ) { if ( applyingHero ) { duration += applyingHero->GetBagArtifacts().getTotalArtifactEffectValue( fheroes2::ArtifactBonusType::EVERY_COMBAT_SPELL_DURATION ); } switch ( spell.GetID() ) { case Spell::BLESS: case Spell::MASSBLESS: replaceAffection( SP_CURSE, SP_BLESS, duration ); break; case Spell::BLOODLUST: addAffection( SP_BLOODLUST, 3 ); break; case Spell::CURSE: case Spell::MASSCURSE: replaceAffection( SP_BLESS, SP_CURSE, duration ); break; case Spell::HASTE: case Spell::MASSHASTE: replaceAffection( SP_SLOW, SP_HASTE, duration ); break; case Spell::DISPEL: case Spell::MASSDISPEL: removeAffection( IS_MAGIC ); break; case Spell::SHIELD: case Spell::MASSSHIELD: addAffection( SP_SHIELD, duration ); break; case Spell::SLOW: case Spell::MASSSLOW: replaceAffection( SP_HASTE, SP_SLOW, duration ); break; case Spell::STONESKIN: replaceAffection( SP_STEELSKIN, SP_STONESKIN, duration ); break; case Spell::BLIND: addAffection( SP_BLIND, duration ); // Blindness can be cast by an attacking unit. In this case, there should be no response to the attack. _blindRetaliation = false; break; case Spell::DRAGONSLAYER: addAffection( SP_DRAGONSLAYER, duration ); break; case Spell::STEELSKIN: replaceAffection( SP_STONESKIN, SP_STEELSKIN, duration ); break; case Spell::ANTIMAGIC: replaceAffection( IS_MAGIC, SP_ANTIMAGIC, duration ); break; case Spell::PARALYZE: addAffection( SP_PARALYZE, duration ); break; case Spell::BERSERKER: replaceAffection( SP_HYPNOTIZE, SP_BERSERKER, duration ); break; case Spell::HYPNOTIZE: replaceAffection( SP_BERSERKER, SP_HYPNOTIZE, duration ); break; case Spell::PETRIFY: addAffection( SP_STONE, duration ); break; case Spell::MIRRORIMAGE: // Special case, CAP_MIRROROWNER mode will be set when mirror image unit will be created affected.AddMode( CAP_MIRROROWNER, duration ); break; case Spell::DISRUPTINGRAY: ++_disruptingRaysNum; break; default: assert( 0 ); break; } } void Battle::Unit::SpellApplyDamage( const Spell & spell, const uint32_t spellPower, const HeroBase * applyingHero, TargetInfo & target ) { assert( spell.isDamage() ); const uint32_t dmg = CalculateSpellDamage( spell, spellPower, applyingHero, target.damage, false /* ignore defending hero */ ); // apply damage if ( dmg ) { target.damage = dmg; target.killed = ApplyDamage( dmg ); } } uint32_t Battle::Unit::CalculateSpellDamage( const Spell & spell, uint32_t spellPower, const HeroBase * applyingHero, const uint32_t targetDamage, const bool ignoreDefendingHero ) const { assert( spell.isDamage() ); uint32_t dmg = spell.Damage() * spellPower; // If multiple options are suitable at the same time, then the abilities are considered first (in order from more specific to less specific), // and then the weaknesses are considered (also in order from more specific to less specific) { const std::vector & abilities = fheroes2::getMonsterData( GetID() ).battleStats.abilities; const std::vector & weaknesses = fheroes2::getMonsterData( GetID() ).battleStats.weaknesses; // Abilities // if ( const auto certainSpellDmgRedIter = std::find( abilities.begin(), abilities.end(), std::make_pair( fheroes2::MonsterAbilityType::CERTAIN_SPELL_DAMAGE_REDUCTION, static_cast( spell.GetID() ) ) ); certainSpellDmgRedIter != abilities.end() ) { dmg = dmg * certainSpellDmgRedIter->percentage / 100; } else if ( const auto elementalSpellDmgRedIter = std::find( abilities.begin(), abilities.end(), fheroes2::MonsterAbilityType::ELEMENTAL_SPELL_DAMAGE_REDUCTION ); elementalSpellDmgRedIter != abilities.end() && spell.isElementalSpell() ) { dmg = dmg * elementalSpellDmgRedIter->percentage / 100; } // // Weaknesses // else if ( const auto certainSpellExtraDmgIter = std::find( weaknesses.begin(), weaknesses.end(), std::make_pair( fheroes2::MonsterWeaknessType::EXTRA_DAMAGE_FROM_CERTAIN_SPELL, static_cast( spell.GetID() ) ) ); certainSpellExtraDmgIter != weaknesses.end() ) { dmg = dmg * ( 100 + certainSpellExtraDmgIter->percentage ) / 100; } else if ( ( isWeaknessPresent( fheroes2::MonsterWeaknessType::DOUBLE_DAMAGE_FROM_FIRE_SPELLS ) && spell.isFire() ) || ( isWeaknessPresent( fheroes2::MonsterWeaknessType::DOUBLE_DAMAGE_FROM_COLD_SPELLS ) && spell.isCold() ) ) { dmg *= 2; } } if ( applyingHero ) { const HeroBase * defendingHero = GetCommander(); const bool useDefendingHeroArts = defendingHero && !ignoreDefendingHero; switch ( spell.GetID() ) { case Spell::COLDRAY: case Spell::COLDRING: { std::vector extraDamagePercent = applyingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::COLD_SPELL_EXTRA_EFFECTIVENESS_PERCENT ); for ( const int32_t value : extraDamagePercent ) { dmg = dmg * ( 100 + value ) / 100; } if ( useDefendingHeroArts ) { const std::vector damageReductionPercent = defendingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::COLD_SPELL_DAMAGE_REDUCTION_PERCENT ); for ( const int32_t value : damageReductionPercent ) { dmg = dmg * ( 100 - value ) / 100; } extraDamagePercent = defendingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactCurseType::COLD_SPELL_EXTRA_DAMAGE_PERCENT ); for ( const int32_t value : extraDamagePercent ) { dmg = dmg * ( 100 + value ) / 100; } } break; } case Spell::FIREBALL: case Spell::FIREBLAST: { std::vector extraDamagePercent = applyingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::FIRE_SPELL_EXTRA_EFFECTIVENESS_PERCENT ); for ( const int32_t value : extraDamagePercent ) { dmg = dmg * ( 100 + value ) / 100; } if ( useDefendingHeroArts ) { const std::vector damageReductionPercent = defendingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::FIRE_SPELL_DAMAGE_REDUCTION_PERCENT ); for ( const int32_t value : damageReductionPercent ) { dmg = dmg * ( 100 - value ) / 100; } extraDamagePercent = defendingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactCurseType::FIRE_SPELL_EXTRA_DAMAGE_PERCENT ); for ( const int32_t value : extraDamagePercent ) { dmg = dmg * ( 100 + value ) / 100; } } break; } case Spell::LIGHTNINGBOLT: case Spell::CHAINLIGHTNING: { const std::vector extraDamagePercent = applyingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::LIGHTNING_SPELL_EXTRA_EFFECTIVENESS_PERCENT ); for ( const int32_t value : extraDamagePercent ) { dmg = dmg * ( 100 + value ) / 100; } if ( useDefendingHeroArts ) { const std::vector damageReductionPercent = defendingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::LIGHTNING_SPELL_DAMAGE_REDUCTION_PERCENT ); for ( const int32_t value : damageReductionPercent ) { dmg = dmg * ( 100 - value ) / 100; } } if ( spell.GetID() == Spell::CHAINLIGHTNING ) { switch ( targetDamage ) { case 0: break; case 1: dmg /= 2; break; case 2: dmg /= 4; break; case 3: dmg /= 8; break; default: break; } } break; } case Spell::ELEMENTALSTORM: case Spell::ARMAGEDDON: { if ( useDefendingHeroArts ) { const std::vector damageReductionPercent = defendingHero->GetBagArtifacts().getTotalArtifactMultipliedPercent( fheroes2::ArtifactBonusType::ELEMENTAL_SPELL_DAMAGE_REDUCTION_PERCENT ); for ( const int32_t value : damageReductionPercent ) { dmg = dmg * ( 100 - value ) / 100; } } break; } default: break; } } return dmg; } void Battle::Unit::SpellRestoreAction( const Spell & spell, const uint32_t spellPoints, const HeroBase * applyingHero ) { switch ( spell.GetID() ) { case Spell::CURE: case Spell::MASSCURE: // clear bad magic removeAffection( IS_BAD_MAGIC ); // restore hp += fheroes2::getHPRestorePoints( spell, spellPoints, applyingHero ); if ( hp > ArmyTroop::GetHitPoints() ) { hp = ArmyTroop::GetHitPoints(); } break; case Spell::RESURRECT: case Spell::ANIMATEDEAD: case Spell::RESURRECTTRUE: { if ( !isValid() ) { Graveyard * graveyard = Arena::GetGraveyard(); assert( graveyard != nullptr ); graveyard->removeUnit( this ); } const uint32_t restore = fheroes2::getResurrectPoints( spell, spellPoints, applyingHero ); const uint32_t resurrect = Resurrect( restore, false, ( spell == Spell::RESURRECT ) ); // Put the unit back on the board SetPosition( GetPosition() ); if ( Arena::GetInterface() ) { std::string str( _n( "%{count} %{name} rises from the dead!", "%{count} %{name} rise from the dead!", resurrect ) ); StringReplace( str, "%{count}", resurrect ); StringReplace( str, "%{name}", Monster::GetPluralName( resurrect ) ); Arena::GetInterface()->setStatus( str, true ); } break; } default: assert( 0 ); break; } } bool Battle::Unit::isDoubleAttack() const { if ( !isArchers() || isHandFighting() ) { return isAbilityPresent( fheroes2::MonsterAbilityType::DOUBLE_MELEE_ATTACK ); } // Archers with double shooting ability can only fire a second shot if they have enough ammo if ( isAbilityPresent( fheroes2::MonsterAbilityType::DOUBLE_SHOOTING ) ) { return GetShots() > 1; } return false; } uint32_t Battle::Unit::GetMagicResist( const Spell & spell, const HeroBase * applyingHero ) const { if ( Modes( SP_ANTIMAGIC ) ) { return 100; } switch ( spell.GetID() ) { case Spell::CURE: case Spell::MASSCURE: if ( !isHaveDamage() && !( modes & IS_BAD_MAGIC ) ) { return 100; } break; case Spell::RESURRECT: case Spell::RESURRECTTRUE: case Spell::ANIMATEDEAD: if ( GetCount() == _initialCount ) { return 100; } break; case Spell::DISPEL: case Spell::MASSDISPEL: if ( !( modes & IS_MAGIC ) ) { return 100; } break; case Spell::HYPNOTIZE: assert( applyingHero != nullptr ); if ( fheroes2::getHypnotizeMonsterHPPoints( spell, applyingHero->GetPower(), applyingHero ) < hp ) { return 100; } break; default: break; } const Artifact spellImmunityArt = getImmunityArtifactForSpell( GetCommander(), spell ); if ( spellImmunityArt.isValid() ) { return 100; } return fheroes2::getSpellResistance( id, spell.GetID() ); } int Battle::Unit::GetSpellMagic( Rand::DeterministicRandomGenerator & randomGenerator ) const { const std::vector & abilities = fheroes2::getMonsterData( GetID() ).battleStats.abilities; const auto abilityIter = std::find( abilities.begin(), abilities.end(), fheroes2::MonsterAbilityType::SPELL_CASTER ); if ( abilityIter == abilities.end() ) { // Not a spell caster. return Spell::NONE; } if ( randomGenerator.Get( 1, 100 ) > abilityIter->percentage ) { // No luck to cast the spell. return Spell::NONE; } return abilityIter->value; } bool Battle::Unit::isHaveDamage() const { return hp < _initialCount * Monster::GetHitPoints(); } bool Battle::Unit::SwitchAnimation( int rule, bool reverse ) { if ( rule == Monster_Info::STATIC && GetAnimationState() != Monster_Info::IDLE ) { // Reset the delay before switching to the 'IDLE' animation from 'STATIC'. checkIdleDelay(); } // We return true if the animation was correctly changed and if it is valid. return ( animation.switchAnimation( rule, reverse ) && animation.isValid() ); } bool Battle::Unit::SwitchAnimation( const std::vector & animationList, bool reverse ) { // We return true if the animation was correctly changed and if it is valid. return ( animation.switchAnimation( animationList, reverse ) && animation.isValid() ); } int Battle::Unit::M82Attk( const Unit & enemy ) const { const fheroes2::MonsterSound & sounds = fheroes2::getMonsterData( id ).sounds; if ( isArchers() && !isHandFighting( *this, enemy ) ) { // Added a new shooter without sound? Grant him a voice! assert( sounds.rangeAttack != M82::UNKNOWN ); return sounds.rangeAttack; } assert( sounds.meleeAttack != M82::UNKNOWN ); return sounds.meleeAttack; } int Battle::Unit::M82Kill() const { return fheroes2::getMonsterData( id ).sounds.death; } int Battle::Unit::M82Move() const { return fheroes2::getMonsterData( id ).sounds.movement; } int Battle::Unit::M82Wnce() const { return fheroes2::getMonsterData( id ).sounds.wince; } int Battle::Unit::M82Expl() const { return fheroes2::getMonsterData( id ).sounds.explosion; } int Battle::Unit::M82Tkof() const { return fheroes2::getMonsterData( id ).sounds.takeoff; } int Battle::Unit::M82Land() const { return fheroes2::getMonsterData( id ).sounds.landing; } fheroes2::Point Battle::Unit::GetBackPoint() const { const fheroes2::Rect & rt = position.GetRect(); return reflect ? fheroes2::Point( rt.x + rt.width, rt.y + rt.height / 2 ) : fheroes2::Point( rt.x, rt.y + rt.height / 2 ); } fheroes2::Point Battle::Unit::GetCenterPoint() const { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( GetMonsterSprite(), GetFrame() ); const fheroes2::Rect & pos = position.GetRect(); const int32_t centerY = pos.y + pos.height + sprite.y() / 2 - 10; return fheroes2::Point( pos.x + pos.width / 2, centerY ); } fheroes2::Point Battle::Unit::GetStartMissileOffset( size_t direction ) const { return animation.getProjectileOffset( direction ); } int Battle::Unit::GetCurrentColor() const { if ( Modes( SP_BERSERKER ) ) { return -1; // Be aware of unknown color } if ( Modes( SP_HYPNOTIZE ) ) { const Arena * arena = GetArena(); assert( arena != nullptr ); return arena->GetOppositeColor( GetArmyColor() ); } return GetColor(); } int Battle::Unit::GetCurrentOrArmyColor() const { const int color = GetCurrentColor(); // Unknown color in case of SP_BERSERKER mode if ( color < 0 ) { return GetArmyColor(); } return color; } int Battle::Unit::GetCurrentControl() const { // Let's say that berserkers belong to AI, which is not present in the battle if ( Modes( SP_BERSERKER ) ) { return CONTROL_AI; } if ( Modes( SP_HYPNOTIZE ) ) { const Arena * arena = GetArena(); assert( arena != nullptr ); return arena->getForce( GetCurrentColor() ).GetControl(); } return GetControl(); } const HeroBase * Battle::Unit::GetCommander() const { return GetArmy() ? GetArmy()->GetCommander() : nullptr; } const HeroBase * Battle::Unit::GetCurrentOrArmyCommander() const { const Arena * arena = GetArena(); assert( arena != nullptr ); return arena->getCommander( GetCurrentOrArmyColor() ); } void Battle::Unit::addAffection( const uint32_t mode, const uint32_t duration ) { assert( CountBits( mode ) == 1 ); SetModes( mode ); affected.AddMode( mode, duration ); } void Battle::Unit::removeAffection( const uint32_t mode ) { ResetModes( mode ); affected.RemoveMode( mode ); } void Battle::Unit::replaceAffection( const uint32_t modeToReplace, const uint32_t replacementMode, const uint32_t duration ) { removeAffection( modeToReplace ); addAffection( replacementMode, duration ); } fheroes2-1.1.6+dfsg/src/fheroes2/battle/battle_troop.h000066400000000000000000000304431476115357100226170ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "army_troop.h" #include "battle_animation.h" #include "battle_cell.h" #include "bitmodes.h" #include "math_base.h" #include "players.h" #include "resource.h" class Spell; class HeroBase; namespace Rand { class DeterministicRandomGenerator; } namespace Battle { struct TargetInfo; struct ModeDuration : public std::pair { ModeDuration( uint32_t, uint32_t ); bool isMode( uint32_t ) const; bool isZeroDuration() const; void DecreaseDuration(); }; struct ModesAffected : public std::vector { ModesAffected(); uint32_t GetMode( uint32_t ) const; void AddMode( uint32_t, uint32_t ); void RemoveMode( uint32_t ); void DecreaseDuration(); uint32_t FindZeroDuration() const; }; class Unit : public ArmyTroop, public BitModes, public Control { public: Unit( const Troop & troop, const Position & pos, const bool ref, const uint32_t uid ); Unit( const Unit & ) = delete; ~Unit() override = default; Unit & operator=( const Unit & ) = delete; bool isModes( uint32_t v ) const override; bool isBattle() const override; std::string GetShotString() const override; std::string GetSpeedString() const override; uint32_t GetHitPointsLeft() const override; virtual uint32_t GetMissingHitPoints() const; uint32_t GetAffectedDuration( uint32_t mod ) const override; uint32_t GetSpeed() const override; int GetMorale() const override; Unit * GetMirror() { return mirror; } void SetMirror( Unit * ptr ) { mirror = ptr; } void SetRandomMorale( Rand::DeterministicRandomGenerator & randomGenerator ); void SetRandomLuck( Rand::DeterministicRandomGenerator & randomGenerator ); void NewTurn(); bool isFlying() const; bool isDoubleAttack() const; bool AllowResponse() const; // Checks whether this unit is forced to fight in melee (there is an enemy unit nearby) bool isHandFighting() const; bool isReflect() const { return reflect; } bool isHaveDamage() const; bool isOutOfCastleWalls() const; std::string String( bool more = false ) const; uint32_t GetUID() const { return _uid; } bool isUID( uint32_t v ) const { return _uid == v; } int32_t GetHeadIndex() const; int32_t GetTailIndex() const; const Position & GetPosition() const { return position; } void SetPosition( const int32_t idx ); void SetPosition( const Position & pos ); void SetReflection( bool ); uint32_t GetAttack() const override; uint32_t GetDefense() const override; int GetArmyColor() const { return GetColor(); } // Returns the current color of the unit according to its current combat state (the unit // may be under a spell that changes its affiliation). int GetCurrentColor() const; // Returns the current unit color (if valid, the unit's color can be invalid if the unit // is under the Berserker spell), otherwise returns the color of the unit's army. int GetCurrentOrArmyColor() const; int GetControl() const override; int GetCurrentControl() const; // Returns the current speed of the unit, optionally performing additional checks in accordance // with the call arguments. If 'skipStandingCheck' is set to false, then the method returns // Speed::STANDING if the unit is immovable due to spells cast on it or if this unit is dead // (contains 0 fighters). Additionally, if 'skipMovedCheck' is set to false, then this method // returns Speed::STANDING if the unit has already completed its turn. If 'skipStandingCheck' // is set to true, then the value of 'skipMovedCheck' doesn't matter. uint32_t GetSpeed( const bool skipStandingCheck, const bool skipMovedCheck ) const; uint32_t GetDamage( const Unit & enemy, Rand::DeterministicRandomGenerator & randomGenerator ) const; // Returns the threat level of this unit, calculated as if it attacked the 'defender' unit. See // the implementation for details. int32_t evaluateThreatForUnit( const Unit & defender ) const; uint32_t GetInitialCount() const; uint32_t GetDead() const; uint32_t GetHitPoints() const; // Returns the cost of this unit, suitable for calculating the cost of surrendering the army (see // the implementation for details). Discounts are not applied when calculating this cost. Funds GetSurrenderCost() const; uint32_t GetShots() const override { return shots; } bool isImmovable() const; uint32_t ApplyDamage( Unit & enemy, const uint32_t dmg, uint32_t & killed, uint32_t * ptrResurrected ); uint32_t CalculateMinDamage( const Unit & ) const; uint32_t CalculateMaxDamage( const Unit & ) const; uint32_t CalculateDamageUnit( const Unit & enemy, double dmg ) const; // Returns a very rough estimate of the retaliatory damage after this unit receives the damage of the specified value. // The returned value is not suitable for accurate calculations, but only for approximate comparison with other units // in similar circumstances. uint32_t EstimateRetaliatoryDamage( const uint32_t damageTaken ) const; bool ApplySpell( const Spell & spell, const HeroBase * applyingHero, TargetInfo & target ); bool AllowApplySpell( const Spell & spell, const HeroBase * applyingHero, const bool forceApplyToAlly = false ) const; std::vector getCurrentSpellEffects() const; void PostAttackAction( const Unit & enemy ); // Sets whether a unit performs a retaliatory attack while being blinded (i.e. with reduced efficiency) void SetBlindRetaliation( const bool value ); uint32_t CalculateSpellDamage( const Spell & spell, uint32_t spellPower, const HeroBase * applyingHero, const uint32_t targetDamage, const bool ignoreDefendingHero ) const; bool SwitchAnimation( int rule, bool reverse = false ); bool SwitchAnimation( const std::vector & animationList, bool reverse = false ); void IncreaseAnimFrame( bool loop = false ) { animation.playAnimation( loop ); } bool isFinishAnimFrame() const { return animation.isLastFrame(); } int GetFrame() const { return animation.getFrame(); } uint8_t GetCustomAlpha() const { return customAlphaMask; } void SetCustomAlpha( uint8_t alpha ) { customAlphaMask = alpha; } fheroes2::Point GetStartMissileOffset( size_t ) const; int M82Attk( const Unit & enemy ) const; int M82Kill() const; int M82Move() const; int M82Wnce() const; int M82Expl() const; int M82Tkof() const; int M82Land() const; fheroes2::Point GetBackPoint() const; fheroes2::Point GetCenterPoint() const; fheroes2::Rect GetRectPosition() const { return position.GetRect(); } uint32_t HowManyWillBeKilled( const uint32_t dmg ) const; void SetResponse(); void UpdateDirection(); bool UpdateDirection( const fheroes2::Rect & ); void PostKilledAction(); uint32_t GetMagicResist( const Spell & spell, const HeroBase * applyingHero ) const; int GetSpellMagic( Rand::DeterministicRandomGenerator & randomGenerator ) const; const HeroBase * GetCommander() const; // If the color of the current unit is valid (i.e. this unit is not under the influence of a Berserker spell), then returns the commander of the army with the // corresponding color. Otherwise, returns the commander of the unit's army. const HeroBase * GetCurrentOrArmyCommander() const; // Checks whether the attacker will fight the defender in melee static bool isHandFighting( const Unit & attacker, const Unit & defender ); int GetAnimationState() const { return animation.getCurrentState(); } bool isIdling() const; bool checkIdleDelay() { return idleTimer.checkDelay(); } // Removes temporary affection(s) (usually spell effect(s)). Multiple affections can be removed using a single call. void removeAffection( const uint32_t mode ); // TODO: find a better way to expose it without a million getters/setters AnimationState animation; private: uint32_t ApplyDamage( const uint32_t dmg ); uint32_t Resurrect( const uint32_t points, const bool allowToExceedInitialCount, const bool isTemporary ); // Applies a damage-causing spell to this unit void SpellApplyDamage( const Spell & spell, const uint32_t spellPower, const HeroBase * applyingHero, TargetInfo & target ); // Applies a restoring or reviving spell to this unit void SpellRestoreAction( const Spell & spell, const uint32_t spellPoints, const HeroBase * applyingHero ); // Applies a spell to this unit that changes its parameters void SpellModesAction( const Spell & spell, uint32_t duration, const HeroBase * applyingHero ); // Adds a temporary affection (usually a spell effect) with the specified duration. Only one affection can be added. void addAffection( const uint32_t mode, const uint32_t duration ); // Replaces some temporary affection(s) with another affection. Multiple affections can be replaced by a new one (but // only one) with a single call. void replaceAffection( const uint32_t modeToReplace, const uint32_t replacementMode, const uint32_t duration ); const uint32_t _uid; uint32_t hp; uint32_t _initialCount; uint32_t dead; uint32_t shots; uint32_t _disruptingRaysNum; bool reflect; Position position; ModesAffected affected; Unit * mirror; RandomizedDelay idleTimer; // Whether a unit performs a retaliatory attack while being blinded (i.e. with reduced efficiency) bool _blindRetaliation; uint8_t customAlphaMask; }; } fheroes2-1.1.6+dfsg/src/fheroes2/campaign/000077500000000000000000000000001476115357100202505ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/campaign/campaign_data.cpp000066400000000000000000001723371476115357100235410ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "campaign_data.h" #include #include #include #include #include #include "artifact.h" #include "color.h" #include "game_video_type.h" #include "heroes.h" #include "maps_fileinfo.h" #include "monster.h" #include "resource.h" #include "spell.h" #include "tools.h" #include "translations.h" namespace { const std::vector emptyPlayback; std::vector getRolandCampaignAwardData( const int scenarioID ) { std::vector obtainableAwards; switch ( scenarioID ) { case 2: obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::DWARF, gettext_noop( "Dwarven Alliance" ) ); break; case 5: obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::ELIZA, 0, 0, gettext_noop( "Sorceress Guild" ) ); break; case 6: obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_CARRY_OVER_FORCES, 0, 0, 9 ); break; case 7: obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::ULTIMATE_CROWN, 1, 9 ); break; case 8: obtainableAwards.emplace_back( 4, Campaign::CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO, Heroes::CORLAGON, 0, 9 ); break; default: break; } return obtainableAwards; } std::vector getArchibaldCampaignAwardData( const int scenarioID ) { std::vector obtainableAwards; switch ( scenarioID ) { case 2: obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::BRAX, 0, 0, gettext_noop( "Necromancer Guild" ) ); break; case 3: obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::OGRE, gettext_noop( "Ogre Alliance" ) ); obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_CREATURE_CURSE, Monster::DWARF, gettext_noop( "Dwarfbane" ) ); break; case 6: obtainableAwards.emplace_back( 4, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::GREEN_DRAGON, gettext_noop( "Dragon Alliance" ) ); break; case 8: obtainableAwards.emplace_back( 5, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::ULTIMATE_CROWN ); break; case 9: obtainableAwards.emplace_back( 6, Campaign::CampaignAwardData::TYPE_CARRY_OVER_FORCES, 0 ); break; default: break; } return obtainableAwards; } std::vector getPriceOfLoyaltyCampaignAwardData( const int scenarioID ) { std::vector obtainableAwards; switch ( scenarioID ) { case 1: obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::BREASTPLATE_ANDURAN ); break; case 2: obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::ELF, gettext_noop( "Elven Alliance" ) ); obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_RESOURCE_BONUS, Resource::WOOD, 2 ); break; case 5: obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::HELMET_ANDURAN ); break; case 6: // Will assemble Battle Garb of Anduran along with the previous Anduran set pieces // If we get all the parts, we'll obtain the Battle Garb award while removing the awards for the individual parts obtainableAwards.emplace_back( 4, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::SWORD_ANDURAN ); // seems that Kraeger is a custom name for Dainwin in this case obtainableAwards.emplace_back( 5, Campaign::CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO, Heroes::DAINWIN, gettext_noop( "Kraeger defeated" ) ); break; default: break; } return obtainableAwards; } std::vector getWizardsIsleCampaignAwardData( const int scenarioID ) { std::vector obtainableAwards; switch ( scenarioID ) { case 1: obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_GET_SPELL, Spell::SETEGUARDIAN ); break; case 2: obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::SPHERE_NEGATION ); break; default: break; } return obtainableAwards; } std::vector getDescendantsCampaignAwardData( const int scenarioID ) { std::vector obtainableAwards; switch ( scenarioID ) { case 2: obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::JOSEPH, 0, 0, gettext_noop( "Wayward Son" ) ); break; case 3: obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::UNCLEIVAN, 0, 0, gettext_noop( "Uncle Ivan" ) ); break; case 5: obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::LEGENDARY_SCEPTER ); break; case 6: obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::ELF, gettext_noop( "Elven Alliance" ) ); break; default: break; } return obtainableAwards; } Campaign::CampaignData getRolandCampaignData() { const int scenarioCount = 11; const std::array scenarioName = { gettext_noop( "Force of Arms" ), gettext_noop( "Annexation" ), gettext_noop( "Save the Dwarves" ), gettext_noop( "Carator Mines" ), gettext_noop( "Turning Point" ), gettext_noop( "scenarioName|Defender" ), gettext_noop( "The Gauntlet" ), gettext_noop( "The Crown" ), gettext_noop( "Corlagon's Defense" ), gettext_noop( "Final Justice" ), gettext_noop( "Betrayal" ) }; const std::array scenarioDescription = { gettext_noop( "Roland needs you to defeat the lords near his castle to begin his war of rebellion against his brother. They are not allied with each other, so they will spend" " most of their time fighting with one another. Victory is yours when you have defeated all of their castles and heroes." ), gettext_noop( "The local lords refuse to swear allegiance to Roland, and must be subdued. They are wealthy and powerful, so be prepared for a tough fight. Capture all enemy castles to win." ), gettext_noop( "Your task is to defend the Dwarves against Archibald's forces. Capture all of the enemy towns and castles to win, and be sure not to lose all of the dwarf towns at once, or the enemy will have won." ), gettext_noop( "You will face four allied enemies in a straightforward fight for resources and treasure. Capture all of the enemy castles for victory." ), gettext_noop( "Your enemies are allied against you and start close by, so be ready to come out fighting. You will need to own all four castles in this small valley to win." ), gettext_noop( "The Sorceress' guild of Noraston has requested Roland's aid against an attack from Archibald's allies. Capture all of the enemy castles to win, and don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy castle on an island in the ocean.)" ), gettext_noop( "Gather as large an army as possible and capture the enemy castle within 8 weeks. You are opposed by only one enemy, but must travel a long way to get to the enemy castle. Any troops you have in your army at the end of this scenario will be with you in the final battle." ), gettext_noop( "Find the Crown before Archibald's heroes find it. Roland will need the Crown for the final battle against Archibald." ), gettext_noop( "Three allied enemies stand before you and victory, including Lord Corlagon. Roland is in a castle to the northwest, and you will lose if he falls to the enemy. Remember that capturing Lord Corlagon will ensure that he will not fight against you in the final scenario." ), gettext_noop( "This is the final battle. Both you and your enemy are armed to the teeth, and all are allied against you. Capture Archibald to end the war!" ), gettext_noop( "Switching sides leaves you with three castles against the enemy's one. This battle will be the easiest one you will face for the rest of the war...traitor." ) }; std::vector scenarioDatas; scenarioDatas.reserve( scenarioCount ); std::vector scenarioInfo; scenarioInfo.reserve( scenarioCount ); for ( int i = 0; i < scenarioCount; ++i ) { scenarioInfo.emplace_back( Campaign::ROLAND_CAMPAIGN, i ); } scenarioDatas.emplace_back( scenarioInfo[0], std::vector{ scenarioInfo[1] }, "CAMPG01.H2C", scenarioName[0], scenarioDescription[0], Campaign::VideoSequence{ { "GOOD01V.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD01.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[1], std::vector{ scenarioInfo[2], scenarioInfo[3] }, "CAMPG02.H2C", scenarioName[1], scenarioDescription[1], Campaign::VideoSequence{ { "GOOD02W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD02.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "GOOD03QW.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD03.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[2], std::vector{ scenarioInfo[3] }, "CAMPG03.H2C", scenarioName[2], scenarioDescription[2], emptyPlayback, Campaign::VideoSequence{ { "GOOD04W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD04.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::ScenarioVictoryCondition::STANDARD, Campaign::ScenarioLossCondition::LOSE_ALL_SORCERESS_VILLAGES ); scenarioDatas.emplace_back( scenarioInfo[3], std::vector{ scenarioInfo[4], scenarioInfo[10] }, "CAMPG04.H2C", scenarioName[3], scenarioDescription[3], emptyPlayback, Campaign::VideoSequence{ { "GOOD05V.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[4], std::vector{ scenarioInfo[5] }, "CAMPG05.H2C", scenarioName[4], scenarioDescription[4], emptyPlayback, Campaign::VideoSequence{ { "GOOD06AV.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD06.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[5], std::vector{ scenarioInfo[6], scenarioInfo[7] }, "CAMPG06.H2C", scenarioName[5], scenarioDescription[5], emptyPlayback, Campaign::VideoSequence{ { "GOOD07QW.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD07.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[6], std::vector{ scenarioInfo[8] }, "CAMPG07.H2C", scenarioName[6], scenarioDescription[6], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[7], std::vector{ scenarioInfo[8] }, "CAMPG08.H2C", scenarioName[7], scenarioDescription[7], emptyPlayback, emptyPlayback, Campaign::ScenarioVictoryCondition::OBTAIN_ULTIMATE_CROWN ); scenarioDatas.emplace_back( scenarioInfo[8], std::vector{ scenarioInfo[9] }, "CAMPG09.H2C", scenarioName[8], scenarioDescription[8], Campaign::VideoSequence{ { "GOOD09W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD09.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[9], std::vector{}, "CAMPG10.H2C", scenarioName[9], scenarioDescription[9], Campaign::VideoSequence{ { "GOOD10W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD10.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "LIBRARYW.SMK", Video::VideoAction::IGNORE_VIDEO }, { "LIBRARY.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); // At the end of the Betrayal scenario we should start an Archibald scenario. scenarioDatas.emplace_back( scenarioInfo[10], std::vector{ Campaign::ScenarioInfoId( Campaign::ARCHIBALD_CAMPAIGN, 5 ) }, "CAMPG05B.H2C", scenarioName[10], scenarioDescription[10], emptyPlayback, Campaign::VideoSequence{ { "EVIL06BW.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL06.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); Campaign::CampaignData campaignData; campaignData.setCampaignID( Campaign::ROLAND_CAMPAIGN ); campaignData.setCampaignScenarios( std::move( scenarioDatas ) ); return campaignData; } Campaign::CampaignData getArchibaldCampaignData() { const int scenarioCount = 12; const std::array scenarioName = { gettext_noop( "First Blood" ), gettext_noop( "Barbarian Wars" ), gettext_noop( "Necromancers" ), gettext_noop( "Slay the Dwarves" ), gettext_noop( "Turning Point" ), gettext_noop( "Rebellion" ), gettext_noop( "Dragon Master" ), gettext_noop( "Country Lords" ), gettext_noop( "The Crown" ), gettext_noop( "Greater Glory" ), gettext_noop( "Apocalypse" ), gettext_noop( "Betrayal" ) }; const std::array scenarioDescription = { gettext_noop( "King Archibald requires you to defeat the three enemies in this region. They are not allied with one another, so they will spend most of their energy fighting" " amongst themselves. You will win when you own all of the enemy castles and there are no more heroes left to fight." ), gettext_noop( "You must unify the barbarian tribes of the north by conquering them. As in the previous mission, the enemy is not allied against you, but they have more resources at their disposal. You will win when you own all of the enemy castles and there are no more heroes left to fight." ), gettext_noop( "Do-gooder wizards have taken the Necromancers' castle. You must retake it to achieve victory. Remember that while you start with a powerful army, you have no castle and must take one within 7 days, or lose this battle. (Hint: The nearest castle is to the southeast.)" ), gettext_noop( "The dwarves need conquering before they can interfere in King Archibald's plans. Roland's forces have more than one hero and many towns to start with, so be ready for attack from multiple directions. You must capture all of the enemy towns and castles to claim victory." ), gettext_noop( "Your enemies are allied against you and start close by, so be ready to come out fighting. You will need to own all four castles in this small valley to win." ), gettext_noop( "You must put down a peasant revolt led by Roland's forces. All are allied against you, but you have Lord Corlagon, an experienced hero, to help you. Capture all enemy castles to win." ), gettext_noop( "There are two enemies allied against you in this mission. Both are well armed and seek to evict you from their island. Avoid them and capture Dragon City to win." ), gettext_noop( "Your orders are to conquer the country lords that have sworn to serve Roland. All of the enemy castles are unified against you. Since you start without a castle, you must hurry to capture one before the end of the week. Capture all enemy castles for victory." ), gettext_noop( "Find the Crown before Roland's heroes find it. Archibald will need the Crown for the final battle against Roland." ), gettext_noop( "Gather as large an army as possible and capture the enemy castle within 8 weeks. You are opposed by only one enemy, but must travel a long way to get to the enemy castle. Any troops you have in your army at the end of this scenario will be with you in the final battle." ), gettext_noop( "This is the final battle. Both you and your enemy are armed to the teeth, and all are allied against you. Capture Roland to win the war, and be sure not to lose Archibald in the fight!" ), gettext_noop( "Switching sides leaves you with three castles against the enemy's one. This battle will be the easiest one you will face for the rest of the war...traitor." ) }; std::vector scenarioDatas; scenarioDatas.reserve( scenarioCount ); std::vector scenarioInfo; scenarioInfo.reserve( scenarioCount ); for ( int i = 0; i < scenarioCount; ++i ) { scenarioInfo.emplace_back( Campaign::ARCHIBALD_CAMPAIGN, i ); } scenarioDatas.emplace_back( scenarioInfo[0], std::vector{ scenarioInfo[1] }, "CAMPE01.H2C", scenarioName[0], scenarioDescription[0], Campaign::VideoSequence{ { "EVIL01V.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL01.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[1], std::vector{ scenarioInfo[2], scenarioInfo[3] }, "CAMPE02.H2C", scenarioName[1], scenarioDescription[1], Campaign::VideoSequence{ { "EVIL02W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL02.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "EVIL03QW.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL03.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[2], std::vector{ scenarioInfo[4], scenarioInfo[11] }, "CAMPE03.H2C", scenarioName[2], scenarioDescription[2], emptyPlayback, Campaign::VideoSequence{ { "EVIL05AV.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END }, { "SBETRAYV.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[3], std::vector{ scenarioInfo[4], scenarioInfo[11] }, "CAMPE04.H2C", scenarioName[3], scenarioDescription[3], emptyPlayback, Campaign::VideoSequence{ { "EVIL05BV.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END }, { "SBETRAYV.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[4], std::vector{ scenarioInfo[5] }, "CAMPE05.H2C", scenarioName[4], scenarioDescription[4], emptyPlayback, Campaign::VideoSequence{ { "EVIL06AW.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL06.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[5], std::vector{ scenarioInfo[6], scenarioInfo[7] }, "CAMPE06.H2C", scenarioName[5], scenarioDescription[5], emptyPlayback, Campaign::VideoSequence{ { "EVIL07W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL07.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[6], std::vector{ scenarioInfo[7] }, "CAMPE07.H2C", scenarioName[6], scenarioDescription[6], emptyPlayback, Campaign::VideoSequence{ { "EVIL08.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END } }, Campaign::ScenarioVictoryCondition::CAPTURE_DRAGON_CITY ); scenarioDatas.emplace_back( scenarioInfo[7], std::vector{ scenarioInfo[8], scenarioInfo[9] }, "CAMPE08.H2C", scenarioName[7], scenarioDescription[7], emptyPlayback, Campaign::VideoSequence{ { "EVIL09W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL09.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[8], std::vector{ scenarioInfo[10] }, "CAMPE09.H2C", scenarioName[8], scenarioDescription[8], emptyPlayback, emptyPlayback, Campaign::ScenarioVictoryCondition::OBTAIN_ULTIMATE_CROWN ); scenarioDatas.emplace_back( scenarioInfo[9], std::vector{ scenarioInfo[10] }, "CAMPE10.H2C", scenarioName[9], scenarioDescription[9], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[10], std::vector{}, "CAMPE11.H2C", scenarioName[10], scenarioDescription[10], Campaign::VideoSequence{ { "EVIL11W.SMK", Video::VideoAction::IGNORE_VIDEO }, { "EVIL10.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "PRISON.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END } } ); // At the end of the Betrayal scenario we should start a Roland scenario. scenarioDatas.emplace_back( scenarioInfo[11], std::vector{ Campaign::ScenarioInfoId( Campaign::ROLAND_CAMPAIGN, 5 ) }, "CAMPE05B.H2C", scenarioName[11], scenarioDescription[11], emptyPlayback, Campaign::VideoSequence{ { "GOOD06BV.SMK", Video::VideoAction::IGNORE_VIDEO }, { "GOOD06.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); Campaign::CampaignData campaignData; campaignData.setCampaignID( Campaign::ARCHIBALD_CAMPAIGN ); campaignData.setCampaignScenarios( std::move( scenarioDatas ) ); return campaignData; } Campaign::CampaignData getPriceOfLoyaltyCampaignData() { const int scenarioCount = 8; const std::array scenarioName = { gettext_noop( "Uprising" ), gettext_noop( "Island of Chaos" ), gettext_noop( "Arrow's Flight" ), gettext_noop( "The Abyss" ), gettext_noop( "The Giant's Pass" ), gettext_noop( "Aurora Borealis" ), gettext_noop( "Betrayal's End" ), gettext_noop( "Corruption's Heart" ) }; const std::array scenarioDescription = { gettext_noop( "Subdue the unruly local lords in order to provide the Empire with facilities to operate in this region." ), gettext_noop( "Eliminate all opposition in this area. Then the first piece of the artifact will be yours." ), gettext_noop( "The sorceresses to the northeast are rebelling! For the good of the empire you must quash their feeble uprising on your way to the mountains." ), gettext_noop( "Having prepared for your arrival, Kraeger has arranged for a force of necromancers to thwart your quest. You must capture the castle of Scabsdale before the first day of the third week, or the Necromancers will be too strong for you." ), gettext_noop( "The barbarian despot in this area is, as yet, ignorant of your presence. Quickly, build up your forces before you are discovered and attacked! Secure the region by subduing all enemy forces." ), gettext_noop( "The Empire is weak in this region. You will be unable to completely subdue all forces in this area, so take what you can before reprisal strikes. Remember, your true goal is to claim the Helmet of Anduran." ), gettext_noop( "For the good of the Empire, eliminate Kraeger." ), gettext_noop( "At last, you have the opportunity and the facilities to rid the Empire of the necromancer's evil. Eradicate them completely, and you will be sung as a hero for all time." ) }; std::vector scenarioDatas; scenarioDatas.reserve( 8 ); std::vector scenarioInfo; scenarioInfo.reserve( scenarioCount ); for ( int i = 0; i < scenarioCount; ++i ) { scenarioInfo.emplace_back( Campaign::PRICE_OF_LOYALTY_CAMPAIGN, i ); } scenarioDatas.emplace_back( scenarioInfo[0], std::vector{ scenarioInfo[1] }, "CAMP1_01.HXC", scenarioName[0], scenarioDescription[0], Campaign::VideoSequence{ { "MIXPOL1.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL1.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[1], std::vector{ scenarioInfo[2], scenarioInfo[3] }, "CAMP1_02.HXC", scenarioName[1], scenarioDescription[1], Campaign::VideoSequence{ { "MIXPOL2.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL2.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "MIXPOL3.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL3.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[2], std::vector{ scenarioInfo[4] }, "CAMP1_03.HXC", scenarioName[2], scenarioDescription[2], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[3], std::vector{ scenarioInfo[5] }, "CAMP1_04.HXC", scenarioName[3], scenarioDescription[3], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[4], std::vector{ scenarioInfo[5] }, "CAMP1_05.HXC", scenarioName[4], scenarioDescription[4], Campaign::VideoSequence{ { "MIXPOL4.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL4.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[5], std::vector{ scenarioInfo[6], scenarioInfo[7] }, "CAMP1_06.HXC", scenarioName[5], scenarioDescription[5], Campaign::VideoSequence{ { "MIXPOL5.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL5.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "MIXPOL6.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL6.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[6], std::vector{ scenarioInfo[7] }, "CAMP1_07.HXC", scenarioName[6], scenarioDescription[6], emptyPlayback, Campaign::VideoSequence{ { "MIXPOL7.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL7.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[7], std::vector{}, "CAMP1_08.HXC", scenarioName[7], scenarioDescription[7], emptyPlayback, Campaign::VideoSequence{ { "MIXPOL8.SMK", Video::VideoAction::IGNORE_VIDEO }, { "POL8.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); Campaign::CampaignData campaignData; campaignData.setCampaignID( Campaign::PRICE_OF_LOYALTY_CAMPAIGN ); campaignData.setCampaignScenarios( std::move( scenarioDatas ) ); return campaignData; } Campaign::CampaignData getDescendantsCampaignData() { const int scenarioCount = 8; const std::array scenarioName = { gettext_noop( "Conquer and Unify" ), gettext_noop( "Border Towns" ), gettext_noop( "The Wayward Son" ), gettext_noop( "Crazy Uncle Ivan" ), gettext_noop( "The Southern War" ), gettext_noop( "Ivory Gates" ), gettext_noop( "The Elven Lands" ), gettext_noop( "The Epic Battle" ) }; const std::array scenarioDescription = { gettext_noop( "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the forefather of all descendants." ), gettext_noop( "Your rival, the Kingdom of Harondale, is attacking weak towns on your border! Recover from their first strike and crush them completely!" ), gettext_noop( "Find your wayward son Joseph who is rumored to be living in the desolate lands. Do it before the first day of the third month or it will be of no help to your family." ), gettext_noop( "Rescue your crazy uncle Ivan. Find him before the first day of the fourth month or it will be of no help to your kingdom." ), gettext_noop( "Destroy the barbarians who are attacking the southern border of your kingdom! Recover your fallen towns, and then invade the jungle kingdom. Leave no enemy standing." ), gettext_noop( "Retake the castle of Ivory Gates, which has fallen due to treachery." ), gettext_noop( "Gain the favor of the elves. They will not allow trees to be chopped down, so we will send you wood every 2 weeks. You must complete your mission before the first day of the seventh month, or the kingdom will surely fall." ), gettext_noop( "This is the final battle against your rival kingdom of Harondale. Eliminate everyone, and don't lose the hero Jarkonas VI." ) }; std::vector scenarioDatas; scenarioDatas.reserve( 8 ); std::vector scenarioInfo; scenarioInfo.reserve( scenarioCount ); for ( int i = 0; i < scenarioCount; ++i ) { scenarioInfo.emplace_back( Campaign::DESCENDANTS_CAMPAIGN, i ); } scenarioDatas.emplace_back( scenarioInfo[0], std::vector{ scenarioInfo[1] }, "CAMP2_01.HXC", scenarioName[0], scenarioDescription[0], Campaign::VideoSequence{ { "MIXDES9.SMK", Video::VideoAction::IGNORE_VIDEO }, { "DES9.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[1], std::vector{ scenarioInfo[2], scenarioInfo[3] }, "CAMP2_02.HXC", scenarioName[1], scenarioDescription[1], Campaign::VideoSequence{ { "MIXDES10.SMK", Video::VideoAction::IGNORE_VIDEO }, { "DES10.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "MIXDES11.SMK", Video::VideoAction::IGNORE_VIDEO }, { "DES11.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[2], std::vector{ scenarioInfo[4] }, "CAMP2_03.HXC", scenarioName[2], scenarioDescription[2], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[3], std::vector{ scenarioInfo[4] }, "CAMP2_04.HXC", scenarioName[3], scenarioDescription[3], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[4], std::vector{ scenarioInfo[5], scenarioInfo[6] }, "CAMP2_05.HXC", scenarioName[4], scenarioDescription[4], Campaign::VideoSequence{ { "MIXDES12.SMK", Video::VideoAction::IGNORE_VIDEO }, { "DES12.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "MIXDES13.SMK", Video::VideoAction::IGNORE_VIDEO }, { "DES13.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[5], std::vector{ scenarioInfo[7] }, "CAMP2_06.HXC", scenarioName[5], scenarioDescription[5], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[6], std::vector{ scenarioInfo[7] }, "CAMP2_07.HXC", scenarioName[6], scenarioDescription[6], emptyPlayback, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[7], std::vector{}, "CAMP2_08.HXC", scenarioName[7], scenarioDescription[7], Campaign::VideoSequence{ { "MIXDES14.SMK", Video::VideoAction::IGNORE_VIDEO }, { "DES14.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "MIXDES15.SMK", Video::VideoAction::IGNORE_VIDEO }, { "DES15.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); Campaign::CampaignData campaignData; campaignData.setCampaignID( Campaign::DESCENDANTS_CAMPAIGN ); campaignData.setCampaignScenarios( std::move( scenarioDatas ) ); return campaignData; } Campaign::CampaignData getWizardsIsleCampaignData() { const int scenarioCount = 4; const std::array scenarioName = { gettext_noop( "The Shrouded Isles" ), gettext_noop( "The Eternal Scrolls" ), gettext_noop( "Power's End" ), gettext_noop( "Fount of Wizardry" ) }; const std::array scenarioDescription = { gettext_noop( "Your mission is to vanquish the warring mages in the magical Shrouded Isles. The completion of this task will give you a fighting chance against your rivals." ), gettext_noop( "The location of the great library has been discovered! You must make your way to it, and reclaim the city of Chronos in which it lies." ), gettext_noop( "Find the Orb of negation, which is said to be buried in this land. There are clues inscribed on stone obelisks which will help lead you to your prize. Find the Orb before the first day of the sixth month, or your rivals will surely have gotten to the fount before you." ), gettext_noop( "You must take control of the castle of Magic, where the fount of wizardry lies. Do this and your victory will be supreme." ) }; std::vector scenarioDatas; scenarioDatas.reserve( 4 ); std::vector scenarioInfo; scenarioInfo.reserve( scenarioCount ); for ( int i = 0; i < scenarioCount; ++i ) { scenarioInfo.emplace_back( Campaign::WIZARDS_ISLE_CAMPAIGN, i ); } scenarioDatas.emplace_back( scenarioInfo[0], std::vector{ scenarioInfo[1] }, "CAMP3_01.HXC", scenarioName[0], scenarioDescription[0], Campaign::VideoSequence{ { "MIXWIZ16.SMK", Video::VideoAction::IGNORE_VIDEO }, { "WIZ16.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[1], std::vector{ scenarioInfo[2], scenarioInfo[3] }, "CAMP3_02.HXC", scenarioName[1], scenarioDescription[1], Campaign::VideoSequence{ { "MIXWIZ17.SMK", Video::VideoAction::IGNORE_VIDEO }, { "WIZ17.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "MIXWIZ18.SMK", Video::VideoAction::IGNORE_VIDEO }, { "WIZ18.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[2], std::vector{ scenarioInfo[3] }, "CAMP3_03.HXC", scenarioName[2], scenarioDescription[2], emptyPlayback, Campaign::VideoSequence{ { "MIXWIZ19.SMK", Video::VideoAction::IGNORE_VIDEO }, { "WIZ19.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::ScenarioVictoryCondition::OBTAIN_SPHERE_NEGATION ); scenarioDatas.emplace_back( scenarioInfo[3], std::vector{}, "CAMP3_04.HXC", scenarioName[3], scenarioDescription[3], emptyPlayback, Campaign::VideoSequence{ { "MIXWIZ20.SMK", Video::VideoAction::IGNORE_VIDEO }, { "WIZ20.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); Campaign::CampaignData campaignData; campaignData.setCampaignID( Campaign::WIZARDS_ISLE_CAMPAIGN ); campaignData.setCampaignScenarios( std::move( scenarioDatas ) ); return campaignData; } Campaign::CampaignData getVoyageHomeCampaignData() { const int scenarioCount = 4; const std::array scenarioName = { gettext_noop( "Stranded" ), gettext_noop( "Pirate Isles" ), gettext_noop( "King and Country" ), gettext_noop( "Blood is Thicker" ) }; const std::array scenarioDescription = { gettext_noop( "Capture the town on the island off the southeast shore in order to construct a boat and travel back towards the mainland. Do not lose the hero Gallavant." ), gettext_noop( "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do not lose Gallavant or your quest will be over." ), gettext_noop( "Eliminate all the other forces who oppose the rule of Lord Alberon. Gallavant must not die." ), gettext_noop( "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in your name. Gallavant must not die." ) }; std::vector scenarioDatas; scenarioDatas.reserve( 4 ); std::vector scenarioInfo; scenarioInfo.reserve( scenarioCount ); for ( int i = 0; i < scenarioCount; ++i ) { scenarioInfo.emplace_back( Campaign::VOYAGE_HOME_CAMPAIGN, i ); } scenarioDatas.emplace_back( scenarioInfo[0], std::vector{ scenarioInfo[1] }, "CAMP4_01.HXC", scenarioName[0], scenarioDescription[0], Campaign::VideoSequence{ { "MIXVOY21.SMK", Video::VideoAction::IGNORE_VIDEO }, { "VOY21.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, emptyPlayback ); scenarioDatas.emplace_back( scenarioInfo[1], std::vector{ scenarioInfo[2], scenarioInfo[3] }, "CAMP4_02.HXC", scenarioName[1], scenarioDescription[1], Campaign::VideoSequence{ { "MIXVOY22.SMK", Video::VideoAction::IGNORE_VIDEO }, { "VOY22.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, Campaign::VideoSequence{ { "MIXVOY23.SMK", Video::VideoAction::IGNORE_VIDEO }, { "VOY23.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[2], std::vector{}, "CAMP4_03.HXC", scenarioName[2], scenarioDescription[2], emptyPlayback, Campaign::VideoSequence{ { "MIXVOY24.SMK", Video::VideoAction::IGNORE_VIDEO }, { "VOY24.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); scenarioDatas.emplace_back( scenarioInfo[3], std::vector{}, "CAMP4_04.HXC", scenarioName[3], scenarioDescription[3], emptyPlayback, Campaign::VideoSequence{ { "MIXVOY25.SMK", Video::VideoAction::IGNORE_VIDEO }, { "VOY25.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); Campaign::CampaignData campaignData; campaignData.setCampaignID( Campaign::VOYAGE_HOME_CAMPAIGN ); campaignData.setCampaignScenarios( std::move( scenarioDatas ) ); return campaignData; } } namespace Campaign { // this is used to get awards that are not directly obtainable via scenario clear, such as assembling artifacts std::vector CampaignAwardData::getExtraCampaignAwardData( const int campaignID ) { assert( campaignID >= 0 ); switch ( campaignID ) { case PRICE_OF_LOYALTY_CAMPAIGN: { std::vector extraAwards; extraAwards.emplace_back( 10, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::BATTLE_GARB ); return extraAwards; } case ROLAND_CAMPAIGN: case ARCHIBALD_CAMPAIGN: case DESCENDANTS_CAMPAIGN: case WIZARDS_ISLE_CAMPAIGN: case VOYAGE_HOME_CAMPAIGN: break; default: // Did you add a new campaign? Add the case handling code for it! assert( 0 ); break; } return {}; } const std::vector & CampaignData::getScenariosAfter( const ScenarioInfoId & scenarioInfo ) { const CampaignData & campaignData = getCampaignData( scenarioInfo.campaignId ); const std::vector & scenarios = campaignData.getAllScenarios(); assert( scenarioInfo.scenarioId >= 0 && static_cast( scenarioInfo.scenarioId ) < scenarios.size() ); return scenarios[scenarioInfo.scenarioId].getNextScenarios(); } std::vector CampaignData::getStartingScenarios() const { std::vector startingScenarios; for ( size_t i = 0; i < _scenarios.size(); ++i ) { const int scenarioID = _scenarios[i].getScenarioID(); if ( isStartingScenario( { _campaignID, scenarioID } ) ) startingScenarios.emplace_back( _campaignID, scenarioID ); } return startingScenarios; } bool CampaignData::isStartingScenario( const ScenarioInfoId & scenarioInfo ) const { // starting scenario = a scenario that is never included as a nextMap for ( size_t i = 0; i < _scenarios.size(); ++i ) { const std::vector & nextMaps = _scenarios[i].getNextScenarios(); if ( std::find( nextMaps.begin(), nextMaps.end(), scenarioInfo ) != nextMaps.end() ) return false; } return true; } bool CampaignData::isAllCampaignMapsPresent() const { for ( size_t i = 0; i < _scenarios.size(); ++i ) { if ( !_scenarios[i].isMapFilePresent() ) return false; } return true; } bool CampaignData::isLastScenario( const Campaign::ScenarioInfoId & scenarioInfoId ) const { assert( !_scenarios.empty() ); for ( const ScenarioData & scenario : _scenarios ) { if ( ( scenario.getScenarioInfoId() == scenarioInfoId ) && scenario.getNextScenarios().empty() ) { return true; } } return false; } void CampaignData::setCampaignScenarios( std::vector && scenarios ) { _scenarios = std::move( scenarios ); } const CampaignData & CampaignData::getCampaignData( const int campaignID ) { switch ( campaignID ) { case ROLAND_CAMPAIGN: { static const Campaign::CampaignData campaign( getRolandCampaignData() ); return campaign; } case ARCHIBALD_CAMPAIGN: { static const Campaign::CampaignData campaign( getArchibaldCampaignData() ); return campaign; } case PRICE_OF_LOYALTY_CAMPAIGN: { static const Campaign::CampaignData campaign( getPriceOfLoyaltyCampaignData() ); return campaign; } case DESCENDANTS_CAMPAIGN: { static const Campaign::CampaignData campaign( getDescendantsCampaignData() ); return campaign; } case VOYAGE_HOME_CAMPAIGN: { static const Campaign::CampaignData campaign( getVoyageHomeCampaignData() ); return campaign; } case WIZARDS_ISLE_CAMPAIGN: { static const Campaign::CampaignData campaign( getWizardsIsleCampaignData() ); return campaign; } default: { // Did you add a new campaign? Add the corresponding case above. assert( 0 ); static const Campaign::CampaignData noCampaign; return noCampaign; } } } void CampaignData::updateScenarioGameplayConditions( const Campaign::ScenarioInfoId & scenarioInfoId, Maps::FileInfo & mapInfo ) { bool allAIPlayersInAlliance = false; switch ( scenarioInfoId.campaignId ) { case ROLAND_CAMPAIGN: if ( scenarioInfoId.scenarioId == 9 ) { allAIPlayersInAlliance = true; } break; case ARCHIBALD_CAMPAIGN: if ( scenarioInfoId.scenarioId == 5 || scenarioInfoId.scenarioId == 10 ) { allAIPlayersInAlliance = true; } break; case PRICE_OF_LOYALTY_CAMPAIGN: case DESCENDANTS_CAMPAIGN: case VOYAGE_HOME_CAMPAIGN: case WIZARDS_ISLE_CAMPAIGN: break; default: // Did you add a new campaign? Add the corresponding case above. assert( 0 ); return; } if ( allAIPlayersInAlliance ) { const Colors humanColors( mapInfo.colorsAvailableForHumans ); // Make sure that this is only one human player on the map. if ( humanColors.size() != 1 ) { // Looks like somebody is modifying the original map. assert( 0 ); return; } const int aiColors = ( mapInfo.kingdomColors & ( ~mapInfo.colorsAvailableForHumans ) ); if ( aiColors == 0 ) { // This is definitely not the map to modify. assert( 0 ); return; } // If this assertion blows up then the whole logic behind colors is going crazy. assert( aiColors < 256 ); const uint8_t humanColor = static_cast( humanColors.front() ); for ( uint8_t & allianceColor : mapInfo.unions ) { if ( allianceColor != humanColor && ( aiColors & allianceColor ) ) { allianceColor = static_cast( aiColors ); } } } } // default amount to 1 for initialized campaign award data CampaignAwardData::CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType ) : CampaignAwardData( id, type, subType, 1, 0 ) { // Do nothing. } CampaignAwardData::CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType, const int32_t amount ) : CampaignAwardData( id, type, subType, amount, 0 ) { // Do nothing. } CampaignAwardData::CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType, std::string customName ) : CampaignAwardData( id, type, subType, 1, 0, std::move( customName ) ) { // Do nothing. } CampaignAwardData::CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType, const int32_t amount, const int32_t startScenarioID, std::string customName ) : _id( id ) , _type( type ) , _subType( subType ) , _amount( amount ) , _startScenarioID( startScenarioID ) , _customName( std::move( customName ) ) { // Do nothing. } std::string CampaignAwardData::getName() const { if ( !_customName.empty() ) return _( _customName ); switch ( _type ) { case CampaignAwardData::TYPE_CREATURE_CURSE: return Monster( _subType ).GetName() + std::string( _( " bane" ) ); case CampaignAwardData::TYPE_CREATURE_ALLIANCE: return Monster( _subType ).GetName() + std::string( _( " alliance" ) ); case CampaignAwardData::TYPE_GET_ARTIFACT: return Artifact( _subType ).GetName(); case CampaignAwardData::TYPE_CARRY_OVER_FORCES: return _( "Carry-over forces" ); case CampaignAwardData::TYPE_RESOURCE_BONUS: return Resource::String( _subType ) + std::string( _( " bonus" ) ); case CampaignAwardData::TYPE_GET_SPELL: return Spell( _subType ).GetName(); case CampaignAwardData::TYPE_HIREABLE_HERO: return Heroes( _subType, 0 ).GetName(); case CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO: return Heroes( _subType, 0 ).GetName() + std::string( _( " defeated" ) ); default: // Did you add a new award? Add the logic above! assert( 0 ); break; } return {}; } std::string CampaignAwardData::getDescription() const { switch ( _type ) { case CampaignAwardData::TYPE_CREATURE_CURSE: { std::vector monsters; monsters.emplace_back( _subType ); std::string description( monsters.back().GetMultiName() ); while ( monsters.back() != monsters.back().GetUpgrade() ) { monsters.emplace_back( monsters.back().GetUpgrade() ); description += ", "; description += monsters.back().GetMultiName(); } description += _( " will always run away from your army." ); return description; } case CampaignAwardData::TYPE_CREATURE_ALLIANCE: { std::vector monsters; monsters.emplace_back( _subType ); std::string description( monsters.back().GetMultiName() ); while ( monsters.back() != monsters.back().GetUpgrade() ) { monsters.emplace_back( monsters.back().GetUpgrade() ); description += ", "; description += monsters.back().GetMultiName(); } description += _( " will be willing to join your army." ); return description; } case CampaignAwardData::TYPE_GET_ARTIFACT: { std::string description( _( "\"%{artifact}\" artifact will be carried over in the campaign." ) ); StringReplace( description, "%{artifact}", Artifact( _subType ).GetName() ); return description; } case CampaignAwardData::TYPE_CARRY_OVER_FORCES: { return _( "The army will be carried over in the campaign." ); } case CampaignAwardData::TYPE_RESOURCE_BONUS: { std::string description( _( "The kingdom will have +%{count} %{resource} each day." ) ); StringReplace( description, "%{count}", std::to_string( _amount ) ); StringReplace( description, "%{resource}", Resource::String( _subType ) ); return description; } case CampaignAwardData::TYPE_GET_SPELL: { std::string description( _( "The \"%{spell}\" spell will be carried over in the campaign." ) ); StringReplace( description, "%{spell}", Spell( _subType ).GetName() ); return description; } case CampaignAwardData::TYPE_HIREABLE_HERO: { std::string description( _( "%{hero} can be hired during scenarios." ) ); StringReplace( description, "%{hero}", Heroes( _subType, 0 ).GetName() ); return description; } case CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO: { std::string description( _( "%{hero} has been defeated and will not appear in subsequent scenarios." ) ); StringReplace( description, "%{hero}", Heroes( _subType, 0 ).GetName() ); return description; } default: // Did you add a new award? Add the logic above! assert( 0 ); break; } return {}; } std::vector CampaignAwardData::getCampaignAwardData( const ScenarioInfoId & scenarioInfo ) { assert( scenarioInfo.campaignId >= 0 && scenarioInfo.scenarioId >= 0 ); switch ( scenarioInfo.campaignId ) { case ROLAND_CAMPAIGN: return getRolandCampaignAwardData( scenarioInfo.scenarioId ); case ARCHIBALD_CAMPAIGN: return getArchibaldCampaignAwardData( scenarioInfo.scenarioId ); case PRICE_OF_LOYALTY_CAMPAIGN: return getPriceOfLoyaltyCampaignAwardData( scenarioInfo.scenarioId ); case DESCENDANTS_CAMPAIGN: return getDescendantsCampaignAwardData( scenarioInfo.scenarioId ); case WIZARDS_ISLE_CAMPAIGN: return getWizardsIsleCampaignAwardData( scenarioInfo.scenarioId ); case VOYAGE_HOME_CAMPAIGN: // No campaign award for voyage home! return {}; default: // Did you add a new campaign? Add the corresponding case above. assert( 0 ); break; } return {}; } const char * CampaignAwardData::getAllianceJoiningMessage( const int monsterId ) { switch ( monsterId ) { case Monster::DWARF: case Monster::BATTLE_DWARF: return _( "The dwarves recognize their allies and gladly join your forces." ); case Monster::OGRE: case Monster::OGRE_LORD: return _( "The ogres recognize you as the Dwarfbane and lumber over to join you." ); case Monster::GREEN_DRAGON: case Monster::RED_DRAGON: case Monster::BLACK_DRAGON: return _( "The dragons, snarling and growling, agree to join forces with you, their 'Ally'." ); case Monster::ELF: case Monster::GRAND_ELF: return _( "As you approach the group of elves, their leader calls them all to attention. He shouts to them, \"Who of you is brave enough to join this fearless ally of ours?\" The group explodes with cheers as they run to join your ranks." ); default: break; } assert( 0 ); // Did you forget to add a new alliance type? return nullptr; } const char * CampaignAwardData::getAllianceFleeingMessage( const int monsterId ) { switch ( monsterId ) { case Monster::DWARF: case Monster::BATTLE_DWARF: return _( "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may pass.\"" ); case Monster::OGRE: case Monster::OGRE_LORD: return _( "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" ); case Monster::GREEN_DRAGON: case Monster::RED_DRAGON: case Monster::BLACK_DRAGON: return _( "The dragons see you and call out. \"Our alliance with Archibald compels us to join you. Unfortunately you have no room. A pity!\" They quickly scatter." ); case Monster::ELF: case Monster::GRAND_ELF: return _( "The elves stand at attention as you approach. Their leader calls to you and says, \"Let us not impede your progress, ally! Move on, and may victory be yours.\"" ); default: break; } assert( 0 ); // Did you forget to add a new alliance type? return nullptr; } const char * CampaignAwardData::getBaneFleeingMessage( const int monsterId ) { switch ( monsterId ) { case Monster::DWARF: case Monster::BATTLE_DWARF: return _( "\"The Dwarfbane!!!!, run for your lives.\"" ); default: break; } assert( 0 ); // Did you forget to add a new bane type? return nullptr; } } fheroes2-1.1.6+dfsg/src/fheroes2/campaign/campaign_data.h000066400000000000000000000116721476115357100232000ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "campaign_scenariodata.h" namespace Maps { struct FileInfo; } namespace Campaign { class CampaignData { public: int getCampaignID() const { return _campaignID; } const std::vector & getAllScenarios() const { return _scenarios; } static const std::vector & getScenariosAfter( const ScenarioInfoId & scenarioInfo ); std::vector getStartingScenarios() const; bool isAllCampaignMapsPresent() const; bool isLastScenario( const Campaign::ScenarioInfoId & scenarioInfoId ) const; void setCampaignID( const int campaignID ) { _campaignID = campaignID; } void setCampaignScenarios( std::vector && scenarios ); static const CampaignData & getCampaignData( const int campaignID ); // Some scenarios have different gameplay conditions like unions which are not specified within the map file itself. static void updateScenarioGameplayConditions( const Campaign::ScenarioInfoId & scenarioInfoId, Maps::FileInfo & mapInfo ); private: int _campaignID{ 0 }; std::string _campaignName; std::vector _scenarios; bool isStartingScenario( const ScenarioInfoId & scenarioInfo ) const; }; struct CampaignAwardData { public: enum AwardType : int32_t { TYPE_CREATURE_CURSE, // eg: dwarf bane TYPE_CREATURE_ALLIANCE, // eg: dwarf alliance TYPE_GET_ARTIFACT, // eg: ultimate crown TYPE_GET_SPELL, // eg: guardian spell in wizard's isle TYPE_CARRY_OVER_FORCES, // eg: the gauntlet TYPE_HIREABLE_HERO, // eg: sorceress guild TYPE_DEFEAT_ENEMY_HERO, // eg: corlagon defeated TYPE_RESOURCE_BONUS, // eg: wood bonus in price of loyalty }; // NOTE: Carry over forces shouldn't use these other than id, type and startScenarioID // IDs are here so that we just have to store an int instead of the entire award data in a campaign save data // also usable when we have to remove specific awards when completing a mission (PoL campaign) int32_t _id; int32_t _type; int32_t _subType; int32_t _amount; int32_t _startScenarioID; std::string _customName; CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType ); CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType, const int32_t amount ); CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType, std::string customName ); CampaignAwardData( const int32_t id, const int32_t type, const int32_t subType, const int32_t amount, const int32_t startScenarioID, std::string customName = std::string() ); std::string getName() const; std::string getDescription() const; static std::vector getCampaignAwardData( const ScenarioInfoId & scenarioInfo ); static std::vector getExtraCampaignAwardData( const int campaignID ); static const char * getAllianceJoiningMessage( const int monsterId ); static const char * getAllianceFleeingMessage( const int monsterId ); static const char * getBaneFleeingMessage( const int monsterId ); }; } fheroes2-1.1.6+dfsg/src/fheroes2/campaign/campaign_savedata.cpp000066400000000000000000000252761476115357100244170ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "campaign_savedata.h" #include #include #include #include #include #include "army.h" #include "campaign_data.h" #include "difficulty.h" #include "serialize.h" namespace Campaign { CampaignSaveData & Campaign::CampaignSaveData::Get() { static CampaignSaveData instance; return instance; } void CampaignSaveData::addCampaignAward( const int awardID ) { _obtainedCampaignAwards.emplace_back( awardID ); } void CampaignSaveData::removeCampaignAward( const int awardID ) { _obtainedCampaignAwards.erase( std::remove( _obtainedCampaignAwards.begin(), _obtainedCampaignAwards.end(), awardID ), _obtainedCampaignAwards.end() ); } void CampaignSaveData::setEnemyDefeatedAward( const int heroId ) { const ScenarioInfoId & currentScenarioInfo = getCurrentScenarioInfoId(); const std::vector obtainableAwards = CampaignAwardData::getCampaignAwardData( currentScenarioInfo ); for ( const auto & obtainableAward : obtainableAwards ) { const int32_t awardType = obtainableAward._type; if ( awardType == CampaignAwardData::AwardType::TYPE_DEFEAT_ENEMY_HERO ) { if ( obtainableAward._subType == heroId ) { addCampaignAward( obtainableAward._id ); } break; } } } void CampaignSaveData::setCurrentScenarioInfo( const ScenarioInfoId & scenarioInfoId, const int32_t bonusId /* = -1 */ ) { assert( scenarioInfoId.campaignId >= 0 && scenarioInfoId.scenarioId >= 0 ); _currentScenarioInfoId = scenarioInfoId; _currentScenarioBonusId = bonusId; } void CampaignSaveData::addCurrentMapToFinished() { // Check for a duplicate if ( std::find( _finishedMaps.begin(), _finishedMaps.end(), _currentScenarioInfoId ) != _finishedMaps.end() ) { return; } _finishedMaps.emplace_back( _currentScenarioInfoId ); _bonusesForFinishedMaps.emplace_back( _currentScenarioBonusId ); assert( _finishedMaps.size() == _bonusesForFinishedMaps.size() ); } void CampaignSaveData::addDaysPassed( const uint32_t days ) { _daysPassed += days; } void CampaignSaveData::reset() { _finishedMaps.clear(); _bonusesForFinishedMaps.clear(); _obtainedCampaignAwards.clear(); _carryOverTroops.clear(); _currentScenarioInfoId = { -1, -1 }; _currentScenarioBonusId = -1; _daysPassed = 0; _difficulty = CampaignDifficulty::Normal; } void CampaignSaveData::setCarryOverTroops( const Troops & troops ) { _carryOverTroops.clear(); for ( size_t i = 0; i < troops.Size(); ++i ) { _carryOverTroops.emplace_back( *troops.GetTroop( i ) ); } } const ScenarioInfoId & CampaignSaveData::getLastCompletedScenarioInfoID() const { assert( !_finishedMaps.empty() ); return _finishedMaps.back(); } uint32_t CampaignSaveData::getCampaignDifficultyPercent() const { switch ( _difficulty ) { case CampaignDifficulty::Easy: return 125; case CampaignDifficulty::Normal: // Original campaign difficulty. return 100; case CampaignDifficulty::Hard: return 75; default: // Did you add a new campaign difficulty? Add the logic above! assert( 0 ); return 100; } } std::vector CampaignSaveData::getObtainedCampaignAwards() const { std::vector obtainedAwards; for ( size_t i = 0; i < _finishedMaps.size(); ++i ) { const std::vector awards = Campaign::CampaignAwardData::getCampaignAwardData( _finishedMaps[i] ); for ( size_t j = 0; j < awards.size(); ++j ) { if ( std::find( _obtainedCampaignAwards.begin(), _obtainedCampaignAwards.end(), awards[j]._id ) != _obtainedCampaignAwards.end() ) obtainedAwards.emplace_back( awards[j] ); } } const std::vector extraAwards = Campaign::CampaignAwardData::getExtraCampaignAwardData( _currentScenarioInfoId.campaignId ); for ( const Campaign::CampaignAwardData & award : extraAwards ) { if ( std::find( _obtainedCampaignAwards.begin(), _obtainedCampaignAwards.end(), award._id ) != _obtainedCampaignAwards.end() ) obtainedAwards.emplace_back( award ); } return obtainedAwards; } OStreamBase & operator<<( OStreamBase & stream, const CampaignSaveData & data ) { return stream << data._currentScenarioInfoId.campaignId << data._currentScenarioInfoId.scenarioId << data._currentScenarioBonusId << data._finishedMaps << data._bonusesForFinishedMaps << data._daysPassed << data._obtainedCampaignAwards << data._carryOverTroops << data._difficulty; } IStreamBase & operator>>( IStreamBase & stream, CampaignSaveData & data ) { stream >> data._currentScenarioInfoId.campaignId >> data._currentScenarioInfoId.scenarioId >> data._currentScenarioBonusId >> data._finishedMaps >> data._bonusesForFinishedMaps; // Make sure that the number of elements in the vector of map bonuses matches the number of elements in the vector of finished maps data._bonusesForFinishedMaps.resize( data._finishedMaps.size(), -1 ); return stream >> data._daysPassed >> data._obtainedCampaignAwards >> data._carryOverTroops >> data._difficulty; } ScenarioVictoryCondition getCurrentScenarioVictoryCondition() { const CampaignSaveData & campaignData = CampaignSaveData::Get(); const std::vector & scenarios = CampaignData::getCampaignData( campaignData.getCampaignID() ).getAllScenarios(); const int scenarioId = campaignData.getCurrentScenarioID(); assert( scenarioId >= 0 && static_cast( scenarioId ) < scenarios.size() ); if ( scenarioId >= 0 && static_cast( scenarioId ) < scenarios.size() ) { return scenarios[scenarioId].getVictoryCondition(); } return ScenarioVictoryCondition::STANDARD; } ScenarioLossCondition getCurrentScenarioLossCondition() { const CampaignSaveData & campaignData = CampaignSaveData::Get(); const std::vector & scenarios = CampaignData::getCampaignData( campaignData.getCampaignID() ).getAllScenarios(); const int scenarioId = campaignData.getCurrentScenarioID(); assert( scenarioId >= 0 && static_cast( scenarioId ) < scenarios.size() ); if ( scenarioId >= 0 && static_cast( scenarioId ) < scenarios.size() ) { return scenarios[scenarioId].getLossCondition(); } return ScenarioLossCondition::STANDARD; } std::optional getCurrentScenarioDifficultyLevel() { static const std::map, int> adjustedDifficultyLevels = { // Roland { { ROLAND_CAMPAIGN, 1 }, Difficulty::EASY }, // Archibald { { ARCHIBALD_CAMPAIGN, 1 }, Difficulty::EASY }, // Descendants { { DESCENDANTS_CAMPAIGN, 0 }, Difficulty::EASY }, { { DESCENDANTS_CAMPAIGN, 5 }, Difficulty::HARD }, // Wizard's Isle { { WIZARDS_ISLE_CAMPAIGN, 3 }, Difficulty::HARD }, // Voyage Home { { VOYAGE_HOME_CAMPAIGN, 0 }, Difficulty::EASY }, // Price of Loyalty { { PRICE_OF_LOYALTY_CAMPAIGN, 0 }, Difficulty::EASY }, { { PRICE_OF_LOYALTY_CAMPAIGN, 5 }, Difficulty::HARD }, { { PRICE_OF_LOYALTY_CAMPAIGN, 6 }, Difficulty::HARD }, { { PRICE_OF_LOYALTY_CAMPAIGN, 7 }, Difficulty::EXPERT } }; const CampaignSaveData & campaignData = CampaignSaveData::Get(); const auto iter = adjustedDifficultyLevels.find( { campaignData.getCampaignID(), campaignData.getCurrentScenarioID() } ); if ( iter == adjustedDifficultyLevels.end() ) { return {}; } return iter->second; } } fheroes2-1.1.6+dfsg/src/fheroes2/campaign/campaign_savedata.h000066400000000000000000000123701476115357100240530ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "army_troop.h" #include "campaign_scenariodata.h" class IStreamBase; class OStreamBase; class Troops; namespace Campaign { struct CampaignAwardData; enum CampaignDifficulty : int32_t { Easy = -1, Normal = 0, Hard = 1 }; class CampaignSaveData { public: const std::vector & getFinishedMaps() const { return _finishedMaps; } int getCampaignID() const { return _currentScenarioInfoId.campaignId; } int getCurrentScenarioID() const { return _currentScenarioInfoId.scenarioId; } const ScenarioInfoId & getCurrentScenarioInfoId() const { return _currentScenarioInfoId; } int32_t getCurrentScenarioBonusId() const { return _currentScenarioBonusId; } // Make sure that this is not the first scenario in the campaign. Please call isStarting to verify this. const ScenarioInfoId & getLastCompletedScenarioInfoID() const; bool isStarting() const { return _finishedMaps.empty(); } uint32_t getDaysPassed() const { return _daysPassed; } int32_t getDifficulty() const { return _difficulty; } void setDifficulty( const int32_t difficulty ) { _difficulty = difficulty; } // Get the campaign difficulty in percents for rating calculations. uint32_t getCampaignDifficultyPercent() const; const std::vector & getCarryOverTroops() const { return _carryOverTroops; } std::vector getObtainedCampaignAwards() const; void setCurrentScenarioInfo( const ScenarioInfoId & scenarioInfoId, const int32_t bonusId = -1 ); void addCurrentMapToFinished(); void addCampaignAward( const int awardID ); void setCarryOverTroops( const Troops & troops ); void reset(); void addDaysPassed( const uint32_t days ); void removeCampaignAward( const int awardID ); void setEnemyDefeatedAward( const int heroId ); void removeAllAwards() { _obtainedCampaignAwards.clear(); } static CampaignSaveData & Get(); private: friend OStreamBase & operator<<( OStreamBase & stream, const CampaignSaveData & data ); friend IStreamBase & operator>>( IStreamBase & stream, CampaignSaveData & data ); CampaignSaveData() = default; std::vector _finishedMaps; std::vector _bonusesForFinishedMaps; std::vector _obtainedCampaignAwards; std::vector _carryOverTroops; ScenarioInfoId _currentScenarioInfoId; int32_t _currentScenarioBonusId{ -1 }; uint32_t _daysPassed{ 0 }; int32_t _difficulty{ CampaignDifficulty::Normal }; }; // Call this function only when playing campaign scenario. ScenarioVictoryCondition getCurrentScenarioVictoryCondition(); // Call this function only when playing campaign scenario. ScenarioLossCondition getCurrentScenarioLossCondition(); // For some scenarios of the original campaign, the difficulty of the scenario does not match the difficulty of the corresponding campaign map (these values are // hard-coded in the game itself). This function returns either the adjusted difficulty for the currently active scenario, if required, or an empty result (and in // that case the difficulty of the corresponding campaign map should be used). Call this function only when playing campaign scenario. std::optional getCurrentScenarioDifficultyLevel(); } fheroes2-1.1.6+dfsg/src/fheroes2/campaign/campaign_scenariodata.cpp000066400000000000000000001150421476115357100252530ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "campaign_scenariodata.h" #include #include #include #include #include #include #include #include "artifact.h" #include "dir.h" #include "maps_fileinfo.h" #include "monster.h" #include "race.h" #include "resource.h" #include "serialize.h" #include "settings.h" #include "skill.h" #include "spell.h" #include "system.h" #include "tools.h" #include "translations.h" namespace { std::vector getRolandCampaignBonusData( const int scenarioID ) { std::vector bonus; switch ( scenarioID ) { case 0: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::THUNDER_MACE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::ARMORED_GAUNTLETS, 1 ); break; case 1: case 2: case 3: case 4: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WZRD, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::SORC, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::KNGT, 1 ); break; case 5: bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::MIRRORIMAGE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::SUMMONEELEMENT, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::RESURRECT, 1 ); break; case 6: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::BLACK_PEARL, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::DRAGON_SWORD, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::DIVINE_BREASTPLATE, 1 ); break; case 7: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WZRD, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::SORC, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::KNGT, 1 ); break; case 8: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::CRYSTAL, 20 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GEMS, 20 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::MERCURY, 20 ); break; case 9: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::TAX_LIEN, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::HIDEOUS_MASK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::FIZBIN_MISFORTUNE, 1 ); break; case 10: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::NECR, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WRLK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::BARB, 1 ); break; default: assert( 0 ); break; } return bonus; } std::vector getArchibaldCampaignBonusData( const int scenarioID ) { std::vector bonus; switch ( scenarioID ) { case 0: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MAGE_RING, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MINOR_SCROLL, 1 ); break; case 1: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::NECR, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WRLK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::BARB, 1 ); break; case 2: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::MASSCURSE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::DEFENDER_HELM, 1 ); break; case 3: case 4: case 5: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::NECR, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WRLK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::BARB, 1 ); break; case 6: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE_AND_ARMY, Race::NECR, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE_AND_ARMY, Race::WRLK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE_AND_ARMY, Race::BARB, 1 ); break; case 7: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LOGISTICS, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::POWER_AXE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::WHITE_PEARL, 1 ); break; case 8: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::NECR, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WRLK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::BARB, 1 ); break; case 9: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::BLACK_PEARL, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::DRAGON_SWORD, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::DIVINE_BREASTPLATE, 1 ); break; case 10: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::TAX_LIEN, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::HIDEOUS_MASK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::FIZBIN_MISFORTUNE, 1 ); break; case 11: bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::WZRD, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::SORC, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::STARTING_RACE, Race::KNGT, 1 ); break; default: assert( 0 ); break; } return bonus; } std::vector getPriceOfLoyaltyCampaignBonusData( const int scenarioID ) { std::vector bonus; switch ( scenarioID ) { case 0: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MEDAL_VALOR, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::STEALTH_SHIELD, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MINOR_SCROLL, 1 ); break; case 1: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::WHITE_PEARL, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::BALLISTA, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); break; case 2: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MAGE_RING, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MAJOR_SCROLL, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LOGISTICS, Skill::Level::ADVANCED ); break; case 3: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MEDAL_HONOR, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::CASTER_BRACELET, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::DEFENDER_HELM, 1 ); break; case 4: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::POWER_AXE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_PRIMARY, Skill::Primary::DEFENSE, 2 ); break; case 5: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); bonus.emplace_back( Campaign::ScenarioBonusData::TROOP, Monster::CRUSADER, 3 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::TRAVELER_BOOTS_MOBILITY, 1 ); break; case 6: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::SULFUR, 10 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::POWER_AXE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::SPELL_SCROLL, 1, Spell::ANIMATEDEAD ); break; case 7: bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::VIEWHEROES, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::TROOP, Monster::MAGE, 5 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::ESTATES, Skill::Level::ADVANCED ); break; default: assert( 0 ); break; } return bonus; } std::vector getDescendantsCampaignBonusData( const int scenarioID ) { std::vector bonus; switch ( scenarioID ) { case 0: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 1000 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::WOOD, 50 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::CRYSTAL, 10 ); break; case 1: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_PRIMARY, Skill::Primary::ATTACK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_PRIMARY, Skill::Primary::DEFENSE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 1000 ); break; case 2: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LOGISTICS, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::STEELSKIN, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MAGE_RING, 1 ); break; case 3: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LOGISTICS, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::SCOUTING, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::POWER_AXE, 1 ); break; case 4: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LUCK, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LEADERSHIP, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::SPIKED_SHIELD, 1 ); break; case 5: // These are negative values as they should be. Do NOT change them! bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, -1000 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::WOOD, -10 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::MERCURY, -2 ); break; case 6: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 1000 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::SCOUTING, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::WOOD, 20 ); break; case 7: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LEADERSHIP, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::ARCHERY, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_PRIMARY, Skill::Primary::POWER, 1 ); break; default: assert( 0 ); break; } return bonus; } std::vector getWizardsIsleCampaignBonusData( const int scenarioID ) { std::vector bonus; switch ( scenarioID ) { case 0: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::POWER_AXE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::STEALTH_SHIELD, 1 ); break; case 1: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::MAGE_RING, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::FOREMOST_SCROLL, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::FIREBLAST, 1 ); break; case 2: bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::MASSHASTE, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::SUMMONEELEMENT, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::SPELL, Spell::CHAINLIGHTNING, 1 ); break; case 3: bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::WOOD, 5 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::ORE, 5 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 1000 ); break; default: assert( 0 ); break; } return bonus; } std::vector getVoyageHomeCampaignBonusData( const int scenarioID ) { std::vector bonus; switch ( scenarioID ) { case 0: bonus.emplace_back( Campaign::ScenarioBonusData::ARTIFACT, Artifact::NOMAD_BOOTS_MOBILITY, 1 ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 500 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::SCOUTING, Skill::Level::BASIC ); break; case 1: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::PATHFINDING, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::NAVIGATION, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::SULFUR, 15 ); break; case 2: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::ARCHERY, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 3000 ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_PRIMARY, Skill::Primary::ATTACK, 1 ); break; case 3: bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::NECROMANCY, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::SKILL_SECONDARY, Skill::Secondary::LOGISTICS, Skill::Level::BASIC ); bonus.emplace_back( Campaign::ScenarioBonusData::RESOURCES, Resource::GOLD, 2000 ); break; default: assert( 0 ); break; } return bonus; } const char * getSpellCampaignName( const int32_t spellId ) { switch ( spellId ) { case Spell::ANIMATEDEAD: return _( "campaignBonus|Animate Dead" ); case Spell::CHAINLIGHTNING: return _( "campaignBonus|Chain Lightning" ); case Spell::FIREBLAST: return _( "campaignBonus|Fireblast" ); case Spell::MASSCURSE: return _( "campaignBonus|Mass Curse" ); case Spell::MASSHASTE: return _( "campaignBonus|Mass Haste" ); case Spell::MIRRORIMAGE: return _( "campaignBonus|Mirror Image" ); case Spell::RESURRECT: return _( "campaignBonus|Resurrect" ); case Spell::STEELSKIN: return _( "campaignBonus|Steelskin" ); case Spell::SUMMONEELEMENT: return _( "campaignBonus|Summon Earth" ); case Spell::VIEWHEROES: return _( "campaignBonus|View Heroes" ); default: return Spell( spellId ).GetName(); } } const char * getArtifactCampaignName( const int32_t artifactId, const int32_t spellId ) { switch ( artifactId ) { case Artifact::BALLISTA: return _( "campaignBonus|Ballista" ); case Artifact::BLACK_PEARL: return _( "campaignBonus|Black Pearl" ); case Artifact::CASTER_BRACELET: return _( "campaignBonus|Caster's Bracelet" ); case Artifact::DEFENDER_HELM: return _( "campaignBonus|Defender Helm" ); case Artifact::DIVINE_BREASTPLATE: return _( "campaignBonus|Breastplate" ); case Artifact::DRAGON_SWORD: return _( "campaignBonus|Dragon Sword" ); case Artifact::FIZBIN_MISFORTUNE: return _( "campaignBonus|Fizbin Medal" ); case Artifact::FOREMOST_SCROLL: return _( "campaignBonus|Foremost Scroll" ); case Artifact::ARMORED_GAUNTLETS: return _( "campaignBonus|Gauntlets" ); case Artifact::HIDEOUS_MASK: return _( "campaignBonus|Hideous Mask" ); case Artifact::MAGE_RING: return _( "campaignBonus|Mage's Ring" ); case Artifact::MAJOR_SCROLL: return _( "campaignBonus|Major Scroll" ); case Artifact::MEDAL_HONOR: return _( "campaignBonus|Medal of Honor" ); case Artifact::MEDAL_VALOR: return _( "campaignBonus|Medal of Valor" ); case Artifact::MINOR_SCROLL: return _( "campaignBonus|Minor Scroll" ); case Artifact::NOMAD_BOOTS_MOBILITY: return _( "campaignBonus|Nomad Boots" ); case Artifact::POWER_AXE: return _( "campaignBonus|Power Axe" ); case Artifact::SPIKED_SHIELD: return _( "campaignBonus|Spiked Shield" ); case Artifact::STEALTH_SHIELD: return _( "campaignBonus|Stealth Shield" ); case Artifact::TAX_LIEN: return _( "campaignBonus|Tax Lien" ); case Artifact::THUNDER_MACE: return _( "campaignBonus|Thunder Mace" ); case Artifact::TRAVELER_BOOTS_MOBILITY: return _( "campaignBonus|Traveler's Boots" ); case Artifact::WHITE_PEARL: return _( "campaignBonus|White Pearl" ); case Artifact::SPELL_SCROLL: return getSpellCampaignName( spellId ); default: return Artifact( artifactId ).GetName(); } } std::string getSecondarySkillCampaignName( const uint32_t secondarySkillId, const uint32_t secondarySkillLevel ) { switch ( secondarySkillId ) { case Skill::Secondary::ARCHERY: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Archery" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Archery" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Archery" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::BALLISTICS: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Ballistics" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Ballistics" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Ballistics" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::DIPLOMACY: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Diplomacy" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Diplomacy" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Diplomacy" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::EAGLE_EYE: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Eagle Eye" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Eagle Eye" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Eagle Eye" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::ESTATES: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Estates" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Estates" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Estates" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::LEADERSHIP: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Leadership" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Leadership" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Leadership" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::LOGISTICS: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Logistics" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Logistics" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Logistics" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::LUCK: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Luck" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Luck" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Luck" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::MYSTICISM: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Mysticism" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Mysticism" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Mysticism" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::NAVIGATION: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Navigation" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Navigation" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Navigation" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::NECROMANCY: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Necromancy" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Necromancy" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Necromancy" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::PATHFINDING: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Pathfinding" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Pathfinding" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Pathfinding" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::SCOUTING: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Scouting" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Scouting" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Scouting" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } case Skill::Secondary::WISDOM: switch ( secondarySkillLevel ) { case Skill::Level::BASIC: return _( "campaignBonus|Basic Wisdom" ); case Skill::Level::ADVANCED: return _( "campaignBonus|Advanced Wisdom" ); case Skill::Level::EXPERT: return _( "campaignBonus|Expert Wisdom" ); default: // There cannot be other valid values of the skill level assert( 0 ); return {}; } default: // There cannot be other valid values of secondary skills assert( 0 ); return {}; } } bool tryGetMatchingFile( const std::string & fileName, std::string & matchingFilePath ) { static const auto fileNameToPath = []() { std::map result; const ListFiles files = Settings::FindFiles( "maps", "", false ); for ( const std::string & file : files ) { result.try_emplace( StringLower( System::GetFileName( file ) ), file ); } return result; }(); const auto result = fileNameToPath.find( fileName ); if ( result != fileNameToPath.end() ) { matchingFilePath = result->second; return true; } return false; } } namespace Campaign { OStreamBase & operator<<( OStreamBase & stream, const ScenarioInfoId & data ) { return stream << data.campaignId << data.scenarioId; } IStreamBase & operator>>( IStreamBase & stream, ScenarioInfoId & data ) { return stream >> data.campaignId >> data.scenarioId; } ScenarioBonusData::ScenarioBonusData() : _type( 0 ) , _subType( 0 ) , _amount( 0 ) , _artifactSpellId( Spell::NONE ) {} ScenarioBonusData::ScenarioBonusData( const int32_t type, const int32_t subType, const int32_t amount ) : _type( type ) , _subType( subType ) , _amount( amount ) , _artifactSpellId( Spell::NONE ) {} ScenarioBonusData::ScenarioBonusData( const int32_t type, const int32_t subType, const int32_t amount, const int32_t spellId ) : _type( type ) , _subType( subType ) , _amount( amount ) , _artifactSpellId( spellId ) {} std::string ScenarioBonusData::getName() const { std::string objectName; switch ( _type ) { case ScenarioBonusData::ARTIFACT: objectName = getArtifactCampaignName( _subType, _artifactSpellId ); break; case ScenarioBonusData::RESOURCES: objectName = std::to_string( _amount ) + " " + Resource::String( _subType ); break; case ScenarioBonusData::TROOP: objectName = Monster( _subType ).GetPluralName( _amount ); break; case ScenarioBonusData::SPELL: objectName = getSpellCampaignName( _subType ); break; case ScenarioBonusData::STARTING_RACE: case ScenarioBonusData::STARTING_RACE_AND_ARMY: objectName = Race::String( _subType ); break; case ScenarioBonusData::SKILL_PRIMARY: objectName = Skill::Primary::String( _subType ); break; case ScenarioBonusData::SKILL_SECONDARY: objectName = getSecondarySkillCampaignName( _subType, _amount ); break; default: assert( 0 ); // some new bonus? break; } const std::vector useAmountTypes = { ScenarioBonusData::ARTIFACT, ScenarioBonusData::TROOP, ScenarioBonusData::SKILL_PRIMARY }; const bool useAmount = std::find( useAmountTypes.begin(), useAmountTypes.end(), _type ) != useAmountTypes.end() && _amount > 1; return useAmount ? std::to_string( _amount ) + " " + objectName : objectName; } std::string ScenarioBonusData::getDescription() const { switch ( _type ) { case ScenarioBonusData::ARTIFACT: { std::string description( _( "The main hero will have the \"%{artifact}\" artifact at the start of the scenario." ) ); StringReplace( description, "%{artifact}", Artifact( _subType ).GetName() ); return description; } case ScenarioBonusData::RESOURCES: { std::string description( _amount > 0 ? _( "The kingdom will receive %{amount} additional %{resource} at the start of the scenario." ) : _( "The kingdom will have %{amount} less %{resource} at the start of the scenario." ) ); StringReplace( description, "%{amount}", std::to_string( std::abs( _amount ) ) ); StringReplace( description, "%{resource}", Resource::String( _subType ) ); return description; } case ScenarioBonusData::TROOP: { std::string description( _( "The main hero will have %{count} %{monster} at the start of the scenario." ) ); StringReplace( description, "%{count}", std::to_string( _amount ) ); StringReplaceWithLowercase( description, "%{monster}", Monster( _subType ).GetPluralName( _amount ) ); return description; } case ScenarioBonusData::SPELL: { std::string description( _( "The main hero will have the \"%{spell}\" spell at the start of the scenario." ) ); StringReplace( description, "%{spell}", Spell( _subType ).GetName() ); return description; } case ScenarioBonusData::STARTING_RACE: case ScenarioBonusData::STARTING_RACE_AND_ARMY: { std::string description( _( "The starting alignment of the scenario will be %{race}." ) ); StringReplace( description, "%{race}", Race::String( _subType ) ); return description; } case ScenarioBonusData::SKILL_PRIMARY: { std::string description( _( "The main hero will receive a +%{count} to their %{skill} at the start of the scenario." ) ); StringReplace( description, "%{count}", std::to_string( _amount ) ); StringReplace( description, "%{skill}", Skill::Primary::String( _subType ) ); return description; } case ScenarioBonusData::SKILL_SECONDARY: { std::string description( _( "The main hero will have %{skill} at the start of the scenario." ) ); StringReplace( description, "%{skill}", Skill::Secondary( _subType, _amount ).GetName() ); return description; } default: assert( 0 ); // some new bonus? break; } return {}; } std::vector ScenarioBonusData::getCampaignBonusData( const ScenarioInfoId & scenarioInfo ) { assert( scenarioInfo.scenarioId >= 0 ); switch ( scenarioInfo.campaignId ) { case Campaign::ROLAND_CAMPAIGN: return getRolandCampaignBonusData( scenarioInfo.scenarioId ); case Campaign::ARCHIBALD_CAMPAIGN: return getArchibaldCampaignBonusData( scenarioInfo.scenarioId ); case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: return getPriceOfLoyaltyCampaignBonusData( scenarioInfo.scenarioId ); case Campaign::VOYAGE_HOME_CAMPAIGN: return getVoyageHomeCampaignBonusData( scenarioInfo.scenarioId ); case Campaign::WIZARDS_ISLE_CAMPAIGN: return getWizardsIsleCampaignBonusData( scenarioInfo.scenarioId ); case Campaign::DESCENDANTS_CAMPAIGN: return getDescendantsCampaignBonusData( scenarioInfo.scenarioId ); default: // Did you add a new campaign? Add the corresponding case above. assert( 0 ); break; } // shouldn't be here unless we get an unsupported campaign return std::vector(); } ScenarioData::ScenarioData( const ScenarioInfoId & scenarioInfo, std::vector && nextScenarios, const std::string & fileName, const std::string & scenarioName, const std::string & description, const VideoSequence & startScenarioVideoPlayback, const VideoSequence & endScenarioVideoPlayback, const ScenarioVictoryCondition victoryCondition, const ScenarioLossCondition lossCondition ) : _scenarioInfo( scenarioInfo ) , _nextScenarios( std::move( nextScenarios ) ) , _bonuses( ScenarioBonusData::getCampaignBonusData( scenarioInfo ) ) , _fileName( StringLower( fileName ) ) , _scenarioName( scenarioName ) , _description( description ) , _victoryCondition( victoryCondition ) , _lossCondition( lossCondition ) , _startScenarioVideoPlayback( startScenarioVideoPlayback ) , _endScenarioVideoPlayback( endScenarioVideoPlayback ) {} const char * ScenarioData::getScenarioName() const { return _( _scenarioName ); } const char * ScenarioData::getDescription() const { return _( _description ); } bool Campaign::ScenarioData::isMapFilePresent() const { std::string matchingFilePath; return tryGetMatchingFile( _fileName, matchingFilePath ); } Maps::FileInfo Campaign::ScenarioData::loadMap() const { std::string matchingFilePath; if ( tryGetMatchingFile( _fileName, matchingFilePath ) ) { Maps::FileInfo fi; if ( fi.readMP2Map( std::move( matchingFilePath ), false ) ) { return fi; } } return {}; } const char * getCampaignName( const int campaignId ) { switch ( campaignId ) { case Campaign::ROLAND_CAMPAIGN: return _( "Roland" ); case Campaign::ARCHIBALD_CAMPAIGN: return _( "Archibald" ); case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: return _( "Price of Loyalty" ); case Campaign::VOYAGE_HOME_CAMPAIGN: return _( "Voyage Home" ); case Campaign::WIZARDS_ISLE_CAMPAIGN: return _( "Wizard's Isle" ); case Campaign::DESCENDANTS_CAMPAIGN: return _( "Descendants" ); default: // Did you add a new campaign? Add the corresponding case above. assert( 0 ); break; } return "???"; } } fheroes2-1.1.6+dfsg/src/fheroes2/campaign/campaign_scenariodata.h000066400000000000000000000151271476115357100247230ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "maps_fileinfo.h" class IStreamBase; class OStreamBase; namespace Video { enum class VideoAction : int; } namespace Campaign { enum CampaignID { ROLAND_CAMPAIGN = 0, ARCHIBALD_CAMPAIGN = 1, PRICE_OF_LOYALTY_CAMPAIGN = 2, DESCENDANTS_CAMPAIGN = 3, WIZARDS_ISLE_CAMPAIGN = 4, VOYAGE_HOME_CAMPAIGN = 5 }; enum class ScenarioVictoryCondition : int { STANDARD = 0, // standard map's defined victory condition CAPTURE_DRAGON_CITY = 1, OBTAIN_ULTIMATE_CROWN = 2, OBTAIN_SPHERE_NEGATION = 3 }; enum class ScenarioLossCondition : int { STANDARD = 0, // standard map's defined loss condition LOSE_ALL_SORCERESS_VILLAGES = 1 }; struct ScenarioInfoId { ScenarioInfoId() = default; ScenarioInfoId( const int campaignId_, const int scenarioId_ ) : campaignId( campaignId_ ) , scenarioId( scenarioId_ ) { // Do nothing. } bool operator==( const ScenarioInfoId & info ) const { return campaignId == info.campaignId && scenarioId == info.scenarioId; } bool operator!=( const ScenarioInfoId & info ) const { return !operator==( info ); } friend OStreamBase & operator<<( OStreamBase & stream, const ScenarioInfoId & data ); friend IStreamBase & operator>>( IStreamBase & stream, ScenarioInfoId & data ); int campaignId{ -1 }; int scenarioId{ -1 }; }; struct ScenarioBonusData { public: enum BonusType : int32_t { RESOURCES = 0, ARTIFACT, TROOP, SPELL, STARTING_RACE, SKILL_PRIMARY, SKILL_SECONDARY, STARTING_RACE_AND_ARMY }; int32_t _type; int32_t _subType; int32_t _amount; int32_t _artifactSpellId; // Spell ID of a spell scroll ScenarioBonusData(); ScenarioBonusData( const int32_t type, const int32_t subType, const int32_t amount ); ScenarioBonusData( const int32_t type, const int32_t subType, const int32_t amount, const int32_t spellId ); std::string getName() const; std::string getDescription() const; static std::vector getCampaignBonusData( const ScenarioInfoId & scenarioInfo ); }; struct ScenarioIntroVideoInfo { std::string fileName; Video::VideoAction action; }; using VideoSequence = std::vector; class ScenarioData { public: ScenarioData() = delete; ScenarioData( const ScenarioInfoId & scenarioInfo, std::vector && nextScenarios, const std::string & fileName, const std::string & scenarioName, const std::string & description, const VideoSequence & startScenarioVideoPlayback, const VideoSequence & endScenarioVideoPlayback, const ScenarioVictoryCondition victoryCondition = ScenarioVictoryCondition::STANDARD, const ScenarioLossCondition lossCondition = ScenarioLossCondition::STANDARD ); const std::vector & getNextScenarios() const { return _nextScenarios; } const std::vector & getBonuses() const { return _bonuses; } int getScenarioID() const { return _scenarioInfo.scenarioId; } int getCampaignId() const { return _scenarioInfo.campaignId; } const ScenarioInfoId & getScenarioInfoId() const { return _scenarioInfo; } const char * getScenarioName() const; const char * getDescription() const; ScenarioVictoryCondition getVictoryCondition() const { return _victoryCondition; } ScenarioLossCondition getLossCondition() const { return _lossCondition; } const std::vector & getStartScenarioVideoPlayback() const { return _startScenarioVideoPlayback; } const std::vector & getEndScenarioVideoPlayback() const { return _endScenarioVideoPlayback; } bool isMapFilePresent() const; Maps::FileInfo loadMap() const; private: ScenarioInfoId _scenarioInfo; std::vector _nextScenarios; std::vector _bonuses; std::string _fileName; // Note: There are inconsistencies with the content of the map file in regards to the map name and description, so we'll be getting them from somewhere else std::string _scenarioName; std::string _description; ScenarioVictoryCondition _victoryCondition; ScenarioLossCondition _lossCondition; VideoSequence _startScenarioVideoPlayback; VideoSequence _endScenarioVideoPlayback; }; const char * getCampaignName( const int campaignId ); } fheroes2-1.1.6+dfsg/src/fheroes2/castle/000077500000000000000000000000001476115357100177445ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/castle/buildinginfo.cpp000066400000000000000000000707171476115357100231350ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "buildinginfo.h" #include #include #include #include "agg_image.h" #include "army_troop.h" #include "audio_manager.h" #include "castle.h" #include "castle_building_info.h" #include "cursor.h" #include "dialog.h" #include "icn.h" #include "localevent.h" #include "m82.h" #include "maps_fileinfo.h" #include "monster.h" #include "pal.h" #include "payment.h" #include "profit.h" #include "race.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "statusbar.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_text.h" namespace { fheroes2::Point GetFlagOffset( int race ) { switch ( race ) { case Race::KNGT: return { 36, 10 }; case Race::BARB: return { 35, 9 }; case Race::SORC: return { 36, 10 }; case Race::WRLK: return { 34, 10 }; case Race::WZRD: return { 35, 9 }; case Race::NECR: return { 35, 10 }; default: // Did you add a new race? assert( 0 ); return {}; } } const char * GetBuildConditionDescription( const BuildingStatus status ) { switch ( status ) { case BuildingStatus::NOT_TODAY: return _( "Cannot build. You have already built here today." ); case BuildingStatus::NEED_CASTLE: return _( "For this action it is necessary to build a castle first." ); default: break; } return nullptr; } } struct BuildingStats { uint32_t id2; uint8_t race; Cost cost; }; const BuildingStats buildingStats[] = { // id gold wood mercury ore sulfur crystal gems { BUILD_THIEVESGUILD, Race::ALL, { 750, 5, 0, 0, 0, 0, 0 } }, { BUILD_TAVERN, Race::ALL, { 500, 5, 0, 0, 0, 0, 0 } }, { BUILD_SHIPYARD, Race::ALL, { 2000, 20, 0, 0, 0, 0, 0 } }, { BUILD_WELL, Race::ALL, { 500, 0, 0, 0, 0, 0, 0 } }, { BUILD_STATUE, Race::ALL, { 1250, 0, 0, 5, 0, 0, 0 } }, { BUILD_LEFTTURRET, Race::ALL, { 1500, 0, 0, 5, 0, 0, 0 } }, { BUILD_RIGHTTURRET, Race::ALL, { 1500, 0, 0, 5, 0, 0, 0 } }, { BUILD_MARKETPLACE, Race::ALL, { 500, 5, 0, 0, 0, 0, 0 } }, { BUILD_MOAT, Race::ALL, { 750, 0, 0, 0, 0, 0, 0 } }, { BUILD_CASTLE, Race::ALL, { 5000, 20, 0, 20, 0, 0, 0 } }, { BUILD_CAPTAIN, Race::ALL, { 500, 0, 0, 0, 0, 0, 0 } }, { BUILD_MAGEGUILD1, Race::ALL, { 2000, 5, 0, 5, 0, 0, 0 } }, { BUILD_MAGEGUILD2, Race::ALL, { 1000, 5, 4, 5, 4, 4, 4 } }, { BUILD_MAGEGUILD3, Race::ALL, { 1000, 5, 6, 5, 6, 6, 6 } }, { BUILD_MAGEGUILD4, Race::ALL, { 1000, 5, 8, 5, 8, 8, 8 } }, { BUILD_MAGEGUILD5, Race::ALL, { 1000, 5, 10, 5, 10, 10, 10 } }, { BUILD_WEL2, Race::KNGT, { 1000, 0, 0, 0, 0, 0, 0 } }, { BUILD_WEL2, Race::BARB, { 1000, 0, 0, 0, 0, 0, 0 } }, { BUILD_WEL2, Race::SORC, { 1000, 0, 0, 0, 0, 0, 0 } }, { BUILD_WEL2, Race::WRLK, { 1000, 0, 0, 0, 0, 0, 0 } }, { BUILD_WEL2, Race::WZRD, { 1000, 0, 0, 0, 0, 0, 0 } }, { BUILD_WEL2, Race::NECR, { 1000, 0, 0, 0, 0, 0, 0 } }, { BUILD_SPEC, Race::KNGT, { 1500, 5, 0, 15, 0, 0, 0 } }, { BUILD_SPEC, Race::BARB, { 2000, 10, 0, 10, 0, 0, 0 } }, { BUILD_SPEC, Race::SORC, { 1500, 0, 0, 0, 0, 10, 0 } }, { BUILD_SPEC, Race::WRLK, { 3000, 5, 0, 10, 0, 0, 0 } }, { BUILD_SPEC, Race::WZRD, { 1500, 5, 5, 5, 5, 5, 5 } }, { BUILD_SPEC, Race::NECR, { 1000, 0, 10, 0, 10, 0, 0 } }, { BUILD_SHRINE, Race::NECR, { 4000, 10, 0, 0, 0, 10, 0 } }, { DWELLING_MONSTER1, Race::KNGT, { 200, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER2, Race::KNGT, { 1000, 0, 0, 0, 0, 0, 0 } }, { DWELLING_UPGRADE2, Race::KNGT, { 1500, 5, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER3, Race::KNGT, { 1000, 0, 0, 5, 0, 0, 0 } }, { DWELLING_UPGRADE3, Race::KNGT, { 1500, 0, 0, 5, 0, 0, 0 } }, { DWELLING_MONSTER4, Race::KNGT, { 2000, 10, 0, 10, 0, 0, 0 } }, { DWELLING_UPGRADE4, Race::KNGT, { 2000, 5, 0, 5, 0, 0, 0 } }, { DWELLING_MONSTER5, Race::KNGT, { 3000, 20, 0, 0, 0, 0, 0 } }, { DWELLING_UPGRADE5, Race::KNGT, { 3000, 10, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER6, Race::KNGT, { 5000, 20, 0, 0, 0, 20, 0 } }, { DWELLING_UPGRADE6, Race::KNGT, { 5000, 10, 0, 0, 0, 10, 0 } }, { DWELLING_MONSTER1, Race::BARB, { 300, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER2, Race::BARB, { 800, 5, 0, 0, 0, 0, 0 } }, { DWELLING_UPGRADE2, Race::BARB, { 1200, 5, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER3, Race::BARB, { 1000, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER4, Race::BARB, { 2000, 10, 0, 10, 0, 0, 0 } }, { DWELLING_UPGRADE4, Race::BARB, { 3000, 5, 0, 5, 0, 0, 0 } }, { DWELLING_MONSTER5, Race::BARB, { 4000, 0, 0, 20, 0, 0, 0 } }, { DWELLING_UPGRADE5, Race::BARB, { 2000, 0, 0, 10, 0, 0, 0 } }, { DWELLING_MONSTER6, Race::BARB, { 6000, 0, 0, 20, 0, 20, 0 } }, { DWELLING_MONSTER1, Race::SORC, { 500, 5, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER2, Race::SORC, { 1000, 5, 0, 0, 0, 0, 0 } }, { DWELLING_UPGRADE2, Race::SORC, { 1500, 5, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER3, Race::SORC, { 1500, 0, 0, 0, 0, 0, 0 } }, { DWELLING_UPGRADE3, Race::SORC, { 1500, 5, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER4, Race::SORC, { 2500, 0, 0, 10, 0, 0, 0 } }, { DWELLING_UPGRADE4, Race::SORC, { 1500, 0, 5, 0, 0, 0, 0 } }, { DWELLING_MONSTER5, Race::SORC, { 3000, 10, 0, 0, 0, 0, 10 } }, { DWELLING_MONSTER6, Race::SORC, { 10000, 0, 20, 30, 0, 0, 0 } }, { DWELLING_MONSTER1, Race::WRLK, { 500, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER2, Race::WRLK, { 1000, 0, 0, 10, 0, 0, 0 } }, { DWELLING_MONSTER3, Race::WRLK, { 2000, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER4, Race::WRLK, { 3000, 0, 0, 0, 0, 0, 10 } }, { DWELLING_UPGRADE4, Race::WRLK, { 2000, 0, 0, 0, 0, 0, 5 } }, { DWELLING_MONSTER5, Race::WRLK, { 4000, 0, 0, 0, 10, 0, 0 } }, { DWELLING_MONSTER6, Race::WRLK, { 15000, 0, 0, 30, 20, 0, 0 } }, { DWELLING_UPGRADE6, Race::WRLK, { 5000, 0, 0, 5, 10, 0, 0 } }, { DWELLING_UPGRADE7, Race::WRLK, { 5000, 0, 0, 5, 10, 0, 0 } }, { DWELLING_MONSTER1, Race::WZRD, { 400, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER2, Race::WZRD, { 800, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER3, Race::WZRD, { 1500, 5, 0, 5, 0, 0, 0 } }, { DWELLING_UPGRADE3, Race::WZRD, { 1500, 0, 5, 0, 0, 0, 0 } }, { DWELLING_MONSTER4, Race::WZRD, { 3000, 5, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER5, Race::WZRD, { 3500, 5, 5, 5, 5, 5, 5 } }, { DWELLING_UPGRADE5, Race::WZRD, { 4000, 5, 0, 5, 0, 0, 0 } }, { DWELLING_MONSTER6, Race::WZRD, { 12500, 5, 0, 5, 0, 0, 20 } }, { DWELLING_UPGRADE6, Race::WZRD, { 12500, 5, 0, 5, 0, 0, 20 } }, { DWELLING_MONSTER1, Race::NECR, { 400, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER2, Race::NECR, { 1000, 0, 0, 0, 0, 0, 0 } }, { DWELLING_UPGRADE2, Race::NECR, { 1000, 0, 0, 0, 0, 0, 0 } }, { DWELLING_MONSTER3, Race::NECR, { 1500, 0, 0, 10, 0, 0, 0 } }, { DWELLING_UPGRADE3, Race::NECR, { 1500, 0, 0, 5, 0, 0, 0 } }, { DWELLING_MONSTER4, Race::NECR, { 3000, 10, 0, 0, 0, 0, 0 } }, { DWELLING_UPGRADE4, Race::NECR, { 4000, 5, 0, 0, 0, 10, 10 } }, { DWELLING_MONSTER5, Race::NECR, { 4000, 10, 0, 0, 10, 0, 0 } }, { DWELLING_UPGRADE5, Race::NECR, { 3000, 0, 0, 5, 0, 5, 0 } }, { DWELLING_MONSTER6, Race::NECR, { 10000, 10, 5, 10, 5, 5, 5 } }, // end { BUILD_NOTHING, Race::NONE, { 0, 0, 0, 0, 0, 0, 0 } }, }; Funds BuildingInfo::GetCost( uint32_t build, int race ) { Funds payment; const BuildingStats * ptr = &buildingStats[0]; while ( BUILD_NOTHING != ptr->id2 && !( ptr->id2 == build && ( !race || ( race & ptr->race ) ) ) ) ++ptr; if ( BUILD_NOTHING != ptr->id2 ) { payment.gold = ptr->cost.gold; payment.wood = ptr->cost.wood; payment.mercury = ptr->cost.mercury; payment.ore = ptr->cost.ore; payment.sulfur = ptr->cost.sulfur; payment.crystal = ptr->cost.crystal; payment.gems = ptr->cost.gems; } return payment; } BuildingInfo::BuildingInfo( const Castle & c, const BuildingType b ) : castle( c ) , _buildingType( b ) , area( 0, 0, 135, 70 ) , _status( BuildingStatus::ALLOW_BUILD ) { if ( isDwelling( _buildingType ) ) _buildingType = castle.GetActualDwelling( b ); _buildingType = castle.isBuild( b ) ? castle.GetUpgradeBuilding( b ) : b; if ( BUILD_TAVERN == _buildingType && Race::NECR == castle.GetRace() ) { const GameVersion version = Settings::Get().getCurrentMapInfo().version; _buildingType = ( version == GameVersion::PRICE_OF_LOYALTY || version == GameVersion::RESURRECTION ) ? BUILD_SHRINE : BUILD_NOTHING; } _status = castle.CheckBuyBuilding( _buildingType ); // generate description if ( _status == BuildingStatus::BUILD_DISABLE || _status == BuildingStatus::SHIPYARD_NOT_ALLOWED ) description = GetConditionDescription(); else { description = getBuildingDescription( castle.GetRace(), _buildingType ); } // fix area for captain if ( b == BUILD_CAPTAIN ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::getCaptainIcnId( castle.GetRace() ), ( _buildingType & BUILD_CAPTAIN ? 1 : 0 ) ); area.width = sprite.width(); area.height = sprite.height(); } } void BuildingInfo::SetPos( int32_t x, int32_t y ) { area.x = x; area.y = y; } bool BuildingInfo::isDwelling( const uint32_t building ) { switch ( building ) { case DWELLING_MONSTER1: case DWELLING_MONSTER2: case DWELLING_MONSTER3: case DWELLING_MONSTER4: case DWELLING_MONSTER5: case DWELLING_MONSTER6: case DWELLING_UPGRADE2: case DWELLING_UPGRADE3: case DWELLING_UPGRADE4: case DWELLING_UPGRADE5: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return true; default: break; } return false; } std::string BuildingInfo::getBuildingDescription( const int race, const uint32_t buildingId ) { std::string description; if ( isDwelling( buildingId ) ) { description = _( "The %{building} produces %{monster}." ); StringReplace( description, "%{building}", Castle::GetStringBuilding( buildingId, race ) ); if ( race == Race::RAND ) { StringReplace( description, "%{monster}", Monster::getRandomRaceMonstersName( buildingId ) ); } else { StringReplaceWithLowercase( description, "%{monster}", Monster( race, buildingId ).GetMultiName() ); } } else { description = fheroes2::getBuildingDescription( race, static_cast( buildingId ) ); switch ( buildingId ) { case BUILD_WELL: StringReplace( description, "%{count}", Castle::GetGrownWell() ); break; case BUILD_WEL2: StringReplace( description, "%{count}", Castle::GetGrownWel2() ); break; case BUILD_CASTLE: case BUILD_STATUE: case BUILD_SPEC: { const Funds profit = ProfitConditions::FromBuilding( buildingId, race ); StringReplace( description, "%{count}", profit.gold ); break; } default: break; } } return description; } void BuildingInfo::RedrawCaptain() const { fheroes2::Display & display = fheroes2::Display::instance(); if ( _status == BuildingStatus::ALREADY_BUILT ) { const fheroes2::Sprite & captainSprite = fheroes2::AGG::GetICN( ICN::getCaptainIcnId( castle.GetRace() ), 1 ); const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( ICN::getFlagIcnId( castle.GetColor() ), 0 ); fheroes2::Blit( captainSprite, display, area.x, area.y ); const fheroes2::Point flagOffset = GetFlagOffset( castle.GetRace() ); fheroes2::Blit( flag, display, area.x + flagOffset.x, area.y + flagOffset.y ); } else { fheroes2::Blit( fheroes2::AGG::GetICN( ICN::getCaptainIcnId( castle.GetRace() ), 0 ), display, area.x, area.y ); } // indicator if ( _status == BuildingStatus::ALREADY_BUILT ) { const fheroes2::Sprite & spriteAllow = fheroes2::AGG::GetICN( ICN::TOWNWIND, 11 ); fheroes2::Blit( spriteAllow, display, area.x + 83 - 4 - spriteAllow.width(), area.y + 79 - 2 - spriteAllow.height() ); } else if ( _status != BuildingStatus::ALLOW_BUILD ) { if ( BuildingStatus::LACK_RESOURCES == _status ) { const fheroes2::Sprite & spriteMoney = fheroes2::AGG::GetICN( ICN::TOWNWIND, 13 ); fheroes2::Blit( spriteMoney, display, area.x + 83 - 4 + 1 - spriteMoney.width(), area.y + 79 - 3 - spriteMoney.height() ); } else { const fheroes2::Sprite & spriteDeny = fheroes2::AGG::GetICN( ICN::TOWNWIND, 12 ); fheroes2::Blit( spriteDeny, display, area.x + 83 - 4 + 1 - spriteDeny.width(), area.y + 79 - 2 - spriteDeny.height() ); } } } void BuildingInfo::Redraw() const { if ( BUILD_CAPTAIN == _buildingType ) { RedrawCaptain(); return; } fheroes2::Display & display = fheroes2::Display::instance(); const int index = fheroes2::getIndexBuildingSprite( static_cast( _buildingType ) ); const fheroes2::Sprite & buildingFrame = fheroes2::AGG::GetICN( ICN::BLDGXTRA, 0 ); fheroes2::Blit( buildingFrame, display, area.x, area.y ); if ( _status == BuildingStatus::BUILD_DISABLE || _status == BuildingStatus::SHIPYARD_NOT_ALLOWED ) { const fheroes2::Point offset( 6, 59 ); fheroes2::Sprite grayedOut = fheroes2::Crop( buildingFrame, offset.x, offset.y, 125, 12 ); fheroes2::ApplyPalette( grayedOut, PAL::GetPalette( PAL::PaletteType::GRAY ) ); fheroes2::ApplyPalette( grayedOut, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); fheroes2::Copy( grayedOut, 0, 0, display, area.x + offset.x, area.y + offset.y, 125, 12 ); } // build image if ( BUILD_NOTHING == _buildingType ) { const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & buildBackground = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CASLXTRA_EVIL : ICN::CASLXTRA, 0 ); fheroes2::Copy( buildBackground, 0, 0, display, area.x, area.y, buildBackground.width(), buildBackground.height() ); return; } fheroes2::Blit( fheroes2::AGG::GetICN( ICN::getBuildingIcnId( castle.GetRace() ), index ), display, area.x + 1, area.y + 1 ); // indicator if ( _status == BuildingStatus::ALREADY_BUILT ) { const fheroes2::Sprite & spriteAllow = fheroes2::AGG::GetICN( ICN::TOWNWIND, 11 ); fheroes2::Blit( spriteAllow, display, area.x + buildingFrame.width() - 5 - spriteAllow.width(), area.y + 58 - 2 - spriteAllow.height() ); } else if ( _status == BuildingStatus::BUILD_DISABLE || _status == BuildingStatus::SHIPYARD_NOT_ALLOWED ) { const fheroes2::Sprite & spriteDeny = fheroes2::AGG::GetICN( ICN::TOWNWIND, 12 ); fheroes2::Sprite disabledSprite( spriteDeny ); fheroes2::ApplyPalette( disabledSprite, PAL::GetPalette( PAL::PaletteType::GRAY ) ); fheroes2::ApplyPalette( disabledSprite, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); fheroes2::Blit( disabledSprite, display, area.x + buildingFrame.width() - 5 + 1 - spriteDeny.width(), area.y + 58 - 2 - spriteDeny.height() ); } else if ( _status != BuildingStatus::ALLOW_BUILD ) { if ( BuildingStatus::LACK_RESOURCES == _status ) { const fheroes2::Sprite & spriteMoney = fheroes2::AGG::GetICN( ICN::TOWNWIND, 13 ); fheroes2::Blit( spriteMoney, display, area.x + buildingFrame.width() - 5 + 1 - spriteMoney.width(), area.y + 58 - 3 - spriteMoney.height() ); } else { const fheroes2::Sprite & spriteDeny = fheroes2::AGG::GetICN( ICN::TOWNWIND, 12 ); fheroes2::Blit( spriteDeny, display, area.x + buildingFrame.width() - 5 + 1 - spriteDeny.width(), area.y + 58 - 2 - spriteDeny.height() ); } const fheroes2::Sprite & textBackground = fheroes2::AGG::GetICN( ICN::CASLXTRA, 2 ); fheroes2::Copy( textBackground, 0, 0, display, area.x, area.y + 58, textBackground.width(), textBackground.height() ); } else { const fheroes2::Sprite & textBackground = fheroes2::AGG::GetICN( ICN::CASLXTRA, 1 ); fheroes2::Copy( textBackground, 0, 0, display, area.x, area.y + 58, textBackground.width(), textBackground.height() ); } const fheroes2::Text buildingName( Castle::GetStringBuilding( _buildingType, castle.GetRace() ), fheroes2::FontType::smallWhite() ); buildingName.draw( area.x + 68 - buildingName.width() / 2, area.y + 61, display ); } const char * BuildingInfo::GetName() const { return Castle::GetStringBuilding( _buildingType, castle.GetRace() ); } bool BuildingInfo::QueueEventProcessing( fheroes2::ButtonBase & exitButton ) const { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( area ) ) { if ( _status == BuildingStatus::LACK_RESOURCES || _status == BuildingStatus::ALLOW_BUILD ) { const fheroes2::ButtonRestorer exitRestorer( exitButton ); return DialogBuyBuilding( true ); } } else if ( le.isMouseRightButtonPressedInArea( area ) ) { DialogBuyBuilding( false ); } return false; } bool BuildingInfo::DialogBuyBuilding( bool buttons ) const { if ( _buildingType == BUILD_NOTHING ) { return false; } const CursorRestorer cursorRestorer( buttons, Cursor::POINTER ); std::string extendedDescription = description; if ( BuildingStatus::ALLOW_BUILD != _status ) { const std::string & ext = GetConditionDescription(); if ( !ext.empty() && ext != description ) { extendedDescription.append( "\n\n" ); extendedDescription.append( ext ); } } const fheroes2::Text descriptionText( std::move( extendedDescription ), fheroes2::FontType::normalWhite() ); // prepare requirement build string std::string requirement; if ( _status != BuildingStatus::BUILD_DISABLE ) { requirement = fheroes2::getBuildingRequirementString( castle.GetRace(), static_cast( _buildingType ) ); } const bool requirementsPresent = !requirement.empty(); const fheroes2::Text requirementTitle( _( "Requires:" ), fheroes2::FontType::normalWhite() ); const fheroes2::Text requirementText( std::move( requirement ), fheroes2::FontType::normalWhite() ); const int elementOffset = 10; int32_t requirementHeight = 0; if ( requirementsPresent ) { requirementHeight = requirementTitle.height() + requirementText.height( fheroes2::boxAreaWidthPx ) + elementOffset; } Resource::BoxSprite rbs( PaymentConditions::BuyBuilding( castle.GetRace(), _buildingType ), fheroes2::boxAreaWidthPx ); const fheroes2::Sprite & buildingFrame = fheroes2::AGG::GetICN( ICN::BLDGXTRA, 0 ); const int32_t totalDialogHeight = elementOffset + buildingFrame.height() + elementOffset + descriptionText.height( fheroes2::boxAreaWidthPx ) + elementOffset + requirementHeight + rbs.GetArea().height; const Dialog::FrameBox dialogFrame( totalDialogHeight, buttons ); const fheroes2::Rect & dialogRoi = dialogFrame.GetArea(); fheroes2::Point pos{ dialogRoi.x + ( dialogRoi.width - buildingFrame.width() ) / 2, pos.y = dialogRoi.y + elementOffset }; fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( buildingFrame, display, pos.x, pos.y ); const fheroes2::Sprite & buildingImage = fheroes2::AGG::GetICN( ICN::getBuildingIcnId( castle.GetRace() ), fheroes2::getIndexBuildingSprite( static_cast( _buildingType ) ) ); pos.x = dialogRoi.x + ( dialogRoi.width - buildingImage.width() ) / 2; pos.y += 1; fheroes2::Blit( buildingImage, display, pos.x, pos.y ); const fheroes2::Text buildingName( GetName(), fheroes2::FontType::smallWhite() ); pos.x = dialogRoi.x + ( dialogRoi.width - buildingName.width() ) / 2; pos.y += 58; buildingName.draw( pos.x, pos.y + 2, display ); pos.x = dialogRoi.x; pos.y = dialogRoi.y + elementOffset + buildingFrame.height() + elementOffset; descriptionText.draw( pos.x, pos.y + 2, fheroes2::boxAreaWidthPx, display ); pos.y += descriptionText.height( fheroes2::boxAreaWidthPx ) + elementOffset; if ( requirementsPresent ) { pos.x = dialogRoi.x + ( dialogRoi.width - requirementTitle.width() ) / 2; requirementTitle.draw( pos.x, pos.y + 2, display ); pos.x = dialogRoi.x; pos.y += requirementTitle.height(); requirementText.draw( pos.x, pos.y + 2, fheroes2::boxAreaWidthPx, display ); pos.y += requirementText.height( fheroes2::boxAreaWidthPx ) + elementOffset; } rbs.SetPos( pos.x, pos.y ); rbs.Redraw(); LocalEvent & le = LocalEvent::Get(); if ( !buttons ) { // This is a case when this dialog was called by the right mouse button press. display.render(); while ( le.HandleEvents() ) { if ( !le.isMouseRightButtonPressed() ) { break; } } return false; } fheroes2::ButtonGroup buttonGroup( dialogRoi, Dialog::OK | Dialog::CANCEL ); fheroes2::ButtonBase & buttonOkay = buttonGroup.button( 0 ); const fheroes2::ButtonBase & buttonCancel = buttonGroup.button( 1 ); if ( BuildingStatus::ALLOW_BUILD != castle.CheckBuyBuilding( _buildingType ) ) { buttonOkay.disable(); } buttonGroup.draw(); display.render(); while ( le.HandleEvents() ) { const int result = buttonGroup.processEvents(); if ( result != Dialog::ZERO ) { return result == Dialog::OK; } if ( le.isMouseRightButtonPressedInArea( buttonOkay.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), GetConditionDescription(), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } } return false; } std::string BuildingInfo::GetConditionDescription() const { switch ( _status ) { case BuildingStatus::NOT_TODAY: case BuildingStatus::NEED_CASTLE: return GetBuildConditionDescription( _status ); case BuildingStatus::SHIPYARD_NOT_ALLOWED: { assert( _buildingType == BUILD_SHIPYARD ); std::string res = _( "Cannot build %{name}. The castle is too far away from an ocean." ); StringReplace( res, "%{name}", Castle::GetStringBuilding( BUILD_SHIPYARD, castle.GetRace() ) ); return res; } case BuildingStatus::BUILD_DISABLE: return _( "This building has been disabled." ); case BuildingStatus::LACK_RESOURCES: { std::string res = _( "Cannot afford the %{name}." ); StringReplace( res, "%{name}", GetName() ); return res; } case BuildingStatus::ALREADY_BUILT: { std::string res = _( "The %{name} is already built." ); StringReplace( res, "%{name}", GetName() ); return res; } case BuildingStatus::REQUIRES_BUILD: { std::string res = _( "Cannot build the %{name}." ); StringReplace( res, "%{name}", GetName() ); return res; } case BuildingStatus::ALLOW_BUILD: { std::string res = _( "Build %{name}." ); StringReplace( res, "%{name}", GetName() ); return res; } default: break; } return {}; } void BuildingInfo::SetStatusMessage( StatusBar & bar ) const { if ( _buildingType == BUILD_NOTHING ) { return; } switch ( _status ) { case BuildingStatus::NOT_TODAY: case BuildingStatus::ALREADY_BUILT: case BuildingStatus::NEED_CASTLE: case BuildingStatus::BUILD_DISABLE: case BuildingStatus::SHIPYARD_NOT_ALLOWED: case BuildingStatus::LACK_RESOURCES: case BuildingStatus::REQUIRES_BUILD: case BuildingStatus::ALLOW_BUILD: bar.ShowMessage( GetConditionDescription() ); break; default: break; } } DwellingsBar::DwellingsBar( Castle & cstl, const fheroes2::Size & sz ) : castle( cstl ) , backsf( sz.width, sz.height ) { backsf.reset(); content.reserve( CountBits( DWELLING_MONSTERS ) ); for ( uint32_t dw = DWELLING_MONSTER1; dw <= DWELLING_MONSTER6; dw <<= 1 ) { content.emplace_back( dw ); } SetContent( content ); fheroes2::DrawBorder( backsf, fheroes2::GetColorId( 0xd0, 0xc0, 0x48 ) ); setSingleItemSize( sz ); } void DwellingsBar::RedrawBackground( const fheroes2::Rect & pos, fheroes2::Image & dstsf ) { fheroes2::Blit( backsf, dstsf, pos.x, pos.y ); } void DwellingsBar::RedrawItem( DwellingItem & dwl, const fheroes2::Rect & pos, fheroes2::Image & dstsf ) { const uint32_t dwType = castle.GetActualDwelling( dwl.dwType ); const Monster mons{ castle.GetRace(), dwType }; const fheroes2::Sprite & mons32 = fheroes2::AGG::GetICN( ICN::MONS32, mons.GetSpriteIndex() ); fheroes2::Blit( mons32, dstsf, pos.x + ( pos.width - mons32.width() ) / 2, pos.y + ( pos.height - 3 - mons32.height() ) ); if ( !castle.isBuild( dwType ) ) { fheroes2::Blit( fheroes2::AGG::GetICN( ICN::CSLMARKER, 0 ), dstsf, pos.x + pos.width - 10, pos.y + 4 ); return; } // Units available for hire. fheroes2::Text text( std::to_string( castle.getMonstersInDwelling( dwType ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + pos.width - text.width() - 3, pos.y + pos.height - text.height() + 1, dstsf ); uint32_t grown = mons.GetGrown(); if ( castle.isBuild( BUILD_WELL ) ) { grown += Castle::GetGrownWell(); } if ( castle.isBuild( BUILD_WEL2 ) && DWELLING_MONSTER1 == dwType ) { grown += Castle::GetGrownWel2(); } // Dwelling's growth. text.set( "+" + std::to_string( grown ), fheroes2::FontType::smallYellow() ); text.draw( pos.x + pos.width - text.width() - 3, pos.y + 4, dstsf ); } bool DwellingsBar::ActionBarLeftMouseSingleClick( DwellingItem & dwl ) { const uint32_t dwType = castle.GetActualDwelling( dwl.dwType ); if ( castle.isBuild( dwType ) ) { castle.RecruitMonster( Dialog::RecruitMonster( { castle.GetRace(), dwType }, castle.getMonstersInDwelling( dwType ), true, -60 ) ); } else if ( !castle.isBuild( BUILD_CASTLE ) ) fheroes2::showStandardTextMessage( "", GetBuildConditionDescription( BuildingStatus::NEED_CASTLE ), Dialog::OK ); else { const BuildingInfo _dwelling( castle, static_cast( dwType ) ); if ( _dwelling.DialogBuyBuilding( true ) ) { AudioManager::PlaySound( M82::BUILDTWN ); castle.BuyBuilding( dwType ); } } return true; } bool DwellingsBar::ActionBarRightMouseHold( DwellingItem & dwl ) { const uint32_t dwType = castle.GetActualDwelling( dwl.dwType ); Dialog::DwellingInfo( { castle.GetRace(), dwType }, castle.getMonstersInDwelling( dwType ) ); return true; } fheroes2-1.1.6+dfsg/src/fheroes2/castle/buildinginfo.h000066400000000000000000000071031476115357100225670ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "image.h" #include "interface_itemsbar.h" #include "math_base.h" #include "resource.h" namespace fheroes2 { class ButtonBase; } class Castle; class StatusBar; enum BuildingType : uint32_t; enum class BuildingStatus : int32_t; class BuildingInfo { public: BuildingInfo( const Castle & c, const BuildingType b ); uint32_t getBuilding() const { return _buildingType; } void SetPos( int32_t, int32_t ); const fheroes2::Rect & GetArea() const { return area; } const char * GetName() const; void SetStatusMessage( StatusBar & ) const; static bool isDwelling( const uint32_t building ); static std::string getBuildingDescription( const int race, const uint32_t buildingId ); void Redraw() const; bool QueueEventProcessing( fheroes2::ButtonBase & exitButton ) const; bool DialogBuyBuilding( bool buttons ) const; static Funds GetCost( uint32_t, int ); private: void RedrawCaptain() const; std::string GetConditionDescription() const; const Castle & castle; uint32_t _buildingType; std::string description; fheroes2::Rect area; BuildingStatus _status; }; struct DwellingItem { explicit DwellingItem( const uint32_t dw ) : dwType( dw ) {} const uint32_t dwType; }; class DwellingsBar final : public Interface::ItemsBar { public: DwellingsBar( Castle & cstl, const fheroes2::Size & sz ); void RedrawBackground( const fheroes2::Rect & pos, fheroes2::Image & dstsf ) override; void RedrawItem( DwellingItem & dwl, const fheroes2::Rect & pos, fheroes2::Image & dstsf ) override; bool ActionBarLeftMouseSingleClick( DwellingItem & dwl ) override; bool ActionBarRightMouseHold( DwellingItem & dwl ) override; private: Castle & castle; fheroes2::Image backsf; std::vector content; }; fheroes2-1.1.6+dfsg/src/fheroes2/castle/captain.cpp000066400000000000000000000173271476115357100221010ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "captain.h" #include #include "agg_image.h" #include "artifact.h" #include "artifact_info.h" #include "castle.h" #include "icn.h" #include "interface_icons.h" #include "luck.h" #include "math_base.h" #include "morale.h" #include "race.h" #include "spell_book.h" class Army; namespace { int GetPortraitIcnId( int race ) { switch ( race ) { case Race::KNGT: return ICN::PORT0090; case Race::BARB: return ICN::PORT0091; case Race::SORC: return ICN::PORT0092; case Race::WRLK: return ICN::PORT0093; case Race::WZRD: return ICN::PORT0094; case Race::NECR: return ICN::PORT0095; default: return -1; } } fheroes2::Point GetFlagOffset( int race ) { switch ( race ) { case Race::KNGT: return { 43, 9 }; case Race::BARB: return { 42, 8 }; case Race::SORC: return { 43, 9 }; case Race::WRLK: return { 41, 9 }; case Race::WZRD: return { 42, 10 }; case Race::NECR: return { 42, 9 }; default: return {}; } } } Captain::Captain( Castle & castle ) : HeroBase( HeroBase::CAPTAIN, castle.GetRace() ) , home( castle ) { SetCenter( home.GetCenter() ); } bool Captain::isValid() const { return home.isBuild( BUILD_CAPTAIN ); } int Captain::GetAttack() const { return attack + GetAttackModificator( nullptr ); } int Captain::GetDefense() const { return defense + GetDefenseModificator( nullptr ); } int Captain::GetPower() const { const int finalPower = power + GetPowerModificator( nullptr ); return finalPower < 1 ? 1 : ( finalPower > 255 ? 255 : finalPower ); } int Captain::GetKnowledge() const { return knowledge + GetKnowledgeModificator( nullptr ); } int Captain::GetMorale() const { int result = Morale::NORMAL; // global modificator result += GetMoraleModificator( nullptr ); // A special artifact ability presence must be the last check. const Artifact maxMoraleArtifact = bag_artifacts.getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::MAXIMUM_MORALE ); if ( maxMoraleArtifact.isValid() ) { result = Morale::BLOOD; } return Morale::Normalize( result ); } int Captain::GetLuck() const { int result = Luck::NORMAL; // global modificator result += GetLuckModificator( nullptr ); // A special artifact ability presence must be the last check. const Artifact maxLuckArtifact = bag_artifacts.getFirstArtifactWithBonus( fheroes2::ArtifactBonusType::MAXIMUM_LUCK ); if ( maxLuckArtifact.isValid() ) { result = Luck::IRISH; } return Luck::Normalize( result ); } int Captain::GetRace() const { return home.GetRace(); } int Captain::GetColor() const { return home.GetColor(); } const std::string & Captain::GetName() const { return home.GetName(); } int Captain::GetType() const { return HeroBase::CAPTAIN; } const Army & Captain::GetArmy() const { return home.GetArmy(); } Army & Captain::GetArmy() { return home.GetArmy(); } int Captain::GetControl() const { return home.GetControl(); } void Captain::ActionAfterBattle() { SetSpellPoints( GetMaxSpellPoints() ); } void Captain::ActionPreBattle() { spell_book.resetState(); } const Castle * Captain::inCastle() const { return &home; } fheroes2::Sprite Captain::GetPortrait( const PortraitType type ) const { switch ( type ) { case PORT_BIG: { const int portraitIcnId = GetPortraitIcnId( GetRace() ); if ( portraitIcnId < 0 ) return fheroes2::Image(); fheroes2::Sprite portrait = fheroes2::AGG::GetICN( portraitIcnId, 0 ); const fheroes2::Image & flag = fheroes2::AGG::GetICN( ICN::getFlagIcnId( GetColor() ), 0 ); const fheroes2::Point & offset = GetFlagOffset( GetRace() ); fheroes2::Blit( flag, portrait, offset.x, offset.y ); return portrait; } case PORT_MEDIUM: case PORT_SMALL: switch ( GetRace() ) { case Race::KNGT: return fheroes2::AGG::GetICN( ICN::MINICAPT, 0 ); case Race::BARB: return fheroes2::AGG::GetICN( ICN::MINICAPT, 1 ); case Race::SORC: return fheroes2::AGG::GetICN( ICN::MINICAPT, 2 ); case Race::WRLK: return fheroes2::AGG::GetICN( ICN::MINICAPT, 3 ); case Race::WZRD: return fheroes2::AGG::GetICN( ICN::MINICAPT, 4 ); case Race::NECR: return fheroes2::AGG::GetICN( ICN::MINICAPT, 5 ); default: break; } break; default: break; } // We shouldn't even reach this code! assert( 0 ); return fheroes2::AGG::GetICN( -1, 0 ); } void Captain::PortraitRedraw( const int32_t px, const int32_t py, const PortraitType type, fheroes2::Image & dstsf ) const { if ( !isValid() ) return; const fheroes2::Sprite & port = GetPortrait( type ); if ( PORT_SMALL != type ) { // a normal portrait in a castle or in battle fheroes2::Blit( port, dstsf, px, py ); return; } const fheroes2::Sprite & mana = fheroes2::AGG::GetICN( ICN::MANA, GetManaIndexSprite() ); const int iconWidth = Interface::IconsBar::getItemWidth(); const int iconHeight = Interface::IconsBar::getItemHeight(); const int barWidth = 7; // background fheroes2::Fill( dstsf, px, py, iconWidth, iconHeight, 0 ); // mobility is always 0 const uint8_t blueColor = fheroes2::GetColorId( 15, 30, 120 ); fheroes2::Fill( dstsf, px, py, barWidth, iconHeight, blueColor ); // portrait fheroes2::Blit( port, dstsf, px + barWidth + 1, py ); // spell points fheroes2::Fill( dstsf, px + barWidth + port.width() + 2, py, barWidth, iconHeight, blueColor ); fheroes2::Blit( mana, dstsf, px + barWidth + port.width() + 2, py + mana.y() ); } int Captain::GetManaIndexSprite() const { // valid range (0 - 25) const int r = GetMaxSpellPoints() / 5; return 25 >= r ? r : 25; } fheroes2-1.1.6+dfsg/src/fheroes2/castle/captain.h000066400000000000000000000062211476115357100215350ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "heroes_base.h" #include "image.h" class Army; class Castle; class Captain final : public HeroBase { public: explicit Captain( Castle & castle ); Captain( const Captain & ) = delete; ~Captain() override = default; Captain & operator=( const Captain & ) = delete; bool isValid() const override; int GetAttack() const override; int GetDefense() const override; int GetPower() const override; int GetKnowledge() const override; int GetMorale() const override; int GetLuck() const override; int GetRace() const override; int GetColor() const override; int GetType() const override; int GetControl() const override; const std::string & GetName() const override; const Castle * inCastle() const override; int GetLevelSkill( int ) const override { return 0; } uint32_t GetSecondarySkillValue( int /* skill */ ) const override { return 0; } const Army & GetArmy() const override; Army & GetArmy() override; uint32_t GetMaxSpellPoints() const override { return knowledge * 10; } void ActionPreBattle() override; void ActionAfterBattle() override; void PortraitRedraw( const int32_t px, const int32_t py, const PortraitType type, fheroes2::Image & dstsf ) const override; fheroes2::Sprite GetPortrait( const PortraitType type ) const; private: int GetManaIndexSprite() const; Castle & home; }; fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle.cpp000066400000000000000000002357151476115357100217400ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "castle.h" #include #include #include #include #include #include #include "agg_image.h" #include "ai_planner.h" #include "army_troop.h" #include "artifact.h" #include "audio_manager.h" #include "battle_board.h" #include "battle_tower.h" #include "castle_building_info.h" #include "dialog.h" #include "difficulty.h" #include "direction.h" #include "game.h" #include "game_io.h" #include "game_static.h" #include "ground.h" #include "heroes.h" #include "heroes_base.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "logging.h" #include "luck.h" #include "m82.h" #include "map_format_helper.h" #include "map_format_info.h" #include "maps.h" #include "maps_fileinfo.h" #include "maps_tiles.h" #include "morale.h" #include "mp2.h" #include "payment.h" #include "profit.h" #include "rand.h" #include "resource.h" #include "save_format_version.h" #include "screen.h" #include "serialize.h" #include "settings.h" #include "skill.h" #include "spell.h" #include "spell_storage.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "week.h" #include "world.h" namespace { const size_t maximumCastles = 72; const std::array defaultCastleNames = { gettext_noop( "Blackridge" ), gettext_noop( "Pinehurst" ), gettext_noop( "Woodhaven" ), gettext_noop( "Hillstone" ), gettext_noop( "Whiteshield" ), gettext_noop( "Bloodreign" ), gettext_noop( "Dragontooth" ), gettext_noop( "Greywind" ), gettext_noop( "Blackwind" ), gettext_noop( "Portsmith" ), gettext_noop( "Middle Gate" ), gettext_noop( "Tundara" ), gettext_noop( "Vulcania" ), gettext_noop( "Sansobar" ), gettext_noop( "Atlantium" ), gettext_noop( "Baywatch" ), gettext_noop( "Wildabar" ), gettext_noop( "Fountainhead" ), gettext_noop( "Vertigo" ), gettext_noop( "Winterkill" ), gettext_noop( "Nightshadow" ), gettext_noop( "Sandcaster" ), gettext_noop( "Lakeside" ), gettext_noop( "Olympus" ), gettext_noop( "Brindamoor" ), gettext_noop( "Burlock" ), gettext_noop( "Xabran" ), gettext_noop( "Dragadune" ), gettext_noop( "Alamar" ), gettext_noop( "Kalindra" ), gettext_noop( "Blackfang" ), gettext_noop( "Basenji" ), gettext_noop( "Algary" ), gettext_noop( "Sorpigal" ), gettext_noop( "New Dawn" ), gettext_noop( "Erliquin" ), gettext_noop( "Avone" ), gettext_noop( "Big Oak" ), gettext_noop( "Hampshire" ), gettext_noop( "Chandler" ), gettext_noop( "South Mill" ), gettext_noop( "Weed Patch" ), gettext_noop( "Roc Haven" ), gettext_noop( "Avalon" ), gettext_noop( "Antioch" ), gettext_noop( "Brownston" ), gettext_noop( "Weddington" ), gettext_noop( "Whittingham" ), gettext_noop( "Westfork" ), gettext_noop( "Hilltop" ), gettext_noop( "Yorksford" ), gettext_noop( "Sherman" ), gettext_noop( "Roscomon" ), gettext_noop( "Elk's Head" ), gettext_noop( "Cathcart" ), gettext_noop( "Viper's Nest" ), gettext_noop( "Pig's Eye" ), gettext_noop( "Blacksford" ), gettext_noop( "Burton" ), gettext_noop( "Blackburn" ), gettext_noop( "Lankershire" ), gettext_noop( "Lombard" ), gettext_noop( "Timberhill" ), gettext_noop( "Fenton" ), gettext_noop( "Troy" ), gettext_noop( "Forder Oaks" ), gettext_noop( "Meramec" ), gettext_noop( "Quick Silver" ), gettext_noop( "Westmoor" ), gettext_noop( "Willow" ), gettext_noop( "Sheltemburg" ), gettext_noop( "Corackston" ) }; } Castle::Castle( const int32_t posX, const int32_t posY, int race ) : MapPosition( { posX, posY } ) , _race( race ) { // Do nothing. } void Castle::LoadFromMP2( const std::vector & data ) { assert( data.size() == MP2::MP2_CASTLE_STRUCTURE_SIZE ); // Structure containing information about town or castle. // // - uint8_t (1 byte) // Owner color. Possible values: // 00 - blue // 01 - green // 02 - red // 03 - yellow // 04 - orange // 05 - purple // 255 - none // // - uint8_t (1 byte) // Does the town / castle have custom buildings set by map creator? // // - uint16_t (2 bytes) // Bitfield containing common buildings within the town / castle. // 0000 0000 0000 0010 : Thieves' Guild // 0000 0000 0000 0100 : Tavern // 0000 0000 0000 1000 : Shipyard // 0000 0000 0001 0000 : Well // 0000 0000 1000 0000 : Statue // 0000 0001 0000 0000 : Left Turret // 0000 0010 0000 0000 : Right Turret // 0000 0100 0000 0000 : Marketplace // 0000 1000 0000 0000 : First monster level growth building // 0001 0000 0000 0000 : Moat // 0010 0000 0000 0000 : Special building // // - uint16_t (2 bytes) // Bitfield containing information about built dwellings in the town / castle. // 0000 0000 0000 1000 : level 1 dwelling // 0000 0000 0001 0000 : level 2 dwelling // 0000 0000 0010 0000 : level 3 dwelling // 0000 0000 0100 0000 : level 4 dwelling // 0000 0000 1000 0000 : level 5 dwelling // 0000 0001 0000 0000 : level 6 dwelling // 0000 0010 0000 0000 : upgraded level 2 dwelling // 0000 0100 0000 0000 : upgraded level 3 dwelling // 0000 1000 0000 0000 : upgraded level 4 dwelling // 0001 0000 0000 0000 : upgraded level 5 dwelling // 0010 0000 0000 0000 : upgraded level 6 dwelling // // - uint8_t (1 byte) // Magic Guild level. // // - uint8_t (1 byte) // Does the town / castle have custom set defenders? // // - uint8_t (1 byte) // Custom defender monster type in army slot 1. // // - uint8_t (1 byte) // Custom defender monster type in army slot 2. // // - uint8_t (1 byte) // Custom defender monster type in army slot 3. // // - uint8_t (1 byte) // Custom defender monster type in army slot 4. // // - uint8_t (1 byte) // Custom defender monster type in army slot 5. // // - uint16_t (2 bytes) // The number of custom defender monsters in army slot 1. // // - uint16_t (2 bytes) // The number of custom defender monsters in army slot 2. // // - uint16_t (2 bytes) // The number of custom defender monsters in army slot 3. // // - uint16_t (2 bytes) // The number of custom defender monsters in army slot 4. // // - uint16_t (2 bytes) // The number of custom defender monsters in army slot 5. // // - uint8_t (1 byte) // Does the town / castle have captain? // // - uint8_t (1 byte) // Does the town / castle have a specified name? // // - string of 13 bytes // Null terminated string of custom town / castle name. // // - uint8_t (1 byte) // Town / castle faction type. Possible values // 00 - knight // 01 - barbarian // 02 - sorceress // 03 - warlock // 04 - wizard // 05 - necromancer // 06 - random // // - uint8_t (1 byte) // Is it a castle (is castle building being built)? // // - uint8_t (1 byte) // Is it allowed to build a castle? // // - unused 29 bytes // Always zeros. ROStreamBuf dataStream( data ); const uint8_t ownerColor = dataStream.get(); switch ( ownerColor ) { case 0: SetColor( Color::BLUE ); break; case 1: SetColor( Color::GREEN ); break; case 2: SetColor( Color::RED ); break; case 3: SetColor( Color::YELLOW ); break; case 4: SetColor( Color::ORANGE ); break; case 5: SetColor( Color::PURPLE ); break; default: SetColor( Color::NONE ); break; } const bool hasCustomBuildings = ( dataStream.get() != 0 ); if ( hasCustomBuildings ) { // Common buildings. const uint16_t commonBuildings = dataStream.getLE16(); if ( 0x0002 & commonBuildings ) _constructedBuildings |= BUILD_THIEVESGUILD; if ( 0x0004 & commonBuildings ) _constructedBuildings |= BUILD_TAVERN; if ( 0x0008 & commonBuildings ) _constructedBuildings |= BUILD_SHIPYARD; if ( 0x0010 & commonBuildings ) _constructedBuildings |= BUILD_WELL; if ( 0x0080 & commonBuildings ) _constructedBuildings |= BUILD_STATUE; if ( 0x0100 & commonBuildings ) _constructedBuildings |= BUILD_LEFTTURRET; if ( 0x0200 & commonBuildings ) _constructedBuildings |= BUILD_RIGHTTURRET; if ( 0x0400 & commonBuildings ) _constructedBuildings |= BUILD_MARKETPLACE; if ( 0x1000 & commonBuildings ) _constructedBuildings |= BUILD_MOAT; if ( 0x0800 & commonBuildings ) _constructedBuildings |= BUILD_WEL2; if ( 0x2000 & commonBuildings ) _constructedBuildings |= BUILD_SPEC; // Existing dwellings. const uint16_t existingDwellings = dataStream.getLE16(); if ( 0x0008 & existingDwellings ) _constructedBuildings |= DWELLING_MONSTER1; if ( 0x0010 & existingDwellings ) _constructedBuildings |= DWELLING_MONSTER2; if ( 0x0020 & existingDwellings ) _constructedBuildings |= DWELLING_MONSTER3; if ( 0x0040 & existingDwellings ) _constructedBuildings |= DWELLING_MONSTER4; if ( 0x0080 & existingDwellings ) _constructedBuildings |= DWELLING_MONSTER5; if ( 0x0100 & existingDwellings ) _constructedBuildings |= DWELLING_MONSTER6; if ( 0x0200 & existingDwellings ) _constructedBuildings |= DWELLING_UPGRADE2 | DWELLING_MONSTER2; if ( 0x0400 & existingDwellings ) _constructedBuildings |= DWELLING_UPGRADE3 | DWELLING_MONSTER3; if ( 0x0800 & existingDwellings ) _constructedBuildings |= DWELLING_UPGRADE4 | DWELLING_MONSTER4; if ( 0x1000 & existingDwellings ) _constructedBuildings |= DWELLING_UPGRADE5 | DWELLING_MONSTER5; if ( 0x2000 & existingDwellings ) _constructedBuildings |= DWELLING_UPGRADE6 | DWELLING_MONSTER6; // magic tower const uint8_t magicGuildLevel = dataStream.get(); if ( 0 < magicGuildLevel ) _constructedBuildings |= BUILD_MAGEGUILD1; if ( 1 < magicGuildLevel ) _constructedBuildings |= BUILD_MAGEGUILD2; if ( 2 < magicGuildLevel ) _constructedBuildings |= BUILD_MAGEGUILD3; if ( 3 < magicGuildLevel ) _constructedBuildings |= BUILD_MAGEGUILD4; if ( 4 < magicGuildLevel ) _constructedBuildings |= BUILD_MAGEGUILD5; } else { // Skip reading 5 bytes corresponding to custom buildings for the town / castle. dataStream.skip( 5 ); // Set default buildings. _setDefaultBuildings(); } const bool customDefenders = ( dataStream.get() != 0 ); if ( customDefenders ) { Troop troops[5]; // set monster id for ( Troop & troop : troops ) troop.SetMonster( dataStream.get() + 1 ); // set count for ( Troop & troop : troops ) troop.SetCount( dataStream.getLE16() ); _army.Assign( troops, std::end( troops ) ); SetModes( CUSTOM_ARMY ); } else { // Skip 15 bytes as custom defenders are not set. dataStream.skip( 15 ); } const bool isCaptainAvailable = ( dataStream.get() != 0 ); if ( isCaptainAvailable ) { _constructedBuildings |= BUILD_CAPTAIN; } const bool isCustomTownNameSet = ( dataStream.get() != 0 ); if ( isCustomTownNameSet ) { _name = dataStream.getString( 13 ); } else { // Skip 13 bytes since the name is not set. dataStream.skip( 13 ); } const uint8_t castleFaction = dataStream.get(); switch ( castleFaction ) { case 0: _race = Race::KNGT; break; case 1: _race = Race::BARB; break; case 2: _race = Race::SORC; break; case 3: _race = Race::WRLK; break; case 4: _race = Race::WZRD; break; case 5: _race = Race::NECR; break; default: { const uint32_t kingdomRace = Players::GetPlayerRace( GetColor() ); _race = ( Color::NONE != GetColor() && ( Race::ALL & kingdomRace ) ? kingdomRace : Race::Rand() ); break; } } const bool isCastleBuilt = ( dataStream.get() != 0 ); if ( isCastleBuilt ) { _constructedBuildings |= BUILD_CASTLE; } else { _constructedBuildings |= BUILD_TENT; } _disabledBuildings = 0; const bool isCastleNotAllowed = ( dataStream.get() != 0 ); if ( isCastleNotAllowed ) { _disabledBuildings |= BUILD_CASTLE; } // Skip the rest of 29 bytes. _postLoad(); } void Castle::loadFromResurrectionMap( const Maps::Map_Format::CastleMetadata & metadata ) { modes = 0; _constructedBuildings = Maps::getBuildingsFromVector( metadata.builtBuildings ); if ( !metadata.customBuildings ) { _setDefaultBuildings(); } _disabledBuildings = 0; for ( const uint32_t building : metadata.bannedBuildings ) { _disabledBuildings |= building; } // Check the default Army state for the Neutral player. if ( Maps::loadCastleArmy( _army, metadata ) ) { SetModes( CUSTOM_ARMY ); } if ( !metadata.customName.empty() ) { _name = metadata.customName; } _postLoad(); } void Castle::_postLoad() { // Fix dwelling upgrades dependent from race. (For random race towns.) switch ( _race ) { case Race::KNGT: _constructedBuildings &= ~DWELLING_UPGRADE7; break; case Race::BARB: _constructedBuildings &= ~( DWELLING_UPGRADE3 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7 ); break; case Race::SORC: _constructedBuildings &= ~( DWELLING_UPGRADE5 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7 ); break; case Race::WRLK: _constructedBuildings &= ~( DWELLING_UPGRADE2 | DWELLING_UPGRADE3 | DWELLING_UPGRADE5 ); break; case Race::WZRD: _constructedBuildings &= ~( DWELLING_UPGRADE2 | DWELLING_UPGRADE4 | DWELLING_UPGRADE7 ); break; case Race::NECR: _constructedBuildings &= ~( DWELLING_UPGRADE6 | DWELLING_UPGRADE7 ); break; default: break; } // Fill built dwellings with weekly growth monsters. if ( _constructedBuildings & DWELLING_MONSTER1 ) { _dwelling[0] = Monster( _race, DWELLING_MONSTER1 ).GetGrown(); } if ( _constructedBuildings & DWELLING_UPGRADE2 ) { _dwelling[1] = Monster( _race, DWELLING_UPGRADE2 ).GetGrown(); } else if ( _constructedBuildings & DWELLING_MONSTER2 ) { _dwelling[1] = Monster( _race, DWELLING_MONSTER2 ).GetGrown(); } if ( _constructedBuildings & DWELLING_UPGRADE3 ) { _dwelling[2] = Monster( _race, DWELLING_UPGRADE3 ).GetGrown(); } else if ( _constructedBuildings & DWELLING_MONSTER3 ) { _dwelling[2] = Monster( _race, DWELLING_MONSTER3 ).GetGrown(); } if ( _constructedBuildings & DWELLING_UPGRADE4 ) { _dwelling[3] = Monster( _race, DWELLING_UPGRADE4 ).GetGrown(); } else if ( _constructedBuildings & DWELLING_MONSTER4 ) { _dwelling[3] = Monster( _race, DWELLING_MONSTER4 ).GetGrown(); } if ( _constructedBuildings & DWELLING_UPGRADE5 ) { _dwelling[4] = Monster( _race, DWELLING_UPGRADE5 ).GetGrown(); } else if ( _constructedBuildings & DWELLING_MONSTER5 ) { _dwelling[4] = Monster( _race, DWELLING_MONSTER5 ).GetGrown(); } if ( _constructedBuildings & DWELLING_UPGRADE7 ) { _dwelling[5] = Monster( _race, DWELLING_UPGRADE7 ).GetGrown(); } else if ( _constructedBuildings & DWELLING_UPGRADE6 ) { _dwelling[5] = Monster( _race, DWELLING_UPGRADE6 ).GetGrown(); } else if ( _constructedBuildings & DWELLING_MONSTER6 ) { _dwelling[5] = Monster( _race, DWELLING_MONSTER6 ).GetGrown(); } _army.SetColor( GetColor() ); // fix captain if ( _constructedBuildings & BUILD_CAPTAIN ) { _captain.LoadDefaults( HeroBase::CAPTAIN, _race ); _captain.SetSpellPoints( _captain.GetMaxSpellPoints() ); } // MageGuild _mageGuild.initialize( _race, HaveLibraryCapability() ); // educate heroes and captain _educateHeroes(); // AI troops auto pack for gray towns if ( Color::NONE == GetColor() && !Modes( CUSTOM_ARMY ) ) { // towns get 4 reinforcements at the start of the game for ( int i = 0; i < 4; ++i ) _joinRNDArmy(); } if ( !HasSeaAccess() ) { // Remove shipyard if no sea access. _constructedBuildings &= ~BUILD_SHIPYARD; } // remove tavern from necromancer castle if ( Race::NECR == _race && ( _constructedBuildings & BUILD_TAVERN ) ) { _constructedBuildings &= ~BUILD_TAVERN; const GameVersion version = Settings::Get().getCurrentMapInfo().version; if ( version == GameVersion::PRICE_OF_LOYALTY || version == GameVersion::RESURRECTION ) { _constructedBuildings |= BUILD_SHRINE; } } SetModes( ALLOW_TO_BUILD_TODAY ); // end DEBUG_LOG( DBG_GAME, DBG_INFO, ( _constructedBuildings & BUILD_CASTLE ? "castle" : "town" ) << ": " << _name << ", color: " << Color::String( GetColor() ) << ", race: " << Race::String( _race ) ) } void Castle::_setDefaultBuildings() { _constructedBuildings |= DWELLING_MONSTER1; uint32_t dwelling2 = 0; switch ( Game::getDifficulty() ) { case Difficulty::EASY: dwelling2 = 75; break; case Difficulty::NORMAL: dwelling2 = 50; break; case Difficulty::HARD: dwelling2 = 25; break; case Difficulty::EXPERT: dwelling2 = 10; break; default: break; } if ( dwelling2 >= Rand::Get( 1, 100 ) ) { _constructedBuildings |= DWELLING_MONSTER2; } } uint32_t Castle::CountBuildings() const { uint32_t tavern = BUILD_TAVERN; if ( _race == Race::NECR ) { const GameVersion version = Settings::Get().getCurrentMapInfo().version; if ( version == GameVersion::PRICE_OF_LOYALTY || version == GameVersion::RESURRECTION ) { tavern = BUILD_SHRINE; } else { tavern = BUILD_NOTHING; } } return CountBits( _constructedBuildings & ( BUILD_THIEVESGUILD | tavern | BUILD_SHIPYARD | BUILD_WELL | BUILD_STATUE | BUILD_LEFTTURRET | BUILD_RIGHTTURRET | BUILD_MARKETPLACE | BUILD_WEL2 | BUILD_MOAT | BUILD_SPEC | BUILD_CAPTAIN | BUILD_CASTLE | BUILD_MAGEGUILD1 | DWELLING_MONSTER1 | DWELLING_MONSTER2 | DWELLING_MONSTER3 | DWELLING_MONSTER4 | DWELLING_MONSTER5 | DWELLING_MONSTER6 ) ); } bool Castle::isPosition( const fheroes2::Point & pt ) const { const fheroes2::Point & mp = GetCenter(); /* - --- -+++- ++X++ */ return ( ( pt.x >= mp.x - 1 && pt.x <= mp.x + 1 && ( pt.y == mp.y - 1 || pt.y == mp.y ) ) || ( ( pt.x == mp.x - 2 || pt.x == mp.x + 2 ) && pt.y == mp.y ) ); } void Castle::_educateHeroes() { if ( GetLevelMageGuild() == 0 ) { return; } Heroes * hero = world.GetHero( *this ); if ( hero != nullptr ) { MageGuildEducateHero( *hero ); } if ( _captain.isValid() ) { MageGuildEducateHero( _captain ); } } int Castle::getBuildingValue() const { int value = CountBuildings(); // Additional value for the most important buildings if ( isBuild( BUILD_CASTLE ) ) value += 5; if ( isBuild( DWELLING_MONSTER6 ) ) value += 6; if ( _race == Race::WRLK && isBuild( DWELLING_UPGRADE7 ) ) value += 2; // DWELLING_UPGRADE7 resolves to a negative, can't use <= operator for ( uint32_t upgrade = DWELLING_UPGRADE2; upgrade <= DWELLING_UPGRADE6; upgrade <<= 1 ) { if ( isBuild( upgrade ) ) ++value; } int increase = 1; for ( uint32_t guild = BUILD_MAGEGUILD2; guild <= BUILD_MAGEGUILD5; guild <<= 1 ) { if ( isBuild( guild ) ) value += increase; ++increase; } return value; } Troops Castle::getAvailableArmy( Funds potentialBudget ) const { Troops reinforcement( _army.getTroops() ); for ( uint32_t dw = DWELLING_MONSTER6; dw >= DWELLING_MONSTER1; dw >>= 1 ) { if ( isBuild( dw ) ) { const Monster monster( _race, GetActualDwelling( dw ) ); const uint32_t available = getMonstersInDwelling( dw ); uint32_t couldRecruit = potentialBudget.getLowestQuotient( monster.GetCost() ); if ( available < couldRecruit ) couldRecruit = available; if ( couldRecruit > 0 ) { potentialBudget -= ( monster.GetCost() * couldRecruit ); reinforcement.PushBack( monster, couldRecruit ); } } } return reinforcement; } double Castle::getArmyRecruitmentValue() const { return getAvailableArmy( GetKingdom().GetFunds() ).GetStrength(); } double Castle::getVisitValue( const Heroes & hero ) const { const Troops & heroArmy = hero.GetArmy(); Troops futureArmy( heroArmy ); const double heroArmyStrength = futureArmy.GetStrength(); Funds potentialFunds = GetKingdom().GetFunds(); double spellValue = 0; const int mageGuildLevel = GetLevelMageGuild(); if ( mageGuildLevel > 0 ) { const int spellPower = hero.GetPower(); const SpellStorage & guildSpells = _mageGuild.GetSpells( GetLevelMageGuild(), isLibraryBuild() ); for ( const Spell & spell : guildSpells ) { if ( hero.CanLearnSpell( spell ) && !hero.HaveSpell( spell, true ) ) { spellValue += spell.getStrategicValue( heroArmyStrength, hero.GetMaxSpellPoints(), spellPower ); } } if ( !hero.HaveSpellBook() && spellValue > 0 ) { const Funds payment = PaymentConditions::BuySpellBook(); if ( potentialFunds < payment || hero.GetBagArtifacts().isFull() ) { // Since the hero does not have a magic book and cannot buy any then spells are useless. spellValue = 0; } else { // The hero does not have a magic book but it can buy one. Let's make the visit little more valuable. potentialFunds -= payment; spellValue += 50; } } } for ( size_t i = 0; i < futureArmy.Size(); ++i ) { Troop * troop = futureArmy.GetTroop( i ); if ( troop != nullptr && troop->isValid() && troop->isAllowUpgrade() ) { if ( GetRace() != troop->GetRace() ) { continue; } if ( !isBuild( troop->GetUpgrade().GetDwelling() ) ) { continue; } const Funds payment = troop->GetTotalUpgradeCost(); if ( potentialFunds >= payment ) { potentialFunds -= payment; troop->Upgrade(); } } } const double upgradeStrength = futureArmy.GetStrength() - heroArmyStrength; return spellValue + upgradeStrength + futureArmy.getReinforcementValue( getAvailableArmy( potentialFunds ) ); } bool Castle::_isExactBuildingBuilt( const uint32_t buildingToCheck ) const { assert( CountBits( buildingToCheck ) == 1 ); // This building is not built at all if ( ( _constructedBuildings & buildingToCheck ) == 0 ) { return false; } const auto checkBuilding = [this]( const uint32_t expectedLevels, const uint32_t allPossibleLevels ) { // All expected levels should be built assert( ( _constructedBuildings & expectedLevels ) == expectedLevels ); // Only the expected levels of all possible levels should be built return ( _constructedBuildings & allPossibleLevels ) == expectedLevels; }; if ( buildingToCheck & BUILD_MAGEGUILD ) { switch ( buildingToCheck ) { case BUILD_MAGEGUILD1: return checkBuilding( BUILD_MAGEGUILD1, BUILD_MAGEGUILD ); case BUILD_MAGEGUILD2: return checkBuilding( BUILD_MAGEGUILD1 | BUILD_MAGEGUILD2, BUILD_MAGEGUILD ); case BUILD_MAGEGUILD3: return checkBuilding( BUILD_MAGEGUILD1 | BUILD_MAGEGUILD2 | BUILD_MAGEGUILD3, BUILD_MAGEGUILD ); case BUILD_MAGEGUILD4: return checkBuilding( BUILD_MAGEGUILD1 | BUILD_MAGEGUILD2 | BUILD_MAGEGUILD3 | BUILD_MAGEGUILD4, BUILD_MAGEGUILD ); case BUILD_MAGEGUILD5: return checkBuilding( BUILD_MAGEGUILD1 | BUILD_MAGEGUILD2 | BUILD_MAGEGUILD3 | BUILD_MAGEGUILD4 | BUILD_MAGEGUILD5, BUILD_MAGEGUILD ); default: assert( 0 ); } } if ( buildingToCheck & ( DWELLING_MONSTERS | DWELLING_UPGRADES ) ) { switch ( buildingToCheck ) { case DWELLING_MONSTER1: // Level 1 dwellings have no upgrades return true; case DWELLING_MONSTER2: return checkBuilding( DWELLING_MONSTER2, DWELLING_MONSTER2 | DWELLING_UPGRADE2 ); case DWELLING_MONSTER3: return checkBuilding( DWELLING_MONSTER3, DWELLING_MONSTER3 | DWELLING_UPGRADE3 ); case DWELLING_MONSTER4: return checkBuilding( DWELLING_MONSTER4, DWELLING_MONSTER4 | DWELLING_UPGRADE4 ); case DWELLING_MONSTER5: return checkBuilding( DWELLING_MONSTER5, DWELLING_MONSTER5 | DWELLING_UPGRADE5 ); case DWELLING_MONSTER6: // Take the Black Dragon upgrade (DWELLING_UPGRADE7) into account return checkBuilding( DWELLING_MONSTER6, DWELLING_MONSTER6 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7 ); case DWELLING_UPGRADE2: return checkBuilding( DWELLING_MONSTER2 | DWELLING_UPGRADE2, DWELLING_MONSTER2 | DWELLING_UPGRADE2 ); case DWELLING_UPGRADE3: return checkBuilding( DWELLING_MONSTER3 | DWELLING_UPGRADE3, DWELLING_MONSTER3 | DWELLING_UPGRADE3 ); case DWELLING_UPGRADE4: return checkBuilding( DWELLING_MONSTER4 | DWELLING_UPGRADE4, DWELLING_MONSTER4 | DWELLING_UPGRADE4 ); case DWELLING_UPGRADE5: return checkBuilding( DWELLING_MONSTER5 | DWELLING_UPGRADE5, DWELLING_MONSTER5 | DWELLING_UPGRADE5 ); case DWELLING_UPGRADE6: // Take the Black Dragon upgrade (DWELLING_UPGRADE7) into account return checkBuilding( DWELLING_MONSTER6 | DWELLING_UPGRADE6, DWELLING_MONSTER6 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7 ); case DWELLING_UPGRADE7: // Black Dragon upgrade return checkBuilding( DWELLING_MONSTER6 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7, DWELLING_MONSTER6 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7 ); default: assert( 0 ); } } return true; } uint32_t * Castle::_getDwelling( const uint32_t buildingType ) { if ( isBuild( buildingType ) ) switch ( buildingType ) { case DWELLING_MONSTER1: return &_dwelling[0]; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return &_dwelling[1]; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return &_dwelling[2]; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return &_dwelling[3]; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return &_dwelling[4]; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return &_dwelling[5]; default: break; } return nullptr; } void Castle::ActionNewDay() { _educateHeroes(); SetModes( ALLOW_TO_BUILD_TODAY ); } void Castle::ActionNewWeek() { // Skip the first week if ( world.CountWeek() < 2 ) { return; } static const std::array allDwellings = { DWELLING_MONSTER1, DWELLING_MONSTER2, DWELLING_MONSTER3, DWELLING_MONSTER4, DWELLING_MONSTER5, DWELLING_MONSTER6, DWELLING_UPGRADE2, DWELLING_UPGRADE3, DWELLING_UPGRADE4, DWELLING_UPGRADE5, DWELLING_UPGRADE6, DWELLING_UPGRADE7 }; const bool isNeutral = ( GetColor() == Color::NONE ); const bool isPlagueWeek = ( world.GetWeekType().GetType() == WeekName::PLAGUE ); const bool isMonsterWeek = ( world.GetWeekType().GetType() == WeekName::MONSTERS ); if ( !isPlagueWeek ) { static const std::array basicDwellings = { DWELLING_MONSTER1, DWELLING_MONSTER2, DWELLING_MONSTER3, DWELLING_MONSTER4, DWELLING_MONSTER5, DWELLING_MONSTER6 }; // Normal population growth for ( const uint32_t dwellingId : basicDwellings ) { uint32_t * dwellingMonsters = _getDwelling( dwellingId ); if ( dwellingMonsters == nullptr ) { // Such dwelling (or its upgrade) has not been built continue; } uint32_t growth = Monster( _race, GetActualDwelling( dwellingId ) ).GetGrown(); if ( _constructedBuildings & BUILD_WELL ) { // The well is built. growth += GetGrownWell(); } if ( ( dwellingId == DWELLING_MONSTER1 ) && ( _constructedBuildings & BUILD_WEL2 ) ) { growth += GetGrownWel2(); } if ( isNeutral ) { // Neutral towns always have 50% population growth. growth /= 2; } *dwellingMonsters += growth; } if ( isMonsterWeek && !world.BeginMonth() ) { for ( const uint32_t dwellingId : allDwellings ) { // A building of exactly this level should be built (its upgraded versions should not be considered) if ( !_isExactBuildingBuilt( dwellingId ) ) { continue; } const Monster mons( _race, dwellingId ); if ( !mons.isValid() || mons.GetID() != world.GetWeekType().GetMonster() ) { continue; } uint32_t * dwellingMonsters = _getDwelling( dwellingId ); assert( dwellingMonsters != nullptr ); *dwellingMonsters += GetGrownWeekOf(); break; } } if ( isNeutral ) { // Neutral towns have additional increase in garrison army. _joinRNDArmy(); // The probability that a town will get additional troops is 40%, castle always gets them if ( isCastle() || Rand::Get( 1, 100 ) <= 40 ) { _joinRNDArmy(); } } } // Monthly population growth bonuses should be calculated taking the weekly growth into account if ( world.BeginMonth() ) { assert( world.GetMonth() > 1 ); if ( isPlagueWeek ) { for ( uint32_t & dwellingRef : _dwelling ) { dwellingRef /= 2; } } else if ( isMonsterWeek ) { for ( const uint32_t dwellingId : allDwellings ) { // A building of exactly this level should be built (its upgraded versions should not be considered) if ( !_isExactBuildingBuilt( dwellingId ) ) { continue; } const Monster mons( _race, dwellingId ); if ( !mons.isValid() || mons.GetID() != world.GetWeekType().GetMonster() ) { continue; } uint32_t * dwellingMonsters = _getDwelling( dwellingId ); assert( dwellingMonsters != nullptr ); *dwellingMonsters += *dwellingMonsters * GetGrownMonthOf() / 100; break; } } } } void Castle::ChangeColor( const int newColor ) { SetColor( newColor ); _army.SetColor( newColor ); } int Castle::GetLevelMageGuild() const { if ( _constructedBuildings & BUILD_MAGEGUILD5 ) return 5; if ( _constructedBuildings & BUILD_MAGEGUILD4 ) return 4; if ( _constructedBuildings & BUILD_MAGEGUILD3 ) return 3; if ( _constructedBuildings & BUILD_MAGEGUILD2 ) return 2; if ( _constructedBuildings & BUILD_MAGEGUILD1 ) return 1; return 0; } const char * Castle::GetStringBuilding( const uint32_t buildingType, const int race ) { return fheroes2::getBuildingName( race, static_cast( buildingType ) ); } bool Castle::AllowBuyHero( std::string * msg ) const { const Heroes * hero = world.GetHero( *this ); if ( hero != nullptr ) { if ( msg ) { *msg = _( "Cannot recruit - you already have a Hero in this town." ); } return false; } const Kingdom & myKingdom = GetKingdom(); if ( !myKingdom.AllowRecruitHero( false ) ) { if ( msg ) { *msg = _( "Cannot recruit - you have too many Heroes." ); } return false; } if ( !myKingdom.AllowRecruitHero( true ) ) { if ( msg ) { *msg = _( "Cannot afford a Hero." ); } return false; } return true; } Heroes * Castle::RecruitHero( Heroes * hero ) { if ( !hero || !AllowBuyHero() ) { return nullptr; } if ( world.GetHero( *this ) != nullptr ) { return nullptr; } if ( !hero->Recruit( *this ) ) { return nullptr; } Kingdom & currentKingdom = GetKingdom(); currentKingdom.OddFundsResource( PaymentConditions::RecruitHero() ); if ( GetLevelMageGuild() ) { MageGuildEducateHero( *hero ); } DEBUG_LOG( DBG_GAME, DBG_INFO, _name << ", recruit: " << hero->GetName() ) return hero; } bool Castle::RecruitMonster( const Troop & troop, bool showDialog ) { if ( !troop.isValid() ) return false; int dwellingIndex = 0; switch ( troop.GetDwelling() ) { case DWELLING_MONSTER1: dwellingIndex = 0; break; case DWELLING_UPGRADE2: case DWELLING_MONSTER2: dwellingIndex = 1; break; case DWELLING_UPGRADE3: case DWELLING_MONSTER3: dwellingIndex = 2; break; case DWELLING_UPGRADE4: case DWELLING_MONSTER4: dwellingIndex = 3; break; case DWELLING_UPGRADE5: case DWELLING_MONSTER5: dwellingIndex = 4; break; case DWELLING_UPGRADE7: case DWELLING_UPGRADE6: case DWELLING_MONSTER6: dwellingIndex = 5; break; default: return false; } uint32_t count = troop.GetCount(); if ( _dwelling[dwellingIndex] < count ) { count = _dwelling[dwellingIndex]; } const Funds paymentCosts = troop.GetTotalCost(); Kingdom & kingdom = GetKingdom(); if ( !kingdom.AllowPayment( paymentCosts ) ) { return false; } if ( !GetArmy().JoinTroop( troop ) ) { Heroes * hero = world.GetHero( *this ); if ( hero == nullptr || !hero->GetArmy().JoinTroop( troop ) ) { if ( showDialog ) { fheroes2::showStandardTextMessage( "", _( "There is no room in the garrison for this army." ), Dialog::OK ); } return false; } } kingdom.OddFundsResource( paymentCosts ); _dwelling[dwellingIndex] -= count; DEBUG_LOG( DBG_GAME, DBG_TRACE, _name << " recruit: " << troop.GetMultiName() << "(" << count << ")" ) return true; } uint32_t Castle::getRecruitLimit( const Monster & monster, const Funds & budget ) const { // validate that monster is from the current castle if ( monster.GetRace() != _race ) return 0; const uint32_t available = getMonstersInDwelling( monster.GetDwelling() ); uint32_t willRecruit = budget.getLowestQuotient( monster.GetCost() ); if ( available < willRecruit ) return available; return willRecruit; } uint32_t Castle::getMonstersInDwelling( const uint32_t buildingType ) const { switch ( buildingType ) { case DWELLING_MONSTER1: return _dwelling[0]; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return _dwelling[1]; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return _dwelling[2]; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return _dwelling[3]; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return _dwelling[4]; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return _dwelling[5]; default: break; } return 0; } BuildingStatus Castle::CheckBuyBuilding( const uint32_t build ) const { if ( build & _constructedBuildings ) { return BuildingStatus::ALREADY_BUILT; } if ( _disabledBuildings & build ) { return BuildingStatus::BUILD_DISABLE; } // TODO: remove these conditions and do calculation once per game. switch ( build ) { case BUILD_SHIPYARD: if ( !HasSeaAccess() ) { return BuildingStatus::SHIPYARD_NOT_ALLOWED; } break; case BUILD_SHRINE: if ( Race::NECR != GetRace() || ( Settings::Get().getCurrentMapInfo().version == GameVersion::SUCCESSION_WARS ) ) { return BuildingStatus::BUILD_DISABLE; } break; case BUILD_TAVERN: if ( Race::NECR == GetRace() ) { return BuildingStatus::BUILD_DISABLE; } break; default: break; } if ( build >= BUILD_MAGEGUILD2 && build <= BUILD_MAGEGUILD5 ) { const uint32_t prevMageGuild = build >> 1; if ( !( _constructedBuildings & prevMageGuild ) ) { return BuildingStatus::BUILD_DISABLE; } } if ( !Modes( ALLOW_TO_BUILD_TODAY ) ) { return BuildingStatus::NOT_TODAY; } if ( isCastle() ) { if ( build == BUILD_TENT ) { return BuildingStatus::BUILD_DISABLE; } } else { if ( build != BUILD_CASTLE ) { return BuildingStatus::NEED_CASTLE; } } switch ( build ) { case DWELLING_UPGRADE2: if ( ( Race::WRLK | Race::WZRD ) & _race ) return BuildingStatus::UNKNOWN_UPGRADE; break; case DWELLING_UPGRADE3: if ( ( Race::BARB | Race::WRLK ) & _race ) return BuildingStatus::UNKNOWN_UPGRADE; break; case DWELLING_UPGRADE4: if ( Race::WZRD & _race ) return BuildingStatus::UNKNOWN_UPGRADE; break; case DWELLING_UPGRADE5: if ( ( Race::SORC | Race::WRLK ) & _race ) return BuildingStatus::UNKNOWN_UPGRADE; break; case DWELLING_UPGRADE6: if ( ( Race::BARB | Race::SORC | Race::NECR ) & _race ) return BuildingStatus::UNKNOWN_UPGRADE; break; case DWELLING_UPGRADE7: if ( Race::WRLK != _race ) return BuildingStatus::UNKNOWN_UPGRADE; break; default: break; } const uint32_t requirement = fheroes2::getBuildingRequirement( _race, static_cast( build ) ); for ( uint32_t itr = 0x00000001; itr; itr <<= 1 ) { if ( ( requirement & itr ) && !( _constructedBuildings & itr ) ) { return BuildingStatus::REQUIRES_BUILD; } } if ( !GetKingdom().AllowPayment( PaymentConditions::BuyBuilding( _race, build ) ) ) { return BuildingStatus::LACK_RESOURCES; } return BuildingStatus::ALLOW_BUILD; } BuildingStatus Castle::GetAllBuildingStatus( const Castle & castle ) { if ( !castle.Modes( ALLOW_TO_BUILD_TODAY ) ) return BuildingStatus::NOT_TODAY; if ( !castle.isCastle() ) return BuildingStatus::NEED_CASTLE; const uint32_t rest = ~castle._constructedBuildings; for ( uint32_t itr = 0x00000001; itr; itr <<= 1 ) if ( ( rest & itr ) && ( BuildingStatus::ALLOW_BUILD == castle.CheckBuyBuilding( itr ) ) ) return BuildingStatus::ALLOW_BUILD; for ( uint32_t itr = 0x00000001; itr; itr <<= 1 ) if ( ( rest & itr ) && ( BuildingStatus::LACK_RESOURCES == castle.CheckBuyBuilding( itr ) ) ) return BuildingStatus::LACK_RESOURCES; for ( uint32_t itr = 0x00000001; itr; itr <<= 1 ) if ( ( rest & itr ) && ( BuildingStatus::REQUIRES_BUILD == castle.CheckBuyBuilding( itr ) ) ) return BuildingStatus::REQUIRES_BUILD; return BuildingStatus::UNKNOWN_COND; } bool Castle::BuyBuilding( const uint32_t buildingType ) { if ( !AllowBuyBuilding( buildingType ) ) return false; GetKingdom().OddFundsResource( PaymentConditions::BuyBuilding( _race, buildingType ) ); // add build _constructedBuildings |= buildingType; switch ( buildingType ) { case BUILD_CASTLE: _constructedBuildings &= ~BUILD_TENT; Maps::UpdateCastleSprite( GetCenter(), _race ); Maps::ClearFog( GetIndex(), GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::CASTLE ), GetColor() ); break; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: _educateHeroes(); break; case BUILD_CAPTAIN: _captain.LoadDefaults( HeroBase::CAPTAIN, _race ); _captain.SetSpellPoints( _captain.GetMaxSpellPoints() ); if ( GetLevelMageGuild() ) MageGuildEducateHero( _captain ); break; case BUILD_SPEC: // build library if ( HaveLibraryCapability() ) _educateHeroes(); break; case DWELLING_MONSTER1: _dwelling[0] = Monster( _race, DWELLING_MONSTER1 ).GetGrown(); break; case DWELLING_MONSTER2: _dwelling[1] = Monster( _race, DWELLING_MONSTER2 ).GetGrown(); break; case DWELLING_MONSTER3: _dwelling[2] = Monster( _race, DWELLING_MONSTER3 ).GetGrown(); break; case DWELLING_MONSTER4: _dwelling[3] = Monster( _race, DWELLING_MONSTER4 ).GetGrown(); break; case DWELLING_MONSTER5: _dwelling[4] = Monster( _race, DWELLING_MONSTER5 ).GetGrown(); break; case DWELLING_MONSTER6: _dwelling[5] = Monster( _race, DWELLING_MONSTER6 ).GetGrown(); break; default: break; } // disable day build ResetModes( ALLOW_TO_BUILD_TODAY ); DEBUG_LOG( DBG_GAME, DBG_INFO, _name << " build " << GetStringBuilding( buildingType, _race ) ) return true; } /* draw image castle to position */ void Castle::DrawImageCastle( const fheroes2::Point & pt ) const { fheroes2::Display & display = fheroes2::Display::instance(); const Maps::Tile & tile = world.getTile( GetIndex() ); uint32_t index = 0; fheroes2::Point dst_pt; // draw ground switch ( tile.GetGround() ) { case Maps::Ground::GRASS: index = 0; break; case Maps::Ground::SNOW: index = 10; break; case Maps::Ground::SWAMP: index = 20; break; case Maps::Ground::LAVA: index = 30; break; case Maps::Ground::DESERT: index = 40; break; case Maps::Ground::DIRT: index = 50; break; case Maps::Ground::WASTELAND: index = 60; break; case Maps::Ground::BEACH: index = 70; break; default: return; } for ( uint32_t ii = 0; ii < 5; ++ii ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTWBA, index + ii ); dst_pt.x = pt.x + ii * 32 + sprite.x(); dst_pt.y = pt.y + 3 * 32 + sprite.y(); fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); } for ( uint32_t ii = 0; ii < 5; ++ii ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTWBA, index + 5 + ii ); dst_pt.x = pt.x + ii * 32 + sprite.x(); dst_pt.y = pt.y + 4 * 32 + sprite.y(); fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); } // draw castle switch ( _race ) { case Race::KNGT: index = 0; break; case Race::BARB: index = 32; break; case Race::SORC: index = 64; break; case Race::WRLK: index = 96; break; case Race::WZRD: index = 128; break; case Race::NECR: index = 160; break; default: break; } if ( !( BUILD_CASTLE & _constructedBuildings ) ) index += 16; const fheroes2::Sprite & sprite2 = fheroes2::AGG::GetICN( ICN::OBJNTOWN, index ); dst_pt.x = pt.x + 2 * 32 + sprite2.x(); dst_pt.y = pt.y + sprite2.y(); fheroes2::Blit( sprite2, display, dst_pt.x, dst_pt.y ); for ( uint32_t ii = 0; ii < 5; ++ii ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTOWN, index + 1 + ii ); dst_pt.x = pt.x + ii * 32 + sprite.x(); dst_pt.y = pt.y + 32 + sprite.y(); fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); } for ( uint32_t ii = 0; ii < 5; ++ii ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTOWN, index + 6 + ii ); dst_pt.x = pt.x + ii * 32 + sprite.x(); dst_pt.y = pt.y + 2 * 32 + sprite.y(); fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); } for ( uint32_t ii = 0; ii < 5; ++ii ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::OBJNTOWN, index + 11 + ii ); dst_pt.x = pt.x + ii * 32 + sprite.x(); dst_pt.y = pt.y + 3 * 32 + sprite.y(); fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); } } int Castle::GetICNBoat( const int race ) { switch ( race ) { case Race::BARB: return ICN::TWNBBOAT; case Race::KNGT: return ICN::TWNKBOAT; case Race::NECR: return ICN::TWNNBOAT; case Race::SORC: return ICN::TWNSBOAT; case Race::WRLK: return ICN::TWNWBOAT; case Race::WZRD: return ICN::TWNZBOAT; default: break; } DEBUG_LOG( DBG_GAME, DBG_WARN, "return unknown" ) return ICN::UNKNOWN; } int Castle::GetICNBuilding( const uint32_t buildingType, const int race ) { if ( Race::BARB == race ) { switch ( buildingType ) { case BUILD_CASTLE: return ICN::TWNBCSTL; case BUILD_TENT: return ICN::TWNBTENT; case BUILD_SPEC: return ICN::TWNBSPEC; case BUILD_CAPTAIN: return ICN::TWNBCAPT; case BUILD_WEL2: return ICN::TWNBWEL2; case BUILD_LEFTTURRET: return ICN::TWNBLTUR; case BUILD_RIGHTTURRET: return ICN::TWNBRTUR; case BUILD_MOAT: return ICN::TWNBMOAT; case BUILD_MARKETPLACE: return ICN::TWNBMARK; case BUILD_THIEVESGUILD: return ICN::TWNBTHIE; case BUILD_TAVERN: return ICN::TWNBTVRN; case BUILD_WELL: return ICN::TWNBWELL; case BUILD_STATUE: return ICN::TWNBSTAT; case BUILD_SHIPYARD: return ICN::TWNBDOCK; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return ICN::TWNBMAGE; case DWELLING_MONSTER1: return ICN::TWNBDW_0; case DWELLING_MONSTER2: return ICN::TWNBDW_1; case DWELLING_UPGRADE2: return ICN::TWNBUP_1; case DWELLING_MONSTER3: return ICN::TWNBDW_2; case DWELLING_MONSTER4: return ICN::TWNBDW_3; case DWELLING_UPGRADE4: return ICN::TWNBUP_3; case DWELLING_MONSTER5: return ICN::TWNBDW_4; case DWELLING_UPGRADE5: return ICN::TWNBUP_4; case DWELLING_MONSTER6: return ICN::TWNBDW_5; default: break; } } else if ( Race::KNGT == race ) { switch ( buildingType ) { case BUILD_CASTLE: return ICN::TWNKCSTL; case BUILD_TENT: return ICN::TWNKTENT; case BUILD_SPEC: return ICN::TWNKSPEC; case BUILD_CAPTAIN: return ICN::TWNKCAPT; case BUILD_WEL2: return ICN::KNIGHT_CASTLE_RIGHT_FARM; case BUILD_LEFTTURRET: return ICN::TWNKLTUR; case BUILD_RIGHTTURRET: return ICN::TWNKRTUR; case BUILD_MOAT: return ICN::TWNKMOAT; case BUILD_MARKETPLACE: return ICN::TWNKMARK; case BUILD_THIEVESGUILD: return ICN::TWNKTHIE; case BUILD_TAVERN: return ICN::TWNKTVRN; case BUILD_WELL: return ICN::TWNKWELL; case BUILD_STATUE: return ICN::TWNKSTAT; case BUILD_SHIPYARD: return ICN::TWNKDOCK; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return ICN::TWNKMAGE; case DWELLING_MONSTER1: return ICN::TWNKDW_0; case DWELLING_MONSTER2: return ICN::TWNKDW_1; case DWELLING_UPGRADE2: return ICN::TWNKUP_1; case DWELLING_MONSTER3: return ICN::TWNKDW_2; case DWELLING_UPGRADE3: return ICN::TWNKUP_2; case DWELLING_MONSTER4: return ICN::TWNKDW_3; case DWELLING_UPGRADE4: return ICN::TWNKUP_3; case DWELLING_MONSTER5: return ICN::TWNKDW_4; case DWELLING_UPGRADE5: return ICN::TWNKUP_4; case DWELLING_MONSTER6: return ICN::TWNKDW_5; case DWELLING_UPGRADE6: return ICN::TWNKUP_5; default: break; } } else if ( Race::NECR == race ) { switch ( buildingType ) { case BUILD_CASTLE: return ICN::TWNNCSTL; case BUILD_TENT: return ICN::TWNNTENT; case BUILD_SPEC: return ICN::TWNNSPEC; case BUILD_CAPTAIN: return ICN::NECROMANCER_CASTLE_STANDALONE_CAPTAIN_QUARTERS; case BUILD_WEL2: return ICN::TWNNWEL2; case BUILD_LEFTTURRET: return ICN::TWNNLTUR; case BUILD_RIGHTTURRET: return ICN::TWNNRTUR; case BUILD_MOAT: return ICN::TWNNMOAT; case BUILD_MARKETPLACE: return ICN::TWNNMARK; case BUILD_THIEVESGUILD: return ICN::TWNNTHIE; // shrine case BUILD_SHRINE: return ICN::TWNNTVRN; case BUILD_WELL: return ICN::TWNNWELL; case BUILD_STATUE: return ICN::TWNNSTAT; case BUILD_SHIPYARD: return ICN::TWNNDOCK; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return ICN::TWNNMAGE; case DWELLING_MONSTER1: return ICN::TWNNDW_0; case DWELLING_MONSTER2: return ICN::TWNNDW_1; case DWELLING_UPGRADE2: return ICN::TWNNUP_1; case DWELLING_MONSTER3: return ICN::TWNNDW_2; case DWELLING_UPGRADE3: return ICN::TWNNUP_2; case DWELLING_MONSTER4: return ICN::TWNNDW_3; case DWELLING_UPGRADE4: return ICN::TWNNUP_3; case DWELLING_MONSTER5: return ICN::TWNNDW_4; case DWELLING_UPGRADE5: return ICN::TWNNUP_4; case DWELLING_MONSTER6: return ICN::TWNNDW_5; default: break; } } else if ( Race::SORC == race ) { switch ( buildingType ) { case BUILD_CASTLE: return ICN::TWNSCSTL; case BUILD_TENT: return ICN::TWNSTENT; case BUILD_SPEC: return ICN::TWNSSPEC; case BUILD_CAPTAIN: return ICN::TWNSCAPT; case BUILD_WEL2: return ICN::TWNSWEL2; case BUILD_LEFTTURRET: return ICN::TWNSLTUR; case BUILD_RIGHTTURRET: return ICN::TWNSRTUR; case BUILD_MOAT: return ICN::TWNSMOAT; case BUILD_MARKETPLACE: return ICN::TWNSMARK; case BUILD_THIEVESGUILD: return ICN::TWNSTHIE; case BUILD_TAVERN: return ICN::TWNSTVRN; case BUILD_WELL: return ICN::TWNSWELL; case BUILD_STATUE: return ICN::TWNSSTAT; case BUILD_SHIPYARD: return ICN::TWNSDOCK; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return ICN::TWNSMAGE; case DWELLING_MONSTER1: return ICN::TWNSDW_0; case DWELLING_MONSTER2: return ICN::TWNSDW_1; case DWELLING_UPGRADE2: return ICN::TWNSUP_1; case DWELLING_MONSTER3: return ICN::TWNSDW_2; case DWELLING_UPGRADE3: return ICN::TWNSUP_2; case DWELLING_MONSTER4: return ICN::TWNSDW_3; case DWELLING_UPGRADE4: return ICN::TWNSUP_3; case DWELLING_MONSTER5: return ICN::TWNSDW_4; case DWELLING_MONSTER6: return ICN::TWNSDW_5; default: break; } } else if ( Race::WRLK == race ) { switch ( buildingType ) { case BUILD_CASTLE: return ICN::TWNWCSTL; case BUILD_TENT: return ICN::TWNWTENT; case BUILD_SPEC: return ICN::TWNWSPEC; case BUILD_CAPTAIN: return ICN::TWNWCAPT; case BUILD_WEL2: return ICN::TWNWWEL2; case BUILD_LEFTTURRET: return ICN::TWNWLTUR; case BUILD_RIGHTTURRET: return ICN::TWNWRTUR; case BUILD_MOAT: return ICN::TWNWMOAT; case BUILD_MARKETPLACE: return ICN::TWNWMARK; case BUILD_THIEVESGUILD: return ICN::TWNWTHIE; case BUILD_TAVERN: return ICN::TWNWTVRN; case BUILD_WELL: return ICN::TWNWWELL; case BUILD_STATUE: return ICN::TWNWSTAT; case BUILD_SHIPYARD: return ICN::TWNWDOCK; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return ICN::TWNWMAGE; case DWELLING_MONSTER1: return ICN::TWNWDW_0; case DWELLING_MONSTER2: return ICN::TWNWDW_1; case DWELLING_MONSTER3: return ICN::TWNWDW_2; case DWELLING_MONSTER4: return ICN::TWNWDW_3; case DWELLING_UPGRADE4: return ICN::TWNWUP_3; case DWELLING_MONSTER5: return ICN::TWNWDW_4; case DWELLING_MONSTER6: return ICN::TWNWDW_5; case DWELLING_UPGRADE6: return ICN::TWNWUP_5; case DWELLING_UPGRADE7: return ICN::TWNWUP5B; default: break; } } else if ( Race::WZRD == race ) { switch ( buildingType ) { case BUILD_CASTLE: return ICN::TWNZCSTL; case BUILD_TENT: return ICN::TWNZTENT; case BUILD_SPEC: return ICN::TWNZSPEC; case BUILD_CAPTAIN: return ICN::TWNZCAPT; case BUILD_WEL2: return ICN::TWNZWEL2; case BUILD_LEFTTURRET: return ICN::TWNZLTUR; case BUILD_RIGHTTURRET: return ICN::TWNZRTUR; case BUILD_MOAT: return ICN::TWNZMOAT; case BUILD_MARKETPLACE: return ICN::TWNZMARK; case BUILD_THIEVESGUILD: return ICN::TWNZTHIE; case BUILD_TAVERN: return ICN::TWNZTVRN; case BUILD_WELL: return ICN::TWNZWELL; case BUILD_STATUE: return ICN::TWNZSTAT; case BUILD_SHIPYARD: return ICN::TWNZDOCK; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return ICN::TWNZMAGE; case DWELLING_MONSTER1: return ICN::TWNZDW_0; case DWELLING_MONSTER2: return ICN::TWNZDW_1; case DWELLING_MONSTER3: return ICN::TWNZDW_2; case DWELLING_UPGRADE3: return ICN::TWNZUP_2; case DWELLING_MONSTER4: return ICN::TWNZDW_3; case DWELLING_MONSTER5: return ICN::TWNZDW_4; case DWELLING_UPGRADE5: return ICN::TWNZUP_4; case DWELLING_MONSTER6: return ICN::TWNZDW_5; case DWELLING_UPGRADE6: return ICN::TWNZUP_5; default: break; } } DEBUG_LOG( DBG_GAME, DBG_WARN, "return unknown" << ", race: " << Race::String( race ) << ", build: " << Castle::GetStringBuilding( buildingType, race ) << ", " << buildingType ) return ICN::UNKNOWN; } Heroes * Castle::GetHero() const { return world.GetHero( *this ); } bool Castle::HasSeaAccess() const { const fheroes2::Point possibleSeaTile{ center.x, center.y + 2 }; if ( !Maps::isValidAbsPoint( possibleSeaTile.x, possibleSeaTile.y ) ) { // If a tile below doesn't exist then no reason to check other tiles. return false; } auto doesTileAllowsToPutBoat = []( const Maps::Tile & tile ) { if ( !tile.isWater() ) { // No water, no boat. return false; } if ( tile.getMainObjectPart().icnType == MP2::OBJ_ICN_TYPE_UNKNOWN ) { // The main addon does not exist on this tile. // This means that all objects on this tile are not primary objects (like shadows or some parts of objects). return true; } // If this is an object's shadow or this is an action object that can be removed then it is possible to put a boat here. const MP2::MapObjectType objectType = tile.getMainObjectType(); return MP2::isPickupObject( objectType ) || objectType == MP2::OBJ_BOAT || tile.isPassabilityTransparent(); }; const int32_t index = Maps::GetIndexFromAbsPoint( possibleSeaTile.x, possibleSeaTile.y ); if ( doesTileAllowsToPutBoat( world.getTile( index ) ) ) { return true; } if ( Maps::isValidAbsPoint( possibleSeaTile.x - 1, possibleSeaTile.y ) && doesTileAllowsToPutBoat( world.getTile( index - 1 ) ) ) { return true; } if ( Maps::isValidAbsPoint( possibleSeaTile.x + 1, possibleSeaTile.y ) && doesTileAllowsToPutBoat( world.getTile( index + 1 ) ) ) { return true; } return false; } bool Castle::HasBoatNearby() const { const fheroes2::Point possibleSeaTile{ center.x, center.y + 2 }; if ( !Maps::isValidAbsPoint( possibleSeaTile.x, possibleSeaTile.y ) ) { // If a tile below doesn't exist then no reason to check other tiles. return false; } auto doesTileHaveBoat = []( const Maps::Tile & tile ) { if ( !tile.isWater() ) { // No water, no boat. return false; } const MP2::MapObjectType objectType = tile.getMainObjectType(); return ( objectType == MP2::OBJ_BOAT || objectType == MP2::OBJ_HERO ); }; const int32_t index = Maps::GetIndexFromAbsPoint( possibleSeaTile.x, possibleSeaTile.y ); if ( doesTileHaveBoat( world.getTile( index ) ) ) { return true; } if ( Maps::isValidAbsPoint( possibleSeaTile.x - 1, possibleSeaTile.y ) && doesTileHaveBoat( world.getTile( index - 1 ) ) ) { return true; } if ( Maps::isValidAbsPoint( possibleSeaTile.x + 1, possibleSeaTile.y ) && doesTileHaveBoat( world.getTile( index + 1 ) ) ) { return true; } return false; } int32_t Castle::getTileIndexToPlaceBoat() const { const fheroes2::Point possibleSeaTile{ center.x, center.y + 2 }; if ( !Maps::isValidAbsPoint( possibleSeaTile.x, possibleSeaTile.y ) ) { // If a tile below doesn't exist then no reason to check other tiles. return -1; } auto doesTileAllowsToPutBoat = []( const Maps::Tile & tile ) { if ( !tile.isWater() ) { // No water, no boat. return false; } // Mark the tile as worthy to a place a boat if the main object part does not exist on this tile. // This means that all objects on this tile are not primary objects (like shadows or some parts of objects). return ( tile.getMainObjectPart().icnType == MP2::OBJ_ICN_TYPE_UNKNOWN || tile.isPassabilityTransparent() ); }; const int32_t index = Maps::GetIndexFromAbsPoint( possibleSeaTile.x, possibleSeaTile.y ); if ( doesTileAllowsToPutBoat( world.getTile( index ) ) ) { return index; } if ( Maps::isValidAbsPoint( possibleSeaTile.x - 1, possibleSeaTile.y ) && doesTileAllowsToPutBoat( world.getTile( index - 1 ) ) ) { return index - 1; } if ( Maps::isValidAbsPoint( possibleSeaTile.x + 1, possibleSeaTile.y ) && doesTileAllowsToPutBoat( world.getTile( index + 1 ) ) ) { return index + 1; } return -1; } uint32_t Castle::GetActualDwelling( const uint32_t buildId ) const { switch ( buildId ) { case DWELLING_MONSTER1: case DWELLING_UPGRADE2: case DWELLING_UPGRADE3: case DWELLING_UPGRADE4: case DWELLING_UPGRADE5: case DWELLING_UPGRADE7: return buildId; case DWELLING_MONSTER2: return _constructedBuildings & DWELLING_UPGRADE2 ? DWELLING_UPGRADE2 : buildId; case DWELLING_MONSTER3: return _constructedBuildings & DWELLING_UPGRADE3 ? DWELLING_UPGRADE3 : buildId; case DWELLING_MONSTER4: return _constructedBuildings & DWELLING_UPGRADE4 ? DWELLING_UPGRADE4 : buildId; case DWELLING_MONSTER5: return _constructedBuildings & DWELLING_UPGRADE5 ? DWELLING_UPGRADE5 : buildId; case DWELLING_MONSTER6: return _constructedBuildings & DWELLING_UPGRADE7 ? DWELLING_UPGRADE7 : ( _constructedBuildings & DWELLING_UPGRADE6 ? DWELLING_UPGRADE6 : buildId ); case DWELLING_UPGRADE6: return _constructedBuildings & DWELLING_UPGRADE7 ? DWELLING_UPGRADE7 : buildId; default: break; } return BUILD_NOTHING; } uint32_t Castle::GetUpgradeBuilding( const uint32_t buildingId ) const { if ( _race == Race::WRLK && buildingId == DWELLING_MONSTER6 && isBuild( DWELLING_UPGRADE6 ) ) { // Warlock's dwelling 6 is a special case. return fheroes2::getUpgradeForBuilding( _race, DWELLING_UPGRADE6 ); } return fheroes2::getUpgradeForBuilding( _race, static_cast( buildingId ) ); } std::string Castle::String() const { std::ostringstream os; const Heroes * hero = GetHero(); os << "name and type : " << _name << " (" << Race::String( _race ) << ")" << std::endl << "color : " << Color::String( GetColor() ) << std::endl << "dwellings : "; for ( uint32_t level = 0; level < 7; ++level ) { // there is no dwelling 7 if ( level != 6 && isBuild( DWELLING_MONSTER1 << level ) ) os << level + 1; if ( level > 0 && isBuild( DWELLING_UPGRADE2 << ( level - 1 ) ) ) os << "U, "; else os << ", "; } os << std::endl; os << "buildings : " << CountBuildings() << " (mage guild: " << GetLevelMageGuild() << ")" << std::endl << "coast/has boat : " << ( HasSeaAccess() ? "yes" : "no" ) << " / " << ( HasBoatNearby() ? "yes" : "no" ) << std::endl << "is castle : " << ( isCastle() ? "yes" : "no" ) << " (" << getBuildingValue() << ")" << std::endl << "army : " << _army.String() << std::endl; if ( hero != nullptr ) { os << "hero army : " << hero->GetArmy().String() << std::endl; } return os.str(); } int Castle::GetPowerModificator( std::string * strs ) const { int result = 0; if ( Race::NECR == _race && isBuild( BUILD_SPEC ) ) { const int mod = 2; result += mod; if ( strs ) { strs->append( GetStringBuilding( BUILD_SPEC, _race ) ); fheroes2::appendModifierToString( *strs, mod ); } } return result; } int Castle::GetMoraleModificator( std::string * strs ) const { int result = Morale::NORMAL; // and tavern if ( isBuild( BUILD_TAVERN ) ) { const int mod = 1; result += mod; if ( strs ) { strs->append( GetStringBuilding( BUILD_TAVERN, _race ) ); fheroes2::appendModifierToString( *strs, mod ); strs->append( "\n" ); } } // and barbarian coliseum if ( Race::BARB == _race && isBuild( BUILD_SPEC ) ) { const int mod = 2; result += mod; if ( strs ) { strs->append( GetStringBuilding( BUILD_SPEC, _race ) ); fheroes2::appendModifierToString( *strs, mod ); strs->append( "\n" ); } } return result; } int Castle::GetLuckModificator( std::string * strs ) const { int result = Luck::NORMAL; if ( Race::SORC == _race && isBuild( BUILD_SPEC ) ) { const int mod = 2; result += mod; if ( strs ) { strs->append( Castle::GetStringBuilding( BUILD_SPEC, _race ) ); fheroes2::appendModifierToString( *strs, mod ); strs->append( "\n" ); } } return result; } const Army & Castle::GetActualArmy() const { const Heroes * hero = world.GetHero( *this ); return hero ? hero->GetArmy() : _army; } Army & Castle::GetActualArmy() { Heroes * hero = world.GetHero( *this ); return hero ? hero->GetArmy() : _army; } double Castle::GetGarrisonStrength( const Heroes * attackingHero ) const { double totalStrength = 0; Heroes * hero = world.GetHero( *this ); // If there is a hero in the castle, then some of the garrison troops can join his army if // there is a place for them. Castle bonuses are applied to the resulting combined army. if ( hero ) { Army garrisonArmy; garrisonArmy.Assign( _army ); Army combinedArmy( hero ); combinedArmy.Assign( hero->GetArmy() ); combinedArmy.ArrangeForCastleDefense( garrisonArmy ); totalStrength += combinedArmy.GetStrength(); } // Otherwise just use the garrison army strength. Castle bonuses are also applied. else { totalStrength += _army.GetStrength(); } // Add castle bonuses if there are any troops defending the castle if ( isCastle() && totalStrength > 0.1 ) { const Battle::Tower tower( *this, Battle::TowerType::TWR_CENTER, 0 ); const double towerStr = tower.GetStrengthWithBonus( tower.GetAttackBonus(), 0 ); totalStrength += towerStr; if ( isBuild( BUILD_LEFTTURRET ) ) { totalStrength += towerStr / 2; } if ( isBuild( BUILD_RIGHTTURRET ) ) { totalStrength += towerStr / 2; } if ( attackingHero && !attackingHero->HasSecondarySkill( Skill::Secondary::BALLISTICS ) && attackingHero->GetArmy().isMeleeDominantArmy() ) { // Heavy penalty if the attacking hero does not have a ballistic skill, and his army is based on melee infantry totalStrength *= isBuild( BUILD_MOAT ) ? 1.45 : 1.25; } else { totalStrength *= isBuild( BUILD_MOAT ) ? 1.2 : 1.15; } } return totalStrength; } bool Castle::AllowBuyBoat( const bool checkPayment ) const { if ( !isBuild( BUILD_SHIPYARD ) ) { return false; } if ( checkPayment && !GetKingdom().AllowPayment( PaymentConditions::BuyBoat() ) ) { return false; } if ( HasBoatNearby() ) { return false; } return getTileIndexToPlaceBoat() >= 0; } bool Castle::BuyBoat() const { if ( !AllowBuyBoat( true ) ) { return false; } // If this assertion blows up then you didn't even check conditions to build a shipyard! assert( HasSeaAccess() ); const int32_t index = getTileIndexToPlaceBoat(); if ( index < 0 ) { return false; } if ( isControlHuman() ) { AudioManager::PlaySound( M82::BUILDTWN ); } Kingdom & kingdom = GetKingdom(); kingdom.OddFundsResource( PaymentConditions::BuyBoat() ); world.getTile( index ).setBoat( Direction::RIGHT, kingdom.GetColor() ); return true; } void Castle::setName( const std::set> & usedNames ) { assert( _name.empty() ); std::vector shuffledCastleNames( defaultCastleNames.begin(), defaultCastleNames.end() ); Rand::Shuffle( shuffledCastleNames ); for ( const char * originalName : shuffledCastleNames ) { const char * translatedCastleName = _( originalName ); if ( usedNames.count( translatedCastleName ) < 1 ) { _name = translatedCastleName; return; } } // How is it possible that we're out of castle names? assert( 0 ); } int Castle::GetControl() const { // Neutral castles & towns are always controlled by AI return ( GetColor() & Color::ALL ) ? GetKingdom().GetControl() : CONTROL_AI; } uint32_t Castle::GetGrownWell() { return GameStatic::GetCastleGrownWell(); } uint32_t Castle::GetGrownWel2() { return GameStatic::GetCastleGrownWel2(); } uint32_t Castle::GetGrownWeekOf() { return GameStatic::GetCastleGrownWeekOf(); } uint32_t Castle::GetGrownMonthOf() { return GameStatic::GetCastleGrownMonthOf(); } void Castle::Scout() const { Maps::ClearFog( GetIndex(), GameStatic::getFogDiscoveryDistance( GameStatic::FogDiscoveryType::CASTLE ), GetColor() ); } void Castle::_joinRNDArmy() { const uint32_t timeModifier = world.CountDay() / 10; const uint32_t reinforcementQuality = Rand::Get( 1, 15 ) + timeModifier; uint32_t count = timeModifier / 2; uint32_t dwellingType = DWELLING_MONSTER1; if ( reinforcementQuality > 15 ) { dwellingType = DWELLING_MONSTER5; count += 1; } else if ( reinforcementQuality > 13 ) { dwellingType = DWELLING_MONSTER4; count += Rand::Get( 1, 3 ); } else if ( reinforcementQuality > 10 ) { dwellingType = DWELLING_MONSTER3; count += Rand::Get( 3, 5 ); } else if ( reinforcementQuality > 5 ) { dwellingType = DWELLING_MONSTER2; count += Rand::Get( 5, 7 ); } else { count += Rand::Get( 8, 15 ); } _army.JoinTroop( Monster( _race, dwellingType ), count, false ); } void Castle::ActionPreBattle() { if ( isControlAI() ) { AI::Planner::CastlePreBattle( *this ); return; } Heroes * hero = world.GetHero( *this ); if ( hero == nullptr ) { return; } hero->GetArmy().ArrangeForCastleDefense( _army ); } void Castle::ActionAfterBattle( const bool attackerWins ) { if ( attackerWins ) { _army.Clean(); ResetModes( CUSTOM_ARMY ); } } Castle * VecCastles::GetFirstCastle() const { const_iterator iter = std::find_if( begin(), end(), []( const Castle * castle ) { return castle->isCastle(); } ); if ( iter == end() ) { return nullptr; } return *iter; } AllCastles::AllCastles() { _castles.reserve( maximumCastles ); } void AllCastles::AddCastle( std::unique_ptr && castle ) { assert( castle ); const fheroes2::Point & center = castle->GetCenter(); _castles.emplace_back( std::move( castle ) ); /* Register position of all castle elements on the map Castle element positions are: + +++++ +++++ ++X++ ++ ++ where X is the main castle position + are tiles that are considered part of the castle for the Get() method */ const size_t id = _castles.size() - 1; // Castles are added from top to bottom, from left to right. // Tiles containing castle ID cannot be overwritten. for ( int32_t y = -2; y <= 1; ++y ) { for ( int32_t x = -2; x <= 2; ++x ) { if ( y == 1 && x == 0 ) { // Do not mark a tile below castle's entrance as castle. continue; } if ( const auto [dummy, inserted] = _castleTiles.try_emplace( center + fheroes2::Point( x, y ), id ); !inserted ) { DEBUG_LOG( DBG_GAME, DBG_INFO, "Tile [" << center.x + x << ", " << center.y + y << "] is occupied by another castle" ) } } } if ( const auto [dummy, inserted] = _castleTiles.try_emplace( center + fheroes2::Point( 0, -3 ), id ); !inserted ) { DEBUG_LOG( DBG_GAME, DBG_INFO, "Tile [" << center.x << ", " << center.y - 3 << "] is occupied by another castle" ) } } Castle * AllCastles::Get( const fheroes2::Point & position ) const { auto iter = _castleTiles.find( position ); if ( iter == _castleTiles.end() ) { return nullptr; } assert( iter->second < _castles.size() && _castles[iter->second] ); return _castles[iter->second].get(); } void AllCastles::Scout( const int colors ) const { for ( const Castle * castle : *this ) { assert( castle != nullptr ); if ( !( castle->GetColor() & colors ) ) { continue; } castle->Scout(); } } void AllCastles::NewDay() const { std::for_each( begin(), end(), []( Castle * castle ) { assert( castle != nullptr ); castle->ActionNewDay(); } ); } void AllCastles::NewWeek() const { std::for_each( begin(), end(), []( Castle * castle ) { assert( castle != nullptr ); castle->ActionNewWeek(); } ); } void AllCastles::NewMonth() const { std::for_each( begin(), end(), []( const Castle * castle ) { assert( castle != nullptr ); castle->ActionNewMonth(); } ); } OStreamBase & operator<<( OStreamBase & stream, const Castle & castle ) { const ColorBase & color = castle; stream << static_cast( castle ) << castle.modes << castle._race << castle._constructedBuildings << castle._disabledBuildings << castle._captain << color << castle._name << castle._mageGuild; stream.put32( static_cast( castle._dwelling.size() ) ); for ( const uint32_t _dwelling : castle._dwelling ) { stream << _dwelling; } return stream << castle._army; } IStreamBase & operator>>( IStreamBase & stream, Castle & castle ) { stream >> static_cast( castle ) >> castle.modes >> castle._race >> castle._constructedBuildings; static_assert( LAST_SUPPORTED_FORMAT_VERSION < FORMAT_VERSION_1101_RELEASE, "Remove the logic below." ); if ( Game::GetVersionOfCurrentSaveFile() < FORMAT_VERSION_1101_RELEASE ) { if ( !castle.Modes( Castle::UNUSED_ALLOW_CASTLE_CONSTRUCTION ) ) { castle._disabledBuildings = BUILD_CASTLE; } } else { stream >> castle._disabledBuildings; } ColorBase & color = castle; stream >> castle._captain >> color >> castle._name >> castle._mageGuild; if ( const uint32_t size = stream.get32(); castle._dwelling.size() != size ) { // Most likely the save file is corrupted. stream.setFail(); castle._dwelling = { 0 }; } else { for ( uint32_t & _dwelling : castle._dwelling ) { stream >> _dwelling; } } stream >> castle._army; castle._army.SetCommander( &castle._captain ); return stream; } OStreamBase & operator<<( OStreamBase & stream, const VecCastles & castles ) { stream.put32( static_cast( castles.size() ) ); std::for_each( castles.begin(), castles.end(), [&stream]( const Castle * castle ) { assert( castle != nullptr ); stream << castle->GetIndex(); } ); return stream; } IStreamBase & operator>>( IStreamBase & stream, VecCastles & castles ) { const uint32_t size = stream.get32(); castles.clear(); castles.reserve( size ); for ( uint32_t i = 0; i < size; ++i ) { int32_t index{ -1 }; stream >> index; Castle * castle = world.getCastleEntrance( Maps::GetPoint( index ) ); if ( castle == nullptr ) { // Most likely the save file is corrupted. stream.setFail(); continue; } castles.push_back( castle ); } return stream; } OStreamBase & operator<<( OStreamBase & stream, const AllCastles & castles ) { stream.put32( static_cast( castles.Size() ) ); for ( const Castle * castle : castles ) { stream << *castle; } return stream; } IStreamBase & operator>>( IStreamBase & stream, AllCastles & castles ) { const uint32_t size = stream.get32(); castles.Clear(); for ( uint32_t i = 0; i < size; ++i ) { auto castle = std::make_unique(); stream >> *castle; castles.AddCastle( std::move( castle ) ); } return stream; } std::string Castle::GetDescriptionBuilding( const uint32_t buildingType ) const { std::string res = fheroes2::getBuildingDescription( GetRace(), static_cast( buildingType ) ); switch ( buildingType ) { case BUILD_WELL: StringReplace( res, "%{count}", GetGrownWell() ); break; case BUILD_WEL2: StringReplace( res, "%{count}", GetGrownWel2() ); break; case BUILD_CASTLE: { StringReplace( res, "%{count}", ProfitConditions::FromBuilding( BUILD_CASTLE, _race ).gold ); if ( isBuild( BUILD_CASTLE ) ) { res.append( "\n\n" ); res.append( Battle::Tower::GetInfo( *this ) ); } if ( isBuild( BUILD_MOAT ) ) { res.append( "\n\n" ); res.append( Battle::Board::GetMoatInfo() ); } break; } case BUILD_SPEC: case BUILD_STATUE: { const Funds profit = ProfitConditions::FromBuilding( buildingType, GetRace() ); StringReplace( res, "%{count}", profit.gold ); break; } default: break; } return res; } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle.h000066400000000000000000000414241476115357100213750ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include #include #include #include #include "army.h" #include "bitmodes.h" #include "captain.h" #include "color.h" #include "mageguild.h" #include "math_base.h" #include "monster.h" #include "players.h" #include "position.h" #include "race.h" class IStreamBase; class OStreamBase; class HeroBase; class Heroes; class Troop; struct Funds; namespace fheroes2 { class RandomMonsterAnimation; class Image; } namespace Maps::Map_Format { struct CastleMetadata; } enum BuildingType : uint32_t { BUILD_NOTHING = 0x00000000, BUILD_THIEVESGUILD = 0x00000001, BUILD_TAVERN = 0x00000002, BUILD_SHIPYARD = 0x00000004, BUILD_WELL = 0x00000008, BUILD_STATUE = 0x00000010, BUILD_LEFTTURRET = 0x00000020, BUILD_RIGHTTURRET = 0x00000040, BUILD_MARKETPLACE = 0x00000080, // Farm, Garbage Heap, Crystal Garden, Waterfall, Orchard, Skull Pile BUILD_WEL2 = 0x00000100, BUILD_MOAT = 0x00000200, // Fortifications, Coliseum, Rainbow, Dungeon, Library, Storm BUILD_SPEC = 0x00000400, BUILD_CASTLE = 0x00000800, BUILD_CAPTAIN = 0x00001000, BUILD_SHRINE = 0x00002000, BUILD_MAGEGUILD1 = 0x00004000, BUILD_MAGEGUILD2 = 0x00008000, BUILD_MAGEGUILD3 = 0x00010000, BUILD_MAGEGUILD4 = 0x00020000, BUILD_MAGEGUILD5 = 0x00040000, BUILD_MAGEGUILD = BUILD_MAGEGUILD1 | BUILD_MAGEGUILD2 | BUILD_MAGEGUILD3 | BUILD_MAGEGUILD4 | BUILD_MAGEGUILD5, BUILD_TENT = 0x00080000, DWELLING_MONSTER1 = 0x00100000, DWELLING_MONSTER2 = 0x00200000, DWELLING_MONSTER3 = 0x00400000, DWELLING_MONSTER4 = 0x00800000, DWELLING_MONSTER5 = 0x01000000, DWELLING_MONSTER6 = 0x02000000, DWELLING_MONSTERS = DWELLING_MONSTER1 | DWELLING_MONSTER2 | DWELLING_MONSTER3 | DWELLING_MONSTER4 | DWELLING_MONSTER5 | DWELLING_MONSTER6, DWELLING_UPGRADE2 = 0x04000000, DWELLING_UPGRADE3 = 0x08000000, DWELLING_UPGRADE4 = 0x10000000, DWELLING_UPGRADE5 = 0x20000000, DWELLING_UPGRADE6 = 0x40000000, // Black Dragons DWELLING_UPGRADE7 = 0x80000000, DWELLING_UPGRADES = DWELLING_UPGRADE2 | DWELLING_UPGRADE3 | DWELLING_UPGRADE4 | DWELLING_UPGRADE5 | DWELLING_UPGRADE6 | DWELLING_UPGRADE7 }; enum class BuildingStatus : int32_t { UNKNOWN_COND, ALLOW_BUILD, NOT_TODAY, ALREADY_BUILT, NEED_CASTLE, BUILD_DISABLE, SHIPYARD_NOT_ALLOWED, UNKNOWN_UPGRADE, REQUIRES_BUILD, LACK_RESOURCES }; class Castle final : public MapPosition, public BitModes, public ColorBase, public Control { public: // Maximum number of creature dwellings that can be built in a castle static constexpr int maxNumOfDwellings{ 6 }; enum : uint32_t { UNUSED_ALLOW_CASTLE_CONSTRUCTION = ( 1 << 1 ), CUSTOM_ARMY = ( 1 << 2 ), ALLOW_TO_BUILD_TODAY = ( 1 << 3 ) }; enum class CastleDialogReturnValue : int { DoNothing, Close, // Close the dialog. NextCastle, // Open main dialog of the next castle. PreviousCastle, // Open main dialog of the previous castle. NextCostructionWindow, // Open construction dialog of the next castle. PreviousCostructionWindow // Open construction dialog of the previous castle. }; Castle() = default; Castle( const int32_t posX, const int32_t posY, int race ); Castle( const Castle & ) = delete; ~Castle() override = default; Castle & operator=( const Castle & ) = delete; void LoadFromMP2( const std::vector & data ); void loadFromResurrectionMap( const Maps::Map_Format::CastleMetadata & metadata ); Captain & GetCaptain() { return _captain; } const Captain & GetCaptain() const { return _captain; } bool isCastle() const { return ( _constructedBuildings & BUILD_CASTLE ) != 0; } bool HasSeaAccess() const; bool HasBoatNearby() const; // Returns a tile ID where it is possible to place a boat or -1 if it is not. int32_t getTileIndexToPlaceBoat() const; bool AllowBuyHero( std::string * msg = nullptr ) const; bool isPosition( const fheroes2::Point & pt ) const override; bool isNecromancyShrineBuild() const { return _race == Race::NECR && ( BUILD_SHRINE & _constructedBuildings ); } uint32_t CountBuildings() const; Heroes * RecruitHero( Heroes * hero ); Heroes * GetHero() const; int GetRace() const { return _race; } const std::string & GetName() const { return _name; } // This method must be called only at the time of map loading and only for castles with empty names. void setName( const std::set> & usedNames ); int GetControl() const override; int GetLevelMageGuild() const; const MageGuild & GetMageGuild() const { return _mageGuild; } bool HaveLibraryCapability() const { return _race == Race::WZRD; } bool isLibraryBuild() const { return _race == Race::WZRD && isBuild( BUILD_SPEC ); } void MageGuildEducateHero( HeroBase & hero ) const { _mageGuild.educateHero( hero, GetLevelMageGuild(), isLibraryBuild() ); } bool isFortificationBuilt() const { return _race == Race::KNGT && isBuild( BUILD_SPEC ); } const Army & GetArmy() const { return _army; } Army & GetArmy() { return _army; } const Army & GetActualArmy() const; Army & GetActualArmy(); // Returns current monsters count in dwelling. uint32_t getMonstersInDwelling( const uint32_t buildingType ) const; // Returns the garrison strength estimation calculated as if this castle had really been attacked, including // an estimate of the strength of the combined army consisting of the garrison and the guest hero's troops // (if present), castle-specific bonuses from moat, towers and so on, relative to the attacking hero's abilities // (if the 'attackingHero' is not 'nullptr'). See the implementation for details. double GetGarrisonStrength( const Heroes * attackingHero ) const; double GetGarrisonStrength( const Heroes & attackingHero ) const { return GetGarrisonStrength( &attackingHero ); } // Returns the correct dwelling type available in the castle. BUILD_NOTHING is returned if this is not a dwelling. uint32_t GetActualDwelling( const uint32_t buildId ) const; // Returns true in case of successful recruitment. bool RecruitMonster( const Troop & troop, bool showDialog = true ); uint32_t getRecruitLimit( const Monster & monster, const Funds & budget ) const; int getBuildingValue() const; // Used only for AI. double getArmyRecruitmentValue() const; double getVisitValue( const Heroes & hero ) const; void ChangeColor( const int newColor ); void ActionNewDay(); void ActionNewWeek(); void ActionNewMonth() const { // Do nothing. } void ActionPreBattle(); void ActionAfterBattle( const bool attackerWins ); void DrawImageCastle( const fheroes2::Point & pt ) const; CastleDialogReturnValue OpenDialog( const bool openConstructionWindow, const bool fade, const bool renderBackgroundDialog ); int GetAttackModificator( const std::string * /* unused */ ) const { return 0; } int GetDefenseModificator( const std::string * /* unused */ ) const { return 0; } int GetPowerModificator( std::string * strs ) const; int GetKnowledgeModificator( const std::string * /* unused */ ) const { return 0; } int GetMoraleModificator( std::string * strs ) const; int GetLuckModificator( std::string * strs ) const; bool AllowBuyBuilding( const uint32_t buildingType ) const { return BuildingStatus::ALLOW_BUILD == CheckBuyBuilding( buildingType ); } bool isBuild( const uint32_t buildingType ) const { return ( _constructedBuildings & buildingType ) != 0; } bool BuyBuilding( const uint32_t buildingType ); BuildingStatus CheckBuyBuilding( const uint32_t build ) const; static BuildingStatus GetAllBuildingStatus( const Castle & castle ); bool AllowBuyBoat( const bool checkPayment ) const; bool BuyBoat() const; void Scout() const; std::string GetStringBuilding( const uint32_t buildingType ) const { return GetStringBuilding( buildingType, _race ); } std::string GetDescriptionBuilding( const uint32_t buildingType ) const; static const char * GetStringBuilding( const uint32_t buildingType, const int race ); // Get building ICN ID for given race and building type. static int GetICNBuilding( const uint32_t buildingType, const int race ); static int GetICNBoat( const int race ); uint32_t GetUpgradeBuilding( const uint32_t buildingId ) const; static bool PredicateIsCastle( const Castle * castle ) { return castle && castle->isCastle(); } static bool PredicateIsTown( const Castle * castle ) { return castle && !castle->isCastle(); } static bool PredicateIsBuildBuilding( const Castle * castle, const uint32_t buildingType ) { return castle && castle->isBuild( buildingType ); } static uint32_t GetGrownWell(); static uint32_t GetGrownWel2(); static uint32_t GetGrownWeekOf(); static uint32_t GetGrownMonthOf(); std::string String() const; int DialogBuyHero( const Heroes * hero ) const; int DialogBuyCastle( const bool hasButtons = true ) const; Troops getAvailableArmy( Funds potentialBudget ) const; bool isBuildingDisabled( const uint32_t buildingType ) const { return ( _disabledBuildings & buildingType ) != 0; } private: enum class ConstructionDialogResult : int { DoNothing, NextConstructionWindow, // Open construction dialog for the next castle. PrevConstructionWindow, // Open construction dialog for the previous castle. Build, // Build something. RecruitHero // Recruit a hero. }; // Checks whether this particular building is currently built in the castle (unlike // the isBuild(), upgraded versions of the same building are not taken into account) bool _isExactBuildingBuilt( const uint32_t buildingToCheck ) const; uint32_t * _getDwelling( const uint32_t buildingType ); void _educateHeroes(); ConstructionDialogResult _openConstructionDialog( uint32_t & dwellingTobuild ); void _openTavern() const; void _openWell(); void _openMageGuild( const Heroes * hero ) const; void _joinRNDArmy(); void _postLoad(); void _wellRedrawAvailableMonsters( const uint32_t dwellingType, const bool restoreBackground, fheroes2::Image & background ) const; void _wellRedrawBackground( fheroes2::Image & background ) const; void _wellRedrawMonsterAnimation( const fheroes2::Rect & roi, std::array & monsterAnimInfo ) const; void _setDefaultBuildings(); // Recruit maximum monsters from the castle. Returns 'true' if the recruit was made. bool _recruitCastleMax( const Troops & currentCastleArmy ); friend OStreamBase & operator<<( OStreamBase & stream, const Castle & castle ); friend IStreamBase & operator>>( IStreamBase & stream, Castle & castle ); int _race{ Race::NONE }; uint32_t _constructedBuildings{ 0 }; uint32_t _disabledBuildings{ 0 }; Captain _captain{ *this }; std::string _name; MageGuild _mageGuild; std::array _dwelling{ 0 }; Army _army{ &_captain }; }; namespace CastleDialog { // Class used for fading animation class FadeBuilding { public: FadeBuilding() = default; void startFadeBuilding( const uint32_t building ) { _alpha = 0; _building = building; _isOnlyBoat = false; } void startFadeBoat() { _alpha = 0; _building = BUILD_SHIPYARD; _isOnlyBoat = true; } bool updateFadeAlpha(); bool isFadeDone() const { return _alpha == 255; } void stopFade() { _alpha = 255; _building = BUILD_NOTHING; _isOnlyBoat = false; } uint8_t getAlpha() const { return _alpha; } uint32_t getBuilding() const { return _building; } bool isOnlyBoat() const { return _isOnlyBoat; } private: uint32_t _building{ BUILD_NOTHING }; uint8_t _alpha{ 255 }; bool _isOnlyBoat{ false }; }; struct BuildingRenderInfo { BuildingRenderInfo( const BuildingType buildingType, const fheroes2::Rect & buildingRect ) : id( buildingType ) , coord( buildingRect ) { // Do nothing. } bool operator==( const uint32_t buildingType ) const { return buildingType == static_cast( id ); } BuildingType id; fheroes2::Rect coord; }; struct BuildingsRenderQueue : std::vector { BuildingsRenderQueue( const Castle & castle, const fheroes2::Point & top ); }; void redrawAllBuildings( const Castle & castle, const fheroes2::Point & offset, const BuildingsRenderQueue & buildings, const CastleDialog::FadeBuilding & alphaBuilding, const uint32_t animationIndex ); } struct VecCastles : public std::vector { VecCastles() = default; Castle * GetFirstCastle() const; }; class AllCastles { public: AllCastles(); AllCastles( const AllCastles & ) = delete; ~AllCastles() = default; AllCastles & operator=( const AllCastles & ) = delete; auto begin() const noexcept { return Iterator( _castles.begin() ); } auto end() const noexcept { return Iterator( _castles.end() ); } void Init() { Clear(); } void Clear() { _castles.clear(); _castleTiles.clear(); } size_t Size() const { return _castles.size(); } void AddCastle( std::unique_ptr && castle ); Castle * Get( const fheroes2::Point & position ) const; void Scout( const int colors ) const; void NewDay() const; void NewWeek() const; void NewMonth() const; template struct Iterator : public BaseIterator { explicit Iterator( BaseIterator && other ) noexcept : BaseIterator( std::move( other ) ) {} auto * operator*() const noexcept { return BaseIterator::operator*().get(); } }; private: std::vector> _castles; std::map _castleTiles; }; OStreamBase & operator<<( OStreamBase & stream, const VecCastles & castles ); IStreamBase & operator>>( IStreamBase & stream, VecCastles & castles ); OStreamBase & operator<<( OStreamBase & stream, const AllCastles & castles ); IStreamBase & operator>>( IStreamBase & stream, AllCastles & castles ); fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_building.cpp000066400000000000000000000546631476115357100236160ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include "agg_image.h" #include "castle.h" // IWYU pragma: associated #include "castle_building_info.h" #include "game_delays.h" #include "icn.h" #include "image.h" #include "maps_fileinfo.h" #include "math_base.h" #include "race.h" #include "screen.h" #include "settings.h" #include "ui_castle.h" namespace { int getTownIcnId( const int race ) { switch ( race ) { case Race::KNGT: return ICN::TOWNBKG0; case Race::BARB: return ICN::TOWNBKG1; case Race::SORC: return ICN::TOWNBKG2; case Race::WRLK: return ICN::TOWNBKG3; case Race::WZRD: return ICN::TOWNBKG4; case Race::NECR: return ICN::TOWNBKG5; default: // Have you added a new race? Add the logic for it! assert( 0 ); break; } return ICN::UNKNOWN; } fheroes2::Rect CastleGetMaxArea( const Castle & castle, const fheroes2::Point & top ) { const fheroes2::Sprite & townbkg = fheroes2::AGG::GetICN( getTownIcnId( castle.GetRace() ), 0 ); return { top.x, top.y, townbkg.width(), townbkg.height() }; } bool isBuildingConnectionNeeded( const Castle & castle, const uint32_t building ) { const int race = castle.GetRace(); if ( race == Race::BARB ) { if ( building & BUILD_MAGEGUILD ) { const int mageGuildLevel = castle.GetLevelMageGuild(); assert( mageGuildLevel > 0 ); return building == ( BUILD_MAGEGUILD1 << ( mageGuildLevel - 1 ) ); } if ( building == BUILD_THIEVESGUILD ) { return true; } } else if ( race == Race::NECR && building == BUILD_CAPTAIN ) { return true; } return false; } bool isBuildingFullyBuilt( const Castle & castle, const uint32_t building, const uint32_t buildingCurrentlyUnderConstruction ) { return castle.isBuild( building ) && building != buildingCurrentlyUnderConstruction; } void redrawBuildingConnection( const Castle & castle, const fheroes2::Point & position, const uint32_t building, const uint32_t buildingCurrentlyUnderConstruction, const uint8_t alpha = 255 ) { const fheroes2::Rect & roi = CastleGetMaxArea( castle, position ); const int race = castle.GetRace(); if ( race == Race::BARB ) { if ( building & BUILD_MAGEGUILD || building == BUILD_SPEC ) { if ( building & BUILD_MAGEGUILD && ( !castle.isBuild( building ) || !isBuildingFullyBuilt( castle, BUILD_SPEC, buildingCurrentlyUnderConstruction ) ) ) { return; } if ( building == BUILD_SPEC && ( !castle.isBuild( building ) || !isBuildingFullyBuilt( castle, BUILD_MAGEGUILD1, buildingCurrentlyUnderConstruction ) ) ) { return; } fheroes2::drawCastleDialogBuilding( ICN::TWNBEXT2, 0, castle, position, roi, alpha ); } if ( building == DWELLING_MONSTER3 || building == BUILD_THIEVESGUILD ) { if ( building == DWELLING_MONSTER3 && ( !castle.isBuild( building ) || !isBuildingFullyBuilt( castle, BUILD_THIEVESGUILD, buildingCurrentlyUnderConstruction ) ) ) { return; } if ( building == BUILD_THIEVESGUILD && ( !castle.isBuild( building ) || !isBuildingFullyBuilt( castle, DWELLING_MONSTER3, buildingCurrentlyUnderConstruction ) ) ) { return; } fheroes2::drawCastleDialogBuilding( ICN::TWNBEXT3, 0, castle, position, roi, alpha ); } } else if ( race == Race::NECR ) { if ( building == BUILD_CAPTAIN && ( !castle.isBuild( building ) || !isBuildingFullyBuilt( castle, BUILD_CASTLE, buildingCurrentlyUnderConstruction ) ) ) { return; } if ( building == BUILD_CASTLE && ( !castle.isBuild( building ) || !isBuildingFullyBuilt( castle, BUILD_CAPTAIN, buildingCurrentlyUnderConstruction ) ) ) { return; } fheroes2::drawCastleDialogBuilding( ICN::NECROMANCER_CASTLE_CAPTAIN_QUARTERS_BRIDGE, 0, castle, position, roi, alpha ); } } void redrawCastleBuilding( const Castle & castle, const fheroes2::Point & offset, const uint32_t building, const uint32_t frame, const uint32_t buildingCurrentlyUnderConstruction, const uint8_t alpha = 255 ) { if ( building == BUILD_TENT ) { // We don't need to draw a tent because it's on the background image. return; } if ( building & BUILD_MAGEGUILD ) { assert( ( [&castle, building]() { const int mageGuildLevel = castle.GetLevelMageGuild(); // If we are going to draw a Mage Guild building, then the castle should have a Mage Guild if ( mageGuildLevel < 1 ) { return false; } // The drawing of the Mage Guild building of the currently built level is allowed if ( building == ( BUILD_MAGEGUILD1 << ( mageGuildLevel - 1 ) ) ) { return true; } // If we are going to draw a Mage Guild building not of the currently built level, then the castle should have at least a Level 2 Mage Guild if ( mageGuildLevel < 2 ) { return false; } // The drawing of the Mage Guild building of the previous level is allowed as well, so that we can draw the "upgrade" animation if ( building == ( BUILD_MAGEGUILD1 << ( mageGuildLevel - 2 ) ) ) { return true; } // In all other cases, we should never draw this Mage Guild building return false; }() ) ); } const int race = castle.GetRace(); // For the Sorceress town when Statue and Crystal Garden are both built they have an extra image ICN::TWNSEXT1 // that should be used instead of separate Statue and Crystal Garden images render. // This extra image is rendered in redrawCastleBuildingExtended() function. // When Statue is constructing (fade-in animation) its render is also skipped here and is done in redrawCastleBuildingExtended(). if ( race == Race::SORC && ( building == BUILD_STATUE || building == BUILD_WEL2 ) && castle.isBuild( BUILD_STATUE ) && isBuildingFullyBuilt( castle, BUILD_WEL2, buildingCurrentlyUnderConstruction ) ) { return; } const uint32_t index = [building, race]() -> uint32_t { switch ( building ) { case BUILD_MAGEGUILD2: return ( race == Race::NECR ? 6 : 1 ); case BUILD_MAGEGUILD3: return ( race == Race::NECR ? 12 : 2 ); case BUILD_MAGEGUILD4: return ( race == Race::NECR ? 18 : 3 ); case BUILD_MAGEGUILD5: return ( race == Race::NECR ? 24 : 4 ); default: break; } return 0; }(); const int icn = Castle::GetICNBuilding( building, race ); if ( icn == ICN::UNKNOWN ) { // Have you added a new building? Add the logic for it! assert( 0 ); return; } const fheroes2::Rect roi = CastleGetMaxArea( castle, offset ); // Building main sprite. fheroes2::drawCastleDialogBuilding( icn, index, castle, offset, roi, alpha ); // Special case: Knight castle's flags are overlapped by Right Turret so we need to draw flags after drawing the Turret. const bool knightCastleCase = ( race == Race::KNGT && isBuildingFullyBuilt( castle, BUILD_RIGHTTURRET, buildingCurrentlyUnderConstruction ) && isBuildingFullyBuilt( castle, BUILD_CASTLE, buildingCurrentlyUnderConstruction ) ); if ( knightCastleCase && building == BUILD_CASTLE ) { // Do not draw flags. return; } // Building animation sprite. if ( const uint32_t index2 = ICN::getAnimatedIcnIndex( icn, index, frame ); index2 != 0 ) { fheroes2::drawCastleDialogBuilding( icn, index2, castle, offset, roi, alpha ); } if ( knightCastleCase && building == BUILD_RIGHTTURRET ) { // Draw Castle's flags after the Turret. const int castleIcn = Castle::GetICNBuilding( BUILD_CASTLE, race ); const uint32_t flagAnimFrame = ICN::getAnimatedIcnIndex( castleIcn, index, frame ); if ( flagAnimFrame > 0 ) { fheroes2::drawCastleDialogBuilding( castleIcn, flagAnimFrame, castle, offset, roi, alpha ); } } } void redrawCastleBuildingExtended( const Castle & castle, const fheroes2::Point & offset, const uint32_t building, const uint32_t frame, const uint32_t buildingCurrentlyUnderConstruction, const uint8_t alpha = 255 ) { if ( building == BUILD_TENT ) { // We don't need to draw a tent because it's on the background image. return; } const fheroes2::Rect roi = CastleGetMaxArea( castle, offset ); const int castleRace = castle.GetRace(); if ( building == BUILD_SHIPYARD ) { if ( castle.HasBoatNearby() ) { const int icn2 = Castle::GetICNBoat( castleRace ); fheroes2::drawCastleDialogBuilding( icn2, 0, castle, offset, roi, alpha ); if ( const uint32_t index2 = ICN::getAnimatedIcnIndex( icn2, 0, frame ) ) { fheroes2::drawCastleDialogBuilding( icn2, index2, castle, offset, roi, alpha ); } } else { const int icn = Castle::GetICNBuilding( building, castleRace ); if ( const uint32_t index2 = ICN::getAnimatedIcnIndex( icn, 0, frame ) ) { fheroes2::drawCastleDialogBuilding( icn, index2, castle, offset, roi, alpha ); } } } else if ( building == BUILD_STATUE ) { if ( castleRace == Race::SORC && buildingCurrentlyUnderConstruction == BUILD_STATUE && isBuildingFullyBuilt( castle, BUILD_WEL2, buildingCurrentlyUnderConstruction ) ) { // This is an extra case for the Sorceress castle Statue fade-in animation when Crystal Garden is already built. // It is done to swap render priority of these objects during this animation. const int gardenIcn = Castle::GetICNBuilding( BUILD_WEL2, castleRace ); fheroes2::drawCastleDialogBuilding( gardenIcn, 0, castle, offset, roi ); if ( const uint32_t index = ICN::getAnimatedIcnIndex( gardenIcn, 0, frame ) ) { fheroes2::drawCastleDialogBuilding( gardenIcn, index, castle, offset, roi ); } // Fade-in Statue. fheroes2::drawCastleDialogBuilding( ICN::TWNSEXT1, 0, castle, offset, roi, alpha ); } } else if ( building == BUILD_WEL2 ) { if ( castleRace == Race::SORC ) { if ( buildingCurrentlyUnderConstruction != BUILD_STATUE && isBuildingFullyBuilt( castle, BUILD_STATUE, buildingCurrentlyUnderConstruction ) ) { // This is an extra case for the Sorceress castle when Statue and Crystal Garden are built. // They are both rendered using ICN::TWNSEXT1. fheroes2::drawCastleDialogBuilding( ICN::TWNSEXT1, 0, castle, offset, roi, alpha ); if ( const uint32_t index2 = ICN::getAnimatedIcnIndex( ICN::TWNSEXT1, 0, frame ) ) { fheroes2::drawCastleDialogBuilding( ICN::TWNSEXT1, index2, castle, offset, roi, alpha ); } } } else if ( castleRace == Race::KNGT && !isBuildingFullyBuilt( castle, BUILD_CASTLE, buildingCurrentlyUnderConstruction ) ) { const fheroes2::Sprite & rightFarm = fheroes2::AGG::GetICN( ICN::KNIGHT_CASTLE_RIGHT_FARM, 0 ); const fheroes2::Sprite & leftFarm = fheroes2::AGG::GetICN( ICN::KNIGHT_CASTLE_LEFT_FARM, 0 ); fheroes2::drawCastleDialogBuilding( ICN::KNIGHT_CASTLE_LEFT_FARM, 0, castle, { offset.x + rightFarm.x() - leftFarm.width(), offset.y + rightFarm.y() }, roi, alpha ); } } else if ( building == BUILD_CAPTAIN ) { if ( castleRace == Race::BARB ) { if ( !isBuildingFullyBuilt( castle, BUILD_CASTLE, buildingCurrentlyUnderConstruction ) ) { const fheroes2::Sprite & rightCaptainQuarters = fheroes2::AGG::GetICN( ICN::TWNBCAPT, 0 ); const fheroes2::Sprite & leftCaptainQuarters = fheroes2::AGG::GetICN( ICN::BARBARIAN_CASTLE_CAPTAIN_QUARTERS_LEFT_SIDE, 0 ); fheroes2::drawCastleDialogBuilding( ICN::BARBARIAN_CASTLE_CAPTAIN_QUARTERS_LEFT_SIDE, 0, castle, { offset.x + rightCaptainQuarters.x() - leftCaptainQuarters.width(), offset.y + rightCaptainQuarters.y() }, roi, alpha ); } } else if ( castleRace == Race::SORC && !isBuildingFullyBuilt( castle, BUILD_CASTLE, buildingCurrentlyUnderConstruction ) ) { fheroes2::drawCastleDialogBuilding( ICN::SORCERESS_CASTLE_CAPTAIN_QUARTERS_LEFT_SIDE, 0, castle, offset, roi, alpha ); } } } void redrawCastleBuildings( const Castle & castle, const fheroes2::Point & offset, const CastleDialog::BuildingsRenderQueue & buildings, const CastleDialog::FadeBuilding & fadeBuilding, const uint32_t animationIndex ) { fheroes2::Display & display = fheroes2::Display::instance(); const int castleRace = castle.GetRace(); const fheroes2::Sprite & townbkg = fheroes2::AGG::GetICN( getTownIcnId( castleRace ), 0 ); const fheroes2::Rect max( offset.x, offset.y, townbkg.width(), townbkg.height() ); fheroes2::Copy( townbkg, 0, 0, display, offset.x, offset.y, max.width, max.height ); if ( castleRace == Race::BARB ) { // Render the river animation for the Barbarian castle. const fheroes2::Sprite & sprite0 = fheroes2::AGG::GetICN( ICN::TWNBEXT1, 1 + animationIndex % 5 ); fheroes2::Blit( sprite0, display, offset.x + sprite0.x(), offset.y + sprite0.y() ); } const uint32_t fadingInBuildingId = fadeBuilding.getBuilding(); // Bay animation. The Wizard's castle is "special": its "bay" is not actually a bay, but a river flowing through a gorge in the wastelands, which must be drawn // and animated, even if the castle itself is not located on the seashore. if ( castleRace == Race::WZRD || ( castle.HasSeaAccess() && ( !castle.isBuild( BUILD_SHIPYARD ) || fadingInBuildingId == BUILD_SHIPYARD ) ) ) { int bayIcnId = 0; const uint32_t bayExtraIndex = 1 + animationIndex % 5; switch ( castleRace ) { case Race::KNGT: bayIcnId = ICN::TWNKEXT0; break; case Race::BARB: bayIcnId = ICN::TWNBEXT0; break; case Race::SORC: bayIcnId = ICN::TWNSEXT0; break; case Race::NECR: bayIcnId = ICN::TWNNEXT0; break; case Race::WRLK: bayIcnId = ICN::TWNWEXT0; break; case Race::WZRD: bayIcnId = ICN::TWNZEXT0; break; default: // Did you add a new race? Add the logic for it! assert( 0 ); break; } fheroes2::drawCastleDialogBuilding( bayIcnId, 0, castle, offset, max ); fheroes2::drawCastleDialogBuilding( bayIcnId, bayExtraIndex, castle, offset, max ); } if ( fadingInBuildingId == BUILD_NOTHING ) { for ( const CastleDialog::BuildingRenderInfo & currentBuild : buildings ) { if ( !castle.isBuild( currentBuild.id ) ) { continue; } // Only draw this building if an upgraded version of this building has not yet been built const BuildingType upgradeForCurrentBuilding = fheroes2::getUpgradeForBuilding( castleRace, currentBuild.id ); if ( upgradeForCurrentBuilding != currentBuild.id && castle.isBuild( upgradeForCurrentBuilding ) ) { continue; } redrawCastleBuilding( castle, offset, currentBuild.id, animationIndex, fadingInBuildingId ); redrawCastleBuildingExtended( castle, offset, currentBuild.id, animationIndex, fadingInBuildingId ); if ( isBuildingConnectionNeeded( castle, currentBuild.id ) ) { redrawBuildingConnection( castle, offset, currentBuild.id, fadingInBuildingId ); } } return; } if ( std::find( buildings.cbegin(), buildings.cend(), fadingInBuildingId ) == buildings.cend() ) { // No building construction fade-in animation is needed. return; } const uint8_t fadeAlpha = fadeBuilding.getAlpha(); for ( const CastleDialog::BuildingRenderInfo & currentBuild : buildings ) { if ( !castle.isBuild( currentBuild.id ) ) { continue; } // Only draw this building if an upgraded version of this building has either not been built yet, or is still under construction at the moment const BuildingType upgradeForCurrentBuilding = fheroes2::getUpgradeForBuilding( castleRace, currentBuild.id ); if ( upgradeForCurrentBuilding != currentBuild.id && castle.isBuild( upgradeForCurrentBuilding ) && upgradeForCurrentBuilding != fadingInBuildingId ) { continue; } if ( currentBuild.id == fadingInBuildingId && !fadeBuilding.isOnlyBoat() ) { redrawCastleBuilding( castle, offset, currentBuild.id, animationIndex, fadingInBuildingId, fadeAlpha ); redrawCastleBuildingExtended( castle, offset, currentBuild.id, animationIndex, fadingInBuildingId, fadeAlpha ); if ( isBuildingConnectionNeeded( castle, currentBuild.id ) ) { redrawBuildingConnection( castle, offset, currentBuild.id, fadingInBuildingId, fadeAlpha ); } continue; } redrawCastleBuilding( castle, offset, currentBuild.id, animationIndex, fadingInBuildingId ); if ( currentBuild.id == BUILD_SHIPYARD && fadingInBuildingId == BUILD_SHIPYARD ) { redrawCastleBuildingExtended( castle, offset, currentBuild.id, animationIndex, fadingInBuildingId, fadeAlpha ); } else { redrawCastleBuildingExtended( castle, offset, currentBuild.id, animationIndex, fadingInBuildingId ); } if ( isBuildingConnectionNeeded( castle, currentBuild.id ) ) { redrawBuildingConnection( castle, offset, fadingInBuildingId, fadingInBuildingId, fadeAlpha ); redrawBuildingConnection( castle, offset, currentBuild.id, fadingInBuildingId ); } } } } CastleDialog::BuildingsRenderQueue::BuildingsRenderQueue( const Castle & castle, const fheroes2::Point & top ) { const int castleRace = castle.GetRace(); const std::vector ordersBuildings = fheroes2::getBuildingDrawingPriorities( castleRace, Settings::Get().getCurrentMapInfo().version ); for ( const BuildingType buildingId : ordersBuildings ) { emplace_back( buildingId, fheroes2::getCastleBuildingArea( castleRace, buildingId ) + top ); } } bool CastleDialog::FadeBuilding::updateFadeAlpha() { if ( _alpha < 255 && Game::validateAnimationDelay( Game::CASTLE_BUILD_DELAY ) ) { if ( _alpha < 255 - 15 ) { _alpha += 15; } else { _alpha = 255; } return true; } return false; } void CastleDialog::redrawAllBuildings( const Castle & castle, const fheroes2::Point & offset, const BuildingsRenderQueue & buildings, const CastleDialog::FadeBuilding & alphaBuilding, const uint32_t animationIndex ) { redrawCastleBuildings( castle, offset, buildings, alphaBuilding, animationIndex ); fheroes2::drawCastleName( castle, fheroes2::Display::instance(), offset ); } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_building_info.cpp000066400000000000000000001542721476115357100246260ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "castle_building_info.h" #include #include #include "maps_fileinfo.h" #include "race.h" #include "translations.h" namespace { fheroes2::Rect getKnightBuildingArea( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_THIEVESGUILD: return { 0, 130, 53, 63 }; case BUILD_TAVERN: return { 345, 114, 83, 62 }; case BUILD_SHIPYARD: return { 531, 211, 108, 45 }; case BUILD_WELL: return { 188, 214, 39, 42 }; case BUILD_STATUE: return { 478, 193, 46, 63 }; case BUILD_MARKETPLACE: return { 219, 138, 120, 30 }; case BUILD_WEL2: return { 241, 102, 141, 24 }; case BUILD_MOAT: return { 0, 146, 311, 30 }; case BUILD_SPEC: return { 0, 78, 251, 22 }; case BUILD_CASTLE: return { 0, 49, 286, 116 }; case BUILD_CAPTAIN: return { 293, 107, 59, 35 }; case BUILD_MAGEGUILD1: return { 397, 150, 84, 32 }; case BUILD_MAGEGUILD2: return { 397, 128, 84, 54 }; case BUILD_MAGEGUILD3: return { 397, 105, 84, 77 }; case BUILD_MAGEGUILD4: return { 397, 85, 84, 97 }; case BUILD_MAGEGUILD5: return { 397, 55, 84, 127 }; case BUILD_TENT: return { 69, 108, 67, 55 }; case DWELLING_MONSTER1: return { 192, 163, 69, 52 }; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return { 135, 149, 73, 32 }; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return { 240, 166, 91, 66 }; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return { 323, 174, 132, 73 }; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return { 0, 176, 152, 79 }; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return { 445, 50, 194, 157 }; case BUILD_LEFTTURRET: return { 7, 33, 0, 0 }; case BUILD_RIGHTTURRET: return { 134, 37, 0, 0 }; default: break; } // Did you add a new building but forgot to add its area? assert( 0 ); return {}; } fheroes2::Rect getBarbarianBuildingArea( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_THIEVESGUILD: return { 466, 94, 87, 47 }; case BUILD_TAVERN: return { 0, 161, 136, 90 }; case BUILD_SHIPYARD: return { 505, 199, 134, 56 }; case BUILD_WELL: return { 268, 189, 50, 58 }; case BUILD_STATUE: return { 463, 154, 38, 81 }; case BUILD_MARKETPLACE: return { 217, 166, 67, 43 }; case BUILD_WEL2: return { 240, 106, 73, 34 }; case BUILD_MOAT: return { 115, 138, 182, 42 }; case BUILD_SPEC: return { 210, 80, 197, 61 }; case BUILD_CASTLE: return { 0, 0, 214, 175 }; case BUILD_CAPTAIN: return { 206, 99, 46, 42 }; case BUILD_MAGEGUILD1: return { 348, 118, 50, 25 }; case BUILD_MAGEGUILD2: return { 348, 94, 50, 49 }; case BUILD_MAGEGUILD3: return { 348, 72, 50, 72 }; case BUILD_MAGEGUILD4: return { 348, 48, 50, 96 }; case BUILD_MAGEGUILD5: return { 348, 20, 50, 124 }; case BUILD_TENT: return { 44, 109, 87, 52 }; case DWELLING_MONSTER1: return { 290, 138, 58, 45 }; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return { 145, 195, 76, 52 }; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return { 557, 48, 83, 83 }; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return { 496, 136, 138, 64 }; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return { 318, 174, 131, 54 }; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return { 407, 0, 113, 106 }; case BUILD_LEFTTURRET: return { 5, 50, 0, 0 }; case BUILD_RIGHTTURRET: return { 118, 45, 0, 0 }; default: break; } // Did you add a new building but forgot to add its area? assert( 0 ); return {}; } fheroes2::Rect getSorceressBuildingArea( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_THIEVESGUILD: return { 423, 167, 87, 50 }; case BUILD_TAVERN: return { 490, 141, 148, 91 }; case BUILD_SHIPYARD: return { 0, 208, 178, 48 }; case BUILD_WELL: return { 335, 205, 45, 29 }; case BUILD_STATUE: return { 152, 163, 28, 65 }; case BUILD_MARKETPLACE: return { 404, 122, 69, 45 }; case BUILD_WEL2: return { 131, 185, 71, 53 }; case BUILD_MOAT: return { 0, 171, 272, 23 }; case BUILD_SPEC: return { 152, 0, 236, 84 }; case BUILD_CASTLE: return { 0, 0, 201, 179 }; case BUILD_CAPTAIN: return { 223, 122, 37, 52 }; case BUILD_MAGEGUILD1: return { 280, 21, 60, 143 }; case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return { 280, 0, 60, 164 }; case BUILD_TENT: return { 104, 130, 59, 42 }; case DWELLING_MONSTER1: return { 472, 59, 111, 92 }; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return { 338, 146, 93, 61 }; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return { 51, 164, 106, 40 }; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return { 198, 178, 143, 71 }; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return { 263, 226, 296, 30 }; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return { 179, 0, 84, 119 }; case BUILD_LEFTTURRET: return { 98, 99, 0, 0 }; case BUILD_RIGHTTURRET: return { 151, 98, 0, 0 }; default: break; } // Did you add a new building but forgot to add its area? assert( 0 ); return {}; } fheroes2::Rect getWarlockBuildingArea( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_THIEVESGUILD: return { 520, 103, 64, 54 }; case BUILD_TAVERN: return { 476, 96, 82, 55 }; case BUILD_SHIPYARD: return { 517, 200, 122, 56 }; case BUILD_WELL: return { 342, 205, 67, 42 }; case BUILD_STATUE: return { 478, 161, 37, 63 }; case BUILD_MARKETPLACE: return { 386, 171, 71, 40 }; case BUILD_WEL2: return { 60, 32, 63, 186 }; case BUILD_MOAT: return { 211, 166, 301, 21 }; case BUILD_SPEC: return { 0, 160, 59, 95 }; case BUILD_CASTLE: return { 241, 18, 181, 150 }; case BUILD_CAPTAIN: return { 418, 83, 53, 84 }; case BUILD_MAGEGUILD1: return { 590, 135, 49, 35 }; case BUILD_MAGEGUILD2: return { 590, 108, 49, 60 }; case BUILD_MAGEGUILD3: return { 590, 77, 49, 90 }; case BUILD_MAGEGUILD4: return { 590, 45, 49, 125 }; case BUILD_MAGEGUILD5: return { 590, 14, 49, 155 }; case BUILD_TENT: return { 298, 135, 72, 31 }; case DWELLING_MONSTER1: return { 0, 64, 48, 50 }; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return { 237, 168, 78, 79 }; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return { 492, 50, 53, 39 }; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return { 139, 163, 190, 83 }; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return { 82, 92, 178, 68 }; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return { 92, 0, 64, 255 }; case BUILD_LEFTTURRET: return { 311, 84, 0, 0 }; case BUILD_RIGHTTURRET: return { 359, 83, 0, 0 }; default: break; } // Did you add a new building but forgot to add its area? assert( 0 ); return {}; } fheroes2::Rect getWizardBuildingArea( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_THIEVESGUILD: return { 505, 50, 51, 49 }; case BUILD_TAVERN: return { 0, 149, 118, 76 }; case BUILD_SHIPYARD: return { 0, 206, 206, 49 }; case BUILD_WELL: return { 249, 139, 28, 33 }; case BUILD_STATUE: return { 464, 45, 24, 72 }; case BUILD_MARKETPLACE: return { 255, 163, 108, 53 }; case BUILD_WEL2: return { 237, 208, 137, 39 }; case BUILD_MOAT: return { 0, 90, 223, 14 }; case BUILD_SPEC: return { 297, 95, 109, 78 }; case BUILD_CASTLE: return { 0, 0, 200, 99 }; case BUILD_CAPTAIN: return { 210, 52, 28, 35 }; case BUILD_MAGEGUILD1: return { 585, 73, 54, 48 }; case BUILD_MAGEGUILD2: return { 585, 69, 54, 50 }; case BUILD_MAGEGUILD3: return { 585, 44, 54, 78 }; case BUILD_MAGEGUILD4: return { 585, 20, 54, 102 }; case BUILD_MAGEGUILD5: return { 585, 0, 54, 122 }; case BUILD_TENT: return { 58, 60, 49, 42 }; case DWELLING_MONSTER1: return { 467, 181, 38, 30 }; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return { 231, 68, 192, 36 }; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return { 152, 130, 96, 60 }; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return { 593, 184, 46, 31 }; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return { 411, 0, 49, 167 }; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return { 160, 0, 178, 67 }; case BUILD_LEFTTURRET: return { 30, 17, 0, 0 }; case BUILD_RIGHTTURRET: return { 127, 17, 0, 0 }; default: break; } // Did you add a new building but forgot to add its area? assert( 0 ); return {}; } fheroes2::Rect getNecromancerBuildingArea( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_THIEVESGUILD: return { 275, 124, 62, 77 }; case BUILD_SHRINE: return { 455, 39, 51, 103 }; case BUILD_SHIPYARD: return { 500, 220, 139, 36 }; case BUILD_WELL: return { 215, 213, 29, 39 }; case BUILD_STATUE: return { 365, 154, 41, 93 }; case BUILD_MARKETPLACE: return { 412, 193, 98, 61 }; case BUILD_WEL2: return { 263, 181, 90, 65 }; case BUILD_MOAT: return { 258, 171, 193, 19 }; case BUILD_SPEC: return { 0, 0, 640, 63 }; case BUILD_CASTLE: return { 289, 10, 134, 164 }; case BUILD_CAPTAIN: return { 441, 77, 22, 99 }; case BUILD_MAGEGUILD1: return { 565, 131, 73, 74 }; case BUILD_MAGEGUILD2: return { 568, 102, 62, 104 }; case BUILD_MAGEGUILD3: return { 570, 79, 56, 130 }; case BUILD_MAGEGUILD4: return { 570, 61, 60, 146 }; case BUILD_MAGEGUILD5: return { 570, 45, 61, 162 }; case BUILD_TENT: return { 333, 115, 47, 70 }; case DWELLING_MONSTER1: return { 396, 177, 71, 35 }; case DWELLING_MONSTER2: case DWELLING_UPGRADE2: return { 110, 174, 141, 45 }; case DWELLING_MONSTER3: case DWELLING_UPGRADE3: return { 0, 28, 241, 142 }; case DWELLING_MONSTER4: case DWELLING_UPGRADE4: return { 0, 107, 140, 129 }; case DWELLING_MONSTER5: case DWELLING_UPGRADE5: return { 221, 127, 66, 84 }; case DWELLING_MONSTER6: case DWELLING_UPGRADE6: case DWELLING_UPGRADE7: return { 464, 72, 105, 124 }; case BUILD_LEFTTURRET: return { 330, 47, 0, 0 }; case BUILD_RIGHTTURRET: return { 360, 46, 0, 0 }; default: break; } // Did you add a new building but forgot to add its area? assert( 0 ); return {}; } const char * getKnightBuildingName( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "Fortifications" ); case BUILD_WEL2: return _( "Farm" ); case DWELLING_MONSTER1: return _( "Thatched Hut" ); case DWELLING_MONSTER2: return _( "Archery Range" ); case DWELLING_UPGRADE2: return _( "Upg. Archery Range" ); case DWELLING_MONSTER3: return _( "Blacksmith" ); case DWELLING_UPGRADE3: return _( "Upg. Blacksmith" ); case DWELLING_MONSTER4: return _( "Armory" ); case DWELLING_UPGRADE4: return _( "Upg. Armory" ); case DWELLING_MONSTER5: return _( "Jousting Arena" ); case DWELLING_UPGRADE5: return _( "Upg. Jousting Arena" ); case DWELLING_MONSTER6: return _( "Cathedral" ); case DWELLING_UPGRADE6: return _( "Upg. Cathedral" ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getBarbarianBuildingName( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "Coliseum" ); case BUILD_WEL2: return _( "Garbage Heap" ); case DWELLING_MONSTER1: return _( "Hut" ); case DWELLING_MONSTER2: return _( "Stick Hut" ); case DWELLING_UPGRADE2: return _( "Upg. Stick Hut" ); case DWELLING_MONSTER3: return _( "Den" ); case DWELLING_MONSTER4: return _( "Adobe" ); case DWELLING_UPGRADE4: return _( "Upg. Adobe" ); case DWELLING_MONSTER5: return _( "Bridge" ); case DWELLING_UPGRADE5: return _( "Upg. Bridge" ); case DWELLING_MONSTER6: return _( "Pyramid" ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getSorceressBuildingName( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "Rainbow" ); case BUILD_WEL2: return _( "Crystal Garden" ); case DWELLING_MONSTER1: return _( "Treehouse" ); case DWELLING_MONSTER2: return _( "Cottage" ); case DWELLING_UPGRADE2: return _( "Upg. Cottage" ); case DWELLING_MONSTER3: return _( "Archery Range" ); case DWELLING_UPGRADE3: return _( "Upg. Archery Range" ); case DWELLING_MONSTER4: return _( "Stonehenge" ); case DWELLING_UPGRADE4: return _( "Upg. Stonehenge" ); case DWELLING_MONSTER5: return _( "Fenced Meadow" ); case DWELLING_MONSTER6: return _( "sorceress|Red Tower" ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getWarlockBuildingName( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "Dungeon" ); case BUILD_WEL2: return _( "Waterfall" ); case DWELLING_MONSTER1: return _( "Cave" ); case DWELLING_MONSTER2: return _( "Crypt" ); case DWELLING_MONSTER3: return _( "Nest" ); case DWELLING_MONSTER4: return _( "Maze" ); case DWELLING_UPGRADE4: return _( "Upg. Maze" ); case DWELLING_MONSTER5: return _( "Swamp" ); case DWELLING_MONSTER6: return _( "Green Tower" ); case DWELLING_UPGRADE6: return _( "warlock|Red Tower" ); case DWELLING_UPGRADE7: return _( "Black Tower" ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getWizardBuildingName( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "Library" ); case BUILD_WEL2: return _( "Orchard" ); case DWELLING_MONSTER1: return _( "Habitat" ); case DWELLING_MONSTER2: return _( "Pen" ); case DWELLING_MONSTER3: return _( "Foundry" ); case DWELLING_UPGRADE3: return _( "Upg. Foundry" ); case DWELLING_MONSTER4: return _( "Cliff Nest" ); case DWELLING_MONSTER5: return _( "Ivory Tower" ); case DWELLING_UPGRADE5: return _( "Upg. Ivory Tower" ); case DWELLING_MONSTER6: return _( "Cloud Castle" ); case DWELLING_UPGRADE6: return _( "Upg. Cloud Castle" ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getNecromancerBuildingName( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "Storm" ); case BUILD_WEL2: return _( "Skull Pile" ); case DWELLING_MONSTER1: return _( "Excavation" ); case DWELLING_MONSTER2: return _( "Graveyard" ); case DWELLING_UPGRADE2: return _( "Upg. Graveyard" ); case DWELLING_MONSTER3: return _( "Pyramid" ); case DWELLING_UPGRADE3: return _( "Upg. Pyramid" ); case DWELLING_MONSTER4: return _( "Mansion" ); case DWELLING_UPGRADE4: return _( "Upg. Mansion" ); case DWELLING_MONSTER5: return _( "Mausoleum" ); case DWELLING_UPGRADE5: return _( "Upg. Mausoleum" ); case DWELLING_MONSTER6: return _( "Laboratory" ); case BUILD_SHRINE: return _( "Shrine" ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getRandomBuildingName( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "Special" ); case BUILD_WEL2: return _( "Horde Building" ); case DWELLING_MONSTER1: return _( "Dwelling 1" ); case DWELLING_MONSTER2: return _( "Dwelling 2" ); case DWELLING_UPGRADE2: return _( "Upg. Dwelling 2" ); case DWELLING_MONSTER3: return _( "Dwelling 3" ); case DWELLING_UPGRADE3: return _( "Upg. Dwelling 3" ); case DWELLING_MONSTER4: return _( "Dwelling 4" ); case DWELLING_UPGRADE4: return _( "Upg. Dwelling 4" ); case DWELLING_MONSTER5: return _( "Dwelling 5" ); case DWELLING_UPGRADE5: return _( "Upg. Dwelling 5" ); case DWELLING_MONSTER6: return _( "Dwelling 6" ); case DWELLING_UPGRADE6: return _( "Upg. Dwelling 6" ); case DWELLING_UPGRADE7: return _( "2x Upg. Dwelling 6" ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getKnightBuildingDescription( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "The Fortifications increase the toughness of the walls, increasing the number of turns it takes to knock them down." ); case BUILD_WEL2: return _( "The Farm increases production of Peasants by %{count} per week." ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getBarbarianBuildingDescription( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "The Coliseum provides inspiring spectacles to defending troops, raising their morale by two during combat." ); case BUILD_WEL2: return _( "The Garbage Heap increases production of Goblins by %{count} per week." ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getSorceressBuildingDescription( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "The Rainbow increases the luck of the defending units by two." ); case BUILD_WEL2: return _( "The Crystal Garden increases production of Sprites by %{count} per week." ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getWarlockBuildingDescription( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "The Dungeon increases the income of the town by %{count} gold per day." ); case BUILD_WEL2: return _( "The Waterfall increases production of Centaurs by %{count} per week." ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getWizardBuildingDescription( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "The Library increases the number of spells in the Guild by one for each level of the guild." ); case BUILD_WEL2: return _( "The Orchard increases production of Halflings by %{count} per week." ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getNecromancerBuildingDescription( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "The Storm adds +2 to the power of spells of a defending spell caster." ); case BUILD_WEL2: return _( "The Skull Pile increases production of Skeletons by %{count} per week." ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } const char * getRandomBuildingDescription( const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_SPEC: return _( "The Special building gives a specific bonus to the chosen castle type." ); case BUILD_WEL2: return _( "The Horde Building increases the growth rate of the level 1 creatures by 8 per week." ); default: break; } // Did you add a new building? assert( 0 ); return nullptr; } } namespace fheroes2 { Rect getCastleBuildingArea( const int race, const BuildingType buildingId ) { if ( buildingId == BUILD_NOTHING ) { // Special case which we should ignore. return {}; } switch ( race ) { case Race::KNGT: return getKnightBuildingArea( buildingId ); case Race::BARB: return getBarbarianBuildingArea( buildingId ); case Race::SORC: return getSorceressBuildingArea( buildingId ); case Race::WRLK: return getWarlockBuildingArea( buildingId ); case Race::WZRD: return getWizardBuildingArea( buildingId ); case Race::NECR: return getNecromancerBuildingArea( buildingId ); default: break; } // Did you add a new castle? assert( 0 ); return {}; } const char * getBuildingName( const int race, const BuildingType buildingId ) { if ( buildingId == BUILD_NOTHING ) { // Special case which we should ignore. return ""; } // Check common buildings as they have the same name. switch ( buildingId ) { case BUILD_THIEVESGUILD: return _( "Thieves' Guild" ); case BUILD_TAVERN: return _( "Tavern" ); case BUILD_SHIPYARD: return _( "Shipyard" ); case BUILD_WELL: return _( "Well" ); case BUILD_STATUE: return _( "Statue" ); case BUILD_LEFTTURRET: return _( "Left Turret" ); case BUILD_RIGHTTURRET: return _( "Right Turret" ); case BUILD_MARKETPLACE: return _( "Marketplace" ); case BUILD_MOAT: return _( "Moat" ); case BUILD_CASTLE: return _( "Castle" ); case BUILD_TENT: return _( "Tent" ); case BUILD_CAPTAIN: return _( "Captain's Quarters" ); case BUILD_MAGEGUILD1: return _( "Mage Guild, Level 1" ); case BUILD_MAGEGUILD2: return _( "Mage Guild, Level 2" ); case BUILD_MAGEGUILD3: return _( "Mage Guild, Level 3" ); case BUILD_MAGEGUILD4: return _( "Mage Guild, Level 4" ); case BUILD_MAGEGUILD5: return _( "Mage Guild, Level 5" ); default: break; } switch ( race ) { case Race::KNGT: return getKnightBuildingName( buildingId ); case Race::BARB: return getBarbarianBuildingName( buildingId ); case Race::SORC: return getSorceressBuildingName( buildingId ); case Race::WRLK: return getWarlockBuildingName( buildingId ); case Race::WZRD: return getWizardBuildingName( buildingId ); case Race::NECR: return getNecromancerBuildingName( buildingId ); case Race::RAND: return getRandomBuildingName( buildingId ); default: break; } // Did you add a new castle? assert( 0 ); return nullptr; } const char * getBuildingDescription( const int race, const BuildingType buildingId ) { if ( buildingId == BUILD_NOTHING ) { // Special case which we should ignore. return ""; } switch ( buildingId ) { case BUILD_SHRINE: return _( "The Shrine increases the necromancy skill of all your necromancers by 10 percent." ); case BUILD_THIEVESGUILD: return _( "The Thieves' Guild provides information on enemy players. Thieves' Guilds can also provide scouting information on enemy towns. Additional Guilds provide more information." ); case BUILD_TAVERN: return _( "The Tavern increases morale for troops defending the castle." ); case BUILD_SHIPYARD: return _( "The Shipyard allows ships to be built." ); case BUILD_WELL: return _( "The Well increases the growth rate of all dwellings by %{count} creatures per week." ); case BUILD_STATUE: return _( "The Statue increases the town's income by %{count} gold per day." ); case BUILD_LEFTTURRET: return _( "The Left Turret provides extra firepower during castle combat." ); case BUILD_RIGHTTURRET: return _( "The Right Turret provides extra firepower during castle combat." ); case BUILD_MARKETPLACE: return _( "The Marketplace can be used to convert one type of resource into another. The more marketplaces you control, the better the exchange rate." ); case BUILD_MOAT: return _( "The Moat slows attacking units. Any unit entering the moat must end its turn there and becomes more vulnerable to attack." ); case BUILD_CASTLE: return _( "The Castle improves the town's defense and increases its income to %{count} gold per day." ); case BUILD_TENT: return _( "The Tent provides workers to build a castle, provided the materials and the gold are available." ); case BUILD_CAPTAIN: return _( "The Captain's Quarters provides a captain to assist in the castle's defense when no hero is present." ); case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return _( "The Mage Guild allows heroes to learn spells and replenish their spell points." ); default: break; } switch ( race ) { case Race::KNGT: return getKnightBuildingDescription( buildingId ); case Race::BARB: return getBarbarianBuildingDescription( buildingId ); case Race::SORC: return getSorceressBuildingDescription( buildingId ); case Race::WRLK: return getWarlockBuildingDescription( buildingId ); case Race::WZRD: return getWizardBuildingDescription( buildingId ); case Race::NECR: return getNecromancerBuildingDescription( buildingId ); case Race::RAND: return getRandomBuildingDescription( buildingId ); default: break; } // Did you add a new castle? assert( 0 ); return nullptr; } BuildingType getUpgradeForBuilding( const int race, const BuildingType buildingId ) { switch ( buildingId ) { case BUILD_TENT: return BUILD_CASTLE; case BUILD_MAGEGUILD1: return BUILD_MAGEGUILD2; case BUILD_MAGEGUILD2: return BUILD_MAGEGUILD3; case BUILD_MAGEGUILD3: return BUILD_MAGEGUILD4; case BUILD_MAGEGUILD4: return BUILD_MAGEGUILD5; default: break; } if ( race == Race::BARB ) { switch ( buildingId ) { case DWELLING_MONSTER2: return DWELLING_UPGRADE2; case DWELLING_MONSTER4: return DWELLING_UPGRADE4; case DWELLING_MONSTER5: return DWELLING_UPGRADE5; default: break; } } else if ( race == Race::KNGT ) { switch ( buildingId ) { case DWELLING_MONSTER2: return DWELLING_UPGRADE2; case DWELLING_MONSTER3: return DWELLING_UPGRADE3; case DWELLING_MONSTER4: return DWELLING_UPGRADE4; case DWELLING_MONSTER5: return DWELLING_UPGRADE5; case DWELLING_MONSTER6: return DWELLING_UPGRADE6; default: break; } } else if ( race == Race::NECR ) { switch ( buildingId ) { case DWELLING_MONSTER2: return DWELLING_UPGRADE2; case DWELLING_MONSTER3: return DWELLING_UPGRADE3; case DWELLING_MONSTER4: return DWELLING_UPGRADE4; case DWELLING_MONSTER5: return DWELLING_UPGRADE5; default: break; } } else if ( race == Race::SORC ) { switch ( buildingId ) { case DWELLING_MONSTER2: return DWELLING_UPGRADE2; case DWELLING_MONSTER3: return DWELLING_UPGRADE3; case DWELLING_MONSTER4: return DWELLING_UPGRADE4; default: break; } } else if ( race == Race::WRLK ) { switch ( buildingId ) { case DWELLING_MONSTER4: return DWELLING_UPGRADE4; case DWELLING_MONSTER6: return DWELLING_UPGRADE6; case DWELLING_UPGRADE6: return DWELLING_UPGRADE7; default: break; } } else if ( race == Race::WZRD ) { switch ( buildingId ) { case DWELLING_MONSTER3: return DWELLING_UPGRADE3; case DWELLING_MONSTER5: return DWELLING_UPGRADE5; case DWELLING_MONSTER6: return DWELLING_UPGRADE6; default: break; } } else if ( race == Race::RAND ) { switch ( buildingId ) { case DWELLING_MONSTER2: return DWELLING_UPGRADE2; case DWELLING_MONSTER3: return DWELLING_UPGRADE3; case DWELLING_MONSTER4: return DWELLING_UPGRADE4; case DWELLING_MONSTER5: return DWELLING_UPGRADE5; case DWELLING_MONSTER6: return DWELLING_UPGRADE6; case DWELLING_UPGRADE6: return DWELLING_UPGRADE7; default: break; } } return buildingId; } BuildingType getBuildingRequirement( const int race, const BuildingType building ) { uint32_t requirement = 0; switch ( building ) { case BUILD_SPEC: if ( race == Race::WZRD ) { requirement |= BUILD_MAGEGUILD1; } break; case DWELLING_MONSTER2: switch ( race ) { case Race::KNGT: case Race::BARB: case Race::WZRD: case Race::WRLK: case Race::NECR: requirement |= DWELLING_MONSTER1; break; case Race::SORC: requirement |= DWELLING_MONSTER1; requirement |= BUILD_TAVERN; break; default: break; } break; case DWELLING_MONSTER3: switch ( race ) { case Race::KNGT: requirement |= DWELLING_MONSTER1; requirement |= BUILD_WELL; break; case Race::BARB: case Race::SORC: case Race::WZRD: case Race::WRLK: case Race::NECR: requirement |= DWELLING_MONSTER1; break; default: break; } break; case DWELLING_MONSTER4: switch ( race ) { case Race::KNGT: requirement |= DWELLING_MONSTER1; requirement |= BUILD_TAVERN; break; case Race::BARB: requirement |= DWELLING_MONSTER1; break; case Race::SORC: requirement |= DWELLING_MONSTER3; requirement |= BUILD_MAGEGUILD1; break; case Race::WZRD: case Race::WRLK: requirement |= DWELLING_MONSTER2; break; case Race::NECR: requirement |= DWELLING_MONSTER3; requirement |= BUILD_THIEVESGUILD; break; default: break; } break; case DWELLING_MONSTER5: switch ( race ) { case Race::KNGT: case Race::BARB: requirement |= DWELLING_MONSTER2; requirement |= DWELLING_MONSTER3; requirement |= DWELLING_MONSTER4; break; case Race::SORC: requirement |= DWELLING_MONSTER4; break; case Race::WRLK: requirement |= DWELLING_MONSTER3; break; case Race::WZRD: requirement |= DWELLING_MONSTER3; requirement |= BUILD_MAGEGUILD1; break; case Race::NECR: requirement |= DWELLING_MONSTER2; requirement |= BUILD_MAGEGUILD1; break; default: break; } break; case DWELLING_MONSTER6: switch ( race ) { case Race::KNGT: requirement |= DWELLING_MONSTER2; requirement |= DWELLING_MONSTER3; requirement |= DWELLING_MONSTER4; break; case Race::BARB: case Race::SORC: case Race::NECR: requirement |= DWELLING_MONSTER5; break; case Race::WRLK: case Race::WZRD: requirement |= DWELLING_MONSTER4; requirement |= DWELLING_MONSTER5; break; default: break; } break; case DWELLING_UPGRADE2: switch ( race ) { case Race::KNGT: case Race::BARB: requirement |= DWELLING_MONSTER2; requirement |= DWELLING_MONSTER3; requirement |= DWELLING_MONSTER4; break; case Race::SORC: requirement |= DWELLING_MONSTER2; requirement |= BUILD_WELL; break; case Race::NECR: requirement |= DWELLING_MONSTER2; break; default: break; } break; case DWELLING_UPGRADE3: switch ( race ) { case Race::KNGT: requirement |= DWELLING_MONSTER2; requirement |= DWELLING_MONSTER3; requirement |= DWELLING_MONSTER4; break; case Race::SORC: requirement |= DWELLING_MONSTER3; requirement |= DWELLING_MONSTER4; break; case Race::WZRD: requirement |= DWELLING_MONSTER3; requirement |= BUILD_WELL; break; case Race::NECR: requirement |= DWELLING_MONSTER3; break; default: break; } break; case DWELLING_UPGRADE4: switch ( race ) { case Race::KNGT: case Race::BARB: requirement |= DWELLING_MONSTER2; requirement |= DWELLING_MONSTER3; requirement |= DWELLING_MONSTER4; break; case Race::SORC: case Race::WRLK: case Race::NECR: requirement |= DWELLING_MONSTER4; break; default: break; } break; case DWELLING_UPGRADE5: switch ( race ) { case Race::KNGT: case Race::BARB: requirement |= DWELLING_MONSTER5; break; case Race::WZRD: requirement |= BUILD_SPEC; requirement |= DWELLING_MONSTER5; break; case Race::NECR: requirement |= BUILD_MAGEGUILD2; requirement |= DWELLING_MONSTER5; break; default: break; } break; case DWELLING_UPGRADE6: switch ( race ) { case Race::KNGT: case Race::WRLK: case Race::WZRD: requirement |= DWELLING_MONSTER6; break; default: break; } break; case DWELLING_UPGRADE7: if ( race == Race::WRLK ) requirement |= DWELLING_UPGRADE6; break; default: break; } return static_cast( requirement ); } std::string getBuildingRequirementString( const int race, const BuildingType building ) { // prepare requirement build string std::string requirement; const uint32_t requirementBuildingIds = fheroes2::getBuildingRequirement( race, building ); const char sep = '\n'; for ( uint32_t itr = 0x00000001; itr; itr <<= 1 ) if ( requirementBuildingIds & itr ) { requirement.append( Castle::GetStringBuilding( itr, race ) ); requirement += sep; } // Remove the last separator. if ( !requirement.empty() ) { requirement.pop_back(); } return requirement; } int getIndexBuildingSprite( const BuildingType build ) { switch ( build ) { case DWELLING_MONSTER1: return 19; case DWELLING_MONSTER2: return 20; case DWELLING_MONSTER3: return 21; case DWELLING_MONSTER4: return 22; case DWELLING_MONSTER5: return 23; case DWELLING_MONSTER6: return 24; case DWELLING_UPGRADE2: return 25; case DWELLING_UPGRADE3: return 26; case DWELLING_UPGRADE4: return 27; case DWELLING_UPGRADE5: return 28; case DWELLING_UPGRADE6: return 29; case DWELLING_UPGRADE7: return 30; case BUILD_MAGEGUILD1: case BUILD_MAGEGUILD2: case BUILD_MAGEGUILD3: case BUILD_MAGEGUILD4: case BUILD_MAGEGUILD5: return 0; case BUILD_THIEVESGUILD: return 1; case BUILD_SHRINE: case BUILD_TAVERN: return 2; case BUILD_SHIPYARD: return 3; case BUILD_WELL: return 4; case BUILD_CASTLE: return 6; case BUILD_STATUE: return 7; case BUILD_LEFTTURRET: return 8; case BUILD_RIGHTTURRET: return 9; case BUILD_MARKETPLACE: return 10; case BUILD_WEL2: return 11; case BUILD_MOAT: return 12; case BUILD_SPEC: return 13; case BUILD_CAPTAIN: return 15; default: break; } return 0; } std::vector getBuildingDrawingPriorities( const int race, const GameVersion version ) { std::vector priorities; priorities.reserve( 32 ); switch ( race ) { case Race::KNGT: priorities.emplace_back( BUILD_TENT ); priorities.emplace_back( BUILD_WEL2 ); priorities.emplace_back( BUILD_CASTLE ); priorities.emplace_back( BUILD_SPEC ); priorities.emplace_back( BUILD_CAPTAIN ); priorities.emplace_back( BUILD_LEFTTURRET ); priorities.emplace_back( BUILD_RIGHTTURRET ); priorities.emplace_back( BUILD_MOAT ); priorities.emplace_back( BUILD_MARKETPLACE ); priorities.emplace_back( DWELLING_MONSTER2 ); priorities.emplace_back( DWELLING_UPGRADE2 ); priorities.emplace_back( BUILD_THIEVESGUILD ); priorities.emplace_back( BUILD_TAVERN ); priorities.emplace_back( BUILD_MAGEGUILD1 ); priorities.emplace_back( BUILD_MAGEGUILD2 ); priorities.emplace_back( BUILD_MAGEGUILD3 ); priorities.emplace_back( BUILD_MAGEGUILD4 ); priorities.emplace_back( BUILD_MAGEGUILD5 ); priorities.emplace_back( DWELLING_MONSTER5 ); priorities.emplace_back( DWELLING_UPGRADE5 ); priorities.emplace_back( DWELLING_MONSTER6 ); priorities.emplace_back( DWELLING_UPGRADE6 ); priorities.emplace_back( DWELLING_MONSTER1 ); priorities.emplace_back( DWELLING_MONSTER3 ); priorities.emplace_back( DWELLING_UPGRADE3 ); priorities.emplace_back( DWELLING_MONSTER4 ); priorities.emplace_back( DWELLING_UPGRADE4 ); priorities.emplace_back( BUILD_WELL ); priorities.emplace_back( BUILD_SHIPYARD ); priorities.emplace_back( BUILD_STATUE ); break; case Race::BARB: priorities.emplace_back( BUILD_SPEC ); priorities.emplace_back( BUILD_WEL2 ); priorities.emplace_back( DWELLING_MONSTER6 ); priorities.emplace_back( BUILD_MAGEGUILD1 ); priorities.emplace_back( BUILD_MAGEGUILD2 ); priorities.emplace_back( BUILD_MAGEGUILD3 ); priorities.emplace_back( BUILD_MAGEGUILD4 ); priorities.emplace_back( BUILD_MAGEGUILD5 ); priorities.emplace_back( BUILD_CAPTAIN ); priorities.emplace_back( BUILD_TENT ); priorities.emplace_back( BUILD_CASTLE ); priorities.emplace_back( BUILD_LEFTTURRET ); priorities.emplace_back( BUILD_RIGHTTURRET ); priorities.emplace_back( BUILD_MOAT ); priorities.emplace_back( DWELLING_MONSTER3 ); priorities.emplace_back( BUILD_THIEVESGUILD ); priorities.emplace_back( DWELLING_MONSTER1 ); priorities.emplace_back( BUILD_MARKETPLACE ); priorities.emplace_back( DWELLING_MONSTER2 ); priorities.emplace_back( DWELLING_UPGRADE2 ); priorities.emplace_back( BUILD_TAVERN ); priorities.emplace_back( DWELLING_MONSTER4 ); priorities.emplace_back( DWELLING_UPGRADE4 ); priorities.emplace_back( DWELLING_MONSTER5 ); priorities.emplace_back( DWELLING_UPGRADE5 ); priorities.emplace_back( BUILD_WELL ); priorities.emplace_back( BUILD_STATUE ); priorities.emplace_back( BUILD_SHIPYARD ); break; case Race::SORC: priorities.emplace_back( BUILD_SPEC ); priorities.emplace_back( DWELLING_MONSTER6 ); priorities.emplace_back( BUILD_MAGEGUILD1 ); priorities.emplace_back( BUILD_MAGEGUILD2 ); priorities.emplace_back( BUILD_MAGEGUILD3 ); priorities.emplace_back( BUILD_MAGEGUILD4 ); priorities.emplace_back( BUILD_MAGEGUILD5 ); priorities.emplace_back( BUILD_CAPTAIN ); priorities.emplace_back( BUILD_TENT ); priorities.emplace_back( BUILD_CASTLE ); priorities.emplace_back( BUILD_LEFTTURRET ); priorities.emplace_back( BUILD_RIGHTTURRET ); priorities.emplace_back( BUILD_MOAT ); priorities.emplace_back( DWELLING_MONSTER3 ); priorities.emplace_back( DWELLING_UPGRADE3 ); priorities.emplace_back( BUILD_SHIPYARD ); priorities.emplace_back( BUILD_MARKETPLACE ); priorities.emplace_back( DWELLING_MONSTER2 ); priorities.emplace_back( DWELLING_UPGRADE2 ); priorities.emplace_back( BUILD_THIEVESGUILD ); priorities.emplace_back( DWELLING_MONSTER1 ); priorities.emplace_back( BUILD_TAVERN ); priorities.emplace_back( BUILD_STATUE ); priorities.emplace_back( BUILD_WEL2 ); priorities.emplace_back( DWELLING_MONSTER4 ); priorities.emplace_back( DWELLING_UPGRADE4 ); priorities.emplace_back( BUILD_WELL ); priorities.emplace_back( DWELLING_MONSTER5 ); break; case Race::WRLK: priorities.emplace_back( DWELLING_MONSTER5 ); priorities.emplace_back( DWELLING_MONSTER3 ); priorities.emplace_back( BUILD_TENT ); priorities.emplace_back( BUILD_CASTLE ); priorities.emplace_back( BUILD_LEFTTURRET ); priorities.emplace_back( BUILD_RIGHTTURRET ); priorities.emplace_back( BUILD_MOAT ); priorities.emplace_back( BUILD_CAPTAIN ); priorities.emplace_back( BUILD_SHIPYARD ); priorities.emplace_back( BUILD_MAGEGUILD1 ); priorities.emplace_back( BUILD_MAGEGUILD2 ); priorities.emplace_back( BUILD_MAGEGUILD3 ); priorities.emplace_back( BUILD_MAGEGUILD4 ); priorities.emplace_back( BUILD_MAGEGUILD5 ); priorities.emplace_back( BUILD_TAVERN ); priorities.emplace_back( BUILD_THIEVESGUILD ); priorities.emplace_back( BUILD_MARKETPLACE ); priorities.emplace_back( BUILD_STATUE ); priorities.emplace_back( DWELLING_MONSTER1 ); priorities.emplace_back( BUILD_WEL2 ); priorities.emplace_back( BUILD_SPEC ); priorities.emplace_back( DWELLING_MONSTER4 ); priorities.emplace_back( DWELLING_UPGRADE4 ); priorities.emplace_back( DWELLING_MONSTER2 ); priorities.emplace_back( DWELLING_MONSTER6 ); priorities.emplace_back( DWELLING_UPGRADE6 ); priorities.emplace_back( DWELLING_UPGRADE7 ); priorities.emplace_back( BUILD_WELL ); break; case Race::WZRD: priorities.emplace_back( DWELLING_MONSTER6 ); priorities.emplace_back( DWELLING_UPGRADE6 ); priorities.emplace_back( BUILD_TENT ); priorities.emplace_back( BUILD_CASTLE ); priorities.emplace_back( BUILD_LEFTTURRET ); priorities.emplace_back( BUILD_RIGHTTURRET ); priorities.emplace_back( BUILD_MOAT ); priorities.emplace_back( BUILD_CAPTAIN ); priorities.emplace_back( DWELLING_MONSTER2 ); priorities.emplace_back( BUILD_THIEVESGUILD ); priorities.emplace_back( BUILD_TAVERN ); priorities.emplace_back( BUILD_SHIPYARD ); priorities.emplace_back( BUILD_WELL ); priorities.emplace_back( DWELLING_MONSTER3 ); priorities.emplace_back( DWELLING_UPGRADE3 ); priorities.emplace_back( DWELLING_MONSTER5 ); priorities.emplace_back( DWELLING_UPGRADE5 ); priorities.emplace_back( BUILD_MAGEGUILD1 ); priorities.emplace_back( BUILD_MAGEGUILD2 ); priorities.emplace_back( BUILD_MAGEGUILD3 ); priorities.emplace_back( BUILD_MAGEGUILD4 ); priorities.emplace_back( BUILD_MAGEGUILD5 ); priorities.emplace_back( BUILD_SPEC ); priorities.emplace_back( BUILD_STATUE ); priorities.emplace_back( DWELLING_MONSTER1 ); priorities.emplace_back( DWELLING_MONSTER4 ); priorities.emplace_back( BUILD_MARKETPLACE ); priorities.emplace_back( BUILD_WEL2 ); break; case Race::NECR: priorities.emplace_back( BUILD_SPEC ); if ( version == GameVersion::PRICE_OF_LOYALTY || version == GameVersion::RESURRECTION ) { priorities.emplace_back( BUILD_SHRINE ); } priorities.emplace_back( BUILD_TENT ); priorities.emplace_back( BUILD_CASTLE ); priorities.emplace_back( BUILD_LEFTTURRET ); priorities.emplace_back( BUILD_RIGHTTURRET ); priorities.emplace_back( BUILD_MOAT ); priorities.emplace_back( BUILD_CAPTAIN ); priorities.emplace_back( DWELLING_MONSTER6 ); priorities.emplace_back( DWELLING_MONSTER1 ); priorities.emplace_back( BUILD_THIEVESGUILD ); priorities.emplace_back( DWELLING_MONSTER3 ); priorities.emplace_back( DWELLING_UPGRADE3 ); priorities.emplace_back( DWELLING_MONSTER5 ); priorities.emplace_back( DWELLING_UPGRADE5 ); priorities.emplace_back( DWELLING_MONSTER2 ); priorities.emplace_back( DWELLING_UPGRADE2 ); priorities.emplace_back( DWELLING_MONSTER4 ); priorities.emplace_back( DWELLING_UPGRADE4 ); priorities.emplace_back( BUILD_MAGEGUILD1 ); priorities.emplace_back( BUILD_MAGEGUILD2 ); priorities.emplace_back( BUILD_MAGEGUILD3 ); priorities.emplace_back( BUILD_MAGEGUILD4 ); priorities.emplace_back( BUILD_MAGEGUILD5 ); priorities.emplace_back( BUILD_SHIPYARD ); priorities.emplace_back( BUILD_WEL2 ); priorities.emplace_back( BUILD_MARKETPLACE ); priorities.emplace_back( BUILD_STATUE ); priorities.emplace_back( BUILD_WELL ); break; default: // Did you add a new castle? assert( 0 ); break; } return priorities; } } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_building_info.h000066400000000000000000000045621476115357100242670ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "castle.h" #include "math_base.h" enum class GameVersion : int; namespace fheroes2 { Rect getCastleBuildingArea( const int race, const BuildingType buildingId ); const char * getBuildingName( const int race, const BuildingType buildingId ); const char * getBuildingDescription( const int race, const BuildingType buildingId ); // Returns the upgraded building ID for the given one or the input building if no upgrade is available. BuildingType getUpgradeForBuilding( const int race, const BuildingType buildingId ); BuildingType getBuildingRequirement( const int race, const BuildingType building ); std::string getBuildingRequirementString( const int race, const BuildingType building ); int getIndexBuildingSprite( const BuildingType build ); std::vector getBuildingDrawingPriorities( const int race, const GameVersion version ); } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_dialog.cpp000066400000000000000000001011501476115357100232400ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "army_bar.h" #include "army_troop.h" #include "audio.h" #include "audio_manager.h" #include "captain.h" #include "castle.h" // IWYU pragma: associated #include "castle_building_info.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "game.h" #include "game_delays.h" #include "game_hotkeys.h" #include "game_interface.h" #include "heroes.h" #include "heroes_base.h" #include "icn.h" #include "image.h" #include "interface_gamearea.h" #include "kingdom.h" #include "localevent.h" #include "m82.h" #include "math_base.h" #include "monster.h" #include "mus.h" #include "screen.h" #include "statusbar.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_castle.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_kingdom.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" namespace { BuildingType getPressedBuildingHotkey() { if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_1 ) ) { return DWELLING_MONSTER1; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_2 ) ) { return DWELLING_MONSTER2; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_3 ) ) { return DWELLING_MONSTER3; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_4 ) ) { return DWELLING_MONSTER4; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_5 ) ) { return DWELLING_MONSTER5; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_6 ) ) { return DWELLING_MONSTER6; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_MARKETPLACE ) ) { return BUILD_MARKETPLACE; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_WELL ) ) { return BUILD_WELL; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_MAGE_GUILD ) ) { return BUILD_MAGEGUILD; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_SHIPYARD ) ) { return BUILD_SHIPYARD; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_THIEVES_GUILD ) ) { return BUILD_THIEVESGUILD; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_TAVERN ) ) { return BUILD_TAVERN; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_CONSTRUCTION ) ) { return BUILD_CASTLE; } return BUILD_NOTHING; } std::string buildingStatusMessage( const int race, const uint32_t buildingId ) { // Check if building is a monster dwelling or its upgraded version if ( ( buildingId & DWELLING_MONSTERS ) == 0 && ( buildingId & DWELLING_UPGRADES ) == 0 ) { return fheroes2::getBuildingName( race, static_cast( buildingId ) ); } const Monster monster( race, buildingId ); std::string msgStatus = _( "Recruit %{name}" ); StringReplaceWithLowercase( msgStatus, "%{name}", monster.GetMultiName() ); return msgStatus; } void RedrawIcons( const Castle & castle, const Heroes * hero, const fheroes2::Point & pt ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::STRIP, 0 ), display, pt.x, pt.y + 256 ); if ( castle.isBuild( BUILD_CAPTAIN ) ) { const fheroes2::Sprite & captainImage = castle.GetCaptain().GetPortrait( PORT_BIG ); fheroes2::Copy( captainImage, 0, 0, display, pt.x + 5, pt.y + 262, captainImage.width(), captainImage.height() ); } else { const fheroes2::Sprite & crestImage = fheroes2::AGG::GetICN( ICN::CREST, Color::GetIndex( castle.GetColor() ) ); fheroes2::Copy( crestImage, 0, 0, display, pt.x + 5, pt.y + 262, crestImage.width(), crestImage.height() ); } if ( hero ) { hero->PortraitRedraw( pt.x + 5, pt.y + 361, PORT_BIG, display ); } else { const fheroes2::Sprite & heroImage = fheroes2::AGG::GetICN( ICN::STRIP, 3 ); const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( ICN::STRIP, 11 ); fheroes2::Copy( heroImage, 0, 0, display, pt.x + 5, pt.y + 361, heroImage.width(), heroImage.height() ); fheroes2::Copy( backgroundImage, 0, 0, display, pt.x + 112, pt.y + 361, backgroundImage.width(), backgroundImage.height() ); } } std::string getDateString() { std::string output( _( "Month: %{month}, Week: %{week}, Day: %{day}" ) ); StringReplace( output, "%{month}", world.GetMonth() ); StringReplace( output, "%{week}", world.GetWeek() ); StringReplace( output, "%{day}", world.GetDay() ); return output; } bool purchaseSpellBookIfNecessary( const Castle & castle, Heroes * hero ) { if ( hero == nullptr || hero->HaveSpellBook() ) { return false; } if ( hero->IsFullBagArtifacts() ) { fheroes2::showStandardTextMessage( hero->GetName(), _( "You must purchase a spell book to use the mage guild, but you currently have no room for a spell book. Try giving one of your artifacts to another hero." ), Dialog::OK ); return false; } return hero->BuySpellBook( &castle ); } void openHeroDialog( ArmyBar & topArmyBar, ArmyBar & bottomArmyBar, Heroes & hero ) { Game::SetUpdateSoundsOnFocusUpdate( false ); Game::OpenHeroesDialog( hero, false, false ); if ( topArmyBar.isValid() && topArmyBar.isSelected() ) { topArmyBar.ResetSelected(); } if ( bottomArmyBar.isValid() && bottomArmyBar.isSelected() ) { bottomArmyBar.ResetSelected(); } } void generateHeroImage( fheroes2::Image & image, Heroes * hero ) { assert( hero != nullptr ); if ( image.empty() ) { image.resize( 552, 105 ); image.reset(); } fheroes2::Blit( fheroes2::AGG::GetICN( ICN::STRIP, 0 ), 0, 100, image, 0, 0, 552, 107 ); const fheroes2::Sprite & port = hero->GetPortrait( PORT_BIG ); fheroes2::Copy( port, 0, 0, image, 5, 5, port.width(), port.height() ); ArmyBar armyBar( &hero->GetArmy(), false, false ); armyBar.setTableSize( { 5, 1 } ); armyBar.setRenderingOffset( { 112, 5 } ); armyBar.setInBetweenItemsOffset( { 6, 0 } ); armyBar.Redraw( image ); } } Castle::CastleDialogReturnValue Castle::OpenDialog( const bool openConstructionWindow, const bool fade, const bool renderBackgroundDialog ) { // Set the cursor image. This dialog does not require a cursor restorer. It is called from other dialogs that have the same cursor // or from the Game Area that will set the appropriate cursor after this dialog is closed. Cursor::Get().SetThemes( Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Rect dialogRoi; fheroes2::Rect dialogWithShadowRoi; std::unique_ptr background; std::unique_ptr restorer; if ( renderBackgroundDialog ) { background = std::make_unique( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, false ); dialogRoi = background->activeArea(); dialogWithShadowRoi = background->totalArea(); } else { dialogRoi = { ( display.width() - fheroes2::Display::DEFAULT_WIDTH ) / 2, ( display.height() - fheroes2::Display::DEFAULT_HEIGHT ) / 2, fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT }; dialogWithShadowRoi = { dialogRoi.x - 2 * fheroes2::borderWidthPx, dialogRoi.y - fheroes2::borderWidthPx, dialogRoi.width + 3 * fheroes2::borderWidthPx, dialogRoi.height + 3 * fheroes2::borderWidthPx }; restorer = std::make_unique( display, dialogRoi.x, dialogRoi.y, dialogRoi.width, dialogRoi.height ); } // Fade-out game screen only for 640x480 resolution and if 'renderBackgroundDialog' is false (we are replacing image in already opened dialog). const bool isDefaultScreenSize = display.isDefaultSize(); if ( fade && ( isDefaultScreenSize || !renderBackgroundDialog ) ) { fheroes2::fadeOutDisplay( dialogRoi, !isDefaultScreenSize ); } AudioManager::PlayMusicAsync( MUS::FromRace( _race ), Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); int alphaHero = 255; CastleDialog::FadeBuilding fadeBuilding; Heroes * hero = world.GetHero( *this ); fheroes2::Image surfaceHero; auto constructionDialogHandler = [this, &display, &dialogRoi, &fadeBuilding, &hero, &surfaceHero, &alphaHero]() { uint32_t build = BUILD_NOTHING; const Castle::ConstructionDialogResult result = _openConstructionDialog( build ); switch ( result ) { case ConstructionDialogResult::NextConstructionWindow: return CastleDialogReturnValue::NextCostructionWindow; case ConstructionDialogResult::PrevConstructionWindow: return CastleDialogReturnValue::PreviousCostructionWindow; case ConstructionDialogResult::RecruitHero: hero = world.GetHero( *this ); generateHeroImage( surfaceHero, hero ); AudioManager::PlaySound( M82::BUILDTWN ); alphaHero = 0; break; default: if ( build == BUILD_NOTHING ) { break; } if ( !BuyBuilding( build ) ) { assert( 0 ); } AudioManager::PlaySound( M82::BUILDTWN ); fadeBuilding.startFadeBuilding( build ); break; } // Set next render ROI to dialog ROI. It is needed to properly update the castle dialog after the construction dialog is closed. display.updateNextRenderRoi( dialogRoi ); return CastleDialogReturnValue::DoNothing; }; if ( openConstructionWindow && isBuild( BUILD_CASTLE ) ) { const CastleDialogReturnValue constructionResult = constructionDialogHandler(); if ( constructionResult != CastleDialogReturnValue::DoNothing ) { return constructionResult; } } const std::string currentDate = getDateString(); // Previous castle button. fheroes2::Point statusBarPosition( dialogRoi.x, dialogRoi.y + 480 - 19 ); fheroes2::Button buttonPrevCastle( statusBarPosition.x, statusBarPosition.y, ICN::SMALLBAR, 1, 2 ); fheroes2::TimedEventValidator timedButtonPrevCastle( [&buttonPrevCastle]() { return buttonPrevCastle.isPressed(); } ); buttonPrevCastle.subscribe( &timedButtonPrevCastle ); statusBarPosition.x += buttonPrevCastle.area().width; // Status bar at the bottom of dialog. const fheroes2::Sprite & bar = fheroes2::AGG::GetICN( ICN::SMALLBAR, 0 ); fheroes2::Copy( bar, 0, 0, display, statusBarPosition.x, statusBarPosition.y, bar.width(), bar.height() ); StatusBar statusBar; // Status bar must be smaller due to extra art on both sides. statusBar.setRoi( { statusBarPosition.x + 16, statusBarPosition.y + 3, bar.width() - 16 * 2, 0 } ); // Next castle button. fheroes2::Button buttonNextCastle( statusBarPosition.x + bar.width(), statusBarPosition.y, ICN::SMALLBAR, 3, 4 ); fheroes2::TimedEventValidator timedButtonNextCastle( [&buttonNextCastle]() { return buttonNextCastle.isPressed(); } ); buttonNextCastle.subscribe( &timedButtonNextCastle ); // Position of the captain/crest and hero portrait to the left of army bars. const fheroes2::Sprite & crest = fheroes2::AGG::GetICN( ICN::CREST, Color::GetIndex( GetColor() ) ); const fheroes2::Rect rectSign1( dialogRoi.x + 5, dialogRoi.y + 262, crest.width(), crest.height() ); const fheroes2::Rect rectSign2( rectSign1.x, dialogRoi.y + 361, 100, 92 ); // For the case when new hero is recruited we need to render bottom army bar // without hero and his army to properly perform hero fade-in. RedrawIcons( *this, ( alphaHero == 0 ) ? nullptr : hero, dialogRoi.getPosition() ); auto setArmyBarParameters = []( ArmyBar & armyBar, const fheroes2::Point & offset ) { armyBar.setTableSize( { 5, 1 } ); armyBar.setRenderingOffset( offset ); armyBar.setInBetweenItemsOffset( { 6, 0 } ); }; // Castle army (top) bar. ArmyBar topArmyBar( &_army, false, false ); setArmyBarParameters( topArmyBar, { dialogRoi.x + 112, rectSign1.y } ); topArmyBar.Redraw( display ); // Hero army (bottom) bar. ArmyBar bottomArmyBar( hero ? &hero->GetArmy() : nullptr, false, false ); setArmyBarParameters( bottomArmyBar, { dialogRoi.x + 112, rectSign2.y } ); if ( hero && alphaHero != 0 ) { // Draw bottom bar only if no hero fading animation is going. bottomArmyBar.Redraw( display ); } // Exit button. fheroes2::Button buttonExit( dialogRoi.x + 553, dialogRoi.y + 428, ICN::BUTTON_EXIT_TOWN, 0, 1 ); // Kingdom resources. const fheroes2::Rect & rectResource = fheroes2::drawResourcePanel( GetKingdom().GetFunds(), display, dialogRoi.getPosition() ); const fheroes2::Rect resActiveArea( rectResource.x, rectResource.y, rectResource.width, buttonExit.area().y - rectResource.y - 3 ); // Cache a vector of castle buildings in the order they are rendered. const CastleDialog::BuildingsRenderQueue cacheBuildings( *this, dialogRoi.getPosition() ); // Render castle buildings. CastleDialog::redrawAllBuildings( *this, dialogRoi.getPosition(), cacheBuildings, fadeBuilding, 0 ); if ( GetKingdom().GetCastles().size() < 2 ) { buttonPrevCastle.disable(); buttonNextCastle.disable(); } buttonPrevCastle.draw(); buttonNextCastle.draw(); buttonExit.draw(); // Fade-in castle dialog. if ( fade ) { if ( renderBackgroundDialog && !isDefaultScreenSize ) { // We need to expand the ROI for the next render to properly render window borders and shadow. display.updateNextRenderRoi( dialogWithShadowRoi ); } // Use half fade if game resolution is not 640x480. fheroes2::fadeInDisplay( dialogRoi, !isDefaultScreenSize ); } else { display.render( dialogWithShadowRoi ); } CastleDialogReturnValue result = CastleDialogReturnValue::DoNothing; // This variable must be declared out of the loop for performance reasons. std::string statusMessage; uint32_t castleAnimationIndex = 1; Game::passAnimationDelay( Game::CASTLE_AROUND_DELAY ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() && result == CastleDialogReturnValue::DoNothing ) { bool needRedraw = false; bool needFadeIn = false; // During hero purchase or building construction skip any interaction with the dialog. if ( alphaHero >= 255 && fadeBuilding.isFadeDone() ) { if ( buttonPrevCastle.isEnabled() ) { buttonPrevCastle.drawOnState( le.isMouseLeftButtonPressedInArea( buttonPrevCastle.area() ) ); } if ( buttonNextCastle.isEnabled() ) { buttonNextCastle.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNextCastle.area() ) ); } buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); // Check buttons for closing this castle's window. if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { result = CastleDialogReturnValue::Close; // Disable fast scroll for resolutions where the exit button is directly above the border. Interface::AdventureMap::Get().getGameArea().setFastScrollStatus( false ); // Fade-out castle dialog. fheroes2::fadeOutDisplay( dialogRoi, !isDefaultScreenSize ); break; } if ( buttonPrevCastle.isEnabled() && ( le.MouseClickLeft( buttonPrevCastle.area() ) || HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_LEFT ) || timedButtonPrevCastle.isDelayPassed() ) ) { result = CastleDialogReturnValue::PreviousCastle; break; } if ( buttonNextCastle.isEnabled() && ( le.MouseClickLeft( buttonNextCastle.area() ) || HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) || timedButtonNextCastle.isDelayPassed() ) ) { result = CastleDialogReturnValue::NextCastle; break; } if ( le.MouseClickLeft( resActiveArea ) ) { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); fheroes2::showKingdomIncome( GetKingdom(), Dialog::OK ); } else if ( le.isMouseRightButtonPressedInArea( resActiveArea ) ) { fheroes2::showKingdomIncome( GetKingdom(), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonNextCastle.area() ) ) { fheroes2::showStandardTextMessage( _( "Show next town" ), _( "Click to show next town." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonPrevCastle.area() ) ) { fheroes2::showStandardTextMessage( _( "Show previous town" ), _( "Click to show previous town." ), Dialog::ZERO ); } else if ( isBuild( BUILD_CAPTAIN ) && le.isMouseRightButtonPressedInArea( rectSign1 ) ) { Dialog::QuickInfo( GetCaptain() ); } else if ( hero && le.isMouseRightButtonPressedInArea( rectSign2 ) ) { Dialog::QuickInfo( *hero ); } // Army bar events processing. if ( ( bottomArmyBar.isValid() && ( ( le.isMouseCursorPosInArea( topArmyBar.GetArea() ) && topArmyBar.QueueEventProcessing( bottomArmyBar, &statusMessage ) ) || ( le.isMouseCursorPosInArea( bottomArmyBar.GetArea() ) && bottomArmyBar.QueueEventProcessing( topArmyBar, &statusMessage ) ) ) ) || ( !bottomArmyBar.isValid() && le.isMouseCursorPosInArea( topArmyBar.GetArea() ) && topArmyBar.QueueEventProcessing( &statusMessage ) ) ) { needRedraw = true; } // Actions with hero army. if ( hero ) { bool isArmyActionPerformed = false; // Preselecting of troop. const ArmyTroop * keep = nullptr; if ( topArmyBar.isSelected() ) { keep = topArmyBar.GetSelectedItem(); } else if ( bottomArmyBar.isSelected() ) { keep = bottomArmyBar.GetSelectedItem(); } if ( HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_DOWN ) ) { hero->GetArmy().MoveTroops( GetArmy(), keep ? keep->GetID() : Monster::UNKNOWN ); isArmyActionPerformed = true; } else if ( HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_UP ) ) { GetArmy().MoveTroops( hero->GetArmy(), keep ? keep->GetID() : Monster::UNKNOWN ); isArmyActionPerformed = true; } // Reset selection and schedule dialog redraw if any action modifying armies has been made. if ( isArmyActionPerformed ) { if ( topArmyBar.isSelected() ) { topArmyBar.ResetSelected(); } if ( bottomArmyBar.isSelected() ) { bottomArmyBar.ResetSelected(); } needRedraw = true; } } if ( hero && le.MouseClickLeft( rectSign2 ) ) { // View hero. openHeroDialog( topArmyBar, bottomArmyBar, *hero ); needFadeIn = true; needRedraw = true; } // Get pressed hotkey. const BuildingType hotKeyBuilding = getPressedBuildingHotkey(); // Interaction with buildings. // Animation queue starts from the lowest by Z-value buildings which means that they draw first and most likely overlap by the top buildings in the queue. // In this case we must revert the queue and finding the first suitable building. for ( auto it = cacheBuildings.crbegin(); it != cacheBuildings.crend(); ++it ) { if ( !isBuild( it->id ) ) { continue; } const uint32_t monsterDwelling = GetActualDwelling( it->id ); const bool isMonsterDwelling = ( monsterDwelling != BUILD_NOTHING ); if ( le.isMouseRightButtonPressedInArea( it->coord ) ) { // Check mouse right click. if ( isMonsterDwelling ) { Dialog::DwellingInfo( Monster( _race, it->id ), getMonstersInDwelling( it->id ) ); } else { fheroes2::showStandardTextMessage( GetStringBuilding( it->id ), GetDescriptionBuilding( it->id ), Dialog::ZERO ); } // Nothing we need to do after. break; } const bool isMagicGuild = ( BUILD_MAGEGUILD & it->id ) != 0; if ( le.MouseClickLeft( it->coord ) || hotKeyBuilding == it->id || ( isMagicGuild && hotKeyBuilding == BUILD_MAGEGUILD ) ) { if ( topArmyBar.isSelected() ) { topArmyBar.ResetSelected(); } if ( bottomArmyBar.isValid() && bottomArmyBar.isSelected() ) { bottomArmyBar.ResetSelected(); } if ( isMagicGuild ) { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); if ( purchaseSpellBookIfNecessary( *this, hero ) ) { // Guest hero purchased the spellbook, redraw the resource panel needRedraw = true; } _openMageGuild( hero ); } else if ( isMonsterDwelling ) { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); const int32_t recruitMonsterWindowOffsetY = -65; const Troop monsterToRecruit = Dialog::RecruitMonster( Monster( _race, monsterDwelling ), getMonstersInDwelling( it->id ), true, recruitMonsterWindowOffsetY ); if ( Castle::RecruitMonster( monsterToRecruit ) ) { needRedraw = true; } } else { switch ( it->id ) { case BUILD_THIEVESGUILD: Dialog::ThievesGuild( false ); break; case BUILD_TAVERN: { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); _openTavern(); break; } case BUILD_CAPTAIN: case BUILD_STATUE: case BUILD_WEL2: case BUILD_MOAT: case BUILD_SPEC: case BUILD_SHRINE: { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); fheroes2::showStandardTextMessage( GetStringBuilding( it->id ), GetDescriptionBuilding( it->id ), Dialog::OK ); break; } case BUILD_SHIPYARD: { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); if ( Dialog::BuyBoat( AllowBuyBoat( true ) ) != Dialog::OK ) { break; } if ( !BuyBoat() ) { assert( 0 ); } fadeBuilding.startFadeBoat(); needRedraw = true; break; } case BUILD_MARKETPLACE: { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); Dialog::Marketplace( GetKingdom(), false ); needRedraw = true; break; } case BUILD_WELL: _openWell(); needRedraw = true; break; case BUILD_TENT: { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); if ( isBuildingDisabled( BUILD_CASTLE ) ) { fheroes2::showStandardTextMessage( _( "Town" ), _( "This town may not be upgraded to a castle." ), Dialog::OK ); break; } if ( DialogBuyCastle( true ) != Dialog::OK ) { break; } if ( !BuyBuilding( BUILD_CASTLE ) ) { assert( 0 ); } AudioManager::PlaySound( M82::BUILDTWN ); fadeBuilding.startFadeBuilding( BUILD_CASTLE ); needRedraw = true; break; } case BUILD_CASTLE: { result = constructionDialogHandler(); needRedraw = true; break; } default: // Some new building? assert( 0 ); break; } } break; } } } if ( result != CastleDialogReturnValue::DoNothing ) { break; } if ( alphaHero < 255 && Game::validateAnimationDelay( Game::CASTLE_BUYHERO_DELAY ) ) { alphaHero += 10; if ( alphaHero >= 255 ) { alphaHero = 255; // Hero fade-in animation is finished, we can set up his army bar. bottomArmyBar.SetArmy( &hero->GetArmy() ); } fheroes2::AlphaBlit( surfaceHero, display, dialogRoi.x, dialogRoi.y + 356, static_cast( alphaHero ) ); if ( !needRedraw ) { display.render( dialogRoi ); } } if ( needRedraw ) { // Redraw the bottom part of the castle dialog (army bars, resources, exit button). topArmyBar.Redraw( display ); if ( bottomArmyBar.isValid() && alphaHero >= 255 ) { bottomArmyBar.Redraw( display ); } fheroes2::drawResourcePanel( GetKingdom().GetFunds(), display, dialogRoi.getPosition() ); if ( buttonExit.isPressed() ) { buttonExit.draw(); } if ( needFadeIn ) { fheroes2::fadeInDisplay( dialogRoi, !isDefaultScreenSize ); } else { display.render( dialogRoi ); } } // Update status bar. It doesn't depend on animation status. // Animation queue starts from the lowest by Z-value buildings which means that they draw first and most likely overlap by the top buildings in the queue. // In this case we must revert the queue and finding the first suitable building. for ( auto it = cacheBuildings.crbegin(); it != cacheBuildings.crend(); ++it ) { if ( isBuild( it->id ) && le.isMouseCursorPosInArea( it->coord ) ) { statusMessage = buildingStatusMessage( _race, it->id ); break; } } if ( le.isMouseCursorPosInArea( buttonExit.area() ) ) { statusMessage = isCastle() ? _( "Exit Castle" ) : _( "Exit Town" ); } else if ( le.isMouseCursorPosInArea( resActiveArea ) ) { statusMessage = _( "Show Income" ); } else if ( buttonPrevCastle.isEnabled() && le.isMouseCursorPosInArea( buttonPrevCastle.area() ) ) { statusMessage = _( "Show previous town" ); } else if ( buttonNextCastle.isEnabled() && le.isMouseCursorPosInArea( buttonNextCastle.area() ) ) { statusMessage = _( "Show next town" ); } else if ( hero && le.isMouseCursorPosInArea( rectSign2 ) ) { statusMessage = _( "View Hero" ); } if ( statusMessage.empty() ) { statusBar.ShowMessage( currentDate ); } else { statusBar.ShowMessage( statusMessage ); statusMessage.clear(); } needRedraw = fadeBuilding.updateFadeAlpha(); if ( fadeBuilding.isFadeDone() ) { const uint32_t build = fadeBuilding.getBuilding(); if ( build != BUILD_NOTHING ) { if ( BUILD_CAPTAIN == build ) { RedrawIcons( *this, hero, dialogRoi.getPosition() ); fheroes2::drawCastleName( *this, fheroes2::Display::instance(), dialogRoi.getPosition() ); } fheroes2::drawResourcePanel( GetKingdom().GetFunds(), display, dialogRoi.getPosition() ); display.render( dialogRoi ); } fadeBuilding.stopFade(); } else if ( fadeBuilding.getBuilding() == BUILD_CAPTAIN ) { // Fade-in the captain image while fading-in his quarters. const fheroes2::Sprite & crestImage = fheroes2::AGG::GetICN( ICN::CREST, Color::GetIndex( GetColor() ) ); fheroes2::Copy( crestImage, 0, 0, display, rectSign1.x, rectSign1.y, crestImage.width(), crestImage.height() ); const fheroes2::Sprite & captainImage = GetCaptain().GetPortrait( PORT_BIG ); fheroes2::AlphaBlit( captainImage, display, rectSign1.x, rectSign1.y, fadeBuilding.getAlpha() ); } // Castle dialog animation. if ( Game::validateAnimationDelay( Game::CASTLE_AROUND_DELAY ) || needRedraw ) { CastleDialog::redrawAllBuildings( *this, dialogRoi.getPosition(), cacheBuildings, fadeBuilding, castleAnimationIndex ); display.render( dialogRoi ); if ( !needRedraw ) { ++castleAnimationIndex; } } } Game::SetUpdateSoundsOnFocusUpdate( true ); return result; } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_mageguild.cpp000066400000000000000000000241551476115357100237500ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include "agg_image.h" #include "castle.h" // IWYU pragma: associated #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "mageguild.h" #include "math_base.h" #include "math_tools.h" #include "race.h" #include "screen.h" #include "settings.h" #include "spell.h" #include "spell_storage.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" namespace { const int32_t bottomBarOffsetY = 461; class RowSpells { public: RowSpells( const fheroes2::Point & pos, const Castle & castle, const int lvl ); void Redraw( fheroes2::Image & output ); bool QueueEventProcessing(); private: std::vector coords; SpellStorage spells; }; } RowSpells::RowSpells( const fheroes2::Point & pos, const Castle & castle, const int lvl ) { const bool hide = castle.GetLevelMageGuild() < lvl; const fheroes2::Sprite & roll_show = fheroes2::AGG::GetICN( ICN::TOWNWIND, 0 ); const fheroes2::Sprite & roll_hide = fheroes2::AGG::GetICN( ICN::TOWNWIND, 1 ); const fheroes2::Sprite & roll = ( hide ? roll_hide : roll_show ); int32_t count = 0; switch ( lvl ) { case 1: case 2: count = 3; break; case 3: case 4: count = 2; break; case 5: count = 1; break; default: break; } for ( int32_t i = 0; i < count; ++i ) coords.emplace_back( pos.x + i * 110 - roll.width() / 2, pos.y, roll.width(), roll.height() ); if ( castle.HaveLibraryCapability() ) { if ( !hide && castle.isLibraryBuild() ) coords.emplace_back( pos.x + count * 110 - roll_show.width() / 2, pos.y, roll_show.width(), roll_show.height() ); else coords.emplace_back( pos.x + count * 110 - roll_hide.width() / 2, pos.y, roll_hide.width(), roll_hide.height() ); } spells.reserve( 6 ); spells = castle.GetMageGuild().GetSpells( castle.GetLevelMageGuild(), castle.isLibraryBuild(), lvl ); spells.resize( coords.size(), Spell::NONE ); } void RowSpells::Redraw( fheroes2::Image & output ) { const fheroes2::Sprite & roll_show = fheroes2::AGG::GetICN( ICN::TOWNWIND, 0 ); for ( std::vector::iterator it = coords.begin(); it != coords.end(); ++it ) { const fheroes2::Rect & dst = ( *it ); const Spell & spell = spells[std::distance( coords.begin(), it )]; // roll hide if ( dst.width < roll_show.width() || spell == Spell::NONE ) { const fheroes2::Sprite & roll_hide = fheroes2::AGG::GetICN( ICN::TOWNWIND, 1 ); fheroes2::Blit( roll_hide, output, dst.x, dst.y ); } // roll show else { fheroes2::Blit( roll_show, output, dst.x, dst.y ); const fheroes2::Sprite & icon = fheroes2::AGG::GetICN( ICN::SPELLS, spell.IndexSprite() ); fheroes2::Blit( icon, output, dst.x + 3 + ( dst.width - icon.width() ) / 2, dst.y + 31 - icon.height() / 2 ); const fheroes2::Text text( spell.GetName(), fheroes2::FontType::smallWhite() ); text.draw( dst.x + 18, dst.y + 57, 78, fheroes2::Display::instance() ); } } } bool RowSpells::QueueEventProcessing() { LocalEvent & le = LocalEvent::Get(); const int32_t index = GetRectIndex( coords, le.getMouseCursorPos() ); if ( 0 <= index && ( le.MouseClickLeft() || le.isMouseRightButtonPressed() ) ) { const Spell & spell = spells[index]; if ( spell != Spell::NONE ) { fheroes2::SpellDialogElement( spell, nullptr ).showPopup( le.isMouseRightButtonPressed() ? Dialog::ZERO : Dialog::OK ); } } return 0 <= index; } void Castle::_openMageGuild( const Heroes * hero ) const { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::ImageRestorer restorer( display, ( display.width() - fheroes2::Display::DEFAULT_WIDTH ) / 2, ( display.height() - fheroes2::Display::DEFAULT_HEIGHT ) / 2, fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ); const fheroes2::Point cur_pt( restorer.x(), restorer.y() ); fheroes2::Point dst_pt( cur_pt.x, cur_pt.y ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); fheroes2::Blit( fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ), display, cur_pt.x, cur_pt.y ); // status bar const int32_t exitWidth = fheroes2::AGG::GetICN( ICN::BUTTON_GUILDWELL_EXIT, 0 ).width(); dst_pt.x = cur_pt.x; dst_pt.y = cur_pt.y + bottomBarOffsetY; // The original ICN::WELLXTRA image does not have a yellow outer frame. const fheroes2::Sprite & bottomBar = fheroes2::AGG::GetICN( ICN::SMALLBAR, 0 ); const int32_t barHeight = bottomBar.height(); // ICN::SMALLBAR image's first column contains all black pixels. This should not be drawn. fheroes2::Copy( bottomBar, 1, 0, display, dst_pt.x, dst_pt.y, fheroes2::Display::DEFAULT_WIDTH / 2, barHeight ); fheroes2::Copy( bottomBar, bottomBar.width() - fheroes2::Display::DEFAULT_WIDTH / 2 + exitWidth - 1, 0, display, dst_pt.x + fheroes2::Display::DEFAULT_WIDTH / 2, dst_pt.y, fheroes2::Display::DEFAULT_WIDTH / 2 - exitWidth + 1, barHeight ); // text bar const char * textAlternative; if ( hero == nullptr || !hero->HaveSpellBook() ) { textAlternative = _( "The above spells are available here." ); } else { textAlternative = _( "The spells the hero can learn have been added to their book." ); } fheroes2::Text statusText( textAlternative, fheroes2::FontType::normalWhite() ); statusText.draw( cur_pt.x + ( fheroes2::Display::DEFAULT_WIDTH - exitWidth ) / 2 - statusText.width() / 2, cur_pt.y + 464, display ); const int level = GetLevelMageGuild(); // sprite int icn = ICN::UNKNOWN; switch ( _race ) { case Race::KNGT: icn = ICN::MAGEGLDK; break; case Race::BARB: icn = ICN::MAGEGLDB; break; case Race::SORC: icn = ICN::MAGEGLDS; break; case Race::WRLK: icn = ICN::MAGEGLDW; break; case Race::WZRD: icn = ICN::MAGEGLDZ; break; case Race::NECR: icn = ICN::MAGEGLDN; break; default: break; } const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icn, level - 1 ); const fheroes2::Rect area = fheroes2::GetActiveROI( sprite ); fheroes2::Point inPos( 0, 0 ); fheroes2::Point outPos( cur_pt.x + 100 - area.x - area.width / 2, cur_pt.y + 290 - sprite.height() ); fheroes2::Size inSize( sprite.width(), sprite.height() ); if ( fheroes2::FitToRoi( sprite, inPos, display, outPos, inSize, { cur_pt.x, cur_pt.y, 200, fheroes2::Display::DEFAULT_HEIGHT } ) ) { fheroes2::Blit( sprite, inPos, display, outPos, inSize ); } RowSpells spells5( { cur_pt.x + 250, cur_pt.y + 5 }, *this, 5 ); RowSpells spells4( { cur_pt.x + 250, cur_pt.y + 95 }, *this, 4 ); RowSpells spells3( { cur_pt.x + 250, cur_pt.y + 185 }, *this, 3 ); RowSpells spells2( { cur_pt.x + 250, cur_pt.y + 275 }, *this, 2 ); RowSpells spells1( { cur_pt.x + 250, cur_pt.y + 365 }, *this, 1 ); spells1.Redraw( display ); spells2.Redraw( display ); spells3.Redraw( display ); spells4.Redraw( display ); spells5.Redraw( display ); fheroes2::Button buttonExit( cur_pt.x + fheroes2::Display::DEFAULT_WIDTH - exitWidth, cur_pt.y + bottomBarOffsetY, ICN::BUTTON_GUILDWELL_EXIT, 0, 1 ); buttonExit.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); // message loop while ( le.HandleEvents() ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { break; } spells1.QueueEventProcessing() || spells2.QueueEventProcessing() || spells3.QueueEventProcessing() || spells4.QueueEventProcessing() || spells5.QueueEventProcessing(); if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), Dialog::ZERO ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_tavern.cpp000066400000000000000000000053151476115357100233060ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include "castle.h" // IWYU pragma: associated #include "dialog.h" #include "game_delays.h" #include "game_string.h" #include "icn.h" #include "translations.h" #include "ui_dialog.h" #include "ui_text.h" #include "world.h" void Castle::_openTavern() const { auto rumor = world.getCurrentRumor(); std::string body( _( "A generous tip for the barkeep yields the following rumor:" ) ); body += "\n\n"; auto text = std::make_shared(); text->add( fheroes2::Text{ std::move( body ), fheroes2::FontType::normalWhite() } ); text->add( fheroes2::Text{ std::move( rumor.text ), fheroes2::FontType::normalWhite(), rumor.language } ); const fheroes2::AnimationDialogElement imageUI( ICN::TAVWIN, { 0, 1 }, 0, Game::getAnimationDelayValue( Game::CASTLE_TAVERN_DELAY ) ); const fheroes2::TextDialogElement textBodyUI( text ); fheroes2::showStandardTextMessage( GetStringBuilding( BUILD_TAVERN ), {}, Dialog::OK, { &imageUI, &textBodyUI } ); } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_town.cpp000066400000000000000000001015611476115357100227760ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "artifact.h" #include "buildinginfo.h" #include "captain.h" #include "castle.h" // IWYU pragma: associated #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "heroes.h" #include "heroes_base.h" #include "heroes_recruits.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "maps_fileinfo.h" #include "math_base.h" #include "payment.h" #include "race.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "statusbar.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_castle.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_kingdom.h" #include "ui_language.h" #include "ui_text.h" #include "ui_tool.h" #include "world.h" int Castle::DialogBuyHero( const Heroes * hero ) const { if ( !hero ) { return Dialog::CANCEL; } fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const int32_t spacer = 10; const fheroes2::Sprite & portrait_frame = fheroes2::AGG::GetICN( ICN::SURRENDR, 4 ); const fheroes2::Text recruitHeroText( _( "Recruit Hero" ), fheroes2::FontType::normalYellow() ); uint32_t count = hero->GetCountArtifacts(); if ( hero->hasArtifact( Artifact::MAGIC_BOOK ) ) { --count; } std::string str = _( "%{name} is a level %{value} %{race} " ); if ( count ) { str += count > 1 ? _( "with %{count} artifacts." ) : _( "with 1 artifact." ); } else { str += _( "without artifacts." ); } StringReplace( str, "%{name}", hero->GetName() ); StringReplace( str, "%{value}", hero->GetLevel() ); StringReplace( str, "%{race}", Race::String( hero->GetRace() ) ); StringReplace( str, "%{count}", count ); const fheroes2::Text heroDescriptionText( std::move( str ), fheroes2::FontType::normalWhite() ); Resource::BoxSprite rbs( PaymentConditions::RecruitHero(), fheroes2::boxAreaWidthPx ); const int32_t dialogHeight = recruitHeroText.height( fheroes2::boxAreaWidthPx ) + spacer + portrait_frame.height() + spacer + heroDescriptionText.height( fheroes2::boxAreaWidthPx ) + spacer + rbs.GetArea().height; const Dialog::FrameBox box( dialogHeight, true ); const fheroes2::Rect & dialogRoi = box.GetArea(); recruitHeroText.draw( dialogRoi.x, dialogRoi.y + 2, fheroes2::boxAreaWidthPx, display ); // portrait and frame fheroes2::Point pos{ dialogRoi.x + ( dialogRoi.width - portrait_frame.width() ) / 2, dialogRoi.y + recruitHeroText.height( fheroes2::boxAreaWidthPx ) + spacer }; fheroes2::Blit( portrait_frame, display, pos.x, pos.y ); const fheroes2::Rect heroPortraitArea( pos.x, pos.y, portrait_frame.width(), portrait_frame.height() ); pos.x = pos.x + 5; pos.y = pos.y + 6; hero->PortraitRedraw( pos.x, pos.y, PORT_BIG, display ); pos.y += portrait_frame.height() + spacer; heroDescriptionText.draw( dialogRoi.x, pos.y + 2, fheroes2::boxAreaWidthPx, display ); rbs.SetPos( dialogRoi.x, pos.y + heroDescriptionText.height( fheroes2::boxAreaWidthPx ) + spacer ); rbs.Redraw(); fheroes2::ButtonGroup buttonGroup( dialogRoi, Dialog::OK | Dialog::CANCEL ); fheroes2::ButtonBase & buttonOkay = buttonGroup.button( 0 ); const fheroes2::ButtonBase & buttonCancel = buttonGroup.button( 1 ); if ( !AllowBuyHero() ) { buttonOkay.disable(); } buttonGroup.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { const int result = buttonGroup.processEvents(); if ( result != Dialog::ZERO ) { return result; } if ( le.isMouseRightButtonPressedInArea( heroPortraitArea ) ) { Dialog::QuickInfo( *hero ); } else if ( le.isMouseRightButtonPressedInArea( buttonOkay.area() ) ) { std::string recruitHero = _( "Recruit %{name} the %{race}" ); StringReplace( recruitHero, "%{name}", hero->GetName() ); StringReplace( recruitHero, "%{race}", Race::String( hero->GetRace() ) ); recruitHero += '.'; fheroes2::showStandardTextMessage( _( "Okay" ), std::move( recruitHero ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } } return Dialog::CANCEL; } int Castle::DialogBuyCastle( const bool hasButtons /* = true */ ) const { const BuildingInfo info( *this, BUILD_CASTLE ); return info.DialogBuyBuilding( hasButtons ) ? Dialog::OK : Dialog::CANCEL; } Castle::ConstructionDialogResult Castle::_openConstructionDialog( uint32_t & dwellingTobuild ) { if ( !isBuild( BUILD_CASTLE ) ) { // It is not possible to open this dialog without a built castle! assert( 0 ); return ConstructionDialogResult::DoNothing; } dwellingTobuild = BUILD_NOTHING; // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::ImageRestorer restorer( display, ( display.width() - fheroes2::Display::DEFAULT_WIDTH ) / 2, ( display.height() - fheroes2::Display::DEFAULT_HEIGHT ) / 2, fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ); const fheroes2::Point cur_pt( restorer.x(), restorer.y() ); fheroes2::Point dst_pt( cur_pt ); const Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Blit( fheroes2::AGG::GetICN( isEvilInterface ? ICN::CASLWIND_EVIL : ICN::CASLWIND, 0 ), display, dst_pt.x, dst_pt.y ); // hide captain options if ( !( _constructedBuildings & BUILD_CAPTAIN ) ) { dst_pt.x = 530; dst_pt.y = 163; const fheroes2::Rect rect( dst_pt.x, dst_pt.y, 110, 84 ); dst_pt.x += cur_pt.x; dst_pt.y += cur_pt.y; const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ); fheroes2::Copy( backgroundImage, rect.x, rect.y, display, dst_pt.x, dst_pt.y, rect.width, rect.height ); } // draw castle sprite dst_pt.x = cur_pt.x + 459; dst_pt.y = cur_pt.y + 5; DrawImageCastle( dst_pt ); // castle name const fheroes2::Text castleName( GetName(), fheroes2::FontType::smallWhite() ); castleName.draw( cur_pt.x + 538 - castleName.width() / 2, cur_pt.y + 3, display ); dst_pt.y = cur_pt.y + 2; BuildingInfo dwelling1( *this, DWELLING_MONSTER1 ); dwelling1.SetPos( cur_pt.x + 5, dst_pt.y ); dwelling1.Redraw(); BuildingInfo dwelling2( *this, DWELLING_MONSTER2 ); dwelling2.SetPos( cur_pt.x + 149, dst_pt.y ); dwelling2.Redraw(); BuildingInfo dwelling3( *this, DWELLING_MONSTER3 ); dwelling3.SetPos( cur_pt.x + 293, dst_pt.y ); dwelling3.Redraw(); dst_pt.y = cur_pt.y + 77; BuildingInfo dwelling4( *this, DWELLING_MONSTER4 ); dwelling4.SetPos( cur_pt.x + 5, dst_pt.y ); dwelling4.Redraw(); BuildingInfo dwelling5( *this, DWELLING_MONSTER5 ); dwelling5.SetPos( cur_pt.x + 149, dst_pt.y ); dwelling5.Redraw(); BuildingInfo dwelling6( *this, DWELLING_MONSTER6 ); dwelling6.SetPos( cur_pt.x + 293, dst_pt.y ); dwelling6.Redraw(); // mage guild BuildingType level = BUILD_NOTHING; switch ( GetLevelMageGuild() ) { case 0: level = BUILD_MAGEGUILD1; break; case 1: level = BUILD_MAGEGUILD2; break; case 2: level = BUILD_MAGEGUILD3; break; case 3: level = BUILD_MAGEGUILD4; break; default: level = BUILD_MAGEGUILD5; break; } dst_pt.y = cur_pt.y + 157; BuildingInfo buildingMageGuild( *this, level ); buildingMageGuild.SetPos( cur_pt.x + 5, dst_pt.y ); buildingMageGuild.Redraw(); // tavern const bool isSkipTavernInteraction = ( Race::NECR == _race ) && ( conf.getCurrentMapInfo().version == GameVersion::SUCCESSION_WARS ); BuildingInfo buildingTavern( *this, BUILD_TAVERN ); buildingTavern.SetPos( cur_pt.x + 149, dst_pt.y ); buildingTavern.Redraw(); // thieves guild BuildingInfo buildingThievesGuild( *this, BUILD_THIEVESGUILD ); buildingThievesGuild.SetPos( cur_pt.x + 293, dst_pt.y ); buildingThievesGuild.Redraw(); dst_pt.y = cur_pt.y + 232; // shipyard BuildingInfo buildingShipyard( *this, BUILD_SHIPYARD ); buildingShipyard.SetPos( cur_pt.x + 5, dst_pt.y ); buildingShipyard.Redraw(); // statue BuildingInfo buildingStatue( *this, BUILD_STATUE ); buildingStatue.SetPos( cur_pt.x + 149, dst_pt.y ); buildingStatue.Redraw(); // marketplace BuildingInfo buildingMarketplace( *this, BUILD_MARKETPLACE ); buildingMarketplace.SetPos( cur_pt.x + 293, dst_pt.y ); buildingMarketplace.Redraw(); dst_pt.y = cur_pt.y + 307; // well BuildingInfo buildingWell( *this, BUILD_WELL ); buildingWell.SetPos( cur_pt.x + 5, dst_pt.y ); buildingWell.Redraw(); // wel2 BuildingInfo buildingWel2( *this, BUILD_WEL2 ); buildingWel2.SetPos( cur_pt.x + 149, dst_pt.y ); buildingWel2.Redraw(); // spec BuildingInfo buildingSpec( *this, BUILD_SPEC ); buildingSpec.SetPos( cur_pt.x + 293, dst_pt.y ); buildingSpec.Redraw(); dst_pt.y = cur_pt.y + 387; // left turret BuildingInfo buildingLTurret( *this, BUILD_LEFTTURRET ); buildingLTurret.SetPos( cur_pt.x + 5, dst_pt.y ); buildingLTurret.Redraw(); // right turret BuildingInfo buildingRTurret( *this, BUILD_RIGHTTURRET ); buildingRTurret.SetPos( cur_pt.x + 149, dst_pt.y ); buildingRTurret.Redraw(); // moat BuildingInfo buildingMoat( *this, BUILD_MOAT ); buildingMoat.SetPos( cur_pt.x + 293, dst_pt.y ); buildingMoat.Redraw(); // captain BuildingInfo buildingCaptain( *this, BUILD_CAPTAIN ); buildingCaptain.SetPos( cur_pt.x + 444, cur_pt.y + 165 ); buildingCaptain.Redraw(); // combat format const fheroes2::Sprite & spriteSpreadArmyFormat = fheroes2::AGG::GetICN( ICN::HSICONS, 9 ); const fheroes2::Sprite & spriteGroupedArmyFormat = fheroes2::AGG::GetICN( ICN::HSICONS, 10 ); const fheroes2::Rect rectSpreadArmyFormat( cur_pt.x + 550, cur_pt.y + 220, spriteSpreadArmyFormat.width(), spriteSpreadArmyFormat.height() ); const fheroes2::Rect rectGroupedArmyFormat( cur_pt.x + 585, cur_pt.y + 220, spriteGroupedArmyFormat.width(), spriteGroupedArmyFormat.height() ); const std::string descriptionSpreadArmyFormat( _( "'Spread' combat formation spreads the castle's units from the top to the bottom of the battlefield, with at least one empty space between each unit." ) ); const std::string descriptionGroupedArmyFormat( _( "'Grouped' combat formation bunches the castle's units together in the center of the castle's side of the battlefield." ) ); const fheroes2::Point pointSpreadArmyFormat( rectSpreadArmyFormat.x - 1, rectSpreadArmyFormat.y - 1 ); const fheroes2::Point pointGroupedArmyFormat( rectGroupedArmyFormat.x - 1, rectGroupedArmyFormat.y - 1 ); const fheroes2::Rect armyFormatRenderRect( pointSpreadArmyFormat, { rectGroupedArmyFormat.x + rectGroupedArmyFormat.width - pointSpreadArmyFormat.x + 1, rectGroupedArmyFormat.y + rectGroupedArmyFormat.height - pointSpreadArmyFormat.y + 1 } ); fheroes2::MovableSprite cursorFormat( fheroes2::AGG::GetICN( ICN::HSICONS, 11 ) ); if ( isBuild( BUILD_CAPTAIN ) ) { const int32_t skillValueOffsetX = 90; const int32_t skillOffsetY = 12; fheroes2::Text text( Skill::Primary::String( Skill::Primary::ATTACK ), fheroes2::FontType::smallWhite() ); dst_pt.x = cur_pt.x + 535; dst_pt.y = cur_pt.y + 170; text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( _captain.GetAttack() ), fheroes2::FontType::smallWhite() ); text.draw( dst_pt.x + skillValueOffsetX, dst_pt.y, display ); dst_pt.y += skillOffsetY; text.set( Skill::Primary::String( Skill::Primary::DEFENSE ), fheroes2::FontType::smallWhite() ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( _captain.GetDefense() ), fheroes2::FontType::smallWhite() ); text.draw( dst_pt.x + skillValueOffsetX, dst_pt.y, display ); dst_pt.y += skillOffsetY; text.set( Skill::Primary::String( Skill::Primary::POWER ), fheroes2::FontType::smallWhite() ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( _captain.GetPower() ), fheroes2::FontType::smallWhite() ); text.draw( dst_pt.x + skillValueOffsetX, dst_pt.y, display ); dst_pt.y += skillOffsetY; text.set( Skill::Primary::String( Skill::Primary::KNOWLEDGE ), fheroes2::FontType::smallWhite() ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( _captain.GetKnowledge() ), fheroes2::FontType::smallWhite() ); text.draw( dst_pt.x + skillValueOffsetX, dst_pt.y, display ); fheroes2::Copy( spriteSpreadArmyFormat, 0, 0, display, rectSpreadArmyFormat.x, rectSpreadArmyFormat.y, rectSpreadArmyFormat.width, rectSpreadArmyFormat.height ); fheroes2::Copy( spriteGroupedArmyFormat, 0, 0, display, rectGroupedArmyFormat.x, rectGroupedArmyFormat.y, rectGroupedArmyFormat.width, rectGroupedArmyFormat.height ); if ( _army.isSpreadFormation() ) { cursorFormat.setPosition( pointSpreadArmyFormat.x, pointSpreadArmyFormat.y ); } else { cursorFormat.setPosition( pointGroupedArmyFormat.x, pointGroupedArmyFormat.y ); } } Kingdom & kingdom = GetKingdom(); Heroes * hero1 = kingdom.GetRecruits().GetHero1(); Heroes * hero2 = kingdom.GetRecruits().GetHero2(); std::string not_allow1_msg; std::string not_allow2_msg; const bool allow_buy_hero1 = hero1 ? AllowBuyHero( ¬_allow1_msg ) : false; const bool allow_buy_hero2 = hero2 ? AllowBuyHero( ¬_allow2_msg ) : false; // first hero dst_pt.x = cur_pt.x + 443; dst_pt.y = cur_pt.y + 260; const fheroes2::Rect rectHero1( dst_pt.x, dst_pt.y, 102, 93 ); if ( hero1 ) { hero1->PortraitRedraw( dst_pt.x, dst_pt.y, PORT_BIG, display ); } else { fheroes2::Image noHeroPortrait; noHeroPortrait._disableTransformLayer(); noHeroPortrait.resize( rectHero1.width, rectHero1.height ); noHeroPortrait.fill( 0 ); fheroes2::Copy( noHeroPortrait, 0, 0, display, rectHero1.x, rectHero1.y, rectHero1.width, rectHero1.height ); } // indicator if ( !allow_buy_hero1 ) { const fheroes2::Sprite & spriteDeny = fheroes2::AGG::GetICN( ICN::TOWNWIND, 12 ); fheroes2::Blit( spriteDeny, display, dst_pt.x + 102 - 4 + 1 - spriteDeny.width(), dst_pt.y + 93 - 2 - spriteDeny.height() ); } // second hero dst_pt.x = cur_pt.x + 443; dst_pt.y = cur_pt.y + 363; const fheroes2::Rect rectHero2( dst_pt.x, dst_pt.y, 102, 94 ); if ( hero2 ) { hero2->PortraitRedraw( dst_pt.x, dst_pt.y, PORT_BIG, display ); } else { fheroes2::Image noHeroPortrait; noHeroPortrait._disableTransformLayer(); noHeroPortrait.resize( rectHero2.width, rectHero2.height ); noHeroPortrait.fill( 0 ); fheroes2::Copy( noHeroPortrait, 0, 0, display, rectHero2.x, rectHero2.y, rectHero2.width, rectHero2.height ); } // indicator if ( !allow_buy_hero2 ) { const fheroes2::Sprite & spriteDeny = fheroes2::AGG::GetICN( ICN::TOWNWIND, 12 ); fheroes2::Blit( spriteDeny, display, dst_pt.x + 102 - 4 + 1 - spriteDeny.width(), dst_pt.y + 93 - 2 - spriteDeny.height() ); } dst_pt.y = cur_pt.y + 480 - 19; fheroes2::Button buttonPrevCastle( cur_pt.x, dst_pt.y, ICN::SMALLBAR, 1, 2 ); fheroes2::TimedEventValidator timedButtonPrevCastle( [&buttonPrevCastle]() { return buttonPrevCastle.isPressed(); } ); buttonPrevCastle.subscribe( &timedButtonPrevCastle ); // bottom small bar const fheroes2::Sprite & bar = fheroes2::AGG::GetICN( ICN::SMALLBAR, 0 ); const int32_t statusBarWidth = bar.width(); dst_pt.x = cur_pt.x + buttonPrevCastle.area().width; fheroes2::Copy( bar, 0, 0, display, dst_pt.x, dst_pt.y, statusBarWidth, bar.height() ); StatusBar statusBar; // Status bar must be smaller due to extra art on both sides. statusBar.setRoi( { dst_pt.x + 16, dst_pt.y + 3, statusBarWidth - 16 * 2, 0 } ); // button next castle fheroes2::Button buttonNextCastle( dst_pt.x + statusBarWidth, dst_pt.y, ICN::SMALLBAR, 3, 4 ); fheroes2::TimedEventValidator timedButtonNextCastle( [&buttonNextCastle]() { return buttonNextCastle.isPressed(); } ); buttonNextCastle.subscribe( &timedButtonNextCastle ); // button exit dst_pt.x = cur_pt.x + 553; dst_pt.y = cur_pt.y + 428; fheroes2::Button buttonExit( dst_pt.x, dst_pt.y, ICN::BUTTON_EXIT_TOWN, 0, 1 ); if ( GetKingdom().GetCastles().size() < 2 ) { buttonPrevCastle.disable(); buttonNextCastle.disable(); } buttonPrevCastle.draw(); buttonNextCastle.draw(); buttonExit.draw(); // redraw resource panel const fheroes2::Rect & rectResource = fheroes2::drawResourcePanel( GetKingdom().GetFunds(), display, cur_pt ); const fheroes2::Rect resActiveArea( rectResource.x, rectResource.y, rectResource.width, buttonExit.area().y - rectResource.y - 3 ); auto recruitHeroDialog = [this, &buttonExit]( Heroes * hero ) { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); if ( Dialog::OK == DialogBuyHero( hero ) ) { RecruitHero( hero ); return true; } return false; }; display.render( restorer.rect() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( buttonPrevCastle.isEnabled() ) { buttonPrevCastle.drawOnState( le.isMouseLeftButtonPressedInArea( buttonPrevCastle.area() ) ); if ( le.MouseClickLeft( buttonPrevCastle.area() ) || HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_LEFT ) || timedButtonPrevCastle.isDelayPassed() ) { return ConstructionDialogResult::PrevConstructionWindow; } } if ( buttonNextCastle.isEnabled() ) { buttonNextCastle.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNextCastle.area() ) ); if ( le.MouseClickLeft( buttonNextCastle.area() ) || HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) || timedButtonNextCastle.isDelayPassed() ) { return ConstructionDialogResult::NextConstructionWindow; } } if ( le.MouseClickLeft( resActiveArea ) ) { const fheroes2::ButtonRestorer exitRestorer( buttonExit ); fheroes2::showKingdomIncome( world.GetKingdom( GetColor() ), Dialog::OK ); } else if ( le.isMouseRightButtonPressedInArea( resActiveArea ) ) { fheroes2::showKingdomIncome( world.GetKingdom( GetColor() ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), Dialog::ZERO ); } else if ( le.isMouseCursorPosInArea( dwelling1.GetArea() ) && dwelling1.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = dwelling1.getBuilding(); return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( dwelling2.GetArea() ) && dwelling2.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = dwelling2.getBuilding(); return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( dwelling3.GetArea() ) && dwelling3.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = dwelling3.getBuilding(); return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( dwelling4.GetArea() ) && dwelling4.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = dwelling4.getBuilding(); return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( dwelling5.GetArea() ) && dwelling5.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = dwelling5.getBuilding(); return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( dwelling6.GetArea() ) && dwelling6.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = dwelling6.getBuilding(); return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingMageGuild.GetArea() ) && buildingMageGuild.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = buildingMageGuild.getBuilding(); return ConstructionDialogResult::Build; } if ( !isSkipTavernInteraction && le.isMouseCursorPosInArea( buildingTavern.GetArea() ) && buildingTavern.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = ( Race::NECR == _race ? BUILD_SHRINE : BUILD_TAVERN ); return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingThievesGuild.GetArea() ) && buildingThievesGuild.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_THIEVESGUILD; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingShipyard.GetArea() ) && buildingShipyard.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_SHIPYARD; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingStatue.GetArea() ) && buildingStatue.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_STATUE; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingMarketplace.GetArea() ) && buildingMarketplace.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_MARKETPLACE; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingWell.GetArea() ) && buildingWell.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_WELL; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingWel2.GetArea() ) && buildingWel2.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_WEL2; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingSpec.GetArea() ) && buildingSpec.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_SPEC; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingLTurret.GetArea() ) && buildingLTurret.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_LEFTTURRET; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingRTurret.GetArea() ) && buildingRTurret.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_RIGHTTURRET; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingMoat.GetArea() ) && buildingMoat.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_MOAT; return ConstructionDialogResult::Build; } if ( le.isMouseCursorPosInArea( buildingCaptain.GetArea() ) && buildingCaptain.QueueEventProcessing( buttonExit ) ) { dwellingTobuild = BUILD_CAPTAIN; return ConstructionDialogResult::Build; } if ( hero1 && le.MouseClickLeft( rectHero1 ) && recruitHeroDialog( hero1 ) ) { return ConstructionDialogResult::RecruitHero; } if ( hero2 && le.MouseClickLeft( rectHero2 ) && recruitHeroDialog( hero2 ) ) { return ConstructionDialogResult::RecruitHero; } const bool isCaptainBuilt = isBuild( BUILD_CAPTAIN ); if ( isCaptainBuilt ) { if ( le.MouseClickLeft( rectSpreadArmyFormat ) && !_army.isSpreadFormation() ) { cursorFormat.setPosition( pointSpreadArmyFormat.x, pointSpreadArmyFormat.y ); display.render( armyFormatRenderRect ); _army.SetSpreadFormation( true ); } else if ( le.MouseClickLeft( rectGroupedArmyFormat ) && _army.isSpreadFormation() ) { cursorFormat.setPosition( pointGroupedArmyFormat.x, pointGroupedArmyFormat.y ); display.render( armyFormatRenderRect ); _army.SetSpreadFormation( false ); } else if ( le.isMouseRightButtonPressedInArea( rectSpreadArmyFormat ) ) { fheroes2::showStandardTextMessage( _( "Spread Formation" ), descriptionSpreadArmyFormat, Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( rectGroupedArmyFormat ) ) { fheroes2::showStandardTextMessage( _( "Grouped Formation" ), descriptionGroupedArmyFormat, Dialog::ZERO ); } } // Right click if ( hero1 && le.isMouseRightButtonPressedInArea( rectHero1 ) ) { LocalEvent::Get().reset(); hero1->OpenDialog( true, true, false, false, false, false, fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() ) ); // Use half fade if game resolution is not 640x480. fheroes2::fadeInDisplay( restorer.rect(), !display.isDefaultSize() ); } else if ( hero2 && le.isMouseRightButtonPressedInArea( rectHero2 ) ) { LocalEvent::Get().reset(); hero2->OpenDialog( true, true, false, false, false, false, fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() ) ); // Use half fade if game resolution is not 640x480. fheroes2::fadeInDisplay( restorer.rect(), !display.isDefaultSize() ); } else if ( le.isMouseRightButtonPressedInArea( buttonNextCastle.area() ) ) { fheroes2::showStandardTextMessage( _( "Show next town" ), _( "Click to show the next town." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonPrevCastle.area() ) ) { fheroes2::showStandardTextMessage( _( "Show previous town" ), _( "Click to show the previous town." ), Dialog::ZERO ); } // status info if ( le.isMouseCursorPosInArea( dwelling1.GetArea() ) ) dwelling1.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( dwelling2.GetArea() ) ) dwelling2.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( dwelling3.GetArea() ) ) dwelling3.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( dwelling4.GetArea() ) ) dwelling4.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( dwelling5.GetArea() ) ) dwelling5.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( dwelling6.GetArea() ) ) dwelling6.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingMageGuild.GetArea() ) ) buildingMageGuild.SetStatusMessage( statusBar ); else if ( !isSkipTavernInteraction && le.isMouseCursorPosInArea( buildingTavern.GetArea() ) ) buildingTavern.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingThievesGuild.GetArea() ) ) buildingThievesGuild.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingShipyard.GetArea() ) ) buildingShipyard.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingStatue.GetArea() ) ) buildingStatue.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingMarketplace.GetArea() ) ) buildingMarketplace.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingWell.GetArea() ) ) buildingWell.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingWel2.GetArea() ) ) buildingWel2.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingSpec.GetArea() ) ) buildingSpec.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingLTurret.GetArea() ) ) buildingLTurret.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingRTurret.GetArea() ) ) buildingRTurret.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingMoat.GetArea() ) ) buildingMoat.SetStatusMessage( statusBar ); else if ( le.isMouseCursorPosInArea( buildingCaptain.GetArea() ) ) buildingCaptain.SetStatusMessage( statusBar ); else if ( hero1 && le.isMouseCursorPosInArea( rectHero1 ) ) { if ( !allow_buy_hero1 ) statusBar.ShowMessage( not_allow1_msg ); else { std::string str = _( "Recruit %{name} the %{race}" ); StringReplace( str, "%{name}", hero1->GetName() ); StringReplace( str, "%{race}", Race::String( hero1->GetRace() ) ); statusBar.ShowMessage( str ); } } else if ( hero2 && le.isMouseCursorPosInArea( rectHero2 ) ) { if ( !allow_buy_hero2 ) statusBar.ShowMessage( not_allow2_msg ); else { std::string str = _( "Recruit %{name} the %{race}" ); StringReplace( str, "%{name}", hero2->GetName() ); StringReplace( str, "%{race}", Race::String( hero2->GetRace() ) ); statusBar.ShowMessage( str ); } } else if ( isCaptainBuilt && le.isMouseCursorPosInArea( rectSpreadArmyFormat ) ) statusBar.ShowMessage( _( "Set garrison combat formation to 'Spread'" ) ); else if ( isCaptainBuilt && le.isMouseCursorPosInArea( rectGroupedArmyFormat ) ) statusBar.ShowMessage( _( "Set garrison combat formation to 'Grouped'" ) ); else if ( le.isMouseCursorPosInArea( buttonExit.area() ) ) statusBar.ShowMessage( _( "Exit Castle Options" ) ); else if ( le.isMouseCursorPosInArea( resActiveArea ) ) statusBar.ShowMessage( _( "Show Income" ) ); else if ( buttonPrevCastle.isEnabled() && le.isMouseCursorPosInArea( buttonPrevCastle.area() ) ) { statusBar.ShowMessage( _( "Show previous town" ) ); } else if ( buttonNextCastle.isEnabled() && le.isMouseCursorPosInArea( buttonNextCastle.area() ) ) { statusBar.ShowMessage( _( "Show next town" ) ); } else { statusBar.ShowMessage( _( "Castle Options" ) ); } } return ConstructionDialogResult::DoNothing; } fheroes2-1.1.6+dfsg/src/fheroes2/castle/castle_well.cpp000066400000000000000000000573151476115357100227610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "army_troop.h" #include "battle_cell.h" #include "castle.h" // IWYU pragma: associated #include "cursor.h" #include "dialog.h" #include "game_delays.h" #include "game_hotkeys.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "math_base.h" #include "monster.h" #include "monster_anim.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "speed.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" namespace { const int32_t bottomBarOffsetY = 461; const std::array castleDwellings = { DWELLING_MONSTER1, DWELLING_MONSTER2, DWELLING_MONSTER3, DWELLING_MONSTER4, DWELLING_MONSTER5, DWELLING_MONSTER6 }; uint32_t howManyRecruitMonster( const Castle & castle, Troops & tempCastleArmy, Troops & tempHeroArmy, const uint32_t dw, const Funds & add, Funds & res ) { const Monster monsters( castle.GetRace(), castle.GetActualDwelling( dw ) ); if ( !tempCastleArmy.CanJoinTroop( monsters ) && !tempHeroArmy.CanJoinTroop( monsters ) ) { return 0; } uint32_t count = castle.getMonstersInDwelling( dw ); Funds payment; const Kingdom & kingdom = castle.GetKingdom(); while ( count ) { payment = monsters.GetCost() * count; res = payment; payment += add; if ( kingdom.AllowPayment( payment ) ) { break; } --count; } if ( count > 0 ) { if ( tempCastleArmy.CanJoinTroop( monsters ) ) { tempCastleArmy.JoinTroop( monsters, count, false ); } else if ( tempHeroArmy.CanJoinTroop( monsters ) ) { tempHeroArmy.JoinTroop( monsters, count, false ); } } return count; } BuildingType getPressedBuildingHotkey() { if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_1 ) ) { return DWELLING_MONSTER1; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_2 ) ) { return DWELLING_MONSTER2; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_3 ) ) { return DWELLING_MONSTER3; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_4 ) ) { return DWELLING_MONSTER4; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_5 ) ) { return DWELLING_MONSTER5; } if ( HotKeyPressEvent( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_6 ) ) { return DWELLING_MONSTER6; } return BUILD_NOTHING; } } bool Castle::_recruitCastleMax( const Troops & currentCastleArmy ) { std::vector totalRecruitmentResult; Funds currentMonsterCost; Funds totalMonstersCost; std::string monstersRecruitedText; Troops tempCastleArmy( currentCastleArmy ); Troops tempGuestArmy; const Heroes * hero = GetHero(); if ( hero ) { tempGuestArmy.Insert( hero->GetArmy().getTroops() ); } // In this loop we should go in reverse order - from strongest monsters to weakest in order to purchase most of the best monsters. for ( size_t id = 0; id < maxNumOfDwellings; ++id ) { const uint32_t dwellingType = castleDwellings[maxNumOfDwellings - id - 1]; const uint32_t recruitableNumber = howManyRecruitMonster( *this, tempCastleArmy, tempGuestArmy, dwellingType, totalMonstersCost, currentMonsterCost ); if ( recruitableNumber == 0 ) { continue; } const Monster recruitableMonster( _race, GetActualDwelling( dwellingType ) ); totalRecruitmentResult.emplace_back( recruitableMonster, recruitableNumber ); totalMonstersCost += currentMonsterCost; monstersRecruitedText += recruitableMonster.GetPluralName( recruitableNumber ); monstersRecruitedText += " : "; monstersRecruitedText += std::to_string( recruitableNumber ); monstersRecruitedText += '\n'; } const fheroes2::FontType normalWhite = fheroes2::FontType::normalWhite(); if ( monstersRecruitedText.empty() ) { bool isCreaturePresent = false; bool canAffordOneCreature = false; for ( const uint32_t dwellingType : castleDwellings ) { if ( getMonstersInDwelling( dwellingType ) > 0 ) { const Monster monsters( _race, dwellingType ); const Funds payment = monsters.GetCost(); if ( GetKingdom().AllowPayment( payment ) ) { canAffordOneCreature = true; } isCreaturePresent = true; break; } } if ( isCreaturePresent ) { if ( !canAffordOneCreature ) { fheroes2::showStandardTextMessage( {}, _( "Not enough resources to recruit creatures." ), Dialog::OK ); } else { fheroes2::showStandardTextMessage( {}, _( "You are unable to recruit at this time, your ranks are full." ), Dialog::OK ); } } else { fheroes2::showStandardTextMessage( {}, _( "No creatures available for purchase." ), Dialog::OK ); } } else if ( fheroes2::showResourceMessage( fheroes2::Text( _( "Recruit Creatures" ), fheroes2::FontType::normalYellow() ), fheroes2::Text( std::move( monstersRecruitedText ), normalWhite ), Dialog::YES | Dialog::NO, totalMonstersCost ) == Dialog::YES ) { for ( const Troop & troop : totalRecruitmentResult ) { RecruitMonster( troop, false ); } return true; } return false; } void Castle::_openWell() { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::ImageRestorer restorer( display, ( display.width() - fheroes2::Display::DEFAULT_WIDTH ) / 2, ( display.height() - fheroes2::Display::DEFAULT_HEIGHT ) / 2, fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT ); const fheroes2::Rect roi = restorer.rect(); const int32_t buttonOffsetY = roi.y + bottomBarOffsetY; // MAX button. fheroes2::Button buttonMax( roi.x, buttonOffsetY, ICN::BUTTON_WELL_MAX, 0, 1 ); // EXIT button. fheroes2::Button buttonExit( roi.x + roi.width - fheroes2::AGG::GetICN( ICN::BUTTON_GUILDWELL_EXIT, 0 ).width(), buttonOffsetY, ICN::BUTTON_GUILDWELL_EXIT, 0, 1 ); const std::array rectMonster = { fheroes2::Rect( roi.x + 20, roi.y + 18, 288, 124 ), fheroes2::Rect( roi.x + 20, roi.y + 168, 288, 124 ), fheroes2::Rect( roi.x + 20, roi.y + 318, 288, 124 ), fheroes2::Rect( roi.x + 334, roi.y + 18, 288, 124 ), fheroes2::Rect( roi.x + 334, roi.y + 168, 288, 124 ), fheroes2::Rect( roi.x + 334, roi.y + 318, 288, 124 ) }; const std::array castleMonster = { Monster( _race, GetActualDwelling( castleDwellings[0] ) ), Monster( _race, GetActualDwelling( castleDwellings[1] ) ), Monster( _race, GetActualDwelling( castleDwellings[2] ) ), Monster( _race, GetActualDwelling( castleDwellings[3] ) ), Monster( _race, GetActualDwelling( castleDwellings[4] ) ), Monster( _race, GetActualDwelling( castleDwellings[5] ) ) }; std::array monsterAnimInfo = { fheroes2::RandomMonsterAnimation( castleMonster[0] ), fheroes2::RandomMonsterAnimation( castleMonster[1] ), fheroes2::RandomMonsterAnimation( castleMonster[2] ), fheroes2::RandomMonsterAnimation( castleMonster[3] ), fheroes2::RandomMonsterAnimation( castleMonster[4] ), fheroes2::RandomMonsterAnimation( castleMonster[5] ) }; fheroes2::Image background; background._disableTransformLayer(); background.resize( roi.width, roi.height ); _wellRedrawBackground( background ); LocalEvent & le = LocalEvent::Get(); Game::passAnimationDelay( Game::CASTLE_UNIT_DELAY ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::CASTLE_UNIT_DELAY } ) ) ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); buttonMax.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMax.area() ) ); const BuildingType pressedHotkeyBuildingID = getPressedBuildingHotkey(); if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.MouseClickLeft( buttonMax.area() ) || HotKeyPressEvent( Game::HotKeyEvent::TOWN_WELL_BUY_ALL ) ) { const Troops & currentArmy = GetArmy(); if ( _recruitCastleMax( currentArmy ) ) { // Update available monster count on background. for ( const uint32_t dwellingType : castleDwellings ) { _wellRedrawAvailableMonsters( dwellingType, true, background ); } } } for ( size_t dwellingId = 0; dwellingId < maxNumOfDwellings; ++dwellingId ) { if ( _constructedBuildings & castleDwellings[dwellingId] ) { if ( le.MouseClickLeft( rectMonster[dwellingId] ) || pressedHotkeyBuildingID == castleDwellings[dwellingId] ) { if ( RecruitMonster( Dialog::RecruitMonster( castleMonster[dwellingId], _dwelling[dwellingId], true, 2 ) ) ) { // Update available monster count on background. _wellRedrawAvailableMonsters( castleDwellings[dwellingId], true, background ); } break; } if ( le.isMouseRightButtonPressedInArea( rectMonster[dwellingId] ) ) { Dialog::DwellingInfo( castleMonster[dwellingId], _dwelling[dwellingId] ); break; } } } if ( Game::validateAnimationDelay( Game::CASTLE_UNIT_DELAY ) ) { fheroes2::Copy( background, 0, 0, display, roi.x, roi.y, roi.width, roi.height ); _wellRedrawMonsterAnimation( roi, monsterAnimInfo ); buttonMax.draw(); buttonExit.draw(); display.render( roi ); } if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), Dialog::ZERO ); } if ( le.isMouseRightButtonPressedInArea( buttonMax.area() ) ) { fheroes2::showStandardTextMessage( _( "Max" ), _( "Hire all creatures in the town." ), Dialog::ZERO ); } } } void Castle::_wellRedrawAvailableMonsters( const uint32_t dwellingType, const bool restoreBackground, fheroes2::Image & background ) const { if ( !( _constructedBuildings & dwellingType ) ) { // This building has not been built. return; } uint32_t population = 0; fheroes2::Point offset{ 20, 121 }; switch ( dwellingType ) { case DWELLING_MONSTER1: population = _dwelling[0]; break; case DWELLING_MONSTER2: population = _dwelling[1]; offset.y += 150; break; case DWELLING_MONSTER3: population = _dwelling[2]; offset.y += 300; break; case DWELLING_MONSTER4: offset.x += 314; population = _dwelling[3]; break; case DWELLING_MONSTER5: population = _dwelling[4]; offset.x += 314; offset.y += 150; break; case DWELLING_MONSTER6: population = _dwelling[5]; offset.x += 314; offset.y += 300; break; default: // Have you added a new dwelling? assert( 0 ); break; } if ( restoreBackground ) { // Restore background under "Available: " text. const fheroes2::Sprite & wellBackground = fheroes2::AGG::GetICN( Settings::Get().isEvilInterfaceEnabled() ? ICN::WELLBKG_EVIL : ICN::WELLBKG, 0 ); fheroes2::Copy( wellBackground, offset.x, offset.y, background, offset.x, offset.y, 137, fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) ); } std::string textString = _( "Available" ); textString += ": "; fheroes2::Text text( std::move( textString ), fheroes2::FontType::smallWhite() ); text.draw( offset.x + 24, offset.y + 2, background ); text.set( std::to_string( population ), fheroes2::FontType::normalYellow() ); text.draw( offset.x + 109 - text.width() / 2, offset.y, background ); } void Castle::_wellRedrawBackground( fheroes2::Image & background ) const { const fheroes2::Sprite & wellBackground = fheroes2::AGG::GetICN( Settings::Get().isEvilInterfaceEnabled() ? ICN::WELLBKG_EVIL : ICN::WELLBKG, 0 ); const int32_t backgroundWidth = wellBackground.width(); fheroes2::Copy( wellBackground, 0, 0, background, 0, 0, backgroundWidth, bottomBarOffsetY ); // TODO: Make Well bottom bar and buttons for Evil interface. // The original ICN::WELLBKG image has incorrect bottom message bar with no yellow outline. Also the original graphics did not have MAX button. const fheroes2::Sprite & bottomBar = fheroes2::AGG::GetICN( ICN::SMALLBAR, 0 ); const int32_t barHeight = bottomBar.height(); const int32_t exitWidth = fheroes2::AGG::GetICN( ICN::BUTTON_GUILDWELL_EXIT, 0 ).width(); const int32_t buttonMaxWidth = fheroes2::AGG::GetICN( ICN::BUTTON_WELL_MAX, 0 ).width(); // ICN::SMALLBAR image's first column contains all black pixels. This should not be drawn. fheroes2::Copy( bottomBar, 1, 0, background, buttonMaxWidth, bottomBarOffsetY, backgroundWidth / 2 - buttonMaxWidth, barHeight ); fheroes2::Copy( bottomBar, bottomBar.width() - backgroundWidth / 2 + exitWidth - 1, 0, background, backgroundWidth / 2, bottomBarOffsetY, backgroundWidth / 2 - exitWidth + 1, barHeight ); // The original assets Well background has a transparent line to the right of EXIT button and it is not covered by any other image. Fill it with the black color. fheroes2::Fill( background, background.width() - 1, bottomBarOffsetY, 1, bottomBar.height(), static_cast( 0 ) ); fheroes2::Text text( _( "Town Population Information and Statistics" ), fheroes2::FontType::normalWhite() ); text.draw( 315 - text.width() / 2, bottomBarOffsetY + 3, background ); const fheroes2::FontType statsFontType = fheroes2::FontType::smallWhite(); for ( const uint32_t dwellingType : castleDwellings ) { // By default the 'icnIndex' and 'offset' values are set for DWELLING_MONSTER1. uint32_t icnIndex = 19; fheroes2::Point offset{ 0, 1 }; switch ( dwellingType ) { case DWELLING_MONSTER1: break; case DWELLING_MONSTER2: offset.y = 151; icnIndex = DWELLING_UPGRADE2 & _constructedBuildings ? 25 : 20; break; case DWELLING_MONSTER3: offset.y = 301; icnIndex = DWELLING_UPGRADE3 & _constructedBuildings ? 26 : 21; break; case DWELLING_MONSTER4: offset.x = 314; icnIndex = DWELLING_UPGRADE4 & _constructedBuildings ? 27 : 22; break; case DWELLING_MONSTER5: offset.x = 314; offset.y = 151; icnIndex = DWELLING_UPGRADE5 & _constructedBuildings ? 28 : 23; break; case DWELLING_MONSTER6: offset.x = 314; offset.y = 301; icnIndex = DWELLING_UPGRADE7 & _constructedBuildings ? 30 : ( DWELLING_UPGRADE6 & _constructedBuildings ? 29 : 24 ); break; default: // Have you added a new dwelling? assert( 0 ); break; } const uint32_t actualDwellindType = GetActualDwelling( dwellingType ); const Monster monster( _race, actualDwellindType ); // Dwelling building image. fheroes2::Point renderPoint( offset.x + 21, offset.y + 35 ); const fheroes2::Sprite & dwellingImage = fheroes2::AGG::GetICN( ICN::getBuildingIcnId( _race ), icnIndex ); fheroes2::Copy( dwellingImage, 0, 0, background, renderPoint.x, renderPoint.y, dwellingImage.width(), dwellingImage.height() ); // Dwelling name. text.set( GetStringBuilding( actualDwellindType, _race ), statsFontType ); renderPoint.x = offset.x + 86 - text.width() / 2; renderPoint.y = offset.y + 104; text.draw( renderPoint.x, renderPoint.y, background ); // Creature name. text.set( monster.GetMultiName(), statsFontType ); renderPoint.x = offset.x + 122 - text.width() / 2; renderPoint.y = offset.y + 19; text.draw( renderPoint.x, renderPoint.y, background ); // attack std::string textString; textString = _( "Attack" ); textString += ": "; textString += std::to_string( monster.GetAttack() ); text.set( textString, statsFontType ); // Set initial X and Y offset. renderPoint.x = offset.x + 269; renderPoint.y = offset.y + 22; text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); renderPoint.y += text.height( text.width() ); // defense textString = _( "Defense" ); textString += ": "; textString += std::to_string( monster.GetDefense() ); text.set( textString, statsFontType ); text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); renderPoint.y += text.height( text.width() ); // damage textString = _( "Damage" ); textString += ": "; const uint32_t monsterMinDamage = monster.GetDamageMin(); const uint32_t monsterMaxDamage = monster.GetDamageMax(); textString += std::to_string( monsterMinDamage ); if ( monsterMinDamage != monsterMaxDamage ) { textString += '-'; textString += std::to_string( monsterMaxDamage ); } text.set( textString, statsFontType ); text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); renderPoint.y += text.height( text.width() ); // hp textString = _( "HP" ); textString += ": "; textString += std::to_string( monster.GetHitPoints() ); text.set( textString, statsFontType ); text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); renderPoint.y += 2 * ( text.height( text.width() ) ); // skip a line // speed textString = _( "Speed" ); textString += ':'; text.set( textString, statsFontType ); text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); renderPoint.y += text.height( text.width() ); text.set( Speed::String( static_cast( monster.GetSpeed() ) ), statsFontType ); text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); renderPoint.y += 2 * ( text.height( text.width() ) ); // skip a line // If dwelling is built show growth and available population. if ( _constructedBuildings & dwellingType ) { uint32_t monsterGrown = monster.GetGrown(); monsterGrown += _constructedBuildings & BUILD_WELL ? GetGrownWell() : 0; if ( DWELLING_MONSTER1 & dwellingType ) { monsterGrown += _constructedBuildings & BUILD_WEL2 ? GetGrownWel2() : 0; } text.set( _( "Growth" ), statsFontType ); text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); renderPoint.y += text.height( text.width() ); textString = "+ "; textString += std::to_string( monsterGrown ); textString += " / "; textString += _( "week" ); text.set( textString, statsFontType ); text.draw( renderPoint.x - text.width() / 2, renderPoint.y, background ); _wellRedrawAvailableMonsters( dwellingType, false, background ); } } } void Castle::_wellRedrawMonsterAnimation( const fheroes2::Rect & roi, std::array & monsterAnimInfo ) const { fheroes2::Display & display = fheroes2::Display::instance(); for ( size_t monsterId = 0; monsterId < maxNumOfDwellings; ++monsterId ) { fheroes2::Point outPos( roi.x, roi.y + 1 ); switch ( monsterId ) { case 0: break; case 1: outPos.y += 150; break; case 2: outPos.y += 300; break; case 3: outPos.x += 314; break; case 4: outPos.x += 314; outPos.y += 150; break; case 5: outPos.x += 314; outPos.y += 300; break; default: // Have you added a new dwelling? assert( 0 ); break; } const Monster monster( _race, GetActualDwelling( castleDwellings[monsterId] ) ); // monster const bool flipMonsterSprite = ( monsterId > 2 ); const fheroes2::Sprite & smonster = fheroes2::AGG::GetICN( monsterAnimInfo[monsterId].icnFile(), monsterAnimInfo[monsterId].frameId() ); if ( flipMonsterSprite ) { outPos.x += 193 - ( smonster.x() + smonster.width() ) + ( monster.isWide() ? Battle::Cell::widthPx / 2 : 0 ) + monsterAnimInfo[monsterId].offset(); } else { outPos.x += 193 + smonster.x() - ( monster.isWide() ? Battle::Cell::widthPx / 2 : 0 ) - monsterAnimInfo[monsterId].offset(); } outPos.y += 124 + smonster.y(); fheroes2::Point inPos( 0, 0 ); fheroes2::Size inSize( smonster.width(), smonster.height() ); if ( fheroes2::FitToRoi( smonster, inPos, display, outPos, inSize, roi ) ) { fheroes2::Blit( smonster, inPos, display, outPos, inSize, flipMonsterSprite ); } monsterAnimInfo[monsterId].increment(); } } fheroes2-1.1.6+dfsg/src/fheroes2/castle/mageguild.cpp000066400000000000000000000151301476115357100224060ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "mageguild.h" #include #include #include #include #include #include #include #include "heroes_base.h" #include "race.h" #include "rand.h" #include "serialize.h" #include "spell.h" #include "tools.h" namespace { Spell getGuaranteedDamageSpell() { const uint32_t rand = Rand::Get( 0, 100 ); if ( rand < 20 ) { return Spell::ARROW; } if ( rand < 40 ) { return Spell::LIGHTNINGBOLT; } if ( rand < 60 ) { return Spell::FIREBALL; } if ( rand < 80 ) { return Spell::COLDRAY; } return Spell::COLDRING; } Spell getGuaranteedCancellationSpell() { const uint32_t rand = Rand::Get( 0, 100 ); if ( rand < 25 ) { return Spell::DISPEL; } if ( rand < 50 ) { return Spell::MASSDISPEL; } if ( rand < 75 ) { return Spell::ANTIMAGIC; } return Spell::CURE; } } void MageGuild::initialize( const int race, const bool hasLibrary ) { assert( CountBits( race ) == 1 && ( race & Race::ALL ) ); general.clear(); library.clear(); std::set spellsInUse; struct MageGuildLevelProps { int freeSlots = 0; bool hasAdventureSpell = false; }; std::array mageGuildLevels = { { { 3, false }, { 3, false }, { 2, false }, { 2, false }, { 1, false } } }; if ( hasLibrary ) { for ( auto & [freeSlots, dummy] : mageGuildLevels ) { ++freeSlots; } } const auto addSpell = [this, hasLibrary, &spellsInUse, &mageGuildLevels]( const Spell & spell ) { const size_t spellLevel = fheroes2::checkedCast( spell.Level() ).value(); assert( spellLevel > 0 && spellLevel <= mageGuildLevels.size() ); auto & [freeSlots, hasAdventureSpell] = mageGuildLevels[spellLevel - 1]; assert( freeSlots > 0 ); // Check for possible duplicates if ( const auto [dummy, inserted] = spellsInUse.insert( spell ); !inserted ) { return; } if ( hasLibrary && freeSlots == 1 ) { library.Append( spell ); } else { general.Append( spell ); } --freeSlots; if ( spell.isAdventure() ) { assert( !hasAdventureSpell ); hasAdventureSpell = true; } }; // Mage Guild must always have one of the specific damage spells... addSpell( getGuaranteedDamageSpell() ); // ... as well as one of the specific "spell cancellation" spells addSpell( getGuaranteedCancellationSpell() ); for ( size_t level = 1; level <= mageGuildLevels.size(); ++level ) { const auto & [freeSlots, hasAdventureSpell] = mageGuildLevels[level - 1]; std::vector allSpellsOfLevel = Spell::getAllSpellIdsSuitableForSpellBook( fheroes2::checkedCast( level ).value() ); while ( freeSlots > 0 ) { assert( !allSpellsOfLevel.empty() ); const uint32_t spellIdx = Rand::Get( 0, fheroes2::checkedCast( allSpellsOfLevel.size() - 1 ).value() ); const Spell spell( allSpellsOfLevel[spellIdx] ); // Some spells may occur less frequently in Mage Guilds than others, depending on race if ( Rand::Get( 0, 10 ) > spell.weightForRace( race ) ) { continue; } // There can only be one adventure spell at each level of the Mage Guild if ( !hasAdventureSpell || !spell.isAdventure() ) { addSpell( spell ); } allSpellsOfLevel.erase( allSpellsOfLevel.begin() + spellIdx ); } } } SpellStorage MageGuild::GetSpells( int guildLevel, bool hasLibrary, int spellLevel ) const { SpellStorage result; if ( spellLevel == -1 ) { // Get all available spells for ( int level = 1; level <= guildLevel; ++level ) { result.Append( general.GetSpells( level ) ); if ( hasLibrary ) { result.Append( library.GetSpells( level ) ); } } } else if ( spellLevel <= guildLevel ) { result = general.GetSpells( spellLevel ); if ( hasLibrary ) { result.Append( library.GetSpells( spellLevel ) ); } } return result; } void MageGuild::educateHero( HeroBase & hero, int guildLevel, bool hasLibrary ) const { if ( hero.HaveSpellBook() && guildLevel > 0 ) { // This method will test the hero for compliance with the wisdom requirements hero.AppendSpellsToBook( MageGuild::GetSpells( guildLevel, hasLibrary ) ); } } OStreamBase & operator<<( OStreamBase & stream, const MageGuild & guild ) { return stream << guild.general << guild.library; } IStreamBase & operator>>( IStreamBase & stream, MageGuild & guild ) { return stream >> guild.general >> guild.library; } fheroes2-1.1.6+dfsg/src/fheroes2/castle/mageguild.h000066400000000000000000000047561476115357100220670ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include "spell_storage.h" class IStreamBase; class OStreamBase; class HeroBase; class MageGuild { public: MageGuild() = default; // Initializes the Mage Guild according to the rules described in // https://handbookhmm.ru/kakim-obrazom-zaklinaniya-popadayut-v-magicheskuyu-gildiyu.html // except for the part related to the hidden AI-only bonuses. void initialize( const int race, const bool hasLibrary ); void educateHero( HeroBase & hero, int guildLevel, bool hasLibrary ) const; SpellStorage GetSpells( int guildLevel, bool hasLibrary, int spellLevel = -1 ) const; private: friend OStreamBase & operator<<( OStreamBase & stream, const MageGuild & guild ); friend IStreamBase & operator>>( IStreamBase & stream, MageGuild & guild ); SpellStorage general; SpellStorage library; }; fheroes2-1.1.6+dfsg/src/fheroes2/dialog/000077500000000000000000000000001476115357100177305ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog.h000066400000000000000000000202311476115357100213360ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "game_mode.h" #include "image.h" #include "math_base.h" #include "ui_constants.h" class Castle; class Kingdom; class HeroBase; class Heroes; class Monster; class Troop; struct ArtifactSetData; namespace fheroes2 { class DialogElement; class TextBase; enum class SupportedLanguage : uint8_t; } namespace Skill { class Secondary; } namespace Maps { class Tile; } namespace Dialog { enum { ZERO = 0x0000, YES = 0x0001, OK = 0x0002, NO = 0x0004, CANCEL = 0x0008, DISMISS = 0x0010, UPGRADE = 0x0020, MAX = 0x0040, PREV = 0x0080, NEXT = 0x0100, WORLD = 0x0200, PUZZLE = 0x0400, INFO = 0x0800, DIG = 0x1000, UPGRADE_DISABLE = MAX, BUTTONS = ( YES | OK | NO | CANCEL ) }; int AdventureOptions( const bool enableDig ); fheroes2::GameMode FileOptions(); std::string SelectFileLoad(); std::string SelectFileSave(); // Shows the quick info window for the given tile void QuickInfo( const Maps::Tile & tile ); // Shows the quick info window for the given castle void QuickInfo( const Castle & castle ); // Shows the quick info window for the given hero or captain. If the 'showFullInfo' parameter is specified, // then whether full or abbreviated information will be displayed is determined according to its value, // otherwise it is determined by the internal logic of this function. See the implementation for details. void QuickInfo( const HeroBase & hero, const std::optional showFullInfo = {} ); // Shows the quick info window for the given castle, and also indicates the location of this castle on the radar. // 'areaToRestore' defines the area whose contents should be restored when the radar is redrawn. void QuickInfoWithIndicationOnRadar( const Castle & castle, const fheroes2::Rect & areaToRestore ); // Shows the quick info window for the given hero, and also indicates the location of this hero on the radar. // 'areaToRestore' defines the area whose contents should be restored when the radar is redrawn. void QuickInfoWithIndicationOnRadar( const HeroBase & hero, const fheroes2::Rect & areaToRestore ); // Shows the quick info window for the given castle at the given position on the screen, and also indicates the // location of this castle on the radar. void QuickInfoAtPosition( const Castle & castle, const fheroes2::Point & position ); // Shows the quick info window for the given hero at the given position on the screen, and also indicates the // location of this hero on the radar. void QuickInfoAtPosition( const HeroBase & hero, const fheroes2::Point & position ); int LevelUpSelectSkill( const std::string & name, const int primarySkillType, const Skill::Secondary & sec1, const Skill::Secondary & sec2, Heroes & hero ); bool SelectGoldOrExp( const std::string &, const std::string &, uint32_t gold, uint32_t expr, const Heroes & ); int SelectSkillFromArena(); bool SelectCount( std::string header, const int32_t min, const int32_t max, int32_t & selectedValue, const int32_t step = 1, const fheroes2::DialogElement * uiElement = nullptr ); // If character limit is set to 0, then no limitation for the resulting string will be applied. bool inputString( const fheroes2::TextBase & title, const fheroes2::TextBase & body, std::string & result, const size_t charLimit, const bool isMultiLine, const std::optional & textLanguage ); Troop RecruitMonster( const Monster & monster0, const uint32_t available, const bool allowDowngradedMonster, const int32_t windowOffsetY ); void DwellingInfo( const Monster &, const uint32_t available ); int ArmyInfo( const Troop & troop, int flags, bool isReflected = false, const int32_t windowOffsetY = 0 ); int ArmyJoinFree( const Troop & troop ); int ArmyJoinWithCost( const Troop &, const uint32_t join, const uint32_t gold ); int ArmySplitTroop( const int32_t freeSlots, const int32_t redistributeMax, int32_t & redistributeCount, bool & useFastSplit, const std::string & troopName ); void Marketplace( Kingdom & kingdom, bool fromTradingPost ); void MakeGiftResource( Kingdom & kingdom ); int BuyBoat( bool enable ); void ThievesGuild( const bool oracle ); void GameInfo(); // Displays a dialog box informing that an artifact set has been assembled void ArtifactSetAssembled( const ArtifactSetData & artifactSetData ); class NonFixedFrameBox { public: explicit NonFixedFrameBox( int height = 0, int startYPos = -1, bool showButtons = false ); virtual ~NonFixedFrameBox(); const fheroes2::Rect & GetArea() const { return area; } void redraw(); static int32_t getButtonAreaHeight(); protected: std::unique_ptr _restorer; fheroes2::Rect area; private: fheroes2::Point _position; uint32_t _middleFragmentCount; int32_t _middleFragmentHeight; }; class FrameBox : public NonFixedFrameBox { public: FrameBox( int height, bool buttons = false ) : Dialog::NonFixedFrameBox( height, -1, buttons ) { // Do nothing. } ~FrameBox() override = default; }; class FrameBorder { public: explicit FrameBorder( int v = fheroes2::borderWidthPx ); int BorderWidth() const { return border; } int BorderHeight() const { return border; } void SetPosition( int32_t posx, int32_t posy, int32_t encw, int32_t ench ); bool isValid() const { return rect.width != 0 && rect.height != 0; } const fheroes2::Rect & GetRect() const { return rect; } const fheroes2::Rect & GetArea() const { return area; } const fheroes2::Rect & GetTop() const { return top; } static void RenderRegular( const fheroes2::Rect & dstrt ); static void RenderOther( const fheroes2::Image &, const fheroes2::Rect & ); protected: fheroes2::ImageRestorer restorer; private: fheroes2::Rect rect; fheroes2::Rect area; fheroes2::Rect top; int border; }; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_adventure.cpp000066400000000000000000000151021476115357100237470ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "icn.h" #include "localevent.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_window.h" namespace { int selectAdventureOption( const bool enableDig ) { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 289, 204, true, display ); fheroes2::Button buttonWorld; fheroes2::Button buttonPuzzle; fheroes2::Button buttonInfo; fheroes2::Button buttonDig; fheroes2::Button buttonCancel; const int32_t largeButtonsXOffset = 30; const int32_t largeButtonsYOffset = 15; const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int apanel = isEvilInterface ? ICN::APANELE : ICN::APANEL; background.renderButton( buttonWorld, apanel, 0, 1, { largeButtonsXOffset, largeButtonsYOffset }, fheroes2::StandardWindow::Padding::TOP_LEFT ); background.renderButton( buttonPuzzle, apanel, 2, 3, { largeButtonsXOffset, largeButtonsYOffset }, fheroes2::StandardWindow::Padding::TOP_RIGHT ); background.renderButton( buttonInfo, isEvilInterface ? ICN::BUTTON_INFO_EVIL : ICN::BUTTON_INFO_GOOD, 0, 1, { largeButtonsXOffset, largeButtonsYOffset + 2 }, fheroes2::StandardWindow::Padding::CENTER_LEFT ); background.renderButton( buttonDig, apanel, 6, 7, { largeButtonsXOffset, largeButtonsYOffset + 2 }, fheroes2::StandardWindow::Padding::CENTER_RIGHT ); background.renderButton( buttonCancel, isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); if ( !enableDig ) { buttonDig.disable(); buttonDig.draw(); } display.render( background.totalArea() ); int result = Dialog::ZERO; LocalEvent & le = LocalEvent::Get(); // dialog menu loop while ( le.HandleEvents() ) { buttonWorld.drawOnState( le.isMouseLeftButtonPressedInArea( buttonWorld.area() ) ); buttonPuzzle.drawOnState( le.isMouseLeftButtonPressedInArea( buttonPuzzle.area() ) ); buttonInfo.drawOnState( le.isMouseLeftButtonPressedInArea( buttonInfo.area() ) ); buttonDig.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDig.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonWorld.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_VIEW_WORLD ) ) { result = Dialog::WORLD; break; } if ( le.MouseClickLeft( buttonPuzzle.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_PUZZLE_MAP ) ) { result = Dialog::PUZZLE; break; } if ( le.MouseClickLeft( buttonInfo.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCENARIO_INFORMATION ) ) { result = Dialog::INFO; break; } if ( enableDig && ( le.MouseClickLeft( buttonDig.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_DIG_ARTIFACT ) ) ) { result = Dialog::DIG; break; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyCloseWindow() ) { result = Dialog::CANCEL; break; } // right info if ( le.isMouseRightButtonPressedInArea( buttonWorld.area() ) ) fheroes2::showStandardTextMessage( _( "View World" ), _( "View the entire world." ), Dialog::ZERO ); else if ( le.isMouseRightButtonPressedInArea( buttonPuzzle.area() ) ) fheroes2::showStandardTextMessage( _( "Puzzle" ), _( "View the obelisk puzzle." ), Dialog::ZERO ); else if ( le.isMouseRightButtonPressedInArea( buttonInfo.area() ) ) fheroes2::showStandardTextMessage( _( "Scenario Information" ), _( "View information on the scenario you are currently playing." ), Dialog::ZERO ); else if ( le.isMouseRightButtonPressedInArea( buttonDig.area() ) ) fheroes2::showStandardTextMessage( _( "Digging" ), _( "Dig for the Ultimate Artifact." ), Dialog::ZERO ); else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } return result; } } int Dialog::AdventureOptions( const bool enableDig ) { const int result = selectAdventureOption( enableDig ); return result; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_arena.cpp000066400000000000000000000213171476115357100230450ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" namespace { void InfoSkillClear( const fheroes2::Rect & rect1, const fheroes2::Rect & rect2, const fheroes2::Rect & rect3 ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::XPRIMARY, 0 ), display, rect1.x, rect1.y ); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::XPRIMARY, 1 ), display, rect2.x, rect2.y ); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::XPRIMARY, 2 ), display, rect3.x, rect3.y ); } void InfoSkillSelect( int skill, const fheroes2::Rect & rect1, const fheroes2::Rect & rect2, const fheroes2::Rect & rect3 ) { fheroes2::Display & display = fheroes2::Display::instance(); switch ( skill ) { case Skill::Primary::ATTACK: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::XPRIMARY, 4 ), display, rect1.x, rect1.y ); break; case Skill::Primary::DEFENSE: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::XPRIMARY, 5 ), display, rect2.x, rect2.y ); break; case Skill::Primary::POWER: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::XPRIMARY, 6 ), display, rect3.x, rect3.y ); break; default: break; } } int InfoSkillNext( int skill ) { switch ( skill ) { case Skill::Primary::ATTACK: return Skill::Primary::DEFENSE; case Skill::Primary::DEFENSE: return Skill::Primary::POWER; default: break; } return Skill::Primary::UNKNOWN; } int InfoSkillPrev( int skill ) { switch ( skill ) { case Skill::Primary::POWER: return Skill::Primary::DEFENSE; case Skill::Primary::DEFENSE: return Skill::Primary::ATTACK; default: break; } return Skill::Primary::UNKNOWN; } } int Dialog::SelectSkillFromArena() { fheroes2::Display & display = fheroes2::Display::instance(); const int system = Settings::Get().isEvilInterfaceEnabled() ? ICN::SYSTEME : ICN::SYSTEM; // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Text title( _( "Arena" ), fheroes2::FontType::normalYellow() ); fheroes2::Text textbox( _( "You enter the arena and face a pack of vicious lions. You handily defeat them, to the wild cheers of the crowd. Impressed by your skill, the aged trainer of gladiators agrees to train you in a skill of your choice." ), fheroes2::FontType::normalWhite() ); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::XPRIMARY, 0 ); const int spacer = 10; const Dialog::FrameBox box( title.height( fheroes2::boxAreaWidthPx ) + textbox.height( fheroes2::boxAreaWidthPx ) + 2 * spacer + sprite.height() + 15, true ); const fheroes2::Rect & box_rt = box.GetArea(); fheroes2::Point dst_pt( box_rt.x, box_rt.y ); title.draw( dst_pt.x, dst_pt.y + 2, fheroes2::boxAreaWidthPx, display ); dst_pt.y += title.height( fheroes2::boxAreaWidthPx ) + spacer; textbox.draw( dst_pt.x, dst_pt.y + 2, fheroes2::boxAreaWidthPx, display ); dst_pt.y += textbox.height( fheroes2::boxAreaWidthPx ) + spacer; int res = Skill::Primary::ATTACK; const int spacingX = ( box_rt.width - sprite.width() * 3 ) / 4; fheroes2::Rect rect1( dst_pt.x + spacingX, dst_pt.y, sprite.width(), sprite.height() ); fheroes2::Rect rect2( rect1.x + sprite.width() + spacingX, dst_pt.y, sprite.width(), sprite.height() ); fheroes2::Rect rect3( rect2.x + sprite.width() + spacingX, dst_pt.y, sprite.width(), sprite.height() ); InfoSkillClear( rect1, rect2, rect3 ); InfoSkillSelect( res, rect1, rect2, rect3 ); // info texts const int32_t skillTextWidth = 60; fheroes2::Text text( Skill::Primary::String( Skill::Primary::ATTACK ), fheroes2::FontType::smallWhite() ); dst_pt.x = rect1.x + ( rect1.width - skillTextWidth ) / 2; dst_pt.y = rect1.y + rect1.height + 5; text.draw( dst_pt.x, dst_pt.y + 2, skillTextWidth, display ); text.set( Skill::Primary::String( Skill::Primary::DEFENSE ), fheroes2::FontType::smallWhite() ); dst_pt.x = rect2.x + ( rect2.width - skillTextWidth ) / 2; dst_pt.y = rect2.y + rect2.height + 5; text.draw( dst_pt.x, dst_pt.y + 2, skillTextWidth, display ); text.set( Skill::Primary::String( Skill::Primary::POWER ), fheroes2::FontType::smallWhite() ); dst_pt.x = rect3.x + ( rect3.width - skillTextWidth ) / 2; dst_pt.y = rect3.y + rect3.height + 5; text.draw( dst_pt.x, dst_pt.y + 2, skillTextWidth, display ); // buttons dst_pt.x = box_rt.x + ( box_rt.width - fheroes2::AGG::GetICN( system, 1 ).width() ) / 2; dst_pt.y = box_rt.y + box_rt.height - fheroes2::AGG::GetICN( system, 1 ).height(); fheroes2::Button buttonOk( dst_pt.x, dst_pt.y, system, 1, 2 ); LocalEvent & le = LocalEvent::Get(); buttonOk.draw(); display.render(); // message loop while ( le.HandleEvents() ) { bool redraw = false; buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_LEFT ) && Skill::Primary::UNKNOWN != InfoSkillPrev( res ) ) { res = InfoSkillPrev( res ); redraw = true; } else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) && Skill::Primary::UNKNOWN != InfoSkillNext( res ) ) { res = InfoSkillNext( res ); redraw = true; } else if ( le.MouseClickLeft( rect1 ) ) { res = Skill::Primary::ATTACK; redraw = true; } else if ( le.MouseClickLeft( rect2 ) ) { res = Skill::Primary::DEFENSE; redraw = true; } else if ( le.MouseClickLeft( rect3 ) ) { res = Skill::Primary::POWER; redraw = true; } else if ( le.isMouseRightButtonPressedInArea( rect1 ) ) { fheroes2::PrimarySkillDialogElement( Skill::Primary::ATTACK, "" ).showPopup( Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( rect2 ) ) { fheroes2::PrimarySkillDialogElement( Skill::Primary::DEFENSE, "" ).showPopup( Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( rect3 ) ) { fheroes2::PrimarySkillDialogElement( Skill::Primary::POWER, "" ).showPopup( Dialog::ZERO ); } if ( redraw ) { InfoSkillClear( rect1, rect2, rect3 ); InfoSkillSelect( res, rect1, rect2, rect3 ); display.render(); } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( buttonOk.area() ) ) break; } return res; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_armyinfo.cpp000066400000000000000000000744751476115357100236200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "army_troop.h" #include "battle.h" #include "battle_cell.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_delays.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "luck.h" #include "math_base.h" #include "monster.h" #include "monster_anim.h" #include "monster_info.h" #include "morale.h" #include "pal.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "spell.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" namespace { const int offsetXAmountBox = 80; const int offsetYAmountBox = 223; const int widthAmountBox = 125; const int heightAmountBox = 23; struct SpellInfo { SpellInfo( const uint32_t mode_, const uint32_t duration_, const int32_t offset_, const int32_t space_ ) : mode( mode_ ) , duration( duration_ ) , offset( offset_ ) , space( space_ ) {} uint32_t mode; uint32_t duration; int32_t offset; int32_t space; Spell spell; }; Spell modeToSpell( const uint32_t modeId ) { switch ( modeId ) { case Battle::SP_BLOODLUST: return Spell::BLOODLUST; case Battle::SP_BLESS: return Spell::BLESS; case Battle::SP_HASTE: return Spell::HASTE; case Battle::SP_SHIELD: return Spell::SHIELD; case Battle::SP_STONESKIN: return Spell::STONESKIN; case Battle::SP_DRAGONSLAYER: return Spell::DRAGONSLAYER; case Battle::SP_STEELSKIN: return Spell::STEELSKIN; case Battle::SP_ANTIMAGIC: return Spell::ANTIMAGIC; case Battle::SP_CURSE: return Spell::CURSE; case Battle::SP_SLOW: return Spell::SLOW; case Battle::SP_BERSERKER: return Spell::BERSERKER; case Battle::SP_HYPNOTIZE: return Spell::HYPNOTIZE; case Battle::SP_BLIND: return Spell::BLIND; case Battle::SP_PARALYZE: return Spell::PARALYZE; case Battle::SP_STONE: return Spell::PETRIFY; default: // Did you add another mode? Please add a corresponding spell. assert( 0 ); break; } return Spell::NONE; } void DrawMonsterStats( const fheroes2::Point & dst, const Troop & troop ) { fheroes2::Display & display = fheroes2::Display::instance(); // attack fheroes2::Text text( std::string( _( "Attack Skill" ) ) + ":", fheroes2::FontType::normalWhite() ); fheroes2::Point dst_pt{ dst.x - text.width(), dst.y }; text.draw( dst_pt.x, dst_pt.y + 2, display ); const int offsetX = 6; const int offsetY = 16; text.set( troop.GetAttackString(), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); // defense text.set( std::string( _( "Defense Skill" ) ) + ":", fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( troop.GetDefenseString(), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); if ( fheroes2::getMonsterData( troop.GetID() ).battleStats.shots > 0 ) { std::string message = troop.isBattle() ? _( "Shots Left" ) : _( "Shots" ); message += ':'; text.set( std::move( message ), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( troop.GetShotString(), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); } // damage text.set( std::string( _( "Damage" ) ) + ":", fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); if ( troop.GetMonster().GetDamageMin() != troop.GetMonster().GetDamageMax() ) { text.set( std::to_string( troop.GetMonster().GetDamageMin() ) + "-" + std::to_string( troop.GetMonster().GetDamageMax() ), fheroes2::FontType::normalWhite() ); } else { text.set( std::to_string( troop.GetMonster().GetDamageMin() ), fheroes2::FontType::normalWhite() ); } dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); // hp text.set( std::string( _( "Hit Points" ) ) + ":", fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( std::to_string( troop.GetMonster().GetHitPoints() ), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); if ( troop.isBattle() && troop.GetCount() != 0 ) { text.set( std::string( _( "Hit Points Left" ) ) + ":", fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( std::to_string( troop.GetHitPointsLeft() ), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); } // speed text.set( std::string( _( "Speed" ) ) + ":", fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( troop.GetSpeedString(), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); // morale text.set( std::string( _( "Morale" ) ) + ":", fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( Morale::String( troop.GetMorale() ), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); // luck text.set( std::string( _( "Luck" ) ) + ":", fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x - text.width(); dst_pt.y += offsetY; text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( Luck::String( troop.GetLuck() ), fheroes2::FontType::normalWhite() ); dst_pt.x = dst.x + offsetX; text.draw( dst_pt.x, dst_pt.y + 2, display ); } const fheroes2::Sprite & GetModesSprite( const uint32_t mod ) { switch ( mod ) { case Battle::SP_BLOODLUST: return fheroes2::AGG::GetICN( ICN::SPELLINL, 9 ); case Battle::SP_BLESS: return fheroes2::AGG::GetICN( ICN::SPELLINL, 3 ); case Battle::SP_HASTE: return fheroes2::AGG::GetICN( ICN::SPELLINL, 0 ); case Battle::SP_SHIELD: return fheroes2::AGG::GetICN( ICN::SPELLINL, 10 ); case Battle::SP_STONESKIN: return fheroes2::AGG::GetICN( ICN::SPELLINL, 13 ); case Battle::SP_DRAGONSLAYER: return fheroes2::AGG::GetICN( ICN::SPELLINL, 8 ); case Battle::SP_STEELSKIN: return fheroes2::AGG::GetICN( ICN::SPELLINL, 14 ); case Battle::SP_ANTIMAGIC: return fheroes2::AGG::GetICN( ICN::SPELLINL, 12 ); case Battle::SP_CURSE: return fheroes2::AGG::GetICN( ICN::SPELLINL, 4 ); case Battle::SP_SLOW: return fheroes2::AGG::GetICN( ICN::SPELLINL, 1 ); case Battle::SP_BERSERKER: return fheroes2::AGG::GetICN( ICN::SPELLINL, 5 ); case Battle::SP_HYPNOTIZE: return fheroes2::AGG::GetICN( ICN::SPELLINL, 7 ); case Battle::SP_BLIND: return fheroes2::AGG::GetICN( ICN::SPELLINL, 2 ); case Battle::SP_PARALYZE: return fheroes2::AGG::GetICN( ICN::SPELLINL, 6 ); case Battle::SP_STONE: return fheroes2::AGG::GetICN( ICN::SPELLINL, 11 ); default: break; } return fheroes2::AGG::GetICN( ICN::UNKNOWN, 0 ); } std::vector> DrawBattleStats( const fheroes2::Point & dst, const Troop & b ) { std::vector> output; const std::array modes = { Battle::SP_BLOODLUST, Battle::SP_BLESS, Battle::SP_HASTE, Battle::SP_SHIELD, Battle::SP_STONESKIN, Battle::SP_DRAGONSLAYER, Battle::SP_STEELSKIN, Battle::SP_ANTIMAGIC, Battle::SP_CURSE, Battle::SP_SLOW, Battle::SP_BERSERKER, Battle::SP_HYPNOTIZE, Battle::SP_BLIND, Battle::SP_PARALYZE, Battle::SP_STONE }; int32_t ow = 0; int32_t spritesWidth = 0; std::vector spellsInfo; for ( const uint32_t mode : modes ) { if ( !b.isModes( mode ) ) continue; const fheroes2::Sprite & sprite = GetModesSprite( mode ); if ( sprite.empty() ) continue; const uint32_t duration = b.GetAffectedDuration( mode ); int offset = 0; if ( duration > 0 ) { offset = duration >= 10 ? 12 : 7; if ( mode >= Battle::SP_BLESS && mode <= Battle::SP_DRAGONSLAYER ) offset -= 5; } const int space = ( offset == 2 ) ? 10 : 5; spellsInfo.emplace_back( mode, duration, offset, space ); ow += sprite.width() + offset + space; spritesWidth += sprite.width(); } if ( spellsInfo.empty() ) return output; std::sort( spellsInfo.begin(), spellsInfo.end(), []( const SpellInfo & first, const SpellInfo & second ) { return first.duration > 0 && first.duration < second.duration; } ); ow -= spellsInfo.back().space; const int maxSpritesWidth = 212; const int maxSpriteHeight = 32; fheroes2::Display & display = fheroes2::Display::instance(); if ( ow <= maxSpritesWidth ) { ow = dst.x - ow / 2; for ( const auto & spell : spellsInfo ) { const fheroes2::Sprite & sprite = GetModesSprite( spell.mode ); const fheroes2::Point imageOffset( ow, dst.y + maxSpriteHeight - sprite.height() ); fheroes2::Blit( sprite, display, imageOffset.x, imageOffset.y ); output.emplace_back( fheroes2::Rect( imageOffset.x, imageOffset.y, sprite.width(), sprite.height() ), modeToSpell( spell.mode ) ); if ( spell.duration > 0 ) { const fheroes2::Text text( std::to_string( spell.duration ), fheroes2::FontType::smallWhite() ); ow += sprite.width() + spell.offset; text.draw( ow - text.width(), dst.y + maxSpriteHeight - text.height() + 3, display ); } ow += spell.space; } } else { // Too many spells const int widthDiff = maxSpritesWidth - spritesWidth; int space = widthDiff / static_cast( spellsInfo.size() - 1 ); if ( widthDiff > 0 ) { if ( space > 10 ) space = 10; ow = dst.x + ( spritesWidth + space * static_cast( spellsInfo.size() - 1 ) ) / 2; } else { ow = dst.x + maxSpritesWidth / 2; } for ( auto spellIt = spellsInfo.crbegin(); spellIt != spellsInfo.crend(); ++spellIt ) { const fheroes2::Sprite & sprite = GetModesSprite( spellIt->mode ); const fheroes2::Point imageOffset( ow - sprite.width(), dst.y + maxSpriteHeight - sprite.height() ); fheroes2::Blit( sprite, display, imageOffset.x, imageOffset.y ); output.emplace_back( fheroes2::Rect( imageOffset.x, imageOffset.y, sprite.width(), sprite.height() ), modeToSpell( spellIt->mode ) ); if ( spellIt->duration > 0 ) { const fheroes2::Text text( std::to_string( spellIt->duration ), fheroes2::FontType::smallWhite() ); text.draw( ow - text.width(), dst.y + maxSpriteHeight - text.height() + 3, display ); } ow -= sprite.width() + space; } } return output; } void DrawMonsterInfo( const fheroes2::Point & offset, const Troop & troop ) { fheroes2::Display & display = fheroes2::Display::instance(); // name fheroes2::Text text( troop.GetName(), fheroes2::FontType::normalYellow() ); fheroes2::Point pos( offset.x + 29 + ( 227 - text.width() ) / 2, offset.y + 37 ); text.draw( pos.x, pos.y + 2, display ); // Description. const std::vector descriptions = fheroes2::getMonsterPropertiesDescription( troop.GetID() ); if ( !descriptions.empty() ) { const int32_t descriptionWidth = 210; const int32_t maximumRowCount = 3; const int32_t rowHeight = fheroes2::getFontHeight( fheroes2::FontSize::SMALL ); bool asSolidText = true; if ( descriptions.size() <= static_cast( maximumRowCount ) ) { asSolidText = false; for ( const std::string & sentence : descriptions ) { if ( fheroes2::Text( sentence, fheroes2::FontType::smallWhite() ).width() > descriptionWidth ) { asSolidText = true; break; } } } if ( asSolidText ) { std::string description; for ( const std::string & sentence : descriptions ) { if ( !description.empty() ) { description += ' '; } description += sentence; } const fheroes2::Text descriptionText( description, fheroes2::FontType::smallWhite() ); const int32_t rowCount = descriptionText.rows( descriptionWidth ); descriptionText.draw( offset.x + 37, offset.y + 185 + ( maximumRowCount - rowCount ) * rowHeight, descriptionWidth, display ); } else { int32_t sentenceId = maximumRowCount - static_cast( descriptions.size() ); // safe to cast as we check the size before. for ( const std::string & sentence : descriptions ) { const fheroes2::Text descriptionText( sentence, fheroes2::FontType::smallWhite() ); descriptionText.draw( offset.x + 37, offset.y + 185 + sentenceId * rowHeight, descriptionWidth, display ); ++sentenceId; } } } // amount if ( troop.GetCount() != 0 ) { text.set( std::to_string( troop.GetCount() ), fheroes2::FontType::normalWhite() ); pos.x = offset.x + offsetXAmountBox + widthAmountBox / 2 - text.width() / 2; pos.y = offset.y + offsetYAmountBox + heightAmountBox / 2 - text.height() / 2; text.draw( pos.x, pos.y + 2, display ); } } void DrawMonster( fheroes2::RandomMonsterAnimation & monsterAnimation, const Troop & troop, const fheroes2::Point & offset, bool isReflected, bool isAnimated, const fheroes2::Rect & roi ) { const fheroes2::Sprite & monsterSprite = fheroes2::AGG::GetICN( monsterAnimation.icnFile(), monsterAnimation.frameId() ); fheroes2::Point monsterPos( offset.x, offset.y + monsterSprite.y() ); if ( isReflected ) monsterPos.x -= monsterSprite.x() - ( troop.isWide() ? Battle::Cell::widthPx / 2 : 0 ) - monsterAnimation.offset() + monsterSprite.width(); else monsterPos.x += monsterSprite.x() - ( troop.isWide() ? Battle::Cell::widthPx / 2 : 0 ) - monsterAnimation.offset(); fheroes2::Point inPos( 0, 0 ); fheroes2::Point outPos( monsterPos.x, monsterPos.y ); fheroes2::Size inSize( monsterSprite.width(), monsterSprite.height() ); fheroes2::Display & display = fheroes2::Display::instance(); if ( fheroes2::FitToRoi( monsterSprite, inPos, display, outPos, inSize, roi ) ) { if ( troop.isModes( Battle::CAP_MIRRORIMAGE ) ) { fheroes2::Sprite outMonsterSprite = monsterSprite; fheroes2::ApplyPalette( outMonsterSprite, PAL::GetPalette( PAL::PaletteType::MIRROR_IMAGE ) ); fheroes2::Blit( outMonsterSprite, inPos, display, outPos, inSize, isReflected ); } else { fheroes2::Blit( monsterSprite, inPos, display, outPos, inSize, isReflected ); } } if ( isAnimated ) monsterAnimation.increment(); } } int Dialog::ArmyInfo( const Troop & troop, int flags, bool isReflected, const int32_t windowOffsetY ) { // Unit cannot be dismissed or upgraded during combat assert( !troop.isBattle() || !( flags & BUTTONS ) || !( flags & ( UPGRADE | DISMISS ) ) ); // This function should not be called with the UPGRADE flag for a non-upgradeable unit assert( !( flags & BUTTONS ) || !( flags & UPGRADE ) || troop.isAllowUpgrade() ); // The active size of the window is 520 by 256 pixels fheroes2::Display & display = fheroes2::Display::instance(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int viewarmy = isEvilInterface ? ICN::VIEWARME : ICN::VIEWARMY; const fheroes2::Sprite & sprite_dialog = fheroes2::AGG::GetICN( viewarmy, 0 ); const fheroes2::Sprite & spriteDialogShadow = fheroes2::AGG::GetICN( viewarmy, 7 ); // setup cursor const CursorRestorer cursorRestorer( ( flags & BUTTONS ) != 0, Cursor::POINTER ); fheroes2::Point dialogOffset( ( display.width() - sprite_dialog.width() ) / 2, ( display.height() - sprite_dialog.height() ) / 2 ); if ( isEvilInterface ) { dialogOffset.y += 3; } dialogOffset.y += windowOffsetY; const fheroes2::Point shadowShift( spriteDialogShadow.x() - sprite_dialog.x(), spriteDialogShadow.y() - sprite_dialog.y() ); const fheroes2::Point shadowOffset( dialogOffset.x + shadowShift.x, dialogOffset.y + shadowShift.y ); const fheroes2::ImageRestorer restorer( display, shadowOffset.x, dialogOffset.y, sprite_dialog.width() - shadowShift.x, sprite_dialog.height() + shadowShift.y ); fheroes2::Blit( spriteDialogShadow, display, dialogOffset.x + shadowShift.x, dialogOffset.y + shadowShift.y ); fheroes2::Blit( sprite_dialog, display, dialogOffset.x, dialogOffset.y ); fheroes2::Rect pos_rt( dialogOffset.x, dialogOffset.y, sprite_dialog.width(), sprite_dialog.height() ); if ( isEvilInterface ) { pos_rt.x += 9; pos_rt.y -= 1; } const fheroes2::Point monsterStatOffset( pos_rt.x + 400, pos_rt.y + 37 ); DrawMonsterStats( monsterStatOffset, troop ); std::vector> spellAreas; const fheroes2::Point battleStatOffset( pos_rt.x + 395, pos_rt.y + 184 ); if ( troop.isBattle() ) { spellAreas = DrawBattleStats( battleStatOffset, troop ); } DrawMonsterInfo( pos_rt.getPosition(), troop ); const bool isAnimated = ( flags & BUTTONS ) != 0; fheroes2::RandomMonsterAnimation monsterAnimation( troop ); const fheroes2::Point monsterOffset( pos_rt.x + 520 / 4 + 16, pos_rt.y + 175 ); if ( !isAnimated ) { monsterAnimation.reset(); } const fheroes2::Rect dialogRoi( pos_rt.x, pos_rt.y + fheroes2::shadowWidthPx, sprite_dialog.width(), sprite_dialog.height() - 2 * fheroes2::shadowWidthPx ); DrawMonster( monsterAnimation, troop, monsterOffset, isReflected, isAnimated, dialogRoi ); const int exitButtonIcnID = isEvilInterface ? ICN::BUTTON_SMALL_EXIT_EVIL : ICN::BUTTON_SMALL_EXIT_GOOD; const int32_t exitWidth = fheroes2::AGG::GetICN( exitButtonIcnID, 0 ).width(); const int32_t interfaceAdjustment = isEvilInterface ? 0 : 18; fheroes2::Button buttonExit( pos_rt.x + sprite_dialog.width() - 58 - exitWidth + interfaceAdjustment, pos_rt.y + 221, exitButtonIcnID, 0, 1 ); LocalEvent & le = LocalEvent::Get(); if ( !( flags & BUTTONS ) ) { // This is a case when this dialog was called by the right mouse button press. display.render( restorer.rect() ); while ( le.HandleEvents( true ) ) { if ( !le.isMouseRightButtonPressed() ) { break; } } return Dialog::ZERO; } std::unique_ptr buttonUpgrade; std::unique_ptr buttonDismiss; if ( flags & UPGRADE ) { const int upgradeButtonIcnID = isEvilInterface ? ICN::BUTTON_SMALL_UPGRADE_EVIL : ICN::BUTTON_SMALL_UPGRADE_GOOD; buttonUpgrade = std::make_unique( pos_rt.x + 280, pos_rt.y + 192, upgradeButtonIcnID, 0, 1 ); buttonUpgrade->draw(); } if ( flags & DISMISS ) { const int dismissButtonIcnID = isEvilInterface ? ICN::BUTTON_SMALL_DISMISS_EVIL : ICN::BUTTON_SMALL_DISMISS_GOOD; buttonDismiss = std::make_unique( pos_rt.x + 280, pos_rt.y + 221, dismissButtonIcnID, 0, 1 ); buttonDismiss->draw(); } buttonExit.draw(); int result = Dialog::ZERO; display.render( restorer.rect() ); while ( le.HandleEvents( Game::isDelayNeeded( { Game::CASTLE_UNIT_DELAY } ) ) ) { if ( buttonUpgrade ) { buttonUpgrade->drawOnState( le.isMouseLeftButtonPressedInArea( buttonUpgrade->area() ) ); } if ( buttonDismiss ) { buttonDismiss->drawOnState( le.isMouseLeftButtonPressedInArea( buttonDismiss->area() ) ); } buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( buttonUpgrade && ( le.MouseClickLeft( buttonUpgrade->area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::ARMY_UPGRADE_TROOP ) ) ) { // If this assertion blows up then you are executing this code for a monster which has no upgrades. assert( troop.isAllowUpgrade() ); if ( UPGRADE_DISABLE & flags ) { const fheroes2::Text description( _( "You can't afford to upgrade your troops!" ), fheroes2::FontType::normalWhite() ); fheroes2::showResourceMessage( fheroes2::Text( "", {} ), description, Dialog::OK, troop.GetTotalUpgradeCost() ); } else { const fheroes2::Text description( _( "Your troops can be upgraded, but it will cost you dearly. Do you wish to upgrade them?" ), fheroes2::FontType::normalWhite() ); if ( fheroes2::showResourceMessage( fheroes2::Text( "", {} ), description, Dialog::YES | Dialog::NO, troop.GetTotalUpgradeCost() ) == Dialog::YES ) { result = Dialog::UPGRADE; break; } } } if ( buttonDismiss && ( le.MouseClickLeft( buttonDismiss->area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::ARMY_DISMISS ) ) && Dialog::YES == fheroes2::showStandardTextMessage( troop.GetPluralName( troop.GetCount() ), _( "Are you sure you want to dismiss this army?" ), Dialog::YES | Dialog::NO ) ) { result = Dialog::DISMISS; break; } if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { result = Dialog::CANCEL; break; } if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), 0 ); } else if ( buttonUpgrade && le.isMouseRightButtonPressedInArea( buttonUpgrade->area() ) ) { fheroes2::showStandardTextMessage( _( "Upgrade" ), _( "Upgrade your troops." ), 0 ); } else if ( buttonDismiss && le.isMouseRightButtonPressedInArea( buttonDismiss->area() ) ) { fheroes2::showStandardTextMessage( _( "Dismiss" ), _( "Dismiss this army." ), 0 ); } for ( const auto & spellInfo : spellAreas ) { if ( le.isMouseRightButtonPressedInArea( spellInfo.first ) ) { fheroes2::SpellDialogElement( spellInfo.second, nullptr ).showPopup( Dialog::ZERO ); break; } } if ( Game::validateAnimationDelay( Game::CASTLE_UNIT_DELAY ) ) { fheroes2::Blit( sprite_dialog, display, dialogOffset.x, dialogOffset.y ); DrawMonsterStats( monsterStatOffset, troop ); if ( troop.isBattle() ) { spellAreas = DrawBattleStats( battleStatOffset, troop ); } DrawMonsterInfo( pos_rt.getPosition(), troop ); DrawMonster( monsterAnimation, troop, monsterOffset, isReflected, true, dialogRoi ); if ( buttonUpgrade ) { buttonUpgrade->draw(); } if ( buttonDismiss ) { buttonDismiss->draw(); } if ( buttonExit.isEnabled() ) { buttonExit.draw(); } display.render( restorer.rect() ); } } return result; } int Dialog::ArmyJoinFree( const Troop & troop ) { std::string message = _( "A group of %{monster} with a desire for greater glory wish to join you.\nDo you accept?" ); StringReplaceWithLowercase( message, "%{monster}", troop.GetMultiName() ); return fheroes2::showStandardTextMessage( _( "Followers" ), std::move( message ), Dialog::YES | Dialog::NO ); } int Dialog::ArmyJoinWithCost( const Troop & troop, const uint32_t join, const uint32_t gold ) { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); std::string message; if ( troop.GetCount() == 1 ) { message = _( "The %{monster} is swayed by your diplomatic tongue, and offers to join your army for the sum of %{gold} gold.\nDo you accept?" ); } else { message = _( "The creatures are swayed by your diplomatic\ntongue, and make you an offer:\n\n" ); if ( join != troop.GetCount() ) message += _( "%{offer} of the %{total} %{monster} will join your army, and the rest will leave you alone, for the sum of %{gold} gold.\nDo you accept?" ); else message += _( "All %{offer} of the %{monster} will join your army for the sum of %{gold} gold.\nDo you accept?" ); } StringReplace( message, "%{offer}", join ); StringReplace( message, "%{total}", troop.GetCount() ); StringReplaceWithLowercase( message, "%{monster}", troop.GetPluralName( join ) ); StringReplace( message, "%{gold}", gold ); fheroes2::Text textbox( message, fheroes2::FontType::normalWhite() ); const int buttons = Dialog::YES | Dialog::NO; const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::RESOURCE, 6 ); int posy = 0; message = _( "(Rate: %{percent})" ); StringReplace( message, "%{percent}", troop.GetMonster().GetCost().gold * join * 100 / gold ); fheroes2::Text text( message, fheroes2::FontType::normalWhite() ); const FrameBox box( 10 + textbox.height( fheroes2::boxAreaWidthPx ) + 10 + text.height() + 40 + sprite.height() + 10, true ); const fheroes2::Rect & pos = box.GetArea(); posy = pos.y + 10; textbox.draw( pos.x, posy + 2, fheroes2::boxAreaWidthPx, display ); posy += textbox.height( fheroes2::boxAreaWidthPx ) + 10; text.draw( pos.x + ( pos.width - text.width() ) / 2, posy + 2, display ); posy += text.height() + 40; fheroes2::Blit( sprite, display, pos.x + ( pos.width - sprite.width() ) / 2, posy ); const fheroes2::Text goldText( std::to_string( gold ), fheroes2::FontType::smallWhite() ); goldText.draw( pos.x + ( pos.width - goldText.width() ) / 2, posy + sprite.height() + 5, display ); fheroes2::ButtonGroup btnGroup( pos, buttons ); btnGroup.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); // message loop int result = Dialog::ZERO; while ( result == Dialog::ZERO && le.HandleEvents() ) { result = btnGroup.processEvents(); } return result; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_artifact.cpp000066400000000000000000000040121476115357100235450ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include "artifact.h" #include "audio_manager.h" #include "dialog.h" // IWYU pragma: associated #include "m82.h" #include "translations.h" #include "ui_dialog.h" void Dialog::ArtifactSetAssembled( const ArtifactSetData & artifactSetData ) { const Artifact artifact( artifactSetData._assembledArtifactID ); const fheroes2::ArtifactDialogElement artifactUI( artifact ); AudioManager::PlaySound( M82::TREASURE ); fheroes2::showStandardTextMessage( artifact.GetName(), _( artifactSetData._assembleMessage ), Dialog::OK, { &artifactUI } ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_audio.cpp000066400000000000000000000247001476115357100230570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_audio.h" #include #include #include #include #include "agg_image.h" #include "audio.h" #include "audio_manager.h" #include "cursor.h" #include "game.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_option_item.h" #include "ui_window.h" namespace { void drawDialog( const std::vector & rects ) { assert( rects.size() == 4 ); const Settings & conf = Settings::Get(); // Music volume. const bool isMusicOn = ( Audio::isValid() && conf.MusicVolume() > 0 ); const fheroes2::Sprite & musicVolumeIcon = fheroes2::AGG::GetICN( ICN::SPANEL, isMusicOn ? 1 : 0 ); std::string value; if ( isMusicOn ) { value = std::to_string( conf.MusicVolume() ); } else { value = _( "off" ); } fheroes2::drawOption( rects[0], musicVolumeIcon, _( "Music" ), value, fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); // Sound volume. const bool isAudioOn = ( Audio::isValid() && conf.SoundVolume() > 0 ); const fheroes2::Sprite & soundVolumeOption = fheroes2::AGG::GetICN( ICN::SPANEL, isAudioOn ? 3 : 2 ); if ( isAudioOn ) { value = std::to_string( conf.SoundVolume() ); } else { value = _( "off" ); } fheroes2::drawOption( rects[1], soundVolumeOption, _( "Effects" ), value, fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); // Music Type. const MusicSource musicType = conf.MusicType(); const fheroes2::Sprite & musicTypeIcon = fheroes2::AGG::GetICN( ICN::SPANEL, musicType == MUSIC_EXTERNAL ? 11 : 10 ); if ( musicType == MUSIC_MIDI_ORIGINAL ) { value = _( "MIDI" ); } else if ( musicType == MUSIC_MIDI_EXPANSION ) { value = _( "MIDI Expansion" ); } else if ( musicType == MUSIC_EXTERNAL ) { value = _( "External" ); } fheroes2::drawOption( rects[2], musicTypeIcon, _( "Music Type" ), value, fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); // 3D Audio. const bool is3DAudioEnabled = conf.is3DAudioEnabled(); const fheroes2::Sprite & interfaceStateIcon = is3DAudioEnabled ? fheroes2::AGG::GetICN( ICN::SPANEL, 11 ) : fheroes2::AGG::GetICN( ICN::SPANEL, 10 ); if ( is3DAudioEnabled ) { value = _( "On" ); } else { value = _( "Off" ); } fheroes2::drawOption( rects[3], interfaceStateIcon, _( "3D Audio" ), value, fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); } } namespace Dialog { bool openAudioSettingsDialog( const bool fromAdventureMap ) { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 289, 272, true, display ); const fheroes2::Rect windowRoi = background.activeArea(); Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Button buttonOk; const int buttonOkIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcnId, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); fheroes2::ImageRestorer emptyDialogRestorer( display, windowRoi.x, windowRoi.y, windowRoi.width, windowRoi.height ); const fheroes2::Sprite & optionSprite = fheroes2::AGG::GetICN( ICN::SPANEL, 0 ); const fheroes2::Point optionOffset( windowRoi.x + 53, windowRoi.y + 31 ); const fheroes2::Point optionStep( 118, 110 ); std::vector roi; roi.reserve( 4 ); roi.emplace_back( optionOffset.x, optionOffset.y, optionSprite.width(), optionSprite.height() ); roi.emplace_back( optionOffset.x + optionStep.x, optionOffset.y, optionSprite.width(), optionSprite.height() ); roi.emplace_back( optionOffset.x, optionOffset.y + optionStep.y, optionSprite.width(), optionSprite.height() ); roi.emplace_back( optionOffset.x + optionStep.x, optionOffset.y + optionStep.y, optionSprite.width(), optionSprite.height() ); const fheroes2::Rect & musicVolumeRoi = roi[0]; const fheroes2::Rect & soundVolumeRoi = roi[1]; const fheroes2::Rect & musicTypeRoi = roi[2]; const fheroes2::Rect & audio3D = roi[3]; drawDialog( roi ); display.render( background.totalArea() ); bool saveConfig = false; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } bool haveSettingsChanged = false; if ( Audio::isValid() ) { { bool haveMusicSettingsChanged = false; if ( le.MouseClickLeft( musicVolumeRoi ) ) { conf.SetMusicVolume( ( conf.MusicVolume() + 1 ) % 11 ); haveMusicSettingsChanged = true; } else if ( le.isMouseWheelUpInArea( musicVolumeRoi ) ) { conf.SetMusicVolume( conf.MusicVolume() + 1 ); haveMusicSettingsChanged = true; } else if ( le.isMouseWheelDownInArea( musicVolumeRoi ) ) { conf.SetMusicVolume( conf.MusicVolume() - 1 ); haveMusicSettingsChanged = true; } if ( haveMusicSettingsChanged ) { Music::setVolume( 100 * conf.MusicVolume() / 10 ); haveSettingsChanged = true; } } { bool haveSoundSettingsChanged = false; if ( le.MouseClickLeft( soundVolumeRoi ) ) { conf.SetSoundVolume( ( conf.SoundVolume() + 1 ) % 11 ); haveSoundSettingsChanged = true; } else if ( le.isMouseWheelUpInArea( soundVolumeRoi ) ) { conf.SetSoundVolume( conf.SoundVolume() + 1 ); haveSoundSettingsChanged = true; } else if ( le.isMouseWheelDownInArea( soundVolumeRoi ) ) { conf.SetSoundVolume( conf.SoundVolume() - 1 ); haveSoundSettingsChanged = true; } if ( haveSoundSettingsChanged ) { Mixer::setVolume( 100 * conf.SoundVolume() / 10 ); haveSettingsChanged = true; } } } if ( le.MouseClickLeft( musicTypeRoi ) ) { int type = conf.MusicType() + 1; // If there's no expansion files we skip this option if ( type == MUSIC_MIDI_EXPANSION && !conf.isPriceOfLoyaltySupported() ) { ++type; } conf.SetMusicType( type > MUSIC_EXTERNAL ? 0 : type ); AudioManager::PlayCurrentMusic(); haveSettingsChanged = true; } if ( le.MouseClickLeft( audio3D ) ) { conf.set3DAudio( !conf.is3DAudioEnabled() ); if ( fromAdventureMap ) { Game::EnvironmentSoundMixer(); } haveSettingsChanged = true; } if ( le.isMouseRightButtonPressedInArea( musicVolumeRoi ) ) { fheroes2::showStandardTextMessage( _( "Music" ), _( "Toggle ambient music level." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( soundVolumeRoi ) ) { fheroes2::showStandardTextMessage( _( "Effects" ), _( "Toggle foreground sounds level." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( musicTypeRoi ) ) { fheroes2::showStandardTextMessage( _( "Music Type" ), _( "Change the type of music." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( audio3D ) ) { fheroes2::showStandardTextMessage( _( "3D Audio" ), _( "Toggle the 3D effect of foreground sounds." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } if ( haveSettingsChanged ) { emptyDialogRestorer.restore(); drawDialog( roi ); display.render( background.totalArea() ); saveConfig = true; } } return saveConfig; } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_audio.h000066400000000000000000000030351476115357100225220ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace Dialog { bool openAudioSettingsDialog( const bool fromAdventureMap ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_box.cpp000066400000000000000000000164731476115357100225560ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include "agg_image.h" #include "dialog.h" // IWYU pragma: associated #include "icn.h" #include "image.h" #include "screen.h" #include "settings.h" namespace { const int32_t windowWidth = 288; // this is measured value const int32_t buttonHeight = 40; const int32_t activeAreaHeight = 35; int32_t topHeight( const bool isEvilInterface ) { const fheroes2::Sprite & image = fheroes2::AGG::GetICN( isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD, 0 ); return image.height(); } int32_t bottomHeight( const bool isEvilInterface ) { const fheroes2::Sprite & image = fheroes2::AGG::GetICN( isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD, 2 ); return image.height(); } int32_t leftWidth( const bool isEvilInterface ) { const int icnId = isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD; const fheroes2::Sprite & image3 = fheroes2::AGG::GetICN( icnId, 3 ); const fheroes2::Sprite & image4 = fheroes2::AGG::GetICN( icnId, 4 ); const fheroes2::Sprite & image5 = fheroes2::AGG::GetICN( icnId, 5 ); int32_t widthLeft = image3.width(); widthLeft = std::max( widthLeft, image4.width() ); widthLeft = std::max( widthLeft, image5.width() ); return widthLeft; } int32_t rightWidth( const bool isEvilInterface ) { const int icnId = isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD; const fheroes2::Sprite & image0 = fheroes2::AGG::GetICN( icnId, 0 ); const fheroes2::Sprite & image1 = fheroes2::AGG::GetICN( icnId, 1 ); const fheroes2::Sprite & image2 = fheroes2::AGG::GetICN( icnId, 2 ); int32_t widthRight = image0.width(); widthRight = std::max( widthRight, image1.width() ); widthRight = std::max( widthRight, image2.width() ); return widthRight; } int32_t overallWidth( const bool isEvilInterface ) { return leftWidth( isEvilInterface ) + rightWidth( isEvilInterface ); } int32_t leftOffset( const bool isEvilInterface ) { return leftWidth( isEvilInterface ) - windowWidth / 2; } } Dialog::NonFixedFrameBox::NonFixedFrameBox( int height, int startYPos, bool showButtons ) : _middleFragmentCount( 0 ) , _middleFragmentHeight( 0 ) { if ( showButtons ) height += buttonHeight; const bool evil = Settings::Get().isEvilInterfaceEnabled(); _middleFragmentCount = ( height <= 2 * activeAreaHeight ? 0 : 1 + ( height - 2 * activeAreaHeight ) / activeAreaHeight ); _middleFragmentHeight = height <= 2 * activeAreaHeight ? 0 : height - 2 * activeAreaHeight; const int32_t height_top_bottom = topHeight( evil ) + bottomHeight( evil ); area.width = fheroes2::boxAreaWidthPx; area.height = activeAreaHeight + activeAreaHeight + _middleFragmentHeight; fheroes2::Display & display = fheroes2::Display::instance(); const int32_t leftSideOffset = leftOffset( evil ); _position.x = ( display.width() - windowWidth ) / 2 - leftSideOffset; _position.y = startYPos; if ( startYPos < 0 ) { _position.y = ( ( display.height() - _middleFragmentHeight ) / 2 ) - topHeight( evil ); } _restorer.reset( new fheroes2::ImageRestorer( display, _position.x, _position.y, overallWidth( evil ), height_top_bottom + _middleFragmentHeight ) ); area.x = _position.x + ( windowWidth - fheroes2::boxAreaWidthPx ) / 2 + leftSideOffset; area.y = _position.y + ( topHeight( evil ) - activeAreaHeight ); redraw(); } void Dialog::NonFixedFrameBox::redraw() { const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int buybuild = isEvilInterface ? ICN::BUYBUILE : ICN::BUYBUILD; const int32_t overallLeftWidth = leftWidth( isEvilInterface ); // right-top const fheroes2::Sprite & part0 = fheroes2::AGG::GetICN( buybuild, 0 ); // left-top const fheroes2::Sprite & part4 = fheroes2::AGG::GetICN( buybuild, 4 ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( part4, display, _position.x + overallLeftWidth - part4.width(), _position.y ); fheroes2::Blit( part0, display, _position.x + overallLeftWidth, _position.y ); _position.y += part4.height(); const int32_t posBeforeMiddle = _position.y; int32_t middleLeftHeight = _middleFragmentHeight; for ( uint32_t i = 0; i < _middleFragmentCount; ++i ) { const int32_t chunkHeight = middleLeftHeight >= activeAreaHeight ? activeAreaHeight : middleLeftHeight; // left-middle const fheroes2::Sprite & sl = fheroes2::AGG::GetICN( buybuild, 5 ); fheroes2::Blit( sl, 0, 10, display, _position.x + overallLeftWidth - sl.width(), _position.y, sl.width(), chunkHeight ); // right-middle const fheroes2::Sprite & sr = fheroes2::AGG::GetICN( buybuild, 1 ); fheroes2::Blit( sr, 0, 10, display, _position.x + overallLeftWidth, _position.y, sr.width(), chunkHeight ); middleLeftHeight -= chunkHeight; _position.y += chunkHeight; } _position.y = posBeforeMiddle + _middleFragmentHeight; // right-bottom const fheroes2::Sprite & part2 = fheroes2::AGG::GetICN( buybuild, 2 ); // left-bottom const fheroes2::Sprite & part6 = fheroes2::AGG::GetICN( buybuild, 6 ); fheroes2::Blit( part6, display, _position.x + overallLeftWidth - part6.width(), _position.y ); fheroes2::Blit( part2, display, _position.x + overallLeftWidth, _position.y ); } Dialog::NonFixedFrameBox::~NonFixedFrameBox() { _restorer->restore(); fheroes2::Display::instance().render( _restorer->rect() ); } int32_t Dialog::NonFixedFrameBox::getButtonAreaHeight() { return buttonHeight; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_buyboat.cpp000066400000000000000000000074031476115357100234240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "payment.h" #include "resource.h" #include "screen.h" #include "translations.h" #include "ui_button.h" #include "ui_text.h" int Dialog::BuyBoat( bool enable ) { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); Resource::BoxSprite rbs( PaymentConditions::BuyBoat(), fheroes2::boxAreaWidthPx ); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::BOATWIND, 0 ); fheroes2::Text text{ _( "Build a new ship:" ), fheroes2::FontType::normalWhite() }; const int spacer = 10; Dialog::FrameBox box( text.height() + spacer + sprite.height() + spacer + text.height() + spacer + rbs.GetArea().height - 20, true ); const fheroes2::Rect & box_rt = box.GetArea(); fheroes2::Point dst_pt( box_rt.x + ( box_rt.width - text.width() ) / 2, box_rt.y ); text.draw( dst_pt.x, dst_pt.y + 2, display ); dst_pt.x = box_rt.x + ( box_rt.width - sprite.width() ) / 2; dst_pt.y = box_rt.y + text.height() + spacer; fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); text.set( _( "Resource cost:" ), fheroes2::FontType::normalWhite() ); dst_pt.x = box_rt.x + ( box_rt.width - text.width() ) / 2; dst_pt.y = dst_pt.y + sprite.height() + spacer; text.draw( dst_pt.x, dst_pt.y + 2, display ); rbs.SetPos( box_rt.x, dst_pt.y + spacer ); rbs.Redraw(); // buttons fheroes2::ButtonGroup buttonGroup( box_rt, Dialog::OK | Dialog::CANCEL ); fheroes2::ButtonBase & buttonOkay = buttonGroup.button( 0 ); if ( !enable ) { buttonOkay.press(); buttonOkay.disable(); } buttonGroup.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); // message loop while ( le.HandleEvents() ) { const int result = buttonGroup.processEvents(); if ( result != Dialog::ZERO ) { return result; } } return Dialog::ZERO; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_chest.cpp000066400000000000000000000137471476115357100230750ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "math_base.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_text.h" #include "world.h" bool Dialog::SelectGoldOrExp( const std::string & header, const std::string & message, uint32_t gold, uint32_t expr, const Heroes & hero ) { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::Sprite & sprite_gold = fheroes2::AGG::GetICN( ICN::RESOURCE, 6 ); const fheroes2::Sprite & sprite_expr = fheroes2::AGG::GetICN( ICN::EXPMRL, 4 ); fheroes2::Text headerText( header, fheroes2::FontType::normalYellow() ); fheroes2::Text messageText( message, fheroes2::FontType::normalWhite() ); fheroes2::Text text{ std::to_string( gold ) + " (" + _( "Total: " ) + std::to_string( world.GetKingdom( hero.GetColor() ).GetFunds().Get( Resource::GOLD ) ) + ")", fheroes2::FontType::smallWhite() }; const int spacer = 10; const FrameBox box( headerText.height( fheroes2::boxAreaWidthPx ) + spacer + messageText.height( fheroes2::boxAreaWidthPx ) + spacer + sprite_expr.height() + 2 + text.height(), true ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int buttonYesIcnID = isEvilInterface ? ICN::BUTTON_SMALL_YES_EVIL : ICN::BUTTON_SMALL_YES_GOOD; const int buttonNoIcnID = isEvilInterface ? ICN::BUTTON_SMALL_NO_EVIL : ICN::BUTTON_SMALL_NO_GOOD; const fheroes2::Sprite & buttonYesSprite = fheroes2::AGG::GetICN( buttonYesIcnID, 0 ); const int32_t buttonsYPosition = box.GetArea().y + box.GetArea().height - buttonYesSprite.height(); const int32_t buttonYesXPosition = box.GetArea().x + box.GetArea().width / 2 - buttonYesSprite.width() - 20; fheroes2::Button buttonYes( buttonYesXPosition, buttonsYPosition, buttonYesIcnID, 0, 1 ); const int32_t buttonNoXPosition = box.GetArea().x + box.GetArea().width / 2 + 20; fheroes2::Button buttonNo( buttonNoXPosition, buttonsYPosition, buttonNoIcnID, 0, 1 ); fheroes2::Rect pos = box.GetArea(); if ( !header.empty() ) { headerText.draw( pos.x, pos.y + 2, fheroes2::boxAreaWidthPx, display ); } pos.y += headerText.height( fheroes2::boxAreaWidthPx ) + spacer; if ( !message.empty() ) { messageText.draw( pos.x, pos.y + 2, fheroes2::boxAreaWidthPx, display ); } pos.y += messageText.height( fheroes2::boxAreaWidthPx ) + spacer; pos.y += sprite_expr.height(); // sprite1 pos.x = buttonYesXPosition + ( ( buttonYesSprite.width() - sprite_gold.width() ) / 2 ); fheroes2::Blit( sprite_gold, display, pos.x, pos.y - sprite_gold.height() ); // text text.draw( pos.x + sprite_gold.width() / 2 - text.width() / 2, pos.y + 4, display ); // sprite2 pos.x = buttonNoXPosition + ( ( fheroes2::AGG::GetICN( buttonNoIcnID, 0 ).width() - sprite_expr.width() ) / 2 ); fheroes2::Blit( sprite_expr, display, pos.x, pos.y - sprite_expr.height() ); // text text.set( std::to_string( expr ) + " (" + _( "Need: " ) + std::to_string( Heroes::GetExperienceFromLevel( hero.GetLevel() ) - hero.GetExperience() ) + ")", fheroes2::FontType::smallWhite() ); text.draw( pos.x + sprite_expr.width() / 2 - text.width() / 2, pos.y + 4, display ); buttonYes.draw(); buttonNo.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); bool result = false; // message loop while ( le.HandleEvents() ) { buttonYes.drawOnState( le.isMouseLeftButtonPressedInArea( buttonYes.area() ) ); buttonNo.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNo.area() ) ); if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( buttonYes.area() ) ) { result = true; break; } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonNo.area() ) ) { result = false; break; } } return result; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_file.cpp000066400000000000000000000165471476115357100227070ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "game_interface.h" #include "game_mode.h" #include "icn.h" #include "localevent.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_window.h" namespace { fheroes2::GameMode selectFileOption() { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 289, 204, true, display ); fheroes2::Button buttonNew; fheroes2::Button buttonLoad; fheroes2::Button buttonSave; fheroes2::Button buttonQuit; fheroes2::Button buttonCancel; const int32_t largeButtonsXOffset = 30; const int32_t largeButtonsYOffset = 15; const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); background.renderButton( buttonNew, isEvilInterface ? ICN::BUTTON_NEW_GAME_EVIL : ICN::BUTTON_NEW_GAME_GOOD, 0, 1, { largeButtonsXOffset, largeButtonsYOffset }, fheroes2::StandardWindow::Padding::TOP_LEFT ); background.renderButton( buttonLoad, isEvilInterface ? ICN::BUTTON_LOAD_GAME_EVIL : ICN::BUTTON_LOAD_GAME_GOOD, 0, 1, { largeButtonsXOffset, largeButtonsYOffset }, fheroes2::StandardWindow::Padding::TOP_RIGHT ); background.renderButton( buttonSave, isEvilInterface ? ICN::BUTTON_SAVE_GAME_EVIL : ICN::BUTTON_SAVE_GAME_GOOD, 0, 1, { largeButtonsXOffset, largeButtonsYOffset + 2 }, fheroes2::StandardWindow::Padding::CENTER_LEFT ); background.renderButton( buttonQuit, isEvilInterface ? ICN::BUTTON_QUIT_EVIL : ICN::BUTTON_QUIT_GOOD, 0, 1, { largeButtonsXOffset, largeButtonsYOffset + 2 }, fheroes2::StandardWindow::Padding::CENTER_RIGHT ); background.renderButton( buttonCancel, isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); display.render( background.totalArea() ); fheroes2::GameMode result = fheroes2::GameMode::QUIT_GAME; LocalEvent & le = LocalEvent::Get(); // dialog menu loop while ( le.HandleEvents() ) { buttonNew.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNew.area() ) ); buttonLoad.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLoad.area() ) ); buttonSave.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSave.area() ) ); buttonQuit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonQuit.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonNew.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_NEW_GAME ) ) { if ( Interface::AdventureMap::Get().EventNewGame() == fheroes2::GameMode::NEW_GAME ) { result = fheroes2::GameMode::NEW_GAME; break; } } else if ( le.MouseClickLeft( buttonLoad.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME ) ) { if ( Interface::AdventureMap::Get().EventLoadGame() == fheroes2::GameMode::LOAD_GAME ) { result = fheroes2::GameMode::LOAD_GAME; break; } } else if ( le.MouseClickLeft( buttonSave.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_SAVE_GAME ) ) { // Special case: since we show a window about file saving we don't want to display the current dialog anymore. background.hideWindow(); return Interface::AdventureMap::Get().EventSaveGame(); } if ( le.MouseClickLeft( buttonQuit.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_QUIT ) ) { if ( Interface::AdventureMap::EventExit() == fheroes2::GameMode::QUIT_GAME ) { result = fheroes2::GameMode::QUIT_GAME; break; } } else if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyCloseWindow() ) { result = fheroes2::GameMode::CANCEL; break; } if ( le.isMouseRightButtonPressedInArea( buttonNew.area() ) ) { fheroes2::showStandardTextMessage( _( "New Game" ), _( "Start a single or multi-player game." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonLoad.area() ) ) { fheroes2::showStandardTextMessage( _( "Load Game" ), _( "Load a previously saved game." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonSave.area() ) ) { fheroes2::showStandardTextMessage( _( "Save Game" ), _( "Save the current game." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonQuit.area() ) ) { fheroes2::showStandardTextMessage( _( "Quit" ), _( "Quit out of Heroes of Might and Magic II." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } } return result; } } fheroes2::GameMode Dialog::FileOptions() { const fheroes2::GameMode result = selectFileOption(); return result; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_frameborder.cpp000066400000000000000000000067261476115357100242560ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "agg_image.h" #include "dialog.h" // IWYU pragma: associated #include "icn.h" #include "image.h" #include "math_base.h" #include "screen.h" #include "settings.h" Dialog::FrameBorder::FrameBorder( int v ) : restorer( fheroes2::Display::instance(), 0, 0, 0, 0 ) , border( v ) {} void Dialog::FrameBorder::SetPosition( int32_t posx, int32_t posy, int32_t encw, int32_t ench ) { restorer.restore(); rect.x = posx; rect.y = posy; if ( encw > 0 && ench > 0 ) { rect.width = encw + 2 * border; rect.height = ench + 2 * border; restorer.update( rect.x, rect.y, rect.width, rect.height ); area.width = encw; area.height = ench; } else { restorer.update( posx, posy, restorer.width(), restorer.height() ); } area.x = posx + border; area.y = posy + border; top = fheroes2::Rect( rect.x, rect.y, rect.width, border ); } void Dialog::FrameBorder::RenderRegular( const fheroes2::Rect & dstrt ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ( Settings::Get().isEvilInterfaceEnabled() ? ICN::SURDRBKE : ICN::SURDRBKG ), 0 ); const fheroes2::Image renderedImage = fheroes2::Stretch( sprite, fheroes2::shadowWidthPx, 0, sprite.width() - fheroes2::shadowWidthPx, sprite.height() - fheroes2::shadowWidthPx, dstrt.width, dstrt.height ); fheroes2::Blit( renderedImage, fheroes2::Display::instance(), dstrt.x, dstrt.y ); } void Dialog::FrameBorder::RenderOther( const fheroes2::Image & srcsf, const fheroes2::Rect & dstrt ) { const fheroes2::Image renderedImage = fheroes2::Stretch( srcsf, 0, 0, srcsf.width(), srcsf.height(), dstrt.width, dstrt.height ); fheroes2::Blit( renderedImage, fheroes2::Display::instance(), dstrt.x, dstrt.y ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_game_settings.cpp000066400000000000000000000327561476115357100246210ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_game_settings.h" #include #include #include #include #include #include "agg_image.h" #include "dialog.h" #include "dialog_audio.h" #include "dialog_graphics_settings.h" #include "dialog_hotkeys.h" #include "dialog_language_selection.h" #include "game_hotkeys.h" #include "game_language.h" #include "game_mainmenu_ui.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_option_item.h" #include "ui_window.h" namespace { enum class SelectedWindow : int { Configuration, Language, Graphics, AudioSettings, HotKeys, CursorType, TextSupportMode, UpdateSettings, Exit }; const fheroes2::Size offsetBetweenOptions{ 92, 110 }; const fheroes2::Point optionOffset{ 20, 31 }; const int32_t optionWindowSize{ 65 }; const fheroes2::Rect languageRoi{ optionOffset.x, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect graphicsRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect audioRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect hotKeyRoi{ optionOffset.x, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect cursorTypeRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect textSupportModeRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; void drawLanguage( const fheroes2::Rect & optionRoi ) { const fheroes2::SupportedLanguage currentLanguage = fheroes2::getLanguageFromAbbreviation( Settings::Get().getGameLanguage() ); fheroes2::LanguageSwitcher languageSwitcher( currentLanguage ); fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 18 ), _( "Language" ), fheroes2::getLanguageName( currentLanguage ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawGraphics( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::GAME_OPTION_ICON, 1 ), _( "Graphics" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawAudioOptions( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 1 ), _( "Audio" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawHotKeyOptions( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::GAME_OPTION_ICON, 0 ), _( "Hot Keys" ), _( "Configure" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawCursorTypeOptions( const fheroes2::Rect & optionRoi ) { if ( Settings::Get().isMonochromeCursorEnabled() ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 20 ), _( "Mouse Cursor" ), _( "Black & White" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } else { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 21 ), _( "Mouse Cursor" ), _( "Color" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } } void drawTextSupportModeOptions( const fheroes2::Rect & optionRoi ) { if ( Settings::Get().isTextSupportModeEnabled() ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::CSPANEL, 4 ), _( "Text Support" ), _( "On" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } else { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 9 ), _( "Text Support" ), _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } } SelectedWindow showConfigurationWindow() { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 289, 272, true, display ); const fheroes2::Rect windowRoi = background.activeArea(); const Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Button buttonOk; const int buttonOkIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcnId, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); fheroes2::ImageRestorer emptyDialogRestorer( display, windowRoi.x, windowRoi.y, windowRoi.width, windowRoi.height ); const fheroes2::Rect windowLanguageRoi( languageRoi + windowRoi.getPosition() ); const fheroes2::Rect windowGraphicsRoi( graphicsRoi + windowRoi.getPosition() ); const fheroes2::Rect windowAudioRoi( audioRoi + windowRoi.getPosition() ); const fheroes2::Rect windowHotKeyRoi( hotKeyRoi + windowRoi.getPosition() ); const fheroes2::Rect windowCursorTypeRoi( cursorTypeRoi + windowRoi.getPosition() ); const fheroes2::Rect windowTextSupportModeRoi( textSupportModeRoi + windowRoi.getPosition() ); const auto drawOptions = [&windowLanguageRoi, &windowGraphicsRoi, &windowAudioRoi, &windowHotKeyRoi, &windowCursorTypeRoi, &windowTextSupportModeRoi]() { drawLanguage( windowLanguageRoi ); drawGraphics( windowGraphicsRoi ); drawAudioOptions( windowAudioRoi ); drawHotKeyOptions( windowHotKeyRoi ); drawCursorTypeOptions( windowCursorTypeRoi ); drawTextSupportModeOptions( windowTextSupportModeRoi ); }; drawOptions(); display.render( background.totalArea() ); bool isTextSupportModeEnabled = conf.isTextSupportModeEnabled(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.MouseClickLeft( windowLanguageRoi ) ) { return SelectedWindow::Language; } if ( le.MouseClickLeft( windowGraphicsRoi ) ) { return SelectedWindow::Graphics; } if ( le.MouseClickLeft( windowAudioRoi ) ) { return SelectedWindow::AudioSettings; } if ( le.MouseClickLeft( windowHotKeyRoi ) ) { return SelectedWindow::HotKeys; } if ( le.MouseClickLeft( windowCursorTypeRoi ) ) { return SelectedWindow::CursorType; } if ( le.MouseClickLeft( windowTextSupportModeRoi ) ) { return SelectedWindow::TextSupportMode; } if ( le.isMouseRightButtonPressedInArea( windowLanguageRoi ) ) { fheroes2::showStandardTextMessage( _( "Select Game Language" ), _( "Change the language of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowGraphicsRoi ) ) { fheroes2::showStandardTextMessage( _( "Graphics" ), _( "Change the graphics settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowAudioRoi ) ) { fheroes2::showStandardTextMessage( _( "Audio" ), _( "Change the audio settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowHotKeyRoi ) ) { fheroes2::showStandardTextMessage( _( "Hot Keys" ), _( "Check and configure all the hot keys present in the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowCursorTypeRoi ) ) { fheroes2::showStandardTextMessage( _( "Mouse Cursor" ), _( "Toggle colored cursor on or off. This is only an aesthetic choice." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowTextSupportModeRoi ) ) { fheroes2::showStandardTextMessage( _( "Text Support" ), _( "Toggle text support mode to output extra information about windows and events in the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } // Text support mode can be toggled using a global hotkey, we need to properly reflect this change in the UI if ( isTextSupportModeEnabled != conf.isTextSupportModeEnabled() ) { isTextSupportModeEnabled = conf.isTextSupportModeEnabled(); emptyDialogRestorer.restore(); drawOptions(); display.render( emptyDialogRestorer.rect() ); } } return SelectedWindow::Exit; } } namespace fheroes2 { void openGameSettings() { drawMainMenuScreen(); fheroes2::Display::instance().render(); Settings & conf = Settings::Get(); bool saveConfiguration = false; SelectedWindow windowType = SelectedWindow::Configuration; while ( windowType != SelectedWindow::Exit ) { switch ( windowType ) { case SelectedWindow::Configuration: windowType = showConfigurationWindow(); break; case SelectedWindow::Language: { const std::vector supportedLanguages = getSupportedLanguages(); if ( supportedLanguages.size() > 1 ) { selectLanguage( supportedLanguages, getLanguageFromAbbreviation( conf.getGameLanguage() ), true ); } else { assert( supportedLanguages.front() == SupportedLanguage::English ); conf.setGameLanguage( getLanguageAbbreviation( SupportedLanguage::English ) ); fheroes2::showStandardTextMessage( "Attention", "Your version of Heroes of Might and Magic II does not support any other languages than English.", Dialog::OK ); } windowType = SelectedWindow::UpdateSettings; break; } case SelectedWindow::Graphics: saveConfiguration |= fheroes2::openGraphicsSettingsDialog( []() { drawMainMenuScreen(); } ); windowType = SelectedWindow::Configuration; break; case SelectedWindow::AudioSettings: saveConfiguration |= Dialog::openAudioSettingsDialog( false ); windowType = SelectedWindow::Configuration; break; case SelectedWindow::HotKeys: fheroes2::openHotkeysDialog(); windowType = SelectedWindow::Configuration; break; case SelectedWindow::CursorType: conf.setMonochromeCursor( !conf.isMonochromeCursorEnabled() ); windowType = SelectedWindow::UpdateSettings; break; case SelectedWindow::TextSupportMode: conf.setTextSupportMode( !conf.isTextSupportModeEnabled() ); windowType = SelectedWindow::UpdateSettings; break; case SelectedWindow::UpdateSettings: saveConfiguration = true; windowType = SelectedWindow::Configuration; break; default: return; } } if ( saveConfiguration ) { conf.Save( Settings::configFileName ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_game_settings.h000066400000000000000000000027731476115357100242620ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace fheroes2 { void openGameSettings(); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_gameinfo.cpp000066400000000000000000000232531476115357100235450ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "difficulty.h" #include "game.h" #include "game_hotkeys.h" #include "game_over.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "maps.h" #include "maps_fileinfo.h" #include "math_base.h" #include "player_info.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" namespace { enum GameInfoCoordinates { SCENARIO_INFO_VALUES_BOX_WIDTH = 80, DIALOG_CONTENT_WIDTH = 420, SCENARIO_INFO_BOX_INNER_MARGIN = 11, SCENARIO_INFO_ROW_OUTER_MARGIN = 16, DESCRIPTION_INNER_MARGIN = 6, SCENARIO_DESCRIPTION_OUTER_MARGIN = 11, // This is the shadow offset from the original ICN::SCENIBKG image. DIALOG_SHADOW_OFFSET_X = 16, DIALOG_SHADOW_OFFSET_Y = 4 + 12, // This ICN has been modified with a 12 px larger shadow. DIALOG_BORDER_WIDTH = 18, // The following values are calculated using the previous values. SCENARIO_INFO_ROW_OFFSET = DIALOG_BORDER_WIDTH + SCENARIO_INFO_ROW_OUTER_MARGIN, SCENARIO_MAP_DIFFICULTY_OFFSET = SCENARIO_INFO_ROW_OFFSET, SCENARIO_GAME_DIFFICULTY_OFFSET = SCENARIO_INFO_ROW_OFFSET + SCENARIO_INFO_VALUES_BOX_WIDTH + SCENARIO_INFO_BOX_INNER_MARGIN, SCENARIO_RATING_OFFSET = SCENARIO_INFO_ROW_OFFSET + SCENARIO_INFO_VALUES_BOX_WIDTH * 2 + SCENARIO_INFO_BOX_INNER_MARGIN * 2, SCENARIO_MAP_SIZE_OFFSET = SCENARIO_INFO_ROW_OFFSET + SCENARIO_INFO_VALUES_BOX_WIDTH * 3 + SCENARIO_INFO_BOX_INNER_MARGIN * 3, SCENARIO_DESCRIPTION_OFFSET = DIALOG_BORDER_WIDTH + SCENARIO_DESCRIPTION_OUTER_MARGIN + DESCRIPTION_INNER_MARGIN, SCENARIO_DESCRIPTION_WIDTH = 350, PLAYER_INFO_ROW_OFFSET = DIALOG_BORDER_WIDTH + 6, CONDITION_LABEL_OFFSET = DIALOG_BORDER_WIDTH, CONDITION_LABEL_WIDTH = 93, CONDITION_DESCRIPTION_OFFSET = CONDITION_LABEL_OFFSET + CONDITION_LABEL_WIDTH + DESCRIPTION_INNER_MARGIN, CONDITION_DESCRIPTION_WIDTH = 266, OK_BUTTON_OFFSET = DIALOG_CONTENT_WIDTH / 2, }; } void Dialog::GameInfo() { fheroes2::Display & display = fheroes2::Display::instance(); Settings & conf = Settings::Get(); const Maps::FileInfo & mapInfo = conf.getCurrentMapInfo(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const fheroes2::Sprite & window = fheroes2::AGG::GetICN( isEvilInterface ? ICN::SCENIBKG_EVIL : ICN::SCENIBKG, 0 ); const fheroes2::Point dialogOffset( ( display.width() - window.width() - DIALOG_SHADOW_OFFSET_X ) / 2, ( display.height() - window.height() ) / 2 ); const fheroes2::Point shadowOffset( dialogOffset.x + DIALOG_SHADOW_OFFSET_X, dialogOffset.y + DIALOG_SHADOW_OFFSET_Y / 2 ); fheroes2::ImageRestorer restorer( display, dialogOffset.x, shadowOffset.y, window.width(), window.height() ); fheroes2::Blit( window, display, dialogOffset.x, shadowOffset.y ); const fheroes2::Rect scenarioNameRoi{ 37 + shadowOffset.x, 29 + shadowOffset.y, 349, 19 }; fheroes2::Text text( mapInfo.name, fheroes2::FontType::normalWhite(), mapInfo.getSupportedLanguage() ); text.fitToOneRow( scenarioNameRoi.width ); text.draw( scenarioNameRoi.x, shadowOffset.y + 32, scenarioNameRoi.width, display ); text.set( _( "Map\nDifficulty" ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_MAP_DIFFICULTY_OFFSET, shadowOffset.y + 56, SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( _( "Game\nDifficulty" ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_GAME_DIFFICULTY_OFFSET, shadowOffset.y + 56, SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( _( "Rating" ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_RATING_OFFSET, shadowOffset.y + 78 - text.height( SCENARIO_INFO_VALUES_BOX_WIDTH ), SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( _( "Map Size" ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_MAP_SIZE_OFFSET, shadowOffset.y + 78 - text.height( SCENARIO_INFO_VALUES_BOX_WIDTH ), SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( Difficulty::String( mapInfo.difficulty ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_MAP_DIFFICULTY_OFFSET, shadowOffset.y + 84, SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( Difficulty::String( Game::getDifficulty() ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_GAME_DIFFICULTY_OFFSET, shadowOffset.y + 84, SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( std::to_string( Game::GetRating() ) + " %", fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_RATING_OFFSET, shadowOffset.y + 84, SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( Maps::SizeString( mapInfo.width ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + SCENARIO_MAP_SIZE_OFFSET, shadowOffset.y + 84, SCENARIO_INFO_VALUES_BOX_WIDTH, display ); text.set( mapInfo.description, fheroes2::FontType::smallWhite(), mapInfo.getSupportedLanguage() ); text.draw( shadowOffset.x + SCENARIO_DESCRIPTION_OFFSET, shadowOffset.y + 107, SCENARIO_DESCRIPTION_WIDTH, display ); text.set( _( "Opponents" ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x, shadowOffset.y + 152, DIALOG_CONTENT_WIDTH, display ); text.set( _( "Class" ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x, shadowOffset.y + 229, DIALOG_CONTENT_WIDTH, display ); Interface::PlayersInfo playersInfo; playersInfo.UpdateInfo( conf.GetPlayers(), fheroes2::Point( shadowOffset.x + PLAYER_INFO_ROW_OFFSET, shadowOffset.y + 165 ), fheroes2::Point( shadowOffset.x + PLAYER_INFO_ROW_OFFSET, shadowOffset.y + 240 ) ); playersInfo.RedrawInfo( true ); text.set( _( "Victory\nConditions" ), fheroes2::FontType::smallWhite() ); text.draw( shadowOffset.x + CONDITION_LABEL_OFFSET, shadowOffset.y + 347, CONDITION_LABEL_WIDTH, display ); text.set( GameOver::GetActualDescription( mapInfo.ConditionWins() ), fheroes2::FontType::smallWhite() ); text.setUniformVerticalAlignment( false ); text.draw( shadowOffset.x + CONDITION_DESCRIPTION_OFFSET, shadowOffset.y + 350, CONDITION_DESCRIPTION_WIDTH, display ); text.set( _( "Loss\nConditions" ), fheroes2::FontType::smallWhite() ); text.setUniformVerticalAlignment( true ); text.draw( shadowOffset.x + CONDITION_LABEL_OFFSET, shadowOffset.y + 392, CONDITION_LABEL_WIDTH, display ); text.set( GameOver::GetActualDescription( mapInfo.ConditionLoss() ), fheroes2::FontType::smallWhite() ); text.setUniformVerticalAlignment( false ); text.draw( shadowOffset.x + CONDITION_DESCRIPTION_OFFSET, shadowOffset.y + 398, CONDITION_DESCRIPTION_WIDTH, display ); const int buttonOkIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; fheroes2::Button buttonOk( shadowOffset.x + OK_BUTTON_OFFSET - fheroes2::AGG::GetICN( buttonOkIcnId, 0 ).width() / 2, shadowOffset.y + 426, buttonOkIcnId, 0, 1 ); buttonOk.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); // message loop while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.isMouseRightButtonPressedInArea( scenarioNameRoi ) ) { text.set( mapInfo.name, fheroes2::FontType::normalYellow(), mapInfo.getSupportedLanguage() ); fheroes2::showMessage( text, fheroes2::Text{}, Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } else { playersInfo.readOnlyEventProcessing(); } } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_giftresources.cpp000066400000000000000000000330321476115357100246400ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2011 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include "agg_image.h" #include "color.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "math_base.h" #include "players.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_window.h" #include "world.h" namespace { const fheroes2::Size giftDialogSize( 320, 234 ); int32_t GetIndexClickRects( const std::vector & rects ) { LocalEvent & le = LocalEvent::Get(); const fheroes2::Point & pos = le.getMouseCursorPos(); const fheroes2::Point position( pos.x, pos.y ); for ( size_t i = 0; i < rects.size(); ++i ) { if ( rects[i] & position ) { if ( le.MouseClickLeft() ) { return static_cast( i ); } return -1; } } return -1; } struct SelectRecipientsColors { static constexpr int recipientSpacing = 22; const Colors colors; int recipients{ 0 }; std::vector positions; SelectRecipientsColors( const fheroes2::Point & pos, int senderColor ) : colors( Settings::Get().GetPlayers().GetActualColors() & ~senderColor ) { positions.reserve( colors.size() ); const fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Rect box( ( display.width() - giftDialogSize.width ) / 2, ( display.height() - giftDialogSize.height ) / 2, giftDialogSize.width, giftDialogSize.height ); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::CELLWIN, 43 ); const int32_t colorCount = static_cast( colors.size() ); // safe to cast as the number of players <= 8. const int32_t playerContainerWidth = colorCount * sprite.width() + ( colorCount - 1 ) * recipientSpacing; const int32_t startX = box.x + ( giftDialogSize.width - playerContainerWidth ) / 2; for ( int32_t i = 0; i < colorCount; ++i ) { const int32_t posX = startX + i * ( recipientSpacing + sprite.width() ); positions.emplace_back( posX, pos.y, sprite.width(), sprite.height() ); } } int32_t GetIndexClick() const { return GetIndexClickRects( positions ); } void Redraw() const { fheroes2::Display & display = fheroes2::Display::instance(); for ( Colors::const_iterator it = colors.begin(); it != colors.end(); ++it ) { const fheroes2::Rect & pos = positions[std::distance( colors.begin(), it )]; fheroes2::Blit( fheroes2::AGG::GetICN( ICN::CELLWIN, 43 + Color::GetIndex( *it ) ), display, pos.x, pos.y ); if ( recipients & *it ) fheroes2::Blit( fheroes2::AGG::GetICN( ICN::CELLWIN, 2 ), display, pos.x + 2, pos.y + 2 ); } } bool QueueEventProcessing() { const int32_t index = GetIndexClick(); if ( index >= 0 ) { const int cols = colors[index]; if ( recipients & cols ) recipients &= ~cols; else recipients |= cols; return true; } return false; } }; struct ResourceBar { Funds & resource; std::vector positions; ResourceBar( Funds & funds, int32_t posx, int32_t posy ) : resource( funds ) { positions.reserve( 7 ); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::TRADPOST, 7 ); positions.emplace_back( posx, posy, sprite.width(), sprite.height() ); positions.emplace_back( posx + 40, posy, sprite.width(), sprite.height() ); positions.emplace_back( posx + 80, posy, sprite.width(), sprite.height() ); positions.emplace_back( posx + 120, posy, sprite.width(), sprite.height() ); positions.emplace_back( posx + 160, posy, sprite.width(), sprite.height() ); positions.emplace_back( posx + 200, posy, sprite.width(), sprite.height() ); positions.emplace_back( posx + 240, posy, sprite.width(), sprite.height() ); } static void RedrawResource( int type, int32_t count, int32_t posx, int32_t posy ) { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Text text( std::to_string( count ), fheroes2::FontType::smallWhite() ); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::TRADPOST, 7 + Resource::getIconIcnIndex( type ) ); fheroes2::Blit( sprite, display, posx, posy ); text.draw( posx + ( sprite.width() - text.width() ) / 2, posy + sprite.height() - 10, display ); } void Redraw( const Funds * res = nullptr ) const { if ( !res ) res = &resource; for ( size_t i = 0; i < positions.size(); ++i ) { const int rs = Resource::getResourceTypeFromIconIndex( static_cast( i ) ); RedrawResource( rs, res->Get( rs ), positions[i].x, positions[i].y ); } } int32_t GetIndexClick() const { return GetIndexClickRects( positions ); } bool QueueEventProcessing( Funds & funds, uint32_t mul ) { const int32_t index = GetIndexClick(); if ( index >= 0 ) { const int rs = Resource::getResourceTypeFromIconIndex( index ); const int32_t step = ( rs == Resource::GOLD ) ? 100 : 1; const int32_t cur = resource.Get( rs ); int32_t sel = cur; const int32_t max = mul > 1 ? ( funds.Get( rs ) + resource.Get( rs ) ) / static_cast( mul ) : funds.Get( rs ) + resource.Get( rs ); if ( 0 == mul ) { fheroes2::showStandardTextMessage( {}, _( "First select recipients!" ), Dialog::OK ); } else if ( 0 == max ) { std::string msg = _( "You cannot select %{resource}!" ); StringReplace( msg, "%{resource}", Resource::String( rs ) ); fheroes2::showStandardTextMessage( {}, std::move( msg ), Dialog::OK ); } else { std::string msg = _( "Set %{resource-type} Count" ); StringReplace( msg, "%{resource-type}", Resource::String( rs ) ); if ( Dialog::SelectCount( std::move( msg ), 0, max, sel, step ) && cur != sel ) { int32_t * from = funds.GetPtr( rs ); int32_t * to = resource.GetPtr( rs ); if ( from && to ) { const int32_t count = sel - cur; *from -= mul > 1 ? count * static_cast( mul ) : count; *to += count; return true; } } } } return false; } }; } void Dialog::MakeGiftResource( Kingdom & kingdom ) { fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::StandardWindow frameborder( 320, 234, true ); const fheroes2::Rect box( frameborder.activeArea() ); Funds funds1( kingdom.GetFunds() ); Funds funds2; const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::TRADPOST, 7 ); const int32_t posX = box.x + ( giftDialogSize.width - ( sprite.width() + 240 ) ) / 2; const fheroes2::FontType normalWhite = fheroes2::FontType::normalWhite(); fheroes2::Text text( _( "Select Recipients" ), normalWhite ); text.draw( box.x + ( box.width - text.width() ) / 2, box.y + 7, display ); SelectRecipientsColors selector( fheroes2::Point( box.x + 65, box.y + 28 ), kingdom.GetColor() ); selector.Redraw(); text.set( _( "Your Funds" ), normalWhite ); text.draw( box.x + ( box.width - text.width() ) / 2, box.y + 57, display ); ResourceBar info1( funds1, posX, box.y + 80 ); info1.Redraw(); text.set( _( "Planned Gift" ), normalWhite ); text.draw( box.x + ( box.width - text.width() ) / 2, box.y + 127, display ); ResourceBar info2( funds2, posX, box.y + 150 ); info2.Redraw(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int okIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; const int cancelIcnId = isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD; const fheroes2::Sprite & buttonOkSprite = fheroes2::AGG::GetICN( okIcnId, 0 ); const fheroes2::Sprite & buttonCancelSprite = fheroes2::AGG::GetICN( cancelIcnId, 0 ); const int32_t border = 10; fheroes2::ButtonGroup btnGroup; btnGroup.addButton( fheroes2::makeButtonWithShadow( box.x + border, box.y + box.height - border - buttonOkSprite.height(), buttonOkSprite, fheroes2::AGG::GetICN( okIcnId, 1 ), display ), Dialog::OK ); btnGroup.addButton( fheroes2::makeButtonWithShadow( box.x + box.width - border - buttonCancelSprite.width(), box.y + box.height - border - buttonCancelSprite.height(), buttonCancelSprite, fheroes2::AGG::GetICN( cancelIcnId, 1 ), display ), Dialog::CANCEL ); btnGroup.button( 0 ).disable(); btnGroup.draw(); display.render(); uint32_t count = Color::Count( selector.recipients ); // message loop int result = Dialog::ZERO; while ( result == Dialog::ZERO && le.HandleEvents() ) { result = btnGroup.processEvents(); if ( selector.QueueEventProcessing() ) { uint32_t new_count = Color::Count( selector.recipients ); if ( 0 == new_count || 0 == funds2.GetValidItemsCount() ) btnGroup.button( 0 ).disable(); else btnGroup.button( 0 ).enable(); if ( count != new_count ) { funds1 = kingdom.GetFunds(); funds2.Reset(); info1.Redraw(); info2.Redraw(); count = new_count; } btnGroup.draw(); selector.Redraw(); display.render(); } else if ( info2.QueueEventProcessing( funds1, count ) ) { if ( 0 == Color::Count( selector.recipients ) || 0 == funds2.GetValidItemsCount() ) btnGroup.button( 0 ).disable(); else btnGroup.button( 0 ).enable(); info1.Redraw(); info2.Redraw(); btnGroup.draw(); display.render(); } } if ( Dialog::OK == result ) { EventDate event; event.resource = funds2; event.isApplicableForAIPlayers = true; event.firstOccurrenceDay = world.CountDay() + 1; event.repeatPeriodInDays = 0; event.colors = selector.recipients; event.message = _( "Gift from %{name}" ); const Player * player = Players::Get( kingdom.GetColor() ); if ( player ) StringReplace( event.message, "%{name}", player->GetName() ); world.AddEventDate( event ); if ( 1 < count ) funds2 *= count; kingdom.OddFundsResource( funds2 ); } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_graphics_settings.cpp000066400000000000000000000263101476115357100254750ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_graphics_settings.h" #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog_resolution.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_option_item.h" #include "ui_text.h" #include "ui_window.h" namespace { enum class SelectedWindow : int { Configuration, Resolution, Mode, VSync, SystemInfo, Exit }; const fheroes2::Size offsetBetweenOptions{ 118, 110 }; const fheroes2::Point optionOffset{ 53, 31 }; const int32_t optionWindowSize{ 65 }; const fheroes2::Rect resolutionRoi{ optionOffset.x, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect modeRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect vSyncRoi{ optionOffset.x, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect systemInfoRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; void drawResolution( const fheroes2::Rect & optionRoi ) { const fheroes2::Display & display = fheroes2::Display::instance(); std::string resolutionName; if ( display.screenSize().width != display.width() || display.screenSize().height != display.height() ) { const int32_t integer = display.screenSize().width / display.width(); const int32_t fraction = display.screenSize().width * 10 / display.width() - 10 * integer; resolutionName = std::to_string( display.width() ) + 'x' + std::to_string( display.height() ) + " (x" + std::to_string( integer ) + '.' + std::to_string( fraction ) + ')'; } else { resolutionName = std::to_string( display.width() ) + 'x' + std::to_string( display.height() ); } fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, Settings::Get().isEvilInterfaceEnabled() ? 17 : 16 ), _( "Resolution" ), std::move( resolutionName ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); } void drawMode( const fheroes2::Rect & optionRoi ) { const fheroes2::Sprite & originalIcon = fheroes2::AGG::GetICN( ICN::SPANEL, Settings::Get().isEvilInterfaceEnabled() ? 17 : 16 ); if ( fheroes2::engine().isFullScreen() ) { fheroes2::Sprite icon = originalIcon; fheroes2::Resize( originalIcon, 6, 6, 53, 53, icon, 2, 2, 61, 61 ); fheroes2::drawOption( optionRoi, icon, _( "window|Mode" ), _( "Fullscreen" ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); } else { fheroes2::drawOption( optionRoi, originalIcon, _( "window|Mode" ), _( "Windowed" ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); } } void drawVSync( const fheroes2::Rect & optionRoi ) { const bool isVSyncEnabled = Settings::Get().isVSyncEnabled(); fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, isVSyncEnabled ? 18 : 19 ), _( "V-Sync" ), isVSyncEnabled ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); } void drawSystemInfo( const fheroes2::Rect & optionRoi ) { const bool isSystemInfoDisplayed = Settings::Get().isSystemInfoEnabled(); fheroes2::Sprite image = fheroes2::Crop( fheroes2::AGG::GetICN( ICN::ESPANBKG, 0 ), 69, 47, 65, 65 ); image.setPosition( 0, 0 ); fheroes2::Text info; if ( isSystemInfoDisplayed ) { info.set( _( "FPS" ), fheroes2::FontType( fheroes2::FontSize::NORMAL, fheroes2::FontColor::YELLOW ) ); } else { info.set( _( "N/A" ), fheroes2::FontType( fheroes2::FontSize::NORMAL, fheroes2::FontColor::GRAY ) ); } info.draw( ( image.width() - info.width() ) / 2, ( image.height() - info.height() ) / 2, image ); fheroes2::drawOption( optionRoi, image, _( "System Info" ), isSystemInfoDisplayed ? _( "On" ) : _( "Off" ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); } SelectedWindow showConfigurationWindow() { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 289, 272, true, display ); const fheroes2::Rect windowRoi = background.activeArea(); const Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Button buttonOk; const int buttonOkIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcnId, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); fheroes2::ImageRestorer emptyDialogRestorer( display, windowRoi.x, windowRoi.y, windowRoi.width, windowRoi.height ); const fheroes2::Rect windowResolutionRoi( resolutionRoi + windowRoi.getPosition() ); const fheroes2::Rect windowModeRoi( modeRoi + windowRoi.getPosition() ); const fheroes2::Rect windowVSyncRoi( vSyncRoi + windowRoi.getPosition() ); const fheroes2::Rect windowSystemInfoRoi( systemInfoRoi + windowRoi.getPosition() ); const auto drawOptions = [&windowResolutionRoi, &windowModeRoi, &windowVSyncRoi, &windowSystemInfoRoi]() { drawResolution( windowResolutionRoi ); drawMode( windowModeRoi ); drawVSync( windowVSyncRoi ); drawSystemInfo( windowSystemInfoRoi ); }; drawOptions(); display.render( background.totalArea() ); bool isFullScreen = fheroes2::engine().isFullScreen(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.MouseClickLeft( windowResolutionRoi ) ) { return SelectedWindow::Resolution; } if ( le.MouseClickLeft( windowModeRoi ) ) { return SelectedWindow::Mode; } if ( le.MouseClickLeft( windowVSyncRoi ) ) { return SelectedWindow::VSync; } if ( le.MouseClickLeft( windowSystemInfoRoi ) ) { return SelectedWindow::SystemInfo; } if ( le.isMouseRightButtonPressedInArea( windowResolutionRoi ) ) { fheroes2::showStandardTextMessage( _( "Select Game Resolution" ), _( "Change the resolution of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowModeRoi ) ) { fheroes2::showStandardTextMessage( _( "window|Mode" ), _( "Toggle between fullscreen and windowed modes." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowVSyncRoi ) ) { fheroes2::showStandardTextMessage( _( "V-Sync" ), _( "The V-Sync option can be enabled to resolve flickering issues on some monitors." ), 0 ); } if ( le.isMouseRightButtonPressedInArea( windowSystemInfoRoi ) ) { fheroes2::showStandardTextMessage( _( "System Info" ), _( "Show extra information such as FPS and current time." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } // Fullscreen mode can be toggled using a global hotkey, we need to properly reflect this change in the UI if ( isFullScreen != fheroes2::engine().isFullScreen() ) { isFullScreen = fheroes2::engine().isFullScreen(); emptyDialogRestorer.restore(); drawOptions(); display.render( emptyDialogRestorer.rect() ); } } return SelectedWindow::Exit; } } namespace fheroes2 { bool openGraphicsSettingsDialog( const std::function & updateUI ) { const CursorRestorer cursorRestorer( true, ::Cursor::POINTER ); Settings & conf = Settings::Get(); bool saveConfiguration = false; SelectedWindow windowType = SelectedWindow::Configuration; while ( windowType != SelectedWindow::Exit ) { switch ( windowType ) { case SelectedWindow::Configuration: windowType = showConfigurationWindow(); break; case SelectedWindow::Resolution: if ( Dialog::SelectResolution() ) { saveConfiguration = true; } updateUI(); windowType = SelectedWindow::Configuration; break; case SelectedWindow::Mode: conf.setFullScreen( !conf.FullScreen() ); saveConfiguration = true; windowType = SelectedWindow::Configuration; break; case SelectedWindow::VSync: conf.setVSync( !conf.isVSyncEnabled() ); saveConfiguration = true; windowType = SelectedWindow::Configuration; break; case SelectedWindow::SystemInfo: conf.setSystemInfo( !conf.isSystemInfoEnabled() ); saveConfiguration = true; windowType = SelectedWindow::Configuration; break; default: return saveConfiguration; } } return saveConfiguration; } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_graphics_settings.h000066400000000000000000000031041476115357100251360ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace fheroes2 { bool openGraphicsSettingsDialog( const std::function & updateUI ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_hotkeys.cpp000066400000000000000000000341611476115357100234460ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_hotkeys.h" #include #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_window.h" namespace { const int32_t keyDescriptionLength = 300; const int32_t hotKeyLength = 120; class HotKeyElement : public fheroes2::DialogElement { public: HotKeyElement( const fheroes2::Key key, fheroes2::Image & output ) : _restorer( output, 0, 0, 0, 0 ) , _key( key ) { // Text always occupies the whole width of the dialog. _area = { fheroes2::boxAreaWidthPx, fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) }; } ~HotKeyElement() override = default; void draw( fheroes2::Image & output, const fheroes2::Point & offset ) const override { _restorer.restore(); fheroes2::MultiFontText text; text.add( fheroes2::Text{ _( "Hotkey: " ), fheroes2::FontType::normalYellow() } ); text.add( fheroes2::Text{ StringUpper( KeySymGetName( _key ) ), fheroes2::FontType::normalWhite() } ); _restorer.update( offset.x, offset.y, fheroes2::boxAreaWidthPx, text.height() ); text.draw( offset.x, offset.y, fheroes2::boxAreaWidthPx, output ); } void processEvents( const fheroes2::Point & /*offset*/ ) const override { const LocalEvent & le = LocalEvent::Get(); if ( le.isAnyKeyPressed() ) { _key = le.getPressedKeyValue(); _keyChanged = true; } } // Never call this method as a custom image has nothing to popup. void showPopup( const int /*buttons*/ ) const override { assert( 0 ); } bool update( fheroes2::Image & output, const fheroes2::Point & offset ) const override { if ( _keyChanged ) { _keyChanged = false; draw( output, offset ); return true; } return false; } void reset() { _restorer.reset(); } fheroes2::Key getKey() const { return _key; } private: mutable fheroes2::ImageRestorer _restorer; mutable fheroes2::Key _key; mutable bool _keyChanged{ false }; }; class HotKeyList : public Interface::ListBox> { public: using Interface::ListBox>::ListBox; using Interface::ListBox>::ActionListSingleClick; using Interface::ListBox>::ActionListPressRight; using Interface::ListBox>::ActionListDoubleClick; void RedrawItem( const std::pair & hotKeyEvent, int32_t offsetX, int32_t offsetY, bool current ) override { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::FontType fontType = current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite(); offsetY += 2; fheroes2::Text name( _( Game::getHotKeyEventNameByEventId( hotKeyEvent.first ) ), fontType ); name.fitToOneRow( keyDescriptionLength ); name.draw( offsetX + 4, offsetY, display ); fheroes2::Text hotkey( Game::getHotKeyNameByEventId( hotKeyEvent.first ), fontType ); hotkey.fitToOneRow( hotKeyLength ); hotkey.draw( offsetX + keyDescriptionLength + 9, offsetY, hotKeyLength, display ); } void RedrawBackground( const fheroes2::Point & /* unused */ ) override { _listBackground->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListSingleClick( std::pair & /*unused*/ ) override { // Do nothing. } void ActionListPressRight( std::pair & hotKeyEvent ) override { fheroes2::MultiFontText title; title.add( fheroes2::Text{ _( "Category: " ), fheroes2::FontType::normalYellow() } ); title.add( fheroes2::Text{ _( Game::getHotKeyCategoryName( hotKeyEvent.second ) ), fheroes2::FontType::normalWhite() } ); title.add( fheroes2::Text{ "\n\n", fheroes2::FontType::normalWhite() } ); title.add( fheroes2::Text{ _( "Event: " ), fheroes2::FontType::normalYellow() } ); title.add( fheroes2::Text{ _( Game::getHotKeyEventNameByEventId( hotKeyEvent.first ) ), fheroes2::FontType::normalWhite() } ); title.add( fheroes2::Text{ "\n\n", fheroes2::FontType::normalWhite() } ); title.add( fheroes2::Text{ _( "Hotkey: " ), fheroes2::FontType::normalYellow() } ); title.add( fheroes2::Text{ Game::getHotKeyNameByEventId( hotKeyEvent.first ), fheroes2::FontType::normalWhite() } ); fheroes2::showMessage( fheroes2::Text{}, title, Dialog::ZERO ); } void ActionListDoubleClick( std::pair & hotKeyEvent ) override { HotKeyElement hotKeyUI( Game::getHotKeyForEvent( hotKeyEvent.first ), fheroes2::Display::instance() ); // Okay and Cancel events are special cases as they are used in dialogs. By default we need to disable these events to allow to be set any key for an event. // Global events (that work on all screens) must be disabled as well. const fheroes2::Key okayEventKey = Game::getHotKeyForEvent( Game::HotKeyEvent::DEFAULT_OKAY ); const fheroes2::Key cancelEventKey = Game::getHotKeyForEvent( Game::HotKeyEvent::DEFAULT_CANCEL ); const fheroes2::Key fullscreenEventKey = Game::getHotKeyForEvent( Game::HotKeyEvent::GLOBAL_TOGGLE_FULLSCREEN ); const fheroes2::Key textSupportModeEventKey = Game::getHotKeyForEvent( Game::HotKeyEvent::GLOBAL_TOGGLE_TEXT_SUPPORT_MODE ); Game::setHotKeyForEvent( Game::HotKeyEvent::DEFAULT_OKAY, fheroes2::Key::NONE ); Game::setHotKeyForEvent( Game::HotKeyEvent::DEFAULT_CANCEL, fheroes2::Key::NONE ); Game::setHotKeyForEvent( Game::HotKeyEvent::GLOBAL_TOGGLE_FULLSCREEN, fheroes2::Key::NONE ); Game::setHotKeyForEvent( Game::HotKeyEvent::GLOBAL_TOGGLE_TEXT_SUPPORT_MODE, fheroes2::Key::NONE ); fheroes2::MultiFontText title; title.add( fheroes2::Text{ _( "Category: " ), fheroes2::FontType::normalYellow() } ); title.add( fheroes2::Text{ _( Game::getHotKeyCategoryName( hotKeyEvent.second ) ), fheroes2::FontType::normalWhite() } ); title.add( fheroes2::Text{ "\n\n", fheroes2::FontType::normalWhite() } ); title.add( fheroes2::Text{ _( "Event: " ), fheroes2::FontType::normalYellow() } ); title.add( fheroes2::Text{ _( Game::getHotKeyEventNameByEventId( hotKeyEvent.first ) ), fheroes2::FontType::normalWhite() } ); const int returnValue = fheroes2::showMessage( fheroes2::Text{}, title, Dialog::OK | Dialog::CANCEL, { &hotKeyUI } ); Game::setHotKeyForEvent( Game::HotKeyEvent::DEFAULT_OKAY, okayEventKey ); Game::setHotKeyForEvent( Game::HotKeyEvent::DEFAULT_CANCEL, cancelEventKey ); Game::setHotKeyForEvent( Game::HotKeyEvent::GLOBAL_TOGGLE_FULLSCREEN, fullscreenEventKey ); Game::setHotKeyForEvent( Game::HotKeyEvent::GLOBAL_TOGGLE_TEXT_SUPPORT_MODE, textSupportModeEventKey ); // To avoid UI issues we need to reset restorer manually. hotKeyUI.reset(); if ( returnValue == Dialog::CANCEL ) { return; } Game::setHotKeyForEvent( hotKeyEvent.first, hotKeyUI.getKey() ); Game::HotKeySave(); } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: std::unique_ptr _listBackground; }; } namespace fheroes2 { void openHotkeysDialog() { // Setup cursor. const CursorRestorer cursorRestorer( true, ::Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); // Dialog height is capped with the current screen height minus 100 pixels. fheroes2::StandardWindow background( keyDescriptionLength + hotKeyLength + 8 + 75, std::min( display.height() - 100, 520 ), true, display ); const fheroes2::Rect roi( background.activeArea() ); const fheroes2::Rect listRoi( roi.x + 24, roi.y + 37, keyDescriptionLength + hotKeyLength + 8, roi.height - 75 ); const fheroes2::Text title( _( "Hot Keys:" ), fheroes2::FontType::normalYellow() ); title.draw( roi.x + ( roi.width - title.width() ) / 2, roi.y + 16, display ); // We divide the list: action description and binded hot-key. background.applyTextBackgroundShading( { listRoi.x, listRoi.y, keyDescriptionLength + 8, listRoi.height } ); background.applyTextBackgroundShading( { listRoi.x + keyDescriptionLength + 8, listRoi.y, hotKeyLength, listRoi.height } ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); // Prepare OKAY button and render its shadow. fheroes2::Button buttonOk; const int buttonOkIcn = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcn, 0, 1, { 0, 7 }, StandardWindow::Padding::BOTTOM_CENTER ); HotKeyList listbox( roi.getPosition() ); listbox.initListBackgroundRestorer( listRoi ); listbox.SetAreaItems( { listRoi.x, listRoi.y + 3, listRoi.width - 3, listRoi.height - 4 } ); int32_t scrollbarOffsetX = roi.x + roi.width - 35; background.renderScrollbarBackground( { scrollbarOffsetX, listRoi.y, listRoi.width, listRoi.height }, isEvilInterface ); const int32_t topPartHeight = 19; const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; ++scrollbarOffsetX; listbox.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, listRoi.y + 1 } ); listbox.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, listRoi.y + listRoi.height - 15 } ); listbox.setScrollBarArea( { scrollbarOffsetX + 2, listRoi.y + topPartHeight, 10, listRoi.height - 2 * topPartHeight } ); listbox.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); listbox.SetAreaMaxItems( ( listRoi.height - 7 ) / fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) ); std::vector> hotKeyEvents = Game::getAllHotKeyEvents(); listbox.SetListContent( hotKeyEvents ); listbox.updateScrollBarImage(); listbox.Redraw(); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); listbox.QueueEventProcessing(); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { return; } if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), Dialog::ZERO ); continue; } if ( !listbox.IsNeedRedraw() ) { continue; } listbox.Redraw(); display.render( roi ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_hotkeys.h000066400000000000000000000027741476115357100231200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace fheroes2 { void openHotkeysDialog(); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_interface_settings.cpp000066400000000000000000000254611476115357100256430ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_interface_settings.h" #include #include #include #include "agg_image.h" #include "cursor.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_option_item.h" namespace { enum class SelectedWindow : int { Configuration, InterfaceType, InterfacePresence, CursorType, Exit }; const fheroes2::Size offsetBetweenOptions{ 118, 110 }; const fheroes2::Point optionOffset{ 69, 47 }; const int32_t optionWindowSize{ 65 }; const fheroes2::Rect interfaceTypeRoi{ optionOffset.x, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect interfacePresenceRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect cursorTypeRoi{ optionOffset.x, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect scrollSpeedRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; void drawInterfacePresence( const fheroes2::Rect & optionRoi ) { // Interface show/hide state. const Settings & conf = Settings::Get(); const bool isHiddenInterface = conf.isHideInterfaceEnabled(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const fheroes2::Sprite & interfaceStateIcon = isHiddenInterface ? fheroes2::AGG::GetICN( ICN::ESPANEL, 4 ) : fheroes2::AGG::GetICN( ICN::SPANEL, isEvilInterface ? 17 : 16 ); std::string value; if ( isHiddenInterface ) { value = _( "Hide" ); } else { value = _( "Show" ); } fheroes2::drawOption( optionRoi, interfaceStateIcon, _( "Interface" ), std::move( value ), fheroes2::UiOptionTextWidth::TWO_ELEMENTS_ROW ); } SelectedWindow showConfigurationWindow( bool & saveConfiguration ) { fheroes2::Display & display = fheroes2::Display::instance(); Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const fheroes2::Sprite & dialog = fheroes2::AGG::GetICN( ( isEvilInterface ? ICN::ESPANBKG_EVIL : ICN::ESPANBKG ), 0 ); const fheroes2::Sprite & dialogShadow = fheroes2::AGG::GetICN( ( isEvilInterface ? ICN::CSPANBKE : ICN::CSPANBKG ), 1 ); const fheroes2::Point dialogOffset( ( display.width() - dialog.width() ) / 2, ( display.height() - dialog.height() ) / 2 ); const fheroes2::Point shadowOffset( dialogOffset.x - fheroes2::borderWidthPx, dialogOffset.y ); const fheroes2::ImageRestorer restorer( display, shadowOffset.x, shadowOffset.y, dialog.width() + fheroes2::borderWidthPx, dialog.height() + fheroes2::borderWidthPx ); const fheroes2::Rect windowRoi{ dialogOffset.x, dialogOffset.y, dialog.width(), dialog.height() }; fheroes2::Blit( dialogShadow, display, windowRoi.x - fheroes2::borderWidthPx, windowRoi.y + fheroes2::borderWidthPx ); fheroes2::Blit( dialog, display, windowRoi.x, windowRoi.y ); fheroes2::ImageRestorer emptyDialogRestorer( display, windowRoi.x, windowRoi.y, windowRoi.width, windowRoi.height ); const fheroes2::Rect windowInterfaceTypeRoi( interfaceTypeRoi + windowRoi.getPosition() ); const fheroes2::Rect windowInterfacePresenceRoi( interfacePresenceRoi + windowRoi.getPosition() ); const fheroes2::Rect windowCursorTypeRoi( cursorTypeRoi + windowRoi.getPosition() ); const fheroes2::Rect windowScrollSpeedRoi( scrollSpeedRoi + windowRoi.getPosition() ); const auto drawOptions = [&conf, &windowInterfaceTypeRoi, &windowInterfacePresenceRoi, &windowCursorTypeRoi, &windowScrollSpeedRoi]() { drawInterfaceType( windowInterfaceTypeRoi, conf.isEvilInterfaceEnabled() ); drawInterfacePresence( windowInterfacePresenceRoi ); drawCursorType( windowCursorTypeRoi, conf.isMonochromeCursorEnabled() ); drawScrollSpeed( windowScrollSpeedRoi, conf.ScrollSpeed() ); }; drawOptions(); const fheroes2::Point buttonOffset( 112 + windowRoi.x, 252 + windowRoi.y ); fheroes2::Button buttonOk( buttonOffset.x, buttonOffset.y, isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD, 0, 1 ); buttonOk.draw(); const auto refreshWindow = [&drawOptions, &emptyDialogRestorer, &buttonOk, &display]() { emptyDialogRestorer.restore(); drawOptions(); buttonOk.draw(); display.render( emptyDialogRestorer.rect() ); }; display.render(); bool isFullScreen = fheroes2::engine().isFullScreen(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.MouseClickLeft( windowInterfaceTypeRoi ) ) { return SelectedWindow::InterfaceType; } if ( le.MouseClickLeft( windowInterfacePresenceRoi ) ) { return SelectedWindow::InterfacePresence; } if ( le.MouseClickLeft( windowCursorTypeRoi ) ) { return SelectedWindow::CursorType; } if ( le.MouseClickLeft( windowScrollSpeedRoi ) ) { saveConfiguration = true; conf.SetScrollSpeed( ( conf.ScrollSpeed() + 1 ) % ( SCROLL_SPEED_VERY_FAST + 1 ) ); refreshWindow(); continue; } if ( le.isMouseWheelUpInArea( windowScrollSpeedRoi ) ) { saveConfiguration = true; conf.SetScrollSpeed( conf.ScrollSpeed() + 1 ); refreshWindow(); continue; } if ( le.isMouseWheelDownInArea( windowScrollSpeedRoi ) ) { saveConfiguration = true; conf.SetScrollSpeed( conf.ScrollSpeed() - 1 ); refreshWindow(); continue; } if ( le.isMouseRightButtonPressedInArea( windowInterfaceTypeRoi ) ) { fheroes2::showStandardTextMessage( _( "Interface Type" ), _( "Toggle the type of interface you want to use." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowInterfacePresenceRoi ) ) { fheroes2::showStandardTextMessage( _( "Interface" ), _( "Toggle interface visibility." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowCursorTypeRoi ) ) { fheroes2::showStandardTextMessage( _( "Mouse Cursor" ), _( "Toggle colored cursor on or off. This is only an aesthetic choice." ), 0 ); } if ( le.isMouseRightButtonPressedInArea( windowScrollSpeedRoi ) ) { fheroes2::showStandardTextMessage( _( "Scroll Speed" ), _( "Sets the speed at which you scroll the window." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } // Fullscreen mode can be toggled using a global hotkey, we need to properly reflect this change in the UI if ( isFullScreen != fheroes2::engine().isFullScreen() ) { isFullScreen = fheroes2::engine().isFullScreen(); emptyDialogRestorer.restore(); drawOptions(); display.render( emptyDialogRestorer.rect() ); } } return SelectedWindow::Exit; } } namespace fheroes2 { bool openInterfaceSettingsDialog( const std::function & updateUI ) { const CursorRestorer cursorRestorer( true, ::Cursor::POINTER ); Settings & conf = Settings::Get(); bool saveConfiguration = false; SelectedWindow windowType = SelectedWindow::Configuration; while ( windowType != SelectedWindow::Exit ) { switch ( windowType ) { case SelectedWindow::Configuration: windowType = showConfigurationWindow( saveConfiguration ); break; case SelectedWindow::InterfaceType: conf.setEvilInterface( !conf.isEvilInterfaceEnabled() ); updateUI(); saveConfiguration = true; windowType = SelectedWindow::Configuration; break; case SelectedWindow::InterfacePresence: conf.setHideInterface( !conf.isHideInterfaceEnabled() ); updateUI(); saveConfiguration = true; windowType = SelectedWindow::Configuration; break; case SelectedWindow::CursorType: conf.setMonochromeCursor( !conf.isMonochromeCursorEnabled() ); saveConfiguration = true; windowType = SelectedWindow::Configuration; break; default: return saveConfiguration; } } return saveConfiguration; } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_interface_settings.h000066400000000000000000000031051476115357100252770ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace fheroes2 { bool openInterfaceSettingsDialog( const std::function & updateUI ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_language_selection.cpp000066400000000000000000000332201476115357100256030ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_language_selection.h" #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "game_language.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_window.h" namespace { const int32_t verticalPaddingAreasHight = 30; const int32_t textAreaWidth = 270; const int32_t scrollBarAreaWidth = 48; const int32_t paddingLeftSide = 24; class LanguageList : public Interface::ListBox { public: using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; using Interface::ListBox::ActionListDoubleClick; explicit LanguageList( const fheroes2::Point & offset ) : Interface::ListBox( offset ) , _isDoubleClicked( false ) { // Do nothing. } void RedrawItem( const fheroes2::SupportedLanguage & language, int32_t offsetX, int32_t offsetY, bool isSelected ) override { fheroes2::LanguageSwitcher languageSwitcher( language ); const fheroes2::Text languageName( fheroes2::getLanguageName( language ), isSelected ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ); languageName.draw( ( textAreaWidth - languageName.width() ) / 2 + offsetX, offsetY, fheroes2::Display::instance() ); } void RedrawBackground( const fheroes2::Point & /* unused */ ) override { _listBackground->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListSingleClick( fheroes2::SupportedLanguage & /*language*/ ) override { // Do nothing. } void ActionListPressRight( fheroes2::SupportedLanguage & /*language*/ ) override { // Do nothing. } void ActionListDoubleClick( fheroes2::SupportedLanguage & /*language*/ ) override { _isDoubleClicked = true; } bool isDoubleClicked() const { return _isDoubleClicked; } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: bool _isDoubleClicked; std::unique_ptr _listBackground; }; void redrawDialogInfo( const fheroes2::Rect & listRoi, const fheroes2::SupportedLanguage language, const bool isGameLanguage ) { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::FontType fontType = fheroes2::FontType::normalYellow(); const fheroes2::Text title( isGameLanguage ? _( "Select Game Language:" ) : _( "Select Language:" ), fontType ); title.draw( listRoi.x + ( listRoi.width - title.width() ) / 2, listRoi.y - ( verticalPaddingAreasHight + title.height() + 2 ) / 2, display ); const fheroes2::LanguageSwitcher languageSwitcher( language ); const fheroes2::Text selectedLanguage( fheroes2::getLanguageName( language ), fontType ); selectedLanguage.draw( listRoi.x + ( listRoi.width - selectedLanguage.width() ) / 2, listRoi.y + listRoi.height + 12 + ( 21 - selectedLanguage.height() ) / 2 + 2, display ); } bool getLanguage( const std::vector & languages, fheroes2::SupportedLanguage & chosenLanguage, const bool isGameLanguage ) { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const int32_t listHeightDeduction = 112; const int32_t listAreaOffsetY = 3; const int32_t listAreaHeightDeduction = 4; // If we don't have many languages, we reduce the maximum dialog height, // but not less than enough for 11 elements. // We also limit the maximum list height to 22 lines. const int32_t maxDialogHeight = fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) * std::clamp( static_cast( languages.size() ), 11, 22 ) + listAreaOffsetY + listAreaHeightDeduction + listHeightDeduction; fheroes2::Display & display = fheroes2::Display::instance(); // Dialog height is also capped with the current screen height. fheroes2::StandardWindow background( paddingLeftSide + textAreaWidth + scrollBarAreaWidth + 3, std::min( display.height() - 100, maxDialogHeight ), true, display ); const fheroes2::Rect roi( background.activeArea() ); const fheroes2::Rect listRoi( roi.x + paddingLeftSide, roi.y + 37, textAreaWidth, roi.height - listHeightDeduction ); // We divide the list: language list and selected language. const fheroes2::Rect selectedLangRoi( listRoi.x, listRoi.y + listRoi.height + 12, listRoi.width, 21 ); background.applyTextBackgroundShading( selectedLangRoi ); background.applyTextBackgroundShading( { listRoi.x, listRoi.y, listRoi.width, listRoi.height } ); fheroes2::ImageRestorer titleBackground( fheroes2::Display::instance(), roi.x, listRoi.y - verticalPaddingAreasHight, roi.width, verticalPaddingAreasHight ); fheroes2::ImageRestorer selectedLangBackground( fheroes2::Display::instance(), selectedLangRoi.x, selectedLangRoi.y, listRoi.width, selectedLangRoi.height ); fheroes2::ImageRestorer buttonsBackground( fheroes2::Display::instance(), roi.x, selectedLangRoi.y + selectedLangRoi.height + 10, roi.width, verticalPaddingAreasHight ); LanguageList listBox( roi.getPosition() ); listBox.initListBackgroundRestorer( listRoi ); Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); // Prepare OKAY and CANCEL buttons and render their shadows. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); listBox.SetAreaItems( { listRoi.x, listRoi.y + 3, listRoi.width - 3, listRoi.height - 4 } ); int32_t scrollbarOffsetX = roi.x + roi.width - 35; background.renderScrollbarBackground( { scrollbarOffsetX, listRoi.y, listRoi.width, listRoi.height }, isEvilInterface ); const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; const int32_t topPartHeight = 19; ++scrollbarOffsetX; listBox.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, listRoi.y + 1 } ); listBox.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, listRoi.y + listRoi.height - 15 } ); listBox.setScrollBarArea( { scrollbarOffsetX + 2, listRoi.y + topPartHeight, 10, listRoi.height - 2 * topPartHeight } ); listBox.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); listBox.SetAreaMaxItems( ( listRoi.height - 7 ) / fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) ); std::vector temp = languages; listBox.SetListContent( temp ); listBox.updateScrollBarImage(); for ( size_t i = 0; i < languages.size(); ++i ) { if ( languages[i] == chosenLanguage ) { listBox.SetCurrent( i ); break; } } listBox.Redraw(); redrawDialogInfo( listRoi, chosenLanguage, isGameLanguage ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { if ( buttonOk.isEnabled() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.isMouseRightButtonPressedInArea( listRoi ) ) { continue; } const int listId = listBox.getCurrentId(); listBox.QueueEventProcessing(); const bool needRedraw = listId != listBox.getCurrentId(); if ( ( buttonOk.isEnabled() && le.MouseClickLeft( buttonOk.area() ) ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || listBox.isDoubleClicked() ) { return true; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return false; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to choose the selected language." ), Dialog::ZERO ); } if ( !listBox.IsNeedRedraw() ) { continue; } if ( needRedraw ) { const fheroes2::SupportedLanguage newChosenLanguage = listBox.GetCurrent(); if ( newChosenLanguage != chosenLanguage ) { chosenLanguage = newChosenLanguage; if ( isGameLanguage ) { conf.setGameLanguage( fheroes2::getLanguageAbbreviation( chosenLanguage ) ); } titleBackground.restore(); selectedLangBackground.restore(); redrawDialogInfo( listRoi, chosenLanguage, isGameLanguage ); buttonsBackground.restore(); background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); } } listBox.Redraw(); display.render( roi ); } return false; } } namespace fheroes2 { SupportedLanguage selectLanguage( const std::vector & languages, const SupportedLanguage currentLanguage, const bool isGameLanguage ) { if ( languages.empty() ) { // Why do you even call this function having 0 languages? assert( 0 ); Settings::Get().setGameLanguage( fheroes2::getLanguageAbbreviation( SupportedLanguage::English ) ); return SupportedLanguage::English; } if ( languages.size() == 1 ) { Settings::Get().setGameLanguage( fheroes2::getLanguageAbbreviation( languages.front() ) ); return languages.front(); } SupportedLanguage chosenLanguage = languages.front(); for ( const SupportedLanguage language : languages ) { if ( currentLanguage == language ) { chosenLanguage = currentLanguage; break; } } if ( !getLanguage( languages, chosenLanguage, isGameLanguage ) ) { if ( isGameLanguage ) { Settings::Get().setGameLanguage( fheroes2::getLanguageAbbreviation( currentLanguage ) ); } return currentLanguage; } return chosenLanguage; } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_language_selection.h000066400000000000000000000033761476115357100252610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace fheroes2 { enum class SupportedLanguage : uint8_t; // UI window to select a language by user. SupportedLanguage selectLanguage( const std::vector & languages, const SupportedLanguage currentLanguage, const bool isGameLanguage ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_levelup.cpp000066400000000000000000000252651476115357100234410ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_text.h" namespace { void DialogPrimaryOnly( const std::string & name, const int primarySkillType ) { std::string message = _( "%{name} has gained a level." ); message.append( "\n\n" ); message.append( _( "%{skill} +1" ) ); StringReplace( message, "%{name}", name ); StringReplace( message, "%{skill}", Skill::Primary::String( primarySkillType ) ); const fheroes2::PrimarySkillDialogElement primarySkillUI( primarySkillType, "+1" ); fheroes2::showStandardTextMessage( {}, std::move( message ), Dialog::OK, { &primarySkillUI } ); } int DialogOneSecondary( const Heroes & hero, const std::string & name, const int primarySkillType, const Skill::Secondary & sec ) { std::string message = _( "%{name} has gained a level." ); message.append( "\n\n" ); message.append( _( "%{skill} +1" ) ); StringReplace( message, "%{name}", name ); StringReplace( message, "%{skill}", Skill::Primary::String( primarySkillType ) ); message.append( "\n\n" ); message.append( _( "You have learned %{skill}." ) ); StringReplace( message, "%{skill}", sec.GetName() ); const fheroes2::SecondarySkillDialogElement secondarySkillUI( sec, hero ); fheroes2::showStandardTextMessage( {}, std::move( message ), Dialog::OK, { &secondarySkillUI } ); return sec.Skill(); } int DialogSelectSecondary( const std::string & name, const int primarySkillType, const Skill::Secondary & sec1, const Skill::Secondary & sec2, Heroes & hero ) { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); std::string header = _( "%{name} has gained a level.\n\n%{skill} +1" ); StringReplace( header, "%{name}", name ); StringReplace( header, "%{skill}", Skill::Primary::String( primarySkillType ) ); std::string body = _( "You may learn either:\n%{skill1}\nor\n%{skill2}" ); StringReplace( body, "%{skill1}", sec1.GetName() ); StringReplace( body, "%{skill2}", sec2.GetName() ); const fheroes2::Text headerText{ std::move( header ), fheroes2::FontType::normalWhite() }; const fheroes2::Text bodyText{ std::move( body ), fheroes2::FontType::normalWhite() }; const int spacer = 10; const fheroes2::SecondarySkillDialogElement skillLeft{ sec1, hero }; const fheroes2::SecondarySkillDialogElement skillRight{ sec2, hero }; const Dialog::FrameBox dialogFrame( headerText.height( fheroes2::boxAreaWidthPx ) + spacer + bodyText.height( fheroes2::boxAreaWidthPx ) + 10 + skillLeft.area().height, true ); const Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const int buttonLearnIcnID = isEvilInterface ? ICN::BUTTON_SMALL_LEARN_EVIL : ICN::BUTTON_SMALL_LEARN_GOOD; const fheroes2::Rect & dialogRoi = dialogFrame.GetArea(); const fheroes2::Sprite & buttonLearnImage = fheroes2::AGG::GetICN( buttonLearnIcnID, 0 ); fheroes2::Point offset; offset.x = dialogRoi.x + dialogRoi.width / 2 - buttonLearnImage.width() - 20; offset.y = dialogRoi.y + dialogRoi.height - buttonLearnImage.height(); fheroes2::Button buttonLearnLeft( offset.x, offset.y, buttonLearnIcnID, 0, 1 ); offset.x = dialogRoi.x + dialogRoi.width / 2 + 20; offset.y = dialogRoi.y + dialogRoi.height - buttonLearnImage.height(); fheroes2::Button buttonLearnRight( offset.x, offset.y, buttonLearnIcnID, 0, 1 ); offset = { dialogRoi.x, dialogRoi.y }; fheroes2::Display & display = fheroes2::Display::instance(); headerText.draw( offset.x, offset.y + 2, fheroes2::boxAreaWidthPx, display ); offset.y += headerText.height( fheroes2::boxAreaWidthPx ) + spacer; bodyText.draw( offset.x, offset.y + 2, fheroes2::boxAreaWidthPx, display ); offset.y += bodyText.height( fheroes2::boxAreaWidthPx ) + spacer; offset.x = dialogRoi.x + dialogRoi.width / 2 - skillLeft.area().width - 20; offset.x += 3; skillLeft.draw( display, offset ); const fheroes2::Rect skillLeftRoi{ offset.x, offset.y, skillLeft.area().width, skillLeft.area().height }; offset.x = dialogRoi.x + dialogRoi.width / 2 + 20; offset.x += 3; skillRight.draw( display, offset ); const fheroes2::Rect skillRightRoi{ offset.x, offset.y, skillRight.area().width, skillRight.area().height }; // hero button offset.x = dialogRoi.x + dialogRoi.width / 2 - 18; offset.y = dialogRoi.y + dialogRoi.height - 35; const int icnHeroes = isEvilInterface ? ICN::EVIL_ARMY_BUTTON : ICN::GOOD_ARMY_BUTTON; fheroes2::ButtonSprite buttonHero = fheroes2::makeButtonWithBackground( offset.x, offset.y, fheroes2::AGG::GetICN( icnHeroes, 0 ), fheroes2::AGG::GetICN( icnHeroes, 1 ), display ); const fheroes2::Text text{ std::to_string( hero.GetSecondarySkills().Count() ) + "/" + std::to_string( Heroes::maxNumOfSecSkills ), fheroes2::FontType::normalWhite() }; text.draw( dialogRoi.x + ( dialogRoi.width - text.width() ) / 2, offset.y - 15, display ); buttonLearnLeft.draw(); buttonLearnRight.draw(); buttonHero.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonLearnLeft.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLearnLeft.area() ) ); buttonLearnRight.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLearnRight.area() ) ); buttonHero.drawOnState( le.isMouseLeftButtonPressedInArea( buttonHero.area() ) ); if ( le.MouseClickLeft( buttonLearnLeft.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_LEFT ) ) { return sec1.Skill(); } if ( le.MouseClickLeft( buttonLearnRight.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) ) { return sec2.Skill(); } if ( le.MouseClickLeft( buttonHero.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) { le.reset(); hero.OpenDialog( false, true, true, true, true, false, fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() ) ); display.render(); } if ( le.MouseClickLeft( skillLeftRoi ) ) { skillLeft.showPopup( Dialog::OK ); } else if ( le.MouseClickLeft( skillRightRoi ) ) { skillRight.showPopup( Dialog::OK ); } if ( le.isMouseRightButtonPressedInArea( skillLeftRoi ) ) { skillLeft.showPopup( Dialog::ZERO ); display.render(); } else if ( le.isMouseRightButtonPressedInArea( skillRightRoi ) ) { skillRight.showPopup( Dialog::ZERO ); display.render(); } else if ( le.isMouseRightButtonPressedInArea( buttonHero.area() ) ) { fheroes2::showStandardTextMessage( "", _( "View Hero" ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonLearnLeft.area() ) ) { std::string message = _( "Learn %{secondary-skill}" ); StringReplace( message, "%{secondary-skill}", sec1.GetName() ); fheroes2::showStandardTextMessage( "", std::move( message ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonLearnRight.area() ) ) { std::string message = _( "Learn %{secondary-skill}" ); StringReplace( message, "%{secondary-skill}", sec2.GetName() ); fheroes2::showStandardTextMessage( "", std::move( message ), Dialog::ZERO ); } } return Skill::Secondary::UNKNOWN; } } int Dialog::LevelUpSelectSkill( const std::string & name, const int primarySkillType, const Skill::Secondary & sec1, const Skill::Secondary & sec2, Heroes & hero ) { if ( Skill::Secondary::UNKNOWN == sec1.Skill() && Skill::Secondary::UNKNOWN == sec2.Skill() ) { DialogPrimaryOnly( name, primarySkillType ); return Skill::Secondary::UNKNOWN; } if ( Skill::Secondary::UNKNOWN == sec1.Skill() || Skill::Secondary::UNKNOWN == sec2.Skill() ) { return DialogOneSecondary( hero, name, primarySkillType, ( Skill::Secondary::UNKNOWN == sec2.Skill() ? sec1 : sec2 ) ); } return DialogSelectSecondary( name, primarySkillType, sec1, sec2, hero ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_marketplace.cpp000066400000000000000000000720051476115357100242470ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "math_base.h" #include "players.h" #include "resource.h" #include "resource_trading.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_kingdom.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_tool.h" #include "world.h" namespace { uint32_t GetTradeCosts( const Kingdom & kingdom, int rs_from, int rs_to, bool tradingPost ) { return fheroes2::getTradeCost( ( tradingPost ? 3 : kingdom.GetCountMarketplace() ), rs_from, rs_to ); } std::string GetStringTradeCosts( const Kingdom & kingdom, int rs_from, int rs_to, bool tradingPost ) { std::string res; if ( rs_from == rs_to ) { res = _( "n/a" ); } else { res = "1/"; res.append( std::to_string( GetTradeCosts( kingdom, rs_from, rs_to, tradingPost ) ) ); } return res; } class TradeWindowGUI { public: explicit TradeWindowGUI( const fheroes2::Rect & rt ) : pos_rt( rt ) , back( fheroes2::Display::instance() ) , tradpostIcnId( Settings::Get().isEvilInterfaceEnabled() ? ICN::TRADPOSE : ICN::TRADPOST ) , textSell( fheroes2::Display::instance() ) , textBuy( fheroes2::Display::instance() ) { Settings & conf = Settings::Get(); back.update( rt.x - 5, rt.y + 15, rt.width + 10, 160 ); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const int tradeButtonIcnID = isEvilInterface ? ICN::BUTTON_SMALL_TRADE_EVIL : ICN::BUTTON_SMALL_TRADE_GOOD; const int giftButtonIcnID = isEvilInterface ? ICN::BUTTON_GIFT_EVIL : ICN::BUTTON_GIFT_GOOD; buttonGift.setICNInfo( giftButtonIcnID, 0, 1 ); buttonTrade.setICNInfo( tradeButtonIcnID, 0, 1 ); buttonLeft.setICNInfo( tradpostIcnId, 3, 4 ); buttonRight.setICNInfo( tradpostIcnId, 5, 6 ); const fheroes2::Sprite & spriteGift = fheroes2::AGG::GetICN( giftButtonIcnID, 0 ); const fheroes2::Sprite & spriteTrade = fheroes2::AGG::GetICN( tradeButtonIcnID, 0 ); buttonGift.setPosition( pos_rt.x - 68 + ( pos_rt.width - spriteGift.width() ) / 2, pos_rt.y + pos_rt.height - spriteGift.height() ); buttonTrade.setPosition( pos_rt.x + ( pos_rt.width - spriteTrade.width() ) / 2, pos_rt.y + 150 ); buttonLeft.setPosition( pos_rt.x + 11, pos_rt.y + 129 ); buttonRight.setPosition( pos_rt.x + 220, pos_rt.y + 129 ); _scrollbar.setImage( fheroes2::AGG::GetICN( tradpostIcnId, 2 ) ); _scrollbar.setArea( { pos_rt.x + ( pos_rt.width - fheroes2::AGG::GetICN( tradpostIcnId, 1 ).width() ) / 2 + 22, pos_rt.y + 131, 187, 11 } ); _scrollbar.hide(); const fheroes2::Text text( _( "Please inspect our fine wares. If you feel like offering a trade, click on the items you wish to trade with and for." ), fheroes2::FontType::normalWhite() ); text.draw( pos_rt.x, pos_rt.y + 32, pos_rt.width, fheroes2::Display::instance() ); const Players & players = conf.GetPlayers(); // If there are less than two active players in the game, then there is no one to give resources to const bool isGiftDisabled = ( std::count_if( players.begin(), players.end(), []( const Player * player ) { if ( player == nullptr ) { return false; } return world.GetKingdom( player->GetColor() ).isPlay(); } ) < 2 ); isGiftDisabled ? buttonGift.disable() : buttonGift.enable(); } void RedrawInfoBuySell( uint32_t count_sell, uint32_t count_buy, uint32_t max_sell, uint32_t orig_buy ); void ShowTradeArea( const Kingdom & kingdom, int resourceFrom, int resourceTo, uint32_t max_buy, uint32_t max_sell, uint32_t count_buy, uint32_t count_sell, const bool fromTradingPost, const bool firstExchange ); fheroes2::Rect buttonMax; fheroes2::Rect buttonMin; fheroes2::Button buttonTrade; fheroes2::Button buttonLeft; fheroes2::Button buttonRight; fheroes2::Button buttonGift; fheroes2::Scrollbar _scrollbar; private: fheroes2::Rect pos_rt; fheroes2::ImageRestorer back; const int tradpostIcnId; fheroes2::MovableText textSell; fheroes2::MovableText textBuy; }; void TradeWindowGUI::ShowTradeArea( const Kingdom & kingdom, int resourceFrom, int resourceTo, uint32_t max_buy, uint32_t max_sell, uint32_t count_buy, uint32_t count_sell, const bool fromTradingPost, const bool firstExchange ) { fheroes2::Display & display = fheroes2::Display::instance(); const bool disable = kingdom.GetFunds().Get( resourceFrom ) <= 0; if ( disable || resourceFrom == resourceTo || ( Resource::GOLD != resourceTo && 0 == max_buy ) ) { _scrollbar.hide(); back.restore(); const fheroes2::Rect dst_rt( pos_rt.x, pos_rt.y + 30, pos_rt.width, 100 ); std::string message = firstExchange && ( resourceFrom == resourceTo || 0 == max_buy ) ? _( "Please inspect our fine wares. If you feel like offering a trade, click on the items you wish to trade with and for." ) : _( "You have received quite a bargain. I expect to make no profit on the deal. Can I interest you in any of my other wares?" ); const fheroes2::Text displayMessage( std::move( message ), fheroes2::FontType::normalWhite() ); displayMessage.draw( dst_rt.x, dst_rt.y + 2, dst_rt.width, display ); buttonTrade.disable(); buttonLeft.disable(); buttonRight.disable(); buttonGift.draw(); buttonMax = fheroes2::Rect(); buttonMin = fheroes2::Rect(); } else { back.restore(); const fheroes2::Sprite & bar = fheroes2::AGG::GetICN( tradpostIcnId, 1 ); fheroes2::Point dst_pt( pos_rt.x + ( pos_rt.width - bar.width() ) / 2 - 2, pos_rt.y + 128 ); fheroes2::Blit( bar, display, dst_pt.x, dst_pt.y ); const uint32_t maximumValue = ( Resource::GOLD == resourceTo ) ? max_sell : max_buy; const fheroes2::Sprite & originalSlider = fheroes2::AGG::GetICN( tradpostIcnId, 2 ); const fheroes2::Image scrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, true, 187, 1, static_cast( maximumValue + 1 ), { 0, 0, 2, originalSlider.height() }, { 2, 0, 8, originalSlider.height() } ); _scrollbar.setImage( scrollbarSlider ); _scrollbar.setRange( 0, maximumValue ); const uint32_t exchange_rate = GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ); std::string message; if ( Resource::GOLD == resourceTo ) { message = _( "I can offer you %{count} for 1 unit of %{resfrom}." ); StringReplace( message, "%{count}", exchange_rate ); StringReplace( message, "%{resfrom}", Resource::String( resourceFrom ) ); } else { message = _( "I can offer you 1 unit of %{resto} for %{count} units of %{resfrom}." ); StringReplace( message, "%{resto}", Resource::String( resourceTo ) ); StringReplace( message, "%{resfrom}", Resource::String( resourceFrom ) ); StringReplace( message, "%{count}", exchange_rate ); } const fheroes2::Text displayMessage( std::move( message ), fheroes2::FontType::normalWhite() ); displayMessage.draw( pos_rt.x, pos_rt.y + 32, pos_rt.width, display ); const fheroes2::Sprite & sprite_from = fheroes2::AGG::GetICN( ICN::RESOURCE, Resource::getIconIcnIndex( resourceFrom ) ); dst_pt.x = pos_rt.x + ( pos_rt.width - sprite_from.width() + 1 ) / 2 - 70; dst_pt.y = pos_rt.y + 115 - sprite_from.height(); fheroes2::Blit( sprite_from, display, dst_pt.x, dst_pt.y ); const fheroes2::Sprite & sprite_to = fheroes2::AGG::GetICN( ICN::RESOURCE, Resource::getIconIcnIndex( resourceTo ) ); dst_pt.x = pos_rt.x + ( pos_rt.width - sprite_to.width() + 1 ) / 2 + 70; dst_pt.y = pos_rt.y + 115 - sprite_to.height(); fheroes2::Blit( sprite_to, display, dst_pt.x, dst_pt.y ); const fheroes2::Sprite & sprite_fromto = fheroes2::AGG::GetICN( tradpostIcnId, 0 ); dst_pt.x = pos_rt.x + ( pos_rt.width - sprite_fromto.width() ) / 2; dst_pt.y = pos_rt.y + 90; fheroes2::Blit( sprite_fromto, display, dst_pt.x, dst_pt.y ); fheroes2::Text text( _( "Max" ), fheroes2::FontType::smallYellow() ); dst_pt.x = pos_rt.x + ( pos_rt.width - text.width() ) / 2 - 5; dst_pt.y = pos_rt.y + 80; buttonMax = fheroes2::Rect( dst_pt.x, dst_pt.y, text.width(), text.height() ); text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( _( "Min" ), fheroes2::FontType::smallYellow() ); dst_pt.x = pos_rt.x + ( pos_rt.width - text.width() ) / 2 - 5; dst_pt.y = pos_rt.y + 103; buttonMin = fheroes2::Rect( dst_pt.x, dst_pt.y, text.width(), text.height() ); text.draw( dst_pt.x, dst_pt.y + 2, display ); text.set( _( "Qty to trade" ), fheroes2::FontType::smallWhite() ); dst_pt.x = pos_rt.x + ( pos_rt.width - text.width() ) / 2; dst_pt.y = pos_rt.y + 115; text.draw( dst_pt.x, dst_pt.y + 2, display ); buttonTrade.enable(); buttonLeft.enable(); buttonRight.enable(); buttonTrade.draw(); buttonLeft.draw(); buttonRight.draw(); RedrawInfoBuySell( count_sell, count_buy, max_sell, kingdom.GetFunds().Get( resourceTo ) ); _scrollbar.show(); } display.render(); } void TradeWindowGUI::RedrawInfoBuySell( uint32_t count_sell, uint32_t count_buy, uint32_t max_sell, uint32_t orig_buy ) { fheroes2::Point dst_pt; _scrollbar.hide(); auto text = std::make_unique( std::string( "-" ) + std::to_string( count_sell ) + " " + "(" + std::to_string( max_sell - count_sell ) + ")", fheroes2::FontType::smallWhite() ); int32_t textWidth = text->width(); textSell.update( std::move( text ) ); dst_pt.x = pos_rt.x + pos_rt.width / 2 - 70 - ( textWidth + 1 ) / 2; dst_pt.y = pos_rt.y + 116; textSell.draw( dst_pt.x, dst_pt.y ); text = std::make_unique( std::string( "+" ) + std::to_string( count_buy ) + " " + "(" + std::to_string( orig_buy + count_buy ) + ")", fheroes2::FontType::smallWhite() ); textWidth = text->width(); textBuy.update( std::move( text ) ); dst_pt.x = pos_rt.x + pos_rt.width / 2 + 70 - ( textWidth + 1 ) / 2; dst_pt.y = pos_rt.y + 116; textBuy.draw( dst_pt.x, dst_pt.y ); _scrollbar.show(); } void RedrawResourceSprite( const fheroes2::Image & sf, int32_t px, int32_t py, int32_t value ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( sf, display, px, py ); const fheroes2::Text text( std::to_string( value ), fheroes2::FontType::smallWhite() ); text.draw( px + ( 34 - text.width() ) / 2, py + 23, display ); } void RedrawFromResource( const fheroes2::Point & pt, const Funds & rs ) { const int tradpost = Settings::Get().isEvilInterfaceEnabled() ? ICN::TRADPOSE : ICN::TRADPOST; // wood RedrawResourceSprite( fheroes2::AGG::GetICN( tradpost, 7 ), pt.x, pt.y, rs.wood ); // mercury RedrawResourceSprite( fheroes2::AGG::GetICN( tradpost, 8 ), pt.x + 37, pt.y, rs.mercury ); // ore RedrawResourceSprite( fheroes2::AGG::GetICN( tradpost, 9 ), pt.x + 74, pt.y, rs.ore ); // sulfur RedrawResourceSprite( fheroes2::AGG::GetICN( tradpost, 10 ), pt.x, pt.y + 37, rs.sulfur ); // crystal RedrawResourceSprite( fheroes2::AGG::GetICN( tradpost, 11 ), pt.x + 37, pt.y + 37, rs.crystal ); // gems RedrawResourceSprite( fheroes2::AGG::GetICN( tradpost, 12 ), pt.x + 74, pt.y + 37, rs.gems ); // gold RedrawResourceSprite( fheroes2::AGG::GetICN( tradpost, 13 ), pt.x + 37, pt.y + 74, rs.gold ); } void RedrawResourceSprite2( const fheroes2::Image & sf, int32_t px, int32_t py, bool show, const Kingdom & kingdom, int from, int res, bool trading ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( sf, display, px, py ); if ( show ) { const fheroes2::Text text( GetStringTradeCosts( kingdom, from, res, trading ), fheroes2::FontType::smallWhite() ); text.draw( px + ( 34 - text.width() ) / 2, py + 23, display ); } } void RedrawToResource( const fheroes2::Point & pt, bool showcost, const Kingdom & kingdom, bool tradingPost, int from_resource ) { const int tradpost = Settings::Get().isEvilInterfaceEnabled() ? ICN::TRADPOSE : ICN::TRADPOST; // wood RedrawResourceSprite2( fheroes2::AGG::GetICN( tradpost, 7 ), pt.x, pt.y, showcost, kingdom, from_resource, Resource::WOOD, tradingPost ); // mercury RedrawResourceSprite2( fheroes2::AGG::GetICN( tradpost, 8 ), pt.x + 37, pt.y, showcost, kingdom, from_resource, Resource::MERCURY, tradingPost ); // ore RedrawResourceSprite2( fheroes2::AGG::GetICN( tradpost, 9 ), pt.x + 74, pt.y, showcost, kingdom, from_resource, Resource::ORE, tradingPost ); // sulfur RedrawResourceSprite2( fheroes2::AGG::GetICN( tradpost, 10 ), pt.x, pt.y + 37, showcost, kingdom, from_resource, Resource::SULFUR, tradingPost ); // crystal RedrawResourceSprite2( fheroes2::AGG::GetICN( tradpost, 11 ), pt.x + 37, pt.y + 37, showcost, kingdom, from_resource, Resource::CRYSTAL, tradingPost ); // gems RedrawResourceSprite2( fheroes2::AGG::GetICN( tradpost, 12 ), pt.x + 74, pt.y + 37, showcost, kingdom, from_resource, Resource::GEMS, tradingPost ); // gold RedrawResourceSprite2( fheroes2::AGG::GetICN( tradpost, 13 ), pt.x + 37, pt.y + 74, showcost, kingdom, from_resource, Resource::GOLD, tradingPost ); } } void Dialog::Marketplace( Kingdom & kingdom, bool fromTradingPost ) { fheroes2::Display & display = fheroes2::Display::instance(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int tradpost = isEvilInterface ? ICN::TRADPOSE : ICN::TRADPOST; const std::string & header = fromTradingPost ? _( "Trading Post" ) : _( "Marketplace" ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); Dialog::FrameBox box( 297, true ); const fheroes2::Rect & pos_rt = box.GetArea(); fheroes2::Point dst_pt( pos_rt.x, pos_rt.y ); // header fheroes2::Text text{ header, fheroes2::FontType::normalYellow() }; dst_pt.x = pos_rt.x + ( pos_rt.width - text.width() ) / 2; dst_pt.y = pos_rt.y; text.draw( dst_pt.x, dst_pt.y + 2, display ); TradeWindowGUI gui( pos_rt ); Funds fundsFrom = kingdom.GetFunds(); int resourceFrom = 0; const fheroes2::Point pt1( pos_rt.x, pos_rt.y + 190 ); std::vector rectsFrom; rectsFrom.reserve( 7 ); rectsFrom.emplace_back( pt1.x, pt1.y, 34, 34 ); // wood rectsFrom.emplace_back( pt1.x + 37, pt1.y, 34, 34 ); // mercury rectsFrom.emplace_back( pt1.x + 74, pt1.y, 34, 34 ); // ore rectsFrom.emplace_back( pt1.x, pt1.y + 37, 34, 34 ); // sulfur rectsFrom.emplace_back( pt1.x + 37, pt1.y + 37, 34, 34 ); // crystal rectsFrom.emplace_back( pt1.x + 74, pt1.y + 37, 34, 34 ); // gems rectsFrom.emplace_back( pt1.x + 37, pt1.y + 74, 34, 34 ); // gold fheroes2::MovableSprite cursorFrom( fheroes2::AGG::GetICN( tradpost, 14 ) ); text.set( _( "Your Resources" ), fheroes2::FontType::smallWhite() ); dst_pt.x = pt1.x + ( 108 - text.width() ) / 2; dst_pt.y = pt1.y - 15; text.draw( dst_pt.x, dst_pt.y + 2, display ); RedrawFromResource( pt1, fundsFrom ); int resourceTo = 0; const fheroes2::Point pt2( 136 + pos_rt.x, pos_rt.y + 190 ); std::vector rectsTo; rectsTo.reserve( 7 ); rectsTo.emplace_back( pt2.x, pt2.y, 34, 34 ); // wood rectsTo.emplace_back( pt2.x + 37, pt2.y, 34, 34 ); // mercury rectsTo.emplace_back( pt2.x + 74, pt2.y, 34, 34 ); // ore rectsTo.emplace_back( pt2.x, pt2.y + 37, 34, 34 ); // sulfur rectsTo.emplace_back( pt2.x + 37, pt2.y + 37, 34, 34 ); // crystal rectsTo.emplace_back( pt2.x + 74, pt2.y + 37, 34, 34 ); // gems rectsTo.emplace_back( pt2.x + 37, pt2.y + 74, 34, 34 ); // gold fheroes2::MovableSprite cursorTo( fheroes2::AGG::GetICN( tradpost, 14 ) ); text.set( _( "Available Trades" ), fheroes2::FontType::smallWhite() ); dst_pt.x = pt2.x + ( 108 - text.width() ) / 2; dst_pt.y = pt2.y - 15; text.draw( dst_pt.x, dst_pt.y + 2, display ); RedrawToResource( pt2, false, kingdom, fromTradingPost, 0 ); uint32_t count_sell = 0; uint32_t count_buy = 0; uint32_t max_sell = 0; uint32_t max_buy = 0; const fheroes2::Rect & buttonMax = gui.buttonMax; const fheroes2::Rect & buttonMin = gui.buttonMin; fheroes2::Button & buttonGift = gui.buttonGift; fheroes2::Button & buttonTrade = gui.buttonTrade; fheroes2::Button & buttonLeft = gui.buttonLeft; fheroes2::Button & buttonRight = gui.buttonRight; fheroes2::TimedEventValidator timedButtonLeft( [&buttonLeft]() { return buttonLeft.isPressed(); } ); fheroes2::TimedEventValidator timedButtonRight( [&buttonRight]() { return buttonRight.isPressed(); } ); buttonLeft.subscribe( &timedButtonLeft ); buttonRight.subscribe( &timedButtonRight ); fheroes2::Scrollbar & scrollbar = gui._scrollbar; // button exit const int exitButtonIcnID = isEvilInterface ? ICN::UNIFORM_EVIL_EXIT_BUTTON : ICN::UNIFORM_GOOD_EXIT_BUTTON; const fheroes2::Sprite & spriteExit = fheroes2::AGG::GetICN( exitButtonIcnID, 0 ); dst_pt.x = pos_rt.x + 68 + ( pos_rt.width - spriteExit.width() ) / 2; dst_pt.y = pos_rt.y + pos_rt.height - spriteExit.height(); fheroes2::Button buttonExit( dst_pt.x, dst_pt.y, exitButtonIcnID, 0, 1 ); buttonTrade.disable(); buttonGift.draw(); buttonExit.draw(); display.render(); LocalEvent & le = LocalEvent::Get(); bool firstExchange = true; // message loop while ( le.HandleEvents() ) { if ( buttonGift.isEnabled() ) { buttonGift.drawOnState( le.isMouseLeftButtonPressedInArea( buttonGift.area() ) ); } if ( buttonTrade.isEnabled() ) { buttonTrade.drawOnState( le.isMouseLeftButtonPressedInArea( buttonTrade.area() ) ); } if ( buttonLeft.isEnabled() ) { buttonLeft.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLeft.area() ) ); } if ( buttonRight.isEnabled() ) { buttonRight.drawOnState( le.isMouseLeftButtonPressedInArea( buttonRight.area() ) ); } buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) break; // gift resources if ( buttonGift.isEnabled() && le.MouseClickLeft( buttonGift.area() ) ) { Dialog::MakeGiftResource( kingdom ); resourceTo = Resource::UNKNOWN; resourceFrom = Resource::UNKNOWN; gui.ShowTradeArea( kingdom, resourceFrom, resourceTo, 0, 0, 0, 0, fromTradingPost, firstExchange ); cursorTo.hide(); cursorFrom.hide(); fundsFrom = kingdom.GetFunds(); RedrawFromResource( pt1, fundsFrom ); display.render(); } // click from for ( uint32_t ii = 0; ii < rectsFrom.size(); ++ii ) { const fheroes2::Rect & rect_from = rectsFrom[ii]; if ( le.MouseClickLeft( rect_from ) ) { resourceFrom = Resource::getResourceTypeFromIconIndex( ii ); max_sell = fundsFrom.Get( resourceFrom ); const uint32_t tradeCost = GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ); if ( tradeCost ) { max_buy = Resource::GOLD == resourceTo ? max_sell * tradeCost : max_sell / tradeCost; } count_sell = 0; count_buy = 0; cursorFrom.show(); cursorFrom.setPosition( rect_from.x - 2, rect_from.y - 2 ); if ( resourceTo ) { cursorTo.hide(); } RedrawToResource( pt2, true, kingdom, fromTradingPost, resourceFrom ); if ( resourceTo ) { cursorTo.show(); gui.ShowTradeArea( kingdom, resourceFrom, resourceTo, max_buy, max_sell, count_buy, count_sell, fromTradingPost, firstExchange ); } display.render(); } else if ( le.isMouseRightButtonPressedInArea( rect_from ) ) { fheroes2::showKingdomIncome( kingdom, 0 ); } } // click to for ( uint32_t ii = 0; ii < rectsTo.size(); ++ii ) { const fheroes2::Rect & rect_to = rectsTo[ii]; if ( le.MouseClickLeft( rect_to ) ) { resourceTo = Resource::getResourceTypeFromIconIndex( ii ); const uint32_t tradeCost = GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ); if ( tradeCost ) { max_buy = Resource::GOLD == resourceTo ? max_sell * tradeCost : max_sell / tradeCost; } count_sell = 0; count_buy = 0; cursorTo.show(); cursorTo.setPosition( rect_to.x - 2, rect_to.y - 2 ); if ( resourceFrom ) { cursorTo.hide(); RedrawToResource( pt2, true, kingdom, fromTradingPost, resourceFrom ); cursorTo.show(); gui.ShowTradeArea( kingdom, resourceFrom, resourceTo, max_buy, max_sell, count_buy, count_sell, fromTradingPost, firstExchange ); } display.render(); } } // Scrollbar if ( buttonLeft.isEnabled() && buttonRight.isEnabled() && max_buy && le.isMouseLeftButtonPressedInArea( scrollbar.getArea() ) ) { const fheroes2::Point & mousePos = le.getMouseCursorPos(); scrollbar.moveToPos( mousePos ); const int32_t seek = scrollbar.currentIndex(); count_buy = seek * ( Resource::GOLD == resourceTo ? GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) : 1 ); count_sell = seek * ( Resource::GOLD == resourceTo ? 1 : GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) ); gui.RedrawInfoBuySell( count_sell, count_buy, max_sell, fundsFrom.Get( resourceTo ) ); display.render(); } else if ( scrollbar.updatePosition() ) { display.render(); } // click max if ( buttonMax.width && max_buy && le.MouseClickLeft( buttonMax ) ) { const int32_t max = scrollbar.maxIndex(); count_buy = max * ( Resource::GOLD == resourceTo ? GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) : 1 ); count_sell = max * ( Resource::GOLD == resourceTo ? 1 : GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) ); scrollbar.moveToIndex( max ); gui.RedrawInfoBuySell( count_sell, count_buy, max_sell, fundsFrom.Get( resourceTo ) ); display.render(); } // click min if ( buttonMin.width && max_buy && le.MouseClickLeft( buttonMin ) ) { const int32_t min = 1; count_buy = min * ( Resource::GOLD == resourceTo ? GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) : 1 ); count_sell = min * ( Resource::GOLD == resourceTo ? 1 : GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) ); scrollbar.moveToIndex( min ); gui.RedrawInfoBuySell( count_sell, count_buy, max_sell, fundsFrom.Get( resourceTo ) ); display.render(); } // trade if ( buttonTrade.isEnabled() && le.MouseClickLeft( buttonTrade.area() ) && count_sell && count_buy ) { kingdom.OddFundsResource( Funds( resourceFrom, count_sell ) ); kingdom.AddFundsResource( Funds( resourceTo, count_buy ) ); firstExchange = false; resourceTo = Resource::UNKNOWN; resourceFrom = Resource::UNKNOWN; gui.ShowTradeArea( kingdom, resourceFrom, resourceTo, 0, 0, 0, 0, fromTradingPost, firstExchange ); fundsFrom = kingdom.GetFunds(); cursorTo.hide(); cursorFrom.hide(); RedrawFromResource( pt1, fundsFrom ); RedrawToResource( pt2, false, kingdom, fromTradingPost, resourceFrom ); display.render(); } // decrease trade resource if ( count_buy && ( ( buttonLeft.isEnabled() && ( le.MouseClickLeft( buttonLeft.area() ) || timedButtonLeft.isDelayPassed() ) ) || le.isMouseWheelDownInArea( scrollbar.getArea() ) ) ) { count_buy -= Resource::GOLD == resourceTo ? GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) : 1; count_sell -= Resource::GOLD == resourceTo ? 1 : GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ); scrollbar.backward(); gui.RedrawInfoBuySell( count_sell, count_buy, max_sell, fundsFrom.Get( resourceTo ) ); display.render(); } // increase trade resource if ( count_buy < max_buy && ( ( buttonRight.isEnabled() && ( le.MouseClickLeft( buttonRight.area() ) || timedButtonRight.isDelayPassed() ) ) || le.isMouseWheelUpInArea( scrollbar.getArea() ) ) ) { count_buy += Resource::GOLD == resourceTo ? GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ) : 1; count_sell += Resource::GOLD == resourceTo ? 1 : GetTradeCosts( kingdom, resourceFrom, resourceTo, fromTradingPost ); scrollbar.forward(); gui.RedrawInfoBuySell( count_sell, count_buy, max_sell, fundsFrom.Get( resourceTo ) ); display.render(); } } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_quickinfo.cpp000066400000000000000000001036721476115357100237540ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "army_troop.h" #include "artifact_ultimate.h" #include "captain.h" #include "castle.h" #include "color.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game.h" #include "game_interface.h" #include "ground.h" #include "heroes.h" #include "heroes_base.h" #include "icn.h" #include "image.h" #include "interface_base.h" #include "interface_gamearea.h" #include "kingdom.h" #include "localevent.h" #include "logging.h" #include "maps.h" #include "maps_tiles.h" #include "maps_tiles_helper.h" #include "math_base.h" #include "mp2.h" #include "pal.h" #include "profit.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "spell.h" #include "tools.h" #include "translations.h" #include "ui_castle.h" #include "ui_map_interface.h" #include "ui_text.h" #include "world.h" namespace { void outputInTextSupportMode( const Maps::Tile & tile, const std::string & info ) { START_TEXT_SUPPORT_MODE const int tileIndex = tile.GetIndex(); const int mapWidth = world.w(); const int x = tileIndex % mapWidth; const int y = tileIndex / mapWidth; COUT( "[" << x + 1 << ", " << y + 1 << "]" ) COUT( info ) } class RadarUpdater { public: RadarUpdater( const bool performUpdate, const fheroes2::Point & updatedPosition, const fheroes2::Rect & areaToRestore ) : _performUpdate( performUpdate ) , _updatedPosition( updatedPosition ) , _prevPosition( Interface::AdventureMap::Get().getGameArea().getCurrentCenterInPixels() ) , _restorer( fheroes2::Display::instance(), areaToRestore.x, areaToRestore.y, areaToRestore.width, areaToRestore.height ) { if ( !_performUpdate || _updatedPosition == _prevPosition ) { return; } Interface::AdventureMap & iface = Interface::AdventureMap::Get(); iface.getGameArea().SetCenter( updatedPosition ); iface.redraw( Interface::REDRAW_RADAR_CURSOR ); _restorer.restore(); } void restore() { if ( !_performUpdate || _updatedPosition == _prevPosition ) { return; } Interface::AdventureMap & iface = Interface::AdventureMap::Get(); iface.getGameArea().SetCenterInPixels( _prevPosition ); iface.redraw( Interface::REDRAW_RADAR_CURSOR ); _restorer.restore(); } private: const bool _performUpdate; const fheroes2::Point _updatedPosition; const fheroes2::Point _prevPosition; fheroes2::ImageRestorer _restorer; }; std::string getMineIncomeString( const int32_t resourceType ) { const Funds income = ProfitConditions::FromMine( resourceType ); const int32_t value = income.Get( resourceType ); std::string res; if ( value == 0 ) { return res; } res += ' '; res += '('; res += ( value > 0 ? '+' : '-' ); res.append( std::to_string( value ) ); res += ')'; return res; } std::string showMineInfo( const Maps::Tile & tile, const bool isOwned ) { const int32_t resourceType = getDailyIncomeObjectResources( tile ).getFirstValidResource().first; std::string objectInfo = Maps::GetMineName( resourceType ); if ( isOwned ) { // TODO: we should use the value from funds. objectInfo.append( getMineIncomeString( resourceType ) ); } return objectInfo; } std::string showGuardiansInfo( const Maps::Tile & tile, const bool isOwned ) { const MP2::MapObjectType objectType = tile.getMainObjectType( false ); std::string str; if ( objectType == MP2::OBJ_MINE ) { str = showMineInfo( tile, isOwned ); } else { str = MP2::StringObject( objectType ); } const Troop & troop = getTroopFromTile( tile ); if ( troop.isValid() ) { str.append( "\n\n" ); if ( isOwned ) { str.append( _( "guarded by %{count} %{monster}" ) ); StringReplaceWithLowercase( str, "%{count}", Game::formatMonsterCount( troop.GetCount(), true ) ); if ( troop.GetCount() == 1 ) { StringReplaceWithLowercase( str, "%{monster}", troop.GetName() ); } else { StringReplaceWithLowercase( str, "%{monster}", troop.GetMultiName() ); } } else { str.append( _( "guarded by " ) ).append( Translation::StringLower( Army::TroopSizeString( troop ) ) ); } } return str; } std::string showMonsterInfo( const Maps::Tile & tile, const bool isVisibleFromCrystalBall ) { const Troop & troop = getTroopFromTile( tile ); if ( isVisibleFromCrystalBall ) { std::string str = "%{count} %{monster}"; StringReplace( str, "%{count}", Game::formatMonsterCount( troop.GetCount(), true ) ); if ( troop.GetCount() == 1 ) { StringReplaceWithLowercase( str, "%{monster}", troop.GetName() ); } else { StringReplaceWithLowercase( str, "%{monster}", troop.GetMultiName() ); } return str; } return Army::TroopSizeString( troop ); } std::string showDwellingInfo( const Maps::Tile & tile, const bool isOwned ) { std::string str = MP2::StringObject( tile.getMainObjectType( false ) ); if ( isOwned ) { str += "\n\n"; const Troop & troop = getTroopFromTile( tile ); if ( troop.isValid() ) { str.append( _( "(available: %{count})" ) ); StringReplace( str, "%{count}", Game::formatMonsterCount( troop.GetCount(), true ) ); } else { str.append( _( "(empty)" ) ); } } return str; } std::string showShrineInfo( const Maps::Tile & tile, const bool isVisited ) { const MP2::MapObjectType objectType = tile.getMainObjectType( false ); std::string str = MP2::StringObject( objectType ); if ( isVisited ) { const Spell & spell = getSpellFromTile( tile ); str.append( "\n\n(" ); str.append( spell.GetName() ); str += ')'; const Heroes * hero = Interface::GetFocusHeroes(); if ( hero && hero->HaveSpell( spell ) ) { str.append( "\n(" ); str.append( _( "already learned" ) ); str += ')'; } } return str; } std::string showTreeOfKnowledgeInfo( const Maps::Tile & tile, const bool isVisited ) { const MP2::MapObjectType objectType = tile.getMainObjectType( false ); std::string str = MP2::StringObject( objectType ); const Heroes * hero = Interface::GetFocusHeroes(); if ( isVisited ) { const Funds & payment = getTreeOfKnowledgeRequirement( tile ); str.append( "\n\n(" ); if ( payment.GetValidItemsCount() == 0 ) { str.append( _( "treeOfKnowledge|free" ) ); } else { const auto rc = payment.getFirstValidResource(); str.append( std::to_string( rc.second ) ); str += ' '; str.append( Translation::StringLower( Resource::String( rc.first ) ) ); } str += ')'; if ( hero ) { str.append( "\n(" ); str.append( hero->isVisited( tile ) ? _( "already claimed" ) : _( "not claimed" ) ); str += ')'; } } else { if ( hero ) { str.append( "\n\n(" ); // In case another player visited this tree with this hero. str.append( hero->isVisited( tile ) ? _( "already claimed" ) : _( "not claimed" ) ); str += ')'; } } return str; } std::string showWitchHutInfo( const Maps::Tile & tile, const bool isVisited ) { std::string str = MP2::StringObject( tile.getMainObjectType( false ) ); if ( isVisited ) { const Skill::Secondary & skill = getSecondarySkillFromWitchsHut( tile ); str.append( "\n\n(" ); str.append( Skill::Secondary::String( skill.Skill() ) ); str += ')'; const Heroes * hero = Interface::GetFocusHeroes(); if ( hero ) { const char * heroStr = nullptr; if ( hero->HasSecondarySkill( skill.Skill() ) ) { heroStr = ( _( "already knows this skill" ) ); } else if ( hero->HasMaxSecondarySkill() ) { heroStr = ( _( "already has max skills" ) ); } if ( heroStr != nullptr ) { str.append( "\n(" ); str.append( heroStr ); str += ')'; } } } return str; } std::string showLocalVisitTileInfo( const Maps::Tile & tile ) { std::string str = MP2::StringObject( tile.getMainObjectType( false ) ); const Heroes * hero = Interface::GetFocusHeroes(); if ( hero ) { str.append( "\n\n" ); str.append( hero->isVisited( tile ) ? _( "(already visited)" ) : _( "(not visited)" ) ); } return str; } std::string showLocalVisitObjectInfo( const MP2::MapObjectType objectType ) { std::string str = MP2::StringObject( objectType ); const Heroes * hero = Interface::GetFocusHeroes(); if ( hero ) { str.append( "\n\n" ); str.append( hero->isObjectTypeVisited( objectType ) ? _( "(already visited)" ) : _( "(not visited)" ) ); } return str; } std::string showObjectVisitInfo( const MP2::MapObjectType objectType, const bool isVisited ) { std::string str = MP2::StringObject( objectType ); str.append( "\n\n" ); str.append( isVisited ? _( "(already visited)" ) : _( "(not visited)" ) ); return str; } std::string showBarrierInfo( const Maps::Tile & tile, const Kingdom & kingdom ) { std::string str = _( "%{color} Barrier" ); const int32_t barrierColor = getColorFromTile( tile ); StringReplace( str, "%{color}", fheroes2::getBarrierColorName( barrierColor ) ); if ( kingdom.IsVisitTravelersTent( barrierColor ) ) { str.append( "\n\n" ); str.append( _( "(tent visited)" ) ); } return str; } std::string showTentInfo( const Maps::Tile & tile, const Kingdom & kingdom ) { std::string str = _( "%{color} Tent" ); const int32_t tentColor = getColorFromTile( tile ); StringReplace( str, "%{color}", fheroes2::getTentColorName( tentColor ) ); if ( kingdom.IsVisitTravelersTent( tentColor ) ) { str.append( "\n\n" ); str.append( _( "(already visited)" ) ); } return str; } std::string showGroundInfo( const Maps::Tile & tile ) { const MP2::MapObjectType objectType = tile.getMainObjectType( false ); const bool isRoad = tile.isRoad(); std::string str; if ( objectType == MP2::OBJ_COAST ) { str = MP2::StringObject( objectType ); } else if ( isRoad ) { str = _( "Road" ); } else { str = Maps::Ground::String( tile.GetGround() ); } str.append( "\n\n" ); // Original Editor allows to put an Ultimate Artifact on an invalid tile. So checking tile index solves this issue. if ( tile.GoodForUltimateArtifact() || world.GetUltimateArtifact().getPosition() == tile.GetIndex() ) { str.append( _( "(digging ok)" ) ); } else { str.append( _( "(no digging)" ) ); } const Heroes * hero = Interface::GetFocusHeroes(); if ( hero ) { const uint32_t cost = isRoad ? Maps::Ground::roadPenalty : Maps::Ground::GetPenalty( tile, hero->GetLevelSkill( Skill::Secondary::PATHFINDING ) ); if ( cost > 0 ) { str += '\n'; str.append( _( "penalty: %{cost}" ) ); StringReplace( str, "%{cost}", static_cast( cost ) ); } } return str; } fheroes2::Rect makeRectQuickInfo( const LocalEvent & le, const fheroes2::Sprite & imageBox, const fheroes2::Point & position = fheroes2::Point() ) { if ( position.x > 0 && position.y > 0 ) { return { position.x - imageBox.width(), position.y, imageBox.width(), imageBox.height() }; } return Interface::getPopupWindowPosition( le.getMouseCursorPos(), Interface::AdventureMap::Get().getGameArea().GetROI(), { imageBox.width(), imageBox.height() } ); } std::string getQuickInfoText( const Maps::Tile & tile ) { const int32_t playerColor = Settings::Get().CurrentColor(); const MP2::MapObjectType objectType = tile.getMainObjectType( false ); if ( objectType == MP2::OBJ_ABANDONED_MINE || isCaptureObjectProtected( tile ) ) { return showGuardiansInfo( tile, playerColor == getColorFromTile( tile ) ); } const Kingdom & kingdom = world.GetKingdom( playerColor ); switch ( objectType ) { case MP2::OBJ_MONSTER: return showMonsterInfo( tile, kingdom.IsTileVisibleFromCrystalBall( tile.GetIndex() ) ); case MP2::OBJ_EVENT: case MP2::OBJ_NONE: case MP2::OBJ_COAST: return showGroundInfo( tile ); case MP2::OBJ_DERELICT_SHIP: case MP2::OBJ_SHIPWRECK: case MP2::OBJ_GRAVEYARD: case MP2::OBJ_DAEMON_CAVE: case MP2::OBJ_SPHINX: case MP2::OBJ_PYRAMID: case MP2::OBJ_WAGON: case MP2::OBJ_SKELETON: case MP2::OBJ_LEAN_TO: case MP2::OBJ_WINDMILL: case MP2::OBJ_WATER_WHEEL: case MP2::OBJ_MAGIC_GARDEN: case MP2::OBJ_ARTESIAN_SPRING: case MP2::OBJ_OBELISK: return showObjectVisitInfo( objectType, kingdom.isVisited( tile ) ); case MP2::OBJ_MAGELLANS_MAPS: return showObjectVisitInfo( objectType, kingdom.isVisited( objectType ) ); case MP2::OBJ_RESOURCE: { const Funds funds = getFundsFromTile( tile ); assert( funds.GetValidItemsCount() == 1 ); return Resource::String( funds.getFirstValidResource().first ); } case MP2::OBJ_MINE: return showMineInfo( tile, playerColor == getColorFromTile( tile ) ); case MP2::OBJ_ALCHEMIST_LAB: case MP2::OBJ_SAWMILL: { std::string objectInfo = MP2::StringObject( objectType ); if ( playerColor == getColorFromTile( tile ) ) { const Funds funds = getDailyIncomeObjectResources( tile ); assert( funds.GetValidItemsCount() == 1 ); // TODO: we should use the value from funds. objectInfo.append( getMineIncomeString( funds.getFirstValidResource().first ) ); } return objectInfo; } // join army case MP2::OBJ_WATCH_TOWER: case MP2::OBJ_EXCAVATION: case MP2::OBJ_CAVE: case MP2::OBJ_TREE_HOUSE: case MP2::OBJ_ARCHER_HOUSE: case MP2::OBJ_GOBLIN_HUT: case MP2::OBJ_DWARF_COTTAGE: case MP2::OBJ_HALFLING_HOLE: case MP2::OBJ_PEASANT_HUT: // recruit army case MP2::OBJ_RUINS: case MP2::OBJ_TREE_CITY: case MP2::OBJ_WAGON_CAMP: case MP2::OBJ_DESERT_TENT: // battle and recruit army case MP2::OBJ_DRAGON_CITY: case MP2::OBJ_CITY_OF_DEAD: case MP2::OBJ_TROLL_BRIDGE: case MP2::OBJ_BARROW_MOUNDS: case MP2::OBJ_AIR_ALTAR: case MP2::OBJ_FIRE_ALTAR: case MP2::OBJ_EARTH_ALTAR: case MP2::OBJ_WATER_ALTAR: return showDwellingInfo( tile, kingdom.isVisited( tile ) ); case MP2::OBJ_GAZEBO: case MP2::OBJ_FORT: case MP2::OBJ_XANADU: case MP2::OBJ_MERCENARY_CAMP: case MP2::OBJ_WITCH_DOCTORS_HUT: case MP2::OBJ_STANDING_STONES: return showLocalVisitTileInfo( tile ); case MP2::OBJ_MAGIC_WELL: case MP2::OBJ_FOUNTAIN: case MP2::OBJ_FAERIE_RING: case MP2::OBJ_IDOL: case MP2::OBJ_OASIS: case MP2::OBJ_TEMPLE: case MP2::OBJ_BUOY: case MP2::OBJ_MERMAID: case MP2::OBJ_WATERING_HOLE: case MP2::OBJ_ARENA: case MP2::OBJ_STABLES: case MP2::OBJ_SIRENS: return showLocalVisitObjectInfo( objectType ); case MP2::OBJ_SHRINE_FIRST_CIRCLE: case MP2::OBJ_SHRINE_SECOND_CIRCLE: case MP2::OBJ_SHRINE_THIRD_CIRCLE: return showShrineInfo( tile, kingdom.isVisited( tile ) ); case MP2::OBJ_WITCHS_HUT: return showWitchHutInfo( tile, kingdom.isVisited( tile ) ); case MP2::OBJ_BARRIER: return showBarrierInfo( tile, kingdom ); case MP2::OBJ_TRAVELLER_TENT: return showTentInfo( tile, kingdom ); case MP2::OBJ_TREE_OF_KNOWLEDGE: return showTreeOfKnowledgeInfo( tile, kingdom.isVisited( tile ) ); // These objects do not have extra text for quick info. case MP2::OBJ_ARTIFACT: case MP2::OBJ_CAMPFIRE: default: return MP2::StringObject( objectType ); } } void showQuickInfo( const Castle & castle, const fheroes2::Point & position, const bool showOnRadar, const fheroes2::Rect & areaToRestore ) { const CursorRestorer cursorRestorer( false ); // Update radar if needed RadarUpdater radarUpdater( showOnRadar, castle.GetCenter(), areaToRestore ); // image box const fheroes2::Sprite & box = fheroes2::AGG::GetICN( ICN::QWIKTOWN, 0 ); LocalEvent & le = LocalEvent::Get(); fheroes2::Rect cur_rt = makeRectQuickInfo( le, box, position ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::ImageRestorer back( display, cur_rt.x, cur_rt.y, cur_rt.width, cur_rt.height ); fheroes2::Blit( box, display, cur_rt.x, cur_rt.y ); cur_rt = fheroes2::Rect( cur_rt.x + 22, cur_rt.y + 9, 192, 154 ); fheroes2::Point dst_pt; // castle name fheroes2::Text text( castle.GetName(), fheroes2::FontType::smallWhite() ); dst_pt.x = cur_rt.x + ( cur_rt.width - text.width() ) / 2; dst_pt.y = cur_rt.y + 3; text.draw( dst_pt.x, dst_pt.y, display ); // castle icon const Settings & conf = Settings::Get(); const fheroes2::Sprite & castleIcon = fheroes2::AGG::GetICN( conf.isEvilInterfaceEnabled() ? ICN::LOCATORE : ICN::LOCATORS, 23 ); dst_pt.x = cur_rt.x + ( cur_rt.width - castleIcon.width() ) / 2; dst_pt.y += 10; fheroes2::Blit( castleIcon, display, dst_pt.x, dst_pt.y ); fheroes2::drawCastleIcon( castle, display, fheroes2::Point( dst_pt.x + 4, dst_pt.y + 4 ) ); // color flags const uint32_t flagIcnIndex = fheroes2::getCastleLeftFlagIcnIndex( castle.GetColor() ); const fheroes2::Point flagOffset( 5, 4 ); const fheroes2::Sprite & l_flag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex ); fheroes2::Blit( l_flag, display, dst_pt.x - flagOffset.x - l_flag.width(), dst_pt.y + flagOffset.y ); const fheroes2::Sprite & r_flag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex + 1 ); fheroes2::Blit( r_flag, display, dst_pt.x + flagOffset.x + castleIcon.width(), dst_pt.y + flagOffset.y ); const int currentColor = conf.CurrentColor(); const Kingdom & kingdom = world.GetKingdom( currentColor ); const bool isDetailedView = castle.isFriends( currentColor ) || kingdom.IsTileVisibleFromCrystalBall( castle.GetIndex() ); const uint32_t thievesGuildsCount = kingdom.GetCountThievesGuild(); text.set( _( "Defenders:" ), fheroes2::FontType::smallWhite() ); dst_pt.x = cur_rt.x + ( cur_rt.width - text.width() ) / 2; dst_pt.y += castleIcon.height() + 2; text.draw( dst_pt.x, dst_pt.y, display ); // draw defenders if ( isDetailedView || thievesGuildsCount > 0 ) { const Army & castleArmy = castle.GetArmy(); if ( castleArmy.isValid() ) { dst_pt.x = cur_rt.x - 1; dst_pt.y += 21; Army::drawMultipleMonsterLines( castleArmy, dst_pt.x, dst_pt.y, 192, false, isDetailedView, true, thievesGuildsCount ); } else { text.set( _( "None" ), fheroes2::FontType::smallWhite() ); dst_pt.x = cur_rt.x + ( cur_rt.width - text.width() ) / 2; dst_pt.y += 47; text.draw( dst_pt.x, dst_pt.y, display ); } } else { text.set( _( "Unknown" ), fheroes2::FontType::smallWhite() ); dst_pt.x = cur_rt.x + ( cur_rt.width - text.width() ) / 2; dst_pt.y += 47; text.draw( dst_pt.x, dst_pt.y, display ); } display.render(); // quick info loop while ( le.HandleEvents() && le.isMouseRightButtonPressed() ) ; // restore background back.restore(); // Restore radar view radarUpdater.restore(); display.render(); } void showQuickInfo( const HeroBase & hero, const fheroes2::Point & position, const bool showOnRadar, const fheroes2::Rect & areaToRestore, const std::optional showFullInfo ) { const CursorRestorer cursorRestorer( false ); // Update radar if needed RadarUpdater radarUpdater( showOnRadar, hero.GetCenter(), areaToRestore ); // image box const fheroes2::Sprite & box = fheroes2::AGG::GetICN( ICN::QWIKHERO, 0 ); LocalEvent & le = LocalEvent::Get(); fheroes2::Rect cur_rt = makeRectQuickInfo( le, box, position ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::ImageRestorer restorer( display, cur_rt.x, cur_rt.y, cur_rt.width, cur_rt.height ); fheroes2::Blit( box, display, cur_rt.x, cur_rt.y ); cur_rt = fheroes2::Rect( restorer.x() + 28, restorer.y() + 10, 146, 144 ); fheroes2::Point dst_pt; const Settings & conf = Settings::Get(); const bool isNeutralHero = ( hero.GetColor() == Color::NONE ); const bool isFullInfo = [&hero, showFullInfo, &conf, isNeutralHero]() { if ( showFullInfo ) { return *showFullInfo; } const Kingdom & kingdom = world.GetKingdom( conf.CurrentColor() ); const bool isFriend = ColorBase( hero.GetColor() ).isFriends( conf.CurrentColor() ); const bool isUnderIdentifyHeroSpell = kingdom.Modes( Kingdom::IDENTIFYHERO ); return ( isNeutralHero || isFriend || isUnderIdentifyHeroSpell || kingdom.IsTileVisibleFromCrystalBall( hero.GetIndex() ) ); }(); const Heroes * activeHero = dynamic_cast( &hero ); const Captain * activeCaptain = dynamic_cast( &hero ); assert( activeHero != nullptr || activeCaptain != nullptr ); const bool isActiveHero = ( activeHero != nullptr ); // hero's name const fheroes2::FontType smallWhite = fheroes2::FontType::smallWhite(); fheroes2::Text text( hero.GetName(), smallWhite ); // hero's level if ( isFullInfo && isActiveHero ) { std::string heroLevel = _( "heroQuickInfo|(Level %{level})" ); StringReplace( heroLevel, "%{level}", activeHero->GetLevel() ); heroLevel.insert( 0, " " ); // if Identify Hero has been cast then we want to know the hero's level rather than name. const int32_t boxShadowAndBorder = 39; text.fitToOneRow( box.width() - boxShadowAndBorder - fheroes2::Text{ heroLevel, smallWhite }.width() ); text.set( text.text() + heroLevel, smallWhite ); } dst_pt.x = cur_rt.x + ( cur_rt.width - text.width() ) / 2; dst_pt.y = cur_rt.y + 2; text.draw( dst_pt.x, dst_pt.y, display ); const fheroes2::Sprite & heroPortraitFrame = fheroes2::AGG::GetICN( conf.isEvilInterfaceEnabled() ? ICN::LOCATORE : ICN::LOCATORS, 22 ); // mini port heroes const fheroes2::Sprite & port = isActiveHero ? activeHero->GetPortrait( PORT_SMALL ) : activeCaptain->GetPortrait( PORT_SMALL ); if ( !port.empty() ) { fheroes2::Blit( heroPortraitFrame, display, cur_rt.x + ( cur_rt.width - heroPortraitFrame.width() ) / 2, cur_rt.y + 12 ); fheroes2::Blit( port, display, cur_rt.x + ( cur_rt.width - port.width() ) / 2, cur_rt.y + 16 ); } // luck if ( isFullInfo ) { const int32_t luck = hero.GetLuck(); const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::MINILKMR, ( 0 > luck ? 0 : ( 0 < luck ? 1 : 2 ) ) ); uint32_t count = ( 0 == luck ? 1 : std::abs( luck ) ); dst_pt.x = cur_rt.x + 120; dst_pt.y = cur_rt.y + ( count == 1 ? 20 : 13 ); while ( count-- ) { fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); dst_pt.y += sprite.height() - 1; } } // morale if ( isFullInfo ) { const int32_t morale = hero.GetMorale(); uint32_t spriteInx = 5; if ( morale < 0 ) { spriteInx = 3; } else if ( morale > 0 ) { spriteInx = 4; } fheroes2::Sprite sprite = fheroes2::AGG::GetICN( ICN::MINILKMR, spriteInx ); if ( hero.GetArmy().AllTroopsAreUndead() ) { fheroes2::ApplyPalette( sprite, PAL::GetPalette( PAL::PaletteType::GRAY ) ); fheroes2::ApplyPalette( sprite, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); } uint32_t count = ( 0 == morale ? 1 : std::abs( morale ) ); dst_pt.x = cur_rt.x + 10; dst_pt.y = cur_rt.y + ( count == 1 ? 20 : 13 ); while ( count-- ) { fheroes2::Blit( sprite, display, dst_pt.x, dst_pt.y ); dst_pt.y += sprite.height() - 1; } } dst_pt.y = cur_rt.y + 13; // color flags, except for neutral heroes if ( !isNeutralHero ) { // Use castle flags to show hero's color flags. const uint32_t flagIcnIndex = fheroes2::getCastleLeftFlagIcnIndex( hero.GetColor() ); const fheroes2::Sprite & l_flag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex ); dst_pt.x = cur_rt.x + ( cur_rt.width - 40 ) / 2 - l_flag.width(); fheroes2::Blit( l_flag, display, dst_pt.x, dst_pt.y ); const fheroes2::Sprite & r_flag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex + 1 ); dst_pt.x = cur_rt.x + ( cur_rt.width + 40 ) / 2; fheroes2::Blit( r_flag, display, dst_pt.x, dst_pt.y ); } const uint16_t statNumberColumn = 89; const uint16_t statRow = 11; if ( isFullInfo ) { // attack text.set( _( "Attack:" ), smallWhite ); dst_pt.x = cur_rt.x + 10; dst_pt.y += heroPortraitFrame.height(); text.fitToOneRow( statNumberColumn ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( hero.GetAttack() ), smallWhite ); dst_pt.x += statNumberColumn; text.draw( dst_pt.x, dst_pt.y, display ); // defense text.set( _( "Defense:" ), smallWhite ); dst_pt.x = cur_rt.x + 10; dst_pt.y += statRow; text.fitToOneRow( statNumberColumn ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( hero.GetDefense() ), smallWhite ); dst_pt.x += statNumberColumn; text.draw( dst_pt.x, dst_pt.y, display ); // power text.set( _( "Spell Power:" ), smallWhite ); dst_pt.x = cur_rt.x + 10; dst_pt.y += statRow; text.fitToOneRow( statNumberColumn ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( hero.GetPower() ), smallWhite ); dst_pt.x += statNumberColumn; text.draw( dst_pt.x, dst_pt.y, display ); // knowledge text.set( _( "Knowledge:" ), smallWhite ); dst_pt.x = cur_rt.x + 10; dst_pt.y += statRow; text.fitToOneRow( statNumberColumn ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( hero.GetKnowledge() ), smallWhite ); dst_pt.x += statNumberColumn; text.draw( dst_pt.x, dst_pt.y, display ); // spell point text.set( _( "Spell Points:" ), smallWhite ); dst_pt.x = cur_rt.x + 10; dst_pt.y += statRow; text.fitToOneRow( statNumberColumn ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( hero.GetSpellPoints() ) + "/" + std::to_string( hero.GetMaxSpellPoints() ), smallWhite ); dst_pt.x += statNumberColumn; text.draw( dst_pt.x, dst_pt.y, display ); // move point if ( isActiveHero ) { text.set( _( "Move Points:" ), smallWhite ); dst_pt.x = cur_rt.x + 10; dst_pt.y += statRow; text.fitToOneRow( statNumberColumn ); text.draw( dst_pt.x, dst_pt.y, display ); text.set( std::to_string( activeHero->GetMovePoints() ) + "/" + std::to_string( activeHero->GetMaxMovePoints() ), smallWhite ); dst_pt.x += statNumberColumn; text.draw( dst_pt.x, dst_pt.y, display ); } Army::drawSingleDetailedMonsterLine( hero.GetArmy(), cur_rt.x - 7, cur_rt.y + 118, 160 ); } else { // show limited Army::drawMultipleMonsterLines( hero.GetArmy(), cur_rt.x - 6, cur_rt.y + 60, 160, false, false ); } display.render(); // quick info loop while ( le.HandleEvents() && le.isMouseRightButtonPressed() ) ; // restore background restorer.restore(); // Restore radar view radarUpdater.restore(); display.render(); } } void Dialog::QuickInfo( const Maps::Tile & tile ) { std::string infoString; const int32_t playerColor = Settings::Get().CurrentColor(); if ( ( playerColor != 0 ) && tile.isFog( playerColor ) ) { infoString = _( "Uncharted Territory" ); } else { const int32_t mainTileIndex = Maps::Tile::getIndexOfMainTile( tile ); if ( mainTileIndex != -1 ) { infoString = getQuickInfoText( world.getTile( mainTileIndex ) ); } else { infoString = getQuickInfoText( tile ); } } outputInTextSupportMode( tile, infoString ); Interface::displayStandardPopupWindow( std::move( infoString ), Interface::AdventureMap::Get().getGameArea().GetROI() ); } void Dialog::QuickInfo( const Castle & castle ) { showQuickInfo( castle, {}, false, {} ); } void Dialog::QuickInfo( const HeroBase & hero, const std::optional showFullInfo /* = {} */ ) { showQuickInfo( hero, {}, false, {}, showFullInfo ); } void Dialog::QuickInfoWithIndicationOnRadar( const Castle & castle, const fheroes2::Rect & areaToRestore ) { showQuickInfo( castle, {}, true, areaToRestore ); } void Dialog::QuickInfoWithIndicationOnRadar( const HeroBase & hero, const fheroes2::Rect & areaToRestore ) { showQuickInfo( hero, {}, true, areaToRestore, {} ); } void Dialog::QuickInfoAtPosition( const Castle & castle, const fheroes2::Point & position ) { showQuickInfo( castle, position, true, {} ); } void Dialog::QuickInfoAtPosition( const HeroBase & hero, const fheroes2::Point & position ) { showQuickInfo( hero, position, true, {}, {} ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_recruit.cpp000066400000000000000000000700601476115357100234330ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include "agg_image.h" #include "army_troop.h" #include "bin_info.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "math_base.h" #include "monster.h" #include "pal.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_keyboard.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" namespace { void drawButtonShadow( fheroes2::Image & output, const int buttonIcn, const uint32_t icnIndex, const fheroes2::Point & offset ) { const fheroes2::Sprite & buttonSprite = fheroes2::AGG::GetICN( buttonIcn, icnIndex ); fheroes2::addGradientShadow( buttonSprite, output, offset, { -5, 5 } ); } void drawCostPerTroopFrame( fheroes2::Image & output, const fheroes2::Point & offset ) { const fheroes2::Sprite & originalBackground = fheroes2::AGG::GetICN( ICN::RECRBKG, 0 ); const fheroes2::Sprite & recruitWindowTitle = fheroes2::AGG::GetICN( ICN::BLDGXTRA, 0 ); fheroes2::Image recruitWindow( 132, 67 ); // Reset the transparent layer. recruitWindow.reset(); // Copy recruit cost title background and borders to make shadows for it and to Blit it to the Recruit dialog. fheroes2::Copy( recruitWindowTitle, 3, 58, recruitWindow, 3, 0, 63, 14 ); fheroes2::Copy( recruitWindowTitle, recruitWindowTitle.width() - 66, 58, recruitWindow, 66, 0, 63, 14 ); fheroes2::Copy( originalBackground, 138, 54, recruitWindow, 0, 0, 3, 63 ); fheroes2::Copy( originalBackground, 267, 54, recruitWindow, 129, 0, 3, 63 ); fheroes2::Copy( originalBackground, 138, 117, recruitWindow, 0, 63, 132, 4 ); const fheroes2::Text recruitWindowText( _( "Cost per troop:" ), fheroes2::FontType::smallWhite() ); recruitWindowText.draw( ( recruitWindow.width() - recruitWindowText.width() ) / 2, 3, recruitWindow ); if ( Settings::Get().isEvilInterfaceEnabled() ) { fheroes2::ApplyPalette( recruitWindow, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ) ); } fheroes2::Blit( recruitWindow, output, offset.x, offset.y ); fheroes2::addGradientShadow( recruitWindow, output, { offset.x, offset.y }, { -5, 5 } ); } void RedrawCurrentInfo( const fheroes2::Point & pos, const uint32_t result, const Funds & paymentMonster, const Funds & paymentCosts, const Funds & funds, const std::string & label, const fheroes2::Image & background = {} ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Text text( std::to_string( result ), fheroes2::FontType::normalWhite() ); // Restore the background of the text before rendering it. fheroes2::Copy( background, 118, 147, display, pos.x + 118, pos.y + 147, 68, text.height() ); text.draw( pos.x + 151 - text.width() / 2, pos.y + 147, display ); std::string sgold = std::to_string( paymentCosts.gold ) + " " + "(" + std::to_string( funds.gold - paymentCosts.gold ) + ")"; const int rsext = paymentMonster.GetValidItems() & ~Resource::GOLD; text.set( std::move( sgold ), fheroes2::FontType::smallWhite() ); // Restore the background of the text before rendering it. fheroes2::Copy( background, 0, 214, display, pos.x, pos.y + 214, background.width(), text.height() ); if ( rsext ) { text.draw( pos.x + 117 - text.width() / 2, pos.y + 214, display ); text.set( std::to_string( paymentCosts.Get( rsext ) ) + " " + "(" + std::to_string( funds.Get( rsext ) - paymentCosts.Get( rsext ) ) + ")", fheroes2::FontType::smallWhite() ); text.draw( pos.x + 179 - text.width() / 2, pos.y + 214, display ); } else { text.draw( pos.x + 144 - text.width() / 2, pos.y + 214, display ); } // Restore the background of the text before rendering it or to leave it blank if there is no text. fheroes2::Copy( background, 0, 166, display, pos.x, pos.y + 166, background.width(), text.height() ); if ( !label.empty() ) { text.set( label, fheroes2::FontType::smallWhite() ); text.draw( pos.x + 151 - text.width() / 2, pos.y + 166, display ); } } void RedrawResourceInfo( const int resourceIcnIndex, const fheroes2::Point & pos, const int32_t value, const int32_t px1, const int32_t py1, const int32_t px2, const int32_t py2, const bool showTotalSum ) { fheroes2::Display & display = fheroes2::Display::instance(); // In recruit dialog (where the total sum is also shown) the resource info is shifted by 10 pixels to the right. const int32_t offsetX = showTotalSum ? 10 : 0; const fheroes2::Sprite & sres = fheroes2::AGG::GetICN( ICN::RESOURCE, Resource::getIconIcnIndex( resourceIcnIndex ) ); fheroes2::Blit( sres, fheroes2::Display::instance(), pos.x + px1 + offsetX, pos.y + py1 ); const fheroes2::Text text( std::to_string( value ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + px2 - text.width() / 2 + offsetX, pos.y + py2, display ); if ( showTotalSum ) { fheroes2::Blit( sres, display, pos.x + px1 - 45, pos.y + py1 + 125 ); } } void RedrawMonsterInfo( const fheroes2::Rect & pos, const Monster & monster, const uint32_t available, const bool showTotalSum ) { fheroes2::Display & display = fheroes2::Display::instance(); const Funds paymentMonster = monster.GetCost(); const bool needExtraResources = 2 == paymentMonster.GetValidItemsCount(); // Recruit monster text. std::string str = _( "Recruit %{name}" ); StringReplace( str, "%{name}", monster.GetMultiName() ); fheroes2::Text text( std::move( str ), fheroes2::FontType::normalYellow() ); fheroes2::Point dst_pt( pos.x + ( pos.width - text.width() ) / 2, pos.y + 11 ); text.draw( dst_pt.x, dst_pt.y, display ); // Monster sprite. const int monsterId = monster.GetID(); const Bin_Info::MonsterAnimInfo & monsterInfo = Bin_Info::GetMonsterInfo( monsterId ); assert( !monsterInfo.animationFrames[Bin_Info::MonsterAnimInfo::STATIC].empty() ); const fheroes2::Sprite & smon = fheroes2::AGG::GetICN( monster.GetMonsterSprite(), monsterInfo.animationFrames[Bin_Info::MonsterAnimInfo::STATIC][0] ); dst_pt.x = pos.x + 64 + smon.x() - ( monster.isWide() ? 22 : 0 ); const int32_t monsterExtraOffsetY = std::max( 0, smon.height() - 96 ); dst_pt.y = pos.y + 119 - smon.height() + monsterExtraOffsetY; if ( monsterId == Monster::CHAMPION ) { ++dst_pt.x; } fheroes2::Blit( smon, display, dst_pt.x, dst_pt.y ); // Resources needed to buy monster. if ( needExtraResources ) { RedrawResourceInfo( Resource::GOLD, pos.getPosition(), paymentMonster.gold, 134, 59, 167, 89, showTotalSum ); if ( paymentMonster.crystal > 0 ) { RedrawResourceInfo( Resource::CRYSTAL, pos.getPosition(), paymentMonster.crystal, 206, 53, 224, 89, showTotalSum ); } else if ( paymentMonster.mercury > 0 ) { RedrawResourceInfo( Resource::MERCURY, pos.getPosition(), paymentMonster.mercury, 209, 56, 224, 89, showTotalSum ); } else if ( paymentMonster.wood > 0 ) { RedrawResourceInfo( Resource::WOOD, pos.getPosition(), paymentMonster.wood, 209, 56, 224, 89, showTotalSum ); } else if ( paymentMonster.ore > 0 ) { RedrawResourceInfo( Resource::ORE, pos.getPosition(), paymentMonster.ore, 209, 56, 224, 89, showTotalSum ); } else if ( paymentMonster.sulfur > 0 ) { RedrawResourceInfo( Resource::SULFUR, pos.getPosition(), paymentMonster.sulfur, 209, 59, 224, 89, showTotalSum ); } else if ( paymentMonster.gems > 0 ) { RedrawResourceInfo( Resource::GEMS, pos.getPosition(), paymentMonster.gems, 209, 59, 224, 89, showTotalSum ); } } else { // Only gold is needed. RedrawResourceInfo( Resource::GOLD, pos.getPosition(), paymentMonster.gold, 159, 59, 189, 89, showTotalSum ); } str = _( "Available: %{count}" ); StringReplace( str, "%{count}", available ); text.set( std::move( str ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 64 - text.width() / 2, pos.y + 120 + std::max( monsterExtraOffsetY, 2 ), display ); if ( showTotalSum ) { text.set( _( "Number to buy:" ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 107 - text.width(), pos.y + 149, display ); } } const char * SwitchMaxMinButtons( fheroes2::ButtonBase & btnMax, fheroes2::ButtonBase & btnMin, bool max ) { if ( btnMax.isEnabled() || btnMin.isEnabled() ) { if ( max ) { btnMax.disable(); btnMin.enable(); return _( "Max" ); } btnMin.disable(); btnMax.enable(); return _( "Min" ); } return ""; } uint32_t CalculateMax( const Monster & monster, const Kingdom & kingdom, const uint32_t available ) { uint32_t max = 0; while ( kingdom.AllowPayment( monster.GetCost() * ( max + 1 ) ) && ( max + 1 ) <= available ) { ++max; } return max; } } Troop Dialog::RecruitMonster( const Monster & monster0, const uint32_t available, const bool allowDowngradedMonster, const int32_t windowOffsetY ) { const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); // Set cursor. const CursorRestorer cursorRestorer( true, Cursor::POINTER ); // Calculate max count. Monster monster = monster0; Funds paymentMonster = monster.GetCost(); const Kingdom & kingdom = world.GetKingdom( Settings::Get().CurrentColor() ); uint32_t max = CalculateMax( monster, kingdom, available ); uint32_t result = max; Funds paymentCosts( paymentMonster * result ); const fheroes2::Size windowSize{ 299, 272 }; const fheroes2::Point dialogOffset( ( display.width() - windowSize.width ) / 2, ( display.height() - windowSize.height ) / 2 + windowOffsetY ); const fheroes2::StandardWindow window( dialogOffset.x, dialogOffset.y, windowSize.width, windowSize.height, true, display ); const fheroes2::Rect roi( window.totalArea() ); const fheroes2::Rect windowActiveArea( window.activeArea() ); const fheroes2::Sprite & originalBackground = fheroes2::AGG::GetICN( ICN::RECRBKG, 0 ); // Render the recruit count background from original recruit dialog ICN. fheroes2::Image background( 68, 19 ); fheroes2::Copy( originalBackground, 134, 159, background, 0, 0, background.width(), background.height() ); const fheroes2::Rect recruitCountInputArea( dialogOffset.x + 118, dialogOffset.y + 147, background.width(), background.height() ); if ( isEvilInterface ) { fheroes2::ApplyPalette( background, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ) ); } fheroes2::Point dst_pt( dialogOffset.x + 118, dialogOffset.y + 143 ); fheroes2::Copy( background, 0, 0, display, dst_pt.x, dst_pt.y, background.width(), background.height() ); fheroes2::addGradientShadow( background, display, dst_pt, { -5, 5 } ); dst_pt.x = dialogOffset.x + 132; dst_pt.y = dialogOffset.y + 38; drawCostPerTroopFrame( display, dst_pt ); // Prepare buttons. const int32_t backgroundMargin = 18; dst_pt.x = dialogOffset.x + backgroundMargin; dst_pt.y = dialogOffset.y + 233; int buttonId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; fheroes2::Button buttonOk( dst_pt.x, dst_pt.y, buttonId, 0, 1 ); drawButtonShadow( display, buttonId, 0, dst_pt ); buttonId = isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD; const int32_t buttonCancelWidth = fheroes2::AGG ::GetICN( buttonId, 0 ).width(); dst_pt.x = dialogOffset.x + windowSize.width - backgroundMargin - buttonCancelWidth; fheroes2::Button buttonCancel( dst_pt.x, dst_pt.y, buttonId, 0, 1 ); drawButtonShadow( display, buttonId, 0, dst_pt ); buttonId = isEvilInterface ? ICN::BUTTON_SMALL_MAX_EVIL : ICN::BUTTON_SMALL_MAX_GOOD; const int32_t buttonMaxWidth = fheroes2::AGG ::GetICN( buttonId, 0 ).width(); dst_pt.x = dialogOffset.x + 253 - buttonMaxWidth / 2; dst_pt.y = dialogOffset.y + 140; fheroes2::Button buttonMax( dst_pt.x, dst_pt.y, buttonId, 0, 1 ); fheroes2::Button buttonMin( dst_pt.x, dst_pt.y, isEvilInterface ? ICN::BUTTON_SMALL_MIN_EVIL : ICN::BUTTON_SMALL_MIN_GOOD, 0, 1 ); drawButtonShadow( display, buttonId, 0, dst_pt ); dst_pt.x = dialogOffset.x + 189; dst_pt.y = dialogOffset.y + 138; fheroes2::Button buttonUp( dst_pt.x, dst_pt.y, ICN::RECRUIT, 0, 1 ); drawButtonShadow( display, ICN::RECRUIT, 0, dst_pt ); dst_pt.y = dialogOffset.y + 153; fheroes2::Button buttonDn( dst_pt.x, dst_pt.y, ICN::RECRUIT, 2, 3 ); drawButtonShadow( display, ICN::RECRUIT, 2, dst_pt ); fheroes2::TimedEventValidator timedButtonUp( [&buttonUp]() { return buttonUp.isPressed(); } ); fheroes2::TimedEventValidator timedButtonDn( [&buttonDn]() { return buttonDn.isPressed(); } ); buttonDn.subscribe( &timedButtonDn ); buttonUp.subscribe( &timedButtonUp ); const fheroes2::Rect rtWheel( dialogOffset.x + 114, dialogOffset.y + 139, 100, 30 ); // Create monster switching arrows fheroes2::ButtonSprite monsterSwitchLeft; fheroes2::ButtonSprite monsterSwitchRight; const bool showDowngradedMonsterSwitchButtons = allowDowngradedMonster && ( monster0.GetDowngrade() != monster0 ); if ( showDowngradedMonsterSwitchButtons ) { const fheroes2::Sprite & leftButtonSprite = fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_LEFT_ARROW, 0 ); monsterSwitchLeft.setSprite( leftButtonSprite, fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_LEFT_ARROW, 1 ) ); dst_pt.x = dialogOffset.x + 6; dst_pt.y = dialogOffset.y + 64; monsterSwitchLeft.setPosition( dst_pt.x, dst_pt.y ); fheroes2::addGradientShadow( leftButtonSprite, display, dst_pt, { -5, 5 } ); const fheroes2::Sprite & rightButtonSprite = fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_RIGHT_ARROW, 0 ); monsterSwitchRight.setSprite( rightButtonSprite, fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_RIGHT_ARROW, 1 ) ); dst_pt.x = dialogOffset.x + 105; monsterSwitchRight.setPosition( dst_pt.x, dst_pt.y ); fheroes2::addGradientShadow( rightButtonSprite, display, dst_pt, { -5, 5 } ); // Render Left and Right buttons to restore their initial state later. monsterSwitchLeft.draw(); monsterSwitchRight.draw(); } else { monsterSwitchLeft.hide(); monsterSwitchRight.hide(); monsterSwitchLeft.disable(); monsterSwitchRight.disable(); } // Render Up and Down buttons to restore their initial state later. buttonUp.draw(); buttonDn.draw(); // Make a copy of background dialog to restore its parts before updating some dialog elements. background.resize( windowSize.width, windowSize.height ); fheroes2::Copy( display, dialogOffset.x, dialogOffset.y, background, 0, 0, windowSize.width, windowSize.height ); RedrawMonsterInfo( windowActiveArea, monster, available, true ); if ( 0 == result ) { buttonOk.disable(); buttonMax.disable(); buttonMin.disable(); buttonMax.draw(); } const Funds & funds = kingdom.GetFunds(); std::string maxmin = SwitchMaxMinButtons( buttonMax, buttonMin, true ); RedrawCurrentInfo( dialogOffset, result, paymentMonster, paymentCosts, funds, maxmin ); buttonOk.draw(); buttonCancel.draw(); if ( buttonMax.isEnabled() ) { buttonMax.draw(); } if ( buttonMin.isEnabled() ) { buttonMin.draw(); } display.render( roi ); const fheroes2::Rect monsterArea( dialogOffset.x + 24, dialogOffset.y + 19, 75, 95 ); const auto buttonReleaseRestore = [&display, &background, &dialogOffset]( fheroes2::ButtonBase & button ) { if ( button.isReleased() ) { return; } // When the "Up"/"Down" button is pressed it is shifted 1 pixel down so we need to properly restore the background. button.release(); const fheroes2::Rect & buttonRoi = button.area(); fheroes2::Copy( background, buttonRoi.x - dialogOffset.x, buttonRoi.y - dialogOffset.y, display, buttonRoi.x, buttonRoi.y, buttonRoi.width, buttonRoi.height ); // The non-pressed button is already on the "background" copy so we do not render the button. display.render( buttonRoi ); }; std::vector upgrades = { monster0 }; while ( upgrades.back().GetDowngrade() != upgrades.back() ) { upgrades.emplace_back( upgrades.back().GetDowngrade() ); } const auto updateCurrentInfo = [&paymentMonster = std::as_const( paymentMonster ), &max = std::as_const( max ), &result = std::as_const( result ), &paymentCosts, &buttonMax, &buttonMin, &maxmin]() { paymentCosts = paymentMonster * result; if ( result == max ) { maxmin = SwitchMaxMinButtons( buttonMax, buttonMin, true ); } else if ( result == 1 ) { maxmin = SwitchMaxMinButtons( buttonMax, buttonMin, false ); } else { maxmin.clear(); } }; while ( le.HandleEvents() ) { bool redraw = false; if ( buttonOk.isEnabled() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.isMouseLeftButtonPressedInArea( buttonUp.area() ) ) { buttonUp.drawOnPress(); } else { buttonReleaseRestore( buttonUp ); } if ( le.isMouseLeftButtonPressedInArea( buttonDn.area() ) ) { buttonDn.drawOnPress(); } else { buttonReleaseRestore( buttonDn ); } if ( buttonMax.isEnabled() ) { buttonMax.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMax.area() ) ); } if ( buttonMin.isEnabled() ) { buttonMin.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMin.area() ) ); } bool updateMonsterInfo = false; if ( showDowngradedMonsterSwitchButtons ) { if ( le.isMouseLeftButtonPressedInArea( monsterSwitchLeft.area() ) ) { monsterSwitchLeft.drawOnPress(); } else { buttonReleaseRestore( monsterSwitchLeft ); } if ( le.isMouseLeftButtonPressedInArea( monsterSwitchRight.area() ) ) { monsterSwitchRight.drawOnPress(); } else { buttonReleaseRestore( monsterSwitchRight ); } if ( le.MouseClickLeft( monsterSwitchLeft.area() ) || le.isKeyPressed( fheroes2::Key::KEY_LEFT ) ) { for ( size_t i = 0; i < upgrades.size(); ++i ) { if ( upgrades[i] == monster ) { if ( i < upgrades.size() - 1 ) { monster = upgrades[i + 1]; } else { monster = upgrades[0]; } break; } } updateMonsterInfo = true; } else if ( le.MouseClickLeft( monsterSwitchRight.area() ) || le.isKeyPressed( fheroes2::Key::KEY_RIGHT ) ) { for ( size_t i = 0; i < upgrades.size(); ++i ) { if ( upgrades[i] == monster ) { if ( i > 0 ) { monster = upgrades[i - 1]; } else { monster = upgrades.back(); } break; } } updateMonsterInfo = true; } } if ( updateMonsterInfo ) { // Restore the recruit dialog background. fheroes2::Copy( background, 0, 0, display, dialogOffset.x, dialogOffset.y, windowSize.width, windowSize.height ); max = CalculateMax( monster, kingdom, available ); if ( max == 0 ) { buttonMin.disable(); buttonMax.disable(); } else if ( !buttonMax.isEnabled() && !buttonMin.isEnabled() ) { buttonMin.enable(); } result = max; paymentMonster = monster.GetCost(); updateCurrentInfo(); RedrawMonsterInfo( windowActiveArea, monster, available, true ); redraw = true; } if ( le.isMouseRightButtonPressedInArea( monsterArea ) ) { ArmyInfo( Troop( monster, available ), ZERO ); // Perform a full rendering to properly restore the parts of the screen outside of this dialog display.render(); continue; } if ( le.MouseClickLeft( monsterArea ) ) { ArmyInfo( Troop( monster, available ), BUTTONS ); // Perform a full rendering to properly restore the parts of the screen outside of this dialog display.render(); continue; } if ( int32_t temp = static_cast( result ); fheroes2::processIntegerValueTyping( 0, static_cast( max ), temp ) ) { result = temp; updateCurrentInfo(); redraw = true; } if ( le.MouseClickLeft( recruitCountInputArea ) ) { int32_t temp = static_cast( result ); fheroes2::openVirtualNumpad( temp, 0, static_cast( max ) ); assert( temp >= 0 && temp <= static_cast( max ) ); result = temp; updateCurrentInfo(); redraw = true; } else if ( ( le.isMouseWheelUpInArea( rtWheel ) || le.MouseClickLeft( buttonUp.area() ) || le.isKeyPressed( fheroes2::Key::KEY_UP ) || timedButtonUp.isDelayPassed() ) && result < max ) { ++result; updateCurrentInfo(); redraw = true; } else if ( ( le.isMouseWheelDownInArea( rtWheel ) || le.MouseClickLeft( buttonDn.area() ) || le.isKeyPressed( fheroes2::Key::KEY_DOWN ) || timedButtonDn.isDelayPassed() ) && result ) { --result; updateCurrentInfo(); redraw = true; } else if ( buttonMax.isEnabled() && le.MouseClickLeft( buttonMax.area() ) && result != max ) { result = max; updateCurrentInfo(); redraw = true; } else if ( buttonMin.isEnabled() && le.MouseClickLeft( buttonMin.area() ) && result != 1 ) { result = 1; updateCurrentInfo(); redraw = true; } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Recruit selected monsters." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), 0 ); } else if ( buttonMax.isEnabled() && le.isMouseRightButtonPressedInArea( buttonMax.area() ) ) { fheroes2::showStandardTextMessage( _( "MAX" ), _( "Select maximum monsters to be recruited." ), 0 ); } else if ( buttonMin.isEnabled() && le.isMouseRightButtonPressedInArea( buttonMin.area() ) ) { fheroes2::showStandardTextMessage( _( "MIN" ), _( "Select only 1 monster to be recruited." ), 0 ); } if ( redraw ) { RedrawCurrentInfo( dialogOffset, result, paymentMonster, paymentCosts, funds, maxmin, background ); if ( 0 == result ) { buttonOk.disable(); buttonOk.draw(); } else { buttonOk.enable(); buttonOk.draw(); } buttonCancel.draw(); if ( buttonMax.isEnabled() || max == 0 ) { buttonMax.draw(); } else if ( buttonMin.isEnabled() ) { buttonMin.draw(); } monsterSwitchLeft.draw(); monsterSwitchRight.draw(); display.render( windowActiveArea ); } if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) ) ) { break; } if ( le.MouseClickLeft( buttonCancel.area() ) || ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) ) { result = 0; break; } } display.updateNextRenderRoi( roi ); return { monster, result }; } void Dialog::DwellingInfo( const Monster & monster, const uint32_t available ) { const fheroes2::Size windowSize{ 289, 141 }; fheroes2::Display & display = fheroes2::Display::instance(); // Set cursor. const CursorRestorer cursorRestorer( false ); const fheroes2::Point dialogOffset( ( display.width() - windowSize.width ) / 2, display.height() / 2 - fheroes2::Display::DEFAULT_HEIGHT / 2 + fheroes2::borderWidthPx ); const fheroes2::StandardWindow window( dialogOffset.x, dialogOffset.y, windowSize.width, windowSize.height, true, display ); drawCostPerTroopFrame( display, { dialogOffset.x + 122, dialogOffset.y + 38 } ); RedrawMonsterInfo( window.activeArea(), monster, available, false ); display.render( window.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() && le.isMouseRightButtonPressed() ) { // Do nothing. } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_resolution.cpp000066400000000000000000000371451476115357100241700ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_resolution.h" #include #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "embedded_image.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_window.h" #include "zzlib.h" namespace { const int32_t textAreaWidth = 270; const int32_t scrollBarAreaWidth = 48; const int32_t paddingLeftSide = 24; const int32_t resolutionItemHeight = 19; // TODO: this is a hack over partially incorrect text height calculation. Fix it later together with the Text classes. const int32_t textOffsetYCorrection = 6; const std::string middleText = " x "; std::pair getResolutionStrings( const fheroes2::ResolutionInfo & resolution ) { if ( resolution.screenWidth != resolution.gameWidth && resolution.screenHeight != resolution.gameHeight ) { const int32_t integer = resolution.screenWidth / resolution.gameWidth; const int32_t fraction = resolution.screenWidth * 10 / resolution.gameWidth - 10 * integer; return std::make_pair( std::to_string( resolution.gameWidth ), std::to_string( resolution.gameHeight ) + " (x" + std::to_string( integer ) + "." + std::to_string( fraction ) + ')' ); } return std::make_pair( std::to_string( resolution.gameWidth ), std::to_string( resolution.gameHeight ) ); } class ResolutionList : public Interface::ListBox { public: using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; using Interface::ListBox::ActionListDoubleClick; explicit ResolutionList( const fheroes2::Point & offset ) : Interface::ListBox( offset ) , _isDoubleClicked( false ) { // Do nothing. } void RedrawItem( const fheroes2::ResolutionInfo & resolution, int32_t offsetX, int32_t offsetY, bool current ) override { const fheroes2::FontType fontType = current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite(); const auto [leftText, rightText] = getResolutionStrings( resolution ); const int32_t middleTextSize = fheroes2::Text( middleText, fontType ).width(); const int32_t leftTextSize = fheroes2::Text( leftText, fontType ).width(); const fheroes2::Text resolutionText( leftText + middleText + rightText, fontType ); const int32_t textOffsetX = offsetX + textAreaWidth / 2 - leftTextSize - middleTextSize / 2; const int32_t textOffsetY = offsetY + ( resolutionItemHeight - resolutionText.height() + textOffsetYCorrection ) / 2; resolutionText.draw( textOffsetX, textOffsetY, fheroes2::Display::instance() ); } void RedrawBackground( const fheroes2::Point & /* unused */ ) override { _listBackground->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListSingleClick( fheroes2::ResolutionInfo & /*unused*/ ) override { // Do nothing. } void ActionListPressRight( fheroes2::ResolutionInfo & resolution ) override { const auto [leftText, rightText] = getResolutionStrings( resolution ); if ( resolution.gameHeight == resolution.screenHeight && resolution.gameWidth == resolution.screenWidth ) { fheroes2::showStandardTextMessage( leftText + middleText + rightText, _( "Select this game resolution." ), Dialog::ZERO ); } else { const int32_t integer = resolution.screenWidth / resolution.gameWidth; const int32_t fraction = resolution.screenWidth * 10 / resolution.gameWidth - 10 * integer; std::string scaledResolutionText = _( "Selecting this resolution will set a resolution that is scaled from the original resolution (%{resolution}) by multiplying it with the number " "in the brackets (%{scale}).\n\nA resolution with a clean integer number (2.0x, 3.0x etc.) will usually look better because the pixels are upscaled " "evenly in both horizontal and vertical directions." ); StringReplace( scaledResolutionText, "%{resolution}", std::to_string( resolution.gameWidth ) + middleText + std::to_string( resolution.gameHeight ) ); StringReplace( scaledResolutionText, "%{scale}", std::to_string( integer ) + "." + std::to_string( fraction ) ); fheroes2::showStandardTextMessage( leftText + middleText + rightText, scaledResolutionText, Dialog::ZERO ); } } void ActionListDoubleClick( fheroes2::ResolutionInfo & /*unused*/ ) override { _isDoubleClicked = true; } bool isDoubleClicked() const { return _isDoubleClicked; } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: bool _isDoubleClicked; std::unique_ptr _listBackground; }; void RedrawInfo( const fheroes2::Point & dst, const fheroes2::ResolutionInfo & resolution, fheroes2::Image & output ) { if ( resolution.gameWidth > 0 && resolution.gameHeight > 0 ) { const fheroes2::FontType fontType = fheroes2::FontType::normalYellow(); const auto [leftText, rightText] = getResolutionStrings( resolution ); const int32_t middleTextSize = fheroes2::Text( middleText, fontType ).width(); const int32_t leftTextSize = fheroes2::Text( leftText, fontType ).width(); const int32_t textOffsetX = dst.x + textAreaWidth / 2 - leftTextSize - middleTextSize / 2; const fheroes2::Text resolutionText( leftText + middleText + rightText, fontType ); resolutionText.draw( textOffsetX, dst.y + ( resolutionItemHeight - resolutionText.height() + textOffsetYCorrection ) / 2, output ); } } fheroes2::ResolutionInfo getNewResolution() { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const int32_t listHeightDeduction = 112; const int32_t listAreaOffsetY = 3; const int32_t listAreaHeightDeduction = 4; std::vector resolutions = fheroes2::engine().getAvailableResolutions(); // If we don't have many resolutions, we reduce the maximum dialog height, // but not less than enough for 11 elements. // We also limit the maximum list height to 22 lines. const int32_t maxDialogHeight = fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) * std::clamp( static_cast( resolutions.size() ), 11, 22 ) + listAreaOffsetY + listAreaHeightDeduction + listHeightDeduction; fheroes2::Display & display = fheroes2::Display::instance(); // Dialog height is also capped with the current screen height. fheroes2::StandardWindow background( paddingLeftSide + textAreaWidth + scrollBarAreaWidth + 3, std::min( display.height() - 100, maxDialogHeight ), true, display ); const fheroes2::Rect roi( background.activeArea() ); const fheroes2::Rect listRoi( roi.x + paddingLeftSide, roi.y + 37, textAreaWidth, roi.height - listHeightDeduction ); // We divide the list: resolution list and selected resolution. const fheroes2::Rect selectedResRoi( listRoi.x, listRoi.y + listRoi.height + 12, listRoi.width, 21 ); background.applyTextBackgroundShading( selectedResRoi ); background.applyTextBackgroundShading( { listRoi.x, listRoi.y, listRoi.width, listRoi.height } ); fheroes2::ImageRestorer selectedResBackground( fheroes2::Display::instance(), selectedResRoi.x, selectedResRoi.y, listRoi.width, selectedResRoi.height ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); // Prepare OKAY and CANCEL buttons and render their shadows. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); ResolutionList listBox( roi.getPosition() ); listBox.initListBackgroundRestorer( listRoi ); listBox.SetAreaItems( { listRoi.x, listRoi.y + 3, listRoi.width - 3, listRoi.height - 4 } ); int32_t scrollbarOffsetX = roi.x + roi.width - 35; background.renderScrollbarBackground( { scrollbarOffsetX, listRoi.y, listRoi.width, listRoi.height }, isEvilInterface ); const int32_t topPartHeight = 19; ++scrollbarOffsetX; const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; listBox.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, listRoi.y + 1 } ); listBox.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, listRoi.y + listRoi.height - 15 } ); listBox.setScrollBarArea( { scrollbarOffsetX + 2, listRoi.y + topPartHeight, 10, listRoi.height - 2 * topPartHeight } ); listBox.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); listBox.SetAreaMaxItems( ( listRoi.height - 7 ) / fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) ); listBox.SetListContent( resolutions ); listBox.updateScrollBarImage(); const fheroes2::ResolutionInfo currentResolution{ display.width(), display.height(), display.screenSize().width, display.screenSize().height }; fheroes2::ResolutionInfo selectedResolution; for ( size_t i = 0; i < resolutions.size(); ++i ) { if ( resolutions[i] == currentResolution ) { listBox.SetCurrent( i ); selectedResolution = listBox.GetCurrent(); break; } } listBox.Redraw(); RedrawInfo( selectedResRoi.getPosition(), selectedResolution, display ); const fheroes2::Text title( _( "Select Game Resolution:" ), fheroes2::FontType::normalYellow() ); title.draw( roi.x + ( roi.width - title.width() ) / 2, roi.y + 16, display ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); const int listId = listBox.getCurrentId(); listBox.QueueEventProcessing(); const bool needRedraw = listId != listBox.getCurrentId(); if ( ( buttonOk.isEnabled() && le.MouseClickLeft( buttonOk.area() ) ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || listBox.isDoubleClicked() ) { if ( listBox.isSelected() ) { break; } } else if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { selectedResolution = {}; break; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to apply the selected resolution." ), Dialog::ZERO ); } if ( !listBox.IsNeedRedraw() ) { continue; } if ( needRedraw ) { selectedResolution = listBox.GetCurrent(); selectedResBackground.restore(); RedrawInfo( selectedResRoi.getPosition(), selectedResolution, display ); } listBox.Redraw(); display.render( roi ); } return selectedResolution; } } namespace Dialog { bool SelectResolution() { const fheroes2::ResolutionInfo selectedResolution = getNewResolution(); if ( selectedResolution == fheroes2::ResolutionInfo{} ) { return false; } fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::ResolutionInfo currentResolution{ display.width(), display.height(), display.screenSize().width, display.screenSize().height }; if ( selectedResolution.gameWidth > 0 && selectedResolution.gameHeight > 0 && selectedResolution.screenWidth >= selectedResolution.gameWidth && selectedResolution.screenHeight >= selectedResolution.gameHeight && selectedResolution != currentResolution ) { display.setResolution( selectedResolution ); #if !defined( MACOS_APP_BUNDLE ) const fheroes2::Image & appIcon = Compression::CreateImageFromZlib( 32, 32, iconImage, sizeof( iconImage ), true ); fheroes2::engine().setIcon( appIcon ); #endif return true; } return false; } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_resolution.h000066400000000000000000000031211476115357100236200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace Dialog { // Returns true if the screen resolution has been changed, otherwise returns false. bool SelectResolution(); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_selectcount.cpp000066400000000000000000000601521476115357100243070ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game_delays.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "math_tools.h" #include "screen.h" #include "settings.h" #include "system.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_keyboard.h" #include "ui_language.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" namespace { bool SwitchMaxMinButtons( fheroes2::ButtonBase & minButton, fheroes2::ButtonBase & maxButton, const int32_t currentValue, const int32_t minimumValue ) { const bool isMinValue = ( currentValue <= minimumValue ); if ( ( isMinValue && minButton.isHidden() && maxButton.isVisible() ) || ( !isMinValue && minButton.isVisible() && maxButton.isHidden() ) ) { // The MIN/MAX buttons switch is not needed. return false; } if ( isMinValue ) { minButton.hide(); maxButton.show(); maxButton.draw(); } else { maxButton.hide(); minButton.show(); minButton.draw(); } return true; } } bool Dialog::SelectCount( std::string header, const int32_t min, const int32_t max, int32_t & selectedValue, const int32_t step, const fheroes2::DialogElement * uiElement ) { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::Text headerText( std::move( header ), fheroes2::FontType::normalWhite() ); int32_t headerOffsetY{ 10 }; const int32_t selectionAreaHeight{ 30 }; const int32_t headerHeight = headerText.height( fheroes2::boxAreaWidthPx ); const int32_t uiWidth = uiElement ? uiElement->area().width : 0; const int32_t uiHeight = uiElement ? uiElement->area().height : 0; const FrameBox box( headerHeight + headerOffsetY + selectionAreaHeight + uiHeight, true ); const fheroes2::Rect & windowArea = box.GetArea(); fheroes2::Display & display = fheroes2::Display::instance(); headerText.draw( windowArea.x, windowArea.y, fheroes2::boxAreaWidthPx, display ); const fheroes2::Point uiOffset{ windowArea.x + ( windowArea.width - uiWidth ) / 2, windowArea.y + headerHeight + headerOffsetY }; if ( uiElement ) { uiElement->draw( display, uiOffset ); headerOffsetY *= 2; } const fheroes2::Size valueSelectionSize{ fheroes2::ValueSelectionDialogElement::getArea() }; const fheroes2::Rect selectionBoxArea{ windowArea.x + 38, windowArea.y + headerOffsetY + headerHeight + uiHeight, valueSelectionSize.width, valueSelectionSize.height }; fheroes2::ValueSelectionDialogElement valueSelectionElement( min, max, selectedValue, step, selectionBoxArea.getPosition() ); valueSelectionElement.ignoreMouseWheelEventRoiCheck(); valueSelectionElement.draw( display ); fheroes2::ButtonGroup btnGroups( box.GetArea(), Dialog::OK | Dialog::CANCEL ); btnGroups.draw(); const fheroes2::Point minMaxButtonOffset( selectionBoxArea.x + selectionBoxArea.width + 6, selectionBoxArea.y ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); fheroes2::Button buttonMax( minMaxButtonOffset.x, minMaxButtonOffset.y, isEvilInterface ? ICN::UNIFORM_EVIL_MAX_BUTTON : ICN::UNIFORM_GOOD_MAX_BUTTON, 0, 1 ); fheroes2::Button buttonMin( minMaxButtonOffset.x, minMaxButtonOffset.y, isEvilInterface ? ICN::UNIFORM_EVIL_MIN_BUTTON : ICN::UNIFORM_GOOD_MIN_BUTTON, 0, 1 ); const fheroes2::Rect interactionElementsRect( fheroes2::getBoundaryRect( fheroes2::getBoundaryRect( buttonMin.area(), buttonMax.area() ), selectionBoxArea ) ); SwitchMaxMinButtons( buttonMin, buttonMax, selectedValue, min ); display.render(); int result = Dialog::ZERO; const fheroes2::Rect uiRect = uiElement ? fheroes2::Rect{ uiOffset, uiElement->area() } : fheroes2::Rect{}; LocalEvent & le = LocalEvent::Get(); while ( result == Dialog::ZERO && le.HandleEvents() ) { bool needRedraw = false; if ( buttonMax.isVisible() ) { buttonMax.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMax.area() ) ); } if ( buttonMin.isVisible() ) { buttonMin.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMin.area() ) ); } if ( fheroes2::processIntegerValueTyping( min, max, selectedValue ) ) { valueSelectionElement.setValue( selectedValue ); needRedraw = true; } else if ( buttonMax.isVisible() && le.MouseClickLeft( buttonMax.area() ) ) { valueSelectionElement.setValue( max ); needRedraw = true; } else if ( buttonMin.isVisible() && le.MouseClickLeft( buttonMin.area() ) ) { valueSelectionElement.setValue( min ); needRedraw = true; } if ( valueSelectionElement.processEvents() ) { selectedValue = valueSelectionElement.getValue(); needRedraw = true; } if ( uiElement && ( le.isMouseLeftButtonReleasedInArea( uiRect ) || le.isMouseRightButtonPressedInArea( uiRect ) ) ) { uiElement->processEvents( uiOffset ); display.render(); } if ( needRedraw ) { const bool redrawMinMax = SwitchMaxMinButtons( buttonMin, buttonMax, valueSelectionElement.getValue(), min ); valueSelectionElement.draw( display ); display.render( redrawMinMax ? interactionElementsRect : selectionBoxArea ); } result = btnGroups.processEvents(); } selectedValue = ( result == Dialog::OK ) ? valueSelectionElement.getValue() : 0; return result == Dialog::OK; } bool Dialog::inputString( const fheroes2::TextBase & title, const fheroes2::TextBase & body, std::string & result, const size_t charLimit, const bool isMultiLine, const std::optional & textLanguage ) { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); result.reserve( charLimit == 0 ? 48 : charLimit ); size_t charInsertPos = result.size(); const bool hasTitle = !title.empty(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int32_t titleHeight = hasTitle ? title.height( fheroes2::boxAreaWidthPx ) + 10 : 0; const int32_t keyBoardButtonExtraHeight = 20; const fheroes2::Sprite & inputArea = fheroes2::AGG::GetICN( ( isEvilInterface ? ICN::BUYBUILD : ICN::BUYBUILE ), 3 ); const int32_t inputAreaWidth = isMultiLine ? 224 : inputArea.width(); const int32_t inputAreaHeight = isMultiLine ? 265 : inputArea.height(); const int32_t textboxHeight = body.height( fheroes2::boxAreaWidthPx ); const int32_t frameBoxHeight = 10 + titleHeight + textboxHeight + 10 + inputAreaHeight + keyBoardButtonExtraHeight; const FrameBox box( frameBoxHeight, true ); const fheroes2::Rect & frameBoxArea = box.GetArea(); // Title text. if ( hasTitle ) { title.draw( frameBoxArea.x, frameBoxArea.y + 12, fheroes2::boxAreaWidthPx, display ); } // Header text. body.draw( frameBoxArea.x, frameBoxArea.y + 12 + titleHeight, fheroes2::boxAreaWidthPx, display ); fheroes2::Point dst_pt{ frameBoxArea.x + ( frameBoxArea.width - inputAreaWidth ) / 2, frameBoxArea.y + 10 + titleHeight + textboxHeight + 10 }; fheroes2::Rect inputAreaOffset; if ( isMultiLine ) { inputAreaOffset = { 5, 5, -10, -10 }; fheroes2::StandardWindow::applyTextBackgroundShading( display, { dst_pt.x, dst_pt.y, inputAreaWidth, inputAreaHeight } ); } else { inputAreaOffset = { 13, 1, -26, -3 }; fheroes2::Blit( inputArea, display, dst_pt.x, dst_pt.y ); } const fheroes2::Rect textInputArea( dst_pt.x + inputAreaOffset.x, dst_pt.y + inputAreaOffset.y, inputAreaWidth + inputAreaOffset.width, inputAreaHeight + inputAreaOffset.height ); fheroes2::ImageRestorer textBackground( display, textInputArea.x, textInputArea.y, textInputArea.width, textInputArea.height ); bool isCursorVisible = true; const fheroes2::FontType fontType( fheroes2::FontType::normalWhite() ); fheroes2::Text text( insertCharToString( result, charInsertPos, isCursorVisible ? '_' : '\x7F' ), fontType, textLanguage ); text.keepLineTrailingSpaces(); if ( !isMultiLine ) { text.fitToOneRow( textInputArea.width ); } text.drawInRoi( textInputArea.x, textInputArea.y + 2, textInputArea.width, display, textInputArea ); const int okayButtonICNID = isEvilInterface ? ICN::UNIFORM_EVIL_OKAY_BUTTON : ICN::UNIFORM_GOOD_OKAY_BUTTON; dst_pt.x = frameBoxArea.x; dst_pt.y = frameBoxArea.y + frameBoxArea.height - fheroes2::AGG::GetICN( okayButtonICNID, 0 ).height(); fheroes2::Button buttonOk( dst_pt.x, dst_pt.y, okayButtonICNID, 0, 1 ); const int cancelButtonIcnID = isEvilInterface ? ICN::UNIFORM_EVIL_CANCEL_BUTTON : ICN::UNIFORM_GOOD_CANCEL_BUTTON; const fheroes2::Sprite & cancelButtonIcn = fheroes2::AGG::GetICN( cancelButtonIcnID, 0 ); dst_pt.x = frameBoxArea.x + frameBoxArea.width - cancelButtonIcn.width(); dst_pt.y = frameBoxArea.y + frameBoxArea.height - cancelButtonIcn.height(); fheroes2::Button buttonCancel( dst_pt.x, dst_pt.y, cancelButtonIcnID, 0, 1 ); // Generate a button to open the Virtual Keyboard window. fheroes2::Sprite releasedVirtualKB; fheroes2::Sprite pressedVirtualKB; const fheroes2::Size buttonVirtualKBSize{ 40, 25 }; makeButtonSprites( releasedVirtualKB, pressedVirtualKB, "...", buttonVirtualKBSize, isEvilInterface, isEvilInterface ? ICN::UNIFORMBAK_EVIL : ICN::UNIFORMBAK_GOOD ); // To center the button horizontally we have to take into account that actual button sprite is 10 pixels longer then the requested button width. fheroes2::ButtonSprite buttonVirtualKB = makeButtonWithBackground( frameBoxArea.x + ( frameBoxArea.width - buttonVirtualKBSize.width - 10 ) / 2, dst_pt.y - 30, releasedVirtualKB, pressedVirtualKB, display ); if ( result.empty() ) { buttonOk.disable(); } else { buttonOk.enable(); } buttonOk.draw(); buttonCancel.draw(); buttonVirtualKB.draw(); display.render(); // We add extra 4 pixels to the click area width to help setting the cursor at the end of the line if it is fully filled with text characters. const fheroes2::Rect textEditClickArea{ textInputArea.x, textInputArea.y, textInputArea.width + 4, textInputArea.height }; LocalEvent & le = LocalEvent::Get(); Game::AnimateResetDelay( Game::DelayType::CURSOR_BLINK_DELAY ); const bool isInGameKeyboardRequired = System::isVirtualKeyboardSupported(); while ( le.HandleEvents( Game::isDelayNeeded( { Game::DelayType::CURSOR_BLINK_DELAY } ) ) ) { bool redraw = false; if ( buttonOk.isEnabled() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonVirtualKB.drawOnState( le.isMouseLeftButtonPressedInArea( buttonVirtualKB.area() ) ); // In this dialog we input text so we need to use hotkeys that cannot be use in text typing. if ( ( !isMultiLine && le.isKeyPressed( fheroes2::Key::KEY_ENTER ) ) || ( buttonOk.isEnabled() && le.MouseClickLeft( buttonOk.area() ) ) ) { return !result.empty(); } if ( le.isKeyPressed( fheroes2::Key::KEY_ESCAPE ) || le.MouseClickLeft( buttonCancel.area() ) ) { result.clear(); return false; } if ( le.MouseClickLeft( buttonVirtualKB.area() ) || ( isInGameKeyboardRequired && le.MouseClickLeft( textEditClickArea ) ) ) { if ( textLanguage.has_value() ) { const fheroes2::LanguageSwitcher switcher( textLanguage.value() ); fheroes2::openVirtualKeyboard( result, charLimit ); } else { fheroes2::openVirtualKeyboard( result, charLimit ); } if ( charLimit > 0 && result.size() > charLimit ) { result.resize( charLimit ); } charInsertPos = result.size(); redraw = true; } else if ( le.isAnyKeyPressed() && ( charLimit == 0 || charLimit > result.size() || le.getPressedKeyValue() == fheroes2::Key::KEY_BACKSPACE ) ) { // Handle new line input for multi-line texts only. if ( isMultiLine && le.getPressedKeyValue() == fheroes2::Key::KEY_ENTER ) { result.insert( charInsertPos, 1, '\n' ); ++charInsertPos; } else { charInsertPos = InsertKeySym( result, charInsertPos, le.getPressedKeyValue(), LocalEvent::getCurrentKeyModifiers() ); } redraw = true; } else if ( le.MouseClickLeft( textEditClickArea ) ) { if ( textLanguage.has_value() ) { const fheroes2::LanguageSwitcher switcher( textLanguage.value() ); charInsertPos = fheroes2::getTextInputCursorPosition( text, charInsertPos, le.getMouseCursorPos(), textInputArea ); } else { charInsertPos = fheroes2::getTextInputCursorPosition( text, charInsertPos, le.getMouseCursorPos(), textInputArea ); } redraw = true; } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to apply the entered text." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonVirtualKB.area() ) ) { fheroes2::showStandardTextMessage( _( "Open Virtual Keyboard" ), _( "Click to open the Virtual Keyboard dialog." ), Dialog::ZERO ); } // Text input cursor blink. if ( Game::validateAnimationDelay( Game::DelayType::CURSOR_BLINK_DELAY ) ) { isCursorVisible = !isCursorVisible; redraw = true; } if ( redraw ) { bool redrawOkButton = false; if ( result.empty() && buttonOk.isEnabled() ) { buttonOk.disable(); redrawOkButton = true; } else if ( !result.empty() && !buttonOk.isEnabled() ) { buttonOk.enable(); redrawOkButton = true; } if ( redrawOkButton ) { buttonOk.draw(); display.updateNextRenderRoi( buttonOk.area() ); } text.set( insertCharToString( result, charInsertPos, isCursorVisible ? '_' : '\x7F' ), fontType, textLanguage ); if ( !isMultiLine ) { text.fitToOneRow( textInputArea.width ); } textBackground.restore(); text.drawInRoi( textInputArea.x, textInputArea.y + 2, textInputArea.width, display, textInputArea ); display.render( textInputArea ); } } return !result.empty(); } int Dialog::ArmySplitTroop( const int32_t freeSlots, const int32_t redistributeMax, int32_t & redistributeCount, bool & useFastSplit, const std::string & troopName ) { assert( redistributeCount >= 0 ); assert( freeSlots > 0 ); fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const int32_t redistributeMin = std::min( 1, redistributeMax ); const int spacer = 10; const fheroes2::Text header( troopName, fheroes2::FontType::normalYellow() ); const int32_t headerHeight = header.height() + 6; const std::string msg( _( "How many creatures do you wish to move?" ) ); fheroes2::Text titleText( msg, fheroes2::FontType::normalWhite() ); titleText.setUniformVerticalAlignment( false ); const int32_t titleHeight = headerHeight + titleText.rows( fheroes2::boxAreaWidthPx ) * titleText.height(); fheroes2::Text slotSeparationText( _( "Select how many units to separate into:" ), fheroes2::FontType::normalWhite() ); slotSeparationText.setUniformVerticalAlignment( false ); const int32_t bodyHeight = slotSeparationText.rows( fheroes2::boxAreaWidthPx ) * slotSeparationText.height(); const int defaultYPosition = 160; const int boxHeight = freeSlots > 1 ? 63 + spacer + titleHeight + bodyHeight : 45; const int boxYPosition = defaultYPosition + ( ( display.height() - fheroes2::Display::DEFAULT_HEIGHT ) / 2 ) - boxHeight; const NonFixedFrameBox box( boxHeight, boxYPosition, true ); const fheroes2::Rect & pos = box.GetArea(); const int center = pos.x + pos.width / 2; const int textTopOffset = 13; header.draw( pos.x, pos.y + 2, fheroes2::boxAreaWidthPx, display ); titleText.draw( pos.x, pos.y + 2 + headerHeight, fheroes2::boxAreaWidthPx, display ); const fheroes2::Size valueSelectionSize{ fheroes2::ValueSelectionDialogElement::getArea() }; const fheroes2::Rect selectionBoxArea{ pos.x + 70, pos.y + textTopOffset + titleHeight, valueSelectionSize.width, valueSelectionSize.height }; fheroes2::ValueSelectionDialogElement valueSelectionElement( redistributeMin, redistributeMax, redistributeCount, 1, selectionBoxArea.getPosition() ); valueSelectionElement.ignoreMouseWheelEventRoiCheck(); valueSelectionElement.draw( display ); fheroes2::MovableSprite ssp; std::vector vrts( freeSlots - 1 ); if ( freeSlots > 1 ) { std::vector sprites( freeSlots - 1 ); int spriteIconIdx = 21; const int deltaX = 10; const int deltaXStart = ( freeSlots - 2 ) * -5; for ( int32_t i = 0; i < freeSlots - 1; ++i ) { sprites[i] = fheroes2::AGG::GetICN( ICN::REQUESTS, spriteIconIdx ); ++spriteIconIdx; const int spriteWidth = sprites[i].width(); const int offset = spriteWidth * ( 2 * i + 1 - freeSlots ) / 2; vrts[i] = { center + offset + deltaXStart + i * deltaX, pos.y + textTopOffset + titleHeight + bodyHeight + 45, spriteWidth, sprites[i].height() }; } slotSeparationText.draw( pos.x, pos.y + textTopOffset + titleHeight + 37, fheroes2::boxAreaWidthPx, display ); for ( int32_t i = 0; i < freeSlots - 1; ++i ) { fheroes2::Blit( sprites[i], display, vrts[i].x, vrts[i].y ); } ssp.resize( sprites[0].width(), sprites[0].height() ); ssp.reset(); fheroes2::DrawBorder( ssp, 214 ); if ( useFastSplit ) { ssp.setPosition( vrts[0].x, vrts[0].y ); ssp.show(); } } fheroes2::ButtonGroup btnGroups( box.GetArea(), Dialog::OK | Dialog::CANCEL ); btnGroups.draw(); const fheroes2::Point minMaxButtonOffset( pos.x + 165, pos.y + textTopOffset + titleHeight ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); fheroes2::Button buttonMax( minMaxButtonOffset.x, minMaxButtonOffset.y, isEvilInterface ? ICN::UNIFORM_EVIL_MAX_BUTTON : ICN::UNIFORM_GOOD_MAX_BUTTON, 0, 1 ); fheroes2::Button buttonMin( minMaxButtonOffset.x, minMaxButtonOffset.y, isEvilInterface ? ICN::UNIFORM_EVIL_MIN_BUTTON : ICN::UNIFORM_GOOD_MIN_BUTTON, 0, 1 ); const fheroes2::Rect buttonArea( 5, 0, 61, 25 ); SwitchMaxMinButtons( buttonMin, buttonMax, redistributeCount, redistributeMin ); LocalEvent & le = LocalEvent::Get(); display.render(); // message loop int bres = Dialog::ZERO; while ( bres == Dialog::ZERO && le.HandleEvents() ) { bool redraw_count = false; if ( buttonMax.isVisible() ) { buttonMax.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMax.area() ) ); } if ( buttonMin.isVisible() ) { buttonMin.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMin.area() ) ); } if ( fheroes2::processIntegerValueTyping( redistributeMin, redistributeMax, redistributeCount ) ) { valueSelectionElement.setValue( redistributeCount ); redraw_count = true; } else if ( buttonMax.isVisible() && le.MouseClickLeft( buttonMax.area() ) ) { redistributeCount = redistributeMax; valueSelectionElement.setValue( redistributeMax ); redraw_count = true; } else if ( buttonMin.isVisible() && le.MouseClickLeft( buttonMin.area() ) ) { redistributeCount = redistributeMin; valueSelectionElement.setValue( redistributeMin ); redraw_count = true; } else if ( valueSelectionElement.processEvents() ) { redistributeCount = valueSelectionElement.getValue(); redraw_count = true; } if ( !ssp.empty() ) { for ( std::vector::const_iterator it = vrts.begin(); it != vrts.end(); ++it ) { if ( le.MouseClickLeft( *it ) ) { ssp.setPosition( it->x, it->y ); ssp.show(); display.render( pos ); } } } if ( redraw_count ) { SwitchMaxMinButtons( buttonMin, buttonMax, valueSelectionElement.getValue(), redistributeMin ); if ( !ssp.empty() ) { ssp.hide(); } valueSelectionElement.draw( display ); if ( buttonMax.isVisible() ) { buttonMax.draw(); } if ( buttonMin.isVisible() ) { buttonMin.draw(); } display.render( pos ); } bres = btnGroups.processEvents(); } int result = 0; if ( bres == Dialog::OK ) { redistributeCount = valueSelectionElement.getValue(); if ( !ssp.isHidden() ) { const fheroes2::Rect rt( ssp.x(), ssp.y(), ssp.width(), ssp.height() ); for ( int32_t i = 0; i < freeSlots - 1; ++i ) { if ( rt == vrts[i] ) { result = i + 2; break; } } useFastSplit = true; } else { result = 2; useFastSplit = false; } } return result; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_selectfile.cpp000066400000000000000000000602601476115357100240760ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "dir.h" #include "game_delays.h" #include "game_hotkeys.h" #include "game_io.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "maps_fileinfo.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "system.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_keyboard.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" namespace { // This constant sets the maximum displayed file name width. This value affects the dialog horizontal size. const int32_t maxFileNameWidth = 260; void redrawDateTime( fheroes2::Image & output, const time_t timestamp, const int32_t dstx, const int32_t dsty, const fheroes2::FontType font ) { const size_t arraySize = 5; char shortMonth[arraySize]; char shortDate[arraySize]; char shortHours[arraySize]; char shortMinutes[arraySize]; const tm tmi = System::GetTM( timestamp ); // TODO: Use system locale date format (e.g. 9 Mar instead of Mar 09). std::strftime( shortMonth, arraySize, "%b", &tmi ); std::strftime( shortDate, arraySize, "%d", &tmi ); std::strftime( shortHours, arraySize, "%H", &tmi ); std::strftime( shortMinutes, arraySize, "%M", &tmi ); fheroes2::Text text( shortMonth, font ); text.draw( dstx + 4, dsty, output ); text.set( shortDate, font ); text.draw( dstx + 56 - text.width() / 2, dsty, output ); text.set( ",", font ); text.draw( dstx + 66, dsty, output ); text.set( shortHours, font ); text.draw( dstx + 82 - text.width() / 2, dsty, output ); text.set( ":", font ); text.draw( dstx + 92, dsty, output ); text.set( shortMinutes, font ); text.draw( dstx + 105 - text.width() / 2, dsty, output ); } void redrawTextInputField( const std::string & filename, const fheroes2::Rect & field, const bool isEditing ) { if ( filename.empty() ) { return; } fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Text currentFilename( filename, isEditing ? fheroes2::FontType::normalWhite() : fheroes2::FontType::normalYellow() ); // Do not ignore spaces at the end. currentFilename.keepLineTrailingSpaces(); currentFilename.fitToOneRow( maxFileNameWidth ); currentFilename.draw( field.x + 4 + ( maxFileNameWidth - currentFilename.width() ) / 2, field.y + 4, display ); } class FileInfoListBox : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; using ListBox::ListBox; void RedrawItem( const Maps::FileInfo & info, int32_t dstx, int32_t dsty, bool current ) override; void RedrawBackground( const fheroes2::Point & dst ) override; void ActionCurrentUp() override; void ActionCurrentDn() override; void ActionListDoubleClick( Maps::FileInfo & info ) override; void ActionListSingleClick( Maps::FileInfo & info ) override; void ActionListPressRight( Maps::FileInfo & info ) override { const fheroes2::Text header( System::GetStem( info.filename ), fheroes2::FontType::normalYellow() ); fheroes2::MultiFontText body; body.add( { _( "Map: " ), fheroes2::FontType::normalYellow() } ); body.add( { info.name, fheroes2::FontType::normalWhite(), info.getSupportedLanguage() } ); if ( info.worldDay > 0 || info.worldWeek > 0 || info.worldMonth > 0 ) { body.add( { _( "\n\nMonth: " ), fheroes2::FontType::normalYellow() } ); body.add( { std::to_string( info.worldMonth ), fheroes2::FontType::normalWhite() } ); body.add( { _( ", Week: " ), fheroes2::FontType::normalYellow() } ); body.add( { std::to_string( info.worldWeek ), fheroes2::FontType::normalWhite() } ); body.add( { _( ", Day: " ), fheroes2::FontType::normalYellow() } ); body.add( { std::to_string( info.worldDay ), fheroes2::FontType::normalWhite() } ); } body.add( { _( "\n\nLocation: " ), fheroes2::FontType::smallYellow() } ); body.add( { info.filename, fheroes2::FontType::smallWhite() } ); fheroes2::showMessage( header, body, Dialog::ZERO ); } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } bool isDoubleClicked() const { return _isDoubleClicked; } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: bool _isDoubleClicked{ false }; std::unique_ptr _listBackground; }; void FileInfoListBox::RedrawItem( const Maps::FileInfo & info, int32_t dstx, int32_t dsty, bool current ) { std::string savname( System::GetStem( info.filename ) ); assert( !savname.empty() ); const fheroes2::FontType font = current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite(); fheroes2::Display & display = fheroes2::Display::instance(); dsty += 2; fheroes2::Text text{ std::move( savname ), font }; text.keepLineTrailingSpaces(); text.fitToOneRow( maxFileNameWidth ); text.draw( dstx + 4 + ( maxFileNameWidth - text.width() ) / 2, dsty, display ); redrawDateTime( display, info.timestamp, dstx + maxFileNameWidth + 9, dsty, font ); } void FileInfoListBox::RedrawBackground( const fheroes2::Point & /* unused */ ) { _listBackground->restore(); } void FileInfoListBox::ActionCurrentUp() { // Do nothing. } void FileInfoListBox::ActionCurrentDn() { // Do nothing. } void FileInfoListBox::ActionListDoubleClick( Maps::FileInfo & /*unused*/ ) { _isDoubleClicked = true; } void FileInfoListBox::ActionListSingleClick( Maps::FileInfo & /*unused*/ ) { // Do nothing. } MapsFileInfoList getSortedMapsFileInfoList() { ListFiles files; files.ReadDir( Game::GetSaveDir(), Game::GetSaveFileExtension() ); MapsFileInfoList mapInfos; mapInfos.reserve( files.size() ); for ( std::string & saveFile : files ) { Maps::FileInfo mapInfo; if ( Game::LoadSAV2FileInfo( std::move( saveFile ), mapInfo ) ) { mapInfos.emplace_back( std::move( mapInfo ) ); } } std::sort( mapInfos.begin(), mapInfos.end(), Maps::FileInfo::sortByFileName ); return mapInfos; } std::string selectFileListSimple( const std::string & header, const std::string & lastfile, const bool isEditing ) { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); MapsFileInfoList lists = getSortedMapsFileInfoList(); const int32_t listHeightDeduction = 112; const int32_t listAreaOffsetY = 3; const int32_t listAreaHeightDeduction = 4; // If we don't have many save files, we reduce the maximum dialog height, // but not less than enough for 11 elements. // We also limit the maximum list height to 22 lines. const int32_t maxDialogHeight = fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) * std::clamp( static_cast( lists.size() ), 11, 22 ) + listAreaOffsetY + listAreaHeightDeduction + listHeightDeduction; fheroes2::Display & display = fheroes2::Display::instance(); // Dialog height is also capped with the current screen height. fheroes2::StandardWindow background( maxFileNameWidth + 204, std::min( display.height() - 100, maxDialogHeight ), true, display ); const fheroes2::Rect area( background.activeArea() ); const fheroes2::Rect listRoi( area.x + 24, area.y + 37, area.width - 75, area.height - listHeightDeduction ); const fheroes2::Rect textInputRoi( listRoi.x, listRoi.y + listRoi.height + 12, maxFileNameWidth + 8, 21 ); const int32_t dateTimeoffsetX = textInputRoi.x + textInputRoi.width; const int32_t dateTimeWidth = listRoi.width - textInputRoi.width; // We divide the save-files list: file name and file date/time. background.applyTextBackgroundShading( { listRoi.x, listRoi.y, textInputRoi.width, listRoi.height } ); background.applyTextBackgroundShading( { listRoi.x + textInputRoi.width, listRoi.y, dateTimeWidth, listRoi.height } ); background.applyTextBackgroundShading( textInputRoi ); // Make background for the selected file date and time. background.applyTextBackgroundShading( { dateTimeoffsetX, textInputRoi.y, dateTimeWidth, textInputRoi.height } ); fheroes2::ImageRestorer textInputAndDateBackground( fheroes2::Display::instance(), textInputRoi.x, textInputRoi.y, listRoi.width, textInputRoi.height ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); // Prepare OKAY and CANCEL buttons and render their shadows. fheroes2::Button buttonOk; if ( !isEditing && lists.empty() ) { buttonOk.disable(); } fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); // Virtual keyboard button is used only in save game mode (when 'isEditing' is true ). std::unique_ptr buttonVirtualKB; FileInfoListBox listbox( area.getPosition() ); // Initialize list background restorer to use it in list method 'listbox.RedrawBackground()'. listbox.initListBackgroundRestorer( listRoi ); listbox.SetAreaItems( { listRoi.x, listRoi.y + 3, listRoi.width - listAreaOffsetY, listRoi.height - listAreaHeightDeduction } ); int32_t scrollbarOffsetX = area.x + area.width - 35; background.renderScrollbarBackground( { scrollbarOffsetX, listRoi.y, listRoi.width, listRoi.height }, isEvilInterface ); const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; const int32_t topPartHeight = 19; ++scrollbarOffsetX; listbox.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, listRoi.y + 1 } ); listbox.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, listRoi.y + listRoi.height - 15 } ); listbox.setScrollBarArea( { scrollbarOffsetX + 2, listRoi.y + topPartHeight, 10, listRoi.height - 2 * topPartHeight } ); listbox.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); listbox.SetAreaMaxItems( ( listRoi.height - 7 ) / fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) ); listbox.SetListContent( lists ); listbox.updateScrollBarImage(); std::string filename; size_t charInsertPos = 0; if ( !lastfile.empty() ) { filename = System::GetStem( lastfile ); charInsertPos = filename.size(); MapsFileInfoList::iterator it = lists.begin(); for ( ; it != lists.end(); ++it ) { if ( ( *it ).filename == lastfile ) { break; } } if ( it != lists.end() ) { listbox.SetCurrent( std::distance( lists.begin(), it ) ); } else { if ( !isEditing ) { filename.clear(); charInsertPos = 0; } listbox.Unselect(); } } if ( filename.empty() && listbox.isSelected() ) { filename = System::GetStem( listbox.GetCurrent().filename ); charInsertPos = filename.size(); } auto buttonOkDisabler = [&buttonOk, &filename]() { if ( filename.empty() && buttonOk.isEnabled() ) { buttonOk.disable(); buttonOk.draw(); } else if ( !filename.empty() && buttonOk.isDisabled() ) { buttonOk.enable(); buttonOk.draw(); } }; listbox.Redraw(); redrawTextInputField( filename, textInputRoi, isEditing ); const fheroes2::Text title( header, fheroes2::FontType::normalYellow() ); title.draw( area.x + ( area.width - title.width() ) / 2, area.y + 16, display ); if ( isEditing ) { // Render a button to open the Virtual Keyboard window. buttonVirtualKB = std::make_unique(); background.renderButtonSprite( *buttonVirtualKB, "...", { 48, 25 }, { 0, 7 }, isEvilInterface, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); Game::passAnimationDelay( Game::DelayType::CURSOR_BLINK_DELAY ); } else if ( listbox.isSelected() ) { // Render the saved file date and time. redrawDateTime( display, listbox.GetCurrent().timestamp, dateTimeoffsetX, textInputRoi.y + 4, fheroes2::FontType::normalYellow() ); } display.render( background.totalArea() ); std::string result; std::string lastSelectedSaveFileName; const bool isInGameKeyboardRequired = System::isVirtualKeyboardSupported(); bool isCursorVisible = true; const size_t lengthLimit{ 255 }; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( !isEditing || Game::isDelayNeeded( { Game::DelayType::CURSOR_BLINK_DELAY } ) ) && result.empty() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( isEditing ) { buttonVirtualKB->drawOnState( le.isMouseLeftButtonPressedInArea( buttonVirtualKB->area() ) ); } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return {}; } const int listId = listbox.getCurrentId(); const bool listboxEvent = listbox.QueueEventProcessing(); bool isListboxSelected = listbox.isSelected(); bool needRedraw = listId != listbox.getCurrentId(); if ( le.isKeyPressed( fheroes2::Key::KEY_DELETE ) && isListboxSelected ) { listbox.SetCurrent( listId ); listbox.Redraw(); std::string msg( _( "Are you sure you want to delete file:" ) ); msg.append( "\n\n" ); msg.append( System::GetFileName( listbox.GetCurrent().filename ) ); if ( Dialog::YES == fheroes2::showStandardTextMessage( _( "Warning" ), msg, Dialog::YES | Dialog::NO ) ) { System::Unlink( listbox.GetCurrent().filename ); listbox.RemoveSelected(); if ( lists.empty() ) { listbox.Redraw(); isListboxSelected = false; charInsertPos = 0; filename.clear(); buttonOk.disable(); buttonOk.draw(); } listbox.updateScrollBarImage(); listbox.SetCurrent( std::max( listId - 1, 0 ) ); } needRedraw = true; } else if ( ( buttonOk.isEnabled() && le.MouseClickLeft( buttonOk.area() ) ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || listbox.isDoubleClicked() ) { if ( isListboxSelected ) { result = listbox.GetCurrent().filename; } else if ( !filename.empty() ) { result = System::concatPath( Game::GetSaveDir(), filename + Game::GetSaveFileExtension() ); } } else if ( isEditing ) { if ( le.MouseClickLeft( buttonVirtualKB->area() ) || ( isInGameKeyboardRequired && le.MouseClickLeft( textInputRoi ) ) ) { fheroes2::openVirtualKeyboard( filename, lengthLimit ); charInsertPos = filename.size(); listbox.Unselect(); isListboxSelected = false; needRedraw = true; buttonOkDisabler(); // Set the whole screen to redraw next time to properly restore image under the Virtual Keyboard dialog. display.updateNextRenderRoi( { 0, 0, display.width(), display.height() } ); } else if ( !filename.empty() && le.MouseClickLeft( textInputRoi ) ) { const fheroes2::Text text( filename, fheroes2::FontType::normalWhite() ); const int32_t textStartOffsetX = std::max( 0, ( textInputRoi.width - text.width() ) / 2 ); charInsertPos = fheroes2::getTextInputCursorPosition( filename, fheroes2::FontType::normalWhite(), charInsertPos, le.getMouseCursorPos().x, textInputRoi.x + textStartOffsetX ); listbox.Unselect(); isListboxSelected = false; needRedraw = true; } else if ( !listboxEvent && le.isAnyKeyPressed() && ( filename.size() < lengthLimit || fheroes2::Key::KEY_BACKSPACE == le.getPressedKeyValue() || fheroes2::Key::KEY_DELETE == le.getPressedKeyValue() ) && le.getPressedKeyValue() != fheroes2::Key::KEY_UP && le.getPressedKeyValue() != fheroes2::Key::KEY_DOWN ) { charInsertPos = InsertKeySym( filename, charInsertPos, le.getPressedKeyValue(), LocalEvent::getCurrentKeyModifiers() ); buttonOkDisabler(); needRedraw = true; listbox.Unselect(); isListboxSelected = false; } } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { if ( isEditing ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to save the current game." ), Dialog::ZERO ); } else { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to load a previously saved game." ), Dialog::ZERO ); } } else if ( isEditing && le.isMouseRightButtonPressedInArea( buttonVirtualKB->area() ) ) { fheroes2::showStandardTextMessage( _( "Open Virtual Keyboard" ), _( "Click to open the Virtual Keyboard dialog." ), Dialog::ZERO ); } // Text input cursor blink. if ( isEditing && Game::validateAnimationDelay( Game::DelayType::CURSOR_BLINK_DELAY ) ) { isCursorVisible = !isCursorVisible; needRedraw = true; } if ( !needRedraw && !listbox.IsNeedRedraw() ) { continue; } if ( needRedraw ) { const std::string selectedFileName = isListboxSelected ? System::GetStem( listbox.GetCurrent().filename ) : ""; if ( isListboxSelected && lastSelectedSaveFileName != selectedFileName ) { lastSelectedSaveFileName = selectedFileName; filename = selectedFileName; charInsertPos = filename.size(); buttonOkDisabler(); } else if ( isEditing ) { // Empty last selected save file name so that we can replace the input field's name if we select the same save file again. // But when loading (i.e. isEditing == false), this doesn't matter since we cannot write to the input field lastSelectedSaveFileName = ""; } textInputAndDateBackground.restore(); if ( isEditing ) { redrawTextInputField( insertCharToString( filename, charInsertPos, isCursorVisible ? '_' : '\x7F' ), textInputRoi, true ); redrawDateTime( display, std::time( nullptr ), dateTimeoffsetX, textInputRoi.y + 4, fheroes2::FontType::normalWhite() ); } else if ( isListboxSelected ) { redrawTextInputField( filename, textInputRoi, false ); redrawDateTime( display, listbox.GetCurrent().timestamp, dateTimeoffsetX, textInputRoi.y + 4, fheroes2::FontType::normalYellow() ); } } if ( listbox.IsNeedRedraw() ) { listbox.Redraw(); display.render( area ); } else { display.render( textInputAndDateBackground.rect() ); } } return result; } } namespace Dialog { std::string SelectFileSave() { std::ostringstream os; os << System::concatPath( Game::GetSaveDir(), Game::GetSaveFileBaseName() ) << '_' << std::setw( 4 ) << std::setfill( '0' ) << world.CountDay() << Game::GetSaveFileExtension(); return selectFileListSimple( _( "File to Save:" ), os.str(), true ); } std::string SelectFileLoad() { const std::string & lastfile = Game::GetLastSaveName(); return selectFileListSimple( _( "File to Load:" ), ( !lastfile.empty() ? lastfile : "" ), false ); } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_selectitems.cpp000066400000000000000000002244151476115357100243040ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2011 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_selectitems.h" #include #include #include #include #include #include #include #include #include "agg_image.h" #include "army_troop.h" #include "castle.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "ground.h" #include "heroes_base.h" #include "icn.h" #include "kingdom.h" #include "localevent.h" #include "map_object_info.h" #include "maps.h" #include "maps_fileinfo.h" #include "mp2.h" #include "pal.h" #include "race.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_castle.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_map_object.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_tool.h" #include "world.h" namespace { const int32_t dialogHeightDeduction = 150; // Returns the town type according the given player color, race and castle/town state. int getPackedTownType( const int townRace, const bool isCastle ) { // NOTICE: This calculation should be consistent with the number of KINGDOM_TOWNS objects. return townRace * 2 + ( isCastle ? 0 : 1 ); } class SelectEnumMonster final : public Dialog::ItemSelectionWindow { public: explicit SelectEnumMonster( const fheroes2::Size & rt, std::string title ) : Dialog::ItemSelectionWindow( rt, std::move( title ) ) { SetAreaMaxItems( rtAreaItems.height / _offsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { const Monster mons( index ); const fheroes2::Sprite & monsterSprite = fheroes2::AGG::GetICN( ICN::MONS32, mons.GetSpriteIndex() ); renderItem( monsterSprite, mons.GetName(), { dstx, dsty }, 45 / 2, 50, _offsetY / 2, current ); } void ActionListPressRight( int & index ) override { const Monster monster( index ); if ( !monster.isValid() ) { fheroes2::showStandardTextMessage( monster.GetName(), "", Dialog::ZERO ); return; } Dialog::ArmyInfo( Troop( monster, 0 ), Dialog::ZERO ); } private: static const int32_t _offsetY{ 43 }; }; class SelectEnumHeroes final : public Dialog::ItemSelectionWindow { public: explicit SelectEnumHeroes( const fheroes2::Size & rt, std::string title ) : Dialog::ItemSelectionWindow( rt, std::move( title ) ) { SetAreaMaxItems( rtAreaItems.height / _offsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { const fheroes2::Sprite & port = Heroes::GetPortrait( index, PORT_SMALL ); renderItem( port, Heroes::GetName( index ), { dstx, dsty }, 45 / 2, 50, _offsetY / 2, current ); } void ActionListPressRight( int & index ) override { Dialog::QuickInfo( *world.GetHeroes( index ) ); } private: static const int32_t _offsetY{ 35 }; }; class SelectEnumArtifact final : public Dialog::ItemSelectionWindow { public: explicit SelectEnumArtifact( const fheroes2::Size & rt, std::string title ) : Dialog::ItemSelectionWindow( rt, std::move( title ) ) { SetAreaMaxItems( rtAreaItems.height / _offsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { const Artifact art( index ); const fheroes2::Sprite & artifactSprite = fheroes2::AGG::GetICN( ICN::ARTFX, art.IndexSprite32() ); renderItem( artifactSprite, art.GetName(), { dstx, dsty }, 45 / 2, 50, _offsetY / 2, current ); } void ActionListPressRight( int & index ) override { fheroes2::ArtifactDialogElement( Artifact( index ) ).showPopup( Dialog::ZERO ); } private: static const int32_t _offsetY{ 42 }; }; class SelectEnumSpell final : public Dialog::ItemSelectionWindow { public: explicit SelectEnumSpell( const fheroes2::Size & rt, std::string title ) : Dialog::ItemSelectionWindow( rt, std::move( title ) ) { SetAreaMaxItems( rtAreaItems.height / _offsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { const Spell spell( index ); const fheroes2::Sprite & spellSprite = fheroes2::AGG::GetICN( ICN::SPELLS, spell.IndexSprite() ); renderItem( spellSprite, spell.GetName(), { dstx, dsty }, 75 / 2, 80, _offsetY / 2, current ); } void ActionListPressRight( int & index ) override { fheroes2::SpellDialogElement( Spell( index ), nullptr ).showPopup( Dialog::ZERO ); } private: static const int32_t _offsetY{ 55 }; }; class SelectEnumSecSkill final : public Dialog::ItemSelectionWindow { public: static int getSkillFromListIndex( int index ) { return 1 + index / 3; } static int getLevelFromListIndex( int index ) { return 1 + ( index % 3 ); } explicit SelectEnumSecSkill( const fheroes2::Size & rt, std::string title ) : Dialog::ItemSelectionWindow( rt, std::move( title ) ) { SetAreaMaxItems( rtAreaItems.height / _offsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { const Skill::Secondary skill( getSkillFromListIndex( index ), getLevelFromListIndex( index ) ); const fheroes2::Sprite & skillSprite = fheroes2::AGG::GetICN( ICN::MINISS, skill.GetIndexSprite2() ); renderItem( skillSprite, skill.GetName(), { dstx, dsty }, 45 / 2, 50, _offsetY / 2, current ); } void ActionListPressRight( int & index ) override { fheroes2::SecondarySkillDialogElement( Skill::Secondary( getSkillFromListIndex( index ), getLevelFromListIndex( index ) ), Heroes() ) .showPopup( Dialog::ZERO ); } private: static const int32_t _offsetY{ 42 }; }; class SelectKingdomCastle final : public Dialog::ItemSelectionWindow { public: explicit SelectKingdomCastle( const fheroes2::Size & rt, std::string title, std::string description ) : Dialog::ItemSelectionWindow( rt, std::move( title ), std::move( description ) ) , _townFrameIcnId( Settings::Get().isEvilInterfaceEnabled() ? ICN::LOCATORE : ICN::LOCATORS ) { SetAreaMaxItems( rtAreaItems.height / itemsOffsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { const Castle * castle = world.getCastleEntrance( Maps::GetPoint( index ) ); assert( castle != nullptr ); fheroes2::Sprite castleIcon( fheroes2::AGG::GetICN( _townFrameIcnId, 23 ) ); fheroes2::drawCastleIcon( *castle, castleIcon, { 4, 4 } ); renderItem( castleIcon, castle->GetName(), { dstx, dsty }, 35, 75, itemsOffsetY / 2, current ); } void ActionListPressRight( int & index ) override { Dialog::QuickInfoWithIndicationOnRadar( *world.getCastleEntrance( Maps::GetPoint( index ) ), getBackgroundArea() ); } static const int32_t itemsOffsetY{ 35 }; private: const int _townFrameIcnId; }; // This is a base class for items used in the Editor and they rely on Maps::ObjectInfo structures. class ObjectTypeSelection : public Dialog::ItemSelectionWindow { public: ObjectTypeSelection( const std::vector & objectInfo, const fheroes2::Size & size, std::string title, const int32_t imageOffsetX, const int32_t textOffsetX, const int32_t offsetY ) : Dialog::ItemSelectionWindow( size, std::move( title ) ) , _objectInfo( objectInfo ) , _imageOffsetX( imageOffsetX ) , _textOffsetX( textOffsetX ) , _offsetY( offsetY ) { SetAreaMaxItems( rtAreaItems.height / _offsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & objectId, int32_t posX, int32_t posY, bool isSelected ) override { // If this assertion blows up then you are setting different number of items. assert( objectId >= 0 && objectId < static_cast( _objectInfo.size() ) ); const fheroes2::Sprite & image = fheroes2::generateMapObjectImage( _objectInfo[objectId] ); const int32_t imageHeight = image.height(); const int32_t imageWidth = image.width(); if ( imageHeight > fheroes2::tileWidthPx * 3 || imageWidth > fheroes2::tileWidthPx * 5 ) { // Reduce the size of very tall images to fit the list. const double ratio = std::max( imageHeight / ( fheroes2::tileWidthPx * 3. ), imageWidth / ( fheroes2::tileWidthPx * 5. ) ); fheroes2::Image resized( static_cast( imageWidth / ratio ), static_cast( imageHeight / ratio ) ); fheroes2::Resize( image, resized ); renderItem( resized, getObjectName( _objectInfo[objectId] ), { posX, posY }, _imageOffsetX, _textOffsetX, _offsetY / 2, isSelected ); } else { renderItem( image, getObjectName( _objectInfo[objectId] ), { posX, posY }, _imageOffsetX, _textOffsetX, _offsetY / 2, isSelected ); } } void ActionListPressRight( int & objectId ) override { // If this assertion blows up then you are setting different number of items. assert( objectId >= 0 && objectId < static_cast( _objectInfo.size() ) ); showPopupWindow( _objectInfo[objectId] ); } private: virtual void showPopupWindow( const Maps::ObjectInfo & info ) = 0; virtual std::string getObjectName( const Maps::ObjectInfo & info ) = 0; const std::vector & _objectInfo; const int32_t _imageOffsetX{ 0 }; const int32_t _textOffsetX{ 0 }; const int32_t _offsetY{ 0 }; }; class MonsterTypeSelection final : public ObjectTypeSelection { public: MonsterTypeSelection( const std::vector & objectInfo, const fheroes2::Size & size, std::string title ) : ObjectTypeSelection( objectInfo, size, std::move( title ), 45 / 2, 50, 43 ) { // Do nothing. } private: void showPopupWindow( const Maps::ObjectInfo & info ) override { const Monster monster( static_cast( info.metadata[0] ) ); if ( !monster.isValid() ) { fheroes2::showStandardTextMessage( monster.GetName(), "", Dialog::ZERO ); return; } Dialog::ArmyInfo( Troop( monster, 0 ), Dialog::ZERO ); } std::string getObjectName( const Maps::ObjectInfo & info ) override { return Monster( static_cast( info.metadata[0] ) ).GetName(); } }; class ArtifactTypeSelection final : public ObjectTypeSelection { public: ArtifactTypeSelection( const std::vector & objectInfo, const fheroes2::Size & size, std::string title ) : ObjectTypeSelection( objectInfo, size, std::move( title ), 24, 65, 40 ) { // Do nothing. } private: void showPopupWindow( const Maps::ObjectInfo & info ) override { switch ( info.objectType ) { case MP2::OBJ_ARTIFACT: fheroes2::ArtifactDialogElement( Artifact( static_cast( info.metadata[0] ) ) ).showPopup( Dialog::ZERO ); break; case MP2::OBJ_RANDOM_ARTIFACT: case MP2::OBJ_RANDOM_ARTIFACT_MINOR: case MP2::OBJ_RANDOM_ARTIFACT_MAJOR: case MP2::OBJ_RANDOM_ARTIFACT_TREASURE: case MP2::OBJ_RANDOM_ULTIMATE_ARTIFACT: fheroes2::showStandardTextMessage( MP2::StringObject( info.objectType ), "", Dialog::ZERO ); break; default: // Did you expand the list of artifacts? Add the corresponding logic! assert( 0 ); break; } } std::string getObjectName( const Maps::ObjectInfo & info ) override { switch ( info.objectType ) { case MP2::OBJ_ARTIFACT: return Artifact( static_cast( info.metadata[0] ) ).GetName(); case MP2::OBJ_RANDOM_ARTIFACT: case MP2::OBJ_RANDOM_ARTIFACT_MINOR: case MP2::OBJ_RANDOM_ARTIFACT_MAJOR: case MP2::OBJ_RANDOM_ARTIFACT_TREASURE: case MP2::OBJ_RANDOM_ULTIMATE_ARTIFACT: return MP2::StringObject( info.objectType ); default: // Did you expand the list of treasures? Add the corresponding logic! assert( 0 ); break; } return {}; } }; class TreasureTypeSelection final : public ObjectTypeSelection { public: TreasureTypeSelection( const std::vector & objectInfo, const fheroes2::Size & size, std::string title ) : ObjectTypeSelection( objectInfo, size, std::move( title ), 17, 60, 40 ) { // Do nothing. } private: void showPopupWindow( const Maps::ObjectInfo & info ) override { switch ( info.objectType ) { case MP2::OBJ_RESOURCE: fheroes2::showResourceMessage( fheroes2::Text{ getObjectName( info ), fheroes2::FontType::normalYellow() }, fheroes2::Text{ Resource::getDescription(), fheroes2::FontType::normalWhite() }, Dialog::ZERO, Funds{ static_cast( info.metadata[0] ), 0 } ); break; case MP2::OBJ_CAMPFIRE: case MP2::OBJ_GENIE_LAMP: case MP2::OBJ_RANDOM_RESOURCE: case MP2::OBJ_TREASURE_CHEST: fheroes2::showStandardTextMessage( getObjectName( info ), "", Dialog::ZERO ); break; default: // Did you expand the list of treasures? Add the corresponding logic! assert( 0 ); break; } } std::string getObjectName( const Maps::ObjectInfo & info ) override { switch ( info.objectType ) { case MP2::OBJ_RESOURCE: return Resource::String( static_cast( info.metadata[0] ) ); case MP2::OBJ_CAMPFIRE: case MP2::OBJ_GENIE_LAMP: case MP2::OBJ_RANDOM_RESOURCE: case MP2::OBJ_TREASURE_CHEST: return MP2::StringObject( info.objectType ); default: // Did you expand the list of treasures? Add the corresponding logic! assert( 0 ); break; } return {}; } }; class OceanObjectTypeSelection final : public ObjectTypeSelection { public: OceanObjectTypeSelection( const std::vector & objectInfo, const fheroes2::Size & size, std::string title ) : ObjectTypeSelection( objectInfo, size, std::move( title ), 3 * 32 / 2, 3 * 32 + 10, 2 * 32 + 24 ) { // Do nothing. } private: void showPopupWindow( const Maps::ObjectInfo & info ) override { fheroes2::showStandardTextMessage( getObjectName( info ), "", Dialog::ZERO ); } std::string getObjectName( const Maps::ObjectInfo & info ) override { if ( info.objectType == MP2::OBJ_NONE ) { return _( "Terrain object" ); } return MP2::StringObject( info.objectType ); } }; class GenericObjectTypeSelection final : public ObjectTypeSelection { public: GenericObjectTypeSelection( const std::vector & objectInfo, const fheroes2::Size & size, std::string title ) : ObjectTypeSelection( objectInfo, size, std::move( title ), 6 * 32 / 2, 6 * 32 + 10, 3 * 32 ) { // Do nothing. } private: void showPopupWindow( const Maps::ObjectInfo & info ) override { fheroes2::showStandardTextMessage( getObjectName( info ), "", Dialog::ZERO ); } std::string getObjectName( const Maps::ObjectInfo & info ) override { if ( info.objectType == MP2::OBJ_NONE ) { return _( "Terrain object" ); } // Barriers and Traveller's Tents use the same name while we need to show their color as well. if ( info.objectType == MP2::OBJ_BARRIER ) { std::string str = _( "%{color} Barrier" ); StringReplace( str, "%{color}", fheroes2::getBarrierColorName( static_cast( info.metadata[0] ) ) ); return str; } if ( info.objectType == MP2::OBJ_TRAVELLER_TENT ) { std::string str = _( "%{color} Tent" ); StringReplace( str, "%{color}", fheroes2::getTentColorName( static_cast( info.metadata[0] ) ) ); return str; } return MP2::StringObject( info.objectType ); } }; class PowerUpObjectTypeSelection final : public ObjectTypeSelection { public: PowerUpObjectTypeSelection( const std::vector & objectInfo, const fheroes2::Size & size, std::string title ) : ObjectTypeSelection( objectInfo, size, std::move( title ), 4 * 32 / 2, 4 * 32 + 10, 3 * 32 ) { // Do nothing. } private: void showPopupWindow( const Maps::ObjectInfo & info ) override { fheroes2::showStandardTextMessage( getObjectName( info ), "", Dialog::ZERO ); } std::string getObjectName( const Maps::ObjectInfo & info ) override { return MP2::StringObject( info.objectType ); } }; int selectObjectType( const int objectType, const size_t objectCount, ObjectTypeSelection & objectSelection ) { std::vector objects( objectCount, 0 ); std::iota( objects.begin(), objects.end(), 0 ); objectSelection.SetListContent( objects ); objectSelection.SetCurrent( std::max( objectType, 0 ) ); const int32_t result = objectSelection.selectItemsEventProcessing(); return result == Dialog::OK ? objectSelection.GetCurrent() : -1; } class MineTypeList final : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; using ListBox::ListBox; void ActionListPressRight( Maps::ObjectInfo & info ) override { if ( info.objectType == MP2::OBJ_MINE ) { // Mine description is done by its resource type stored in metadata. fheroes2::showStandardTextMessage( Maps::GetMineName( static_cast( info.metadata[0] ) ), "", Dialog::ZERO ); return; } fheroes2::showStandardTextMessage( MP2::StringObject( info.objectType ), "", Dialog::ZERO ); } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } bool isDoubleClicked() const { return _isDoubleClicked; } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } void RedrawItem( const Maps::ObjectInfo & info, int32_t dstx, int32_t dsty, bool current ) override { if ( _color < 0 ) { assert( 0 ); return; } const fheroes2::Sprite mineSprite( fheroes2::generateMapObjectImage( info ) ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( mineSprite, display, dstx + fheroes2::tileWidthPx * 5 + 5 - mineSprite.width(), dsty + 1 ); // Mine type selection mark background. const fheroes2::Sprite & markBackground = fheroes2::AGG::GetICN( Settings::Get().isEvilInterfaceEnabled() ? ICN::CELLWIN_EVIL : ICN::CELLWIN, 4 ); fheroes2::Blit( markBackground, display, dstx + 10, dsty + 24 ); if ( current ) { const fheroes2::Sprite & mark = fheroes2::AGG::GetICN( ICN::CELLWIN, 5 ); fheroes2::Blit( mark, display, dstx + 13, dsty + 27 ); } } void RedrawBackground( const fheroes2::Point & /* unused */ ) override { _listBackground->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListDoubleClick( Maps::ObjectInfo & /*unused*/ ) override { _isDoubleClicked = true; } void ActionListSingleClick( Maps::ObjectInfo & /*unused*/ ) override { // Do nothing. } void setOwnerColor( const int32_t color ) { _color = color; } private: bool _isDoubleClicked{ false }; int32_t _color{ 0 }; std::unique_ptr _listBackground; }; } int32_t Dialog::selectKingdomCastle( const Kingdom & kingdom, const bool notOccupiedByHero, std::string title, std::string description /* = {} */, int32_t castlePositionIndex /* = -1 */ ) { std::vector castles; const VecCastles & kingdomCastles = kingdom.GetCastles(); castles.reserve( kingdomCastles.size() ); for ( const Castle * castle : kingdomCastles ) { assert( castle != nullptr ); if ( notOccupiedByHero && castle->GetHero() ) { continue; } castles.push_back( castle->GetIndex() ); } const int32_t maxHeight = std::min( 100 + SelectKingdomCastle::itemsOffsetY * 12, fheroes2::Display::instance().height() - dialogHeightDeduction ); const int32_t itemsHeight = std::max( 100 + SelectKingdomCastle::itemsOffsetY * static_cast( castles.size() ), 100 + SelectKingdomCastle::itemsOffsetY * 5 ); const int32_t totalHeight = std::min( itemsHeight, maxHeight ); SelectKingdomCastle listbox( { 350, totalHeight }, std::move( title ), std::move( description ) ); listbox.SetListContent( castles ); if ( castlePositionIndex != -1 ) { listbox.SetCurrent( castlePositionIndex ); } const int32_t result = listbox.selectItemsEventProcessing(); return ( result == Dialog::OK ) ? listbox.GetCurrent() : -1; } namespace Dialog { ItemSelectionWindow::ItemSelectionWindow( const fheroes2::Size & dialogSize, std::string title, std::string description ) { assert( !title.empty() ); fheroes2::Display & display = fheroes2::Display::instance(); _window = std::make_unique( dialogSize.width, dialogSize.height, true, display ); const fheroes2::Rect & area = _window->activeArea(); int32_t listOffsetY = 0; fheroes2::Text text( std::move( title ), fheroes2::FontType::normalYellow() ); text.draw( area.x + ( area.width - text.width() ) / 2, area.y + 10, display ); // The additional text under the title. if ( !description.empty() ) { text.set( std::move( description ), fheroes2::FontType::normalWhite() ); text.draw( area.x + ( area.width - text.width() ) / 2, area.y + 30, display ); listOffsetY = text.height() + 3; } const fheroes2::Rect listRoi( area.x + 10, area.y + 30 + listOffsetY, area.width - 40, area.height - 70 - listOffsetY ); _window->applyTextBackgroundShading( listRoi ); _backgroundRestorer = std::make_unique( display, listRoi.x, listRoi.y, listRoi.width, listRoi.height ); SetAreaItems( { listRoi.x + 5, listRoi.y + 5, listRoi.width - 10, listRoi.height - 10 } ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int32_t scrollbarOffsetX = area.x + area.width - 25; _window->renderScrollbarBackground( { scrollbarOffsetX, listRoi.y, listRoi.width, listRoi.height }, isEvilInterface ); const int32_t topPartHeight = 19; const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX + 1, listRoi.y + 1 } ); SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX + 1, listRoi.y + listRoi.height - 15 } ); setScrollBarArea( { scrollbarOffsetX + 3, listRoi.y + topPartHeight, 10, listRoi.height - 2 * topPartHeight } ); setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); // Render dialog buttons. _window->renderOkayCancelButtons( _buttonOk, _buttonCancel, isEvilInterface ); } void ItemSelectionWindow::updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } // An image with text should have offset of 10 pixels from all left and right edges. void ItemSelectionWindow::renderItem( const fheroes2::Sprite & itemSprite, std::string itemText, const fheroes2::Point & destination, const int32_t middleImageOffsetX, const int32_t textOffsetX, const int32_t itemOffsetY, const bool current ) const { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( itemSprite, display, destination.x + middleImageOffsetX - ( itemSprite.width() / 2 ), destination.y + itemOffsetY - ( itemSprite.height() / 2 ) ); fheroes2::Text text( std::move( itemText ), current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ); text.fitToOneRow( _window->activeArea().width - textOffsetX - 55 ); text.draw( destination.x + textOffsetX, destination.y + itemOffsetY - ( text.height() / 2 ) + 2, display ); } int32_t ItemSelectionWindow::selectItemsEventProcessing() { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::Rect & roi = _window->activeArea(); updateScrollBarImage(); Redraw(); display.render( _window->totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( !_isDoubleClicked && le.HandleEvents() ) { _buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( _buttonOk.area() ) ); _buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( _buttonCancel.area() ) ); if ( le.MouseClickLeft( _buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) { return Dialog::OK; } if ( le.MouseClickLeft( _buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return Dialog::CANCEL; } if ( le.isMouseRightButtonPressedInArea( _buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Accept the choice made." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } QueueEventProcessing(); if ( !IsNeedRedraw() ) { continue; } Redraw(); display.render( roi ); } if ( _isDoubleClicked ) { return Dialog::OK; } return Dialog::ZERO; } fheroes2::Rect ItemSelectionWindow::getBackgroundArea() const { assert( _window ); return _window->totalArea(); } } Skill::Secondary Dialog::selectSecondarySkill( const Heroes & hero, const int skillId /* = Skill::Secondary::UNKNOWN */ ) { std::vector skills; skills.reserve( static_cast( Skill::numOfSecondarySkills ) * 3 ); for ( int i = 0; i < Skill::numOfSecondarySkills * 3; ++i ) { if ( !hero.HasSecondarySkill( SelectEnumSecSkill::getSkillFromListIndex( i ) ) ) { skills.push_back( i ); } } SelectEnumSecSkill listbox( { 350, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Skill:" ) ); listbox.SetListContent( skills ); if ( skillId != Skill::Secondary::UNKNOWN ) { listbox.SetCurrent( skillId ); } const int32_t result = listbox.selectItemsEventProcessing(); if ( result == Dialog::OK ) { const int skillIndex = listbox.GetCurrent(); return { SelectEnumSecSkill::getSkillFromListIndex( skillIndex ), SelectEnumSecSkill::getLevelFromListIndex( skillIndex ) }; } return {}; } Spell Dialog::selectSpell( const int spellId, const bool includeRandomSpells ) { std::vector spells = Spell::getAllSpellIdsSuitableForSpellBook(); if ( includeRandomSpells ) { // We add random spell items to the end of the list. for ( int randomSpellId = Spell::RANDOM; randomSpellId <= Spell::RANDOM5; ++randomSpellId ) { spells.push_back( randomSpellId ); } } SelectEnumSpell listbox( { 340, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Spell:" ) ); listbox.SetListContent( spells ); if ( spellId != Spell::NONE ) { listbox.SetCurrent( spellId ); } const int32_t result = listbox.selectItemsEventProcessing(); return ( result == Dialog::OK ) ? Spell( listbox.GetCurrent() ) : Spell( Spell::NONE ); } Artifact Dialog::selectArtifact( const int artifactId, const bool isForVictoryConditions ) { std::vector artifacts; artifacts.reserve( Artifact::ARTIFACT_COUNT - 2 ); const GameVersion version = Settings::Get().getCurrentMapInfo().version; const bool isPriceofLoyaltyArtifactAllowed = ( version == GameVersion::PRICE_OF_LOYALTY || version == GameVersion::RESURRECTION ); if ( !isForVictoryConditions ) { // We show the Magic Book at the first place. artifacts.emplace_back( Artifact::MAGIC_BOOK ); } else { // We show the Ultimate Artifact at the first place. artifacts.emplace_back( Artifact::EDITOR_ANY_ULTIMATE_ARTIFACT ); } for ( int id = Artifact::UNKNOWN + 1; id < Artifact::ARTIFACT_COUNT; ++id ) { if ( id == Artifact::MAGIC_BOOK ) { continue; } if ( isForVictoryConditions && id == Artifact::SPELL_SCROLL ) { continue; } if ( !Artifact( id ).isValid() ) { continue; } if ( !isPriceofLoyaltyArtifactAllowed && fheroes2::isPriceOfLoyaltyArtifact( id ) ) { continue; } artifacts.emplace_back( id ); } SelectEnumArtifact listbox( { 370, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Artifact:" ) ); listbox.SetListContent( artifacts ); if ( artifactId != Artifact::UNKNOWN ) { listbox.SetCurrent( artifactId ); } const int32_t result = listbox.selectItemsEventProcessing(); return ( result == Dialog::OK ) ? Artifact( listbox.GetCurrent() ) : Artifact( Artifact::UNKNOWN ); } Monster Dialog::selectMonster( const int monsterId ) { std::vector monsters( Monster::MONSTER_COUNT - 1, Monster::UNKNOWN ); // Skip Monster::UNKNOWN and start from the next one. std::iota( monsters.begin(), monsters.end(), Monster::UNKNOWN + 1 ); monsters.erase( std::remove_if( monsters.begin(), monsters.end(), []( const int id ) { return Monster( id ).isRandomMonster(); } ), monsters.end() ); SelectEnumMonster listbox( { 320, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Monster:" ) ); listbox.SetListContent( monsters ); if ( monsterId != Monster::UNKNOWN ) { listbox.SetCurrent( monsterId ); } const int32_t result = listbox.selectItemsEventProcessing(); return ( result == Dialog::OK ) ? Monster( listbox.GetCurrent() ) : Monster( Monster::UNKNOWN ); } int Dialog::selectHeroes( const int heroId /* = Heroes::UNKNOWN */ ) { const GameVersion version = Settings::Get().getCurrentMapInfo().version; const bool isPoLHeroesAllowed = ( version == GameVersion::PRICE_OF_LOYALTY || version == GameVersion::RESURRECTION ); std::vector heroes( static_cast( isPoLHeroesAllowed ? Heroes::JARKONAS : Heroes::BRAX ), Heroes::UNKNOWN ); std::iota( heroes.begin(), heroes.end(), Heroes::UNKNOWN + 1 ); SelectEnumHeroes listbox( { 300, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Hero:" ) ); listbox.SetListContent( heroes ); if ( heroId != Heroes::UNKNOWN ) { listbox.SetCurrent( heroId ); } const int32_t result = listbox.selectItemsEventProcessing(); return ( result == Dialog::OK ) ? listbox.GetCurrent() : Heroes::UNKNOWN; } int Dialog::selectHeroType( const int heroType ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 520, 250, true, display ); const fheroes2::Rect & area = background.activeArea(); fheroes2::Text text( _( "Select Hero:" ), fheroes2::FontType::normalYellow() ); text.draw( area.x + ( area.width - text.width() ) / 2, area.y + 10, display ); // Render color and race selection sprites. const int32_t stepX = 70; const int32_t raceOffsetY = 80; fheroes2::Point pos( area.x + 20, area.y + 30 ); const fheroes2::Sprite & colorSpriteBorderSelected = fheroes2::AGG::GetICN( ICN::BRCREST, 6 ); const fheroes2::Sprite & raceShadow = fheroes2::AGG::GetICN( ICN::NGEXTRA, 61 ); fheroes2::Sprite colorSpriteBorder( colorSpriteBorderSelected ); const std::vector darkGrayPalette = PAL::CombinePalettes( PAL::GetPalette( PAL::PaletteType::GRAY ), PAL::GetPalette( PAL::PaletteType::DARKENING ) ); fheroes2::ApplyPalette( colorSpriteBorder, darkGrayPalette ); // Make race selection borders. const fheroes2::Sprite & randomRaceSprite = fheroes2::AGG::GetICN( ICN::NGEXTRA, 58 ); const int32_t raceBorderWidth = randomRaceSprite.width(); const int32_t raceBorderHeight = randomRaceSprite.height(); fheroes2::Image raceSpriteBorder( raceBorderWidth, raceBorderHeight ); raceSpriteBorder.reset(); const int32_t raceImageWidth = raceBorderWidth - 8; const int32_t raceImageHeight = raceBorderHeight - 8; fheroes2::Copy( randomRaceSprite, 0, 0, raceSpriteBorder, 0, 0, raceBorderWidth, 4 ); fheroes2::Copy( randomRaceSprite, 0, 4, raceSpriteBorder, 0, 4, 4, raceImageHeight ); int32_t imageCopyOffset = raceBorderWidth - 4; fheroes2::Copy( randomRaceSprite, imageCopyOffset, 4, raceSpriteBorder, imageCopyOffset, 4, 4, raceImageHeight ); imageCopyOffset = raceBorderHeight - 4; fheroes2::Copy( randomRaceSprite, 0, imageCopyOffset, raceSpriteBorder, 0, imageCopyOffset, raceBorderWidth, 4 ); fheroes2::Image raceSpriteBorderSelected( raceSpriteBorder ); fheroes2::ApplyPalette( raceSpriteBorder, darkGrayPalette ); fheroes2::ApplyPalette( raceSpriteBorderSelected, PAL::GetPalette( PAL::PaletteType::RED ) ); std::array colorRect; std::array raceRect; // Random race. raceRect.back() = { pos.x - 2, pos.y + raceOffsetY, raceBorderWidth, raceBorderHeight }; fheroes2::Copy( randomRaceSprite, 4, 4, display, raceRect.back().x + 4, raceRect.back().y + 4, raceImageWidth, raceImageHeight ); fheroes2::Blit( raceShadow, display, pos.x - 5, pos.y + raceOffsetY + 2 ); text.set( _( "race|Random" ), fheroes2::FontType::smallWhite() ); text.draw( raceRect.back().x, raceRect.back().y + raceRect.back().height + 4, raceBorderWidth, display ); pos.x += stepX; for ( uint32_t i = 0; i < 6; ++i ) { const fheroes2::Sprite & colorSprite = fheroes2::AGG::GetICN( ICN::BRCREST, i ); fheroes2::addGradientShadow( colorSpriteBorder, display, { pos.x - stepX / 2, pos.y }, { -5, 5 } ); colorRect[i] = { pos.x - stepX / 2, pos.y, colorSpriteBorder.width(), colorSpriteBorder.height() }; fheroes2::Copy( colorSprite, 0, 0, display, colorRect[i].x + 4, colorRect[i].y + 4, colorSprite.width(), colorSprite.height() ); text.set( Color::String( Color::IndexToColor( static_cast( i ) ) ), fheroes2::FontType::smallWhite() ); text.draw( colorRect[i].x + ( colorRect[i].width - text.width() ) / 2, colorRect[i].y + colorRect[i].height + 4, display ); const fheroes2::Sprite & raceSprite = fheroes2::AGG::GetICN( ICN::NGEXTRA, 51U + i ); raceRect[i] = { pos.x - 2, pos.y + raceOffsetY, raceBorderWidth, raceBorderHeight }; fheroes2::Copy( raceSprite, 4, 4, display, raceRect[i].x + 4, raceRect[i].y + 4, raceImageWidth, raceImageHeight ); fheroes2::Blit( raceShadow, display, pos.x - 5, pos.y + raceOffsetY + 2 ); text.set( Race::DoubleLinedString( Race::IndexToRace( static_cast( i ) ) ), fheroes2::FontType::smallWhite() ); text.draw( raceRect[i].x, raceRect[i].y + raceRect[i].height + 4, raceBorderWidth, display ); pos.x += stepX; } pos.x = area.x + area.width / 2; pos.y += 175; const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); // Render dialog buttons. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::KINGDOM_HEROES ); fheroes2::Rect heroRoi; { // We are doing this is a code block to reduce variable scope. // This calculation is done with an assumption that all hero images are the same. const fheroes2::Sprite heroImage = fheroes2::generateMapObjectImage( objectInfo[0] ); heroRoi = { heroImage.x(), heroImage.y(), heroImage.width(), heroImage.height() }; } fheroes2::ImageRestorer heroBackground( display, pos.x + heroRoi.x, pos.y + heroRoi.y, heroRoi.width, heroRoi.height ); LocalEvent & le = LocalEvent::Get(); bool needRedraw = true; int heroRace = 0; int heroColor = 0; if ( heroType > -1 ) { heroRace = heroType % 7; heroColor = heroType / 7; } while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) { return heroColor * 7 + heroRace; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { break; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to start placing the selected hero." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( heroBackground.rect() ) ) { std::string name( _( "%{color} %{race}" ) ); StringReplace( name, "%{color}", Color::String( Color::IndexToColor( heroColor ) ) ); StringReplace( name, "%{race}", ( heroRace < 6 ) ? Race::String( Race::IndexToRace( heroRace ) ) : _( "race|Random" ) ); fheroes2::showStandardTextMessage( _( "You will place" ), std::move( name ), Dialog::ZERO ); } else { for ( size_t i = 0; i < 7; ++i ) { if ( le.MouseClickLeft( raceRect[i] ) ) { heroRace = static_cast( i ); needRedraw = true; break; } if ( le.isMouseRightButtonPressedInArea( raceRect[i] ) ) { fheroes2::showStandardTextMessage( Race::String( Race::IndexToRace( static_cast( i == 6 ? 7 : i ) ) ), _( "Click to select this class." ), Dialog::ZERO ); } } for ( size_t i = 0; i < 6; ++i ) { if ( le.MouseClickLeft( colorRect[i] ) ) { heroColor = static_cast( i ); needRedraw = true; break; } if ( le.isMouseRightButtonPressedInArea( colorRect[i] ) ) { fheroes2::showStandardTextMessage( Color::String( Color::IndexToColor( static_cast( i ) ) ), _( "Click to select this color." ), Dialog::ZERO ); } } } if ( !needRedraw ) { continue; } heroBackground.restore(); // Update hero image. const fheroes2::Sprite heroImage = fheroes2::generateMapObjectImage( objectInfo[heroColor * 7 + heroRace] ); fheroes2::Blit( heroImage, display, pos.x + heroImage.x(), pos.y + heroImage.y() ); // Update color and race borders. for ( int i = 0; i < 6; ++i ) { fheroes2::Blit( ( i == heroColor ) ? colorSpriteBorderSelected : colorSpriteBorder, display, colorRect[i].x, colorRect[i].y ); } for ( int i = 0; i < 7; ++i ) { fheroes2::Blit( ( i == heroRace ) ? raceSpriteBorderSelected : raceSpriteBorder, display, raceRect[i].x, raceRect[i].y ); } display.render( background.totalArea() ); needRedraw = false; } return Heroes::UNKNOWN; } int Dialog::selectMonsterType( const int monsterType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::MONSTERS ); MonsterTypeSelection listbox( objectInfo, { 350, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Monster:" ) ); return selectObjectType( monsterType, objectInfo.size(), listbox ); } int Dialog::selectArtifactType( const int artifactType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_ARTIFACTS ); ArtifactTypeSelection listbox( objectInfo, { 350, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Artifact:" ) ); return selectObjectType( artifactType, objectInfo.size(), listbox ); } int Dialog::selectTreasureType( const int resourceType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_TREASURES ); TreasureTypeSelection listbox( objectInfo, { 350, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Treasure:" ) ); return selectObjectType( resourceType, objectInfo.size(), listbox ); } int Dialog::selectOceanObjectType( const int objectType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_WATER ); OceanObjectTypeSelection listbox( objectInfo, { 350, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Ocean Object:" ) ); return selectObjectType( objectType, objectInfo.size(), listbox ); } int Dialog::selectLandscapeOceanObjectType( const int objectType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::LANDSCAPE_WATER ); OceanObjectTypeSelection listbox( objectInfo, { 350, fheroes2::Display::instance().height() - dialogHeightDeduction }, _( "Select Ocean Object:" ) ); return selectObjectType( objectType, objectInfo.size(), listbox ); } void Dialog::selectTownType( int & type, int & color ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 520, 370, true, display ); const fheroes2::Rect & area = background.activeArea(); fheroes2::Text text( _( "Castle/town placing" ), fheroes2::FontType::normalYellow() ); text.draw( area.x + ( area.width - text.width() ) / 2, area.y + 10, display ); // Render color and race selection sprites. const int32_t stepX = 70; const int32_t raceOffsetY = 80; fheroes2::Point pos( area.x + 20, area.y + 30 ); const fheroes2::Sprite & colorSpriteBorderSelected = fheroes2::AGG::GetICN( ICN::BRCREST, 6 ); const fheroes2::Sprite & raceShadow = fheroes2::AGG::GetICN( ICN::NGEXTRA, 61 ); fheroes2::Sprite colorSpriteBorder( colorSpriteBorderSelected ); const std::vector darkGrayPalette = PAL::CombinePalettes( PAL::GetPalette( PAL::PaletteType::GRAY ), PAL::GetPalette( PAL::PaletteType::DARKENING ) ); fheroes2::ApplyPalette( colorSpriteBorder, darkGrayPalette ); // Make race selection borders. const fheroes2::Sprite & randomRaceSprite = fheroes2::AGG::GetICN( ICN::NGEXTRA, 58 ); const int32_t raceBorderWidth = randomRaceSprite.width(); const int32_t raceBorderHeight = randomRaceSprite.height(); fheroes2::Image raceSpriteBorder( raceBorderWidth, raceBorderHeight ); raceSpriteBorder.reset(); const int32_t raceImageWidth = raceBorderWidth - 8; const int32_t raceImageHeight = raceBorderHeight - 8; fheroes2::Copy( randomRaceSprite, 0, 0, raceSpriteBorder, 0, 0, raceBorderWidth, 4 ); fheroes2::Copy( randomRaceSprite, 0, 4, raceSpriteBorder, 0, 4, 4, raceImageHeight ); int32_t imageCopyOffset = raceBorderWidth - 4; fheroes2::Copy( randomRaceSprite, imageCopyOffset, 4, raceSpriteBorder, imageCopyOffset, 4, 4, raceImageHeight ); imageCopyOffset = raceBorderHeight - 4; fheroes2::Copy( randomRaceSprite, 0, imageCopyOffset, raceSpriteBorder, 0, imageCopyOffset, raceBorderWidth, 4 ); fheroes2::Image raceSpriteBorderSelected( raceSpriteBorder ); fheroes2::ApplyPalette( raceSpriteBorder, darkGrayPalette ); fheroes2::ApplyPalette( raceSpriteBorderSelected, PAL::GetPalette( PAL::PaletteType::RED ) ); std::array colorRect; std::array raceRect; // Neutral color. fheroes2::addGradientShadow( colorSpriteBorder, display, pos, { -5, 5 } ); const fheroes2::Sprite & neutralColorSprite = fheroes2::AGG::GetICN( ICN::BRCREST, 7 ); colorRect.back() = { pos.x, pos.y, colorSpriteBorder.width(), colorSpriteBorder.height() }; fheroes2::Copy( neutralColorSprite, 0, 0, display, colorRect.back().x + 4, colorRect.back().y + 4, neutralColorSprite.width(), neutralColorSprite.height() ); text.set( _( "doubleLinedRace|Neutral" ), fheroes2::FontType::smallWhite() ); text.draw( colorRect.back().x + ( colorRect.back().width - text.width() ) / 2, colorRect.back().y + colorRect.back().height + 4, display ); // Random race. raceRect.back() = { pos.x - 2, pos.y + raceOffsetY, raceBorderWidth, raceBorderHeight }; fheroes2::Copy( randomRaceSprite, 4, 4, display, raceRect.back().x + 4, raceRect.back().y + 4, raceImageWidth, raceImageHeight ); fheroes2::Blit( raceShadow, display, pos.x - 5, pos.y + raceOffsetY + 2 ); text.set( _( "race|Random" ), fheroes2::FontType::smallWhite() ); text.draw( raceRect.back().x, raceRect.back().y + raceRect.back().height + 4, raceBorderWidth, display ); pos.x += stepX; for ( uint32_t i = 0; i < 6; ++i ) { const fheroes2::Sprite & colorSprite = fheroes2::AGG::GetICN( ICN::BRCREST, i ); fheroes2::addGradientShadow( colorSpriteBorder, display, pos, { -5, 5 } ); colorRect[i] = { pos.x, pos.y, colorSpriteBorder.width(), colorSpriteBorder.height() }; fheroes2::Copy( colorSprite, 0, 0, display, colorRect[i].x + 4, colorRect[i].y + 4, colorSprite.width(), colorSprite.height() ); text.set( Color::String( Color::IndexToColor( static_cast( i ) ) ), fheroes2::FontType::smallWhite() ); text.draw( colorRect[i].x + ( colorRect[i].width - text.width() ) / 2, colorRect[i].y + colorRect[i].height + 4, display ); const fheroes2::Sprite & raceSprite = fheroes2::AGG::GetICN( ICN::NGEXTRA, 51U + i ); raceRect[i] = { pos.x - 2, pos.y + raceOffsetY, raceBorderWidth, raceBorderHeight }; fheroes2::Copy( raceSprite, 4, 4, display, raceRect[i].x + 4, raceRect[i].y + 4, raceImageWidth, raceImageHeight ); fheroes2::Blit( raceShadow, display, pos.x - 5, pos.y + raceOffsetY + 2 ); text.set( Race::DoubleLinedString( Race::IndexToRace( static_cast( i ) ) ), fheroes2::FontType::smallWhite() ); text.draw( raceRect[i].x, raceRect[i].y + raceRect[i].height + 4, raceBorderWidth, display ); pos.x += stepX; } pos.x = area.x + area.width / 2; pos.y += 260; const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); // Render dialog buttons. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); const int32_t townButtonIcnId = isEvilInterface ? ICN::BUTTON_TOWN_EVIL : ICN::BUTTON_TOWN_GOOD; const fheroes2::Sprite & townButtonImage = fheroes2::AGG::GetICN( townButtonIcnId, 0 ); fheroes2::Button buttonTown{ 0, 0, townButtonIcnId, 0, 1 }; fheroes2::Button buttonCastle{ 0, 0, isEvilInterface ? ICN::BUTTON_CASTLE_EVIL : ICN::BUTTON_CASTLE_GOOD, 0, 1 }; const fheroes2::Point buttonOffset{ area.x + ( area.width - townButtonImage.width() ) / 2, area.y + area.height - townButtonImage.height() - 7 }; buttonTown.setPosition( buttonOffset.x, buttonOffset.y ); buttonCastle.setPosition( buttonOffset.x, buttonOffset.y ); fheroes2::addGradientShadow( townButtonImage, display, buttonOffset, { -5, 5 } ); const fheroes2::Rect castleRoi{ pos.x - 2 * fheroes2::tileWidthPx - fheroes2::tileWidthPx / 2, pos.y - 4 * fheroes2::tileWidthPx + fheroes2::tileWidthPx / 2, 5 * fheroes2::tileWidthPx, 5 * fheroes2::tileWidthPx }; fheroes2::ImageRestorer castleBackground( display, pos.x - 5 * fheroes2::tileWidthPx, pos.y - 4 * fheroes2::tileWidthPx + fheroes2::tileWidthPx / 2, 8 * fheroes2::tileWidthPx, 5 * fheroes2::tileWidthPx ); LocalEvent & le = LocalEvent::Get(); bool needRedraw = true; bool isCastle = false; int townRace = 6; int townColor = 6; const int basementGround = isEvilInterface ? Maps::Ground::LAVA : Maps::Ground::DIRT; if ( type > -1 && color > -1 ) { isCastle = ( type % 2 ) == 0; townRace = type / 2; townColor = color; } if ( isCastle ) { buttonCastle.disable(); buttonTown.enable(); buttonTown.draw(); } else { buttonCastle.enable(); buttonTown.disable(); buttonCastle.draw(); } while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( isCastle ) { if ( le.isMouseLeftButtonPressedInArea( buttonTown.area() ) ) { buttonTown.drawOnPress(); } else if ( le.MouseClickLeft( buttonTown.area() ) ) { buttonTown.drawOnPress(); isCastle = false; needRedraw = true; } else { buttonTown.drawOnRelease(); } } else { if ( le.isMouseLeftButtonPressedInArea( buttonCastle.area() ) ) { buttonCastle.drawOnPress(); } else if ( le.MouseClickLeft( buttonCastle.area() ) ) { buttonCastle.drawOnPress(); isCastle = true; needRedraw = true; } else { buttonCastle.drawOnRelease(); } } if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) { type = getPackedTownType( townRace, isCastle ); color = townColor; return; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to start placing the selected castle/town." ), Dialog::ZERO ); } else if ( buttonTown.isEnabled() && le.isMouseRightButtonPressedInArea( buttonTown.area() ) ) { fheroes2::showStandardTextMessage( _( "Town" ), _( "Click to select town placing." ), Dialog::ZERO ); } else if ( buttonCastle.isEnabled() && le.isMouseRightButtonPressedInArea( buttonCastle.area() ) ) { fheroes2::showStandardTextMessage( _( "Castle" ), _( "Click to select castle placing." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( castleRoi ) ) { std::string name( _( "%{color} %{race} %{townOrCastle}" ) ); StringReplace( name, "%{color}", ( townColor < 6 ) ? Color::String( Color::IndexToColor( townColor ) ) : _( "race|Neutral" ) ); StringReplace( name, "%{race}", ( townRace < 6 ) ? Race::String( Race::IndexToRace( townRace ) ) : _( "race|Random" ) ); StringReplace( name, "%{townOrCastle}", isCastle ? _( "Castle" ) : _( "Town" ) ); fheroes2::showStandardTextMessage( _( "You will place" ), std::move( name ), Dialog::ZERO ); } else { for ( size_t i = 0; i < 7; ++i ) { if ( le.MouseClickLeft( raceRect[i] ) ) { townRace = static_cast( i ); needRedraw = true; break; } if ( le.MouseClickLeft( colorRect[i] ) ) { townColor = static_cast( i ); needRedraw = true; break; } if ( le.isMouseRightButtonPressedInArea( raceRect[i] ) ) { fheroes2::showStandardTextMessage( Race::String( Race::IndexToRace( static_cast( i == 6 ? 7 : i ) ) ), _( "Click to select this class." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( colorRect[i] ) ) { fheroes2::showStandardTextMessage( i == 6 ? _( "race|Neutral" ) : Color::String( Color::IndexToColor( static_cast( i ) ) ), _( "Click to select this color." ), Dialog::ZERO ); } } } if ( !needRedraw ) { continue; } castleBackground.restore(); if ( isCastle ) { buttonCastle.disable(); buttonTown.enable(); buttonTown.draw(); } else { buttonCastle.enable(); buttonTown.disable(); buttonCastle.draw(); } // Update town image. const fheroes2::Sprite townImage = fheroes2::generateTownObjectImage( getPackedTownType( townRace, isCastle ), townColor, basementGround ); fheroes2::Blit( townImage, display, pos.x + townImage.x(), pos.y + townImage.y() ); // Update color and race borders. for ( int i = 0; i < 7; ++i ) { fheroes2::Blit( ( i == townColor ) ? colorSpriteBorderSelected : colorSpriteBorder, display, colorRect[i].x, colorRect[i].y ); fheroes2::Blit( ( i == townRace ) ? raceSpriteBorderSelected : raceSpriteBorder, display, raceRect[i].x, raceRect[i].y ); } display.render( background.totalArea() ); needRedraw = false; } } int Dialog::selectDwellingType( const int dwellingType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_DWELLINGS ); GenericObjectTypeSelection listbox( objectInfo, { 480, fheroes2::Display::instance().height() - 180 }, _( "Select Dwelling:" ) ); return selectObjectType( dwellingType, objectInfo.size(), listbox ); } int Dialog::selectLandscapeMiscellaneousObjectType( const int objectType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS ); GenericObjectTypeSelection listbox( objectInfo, { 420, fheroes2::Display::instance().height() - 180 }, _( "Select Landscape Object:" ) ); return selectObjectType( objectType, objectInfo.size(), listbox ); } void Dialog::selectMineType( int32_t & type, int32_t & color ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 380, 395, true, display ); const fheroes2::Rect & area = background.activeArea(); fheroes2::Text text( _( "Mine placing" ), fheroes2::FontType::normalYellow() ); int32_t offsetY = area.y + 10; text.draw( area.x + ( area.width - text.width() ) / 2, offsetY, display ); // There are 7 resource types (WOOD, MERCURY, ORE, SULFUR, CRYSTAL, GEMS, GOLD) and abandoned mine. const uint32_t resourceCount{ 8 }; const int32_t stepY = 35; offsetY += 50; const fheroes2::Rect resourceSelectRoi( area.x + 22, offsetY - 5, 100, stepY * resourceCount + 10 ); background.applyTextBackgroundShading( resourceSelectRoi ); text.set( _( "Resource\ntype:" ), fheroes2::FontType::smallWhite() ); text.draw( resourceSelectRoi.x, resourceSelectRoi.y - text.height( resourceSelectRoi.width ), resourceSelectRoi.width, display ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); std::array resourceRoi; // Resource type selection mark background. const fheroes2::Sprite & markBackground = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CELLWIN_EVIL : ICN::CELLWIN, 4 ); // Resource icons. const int32_t iconOffsetX = 35; const std::vector & resourceInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_TREASURES ); assert( resourceInfo.size() > resourceCount - 1 ); for ( uint32_t i = 0; i < resourceCount - 1; ++i ) { const fheroes2::Sprite & resourceImage = fheroes2::generateMapObjectImage( resourceInfo[i] ); const fheroes2::Point imagePosition( area.x + iconOffsetX + ( resourceSelectRoi.width - fheroes2::tileWidthPx * 3 ) / 2, offsetY + ( stepY - fheroes2::tileWidthPx ) / 2 ); resourceRoi[i] = { resourceSelectRoi.x + 5, imagePosition.y, resourceSelectRoi.width - 10, fheroes2::tileWidthPx }; fheroes2::Blit( resourceImage, display, imagePosition.x, imagePosition.y - 4 ); fheroes2::Blit( markBackground, display, resourceRoi[i].x + 2, resourceRoi[i].y + ( resourceRoi[i].height - markBackground.height() ) / 2 ); offsetY += stepY; } // Render ghosts to select Abandoned mine type. const fheroes2::Sprite & ghostImage = fheroes2::AGG::GetICN( ICN::MONS32, 59 ); const int32_t ghostsOnIcon = 4; const int32_t ghostsIconOverlap = 12; const int32_t ghostsStepX = ghostImage.width() - ghostsIconOverlap; const int32_t ghostsIconWight = ghostsOnIcon * ghostsStepX + ghostsIconOverlap; const int32_t ghostsIconHeight = ghostImage.height(); resourceRoi[7] = { resourceSelectRoi.x + 5, offsetY + ( stepY - ghostsIconHeight ) / 2, resourceSelectRoi.width - 10, ghostsIconHeight }; for ( int32_t i = 0; i < ghostsOnIcon; ++i ) { fheroes2::Blit( ghostImage, display, area.x + iconOffsetX + ( resourceSelectRoi.width - ghostsIconWight ) / 2 + ghostsStepX * i, resourceRoi[7].y, i < 2 ); } fheroes2::Blit( markBackground, display, resourceRoi[7].x + 2, resourceRoi[7].y + ( resourceRoi[7].height - markBackground.height() ) / 2 ); // Resource type selection mark. const fheroes2::Sprite & mark = fheroes2::AGG::GetICN( ICN::CELLWIN, 5 ); uint32_t selectedResourceType = 0; const std::vector & allObjectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_MINES ); if ( type >= 0 ) { assert( static_cast( type ) < allObjectInfo.size() ); if ( allObjectInfo[type].objectType == MP2::OBJ_ABANDONED_MINE ) { selectedResourceType = 7; } else { switch ( allObjectInfo[type].metadata[0] ) { case Resource::ORE: selectedResourceType = 2; break; case Resource::SULFUR: selectedResourceType = 3; break; case Resource::CRYSTAL: selectedResourceType = 4; break; case Resource::GEMS: selectedResourceType = 5; break; case Resource::GOLD: selectedResourceType = 6; break; case Resource::WOOD: selectedResourceType = 0; break; case Resource::MERCURY: selectedResourceType = 1; break; default: // Have you added a new resource type for mines? assert( 0 ); } } } fheroes2::MovableSprite resourceTypeSelection( mark ); auto redrawResourceSelection = [&resourceTypeSelection, &mark]( const fheroes2::Rect & pos ) { resourceTypeSelection.setPosition( pos.x + 5, pos.y + ( pos.height - mark.height() ) / 2 ); resourceTypeSelection.redraw(); }; redrawResourceSelection( resourceRoi[selectedResourceType] ); // Mine appearance type selection list. MineTypeList listbox( area.getPosition() ); const fheroes2::Rect listRoi( area.x + area.width - 5 * fheroes2::tileWidthPx - 75, resourceSelectRoi.y, 5 * fheroes2::tileWidthPx + 20, resourceSelectRoi.height ); background.applyTextBackgroundShading( listRoi ); // Initialize list background restorer to use it in list method 'listbox.RedrawBackground()'. listbox.initListBackgroundRestorer( listRoi ); listbox.SetAreaItems( { listRoi.x, listRoi.y + 3, listRoi.width, listRoi.height - 3 } ); int32_t scrollbarOffsetX = listRoi.x + listRoi.width + 15; background.renderScrollbarBackground( { scrollbarOffsetX, listRoi.y, listRoi.width, listRoi.height }, isEvilInterface ); const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; const int32_t topPartHeight = 19; ++scrollbarOffsetX; listbox.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, listRoi.y + 1 } ); listbox.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, listRoi.y + listRoi.height - 15 } ); listbox.setScrollBarArea( { scrollbarOffsetX + 2, listRoi.y + topPartHeight, 10, listRoi.height - 2 * topPartHeight } ); listbox.SetAreaMaxItems( 4 ); auto getObjectTypeByResource = []( const uint32_t resourceType ) { switch ( resourceType ) { case 0: return MP2::OBJ_SAWMILL; case 1: return MP2::OBJ_ALCHEMIST_LAB; case 2: case 3: case 4: case 5: case 6: return MP2::OBJ_MINE; case 7: return MP2::OBJ_ABANDONED_MINE; default: // Have you added a new resource type for mines? assert( 0 ); } return MP2::OBJ_NONE; }; std::vector objectInfo; std::vector objectInfoIndexes; auto updateListContent = [&listbox, &objectInfo, &allObjectInfo, &objectInfoIndexes, &listIcnId, &getObjectTypeByResource]( const uint32_t resourceId ) { const MP2::MapObjectType objectType = getObjectTypeByResource( resourceId ); // Mine appearance is the same for different mine resources so we keep the selection. const bool keepSelection = ( objectType == MP2::OBJ_MINE ) && !objectInfo.empty() && ( objectInfo.front().objectType == MP2::OBJ_MINE ); const int selectedId = keepSelection ? listbox.getCurrentId() : 0; const int topId = keepSelection ? listbox.getTopId() : 0; objectInfo.clear(); objectInfoIndexes.clear(); // For the Abandoned Mine there is no metadata set so 'metadata[0] == 0'. const uint32_t resourceType = ( objectType != MP2::OBJ_ABANDONED_MINE ) ? Resource::getResourceTypeFromIconIndex( resourceId ) : 0; for ( size_t i = 0; i < allObjectInfo.size(); ++i ) { if ( allObjectInfo[i].objectType == objectType && allObjectInfo[i].metadata[0] == resourceType ) { objectInfo.push_back( allObjectInfo[i] ); objectInfoIndexes.push_back( static_cast( i ) ); } } listbox.SetListContent( objectInfo ); // We need to reset the initial slider image to be able to reduce the current slider height. listbox.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); listbox.updateScrollBarImage(); if ( keepSelection ) { listbox.SetCurrent( selectedId ); listbox.setTopVisibleItem( topId ); } }; updateListContent( selectedResourceType ); // Select the previously used mine type and resource type in the lists. if ( type > -1 ) { listbox.SetCurrent( std::distance( objectInfoIndexes.begin(), std::find( objectInfoIndexes.begin(), objectInfoIndexes.end(), type ) ) ); } fheroes2::ImageRestorer appearanceTextBackground( display, 0, 0, 0, 0 ); // Mine appearance selection text. auto redrawAppearanceText = [&appearanceTextBackground, &listRoi, &display]( const Maps::ObjectInfo & info ) { std::string mineText( _( "%{mineName} appearance:" ) ); if ( info.objectType == MP2::OBJ_MINE ) { StringReplace( mineText, "%{mineName}", Maps::GetMineName( static_cast( info.metadata[0] ) ) ); } else { StringReplace( mineText, "%{mineName}", MP2::StringObject( info.objectType ) ); } const fheroes2::Text appearanceText( std::move( mineText ), fheroes2::FontType::smallWhite() ); const int32_t textWidth = appearanceText.width( listRoi.width ); const int32_t textHeight = appearanceText.height( listRoi.width ); appearanceTextBackground.restore(); // The text height does not take into account the diacritical marks. Add extra 2 pixels to the restorer. appearanceTextBackground.update( listRoi.x + ( listRoi.width - textWidth ) / 2, listRoi.y - textHeight - 2, textWidth, textHeight + 2 ); appearanceText.draw( listRoi.x, listRoi.y - textHeight, listRoi.width, display ); }; redrawAppearanceText( objectInfo[listbox.getCurrentId()] ); // TODO: Implement owner color selection. listbox.setOwnerColor( 0 ); listbox.Redraw(); // Render dialog buttons. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); bool needRedraw = listbox.QueueEventProcessing(); if ( listbox.isDoubleClicked() || le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) { type = objectInfoIndexes[listbox.getCurrentId()]; color = 0; return; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to start placing the selected castle/town." ), Dialog::ZERO ); } else { for ( uint32_t i = 0; i < resourceCount; ++i ) { if ( le.MouseClickLeft( resourceRoi[i] ) ) { if ( i != selectedResourceType ) { selectedResourceType = i; redrawResourceSelection( resourceRoi[selectedResourceType] ); updateListContent( selectedResourceType ); redrawAppearanceText( objectInfo[listbox.getCurrentId()] ); needRedraw = true; } break; } if ( le.isMouseRightButtonPressedInArea( resourceRoi[i] ) ) { const MP2::MapObjectType objectType = getObjectTypeByResource( i ); std::string objectName; if ( objectType == MP2::OBJ_MINE ) { objectName = Maps::GetMineName( Resource::getResourceTypeFromIconIndex( i ) ); } else { objectName = MP2::StringObject( objectType ); } std::string description( _( "Click to select %{object} as the resource generator to be placed." ) ); StringReplace( description, "%{object}", objectName ); fheroes2::showStandardTextMessage( std::move( objectName ), std::move( description ), Dialog::ZERO ); break; } } } if ( !needRedraw ) { continue; } listbox.Redraw(); display.render( area ); } } int Dialog::selectMountainType( const int mountainType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::LANDSCAPE_MOUNTAINS ); GenericObjectTypeSelection listbox( objectInfo, { 420, fheroes2::Display::instance().height() - 180 }, _( "Select Mountain Object:" ) ); return selectObjectType( mountainType, objectInfo.size(), listbox ); } int Dialog::selectRockType( const int rockType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::LANDSCAPE_ROCKS ); GenericObjectTypeSelection listbox( objectInfo, { 420, fheroes2::Display::instance().height() - 180 }, _( "Select Rock Object:" ) ); return selectObjectType( rockType, objectInfo.size(), listbox ); } int Dialog::selectTreeType( const int treeType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::LANDSCAPE_TREES ); GenericObjectTypeSelection listbox( objectInfo, { 420, fheroes2::Display::instance().height() - 180 }, _( "Select Tree Object:" ) ); return selectObjectType( treeType, objectInfo.size(), listbox ); } int Dialog::selectPowerUpObjectType( const int powerUpObjectType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_POWER_UPS ); PowerUpObjectTypeSelection listbox( objectInfo, { 420, fheroes2::Display::instance().height() - 180 }, _( "Select Power Up Object:" ) ); return selectObjectType( powerUpObjectType, objectInfo.size(), listbox ); } int Dialog::selectAdventureMiscellaneousObjectType( const int objectType ) { const auto & objectInfo = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS ); GenericObjectTypeSelection listbox( objectInfo, { 420, fheroes2::Display::instance().height() - 180 }, _( "Select Adventure Object:" ) ); return selectObjectType( objectType, objectInfo.size(), listbox ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_selectitems.h000066400000000000000000000130231476115357100237400ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2011 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "artifact.h" #include "heroes.h" #include "image.h" #include "interface_list.h" #include "math_base.h" #include "monster.h" #include "skill.h" #include "spell.h" #include "ui_button.h" #include "ui_window.h" class Kingdom; namespace Dialog { class ItemSelectionWindow : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; ItemSelectionWindow() = delete; explicit ItemSelectionWindow( const fheroes2::Size & dialogSize, std::string title, std::string description = {} ); void RedrawBackground( const fheroes2::Point & /* unused */ ) override { _backgroundRestorer->restore(); } void ActionListDoubleClick( int & /* unused */ ) override { _isDoubleClicked = true; } void RedrawItem( const int & /* unused */, int32_t /* ox */, int32_t /* oy */, bool /* current */ ) override { // Do nothing. } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListSingleClick( int & /* unused */ ) override { // Do nothing. } void ActionListPressRight( int & /* unused */ ) override { // Do nothing. } void updateScrollBarImage(); // An image with text should have offset of 10 pixels from all left and right edges. void renderItem( const fheroes2::Sprite & itemSprite, std::string itemText, const fheroes2::Point & destination, const int32_t middleImageOffsetX, const int32_t textOffsetX, const int32_t itemOffsetY, const bool current ) const; int32_t selectItemsEventProcessing(); fheroes2::Rect getBackgroundArea() const; private: bool _isDoubleClicked{ false }; std::unique_ptr _window; std::unique_ptr _backgroundRestorer; fheroes2::Button _buttonOk; fheroes2::Button _buttonCancel; }; Monster selectMonster( const int monsterId ); int selectHeroes( const int heroId = Heroes::UNKNOWN ); Artifact selectArtifact( const int artifactId, const bool isForVictoryConditions ); Spell selectSpell( const int spellId, const bool includeRandomSpells ); int32_t selectKingdomCastle( const Kingdom & kingdom, const bool notOccupiedByHero, std::string title, std::string description = {}, int32_t castlePositionIndex = -1 ); Skill::Secondary selectSecondarySkill( const Heroes & hero, const int skillId = Skill::Secondary::UNKNOWN ); // These functions should be called only from the Editor as they rely on Maps::ObjectInfo structures that are not the same as in-game items. int selectHeroType( const int heroType ); int selectMonsterType( const int monsterType ); int selectArtifactType( const int artifactType ); int selectTreasureType( const int resourceType ); int selectOceanObjectType( const int objectType ); int selectLandscapeOceanObjectType( const int objectType ); void selectTownType( int & type, int & color ); int selectDwellingType( const int dwellingType ); int selectLandscapeMiscellaneousObjectType( const int objectType ); void selectMineType( int32_t & type, int32_t & color ); int selectMountainType( const int mountainType ); int selectRockType( const int rockType ); int selectTreeType( const int treeType ); int selectPowerUpObjectType( const int powerUpObjectType ); int selectAdventureMiscellaneousObjectType( const int objectType ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_selectscenario.cpp000066400000000000000000001033451476115357100247640ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_selectscenario.h" #include #include #include #include #include #include #include "agg_image.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "difficulty.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "logging.h" #include "screen.h" #include "settings.h" #include "system.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_scrollbar.h" #include "ui_text.h" namespace { enum { // MAP LIST SCENARIO_LIST_COUNT_PLAYERS_OFFSET_X = 48, SCENARIO_LIST_MAP_SIZE_OFFSET_X = 67, SCENARIO_LIST_MAP_TYPE_OFFSET_X = 86, SCENARIO_LIST_MAP_NAME_OFFSET_X = 104, SCENARIO_LIST_MAP_NAME_WIDTH = 160, SCENARIO_LIST_VICTORY_CONDITION_OFFSET_X = 266, SCENARIO_LIST_LOSS_CONDITION_OFFSET_X = 285, SCENARIO_LIST_ROW_OFFSET_Y = 57, SCENARIO_LIST_COLUMN_HEIGHT = 175, MAP_LIST_ROW_SPACING_Y = 4, // SELECTED SELECTED_SCENARIO_COUNT_PLAYERS_OFFSET_X = 45, SELECTED_SCENARIO_MAP_SIZE_OFFSET_X = 64, SELECTED_SCENARIO_MAP_TYPE_OFFSET_X = 83, SELECTED_SCENARIO_MAP_NAME_OFFSET_X = 108, SELECTED_SCENARIO_MAP_NAME_WIDTH = 160, SELECTED_SCENARIO_VICTORY_CONDITION_OFFSET_X = 276, SELECTED_SCENARIO_LOSS_CONDITION_OFFSET_X = 295, SELECTED_SCENARIO_DIFFICULTY_OFFSET_X = 220, SELECTED_SCENARIO_DIFFICULTY_OFFSET_Y = 293, SELECTED_SCENARIO_DIFFICULTY_WIDTH = 114, SELECTED_SCENARIO_DIFFICULTY_HEIGHT = 20, SELECTED_SCENARIO_DESCRIPTION_OFFSET_X = 42, SELECTED_SCENARIO_DESCRIPTION_OFFSET_Y = 318, SELECTED_SCENARIO_DESCRIPTION_BOX_WIDTH = 292, SELECTED_SCENARIO_DESCRIPTION_HEIGHT = 90, SELECTED_SCENARIO_GENERAL_OFFSET_Y = 265, // COMMON ICON_SIZE = 18, MAP_SIZE_BUTTON_OFFSET_Y = 23 }; Maps::MapSize currentMapFilter = Maps::ZERO; void outputMapSelectionInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Choose Map\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_SMALL ) << " to view only maps of size small (36 x 36)." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_MEDIUM ) << " to view only maps of size medium (72 x 72)." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_LARGE ) << " to view only maps of size large (108 x 108)." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_EXTRA_LARGE ) << " to view only maps of size extra large (144 x 144)." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_EXTRA_LARGE ) << " to view all maps, regardless of size." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to close the dialog and return to the previous menu." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_OKAY ) << " to select the map." ) } void outputNoMapInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "No maps exist for the chosen type. Returning to the previous menu." ) } void ShowToolTip( const std::string & header, const std::string & body ) { fheroes2::showStandardTextMessage( header, body, Dialog::ZERO ); } void PlayersToolTip( const Maps::FileInfo * /* info */ = nullptr ) { ShowToolTip( _( "Players Icon" ), _( "Indicates how many players total are in the scenario. Any positions not occupied by human players will be occupied by computer players." ) ); } void SizeToolTip( const Maps::FileInfo * /* info */ = nullptr ) { ShowToolTip( _( "Size Icon" ), _( "Indicates whether the map\nis small (36 x 36), medium\n(72 x 72), large (108 x 108),\nor extra large (144 x 144)." ) ); } void MapTypeToolTip( const Maps::FileInfo * /* info */ = nullptr ) { ShowToolTip( _( "Map Type" ), _( "Indicates whether the map is made for \"The Succession Wars\", \"The Price of Loyalty\" or \"Resurrection\" version of the game." ) ); } void mapInfo( const Maps::FileInfo * info ) { assert( info != nullptr ); const fheroes2::Text header( info->name, fheroes2::FontType::normalYellow(), info->getSupportedLanguage() ); fheroes2::MultiFontText body; body.add( { _( "Map Type:\n" ), fheroes2::FontType::normalYellow() } ); switch ( info->version ) { case GameVersion::SUCCESSION_WARS: body.add( { _( "The Succession Wars" ), fheroes2::FontType::normalWhite() } ); break; case GameVersion::PRICE_OF_LOYALTY: body.add( { _( "The Price of Loyalty" ), fheroes2::FontType::normalWhite() } ); break; case GameVersion::RESURRECTION: body.add( { _( "Resurrection" ), fheroes2::FontType::normalWhite() } ); break; default: // Did you add a new map version? Add the logic above! assert( 0 ); break; } if ( info->version == GameVersion::RESURRECTION ) { body.add( { _( "\n\nLanguage:\n" ), fheroes2::FontType::normalYellow() } ); body.add( { fheroes2::getLanguageName( info->mainLanguage ), fheroes2::FontType::normalWhite() } ); } body.add( { _( "\n\nLocation: " ), fheroes2::FontType::smallYellow() } ); body.add( { info->filename, fheroes2::FontType::smallWhite() } ); fheroes2::showMessage( header, body, Dialog::ZERO ); } void LossConditionInfo( const Maps::FileInfo * info ) { std::string msg; switch ( info->lossConditionType ) { case Maps::FileInfo::LOSS_EVERYTHING: msg = _( "Lose all your heroes and towns." ); break; case Maps::FileInfo::LOSS_TOWN: msg = _( "Lose a specific town." ); break; case Maps::FileInfo::LOSS_HERO: msg = _( "Lose a specific hero." ); break; case Maps::FileInfo::LOSS_OUT_OF_TIME: msg = _( "Run out of time. Fail to win by a certain point." ); break; default: // This is an unknown condition. Add the logic for it above! assert( 0 ); return; } ShowToolTip( _( "Loss Condition" ), msg ); } void VictoryConditionInfo( const Maps::FileInfo * info ) { std::string msg; switch ( info->victoryConditionType ) { case Maps::FileInfo::VICTORY_DEFEAT_EVERYONE: msg = _( "Defeat all enemy heroes and towns." ); break; case Maps::FileInfo::VICTORY_CAPTURE_TOWN: msg = _( "Capture a specific town." ); break; case Maps::FileInfo::VICTORY_KILL_HERO: msg = _( "Defeat a specific hero." ); break; case Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT: msg = _( "Find a specific artifact." ); break; case Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE: msg = _( "Your side must defeat the opposing side." ); break; case Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD: msg = _( "Accumulate a large amount of gold." ); break; default: // This is an unknown condition. Add the logic for it above! assert( 0 ); return; } ShowToolTip( _( "Victory Condition" ), msg ); } size_t GetInitialMapId( const MapsFileInfoList & lists ) { const Maps::FileInfo & currentMapinfo = Settings::Get().getCurrentMapInfo(); size_t mapId = 0; for ( MapsFileInfoList::const_iterator mapIter = lists.begin(); mapIter != lists.end(); ++mapIter, ++mapId ) { if ( mapIter->name == currentMapinfo.name && mapIter->filename == currentMapinfo.filename ) { return mapId; } } return 0; } int32_t GetCenteredTextXCoordinate( const int32_t startCoordX, const int32_t areaWidth, const int32_t textWidth ) { const int32_t centerTransform = areaWidth > textWidth ? ( areaWidth - textWidth ) / 2 : 0; return startCoordX + centerTransform; } void renderFileName( const Maps::FileInfo & info, bool selected, const int32_t posX, const int32_t posY, fheroes2::Display & display ) { fheroes2::Text text( System::GetFileName( info.filename ), selected ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ); text.fitToOneRow( SCENARIO_LIST_MAP_NAME_WIDTH ); const int32_t xCoordinate = posX + SCENARIO_LIST_MAP_NAME_OFFSET_X; const int32_t yCoordinate = posY + MAP_LIST_ROW_SPACING_Y - 1; text.draw( xCoordinate, yCoordinate, display ); } template void ShowIfFound( ScenarioListBox & listbox, const fheroes2::Point & mouseLocation, const ShowFunction & function ) { const Maps::FileInfo * item = listbox.GetFromPosition( mouseLocation ); if ( item ) { function( item ); } } } void ScenarioListBox::RedrawItem( const Maps::FileInfo & info, int32_t /*dstx*/, int32_t dsty, bool current ) { fheroes2::Display & display = fheroes2::Display::instance(); dsty = dsty + MAP_LIST_ROW_SPACING_Y; _renderScenarioListItem( info, display, dsty, current ); } void ScenarioListBox::RedrawBackground( const fheroes2::Point & dst ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::REQSBKG, 0 ), display, dst.x, dst.y ); if ( isSelected() ) { _renderSelectedScenarioInfo( display, dst ); } } void ScenarioListBox::_renderScenarioListItem( const Maps::FileInfo & info, fheroes2::Display & display, const int32_t dsty, const bool current ) const { fheroes2::Blit( _getPlayersCountIcon( info.kingdomColors ), display, _offsetX + SCENARIO_LIST_COUNT_PLAYERS_OFFSET_X, dsty ); _renderMapIcon( info.width, display, _offsetX + SCENARIO_LIST_MAP_SIZE_OFFSET_X, dsty ); fheroes2::Blit( _getMapTypeIcon( info.version ), display, _offsetX + SCENARIO_LIST_MAP_TYPE_OFFSET_X, dsty ); if ( _isForEditor ) { renderFileName( info, current, _offsetX, dsty, display ); } else { _renderMapName( info, current, dsty, display ); } fheroes2::Blit( _getWinConditionsIcon( info.victoryConditionType ), display, _offsetX + SCENARIO_LIST_VICTORY_CONDITION_OFFSET_X, dsty ); fheroes2::Blit( _getLossConditionsIcon( info.lossConditionType ), display, _offsetX + SCENARIO_LIST_LOSS_CONDITION_OFFSET_X, dsty ); } void ScenarioListBox::_renderSelectedScenarioInfo( fheroes2::Display & display, const fheroes2::Point & dst ) { const Maps::FileInfo & info = GetCurrent(); fheroes2::Blit( _getPlayersCountIcon( info.kingdomColors ), display, dst.x + SELECTED_SCENARIO_COUNT_PLAYERS_OFFSET_X, dst.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y ); _renderMapIcon( info.width, display, dst.x + SELECTED_SCENARIO_MAP_SIZE_OFFSET_X, dst.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y ); fheroes2::Blit( _getMapTypeIcon( info.version ), display, dst.x + SELECTED_SCENARIO_MAP_TYPE_OFFSET_X, dst.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y ); fheroes2::Text mapNameText{ info.name, fheroes2::FontType::normalWhite(), info.getSupportedLanguage() }; mapNameText.fitToOneRow( SCENARIO_LIST_MAP_NAME_WIDTH ); mapNameText.draw( GetCenteredTextXCoordinate( dst.x + SELECTED_SCENARIO_MAP_NAME_OFFSET_X, SELECTED_SCENARIO_MAP_NAME_WIDTH, mapNameText.width() ), dst.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y + 2, display ); fheroes2::Blit( _getWinConditionsIcon( info.victoryConditionType ), display, dst.x + SELECTED_SCENARIO_VICTORY_CONDITION_OFFSET_X, dst.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y ); fheroes2::Blit( _getLossConditionsIcon( info.lossConditionType ), display, dst.x + SELECTED_SCENARIO_LOSS_CONDITION_OFFSET_X, dst.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y ); fheroes2::Text difficultyLabelText( _( "Map difficulty:" ), fheroes2::FontType::normalWhite() ); difficultyLabelText.draw( dst.x + 210 - difficultyLabelText.width(), dst.y + SELECTED_SCENARIO_DIFFICULTY_OFFSET_Y, display ); fheroes2::Text difficultyText( Difficulty::String( info.difficulty ), fheroes2::FontType::normalWhite() ); difficultyText.draw( GetCenteredTextXCoordinate( dst.x + SELECTED_SCENARIO_DIFFICULTY_OFFSET_X, SELECTED_SCENARIO_DIFFICULTY_WIDTH, difficultyText.width() ), dst.y + SELECTED_SCENARIO_DIFFICULTY_OFFSET_Y, display ); fheroes2::Text descriptionText( info.description, fheroes2::FontType::normalWhite(), info.getSupportedLanguage() ); descriptionText.setUniformVerticalAlignment( false ); descriptionText.draw( dst.x + SELECTED_SCENARIO_DESCRIPTION_OFFSET_X + 4, dst.y + SELECTED_SCENARIO_DESCRIPTION_OFFSET_Y + 3, SELECTED_SCENARIO_DESCRIPTION_BOX_WIDTH - 8, display ); } void ScenarioListBox::_renderMapName( const Maps::FileInfo & info, bool selected, const int32_t & baseYOffset, fheroes2::Display & display ) const { fheroes2::Text mapName{ info.name, { fheroes2::FontSize::NORMAL, ( selected ? fheroes2::FontColor::YELLOW : fheroes2::FontColor::WHITE ) }, info.getSupportedLanguage() }; mapName.fitToOneRow( SCENARIO_LIST_MAP_NAME_WIDTH ); const int32_t xCoordinate = GetCenteredTextXCoordinate( _offsetX + SCENARIO_LIST_MAP_NAME_OFFSET_X, SCENARIO_LIST_MAP_NAME_WIDTH, mapName.width() ); const int32_t yCoordinate = baseYOffset + MAP_LIST_ROW_SPACING_Y - 1; mapName.draw( xCoordinate, yCoordinate, display ); } void ScenarioListBox::SelectMapSize( MapsFileInfoList & mapsList, const int selectedSize_ ) { const fheroes2::Sprite & originalSlider = fheroes2::AGG::GetICN( ICN::ESCROLL, 3 ); const fheroes2::Image updatedScrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, false, 140, 9, static_cast( mapsList.size() ), { 0, 0, originalSlider.width(), 8 }, { 0, 7, originalSlider.width(), 8 } ); setScrollBarImage( updatedScrollbarSlider ); Maps::FileInfo currentScenario; if ( _size() > 0 ) { currentScenario = GetCurrent(); } else { currentScenario = mapsList[0]; } SetListContent( mapsList ); if ( currentScenario.width == selectedSize_ || selectedSize_ == Maps::ZERO ) { SetCurrent( currentScenario ); } selectedSize = selectedSize_; } void ScenarioListBox::_renderMapIcon( const uint16_t size, fheroes2::Display & display, const int32_t coordX, const int32_t coordY ) { int16_t mapIconIndex = -1; switch ( size ) { case Maps::SMALL: mapIconIndex = 26; break; case Maps::MEDIUM: mapIconIndex = 27; break; case Maps::LARGE: mapIconIndex = 28; break; case Maps::XLARGE: mapIconIndex = 29; break; default: break; } if ( mapIconIndex == -1 ) { fheroes2::Image icon( 17, 17 ); icon.reset(); fheroes2::Fill( icon, 1, 1, 15, 15, fheroes2::GetColorId( 0x8D, 0x73, 0xFF ) ); fheroes2::Text text( _( "N" ), fheroes2::FontType::smallWhite() ); text.draw( ( 17 - text.width() ) / 2, ( 17 - text.height() ) / 2, icon ); fheroes2::Blit( icon, display, coordX, coordY ); } else { fheroes2::Blit( fheroes2::AGG::GetICN( ICN::REQUESTS, mapIconIndex ), display, coordX, coordY ); } } const fheroes2::Sprite & ScenarioListBox::_getPlayersCountIcon( const uint8_t colors ) { const uint32_t iconIndex = 19 + Color::Count( colors ); return fheroes2::AGG::GetICN( ICN::REQUESTS, iconIndex ); } const fheroes2::Sprite & ScenarioListBox::_getMapTypeIcon( const GameVersion version ) { switch ( version ) { case GameVersion::SUCCESSION_WARS: return fheroes2::AGG::GetICN( ICN::MAP_TYPE_ICON, 0 ); case GameVersion::PRICE_OF_LOYALTY: return fheroes2::AGG::GetICN( ICN::MAP_TYPE_ICON, 1 ); case GameVersion::RESURRECTION: return fheroes2::AGG::GetICN( ICN::MAP_TYPE_ICON, 2 ); default: // Did you add a new game version? Add the corresponding logic above! assert( 0 ); break; } return fheroes2::AGG::GetICN( ICN::UNKNOWN, 0 ); } const fheroes2::Sprite & ScenarioListBox::_getWinConditionsIcon( const uint8_t condition ) { uint32_t iconIndex = 30 + condition; return fheroes2::AGG::GetICN( ICN::REQUESTS, iconIndex ); } const fheroes2::Sprite & ScenarioListBox::_getLossConditionsIcon( const uint8_t condition ) { uint32_t iconIndex = 36 + condition; return fheroes2::AGG::GetICN( ICN::REQUESTS, iconIndex ); } void ScenarioListBox::ActionListDoubleClick( Maps::FileInfo & /* unused */ ) { _isDoubleClicked = true; } const Maps::FileInfo * Dialog::SelectScenario( const MapsFileInfoList & allMaps, const bool isForEditor ) { if ( allMaps.empty() ) { outputNoMapInTextSupportMode(); return nullptr; } outputMapSelectionInTextSupportMode(); fheroes2::Display & display = fheroes2::Display::instance(); LocalEvent & le = LocalEvent::Get(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); MapsFileInfoList small; MapsFileInfoList medium; MapsFileInfoList large; MapsFileInfoList xlarge; MapsFileInfoList all( allMaps ); small.reserve( all.size() ); medium.reserve( all.size() ); large.reserve( all.size() ); xlarge.reserve( all.size() ); for ( const Maps::FileInfo & info : all ) { switch ( info.width ) { case Maps::SMALL: small.push_back( info ); break; case Maps::MEDIUM: medium.push_back( info ); break; case Maps::LARGE: large.push_back( info ); break; case Maps::XLARGE: xlarge.push_back( info ); break; default: // Did you add a new map size? Add the corresponding logic! assert( 0 ); continue; } } const fheroes2::Sprite & panel = fheroes2::AGG::GetICN( ICN::REQSBKG, 0 ); const fheroes2::Rect rt( ( display.width() - panel.width() ) / 2, ( display.height() - panel.height() ) / 2, panel.width(), panel.height() ); const fheroes2::ImageRestorer background( display, rt.x - fheroes2::shadowWidthPx, rt.y, rt.width + fheroes2::shadowWidthPx, rt.height + fheroes2::shadowWidthPx ); const fheroes2::Sprite & shadow = fheroes2::AGG::GetICN( ICN::REQSBKG, 1 ); fheroes2::Blit( shadow, display, rt.x - fheroes2::shadowWidthPx, rt.y + fheroes2::shadowWidthPx ); const fheroes2::Rect countPlayers( rt.x + SCENARIO_LIST_COUNT_PLAYERS_OFFSET_X, rt.y + SCENARIO_LIST_ROW_OFFSET_Y, ICON_SIZE, SCENARIO_LIST_COLUMN_HEIGHT ); const fheroes2::Rect sizeMaps( rt.x + SCENARIO_LIST_MAP_SIZE_OFFSET_X, rt.y + SCENARIO_LIST_ROW_OFFSET_Y, ICON_SIZE, SCENARIO_LIST_COLUMN_HEIGHT ); const fheroes2::Rect mapTypes( rt.x + SCENARIO_LIST_MAP_TYPE_OFFSET_X, rt.y + SCENARIO_LIST_ROW_OFFSET_Y, ICON_SIZE, SCENARIO_LIST_COLUMN_HEIGHT ); const fheroes2::Rect mapNames( rt.x + SCENARIO_LIST_MAP_NAME_OFFSET_X, rt.y + SCENARIO_LIST_ROW_OFFSET_Y, SCENARIO_LIST_MAP_NAME_WIDTH, SCENARIO_LIST_COLUMN_HEIGHT ); const fheroes2::Rect victoryConds( rt.x + SCENARIO_LIST_VICTORY_CONDITION_OFFSET_X, rt.y + SCENARIO_LIST_ROW_OFFSET_Y, ICON_SIZE, SCENARIO_LIST_COLUMN_HEIGHT ); const fheroes2::Rect lossConds( rt.x + SCENARIO_LIST_LOSS_CONDITION_OFFSET_X, rt.y + SCENARIO_LIST_ROW_OFFSET_Y, ICON_SIZE, SCENARIO_LIST_COLUMN_HEIGHT ); const fheroes2::Rect curCountPlayer( rt.x + SELECTED_SCENARIO_COUNT_PLAYERS_OFFSET_X, rt.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y, ICON_SIZE, ICON_SIZE ); const fheroes2::Rect curMapSize( rt.x + SELECTED_SCENARIO_MAP_SIZE_OFFSET_X, rt.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y, ICON_SIZE, ICON_SIZE ); const fheroes2::Rect curMapType( rt.x + SELECTED_SCENARIO_MAP_TYPE_OFFSET_X, rt.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y, ICON_SIZE, ICON_SIZE ); const fheroes2::Rect curMapName( rt.x + SELECTED_SCENARIO_MAP_NAME_OFFSET_X, rt.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y, SELECTED_SCENARIO_MAP_NAME_WIDTH, ICON_SIZE ); const fheroes2::Rect curVictoryCond( rt.x + SELECTED_SCENARIO_VICTORY_CONDITION_OFFSET_X, rt.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y, ICON_SIZE, ICON_SIZE ); const fheroes2::Rect curLossCond( rt.x + SELECTED_SCENARIO_LOSS_CONDITION_OFFSET_X, rt.y + SELECTED_SCENARIO_GENERAL_OFFSET_Y, ICON_SIZE, ICON_SIZE ); const fheroes2::Rect curDifficulty( rt.x + SELECTED_SCENARIO_DIFFICULTY_OFFSET_X, rt.y + SELECTED_SCENARIO_DIFFICULTY_OFFSET_Y, SELECTED_SCENARIO_DIFFICULTY_WIDTH, SELECTED_SCENARIO_DIFFICULTY_HEIGHT ); const fheroes2::Rect curDescription( rt.x + SELECTED_SCENARIO_DESCRIPTION_OFFSET_X, rt.y + SELECTED_SCENARIO_DESCRIPTION_OFFSET_Y, SELECTED_SCENARIO_DESCRIPTION_BOX_WIDTH, SELECTED_SCENARIO_DESCRIPTION_HEIGHT ); fheroes2::Button buttonOk( rt.x + 140, rt.y + 410, ICN::BUTTON_SMALL_OKAY_GOOD, 0, 1 ); fheroes2::Button buttonSelectSmall( rt.x + 36, rt.y + MAP_SIZE_BUTTON_OFFSET_Y, ICN::BUTTON_MAPSIZE_SMALL, 0, 1 ); fheroes2::Button buttonSelectMedium( rt.x + 98, rt.y + MAP_SIZE_BUTTON_OFFSET_Y, ICN::BUTTON_MAPSIZE_MEDIUM, 0, 1 ); fheroes2::Button buttonSelectLarge( rt.x + 160, rt.y + MAP_SIZE_BUTTON_OFFSET_Y, ICN::BUTTON_MAPSIZE_LARGE, 0, 1 ); fheroes2::Button buttonSelectXLarge( rt.x + 222, rt.y + MAP_SIZE_BUTTON_OFFSET_Y, ICN::BUTTON_MAPSIZE_XLARGE, 0, 1 ); fheroes2::Button buttonSelectAll( rt.x + 284, rt.y + MAP_SIZE_BUTTON_OFFSET_Y, ICN::BUTTON_MAPSIZE_ALL, 0, 1 ); const auto drawAllButtons = [&buttonOk, &buttonSelectSmall, &buttonSelectMedium, &buttonSelectLarge, &buttonSelectXLarge, &buttonSelectAll]() { buttonOk.draw(); buttonSelectSmall.draw(); buttonSelectMedium.draw(); buttonSelectLarge.draw(); buttonSelectXLarge.draw(); buttonSelectAll.draw(); }; ScenarioListBox listbox( rt.getPosition() ); listbox.SetScrollButtonUp( ICN::REQUESTS, 5, 6, { rt.x + 327, rt.y + 55 } ); listbox.SetScrollButtonDn( ICN::REQUESTS, 7, 8, { rt.x + 327, rt.y + 217 } ); listbox.setScrollBarArea( { rt.x + 328, rt.y + 73, 12, 140 } ); listbox.SetAreaMaxItems( 9 ); // This has impact on displaying selected scenario info listbox.SetAreaItems( { rt.x + 55, rt.y + 55, 270, 175 } ); listbox.setForEditorMode( isForEditor ); fheroes2::ButtonBase * currentPressedButton = nullptr; { MapsFileInfoList * currentMapsList = nullptr; const auto resetFilter = [&all, &buttonSelectAll, ¤tPressedButton, ¤tMapsList]() { currentPressedButton = &buttonSelectAll; currentMapsList = &all; currentMapFilter = Maps::ZERO; }; switch ( currentMapFilter ) { case Maps::SMALL: currentPressedButton = &buttonSelectSmall; currentMapsList = &small; break; case Maps::MEDIUM: currentPressedButton = &buttonSelectMedium; currentMapsList = &medium; break; case Maps::LARGE: currentPressedButton = &buttonSelectLarge; currentMapsList = &large; break; case Maps::XLARGE: currentPressedButton = &buttonSelectXLarge; currentMapsList = &xlarge; break; default: resetFilter(); break; } assert( currentMapsList != nullptr ); if ( currentMapsList->empty() ) { resetFilter(); } assert( currentPressedButton != nullptr && currentMapsList != nullptr && !currentMapsList->empty() ); listbox.SelectMapSize( *currentMapsList, currentMapFilter ); listbox.SetCurrent( GetInitialMapId( *currentMapsList ) ); currentPressedButton->press(); } listbox.RedrawBackground( rt.getPosition() ); listbox.Redraw(); drawAllButtons(); display.render(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); listbox.QueueEventProcessing(); bool needRedraw = false; if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || listbox.isDoubleClicked() ) { MapsFileInfoList::const_iterator it = std::find( allMaps.begin(), allMaps.end(), listbox.GetCurrent() ); return ( it != allMaps.end() ) ? &( *it ) : nullptr; } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return nullptr; } if ( le.MouseClickLeft( buttonSelectSmall.area() ) || HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_SMALL ) ) { if ( small.empty() ) { fheroes2::showStandardTextMessage( "", _( "No maps exist at that size." ), Dialog::OK ); } else { currentMapFilter = Maps::SMALL; listbox.SelectMapSize( small, Maps::SMALL ); currentPressedButton = &buttonSelectSmall; needRedraw = true; } } else if ( le.MouseClickLeft( buttonSelectMedium.area() ) || HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_MEDIUM ) ) { if ( medium.empty() ) { fheroes2::showStandardTextMessage( "", _( "No maps exist at that size." ), Dialog::OK ); } else { currentMapFilter = Maps::MEDIUM; listbox.SelectMapSize( medium, Maps::MEDIUM ); currentPressedButton = &buttonSelectMedium; needRedraw = true; } } else if ( le.MouseClickLeft( buttonSelectLarge.area() ) || HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_LARGE ) ) { if ( large.empty() ) { fheroes2::showStandardTextMessage( "", _( "No maps exist at that size." ), Dialog::OK ); } else { currentMapFilter = Maps::LARGE; listbox.SelectMapSize( large, Maps::LARGE ); currentPressedButton = &buttonSelectLarge; needRedraw = true; } } else if ( le.MouseClickLeft( buttonSelectXLarge.area() ) || HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_EXTRA_LARGE ) ) { if ( xlarge.empty() ) { fheroes2::showStandardTextMessage( "", _( "No maps exist at that size." ), Dialog::OK ); } else { currentMapFilter = Maps::XLARGE; listbox.SelectMapSize( xlarge, Maps::XLARGE ); currentPressedButton = &buttonSelectXLarge; needRedraw = true; } } else if ( le.MouseClickLeft( buttonSelectAll.area() ) || HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_ALL ) ) { currentMapFilter = Maps::ZERO; listbox.SelectMapSize( all, Maps::ZERO ); currentPressedButton = &buttonSelectAll; needRedraw = true; } // The currentPressedButton must be set correctly before the following button redrawing code block, otherwise, the map size selection button that has just been // clicked will be redrawn in the released state for a short time. buttonSelectSmall.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSelectSmall.area() ) || currentPressedButton == &buttonSelectSmall ); buttonSelectMedium.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSelectMedium.area() ) || currentPressedButton == &buttonSelectMedium ); buttonSelectLarge.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSelectLarge.area() ) || currentPressedButton == &buttonSelectLarge ); buttonSelectXLarge.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSelectXLarge.area() ) || currentPressedButton == &buttonSelectXLarge ); buttonSelectAll.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSelectAll.area() ) || currentPressedButton == &buttonSelectAll ); if ( le.isMouseRightButtonPressedInArea( buttonSelectSmall.area() ) ) { ShowToolTip( _( "Small Maps" ), _( "View only maps of size small (36 x 36)." ) ); } else if ( le.isMouseRightButtonPressedInArea( buttonSelectMedium.area() ) ) { ShowToolTip( _( "Medium Maps" ), _( "View only maps of size medium (72 x 72)." ) ); } else if ( le.isMouseRightButtonPressedInArea( buttonSelectLarge.area() ) ) { ShowToolTip( _( "Large Maps" ), _( "View only maps of size large (108 x 108)." ) ); } else if ( le.isMouseRightButtonPressedInArea( buttonSelectXLarge.area() ) ) { ShowToolTip( _( "Extra Large Maps" ), _( "View only maps of size extra large (144 x 144)." ) ); } else if ( le.isMouseRightButtonPressedInArea( buttonSelectAll.area() ) ) { ShowToolTip( _( "All Maps" ), _( "View all maps, regardless of size." ) ); } else if ( le.isMouseRightButtonPressedInArea( countPlayers ) ) { ShowIfFound( listbox, le.getMouseCursorPos(), PlayersToolTip ); } else if ( le.isMouseRightButtonPressedInArea( curCountPlayer ) ) { PlayersToolTip(); } else if ( le.isMouseRightButtonPressedInArea( sizeMaps ) ) { ShowIfFound( listbox, le.getMouseCursorPos(), SizeToolTip ); } else if ( le.isMouseRightButtonPressedInArea( curMapSize ) ) { SizeToolTip(); } else if ( le.isMouseRightButtonPressedInArea( mapTypes ) ) { ShowIfFound( listbox, le.getMouseCursorPos(), MapTypeToolTip ); } else if ( le.isMouseRightButtonPressedInArea( curMapType ) ) { MapTypeToolTip(); } else if ( le.isMouseRightButtonPressedInArea( mapNames ) ) { ShowIfFound( listbox, le.getMouseCursorPos(), mapInfo ); } else if ( le.isMouseRightButtonPressedInArea( curMapName ) ) { ShowToolTip( _( "Selected Name" ), _( "The name of the currently selected map." ) ); } else if ( le.isMouseRightButtonPressedInArea( victoryConds ) ) { ShowIfFound( listbox, le.getMouseCursorPos(), VictoryConditionInfo ); } else if ( le.isMouseRightButtonPressedInArea( lossConds ) ) { ShowIfFound( listbox, le.getMouseCursorPos(), LossConditionInfo ); } else if ( le.isMouseRightButtonPressedInArea( curVictoryCond ) ) { VictoryConditionInfo( &( listbox.GetCurrent() ) ); } else if ( le.isMouseRightButtonPressedInArea( curLossCond ) ) { LossConditionInfo( &( listbox.GetCurrent() ) ); } else if ( le.isMouseRightButtonPressedInArea( curDifficulty ) ) { ShowToolTip( _( "Selected Map Difficulty" ), _( "The map difficulty of the currently selected map. The map difficulty is determined by the scenario designer. More difficult maps might include more or stronger enemies, fewer resources, or other special conditions making things tougher for the human player." ) ); } else if ( le.isMouseRightButtonPressedInArea( curDescription ) ) { ShowToolTip( _( "Selected Description" ), _( "The description of the currently selected map." ) ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { ShowToolTip( _( "Okay" ), _( "Accept the choice made." ) ); } if ( !needRedraw && !listbox.IsNeedRedraw() ) { continue; } listbox.Redraw(); // The map list box redraws the entire window as a background (including all the buttons), so we have to redraw these buttons once again to correctly reflect // their current state and not mess up with localized labels on these buttons. drawAllButtons(); display.render(); } return nullptr; } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_selectscenario.h000066400000000000000000000102511476115357100244220ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "interface_list.h" #include "maps.h" #include "maps_fileinfo.h" #include "math_base.h" namespace fheroes2 { class Display; class Sprite; } class ScenarioListBox : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; explicit ScenarioListBox( const fheroes2::Point & pt ) : Interface::ListBox( pt ) , _offsetX( pt.x ) {} void RedrawItem( const Maps::FileInfo & info, int32_t /*dstx*/, int32_t dsty, bool current ) override; void RedrawBackground( const fheroes2::Point & dst ) override; void SelectMapSize( MapsFileInfoList & mapsList, const int selectedSize ); void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListDoubleClick( Maps::FileInfo & ) override; void ActionListSingleClick( Maps::FileInfo & ) override { // Do nothing. } void ActionListPressRight( Maps::FileInfo & /* info */ ) override { // Do nothing. } bool isDoubleClicked() const { return _isDoubleClicked; } void setForEditorMode( const bool isForEditor ) { _isForEditor = isForEditor; } private: int selectedSize{ Maps::ZERO }; const int32_t _offsetX; bool _isDoubleClicked{ false }; bool _isForEditor{ false }; void _renderScenarioListItem( const Maps::FileInfo & info, fheroes2::Display & display, const int32_t dsty, const bool current ) const; void _renderSelectedScenarioInfo( fheroes2::Display & display, const fheroes2::Point & dst ); void _renderMapName( const Maps::FileInfo & info, bool selected, const int32_t & baseYOffset, fheroes2::Display & display ) const; static void _renderMapIcon( const uint16_t size, fheroes2::Display & display, const int32_t coordX, const int32_t coordY ); static const fheroes2::Sprite & _getPlayersCountIcon( const uint8_t colors ); static const fheroes2::Sprite & _getMapTypeIcon( const GameVersion version ); static const fheroes2::Sprite & _getWinConditionsIcon( const uint8_t condition ); static const fheroes2::Sprite & _getLossConditionsIcon( const uint8_t condition ); }; namespace Dialog { const Maps::FileInfo * SelectScenario( const MapsFileInfoList & allMaps, const bool isForEditor ); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_system_options.cpp000066400000000000000000000512141476115357100250550ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "dialog_system_options.h" #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "dialog_audio.h" #include "dialog_graphics_settings.h" #include "dialog_hotkeys.h" #include "dialog_interface_settings.h" #include "dialog_language_selection.h" #include "game_delays.h" #include "game_hotkeys.h" #include "game_interface.h" #include "game_language.h" #include "icn.h" #include "image.h" #include "interface_base.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_option_item.h" #include "ui_window.h" namespace { enum class DialogAction : int { Configuration, Language, Graphics, AudioSettings, HotKeys, InterfaceSettings, UpdateInterface, Close }; const fheroes2::Size offsetBetweenOptions{ 92, 110 }; const fheroes2::Point optionOffset{ 20, 31 }; const int32_t optionWindowSize{ 65 }; const fheroes2::Rect languageRoi{ optionOffset.x, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect graphicsRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect audioRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect heroSpeedRoi{ optionOffset.x, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect enemySpeedRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect hotKeyRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect interfaceRoi{ optionOffset.x, optionOffset.y + offsetBetweenOptions.height * 2, optionWindowSize, optionWindowSize }; const fheroes2::Rect textSupportModeRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y + offsetBetweenOptions.height * 2, optionWindowSize, optionWindowSize }; const fheroes2::Rect battlesRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y + offsetBetweenOptions.height * 2, optionWindowSize, optionWindowSize }; void drawLanguage( const fheroes2::Rect & optionRoi ) { const fheroes2::SupportedLanguage currentLanguage = fheroes2::getLanguageFromAbbreviation( Settings::Get().getGameLanguage() ); fheroes2::LanguageSwitcher languageSwitcher( currentLanguage ); fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 18 ), _( "Language" ), fheroes2::getLanguageName( currentLanguage ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawGraphics( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::GAME_OPTION_ICON, 1 ), _( "Graphics" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawAudioOptions( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 1 ), _( "Audio" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawHeroSpeed( const fheroes2::Rect & optionRoi ) { const Settings & conf = Settings::Get(); const int heroSpeed = conf.HeroesMoveSpeed(); uint32_t heroSpeedIconId = 9; if ( heroSpeed >= 4 ) { heroSpeedIconId = 3 + heroSpeed / 2; } else if ( heroSpeed > 0 ) { heroSpeedIconId = 4; } const fheroes2::Sprite & heroSpeedIcon = fheroes2::AGG::GetICN( ICN::SPANEL, heroSpeedIconId ); std::string value; if ( heroSpeed == 10 ) { value = _( "Jump" ); } else { value = std::to_string( heroSpeed ); } fheroes2::drawOption( optionRoi, heroSpeedIcon, _( "Hero Speed" ), std::move( value ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawEnemySpeed( const fheroes2::Rect & optionRoi ) { const Settings & conf = Settings::Get(); const int aiSpeed = conf.AIMoveSpeed(); uint32_t aiSpeedIconId = 9; if ( aiSpeed >= 4 ) { aiSpeedIconId = 3 + aiSpeed / 2; } else if ( aiSpeed > 0 ) { aiSpeedIconId = 4; } const fheroes2::Sprite & aiSpeedIcon = fheroes2::AGG::GetICN( ICN::SPANEL, aiSpeedIconId ); std::string value; if ( aiSpeed == 0 ) { value = _( "Don't Show" ); } else if ( aiSpeed == 10 ) { value = _( "Jump" ); } else { value = std::to_string( aiSpeed ); } fheroes2::drawOption( optionRoi, aiSpeedIcon, _( "Enemy Speed" ), std::move( value ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawHotKeyOptions( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::GAME_OPTION_ICON, 0 ), _( "Hot Keys" ), _( "Configure" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawInterfaceSettings( const fheroes2::Rect & optionRoi ) { const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & interfaceThemeIcon = fheroes2::AGG::GetICN( ICN::SPANEL, isEvilInterface ? 17 : 16 ); fheroes2::drawOption( optionRoi, interfaceThemeIcon, _( "Interface" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawTextSupportModeOptions( const fheroes2::Rect & optionRoi ) { if ( Settings::Get().isTextSupportModeEnabled() ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::CSPANEL, 4 ), _( "Text Support" ), _( "On" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } else { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 9 ), _( "Text Support" ), _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } } void drawBattles( const fheroes2::Rect & optionRoi ) { const Settings & conf = Settings::Get(); if ( conf.BattleAutoResolve() ) { const bool spellcast = conf.BattleAutoSpellcast(); std::string value = spellcast ? _( "Auto Resolve" ) : _( "Auto, No Spells" ); const fheroes2::Sprite & autoBattleIcon = fheroes2::AGG::GetICN( ICN::CSPANEL, spellcast ? 7 : 6 ); fheroes2::drawOption( optionRoi, autoBattleIcon, _( "Battles" ), std::move( value ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } else { const fheroes2::Sprite & autoBattleIcon = fheroes2::AGG::GetICN( ICN::SPANEL, 18 ); fheroes2::drawOption( optionRoi, autoBattleIcon, _( "Battles" ), _( "combatMode|Manual" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } } DialogAction openSystemOptionsDialog( bool & saveConfiguration ) { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 289, 382, true, display ); const fheroes2::Rect windowRoi = background.activeArea(); fheroes2::ImageRestorer emptyDialogRestorer( display, windowRoi.x, windowRoi.y, windowRoi.width, windowRoi.height - 30 ); const fheroes2::Rect windowLanguageRoi( languageRoi + windowRoi.getPosition() ); const fheroes2::Rect windowGraphicsRoi( graphicsRoi + windowRoi.getPosition() ); const fheroes2::Rect windowAudioRoi( audioRoi + windowRoi.getPosition() ); const fheroes2::Rect windowHeroSpeedRoi( heroSpeedRoi + windowRoi.getPosition() ); const fheroes2::Rect windowEnemySpeedRoi( enemySpeedRoi + windowRoi.getPosition() ); const fheroes2::Rect windowHotKeyRoi( hotKeyRoi + windowRoi.getPosition() ); const fheroes2::Rect windowInterfaceRoi( interfaceRoi + windowRoi.getPosition() ); const fheroes2::Rect windowTextSupportModeRoi( textSupportModeRoi + windowRoi.getPosition() ); const fheroes2::Rect windowBattlesRoi( battlesRoi + windowRoi.getPosition() ); const auto drawOptions = [&windowLanguageRoi, &windowGraphicsRoi, &windowAudioRoi, &windowHeroSpeedRoi, &windowEnemySpeedRoi, &windowHotKeyRoi, &windowInterfaceRoi, &windowTextSupportModeRoi, &windowBattlesRoi]() { drawLanguage( windowLanguageRoi ); drawGraphics( windowGraphicsRoi ); drawAudioOptions( windowAudioRoi ); drawHeroSpeed( windowHeroSpeedRoi ); drawEnemySpeed( windowEnemySpeedRoi ); drawHotKeyOptions( windowHotKeyRoi ); drawInterfaceSettings( windowInterfaceRoi ); drawTextSupportModeOptions( windowTextSupportModeRoi ); drawBattles( windowBattlesRoi ); }; drawOptions(); Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Button buttonOk; const int buttonOkIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcnId, 0, 1, { 0, 5 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); const auto refreshWindow = [&drawOptions, &emptyDialogRestorer, &display]() { emptyDialogRestorer.restore(); drawOptions(); display.render( emptyDialogRestorer.rect() ); }; display.render(); bool isTextSupportModeEnabled = conf.isTextSupportModeEnabled(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.MouseClickLeft( windowLanguageRoi ) ) { return DialogAction::Language; } if ( le.MouseClickLeft( windowGraphicsRoi ) ) { return DialogAction::Graphics; } if ( le.MouseClickLeft( windowAudioRoi ) ) { return DialogAction::AudioSettings; } if ( le.MouseClickLeft( windowHeroSpeedRoi ) ) { saveConfiguration = true; conf.SetHeroesMoveSpeed( conf.HeroesMoveSpeed() % 10 + 1 ); Game::UpdateGameSpeed(); refreshWindow(); continue; } if ( le.isMouseWheelUpInArea( windowHeroSpeedRoi ) ) { saveConfiguration = true; conf.SetHeroesMoveSpeed( conf.HeroesMoveSpeed() + 1 ); Game::UpdateGameSpeed(); refreshWindow(); continue; } if ( le.isMouseWheelDownInArea( windowHeroSpeedRoi ) ) { saveConfiguration = true; conf.SetHeroesMoveSpeed( conf.HeroesMoveSpeed() - 1 ); Game::UpdateGameSpeed(); refreshWindow(); continue; } if ( le.MouseClickLeft( windowEnemySpeedRoi ) ) { saveConfiguration = true; conf.SetAIMoveSpeed( ( conf.AIMoveSpeed() + 1 ) % 11 ); Game::UpdateGameSpeed(); refreshWindow(); continue; } if ( le.isMouseWheelUpInArea( windowEnemySpeedRoi ) ) { saveConfiguration = true; conf.SetAIMoveSpeed( conf.AIMoveSpeed() + 1 ); Game::UpdateGameSpeed(); refreshWindow(); continue; } if ( le.isMouseWheelDownInArea( windowEnemySpeedRoi ) ) { saveConfiguration = true; conf.SetAIMoveSpeed( conf.AIMoveSpeed() - 1 ); Game::UpdateGameSpeed(); refreshWindow(); continue; } if ( le.MouseClickLeft( windowHotKeyRoi ) ) { return DialogAction::HotKeys; } if ( le.MouseClickLeft( windowInterfaceRoi ) ) { return DialogAction::InterfaceSettings; } if ( le.MouseClickLeft( windowTextSupportModeRoi ) ) { saveConfiguration = true; conf.setTextSupportMode( !conf.isTextSupportModeEnabled() ); refreshWindow(); continue; } if ( le.MouseClickLeft( windowBattlesRoi ) ) { saveConfiguration = true; if ( conf.BattleAutoResolve() ) { if ( conf.BattleAutoSpellcast() ) { conf.setBattleAutoSpellcast( false ); } else { conf.setBattleAutoResolve( false ); } } else { conf.setBattleAutoResolve( true ); conf.setBattleAutoSpellcast( true ); } refreshWindow(); continue; } if ( le.isMouseRightButtonPressedInArea( windowLanguageRoi ) ) { fheroes2::showStandardTextMessage( _( "Select Game Language" ), _( "Change the language of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowGraphicsRoi ) ) { fheroes2::showStandardTextMessage( _( "Graphics" ), _( "Change the graphics settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowAudioRoi ) ) { fheroes2::showStandardTextMessage( _( "Audio" ), _( "Change the audio settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowHeroSpeedRoi ) ) { fheroes2::showStandardTextMessage( _( "Hero Speed" ), _( "Change the speed at which your heroes move on the main screen." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowEnemySpeedRoi ) ) { fheroes2::showStandardTextMessage( _( "Enemy Speed" ), _( "Sets the speed that computer heroes move at. You can also elect not to view computer movement at all." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowHotKeyRoi ) ) { fheroes2::showStandardTextMessage( _( "Hot Keys" ), _( "Check and configure all the hot keys present in the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowInterfaceRoi ) ) { fheroes2::showStandardTextMessage( _( "Interface Settings" ), _( "Change the interface settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowTextSupportModeRoi ) ) { fheroes2::showStandardTextMessage( _( "Text Support" ), _( "Toggle text support mode to output extra information about windows and events in the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowBattlesRoi ) ) { fheroes2::showStandardTextMessage( _( "Battles" ), _( "Toggle instant battle mode." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } // Text support mode can be toggled using a global hotkey, we need to properly reflect this change in the UI if ( isTextSupportModeEnabled != conf.isTextSupportModeEnabled() ) { isTextSupportModeEnabled = conf.isTextSupportModeEnabled(); refreshWindow(); } } return DialogAction::Close; } } namespace fheroes2 { void showSystemOptionsDialog() { // We should make file writing only once. bool saveConfiguration = false; Settings & conf = Settings::Get(); auto redrawAdventureMap = []() { Interface::AdventureMap & adventureMap = Interface::AdventureMap::Get(); // Since radar interface has a restorer we must redraw it first to avoid the restorer do some nasty work. adventureMap.redraw( Interface::REDRAW_RADAR ); adventureMap.redraw( Interface::REDRAW_ALL & ( ~Interface::REDRAW_RADAR ) ); }; auto rebildAdventureMap = [&redrawAdventureMap]() { Interface::AdventureMap::Get().reset(); redrawAdventureMap(); }; DialogAction action = DialogAction::Configuration; while ( action != DialogAction::Close ) { switch ( action ) { case DialogAction::Configuration: action = openSystemOptionsDialog( saveConfiguration ); break; case DialogAction::Language: { const std::vector supportedLanguages = getSupportedLanguages(); if ( supportedLanguages.size() > 1 ) { selectLanguage( supportedLanguages, getLanguageFromAbbreviation( conf.getGameLanguage() ), true ); } else { assert( supportedLanguages.front() == SupportedLanguage::English ); conf.setGameLanguage( getLanguageAbbreviation( SupportedLanguage::English ) ); fheroes2::showStandardTextMessage( "Attention", "Your version of Heroes of Might and Magic II does not support any other languages than English.", Dialog::OK ); } // We can redraw only status window as it is the only place that has text but to be safe let's redraw everything. redrawAdventureMap(); saveConfiguration = true; action = DialogAction::Configuration; break; } case DialogAction::Graphics: saveConfiguration |= fheroes2::openGraphicsSettingsDialog( rebildAdventureMap ); action = DialogAction::Configuration; break; case DialogAction::AudioSettings: saveConfiguration |= Dialog::openAudioSettingsDialog( true ); action = DialogAction::Configuration; break; case DialogAction::HotKeys: fheroes2::openHotkeysDialog(); action = DialogAction::Configuration; break; case DialogAction::InterfaceSettings: saveConfiguration |= fheroes2::openInterfaceSettingsDialog( rebildAdventureMap ); action = DialogAction::Configuration; break; default: break; } } if ( saveConfiguration ) { conf.Save( Settings::configFileName ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_system_options.h000066400000000000000000000030021476115357100245120ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace fheroes2 { void showSystemOptionsDialog(); } fheroes2-1.1.6+dfsg/src/fheroes2/dialog/dialog_thievesguild.cpp000066400000000000000000000472231476115357100244570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "castle.h" #include "color.h" #include "cursor.h" #include "dialog.h" // IWYU pragma: associated #include "game.h" #include "game_hotkeys.h" #include "heroes.h" #include "heroes_base.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "math_base.h" #include "monster.h" #include "mp2.h" #include "players.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" namespace { struct ValueColors : std::pair { ValueColors( int value, int color ) : std::pair( value, color ) {} static bool SortValueGreat( const ValueColors & v1, const ValueColors & v2 ) { return v1.first > v2.first; } }; void UpdateValuesColors( std::vector & v, int value, int color ) { const auto it = std::find_if( v.begin(), v.end(), [value]( const ValueColors & vc ) { return vc.first == value; } ); if ( it == v.end() ) { v.emplace_back( value, color ); } else { ( *it ).second |= color; } } void getInfo( std::vector & v, const Colors & colors, const std::function & getValue ) { // 'getValue' should contain a callable function. assert( getValue ); v.clear(); for ( const int color : colors ) { UpdateValuesColors( v, getValue( color ), color ); } std::sort( v.begin(), v.end(), ValueColors::SortValueGreat ); } int getWoodOreValue( const int color ) { const Funds & funds = world.GetKingdom( color ).GetFunds(); return funds.Get( Resource::WOOD ) + funds.Get( Resource::ORE ); } int getGemsCrSlfMerValue( const int color ) { const Funds & funds = world.GetKingdom( color ).GetFunds(); return funds.Get( Resource::GEMS ) + funds.Get( Resource::CRYSTAL ) + funds.Get( Resource::SULFUR ) + funds.Get( Resource::MERCURY ); } void drawFlags( const std::vector & v, const fheroes2::Point & pos, const int32_t step, const size_t count, fheroes2::Image & output ) { const size_t flagGroups = std::min( count, v.size() ); if ( flagGroups == 0 ) { return; } const int32_t sptireWidth = fheroes2::AGG::GetICN( ICN::TOWNWIND, 22 ).width(); const int32_t offsetY = pos.y - 4; for ( size_t i = 0; i < flagGroups; ++i ) { const Colors colors( v[i].second ); int32_t offsetX = pos.x + static_cast( i ) * step - ( static_cast( colors.size() ) * sptireWidth ) / 2 + 3; for ( const int color : colors ) { const fheroes2::Sprite & flag = fheroes2::AGG::GetICN( ICN::TOWNWIND, 22 + Color::GetIndex( color ) ); fheroes2::Blit( flag, output, offsetX, offsetY ); offsetX += sptireWidth; } } } void drawHeroStats( const Heroes * hero, const int32_t offsetX, int32_t offsetY, fheroes2::Image & output ) { fheroes2::Text text( _( "Att." ), fheroes2::FontType::smallWhite() ); text.draw( offsetX, offsetY, output ); text.set( std::to_string( hero->GetAttack() ), fheroes2::FontType::smallWhite() ); text.draw( offsetX + 50 - text.width(), offsetY, output ); offsetY += 11; text.set( _( "Def." ), fheroes2::FontType::smallWhite() ); text.draw( offsetX, offsetY, output ); text.set( std::to_string( hero->GetDefense() ), fheroes2::FontType::smallWhite() ); text.draw( offsetX + 50 - text.width(), offsetY, output ); offsetY += 11; text.set( _( "Power" ), fheroes2::FontType::smallWhite() ); text.draw( offsetX, offsetY, output ); text.set( std::to_string( hero->GetPower() ), fheroes2::FontType::smallWhite() ); text.draw( offsetX + 50 - text.width(), offsetY, output ); offsetY += 11; text.set( _( "Knowl" ), fheroes2::FontType::smallWhite() ); text.draw( offsetX, offsetY, output ); text.set( std::to_string( hero->GetKnowledge() ), fheroes2::FontType::smallWhite() ); text.draw( offsetX + 50 - text.width(), offsetY, output ); } void drawHeroIcons( const Colors & colors, const bool drawStats, const fheroes2::Point & pos, const int32_t step, const int frameIcnID, fheroes2::Image & output ) { int32_t offsetX = pos.x + 1; for ( const int color : colors ) { const Heroes * hero = world.GetKingdom( color ).GetBestHero(); if ( hero == nullptr ) { offsetX += step; continue; } const fheroes2::Sprite & window = fheroes2::AGG::GetICN( frameIcnID, 22 ); fheroes2::Blit( window, output, offsetX - window.width() / 2, pos.y - 4 ); const fheroes2::Sprite & icon = hero->GetPortrait( PORT_SMALL ); fheroes2::Copy( icon, 0, 0, output, offsetX - icon.width() / 2, pos.y, icon.width(), icon.height() ); if ( drawStats ) { drawHeroStats( hero, offsetX - 26, pos.y + 34, output ); } offsetX += step; } } void drawPersonality( const Colors & colors, const fheroes2::Point & pos, const int32_t step, fheroes2::Image & output ) { int32_t offsetX = pos.x; for ( const int color : colors ) { const Player * player = Players::Get( color ); const fheroes2::Text text( player->isControlHuman() ? _( "Human" ) : player->GetPersonalityString(), fheroes2::FontType::smallWhite() ); text.draw( offsetX - text.width() / 2, pos.y, output ); offsetX += step; } } void drawBestMonsterIcons( const Colors & colors, const fheroes2::Point & pos, const int32_t step, fheroes2::Image & output ) { int32_t offsetX = pos.x; for ( const int color : colors ) { const Monster monster = world.GetKingdom( color ).GetStrongestMonster(); if ( monster.isValid() ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::MONS32, monster.GetSpriteIndex() ); fheroes2::Blit( sprite, output, offsetX - sprite.width() / 2, pos.y - sprite.height() / 2 ); } offsetX += step; } } const char * getPlayerOrderString( const size_t player ) { switch ( player ) { case 0: return _( "1st" ); case 1: return _( "2nd" ); case 2: return _( "3rd" ); case 3: return _( "4th" ); case 4: return _( "5th" ); case 5: return _( "6th" ); default: // The engine supports up to 6 players. Check your logic! assert( 0 ); } return {}; } } void Dialog::ThievesGuild( const bool oracle ) { // Set the cursor image.This dialog does not require a cursor restorer. It is called from other dialogs that have the same cursor // or from the Game Area that will set the appropriate cursor after this dialog is closed. Cursor::Get().SetThemes( Cursor::POINTER ); fheroes2::Rect dialogRoi; fheroes2::Rect dialogWithShadowRoi; std::unique_ptr background; std::unique_ptr restorer; fheroes2::Display & display = fheroes2::Display::instance(); if ( oracle ) { // We open a new dialog window for the Oracle. background = std::make_unique( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, false ); dialogRoi = background->activeArea(); dialogWithShadowRoi = background->totalArea(); } else { // The Thieves Guild dialog is opened from the castle dialog. We do not need to make a new dialog window. dialogRoi = { ( display.width() - fheroes2::Display::DEFAULT_WIDTH ) / 2, ( display.height() - fheroes2::Display::DEFAULT_HEIGHT ) / 2, fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT }; restorer = std::make_unique( display, dialogRoi.x, dialogRoi.y, dialogRoi.width, dialogRoi.height ); } // Fade-out game screen only for 640x480 resolution and if 'renderBackgroundDialog' is false (we are replacing image in already opened dialog). const bool isDefaultScreenSize = display.isDefaultSize(); if ( isDefaultScreenSize || !oracle ) { fheroes2::fadeOutDisplay( dialogRoi, !isDefaultScreenSize ); } const bool isEvilInterfaceTown = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & backgroundSprite = fheroes2::AGG::GetICN( isEvilInterfaceTown ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ); fheroes2::Copy( backgroundSprite, 0, 0, display, dialogRoi.x, dialogRoi.y, backgroundSprite.width(), backgroundSprite.height() ); const uint32_t thievesGuildCount = oracle ? 0xFF : world.GetKingdom( Settings::Get().CurrentColor() ).GetCountBuilding( BUILD_THIEVESGUILD ); std::vector valuesForPlayerColors; const Colors colors( Game::GetActualKingdomColors() ); const size_t playersCount = colors.size(); valuesForPlayerColors.reserve( playersCount ); const int32_t textOffsetX = dialogRoi.x + 207; const int32_t startOffsetX = dialogRoi.x + 264; const int32_t stepX = 68; fheroes2::Text text; fheroes2::Point offset( startOffsetX, dialogRoi.y + 3 ); for ( size_t player = 0; player < playersCount; ++player ) { text.set( getPlayerOrderString( player ), fheroes2::FontType::normalWhite() ); text.draw( offset.x - text.width() / 2, offset.y, display ); offset.x += stepX; } // Status bar. const int32_t exitWidth = fheroes2::AGG::GetICN( ICN::BUTTON_GUILDWELL_EXIT, 0 ).width(); const int32_t bottomBarOffsetY = 461; const fheroes2::Sprite & bottomBar = fheroes2::AGG::GetICN( ICN::SMALLBAR, 0 ); const int32_t barHeight = bottomBar.height(); offset.y = dialogRoi.y + bottomBarOffsetY; // ICN::SMALLBAR image's first column contains all black pixels. This should not be drawn. fheroes2::Copy( bottomBar, 1, 0, display, dialogRoi.x, offset.y, fheroes2::Display::DEFAULT_WIDTH / 2, barHeight ); fheroes2::Copy( bottomBar, bottomBar.width() - fheroes2::Display::DEFAULT_WIDTH / 2 + exitWidth - 1, 0, display, dialogRoi.x + fheroes2::Display::DEFAULT_WIDTH / 2, offset.y, fheroes2::Display::DEFAULT_WIDTH / 2 - exitWidth + 1, barHeight ); // Exit button. offset.x = dialogRoi.x + fheroes2::Display::DEFAULT_WIDTH - exitWidth; fheroes2::Button buttonExit( offset.x, offset.y, ICN::BUTTON_GUILDWELL_EXIT, 0, 1 ); // Text on status bar. text.set( oracle ? _( "Oracle: Player Rankings" ) : _( "Thieves' Guild: Player Rankings" ), fheroes2::FontType::normalWhite() ); offset.x = dialogRoi.x + ( fheroes2::Display::DEFAULT_WIDTH - exitWidth - text.width() ) / 2; text.draw( offset.x, dialogRoi.y + 464, display ); text.set( _( "Number of Towns:" ), fheroes2::FontType::normalWhite() ); offset.y = dialogRoi.y + 31; text.draw( textOffsetX - text.width(), offset.y, display ); offset.x = startOffsetX; getInfo( valuesForPlayerColors, colors, []( const int color ) { return static_cast( world.GetKingdom( color ).GetCountTown() ); } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); text.set( _( "Number of Castles:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); getInfo( valuesForPlayerColors, colors, []( const int color ) { return static_cast( world.GetKingdom( color ).GetCountCastle() ); } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); text.set( _( "Number of Heroes:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); getInfo( valuesForPlayerColors, colors, []( const int color ) { return static_cast( world.GetKingdom( color ).GetHeroes().size() ); } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); text.set( _( "Gold in Treasury:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); if ( thievesGuildCount > 1 ) { getInfo( valuesForPlayerColors, colors, []( const int color ) { return world.GetKingdom( color ).GetFunds().Get( Resource::GOLD ); } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); } text.set( _( "Wood & Ore:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); if ( thievesGuildCount > 1 ) { getInfo( valuesForPlayerColors, colors, getWoodOreValue ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); } text.set( _( "Gems, Cr, Slf & Mer:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); if ( thievesGuildCount > 2 ) { getInfo( valuesForPlayerColors, colors, getGemsCrSlfMerValue ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); } text.set( _( "Obelisks Found:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); if ( thievesGuildCount > 2 ) { getInfo( valuesForPlayerColors, colors, []( const int color ) { return static_cast( world.GetKingdom( color ).CountVisitedObjects( MP2::OBJ_OBELISK ) ); } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); } text.set( _( "Artifacts:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); if ( thievesGuildCount > 3 ) { getInfo( valuesForPlayerColors, colors, []( const int color ) { return static_cast( world.GetKingdom( color ).GetCountArtifacts() ); } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); } text.set( _( "Total Army Strength:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); if ( thievesGuildCount > 3 ) { getInfo( valuesForPlayerColors, colors, []( const int color ) { return static_cast( world.GetKingdom( color ).GetArmiesStrength() ); } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); } text.set( _( "Income:" ), fheroes2::FontType::normalWhite() ); offset.y += 24; text.draw( textOffsetX - text.width(), offset.y, display ); if ( thievesGuildCount > 4 ) { getInfo( valuesForPlayerColors, colors, []( const int color ) { return world.GetKingdom( color ).GetIncome().gold; } ); drawFlags( valuesForPlayerColors, offset, stepX, playersCount, display ); } // Render color's names for each player. offset.y += 24; bool shiftVertically = false; for ( const int color : colors ) { text.set( Color::String( color ), fheroes2::FontType::normalWhite() ); text.draw( offset.x - text.width() / 2, shiftVertically ? ( offset.y + 15 ) : offset.y, display ); offset.x += stepX; shiftVertically = !shiftVertically; } text.set( _( "Best Hero:" ), fheroes2::FontType::normalWhite() ); offset.y += 38; text.draw( textOffsetX - text.width(), offset.y, display ); offset.x = startOffsetX; offset.y -= 4; const int frameIcnID = isEvilInterfaceTown ? ICN::LOCATORE : ICN::LOCATORS; drawHeroIcons( colors, thievesGuildCount > 1, offset, stepX, frameIcnID, display ); text.set( _( "Best Hero Stats:" ), fheroes2::FontType::normalWhite() ); offset.y += 47; text.draw( textOffsetX - text.width(), offset.y, display ); text.set( _( "Personality:" ), fheroes2::FontType::normalWhite() ); offset.y += 42; text.draw( textOffsetX - text.width(), offset.y, display ); offset.y += 3; if ( thievesGuildCount > 2 ) { drawPersonality( colors, offset, stepX, display ); } text.set( _( "Best Monster:" ), fheroes2::FontType::normalWhite() ); offset.y += 32; text.draw( textOffsetX - text.width(), offset.y, display ); offset.y += text.height() / 2; if ( thievesGuildCount > 3 ) { drawBestMonsterIcons( colors, offset, stepX, display ); } buttonExit.draw(); // Fade-in thieves guild dialog. if ( oracle && !isDefaultScreenSize ) { // We need to expand the ROI for the next render to properly render window borders and shadow. display.updateNextRenderRoi( dialogWithShadowRoi ); } // Use half fade if game resolution is not 640x480. fheroes2::fadeInDisplay( dialogRoi, !isDefaultScreenSize ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), Dialog::ZERO ); } } // Fade-out dialog. fheroes2::fadeOutDisplay( dialogRoi, !isDefaultScreenSize ); if ( oracle ) { // Fade-in game screen only for 640x480 resolution. if ( isDefaultScreenSize ) { Game::setDisplayFadeIn(); } else { display.updateNextRenderRoi( dialogWithShadowRoi ); } } else { restorer->restore(); fheroes2::fadeInDisplay( dialogRoi, !isDefaultScreenSize ); } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/000077500000000000000000000000001476115357100177575ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_castle_details_window.cpp000066400000000000000000000766541476115357100264220ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_castle_details_window.h" #include #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "army_bar.h" #include "buildinginfo.h" #include "castle.h" #include "castle_building_info.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "editor_ui_helper.h" #include "game_hotkeys.h" #include "game_language.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "map_format_helper.h" #include "map_format_info.h" #include "math_base.h" #include "pal.h" #include "race.h" #include "screen.h" #include "settings.h" #include "statusbar.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" namespace { class BuildingData { public: explicit BuildingData( BuildingType buildingType, const int race, const BuildingType builtBuildings, const BuildingType restrictedBuildings ) : _mainBuildingType( buildingType ) , _race( race ) { if ( builtBuildings & _mainBuildingType ) { _builtId = 0; } else if ( restrictedBuildings & _mainBuildingType ) { _restrictedId = 0; } for ( BuildingType upgradedBuildingType = fheroes2::getUpgradeForBuilding( _race, _mainBuildingType ); upgradedBuildingType != buildingType; upgradedBuildingType = fheroes2::getUpgradeForBuilding( _race, upgradedBuildingType ) ) { if ( builtBuildings & upgradedBuildingType ) { _builtId = _buildingVariants; } else if ( restrictedBuildings & upgradedBuildingType ) { _restrictedId = _buildingVariants; } ++_buildingVariants; buildingType = upgradedBuildingType; } } void setPosition( const int32_t posX, const int32_t posY ) { _area.x = posX; _area.y = posY; _buildArea.x = posX; _buildArea.y = posY; _banArea.x = posX + _buildArea.width; _banArea.y = posY; } void resetBuilding() { _builtId = -1; _restrictedId = -1; } const fheroes2::Rect & getArea() const { return _area; } std::vector getBuildLevel() const { if ( _builtId < 0 ) { return {}; } const int8_t levelsBuilt = _builtId + 1; std::vector buildings; buildings.reserve( levelsBuilt ); for ( int8_t i = 0; i < levelsBuilt; ++i ) { buildings.push_back( _getBuildingType( i ) ); } return buildings; } BuildingType getRestrictLevel() const { return _getBuildingType( _restrictedId ); } bool queueEventProcessing( const bool restrictionMode ) { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( _area ) ) { if ( restrictionMode ) { if ( _restrictedId <= -1 ) { _restrictedId = _buildingVariants; } --_restrictedId; if ( _builtId != -1 && _builtId >= _restrictedId ) { _builtId = _restrictedId - 1; } } else { ++_builtId; if ( _builtId >= _buildingVariants ) { _builtId = -1; } else if ( _restrictedId != -1 && _builtId >= _restrictedId ) { _restrictedId = ( _builtId < _buildingVariants - 1 ) ? _builtId + 1 : -1; } } return true; } if ( le.isMouseRightButtonPressedInArea( _area ) ) { const BuildingType building = _getBuildindTypeForRender(); std::string description = BuildingInfo::getBuildingDescription( _race, building ); const std::string requirement = fheroes2::getBuildingRequirementString( _race, building ); if ( !requirement.empty() ) { description += "\n\n"; description += _( "Requires:" ); description += "\n"; description += requirement; } fheroes2::showStandardTextMessage( Castle::GetStringBuilding( building, _race ), std::move( description ), Dialog::ZERO ); } return false; } std::string getSetStatusMessage() const { return fheroes2::getBuildingName( _race, _getBuildindTypeForRender() ); } void redraw( const bool isNotDefault ) const { fheroes2::Display & display = fheroes2::Display::instance(); const int index = fheroes2::getIndexBuildingSprite( _getBuildindTypeForRender() ); const int buildingIcnId = ICN::getBuildingIcnId( _race ); const fheroes2::Sprite & buildingImage = ( buildingIcnId == ICN::UNKNOWN ) ? fheroes2::AGG::GetICN( Settings::Get().isEvilInterfaceEnabled() ? ICN::CASLXTRA_EVIL : ICN::CASLXTRA, 0 ) : fheroes2::AGG::GetICN( buildingIcnId, index ); const fheroes2::Rect buildingImageRoi( _area.x + 1, _area.y + 1, 135, 57 ); if ( isNotDefault ) { fheroes2::Copy( buildingImage, 0, 0, display, buildingImageRoi ); } else { // Apply the blur effect originally used for the Holy Shout spell. fheroes2::Copy( fheroes2::CreateHolyShoutEffect( buildingImage, 1, 0 ), 0, 0, display, buildingImageRoi ); fheroes2::ApplyPalette( display, buildingImageRoi.x, buildingImageRoi.y, display, buildingImageRoi.x, buildingImageRoi.y, buildingImageRoi.width, buildingImageRoi.height, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); } // Build and restrict status indicator. const int32_t maxUpgrades = static_cast( _buildingVariants ); for ( int32_t i = 0; i < maxUpgrades; ++i ) { if ( _restrictedId != -1 && i >= _restrictedId ) { // Render the restricted sign: gray cross. fheroes2::Sprite denySign( fheroes2::AGG::GetICN( ICN::TOWNWIND, 12 ) ); fheroes2::ApplyPalette( denySign, PAL::CombinePalettes( PAL::GetPalette( PAL::PaletteType::GRAY ), PAL::GetPalette( PAL::PaletteType::DARKENING ) ) ); fheroes2::Blit( denySign, display, _area.x + _area.width - ( maxUpgrades - i ) * 20 - denySign.width() / 2, _area.y + 48 - denySign.height() / 2 ); continue; } const int icnId = ( i > _builtId ) ? ICN::CELLWIN : ICN::TOWNWIND; const uint32_t icnIndex = ( i > _builtId ) ? 5 : 11; const fheroes2::Sprite & mark = fheroes2::AGG::GetICN( icnId, icnIndex ); fheroes2::Blit( mark, display, _area.x + _area.width - ( maxUpgrades - i ) * 20 - mark.width() / 2, _area.y + 48 - mark.height() / 2 ); } if ( _builtId > -1 ) { const fheroes2::Sprite & textBackground = fheroes2::AGG::GetICN( ICN::BLDGXTRA, 0 ); fheroes2::Copy( textBackground, 0, 58, display, _area.x, _area.y + 58, _area.width, textBackground.height() ); } else if ( _restrictedId != 0 ) { const fheroes2::Sprite & textBackground = fheroes2::AGG::GetICN( ICN::CASLXTRA, 1 ); fheroes2::Copy( textBackground, 0, 0, display, _area.x, _area.y + 58, _area.width, textBackground.height() ); } if ( _restrictedId > -1 ) { fheroes2::Sprite textBackground( fheroes2::AGG::GetICN( ICN::CASLXTRA, 2 ) ); fheroes2::ApplyPalette( textBackground, 6, 1, textBackground, 6, 1, 125, 12, PAL::CombinePalettes( PAL::GetPalette( PAL::PaletteType::GRAY ), PAL::GetPalette( PAL::PaletteType::DARKENING ) ) ); if ( _restrictedId == 0 ) { fheroes2::Copy( textBackground, 0, 0, display, _area.x, _area.y + 58, _area.width - 5, textBackground.height() ); } else { fheroes2::CreateDitheringTransition( textBackground, _buildArea.width - 5, 0, display, _banArea.x - 5, _area.y + 58, 10, textBackground.height(), true, false ); fheroes2::Copy( textBackground, _buildArea.width + 5, 0, display, _banArea.x + 5, _area.y + 58, _banArea.width - 5, textBackground.height() ); } } if ( !isNotDefault ) { // Make the header darker for the default buildings. fheroes2::ApplyPalette( display, _area.x + 6, _area.y + 59, display, _area.x + 6, _area.y + 59, 125, 12, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); } const fheroes2::Text buildingName( Castle::GetStringBuilding( _getBuildindTypeForRender(), _race ), fheroes2::FontType::smallWhite() ); buildingName.draw( _area.x + 68 - buildingName.width() / 2, _area.y + 61, display ); } private: BuildingType _getBuildindTypeForRender() const { if ( _builtId < 1 ) { return _mainBuildingType; } return _getBuildingType( _builtId ); } BuildingType _getBuildingType( const int8_t level ) const { if ( level < 0 ) { return BUILD_NOTHING; } BuildingType building = _mainBuildingType; for ( int8_t i = 0; i < level; ++i ) { building = fheroes2::getUpgradeForBuilding( _race, building ); } return building; } BuildingType _mainBuildingType{ BUILD_NOTHING }; int _race{ Race::NONE }; int8_t _builtId{ -1 }; int8_t _restrictedId{ -1 }; int8_t _buildingVariants{ 1 }; fheroes2::Rect _area{ 0, 0, 137, 70 }; fheroes2::Rect _buildArea{ 0, 0, 69, 70 }; fheroes2::Rect _banArea{ 0, 0, 68, 70 }; }; } namespace Editor { void castleDetailsDialog( Maps::Map_Format::CastleMetadata & castleMetadata, const int race, const int color, const fheroes2::SupportedLanguage language ) { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::StandardWindow background( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, false ); const fheroes2::Rect dialogRoi = background.activeArea(); const fheroes2::Rect dialogWithShadowRoi = background.totalArea(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & constructionBackground = fheroes2::AGG::GetICN( isEvilInterface ? ICN::CASLWIND_EVIL : ICN::CASLWIND, 0 ); const int32_t backgroundHeight = constructionBackground.height(); // Use the left part of town construction dialog. const int32_t rightPartOffsetX = 438; const int32_t rightPartWidth = dialogRoi.width - rightPartOffsetX; fheroes2::Blit( constructionBackground, 0, 0, display, dialogRoi.x, dialogRoi.y, rightPartOffsetX, backgroundHeight ); // Use the right part of standard background dialog. fheroes2::Copy( fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ), rightPartOffsetX, 0, display, dialogRoi.x + rightPartOffsetX, dialogRoi.y, rightPartWidth, backgroundHeight ); // Add horizontal separators. fheroes2::Copy( constructionBackground, rightPartOffsetX, 251, display, dialogRoi.x + rightPartOffsetX, dialogRoi.y + 226, rightPartWidth, 4 ); fheroes2::Copy( constructionBackground, rightPartOffsetX, 251, display, dialogRoi.x + rightPartOffsetX, dialogRoi.y + 306, rightPartWidth, 4 ); // Castle name background. const fheroes2::Sprite & statusBarSprite = fheroes2::AGG::GetICN( ICN::CASLBAR, 0 ); const fheroes2::Rect nameArea( dialogRoi.x + rightPartOffsetX, dialogRoi.y + 1, rightPartWidth, statusBarSprite.height() - 2 ); fheroes2::Copy( statusBarSprite, 17, 0, display, nameArea.x, dialogRoi.y, nameArea.width, statusBarSprite.height() ); const bool isTown = std::find( castleMetadata.builtBuildings.begin(), castleMetadata.builtBuildings.end(), BUILD_CASTLE ) == castleMetadata.builtBuildings.end(); // Castle name text. auto drawCastleName = [&castleMetadata, &display, &nameArea, isTown]() { // TODO: use language for castle name. At the moment it is disabled. fheroes2::Text text( castleMetadata.customName, fheroes2::FontType::normalWhite() ); if ( castleMetadata.customName.empty() ) { text.set( isTown ? _( "Random Town Name" ) : _( "Random Castle Name" ), fheroes2::FontType::normalWhite() ); } text.fitToOneRow( nameArea.width ); text.drawInRoi( nameArea.x + ( nameArea.width - text.width() ) / 2, nameArea.y + 2, display, nameArea ); }; drawCastleName(); // Allow castle building checkbox. fheroes2::Point dstPt( dialogRoi.x + rightPartOffsetX + 10, dialogRoi.y + 130 ); fheroes2::MovableSprite allowCastleSign; fheroes2::Rect allowCastleArea; if ( isTown ) { allowCastleArea = drawCheckboxWithText( allowCastleSign, _( "Allow Castle build" ), display, dstPt.x, dstPt.y, isEvilInterface, rightPartWidth - 10 ); if ( std::find( castleMetadata.bannedBuildings.begin(), castleMetadata.bannedBuildings.end(), BUILD_CASTLE ) == castleMetadata.bannedBuildings.end() ) { allowCastleSign.show(); } else { allowCastleSign.hide(); } } // Default buildings checkbox indicator. dstPt.y += 30; fheroes2::MovableSprite defaultBuildingsSign; const fheroes2::Rect defaultBuildingsArea = drawCheckboxWithText( defaultBuildingsSign, _( "Default Buildings" ), display, dstPt.x, dstPt.y, isEvilInterface, rightPartWidth - 10 ); castleMetadata.customBuildings ? defaultBuildingsSign.hide() : defaultBuildingsSign.show(); // Build restrict mode button. fheroes2::Button buttonRestrictBuilding( 0, 0, isEvilInterface ? ICN::BUTTON_RESTRICT_EVIL : ICN::BUTTON_RESTRICT_GOOD, 0, 1 ); buttonRestrictBuilding.setPosition( dialogRoi.x + rightPartOffsetX + ( rightPartWidth - buttonRestrictBuilding.area().width ) / 2, dialogRoi.y + 195 ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( ICN::BUTTON_RESTRICT_GOOD, 0 ), display, buttonRestrictBuilding.area().getPosition(), { -5, 5 } ); buttonRestrictBuilding.draw(); const bool isNeutral = ( color == Color::NONE ); // Castle army. dstPt.y = dialogRoi.y + 311; fheroes2::MovableSprite defaultArmySign; fheroes2::Rect defaultArmyArea; if ( isNeutral ) { defaultArmyArea = drawCheckboxWithText( defaultArmySign, _( "Default Army" ), display, dstPt.x, dstPt.y, isEvilInterface, rightPartWidth - 10 ); if ( Maps::isDefaultCastleDefenderArmy( castleMetadata ) ) { defaultArmySign.show(); } else { defaultArmySign.hide(); } } else { defaultArmySign.hide(); const fheroes2::Text armyText( isTown ? _( "Town Army" ) : _( "Castle Army" ), fheroes2::FontType::normalWhite() ); armyText.drawInRoi( dialogRoi.x + rightPartOffsetX + ( rightPartWidth - armyText.width() ) / 2, dstPt.y + 4, display, dialogRoi ); } Army castleArmy; // Load army from metadata. Maps::loadCastleArmy( castleArmy, castleMetadata ); ArmyBar armyBar( &castleArmy, true, false, true, false ); armyBar.setTableSize( { 3, 2 } ); armyBar.setCustomItemsCountInRow( { 2, 3 } ); armyBar.setInBetweenItemsOffset( { 3, 3 } ); armyBar.setRenderingOffset( { dialogRoi.x + rightPartOffsetX + 33, dialogRoi.y + 332 } ); armyBar.Redraw( display ); const BuildingType metadataBuildings = static_cast( Maps::getBuildingsFromVector( castleMetadata.builtBuildings ) ); const BuildingType metadataRestrictedBuildings = static_cast( Maps::getBuildingsFromVector( castleMetadata.bannedBuildings ) ); assert( ( metadataBuildings & metadataRestrictedBuildings ) == 0 ); const size_t buildingsSize = 19; std::array buildings{ BuildingData( DWELLING_MONSTER1, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( DWELLING_MONSTER2, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( DWELLING_MONSTER3, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( DWELLING_MONSTER4, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( DWELLING_MONSTER5, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( DWELLING_MONSTER6, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_MAGEGUILD1, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( race == Race::NECR ? BUILD_SHRINE : BUILD_TAVERN, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_THIEVESGUILD, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_SHIPYARD, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_STATUE, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_MARKETPLACE, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_WELL, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_WEL2, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_SPEC, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_LEFTTURRET, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_RIGHTTURRET, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_MOAT, race, metadataBuildings, metadataRestrictedBuildings ), BuildingData( BUILD_CAPTAIN, race, metadataBuildings, metadataRestrictedBuildings ) }; dstPt.x = dialogRoi.x + 5; dstPt.y = dialogRoi.y + 2; for ( size_t i = 0; i < buildingsSize - 1; ++i ) { buildings[i].setPosition( dstPt.x + ( static_cast( i ) % 3 ) * 144, dstPt.y ); buildings[i].redraw( defaultBuildingsSign.isHidden() ); if ( i % 3 == 2 ) { dstPt.y += ( i == 5 || i == 14 ) ? 80 : 75; } } // Captain building. dstPt.x = dialogRoi.x + rightPartOffsetX + 33; dstPt.y = dialogRoi.y + 232; const fheroes2::Sprite & buildingFrame = fheroes2::AGG::GetICN( ICN::BLDGXTRA, 0 ); fheroes2::Blit( buildingFrame, display, dstPt.x, dstPt.y ); buildings.back().setPosition( dstPt.x, dstPt.y ); buildings.back().redraw( defaultBuildingsSign.isHidden() ); // Exit button. fheroes2::Button buttonExit( dialogRoi.x + rightPartOffsetX + 50, dialogRoi.y + 430, isEvilInterface ? ICN::BUTTON_SMALL_EXIT_EVIL : ICN::BUTTON_SMALL_EXIT_GOOD, 0, 1 ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( ICN::BUTTON_SMALL_EXIT_GOOD, 0 ), display, buttonExit.area().getPosition(), { -2, 2 } ); buttonExit.draw(); // Status bar. const int32_t statusBarWidth = statusBarSprite.width(); const int32_t statusBarheight = statusBarSprite.height(); dstPt.y = dialogRoi.y + dialogRoi.height - statusBarheight; fheroes2::Copy( statusBarSprite, 0, 0, display, dialogRoi.x, dstPt.y, statusBarWidth, statusBarheight ); StatusBar statusBar; statusBar.setRoi( { dialogRoi.x, dstPt.y + 3, statusBarWidth, 0 } ); display.render( dialogWithShadowRoi ); LocalEvent & le = LocalEvent::Get(); std::string message; bool buildingRestriction = false; while ( le.HandleEvents() ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.MouseClickLeft( buttonRestrictBuilding.area() ) ) { buildingRestriction = !buildingRestriction; } buttonRestrictBuilding.drawOnState( buildingRestriction || le.isMouseLeftButtonPressedInArea( buttonRestrictBuilding.area() ) ); if ( le.isMouseCursorPosInArea( nameArea ) ) { message = _( "Click to change the Castle name. Right-click to reset to default." ); bool redrawName = false; if ( le.MouseClickLeft( nameArea ) ) { std::string res = castleMetadata.customName; // TODO: use the provided language to set the castle's name. (void)language; const fheroes2::Text body{ _( "Enter Castle name" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, res, 30, false, fheroes2::SupportedLanguage::English ) && !res.empty() ) { castleMetadata.customName = std::move( res ); redrawName = true; } } else if ( le.MouseClickRight( nameArea ) ) { castleMetadata.customName.clear(); redrawName = true; } if ( redrawName ) { // Restore name background fheroes2::Copy( statusBarSprite, 17, 1, display, nameArea ); drawCastleName(); display.render( nameArea ); } } else if ( isTown && le.isMouseCursorPosInArea( allowCastleArea ) ) { message = _( "Allow to build a castle in this town." ); if ( le.MouseClickLeft( allowCastleArea ) ) { allowCastleSign.isHidden() ? allowCastleSign.show() : allowCastleSign.hide(); display.render( allowCastleSign.getArea() ); } else if ( le.isMouseRightButtonPressedInArea( allowCastleArea ) ) { fheroes2::showStandardTextMessage( _( "Allow Castle build" ), message, Dialog::ZERO ); } } else if ( le.isMouseCursorPosInArea( defaultBuildingsArea ) ) { message = _( "Toggle the use of default buildings. Custom buildings will be reset!" ); if ( le.MouseClickLeft( defaultBuildingsArea ) ) { if ( defaultBuildingsSign.isHidden() ) { // Reset all buildings to their build and restrict default states. for ( BuildingData & building : buildings ) { building.resetBuilding(); building.redraw( false ); } defaultBuildingsSign.show(); display.render( dialogRoi ); } else { defaultBuildingsSign.hide(); for ( const BuildingData & building : buildings ) { building.redraw( true ); } display.render( dialogRoi ); } } else if ( le.isMouseRightButtonPressedInArea( defaultBuildingsArea ) ) { fheroes2::showStandardTextMessage( _( "Default Buildings" ), message, Dialog::ZERO ); } } else if ( le.isMouseCursorPosInArea( buttonRestrictBuilding.area() ) ) { message = _( "Toggle building construction restriction mode." ); if ( le.isMouseRightButtonPressedInArea( buttonRestrictBuilding.area() ) ) { fheroes2::showStandardTextMessage( _( "Restrict Building Construction" ), message, Dialog::ZERO ); } } else if ( isNeutral && le.isMouseCursorPosInArea( defaultArmyArea ) ) { message = _( "Use default defenders army." ); if ( le.MouseClickLeft( defaultArmyArea ) ) { if ( defaultArmySign.isHidden() ) { defaultArmySign.show(); castleArmy.Reset( false ); armyBar.Redraw( display ); display.render( dialogRoi ); } else { defaultArmySign.hide(); display.render( defaultArmySign.getArea() ); } } else if ( le.isMouseRightButtonPressedInArea( defaultArmyArea ) ) { fheroes2::showStandardTextMessage( _( "Default Army" ), message, Dialog::ZERO ); } } else if ( le.isMouseCursorPosInArea( armyBar.GetArea() ) ) { if ( armyBar.QueueEventProcessing( &message ) ) { armyBar.Redraw( display ); defaultArmySign.hide(); display.render( dialogRoi ); } if ( message.empty() ) { message = _( "Set custom Castle Army. Right-click to reset unit." ); } } else if ( le.isMouseCursorPosInArea( buttonExit.area() ) ) { message = _( "Exit Castle Options" ); if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), message, Dialog::ZERO ); } } else { for ( size_t i = 0; i < buildingsSize; ++i ) { if ( le.isMouseCursorPosInArea( buildings[i].getArea() ) ) { message = buildings[i].getSetStatusMessage(); if ( buildings[i].queueEventProcessing( buildingRestriction ) ) { if ( defaultBuildingsSign.isHidden() ) { buildings[i].redraw( true ); display.render( buildings[i].getArea() ); } else { // The building properties have been changed. Uncheck the default buildings checkbox. defaultBuildingsSign.hide(); for ( const BuildingData & building : buildings ) { building.redraw( true ); } display.render( dialogRoi ); } } break; } } } if ( message.empty() ) { statusBar.ShowMessage( _( "Castle Options" ) ); } else { statusBar.ShowMessage( std::move( message ) ); message.clear(); } } // Update army in metadata. if ( isNeutral && !defaultArmySign.isHidden() ) { Maps::setDefaultCastleDefenderArmy( castleMetadata ); } else { Maps::saveCastleArmy( castleArmy, castleMetadata ); } // Update buildings data. castleMetadata.builtBuildings.clear(); castleMetadata.bannedBuildings.clear(); // Build main buildings for town or castle. castleMetadata.builtBuildings.push_back( isTown ? BUILD_TENT : BUILD_CASTLE ); if ( isTown && allowCastleSign.isHidden() ) { castleMetadata.bannedBuildings.push_back( BUILD_CASTLE ); } castleMetadata.customBuildings = defaultBuildingsSign.isHidden(); if ( castleMetadata.customBuildings ) { for ( const BuildingData & building : buildings ) { std::vector buildingLevels = building.getBuildLevel(); std::move( buildingLevels.begin(), buildingLevels.end(), std::back_inserter( castleMetadata.builtBuildings ) ); if ( const BuildingType buildId = building.getRestrictLevel(); buildId != BUILD_NOTHING ) { castleMetadata.bannedBuildings.push_back( buildId ); } } } } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_castle_details_window.h000066400000000000000000000034171476115357100260520ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace Maps::Map_Format { struct CastleMetadata; } namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace Editor { void castleDetailsDialog( Maps::Map_Format::CastleMetadata & castleMetadata, const int race, const int color, const fheroes2::SupportedLanguage language ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_daily_event_spec_window.cpp000066400000000000000000000425221476115357100267420ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_daily_event_spec_window.h" #include #include #include #include #include #include #include #include #include #include "color.h" #include "cursor.h" #include "dialog.h" #include "editor_ui_helper.h" #include "game_hotkeys.h" #include "image.h" #include "localevent.h" #include "map_format_info.h" #include "math_base.h" #include "mp2.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_window.h" namespace { const std::array resourceTypes = { Resource::WOOD, Resource::SULFUR, Resource::CRYSTAL, Resource::MERCURY, Resource::ORE, Resource::GEMS, Resource::GOLD }; const fheroes2::Size messageArea{ 300, 210 }; const int32_t elementOffset{ 9 }; const int32_t playerAreaWidth{ fheroes2::Display::DEFAULT_WIDTH - fheroes2::borderWidthPx * 2 - 3 * elementOffset - messageArea.width }; const int32_t daysInYear{ 7 * 4 * 12 }; const int32_t lastDayForEvents{ daysInYear * 100 }; } namespace Editor { bool editDailyEvent( Maps::Map_Format::DailyEvent & eventMetadata, const uint8_t humanPlayerColors, const uint8_t computerPlayerColors, const fheroes2::SupportedLanguage language ) { // An event can be outdated in terms of players since we don't update players while placing or removing heroes and castles. eventMetadata.humanPlayerColors = eventMetadata.humanPlayerColors & humanPlayerColors; eventMetadata.computerPlayerColors = eventMetadata.computerPlayerColors & computerPlayerColors; // First occurrence day logically has no limits but we still have to check it for some human logical value. eventMetadata.firstOccurrenceDay = std::clamp( eventMetadata.firstOccurrenceDay, 1U, static_cast( lastDayForEvents ) ); eventMetadata.repeatPeriodInDays = std::min( eventMetadata.repeatPeriodInDays, static_cast( daysInYear ) ); const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); fheroes2::StandardWindow background( fheroes2::Display::DEFAULT_WIDTH - fheroes2::borderWidthPx * 2, messageArea.height + 220, true, display ); const fheroes2::Rect dialogRoi = background.activeArea(); int32_t offsetY = dialogRoi.y + elementOffset; const fheroes2::Text title( MP2::StringObject( MP2::OBJ_EVENT ), fheroes2::FontType::normalYellow() ); title.draw( dialogRoi.x + ( dialogRoi.width - title.width() ) / 2, offsetY, display ); offsetY += title.height() + elementOffset; fheroes2::Text text{ _( "Message Text:" ), fheroes2::FontType::normalWhite() }; const fheroes2::Rect messageRoi{ dialogRoi.x + elementOffset, offsetY + text.height(), messageArea.width, messageArea.height }; background.applyTextBackgroundShading( messageRoi ); fheroes2::ImageRestorer messageRoiRestorer( display, messageRoi.x, messageRoi.y, messageRoi.width, messageRoi.height ); text.draw( messageRoi.x + ( messageRoi.width - text.width() ) / 2, offsetY, display ); text.set( eventMetadata.message, fheroes2::FontType::normalWhite(), language ); text.drawInRoi( messageRoi.x + 5, messageRoi.y + 5, messageRoi.width - 10, display, messageRoi ); // Resources text.set( _( "Reward:" ), fheroes2::FontType::normalWhite() ); text.draw( messageRoi.x + ( messageRoi.width - text.width() ) / 2, offsetY + messageArea.height + 2 * elementOffset, display ); const fheroes2::Rect resourceRoi{ messageRoi.x, text.height() + offsetY + messageArea.height + 2 * elementOffset, messageRoi.width, 99 }; background.applyTextBackgroundShading( resourceRoi ); fheroes2::ImageRestorer resourceRoiRestorer( display, resourceRoi.x, resourceRoi.y, resourceRoi.width, resourceRoi.height ); std::array individualResourceRoi; renderResources( eventMetadata.resources, resourceRoi, display, individualResourceRoi ); const int32_t playerAreaOffsetX = dialogRoi.x + elementOffset + messageRoi.width + elementOffset; text.set( _( "Player colors allowed to get event:" ), fheroes2::FontType::normalWhite() ); int32_t textWidth = playerAreaWidth; // If the text fits on one line, make it span two lines. while ( text.rows( textWidth ) < 2 ) { textWidth = textWidth * 2 / 3; } text.draw( playerAreaOffsetX + ( playerAreaWidth - textWidth ) / 2, offsetY, textWidth, display ); offsetY += 3 + text.height( textWidth ); const int32_t availablePlayersCount = Color::Count( humanPlayerColors | computerPlayerColors ); const int32_t checkOffX = ( playerAreaWidth - availablePlayersCount * 32 ) / 2; std::vector> humanCheckboxes; createColorCheckboxes( humanCheckboxes, humanPlayerColors, eventMetadata.humanPlayerColors, playerAreaOffsetX + checkOffX, offsetY, display ); assert( humanCheckboxes.size() == static_cast( Color::Count( humanPlayerColors ) ) ); offsetY += 35; text.set( _( "Computer colors allowed to get event:" ), fheroes2::FontType::normalWhite() ); textWidth = playerAreaWidth; // If the text fits on one line, make it span two lines. while ( text.rows( textWidth ) < 2 ) { textWidth = textWidth * 2 / 3; } text.draw( playerAreaOffsetX + ( playerAreaWidth - textWidth ) / 2, offsetY, textWidth, display ); offsetY += 3 + text.height( textWidth ); std::vector> computerCheckboxes; createColorCheckboxes( computerCheckboxes, computerPlayerColors, eventMetadata.computerPlayerColors, playerAreaOffsetX + checkOffX, offsetY, display ); assert( computerCheckboxes.size() == static_cast( Color::Count( computerPlayerColors ) ) ); offsetY += 35; text.set( _( "First day of occurrence:" ), fheroes2::FontType::normalWhite() ); textWidth = playerAreaWidth; // If the text fits on one line, make it span two lines. while ( text.rows( textWidth ) < 2 ) { textWidth = textWidth * 2 / 3; } text.draw( playerAreaOffsetX + ( playerAreaWidth - textWidth ) / 2, offsetY, textWidth, display ); offsetY += 3 + text.height( textWidth ); const fheroes2::Point firstDayOccurrencePos{ playerAreaOffsetX + ( playerAreaWidth - fheroes2::ValueSelectionDialogElement::getArea().width ) / 2, offsetY }; fheroes2::ValueSelectionDialogElement firstDaySelection( 1, lastDayForEvents, static_cast( eventMetadata.firstOccurrenceDay ), 1, firstDayOccurrencePos ); firstDaySelection.draw( display ); offsetY += 10 + fheroes2::ValueSelectionDialogElement::getArea().height; fheroes2::ImageRestorer firstDateDescription( display, playerAreaOffsetX, offsetY, playerAreaWidth, 35 ); text.set( getDateDescription( firstDaySelection.getValue() ), fheroes2::FontType::normalWhite() ); text.draw( playerAreaOffsetX + ( playerAreaWidth - text.width() ) / 2, offsetY, text.width(), display ); offsetY += 35; text.set( _( "Repeat period (days):" ), fheroes2::FontType::normalWhite() ); textWidth = playerAreaWidth; // If the text fits on one line, make it span two lines. while ( text.rows( textWidth ) < 2 ) { textWidth = textWidth * 2 / 3; } text.draw( playerAreaOffsetX + ( playerAreaWidth - textWidth ) / 2, offsetY, textWidth, display ); offsetY += 3 + text.height( textWidth ); const fheroes2::Point repeatPeriodPos{ playerAreaOffsetX + ( playerAreaWidth - fheroes2::ValueSelectionDialogElement::getArea().width ) / 2, offsetY }; fheroes2::ValueSelectionDialogElement repeatPeriodSelection( 0, daysInYear, static_cast( eventMetadata.repeatPeriodInDays ), 1, repeatPeriodPos ); repeatPeriodSelection.draw( display ); // Window buttons fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); display.render( background.totalArea() ); bool isRedrawNeeded = false; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( firstDaySelection.processEvents() ) { firstDaySelection.draw( display ); eventMetadata.firstOccurrenceDay = static_cast( firstDaySelection.getValue() ); firstDateDescription.restore(); text.set( getDateDescription( firstDaySelection.getValue() ), fheroes2::FontType::normalWhite() ); text.draw( playerAreaOffsetX + ( playerAreaWidth - text.width() ) / 2, firstDateDescription.y(), text.width(), display ); isRedrawNeeded = true; } if ( repeatPeriodSelection.processEvents() ) { repeatPeriodSelection.draw( display ); eventMetadata.repeatPeriodInDays = static_cast( repeatPeriodSelection.getValue() ); isRedrawNeeded = true; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return false; } if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) ) { break; } for ( const auto & humanCheckbox : humanCheckboxes ) { const fheroes2::Rect & checkboxRect = humanCheckbox->getRect(); if ( le.MouseClickLeft( checkboxRect ) ) { const int color = humanCheckbox->getColor(); if ( humanCheckbox->toggle() ) { eventMetadata.humanPlayerColors |= color; } else { eventMetadata.humanPlayerColors ^= color; } break; } if ( le.isMouseRightButtonPressedInArea( checkboxRect ) ) { std::string header = _( "Allow %{color} human player to get event" ); std::string messageText = _( "If this checkbox is checked, this event will trigger for the %{color} player if they are controlled by a human." ); const std::string colorString = Color::String( humanCheckbox->getColor() ); StringReplace( header, "%{color}", colorString ); StringReplace( messageText, "%{color}", colorString ); fheroes2::showStandardTextMessage( std::move( header ), std::move( messageText ), Dialog::ZERO ); break; } } for ( const auto & computerCheckbox : computerCheckboxes ) { const fheroes2::Rect & checkboxRect = computerCheckbox->getRect(); if ( le.MouseClickLeft( checkboxRect ) ) { const int color = computerCheckbox->getColor(); if ( computerCheckbox->toggle() ) { eventMetadata.computerPlayerColors |= color; } else { eventMetadata.computerPlayerColors ^= color; } break; } if ( le.isMouseRightButtonPressedInArea( checkboxRect ) ) { std::string header = _( "Allow %{color} computer player to get event" ); std::string messageText = _( "If this checkbox is checked, this event will trigger for the %{color} player if they are controlled by a computer." ); const std::string colorString = Color::String( computerCheckbox->getColor() ); StringReplace( header, "%{color}", colorString ); StringReplace( messageText, "%{color}", colorString ); fheroes2::showStandardTextMessage( std::move( header ), std::move( messageText ), Dialog::ZERO ); break; } } for ( size_t i = 0; i < individualResourceRoi.size(); ++i ) { if ( le.MouseClickLeft( individualResourceRoi[i] ) ) { const int resourceType = resourceTypes[i]; int32_t * resourcePtr = eventMetadata.resources.GetPtr( resourceType ); assert( resourcePtr != nullptr ); int32_t temp = *resourcePtr; const fheroes2::ResourceDialogElement resourceUI( resourceType, {} ); std::string message = _( "Set %{resource-type} Count" ); StringReplace( message, "%{resource-type}", Resource::String( resourceType ) ); if ( Dialog::SelectCount( std::move( message ), -99999, 999999, temp, 1, &resourceUI ) ) { *resourcePtr = temp; } resourceRoiRestorer.restore(); renderResources( eventMetadata.resources, resourceRoi, display, individualResourceRoi ); display.render( resourceRoi ); break; } } if ( le.MouseClickLeft( messageRoi ) ) { std::string temp = eventMetadata.message; const fheroes2::Text body{ _( "Message:" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, temp, 200, true, language ) ) { eventMetadata.message = std::move( temp ); messageRoiRestorer.restore(); text.set( eventMetadata.message, fheroes2::FontType::normalWhite(), language ); text.drawInRoi( messageRoi.x + 5, messageRoi.y + 5, messageRoi.width - 10, display, messageRoi ); isRedrawNeeded = true; } } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to save the Event properties." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( resourceRoi ) ) { if ( eventMetadata.resources.GetValidItemsCount() == 0 ) { fheroes2::showStandardTextMessage( _( "Resources" ), _( "No resources will be given as a reward." ), Dialog::ZERO ); } else { fheroes2::showResourceMessage( fheroes2::Text( _( "Resources" ), fheroes2::FontType::normalYellow() ), fheroes2::Text{ _( "Resources will be given as a reward." ), fheroes2::FontType::normalWhite() }, Dialog::ZERO, eventMetadata.resources ); } } else if ( le.isMouseRightButtonPressedInArea( messageRoi ) ) { fheroes2::showStandardTextMessage( _( "Event Message Text" ), _( "Click here to change the event message." ), Dialog::ZERO ); } if ( isRedrawNeeded ) { isRedrawNeeded = false; display.render( dialogRoi ); } } return true; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_daily_event_spec_window.h000066400000000000000000000034761476115357100264140ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace Maps::Map_Format { struct DailyEvent; } namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace Editor { bool editDailyEvent( Maps::Map_Format::DailyEvent & eventMetadata, const uint8_t humanPlayerColors, const uint8_t computerPlayerColors, const fheroes2::SupportedLanguage language ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_daily_events_window.cpp000066400000000000000000000322711476115357100261130ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_daily_events_window.h" #include #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "editor_daily_event_spec_window.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "map_format_info.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_window.h" namespace { const int32_t elementOffset{ 9 }; const fheroes2::Size eventsArea{ 500, 315 }; const int32_t listAreaHeightDeduction{ 8 }; class EventListBox final : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; EventListBox( const fheroes2::Point & pt, const fheroes2::SupportedLanguage language ) : ListBox( pt ) , _language( language ) { // Do nothing. } void RedrawItem( const Maps::Map_Format::DailyEvent & event, int32_t posX, int32_t posY, bool current ) override { std::string message = _( "Day: %{day}" ); StringReplace( message, "%{day}", std::to_string( event.firstOccurrenceDay ) ); if ( !event.message.empty() ) { message += " \""; } fheroes2::Text dateText{ message, ( current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ) }; const int32_t dateLength = dateText.width(); assert( dateLength < eventsArea.width - 10 ); fheroes2::MultiFontText text; text.add( std::move( dateText ) ); if ( !event.message.empty() ) { fheroes2::Text messageText{ event.message + '\"', ( current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ), _language }; messageText.fitToOneRow( eventsArea.width - 10 - dateLength ); text.add( std::move( messageText ) ); } text.draw( posX + 5, posY + 5, fheroes2::Display::instance() ); } void RedrawBackground( const fheroes2::Point & /*unused*/ ) override { _listBackground->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListDoubleClick( Maps::Map_Format::DailyEvent & /*unused*/ ) override { _isDoubleClicked = true; } bool isDoubleClicked() const { return _isDoubleClicked; } void resetDoubleClickedState() { _isDoubleClicked = false; } void ActionListSingleClick( Maps::Map_Format::DailyEvent & /*unused*/ ) override { // Do nothing. } void ActionListPressRight( Maps::Map_Format::DailyEvent & /*unused*/ ) override { // Do nothing. } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: std::unique_ptr _listBackground; bool _isDoubleClicked{ false }; const fheroes2::SupportedLanguage _language; }; void sortEvents( std::vector & dailyEvents ) { std::sort( dailyEvents.begin(), dailyEvents.end(), []( const auto & first, const auto & second ) { return first.firstOccurrenceDay < second.firstOccurrenceDay; } ); } } namespace Editor { bool openDailyEventsWindow( std::vector & dailyEvents, const uint8_t humanPlayerColors, const uint8_t computerPlayerColors, const fheroes2::SupportedLanguage language ) { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background{ eventsArea.width + 50, eventsArea.height + 100, true, display }; const fheroes2::Rect windowArea{ background.activeArea() }; int32_t offsetY = windowArea.y + elementOffset; const fheroes2::Text title( _( "Daily Events" ), fheroes2::FontType::normalYellow() ); title.draw( windowArea.x + ( windowArea.width - title.width() ) / 2, offsetY, display ); offsetY += title.height() + elementOffset; const fheroes2::Rect eventsRoi{ windowArea.x + elementOffset, offsetY, eventsArea.width, eventsArea.height }; background.applyTextBackgroundShading( eventsRoi ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); EventListBox eventList( eventsRoi.getPosition(), language ); eventList.initListBackgroundRestorer( eventsRoi ); eventList.SetAreaItems( { eventsRoi.x, eventsRoi.y, eventsRoi.width, eventsRoi.height - listAreaHeightDeduction } ); int32_t scrollbarOffsetX = eventsRoi.x + eventsRoi.width + 5; background.renderScrollbarBackground( { scrollbarOffsetX, eventsRoi.y, eventsRoi.width, eventsRoi.height }, isEvilInterface ); const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; const int32_t topPartHeight = 19; ++scrollbarOffsetX; eventList.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, eventsRoi.y + 1 } ); eventList.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, eventsRoi.y + eventsRoi.height - 15 } ); eventList.setScrollBarArea( { scrollbarOffsetX + 2, eventsRoi.y + topPartHeight, 10, eventsRoi.height - 2 * topPartHeight } ); eventList.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); eventList.SetAreaMaxItems( 10 ); eventList.SetListContent( dailyEvents ); eventList.updateScrollBarImage(); eventList.Redraw(); const int minibuttonIcnId = isEvilInterface ? ICN::CELLWIN_EVIL : ICN::CELLWIN; const fheroes2::Sprite & buttonImage = fheroes2::AGG::GetICN( minibuttonIcnId, 13 ); const int32_t buttonWidth = buttonImage.width(); const int32_t buttonOffset = ( eventsArea.width - 3 * buttonWidth ) / 2 + buttonWidth; fheroes2::Button buttonAdd( eventsRoi.x, eventsRoi.y + eventsRoi.height + 5, minibuttonIcnId, 13, 14 ); buttonAdd.draw(); fheroes2::Button buttonEdit( eventsRoi.x + buttonOffset, eventsRoi.y + eventsRoi.height + 5, minibuttonIcnId, 15, 16 ); buttonEdit.draw(); fheroes2::Button buttonDelete( eventsRoi.x + eventsArea.width - buttonWidth, eventsRoi.y + eventsRoi.height + 5, minibuttonIcnId, 17, 18 ); buttonDelete.draw(); // Prepare OKAY and CANCEL buttons and render their shadows. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); display.render( background.totalArea() ); bool isRedrawNeeded = false; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonAdd.drawOnState( le.isMouseLeftButtonPressedInArea( buttonAdd.area() ) ); buttonEdit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonEdit.area() ) ); buttonDelete.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDelete.area() ) ); if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { break; } if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) ) { return true; } eventList.QueueEventProcessing(); if ( eventList.IsNeedRedraw() ) { eventList.Redraw(); isRedrawNeeded = true; } if ( le.MouseClickLeft( buttonAdd.area() ) ) { Maps::Map_Format::DailyEvent temp; if ( editDailyEvent( temp, humanPlayerColors, computerPlayerColors, language ) ) { dailyEvents.emplace_back( std::move( temp ) ); sortEvents( dailyEvents ); eventList.updateScrollBarImage(); eventList.Redraw(); } isRedrawNeeded = true; } else if ( eventList.isDoubleClicked() || le.MouseClickLeft( buttonEdit.area() ) ) { if ( eventList.getCurrentId() < 0 ) { continue; } eventList.resetDoubleClickedState(); Maps::Map_Format::DailyEvent temp = eventList.GetCurrent(); if ( editDailyEvent( temp, humanPlayerColors, computerPlayerColors, language ) ) { eventList.GetCurrent() = std::move( temp ); sortEvents( dailyEvents ); eventList.Redraw(); } isRedrawNeeded = true; } else if ( le.MouseClickLeft( buttonDelete.area() ) ) { if ( eventList.getCurrentId() < 0 ) { continue; } eventList.RemoveSelected(); sortEvents( dailyEvents ); eventList.updateScrollBarImage(); eventList.Redraw(); isRedrawNeeded = true; } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to save the events." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonAdd.area() ) ) { fheroes2::showStandardTextMessage( _( "Add Event" ), _( "Add an additional event." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonEdit.area() ) ) { fheroes2::showStandardTextMessage( _( "Edit Event" ), _( "Edit an existing event." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonDelete.area() ) ) { fheroes2::showStandardTextMessage( _( "Delete Event" ), _( "Delete an existing event." ), Dialog::ZERO ); } if ( isRedrawNeeded ) { isRedrawNeeded = false; display.render( windowArea ); } } return false; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_daily_events_window.h000066400000000000000000000035511476115357100255570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace Maps::Map_Format { struct DailyEvent; } namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace Editor { bool openDailyEventsWindow( std::vector & dailyEvents, const uint8_t humanPlayerColors, const uint8_t computerPlayerColors, const fheroes2::SupportedLanguage language ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_event_details_window.cpp000066400000000000000000000621771476115357100262630ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_event_details_window.h" #include #include #include #include #include #include #include #include #include "agg_image.h" #include "artifact.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "dialog_selectitems.h" #include "editor_ui_helper.h" #include "game_hotkeys.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "map_format_info.h" #include "math_base.h" #include "mp2.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "spell.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" namespace { const std::array resourceTypes = { Resource::WOOD, Resource::SULFUR, Resource::CRYSTAL, Resource::MERCURY, Resource::ORE, Resource::GEMS, Resource::GOLD }; const int32_t elementOffset{ 9 }; const int32_t sectionWidth{ ( fheroes2::Display::DEFAULT_WIDTH - elementOffset * 3 ) / 2 }; const fheroes2::Size messageArea{ sectionWidth, 207 }; } namespace Editor { bool eventDetailsDialog( Maps::Map_Format::AdventureMapEventMetadata & eventMetadata, const uint8_t humanPlayerColors, const uint8_t computerPlayerColors, const fheroes2::SupportedLanguage language ) { // First, make sure that the event has proper player colors according to the map specification. eventMetadata.humanPlayerColors = eventMetadata.humanPlayerColors & humanPlayerColors; eventMetadata.computerPlayerColors = eventMetadata.computerPlayerColors & computerPlayerColors; const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const bool isDefaultScreenSize = display.isDefaultSize(); fheroes2::StandardWindow background( sectionWidth * 2 + elementOffset * 3, fheroes2::Display::DEFAULT_HEIGHT, !isDefaultScreenSize, display ); const fheroes2::Rect dialogRoi = background.activeArea(); if ( isDefaultScreenSize ) { const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ); fheroes2::Copy( backgroundImage, 0, 0, display, dialogRoi ); } int32_t offsetY = dialogRoi.y + elementOffset; const fheroes2::Text title( MP2::StringObject( MP2::OBJ_EVENT ), fheroes2::FontType::normalYellow() ); title.draw( dialogRoi.x + ( dialogRoi.width - title.width() ) / 2, offsetY, display ); offsetY += title.height() + elementOffset; const int32_t startOffsetY = offsetY; fheroes2::Text text{ _( "Message Text:" ), fheroes2::FontType::normalWhite() }; const fheroes2::Rect messageRoi{ dialogRoi.x + elementOffset, offsetY + text.height(), messageArea.width, messageArea.height }; background.applyTextBackgroundShading( messageRoi ); fheroes2::ImageRestorer messageRoiRestorer( display, messageRoi.x, messageRoi.y, messageRoi.width, messageRoi.height ); text.draw( messageRoi.x + ( messageRoi.width - text.width() ) / 2, offsetY, display ); text.set( eventMetadata.message, fheroes2::FontType::normalWhite(), language ); text.drawInRoi( messageRoi.x + 5, messageRoi.y + 5, messageRoi.width - 10, display, messageRoi ); offsetY = startOffsetY; const int32_t secondColumnOffsetX = dialogRoi.x + sectionWidth + 2 * elementOffset; text.set( _( "Effects:" ), fheroes2::FontType::normalWhite() ); text.draw( secondColumnOffsetX + ( sectionWidth - text.width() ) / 2, offsetY, display ); offsetY += text.height( sectionWidth ); // Resources const fheroes2::Rect resourceRoi{ secondColumnOffsetX, offsetY, sectionWidth, 99 }; background.applyTextBackgroundShading( resourceRoi ); fheroes2::ImageRestorer resourceRoiRestorer( display, resourceRoi.x, resourceRoi.y, resourceRoi.width, resourceRoi.height ); std::array individualResourceRoi; renderResources( eventMetadata.resources, resourceRoi, display, individualResourceRoi ); // Artifact offsetY += resourceRoi.height + elementOffset; auto artifactUI = std::make_unique( eventMetadata.artifact ); const fheroes2::Rect artifactRoi{ secondColumnOffsetX, offsetY, artifactUI->area().width, artifactUI->area().height }; artifactUI->draw( display, artifactRoi.getPosition() ); const int minibuttonIcnId = isEvilInterface ? ICN::CELLWIN_EVIL : ICN::CELLWIN; const fheroes2::Sprite & buttonImage = fheroes2::AGG::GetICN( minibuttonIcnId, 17 ); const int32_t buttonWidth = buttonImage.width(); fheroes2::Button buttonDeleteArtifact( artifactRoi.x + ( artifactRoi.width - buttonWidth ) / 2, artifactRoi.y + artifactRoi.height + 5, minibuttonIcnId, 17, 18 ); buttonDeleteArtifact.draw(); // Experience auto experienceUI = std::make_unique( 0 ); const fheroes2::Rect experienceRoi{ secondColumnOffsetX + sectionWidth - experienceUI->area().width, offsetY + ( artifactRoi.height - experienceUI->area().height ) / 2, experienceUI->area().width, experienceUI->area().height }; const fheroes2::Rect experienceValueRoi{ experienceRoi.x, buttonDeleteArtifact.area().y, experienceRoi.width, buttonDeleteArtifact.area().height }; background.applyTextBackgroundShading( experienceValueRoi ); fheroes2::ImageRestorer experienceRoiRestorer( display, experienceRoi.x, experienceRoi.y, experienceRoi.width, experienceValueRoi.y + experienceValueRoi.height - experienceRoi.y ); experienceUI->draw( display, experienceRoi.getPosition() ); text.set( std::to_string( eventMetadata.experience ), fheroes2::FontType::smallWhite() ); text.draw( experienceValueRoi.x + ( experienceValueRoi.width - text.width() ) / 2, experienceValueRoi.y + 5, display ); // Secondary Skill const Heroes fakeHero; auto secondarySkillUI = std::make_unique( Skill::Secondary{ eventMetadata.secondarySkill, eventMetadata.secondarySkillLevel }, fakeHero ); const fheroes2::Rect secondarySkillRoi{ ( artifactRoi.x + artifactRoi.width + experienceRoi.x - secondarySkillUI->area().width ) / 2, offsetY + ( artifactRoi.height - secondarySkillUI->area().height ) / 2, secondarySkillUI->area().width, secondarySkillUI->area().height }; secondarySkillUI->draw( display, secondarySkillRoi.getPosition() ); fheroes2::Button buttonDeleteSecondarySkill( secondarySkillRoi.x + ( secondarySkillRoi.width - buttonWidth ) / 2, artifactRoi.y + artifactRoi.height + 5, minibuttonIcnId, 17, 18 ); buttonDeleteSecondarySkill.draw(); // Conditions offsetY = messageRoi.y + messageRoi.height + 2 * elementOffset; text.set( _( "Conditions:" ), fheroes2::FontType::normalWhite() ); text.draw( dialogRoi.x + ( dialogRoi.width - text.width() ) / 2, offsetY, display ); offsetY += text.height() + elementOffset; const int32_t conditionSectionOffsetY = offsetY; const fheroes2::Point recurringEventPos{ messageRoi.x + elementOffset, offsetY }; fheroes2::MovableSprite recurringEventCheckbox; const fheroes2::Rect recurringEventArea = drawCheckboxWithText( recurringEventCheckbox, _( "Cancel event after first visit" ), display, recurringEventPos.x, recurringEventPos.y, isEvilInterface, dialogRoi.width - 2 * elementOffset ); if ( eventMetadata.isRecurringEvent ) { recurringEventCheckbox.hide(); } else { recurringEventCheckbox.show(); } offsetY = conditionSectionOffsetY; text.set( _( "Player colors allowed to get event:" ), fheroes2::FontType::normalWhite() ); int32_t textWidth = sectionWidth; // If the text fits on one line, make it span two lines. while ( text.rows( textWidth ) < 2 ) { textWidth = textWidth * 2 / 3; } text.draw( secondColumnOffsetX + ( sectionWidth - textWidth ) / 2, offsetY, textWidth, display ); const int32_t availablePlayersCount = Color::Count( humanPlayerColors | computerPlayerColors ); const int32_t checkOffX = ( sectionWidth - availablePlayersCount * 32 ) / 2; offsetY += 3 + text.height( textWidth ); std::vector> humanCheckboxes; createColorCheckboxes( humanCheckboxes, humanPlayerColors, eventMetadata.humanPlayerColors, secondColumnOffsetX + checkOffX, offsetY, display ); assert( humanCheckboxes.size() == static_cast( Color::Count( humanPlayerColors ) ) ); offsetY += 35; text.set( _( "Computer colors allowed to get the event:" ), fheroes2::FontType::normalWhite() ); textWidth = sectionWidth; // If the text fits on one line, make it span two lines. while ( text.rows( textWidth ) < 2 ) { textWidth = textWidth * 2 / 3; } text.draw( secondColumnOffsetX + ( sectionWidth - textWidth ) / 2, offsetY, textWidth, display ); offsetY += 3 + text.height( textWidth ); std::vector> computerCheckboxes; createColorCheckboxes( computerCheckboxes, computerPlayerColors, eventMetadata.computerPlayerColors, secondColumnOffsetX + checkOffX, offsetY, display ); assert( computerCheckboxes.size() == static_cast( Color::Count( computerPlayerColors ) ) ); // Window buttons fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); display.render( background.totalArea() ); bool isRedrawNeeded = false; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonDeleteArtifact.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDeleteArtifact.area() ) ); buttonDeleteSecondarySkill.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDeleteSecondarySkill.area() ) ); if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return false; } if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) ) { break; } for ( const auto & humanCheckbox : humanCheckboxes ) { const fheroes2::Rect & checkboxRect = humanCheckbox->getRect(); if ( le.MouseClickLeft( checkboxRect ) ) { const int color = humanCheckbox->getColor(); if ( humanCheckbox->toggle() ) { eventMetadata.humanPlayerColors |= color; } else { eventMetadata.humanPlayerColors ^= color; } break; } if ( le.isMouseRightButtonPressedInArea( checkboxRect ) ) { std::string header = _( "Allow %{color} human player to get event" ); std::string messageText = _( "If this checkbox is checked, this event will trigger for the %{color} player if they are controlled by a human." ); const std::string colorString = Color::String( humanCheckbox->getColor() ); StringReplace( header, "%{color}", colorString ); StringReplace( messageText, "%{color}", colorString ); fheroes2::showStandardTextMessage( std::move( header ), std::move( messageText ), Dialog::ZERO ); break; } } for ( const auto & computerCheckbox : computerCheckboxes ) { const fheroes2::Rect & checkboxRect = computerCheckbox->getRect(); if ( le.MouseClickLeft( checkboxRect ) ) { const int color = computerCheckbox->getColor(); if ( computerCheckbox->toggle() ) { eventMetadata.computerPlayerColors |= color; } else { eventMetadata.computerPlayerColors ^= color; } break; } if ( le.isMouseRightButtonPressedInArea( checkboxRect ) ) { std::string header = _( "Allow %{color} computer player to get event" ); std::string messageText = _( "If this checkbox is checked, this event will trigger for the %{color} player if they are controlled by a computer." ); const std::string colorString = Color::String( computerCheckbox->getColor() ); StringReplace( header, "%{color}", colorString ); StringReplace( messageText, "%{color}", colorString ); fheroes2::showStandardTextMessage( std::move( header ), std::move( messageText ), Dialog::ZERO ); break; } } for ( size_t i = 0; i < individualResourceRoi.size(); ++i ) { if ( le.MouseClickLeft( individualResourceRoi[i] ) ) { const int resourceType = resourceTypes[i]; int32_t * resourcePtr = eventMetadata.resources.GetPtr( resourceType ); assert( resourcePtr != nullptr ); int32_t temp = *resourcePtr; const fheroes2::ResourceDialogElement resourceUI( resourceType, {} ); std::string message = _( "Set %{resource-type} Count" ); StringReplace( message, "%{resource-type}", Resource::String( resourceType ) ); if ( Dialog::SelectCount( std::move( message ), -99999, 999999, temp, 1, &resourceUI ) ) { *resourcePtr = temp; } resourceRoiRestorer.restore(); renderResources( eventMetadata.resources, resourceRoi, display, individualResourceRoi ); display.render( resourceRoi ); break; } } if ( le.MouseClickLeft( messageRoi ) ) { std::string temp = eventMetadata.message; const fheroes2::Text body{ _( "Message:" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, temp, 200, true, language ) ) { eventMetadata.message = std::move( temp ); messageRoiRestorer.restore(); text.set( eventMetadata.message, fheroes2::FontType::normalWhite(), language ); text.drawInRoi( messageRoi.x + 5, messageRoi.y + 5, messageRoi.width - 10, display, messageRoi ); isRedrawNeeded = true; } } else if ( le.MouseClickLeft( recurringEventArea ) ) { eventMetadata.isRecurringEvent = !eventMetadata.isRecurringEvent; eventMetadata.isRecurringEvent ? recurringEventCheckbox.hide() : recurringEventCheckbox.show(); display.render( recurringEventCheckbox.getArea() ); } else if ( le.MouseClickLeft( artifactRoi ) ) { const Artifact artifact = Dialog::selectArtifact( eventMetadata.artifact, false ); if ( artifact.isValid() ) { int32_t artifactMetadata = eventMetadata.artifactMetadata; if ( artifact.GetID() == Artifact::SPELL_SCROLL ) { artifactMetadata = Dialog::selectSpell( artifactMetadata, true ).GetID(); if ( artifactMetadata == Spell::NONE ) { // No spell for the Spell Scroll artifact was selected - cancel the artifact selection. continue; } } else { artifactMetadata = 0; } eventMetadata.artifact = artifact.GetID(); eventMetadata.artifactMetadata = artifactMetadata; artifactUI = std::make_unique( eventMetadata.artifact ); artifactUI->draw( display, artifactRoi.getPosition() ); } // The opened selectArtifact() dialog might be bigger than this dialog so we render the whole screen. display.render(); } else if ( le.MouseClickLeft( buttonDeleteArtifact.area() ) ) { eventMetadata.artifact = 0; eventMetadata.artifactMetadata = 0; const fheroes2::Sprite & artifactImage = fheroes2::AGG::GetICN( ICN::ARTIFACT, Artifact( eventMetadata.artifact ).IndexSprite64() ); fheroes2::Copy( artifactImage, 0, 0, display, artifactRoi.x + 6, artifactRoi.y + 6, artifactImage.width(), artifactImage.height() ); display.render( artifactRoi ); } else if ( le.MouseClickLeft( secondarySkillRoi ) ) { const Skill::Secondary skill = Dialog::selectSecondarySkill( fakeHero, eventMetadata.secondarySkill * 3 + eventMetadata.secondarySkillLevel ); if ( skill.isValid() ) { eventMetadata.secondarySkill = static_cast( skill.Skill() ); eventMetadata.secondarySkillLevel = static_cast( skill.Level() ); secondarySkillUI = std::make_unique( skill, fakeHero ); secondarySkillUI->draw( display, secondarySkillRoi.getPosition() ); } // The opened selectSecondarySkill() dialog might be bigger than this dialog so we render the whole screen. display.render(); } else if ( le.MouseClickLeft( buttonDeleteSecondarySkill.area() ) ) { eventMetadata.secondarySkill = 0; eventMetadata.secondarySkillLevel = 0; secondarySkillUI = std::make_unique( Skill::Secondary{}, fakeHero ); secondarySkillUI->draw( display, secondarySkillRoi.getPosition() ); display.render( secondarySkillRoi ); } else if ( le.MouseClickLeft( experienceRoiRestorer.rect() ) ) { const fheroes2::ExperienceDialogElement tempExperienceUI{ 0 }; int32_t tempValue{ eventMetadata.experience }; if ( Dialog::SelectCount( _( "Set Experience value" ), 0, static_cast( Heroes::getExperienceMaxValue() ), tempValue, 1, &tempExperienceUI ) ) { eventMetadata.experience = tempValue; experienceRoiRestorer.restore(); experienceUI->draw( display, experienceRoi.getPosition() ); text.set( std::to_string( eventMetadata.experience ), fheroes2::FontType::smallWhite() ); text.draw( experienceValueRoi.x + ( experienceValueRoi.width - text.width() ) / 2, experienceValueRoi.y + 5, display ); } // The opened SelectCount() dialog might be bigger than this dialog so we render the whole screen. display.render(); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to save the Event properties." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( artifactRoi ) ) { // Since Artifact class does not allow to set a random spell (for obvious reasons), // we have to use special UI code to render the popup window with all needed information. const Artifact artifact( eventMetadata.artifact ); if ( artifact.isValid() ) { artifactUI->showPopup( Dialog::ZERO ); } else { fheroes2::showStandardTextMessage( _( "Artifact" ), _( "No artifact will be given by the event." ), Dialog::ZERO ); } } else if ( le.isMouseRightButtonPressedInArea( buttonDeleteArtifact.area() ) ) { fheroes2::showStandardTextMessage( _( "Delete Artifact" ), _( "Delete an artifact from the event." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( secondarySkillRoi ) ) { const Skill::Secondary skill( eventMetadata.secondarySkill, eventMetadata.secondarySkillLevel ); if ( skill.isValid() ) { secondarySkillUI->showPopup( Dialog::ZERO ); } else { fheroes2::showStandardTextMessage( _( "Secondary Skill" ), _( "No Secondary Skill will be given by the event." ), Dialog::ZERO ); } } else if ( le.isMouseRightButtonPressedInArea( buttonDeleteSecondarySkill.area() ) ) { fheroes2::showStandardTextMessage( _( "Delete Secondary Skill" ), _( "Delete the Secondary Skill from the event." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( experienceRoiRestorer.rect() ) ) { experienceUI->showPopup( Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( resourceRoi ) ) { if ( eventMetadata.resources.GetValidItemsCount() == 0 ) { fheroes2::showStandardTextMessage( _( "Resources" ), _( "No resources will be part of this event." ), Dialog::ZERO ); } else { fheroes2::showResourceMessage( fheroes2::Text( _( "Resources" ), fheroes2::FontType::normalYellow() ), fheroes2::Text{ _( "These resources will be a part of the event." ), fheroes2::FontType::normalWhite() }, Dialog::ZERO, eventMetadata.resources ); } } else if ( le.isMouseRightButtonPressedInArea( recurringEventArea ) ) { fheroes2::showStandardTextMessage( _( "Cancel event after first visit" ), _( "If this checkbox is checked, the event will trigger only once. If not checked, the event will trigger every time one of the specified players crosses the event tile." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( messageRoi ) ) { fheroes2::showStandardTextMessage( _( "Event Message Text" ), _( "Click here to change the event message." ), Dialog::ZERO ); } if ( isRedrawNeeded ) { isRedrawNeeded = false; display.render( dialogRoi ); } } return true; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_event_details_window.h000066400000000000000000000035431476115357100257200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace Maps::Map_Format { struct AdventureMapEventMetadata; } namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace Editor { bool eventDetailsDialog( Maps::Map_Format::AdventureMapEventMetadata & eventMetadata, const uint8_t humanPlayerColors, const uint8_t computerPlayerColors, const fheroes2::SupportedLanguage language ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_interface.cpp000066400000000000000000003136521476115357100240030ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_interface.h" #include #include #include #include #include #include #include #include #include #include #include "artifact.h" #include "audio_manager.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "dialog_selectitems.h" #include "direction.h" #include "editor_castle_details_window.h" #include "editor_event_details_window.h" #include "editor_map_specs_window.h" #include "editor_object_popup_window.h" #include "editor_save_map_window.h" #include "editor_secondary_skill_selection.h" #include "editor_spell_selection.h" #include "editor_sphinx_window.h" #include "game.h" #include "game_delays.h" #include "game_hotkeys.h" #include "game_static.h" #include "ground.h" #include "heroes.h" #include "history_manager.h" #include "icn.h" #include "interface_base.h" #include "interface_border.h" #include "interface_gamearea.h" #include "interface_radar.h" #include "localevent.h" #include "map_format_helper.h" #include "map_object_info.h" #include "maps.h" #include "maps_fileinfo.h" #include "maps_tiles.h" #include "maps_tiles_helper.h" #include "math_base.h" #include "monster.h" #include "mp2.h" #include "puzzle.h" #include "race.h" #include "render_processor.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "spell.h" #include "system.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_map_object.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" #include "view_world.h" #include "world.h" #include "world_object_uid.h" namespace { const uint32_t mapUpdateFlags = Interface::REDRAW_GAMEAREA | Interface::REDRAW_RADAR; // In original Editor map name is limited to 17 characters. // However, we have no such limitation but to be reasonable we still have a limit. const int32_t maxMapNameLength = 50; class HideInterfaceModeDisabler { public: HideInterfaceModeDisabler() { // If Hide Interface mode is enabled we temporary disable it to allow editor properly place all interface items. if ( _isHideInterfaceEnabled ) { Settings::Get().setHideInterface( false ); } } HideInterfaceModeDisabler & operator=( const HideInterfaceModeDisabler & ) = delete; HideInterfaceModeDisabler( const HideInterfaceModeDisabler & ) = delete; ~HideInterfaceModeDisabler() { if ( _isHideInterfaceEnabled ) { // Restore Hide Interface mode if it was enabled. Settings::Get().setHideInterface( true ); } } private: const bool _isHideInterfaceEnabled{ Settings::Get().isHideInterfaceEnabled() }; }; size_t getObeliskCount( const Maps::Map_Format::MapFormat & _mapFormat ) { const auto & miscellaneousObjects = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS ); std::set obeliskIndex; for ( size_t i = 0; i < miscellaneousObjects.size(); ++i ) { if ( miscellaneousObjects[i].objectType == MP2::OBJ_OBELISK ) { obeliskIndex.emplace( i ); } } size_t obeliskCount = 0; for ( const auto & mapTile : _mapFormat.tiles ) { for ( const auto & object : mapTile.objects ) { if ( object.group == Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS && obeliskIndex.count( object.index ) > 0 ) { assert( object.index < miscellaneousObjects.size() ); ++obeliskCount; } } } return obeliskCount; } fheroes2::Point getBrushAreaIndicies( const fheroes2::Rect & brushSize, const int32_t startIndex ) { if ( brushSize.width <= 0 || brushSize.height <= 0 ) { return { startIndex, startIndex }; } const int32_t worldWidth = world.w(); const int32_t worldHeight = world.h(); fheroes2::Point startPos{ ( startIndex % worldWidth ) + brushSize.x, ( startIndex / worldWidth ) + brushSize.y }; fheroes2::Point endPos{ startPos.x + brushSize.width - 1, startPos.y + brushSize.height - 1 }; startPos.x = std::max( startPos.x, 0 ); startPos.y = std::max( startPos.y, 0 ); endPos.x = std::min( endPos.x, worldWidth - 1 ); endPos.y = std::min( endPos.y, worldHeight - 1 ); return { startPos.x + startPos.y * worldWidth, endPos.x + endPos.y * worldWidth }; } bool isObjectPlacementAllowed( const Maps::ObjectInfo & info, const fheroes2::Point & mainTilePos ) { // Run through all tile offsets and check that all objects parts can be put on the map. for ( const auto & objectPart : info.groundLevelParts ) { if ( objectPart.layerType == Maps::SHADOW_LAYER ) { // Shadow layer parts are ignored. continue; } if ( !Maps::isValidAbsPoint( mainTilePos.x + objectPart.tileOffset.x, mainTilePos.y + objectPart.tileOffset.y ) ) { return false; } } for ( const auto & objectPart : info.topLevelParts ) { if ( !Maps::isValidAbsPoint( mainTilePos.x + objectPart.tileOffset.x, mainTilePos.y + objectPart.tileOffset.y ) ) { return false; } } return true; } bool isActionObjectAllowed( const Maps::ObjectInfo & info, const fheroes2::Point & mainTilePos ) { // Active action object parts must be placed on a tile without any other objects. // Only ground parts should be checked for this condition. for ( const auto & objectPart : info.groundLevelParts ) { if ( objectPart.layerType == Maps::SHADOW_LAYER || objectPart.layerType == Maps::TERRAIN_LAYER ) { // Shadow and terrain layer parts are ignored. continue; } const fheroes2::Point pos{ mainTilePos.x + objectPart.tileOffset.x, mainTilePos.y + objectPart.tileOffset.y }; if ( !Maps::isValidAbsPoint( pos.x, pos.y ) ) { return false; } const auto & tile = world.getTile( pos.x, pos.y ); if ( MP2::isOffGameActionObject( tile.getMainObjectType() ) ) { // An action object already exist. We cannot allow to put anything on top of it. return false; } if ( MP2::isOffGameActionObject( objectPart.objectType ) && !Maps::isClearGround( tile ) ) { // We are trying to place an action object on a tile that has some other objects. return false; } } return true; } bool isConditionValid( const std::vector & offsets, const fheroes2::Point & mainTilePos, const std::function & condition ) { if ( offsets.empty() ) { return true; } assert( condition ); for ( const auto & offset : offsets ) { const fheroes2::Point temp{ mainTilePos.x + offset.x, mainTilePos.y + offset.y }; if ( !Maps::isValidAbsPoint( temp.x, temp.y ) ) { return false; } if ( !condition( world.getTile( temp.x, temp.y ) ) ) { return false; } } return true; } bool checkConditionForUsedTiles( const Maps::ObjectInfo & info, const fheroes2::Point & mainTilePos, const std::function & condition ) { return isConditionValid( Maps::getGroundLevelUsedTileOffset( info ), mainTilePos, condition ); } bool removeObjects( Maps::Map_Format::MapFormat & mapFormat, std::set objectsUids, const std::set & objectGroups ) { if ( objectsUids.empty() ) { return false; } bool needRedraw = false; bool updateMapPlayerInformation = false; // Filter objects by group and remove them from '_mapFormat'. for ( size_t mapTileIndex = 0; mapTileIndex < mapFormat.tiles.size(); ++mapTileIndex ) { Maps::Map_Format::TileInfo & mapTile = mapFormat.tiles[mapTileIndex]; for ( auto objectIter = mapTile.objects.begin(); objectIter != mapTile.objects.end(); ) { // LANDSCAPE_FLAGS and LANDSCAPE_TOWN_BASEMENTS are special objects that should be erased only when erasing the main object. if ( objectIter->group == Maps::ObjectGroup::LANDSCAPE_FLAGS || objectIter->group == Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS || objectsUids.find( objectIter->id ) == objectsUids.end() ) { // No main object UID was found. ++objectIter; continue; } // The object with this UID is found, remove UID not to search for it more. objectsUids.erase( objectIter->id ); if ( std::none_of( objectGroups.begin(), objectGroups.end(), [&objectIter]( const Maps::ObjectGroup group ) { return group == objectIter->group; } ) ) { // This object is not in the selected to erase groups. if ( objectsUids.empty() ) { break; } ++objectIter; continue; } if ( objectIter->group == Maps::ObjectGroup::KINGDOM_TOWNS ) { // Towns and castles consist of four objects. We need to search them all and remove from map. const uint32_t objectId = objectIter->id; auto findTownPart = [objectId]( const Maps::Map_Format::TileInfo & tileToSearch, const Maps::ObjectGroup group ) { auto foundObjectIter = std::find_if( tileToSearch.objects.begin(), tileToSearch.objects.end(), [objectId, group]( const Maps::Map_Format::TileObjectInfo & mapObject ) { return mapObject.group == group && mapObject.id == objectId; } ); // The town part should exist on the map. If no then there might be issues in towns placing. assert( foundObjectIter != tileToSearch.objects.end() ); return foundObjectIter; }; // Remove the town object. mapTile.objects.erase( objectIter ); // Town basement is also located at this tile. Find and remove it. mapTile.objects.erase( findTownPart( mapTile, Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS ) ); // Remove flags. assert( mapTileIndex > 0 ); Maps::Map_Format::TileInfo & previousMapTile = mapFormat.tiles[mapTileIndex - 1]; previousMapTile.objects.erase( findTownPart( previousMapTile, Maps::ObjectGroup::LANDSCAPE_FLAGS ) ); assert( mapTileIndex < mapFormat.tiles.size() - 1 ); Maps::Map_Format::TileInfo & nextMapTile = mapFormat.tiles[mapTileIndex + 1]; nextMapTile.objects.erase( findTownPart( nextMapTile, Maps::ObjectGroup::LANDSCAPE_FLAGS ) ); // Two objects have been removed from this tile. Start search from the beginning. objectIter = mapTile.objects.begin(); // Remove this town metadata. assert( mapFormat.castleMetadata.find( objectId ) != mapFormat.castleMetadata.end() ); mapFormat.castleMetadata.erase( objectId ); // There could be a road in front of the castle entrance. Remove it because there is no entrance to the castle anymore. const size_t bottomTileIndex = mapTileIndex + mapFormat.size; assert( bottomTileIndex < mapFormat.tiles.size() ); auto & bottomTileObjects = mapFormat.tiles[bottomTileIndex].objects; const bool isRoadAtBottom = std::find_if( bottomTileObjects.begin(), bottomTileObjects.end(), []( const Maps::Map_Format::TileObjectInfo & mapObject ) { return mapObject.group == Maps::ObjectGroup::ROADS; } ) != bottomTileObjects.end(); if ( isRoadAtBottom ) { // TODO: Update (not remove) the road. It may be done properly only after roads handling will be moved from 'world' tiles to 'Map_Format' tiles. Maps::updateRoadOnTile( world.getTile( static_cast( bottomTileIndex ) ), false ); } needRedraw = true; updateMapPlayerInformation = true; } else if ( objectIter->group == Maps::ObjectGroup::ROADS ) { assert( mapTileIndex < world.getSize() ); needRedraw |= Maps::updateRoadOnTile( world.getTile( static_cast( mapTileIndex ) ), false ); ++objectIter; } else if ( objectIter->group == Maps::ObjectGroup::STREAMS ) { objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; Maps::updateStreamsAround( mapFormat, static_cast( mapTileIndex ) ); } else if ( objectIter->group == Maps::ObjectGroup::KINGDOM_HEROES || Maps::isJailObject( objectIter->group, objectIter->index ) ) { // Remove this hero metadata. assert( mapFormat.heroMetadata.find( objectIter->id ) != mapFormat.heroMetadata.end() ); mapFormat.heroMetadata.erase( objectIter->id ); objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; updateMapPlayerInformation = true; } else if ( objectIter->group == Maps::ObjectGroup::MONSTERS ) { assert( mapFormat.standardMetadata.find( objectIter->id ) != mapFormat.standardMetadata.end() ); mapFormat.standardMetadata.erase( objectIter->id ); objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; } else if ( objectIter->group == Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS ) { const auto & objects = Maps::getObjectsByGroup( objectIter->group ); assert( objectIter->index < objects.size() ); const auto objectType = objects[objectIter->index].objectType; switch ( objectType ) { case MP2::OBJ_EVENT: assert( mapFormat.adventureMapEventMetadata.find( objectIter->id ) != mapFormat.adventureMapEventMetadata.end() ); mapFormat.adventureMapEventMetadata.erase( objectIter->id ); break; case MP2::OBJ_PYRAMID: mapFormat.selectionObjectMetadata.erase( objectIter->id ); break; case MP2::OBJ_SIGN: assert( mapFormat.signMetadata.find( objectIter->id ) != mapFormat.signMetadata.end() ); mapFormat.signMetadata.erase( objectIter->id ); break; case MP2::OBJ_SPHINX: assert( mapFormat.sphinxMetadata.find( objectIter->id ) != mapFormat.sphinxMetadata.end() ); mapFormat.sphinxMetadata.erase( objectIter->id ); break; case MP2::OBJ_WITCHS_HUT: mapFormat.selectionObjectMetadata.erase( objectIter->id ); break; default: break; } objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; } else if ( objectIter->group == Maps::ObjectGroup::ADVENTURE_WATER ) { const auto & objects = Maps::getObjectsByGroup( objectIter->group ); assert( objectIter->index < objects.size() ); const auto objectType = objects[objectIter->index].objectType; if ( objectType == MP2::OBJ_BOTTLE ) { assert( mapFormat.signMetadata.find( objectIter->id ) != mapFormat.signMetadata.end() ); mapFormat.signMetadata.erase( objectIter->id ); } objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; } else if ( objectIter->group == Maps::ObjectGroup::ADVENTURE_ARTIFACTS ) { assert( mapFormat.standardMetadata.find( objectIter->id ) != mapFormat.standardMetadata.end() ); mapFormat.standardMetadata.erase( objectIter->id ); objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; } else if ( objectIter->group == Maps::ObjectGroup::ADVENTURE_TREASURES ) { const auto & objects = Maps::getObjectsByGroup( objectIter->group ); assert( objectIter->index < objects.size() ); const auto objectType = objects[objectIter->index].objectType; if ( objectType == MP2::OBJ_RESOURCE ) { mapFormat.standardMetadata.erase( objectIter->id ); } objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; } else if ( objectIter->group == Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS ) { // We need to check if the object being removed is a River Delta, and if so, use that data to update the nearby Stream correctly. const int riverDeltaDirection = Maps::getRiverDeltaDirectionByIndex( objectIter->group, static_cast( objectIter->index ) ); objectIter = mapTile.objects.erase( objectIter ); if ( riverDeltaDirection != Direction::UNKNOWN ) { // For River Deltas we update the nearby Streams to properly disconnect from them. Maps::updateStreamsToDeltaConnection( mapFormat, static_cast( mapTileIndex ), riverDeltaDirection ); } needRedraw = true; } else if ( objectIter->group == Maps::ObjectGroup::ADVENTURE_POWER_UPS ) { const auto & objects = Maps::getObjectsByGroup( objectIter->group ); assert( objectIter->index < objects.size() ); const auto objectType = objects[objectIter->index].objectType; switch ( objectType ) { case MP2::OBJ_SHRINE_FIRST_CIRCLE: case MP2::OBJ_SHRINE_SECOND_CIRCLE: case MP2::OBJ_SHRINE_THIRD_CIRCLE: // We cannot assert non-existing metadata as these objects could have been created by an older Editor version. mapFormat.selectionObjectMetadata.erase( objectIter->id ); break; default: break; } objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; } else { objectIter = mapTile.objects.erase( objectIter ); needRedraw = true; } if ( objectsUids.empty() ) { break; } } if ( objectsUids.empty() ) { break; } } if ( updateMapPlayerInformation && !Maps::updateMapPlayers( mapFormat ) ) { assert( 0 ); } return needRedraw; } bool verifyTerrainPlacement( const fheroes2::Point & tilePos, const Maps::ObjectGroup groupType, const int32_t objectType, std::string & errorMessage ) { switch ( groupType ) { case Maps::ObjectGroup::ADVENTURE_ARTIFACTS: { const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); if ( !checkConditionForUsedTiles( objectInfo, tilePos, []( const Maps::Tile & tileToCheck ) { return !tileToCheck.isWater(); } ) ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } if ( objectInfo.objectType == MP2::OBJ_RANDOM_ULTIMATE_ARTIFACT && !checkConditionForUsedTiles( objectInfo, tilePos, []( const Maps::Tile & tileToCheck ) { // This check is being run for every action in the Editor. // Therefore, after the placement of an Ultimate Artifact on this tile the check would fail since the tile contains something on it. // So, before checking for correctness on placement an Ultimate Artifact we check whether the current tile already has one. // If this is true then we consider that the placement is allowed. if ( tileToCheck.getMainObjectType() == MP2::OBJ_RANDOM_ULTIMATE_ARTIFACT ) { return true; } return tileToCheck.GoodForUltimateArtifact(); } ) ) { errorMessage = _( "The Ultimate Artifact can only be placed on terrain where digging is possible." ); return false; } break; } case Maps::ObjectGroup::ADVENTURE_DWELLINGS: case Maps::ObjectGroup::ADVENTURE_MINES: case Maps::ObjectGroup::ADVENTURE_POWER_UPS: case Maps::ObjectGroup::ADVENTURE_TREASURES: case Maps::ObjectGroup::KINGDOM_HEROES: case Maps::ObjectGroup::LANDSCAPE_MOUNTAINS: case Maps::ObjectGroup::LANDSCAPE_ROCKS: case Maps::ObjectGroup::LANDSCAPE_TREES: case Maps::ObjectGroup::MONSTERS: case Maps::ObjectGroup::STREAMS: { const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); if ( !checkConditionForUsedTiles( objectInfo, tilePos, []( const Maps::Tile & tileToCheck ) { return !tileToCheck.isWater(); } ) ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } break; } case Maps::ObjectGroup::ADVENTURE_WATER: case Maps::ObjectGroup::LANDSCAPE_WATER: { const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); if ( !checkConditionForUsedTiles( objectInfo, tilePos, []( const Maps::Tile & tileToCheck ) { return tileToCheck.isWater(); } ) ) { errorMessage = _( "%{objects} must be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } break; } case Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS: { // River deltas are only objects that can be placed on water and on land. if ( Maps::isRiverDeltaObject( groupType, objectType ) ) { // This is a river delta. Just don't check the terrain type. } else if ( !checkConditionForUsedTiles( Maps::getObjectInfo( groupType, objectType ), tilePos, []( const Maps::Tile & tileToCheck ) { return !tileToCheck.isWater(); } ) ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } break; } case Maps::ObjectGroup::KINGDOM_TOWNS: { const Maps::Tile & tile = world.getTile( tilePos.x, tilePos.y ); if ( tile.isWater() ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } const int groundType = Maps::Ground::getGroundByImageIndex( tile.getTerrainImageIndex() ); const int32_t basementId = fheroes2::getTownBasementId( groundType ); const auto & townObjectInfo = Maps::getObjectInfo( groupType, objectType ); const auto & basementObjectInfo = Maps::getObjectInfo( Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS, basementId ); if ( !checkConditionForUsedTiles( townObjectInfo, tilePos, []( const Maps::Tile & tileToCheck ) { return !tileToCheck.isWater(); } ) ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } if ( !checkConditionForUsedTiles( basementObjectInfo, tilePos, []( const Maps::Tile & tileToCheck ) { return !tileToCheck.isWater(); } ) ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } break; } case Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS: { const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); if ( objectInfo.objectType == MP2::OBJ_EVENT ) { // Only event objects are allowed to be placed anywhere. } else if ( !checkConditionForUsedTiles( objectInfo, tilePos, []( const Maps::Tile & tileToCheck ) { return !tileToCheck.isWater(); } ) ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } break; } default: // Did you add a new object group? Add the logic for it! assert( 0 ); break; } return true; } bool verifyObjectPlacement( const fheroes2::Point & tilePos, const Maps::ObjectGroup groupType, const int32_t objectType, std::string & errorMessage ) { switch ( groupType ) { case Maps::ObjectGroup::ADVENTURE_ARTIFACTS: case Maps::ObjectGroup::ADVENTURE_DWELLINGS: case Maps::ObjectGroup::ADVENTURE_MINES: case Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS: case Maps::ObjectGroup::ADVENTURE_POWER_UPS: case Maps::ObjectGroup::ADVENTURE_TREASURES: case Maps::ObjectGroup::ADVENTURE_WATER: case Maps::ObjectGroup::KINGDOM_HEROES: case Maps::ObjectGroup::LANDSCAPE_MOUNTAINS: case Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS: case Maps::ObjectGroup::LANDSCAPE_ROCKS: case Maps::ObjectGroup::LANDSCAPE_TREES: case Maps::ObjectGroup::LANDSCAPE_WATER: case Maps::ObjectGroup::MONSTERS: { const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); if ( !isObjectPlacementAllowed( objectInfo, tilePos ) ) { errorMessage = _( "Objects cannot be placed outside the map." ); return false; } if ( !isActionObjectAllowed( objectInfo, tilePos ) ) { errorMessage = _( "Action objects must be placed on clear tiles." ); return false; } break; } case Maps::ObjectGroup::KINGDOM_TOWNS: { const Maps::Tile & tile = world.getTile( tilePos.x, tilePos.y ); if ( tile.isWater() ) { errorMessage = _( "%{objects} cannot be placed on water." ); StringReplace( errorMessage, "%{objects}", Interface::EditorPanel::getObjectGroupName( groupType ) ); return false; } const int groundType = Maps::Ground::getGroundByImageIndex( tile.getTerrainImageIndex() ); const int32_t basementId = fheroes2::getTownBasementId( groundType ); const auto & townObjectInfo = Maps::getObjectInfo( groupType, objectType ); const auto & basementObjectInfo = Maps::getObjectInfo( Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS, basementId ); if ( !isObjectPlacementAllowed( townObjectInfo, tilePos ) || !isObjectPlacementAllowed( basementObjectInfo, tilePos ) ) { errorMessage = _( "Objects cannot be placed outside the map." ); return false; } if ( !isActionObjectAllowed( townObjectInfo, tilePos ) || !isActionObjectAllowed( basementObjectInfo, tilePos ) ) { errorMessage = _( "Action objects must be placed on clear tiles." ); return false; } break; } default: { // Did you add a new object group? Add the logic for it! assert( 0 ); return false; } } return verifyTerrainPlacement( tilePos, groupType, objectType, errorMessage ); } template bool replaceKey( std::map & data, const uint32_t oldKey, const uint32_t newKey ) { auto iter = data.find( oldKey ); if ( iter == data.end() ) { return false; } auto node = data.extract( iter ); assert( !node.empty() ); node.key() = newKey; data.insert( std::move( node ) ); return true; } } namespace Interface { void EditorInterface::reset() { const HideInterfaceModeDisabler hideInterfaceModeDisabler; const fheroes2::Display & display = fheroes2::Display::instance(); const int32_t xOffset = display.width() - fheroes2::borderWidthPx - fheroes2::radarWidthPx; _radar.SetPos( xOffset, fheroes2::borderWidthPx ); _editorPanel.setPos( xOffset, _radar.GetArea().y + _radar.GetArea().height + ( ( display.height() > fheroes2::Display::DEFAULT_HEIGHT + fheroes2::borderWidthPx ) ? fheroes2::borderWidthPx : 0 ) ); const fheroes2::Point prevCenter = _gameArea.getCurrentCenterInPixels(); const fheroes2::Rect prevRoi = _gameArea.GetROI(); _gameArea.SetAreaPosition( fheroes2::borderWidthPx, fheroes2::borderWidthPx, display.width() - fheroes2::radarWidthPx - 3 * fheroes2::borderWidthPx, display.height() - 2 * fheroes2::borderWidthPx ); const fheroes2::Rect newRoi = _gameArea.GetROI(); _gameArea.SetCenterInPixels( prevCenter + fheroes2::Point( newRoi.x + newRoi.width / 2, newRoi.y + newRoi.height / 2 ) - fheroes2::Point( prevRoi.x + prevRoi.width / 2, prevRoi.y + prevRoi.height / 2 ) ); } void EditorInterface::redraw( const uint32_t force ) { const uint32_t combinedRedraw = _redraw | force; if ( combinedRedraw & REDRAW_GAMEAREA ) { int renderFlags = LEVEL_OBJECTS | LEVEL_HEROES | LEVEL_ROUTES; if ( combinedRedraw & REDRAW_PASSABILITIES ) { renderFlags |= LEVEL_PASSABILITIES; } fheroes2::Display & display = fheroes2::Display::instance(); // Render all except the fog. _gameArea.Redraw( display, renderFlags ); if ( _warningMessage.isValid() ) { const fheroes2::Rect & roi = _gameArea.GetROI(); fheroes2::Text text{ _warningMessage.message(), fheroes2::FontType::normalWhite() }; // Keep 4 pixels from each edge. text.fitToOneRow( roi.width - 8 ); const bool isSystemInfoShown = Settings::Get().isSystemInfoEnabled(); text.draw( roi.x + 4, roi.y + roi.height - text.height() - ( isSystemInfoShown ? 14 : 4 ), display ); } // TODO:: Render horizontal and vertical map tiles scale and highlight with yellow text cursor position. if ( _editorPanel.showAreaSelectRect() && ( _tileUnderCursor > -1 ) ) { const fheroes2::Rect brushSize = _editorPanel.getBrushArea(); if ( brushSize.width > 0 && brushSize.height > 0 ) { const fheroes2::Point indices = getBrushAreaIndicies( brushSize, _tileUnderCursor ); assert( Maps::isValidAbsIndex( indices.x ) ); const bool isActionObject = ( _editorPanel.isDetailEdit() && brushSize.width == 1 && brushSize.height == 1 && MP2::isOffGameActionObject( world.getTile( indices.x ).getMainObjectType() ) ); _gameArea.renderTileAreaSelect( display, indices.x, indices.y, isActionObject ); } else if ( _editorPanel.isTerrainEdit() || _editorPanel.isEraseMode() ) { assert( brushSize == fheroes2::Rect() ); // Render area selection from the tile where the left mouse button was pressed till the tile under the cursor. _gameArea.renderTileAreaSelect( display, _areaSelectionStartTileId, _tileUnderCursor, false ); } } } if ( combinedRedraw & ( REDRAW_RADAR_CURSOR | REDRAW_RADAR ) ) { // Render the mini-map without fog. _radar.redrawForEditor( combinedRedraw & REDRAW_RADAR ); } if ( combinedRedraw & REDRAW_BORDER ) { // Game border for the View World are the same as for the Map Editor. GameBorderRedraw( true ); } if ( combinedRedraw & REDRAW_PANEL ) { _editorPanel._redraw(); } _redraw = 0; } EditorInterface & EditorInterface::Get() { static EditorInterface editorInterface; return editorInterface; } fheroes2::GameMode EditorInterface::startEdit( const bool isNewMap ) { // The Editor has a special option to disable animation. This affects cycling animation as well. // First, we disable it to make sure to enable it back while exiting this function. const fheroes2::ScreenPaletteRestorer restorer; Settings & conf = Settings::Get(); if ( conf.isEditorAnimationEnabled() ) { fheroes2::RenderProcessor::instance().startColorCycling(); } reset(); _historyManager.reset(); if ( isNewMap ) { _mapFormat = {}; Maps::saveMapInEditor( _mapFormat ); _loadedFileName.clear(); } // Stop all sounds and music. AudioManager::ResetAudio(); _radar.Build(); _radar.SetHide( false ); fheroes2::GameMode res = fheroes2::GameMode::CANCEL; _gameArea.SetUpdateCursor(); // The cursor parameters may contain values from a previously edited map that are not suitable for this one. Reset them. _tileUnderCursor = -1; _areaSelectionStartTileId = -1; uint32_t redrawFlags = REDRAW_GAMEAREA | REDRAW_RADAR | REDRAW_PANEL | REDRAW_STATUS | REDRAW_BORDER; if ( conf.isEditorPassabilityEnabled() ) { redrawFlags |= REDRAW_PASSABILITIES; } setRedraw( redrawFlags ); int32_t fastScrollRepeatCount = 0; const int32_t fastScrollStartThreshold = 2; const std::vector delayTypes = { Game::MAPS_DELAY }; LocalEvent & le = LocalEvent::Get(); Cursor & cursor = Cursor::Get(); while ( res == fheroes2::GameMode::CANCEL ) { if ( !le.HandleEvents( Game::isDelayNeeded( delayTypes ), true ) ) { if ( EventExit() == fheroes2::GameMode::QUIT_GAME ) { res = fheroes2::GameMode::QUIT_GAME; break; } continue; } // Hotkeys if ( le.isAnyKeyPressed() ) { if ( HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_QUIT ) || HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { res = EventExit(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::EDITOR_NEW_MAP_MENU ) ) { res = eventNewMap(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SAVE_GAME ) ) { saveMapToFile(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME ) ) { res = eventLoadMap(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_FILE_OPTIONS ) ) { res = eventFileDialog(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCENARIO_INFORMATION ) ) { openMapSpecificationsDialog(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_VIEW_WORLD ) ) { eventViewWorld(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_LEFT ) ) { _gameArea.SetScroll( SCROLL_LEFT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_RIGHT ) ) { _gameArea.SetScroll( SCROLL_RIGHT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_UP ) ) { _gameArea.SetScroll( SCROLL_TOP ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_DOWN ) ) { _gameArea.SetScroll( SCROLL_BOTTOM ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::EDITOR_UNDO_LAST_ACTION ) ) { undoAction(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::EDITOR_REDO_LAST_ACTION ) ) { redoAction(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::EDITOR_TO_GAME_MAIN_MENU ) ) { const int returnValue = fheroes2::showStandardTextMessage( _( "Editor" ), _( "Do you wish to return to the game's Main Menu? All unsaved changes will be lost." ), Dialog::YES | Dialog::NO ); if ( returnValue == Dialog::YES ) { return fheroes2::GameMode::MAIN_MENU; } } else if ( HotKeyPressEvent( Game::HotKeyEvent::EDITOR_TOGGLE_PASSABILITY ) ) { conf.setEditorPassability( !conf.isEditorPassabilityEnabled() ); // This is not an ideal solution as we should save the whole configuration while tweaking one option. // However, we can improve it later if it leads to slowdowns while using the Editor. conf.Save( Settings::configFileName ); setRedraw( REDRAW_GAMEAREA ); } } if ( res != fheroes2::GameMode::CANCEL ) { break; } bool isCursorOverGameArea = false; // Mouse is captured by radar if ( _radar.isMouseCaptured() ) { cursor.SetThemes( Cursor::POINTER ); _radar.QueueEventProcessing(); } // Mouse is captured by the game area for scrolling by dragging else if ( _gameArea.isDragScroll() ) { _gameArea.QueueEventProcessing(); } else { if ( fheroes2::cursor().isFocusActive() && conf.ScrollSpeed() != SCROLL_SPEED_NONE ) { int scrollDirection = SCROLL_NONE; if ( isScrollLeft( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_LEFT; } else if ( isScrollRight( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_RIGHT; } if ( isScrollTop( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_TOP; } else if ( isScrollBottom( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_BOTTOM; } if ( scrollDirection != SCROLL_NONE && _gameArea.isFastScrollEnabled() ) { if ( Game::validateAnimationDelay( Game::SCROLL_START_DELAY ) && fastScrollRepeatCount < fastScrollStartThreshold ) { ++fastScrollRepeatCount; } if ( fastScrollRepeatCount >= fastScrollStartThreshold ) { _gameArea.SetScroll( scrollDirection ); } } else { fastScrollRepeatCount = 0; } } else { fastScrollRepeatCount = 0; } // Re-enable fast scrolling if the cursor movement indicates the need if ( !_gameArea.isFastScrollEnabled() && _gameArea.mouseIndicatesFastScroll( le.getMouseCursorPos() ) ) { _gameArea.setFastScrollStatus( true ); } // Cursor is over the radar if ( le.isMouseCursorPosInArea( _radar.GetRect() ) ) { cursor.SetThemes( Cursor::POINTER ); // TODO: Add checks for object placing/moving, and other Editor functions that uses mouse dragging. if ( _editorPanel.getBrushArea().width > 0 || _areaSelectionStartTileId == -1 ) { _radar.QueueEventProcessing(); } } // Cursor is over the editor panel else if ( le.isMouseCursorPosInArea( _editorPanel.getRect() ) ) { // At lower resolutions, the Editor panel has no border at the bottom. If the mouse cursor is over // this bottom section, then the game area may scroll. In this case, the mouse cursor shouldn't be // changed, but the editor panel should still handle events. if ( !_gameArea.NeedScroll() ) { cursor.SetThemes( Cursor::POINTER ); } res = _editorPanel.queueEventProcessing(); } else if ( !_gameArea.NeedScroll() ) { // Cursor is over the game area if ( le.isMouseCursorPosInArea( _gameArea.GetROI() ) ) { _gameArea.QueueEventProcessing(); isCursorOverGameArea = true; } // Cursor is somewhere else else { cursor.SetThemes( Cursor::POINTER ); } } } if ( res != fheroes2::GameMode::CANCEL ) { break; } if ( isCursorOverGameArea ) { // Get relative tile position under the cursor. This position can be outside the map size. const fheroes2::Point posInGameArea = _gameArea.getInternalPosition( le.getMouseCursorPos() ); const fheroes2::Point tilePos{ posInGameArea.x / fheroes2::tileWidthPx, posInGameArea.y / fheroes2::tileWidthPx }; const bool isValidTile = ( tilePos.x >= 0 && tilePos.y >= 0 && tilePos.x < world.w() && tilePos.y < world.h() ); const bool isBrushEmpty = ( _editorPanel.getBrushArea() == fheroes2::Rect() ); if ( isValidTile ) { const int32_t tileIndex = tilePos.y * world.w() + tilePos.x; if ( _tileUnderCursor != tileIndex ) { _tileUnderCursor = tileIndex; // Force redraw if cursor position was changed as area rectangle is also changed. if ( _editorPanel.showAreaSelectRect() && ( !isBrushEmpty || _areaSelectionStartTileId != -1 ) ) { _redraw |= REDRAW_GAMEAREA; } } } else if ( _areaSelectionStartTileId != -1 ) { assert( _editorPanel.showAreaSelectRect() && isBrushEmpty ); const fheroes2::Point clampedPoint{ std::clamp( tilePos.x, 0, world.w() - 1 ), std::clamp( tilePos.y, 0, world.h() - 1 ) }; const int32_t tileIndex = clampedPoint.y * world.w() + clampedPoint.x; if ( _tileUnderCursor != tileIndex ) { _tileUnderCursor = tileIndex; // Force redraw if cursor position was changed as area rectangle is also changed. _redraw |= REDRAW_GAMEAREA; } } if ( _areaSelectionStartTileId == -1 && isValidTile && isBrushEmpty && le.isMouseLeftButtonPressed() ) { _areaSelectionStartTileId = tilePos.y * world.w() + tilePos.x; _redraw |= REDRAW_GAMEAREA; } } else if ( _tileUnderCursor != -1 ) { _tileUnderCursor = -1; _redraw |= REDRAW_GAMEAREA; } if ( _areaSelectionStartTileId > -1 && le.isMouseLeftButtonReleased() ) { if ( isCursorOverGameArea && _tileUnderCursor > -1 && _editorPanel.getBrushArea().width == 0 ) { if ( _editorPanel.isTerrainEdit() ) { // Fill the selected area in terrain edit mode. fheroes2::ActionCreator action( _historyManager, _mapFormat ); const int groundId = _editorPanel.selectedGroundType(); Maps::setTerrainOnTiles( _areaSelectionStartTileId, _tileUnderCursor, groundId ); _validateObjectsOnTerrainUpdate(); action.commit(); _redraw |= mapUpdateFlags; // TODO: Make a proper function to remove all types of objects from the 'world tiles' not to do full reload of '_mapFormat'. Maps::readMapInEditor( _mapFormat ); } else if ( _editorPanel.isEraseMode() ) { // Erase objects in the selected area. fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( removeObjects( _mapFormat, Maps::getObjectUidsInArea( _areaSelectionStartTileId, _tileUnderCursor ), _editorPanel.getEraseObjectGroups() ) ) { action.commit(); _redraw |= mapUpdateFlags; // TODO: Make a proper function to remove all types of objects from the 'world tiles' not to do full reload of '_mapFormat'. Maps::readMapInEditor( _mapFormat ); } } } // Reset the area start tile. _areaSelectionStartTileId = -1; _redraw |= mapUpdateFlags; } // Scrolling the game area if ( _gameArea.NeedScroll() && Game::validateAnimationDelay( Game::SCROLL_DELAY ) ) { assert( !_gameArea.isDragScroll() ); if ( isScrollLeft( le.getMouseCursorPos() ) || isScrollRight( le.getMouseCursorPos() ) || isScrollTop( le.getMouseCursorPos() ) || isScrollBottom( le.getMouseCursorPos() ) ) { cursor.SetThemes( _gameArea.GetScrollCursor() ); } _gameArea.Scroll(); setRedraw( REDRAW_GAMEAREA | REDRAW_RADAR_CURSOR ); } else if ( _gameArea.needDragScrollRedraw() ) { setRedraw( REDRAW_GAMEAREA | REDRAW_RADAR_CURSOR ); } assert( res == fheroes2::GameMode::CANCEL ); // Map objects animation if ( Game::validateAnimationDelay( Game::MAPS_DELAY ) ) { if ( conf.isEditorAnimationEnabled() ) { Game::updateAdventureMapAnimationIndex(); } _redraw |= REDRAW_GAMEAREA; } if ( needRedraw() ) { if ( conf.isEditorPassabilityEnabled() ) { _redraw |= REDRAW_PASSABILITIES; } redraw( 0 ); // If this assertion blows up it means that we are holding a RedrawLocker lock for rendering which should not happen. assert( getRedrawMask() == 0 ); validateFadeInAndRender(); } } Game::setDisplayFadeIn(); fheroes2::fadeOutDisplay(); return res; } fheroes2::GameMode EditorInterface::eventLoadMap() { return Dialog::YES == fheroes2::showStandardTextMessage( "", _( "Are you sure you want to load a new map? (Any unsaved changes to the current map will be lost.)" ), Dialog::YES | Dialog::NO ) ? fheroes2::GameMode::EDITOR_LOAD_MAP : fheroes2::GameMode::CANCEL; } fheroes2::GameMode EditorInterface::eventNewMap() { return Dialog::YES == fheroes2::showStandardTextMessage( "", _( "Are you sure you want to create a new map? (Any unsaved changes to the current map will be lost.)" ), Dialog::YES | Dialog::NO ) ? fheroes2::GameMode::EDITOR_NEW_MAP : fheroes2::GameMode::CANCEL; } fheroes2::GameMode EditorInterface::eventFileDialog() { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 418 - fheroes2::borderWidthPx * 2, 236 - fheroes2::borderWidthPx * 2, true, display ); fheroes2::Button buttonNew; fheroes2::Button buttonLoad; fheroes2::Button buttonSave; fheroes2::Button buttonQuit; fheroes2::ButtonSprite buttonMainMenu; fheroes2::ButtonSprite buttonPlayMap; fheroes2::Button buttonCancel; const Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const fheroes2::Point buttonOffsets = { 30, 15 }; background.renderButton( buttonNew, isEvilInterface ? ICN::BUTTON_NEW_MAP_EVIL : ICN::BUTTON_NEW_MAP_GOOD, 0, 1, buttonOffsets, fheroes2::StandardWindow::Padding::TOP_LEFT ); background.renderButton( buttonLoad, isEvilInterface ? ICN::BUTTON_LOAD_MAP_EVIL : ICN::BUTTON_LOAD_MAP_GOOD, 0, 1, { 0, buttonOffsets.y }, fheroes2::StandardWindow::Padding::TOP_CENTER ); background.renderButton( buttonSave, isEvilInterface ? ICN::BUTTON_SAVE_MAP_EVIL : ICN::BUTTON_SAVE_MAP_GOOD, 0, 1, { buttonOffsets.x, buttonOffsets.y }, fheroes2::StandardWindow::Padding::CENTER_LEFT ); background.renderButton( buttonQuit, isEvilInterface ? ICN::BUTTON_QUIT_EVIL : ICN::BUTTON_QUIT_GOOD, 0, 1, { buttonOffsets.x, buttonOffsets.y }, fheroes2::StandardWindow::Padding::CENTER_RIGHT ); const fheroes2::FontType releasedButtonFont{ fheroes2::FontSize::BUTTON_RELEASED, fheroes2::FontColor::WHITE }; background.renderButtonSprite( buttonMainMenu, fheroes2::getSupportedText( gettext_noop( "MAIN\nMENU" ), releasedButtonFont ), { buttonSave.area().width - 10, buttonSave.area().height }, { 0, buttonOffsets.y }, isEvilInterface, fheroes2::StandardWindow::Padding::CENTER_CENTER ); background.renderButtonSprite( buttonPlayMap, fheroes2::getSupportedText( gettext_noop( "START\nMAP" ), releasedButtonFont ), { buttonSave.area().width - 10, buttonSave.area().height }, { buttonOffsets.x, buttonOffsets.y }, isEvilInterface, fheroes2::StandardWindow::Padding::TOP_RIGHT ); background.renderButton( buttonCancel, isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonNew.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNew.area() ) ); buttonLoad.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLoad.area() ) ); buttonSave.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSave.area() ) ); buttonQuit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonQuit.area() ) ); buttonMainMenu.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMainMenu.area() ) ); buttonPlayMap.drawOnState( le.isMouseLeftButtonPressedInArea( buttonPlayMap.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonNew.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_NEW_MAP_MENU ) ) { if ( eventNewMap() == fheroes2::GameMode::EDITOR_NEW_MAP ) { return fheroes2::GameMode::EDITOR_NEW_MAP; } } if ( le.MouseClickLeft( buttonLoad.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME ) ) { if ( eventLoadMap() == fheroes2::GameMode::EDITOR_LOAD_MAP ) { return fheroes2::GameMode::EDITOR_LOAD_MAP; } } if ( le.MouseClickLeft( buttonSave.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::WORLD_SAVE_GAME ) ) { // Special case: since we show a window about file saving we don't want to display the current dialog anymore. background.hideWindow(); Get().saveMapToFile(); return fheroes2::GameMode::CANCEL; } if ( le.MouseClickLeft( buttonQuit.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_QUIT ) ) { if ( EventExit() == fheroes2::GameMode::QUIT_GAME ) { return fheroes2::GameMode::QUIT_GAME; } } if ( le.MouseClickLeft( buttonMainMenu.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_TO_GAME_MAIN_MENU ) ) { if ( fheroes2::showStandardTextMessage( _( "Main Menu" ), _( "Do you wish to return to the game's Main Menu? (Any unsaved changes to the current map will be lost.)" ), Dialog::YES | Dialog::NO ) == Dialog::YES ) { return fheroes2::GameMode::MAIN_MENU; } } else if ( le.MouseClickLeft( buttonPlayMap.area() ) ) { bool isNameEmpty = conf.getCurrentMapInfo().name.empty(); if ( isNameEmpty && fheroes2::showStandardTextMessage( _( "Unsaved Changes" ), _( "This map has either terrain changes, undo history or has not yet been saved to a file.\n\nDo you wish to save the current map?" ), Dialog::YES | Dialog::NO ) == Dialog::NO ) { continue; } if ( isNameEmpty ) { Get().saveMapToFile(); isNameEmpty = conf.getCurrentMapInfo().name.empty(); if ( isNameEmpty ) { // Saving was aborted. display.render( background.totalArea() ); continue; } } if ( conf.getCurrentMapInfo().colorsAvailableForHumans == 0 ) { fheroes2::showStandardTextMessage( _( "Unplayable Map" ), _( "This map is not playable. You need at least one human player for the map to be playable." ), Dialog::OK ); } else { if ( fheroes2:: showStandardTextMessage( _( "Start Map" ), _( "Do you wish to leave the Editor and start the map? (Any unsaved changes to the current map will be lost.)" ), Dialog::YES | Dialog::NO ) == Dialog::YES ) { return fheroes2::GameMode::NEW_STANDARD; } } } else if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyCloseWindow() ) { return fheroes2::GameMode::CANCEL; } if ( le.isMouseRightButtonPressedInArea( buttonNew.area() ) ) { // TODO: update this text once random map generator is ready. // The original text should be "Create a new map, either from scratch or using the random map generator." fheroes2::showStandardTextMessage( _( "New Map" ), _( "Create a new map from scratch." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonLoad.area() ) ) { fheroes2::showStandardTextMessage( _( "Load Map" ), _( "Load an existing map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonSave.area() ) ) { fheroes2::showStandardTextMessage( _( "Save Map" ), _( "Save the current map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonQuit.area() ) ) { fheroes2::showStandardTextMessage( _( "Quit" ), _( "Quit out of the map editor." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonMainMenu.area() ) ) { fheroes2::showStandardTextMessage( _( "Main Menu" ), _( "Return to the game's Main Menu." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonPlayMap.area() ) ) { fheroes2::showStandardTextMessage( _( "Start Map" ), _( "Leave the Editor and play the map in the Standard Game mode." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } } return fheroes2::GameMode::CANCEL; } void EditorInterface::eventViewWorld() { // TODO: Make proper borders restoration for low height resolutions, like for hide interface mode. ViewWorld::ViewWorldWindow( 0, ViewWorldMode::ViewAll, *this ); } void EditorInterface::mouseCursorAreaClickLeft( const int32_t tileIndex ) { assert( tileIndex >= 0 && tileIndex < static_cast( world.getSize() ) ); Maps::Tile & tile = world.getTile( tileIndex ); if ( _editorPanel.isDetailEdit() ) { // Trigger an action only when metadata has been changed to avoid expensive computations and bloated list of actions. // Comparing a metadata structure is much faster than restoring the whole map. for ( const auto & object : _mapFormat.tiles[tileIndex].objects ) { const auto & objectGroupInfo = Maps::getObjectsByGroup( object.group ); assert( object.index <= objectGroupInfo.size() ); const auto & objectInfo = objectGroupInfo[object.index]; assert( !objectInfo.groundLevelParts.empty() ); const MP2::MapObjectType objectType = objectInfo.groundLevelParts.front().objectType; const bool isActionObject = MP2::isOffGameActionObject( objectType ); if ( !isActionObject ) { // Only action objects can have metadata. continue; } if ( objectType == MP2::OBJ_HERO || objectType == MP2::OBJ_JAIL ) { assert( _mapFormat.heroMetadata.find( object.id ) != _mapFormat.heroMetadata.end() ); const int color = ( objectType == MP2::OBJ_JAIL ) ? Color::NONE : ( 1 << objectInfo.metadata[0] ); // Make a temporary hero to edit his details. Heroes hero; hero.SetColor( color ); hero.applyHeroMetadata( _mapFormat.heroMetadata[object.id], objectType == MP2::OBJ_JAIL, true ); hero.OpenDialog( false, false, true, true, true, true, _mapFormat.mainLanguage ); Maps::Map_Format::HeroMetadata heroNewMetadata = hero.getHeroMetadata(); if ( heroNewMetadata != _mapFormat.heroMetadata[object.id] ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); _mapFormat.heroMetadata[object.id] = std::move( heroNewMetadata ); action.commit(); } } else if ( objectType == MP2::OBJ_CASTLE || objectType == MP2::OBJ_RANDOM_TOWN || objectType == MP2::OBJ_RANDOM_CASTLE ) { assert( _mapFormat.castleMetadata.find( object.id ) != _mapFormat.castleMetadata.end() ); const int race = Race::IndexToRace( static_cast( objectInfo.metadata[0] ) ); const int color = Color::IndexToColor( Maps::getTownColorIndex( _mapFormat, tileIndex, object.id ) ); auto & castleMetadata = _mapFormat.castleMetadata[object.id]; Maps::Map_Format::CastleMetadata newCastleMetadata = castleMetadata; Editor::castleDetailsDialog( newCastleMetadata, race, color, _mapFormat.mainLanguage ); if ( castleMetadata != newCastleMetadata ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); castleMetadata = std::move( newCastleMetadata ); action.commit(); } } else if ( objectType == MP2::OBJ_SIGN || objectType == MP2::OBJ_BOTTLE ) { std::string header = _( "Input %{object} text" ); StringReplace( header, "%{object}", MP2::StringObject( objectType ) ); auto & originalMessage = _mapFormat.signMetadata[object.id].message; std::string signText = originalMessage; const fheroes2::Text body{ std::move( header ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, signText, 0, true, _mapFormat.mainLanguage ) && originalMessage != signText ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); originalMessage = std::move( signText ); action.commit(); } } else if ( objectType == MP2::OBJ_EVENT ) { assert( _mapFormat.adventureMapEventMetadata.find( object.id ) != _mapFormat.adventureMapEventMetadata.end() ); auto & eventMetadata = _mapFormat.adventureMapEventMetadata[object.id]; Maps::Map_Format::AdventureMapEventMetadata newEventData = eventMetadata; if ( Editor::eventDetailsDialog( newEventData, _mapFormat.humanPlayerColors, _mapFormat.computerPlayerColors, _mapFormat.mainLanguage ) && newEventData != eventMetadata ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); eventMetadata = std::move( newEventData ); action.commit(); } } else if ( object.group == Maps::ObjectGroup::MONSTERS ) { int32_t monsterCount = 0; auto monsterMetadata = _mapFormat.standardMetadata.find( object.id ); if ( monsterMetadata != _mapFormat.standardMetadata.end() ) { monsterCount = monsterMetadata->second.metadata[0]; } else { // This could be a corrupted map. Add missing metadata into it. This action should be outside action manager scope. _mapFormat.standardMetadata[object.id] = { 0, 0, Monster::JOIN_CONDITION_UNSET }; } const Monster tempMonster( static_cast( object.index ) + 1 ); std::string str = _( "Set %{monster} Count" ); StringReplace( str, "%{monster}", tempMonster.GetName() ); std::unique_ptr monsterUi = nullptr; if ( tempMonster.isValid() ) { monsterUi = std::make_unique( tempMonster ); } if ( Dialog::SelectCount( std::move( str ), 0, 500000, monsterCount, 1, monsterUi.get() ) && _mapFormat.standardMetadata[object.id].metadata[0] != monsterCount ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); _mapFormat.standardMetadata[object.id] = { monsterCount, 0, Monster::JOIN_CONDITION_UNSET }; action.commit(); } } else if ( objectInfo.objectType == MP2::OBJ_RESOURCE ) { int32_t resourceCount = 0; auto resourceMetadata = _mapFormat.standardMetadata.find( object.id ); if ( resourceMetadata != _mapFormat.standardMetadata.end() ) { resourceCount = resourceMetadata->second.metadata[0]; } else { // This could be a corrupted or older format map. Add missing metadata into it. This action should be outside action manager scope. _mapFormat.standardMetadata[object.id] = { 0, 0, 0 }; } const int32_t resourceType = static_cast( objectInfo.metadata[0] ); const fheroes2::ResourceDialogElement resourceUI( resourceType, {} ); std::string str = _( "Set %{resource-type} Count" ); StringReplace( str, "%{resource-type}", Resource::String( resourceType ) ); // We cannot support more than 6 digits in the dialog due to its UI element size. if ( Dialog::SelectCount( std::move( str ), 0, 999999, resourceCount, 1, &resourceUI ) && _mapFormat.standardMetadata[object.id].metadata[0] != resourceCount ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); _mapFormat.standardMetadata[object.id] = { resourceCount, 0, 0 }; action.commit(); } } else if ( object.group == Maps::ObjectGroup::ADVENTURE_ARTIFACTS ) { if ( objectInfo.objectType == MP2::OBJ_RANDOM_ULTIMATE_ARTIFACT ) { assert( _mapFormat.standardMetadata.find( object.id ) != _mapFormat.standardMetadata.end() ); auto & originalRadius = _mapFormat.standardMetadata[object.id].metadata[0]; int32_t radius = originalRadius; if ( Dialog::SelectCount( _( "Set Random Ultimate Artifact Radius" ), 0, 100, radius ) && radius != originalRadius ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); originalRadius = radius; action.commit(); } } else if ( objectInfo.objectType == MP2::OBJ_ARTIFACT && objectInfo.metadata[0] == Artifact::SPELL_SCROLL ) { // Find Artifact object. assert( _mapFormat.standardMetadata.find( object.id ) != _mapFormat.standardMetadata.end() ); auto & artifactSpellId = _mapFormat.standardMetadata[object.id].metadata[0]; const int newSpellId = Dialog::selectSpell( artifactSpellId, true ).GetID(); if ( newSpellId == Spell::NONE || artifactSpellId == newSpellId ) { // We do not place the Spell Scroll artifact if the spell for it was not selected // or when the same spell was chosen. return; } fheroes2::ActionCreator action( _historyManager, _mapFormat ); artifactSpellId = newSpellId; Maps::setSpellOnTile( tile, newSpellId ); action.commit(); } else if ( Artifact( static_cast( objectInfo.metadata[0] ) ).isValid() ) { fheroes2::ArtifactDialogElement( static_cast( objectInfo.metadata[0] ) ).showPopup( Dialog::OK ); } else { std::string msg = _( "%{object} has no properties to change." ); StringReplace( msg, "%{object}", _( "This artifact" ) ); _warningMessage.reset( std::move( msg ) ); } } else if ( objectType == MP2::OBJ_SPHINX ) { assert( _mapFormat.sphinxMetadata.find( object.id ) != _mapFormat.sphinxMetadata.end() ); auto & originalMetadata = _mapFormat.sphinxMetadata[object.id]; Maps::Map_Format::SphinxMetadata newMetadata = originalMetadata; if ( Editor::openSphinxWindow( newMetadata, _mapFormat.mainLanguage ) && newMetadata != originalMetadata ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); originalMetadata = std::move( newMetadata ); action.commit(); } } else if ( objectType == MP2::OBJ_SHRINE_FIRST_CIRCLE || objectType == MP2::OBJ_SHRINE_SECOND_CIRCLE || objectType == MP2::OBJ_SHRINE_THIRD_CIRCLE ) { if ( _mapFormat.selectionObjectMetadata.find( object.id ) == _mapFormat.selectionObjectMetadata.end() ) { _mapFormat.selectionObjectMetadata[object.id] = {}; } auto & originalMetadata = _mapFormat.selectionObjectMetadata[object.id]; auto newMetadata = originalMetadata; int spellLevel = 0; if ( objectType == MP2::OBJ_SHRINE_FIRST_CIRCLE ) { spellLevel = 1; } else if ( objectType == MP2::OBJ_SHRINE_SECOND_CIRCLE ) { spellLevel = 2; } else if ( objectType == MP2::OBJ_SHRINE_THIRD_CIRCLE ) { spellLevel = 3; } else { assert( 0 ); spellLevel = 1; } if ( Editor::openSpellSelectionWindow( MP2::StringObject( objectType ), spellLevel, newMetadata.selectedItems ) && originalMetadata.selectedItems != newMetadata.selectedItems ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); originalMetadata = std::move( newMetadata ); action.commit(); } } else if ( objectType == MP2::OBJ_WITCHS_HUT ) { if ( _mapFormat.selectionObjectMetadata.find( object.id ) == _mapFormat.selectionObjectMetadata.end() ) { _mapFormat.selectionObjectMetadata[object.id] = {}; } auto & originalMetadata = _mapFormat.selectionObjectMetadata[object.id]; auto newMetadata = originalMetadata; if ( Editor::openSecondarySkillSelectionWindow( MP2::StringObject( objectType ), 1, newMetadata.selectedItems ) && originalMetadata.selectedItems != newMetadata.selectedItems ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); originalMetadata = std::move( newMetadata ); action.commit(); } } else if ( objectType == MP2::OBJ_PYRAMID ) { if ( _mapFormat.selectionObjectMetadata.find( object.id ) == _mapFormat.selectionObjectMetadata.end() ) { _mapFormat.selectionObjectMetadata[object.id] = {}; } auto & originalMetadata = _mapFormat.selectionObjectMetadata[object.id]; auto newMetadata = originalMetadata; if ( Editor::openSpellSelectionWindow( MP2::StringObject( objectType ), 5, newMetadata.selectedItems ) && originalMetadata.selectedItems != newMetadata.selectedItems ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); originalMetadata = std::move( newMetadata ); action.commit(); } } else if ( objectType == MP2::OBJ_OBELISK ) { std::string str = _( "The total number of obelisks is %{count}." ); StringReplace( str, "%{count}", getObeliskCount( _mapFormat ) ); fheroes2::showStandardTextMessage( MP2::StringObject( objectType ), std::move( str ), Dialog::OK ); } else { std::string msg = _( "%{object} has no properties to change." ); StringReplace( msg, "%{object}", MP2::StringObject( objectType ) ); _warningMessage.reset( std::move( msg ) ); } } } else if ( _editorPanel.isTerrainEdit() ) { const fheroes2::Rect brushSize = _editorPanel.getBrushArea(); assert( brushSize.width == brushSize.height ); const int groundId = _editorPanel.selectedGroundType(); fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( brushSize.width > 0 ) { const fheroes2::Point indices = getBrushAreaIndicies( brushSize, tileIndex ); Maps::setTerrainOnTiles( indices.x, indices.y, groundId ); } else { assert( brushSize.width == 0 ); // This is a case when area was not selected but a single tile was clicked. Maps::setTerrainOnTiles( tileIndex, tileIndex, groundId ); _areaSelectionStartTileId = -1; } _validateObjectsOnTerrainUpdate(); _redraw |= mapUpdateFlags; action.commit(); // TODO: Make a proper function to remove all types of objects from the 'world tiles' not to do full reload of '_mapFormat'. Maps::readMapInEditor( _mapFormat ); } else if ( _editorPanel.isRoadDraw() ) { if ( tile.isWater() ) { std::string msg = _( "%{objects} cannot be placed on water." ); StringReplace( msg, "%{objects}", _( "Roads" ) ); _warningMessage.reset( std::move( msg ) ); return; } fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( Maps::updateRoadOnTile( tile, true ) ) { _redraw |= mapUpdateFlags; action.commit(); } } else if ( _editorPanel.isStreamDraw() ) { if ( tile.isWater() ) { std::string msg = _( "%{objects} cannot be placed on water." ); StringReplace( msg, "%{objects}", _( "Streams" ) ); _warningMessage.reset( std::move( msg ) ); return; } fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( Maps::addStream( _mapFormat, tileIndex ) ) { _redraw |= mapUpdateFlags; action.commit(); } } else if ( _editorPanel.isEraseMode() ) { const fheroes2::Rect brushSize = _editorPanel.getBrushArea(); assert( brushSize.width == brushSize.height ); fheroes2::ActionCreator action( _historyManager, _mapFormat ); const fheroes2::Point indices = getBrushAreaIndicies( brushSize, tileIndex ); if ( removeObjects( _mapFormat, Maps::getObjectUidsInArea( indices.x, indices.y ), _editorPanel.getEraseObjectGroups() ) ) { action.commit(); _redraw |= mapUpdateFlags; // TODO: Make a proper function to remove all types of objects from the 'world tiles' not to do full reload of '_mapFormat'. Maps::readMapInEditor( _mapFormat ); } if ( brushSize.width == 0 ) { // This is a case when area was not selected but a single tile was clicked. _areaSelectionStartTileId = -1; } } else if ( _editorPanel.isObjectMode() ) { _handleObjectMouseLeftClick( tile ); } } void EditorInterface::_handleObjectMouseLeftClick( Maps::Tile & tile ) { assert( _editorPanel.isObjectMode() ); const int32_t objectType = _editorPanel.getSelectedObjectType(); if ( objectType < 0 ) { return; } const fheroes2::Point tilePos = tile.GetCenter(); const Maps::ObjectGroup groupType = _editorPanel.getSelectedObjectGroup(); if ( _moveExistingObject( tile.GetIndex(), groupType, objectType ) ) { return; } std::string errorMessage; if ( groupType == Maps::ObjectGroup::KINGDOM_HEROES ) { if ( !verifyObjectPlacement( tilePos, groupType, objectType, errorMessage ) ) { _warningMessage.reset( std::move( errorMessage ) ); return; } const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); // Heroes are limited to 8 per color so all attempts to set more than 8 heroes must be prevented. const auto & objects = Maps::getObjectsByGroup( groupType ); const uint32_t color = objectInfo.metadata[0]; size_t heroCount = 0; for ( const auto & mapTile : _mapFormat.tiles ) { for ( const auto & object : mapTile.objects ) { if ( object.group == groupType ) { assert( object.index < objects.size() ); if ( objects[object.index].metadata[0] == color ) { ++heroCount; } } } } if ( heroCount >= GameStatic::GetKingdomMaxHeroes() ) { std::string warning( _( "A maximum of %{count} heroes of the same color can be placed on the map." ) ); StringReplace( warning, "%{count}", GameStatic::GetKingdomMaxHeroes() ); _warningMessage.reset( std::move( warning ) ); return; } if ( !_setObjectOnTileAsAction( tile, groupType, objectType ) ) { return; } Heroes * hero = world.GetHeroForHire( Race::IndexToRace( static_cast( objectInfo.metadata[1] ) ) ); if ( hero ) { hero->SetCenter( tilePos ); hero->SetColor( Color::IndexToColor( static_cast( color ) ) ); } else { // How is it possible that the action was successful but no hero? assert( 0 ); } if ( !Maps::updateMapPlayers( _mapFormat ) ) { _warningMessage.reset( _( "Failed to update player information." ) ); } } else if ( groupType == Maps::ObjectGroup::ADVENTURE_ARTIFACTS ) { if ( !verifyObjectPlacement( tilePos, groupType, objectType, errorMessage ) ) { _warningMessage.reset( std::move( errorMessage ) ); return; } const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); if ( objectInfo.objectType == MP2::OBJ_RANDOM_ULTIMATE_ARTIFACT ) { // First of all, verify that only one Random Ultimate artifact exists on the map. for ( const auto & tileInfo : _mapFormat.tiles ) { for ( const auto & object : tileInfo.objects ) { if ( groupType == object.group && static_cast( objectType ) == object.index ) { _warningMessage.reset( _( "Only one Random Ultimate Artifact can be placed on the map." ) ); return; } } } } // For each Spell Scroll artifact we select a spell. if ( objectInfo.objectType == MP2::OBJ_ARTIFACT && objectInfo.metadata[0] == Artifact::SPELL_SCROLL ) { const int spellId = Dialog::selectSpell( Spell::RANDOM, true ).GetID(); if ( spellId == Spell::NONE ) { // We do not place the Spell Scroll artifact if the spell for it was not selected. return; } if ( !_setObjectOnTileAsAction( tile, groupType, objectType ) ) { return; } assert( !_mapFormat.tiles[tile.GetIndex()].objects.empty() ); const auto & insertedObject = _mapFormat.tiles[tile.GetIndex()].objects.back(); assert( insertedObject.group == groupType && insertedObject.index == static_cast( objectType ) ); assert( _mapFormat.standardMetadata.find( insertedObject.id ) != _mapFormat.standardMetadata.end() ); _mapFormat.standardMetadata[insertedObject.id].metadata[0] = spellId; Maps::setSpellOnTile( tile, spellId ); } else { _setObjectOnTileAsAction( tile, groupType, objectType ); } } else if ( groupType == Maps::ObjectGroup::KINGDOM_TOWNS ) { int32_t type = -1; int32_t color = -1; _editorPanel.getTownObjectProperties( type, color ); if ( type < 0 || color < 0 ) { // Check your logic! assert( 0 ); return; } if ( !verifyObjectPlacement( tilePos, groupType, type, errorMessage ) ) { _warningMessage.reset( std::move( errorMessage ) ); return; } const int groundType = Maps::Ground::getGroundByImageIndex( tile.getTerrainImageIndex() ); const int32_t basementId = fheroes2::getTownBasementId( groundType ); const auto & townObjectInfo = Maps::getObjectInfo( groupType, type ); fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( !_setObjectOnTile( tile, Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS, basementId ) ) { return; } // Since the whole object consists of multiple "objects" we have to put the same ID for all of them. // Every time an object is being placed on a map the counter is going to be increased by 1. // Therefore, we set the counter by 1 less for each object to match object UID for all of them. assert( Maps::getLastObjectUID() > 0 ); const uint32_t objectId = Maps::getLastObjectUID() - 1; Maps::setLastObjectUID( objectId ); if ( !_setObjectOnTile( tile, groupType, type ) ) { return; } // By default use random (default) army for the neutral race town/castle. if ( Color::IndexToColor( color ) == Color::NONE ) { Maps::setDefaultCastleDefenderArmy( _mapFormat.castleMetadata[Maps::getLastObjectUID()] ); } // Add flags. assert( tile.GetIndex() > 0 && tile.GetIndex() < world.w() * world.h() - 1 ); Maps::setLastObjectUID( objectId ); if ( !_setObjectOnTile( world.getTile( tile.GetIndex() - 1 ), Maps::ObjectGroup::LANDSCAPE_FLAGS, color * 2 ) ) { return; } Maps::setLastObjectUID( objectId ); if ( !_setObjectOnTile( world.getTile( tile.GetIndex() + 1 ), Maps::ObjectGroup::LANDSCAPE_FLAGS, color * 2 + 1 ) ) { return; } world.addCastle( tile.GetIndex(), Race::IndexToRace( static_cast( townObjectInfo.metadata[0] ) ), Color::IndexToColor( color ) ); action.commit(); if ( !Maps::updateMapPlayers( _mapFormat ) ) { _warningMessage.reset( _( "Failed to update player information." ) ); } } else if ( groupType == Maps::ObjectGroup::ADVENTURE_MINES ) { int32_t type = -1; int32_t color = -1; _editorPanel.getMineObjectProperties( type, color ); if ( type < 0 || color < 0 ) { // Check your logic! assert( 0 ); return; } if ( !verifyObjectPlacement( tilePos, groupType, type, errorMessage ) ) { _warningMessage.reset( std::move( errorMessage ) ); return; } fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( !_setObjectOnTile( tile, groupType, type ) ) { return; } // TODO: Place owner flag according to the color state. action.commit(); } else if ( groupType == Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS ) { if ( !verifyObjectPlacement( tilePos, groupType, objectType, errorMessage ) ) { _warningMessage.reset( std::move( errorMessage ) ); return; } fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( !_setObjectOnTile( tile, groupType, objectType ) ) { return; } // For River Deltas we update the nearby Streams to properly connect to them. if ( const int riverDeltaDirection = Maps::getRiverDeltaDirectionByIndex( groupType, objectType ); riverDeltaDirection != Direction::UNKNOWN ) { Maps::updateStreamsToDeltaConnection( _mapFormat, tile.GetIndex(), riverDeltaDirection ); } action.commit(); } else if ( groupType == Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS ) { const auto & objectInfo = Maps::getObjectInfo( groupType, objectType ); if ( objectInfo.objectType == MP2::OBJ_OBELISK ) { const size_t obeliskCount = getObeliskCount( _mapFormat ); if ( obeliskCount >= numOfPuzzleTiles ) { std::string warning( _( "A maximum of %{count} obelisks can be placed on the map." ) ); StringReplace( warning, "%{count}", numOfPuzzleTiles ); _warningMessage.reset( std::move( warning ) ); return; } } if ( !verifyObjectPlacement( tilePos, groupType, objectType, errorMessage ) ) { _warningMessage.reset( std::move( errorMessage ) ); return; } _setObjectOnTileAsAction( tile, groupType, objectType ); } else { if ( !verifyObjectPlacement( tilePos, groupType, objectType, errorMessage ) ) { _warningMessage.reset( std::move( errorMessage ) ); return; } _setObjectOnTileAsAction( tile, groupType, objectType ); } } void EditorInterface::mouseCursorAreaPressRight( const int32_t tileIndex ) const { Editor::showPopupWindow( world.getTile( tileIndex ), _mapFormat ); } void EditorInterface::updateCursor( const int32_t tileIndex ) { if ( _cursorUpdater && tileIndex >= 0 ) { _cursorUpdater( tileIndex ); } else { Cursor::Get().SetThemes( Cursor::POINTER ); } } bool EditorInterface::_setObjectOnTile( Maps::Tile & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex ) { const auto & objectInfo = Maps::getObjectInfo( groupType, objectIndex ); if ( objectInfo.empty() ) { // Check your logic as you are trying to insert an empty object! assert( 0 ); return false; } _redraw |= mapUpdateFlags; if ( !Maps::setObjectOnTile( tile, objectInfo, true ) ) { return false; } Maps::addObjectToMap( _mapFormat, tile.GetIndex(), groupType, static_cast( objectIndex ) ); return true; } bool EditorInterface::_setObjectOnTileAsAction( Maps::Tile & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); if ( _setObjectOnTile( tile, groupType, objectIndex ) ) { action.commit(); return true; } return false; } bool EditorInterface::loadMap( const std::string & filePath ) { if ( !Maps::Map_Format::loadMap( filePath, _mapFormat ) ) { fheroes2::showStandardTextMessage( _( "Error" ), "Failed to load the map.", Dialog::OK ); return false; } if ( !Maps::readMapInEditor( _mapFormat ) ) { fheroes2::showStandardTextMessage( _( "Error" ), "Failed to read the map.", Dialog::OK ); return false; } _loadedFileName = System::GetStem( filePath ); // Set the loaded map as a default map for the new Standard Game. Maps::FileInfo fi; if ( fi.loadResurrectionMap( _mapFormat, filePath ) ) { Settings::Get().setCurrentMapInfo( std::move( fi ) ); } else { assert( 0 ); } return true; } void EditorInterface::saveMapToFile() { if ( !Maps::updateMapPlayers( _mapFormat ) ) { fheroes2::showStandardTextMessage( _( "Error" ), _( "The map is corrupted." ), Dialog::OK ); return; } const std::string dataPath = System::GetDataDirectory( "fheroes2" ); if ( dataPath.empty() ) { fheroes2::showStandardTextMessage( _( "Error" ), _( "Unable to locate data directory to save the map." ), Dialog::OK ); return; } std::string mapDirectory = System::concatPath( dataPath, "maps" ); if ( !System::IsDirectory( mapDirectory ) && !System::MakeDirectory( mapDirectory ) ) { fheroes2::showStandardTextMessage( _( "Error" ), _( "Unable to create a directory to save the map." ), Dialog::OK ); return; } // Since the name of the map directory can be in arbitrary case, we need to get its real case-sensitive name first { std::string correctedMapDirectory; if ( !System::GetCaseInsensitivePath( mapDirectory, correctedMapDirectory ) ) { fheroes2::showStandardTextMessage( _( "Error" ), _( "Unable to locate a directory to save the map." ), Dialog::OK ); return; } mapDirectory = std::move( correctedMapDirectory ); } std::string fileName = _loadedFileName; std::string mapName = _mapFormat.name; std::string fullPath; while ( true ) { if ( !Editor::mapSaveSelectFile( fileName, mapName, _mapFormat.mainLanguage, maxMapNameLength ) ) { return; } fullPath = System::concatPath( mapDirectory, fileName + ".fh2m" ); if ( !System::IsFile( fullPath ) || fheroes2::showStandardTextMessage( "", _( "Are you sure you want to overwrite the existing map?" ), Dialog::YES | Dialog::NO ) == Dialog::YES ) { break; } } _mapFormat.name = std::move( mapName ); _loadedFileName = std::move( fileName ); if ( Maps::Map_Format::saveMap( fullPath, _mapFormat ) ) { // Set the saved map as a default map for the new Standard Game. Maps::FileInfo fi; if ( fi.loadResurrectionMap( _mapFormat, fullPath ) ) { Settings::Get().setCurrentMapInfo( std::move( fi ) ); } else { assert( 0 ); } _warningMessage.reset( _( "Map saved to: " ) + std::move( fullPath ) ); return; } fheroes2::showStandardTextMessage( _( "Error" ), _( "Failed to save the map." ), Dialog::OK ); } void EditorInterface::openMapSpecificationsDialog() { Maps::Map_Format::MapFormat mapBackup = _mapFormat; if ( Editor::mapSpecificationsDialog( _mapFormat, maxMapNameLength ) ) { fheroes2::ActionCreator action( _historyManager, _mapFormat ); action.commit(); } else { _mapFormat = std::move( mapBackup ); } } void EditorInterface::_validateObjectsOnTerrainUpdate() { std::string errorMessage; std::set uids; for ( size_t i = 0; i < _mapFormat.tiles.size(); ++i ) { const fheroes2::Point pos{ static_cast( i ) % world.w(), static_cast( i ) / world.w() }; bool removeRoad = false; for ( const auto & object : _mapFormat.tiles[i].objects ) { if ( object.group == Maps::ObjectGroup::LANDSCAPE_FLAGS || object.group == Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS ) { // These objects belong to the main objects and will be checked with them. continue; } if ( object.group == Maps::ObjectGroup::ROADS ) { if ( world.getTile( static_cast( i ) ).isWater() ) { removeRoad = true; } continue; } if ( !verifyTerrainPlacement( pos, object.group, static_cast( object.index ), errorMessage ) ) { uids.emplace( object.id ); } } if ( removeRoad ) { auto & worldTile = world.getTile( static_cast( i ) ); Maps::updateRoadOnTile( worldTile, false ); } } if ( !uids.empty() ) { std::set groups; for ( int32_t i = 0; i < static_cast( Maps::ObjectGroup::GROUP_COUNT ); ++i ) { groups.emplace( static_cast( i ) ); } removeObjects( _mapFormat, uids, groups ); } // Run through each town and castle and update its terrain. for ( size_t i = 0; i < _mapFormat.tiles.size(); ++i ) { for ( auto & object : _mapFormat.tiles[i].objects ) { if ( object.group == Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS ) { const auto & worldTile = world.getTile( static_cast( i ) ); const int groundType = Maps::Ground::getGroundByImageIndex( worldTile.getTerrainImageIndex() ); const int32_t basementId = fheroes2::getTownBasementId( groundType ); object.index = static_cast( basementId ); } } } } bool EditorInterface::_moveExistingObject( const int32_t tileIndex, const Maps::ObjectGroup groupType, int32_t objectIndex ) { assert( tileIndex >= 0 && static_cast( tileIndex ) < _mapFormat.tiles.size() ); if ( groupType == Maps::ObjectGroup::KINGDOM_TOWNS ) { int32_t type = -1; int32_t color = -1; _editorPanel.getTownObjectProperties( type, color ); if ( type < 0 || color < 0 ) { // Check your logic! assert( 0 ); return false; } objectIndex = type; } else if ( groupType == Maps::ObjectGroup::ADVENTURE_MINES ) { int32_t type = -1; int32_t color = -1; _editorPanel.getMineObjectProperties( type, color ); if ( type < 0 || color < 0 ) { // Check your logic! assert( 0 ); return false; } objectIndex = type; } for ( const auto & object : _mapFormat.tiles[tileIndex].objects ) { if ( object.group == groupType && object.index == static_cast( objectIndex ) ) { if ( object.id == Maps::getLastObjectUID() ) { // Just do nothing since this is the last object. return true; } const uint32_t oldObjectUID = object.id; fheroes2::ActionCreator action( _historyManager, _mapFormat ); const uint32_t newObjectUID = Maps::getNewObjectUID(); _updateObjectMetadata( object, newObjectUID ); _updateObjectUID( oldObjectUID, newObjectUID ); action.commit(); // TODO: so far this is the only way to update objects for rendering. return Maps::readMapInEditor( _mapFormat ); } } return false; } void EditorInterface::_updateObjectMetadata( const Maps::Map_Format::TileObjectInfo & object, const uint32_t newObjectUID ) { const auto & objectGroupInfo = Maps::getObjectsByGroup( object.group ); assert( object.index <= objectGroupInfo.size() ); const auto & objectInfo = objectGroupInfo[object.index]; assert( !objectInfo.groundLevelParts.empty() ); const MP2::MapObjectType objectType = objectInfo.groundLevelParts.front().objectType; const bool isActionObject = MP2::isOffGameActionObject( objectType ); if ( !isActionObject ) { // Only action objects have metadata. return; } [[maybe_unused]] size_t objectsReplaced = 0; // This logic is based on an assumption that only one action object can exist on one tile. if ( replaceKey( _mapFormat.standardMetadata, object.id, newObjectUID ) ) { ++objectsReplaced; } if ( replaceKey( _mapFormat.castleMetadata, object.id, newObjectUID ) ) { ++objectsReplaced; } if ( replaceKey( _mapFormat.heroMetadata, object.id, newObjectUID ) ) { ++objectsReplaced; } if ( replaceKey( _mapFormat.sphinxMetadata, object.id, newObjectUID ) ) { ++objectsReplaced; } if ( replaceKey( _mapFormat.signMetadata, object.id, newObjectUID ) ) { ++objectsReplaced; } if ( replaceKey( _mapFormat.adventureMapEventMetadata, object.id, newObjectUID ) ) { ++objectsReplaced; } if ( replaceKey( _mapFormat.selectionObjectMetadata, object.id, newObjectUID ) ) { ++objectsReplaced; } assert( objectsReplaced == 0 || objectsReplaced == 1 ); } void EditorInterface::_updateObjectUID( const uint32_t oldObjectUID, const uint32_t newObjectUID ) { for ( auto & tile : _mapFormat.tiles ) { for ( size_t i = 0; i < tile.objects.size(); ) { if ( tile.objects[i].id == oldObjectUID ) { tile.objects[i].id = newObjectUID; if ( i != tile.objects.size() - 1 ) { // Put the object on top of others. std::swap( tile.objects[i], tile.objects[tile.objects.size() - 1] ); continue; } } ++i; } } } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_interface.h000066400000000000000000000127671476115357100234530ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include "editor_interface_panel.h" #include "game_mode.h" #include "history_manager.h" #include "interface_base.h" #include "map_format_info.h" #include "timing.h" namespace Maps { class Tile; enum class ObjectGroup : uint8_t; } namespace Interface { class EditorInterface final : public BaseInterface { public: static EditorInterface & Get(); void redraw( const uint32_t force ) override; // Regenerates the game area and updates the panel positions depending on the UI settings void reset() override; // Start Map Editor interface main function. fheroes2::GameMode startEdit( const bool isNewMap ); static fheroes2::GameMode eventLoadMap(); static fheroes2::GameMode eventNewMap(); static fheroes2::GameMode eventFileDialog(); void eventViewWorld(); bool useMouseDragMovement() override { return _editorPanel.useMouseDragMovement(); } void mouseCursorAreaClickLeft( const int32_t tileIndex ) override; void mouseCursorAreaPressRight( const int32_t tileIndex ) const override; void mouseCursorAreaLongPressLeft( const int32_t /*Unused*/ ) override { // Do nothing. } void undoAction() { if ( _historyManager.undo() ) { _redraw |= ( REDRAW_GAMEAREA | REDRAW_RADAR ); } } void redoAction() { if ( _historyManager.redo() ) { _redraw |= ( REDRAW_GAMEAREA | REDRAW_RADAR ); } } void updateCursor( const int32_t tileIndex ) override; void setCursorUpdater( const std::function & cursorUpdater ) { _cursorUpdater = cursorUpdater; } bool loadMap( const std::string & filePath ); void saveMapToFile(); void openMapSpecificationsDialog(); private: class WarningMessage { public: explicit WarningMessage( EditorInterface & interface ) : _interface( interface ) { // Do nothing. } void reset( std::string info ) { _message = std::move( info ); _interface.setRedraw( REDRAW_GAMEAREA ); _timer.reset(); } bool isValid() const { return _timer.getS() < 5 && !_message.empty(); } std::string message() const { return _message; } private: EditorInterface & _interface; std::string _message; fheroes2::Time _timer; }; EditorInterface() : BaseInterface( true ) , _editorPanel( *this ) , _warningMessage( *this ) { // Do nothing. } bool _setObjectOnTile( Maps::Tile & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex ); bool _setObjectOnTileAsAction( Maps::Tile & tile, const Maps::ObjectGroup groupType, const int32_t objectIndex ); void _handleObjectMouseLeftClick( Maps::Tile & tile ); void _validateObjectsOnTerrainUpdate(); // Returns true if an existing object was moved. bool _moveExistingObject( const int32_t tileIndex, const Maps::ObjectGroup groupType, int32_t objectIndex ); void _updateObjectMetadata( const Maps::Map_Format::TileObjectInfo & object, const uint32_t newObjectUID ); void _updateObjectUID( const uint32_t oldObjectUID, const uint32_t newObjectUID ); EditorPanel _editorPanel; int32_t _areaSelectionStartTileId{ -1 }; int32_t _tileUnderCursor{ -1 }; std::function _cursorUpdater; fheroes2::HistoryManager _historyManager; Maps::Map_Format::MapFormat _mapFormat; WarningMessage _warningMessage; std::string _loadedFileName; }; } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_interface_panel.cpp000066400000000000000000002023411476115357100251520ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_interface_panel.h" #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "dialog_selectitems.h" #include "editor_interface.h" #include "editor_options.h" #include "ground.h" #include "icn.h" #include "image.h" #include "interface_base.h" #include "localevent.h" #include "maps_tiles.h" #include "monster.h" #include "pal.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_map_object.h" #include "ui_text.h" #include "ui_window.h" #include "world.h" namespace { fheroes2::Sprite getObjectImage( const Maps::ObjectGroup group, const int32_t type ) { if ( type == -1 ) { return {}; } const auto & objectInfo = Maps::getObjectsByGroup( group ); if ( type < 0 || type >= static_cast( objectInfo.size() ) ) { // You are trying to render some unknown stuff! assert( 0 ); return {}; } return fheroes2::generateMapObjectImage( objectInfo[type] ); } void setCustomCursor( const Maps::ObjectGroup group, const int32_t type ) { if ( type == -1 ) { // The object type is not set. We show the POINTER cursor for this case. Cursor::Get().SetThemes( Cursor::POINTER ); return; } const fheroes2::Sprite & image = getObjectImage( group, type ); Cursor::Get().setCustomImage( image, { image.x(), image.y() } ); } fheroes2::Rect getObjectOccupiedArea( const Maps::ObjectGroup group, const int32_t objectType ) { if ( group == Maps::ObjectGroup::KINGDOM_TOWNS ) { // TODO: make occupied area calculation for complex objects. return { -2, -3, 5, 5 }; } const auto & objectInfo = Maps::getObjectsByGroup( group ); if ( objectType < 0 || objectType >= static_cast( objectInfo.size() ) ) { assert( 0 ); return { 0, 0, 1, 1 }; } const auto & offsets = Maps::getGroundLevelOccupiedTileOffset( objectInfo[objectType] ); if ( offsets.size() < 2 ) { return { 0, 0, 1, 1 }; } fheroes2::Point minPos{ offsets.front() }; fheroes2::Point maxPos{ offsets.front() }; for ( const auto & offset : offsets ) { minPos.x = std::min( minPos.x, offset.x ); minPos.y = std::min( minPos.y, offset.y ); maxPos.x = std::max( maxPos.x, offset.x ); maxPos.y = std::max( maxPos.y, offset.y ); } return { minPos.x, minPos.y, maxPos.x - minPos.x + 1, maxPos.y - minPos.y + 1 }; } fheroes2::Image makeInstrumentPanelBackground( const int32_t width, const int32_t height ) { fheroes2::Image background; background._disableTransformLayer(); background.resize( width, height ); fheroes2::StandardWindow::renderBackgroundImage( background, { 0, 0, width, height }, 0, Settings::Get().isEvilInterfaceEnabled() ); // Make background borders: it consists of rectangles with different transform shading. auto applyRectTransform = [width, height]( fheroes2::Image & output, const int32_t offset, const uint8_t transformId ) { const int32_t doubleOffset = 2 * offset; // Top horizontal line. ApplyTransform( output, offset, offset, width - doubleOffset, 1, transformId ); // Left vertical line without pixels that are parts of horizontal lines. ApplyTransform( output, offset, offset + 1, 1, height - doubleOffset - 2, transformId ); // Bottom horizontal line. ApplyTransform( output, offset, height - 1 - offset, width - doubleOffset, 1, transformId ); // Right vertical line without pixels that are parts of horizontal lines. ApplyTransform( output, width - 1 - offset, offset + 1, 1, height - doubleOffset - 2, transformId ); }; applyRectTransform( background, 0, 2 ); applyRectTransform( background, 1, 4 ); applyRectTransform( background, 2, 5 ); applyRectTransform( background, 2, 9 ); applyRectTransform( background, 3, 8 ); applyRectTransform( background, 4, 9 ); return background; } void drawInstrumentName( fheroes2::Image & output, const fheroes2::Point & pos, std::string text ) { const fheroes2::Sprite & originalPanel = fheroes2::AGG::GetICN( ICN::EDITPANL, 0 ); const int32_t nameBackgroundOffsetX{ 7 }; const int32_t nameBackgroundOffsetY{ 104 }; const int32_t nameBackgroundWidth{ 130 }; const int32_t nameBackgroundHeight{ 14 }; if ( Settings::Get().isEvilInterfaceEnabled() ) { fheroes2::ApplyPalette( originalPanel, nameBackgroundOffsetX, nameBackgroundOffsetY, output, pos.x, pos.y, nameBackgroundWidth, nameBackgroundHeight, PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ) ); } else { fheroes2::Copy( originalPanel, nameBackgroundOffsetX, nameBackgroundOffsetY, output, pos.x, pos.y, nameBackgroundWidth, nameBackgroundHeight ); } const fheroes2::Text terrainText( std::move( text ), fheroes2::FontType::smallWhite() ); terrainText.draw( pos.x + ( nameBackgroundWidth - terrainText.width() ) / 2, pos.y + 3, output ); } void drawObjectTypeSelectionRect( fheroes2::Image & output, const fheroes2::Point & pos ) { const fheroes2::Sprite & selection = fheroes2::AGG::GetICN( ICN::TERRAINS, 9 ); fheroes2::Blit( selection, 0, 0, output, pos.x - 2, pos.y - 2, selection.width(), selection.height() ); } void showObjectTypeInfoText( std::string objectName ) { std::string text = _( "Used to place %{object}." ); StringReplaceWithLowercase( text, "%{object}", objectName ); fheroes2::showStandardTextMessage( std::move( objectName ), std::move( text ), Dialog::ZERO ); } template void updateObjectTypeSelection( const int8_t objectId, const std::array & buttonAreas, const std::function & getObjectTypeName, const fheroes2::Point & ObjectTypeNamePosition, fheroes2::Image & output ) { if ( objectId < 0 ) { drawInstrumentName( output, ObjectTypeNamePosition, _( "Select object type" ) ); } else { drawObjectTypeSelectionRect( output, buttonAreas[objectId].getPosition() ); drawInstrumentName( output, ObjectTypeNamePosition, getObjectTypeName( objectId ) ); } } } namespace Interface { const std::array EditorPanel::_selectedLandscapeObjectGroup{ Maps::ObjectGroup::LANDSCAPE_MOUNTAINS, Maps::ObjectGroup::LANDSCAPE_ROCKS, Maps::ObjectGroup::LANDSCAPE_TREES, Maps::ObjectGroup::LANDSCAPE_WATER, Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS }; const std::array EditorPanel::_selectedAdventureObjectGroup{ Maps::ObjectGroup::ADVENTURE_ARTIFACTS, Maps::ObjectGroup::ADVENTURE_DWELLINGS, Maps::ObjectGroup::ADVENTURE_MINES, Maps::ObjectGroup::ADVENTURE_POWER_UPS, Maps::ObjectGroup::ADVENTURE_TREASURES, Maps::ObjectGroup::ADVENTURE_WATER, Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS }; const std::array EditorPanel::_selectedKingdomObjectGroup{ Maps::ObjectGroup::KINGDOM_HEROES, Maps::ObjectGroup::KINGDOM_TOWNS }; EditorPanel::EditorPanel( EditorInterface & interface_ ) : _interface( interface_ ) { _instrumentButtons[_selectedInstrument].press(); _brushSizeButtons[_selectedBrushSize].press(); _selectedLandscapeObjectType.fill( -1 ); _selectedAdventureObjectType.fill( -1 ); _selectedKingdomObjectType.fill( -1 ); } fheroes2::Rect EditorPanel::getBrushArea() const { // Roads and streams are placed using only 1x1 brush. if ( _selectedInstrument == Instrument::STREAM || _selectedInstrument == Instrument::ROAD || _selectedInstrument == Instrument::DETAIL || _selectedInstrument == Instrument::MONSTERS ) { return { 0, 0, 1, 1 }; } if ( _selectedInstrument == Instrument::LANDSCAPE_OBJECTS || _selectedInstrument == Instrument::ADVENTURE_OBJECTS || _selectedInstrument == Instrument::KINGDOM_OBJECTS ) { const int32_t objectType = getSelectedObjectType(); if ( objectType >= 0 ) { const Maps::ObjectGroup objectGroup = getSelectedObjectGroup(); if ( objectGroup == Maps::ObjectGroup::ADVENTURE_MINES ) { // For mine we need to decode the objectType. int32_t type = -1; int32_t color = -1; getMineObjectProperties( type, color ); return getObjectOccupiedArea( objectGroup, type ); } return getObjectOccupiedArea( objectGroup, objectType ); } return {}; } switch ( _selectedBrushSize ) { case BrushSize::SMALL: return { 0, 0, 1, 1 }; case BrushSize::MEDIUM: return { 0, 0, 2, 2 }; case BrushSize::LARGE: return { -1, -1, 4, 4 }; case BrushSize::AREA: return {}; default: // Have you added a new Brush size? Update the logic above! assert( 0 ); break; } return {}; } std::set EditorPanel::getEraseObjectGroups() const { if ( _eraseTypes == ObjectErasureType::ERASE_NONE ) { return {}; } std::set objectGroups; if ( _eraseTypes & ObjectErasureType::ERASE_LANDSCAPE ) { objectGroups.insert( { Maps::ObjectGroup::LANDSCAPE_MOUNTAINS, Maps::ObjectGroup::LANDSCAPE_ROCKS, Maps::ObjectGroup::LANDSCAPE_TREES, Maps::ObjectGroup::LANDSCAPE_WATER, Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS } ); } if ( _eraseTypes & ObjectErasureType::ERASE_ADVENTURE_NON_PICKABLE ) { objectGroups.insert( { Maps::ObjectGroup::ADVENTURE_DWELLINGS, Maps::ObjectGroup::ADVENTURE_MINES, Maps::ObjectGroup::ADVENTURE_POWER_UPS, Maps::ObjectGroup::ADVENTURE_WATER, Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS } ); } if ( _eraseTypes & ObjectErasureType::ERASE_TOWNS ) { objectGroups.insert( Maps::ObjectGroup::KINGDOM_TOWNS ); } if ( _eraseTypes & ObjectErasureType::ERASE_ADVENTURE_PICKABLE ) { objectGroups.insert( { Maps::ObjectGroup::ADVENTURE_ARTIFACTS, Maps::ObjectGroup::ADVENTURE_TREASURES, Maps::ObjectGroup::ADVENTURE_WATER } ); } if ( _eraseTypes & ObjectErasureType::ERASE_MONSTERS ) { objectGroups.insert( Maps::ObjectGroup::MONSTERS ); } if ( _eraseTypes & ObjectErasureType::ERASE_HEROES ) { objectGroups.insert( Maps::ObjectGroup::KINGDOM_HEROES ); } if ( _eraseTypes & ObjectErasureType::ERASE_STREAMS ) { objectGroups.insert( Maps::ObjectGroup::STREAMS ); } if ( _eraseTypes & ObjectErasureType::ERASE_ROADS ) { objectGroups.insert( Maps::ObjectGroup::ROADS ); } return objectGroups; } void EditorPanel::setPos( const int32_t displayX, int32_t displayY ) { int32_t offsetX = displayX; // Editor panel consists of 3 instrument button rows, instrument panel and 2 system button rows. // Each button row is 36 pixels height. const fheroes2::Display & display = fheroes2::Display::instance(); const int32_t instrumentPanelWidth = display.width() - displayX - fheroes2::borderWidthPx; const int32_t bottomBorderOffset = ( display.height() > fheroes2::Display::DEFAULT_HEIGHT + fheroes2::borderWidthPx ) ? fheroes2::borderWidthPx : 0; const int32_t instrumentPanelHeight = display.height() - displayY - fheroes2::AGG::GetICN( ICN::EDITBTNS, 0 ).height() * 5 - bottomBorderOffset; _instrumentPanelBackground = makeInstrumentPanelBackground( instrumentPanelWidth, instrumentPanelHeight ); uint32_t icnIndex = 0; const int icnId = Settings::Get().isEvilInterfaceEnabled() ? ICN::EDITBTNS_EVIL : ICN::EDITBTNS; // Editor Instruments go in this order in ICN: TERRAIN, LANDSCAPE_OBJECTS, DETAIL, ADVENTURE_OBJECTS, KINGDOM_OBJECTS, MONSTERS, STREAM, ROAD, ERASE. for ( size_t i = 0; i < Instrument::INSTRUMENTS_COUNT; ++i ) { if ( i == Instrument::ADVENTURE_OBJECTS ) { // Second row buttons ICN index starts from 53. icnIndex = 35; } else if ( i == Instrument::STREAM ) { // Third row buttons ICN index starts from 53. icnIndex = 6; } _instrumentButtons[i].setICNInfo( icnId, icnIndex, icnIndex + 1 ); icnIndex += 2; } _buttonMagnify.setICNInfo( icnId, 12, 13 ); _buttonUndo.setICNInfo( icnId, 41, 42 ); _buttonRedo.setICNInfo( icnId, 43, 44 ); _buttonSpecs.setICNInfo( icnId, 18, 19 ); _buttonFile.setICNInfo( icnId, 20, 21 ); _buttonSystem.setICNInfo( icnId, 22, 23 ); // Brush Size buttons go in this order in ICN: SMALL (1x), MEDIUM (2x), LARGE (4x), AREA. icnIndex = 24; for ( fheroes2::Button & button : _brushSizeButtons ) { button.setICNInfo( icnId, icnIndex, icnIndex + 1 ); icnIndex += 2; } for ( size_t i = 0; i < _instrumentButtonsRect.size(); ++i ) { _instrumentButtons[i].setPosition( offsetX, displayY ); _instrumentButtonsRect[i] = _instrumentButtons[i].area(); // We have 3 buttons in a row. if ( ( i + 1 ) % 3 == 0 ) { offsetX = displayX; displayY += _instrumentButtonsRect[i].height; } else { offsetX += _instrumentButtonsRect[i].width; } } _rectInstruments = { _instrumentButtonsRect.front().x, _instrumentButtonsRect.front().y, _instrumentButtonsRect.back().x + _instrumentButtonsRect.back().width - _instrumentButtonsRect.front().x, displayY - _instrumentButtonsRect.front().y }; // Instrument panel. _rectInstrumentPanel = { displayX, displayY, instrumentPanelWidth, instrumentPanelHeight }; // Brush size buttons position. Shown on the terrain and erasure instrument panels. offsetX = displayX + 14; int32_t offsetY = displayY + std::min( instrumentPanelHeight - 27, 135 ); for ( size_t i = 0; i < _brushSizeButtonsRect.size(); ++i ) { _brushSizeButtons[i].setPosition( offsetX, offsetY ); _brushSizeButtonsRect[i] = _brushSizeButtons[i].area(); offsetX += 30; } const int32_t buttonStepX{ 36 }; const int32_t buttonStepY{ 33 }; const int32_t buttonWidth{ 27 }; const int32_t buttonHeight{ 27 }; const int32_t buttonHalfStepX = buttonStepX / 2; // Terrain type select buttons position. Shown on the terrain instrument panel. offsetX = displayX + 23; offsetY = displayY + 11; for ( size_t i = 0; i < _terrainButtonsRect.size(); ++i ) { _terrainButtonsRect[i] = { offsetX + static_cast( i % 3 ) * buttonStepX, offsetY + static_cast( i / 3 ) * buttonStepY, buttonWidth, buttonHeight }; } // Landscape objects buttons position. for ( size_t i = 0; i < _landscapeObjectButtonsRect.size(); ++i ) { _landscapeObjectButtonsRect[i] = { offsetX + static_cast( i % 3 ) * buttonStepX + ( i > 2 ? buttonHalfStepX : 0 ), offsetY + static_cast( i / 3 ) * buttonStepY, buttonWidth, buttonHeight }; } // Adventure objects buttons position. for ( size_t i = 0; i < _adventureObjectButtonsRect.size(); ++i ) { _adventureObjectButtonsRect[i] = { offsetX + static_cast( i % 2 ) * buttonStepX + ( i < 4 ? buttonHalfStepX : ( i < 6 ? 0 : buttonStepX * 2 ) ), offsetY + static_cast( i / 2 ) * buttonStepY - ( i < 6 ? 0 : buttonStepY ), buttonWidth, buttonHeight }; } // Kingdom objects buttons position. for ( size_t i = 0; i < _kingdomObjectButtonsRect.size(); ++i ) { // We have only two buttons and have enough space to make a double stepX. _kingdomObjectButtonsRect[i] = { offsetX + static_cast( i ) * buttonStepX + buttonHalfStepX, offsetY, buttonWidth, buttonHeight }; } // Erase tool object type buttons. offsetY += 13; for ( size_t i = 0; i < _eraseButtonsRect.size(); ++i ) { _eraseButtonsRect[i] = { offsetX + static_cast( i % 3 ) * buttonStepX + ( i > 5 ? buttonHalfStepX : 0 ), offsetY + static_cast( i / 3 ) * ( buttonStepY - ( display.height() < 500 ? 3 : 0 ) ), buttonWidth, buttonHeight }; } displayY += _rectInstrumentPanel.height; // System buttons top row. _buttonMagnify.setPosition( displayX, displayY ); _rectMagnify = _buttonMagnify.area(); _buttonUndo.setPosition( _rectMagnify.x + _rectMagnify.width, displayY ); _rectUndo = _buttonUndo.area(); _buttonRedo.setPosition( _rectUndo.x + _rectUndo.width, displayY ); _rectRedo = _buttonRedo.area(); // System buttons bottom row. displayY += _rectMagnify.height; _buttonSpecs.setPosition( displayX, displayY ); _rectSpecs = _buttonSpecs.area(); _buttonFile.setPosition( _rectSpecs.x + _rectSpecs.width, displayY ); _rectFile = _buttonFile.area(); _buttonSystem.setPosition( _rectFile.x + _rectFile.width, displayY ); _rectSystem = _buttonSystem.area(); _rectEditorPanel = { _rectInstruments.x, _rectInstruments.y, _rectSystem.x + _rectSystem.width - _rectInstruments.x, _rectSystem.y + _rectSystem.height - _rectInstruments.y }; } void EditorPanel::setRedraw() const { _interface.setRedraw( REDRAW_PANEL ); } void EditorPanel::_redraw() const { for ( const fheroes2::Button & button : _instrumentButtons ) { button.draw(); } fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Copy( _instrumentPanelBackground, 0, 0, display, _rectInstrumentPanel.x, _rectInstrumentPanel.y, _rectInstrumentPanel.width, _rectInstrumentPanel.height ); if ( _selectedInstrument == Instrument::TERRAIN || _selectedInstrument == Instrument::ERASE ) { for ( const fheroes2::Button & button : _brushSizeButtons ) { button.draw(); } } if ( _selectedInstrument == Instrument::TERRAIN ) { // We use terrain images from the original terrain instrument panel sprite. const fheroes2::Sprite & originalPanel = fheroes2::AGG::GetICN( ICN::EDITPANL, 0 ); for ( size_t i = 0; i < TerrainBrush::TERRAIN_COUNT; ++i ) { const int32_t originalOffsetX = 30 + static_cast( i % 3 ) * 29; const int32_t originalOffsetY = 11 + static_cast( i / 3 ) * 29; fheroes2::Copy( originalPanel, originalOffsetX, originalOffsetY, display, _terrainButtonsRect[i] ); } // Terrain type selection yellow rectangle. drawObjectTypeSelectionRect( display, _terrainButtonsRect[_selectedTerrain].getPosition() ); // On high resolutions we have space to show selected terrain text. if ( _rectInstrumentPanel.height > 160 ) { drawInstrumentName( display, { _rectInstrumentPanel.x + 7, _rectInstrumentPanel.y + 113 }, _getTerrainTypeName( _selectedTerrain ) ); } } else if ( _selectedInstrument == Instrument::LANDSCAPE_OBJECTS ) { // Landscape objects buttons. for ( uint32_t i = 0; i < LandscapeObjectBrush::LANDSCAPE_COUNT; ++i ) { fheroes2::Copy( fheroes2::AGG::GetICN( ICN::EDITPANL, i + 6 ), 0, 0, display, _landscapeObjectButtonsRect[i] ); } updateObjectTypeSelection( _selectedLandscapeObject, _landscapeObjectButtonsRect, _getLandscapeObjectTypeName, { _rectInstrumentPanel.x + 7, _rectInstrumentPanel.y + 80 }, display ); } else if ( _selectedInstrument == Instrument::ADVENTURE_OBJECTS ) { // Adventure objects buttons. const fheroes2::Sprite & originalPanel = fheroes2::AGG::GetICN( ICN::EDITPANL, 1 ); const int32_t originalArtifactsImageOffsetX{ 15 }; const int32_t originalTreasuresImageOffsetX{ 102 }; const int32_t originalImagesOffsetY{ 96 }; fheroes2::Copy( originalPanel, originalArtifactsImageOffsetX, originalImagesOffsetY, display, _adventureObjectButtonsRect[AdventureObjectBrush::ARTIFACTS] ); for ( uint32_t i = AdventureObjectBrush::DWELLINGS; i < AdventureObjectBrush::TREASURES; ++i ) { fheroes2::Copy( fheroes2::AGG::GetICN( ICN::EDITPANL, i + 10 ), 0, 0, display, _adventureObjectButtonsRect[i] ); } fheroes2::Copy( originalPanel, originalTreasuresImageOffsetX, originalImagesOffsetY, display, _adventureObjectButtonsRect[AdventureObjectBrush::TREASURES] ); for ( uint32_t i = AdventureObjectBrush::WATER_ADVENTURE; i < AdventureObjectBrush::ADVENTURE_COUNT; ++i ) { fheroes2::Copy( fheroes2::AGG::GetICN( ICN::EDITPANL, i + 9 ), 0, 0, display, _adventureObjectButtonsRect[i] ); } updateObjectTypeSelection( _selectedAdventureObject, _adventureObjectButtonsRect, _getAdventureObjectTypeName, { _rectInstrumentPanel.x + 7, _rectInstrumentPanel.y + 113 }, display ); } else if ( _selectedInstrument == Instrument::KINGDOM_OBJECTS ) { // Kingdom objects buttons. const fheroes2::Sprite & originalPanel = fheroes2::AGG::GetICN( ICN::EDITPANL, 1 ); const int32_t originalHeroesImageOffsetX{ 102 }; const int32_t originalTownsImageOffsetX{ 44 }; const int32_t originalImagesOffsetY{ 68 }; fheroes2::Copy( originalPanel, originalHeroesImageOffsetX, originalImagesOffsetY, display, _kingdomObjectButtonsRect[KingdomObjectBrush::HEROES] ); fheroes2::Copy( originalPanel, originalTownsImageOffsetX, originalImagesOffsetY, display, _kingdomObjectButtonsRect[KingdomObjectBrush::TOWNS] ); updateObjectTypeSelection( _selectedKingdomObject, _kingdomObjectButtonsRect, _getKingdomObjectTypeName, { _rectInstrumentPanel.x + 7, _rectInstrumentPanel.y + 48 }, display ); } else if ( _selectedInstrument == Instrument::MONSTERS ) { const fheroes2::Text instrumentName( getObjectGroupName( Maps::ObjectGroup::MONSTERS ), fheroes2::FontType::normalWhite() ); instrumentName.draw( _rectInstrumentPanel.x + ( _rectInstrumentPanel.width - instrumentName.width() ) / 2, _rectInstrumentPanel.y + 8, display ); if ( _selectedMonsterType < 0 ) { // Show a tip. const fheroes2::Text text( _( "Click here to\nselect a monster." ), fheroes2::FontType::smallWhite() ); text.draw( _rectInstrumentPanel.x + 5, _rectInstrumentPanel.y + 38, _rectInstrumentPanel.width - 10, display ); } else { // Show the selected monster image on the panel. const fheroes2::Sprite & image = getObjectImage( Maps::ObjectGroup::MONSTERS, _selectedMonsterType ); fheroes2::Blit( image, display, _rectInstrumentPanel.x + ( _rectInstrumentPanel.width - image.width() ) / 2, _rectInstrumentPanel.y + 67 - image.height() ); fheroes2::Text text( Monster( _selectedMonsterType + 1 ).GetName(), fheroes2::FontType::smallWhite() ); text.draw( _rectInstrumentPanel.x + 5, _rectInstrumentPanel.y + 70, _rectInstrumentPanel.width - 10, display ); text.set( _( "Click here to\nselect another monster." ), fheroes2::FontType::smallWhite() ); text.draw( _rectInstrumentPanel.x + 5, _rectInstrumentPanel.y + 95, _rectInstrumentPanel.width - 10, display ); } } else if ( _selectedInstrument == Instrument::DETAIL ) { const fheroes2::Text instrumentName( _( "Cell\nDetails" ), fheroes2::FontType::normalWhite() ); instrumentName.draw( _rectInstrumentPanel.x + 5, _rectInstrumentPanel.y + 8, _rectInstrumentPanel.width - 10, display ); } else if ( _selectedInstrument == Instrument::ROAD ) { const fheroes2::Text instrumentName( getObjectGroupName( Maps::ObjectGroup::ROADS ), fheroes2::FontType::normalWhite() ); instrumentName.draw( _rectInstrumentPanel.x + ( _rectInstrumentPanel.width - instrumentName.width() ) / 2, _rectInstrumentPanel.y + 8, display ); } else if ( _selectedInstrument == Instrument::STREAM ) { const fheroes2::Text instrumentName( getObjectGroupName( Maps::ObjectGroup::STREAMS ), fheroes2::FontType::normalWhite() ); instrumentName.draw( _rectInstrumentPanel.x + ( _rectInstrumentPanel.width - instrumentName.width() ) / 2, _rectInstrumentPanel.y + 8, display ); } else if ( _selectedInstrument == Instrument::ERASE ) { const fheroes2::Text instrumentName( _( "Erase" ), fheroes2::FontType::normalWhite() ); instrumentName.draw( _rectInstrumentPanel.x + ( _rectInstrumentPanel.width - instrumentName.width() ) / 2, _rectInstrumentPanel.y + 8, display ); // Object type to erase buttons. const fheroes2::Sprite & originalPanel = fheroes2::AGG::GetICN( ICN::EDITPANL, 1 ); const int32_t originalTownsImageOffsetX{ 44 }; const int32_t originalMonstersImageOffsetX{ 73 }; const int32_t originalHeroesTreasuresImageOffsetX{ 102 }; const int32_t originalTownsMonstersHeroesOffsetY{ 68 }; const int32_t originalArtifactsTreasresOffsetY{ 96 }; // Landscape objects icon. fheroes2::Copy( fheroes2::AGG::GetICN( ICN::EDITPANL, 8 ), 0, 0, display, _eraseButtonsRect[0] ); // Adventure non pickable objects icon. fheroes2::Copy( fheroes2::AGG::GetICN( ICN::EDITPANL, 13 ), 0, 0, display, _eraseButtonsRect[1] ); // Castle objects icon. fheroes2::Copy( originalPanel, originalTownsImageOffsetX, originalTownsMonstersHeroesOffsetY, display, _eraseButtonsRect[2] ); // Adventure pickable objects icon. fheroes2::Copy( originalPanel, originalHeroesTreasuresImageOffsetX, originalArtifactsTreasresOffsetY, display, _eraseButtonsRect[3] ); // Monster objects icon. fheroes2::Copy( originalPanel, originalMonstersImageOffsetX, originalTownsMonstersHeroesOffsetY, display, _eraseButtonsRect[4] ); // Hero objects icon. fheroes2::Copy( originalPanel, originalHeroesTreasuresImageOffsetX, originalTownsMonstersHeroesOffsetY, display, _eraseButtonsRect[5] ); // Road objects icon. fheroes2::Copy( fheroes2::AGG::GetICN( ICN::EDITPANL, 16 ), 0, 0, display, _eraseButtonsRect[6] ); // Stream objects icon. fheroes2::Copy( fheroes2::AGG::GetICN( ICN::EDITPANL, 17 ), 0, 0, display, _eraseButtonsRect[7] ); // Object type to erase selection marks. const fheroes2::Sprite & selectionMark = fheroes2::AGG::GetICN( ICN::TOWNWIND, 11 ); for ( size_t i = 0; i < _eraseButtonsRect.size(); ++i ) { if ( _eraseButtonObjectTypes[i] & _eraseTypes ) { fheroes2::Blit( selectionMark, 0, 0, display, _eraseButtonsRect[i].x + 10, _eraseButtonsRect[i].y + 11, selectionMark.width(), selectionMark.height() ); } } } _buttonMagnify.draw(); _buttonUndo.draw(); _buttonRedo.draw(); _buttonSpecs.draw(); _buttonFile.draw(); _buttonSystem.draw(); } int32_t EditorPanel::getSelectedObjectType() const { switch ( _selectedInstrument ) { case Instrument::MONSTERS: return _selectedMonsterType; case Instrument::LANDSCAPE_OBJECTS: if ( _selectedLandscapeObject < 0 ) { return -1; } return _selectedLandscapeObjectType[_selectedLandscapeObject]; case Instrument::ADVENTURE_OBJECTS: if ( _selectedAdventureObject < 0 ) { return -1; } return _selectedAdventureObjectType[_selectedAdventureObject]; case Instrument::KINGDOM_OBJECTS: if ( _selectedKingdomObject < 0 ) { return -1; } return _selectedKingdomObjectType[_selectedKingdomObject]; default: // Why are you trying to get type for the non-object instrument. Check your logic! assert( 0 ); return -1; } } Maps::ObjectGroup EditorPanel::getSelectedObjectGroup() const { switch ( _selectedInstrument ) { case Instrument::MONSTERS: return Maps::ObjectGroup::MONSTERS; case Instrument::LANDSCAPE_OBJECTS: assert( _selectedLandscapeObject > -1 ); return _selectedLandscapeObjectGroup[_selectedLandscapeObject]; case Instrument::ADVENTURE_OBJECTS: assert( _selectedAdventureObject > -1 ); return _selectedAdventureObjectGroup[_selectedAdventureObject]; case Instrument::KINGDOM_OBJECTS: assert( _selectedKingdomObject > -1 ); return _selectedKingdomObjectGroup[_selectedKingdomObject]; default: // Why are you trying to get object group for the non-object instrument. Check your logic! assert( 0 ); return Maps::ObjectGroup::GROUP_COUNT; } } const char * EditorPanel::getObjectGroupName( const Maps::ObjectGroup groupName ) { switch ( groupName ) { case Maps::ObjectGroup::ROADS: return _( "Roads" ); case Maps::ObjectGroup::STREAMS: return _( "Streams" ); case Maps::ObjectGroup::LANDSCAPE_MOUNTAINS: return _( "Mountains" ); case Maps::ObjectGroup::LANDSCAPE_ROCKS: return _( "Rocks" ); case Maps::ObjectGroup::LANDSCAPE_TREES: return _( "Trees" ); case Maps::ObjectGroup::ADVENTURE_WATER: case Maps::ObjectGroup::LANDSCAPE_WATER: return _( "Water Objects" ); case Maps::ObjectGroup::ADVENTURE_MISCELLANEOUS: case Maps::ObjectGroup::LANDSCAPE_MISCELLANEOUS: return _( "Miscellaneous" ); case Maps::ObjectGroup::LANDSCAPE_TOWN_BASEMENTS: // You shouldn't call this path! assert( 0 ); return "Towns"; case Maps::ObjectGroup::LANDSCAPE_FLAGS: // You shouldn't call this path! assert( 0 ); return "Flags"; case Maps::ObjectGroup::ADVENTURE_ARTIFACTS: return _( "Artifacts" ); case Maps::ObjectGroup::ADVENTURE_DWELLINGS: return _( "Dwellings" ); case Maps::ObjectGroup::ADVENTURE_MINES: return _( "Mines" ); case Maps::ObjectGroup::ADVENTURE_POWER_UPS: return _( "Power-ups" ); case Maps::ObjectGroup::ADVENTURE_TREASURES: return _( "Treasures" ); case Maps::ObjectGroup::KINGDOM_HEROES: return _( "Heroes" ); case Maps::ObjectGroup::KINGDOM_TOWNS: return _( "Towns" ); case Maps::ObjectGroup::MONSTERS: return _( "Monsters" ); default: // Did you add a new group? Add the logic for it! assert( 0 ); return "Unknown objects"; } } int EditorPanel::_getGroundId( const uint8_t brushId ) { switch ( brushId ) { case TerrainBrush::WATER: return Maps::Ground::WATER; case TerrainBrush::GRASS: return Maps::Ground::GRASS; case TerrainBrush::SNOW: return Maps::Ground::SNOW; case TerrainBrush::SWAMP: return Maps::Ground::SWAMP; case TerrainBrush::LAVA: return Maps::Ground::LAVA; case TerrainBrush::DESERT: return Maps::Ground::DESERT; case TerrainBrush::DIRT: return Maps::Ground::DIRT; case TerrainBrush::WASTELAND: return Maps::Ground::WASTELAND; case TerrainBrush::BEACH: return Maps::Ground::BEACH; default: // Have you added a new terrain type? Add the logic above! assert( 0 ); break; } return Maps::Ground::UNKNOWN; } const char * EditorPanel::_getLandscapeObjectTypeName( const uint8_t brushId ) { if ( brushId >= _selectedLandscapeObjectGroup.size() ) { return "Unknown object type"; } return getObjectGroupName( _selectedLandscapeObjectGroup[brushId] ); } const char * EditorPanel::_getAdventureObjectTypeName( const uint8_t brushId ) { if ( brushId >= _selectedAdventureObjectGroup.size() ) { return "Unknown object type"; } return getObjectGroupName( _selectedAdventureObjectGroup[brushId] ); } const char * EditorPanel::_getKingdomObjectTypeName( const uint8_t brushId ) { if ( brushId >= _selectedKingdomObjectGroup.size() ) { return "Unknown object type"; } return getObjectGroupName( _selectedKingdomObjectGroup[brushId] ); } const char * EditorPanel::_getEraseObjectTypeName( const uint32_t eraseObjectType ) { switch ( eraseObjectType ) { case ObjectErasureType::ERASE_LANDSCAPE: return _( "editorErasure|Landscape objects" ); case ObjectErasureType::ERASE_ADVENTURE_NON_PICKABLE: return _( "editorErasure|Adventure non pickable objects" ); case ObjectErasureType::ERASE_TOWNS: return _( "editorErasure|Castles" ); case ObjectErasureType::ERASE_ADVENTURE_PICKABLE: return _( "editorErasure|Adventure pickable objects" ); case ObjectErasureType::ERASE_MONSTERS: return _( "editorErasure|Monsters" ); case ObjectErasureType::ERASE_HEROES: return _( "editorErasure|Heroes" ); case ObjectErasureType::ERASE_ROADS: return _( "editorErasure|Roads" ); case ObjectErasureType::ERASE_STREAMS: return _( "editorErasure|Streams" ); default: // Have you added a new object type to erase? Add the logic above! assert( 0 ); break; } return "Unknown object type"; } void EditorPanel::_setCursor() { switch ( _selectedInstrument ) { case Instrument::MONSTERS: _interface.setCursorUpdater( [type = getSelectedObjectType(), group = getSelectedObjectGroup()]( const int32_t /*tileIndex*/ ) { setCustomCursor( group, type ); } ); return; case Instrument::LANDSCAPE_OBJECTS: switch ( _selectedLandscapeObject ) { case LandscapeObjectBrush::MOUNTAINS: case LandscapeObjectBrush::ROCKS: case LandscapeObjectBrush::TREES: case LandscapeObjectBrush::WATER_OBJECTS: case LandscapeObjectBrush::LANDSCAPE_MISC: _interface.setCursorUpdater( [type = getSelectedObjectType(), group = getSelectedObjectGroup()]( const int32_t /*tileIndex*/ ) { setCustomCursor( group, type ); } ); return; default: break; } break; case Instrument::ADVENTURE_OBJECTS: switch ( _selectedAdventureObject ) { case AdventureObjectBrush::ARTIFACTS: case AdventureObjectBrush::DWELLINGS: case AdventureObjectBrush::POWER_UPS: case AdventureObjectBrush::TREASURES: case AdventureObjectBrush::WATER_ADVENTURE: case AdventureObjectBrush::ADVENTURE_MISC: _interface.setCursorUpdater( [type = getSelectedObjectType(), group = getSelectedObjectGroup()]( const int32_t /*tileIndex*/ ) { setCustomCursor( group, type ); } ); return; case AdventureObjectBrush::MINES: _interface.setCursorUpdater( [this]( const int32_t /*tileIndex*/ ) { int32_t type = -1; int32_t color = -1; getMineObjectProperties( type, color ); if ( type == -1 || color == -1 ) { // The object type is not set. We show the POINTER cursor for this case. Cursor::Get().SetThemes( Cursor::POINTER ); return; } assert( Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_MINES ).size() > static_cast( type ) ); // TODO: Implement a function to render also the owner flag after ownership selection is implemented. const fheroes2::Sprite & image = getObjectImage( Maps::ObjectGroup::ADVENTURE_MINES, type ); Cursor::Get().setCustomImage( image, { image.x(), image.y() } ); } ); return; default: break; } break; case Instrument::KINGDOM_OBJECTS: switch ( _selectedKingdomObject ) { case KingdomObjectBrush::HEROES: _interface.setCursorUpdater( [type = getSelectedObjectType()]( const int32_t /*tileIndex*/ ) { if ( type == -1 ) { // The object type is not set. We show the POINTER cursor for this case. Cursor::Get().SetThemes( Cursor::POINTER ); return; } // TODO: render ICN::MINIHERO from the existing hero images. const fheroes2::Sprite & image = fheroes2::AGG::GetICN( ICN::MINIHERO, type ); // Mini-hero images contain a pole with a flag. // This causes a situation that a selected tile does not properly correspond to current position of the cursor. // We need to add a hardcoded correction. const int32_t heroCorrectionY{ 12 }; Cursor::Get().setCustomImage( image, { -image.width() / 2, -image.height() / 2 - heroCorrectionY } ); } ); return; case KingdomObjectBrush::TOWNS: _interface.setCursorUpdater( [this]( const int32_t tileIndex ) { int32_t type = -1; int32_t color = -1; getTownObjectProperties( type, color ); if ( type == -1 || color == -1 ) { // The object type is not set. We show the POINTER cursor for this case. Cursor::Get().SetThemes( Cursor::POINTER ); return; } const fheroes2::Sprite & image = fheroes2::generateTownObjectImage( type, color, world.getTile( tileIndex ).GetGround() ); Cursor::Get().setCustomImage( image, { image.x(), image.y() } ); } ); return; default: break; } break; default: break; } _interface.setCursorUpdater( {} ); } fheroes2::GameMode EditorPanel::queueEventProcessing() { LocalEvent & le = LocalEvent::Get(); fheroes2::GameMode res = fheroes2::GameMode::CANCEL; if ( le.isMouseLeftButtonPressedInArea( _rectInstruments ) ) { for ( size_t i = 0; i < _instrumentButtonsRect.size(); ++i ) { if ( i != _selectedInstrument && ( _instrumentButtonsRect[i] & le.getMouseLeftButtonPressedPos() ) ) { _selectedInstrument = static_cast( i ); // Reset cursor updater since this UI element was clicked. _setCursor(); // Redraw all instrument buttons. for ( size_t index = 0; index < _instrumentButtonsRect.size(); ++index ) { _instrumentButtons[index].drawOnState( index == _selectedInstrument ); } // When opening Monsters placing and no monster was previously selected force open the Select Monster dialog. if ( _selectedInstrument == Instrument::MONSTERS && _selectedMonsterType == -1 ) { // Update panel image and then open the Select Monster dialog. _redraw(); handleObjectMouseClick( Dialog::selectMonsterType ); } setRedraw(); break; } } return res; } if ( _selectedInstrument == Instrument::TERRAIN || _selectedInstrument == Instrument::ERASE ) { for ( size_t i = 0; i < _brushSizeButtonsRect.size(); ++i ) { if ( i != _selectedBrushSize && le.isMouseLeftButtonPressedInArea( _brushSizeButtonsRect[i] ) ) { _selectedBrushSize = static_cast( i ); // Redraw all brush size buttons. for ( size_t index = 0; index < _brushSizeButtonsRect.size(); ++index ) { _brushSizeButtons[index].drawOnState( index == _selectedBrushSize ); } break; } } const auto brushSizeText = []( const int brushSize, const bool isFillBrush ) { std::string text = isFillBrush ? _( "Draws terrain in\n%{size} by %{size} square increments." ) : _( "Erases objects in\n%{size} by %{size} square increments." ); StringReplace( text, "%{size}", brushSize ); return text; }; if ( le.isMouseRightButtonPressedInArea( _brushSizeButtonsRect[BrushSize::SMALL] ) ) { fheroes2::showStandardTextMessage( _( "Small Brush" ), brushSizeText( 1, _selectedInstrument == Instrument::TERRAIN ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _brushSizeButtonsRect[BrushSize::MEDIUM] ) ) { fheroes2::showStandardTextMessage( _( "Medium Brush" ), brushSizeText( 2, _selectedInstrument == Instrument::TERRAIN ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _brushSizeButtonsRect[BrushSize::LARGE] ) ) { fheroes2::showStandardTextMessage( _( "Large Brush" ), brushSizeText( 4, _selectedInstrument == Instrument::TERRAIN ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _brushSizeButtonsRect[BrushSize::AREA] ) ) { if ( _selectedInstrument == Instrument::TERRAIN ) { fheroes2::showStandardTextMessage( _( "Area Fill" ), _( "Used to click and drag for filling in large areas." ), Dialog::ZERO ); } else { fheroes2::showStandardTextMessage( _( "Clear Area" ), _( "Used to click and drag for clearing large areas." ), Dialog::ZERO ); } } } if ( _selectedInstrument == Instrument::TERRAIN ) { for ( size_t i = 0; i < _terrainButtonsRect.size(); ++i ) { if ( ( _selectedTerrain != i ) && le.isMouseLeftButtonPressedInArea( _terrainButtonsRect[i] ) ) { _selectedTerrain = static_cast( i ); setRedraw(); // There is no need to continue the loop as only one button can be pressed at one moment. break; } } const auto movePenaltyText = []( const std::string & rate ) { std::string text = _( "Costs %{rate} times normal movement for all heroes. (Pathfinding reduces or eliminates the penalty.)" ); StringReplace( text, "%{rate}", rate ); return text; }; if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::WATER] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::WATER ), _( "Traversable only by boat." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::GRASS] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::GRASS ), _( "No special modifiers." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::SNOW] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::SNOW ), movePenaltyText( "1.5" ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::SWAMP] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::SWAMP ), movePenaltyText( "1.75" ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::LAVA] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::LAVA ), _( "No special modifiers." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::DESERT] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::DESERT ), movePenaltyText( "2" ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::DIRT] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::DIRT ), _( "No special modifiers." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::WASTELAND] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::WASTELAND ), movePenaltyText( "1.25" ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _terrainButtonsRect[TerrainBrush::BEACH] ) ) { fheroes2::showStandardTextMessage( _getTerrainTypeName( TerrainBrush::BEACH ), movePenaltyText( "1.25" ), Dialog::ZERO ); } } else if ( _selectedInstrument == Instrument::LANDSCAPE_OBJECTS ) { for ( size_t i = 0; i < _landscapeObjectButtonsRect.size(); ++i ) { if ( ( _selectedLandscapeObject != static_cast( i ) ) && le.isMouseLeftButtonPressedInArea( _landscapeObjectButtonsRect[i] ) ) { _selectedLandscapeObject = static_cast( i ); // Reset cursor updater since this UI element was clicked. _setCursor(); setRedraw(); break; } } for ( uint8_t objectId = LandscapeObjectBrush::MOUNTAINS; objectId < LandscapeObjectBrush::LANDSCAPE_COUNT; ++objectId ) { if ( le.isMouseRightButtonPressedInArea( _landscapeObjectButtonsRect[objectId] ) ) { showObjectTypeInfoText( _getLandscapeObjectTypeName( objectId ) ); break; } } if ( le.MouseClickLeft( _landscapeObjectButtonsRect[LandscapeObjectBrush::MOUNTAINS] ) ) { handleObjectMouseClick( Dialog::selectMountainType ); return res; } if ( le.MouseClickLeft( _landscapeObjectButtonsRect[LandscapeObjectBrush::ROCKS] ) ) { handleObjectMouseClick( Dialog::selectRockType ); return res; } if ( le.MouseClickLeft( _landscapeObjectButtonsRect[LandscapeObjectBrush::TREES] ) ) { handleObjectMouseClick( Dialog::selectTreeType ); return res; } if ( le.MouseClickLeft( _landscapeObjectButtonsRect[LandscapeObjectBrush::WATER_OBJECTS] ) ) { handleObjectMouseClick( Dialog::selectLandscapeOceanObjectType ); return res; } if ( le.MouseClickLeft( _landscapeObjectButtonsRect[LandscapeObjectBrush::LANDSCAPE_MISC] ) ) { handleObjectMouseClick( Dialog::selectLandscapeMiscellaneousObjectType ); return res; } } else if ( _selectedInstrument == Instrument::ADVENTURE_OBJECTS ) { for ( size_t i = 0; i < _adventureObjectButtonsRect.size(); ++i ) { if ( ( _selectedAdventureObject != static_cast( i ) ) && le.isMouseLeftButtonPressedInArea( _adventureObjectButtonsRect[i] ) ) { _selectedAdventureObject = static_cast( i ); // Reset cursor updater since this UI element was clicked. _setCursor(); setRedraw(); break; } } for ( uint8_t objectId = AdventureObjectBrush::ARTIFACTS; objectId < AdventureObjectBrush::ADVENTURE_COUNT; ++objectId ) { if ( le.isMouseRightButtonPressedInArea( _adventureObjectButtonsRect[objectId] ) ) { showObjectTypeInfoText( _getAdventureObjectTypeName( objectId ) ); break; } } if ( le.MouseClickLeft( _adventureObjectButtonsRect[AdventureObjectBrush::ARTIFACTS] ) ) { handleObjectMouseClick( Dialog::selectArtifactType ); return res; } if ( le.MouseClickLeft( _adventureObjectButtonsRect[AdventureObjectBrush::TREASURES] ) ) { handleObjectMouseClick( Dialog::selectTreasureType ); return res; } if ( le.MouseClickLeft( _adventureObjectButtonsRect[AdventureObjectBrush::WATER_ADVENTURE] ) ) { handleObjectMouseClick( Dialog::selectOceanObjectType ); return res; } if ( le.MouseClickLeft( _adventureObjectButtonsRect[AdventureObjectBrush::MINES] ) ) { handleObjectMouseClick( [this]( const int32_t /* type */ ) { int32_t type = -1; int32_t color = -1; getMineObjectProperties( type, color ); Dialog::selectMineType( type, color ); return _generateMineObjectProperties( type, color ); } ); return res; } if ( le.MouseClickLeft( _adventureObjectButtonsRect[AdventureObjectBrush::DWELLINGS] ) ) { handleObjectMouseClick( Dialog::selectDwellingType ); return res; } if ( le.MouseClickLeft( _adventureObjectButtonsRect[AdventureObjectBrush::POWER_UPS] ) ) { handleObjectMouseClick( Dialog::selectPowerUpObjectType ); return res; } if ( le.MouseClickLeft( _adventureObjectButtonsRect[AdventureObjectBrush::ADVENTURE_MISC] ) ) { handleObjectMouseClick( Dialog::selectAdventureMiscellaneousObjectType ); return res; } } else if ( _selectedInstrument == Instrument::KINGDOM_OBJECTS ) { for ( size_t i = 0; i < _kingdomObjectButtonsRect.size(); ++i ) { if ( ( _selectedKingdomObject != static_cast( i ) ) && le.isMouseLeftButtonPressedInArea( _kingdomObjectButtonsRect[i] ) ) { _selectedKingdomObject = static_cast( i ); // Reset cursor updater since this UI element was clicked. _setCursor(); setRedraw(); break; } } for ( uint8_t objectId = KingdomObjectBrush::HEROES; objectId < KingdomObjectBrush::KINGDOM_OBJECTS_COUNT; ++objectId ) { if ( le.isMouseRightButtonPressedInArea( _kingdomObjectButtonsRect[objectId] ) ) { showObjectTypeInfoText( _getKingdomObjectTypeName( objectId ) ); break; } } if ( le.MouseClickLeft( _kingdomObjectButtonsRect[KingdomObjectBrush::HEROES] ) ) { handleObjectMouseClick( Dialog::selectHeroType ); return res; } if ( le.MouseClickLeft( _kingdomObjectButtonsRect[KingdomObjectBrush::TOWNS] ) ) { handleObjectMouseClick( [this]( const int32_t /* type */ ) { int32_t type = -1; int32_t color = -1; getTownObjectProperties( type, color ); Dialog::selectTownType( type, color ); return _generateTownObjectProperties( type, color ); } ); return res; } } else if ( _selectedInstrument == Instrument::MONSTERS && le.MouseClickLeft( _rectInstrumentPanel ) ) { handleObjectMouseClick( Dialog::selectMonsterType ); setRedraw(); return res; } else if ( _selectedInstrument == Instrument::ERASE ) { for ( size_t i = 0; i < _eraseButtonsRect.size(); ++i ) { if ( le.MouseClickLeft( _eraseButtonsRect[i] ) ) { _eraseTypes ^= _eraseButtonObjectTypes[i]; setRedraw(); } else if ( le.isMouseRightButtonPressedInArea( _eraseButtonsRect[i] ) ) { std::string header = _( "Toggle the erasure of %{type} objects." ); StringReplaceWithLowercase( header, "%{type}", _getEraseObjectTypeName( _eraseButtonObjectTypes[i] ) ); fheroes2::showStandardTextMessage( std::move( header ), ( _eraseButtonObjectTypes[i] & _eraseTypes ) ? _( "Objects of this type will be deleted with the Erase tool. Left-click here to deselect this type. Press and hold this button to deselect all other object types." ) : _( "Objects of this type will NOT be deleted with the Erase tool. Left-click here to select this type. Press and hold this button to select all other object types." ), Dialog::ZERO ); } else if ( le.MouseLongPressLeft( _eraseButtonsRect[i] ) ) { _eraseTypes = ( _eraseButtonObjectTypes[i] & _eraseTypes ) ? _eraseButtonObjectTypes[i] : ( ObjectErasureType::ERASE_ALL_OBJECTS & ~_eraseButtonObjectTypes[i] ); setRedraw(); } } } _buttonMagnify.drawOnState( le.isMouseLeftButtonPressedInArea( _rectMagnify ) ); _buttonUndo.drawOnState( le.isMouseLeftButtonPressedInArea( _rectUndo ) ); _buttonRedo.drawOnState( le.isMouseLeftButtonPressedInArea( _rectRedo ) ); _buttonSpecs.drawOnState( le.isMouseLeftButtonPressedInArea( _rectSpecs ) ); _buttonFile.drawOnState( le.isMouseLeftButtonPressedInArea( _rectFile ) ); _buttonSystem.drawOnState( le.isMouseLeftButtonPressedInArea( _rectSystem ) ); if ( le.MouseClickLeft( _rectMagnify ) ) { _interface.eventViewWorld(); } else if ( _buttonUndo.isEnabled() && le.MouseClickLeft( _rectUndo ) ) { _interface.undoAction(); // TODO: Disable Undo button when there are no actions left to undo. } else if ( _buttonRedo.isEnabled() && le.MouseClickLeft( _rectRedo ) ) { _interface.redoAction(); // TODO: Disable Redo button when there are no actions left to redo. } else if ( le.MouseClickLeft( _rectSpecs ) ) { EditorInterface::Get().openMapSpecificationsDialog(); } else if ( le.MouseClickLeft( _rectFile ) ) { res = Interface::EditorInterface::eventFileDialog(); } else if ( le.MouseClickLeft( _rectSystem ) ) { Editor::openEditorSettings(); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::TERRAIN] ) ) { fheroes2::showStandardTextMessage( _( "Terrain Mode" ), _( "Used to draw the underlying grass, dirt, water, etc. on the map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::LANDSCAPE_OBJECTS] ) ) { fheroes2::showStandardTextMessage( _( "Landscape Objects Mode" ), _( "Used to place landscape objects (mountains, rocks, trees, etc.) on the map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::DETAIL] ) ) { fheroes2::showStandardTextMessage( _( "Detail Mode" ), _( "Used for special editing of action objects." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::ADVENTURE_OBJECTS] ) ) { fheroes2::showStandardTextMessage( _( "Adventure Objects Mode" ), _( "Used to place adventure objects (artifacts, dwellings, mines, treasures, etc.) on the map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::KINGDOM_OBJECTS] ) ) { fheroes2::showStandardTextMessage( _( "Kingdom Objects Mode" ), _( "Used to place kingdom objects (towns, castles and heroes) on the map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::MONSTERS] ) ) { fheroes2::showStandardTextMessage( _( "Monsters Mode" ), _( "Used to place monsters on the map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::STREAM] ) ) { fheroes2::showStandardTextMessage( _( "Stream Mode" ), _( "Allows you to draw streams by clicking and dragging." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::ROAD] ) ) { fheroes2::showStandardTextMessage( _( "Road Mode" ), _( "Allows you to draw roads by clicking and dragging." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _instrumentButtonsRect[Instrument::ERASE] ) ) { fheroes2::showStandardTextMessage( _( "Erase Mode" ), _( "Used to erase objects from the map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _rectMagnify ) ) { fheroes2::showStandardTextMessage( _( "Magnify" ), _( "Change between zoom and normal view." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _rectUndo ) ) { fheroes2::showStandardTextMessage( _( "Undo" ), _( "Undo your last action." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _rectRedo ) ) { fheroes2::showStandardTextMessage( _( "Redo" ), _( "Redo the last undone action." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _rectSpecs ) ) { fheroes2::showStandardTextMessage( _( "Specifications" ), _( "Edit map title, description, and other general information." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _rectFile ) ) { fheroes2::showStandardTextMessage( _( "File Options" ), _( "Open the file options menu, where you can save or load maps, or quit out of the editor." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _rectSystem ) ) { fheroes2::showStandardTextMessage( _( "System Options" ), _( "View the editor system options, which let you customize the editor." ), Dialog::ZERO ); } return res; } void EditorPanel::handleObjectMouseClick( const std::function & typeSelection ) { const int type = typeSelection( getSelectedObjectType() ); if ( type >= 0 ) { switch ( _selectedInstrument ) { case Instrument::MONSTERS: _selectedMonsterType = type; break; case Instrument::LANDSCAPE_OBJECTS: _selectedLandscapeObjectType[_selectedLandscapeObject] = type; break; case Instrument::ADVENTURE_OBJECTS: _selectedAdventureObjectType[_selectedAdventureObject] = type; break; case Instrument::KINGDOM_OBJECTS: _selectedKingdomObjectType[_selectedKingdomObject] = type; break; default: // Why are you trying to get type for the non-object instrument. Check your logic! assert( 0 ); } } _setCursor(); _interface.updateCursor( 0 ); } void EditorPanel::getTownObjectProperties( int32_t & type, int32_t & color ) const { const auto & townObjects = Maps::getObjectsByGroup( Maps::ObjectGroup::KINGDOM_TOWNS ); if ( townObjects.empty() ) { // How is it even possible? assert( 0 ); type = -1; color = -1; return; } type = _selectedKingdomObjectType[KingdomObjectBrush::TOWNS] % static_cast( townObjects.size() ); color = _selectedKingdomObjectType[KingdomObjectBrush::TOWNS] / static_cast( townObjects.size() ); } int32_t EditorPanel::_generateTownObjectProperties( const int32_t type, const int32_t color ) { const auto & townObjects = Maps::getObjectsByGroup( Maps::ObjectGroup::KINGDOM_TOWNS ); if ( townObjects.empty() ) { // How is it even possible? assert( 0 ); return -1; } return color * static_cast( townObjects.size() ) + type; } void EditorPanel::getMineObjectProperties( int32_t & type, int32_t & color ) const { const auto & mineObjects = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_MINES ); if ( mineObjects.empty() ) { // How is it even possible? assert( 0 ); type = -1; color = -1; return; } type = _selectedAdventureObjectType[AdventureObjectBrush::MINES] % static_cast( mineObjects.size() ); color = _selectedAdventureObjectType[AdventureObjectBrush::MINES] / static_cast( mineObjects.size() ); } int32_t EditorPanel::_generateMineObjectProperties( const int32_t type, const int32_t color ) { const auto & mineObjects = Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_MINES ); if ( mineObjects.empty() ) { // How is it even possible? assert( 0 ); return -1; } const int32_t objectType = ( color * static_cast( mineObjects.size() ) + type ); return ( objectType < 0 ) ? -1 : objectType; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_interface_panel.h000066400000000000000000000265721476115357100246310ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include "game_mode.h" #include "ground.h" #include "image.h" #include "map_object_info.h" #include "math_base.h" #include "ui_button.h" namespace Interface { class EditorInterface; class EditorPanel { public: explicit EditorPanel( EditorInterface & interface_ ); ~EditorPanel() = default; const fheroes2::Rect & getRect() const { return _rectEditorPanel; } fheroes2::Rect getBrushArea() const; int selectedGroundType() const { return _getGroundId( _selectedTerrain ); } bool isTerrainEdit() const { return _selectedInstrument == Instrument::TERRAIN; } bool isDetailEdit() const { return _selectedInstrument == Instrument::DETAIL; } bool isRoadDraw() const { return _selectedInstrument == Instrument::ROAD; } bool isStreamDraw() const { return _selectedInstrument == Instrument::STREAM; } bool isEraseMode() const { return _selectedInstrument == Instrument::ERASE; } bool isObjectMode() const { return _selectedInstrument == Instrument::LANDSCAPE_OBJECTS || _selectedInstrument == Instrument::ADVENTURE_OBJECTS || _selectedInstrument == Instrument::KINGDOM_OBJECTS || _selectedInstrument == Instrument::MONSTERS; } std::set getEraseObjectGroups() const; bool showAreaSelectRect() const { return _selectedInstrument == Instrument::TERRAIN || _selectedInstrument == Instrument::STREAM || _selectedInstrument == Instrument::ROAD || _selectedInstrument == Instrument::ERASE || isObjectMode() || _selectedInstrument == Instrument::DETAIL; } bool useMouseDragMovement() const { return !( ( _selectedInstrument == Instrument::TERRAIN || _selectedInstrument == Instrument::ERASE ) && _selectedBrushSize == BrushSize::AREA ); } // Set Editor panel positions on screen. void setPos( const int32_t displayX, int32_t displayY ); // Set flag to redraw Editor buttons panel on the next interface render. void setRedraw() const; fheroes2::GameMode queueEventProcessing(); // Do not call this method directly, use Interface::Editor::redraw() instead. // The name of this method starts from _ on purpose to do not mix with other public methods. void _redraw() const; int32_t getSelectedObjectType() const; Maps::ObjectGroup getSelectedObjectGroup() const; void getTownObjectProperties( int32_t & type, int32_t & color ) const; void getMineObjectProperties( int32_t & type, int32_t & color ) const; static const char * getObjectGroupName( const Maps::ObjectGroup groupName ); private: static int _getGroundId( const uint8_t brushId ); static const char * _getTerrainTypeName( const uint8_t brushId ) { return Maps::Ground::String( _getGroundId( brushId ) ); } static const char * _getLandscapeObjectTypeName( const uint8_t brushId ); static const char * _getAdventureObjectTypeName( const uint8_t brushId ); static const char * _getKingdomObjectTypeName( const uint8_t brushId ); static const char * _getEraseObjectTypeName( const uint32_t eraseObjectType ); static int32_t _generateTownObjectProperties( const int32_t type, const int32_t color ); static int32_t _generateMineObjectProperties( const int32_t type, const int32_t color ); void _setCursor(); void handleObjectMouseClick( const std::function & typeSelection ); enum Instrument : uint8_t { // IMPORTANT. This enumeration corresponds with the order of instruments in original assets. Do not change this order. TERRAIN = 0U, LANDSCAPE_OBJECTS = 1U, DETAIL = 2U, ADVENTURE_OBJECTS = 3U, KINGDOM_OBJECTS = 4U, MONSTERS = 5U, STREAM = 6U, ROAD = 7U, ERASE = 8U, // The last element corresponds to the editor instruments count. INSTRUMENTS_COUNT = 9U }; enum TerrainBrush : uint8_t { // IMPORTANT. This enumeration corresponds with the order of instruments in original assets. Do not change this order. WATER = 0U, GRASS = 1U, SNOW = 2U, SWAMP = 3U, LAVA = 4U, DESERT = 5U, DIRT = 6U, WASTELAND = 7U, BEACH = 8U, // The last element corresponds to the editor terrain types count. TERRAIN_COUNT = 9U, }; enum LandscapeObjectBrush : int8_t { MOUNTAINS = 0, ROCKS = 1, TREES = 2, WATER_OBJECTS = 3, LANDSCAPE_MISC = 4, LANDSCAPE_COUNT = 5, }; enum AdventureObjectBrush : int8_t { ARTIFACTS = 0U, DWELLINGS = 1U, MINES = 2U, POWER_UPS = 3U, TREASURES = 4U, WATER_ADVENTURE = 5U, ADVENTURE_MISC = 6U, ADVENTURE_COUNT = 7U, }; enum KingdomObjectBrush : int8_t { HEROES = 0U, TOWNS = 1U, KINGDOM_OBJECTS_COUNT = 2U, }; enum BrushSize : uint8_t { // IMPORTANT. This enumeration corresponds with the order of brush size in original assets. Do not change this order. SMALL = 0U, MEDIUM = 1U, LARGE = 2U, AREA = 3U, // The last element corresponds to the editor brush size count. BRUSH_SIZE_COUNT = 4U }; enum ObjectErasureType : uint8_t { ERASE_NONE = 0x00, // Terrain objects are objects that are placed in editor using a terrain palette in objects placing mode. ERASE_LANDSCAPE = 0x01, ERASE_ADVENTURE_NON_PICKABLE = 0x02, ERASE_TOWNS = 0x04, ERASE_ADVENTURE_PICKABLE = 0x08, ERASE_MONSTERS = 0x10, ERASE_HEROES = 0x20, ERASE_STREAMS = 0x40, ERASE_ROADS = 0x80, ERASE_ALL_OBJECTS = ERASE_LANDSCAPE | ERASE_ADVENTURE_NON_PICKABLE | ERASE_TOWNS | ERASE_ADVENTURE_PICKABLE | ERASE_MONSTERS | ERASE_HEROES | ERASE_STREAMS | ERASE_ROADS, }; // This array represents the order of object-to-erase images on the erase tool panel (from left to right, from top to bottom). const std::array _eraseButtonObjectTypes{ ObjectErasureType::ERASE_LANDSCAPE, ObjectErasureType::ERASE_ADVENTURE_NON_PICKABLE, ObjectErasureType::ERASE_TOWNS, ObjectErasureType::ERASE_ADVENTURE_PICKABLE, ObjectErasureType::ERASE_MONSTERS, ObjectErasureType::ERASE_HEROES, ObjectErasureType::ERASE_ROADS, ObjectErasureType::ERASE_STREAMS }; EditorInterface & _interface; fheroes2::Button _buttonMagnify; fheroes2::Button _buttonUndo; fheroes2::Button _buttonRedo; fheroes2::Button _buttonSpecs; fheroes2::Button _buttonFile; fheroes2::Button _buttonSystem; fheroes2::Rect _rectMagnify; fheroes2::Rect _rectUndo; fheroes2::Rect _rectRedo; fheroes2::Rect _rectSpecs; fheroes2::Rect _rectFile; fheroes2::Rect _rectSystem; fheroes2::Rect _rectInstruments; fheroes2::Rect _rectInstrumentPanel; fheroes2::Rect _rectEditorPanel; fheroes2::Image _instrumentPanelBackground; std::array _instrumentButtons; std::array _brushSizeButtons; std::array _instrumentButtonsRect; std::array _terrainButtonsRect; std::array _landscapeObjectButtonsRect; std::array _adventureObjectButtonsRect; std::array _kingdomObjectButtonsRect; std::array _brushSizeButtonsRect; std::array _eraseButtonsRect; uint8_t _selectedInstrument{ Instrument::TERRAIN }; // A brand new map is always filled with Water so there is no need to make Water terrain brush as a default terrain selection. uint8_t _selectedTerrain{ TerrainBrush::GRASS }; int8_t _selectedLandscapeObject{ -1 }; int8_t _selectedAdventureObject{ -1 }; int8_t _selectedKingdomObject{ -1 }; uint8_t _selectedBrushSize{ BrushSize::MEDIUM }; uint32_t _eraseTypes{ ObjectErasureType::ERASE_ALL_OBJECTS }; std::array _selectedLandscapeObjectType; std::array _selectedAdventureObjectType; std::array _selectedKingdomObjectType; int32_t _selectedMonsterType{ -1 }; static const std::array _selectedLandscapeObjectGroup; static const std::array _selectedAdventureObjectGroup; static const std::array _selectedKingdomObjectGroup; }; } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_mainmenu.cpp000066400000000000000000000345241476115357100236520ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_mainmenu.h" #include #include #include #include #include #include "audio.h" #include "audio_manager.h" #include "cursor.h" #include "dialog.h" #include "dialog_selectscenario.h" #include "editor_interface.h" #include "game.h" #include "game_hotkeys.h" #include "game_mainmenu_ui.h" #include "game_mode.h" #include "icn.h" #include "localevent.h" #include "logging.h" #include "maps.h" #include "maps_fileinfo.h" #include "math_base.h" #include "mus.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_tool.h" #include "world.h" #include "world_object_uid.h" namespace { const int32_t buttonYStep = 66; const size_t mapSizeCount = 4; const std::array mapSizeHotkeys = { Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_SMALL, Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_MEDIUM, Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_LARGE, Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_EXTRA_LARGE }; const std::array mapSizes = { Maps::SMALL, Maps::MEDIUM, Maps::LARGE, Maps::XLARGE }; void outputEditorMainMenuInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Map Editor\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::EDITOR_NEW_MAP_MENU ) << " to create a new map either from scratch or using the random map generator." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::EDITOR_LOAD_MAP_MENU ) << " to load an existing map." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to go back to Main Menu." ) } void outputEditorNewMapMenuInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "New Map\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::EDITOR_FROM_SCRATCH_MAP_MENU ) << " to create a blank map from scratch." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::EDITOR_RANDOM_MAP_MENU ) << " to create a randomly generated map." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to go back to Map Editor main menu." ) } void outputEditorMapSizeMenuInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Map Size\n" ) const size_t buttonCount = mapSizeHotkeys.size(); for ( size_t i = 0; i < buttonCount; ++i ) { std::string message = " to create a map that is %{size} squares wide and %{size} squares high."; StringReplace( message, "%{size}", std::to_string( mapSizes[i] ) ); COUT( "Press " << Game::getHotKeyNameByEventId( mapSizeHotkeys[i] ) << message ) } COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to go back to New Map menu." ) } void showWIPInfo() { fheroes2::showStandardTextMessage( _( "Warning" ), "The Map Editor is still in development. This function is not available yet.", Dialog::OK ); } Maps::MapSize selectMapSize() { outputEditorMapSizeMenuInTextSupportMode(); const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawEditorMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); std::array buttons; for ( uint32_t i = 0; i < mapSizeCount; ++i ) { buttons[i].setICNInfo( ICN::BTNESIZE, 0 + i * 2, 1 + i * 2 ); buttons[i].setPosition( buttonPos.x, buttonPos.y + buttonYStep * static_cast( i ) ); buttons[i].draw(); } fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + 5 * buttonYStep, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); buttonCancel.draw(); fheroes2::validateFadeInAndRender(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { for ( size_t i = 0; i < mapSizeCount; ++i ) { buttons[i].drawOnState( le.isMouseLeftButtonPressedInArea( buttons[i].area() ) ); if ( le.MouseClickLeft( buttons[i].area() ) || Game::HotKeyPressEvent( mapSizeHotkeys[i] ) ) { return mapSizes[i]; } if ( le.isMouseRightButtonPressedInArea( buttons[i].area() ) ) { std::string mapSize = std::to_string( mapSizes[i] ); std::string message = _( "Create a map that is %{size} squares wide and %{size} squares high." ); StringReplace( message, "%{size}", mapSize ); mapSize += " x " + mapSize; fheroes2::showStandardTextMessage( mapSize, message, Dialog::ZERO ); } } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return Maps::ZERO; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the New Map menu." ), Dialog::ZERO ); } } return Maps::ZERO; } } namespace Editor { fheroes2::GameMode menuMain() { outputEditorMainMenuInTextSupportMode(); // Stop all sounds, but not the music AudioManager::stopSounds(); AudioManager::PlayMusicAsync( MUS::MAINMENU, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawEditorMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonNewMap( buttonPos.x, buttonPos.y, ICN::BTNEMAIN, 0, 1 ); fheroes2::Button buttonLoadMap( buttonPos.x, buttonPos.y + buttonYStep, ICN::BTNEMAIN, 2, 3 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + 5 * buttonYStep, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); buttonNewMap.draw(); buttonLoadMap.draw(); buttonCancel.draw(); fheroes2::validateFadeInAndRender(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonNewMap.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNewMap.area() ) ); buttonLoadMap.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLoadMap.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonNewMap.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_NEW_MAP_MENU ) ) { return fheroes2::GameMode::EDITOR_NEW_MAP; } if ( le.MouseClickLeft( buttonLoadMap.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_LOAD_MAP_MENU ) ) { return fheroes2::GameMode::EDITOR_LOAD_MAP; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return fheroes2::GameMode::MAIN_MENU; } if ( le.isMouseRightButtonPressedInArea( buttonNewMap.area() ) ) { // TODO: update this text once random map generator is ready. // The original text should be "Create a new map, either from scratch or using the random map generator." fheroes2::showStandardTextMessage( _( "New Map" ), _( "Create a new map from scratch." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonLoadMap.area() ) ) { fheroes2::showStandardTextMessage( _( "Load Map" ), _( "Load an existing map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::MAIN_MENU; } fheroes2::GameMode menuNewMap() { outputEditorNewMapMenuInTextSupportMode(); const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawEditorMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonScratchMap( buttonPos.x, buttonPos.y, ICN::BTNENEW, 0, 1 ); fheroes2::Button buttonRandomMap( buttonPos.x, buttonPos.y + buttonYStep, ICN::BTNENEW, 2, 3 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + 5 * buttonYStep, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); // TODO: enable it back once random map generator is ready. buttonRandomMap.disable(); buttonScratchMap.draw(); buttonRandomMap.draw(); buttonCancel.draw(); fheroes2::validateFadeInAndRender(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonScratchMap.drawOnState( le.isMouseLeftButtonPressedInArea( buttonScratchMap.area() ) ); if ( buttonRandomMap.isEnabled() ) { buttonRandomMap.drawOnState( le.isMouseLeftButtonPressedInArea( buttonRandomMap.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonScratchMap.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_FROM_SCRATCH_MAP_MENU ) ) { const Maps::MapSize mapSize = selectMapSize(); if ( mapSize != Maps::ZERO ) { world.generateForEditor( mapSize ); // Reset object UID to keep track of newly added objects. Maps::resetObjectUID(); fheroes2::fadeOutDisplay(); Game::setDisplayFadeIn(); return Interface::EditorInterface::Get().startEdit( true ); } return fheroes2::GameMode::EDITOR_NEW_MAP; } if ( buttonRandomMap.isEnabled() && ( le.MouseClickLeft( buttonRandomMap.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::EDITOR_RANDOM_MAP_MENU ) ) ) { if ( selectMapSize() != Maps::ZERO ) { showWIPInfo(); } return fheroes2::GameMode::EDITOR_NEW_MAP; } if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return fheroes2::GameMode::EDITOR_MAIN_MENU; } if ( le.isMouseRightButtonPressedInArea( buttonScratchMap.area() ) ) { fheroes2::showStandardTextMessage( _( "From Scratch" ), _( "Start from scratch with a blank map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonRandomMap.area() ) ) { fheroes2::showStandardTextMessage( _( "Random" ), _( "Create a randomly generated map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the Map Editor main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::EDITOR_MAIN_MENU; } fheroes2::GameMode menuLoadMap() { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawEditorMainMenuScreen(); fheroes2::validateFadeInAndRender(); const MapsFileInfoList lists = Maps::getResurrectionMapFileInfos( true, 0 ); if ( lists.empty() ) { fheroes2::showStandardTextMessage( _( "Warning" ), _( "No maps available!" ), Dialog::OK ); return fheroes2::GameMode::EDITOR_MAIN_MENU; } const Maps::FileInfo * fileInfo = Dialog::SelectScenario( lists, true ); if ( fileInfo == nullptr ) { return fheroes2::GameMode::EDITOR_MAIN_MENU; } Interface::EditorInterface & editorInterface = Interface::EditorInterface::Get(); if ( !editorInterface.loadMap( fileInfo->filename ) ) { return fheroes2::GameMode::CANCEL; } fheroes2::fadeOutDisplay(); Game::setDisplayFadeIn(); return Interface::EditorInterface::Get().startEdit( false ); } fheroes2::GameMode menuNewFromScratchMap() { const Maps::MapSize mapSize = selectMapSize(); if ( mapSize != Maps::ZERO ) { world.generateForEditor( mapSize ); // Reset object UID to keep track of newly added objects. Maps::resetObjectUID(); fheroes2::fadeOutDisplay(); Game::setDisplayFadeIn(); return Interface::EditorInterface::Get().startEdit( true ); } return fheroes2::GameMode::EDITOR_MAIN_MENU; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_mainmenu.h000066400000000000000000000033361476115357100233140ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include "game_mode.h" namespace Editor { fheroes2::GameMode menuMain(); fheroes2::GameMode menuNewMap(); fheroes2::GameMode menuLoadMap(); // TODO: this is a temporary solution before we implement random maps. fheroes2::GameMode menuNewFromScratchMap(); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_map_specs_window.cpp000066400000000000000000003506301476115357100254010ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_map_specs_window.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "artifact.h" #include "castle.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "dialog_language_selection.h" #include "dialog_selectitems.h" #include "difficulty.h" #include "editor_daily_events_window.h" #include "editor_rumor_window.h" #include "editor_ui_helper.h" #include "game_hotkeys.h" #include "game_over.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "map_format_helper.h" #include "map_format_info.h" #include "map_object_info.h" #include "maps_fileinfo.h" #include "math_base.h" #include "math_tools.h" #include "race.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_castle.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace { const int32_t descriptionBoxWidth = 292; const int32_t descriptionBoxHeight = 90; const int32_t playerStepX = 80; const int32_t difficultyStepX = 77; const int32_t daysInMonth{ 7 * 4 }; const int32_t daysInYear{ daysInMonth * 12 }; const uint32_t ultimateArtifactId = static_cast( Artifact::EDITOR_ANY_ULTIMATE_ARTIFACT ); const std::vector supportedVictoryConditions{ Maps::FileInfo::VICTORY_DEFEAT_EVERYONE, Maps::FileInfo::VICTORY_CAPTURE_TOWN, Maps::FileInfo::VICTORY_KILL_HERO, Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT, Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE, Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD }; const std::vector supportedLossConditions{ Maps::FileInfo::LOSS_EVERYTHING, Maps::FileInfo::LOSS_TOWN, Maps::FileInfo::LOSS_HERO, Maps::FileInfo::LOSS_OUT_OF_TIME }; struct HeroInfo { int32_t tileIndex{ -1 }; int32_t color{ Color::NONE }; const Maps::Map_Format::HeroMetadata * heroMetadata{ nullptr }; }; struct TownInfo { int32_t tileIndex{ -1 }; int32_t color{ Color::NONE }; int32_t race{ Race::NONE }; const Maps::Map_Format::CastleMetadata * castleMetadata{ nullptr }; }; fheroes2::Sprite getHeroIcon( const int32_t heroPortait, const int32_t race, const int32_t color, const int townIcnId ) { // To render hero icons we use castle flags and frame. const uint32_t flagIcnIndex = fheroes2::getCastleLeftFlagIcnIndex( color ); const fheroes2::Sprite & castleLeftFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex ); const fheroes2::Sprite & castleFrame = fheroes2::AGG::GetICN( townIcnId, 22 ); const fheroes2::Sprite & castleRightFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex + 1 ); fheroes2::Sprite castleIcon( castleFrame.width() + castleLeftFlag.width() + castleRightFlag.width() + 4, castleFrame.height() ); castleIcon.reset(); fheroes2::Blit( castleLeftFlag, 0, 0, castleIcon, 0, 5, castleLeftFlag.width(), castleLeftFlag.height() ); fheroes2::Blit( castleFrame, 0, 0, castleIcon, castleLeftFlag.width() + 2, 0, castleFrame.width(), castleFrame.height() ); fheroes2::Blit( castleRightFlag, 0, 0, castleIcon, castleFrame.width() + castleLeftFlag.width() + 4, 5, castleRightFlag.width(), castleRightFlag.height() ); if ( heroPortait > 0 ) { const fheroes2::Sprite & heroPortrait = fheroes2::AGG::GetICN( ICN::MINIPORT, heroPortait - 1 ); fheroes2::Copy( heroPortrait, 0, 0, castleIcon, castleLeftFlag.width() + 6, 4, heroPortrait.width(), heroPortrait.height() ); } else { // This is a hero with a random race dependent portrait. Render the default race portrait. uint32_t portraitIndex = 0; switch ( race ) { case Race::KNGT: portraitIndex = 51; break; case Race::BARB: portraitIndex = 52; break; case Race::SORC: portraitIndex = 53; break; case Race::WRLK: portraitIndex = 54; break; case Race::WZRD: portraitIndex = 55; break; case Race::NECR: portraitIndex = 56; break; case Race::RAND: portraitIndex = 58; break; default: // Have you added a new race? Correct the logic above! assert( 0 ); break; } fheroes2::Copy( fheroes2::AGG::GetICN( ICN::NGEXTRA, portraitIndex ), 17, 10, castleIcon, castleLeftFlag.width() + 6, 4, 30, 22 ); } return castleIcon; } fheroes2::Sprite getTownIcon( const bool isTown, const int32_t race, const int32_t color, const int townIcnId ) { const uint32_t flagIcnIndex = fheroes2::getCastleLeftFlagIcnIndex( color ); const fheroes2::Sprite & castleLeftFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex ); const fheroes2::Sprite & castleFrame = fheroes2::AGG::GetICN( townIcnId, 23 ); const fheroes2::Sprite & castleRightFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex + 1 ); fheroes2::Sprite castleIcon( castleFrame.width() + castleLeftFlag.width() + castleRightFlag.width() + 4, castleFrame.height() ); castleIcon.reset(); fheroes2::Blit( castleLeftFlag, 0, 0, castleIcon, 0, 5, castleLeftFlag.width(), castleLeftFlag.height() ); fheroes2::Blit( castleFrame, 0, 0, castleIcon, castleLeftFlag.width() + 2, 0, castleFrame.width(), castleFrame.height() ); fheroes2::Blit( castleRightFlag, 0, 0, castleIcon, castleFrame.width() + castleLeftFlag.width() + 4, 5, castleRightFlag.width(), castleRightFlag.height() ); const uint32_t icnIndex = fheroes2::getCastleIcnIndex( race, !isTown ); const fheroes2::Sprite & castleImage = fheroes2::AGG::GetICN( townIcnId, icnIndex ); fheroes2::Copy( castleImage, 0, 0, castleIcon, castleLeftFlag.width() + 6, 4, castleImage.width(), castleImage.height() ); return castleIcon; } std::string getHeroTitle( const std::string & name, const int race, const int32_t tileIndex, const int32_t mapWidth ) { std::string title; if ( name.empty() ) { title = _( "[%{pos}]: %{race} hero" ); } else { title = _( "[%{pos}]: %{name}, %{race} hero" ); StringReplace( title, "%{name}", name ); } StringReplace( title, "%{pos}", std::to_string( tileIndex % mapWidth ) + ", " + std::to_string( tileIndex / mapWidth ) ); StringReplace( title, "%{race}", Race::String( race ) ); return title; } std::string getTownTitle( const std::string & name, const int race, const bool isTown, const int32_t tileIndex, const int32_t mapWidth ) { std::string title; if ( name.empty() ) { if ( isTown ) { title = _( "[%{pos}]: %{race} town" ); } else { title = _( "[%{pos}]: %{race} castle" ); } } else { if ( isTown ) { title = _( "[%{pos}]: %{name}, %{race} town" ); } else { title = _( "[%{pos}]: %{name}, %{race} castle" ); } StringReplace( title, "%{name}", name ); } StringReplace( title, "%{pos}", std::to_string( tileIndex % mapWidth ) + ", " + std::to_string( tileIndex / mapWidth ) ); StringReplace( title, "%{race}", Race::String( race ) ); return title; } class SelectMapHero final : public Dialog::ItemSelectionWindow { public: explicit SelectMapHero( const fheroes2::Size & dialogSize, std::string title, std::string description, const int32_t mapWidth, const std::vector & heroInfos, const bool isEvilInterface ) : Dialog::ItemSelectionWindow( dialogSize, std::move( title ), std::move( description ) ) , _townIcnId( isEvilInterface ? ICN::LOCATORE : ICN::LOCATORS ) , _mapWidth( mapWidth ) , _heroInfos( heroInfos ) { SetAreaMaxItems( rtAreaItems.height / itemsOffsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { assert( index >= 0 && static_cast( index ) < _heroInfos.size() ); const auto & heroInfo = _heroInfos[index]; const auto * heroMetadata = heroInfo.heroMetadata; renderItem( getHeroIcon( heroMetadata->customPortrait, heroMetadata->race, heroInfo.color, _townIcnId ), getHeroTitle( heroMetadata->customName, heroMetadata->race, heroInfo.tileIndex, _mapWidth ), { dstx, dsty }, 40, 85, itemsOffsetY / 2, current ); } void ActionListPressRight( int & index ) override { assert( index >= 0 && static_cast( index ) < _heroInfos.size() ); const auto & heroInfo = _heroInfos[index]; fheroes2::showStandardTextMessage( {}, getHeroTitle( heroInfo.heroMetadata->customName, heroInfo.heroMetadata->race, heroInfo.tileIndex, _mapWidth ), Dialog::ZERO ); } static const int32_t itemsOffsetY{ 35 }; private: const int _townIcnId{ ICN::UNKNOWN }; const int32_t _mapWidth{ 0 }; const std::vector & _heroInfos; }; class SelectMapCastle final : public Dialog::ItemSelectionWindow { public: explicit SelectMapCastle( const fheroes2::Size & dialogSize, std::string title, std::string description, const int32_t mapWidth, const std::vector & townInfos, const bool isEvilInterface ) : Dialog::ItemSelectionWindow( dialogSize, std::move( title ), std::move( description ) ) , _townIcnId( isEvilInterface ? ICN::LOCATORE : ICN::LOCATORS ) , _mapWidth( mapWidth ) , _townInfos( townInfos ) { SetAreaMaxItems( rtAreaItems.height / itemsOffsetY ); } using Dialog::ItemSelectionWindow::ActionListPressRight; void RedrawItem( const int & index, int32_t dstx, int32_t dsty, bool current ) override { assert( index >= 0 && static_cast( index ) < _townInfos.size() ); const auto & townInfo = _townInfos[index]; const auto * castleMetadata = townInfo.castleMetadata; const bool isTown = std::find( castleMetadata->builtBuildings.begin(), castleMetadata->builtBuildings.end(), BUILD_CASTLE ) == castleMetadata->builtBuildings.end(); renderItem( getTownIcon( isTown, townInfo.race, townInfo.color, _townIcnId ), getTownTitle( castleMetadata->customName, townInfo.race, isTown, townInfo.tileIndex, _mapWidth ), { dstx, dsty }, 45, 95, itemsOffsetY / 2, current ); } void ActionListPressRight( int & index ) override { assert( index >= 0 && static_cast( index ) < _townInfos.size() ); const auto & townInfo = _townInfos[index]; const auto * castleMetadata = townInfo.castleMetadata; const bool isTown = std::find( castleMetadata->builtBuildings.begin(), castleMetadata->builtBuildings.end(), BUILD_CASTLE ) == castleMetadata->builtBuildings.end(); fheroes2::showStandardTextMessage( {}, getTownTitle( townInfo.castleMetadata->customName, townInfo.race, isTown, townInfo.tileIndex, _mapWidth ), Dialog::ZERO ); } static const int32_t itemsOffsetY{ 35 }; private: const int _townIcnId{ ICN::UNKNOWN }; const int32_t _mapWidth{ 0 }; const std::vector & _townInfos; }; std::vector getMapHeroes( const Maps::Map_Format::MapFormat & map, const int32_t allowedColors ) { if ( allowedColors == Color::NONE ) { // Nothing to do. return {}; } const auto & heroObjects = Maps::getObjectsByGroup( Maps::ObjectGroup::KINGDOM_HEROES ); std::vector heroInfos; // TODO: cache all heroes once this dialog is open. No need to run through all objects every time. for ( size_t tileIndex = 0; tileIndex < map.tiles.size(); ++tileIndex ) { for ( const auto & object : map.tiles[tileIndex].objects ) { if ( object.group != Maps::ObjectGroup::KINGDOM_HEROES ) { continue; } if ( object.index >= heroObjects.size() ) { assert( 0 ); continue; } const auto & metadata = heroObjects[object.index].metadata; const int32_t color = 1 << metadata[0]; if ( !( color & allowedColors ) ) { // Current hero color is not allowed. continue; } heroInfos.emplace_back(); HeroInfo & heroInfo = heroInfos.back(); heroInfo.tileIndex = static_cast( tileIndex ); heroInfo.color = color; auto heroMetadataIter = map.heroMetadata.find( object.id ); assert( heroMetadataIter != map.heroMetadata.end() ); heroInfo.heroMetadata = &heroMetadataIter->second; } } return heroInfos; } std::vector getMapTowns( const Maps::Map_Format::MapFormat & map, const int32_t allowedColors, const bool excludeNeutralTowns ) { if ( excludeNeutralTowns && allowedColors == Color::NONE ) { // Nothing to do. return {}; } const auto & townObjects = Maps::getObjectsByGroup( Maps::ObjectGroup::KINGDOM_TOWNS ); std::vector townInfos; // TODO: cache all towns once this dialog is open. No need to run through all objects every time. for ( size_t tileIndex = 0; tileIndex < map.tiles.size(); ++tileIndex ) { for ( const auto & object : map.tiles[tileIndex].objects ) { if ( object.group != Maps::ObjectGroup::KINGDOM_TOWNS ) { continue; } if ( object.index >= townObjects.size() ) { assert( 0 ); continue; } const int32_t color = Color::IndexToColor( Maps::getTownColorIndex( map, tileIndex, object.id ) ); if ( !( color & allowedColors ) && ( excludeNeutralTowns || color != Color::NONE ) ) { // Current town color is not allowed. continue; } townInfos.emplace_back(); TownInfo & townInfo = townInfos.back(); townInfo.tileIndex = static_cast( tileIndex ); townInfo.color = color; townInfo.race = Race::IndexToRace( static_cast( townObjects[object.index].metadata[0] ) ); const auto castleMetadataIter = map.castleMetadata.find( object.id ); assert( castleMetadataIter != map.castleMetadata.end() ); townInfo.castleMetadata = &castleMetadataIter->second; } } return townInfos; } const char * getVictoryConditionText( const uint8_t victoryConditionType ) { switch ( victoryConditionType ) { case Maps::FileInfo::VICTORY_DEFEAT_EVERYONE: return _( "None." ); case Maps::FileInfo::VICTORY_CAPTURE_TOWN: return GameOver::GetString( GameOver::WINS_TOWN ); case Maps::FileInfo::VICTORY_KILL_HERO: return GameOver::GetString( GameOver::WINS_HERO ); case Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT: return GameOver::GetString( GameOver::WINS_ARTIFACT ); case Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE: return _( "One side defeats another." ); case Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD: return _( "Accumulate gold." ); default: // This is an unknown condition. Add the logic for it above! assert( 0 ); break; } return "Unknown"; } uint32_t getVictoryIcnIndex( const uint8_t victoryConditionType ) { switch ( victoryConditionType ) { case Maps::FileInfo::VICTORY_DEFEAT_EVERYONE: return 30; case Maps::FileInfo::VICTORY_CAPTURE_TOWN: return 31; case Maps::FileInfo::VICTORY_KILL_HERO: return 32; case Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT: return 33; case Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE: return 34; case Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD: return 35; default: // This is an unknown condition. Add the logic for it above! assert( 0 ); break; } return 0; } const char * getLossConditionText( const uint8_t lossConditionType ) { switch ( lossConditionType ) { case Maps::FileInfo::LOSS_EVERYTHING: return _( "None." ); case Maps::FileInfo::LOSS_TOWN: return GameOver::GetString( GameOver::LOSS_TOWN ); case Maps::FileInfo::LOSS_HERO: return GameOver::GetString( GameOver::LOSS_HERO ); case Maps::FileInfo::LOSS_OUT_OF_TIME: return _( "Run out of time." ); default: // This is an unknown condition. Add the logic for it above! assert( 0 ); break; } return "Unknown"; } // Returns the order text of the alliance: 0 will be "1st" and so on. const char * getAllianceOrderText( const size_t index ) { switch ( index ) { case 0: return _( "alliance|1st" ); case 1: return _( "alliance|2nd" ); case 2: return _( "alliance|3rd" ); case 3: return _( "alliance|4th" ); case 4: return _( "alliance|5th" ); default: // The engine supports up to 6 players so there can be a maximum of 5 alliances: one with 2 players and four with 1 player. assert( 0 ); } return "Unknown"; } uint32_t getLossIcnIndex( const uint8_t lossConditionType ) { switch ( lossConditionType ) { case Maps::FileInfo::LOSS_EVERYTHING: return 36; case Maps::FileInfo::LOSS_TOWN: return 37; case Maps::FileInfo::LOSS_HERO: return 38; case Maps::FileInfo::LOSS_OUT_OF_TIME: return 39; default: // This is an unknown condition. Add the logic for it above! assert( 0 ); break; } return 0; } void redrawVictoryCondition( const uint8_t condition, const fheroes2::Rect & roi, const bool yellowFont, fheroes2::Image & output ) { const fheroes2::Sprite & winIcon = fheroes2::AGG::GetICN( ICN::REQUESTS, getVictoryIcnIndex( condition ) ); fheroes2::Copy( winIcon, 0, 0, output, roi.x + 1, roi.y, winIcon.width(), winIcon.height() ); const fheroes2::Text winText( getVictoryConditionText( condition ), yellowFont ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ); winText.drawInRoi( roi.x + 20, roi.y + 2, output, roi ); } void redrawLossCondition( const uint8_t condition, const fheroes2::Rect & roi, const bool yellowFont, fheroes2::Image & output ) { const fheroes2::Sprite & icon = fheroes2::AGG::GetICN( ICN::REQUESTS, getLossIcnIndex( condition ) ); fheroes2::Copy( icon, 0, 0, output, roi.x + 1, roi.y, icon.width(), icon.height() ); const fheroes2::Text winText( getLossConditionText( condition ), yellowFont ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ); winText.drawInRoi( roi.x + 20, roi.y + 2, output, roi ); } class DropBoxList final : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; DropBoxList( const DropBoxList & ) = delete; DropBoxList & operator=( const DropBoxList & ) = delete; ~DropBoxList() override = default; explicit DropBoxList( const fheroes2::Point & pt, const int32_t itemsCount, const bool isLossList, const int dropBoxIcn ) : Interface::ListBox( pt ) , _isLossList( isLossList ) { SetAreaMaxItems( itemsCount ); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Sprite & image = fheroes2::AGG::GetICN( dropBoxIcn, 0 ); const int32_t topPartHeight = image.height() - 2; const int32_t listWidth = image.width(); const int32_t middlePartHeight = topPartHeight - 2; const int32_t bottomPartHeight = topPartHeight; const int32_t listHeight = itemsCount * ( _itemHeight + 2 ) + 6; _itemWidth = listWidth - 6; _restorer = std::make_unique( display, pt.x, pt.y, listWidth + 1, listHeight ); // Top part of list background. fheroes2::Copy( image, 0, 0, display, pt.x, pt.y, listWidth, topPartHeight ); const int32_t lineFixOffsetX = pt.x + listWidth; fheroes2::Copy( image, 0, 0, display, lineFixOffsetX, pt.y, 1, topPartHeight ); // Middle part of list background. const int32_t middlePartCount = ( listHeight - topPartHeight - bottomPartHeight + middlePartHeight - 1 ) / middlePartHeight; int32_t offsetY = topPartHeight; for ( int32_t i = 0; i < middlePartCount; ++i ) { const int32_t copyHeight = std::min( middlePartHeight, listHeight - bottomPartHeight - offsetY ); const int32_t posY = pt.y + offsetY; fheroes2::Copy( image, 0, 2, display, pt.x, posY, listWidth, copyHeight ); fheroes2::Copy( image, 0, 2, display, lineFixOffsetX, posY, 1, copyHeight ); offsetY += middlePartHeight; } // Bottom part of list background. offsetY = pt.y + listHeight - bottomPartHeight; fheroes2::Copy( image, 0, 2, display, pt.x, offsetY, listWidth, bottomPartHeight ); fheroes2::Copy( image, 0, 2, display, lineFixOffsetX, offsetY, 1, bottomPartHeight ); _background = std::make_unique( display, pt.x + 2, pt.y + 2, listWidth - 3, listHeight - 4 ); SetAreaItems( { pt.x + 2, pt.y + 5, listWidth - 4, listHeight - 6 } ); } void RedrawItem( const uint8_t & condition, int32_t dstX, int32_t dstY, bool current ) override { if ( _isLossList ) { redrawLossCondition( condition, { dstX, dstY, _itemWidth, _itemHeight }, current, fheroes2::Display::instance() ); } else { redrawVictoryCondition( condition, { dstX, dstY, _itemWidth, _itemHeight }, current, fheroes2::Display::instance() ); } } void RedrawBackground( const fheroes2::Point & /*dst*/ ) override { _background->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListDoubleClick( uint8_t & /* item */ ) override { _isClicked = true; } void ActionListSingleClick( uint8_t & /* item */ ) override { _isClicked = true; } void ActionListPressRight( uint8_t & condition ) override { if ( _isLossList ) { fheroes2::showStandardTextMessage( _( "Special Loss Condition" ), getLossConditionText( condition ), Dialog::ZERO ); } else { fheroes2::showStandardTextMessage( _( "Special Victory Condition" ), getVictoryConditionText( condition ), Dialog::ZERO ); } } fheroes2::Rect getArea() const { if ( _restorer == nullptr ) { return {}; } return _restorer->rect(); } bool isClicked() const { return _isClicked; } private: bool _isClicked{ false }; bool _isLossList{ false }; int32_t _itemWidth; int32_t _itemHeight{ fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ) + 1 }; std::unique_ptr _restorer; std::unique_ptr _background; }; class VictoryConditionUI final { public: VictoryConditionUI( fheroes2::Image & output, const fheroes2::Rect & roi, const Maps::Map_Format::MapFormat & mapFormat, const bool isEvilInterface ) : _conditionType( mapFormat.victoryConditionType ) , _availableColors( mapFormat.availablePlayerColors ) , _isNormalVictoryAllowed( mapFormat.allowNormalVictory ) , _isVictoryConditionApplicableForAI( mapFormat.isVictoryConditionApplicableForAI ) , _isEvilInterface( isEvilInterface ) , _mapWidth( mapFormat.size ) , _restorer( output, roi.x, roi.y, roi.width, roi.height ) { // Set the initial state for all victory conditions. switch ( _conditionType ) { case Maps::FileInfo::VICTORY_DEFEAT_EVERYONE: // This condition has no extra options. break; case Maps::FileInfo::VICTORY_CAPTURE_TOWN: if ( mapFormat.victoryConditionMetadata.size() == 2 ) { std::copy( mapFormat.victoryConditionMetadata.begin(), mapFormat.victoryConditionMetadata.end(), _townToCapture.begin() ); // Verify that this is a valid computer-only town. _mapTownInfos = getMapTowns( mapFormat, mapFormat.computerPlayerColors & ( ~mapFormat.humanPlayerColors ), false ); const int32_t townTileIndex = static_cast( _townToCapture[0] ); bool townFound = false; for ( const auto & town : _mapTownInfos ) { if ( townTileIndex == town.tileIndex && static_cast( _townToCapture[1] ) == town.color ) { townFound = true; break; } } if ( !townFound ) { _conditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; } } else { // Since the metadata is invalid we have 2 options: // - fall back to normal victory condition as no town was set // - generate a list of towns and pick one // For simplicity we are choosing the first option for now. _conditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; } break; case Maps::FileInfo::VICTORY_KILL_HERO: if ( mapFormat.victoryConditionMetadata.size() == 2 ) { std::copy( mapFormat.victoryConditionMetadata.begin(), mapFormat.victoryConditionMetadata.end(), _heroToKill.begin() ); // Verify that this is a valid computer-only hero. _mapHeroInfos = getMapHeroes( mapFormat, mapFormat.computerPlayerColors & ( ~mapFormat.humanPlayerColors ) ); const int32_t heroTileIndex = static_cast( _heroToKill[0] ); bool heroFound = false; for ( const auto & hero : _mapHeroInfos ) { if ( heroTileIndex == hero.tileIndex && static_cast( _heroToKill[1] ) == hero.color ) { heroFound = true; break; } } if ( !heroFound ) { _conditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; } } else { // Since the metadata is invalid we have 2 options: // - fall back to normal victory condition as no hero was set // - generate a list of heroes and pick one // For simplicity we are choosing the first option for now. _conditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; } break; case Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT: if ( mapFormat.victoryConditionMetadata.size() == 1 ) { // In original game's map format '0' stands for any Ultimate Artifact. _victoryArtifactId = ( mapFormat.victoryConditionMetadata[0] == 0 ) ? ultimateArtifactId : mapFormat.victoryConditionMetadata[0]; } break; case Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE: // As of now only 2 alliances are supported. // TODO: Update this logic for more than 2 alliances. // Use the alliances saved in the mapFormat only if they are correct. if ( mapFormat.alliances.size() == 2 && ( mapFormat.alliances[0] & mapFormat.alliances[1] ) == 0 && mapFormat.availablePlayerColors == ( mapFormat.alliances[0] | mapFormat.alliances[1] ) && mapFormat.alliances[0] != 0 && mapFormat.alliances[1] != 0 ) { _alliances = mapFormat.alliances; } break; case Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD: { if ( mapFormat.victoryConditionMetadata.size() == 1 ) { _goldAccumulationValue.setValue( static_cast( mapFormat.victoryConditionMetadata[0] ) ); } break; } default: // Did you add more conditions? Add the logic for them! assert( 0 ); break; } if ( _alliances.size() != 2 ) { // Fill in the default alliances: the first human player against all others. _alliances.clear(); const uint8_t firstColor = static_cast( Color::GetFirst( mapFormat.humanPlayerColors ) ); _alliances.push_back( firstColor ); _alliances.push_back( mapFormat.availablePlayerColors ^ firstColor ); } } void setConditionType( const uint8_t victoryConditionType ) { _conditionType = victoryConditionType; } bool updateCondition( Maps::Map_Format::MapFormat & mapFormat ) { switch ( _conditionType ) { case Maps::FileInfo::VICTORY_CAPTURE_TOWN: { _mapTownInfos = getMapTowns( mapFormat, mapFormat.computerPlayerColors & ( ~mapFormat.humanPlayerColors ), false ); if ( _mapTownInfos.empty() ) { // No towns exist for computer-only players. _conditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; mapFormat.victoryConditionType = _conditionType; return true; } bool townFound = false; for ( const auto & town : _mapTownInfos ) { if ( static_cast( _townToCapture[0] ) == town.tileIndex && static_cast( _townToCapture[1] ) == town.color ) { townFound = true; break; } } if ( !townFound ) { // The town doesn't exist in the list. Select the first one. _townToCapture[0] = static_cast( _mapTownInfos[0].tileIndex ); _townToCapture[1] = static_cast( _mapTownInfos[0].color ); return true; } return false; } case Maps::FileInfo::VICTORY_KILL_HERO: { _mapHeroInfos = getMapHeroes( mapFormat, mapFormat.computerPlayerColors & ( ~mapFormat.humanPlayerColors ) ); if ( _mapHeroInfos.empty() ) { // No heroes exist for computer-only players. _conditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; mapFormat.victoryConditionType = _conditionType; return true; } const int32_t heroTileIndex = static_cast( _heroToKill[0] ); bool heroFound = false; for ( const auto & hero : _mapHeroInfos ) { if ( heroTileIndex == hero.tileIndex && static_cast( _heroToKill[1] ) == hero.color ) { heroFound = true; break; } } if ( !heroFound ) { // The hero doesn't exist in the list. Select the first one. _heroToKill[0] = static_cast( _mapHeroInfos[0].tileIndex ); _heroToKill[1] = static_cast( _mapHeroInfos[0].color ); } return false; } default: // No changes for other victory conditions. break; } return false; } void getConditionMetadata( Maps::Map_Format::MapFormat & mapFormat ) const { assert( mapFormat.victoryConditionType == _conditionType ); switch ( _conditionType ) { case Maps::FileInfo::VICTORY_DEFEAT_EVERYONE: // This condition has no metadata. mapFormat.victoryConditionMetadata.clear(); mapFormat.allowNormalVictory = false; mapFormat.isVictoryConditionApplicableForAI = false; return; case Maps::FileInfo::VICTORY_CAPTURE_TOWN: if ( mapFormat.victoryConditionMetadata.size() != 2 ) { mapFormat.victoryConditionMetadata.resize( 2 ); } std::copy( _townToCapture.begin(), _townToCapture.end(), mapFormat.victoryConditionMetadata.begin() ); mapFormat.allowNormalVictory = _isNormalVictoryAllowed; // For all non-neutral towns disable the "Allow this condition also for AI" setting. mapFormat.isVictoryConditionApplicableForAI = ( _townToCapture[1] == Color::NONE ) ? _isVictoryConditionApplicableForAI : false; return; case Maps::FileInfo::VICTORY_KILL_HERO: if ( mapFormat.victoryConditionMetadata.size() != 2 ) { mapFormat.victoryConditionMetadata.resize( 2 ); } std::copy( _heroToKill.begin(), _heroToKill.end(), mapFormat.victoryConditionMetadata.begin() ); mapFormat.allowNormalVictory = false; mapFormat.isVictoryConditionApplicableForAI = false; return; case Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT: if ( mapFormat.victoryConditionMetadata.size() != 1 ) { mapFormat.victoryConditionMetadata.resize( 1 ); } mapFormat.isVictoryConditionApplicableForAI = false; // In original game's map format '0' stands for any Ultimate Artifact. Set it also to '0' for the compatibility. mapFormat.victoryConditionMetadata[0] = ( _victoryArtifactId == ultimateArtifactId ) ? 0 : _victoryArtifactId; mapFormat.allowNormalVictory = _isNormalVictoryAllowed; return; case Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE: mapFormat.alliances = _alliances; mapFormat.allowNormalVictory = false; mapFormat.isVictoryConditionApplicableForAI = false; return; case Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD: if ( mapFormat.victoryConditionMetadata.size() != 1 ) { mapFormat.victoryConditionMetadata.resize( 1 ); } mapFormat.victoryConditionMetadata[0] = static_cast( _goldAccumulationValue.getValue() ); mapFormat.allowNormalVictory = _isNormalVictoryAllowed; mapFormat.isVictoryConditionApplicableForAI = _isVictoryConditionApplicableForAI; return; default: // Did you add more conditions? Add the logic for them! assert( 0 ); // Reset the unknown condition to the default condition type. mapFormat.victoryConditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; mapFormat.allowNormalVictory = false; mapFormat.isVictoryConditionApplicableForAI = false; break; } } void render( fheroes2::Image & output, const bool renderEverything ) { if ( renderEverything ) { // Restore background to make sure that other UI elements aren't being rendered. _restorer.restore(); } switch ( _conditionType ) { case Maps::FileInfo::VICTORY_DEFEAT_EVERYONE: // No special UI is needed. break; case Maps::FileInfo::VICTORY_CAPTURE_TOWN: { if ( !renderEverything ) { // To render this condition we always redraw the whole conditions UI. // TODO: optimize the rendering. _restorer.restore(); } assert( !_mapTownInfos.empty() ); size_t selectedTownIndex = 0; for ( size_t i = 0; i < _mapTownInfos.size(); ++i ) { if ( static_cast( _townToCapture[0] ) == _mapTownInfos[i].tileIndex && static_cast( _townToCapture[1] ) == _mapTownInfos[i].color ) { selectedTownIndex = i; break; } } const auto & townInfo = _mapTownInfos[selectedTownIndex]; const auto * castleMetadata = townInfo.castleMetadata; const int townIcnId = _isEvilInterface ? ICN::LOCATORE : ICN::LOCATORS; const bool isTown = std::find( castleMetadata->builtBuildings.begin(), castleMetadata->builtBuildings.end(), BUILD_CASTLE ) == castleMetadata->builtBuildings.end(); const fheroes2::Sprite townIcon( getTownIcon( isTown, townInfo.race, townInfo.color, townIcnId ) ); const fheroes2::Rect roi{ _restorer.rect() }; fheroes2::Blit( townIcon, output, roi.x, roi.y + 4 ); fheroes2::Text text( getTownTitle( castleMetadata->customName, townInfo.race, isTown, townInfo.tileIndex, _mapWidth ), fheroes2::FontType::normalWhite() ); text.fitToOneRow( roi.width - townIcon.width() - 5 ); text.drawInRoi( roi.x + townIcon.width() + 5, roi.y + 12, output, roi ); _selectConditionRoi = { roi.x, roi.y + 4, townIcon.width() + 5 + text.width(), townIcon.height() }; if ( !_isNormalVictoryAllowed ) { _allowNormalVictory.hide(); } _allowNormalVictoryRoi = Editor::drawCheckboxWithText( _allowNormalVictory, _( "Allow standard victory conditions" ), output, roi.x + 5, roi.y + _selectConditionRoi.height + 35, _isEvilInterface, roi.width - 5 ); if ( _isNormalVictoryAllowed ) { _allowNormalVictory.show(); } // Allow "Allow this condition also for AI" setting only for neutral towns. if ( _townToCapture[1] == Color::NONE ) { if ( !_isVictoryConditionApplicableForAI ) { _allowVictoryConditionForAI.hide(); } _allowVictoryConditionForAIRoi = Editor::drawCheckboxWithText( _allowVictoryConditionForAI, _( "Allow this condition also for AI" ), output, roi.x + 5, roi.y + _selectConditionRoi.height + 10, _isEvilInterface, roi.width - 5 ); if ( _isVictoryConditionApplicableForAI ) { _allowVictoryConditionForAI.show(); } } break; } case Maps::FileInfo::VICTORY_KILL_HERO: { if ( !renderEverything ) { // To render this condition we always redraw the whole conditions UI. // TODO: optimize the rendering. _restorer.restore(); } const fheroes2::Rect roi{ _restorer.rect() }; const fheroes2::Sprite & heroFrame = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); const int32_t heroFrameWidth = 111; const int32_t heroFrameHeight = 105; _selectConditionRoi = { roi.x + ( roi.width - heroFrameWidth ) / 2, roi.y + 4, heroFrameWidth, heroFrameHeight }; fheroes2::Blit( heroFrame, 88, 66, output, _selectConditionRoi.x, _selectConditionRoi.y, heroFrameWidth, heroFrameHeight ); assert( !_mapHeroInfos.empty() ); size_t selectedHeroIndex = 0; for ( size_t i = 0; i < _mapHeroInfos.size(); ++i ) { if ( static_cast( _heroToKill[0] ) == _mapHeroInfos[i].tileIndex && static_cast( _heroToKill[1] ) == _mapHeroInfos[i].color ) { selectedHeroIndex = i; break; } } // To render hero icons we use castle flags and frame. const uint32_t flagIcnIndex = fheroes2::getCastleLeftFlagIcnIndex( static_cast( _heroToKill[1] ) ); const fheroes2::Sprite & castleLeftFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex ); const fheroes2::Sprite & castleRightFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex + 1 ); Blit( castleLeftFlag, 0, 0, output, _selectConditionRoi.x - 21, _selectConditionRoi.y + 45, castleLeftFlag.width(), castleLeftFlag.height() ); Blit( castleRightFlag, 0, 0, output, _selectConditionRoi.x + _selectConditionRoi.width + 2, _selectConditionRoi.y + 45, castleRightFlag.width(), castleRightFlag.height() ); const auto * heroMetadata = _mapHeroInfos[selectedHeroIndex].heroMetadata; const int32_t heroPortraitId = heroMetadata->customPortrait; if ( heroPortraitId > 0 ) { const fheroes2::Sprite & heroPortrait = fheroes2::AGG::GetICN( ICN::getHeroPortraitIcnId( heroPortraitId ), 0 ); fheroes2::Copy( heroPortrait, 0, 0, output, _selectConditionRoi.x + 5, _selectConditionRoi.y + 6, heroPortrait.width(), heroPortrait.height() ); } else { fheroes2::renderHeroRacePortrait( heroMetadata->race, { _selectConditionRoi.x + 5, _selectConditionRoi.y + 6, 101, 93 }, output ); } fheroes2::Text extraText( getHeroTitle( heroMetadata->customName, heroMetadata->race, static_cast( _heroToKill[0] ), _mapWidth ), fheroes2::FontType::normalWhite() ); extraText.fitToOneRow( roi.width ); extraText.drawInRoi( roi.x, _selectConditionRoi.y + _selectConditionRoi.height + 5, roi.width, output, roi ); break; } case Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT: { if ( renderEverything ) { const fheroes2::Rect roi{ _restorer.rect() }; const fheroes2::Sprite & artifactFrame = fheroes2::AGG::GetICN( ICN::RESOURCE, 7 ); _selectConditionRoi = { roi.x + ( roi.width - artifactFrame.width() ) / 2, roi.y + 4, artifactFrame.width(), artifactFrame.height() }; fheroes2::Blit( artifactFrame, output, _selectConditionRoi.x, _selectConditionRoi.y ); if ( !_isNormalVictoryAllowed ) { _allowNormalVictory.hide(); } _allowNormalVictoryRoi = Editor::drawCheckboxWithText( _allowNormalVictory, _( "Allow standard victory conditions" ), output, roi.x + 5, roi.y + _selectConditionRoi.height + 10, _isEvilInterface, roi.width - 5 ); } const fheroes2::Sprite & artifactImage = fheroes2::AGG::GetICN( ICN::ARTIFACT, Artifact( static_cast( _victoryArtifactId ) ).IndexSprite64() ); fheroes2::Copy( artifactImage, 0, 0, output, _selectConditionRoi.x + 6, _selectConditionRoi.y + 6, artifactImage.width(), artifactImage.height() ); if ( _isNormalVictoryAllowed ) { _allowNormalVictory.show(); } else { _allowNormalVictory.hide(); } break; } case Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE: { if ( renderEverything ) { const fheroes2::Rect roi{ _restorer.rect() }; int32_t offsetY = roi.y + 2; fheroes2::Text text( _( "Set alliances:" ), fheroes2::FontType::normalWhite() ); text.draw( roi.x + ( roi.width - text.width() ) / 2, offsetY, output ); _alliancesCheckboxes.clear(); offsetY += text.height(); const int32_t stepY = 32; const int32_t checkboxesOffsetX = roi.x + ( roi.width - Color::Count( _availableColors ) * 32 + 12 ) / 2; for ( size_t i = 0; i < _alliances.size(); ++i ) { std::string allianceText = _( "{%number} alliance: " ); StringReplace( allianceText, "{%number}", getAllianceOrderText( i ) ); text.set( std::move( allianceText ), fheroes2::FontType::normalWhite() ); const int32_t textWidth = text.width() + 5; const int32_t posX = checkboxesOffsetX - textWidth / 2; text.draw( posX, offsetY + 4, output ); std::vector> allianceCheckboxes; createColorCheckboxes( allianceCheckboxes, _availableColors, _alliances[i], posX + textWidth, offsetY, output ); _alliancesCheckboxes.push_back( std::move( allianceCheckboxes ) ); offsetY += stepY; } } // The mark rendering of the checkboxes is handled in processEvents(). break; } case Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD: { if ( renderEverything ) { const fheroes2::Size valueSectionUiSize = fheroes2::ValueSelectionDialogElement::getArea(); const fheroes2::Rect roi{ _restorer.rect() }; const fheroes2::Point uiOffset{ roi.x + ( roi.width - valueSectionUiSize.width ) / 2, roi.y }; _goldAccumulationValue.setOffset( uiOffset ); _goldAccumulationValue.draw( output ); const fheroes2::Text text( _( "Gold:" ), fheroes2::FontType::normalWhite() ); text.draw( uiOffset.x - text.width() - 5, roi.y + ( valueSectionUiSize.height - text.height() ) / 2 + 2, output ); if ( !_isVictoryConditionApplicableForAI ) { _allowVictoryConditionForAI.hide(); } if ( !_isNormalVictoryAllowed ) { _allowNormalVictory.hide(); } _allowVictoryConditionForAIRoi = Editor::drawCheckboxWithText( _allowVictoryConditionForAI, _( "Allow this condition also for AI" ), output, roi.x + 5, roi.y + valueSectionUiSize.height + 10, _isEvilInterface, roi.width - 5 ); _allowNormalVictoryRoi = Editor::drawCheckboxWithText( _allowNormalVictory, _( "Allow standard victory conditions" ), output, roi.x + 5, roi.y + valueSectionUiSize.height + 35, _isEvilInterface, roi.width - 5 ); } _goldAccumulationValue.draw( output ); if ( _isNormalVictoryAllowed ) { _allowNormalVictory.show(); } else { _allowNormalVictory.hide(); } if ( _isVictoryConditionApplicableForAI ) { _allowVictoryConditionForAI.show(); } else { _allowVictoryConditionForAI.hide(); } break; } default: // Did you add more conditions? Add the logic for them! assert( 0 ); break; } } // Returns true if rendering is required. bool processEvents() { switch ( _conditionType ) { case Maps::FileInfo::VICTORY_DEFEAT_EVERYONE: // No events to process. return false; case Maps::FileInfo::VICTORY_CAPTURE_TOWN: { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( _selectConditionRoi ) ) { assert( !_mapTownInfos.empty() ); const int32_t maxHeight = std::min( 100 + SelectMapCastle::itemsOffsetY * 12, fheroes2::Display::instance().height() - 100 ); const int32_t itemsHeight = std::max( 100 + SelectMapCastle::itemsOffsetY * static_cast( _mapTownInfos.size() ), 100 + SelectMapCastle::itemsOffsetY * 5 ); const int32_t totalHeight = std::min( itemsHeight, maxHeight ); SelectMapCastle listbox( { 450, totalHeight }, _( "Select a Town to capture to achieve victory" ), {}, _mapWidth, _mapTownInfos, _isEvilInterface ); std::vector townIndicies( _mapTownInfos.size() ); std::iota( townIndicies.begin(), townIndicies.end(), 0 ); listbox.SetListContent( townIndicies ); int initiallySelectedTownIndex = 0; for ( size_t i = 0; i < _mapTownInfos.size(); ++i ) { if ( static_cast( _townToCapture[0] ) == _mapTownInfos[i].tileIndex && static_cast( _townToCapture[1] ) == _mapTownInfos[i].color ) { initiallySelectedTownIndex = static_cast( i ); listbox.SetCurrent( initiallySelectedTownIndex ); break; } } if ( listbox.selectItemsEventProcessing() == Dialog::OK ) { const int townIndex = listbox.GetCurrent(); if ( townIndex != initiallySelectedTownIndex ) { _townToCapture[0] = static_cast( _mapTownInfos[townIndex].tileIndex ); _townToCapture[1] = static_cast( _mapTownInfos[townIndex].color ); } } return true; } if ( le.isMouseRightButtonPressedInArea( _selectConditionRoi ) ) { fheroes2::showStandardTextMessage( _( "Special Victory Condition" ), _( "Click here to change the town needed to capture to achieve victory." ), Dialog::ZERO ); return false; } if ( le.MouseClickLeft( _allowNormalVictoryRoi ) ) { _isNormalVictoryAllowed = !_isNormalVictoryAllowed; return true; } if ( le.MouseClickLeft( _allowVictoryConditionForAIRoi ) ) { _isVictoryConditionApplicableForAI = !_isVictoryConditionApplicableForAI; return true; } break; } case Maps::FileInfo::VICTORY_KILL_HERO: { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( _selectConditionRoi ) ) { assert( !_mapHeroInfos.empty() ); const int32_t maxHeight = std::min( 100 + SelectMapCastle::itemsOffsetY * 12, fheroes2::Display::instance().height() - 100 ); const int32_t itemsHeight = std::max( 100 + SelectMapCastle::itemsOffsetY * static_cast( _mapHeroInfos.size() ), 100 + SelectMapCastle::itemsOffsetY * 5 ); const int32_t totalHeight = std::min( itemsHeight, maxHeight ); SelectMapHero listbox( { 450, totalHeight }, _( "Select a Hero to defeat to achieve victory" ), {}, _mapWidth, _mapHeroInfos, _isEvilInterface ); std::vector heroIndicies( _mapHeroInfos.size() ); std::iota( heroIndicies.begin(), heroIndicies.end(), 0 ); listbox.SetListContent( heroIndicies ); int initiallySelectedHeroIndex = 0; for ( size_t i = 0; i < _mapHeroInfos.size(); ++i ) { if ( static_cast( _heroToKill[0] ) == _mapHeroInfos[i].tileIndex && static_cast( _heroToKill[1] ) == _mapHeroInfos[i].color ) { initiallySelectedHeroIndex = static_cast( i ); listbox.SetCurrent( initiallySelectedHeroIndex ); break; } } if ( listbox.selectItemsEventProcessing() == Dialog::OK ) { const int heroIndex = listbox.GetCurrent(); if ( heroIndex != initiallySelectedHeroIndex ) { _heroToKill[0] = static_cast( _mapHeroInfos[heroIndex].tileIndex ); _heroToKill[1] = static_cast( _mapHeroInfos[heroIndex].color ); } } return true; } if ( le.isMouseRightButtonPressedInArea( _selectConditionRoi ) ) { fheroes2::showStandardTextMessage( _( "Special Victory Condition" ), _( "Click here to change the hero needed to defeat to achieve victory." ), Dialog::ZERO ); return false; } break; } case Maps::FileInfo::VICTORY_OBTAIN_ARTIFACT: { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( _selectConditionRoi ) ) { const Artifact artifact = Dialog::selectArtifact( static_cast( _victoryArtifactId ), true ); if ( artifact.isValid() || artifact.GetID() == Artifact::EDITOR_ANY_ULTIMATE_ARTIFACT ) { _victoryArtifactId = artifact.GetID(); } return true; } if ( le.isMouseRightButtonPressedInArea( _selectConditionRoi ) ) { fheroes2::ArtifactDialogElement( Artifact( static_cast( _victoryArtifactId ) ) ).showPopup( Dialog::ZERO ); return false; } if ( le.MouseClickLeft( _allowNormalVictoryRoi ) ) { _isNormalVictoryAllowed = !_isNormalVictoryAllowed; return true; } break; } case Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE: { LocalEvent & le = LocalEvent::Get(); for ( size_t allianceNumber = 0; allianceNumber < _alliancesCheckboxes.size(); ++allianceNumber ) { for ( size_t playerNumber = 0; playerNumber < _alliancesCheckboxes[allianceNumber].size(); ++playerNumber ) { const fheroes2::Rect & checkboxRect = _alliancesCheckboxes[allianceNumber][playerNumber]->getRect(); // Allow to select player only if it is not already selected. if ( le.MouseClickLeft( checkboxRect ) ) { const uint8_t color = static_cast( _alliancesCheckboxes[allianceNumber][playerNumber]->getColor() ); // There can be a maximum of (active_players - 1) in one alliance to have at least one player in the other alliance. if ( ( ( _alliances[allianceNumber] & color ) == 0 ) && ( ( Color::Count( _availableColors ) - Color::Count( _alliances[allianceNumber] ) ) > 1 ) ) { for ( size_t i = 0; i < _alliancesCheckboxes.size(); ++i ) { if ( _alliancesCheckboxes[i][playerNumber]->toggle() ) { _alliances[i] |= color; } else { _alliances[i] ^= color; } } return true; } return false; } if ( le.isMouseRightButtonPressedInArea( checkboxRect ) ) { std::string header = _( "Put %{color} player in the %{alliance} alliance" ); std::string messageText = _( "If this checkbox is checked, the %{color} player will be in the %{alliance} alliance." ); const std::string colorString = Color::String( _alliancesCheckboxes[allianceNumber][playerNumber]->getColor() ); StringReplace( header, "%{color}", colorString ); StringReplace( header, "%{alliance}", getAllianceOrderText( allianceNumber ) ); StringReplace( messageText, "%{color}", colorString ); StringReplace( messageText, "%{alliance}", getAllianceOrderText( allianceNumber ) ); fheroes2::showStandardTextMessage( std::move( header ), std::move( messageText ), Dialog::ZERO ); return false; } } } break; } case Maps::FileInfo::VICTORY_COLLECT_ENOUGH_GOLD: { if ( _goldAccumulationValue.processEvents() ) { return true; } LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( _allowNormalVictoryRoi ) ) { _isNormalVictoryAllowed = !_isNormalVictoryAllowed; return true; } if ( le.MouseClickLeft( _allowVictoryConditionForAIRoi ) ) { _isVictoryConditionApplicableForAI = !_isVictoryConditionApplicableForAI; return true; } break; } default: // Did you add more conditions? Add the logic for them! assert( 0 ); break; } return false; } private: uint8_t _conditionType{ Maps::FileInfo::VICTORY_DEFEAT_EVERYONE }; const uint8_t _availableColors{ Color::NONE }; bool _isNormalVictoryAllowed{ false }; bool _isVictoryConditionApplicableForAI{ false }; const bool _isEvilInterface{ false }; uint32_t _victoryArtifactId{ ultimateArtifactId }; const int32_t _mapWidth{ 0 }; // Town or hero loss metadata include tile ID and color. std::array _heroToKill{ 0 }; std::array _townToCapture{ 0 }; std::vector _alliances; std::vector>> _alliancesCheckboxes; std::vector _mapTownInfos; std::vector _mapHeroInfos; fheroes2::ImageRestorer _restorer; fheroes2::ValueSelectionDialogElement _goldAccumulationValue{ 10000, 1000000, 10000, 1000, {} }; fheroes2::MovableSprite _allowNormalVictory; fheroes2::MovableSprite _allowVictoryConditionForAI; fheroes2::Rect _allowNormalVictoryRoi; fheroes2::Rect _allowVictoryConditionForAIRoi; fheroes2::Rect _selectConditionRoi; }; class LossConditionUI final { public: LossConditionUI( fheroes2::Image & output, const fheroes2::Rect & roi, const Maps::Map_Format::MapFormat & mapFormat, const bool isEvilInterface ) : _conditionType( mapFormat.lossConditionType ) , _isEvilInterface( isEvilInterface ) , _mapWidth( mapFormat.size ) , _restorer( output, roi.x, roi.y, roi.width, roi.height ) { switch ( _conditionType ) { case Maps::FileInfo::LOSS_EVERYTHING: // This condition has no metadata. break; case Maps::FileInfo::LOSS_TOWN: if ( mapFormat.lossConditionMetadata.size() == 2 ) { std::copy( mapFormat.lossConditionMetadata.begin(), mapFormat.lossConditionMetadata.end(), _townToLose.begin() ); // Verify that this is a valid human-only town. _mapTownInfos = getMapTowns( mapFormat, mapFormat.humanPlayerColors & ( ~mapFormat.computerPlayerColors ), true ); const int32_t townTileIndex = static_cast( _townToLose[0] ); bool townFound = false; for ( const auto & town : _mapTownInfos ) { if ( townTileIndex == town.tileIndex && static_cast( _townToLose[1] ) == town.color ) { townFound = true; break; } } if ( !townFound ) { _conditionType = Maps::FileInfo::LOSS_EVERYTHING; } } else { // Since the metadata is invalid we have 2 options: // - fall back to normal loss condition as no town was set // - generate a list of towns and pick one // For simplicity we are choosing the first option for now. _conditionType = Maps::FileInfo::LOSS_EVERYTHING; } break; case Maps::FileInfo::LOSS_HERO: if ( mapFormat.lossConditionMetadata.size() == 2 ) { std::copy( mapFormat.lossConditionMetadata.begin(), mapFormat.lossConditionMetadata.end(), _heroToLose.begin() ); // Verify that this is a valid human-only hero. _mapHeroInfos = getMapHeroes( mapFormat, mapFormat.humanPlayerColors & ( ~mapFormat.computerPlayerColors ) ); const int32_t heroTileIndex = static_cast( _heroToLose[0] ); bool heroFound = false; for ( const auto & hero : _mapHeroInfos ) { if ( heroTileIndex == hero.tileIndex && static_cast( _heroToLose[1] ) == hero.color ) { heroFound = true; break; } } if ( !heroFound ) { _conditionType = Maps::FileInfo::LOSS_EVERYTHING; } } else { // Since the metadata is invalid we have 2 options: // - fall back to normal loss condition as no hero was set // - generate a list of heroes and pick one // For simplicity we are choosing the first option for now. _conditionType = Maps::FileInfo::LOSS_EVERYTHING; } break; case Maps::FileInfo::LOSS_OUT_OF_TIME: if ( mapFormat.lossConditionMetadata.size() == 1 ) { _outOfTimeValue.setValue( static_cast( mapFormat.lossConditionMetadata[0] ) ); } break; default: // Did you add more conditions? Add the logic for them! assert( 0 ); break; } } void setConditionType( const uint8_t lossConditionType ) { _conditionType = lossConditionType; } bool updateCondition( Maps::Map_Format::MapFormat & mapFormat ) { switch ( _conditionType ) { case Maps::FileInfo::LOSS_TOWN: { _mapTownInfos = getMapTowns( mapFormat, mapFormat.humanPlayerColors & ( ~mapFormat.computerPlayerColors ), true ); if ( _mapTownInfos.empty() ) { // No towns exist for human-only players. _conditionType = Maps::FileInfo::LOSS_EVERYTHING; mapFormat.lossConditionType = _conditionType; return true; } const int32_t townTileIndex = static_cast( _townToLose[0] ); bool townFound = false; for ( const auto & town : _mapTownInfos ) { if ( townTileIndex == town.tileIndex && static_cast( _townToLose[1] ) == town.color ) { townFound = true; break; } } if ( !townFound ) { // The town doesn't exist in the list. Select the first one. _townToLose[0] = static_cast( _mapTownInfos[0].tileIndex ); _townToLose[1] = static_cast( _mapTownInfos[0].color ); return true; } break; } case Maps::FileInfo::LOSS_HERO: { _mapHeroInfos = getMapHeroes( mapFormat, mapFormat.humanPlayerColors & ( ~mapFormat.computerPlayerColors ) ); if ( _mapHeroInfos.empty() ) { // No heroes exist for human-only players. _conditionType = Maps::FileInfo::LOSS_EVERYTHING; mapFormat.lossConditionType = _conditionType; return true; } const int32_t heroTileIndex = static_cast( _heroToLose[0] ); bool heroFound = false; for ( const auto & hero : _mapHeroInfos ) { if ( heroTileIndex == hero.tileIndex && static_cast( _heroToLose[1] ) == hero.color ) { heroFound = true; break; } } if ( !heroFound ) { // The hero doesn't exist in the list. Select the first one. _heroToLose[0] = static_cast( _mapHeroInfos[0].tileIndex ); _heroToLose[1] = static_cast( _mapHeroInfos[0].color ); } return false; } default: // No changes for other loss conditions. break; } return false; } void getConditionMetadata( Maps::Map_Format::MapFormat & mapFormat ) const { assert( _conditionType == mapFormat.lossConditionType ); switch ( _conditionType ) { case Maps::FileInfo::LOSS_EVERYTHING: // This condition has no metadata. mapFormat.lossConditionMetadata.clear(); break; case Maps::FileInfo::LOSS_TOWN: if ( mapFormat.lossConditionMetadata.size() != 2 ) { mapFormat.lossConditionMetadata.resize( 2 ); } std::copy( _townToLose.begin(), _townToLose.end(), mapFormat.lossConditionMetadata.begin() ); return; case Maps::FileInfo::LOSS_HERO: if ( mapFormat.lossConditionMetadata.size() != 2 ) { mapFormat.lossConditionMetadata.resize( 2 ); } std::copy( _heroToLose.begin(), _heroToLose.end(), mapFormat.lossConditionMetadata.begin() ); return; case Maps::FileInfo::LOSS_OUT_OF_TIME: if ( mapFormat.lossConditionMetadata.size() != 1 ) { mapFormat.lossConditionMetadata.resize( 1 ); } mapFormat.lossConditionMetadata[0] = static_cast( _outOfTimeValue.getValue() ); break; default: // Did you add more conditions? Add the logic for them! assert( 0 ); // Reset the unknown condition to the default condition type. mapFormat.lossConditionType = Maps::FileInfo::LOSS_EVERYTHING; break; } } void render( fheroes2::Image & output, const bool renderEverything ) { // Restore background to make sure that other UI elements aren't being rendered. _restorer.restore(); switch ( _conditionType ) { case Maps::FileInfo::LOSS_EVERYTHING: // No special UI is needed. break; case Maps::FileInfo::LOSS_TOWN: { if ( !renderEverything ) { // To render this condition we always redraw the whole conditions UI. // TODO: optimize the rendering. _restorer.restore(); } assert( !_mapTownInfos.empty() ); size_t selectedTownIndex = 0; for ( size_t i = 0; i < _mapTownInfos.size(); ++i ) { if ( static_cast( _townToLose[0] ) == _mapTownInfos[i].tileIndex && static_cast( _townToLose[1] ) == _mapTownInfos[i].color ) { selectedTownIndex = i; break; } } const auto & townInfo = _mapTownInfos[selectedTownIndex]; const auto * castleMetadata = townInfo.castleMetadata; const int townIcnId = _isEvilInterface ? ICN::LOCATORE : ICN::LOCATORS; const bool isTown = std::find( castleMetadata->builtBuildings.begin(), castleMetadata->builtBuildings.end(), BUILD_CASTLE ) == castleMetadata->builtBuildings.end(); const fheroes2::Sprite townIcon( getTownIcon( isTown, townInfo.race, townInfo.color, townIcnId ) ); const fheroes2::Rect roi{ _restorer.rect() }; fheroes2::Blit( townIcon, output, roi.x, roi.y + 4 ); fheroes2::Text text( getTownTitle( castleMetadata->customName, townInfo.race, isTown, townInfo.tileIndex, _mapWidth ), fheroes2::FontType::normalWhite() ); text.fitToOneRow( roi.width - townIcon.width() - 5 ); text.draw( roi.x + townIcon.width() + 5, roi.y + 12, output ); _selectConditionRoi = { roi.x, roi.y + 4, townIcon.width() + 5 + text.width(), townIcon.height() }; break; } case Maps::FileInfo::LOSS_HERO: { if ( !renderEverything ) { // To render this condition we always redraw the whole conditions UI. // TODO: optimize the rendering. _restorer.restore(); } const fheroes2::Rect roi{ _restorer.rect() }; const fheroes2::Sprite & heroFrame = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); const int32_t heroFrameWidth = 111; const int32_t heroFrameHeight = 105; _selectConditionRoi = { roi.x + ( roi.width - heroFrameWidth ) / 2, roi.y + 4, heroFrameWidth, heroFrameHeight }; fheroes2::Blit( heroFrame, 88, 66, output, _selectConditionRoi.x, _selectConditionRoi.y, heroFrameWidth, heroFrameHeight ); assert( !_mapHeroInfos.empty() ); size_t selectedHeroIndex = 0; for ( size_t i = 0; i < _mapHeroInfos.size(); ++i ) { if ( static_cast( _heroToLose[0] ) == _mapHeroInfos[i].tileIndex && static_cast( _heroToLose[1] ) == _mapHeroInfos[i].color ) { selectedHeroIndex = i; break; } } // To render hero icons we use castle flags and frame. const uint32_t flagIcnIndex = fheroes2::getCastleLeftFlagIcnIndex( static_cast( _heroToLose[1] ) ); const fheroes2::Sprite & castleLeftFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex ); const fheroes2::Sprite & castleRightFlag = fheroes2::AGG::GetICN( ICN::FLAG32, flagIcnIndex + 1 ); Blit( castleLeftFlag, 0, 0, output, _selectConditionRoi.x - 21, _selectConditionRoi.y + 45, castleLeftFlag.width(), castleLeftFlag.height() ); Blit( castleRightFlag, 0, 0, output, _selectConditionRoi.x + _selectConditionRoi.width + 2, _selectConditionRoi.y + 45, castleRightFlag.width(), castleRightFlag.height() ); const auto * heroMetadata = _mapHeroInfos[selectedHeroIndex].heroMetadata; const int32_t heroPortraitId = heroMetadata->customPortrait; if ( heroPortraitId > 0 ) { const fheroes2::Sprite & heroPortrait = fheroes2::AGG::GetICN( ICN::getHeroPortraitIcnId( heroPortraitId ), 0 ); fheroes2::Copy( heroPortrait, 0, 0, output, _selectConditionRoi.x + 5, _selectConditionRoi.y + 6, heroPortrait.width(), heroPortrait.height() ); } else { fheroes2::renderHeroRacePortrait( heroMetadata->race, { _selectConditionRoi.x + 5, _selectConditionRoi.y + 6, 101, 93 }, output ); } fheroes2::Text extraText( getHeroTitle( heroMetadata->customName, heroMetadata->race, static_cast( _heroToLose[0] ), _mapWidth ), fheroes2::FontType::normalWhite() ); extraText.fitToOneRow( roi.width ); extraText.drawInRoi( roi.x, _selectConditionRoi.y + _selectConditionRoi.height + 5, roi.width, output, roi ); break; } case Maps::FileInfo::LOSS_OUT_OF_TIME: { const fheroes2::Rect roi = _restorer.rect(); const fheroes2::Point uiOffset{ roi.x + ( roi.width - fheroes2::ValueSelectionDialogElement::getArea().width ) / 2, roi.y }; _outOfTimeValue.setOffset( uiOffset ); _outOfTimeValue.draw( output ); fheroes2::Text text( _( "Days:" ), fheroes2::FontType::normalWhite() ); text.draw( uiOffset.x - text.width() - 5, roi.y + ( fheroes2::ValueSelectionDialogElement::getArea().height - text.height() ) / 2 + 2, output ); const int32_t offsetY = roi.y + fheroes2::ValueSelectionDialogElement::getArea().height + 14; text.set( Editor::getDateDescription( _outOfTimeValue.getValue() ), fheroes2::FontType::normalWhite() ); text.draw( roi.x, offsetY, roi.width, output ); break; } default: // Did you add more conditions? Add the logic for them! assert( 0 ); break; } } // Returns true if rendering is required. bool processEvents() { switch ( _conditionType ) { case Maps::FileInfo::LOSS_EVERYTHING: // No events to process. return false; case Maps::FileInfo::LOSS_TOWN: { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( _selectConditionRoi ) ) { assert( !_mapTownInfos.empty() ); const int32_t maxHeight = std::min( 100 + SelectMapCastle::itemsOffsetY * 12, fheroes2::Display::instance().height() - 100 ); const int32_t itemsHeight = std::max( 100 + SelectMapCastle::itemsOffsetY * static_cast( _mapTownInfos.size() ), 100 + SelectMapCastle::itemsOffsetY * 5 ); const int32_t totalHeight = std::min( itemsHeight, maxHeight ); SelectMapCastle listbox( { 450, totalHeight }, _( "Select a Town to lose to suffer defeat" ), {}, _mapWidth, _mapTownInfos, _isEvilInterface ); std::vector townIndicies( _mapTownInfos.size() ); std::iota( townIndicies.begin(), townIndicies.end(), 0 ); listbox.SetListContent( townIndicies ); int initiallySelectedTownIndex = 0; for ( size_t i = 0; i < _mapTownInfos.size(); ++i ) { if ( static_cast( _townToLose[0] ) == _mapTownInfos[i].tileIndex && static_cast( _townToLose[1] ) == _mapTownInfos[i].color ) { initiallySelectedTownIndex = static_cast( i ); listbox.SetCurrent( initiallySelectedTownIndex ); break; } } const int32_t result = listbox.selectItemsEventProcessing(); if ( result == Dialog::OK ) { const int townIndex = listbox.GetCurrent(); if ( townIndex != initiallySelectedTownIndex ) { _townToLose[0] = static_cast( _mapTownInfos[townIndex].tileIndex ); _townToLose[1] = static_cast( _mapTownInfos[townIndex].color ); } } return true; } if ( le.isMouseRightButtonPressedInArea( _selectConditionRoi ) ) { fheroes2::showStandardTextMessage( _( "Special Loss Condition" ), _( "Click here to change the town whose loss would mean defeat." ), Dialog::ZERO ); return false; } break; } case Maps::FileInfo::LOSS_HERO: { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( _selectConditionRoi ) ) { assert( !_mapHeroInfos.empty() ); const int32_t maxHeight = std::min( 100 + SelectMapCastle::itemsOffsetY * 12, fheroes2::Display::instance().height() - 100 ); const int32_t itemsHeight = std::max( 100 + SelectMapCastle::itemsOffsetY * static_cast( _mapHeroInfos.size() ), 100 + SelectMapCastle::itemsOffsetY * 5 ); const int32_t totalHeight = std::min( itemsHeight, maxHeight ); SelectMapHero listbox( { 450, totalHeight }, _( "Select a Hero to lose to suffer defeat" ), {}, _mapWidth, _mapHeroInfos, _isEvilInterface ); std::vector heroIndicies( _mapHeroInfos.size() ); std::iota( heroIndicies.begin(), heroIndicies.end(), 0 ); listbox.SetListContent( heroIndicies ); int initiallySelectedHeroIndex = 0; for ( size_t i = 0; i < _mapHeroInfos.size(); ++i ) { if ( static_cast( _heroToLose[0] ) == _mapHeroInfos[i].tileIndex && static_cast( _heroToLose[1] ) == _mapHeroInfos[i].color ) { initiallySelectedHeroIndex = static_cast( i ); listbox.SetCurrent( initiallySelectedHeroIndex ); break; } } const int32_t result = listbox.selectItemsEventProcessing(); if ( result == Dialog::OK ) { const int heroIndex = listbox.GetCurrent(); if ( heroIndex != initiallySelectedHeroIndex ) { _heroToLose[0] = static_cast( _mapHeroInfos[heroIndex].tileIndex ); _heroToLose[1] = static_cast( _mapHeroInfos[heroIndex].color ); } } return true; } if ( le.isMouseRightButtonPressedInArea( _selectConditionRoi ) ) { fheroes2::showStandardTextMessage( _( "Special Loss Condition" ), _( "Click here to change the hero whose loss would mean defeat." ), Dialog::ZERO ); return false; } break; } case Maps::FileInfo::LOSS_OUT_OF_TIME: return _outOfTimeValue.processEvents(); default: // Did you add more conditions? Add the logic for them! assert( 0 ); break; } return false; } private: uint8_t _conditionType{ Maps::FileInfo::LOSS_EVERYTHING }; const bool _isEvilInterface{ false }; const int32_t _mapWidth{ 0 }; std::array _heroToLose{ 0 }; std::array _townToLose{ 0 }; std::vector _mapTownInfos; std::vector _mapHeroInfos; fheroes2::ImageRestorer _restorer; fheroes2::ValueSelectionDialogElement _outOfTimeValue{ 1, 10 * daysInYear, daysInMonth, 1, {} }; fheroes2::Rect _selectConditionRoi; }; uint8_t showWinLoseList( const Maps::Map_Format::MapFormat & mapFormat, const fheroes2::Point & offset, const uint8_t selectedCondition, const bool isLossList, const int dropBoxIcn ) { std::vector conditions = isLossList ? supportedLossConditions : supportedVictoryConditions; assert( std::find( conditions.begin(), conditions.end(), selectedCondition ) != conditions.end() ); if ( isLossList ) { // Remove the conditions that have no selection among objects. if ( getMapHeroes( mapFormat, mapFormat.humanPlayerColors & ( ~mapFormat.computerPlayerColors ) ).empty() ) { conditions.erase( std::remove_if( conditions.begin(), conditions.end(), []( const uint8_t condition ) { return condition == Maps::FileInfo::LOSS_HERO; } ), conditions.end() ); } if ( getMapTowns( mapFormat, mapFormat.humanPlayerColors & ( ~mapFormat.computerPlayerColors ), true ).empty() ) { conditions.erase( std::remove_if( conditions.begin(), conditions.end(), []( const uint8_t condition ) { return condition == Maps::FileInfo::LOSS_TOWN; } ), conditions.end() ); } } else { // Remove the conditions that have no selection among objects. if ( getMapHeroes( mapFormat, mapFormat.computerPlayerColors & ( ~mapFormat.humanPlayerColors ) ).empty() ) { conditions.erase( std::remove_if( conditions.begin(), conditions.end(), []( const uint8_t condition ) { return condition == Maps::FileInfo::VICTORY_KILL_HERO; } ), conditions.end() ); } if ( getMapTowns( mapFormat, mapFormat.computerPlayerColors & ( ~mapFormat.humanPlayerColors ), false ).empty() ) { conditions.erase( std::remove_if( conditions.begin(), conditions.end(), []( const uint8_t condition ) { return condition == Maps::FileInfo::VICTORY_CAPTURE_TOWN; } ), conditions.end() ); } // Alliances can be formed for a minimum of three players: two on the one side and one on the other. if ( Color::Count( mapFormat.availablePlayerColors ) < 3 ) { conditions.erase( std::remove_if( conditions.begin(), conditions.end(), []( const uint8_t condition ) { return condition == Maps::FileInfo::VICTORY_DEFEAT_OTHER_SIDE; } ), conditions.end() ); } } DropBoxList conditionList( offset, static_cast( conditions.size() ), isLossList, dropBoxIcn ); conditionList.SetListContent( conditions ); conditionList.SetCurrent( selectedCondition ); conditionList.Redraw(); const fheroes2::Rect listArea( conditionList.getArea() ); fheroes2::Display & display = fheroes2::Display::instance(); display.render( listArea ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { conditionList.QueueEventProcessing(); if ( conditionList.isClicked() || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) { assert( conditionList.IsValid() ); return conditionList.GetCurrent(); } if ( le.MouseClickLeft() || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { break; } if ( conditionList.IsNeedRedraw() ) { conditionList.Redraw(); display.render( listArea ); } } return selectedCondition; } uint32_t getPlayerIcnIndex( const Maps::Map_Format::MapFormat & mapFormat, const int currentColor ) { if ( !( mapFormat.availablePlayerColors & currentColor ) ) { // This player is not available. assert( 0 ); return 70; } if ( mapFormat.humanPlayerColors & currentColor ) { if ( mapFormat.computerPlayerColors & currentColor ) { // Both AI and human can choose this player color. return 82; } // Human only. return 9; } if ( mapFormat.computerPlayerColors & currentColor ) { // AI only. return 3; } // It is not possible to have available player which is not allowed to be controlled by AI or human. assert( 0 ); return 70; } size_t getDifficultyIndex( const uint8_t difficulty ) { switch ( difficulty ) { case Difficulty::EASY: return 0; case Difficulty::NORMAL: return 1; case Difficulty::HARD: return 2; case Difficulty::EXPERT: return 3; default: // Did you add a new difficulty mode? Add the corresponding case above! assert( 0 ); break; } return 0; } uint8_t setDifficultyByIndex( const size_t difficultyIndex ) { switch ( difficultyIndex ) { case 0: return Difficulty::EASY; case 1: return Difficulty::NORMAL; case 2: return Difficulty::HARD; case 3: return Difficulty::EXPERT; default: // Did you add a new difficulty mode? Add the corresponding case above! assert( 0 ); break; } return Difficulty::EASY; } } namespace Editor { bool mapSpecificationsDialog( Maps::Map_Format::MapFormat & mapFormat, const int32_t maxMapNameLength ) { // Verify victory and loss condition types. if ( std::find( supportedVictoryConditions.begin(), supportedVictoryConditions.end(), mapFormat.victoryConditionType ) == supportedVictoryConditions.end() ) { assert( 0 ); mapFormat.victoryConditionType = Maps::FileInfo::VICTORY_DEFEAT_EVERYONE; } if ( std::find( supportedLossConditions.begin(), supportedLossConditions.end(), mapFormat.lossConditionType ) == supportedLossConditions.end() ) { assert( 0 ); mapFormat.lossConditionType = Maps::FileInfo::LOSS_EVERYTHING; } const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const bool isDefaultScreenSize = display.isDefaultSize(); fheroes2::StandardWindow background( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, !isDefaultScreenSize ); const fheroes2::Rect activeArea( background.activeArea() ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); if ( isDefaultScreenSize ) { const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ); fheroes2::Copy( backgroundImage, 0, 0, display, activeArea ); } if ( mapFormat.name.empty() ) { mapFormat.name = "My Map"; } // Map name. const fheroes2::Sprite & scenarioBox = fheroes2::AGG::GetICN( isEvilInterface ? ICN::METALLIC_BORDERED_TEXTBOX_EVIL : ICN::METALLIC_BORDERED_TEXTBOX_GOOD, 0 ); const fheroes2::Rect scenarioBoxRoi( activeArea.x + ( activeArea.width - scenarioBox.width() ) / 2, activeArea.y + 10, scenarioBox.width(), scenarioBox.height() ); const fheroes2::Rect mapNameRoi( scenarioBoxRoi.x + 6, scenarioBoxRoi.y + 5, scenarioBoxRoi.width - 12, scenarioBoxRoi.height - 11 ); fheroes2::Copy( scenarioBox, 0, 0, display, scenarioBoxRoi ); fheroes2::addGradientShadow( scenarioBox, display, scenarioBoxRoi.getPosition(), { -5, 5 } ); fheroes2::Text text( mapFormat.name, fheroes2::FontType::normalWhite(), mapFormat.mainLanguage ); text.fitToOneRow( mapNameRoi.width ); text.drawInRoi( mapNameRoi.x, mapNameRoi.y + 3, mapNameRoi.width, display, mapNameRoi ); // Players setting (AI or human). const int32_t availablePlayersCount = Color::Count( mapFormat.availablePlayerColors ); int32_t offsetX = activeArea.x + ( activeArea.width - availablePlayersCount * playerStepX ) / 2; int32_t offsetY = scenarioBoxRoi.y + scenarioBoxRoi.height + 10; std::vector playerRects( availablePlayersCount ); const Colors availableColors( mapFormat.availablePlayerColors ); const fheroes2::Sprite & playerIconShadow = fheroes2::AGG::GetICN( ICN::NGEXTRA, 61 ); for ( int32_t i = 0; i < availablePlayersCount; ++i ) { playerRects[i].x = offsetX + i * playerStepX; playerRects[i].y = offsetY; fheroes2::Blit( playerIconShadow, display, playerRects[i].x - 5, playerRects[i].y + 3 ); const uint32_t icnIndex = Color::GetIndex( availableColors[i] ) + getPlayerIcnIndex( mapFormat, availableColors[i] ); const fheroes2::Sprite & playerIcon = fheroes2::AGG::GetICN( ICN::NGEXTRA, icnIndex ); playerRects[i].width = playerIcon.width(); playerRects[i].height = playerIcon.height(); fheroes2::Copy( playerIcon, 0, 0, display, playerRects[i].x, playerRects[i].y, playerRects[i].width, playerRects[i].height ); } // Draw difficulty icons. offsetX = activeArea.x + 15; offsetY = scenarioBoxRoi.y + scenarioBoxRoi.height + 65; text.set( _( "Map Difficulty" ), fheroes2::FontType::normalWhite() ); text.draw( offsetX + ( difficultyStepX * 4 - text.width() ) / 2, scenarioBoxRoi.y + scenarioBoxRoi.height + 65, display ); std::array difficultyRects; offsetY += 23; const fheroes2::Sprite & difficultyCursorSprite = fheroes2::AGG::GetICN( ICN::NGEXTRA, 62 ); const int32_t difficultyIconSideLength = difficultyCursorSprite.width(); const int difficultyIcnIndex = isEvilInterface ? 1 : 0; for ( int i = 0; i < 4; ++i ) { difficultyRects[i].x = offsetX + difficultyStepX * i; difficultyRects[i].y = offsetY; difficultyRects[i].width = difficultyIconSideLength; difficultyRects[i].height = difficultyIconSideLength; const fheroes2::Sprite & icon = fheroes2::AGG::GetICN( ICN::DIFFICULTY_ICON_EASY + i, difficultyIcnIndex ); fheroes2::Copy( icon, 0, 0, display, difficultyRects[i] ); fheroes2::addGradientShadow( icon, display, { difficultyRects[i].x, difficultyRects[i].y }, { -5, 5 } ); difficultyRects[i].x -= 3; difficultyRects[i].y -= 3; text.set( Difficulty::String( setDifficultyByIndex( i ) ), fheroes2::FontType::smallWhite() ); text.draw( difficultyRects[i].x + ( difficultyRects[i].width - text.width() ) / 2, difficultyRects[i].y + difficultyRects[i].height + 7, display ); } fheroes2::MovableSprite difficultyCursor( difficultyCursorSprite ); size_t difficultyIndex = getDifficultyIndex( mapFormat.difficulty ); difficultyCursor.setPosition( difficultyRects[difficultyIndex].x, difficultyRects[difficultyIndex].y ); difficultyCursor.redraw(); // Map description. offsetX = activeArea.x + activeArea.width - descriptionBoxWidth - 15; offsetY -= 23; text.set( _( "Map Description" ), fheroes2::FontType::normalWhite() ); text.draw( offsetX + ( descriptionBoxWidth - text.width() ) / 2, offsetY, display ); offsetY += 25; const fheroes2::Rect descriptionTextRoi( offsetX, offsetY, descriptionBoxWidth, descriptionBoxHeight ); background.applyTextBackgroundShading( { descriptionTextRoi.x - 6, descriptionTextRoi.y - 6, descriptionTextRoi.width + 12, descriptionTextRoi.height + 12 } ); fheroes2::ImageRestorer descriptionBackground( display, descriptionTextRoi.x, descriptionTextRoi.y, descriptionTextRoi.width, descriptionTextRoi.height ); text.set( mapFormat.description, fheroes2::FontType::normalWhite(), mapFormat.mainLanguage ); text.drawInRoi( descriptionTextRoi.x, descriptionTextRoi.y, descriptionTextRoi.width, display, descriptionTextRoi ); // Victory conditions. offsetY += descriptionTextRoi.height + 20; text.set( _( "Special Victory Condition" ), fheroes2::FontType::normalWhite() ); text.draw( activeArea.x + activeArea.width / 4 - text.width() / 2, offsetY, display ); offsetY += 20; const int dropListIcn = isEvilInterface ? ICN::DROPLISL_EVIL : ICN::DROPLISL; const fheroes2::Sprite & itemBackground = fheroes2::AGG::GetICN( dropListIcn, 0 ); const int32_t itemBackgroundWidth = itemBackground.width(); const int32_t itemBackgroundHeight = itemBackground.height(); const int32_t itemBackgroundOffsetX = activeArea.width / 4 - itemBackgroundWidth / 2 - 11; offsetX = activeArea.x + itemBackgroundOffsetX; fheroes2::Copy( itemBackground, 0, 0, display, offsetX, offsetY, itemBackgroundWidth, itemBackgroundHeight ); const fheroes2::Rect victoryTextRoi( offsetX + 2, offsetY + 3, itemBackgroundWidth - 4, itemBackgroundHeight - 5 ); redrawVictoryCondition( mapFormat.victoryConditionType, victoryTextRoi, false, display ); const fheroes2::Sprite & dropListButtonSprite = fheroes2::AGG::GetICN( dropListIcn, 1 ); const fheroes2::Sprite & dropListButtonPressedSprite = fheroes2::AGG::GetICN( dropListIcn, 2 ); fheroes2::ButtonSprite victoryDroplistButton( offsetX + itemBackgroundWidth, offsetY, dropListButtonSprite, dropListButtonPressedSprite ); const fheroes2::Rect victoryDroplistButtonRoi( fheroes2::getBoundaryRect( victoryDroplistButton.area(), victoryTextRoi ) ); victoryDroplistButton.draw(); offsetY += 30; const fheroes2::Rect victoryConditionUIRoi{ offsetX, offsetY, victoryDroplistButtonRoi.width, 150 }; VictoryConditionUI victoryConditionUI( display, victoryConditionUIRoi, mapFormat, isEvilInterface ); victoryConditionUI.render( display, true ); // Loss conditions. offsetY = descriptionTextRoi.y + descriptionTextRoi.height + 20; text.set( _( "Special Loss Condition" ), fheroes2::FontType::normalWhite() ); text.draw( activeArea.x + 3 * activeArea.width / 4 - text.width() / 2, offsetY, display ); offsetY += 20; offsetX = activeArea.x + activeArea.width / 2 + itemBackgroundOffsetX; fheroes2::Copy( itemBackground, 0, 0, display, offsetX, offsetY, itemBackgroundWidth, itemBackground.height() ); const fheroes2::Rect lossTextRoi( offsetX + 2, offsetY + 3, victoryTextRoi.width, victoryTextRoi.height ); redrawLossCondition( mapFormat.lossConditionType, lossTextRoi, false, display ); fheroes2::ButtonSprite lossDroplistButton( offsetX + itemBackgroundWidth, offsetY, dropListButtonSprite, dropListButtonPressedSprite ); const fheroes2::Rect lossDroplistButtonRoi( fheroes2::getBoundaryRect( lossDroplistButton.area(), lossTextRoi ) ); lossDroplistButton.draw(); offsetY += 30; const fheroes2::Rect lossConditionUIRoi{ offsetX, offsetY, lossDroplistButtonRoi.width, 150 }; LossConditionUI lossConditionUI( display, lossConditionUIRoi, mapFormat, isEvilInterface ); lossConditionUI.render( display, true ); // Buttons. fheroes2::Button buttonCancel; const int buttonCancelIcn = isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD; background.renderButton( buttonCancel, buttonCancelIcn, 0, 1, { 20, 6 }, fheroes2::StandardWindow::Padding::BOTTOM_RIGHT ); fheroes2::Button buttonOk; const int buttonOkIcn = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcn, 0, 1, { 20 + buttonCancel.area().width + 10, 6 }, fheroes2::StandardWindow::Padding::BOTTOM_RIGHT ); fheroes2::Button buttonRumors; const int buttonRumorsIcn = isEvilInterface ? ICN::BUTTON_RUMORS_EVIL : ICN::BUTTON_RUMORS_GOOD; background.renderButton( buttonRumors, buttonRumorsIcn, 0, 1, { 20, 6 }, fheroes2::StandardWindow::Padding::BOTTOM_LEFT ); fheroes2::Button buttonEvents; const int buttonEventsIcn = isEvilInterface ? ICN::BUTTON_EVENTS_EVIL : ICN::BUTTON_EVENTS_GOOD; background.renderButton( buttonEvents, buttonEventsIcn, 0, 1, { 20 + buttonRumors.area().width + 10, 6 }, fheroes2::StandardWindow::Padding::BOTTOM_LEFT ); fheroes2::Button buttonLanguage; const int buttonLanguageIcn = isEvilInterface ? ICN::BUTTON_LANGUAGE_EVIL : ICN::BUTTON_LANGUAGE_GOOD; background.renderButton( buttonLanguage, buttonLanguageIcn, 0, 1, { 20 + buttonRumors.area().width + buttonEvents.area().width + 2 * 10, 6 }, fheroes2::StandardWindow::Padding::BOTTOM_LEFT ); auto renderMapName = [&text, &mapFormat, &display, &scenarioBox, &mapNameRoi, &scenarioBoxRoi]() { text.set( mapFormat.name, fheroes2::FontType::normalWhite(), mapFormat.mainLanguage ); fheroes2::Copy( scenarioBox, 0, 0, display, scenarioBoxRoi ); text.fitToOneRow( mapNameRoi.width ); text.drawInRoi( mapNameRoi.x, mapNameRoi.y + 3, mapNameRoi.width, display, mapNameRoi ); }; auto renderMapDescription = [&text, &mapFormat, &display, &descriptionTextRoi, &descriptionBackground]() { text.set( mapFormat.description, fheroes2::FontType::normalWhite(), mapFormat.mainLanguage ); // TODO: Remove this temporary fix when direct text edit with text length checks is implemented. if ( text.rows( descriptionTextRoi.width ) > 5 ) { fheroes2::showStandardTextMessage( _( "Warning" ), _( "The entered map description exceeds the maximum allowed 5 rows. It will be shortened to fit the map description field." ), Dialog::OK ); // As a temporary solution we cut the end of the text to fit 5 rows. while ( text.rows( descriptionTextRoi.width ) > 5 ) { mapFormat.description.pop_back(); text.set( mapFormat.description, fheroes2::FontType::normalWhite(), mapFormat.mainLanguage ); } } descriptionBackground.restore(); text.drawInRoi( descriptionTextRoi.x, descriptionTextRoi.y, descriptionTextRoi.width, display, descriptionTextRoi ); }; LocalEvent & le = LocalEvent::Get(); display.render( background.totalArea() ); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonRumors.drawOnState( le.isMouseLeftButtonPressedInArea( buttonRumors.area() ) ); buttonEvents.drawOnState( le.isMouseLeftButtonPressedInArea( buttonEvents.area() ) ); buttonLanguage.drawOnState( le.isMouseLeftButtonPressedInArea( buttonLanguage.area() ) ); victoryDroplistButton.drawOnState( le.isMouseLeftButtonPressedInArea( victoryDroplistButtonRoi ) ); lossDroplistButton.drawOnState( le.isMouseLeftButtonPressedInArea( lossDroplistButtonRoi ) ); if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return false; } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( buttonOk.area() ) ) { break; } if ( victoryConditionUI.processEvents() ) { victoryConditionUI.render( display, false ); display.render( victoryConditionUIRoi ); } else if ( lossConditionUI.processEvents() ) { lossConditionUI.render( display, false ); display.render( lossConditionUIRoi ); } else if ( le.MouseClickLeft( buttonRumors.area() ) ) { auto temp = mapFormat.rumors; if ( openRumorWindow( temp, mapFormat.mainLanguage ) ) { mapFormat.rumors = std::move( temp ); } display.render( background.totalArea() ); } else if ( le.MouseClickLeft( buttonEvents.area() ) ) { auto temp = mapFormat.dailyEvents; if ( openDailyEventsWindow( temp, mapFormat.humanPlayerColors, mapFormat.computerPlayerColors, mapFormat.mainLanguage ) ) { mapFormat.dailyEvents = std::move( temp ); } display.render( background.totalArea() ); } else if ( le.MouseClickLeft( buttonLanguage.area() ) ) { const std::vector supportedLanguages = fheroes2::getSupportedLanguages(); const fheroes2::SupportedLanguage language = fheroes2::selectLanguage( supportedLanguages, mapFormat.mainLanguage, false ); if ( language != mapFormat.mainLanguage ) { std::string differentLanguageWarning = _( "You are about to change the map's language from %{oldLanguage} to %{newLanguage}. " "Some texts might not be displayed properly after this. Do you want to proceed?" ); StringReplace( differentLanguageWarning, "%{oldLanguage}", fheroes2::getLanguageName( mapFormat.mainLanguage ) ); StringReplace( differentLanguageWarning, "%{newLanguage}", fheroes2::getLanguageName( language ) ); if ( fheroes2::showStandardTextMessage( _( "Warning" ), differentLanguageWarning, Dialog::YES | Dialog::NO ) == Dialog::YES ) { mapFormat.mainLanguage = language; renderMapName(); renderMapDescription(); display.render( fheroes2::getBoundaryRect( scenarioBoxRoi, descriptionTextRoi ) ); } } } else if ( le.MouseClickLeft( mapNameRoi ) ) { // TODO: Edit texts directly in this dialog. std::string editableMapName = mapFormat.name; const fheroes2::Text body{ _( "Change Map Name" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, editableMapName, maxMapNameLength, false, mapFormat.mainLanguage ) ) { mapFormat.name = std::move( editableMapName ); renderMapName(); display.render( scenarioBoxRoi ); } } else if ( le.MouseClickLeft( descriptionTextRoi ) ) { // TODO: Edit texts directly in this dialog. // TODO: Limit description to 5 text lines. std::string descripton = mapFormat.description; const fheroes2::Text body{ _( "Change Map Description" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, descripton, 150, true, mapFormat.mainLanguage ) ) { mapFormat.description = std::move( descripton ); renderMapDescription(); display.render( descriptionTextRoi ); } } else if ( le.MouseClickLeft( victoryDroplistButtonRoi ) ) { const uint8_t result = showWinLoseList( mapFormat, { victoryTextRoi.x - 2, victoryTextRoi.y + victoryTextRoi.height }, mapFormat.victoryConditionType, false, dropListIcn ); if ( result != mapFormat.victoryConditionType ) { mapFormat.victoryConditionType = result; victoryConditionUI.setConditionType( mapFormat.victoryConditionType ); victoryConditionUI.updateCondition( mapFormat ); victoryConditionUI.render( display, true ); fheroes2::Copy( itemBackground, 2, 3, display, victoryTextRoi ); redrawVictoryCondition( mapFormat.victoryConditionType, victoryTextRoi, false, display ); } display.render( fheroes2::getBoundaryRect( victoryTextRoi, victoryConditionUIRoi ) ); } else if ( le.MouseClickLeft( lossDroplistButtonRoi ) ) { const uint8_t result = showWinLoseList( mapFormat, { lossTextRoi.x - 2, lossTextRoi.y + lossTextRoi.height }, mapFormat.lossConditionType, true, dropListIcn ); if ( result != mapFormat.lossConditionType ) { mapFormat.lossConditionType = result; lossConditionUI.setConditionType( mapFormat.lossConditionType ); lossConditionUI.updateCondition( mapFormat ); lossConditionUI.render( display, true ); fheroes2::Copy( itemBackground, 2, 3, display, lossTextRoi ); redrawLossCondition( mapFormat.lossConditionType, lossTextRoi, false, display ); } display.render( fheroes2::getBoundaryRect( lossTextRoi, lossConditionUIRoi ) ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to accept the changes made." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonRumors.area() ) ) { fheroes2::showStandardTextMessage( _( "Rumors" ), _( "Click to edit custom rumors." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonEvents.area() ) ) { fheroes2::showStandardTextMessage( _( "Events" ), _( "Click to edit daily events." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonLanguage.area() ) ) { fheroes2::showStandardTextMessage( _( "Language" ), _( "Click to change the language of the map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( mapNameRoi ) ) { fheroes2::MultiFontText message; message.add( fheroes2::Text{ "\"", fheroes2::FontType::normalWhite() } ); message.add( fheroes2::Text{ mapFormat.name, fheroes2::FontType::normalWhite(), mapFormat.mainLanguage } ); message.add( fheroes2::Text{ "\"\n\n", fheroes2::FontType::normalWhite() } ); message.add( fheroes2::Text{ _( "Click to change your map name." ), fheroes2::FontType::normalWhite() } ); fheroes2::showMessage( fheroes2::Text{ _( "Map Name" ), fheroes2::FontType::normalYellow() }, message, Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( descriptionTextRoi ) ) { fheroes2::showStandardTextMessage( _( "Map Description" ), _( "Click to change the description of the current map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( victoryDroplistButtonRoi ) ) { fheroes2::showStandardTextMessage( _( "Special Victory Condition" ), _( "Click to change the victory condition of the current map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( lossDroplistButtonRoi ) ) { fheroes2::showStandardTextMessage( _( "Special Loss Condition" ), _( "Click to change the loss condition of the current map." ), Dialog::ZERO ); } for ( int32_t i = 0; i < availablePlayersCount; ++i ) { if ( le.MouseClickLeft( playerRects[i] ) ) { if ( !( mapFormat.availablePlayerColors & availableColors[i] ) ) { break; } const bool allowAi = mapFormat.computerPlayerColors & availableColors[i]; const bool allowHuman = mapFormat.humanPlayerColors & availableColors[i]; if ( allowHuman ) { if ( allowAi ) { // Disable AI. mapFormat.computerPlayerColors ^= availableColors[i]; } else { // Enable AI. mapFormat.computerPlayerColors |= availableColors[i]; if ( Color::Count( mapFormat.humanPlayerColors ) > 1 ) { // and disable human only if any other player can be controlled by human. mapFormat.humanPlayerColors ^= availableColors[i]; } } } else { // Enable human. mapFormat.humanPlayerColors |= availableColors[i]; } fheroes2::Rect renderRoi; if ( victoryConditionUI.updateCondition( mapFormat ) ) { victoryConditionUI.render( display, true ); fheroes2::Copy( itemBackground, 2, 3, display, victoryTextRoi ); redrawVictoryCondition( mapFormat.victoryConditionType, victoryTextRoi, false, display ); renderRoi = fheroes2::getBoundaryRect( renderRoi, victoryConditionUIRoi ); renderRoi = fheroes2::getBoundaryRect( renderRoi, victoryTextRoi ); } if ( lossConditionUI.updateCondition( mapFormat ) ) { lossConditionUI.render( display, true ); fheroes2::Copy( itemBackground, 2, 3, display, lossTextRoi ); redrawLossCondition( mapFormat.lossConditionType, lossTextRoi, false, display ); renderRoi = fheroes2::getBoundaryRect( renderRoi, lossConditionUIRoi ); renderRoi = fheroes2::getBoundaryRect( renderRoi, lossTextRoi ); } // Update player icon. const uint32_t icnIndex = Color::GetIndex( availableColors[i] ) + getPlayerIcnIndex( mapFormat, availableColors[i] ); const fheroes2::Sprite & playerIcon = fheroes2::AGG::GetICN( ICN::NGEXTRA, icnIndex ); fheroes2::Copy( playerIcon, 0, 0, display, playerRects[i].x, playerRects[i].y, playerRects[i].width, playerRects[i].height ); renderRoi = fheroes2::getBoundaryRect( renderRoi, playerRects[i] ); display.render( renderRoi ); break; } if ( le.isMouseRightButtonPressedInArea( playerRects[i] ) ) { fheroes2::showStandardTextMessage( _( "Player Type" ), _( "Indicates the player types in the scenario. Click to change." ), Dialog::ZERO ); } } for ( size_t i = 0; i < 4; ++i ) { if ( le.MouseClickLeft( difficultyRects[i] ) ) { if ( i == difficultyIndex ) { // This difficulty is already selected. break; } difficultyCursor.setPosition( difficultyRects[i].x, difficultyRects[i].y ); difficultyCursor.redraw(); mapFormat.difficulty = setDifficultyByIndex( i ); display.updateNextRenderRoi( difficultyRects[difficultyIndex] ); difficultyIndex = i; display.render( difficultyRects[i] ); break; } if ( le.isMouseRightButtonPressedInArea( difficultyRects[i] ) ) { fheroes2::showStandardTextMessage( _( "Map Difficulty" ), _( "Click to set map difficulty. More difficult maps might include more or stronger enemies, fewer resources, or other special conditions making things tougher for the human player." ), Dialog::ZERO ); } } } // Retrieve victory and loss conditions. victoryConditionUI.getConditionMetadata( mapFormat ); lossConditionUI.getConditionMetadata( mapFormat ); return true; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_map_specs_window.h000066400000000000000000000032231476115357100250370ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace Maps::Map_Format { struct MapFormat; } namespace Editor { bool mapSpecificationsDialog( Maps::Map_Format::MapFormat & mapFormat, const int32_t maxMapNameLength ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_object_popup_window.cpp000066400000000000000000000154451476115357100261220ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_object_popup_window.h" #include #include #include #include #include #include #include #include #include "artifact.h" #include "editor_interface.h" #include "ground.h" #include "interface_gamearea.h" #include "logging.h" #include "map_format_info.h" #include "map_object_info.h" #include "maps_tiles.h" #include "monster.h" #include "mp2.h" #include "resource.h" #include "tools.h" #include "translations.h" #include "ui_map_interface.h" #include "world.h" namespace { std::string getObjectInfoText( const Maps::Tile & tile, const Maps::Map_Format::MapFormat & mapFormat ) { const MP2::MapObjectType type = tile.getMainObjectType(); switch ( type ) { case MP2::OBJ_NONE: if ( tile.isRoad() ) { return _( "Road" ); } return Maps::Ground::String( tile.GetGround() ); case MP2::OBJ_RESOURCE: { for ( const auto & info : Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_TREASURES ) ) { assert( !info.groundLevelParts.empty() ); if ( info.objectType == MP2::OBJ_RESOURCE && info.groundLevelParts.front().icnIndex == tile.getMainObjectPart().icnIndex && info.groundLevelParts.front().icnType == tile.getMainObjectPart().icnType ) { const auto iter = mapFormat.standardMetadata.find( tile.getMainObjectPart()._uid ); if ( iter != mapFormat.standardMetadata.end() && iter->second.metadata[0] > 0 ) { std::string message = _( "editor|%{count} %{resource}" ); StringReplace( message, "%{count}", iter->second.metadata[0] ); StringReplace( message, "%{resource}", Resource::String( static_cast( info.metadata[0] ) ) ); return message; } return Resource::String( static_cast( info.metadata[0] ) ); } } // This is an invalid object! assert( 0 ); break; } case MP2::OBJ_ARTIFACT: { for ( const auto & info : Maps::getObjectsByGroup( Maps::ObjectGroup::ADVENTURE_ARTIFACTS ) ) { assert( !info.groundLevelParts.empty() ); if ( info.objectType == MP2::OBJ_ARTIFACT && info.groundLevelParts.front().icnIndex == tile.getMainObjectPart().icnIndex && info.groundLevelParts.front().icnType == tile.getMainObjectPart().icnType ) { return MP2::StringObject( MP2::OBJ_ARTIFACT ) + std::string( "\n" ) + Artifact( static_cast( info.metadata[0] ) ).GetName(); } } // This is an invalid object! assert( 0 ); break; } case MP2::OBJ_MONSTER: { for ( const auto & info : Maps::getObjectsByGroup( Maps::ObjectGroup::MONSTERS ) ) { assert( !info.groundLevelParts.empty() ); if ( info.objectType == MP2::OBJ_MONSTER && info.groundLevelParts.front().icnIndex == tile.getMainObjectPart().icnIndex && info.groundLevelParts.front().icnType == tile.getMainObjectPart().icnType ) { const auto iter = mapFormat.standardMetadata.find( tile.getMainObjectPart()._uid ); if ( iter != mapFormat.standardMetadata.end() && iter->second.metadata[0] > 0 ) { const int32_t monsterCount = iter->second.metadata[0]; std::string message = "%{count} %{monster}"; StringReplace( message, "%{count}", monsterCount ); if ( monsterCount == 1 ) { StringReplace( message, "%{monster}", Monster( static_cast( info.metadata[0] ) ).GetName() ); } else { StringReplace( message, "%{monster}", Monster( static_cast( info.metadata[0] ) ).GetMultiName() ); } return message; } return MP2::StringObject( MP2::OBJ_MONSTER ) + std::string( "\n" ) + Monster( static_cast( info.metadata[0] ) ).GetMultiName(); } } // This is an invalid object! assert( 0 ); break; } default: break; } return MP2::StringObject( type ); } } namespace Editor { void showPopupWindow( const Maps::Tile & tile, const Maps::Map_Format::MapFormat & mapFormat ) { DEBUG_LOG( DBG_DEVEL, DBG_INFO, '\n' << tile.String() ) std::string infoString; const int32_t mainTileIndex = Maps::Tile::getIndexOfMainTile( tile ); if ( mainTileIndex != -1 ) { infoString = getObjectInfoText( world.getTile( mainTileIndex ), mapFormat ); } else { infoString = getObjectInfoText( tile, mapFormat ); } infoString += "\n["; infoString += std::to_string( tile.GetIndex() % world.w() ); infoString += "; "; infoString += std::to_string( tile.GetIndex() / world.w() ); infoString += ']'; Interface::displayStandardPopupWindow( std::move( infoString ), Interface::EditorInterface::Get().getGameArea().GetROI() ); } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_object_popup_window.h000066400000000000000000000032441476115357100255610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace Maps { class Tile; namespace Map_Format { struct MapFormat; } } namespace Editor { void showPopupWindow( const Maps::Tile & tile, const Maps::Map_Format::MapFormat & mapFormat ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_options.cpp000066400000000000000000000433441476115357100235340ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_options.h" #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "dialog_audio.h" #include "dialog_graphics_settings.h" #include "dialog_hotkeys.h" #include "dialog_language_selection.h" #include "editor_interface.h" #include "game_hotkeys.h" #include "game_language.h" #include "icn.h" #include "interface_base.h" #include "localevent.h" #include "math_base.h" #include "render_processor.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_option_item.h" #include "ui_window.h" namespace { enum class DialogAction : uint8_t { Configuration, Language, Graphics, AudioSettings, HotKeys, Animation, Passabiility, UpdateSettings, InterfaceType, CursorType, UpdateScrollSpeed, IncreaseScrollSpeed, DecreaseScrollSpeed, Close }; const fheroes2::Size offsetBetweenOptions{ 92, 110 }; const fheroes2::Point optionOffset{ 20, 31 }; const int32_t optionWindowSize{ 65 }; const fheroes2::Rect languageRoi{ optionOffset.x, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect graphicsRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect audioRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y, optionWindowSize, optionWindowSize }; const fheroes2::Rect hotKeyRoi{ optionOffset.x, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect animationRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect passabilityRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y + offsetBetweenOptions.height, optionWindowSize, optionWindowSize }; const fheroes2::Rect interfaceTypeRoi{ optionOffset.x, optionOffset.y + offsetBetweenOptions.height * 2, optionWindowSize, optionWindowSize }; const fheroes2::Rect cursorTypeRoi{ optionOffset.x + offsetBetweenOptions.width, optionOffset.y + offsetBetweenOptions.height * 2, optionWindowSize, optionWindowSize }; const fheroes2::Rect scrollSpeedRoi{ optionOffset.x + offsetBetweenOptions.width * 2, optionOffset.y + offsetBetweenOptions.height * 2, optionWindowSize, optionWindowSize }; void drawLanguage( const fheroes2::Rect & optionRoi ) { const fheroes2::SupportedLanguage currentLanguage = fheroes2::getLanguageFromAbbreviation( Settings::Get().getGameLanguage() ); const fheroes2::LanguageSwitcher languageSwitcher( currentLanguage ); fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 18 ), _( "Language" ), fheroes2::getLanguageName( currentLanguage ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawGraphics( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::GAME_OPTION_ICON, 1 ), _( "Graphics" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawAudioOptions( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::SPANEL, 1 ), _( "Audio" ), _( "Settings" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawHotKeyOptions( const fheroes2::Rect & optionRoi ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::GAME_OPTION_ICON, 0 ), _( "Hot Keys" ), _( "Configure" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } void drawAnimationOptions( const fheroes2::Rect & optionRoi ) { if ( Settings::Get().isEditorAnimationEnabled() ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::ESPANEL, 1 ), _( "Animation" ), _( "On" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } else { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::ESPANEL, 0 ), _( "Animation" ), _( "Off" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } } void drawPassabilityOptions( const fheroes2::Rect & optionRoi ) { if ( Settings::Get().isEditorPassabilityEnabled() ) { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::ESPANEL, 5 ), _( "Passability" ), _( "Show" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } else { fheroes2::drawOption( optionRoi, fheroes2::AGG::GetICN( ICN::ESPANEL, 4 ), _( "Passability" ), _( "Hide" ), fheroes2::UiOptionTextWidth::THREE_ELEMENTS_ROW ); } } DialogAction openEditorOptionsDialog() { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background( 289, 382, true, display ); const fheroes2::Rect windowRoi = background.activeArea(); const fheroes2::Rect windowLanguageRoi( languageRoi + windowRoi.getPosition() ); const fheroes2::Rect windowGraphicsRoi( graphicsRoi + windowRoi.getPosition() ); const fheroes2::Rect windowAudioRoi( audioRoi + windowRoi.getPosition() ); const fheroes2::Rect windowHotKeyRoi( hotKeyRoi + windowRoi.getPosition() ); const fheroes2::Rect windowAnimationRoi( animationRoi + windowRoi.getPosition() ); const fheroes2::Rect windowPassabilityRoi( passabilityRoi + windowRoi.getPosition() ); const fheroes2::Rect windowInterfaceTypeRoi( interfaceTypeRoi + windowRoi.getPosition() ); const fheroes2::Rect windowCursorTypeRoi( cursorTypeRoi + windowRoi.getPosition() ); const fheroes2::Rect windowScrollSpeedRoi( scrollSpeedRoi + windowRoi.getPosition() ); const auto drawOptions = [&windowLanguageRoi, &windowGraphicsRoi, &windowAudioRoi, &windowHotKeyRoi, &windowAnimationRoi, &windowPassabilityRoi, &windowInterfaceTypeRoi, &windowCursorTypeRoi, &windowScrollSpeedRoi]() { const Settings & conf = Settings::Get(); drawLanguage( windowLanguageRoi ); drawGraphics( windowGraphicsRoi ); drawAudioOptions( windowAudioRoi ); drawHotKeyOptions( windowHotKeyRoi ); drawAnimationOptions( windowAnimationRoi ); drawPassabilityOptions( windowPassabilityRoi ); drawInterfaceType( windowInterfaceTypeRoi, conf.isEvilInterfaceEnabled() ); drawCursorType( windowCursorTypeRoi, conf.isMonochromeCursorEnabled() ); drawScrollSpeed( windowScrollSpeedRoi, conf.ScrollSpeed() ); }; drawOptions(); const Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Button buttonOk; const int buttonOkIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcnId, 0, 1, { 0, 11 }, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); // Render the whole screen as interface type or resolution could have been changed. display.render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } if ( le.MouseClickLeft( windowLanguageRoi ) ) { return DialogAction::Language; } if ( le.MouseClickLeft( windowGraphicsRoi ) ) { return DialogAction::Graphics; } if ( le.MouseClickLeft( windowAudioRoi ) ) { return DialogAction::AudioSettings; } if ( le.MouseClickLeft( windowHotKeyRoi ) ) { return DialogAction::HotKeys; } if ( le.MouseClickLeft( windowAnimationRoi ) ) { return DialogAction::Animation; } if ( le.MouseClickLeft( windowPassabilityRoi ) ) { return DialogAction::Passabiility; } if ( le.MouseClickLeft( windowInterfaceTypeRoi ) ) { return DialogAction::InterfaceType; } if ( le.MouseClickLeft( windowCursorTypeRoi ) ) { return DialogAction::CursorType; } if ( le.MouseClickLeft( windowScrollSpeedRoi ) ) { return DialogAction::UpdateScrollSpeed; } if ( le.isMouseWheelUpInArea( windowScrollSpeedRoi ) ) { return DialogAction::IncreaseScrollSpeed; } if ( le.isMouseWheelDownInArea( windowScrollSpeedRoi ) ) { return DialogAction::DecreaseScrollSpeed; } if ( le.isMouseRightButtonPressedInArea( windowLanguageRoi ) ) { fheroes2::showStandardTextMessage( _( "Select Game Language" ), _( "Change the language of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowGraphicsRoi ) ) { fheroes2::showStandardTextMessage( _( "Graphics" ), _( "Change the graphics settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowAudioRoi ) ) { fheroes2::showStandardTextMessage( _( "Audio" ), _( "Change the audio settings of the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowHotKeyRoi ) ) { fheroes2::showStandardTextMessage( _( "Hot Keys" ), _( "Check and configure all the hot keys present in the game." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowAnimationRoi ) ) { fheroes2::showStandardTextMessage( _( "Animation" ), _( "Toggle animation of the objects." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowPassabilityRoi ) ) { fheroes2::showStandardTextMessage( _( "Passability" ), _( "Toggle display of objects' passability." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowInterfaceTypeRoi ) ) { fheroes2::showStandardTextMessage( _( "Interface Type" ), _( "Toggle the type of interface you want to use." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( windowCursorTypeRoi ) ) { fheroes2::showStandardTextMessage( _( "Mouse Cursor" ), _( "Toggle colored cursor on or off. This is only an aesthetic choice." ), 0 ); } if ( le.isMouseRightButtonPressedInArea( windowScrollSpeedRoi ) ) { fheroes2::showStandardTextMessage( _( "Scroll Speed" ), _( "Sets the speed at which you scroll the window." ), 0 ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), 0 ); } } return DialogAction::Close; } } namespace Editor { void openEditorSettings() { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); // We should write to the configuration file only once to avoid extra I/O operations. bool saveConfiguration = false; Settings & conf = Settings::Get(); auto redrawEditor = [&conf]() { Interface::EditorInterface & editorInterface = Interface::EditorInterface::Get(); // Since the radar interface has a restorer we must redraw it first to avoid the restorer doing something nasty. editorInterface.redraw( Interface::REDRAW_RADAR ); uint32_t redrawOptions = Interface::REDRAW_ALL; if ( conf.isEditorPassabilityEnabled() ) { redrawOptions |= Interface::REDRAW_PASSABILITIES; } editorInterface.redraw( redrawOptions & ( ~Interface::REDRAW_RADAR ) ); }; auto rebuildEditor = [&redrawEditor]() { Interface::EditorInterface::Get().reset(); redrawEditor(); }; DialogAction action = DialogAction::Configuration; while ( action != DialogAction::Close ) { switch ( action ) { case DialogAction::Configuration: action = openEditorOptionsDialog(); break; case DialogAction::Language: { const std::vector supportedLanguages = fheroes2::getSupportedLanguages(); if ( supportedLanguages.size() > 1 ) { selectLanguage( supportedLanguages, fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() ), true ); } else { assert( supportedLanguages.front() == fheroes2::SupportedLanguage::English ); conf.setGameLanguage( fheroes2::getLanguageAbbreviation( fheroes2::SupportedLanguage::English ) ); fheroes2::showStandardTextMessage( "Attention", "Your version of Heroes of Might and Magic II does not support any other languages than English.", Dialog::OK ); } redrawEditor(); saveConfiguration = true; action = DialogAction::Configuration; break; } case DialogAction::Graphics: saveConfiguration |= fheroes2::openGraphicsSettingsDialog( rebuildEditor ); action = DialogAction::Configuration; break; case DialogAction::AudioSettings: saveConfiguration |= Dialog::openAudioSettingsDialog( false ); action = DialogAction::Configuration; break; case DialogAction::HotKeys: fheroes2::openHotkeysDialog(); action = DialogAction::Configuration; break; case DialogAction::Animation: conf.setEditorAnimation( !conf.isEditorAnimationEnabled() ); saveConfiguration = true; if ( conf.isEditorAnimationEnabled() ) { fheroes2::RenderProcessor::instance().startColorCycling(); } else { fheroes2::RenderProcessor::instance().stopColorCycling(); } action = DialogAction::Configuration; break; case DialogAction::Passabiility: conf.setEditorPassability( !conf.isEditorPassabilityEnabled() ); saveConfiguration = true; redrawEditor(); action = DialogAction::Configuration; break; case DialogAction::InterfaceType: conf.setEvilInterface( !conf.isEvilInterfaceEnabled() ); rebuildEditor(); saveConfiguration = true; action = DialogAction::Configuration; break; case DialogAction::CursorType: conf.setMonochromeCursor( !conf.isMonochromeCursorEnabled() ); saveConfiguration = true; action = DialogAction::Configuration; break; case DialogAction::UpdateScrollSpeed: conf.SetScrollSpeed( ( conf.ScrollSpeed() + 1 ) % ( SCROLL_SPEED_VERY_FAST + 1 ) ); saveConfiguration = true; action = DialogAction::Configuration; break; case DialogAction::IncreaseScrollSpeed: conf.SetScrollSpeed( conf.ScrollSpeed() + 1 ); saveConfiguration = true; action = DialogAction::Configuration; break; case DialogAction::DecreaseScrollSpeed: conf.SetScrollSpeed( conf.ScrollSpeed() - 1 ); saveConfiguration = true; action = DialogAction::Configuration; break; default: break; } } if ( saveConfiguration ) { conf.Save( Settings::configFileName ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_options.h000066400000000000000000000027731476115357100232020ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace Editor { void openEditorSettings(); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_rumor_window.cpp000066400000000000000000000316231476115357100245710ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_rumor_window.h" #include #include #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_window.h" namespace { const int32_t elementOffset{ 9 }; const fheroes2::Size rumorArea{ 550, 300 }; const int32_t listAreaHeightDeduction{ 8 }; const size_t longestRumor{ 200 }; class RumorListBox final : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; RumorListBox( const fheroes2::Point & pt, const fheroes2::SupportedLanguage language ) : ListBox( pt ) , _language( language ) { // Do nothing. } void RedrawItem( const std::string & rumor, int32_t posX, int32_t posY, bool current ) override { fheroes2::Text text{ rumor, ( current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ), _language }; text.fitToOneRow( rumorArea.width - 10 ); text.draw( posX + 5, posY + 5, fheroes2::Display::instance() ); } void RedrawBackground( const fheroes2::Point & /*unused*/ ) override { _listBackground->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListDoubleClick( std::string & /*unused*/ ) override { _isDoubleClicked = true; } bool isDoubleClicked() const { return _isDoubleClicked; } void resetDoubleClickedState() { _isDoubleClicked = false; } void ActionListSingleClick( std::string & /*unused*/ ) override { // Do nothing. } void ActionListPressRight( std::string & /*unused*/ ) override { // Do nothing. } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: std::unique_ptr _listBackground; bool _isDoubleClicked{ false }; const fheroes2::SupportedLanguage _language; }; } namespace Editor { bool openRumorWindow( std::vector & rumors, const fheroes2::SupportedLanguage language ) { // Remove all empty rumors. assert( std::all_of( rumors.begin(), rumors.end(), []( const auto & rumor ) { return !rumor.empty(); } ) ); rumors.erase( std::remove_if( rumors.begin(), rumors.end(), []( const auto & rumor ) { return rumor.empty(); } ), rumors.end() ); const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background{ rumorArea.width + 50, rumorArea.height + 100, true, display }; const fheroes2::Rect windowArea{ background.activeArea() }; int32_t offsetY = windowArea.y + elementOffset; const fheroes2::Text title( _( "Rumors" ), fheroes2::FontType::normalYellow() ); title.draw( windowArea.x + ( windowArea.width - title.width() ) / 2, offsetY, display ); offsetY += title.height() + elementOffset; const fheroes2::Rect rumorsRoi{ windowArea.x + elementOffset, offsetY, rumorArea.width, rumorArea.height }; background.applyTextBackgroundShading( rumorsRoi ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); RumorListBox rumorList( rumorsRoi.getPosition(), language ); rumorList.initListBackgroundRestorer( rumorsRoi ); rumorList.SetAreaItems( { rumorsRoi.x, rumorsRoi.y, rumorsRoi.width, rumorsRoi.height - listAreaHeightDeduction } ); int32_t scrollbarOffsetX = rumorsRoi.x + rumorsRoi.width + 5; background.renderScrollbarBackground( { scrollbarOffsetX, rumorsRoi.y, rumorsRoi.width, rumorsRoi.height }, isEvilInterface ); const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; const int32_t topPartHeight = 19; ++scrollbarOffsetX; rumorList.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, rumorsRoi.y + 1 } ); rumorList.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, rumorsRoi.y + rumorsRoi.height - 15 } ); rumorList.setScrollBarArea( { scrollbarOffsetX + 2, rumorsRoi.y + topPartHeight, 10, rumorsRoi.height - 2 * topPartHeight } ); rumorList.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); rumorList.SetAreaMaxItems( 10 ); rumorList.SetListContent( rumors ); rumorList.updateScrollBarImage(); rumorList.Redraw(); const int minibuttonIcnId = isEvilInterface ? ICN::CELLWIN_EVIL : ICN::CELLWIN; const fheroes2::Sprite & buttonImage = fheroes2::AGG::GetICN( minibuttonIcnId, 13 ); const int32_t buttonWidth = buttonImage.width(); const int32_t buttonOffset = ( rumorArea.width - 3 * buttonWidth ) / 2 + buttonWidth; fheroes2::Button buttonAdd( rumorsRoi.x, rumorsRoi.y + rumorsRoi.height + 5, minibuttonIcnId, 13, 14 ); buttonAdd.draw(); fheroes2::Button buttonEdit( rumorsRoi.x + buttonOffset, rumorsRoi.y + rumorsRoi.height + 5, minibuttonIcnId, 15, 16 ); buttonEdit.draw(); fheroes2::Button buttonDelete( rumorsRoi.x + rumorArea.width - buttonWidth, rumorsRoi.y + rumorsRoi.height + 5, minibuttonIcnId, 17, 18 ); buttonDelete.draw(); // Prepare OKAY and CANCEL buttons and render their shadows. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); display.render( background.totalArea() ); bool isRedrawNeeded = false; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonAdd.drawOnState( le.isMouseLeftButtonPressedInArea( buttonAdd.area() ) ); buttonEdit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonEdit.area() ) ); buttonDelete.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDelete.area() ) ); if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { break; } if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) ) { return true; } rumorList.QueueEventProcessing(); if ( rumorList.IsNeedRedraw() ) { rumorList.Redraw(); isRedrawNeeded = true; } if ( le.MouseClickLeft( buttonAdd.area() ) ) { std::string newRumor; const fheroes2::Text body{ _( "Rumor:" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, newRumor, longestRumor, true, language ) ) { if ( std::any_of( rumors.begin(), rumors.end(), [&newRumor]( const auto & rumor ) { return rumor == newRumor; } ) ) { fheroes2::showStandardTextMessage( _( "Rumor" ), _( "This rumor already exists in the list." ), Dialog::OK ); continue; } rumors.emplace_back( std::move( newRumor ) ); rumorList.updateScrollBarImage(); rumorList.Redraw(); isRedrawNeeded = true; } } else if ( rumorList.isDoubleClicked() || le.MouseClickLeft( buttonEdit.area() ) ) { if ( rumorList.getCurrentId() < 0 ) { continue; } rumorList.resetDoubleClickedState(); std::string temp = rumorList.GetCurrent(); const fheroes2::Text body{ _( "Rumor:" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, temp, longestRumor, true, language ) ) { const auto count = std::count_if( rumors.begin(), rumors.end(), [&temp]( const auto & rumor ) { return rumor == temp; } ); if ( rumorList.GetCurrent() != temp && count > 0 ) { fheroes2::showStandardTextMessage( _( "Rumor" ), _( "This rumor already exists in the list." ), Dialog::OK ); continue; } rumorList.GetCurrent() = std::move( temp ); rumorList.Redraw(); isRedrawNeeded = true; } } else if ( le.MouseClickLeft( buttonDelete.area() ) ) { if ( rumorList.getCurrentId() < 0 ) { continue; } rumorList.RemoveSelected(); rumorList.updateScrollBarImage(); rumorList.Redraw(); isRedrawNeeded = true; } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to save the rumors." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonAdd.area() ) ) { fheroes2::showStandardTextMessage( _( "Add Rumor" ), _( "Add an additional rumor." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonEdit.area() ) ) { fheroes2::showStandardTextMessage( _( "Edit Rumor" ), _( "Edit an existing rumor." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonDelete.area() ) ) { fheroes2::showStandardTextMessage( _( "Delete Rumor" ), _( "Delete an existing rumor." ), Dialog::ZERO ); } if ( isRedrawNeeded ) { isRedrawNeeded = false; display.render( windowArea ); } } return false; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_rumor_window.h000066400000000000000000000033031476115357100242300ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace Editor { bool openRumorWindow( std::vector & rumors, const fheroes2::SupportedLanguage language ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_save_map_window.cpp000066400000000000000000000527111476115357100252210ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_save_map_window.h" #include #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "game_delays.h" #include "game_hotkeys.h" #include "game_language.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "maps.h" #include "maps_fileinfo.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "system.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_keyboard.h" #include "ui_language.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" namespace { // This constant sets the maximum displayed file name width. This value affects the dialog horizontal size. const int32_t maxFileNameWidth = 300; const std::string mapFileExtension = ".fh2m"; bool redrawSaveFileName( const std::string & name, const fheroes2::Rect & roi ) { if ( name.empty() ) { return false; } fheroes2::Text nameText( name + mapFileExtension, fheroes2::FontType::normalWhite() ); const bool isTextLimit = ( nameText.width() + 10 ) > maxFileNameWidth; nameText.fitToOneRow( maxFileNameWidth ); nameText.drawInRoi( roi.x + 4, roi.y + 4, fheroes2::Display::instance(), roi ); return isTextLimit; } class FileInfoListBox : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; using ListBox::ListBox; void RedrawItem( const Maps::FileInfo & info, int32_t posX, int32_t posY, bool current ) override; void RedrawBackground( const fheroes2::Point & dst ) override; void ActionCurrentUp() override; void ActionCurrentDn() override; void ActionListDoubleClick( Maps::FileInfo & info ) override; void ActionListSingleClick( Maps::FileInfo & info ) override; void ActionListPressRight( Maps::FileInfo & info ) override { const fheroes2::Text header( System::GetStem( info.filename ), fheroes2::FontType::normalYellow() ); fheroes2::MultiFontText body; body.add( { _( "Map: " ), fheroes2::FontType::normalYellow() } ); body.add( { info.name, fheroes2::FontType::normalWhite(), info.getSupportedLanguage() } ); body.add( { _( "\n\nSize: " ), fheroes2::FontType::normalYellow() } ); body.add( { std::to_string( info.width ) + " x " + std::to_string( info.height ), fheroes2::FontType::normalWhite() } ); body.add( { _( "\n\nDescription: " ), fheroes2::FontType::normalYellow() } ); body.add( { info.description, fheroes2::FontType::normalWhite() } ); body.add( { _( "\n\nLocation: " ), fheroes2::FontType::smallYellow() } ); body.add( { info.filename, fheroes2::FontType::smallWhite() } ); fheroes2::showMessage( header, body, Dialog::ZERO ); } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } bool isDoubleClicked() const { return _isDoubleClicked; } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: bool _isDoubleClicked{ false }; std::unique_ptr _listBackground; }; void FileInfoListBox::RedrawItem( const Maps::FileInfo & info, int32_t posX, int32_t posY, bool current ) { std::string mapFileName( System::GetFileName( info.filename ) ); assert( !mapFileName.empty() ); const fheroes2::FontType font = current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite(); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Text fileNameText( std::move( mapFileName ), font ); fileNameText.fitToOneRow( maxFileNameWidth - 40 ); fileNameText.draw( posX + 44, posY + 2, display ); const uint32_t racesCountIcnIndex = static_cast( Color::Count( info.kingdomColors ) + 19 ); const fheroes2::Sprite & racesCount = fheroes2::AGG::GetICN( ICN::REQUESTS, racesCountIcnIndex ); fheroes2::Copy( racesCount, 0, 0, display, posX + 6, posY, racesCount.width(), racesCount.height() ); const uint32_t mapSizeIcnIndex = static_cast( info.width / Maps::SMALL + 25 ); const fheroes2::Sprite & mapSize = fheroes2::AGG::GetICN( ICN::REQUESTS, mapSizeIcnIndex ); fheroes2::Copy( mapSize, 0, 0, display, posX + 25, posY, mapSize.width(), mapSize.height() ); } void FileInfoListBox::RedrawBackground( const fheroes2::Point & /* unused */ ) { _listBackground->restore(); } void FileInfoListBox::ActionCurrentUp() { // Do nothing. } void FileInfoListBox::ActionCurrentDn() { // Do nothing. } void FileInfoListBox::ActionListDoubleClick( Maps::FileInfo & /*unused*/ ) { _isDoubleClicked = true; } void FileInfoListBox::ActionListSingleClick( Maps::FileInfo & /*unused*/ ) { // Do nothing. } } namespace Editor { bool mapSaveSelectFile( std::string & fileName, std::string & mapName, const fheroes2::SupportedLanguage language, const int32_t maxMapNameLength ) { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); MapsFileInfoList lists = Maps::getResurrectionMapFileInfos( true, 0 ); const int32_t listWidth = maxFileNameWidth + 9; const int32_t listHeightDeduction = 112 + 17; const int32_t listAreaOffsetY = 6; const int32_t listAreaHeightDeduction = 8; // If we don't have many map files, we reduce the maximum dialog height, // but not less than enough for 11 elements. We also limit the maximum list height to 22 lines. const int32_t listLineHeight = 2 + fheroes2::getFontHeight( fheroes2::FontSize::NORMAL ); const int32_t estraDialogHeight = listAreaOffsetY + listAreaHeightDeduction + listHeightDeduction; const int32_t maxDialogHeight = listLineHeight * std::clamp( static_cast( lists.size() ), 11, 22 ) + estraDialogHeight; fheroes2::Display & display = fheroes2::Display::instance(); const int32_t listItems = ( std::min( display.height() - 100, maxDialogHeight ) - estraDialogHeight ) / listLineHeight; const int32_t dialogHeight = listLineHeight * listItems + estraDialogHeight; // Dialog height is also capped with the current screen height. fheroes2::StandardWindow background( listWidth + 75, dialogHeight, true, display ); const fheroes2::Rect area( background.activeArea() ); const fheroes2::Rect listRoi( area.x + 24, area.y + 37 + 17, listWidth, area.height - listHeightDeduction ); const fheroes2::Rect fileNameRoi( listRoi.x, listRoi.y + listRoi.height + 12, maxFileNameWidth + 8, 21 ); const fheroes2::Text header( _( "Save Map:" ), fheroes2::FontType::normalYellow() ); header.draw( area.x + ( area.width - header.width() ) / 2, area.y + 10, display ); if ( fileName.empty() ) { fileName = "My map"; } if ( mapName.empty() ) { mapName = fileName; } fheroes2::Text mapNameText( mapName, fheroes2::FontType::normalWhite(), language ); const fheroes2::Rect mapNameRoi( listRoi.x, area.y + 28, listRoi.width, mapNameText.height() + 4 ); background.applyTextBackgroundShading( mapNameRoi ); fheroes2::ImageRestorer mapNameBackground( display, mapNameRoi.x, mapNameRoi.y, mapNameRoi.width, mapNameRoi.height ); const int32_t maxMapNameTextWidth = mapNameRoi.width - 6; mapNameText.fitToOneRow( maxMapNameTextWidth ); mapNameText.drawInRoi( mapNameRoi.x, mapNameRoi.y + 4, mapNameRoi.width, display, mapNameRoi ); background.applyTextBackgroundShading( { listRoi.x, listRoi.y, fileNameRoi.width, listRoi.height } ); background.applyTextBackgroundShading( fileNameRoi ); fheroes2::ImageRestorer fileNameBackground( display, fileNameRoi.x, fileNameRoi.y, fileNameRoi.width, fileNameRoi.height ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); // Prepare OKAY and CANCEL buttons and render their shadows. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); FileInfoListBox listbox( area.getPosition() ); // Initialize list background restorer to use it in list method 'listbox.RedrawBackground()'. listbox.initListBackgroundRestorer( listRoi ); listbox.SetAreaItems( { listRoi.x, listRoi.y + listAreaOffsetY, listRoi.width, listRoi.height - listAreaHeightDeduction } ); int32_t scrollbarOffsetX = area.x + area.width - 35; background.renderScrollbarBackground( { scrollbarOffsetX, listRoi.y, listRoi.width, listRoi.height }, isEvilInterface ); const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; const int32_t topPartHeight = 19; ++scrollbarOffsetX; listbox.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, listRoi.y + 1 } ); listbox.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, listRoi.y + listRoi.height - 15 } ); listbox.setScrollBarArea( { scrollbarOffsetX + 2, listRoi.y + topPartHeight, 10, listRoi.height - 2 * topPartHeight } ); listbox.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); listbox.SetAreaMaxItems( listItems ); listbox.SetListContent( lists ); listbox.updateScrollBarImage(); size_t charInsertPos = 0; charInsertPos = fileName.size(); MapsFileInfoList::iterator it = lists.begin(); for ( ; it != lists.end(); ++it ) { if ( System::GetStem( ( *it ).filename ) == fileName ) { break; } } if ( it != lists.end() ) { listbox.SetCurrent( std::distance( lists.begin(), it ) ); } else { listbox.Unselect(); } auto buttonOkDisabler = [&buttonOk, &fileName]() { if ( fileName.empty() && buttonOk.isEnabled() ) { buttonOk.disable(); buttonOk.draw(); } else if ( !fileName.empty() && buttonOk.isDisabled() ) { buttonOk.enable(); buttonOk.draw(); } }; listbox.Redraw(); redrawSaveFileName( fileName, fileNameRoi ); // Render a button to open the Virtual Keyboard window. fheroes2::ButtonSprite buttonVirtualKB; background.renderButtonSprite( buttonVirtualKB, "...", { 48, 25 }, { 0, 7 }, isEvilInterface, fheroes2::StandardWindow::Padding::BOTTOM_CENTER ); Game::passAnimationDelay( Game::DelayType::CURSOR_BLINK_DELAY ); display.render( background.totalArea() ); bool isTextLimit = false; std::string lastSelectedSaveFileName; const bool isInGameKeyboardRequired = System::isVirtualKeyboardSupported(); bool isCursorVisible = true; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isDelayNeeded( { Game::DelayType::CURSOR_BLINK_DELAY } ) ) ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonVirtualKB.drawOnState( le.isMouseLeftButtonPressedInArea( buttonVirtualKB.area() ) ); if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { return false; } if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || listbox.isDoubleClicked() ) ) { return true; } const int listId = listbox.getCurrentId(); const bool listboxEvent = listbox.QueueEventProcessing(); bool isListboxSelected = listbox.isSelected(); bool needFileNameRedraw = listId != listbox.getCurrentId(); if ( le.MouseClickLeft( buttonVirtualKB.area() ) || ( isInGameKeyboardRequired && le.MouseClickLeft( fileNameRoi ) ) ) { { // TODO: allow to use other languages once we add support of filesystem language support. const fheroes2::LanguageSwitcher switcher( fheroes2::SupportedLanguage::English ); fheroes2::openVirtualKeyboard( fileName, 255 ); } charInsertPos = fileName.size(); listbox.Unselect(); isListboxSelected = false; needFileNameRedraw = true; buttonOkDisabler(); // Set the whole screen to redraw next time to properly restore image under the Virtual Keyboard dialog. display.updateNextRenderRoi( { 0, 0, display.width(), display.height() } ); } else if ( !fileName.empty() && le.MouseClickLeft( fileNameRoi ) ) { const fheroes2::Text text( fileName, fheroes2::FontType::normalWhite() ); charInsertPos = fheroes2::getTextInputCursorPosition( fileName, fheroes2::FontType::normalWhite(), charInsertPos, le.getMouseCursorPos().x, fileNameRoi.x ); listbox.Unselect(); isListboxSelected = false; needFileNameRedraw = true; } else if ( le.MouseClickLeft( mapNameRoi ) ) { std::string editableMapName = mapName; const fheroes2::Text body{ _( "Change Map Name" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, editableMapName, maxMapNameLength, false, language ) ) { if ( editableMapName.empty() ) { // Map should have a non empty name. continue; } mapName = std::move( editableMapName ); mapNameText.set( mapName, fheroes2::FontType::normalWhite(), language ); mapNameBackground.restore(); mapNameText.fitToOneRow( maxMapNameTextWidth ); mapNameText.drawInRoi( mapNameRoi.x, mapNameRoi.y + 4, mapNameRoi.width, display, mapNameRoi ); display.render( mapNameRoi ); continue; } } else if ( isListboxSelected && le.isKeyPressed( fheroes2::Key::KEY_DELETE ) ) { listbox.SetCurrent( listId ); listbox.Redraw(); std::string msg( _( "Are you sure you want to delete file:" ) ); msg.append( "\n\n" ); msg.append( System::GetFileName( listbox.GetCurrent().filename ) ); if ( Dialog::YES == fheroes2::showStandardTextMessage( _( "Warning" ), msg, Dialog::YES | Dialog::NO ) ) { System::Unlink( listbox.GetCurrent().filename ); listbox.RemoveSelected(); if ( lists.empty() ) { isListboxSelected = false; charInsertPos = 0; fileName.clear(); buttonOk.disable(); buttonOk.draw(); } listbox.updateScrollBarImage(); listbox.SetCurrent( std::max( listId - 1, 0 ) ); } needFileNameRedraw = true; } else if ( !listboxEvent && le.isAnyKeyPressed() && ( !isTextLimit || fheroes2::Key::KEY_BACKSPACE == le.getPressedKeyValue() || fheroes2::Key::KEY_DELETE == le.getPressedKeyValue() ) && le.getPressedKeyValue() != fheroes2::Key::KEY_UP && le.getPressedKeyValue() != fheroes2::Key::KEY_DOWN ) { charInsertPos = InsertKeySym( fileName, charInsertPos, le.getPressedKeyValue(), LocalEvent::getCurrentKeyModifiers() ); buttonOkDisabler(); needFileNameRedraw = true; listbox.Unselect(); isListboxSelected = false; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to save the current map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonVirtualKB.area() ) ) { fheroes2::showStandardTextMessage( _( "Open Virtual Keyboard" ), _( "Click to open the Virtual Keyboard dialog." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( mapNameRoi ) ) { fheroes2::MultiFontText message; message.add( fheroes2::Text{ "\"", fheroes2::FontType::normalWhite() } ); message.add( fheroes2::Text{ mapName, fheroes2::FontType::normalWhite(), language } ); message.add( fheroes2::Text{ "\"\n\n", fheroes2::FontType::normalWhite() } ); message.add( fheroes2::Text{ _( "Click to change your map name." ), fheroes2::FontType::normalWhite() } ); fheroes2::showMessage( fheroes2::Text{ _( "Map Name" ), fheroes2::FontType::normalYellow() }, message, Dialog::ZERO ); } // Text input cursor blink. if ( Game::validateAnimationDelay( Game::DelayType::CURSOR_BLINK_DELAY ) ) { isCursorVisible = !isCursorVisible; needFileNameRedraw = true; } if ( !needFileNameRedraw && !listbox.IsNeedRedraw() ) { continue; } if ( needFileNameRedraw ) { const std::string selectedFileName = isListboxSelected ? System::GetStem( listbox.GetCurrent().filename ) : ""; if ( isListboxSelected && lastSelectedSaveFileName != selectedFileName ) { lastSelectedSaveFileName = selectedFileName; fileName = selectedFileName; charInsertPos = fileName.size(); buttonOkDisabler(); } else { // Empty last selected save file name so that we can replace the input field's name if we select the same save file again. // But when loading (i.e. isEditing == false), this doesn't matter since we cannot write to the input field lastSelectedSaveFileName = ""; } fileNameBackground.restore(); isTextLimit = redrawSaveFileName( insertCharToString( fileName, charInsertPos, isCursorVisible ? '_' : '\x7F' ), fileNameRoi ); } if ( listbox.IsNeedRedraw() ) { listbox.Redraw(); display.render( area ); } else { display.render( fileNameRoi ); } } return false; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_save_map_window.h000066400000000000000000000033371476115357100246660ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace Editor { bool mapSaveSelectFile( std::string & fileName, std::string & mapName, const fheroes2::SupportedLanguage language, const int32_t maxMapNameLength ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_secondary_skill_selection.cpp000066400000000000000000000337721476115357100272770ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_secondary_skill_selection.h" #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "game_static.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "math_tools.h" #include "pal.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_window.h" namespace { const int32_t skillRowOffsetY{ 90 }; const int32_t skillItemWidth{ 90 }; // Up to 5 skills can be displayed in a row. // Up to 5 rows can be displayed. // So far the number of skills of any level is much more than 25. class SecondarySkillContainerUI final { public: SecondarySkillContainerUI( fheroes2::Point offset, std::vector> & skills ) : _skills( skills ) { assert( !skills.empty() && skills.size() < 25 ); // Figure out how many rows and columns we want to display. for ( size_t i = 1; i < 5; ++i ) { if ( i * i >= skills.size() ) { _skillsPerRow = i; break; } } offset.x += ( fheroes2::Display::DEFAULT_WIDTH - static_cast( _skillsPerRow ) * skillItemWidth ) / 2; offset.y += ( fheroes2::Display::DEFAULT_HEIGHT - 50 - skillRowOffsetY * static_cast( _skills.size() / _skillsPerRow ) ) / 2; // Calculate all areas where we are going to render skills. _skillRoi.reserve( _skills.size() ); const fheroes2::Sprite & frameImage = fheroes2::AGG::GetICN( ICN::SECSKILL, 15 ); const int32_t lastRowColumns = static_cast( _skills.size() % _skillsPerRow ); const int32_t lastRowOffsetX = ( lastRowColumns > 0 ) ? ( static_cast( _skillsPerRow ) - lastRowColumns ) * skillItemWidth / 2 : 0; for ( size_t i = 0; i < _skills.size(); ++i ) { const int32_t rowId = static_cast( i / _skillsPerRow ); const int32_t columnId = static_cast( i % _skillsPerRow ); if ( rowId == static_cast( _skills.size() / _skillsPerRow ) ) { // This is the last row. _skillRoi.emplace_back( offset.x + columnId * skillItemWidth + lastRowOffsetX, offset.y + rowId * skillRowOffsetY, frameImage.width(), frameImage.height() ); } else { _skillRoi.emplace_back( offset.x + columnId * skillItemWidth, offset.y + rowId * skillRowOffsetY, frameImage.width(), frameImage.height() ); } } } void draw( fheroes2::Image & output ) { const fheroes2::Sprite & frameImage = fheroes2::AGG::GetICN( ICN::SECSKILL, 15 ); fheroes2::Sprite inactiveFrameImage( frameImage ); fheroes2::ApplyPalette( inactiveFrameImage, PAL::GetPalette( PAL::PaletteType::GRAY ) ); for ( size_t i = 0; i < _skills.size(); ++i ) { const Skill::Secondary & skill = _skills[i].first; const fheroes2::Sprite & skillImage = fheroes2::AGG::GetICN( ICN::SECSKILL, skill.GetIndexSprite1() ); const fheroes2::Point skillImagePos( _skillRoi[i].x + 3, _skillRoi[i].y + 3 ); fheroes2::Copy( skillImage, 0, 0, output, skillImagePos.x, skillImagePos.y, skillImage.width(), skillImage.height() ); if ( _skills[i].second ) { fheroes2::Blit( frameImage, output, _skillRoi[i].x, _skillRoi[i].y ); } else { // The skill is being inactive. fheroes2::Blit( inactiveFrameImage, output, _skillRoi[i].x, _skillRoi[i].y ); fheroes2::ApplyPalette( output, skillImagePos.x, skillImagePos.y, output, _skillRoi[i].x + 3, _skillRoi[i].y + 3, skillImage.width(), skillImage.height(), PAL::GetPalette( PAL::PaletteType::GRAY ) ); } fheroes2::Text text{ Skill::Secondary::String( skill.Skill() ), fheroes2::FontType::smallWhite() }; text.drawInRoi( skillImagePos.x + ( skillImage.width() - text.width() ) / 2, _skillRoi[i].y + 7, output, _skillRoi[i] ); text.set( Skill::Level::String( skill.Level() ), fheroes2::FontType::smallWhite() ); text.drawInRoi( skillImagePos.x + ( skillImage.width() - text.width() ) / 2, _skillRoi[i].y + skillImage.height() - 10, output, _skillRoi[i] ); } } const fheroes2::Rect & redrawChangedSkill( fheroes2::Image & output ) { assert( _skillToRedraw >= 0 && _skillToRedraw < static_cast( _skillRoi.size() ) ); const fheroes2::Rect & roi = _skillRoi[_skillToRedraw]; if ( _skills[_skillToRedraw].second ) { const Skill::Secondary & skill = _skills[_skillToRedraw].first; const fheroes2::Sprite & frameImage = fheroes2::AGG::GetICN( ICN::SECSKILL, 15 ); const fheroes2::Sprite & skillImage = fheroes2::AGG::GetICN( ICN::SECSKILL, skill.GetIndexSprite1() ); const int32_t skillImageOffsetX = roi.x + 3; fheroes2::Blit( frameImage, output, roi.x, roi.y ); fheroes2::Copy( skillImage, 0, 0, output, skillImageOffsetX, roi.y + 3, skillImage.width(), skillImage.height() ); fheroes2::Text text{ Skill::Secondary::String( skill.Skill() ), fheroes2::FontType::smallWhite() }; text.drawInRoi( skillImageOffsetX + ( skillImage.width() - text.width() ) / 2, roi.y + 7, output, roi ); text.set( Skill::Level::String( skill.Level() ), fheroes2::FontType::smallWhite() ); text.drawInRoi( skillImageOffsetX + ( skillImage.width() - text.width() ) / 2, roi.y + skillImage.height() - 10, output, roi ); } else { // The skill is being inactive. Just make it grayscale. fheroes2::ApplyPalette( output, roi.x, roi.y, output, roi.x, roi.y, roi.width, roi.height, PAL::GetPalette( PAL::PaletteType::GRAY ) ); } return roi; } bool processEvents( LocalEvent & eventProcessor ) { const int32_t skillIndex = GetRectIndex( _skillRoi, eventProcessor.getMouseCursorPos() ); if ( skillIndex < 0 ) { return false; } assert( static_cast( skillIndex ) < _skillRoi.size() ); const fheroes2::Rect skillRoi = _skillRoi[skillIndex]; if ( eventProcessor.MouseClickLeft( skillRoi ) ) { _skills[skillIndex].second = !_skills[skillIndex].second; _skillToRedraw = skillIndex; return true; } if ( eventProcessor.isMouseRightButtonPressedInArea( skillRoi ) ) { const Heroes fakeHero; fheroes2::SecondarySkillDialogElement( _skills[skillIndex].first, fakeHero ).showPopup( Dialog::ZERO ); } return false; } private: std::vector> & _skills; std::vector _skillRoi; size_t _skillsPerRow{ 0 }; int32_t _skillToRedraw{ 0 }; }; } namespace Editor { bool openSecondarySkillSelectionWindow( std::string title, const int skillLevel, std::vector & selectedSkills ) { if ( skillLevel < 1 || skillLevel > 3 ) { // What are you trying to achieve?! assert( 0 ); return false; } const std::vector & existingSkills = GameStatic::getSecondarySkillsForWitchsHut(); // Create a container of active and disabled skills. std::vector> skills; skills.reserve( existingSkills.size() ); bool isAnySkillEnabled = false; for ( const int skill : existingSkills ) { const bool isSelected = ( std::find( selectedSkills.begin(), selectedSkills.end(), skill ) != selectedSkills.end() ); skills.emplace_back( Skill::Secondary( skill, skillLevel ), isSelected ); if ( isSelected ) { isAnySkillEnabled = true; } } // If no skills are selected, select all of them. if ( !isAnySkillEnabled ) { for ( auto & [skill, isSelected] : skills ) { isSelected = true; } } const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const bool isDefaultScreenSize = display.isDefaultSize(); fheroes2::StandardWindow background( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, !isDefaultScreenSize ); const fheroes2::Rect activeArea( background.activeArea() ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); if ( isDefaultScreenSize ) { const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ); fheroes2::Copy( backgroundImage, 0, 0, display, activeArea ); } const fheroes2::Text text( std::move( title ), fheroes2::FontType::normalYellow() ); text.draw( activeArea.x + ( activeArea.width - text.width() ) / 2, activeArea.y + 10, display ); // Buttons. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); SecondarySkillContainerUI skillContainer( activeArea.getPosition(), skills ); skillContainer.draw( display ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { if ( buttonOk.isEnabled() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return false; } if ( buttonOk.isEnabled() && ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( buttonOk.area() ) ) ) { break; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to accept the changes made." ), Dialog::ZERO ); } if ( skillContainer.processEvents( le ) ) { const fheroes2::Rect & roi = skillContainer.redrawChangedSkill( display ); // Check if all skills are being disabled. If they are disable the OKAY button. bool areAllSkillsDisabled = true; for ( const auto & [skill, isSelected] : skills ) { if ( isSelected ) { areAllSkillsDisabled = false; break; } } if ( areAllSkillsDisabled && buttonOk.isEnabled() ) { buttonOk.disable(); buttonOk.draw(); display.updateNextRenderRoi( buttonOk.area() ); } else if ( buttonOk.isDisabled() ) { buttonOk.enable(); buttonOk.draw(); display.updateNextRenderRoi( buttonOk.area() ); } display.render( roi ); } } selectedSkills.clear(); for ( const auto & [skill, isSelected] : skills ) { if ( isSelected ) { selectedSkills.emplace_back( skill.first ); } } // If all skills are selected, remove all skills from the selection since an empty container means the use of the default behavior of the game. if ( selectedSkills.size() == skills.size() ) { selectedSkills = {}; } return true; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_secondary_skill_selection.h000066400000000000000000000032221476115357100267270ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include namespace Editor { bool openSecondarySkillSelectionWindow( std::string title, const int skillLevel, std::vector & selectedSkills ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_spell_selection.cpp000066400000000000000000000300211476115357100252110ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_spell_selection.h" #include #include #include #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "math_tools.h" #include "pal.h" #include "screen.h" #include "settings.h" #include "spell.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_window.h" namespace { const int32_t spellRowOffsetY{ 90 }; const int32_t spellItemWidth{ 110 }; // Up to 5 spells can be displayed in a row. // Up to 5 rows can be displayed. // So far the number of spells of any level is much more than 25. class SpellContainerUI final { public: SpellContainerUI( fheroes2::Point offset, std::vector> & spells ) : _spells( spells ) { assert( !spells.empty() && spells.size() < 25 ); // Figure out how many rows and columns we want to display. for ( size_t i = 1; i < 5; ++i ) { if ( i * i >= _spells.size() ) { _spellsPerRow = i; break; } } offset.x += ( fheroes2::Display::DEFAULT_WIDTH - static_cast( _spellsPerRow ) * spellItemWidth ) / 2; offset.y += ( fheroes2::Display::DEFAULT_HEIGHT - 50 - spellRowOffsetY * static_cast( _spells.size() / _spellsPerRow ) ) / 2; // Calculate all areas where we are going to render spells. _spellRoi.reserve( _spells.size() ); const fheroes2::Sprite & scrollImage = fheroes2::AGG::GetICN( ICN::TOWNWIND, 0 ); const int32_t lastRowColumns = static_cast( _spells.size() % _spellsPerRow ); const int32_t lastRowOffsetX = ( lastRowColumns > 0 ) ? ( static_cast( _spellsPerRow ) - lastRowColumns ) * spellItemWidth / 2 : 0; for ( size_t i = 0; i < _spells.size(); ++i ) { const int32_t rowId = static_cast( i / _spellsPerRow ); const int32_t columnId = static_cast( i % _spellsPerRow ); if ( rowId == static_cast( _spells.size() / _spellsPerRow ) ) { // This is the last row. _spellRoi.emplace_back( offset.x + columnId * spellItemWidth + lastRowOffsetX, offset.y + rowId * spellRowOffsetY, scrollImage.width(), scrollImage.height() ); } else { _spellRoi.emplace_back( offset.x + columnId * spellItemWidth, offset.y + rowId * spellRowOffsetY, scrollImage.width(), scrollImage.height() ); } } } void draw( fheroes2::Image & output ) { const fheroes2::Sprite & scrollImage = fheroes2::AGG::GetICN( ICN::TOWNWIND, 0 ); fheroes2::Sprite inactiveScrollImage( scrollImage ); fheroes2::ApplyPalette( inactiveScrollImage, PAL::GetPalette( PAL::PaletteType::GRAY ) ); for ( size_t i = 0; i < _spells.size(); ++i ) { if ( !_spells[i].second ) { // The spell is being inactive. fheroes2::Blit( inactiveScrollImage, output, _spellRoi[i].x, _spellRoi[i].y ); } else { fheroes2::Blit( scrollImage, output, _spellRoi[i].x, _spellRoi[i].y ); } const fheroes2::Sprite & spellImage = fheroes2::AGG::GetICN( ICN::SPELLS, _spells[i].first.IndexSprite() ); if ( !_spells[i].second ) { // The spell is being inactive. fheroes2::Sprite inactiveSpellImage( spellImage ); fheroes2::ApplyPalette( inactiveSpellImage, PAL::GetPalette( PAL::PaletteType::GRAY ) ); fheroes2::Blit( inactiveSpellImage, output, _spellRoi[i].x + 3 + ( _spellRoi[i].width - inactiveSpellImage.width() ) / 2, _spellRoi[i].y + 31 - inactiveSpellImage.height() / 2 ); } else { fheroes2::Blit( spellImage, output, _spellRoi[i].x + 3 + ( _spellRoi[i].width - spellImage.width() ) / 2, _spellRoi[i].y + 31 - spellImage.height() / 2 ); } const fheroes2::Text text( _spells[i].first.GetName(), fheroes2::FontType::smallWhite() ); text.draw( _spellRoi[i].x + 18, _spellRoi[i].y + 57, 78, fheroes2::Display::instance() ); } } bool processEvents( LocalEvent & eventProcessor ) { const int32_t spellIndex = GetRectIndex( _spellRoi, eventProcessor.getMouseCursorPos() ); if ( spellIndex < 0 ) { return false; } assert( static_cast( spellIndex ) < _spellRoi.size() ); const fheroes2::Rect spellRoi = _spellRoi[spellIndex]; if ( eventProcessor.MouseClickLeft( spellRoi ) ) { _spells[spellIndex].second = !_spells[spellIndex].second; return true; } if ( eventProcessor.isMouseRightButtonPressedInArea( spellRoi ) ) { fheroes2::SpellDialogElement( _spells[spellIndex].first, nullptr ).showPopup( Dialog::ZERO ); } return false; } private: std::vector> & _spells; std::vector _spellRoi; size_t _spellsPerRow{ 0 }; }; } namespace Editor { bool openSpellSelectionWindow( std::string title, const int spellLevel, std::vector & selectedSpells ) { if ( spellLevel < 1 || spellLevel > 5 ) { // What are you trying to achieve?! assert( 0 ); return false; } const std::vector & availableSpells = Spell::getAllSpellIdsSuitableForSpellBook( spellLevel ); assert( !availableSpells.empty() ); // Create a container of active and disabled spells. std::vector> spells; spells.reserve( availableSpells.size() ); bool isAnySpellEnabled = false; for ( const int spell : availableSpells ) { const bool isSelected = ( std::find( selectedSpells.begin(), selectedSpells.end(), spell ) != selectedSpells.end() ); spells.emplace_back( spell, isSelected ); if ( isSelected ) { isAnySpellEnabled = true; } } // If no spells are selected, select all of them. if ( !isAnySpellEnabled ) { for ( auto & [spell, isSelected] : spells ) { isSelected = true; } } const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const bool isDefaultScreenSize = display.isDefaultSize(); fheroes2::StandardWindow background( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT, !isDefaultScreenSize ); const fheroes2::Rect activeArea( background.activeArea() ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); if ( isDefaultScreenSize ) { const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ); fheroes2::Copy( backgroundImage, 0, 0, display, activeArea ); } const fheroes2::Text text( std::move( title ), fheroes2::FontType::normalYellow() ); text.draw( activeArea.x + ( activeArea.width - text.width() ) / 2, activeArea.y + 10, display ); // Buttons. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); fheroes2::ImageRestorer restorer( display, activeArea.x, activeArea.y, activeArea.width, activeArea.height ); SpellContainerUI spellContainer( activeArea.getPosition(), spells ); spellContainer.draw( display ); display.render( background.totalArea() ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { if ( buttonOk.isEnabled() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return false; } if ( buttonOk.isEnabled() && ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( buttonOk.area() ) ) ) { break; } if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to accept the changes made." ), Dialog::ZERO ); } if ( spellContainer.processEvents( le ) ) { restorer.restore(); spellContainer.draw( display ); // Check if all spells are being disabled. If they are disable the OKAY button. bool areAllSpellsDisabled = true; for ( const auto & [spell, isSelected] : spells ) { if ( isSelected ) { areAllSpellsDisabled = false; break; } } if ( areAllSpellsDisabled ) { buttonOk.disable(); buttonOk.draw(); } else { buttonOk.enable(); buttonOk.draw(); } display.render( activeArea ); } } selectedSpells.clear(); for ( const auto & [spell, isSelected] : spells ) { if ( isSelected ) { selectedSpells.emplace_back( spell.GetID() ); } } // If all spells are selected, remove all spells from the selection since an empty container means the use of the default behavior of the game. if ( selectedSpells.size() == spells.size() ) { selectedSpells = {}; } return true; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_spell_selection.h000066400000000000000000000032111476115357100246570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include namespace Editor { bool openSpellSelectionWindow( std::string title, const int spellLevel, std::vector & selectedSpells ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_sphinx_window.cpp000066400000000000000000000526641476115357100247460ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_sphinx_window.h" #include #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "artifact.h" #include "artifact_info.h" #include "cursor.h" #include "dialog.h" #include "dialog_selectitems.h" #include "editor_ui_helper.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "interface_list.h" #include "localevent.h" #include "map_format_info.h" #include "math_base.h" #include "mp2.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "spell.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_scrollbar.h" #include "ui_text.h" #include "ui_window.h" namespace { const fheroes2::Size riddleArea{ 250, 180 }; const fheroes2::Size answerArea{ 250, 155 }; const int32_t elementOffset{ 9 }; const int32_t listAreaHeightDeduction{ 8 }; const size_t longestAnswer{ 64 }; // TODO: expand the riddle area to support more characters. // At the moment only up to 140 of the biggest characters can be added. const size_t longestRiddle{ 140 }; const std::array resourceTypes = { Resource::WOOD, Resource::SULFUR, Resource::CRYSTAL, Resource::MERCURY, Resource::ORE, Resource::GEMS, Resource::GOLD }; class AnswerListBox : public Interface::ListBox { public: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; AnswerListBox( const fheroes2::Point & pt, const fheroes2::SupportedLanguage language ) : ListBox( pt ) , _language( language ) { // Do nothing. } void RedrawItem( const std::string & answer, int32_t posX, int32_t posY, bool current ) override { fheroes2::Text text{ answer, ( current ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite() ), _language }; text.fitToOneRow( answerArea.width - 10 ); text.draw( posX + 5, posY + 5, fheroes2::Display::instance() ); } void RedrawBackground( const fheroes2::Point & /*unused*/ ) override { _listBackground->restore(); } void ActionCurrentUp() override { // Do nothing. } void ActionCurrentDn() override { // Do nothing. } void ActionListDoubleClick( std::string & /*unused*/ ) override { _isDoubleClicked = true; } bool isDoubleClicked() const { return _isDoubleClicked; } void resetDoubleClickedState() { _isDoubleClicked = false; } void ActionListSingleClick( std::string & /*unused*/ ) override { // Do nothing. } void ActionListPressRight( std::string & /*unused*/ ) override { // Do nothing. } int getCurrentId() const { return _currentId; } void initListBackgroundRestorer( fheroes2::Rect roi ) { _listBackground = std::make_unique( fheroes2::Display::instance(), roi.x, roi.y, roi.width, roi.height ); } void updateScrollBarImage() { const int32_t scrollBarWidth = _scrollbar.width(); setScrollBarImage( fheroes2::generateScrollbarSlider( _scrollbar, false, _scrollbar.getArea().height, VisibleItemCount(), _size(), { 0, 0, scrollBarWidth, 8 }, { 0, 7, scrollBarWidth, 8 } ) ); _scrollbar.moveToIndex( _topId ); } private: std::unique_ptr _listBackground; bool _isDoubleClicked{ false }; const fheroes2::SupportedLanguage _language; }; } namespace Editor { bool openSphinxWindow( Maps::Map_Format::SphinxMetadata & metadata, const fheroes2::SupportedLanguage language ) { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::StandardWindow background{ riddleArea.width + answerArea.width + 50, riddleArea.height + 220, true, display }; const fheroes2::Rect windowArea{ background.activeArea() }; int32_t offsetY = windowArea.y + elementOffset; const fheroes2::Text title( MP2::StringObject( MP2::OBJ_SPHINX ), fheroes2::FontType::normalYellow() ); title.draw( windowArea.x + ( windowArea.width - title.width() ) / 2, offsetY, display ); offsetY += title.height() + elementOffset; fheroes2::Text text{ _( "Riddle:" ), fheroes2::FontType::normalWhite() }; const fheroes2::Rect riddleRoi{ windowArea.x + elementOffset, offsetY + text.height(), riddleArea.width, riddleArea.height }; background.applyTextBackgroundShading( riddleRoi ); fheroes2::ImageRestorer riddleRoiRestorer( display, riddleRoi.x, riddleRoi.y, riddleRoi.width, riddleRoi.height ); text.draw( riddleRoi.x + ( riddleRoi.width - text.width() ) / 2, offsetY, display ); text.set( metadata.riddle, fheroes2::FontType::normalWhite(), language ); text.draw( riddleRoi.x + 5, riddleRoi.y + 5, riddleRoi.width - 10, display ); const fheroes2::Rect answerRoi{ windowArea.x + elementOffset + riddleRoi.width + elementOffset, offsetY + text.height(), answerArea.width, answerArea.height }; background.applyTextBackgroundShading( answerRoi ); text.set( _( "Answers:" ), fheroes2::FontType::normalWhite() ); text.draw( answerRoi.x + ( answerRoi.width - text.width() ) / 2, offsetY, display ); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); AnswerListBox answerList( answerRoi.getPosition(), language ); answerList.initListBackgroundRestorer( answerRoi ); answerList.SetAreaItems( { answerRoi.x, answerRoi.y, answerRoi.width, answerRoi.height - listAreaHeightDeduction } ); int32_t scrollbarOffsetX = answerRoi.x + answerRoi.width + 5; background.renderScrollbarBackground( { scrollbarOffsetX, answerRoi.y, answerRoi.width, answerRoi.height }, isEvilInterface ); const int listIcnId = isEvilInterface ? ICN::SCROLLE : ICN::SCROLL; const int32_t topPartHeight = 19; ++scrollbarOffsetX; answerList.SetScrollButtonUp( listIcnId, 0, 1, { scrollbarOffsetX, answerRoi.y + 1 } ); answerList.SetScrollButtonDn( listIcnId, 2, 3, { scrollbarOffsetX, answerRoi.y + answerRoi.height - 15 } ); answerList.setScrollBarArea( { scrollbarOffsetX + 2, answerRoi.y + topPartHeight, 10, answerRoi.height - 2 * topPartHeight } ); answerList.setScrollBarImage( fheroes2::AGG::GetICN( listIcnId, 4 ) ); answerList.SetAreaMaxItems( 10 ); answerList.SetListContent( metadata.answers ); answerList.updateScrollBarImage(); answerList.Redraw(); const int minibuttonIcnId = isEvilInterface ? ICN::CELLWIN_EVIL : ICN::CELLWIN; const fheroes2::Sprite & buttonImage = fheroes2::AGG::GetICN( minibuttonIcnId, 13 ); const int32_t buttonWidth = buttonImage.width(); const int32_t buttonOffset = ( answerArea.width - 3 * buttonWidth ) / 2 + buttonWidth; fheroes2::Button buttonAdd( answerRoi.x, answerRoi.y + answerRoi.height + 5, minibuttonIcnId, 13, 14 ); buttonAdd.draw(); fheroes2::Button buttonEdit( answerRoi.x + buttonOffset, answerRoi.y + answerRoi.height + 5, minibuttonIcnId, 15, 16 ); buttonEdit.draw(); fheroes2::Button buttonDelete( answerRoi.x + answerArea.width - buttonWidth, answerRoi.y + answerRoi.height + 5, minibuttonIcnId, 17, 18 ); buttonDelete.draw(); offsetY += text.height() + riddleArea.height + elementOffset; text.set( _( "Reward:" ), fheroes2::FontType::normalWhite() ); text.draw( windowArea.x + ( windowArea.width - text.width() ) / 2, offsetY, display ); const fheroes2::Sprite & artifactFrame = fheroes2::AGG::GetICN( ICN::RESOURCE, 7 ); const fheroes2::Rect artifactRoi{ riddleRoi.x + ( riddleRoi.width - artifactFrame.width() ) / 2, offsetY + text.height(), artifactFrame.width(), artifactFrame.height() }; fheroes2::Blit( artifactFrame, display, artifactRoi.x, artifactRoi.y ); auto redrawArtifactImage = [&display, &artifactRoi]( const int32_t artifactId ) { const fheroes2::Sprite & artifactImage = fheroes2::AGG::GetICN( ICN::ARTIFACT, Artifact( artifactId ).IndexSprite64() ); fheroes2::Copy( artifactImage, 0, 0, display, artifactRoi.x + 6, artifactRoi.y + 6, artifactImage.width(), artifactImage.height() ); }; redrawArtifactImage( metadata.artifact ); fheroes2::Button buttonDeleteArtifact( artifactRoi.x + ( artifactRoi.width - buttonWidth ) / 2, artifactRoi.y + artifactRoi.height + 5, minibuttonIcnId, 17, 18 ); buttonDeleteArtifact.draw(); const fheroes2::Rect resourceRoi{ answerRoi.x, offsetY + text.height(), answerRoi.width, 99 }; background.applyTextBackgroundShading( resourceRoi ); fheroes2::ImageRestorer resourceRoiRestorer( display, resourceRoi.x, resourceRoi.y, resourceRoi.width, resourceRoi.height ); std::array individualResourceRoi; renderResources( metadata.resources, resourceRoi, display, individualResourceRoi ); // Prepare OKAY and CANCEL buttons and render their shadows. fheroes2::Button buttonOk; fheroes2::Button buttonCancel; background.renderOkayCancelButtons( buttonOk, buttonCancel, isEvilInterface ); display.render( background.totalArea() ); bool isRedrawNeeded = false; LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonAdd.drawOnState( le.isMouseLeftButtonPressedInArea( buttonAdd.area() ) ); buttonEdit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonEdit.area() ) ); buttonDelete.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDelete.area() ) ); buttonDeleteArtifact.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDeleteArtifact.area() ) ); if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { break; } if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) ) ) { return true; } answerList.QueueEventProcessing(); if ( answerList.IsNeedRedraw() ) { answerList.Redraw(); isRedrawNeeded = true; } for ( size_t i = 0; i < individualResourceRoi.size(); ++i ) { if ( le.MouseClickLeft( individualResourceRoi[i] ) ) { const int resourceType = resourceTypes[i]; int32_t * resourcePtr = metadata.resources.GetPtr( resourceType ); assert( resourcePtr != nullptr ); int32_t temp = *resourcePtr; const fheroes2::ResourceDialogElement resourceUI( resourceType, {} ); std::string str = _( "Set %{resource-type} Count" ); StringReplace( str, "%{resource-type}", Resource::String( resourceType ) ); if ( Dialog::SelectCount( std::move( str ), 0, 1000000, temp, 1, &resourceUI ) ) { *resourcePtr = temp; } resourceRoiRestorer.restore(); renderResources( metadata.resources, resourceRoi, display, individualResourceRoi ); display.render( resourceRoi ); break; } } if ( le.MouseClickLeft( riddleRoi ) ) { std::string temp = metadata.riddle; const fheroes2::Text body{ _( "Riddle:" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, temp, longestRiddle, true, language ) ) { metadata.riddle = std::move( temp ); riddleRoiRestorer.restore(); text.set( metadata.riddle, fheroes2::FontType::normalWhite(), language ); text.draw( riddleRoi.x + 5, riddleRoi.y + 5, riddleRoi.width - 10, display ); isRedrawNeeded = true; } } else if ( le.MouseClickLeft( buttonAdd.area() ) ) { std::string newAnswer; const fheroes2::Text body{ _( "Answer:" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, newAnswer, longestAnswer, false, language ) ) { if ( std::any_of( metadata.answers.begin(), metadata.answers.end(), [&newAnswer]( const auto & answer ) { return answer == newAnswer; } ) ) { fheroes2::showStandardTextMessage( _( "Answer" ), _( "This answer exists in the list." ), Dialog::OK ); continue; } metadata.answers.emplace_back( std::move( newAnswer ) ); answerList.updateScrollBarImage(); answerList.Redraw(); isRedrawNeeded = true; } } else if ( answerList.isDoubleClicked() || le.MouseClickLeft( buttonEdit.area() ) ) { if ( answerList.getCurrentId() < 0 ) { continue; } answerList.resetDoubleClickedState(); std::string temp = answerList.GetCurrent(); const fheroes2::Text body{ _( "Answer:" ), fheroes2::FontType::normalWhite() }; if ( Dialog::inputString( fheroes2::Text{}, body, temp, longestAnswer, false, language ) ) { const auto count = std::count_if( metadata.answers.begin(), metadata.answers.end(), [&temp]( const auto & answer ) { return answer == temp; } ); if ( answerList.GetCurrent() != temp && count > 0 ) { fheroes2::showStandardTextMessage( _( "Answer" ), _( "This answer exists in the list." ), Dialog::OK ); continue; } answerList.GetCurrent() = std::move( temp ); answerList.Redraw(); isRedrawNeeded = true; } } else if ( le.MouseClickLeft( buttonDelete.area() ) ) { if ( answerList.getCurrentId() < 0 ) { continue; } answerList.RemoveSelected(); answerList.updateScrollBarImage(); answerList.Redraw(); isRedrawNeeded = true; } else if ( le.MouseClickLeft( artifactRoi ) ) { const Artifact artifact = Dialog::selectArtifact( metadata.artifact, false ); if ( artifact.isValid() ) { int32_t artifactMetadata = metadata.artifactMetadata; if ( artifact.GetID() == Artifact::SPELL_SCROLL ) { artifactMetadata = Dialog::selectSpell( artifactMetadata, true ).GetID(); if ( artifactMetadata == Spell::NONE ) { // No spell for the Spell Scroll artifact was selected - cancel the artifact selection. continue; } } else { artifactMetadata = 0; } metadata.artifact = artifact.GetID(); metadata.artifactMetadata = artifactMetadata; redrawArtifactImage( metadata.artifact ); } // The opened selectArtifact() dialog might be bigger than the Sphinx dialog so we render the whole screen. display.render(); isRedrawNeeded = false; } else if ( le.MouseClickLeft( buttonDeleteArtifact.area() ) ) { metadata.artifact = 0; metadata.artifactMetadata = 0; const fheroes2::Sprite & artifactImage = fheroes2::AGG::GetICN( ICN::ARTIFACT, Artifact( metadata.artifact ).IndexSprite64() ); fheroes2::Copy( artifactImage, 0, 0, display, artifactRoi.x + 6, artifactRoi.y + 6, artifactImage.width(), artifactImage.height() ); display.render( artifactRoi ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to save the Sphinx properties." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonAdd.area() ) ) { fheroes2::showStandardTextMessage( _( "Add Answer" ), _( "Add an additional answer for the question." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonEdit.area() ) ) { fheroes2::showStandardTextMessage( _( "Edit Answer" ), _( "Edit an existing answer for the question." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonDelete.area() ) ) { fheroes2::showStandardTextMessage( _( "Delete Answer" ), _( "Delete an existing answer for the question." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( artifactRoi ) ) { // Since Artifact class does not allow to set a random spell (for obvious reasons), // we have to use special UI code to render the popup window with all needed information. const Artifact artifact( metadata.artifact ); if ( artifact.isValid() ) { fheroes2::ArtifactDialogElement artifactUI( artifact ); fheroes2::showStandardTextMessage( artifact.GetName(), fheroes2::getArtifactData( metadata.artifact ).getDescription( metadata.artifactMetadata ), Dialog::ZERO, { &artifactUI } ); } else { fheroes2::showStandardTextMessage( _( "Artifact" ), _( "No artifact will be given as a reward." ), Dialog::ZERO ); } } else if ( le.isMouseRightButtonPressedInArea( buttonDeleteArtifact.area() ) ) { fheroes2::showStandardTextMessage( _( "Delete Artifact" ), _( "Delete an artifact from the reward." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( resourceRoi ) ) { if ( metadata.resources.GetValidItemsCount() == 0 ) { fheroes2::showStandardTextMessage( _( "Resources" ), _( "No resources will be given as a reward." ), Dialog::ZERO ); } else { fheroes2::showResourceMessage( fheroes2::Text( _( "Resources" ), fheroes2::FontType::normalYellow() ), fheroes2::Text{ _( "Resources will be given as a reward." ), fheroes2::FontType::normalWhite() }, Dialog::ZERO, metadata.resources ); } } if ( isRedrawNeeded ) { isRedrawNeeded = false; display.render( windowArea ); } } return false; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_sphinx_window.h000066400000000000000000000033451476115357100244030ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace Maps::Map_Format { struct SphinxMetadata; } namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace Editor { bool openSphinxWindow( Maps::Map_Format::SphinxMetadata & metadata, const fheroes2::SupportedLanguage language ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_ui_helper.cpp000066400000000000000000000225621476115357100240140ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "editor_ui_helper.h" #include #include #include "agg_image.h" #include "color.h" #include "icn.h" #include "image.h" #include "resource.h" #include "screen.h" #include "tools.h" #include "translations.h" #include "ui_text.h" #include "ui_tool.h" namespace Editor { Checkbox::Checkbox( const int32_t x, const int32_t y, const int boxColor, const bool checked, fheroes2::Image & output ) : _color( boxColor ) , _checkmark( fheroes2::AGG::GetICN( ICN::CELLWIN, 2 ) ) { const int32_t icnIndex = ( _color == Color::NONE ) ? 1 : Color::GetIndex( _color ) + 43; const fheroes2::Sprite & playerIcon = fheroes2::AGG::GetICN( ICN::CELLWIN, icnIndex ); _area = { x, y, playerIcon.width(), playerIcon.height() }; fheroes2::Copy( playerIcon, 0, 0, output, _area ); _checkmark.setPosition( _area.x + 2, _area.y + 2 ); if ( checked ) { _checkmark.show(); } else { _checkmark.hide(); } } bool Checkbox::toggle() { _checkmark.isHidden() ? _checkmark.show() : _checkmark.hide(); fheroes2::Display::instance().render( _area ); return !_checkmark.isHidden(); } void createColorCheckboxes( std::vector> & list, const int32_t availableColors, const int32_t selectedColors, const int32_t boxOffsetX, const int32_t boxOffsetY, fheroes2::Image & output ) { int32_t colorsAdded = 0; for ( const int color : Colors( availableColors ) ) { list.emplace_back( std::make_unique( boxOffsetX + colorsAdded * 32, boxOffsetY, color, ( color & selectedColors ) != 0, output ) ); ++colorsAdded; } } fheroes2::Rect drawCheckboxWithText( fheroes2::MovableSprite & checkSprite, std::string str, fheroes2::Image & output, const int32_t posX, const int32_t posY, const bool isEvil, const int32_t maxWidth ) { assert( maxWidth > 0 ); const fheroes2::Sprite & checkboxBackground = fheroes2::AGG::GetICN( isEvil ? ICN::CELLWIN_EVIL : ICN::CELLWIN, 1 ); fheroes2::Copy( checkboxBackground, 0, 0, output, posX, posY, checkboxBackground.width(), checkboxBackground.height() ); fheroes2::addGradientShadow( checkboxBackground, output, { posX, posY }, { -4, 4 } ); const int32_t textOffsetX{ 23 }; fheroes2::Text checkboxText( std::move( str ), fheroes2::FontType::normalWhite() ); checkboxText.fitToOneRow( maxWidth - textOffsetX ); checkboxText.draw( posX + textOffsetX, posY + 4, output ); checkSprite = fheroes2::AGG::GetICN( ICN::CELLWIN, 2 ); checkSprite.setPosition( posX + 2, posY + 2 ); return { posX, posY, textOffsetX + checkboxText.width(), checkboxBackground.height() }; } void renderResources( const Funds & resources, const fheroes2::Rect & roi, fheroes2::Image & output, std::array & resourceRoi ) { const int32_t offsetFromEdge{ 7 }; // Maximum width is 39 pixels (except gold), maximum height is 32 pixels const int32_t maxWidth = 39; const int32_t maxHeight = 32; const int32_t midElementOffsetX = ( ( roi.width - 2 * offsetFromEdge ) - maxWidth * 4 ) / 3; const int32_t firstColumnOffset = roi.x + offsetFromEdge; const int32_t columnStep = maxWidth + midElementOffsetX; const int32_t secondColumnOffset = firstColumnOffset + columnStep; const int32_t thirdColumnOffset = secondColumnOffset + columnStep; const int32_t forthColumnOffset = thirdColumnOffset + columnStep; const fheroes2::FontType fontType( fheroes2::FontSize::SMALL, fheroes2::FontColor::WHITE ); const int32_t fontHeight = fheroes2::Text( std::string(), fontType ).height(); const std::array offsetY = { roi.y + offsetFromEdge + maxHeight, roi.y + offsetFromEdge + 2 * maxHeight + fontHeight + 2 }; const fheroes2::Sprite & woodImage = fheroes2::AGG::GetICN( ICN::RESOURCE, 0 ); const fheroes2::Sprite & mercuryImage = fheroes2::AGG::GetICN( ICN::RESOURCE, 1 ); const fheroes2::Sprite & oreImage = fheroes2::AGG::GetICN( ICN::RESOURCE, 2 ); const fheroes2::Sprite & sulfurImage = fheroes2::AGG::GetICN( ICN::RESOURCE, 3 ); const fheroes2::Sprite & crystalImage = fheroes2::AGG::GetICN( ICN::RESOURCE, 4 ); const fheroes2::Sprite & gemsImage = fheroes2::AGG::GetICN( ICN::RESOURCE, 5 ); const fheroes2::Sprite & goldImage = fheroes2::AGG::GetICN( ICN::RESOURCE, 6 ); resourceRoi[0] = { firstColumnOffset + ( maxWidth - woodImage.width() ) / 2, offsetY[0] - woodImage.height(), woodImage.width(), woodImage.height() }; resourceRoi[1] = { secondColumnOffset + ( maxWidth - sulfurImage.width() ) / 2, offsetY[0] - sulfurImage.height(), sulfurImage.width(), sulfurImage.height() }; resourceRoi[2] = { thirdColumnOffset + ( maxWidth - crystalImage.width() ) / 2, offsetY[0] - crystalImage.height(), crystalImage.width(), crystalImage.height() }; resourceRoi[3] = { forthColumnOffset + ( maxWidth - mercuryImage.width() ) / 2, offsetY[0] - mercuryImage.height(), mercuryImage.width(), mercuryImage.height() }; resourceRoi[4] = { firstColumnOffset + ( maxWidth - oreImage.width() ) / 2, offsetY[1] - oreImage.height(), oreImage.width(), oreImage.height() }; resourceRoi[5] = { secondColumnOffset + ( maxWidth - gemsImage.width() ) / 2, offsetY[1] - gemsImage.height(), gemsImage.width(), gemsImage.height() }; resourceRoi[6] = { thirdColumnOffset + ( maxWidth * 2 + midElementOffsetX - goldImage.width() ) / 2, offsetY[1] - goldImage.height(), goldImage.width(), goldImage.height() }; fheroes2::Blit( woodImage, output, resourceRoi[0].x, resourceRoi[0].y ); fheroes2::Blit( sulfurImage, output, resourceRoi[1].x, resourceRoi[1].y ); fheroes2::Blit( crystalImage, output, resourceRoi[2].x, resourceRoi[2].y ); fheroes2::Blit( mercuryImage, output, resourceRoi[3].x, resourceRoi[3].y ); fheroes2::Blit( oreImage, output, resourceRoi[4].x, resourceRoi[4].y ); fheroes2::Blit( gemsImage, output, resourceRoi[5].x, resourceRoi[5].y ); fheroes2::Blit( goldImage, output, resourceRoi[6].x, resourceRoi[6].y ); fheroes2::Text text( std::to_string( resources.wood ), fontType ); text.draw( firstColumnOffset + ( maxWidth - text.width() ) / 2, offsetY[0] + 1, output ); text.set( std::to_string( resources.sulfur ), fontType ); text.draw( secondColumnOffset + ( maxWidth - text.width() ) / 2, offsetY[0] + 1, output ); text.set( std::to_string( resources.crystal ), fontType ); text.draw( thirdColumnOffset + ( maxWidth - text.width() ) / 2, offsetY[0] + 1, output ); text.set( std::to_string( resources.mercury ), fontType ); text.draw( forthColumnOffset + ( maxWidth - text.width() ) / 2, offsetY[0] + 1, output ); text.set( std::to_string( resources.ore ), fontType ); text.draw( firstColumnOffset + ( maxWidth - text.width() ) / 2, offsetY[1] + 1, output ); text.set( std::to_string( resources.gems ), fontType ); text.draw( secondColumnOffset + ( maxWidth - text.width() ) / 2, offsetY[1] + 1, output ); text.set( std::to_string( resources.gold ), fontType ); text.draw( thirdColumnOffset + ( maxWidth * 2 + midElementOffsetX - text.width() ) / 2, offsetY[1] + 1, output ); } std::string getDateDescription( const int32_t day ) { std::string message = _( "Day: %{day} Week: %{week} Month: %{month}" ); int32_t days = day - 1; const int32_t month = days / ( 7 * 4 ); days -= month * ( 7 * 4 ); StringReplace( message, "%{day}", ( days % 7 ) + 1 ); StringReplace( message, "%{week}", ( days / 7 ) + 1 ); StringReplace( message, "%{month}", month + 1 ); return message; } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/editor_ui_helper.h000066400000000000000000000057701476115357100234630ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "math_base.h" #include "ui_tool.h" struct Funds; namespace fheroes2 { class Image; } namespace Editor { class Checkbox { public: Checkbox( const int32_t x, const int32_t y, const int boxColor, const bool checked, fheroes2::Image & output ); Checkbox( Checkbox && other ) = delete; ~Checkbox() = default; Checkbox( Checkbox & ) = delete; Checkbox & operator=( const Checkbox & ) = delete; const fheroes2::Rect & getRect() const { return _area; } int getColor() const { return _color; } bool toggle(); private: const int _color{ 0 }; fheroes2::Rect _area; fheroes2::MovableSprite _checkmark; }; void createColorCheckboxes( std::vector> & list, const int32_t availableColors, const int32_t selectedColors, const int32_t boxOffsetX, const int32_t boxOffsetY, fheroes2::Image & output ); fheroes2::Rect drawCheckboxWithText( fheroes2::MovableSprite & checkSprite, std::string str, fheroes2::Image & output, const int32_t posX, const int32_t posY, const bool isEvil, const int32_t maxWidth ); void renderResources( const Funds & resources, const fheroes2::Rect & roi, fheroes2::Image & output, std::array & resourceRoi ); std::string getDateDescription( const int32_t day ); } fheroes2-1.1.6+dfsg/src/fheroes2/editor/history_manager.cpp000066400000000000000000000107261476115357100236640ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "history_manager.h" #include #include #include "map_format_helper.h" #include "map_format_info.h" #include "world_object_uid.h" namespace { // This class holds 2 copies of MapFormat objects: // - one copy before the action // - one copy after the action // Ideally, we need to store only difference between before and after an action // but for simplification purposes we chose this way. // TODO: optimize this class (if possible) to store less data. class MapAction final : public fheroes2::Action { public: explicit MapAction( Maps::Map_Format::MapFormat & mapFormat ) : _mapFormat( mapFormat ) , _latestObjectUIDBefore( Maps::getLastObjectUID() ) { if ( !Maps::saveMapInEditor( _mapFormat ) ) { // If this assertion blows up then something is really wrong with the Editor. assert( 0 ); } _beforeMapFormat = _mapFormat; } bool prepare() { if ( !Maps::saveMapInEditor( _mapFormat ) ) { // If this assertion blows up then something is really wrong with the Editor. assert( 0 ); return false; } _afterMapFormat = _mapFormat; _latestObjectUIDAfter = Maps::getLastObjectUID(); return true; } bool redo() override { _mapFormat = _afterMapFormat; if ( !Maps::readMapInEditor( _mapFormat ) ) { // If this assertion blows up then something is really wrong with the Editor. assert( 0 ); return false; } Maps::setLastObjectUID( _latestObjectUIDAfter ); return true; } bool undo() override { _mapFormat = _beforeMapFormat; if ( !Maps::readMapInEditor( _mapFormat ) ) { // If this assertion blows up then something is really wrong with the Editor. assert( 0 ); return false; } Maps::setLastObjectUID( _latestObjectUIDBefore ); return true; } private: Maps::Map_Format::MapFormat & _mapFormat; Maps::Map_Format::MapFormat _beforeMapFormat; Maps::Map_Format::MapFormat _afterMapFormat; const uint32_t _latestObjectUIDBefore{ 0 }; uint32_t _latestObjectUIDAfter{ 0 }; }; } namespace fheroes2 { ActionCreator::ActionCreator( HistoryManager & manager, Maps::Map_Format::MapFormat & mapFormat ) : _manager( manager ) { _action = std::make_unique( mapFormat ); } void ActionCreator::commit() { auto * action = dynamic_cast( _action.get() ); if ( action == nullptr ) { // How is it even possible? Did you call this method twice? assert( 0 ); return; } if ( action->prepare() ) { _manager.add( std::move( _action ) ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/editor/history_manager.h000066400000000000000000000074221476115357100233300ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include namespace Maps::Map_Format { struct MapFormat; } namespace fheroes2 { class HistoryManager; class Action { public: virtual ~Action() = default; virtual bool redo() = 0; virtual bool undo() = 0; }; // Remember the map state and create an action if the map has changed. class ActionCreator { public: explicit ActionCreator( HistoryManager & manager, Maps::Map_Format::MapFormat & mapFormat ); ~ActionCreator() { if ( _action ) { // The action wasn't committed. Undo all the changes. _action->undo(); } } ActionCreator( const ActionCreator & ) = delete; ActionCreator & operator=( const ActionCreator & ) = delete; void commit(); private: HistoryManager & _manager; std::unique_ptr _action; }; class HistoryManager { public: void reset() { _actions.clear(); _lastActionId = 0; } void add( std::unique_ptr action ) { _actions.resize( _lastActionId ); _actions.push_back( std::move( action ) ); ++_lastActionId; if ( _actions.size() > maxActions ) { --_lastActionId; _actions.pop_front(); } assert( _actions.size() <= maxActions ); } bool undo() { if ( _lastActionId == 0 ) { // Nothing to do. return false; } --_lastActionId; return _actions[_lastActionId]->undo(); } bool redo() { if ( _lastActionId == _actions.size() ) { // Nothing to do. return false; } const bool result = _actions[_lastActionId]->redo(); ++_lastActionId; return result; } private: // We shouldn't store too many actions. It is extremely rare when there is a need to revert so many changes. static const size_t maxActions{ 500 }; std::deque> _actions; size_t _lastActionId{ 0 }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/game/000077500000000000000000000000001476115357100174025ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/game/difficulty.cpp000066400000000000000000000214121476115357100222500ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "difficulty.h" #include #include #include #include "castle.h" #include "kingdom.h" #include "profit.h" #include "race.h" #include "translations.h" #include "world.h" std::string Difficulty::String( int difficulty ) { switch ( difficulty ) { case Difficulty::EASY: return _( "difficulty|Easy" ); case Difficulty::NORMAL: return _( "difficulty|Normal" ); case Difficulty::HARD: return _( "difficulty|Hard" ); case Difficulty::EXPERT: return _( "difficulty|Expert" ); case Difficulty::IMPOSSIBLE: return _( "difficulty|Impossible" ); default: break; } return "Unknown"; } Funds Difficulty::getResourceIncomeBonusForAI( const int difficulty, const Kingdom & kingdom ) { assert( kingdom.isControlAI() ); const auto getIncomeFromSetsOfResourceMines = []( const int resourceTypes, const uint32_t numOfSets ) { Funds result; Resource::forEach( resourceTypes, [&result]( const int res ) { result += ProfitConditions::FromMine( res ); } ); return result * numOfSets; }; const auto getBonusForCastles = [kingdomColor = kingdom.GetColor(), &kingdomCastles = kingdom.GetCastles()]() { Funds result; const bool kingdomHasMarketplace = std::any_of( kingdomCastles.begin(), kingdomCastles.end(), []( const Castle * castle ) { assert( castle != nullptr ); return castle->isBuild( BUILD_MARKETPLACE ); } ); // Additional rare resources for hiring units from higher-level dwellings can only be provided if the kingdom already has some source of those resources - either // through trade or through mining const auto doesKingdomHaveResourceSource = [kingdomColor, kingdomHasMarketplace]( const int resourceType ) { return ( kingdomHasMarketplace || world.CountCapturedMines( resourceType, kingdomColor ) > 0 ); }; for ( const Castle * castle : kingdomCastles ) { assert( castle != nullptr ); // AI at higher difficulty levels should be able to fully redeem the weekly unit growth in its castles result += ProfitConditions::FromMine( Resource::GOLD ); // Provide additional resources only if there are higher-level dwellings in the castle to avoid distortions in the castle's development rate if ( !castle->isBuild( DWELLING_MONSTER6 ) ) { continue; } switch ( castle->GetRace() ) { case Race::KNGT: case Race::NECR: // Rare resources are not required to hire maximum-level units in these castles break; case Race::BARB: if ( doesKingdomHaveResourceSource( Resource::CRYSTAL ) ) { result += ProfitConditions::FromMine( Resource::CRYSTAL ); } break; case Race::SORC: if ( doesKingdomHaveResourceSource( Resource::MERCURY ) ) { result += ProfitConditions::FromMine( Resource::MERCURY ); } break; case Race::WRLK: if ( doesKingdomHaveResourceSource( Resource::SULFUR ) ) { result += ProfitConditions::FromMine( Resource::SULFUR ); } // The maximum level units in this castle are more expensive than in others result += ProfitConditions::FromMine( Resource::GOLD ); break; case Race::WZRD: if ( doesKingdomHaveResourceSource( Resource::GEMS ) ) { result += ProfitConditions::FromMine( Resource::GEMS ); } // The maximum level units in this castle are more expensive than in others result += ProfitConditions::FromMine( Resource::GOLD ); break; default: assert( 0 ); break; } } return result; }; switch ( difficulty ) { case Difficulty::HARD: return getIncomeFromSetsOfResourceMines( Resource::GOLD, 1 ); case Difficulty::EXPERT: return getIncomeFromSetsOfResourceMines( Resource::GOLD, 1 ) + getBonusForCastles(); case Difficulty::IMPOSSIBLE: return getIncomeFromSetsOfResourceMines( Resource::GOLD, 2 ) + getBonusForCastles(); default: break; } return {}; } double Difficulty::getGoldIncomeBonusForAI( const int difficulty ) { switch ( difficulty ) { case Difficulty::EASY: // It is deduction from the income. return -0.25; default: break; } return 0; } double Difficulty::getArmyStrengthRatioForAIRetreat( const int difficulty ) { switch ( difficulty ) { case Difficulty::NORMAL: return 100.0 / 7.5; case Difficulty::HARD: case Difficulty::EXPERT: return 100.0 / 8.5; case Difficulty::IMPOSSIBLE: return 100.0 / 10.0; default: break; } return 100.0 / 6.0; } uint32_t Difficulty::GetDimensionDoorLimitForAI( int difficulty ) { switch ( difficulty ) { case Difficulty::EASY: return 1; case Difficulty::NORMAL: return 2; case Difficulty::HARD: return 3; default: break; } return UINT32_MAX; } bool Difficulty::areAIHeroRolesAllowed( const int difficulty ) { switch ( difficulty ) { case Difficulty::EASY: return false; case Difficulty::NORMAL: case Difficulty::HARD: case Difficulty::EXPERT: case Difficulty::IMPOSSIBLE: return true; default: // Did you add a new difficulty level? Add the logic above! assert( 0 ); break; } return true; } int Difficulty::getMinStatDiffForAIHeroesMeeting( const int difficulty ) { switch ( difficulty ) { case Difficulty::EASY: // Easy difficulty still allows to merge armies but only if the difference in stats is huge. return 10; case Difficulty::NORMAL: case Difficulty::HARD: case Difficulty::EXPERT: case Difficulty::IMPOSSIBLE: return 2; default: // Did you add a new difficulty level? Add the logic above! assert( 0 ); break; } return 2; } bool Difficulty::allowAIToSplitWeakStacks( const int difficulty ) { switch ( difficulty ) { case Difficulty::EASY: case Difficulty::NORMAL: return false; default: break; } return true; } bool Difficulty::allowAIToDevelopCastlesOnDay( const int difficulty, const bool isCampaign, const uint32_t day ) { switch ( difficulty ) { case Difficulty::EASY: return isCampaign || day % 2 == 0; default: break; } return true; } bool Difficulty::allowAIToBuildCastleBuilding( const int difficulty, const bool isCampaign, const BuildingType building ) { switch ( difficulty ) { case Difficulty::EASY: // Only the construction of the corresponding dwelling is limited, but not its upgrade return isCampaign || ( building != DWELLING_MONSTER6 && building != BUILD_MAGEGUILD5 ); default: break; } return true; } fheroes2-1.1.6+dfsg/src/fheroes2/game/difficulty.h000066400000000000000000000071421476115357100217210ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "resource.h" class Kingdom; enum BuildingType : uint32_t; namespace Difficulty { // !!! IMPORTANT !!! // Do NOT change the order of the items as they are used for the map format. enum DifficultyLevel : int { EASY, NORMAL, HARD, EXPERT, IMPOSSIBLE }; std::string String( int ); // Returns an extra resource bonus for AI based on difficulty level. Funds getResourceIncomeBonusForAI( const int difficulty, const Kingdom & kingdom ); // Returns an extra gold bonus modifier for AI based on difficulty level. This modifier is applied after applying the resource income bonus. double getGoldIncomeBonusForAI( const int difficulty ); // Returns the ratio of the strength of the enemy army to the strength of the AI army, above which the AI decides to surrender or retreat from the battlefield double getArmyStrengthRatioForAIRetreat( const int difficulty ); // Returns the limit on the number of times the Dimension Door spell can be cast, which is applied to each of the AI-controlled heroes individually during one AI // turn uint32_t GetDimensionDoorLimitForAI( int difficulty ); bool areAIHeroRolesAllowed( const int difficulty ); // Returns the minimum advantage in stats (i.e. the sum of the levels of primary and secondary skills) that a hero must have in order to allow another hero with the // same role to meet on his own initiative with this hero to exchange armies and artifacts int getMinStatDiffForAIHeroesMeeting( const int difficulty ); // Returns true if AI should avoid having free slots in the army bool allowAIToSplitWeakStacks( const int difficulty ); bool allowAIToDevelopCastlesOnDay( const int difficulty, const bool isCampaign, const uint32_t day ); bool allowAIToBuildCastleBuilding( const int difficulty, const bool isCampaign, const BuildingType building ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/fheroes2.cpp000066400000000000000000000312171476115357100216270ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdouble-promotion" #pragma GCC diagnostic ignored "-Wold-style-cast" #pragma GCC diagnostic ignored "-Wswitch-default" #endif #include #include // IWYU pragma: keep #include // Managing compiler warnings for SDL headers #if defined( __GNUC__ ) #pragma GCC diagnostic pop #endif #if defined( _WIN32 ) #include #endif #include "agg.h" #include "agg_image.h" #include "audio_manager.h" #include "core.h" #include "cursor.h" #include "dir.h" #include "embedded_image.h" #include "exception.h" #include "game.h" #include "game_logo.h" #include "game_video.h" #include "game_video_type.h" #include "h2d.h" #include "icn.h" #include "image.h" #include "image_palette.h" #include "localevent.h" #include "logging.h" #include "render_processor.h" #include "screen.h" #include "settings.h" #include "system.h" #include "timing.h" #include "ui_tool.h" #include "zzlib.h" namespace { std::string GetCaption() { return std::string( "fheroes2 engine, version: " + Settings::GetVersion() ); } void ReadConfigs() { const std::string configurationFileName( Settings::configFileName ); const std::string confFile = Settings::GetLastFile( "", configurationFileName ); Settings & conf = Settings::Get(); if ( System::IsFile( confFile ) && conf.Read( confFile ) ) { LocalEvent::Get().SetControllerPointerSpeed( conf.controllerPointerSpeed() ); } else { conf.Save( configurationFileName ); // Fullscreen mode can be enabled by default for some devices, we need to forcibly // synchronize reality with the default config if config file was not read conf.setFullScreen( conf.FullScreen() ); } } void InitConfigDir() { const std::string configDir = System::GetConfigDirectory( "fheroes2" ); System::MakeDirectory( configDir ); } void InitDataDir() { const std::string dataDir = System::GetDataDirectory( "fheroes2" ); if ( dataDir.empty() ) { return; } const std::string dataFiles = System::concatPath( dataDir, "files" ); const std::string dataFilesSave = System::concatPath( dataFiles, "save" ); // This call will also create dataDir and dataFiles System::MakeDirectory( dataFilesSave ); } void displayMissingResourceWindow() { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Image & image = Compression::CreateImageFromZlib( 290, 190, errorMessage, sizeof( errorMessage ), false ); display.fill( 0 ); fheroes2::Resize( image, display ); display.render(); LocalEvent & le = LocalEvent::Get(); // Display the message for 5 seconds so that the user sees it enough and not immediately closes without reading properly. const fheroes2::Time timer; bool closeWindow = false; while ( le.HandleEvents( true, true ) ) { if ( closeWindow && timer.getS() >= 5 ) { break; } if ( le.isAnyKeyPressed() || le.MouseClickLeft() ) { closeWindow = true; } } } class DisplayInitializer { public: DisplayInitializer() { const Settings & conf = Settings::Get(); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::ResolutionInfo bestResolution{ conf.currentResolutionInfo() }; if ( conf.isFirstGameRun() && System::isHandheldDevice() ) { // We do not show resolution dialog for first run on handheld devices. In this case it is wise to set 'widest' resolution by default. const std::vector resolutions = fheroes2::engine().getAvailableResolutions(); for ( const fheroes2::ResolutionInfo & info : resolutions ) { if ( info.gameWidth > bestResolution.gameWidth && info.gameHeight == bestResolution.gameHeight ) { bestResolution = info; } } } display.setResolution( bestResolution ); fheroes2::engine().setTitle( GetCaption() ); SDL_ShowCursor( SDL_DISABLE ); // hide system cursor fheroes2::RenderProcessor & renderProcessor = fheroes2::RenderProcessor::instance(); display.subscribe( [&renderProcessor]( std::vector & palette ) { return renderProcessor.preRenderAction( palette ); }, [&renderProcessor]() { renderProcessor.postRenderAction(); } ); // Initialize system info renderer. _systemInfoRenderer = std::make_unique(); renderProcessor.registerRenderers( [sysInfoRenderer = _systemInfoRenderer.get()]() { sysInfoRenderer->preRender(); }, [sysInfoRenderer = _systemInfoRenderer.get()]() { sysInfoRenderer->postRender(); } ); renderProcessor.startColorCycling(); // Update mouse cursor when switching between software emulation and OS mouse modes. fheroes2::cursor().registerUpdater( Cursor::Refresh ); #if !defined( MACOS_APP_BUNDLE ) const fheroes2::Image & appIcon = Compression::CreateImageFromZlib( 32, 32, iconImage, sizeof( iconImage ), true ); fheroes2::engine().setIcon( appIcon ); #endif } DisplayInitializer( const DisplayInitializer & ) = delete; DisplayInitializer & operator=( const DisplayInitializer & ) = delete; ~DisplayInitializer() { fheroes2::RenderProcessor::instance().unregisterRenderers(); fheroes2::Display & display = fheroes2::Display::instance(); display.subscribe( {}, {} ); display.release(); } private: // This member must not be initialized before Display. std::unique_ptr _systemInfoRenderer; }; class DataInitializer { public: DataInitializer() { const fheroes2::ScreenPaletteRestorer screenRestorer; try { _aggInitializer.reset( new AGG::AGGInitializer ); _h2dInitializer.reset( new fheroes2::h2d::H2DInitializer ); // Verify that the font is present and it is not corrupted. fheroes2::AGG::GetICN( ICN::FONT, 0 ); } catch ( ... ) { displayMissingResourceWindow(); throw; } } DataInitializer( const DataInitializer & ) = delete; DataInitializer & operator=( const DataInitializer & ) = delete; ~DataInitializer() = default; const std::string & getOriginalAGGFilePath() const { return _aggInitializer->getOriginalAGGFilePath(); } const std::string & getExpansionAGGFilePath() const { return _aggInitializer->getExpansionAGGFilePath(); } private: std::unique_ptr _aggInitializer; std::unique_ptr _h2dInitializer; }; // This function checks for a possible situation when a user uses a demo version // of the game. There is no 100% certain way to detect this, so assumptions are made. bool isProbablyDemoVersion() { if ( Settings::Get().isPriceOfLoyaltySupported() ) { return false; } // The demo version of the game only has 1 map. const ListFiles maps = Settings::FindFiles( "maps", ".mp2", false ); return maps.size() == 1; } } int main( int argc, char ** argv ) { // SDL2main.lib converts argv to UTF-8, but this application expects ANSI, use the original argv #if defined( _WIN32 ) assert( argc == __argc ); argv = __argv; #else (void)argc; #endif try { const fheroes2::HardwareInitializer hardwareInitializer; Logging::InitLog(); COUT( GetCaption() ) Settings & conf = Settings::Get(); conf.SetProgramPath( argv[0] ); InitConfigDir(); InitDataDir(); ReadConfigs(); std::set coreComponents{ fheroes2::SystemInitializationComponent::Audio, fheroes2::SystemInitializationComponent::Video }; #if defined( TARGET_PS_VITA ) || defined( TARGET_NINTENDO_SWITCH ) coreComponents.emplace( fheroes2::SystemInitializationComponent::GameController ); #endif const fheroes2::CoreInitializer coreInitializer( coreComponents ); DEBUG_LOG( DBG_GAME, DBG_INFO, conf.String() ) const DisplayInitializer displayInitializer; const DataInitializer dataInitializer; ListFiles midiSoundFonts; midiSoundFonts.Append( Settings::FindFiles( System::concatPath( "files", "soundfonts" ), ".sf2", false ) ); midiSoundFonts.Append( Settings::FindFiles( System::concatPath( "files", "soundfonts" ), ".sf3", false ) ); #ifdef WITH_DEBUG for ( const std::string & file : midiSoundFonts ) { DEBUG_LOG( DBG_GAME, DBG_INFO, "MIDI SoundFont to load: " << file ) } #endif const AudioManager::AudioInitializer audioInitializer( dataInitializer.getOriginalAGGFilePath(), dataInitializer.getExpansionAGGFilePath(), midiSoundFonts ); // Load palette. fheroes2::setGamePalette( AGG::getDataFromAggFile( "KB.PAL", false ) ); fheroes2::Display::instance().changePalette( nullptr, true ); // init game data Game::Init(); conf.setGameLanguage( conf.getGameLanguage() ); if ( conf.isShowIntro() ) { fheroes2::showTeamInfo(); Video::ShowVideo( "NWCLOGO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END ); Video::ShowVideo( "CYLOGO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END ); Video::ShowVideo( "H2XINTRO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END ); } try { const CursorRestorer cursorRestorer( true, Cursor::POINTER ); Game::mainGameLoop( conf.isFirstGameRun(), isProbablyDemoVersion() ); } catch ( const fheroes2::InvalidDataResources & ex ) { ERROR_LOG( ex.what() ) displayMissingResourceWindow(); return EXIT_FAILURE; } } catch ( const std::exception & ex ) { ERROR_LOG( "Exception '" << ex.what() << "' occurred during application runtime." ) return EXIT_FAILURE; } catch ( ... ) { ERROR_LOG( "An unknown exception occurred during application runtime." ) return EXIT_FAILURE; } return EXIT_SUCCESS; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game.cpp000066400000000000000000000353121476115357100210230ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game.h" #include #include #include #include #include #include #include #include #include "army.h" #include "audio.h" #include "audio_manager.h" #include "campaign_savedata.h" #include "castle.h" #include "cursor.h" #include "difficulty.h" #include "game_credits.h" #include "game_hotkeys.h" #include "game_interface.h" #include "game_static.h" #include "heroes.h" #include "localevent.h" #include "m82.h" #include "maps.h" #include "maps_fileinfo.h" #include "maps_tiles.h" #include "math_base.h" #include "mus.h" #include "players.h" #include "rand.h" #include "settings.h" #include "tools.h" #include "ui_constants.h" #include "world.h" namespace { std::string lastMapFileName; std::vector savedPlayers; bool updateSoundsOnFocusUpdate = true; bool needFadeIn{ true }; uint32_t maps_animation_frame = 0; } namespace Game { void AnimateDelaysInitialize(); } bool Game::isCampaign() { return Settings::Get().isCampaignGameType(); } int Game::getDifficulty() { const Settings & configuration = Settings::Get(); // Difficulty of non-campaign games depends only on the difficulty settings set by the player if ( !configuration.isCampaignGameType() ) { return configuration.GameDifficulty(); } // Difficulty of campaign games depends on both the difficulty of a particular campaign map and the difficulty settings set by the player int difficulty = Campaign::getCurrentScenarioDifficultyLevel().value_or( configuration.getCurrentMapInfo().difficulty ); const int difficultyAdjustment = Campaign::CampaignSaveData::Get().getDifficulty(); difficulty += difficultyAdjustment; return std::clamp( difficulty, static_cast( Difficulty::EASY ), static_cast( Difficulty::IMPOSSIBLE ) ); } void Game::LoadPlayers( const std::string & mapFileName, Players & players ) { if ( lastMapFileName != mapFileName || savedPlayers.size() != players.size() ) { return; } const auto newHumanCount = std::count_if( players.begin(), players.end(), []( const Player * player ) { return player->GetControl() == CONTROL_HUMAN; } ); const auto savedHumanCount = std::count_if( savedPlayers.begin(), savedPlayers.end(), []( const Player & player ) { return player.GetControl() == CONTROL_HUMAN; } ); if ( newHumanCount != savedHumanCount ) { return; } players.clear(); for ( const Player & p : savedPlayers ) { Player * player = new Player( p.GetColor() ); player->SetRace( p.GetRace() ); player->SetControl( p.GetControl() ); player->SetFriends( p.GetFriends() ); player->SetName( p.GetName() ); player->setHandicapStatus( p.getHandicapStatus() ); players.push_back( player ); Players::Set( p.GetColor(), player ); } } void Game::saveDifficulty( const int difficulty ) { Settings::Get().SetGameDifficulty( difficulty ); } void Game::SavePlayers( const std::string & mapFileName, const Players & players ) { lastMapFileName = mapFileName; savedPlayers.clear(); for ( const Player * p : players ) { assert( p != nullptr ); Player player( p->GetColor() ); player.SetRace( p->GetRace() ); player.SetControl( p->GetControl() ); player.SetFriends( p->GetFriends() ); player.SetName( p->GetName() ); player.setHandicapStatus( p->getHandicapStatus() ); savedPlayers.push_back( player ); } } fheroes2::GameMode Game::Credits() { ShowCredits( true ); return fheroes2::GameMode::MAIN_MENU; } bool Game::UpdateSoundsOnFocusUpdate() { return updateSoundsOnFocusUpdate; } void Game::SetUpdateSoundsOnFocusUpdate( const bool update ) { updateSoundsOnFocusUpdate = update; } bool Game::isFadeInNeeded() { return needFadeIn; } void Game::setDisplayFadeIn() { needFadeIn = true; } bool Game::validateDisplayFadeIn() { if ( needFadeIn ) { needFadeIn = false; return true; } return false; } void Game::Init() { // set global events LocalEvent & le = LocalEvent::Get(); le.setGlobalMouseMotionEventHook( Cursor::updateCursorPosition ); le.setGlobalKeyDownEventHook( Game::globalKeyDownEvent ); Game::AnimateDelaysInitialize(); Game::HotKeysLoad( Settings::GetLastFile( "", "fheroes2.key" ) ); } uint32_t Game::getAdventureMapAnimationIndex() { return maps_animation_frame; } void Game::updateAdventureMapAnimationIndex() { ++maps_animation_frame; } void Game::EnvironmentSoundMixer() { int availableChannels = Mixer::getChannelCount(); if ( availableChannels <= 2 ) { // 2 channels are left for hero's movement. return; } availableChannels -= 2; fheroes2::Point center; fheroes2::Point tilePixelOffset; Player * player = Settings::Get().GetPlayers().GetCurrent(); if ( player != nullptr ) { Focus & focus = player->GetFocus(); const Heroes * hero = focus.GetHeroes(); if ( hero != nullptr ) { center = hero->GetCenter(); tilePixelOffset = hero->getCurrentPixelOffset(); } else if ( focus.GetCastle() ) { center = focus.GetCastle()->GetCenter(); } else { center = { world.w() / 2, world.h() / 2 }; } } else { center = { world.w() / 2, world.h() / 2 }; } std::map> soundEffects; const int32_t maxOffset = 3; // Usual area of getting object sounds around a center is 7 x 7 pixel. However, in case of a moving hero we need to expand the area to make sound transition smooth. int32_t scanningOffset = maxOffset; if ( tilePixelOffset != fheroes2::Point() ) { ++scanningOffset; } std::vector positions; positions.reserve( 2 * 2 * scanningOffset * scanningOffset ); for ( int32_t y = -scanningOffset; y <= scanningOffset; ++y ) { const int32_t posY = y + center.y; for ( int32_t x = -scanningOffset; x <= scanningOffset; ++x ) { if ( Maps::isValidAbsPoint( x + center.x, posY ) ) { positions.emplace_back( x, y ); } } } // Sort positions by distance to the center. std::stable_sort( positions.begin(), positions.end(), []( const fheroes2::Point & p1, const fheroes2::Point & p2 ) { return p1.x * p1.x + p1.y * p1.y < p2.x * p2.x + p2.y * p2.y; } ); const double maxDistance = std::sqrt( ( maxOffset * maxOffset + maxOffset * maxOffset ) * fheroes2::tileWidthPx * fheroes2::tileWidthPx ); const bool is3DAudioEnabled = Settings::Get().is3DAudioEnabled(); for ( const fheroes2::Point & pos : positions ) { const M82::SoundType soundType = M82::getAdventureMapTileSound( world.getTile( pos.x + center.x, pos.y + center.y ) ); if ( soundType == M82::UNKNOWN ) { continue; } fheroes2::Point actualPosition = pos; actualPosition.x *= fheroes2::tileWidthPx; actualPosition.y *= fheroes2::tileWidthPx; actualPosition -= tilePixelOffset; const double dblDistance = std::sqrt( actualPosition.x * actualPosition.x + actualPosition.y * actualPosition.y ); if ( dblDistance >= maxDistance ) { continue; } const uint8_t distance = [maxDistance, dblDistance]() { const long dist = std::lround( dblDistance * 255 / maxDistance ); assert( dist >= 0 && dist <= 255 ); return static_cast( dist ); }(); int16_t angle = 0; if ( is3DAudioEnabled ) { // This is a schema how the direction of sound looks like: // | 0 | // | 270 90 | // | 180 | // so the direction to an object on the top is 0 degrees, on the right side - 90, bottom - 180 and left side - 270 degrees. // We need to swap X and Y axes and invert Y axis as on screen Y axis goes from top to bottom. angle = static_cast( std::atan2( actualPosition.x, -actualPosition.y ) * 180 / M_PI ); // It is extremely important to normalize the angle. if ( angle < 0 ) { angle = 360 + angle; } } std::vector & effects = soundEffects[soundType]; // If there is already a source of the same sound in this direction, then choose the one that is closer. if ( std::find_if( effects.begin(), effects.end(), [distance, angle]( AudioManager::AudioLoopEffectInfo & info ) { if ( info.angle != angle ) { return false; } info.distance = std::min( distance, info.distance ); return true; } ) != effects.end() ) { continue; } // Otherwise, use the current one for now. effects.emplace_back( angle, distance ); --availableChannels; if ( availableChannels == 0 ) { break; } } AudioManager::playLoopSoundsAsync( std::move( soundEffects ) ); } void Game::restoreSoundsForCurrentFocus() { AudioManager::ResetAudio(); switch ( Interface::GetFocusType() ) { case GameFocus::HEROES: { const Heroes * focusedHero = Interface::GetFocusHeroes(); assert( focusedHero != nullptr ); const int heroIndexPos = focusedHero->GetIndex(); if ( heroIndexPos >= 0 ) { Game::EnvironmentSoundMixer(); AudioManager::PlayMusicAsync( MUS::FromGround( world.getTile( heroIndexPos ).GetGround() ), Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); } break; } case GameFocus::CASTLE: { const Castle * focusedCastle = Interface::GetFocusCastle(); assert( focusedCastle != nullptr ); Game::EnvironmentSoundMixer(); AudioManager::PlayMusicAsync( MUS::FromGround( world.getTile( focusedCastle->GetIndex() ).GetGround() ), Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); break; } default: break; } } uint32_t Game::GetRating() { uint32_t rating = 50; switch ( Settings::Get().getCurrentMapInfo().difficulty ) { case Difficulty::NORMAL: rating += 20; break; case Difficulty::HARD: rating += 40; break; case Difficulty::EXPERT: case Difficulty::IMPOSSIBLE: rating += 80; break; default: break; } switch ( Game::getDifficulty() ) { case Difficulty::NORMAL: rating += 30; break; case Difficulty::HARD: rating += 50; break; case Difficulty::EXPERT: rating += 70; break; case Difficulty::IMPOSSIBLE: rating += 90; break; default: break; } return rating; } uint32_t Game::getGameOverScoreFactor() { uint32_t mapSizeFactor = 0; switch ( Settings::Get().getCurrentMapInfo().width ) { case Maps::SMALL: mapSizeFactor = 140; break; case Maps::MEDIUM: mapSizeFactor = 100; break; case Maps::LARGE: mapSizeFactor = 80; break; case Maps::XLARGE: mapSizeFactor = 60; break; default: break; } const uint32_t daysFactor = world.CountDay() * mapSizeFactor / 100; uint32_t daysScore = 0; if ( daysFactor <= 60 ) { daysScore = daysFactor; } else if ( daysFactor <= 120 ) { daysScore = daysFactor / 2 + 30; } else if ( daysFactor <= 360 ) { daysScore = daysFactor / 4 + 60; } else if ( daysFactor <= 600 ) { daysScore = daysFactor / 8 + 105; } else { daysScore = 180; } return ( 200 - daysScore ); } uint32_t Game::GetLostTownDays() { return GameStatic::GetGameOverLostDays(); } uint32_t Game::GetWhirlpoolPercent() { return GameStatic::GetLostOnWhirlpoolPercent(); } int Game::GetKingdomColors() { return Settings::Get().GetPlayers().GetColors(); } int Game::GetActualKingdomColors() { return Settings::Get().GetPlayers().GetActualColors(); } std::string Game::formatMonsterCount( const uint32_t count, const bool isDetailedView, const bool abbreviateNumber /* = false */ ) { if ( isDetailedView ) { return ( abbreviateNumber ? fheroes2::abbreviateNumber( count ) : std::to_string( count ) ); } return Army::SizeString( count ); } void Game::PlayPickupSound() { int wav = M82::UNKNOWN; switch ( Rand::Get( 1, 7 ) ) { case 1: wav = M82::PICKUP01; break; case 2: wav = M82::PICKUP02; break; case 3: wav = M82::PICKUP03; break; case 4: wav = M82::PICKUP04; break; case 5: wav = M82::PICKUP05; break; case 6: wav = M82::PICKUP06; break; case 7: wav = M82::PICKUP07; break; default: return; } AudioManager::PlaySound( wav ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game.h000066400000000000000000000131511476115357100204650ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "game_mode.h" class Players; class Heroes; class Castle; namespace Game { void Init(); enum { TYPE_MENU = 0, TYPE_STANDARD = 0x01, TYPE_CAMPAIGN = 0x02, TYPE_HOTSEAT = 0x04, TYPE_NETWORK = 0x08, TYPE_BATTLEONLY = 0x10, // TYPE_LOADFILE used in the Settings::LoadedGameVersion, if you change that value, // change in that function as well. TYPE_LOADFILE = 0x80, TYPE_MULTI = TYPE_HOTSEAT }; void mainGameLoop( bool isFirstGameRun, bool isProbablyDemoVersion ); fheroes2::GameMode MainMenu( const bool isFirstGameRun ); fheroes2::GameMode NewGame( const bool isProbablyDemoVersion ); fheroes2::GameMode LoadGame(); fheroes2::GameMode Credits(); fheroes2::GameMode NewStandard(); fheroes2::GameMode CampaignSelection(); fheroes2::GameMode NewSuccessionWarsCampaign(); fheroes2::GameMode NewPriceOfLoyaltyCampaign(); fheroes2::GameMode NewMulti(); fheroes2::GameMode NewHotSeat(); fheroes2::GameMode NewBattleOnly(); fheroes2::GameMode NewNetwork(); // To be utilized in future. fheroes2::GameMode LoadStandard(); fheroes2::GameMode LoadCampaign(); fheroes2::GameMode LoadMulti(); fheroes2::GameMode LoadHotseat(); fheroes2::GameMode SelectCampaignScenario( const fheroes2::GameMode prevMode, const bool allowToRestart ); fheroes2::GameMode SelectScenario( const uint8_t humanPlayerCount ); fheroes2::GameMode StartGame(); fheroes2::GameMode StartBattleOnly(); fheroes2::GameMode DisplayLoadGameDialog(); fheroes2::GameMode CompleteCampaignScenario( const bool isLoadingSaveFile ); fheroes2::GameMode DisplayHighScores( const bool isCampaign ); bool isSuccessionWarsCampaignPresent(); bool isPriceOfLoyaltyCampaignPresent(); // Starts playback of ambient sounds produced by surrounding objects located in an area close to the current game focus. void EnvironmentSoundMixer(); void restoreSoundsForCurrentFocus(); bool UpdateSoundsOnFocusUpdate(); void SetUpdateSoundsOnFocusUpdate( const bool update ); bool isFadeInNeeded(); // Set display fade-in state to true. void setDisplayFadeIn(); // If display fade-in state is set reset it to false and return true. Otherwise return false. bool validateDisplayFadeIn(); int GetKingdomColors(); int GetActualKingdomColors(); void DialogPlayers( int color, std::string title, std::string message ); uint32_t getAdventureMapAnimationIndex(); void updateAdventureMapAnimationIndex(); uint32_t GetRating(); uint32_t getGameOverScoreFactor(); uint32_t GetLostTownDays(); uint32_t GetWhirlpoolPercent(); uint8_t SelectCountPlayers(); void PlayPickupSound(); void OpenHeroesDialog( Heroes & hero, bool updateFocus, const bool renderBackgroundDialog, const bool disableDismiss = false ); void OpenCastleDialog( Castle & castle, bool updateFocus = true, const bool renderBackgroundDialog = true ); void LoadPlayers( const std::string & mapFileName, Players & players ); void SavePlayers( const std::string & mapFileName, const Players & players ); // Returns true if the currently active game is a campaign, otherwise returns false bool isCampaign(); // Returns the difficulty level of the currently active game, depending on its type (see the implementation for details) int getDifficulty(); void saveDifficulty( const int difficulty ); int32_t GetStep4Player( const int32_t currentId, const int32_t width, const int32_t totalCount ); // Returns the string representation of the monster count. If a detailed view is requested, the exact number is returned // (unless the abbreviated number is requested), otherwise, a qualitative estimate is returned (Few, Several, etc). std::string formatMonsterCount( const uint32_t count, const bool isDetailedView, const bool abbreviateNumber = false ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_campaign.cpp000066400000000000000000002324251476115357100226660ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "army.h" #include "army_troop.h" #include "artifact.h" #include "audio.h" #include "audio_manager.h" #include "battle.h" #include "campaign_data.h" #include "campaign_savedata.h" #include "campaign_scenariodata.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "game.h" // IWYU pragma: associated #include "game_credits.h" #include "game_hotkeys.h" #include "game_io.h" #include "game_mode.h" #include "game_over.h" #include "game_video.h" #include "game_video_type.h" #include "heroes.h" #include "highscores.h" #include "icn.h" #include "image.h" #include "kingdom.h" #include "localevent.h" #include "logging.h" #include "maps_fileinfo.h" #include "math_base.h" #include "monster.h" #include "mus.h" #include "pal.h" #include "players.h" #include "race.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_campaign.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" namespace { enum ScenarioIcon : uint32_t { SCENARIO_ICON_CLEARED = 0, SCENARIO_ICON_AVAILABLE = 1, SCENARIO_ICON_UNAVAILABLE = 2, }; const int betrayalScenarioId = 4; std::vector getCampaignIconOffsets( const int campaignId, const bool archibaldLowerBetrayalBranch = false ) { switch ( campaignId ) { case Campaign::ROLAND_CAMPAIGN: return { { 0, 1 }, { 2, 1 }, { 3, 0 }, { 4, 1 }, { 6, 1 }, { 8, 1 }, { 10, 2 }, { 10, 0 }, { 12, 1 }, { 14, 1 }, { 6, 2 } }; case Campaign::ARCHIBALD_CAMPAIGN: if ( archibaldLowerBetrayalBranch ) { return { { 0, 1 }, { 2, 1 }, { 4, 0 }, { 4, 2 }, { 6, 1 }, { 8, 1 }, { 9, 0 }, { 10, 1 }, { 12, 0 }, { 12, 2 }, { 14, 1 }, { 6, 2 } }; } else { return { { 0, 1 }, { 2, 1 }, { 4, 0 }, { 4, 2 }, { 6, 1 }, { 8, 1 }, { 9, 0 }, { 10, 1 }, { 12, 0 }, { 12, 2 }, { 14, 1 }, { 6, 0 } }; } case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: return { { 0, 0 }, { 2, 0 }, { 4, 1 }, { 4, 0 }, { 6, 1 }, { 7, 0 }, { 9, 1 }, { 10, 0 } }; case Campaign::DESCENDANTS_CAMPAIGN: return { { 0, 1 }, { 2, 1 }, { 4, 0 }, { 4, 2 }, { 6, 1 }, { 8, 2 }, { 8, 0 }, { 10, 1 } }; case Campaign::WIZARDS_ISLE_CAMPAIGN: return { { 0, 0 }, { 2, 0 }, { 4, 1 }, { 6, 0 } }; case Campaign::VOYAGE_HOME_CAMPAIGN: return { { 0, 0 }, { 2, 0 }, { 4, 0 }, { 4, 1 } }; default: // Implementing a new campaign? Add a new case! assert( 0 ); return {}; } } bool isBetrayalScenario( const Campaign::ScenarioInfoId & scenarioInfoId ) { // Betrayal scenario is a special scenario of switching between campaigns. Next scenarios after this must have different campaign ID. for ( const Campaign::ScenarioInfoId & nextScenario : Campaign::CampaignData::getScenariosAfter( scenarioInfoId ) ) { if ( nextScenario.campaignId != scenarioInfoId.campaignId ) { return true; } } return false; } void getScenarioIconId( const Campaign::ScenarioInfoId & scenarioInfoId, int & iconsId, uint32_t & iconStatusOffset, uint32_t & selectedIconIdx ) { iconsId = ICN::UNKNOWN; iconStatusOffset = 0; selectedIconIdx = 0; switch ( scenarioInfoId.campaignId ) { case Campaign::ROLAND_CAMPAIGN: iconsId = ICN::CAMPXTRG; iconStatusOffset = 10; selectedIconIdx = isBetrayalScenario( scenarioInfoId ) ? 17 : 14; return; case Campaign::ARCHIBALD_CAMPAIGN: iconsId = ICN::CAMPXTRE; iconStatusOffset = 10; selectedIconIdx = isBetrayalScenario( scenarioInfoId ) ? 14 : 17; return; case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: iconsId = ICN::X_CMPEXT; iconStatusOffset = 0; selectedIconIdx = 4; return; case Campaign::DESCENDANTS_CAMPAIGN: iconsId = ICN::X_CMPEXT; iconStatusOffset = 0; selectedIconIdx = 7; return; case Campaign::WIZARDS_ISLE_CAMPAIGN: iconsId = ICN::X_CMPEXT; iconStatusOffset = 0; selectedIconIdx = 10; return; case Campaign::VOYAGE_HOME_CAMPAIGN: iconsId = ICN::X_CMPEXT; iconStatusOffset = 0; selectedIconIdx = 13; return; default: // Implementing a new campaign? Add a new case! assert( 0 ); return; } } void DrawCampaignScenarioIcon( const int icnId, const uint32_t iconIdx, const fheroes2::Point & offset, const int posX, const int posY ) { const fheroes2::Sprite & icon = fheroes2::AGG::GetICN( icnId, iconIdx ); fheroes2::Blit( icon, fheroes2::Display::instance(), offset.x + posX, offset.y + posY ); } void addScenarioButton( fheroes2::ButtonGroup & buttonGroup, const int buttonId, const Campaign::ScenarioInfoId & scenarioInfo, const std::vector & availableMaps, const std::vector & clearedMaps, const fheroes2::Point & trackOffset, const bool archibaldLowerBetrayalBranch ) { const int deltaY = 42; const int deltaX = 37; const std::vector & iconOffsets = getCampaignIconOffsets( scenarioInfo.campaignId, archibaldLowerBetrayalBranch ); assert( scenarioInfo.scenarioId >= 0 && static_cast( scenarioInfo.scenarioId ) < iconOffsets.size() ); if ( scenarioInfo.scenarioId < 0 || static_cast( scenarioInfo.scenarioId ) >= iconOffsets.size() ) { return; } fheroes2::Point offset = iconOffsets[scenarioInfo.scenarioId]; offset.x *= deltaX; offset.y *= deltaY; // Price of loyalty's track doesn't respect the standard offset between icons. if ( scenarioInfo.campaignId == Campaign::CampaignID::PRICE_OF_LOYALTY_CAMPAIGN && scenarioInfo.scenarioId >= 5 ) { switch ( scenarioInfo.scenarioId ) { case 5: offset.x -= 2; break; case 6: offset.x -= 1; break; case 7: offset.x -= 4; break; default: break; } } offset.x -= 2; offset.y -= 2; int iconsId = -1; uint32_t iconStatusOffset = 0; uint32_t selectedIconIdx = 0; getScenarioIconId( scenarioInfo, iconsId, iconStatusOffset, selectedIconIdx ); // available scenario (one of which should be selected) if ( std::find( availableMaps.begin(), availableMaps.end(), scenarioInfo ) != availableMaps.end() ) { const fheroes2::Sprite & availableIcon = fheroes2::AGG::GetICN( iconsId, iconStatusOffset + SCENARIO_ICON_AVAILABLE ); const fheroes2::Sprite & selectedIcon = fheroes2::AGG::GetICN( iconsId, selectedIconIdx ); buttonGroup.createButton( trackOffset.x + offset.x, trackOffset.y + offset.y, availableIcon, selectedIcon, buttonId ); } // cleared scenario else if ( std::find( clearedMaps.begin(), clearedMaps.end(), scenarioInfo ) != clearedMaps.end() ) { if ( isBetrayalScenario( scenarioInfo ) ) { assert( static_cast( betrayalScenarioId ) < iconOffsets.size() ); offset = iconOffsets[betrayalScenarioId]; offset.x *= deltaX; offset.y *= deltaY; offset.x -= 2; offset.y -= 2; } DrawCampaignScenarioIcon( iconsId, iconStatusOffset + SCENARIO_ICON_CLEARED, trackOffset, offset.x, offset.y ); } else if ( !isBetrayalScenario( scenarioInfo ) ) { DrawCampaignScenarioIcon( iconsId, iconStatusOffset + SCENARIO_ICON_UNAVAILABLE, trackOffset, offset.x, offset.y ); } } void DrawCampaignScenarioIcons( fheroes2::ButtonGroup & buttonGroup, const Campaign::CampaignData & campaignData, const fheroes2::Point & top, const int chosenScenarioId ) { std::vector prevScenarioNextMaps; const Campaign::CampaignSaveData & saveData = Campaign::CampaignSaveData::Get(); const std::vector & clearedMaps = saveData.getFinishedMaps(); std::vector availableMaps; if ( chosenScenarioId >= 0 ) { availableMaps.emplace_back( saveData.getCampaignID(), chosenScenarioId ); } else { availableMaps = saveData.isStarting() ? campaignData.getStartingScenarios() : Campaign::CampaignData::getScenariosAfter( saveData.getLastCompletedScenarioInfoID() ); } bool isBetrayalScenarioNext = false; for ( const Campaign::ScenarioInfoId & scenarioInfo : availableMaps ) { if ( isBetrayalScenario( scenarioInfo ) ) { isBetrayalScenarioNext = true; break; } } bool isBetrayalScenarioCompleted = false; if ( !isBetrayalScenarioNext ) { for ( const Campaign::ScenarioInfoId & scenarioInfo : clearedMaps ) { if ( isBetrayalScenario( scenarioInfo ) ) { isBetrayalScenarioCompleted = true; break; } } } int campaignTrack = ICN::UNKNOWN; bool archibaldLowerBetrayalBranch = false; switch ( campaignData.getCampaignID() ) { case Campaign::ROLAND_CAMPAIGN: if ( isBetrayalScenarioNext ) { campaignTrack = ICN::CTRACK04; } else if ( isBetrayalScenarioCompleted ) { campaignTrack = ICN::CTRACK02; } else { campaignTrack = ICN::CTRACK00; } break; case Campaign::ARCHIBALD_CAMPAIGN: if ( isBetrayalScenarioNext ) { // Archibald campaign is unique in terms of scenario branching so this is the only way to make it work. assert( !clearedMaps.empty() ); if ( clearedMaps.back().scenarioId == 2 ) { campaignTrack = ICN::CTRACK05; } else { assert( clearedMaps.back().scenarioId == 3 ); campaignTrack = ICN::CTRACK06; archibaldLowerBetrayalBranch = true; } } else if ( isBetrayalScenarioCompleted ) { campaignTrack = ICN::CTRACK01; } else { campaignTrack = ICN::CTRACK03; } break; case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: campaignTrack = ICN::X_TRACK1; break; case Campaign::DESCENDANTS_CAMPAIGN: campaignTrack = ICN::X_TRACK2; break; case Campaign::WIZARDS_ISLE_CAMPAIGN: campaignTrack = ICN::X_TRACK3; break; case Campaign::VOYAGE_HOME_CAMPAIGN: campaignTrack = ICN::X_TRACK4; break; default: // Implementing a new campaign? Add a new case! assert( 0 ); return; } const fheroes2::Sprite & track = fheroes2::AGG::GetICN( campaignTrack, 0 ); const fheroes2::Point trackOffset( top.x + track.x(), top.y + track.y() ); fheroes2::Blit( track, fheroes2::Display::instance(), trackOffset.x, trackOffset.y ); if ( isBetrayalScenarioCompleted ) { assert( campaignData.getCampaignID() == Campaign::ROLAND_CAMPAIGN || campaignData.getCampaignID() == Campaign::ARCHIBALD_CAMPAIGN ); const bool isRolandCurrentCampaign = ( campaignData.getCampaignID() == Campaign::ROLAND_CAMPAIGN ); const Campaign::CampaignData & beforeCampaignData = Campaign::CampaignData::getCampaignData( isRolandCurrentCampaign ? Campaign::ARCHIBALD_CAMPAIGN : Campaign::ROLAND_CAMPAIGN ); const Campaign::CampaignData & currentCampaignData = Campaign::CampaignData::getCampaignData( isRolandCurrentCampaign ? Campaign::ROLAND_CAMPAIGN : Campaign::ARCHIBALD_CAMPAIGN ); int scenarioCounter = 0; for ( const Campaign::ScenarioData & scenarioData : beforeCampaignData.getAllScenarios() ) { if ( scenarioData.getScenarioID() <= betrayalScenarioId || isBetrayalScenario( scenarioData.getScenarioInfoId() ) ) { const Campaign::ScenarioInfoId scenarioInfo{ scenarioData.getCampaignId(), scenarioData.getScenarioID() }; addScenarioButton( buttonGroup, scenarioCounter, scenarioInfo, availableMaps, clearedMaps, trackOffset, archibaldLowerBetrayalBranch ); ++scenarioCounter; } } for ( const Campaign::ScenarioData & scenarioData : currentCampaignData.getAllScenarios() ) { if ( scenarioData.getScenarioID() > betrayalScenarioId ) { const Campaign::ScenarioInfoId scenarioInfo{ scenarioData.getCampaignId(), scenarioData.getScenarioID() }; addScenarioButton( buttonGroup, scenarioCounter, scenarioInfo, availableMaps, clearedMaps, trackOffset, archibaldLowerBetrayalBranch ); ++scenarioCounter; } } } else { const std::vector & scenarios = campaignData.getAllScenarios(); for ( size_t i = 0; i < scenarios.size(); ++i ) { const Campaign::ScenarioInfoId scenarioInfo{ scenarios[i].getCampaignId(), scenarios[i].getScenarioID() }; addScenarioButton( buttonGroup, static_cast( i ), scenarioInfo, availableMaps, clearedMaps, trackOffset, archibaldLowerBetrayalBranch ); } } } void DrawCampaignScenarioDescription( const Campaign::ScenarioData & scenario, const fheroes2::Point & top ) { fheroes2::Display & display = fheroes2::Display::instance(); const std::vector & bonuses = scenario.getBonuses(); fheroes2::Text mapName( scenario.getScenarioName(), fheroes2::FontType::normalWhite() ); mapName.fitToOneRow( 200 ); mapName.draw( top.x + 197 + ( 200 - mapName.width() ) / 2, top.y + 99 - mapName.height() / 2, display ); int scenarioId = scenario.getScenarioID() + 1; if ( isBetrayalScenario( scenario.getScenarioInfoId() ) ) { assert( scenario.getCampaignId() == Campaign::ARCHIBALD_CAMPAIGN || scenario.getCampaignId() == Campaign::ROLAND_CAMPAIGN ); scenarioId = betrayalScenarioId + 1; } const fheroes2::Text campaignMapId( std::to_string( scenarioId ), fheroes2::FontType::normalWhite() ); campaignMapId.draw( top.x + 172 - campaignMapId.width() / 2, top.y + 99 - campaignMapId.height() / 2, display ); fheroes2::Text mapDescription( scenario.getDescription(), fheroes2::FontType::normalWhite() ); mapDescription.setUniformVerticalAlignment( false ); mapDescription.draw( top.x + 34, top.y + 134, 356, display ); const int textChoiceWidth = 160; const fheroes2::Point initialOffset{ top.x + 425, top.y + 211 }; for ( size_t i = 0; i < bonuses.size(); ++i ) { fheroes2::Text choice( bonuses[i].getName(), fheroes2::FontType::normalWhite() ); choice.fitToOneRow( textChoiceWidth ); choice.draw( initialOffset.x, initialOffset.y + 22 * static_cast( i ) - choice.height() / 2, display ); } } bool displayScenarioBonusPopupWindow( const Campaign::ScenarioData & scenario, const fheroes2::Point & top ) { const std::vector & bonuses = scenario.getBonuses(); if ( bonuses.empty() ) { // Nothing to process. return false; } const LocalEvent & le = LocalEvent::Get(); for ( size_t i = 0; i < bonuses.size(); ++i ) { if ( le.isMouseRightButtonPressedInArea( { top.x + 414, top.y + 198 + 22 * static_cast( i ), 200, 22 } ) ) { fheroes2::showScenarioBonusDataPopupWindow( bonuses[i] ); return true; } } return false; } void drawObtainedCampaignAwards( const Campaign::CampaignSaveData & campaignSaveData, const fheroes2::Point & top ) { if ( isBetrayalScenario( campaignSaveData.getCurrentScenarioInfoId() ) ) { return; } const int textAwardWidth = 180; // if there are more than 3 awards, we need to reduce the offset between text so that it doesn't overflow out of the text box const std::vector obtainedAwards = campaignSaveData.getObtainedCampaignAwards(); const size_t awardCount = obtainedAwards.size(); const size_t indexEnd = awardCount <= 4 ? awardCount : 4; const int yOffset = awardCount > 3 ? 16 : 22; const int initialOffsetY = 102; fheroes2::Display & display = fheroes2::Display::instance(); if ( awardCount == 0 ) { const fheroes2::Text text( _( "None" ), fheroes2::FontType::normalWhite() ); text.draw( top.x + 425, top.y + initialOffsetY - text.height() / 2, textAwardWidth, display ); return; } fheroes2::Text award; for ( size_t i = 0; i < indexEnd; ++i ) { if ( i < 3 ) { award.set( obtainedAwards[i].getName(), fheroes2::FontType::normalWhite() ); } else { // if we have exactly 4 obtained awards, display the fourth award, otherwise show "and more..." award.set( awardCount == 4 ? obtainedAwards[i].getName() : std::string( _( "and more..." ) ), fheroes2::FontType::normalWhite() ); } award.fitToOneRow( textAwardWidth ); award.draw( top.x + 425 + ( textAwardWidth - award.width() ) / 2, top.y + initialOffsetY + yOffset * static_cast( i ) - award.height() / 2, display ); } } bool displayScenarioAwardsPopupWindow( const Campaign::CampaignSaveData & campaignSaveData, const fheroes2::Point & top ) { if ( isBetrayalScenario( campaignSaveData.getCurrentScenarioInfoId() ) ) { return false; } const std::vector obtainedAwards = campaignSaveData.getObtainedCampaignAwards(); if ( obtainedAwards.empty() ) { // Nothing to process. return false; } const size_t awardCount = obtainedAwards.size(); const size_t indexEnd = awardCount <= 4 ? awardCount : 4; const int yOffset = awardCount > 3 ? 16 : 22; const LocalEvent & le = LocalEvent::Get(); for ( size_t i = 0; i < indexEnd; ++i ) { if ( le.isMouseRightButtonPressedInArea( { top.x + 414, top.y + 100 - yOffset / 2 + yOffset * static_cast( i ), 200, yOffset } ) ) { fheroes2::showAwardDataPopupWindow( obtainedAwards[i] ); return true; } } return false; } void replaceArmy( Army & army, const std::vector & troops ) { army.Clean(); const size_t size = std::min( army.Size(), troops.size() ); for ( size_t i = 0; i < size; ++i ) { Troop * troop = army.GetTroop( i ); assert( troop != nullptr ); troop->Set( troops[i] ); } assert( army.isValid() ); } void setHeroAndArmyBonus( Heroes * hero, const Campaign::ScenarioInfoId & scenarioInfoId ) { switch ( scenarioInfoId.campaignId ) { case Campaign::ARCHIBALD_CAMPAIGN: { if ( scenarioInfoId.scenarioId != 6 ) { assert( 0 ); // no other scenario has this bonus return; } switch ( hero->GetRace() ) { case Race::NECR: replaceArmy( hero->GetArmy(), { { Monster::SKELETON, 50 }, { Monster::ROYAL_MUMMY, 18 }, { Monster::VAMPIRE_LORD, 8 } } ); break; case Race::WRLK: replaceArmy( hero->GetArmy(), { { Monster::CENTAUR, 40 }, { Monster::GARGOYLE, 24 }, { Monster::GRIFFIN, 18 } } ); break; case Race::BARB: replaceArmy( hero->GetArmy(), { { Monster::ORC_CHIEF, 12 }, { Monster::OGRE, 18 }, { Monster::GOBLIN, 40 } } ); break; default: assert( 0 ); // bonus changed? } const uint32_t exp = hero->GetExperience(); if ( exp < 5000 ) { hero->IncreaseExperience( 5000 - exp, true ); } break; } default: assert( 0 ); // some new campaign that uses this bonus? } } Heroes * getHeroToApplyBonusOrAwards( const Campaign::ScenarioInfoId & scenarioInfoId, const Kingdom & kingdom ) { { static const std::map, int> targetHeroes = { // Final Justice { { Campaign::ROLAND_CAMPAIGN, 9 }, Heroes::ROLAND }, // Apocalypse { { Campaign::ARCHIBALD_CAMPAIGN, 10 }, Heroes::ARCHIBALD }, // Blood is Thicker { { Campaign::VOYAGE_HOME_CAMPAIGN, 3 }, Heroes::GALLAVANT } }; const auto iter = targetHeroes.find( { scenarioInfoId.campaignId, scenarioInfoId.scenarioId } ); if ( iter != targetHeroes.end() ) { // The "special" kingdom heroes may have the ID of another hero, but a custom name and portrait, // so the search should be performed by the portrait ID for ( Heroes * hero : kingdom.GetHeroes() ) { assert( hero != nullptr ); if ( hero->getPortraitId() == iter->second ) { return hero; } } DEBUG_LOG( DBG_GAME, DBG_WARN, "the hero to whom bonuses or awards should be applied has not been found" << ", campaign id: " << scenarioInfoId.campaignId << ", scenario id: " << scenarioInfoId.scenarioId ) } } { static const std::map, int> targetRaces = { // Defender { { Campaign::ROLAND_CAMPAIGN, 5 }, Race::SORC }, // The Wayward Son { { Campaign::DESCENDANTS_CAMPAIGN, 2 }, Race::SORC }, // The Epic Battle { { Campaign::DESCENDANTS_CAMPAIGN, 7 }, Race::SORC } }; const auto iter = targetRaces.find( { scenarioInfoId.campaignId, scenarioInfoId.scenarioId } ); if ( iter != targetRaces.end() ) { for ( Heroes * hero : kingdom.GetHeroes() ) { assert( hero != nullptr ); if ( hero->GetRace() == iter->second ) { return hero; } } DEBUG_LOG( DBG_GAME, DBG_WARN, "the hero to whom bonuses or awards should be applied has not been found" << ", campaign id: " << scenarioInfoId.campaignId << ", scenario id: " << scenarioInfoId.scenarioId ) } } // By default, bonuses and awards are applied to the best hero of the kingdom return kingdom.GetBestHero(); } void SetScenarioBonus( const Campaign::ScenarioInfoId & scenarioInfoId, const Campaign::ScenarioBonusData & scenarioBonus ) { const Players & sortedPlayers = Settings::Get().GetPlayers(); for ( const Player * player : sortedPlayers ) { if ( player == nullptr ) { continue; } if ( !player->isControlHuman() ) { continue; } Kingdom & kingdom = world.GetKingdom( player->GetColor() ); switch ( scenarioBonus._type ) { case Campaign::ScenarioBonusData::RESOURCES: kingdom.AddFundsResource( Funds( scenarioBonus._subType, scenarioBonus._amount ) ); break; case Campaign::ScenarioBonusData::ARTIFACT: { Heroes * hero = getHeroToApplyBonusOrAwards( scenarioInfoId, kingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { Artifact artifact( scenarioBonus._subType ); if ( artifact == Artifact::SPELL_SCROLL ) { artifact.SetSpell( scenarioBonus._artifactSpellId ); } hero->PickupArtifact( artifact ); } break; } case Campaign::ScenarioBonusData::TROOP: { Heroes * hero = getHeroToApplyBonusOrAwards( scenarioInfoId, kingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { hero->GetArmy().JoinTroop( Troop( Monster( scenarioBonus._subType ), scenarioBonus._amount ) ); } break; } case Campaign::ScenarioBonusData::SPELL: { Heroes * hero = getHeroToApplyBonusOrAwards( scenarioInfoId, kingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { hero->AppendSpellToBook( scenarioBonus._subType, true ); } break; } case Campaign::ScenarioBonusData::STARTING_RACE: Players::SetPlayerRace( player->GetColor(), scenarioBonus._subType ); break; case Campaign::ScenarioBonusData::STARTING_RACE_AND_ARMY: { Heroes * hero = getHeroToApplyBonusOrAwards( scenarioInfoId, kingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { setHeroAndArmyBonus( hero, scenarioInfoId ); } break; } case Campaign::ScenarioBonusData::SKILL_PRIMARY: { Heroes * hero = getHeroToApplyBonusOrAwards( scenarioInfoId, kingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { for ( int32_t i = 0; i < scenarioBonus._amount; ++i ) { hero->IncreasePrimarySkill( scenarioBonus._subType ); } } break; } case Campaign::ScenarioBonusData::SKILL_SECONDARY: { Heroes * hero = getHeroToApplyBonusOrAwards( scenarioInfoId, kingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { hero->LearnSkill( Skill::Secondary( scenarioBonus._subType, scenarioBonus._amount ) ); } break; } default: assert( 0 ); } } } // apply only the ones that are applied at the start (artifact, spell, carry-over troops) // the rest will be applied based on the situation required void applyObtainedCampaignAwards( const Campaign::ScenarioInfoId & currentScenarioInfoId, const std::vector & awards ) { const int humanColor = Players::HumanColors(); assert( Color::Count( humanColor ) == 1 ); const Players & sortedPlayers = Settings::Get().GetPlayers(); const Kingdom & humanKingdom = world.GetKingdom( humanColor ); for ( size_t i = 0; i < awards.size(); ++i ) { if ( currentScenarioInfoId.scenarioId < awards[i]._startScenarioID ) { continue; } switch ( awards[i]._type ) { case Campaign::CampaignAwardData::TYPE_GET_ARTIFACT: { Heroes * hero = getHeroToApplyBonusOrAwards( currentScenarioInfoId, humanKingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { hero->PickupArtifact( Artifact( awards[i]._subType ) ); // Some artifacts increase the Spell Power of the hero we have to set spell points to maximum. hero->SetSpellPoints( std::max( hero->GetSpellPoints(), hero->GetMaxSpellPoints() ) ); } break; } case Campaign::CampaignAwardData::TYPE_GET_SPELL: { Heroes * hero = getHeroToApplyBonusOrAwards( currentScenarioInfoId, humanKingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { hero->AppendSpellToBook( awards[i]._subType, true ); } break; } case Campaign::CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO: for ( const Player * player : sortedPlayers ) { const Kingdom & kingdom = world.GetKingdom( player->GetColor() ); const VecHeroes & heroes = kingdom.GetHeroes(); for ( size_t j = 0; j < heroes.size(); ++j ) { assert( heroes[j] != nullptr ); if ( heroes[j]->GetID() == awards[i]._subType ) { heroes[j]->Dismiss( Battle::RESULT_LOSS ); break; } } } break; case Campaign::CampaignAwardData::TYPE_CARRY_OVER_FORCES: { Heroes * hero = getHeroToApplyBonusOrAwards( currentScenarioInfoId, humanKingdom ); assert( hero != nullptr ); if ( hero != nullptr ) { Army & heroArmy = hero->GetArmy(); const std::vector & carryOverTroops = Campaign::CampaignSaveData::Get().getCarryOverTroops(); if ( std::any_of( carryOverTroops.begin(), carryOverTroops.end(), []( const Troop & troop ) { return troop.isValid(); } ) ) { replaceArmy( heroArmy, carryOverTroops ); } else { heroArmy.Reset(); } } break; } default: break; } } } void playPreviousScenarioVideo() { const Campaign::CampaignSaveData & saveData = Campaign::CampaignSaveData::Get(); if ( saveData.isStarting() ) { return; } const Campaign::ScenarioInfoId & lastCompletedScenarioInfoId = saveData.getLastCompletedScenarioInfoID(); const Campaign::CampaignData & campaignData = Campaign::CampaignData::getCampaignData( lastCompletedScenarioInfoId.campaignId ); const std::vector & scenarios = campaignData.getAllScenarios(); assert( lastCompletedScenarioInfoId.scenarioId >= 0 && static_cast( lastCompletedScenarioInfoId.scenarioId ) < scenarios.size() ); const Campaign::ScenarioData & completedScenario = scenarios[lastCompletedScenarioInfoId.scenarioId]; if ( !completedScenario.getEndScenarioVideoPlayback().empty() ) { AudioManager::ResetAudio(); for ( const Campaign::ScenarioIntroVideoInfo & videoInfo : completedScenario.getEndScenarioVideoPlayback() ) { Video::ShowVideo( videoInfo.fileName, videoInfo.action ); } AudioManager::ResetAudio(); } } void playCurrentScenarioVideo() { const Campaign::CampaignSaveData & saveData = Campaign::CampaignSaveData::Get(); const Campaign::ScenarioInfoId & currentScenarioInfoId = saveData.getCurrentScenarioInfoId(); const Campaign::CampaignData & campaignData = Campaign::CampaignData::getCampaignData( currentScenarioInfoId.campaignId ); const std::vector & scenarios = campaignData.getAllScenarios(); assert( currentScenarioInfoId.scenarioId >= 0 && static_cast( currentScenarioInfoId.scenarioId ) < scenarios.size() ); const Campaign::ScenarioData & scenario = scenarios[currentScenarioInfoId.scenarioId]; if ( !scenario.getStartScenarioVideoPlayback().empty() ) { AudioManager::ResetAudio(); for ( const Campaign::ScenarioIntroVideoInfo & videoInfo : scenario.getStartScenarioVideoPlayback() ) { Video::ShowVideo( videoInfo.fileName, videoInfo.action ); } AudioManager::ResetAudio(); } } int getCampaignButtonId( const int campaignId ) { switch ( campaignId ) { case Campaign::ROLAND_CAMPAIGN: return ICN::GOOD_CAMPAIGN_BUTTONS; case Campaign::ARCHIBALD_CAMPAIGN: return ICN::EVIL_CAMPAIGN_BUTTONS; case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: case Campaign::DESCENDANTS_CAMPAIGN: case Campaign::WIZARDS_ISLE_CAMPAIGN: case Campaign::VOYAGE_HOME_CAMPAIGN: return ICN::POL_CAMPAIGN_BUTTONS; default: // Implementing a new campaign? Add a new case! assert( 0 ); return ICN::UNKNOWN; } } void drawCampaignNameHeader( const int campaignId, fheroes2::Image & output, const fheroes2::Point & offset ) { // Add extra image header if supported uint32_t campaignNameHeader = ICN::UNKNOWN; switch ( campaignId ) { case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: campaignNameHeader = 15; break; case Campaign::DESCENDANTS_CAMPAIGN: campaignNameHeader = 16; break; case Campaign::WIZARDS_ISLE_CAMPAIGN: campaignNameHeader = 17; break; case Campaign::VOYAGE_HOME_CAMPAIGN: campaignNameHeader = 18; break; default: return; } const fheroes2::Sprite & header = fheroes2::AGG::GetICN( ICN::X_CMPEXT, campaignNameHeader ); fheroes2::Blit( header, output, offset.x + 24, offset.y + 25 ); } void playCampaignMusic( const int campaignId ) { switch ( campaignId ) { case Campaign::ROLAND_CAMPAIGN: case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: case Campaign::DESCENDANTS_CAMPAIGN: case Campaign::WIZARDS_ISLE_CAMPAIGN: case Campaign::VOYAGE_HOME_CAMPAIGN: AudioManager::PlayMusicAsync( MUS::ROLAND_CAMPAIGN_SCREEN, Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ); break; case Campaign::ARCHIBALD_CAMPAIGN: AudioManager::PlayMusicAsync( MUS::ARCHIBALD_CAMPAIGN_SCREEN, Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ); break; default: // Implementing a new campaign? Add a new case! assert( 0 ); break; } } std::string getCampaignDifficultyText( const int32_t difficulty ) { switch ( difficulty ) { case Campaign::CampaignDifficulty::Easy: return { _( "Easy" ) }; case Campaign::CampaignDifficulty::Normal: // Original campaign difficulty. return { _( "Normal" ) }; case Campaign::CampaignDifficulty::Hard: return { _( "Hard" ) }; default: // Did you add a new campaign difficulty? Add the logic above! assert( 0 ); return {}; } } int32_t setCampaignDifficulty( int32_t currentDifficulty, const int32_t maximumAllowedDifficulty ) { // It's better to have frame border width value divisible to 2 and 3 w/o remainder. const fheroes2::StandardWindow frameborder( 300, 284, true ); const fheroes2::Rect & windowRoi = frameborder.activeArea(); const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int buttonIcnId = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; const fheroes2::Sprite & buttonSprite = fheroes2::AGG::GetICN( buttonIcnId, 0 ); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Rect buttonMaxRoi( windowRoi.x + 5, windowRoi.y, windowRoi.width - 10, windowRoi.height - 5 ); fheroes2::ButtonSprite buttonOk = fheroes2::makeButtonWithShadow( buttonMaxRoi.x + ( buttonMaxRoi.width - buttonSprite.width() ) / 2, buttonMaxRoi.y + buttonMaxRoi.height - buttonSprite.height(), fheroes2::AGG::GetICN( buttonIcnId, 0 ), fheroes2::AGG::GetICN( buttonIcnId, 1 ), display ); buttonOk.draw(); const fheroes2::Text caption( _( "Campaign Difficulty" ), fheroes2::FontType::normalYellow() ); caption.draw( windowRoi.x + ( windowRoi.width - caption.width() ) / 2, windowRoi.y + 10, display ); const int32_t iconSize = 65; const int32_t iconShadowSize = 4; const int32_t fullIconSize = iconSize + iconShadowSize; const int32_t pawnIconOffsetX = windowRoi.x - iconShadowSize + ( windowRoi.width - iconSize ) / 2 - windowRoi.width / 3; const int32_t horseIconOffsetX = windowRoi.x - iconShadowSize + ( windowRoi.width - iconSize ) / 2; const int32_t rookIconOffsetX = windowRoi.x - iconShadowSize + ( windowRoi.width - iconSize ) / 2 + windowRoi.width / 3; const std::array copyFromArea{ fheroes2::Rect{ 20, 94, fullIconSize, fullIconSize }, fheroes2::Rect{ 97, 94, fullIconSize, fullIconSize }, fheroes2::Rect{ 173, 94, fullIconSize, fullIconSize } }; const std::array copyToOffset{ fheroes2::Point{ pawnIconOffsetX, windowRoi.y + 40 }, fheroes2::Point{ horseIconOffsetX, windowRoi.y + 40 }, fheroes2::Point{ rookIconOffsetX, windowRoi.y + 40 } }; const fheroes2::Sprite & chessIcon = fheroes2::AGG::GetICN( ICN::NGHSBKG, 0 ); for ( size_t i = 0; i < copyToOffset.size(); ++i ) { fheroes2::Copy( chessIcon, copyFromArea[i].x, copyFromArea[i].y, display, copyToOffset[i].x, copyToOffset[i].y, copyFromArea[i].width, copyFromArea[i].height ); } if ( isEvilInterface ) { const std::vector & goodToEvilPalette = PAL::GetPalette( PAL::PaletteType::GOOD_TO_EVIL_INTERFACE ); for ( size_t i = 0; i < copyToOffset.size(); ++i ) { fheroes2::ApplyPalette( display, copyToOffset[i].x, copyToOffset[i].y, display, copyToOffset[i].x, copyToOffset[i].y, copyFromArea[i].width, copyFromArea[i].height, goodToEvilPalette ); } } const fheroes2::Sprite & selectionImage = fheroes2::AGG::GetICN( ICN::NGEXTRA, 62 ); fheroes2::MovableSprite selection( selectionImage ); const char * easyDescription = _( "Choose this difficulty to experience the game's story with less challenge. The AI will be weaker than at Normal difficulty." ); const char * normalDescription = _( "Choose this difficulty to experience the campaign as per the original design." ); const char * hardDescription = _( "Choose this difficulty if you want more challenge. The AI will be stronger than at Normal difficulty." ); const std::array difficultyArea{ fheroes2::Rect( copyToOffset[0].x + 1, windowRoi.y + 37, selectionImage.width(), selectionImage.height() ), fheroes2::Rect( copyToOffset[1].x + 1, windowRoi.y + 37, selectionImage.width(), selectionImage.height() ), fheroes2::Rect( copyToOffset[2].x + 1, windowRoi.y + 37, selectionImage.width(), selectionImage.height() ) }; const std::array iconArea{ fheroes2::Rect( difficultyArea[0].x + iconShadowSize, difficultyArea[0].y + iconShadowSize, iconSize - 1, iconSize - 1 ), fheroes2::Rect( difficultyArea[1].x + iconShadowSize, difficultyArea[1].y + iconShadowSize, iconSize - 1, iconSize - 1 ), fheroes2::Rect( difficultyArea[2].x + iconShadowSize, difficultyArea[2].y + iconShadowSize, iconSize - 1, iconSize - 1 ) }; const char * currentDescription = nullptr; switch ( currentDifficulty ) { case Campaign::CampaignDifficulty::Easy: currentDescription = easyDescription; selection.setPosition( difficultyArea[0].x, difficultyArea[0].y ); break; case Campaign::CampaignDifficulty::Normal: currentDescription = normalDescription; selection.setPosition( difficultyArea[1].x, difficultyArea[1].y ); break; case Campaign::CampaignDifficulty::Hard: currentDescription = hardDescription; selection.setPosition( difficultyArea[2].x, difficultyArea[2].y ); break; default: // Did you add a new difficulty level for campaigns? Add the logic above! assert( 0 ); break; } const std::array allowedSelection{ ( maximumAllowedDifficulty >= Campaign::CampaignDifficulty::Easy ), ( maximumAllowedDifficulty >= Campaign::CampaignDifficulty::Normal ), ( maximumAllowedDifficulty >= Campaign::CampaignDifficulty::Hard ) }; for ( size_t i = 0; i < allowedSelection.size(); ++i ) { if ( !allowedSelection[i] ) { fheroes2::ApplyPalette( display, iconArea[i].x, iconArea[i].y, display, iconArea[i].x, iconArea[i].y, iconArea[i].width, iconArea[i].height, PAL::GetPalette( PAL::PaletteType::GRAY ) ); } } const int32_t textWidth = windowRoi.width - 16; const fheroes2::Point textOffset{ windowRoi.x + 8, windowRoi.y + 140 }; fheroes2::Text description( currentDescription, fheroes2::FontType::normalWhite() ); fheroes2::ImageRestorer restorer( display, textOffset.x, textOffset.y, textWidth, description.height( textWidth ) ); description.setUniformVerticalAlignment( false ); description.draw( textOffset.x, textOffset.y, textWidth, display ); const fheroes2::Text easyName( getCampaignDifficultyText( Campaign::CampaignDifficulty::Easy ), fheroes2::FontType::normalWhite() ); const fheroes2::Text normalName( getCampaignDifficultyText( Campaign::CampaignDifficulty::Normal ), fheroes2::FontType::normalWhite() ); const fheroes2::Text hardName( getCampaignDifficultyText( Campaign::CampaignDifficulty::Hard ), fheroes2::FontType::normalWhite() ); easyName.draw( difficultyArea[0].x + ( difficultyArea[0].width - easyName.width() ) / 2, difficultyArea[0].y + difficultyArea[0].height + 5, display ); normalName.draw( difficultyArea[1].x + ( difficultyArea[1].width - normalName.width() ) / 2, difficultyArea[1].y + difficultyArea[1].height + 5, display ); hardName.draw( difficultyArea[2].x + ( difficultyArea[2].width - hardName.width() ) / 2, difficultyArea[2].y + difficultyArea[2].height + 5, display ); display.render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); if ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyCloseWindow() ) { break; } bool updateInfo = false; if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Exit this menu." ), Dialog::ZERO ); updateInfo = true; } else if ( le.isMouseRightButtonPressedInArea( difficultyArea[0] ) ) { fheroes2::showStandardTextMessage( getCampaignDifficultyText( Campaign::CampaignDifficulty::Easy ), easyDescription, Dialog::ZERO ); updateInfo = true; } else if ( le.isMouseRightButtonPressedInArea( difficultyArea[1] ) ) { fheroes2::showStandardTextMessage( getCampaignDifficultyText( Campaign::CampaignDifficulty::Normal ), normalDescription, Dialog::ZERO ); updateInfo = true; } else if ( le.isMouseRightButtonPressedInArea( difficultyArea[2] ) ) { fheroes2::showStandardTextMessage( getCampaignDifficultyText( Campaign::CampaignDifficulty::Hard ), hardDescription, Dialog::ZERO ); updateInfo = true; } if ( allowedSelection[0] && le.MouseClickLeft( difficultyArea[0] ) ) { currentDescription = easyDescription; selection.setPosition( difficultyArea[0].x, difficultyArea[0].y ); currentDifficulty = Campaign::CampaignDifficulty::Easy; updateInfo = true; } else if ( allowedSelection[1] && le.MouseClickLeft( difficultyArea[1] ) ) { currentDescription = normalDescription; selection.setPosition( difficultyArea[1].x, difficultyArea[1].y ); currentDifficulty = Campaign::CampaignDifficulty::Normal; updateInfo = true; } else if ( allowedSelection[2] && le.MouseClickLeft( difficultyArea[2] ) ) { currentDescription = hardDescription; selection.setPosition( difficultyArea[2].x, difficultyArea[2].y ); currentDifficulty = Campaign::CampaignDifficulty::Hard; updateInfo = true; } if ( updateInfo ) { restorer.restore(); description.set( currentDescription, fheroes2::FontType::normalWhite() ); restorer.reset(); restorer.update( textOffset.x, textOffset.y, textWidth, description.height( textWidth ) ); description.draw( textOffset.x, textOffset.y, textWidth, display ); display.render(); } } return currentDifficulty; } void outputCampaignScenarioInfoInTextSupportMode( const bool allowToRestart ) { START_TEXT_SUPPORT_MODE const Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get(); const int chosenCampaignID = campaignSaveData.getCampaignID(); const Campaign::CampaignData & campaignData = Campaign::CampaignData::getCampaignData( chosenCampaignID ); const int scenarioId = campaignSaveData.getCurrentScenarioID(); const std::vector & scenarios = campaignData.getAllScenarios(); const Campaign::ScenarioData & scenario = scenarios[scenarioId]; COUT( "Scenario Information\n" ) COUT( "'" << Campaign::getCampaignName( chosenCampaignID ) << "' campaign, scenario " << scenarioId + 1 << ": " << scenario.getScenarioName() ) COUT( "Description: " << scenario.getDescription() << '\n' ) const std::vector obtainedAwards = campaignSaveData.getObtainedCampaignAwards(); if ( obtainedAwards.empty() ) { COUT( "Awards: None" ) } else { COUT( "Awards:" ) for ( const Campaign::CampaignAwardData & award : obtainedAwards ) { COUT( "- " << award.getName() << " : " << award.getDescription() ) } } COUT( "Bonuses:" ) const std::vector & bonusChoices = scenario.getBonuses(); for ( const Campaign::ScenarioBonusData & bonus : bonusChoices ) { COUT( "- " << bonus.getName() << " : " << bonus.getDescription() ) } if ( !bonusChoices.empty() ) { COUT( "- Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_SELECT_FIRST_BONUS ) << " to select the first bonus." ) } if ( bonusChoices.size() > 1 ) { COUT( "- Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_SELECT_SECOND_BONUS ) << " to select the second bonus." ) } if ( bonusChoices.size() > 2 ) { COUT( "- Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_SELECT_THIRD_BONUS ) << " to select the third bonus." ) } if ( allowToRestart ) { COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_RESTART_SCENARIO ) << " to Restart scenario." ) } else { COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_OKAY ) << " to Start scenario." ) } COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_VIEW_INTRO ) << " to View Intro Video." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_SELECT_DIFFICULTY ) << " to Select / View Campaign Difficulty." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to Exit this dialog." ) } } bool Game::isSuccessionWarsCampaignPresent() { return Campaign::CampaignData::getCampaignData( Campaign::ROLAND_CAMPAIGN ).isAllCampaignMapsPresent() && Campaign::CampaignData::getCampaignData( Campaign::ARCHIBALD_CAMPAIGN ).isAllCampaignMapsPresent(); } bool Game::isPriceOfLoyaltyCampaignPresent() { // We need to check game resources as well. if ( fheroes2::AGG::GetICN( ICN::X_LOADCM, 0 ).empty() || fheroes2::AGG::GetICN( ICN::X_IVY, 0 ).empty() ) { return false; } return Campaign::CampaignData::getCampaignData( Campaign::PRICE_OF_LOYALTY_CAMPAIGN ).isAllCampaignMapsPresent() && Campaign::CampaignData::getCampaignData( Campaign::VOYAGE_HOME_CAMPAIGN ).isAllCampaignMapsPresent() && Campaign::CampaignData::getCampaignData( Campaign::WIZARDS_ISLE_CAMPAIGN ).isAllCampaignMapsPresent() && Campaign::CampaignData::getCampaignData( Campaign::DESCENDANTS_CAMPAIGN ).isAllCampaignMapsPresent(); } fheroes2::GameMode Game::CompleteCampaignScenario( const bool isLoadingSaveFile ) { Campaign::CampaignSaveData & saveData = Campaign::CampaignSaveData::Get(); const Campaign::CampaignData & campaignData = Campaign::CampaignData::getCampaignData( saveData.getCampaignID() ); if ( !isLoadingSaveFile ) { saveData.addCurrentMapToFinished(); saveData.addDaysPassed( world.CountDay() ); if ( !campaignData.isLastScenario( saveData.getLastCompletedScenarioInfoID() ) ) { Game::SaveCompletedCampaignScenario(); } } const Campaign::ScenarioInfoId & lastCompletedScenarioInfo = saveData.getLastCompletedScenarioInfoID(); const std::vector obtainableAwards = Campaign::CampaignAwardData::getCampaignAwardData( lastCompletedScenarioInfo ); // TODO: Check for awards that have to be obtained with 'freak' conditions for ( const auto & obtainableAward : obtainableAwards ) { const int32_t awardType = obtainableAward._type; if ( awardType == Campaign::CampaignAwardData::AwardType::TYPE_DEFEAT_ENEMY_HERO ) { // This award must be granted only after defeating a hero in a battle. continue; } if ( awardType == Campaign::CampaignAwardData::AwardType::TYPE_CARRY_OVER_FORCES ) { const int humanColor = Players::HumanColors(); assert( Color::Count( humanColor ) == 1 ); const VecHeroes & humanKingdomHeroes = world.GetKingdom( humanColor ).GetHeroes(); // In the original game, carry-over troops are taken from a hero who was hired least recently and who is still in the kingdom (I.E. still "alive"). A starting // hero will count as first if they are still alive since the beginning, but if they are rehired then they take a new place in the queue of heroes. if ( !humanKingdomHeroes.empty() ) { const Heroes * hero = humanKingdomHeroes.front(); assert( hero != nullptr ); saveData.setCarryOverTroops( hero->GetArmy() ); } } saveData.addCampaignAward( obtainableAward._id ); // after adding an artifact award, check whether the artifacts can be assembled into something else if ( awardType == Campaign::CampaignAwardData::AwardType::TYPE_GET_ARTIFACT ) { const std::vector obtainedAwards = saveData.getObtainedCampaignAwards(); std::map artifactAwardIDs; BagArtifacts bagArtifacts; for ( const Campaign::CampaignAwardData & awardData : obtainedAwards ) { if ( awardData._type != Campaign::CampaignAwardData::AwardType::TYPE_GET_ARTIFACT ) continue; artifactAwardIDs.emplace( awardData._subType, awardData._id ); bagArtifacts.PushArtifact( awardData._subType ); saveData.removeCampaignAward( awardData._id ); } // add the assembled artifact's campaign award to artifactAwards for ( const Campaign::CampaignAwardData & awardData : Campaign::CampaignAwardData::getExtraCampaignAwardData( saveData.getCampaignID() ) ) { if ( awardData._type != Campaign::CampaignAwardData::AwardType::TYPE_GET_ARTIFACT ) continue; artifactAwardIDs.emplace( awardData._subType, awardData._id ); } bagArtifacts.assembleArtifactSetIfPossible(); for ( const Artifact & artifact : bagArtifacts ) { if ( !artifact.isValid() ) continue; const auto foundArtifact = artifactAwardIDs.find( artifact.GetID() ); if ( foundArtifact != artifactAwardIDs.end() ) saveData.addCampaignAward( foundArtifact->second ); } } } playPreviousScenarioVideo(); if ( campaignData.isLastScenario( lastCompletedScenarioInfo ) ) { Game::ShowCredits( false ); // Get data for ratings text. const Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get(); const int32_t daysPassed = static_cast( campaignSaveData.getDaysPassed() ); // Rating is calculated based on difficulty of campaign. const int32_t score = daysPassed * static_cast( campaignSaveData.getCampaignDifficultyPercent() ) / 100; // Make ratings text as a subtitle for WIN.SMK. fheroes2::MultiFontText ratingText; std::string textBody = _( "Congratulations!\n\nDays: %{days}\n" ); StringReplace( textBody, "%{days}", daysPassed ); ratingText.add( { textBody, fheroes2::FontType::normalWhite() } ); textBody = _( "\nDifficulty: %{difficulty}\n\n" ); StringReplace( textBody, "%{difficulty}", getCampaignDifficultyText( campaignSaveData.getDifficulty() ) ); ratingText.add( { textBody, fheroes2::FontType::smallWhite() } ); textBody = _( "Score: %{score}\n\nRating:\n%{rating}" ); StringReplace( textBody, "%{score}", score ); StringReplace( textBody, "%{rating}", fheroes2::HighScoreDataContainer::getMonsterByDay( score ).GetName() ); ratingText.add( { textBody, fheroes2::FontType::normalWhite() } ); // Show results from the 5th second until end (forever) and set maximum width to 140 to fit the black area. // Set subtitles top-center position (475,110) to render results over the black rectangle of burned picture in WIN.SMK video. Video::Subtitle ratingSubtitle( ratingText, 5000, UINT32_MAX, { 475, 110 }, 140 ); AudioManager::ResetAudio(); Video::ShowVideo( "WIN.SMK", Video::VideoAction::WAIT_FOR_USER_INPUT, { std::move( ratingSubtitle ) }, true ); // fheroes2::PlayMusic is run here in order to start playing before displaying the high score. AudioManager::PlayMusicAsync( MUS::VICTORY, Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ); return fheroes2::GameMode::HIGHSCORES_CAMPAIGN; } const Campaign::ScenarioInfoId firstNextMap = Campaign::CampaignData::getScenariosAfter( lastCompletedScenarioInfo ).front(); saveData.setCurrentScenarioInfo( firstNextMap ); return fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; } fheroes2::GameMode Game::SelectCampaignScenario( const fheroes2::GameMode prevMode, const bool allowToRestart ) { fheroes2::Display & display = fheroes2::Display::instance(); display.fill( 0 ); Settings & conf = Settings::Get(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get(); const int chosenCampaignID = campaignSaveData.getCampaignID(); const Campaign::CampaignData & campaignData = Campaign::CampaignData::getCampaignData( chosenCampaignID ); const Campaign::ScenarioInfoId & currentScenarioInfoId = campaignSaveData.getCurrentScenarioInfoId(); const std::vector & scenarios = campaignData.getAllScenarios(); const Campaign::ScenarioData & scenario = scenarios[currentScenarioInfoId.scenarioId]; const fheroes2::GameInterfaceTypeRestorer gameInterfaceRestorer( chosenCampaignID != Campaign::ROLAND_CAMPAIGN ); if ( !allowToRestart ) { playCurrentScenarioVideo(); } outputCampaignScenarioInfoInTextSupportMode( allowToRestart ); playCampaignMusic( chosenCampaignID ); int backgroundIconID = ICN::UNKNOWN; switch ( chosenCampaignID ) { case Campaign::ROLAND_CAMPAIGN: backgroundIconID = ICN::CAMPBKGG; break; case Campaign::ARCHIBALD_CAMPAIGN: backgroundIconID = ICN::CAMPBKGE; break; // PoL campaigns use the same background, but different headers. TODO: Implement the headers case Campaign::PRICE_OF_LOYALTY_CAMPAIGN: case Campaign::DESCENDANTS_CAMPAIGN: case Campaign::WIZARDS_ISLE_CAMPAIGN: case Campaign::VOYAGE_HOME_CAMPAIGN: backgroundIconID = ICN::X_CMPBKG; break; default: // Implementing a new campaign? Add a new case! assert( 0 ); break; } const fheroes2::Sprite & backgroundImage = fheroes2::AGG::GetICN( backgroundIconID, 0 ); const int32_t backgroundImageWidth = backgroundImage.width(); const fheroes2::Point top( ( display.width() - backgroundImageWidth ) / 2, ( display.height() - backgroundImage.height() ) / 2 ); fheroes2::Blit( backgroundImage, display, top.x, top.y ); drawCampaignNameHeader( chosenCampaignID, display, top ); const int buttonIconID = getCampaignButtonId( chosenCampaignID ); // find the placements for the buttons by taking into account their widths. The space between VIEW INTRO and CANCEL is divided by 3 // for the 3 interbutton spaces. The OKAY and RESTART buttons never appear together const int32_t backgroundMargin = 30; const int32_t viewIntroPlacement = top.x + backgroundMargin; const int32_t endOfViewIntroPlacement = viewIntroPlacement + fheroes2::AGG::GetICN( buttonIconID, 0 ).width(); const int32_t cancelPlacement = top.x + backgroundImageWidth - backgroundMargin - fheroes2::AGG::GetICN( buttonIconID, 6 ).width(); const int32_t spaceBetweenViewIntroAndCancel = cancelPlacement - endOfViewIntroPlacement; const int32_t difficultyButtonWidth = fheroes2::AGG::GetICN( buttonIconID, 8 ).width(); const uint32_t okayRestartIndex = allowToRestart ? 2 : 4; const int32_t middleButtonsMargin = ( spaceBetweenViewIntroAndCancel - difficultyButtonWidth - ( fheroes2::AGG::GetICN( buttonIconID, okayRestartIndex ).width() ) ) / 3; const int32_t difficultyPlacement = endOfViewIntroPlacement + middleButtonsMargin; const int32_t okRestartPlacement = difficultyPlacement + difficultyButtonWidth + middleButtonsMargin; const int32_t buttonOffsetY = top.y + 431; fheroes2::Button buttonViewIntro( viewIntroPlacement, buttonOffsetY, buttonIconID, 0, 1 ); fheroes2::Button buttonRestart( okRestartPlacement, buttonOffsetY, buttonIconID, 2, 3 ); fheroes2::Button buttonOk( okRestartPlacement, buttonOffsetY, buttonIconID, 4, 5 ); fheroes2::Button buttonCancel( cancelPlacement, buttonOffsetY, buttonIconID, 6, 7 ); fheroes2::Button buttonDifficulty( difficultyPlacement, buttonOffsetY, buttonIconID, 8, 9 ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( buttonIconID, 0 ), display, { viewIntroPlacement, buttonOffsetY }, { -5, 5 } ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( buttonIconID, okayRestartIndex ), display, { okRestartPlacement, buttonOffsetY }, { -5, 5 } ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( buttonIconID, 6 ), display, { cancelPlacement, buttonOffsetY }, { -5, 5 } ); fheroes2::addGradientShadow( fheroes2::AGG::GetICN( buttonIconID, 8 ), display, { difficultyPlacement, buttonOffsetY }, { -5, 5 } ); // create scenario bonus choice buttons fheroes2::ButtonGroup buttonChoices; fheroes2::OptionButtonGroup optionButtonGroup; std::optional scenarioBonusId; const std::vector & bonusChoices = scenario.getBonuses(); const fheroes2::Point optionButtonOffset( 590, 199 ); const int32_t optionButtonStep = 22; const fheroes2::Sprite & pressedButton = fheroes2::AGG::GetICN( ICN::CAMPXTRG, 8 ); fheroes2::Sprite releaseButton( pressedButton.width(), pressedButton.height(), pressedButton.x(), pressedButton.y() ); fheroes2::Copy( backgroundImage, optionButtonOffset.x + pressedButton.x(), optionButtonOffset.y + pressedButton.y(), releaseButton, 0, 0, releaseButton.width(), releaseButton.height() ); const uint32_t bonusChoiceCount = static_cast( bonusChoices.size() ); { const int32_t saveDataBonusId = campaignSaveData.getCurrentScenarioBonusId(); for ( uint32_t i = 0; i < bonusChoiceCount; ++i ) { buttonChoices.createButton( optionButtonOffset.x + top.x, optionButtonOffset.y + optionButtonStep * i + top.y, releaseButton, pressedButton, i ); optionButtonGroup.addButton( &buttonChoices.button( i ) ); if ( allowToRestart && saveDataBonusId >= 0 && static_cast( saveDataBonusId ) == i ) { scenarioBonusId = saveDataBonusId; buttonChoices.button( i ).press(); } } } if ( bonusChoiceCount > 0 ) { if ( allowToRestart ) { // If the campaign scenario is already in progress, then one of the bonuses should be selected assert( scenarioBonusId.has_value() ); } else { // If this is the beginning of a new campaign scenario, then just select the first bonus scenarioBonusId = 0; buttonChoices.button( 0 ).press(); } } optionButtonGroup.draw(); buttonViewIntro.draw(); buttonDifficulty.draw(); const bool isMapPresent = scenario.isMapFilePresent(); if ( allowToRestart ) { buttonOk.disable(); buttonOk.hide(); if ( !isMapPresent ) { buttonRestart.disable(); } buttonRestart.draw(); } else { buttonRestart.disable(); buttonRestart.hide(); if ( !isMapPresent ) { buttonOk.disable(); } buttonOk.draw(); } // Only one button can be enabled at the time. assert( buttonRestart.isHidden() != buttonOk.isHidden() ); buttonCancel.draw(); const fheroes2::Text textDaysSpent( std::to_string( campaignSaveData.getDaysPassed() ), fheroes2::FontType::normalWhite() ); textDaysSpent.draw( top.x + 582 - textDaysSpent.width() / 2, top.y + 33, display ); DrawCampaignScenarioDescription( scenario, top ); drawObtainedCampaignAwards( campaignSaveData, top ); std::vector selectableScenarios; if ( allowToRestart ) { selectableScenarios.emplace_back( currentScenarioInfoId ); } else { selectableScenarios = campaignSaveData.isStarting() ? campaignData.getStartingScenarios() : Campaign::CampaignData::getScenariosAfter( campaignSaveData.getLastCompletedScenarioInfoID() ); } const uint32_t selectableScenariosCount = static_cast( selectableScenarios.size() ); fheroes2::ButtonGroup selectableScenarioButtons; const int highlightedScenarioId = allowToRestart ? currentScenarioInfoId.scenarioId : -1; DrawCampaignScenarioIcons( selectableScenarioButtons, campaignData, top, highlightedScenarioId ); for ( uint32_t i = 0; i < selectableScenariosCount; ++i ) { if ( currentScenarioInfoId == selectableScenarios[i] ) selectableScenarioButtons.button( i ).press(); selectableScenarioButtons.button( i ).draw(); } LocalEvent & le = LocalEvent::Get(); // Fade-in campaign scenario info. if ( validateDisplayFadeIn() ) { fheroes2::fadeInDisplay( { top.x, top.y, backgroundImage.width(), backgroundImage.height() }, false ); } std::vector choiceArea( bonusChoiceCount ); for ( uint32_t i = 0; i < bonusChoiceCount; ++i ) { choiceArea[i] = buttonChoices.button( i ).area(); choiceArea[i].x -= 170; choiceArea[i].width += 170; } const fheroes2::Rect areaDaysSpent{ top.x + 413, top.y + 27, 201, 25 }; const std::array hotKeyBonusChoice{ Game::HotKeyEvent::CAMPAIGN_SELECT_FIRST_BONUS, Game::HotKeyEvent::CAMPAIGN_SELECT_SECOND_BONUS, Game::HotKeyEvent::CAMPAIGN_SELECT_THIRD_BONUS }; int32_t currentDifficulty = campaignSaveData.getDifficulty(); bool updateDisplay = false; while ( le.HandleEvents() ) { buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonViewIntro.drawOnState( le.isMouseLeftButtonPressedInArea( buttonViewIntro.area() ) ); buttonDifficulty.drawOnState( le.isMouseLeftButtonPressedInArea( buttonDifficulty.area() ) ); buttonRestart.drawOnState( le.isMouseLeftButtonPressedInArea( buttonRestart.area() ) ); for ( uint32_t i = 0; i < bonusChoiceCount; ++i ) { if ( le.isMouseLeftButtonPressedInArea( choiceArea[i] ) || ( i < hotKeyBonusChoice.size() && HotKeyPressEvent( hotKeyBonusChoice[i] ) ) ) { scenarioBonusId = fheroes2::checkedCast( i ); buttonChoices.button( i ).press(); optionButtonGroup.draw(); display.render(); break; } } for ( uint32_t i = 0; i < selectableScenariosCount; ++i ) { if ( currentScenarioInfoId != selectableScenarios[i] && le.MouseClickLeft( selectableScenarioButtons.button( i ).area() ) ) { campaignSaveData.setCurrentScenarioInfo( selectableScenarios[i] ); return fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; } } if ( le.MouseClickLeft( buttonCancel.area() ) || HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) ) { if ( !allowToRestart ) { // Make sure to reset a state of the game if a user does not want to load it. GameOver::Result::Get().Reset(); } fheroes2::fadeOutDisplay( { top.x, top.y, backgroundImage.width(), backgroundImage.height() }, false ); if ( prevMode == fheroes2::GameMode::LOAD_CAMPAIGN || prevMode == fheroes2::GameMode::MAIN_MENU ) { // We are going back to main menu. setDisplayFadeIn(); } return prevMode; } if ( displayScenarioAwardsPopupWindow( campaignSaveData, top ) || displayScenarioBonusPopupWindow( scenario, top ) ) { updateDisplay = true; } const bool restartButtonClicked = ( buttonRestart.isEnabled() && ( le.MouseClickLeft( buttonRestart.area() ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_RESTART_SCENARIO ) ) ); if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Exit this menu without doing anything." ), Dialog::ZERO ); updateDisplay = true; } else if ( buttonOk.isVisible() && le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Start the selected scenario." ), Dialog::ZERO ); updateDisplay = true; } else if ( le.isMouseRightButtonPressedInArea( buttonViewIntro.area() ) ) { fheroes2::showStandardTextMessage( _( "View Intro" ), _( "View the intro video for the current state of the campaign." ), Dialog::ZERO ); updateDisplay = true; } else if ( le.isMouseRightButtonPressedInArea( buttonDifficulty.area() ) ) { fheroes2::showStandardTextMessage( _( "Campaign Difficulty" ), _( "Select the campaign difficulty. This can be lowered at any point during the campaign." ), Dialog::ZERO ); updateDisplay = true; } else if ( buttonRestart.isVisible() && le.isMouseRightButtonPressedInArea( buttonRestart.area() ) ) { fheroes2::showStandardTextMessage( _( "Restart" ), _( "Restart the current scenario." ), Dialog::ZERO ); updateDisplay = true; } else if ( ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || HotKeyPressEvent( HotKeyEvent::DEFAULT_OKAY ) ) ) || restartButtonClicked ) { if ( ( !campaignSaveData.isStarting() || allowToRestart ) && currentDifficulty != campaignSaveData.getDifficulty() && fheroes2::showStandardTextMessage( _( "Difficulty" ), _( "You have changed to a lower difficulty for the campaign. You will not be able to revert this after this " "point. The high score will be calculated based solely on the new difficulty. Do you want to proceed?" ), Dialog::YES | Dialog::NO ) == Dialog::NO ) { continue; } if ( restartButtonClicked && fheroes2::showStandardTextMessage( _( "Restart" ), _( "Are you sure you want to restart this scenario?" ), Dialog::YES | Dialog::NO ) == Dialog::NO ) { continue; } Maps::FileInfo mapInfo = scenario.loadMap(); Campaign::CampaignData::updateScenarioGameplayConditions( currentScenarioInfoId, mapInfo ); conf.setCurrentMapInfo( mapInfo ); assert( !scenarioBonusId || ( scenarioBonusId >= 0 && static_cast( *scenarioBonusId ) < bonusChoices.size() ) ); const Campaign::ScenarioBonusData scenarioBonus = [scenarioBonusId, &bonusChoices = std::as_const( bonusChoices )]() -> Campaign::ScenarioBonusData { if ( !scenarioBonusId ) { return {}; } if ( scenarioBonusId < 0 || static_cast( *scenarioBonusId ) >= bonusChoices.size() ) { return {}; } return bonusChoices[*scenarioBonusId]; }(); // Scenario bonus related to the starting faction has to be set before calling players.SetStartGame(). If the scenario bonus includes the starting army, then // only the starting faction should still be set. if ( scenarioBonus._type == Campaign::ScenarioBonusData::STARTING_RACE || scenarioBonus._type == Campaign::ScenarioBonusData::STARTING_RACE_AND_ARMY ) { SetScenarioBonus( currentScenarioInfoId, { Campaign::ScenarioBonusData::STARTING_RACE, scenarioBonus._subType, scenarioBonus._amount } ); } // Betrayal scenario eliminates all obtained awards. if ( isBetrayalScenario( currentScenarioInfoId ) ) { campaignSaveData.removeAllAwards(); } // Scenario difficulty must be set before loading the map, because it is used during the map loading process. campaignSaveData.setDifficulty( currentDifficulty ); Players & players = conf.GetPlayers(); players.SetStartGame(); conf.SetGameType( Game::TYPE_CAMPAIGN ); const bool isSWCampaign = ( chosenCampaignID == Campaign::ROLAND_CAMPAIGN ) || ( chosenCampaignID == Campaign::ARCHIBALD_CAMPAIGN ); if ( !world.LoadMapMP2( mapInfo.filename, isSWCampaign ) ) { fheroes2::showStandardTextMessage( _( "Campaign Scenario loading failure" ), _( "Please make sure that campaign files are correct and present." ), Dialog::OK ); // TODO: find a way to restore world for the current game after a failure. conf.setCurrentMapInfo( {} ); continue; } // Fade-out screen before loading a scenario. fheroes2::fadeOutDisplay(); // The rest of the scenario bonuses should be set after calling players.SetStartGame(). if ( scenarioBonus._type != Campaign::ScenarioBonusData::STARTING_RACE ) { SetScenarioBonus( currentScenarioInfoId, scenarioBonus ); } applyObtainedCampaignAwards( currentScenarioInfoId, campaignSaveData.getObtainedCampaignAwards() ); campaignSaveData.setCurrentScenarioInfo( currentScenarioInfoId, scenarioBonusId.value_or( -1 ) ); return fheroes2::GameMode::START_GAME; } else if ( le.MouseClickLeft( buttonViewIntro.area() ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_VIEW_INTRO ) ) { AudioManager::ResetAudio(); fheroes2::ImageRestorer restorer( display, top.x, top.y, backgroundImage.width(), backgroundImage.height() ); fheroes2::fadeOutDisplay( restorer.rect(), false ); playPreviousScenarioVideo(); playCurrentScenarioVideo(); playCampaignMusic( chosenCampaignID ); restorer.restore(); fheroes2::fadeInDisplay( restorer.rect(), false ); } else if ( le.isMouseRightButtonPressedInArea( areaDaysSpent ) ) { fheroes2::showStandardTextMessage( _( "Days spent" ), _( "The number of days spent on this campaign." ), Dialog::ZERO ); updateDisplay = true; } else if ( le.MouseClickLeft( buttonDifficulty.area() ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_SELECT_DIFFICULTY ) ) { if ( campaignSaveData.isStarting() && !allowToRestart ) { currentDifficulty = setCampaignDifficulty( currentDifficulty, Campaign::CampaignDifficulty::Hard ); } else { currentDifficulty = setCampaignDifficulty( currentDifficulty, campaignSaveData.getDifficulty() ); } updateDisplay = true; } if ( updateDisplay ) { updateDisplay = false; display.render(); } } return prevMode; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_credits.cpp000066400000000000000000001050621476115357100225400ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_credits.h" #include #include #include #include #include #include #include #include "agg_image.h" #include "audio.h" #include "audio_manager.h" #include "cursor.h" #include "game_delays.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "mus.h" #include "pal.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_text.h" #include "ui_tool.h" namespace { void transformToBlack( fheroes2::Image & out ) { if ( out.empty() ) { return; } assert( !out.singleLayer() ); uint8_t * image = out.image(); const uint8_t * transform = out.transform(); const uint8_t * imageEnd = image + out.width() * out.height(); for ( ; image != imageEnd; ++image, ++transform ) { if ( *transform == 0 ) { *image = 0; } } } enum class AnimationState : int { FADING_IN, NO_ACTION, FADING_OUT }; class AnimationSequence { public: AnimationSequence() = delete; explicit AnimationSequence( const int32_t imageCount ) : _imageCount( imageCount ) {} int32_t pageId() const { return _pageId; } uint8_t alpha() const { return static_cast( _alphaValue ); } AnimationState state() const { return _animationState; } void increment() { switch ( _animationState ) { case AnimationState::FADING_IN: _alphaValue += ALPHA_VALUE_STEP; if ( _alphaValue > 255 ) { _alphaValue = 255; _animationState = AnimationState::NO_ACTION; _noActionCounter = 0; } break; case AnimationState::NO_ACTION: ++_noActionCounter; if ( _noActionCounter > NO_ACTION_COUNTER_LIMIT ) { _animationState = AnimationState::FADING_OUT; } break; case AnimationState::FADING_OUT: _alphaValue -= ALPHA_VALUE_STEP; if ( _alphaValue < 0 ) { _alphaValue = 0; _animationState = AnimationState::FADING_IN; ++_pageId; if ( _pageId >= _imageCount ) { _pageId = 0; } } break; default: assert( 0 ); break; } } private: const int32_t _imageCount; int32_t _alphaValue = 0; int32_t _noActionCounter = 0; int32_t _pageId = 0; AnimationState _animationState = AnimationState::FADING_IN; enum : int32_t { ALPHA_VALUE_STEP = 5, NO_ACTION_COUNTER_LIMIT = 100 }; }; fheroes2::Sprite generateHeader() { const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::CBKGLAVA, 0 ); assert( background.height() < fheroes2::Display::DEFAULT_HEIGHT ); fheroes2::Sprite output; output._disableTransformLayer(); output.resize( fheroes2::Display::DEFAULT_WIDTH, fheroes2::Display::DEFAULT_HEIGHT - background.height() ); output.fill( 0 ); const fheroes2::Text caption( "fheroes2 engine (" + Settings::GetVersion() + ")", fheroes2::FontType::normalYellow() ); caption.draw( output.width() / 2 - caption.width() / 2, 17, output ); return output; } int32_t renderText( fheroes2::Image & output, const int32_t offsetX, const int32_t offsetY, const int32_t textWidth, const char * titleText, const char * bodyText ) { const fheroes2::Text title( titleText, fheroes2::FontType::normalYellow() ); const fheroes2::Text name( bodyText, fheroes2::FontType::normalWhite() ); title.draw( offsetX, offsetY, textWidth, output ); const int32_t titleHeight = title.height( textWidth ); name.draw( offsetX, offsetY + titleHeight, textWidth, output ); return name.height( textWidth ) + titleHeight; } fheroes2::Sprite generateResurrectionCreditsFirstPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGLAVA, 0 ); output._disableTransformLayer(); const int32_t columnStep = 210; const int32_t textInitialOffsetY = 42; const int32_t textWidth = 200; int32_t offsetY = textInitialOffsetY; int32_t offsetX = 0; offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Project Coordination and Core Development" ), "Ihar Hubchyk" ); offsetY += 10; const fheroes2::Sprite & blackDragon = fheroes2::AGG::GetICN( ICN::DRAGBLAK, 5 ); fheroes2::Blit( blackDragon, output, ( columnStep - blackDragon.width() ) / 2, offsetY ); offsetY += blackDragon.height() + 50; const int32_t secondAuthorLayerY = offsetY; offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Development" ), "Sergei Ivanov" ); offsetY += 10; const fheroes2::Sprite & minotaur = fheroes2::AGG::GetICN( ICN::MINOTAUR, 14 ); fheroes2::Blit( minotaur, output, ( columnStep - minotaur.width() ) / 2, offsetY ); offsetY += minotaur.height(); offsetY += 40; const fheroes2::Text websiteInto( _( "Visit us at " ), fheroes2::FontType::normalWhite() ); const fheroes2::Text website( "https://github.com/ihhub/fheroes2", fheroes2::FontType::normalYellow() ); const int32_t websiteIntoWidth = websiteInto.width(); const int32_t websiteWidth = website.width(); const int32_t websiteHeight = website.height(); const int32_t websiteOffsetX = ( output.width() - websiteIntoWidth - websiteWidth ) / 2; websiteInto.draw( websiteOffsetX, offsetY, output ); website.draw( websiteOffsetX + websiteIntoWidth, offsetY, output ); const fheroes2::Sprite & missile = fheroes2::AGG::GetICN( ICN::ARCH_MSL, 4 ); fheroes2::Blit( missile, output, websiteOffsetX - 10 - missile.width(), offsetY + websiteHeight / 2 - missile.height() / 2 ); fheroes2::Blit( missile, output, websiteOffsetX + websiteIntoWidth + websiteWidth + 10, offsetY + websiteHeight / 2 - missile.height() / 2, true ); offsetY = textInitialOffsetY; offsetX += columnStep; offsetY += renderText( output, offsetX, offsetY, textWidth, _( "QA and Support" ), "Igor Tsivilko" ); offsetY += 10; const fheroes2::Sprite & cyclop = fheroes2::AGG::GetICN( ICN::CYCLOPS, 38 ); fheroes2::Blit( cyclop, output, offsetX + ( columnStep - cyclop.width() ) / 2, offsetY ); offsetY = secondAuthorLayerY; offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Development" ), "Ivan Shibanov" ); offsetY += 10; const fheroes2::Sprite & crusader = fheroes2::AGG::GetICN( ICN::PALADIN2, 23 ); fheroes2::Blit( crusader, output, offsetX + ( columnStep - crusader.width() ) / 2, offsetY ); offsetY = textInitialOffsetY; offsetX += columnStep; offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Development" ), "Oleg Derevenetz" ); offsetY += 10; const fheroes2::Sprite & mage = fheroes2::AGG::GetICN( ICN::MAGE1, 24 ); fheroes2::Blit( mage, output, offsetX + ( columnStep - mage.width() ) / 2, offsetY ); offsetY = secondAuthorLayerY; offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Dev and Support" ), "Zense" ); offsetY += 10; const fheroes2::Sprite & phoenix = fheroes2::AGG::GetICN( ICN::PHOENIX, 4 ); fheroes2::Blit( phoenix, output, offsetX + ( columnStep - phoenix.width() ) / 2, offsetY - 10 ); const fheroes2::Sprite & goblin = fheroes2::AGG::GetICN( ICN::GOBLIN, 27 ); fheroes2::Blit( goblin, output, output.width() - goblin.width() * 2, output.height() - goblin.height() - 10, true ); return output; } fheroes2::Sprite generateResurrectionCreditsSecondPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGLAVA, 0 ); output._disableTransformLayer(); const int32_t columnStep = 210; const int32_t textInitialOffsetX = output.width() / 2; const int32_t textInitialOffsetY = 60; const int32_t textWidth = 300; int32_t offsetY = textInitialOffsetY; const fheroes2::Text title( _( "Special Thanks to" ), fheroes2::FontType::normalYellow() ); title.draw( textInitialOffsetX - title.width() / 2, offsetY, output ); offsetY += title.height() + 5; std::string contributors( "LeHerosInconnu\n" "undef21\n" "shprotru\n" "Arkadiy Illarionov\n" "a1exsh\n" "vincent-grosbois\n" "eos428\n" "Mr-Bajs\n" "Arthusppp\n" "felix642\n" "Vasilenko Alexey\n" "Andrii Kurdiumov\n" "Stisen1\n" "dimag0g\n" "Effektus\n" "Laserlicht\n" "Mauri Mustonen\n" "tau3\n" ); fheroes2::Text name( std::move( contributors ), fheroes2::FontType::normalWhite() ); const int32_t constributorsHeight = name.height( textWidth ); name.draw( ( columnStep - textWidth ) / 2, offsetY, textWidth, output ); std::string supporters( "Aimi Lindschouw\n" "Aleksei Mazur\n" "Alex Perry\n" "Andrei Dyldin\n" "Andrew Lasinskiy\n" "Andrew Szucs\n" "Benjamin Hughes\n" "Bolsch\n" "Brandon Wright\n" "Connor Townsend\n" "Christophe Didion\n" "Christopher Elliott" ); name.set( std::move( supporters ), fheroes2::FontType::normalWhite() ); name.draw( columnStep + ( columnStep - textWidth ) / 2, offsetY, textWidth, output ); supporters = "David C Jernberg\n" "domoyega\n" "Grigoris Papadourakis\n" "Hajler\n" "Hakon\n" "hommaddict\n" "Kiril Lipatov\n" "Kresimir Condic\n" "Kuza\n" "Matt Taylor\n" "Matthew Pfluger\n" "Michael Van Wambeke\n" "Reximus\n" "Siarzuk Piatrouski\n" "slvclw\n" "TechnoCore\n" "William Hoskinson\n"; name.set( std::move( supporters ), fheroes2::FontType::normalWhite() ); name.draw( columnStep * 2 + ( columnStep - textWidth ) / 2, offsetY, textWidth, output ); offsetY += constributorsHeight; name.set( _( "and many-many other contributors and supporters!" ), fheroes2::FontType::normalWhite() ); name.draw( output.width() / 2 - name.width() / 2, offsetY, output ); const fheroes2::Sprite & hydra = fheroes2::AGG::GetICN( ICN::HYDRA, 11 ); offsetY = output.height() - hydra.height() - 40; fheroes2::Blit( hydra, output, textInitialOffsetX - hydra.width() / 2, offsetY ); return output; } fheroes2::Sprite generateResurrectionCreditsThirdPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGSWMP, 0 ); output._disableTransformLayer(); const int32_t textInitialOffsetX = output.width() / 2; const int32_t textInitialOffsetY = 80; const int32_t textWidth = 300; int32_t offsetX = ( textInitialOffsetX - textWidth ) / 2; int32_t offsetY = textInitialOffsetY; offsetY += renderText( output, offsetX, offsetY, textWidth, _( "Support us at" ), _( "local-donation-platform|https://www.patreon.com/fheroes2" ) ); offsetY += 30; const fheroes2::Sprite & wizard = fheroes2::AGG::GetICN( ICN::CMBTCAPZ, 4 ); fheroes2::Blit( wizard, output, ( textInitialOffsetX - wizard.width() ) / 2, offsetY ); offsetY += wizard.height() + 20; offsetY += renderText( output, offsetX, offsetY, textWidth - 10, _( "Connect with us at" ), _( "local-social-network|https://www.facebook.com/groups/fheroes2" ) ); offsetY += 20; const fheroes2::Sprite & vampireLord = fheroes2::AGG::GetICN( ICN::VAMPIRE2, 22 ); fheroes2::Blit( vampireLord, output, ( textInitialOffsetX - vampireLord.width() ) / 2, offsetY ); offsetY = textInitialOffsetY; offsetX += textInitialOffsetX; offsetY += renderText( output, offsetX, offsetY, textWidth - 10, _( "Need help with the game?" ), "https://discord.com/servers/fheroes2-733093692860137523" ); offsetY += 10; fheroes2::Sprite labyrinth = fheroes2::AGG::GetICN( ICN::TWNWUP_3, 0 ); fheroes2::ApplyPalette( labyrinth, 2 ); fheroes2::Blit( labyrinth, output, textInitialOffsetX + ( textInitialOffsetX - labyrinth.width() ) / 2, offsetY ); offsetY += labyrinth.height() + 50; const int32_t miniMonsterXOffset = textInitialOffsetX * 3 / 2; fheroes2::Text name( _( "Original project before 0.7" ), fheroes2::FontType::smallYellow() ); name.draw( offsetX, offsetY, textWidth - 10, output ); offsetY += name.height( textWidth - 10 ); name.set( "Andrey Afletdinov\nhttps://sourceforge.net/\nprojects/fheroes2/", fheroes2::FontType::smallWhite() ); name.draw( offsetX, offsetY, textWidth - 10, output ); fheroes2::Sprite creature = fheroes2::AGG::GetICN( ICN::MAGE2, 4 ); transformToBlack( creature ); const int32_t creatureOffsetY = output.height() - 95; fheroes2::Blit( creature, 0, 0, output, miniMonsterXOffset - creature.width() / 2, creatureOffsetY, creature.width(), creature.height() ); name.set( "?", fheroes2::FontType::normalYellow() ); name.draw( miniMonsterXOffset - name.width() / 2, creatureOffsetY + creature.height() / 2 - 5, output ); return output; } fheroes2::Sprite generateSuccessionWarsCreditsFirstPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGWATR, 0 ); fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); output._disableTransformLayer(); const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); const fheroes2::Text title( _( "Heroes of Might and Magic II: The Succession Wars team" ), nameFontType ); title.draw( ( output.width() - title.width() ) / 2, 10, output ); const int32_t textInitialOffsetY = 35; const int32_t textWidth = 320; const int32_t titleOffsetY = 7; int32_t offsetY = textInitialOffsetY; int32_t offsetX = 0; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Designed and Directed" ), "Jon Van Caneghem" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Programming and Design" ), "Phil Steinmeyer" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Executive Producer" ), "Mark Caldwell" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Producer" ), "Walt Hochbrueckner" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Additional Design" ), "Paul Rattner\n" "Debbie Van Caneghem" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Additional Programming" ), "George Ruof\n" "Todd Hendrix\n" "Mark Caldwell" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Musical Production" ), "Rob King" ); renderText( output, offsetX, offsetY, textWidth, _( "Music and Sound Design" ), "Rob King\n" "Steve Baca\n" "Paul Romero" ); offsetY = textInitialOffsetY; offsetX += textWidth; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Vocalists" ), "Grant Youngblood\n" "Kareen Meshagan" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Art Director" ), "Julia Ulano" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Assistant Art Director" ), "Bonita Long-Hemsath" ); renderText( output, offsetX, offsetY, textWidth, _( "Artists" ), "Julie Bateman\n" "Rebecca Christel\n" "Shelly Garcia\n" "Sam Hasson\n" "Louis Henderson\n" "Tracy Iwata\n" "Steve Jasper\n" "April Lee\n" "Lieu Pham\n" "Phelan Sykes\n" "Steve Wasaff\n" "Scott White" ); return output; } fheroes2::Sprite generateSuccessionWarsCreditsSecondPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGWATR, 0 ); fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); output._disableTransformLayer(); const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); const fheroes2::Text title( _( "Heroes of Might and Magic II: The Succession Wars team" ), nameFontType ); title.draw( ( output.width() - title.width() ) / 2, 10, output ); const int32_t textInitialOffsetY = 35; const int32_t textWidth = 320; const int32_t titleOffsetY = 7; int32_t offsetY = textInitialOffsetY; int32_t offsetX = 0; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "QA Manager" ), "Peter Ryu" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "QA" ), "David Botan\n" "David Fernandez\n" "Bill Nesemeier\n" "Walter Johnson\n" "Kate McClelland\n" "Timothy Lang\n" "Bryan Farina" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Writing" ), "Paul Rattner" ); renderText( output, offsetX, offsetY, textWidth, _( "Manual and Helpfile" ), "Bryan Farina\n" "Rozita Tolouey\n" "Bruce Schlickbernd" ); offsetY = textInitialOffsetY; offsetX += textWidth; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Scenarios" ), "Jon Van Caneghem\n" "Debbie Van Caneghem\n" "Clayton Retzer\n" "Christian Vanover\n" "Paul Rattner\n" "Benjamin Bent\n" "Bryan Farina\n" "Eric Heffron\n" "Mark Palczynski\n" "Walt Hochbrueckner\n" "Bruce Schlickbernd\n" "Craig Konas" ); renderText( output, offsetX, offsetY, textWidth, _( "Special Thanks to" ), "Scott McDaniel\n" "Dean Rettig\n" "Ted Chapman\n" "Dean Frost" ); return output; } fheroes2::Sprite generatePriceOfLoyaltyCreditsFirstPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGGRAV, 0 ); fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); output._disableTransformLayer(); const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); fheroes2::Text title( _( "Heroes of Might and Magic II: The Price of Loyalty team" ), nameFontType ); title.draw( ( output.width() - title.width() ) / 2, 10, output ); title.set( "Cyberlore Studios", titleFontType ); title.draw( ( output.width() - title.width() ) / 2, 10 + title.height() * 2, output ); const int32_t textInitialOffsetY = 35 + title.height() * 4; const int32_t textWidth = 320; const int32_t titleOffsetY = 7; int32_t offsetY = textInitialOffsetY; int32_t offsetX = 0; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Executive Producer" ), "Lester Humphreys" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Producer" ), "Joe Minton" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Design Lead" ), "Jim DuBois" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Designers" ), "Jesse King\n" "Kris Greenia" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Programming Lead" ), "Mike White" ); renderText( output, offsetX, offsetY, textWidth, _( "Art Director" ), "Seth Spaulding" ); offsetY = textInitialOffsetY; offsetX += textWidth; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Art Lead" ), "Thomas Gale" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Artists" ), "Michael Clarke\n" "Michael Baker\n" "Julie Airoldi" ); renderText( output, offsetX, offsetY, textWidth, _( "Playtesters" ), "Bart Simon\n" "Fred Fredette\n" "Rendall Koski\n" "T.J. Andrzejczyk\n" "Joanne Delphia" ); return output; } fheroes2::Sprite generatePriceOfLoyaltyCreditsSecondPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGGRAV, 0 ); fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); output._disableTransformLayer(); const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); fheroes2::Text title( _( "Heroes of Might and Magic II: The Price of Loyalty team" ), nameFontType ); title.draw( ( output.width() - title.width() ) / 2, 10, output ); title.set( "New World Computing", titleFontType ); title.draw( ( output.width() - title.width() ) / 2, 10 + title.height() * 2, output ); const int32_t textInitialOffsetY = 35 + title.height() * 4; const int32_t textWidth = 320; const int32_t titleOffsetY = 7; int32_t offsetY = textInitialOffsetY; int32_t offsetX = 0; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Designer" ), "Jon Van Caneghem" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Executive Producer" ), "Mark Caldwell" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Producers" ), "Peter Ryu\n" "Deane Rettig" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Musical Production" ), "Rob King" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "QA Managers" ), "Brian Gilmer\n" "Peter Ryu" ); renderText( output, offsetX, offsetY, textWidth, _( "Music" ), "Rob King\n" "Paul Romero\n" "Steve Baca" ); offsetY = textInitialOffsetY; offsetX += textWidth; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Sound Design" ), "Rob King\n" "Steve Baca" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Town Themes" ), "Paul Romero" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Alto Sax" ), "Brock \"Saxman\" Summers" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Harpsichord and Piano" ), "Paul Romero" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Basso Vocal" ), "Reid Bruton" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Soprano Vocal" ), "Karin Meshagin" ); std::string recordedString = _( "Recorded at %{recordingStudio}" ); StringReplace( recordedString, "%{recordingStudio}", "Green Street Studios" ); title.set( recordedString, titleFontType ); title.draw( offsetX, offsetY, textWidth, output ); return output; } fheroes2::Sprite generatePriceOfLoyaltyCreditsThirdPage() { fheroes2::Sprite output = fheroes2::AGG::GetICN( ICN::CBKGGRAV, 0 ); fheroes2::ApplyPalette( output, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); output._disableTransformLayer(); const fheroes2::FontType titleFontType = fheroes2::FontType::normalYellow(); const fheroes2::FontType nameFontType = fheroes2::FontType::normalWhite(); fheroes2::Text title( _( "Heroes of Might and Magic II: The Price of Loyalty team" ), nameFontType ); title.draw( ( output.width() - title.width() ) / 2, 10, output ); title.set( "New World Computing", titleFontType ); title.draw( ( output.width() - title.width() ) / 2, 10 + title.height() * 2, output ); const int32_t textInitialOffsetY = 35 + title.height() * 4; const int32_t textWidth = 320; const int32_t titleOffsetY = 7; int32_t offsetY = textInitialOffsetY; int32_t offsetX = 0; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "credits|Manual" ), "Bryan Farina" ); offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "German Consultant" ), "Dr. Brock H. Summers" ); renderText( output, offsetX, offsetY, textWidth, _( "Map Designers" ), "Christian Vanover\n" "Ben Bent\n" "Tracy Iwata\n" "Clay Ratzner\n" "Walter Hochbrueckner\n" "Paul Ratner" ); offsetY = textInitialOffsetY; offsetX += textWidth; offsetY += titleOffsetY + renderText( output, offsetX, offsetY, textWidth, _( "Package Design" ), "Rozita Tolouey" ); renderText( output, offsetX, offsetY, textWidth, _( "Playtesters" ), "Mikeael Herauf\n" "Walter Johnson\n" "David Botan\n" "David Fernandez\n" "Kate McClelland\n" "William Nesemeier\n" "Tim Lang\n" "Pavel Vesely\n" "John Lencioni\n" "Jason Wildblood" ); return output; } } void Game::ShowCredits( const bool keepMainMenuBorders ) { // Credits are shown in the place of Main Menu background which is correctly resized. // We get the Main Menu background ROI to use it for credits ROI and leave borders unchanged. const fheroes2::Sprite & mainMenuBackground = fheroes2::AGG::GetICN( ICN::HEROES, 0 ); const fheroes2::Rect creditsRoi( mainMenuBackground.x(), mainMenuBackground.y(), mainMenuBackground.width(), mainMenuBackground.height() ); // Hide mouse cursor. const CursorRestorer cursorRestorer( false ); std::unique_ptr restorer; fheroes2::Display & display = fheroes2::Display::instance(); if ( keepMainMenuBorders ) { // Make a copy of background image to restore it during fade after the credits. restorer = std::make_unique( display, creditsRoi.x, creditsRoi.y, creditsRoi.width, creditsRoi.height ); fheroes2::fadeOutDisplay( creditsRoi, false ); } AudioManager::PlayMusicAsync( MUS::VICTORY, Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ); const uint64_t animationDelay = 50; std::vector pages; pages.emplace_back( generateResurrectionCreditsFirstPage() ); pages.emplace_back( generateResurrectionCreditsSecondPage() ); pages.emplace_back( generateResurrectionCreditsThirdPage() ); if ( Settings::Get().isPriceOfLoyaltySupported() ) { pages.emplace_back( generatePriceOfLoyaltyCreditsFirstPage() ); pages.emplace_back( generatePriceOfLoyaltyCreditsSecondPage() ); pages.emplace_back( generatePriceOfLoyaltyCreditsThirdPage() ); } pages.emplace_back( generateSuccessionWarsCreditsFirstPage() ); pages.emplace_back( generateSuccessionWarsCreditsSecondPage() ); // Resize the credits pages. 'creditsRoi' is made using Main Menu background parameters that were already properly calculated for the current resolution. const int32_t resizedPageHeight = creditsRoi.width * pages.front().height() / pages.front().width(); for ( fheroes2::Sprite & page : pages ) { fheroes2::Sprite resizedPage; resizedPage._disableTransformLayer(); resizedPage.resize( creditsRoi.width, resizedPageHeight ); fheroes2::Resize( page, resizedPage ); page = std::move( resizedPage ); } fheroes2::Sprite header; header._disableTransformLayer(); header.resize( creditsRoi.width, creditsRoi.height - resizedPageHeight ); fheroes2::Resize( generateHeader(), header ); AnimationSequence sequence( static_cast( pages.size() ) ); bool fadeInHeader = true; // Immediately indicate that the delay has passed to render first frame immediately. Game::passCustomAnimationDelay( animationDelay ); // Make sure that the first run is passed immediately. assert( !Game::isCustomDelayNeeded( animationDelay ) ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isCustomDelayNeeded( animationDelay ) ) ) { if ( le.isAnyKeyPressed() || le.MouseClickLeft() || le.MouseClickMiddle() || le.MouseClickRight() ) { break; } if ( Game::validateCustomAnimationDelay( animationDelay ) ) { if ( sequence.state() == AnimationState::NO_ACTION ) { if ( fadeInHeader ) { fadeInHeader = false; } sequence.increment(); continue; } const uint8_t alpha = sequence.alpha(); if ( fadeInHeader ) { fheroes2::ApplyAlpha( header, 0, 0, display, creditsRoi.x, creditsRoi.y, header.width(), header.height(), alpha ); } const fheroes2::Image & page = pages[sequence.pageId()]; if ( alpha == 255 ) { // This alpha is for fully bright image so there is no need to apply alpha. Copy( page, 0, 0, display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height() ); } else if ( alpha == 0 ) { // This alpha is for fully dark image so fill it with the black color. Fill( display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height(), 0 ); } else { fheroes2::ApplyAlpha( page, 0, 0, display, creditsRoi.x, creditsRoi.y + header.height(), page.width(), page.height(), alpha ); } display.render(); sequence.increment(); } } if ( keepMainMenuBorders ) { fheroes2::fadeOutDisplay( creditsRoi, false ); // Restore a copy of background image to fade it in. restorer->restore(); fheroes2::fadeInDisplay( creditsRoi, false ); } else { fheroes2::fadeOutDisplay(); } } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_credits.h000066400000000000000000000032531476115357100222040ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace Game { // Setting keepMainMenuBorders to 'true' will keep screen borders without fade // and restore the main menu image during fade after the credits. void ShowCredits( const bool keepMainMenuBorders ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_delays.cpp000066400000000000000000000217471476115357100223730ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_delays.h" #include #include "settings.h" #include "timing.h" namespace { std::vector delays( Game::LAST_DELAY + 1, fheroes2::TimeDelay( 0 ) ); static_assert( ( defaultBattleSpeed >= 0 ) && ( defaultBattleSpeed < 10 ) ); constexpr double battleSpeedAdjustment = 1.0 / static_cast( 10 - defaultBattleSpeed ); int humanHeroMultiplier = 1; int aiHeroMultiplier = 1; void SetupHeroMovement( const int speed, fheroes2::TimeDelay & delay, int & multiplier ) { switch ( speed ) { case 1: delay.setDelay( 18 ); multiplier = 1; break; case 2: delay.setDelay( 16 ); multiplier = 1; break; case 3: delay.setDelay( 14 ); multiplier = 1; break; case 4: delay.setDelay( 12 ); multiplier = 1; break; case 5: delay.setDelay( 10 ); multiplier = 1; break; case 6: delay.setDelay( 16 ); multiplier = 2; break; case 7: delay.setDelay( 12 ); multiplier = 2; break; case 8: delay.setDelay( 16 ); multiplier = 4; break; case 9: delay.setDelay( 8 ); multiplier = 4; break; default: delay.setDelay( 1 ); multiplier = 4; } } } namespace Game { void AnimateDelaysInitialize(); } void Game::AnimateDelaysInitialize() { delays[SCROLL_DELAY].setDelay( 20 ); delays[SCROLL_START_DELAY].setDelay( 20 ); delays[CURSOR_BLINK_DELAY].setDelay( 440 ); delays[MAIN_MENU_DELAY].setDelay( 250 ); delays[MAPS_DELAY].setDelay( 250 ); delays[CASTLE_TAVERN_DELAY].setDelay( 75 ); delays[CASTLE_AROUND_DELAY].setDelay( 200 ); delays[CASTLE_BUYHERO_DELAY].setDelay( 130 ); delays[CASTLE_BUILD_DELAY].setDelay( 130 ); delays[CASTLE_UNIT_DELAY].setDelay( 150 ); delays[HEROES_FADE_DELAY].setDelay( 32 ); delays[HEROES_PICKUP_DELAY].setDelay( 40 ); delays[PUZZLE_FADE_DELAY].setDelay( 50 ); delays[BATTLE_DIALOG_DELAY].setDelay( 75 ); delays[BATTLE_FRAME_DELAY].setDelay( 120 ); delays[BATTLE_MISSILE_DELAY].setDelay( 40 ); delays[BATTLE_SPELL_DELAY].setDelay( 90 ); delays[BATTLE_DISRUPTING_DELAY].setDelay( 20 ); delays[BATTLE_CATAPULT_DELAY].setDelay( 90 ); delays[BATTLE_CATAPULT_BOULDER_DELAY].setDelay( 40 ); delays[BATTLE_CATAPULT_CLOUD_DELAY].setDelay( 40 ); delays[BATTLE_BRIDGE_DELAY].setDelay( 90 ); delays[BATTLE_IDLE_DELAY].setDelay( 150 ); delays[BATTLE_OPPONENTS_DELAY].setDelay( 75 ); delays[BATTLE_FLAGS_DELAY].setDelay( 250 ); delays[BATTLE_POPUP_DELAY].setDelay( 800 ); delays[BATTLE_COLOR_CYCLE_DELAY].setDelay( 220 ); delays[BATTLE_SELECTED_UNIT_DELAY].setDelay( 160 ); delays[CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY].setDelay( 10 ); delays[CURRENT_HERO_DELAY].setDelay( 10 ); delays[CURRENT_AI_DELAY].setDelay( 10 ); for ( fheroes2::TimeDelay & delay : delays ) { delay.reset(); } UpdateGameSpeed(); } void Game::AnimateResetDelay( const DelayType delayType ) { delays[delayType].reset(); } bool Game::validateCustomAnimationDelay( const uint64_t delayMs ) { if ( delays[Game::DelayType::CUSTOM_DELAY].isPassed( delayMs ) ) { delays[Game::DelayType::CUSTOM_DELAY].reset(); return true; } return false; } bool Game::validateAnimationDelay( const DelayType delayType ) { assert( delayType != Game::DelayType::CUSTOM_DELAY ); if ( delays[delayType].isPassed() ) { delays[delayType].reset(); return true; } return false; } void Game::passAnimationDelay( const DelayType delayType ) { assert( delayType != Game::DelayType::CUSTOM_DELAY ); delays[delayType].pass(); } void Game::passCustomAnimationDelay( const uint64_t delayMs ) { delays[Game::DelayType::CUSTOM_DELAY].setDelay( delayMs ); delays[Game::DelayType::CUSTOM_DELAY].pass(); } void Game::setCustomUnitMovementDelay( const uint64_t delayMs ) { delays[Game::DelayType::CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY].setDelay( delayMs > 0 ? delayMs : 1 ); } void Game::UpdateGameSpeed() { const Settings & conf = Settings::Get(); SetupHeroMovement( conf.HeroesMoveSpeed(), delays[CURRENT_HERO_DELAY], humanHeroMultiplier ); SetupHeroMovement( conf.AIMoveSpeed(), delays[CURRENT_AI_DELAY], aiHeroMultiplier ); const int32_t battleSpeed = conf.BattleSpeed(); // For the battle speed = 10 avoid the zero delay and set animation speed to the 1/3 of battleSpeedAdjustment step. const double adjustedBattleSpeed = ( battleSpeed < 10 ) ? ( ( 10 - battleSpeed ) * battleSpeedAdjustment ) : ( battleSpeedAdjustment / 3 ); // Reduce the Idle animation adjustment interval to: 1.2 for speed 1 ... 0.8 for speed 10. const double adjustedIdleAnimationSpeed = ( 28 - battleSpeed ) / 22.5; delays[BATTLE_FRAME_DELAY].setDelay( static_cast( 120 * adjustedBattleSpeed ) ); delays[BATTLE_MISSILE_DELAY].setDelay( static_cast( 40 * adjustedBattleSpeed ) ); delays[BATTLE_SPELL_DELAY].setDelay( static_cast( 75 * adjustedBattleSpeed ) ); delays[BATTLE_DISRUPTING_DELAY].setDelay( static_cast( 25 * adjustedBattleSpeed ) ); delays[BATTLE_CATAPULT_DELAY].setDelay( static_cast( 90 * adjustedBattleSpeed ) ); delays[BATTLE_CATAPULT_BOULDER_DELAY].setDelay( static_cast( 40 * adjustedBattleSpeed ) ); delays[BATTLE_CATAPULT_CLOUD_DELAY].setDelay( static_cast( 40 * adjustedBattleSpeed ) ); delays[BATTLE_BRIDGE_DELAY].setDelay( static_cast( 90 * adjustedBattleSpeed ) ); delays[BATTLE_IDLE_DELAY].setDelay( static_cast( 150 * adjustedIdleAnimationSpeed ) ); delays[BATTLE_OPPONENTS_DELAY].setDelay( static_cast( 75 * adjustedIdleAnimationSpeed ) ); delays[BATTLE_FLAGS_DELAY].setDelay( static_cast( 250 * adjustedIdleAnimationSpeed ) ); } int Game::HumanHeroAnimSpeedMultiplier() { assert( humanHeroMultiplier > 0 ); return humanHeroMultiplier; } int Game::AIHeroAnimSpeedMultiplier() { assert( aiHeroMultiplier > 0 ); return aiHeroMultiplier; } uint32_t Game::ApplyBattleSpeed( uint32_t delay ) { const uint32_t battleSpeed = static_cast( battleSpeedAdjustment * ( 10 - Settings::Get().BattleSpeed() ) * delay ); return battleSpeed == 0 ? 1 : battleSpeed; } bool Game::hasEveryDelayPassed( const std::vector & delayTypes ) { for ( const Game::DelayType type : delayTypes ) { if ( !delays[type].isPassed() ) { return false; } } return true; } bool Game::isDelayNeeded( const std::vector & delayTypes ) { for ( const Game::DelayType type : delayTypes ) { assert( type != Game::DelayType::CUSTOM_DELAY ); if ( delays[type].isPassed() ) { return false; } } return true; } bool Game::isCustomDelayNeeded( const uint64_t delayMs ) { return !delays[Game::DelayType::CUSTOM_DELAY].isPassed( delayMs ); } uint64_t Game::getAnimationDelayValue( const DelayType delayType ) { assert( delayType != Game::DelayType::CUSTOM_DELAY ); return delays[delayType].getDelay(); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_delays.h000066400000000000000000000103521476115357100220260ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace Game { enum DelayType : int { SCROLL_DELAY = 0, SCROLL_START_DELAY, CURSOR_BLINK_DELAY, MAIN_MENU_DELAY, MAPS_DELAY, CASTLE_TAVERN_DELAY, CASTLE_AROUND_DELAY, CASTLE_BUYHERO_DELAY, CASTLE_BUILD_DELAY, CASTLE_UNIT_DELAY, HEROES_FADE_DELAY, HEROES_PICKUP_DELAY, PUZZLE_FADE_DELAY, BATTLE_DIALOG_DELAY, BATTLE_FRAME_DELAY, BATTLE_MISSILE_DELAY, BATTLE_SPELL_DELAY, BATTLE_DISRUPTING_DELAY, BATTLE_CATAPULT_DELAY, BATTLE_CATAPULT_BOULDER_DELAY, BATTLE_CATAPULT_CLOUD_DELAY, BATTLE_BRIDGE_DELAY, BATTLE_IDLE_DELAY, BATTLE_OPPONENTS_DELAY, BATTLE_FLAGS_DELAY, BATTLE_POPUP_DELAY, BATTLE_COLOR_CYCLE_DELAY, BATTLE_SELECTED_UNIT_DELAY, CUSTOM_BATTLE_UNIT_MOVEMENT_DELAY, CURRENT_HERO_DELAY, CURRENT_AI_DELAY, CUSTOM_DELAY, // IMPORTANT!!! All new entries must be put before this entry! LAST_DELAY }; // If delay is passed reset it and return true. Otherwise return false. DelayType::CUSTOM_DELAY must not be passed! bool validateAnimationDelay( const DelayType delayType ); // If custom delay (DelayType::CUSTOM_DELAY) is passed reset it and return true. Otherwise return false. bool validateCustomAnimationDelay( const uint64_t delayMs ); // Explicitly pass delay. Useful for loops when first iterator must pass. DelayType::CUSTOM_DELAY must not be passed! void passAnimationDelay( const DelayType delayType ); // Explicitly pass custom delay. Useful for loops when first iterator must pass. void passCustomAnimationDelay( const uint64_t delayMs ); // Set the delay between frames of unit movement animation sequence on the battlefield. void setCustomUnitMovementDelay( const uint64_t delayMs ); void AnimateResetDelay( const DelayType delayType ); void UpdateGameSpeed(); uint32_t ApplyBattleSpeed( uint32_t delay ); // Returns the animation speed multiplier for a human-controlled hero. int HumanHeroAnimSpeedMultiplier(); // Returns the animation speed multiplier for an AI-controlled hero. int AIHeroAnimSpeedMultiplier(); // Returns true if every of delay type has passed. bool hasEveryDelayPassed( const std::vector & delayTypes ); // Returns true if every of delay type is not passed yet. DelayType::CUSTOM_DELAY must not be added in this function! bool isDelayNeeded( const std::vector & delayTypes ); bool isCustomDelayNeeded( const uint64_t delayMs ); // Custom delay must never be called in this function. uint64_t getAnimationDelayValue( const DelayType delayType ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_highscores.cpp000066400000000000000000000451041476115357100232410ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "campaign_savedata.h" #include "campaign_scenariodata.h" #include "cursor.h" #include "dialog.h" #include "game.h" // IWYU pragma: associated #include "game_delays.h" #include "game_hotkeys.h" #include "game_io.h" #include "game_mode.h" #include "game_over.h" #include "highscores.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "maps_fileinfo.h" #include "math_base.h" #include "monster.h" #include "monster_anim.h" #include "screen.h" #include "settings.h" #include "system.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" #ifdef WITH_DEBUG #include "logging.h" #endif namespace fheroes2 { enum class SupportedLanguage : uint8_t; } namespace { const std::string highScoreFileName = "fheroes2.hgs"; fheroes2::HighScoreDataContainer highScoreDataContainer; const int32_t initialHighScoreEntryOffsetY = 72; const int32_t highScoreEntryStepY = 40; const int32_t playerNameOffset = 88; const int32_t scenarioNameOffset = 244; const int32_t dayCountOffset = 403; const int32_t ratingOffset = 484; const int32_t monsterOffsetX = 554; const int32_t monsterOffsetY = 91; // Calculate the mini monster sprites ROI. fheroes2::Rect getAnimationRoi( const fheroes2::Point & position, const bool isCampaign ) { fheroes2::Rect roi; std::vector animationIndex; if ( isCampaign ) { const std::vector & highScoreData = highScoreDataContainer.getHighScoresCampaign(); animationIndex.reserve( highScoreData.size() ); for ( const fheroes2::HighscoreData & data : highScoreData ) { animationIndex.push_back( fheroes2::HighScoreDataContainer::getMonsterByDay( data.rating ).GetSpriteIndex() * 9 ); } } else { const std::vector & highScoreData = highScoreDataContainer.getHighScoresStandard(); animationIndex.reserve( highScoreData.size() ); for ( const fheroes2::HighscoreData & data : highScoreData ) { animationIndex.push_back( fheroes2::HighScoreDataContainer::getMonsterByRating( data.rating ).GetSpriteIndex() * 9 ); } } // Animation frames: 0 - static part, 1-6 - animation, 7 and 8 - attacking sprite. We analyze and render here only 0-6 frames. for ( uint32_t i = 0; i < 7; ++i ) { const fheroes2::Sprite & topMonsterSprite = fheroes2::AGG::GetICN( ICN::MINIMON, animationIndex.front() + i ); const fheroes2::Sprite & bottomMonsterSprite = fheroes2::AGG::GetICN( ICN::MINIMON, animationIndex.back() + i ); // We search for the most top sprite offset of the top monster sprite, the most bottom offset of the bottom monster. int32_t offset = topMonsterSprite.y(); if ( offset < roi.y ) { roi.y = offset; } // The offset of the sprite right border from the render point. offset = bottomMonsterSprite.y() + bottomMonsterSprite.height(); if ( offset > roi.height ) { roi.height = offset; } for ( const uint32_t index : animationIndex ) { const fheroes2::Sprite & monsterSprite = fheroes2::AGG::GetICN( ICN::MINIMON, index + i ); offset = monsterSprite.x(); if ( offset < roi.x ) { roi.x = offset; } offset += monsterSprite.width(); if ( offset > roi.width ) { roi.width = offset; } } } // We have 10 high score records and should take into account 9 intervals between each record. roi.height += highScoreEntryStepY * 9 - roi.y; roi.width -= roi.x; // We take into account the High Scores windows position and first monster sprite offset. roi.x += position.x + monsterOffsetX; roi.y += position.y + monsterOffsetY; return roi; } void redrawMonstersAnimation( const fheroes2::Point & position, uint32_t & monsterAnimationFrameId, const std::vector & highScores, const std::function & getMonster ) { ++monsterAnimationFrameId; fheroes2::Display & display = fheroes2::Display::instance(); const std::array & monsterAnimationSequence = fheroes2::getMonsterAnimationSequence(); int32_t offsetY = position.y; for ( const fheroes2::HighscoreData & data : highScores ) { // Animation frame of a creature is based on its position on screen and common animation frame ID. const uint32_t monsterAnimationId = monsterAnimationSequence[( position.x + offsetY + data.dayCount + monsterAnimationFrameId ) % monsterAnimationSequence.size()]; const uint32_t secondaryMonsterAnimationIndex = getMonster( data.rating ).GetSpriteIndex() * 9 + 1 + monsterAnimationId; const fheroes2::Sprite & secondaryMonsterSprite = fheroes2::AGG::GetICN( ICN::MINIMON, secondaryMonsterAnimationIndex ); fheroes2::Blit( secondaryMonsterSprite, display, secondaryMonsterSprite.x() + position.x + monsterOffsetX, secondaryMonsterSprite.y() + offsetY + monsterOffsetY ); offsetY += highScoreEntryStepY; } } void redrawHighScoreAnimation( const fheroes2::Point & position, uint32_t & monsterAnimationFrameId, const bool isCampaign ) { if ( isCampaign ) { redrawMonstersAnimation( position, monsterAnimationFrameId, highScoreDataContainer.getHighScoresCampaign(), fheroes2::HighScoreDataContainer::getMonsterByDay ); } else { redrawMonstersAnimation( position, monsterAnimationFrameId, highScoreDataContainer.getHighScoresStandard(), fheroes2::HighScoreDataContainer::getMonsterByRating ); } } void redrawHighScoreScreen( const fheroes2::Point & position, const int32_t selectedScoreIndex, const std::vector & highScores, const uint32_t titleImageIndex, const std::function & getMonster ) { fheroes2::Display & display = fheroes2::Display::instance(); // Draw background. const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::HSBKG, 0 ); fheroes2::Copy( background, 0, 0, display, position.x, position.y, background.width(), background.height() ); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::HISCORE, titleImageIndex ), display, position.x + 50, position.y + 31 ); fheroes2::Text text( "", fheroes2::FontType::normalWhite() ); int32_t scoreIndex = 0; int32_t offsetY = position.y; for ( const fheroes2::HighscoreData & data : highScores ) { const fheroes2::FontType font = ( scoreIndex == selectedScoreIndex ) ? fheroes2::FontType::normalYellow() : fheroes2::FontType::normalWhite(); // TODO: scenario name can have its own independent language. const fheroes2::SupportedLanguage language = fheroes2::getLanguageFromAbbreviation( data.languageAbbreviation ); text.set( data.playerName, font, language ); text.fitToOneRow( scenarioNameOffset - playerNameOffset ); text.draw( position.x + playerNameOffset, offsetY + initialHighScoreEntryOffsetY, display ); text.set( data.scenarioName, font, language ); text.fitToOneRow( dayCountOffset - scenarioNameOffset ); text.draw( position.x + scenarioNameOffset, offsetY + initialHighScoreEntryOffsetY, display ); text.set( std::to_string( data.dayCount ), font ); text.draw( position.x + dayCountOffset, offsetY + initialHighScoreEntryOffsetY, display ); text.set( std::to_string( data.rating ), font ); text.draw( position.x + ratingOffset, offsetY + initialHighScoreEntryOffsetY, display ); // Render static part of monster animation. const Monster monster = getMonster( data.rating ); const uint32_t baseMonsterAnimationIndex = monster.GetSpriteIndex() * 9; const fheroes2::Sprite & baseMonsterSprite = fheroes2::AGG::GetICN( ICN::MINIMON, baseMonsterAnimationIndex ); fheroes2::Blit( baseMonsterSprite, display, baseMonsterSprite.x() + position.x + 554, baseMonsterSprite.y() + offsetY + 91 ); offsetY += highScoreEntryStepY; ++scoreIndex; } } } fheroes2::GameMode Game::DisplayHighScores( const bool isCampaign ) { GameOver::Result & gameResult = GameOver::Result::Get(); #ifdef WITH_DEBUG if ( IS_DEVEL() && ( gameResult.GetResult() & GameOver::WINS ) ) { std::string msg = "Developer mode is active, the result will not be saved! \n\n Your result: "; if ( isCampaign ) { msg += std::to_string( Campaign::CampaignSaveData::Get().getDaysPassed() ); } else { msg += std::to_string( GetRating() * getGameOverScoreFactor() / 100 ); } fheroes2::showStandardTextMessage( _( "High Scores" ), std::move( msg ), Dialog::OK ); gameResult.ResetResult(); return fheroes2::GameMode::MAIN_MENU; } #endif const std::string highScoreDataPath = System::concatPath( GetSaveDir(), highScoreFileName ); if ( !highScoreDataContainer.load( highScoreDataPath ) ) { // Unable to load the file. Let's populate with the default values. highScoreDataContainer.clear(); highScoreDataContainer.populateStandardDefaultHighScores(); highScoreDataContainer.populateCampaignDefaultHighScores(); } int32_t selectedEntryIndex = -1; const bool isAfterGameCompletion = ( ( gameResult.GetResult() & GameOver::WINS ) != 0 ); fheroes2::Display & display = fheroes2::Display::instance(); const bool isDefaultScreenSize = display.isDefaultSize(); if ( isAfterGameCompletion ) { const auto inputPlayerName = []( std::string & playerName ) { Dialog::inputString( fheroes2::Text{}, fheroes2::Text{ _( "Your Name" ), fheroes2::FontType::normalWhite() }, playerName, 15, false, {} ); if ( playerName.empty() ) { playerName = _( "Unknown Hero" ); } }; const uint32_t completionTime = fheroes2::HighscoreData::generateCompletionTime(); std::string lang = fheroes2::getLanguageAbbreviation( fheroes2::getCurrentLanguage() ); // Check whether the game result is good enough to be put on high score board. If not then just skip showing the player name dialog. if ( isCampaign ) { const Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get(); const uint32_t daysPassed = campaignSaveData.getDaysPassed(); // Rating is calculated based on difficulty of campaign. const uint32_t rating = daysPassed * campaignSaveData.getCampaignDifficultyPercent() / 100; const auto & campaignHighscoreData = highScoreDataContainer.getHighScoresCampaign(); assert( !campaignHighscoreData.empty() ); if ( campaignHighscoreData.back().rating < rating ) { gameResult.ResetResult(); return fheroes2::GameMode::MAIN_MENU; } std::string playerName; inputPlayerName( playerName ); selectedEntryIndex = highScoreDataContainer.registerScoreCampaign( { std::move( lang ), playerName, Campaign::getCampaignName( campaignSaveData.getCampaignID() ), completionTime, daysPassed, rating, world.GetMapSeed() } ); } else { const uint32_t rating = GetRating() * getGameOverScoreFactor() / 100; const auto & standardHighscoreData = highScoreDataContainer.getHighScoresStandard(); assert( !standardHighscoreData.empty() ); if ( standardHighscoreData.back().rating > rating ) { gameResult.ResetResult(); return fheroes2::GameMode::MAIN_MENU; } const uint32_t daysPassed = world.CountDay(); std::string playerName; inputPlayerName( playerName ); selectedEntryIndex = highScoreDataContainer.registerScoreStandard( { std::move( lang ), playerName, Settings::Get().getCurrentMapInfo().name, completionTime, daysPassed, rating, world.GetMapSeed() } ); } highScoreDataContainer.save( highScoreDataPath ); gameResult.ResetResult(); // Fade-out game screen. fheroes2::fadeOutDisplay(); } else if ( isDefaultScreenSize ) { fheroes2::fadeOutDisplay(); } // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); const fheroes2::Sprite & back = fheroes2::AGG::GetICN( ICN::HSBKG, 0 ); const fheroes2::Point top{ ( display.width() - back.width() ) / 2, ( display.height() - back.height() ) / 2 }; const fheroes2::StandardWindow border( display.DEFAULT_WIDTH, display.DEFAULT_HEIGHT, false ); uint32_t monsterAnimationFrameId = 0; if ( isCampaign ) { redrawHighScoreScreen( top, selectedEntryIndex, highScoreDataContainer.getHighScoresCampaign(), 7, fheroes2::HighScoreDataContainer::getMonsterByDay ); } else { redrawHighScoreScreen( top, selectedEntryIndex, highScoreDataContainer.getHighScoresStandard(), 6, fheroes2::HighScoreDataContainer::getMonsterByRating ); } const fheroes2::Rect animationRoi = getAnimationRoi( top, isCampaign ); // Make a copy of static monsters animation part with background to restore it during animations. fheroes2::ImageRestorer backgroundCopy( display, animationRoi.x, animationRoi.y, animationRoi.width, animationRoi.height ); // Render first animation frame. redrawHighScoreAnimation( top, monsterAnimationFrameId, isCampaign ); fheroes2::Button buttonOtherHighScore( top.x + 8, top.y + 315, isCampaign ? ICN::BUTTON_HSCORES_VERTICAL_CAMPAIGN : ICN::BUTTON_HSCORES_VERTICAL_STANDARD, 0, 1 ); fheroes2::Button buttonExit( top.x + back.width() - 36, top.y + 315, ICN::BUTTON_HSCORES_VERTICAL_EXIT, 0, 1 ); buttonOtherHighScore.draw(); buttonExit.draw(); // Fade-in High Scores screen. if ( isAfterGameCompletion ) { fheroes2::fadeInDisplay(); } else { if ( !isDefaultScreenSize ) { // We need to expand the ROI for the next render to properly render window borders and shadow. display.updateNextRenderRoi( border.totalArea() ); } fheroes2::fadeInDisplay( border.activeArea(), !isDefaultScreenSize ); } LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isDelayNeeded( { Game::MAPS_DELAY } ) ) ) { buttonOtherHighScore.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOtherHighScore.area() ) ); buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( le.MouseClickLeft( buttonExit.area() ) || HotKeyCloseWindow() ) { if ( isAfterGameCompletion || isDefaultScreenSize ) { fheroes2::fadeOutDisplay(); Game::setDisplayFadeIn(); } else { fheroes2::fadeOutDisplay( border.activeArea(), true ); } return fheroes2::GameMode::MAIN_MENU; } if ( le.MouseClickLeft( buttonOtherHighScore.area() ) ) { return isCampaign ? fheroes2::GameMode::HIGHSCORES_STANDARD : fheroes2::GameMode::HIGHSCORES_CAMPAIGN; } if ( le.isMouseRightButtonPressedInArea( buttonExit.area() ) ) { fheroes2::showStandardTextMessage( _( "Exit" ), _( "Exit this menu." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOtherHighScore.area() ) ) { if ( isCampaign ) { fheroes2::showStandardTextMessage( _( "Standard" ), _( "View High Scores for Standard Maps." ), Dialog::ZERO ); } else { fheroes2::showStandardTextMessage( _( "Campaign" ), _( "View High Scores for Campaigns." ), Dialog::ZERO ); } } if ( Game::validateAnimationDelay( Game::MAPS_DELAY ) ) { // Restore background with static monster animation part. backgroundCopy.restore(); redrawHighScoreAnimation( top, monsterAnimationFrameId, isCampaign ); buttonOtherHighScore.draw(); buttonExit.draw(); display.render( animationRoi ); } } return fheroes2::GameMode::QUIT_GAME; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_hotkeys.cpp000066400000000000000000001062441476115357100225740ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_hotkeys.h" #include #include #include #include #include #include #include #include #include #include #include #include "battle_arena.h" #include "dialog.h" #include "game_interface.h" #include "game_language.h" #include "interface_gamearea.h" #include "localevent.h" #include "logging.h" #include "players.h" #include "serialize.h" #include "settings.h" #include "system.h" #include "tinyconfig.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "ui_language.h" namespace { struct HotKeyEventInfo { HotKeyEventInfo() = default; HotKeyEventInfo( const Game::HotKeyCategory category_, const char * name_, const fheroes2::Key key_ ) : category( category_ ) , name( name_ ) , key( key_ ) { // Do nothing. } HotKeyEventInfo( const HotKeyEventInfo & ) = default; HotKeyEventInfo( HotKeyEventInfo && ) = default; ~HotKeyEventInfo() = default; HotKeyEventInfo & operator=( const HotKeyEventInfo & ) = default; HotKeyEventInfo & operator=( HotKeyEventInfo && ) = default; Game::HotKeyCategory category = Game::HotKeyCategory::DEFAULT; const char * name = ""; fheroes2::Key key = fheroes2::Key::NONE; }; constexpr typename std::underlying_type::type hotKeyEventToInt( Game::HotKeyEvent value ) { return static_cast::type>( value ); } std::array hotKeyEventInfo; void initializeHotKeyEvents() { // Make sure that event name is unique! hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::DEFAULT_OKAY )] = { Game::HotKeyCategory::DEFAULT, gettext_noop( "hotkey|default okay event" ), fheroes2::Key::KEY_ENTER }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::DEFAULT_CANCEL )] = { Game::HotKeyCategory::DEFAULT, gettext_noop( "hotkey|default cancel event" ), fheroes2::Key::KEY_ESCAPE }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::DEFAULT_LEFT )] = { Game::HotKeyCategory::DEFAULT, gettext_noop( "hotkey|default left" ), fheroes2::Key::KEY_LEFT }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::DEFAULT_RIGHT )] = { Game::HotKeyCategory::DEFAULT, gettext_noop( "hotkey|default right" ), fheroes2::Key::KEY_RIGHT }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::DEFAULT_UP )] = { Game::HotKeyCategory::DEFAULT, gettext_noop( "hotkey|default up" ), fheroes2::Key::KEY_UP }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::DEFAULT_DOWN )] = { Game::HotKeyCategory::DEFAULT, gettext_noop( "hotkey|default down" ), fheroes2::Key::KEY_DOWN }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::GLOBAL_TOGGLE_FULLSCREEN )] = { Game::HotKeyCategory::GLOBAL, gettext_noop( "hotkey|toggle fullscreen" ), fheroes2::Key::KEY_F4 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::GLOBAL_TOGGLE_TEXT_SUPPORT_MODE )] = { Game::HotKeyCategory::GLOBAL, gettext_noop( "hotkey|toggle text support mode" ), fheroes2::Key::KEY_F10 }; #if defined( WITH_DEBUG ) hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::DEBUG_TOGGLE_DEVELOPER_MODE )] = { Game::HotKeyCategory::GLOBAL, gettext_noop( "hotkey|toggle developer mode" ), fheroes2::Key::KEY_BACKQUOTE }; #endif hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_NEW_GAME )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|new game" ), fheroes2::Key::KEY_N }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|load game" ), fheroes2::Key::KEY_L }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_HIGHSCORES )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|high scores" ), fheroes2::Key::KEY_H }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_CREDITS )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|credits" ), fheroes2::Key::KEY_C }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_STANDARD )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|standard game" ), fheroes2::Key::KEY_S }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_CAMPAIGN )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|campaign game" ), fheroes2::Key::KEY_C }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_MULTI )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|multi-player game" ), fheroes2::Key::KEY_M }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_SETTINGS )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|settings" ), fheroes2::Key::KEY_T }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_QUIT )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|quit" ), fheroes2::Key::KEY_Q }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_SELECT_MAP )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|select map" ), fheroes2::Key::KEY_S }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_SMALL )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|select small map size" ), fheroes2::Key::KEY_S }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_MEDIUM )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|select medium map size" ), fheroes2::Key::KEY_M }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_LARGE )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|select large map size" ), fheroes2::Key::KEY_L }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_EXTRA_LARGE )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|select extra large map size" ), fheroes2::Key::KEY_X }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_MAP_SIZE_ALL )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|select all map sizes" ), fheroes2::Key::KEY_A }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_HOTSEAT )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|hot seat game" ), fheroes2::Key::KEY_H }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_BATTLEONLY )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|battle only game" ), fheroes2::Key::KEY_B }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_NEW_ORIGINAL_CAMPAIGN )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|choose the original campaign" ), fheroes2::Key::KEY_O }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::MAIN_MENU_NEW_EXPANSION_CAMPAIGN )] = { Game::HotKeyCategory::MAIN_MENU, gettext_noop( "hotkey|choose the expansion campaign" ), fheroes2::Key::KEY_E }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_MAIN_MENU )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|map editor main menu" ), fheroes2::Key::KEY_E }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_NEW_MAP_MENU )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|new map menu" ), fheroes2::Key::KEY_N }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_LOAD_MAP_MENU )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|load map menu" ), fheroes2::Key::KEY_L }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_FROM_SCRATCH_MAP_MENU )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|new map from scratch" ), fheroes2::Key::KEY_S }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_RANDOM_MAP_MENU )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|new random map" ), fheroes2::Key::KEY_R }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_UNDO_LAST_ACTION )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|undo last action" ), fheroes2::Key::KEY_U }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_REDO_LAST_ACTION )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|redo last action" ), fheroes2::Key::KEY_R }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_TO_GAME_MAIN_MENU )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|open game main menu" ), fheroes2::Key::KEY_M }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::EDITOR_TOGGLE_PASSABILITY )] = { Game::HotKeyCategory::EDITOR, gettext_noop( "hotkey|toggle passability" ), fheroes2::Key::KEY_P }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_ROLAND )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|roland campaign" ), fheroes2::Key::KEY_1 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_ARCHIBALD )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|archibald campaign" ), fheroes2::Key::KEY_2 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_PRICE_OF_LOYALTY )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|price of loyalty campaign" ), fheroes2::Key::KEY_1 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_VOYAGE_HOME )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|voyage home campaign" ), fheroes2::Key::KEY_2 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_WIZARDS_ISLE )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|wizard's isle campaign" ), fheroes2::Key::KEY_3 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_DESCENDANTS )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|descendants campaign" ), fheroes2::Key::KEY_4 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_SELECT_FIRST_BONUS )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|select first campaign bonus" ), fheroes2::Key::KEY_1 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_SELECT_SECOND_BONUS )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|select second campaign bonus" ), fheroes2::Key::KEY_2 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_SELECT_THIRD_BONUS )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|select third campaign bonus" ), fheroes2::Key::KEY_3 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_VIEW_INTRO )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|view campaign intro" ), fheroes2::Key::KEY_V }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_SELECT_DIFFICULTY )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|select campaign difficulty" ), fheroes2::Key::KEY_D }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::CAMPAIGN_RESTART_SCENARIO )] = { Game::HotKeyCategory::CAMPAIGN, gettext_noop( "hotkey|restart campaign scenario" ), fheroes2::Key::KEY_R }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_LEFT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map left" ), fheroes2::Key::KEY_KP_4 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_RIGHT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map right" ), fheroes2::Key::KEY_KP_6 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_UP )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map up" ), fheroes2::Key::KEY_KP_8 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_DOWN )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map down" ), fheroes2::Key::KEY_KP_2 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_UP_LEFT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map up left" ), fheroes2::Key::KEY_KP_7 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_UP_RIGHT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map up right" ), fheroes2::Key::KEY_KP_9 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_DOWN_LEFT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map down left" ), fheroes2::Key::KEY_KP_1 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_DOWN_RIGHT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|world map down right" ), fheroes2::Key::KEY_KP_3 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SAVE_GAME )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|save game" ), fheroes2::Key::KEY_S }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_NEXT_HERO )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|next hero" ), fheroes2::Key::KEY_H }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_QUICK_SELECT_HERO )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|change to hero under cursor" ), fheroes2::Key::KEY_LEFT_SHIFT }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_START_HERO_MOVEMENT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|start hero movement" ), fheroes2::Key::KEY_M }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_CAST_SPELL )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|cast adventure spell" ), fheroes2::Key::KEY_C }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SLEEP_HERO )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|put hero to sleep" ), fheroes2::Key::KEY_Z }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_NEXT_TOWN )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|next town" ), fheroes2::Key::KEY_T }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_END_TURN )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|end turn" ), fheroes2::Key::KEY_E }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_FILE_OPTIONS )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|file options" ), fheroes2::Key::KEY_F }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_ADVENTURE_OPTIONS )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|adventure options" ), fheroes2::Key::KEY_A }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_PUZZLE_MAP )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|puzzle map" ), fheroes2::Key::KEY_P }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SCENARIO_INFORMATION )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|scenario information" ), fheroes2::Key::KEY_I }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_DIG_ARTIFACT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|dig for artifact" ), fheroes2::Key::KEY_D }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_VIEW_WORLD )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|view world" ), fheroes2::Key::KEY_V }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_KINGDOM_SUMMARY )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|kingdom summary" ), fheroes2::Key::KEY_K }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_DEFAULT_ACTION )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|default action" ), fheroes2::Key::KEY_SPACE }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_OPEN_FOCUS )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|open focus" ), fheroes2::Key::KEY_ENTER }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SYSTEM_OPTIONS )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|system options" ), fheroes2::Key::KEY_O }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SCROLL_LEFT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|scroll left" ), fheroes2::Key::KEY_LEFT }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SCROLL_RIGHT )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|scroll right" ), fheroes2::Key::KEY_RIGHT }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SCROLL_UP )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|scroll up" ), fheroes2::Key::KEY_UP }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_SCROLL_DOWN )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|scroll down" ), fheroes2::Key::KEY_DOWN }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_TOGGLE_CONTROL_PANEL )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|toggle control panel" ), fheroes2::Key::KEY_1 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_TOGGLE_RADAR )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|toggle radar" ), fheroes2::Key::KEY_2 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_TOGGLE_BUTTONS )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|toggle buttons" ), fheroes2::Key::KEY_3 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_TOGGLE_STATUS )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|toggle status" ), fheroes2::Key::KEY_4 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_TOGGLE_ICONS )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|toggle icons" ), fheroes2::Key::KEY_5 }; #if defined( WITH_DEBUG ) hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::WORLD_TRANSFER_CONTROL_TO_AI )] = { Game::HotKeyCategory::WORLD_MAP, gettext_noop( "hotkey|transfer control to ai" ), fheroes2::Key::KEY_F8 }; #endif hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_RETREAT )] = { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|retreat from battle" ), fheroes2::Key::KEY_R }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_SURRENDER )] = { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|surrender during battle" ), fheroes2::Key::KEY_S }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_TOGGLE_AUTO_COMBAT )] = { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|toggle auto combat mode" ), fheroes2::Key::KEY_A }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_QUICK_COMBAT )] = { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|quick combat" ), fheroes2::Key::KEY_Q }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_OPTIONS )] = { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|battle options" ), fheroes2::Key::KEY_O }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_SKIP )] = { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|skip turn in battle" ), fheroes2::Key::KEY_SPACE }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_CAST_SPELL )] = { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|cast battle spell" ), fheroes2::Key::KEY_C }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_1 )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|dwelling level 1" ), fheroes2::Key::KEY_1 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_2 )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|dwelling level 2" ), fheroes2::Key::KEY_2 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_3 )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|dwelling level 3" ), fheroes2::Key::KEY_3 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_4 )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|dwelling level 4" ), fheroes2::Key::KEY_4 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_5 )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|dwelling level 5" ), fheroes2::Key::KEY_5 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_6 )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|dwelling level 6" ), fheroes2::Key::KEY_6 }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_WELL )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|well" ), fheroes2::Key::KEY_W }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_MARKETPLACE )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|marketplace" ), fheroes2::Key::KEY_M }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_MAGE_GUILD )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|mage guild" ), fheroes2::Key::KEY_S }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_SHIPYARD )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|shipyard" ), fheroes2::Key::KEY_N }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_THIEVES_GUILD )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|thieves guild" ), fheroes2::Key::KEY_T }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_TAVERN )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|tavern" ), fheroes2::Key::KEY_R }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_CONSTRUCTION )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|construction screen" ), fheroes2::Key::KEY_B }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_WELL_BUY_ALL )] = { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|buy all monsters in well" ), fheroes2::Key::KEY_M }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_SPLIT_STACK_BY_HALF )] = { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|split stack by half" ), fheroes2::Key::KEY_LEFT_SHIFT }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_SPLIT_STACK_BY_ONE )] = { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|split stack by one" ), fheroes2::Key::KEY_LEFT_CONTROL }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_JOIN_STACKS )] = { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|join stacks" ), fheroes2::Key::KEY_LEFT_ALT }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_UPGRADE_TROOP )] = { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|upgrade troop" ), fheroes2::Key::KEY_U }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_DISMISS )] = { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|dismiss hero or troop" ), fheroes2::Key::KEY_D }; hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_SWAP )] = { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|exchange all troops" ), fheroes2::Key::KEY_S }; } std::string getHotKeyFileContent() { std::ostringstream os; os << "# fheroes2 hotkey file (saved by version " << Settings::GetVersion() << ")" << std::endl; os << std::endl; Game::HotKeyCategory currentCategory = hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::NONE ) + 1].category; os << "# " << getHotKeyCategoryName( currentCategory ) << ':' << std::endl; #if defined( WITH_DEBUG ) std::set duplicationStringVerifier; #endif const fheroes2::LanguageSwitcher languageSwitcher( fheroes2::SupportedLanguage::English ); for ( int32_t eventId = hotKeyEventToInt( Game::HotKeyEvent::NONE ) + 1; eventId < hotKeyEventToInt( Game::HotKeyEvent::NO_EVENT ); ++eventId ) { if ( currentCategory != hotKeyEventInfo[eventId].category ) { currentCategory = hotKeyEventInfo[eventId].category; os << std::endl; os << "# " << getHotKeyCategoryName( currentCategory ) << ':' << std::endl; } const char * eventName = _( hotKeyEventInfo[eventId].name ); assert( strlen( eventName ) > 0 ); #if defined( WITH_DEBUG ) const bool isUnique = duplicationStringVerifier.emplace( eventName ).second; assert( isUnique ); #endif os << eventName << " = " << StringUpper( KeySymGetName( hotKeyEventInfo[eventId].key ) ) << std::endl; } return os.str(); } } bool Game::HotKeyPressEvent( const HotKeyEvent eventID ) { const LocalEvent & le = LocalEvent::Get(); if ( le.isAnyKeyPressed() ) { // We should disable the fast scroll, because the cursor might be on one of the borders when a dialog gets dismissed. Interface::AdventureMap::Get().getGameArea().setFastScrollStatus( false ); } return le.isAnyKeyPressed() && le.getPressedKeyValue() == hotKeyEventInfo[hotKeyEventToInt( eventID )].key; } bool Game::HotKeyHoldEvent( const HotKeyEvent eventID ) { const LocalEvent & le = LocalEvent::Get(); return le.isKeyBeingHold() && le.getPressedKeyValue() == hotKeyEventInfo[hotKeyEventToInt( eventID )].key; } fheroes2::Key Game::getHotKeyForEvent( const HotKeyEvent eventID ) { return hotKeyEventInfo[hotKeyEventToInt( eventID )].key; } void Game::setHotKeyForEvent( const HotKeyEvent eventID, const fheroes2::Key key ) { hotKeyEventInfo[hotKeyEventToInt( eventID )].key = key; } std::string Game::getHotKeyNameByEventId( const HotKeyEvent eventID ) { return StringUpper( KeySymGetName( hotKeyEventInfo[hotKeyEventToInt( eventID )].key ) ); } const char * Game::getHotKeyEventNameByEventId( const HotKeyEvent eventID ) { return hotKeyEventInfo[hotKeyEventToInt( eventID )].name; } std::vector> Game::getAllHotKeyEvents() { std::vector> events; events.reserve( hotKeyEventInfo.size() - 1 ); const bool disableEditor = !Settings::Get().isPriceOfLoyaltySupported(); for ( size_t i = 1; i < hotKeyEventInfo.size(); ++i ) { if ( disableEditor && ( hotKeyEventInfo[i].category == HotKeyCategory::EDITOR ) ) { continue; } events.emplace_back( static_cast( i ), hotKeyEventInfo[i].category ); } return events; } void Game::HotKeysLoad( const std::string & filename ) { initializeHotKeyEvents(); bool isFilePresent = System::IsFile( filename ); if ( isFilePresent ) { TinyConfig config( '=', '#' ); isFilePresent = config.Load( filename ); if ( isFilePresent ) { std::map> nameToKey; for ( int32_t i = static_cast( fheroes2::Key::NONE ); i < static_cast( fheroes2::Key::LAST_KEY ); ++i ) { const fheroes2::Key key = static_cast( i ); nameToKey.try_emplace( StringUpper( KeySymGetName( key ) ), key ); } const fheroes2::LanguageSwitcher languageSwitcher( fheroes2::SupportedLanguage::English ); for ( int eventId = hotKeyEventToInt( HotKeyEvent::NONE ) + 1; eventId < hotKeyEventToInt( HotKeyEvent::NO_EVENT ); ++eventId ) { const char * eventName = _( hotKeyEventInfo[eventId].name ); std::string value = config.StrParams( eventName ); if ( value.empty() ) { // TODO: remove this temporary workaround if ( eventName == std::string_view( "toggle auto combat mode" ) ) { value = config.StrParams( "toggle battle auto mode" ); if ( value.empty() ) { continue; } } else if ( eventName == std::string_view( "quick combat" ) ) { value = config.StrParams( "finish the battle in auto mode" ); if ( value.empty() ) { continue; } } else { continue; } } value = StringUpper( value ); auto foundKey = nameToKey.find( value ); if ( foundKey == nameToKey.end() ) { continue; } hotKeyEventInfo[eventId].key = foundKey->second; DEBUG_LOG( DBG_GAME, DBG_INFO, "Event '" << eventName << "' has key '" << value << "'" ) } } } HotKeySave(); } void Game::HotKeySave() { const std::string filename = System::concatPath( System::GetConfigDirectory( "fheroes2" ), "fheroes2.key" ); StreamFile fileStream; if ( !fileStream.open( filename, "w" ) ) { ERROR_LOG( "Unable to open the hotkey settings file " << filename ) return; } const std::string data = getHotKeyFileContent(); fileStream.putRaw( data.data(), data.size() ); } void Game::globalKeyDownEvent( const fheroes2::Key key, const int32_t modifier ) { if ( ( modifier & fheroes2::KeyModifier::KEY_MODIFIER_ALT ) || ( modifier & fheroes2::KeyModifier::KEY_MODIFIER_CTRL ) ) { return; } Settings & conf = Settings::Get(); if ( key == hotKeyEventInfo[hotKeyEventToInt( HotKeyEvent::GLOBAL_TOGGLE_FULLSCREEN )].key ) { conf.setFullScreen( !conf.FullScreen() ); conf.Save( Settings::configFileName ); } else if ( key == hotKeyEventInfo[hotKeyEventToInt( HotKeyEvent::GLOBAL_TOGGLE_TEXT_SUPPORT_MODE )].key ) { conf.setTextSupportMode( !conf.isTextSupportModeEnabled() ); conf.Save( Settings::configFileName ); } #if defined( WITH_DEBUG ) else if ( key == hotKeyEventInfo[hotKeyEventToInt( HotKeyEvent::DEBUG_TOGGLE_DEVELOPER_MODE )].key ) { Logging::setDebugLevel( DBG_DEVEL ^ Logging::getDebugLevel() ); } else if ( key == hotKeyEventInfo[hotKeyEventToInt( HotKeyEvent::WORLD_TRANSFER_CONTROL_TO_AI )].key ) { static bool recursiveCall = false; if ( !recursiveCall ) { class RecursionGuard { public: explicit RecursionGuard( bool & rc ) : _recursiveCall( rc ) { _recursiveCall = true; } RecursionGuard( const RecursionGuard & ) = delete; ~RecursionGuard() { _recursiveCall = false; } RecursionGuard & operator=( const RecursionGuard & ) = delete; private: bool & _recursiveCall; }; const RecursionGuard recursionGuard( recursiveCall ); Player * player = Settings::Get().GetPlayers().GetCurrent(); // Do not allow to transfer control to/from AI during battle if ( player && ( player->isControlHuman() || player->isAIAutoControlMode() ) && Battle::GetArena() == nullptr ) { if ( player->isAIAutoControlMode() ) { if ( fheroes2::showStandardTextMessage( _( "Warning" ), _( "Do you want to regain control from AI? The effect will take place only on the next turn." ), Dialog::YES | Dialog::NO ) == Dialog::YES ) { player->setAIAutoControlMode( false ); } } else { if ( fheroes2::showStandardTextMessage( _( "Warning" ), _( "Do you want to transfer control from you to the AI? The effect will take place only on the next turn." ), Dialog::YES | Dialog::NO ) == Dialog::YES ) { player->setAIAutoControlMode( true ); } } } } } #endif } const char * Game::getHotKeyCategoryName( const HotKeyCategory category ) { switch ( category ) { case HotKeyCategory::DEFAULT: return gettext_noop( "Default Actions" ); case HotKeyCategory::GLOBAL: return gettext_noop( "Global Actions" ); case HotKeyCategory::MAIN_MENU: return gettext_noop( "Main Menu" ); case HotKeyCategory::CAMPAIGN: return gettext_noop( "Campaign" ); case HotKeyCategory::WORLD_MAP: return gettext_noop( "World Map" ); case HotKeyCategory::BATTLE: return gettext_noop( "Battle Screen" ); case HotKeyCategory::TOWN: return gettext_noop( "Town Screen" ); case HotKeyCategory::ARMY: return gettext_noop( "Army Actions" ); case HotKeyCategory::EDITOR: return gettext_noop( "Editor" ); default: // Did you add a new category? Add the logic above! assert( 0 ); break; } return ""; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_hotkeys.h000066400000000000000000000145761476115357100222470ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include namespace fheroes2 { enum class Key : int32_t; } namespace Game { enum class HotKeyEvent : int32_t { NONE, DEFAULT_OKAY, DEFAULT_CANCEL, DEFAULT_LEFT, DEFAULT_RIGHT, DEFAULT_UP, DEFAULT_DOWN, GLOBAL_TOGGLE_FULLSCREEN, GLOBAL_TOGGLE_TEXT_SUPPORT_MODE, #if defined( WITH_DEBUG ) // This hotkey is only for debug mode. DEBUG_TOGGLE_DEVELOPER_MODE, #endif MAIN_MENU_NEW_GAME, MAIN_MENU_LOAD_GAME, MAIN_MENU_HIGHSCORES, MAIN_MENU_CREDITS, MAIN_MENU_STANDARD, MAIN_MENU_CAMPAIGN, MAIN_MENU_MULTI, MAIN_MENU_SETTINGS, MAIN_MENU_QUIT, MAIN_MENU_SELECT_MAP, MAIN_MENU_MAP_SIZE_SMALL, MAIN_MENU_MAP_SIZE_MEDIUM, MAIN_MENU_MAP_SIZE_LARGE, MAIN_MENU_MAP_SIZE_EXTRA_LARGE, MAIN_MENU_MAP_SIZE_ALL, MAIN_MENU_HOTSEAT, MAIN_MENU_BATTLEONLY, MAIN_MENU_NEW_ORIGINAL_CAMPAIGN, MAIN_MENU_NEW_EXPANSION_CAMPAIGN, EDITOR_MAIN_MENU, EDITOR_NEW_MAP_MENU, EDITOR_LOAD_MAP_MENU, EDITOR_FROM_SCRATCH_MAP_MENU, EDITOR_RANDOM_MAP_MENU, EDITOR_UNDO_LAST_ACTION, EDITOR_REDO_LAST_ACTION, EDITOR_TO_GAME_MAIN_MENU, EDITOR_TOGGLE_PASSABILITY, CAMPAIGN_ROLAND, CAMPAIGN_ARCHIBALD, CAMPAIGN_PRICE_OF_LOYALTY, CAMPAIGN_VOYAGE_HOME, CAMPAIGN_WIZARDS_ISLE, CAMPAIGN_DESCENDANTS, CAMPAIGN_SELECT_FIRST_BONUS, CAMPAIGN_SELECT_SECOND_BONUS, CAMPAIGN_SELECT_THIRD_BONUS, CAMPAIGN_VIEW_INTRO, CAMPAIGN_SELECT_DIFFICULTY, CAMPAIGN_RESTART_SCENARIO, // Move the hero if there is a selected one, otherwise scroll the adventure map. WORLD_LEFT, WORLD_RIGHT, WORLD_UP, WORLD_DOWN, WORLD_UP_LEFT, WORLD_UP_RIGHT, WORLD_DOWN_LEFT, WORLD_DOWN_RIGHT, // WORLD_SAVE_GAME, WORLD_NEXT_HERO, WORLD_QUICK_SELECT_HERO, WORLD_START_HERO_MOVEMENT, WORLD_CAST_SPELL, WORLD_SLEEP_HERO, WORLD_NEXT_TOWN, WORLD_END_TURN, WORLD_FILE_OPTIONS, WORLD_ADVENTURE_OPTIONS, WORLD_PUZZLE_MAP, WORLD_SCENARIO_INFORMATION, WORLD_DIG_ARTIFACT, WORLD_VIEW_WORLD, WORLD_KINGDOM_SUMMARY, WORLD_DEFAULT_ACTION, WORLD_OPEN_FOCUS, WORLD_SYSTEM_OPTIONS, // Scroll the adventure map regardless of the selected object. WORLD_SCROLL_LEFT, WORLD_SCROLL_RIGHT, WORLD_SCROLL_UP, WORLD_SCROLL_DOWN, // WORLD_TOGGLE_CONTROL_PANEL, WORLD_TOGGLE_RADAR, WORLD_TOGGLE_BUTTONS, WORLD_TOGGLE_STATUS, WORLD_TOGGLE_ICONS, #if defined( WITH_DEBUG ) // This hotkey is only for debug mode as of now. WORLD_TRANSFER_CONTROL_TO_AI, #endif BATTLE_RETREAT, BATTLE_SURRENDER, BATTLE_TOGGLE_AUTO_COMBAT, BATTLE_QUICK_COMBAT, BATTLE_OPTIONS, BATTLE_SKIP, BATTLE_CAST_SPELL, TOWN_DWELLING_LEVEL_1, TOWN_DWELLING_LEVEL_2, TOWN_DWELLING_LEVEL_3, TOWN_DWELLING_LEVEL_4, TOWN_DWELLING_LEVEL_5, TOWN_DWELLING_LEVEL_6, TOWN_WELL, TOWN_MARKETPLACE, TOWN_MAGE_GUILD, TOWN_SHIPYARD, TOWN_THIEVES_GUILD, TOWN_TAVERN, // Also used to build a castle in the town. TOWN_CONSTRUCTION, TOWN_WELL_BUY_ALL, ARMY_SPLIT_STACK_BY_HALF, ARMY_SPLIT_STACK_BY_ONE, ARMY_JOIN_STACKS, ARMY_UPGRADE_TROOP, ARMY_DISMISS, ARMY_SWAP, // WARNING! Put all new event only above this line. No adding in between. NO_EVENT, }; enum class HotKeyCategory : uint8_t { DEFAULT, GLOBAL, MAIN_MENU, CAMPAIGN, WORLD_MAP, BATTLE, TOWN, ARMY, EDITOR, }; bool HotKeyPressEvent( const HotKeyEvent eventID ); bool HotKeyHoldEvent( const HotKeyEvent eventID ); fheroes2::Key getHotKeyForEvent( const HotKeyEvent eventID ); void setHotKeyForEvent( const HotKeyEvent eventID, const fheroes2::Key key ); inline bool HotKeyCloseWindow() { return HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) || HotKeyPressEvent( HotKeyEvent::DEFAULT_OKAY ); } std::string getHotKeyNameByEventId( const HotKeyEvent eventID ); const char * getHotKeyEventNameByEventId( const HotKeyEvent eventID ); std::vector> getAllHotKeyEvents(); void globalKeyDownEvent( const fheroes2::Key key, const int32_t modifier ); void HotKeysLoad( const std::string & filename ); void HotKeySave(); const char * getHotKeyCategoryName( const HotKeyCategory category ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_interface.cpp000066400000000000000000000275711476115357100230530ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_interface.h" #include #include #include "agg_image.h" #include "cursor.h" #include "dialog.h" #include "game.h" #include "game_delays.h" #include "game_hotkeys.h" #include "icn.h" #include "image.h" #include "interface_border.h" #include "interface_gamearea.h" #include "interface_radar.h" #include "interface_status.h" #include "localevent.h" #include "maps.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "ui_button.h" #include "ui_constants.h" #include "ui_tool.h" #include "world.h" Interface::AdventureMap::AdventureMap() : BaseInterface( false ) , _iconsPanel( *this ) , _buttonsPanel( *this ) , _controlPanel( *this ) , _statusPanel( *this ) , _lockRedraw( false ) { AdventureMap::reset(); } void Interface::AdventureMap::reset() { const fheroes2::Display & display = fheroes2::Display::instance(); Settings & conf = Settings::Get(); const bool isHideInterface = conf.isHideInterfaceEnabled(); if ( isHideInterface ) { conf.SetShowControlPanel( true ); _controlPanel.SetPos( display.width() - _controlPanel.GetArea().width - fheroes2::borderWidthPx, 0 ); fheroes2::Point radrPos = conf.PosRadar(); fheroes2::Point bttnPos = conf.PosButtons(); fheroes2::Point iconPos = conf.PosIcons(); fheroes2::Point statPos = conf.PosStatus(); const auto isPosValid = []( const fheroes2::Point & pos ) { return pos.x >= 0 && pos.y >= 0; }; if ( isPosValid( radrPos ) && isPosValid( bttnPos ) && isPosValid( iconPos ) && isPosValid( statPos ) ) { _radar.SetPos( radrPos.x, radrPos.y ); _iconsPanel.SetPos( iconPos.x, iconPos.y ); _buttonsPanel.SetPos( bttnPos.x, bttnPos.y ); _statusPanel.SetPos( statPos.x, statPos.y ); } else { _radar.SetPos( 0, 0 ); // It's OK to use display.width() for the X coordinate here, panel will be docked to the right edge _iconsPanel.SetPos( display.width(), _radar.GetRect().y + _radar.GetRect().height ); _buttonsPanel.SetPos( display.width(), _iconsPanel.GetRect().y + _iconsPanel.GetRect().height ); _statusPanel.SetPos( display.width(), _buttonsPanel.GetRect().y + _buttonsPanel.GetRect().height ); } } else { const int32_t px = display.width() - fheroes2::borderWidthPx - fheroes2::radarWidthPx; _radar.SetPos( px, fheroes2::borderWidthPx ); _iconsPanel.SetPos( px, _radar.GetArea().y + _radar.GetArea().height + fheroes2::borderWidthPx ); _buttonsPanel.SetPos( px, _iconsPanel.GetArea().y + _iconsPanel.GetArea().height + fheroes2::borderWidthPx ); _statusPanel.SetPos( px, _buttonsPanel.GetArea().y + _buttonsPanel.GetArea().height ); } const fheroes2::Point prevCenter = _gameArea.getCurrentCenterInPixels(); const fheroes2::Rect prevRoi = _gameArea.GetROI(); _gameArea.generate( { display.width(), display.height() }, isHideInterface ); const fheroes2::Rect newRoi = _gameArea.GetROI(); _gameArea.SetCenterInPixels( prevCenter + fheroes2::Point( newRoi.x + newRoi.width / 2, newRoi.y + newRoi.height / 2 ) - fheroes2::Point( prevRoi.x + prevRoi.width / 2, prevRoi.y + prevRoi.height / 2 ) ); } Interface::AdventureMap & Interface::AdventureMap::Get() { static AdventureMap basic; return basic; } void Interface::AdventureMap::redraw( const uint32_t force ) { if ( _lockRedraw ) { setRedraw( force ); return; } const Settings & conf = Settings::Get(); const uint32_t combinedRedraw = _redraw | force; const bool hideInterface = conf.isHideInterfaceEnabled(); if ( combinedRedraw & REDRAW_GAMEAREA ) { _gameArea.Redraw( fheroes2::Display::instance(), LEVEL_ALL ); if ( hideInterface && conf.ShowControlPanel() ) { _controlPanel._redraw(); } } if ( ( hideInterface && conf.ShowRadar() ) || ( combinedRedraw & ( REDRAW_RADAR_CURSOR | REDRAW_RADAR ) ) ) { // Redraw radar map only if `REDRAW_RADAR` is set. _radar._redraw( combinedRedraw & REDRAW_RADAR ); } if ( ( hideInterface && conf.ShowIcons() ) || ( combinedRedraw & REDRAW_ICONS ) ) { _iconsPanel._redraw(); } else if ( combinedRedraw & REDRAW_HEROES ) { _iconsPanel._redrawIcons( ICON_HEROES ); } else if ( combinedRedraw & REDRAW_CASTLES ) { _iconsPanel._redrawIcons( ICON_CASTLES ); } if ( ( hideInterface && conf.ShowButtons() ) || ( combinedRedraw & REDRAW_BUTTONS ) ) { _buttonsPanel._redraw(); } if ( ( hideInterface && conf.ShowStatus() ) || ( combinedRedraw & REDRAW_STATUS ) ) { _statusPanel._redraw(); } if ( combinedRedraw & REDRAW_BORDER ) { GameBorderRedraw( false ); } _redraw = 0; } int32_t Interface::AdventureMap::GetDimensionDoorDestination( const int32_t from, const int32_t distance, const bool water ) { fheroes2::Display & display = fheroes2::Display::instance(); Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); const bool isHideInterface = conf.isHideInterfaceEnabled(); const bool isIconsVisible = conf.ShowIcons(); const bool isButtonsVisible = conf.ShowButtons(); const bool isStatusVisible = conf.ShowStatus(); const bool isControlPanelVisible = conf.ShowControlPanel(); const fheroes2::Rect & radarRect = _radar.GetRect(); const fheroes2::Rect & radarArea = _radar.GetArea(); fheroes2::Button buttonExit( radarArea.x + 32, radarArea.y + radarArea.height - 37, ( isEvilInterface ? ICN::BUTTON_EXIT_PUZZLE_DIM_DOOR_EVIL : ICN::BUTTON_EXIT_PUZZLE_DIM_DOOR_GOOD ), 0, 1 ); const auto drawControlPanel = [&display, isEvilInterface, isHideInterface, &radarRect, &radarArea, &buttonExit]() { if ( isHideInterface ) { Dialog::FrameBorder::RenderRegular( radarRect ); } fheroes2::Blit( fheroes2::AGG::GetICN( ( isEvilInterface ? ICN::EVIWDDOR : ICN::VIEWDDOR ), 0 ), display, radarArea.x, radarArea.y ); buttonExit.draw(); }; const fheroes2::Rect & gameAreaROI = _gameArea.GetROI(); const bool isFadingEnabled = ( gameAreaROI.width > fheroes2::tileWidthPx * distance ) || ( gameAreaROI.height > fheroes2::tileWidthPx * distance ); const fheroes2::Rect spellROI = [this, from, distance, isHideInterface, &gameAreaROI]() -> fheroes2::Rect { const fheroes2::Point heroPos = _gameArea.GetRelativeTilePosition( Maps::GetPoint( from ) ); const int32_t x = heroPos.x - fheroes2::tileWidthPx * ( distance / 2 ); const int32_t y = heroPos.y - fheroes2::tileWidthPx * ( distance / 2 ); // We need to add an extra cell since the hero stands exactly in the middle of a cell const int32_t w = std::min( fheroes2::tileWidthPx * ( distance + 1 ), gameAreaROI.width ); const int32_t h = std::min( fheroes2::tileWidthPx * ( distance + 1 ), gameAreaROI.height ); return { isHideInterface ? x : std::max( x, fheroes2::borderWidthPx ), isHideInterface ? y : std::max( y, fheroes2::borderWidthPx ), w, h }; }(); if ( isHideInterface ) { // There is no need to hide the radar because it will be replaced by the Dimension Door control panel conf.SetShowIcons( false ); conf.SetShowButtons( false ); conf.SetShowStatus( false ); conf.SetShowControlPanel( false ); redraw( REDRAW_GAMEAREA ); } if ( isFadingEnabled ) { if ( isHideInterface ) { InvertedShadow( display, gameAreaROI, spellROI, 5, 9 ); drawControlPanel(); } else { drawControlPanel(); fheroes2::InvertedFadeWithPalette( display, gameAreaROI, spellROI, 5, 300, 9 ); } } else { drawControlPanel(); } display.render(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); Cursor & cursor = Cursor::Get(); LocalEvent & le = LocalEvent::Get(); int32_t returnValue = -1; while ( le.HandleEvents( Game::isDelayNeeded( { Game::MAPS_DELAY } ) ) ) { const fheroes2::Point & mp = le.getMouseCursorPos(); if ( radarRect & mp ) { cursor.SetThemes( Cursor::POINTER ); buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) { break; } } else if ( gameAreaROI & mp ) { const int32_t dst = _gameArea.GetValidTileIdFromPoint( mp ); bool valid = ( dst >= 0 ); if ( valid ) { valid = ( spellROI & mp ) && Maps::isValidForDimensionDoor( dst, water ); } cursor.SetThemes( valid ? ( water ? static_cast( Cursor::CURSOR_HERO_BOAT ) : static_cast( Cursor::CURSOR_HERO_MOVE ) ) : static_cast( Cursor::WAR_NONE ) ); if ( dst >= 0 && le.isMouseRightButtonPressed() ) { Dialog::QuickInfo( world.getTile( dst ) ); } else if ( le.MouseClickLeft() && valid ) { returnValue = dst; break; } } else { cursor.SetThemes( Cursor::POINTER ); } if ( Game::validateAnimationDelay( Game::MAPS_DELAY ) ) { Game::updateAdventureMapAnimationIndex(); redraw( REDRAW_GAMEAREA ); if ( isFadingEnabled ) { InvertedShadow( display, gameAreaROI, spellROI, 5, 9 ); if ( isHideInterface ) { drawControlPanel(); } } display.render(); } } if ( isFadingEnabled ) { setRedraw( REDRAW_GAMEAREA ); } if ( isHideInterface ) { conf.SetShowIcons( isIconsVisible ); conf.SetShowButtons( isButtonsVisible ); conf.SetShowStatus( isStatusVisible ); conf.SetShowControlPanel( isControlPanelVisible ); setRedraw( REDRAW_ICONS | REDRAW_BUTTONS | REDRAW_STATUS | REDRAW_GAMEAREA ); } redraw( REDRAW_RADAR_CURSOR ); display.render(); return returnValue; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_interface.h000066400000000000000000000145261476115357100225140ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "game_mode.h" #include "interface_base.h" #include "interface_buttons.h" #include "interface_cpanel.h" #include "interface_icons.h" #include "interface_status.h" #include "players.h" class Castle; class Heroes; namespace Maps { class Tile; } namespace GameFocus { enum { UNSEL = FOCUS_UNSEL, HEROES = FOCUS_HEROES, CASTLE = FOCUS_CASTLE, FIRSTHERO }; } namespace Interface { Castle * GetFocusCastle(); Heroes * GetFocusHeroes(); int GetFocusType(); class AdventureMap final : public BaseInterface { public: // This class is used to lock rendering of Basic class. This is useful when we have to generate only a single frame. // Use this class ONLY when you are going to call rendering after all other operations. class RedrawLocker { public: explicit RedrawLocker( AdventureMap & interface_ ) : _interface( interface_ ) { _interface._lockRedraw = true; } RedrawLocker( const RedrawLocker & ) = delete; RedrawLocker( RedrawLocker && ) = delete; RedrawLocker & operator=( const RedrawLocker & ) = delete; RedrawLocker & operator=( RedrawLocker && ) = delete; ~RedrawLocker() { _interface._lockRedraw = false; } private: AdventureMap & _interface; }; static AdventureMap & Get(); void redraw( const uint32_t force ) override; int32_t GetDimensionDoorDestination( const int32_t from, const int32_t distance, const bool water ); IconsPanel & GetIconsPanel() { return _iconsPanel; } ControlPanel & getControlPanel() { return _controlPanel; } StatusPanel & getStatusPanel() { return _statusPanel; } void SetFocus( Heroes *, const bool retainScrollBarPosition ); void SetFocus( Castle * ); void ResetFocus( const int priority, const bool retainScrollBarPosition ); void RedrawFocus(); void updateFocus(); void EventSwitchHeroSleeping(); fheroes2::GameMode EventDefaultAction(); void EventOpenFocus() const; fheroes2::GameMode EventSaveGame() const; void EventPuzzleMaps() const; static fheroes2::GameMode EventScenarioInformation(); void EventSystemDialog() const; void EventSwitchFocusedHero( const int32_t tileIndex ); void EventNextHero(); void EventNextTown(); fheroes2::GameMode EventHeroMovement(); void EventResetHeroPath(); void EventKingdomInfo() const; void EventCastSpell(); void EventSwitchShowRadar() const; void EventSwitchShowStatus() const; void EventSwitchShowButtons() const; void EventSwitchShowIcons() const; void EventSwitchShowControlPanel() const; fheroes2::GameMode EventNewGame() const; fheroes2::GameMode EventLoadGame() const; fheroes2::GameMode EventAdventureDialog(); void EventViewWorld(); fheroes2::GameMode EventFileDialog() const; fheroes2::GameMode EventEndTurn() const; fheroes2::GameMode EventDigArtifact(); void EventKeyArrowPress( int direct ); fheroes2::GameMode StartGame(); void mouseCursorAreaClickLeft( const int32_t tileIndex ) override; void mouseCursorAreaPressRight( const int32_t tileIndex ) const override; void mouseCursorAreaLongPressLeft( const int32_t tileIndex ) override; void updateCursor( const int32_t tileIndex ) override; // Regenerates the game area and updates the panel positions depending on the UI settings void reset() override; private: AdventureMap(); static int GetCursorFocusCastle( const Castle & castle, const Maps::Tile & tile ); static int GetCursorFocusHeroes( const Heroes & hero, const Maps::Tile & tile ); static int GetCursorFocusShipmaster( const Heroes & hero, const Maps::Tile & tile ); static int _getCursorNoFocus( const Maps::Tile & tile ); static int GetCursorTileIndex( int32_t dstIndex ); void ShowPathOrStartMoveHero( Heroes * hero, const int32_t destinationIdx ); void MoveHeroFromArrowKeys( Heroes & hero, const int direction ); void _startHeroMove( Heroes & hero ); fheroes2::GameMode HumanTurn( const bool isLoadedFromSave ); IconsPanel _iconsPanel; ButtonsPanel _buttonsPanel; ControlPanel _controlPanel; StatusPanel _statusPanel; bool _lockRedraw; }; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_io.cpp000066400000000000000000000317261476115357100215170ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_io.h" #include #include #include #include #include #include #include "campaign_savedata.h" #include "campaign_scenariodata.h" #include "dialog.h" #include "game.h" #include "game_over.h" #include "logging.h" #include "maps_fileinfo.h" #include "save_format_version.h" #include "serialize.h" #include "settings.h" #include "system.h" #include "translations.h" #include "ui_dialog.h" #include "ui_language.h" #include "world.h" #include "zzlib.h" namespace { const std::string autoSaveName{ "AUTOSAVE" }; const uint16_t SAV2ID3 = 0xFF03; uint16_t versionOfCurrentSaveFile = CURRENT_FORMAT_VERSION; std::string lastSaveName; struct HeaderSAV { enum { REQUIRES_POL_RESOURCES = 0x4000 }; HeaderSAV() : status( 0 ) , gameType( 0 ) {} HeaderSAV( const Maps::FileInfo & fi, const int type, const uint32_t worldDay, const uint32_t worldWeek, const uint32_t worldMonth ) : status( 0 ) , info( fi ) , gameType( type ) { time_t rawtime; std::time( &rawtime ); info.timestamp = static_cast( rawtime ); info.worldDay = worldDay; info.worldWeek = worldWeek; info.worldMonth = worldMonth; if ( fi.version != GameVersion::SUCCESSION_WARS ) { status |= REQUIRES_POL_RESOURCES; } } uint16_t status; Maps::FileInfo info; int gameType; }; OStreamBase & operator<<( OStreamBase & stream, const HeaderSAV & hdr ) { return stream << hdr.status << hdr.info << hdr.gameType; } IStreamBase & operator>>( IStreamBase & stream, HeaderSAV & hdr ) { return stream >> hdr.status >> hdr.info >> hdr.gameType; } } bool Game::AutoSave() { return Game::Save( System::concatPath( GetSaveDir(), autoSaveName + GetSaveFileExtension() ), true ); } bool Game::Save( const std::string & filePath, const bool autoSave /* = false */ ) { DEBUG_LOG( DBG_GAME, DBG_INFO, filePath ) const Settings & conf = Settings::Get(); StreamFile fileStream; fileStream.setBigendian( true ); if ( !fileStream.open( filePath, "wb" ) ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "Error opening the file " << filePath ) return false; } // Always use the latest version of the file save format SetVersionOfCurrentSaveFile( CURRENT_FORMAT_VERSION ); uint16_t saveFileVersion = CURRENT_FORMAT_VERSION; // Header fileStream << SAV2ID3 << std::to_string( saveFileVersion ) << saveFileVersion << HeaderSAV( conf.getCurrentMapInfo(), conf.GameType(), world.GetDay(), world.GetWeek(), world.GetMonth() ); if ( fileStream.fail() ) { return false; } RWStreamBuf dataStream; dataStream.setBigendian( true ); dataStream << World::Get() << Settings::Get() << GameOver::Result::Get(); if ( dataStream.fail() ) { return false; } if ( conf.isCampaignGameType() ) { dataStream << Campaign::CampaignSaveData::Get(); } // End-of-data marker dataStream << SAV2ID3; if ( dataStream.fail() || !Compression::zipStreamBuf( dataStream, fileStream ) ) { return false; } if ( !autoSave ) { Game::SetLastSaveName( filePath ); } return true; } fheroes2::GameMode Game::Load( const std::string & filePath ) { DEBUG_LOG( DBG_GAME, DBG_INFO, filePath ) const auto showGenericErrorMessage = []() { fheroes2::showStandardTextMessage( _( "Error" ), _( "The save file is corrupted." ), Dialog::OK ); }; StreamFile fileStream; fileStream.setBigendian( true ); if ( !fileStream.open( filePath, "rb" ) ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "Error opening the file " << filePath ) showGenericErrorMessage(); return fheroes2::GameMode::CANCEL; } uint16_t savId = 0; fileStream >> savId; if ( savId != SAV2ID3 ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "Invalid file identifier in the file " << filePath ) showGenericErrorMessage(); return fheroes2::GameMode::CANCEL; } std::string saveFileVersionStr; uint16_t saveFileVersion = 0; fileStream >> saveFileVersionStr >> saveFileVersion; if ( fileStream.fail() ) { showGenericErrorMessage(); return fheroes2::GameMode::CANCEL; } DEBUG_LOG( DBG_GAME, DBG_TRACE, "Version of the file " << filePath << ": " << saveFileVersion ) if ( saveFileVersion > CURRENT_FORMAT_VERSION || saveFileVersion < LAST_SUPPORTED_FORMAT_VERSION ) { std::string errorMessage( _( "Unsupported save format: " ) ); errorMessage += std::to_string( saveFileVersion ); errorMessage += ".\n"; errorMessage += _( "Current game version: " ); errorMessage += std::to_string( CURRENT_FORMAT_VERSION ); errorMessage += ".\n"; errorMessage += _( "Last supported version: " ); errorMessage += std::to_string( LAST_SUPPORTED_FORMAT_VERSION ); errorMessage += ".\n"; fheroes2::showStandardTextMessage( _( "Error" ), errorMessage, Dialog::OK ); return fheroes2::GameMode::CANCEL; } SetVersionOfCurrentSaveFile( saveFileVersion ); HeaderSAV header; fileStream >> header; Settings & conf = Settings::Get(); if ( ( conf.GameType() & header.gameType ) == 0 ) { fheroes2::showStandardTextMessage( _( "Error" ), _( "This file contains a save with an invalid game type." ), Dialog::OK ); return fheroes2::GameMode::CANCEL; } RWStreamBuf dataStream; dataStream.setBigendian( true ); if ( !Compression::unzipStream( fileStream, dataStream ) ) { showGenericErrorMessage(); return fheroes2::GameMode::CANCEL; } if ( ( header.status & HeaderSAV::REQUIRES_POL_RESOURCES ) && !conf.isPriceOfLoyaltySupported() ) { fheroes2::showStandardTextMessage( _( "Error" ), _( "This save file requires \"The Price of Loyalty\" game assets, but they have not been provided to the engine." ), Dialog::OK ); return fheroes2::GameMode::CANCEL; } dataStream >> World::Get() >> conf >> GameOver::Result::Get(); if ( dataStream.fail() ) { showGenericErrorMessage(); return fheroes2::GameMode::CANCEL; } fheroes2::GameMode returnValue = fheroes2::GameMode::START_GAME; if ( conf.isCampaignGameType() ) { Campaign::CampaignSaveData & saveData = Campaign::CampaignSaveData::Get(); dataStream >> saveData; if ( !saveData.isStarting() && saveData.getCurrentScenarioInfoId() == saveData.getLastCompletedScenarioInfoID() ) { // This is the end of the current scenario. We should show next scenario selection. returnValue = fheroes2::GameMode::COMPLETE_CAMPAIGN_SCENARIO_FROM_LOAD_FILE; } } uint16_t endOfDataMarker = 0; dataStream >> endOfDataMarker; if ( dataStream.fail() || endOfDataMarker != SAV2ID3 ) { showGenericErrorMessage(); return fheroes2::GameMode::CANCEL; } // Settings should contain the full path to the current map file, if this map is available conf.getCurrentMapInfo().filename = Settings::GetLastFile( "maps", System::GetFileName( conf.getCurrentMapInfo().filename ) ); if ( !conf.loadedFileLanguage().empty() && conf.loadedFileLanguage() != "en" && conf.loadedFileLanguage() != conf.getGameLanguage() ) { std::string warningMessage( _( "This saved game is localized to '" ) ); warningMessage.append( fheroes2::getLanguageName( fheroes2::getLanguageFromAbbreviation( conf.loadedFileLanguage() ) ) ); warningMessage.append( _( "' language, but the current language of the game is '" ) ); warningMessage.append( fheroes2::getLanguageName( fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() ) ) ); warningMessage += "'."; fheroes2::showStandardTextMessage( _( "Warning" ), warningMessage, Dialog::OK ); } Game::SetLastSaveName( filePath ); conf.SetGameType( conf.GameType() | Game::TYPE_LOADFILE ); return returnValue; } bool Game::LoadSAV2FileInfo( std::string filePath, Maps::FileInfo & fileInfo ) { DEBUG_LOG( DBG_GAME, DBG_INFO, filePath ) StreamFile fs; fs.setBigendian( true ); if ( !fs.open( filePath, "rb" ) ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "Error opening the file " << filePath ) return false; } uint16_t savId = 0; fs >> savId; if ( savId != SAV2ID3 ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "Invalid file identifier in the file " << filePath ) return false; } std::string saveFileVersionStr; uint16_t saveFileVersion = 0; fs >> saveFileVersionStr >> saveFileVersion; DEBUG_LOG( DBG_GAME, DBG_TRACE, "Version of the file " << filePath << ": " << saveFileVersion ) if ( saveFileVersion > CURRENT_FORMAT_VERSION || saveFileVersion < LAST_SUPPORTED_FORMAT_VERSION ) { return false; } SetVersionOfCurrentSaveFile( saveFileVersion ); HeaderSAV header; fs >> header; if ( fs.fail() ) { return false; } if ( ( Settings::Get().GameType() & header.gameType ) == 0 ) { return false; } fileInfo = std::move( header.info ); fileInfo.filename = std::move( filePath ); return true; } void Game::SetVersionOfCurrentSaveFile( const uint16_t version ) { versionOfCurrentSaveFile = version; } uint16_t Game::GetVersionOfCurrentSaveFile() { return versionOfCurrentSaveFile; } const std::string & Game::GetLastSaveName() { return lastSaveName; } void Game::SetLastSaveName( const std::string & name ) { lastSaveName = name; } std::string Game::GetSaveDir() { return System::concatPath( System::concatPath( System::GetDataDirectory( "fheroes2" ), "files" ), "save" ); } std::string Game::GetSaveFileBaseName() { std::string baseName = Settings::Get().getCurrentMapInfo().name; // Replace all non-ASCII characters by exclamation marks std::replace_if( baseName.begin(), baseName.end(), []( const unsigned char c ) { return ( c > 127 ); }, '!' ); // Remove all non-printable characters baseName.erase( std::remove_if( baseName.begin(), baseName.end(), []( const unsigned char c ) { return !std::isprint( c ); } ), baseName.end() ); // Replace all remaining non-alphanumeric characters (excluding exclamation marks) by underscores std::replace_if( baseName.begin(), baseName.end(), []( const unsigned char c ) { return ( c != '!' && !std::isalnum( c ) ); }, '_' ); // If in the end there are no characters left, set the base name to "newgame" if ( baseName.empty() ) { baseName = "newgame"; } return baseName; } std::string Game::GetSaveFileExtension() { return GetSaveFileExtension( Settings::Get().GameType() ); } std::string Game::GetSaveFileExtension( const int gameType ) { if ( gameType & Game::TYPE_STANDARD ) return ".sav"; else if ( gameType & Game::TYPE_CAMPAIGN ) return ".savc"; else if ( gameType & Game::TYPE_HOTSEAT ) return ".savh"; return ".savm"; } bool Game::SaveCompletedCampaignScenario() { return Save( System::concatPath( GetSaveDir(), GetSaveFileBaseName() ) + "_Complete" + GetSaveFileExtension() ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_io.h000066400000000000000000000047561476115357100211670ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "game_mode.h" namespace Maps { struct FileInfo; } namespace Game { const std::string & GetLastSaveName(); void SetLastSaveName( const std::string & name ); uint16_t GetVersionOfCurrentSaveFile(); void SetVersionOfCurrentSaveFile( const uint16_t version ); std::string GetSaveDir(); std::string GetSaveFileBaseName(); std::string GetSaveFileExtension(); std::string GetSaveFileExtension( const int gameType ); bool AutoSave(); bool Save( const std::string & filePath, const bool autoSave = false ); // Returns GameMode::CANCEL in case of failure. fheroes2::GameMode Load( const std::string & filePath ); bool LoadSAV2FileInfo( std::string filePath, Maps::FileInfo & fileInfo ); bool SaveCompletedCampaignScenario(); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_language.h000066400000000000000000000043061476115357100223320ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include namespace fheroes2 { enum class SupportedLanguage : uint8_t { English = 0, // default language for all versions of the game. French, // GOG version Polish, // GOG version German, // GOG version Russian, // Buka and XXI Vek versions Italian, // Rare version? Czech, // Local release occurred in 2002 by CD Projekt Spanish, // Published by Proein. Only Succession Wars // All languages listed below are original to fheroes2. Belarusian, Bulgarian, Danish, Dutch, Hungarian, Norwegian, Portuguese, Romanian, Slovak, Swedish, Turkish, Ukrainian, Vietnamese }; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_loadgame.cpp000066400000000000000000000247221476115357100226570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game.h" // IWYU pragma: associated #include #include #include #include #include #include "audio.h" #include "audio_manager.h" #include "cursor.h" #include "dialog.h" #include "dir.h" #include "game_hotkeys.h" #include "game_io.h" #include "game_mainmenu_ui.h" #include "game_mode.h" #include "icn.h" #include "localevent.h" #include "logging.h" #include "math_base.h" #include "mus.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_tool.h" namespace { const int32_t buttonYStep = 66; void outputLoadGameInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Load Game\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_STANDARD ) << " to choose Standard Game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_CAMPAIGN ) << " to choose Campaign Game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_MULTI ) << " to show Multi-Player Game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to go back to Main Menu." ) } } fheroes2::GameMode Game::LoadCampaign() { Settings::Get().SetGameType( Game::TYPE_CAMPAIGN ); return DisplayLoadGameDialog(); } fheroes2::GameMode Game::LoadHotseat() { Settings::Get().SetGameType( Game::TYPE_HOTSEAT ); return DisplayLoadGameDialog(); } fheroes2::GameMode Game::LoadMulti() { fheroes2::Display & display = fheroes2::Display::instance(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); // image background fheroes2::drawMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonHotSeat( buttonPos.x, buttonPos.y, ICN::BUTTON_HOT_SEAT, 0, 1 ); fheroes2::Button buttonNetwork( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::BTNMP, 2, 3 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); buttonHotSeat.draw(); buttonCancel.draw(); buttonNetwork.disable(); display.render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonHotSeat.drawOnState( le.isMouseLeftButtonPressedInArea( buttonHotSeat.area() ) ); if ( buttonNetwork.isEnabled() ) { buttonNetwork.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNetwork.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonHotSeat.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_HOTSEAT ) ) { if ( ListFiles::IsEmpty( GetSaveDir(), GetSaveFileExtension( Game::TYPE_HOTSEAT ) ) ) { fheroes2::showStandardTextMessage( _( "Load Game" ), _( "No save files to load." ), Dialog::OK ); } else { return fheroes2::GameMode::LOAD_HOT_SEAT; } } else if ( HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return fheroes2::GameMode::LOAD_GAME; } // right info if ( le.isMouseRightButtonPressedInArea( buttonHotSeat.area() ) ) { fheroes2::showStandardTextMessage( _( "Hot Seat" ), _( "Play a Hot Seat game, where 2 to 6 players play around the same computer, switching into the 'Hot Seat' when it is their turn." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::LOAD_GAME; } fheroes2::GameMode Game::LoadGame() { outputLoadGameInTextSupportMode(); // Stop all sounds, but not the music AudioManager::stopSounds(); AudioManager::PlayMusicAsync( MUS::MAINMENU, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonStandardGame( 0, 0, ICN::BUTTON_STANDARD_GAME, 0, 1 ); fheroes2::Button buttonCampaignGame( 0, 0, ICN::BUTTON_CAMPAIGN_GAME, 0, 1 ); fheroes2::Button buttonMultiplayerGame( 0, 0, ICN::BUTTON_MULTIPLAYER_GAME, 0, 1 ); fheroes2::Button buttonCancel( 0, 0, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); const std::array buttons{ &buttonStandardGame, &buttonCampaignGame, &buttonMultiplayerGame, &buttonCancel }; if ( !isSuccessionWarsCampaignPresent() ) { buttonCampaignGame.disable(); } static_assert( buttons.size() > 1, "The number of buttons in this dialog cannot be less than 2!" ); for ( size_t i = 0; i < buttons.size() - 1; ++i ) { buttons[i]->setPosition( buttonPos.x, buttonPos.y + buttonYStep * static_cast( i ) ); buttons[i]->draw(); } // following the cancel button in new game buttonCancel.setPosition( buttonPos.x, buttonPos.y + buttonYStep * 5 ); buttonCancel.draw(); fheroes2::validateFadeInAndRender(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { for ( fheroes2::ButtonBase * button : buttons ) { button->drawOnState( le.isMouseLeftButtonPressedInArea( button->area() ) ); } if ( le.MouseClickLeft( buttonStandardGame.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_STANDARD ) ) { if ( ListFiles::IsEmpty( GetSaveDir(), GetSaveFileExtension( Game::TYPE_STANDARD ) ) ) { fheroes2::showStandardTextMessage( _( "Load Game" ), _( "No save files to load." ), Dialog::OK ); } else { return fheroes2::GameMode::LOAD_STANDARD; } } else if ( buttonCampaignGame.isEnabled() && ( le.MouseClickLeft( buttonCampaignGame.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_CAMPAIGN ) ) ) { if ( ListFiles::IsEmpty( GetSaveDir(), GetSaveFileExtension( Game::TYPE_CAMPAIGN ) ) ) { fheroes2::showStandardTextMessage( _( "Load Game" ), _( "No save files to load." ), Dialog::OK ); } else { return fheroes2::GameMode::LOAD_CAMPAIGN; } } else if ( le.MouseClickLeft( buttonMultiplayerGame.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_MULTI ) ) { return fheroes2::GameMode::LOAD_MULTI; } if ( le.MouseClickLeft( buttonCancel.area() ) || HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) ) { return fheroes2::GameMode::MAIN_MENU; } if ( le.isMouseRightButtonPressedInArea( buttonStandardGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Standard Game" ), _( "A single player game playing out a single map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCampaignGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Campaign Game" ), _( "A single player game playing through a series of maps." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonMultiplayerGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Multi-Player Game" ), _( "A multi-player game, with several human players completing against each other on a single map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::MAIN_MENU; } fheroes2::GameMode Game::LoadStandard() { Settings::Get().SetGameType( Game::TYPE_STANDARD ); return DisplayLoadGameDialog(); } fheroes2::GameMode Game::DisplayLoadGameDialog() { // Stop all sounds, but not the music AudioManager::stopSounds(); AudioManager::PlayMusicAsync( MUS::MAINMENU, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); // image background fheroes2::drawMainMenuScreen(); fheroes2::validateFadeInAndRender(); const std::string file = Dialog::SelectFileLoad(); if ( file.empty() ) { return fheroes2::GameMode::LOAD_GAME; } const fheroes2::GameMode returnValue = Game::Load( file ); if ( returnValue == fheroes2::GameMode::CANCEL ) { return fheroes2::GameMode::LOAD_GAME; } // We are loading a game so fade-out main menu screen. fheroes2::fadeOutDisplay(); setDisplayFadeIn(); return returnValue; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_logo.cpp000066400000000000000000000066031476115357100220440ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_logo.h" #include #include #include "game_delays.h" #include "image.h" #include "localevent.h" #include "math_base.h" #include "screen.h" #include "translations.h" #include "ui_text.h" #include "ui_tool.h" void fheroes2::showTeamInfo() { const ScreenPaletteRestorer restorer; Display & display = Display::instance(); Text text( _( "fheroes2 Resurrection Team presents" ), FontType::largeWhite() ); const int32_t correctedTextWidth = text.width( 500 ); const Rect roi{ ( display.width() - correctedTextWidth ) / 2, ( display.height() - text.height( correctedTextWidth ) ) / 2, text.width(), text.height( correctedTextWidth ) }; Image textImage( roi.width, roi.height ); textImage.fill( 0 ); text.draw( 0, 0, correctedTextWidth, textImage ); // First frame must be fully rendered. display.fill( 0 ); Copy( textImage, 0, 0, display, roi.x, roi.y, roi.width, roi.height ); display.render(); uint8_t alpha = 250; const uint64_t animationDelay = 40; // Immediately indicate that the delay has passed to render first frame immediately. Game::passCustomAnimationDelay( animationDelay ); // Make sure that the first run is passed immediately. assert( !Game::isCustomDelayNeeded( animationDelay ) ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isCustomDelayNeeded( animationDelay ) ) && alpha > 20 ) { if ( le.isAnyKeyPressed() || le.MouseClickLeft() || le.MouseClickMiddle() || le.MouseClickRight() ) break; // Subsequent frames must update only the area within the text. if ( Game::validateCustomAnimationDelay( animationDelay ) ) { Copy( textImage, 0, 0, display, roi.x, roi.y, roi.width, roi.height ); ApplyAlpha( display, roi.x, roi.y, display, roi.x, roi.y, roi.width, roi.height, alpha ); display.render( roi ); alpha -= 5; } } } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_logo.h000066400000000000000000000027671476115357100215200ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace fheroes2 { void showTeamInfo(); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_mainmenu.cpp000066400000000000000000000447161476115357100227240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "audio.h" #include "audio_manager.h" #include "cursor.h" #include "dialog.h" #include "dialog_game_settings.h" #include "dialog_language_selection.h" #include "dialog_resolution.h" #include "editor_mainmenu.h" #include "game.h" // IWYU pragma: associated #include "game_delays.h" #include "game_hotkeys.h" #include "game_interface.h" #include "game_mainmenu_ui.h" #include "game_mode.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "logging.h" #include "math_base.h" #include "mus.h" #include "screen.h" #include "settings.h" #include "system.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_tool.h" namespace { struct ButtonInfo { uint32_t frame; fheroes2::Button & button; const fheroes2::Rect & buttonArea; bool isOver; bool wasOver; }; enum { NEWGAME_DEFAULT = 1, LOADGAME_DEFAULT = 5, HIGHSCORES_DEFAULT = 9, CREDITS_DEFAULT = 13, QUIT_DEFAULT = 17, EDITOR_DEFAULT = 20 }; void outputMainMenuInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Main Menu\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_NEW_GAME ) << " to choose New Game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME ) << " to choose Load previously saved game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_HIGHSCORES ) << " to show High Scores." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_CREDITS ) << " to show Credits." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_SETTINGS ) << " to open Game Settings." ) if ( Settings::Get().isPriceOfLoyaltySupported() ) { COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::EDITOR_MAIN_MENU ) << " to open Editor." ) } COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_QUIT ) << " or " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to Quit the game." ) } } void Game::mainGameLoop( bool isFirstGameRun, bool isProbablyDemoVersion ) { fheroes2::GameMode result = fheroes2::GameMode::MAIN_MENU; bool exit = false; while ( !exit ) { switch ( result ) { case fheroes2::GameMode::QUIT_GAME: exit = true; break; case fheroes2::GameMode::MAIN_MENU: result = Game::MainMenu( isFirstGameRun ); isFirstGameRun = false; break; case fheroes2::GameMode::NEW_GAME: result = Game::NewGame( isProbablyDemoVersion ); isProbablyDemoVersion = false; break; case fheroes2::GameMode::LOAD_GAME: result = Game::LoadGame(); break; case fheroes2::GameMode::HIGHSCORES_STANDARD: result = Game::DisplayHighScores( false ); break; case fheroes2::GameMode::HIGHSCORES_CAMPAIGN: result = Game::DisplayHighScores( true ); break; case fheroes2::GameMode::CREDITS: result = Game::Credits(); break; case fheroes2::GameMode::NEW_STANDARD: result = Game::NewStandard(); break; case fheroes2::GameMode::NEW_CAMPAIGN_SELECTION: result = Game::CampaignSelection(); break; case fheroes2::GameMode::NEW_SUCCESSION_WARS_CAMPAIGN: result = Game::NewSuccessionWarsCampaign(); break; case fheroes2::GameMode::NEW_PRICE_OF_LOYALTY_CAMPAIGN: result = Game::NewPriceOfLoyaltyCampaign(); break; case fheroes2::GameMode::NEW_MULTI: result = Game::NewMulti(); break; case fheroes2::GameMode::NEW_HOT_SEAT: result = Game::NewHotSeat(); break; case fheroes2::GameMode::NEW_BATTLE_ONLY: result = Game::NewBattleOnly(); break; case fheroes2::GameMode::LOAD_STANDARD: result = Game::LoadStandard(); break; case fheroes2::GameMode::LOAD_CAMPAIGN: result = Game::LoadCampaign(); break; case fheroes2::GameMode::LOAD_MULTI: result = Game::LoadMulti(); break; case fheroes2::GameMode::LOAD_HOT_SEAT: result = Game::LoadHotseat(); break; case fheroes2::GameMode::SELECT_SCENARIO_ONE_HUMAN_PLAYER: case fheroes2::GameMode::SELECT_SCENARIO_TWO_HUMAN_PLAYERS: case fheroes2::GameMode::SELECT_SCENARIO_THREE_HUMAN_PLAYERS: case fheroes2::GameMode::SELECT_SCENARIO_FOUR_HUMAN_PLAYERS: case fheroes2::GameMode::SELECT_SCENARIO_FIVE_HUMAN_PLAYERS: case fheroes2::GameMode::SELECT_SCENARIO_SIX_HUMAN_PLAYERS: { const uint8_t humanPlayerCount = static_cast( static_cast( result ) - static_cast( fheroes2::GameMode::SELECT_SCENARIO_ONE_HUMAN_PLAYER ) ); // Add +1 since we don't have zero human player option. result = Game::SelectScenario( humanPlayerCount + 1 ); break; } case fheroes2::GameMode::START_GAME: result = Game::StartGame(); break; case fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO: result = Game::SelectCampaignScenario( fheroes2::GameMode::MAIN_MENU, false ); break; case fheroes2::GameMode::COMPLETE_CAMPAIGN_SCENARIO: result = Game::CompleteCampaignScenario( false ); break; case fheroes2::GameMode::COMPLETE_CAMPAIGN_SCENARIO_FROM_LOAD_FILE: result = Game::CompleteCampaignScenario( true ); while ( result == fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO ) { result = Game::SelectCampaignScenario( fheroes2::GameMode::LOAD_CAMPAIGN, false ); } break; case fheroes2::GameMode::EDITOR_MAIN_MENU: result = Editor::menuMain(); break; case fheroes2::GameMode::EDITOR_NEW_MAP: result = Editor::menuNewFromScratchMap(); break; case fheroes2::GameMode::EDITOR_LOAD_MAP: result = Editor::menuLoadMap(); break; default: // If this assertion blows up then you are entering an infinite loop! // Add the logic for the newly added entry. assert( 0 ); exit = true; break; } } // We are quitting the game, so fade-out the screen. fheroes2::fadeOutDisplay(); } fheroes2::GameMode Game::MainMenu( const bool isFirstGameRun ) { // Stop all sounds, but not the music AudioManager::stopSounds(); AudioManager::PlayMusicAsync( MUS::MAINMENU, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); Settings & conf = Settings::Get(); conf.SetGameType( TYPE_MENU ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::drawMainMenuScreen(); if ( isFirstGameRun ) { // Fade in Main Menu image before showing messages. This also resets the "need fade" state to have no fade-in after these messages. fheroes2::validateFadeInAndRender(); fheroes2::selectLanguage( fheroes2::getSupportedLanguages(), fheroes2::getLanguageFromAbbreviation( conf.getGameLanguage() ), true ); { std::string body( _( "Welcome to Heroes of Might and Magic II powered by fheroes2 engine!" ) ); if ( System::isTouchInputAvailable() ) { body += _( "\n\nTo simulate a right-click with a touch to get info on various items, you need to first touch and keep touching on the item of interest and then touch anywhere else on the screen. While holding the second finger, you can remove the first one from the screen and keep viewing the information on the item." ); } // Handheld devices should use the minimal game's resolution. Users on handheld devices aren't asked to choose resolution. if ( !System::isHandheldDevice() ) { body += _( "\n\nBefore starting the game, please select a game resolution." ); } fheroes2::showStandardTextMessage( _( "Greetings!" ), std::move( body ), Dialog::OK ); if ( !System::isHandheldDevice() && Dialog::SelectResolution() ) { fheroes2::drawMainMenuScreen(); } } conf.resetFirstGameRun(); conf.Save( Settings::configFileName ); } outputMainMenuInTextSupportMode(); LocalEvent & le = LocalEvent::Get(); fheroes2::Button buttonNewGame( 0, 0, ICN::BTNSHNGL, NEWGAME_DEFAULT, NEWGAME_DEFAULT + 2 ); fheroes2::Button buttonLoadGame( 0, 0, ICN::BTNSHNGL, LOADGAME_DEFAULT, LOADGAME_DEFAULT + 2 ); fheroes2::Button buttonHighScores( 0, 0, ICN::BTNSHNGL, HIGHSCORES_DEFAULT, HIGHSCORES_DEFAULT + 2 ); fheroes2::Button buttonCredits( 0, 0, ICN::BTNSHNGL, CREDITS_DEFAULT, CREDITS_DEFAULT + 2 ); fheroes2::Button buttonEditor( 0, 0, ICN::BTNSHNGL, EDITOR_DEFAULT, EDITOR_DEFAULT + 2 ); fheroes2::Button buttonQuit( 0, 0, ICN::BTNSHNGL, QUIT_DEFAULT, QUIT_DEFAULT + 2 ); const fheroes2::Sprite & lantern10 = fheroes2::AGG::GetICN( ICN::SHNGANIM, 0 ); fheroes2::Blit( lantern10, display, lantern10.x(), lantern10.y() ); const fheroes2::Sprite & lantern11 = fheroes2::AGG::GetICN( ICN::SHNGANIM, ICN::getAnimatedIcnIndex( ICN::SHNGANIM, 0, 0 ) ); fheroes2::Blit( lantern11, display, lantern11.x(), lantern11.y() ); buttonNewGame.draw(); buttonLoadGame.draw(); buttonHighScores.draw(); buttonCredits.draw(); buttonQuit.draw(); fheroes2::validateFadeInAndRender(); const double scaleX = static_cast( display.width() ) / fheroes2::Display::DEFAULT_WIDTH; const double scaleY = static_cast( display.height() ) / fheroes2::Display::DEFAULT_HEIGHT; const double scale = std::min( scaleX, scaleY ); const int32_t offsetX = static_cast( std::lround( display.width() - fheroes2::Display::DEFAULT_WIDTH * scale ) ) / 2; const int32_t offsetY = static_cast( std::lround( display.height() - fheroes2::Display::DEFAULT_HEIGHT * scale ) ) / 2; const fheroes2::Rect settingsArea( static_cast( 63 * scale ) + offsetX, static_cast( 202 * scale ) + offsetY, static_cast( 108 * scale ), static_cast( 160 * scale ) ); uint32_t lantern_frame = 0; const bool isPOLPresent = conf.isPriceOfLoyaltySupported(); std::vector buttons{ ButtonInfo{ NEWGAME_DEFAULT, buttonNewGame, buttonNewGame.area(), false, false }, ButtonInfo{ LOADGAME_DEFAULT, buttonLoadGame, buttonLoadGame.area(), false, false }, ButtonInfo{ HIGHSCORES_DEFAULT, buttonHighScores, buttonHighScores.area(), false, false }, ButtonInfo{ CREDITS_DEFAULT, buttonCredits, buttonCredits.area(), false, false }, ButtonInfo{ QUIT_DEFAULT, buttonQuit, buttonQuit.area(), false, false } }; if ( isPOLPresent ) { buttons.emplace_back( ButtonInfo{ EDITOR_DEFAULT, buttonEditor, buttonEditor.area(), false, false } ); } for ( size_t i = 0; le.hasMouseMoved() && i < buttons.size(); ++i ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::BTNSHNGL, buttons[i].frame ); fheroes2::Blit( sprite, display, sprite.x(), sprite.y() ); } fheroes2::Sprite highlightDoor = fheroes2::AGG::GetICN( ICN::SHNGANIM, 18 ); fheroes2::ApplyPalette( highlightDoor, 8 ); while ( true ) { if ( !le.HandleEvents( true, true ) ) { if ( Interface::AdventureMap::EventExit() == fheroes2::GameMode::QUIT_GAME ) { break; } else { continue; } } bool redrawScreen = false; for ( ButtonInfo & button : buttons ) { button.wasOver = button.isOver; button.button.drawOnState( le.isMouseLeftButtonPressedInArea( button.buttonArea ) ); button.isOver = le.isMouseCursorPosInArea( button.buttonArea ); if ( button.isOver != button.wasOver ) { uint32_t frame = button.frame; if ( button.isOver && !button.wasOver ) ++frame; if ( !redrawScreen ) { redrawScreen = true; } const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::BTNSHNGL, frame ); fheroes2::Blit( sprite, display, sprite.x(), sprite.y() ); } } if ( redrawScreen ) { display.render(); } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_NEW_GAME ) || le.MouseClickLeft( buttonNewGame.area() ) ) { return fheroes2::GameMode::NEW_GAME; } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_LOAD_GAME ) || le.MouseClickLeft( buttonLoadGame.area() ) ) { return fheroes2::GameMode::LOAD_GAME; } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_HIGHSCORES ) || le.MouseClickLeft( buttonHighScores.area() ) ) { return fheroes2::GameMode::HIGHSCORES_STANDARD; } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_CREDITS ) || le.MouseClickLeft( buttonCredits.area() ) ) { return fheroes2::GameMode::CREDITS; } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_QUIT ) || HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonQuit.area() ) ) { if ( Interface::AdventureMap::EventExit() == fheroes2::GameMode::QUIT_GAME ) { return fheroes2::GameMode::QUIT_GAME; } } else if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_SETTINGS ) || le.MouseClickLeft( settingsArea ) ) { fheroes2::openGameSettings(); return fheroes2::GameMode::MAIN_MENU; } if ( isPOLPresent && ( HotKeyPressEvent( HotKeyEvent::EDITOR_MAIN_MENU ) || le.MouseClickLeft( buttonEditor.area() ) ) ) { return fheroes2::GameMode::EDITOR_MAIN_MENU; } // right info if ( le.isMouseRightButtonPressedInArea( buttonQuit.area() ) ) { fheroes2::showStandardTextMessage( _( "Quit" ), _( "Quit Heroes of Might and Magic II and return to the operating system." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonLoadGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Load Game" ), _( "Load a previously saved game." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCredits.area() ) ) { fheroes2::showStandardTextMessage( _( "Credits" ), _( "View the credits screen." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonHighScores.area() ) ) { fheroes2::showStandardTextMessage( _( "High Scores" ), _( "View the high scores screen." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonNewGame.area() ) ) { fheroes2::showStandardTextMessage( _( "New Game" ), _( "Start a single or multi-player game." ), Dialog::ZERO ); } else if ( isPOLPresent && le.isMouseRightButtonPressedInArea( buttonEditor.area() ) ) { { fheroes2::showStandardTextMessage( _( "Editor" ), _( "Create new or modify existing maps." ), Dialog::ZERO ); } } else if ( le.isMouseRightButtonPressedInArea( settingsArea ) ) { fheroes2::showStandardTextMessage( _( "Game Settings" ), _( "Change language, resolution and settings of the game." ), Dialog::ZERO ); } if ( validateAnimationDelay( MAIN_MENU_DELAY ) ) { const fheroes2::Sprite & lantern12 = fheroes2::AGG::GetICN( ICN::SHNGANIM, ICN::getAnimatedIcnIndex( ICN::SHNGANIM, 0, lantern_frame ) ); ++lantern_frame; fheroes2::Blit( lantern12, display, lantern12.x(), lantern12.y() ); if ( le.isMouseCursorPosInArea( settingsArea ) ) { const int32_t doorOffsetY = static_cast( 55 * scale ) + offsetY; fheroes2::Blit( highlightDoor, 0, doorOffsetY, display, highlightDoor.x(), highlightDoor.y() + doorOffsetY, highlightDoor.width(), highlightDoor.height() ); } display.render(); } } return fheroes2::GameMode::QUIT_GAME; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_mainmenu_ui.cpp000066400000000000000000000141561476115357100234140ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_mainmenu_ui.h" #include #include #include #include "agg_image.h" #include "game.h" #include "icn.h" #include "image.h" #include "math_base.h" #include "screen.h" #include "settings.h" #include "ui_constants.h" #include "ui_tool.h" namespace { void drawSprite( fheroes2::Image & output, const int icnId, const uint32_t index ) { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( icnId, index ); fheroes2::Blit( sprite, 0, 0, output, sprite.x(), sprite.y(), sprite.width(), sprite.height() ); } void renderWindowBackground( fheroes2::Image & output, const fheroes2::Rect & roi ) { if ( roi.width == 0 || roi.height == 0 ) { // Nothing to render. return; } const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & background = fheroes2::AGG::GetICN( isEvilInterface ? ICN::STONEBAK_EVIL : ICN::STONEBAK, 0 ); const int32_t stepX = ( roi.width + background.width() ) / background.width(); const int32_t stepY = ( roi.height + background.height() ) / background.height(); fheroes2::Point offset{ roi.x, roi.y }; for ( int y = 0; y < stepY; ++y ) { offset.x = roi.x; const int32_t height = std::min( background.height(), roi.height - y * background.height() ); for ( int x = 0; x < stepX; ++x ) { fheroes2::Copy( background, 0, 0, output, offset.x, offset.y, std::min( background.width(), roi.width - x * background.width() ), height ); offset.x += background.width(); } offset.y += background.height(); } } void fillScreenBorders( fheroes2::Image & output, const fheroes2::Rect & backgroundRoi ) { if ( backgroundRoi.y == 0 ) { renderWindowBackground( output, { 0, 0, backgroundRoi.x, output.height() } ); renderWindowBackground( output, { backgroundRoi.x + backgroundRoi.width, 0, output.width() - backgroundRoi.x - backgroundRoi.width, output.height() } ); } else { assert( backgroundRoi.x == 0 ); renderWindowBackground( output, { 0, 0, output.width(), backgroundRoi.y } ); renderWindowBackground( output, { 0, backgroundRoi.y + backgroundRoi.height, output.width(), output.height() - backgroundRoi.y - backgroundRoi.height } ); } } } namespace fheroes2 { void drawMainMenuScreen() { Display & display = Display::instance(); const Sprite & mainMenuBackground = AGG::GetICN( ICN::HEROES, 0 ); Copy( mainMenuBackground, 0, 0, display, mainMenuBackground.x(), mainMenuBackground.y(), mainMenuBackground.width(), mainMenuBackground.height() ); drawSprite( display, ICN::BTNSHNGL, 1 ); drawSprite( display, ICN::BTNSHNGL, 5 ); drawSprite( display, ICN::BTNSHNGL, 9 ); drawSprite( display, ICN::BTNSHNGL, 13 ); drawSprite( display, ICN::BTNSHNGL, 17 ); fillScreenBorders( display, { mainMenuBackground.x(), mainMenuBackground.y(), mainMenuBackground.width(), mainMenuBackground.height() } ); } void drawEditorMainMenuScreen() { Display & display = Display::instance(); const Sprite & background = AGG::GetICN( ICN::EDITOR, 0 ); Copy( background, 0, 0, display, background.x(), background.y(), background.width(), background.height() ); fillScreenBorders( display, { background.x(), background.y(), background.width(), background.height() } ); } Point drawButtonPanel() { const fheroes2::Sprite & back = fheroes2::AGG::GetICN( ICN::HEROES, 0 ); const fheroes2::Sprite & panel = fheroes2::AGG::GetICN( ICN::REDBACK, 0 ); const int32_t panelOffset = fheroes2::Display::DEFAULT_HEIGHT - panel.height(); const int32_t panelXPos = back.width() + back.x() - ( panel.width() + panelOffset ); fheroes2::Blit( panel, fheroes2::Display::instance(), panelXPos, panelOffset + back.y() ); const int32_t buttonMiddlePos = panelXPos + fheroes2::shadowWidthPx + ( panel.width() - fheroes2::shadowWidthPx ) / 2; const fheroes2::Sprite & buttonSample = fheroes2::AGG::GetICN( ICN::BTNNEWGM, 0 ); const int32_t buttonWidth = buttonSample.width(); const int32_t buttonXPos = buttonMiddlePos - buttonWidth / 2 - 3; // 3 is button shadow const int32_t buttonYPos = 46 + back.y(); return { buttonXPos, buttonYPos }; } void validateFadeInAndRender() { if ( Game::validateDisplayFadeIn() ) { fheroes2::fadeInDisplay(); } else { fheroes2::Display::instance().render(); } } } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_mainmenu_ui.h000066400000000000000000000034171476115357100230570ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2023 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include "math_base.h" namespace fheroes2 { void drawMainMenuScreen(); void drawEditorMainMenuScreen(); Point drawButtonPanel(); // If display fade-in state is set reset it to false and fade-in the full display image. Otherwise render full display image without fade-in. void validateFadeInAndRender(); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_mode.h000066400000000000000000000050151476115357100214710ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace fheroes2 { enum class GameMode : int { CANCEL = 0, QUIT_GAME, MAIN_MENU, NEW_GAME, LOAD_GAME, HIGHSCORES_STANDARD, HIGHSCORES_CAMPAIGN, CREDITS, NEW_STANDARD, NEW_CAMPAIGN_SELECTION, NEW_SUCCESSION_WARS_CAMPAIGN, NEW_PRICE_OF_LOYALTY_CAMPAIGN, NEW_MULTI, NEW_HOT_SEAT, NEW_BATTLE_ONLY, LOAD_STANDARD, LOAD_CAMPAIGN, LOAD_MULTI, LOAD_HOT_SEAT, // Do NOT change the order of the below 6 entries! SELECT_SCENARIO_ONE_HUMAN_PLAYER, SELECT_SCENARIO_TWO_HUMAN_PLAYERS, SELECT_SCENARIO_THREE_HUMAN_PLAYERS, SELECT_SCENARIO_FOUR_HUMAN_PLAYERS, SELECT_SCENARIO_FIVE_HUMAN_PLAYERS, SELECT_SCENARIO_SIX_HUMAN_PLAYERS, START_GAME, SAVE_GAME, END_TURN, SELECT_CAMPAIGN_SCENARIO, COMPLETE_CAMPAIGN_SCENARIO, COMPLETE_CAMPAIGN_SCENARIO_FROM_LOAD_FILE, EDITOR_MAIN_MENU, EDITOR_NEW_MAP, EDITOR_LOAD_MAP }; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_newgame.cpp000066400000000000000000001042611476115357100225260ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game.h" // IWYU pragma: associated #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "audio.h" #include "audio_manager.h" #include "campaign_savedata.h" #include "campaign_scenariodata.h" #include "cursor.h" #include "dialog.h" #include "dialog_game_settings.h" #include "game_delays.h" #include "game_hotkeys.h" #include "game_io.h" #include "game_mainmenu_ui.h" #include "game_mode.h" #include "game_video.h" #include "game_video_type.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "logging.h" #include "maps_fileinfo.h" #include "math_base.h" #include "mus.h" #include "screen.h" #include "settings.h" #include "smk_decoder.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_tool.h" namespace { const int32_t buttonYStep = 66; std::unique_ptr getVideo( const std::string & fileName ) { std::string videoPath; if ( !Video::getVideoFilePath( fileName, videoPath ) ) { return nullptr; } std::unique_ptr video = std::make_unique( videoPath ); if ( video->frameCount() < 1 ) { return nullptr; } return video; } void outputNewMenuInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "New Game\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_STANDARD ) << " to choose Standard Game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_CAMPAIGN ) << " to choose Campaign Game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_MULTI ) << " to choose Multiplayer Game." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_SETTINGS ) << " to open Game Settings." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to come back to Main Menu." ) } void outputNewCampaignSelectionInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "New Campaign\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_NEW_ORIGINAL_CAMPAIGN ) << " to choose The Original Campaign." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_NEW_EXPANSION_CAMPAIGN ) << " to choose The Expansion Campaign." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to come back to Main Menu." ) } void outputNewSuccessionWarsCampaignInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Choose your Lord:\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_ROLAND ) << " to choose Roland Campaign." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_ARCHIBALD ) << " to choose Archibald Campaign." ) } void outputPriceOfLoyaltyCampaignInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Select your campaign\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_PRICE_OF_LOYALTY ) << " to choose The Price of Loyalty Campaign." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_VOYAGE_HOME ) << " to choose Voyage Home Campaign." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_WIZARDS_ISLE ) << " to choose Wizard's Isle Campaign." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::CAMPAIGN_DESCENDANTS ) << " to choose Descendants Campaign." ) } void showMissingVideoFilesWindow() { fheroes2::showStandardTextMessage( _( "Warning" ), _( "The required video files for the campaign selection window are missing. " "Please make sure that all necessary files are present in the system." ), Dialog::OK ); } } fheroes2::GameMode Game::NewStandard() { Settings & conf = Settings::Get(); if ( conf.isCampaignGameType() ) conf.setCurrentMapInfo( {} ); conf.SetGameType( Game::TYPE_STANDARD ); return fheroes2::GameMode::SELECT_SCENARIO_ONE_HUMAN_PLAYER; } fheroes2::GameMode Game::NewBattleOnly() { Settings & conf = Settings::Get(); conf.SetGameType( Game::TYPE_BATTLEONLY ); return fheroes2::GameMode::NEW_MULTI; } fheroes2::GameMode Game::NewHotSeat() { Settings & conf = Settings::Get(); if ( conf.isCampaignGameType() ) conf.setCurrentMapInfo( {} ); if ( conf.IsGameType( Game::TYPE_BATTLEONLY ) ) { // Redraw the main menu screen without multiplayer sub-menu to show it after the battle using screen restorer. fheroes2::drawMainMenuScreen(); return StartBattleOnly(); } else { conf.SetGameType( Game::TYPE_HOTSEAT ); const uint8_t humanPlayerCount = SelectCountPlayers(); switch ( humanPlayerCount ) { case 2: return fheroes2::GameMode::SELECT_SCENARIO_TWO_HUMAN_PLAYERS; case 3: return fheroes2::GameMode::SELECT_SCENARIO_THREE_HUMAN_PLAYERS; case 4: return fheroes2::GameMode::SELECT_SCENARIO_FOUR_HUMAN_PLAYERS; case 5: return fheroes2::GameMode::SELECT_SCENARIO_FIVE_HUMAN_PLAYERS; case 6: return fheroes2::GameMode::SELECT_SCENARIO_SIX_HUMAN_PLAYERS; default: break; } } return fheroes2::GameMode::MAIN_MENU; } fheroes2::GameMode Game::CampaignSelection() { if ( !isPriceOfLoyaltyCampaignPresent() ) { return fheroes2::GameMode::NEW_SUCCESSION_WARS_CAMPAIGN; } outputNewCampaignSelectionInTextSupportMode(); fheroes2::drawMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonSuccessionWars( buttonPos.x, buttonPos.y, ICN::BUTTON_ORIGINAL_CAMPAIGN, 0, 1 ); fheroes2::Button buttonPriceOfLoyalty( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::BUTTON_EXPANSION_CAMPAIGN, 0, 1 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); buttonSuccessionWars.draw(); buttonPriceOfLoyalty.draw(); buttonCancel.draw(); fheroes2::Display::instance().render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonSuccessionWars.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSuccessionWars.area() ) ); buttonPriceOfLoyalty.drawOnState( le.isMouseLeftButtonPressedInArea( buttonPriceOfLoyalty.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonSuccessionWars.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_NEW_ORIGINAL_CAMPAIGN ) ) { return fheroes2::GameMode::NEW_SUCCESSION_WARS_CAMPAIGN; } if ( le.MouseClickLeft( buttonPriceOfLoyalty.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_NEW_EXPANSION_CAMPAIGN ) ) { return fheroes2::GameMode::NEW_PRICE_OF_LOYALTY_CAMPAIGN; } if ( HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return fheroes2::GameMode::MAIN_MENU; } if ( le.isMouseRightButtonPressedInArea( buttonSuccessionWars.area() ) ) { fheroes2::showStandardTextMessage( _( "Original Campaign" ), _( "Either Roland's or Archibald's campaign from the original Heroes of Might and Magic II." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonPriceOfLoyalty.area() ) ) { fheroes2::showStandardTextMessage( _( "Expansion Campaign" ), _( "One of the four new campaigns from the Price of Loyalty expansion set." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::QUIT_GAME; } fheroes2::GameMode Game::NewSuccessionWarsCampaign() { Settings::Get().SetGameType( Game::TYPE_CAMPAIGN ); // Reset all sound and music before playing videos AudioManager::ResetAudio(); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Point roiOffset( ( display.width() - display.DEFAULT_WIDTH ) / 2, ( display.height() - display.DEFAULT_HEIGHT ) / 2 ); // Fade-out screen before playing video. fheroes2::fadeOutDisplay(); const fheroes2::Text loadingScreen( _( "Loading video. Please wait..." ), fheroes2::FontType::normalWhite() ); loadingScreen.draw( display.width() / 2 - loadingScreen.width() / 2, display.height() / 2 - loadingScreen.height() / 2 + 2, display ); display.render(); Video::ShowVideo( "INTRO.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END ); Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get(); campaignSaveData.reset(); std::unique_ptr video = getVideo( "CHOOSE.SMK" ); if ( !video ) { showMissingVideoFilesWindow(); campaignSaveData.setCurrentScenarioInfo( { Campaign::ROLAND_CAMPAIGN, 0 } ); return fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; } const std::array campaignRoi{ fheroes2::Rect( 382 + roiOffset.x, 58 + roiOffset.y, 222, 298 ), fheroes2::Rect( 30 + roiOffset.x, 59 + roiOffset.y, 224, 297 ) }; const uint64_t customDelay = static_cast( std::lround( 1000.0 / video->fps() ) ); outputNewSuccessionWarsCampaignInTextSupportMode(); AudioManager::ResetAudio(); Video::ShowVideo( "CHOOSEW.SMK", Video::VideoAction::IGNORE_VIDEO ); const fheroes2::ScreenPaletteRestorer screenRestorer; std::vector palette = video->getCurrentPalette(); screenRestorer.changePalette( palette.data() ); const CursorRestorer cursorRestorer( true, Cursor::POINTER ); Cursor::Get().setVideoPlaybackCursor(); // Immediately indicate that the delay has passed to render first frame immediately. Game::passCustomAnimationDelay( customDelay ); // Make sure that the first run is passed immediately. assert( !Game::isCustomDelayNeeded( customDelay ) ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( Game::isCustomDelayNeeded( customDelay ) ) ) { if ( le.MouseClickLeft( campaignRoi[0] ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_ROLAND ) ) { campaignSaveData.setCurrentScenarioInfo( { Campaign::ROLAND_CAMPAIGN, 0 } ); break; } if ( le.MouseClickLeft( campaignRoi[1] ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_ARCHIBALD ) ) { campaignSaveData.setCurrentScenarioInfo( { Campaign::ARCHIBALD_CAMPAIGN, 0 } ); break; } size_t highlightCampaignId = campaignRoi.size(); for ( size_t i = 0; i < campaignRoi.size(); ++i ) { if ( le.isMouseCursorPosInArea( campaignRoi[i] ) ) { highlightCampaignId = i; break; } } if ( Game::validateCustomAnimationDelay( customDelay ) ) { fheroes2::Rect frameRoi( roiOffset.x, roiOffset.y, 0, 0 ); video->getNextFrame( display, frameRoi.x, frameRoi.y, frameRoi.width, frameRoi.height, palette ); if ( highlightCampaignId < campaignRoi.size() ) { const fheroes2::Rect & roi = campaignRoi[highlightCampaignId]; fheroes2::DrawRect( display, roi, 51 ); fheroes2::DrawRect( display, { roi.x - 1, roi.y - 1, roi.width + 2, roi.height + 2 }, 51 ); } display.render( frameRoi ); if ( video->frameCount() <= video->getCurrentFrame() ) { video->resetFrame(); } } } screenRestorer.changePalette( nullptr ); // Update the frame but do not render it. display.fill( 0 ); display.updateNextRenderRoi( { 0, 0, display.width(), display.height() } ); // Set the fade-in for the Campaign scenario info. setDisplayFadeIn(); return fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; } fheroes2::GameMode Game::NewPriceOfLoyaltyCampaign() { // TODO: Properly choose the campaign instead of this hackish way Campaign::CampaignSaveData & campaignSaveData = Campaign::CampaignSaveData::Get(); campaignSaveData.reset(); campaignSaveData.setCurrentScenarioInfo( { Campaign::PRICE_OF_LOYALTY_CAMPAIGN, 0 } ); std::array, 4> videos{ getVideo( "IVYPOL.SMK" ), getVideo( "IVYVOY.SMK" ), getVideo( "IVYWIZ.SMK" ), getVideo( "IVYDES.SMK" ) }; if ( !videos[0] ) { // File doesn't exist. Fallback to PoL campaign. showMissingVideoFilesWindow(); return fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; } // Fade-out display before playing video. fheroes2::fadeOutDisplay(); outputPriceOfLoyaltyCampaignInTextSupportMode(); const fheroes2::ScreenPaletteRestorer screenRestorer; const CursorRestorer cursorRestorer( true, Cursor::POINTER ); std::vector palette = videos[0]->getCurrentPalette(); screenRestorer.changePalette( palette.data() ); Cursor::Get().setVideoPlaybackCursor(); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Point roiOffset( ( display.width() - display.DEFAULT_WIDTH ) / 2, ( display.height() - display.DEFAULT_HEIGHT ) / 2 ); const fheroes2::Sprite & background = fheroes2::AGG::GetICN( ICN::X_IVY, 1 ); fheroes2::Blit( background, 0, 0, display, roiOffset.x, roiOffset.y, background.width(), background.height() ); const fheroes2::Sprite & campaignChoice = fheroes2::AGG::GetICN( ICN::X_IVY, 0 ); fheroes2::Blit( campaignChoice, 0, 0, display, roiOffset.x + campaignChoice.x(), roiOffset.y + campaignChoice.y(), campaignChoice.width(), campaignChoice.height() ); display.render(); const std::array activeCampaignArea{ fheroes2::Rect( roiOffset.x + 192, roiOffset.y + 23, 248, 163 ), fheroes2::Rect( roiOffset.x + 19, roiOffset.y + 120, 166, 193 ), fheroes2::Rect( roiOffset.x + 450, roiOffset.y + 120, 166, 193 ), fheroes2::Rect( roiOffset.x + 192, roiOffset.y + 240, 248, 163 ) }; const std::array renderCampaignArea{ fheroes2::Rect( roiOffset.x + 214, roiOffset.y + 47, 248, 163 ), fheroes2::Rect( roiOffset.x + 41, roiOffset.y + 140, 166, 193 ), fheroes2::Rect( roiOffset.x + 472, roiOffset.y + 131, 166, 193 ), fheroes2::Rect( roiOffset.x + 214, roiOffset.y + 273, 248, 163 ) }; size_t highlightCampaignId = videos.size(); fheroes2::GameMode gameChoice = fheroes2::GameMode::NEW_CAMPAIGN_SELECTION; uint64_t customDelay = 0; // Immediately indicate that the delay has passed to render first frame immediately. Game::passCustomAnimationDelay( customDelay ); // Make sure that the first run is passed immediately. assert( !Game::isCustomDelayNeeded( customDelay ) ); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents( highlightCampaignId < videos.size() ? Game::isCustomDelayNeeded( customDelay ) : true ) ) { if ( le.MouseClickLeft( activeCampaignArea[0] ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_PRICE_OF_LOYALTY ) ) { campaignSaveData.setCurrentScenarioInfo( { Campaign::PRICE_OF_LOYALTY_CAMPAIGN, 0 } ); gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; break; } if ( le.MouseClickLeft( activeCampaignArea[1] ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_VOYAGE_HOME ) ) { campaignSaveData.setCurrentScenarioInfo( { Campaign::VOYAGE_HOME_CAMPAIGN, 0 } ); gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; break; } if ( le.MouseClickLeft( activeCampaignArea[2] ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_WIZARDS_ISLE ) ) { campaignSaveData.setCurrentScenarioInfo( { Campaign::WIZARDS_ISLE_CAMPAIGN, 0 } ); gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; break; } if ( le.MouseClickLeft( activeCampaignArea[3] ) || HotKeyPressEvent( HotKeyEvent::CAMPAIGN_DESCENDANTS ) ) { campaignSaveData.setCurrentScenarioInfo( { Campaign::DESCENDANTS_CAMPAIGN, 0 } ); gameChoice = fheroes2::GameMode::SELECT_CAMPAIGN_SCENARIO; break; } const size_t beforeCampaignId = highlightCampaignId; highlightCampaignId = videos.size(); for ( size_t i = 0; i < activeCampaignArea.size(); ++i ) { if ( le.isMouseCursorPosInArea( activeCampaignArea[i] ) && videos[i] ) { highlightCampaignId = i; customDelay = static_cast( std::lround( 1000.0 / videos[highlightCampaignId]->fps() ) ); break; } } if ( highlightCampaignId != beforeCampaignId ) { fheroes2::Blit( background, 0, 0, display, roiOffset.x, roiOffset.y, background.width(), background.height() ); fheroes2::Blit( campaignChoice, 0, 0, display, roiOffset.x + campaignChoice.x(), roiOffset.y + campaignChoice.y(), campaignChoice.width(), campaignChoice.height() ); if ( highlightCampaignId >= videos.size() ) { display.render(); } } if ( highlightCampaignId < videos.size() && Game::validateCustomAnimationDelay( customDelay ) ) { fheroes2::Rect frameRoi( renderCampaignArea[highlightCampaignId].x, renderCampaignArea[highlightCampaignId].y, 0, 0 ); videos[highlightCampaignId]->getNextFrame( display, frameRoi.x, frameRoi.y, frameRoi.width, frameRoi.height, palette ); fheroes2::Blit( background, frameRoi.x - roiOffset.x, frameRoi.y - roiOffset.y, display, frameRoi.x, frameRoi.y, frameRoi.width, frameRoi.height ); display.render( frameRoi ); if ( videos[highlightCampaignId]->frameCount() <= videos[highlightCampaignId]->getCurrentFrame() ) { videos[highlightCampaignId]->resetFrame(); } } } // Update the frame but do not render it. display.fill( 0 ); display.updateNextRenderRoi( { 0, 0, display.width(), display.height() } ); // Set the fade-in for the Campaign scenario info. setDisplayFadeIn(); return gameChoice; } fheroes2::GameMode Game::NewNetwork() { Settings & conf = Settings::Get(); conf.SetGameType( conf.GameType() | Game::TYPE_NETWORK ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonHost( buttonPos.x, buttonPos.y, ICN::BTNNET, 0, 1 ); fheroes2::Button buttonGuest( buttonPos.x, buttonPos.y + buttonYStep, ICN::BTNNET, 2, 3 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); buttonHost.draw(); buttonGuest.draw(); buttonCancel.draw(); fheroes2::Display::instance().render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { buttonHost.drawOnState( le.isMouseLeftButtonPressedInArea( buttonHost.area() ) ); buttonGuest.drawOnState( le.isMouseLeftButtonPressedInArea( buttonGuest.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return fheroes2::GameMode::MAIN_MENU; } // right info if ( le.isMouseRightButtonPressedInArea( buttonHost.area() ) ) { fheroes2::showStandardTextMessage( _( "Host" ), _( "The host sets up the game options. There can only be one host per network game." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonGuest.area() ) ) { fheroes2::showStandardTextMessage( _( "Guest" ), _( "The guest waits for the host to set up the game, then is automatically added in. There can be multiple guests for TCP/IP games." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::MAIN_MENU; } fheroes2::GameMode Game::NewGame( const bool isProbablyDemoVersion ) { outputNewMenuInTextSupportMode(); // Stop all sounds, but not the music AudioManager::stopSounds(); AudioManager::PlayMusicAsync( MUS::MAINMENU, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); // reset last save name Game::SetLastSaveName( "" ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonStandardGame( buttonPos.x, buttonPos.y, ICN::BUTTON_STANDARD_GAME, 0, 1 ); fheroes2::Button buttonCampaignGame( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::BUTTON_CAMPAIGN_GAME, 0, 1 ); fheroes2::Button buttonMultiGame( buttonPos.x, buttonPos.y + buttonYStep * 2, ICN::BUTTON_MULTIPLAYER_GAME, 0, 1 ); fheroes2::Button buttonBattleGame( buttonPos.x, buttonPos.y + buttonYStep * 3, ICN::BTNBATTLEONLY, 0, 1 ); fheroes2::Button buttonSettings( buttonPos.x, buttonPos.y + buttonYStep * 4, ICN::BUTTON_LARGE_CONFIG, 0, 1 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); if ( !isSuccessionWarsCampaignPresent() ) { buttonCampaignGame.disable(); } buttonStandardGame.draw(); buttonCampaignGame.draw(); buttonMultiGame.draw(); buttonBattleGame.draw(); buttonSettings.draw(); buttonCancel.draw(); fheroes2::validateFadeInAndRender(); LocalEvent & le = LocalEvent::Get(); if ( isProbablyDemoVersion ) { fheroes2::showStandardTextMessage( _( "Warning" ), _( "fheroes2 needs data files from the original Heroes of Might and Magic II to operate. " "You appear to be using the demo version of Heroes of Might and Magic II for this purpose. " "Please note that only one scenario will be available in this setup." ), Dialog::OK ); } while ( le.HandleEvents() ) { buttonStandardGame.drawOnState( le.isMouseLeftButtonPressedInArea( buttonStandardGame.area() ) ); if ( buttonCampaignGame.isEnabled() ) { buttonCampaignGame.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCampaignGame.area() ) ); } buttonMultiGame.drawOnState( le.isMouseLeftButtonPressedInArea( buttonMultiGame.area() ) ); buttonBattleGame.drawOnState( le.isMouseLeftButtonPressedInArea( buttonBattleGame.area() ) ); buttonSettings.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSettings.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_STANDARD ) || le.MouseClickLeft( buttonStandardGame.area() ) ) { return fheroes2::GameMode::NEW_STANDARD; } if ( buttonCampaignGame.isEnabled() && ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_CAMPAIGN ) || le.MouseClickLeft( buttonCampaignGame.area() ) ) ) { return fheroes2::GameMode::NEW_CAMPAIGN_SELECTION; } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_MULTI ) || le.MouseClickLeft( buttonMultiGame.area() ) ) { return fheroes2::GameMode::NEW_MULTI; } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_SETTINGS ) || le.MouseClickLeft( buttonSettings.area() ) ) { fheroes2::openGameSettings(); return fheroes2::GameMode::MAIN_MENU; } if ( HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return fheroes2::GameMode::MAIN_MENU; } if ( HotKeyPressEvent( HotKeyEvent::MAIN_MENU_BATTLEONLY ) || le.MouseClickLeft( buttonBattleGame.area() ) ) { return fheroes2::GameMode::NEW_BATTLE_ONLY; } if ( le.isMouseRightButtonPressedInArea( buttonStandardGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Standard Game" ), _( "A single player game playing out a single map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCampaignGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Campaign Game" ), _( "A single player game playing through a series of maps." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonMultiGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Multi-Player Game" ), _( "A multi-player game, with several human players competing against each other on a single map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonBattleGame.area() ) ) { fheroes2::showStandardTextMessage( _( "Battle Only" ), _( "Setup and play a battle without loading any map." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonSettings.area() ) ) { fheroes2::showStandardTextMessage( _( "Game Settings" ), _( "Change language, resolution and settings of the game." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::QUIT_GAME; } fheroes2::GameMode Game::NewMulti() { Settings & conf = Settings::Get(); if ( !( conf.IsGameType( Game::TYPE_BATTLEONLY ) ) ) conf.SetGameType( Game::TYPE_STANDARD ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button buttonHotSeat( buttonPos.x, buttonPos.y, ICN::BUTTON_HOT_SEAT, 0, 1 ); fheroes2::Button buttonNetwork( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::BTNMP, 2, 3 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); buttonHotSeat.draw(); buttonCancel.draw(); buttonNetwork.disable(); fheroes2::Display::instance().render(); LocalEvent & le = LocalEvent::Get(); // new game loop while ( le.HandleEvents() ) { buttonHotSeat.drawOnState( le.isMouseLeftButtonPressedInArea( buttonHotSeat.area() ) ); if ( buttonNetwork.isEnabled() ) { buttonNetwork.drawOnState( le.isMouseLeftButtonPressedInArea( buttonNetwork.area() ) ); } buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( buttonHotSeat.area() ) || HotKeyPressEvent( HotKeyEvent::MAIN_MENU_HOTSEAT ) ) { return fheroes2::GameMode::NEW_HOT_SEAT; } if ( HotKeyPressEvent( HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return fheroes2::GameMode::MAIN_MENU; } // right info if ( le.isMouseRightButtonPressedInArea( buttonHotSeat.area() ) ) { fheroes2:: showStandardTextMessage( _( "Hot Seat" ), _( "Play a Hot Seat game, where 2 to 6 players play on the same device, switching into the 'Hot Seat' when it is their turn." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return fheroes2::GameMode::QUIT_GAME; } uint8_t Game::SelectCountPlayers() { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::drawMainMenuScreen(); const fheroes2::Point buttonPos = fheroes2::drawButtonPanel(); fheroes2::Button button2Players( buttonPos.x, buttonPos.y, ICN::BUTTON_2_PLAYERS, 0, 1 ); fheroes2::Button button3Players( buttonPos.x, buttonPos.y + buttonYStep * 1, ICN::BUTTON_3_PLAYERS, 0, 1 ); fheroes2::Button button4Players( buttonPos.x, buttonPos.y + buttonYStep * 2, ICN::BUTTON_4_PLAYERS, 0, 1 ); fheroes2::Button button5Players( buttonPos.x, buttonPos.y + buttonYStep * 3, ICN::BUTTON_5_PLAYERS, 0, 1 ); fheroes2::Button button6Players( buttonPos.x, buttonPos.y + buttonYStep * 4, ICN::BUTTON_6_PLAYERS, 0, 1 ); fheroes2::Button buttonCancel( buttonPos.x, buttonPos.y + buttonYStep * 5, ICN::BUTTON_LARGE_CANCEL, 0, 1 ); button2Players.draw(); button3Players.draw(); button4Players.draw(); button5Players.draw(); button6Players.draw(); buttonCancel.draw(); fheroes2::Display::instance().render(); LocalEvent & le = LocalEvent::Get(); while ( le.HandleEvents() ) { button2Players.drawOnState( le.isMouseLeftButtonPressedInArea( button2Players.area() ) ); button3Players.drawOnState( le.isMouseLeftButtonPressedInArea( button3Players.area() ) ); button4Players.drawOnState( le.isMouseLeftButtonPressedInArea( button4Players.area() ) ); button5Players.drawOnState( le.isMouseLeftButtonPressedInArea( button5Players.area() ) ); button6Players.drawOnState( le.isMouseLeftButtonPressedInArea( button6Players.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); if ( le.MouseClickLeft( button2Players.area() ) || le.isKeyPressed( fheroes2::Key::KEY_2 ) ) { return 2; } if ( le.MouseClickLeft( button3Players.area() ) || le.isKeyPressed( fheroes2::Key::KEY_3 ) ) { return 3; } if ( le.MouseClickLeft( button4Players.area() ) || le.isKeyPressed( fheroes2::Key::KEY_4 ) ) { return 4; } if ( le.MouseClickLeft( button5Players.area() ) || le.isKeyPressed( fheroes2::Key::KEY_5 ) ) { return 5; } if ( le.MouseClickLeft( button6Players.area() ) || le.isKeyPressed( fheroes2::Key::KEY_6 ) ) { return 6; } if ( HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { return 0; } // right info if ( le.isMouseRightButtonPressedInArea( button2Players.area() ) ) { fheroes2::showStandardTextMessage( _( "2 Players" ), _( "Play with 2 human players, and optionally, up to 4 additional computer players." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( button3Players.area() ) ) { fheroes2::showStandardTextMessage( _( "3 Players" ), _( "Play with 3 human players, and optionally, up to 3 additional computer players." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( button4Players.area() ) ) { fheroes2::showStandardTextMessage( _( "4 Players" ), _( "Play with 4 human players, and optionally, up to 2 additional computer players." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( button5Players.area() ) ) { fheroes2::showStandardTextMessage( _( "5 Players" ), _( "Play with 5 human players, and optionally, up to 1 additional computer player." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( button6Players.area() ) ) { fheroes2::showStandardTextMessage( _( "6 Players" ), _( "Play with 6 human players." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Cancel back to the main menu." ), Dialog::ZERO ); } } return 0; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_over.cpp000066400000000000000000000546371476115357100220710ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_over.h" #include #include #include #include #include "artifact.h" #include "audio.h" #include "audio_manager.h" #include "campaign_savedata.h" #include "campaign_scenariodata.h" #include "castle.h" #include "color.h" #include "dialog.h" #include "game.h" #include "game_video.h" #include "game_video_type.h" #include "heroes.h" #include "highscores.h" #include "kingdom.h" #include "maps_fileinfo.h" #include "monster.h" #include "mus.h" #include "players.h" #include "serialize.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "ui_text.h" #include "world.h" namespace { void DialogWins( uint32_t cond ) { std::string body; const Settings & conf = Settings::Get(); if ( conf.isCampaignGameType() ) { const Campaign::ScenarioVictoryCondition victoryCondition = Campaign::getCurrentScenarioVictoryCondition(); if ( victoryCondition == Campaign::ScenarioVictoryCondition::CAPTURE_DRAGON_CITY ) { body = _( "Dragon city has fallen! You are now the Master of the Dragons." ); } } if ( body.empty() ) { switch ( cond ) { case GameOver::WINS_ALL: break; case GameOver::WINS_TOWN: { body = _( "You captured %{name}!\nYou are victorious." ); const Castle * town = world.getCastleEntrance( conf.getCurrentMapInfo().WinsMapsPositionObject() ); assert( town != nullptr ); if ( town ) { StringReplace( body, "%{name}", town->GetName() ); } break; } case GameOver::WINS_HERO: { body = _( "You have captured the enemy hero %{name}!\nYour quest is complete." ); const Heroes * hero = world.GetHeroesCondWins(); assert( hero != nullptr ); if ( hero ) { StringReplace( body, "%{name}", hero->GetName() ); } break; } case GameOver::WINS_ARTIFACT: body = _( "You have found the %{name}.\nYour quest is complete." ); if ( conf.getCurrentMapInfo().WinsFindUltimateArtifact() ) { StringReplace( body, "%{name}", _( "Ultimate Artifact" ) ); } else { const Artifact art = conf.getCurrentMapInfo().WinsFindArtifactID(); StringReplace( body, "%{name}", art.GetName() ); } break; case GameOver::WINS_SIDE: body = _( "The enemy is beaten.\nYour side has triumphed!" ); break; case GameOver::WINS_GOLD: body = _( "You have built up over %{count} gold in your treasury.\nAll enemies bow before your wealth and power." ); StringReplace( body, "%{count}", conf.getCurrentMapInfo().getWinningGoldAccumulationValue() ); break; default: break; } } if ( !body.empty() ) { AudioManager::PlayMusic( MUS::VICTORY, Music::PlaybackMode::PLAY_ONCE ); fheroes2::showStandardTextMessage( _( "Victory!" ), body, Dialog::OK ); } } void DialogLoss( uint32_t cond ) { const Settings & conf = Settings::Get(); std::string body; switch ( cond ) { case GameOver::LOSS_ENEMY_WINS_TOWN: { body = _( "The enemy has captured %{name}!\nThey are triumphant." ); const Castle * town = world.getCastleEntrance( conf.getCurrentMapInfo().WinsMapsPositionObject() ); assert( town != nullptr ); if ( town ) { StringReplace( body, "%{name}", town->GetName() ); } break; } case GameOver::LOSS_ENEMY_WINS_GOLD: body = _( "The enemy has built up over %{count} gold in his treasury.\nYou must bow done in defeat before his wealth and power." ); StringReplace( body, "%{count}", conf.getCurrentMapInfo().getWinningGoldAccumulationValue() ); break; case GameOver::LOSS_ALL: body = _( "You have been eliminated from the game!!!" ); break; case GameOver::LOSS_TOWN: { body = _( "The enemy has captured %{name}!\nThey are triumphant." ); const Castle * town = world.getCastleEntrance( conf.getCurrentMapInfo().LossMapsPositionObject() ); assert( town != nullptr ); if ( town ) { StringReplace( body, "%{name}", town->GetName() ); } break; } case GameOver::LOSS_HERO: { body = _( "You have lost the hero %{name}.\nYour quest is over." ); const Heroes * hero = world.GetHeroesCondLoss(); assert( hero != nullptr ); if ( hero ) { StringReplace( body, "%{name}", hero->GetName() ); } break; } case GameOver::LOSS_TIME: body = _( "You have failed to complete your quest in time.\nAll is lost." ); break; default: break; } if ( !body.empty() ) { AudioManager::PlayMusic( MUS::LOSTGAME, Music::PlaybackMode::PLAY_ONCE ); fheroes2::showStandardTextMessage( _( "Defeat!" ), body, Dialog::OK ); } } Video::Subtitle standardGameResults() { // Get data for ratings text. const int32_t difficulty = static_cast( Game::GetRating() ); const int32_t baseScore = static_cast( Game::getGameOverScoreFactor() ); const int32_t score = difficulty * baseScore / 100; // Make ratings text as a subtitle for WIN.SMK. fheroes2::MultiFontText ratingText; std::string textBody = _( "Congratulations!\n\nDays: %{days}\n" ); StringReplace( textBody, "%{days}", static_cast( world.CountDay() ) ); ratingText.add( { textBody, fheroes2::FontType::normalWhite() } ); textBody = _( "Base score: %{score}\nDifficulty: %{difficulty}\n\n" ); StringReplace( textBody, "%{score}", baseScore ); StringReplace( textBody, "%{difficulty}", difficulty ); ratingText.add( { textBody, fheroes2::FontType::smallWhite() } ); textBody = _( "Score: %{score}\n\nRating:\n%{rating}" ); StringReplace( textBody, "%{score}", score ); StringReplace( textBody, "%{rating}", fheroes2::HighScoreDataContainer::getMonsterByRating( score ).GetName() ); ratingText.add( { textBody, fheroes2::FontType::normalWhite() } ); // Show results from the 5th second until end (forever) and set maximum width to 140 to fit the black area. // Set subtitles top-center position (475,110) to render results over the black rectangle of burned picture in WIN.SMK video. return { ratingText, 5000, UINT32_MAX, { 475, 110 }, 140 }; } } const char * GameOver::GetString( uint32_t cond ) { switch ( cond ) { case WINS_ALL: return _( "Defeat all enemy heroes and capture all enemy towns and castles." ); case WINS_TOWN: return _( "Capture a specific town." ); case WINS_HERO: return _( "Defeat a specific hero." ); case WINS_ARTIFACT: return _( "Find a specific artifact." ); case WINS_SIDE: return _( "Your side defeats the opposing side." ); case WINS_GOLD: return _( "Accumulate a large amount of gold." ); case LOSS_ALL: return _( "Lose all your heroes and towns." ); case LOSS_TOWN: return _( "Lose a specific town." ); case LOSS_HERO: return _( "Lose a specific hero." ); case LOSS_TIME: return _( "Run out of time. (Fail to win by a certain point.)" ); default: break; } return "None"; } std::string GameOver::GetActualDescription( uint32_t cond ) { const Settings & conf = Settings::Get(); std::string msg; if ( WINS_ALL == cond ) { msg = GetString( WINS_ALL ); } else if ( cond == WINS_SIDE ) { const Player * currentPlayer = Settings::Get().GetPlayers().GetCurrent(); assert( currentPlayer != nullptr ); const int currentColor = currentPlayer->GetColor(); const int friendColors = currentPlayer->GetFriends(); const auto makeListOfPlayers = []( const int colors ) { std::pair result{ {}, 0 }; for ( const int col : Colors( colors ) ) { const Player * player = Players::Get( col ); assert( player != nullptr ); ++result.second; if ( result.second > 1 ) { result.first += ", "; } result.first += player->GetName(); } return result; }; const auto [alliesList, alliesCount] = makeListOfPlayers( friendColors & ~currentColor ); const auto [enemiesList, enemiesCount] = makeListOfPlayers( Game::GetKingdomColors() & ~friendColors ); assert( enemiesCount > 0 ); if ( alliesCount == 0 ) { msg = _n( "You must defeat the enemy %{enemies}.", "You must defeat the enemy alliance of %{enemies}.", enemiesCount ); StringReplace( msg, "%{enemies}", enemiesList ); } else { msg = _n( "The alliance consisting of %{allies} and you must defeat the enemy %{enemies}.", "The alliance consisting of %{allies} and you must defeat the enemy alliance of %{enemies}.", enemiesCount ); StringReplace( msg, "%{allies}", alliesList ); StringReplace( msg, "%{enemies}", enemiesList ); } } else if ( WINS_TOWN & cond ) { const Castle * town = world.getCastleEntrance( conf.getCurrentMapInfo().WinsMapsPositionObject() ); assert( town != nullptr ); if ( town ) { msg = town->isCastle() ? _( "Capture the castle '%{name}'." ) : _( "Capture the town '%{name}'." ); StringReplace( msg, "%{name}", town->GetName() ); } } else if ( WINS_HERO & cond ) { const Heroes * hero = world.GetHeroesCondWins(); assert( hero != nullptr ); if ( hero ) { msg = _( "Defeat the hero '%{name}'." ); StringReplace( msg, "%{name}", hero->GetName() ); } } else if ( WINS_ARTIFACT & cond ) { if ( conf.getCurrentMapInfo().WinsFindUltimateArtifact() ) { msg = _( "Find the ultimate artifact." ); } else { const Artifact art = conf.getCurrentMapInfo().WinsFindArtifactID(); msg = _( "Find the '%{name}' artifact." ); StringReplace( msg, "%{name}", art.GetName() ); } } else if ( WINS_GOLD & cond ) { msg = _( "Accumulate %{count} gold." ); StringReplace( msg, "%{count}", conf.getCurrentMapInfo().getWinningGoldAccumulationValue() ); } if ( WINS_ALL != cond && ( WINS_ALL & cond ) ) { msg.append( _( ", or you may win by defeating all enemy heroes and capturing all enemy towns and castles." ) ); } if ( LOSS_ALL == cond ) { msg = GetString( LOSS_ALL ); } else if ( LOSS_TOWN & cond ) { const Castle * town = world.getCastleEntrance( conf.getCurrentMapInfo().LossMapsPositionObject() ); assert( town != nullptr ); if ( town ) { msg = town->isCastle() ? _( "Lose the castle '%{name}'." ) : _( "Lose the town '%{name}'." ); StringReplace( msg, "%{name}", town->GetName() ); } } else if ( LOSS_HERO & cond ) { const Heroes * hero = world.GetHeroesCondLoss(); assert( hero != nullptr ); if ( hero ) { msg = _( "Lose the hero: %{name}." ); StringReplace( msg, "%{name}", hero->GetName() ); } } else if ( LOSS_TIME & cond ) { const uint32_t dayCount = conf.getCurrentMapInfo().LossCountDays() - 1; const uint32_t month = dayCount / ( numOfDaysPerWeek * numOfWeeksPerMonth ); const uint32_t week = ( dayCount - month * ( numOfDaysPerWeek * numOfWeeksPerMonth ) ) / numOfDaysPerWeek; const uint32_t day = dayCount % numOfDaysPerWeek; msg = _( "Fail to win by the end of month %{month}, week %{week}, day %{day}." ); StringReplace( msg, "%{day}", day + 1 ); StringReplace( msg, "%{week}", week + 1 ); StringReplace( msg, "%{month}", month + 1 ); } return msg; } GameOver::Result & GameOver::Result::Get() { static Result gresult; return gresult; } GameOver::Result::Result() : colors( 0 ) , result( 0 ) {} void GameOver::Result::Reset() { colors = Game::GetKingdomColors(); result = GameOver::COND_NONE; } fheroes2::GameMode GameOver::Result::checkGameOver() { const int humanColors = Players::HumanColors(); const bool isSinglePlayer = ( Color::Count( humanColors ) == 1 ); const Settings & conf = Settings::Get(); const int currentColor = conf.CurrentColor(); // Remembers whether the current player was considered active at the time of calling this function const bool isCurrentPlayerWasActive = ( currentColor & colors ); int activeHumanColors = 0; for ( const int color : Colors( colors ) ) { if ( !world.GetKingdom( color ).isPlay() ) { // This notification should always be displayed for the AI players. For human players, this should only be displayed in a multiplayer game for a // human player who is not currently active - in all other cases, the "you have been eliminated" dialog should be displayed. if ( !( color & humanColors ) || ( !isSinglePlayer && color != currentColor ) ) { Game::DialogPlayers( color, _( "Major Event!" ), _( "%{color} player has been vanquished!" ) ); } colors &= ( ~color ); } else if ( color & humanColors ) { ++activeHumanColors; } } if ( isSinglePlayer ) { assert( activeHumanColors <= 1 ); const Kingdom & kingdom = world.GetKingdom( humanColors ); #if defined( WITH_DEBUG ) const Player * player = Players::Get( humanColors ); assert( player != nullptr ); const bool isAIAutoControlMode = player->isAIAutoControlMode(); #else const bool isAIAutoControlMode = false; #endif if ( kingdom.isControlHuman() || isAIAutoControlMode ) { // First check loss conditions and then victory conditions. // If the player's kingdom has been vanquished, they loses regardless of other conditions. if ( !kingdom.isPlay() ) { result = GameOver::LOSS_ALL; } else { result = world.CheckKingdomLoss( kingdom ); } if ( result != GameOver::COND_NONE ) { // Don't show the loss dialog if player's kingdom has been vanquished due to the expired countdown of days since the loss of the last town. // This case was already handled at the end of the Interface::AdventureMap::HumanTurn(). if ( !( result == GameOver::LOSS_ALL && kingdom.GetCastles().empty() && kingdom.GetLostTownDays() == 0 ) ) { DialogLoss( result ); } AudioManager::ResetAudio(); Video::ShowVideo( "LOSE.SMK", Video::VideoAction::LOOP_VIDEO ); return fheroes2::GameMode::MAIN_MENU; } result = world.CheckKingdomWins( kingdom ); if ( result != GameOver::COND_NONE ) { DialogWins( result ); if ( conf.isCampaignGameType() ) { return fheroes2::GameMode::COMPLETE_CAMPAIGN_SCENARIO; } AudioManager::ResetAudio(); Video::ShowVideo( "WIN.SMK", Video::VideoAction::WAIT_FOR_USER_INPUT, { standardGameResults() }, true ); // AudioManager::PlayMusic is run here in order to start playing before displaying the high score. AudioManager::PlayMusicAsync( MUS::VICTORY, Music::PlaybackMode::REWIND_AND_PLAY_INFINITE ); return fheroes2::GameMode::HIGHSCORES_STANDARD; } } } else { result = [currentColor, activeHumanColors]() -> uint32_t { // If all human-controlled players have been vanquished, then the game is over if ( activeHumanColors == 0 ) { return GameOver::LOSS_ALL; } // Do not perform other checks if there is no active kingdom at the moment if ( !( currentColor & Color::ALL ) ) { return GameOver::COND_NONE; } const Kingdom & kingdom = world.GetKingdom( currentColor ); #if defined( WITH_DEBUG ) const Player * player = Players::Get( currentColor ); assert( player != nullptr ); const bool isAIAutoControlMode = player->isAIAutoControlMode(); #else const bool isAIAutoControlMode = false; #endif // Check the win/loss conditions for human-controlled players only if ( !kingdom.isControlHuman() && !isAIAutoControlMode ) { return GameOver::COND_NONE; } // If the player's kingdom has been vanquished, this particular player loses regardless of other conditions if ( !kingdom.isPlay() ) { return GameOver::LOSS_ALL; } uint32_t condition = world.CheckKingdomWins( kingdom ); if ( condition != GameOver::COND_NONE ) { return condition; } condition = world.CheckKingdomLoss( kingdom ); // LOSS_TOWN is currently not supported in multiplayer if ( condition == GameOver::LOSS_HERO || condition == GameOver::LOSS_TIME || ( condition & GameOver::LOSS_ENEMY_WINS ) ) { return condition; } return GameOver::COND_NONE; }(); if ( result & GameOver::LOSS ) { const bool showLossDialog = [currentColor, isCurrentPlayerWasActive, this]() { // We shouldn't show the loss notification dialog if there is no active kingdom at the moment if ( !( currentColor & Color::ALL ) ) { return false; } const Kingdom & kingdom = world.GetKingdom( currentColor ); #if defined( WITH_DEBUG ) const Player * player = Players::Get( currentColor ); assert( player != nullptr ); const bool isAIAutoControlMode = player->isAIAutoControlMode(); #else const bool isAIAutoControlMode = false; #endif // We shouldn't show the loss notification dialog to AI players if ( !kingdom.isControlHuman() && !isAIAutoControlMode ) { return false; } // Don't show the loss dialog if player's kingdom has been vanquished due to the expired countdown of days since the loss of the last town. // This case was already handled at the end of the Interface::AdventureMap::HumanTurn(). if ( result == GameOver::LOSS_ALL && kingdom.GetCastles().empty() && kingdom.GetLostTownDays() == 0 ) { return false; } // LOSS_ALL fulfillment by itself is not a reason to end the multiplayer game, and in this case, this function can be called multiple times. // Show the loss notification dialog just once. if ( !isCurrentPlayerWasActive ) { return false; } return true; }(); // LOSS_ALL fulfillment by itself is not a reason to end the multiplayer game, unless all human-controlled players are vanquished const bool endGame = ( result != GameOver::LOSS_ALL || activeHumanColors == 0 ); if ( showLossDialog ) { DialogLoss( result ); } if ( endGame ) { AudioManager::ResetAudio(); Video::ShowVideo( "LOSE.SMK", Video::VideoAction::LOOP_VIDEO ); return fheroes2::GameMode::MAIN_MENU; } } else if ( result & GameOver::WINS ) { DialogWins( result ); AudioManager::ResetAudio(); Video::ShowVideo( "WIN.SMK", Video::VideoAction::WAIT_FOR_USER_INPUT, { standardGameResults() }, true ); return fheroes2::GameMode::HIGHSCORES_STANDARD; } } return fheroes2::GameMode::CANCEL; } OStreamBase & GameOver::operator<<( OStreamBase & stream, const Result & res ) { return stream << res.colors << res.result; } IStreamBase & GameOver::operator>>( IStreamBase & stream, Result & res ) { return stream >> res.colors >> res.result; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_over.h000066400000000000000000000067351476115357100215320ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "game_mode.h" class IStreamBase; class OStreamBase; namespace GameOver { enum : uint32_t { COND_NONE = 0x00000000, WINS_ALL = 0x00000001, WINS_TOWN = 0x00000002, WINS_HERO = 0x00000004, WINS_ARTIFACT = 0x00000008, WINS_SIDE = 0x00000010, WINS_GOLD = 0x00000020, WINS = WINS_ALL | WINS_TOWN | WINS_HERO | WINS_ARTIFACT | WINS_SIDE | WINS_GOLD, LOSS_ALL = 0x00000100, LOSS_TOWN = 0x00000200, LOSS_HERO = 0x00000400, LOSS_TIME = 0x00000800, // These loss conditions apply if the enemy player won because of the corresponding win condition LOSS_ENEMY_WINS_TOWN = 0x00010000, LOSS_ENEMY_WINS_GOLD = 0x00020000, LOSS = LOSS_ALL | LOSS_TOWN | LOSS_HERO | LOSS_TIME | LOSS_ENEMY_WINS_TOWN | LOSS_ENEMY_WINS_GOLD, LOSS_ENEMY_WINS = LOSS_ENEMY_WINS_TOWN | LOSS_ENEMY_WINS_GOLD }; const char * GetString( uint32_t cond ); std::string GetActualDescription( uint32_t cond ); class Result { public: static Result & Get(); void Reset(); // Resets everything // Reset game result to COND_NONE. void ResetResult() { result = GameOver::COND_NONE; } uint32_t GetResult() const { return result; } fheroes2::GameMode checkGameOver(); private: friend OStreamBase & operator<<( OStreamBase & stream, const Result & res ); friend IStreamBase & operator>>( IStreamBase & stream, Result & res ); Result(); int colors; uint32_t result; }; OStreamBase & operator<<( OStreamBase & stream, const Result & res ); IStreamBase & operator>>( IStreamBase & stream, Result & res ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_scenarioinfo.cpp000066400000000000000000000556331476115357100235720ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include "agg_image.h" #include "audio.h" #include "audio_manager.h" #include "cursor.h" #include "dialog.h" #include "dialog_selectscenario.h" #include "difficulty.h" #include "game.h" // IWYU pragma: associated #include "game_hotkeys.h" #include "game_interface.h" #include "game_mainmenu_ui.h" #include "game_mode.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "logging.h" #include "maps_fileinfo.h" #include "math_base.h" #include "math_tools.h" #include "mus.h" #include "player_info.h" #include "players.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_button.h" #include "ui_dialog.h" #include "ui_text.h" #include "ui_tool.h" #include "ui_window.h" #include "world.h" namespace { void outputNewGameInTextSupportMode() { START_TEXT_SUPPORT_MODE COUT( "Select Map for New Game\n" ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::MAIN_MENU_SELECT_MAP ) << " to select a map." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_CANCEL ) << " to close the dialog and return to the Main Menu." ) COUT( "Press " << Game::getHotKeyNameByEventId( Game::HotKeyEvent::DEFAULT_OKAY ) << " to start the chosen map." ) } void showCurrentlySelectedMapInfoInTextSupportMode( const Maps::FileInfo & mapInfo ) { START_TEXT_SUPPORT_MODE COUT( "Currently selected map:\n" ) COUT( mapInfo.getSummary() ) } void updatePlayers( Players & players, const int humanPlayerCount ) { if ( humanPlayerCount < 2 ) return; int foundHumans = 0; for ( size_t i = 0; i < players.size(); ++i ) { if ( players[i]->isControlHuman() ) { ++foundHumans; if ( players[i]->isControlAI() ) players[i]->SetControl( CONTROL_HUMAN ); } if ( foundHumans == humanPlayerCount ) break; } } void DrawScenarioStaticInfo( const fheroes2::Rect & rt ) { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::FontType normalWhiteFont = fheroes2::FontType::normalWhite(); // text scenario fheroes2::Text text( _( "Scenario:" ), normalWhiteFont ); text.draw( rt.x, rt.y + 9, rt.width, display ); // text game difficulty text.set( _( "Game Difficulty:" ), normalWhiteFont ); text.draw( rt.x, rt.y + 59, rt.width, display ); // text opponents text.set( _( "Opponents:" ), normalWhiteFont ); text.draw( rt.x, rt.y + 164, rt.width, display ); // text class text.set( _( "Class:" ), normalWhiteFont ); text.draw( rt.x, rt.y + 248, rt.width, display ); } void RedrawMapTitle( const Settings & conf, const fheroes2::Rect & maxRoi, const fheroes2::Rect & centeredRoi ) { const auto & info = conf.getCurrentMapInfo(); fheroes2::Text text{ info.name, fheroes2::FontType::normalWhite(), info.getSupportedLanguage() }; if ( text.width() > centeredRoi.width ) { text.fitToOneRow( maxRoi.width ); text.draw( maxRoi.x + ( maxRoi.width - text.width() ), maxRoi.y + 3, text.width(), fheroes2::Display::instance() ); } else { text.draw( centeredRoi.x, centeredRoi.y + 3, centeredRoi.width, fheroes2::Display::instance() ); } } void RedrawDifficultyInfo( const fheroes2::Point & dst ) { const int32_t width = 77; const int32_t height = 69; for ( int32_t current = Difficulty::EASY; current <= Difficulty::IMPOSSIBLE; ++current ) { const int32_t offset = width * current; int32_t normalSpecificOffset = 0; // Add offset shift because the original difficulty icons have irregular spacing. if ( current == Difficulty::NORMAL ) { normalSpecificOffset = 1; } fheroes2::Text text( Difficulty::String( current ), fheroes2::FontType::smallWhite() ); text.draw( dst.x + 31 + offset + normalSpecificOffset - ( text.width() / 2 ), dst.y + height, fheroes2::Display::instance() ); } } fheroes2::Rect RedrawRatingInfo( const fheroes2::Point & offset, int32_t width_ ) { std::string str( _( "Rating %{rating}%" ) ); StringReplace( str, "%{rating}", Game::GetRating() ); const fheroes2::Text text( str, fheroes2::FontType::normalWhite() ); const int32_t y = offset.y + 372; text.draw( offset.x, y, width_, fheroes2::Display::instance() ); const int32_t textX = ( width_ > text.width() ) ? offset.x + ( width_ - text.width() ) / 2 : 0; return { textX, y, text.width(), text.height() }; } fheroes2::GameMode ChooseNewMap( const MapsFileInfoList & lists, const int humanPlayerCount ) { assert( !lists.empty() ); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); Settings & conf = Settings::Get(); const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::drawMainMenuScreen(); fheroes2::StandardWindow background( 388, 397, true, display ); const fheroes2::Rect roi( background.activeArea() ); const fheroes2::Point pointDifficultyInfo( roi.x + 8, roi.y + 79 ); const fheroes2::Point pointOpponentInfo( roi.x + 8, roi.y + 181 ); const fheroes2::Point pointClassInfo( roi.x + 8, roi.y + 265 ); const fheroes2::Sprite & scenarioBox = fheroes2::AGG::GetICN( isEvilInterface ? ICN::METALLIC_BORDERED_TEXTBOX_EVIL : ICN::METALLIC_BORDERED_TEXTBOX_GOOD, 0 ); const fheroes2::Rect scenarioBoxRoi( roi.x + ( roi.width - scenarioBox.width() ) / 2, roi.y + 24, scenarioBox.width(), scenarioBox.height() ); fheroes2::Copy( scenarioBox, 0, 0, display, scenarioBoxRoi ); fheroes2::addGradientShadow( scenarioBox, display, scenarioBoxRoi.getPosition(), { -5, 5 } ); const fheroes2::Sprite & difficultyCursor = fheroes2::AGG::GetICN( ICN::NGEXTRA, 62 ); const int32_t difficultyCursorWidth = difficultyCursor.width(); const int32_t difficultyCursorHeight = difficultyCursor.height(); // vector coord difficulty std::vector coordDifficulty; coordDifficulty.reserve( 5 ); coordDifficulty.emplace_back( roi.x + 8, roi.y + 78, difficultyCursorWidth, difficultyCursorHeight ); coordDifficulty.emplace_back( roi.x + 85, roi.y + 78, difficultyCursorWidth, difficultyCursorHeight ); coordDifficulty.emplace_back( roi.x + 161, roi.y + 78, difficultyCursorWidth, difficultyCursorHeight ); coordDifficulty.emplace_back( roi.x + 238, roi.y + 78, difficultyCursorWidth, difficultyCursorHeight ); coordDifficulty.emplace_back( roi.x + 315, roi.y + 78, difficultyCursorWidth, difficultyCursorHeight ); const int32_t buttonSelectWidth = fheroes2::AGG::GetICN( ICN::BUTTON_MAP_SELECT_GOOD, 0 ).width(); fheroes2::Button buttonSelectMaps( scenarioBoxRoi.x + scenarioBoxRoi.width - 6 - buttonSelectWidth, scenarioBoxRoi.y + 5, isEvilInterface ? ICN::BUTTON_MAP_SELECT_EVIL : ICN::BUTTON_MAP_SELECT_GOOD, 0, 1 ); buttonSelectMaps.draw(); fheroes2::Button buttonOk; fheroes2::Button buttonCancel; const fheroes2::Point buttonOffset( 20, 6 ); const int buttonOkIcn = isEvilInterface ? ICN::BUTTON_SMALL_OKAY_EVIL : ICN::BUTTON_SMALL_OKAY_GOOD; background.renderButton( buttonOk, buttonOkIcn, 0, 1, buttonOffset, fheroes2::StandardWindow::Padding::BOTTOM_LEFT ); const int buttonCancelIcn = isEvilInterface ? ICN::BUTTON_SMALL_CANCEL_EVIL : ICN::BUTTON_SMALL_CANCEL_GOOD; background.renderButton( buttonCancel, buttonCancelIcn, 0, 1, buttonOffset, fheroes2::StandardWindow::Padding::BOTTOM_RIGHT ); const Maps::FileInfo & mapInfo = [&lists, &conf = std::as_const( conf )]() { const Maps::FileInfo & currentMapinfo = conf.getCurrentMapInfo(); if ( currentMapinfo.filename.empty() ) { return lists.front(); } // Make sure that the current map actually exists in the map's list const auto iter = std::find_if( lists.begin(), lists.end(), [¤tMapinfo]( const Maps::FileInfo & info ) { return info.name == currentMapinfo.name && info.filename == currentMapinfo.filename; } ); if ( iter == lists.end() ) { return lists.front(); } return *iter; }(); Players & players = conf.GetPlayers(); showCurrentlySelectedMapInfoInTextSupportMode( mapInfo ); conf.setCurrentMapInfo( mapInfo ); updatePlayers( players, humanPlayerCount ); Game::LoadPlayers( mapInfo.filename, players ); Interface::PlayersInfo playersInfo; playersInfo.UpdateInfo( players, pointOpponentInfo, pointClassInfo ); DrawScenarioStaticInfo( roi ); RedrawDifficultyInfo( pointDifficultyInfo ); const int icnIndex = isEvilInterface ? 1 : 0; // Draw difficulty icons. for ( int i = 0; i < 5; ++i ) { const fheroes2::Sprite & icon = fheroes2::AGG::GetICN( ICN::DIFFICULTY_ICON_EASY + i, icnIndex ); fheroes2::Copy( icon, 0, 0, display, coordDifficulty[i] ); fheroes2::addGradientShadow( icon, display, { coordDifficulty[i].x, coordDifficulty[i].y }, { -5, 5 } ); } // We calculate the allowed text width according to the select button's width while ensuring symmetric placement of the map title. const int32_t boxBorder = 6; const int32_t overallBoxTextAreaWidth = ( scenarioBoxRoi.width - ( 2 * boxBorder ) ); const int32_t maxTextAreaWidth = overallBoxTextAreaWidth - buttonSelectWidth; const fheroes2::Rect maxTextRoi{ scenarioBoxRoi.x + boxBorder, scenarioBoxRoi.y + 5, maxTextAreaWidth, 19 }; const int32_t halfBoxTextAreaWidth = overallBoxTextAreaWidth / 2; const int32_t rightSideAvailableTextWidth = ( halfBoxTextAreaWidth > buttonSelectWidth ) ? ( halfBoxTextAreaWidth - buttonSelectWidth ) : ( buttonSelectWidth - halfBoxTextAreaWidth ); const fheroes2::Rect centeredTextRoi{ scenarioBoxRoi.x + boxBorder + buttonSelectWidth, scenarioBoxRoi.y + 5, 2 * rightSideAvailableTextWidth, 19 }; // Set up restorers. fheroes2::ImageRestorer mapTitleArea( display, maxTextRoi.x, maxTextRoi.y, maxTextRoi.width, maxTextRoi.height ); fheroes2::ImageRestorer opponentsArea( display, roi.x, pointOpponentInfo.y, roi.width, 65 ); fheroes2::ImageRestorer classArea( display, roi.x, pointClassInfo.y, roi.width, 69 ); fheroes2::ImageRestorer handicapArea( display, roi.x, pointClassInfo.y + 69, roi.width, 31 ); fheroes2::ImageRestorer ratingArea( display, buttonOk.area().x + buttonOk.area().width, buttonOk.area().y, roi.width - buttonOk.area().width - buttonCancel.area().width - 20 * 2, buttonOk.area().height ); // Map name RedrawMapTitle( conf, maxTextRoi, centeredTextRoi ); playersInfo.RedrawInfo( false ); fheroes2::Rect ratingRoi = RedrawRatingInfo( roi.getPosition(), roi.width ); fheroes2::MovableSprite levelCursor( difficultyCursor ); const int32_t levelCursorOffset = 3; switch ( Game::getDifficulty() ) { case Difficulty::EASY: levelCursor.setPosition( coordDifficulty[0].x - levelCursorOffset, coordDifficulty[0].y - levelCursorOffset ); break; case Difficulty::NORMAL: levelCursor.setPosition( coordDifficulty[1].x - levelCursorOffset, coordDifficulty[1].y - levelCursorOffset ); break; case Difficulty::HARD: levelCursor.setPosition( coordDifficulty[2].x - levelCursorOffset, coordDifficulty[2].y - levelCursorOffset ); break; case Difficulty::EXPERT: levelCursor.setPosition( coordDifficulty[3].x - levelCursorOffset, coordDifficulty[3].y - levelCursorOffset ); break; case Difficulty::IMPOSSIBLE: levelCursor.setPosition( coordDifficulty[4].x - levelCursorOffset, coordDifficulty[4].y - levelCursorOffset ); break; default: // Did you add a new difficulty mode? Add the corresponding case above! assert( 0 ); break; } levelCursor.redraw(); fheroes2::validateFadeInAndRender(); fheroes2::GameMode result = fheroes2::GameMode::QUIT_GAME; outputNewGameInTextSupportMode(); LocalEvent & le = LocalEvent::Get(); while ( true ) { if ( !le.HandleEvents( true, true ) ) { if ( Interface::AdventureMap::EventExit() == fheroes2::GameMode::QUIT_GAME ) { fheroes2::fadeOutDisplay(); return fheroes2::GameMode::QUIT_GAME; } continue; } // press button buttonSelectMaps.drawOnState( le.isMouseLeftButtonPressedInArea( buttonSelectMaps.area() ) ); buttonOk.drawOnState( le.isMouseLeftButtonPressedInArea( buttonOk.area() ) ); buttonCancel.drawOnState( le.isMouseLeftButtonPressedInArea( buttonCancel.area() ) ); // click select if ( HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_SELECT_MAP ) || le.MouseClickLeft( buttonSelectMaps.area() ) ) { const Maps::FileInfo * fi = Dialog::SelectScenario( lists, false ); // The previous dialog might still have a pressed button event. We have to clean the state. le.reset(); const std::string currentMapName = conf.getCurrentMapInfo().filename; if ( fi && fi->filename != currentMapName ) { showCurrentlySelectedMapInfoInTextSupportMode( *fi ); Game::SavePlayers( currentMapName, conf.GetPlayers() ); conf.setCurrentMapInfo( *fi ); mapTitleArea.restore(); RedrawMapTitle( conf, maxTextRoi, centeredTextRoi ); Game::LoadPlayers( fi->filename, players ); opponentsArea.restore(); classArea.restore(); handicapArea.restore(); ratingArea.restore(); updatePlayers( players, humanPlayerCount ); playersInfo.UpdateInfo( players, pointOpponentInfo, pointClassInfo ); playersInfo.resetSelection(); playersInfo.RedrawInfo( false ); ratingRoi = RedrawRatingInfo( roi.getPosition(), roi.width ); levelCursor.setPosition( coordDifficulty[Game::getDifficulty()].x - levelCursorOffset, coordDifficulty[Game::getDifficulty()].y - levelCursorOffset ); // From 0 to 4, see: Difficulty enum } display.render(); outputNewGameInTextSupportMode(); } else if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) || le.MouseClickLeft( buttonCancel.area() ) ) { result = fheroes2::GameMode::MAIN_MENU; break; } if ( Game::HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_OKAY ) || le.MouseClickLeft( buttonOk.area() ) ) { DEBUG_LOG( DBG_GAME, DBG_INFO, "select maps: " << conf.getCurrentMapInfo().filename << ", difficulty: " << Difficulty::String( Game::getDifficulty() ) ) result = fheroes2::GameMode::START_GAME; // Fade-out screen before starting a scenario. fheroes2::fadeOutDisplay(); break; } if ( le.MouseClickLeft( roi ) ) { const int32_t index = GetRectIndex( coordDifficulty, le.getMouseCursorPos() ); // select difficulty if ( 0 <= index ) { levelCursor.setPosition( coordDifficulty[index].x - levelCursorOffset, coordDifficulty[index].y - levelCursorOffset ); levelCursor.redraw(); Game::saveDifficulty( index ); ratingArea.restore(); ratingRoi = RedrawRatingInfo( roi.getPosition(), roi.width ); display.render( roi ); } // playersInfo else if ( playersInfo.QueueEventProcessing() ) { opponentsArea.restore(); classArea.restore(); handicapArea.restore(); playersInfo.RedrawInfo( false ); display.render( roi ); } } else if ( ( le.isMouseWheelUp() || le.isMouseWheelDown() ) && playersInfo.QueueEventProcessing() ) { playersInfo.resetSelection(); opponentsArea.restore(); classArea.restore(); handicapArea.restore(); playersInfo.RedrawInfo( false ); display.render( roi ); } if ( le.isMouseRightButtonPressedInArea( roi ) ) { if ( le.isMouseRightButtonPressedInArea( buttonSelectMaps.area() ) ) { fheroes2::showStandardTextMessage( _( "Scenario" ), _( "Click here to select which scenario to play." ), Dialog::ZERO ); } else if ( 0 <= GetRectIndex( coordDifficulty, le.getMouseCursorPos() ) ) { fheroes2::showStandardTextMessage( _( "Game Difficulty" ), _( "This lets you change the starting difficulty at which you will play. Higher difficulty levels start you off with fewer resources, and at the higher settings, give extra resources to the computer." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( ratingRoi ) ) { fheroes2::showStandardTextMessage( _( "Difficulty Rating" ), _( "The difficulty rating reflects a combination of various settings for your game. This number will be applied to your final score." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonOk.area() ) ) { fheroes2::showStandardTextMessage( _( "Okay" ), _( "Click to accept these settings and start a new game." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( buttonCancel.area() ) ) { fheroes2::showStandardTextMessage( _( "Cancel" ), _( "Click to return to the main menu." ), Dialog::ZERO ); } else { playersInfo.QueueEventProcessing(); } } } Game::SavePlayers( conf.getCurrentMapInfo().filename, conf.GetPlayers() ); return result; } fheroes2::GameMode LoadNewMap() { Settings & conf = Settings::Get(); conf.GetPlayers().SetStartGame(); const Maps::FileInfo & mapInfo = conf.getCurrentMapInfo(); if ( mapInfo.version == GameVersion::SUCCESSION_WARS || mapInfo.version == GameVersion::PRICE_OF_LOYALTY ) { if ( world.LoadMapMP2( mapInfo.filename, ( mapInfo.version == GameVersion::SUCCESSION_WARS ) ) ) { return fheroes2::GameMode::START_GAME; } fheroes2::drawMainMenuScreen(); fheroes2::showStandardTextMessage( _( "Warning" ), _( "The map is corrupted." ), Dialog::OK ); return fheroes2::GameMode::MAIN_MENU; } assert( mapInfo.version == GameVersion::RESURRECTION ); if ( world.loadResurrectionMap( mapInfo.filename ) ) { return fheroes2::GameMode::START_GAME; } fheroes2::drawMainMenuScreen(); fheroes2::showStandardTextMessage( _( "Warning" ), _( "The map is corrupted." ), Dialog::OK ); return fheroes2::GameMode::MAIN_MENU; } } fheroes2::GameMode Game::SelectScenario( const uint8_t humanPlayerCount ) { assert( humanPlayerCount >= 1 && humanPlayerCount <= 6 ); AudioManager::PlayMusicAsync( MUS::MAINMENU, Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); const MapsFileInfoList maps = Maps::getAllMapFileInfos( false, humanPlayerCount ); if ( maps.empty() ) { fheroes2::showStandardTextMessage( _( "Warning" ), _( "No maps available!" ), Dialog::OK ); return fheroes2::GameMode::MAIN_MENU; } // We must release UI resources for this window before loading a new map. That's why all UI logic is in a separate function. const fheroes2::GameMode result = ChooseNewMap( maps, humanPlayerCount ); if ( result != fheroes2::GameMode::START_GAME ) { return result; } return LoadNewMap(); } int32_t Game::GetStep4Player( const int32_t currentId, const int32_t width, const int32_t totalCount ) { return currentId * width * maxNumOfPlayers / totalCount + ( width * ( maxNumOfPlayers - totalCount ) / ( 2 * totalCount ) ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_startgame.cpp000066400000000000000000001745331476115357100231030ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game.h" // IWYU pragma: associated #include #include #include #include #include #include #include #include #include #include "agg_image.h" #include "ai_planner.h" #include "army.h" #include "audio.h" #include "audio_manager.h" #include "battle_only.h" #include "castle.h" #include "color.h" #include "cursor.h" #include "dialog.h" #include "direction.h" #include "game_delays.h" #include "game_hotkeys.h" #include "game_interface.h" // IWYU pragma: associated #include "game_io.h" #include "game_mode.h" #include "game_over.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "interface_base.h" #include "interface_buttons.h" #include "interface_cpanel.h" #include "interface_gamearea.h" #include "interface_icons.h" #include "interface_radar.h" #include "interface_status.h" #include "kingdom.h" #include "localevent.h" #include "logging.h" #include "m82.h" #include "maps.h" #include "maps_fileinfo.h" #include "maps_tiles.h" #include "maps_tiles_helper.h" #include "math_base.h" #include "monster.h" #include "mp2.h" #include "mus.h" #include "players.h" #include "resource.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "ui_language.h" #include "ui_text.h" #include "ui_tool.h" #include "week.h" #include "world.h" namespace { bool SortPlayers( const Player * player1, const Player * player2 ) { return ( player1->isControlHuman() && !player2->isControlHuman() ) || ( ( player1->isControlHuman() == player2->isControlHuman() ) && ( player1->GetColor() < player2->GetColor() ) ); } // Get colors value of players to use in fog directions update. // For human allied AI returns colors of this alliance, for hostile AI - colors of all human players and their allies. int32_t hotSeatAIFogColors( const Player * player ) { assert( player != nullptr ); // This function should be called when AI makes a move. assert( world.GetKingdom( player->GetColor() ).GetControl() == CONTROL_AI ); const int32_t humanColors = Players::HumanColors(); // Check if the current AI player is a friend of any of human players to fully show his move and revealed map, // otherwise his revealed map will not be shown - instead of it we will show the revealed map by all human players. const bool isFriendlyAI = Players::isFriends( player->GetColor(), humanColors ); #if defined( WITH_DEBUG ) if ( isFriendlyAI || player->isAIAutoControlMode() ) { #else if ( isFriendlyAI ) { #endif // Fully update fog directions for allied AI players in Hot Seat mode as the previous move could be done by opposing player. return player->GetFriends(); } // If AI is hostile for all human players then fully update fog directions for all human players to see enemy AI hero move on tiles with // discovered fog. int32_t friendColors = 0; for ( const int32_t color : Colors( humanColors ) ) { const Player * humanPlayer = Players::Get( color ); if ( humanPlayer ) { friendColors |= humanPlayer->GetFriends(); } } return friendColors; } void ShowNewWeekDialog() { // restore the original music on exit const AudioManager::MusicRestorer musicRestorer; const bool isNewMonth = world.BeginMonth(); AudioManager::PlayMusic( isNewMonth ? MUS::NEW_MONTH : MUS::NEW_WEEK, Music::PlaybackMode::PLAY_ONCE ); const Week & week = world.GetWeekType(); // head std::string message = isNewMonth ? _( "Astrologers proclaim the Month of the %{name}." ) : _( "Astrologers proclaim the Week of the %{name}." ); StringReplace( message, "%{name}", week.GetName() ); message += "\n\n"; if ( week.GetType() == WeekName::MONSTERS ) { const Monster monster( week.GetMonster() ); const uint32_t count = isNewMonth ? Castle::GetGrownMonthOf() : Castle::GetGrownWeekOf(); if ( monster.isValid() && count ) { if ( isNewMonth ) message += 100 == Castle::GetGrownMonthOf() ? _( "After regular growth, the population of %{monster} is doubled!" ) : _n( "After regular growth, the population of %{monster} increases by %{count} percent!", "After regular growth, the population of %{monster} increases by %{count} percent!", count ); else message += _( "%{monster} growth +%{count}." ); StringReplaceWithLowercase( message, "%{monster}", monster.GetMultiName() ); StringReplace( message, "%{count}", count ); message += "\n\n"; } } if ( week.GetType() == WeekName::PLAGUE ) message += _( " All populations are halved." ); else message += _( " All dwellings increase population." ); fheroes2::showStandardTextMessage( isNewMonth ? _( "New Month!" ) : _( "New Week!" ), message, Dialog::OK ); } void ShowWarningLostTownsDialog() { const Kingdom & myKingdom = world.GetKingdom( Settings::Get().CurrentColor() ); const uint32_t lostTownDays = myKingdom.GetLostTownDays(); if ( lostTownDays == 1 ) { Game::DialogPlayers( myKingdom.GetColor(), _( "Beware!" ), _( "%{color} player, this is your last day to capture a town, or you will be banished from this land." ) ); } else if ( lostTownDays > 0 && lostTownDays <= Game::GetLostTownDays() ) { std::string str = _( "%{color} player, you only have %{day} days left to capture a town, or you will be banished from this land." ); StringReplace( str, "%{day}", lostTownDays ); Game::DialogPlayers( myKingdom.GetColor(), _( "Beware!" ), str ); } } } fheroes2::GameMode Game::StartBattleOnly() { static Battle::Only battleOnlySetup; world.generateBattleOnlyMap(); bool reset = false; bool allowBackup = true; while ( battleOnlySetup.setup( allowBackup, reset ) ) { allowBackup = false; if ( reset ) { world.generateBattleOnlyMap(); battleOnlySetup.reset(); reset = false; continue; } battleOnlySetup.StartBattle(); break; } return fheroes2::GameMode::MAIN_MENU; } fheroes2::GameMode Game::StartGame() { const Settings & conf = Settings::Get(); // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); if ( !conf.LoadedGameVersion() ) GameOver::Result::Get().Reset(); return Interface::AdventureMap::Get().StartGame(); } void Game::DialogPlayers( int color, std::string title, std::string message ) { const Player * player = Players::Get( color ); StringReplace( message, "%{color}", ( player ? player->GetName() : Color::String( color ) ) ); const fheroes2::Sprite & border = fheroes2::AGG::GetICN( ICN::BRCREST, 6 ); fheroes2::Sprite sign = border; switch ( color ) { case Color::BLUE: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::BRCREST, 0 ), sign, 4, 4 ); break; case Color::GREEN: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::BRCREST, 1 ), sign, 4, 4 ); break; case Color::RED: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::BRCREST, 2 ), sign, 4, 4 ); break; case Color::YELLOW: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::BRCREST, 3 ), sign, 4, 4 ); break; case Color::ORANGE: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::BRCREST, 4 ), sign, 4, 4 ); break; case Color::PURPLE: fheroes2::Blit( fheroes2::AGG::GetICN( ICN::BRCREST, 5 ), sign, 4, 4 ); break; default: // Did you add a new color? Add the logic for it! assert( 0 ); break; } const fheroes2::CustomImageDialogElement imageUI( std::move( sign ) ); fheroes2::showStandardTextMessage( std::move( title ), std::move( message ), Dialog::OK, { &imageUI } ); } void Game::OpenCastleDialog( Castle & castle, bool updateFocus /* = true */, const bool renderBackgroundDialog /* = true */ ) { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); // Stop all sounds, but not the music - it will be replaced by the music of the castle AudioManager::stopSounds(); const Settings & conf = Settings::Get(); Kingdom & myKingdom = world.GetKingdom( conf.CurrentColor() ); const VecCastles & myCastles = myKingdom.GetCastles(); VecCastles::const_iterator it = std::find( myCastles.begin(), myCastles.end(), &castle ); const size_t heroCountBefore = myKingdom.GetHeroes().size(); assert( it != myCastles.end() ); Castle::CastleDialogReturnValue result = ( *it )->OpenDialog( false, true, renderBackgroundDialog ); while ( result != Castle::CastleDialogReturnValue::Close ) { if ( result == Castle::CastleDialogReturnValue::PreviousCastle || result == Castle::CastleDialogReturnValue::PreviousCostructionWindow ) { if ( it == myCastles.begin() ) { it = myCastles.end(); } --it; } else if ( result == Castle::CastleDialogReturnValue::NextCastle || result == Castle::CastleDialogReturnValue::NextCostructionWindow ) { ++it; if ( it == myCastles.end() ) { it = myCastles.begin(); } } assert( it != myCastles.end() ); const bool openConstructionWindow = ( result == Castle::CastleDialogReturnValue::PreviousCostructionWindow ) || ( result == Castle::CastleDialogReturnValue::NextCostructionWindow ); result = ( *it )->OpenDialog( openConstructionWindow, false, renderBackgroundDialog ); } // If Castle dialog background was not rendered than we have opened it from other dialog (Kingdom Overview) // and there is no need update Adventure map interface at this time. if ( renderBackgroundDialog ) { Interface::AdventureMap & adventureMapInterface = Interface::AdventureMap::Get(); if ( updateFocus ) { if ( heroCountBefore < myKingdom.GetHeroes().size() ) { adventureMapInterface.SetFocus( myKingdom.GetHeroes()[heroCountBefore], false ); } else if ( it != myCastles.end() ) { Heroes * heroInCastle = world.getTile( ( *it )->GetIndex() ).getHero(); if ( heroInCastle == nullptr ) { adventureMapInterface.SetFocus( *it ); } else { adventureMapInterface.SetFocus( heroInCastle, false ); } } else { adventureMapInterface.ResetFocus( GameFocus::HEROES, false ); } } else { // If we don't update focus, we still have to restore environment sounds and terrain music theme restoreSoundsForCurrentFocus(); } // The castle garrison can change adventureMapInterface.RedrawFocus(); adventureMapInterface.ResetFocus( Interface::GetFocusType(), false ); // Fade-in game screen only for 640x480 resolution. if ( fheroes2::Display::instance().isDefaultSize() ) { setDisplayFadeIn(); } } else { // If we opened the castle dialog from other dialog, we have to restore environment sounds and terrain music theme instead of the castle's music theme restoreSoundsForCurrentFocus(); } } void Game::OpenHeroesDialog( Heroes & hero, bool updateFocus, const bool renderBackgroundDialog, const bool disableDismiss /* = false */ ) { // setup cursor const CursorRestorer cursorRestorer( true, Cursor::POINTER ); Interface::AdventureMap & adventureMapInterface = Interface::AdventureMap::Get(); const VecHeroes & myHeroes = hero.GetKingdom().GetHeroes(); VecHeroes::const_iterator it = std::find( myHeroes.begin(), myHeroes.end(), &hero ); const bool isDefaultScreenSize = fheroes2::Display::instance().isDefaultSize(); bool needFade = true; int result = Dialog::ZERO; while ( it != myHeroes.end() && result != Dialog::CANCEL ) { result = ( *it )->OpenDialog( false, needFade, disableDismiss, false, renderBackgroundDialog, false, fheroes2::getLanguageFromAbbreviation( Settings::Get().getGameLanguage() ) ); if ( needFade ) { needFade = false; } switch ( result ) { case Dialog::PREV: if ( it == myHeroes.begin() ) { it = myHeroes.end(); } --it; break; case Dialog::NEXT: ++it; if ( it == myHeroes.end() ) { it = myHeroes.begin(); } break; case Dialog::DISMISS: AudioManager::PlaySound( M82::KILLFADE ); ( *it )->ShowPath( false ); // Check if this dialog is not opened from the other dialog and we will be exiting to the Adventure map. if ( renderBackgroundDialog ) { // Redraw Adventure map with hidden hero path. adventureMapInterface.redraw( Interface::REDRAW_GAMEAREA ); // Fade-in game screen only for 640x480 resolution. if ( isDefaultScreenSize ) { fheroes2::fadeInDisplay(); } ( *it )->FadeOut(); updateFocus = true; } ( *it )->Dismiss( 0 ); it = myHeroes.end(); result = Dialog::CANCEL; break; case Dialog::CANCEL: needFade = true; break; default: break; } } // If Hero dialog background was not rendered than we have opened it from other dialog (Kingdom Overview or Castle dialog) // and there is no need update Adventure map interface at this time. if ( renderBackgroundDialog ) { if ( updateFocus ) { if ( it != myHeroes.end() ) { adventureMapInterface.SetFocus( *it, false ); } else { adventureMapInterface.ResetFocus( GameFocus::HEROES, false ); } } // The hero's army can change adventureMapInterface.RedrawFocus(); // Fade-in game screen only for 640x480 resolution. if ( needFade && renderBackgroundDialog && isDefaultScreenSize ) { setDisplayFadeIn(); } } } int Interface::AdventureMap::GetCursorFocusCastle( const Castle & castle, const Maps::Tile & tile ) { switch ( tile.getMainObjectType() ) { case MP2::OBJ_NON_ACTION_CASTLE: case MP2::OBJ_CASTLE: { const Castle * otherCastle = world.getCastle( tile.GetCenter() ); if ( otherCastle ) { return otherCastle->GetColor() == castle.GetColor() ? Cursor::CASTLE : Cursor::POINTER; } break; } case MP2::OBJ_HERO: { const Heroes * hero = tile.getHero(); if ( hero ) { return hero->GetColor() == castle.GetColor() ? Cursor::HEROES : Cursor::POINTER; } break; } default: break; } return Cursor::POINTER; } int Interface::AdventureMap::GetCursorFocusShipmaster( const Heroes & hero, const Maps::Tile & tile ) { const bool isWater = tile.isWater(); switch ( tile.getMainObjectType() ) { case MP2::OBJ_NON_ACTION_CASTLE: case MP2::OBJ_CASTLE: { const Castle * castle = world.getCastle( tile.GetCenter() ); if ( castle ) { if ( tile.getMainObjectType() == MP2::OBJ_NON_ACTION_CASTLE && isWater && tile.isPassableFrom( Direction::CENTER, true, false, hero.GetColor() ) ) { return Cursor::DistanceThemes( Cursor::CURSOR_HERO_BOAT, hero.getNumOfTravelDays( tile.GetIndex() ) ); } return hero.GetColor() == castle->GetColor() ? Cursor::CASTLE : Cursor::POINTER; } break; } case MP2::OBJ_HERO: { const Heroes * otherHero = tile.getHero(); if ( otherHero ) { if ( !otherHero->isShipMaster() ) { return hero.GetColor() == otherHero->GetColor() ? Cursor::HEROES : Cursor::POINTER; } if ( otherHero->GetCenter() == hero.GetCenter() ) { return Cursor::HEROES; } if ( hero.GetColor() == otherHero->GetColor() ) { return Cursor::DistanceThemes( Cursor::CURSOR_HERO_MEET, hero.getNumOfTravelDays( tile.GetIndex() ) ); } if ( hero.isFriends( otherHero->GetColor() ) ) { return Cursor::POINTER; } return Cursor::DistanceThemes( Cursor::CURSOR_HERO_FIGHT, hero.getNumOfTravelDays( tile.GetIndex() ) ); } break; } // Some map editors allow to place monsters on water tiles case MP2::OBJ_MONSTER: return isWater ? Cursor::DistanceThemes( Cursor::CURSOR_HERO_FIGHT, hero.getNumOfTravelDays( tile.GetIndex() ) ) : Cursor::POINTER; case MP2::OBJ_COAST: return Cursor::DistanceThemes( Cursor::CURSOR_HERO_ANCHOR, hero.getNumOfTravelDays( tile.GetIndex() ) ); default: if ( isWater ) { if ( MP2::isWaterActionObject( tile.getMainObjectType() ) ) { return Cursor::DistanceThemes( Cursor::CURSOR_HERO_BOAT_ACTION, hero.getNumOfTravelDays( tile.GetIndex() ) ); } if ( tile.isPassableFrom( Direction::CENTER, true, false, hero.GetColor() ) ) { return Cursor::DistanceThemes( Cursor::CURSOR_HERO_BOAT, hero.getNumOfTravelDays( tile.GetIndex() ) ); } } break; } return Cursor::POINTER; } int Interface::AdventureMap::_getCursorNoFocus( const Maps::Tile & tile ) { switch ( tile.getMainObjectType() ) { case MP2::OBJ_NON_ACTION_CASTLE: case MP2::OBJ_CASTLE: { const Castle * castle = world.getCastle( tile.GetCenter() ); if ( castle && castle->GetColor() == Settings::Get().CurrentColor() ) { return Cursor::CASTLE; } break; } case MP2::OBJ_HERO: { const Heroes * hero = tile.getHero(); if ( hero && hero->GetColor() == Settings::Get().CurrentColor() ) { return Cursor::HEROES; } break; } default: break; } return Cursor::POINTER; } int Interface::AdventureMap::GetCursorFocusHeroes( const Heroes & hero, const Maps::Tile & tile ) { if ( hero.Modes( Heroes::ENABLEMOVE ) ) { return Cursor::Get().Themes(); } if ( hero.isShipMaster() ) { return GetCursorFocusShipmaster( hero, tile ); } switch ( tile.getMainObjectType() ) { case MP2::OBJ_NON_ACTION_CASTLE: case MP2::OBJ_CASTLE: { const Castle * castle = world.getCastle( tile.GetCenter() ); if ( castle ) { if ( tile.getMainObjectType() == MP2::OBJ_NON_ACTION_CASTLE ) { if ( tile.GetPassable() == 0 ) { return ( hero.GetColor() == castle->GetColor() ) ? Cursor::CASTLE : Cursor::POINTER; } return Cursor::DistanceThemes( Maps::isTileUnderProtection( tile.GetIndex() ) ? Cursor::CURSOR_HERO_FIGHT : Cursor::CURSOR_HERO_MOVE, hero.getNumOfTravelDays( tile.GetIndex() ) ); } if ( hero.GetIndex() == castle->GetIndex() ) { return hero.GetColor() == castle->GetColor() ? Cursor::CASTLE : Cursor::POINTER; } if ( hero.GetColor() == castle->GetColor() ) { return Cursor::DistanceThemes( Cursor::CURSOR_HERO_ACTION, hero.getNumOfTravelDays( castle->GetIndex() ) ); } if ( hero.isFriends( castle->GetColor() ) ) { return Cursor::POINTER; } if ( castle->GetActualArmy().isValid() ) { return Cursor::DistanceThemes( Cursor::CURSOR_HERO_FIGHT, hero.getNumOfTravelDays( castle->GetIndex() ) ); } return Cursor::DistanceThemes( Cursor::CURSOR_HERO_ACTION, hero.getNumOfTravelDays( castle->GetIndex() ) ); } break; } case MP2::OBJ_HERO: { const Heroes * otherHero = tile.getHero(); if ( otherHero ) { if ( otherHero->GetCenter() == hero.GetCenter() ) { return Cursor::HEROES; } if ( hero.GetColor() == otherHero->GetColor() ) { if ( HotKeyHoldEvent( Game::HotKeyEvent::WORLD_QUICK_SELECT_HERO ) ) { return Cursor::HEROES; } const int cursor = Cursor::DistanceThemes( Cursor::CURSOR_HERO_MEET, hero.getNumOfTravelDays( tile.GetIndex() ) ); return cursor != Cursor::POINTER ? cursor : Cursor::HEROES; } if ( hero.isFriends( otherHero->GetColor() ) ) { return Cursor::POINTER; } return Cursor::DistanceThemes( Cursor::CURSOR_HERO_FIGHT, hero.getNumOfTravelDays( tile.GetIndex() ) ); } break; } case MP2::OBJ_BOAT: return Cursor::DistanceThemes( Cursor::CURSOR_HERO_BOAT, hero.getNumOfTravelDays( tile.GetIndex() ) ); default: if ( MP2::isInGameActionObject( tile.getMainObjectType() ) ) { const bool isProtected = ( Maps::isTileUnderProtection( tile.GetIndex() ) || ( !hero.isFriends( getColorFromTile( tile ) ) && isCaptureObjectProtected( tile ) ) ); return Cursor::DistanceThemes( isProtected ? Cursor::CURSOR_HERO_FIGHT : Cursor::CURSOR_HERO_ACTION, hero.getNumOfTravelDays( tile.GetIndex() ) ); } if ( tile.isPassableFrom( Direction::CENTER, hero.isShipMaster(), false, hero.GetColor() ) ) { return Cursor::DistanceThemes( Maps::isTileUnderProtection( tile.GetIndex() ) ? Cursor::CURSOR_HERO_FIGHT : Cursor::CURSOR_HERO_MOVE, hero.getNumOfTravelDays( tile.GetIndex() ) ); } break; } return Cursor::POINTER; } void Interface::AdventureMap::updateCursor( const int32_t tileIndex ) { Cursor::Get().SetThemes( GetCursorTileIndex( tileIndex ) ); } int Interface::AdventureMap::GetCursorTileIndex( int32_t dstIndex ) { if ( !Maps::isValidAbsIndex( dstIndex ) ) { return Cursor::POINTER; } const Maps::Tile & tile = world.getTile( dstIndex ); if ( tile.isFog( Settings::Get().CurrentColor() ) ) { return Cursor::POINTER; } switch ( GetFocusType() ) { case GameFocus::HEROES: return GetCursorFocusHeroes( *GetFocusHeroes(), tile ); case GameFocus::CASTLE: return GetCursorFocusCastle( *GetFocusCastle(), tile ); case GameFocus::UNSEL: return _getCursorNoFocus( tile ); default: break; } return Cursor::POINTER; } fheroes2::GameMode Interface::AdventureMap::StartGame() { Settings & conf = Settings::Get(); reset(); _radar.Build(); _radar.SetHide( true ); _iconsPanel.hideIcons( ICON_ANY ); _statusPanel.Reset(); // Prepare for render the whole game interface with adventure map filled with fog as it was not uncovered by 'updateMapFogDirections()'. redraw( REDRAW_GAMEAREA | REDRAW_RADAR | REDRAW_ICONS | REDRAW_BUTTONS | REDRAW_STATUS | REDRAW_BORDER ); bool isLoadedFromSave = conf.LoadedGameVersion(); bool skipTurns = isLoadedFromSave; // Set need of fade-in of game screen. Game::setDisplayFadeIn(); GameOver::Result & gameResult = GameOver::Result::Get(); fheroes2::GameMode res = fheroes2::GameMode::END_TURN; std::vector sortedPlayers = conf.GetPlayers().getVector(); std::sort( sortedPlayers.begin(), sortedPlayers.end(), SortPlayers ); if ( !isLoadedFromSave || world.CountDay() == 1 ) { // Clear fog around heroes, castles and mines for all players when starting a new map or if the save was done at the first day. for ( const Player * player : sortedPlayers ) { world.ClearFog( player->GetColor() ); } } const bool isHotSeatGame = conf.IsGameType( Game::TYPE_HOTSEAT ); if ( !isHotSeatGame ) { // It is not a Hot Seat (multiplayer) game so we set current color to the only human player. conf.SetCurrentColor( Players::HumanColors() ); // Fully update fog directions if there will be only one human player. Interface::GameArea::updateMapFogDirections(); } while ( res == fheroes2::GameMode::END_TURN ) { if ( !isLoadedFromSave ) { world.NewDay(); } // Check if the game is over at the beginning of a new day res = gameResult.checkGameOver(); if ( res != fheroes2::GameMode::CANCEL ) { break; } res = fheroes2::GameMode::END_TURN; for ( const Player * player : sortedPlayers ) { assert( player != nullptr ); if ( skipTurns ) { // Game saves can only be performed during a human player's turn (including when it is under temporary AI control // in the case of a debug build), and human players always go first in the turn queue. If we skipped all the human // players and still haven't found the current player, then something is clearly wrong here. if ( player->GetControl() == CONTROL_AI ) { break; } if ( !player->isColor( conf.CurrentColor() ) ) { continue; } } // Player with a color equal to conf.CurrentColor() has been found, there is no need for further skips skipTurns = false; const int playerColor = player->GetColor(); Kingdom & kingdom = world.GetKingdom( playerColor ); if ( kingdom.isPlay() ) { DEBUG_LOG( DBG_GAME, DBG_INFO, world.DateString() << ", color: " << Color::String( playerColor ) << ", resource: " << kingdom.GetFunds().String() ) _radar.SetHide( true ); _radar.SetRedraw( REDRAW_RADAR_CURSOR ); switch ( kingdom.GetControl() ) { case CONTROL_HUMAN: // Reset environment sounds and music theme at the beginning of the human turn AudioManager::ResetAudio(); if ( isHotSeatGame ) { _iconsPanel.hideIcons( ICON_ANY ); _statusPanel.Reset(); // Fully update fog directions in Hot Seat mode to cover the map with fog on player change. // TODO: Cover the Adventure map area with fog sprites without rendering the "Game Area" for player change. Maps::updateFogDirectionsInArea( { 0, 0 }, { world.w(), world.h() }, Color::NONE ); redraw( REDRAW_GAMEAREA | REDRAW_ICONS | REDRAW_BUTTONS | REDRAW_STATUS ); validateFadeInAndRender(); // Reset the music after closing the dialog const AudioManager::MusicRestorer musicRestorer; AudioManager::PlayMusic( MUS::NEW_MONTH, Music::PlaybackMode::PLAY_ONCE ); Game::DialogPlayers( playerColor, "", _( "%{color} player's turn." ) ); } conf.SetCurrentColor( playerColor ); kingdom.ActionBeforeTurn(); _iconsPanel.showIcons( ICON_ANY ); _iconsPanel.setRedraw(); res = HumanTurn( isLoadedFromSave ); // Skip resetting Audio after winning scenario because MUS::VICTORY should continue playing. if ( res == fheroes2::GameMode::HIGHSCORES_STANDARD ) { break; } // Reset environment sounds and music theme at the end of the human turn. AudioManager::ResetAudio(); break; case CONTROL_AI: // TODO: remove this temporary assertion assert( res == fheroes2::GameMode::END_TURN ); Cursor::Get().SetThemes( Cursor::WAIT ); conf.SetCurrentColor( playerColor ); _statusPanel.Reset(); _statusPanel.SetState( StatusType::STATUS_AITURN ); #if defined( WITH_DEBUG ) if ( player->isAIAutoControlMode() ) { // If player gave control to AI we show the radar image and update it fully at the start of player's turn. _radar.SetHide( false ); _radar.SetRedraw( REDRAW_RADAR ); } #endif redraw( 0 ); validateFadeInAndRender(); // In Hot Seat mode there could be different alliances so we have to update fog directions for some cases. if ( isHotSeatGame ) { Maps::updateFogDirectionsInArea( { 0, 0 }, { world.w(), world.h() }, hotSeatAIFogColors( player ) ); } if ( !isLoadedFromSave ) { kingdom.ActionNewDayResourceUpdate( nullptr ); } kingdom.ActionBeforeTurn(); #if defined( WITH_DEBUG ) if ( !isLoadedFromSave && player->isAIAutoControlMode() && conf.isAutoSaveAtBeginningOfTurnEnabled() ) { // This is a human player which gave control to AI so we need to do autosave here. Game::AutoSave(); } #endif AI::Planner::Get().KingdomTurn( kingdom ); #if defined( WITH_DEBUG ) if ( !isLoadedFromSave && player->isAIAutoControlMode() && !conf.isAutoSaveAtBeginningOfTurnEnabled() ) { // This is a human player which gave control to AI so we need to do autosave here. Game::AutoSave(); } #endif break; default: // So far no other player type is supported so this should not happen. assert( 0 ); break; } if ( res != fheroes2::GameMode::END_TURN ) { break; } // Check if the game is over after each player's turn res = gameResult.checkGameOver(); if ( res != fheroes2::GameMode::CANCEL ) { break; } res = fheroes2::GameMode::END_TURN; } // Reset this after potential HumanTurn() call, but regardless of whether current kingdom // is vanquished - next alive kingdom should start a new day from scratch isLoadedFromSave = false; } // We went through all the players, but the current player from the save file is still not found, // something is clearly wrong here if ( skipTurns ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "the current player from the save file was not found" << ", player color: " << Color::String( conf.CurrentColor() ) ) res = fheroes2::GameMode::MAIN_MENU; } // Don't carry the current player color to the next turn. conf.SetCurrentColor( Color::NONE ); } // If we are here, the res value should never be fheroes2::GameMode::END_TURN assert( res != fheroes2::GameMode::END_TURN ); Game::setDisplayFadeIn(); // Do not use fade-out effect when exiting to Highscores screen as in this case name input dialog will be rendered next. if ( res != fheroes2::GameMode::HIGHSCORES_STANDARD ) { fheroes2::fadeOutDisplay(); } return res; } fheroes2::GameMode Interface::AdventureMap::HumanTurn( const bool isLoadedFromSave ) { if ( isLoadedFromSave ) { updateFocus(); } else { ResetFocus( GameFocus::FIRSTHERO, false ); } _radar.SetHide( false ); _statusPanel.Reset(); _gameArea.SetUpdateCursor(); const Settings & conf = Settings::Get(); if ( conf.IsGameType( Game::TYPE_HOTSEAT ) ) { // TODO: Cache fog directions for all Human players in array to not perform full update at every turn start. // Fully update fog directions at the start of player's move in Hot Seat mode as the previous move could be done by opposing player. Interface::GameArea::updateMapFogDirections(); } redraw( REDRAW_GAMEAREA | REDRAW_RADAR | REDRAW_ICONS | REDRAW_BUTTONS | REDRAW_STATUS | REDRAW_BORDER ); validateFadeInAndRender(); Kingdom & myKingdom = world.GetKingdom( conf.CurrentColor() ); if ( !isLoadedFromSave ) { if ( 1 < world.CountWeek() && world.BeginWeek() ) { ShowNewWeekDialog(); } myKingdom.ActionNewDayResourceUpdate( []( const EventDate & event, const Funds & funds ) { const auto & language = Settings::Get().getCurrentMapInfo().getSupportedLanguage(); if ( funds.GetValidItemsCount() ) { fheroes2::showResourceMessage( fheroes2::Text( event.title, fheroes2::FontType::normalYellow(), language ), fheroes2::Text( event.message, fheroes2::FontType::normalWhite(), language ), Dialog::OK, funds ); } else if ( !event.message.empty() ) { const fheroes2::Text header( event.title, fheroes2::FontType::normalYellow(), language ); const fheroes2::Text body( event.message, fheroes2::FontType::normalWhite(), language ); fheroes2::showMessage( header, body, Dialog::OK ); } } ); // The amount of the kingdom resources has changed, the status panel needs to be updated redraw( REDRAW_STATUS ); fheroes2::Display::instance().render(); if ( conf.isAutoSaveAtBeginningOfTurnEnabled() ) { Game::AutoSave(); } } GameOver::Result & gameResult = GameOver::Result::Get(); // Check if the game is over at the beginning of each human-controlled player's turn fheroes2::GameMode res = gameResult.checkGameOver(); const VecCastles & myCastles = myKingdom.GetCastles(); if ( res == fheroes2::GameMode::CANCEL && myCastles.empty() ) { ShowWarningLostTownsDialog(); } int fastScrollRepeatCount = 0; const int fastScrollStartThreshold = 2; bool isHeroMoving = false; bool stopHero = false; int heroAnimationFrameCount = 0; fheroes2::Point heroAnimationOffset; int heroAnimationSpriteId = 0; const std::vector delayTypes = { Game::CURRENT_HERO_DELAY, Game::MAPS_DELAY }; LocalEvent & le = LocalEvent::Get(); Cursor & cursor = Cursor::Get(); // Resets the cursor to a regular pointer and instructs the game area to update the cursor at the first opportunity const auto resetCursor = [this, &cursor]() { cursor.SetThemes( Cursor::POINTER ); _gameArea.SetUpdateCursor(); }; // Resets the cursor to a regular pointer and instructs the game area to update the cursor at the first opportunity, // but only if the game area does not need to be scrolled const auto resetCursorIfNoNeedToScroll = [this, &resetCursor]() { if ( _gameArea.NeedScroll() ) { return; } resetCursor(); }; while ( res == fheroes2::GameMode::CANCEL ) { if ( !le.HandleEvents( Game::isDelayNeeded( delayTypes ), true ) ) { if ( EventExit() == fheroes2::GameMode::QUIT_GAME ) { res = fheroes2::GameMode::QUIT_GAME; break; } continue; } #if defined( WITH_DEBUG ) { const Player * player = Players::Get( myKingdom.GetColor() ); assert( player != nullptr ); // Control has just been transferred to AI, end the turn immediately if ( player->isAIAutoControlMode() ) { return fheroes2::GameMode::END_TURN; } } #endif // Pending timer events _statusPanel.TimerEventProcessing(); if ( isHeroMoving ) { // Hero is moving, set the appropriate cursor cursor.SetThemes( Cursor::WAIT ); // If the hero is currently moving, pressing any key or mouse button should stop him. No other actions are possible at this time. if ( le.isAnyKeyPressed() || le.MouseClickLeft() || le.isMouseRightButtonPressed() ) { stopHero = true; } } else { // Hotkeys if ( le.isAnyKeyPressed() ) { // Adventure map control if ( HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_QUIT ) || HotKeyPressEvent( Game::HotKeyEvent::DEFAULT_CANCEL ) ) { res = EventExit(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_END_TURN ) ) { res = EventEndTurn(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_NEXT_HERO ) ) { EventNextHero(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_NEXT_TOWN ) ) { EventNextTown(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_NEW_GAME ) ) { res = EventNewGame(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SAVE_GAME ) ) { EventSaveGame(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::MAIN_MENU_LOAD_GAME ) ) { res = EventLoadGame(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_FILE_OPTIONS ) ) { res = EventFileDialog(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_ADVENTURE_OPTIONS ) ) { res = EventAdventureDialog(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SYSTEM_OPTIONS ) ) { EventSystemDialog(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_PUZZLE_MAP ) ) { EventPuzzleMaps(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCENARIO_INFORMATION ) ) { res = EventScenarioInformation(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_CAST_SPELL ) ) { EventCastSpell(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_KINGDOM_SUMMARY ) ) { EventKingdomInfo(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_VIEW_WORLD ) ) { EventViewWorld(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_TOGGLE_CONTROL_PANEL ) ) { EventSwitchShowControlPanel(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_TOGGLE_RADAR ) ) { EventSwitchShowRadar(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_TOGGLE_BUTTONS ) ) { EventSwitchShowButtons(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_TOGGLE_STATUS ) ) { EventSwitchShowStatus(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_TOGGLE_ICONS ) ) { EventSwitchShowIcons(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_START_HERO_MOVEMENT ) ) { res = EventHeroMovement(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_DIG_ARTIFACT ) ) { res = EventDigArtifact(); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SLEEP_HERO ) ) { EventSwitchHeroSleeping(); } // Hero movement control else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_LEFT ) ) { EventKeyArrowPress( Direction::LEFT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_RIGHT ) ) { EventKeyArrowPress( Direction::RIGHT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_UP ) ) { EventKeyArrowPress( Direction::TOP ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_DOWN ) ) { EventKeyArrowPress( Direction::BOTTOM ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_UP_LEFT ) ) { EventKeyArrowPress( Direction::TOP_LEFT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_UP_RIGHT ) ) { EventKeyArrowPress( Direction::TOP_RIGHT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_DOWN_LEFT ) ) { EventKeyArrowPress( Direction::BOTTOM_LEFT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_DOWN_RIGHT ) ) { EventKeyArrowPress( Direction::BOTTOM_RIGHT ); } // Adventure map scrolling control else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_LEFT ) ) { _gameArea.SetScroll( SCROLL_LEFT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_RIGHT ) ) { _gameArea.SetScroll( SCROLL_RIGHT ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_UP ) ) { _gameArea.SetScroll( SCROLL_TOP ); } else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_SCROLL_DOWN ) ) { _gameArea.SetScroll( SCROLL_BOTTOM ); } // Default action else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_DEFAULT_ACTION ) ) { res = EventDefaultAction(); } // Open the focused object (hero or castle) else if ( HotKeyPressEvent( Game::HotKeyEvent::WORLD_OPEN_FOCUS ) ) { EventOpenFocus(); } else if ( HotKeyHoldEvent( Game::HotKeyEvent::WORLD_QUICK_SELECT_HERO ) ) { const int32_t index = _gameArea.GetValidTileIdFromPoint( le.getMouseCursorPos() ); // This tells us that this is a hero owned by the current player and that they can meet, so we switch to the helmet cursor. if ( cursor.Themes() == Cursor::CURSOR_HERO_MEET ) { cursor.SetThemes( GetCursorTileIndex( index ) ); } if ( le.MouseClickLeft() ) { EventSwitchFocusedHero( index ); } } } if ( res != fheroes2::GameMode::CANCEL ) { break; } const bool isHiddenInterface = conf.isHideInterfaceEnabled(); // When processing events in the "no interface" mode, care should be taken about the order in which events are handled by different // UI elements, since they may overlap. The order of their rendering on the screen is as follows: the status panel is the topmost, // followed by the buttons panel, followed by the icons panel, followed by the radar, followed by the control panel, and under all // of them there is a game area. It is necessary to process events in exactly the same order in which all these UI elements overlap. // // When the mouse is captured by any UI element, events should not be handled by other UI elements. // // Mouse is captured by the status panel if ( _statusPanel.isMouseCaptured() ) { resetCursor(); _statusPanel.QueueEventProcessing(); } // Mouse is captured by the buttons panel else if ( _buttonsPanel.isMouseCaptured() ) { resetCursor(); res = _buttonsPanel.queueEventProcessing(); } // Mouse is captured by the icons panel else if ( _iconsPanel.isMouseCaptured() ) { resetCursor(); _iconsPanel.queueEventProcessing(); } // Mouse is captured by radar else if ( _radar.isMouseCaptured() ) { resetCursor(); _radar.QueueEventProcessing(); } // Mouse is captured by the game area for scrolling by dragging else if ( _gameArea.isDragScroll() ) { _gameArea.QueueEventProcessing(); } else { if ( fheroes2::cursor().isFocusActive() && conf.ScrollSpeed() != SCROLL_SPEED_NONE ) { int scrollDirection = SCROLL_NONE; if ( isScrollLeft( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_LEFT; } else if ( isScrollRight( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_RIGHT; } if ( isScrollTop( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_TOP; } else if ( isScrollBottom( le.getMouseCursorPos() ) ) { scrollDirection |= SCROLL_BOTTOM; } if ( scrollDirection != SCROLL_NONE && _gameArea.isFastScrollEnabled() ) { if ( Game::validateAnimationDelay( Game::SCROLL_START_DELAY ) && fastScrollRepeatCount < fastScrollStartThreshold ) { ++fastScrollRepeatCount; } if ( fastScrollRepeatCount >= fastScrollStartThreshold ) { _gameArea.SetScroll( scrollDirection ); } } else { fastScrollRepeatCount = 0; } } else { fastScrollRepeatCount = 0; } // Re-enable fast scrolling if the cursor movement indicates the need if ( !_gameArea.isFastScrollEnabled() && _gameArea.mouseIndicatesFastScroll( le.getMouseCursorPos() ) ) { _gameArea.setFastScrollStatus( true ); } // Cursor is over the status panel if ( ( !isHiddenInterface || conf.ShowStatus() ) && le.isMouseCursorPosInArea( _statusPanel.GetRect() ) ) { resetCursorIfNoNeedToScroll(); _statusPanel.QueueEventProcessing(); } // Cursor is over the buttons panel else if ( ( !isHiddenInterface || conf.ShowButtons() ) && le.isMouseCursorPosInArea( _buttonsPanel.GetRect() ) ) { resetCursorIfNoNeedToScroll(); res = _buttonsPanel.queueEventProcessing(); } // Cursor is over the icons panel else if ( ( !isHiddenInterface || conf.ShowIcons() ) && le.isMouseCursorPosInArea( _iconsPanel.GetRect() ) ) { resetCursorIfNoNeedToScroll(); _iconsPanel.queueEventProcessing(); } // Cursor is over the radar else if ( ( !isHiddenInterface || conf.ShowRadar() ) && le.isMouseCursorPosInArea( _radar.GetRect() ) ) { resetCursorIfNoNeedToScroll(); _radar.QueueEventProcessing(); } // Cursor is over the control panel else if ( isHiddenInterface && conf.ShowControlPanel() && le.isMouseCursorPosInArea( _controlPanel.GetArea() ) ) { resetCursorIfNoNeedToScroll(); res = _controlPanel.QueueEventProcessing(); } else if ( !_gameArea.NeedScroll() ) { // Cursor is over the game area if ( le.isMouseCursorPosInArea( _gameArea.GetROI() ) ) { _gameArea.QueueEventProcessing(); } // Cursor is somewhere else else { resetCursor(); } } } if ( res != fheroes2::GameMode::CANCEL ) { break; } } // Animation of the hero's movement if ( Game::validateAnimationDelay( Game::CURRENT_HERO_DELAY ) ) { Heroes * hero = GetFocusHeroes(); if ( hero ) { bool resetHeroSprite = false; if ( heroAnimationFrameCount > 0 ) { const int32_t heroMovementSkipValue = Game::HumanHeroAnimSpeedMultiplier(); _gameArea.ShiftCenter( { heroAnimationOffset.x * heroMovementSkipValue, heroAnimationOffset.y * heroMovementSkipValue } ); _gameArea.SetRedraw(); if ( heroAnimationOffset != fheroes2::Point() ) { Game::EnvironmentSoundMixer(); } heroAnimationFrameCount -= heroMovementSkipValue; if ( ( heroAnimationFrameCount & 0x3 ) == 0 ) { // % 4 hero->SetSpriteIndex( heroAnimationSpriteId ); if ( heroAnimationFrameCount == 0 ) { resetHeroSprite = true; } else { ++heroAnimationSpriteId; } } const int offsetStep = ( ( 4 - ( heroAnimationFrameCount & 0x3 ) ) & 0x3 ); // % 4 hero->SetOffset( { heroAnimationOffset.x * offsetStep, heroAnimationOffset.y * offsetStep } ); } if ( heroAnimationFrameCount == 0 ) { if ( resetHeroSprite ) { hero->SetSpriteIndex( heroAnimationSpriteId - 1 ); } if ( hero->isMoveEnabled() ) { if ( hero->Move( 10 == conf.HeroesMoveSpeed() ) ) { // Do not generate a frame as we are going to do it later. Interface::AdventureMap::RedrawLocker redrawLocker( Interface::AdventureMap::Get() ); _gameArea.SetCenter( hero->GetCenter() ); if ( stopHero ) { hero->SetMove( false ); stopHero = false; } } else { // Don't waste resources if there is no movement if ( const fheroes2::Point movement( hero->MovementDirection() ); movement != fheroes2::Point() ) { // Do not generate a frame as we are going to do it later. Interface::AdventureMap::RedrawLocker redrawLocker( Interface::AdventureMap::Get() ); const int32_t heroMovementSkipValue = Game::HumanHeroAnimSpeedMultiplier(); heroAnimationOffset = movement; _gameArea.ShiftCenter( movement ); heroAnimationFrameCount = 32 - heroMovementSkipValue; heroAnimationSpriteId = hero->GetSpriteIndex(); if ( heroMovementSkipValue < 4 ) { hero->SetSpriteIndex( heroAnimationSpriteId - 1 ); hero->SetOffset( { heroAnimationOffset.x * heroMovementSkipValue, heroAnimationOffset.y * heroMovementSkipValue } ); } else { ++heroAnimationSpriteId; } } _gameArea.SetRedraw(); } // Update the hero's move status. isHeroMoving = hero->isMoveEnabled(); if ( hero->isAction() ) { // The action can not be performed while moving, only after the move is ended. assert( !isHeroMoving ); // Check if the game is over after the hero's action. res = gameResult.checkGameOver(); hero->ResetAction(); } if ( !isHeroMoving ) { // Reset the 'ENABLEMOVE' state on this loop to properly update the cursor in this frame and not in the next. hero->SetMove( false ); // During the action and/or movement the adventure map and/or cursor position may have changed, so we should update the cursor image. if ( Game::isFadeInNeeded() ) { // Do not change cursor right now because fade-in is scheduled. _gameArea.SetUpdateCursor(); } else { if ( le.isMouseCursorPosInArea( _gameArea.GetROI() ) ) { // We do not use '_gameArea.SetUpdateCursor()' here because we need to update the cursor before rendering the current frame // and '_gameArea.QueueEventProcessing()' was called earlier in this loop and will only be able to update the cursor in the // next loop for the next frame. cursor.SetThemes( GetCursorTileIndex( _gameArea.GetValidTileIdFromPoint( le.getMouseCursorPos() ) ) ); } else { // When the cursor is not over the game area we use the Pointer cursor. resetCursor(); } } } } else { hero->SetMove( false ); isHeroMoving = false; stopHero = false; _gameArea.SetUpdateCursor(); } } } else { isHeroMoving = false; stopHero = false; } } // Scrolling the game area if ( !isHeroMoving ) { if ( _gameArea.NeedScroll() && Game::validateAnimationDelay( Game::SCROLL_DELAY ) ) { assert( !_gameArea.isDragScroll() ); if ( isScrollLeft( le.getMouseCursorPos() ) || isScrollRight( le.getMouseCursorPos() ) || isScrollTop( le.getMouseCursorPos() ) || isScrollBottom( le.getMouseCursorPos() ) ) { cursor.SetThemes( _gameArea.GetScrollCursor() ); } _gameArea.Scroll(); setRedraw( REDRAW_GAMEAREA | REDRAW_RADAR_CURSOR ); } else if ( _gameArea.needDragScrollRedraw() ) { setRedraw( REDRAW_GAMEAREA | REDRAW_RADAR_CURSOR ); } } // Check that the kingdom is not vanquished yet (has at least one hero or castle). if ( res == fheroes2::GameMode::CANCEL && !myKingdom.isPlay() ) { res = fheroes2::GameMode::END_TURN; } // Render map only if the turn is not over. if ( res != fheroes2::GameMode::CANCEL ) { break; } // Map objects animation if ( Game::validateAnimationDelay( Game::MAPS_DELAY ) ) { Game::updateAdventureMapAnimationIndex(); _gameArea.SetRedraw(); } if ( needRedraw() ) { redraw( 0 ); // If this assertion blows up it means that we are holding a RedrawLocker lock for rendering which should not happen. assert( getRedrawMask() == 0 ); validateFadeInAndRender(); } } if ( res == fheroes2::GameMode::END_TURN ) { if ( GetFocusHeroes() ) { GetFocusHeroes()->ShowPath( false ); setRedraw( REDRAW_GAMEAREA ); } if ( myKingdom.isPlay() ) { // These warnings should be shown at the end of the turn if ( myCastles.empty() ) { const uint32_t lostTownDays = myKingdom.GetLostTownDays(); if ( lostTownDays > Game::GetLostTownDays() ) { Game::DialogPlayers( conf.CurrentColor(), _( "Beware!" ), _( "%{color} player, you have lost your last town. If you do not conquer another town in the next week, you will be eliminated." ) ); } else if ( lostTownDays == 1 ) { Game::DialogPlayers( conf.CurrentColor(), _( "Defeat!" ), _( "%{color} player, your heroes abandon you, and you are banished from this land." ) ); } } if ( !conf.isAutoSaveAtBeginningOfTurnEnabled() ) { Game::AutoSave(); } } } return res; } void Interface::AdventureMap::mouseCursorAreaClickLeft( const int32_t tileIndex ) { Heroes * focusedHero = GetFocusHeroes(); assert( focusedHero == nullptr || !focusedHero->Modes( Heroes::ENABLEMOVE ) ); const Maps::Tile & tile = world.getTile( tileIndex ); switch ( Cursor::WithoutDistanceThemes( Cursor::Get().Themes() ) ) { case Cursor::HEROES: { Heroes * otherHero = tile.getHero(); if ( otherHero == nullptr ) { break; } if ( focusedHero == nullptr || focusedHero != otherHero ) { SetFocus( otherHero, false ); RedrawFocus(); } else { Game::OpenHeroesDialog( *otherHero, true, true ); } break; } case Cursor::CASTLE: { const MP2::MapObjectType objectType = tile.getMainObjectType(); if ( MP2::OBJ_NON_ACTION_CASTLE != objectType && MP2::OBJ_CASTLE != objectType ) { break; } Castle * otherCastle = world.getCastle( tile.GetCenter() ); if ( otherCastle == nullptr ) { break; } const Castle * focusedCastle = GetFocusCastle(); if ( focusedCastle == nullptr || focusedCastle != otherCastle ) { SetFocus( otherCastle ); RedrawFocus(); } else { Game::OpenCastleDialog( *otherCastle ); } break; } case Cursor::CURSOR_HERO_FIGHT: case Cursor::CURSOR_HERO_MOVE: case Cursor::CURSOR_HERO_BOAT: case Cursor::CURSOR_HERO_ANCHOR: case Cursor::CURSOR_HERO_MEET: case Cursor::CURSOR_HERO_ACTION: case Cursor::CURSOR_HERO_BOAT_ACTION: { if ( focusedHero == nullptr ) { break; } ShowPathOrStartMoveHero( focusedHero, tileIndex ); break; } default: break; } } void Interface::AdventureMap::mouseCursorAreaPressRight( const int32_t tileIndex ) const { #ifndef NDEBUG const Heroes * focusedHero = GetFocusHeroes(); #endif assert( focusedHero == nullptr || !focusedHero->Modes( Heroes::ENABLEMOVE ) ); const Settings & conf = Settings::Get(); const Maps::Tile & tile = world.getTile( tileIndex ); DEBUG_LOG( DBG_DEVEL, DBG_INFO, '\n' << tile.String() ) if ( !IS_DEVEL() && tile.isFog( conf.CurrentColor() ) ) { Dialog::QuickInfo( tile ); } else { switch ( tile.getMainObjectType() ) { case MP2::OBJ_NON_ACTION_CASTLE: case MP2::OBJ_CASTLE: { const Castle * castle = world.getCastle( tile.GetCenter() ); if ( castle ) { Dialog::QuickInfo( *castle ); } else { Dialog::QuickInfo( tile ); } break; } case MP2::OBJ_HERO: { const Heroes * heroes = tile.getHero(); if ( heroes ) { Dialog::QuickInfo( *heroes ); } break; } default: Dialog::QuickInfo( tile ); break; } } } void Interface::AdventureMap::mouseCursorAreaLongPressLeft( const int32_t tileIndex ) { EventSwitchFocusedHero( tileIndex ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_static.cpp000066400000000000000000000323761476115357100224010ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2011 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_static.h" #include #include "heroes.h" #include "mp2.h" #include "race.h" #include "skill.h" #include "skill_static.h" namespace { const std::array factionProperties = { { { "knight", { 1, 1, 1, 1 }, { 2, 2, 1, 1 }, 0, { 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 10, { 35, 45, 10, 10 }, { 25, 25, 25, 25 }, { 2, 4, 3, 1, 3, 5, 3, 1, 1, 2, 0, 3, 2, 2 } }, { "barbarian", { 1, 1, 1, 1 }, { 3, 1, 1, 1 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, 10, { 55, 35, 5, 5 }, { 30, 30, 20, 20 }, { 3, 3, 2, 1, 2, 3, 3, 2, 1, 3, 0, 4, 4, 1 } }, { "sorceress", { 0, 0, 2, 2 }, { 0, 0, 2, 3 }, 15, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1 }, 10, { 10, 10, 30, 50 }, { 20, 20, 30, 30 }, { 3, 3, 2, 2, 2, 1, 2, 3, 3, 4, 0, 2, 1, 4 } }, { "warlock", { 0, 0, 2, 2 }, { 0, 0, 3, 2 }, 19, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1 }, 10, { 10, 10, 50, 30 }, { 20, 20, 30, 30 }, { 1, 3, 2, 3, 2, 1, 2, 1, 3, 2, 1, 2, 4, 5 } }, { "wizard", { 0, 0, 2, 2 }, { 0, 1, 2, 2 }, 17, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }, 10, { 10, 10, 40, 40 }, { 20, 20, 30, 30 }, { 1, 3, 2, 3, 2, 2, 2, 2, 4, 2, 0, 2, 2, 5 } }, { "necromancer", { 0, 0, 2, 2 }, { 1, 0, 2, 2 }, 10, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1 }, 10, { 15, 15, 35, 35 }, { 25, 25, 25, 25 }, { 1, 3, 2, 3, 2, 0, 2, 1, 3, 2, 5, 3, 1, 4 } }, { nullptr, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 10, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } } }; const std::array secondarySkillValuesPerLevel = { { { "pathfinding", { 25, 50, 100 } }, { "archery", { 10, 25, 50 } }, { "logistics", { 10, 20, 30 } }, { "scouting", { 1, 2, 3 } }, { "diplomacy", { 25, 50, 100 } }, { "navigation", { 33, 66, 100 } }, { "leadership", { 1, 2, 3 } }, { "wisdom", { 3, 4, 5 } }, { "mysticism", { 1, 2, 3 } }, { "luck", { 1, 2, 3 } }, { "ballistics", { 0, 0, 0 } }, { "eagleeye", { 20, 30, 40 } }, { "necromancy", { 10, 20, 30 } }, { "estates", { 100, 250, 500 } }, { nullptr, { 0, 0, 0 } }, } }; } uint32_t GameStatic::GetLostOnWhirlpoolPercent() { return 50; } uint32_t GameStatic::getFogDiscoveryDistance( const FogDiscoveryType type ) { switch ( type ) { case FogDiscoveryType::CASTLE: return 5; case FogDiscoveryType::HEROES: return 4; case FogDiscoveryType::OBSERVATION_TOWER: return 20; case FogDiscoveryType::MAGI_EYES: return 9; default: break; } return 0; } uint32_t GameStatic::GetGameOverLostDays() { return 7; } uint32_t GameStatic::GetHeroesRestoreSpellPointsPerDay() { return 1; } uint32_t GameStatic::GetKingdomMaxHeroes() { return 8; } uint32_t GameStatic::GetCastleGrownWell() { return 2; } uint32_t GameStatic::GetCastleGrownWel2() { return 8; } uint32_t GameStatic::GetCastleGrownWeekOf() { return 5; } uint32_t GameStatic::GetCastleGrownMonthOf() { return 100; } int32_t GameStatic::ObjectVisitedModifiers( const MP2::MapObjectType objectType ) { switch ( objectType ) { case MP2::OBJ_BUOY: case MP2::OBJ_OASIS: case MP2::OBJ_WATERING_HOLE: case MP2::OBJ_MERMAID: case MP2::OBJ_FAERIE_RING: case MP2::OBJ_FOUNTAIN: case MP2::OBJ_IDOL: return 1; case MP2::OBJ_TEMPLE: return 2; case MP2::OBJ_GRAVEYARD: case MP2::OBJ_DERELICT_SHIP: case MP2::OBJ_SHIPWRECK: return -1; case MP2::OBJ_PYRAMID: return -2; default: break; } return 0; } const Skill::FactionProperties * GameStatic::GetFactionProperties( const int race ) { switch ( race ) { case Race::KNGT: return &factionProperties[0]; case Race::BARB: return &factionProperties[1]; case Race::SORC: return &factionProperties[2]; case Race::WRLK: return &factionProperties[3]; case Race::WZRD: return &factionProperties[4]; case Race::NECR: return &factionProperties[5]; default: break; } return nullptr; } const Skill::SecondarySkillValuesPerLevel * GameStatic::GetSecondarySkillValuesPerLevel( const int skill ) { switch ( skill ) { case Skill::Secondary::PATHFINDING: return &secondarySkillValuesPerLevel[0]; case Skill::Secondary::ARCHERY: return &secondarySkillValuesPerLevel[1]; case Skill::Secondary::LOGISTICS: return &secondarySkillValuesPerLevel[2]; case Skill::Secondary::SCOUTING: return &secondarySkillValuesPerLevel[3]; case Skill::Secondary::DIPLOMACY: return &secondarySkillValuesPerLevel[4]; case Skill::Secondary::NAVIGATION: return &secondarySkillValuesPerLevel[5]; case Skill::Secondary::LEADERSHIP: return &secondarySkillValuesPerLevel[6]; case Skill::Secondary::WISDOM: return &secondarySkillValuesPerLevel[7]; case Skill::Secondary::MYSTICISM: return &secondarySkillValuesPerLevel[8]; case Skill::Secondary::LUCK: return &secondarySkillValuesPerLevel[9]; case Skill::Secondary::BALLISTICS: return &secondarySkillValuesPerLevel[10]; case Skill::Secondary::EAGLE_EYE: return &secondarySkillValuesPerLevel[11]; case Skill::Secondary::NECROMANCY: return &secondarySkillValuesPerLevel[12]; case Skill::Secondary::ESTATES: return &secondarySkillValuesPerLevel[13]; default: break; } return nullptr; } const std::vector & GameStatic::getSecondarySkillsForWitchsHut() { // Every skill except Leadership and Necromancy. static const std::vector skills{ Skill::Secondary::PATHFINDING, Skill::Secondary::ARCHERY, Skill::Secondary::LOGISTICS, Skill::Secondary::SCOUTING, Skill::Secondary::DIPLOMACY, Skill::Secondary::NAVIGATION, Skill::Secondary::WISDOM, Skill::Secondary::MYSTICISM, Skill::Secondary::LUCK, Skill::Secondary::BALLISTICS, Skill::Secondary::EAGLE_EYE, Skill::Secondary::ESTATES }; return skills; } int GameStatic::GetBattleMoatReduceDefense() { return 3; } uint32_t GameStatic::getCastleWallRangedPenalty() { return 50; } uint32_t GameStatic::getMovementPointBonus( const MP2::MapObjectType objectType ) { switch ( objectType ) { case MP2::OBJ_OASIS: return 800; case MP2::OBJ_STABLES: case MP2::OBJ_WATERING_HOLE: return 400; default: break; } return 0; } bool GameStatic::isHeroWorthyToVisitXanadu( const Heroes & hero ) { const uint32_t heroLevel = hero.GetLevel(); if ( heroLevel > 9 ) { return true; } const uint32_t diplomacyLevel = hero.GetLevelSkill( Skill::Secondary::DIPLOMACY ); return ( diplomacyLevel == Skill::Level::BASIC && heroLevel > 7 ) || ( diplomacyLevel == Skill::Level::ADVANCED && heroLevel > 5 ) || ( diplomacyLevel == Skill::Level::EXPERT && heroLevel > 3 ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_static.h000066400000000000000000000060401476115357100220330ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2011 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include namespace MP2 { enum MapObjectType : uint16_t; } namespace Skill { struct FactionProperties; struct SecondarySkillValuesPerLevel; } class Heroes; namespace GameStatic { enum class FogDiscoveryType : int32_t { CASTLE, HEROES, OBSERVATION_TOWER, MAGI_EYES }; uint32_t GetLostOnWhirlpoolPercent(); uint32_t GetGameOverLostDays(); uint32_t getFogDiscoveryDistance( const FogDiscoveryType type ); uint32_t GetKingdomMaxHeroes(); uint32_t GetCastleGrownWell(); uint32_t GetCastleGrownWel2(); uint32_t GetCastleGrownWeekOf(); uint32_t GetCastleGrownMonthOf(); uint32_t GetHeroesRestoreSpellPointsPerDay(); int32_t ObjectVisitedModifiers( const MP2::MapObjectType objectType ); int GetBattleMoatReduceDefense(); // Returns the percentage penalty for the damage dealt by shooters firing at targets protected by castle walls. uint32_t getCastleWallRangedPenalty(); const Skill::FactionProperties * GetFactionProperties( const int race ); const Skill::SecondarySkillValuesPerLevel * GetSecondarySkillValuesPerLevel( const int skill ); const std::vector & getSecondarySkillsForWitchsHut(); uint32_t getMovementPointBonus( const MP2::MapObjectType objectType ); bool isHeroWorthyToVisitXanadu( const Heroes & hero ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_string.cpp000066400000000000000000000034161476115357100224110ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_string.h" #include "serialize.h" OStreamBase & operator<<( OStreamBase & stream, const fheroes2::LocalizedString & string ) { return stream << string.text << string.language; } IStreamBase & operator>>( IStreamBase & stream, fheroes2::LocalizedString & string ) { return stream >> string.text >> string.language; } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_string.h000066400000000000000000000036261476115357100220610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include class IStreamBase; class OStreamBase; namespace fheroes2 { enum class SupportedLanguage : uint8_t; struct LocalizedString { std::string text; std::optional language; }; } OStreamBase & operator<<( OStreamBase & stream, const fheroes2::LocalizedString & string ); IStreamBase & operator>>( IStreamBase & stream, fheroes2::LocalizedString & string ); fheroes2-1.1.6+dfsg/src/fheroes2/game/game_video.cpp000066400000000000000000000241531476115357100222120ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "game_video.h" #include #include #include #include #include #include #include #include "audio.h" #include "cursor.h" #include "dir.h" #include "game_delays.h" #include "game_video_type.h" #include "localevent.h" #include "logging.h" #include "screen.h" #include "settings.h" #include "smk_decoder.h" #include "system.h" #include "ui_text.h" #include "ui_tool.h" namespace { // Anim2 directory is used in Russian Buka version of the game. std::array videoDir = { "anim", "anim2", System::concatPath( "heroes2", "anim" ), "data" }; void playAudio( const std::vector> & audioChannels ) { for ( const std::vector & audio : audioChannels ) { if ( !audio.empty() ) { Mixer::Play( audio.data(), static_cast( audio.size() ), false ); } } } } namespace Video { bool getVideoFilePath( const std::string & fileName, std::string & path ) { for ( const std::string & rootDir : Settings::GetRootDirs() ) { for ( size_t dirIdx = 0; dirIdx < videoDir.size(); ++dirIdx ) { const std::string fullDirPath = System::concatPath( rootDir, videoDir[dirIdx] ); if ( System::IsDirectory( fullDirPath ) ) { ListFiles videoFiles; videoFiles.FindFileInDir( fullDirPath, fileName ); if ( videoFiles.empty() ) { continue; } std::swap( videoFiles.front(), path ); if ( dirIdx > 0 ) { // Put the current directory at the first place to increase cache hit chance. std::swap( videoDir[0], videoDir[dirIdx] ); } return true; } } } return false; } bool ShowVideo( const std::string & fileName, const VideoAction action, const std::vector & subtitles /* = {} */, const bool fadeColorsOnEnd /* = false */ ) { // Stop any cycling animation. const fheroes2::ScreenPaletteRestorer screenRestorer; std::string videoPath; if ( !getVideoFilePath( fileName, videoPath ) ) { // File doesn't exist, so no need to even try to load it. DEBUG_LOG( DBG_GAME, DBG_INFO, fileName << " video file does not exist." ) return false; } SMKVideoSequence video( videoPath ); const uint32_t frameCount = video.frameCount(); if ( frameCount < 1 ) { // Nothing to show. return false; } const std::vector> & audioChannels = video.getAudioChannels(); const bool hasAudio = Audio::isValid() && !audioChannels.empty(); if ( action == VideoAction::IGNORE_VIDEO ) { // Since no video is rendered play audio if available. if ( hasAudio ) { playAudio( audioChannels ); } return true; } const bool isLooped = ( action == VideoAction::LOOP_VIDEO || action == VideoAction::PLAY_TILL_AUDIO_END ); // Hide mouse cursor. const CursorRestorer cursorRestorer( false ); fheroes2::Display & display = fheroes2::Display::instance(); display.fill( 0 ); display.updateNextRenderRoi( { 0, 0, display.width(), display.height() } ); uint32_t currentFrame = 0; fheroes2::Rect frameRoi( ( display.width() - video.width() ) / 2, ( display.height() - video.height() ) / 2, 0, 0 ); const uint32_t delay = static_cast( 1000.0 / video.fps() + 0.5 ); // This might be not very accurate but it's the best we can have now std::vector palette; std::vector prevPalette; // Prepare the first frame. video.resetFrame(); video.getNextFrame( display, frameRoi.x, frameRoi.y, frameRoi.width, frameRoi.height, prevPalette ); screenRestorer.changePalette( prevPalette.data() ); // Render subtitles on the first frame for ( const Subtitle & subtitle : subtitles ) { if ( subtitle.needRender( 0 ) ) { subtitle.render( display, frameRoi ); } } LocalEvent & le = LocalEvent::Get(); Game::passCustomAnimationDelay( delay ); // Make sure that the first run is passed immediately. assert( !Game::isCustomDelayNeeded( delay ) ); // Play audio just before rendering the frame. This is important to minimize synchronization issues between audio and video. if ( hasAudio ) { playAudio( audioChannels ); } while ( le.HandleEvents( Game::isCustomDelayNeeded( delay ) ) ) { if ( ( action == VideoAction::PLAY_TILL_AUDIO_END ) && !Mixer::isPlaying( -1 ) ) { break; } if ( le.isAnyKeyPressed() || le.MouseClickLeft() || le.MouseClickMiddle() || le.MouseClickRight() ) { Mixer::Stop(); break; } if ( Game::validateCustomAnimationDelay( delay ) ) { if ( currentFrame < frameCount ) { // Render the prepared frame. display.render( frameRoi ); ++currentFrame; if ( ( currentFrame == frameCount ) && isLooped ) { currentFrame = 0; video.resetFrame(); if ( hasAudio ) { playAudio( audioChannels ); } } // Prepare the next frame for render. video.getNextFrame( display, frameRoi.x, frameRoi.y, frameRoi.width, frameRoi.height, palette ); if ( prevPalette != palette ) { screenRestorer.changePalette( palette.data() ); std::swap( prevPalette, palette ); } // Render subtitles on the prepared next frame for ( const Subtitle & subtitle : subtitles ) { if ( subtitle.needRender( currentFrame * delay ) ) { subtitle.render( display, frameRoi ); } } } else if ( action != VideoAction::WAIT_FOR_USER_INPUT ) { break; } } } if ( fadeColorsOnEnd ) { // Do color fade for 1 second with 15 FPS. fheroes2::colorFade( palette, frameRoi, 1000, 15.0 ); } else { display.fill( 0 ); } display.updateNextRenderRoi( { 0, 0, display.width(), display.height() } ); return true; } Subtitle::Subtitle( const fheroes2::TextBase & subtitleText, const uint32_t startTimeMS, const uint32_t durationMS, const fheroes2::Point & position /* = { -1, -1 } */, const int32_t maxWidth /* = fheroes2::Display::DEFAULT_WIDTH */ ) : _position( position ) , _startTimeMS( startTimeMS ) { assert( maxWidth > 0 ); const int32_t textWidth = subtitleText.width( maxWidth ); // We add extra 1 to have space for contour. _subtitleImage.resize( textWidth + 1, subtitleText.height( textWidth ) + 1 ); // Draw text and remove all shadow data if it could not be properly applied to video palette. // We use the black color with id = 36 so no shadow will be applied to it. const uint8_t blackColor = 36; _subtitleImage.fill( blackColor ); // At the left and bottom there is space for contour left by original font shadows, we leave 1 extra pixel from the right and top. subtitleText.draw( 0, 1, textWidth, _subtitleImage ); fheroes2::ReplaceColorIdByTransformId( _subtitleImage, blackColor, 1 ); // Add black contour to the text. fheroes2::Blit( fheroes2::CreateContour( _subtitleImage, blackColor ), _subtitleImage ); // This is made to avoid overflow when calculating the end frame. _endTimeMS = _startTimeMS + std::min( durationMS, UINT32_MAX - _startTimeMS ); // If position has negative value: position subtitles at the bottom center by using default screen size (it is currently equal to video size). if ( ( _position.x < 0 ) || ( _position.y < 0 ) ) { _position.x = ( fheroes2::Display::DEFAULT_WIDTH - _subtitleImage.width() ) / 2; _position.y = fheroes2::Display::DEFAULT_HEIGHT - _subtitleImage.height(); } else { _position.x -= _subtitleImage.width() / 2; } } } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_video.h000066400000000000000000000063221476115357100216550ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "image.h" #include "math_base.h" #include "screen.h" namespace fheroes2 { class TextBase; } namespace Video { enum class VideoAction : int; class Subtitle { public: // Generate the image from subtitles text and store it in Subtitle class. // The 'position' represents the top-center of subtitles image. All subtitles are center aligned. Subtitle( const fheroes2::TextBase & subtitleText, const uint32_t startTimeMS, const uint32_t durationMS, const fheroes2::Point & position = { -1, -1 }, const int32_t maxWidth = fheroes2::Display::DEFAULT_WIDTH ); // Check if subtitles need to be rendered at the current time (in milliseconds). bool needRender( const uint32_t currentTimeMS ) const { return ( ( currentTimeMS >= _startTimeMS ) && ( currentTimeMS < _endTimeMS ) ); } // Render subtitles image to the output image. void render( fheroes2::Image & output, const fheroes2::Rect & frameRoi ) const { fheroes2::Blit( _subtitleImage, 0, 0, output, frameRoi.x + _position.x, frameRoi.y + _position.y, _subtitleImage.width(), _subtitleImage.height() ); } private: fheroes2::Point _position{ -1, -1 }; fheroes2::Image _subtitleImage; const uint32_t _startTimeMS{ 0 }; uint32_t _endTimeMS{ 0 }; }; // Returns true if the file exists. bool getVideoFilePath( const std::string & fileName, std::string & path ); // Returns false if the video is not present or it is corrupted. bool ShowVideo( const std::string & fileName, const VideoAction action, const std::vector & subtitles = {}, const bool fadeColorsOnEnd = false ); } fheroes2-1.1.6+dfsg/src/fheroes2/game/game_video_type.h000066400000000000000000000032111476115357100227100ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace Video { enum class VideoAction : int { PLAY_TILL_VIDEO_END, LOOP_VIDEO, WAIT_FOR_USER_INPUT, PLAY_TILL_AUDIO_END, IGNORE_VIDEO }; } fheroes2-1.1.6+dfsg/src/fheroes2/game/highscores.cpp000066400000000000000000000413351476115357100222520ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "highscores.h" #include #include #include #include #include #include "campaign_scenariodata.h" #include "game_language.h" #include "serialize.h" #include "translations.h" #include "ui_language.h" #include "zzlib.h" namespace { const uint32_t highscoreFileMagicValueV1 = 0xBADC0DE; const uint32_t highscoreFileMagicValueV2 = 0xBADC1DE; const size_t highscoreMaximumEntries = 10; const std::array monstersInRanking = { Monster::PEASANT, Monster::GOBLIN, Monster::SPRITE, Monster::HALFLING, Monster::CENTAUR, Monster::ROGUE, Monster::SKELETON, Monster::ORC, Monster::ZOMBIE, Monster::ARCHER, Monster::RANGER, Monster::BOAR, Monster::DWARF, Monster::MUTANT_ZOMBIE, Monster::ORC_CHIEF, Monster::ELF, Monster::GARGOYLE, Monster::PIKEMAN, Monster::GRAND_ELF, Monster::BATTLE_DWARF, Monster::NOMAD, Monster::VETERAN_PIKEMAN, Monster::WOLF, Monster::MUMMY, Monster::IRON_GOLEM, Monster::ROYAL_MUMMY, Monster::OGRE, Monster::GRIFFIN, Monster::SWORDSMAN, Monster::DRUID, Monster::STEEL_GOLEM, Monster::MASTER_SWORDSMAN, Monster::AIR_ELEMENT, Monster::GREATER_DRUID, Monster::FIRE_ELEMENT, Monster::GHOST, Monster::VAMPIRE, Monster::WATER_ELEMENT, Monster::EARTH_ELEMENT, Monster::ROC, Monster::MINOTAUR, Monster::CAVALRY, Monster::TROLL, Monster::MAGE, Monster::MEDUSA, Monster::LICH, Monster::OGRE_LORD, Monster::MINOTAUR_KING, Monster::CHAMPION, Monster::WAR_TROLL, Monster::VAMPIRE_LORD, Monster::ARCHMAGE, Monster::POWER_LICH, Monster::UNICORN, Monster::HYDRA, Monster::PALADIN, Monster::GENIE, Monster::CRUSADER, Monster::CYCLOPS, Monster::GIANT, Monster::PHOENIX, Monster::BONE_DRAGON, Monster::GREEN_DRAGON, Monster::RED_DRAGON, Monster::TITAN, Monster::BLACK_DRAGON }; int32_t saveHighscoreEntry( fheroes2::HighscoreData && data, std::vector & entries, const bool isCampaign ) { auto iter = std::find( entries.begin(), entries.end(), data ); if ( iter != entries.end() ) { // This is the same game completion. Just replace the entry. *iter = std::move( data ); return static_cast( iter - entries.begin() ); } entries.emplace_back( data ); std::sort( entries.begin(), entries.end(), [isCampaign]( const fheroes2::HighscoreData & first, const fheroes2::HighscoreData & second ) { if ( isCampaign ) { return first.rating < second.rating; } return first.rating > second.rating; } ); if ( entries.size() > highscoreMaximumEntries ) { entries.resize( highscoreMaximumEntries ); } iter = std::find( entries.begin(), entries.end(), data ); if ( iter != entries.end() ) { return static_cast( iter - entries.begin() ); } return -1; } } namespace fheroes2 { uint32_t HighscoreData::generateCompletionTime() { return static_cast( std::time( nullptr ) ); } void HighscoreData::loadV1( IStreamBase & stream ) { languageAbbreviation = fheroes2::getLanguageAbbreviation( fheroes2::SupportedLanguage::English ); stream >> playerName >> scenarioName >> completionTime >> dayCount >> rating >> mapSeed; } OStreamBase & operator<<( OStreamBase & stream, const HighscoreData & data ) { return stream << data.languageAbbreviation << data.playerName << data.scenarioName << data.completionTime << data.dayCount << data.rating << data.mapSeed; } IStreamBase & operator>>( IStreamBase & stream, HighscoreData & data ) { return stream >> data.languageAbbreviation >> data.playerName >> data.scenarioName >> data.completionTime >> data.dayCount >> data.rating >> data.mapSeed; } bool HighScoreDataContainer::load( const std::string & fileName ) { StreamFile fileStream; fileStream.setBigendian( true ); if ( !fileStream.open( fileName, "rb" ) ) { return false; } RWStreamBuf hdata; hdata.setBigendian( true ); if ( !Compression::unzipStream( fileStream, hdata ) ) { return false; } uint32_t magicValue = 0; hdata >> magicValue; if ( magicValue != highscoreFileMagicValueV1 && magicValue != highscoreFileMagicValueV2 ) { // It is not a highscore file. return false; } if ( magicValue == highscoreFileMagicValueV1 ) { uint32_t size = hdata.get32(); _highScoresStandard.resize( size ); for ( HighscoreData & data : _highScoresStandard ) { data.loadV1( hdata ); } size = hdata.get32(); _highScoresCampaign.resize( size ); for ( HighscoreData & data : _highScoresCampaign ) { data.loadV1( hdata ); } } else { hdata >> _highScoresStandard >> _highScoresCampaign; } if ( hdata.fail() ) { return false; } // Since the introduction of campaign difficulty we need to calculate rating of a campaign completion. // Before the change rating for campaigns was always 0. We need to set it to the number of days. for ( fheroes2::HighscoreData & data : _highScoresCampaign ) { if ( data.rating == 0 ) { data.rating = data.dayCount; } } if ( _highScoresStandard.size() < highscoreMaximumEntries ) { populateStandardDefaultHighScores(); } else if ( _highScoresStandard.size() > highscoreMaximumEntries ) { _highScoresStandard.resize( highscoreMaximumEntries ); } if ( _highScoresCampaign.size() < highscoreMaximumEntries ) { populateCampaignDefaultHighScores(); } else if ( _highScoresCampaign.size() > highscoreMaximumEntries ) { _highScoresCampaign.resize( highscoreMaximumEntries ); } return true; } bool HighScoreDataContainer::save( const std::string & fileName ) const { StreamFile fileStream; fileStream.setBigendian( true ); if ( !fileStream.open( fileName, "wb" ) ) { return false; } RWStreamBuf hdata; hdata.setBigendian( true ); hdata << highscoreFileMagicValueV2 << _highScoresStandard << _highScoresCampaign; return !hdata.fail() && Compression::zipStreamBuf( hdata, fileStream ); } int32_t HighScoreDataContainer::registerScoreStandard( HighscoreData && data ) { return saveHighscoreEntry( std::move( data ), _highScoresStandard, false ); } int32_t HighScoreDataContainer::registerScoreCampaign( HighscoreData && data ) { return saveHighscoreEntry( std::move( data ), _highScoresCampaign, true ); } Monster HighScoreDataContainer::getMonsterByRating( const size_t rating ) { static const std::vector> ratingForMonster = []() { std::vector> result; uint32_t threshold = 0; uint32_t step = 0; for ( const Monster::MonsterType monster : monstersInRanking ) { // 0 to 3 if ( monster == Monster::PEASANT ) { step = 3; } // 4 to 131 else if ( monster == Monster::GOBLIN ) { step = 4; } // 132 to 227 else if ( monster == Monster::GREATER_DRUID ) { step = 3; } // >= 228 else if ( monster == Monster::BLACK_DRAGON ) { step = 1; } threshold += step; result.emplace_back( threshold, monster ); } return result; }(); { assert( !ratingForMonster.empty() ); const auto & [threshold, monster] = ratingForMonster.back(); if ( rating >= threshold ) { return { monster }; } } for ( const auto & [threshold, monster] : ratingForMonster ) { if ( rating <= threshold ) { return { monster }; } } assert( 0 ); return { Monster::PEASANT }; } Monster HighScoreDataContainer::getMonsterByDay( const size_t numOfDays ) { static const std::vector> numOfDaysForMonster = []() { std::vector> result; uint32_t threshold = 0; uint32_t step = 0; for ( auto iter = monstersInRanking.crbegin(); iter != monstersInRanking.crend(); ++iter ) { const Monster::MonsterType monster = *iter; // 0 to 300 if ( monster == Monster::BLACK_DRAGON ) { step = 300; } // 301 to 1000 else if ( monster == Monster::TITAN ) { step = 20; } // 1001 to 2000 else if ( monster == Monster::DRUID ) { step = 100; } // 2001 to 5800 else if ( monster == Monster::BATTLE_DWARF ) { step = 200; } // >= 5801 else if ( monster == Monster::PEASANT ) { step = 1; } threshold += step; result.emplace_back( threshold, monster ); } return result; }(); { assert( !numOfDaysForMonster.empty() ); const auto & [threshold, monster] = numOfDaysForMonster.back(); if ( numOfDays >= threshold ) { return { monster }; } } for ( const auto & [threshold, monster] : numOfDaysForMonster ) { if ( numOfDays <= threshold ) { return { monster }; } } assert( 0 ); return { Monster::PEASANT }; } void HighScoreDataContainer::populateStandardDefaultHighScores() { const uint32_t currentTime = HighscoreData::generateCompletionTime(); const std::string lang = fheroes2::getLanguageAbbreviation( fheroes2::getCurrentLanguage() ); registerScoreStandard( { lang, _( "Lord Kilburn" ), "Beltway", currentTime, 70, 150, 0 } ); registerScoreStandard( { lang, _( "Tsabu" ), "Deathgate", currentTime, 80, 140, 0 } ); registerScoreStandard( { lang, _( "Sir Galant" ), "Enroth", currentTime, 90, 130, 0 } ); registerScoreStandard( { lang, _( "Thundax" ), "Lost Continent", currentTime, 100, 120, 0 } ); registerScoreStandard( { lang, _( "Lord Haart" ), "Mountain King", currentTime, 120, 110, 0 } ); registerScoreStandard( { lang, _( "Ariel" ), "Pandemonium", currentTime, 140, 100, 0 } ); registerScoreStandard( { lang, _( "Rebecca" ), "Terra Firma", currentTime, 160, 90, 0 } ); registerScoreStandard( { lang, _( "Sandro" ), "The Clearing", currentTime, 180, 80, 0 } ); registerScoreStandard( { lang, _( "Crodo" ), "Vikings!", currentTime, 200, 70, 0 } ); registerScoreStandard( { lang, _( "Barock" ), "Wastelands", currentTime, 240, 60, 0 } ); } void HighScoreDataContainer::populateCampaignDefaultHighScores() { const uint32_t currentTime = HighscoreData::generateCompletionTime(); const std::string lang = fheroes2::getLanguageAbbreviation( fheroes2::getCurrentLanguage() ); registerScoreCampaign( { lang, _( "Antoine" ), Campaign::getCampaignName( Campaign::ROLAND_CAMPAIGN ), currentTime, 600, 600, 0 } ); registerScoreCampaign( { lang, _( "Astra" ), Campaign::getCampaignName( Campaign::ARCHIBALD_CAMPAIGN ), currentTime, 650, 650, 0 } ); registerScoreCampaign( { lang, _( "Agar" ), Campaign::getCampaignName( Campaign::ROLAND_CAMPAIGN ), currentTime, 700, 700, 0 } ); registerScoreCampaign( { lang, _( "Vatawna" ), Campaign::getCampaignName( Campaign::ARCHIBALD_CAMPAIGN ), currentTime, 750, 750, 0 } ); registerScoreCampaign( { lang, _( "Vesper" ), Campaign::getCampaignName( Campaign::ROLAND_CAMPAIGN ), currentTime, 800, 800, 0 } ); registerScoreCampaign( { lang, _( "Ambrose" ), Campaign::getCampaignName( Campaign::ARCHIBALD_CAMPAIGN ), currentTime, 850, 850, 0 } ); registerScoreCampaign( { lang, _( "Troyan" ), Campaign::getCampaignName( Campaign::ROLAND_CAMPAIGN ), currentTime, 900, 900, 0 } ); registerScoreCampaign( { lang, _( "Jojosh" ), Campaign::getCampaignName( Campaign::ARCHIBALD_CAMPAIGN ), currentTime, 1000, 1000, 0 } ); registerScoreCampaign( { lang, _( "Wrathmont" ), Campaign::getCampaignName( Campaign::ROLAND_CAMPAIGN ), currentTime, 2000, 2000, 0 } ); registerScoreCampaign( { lang, _( "Maximus" ), Campaign::getCampaignName( Campaign::ARCHIBALD_CAMPAIGN ), currentTime, 3000, 3000, 0 } ); } } fheroes2-1.1.6+dfsg/src/fheroes2/game/highscores.h000066400000000000000000000114121476115357100217100ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2022 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "monster.h" class IStreamBase; class OStreamBase; namespace fheroes2 { struct HighscoreData { public: HighscoreData() = default; HighscoreData( std::string languageAbbreviation_, std::string playerName_, std::string scenarioName_, const uint32_t completionTime_, const uint32_t dayCount_, const uint32_t rating_, const uint32_t mapSeed_ ) : languageAbbreviation( std::move( languageAbbreviation_ ) ) , playerName( std::move( playerName_ ) ) , scenarioName( std::move( scenarioName_ ) ) , completionTime( completionTime_ ) , dayCount( dayCount_ ) , rating( rating_ ) , mapSeed( mapSeed_ ) { // Do nothing. } HighscoreData( const HighscoreData & ) = default; HighscoreData( HighscoreData && ) = default; ~HighscoreData() = default; HighscoreData & operator=( const HighscoreData & data ) = default; HighscoreData & operator=( HighscoreData && data ) noexcept = default; bool operator==( const HighscoreData & other ) const { // Ignore player name and completion time. return scenarioName == other.scenarioName && dayCount == other.dayCount && rating == other.rating && mapSeed == other.mapSeed; } std::string languageAbbreviation; std::string playerName; std::string scenarioName; uint32_t completionTime{ 0 }; uint32_t dayCount{ 0 }; // Rating is used only for standalone scenarios. Campaigns do not use this member. uint32_t rating{ 0 }; // Map seed is used to identify the same game completion to avoid duplicates in highscores. uint32_t mapSeed{ 0 }; static uint32_t generateCompletionTime(); void loadV1( IStreamBase & stream ); private: friend OStreamBase & operator<<( OStreamBase & stream, const HighscoreData & data ); friend IStreamBase & operator>>( IStreamBase & stream, HighscoreData & data ); }; class HighScoreDataContainer { public: bool load( const std::string & fileName ); bool save( const std::string & fileName ) const; int32_t registerScoreStandard( HighscoreData && data ); int32_t registerScoreCampaign( HighscoreData && data ); void populateStandardDefaultHighScores(); void populateCampaignDefaultHighScores(); const std::vector & getHighScoresStandard() const { return _highScoresStandard; } const std::vector & getHighScoresCampaign() const { return _highScoresCampaign; } static Monster getMonsterByRating( const size_t rating ); static Monster getMonsterByDay( const size_t numOfDays ); void clear() { _highScoresStandard.clear(); _highScoresCampaign.clear(); } private: std::vector _highScoresStandard; std::vector _highScoresCampaign; }; OStreamBase & operator<<( OStreamBase & stream, const HighscoreData & data ); IStreamBase & operator>>( IStreamBase & stream, HighscoreData & data ); } fheroes2-1.1.6+dfsg/src/fheroes2/gui/000077500000000000000000000000001476115357100172555ustar00rootroot00000000000000fheroes2-1.1.6+dfsg/src/fheroes2/gui/cursor.cpp000066400000000000000000000173301476115357100213020ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "cursor.h" #include "agg_image.h" #include "icn.h" #include "image.h" #include "localevent.h" Cursor & Cursor::Get() { static Cursor _cursor; return _cursor; } void Cursor::SetThemes( const int theme, const bool force /* = false */ ) { if ( _theme == theme && !force ) { return; } _theme = theme; // Video pointer cannot be properly rendered in black-white so we have to force to use color cursor. int icnID = ( _monochromeCursorThemes && ( theme != Cursor::POINTER_VIDEO ) ) ? ICN::MONO_CURSOR_ADVMBW : ICN::ADVMCO; switch ( 0xF000 & theme ) { case 0x3000: icnID = _monochromeCursorThemes ? ICN::MONO_CURSOR_SPELBW : ICN::SPELCO; break; case 0x2000: icnID = _monochromeCursorThemes ? ICN::MONO_CURSOR_CMSSBW : ICN::CMSECO; break; case 0x4000: icnID = _monochromeCursorThemes ? ICN::MONO_CURSOR_ADVENTURE_MAP : ICN::COLOR_CURSOR_ADVENTURE_MAP; break; default: break; } const fheroes2::Sprite & spr = fheroes2::AGG::GetICN( icnID, 0xFF & theme ); SetOffset( theme, { ( spr.width() - spr.x() ) / 2, ( spr.height() - spr.y() ) / 2 } ); fheroes2::cursor().update( spr, -_offset.x, -_offset.y ); // Apply new offset. const fheroes2::Point & currentPos = LocalEvent::Get().getMouseCursorPos(); Move( currentPos.x, currentPos.y ); } void Cursor::setCustomImage( const fheroes2::Image & image, const fheroes2::Point & offset ) { _theme = NONE; fheroes2::cursor().update( image, -offset.x, -offset.y ); // Immediately apply new mouse offset. const fheroes2::Point & currentPos = LocalEvent::Get().getMouseCursorPos(); _offset = offset; Move( currentPos.x, currentPos.y ); } fheroes2::Rect Cursor::updateCursorPosition( const int32_t x, const int32_t y ) { if ( fheroes2::cursor().isSoftwareEmulation() ) { Cursor::Get().Move( x, y ); if ( fheroes2::cursor().isVisible() ) { return { x, y, 1, 1 }; } } return {}; } void Cursor::Move( int32_t x, int32_t y ) const { fheroes2::cursor().setPosition( x + _offset.x, y + _offset.y ); } void Cursor::SetOffset( int name, const fheroes2::Point & defaultOffset ) { switch ( name ) { case Cursor::POINTER: case Cursor::POINTER_VIDEO: case Cursor::WAR_POINTER: _offset = { 0, 0 }; break; case Cursor::CURSOR_HERO_FIGHT: case Cursor::CURSOR_HERO_FIGHT_2: case Cursor::CURSOR_HERO_FIGHT_3: case Cursor::CURSOR_HERO_FIGHT_4: case Cursor::CURSOR_HERO_FIGHT_5: case Cursor::CURSOR_HERO_FIGHT_6: case Cursor::CURSOR_HERO_FIGHT_7: case Cursor::CURSOR_HERO_FIGHT_8: _offset = { -10, -11 }; break; case Cursor::SCROLL_TOPRIGHT: case Cursor::SCROLL_RIGHT: _offset = { -15, 0 }; break; case Cursor::SCROLL_BOTTOM: case Cursor::SCROLL_BOTTOMLEFT: _offset = { 0, -15 }; break; case Cursor::SCROLL_BOTTOMRIGHT: case Cursor::SWORD_BOTTOMRIGHT: _offset = { -20, -20 }; break; case Cursor::SWORD_BOTTOMLEFT: _offset = { -5, -20 }; break; case Cursor::SWORD_TOPLEFT: _offset = { -5, -5 }; break; case Cursor::SWORD_TOPRIGHT: _offset = { -20, -5 }; break; case Cursor::SWORD_LEFT: _offset = { -5, -7 }; break; case Cursor::SWORD_RIGHT: _offset = { -25, -7 }; break; default: _offset = { -defaultOffset.x, -defaultOffset.y }; break; } } void Cursor::setVideoPlaybackCursor() { if ( fheroes2::cursor().isSoftwareEmulation() ) { SetThemes( Cursor::POINTER_VIDEO ); } } void Cursor::Refresh() { Get().SetThemes( Get().Themes(), true ); } int Cursor::DistanceThemes( const int theme, uint32_t distance ) { if ( distance == 0 ) { return POINTER; } if ( distance > 8 ) { distance = 8; } switch ( theme ) { case CURSOR_HERO_MOVE: case CURSOR_HERO_FIGHT: case CURSOR_HERO_BOAT: case CURSOR_HERO_ANCHOR: case CURSOR_HERO_MEET: case CURSOR_HERO_ACTION: case CURSOR_HERO_BOAT_ACTION: return theme + static_cast( distance ) - 1; default: break; } return theme; } int Cursor::WithoutDistanceThemes( const int theme ) { if ( theme > CURSOR_HERO_MOVE && theme <= CURSOR_HERO_MOVE_8 ) { return CURSOR_HERO_MOVE; } if ( theme > CURSOR_HERO_FIGHT && theme <= CURSOR_HERO_FIGHT_8 ) { return CURSOR_HERO_FIGHT; } if ( theme > CURSOR_HERO_BOAT && theme <= CURSOR_HERO_BOAT_8 ) { return CURSOR_HERO_BOAT; } if ( theme > CURSOR_HERO_ANCHOR && theme <= CURSOR_HERO_ANCHOR_8 ) { return CURSOR_HERO_ANCHOR; } if ( theme > CURSOR_HERO_MEET && theme <= CURSOR_HERO_MEET_8 ) { return CURSOR_HERO_MEET; } if ( theme > CURSOR_HERO_ACTION && theme <= CURSOR_HERO_ACTION_8 ) { return CURSOR_HERO_ACTION; } if ( theme > CURSOR_HERO_BOAT_ACTION && theme <= CURSOR_HERO_BOAT_ACTION_8 ) { return CURSOR_HERO_BOAT_ACTION; } return theme; } CursorRestorer::CursorRestorer( const bool visible ) { fheroes2::cursor().show( visible ); } CursorRestorer::CursorRestorer( const bool visible, const int theme ) { Cursor::Get().SetThemes( theme ); fheroes2::cursor().show( visible ); } CursorRestorer::~CursorRestorer() { fheroes2::Cursor & cursorRenderer = fheroes2::cursor(); const bool isShown = _visible && !cursorRenderer.isVisible(); cursorRenderer.show( _visible ); Cursor & cursor = Cursor::Get(); const bool noThemeChange = ( cursor.Themes() == _theme ); cursor.SetThemes( _theme ); // In case of software emulated cursor when cursor theme is not changed and it is shown after it was hidden // we force render the cursor area. It is needed to reduce the cursor show delay. if ( isShown && noThemeChange && cursorRenderer.isSoftwareEmulation() ) { const fheroes2::Point & pos = LocalEvent::Get().getMouseCursorPos(); fheroes2::Display::instance().render( { pos.x, pos.y, 1, 1 } ); } } fheroes2-1.1.6+dfsg/src/fheroes2/gui/cursor.h000066400000000000000000000171731476115357100207540ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "math_base.h" #include "screen.h" namespace fheroes2 { class Image; } class Cursor { public: enum CursorType : int { NONE = 0x0000, // ADVMCO.ICN POINTER = 0x1000, WAIT = 0x1001, HEROES = 0x1002, CASTLE = 0x1003, // 0x1004 to 0x101F are not in use anymore SCROLL_TOP = 0x1020, SCROLL_TOPRIGHT = 0x1021, SCROLL_RIGHT = 0x1022, SCROLL_BOTTOMRIGHT = 0x1023, SCROLL_BOTTOM = 0x1024, SCROLL_BOTTOMLEFT = 0x1025, SCROLL_LEFT = 0x1026, SCROLL_TOPLEFT = 0x1027, POINTER_VIDEO = 0x1028, // this cursor is used only for video playback // CMSECO.ICN WAR_NONE = 0x2000, WAR_MOVE = 0x2001, WAR_FLY = 0x2002, WAR_ARROW = 0x2003, WAR_HERO = 0x2004, WAR_INFO = 0x2005, WAR_POINTER = 0x2006, SWORD_TOPRIGHT = 0x2007, SWORD_RIGHT = 0x2008, SWORD_BOTTOMRIGHT = 0x2009, SWORD_BOTTOMLEFT = 0x200A, SWORD_LEFT = 0x200B, SWORD_TOPLEFT = 0x200C, SWORD_TOP = 0x200D, SWORD_BOTTOM = 0x200E, WAR_BROKENARROW = 0x200F, // SPELCO.ICN SP_NONE = WAR_NONE, SP_SLOW = 0x3001, SP_UNKNOWN = 0x3002, SP_CURSE = 0x3003, SP_LIGHTNINGBOLT = 0x3004, SP_CHAINLIGHTNING = 0x3005, SP_CURE = 0x3006, SP_BLESS = 0x3007, SP_FIREBALL = 0x3008, SP_FIREBLAST = 0x3009, SP_TELEPORT = 0x300A, SP_ELEMENTALSTORM = 0x300B, SP_RESURRECTTRUE = 0x300C, SP_RESURRECT = 0x300D, SP_HASTE = 0x300E, SP_SHIELD = 0x300F, SP_ARMAGEDDON = 0x3010, SP_ANTIMAGIC = 0x3011, SP_DISPEL = 0x3012, SP_BERSERKER = 0x3013, SP_PARALYZE = 0x3014, SP_BLIND = 0x3015, SP_HOLYWORD = 0x3016, SP_HOLYSHOUT = 0x3017, SP_METEORSHOWER = 0x3018, SP_ANIMATEDEAD = 0x3019, SP_MIRRORIMAGE = 0x301A, SP_BLOODLUST = 0x301B, SP_DEATHRIPPLE = 0x301C, SP_DEATHWAVE = 0x301D, SP_STEELSKIN = 0x301E, SP_STONESKIN = 0x301F, SP_DRAGONSLAYER = 0x3020, SP_EARTHQUAKE = 0x3021, SP_DISRUPTINGRAY = 0x3022, SP_COLDRING = 0x3023, SP_COLDRAY = 0x3024, SP_HYPNOTIZE = 0x3025, SP_ARROW = 0x3026 }; enum MapHeroCursor : int { CURSOR_HERO_MOVE = 0x4000, CURSOR_HERO_MOVE_2, CURSOR_HERO_MOVE_3, CURSOR_HERO_MOVE_4, CURSOR_HERO_MOVE_5, CURSOR_HERO_MOVE_6, CURSOR_HERO_MOVE_7, CURSOR_HERO_MOVE_8, CURSOR_HERO_FIGHT, CURSOR_HERO_FIGHT_2, CURSOR_HERO_FIGHT_3, CURSOR_HERO_FIGHT_4, CURSOR_HERO_FIGHT_5, CURSOR_HERO_FIGHT_6, CURSOR_HERO_FIGHT_7, CURSOR_HERO_FIGHT_8, CURSOR_HERO_BOAT, CURSOR_HERO_BOAT_2, CURSOR_HERO_BOAT_3, CURSOR_HERO_BOAT_4, CURSOR_HERO_BOAT_5, CURSOR_HERO_BOAT_6, CURSOR_HERO_BOAT_7, CURSOR_HERO_BOAT_8, CURSOR_HERO_ANCHOR, CURSOR_HERO_ANCHOR_2, CURSOR_HERO_ANCHOR_3, CURSOR_HERO_ANCHOR_4, CURSOR_HERO_ANCHOR_5, CURSOR_HERO_ANCHOR_6, CURSOR_HERO_ANCHOR_7, CURSOR_HERO_ANCHOR_8, CURSOR_HERO_MEET, CURSOR_HERO_MEET_2, CURSOR_HERO_MEET_3, CURSOR_HERO_MEET_4, CURSOR_HERO_MEET_5, CURSOR_HERO_MEET_6, CURSOR_HERO_MEET_7, CURSOR_HERO_MEET_8, CURSOR_HERO_ACTION, CURSOR_HERO_ACTION_2, CURSOR_HERO_ACTION_3, CURSOR_HERO_ACTION_4, CURSOR_HERO_ACTION_5, CURSOR_HERO_ACTION_6, CURSOR_HERO_ACTION_7, CURSOR_HERO_ACTION_8, CURSOR_HERO_BOAT_ACTION, CURSOR_HERO_BOAT_ACTION_2, CURSOR_HERO_BOAT_ACTION_3, CURSOR_HERO_BOAT_ACTION_4, CURSOR_HERO_BOAT_ACTION_5, CURSOR_HERO_BOAT_ACTION_6, CURSOR_HERO_BOAT_ACTION_7, CURSOR_HERO_BOAT_ACTION_8 }; Cursor( const Cursor & ) = delete; Cursor & operator=( const Cursor & ) = delete; static Cursor & Get(); // Returns a non-empty area if it should be updated while rendering. static fheroes2::Rect updateCursorPosition( const int32_t x, const int32_t y ); static int DistanceThemes( const int theme, uint32_t distance ); static int WithoutDistanceThemes( const int theme ); static void Refresh(); int Themes() const { assert( _theme <= CURSOR_HERO_BOAT_ACTION_8 ); return _theme; } void SetThemes( const int theme, const bool force = false ); void setCustomImage( const fheroes2::Image & image, const fheroes2::Point & offset ); // Only for software emulation. void setVideoPlaybackCursor(); // Do not call this method directly anywhere except Settings. void setMonochromeCursor( const bool enable ) { _monochromeCursorThemes = enable; } private: Cursor() = default; ~Cursor() = default; void SetOffset( int name, const fheroes2::Point & defaultOffset ); void Move( int32_t x, int32_t y ) const; int _theme{ Cursor::CursorType::NONE }; fheroes2::Point _offset; bool _monochromeCursorThemes{ false }; }; class CursorRestorer { public: CursorRestorer() = default; // Use only to hide a cursor. Previous cursor visibility and theme will be restored when this object is destroyed. explicit CursorRestorer( const bool visible ); // Use to set cursor visibility and theme of the cursor. Previous cursor visibility and theme will be restored when this object is destroyed. CursorRestorer( const bool visible, const int theme ); CursorRestorer( const CursorRestorer & ) = delete; ~CursorRestorer(); CursorRestorer & operator=( const CursorRestorer & ) = delete; private: const int _theme{ Cursor::Get().Themes() }; const bool _visible{ fheroes2::cursor().isVisible() }; }; fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_base.cpp000066400000000000000000000041271476115357100227170ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2023 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_base.h" #include "game.h" #include "ui_tool.h" namespace Interface { void BaseInterface::renderWithFadeInOrPlanRender( const uint32_t redrawMask ) { if ( Game::validateDisplayFadeIn() ) { redraw( redrawMask ); fheroes2::fadeInDisplay(); } else { setRedraw( redrawMask ); } } void Interface::BaseInterface::validateFadeInAndRender() { if ( Game::validateDisplayFadeIn() ) { fheroes2::fadeInDisplay(); setRedraw( REDRAW_GAMEAREA ); } else { fheroes2::Display::instance().render(); } } } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_base.h000066400000000000000000000122711476115357100223630ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "game_mode.h" #include "interface_gamearea.h" #include "interface_radar.h" #include "math_base.h" #include "screen.h" #include "ui_constants.h" namespace Interface { enum Redraw : uint32_t { // The next values are base for game/editor. // To render the cursor over the previously generated radar map image. REDRAW_RADAR_CURSOR = 0x01, // To render radar map fully or in ROI and then the cursor over it. REDRAW_RADAR = 0x02, REDRAW_BORDER = 0x04, REDRAW_GAMEAREA = 0x08, REDRAW_STATUS = 0x10, // The next values are base for game (Adventure Map) interface. REDRAW_HEROES = 0x20, REDRAW_CASTLES = 0x40, REDRAW_BUTTONS = 0x80, REDRAW_ICONS = REDRAW_HEROES | REDRAW_CASTLES, // The next value is base for Map Editor interface. REDRAW_PANEL = 0x100, REDRAW_ALL = 0x1FF, // This option is only for the Editor. REDRAW_PASSABILITIES = 0x200 }; class BaseInterface { public: explicit BaseInterface( const bool isEditor_ ) : _gameArea( *this ) , _radar( *this ) , _isEditor( isEditor_ ) { // Do nothing } virtual ~BaseInterface() = default; virtual void redraw( const uint32_t force ) = 0; bool needRedraw() const { return _redraw != 0; } void setRedraw( const uint32_t r ) { _redraw |= r; } uint32_t getRedrawMask() const { return _redraw; } static bool isScrollLeft( const fheroes2::Point & cursorPos ) { return cursorPos.x < fheroes2::borderWidthPx; } static bool isScrollRight( const fheroes2::Point & cursorPos ) { const fheroes2::Display & display = fheroes2::Display::instance(); return cursorPos.x >= display.width() - fheroes2::borderWidthPx; } static bool isScrollTop( const fheroes2::Point & cursorPos ) { return cursorPos.y < fheroes2::borderWidthPx; } static bool isScrollBottom( const fheroes2::Point & cursorPos ) { const fheroes2::Display & display = fheroes2::Display::instance(); return cursorPos.y >= display.height() - fheroes2::borderWidthPx; } GameArea & getGameArea() { return _gameArea; } Radar & getRadar() { return _radar; } static fheroes2::GameMode EventExit(); virtual bool useMouseDragMovement() { return true; } virtual void mouseCursorAreaClickLeft( const int32_t tileIndex ) = 0; virtual void mouseCursorAreaPressRight( const int32_t tileIndex ) const = 0; virtual void mouseCursorAreaLongPressLeft( const int32_t tileIndex ) = 0; // Regenerates the game area and updates the panel positions depending on the UI settings virtual void reset() = 0; virtual void updateCursor( const int32_t tileIndex ) = 0; bool isEditor() const { return _isEditor; } // Call this function to plan (set) redraw if fade in is not set // or redraw the given interface items and do fade in with them rendered. void renderWithFadeInOrPlanRender( const uint32_t redrawMask ); protected: // If display fade-in state is set reset it to false and fade-in the full display image. Otherwise render full display image without fade-in. void validateFadeInAndRender(); GameArea _gameArea; Radar _radar; uint32_t _redraw{ 0 }; const bool _isEditor{ false }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_border.cpp000066400000000000000000000542161476115357100232660ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_border.h" #include #include "agg_image.h" #include "cursor.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "screen.h" #include "settings.h" #include "ui_constants.h" #include "ui_tool.h" namespace { void repeatPattern( const fheroes2::Image & in, int32_t inX, int32_t inY, int32_t inWidth, int32_t inHeight, fheroes2::Image & out, int32_t outX, int32_t outY, int32_t width, int32_t height ) { if ( inX < 0 || inY < 0 || outX < 0 || outY < 0 || inWidth <= 0 || inHeight <= 0 || width <= 0 || height <= 0 ) return; const int32_t countX = width / inWidth; const int32_t countY = height / inHeight; const int32_t restWidth = width % inWidth; const int32_t restHeight = height % inHeight; for ( int32_t y = 0; y < countY; ++y ) { for ( int32_t x = 0; x < countX; ++x ) { fheroes2::Blit( in, inX, inY, out, outX + x * inWidth, outY + y * inHeight, inWidth, inHeight ); } if ( restWidth != 0 ) { fheroes2::Blit( in, inX, inY, out, outX + width - restWidth, outY + y * inHeight, restWidth, inHeight ); } } if ( restHeight != 0 ) { for ( int32_t x = 0; x < countX; ++x ) { fheroes2::Blit( in, inX, inY, out, outX + x * inWidth, outY + height - restHeight, inWidth, restHeight ); } if ( restWidth != 0 ) { fheroes2::Blit( in, inX, inY, out, outX + width - restWidth, outY + height - restHeight, restWidth, restHeight ); } } } } void Interface::GameBorderRedraw( const bool viewWorldMode ) { const Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() && !viewWorldMode ) return; const bool isEvilInterface = conf.isEvilInterfaceEnabled(); fheroes2::Display & display = fheroes2::Display::instance(); const int32_t displayWidth = display.width(); const int32_t displayHeight = display.height(); const int32_t extraDisplayWidth = displayWidth - fheroes2::Display::DEFAULT_WIDTH; const int32_t extraDisplayHeight = displayHeight - fheroes2::Display::DEFAULT_HEIGHT; const int32_t topRepeatCount = extraDisplayWidth > 0 ? extraDisplayWidth / fheroes2::tileWidthPx : 0; const int32_t topRepeatWidth = ( topRepeatCount + 1 ) * fheroes2::tileWidthPx; const int32_t vertRepeatCount = extraDisplayHeight > 0 ? extraDisplayHeight / fheroes2::tileWidthPx : 0; const int32_t iconsCount = vertRepeatCount > 3 ? 8 : ( vertRepeatCount < 3 ? 4 : 7 ); const int32_t vertRepeatHeight = ( vertRepeatCount + 1 ) * fheroes2::tileWidthPx; const int32_t vertRepeatHeightTop = ( iconsCount - 3 ) * fheroes2::tileWidthPx; const int32_t vertRepeatHeightBottom = vertRepeatHeight - vertRepeatHeightTop; const int32_t topPadWidth = extraDisplayWidth % fheroes2::tileWidthPx; // top and bottom padding is split in two halves around the repeated "tiles" const int32_t topPadWidthLeft = topPadWidth / 2; const int32_t topPadWidthRight = topPadWidth - topPadWidthLeft; int32_t bottomTileWidth; int32_t bottomRepeatCount; if ( isEvilInterface ) { bottomTileWidth = 7; // width of a single bone piece bottomRepeatCount = extraDisplayWidth > 0 ? extraDisplayWidth / bottomTileWidth : 0; } else { bottomTileWidth = fheroes2::tileWidthPx; bottomRepeatCount = topRepeatCount; } const int32_t bottomRepeatWidth = ( bottomRepeatCount + 1 ) * bottomTileWidth; const int32_t bottomPadWidth = extraDisplayWidth % bottomTileWidth; const int32_t bottomPadWidthLeft = bottomPadWidth / 2; const int32_t bottomPadWidthRight = bottomPadWidth - bottomPadWidthLeft; const int32_t vertPadHeight = extraDisplayHeight % fheroes2::tileWidthPx; fheroes2::Rect srcrt; fheroes2::Point dstpt; const fheroes2::Sprite & icnadv = fheroes2::AGG::GetICN( isEvilInterface ? ICN::ADVBORDE : ICN::ADVBORD, 0 ); // TOP BORDER srcrt.x = 0; srcrt.y = 0; srcrt.width = isEvilInterface ? 153 : 193; srcrt.height = fheroes2::borderWidthPx; dstpt.x = srcrt.x; dstpt.y = srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); srcrt.x += srcrt.width; srcrt.width = 6; dstpt.x = srcrt.x; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, srcrt.width + topPadWidthLeft, fheroes2::borderWidthPx ); dstpt.x += srcrt.width + topPadWidthLeft; srcrt.x += srcrt.width; srcrt.width = isEvilInterface ? 64 : 24; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.x += srcrt.width; srcrt.x += srcrt.width; srcrt.width = fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, topRepeatWidth, fheroes2::borderWidthPx ); dstpt.x += topRepeatWidth; srcrt.x += fheroes2::tileWidthPx; srcrt.width = isEvilInterface ? 65 : 25; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.x += srcrt.width; srcrt.x += srcrt.width; srcrt.width = 6; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, srcrt.width + topPadWidthRight, fheroes2::borderWidthPx ); dstpt.x += srcrt.width + topPadWidthRight; srcrt.x += srcrt.width; srcrt.width = icnadv.width() - srcrt.x; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // LEFT BORDER srcrt.x = 0; srcrt.y = fheroes2::borderWidthPx; srcrt.width = fheroes2::borderWidthPx; srcrt.height = 255 - fheroes2::borderWidthPx; dstpt.x = srcrt.x; dstpt.y = srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; if ( isEvilInterface ) { srcrt.height = fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightTop ); dstpt.y += vertRepeatHeightTop; srcrt.y += fheroes2::tileWidthPx; srcrt.width = fheroes2::borderWidthPx; srcrt.height = 35; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = 6; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, srcrt.height + vertPadHeight ); dstpt.y += srcrt.height + vertPadHeight; srcrt.y += srcrt.height; srcrt.height = 103; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = fheroes2::tileWidthPx; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightBottom ); dstpt.y += vertRepeatHeightBottom; srcrt.y += fheroes2::tileWidthPx; } else { srcrt.height = fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeight ); dstpt.y += vertRepeatHeight; srcrt.y += fheroes2::tileWidthPx; srcrt.height = 125; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = 4; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, srcrt.height + vertPadHeight ); dstpt.y += srcrt.height + vertPadHeight; srcrt.y += srcrt.height; } srcrt.height = icnadv.height() - fheroes2::borderWidthPx - srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // MIDDLE BORDER srcrt.x = icnadv.width() - fheroes2::radarWidthPx - 2 * fheroes2::borderWidthPx; srcrt.y = fheroes2::borderWidthPx; srcrt.width = fheroes2::borderWidthPx; srcrt.height = 255 - fheroes2::borderWidthPx; dstpt.x = displayWidth - fheroes2::radarWidthPx - 2 * fheroes2::borderWidthPx; dstpt.y = srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightTop ); dstpt.y += vertRepeatHeightTop; srcrt.y += fheroes2::tileWidthPx; srcrt.height = isEvilInterface ? 35 : 50; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // hide embranchment if ( viewWorldMode ) { fheroes2::Rect fixrt( 478, isEvilInterface ? 137 : 345, 3, isEvilInterface ? 15 : 20 ); fheroes2::Point fixpt( dstpt.x + 14, dstpt.y + 18 ); fheroes2::Blit( icnadv, fixrt.x, fixrt.y, display, fixpt.x, fixpt.y, fixrt.width, fixrt.height ); } dstpt.y += srcrt.height; srcrt.y += srcrt.height; if ( isEvilInterface ) { srcrt.height = 6; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, srcrt.height + vertPadHeight ); dstpt.y += srcrt.height + vertPadHeight; srcrt.y += srcrt.height; srcrt.height = 103; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = fheroes2::tileWidthPx; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightBottom ); dstpt.y += vertRepeatHeightBottom; srcrt.y += fheroes2::tileWidthPx; } else { srcrt.height = fheroes2::tileWidthPx; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightBottom ); dstpt.y += vertRepeatHeightBottom; srcrt.y += fheroes2::tileWidthPx; srcrt.height = 43; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = 8; // middle border is special on good interface due to all the green leaves repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, srcrt.height + vertPadHeight ); dstpt.y += srcrt.height + vertPadHeight; srcrt.y += srcrt.height; } srcrt.height = icnadv.height() - fheroes2::borderWidthPx - srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // RIGHT BORDER srcrt.x = icnadv.width() - fheroes2::borderWidthPx; srcrt.y = fheroes2::borderWidthPx; srcrt.width = fheroes2::borderWidthPx; srcrt.height = 255 - fheroes2::borderWidthPx; dstpt.x = displayWidth - fheroes2::borderWidthPx; dstpt.y = srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightTop ); dstpt.y += vertRepeatHeightTop; srcrt.y += fheroes2::tileWidthPx; srcrt.height = isEvilInterface ? 35 : 50; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // hide embranchment if ( viewWorldMode ) { fheroes2::Rect fixrt( 624, isEvilInterface ? 139 : 345, 3, isEvilInterface ? 15 : 20 ); fheroes2::Point fixpt( dstpt.x, dstpt.y + 18 ); fheroes2::Blit( icnadv, fixrt.x, fixrt.y, display, fixpt.x, fixpt.y, fixrt.width, fixrt.height ); } dstpt.y += srcrt.height; srcrt.y += srcrt.height; if ( isEvilInterface ) { srcrt.height = 6; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, srcrt.height + vertPadHeight ); dstpt.y += srcrt.height + vertPadHeight; srcrt.y += srcrt.height; srcrt.height = 103; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = fheroes2::tileWidthPx; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightBottom ); dstpt.y += vertRepeatHeightBottom; srcrt.y += fheroes2::tileWidthPx; } else { srcrt.height = fheroes2::tileWidthPx; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += fheroes2::tileWidthPx; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, vertRepeatHeightBottom ); dstpt.y += vertRepeatHeightBottom; srcrt.y += fheroes2::tileWidthPx; srcrt.height = 43; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.y += srcrt.height; srcrt.y += srcrt.height; srcrt.height = 4; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, fheroes2::borderWidthPx, srcrt.height + vertPadHeight ); dstpt.y += srcrt.height + vertPadHeight; srcrt.y += srcrt.height; } srcrt.height = icnadv.height() - fheroes2::borderWidthPx - srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // BOTTOM BORDER srcrt.x = 0; srcrt.y = icnadv.height() - fheroes2::borderWidthPx; srcrt.width = isEvilInterface ? 129 : 193; srcrt.height = fheroes2::borderWidthPx; dstpt.x = srcrt.x; dstpt.y = displayHeight - fheroes2::borderWidthPx; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.x += srcrt.width; srcrt.x += srcrt.width; srcrt.width = 6; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, srcrt.width + bottomPadWidthLeft, fheroes2::borderWidthPx ); dstpt.x += srcrt.width + bottomPadWidthLeft; srcrt.x += srcrt.width; srcrt.width = isEvilInterface ? 90 : 24; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.x += srcrt.width; srcrt.x += srcrt.width; srcrt.width = bottomTileWidth; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, bottomRepeatWidth, fheroes2::borderWidthPx ); dstpt.x += bottomRepeatWidth; srcrt.x += srcrt.width; srcrt.width = isEvilInterface ? 86 : 25; // evil bottom border is asymmetric fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); dstpt.x += srcrt.width; srcrt.x += srcrt.width; srcrt.width = 6; repeatPattern( icnadv, srcrt.x, srcrt.y, srcrt.width, srcrt.height, display, dstpt.x, dstpt.y, srcrt.width + bottomPadWidthRight, fheroes2::borderWidthPx ); dstpt.x += srcrt.width + bottomPadWidthRight; srcrt.x += srcrt.width; srcrt.width = icnadv.width() - srcrt.x; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // ICON BORDER srcrt.x = icnadv.width() - fheroes2::radarWidthPx - fheroes2::borderWidthPx; srcrt.y = fheroes2::radarWidthPx + fheroes2::borderWidthPx; srcrt.width = fheroes2::radarWidthPx; srcrt.height = fheroes2::borderWidthPx; dstpt.x = displayWidth - fheroes2::radarWidthPx - fheroes2::borderWidthPx; dstpt.y = srcrt.y; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); if ( !viewWorldMode ) { dstpt.y = srcrt.y + fheroes2::borderWidthPx + iconsCount * 32; srcrt.y = srcrt.y + fheroes2::borderWidthPx + 4 * 32; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); } } Interface::BorderWindow::BorderWindow( const fheroes2::Rect & rt ) : area( rt ) {} const fheroes2::Rect & Interface::BorderWindow::GetRect() const { return Settings::Get().isHideInterfaceEnabled() && border.isValid() ? border.GetRect() : GetArea(); } bool Interface::BorderWindow::isMouseCaptured() { if ( !_isMouseCaptured ) { return false; } const LocalEvent & le = LocalEvent::Get(); _isMouseCaptured = le.isMouseLeftButtonPressed(); // Even if the mouse has just been released from the capture, consider it still captured at this // stage to ensure that events directly related to the release (for instance, releasing the mouse // button) will not be handled by other UI elements. return true; } void Interface::BorderWindow::Redraw() const { Dialog::FrameBorder::RenderRegular( border.GetRect() ); } void Interface::BorderWindow::SetPosition( const int32_t x, const int32_t y, const int32_t width, const int32_t height ) { area.width = width; area.height = height; SetPosition( x, y ); } void Interface::BorderWindow::SetPosition( int32_t x, int32_t y ) { if ( Settings::Get().isHideInterfaceEnabled() ) { const fheroes2::Display & display = fheroes2::Display::instance(); x = std::max( 0, std::min( x, display.width() - ( area.width + border.BorderWidth() * 2 ) ) ); y = std::max( 0, std::min( y, display.height() - ( area.height + border.BorderHeight() * 2 ) ) ); area.x = x + border.BorderWidth(); area.y = y + border.BorderHeight(); border.SetPosition( x, y, area.width, area.height ); SavePosition(); } else { area.x = x; area.y = y; } } void Interface::BorderWindow::captureMouse() { const LocalEvent & le = LocalEvent::Get(); if ( le.isMouseLeftButtonPressedInArea( GetRect() ) ) { _isMouseCaptured = true; } else { _isMouseCaptured = _isMouseCaptured && le.isMouseLeftButtonPressed(); } } bool Interface::BorderWindow::QueueEventProcessing() { LocalEvent & le = LocalEvent::Get(); if ( !Settings::Get().isHideInterfaceEnabled() || !le.isMouseLeftButtonPressedInArea( border.GetTop() ) ) { return false; } // Reset the cursor when dragging, because if the window border is close to the edge of the game window, // then the mouse cursor could be changed to a scroll cursor. Cursor::Get().SetThemes( Cursor::POINTER ); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Point & mp = le.getMouseCursorPos(); const fheroes2::Rect & pos = GetRect(); fheroes2::MovableSprite moveIndicator( pos.width, pos.height, pos.x, pos.y ); moveIndicator.reset(); fheroes2::DrawBorder( moveIndicator, fheroes2::GetColorId( 0xD0, 0xC0, 0x48 ), 6 ); const int32_t ox = mp.x - pos.x; const int32_t oy = mp.y - pos.y; moveIndicator.setPosition( pos.x, pos.y ); moveIndicator.redraw(); display.render(); while ( le.HandleEvents() && le.isMouseLeftButtonPressed() ) { if ( le.hasMouseMoved() ) { moveIndicator.setPosition( mp.x - ox, mp.y - oy ); display.render(); } } SetPos( mp.x - ox, mp.y - oy ); return true; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_border.h000066400000000000000000000060021476115357100227210ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "dialog.h" #include "math_base.h" namespace Interface { void GameBorderRedraw( const bool viewWorldMode ); class BorderWindow { public: explicit BorderWindow( const fheroes2::Rect & rt ); BorderWindow( const BorderWindow & ) = delete; virtual ~BorderWindow() = default; BorderWindow & operator=( const BorderWindow & ) = delete; virtual void SetPos( int32_t x, int32_t y ) = 0; virtual void SavePosition() = 0; bool QueueEventProcessing(); const fheroes2::Rect & GetRect() const; const fheroes2::Rect & GetArea() const { return area; } // Checks if the mouse is still captured by this UI element. See the implementation for details. bool isMouseCaptured(); protected: void Redraw() const; void SetPosition( const int32_t x, const int32_t y, const int32_t width, const int32_t height ); void SetPosition( int32_t x, int32_t y ); // Captures the mouse by this UI element if necessary. The conditions for capturing imply that // the mouse cursor is on this UI element and the left mouse button is pressed. void captureMouse(); fheroes2::Rect area; Dialog::FrameBorder border; bool _isMouseCaptured{ false }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_buttons.cpp000066400000000000000000000263401476115357100235040ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_buttons.h" #include #include #include "dialog.h" #include "game_interface.h" #include "heroes.h" #include "icn.h" #include "interface_base.h" #include "kingdom.h" #include "localevent.h" #include "mp2.h" #include "route.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_dialog.h" #include "world.h" void Interface::ButtonsPanel::SavePosition() { Settings & conf = Settings::Get(); conf.SetPosButtons( GetRect().getPosition() ); conf.Save( Settings::configFileName ); } void Interface::ButtonsPanel::setRedraw() const { _interface.setRedraw( REDRAW_BUTTONS ); } void Interface::ButtonsPanel::SetPos( int32_t x, int32_t y ) { BorderWindow::SetPosition( x, y ); const int icnbtn = Settings::Get().isEvilInterfaceEnabled() ? ICN::ADVEBTNS : ICN::ADVBTNS; _buttonNextHero.setICNInfo( icnbtn, 0, 1 ); _buttonHeroMovement.setICNInfo( icnbtn, 2, 3 ); _buttonKingdom.setICNInfo( icnbtn, 4, 5 ); _buttonSpell.setICNInfo( icnbtn, 6, 7 ); _buttonEndTurn.setICNInfo( icnbtn, 8, 9 ); _buttonAdventure.setICNInfo( icnbtn, 10, 11 ); _buttonFile.setICNInfo( icnbtn, 12, 13 ); _buttonSystem.setICNInfo( icnbtn, 14, 15 ); _setButtonStatus(); x = GetArea().x; y = GetArea().y; // Top row _buttonNextHero.setPosition( x, y ); _nextHeroRect = _buttonNextHero.area(); _buttonHeroMovement.setPosition( _nextHeroRect.x + _nextHeroRect.width, y ); _heroMovementRect = _buttonHeroMovement.area(); _buttonKingdom.setPosition( _heroMovementRect.x + _heroMovementRect.width, y ); _kingdomRect = _buttonKingdom.area(); _buttonSpell.setPosition( _kingdomRect.x + _kingdomRect.width, y ); _spellRect = _buttonSpell.area(); // Bottom row y = _nextHeroRect.y + _nextHeroRect.height; _buttonEndTurn.setPosition( x, y ); _endTurnRect = _buttonEndTurn.area(); _buttonAdventure.setPosition( _endTurnRect.x + _endTurnRect.width, y ); _adventureRect = _buttonAdventure.area(); _buttonFile.setPosition( _adventureRect.x + _adventureRect.width, y ); _fileRect = _buttonFile.area(); _buttonSystem.setPosition( _fileRect.x + _fileRect.width, y ); _systemRect = _buttonSystem.area(); } void Interface::ButtonsPanel::_redraw() { const Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() ) { if ( !conf.ShowButtons() ) { return; } BorderWindow::Redraw(); } _setButtonStatus(); _buttonNextHero.draw(); _buttonHeroMovement.draw(); _buttonKingdom.draw(); _buttonSpell.draw(); _buttonEndTurn.draw(); _buttonAdventure.draw(); _buttonFile.draw(); _buttonSystem.draw(); } fheroes2::GameMode Interface::ButtonsPanel::queueEventProcessing() { captureMouse(); LocalEvent & le = LocalEvent::Get(); // In the "no interface" mode, the buttons panel may be overlapped by other UI elements, so we can't render the // pressed or released buttons exclusively in a usual way. The overlapping UI elements should also be rendered. const auto drawOnPressOrRelease = [this, &le]( fheroes2::Button & button, const fheroes2::Rect & buttonRect ) { bool shouldRedraw = false; if ( le.isMouseLeftButtonPressedInArea( buttonRect ) ) { if ( !button.isPressed() && button.press() ) { shouldRedraw = true; } } else { if ( !button.isReleased() && button.release() ) { shouldRedraw = true; } } if ( shouldRedraw ) { _interface.redraw( REDRAW_BUTTONS ); // Render now only the changed part of the screen. fheroes2::Display::instance().render( buttonRect ); } }; drawOnPressOrRelease( _buttonNextHero, _nextHeroRect ); drawOnPressOrRelease( _buttonHeroMovement, _heroMovementRect ); drawOnPressOrRelease( _buttonKingdom, _kingdomRect ); drawOnPressOrRelease( _buttonSpell, _spellRect ); drawOnPressOrRelease( _buttonEndTurn, _endTurnRect ); drawOnPressOrRelease( _buttonAdventure, _adventureRect ); drawOnPressOrRelease( _buttonFile, _fileRect ); drawOnPressOrRelease( _buttonSystem, _systemRect ); fheroes2::GameMode res = fheroes2::GameMode::CANCEL; // Move the window border. if ( Settings::Get().ShowButtons() && BorderWindow::QueueEventProcessing() ) { setRedraw(); } else if ( _buttonNextHero.isEnabled() && le.MouseClickLeft( _nextHeroRect ) ) { _interface.EventNextHero(); } else if ( _buttonHeroMovement.isEnabled() && le.MouseClickLeft( _heroMovementRect ) ) { res = _interface.EventHeroMovement(); } // The 'MouseLongPressLeft()' for '_heroMovementRect' should be called only if current hero // has valid path not to trigger the '_mouseButtonLongPressDelay'. // The inlined 'isMouseLeftButtonPressedInArea()' method is called not to call 'isValidForMovement()' // method every time this button is enabled. else if ( _buttonHeroMovement.isEnabled() && le.isMouseLeftButtonPressedInArea( _heroMovementRect ) && []() { const Heroes * currentHero = GetFocusHeroes(); assert( currentHero != nullptr ); return currentHero->GetPath().isValidForMovement(); }() && le.MouseLongPressLeft( _heroMovementRect ) ) { _interface.EventResetHeroPath(); } else if ( le.MouseClickLeft( _kingdomRect ) ) { _interface.EventKingdomInfo(); } else if ( _buttonSpell.isEnabled() && le.MouseClickLeft( _spellRect ) ) { _interface.EventCastSpell(); } else if ( le.MouseClickLeft( _endTurnRect ) ) { res = _interface.EventEndTurn(); } else if ( le.MouseClickLeft( _adventureRect ) ) { res = _interface.EventAdventureDialog(); } else if ( le.MouseClickLeft( _fileRect ) ) { res = _interface.EventFileDialog(); } else if ( le.MouseClickLeft( _systemRect ) ) { _interface.EventSystemDialog(); } else if ( le.isMouseRightButtonPressedInArea( _nextHeroRect ) ) { fheroes2::showStandardTextMessage( _( "Next Hero" ), _( "Select the next Hero." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _heroMovementRect ) ) { fheroes2::showStandardTextMessage( _( "Hero Movement" ), _( "Start the Hero's movement along the current path or re-visit the object occupied by the Hero. Press and hold this button to reset the Hero's path." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _kingdomRect ) ) { fheroes2::showStandardTextMessage( _( "Kingdom Summary" ), _( "View a summary of your Kingdom." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _spellRect ) ) { fheroes2::showStandardTextMessage( _( "Cast Spell" ), _( "Cast an adventure spell." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _endTurnRect ) ) { fheroes2::showStandardTextMessage( _( "End Turn" ), _( "End your turn and let the computer take its turn." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _adventureRect ) ) { fheroes2::showStandardTextMessage( _( "Adventure Options" ), _( "Bring up the adventure options menu." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _fileRect ) ) { fheroes2::showStandardTextMessage( _( "File Options" ), _( "Bring up the file options menu, allowing you to load, save, start a new game or quit." ), Dialog::ZERO ); } else if ( le.isMouseRightButtonPressedInArea( _systemRect ) ) { fheroes2::showStandardTextMessage( _( "System Options" ), _( "Bring up the system options menu, allowing you to customize your game." ), Dialog::ZERO ); } return res; } void Interface::ButtonsPanel::_setButtonStatus() { Heroes * currentHero = GetFocusHeroes(); if ( currentHero && currentHero->GetPath().isValidForMovement() && currentHero->MayStillMove( false, true ) ) { // Move button: to move the hero by the specified path. _buttonHeroMovement.setICNIndexes( 2, 3 ); _buttonHeroMovement.enable(); } else if ( currentHero && MP2::isInGameActionObject( currentHero->getObjectTypeUnderHero(), currentHero->isShipMaster() ) ) { // Action button: to visit the action object hero is standing on. _buttonHeroMovement.setICNIndexes( 16, 17 ); _buttonHeroMovement.enable(); } else if ( currentHero && currentHero->GetPath().isValidForMovement() ) { // Inactive button: to show the hero's path can be reset. _buttonHeroMovement.setICNIndexes( 18, 19 ); _buttonHeroMovement.enable(); } else { // Inactive button (disabled): to show that the hero as no path specified. _buttonHeroMovement.setICNIndexes( 18, 19 ); _buttonHeroMovement.disable(); } if ( currentHero && currentHero->HaveSpellBook() && currentHero->MayCastAdventureSpells() ) { _buttonSpell.enable(); } else { _buttonSpell.disable(); } const Kingdom & kingdom = world.GetKingdom( Settings::Get().CurrentColor() ); const VecHeroes & heroes = kingdom.GetHeroes(); const bool isMovableHeroPresent = std::any_of( heroes.begin(), heroes.end(), []( const Heroes * hero ) { assert( hero != nullptr ); return hero->MayStillMove( false, false ); } ); if ( isMovableHeroPresent ) { _buttonNextHero.enable(); } else { _buttonNextHero.disable(); } } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_buttons.h000066400000000000000000000066221476115357100231520ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "game_mode.h" #include "interface_border.h" #include "math_base.h" #include "ui_button.h" namespace Interface { class AdventureMap; class ButtonsPanel final : public BorderWindow { public: explicit ButtonsPanel( AdventureMap & baseInterface ) : BorderWindow( { 0, 0, 144, 72 } ) , _interface( baseInterface ) { // Do nothing. } ButtonsPanel( const ButtonsPanel & ) = delete; ~ButtonsPanel() override = default; ButtonsPanel & operator=( const ButtonsPanel & ) = delete; void SetPos( int32_t x, int32_t y ) override; void SavePosition() override; void setRedraw() const; fheroes2::GameMode queueEventProcessing(); // Do not call this method directly, use Interface::AdventureMap::redraw() instead to avoid issues in the "no interface" mode. // The name of this method starts from _ on purpose to do not mix with other public methods. void _redraw(); private: void _setButtonStatus(); AdventureMap & _interface; fheroes2::Button _buttonNextHero; fheroes2::Button _buttonHeroMovement; fheroes2::Button _buttonKingdom; fheroes2::Button _buttonSpell; fheroes2::Button _buttonEndTurn; fheroes2::Button _buttonAdventure; fheroes2::Button _buttonFile; fheroes2::Button _buttonSystem; fheroes2::Rect _nextHeroRect; fheroes2::Rect _heroMovementRect; fheroes2::Rect _kingdomRect; fheroes2::Rect _spellRect; fheroes2::Rect _endTurnRect; fheroes2::Rect _adventureRect; fheroes2::Rect _fileRect; fheroes2::Rect _systemRect; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_cpanel.cpp000066400000000000000000000103411476115357100232420ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_cpanel.h" #include #include "agg_image.h" #include "game_interface.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "screen.h" #include "settings.h" Interface::ControlPanel::ControlPanel( AdventureMap & basic ) : interface( basic ) { width = 180; height = 36; rt_radar.width = 36; rt_radar.height = 36; rt_icons.width = 36; rt_icons.height = 36; rt_buttons.width = 36; rt_buttons.height = 36; rt_status.width = 36; rt_status.height = 36; rt_end.width = 36; rt_end.height = 36; ResetTheme(); } void Interface::ControlPanel::ResetTheme() { const int icn = Settings::Get().isEvilInterfaceEnabled() ? ICN::ADVEBTNS : ICN::ADVBTNS; _buttons.reset( new Buttons( fheroes2::AGG::GetICN( icn, 4 ), fheroes2::AGG::GetICN( icn, 0 ), fheroes2::AGG::GetICN( icn, 12 ), fheroes2::AGG::GetICN( icn, 10 ), fheroes2::AGG::GetICN( icn, 8 ) ) ); } const fheroes2::Rect & Interface::ControlPanel::GetArea() const { return *this; } void Interface::ControlPanel::SetPos( int32_t ox, int32_t oy ) { x = ox; y = oy; rt_radar.x = x; rt_radar.y = y; rt_icons.x = x + 36; rt_icons.y = y; rt_buttons.x = x + 72; rt_buttons.y = y; rt_status.x = x + 108; rt_status.y = y; rt_end.x = x + 144; rt_end.y = y; } void Interface::ControlPanel::_redraw() const { assert( _buttons ); fheroes2::Display & display = fheroes2::Display::instance(); const uint8_t alpha = 128; fheroes2::AlphaBlit( _buttons->radar, display, rt_radar.x, rt_radar.y, alpha ); fheroes2::AlphaBlit( _buttons->icons, display, rt_icons.x, rt_icons.y, alpha ); fheroes2::AlphaBlit( _buttons->buttons, display, rt_buttons.x, rt_buttons.y, alpha ); fheroes2::AlphaBlit( _buttons->status, display, rt_status.x, rt_status.y, alpha ); fheroes2::AlphaBlit( _buttons->end, display, rt_end.x, rt_end.y, alpha ); } fheroes2::GameMode Interface::ControlPanel::QueueEventProcessing() const { LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( rt_radar ) ) { interface.EventSwitchShowRadar(); } else if ( le.MouseClickLeft( rt_icons ) ) { interface.EventSwitchShowIcons(); } else if ( le.MouseClickLeft( rt_buttons ) ) { interface.EventSwitchShowButtons(); } else if ( le.MouseClickLeft( rt_status ) ) { interface.EventSwitchShowStatus(); } else if ( le.MouseClickLeft( rt_end ) ) { return interface.EventEndTurn(); } return fheroes2::GameMode::CANCEL; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_cpanel.h000066400000000000000000000070541476115357100227160ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "game_mode.h" #include "math_base.h" namespace fheroes2 { class Sprite; } namespace Interface { class AdventureMap; class ControlPanel final : protected fheroes2::Rect { public: explicit ControlPanel( AdventureMap & ); ControlPanel( const ControlPanel & ) = delete; ~ControlPanel() = default; ControlPanel & operator=( const ControlPanel & ) = delete; void SetPos( int32_t, int32_t ); void ResetTheme(); fheroes2::GameMode QueueEventProcessing() const; const fheroes2::Rect & GetArea() const; // Do not call this method directly, use Interface::AdventureMap::redraw() instead to avoid issues in the "no interface" mode. // The name of this method starts from _ on purpose to do not mix with other public methods. void _redraw() const; private: AdventureMap & interface; // We do not want to make a copy of images but to store just references to them. struct Buttons { Buttons( const fheroes2::Sprite & radar_, const fheroes2::Sprite & icons_, const fheroes2::Sprite & buttons_, const fheroes2::Sprite & status_, const fheroes2::Sprite & end_ ) : radar( radar_ ) , icons( icons_ ) , buttons( buttons_ ) , status( status_ ) , end( end_ ) {} const fheroes2::Sprite & radar; const fheroes2::Sprite & icons; const fheroes2::Sprite & buttons; const fheroes2::Sprite & status; const fheroes2::Sprite & end; }; std::unique_ptr _buttons; fheroes2::Rect rt_radar; fheroes2::Rect rt_icons; fheroes2::Rect rt_buttons; fheroes2::Rect rt_status; fheroes2::Rect rt_end; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_events.cpp000066400000000000000000000505251476115357100233140ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include "artifact.h" #include "artifact_ultimate.h" #include "audio.h" #include "audio_manager.h" #include "castle.h" #include "dialog.h" #include "dialog_system_options.h" #include "direction.h" #include "game.h" #include "game_delays.h" #include "game_interface.h" // IWYU pragma: associated #include "game_io.h" #include "game_mode.h" #include "game_over.h" #include "heroes.h" #include "image.h" #include "interface_base.h" #include "interface_buttons.h" #include "interface_gamearea.h" #include "interface_icons.h" #include "interface_radar.h" #include "interface_status.h" #include "kingdom.h" #include "logging.h" #include "m82.h" #include "maps.h" #include "maps_tiles.h" #include "mp2.h" #include "mus.h" #include "players.h" #include "puzzle.h" #include "route.h" #include "screen.h" #include "settings.h" #include "spell.h" #include "spell_book.h" #include "system.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "ui_tool.h" #include "view_world.h" #include "world.h" void Interface::AdventureMap::ShowPathOrStartMoveHero( Heroes * hero, const int32_t destinationIdx ) { if ( hero == nullptr || !Maps::isValidAbsIndex( destinationIdx ) ) { return; } assert( !hero->Modes( Heroes::ENABLEMOVE ) ); const Route::Path & path = hero->GetPath(); // Calculate and show the hero's path if ( path.GetDestinationIndex() != destinationIdx ) { hero->calculatePath( destinationIdx ); DEBUG_LOG( DBG_GAME, DBG_TRACE, hero->GetName() << ", distance: " << world.getDistance( *hero, destinationIdx ) << ", route: " << path.String() ) _gameArea.SetRedraw(); _buttonsPanel.setRedraw(); } // Start the hero's movement else if ( path.isValidForMovement() && hero->MayStillMove( false, true ) ) { _startHeroMove( *hero ); } } void Interface::AdventureMap::MoveHeroFromArrowKeys( Heroes & hero, const int direction ) { const int32_t heroIndex = hero.GetIndex(); if ( !Maps::isValidDirection( heroIndex, direction ) ) { return; } const int32_t dstIndex = Maps::GetDirectionIndex( heroIndex, direction ); const Maps::Tile & tile = world.getTile( dstIndex ); if ( !tile.isPassableFrom( Direction::CENTER, hero.isShipMaster(), false, hero.GetColor() ) ) { return; } ShowPathOrStartMoveHero( &hero, dstIndex ); } void Interface::AdventureMap::_startHeroMove( Heroes & hero ) { SetFocus( &hero, true ); RedrawFocus(); hero.SetMove( true ); // We pass this delay to start hero moving immediately and set all the variables needed to handle game events correctly // and to stop handling mouse click events until hero stops. Otherwise there could be a rare case // when double click is faster than this delay and the second click will also be handled which should not happen. Game::passAnimationDelay( Game::DelayType::CURRENT_HERO_DELAY ); } void Interface::AdventureMap::EventSwitchFocusedHero( const int32_t tileIndex ) { Heroes * selectedHero = world.getTile( tileIndex ).getHero(); if ( selectedHero == nullptr || selectedHero == GetFocusHeroes() || selectedHero->GetColor() != Settings::Get().GetPlayers().getCurrentColor() ) { return; } SetFocus( selectedHero, false ); RedrawFocus(); } void Interface::AdventureMap::EventNextHero() { const Kingdom & myKingdom = world.GetKingdom( Settings::Get().CurrentColor() ); const VecHeroes & myHeroes = myKingdom.GetHeroes(); if ( myHeroes.empty() ) { return; } if ( GetFocusHeroes() ) { VecHeroes::const_iterator it = std::find( myHeroes.begin(), myHeroes.end(), GetFocusHeroes() ); VecHeroes::const_iterator currentHero = it; do { ++it; if ( it == myHeroes.end() ) { it = myHeroes.begin(); } if ( ( *it )->MayStillMove( true, false ) ) { SetFocus( *it, false ); break; } } while ( it != currentHero ); } else { for ( Heroes * hero : myHeroes ) { if ( hero->MayStillMove( true, false ) ) { SetFocus( hero, false ); break; } } } RedrawFocus(); } fheroes2::GameMode Interface::AdventureMap::EventHeroMovement() { Heroes * hero = GetFocusHeroes(); if ( hero ) { if ( hero->GetPath().isValidForMovement() && hero->MayStillMove( false, true ) ) { _startHeroMove( *hero ); } else if ( MP2::isInGameActionObject( hero->getObjectTypeUnderHero(), hero->isShipMaster() ) ) { return EventDefaultAction(); } else if ( hero->GetPath().isValidForMovement() ) { fheroes2::showStandardTextMessage( "Hero Movement Points", "The hero's army cannot move anymore today. The movement points will be refilled tomorrow after you end your turn.", Dialog::OK ); } } return fheroes2::GameMode::CANCEL; } void Interface::AdventureMap::EventResetHeroPath() { Heroes * hero = GetFocusHeroes(); if ( hero == nullptr ) { return; } hero->GetPath().Reset(); setRedraw( REDRAW_GAMEAREA | REDRAW_BUTTONS ); } void Interface::AdventureMap::EventKingdomInfo() const { Kingdom & myKingdom = world.GetKingdom( Settings::Get().CurrentColor() ); myKingdom.openOverviewDialog(); _iconsPanel.setRedraw(); } void Interface::AdventureMap::EventCastSpell() { Heroes * hero = GetFocusHeroes(); if ( hero == nullptr ) { return; } // Center on the hero before opening the spell book _gameArea.SetCenter( hero->GetCenter() ); redraw( REDRAW_GAMEAREA | REDRAW_RADAR_CURSOR ); const Spell spell = hero->OpenSpellBook( SpellBook::Filter::ADVN, true, false, {} ); if ( !spell.isValid() ) { return; } hero->ActionSpellCast( spell ); // The spell will consume the hero's spell points (and perhaps also movement points) and can move the // hero to another location, so we may have to update the terrain music theme and environment sounds ResetFocus( GameFocus::HEROES, true ); RedrawFocus(); } fheroes2::GameMode Interface::AdventureMap::EventEndTurn() const { #ifndef NDEBUG const Heroes * focusedHero = GetFocusHeroes(); #endif assert( focusedHero == nullptr || !focusedHero->Modes( Heroes::ENABLEMOVE ) ); const Kingdom & myKingdom = world.GetKingdom( Settings::Get().CurrentColor() ); if ( !myKingdom.HeroesMayStillMove() || Dialog::YES == fheroes2::showStandardTextMessage( _( "End Turn" ), _( "One or more heroes may still move, are you sure you want to end your turn?" ), Dialog::YES | Dialog::NO ) ) { return fheroes2::GameMode::END_TURN; } return fheroes2::GameMode::CANCEL; } fheroes2::GameMode Interface::AdventureMap::EventAdventureDialog() { switch ( Dialog::AdventureOptions( GameFocus::HEROES == GetFocusType() ) ) { case Dialog::WORLD: EventViewWorld(); break; case Dialog::PUZZLE: EventPuzzleMaps(); break; case Dialog::INFO: return EventScenarioInformation(); case Dialog::DIG: return EventDigArtifact(); default: break; } return fheroes2::GameMode::CANCEL; } void Interface::AdventureMap::EventViewWorld() { ViewWorld::ViewWorldWindow( Settings::Get().CurrentColor(), ViewWorldMode::OnlyVisible, *this ); } fheroes2::GameMode Interface::AdventureMap::EventFileDialog() const { return Dialog::FileOptions(); } void Interface::AdventureMap::EventSystemDialog() const { fheroes2::showSystemOptionsDialog(); } fheroes2::GameMode Interface::BaseInterface::EventExit() { if ( Dialog::YES & fheroes2::showStandardTextMessage( _( "Quit" ), _( "Are you sure you want to quit?" ), Dialog::YES | Dialog::NO ) ) return fheroes2::GameMode::QUIT_GAME; return fheroes2::GameMode::CANCEL; } void Interface::AdventureMap::EventNextTown() { Kingdom & myKingdom = world.GetKingdom( Settings::Get().CurrentColor() ); VecCastles & myCastles = myKingdom.GetCastles(); if ( !myCastles.empty() ) { if ( GetFocusCastle() ) { VecCastles::const_iterator it = std::find( myCastles.begin(), myCastles.end(), GetFocusCastle() ); ++it; if ( it == myCastles.end() ) it = myCastles.begin(); SetFocus( *it ); } else ResetFocus( GameFocus::CASTLE, false ); RedrawFocus(); } } fheroes2::GameMode Interface::AdventureMap::EventNewGame() const { return Dialog::YES == fheroes2::showStandardTextMessage( "", _( "Are you sure you want to restart? (Your current game will be lost.)" ), Dialog::YES | Dialog::NO ) ? fheroes2::GameMode::NEW_GAME : fheroes2::GameMode::CANCEL; } fheroes2::GameMode Interface::AdventureMap::EventSaveGame() const { while ( true ) { const std::string filename = Dialog::SelectFileSave(); if ( filename.empty() ) { return fheroes2::GameMode::CANCEL; } if ( System::IsFile( filename ) && Dialog::NO == fheroes2::showStandardTextMessage( "", _( "Are you sure you want to overwrite the save with this name?" ), Dialog::YES | Dialog::NO ) ) { continue; } if ( Game::Save( filename ) ) { fheroes2::showStandardTextMessage( "", _( "Game saved successfully." ), Dialog::OK ); } else { fheroes2::showStandardTextMessage( "", _( "There was an issue during saving." ), Dialog::OK ); } return fheroes2::GameMode::CANCEL; } } fheroes2::GameMode Interface::AdventureMap::EventLoadGame() const { return Dialog::YES == fheroes2::showStandardTextMessage( "", _( "Are you sure you want to load a new game? (Your current game will be lost.)" ), Dialog::YES | Dialog::NO ) ? fheroes2::GameMode::LOAD_GAME : fheroes2::GameMode::CANCEL; } void Interface::AdventureMap::EventPuzzleMaps() const { world.GetKingdom( Settings::Get().CurrentColor() ).PuzzleMaps().ShowMapsDialog(); } fheroes2::GameMode Interface::AdventureMap::EventScenarioInformation() { if ( Settings::Get().isCampaignGameType() ) { fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::ImageRestorer saver( display, 0, 0, display.width(), display.height() ); // We are opening campaign scenario info. It is a full screen image change. So do fade-out and set the fade-in. fheroes2::fadeOutDisplay(); Game::setDisplayFadeIn(); AudioManager::ResetAudio(); const fheroes2::GameMode returnMode = Game::SelectCampaignScenario( fheroes2::GameMode::CANCEL, true ); if ( returnMode == fheroes2::GameMode::CANCEL ) { // We are going back to the Adventure map with fade-in. Game::setDisplayFadeIn(); saver.restore(); Game::restoreSoundsForCurrentFocus(); } else { saver.reset(); } return returnMode; } Dialog::GameInfo(); return fheroes2::GameMode::CANCEL; } void Interface::AdventureMap::EventSwitchHeroSleeping() { Heroes * hero = GetFocusHeroes(); if ( hero ) { hero->Modes( Heroes::SLEEPER ) ? hero->ResetModes( Heroes::SLEEPER ) : hero->SetModes( Heroes::SLEEPER ); setRedraw( REDRAW_HEROES ); _buttonsPanel.setRedraw(); } } fheroes2::GameMode Interface::AdventureMap::EventDigArtifact() { Heroes * hero = GetFocusHeroes(); if ( hero == nullptr ) { // TODO: verify how this method can be called if a hero is not selected. return fheroes2::GameMode::CANCEL; } if ( hero->isShipMaster() ) { fheroes2::showStandardTextMessage( "", _( "Try looking on land!!!" ), Dialog::OK ); return fheroes2::GameMode::CANCEL; } if ( hero->GetBagArtifacts().isFull() ) { fheroes2::showStandardTextMessage( "", _( "Searching for the Ultimate Artifact is fruitless. Your hero could not carry it even if he found it - all his artifact slots are full." ), Dialog::OK ); return fheroes2::GameMode::CANCEL; } if ( hero->GetMaxMovePoints() > hero->GetMovePoints() ) { fheroes2::showStandardTextMessage( "", _( "Digging for artifacts requires a whole day, try again tomorrow." ), Dialog::OK ); return fheroes2::GameMode::CANCEL; } // Original Editor allows to put an Ultimate Artifact on an invalid tile. So checking tile index solves this issue. const UltimateArtifact & ultimateArtifact = world.GetUltimateArtifact(); if ( world.getTile( hero->GetIndex() ).GoodForUltimateArtifact() || ( ultimateArtifact.getPosition() == hero->GetIndex() && !ultimateArtifact.isFound() ) ) { AudioManager::PlaySound( M82::DIGSOUND ); hero->ResetMovePoints(); hero->GetPath().Reset(); if ( world.DiggingForUltimateArtifact( hero->GetCenter() ) ) { const AudioManager::MusicRestorer musicRestorer; if ( Settings::Get().MusicMIDI() ) { AudioManager::PlaySound( M82::TREASURE ); } else { AudioManager::PlayMusic( MUS::ULTIMATE_ARTIFACT, Music::PlaybackMode::PLAY_ONCE ); } const Artifact & ultimate = ultimateArtifact.GetArtifact(); if ( !hero->PickupArtifact( ultimate ) ) { assert( 0 ); } std::string msg( _( "After spending many hours digging here, you have uncovered the %{artifact}." ) ); StringReplace( msg, "%{artifact}", ultimate.GetName() ); const fheroes2::ArtifactDialogElement artifactUI( ultimate.GetID() ); fheroes2::showStandardTextMessage( _( "Congratulations!" ), std::move( msg ), Dialog::OK, { &artifactUI } ); } else { fheroes2::showStandardTextMessage( "", _( "Nothing here. Where could it be?" ), Dialog::OK ); } redraw( REDRAW_HEROES | REDRAW_BUTTONS ); fheroes2::Display::instance().render(); // check if the game is over due to conditions related to the ultimate artifact return GameOver::Result::Get().checkGameOver(); } fheroes2::showStandardTextMessage( "", _( "Try searching on clear ground." ), Dialog::OK ); return fheroes2::GameMode::CANCEL; } fheroes2::GameMode Interface::AdventureMap::EventDefaultAction() { Heroes * hero = GetFocusHeroes(); if ( hero ) { if ( MP2::isInGameActionObject( hero->getObjectTypeUnderHero(), hero->isShipMaster() ) ) { hero->Action( hero->GetIndex() ); // The action object can alter the status of the hero (e.g. Stables or Well) or // move it to another location (e.g. Stone Liths or Whirlpool) ResetFocus( GameFocus::HEROES, true ); RedrawFocus(); // If the hero has performed an action, we have to check the completion condition // of the scenario if ( hero->isAction() ) { hero->ResetAction(); return GameOver::Result::Get().checkGameOver(); } } } else if ( GetFocusCastle() ) { Game::OpenCastleDialog( *GetFocusCastle() ); } return fheroes2::GameMode::CANCEL; } void Interface::AdventureMap::EventOpenFocus() const { if ( GetFocusHeroes() ) Game::OpenHeroesDialog( *GetFocusHeroes(), true, true ); else if ( GetFocusCastle() ) Game::OpenCastleDialog( *GetFocusCastle() ); } void Interface::AdventureMap::EventSwitchShowRadar() const { Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() ) { if ( conf.ShowRadar() ) { conf.SetShowRadar( false ); _gameArea.SetRedraw(); } else { conf.SetShowRadar( true ); _radar.SetRedraw( REDRAW_RADAR ); } } } void Interface::AdventureMap::EventSwitchShowButtons() const { Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() ) { if ( conf.ShowButtons() ) { conf.SetShowButtons( false ); _gameArea.SetRedraw(); } else { conf.SetShowButtons( true ); _buttonsPanel.setRedraw(); } } } void Interface::AdventureMap::EventSwitchShowStatus() const { Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() ) { if ( conf.ShowStatus() ) { conf.SetShowStatus( false ); _gameArea.SetRedraw(); } else { conf.SetShowStatus( true ); _statusPanel.setRedraw(); } } } void Interface::AdventureMap::EventSwitchShowIcons() const { Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() ) { if ( conf.ShowIcons() ) { conf.SetShowIcons( false ); _gameArea.SetRedraw(); } else { conf.SetShowIcons( true ); _iconsPanel.setRedraw(); } } } void Interface::AdventureMap::EventSwitchShowControlPanel() const { Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() ) { conf.SetShowControlPanel( !conf.ShowControlPanel() ); _gameArea.SetRedraw(); } } void Interface::AdventureMap::EventKeyArrowPress( int dir ) { Heroes * hero = GetFocusHeroes(); // move hero if ( hero ) MoveHeroFromArrowKeys( *hero, dir ); else // scroll map switch ( dir ) { case Direction::TOP_LEFT: _gameArea.SetScroll( SCROLL_TOP ); _gameArea.SetScroll( SCROLL_LEFT ); break; case Direction::TOP: _gameArea.SetScroll( SCROLL_TOP ); break; case Direction::TOP_RIGHT: _gameArea.SetScroll( SCROLL_TOP ); _gameArea.SetScroll( SCROLL_RIGHT ); break; case Direction::RIGHT: _gameArea.SetScroll( SCROLL_RIGHT ); break; case Direction::BOTTOM_RIGHT: _gameArea.SetScroll( SCROLL_BOTTOM ); _gameArea.SetScroll( SCROLL_RIGHT ); break; case Direction::BOTTOM: _gameArea.SetScroll( SCROLL_BOTTOM ); break; case Direction::BOTTOM_LEFT: _gameArea.SetScroll( SCROLL_BOTTOM ); _gameArea.SetScroll( SCROLL_LEFT ); break; case Direction::LEFT: _gameArea.SetScroll( SCROLL_LEFT ); break; default: break; } } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_focus.cpp000066400000000000000000000236251476115357100231300ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include "audio.h" #include "audio_manager.h" #include "castle.h" #include "game.h" #include "game_interface.h" // IWYU pragma: associated #include "heroes.h" #include "interface_base.h" #include "interface_gamearea.h" #include "interface_icons.h" #include "interface_status.h" #include "kingdom.h" #include "maps_tiles.h" #include "mus.h" #include "players.h" #include "settings.h" #include "world.h" void Interface::AdventureMap::SetFocus( Heroes * hero, const bool retainScrollBarPosition ) { assert( hero != nullptr ); Player * player = Settings::Get().GetPlayers().GetCurrent(); if ( player == nullptr ) { return; } #ifndef NDEBUG #if defined( WITH_DEBUG ) const bool isAIAutoControlMode = player->isAIAutoControlMode(); #else const bool isAIAutoControlMode = false; #endif // WITH_DEBUG #endif // !NDEBUG assert( player->GetColor() == hero->GetColor() && ( player->isControlHuman() || ( player->isControlAI() && isAIAutoControlMode ) ) ); Focus & focus = player->GetFocus(); Heroes * focusedHero = focus.GetHeroes(); if ( focusedHero && focusedHero != hero ) { // Focus has been changed to another hero. Hide the path of the previous hero. focusedHero->ShowPath( false ); } // Heroes::calculatePath() uses PlayerWorldPathfinder and should not be used for an AI-controlled hero if ( !hero->isMoveEnabled() && hero->isControlHuman() ) { hero->calculatePath( -1 ); } hero->ShowPath( true ); focus.Set( hero ); setRedraw( REDRAW_BUTTONS ); if ( !retainScrollBarPosition ) { _iconsPanel.select( hero ); } _gameArea.SetCenter( hero->GetCenter() ); _statusPanel.SetState( StatusType::STATUS_ARMY ); const int heroIndex = hero->GetIndex(); if ( Game::UpdateSoundsOnFocusUpdate() && heroIndex >= 0 ) { Game::EnvironmentSoundMixer(); AudioManager::PlayMusicAsync( MUS::FromGround( world.getTile( heroIndex ).GetGround() ), Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); } } void Interface::AdventureMap::SetFocus( Castle * castle ) { assert( castle != nullptr ); Player * player = Settings::Get().GetPlayers().GetCurrent(); if ( player == nullptr ) { return; } #ifndef NDEBUG #if defined( WITH_DEBUG ) const bool isAIAutoControlMode = player->isAIAutoControlMode(); #else const bool isAIAutoControlMode = false; #endif // WITH_DEBUG #endif // !NDEBUG assert( player->GetColor() == castle->GetColor() && ( player->isControlHuman() || ( player->isControlAI() && isAIAutoControlMode ) ) ); Focus & focus = player->GetFocus(); Heroes * focusedHero = focus.GetHeroes(); if ( focusedHero ) { focusedHero->ShowPath( false ); } focus.Set( castle ); setRedraw( REDRAW_BUTTONS ); _iconsPanel.select( castle ); _gameArea.SetCenter( castle->GetCenter() ); _statusPanel.SetState( StatusType::STATUS_FUNDS ); if ( Game::UpdateSoundsOnFocusUpdate() ) { Game::EnvironmentSoundMixer(); AudioManager::PlayMusicAsync( MUS::FromGround( world.getTile( castle->GetIndex() ).GetGround() ), Music::PlaybackMode::RESUME_AND_PLAY_INFINITE ); } } void Interface::AdventureMap::updateFocus() { Player * player = Settings::Get().GetPlayers().GetCurrent(); if ( player == nullptr ) { return; } const Focus & focus = player->GetFocus(); if ( focus.first == FOCUS_CASTLE ) { Castle * castle = GetFocusCastle(); if ( castle != nullptr ) { SetFocus( castle ); } } else if ( focus.first == FOCUS_HEROES ) { Heroes * hero = GetFocusHeroes(); if ( hero != nullptr ) { SetFocus( hero, false ); } } } void Interface::AdventureMap::ResetFocus( const int priority, const bool retainScrollBarPosition ) { Player * player = Settings::Get().GetPlayers().GetCurrent(); if ( player == nullptr ) { return; } Focus & focus = player->GetFocus(); Kingdom & myKingdom = world.GetKingdom( player->GetColor() ); if ( !retainScrollBarPosition ) { _iconsPanel.resetIcons( ICON_ANY ); } switch ( priority ) { case GameFocus::FIRSTHERO: { const VecHeroes & heroes = myKingdom.GetHeroes(); // Find first hero excluding sleeping ones. const VecHeroes::const_iterator it = std::find_if( heroes.begin(), heroes.end(), []( const Heroes * hero ) { return !hero->Modes( Heroes::SLEEPER ); } ); if ( it != heroes.end() ) { SetFocus( *it, false ); } else { // There are no non-sleeping heroes. Focus on the castle instead. ResetFocus( GameFocus::CASTLE, retainScrollBarPosition ); } break; } case GameFocus::HEROES: if ( Heroes * hero = focus.GetHeroes(); ( hero != nullptr ) && ( hero->GetColor() == player->GetColor() ) ) { // Set focus on the previously focused hero. SetFocus( hero, retainScrollBarPosition ); } else if ( !myKingdom.GetHeroes().empty() ) { // Reset scrollbar here because the current focused hero might have // lost a battle and is not in the heroes list anymore. _iconsPanel.resetIcons( ICON_HEROES ); SetFocus( myKingdom.GetHeroes().front(), false ); } else if ( !myKingdom.GetCastles().empty() ) { // There are no heroes left in the kingdom. Reset the heroes scrollbar and focus on the first castle. _iconsPanel.setRedraw( ICON_HEROES ); SetFocus( myKingdom.GetCastles().front() ); } else { focus.Reset(); } break; case GameFocus::CASTLE: if ( Castle * castle = focus.GetCastle(); ( castle != nullptr ) && ( castle->GetColor() == player->GetColor() ) ) { // Focus on the previously focused castle. SetFocus( castle ); } else if ( !myKingdom.GetCastles().empty() ) { // The previously focused castle is lost, so we update the castles scrollbar. _iconsPanel.resetIcons( ICON_CASTLES ); SetFocus( myKingdom.GetCastles().front() ); } else if ( !myKingdom.GetHeroes().empty() ) { // There are no castles left in the kingdom. Reset the castles scrollbar and focus on the first hero. _iconsPanel.setRedraw( ICON_CASTLES ); SetFocus( myKingdom.GetHeroes().front(), false ); } else { focus.Reset(); } break; default: focus.Reset(); break; } } int Interface::GetFocusType() { Player * player = Settings::Get().GetPlayers().GetCurrent(); if ( player ) { Focus & focus = player->GetFocus(); if ( focus.GetHeroes() ) { return GameFocus::HEROES; } if ( focus.GetCastle() ) { return GameFocus::CASTLE; } } return GameFocus::UNSEL; } Castle * Interface::GetFocusCastle() { Player * player = Settings::Get().GetPlayers().GetCurrent(); return player ? player->GetFocus().GetCastle() : nullptr; } Heroes * Interface::GetFocusHeroes() { Player * player = Settings::Get().GetPlayers().GetCurrent(); return player ? player->GetFocus().GetHeroes() : nullptr; } void Interface::AdventureMap::RedrawFocus() { const int type = GetFocusType(); if ( type != FOCUS_HEROES && _iconsPanel.isSelected( ICON_HEROES ) ) { _iconsPanel.resetIcons( ICON_HEROES ); _iconsPanel.setRedraw(); } else if ( type == FOCUS_HEROES && !_iconsPanel.isSelected( ICON_HEROES ) ) { _iconsPanel.select( GetFocusHeroes() ); _iconsPanel.setRedraw(); } if ( type != FOCUS_CASTLE && _iconsPanel.isSelected( ICON_CASTLES ) ) { _iconsPanel.resetIcons( ICON_CASTLES ); _iconsPanel.setRedraw(); } else if ( type == FOCUS_CASTLE && !_iconsPanel.isSelected( ICON_CASTLES ) ) { _iconsPanel.select( GetFocusCastle() ); _iconsPanel.setRedraw(); } setRedraw( REDRAW_GAMEAREA | REDRAW_RADAR_CURSOR ); if ( type == FOCUS_HEROES ) { _iconsPanel.setRedraw( ICON_HEROES ); } else if ( type == FOCUS_CASTLE ) { _iconsPanel.setRedraw( ICON_CASTLES ); } _statusPanel.setRedraw(); } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_gamearea.cpp000066400000000000000000001421521476115357100235500ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_gamearea.h" #include #include #include #include #include #include #include #include #include "agg_image.h" #include "castle.h" #include "cursor.h" #include "direction.h" #include "game_delays.h" #include "game_interface.h" #include "ground.h" #include "heroes.h" #include "icn.h" #include "interface_base.h" #include "interface_cpanel.h" #include "localevent.h" #include "logging.h" #include "maps.h" #include "maps_tiles.h" #include "maps_tiles_helper.h" #include "maps_tiles_render.h" #include "pal.h" #include "players.h" #include "route.h" #include "screen.h" #include "settings.h" #include "skill.h" #include "ui_constants.h" #include "ui_object_rendering.h" #include "world.h" namespace { const int32_t minimalRequiredDraggingMovement = 10; static_assert( std::is_trivially_copyable::value, "This class is not trivially copyable anymore. Add std::move where required." ); struct TileUnfitRenderObjectInfo { std::map> bottomImages; std::map> bottomBackgroundImages; std::map> topImages; std::map> lowPriorityBottomImages; std::map> highPriorityBottomImages; std::map> heroBackgroundImages; std::map> shadowImages; }; void populateStaticTileUnfitObjectInfo( TileUnfitRenderObjectInfo & tileUnfit, std::vector & imageInfo, std::vector & shadowInfo, const fheroes2::Point & offset, const uint8_t alphaValue ) { for ( auto & objectInfo : imageInfo ) { const fheroes2::Point imagePos = objectInfo.tileOffset; objectInfo.alphaValue = alphaValue; if ( imagePos.y > 0 ) { if ( imagePos.x < 0 ) { tileUnfit.bottomBackgroundImages[imagePos + offset].emplace_front( objectInfo ); } else { tileUnfit.bottomBackgroundImages[imagePos + offset].emplace_back( objectInfo ); } } else if ( imagePos.y == 0 ) { if ( imagePos.x < 0 ) { tileUnfit.bottomImages[imagePos + offset].emplace_front( objectInfo ); } else { tileUnfit.bottomImages[imagePos + offset].emplace_back( objectInfo ); } } else { if ( imagePos.x < 0 ) { tileUnfit.topImages[imagePos + offset].emplace_front( objectInfo ); } else { tileUnfit.topImages[imagePos + offset].emplace_back( objectInfo ); } } } // Static object's shadows are always on the same layer. for ( auto & objectInfo : shadowInfo ) { const fheroes2::Point imagePos = objectInfo.tileOffset + offset; // Shadows outside the game area should not be rendered (objects cast shadows in top-right direction). if ( imagePos.x < 0 || imagePos.y < 0 ) { continue; } objectInfo.alphaValue = alphaValue; tileUnfit.shadowImages[imagePos].emplace_back( objectInfo ); } } void populateStaticTileUnfitBackgroundObjectInfo( TileUnfitRenderObjectInfo & tileUnfit, std::vector & imageInfo, const fheroes2::Point & offset, const uint8_t alphaValue ) { for ( auto & objectInfo : imageInfo ) { const fheroes2::Point imagePos = objectInfo.tileOffset; objectInfo.alphaValue = alphaValue; if ( imagePos.y > 0 ) { tileUnfit.bottomBackgroundImages[imagePos + offset].emplace_front( objectInfo ); } else if ( imagePos.y == 0 ) { tileUnfit.bottomImages[imagePos + offset].emplace_front( objectInfo ); } else { tileUnfit.topImages[imagePos + offset].emplace_front( objectInfo ); } } } void populateHeroObjectInfo( TileUnfitRenderObjectInfo & tileUnfit, const Heroes * hero ) { assert( hero != nullptr ); const fheroes2::Point & heroPos = hero->GetCenter(); fheroes2::Point nextHeroPos = heroPos; const bool movingHero = hero->isMoveEnabled(); if ( movingHero ) { const Route::Path & path = hero->GetPath(); assert( !path.empty() ); nextHeroPos = Maps::GetPoint( Maps::GetDirectionIndex( hero->GetIndex(), path.GetFrontDirection() ) ); } // A castle's road south from a castle should actually be level 3 but it is level 2 causing a hero's horse legs to be truncated. // In order to render the legs properly we need to make the bottom part of the hero's sprite to be rendered after castle's road. // This happens only when a hero stands in a castle. const Castle * castle = world.getCastleEntrance( heroPos ); const bool isHeroInCastle = ( castle != nullptr && castle->GetCenter() == heroPos ); const uint8_t heroAlphaValue = hero->getAlphaValue(); const int32_t worldHeight = world.h(); auto spriteInfo = Maps::getHeroSpritesPerTile( *hero ); auto spriteShadowInfo = Maps::getHeroShadowSpritesPerTile( *hero ); for ( auto & objectInfo : spriteInfo ) { const fheroes2::Point imagePos = objectInfo.tileOffset; objectInfo.alphaValue = heroAlphaValue; if ( movingHero && imagePos.y == 0 ) { if ( nextHeroPos.y > heroPos.y && nextHeroPos.x > heroPos.x && imagePos.x > 0 ) { // The hero moves south-east. We need to render it over everything. tileUnfit.highPriorityBottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } if ( nextHeroPos.y > heroPos.y && nextHeroPos.x < heroPos.x && imagePos.x < 0 ) { // The hero moves south-west. We need to render it over everything. tileUnfit.highPriorityBottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } if ( nextHeroPos.y < heroPos.y && nextHeroPos.x < heroPos.x && imagePos.x < 0 ) { // The hero moves north-west. We need to render it under all other objects. tileUnfit.lowPriorityBottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } if ( nextHeroPos.y < heroPos.y && nextHeroPos.x > heroPos.x && imagePos.x > 0 ) { // The hero moves north-east. We need to render it under all other objects. tileUnfit.lowPriorityBottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } } if ( movingHero && imagePos.y == 1 ) { if ( nextHeroPos.y > heroPos.y && nextHeroPos.x > heroPos.x && imagePos.x > 0 ) { // The hero moves south-east. We need to render it over everything. tileUnfit.bottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } if ( nextHeroPos.y > heroPos.y && nextHeroPos.x < heroPos.x && imagePos.x < 0 ) { // The hero moves south-west. We need to render it over everything. tileUnfit.bottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } } if ( movingHero && imagePos.y == -1 ) { if ( nextHeroPos.y < heroPos.y && nextHeroPos.x < heroPos.x && imagePos.x < 0 ) { // The hero moves north-west. We need to render it under all other objects. tileUnfit.bottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } if ( nextHeroPos.y < heroPos.y && nextHeroPos.x > heroPos.x && imagePos.x > 0 ) { // The hero moves north-east. We need to render it under all other objects. tileUnfit.bottomImages[imagePos + heroPos].emplace_back( objectInfo ); continue; } } if ( imagePos.y > 0 && !isHeroInCastle ) { // Hero horse or boat should not be rendered over the bottom map border. if ( ( heroPos.y + imagePos.y ) >= worldHeight ) { continue; } // The very bottom part of hero (or hero on boat) image should not be rendered before it's shadow so we place it in the extra deque. if ( imagePos.x < 0 ) { tileUnfit.heroBackgroundImages[imagePos + heroPos].emplace_front( objectInfo ); } else { tileUnfit.heroBackgroundImages[imagePos + heroPos].emplace_back( objectInfo ); } } else if ( imagePos.y == 0 || ( isHeroInCastle && imagePos.y > 0 ) ) { if ( imagePos.x < 0 ) { tileUnfit.bottomImages[imagePos + heroPos].emplace_front( objectInfo ); } else { tileUnfit.bottomImages[imagePos + heroPos].emplace_back( objectInfo ); } } else { if ( imagePos.x < 0 ) { tileUnfit.topImages[imagePos + heroPos].emplace_front( objectInfo ); } else { tileUnfit.topImages[imagePos + heroPos].emplace_back( objectInfo ); } } } for ( auto & objectInfo : spriteShadowInfo ) { const fheroes2::Point imagePos = objectInfo.tileOffset + heroPos; // Shadows outside the game area should not be rendered. if ( imagePos.x < 0 || imagePos.y < 0 || imagePos.y >= worldHeight ) { continue; } objectInfo.alphaValue = heroAlphaValue; tileUnfit.shadowImages[imagePos].emplace_back( objectInfo ); } } void renderImagesOnTiles( fheroes2::Image & output, const std::map> & images, const Interface::GameArea & area ) { for ( const auto & [offset, imgInfo] : images ) { for ( const auto & info : imgInfo ) { area.BlitOnTile( output, fheroes2::AGG::GetICN( info.icnId, info.icnIndex ), info.area, info.imageOffset.x, info.imageOffset.y, offset, info.isFlipped, info.alphaValue ); } } } bool isTallTopLayerObject( const int32_t x, const int32_t y, const uint32_t uid ) { if ( y + 1 >= world.h() ) { // There is nothing below so it's not a tall object. return false; } // There is a tile below the current. const Maps::Tile & tileBelow = world.getTile( x, y + 1 ); for ( const auto & lowerPart : tileBelow.getTopObjectParts() ) { if ( lowerPart._uid == uid ) { // This is a tall object. return true; } } return false; } } Interface::GameArea::GameArea( BaseInterface & interface ) : _interface( interface ) , _minLeftOffset( 0 ) , _maxLeftOffset( 0 ) , _minTopOffset( 0 ) , _maxTopOffset( 0 ) , _prevIndexPos( 0 ) , scrollDirection( 0 ) , updateCursor( false ) , _mouseDraggingInitiated( false ) , _mouseDraggingMovement( false ) , _needRedrawByMouseDragging( false ) , _isFastScrollEnabled( false ) , _resetMousePositionForFastScroll( false ) { // Do nothing. } void Interface::GameArea::generate( const fheroes2::Size & screenSize, const bool withoutBorders ) { if ( withoutBorders ) SetAreaPosition( 0, 0, screenSize.width, screenSize.height ); else SetAreaPosition( fheroes2::borderWidthPx, fheroes2::borderWidthPx, screenSize.width - fheroes2::radarWidthPx - 3 * fheroes2::borderWidthPx, screenSize.height - 2 * fheroes2::borderWidthPx ); } void Interface::GameArea::SetAreaPosition( int32_t x, int32_t y, int32_t w, int32_t h ) { _windowROI = { x, y, w, h }; const fheroes2::Size worldSize( world.w() * fheroes2::tileWidthPx, world.h() * fheroes2::tileWidthPx ); if ( worldSize.width > w ) { _minLeftOffset = -( w / 2 ) - fheroes2::tileWidthPx / 2; _maxLeftOffset = worldSize.width - w / 2; } else { _minLeftOffset = -( w - worldSize.width ) / 2; _maxLeftOffset = _minLeftOffset; } if ( worldSize.height > h ) { _minTopOffset = -( h / 2 ) - fheroes2::tileWidthPx / 2; _maxTopOffset = worldSize.height - h / 2; } else { _minTopOffset = -( h - worldSize.height ) / 2; _maxTopOffset = _minTopOffset; } // adding 1 extra tile for both axes in case of drawing tiles partially near sides _visibleTileCount = { ( w + fheroes2::tileWidthPx - 1 ) / fheroes2::tileWidthPx + 1, ( h + fheroes2::tileWidthPx - 1 ) / fheroes2::tileWidthPx + 1 }; _setCenterToTile( fheroes2::Point( world.w() / 2, world.h() / 2 ) ); } void Interface::GameArea::BlitOnTile( fheroes2::Image & dst, const fheroes2::Image & src, int32_t ox, int32_t oy, const fheroes2::Point & mp, bool flip, uint8_t alpha ) const { const fheroes2::Point tileOffset = GetRelativeTilePosition( mp ); const fheroes2::Rect imageRoi{ tileOffset.x + ox, tileOffset.y + oy, src.width(), src.height() }; const fheroes2::Rect overlappedRoi = _windowROI ^ imageRoi; fheroes2::AlphaBlit( src, overlappedRoi.x - imageRoi.x, overlappedRoi.y - imageRoi.y, dst, overlappedRoi.x, overlappedRoi.y, overlappedRoi.width, overlappedRoi.height, alpha, flip ); } void Interface::GameArea::BlitOnTile( fheroes2::Image & dst, const fheroes2::Image & src, const fheroes2::Rect & srcRoi, int32_t ox, int32_t oy, const fheroes2::Point & mp, bool flip, uint8_t alpha ) const { const fheroes2::Point tileOffset = GetRelativeTilePosition( mp ); const fheroes2::Rect imageRoi{ tileOffset.x + ox, tileOffset.y + oy, srcRoi.width, srcRoi.height }; const fheroes2::Rect overlappedRoi = _windowROI ^ imageRoi; fheroes2::AlphaBlit( src, srcRoi.x + overlappedRoi.x - imageRoi.x, srcRoi.y + overlappedRoi.y - imageRoi.y, dst, overlappedRoi.x, overlappedRoi.y, overlappedRoi.width, overlappedRoi.height, alpha, flip ); } void Interface::GameArea::DrawTile( fheroes2::Image & dst, const fheroes2::Image & src, const fheroes2::Point & mp ) const { const fheroes2::Point tileOffset = GetRelativeTilePosition( mp ); const fheroes2::Rect imageRoi{ tileOffset.x, tileOffset.y, src.width(), src.height() }; const fheroes2::Rect overlappedRoi = _windowROI ^ imageRoi; fheroes2::Copy( src, overlappedRoi.x - imageRoi.x, overlappedRoi.y - imageRoi.y, dst, overlappedRoi.x, overlappedRoi.y, overlappedRoi.width, overlappedRoi.height ); } void Interface::GameArea::Redraw( fheroes2::Image & dst, int flag, bool isPuzzleDraw ) const { const fheroes2::Rect & tileROI = GetVisibleTileROI(); int32_t minX = tileROI.x; int32_t minY = tileROI.y; int32_t maxX = tileROI.x + tileROI.width; int32_t maxY = tileROI.y + tileROI.height; #ifdef WITH_DEBUG const bool renderFog = ( ( flag & LEVEL_FOG ) == LEVEL_FOG ) && !IS_DEVEL(); #else const bool renderFog = ( flag & LEVEL_FOG ) == LEVEL_FOG; #endif // Render terrain. for ( int32_t y = 0; y < tileROI.height; ++y ) { fheroes2::Point offset( tileROI.x, tileROI.y + y ); if ( offset.y < 0 || offset.y >= world.h() ) { for ( ; offset.x < maxX; ++offset.x ) { Maps::redrawEmptyTile( dst, offset, *this ); } } else { for ( ; offset.x < maxX; ++offset.x ) { if ( offset.x < 0 || offset.x >= world.w() ) { Maps::redrawEmptyTile( dst, offset, *this ); } else { const Maps::Tile & tile = world.getTile( offset.x, offset.y ); // Do not render terrain on the tiles fully covered with the fog. if ( tile.getFogDirection() != DIRECTION_ALL || !renderFog ) { DrawTile( dst, getTileSurface( tile ), offset ); } } } } } minX = std::max( minX, 0 ); minY = std::max( minY, 0 ); maxX = std::min( maxX, world.w() ); maxY = std::min( maxY, world.h() ); if ( minX >= maxX || minY >= maxY ) { // This can't be true! Please check your code changes as we shouldn't have an empty area. assert( 0 ); return; } // Each tile can contain multiple object parts or sprites. Each object part has its own level or in other words layer of rendering. // We need to use a correct order of levels to render objects on tiles. The levels are: // 0 - main and action objects like mines, forest, castle and etc. // 1 - background objects like lakes or bushes. // 2 - shadows and some special objects like castle's entrance road. // 3 - roads, water flaws and cracks. Essentially everything what is a part of terrain. // The correct order of levels is 3 --> 1 --> 2 --> 0. // // There are also two groups of objects: ground objects (bottom layer) and high objects (top layer). High objects are the parts of the objects which are taller than // 1 tile. For example, a castle. All ground objects are drawn first. // // However, there are some objects which appear to be more than 1 tile (32 x 32 pixels) size such as heroes, monsters and boats. // To render all these 'special' objects we need to create a copy of object sprite stacks for each tile, add temporary extra sprites and render them. // Let's call these objects as tile-unfit objects, the rest of objects will be called tile-fit objects. // Fading animation can be applied as for tile-fit and tile-unfit objects. // In case of tile-fit objects we need to pass UID of the object and alpha values. // In case of tile-unfit objects we need to pass tile ID and set alpha value while creating RenderObjectInfo instances. const bool drawHeroes = ( flag & LEVEL_HEROES ) == LEVEL_HEROES; TileUnfitRenderObjectInfo tileUnfit; // TODO: Dragon City with Object ICN Type OBJ_ICN_TYPE_OBJNMUL2 and object index 46 is a bottom layer sprite. // TODO: When a hero standing besides this turns a part of the hero is visible. This can be fixed only by some hack. // Run through all visible tiles and find all tile-unfit objects. // Also cover extra tiles from right and bottom sides because these objects are usually bigger than 1x1 tiles. const int32_t roiToRenderMinX = std::max( minX - 1, 0 ); const int32_t roiToRenderMinY = std::max( minY - 1, 0 ); const int32_t roiToRenderMaxX = std::min( maxX + 2, world.w() ); const int32_t roiToRenderMaxY = std::min( maxY + 2, world.h() ); const bool isEditor = _interface.isEditor(); for ( int32_t posY = roiToRenderMinY; posY < roiToRenderMaxY; ++posY ) { for ( int32_t posX = roiToRenderMinX; posX < roiToRenderMaxX; ++posX ) { const Maps::Tile & tile = world.getTile( posX, posY ); MP2::MapObjectType objectType = tile.getMainObjectType(); // We will skip objects which are fully under the fog. const bool isTileUnderFog = ( tile.getFogDirection() == DIRECTION_ALL ) && renderFog; switch ( objectType ) { case MP2::OBJ_HERO: { if ( isEditor ) { const uint8_t alphaValue = getObjectAlphaValue( tile.GetIndex(), MP2::OBJ_HERO ); auto spriteInfo = getEditorHeroSpritesPerTile( tile ); std::vector temp; populateStaticTileUnfitObjectInfo( tileUnfit, spriteInfo, temp, tile.GetCenter(), alphaValue ); continue; } if ( !drawHeroes ) { continue; } const bool isUpperTileUnderFog = ( posY > 0 ) ? ( world.getTile( posX, posY - 1 ).getFogDirection() == DIRECTION_ALL ) : true; const Heroes * hero = tile.getHero(); // Boats are 2 tiles high so for hero on the boat we have to populate info for boat one tile lower than the fog. if ( isTileUnderFog && ( isUpperTileUnderFog || !hero->isShipMaster() ) ) { // AI heroes can go out of fog so we have to render them one step earlier than getting out of fog. if ( hero->isControlAI() ) { const Route::Path & path = hero->GetPath(); // Check if the next AI hero path point will not be seen on map to skip it. if ( path.isValidForMovement() && ( world.getTile( path.GetFrontIndex() ).getFogDirection() == DIRECTION_ALL ) ) { continue; } } else { continue; } } populateHeroObjectInfo( tileUnfit, hero ); // Update object type as it could be an object under the hero. objectType = tile.getMainObjectType( false ); break; } case MP2::OBJ_MONSTER: { if ( isPuzzleDraw || isTileUnderFog ) { continue; } const uint8_t alphaValue = getObjectAlphaValue( tile.GetIndex(), MP2::OBJ_MONSTER ); auto spriteInfo = getMonsterSpritesPerTile( tile, isEditor ); auto spriteShadowInfo = getMonsterShadowSpritesPerTile( tile, isEditor ); populateStaticTileUnfitObjectInfo( tileUnfit, spriteInfo, spriteShadowInfo, tile.GetCenter(), alphaValue ); continue; } case MP2::OBJ_BOAT: { // Boats are 2 tiles high so we have to populate info for boat one tile lower than the fog. const bool isUpperTileUnderFog = ( posY > 0 ) ? ( world.getTile( posX, posY - 1 ).getFogDirection() == DIRECTION_ALL ) : true; if ( !drawHeroes || ( isTileUnderFog && isUpperTileUnderFog ) ) { // Boats can be occupied by heroes so they are considered as the same objects. continue; } const uint8_t alphaValue = getObjectAlphaValue( tile.GetIndex(), MP2::OBJ_BOAT ); auto spriteInfo = getBoatSpritesPerTile( tile ); auto spriteShadowInfo = getBoatShadowSpritesPerTile( tile ); populateStaticTileUnfitObjectInfo( tileUnfit, spriteInfo, spriteShadowInfo, tile.GetCenter(), alphaValue ); continue; } default: break; } // These are parts of original action objects which must be rendered under heroes. if ( objectType == MP2::OBJ_MINE ) { auto spriteInfo = getMineGuardianSpritesPerTile( tile ); if ( !spriteInfo.empty() ) { const uint8_t alphaValue = getObjectAlphaValue( tile.getMainObjectPart()._uid ); populateStaticTileUnfitBackgroundObjectInfo( tileUnfit, spriteInfo, tile.GetCenter(), alphaValue ); } } } } // Render all terrain and background layer object. for ( int32_t y = minY; y < maxY; ++y ) { for ( int32_t x = minX; x < maxX; ++x ) { const Maps::Tile & tile = world.getTile( x, y ); if ( tile.getFogDirection() == DIRECTION_ALL && renderFog ) { continue; } // Draw roads, rivers and cracks. redrawBottomLayerObjects( tile, dst, isPuzzleDraw, *this, Maps::TERRAIN_LAYER ); redrawBottomLayerObjects( tile, dst, isPuzzleDraw, *this, Maps::BACKGROUND_LAYER ); } } // Draw the lower part of tile-unfit object's sprite. renderImagesOnTiles( dst, tileUnfit.bottomBackgroundImages, *this ); for ( int32_t y = minY; y < maxY; ++y ) { for ( int32_t x = minX; x < maxX; ++x ) { const Maps::Tile & tile = world.getTile( x, y ); if ( tile.getFogDirection() == DIRECTION_ALL && renderFog ) { continue; } redrawBottomLayerObjects( tile, dst, isPuzzleDraw, *this, Maps::SHADOW_LAYER ); } } // Draw all shadows from tile-unfit objects. renderImagesOnTiles( dst, tileUnfit.shadowImages, *this ); // Draw the lower part of hero's sprite including boat sprite when it is controlled by hero. renderImagesOnTiles( dst, tileUnfit.heroBackgroundImages, *this ); // Low priority images are drawn before any other object on this tile. renderImagesOnTiles( dst, tileUnfit.lowPriorityBottomImages, *this ); for ( int32_t y = minY; y < maxY; ++y ) { for ( int32_t x = minX; x < maxX; ++x ) { const Maps::Tile & tile = world.getTile( x, y ); if ( tile.getFogDirection() == DIRECTION_ALL && renderFog ) { continue; } // TODO: some action objects have tiles above which are still on bottom layer. These images must be drawn last. redrawBottomLayerObjects( tile, dst, isPuzzleDraw, *this, Maps::OBJECT_LAYER ); } } // Draw middle part of tile-unfit sprites. renderImagesOnTiles( dst, tileUnfit.bottomImages, *this ); // High priority images are drawn after any other object on this tile. renderImagesOnTiles( dst, tileUnfit.highPriorityBottomImages, *this ); std::vector topLayerTallObjects; // Expand ROI to properly render very tall objects (1 tile - left and right; 2 tiles - bottom): Abandoned mine Ghosts, Flag on the Alchemist lab, and others. const int32_t roiExtraObjectsMaxX = std::min( maxX + 1, world.w() ); for ( int32_t y = minY; y < roiToRenderMaxY; ++y ) { for ( int32_t x = roiToRenderMinX; x < roiExtraObjectsMaxX; ++x ) { const Maps::Tile & tile = world.getTile( x, y ); const bool isTileUnderFog = ( tile.getFogDirection() == DIRECTION_ALL ) && renderFog; if ( isTileUnderFog ) { // To correctly render tall extra objects (ghosts over abandoned mine) it is needed to analyze one tile to the bottom direction under fog. const bool isUpperTileUnderFog = ( y > 0 ) ? ( world.getTile( x, y - 1 ).getFogDirection() == DIRECTION_ALL ) : true; if ( isUpperTileUnderFog ) { // If current tile and the bottom one are both under the fog continue; } redrawTopLayerExtraObjects( tile, dst, isPuzzleDraw, *this ); continue; } // Since some objects are taller than 2 tiles their top layer sprites must be drawn at the very end. // For now what we need to do is to run through all level 2 objects and verify that the tile below doesn't have // any other level 2 objects with the same UID. topLayerTallObjects.clear(); for ( const auto & part : tile.getTopObjectParts() ) { if ( isTallTopLayerObject( x, y, part._uid ) ) { topLayerTallObjects.emplace_back( &part ); } else { redrawTopLayerObject( tile, dst, isPuzzleDraw, *this, part ); } } redrawTopLayerExtraObjects( tile, dst, isPuzzleDraw, *this ); for ( const auto * part : topLayerTallObjects ) { redrawTopLayerObject( tile, dst, isPuzzleDraw, *this, *part ); } } } // Draw upper part of tile-unfit sprites. renderImagesOnTiles( dst, tileUnfit.topImages, *this ); // Draw hero's route. It should be drawn on top of everything. const bool drawRoutes = ( flag & LEVEL_ROUTES ) != 0; const Heroes * currentHero = drawHeroes ? GetFocusHeroes() : nullptr; if ( drawRoutes && ( currentHero != nullptr ) && currentHero->GetPath().isShow() ) { const Route::Path & path = currentHero->GetPath(); int32_t greenColorSteps = path.GetAllowedSteps(); const int32_t pathfinding = currentHero->GetLevelSkill( Skill::Secondary::PATHFINDING ); Route::Path::const_iterator currentStep = path.begin(); Route::Path::const_iterator nextStep = currentStep; if ( currentHero->isMoveEnabled() && ( currentHero->GetDirection() == path.GetFrontDirection() ) ) { // Do not draw the first path mark when hero / boat is moving in the direction of the path. ++currentStep; ++nextStep; --greenColorSteps; } // Not all arrows and their shadows fit in 1 tile. We need to consider an area of 1 tile bigger to properly render everything. const fheroes2::Rect extendedVisibleRoi{ tileROI.x - 1, tileROI.y - 1, tileROI.width + 2, tileROI.height + 2 }; for ( ; currentStep != path.end(); ++currentStep ) { const int32_t tileIndex = currentStep->GetIndex(); const fheroes2::Point & mp = Maps::GetPoint( tileIndex ); ++nextStep; --greenColorSteps; if ( !( extendedVisibleRoi & mp ) ) { // The mark is on a tile outside the drawing area. Just skip it. continue; } uint32_t routeSpriteIndex = 0; if ( nextStep != path.end() ) { const Maps::Tile & tile = world.getTile( tileIndex ); const uint32_t cost = tile.isRoad() ? Maps::Ground::roadPenalty : Maps::Ground::GetPenalty( tile, pathfinding ); routeSpriteIndex = Route::Path::GetIndexSprite( currentStep->GetDirection(), nextStep->GetDirection(), cost ); } const fheroes2::Sprite & routeSprite = fheroes2::AGG::GetICN( ( ( greenColorSteps < 0 ) ? ICN::ROUTERED : ICN::ROUTE ), routeSpriteIndex ); BlitOnTile( dst, routeSprite, routeSprite.x() - 12, routeSprite.y() + 2, mp, false, 255 ); } } bool drawPassabilities = ( flag & LEVEL_PASSABILITIES ); #ifdef WITH_DEBUG if ( IS_DEVEL() && ( flag & LEVEL_ALL ) ) { drawPassabilities = true; } #endif if ( drawPassabilities ) { const int32_t friendColors = Players::FriendColors(); for ( int32_t y = minY; y < maxY; ++y ) { for ( int32_t x = minX; x < maxX; ++x ) { redrawPassable( world.getTile( x, y ), dst, friendColors, *this, isEditor ); } } } else if ( renderFog ) { const bool drawTowns = ( flag & LEVEL_TOWNS ); for ( int32_t y = minY; y < maxY; ++y ) { for ( int32_t x = minX; x < maxX; ++x ) { const Maps::Tile & tile = world.getTile( x, y ); if ( tile.getFogDirection() != Direction::UNKNOWN ) { drawFog( tile, dst, *this ); if ( drawTowns ) { drawByObjectIcnType( tile, dst, *this, MP2::OBJ_ICN_TYPE_OBJNTWBA ); const MP2::MapObjectType objectType = tile.getMainObjectType( false ); if ( objectType == MP2::OBJ_CASTLE || objectType == MP2::OBJ_NON_ACTION_CASTLE ) { drawByObjectIcnType( tile, dst, *this, MP2::OBJ_ICN_TYPE_OBJNTOWN ); } } } } } } updateObjectAnimationInfo(); } void Interface::GameArea::renderTileAreaSelect( fheroes2::Image & dst, const int32_t startTile, const int32_t endTile, const bool isActionObject ) const { if ( startTile < 0 || endTile < 0 ) { return; } const fheroes2::Point startTileOffset = GetRelativeTilePosition( Maps::GetPoint( startTile ) ); const fheroes2::Point endTileOffset = GetRelativeTilePosition( Maps::GetPoint( endTile ) ); const int32_t startX = std::min( startTileOffset.x, endTileOffset.x ); const int32_t startY = std::min( startTileOffset.y, endTileOffset.y ); const int32_t sizeX = fheroes2::tileWidthPx + std::abs( startTileOffset.x - endTileOffset.x ); const int32_t sizeY = fheroes2::tileWidthPx + std::abs( startTileOffset.y - endTileOffset.y ); const fheroes2::Rect imageRoi{ startX, startY, sizeX, sizeY }; const fheroes2::Rect overlappedRoi = _windowROI ^ imageRoi; const int32_t limitedLineWidth = std::min( 2, overlappedRoi.width ); const int32_t limitedLineHeight = std::min( 2, overlappedRoi.height ); const uint8_t color = ( isActionObject ? 115 : 181 ); fheroes2::Fill( dst, overlappedRoi.x, overlappedRoi.y, overlappedRoi.width, limitedLineHeight, color ); fheroes2::Fill( dst, overlappedRoi.x, overlappedRoi.y + 2, limitedLineWidth, overlappedRoi.height - 4, color ); fheroes2::Fill( dst, overlappedRoi.x, overlappedRoi.y + overlappedRoi.height - limitedLineHeight, overlappedRoi.width, limitedLineHeight, color ); fheroes2::Fill( dst, overlappedRoi.x + overlappedRoi.width - limitedLineWidth, overlappedRoi.y + 2, limitedLineWidth, overlappedRoi.height - 4, color ); } void Interface::GameArea::updateMapFogDirections() { const int32_t friendColors = Players::FriendColors(); Maps::updateFogDirectionsInArea( { 0, 0 }, { world.w(), world.h() }, friendColors ); } void Interface::GameArea::Scroll() { const int32_t scrollSpeed = Settings::Get().ScrollSpeed(); if ( scrollSpeed == SCROLL_SPEED_NONE ) { // No scrolling. scrollDirection = SCROLL_NONE; return; } const int32_t shift = 2 << scrollSpeed; fheroes2::Point offset; if ( scrollDirection & SCROLL_LEFT ) { offset.x = -shift; } else if ( scrollDirection & SCROLL_RIGHT ) { offset.x = shift; } if ( scrollDirection & SCROLL_TOP ) { offset.y = -shift; } else if ( scrollDirection & SCROLL_BOTTOM ) { offset.y = shift; } ShiftCenter( offset ); scrollDirection = SCROLL_NONE; } void Interface::GameArea::SetRedraw() const { _interface.setRedraw( REDRAW_GAMEAREA ); } fheroes2::Image Interface::GameArea::GenerateUltimateArtifactAreaSurface( const int32_t index, const fheroes2::Point & offset ) { if ( !Maps::isValidAbsIndex( index ) ) { DEBUG_LOG( DBG_GAME, DBG_WARN, "Ultimate artifact is not found on index " << index ) return fheroes2::Image(); } fheroes2::Image result; result._disableTransformLayer(); result.resize( 448, 448 ); // Make a temporary copy GameArea gamearea = AdventureMap::Get().getGameArea(); gamearea.SetAreaPosition( 0, 0, result.width(), result.height() ); const fheroes2::Point pt = Maps::GetPoint( index ); gamearea.SetCenter( pt + offset ); gamearea.Redraw( result, LEVEL_OBJECTS, true ); const fheroes2::Sprite & marker = fheroes2::AGG::GetICN( ICN::ROUTE, 0 ); const fheroes2::Point markerPos( gamearea.GetRelativeTilePosition( pt ) - gamearea._middlePoint() - fheroes2::Point( gamearea._windowROI.x, gamearea._windowROI.y ) + fheroes2::Point( result.width() / 2, result.height() / 2 ) ); fheroes2::Blit( marker, result, markerPos.x, markerPos.y + 8 ); fheroes2::ApplyPalette( result, PAL::GetPalette( PAL::PaletteType::TAN ) ); return result; } int Interface::GameArea::GetScrollCursor() const { switch ( scrollDirection ) { case SCROLL_LEFT | SCROLL_TOP: return Cursor::SCROLL_TOPLEFT; case SCROLL_LEFT | SCROLL_BOTTOM: return Cursor::SCROLL_BOTTOMLEFT; case SCROLL_RIGHT | SCROLL_TOP: return Cursor::SCROLL_TOPRIGHT; case SCROLL_RIGHT | SCROLL_BOTTOM: return Cursor::SCROLL_BOTTOMRIGHT; case SCROLL_TOP: return Cursor::SCROLL_TOP; case SCROLL_BOTTOM: return Cursor::SCROLL_BOTTOM; case SCROLL_RIGHT: return Cursor::SCROLL_RIGHT; case SCROLL_LEFT: return Cursor::SCROLL_LEFT; default: break; } return Cursor::NONE; } void Interface::GameArea::SetScroll( const int direction ) { if ( ( direction & SCROLL_LEFT ) == SCROLL_LEFT ) { if ( _topLeftTileOffset.x > _minLeftOffset ) { scrollDirection |= direction; updateCursor = true; } } else if ( ( direction & SCROLL_RIGHT ) == SCROLL_RIGHT ) { if ( _topLeftTileOffset.x < _maxLeftOffset ) { scrollDirection |= direction; updateCursor = true; } } if ( ( direction & SCROLL_TOP ) == SCROLL_TOP ) { if ( _topLeftTileOffset.y > _minTopOffset ) { scrollDirection |= direction; updateCursor = true; } } else if ( ( direction & SCROLL_BOTTOM ) == SCROLL_BOTTOM ) { if ( _topLeftTileOffset.y < _maxTopOffset ) { scrollDirection |= direction; updateCursor = true; } } scrollTime.reset(); } void Interface::GameArea::setFastScrollStatus( const bool enable ) { _isFastScrollEnabled = enable; _resetMousePositionForFastScroll = true; } bool Interface::GameArea::mouseIndicatesFastScroll( const fheroes2::Point & mousePosition ) { const fheroes2::Display & display = fheroes2::Display::instance(); constexpr int32_t deadZone = 3; // Remember the initial reference point for re-enabling checks later on. if ( _resetMousePositionForFastScroll ) { _mousePositionForFastScroll = mousePosition; _resetMousePositionForFastScroll = false; } if ( Interface::BaseInterface::isScrollLeft( _mousePositionForFastScroll ) ) { if ( mousePosition.x > _mousePositionForFastScroll.x ) { // Movement is away from the border, we need to update the checking point. _mousePositionForFastScroll = mousePosition; } else if ( mousePosition.x < _mousePositionForFastScroll.x || ( abs( mousePosition.y - _mousePositionForFastScroll.y ) > deadZone && mousePosition.x <= 0 ) ) { // Movement is towards or along the border, we re-enable the fast scroll. return true; } } else if ( Interface::BaseInterface::isScrollRight( _mousePositionForFastScroll ) ) { if ( mousePosition.x < _mousePositionForFastScroll.x ) { // Movement is away from the border, we need to update the checking point. _mousePositionForFastScroll = mousePosition; } else if ( mousePosition.x > _mousePositionForFastScroll.x || ( abs( mousePosition.y - _mousePositionForFastScroll.y ) > deadZone && mousePosition.x >= display.width() - 1 ) ) { // Movement is towards or along the border, we re-enable the fast scroll. return true; } } else if ( Interface::BaseInterface::isScrollTop( _mousePositionForFastScroll ) ) { if ( mousePosition.y > _mousePositionForFastScroll.y ) { // Movement is away from the border, we need to update the checking point. _mousePositionForFastScroll = mousePosition; } else if ( mousePosition.y < _mousePositionForFastScroll.y || ( abs( mousePosition.x - _mousePositionForFastScroll.x ) > deadZone && mousePosition.y <= 0 ) ) { // Movement is towards or along the border, we re-enable the fast scroll. return true; } } else if ( Interface::BaseInterface::isScrollBottom( _mousePositionForFastScroll ) ) { if ( mousePosition.y < _mousePositionForFastScroll.y ) { // Movement is away from the border, we need to update the checking point. _mousePositionForFastScroll = mousePosition; } else if ( mousePosition.y > _mousePositionForFastScroll.y || ( abs( mousePosition.x - _mousePositionForFastScroll.x ) > deadZone && mousePosition.y >= display.height() - 1 ) ) { // Movement is towards or along the border, we re-enable the fast scroll. return true; } } else { // We have left the scroll borders, fast scrolling can definitely be re-enabled. return true; } // We haven't left the borders, but the direction of the mouse movement within the borders // does not indicate that the user wants to perform the fast scroll right now. return false; } void Interface::GameArea::QueueEventProcessing() { LocalEvent & le = LocalEvent::Get(); const fheroes2::Point & mousePosition = le.getMouseCursorPos(); if ( !le.isMouseLeftButtonPressed() ) { _mouseDraggingInitiated = false; _mouseDraggingMovement = false; _needRedrawByMouseDragging = false; } else if ( _interface.useMouseDragMovement() ) { if ( !_mouseDraggingInitiated ) { _mouseDraggingInitiated = true; _lastMouseDragPosition = mousePosition; } else if ( std::abs( _lastMouseDragPosition.x - mousePosition.x ) > minimalRequiredDraggingMovement || std::abs( _lastMouseDragPosition.y - mousePosition.y ) > minimalRequiredDraggingMovement ) { _mouseDraggingMovement = true; } } if ( _mouseDraggingMovement && le.isMouseLeftButtonPressedInArea( GetROI() ) ) { if ( _lastMouseDragPosition == mousePosition ) { _needRedrawByMouseDragging = false; } else { // Update the center coordinates and redraw the adventure map only if the mouse was moved. _needRedrawByMouseDragging = true; SetCenterInPixels( getCurrentCenterInPixels() + _lastMouseDragPosition - mousePosition ); _lastMouseDragPosition = mousePosition; } return; } int32_t index = GetValidTileIdFromPoint( mousePosition ); if ( !Maps::isValidAbsIndex( index ) ) { // Change the cursor image when it gets out of the map boundaries or by 'updateCursor' flag. if ( updateCursor || index != _prevIndexPos ) { _interface.updateCursor( index ); _prevIndexPos = index; updateCursor = false; } return; } const Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() && conf.ShowControlPanel() && le.isMouseCursorPosInArea( Interface::AdventureMap::Get().getControlPanel().GetArea() ) ) { return; } const fheroes2::Point tileOffset = getInternalPosition( mousePosition ); const fheroes2::Point tilePos( ( tileOffset.x / fheroes2::tileWidthPx ) * fheroes2::tileWidthPx - _topLeftTileOffset.x + _windowROI.x, ( tileOffset.y / fheroes2::tileWidthPx ) * fheroes2::tileWidthPx - _topLeftTileOffset.y + _windowROI.x ); const fheroes2::Rect tileROI( tilePos.x, tilePos.y, fheroes2::tileWidthPx, fheroes2::tileWidthPx ); if ( le.MouseClickLeft( tileROI ) ) { _interface.mouseCursorAreaClickLeft( index ); } else if ( le.isMouseRightButtonPressedInArea( tileROI ) ) { _interface.mouseCursorAreaPressRight( index ); } else if ( le.MouseLongPressLeft( tileROI ) ) { _interface.mouseCursorAreaLongPressLeft( index ); } // The cursor may have moved after mouse click events. index = GetValidTileIdFromPoint( le.getMouseCursorPos() ); // Change the cursor image if needed. if ( updateCursor || index != _prevIndexPos ) { _interface.updateCursor( index ); _prevIndexPos = index; updateCursor = false; } } fheroes2::Point Interface::GameArea::_getStartTileId() const { const int32_t x = ( _topLeftTileOffset.x < 0 ? ( _topLeftTileOffset.x - fheroes2::tileWidthPx - 1 ) / fheroes2::tileWidthPx : _topLeftTileOffset.x / fheroes2::tileWidthPx ); const int32_t y = ( _topLeftTileOffset.y < 0 ? ( _topLeftTileOffset.y - fheroes2::tileWidthPx - 1 ) / fheroes2::tileWidthPx : _topLeftTileOffset.y / fheroes2::tileWidthPx ); return { x, y }; } void Interface::GameArea::_setCenterToTile( const fheroes2::Point & tile ) { SetCenterInPixels( { tile.x * fheroes2::tileWidthPx + fheroes2::tileWidthPx / 2, tile.y * fheroes2::tileWidthPx + fheroes2::tileWidthPx / 2 } ); } void Interface::GameArea::SetCenterInPixels( const fheroes2::Point & point ) { const fheroes2::Point & middlePos = _middlePoint(); int32_t offsetX = point.x - middlePos.x; int32_t offsetY = point.y - middlePos.y; if ( offsetX < _minLeftOffset ) offsetX = _minLeftOffset; else if ( offsetX > _maxLeftOffset ) offsetX = _maxLeftOffset; if ( offsetY < _minTopOffset ) offsetY = _minTopOffset; else if ( offsetY > _maxTopOffset ) offsetY = _maxTopOffset; _topLeftTileOffset = fheroes2::Point( offsetX, offsetY ); } int32_t Interface::GameArea::GetValidTileIdFromPoint( const fheroes2::Point & point ) const { const fheroes2::Point offset = getInternalPosition( point ); if ( offset.x < 0 || offset.y < 0 ) return -1; const int32_t x = offset.x / fheroes2::tileWidthPx; const int32_t y = offset.y / fheroes2::tileWidthPx; if ( x >= world.w() || y >= world.h() ) return -1; return y * world.w() + x; } fheroes2::Point Interface::GameArea::GetRelativeTilePosition( const fheroes2::Point & tileId ) const { return { tileId.x * fheroes2::tileWidthPx - _topLeftTileOffset.x + _windowROI.x, tileId.y * fheroes2::tileWidthPx - _topLeftTileOffset.y + _windowROI.y }; } void Interface::GameArea::updateObjectAnimationInfo() const { for ( auto iter = _animationInfo.begin(); iter != _animationInfo.end(); ) { if ( ( *iter )->update() ) { iter = _animationInfo.erase( iter ); } else { ++iter; } } } uint8_t Interface::GameArea::getObjectAlphaValue( const int32_t tileId, const MP2::MapObjectType type ) const { for ( const auto & info : _animationInfo ) { if ( info->tileId == tileId && type == info->type ) { return info->alphaValue; } } return 255; } uint8_t Interface::GameArea::getObjectAlphaValue( const uint32_t uid ) const { for ( const auto & info : _animationInfo ) { if ( uid == info->uid ) { return info->alphaValue; } } return 255; } void Interface::GameArea::runSingleObjectAnimation( const std::shared_ptr & info ) { if ( !info ) { assert( 0 ); return; } addObjectAnimationInfo( info ); LocalEvent & le = LocalEvent::Get(); fheroes2::Display & display = fheroes2::Display::instance(); Interface::AdventureMap & adventureMapInterface = Interface::AdventureMap::Get(); while ( le.HandleEvents( Game::isDelayNeeded( { Game::HEROES_PICKUP_DELAY } ) ) && !info->isAnimationCompleted() ) { if ( Game::validateAnimationDelay( Game::HEROES_PICKUP_DELAY ) ) { adventureMapInterface.redraw( Interface::REDRAW_GAMEAREA ); display.render(); } } } Interface::ObjectFadingOutInfo::~ObjectFadingOutInfo() { const Maps::Tile & tile = world.getTile( tileId ); if ( tile.getMainObjectType() == type ) { removeMainObjectFromTile( tile ); } } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_gamearea.h000066400000000000000000000245021476115357100232130ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include #include #include "image.h" #include "math_base.h" #include "mp2.h" #include "timing.h" namespace Interface { class BaseInterface; enum ScrollingType { SCROLL_NONE = 0x00, SCROLL_LEFT = 0x01, SCROLL_RIGHT = 0x02, SCROLL_TOP = 0x04, SCROLL_BOTTOM = 0x08 }; enum RedrawLevelType { LEVEL_OBJECTS = 0x00, // we always render objects for each type of view. LEVEL_HEROES = 0x01, LEVEL_FOG = 0x02, LEVEL_ROUTES = 0x04, LEVEL_TOWNS = 0x08, // this level is used only for View All / View Towns spells. LEVEL_PASSABILITIES = 0x10, // this level is used only by the Editor. LEVEL_ALL = LEVEL_OBJECTS | LEVEL_HEROES | LEVEL_FOG | LEVEL_ROUTES }; struct BaseObjectAnimationInfo { BaseObjectAnimationInfo() = default; BaseObjectAnimationInfo( const uint32_t uid_, const int32_t tileId_, const MP2::MapObjectType type_ ) : uid( uid_ ) , tileId( tileId_ ) , type( type_ ) { // Do nothing. } BaseObjectAnimationInfo( const BaseObjectAnimationInfo & ) = delete; BaseObjectAnimationInfo & operator=( const BaseObjectAnimationInfo & ) = delete; virtual ~BaseObjectAnimationInfo() = default; uint32_t uid{ 0 }; int32_t tileId{ -1 }; MP2::MapObjectType type{ MP2::OBJ_NONE }; uint8_t alphaValue{ 255 }; virtual bool update() = 0; virtual bool isAnimationCompleted() const = 0; }; struct ObjectFadingOutInfo : public BaseObjectAnimationInfo { using BaseObjectAnimationInfo::BaseObjectAnimationInfo; ~ObjectFadingOutInfo() override; bool update() override { if ( alphaValue >= alphaStep ) { alphaValue -= alphaStep; } else { alphaValue = 0; } return ( alphaValue == 0 ); } bool isAnimationCompleted() const override { return ( alphaValue == 0 ); } static const uint8_t alphaStep{ 20 }; }; struct ObjectFadingInInfo : public BaseObjectAnimationInfo { ObjectFadingInInfo() = delete; ObjectFadingInInfo( const uint32_t uid_, const int32_t tileId_, const MP2::MapObjectType type_ ) : BaseObjectAnimationInfo( uid_, tileId_, type_ ) { alphaValue = 0; } ~ObjectFadingInInfo() override = default; bool update() override { if ( 255 - alphaValue >= alphaStep ) { alphaValue += alphaStep; } else { alphaValue = 255; } return ( alphaValue == 255 ); } bool isAnimationCompleted() const override { return ( alphaValue == 255 ); } static const uint8_t alphaStep{ 20 }; }; class GameArea { public: explicit GameArea( BaseInterface & interface ); void generate( const fheroes2::Size & screenSize, const bool withoutBorders ); const fheroes2::Rect & GetROI() const // returns visible Game Area ROI in pixels { return _windowROI; } // Do NOT use this method directly in heavy computation loops fheroes2::Rect GetVisibleTileROI() const { return { _getStartTileId(), _visibleTileCount }; } // Shift center in pixels. void ShiftCenter( const fheroes2::Point & offset ) { SetCenterInPixels( _topLeftTileOffset + _middlePoint() + offset ); } int GetScrollCursor() const; bool NeedScroll() const { return scrollDirection != 0; } void Scroll(); void SetScroll( const int direction ); void SetCenter( const fheroes2::Point & point ) { _setCenterToTile( point ); scrollDirection = 0; } // Do not call this method unless it's needed for manual setup of the position void SetCenterInPixels( const fheroes2::Point & point ); void SetRedraw() const; // Do not call this method directly if the rendering takes place on the screen, use // Interface::BaseInterface::Redraw() instead to avoid issues in the "no interface" mode void Redraw( fheroes2::Image & dst, int flag, bool isPuzzleDraw = false ) const; void renderTileAreaSelect( fheroes2::Image & dst, const int32_t startTile, const int32_t endTile, const bool isActionObject ) const; void BlitOnTile( fheroes2::Image & dst, const fheroes2::Image & src, int32_t ox, int32_t oy, const fheroes2::Point & mp, bool flip, uint8_t alpha ) const; void BlitOnTile( fheroes2::Image & dst, const fheroes2::Image & src, const fheroes2::Rect & srcRoi, int32_t ox, int32_t oy, const fheroes2::Point & mp, bool flip, uint8_t alpha ) const; // Use this method to draw TIL images void DrawTile( fheroes2::Image & src, const fheroes2::Image & dst, const fheroes2::Point & mp ) const; void SetUpdateCursor() { updateCursor = true; } // Update fog directions data for entire map tiles by checking fog data for current player and its allies. static void updateMapFogDirections(); void QueueEventProcessing(); static fheroes2::Image GenerateUltimateArtifactAreaSurface( const int32_t index, const fheroes2::Point & offset ); int32_t GetValidTileIdFromPoint( const fheroes2::Point & point ) const; // returns -1 in case of invalid index (out of World Map) fheroes2::Point GetRelativeTilePosition( const fheroes2::Point & tileId ) const; // in relation to screen void SetAreaPosition( int32_t x, int32_t y, int32_t w, int32_t h ); fheroes2::Point getCurrentCenterInPixels() const { return _topLeftTileOffset + _middlePoint(); } void addObjectAnimationInfo( std::shared_ptr info ) { _animationInfo.emplace_back( std::move( info ) ); } uint8_t getObjectAlphaValue( const int32_t tileId, const MP2::MapObjectType type ) const; uint8_t getObjectAlphaValue( const uint32_t uid ) const; // Make sure you do not have a copy of this object after the execution of the method to avoid incorrect object removal in some cases. void runSingleObjectAnimation( const std::shared_ptr & info ); bool isDragScroll() const { return _mouseDraggingMovement; } bool needDragScrollRedraw() const { return _needRedrawByMouseDragging; } bool isFastScrollEnabled() const { return _isFastScrollEnabled; } void setFastScrollStatus( const bool enable ); bool mouseIndicatesFastScroll( const fheroes2::Point & mousePosition ); fheroes2::Point getInternalPosition( const fheroes2::Point & position ) const { return _topLeftTileOffset + position - _windowROI.getPosition(); } private: BaseInterface & _interface; fheroes2::Rect _windowROI; // visible to draw area of World Map in pixels fheroes2::Point _topLeftTileOffset; // offset of tiles to be drawn (from here we can find any tile ID) // boundaries for World Map int32_t _minLeftOffset; int32_t _maxLeftOffset; int32_t _minTopOffset; int32_t _maxTopOffset; fheroes2::Size _visibleTileCount; // number of tiles to be drawn on screen int32_t _prevIndexPos; int scrollDirection; bool updateCursor; fheroes2::Time scrollTime; // This member needs to be mutable because it is modified during rendering. mutable std::vector> _animationInfo; fheroes2::Point _lastMouseDragPosition; fheroes2::Point _mousePositionForFastScroll; bool _mouseDraggingInitiated; bool _mouseDraggingMovement; bool _needRedrawByMouseDragging; bool _isFastScrollEnabled; bool _resetMousePositionForFastScroll; // Returns middle point of window ROI. fheroes2::Point _middlePoint() const { return { _windowROI.width / 2, _windowROI.height / 2 }; } fheroes2::Point _getStartTileId() const; void _setCenterToTile( const fheroes2::Point & tile ); // set center to the middle of tile (input is tile ID) void updateObjectAnimationInfo() const; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_icons.cpp000066400000000000000000000370331476115357100231220ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_icons.h" #include "agg_image.h" #include "castle.h" #include "dialog.h" #include "game.h" #include "game_interface.h" #include "heroes.h" #include "heroes_base.h" #include "icn.h" #include "interface_base.h" #include "kingdom.h" #include "screen.h" #include "settings.h" #include "ui_castle.h" #include "ui_constants.h" #include "ui_scrollbar.h" #include "world.h" namespace { const int32_t iconsCursorWidth = 56; const int32_t iconsCursorHeight = 32; } bool Interface::IconsBar::isVisible() { const Settings & conf = Settings::Get(); return !conf.isHideInterfaceEnabled() || conf.ShowIcons(); } void Interface::redrawCastleIcon( const Castle & castle, const int32_t posX, const int32_t posY ) { fheroes2::drawCastleIcon( castle, fheroes2::Display::instance(), { posX, posY } ); } void Interface::redrawHeroesIcon( const Heroes & hero, const int32_t posX, const int32_t posY ) { hero.PortraitRedraw( posX, posY, PORT_SMALL, fheroes2::Display::instance() ); } void Interface::IconsBar::redrawBackground( fheroes2::Image & output, const fheroes2::Point & offset, const int32_t validItemCount ) const { const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const fheroes2::Sprite & icnadv = fheroes2::AGG::GetICN( isEvilInterface ? ICN::ADVBORDE : ICN::ADVBORD, 0 ); fheroes2::Rect srcrt( icnadv.width() - fheroes2::radarWidthPx - fheroes2::borderWidthPx, fheroes2::radarWidthPx + 2 * fheroes2::borderWidthPx, fheroes2::radarWidthPx / 2, 32 ); fheroes2::Blit( icnadv, srcrt.x, srcrt.y, output, offset.x, offset.y, srcrt.width, srcrt.height ); srcrt.y = srcrt.y + srcrt.height; int32_t internalOffsetY = offset.y + srcrt.height; srcrt.height = 32; if ( _iconsCount > 2 ) { for ( int32_t i = 0; i < _iconsCount - 2; ++i ) { fheroes2::Blit( icnadv, srcrt.x, srcrt.y, output, offset.x, internalOffsetY, srcrt.width, srcrt.height ); internalOffsetY += srcrt.height; } } srcrt.y = srcrt.y + 64; srcrt.height = 32; fheroes2::Blit( icnadv, srcrt.x, srcrt.y, output, offset.x, internalOffsetY, srcrt.width, srcrt.height ); for ( int32_t i = validItemCount; i < _iconsCount; ++i ) { const fheroes2::Sprite & background = fheroes2::AGG::GetICN( isEvilInterface ? ICN::LOCATORE : ICN::LOCATORS, 1 + i % 8 ); fheroes2::Copy( background, 0, 0, output, offset.x + 5, offset.y + 5 + i * ( IconsBar::getItemHeight() + 10 ), background.width(), background.height() ); } } void Interface::CastleIcons::RedrawItem( const CASTLE & item, int32_t ox, int32_t oy, bool current ) { if ( item && _show ) { redrawCastleIcon( *item, ox + 5, oy + 5 ); if ( current ) { fheroes2::Blit( _marker, fheroes2::Display::instance(), ox, oy ); } } } void Interface::CastleIcons::RedrawBackground( const fheroes2::Point & pos ) { redrawBackground( fheroes2::Display::instance(), pos, _show ? _size() : 0 ); } void Interface::CastleIcons::ActionCurrentUp() { Interface::AdventureMap::Get().SetFocus( GetCurrent() ); } void Interface::CastleIcons::ActionCurrentDn() { Interface::AdventureMap::Get().SetFocus( GetCurrent() ); } void Interface::CastleIcons::ActionListDoubleClick( CASTLE & item ) { if ( item ) { Game::OpenCastleDialog( *item ); } } void Interface::CastleIcons::ActionListSingleClick( CASTLE & item ) { if ( item ) { Interface::AdventureMap & I = Interface::AdventureMap::Get(); I.SetFocus( item ); I.RedrawFocus(); } } void Interface::CastleIcons::ActionListPressRight( CASTLE & item ) { if ( item ) { Dialog::QuickInfoAtPosition( *item, { _topLeftCorner.x - 1, _topLeftCorner.y } ); } } void Interface::CastleIcons::showIcons( const bool show ) { IconsBar::setShow( show ); if ( IconsBar::isVisible() ) { if ( show ) { GetScrollbar().show(); } else { GetScrollbar().hide(); } } } void Interface::CastleIcons::setPos( const int32_t px, const int32_t py ) { Castle * selectedCastle = isSelected() ? GetCurrent() : nullptr; const int icnscroll = Settings::Get().isEvilInterfaceEnabled() ? ICN::SCROLLE : ICN::SCROLL; _topLeftCorner = fheroes2::Point( px, py ); SetTopLeft( _topLeftCorner ); setScrollBarArea( { px + iconsCursorWidth + 3, py + 19, 10, iconsCursorHeight * _iconsCount - 38 } ); VecCastles & castles = world.GetKingdom( Settings::Get().CurrentColor() ).GetCastles(); const fheroes2::Sprite & originalSlider = fheroes2::AGG::GetICN( icnscroll, 4 ); const fheroes2::Image scrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, false, iconsCursorHeight * _iconsCount - 38, _iconsCount, static_cast( castles.size() ), { 0, 0, originalSlider.width(), 8 }, { 0, 7, originalSlider.width(), 8 } ); setScrollBarImage( scrollbarSlider ); SetScrollButtonUp( icnscroll, 0, 1, { px + iconsCursorWidth + 1, py + 1 } ); SetScrollButtonDn( icnscroll, 2, 3, { px + iconsCursorWidth + 1, py + _iconsCount * iconsCursorHeight - 15 } ); SetAreaMaxItems( _iconsCount ); SetAreaItems( { px, py, iconsCursorWidth, _iconsCount * iconsCursorHeight } ); DisableHotkeys( true ); SetListContent( castles ); Reset(); if ( selectedCastle ) { SetCurrent( selectedCastle ); } } void Interface::HeroesIcons::RedrawItem( const HEROES & item, int32_t ox, int32_t oy, bool current ) { if ( item && _show ) { redrawHeroesIcon( *item, ox + 5, oy + 5 ); if ( current ) { fheroes2::Blit( _marker, fheroes2::Display::instance(), ox, oy ); } } } void Interface::HeroesIcons::RedrawBackground( const fheroes2::Point & pos ) { redrawBackground( fheroes2::Display::instance(), pos, _show ? _size() : 0 ); } void Interface::HeroesIcons::ActionCurrentUp() { Interface::AdventureMap::Get().SetFocus( GetCurrent(), false ); } void Interface::HeroesIcons::ActionCurrentDn() { Interface::AdventureMap::Get().SetFocus( GetCurrent(), false ); } void Interface::HeroesIcons::ActionListDoubleClick( HEROES & item ) { if ( item ) { Game::OpenHeroesDialog( *item, false, true ); } } void Interface::HeroesIcons::ActionListSingleClick( HEROES & item ) { if ( item ) { Interface::AdventureMap & I = Interface::AdventureMap::Get(); I.SetFocus( item, false ); I.RedrawFocus(); } } void Interface::HeroesIcons::ActionListPressRight( HEROES & item ) { if ( item ) { Dialog::QuickInfoAtPosition( *item, { _topLeftCorner.x - 1, _topLeftCorner.y } ); } } void Interface::HeroesIcons::showIcons( const bool show ) { IconsBar::setShow( show ); if ( IconsBar::isVisible() ) { if ( show ) { GetScrollbar().show(); } else { GetScrollbar().hide(); } } } void Interface::HeroesIcons::setPos( const int32_t px, const int32_t py ) { Heroes * selectedHero = isSelected() ? GetCurrent() : nullptr; const int icnscroll = Settings::Get().isEvilInterfaceEnabled() ? ICN::SCROLLE : ICN::SCROLL; _topLeftCorner = fheroes2::Point( px, py ); SetTopLeft( _topLeftCorner ); setScrollBarArea( { px + iconsCursorWidth + 3, py + 19, 10, iconsCursorHeight * _iconsCount - 38 } ); VecHeroes & heroes = world.GetKingdom( Settings::Get().CurrentColor() ).GetHeroes(); const fheroes2::Sprite & originalSlider = fheroes2::AGG::GetICN( icnscroll, 4 ); const fheroes2::Image scrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, false, iconsCursorHeight * _iconsCount - 38, _iconsCount, static_cast( heroes.size() ), { 0, 0, originalSlider.width(), 8 }, { 0, 7, originalSlider.width(), 8 } ); setScrollBarImage( scrollbarSlider ); SetScrollButtonUp( icnscroll, 0, 1, { px + iconsCursorWidth + 1, py + 1 } ); SetScrollButtonDn( icnscroll, 2, 3, { px + iconsCursorWidth + 1, py + _iconsCount * iconsCursorHeight - 15 } ); SetAreaMaxItems( _iconsCount ); SetAreaItems( { px, py, iconsCursorWidth, _iconsCount * iconsCursorHeight } ); DisableHotkeys( true ); SetListContent( heroes ); Reset(); if ( selectedHero ) { SetCurrent( selectedHero ); } } Interface::IconsPanel::IconsPanel( AdventureMap & interface ) : BorderWindow( { 0, 0, 144, 128 } ) , _interface( interface ) { _sfMarker.resize( iconsCursorWidth, iconsCursorHeight ); _sfMarker.reset(); fheroes2::DrawBorder( _sfMarker, fheroes2::GetColorId( 0xA0, 0xE0, 0xE0 ) ); } void Interface::IconsPanel::SavePosition() { Settings & conf = Settings::Get(); conf.SetPosIcons( GetRect().getPosition() ); conf.Save( Settings::configFileName ); } void Interface::IconsPanel::setRedraw( const HeroesCastlesIcons type ) const { if ( !IconsBar::isVisible() ) { return; } switch ( type ) { case ICON_HEROES: _interface.setRedraw( REDRAW_HEROES ); break; case ICON_CASTLES: _interface.setRedraw( REDRAW_CASTLES ); break; case ICON_ANY: _interface.setRedraw( REDRAW_ICONS ); break; default: break; } } void Interface::IconsPanel::SetPos( int32_t x, int32_t y ) { int32_t iconsCount = 0; if ( Settings::Get().isHideInterfaceEnabled() ) { iconsCount = 2; } else { const int32_t count_h = ( fheroes2::Display::instance().height() - fheroes2::Display::DEFAULT_HEIGHT ) / fheroes2::tileWidthPx; iconsCount = count_h > 3 ? 8 : ( count_h < 3 ? 4 : 7 ); } BorderWindow::SetPosition( x, y, 144, iconsCount * iconsCursorHeight ); _heroesIcons.setIconsCount( iconsCount ); _castleIcons.setIconsCount( iconsCount ); const fheroes2::Rect & rect = GetArea(); _heroesIcons.setPos( rect.x, rect.y ); _castleIcons.setPos( rect.x + 72, rect.y ); } void Interface::IconsPanel::_redraw() { if ( !IconsBar::isVisible() ) { return; } if ( Settings::Get().isHideInterfaceEnabled() ) { BorderWindow::Redraw(); } _heroesIcons.Redraw(); _castleIcons.Redraw(); } void Interface::IconsPanel::queueEventProcessing() { captureMouse(); // Move the window border if ( Settings::Get().ShowIcons() && BorderWindow::QueueEventProcessing() ) { setRedraw(); } else { if ( _heroesIcons.QueueEventProcessing() ) { if ( _heroesIcons.isSelected() ) { _castleIcons.Unselect(); } setRedraw(); } else if ( _castleIcons.QueueEventProcessing() ) { if ( _castleIcons.isSelected() ) { _heroesIcons.Unselect(); } setRedraw(); } } } void Interface::IconsPanel::select( Heroes * const hero ) { _castleIcons.Unselect(); _heroesIcons.SetCurrent( hero ); } void Interface::IconsPanel::select( Castle * const castle ) { _heroesIcons.Unselect(); _castleIcons.SetCurrent( castle ); } void Interface::IconsPanel::resetIcons( const HeroesCastlesIcons type ) { Kingdom & kingdom = world.GetKingdom( Settings::Get().CurrentColor() ); if ( !kingdom.isControlAI() ) { const int icnscroll = Settings::Get().isEvilInterfaceEnabled() ? ICN::SCROLLE : ICN::SCROLL; const fheroes2::Sprite & originalSlider = fheroes2::AGG::GetICN( icnscroll, 4 ); if ( type & ICON_HEROES ) { const fheroes2::Image scrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, false, iconsCursorHeight * _heroesIcons.getIconsCount() - 38, _heroesIcons.getIconsCount(), static_cast( kingdom.GetHeroes().size() ), { 0, 0, originalSlider.width(), 8 }, { 0, 7, originalSlider.width(), 8 } ); _heroesIcons.setScrollBarImage( scrollbarSlider ); _heroesIcons.SetListContent( kingdom.GetHeroes() ); // SetListContent() selects the first item (hero) in the list. We reset it by unselecting. _heroesIcons.Unselect(); } if ( type & ICON_CASTLES ) { const fheroes2::Image scrollbarSlider = fheroes2::generateScrollbarSlider( originalSlider, false, iconsCursorHeight * _castleIcons.getIconsCount() - 38, _castleIcons.getIconsCount(), static_cast( kingdom.GetCastles().size() ), { 0, 0, originalSlider.width(), 8 }, { 0, 7, originalSlider.width(), 8 } ); _castleIcons.setScrollBarImage( scrollbarSlider ); _castleIcons.SetListContent( kingdom.GetCastles() ); // SetListContent() selects the first item (castle/town) in the list. We reset it by unselecting. _castleIcons.Unselect(); } } } void Interface::IconsPanel::hideIcons( const HeroesCastlesIcons type ) { if ( type & ICON_HEROES ) { _heroesIcons.showIcons( false ); } if ( type & ICON_CASTLES ) { _castleIcons.showIcons( false ); } } void Interface::IconsPanel::showIcons( const HeroesCastlesIcons type ) { if ( type & ICON_HEROES ) { _heroesIcons.showIcons( true ); } if ( type & ICON_CASTLES ) { _castleIcons.showIcons( true ); } } void Interface::IconsPanel::_redrawIcons( const HeroesCastlesIcons type ) { if ( type & ICON_HEROES ) { _heroesIcons.Redraw(); } if ( type & ICON_CASTLES ) { _castleIcons.Redraw(); } } bool Interface::IconsPanel::isSelected( const HeroesCastlesIcons type ) const { if ( type & ICON_HEROES ) { return _heroesIcons.isSelected(); } if ( type & ICON_CASTLES ) { return _castleIcons.isSelected(); } return false; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_icons.h000066400000000000000000000163221476115357100225650ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include "image.h" #include "interface_border.h" #include "interface_list.h" #include "math_base.h" class Castle; class Heroes; enum HeroesCastlesIcons : uint8_t { ICON_HEROES = 0x01, ICON_CASTLES = 0x02, ICON_ANY = ICON_HEROES | ICON_CASTLES }; namespace Interface { class AdventureMap; using HEROES = Heroes *; using CASTLE = Castle *; class IconsBar { public: IconsBar( const int32_t count, const fheroes2::Image & markerImage ) : _marker( markerImage ) , _iconsCount( count ) { assert( count >= 0 ); } IconsBar( const IconsBar & ) = delete; virtual ~IconsBar() = default; IconsBar & operator=( const IconsBar & ) = delete; void setShow( bool show ) { _show = show; } void redrawBackground( fheroes2::Image & output, const fheroes2::Point & offset, const int32_t validItemCount ) const; void setIconsCount( const int32_t count ) { _iconsCount = count; } int32_t getIconsCount() const { return _iconsCount; } static int32_t getItemWidth() { return 46; } static int32_t getItemHeight() { return 22; } static bool isVisible(); protected: const fheroes2::Image & _marker; int32_t _iconsCount; bool _show{ true }; }; void redrawHeroesIcon( const Heroes & hero, const int32_t posX, const int32_t posY ); void redrawCastleIcon( const Castle & castle, const int32_t posX, const int32_t posY ); class HeroesIcons final : public Interface::ListBox, public IconsBar { public: HeroesIcons( const int32_t count, const fheroes2::Image & markerImage ) : IconsBar( count, markerImage ) { // Do nothing. } HeroesIcons( const HeroesIcons & ) = delete; ~HeroesIcons() override = default; HeroesIcons & operator=( const HeroesIcons & ) = delete; void setPos( const int32_t px, const int32_t py ); void showIcons( const bool show ); private: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; void ActionCurrentUp() override; void ActionCurrentDn() override; void ActionListDoubleClick( HEROES & item ) override; void ActionListSingleClick( HEROES & item ) override; void ActionListPressRight( HEROES & item ) override; void RedrawItem( const HEROES & item, int32_t ox, int32_t oy, bool current ) override; void RedrawBackground( const fheroes2::Point & pos ) override; fheroes2::Point _topLeftCorner; }; class CastleIcons final : public Interface::ListBox, public IconsBar { public: CastleIcons( const int32_t count, const fheroes2::Image & markerImage ) : IconsBar( count, markerImage ) { // Do nothing. } CastleIcons( const CastleIcons & ) = delete; ~CastleIcons() override = default; CastleIcons & operator=( const CastleIcons & ) = delete; void setPos( const int32_t px, const int32_t py ); void showIcons( const bool show ); private: using Interface::ListBox::ActionListDoubleClick; using Interface::ListBox::ActionListSingleClick; using Interface::ListBox::ActionListPressRight; void ActionCurrentUp() override; void ActionCurrentDn() override; void ActionListDoubleClick( CASTLE & item ) override; void ActionListSingleClick( CASTLE & item ) override; void ActionListPressRight( CASTLE & item ) override; void RedrawItem( const CASTLE & item, int32_t ox, int32_t oy, bool current ) override; void RedrawBackground( const fheroes2::Point & pos ) override; fheroes2::Point _topLeftCorner; }; class IconsPanel final : public BorderWindow { public: explicit IconsPanel( AdventureMap & interface ); IconsPanel( const IconsPanel & ) = delete; ~IconsPanel() override = default; IconsPanel & operator=( const IconsPanel & ) = delete; void SetPos( int32_t x, int32_t y ) override; void SavePosition() override; void setRedraw() const { setRedraw( ICON_ANY ); } void setRedraw( const HeroesCastlesIcons type ) const; void queueEventProcessing(); void select( Heroes * const hero ); void select( Castle * const castle ); bool isSelected( const HeroesCastlesIcons type ) const; void resetIcons( const HeroesCastlesIcons type ); void hideIcons( const HeroesCastlesIcons type ); void showIcons( const HeroesCastlesIcons type ); // Do not call this method directly, use Interface::AdventureMap::redraw() instead to avoid issues in the "no interface" mode. // The name of this method starts from _ on purpose to do not mix with other public methods. void _redraw(); // The name of this method starts from _ on purpose to do not mix with other public methods. void _redrawIcons( const HeroesCastlesIcons type ); private: AdventureMap & _interface; fheroes2::Image _sfMarker; CastleIcons _castleIcons{ 4, _sfMarker }; HeroesIcons _heroesIcons{ 4, _sfMarker }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_itemsbar.h000066400000000000000000000442411476115357100232610ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2012 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "image.h" #include "localevent.h" namespace Interface { template class ItemsBar { public: ItemsBar() = default; virtual ~ItemsBar() = default; virtual void RedrawBackground( const fheroes2::Rect &, fheroes2::Image & ) = 0; virtual void RedrawItem( Item &, const fheroes2::Rect &, fheroes2::Image & ) = 0; void setTableSize( const fheroes2::Size & size ) { assert( size.width > 0 && size.height > 0 ); tableSize = size; calculateRoi(); calculateItemsPos(); } void SetContent( std::vector & content ) { items.clear(); items.reserve( content.size() ); for ( Item & item : content ) { items.push_back( &item ); } SetContentItems(); } void setRenderingOffset( const fheroes2::Point & offset ) { renderingRoi.x = offset.x; renderingRoi.y = offset.y; calculateItemsPos(); } void setSingleItemSize( const fheroes2::Size & size ) { assert( size.width > 0 && size.height > 0 ); singleItemSize = size; calculateRoi(); calculateItemsPos(); } void setInBetweenItemsOffset( const fheroes2::Size & offset ) { offsetBetweenItems = offset; calculateRoi(); calculateItemsPos(); } Item * GetItem( const fheroes2::Point & pt ) { const ItemsIterator posItem = GetItemIter( pt ); return posItem != items.end() ? *posItem : nullptr; } const fheroes2::Rect & GetArea() const { return renderingRoi; } void Redraw( fheroes2::Image & output ) { if ( tableSize.width <= 0 || tableSize.height <= 0 ) { return; } ItemsIterator itemIter = items.begin(); auto itemPosIter = itemPos.begin(); const bool useCustomCountX = ( _customItemsCountInRow.size() == static_cast( tableSize.height ) ); for ( int32_t y = 0; y < tableSize.height; ++y ) { const int32_t coutX = useCustomCountX ? _customItemsCountInRow[y] : tableSize.width; for ( int32_t x = 0; x < coutX; ++x ) { assert( itemPosIter != itemPos.end() ); const fheroes2::Rect itemRoi{ *itemPosIter, singleItemSize }; RedrawBackground( itemRoi, output ); ++itemPosIter; if ( itemIter == items.end() ) { continue; } RedrawItemIter( itemIter, itemRoi, output ); ++itemIter; } } } virtual bool ActionBarLeftMouseSingleClick( Item & ) { return false; } virtual bool ActionBarRightMouseHold( Item & ) { return false; } virtual bool ActionBarCursor( Item & ) { return false; } bool QueueEventProcessing() { if ( isItemsEmpty() ) { return false; } const fheroes2::Point & cursor = LocalEvent::Get().getMouseCursorPos(); return ActionCursorItemIter( cursor, GetItemIterPos( cursor ) ); } void setCustomItemsCountInRow( std::vector itemsXCounts ) { _customItemsCountInRow = std::move( itemsXCounts ); if ( !_customItemsCountInRow.empty() ) { const int32_t maxWidth = *std::max_element( _customItemsCountInRow.begin(), _customItemsCountInRow.end() ); if ( tableSize.width != maxWidth ) { tableSize.width = maxWidth; calculateRoi(); } } calculateItemsPos(); } protected: // Since we store pointers and the number of elements do not change in a container, vector is the most efficient container to be used. using ItemsIterator = typename std::vector::iterator; using ItemIterPos = std::pair; virtual void SetContentItems() { // Do nothing. } ItemsIterator GetBeginItemIter() { return items.begin(); } ItemsIterator GetEndItemIter() { return items.end(); } virtual void RedrawItemIter( ItemsIterator it, const fheroes2::Rect & pos, fheroes2::Image & output ) { RedrawItem( **it, pos, output ); } virtual bool ActionCursorItemIter( const fheroes2::Point &, ItemIterPos iterPos ) { if ( iterPos.first == GetEndItemIter() ) { return false; } if ( ActionBarCursor( **iterPos.first ) ) { return true; } LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( iterPos.second ) ) { return ActionBarLeftMouseSingleClick( **iterPos.first ); } if ( le.isMouseRightButtonPressedInArea( iterPos.second ) ) { return ActionBarRightMouseHold( **iterPos.first ); } return false; } bool isItemsEmpty() { return items.empty(); } ItemsIterator GetItemIter( const fheroes2::Point & pt ) { return GetItemIterPos( pt ).first; } ItemIterPos GetItemIterPos( const fheroes2::Point & position ) { if ( tableSize.width <= 0 || tableSize.height <= 0 ) { return { items.end(), {} }; } ItemsIterator posItem = items.begin(); auto itemPosIter = itemPos.begin(); const bool useCustomCountX = ( _customItemsCountInRow.size() == static_cast( tableSize.height ) ); for ( int32_t y = 0; y < tableSize.height; ++y ) { const int32_t coutX = useCustomCountX ? _customItemsCountInRow[y] : tableSize.width; for ( int32_t x = 0; x < coutX; ++x ) { if ( posItem != items.end() ) { assert( itemPosIter != itemPos.end() ); const fheroes2::Rect itemRoi( *itemPosIter, singleItemSize ); if ( itemRoi & position ) { return ItemIterPos( posItem, itemRoi ); } ++posItem; ++itemPosIter; } } } return { items.end(), {} }; } std::vector items; std::vector _customItemsCountInRow; private: void calculateItemsPos() { itemPos.clear(); if ( tableSize.width <= 0 || tableSize.height <= 0 ) { return; } const bool useCustomCountX = ( _customItemsCountInRow.size() == static_cast( tableSize.height ) ); const int32_t stepX = ( offsetBetweenItems.width + singleItemSize.width ); const int32_t stepY = ( offsetBetweenItems.height + singleItemSize.height ); for ( int32_t y = 0; y < tableSize.height; ++y ) { const int32_t coutX = useCustomCountX ? _customItemsCountInRow[y] : tableSize.width; const int32_t offsetX = useCustomCountX ? ( tableSize.width - _customItemsCountInRow[y] ) * stepX / 2 : 0; for ( int32_t x = 0; x < coutX; ++x ) { itemPos.emplace_back( renderingRoi.x + x * stepX + offsetX, renderingRoi.y + y * stepY ); } } } void calculateRoi() { if ( tableSize.width > 0 ) { renderingRoi.width = tableSize.width * singleItemSize.width + ( tableSize.width - 1 ) * offsetBetweenItems.width; } else { renderingRoi.width = 0; } if ( tableSize.height > 0 ) { renderingRoi.height = tableSize.height * singleItemSize.height + ( tableSize.height - 1 ) * offsetBetweenItems.height; } else { renderingRoi.height = 0; } } fheroes2::Rect renderingRoi; fheroes2::Size singleItemSize; std::vector itemPos; fheroes2::Size tableSize; fheroes2::Size offsetBetweenItems; }; template class ItemsActionBar : public ItemsBar { public: ItemsActionBar() { ResetSelected(); } ~ItemsActionBar() override = default; void RedrawItem( Item &, const fheroes2::Rect &, fheroes2::Image & ) override { // Do nothing. } virtual void RedrawItem( Item &, const fheroes2::Rect &, bool, fheroes2::Image & ) { // Do nothing. } bool ActionBarCursor( Item & ) override { return false; } virtual bool ActionBarCursor( Item &, Item & ) { return false; } virtual bool ActionBarLeftMouseSingleClick( Item &, Item & ) { return false; } bool ActionBarLeftMouseSingleClick( Item & ) override { return false; } virtual bool ActionBarLeftMouseDoubleClick( Item & item ) { return ActionBarLeftMouseSingleClick( item ); } virtual bool ActionBarLeftMouseRelease( Item & ) { return false; } virtual bool ActionBarLeftMouseRelease( Item &, Item & ) { return false; } virtual bool ActionBarRightMouseHold( Item &, Item & ) { return false; } virtual bool ActionBarLeftMouseHold( Item &, const fheroes2::Rect & ) { return false; } virtual bool ActionBarLeftMouseHold( Item &, Item & ) { return false; } bool ActionBarRightMouseHold( Item & ) override { return false; } virtual bool ActionBarRightMouseSingleClick( Item & ) { return false; } virtual bool ActionBarRightMouseSingleClick( Item &, Item & ) { return false; } Item * GetSelectedItem() { return *GetCurItemIter(); } fheroes2::Rect * GetSelectedPos() { return &curItemPos.second; } int32_t GetSelectedIndex() { return std::distance( ItemsBar::GetBeginItemIter(), GetCurItemIter() ); } bool isSelected() { return GetCurItemIter() != ItemsBar::GetEndItemIter(); } void ResetSelected() { topItem = ItemsBar::GetBeginItemIter(); curItemPos = ItemIterPos( ItemsBar::items.end(), fheroes2::Rect() ); } bool QueueEventProcessing() { return ItemsBar::QueueEventProcessing(); } bool QueueEventProcessing( ItemsActionBar & other ) { const LocalEvent & le = LocalEvent::Get(); const fheroes2::Point & cursor = le.getMouseCursorPos(); if ( ItemsBar::isItemsEmpty() && other.isItemsEmpty() ) { return false; } if ( other.GetItem( le.getMouseLeftButtonPressedPos() ) && ActionCrossItemBarDrag( cursor, other ) ) { return true; } return other.isSelected() ? ActionCursorItemIter( cursor, other ) : ActionCursorItemIter( cursor, ItemsBar::GetItemIterPos( cursor ) ); } protected: using ItemsIterator = typename ItemsBar::ItemsIterator; using ItemIterPos = typename ItemsBar::ItemIterPos; ItemsIterator GetCurItemIter() { return curItemPos.first; } void SetContentItems() final { ResetSelected(); } void RedrawItemIter( ItemsIterator it, const fheroes2::Rect & pos, fheroes2::Image & output ) override { RedrawItem( **it, pos, GetCurItemIter() == it, output ); } bool ActionCrossItemBarDrag( const fheroes2::Point & cursor, ItemsActionBar & other ) { const LocalEvent & le = LocalEvent::Get(); Item * otherItemPress = other.GetItem( le.getMouseLeftButtonPressedPos() ); assert( otherItemPress != nullptr ); const ItemIterPos iterPos1 = ItemsBar::GetItemIterPos( cursor ); if ( iterPos1.first == ItemsBar::GetEndItemIter() ) return false; if ( le.isMouseLeftButtonPressedInArea( iterPos1.second ) ) { return ActionBarLeftMouseHold( **iterPos1.first, *otherItemPress ); } if ( le.isMouseLeftButtonReleasedInArea( iterPos1.second ) ) { if ( ActionBarLeftMouseRelease( **iterPos1.first, *otherItemPress ) ) { other.ResetSelected(); } return true; } return false; } bool ActionCursorItemIter( const fheroes2::Point &, ItemIterPos iterPos ) override { if ( iterPos.first == ItemsBar::GetEndItemIter() ) { return false; } if ( ActionBarCursor( **iterPos.first ) ) { return true; } LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( iterPos.second ) ) { if ( iterPos.first == GetCurItemIter() ) { return ActionBarLeftMouseDoubleClick( **iterPos.first ); } if ( ActionBarLeftMouseSingleClick( **iterPos.first ) ) { curItemPos = iterPos; } else { ResetSelected(); } return true; } if ( le.isMouseLeftButtonPressedInArea( iterPos.second ) ) { return ActionBarLeftMouseHold( **iterPos.first, iterPos.second ); } if ( le.isMouseLeftButtonReleasedInArea( iterPos.second ) ) { return ActionBarLeftMouseRelease( **iterPos.first ); } if ( le.MouseClickRight( iterPos.second ) ) { return ActionBarRightMouseSingleClick( **iterPos.first ); } if ( le.isMouseRightButtonPressedInArea( iterPos.second ) ) { return ActionBarRightMouseHold( **iterPos.first ); } return false; } bool ActionCursorItemIter( const fheroes2::Point & cursor, ItemsActionBar & other ) { const ItemIterPos iterPos1 = ItemsBar::GetItemIterPos( cursor ); if ( iterPos1.first == ItemsBar::GetEndItemIter() ) { return false; } const ItemIterPos iterPos2 = other.curItemPos; if ( ActionBarCursor( **iterPos1.first, **iterPos2.first ) ) { return true; } LocalEvent & le = LocalEvent::Get(); if ( le.MouseClickLeft( iterPos1.second ) ) { if ( ActionBarLeftMouseSingleClick( **iterPos1.first, **iterPos2.first ) ) curItemPos = iterPos1; else ResetSelected(); other.ResetSelected(); return true; } if ( le.isMouseLeftButtonPressedInArea( iterPos1.second ) ) { return ActionBarLeftMouseHold( **iterPos1.first, **iterPos2.first ); } // Let the ActionCrossItemBarDrag() handle the case of isMouseLeftButtonReleased() if ( le.MouseClickRight( iterPos1.second ) ) { ActionBarRightMouseSingleClick( **iterPos1.first, **iterPos2.first ); other.ResetSelected(); // has to return true to display selection reset return true; } if ( le.isMouseRightButtonPressedInArea( iterPos1.second ) ) { return ActionBarRightMouseHold( **iterPos1.first, **iterPos2.first ); } return false; } ItemsIterator topItem; ItemIterPos curItemPos; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_list.h000066400000000000000000000477721476115357100224420ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2010 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "localevent.h" #include "ui_button.h" #include "ui_scrollbar.h" namespace Interface { class ListBasic { public: virtual ~ListBasic() = default; virtual bool IsNeedRedraw() const = 0; virtual void Redraw() = 0; virtual bool QueueEventProcessing() = 0; int getTopId() const { return _topId; } protected: int _currentId{ -1 }; int _topId{ -1 }; }; template class ListBox : public ListBasic { public: explicit ListBox( const fheroes2::Point & pt = fheroes2::Point() ) : ptRedraw( pt ) , _timedButtonPgUp( [this]() { return _buttonPgUp.isPressed(); } ) , _timedButtonPgDn( [this]() { return _buttonPgDn.isPressed(); } ) { _buttonPgUp.subscribe( &_timedButtonPgUp ); _buttonPgDn.subscribe( &_timedButtonPgDn ); } ~ListBox() override = default; virtual void RedrawItem( const Item &, int32_t ox, int32_t oy, bool current ) = 0; virtual void RedrawBackground( const fheroes2::Point & ) = 0; virtual void ActionCurrentUp() = 0; virtual void ActionCurrentDn() = 0; virtual void ActionListDoubleClick( Item & ) = 0; virtual void ActionListSingleClick( Item & ) = 0; virtual void ActionListPressRight( Item & ) = 0; virtual void ActionListDoubleClick( Item & item, const fheroes2::Point & /*mousePos*/, int32_t /*itemOffsetX*/, int32_t /*itemOffsetY*/ ) { ActionListDoubleClick( item ); } virtual void ActionListSingleClick( Item & item, const fheroes2::Point & /*mousePos*/, int32_t /*itemOffsetX*/, int32_t /*itemOffsetY*/ ) { ActionListSingleClick( item ); } virtual void ActionListPressRight( Item & item, const fheroes2::Point & /*mousePos*/, int32_t /*itemOffsetX*/, int32_t /*itemOffsetY*/ ) { ActionListPressRight( item ); } virtual bool ActionListCursor( Item & /* item */, const fheroes2::Point & /* cursor */ ) { return false; } void SetTopLeft( const fheroes2::Point & tl ) { ptRedraw = tl; } void SetScrollButtonUp( int icn, uint32_t index1, uint32_t index2, const fheroes2::Point & pos ) { _buttonPgUp.setICNInfo( icn, index1, index2 ); _buttonPgUp.setPosition( pos.x, pos.y ); } void SetScrollButtonDn( int icn, uint32_t index1, uint32_t index2, const fheroes2::Point & pos ) { _buttonPgDn.setICNInfo( icn, index1, index2 ); _buttonPgDn.setPosition( pos.x, pos.y ); } void setScrollBarArea( const fheroes2::Rect & area ) { _scrollbar.setArea( area ); } void setScrollBarImage( const fheroes2::Image & image ) { _scrollbar.setImage( image ); } fheroes2::Scrollbar & GetScrollbar() { return _scrollbar; } void SetAreaMaxItems( int maxValue ) { maxItems = maxValue; Reset(); } void SetAreaItems( const fheroes2::Rect & rt ) { rtAreaItems = rt; } void SetListContent( std::vector & list ) { content = &list; Reset(); if ( IsValid() ) { _currentId = 0; } } void Reset() { if ( content == nullptr || content->empty() ) { // Empty content. It is non-initialized array, initialize it. _currentId = -1; _topId = -1; _scrollbar.setRange( 0, 0 ); } else { _currentId = -1; // no selection _topId = 0; const int newMaxValue = std::max( _size() - maxItems, 0 ); _scrollbar.setRange( 0, newMaxValue ); } } void DisableHotkeys( bool f ) { useHotkeys = !f; } void Redraw() override { needRedraw = false; RedrawBackground( ptRedraw ); _buttonPgUp.draw(); _buttonPgDn.draw(); _scrollbar.redraw(); Verify(); // reset values if they are wrong if ( IsValid() ) { // we have something to display int id = _topId; const int end = ( _topId + maxItems ) > _size() ? _size() - _topId : _topId + maxItems; for ( ; id < end; ++id ) { RedrawItem( ( *content )[id], rtAreaItems.x, rtAreaItems.y + ( id - _topId ) * rtAreaItems.height / maxItems, id == _currentId ); } } } bool IsValid() const { return content != nullptr && !content->empty() && _topId >= 0 && _topId < _size() && _currentId < _size() && maxItems > 0; } bool IsNeedRedraw() const override { return needRedraw; } Item & GetCurrent() // always call this function only after IsValid()! { return ( *content )[_currentId]; } Item * GetFromPosition( const fheroes2::Point & mp ) { Verify(); if ( !IsValid() ) { return nullptr; } if ( mp.y < rtAreaItems.y || mp.y >= rtAreaItems.y + rtAreaItems.height ) { // Out of boundaries. return nullptr; } if ( mp.x < rtAreaItems.x || mp.x >= rtAreaItems.x + rtAreaItems.width ) { // Out of boundaries. return nullptr; } const int id = ( mp.y - rtAreaItems.y ) * maxItems / rtAreaItems.height; if ( _topId + id >= _size() ) { // Out of items. return nullptr; } return &( *content )[_topId + id]; } void SetCurrent( size_t posId ) { if ( posId < content->size() ) { _currentId = static_cast( posId ); } SetCurrentVisible(); } void SetCurrentVisible() { Verify(); if ( !IsValid() ) { Reset(); return; } if ( _currentId >= 0 && ( _topId > _currentId || _topId + maxItems <= _currentId ) ) { // out of view if ( _topId > _currentId ) { // Scroll up, put current id on top. _topId = _currentId; } else if ( _topId + maxItems <= _currentId ) { // Scroll down, put current id at bottom. _topId = _currentId + 1 - maxItems; } } UpdateScrollbarRange(); _scrollbar.moveToIndex( _topId ); } // Move visible area to the position with given element ID being on the top of the list. void setTopVisibleItem( const int topId ) { Verify(); if ( !IsValid() ) { Reset(); return; } _topId = std::max( 0, std::min( topId, _size() - maxItems ) ); UpdateScrollbarRange(); _scrollbar.moveToIndex( _topId ); } void SetCurrent( const Item & item ) { const typename std::vector::iterator pos = std::find( content->begin(), content->end(), item ); if ( pos == content->end() ) { Reset(); } else { _currentId = static_cast( pos - content->begin() ); } SetCurrentVisible(); } void RemoveSelected() { if ( content != nullptr && _currentId >= 0 && _currentId < _size() ) { content->erase( content->begin() + _currentId ); if ( _currentId < _topId && _topId > 0 ) { // The removed item is upper than the list top - reduce the top position. --_topId; } if ( _currentId >= _size() ) { // The removed item is the last in the list - reduce the current position. --_currentId; } // List item is removed, so we need to redraw the list. needRedraw = true; } } bool isSelected() const { return IsValid() && _currentId >= 0; } void Unselect() { Verify(); if ( IsValid() ) { _currentId = -1; // List item is unselected, so we need to redraw the list with no selected elements. needRedraw = true; } } bool QueueEventProcessing() override { LocalEvent & le = LocalEvent::Get(); _buttonPgUp.drawOnState( le.isMouseLeftButtonPressedInArea( _buttonPgUp.area() ) ); _buttonPgDn.drawOnState( le.isMouseLeftButtonPressedInArea( _buttonPgDn.area() ) ); if ( !IsValid() ) { return false; } if ( useHotkeys && le.isKeyPressed( fheroes2::Key::KEY_PAGE_UP ) && ( _topId > 0 ) ) { needRedraw = true; if ( _topId > maxItems ) { _topId -= maxItems; } else { _topId = 0; } UpdateScrollbarRange(); _scrollbar.moveToIndex( _topId ); return true; } if ( useHotkeys && le.isKeyPressed( fheroes2::Key::KEY_PAGE_DOWN ) && ( _topId + maxItems < _size() ) ) { needRedraw = true; _topId += maxItems; if ( _topId + maxItems >= _size() ) { _topId = _size() - maxItems; } UpdateScrollbarRange(); _scrollbar.moveToIndex( _topId ); return true; } if ( useHotkeys && le.isKeyPressed( fheroes2::Key::KEY_UP ) && ( _currentId > 0 ) ) { needRedraw = true; --_currentId; SetCurrentVisible(); ActionCurrentUp(); return true; } if ( useHotkeys && le.isKeyPressed( fheroes2::Key::KEY_DOWN ) && ( _currentId + 1 < _size() ) ) { needRedraw = true; ++_currentId; SetCurrentVisible(); ActionCurrentDn(); return true; } if ( useHotkeys && le.isKeyPressed( fheroes2::Key::KEY_HOME ) && ( _topId > 0 ) ) { needRedraw = true; _topId = 0; UpdateScrollbarRange(); _scrollbar.moveToIndex( _topId ); return true; } if ( useHotkeys && le.isKeyPressed( fheroes2::Key::KEY_END ) && ( _topId + maxItems < _size() ) ) { needRedraw = true; _topId = _size() - maxItems; UpdateScrollbarRange(); _scrollbar.moveToIndex( _topId ); return true; } if ( ( le.MouseClickLeft( _buttonPgUp.area() ) || le.isMouseWheelUpInArea( rtAreaItems ) || le.isMouseWheelUpInArea( _scrollbar.getArea() ) || _timedButtonPgUp.isDelayPassed() ) && ( _topId > 0 ) ) { needRedraw = true; --_topId; _scrollbar.backward(); return true; } if ( ( le.MouseClickLeft( _buttonPgDn.area() ) || le.isMouseWheelDownInArea( rtAreaItems ) || le.isMouseWheelDownInArea( _scrollbar.getArea() ) || _timedButtonPgDn.isDelayPassed() ) && ( _topId + maxItems < _size() ) ) { needRedraw = true; ++_topId; _scrollbar.forward(); return true; } if ( le.isMouseLeftButtonPressedInArea( _scrollbar.getArea() ) || le.isMouseLeftButtonPressedInArea( rtAreaItems ) ) { const fheroes2::Point mousePosition = le.getMouseCursorPos(); const int32_t prevScrollbarX = _scrollbar.x(); const int32_t prevScrollbarY = _scrollbar.y(); UpdateScrollbarRange(); if ( le.isMouseLeftButtonPressedInArea( _scrollbar.getArea() ) && ( _size() > maxItems ) ) { _scrollbar.moveToPos( mousePosition ); } if ( le.isMouseLeftButtonPressedInArea( rtAreaItems ) ) { if ( !le.isDragInProgress() ) { // Remember where has the drag started. _dragStartPos = mousePosition; le.registerDrag(); // We have just started the drag, it might as well be a legitimate click. _lockClick = false; } const int delta = ( _scrollbar.isVertical() ? ( _dragStartPos.y - mousePosition.y ) : ( _dragStartPos.x - mousePosition.x ) ); const int itemSize = ( _scrollbar.isVertical() ? rtAreaItems.height : rtAreaItems.width ) / maxItems; // We have dragged past the size of one list-item. if ( std::abs( delta ) > itemSize ) { // Scroll the list accordingly, update the drag start reference point. _scrollbar.moveToIndex( _scrollbar.currentIndex() + delta / itemSize ); _dragStartPos = mousePosition; // Disable the leftclick on the list, so finishing the drag does not result in clicking on the list-item. _lockClick = true; } } // We don't need to render the scrollbar if it's position is not changed. if ( ( _scrollbar.x() == prevScrollbarX ) && ( _scrollbar.y() == prevScrollbarY ) ) { return false; } _topId = _scrollbar.currentIndex(); needRedraw = true; _updateScrollbar = true; return true; } if ( _updateScrollbar ) { _updateScrollbar = false; if ( _scrollbar.updatePosition() ) { needRedraw = true; return true; } } const fheroes2::Point & mousePos = le.getMouseCursorPos(); if ( rtAreaItems & mousePos ) { // within our rectangle needRedraw = true; const int id = ( mousePos.y - rtAreaItems.y ) * maxItems / rtAreaItems.height + _topId; if ( id < _size() ) { Item & item = ( *content )[static_cast( id )]; // id is always >= 0 const int32_t offsetY = ( id - _topId ) * rtAreaItems.height / maxItems; if ( ActionListCursor( item, mousePos ) ) { return true; } if ( !_lockClick && le.MouseClickLeft( rtAreaItems ) ) { // This is a legitimate click and not a mouse-up on a finished drag. if ( id == _currentId ) { ActionListDoubleClick( item, mousePos, rtAreaItems.x, rtAreaItems.y + offsetY ); } else { _currentId = id; ActionListSingleClick( item, mousePos, rtAreaItems.x, rtAreaItems.y + offsetY ); } return true; } if ( le.isMouseRightButtonPressedInArea( rtAreaItems ) ) { ActionListPressRight( item, mousePos, rtAreaItems.x, rtAreaItems.y + offsetY ); return true; } } needRedraw = false; } return false; } protected: bool needRedraw{ false }; fheroes2::Rect rtAreaItems; fheroes2::Button _buttonPgUp; fheroes2::Button _buttonPgDn; fheroes2::Scrollbar _scrollbar; int VisibleItemCount() const { return maxItems; } int _size() const { return content == nullptr ? 0 : static_cast( content->size() ); } private: std::vector * content{ nullptr }; int maxItems{ 0 }; fheroes2::Point ptRedraw; fheroes2::Point _dragStartPos; bool useHotkeys{ true }; bool _updateScrollbar{ false }; bool _lockClick{ false }; fheroes2::TimedEventValidator _timedButtonPgUp; fheroes2::TimedEventValidator _timedButtonPgDn; void Verify() { if ( content == nullptr || content->empty() ) { _currentId = -1; _topId = -1; } else { const int listSize = _size(); const int maxTopId = std::max( listSize - maxItems, 0 ); if ( _currentId >= listSize ) { _currentId = -1; } if ( _topId < 0 || _topId > maxTopId ) { // Top position is out of list boundaries. if ( _currentId == -1 ) { // There is no item selected. Show the list from its very top. _topId = 0; } else { // Set top position to show the selected item. _topId = std::clamp( _currentId - maxItems / 2, 0, maxTopId ); } } // Update scrollbar range if needed. if ( _scrollbar.maxIndex() != maxTopId ) { _scrollbar.setRange( 0, maxTopId ); _scrollbar.moveToIndex( _topId ); } } } void UpdateScrollbarRange() { const int newMaxValue = _size() - maxItems; const int maxValue = ( content != nullptr && newMaxValue > 0 ) ? newMaxValue : 0; if ( _scrollbar.maxIndex() != maxValue ) { _scrollbar.setRange( 0, maxValue ); } } }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_radar.cpp000066400000000000000000000471561476115357100231070ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_radar.h" #include #include #include "agg_image.h" #include "castle.h" #include "color.h" #include "dialog.h" #include "ground.h" #include "heroes.h" #include "icn.h" #include "interface_base.h" #include "interface_gamearea.h" #include "localevent.h" #include "maps_tiles.h" #include "mp2.h" #include "players.h" #include "screen.h" #include "settings.h" #include "translations.h" #include "ui_constants.h" #include "ui_dialog.h" #include "world.h" #ifdef WITH_DEBUG #include "logging.h" #endif namespace { enum : uint8_t { RADARCOLOR = 0xB5, // index palette COLOR_DESERT = 0x76, COLOR_SNOW = 0x0D, COLOR_SWAMP = 0x68, COLOR_WASTELAND = 0xCE, COLOR_BEACH = 0x29, COLOR_LAVA = 0x20, COLOR_DIRT = 0x36, COLOR_GRASS = 0x62, COLOR_WATER = 0x4D, COLOR_ROAD = 0x7A, COLOR_BLUE = 0x47, COLOR_GREEN = 0x5D, COLOR_RED = 0xbd, COLOR_YELLOW = 0x70, COLOR_ORANGE = 0xCA, COLOR_PURPLE = 0x87, COLOR_GRAY = 0x10, COLOR_WHITE = 0x0a, COLOR_BLACK = 0x00 }; uint8_t GetPaletteIndexFromGround( int ground ) { switch ( ground ) { case Maps::Ground::DESERT: return COLOR_DESERT; case Maps::Ground::SNOW: return COLOR_SNOW; case Maps::Ground::SWAMP: return COLOR_SWAMP; case Maps::Ground::WASTELAND: return COLOR_WASTELAND; case Maps::Ground::BEACH: return COLOR_BEACH; case Maps::Ground::LAVA: return COLOR_LAVA; case Maps::Ground::DIRT: return COLOR_DIRT; case Maps::Ground::GRASS: return COLOR_GRASS; case Maps::Ground::WATER: return COLOR_WATER; default: break; } return COLOR_BLACK; } uint8_t GetPaletteIndexFromColor( int color ) { switch ( color ) { case Color::BLUE: return COLOR_BLUE; case Color::GREEN: return COLOR_GREEN; case Color::RED: return COLOR_RED; case Color::YELLOW: return COLOR_YELLOW; case Color::ORANGE: return COLOR_ORANGE; case Color::PURPLE: return COLOR_PURPLE; default: break; } return COLOR_WHITE; } bool getCastleColor( uint8_t & fillColor, const fheroes2::Point & position ) { const Castle * castle = world.getCastle( position ); if ( castle != nullptr ) { fillColor = GetPaletteIndexFromColor( castle->GetColor() ); return true; } return false; } } Interface::Radar::Radar( BaseInterface & interface ) : BorderWindow( { 0, 0, fheroes2::radarWidthPx, fheroes2::radarWidthPx } ) , _radarType( RadarType::WorldMap ) , _interface( interface ) { // Initialize radar image (_map) as a single-layer image. _map._disableTransformLayer(); _map.resize( fheroes2::radarWidthPx, fheroes2::radarWidthPx ); } Interface::Radar::Radar( const Radar & radar, const fheroes2::Display & display ) : BorderWindow( { display.width() - fheroes2::borderWidthPx - fheroes2::radarWidthPx, fheroes2::borderWidthPx, fheroes2::radarWidthPx, fheroes2::radarWidthPx } ) , _radarType( RadarType::ViewWorld ) , _interface( radar._interface ) , _roi( 0, 0, world.w(), world.h() ) , _zoom( radar._zoom ) , _hide( false ) { // Initialize radar image (_map) as a single-layer image. _map._disableTransformLayer(); _map.resize( fheroes2::radarWidthPx, fheroes2::radarWidthPx ); } void Interface::Radar::SavePosition() { Settings & conf = Settings::Get(); conf.SetPosRadar( GetRect().getPosition() ); conf.Save( Settings::configFileName ); } void Interface::Radar::SetPos( int32_t x, int32_t y ) { BorderWindow::SetPosition( x, y ); } void Interface::Radar::Build() { SetZoom(); _roi = { 0, 0, world.w(), world.h() }; } void Interface::Radar::SetZoom() { const int32_t worldWidth = world.w(); // Currently we have and support only square size maps. assert( worldWidth == world.h() ); _zoom = static_cast( area.width ) / worldWidth; // Currently we have and support only maps with 36 - 144 tiles width and height. assert( ( _zoom >= 1.0 ) && ( _zoom <= 4.0 ) ); } void Interface::Radar::SetRedraw( const uint32_t redrawMode ) const { // Only radar redraws are allowed here. assert( ( redrawMode & ~( REDRAW_RADAR_CURSOR | REDRAW_RADAR ) ) == 0 ); _interface.setRedraw( redrawMode ); } void Interface::Radar::SetRenderArea( const fheroes2::Rect & roi ) { const Settings & conf = Settings::Get(); // We set ROI only if radar is visible as there will be no render of radar map image if it is hidden. if ( !conf.isHideInterfaceEnabled() || conf.ShowRadar() ) { // "_roi" should not be outside the "world". _roi = roi ^ fheroes2::Rect( 0, 0, world.w(), world.h() ); } } void Interface::Radar::_redraw( const bool redrawMapObjects ) { const Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() ) { if ( conf.ShowRadar() ) { BorderWindow::Redraw(); } else { // We are in "Hide Interface" mode and radar is turned off so we have nothing to render. // Force set radar ROI for the whole world to be prepared to fully update radar when it will be shown. _roi = { 0, 0, world.w(), world.h() }; return; } } fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Rect & rect = GetArea(); if ( _hide ) { fheroes2::Blit( fheroes2::AGG::GetICN( ( conf.isEvilInterfaceEnabled() ? ICN::HEROLOGE : ICN::HEROLOGO ), 0 ), display, rect.x, rect.y ); // Force set radar ROI for the whole world to be prepared to fully update radar when it will be shown. _roi = { 0, 0, world.w(), world.h() }; } else { _cursorArea.hide(); if ( redrawMapObjects ) { RedrawObjects( Players::FriendColors(), ViewWorldMode::OnlyVisible ); } fheroes2::Copy( _map, 0, 0, display, rect.x, rect.y, _map.width(), _map.height() ); _cursorArea.show(); RedrawCursor(); } } void Interface::Radar::RedrawForViewWorld( const ViewWorld::ZoomROIs & roi, const ViewWorldMode mode, const bool renderMapObjects ) { _cursorArea.hide(); if ( renderMapObjects ) { RedrawObjects( Players::FriendColors(), mode ); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Rect & rect = GetArea(); fheroes2::Copy( _map, 0, 0, display, rect.x, rect.y, _map.width(), _map.height() ); } const fheroes2::Rect roiInTiles = roi.GetROIinTiles(); _cursorArea.show(); RedrawCursor( &roiInTiles ); } void Interface::Radar::redrawForEditor( const bool renderMapObjects ) { _cursorArea.hide(); if ( renderMapObjects ) { RedrawObjects( 0, ViewWorldMode::ViewAll ); const fheroes2::Rect & rect = GetArea(); fheroes2::Copy( _map, 0, 0, fheroes2::Display::instance(), rect.x, rect.y, _map.width(), _map.height() ); } _cursorArea.show(); RedrawCursor(); } void Interface::Radar::RedrawObjects( const int32_t playerColor, const ViewWorldMode flags ) { #ifdef WITH_DEBUG const bool revealAll = ( flags == ViewWorldMode::ViewAll ) || IS_DEVEL(); #else const bool revealAll = flags == ViewWorldMode::ViewAll; #endif uint8_t * radarImage = _map.image(); assert( _roi.x >= 0 && _roi.y >= 0 && ( _roi.width + _roi.x ) <= world.w() && ( _roi.height + _roi.y ) <= world.h() ); // Fill the radar map with black color ( 0 ) only if we are redrawing the entire map. if ( _roi.x == 0 && _roi.y == 0 && _roi.width == world.w() && _roi.height == world.h() ) { std::memset( radarImage, COLOR_BLACK, static_cast( area.width ) * area.height ); } const bool revealMines = revealAll || ( flags == ViewWorldMode::ViewMines ); const bool revealHeroes = revealAll || ( flags == ViewWorldMode::ViewHeroes ); const bool revealTowns = revealAll || ( flags == ViewWorldMode::ViewTowns ); const bool revealArtifacts = revealAll || ( flags == ViewWorldMode::ViewArtifacts ); const bool revealResources = revealAll || ( flags == ViewWorldMode::ViewResources ); const bool revealOnlyVisible = revealAll || ( flags == ViewWorldMode::OnlyVisible ); const int32_t radarWidth = _map.width(); const bool isZoomIn = _zoom > 1.0; const int32_t maxRoiX = _roi.width + _roi.x; const int32_t maxRoiY = _roi.height + _roi.y; const uint8_t * radarYEnd = nullptr; for ( int32_t y = _roi.y; y < maxRoiY; ++y ) { uint8_t * radarY = radarImage + static_cast( y * _zoom ) * radarWidth; if ( isZoomIn ) { radarYEnd = radarImage + static_cast( ( y + 1 ) * _zoom ) * radarWidth; } for ( int32_t x = _roi.x; x < maxRoiX; ++x ) { const Maps::Tile & tile = world.getTile( x, y ); const bool visibleTile = revealAll || !tile.isFog( playerColor ); uint8_t fillColor = 0; const MP2::MapObjectType objectType = tile.getMainObjectType( revealOnlyVisible || revealHeroes ); switch ( objectType ) { case MP2::OBJ_HERO: { if ( visibleTile || revealHeroes ) { const Heroes * hero = world.GetHeroes( { x, y } ); if ( hero ) { fillColor = GetPaletteIndexFromColor( hero->GetColor() ); break; } } continue; } case MP2::OBJ_LIGHTHOUSE: case MP2::OBJ_ALCHEMIST_LAB: case MP2::OBJ_MINE: case MP2::OBJ_SAWMILL: // TODO: Why Lighthouse is in this category? Verify the logic! if ( visibleTile || revealMines ) { fillColor = GetPaletteIndexFromColor( world.ColorCapturedObject( tile.GetIndex() ) ); break; } continue; case MP2::OBJ_NON_ACTION_LIGHTHOUSE: case MP2::OBJ_NON_ACTION_ALCHEMIST_LAB: case MP2::OBJ_NON_ACTION_MINE: case MP2::OBJ_NON_ACTION_SAWMILL: // TODO: Why Lighthouse is in this category? Verify the logic! if ( visibleTile || revealMines ) { const int32_t mainTileIndex = Maps::Tile::getIndexOfMainTile( tile ); if ( mainTileIndex >= 0 ) { fillColor = GetPaletteIndexFromColor( world.ColorCapturedObject( mainTileIndex ) ); break; } } continue; case MP2::OBJ_ARTIFACT: if ( visibleTile || revealArtifacts ) { fillColor = COLOR_GRAY; break; } continue; case MP2::OBJ_RESOURCE: if ( visibleTile || revealResources ) { fillColor = COLOR_GRAY; break; } continue; default: if ( visibleTile ) { // Castles and Towns can be partially covered by other non-action objects so we need to rely on special storage of castle's tiles. if ( !getCastleColor( fillColor, { x, y } ) ) { // This is a visible tile and not covered by other objects, so fill it with the ground tile data. if ( tile.isRoad() ) { fillColor = COLOR_ROAD; } else { fillColor = GetPaletteIndexFromGround( tile.GetGround() ); if ( objectType == MP2::OBJ_MOUNTAINS || objectType == MP2::OBJ_TREES ) { fillColor += 3; } } } } else if ( revealTowns ) { getCastleColor( fillColor, { x, y } ); } else { // Non visible tile, we have already black radar so skip the render of this tile. continue; } } const size_t offsetX = static_cast( x * _zoom ); uint8_t * radarX = radarY + offsetX; if ( isZoomIn ) { const uint8_t * radarXEnd = radarYEnd + offsetX; const size_t radarXStep = static_cast( ( x + 1 ) * _zoom ) - offsetX; for ( ; radarX != radarXEnd; radarX += radarWidth ) { std::memset( radarX, fillColor, radarXStep ); } } else { *radarX = fillColor; } } } // Reset ROI to full radar image to be able to redraw the mini-map without calling 'SetMapRedraw()'. _roi = { 0, 0, world.w(), world.h() }; } // Redraw radar cursor. RoiRectangle is a rectangle in tile unit of the current radar view. void Interface::Radar::RedrawCursor( const fheroes2::Rect * roiRectangle /* = nullptr */ ) { const Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() && !conf.ShowRadar() && _radarType != RadarType::ViewWorld ) { return; } const fheroes2::Rect worldSize{ 0, 0, world.w(), world.h() }; if ( worldSize.width < 1 || worldSize.height < 1 ) { return; } const fheroes2::Rect & viewableWorldArea = ( roiRectangle == nullptr ) ? _interface.getGameArea().GetVisibleTileROI() : *roiRectangle; if ( ( viewableWorldArea.width > worldSize.width ) && ( viewableWorldArea.height > worldSize.height ) ) { // We hide the cursor if the whole map is displayed. _cursorArea.resize( 0, 0 ); _cursorArea.reset(); _cursorArea.setPosition( 0, 0 ); } else { const fheroes2::Rect radarWorldArea = worldSize ^ viewableWorldArea; const fheroes2::Rect & totalRenderingArea = GetArea(); const fheroes2::Size actualRenderingArea{ totalRenderingArea.width, totalRenderingArea.height }; const fheroes2::Size cursorSize{ ( radarWorldArea.width * actualRenderingArea.width ) / worldSize.width, ( radarWorldArea.height * actualRenderingArea.height ) / worldSize.height }; if ( _cursorArea.width() != cursorSize.width || _cursorArea.height() != cursorSize.height ) { _cursorArea.resize( cursorSize.width, cursorSize.height ); _cursorArea.reset(); fheroes2::DrawBorder( _cursorArea, RADARCOLOR, 6 ); } _cursorArea.setPosition( totalRenderingArea.x + ( radarWorldArea.x * actualRenderingArea.width ) / worldSize.width, totalRenderingArea.y + ( radarWorldArea.y * actualRenderingArea.height ) / worldSize.height ); } } void Interface::Radar::QueueEventProcessing() { captureMouse(); // Move the window border if ( Settings::Get().ShowRadar() && BorderWindow::QueueEventProcessing() ) { _cursorArea.hide(); _interface.setRedraw( REDRAW_RADAR_CURSOR ); return; } LocalEvent & le = LocalEvent::Get(); const fheroes2::Rect & rect = GetArea(); if ( !le.isMouseCursorPosInArea( rect ) ) { return; } if ( le.MouseClickLeft( rect ) || le.isMouseLeftButtonPressedInArea( rect ) ) { const fheroes2::Point & pt = le.getMouseCursorPos(); if ( rect & pt ) { GameArea & gamearea = _interface.getGameArea(); fheroes2::Rect visibleROI( gamearea.GetVisibleTileROI() ); const fheroes2::Point prev( visibleROI.x, visibleROI.y ); gamearea.SetCenter( { ( pt.x - rect.x ) * world.w() / rect.width, ( pt.y - rect.y ) * world.h() / rect.height } ); visibleROI = gamearea.GetVisibleTileROI(); if ( prev.x != visibleROI.x || prev.y != visibleROI.y ) { _interface.setRedraw( REDRAW_RADAR_CURSOR ); gamearea.SetRedraw(); } } } else if ( le.isMouseRightButtonPressedInArea( GetRect() ) ) { fheroes2::showStandardTextMessage( _( "World Map" ), _( "A miniature view of the known world. Left click to move viewing area." ), Dialog::ZERO ); } } bool Interface::Radar::QueueEventProcessingForWorldView( ViewWorld::ZoomROIs & roi ) const { LocalEvent & le = LocalEvent::Get(); const fheroes2::Rect & rect = GetArea(); // move cursor if ( le.isMouseCursorPosInArea( rect ) ) { if ( le.MouseClickLeft( rect ) || le.isMouseLeftButtonPressedInArea( rect ) ) { const fheroes2::Point & pt = le.getMouseCursorPos(); if ( rect & pt ) { const fheroes2::Rect & initROI = roi.GetROIinPixels(); const fheroes2::Point prevCoordsTopLeft( initROI.x, initROI.y ); const fheroes2::Point newCoordsCenter( ( pt.x - rect.x ) * world.w() / rect.width, ( pt.y - rect.y ) * world.h() / rect.height ); const fheroes2::Point newCoordsTopLeft( newCoordsCenter.x - initROI.width / 2, newCoordsCenter.y - initROI.height / 2 ); if ( prevCoordsTopLeft != newCoordsTopLeft ) { return roi.ChangeCenter( { newCoordsCenter.x * fheroes2::tileWidthPx - fheroes2::tileWidthPx / 2, newCoordsCenter.y * fheroes2::tileWidthPx - fheroes2::tileWidthPx / 2 } ); } } } else if ( le.isMouseRightButtonPressedInArea( GetRect() ) ) { fheroes2::showStandardTextMessage( _( "World Map" ), _( "A miniature view of the known world. Left click to move viewing area." ), Dialog::ZERO ); } else if ( le.isMouseWheelUp() ) { return roi.zoomIn( false ); } if ( le.isMouseWheelDown() ) { return roi.zoomOut( false ); } } return false; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_radar.h000066400000000000000000000102301476115357100225330ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "image.h" #include "interface_border.h" #include "math_base.h" #include "ui_tool.h" #include "view_world.h" namespace fheroes2 { class Display; } namespace Interface { class BaseInterface; class Radar final : public BorderWindow { public: explicit Radar( BaseInterface & interface ); // Creates a radar with a fixed position at the top right of the screen, // based on an existing radar and suitable for the View World window Radar( const Radar & radar, const fheroes2::Display & display ); Radar( const Radar & ) = delete; ~Radar() override = default; Radar & operator=( const Radar & ) = delete; void SetPos( int32_t x, int32_t y ) override; // Set the render redraw flag from Interface::Redraw enumeration: // - 'REDRAW_RADAR' - to redraw the radar map image fully or in ROI and render the cursor over it. // - 'REDRAW_RADAR_CURSOR' - to render the previously generated radar map image and the cursor over it. void SetRedraw( const uint32_t redrawMode ) const; // Set the "need" of render the radar map only in the given 'roi' on next radar Redraw call. void SetRenderArea( const fheroes2::Rect & roi ); void Build(); void RedrawForViewWorld( const ViewWorld::ZoomROIs & roi, ViewWorldMode mode, const bool renderMapObjects ); void redrawForEditor( const bool renderMapObjects ); void SetHide( bool f ) { _hide = f; } void QueueEventProcessing(); bool QueueEventProcessingForWorldView( ViewWorld::ZoomROIs & roi ) const; // Do not call this method directly, use Interface::AdventureMap::redraw() instead to avoid issues in the "no interface" mode. // The name of this method starts from _ on purpose to do not mix with other public methods. void _redraw( const bool redrawMapObjects ); private: enum class RadarType : char { WorldMap, ViewWorld }; void SavePosition() override; void SetZoom(); void RedrawObjects( const int32_t playerColor, const ViewWorldMode flags ); void RedrawCursor( const fheroes2::Rect * roiRectangle = nullptr ); RadarType _radarType; BaseInterface & _interface; fheroes2::Image _map; fheroes2::MovableSprite _cursorArea; fheroes2::Rect _roi; double _zoom{ 1.0 }; bool _hide{ true }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_status.cpp000066400000000000000000000445041476115357100233330ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "interface_status.h" #include #include #include #include "agg_image.h" #include "army.h" #include "castle.h" #include "color.h" #include "dialog.h" #include "game.h" #include "game_delays.h" #include "game_interface.h" #include "heroes.h" #include "icn.h" #include "image.h" #include "interface_base.h" #include "kingdom.h" #include "localevent.h" #include "math_base.h" #include "players.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_constants.h" #include "ui_dialog.h" #include "ui_text.h" #include "world.h" void Interface::StatusPanel::SavePosition() { Settings & conf = Settings::Get(); conf.SetPosStatus( GetRect().getPosition() ); conf.Save( Settings::configFileName ); } void Interface::StatusPanel::setRedraw() const { _interface.setRedraw( REDRAW_STATUS ); } void Interface::StatusPanel::SetPos( int32_t x, int32_t y ) { const int32_t width = 144; int32_t height = 72; if ( !Settings::Get().isHideInterfaceEnabled() ) { height = fheroes2::Display::instance().height() - y - fheroes2::borderWidthPx; } BorderWindow::SetPosition( x, y, width, height ); } void Interface::StatusPanel::SetState( const StatusType status ) { // SetResource() should be used to set this status assert( status != StatusType::STATUS_RESOURCE ); if ( _state != StatusType::STATUS_RESOURCE ) { _state = status; } } void Interface::StatusPanel::_redraw() const { const Settings & conf = Settings::Get(); if ( conf.isHideInterfaceEnabled() && !conf.ShowStatus() ) { // The window is hidden. return; } const fheroes2::Rect & pos = GetArea(); if ( conf.isHideInterfaceEnabled() ) { fheroes2::Fill( fheroes2::Display::instance(), pos.x, pos.y, pos.width, pos.height, fheroes2::GetColorId( 0x51, 0x31, 0x18 ) ); BorderWindow::Redraw(); } else { _drawBackground(); } // Do not draw anything if the game hasn't really started yet if ( world.CountDay() == 0 ) { return; } // draw info: Day and Funds and Army const fheroes2::Sprite & ston = fheroes2::AGG::GetICN( conf.isEvilInterfaceEnabled() ? ICN::STONBAKE : ICN::STONBACK, 0 ); const int32_t stonHeight = ston.height(); if ( _state == StatusType::STATUS_AITURN ) { _drawAITurns(); } else if ( StatusType::STATUS_UNKNOWN != _state && pos.height >= ( stonHeight * 3 + 15 ) ) { _drawDayInfo(); if ( conf.CurrentColor() & Players::HumanColors() ) { _drawKingdomInfo( stonHeight + 5 ); if ( _state != StatusType::STATUS_RESOURCE ) { _drawArmyInfo( 2 * stonHeight + 10 ); } else { _drawResourceInfo( 2 * stonHeight + 10 ); } } } else if ( StatusType::STATUS_UNKNOWN != _state && pos.height >= ( stonHeight * 2 + 15 ) ) { _drawDayInfo(); switch ( _state ) { case StatusType::STATUS_FUNDS: _drawKingdomInfo( stonHeight + 5 ); break; case StatusType::STATUS_DAY: case StatusType::STATUS_ARMY: _drawArmyInfo( stonHeight + 5 ); break; case StatusType::STATUS_RESOURCE: _drawResourceInfo( stonHeight + 5 ); break; case StatusType::STATUS_UNKNOWN: case StatusType::STATUS_AITURN: assert( 0 ); // we shouldn't even reach this code break; default: break; } } else { switch ( _state ) { case StatusType::STATUS_DAY: _drawDayInfo(); break; case StatusType::STATUS_FUNDS: _drawKingdomInfo(); break; case StatusType::STATUS_ARMY: _drawArmyInfo(); break; case StatusType::STATUS_RESOURCE: _drawResourceInfo(); break; case StatusType::STATUS_UNKNOWN: case StatusType::STATUS_AITURN: assert( 0 ); // we shouldn't even reach this code break; default: break; } } } void Interface::StatusPanel::NextState() { const int32_t areaHeight = GetArea().height; const fheroes2::Sprite & ston = fheroes2::AGG::GetICN( Settings::Get().isEvilInterfaceEnabled() ? ICN::STONBAKE : ICN::STONBACK, 0 ); const int32_t stonHeight = ston.height(); const bool skipDayStatus = areaHeight >= ( stonHeight * 2 + 15 ) && areaHeight < ( stonHeight * 3 + 15 ); if ( StatusType::STATUS_DAY == _state ) { _state = StatusType::STATUS_FUNDS; } else if ( StatusType::STATUS_FUNDS == _state ) { _state = ( GameFocus::UNSEL == GetFocusType() ? StatusType::STATUS_DAY : StatusType::STATUS_ARMY ); } else if ( StatusType::STATUS_ARMY == _state ) { if ( skipDayStatus ) { _state = StatusType::STATUS_FUNDS; } else { _state = StatusType::STATUS_DAY; } } else if ( StatusType::STATUS_RESOURCE == _state ) { _state = StatusType::STATUS_ARMY; } if ( _state == StatusType::STATUS_ARMY ) { const Castle * castle = GetFocusCastle(); // Skip an empty army in the castle if ( castle && !castle->GetArmy().isValid() ) { NextState(); } } } void Interface::StatusPanel::_drawKingdomInfo( const int32_t offsetY ) const { fheroes2::Point pos = GetArea().getPosition(); const Kingdom & myKingdom = world.GetKingdom( Settings::Get().CurrentColor() ); pos.y += offsetY + 3; // sprite all resource fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( fheroes2::AGG::GetICN( ICN::RESSMALL, 0 ), display, pos.x + 6, pos.y ); pos.y += 27; // count castle fheroes2::Text text( std::to_string( myKingdom.GetCountCastle() ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 26 - text.width() / 2, pos.y, display ); // count town text.set( std::to_string( myKingdom.GetCountTown() ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 78 - text.width() / 2, pos.y, display ); // count gold text.set( std::to_string( myKingdom.GetFunds().Get( Resource::GOLD ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 122 - text.width() / 2, pos.y, display ); pos.y += 30; // count wood text.set( fheroes2::abbreviateNumber( myKingdom.GetFunds().Get( Resource::WOOD ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 15 - text.width() / 2, pos.y, display ); // count mercury text.set( fheroes2::abbreviateNumber( myKingdom.GetFunds().Get( Resource::MERCURY ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 37 - text.width() / 2, pos.y, display ); // count ore text.set( fheroes2::abbreviateNumber( myKingdom.GetFunds().Get( Resource::ORE ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 60 - text.width() / 2, pos.y, display ); // count sulfur text.set( fheroes2::abbreviateNumber( myKingdom.GetFunds().Get( Resource::SULFUR ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 84 - text.width() / 2, pos.y, display ); // count crystal text.set( fheroes2::abbreviateNumber( myKingdom.GetFunds().Get( Resource::CRYSTAL ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 108 - text.width() / 2, pos.y, display ); // count gems text.set( fheroes2::abbreviateNumber( myKingdom.GetFunds().Get( Resource::GEMS ) ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + 130 - text.width() / 2, pos.y, display ); } void Interface::StatusPanel::_drawDayInfo( const int32_t offsetY ) const { const fheroes2::Rect & pos = GetArea(); const int dayOfWeek = world.GetDay(); const int weekOfMonth = world.GetWeek(); const uint32_t month = world.GetMonth(); const int icnType = Settings::Get().isEvilInterfaceEnabled() ? ICN::SUNMOONE : ICN::SUNMOON; uint32_t icnId = dayOfWeek > 1 ? 0 : ( ( weekOfMonth - 1 ) % 4 ) + 1; // Special case if ( dayOfWeek == 1 && weekOfMonth == 1 && month == 1 ) { icnId = 0; } fheroes2::Display & display = fheroes2::Display::instance(); fheroes2::Blit( fheroes2::AGG::GetICN( icnType, icnId ), display, pos.x, pos.y + 1 + offsetY ); std::string message = _( "Month: %{month} Week: %{week}" ); StringReplace( message, "%{month}", month ); StringReplace( message, "%{week}", weekOfMonth ); fheroes2::Text text( message, fheroes2::FontType::smallWhite() ); text.draw( pos.x + ( pos.width - text.width() ) / 2, pos.y + 32 + offsetY, display ); message = _( "Day: %{day}" ); StringReplace( message, "%{day}", dayOfWeek ); text.set( message, fheroes2::FontType::normalWhite() ); text.draw( pos.x + ( pos.width - text.width() ) / 2, pos.y + 48 + offsetY, display ); } void Interface::StatusPanel::SetResource( const int resource, const uint32_t count ) { _lastResource = resource; _lastResourceCount = count; _state = StatusType::STATUS_RESOURCE; _showLastResourceDelay.reset(); } void Interface::StatusPanel::_drawResourceInfo( const int32_t offsetY ) const { const fheroes2::Rect & pos = GetArea(); fheroes2::Display & display = fheroes2::Display::instance(); std::string message = _( "You find a small\nquantity of %{resource}." ); StringReplace( message, "%{resource}", Resource::String( _lastResource ) ); fheroes2::Text text{ std::move( message ), fheroes2::FontType::smallWhite() }; text.draw( pos.x, pos.y + 6 + offsetY, pos.width, display ); const fheroes2::Sprite & spr = fheroes2::AGG::GetICN( ICN::RESOURCE, Resource::getIconIcnIndex( _lastResource ) ); fheroes2::Blit( spr, display, pos.x + ( pos.width - spr.width() ) / 2, pos.y + 6 + offsetY + text.height( pos.width ) ); text.set( std::to_string( _lastResourceCount ), fheroes2::FontType::smallWhite() ); text.draw( pos.x + ( pos.width - text.width() ) / 2, pos.y + offsetY + text.height() * 2 + spr.height() + 10, display ); } void Interface::StatusPanel::_drawArmyInfo( const int32_t offsetY ) const { const Army * armies = nullptr; if ( GetFocusHeroes() ) { armies = &GetFocusHeroes()->GetArmy(); } else if ( GetFocusCastle() ) { armies = &GetFocusCastle()->GetArmy(); } if ( armies ) { const fheroes2::Rect & pos = GetArea(); Army::drawMultipleMonsterLines( *armies, pos.x + 4, pos.y + 1 + offsetY, 138, true, true ); } } void Interface::StatusPanel::_drawAITurns() const { // restore background _drawBackground(); fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Sprite & glass = fheroes2::AGG::GetICN( ICN::HOURGLAS, 0 ); const fheroes2::Rect & statusRoi = GetArea(); int32_t posX = statusRoi.x + ( statusRoi.width - glass.width() ) / 2; int32_t posY = statusRoi.y + ( statusRoi.height - glass.height() ) / 2; fheroes2::Blit( glass, display, posX, posY ); uint32_t colorIndex = 0; switch ( Settings::Get().CurrentColor() ) { case Color::BLUE: break; case Color::GREEN: colorIndex = 1; break; case Color::RED: colorIndex = 2; break; case Color::YELLOW: colorIndex = 3; break; case Color::ORANGE: colorIndex = 4; break; case Color::PURPLE: colorIndex = 5; break; default: // Have you added a new player color? Check the logic above! assert( 0 ); return; } const fheroes2::Sprite & crest = fheroes2::AGG::GetICN( ICN::BRCREST, colorIndex ); posX += 2; posY += 2; fheroes2::Blit( crest, display, posX, posY ); posX += glass.width() - 3; uint32_t animationIndex = Game::getAdventureMapAnimationIndex() - _grainsAnimationIndexOffset; if ( animationIndex < 10 ) { // Start of the sand grains animation. animationIndex = 11 + ( animationIndex % 10 ); } else { // Sand grains animation loop. animationIndex = 21 + ( animationIndex % 10 ); } const fheroes2::Sprite & sandGains = fheroes2::AGG::GetICN( ICN::HOURGLAS, animationIndex ); fheroes2::Blit( sandGains, display, posX - sandGains.width() - sandGains.x(), posY + sandGains.y() ); const fheroes2::Sprite & sand = fheroes2::AGG::GetICN( ICN::HOURGLAS, 1 + ( _aiTurnProgress % 10 ) ); fheroes2::Blit( sand, display, posX - sand.width() - sand.x(), posY + sand.y() ); } void Interface::StatusPanel::_drawBackground() const { fheroes2::Display & display = fheroes2::Display::instance(); const fheroes2::Sprite & icnston = fheroes2::AGG::GetICN( Settings::Get().isEvilInterfaceEnabled() ? ICN::STONBAKE : ICN::STONBACK, 0 ); const fheroes2::Rect & pos = GetArea(); if ( !Settings::Get().isHideInterfaceEnabled() && display.height() - fheroes2::borderWidthPx - icnston.height() > pos.y ) { // top const int32_t startY = 11; const int32_t copyHeight = 46; fheroes2::Rect srcrt( 0, 0, icnston.width(), startY ); fheroes2::Point dstpt( pos.x, pos.y ); fheroes2::Copy( icnston, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); // middle srcrt.y = startY; srcrt.height = copyHeight; const int32_t count = ( pos.height - ( icnston.height() - copyHeight ) ) / copyHeight; for ( int32_t i = 0; i < count; ++i ) { dstpt = fheroes2::Point( pos.x, pos.y + copyHeight * i + startY ); fheroes2::Copy( icnston, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); } // bottom srcrt.height = icnston.height() - startY; dstpt = fheroes2::Point( pos.x, pos.y + pos.height - srcrt.height ); fheroes2::Copy( icnston, srcrt.x, srcrt.y, display, dstpt.x, dstpt.y, srcrt.width, srcrt.height ); } else { fheroes2::Copy( icnston, 0, 0, display, pos.x, pos.y, icnston.width(), icnston.height() ); } } void Interface::StatusPanel::QueueEventProcessing() { captureMouse(); // Move the window border if ( Settings::Get().ShowStatus() && BorderWindow::QueueEventProcessing() ) { setRedraw(); return; } LocalEvent & le = LocalEvent::Get(); const fheroes2::Rect & pos = GetArea(); if ( le.MouseClickLeft( pos ) ) { NextState(); setRedraw(); } else if ( le.isMouseRightButtonPressedInArea( GetRect() ) ) { const fheroes2::Sprite & ston = fheroes2::AGG::GetICN( Settings::Get().isEvilInterfaceEnabled() ? ICN::STONBAKE : ICN::STONBACK, 0 ); const bool isFullInfo = StatusType::STATUS_UNKNOWN != _state && pos.height >= ( ston.height() * 3 + 15 ); if ( isFullInfo ) { fheroes2::showStandardTextMessage( _( "Status Window" ), _( "This window provides information on the status of your hero or kingdom, and shows the date." ), Dialog::ZERO ); } else { fheroes2::showStandardTextMessage( _( "Status Window" ), _( "This window provides information on the status of your hero or kingdom, and shows the date. Left click here to cycle through these windows." ), Dialog::ZERO ); } } } void Interface::StatusPanel::TimerEventProcessing() { if ( _state != StatusType::STATUS_RESOURCE || !_showLastResourceDelay.isPassed() ) { return; } switch ( GetFocusType() ) { case GameFocus::HEROES: _state = StatusType::STATUS_ARMY; break; case GameFocus::CASTLE: _state = StatusType::STATUS_FUNDS; break; default: _state = StatusType::STATUS_DAY; break; } setRedraw(); } void Interface::StatusPanel::drawAITurnProgress( const uint32_t progressValue ) { // Even if there is no need to draw anything, we still need to pump the event queue to // update the position of the software-emulated mouse cursor, feed the music player by // another music chunk on some platforms (e.g. WebAssembly), etc. LocalEvent::Get().HandleEvents( false ); const bool updateProgress = ( progressValue != _aiTurnProgress ); const bool isMapAnimation = Game::validateAnimationDelay( Game::MAPS_DELAY ); if ( !updateProgress && !isMapAnimation ) { return; } if ( updateProgress ) { if ( progressValue == 0 ) { // If turn progress is just started start the grain animation from the beginning. _grainsAnimationIndexOffset = Game::getAdventureMapAnimationIndex(); } _aiTurnProgress = progressValue; } if ( isMapAnimation ) { Game::updateAdventureMapAnimationIndex(); _interface.setRedraw( REDRAW_GAMEAREA ); } _interface.redraw( REDRAW_STATUS ); fheroes2::Display::instance().render(); } fheroes2-1.1.6+dfsg/src/fheroes2/gui/interface_status.h000066400000000000000000000101441476115357100227710ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "interface_border.h" #include "resource.h" #include "timing.h" namespace Interface { class BaseInterface; enum class StatusType : int { STATUS_UNKNOWN, STATUS_DAY, STATUS_FUNDS, STATUS_ARMY, STATUS_RESOURCE, STATUS_AITURN }; class StatusPanel final : public BorderWindow { public: explicit StatusPanel( BaseInterface & interface ) : BorderWindow( { 0, 0, 144, 72 } ) , _interface( interface ) { // Do nothing. } StatusPanel( const StatusPanel & ) = delete; ~StatusPanel() override = default; StatusPanel & operator=( const StatusPanel & ) = delete; void SetPos( int32_t x, int32_t y ) override; void SavePosition() override; void setRedraw() const; void Reset() { _state = StatusType::STATUS_DAY; _lastResource = Resource::UNKNOWN; _lastResourceCount = 0; } void NextState(); void SetState( const StatusType status ); void SetResource( const int resource, const uint32_t count ); void drawAITurnProgress( const uint32_t progressValue ); void resetAITurnProgress() { // We set _aiTurnProgress equal to 10 to properly handle the first draw call for the '0' progress. _aiTurnProgress = 10; } void QueueEventProcessing(); void TimerEventProcessing(); // Do not call this method directly, use Interface::AdventureMap::redraw() instead to avoid issues in the "no interface" mode. // The name of this method starts from _ on purpose to do not mix with other public methods. void _redraw() const; private: void _drawKingdomInfo( const int32_t offsetY = 0 ) const; void _drawDayInfo( const int32_t offsetY = 0 ) const; void _drawArmyInfo( const int32_t offsetY = 0 ) const; void _drawResourceInfo( const int32_t offsetY = 0 ) const; void _drawBackground() const; void _drawAITurns() const; fheroes2::TimeDelay _showLastResourceDelay{ 2500 }; BaseInterface & _interface; StatusType _state{ StatusType::STATUS_UNKNOWN }; int _lastResource{ Resource::UNKNOWN }; uint32_t _lastResourceCount{ 0 }; uint32_t _aiTurnProgress{ 10 }; uint32_t _grainsAnimationIndexOffset{ 0 }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/player_info.cpp000066400000000000000000000443561476115357100223040ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "player_info.h" #include #include #include #include #include #include "agg_image.h" #include "color.h" #include "dialog.h" #include "game.h" #include "icn.h" #include "image.h" #include "localevent.h" #include "maps_fileinfo.h" #include "players.h" #include "race.h" #include "screen.h" #include "settings.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "ui_text.h" void Interface::PlayersInfo::UpdateInfo( Players & players, const fheroes2::Point & playerTypeOffset, const fheroes2::Point & classOffset ) { clear(); const fheroes2::Sprite & playerTypeImage = fheroes2::AGG::GetICN( ICN::NGEXTRA, 3 ); const fheroes2::Sprite & classImage = fheroes2::AGG::GetICN( ICN::NGEXTRA, 51 ); const fheroes2::Sprite & handicapImage = fheroes2::AGG::GetICN( ICN::NGEXTRA, 0 ); const int32_t playerCount = static_cast( players.size() ); // safe to cast as the number of players <= 8. reserve( playerCount ); for ( int32_t i = 0; i < playerCount; ++i ) { emplace_back(); PlayerInfo & info = back(); info.player = players[i]; assert( info.player != nullptr ); info.playerTypeRoi = { playerTypeOffset.x + Game::GetStep4Player( i, playerTypeImage.width(), playerCount ), playerTypeOffset.y, playerTypeImage.width(), playerTypeImage.height() }; info.nameRoi = { info.playerTypeRoi.x, info.playerTypeRoi.y + info.playerTypeRoi.height, info.playerTypeRoi.width, 10 }; info.classRoi = { classOffset.x + Game::GetStep4Player( i, classImage.width(), playerCount ), classOffset.y, classImage.width(), classImage.height() }; info.handicapRoi = { classOffset.x + Game::GetStep4Player( i, handicapImage.width(), playerCount ), classOffset.y + 69, handicapImage.width(), handicapImage.height() }; } } bool Interface::PlayersInfo::SwapPlayers( Player & player1, Player & player2 ) const { const Settings & conf = Settings::Get(); const Maps::FileInfo & mapInfo = conf.getCurrentMapInfo(); const int player1Color = player1.GetColor(); const int player2Color = player2.GetColor(); bool swap = false; if ( player1.isControlAI() == player2.isControlAI() ) { swap = true; } else if ( ( player1Color & mapInfo.AllowCompHumanColors() ) && ( player2Color & mapInfo.AllowCompHumanColors() ) ) { const int humans = conf.GetPlayers().GetColors( CONTROL_HUMAN, true ); if ( humans & player1Color ) { Players::SetPlayerControl( player1Color, CONTROL_AI | CONTROL_HUMAN ); Players::SetPlayerControl( player2Color, CONTROL_HUMAN ); } else { Players::SetPlayerControl( player2Color, CONTROL_AI | CONTROL_HUMAN ); Players::SetPlayerControl( player1Color, CONTROL_HUMAN ); } swap = true; } if ( swap ) { const int player1Race = player1.GetRace(); const int player2Race = player2.GetRace(); const Player::HandicapStatus player1HandicapStatus = player1.getHandicapStatus(); const Player::HandicapStatus player2HandicapStatus = player2.getHandicapStatus(); player2.setHandicapStatus( player1HandicapStatus ); player1.setHandicapStatus( player2HandicapStatus ); if ( player1Race != player2Race && mapInfo.AllowChangeRace( player1Color ) && mapInfo.AllowChangeRace( player2Color ) ) { player1.SetRace( player2Race ); player2.SetRace( player1Race ); } const std::string player1Name = player1.GetName(); const std::string player2Name = player2.GetName(); const std::string player1DefaultName = player1.GetDefaultName(); const std::string player2DefaultName = player2.GetDefaultName(); if ( player2Name == player2DefaultName ) { player1.SetName( player1DefaultName ); } else { player1.SetName( player2Name ); } if ( player1Name == player1DefaultName ) { player2.SetName( player2DefaultName ); } else { player2.SetName( player1Name ); } } return swap; } Player * Interface::PlayersInfo::GetFromOpponentClick( const fheroes2::Point & pt ) { for ( const PlayerInfo & info : *this ) { if ( info.playerTypeRoi & pt ) { return info.player; } } return nullptr; } Player * Interface::PlayersInfo::GetFromOpponentNameClick( const fheroes2::Point & pt ) { for ( const PlayerInfo & info : *this ) { if ( info.nameRoi & pt ) { return info.player; } } return nullptr; } Player * Interface::PlayersInfo::GetFromClassClick( const fheroes2::Point & pt ) { for ( const PlayerInfo & info : *this ) { if ( info.classRoi & pt ) { return info.player; } } return nullptr; } Player * Interface::PlayersInfo::getPlayerFromHandicapRoi( const fheroes2::Point & point ) { for ( const PlayerInfo & info : *this ) { if ( info.handicapRoi & point ) { return info.player; } } return nullptr; } void Interface::PlayersInfo::RedrawInfo( const bool displayInGameInfo ) const { const Settings & conf = Settings::Get(); fheroes2::Display & display = fheroes2::Display::instance(); const Maps::FileInfo & mapInfo = conf.getCurrentMapInfo(); const int32_t playerCount = static_cast( conf.GetPlayers().size() ); const uint32_t humanColors = conf.GetPlayers().GetColors( CONTROL_HUMAN, true ); // We need to render icon shadows and since shadows are drawn on left side from images we have to render images from right to left. for ( auto iter = crbegin(); iter != crend(); ++iter ) { const PlayerInfo & info = *iter; uint32_t playerTypeIcnIndex = 0; if ( humanColors & info.player->GetColor() ) { // Current human. playerTypeIcnIndex = 9 + Color::GetIndex( info.player->GetColor() ); } else if ( mapInfo.ComputerOnlyColors() & info.player->GetColor() ) { // Computer only. playerTypeIcnIndex = 15 + Color::GetIndex( info.player->GetColor() ); } else { // Computer or human. playerTypeIcnIndex = 3 + Color::GetIndex( info.player->GetColor() ); } // wide sprite offset playerTypeIcnIndex += 24; const fheroes2::Sprite & playerIconShadow = fheroes2::AGG::GetICN( ICN::NGEXTRA, 60 ); const fheroes2::Sprite & playerIcon = fheroes2::AGG::GetICN( ICN::NGEXTRA, playerTypeIcnIndex ); fheroes2::Blit( playerIconShadow, display, info.playerTypeRoi.x - 5, info.playerTypeRoi.y + 3 ); fheroes2::Blit( playerIcon, display, info.playerTypeRoi.x, info.playerTypeRoi.y ); if ( currentSelectedPlayer != nullptr && info.player == currentSelectedPlayer ) { // TODO: add an overloaded DrawBorder() function to draw a border inside an image. fheroes2::Image selection( playerIcon.width(), playerIcon.height() ); selection.reset(); fheroes2::DrawBorder( selection, 214 ); fheroes2::Blit( selection, display, info.playerTypeRoi.x, info.playerTypeRoi.y ); } // draw player name fheroes2::Text name( info.player->GetName(), fheroes2::FontType::smallWhite() ); const int32_t maximumTextWidth = playerIcon.width() - 4; name.fitToOneRow( maximumTextWidth ); name.draw( info.playerTypeRoi.x + 2 + ( maximumTextWidth - name.width() ) / 2, info.playerTypeRoi.y + info.playerTypeRoi.height + 1, display ); // 2. redraw class const bool isActivePlayer = displayInGameInfo ? info.player->isPlay() : mapInfo.AllowChangeRace( info.player->GetColor() ); const fheroes2::Sprite & classIcon = fheroes2::AGG::GetICN( ICN::NGEXTRA, Race::getRaceIcnIndex( info.player->GetRace(), isActivePlayer ) ); const fheroes2::Sprite & classIconShadow = fheroes2::AGG::GetICN( ICN::NGEXTRA, 61 ); fheroes2::Blit( classIconShadow, display, info.classRoi.x - 5, info.classRoi.y + 3 ); fheroes2::Blit( classIcon, display, info.classRoi.x, info.classRoi.y ); const char * raceName; if ( playerCount > 4 ) { raceName = Race::DoubleLinedString( info.player->GetRace() ); } else { raceName = Race::String( info.player->GetRace() ); } const int32_t maxClassNameTextWidth = classIcon.width() + 60; const fheroes2::Text text( raceName, fheroes2::FontType::smallWhite() ); text.draw( info.classRoi.x - 31, info.classRoi.y + info.classRoi.height + 4, maxClassNameTextWidth, display ); // Display a handicap icon. uint32_t handicapIcnIndex = 0; if ( humanColors & info.player->GetColor() ) { switch ( info.player->getHandicapStatus() ) { case Player::HandicapStatus::NONE: handicapIcnIndex = 0; break; case Player::HandicapStatus::MILD: handicapIcnIndex = 1; break; case Player::HandicapStatus::SEVERE: handicapIcnIndex = 2; break; default: // Did you add a new handicap status? Add the logic above! assert( 0 ); break; } } else { assert( info.player->getHandicapStatus() == Player::HandicapStatus::NONE ); handicapIcnIndex = 78; } const fheroes2::Sprite & handicapIcon = fheroes2::AGG::GetICN( ICN::NGEXTRA, handicapIcnIndex ); const fheroes2::Sprite & handicapIconShadow = fheroes2::AGG::GetICN( ICN::NGEXTRA, 59 ); fheroes2::Blit( handicapIconShadow, display, info.handicapRoi.x - 5, info.handicapRoi.y + 3 ); fheroes2::Blit( handicapIcon, display, info.handicapRoi.x, info.handicapRoi.y ); } } bool Interface::PlayersInfo::QueueEventProcessing() { Settings & conf = Settings::Get(); const LocalEvent & le = LocalEvent::Get(); if ( le.isMouseRightButtonPressed() ) { const Player * player = GetFromOpponentClick( le.getMouseCursorPos() ); if ( player != nullptr ) { fheroes2::showStandardTextMessage( _( "Opponents" ), _( "This lets you change player starting positions and colors. A particular color will always start in a particular location. Some positions may only be played by a computer player or only by a human player." ), Dialog::ZERO ); return true; } player = GetFromClassClick( le.getMouseCursorPos() ); if ( player != nullptr ) { fheroes2::showStandardTextMessage( _( "Class" ), _( "This lets you change the class of a player. Classes are not always changeable. Depending on the scenario, a player may receive additional towns and/or heroes not of their primary alignment." ), Dialog::ZERO ); return true; } player = getPlayerFromHandicapRoi( le.getMouseCursorPos() ); if ( player != nullptr ) { fheroes2::showStandardTextMessage( _( "Handicap" ), _( "This lets you change the handicap of a particular player. Only human players may have a handicap. Handicapped players " "start with fewer resources and earn 15 or 30% fewer resources per turn for mild and severe handicaps, " "respectively." ), Dialog::ZERO ); return true; } return false; } if ( le.isMouseWheelUp() ) { Player * player = GetFromClassClick( le.getMouseCursorPos() ); if ( player != nullptr && conf.getCurrentMapInfo().AllowChangeRace( player->GetColor() ) ) { player->SetRace( Race::getPreviousRace( player->GetRace() ) ); return true; } return false; } if ( le.isMouseWheelDown() ) { Player * player = GetFromClassClick( le.getMouseCursorPos() ); if ( player != nullptr && conf.getCurrentMapInfo().AllowChangeRace( player->GetColor() ) ) { player->SetRace( Race::getNextRace( player->GetRace() ) ); return true; } return false; } Player * player = GetFromOpponentClick( le.getMouseCursorPos() ); if ( player != nullptr ) { const Maps::FileInfo & fi = conf.getCurrentMapInfo(); if ( conf.IsGameType( Game::TYPE_MULTI ) ) { if ( currentSelectedPlayer == nullptr ) { currentSelectedPlayer = player; } else if ( currentSelectedPlayer == player ) { currentSelectedPlayer = nullptr; } else if ( SwapPlayers( *player, *currentSelectedPlayer ) ) { currentSelectedPlayer = nullptr; } } else { const int playerColor = player->GetColor(); if ( playerColor & fi.colorsAvailableForHumans ) { const int human = conf.GetPlayers().GetColors( CONTROL_HUMAN, true ); if ( playerColor != human ) { Player * currentPlayer = Players::Get( human ); Player * nextPlayer = Players::Get( playerColor ); assert( currentPlayer != nullptr && nextPlayer != nullptr ); const Player::HandicapStatus currentHandicapStatus = currentPlayer->getHandicapStatus(); Players::SetPlayerControl( human, CONTROL_AI | CONTROL_HUMAN ); Players::SetPlayerControl( playerColor, CONTROL_HUMAN ); nextPlayer->setHandicapStatus( currentHandicapStatus ); currentPlayer->setHandicapStatus( Player::HandicapStatus::NONE ); } } } return true; } player = GetFromOpponentNameClick( le.getMouseCursorPos() ); if ( player != nullptr ) { std::string str = _( "%{color} player" ); StringReplace( str, "%{color}", Color::String( player->GetColor() ) ); std::string res = player->GetName(); if ( Dialog::inputString( fheroes2::Text{}, fheroes2::Text{ str, fheroes2::FontType::normalWhite() }, res, 0, false, {} ) && !res.empty() ) { player->SetName( res ); } return true; } player = GetFromClassClick( le.getMouseCursorPos() ); if ( player != nullptr && conf.getCurrentMapInfo().AllowChangeRace( player->GetColor() ) ) { player->SetRace( Race::getNextRace( player->GetRace() ) ); return true; } player = getPlayerFromHandicapRoi( le.getMouseCursorPos() ); if ( player != nullptr ) { if ( !( player->GetControl() & CONTROL_AI ) ) { switch ( player->getHandicapStatus() ) { case Player::HandicapStatus::NONE: player->setHandicapStatus( Player::HandicapStatus::MILD ); break; case Player::HandicapStatus::MILD: player->setHandicapStatus( Player::HandicapStatus::SEVERE ); break; case Player::HandicapStatus::SEVERE: player->setHandicapStatus( Player::HandicapStatus::NONE ); break; default: // Did you add a new handicap status? Add the logic above! assert( 0 ); break; } } return true; } return false; } bool Interface::PlayersInfo::readOnlyEventProcessing() { const LocalEvent & le = LocalEvent::Get(); if ( !le.isMouseRightButtonPressed() ) { // Read only mode works only for right click events. return false; } const Player * player = getPlayerFromHandicapRoi( le.getMouseCursorPos() ); if ( player != nullptr ) { switch ( player->getHandicapStatus() ) { case Player::HandicapStatus::NONE: fheroes2::showStandardTextMessage( _( "No Handicap" ), _( "No special restrictions on starting resources and resource income per turn." ), Dialog::ZERO ); break; case Player::HandicapStatus::MILD: fheroes2::showStandardTextMessage( _( "Mild Handicap" ), _( "Players with mild handicap start with fewer resources and earn 15% fewer resources per turn." ), Dialog::ZERO ); break; case Player::HandicapStatus::SEVERE: fheroes2::showStandardTextMessage( _( "Severe Handicap" ), _( "Players with severe handicap start with fewer resources and earn 30% fewer resources per turn." ), Dialog::ZERO ); break; default: // Did you add a new handicap status? Add the logic above! assert( 0 ); break; } return true; } return false; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/player_info.h000066400000000000000000000053241476115357100217410ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "math_base.h" class Player; class Players; namespace Interface { struct PlayerInfo { Player * player{ nullptr }; fheroes2::Rect playerTypeRoi; fheroes2::Rect classRoi; fheroes2::Rect nameRoi; fheroes2::Rect handicapRoi; }; struct PlayersInfo : std::vector { void UpdateInfo( Players &, const fheroes2::Point & playerTypeOffset, const fheroes2::Point & classOffset ); bool SwapPlayers( Player & player1, Player & player2 ) const; Player * GetFromOpponentClick( const fheroes2::Point & pt ); Player * GetFromOpponentNameClick( const fheroes2::Point & pt ); Player * GetFromClassClick( const fheroes2::Point & pt ); Player * getPlayerFromHandicapRoi( const fheroes2::Point & point ); // displayInGameInfo: use colored and grayscale race icons to distinguish between players who are still in the game and vanquished players respectively void RedrawInfo( const bool displayInGameInfo ) const; void resetSelection() { currentSelectedPlayer = nullptr; } bool QueueEventProcessing(); bool readOnlyEventProcessing(); Player * currentSelectedPlayer{ nullptr }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/skill_bar.cpp000066400000000000000000000421041476115357100217240ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "skill_bar.h" #include #include #include #include "agg_image.h" #include "dialog.h" #include "dialog_selectitems.h" #include "heroes.h" #include "icn.h" #include "pal.h" #include "screen.h" #include "tools.h" #include "translations.h" #include "ui_dialog.h" #include "ui_text.h" namespace { fheroes2::Image GetBarBackgroundSprite() { fheroes2::Image icon( 34, 34 ); // Sprite ( ICN::HSICONS, 0 ) has no transparency so we can say that 'icon' will also have no transparency. icon._disableTransformLayer(); icon.reset(); fheroes2::DrawBorder( icon, fheroes2::GetColorId( 0xD0, 0xC0, 0x48 ) ); fheroes2::Copy( fheroes2::AGG::GetICN( ICN::HSICONS, 0 ), 26, 21, icon, 1, 1, 32, 32 ); return icon; } } PrimarySkillsBar::PrimarySkillsBar( Heroes * hero, const bool useSmallSize, const bool isEditMode, const bool allowSkillReset ) : _hero( hero ) , _useSmallSize( useSmallSize ) , _isEditMode( isEditMode ) , _allowSkillReset( allowSkillReset ) { if ( useSmallSize ) { backsf = GetBarBackgroundSprite(); setSingleItemSize( { backsf.width(), backsf.height() } ); } else { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::PRIMSKIL, 0 ); setSingleItemSize( { sprite.width(), sprite.height() } ); } SetContent( _content ); } void PrimarySkillsBar::SetTextOff( int32_t ox, int32_t oy ) { toff = fheroes2::Point( ox, oy ); } void PrimarySkillsBar::RedrawBackground( const fheroes2::Rect & pos, fheroes2::Image & dstsf ) { if ( _useSmallSize ) { fheroes2::Copy( backsf, 0, 0, dstsf, pos ); } } void PrimarySkillsBar::RedrawItem( int & skill, const fheroes2::Rect & pos, fheroes2::Image & dstsf ) { if ( skill == Skill::Primary::UNKNOWN ) { // Why is the unknown skill here? assert( 0 ); return; } if ( _useSmallSize ) { const fheroes2::Sprite & backSprite = fheroes2::AGG::GetICN( ICN::SWAPWIN, 0 ); const int ww = 32; const fheroes2::Point dstpt( pos.x + ( pos.width - ww ) / 2, pos.y + ( pos.height - ww ) / 2 ); std::string skillText; switch ( skill ) { case Skill::Primary::ATTACK: fheroes2::Copy( backSprite, 217, 52, dstsf, dstpt.x, dstpt.y, ww, ww ); if ( _hero ) { skillText = std::to_string( _hero->GetAttack() ); } break; case Skill::Primary::DEFENSE: fheroes2::Copy( backSprite, 217, 85, dstsf, dstpt.x, dstpt.y, ww, ww ); if ( _hero ) { skillText = std::to_string( _hero->GetDefense() ); } break; case Skill::Primary::POWER: fheroes2::Copy( backSprite, 217, 118, dstsf, dstpt.x, dstpt.y, ww, ww ); if ( _hero ) { skillText = std::to_string( _hero->GetPower() ); } break; case Skill::Primary::KNOWLEDGE: fheroes2::Copy( backSprite, 217, 151, dstsf, dstpt.x, dstpt.y, ww, ww ); if ( _hero ) { skillText = std::to_string( _hero->GetKnowledge() ); } break; default: // Your primary skill is different. Make sure that the logic is correct! assert( 0 ); break; } if ( _hero != nullptr && !skillText.empty() ) { // Render text only if there is something to render. const fheroes2::Text text{ std::move( skillText ), fheroes2::FontType::smallWhite() }; text.draw( pos.x + ( pos.width + toff.x - text.width() ) / 2, pos.y + pos.height + toff.y + 2, dstsf ); } } else { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::PRIMSKIL, skill - 1 ); fheroes2::Copy( sprite, 0, 0, dstsf, pos.x + ( pos.width - sprite.width() ) / 2, pos.y + ( pos.height - sprite.height() ) / 2, pos.width, pos.height ); fheroes2::Text text{ Skill::Primary::String( skill ), fheroes2::FontType::smallWhite() }; if ( _hero == nullptr ) { text.drawInRoi( pos.x + ( pos.width - text.width() ) / 2, pos.y + 6, dstsf, pos ); return; } std::string skillValueText; auto prepareEditModeText = [this, &dstsf, &pos, &skill]( int baseValue, const int modificatorValue ) { if ( _isDefault ) { // In editor the negative value means that this skill does not use custom value. baseValue = Heroes::getHeroDefaultSkillValue( skill, _hero->GetRace() ); // Make the background darker to make text more readable. fheroes2::ApplyPalette( dstsf, pos.x, pos.y, dstsf, pos.x, pos.y, pos.width, pos.height, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); const fheroes2::Text defaultText( _( "Default\nvalue" ), fheroes2::FontType::normalWhite() ); defaultText.drawInRoi( pos.x, pos.y + ( pos.height - defaultText.height() * defaultText.rows( pos.width ) ) / 2 + 2, pos.width, dstsf, pos ); } std::string skillText = "%{withModificators} (%{base})"; StringReplace( skillText, "%{base}", baseValue ); StringReplace( skillText, "%{withModificators}", baseValue + modificatorValue ); return skillText; }; switch ( skill ) { case Skill::Primary::ATTACK: skillValueText = _isEditMode ? prepareEditModeText( _hero->getAttackBaseValue(), _hero->GetAttackModificator() ) : std::to_string( _hero->GetAttack() ); break; case Skill::Primary::DEFENSE: skillValueText = _isEditMode ? prepareEditModeText( _hero->getDefenseBaseValue(), _hero->GetDefenseModificator() ) : std::to_string( _hero->GetDefense() ); break; case Skill::Primary::POWER: skillValueText = _isEditMode ? prepareEditModeText( _hero->getPowerBaseValue(), _hero->GetPowerModificator() ) : std::to_string( _hero->GetPower() ); break; case Skill::Primary::KNOWLEDGE: skillValueText = _isEditMode ? prepareEditModeText( _hero->getKnowledgeBaseValue(), _hero->GetKnowledgeModificator() ) : std::to_string( _hero->GetKnowledge() ); break; default: // Your primary skill is different. Make sure that the logic is correct! assert( 0 ); return; } // In editor the background may be darkened so we render texts here. text.drawInRoi( pos.x + ( pos.width - text.width() ) / 2, pos.y + 6, dstsf, pos ); text.set( std::move( skillValueText ), fheroes2::FontType::normalWhite() ); text.drawInRoi( pos.x, pos.y + pos.height - text.height(), pos.width, dstsf, pos ); } } bool PrimarySkillsBar::ActionBarLeftMouseSingleClick( int & skill ) { if ( skill == Skill::Primary::UNKNOWN ) { return false; } if ( !_isEditMode ) { fheroes2::showStandardTextMessage( Skill::Primary::String( skill ), Skill::Primary::StringDescription( skill, _hero ), Dialog::OK ); return false; } // The case when we are in Editor mode. auto primarySkillEditDialog = [&skill]( int32_t & skillValue ) { std::string header = _( "Set %{skill} Skill" ); StringReplace( header, "%{skill}", Skill::Primary::String( skill ) ); const fheroes2::PrimarySkillDialogElement skillUI{ skill, {} }; return Dialog::SelectCount( std::move( header ), skill == Skill::Primary::POWER ? 1 : 0, 99, skillValue, 1, &skillUI ); }; int32_t value; switch ( skill ) { case Skill::Primary::ATTACK: value = _hero->getAttackBaseValue(); if ( primarySkillEditDialog( value ) ) { _hero->setAttackBaseValue( value ); _isDefault = false; return true; } break; case Skill::Primary::DEFENSE: value = _hero->getDefenseBaseValue(); if ( primarySkillEditDialog( value ) ) { _hero->setDefenseBaseValue( value ); _isDefault = false; return true; } break; case Skill::Primary::POWER: value = _hero->getPowerBaseValue(); if ( primarySkillEditDialog( value ) ) { _hero->setPowerBaseValue( value ); _isDefault = false; return true; } break; case Skill::Primary::KNOWLEDGE: value = _hero->getKnowledgeBaseValue(); if ( primarySkillEditDialog( value ) ) { _hero->setKnowledgeBaseValue( value ); _isDefault = false; return true; } break; default: // Are you sure that you are passing the correct skill type? assert( 0 ); break; } return false; } bool PrimarySkillsBar::ActionBarRightMouseHold( int & skill ) { if ( skill == Skill::Primary::UNKNOWN ) { return false; } if ( !_isEditMode || !_allowSkillReset || _isDefault ) { fheroes2::showStandardTextMessage( Skill::Primary::String( skill ), Skill::Primary::StringDescription( skill, _hero ), Dialog::ZERO ); return false; } // In Editor the Right-click on any primary skill resets all skills to their default state. _isDefault = true; const int heroRace = _hero->GetRace(); _hero->setAttackBaseValue( Heroes::getHeroDefaultSkillValue( Skill::Primary::ATTACK, heroRace ) ); _hero->setDefenseBaseValue( Heroes::getHeroDefaultSkillValue( Skill::Primary::DEFENSE, heroRace ) ); _hero->setPowerBaseValue( Heroes::getHeroDefaultSkillValue( Skill::Primary::POWER, heroRace ) ); _hero->setKnowledgeBaseValue( Heroes::getHeroDefaultSkillValue( Skill::Primary::KNOWLEDGE, heroRace ) ); return true; } bool PrimarySkillsBar::ActionBarCursor( int & skill ) { if ( Skill::Primary::UNKNOWN != skill ) { msg = _isEditMode ? _( "Set %{skill} base value. Right-click to reset all skills to default." ) : _( "View %{skill} Info" ); StringReplace( msg, "%{skill}", Skill::Primary::String( skill ) ); } return false; } bool PrimarySkillsBar::QueueEventProcessing( std::string * str ) { msg.clear(); const bool res = Interface::ItemsBar::QueueEventProcessing(); if ( str ) { *str = msg; } return res; } SecondarySkillsBar::SecondarySkillsBar( const Heroes & hero, const bool mini /* true */, const bool change /* false */, const bool showDefaultSkillsMessage /* false */ ) : use_mini_sprite( mini ) , can_change( change ) , _showDefaultSkillsMessage( showDefaultSkillsMessage ) , _hero( hero ) { if ( use_mini_sprite ) { backsf = GetBarBackgroundSprite(); setSingleItemSize( { backsf.width(), backsf.height() } ); } else { const fheroes2::Sprite & sprite = fheroes2::AGG::GetICN( ICN::SECSKILL, 0 ); setSingleItemSize( { sprite.width(), sprite.height() } ); } } void SecondarySkillsBar::RedrawBackground( const fheroes2::Rect & pos, fheroes2::Image & dstsf ) { if ( use_mini_sprite ) { fheroes2::Copy( backsf, 0, 0, dstsf, pos ); } else { if ( _showDefaultSkillsMessage && std::none_of( items.begin(), items.end(), []( Skill::Secondary const * skill ) { return skill->isValid(); } ) ) { // In editor when no skill are set it means that default skills will be applied on the game start. fheroes2::ApplyPalette( fheroes2::AGG::GetICN( ICN::SECSKILL, 0 ), 0, 0, dstsf, pos.x, pos.y, pos.width, pos.height, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); const fheroes2::Text text( _( "Default\nskill" ), fheroes2::FontType::normalWhite() ); text.drawInRoi( pos.x, pos.y + ( pos.height - text.height() * text.rows( pos.width ) ) / 2 + 2, pos.width, dstsf, pos ); } else { fheroes2::Copy( fheroes2::AGG::GetICN( ICN::SECSKILL, 0 ), 0, 0, dstsf, pos ); } } } void SecondarySkillsBar::RedrawItem( Skill::Secondary & skill, const fheroes2::Rect & pos, fheroes2::Image & dstsf ) { if ( !skill.isValid() ) { // If the skill is invalid nothing we need to do. return; } const fheroes2::Sprite & sprite = use_mini_sprite ? fheroes2::AGG::GetICN( ICN::MINISS, skill.GetIndexSprite2() ) : fheroes2::AGG::GetICN( ICN::SECSKILL, skill.GetIndexSprite1() ); fheroes2::Copy( sprite, 0, 0, dstsf, pos.x + ( pos.width - sprite.width() ) / 2, pos.y + ( pos.height - sprite.height() ) / 2, pos.width, pos.height ); if ( use_mini_sprite ) { const fheroes2::Text text{ std::to_string( skill.Level() ), fheroes2::FontType::smallWhite() }; text.draw( pos.x + ( pos.width - text.width() ) - 3, pos.y + pos.height - 10, dstsf ); } else { fheroes2::Text text{ Skill::Secondary::String( skill.Skill() ), fheroes2::FontType::smallWhite() }; if ( text.width() > sprite.width() + 1 ) { text.fitToOneRow( pos.width ); } const int skillNamePaddingX = ( pos.width - text.width() ) / 2 - 1; text.drawInRoi( pos.x + skillNamePaddingX, pos.y + 5, dstsf, pos ); text.set( Skill::Level::StringWithBonus( _hero, skill ), fheroes2::FontType::smallWhite() ); if ( text.width() > sprite.width() + 1 ) { text.fitToOneRow( pos.width ); } const int skillLevelPaddingX = ( pos.width - text.width() ) / 2 - 1; text.drawInRoi( pos.x + skillLevelPaddingX, pos.y + 53, dstsf, pos ); } } bool SecondarySkillsBar::ActionBarLeftMouseSingleClick( Skill::Secondary & skill ) { if ( skill.isValid() ) { fheroes2::SecondarySkillDialogElement( skill, _hero ).showPopup( Dialog::OK ); return true; } if ( can_change ) { const Skill::Secondary alt = Dialog::selectSecondarySkill( _hero ); if ( alt.isValid() ) { skill = alt; return true; } } return false; } bool SecondarySkillsBar::ActionBarRightMouseHold( Skill::Secondary & skill ) { if ( skill.isValid() ) { if ( can_change ) { skill.Reset(); } else { fheroes2::SecondarySkillDialogElement( skill, _hero ).showPopup( Dialog::ZERO ); } return true; } return false; } bool SecondarySkillsBar::ActionBarCursor( Skill::Secondary & skill ) { if ( skill.isValid() ) { msg = _( "View %{skill} Info" ); StringReplace( msg, "%{skill}", skill.GetName() ); } return false; } bool SecondarySkillsBar::QueueEventProcessing( std::string * str ) { msg.clear(); const bool res = Interface::ItemsBar::QueueEventProcessing(); if ( str ) { *str = msg; } return res; } namespace fheroes2 { void RedrawPrimarySkillInfo( const fheroes2::Point & pos, PrimarySkillsBar * bar1, PrimarySkillsBar * bar2 ) { Display & display = Display::instance(); // attack skill Text text( Skill::Primary::String( Skill::Primary::ATTACK ), FontType::smallWhite() ); text.draw( pos.x + 320 - text.width() / 2, pos.y + 62, display ); // defense skill text.set( Skill::Primary::String( Skill::Primary::DEFENSE ), FontType::smallWhite() ); text.draw( pos.x + 320 - text.width() / 2, pos.y + 95, display ); // spell power text.set( Skill::Primary::String( Skill::Primary::POWER ), FontType::smallWhite() ); text.draw( pos.x + 320 - text.width() / 2, pos.y + 128, display ); // knowledge text.set( Skill::Primary::String( Skill::Primary::KNOWLEDGE ), FontType::smallWhite() ); text.draw( pos.x + 320 - text.width() / 2, pos.y + 161, display ); if ( bar1 ) { bar1->Redraw( display ); } if ( bar2 ) { bar2->Redraw( display ); } } } fheroes2-1.1.6+dfsg/src/fheroes2/gui/skill_bar.h000066400000000000000000000102371476115357100213730ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2024 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include #include #include "image.h" #include "interface_itemsbar.h" #include "math_base.h" #include "skill.h" class Heroes; class PrimarySkillsBar : public Interface::ItemsBar { public: PrimarySkillsBar( Heroes * hero, const bool useSmallSize, const bool isEditMode, const bool allowSkillReset ); void SetTextOff( int32_t, int32_t ); void RedrawBackground( const fheroes2::Rect &, fheroes2::Image & ) override; void RedrawItem( int &, const fheroes2::Rect &, fheroes2::Image & ) override; bool ActionBarLeftMouseSingleClick( int & skill ) override; bool ActionBarRightMouseHold( int & skill ) override; bool ActionBarCursor( int & skill ) override; bool QueueEventProcessing( std::string * = nullptr ); // In Editor primary skills values may be reset to their default state. This method returns this state. bool isDefaultValues() const { return _isDefault; } // In Editor primary skills values may be reset to their default state by this method. void useDefaultValues() { _isDefault = true; } private: // This virtual method is (indirectly) called from the constructor, make it clear that it cannot be overridden in subclasses void SetContentItems() final { Interface::ItemsBar::SetContentItems(); } Heroes * _hero; fheroes2::Image backsf; bool _useSmallSize{ false }; bool _isEditMode{ false }; bool _allowSkillReset{ false }; // The '_isDefault' is used only in Editor mode. bool _isDefault{ false }; std::vector _content{ Skill::Primary::ATTACK, Skill::Primary::DEFENSE, Skill::Primary::POWER, Skill::Primary::KNOWLEDGE }; fheroes2::Point toff; std::string msg; }; class SecondarySkillsBar : public Interface::ItemsBar { public: SecondarySkillsBar( const Heroes & hero, const bool mini = true, const bool change = false, const bool showDefaultSkillsMessage = false ); void RedrawBackground( const fheroes2::Rect &, fheroes2::Image & ) override; void RedrawItem( Skill::Secondary &, const fheroes2::Rect &, fheroes2::Image & ) override; bool ActionBarLeftMouseSingleClick( Skill::Secondary & skill ) override; bool ActionBarRightMouseHold( Skill::Secondary & skill ) override; bool ActionBarCursor( Skill::Secondary & skill ) override; bool QueueEventProcessing( std::string * = nullptr ); private: fheroes2::Image backsf; const bool use_mini_sprite; const bool can_change; const bool _showDefaultSkillsMessage; std::string msg; const Heroes & _hero; }; namespace fheroes2 { void RedrawPrimarySkillInfo( const fheroes2::Point & pos, PrimarySkillsBar * bar1, PrimarySkillsBar * bar2 ); } fheroes2-1.1.6+dfsg/src/fheroes2/gui/statusbar.cpp000066400000000000000000000050631476115357100217750ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2024 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "statusbar.h" #include #include #include #include "math_tools.h" #include "screen.h" #include "ui_text.h" StatusBar::StatusBar() : MovableText( fheroes2::Display::instance() ) { // Do nothing. } void StatusBar::ShowMessage( std::string msg ) { if ( msg == _prevMessage ) { // No updates. return; } _prevMessage = msg; auto text = std::make_unique( std::move( msg ), fheroes2::FontType::normalWhite() ); text->fitToOneRow( _roi.width ); const int32_t textWidth = text->width(); const fheroes2::Rect messageRoi{ _roi.x + ( _roi.width - textWidth ) / 2, _roi.y, textWidth, text->height() }; update( std::move( text ) ); draw( messageRoi.x, messageRoi.y ); fheroes2::Display::instance().render( fheroes2::getBoundaryRect( _prevMessageRoi, messageRoi ) ); _prevMessageRoi = messageRoi; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/statusbar.h000066400000000000000000000040321476115357100214350ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2019 - 2025 * * * * Free Heroes2 Engine: http://sourceforge.net/projects/fheroes2 * * Copyright (C) 2009 by Andrey Afletdinov * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once #include #include "math_base.h" #include "ui_tool.h" class StatusBar : public fheroes2::MovableText { public: StatusBar(); void setRoi( const fheroes2::Rect & roi ) { _roi = roi; } void ShowMessage( std::string msg ); private: fheroes2::Rect _roi; std::string _prevMessage; fheroes2::Rect _prevMessageRoi; }; fheroes2-1.1.6+dfsg/src/fheroes2/gui/ui_base.cpp000066400000000000000000000031201476115357100213640ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ui_base.h" namespace fheroes2 { void ActionObject::senderUpdate( const ActionObject * /*unused*/ ) { // Do nothing. } } fheroes2-1.1.6+dfsg/src/fheroes2/gui/ui_base.h000066400000000000000000000042261476115357100210410ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2021 - 2022 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #pragma once namespace fheroes2 { // Action-event class to communicate between sender and receiver (only for user actions) class ActionObject { public: ActionObject() = default; virtual ~ActionObject() = default; void subscribe( ActionObject * receiver ) { _receiver = receiver; } void unsubscribe() { _receiver = nullptr; } protected: void notifySubscriber() { if ( _receiver != nullptr ) { _receiver->senderUpdate( this ); } } virtual void senderUpdate( const ActionObject * ); private: ActionObject * _receiver{ nullptr }; }; } fheroes2-1.1.6+dfsg/src/fheroes2/gui/ui_button.cpp000066400000000000000000001235141476115357100217770ustar00rootroot00000000000000/*************************************************************************** * fheroes2: https://github.com/ihhub/fheroes2 * * Copyright (C) 2020 - 2025 * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "ui_button.h" #include #include #include "agg_image.h" #include "dialog.h" #include "game_hotkeys.h" #include "icn.h" #include "localevent.h" #include "pal.h" #include "settings.h" #include "translations.h" #include "ui_text.h" namespace { fheroes2::Image resizeButton( const fheroes2::Image & original, const fheroes2::Size & buttonSize ) { const int32_t originalWidth = original.width(); const int32_t originalHeight = original.height(); assert( originalHeight > 0 && originalWidth > 0 ); fheroes2::Image output; if ( originalHeight == buttonSize.height && originalWidth == buttonSize.width ) { fheroes2::Copy( original, output ); return output; } output.resize( buttonSize.width, buttonSize.height ); output.reset(); // Buttons that only are wider. if ( buttonSize.width > originalWidth && buttonSize.height == originalHeight ) { const int32_t middleWidth = originalWidth / 3; const int32_t overallMiddleWidth = buttonSize.width - middleWidth * 2; const int32_t middleWidthCount = overallMiddleWidth / middleWidth; const int32_t middleWidthLeftOver = overallMiddleWidth - middleWidthCount * middleWidth; fheroes2::Copy( original, 0, 0, output, 0, 0, middleWidth, originalHeight ); int32_t offsetX = middleWidth; for ( int32_t i = 0; i < middleWidthCount; ++i ) { fheroes2::Copy( original, middleWidth, 0, output, offsetX, 0, middleWidth, originalHeight ); offsetX += middleWidth; } if ( middleWidthLeftOver > 0 ) { fheroes2::Copy( original, middleWidth, 0, output, offsetX, 0, middleWidthLeftOver, originalHeight ); offsetX += middleWidthLeftOver; } assert( offsetX + originalWidth - middleWidth * 2 == buttonSize.width ); fheroes2::Copy( original, originalWidth - middleWidth, 0, output, offsetX, 0, middleWidth, originalHeight ); } // Buttons that only are taller. else if ( buttonSize.height > originalHeight && buttonSize.width == originalWidth ) { const int32_t middleHeight = originalHeight / 5; const int32_t overallMiddleHeight = buttonSize.height - middleHeight * 2; const int32_t middleHeightCount = overallMiddleHeight / middleHeight; const int32_t middleHeightLeftOver = overallMiddleHeight - middleHeightCount * middleHeight; fheroes2::Copy( original, 0, 0, output, 0, 0, originalWidth, middleHeight ); int32_t offsetY = middleHeight; for ( int32_t i = 0; i < middleHeightCount; ++i ) { fheroes2::Copy( original, 0, middleHeight, output, 0, offsetY, originalWidth, middleHeight ); offsetY += middleHeight; } if ( middleHeightLeftOver > 0 ) { fheroes2::Copy( original, 0, middleHeight, output, 0, offsetY, originalWidth, middleHeightLeftOver ); offsetY += middleHeightLeftOver; } assert( offsetY + originalHeight - middleHeight * 4 == buttonSize.height ); fheroes2::Copy( original, 0, originalHeight - middleHeight, output, 0, offsetY, originalWidth, middleHeight ); } // Buttons that have shrunk in any direction. else if ( buttonSize.height <= originalHeight && buttonSize.width <= originalWidth ) { fheroes2::Copy( original, 0, 0, output, 0, 0, buttonSize.width / 2, buttonSize.height / 2 ); const int32_t secondHalfHeight = buttonSize.height - buttonSize.height / 2; const int32_t secondHalfWidth = buttonSize.width - buttonSize.width / 2; fheroes2::Copy( original, 0, originalHeight - secondHalfHeight, output, 0, buttonSize.height - secondHalfHeight, secondHalfWidth, secondHalfHeight ); fheroes2::Copy( original, originalWidth - secondHalfWidth, 0, output, buttonSize.width - secondHalfWidth, 0, secondHalfWidth, secondHalfHeight ); fheroes2::Copy( original, originalWidth - secondHalfWidth, originalHeight - secondHalfHeight, output, buttonSize.width - secondHalfWidth, buttonSize.height - secondHalfHeight, secondHalfWidth, secondHalfHeight ); } // Buttons that are taller but less wide. else if ( buttonSize.height > originalHeight && buttonSize.width < originalWidth ) { // Height increase const int32_t middleHeight = originalHeight / 5; const int32_t overallMiddleHeight = buttonSize.height - middleHeight * 2; const int32_t middleHeightCount = overallMiddleHeight / middleHeight; const int32_t middleHeightLeftOver = overallMiddleHeight - middleHeightCount * middleHeight; const int32_t middleWidth = originalWidth / 3; // The new button cannot even fit the two end corners. Are you using the wrong empty button to generate the new one? assert( buttonSize.width >= middleWidth * 2 ); const int32_t rightSideWidth = buttonSize.width - middleWidth; fheroes2::Copy( original, 0, 0, output, 0, 0, middleWidth, middleHeight ); fheroes2::Copy( original, rightSideWidth, 0, output, middleWidth, 0, rightSideWidth, middleHeight ); int32_t offsetY = middleHeight; for ( int32_t i = 0; i < middleHeightCount; ++i ) { fheroes2::Copy( original, 0, middleHeight, output, 0, offsetY, middleWidth, middleHeight ); fheroes2::Copy( original, rightSideWidth, middleHeight, output, middleWidth, offsetY, rightSideWidth, middleHeight ); offsetY += middleHeight; } if ( middleHeightLeftOver > 0 ) { fheroes2::Copy( original, 0, middleHeight, output, 0, offsetY, middleWidth, middleHeightLeftOver ); fheroes2::Copy( original, rightSideWidth, middleHeight, output, middleWidth, offsetY, rightSideWidth, middleHeightLeftOver ); offsetY += middleHeightLeftOver; } assert( offsetY + originalHeight - middleHeight * 4 == buttonSize.height ); fheroes2::Copy( original, 0, originalHeight - middleHeight, output, 0, offsetY, middleWidth, middleHeight ); fheroes2::Copy( original, rightSideWidth, originalHeight - middleHeight, output, middleWidth, offsetY, rightSideWidth, middleHeight ); } // Buttons that have increased width and height. else if ( buttonSize.height > originalHeight && buttonSize.width > originalWidth ) { const int32_t middleWidth = originalWidth / 3; const int32_t overallMiddleWidth = buttonSize.width - middleWidth * 2; const int32_t middleWidthCount = overallMiddleWidth / middleWidth; const int32_t middleWidthLeftOver = overallMiddleWidth - middleWidthCount * middleWidth; const int32_t middleHeight = originalHeight / 5; const int32_t overallMiddleHeight = buttonSize.height - middleHeight * 2; const int32_t middleHeightCount = overallMiddleHeight / middleHeight; const int32_t middleHeightLeftOver = overallMiddleHeight - middleHeightCount * middleHeight; fheroes2::Copy( original, 0, 0, output, 0, 0, middleWidth, middleHeight ); const int32_t rightPartWidth = originalWidth - middleWidth * 2; fheroes2::Copy( original, originalWidth - rightPartWidth, 0, output, buttonSize.width - rightPartWidth, 0, middleWidth, middleHeight ); int32_t offsetY = middleHeight; for ( int32_t i = 0; i < middleHeightCount; ++i ) { fheroes2::Copy( original, 0, middleHeight, output, 0, offsetY, middleWidth, middleHeight ); fheroes2::Copy( original, originalWidth - rightPartWidth, middleHeight, output, buttonSize.width - rightPartWidth, offsetY, middleWidth, middleHeight ); offsetY += middleHeight; } if ( middleHeightLeftOver > 0 ) { fheroes2::Copy( original, 0, middleHeight, output, 0, offsetY, middleWidth, middleHeightLeftOver ); fheroes2::Copy( original, originalWidth - rightPartWidth, middleHeight, output, buttonSize.width - rightPartWidth, offsetY, middleWidth, middleHeightLeftOver ); offsetY += middleHeightLeftOver; } const int32_t bottomPartHeight = originalHeight - middleHeight * 4; fheroes2::Copy( original, 0, originalHeight - bottomPartHeight, output, 0, offsetY, middleWidth, bottomPartHeight ); fheroes2::Copy( original, originalWidth - rightPartWidth, originalHeight - bottomPartHeight, output, buttonSize.width - rightPartWidth, offsetY, middleWidth, bottomPartHeight ); int32_t offsetX = middleWidth; for ( int32_t i = 0; i < middleWidthCount; ++i ) { fheroes2::Copy( original, middleWidth, 0, output, offsetX, 0, middleWidth, middleHeight ); fheroes2::Copy( original, middleWidth, originalHeight - bottomPartHeight, output, offsetX, offsetY, middleWidth, middleHeight ); offsetX += middleWidth; } if ( middleWidthLeftOver > 0 ) { fheroes2::Copy( original, middleWidth, 0, output, offsetX, 0, middleWidthLeftOver, middleHeight ); fheroes2::Copy( original, middleWidth, originalHeight - bottomPartHeight, output, offsetX, offsetY, middleWidthLeftOver, middleHeight ); offsetX += middleWidthLeftOver; } assert( offsetX + rightPartWidth == buttonSize.width ); assert( offsetY + bottomPartHeight == buttonSize.height ); // Find the background color using the central pixel of the button background. const uint32_t centralPosition = ( originalWidth * originalHeight / 2 ) - 1 - ( originalWidth >= originalHeight ? originalHeight : originalWidth ) / 2; fheroes2::Fill( output, middleWidth, middleHeight, offsetX - middleWidth, offsetY - middleHeight, original.image()[centralPosition] ); } else { // You are trying to modify the size of the button in an unexpected way. assert( 0 ); } return output; } void addButtonShine( fheroes2::Sprite & buttonImage, const int emptyButtonIcnID ) { const bool isGoodButton = ( emptyButtonIcnID == ICN::EMPTY_GOOD_BUTTON ); if ( isGoodButton || emptyButtonIcnID == ICN::EMPTY_EVIL_BUTTON ) { const uint8_t firstColor = 10; const uint8_t secondColor = isGoodButton ? 37 : 15; const uint8_t lastColor = isGoodButton ? 39 : 16; // Left-side shine fheroes2::SetPixel( buttonImage, 11, 4, firstColor ); fheroes2::SetPixel( buttonImage, 13, 4, firstColor ); fheroes2::SetPixel( buttonImage, 9, 6, firstColor ); fheroes2::SetPixel( buttonImage, 10, 5, secondColor ); fheroes2::SetPixel( buttonImage, 12, 5, secondColor ); fheroes2::SetPixel( buttonImage, 8, 7, lastColor ); fheroes2::SetPixel( buttonImage, 15, 4, lastColor ); // Right-side shine const int32_t buttonWidth = buttonImage.width(); fheroes2::SetPixel( buttonImage, buttonWidth - 9, 4, firstColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 7, 4, firstColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 10, 5 }, { buttonWidth - 11, 6 }, secondColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 8, 5, secondColor ); const int32_t buttonHeight = buttonImage.height(); // To avoid overcrowding the '...' virtual keyboard button with decorations we set 50. if ( buttonWidth > 50 ) { // Longer left-side shine fheroes2::DrawLine( buttonImage, { 11, 4 }, { 9, 6 }, firstColor ); fheroes2::SetPixel( buttonImage, 8, 7, lastColor ); fheroes2::SetPixel( buttonImage, 13, 4, secondColor ); fheroes2::DrawLine( buttonImage, { 12, 5 }, { 9, 8 }, lastColor ); fheroes2::DrawLine( buttonImage, { 8, 9 }, { 7, 10 }, firstColor ); fheroes2::SetPixel( buttonImage, 6, 11, lastColor ); fheroes2::DrawLine( buttonImage, { 15, 4 }, { 13, 6 }, firstColor ); fheroes2::SetPixel( buttonImage, 12, 7, lastColor ); // Longer right-side shine fheroes2::SetPixel( buttonImage, buttonWidth - 10, 2, firstColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 8, 3, secondColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 11, 3, secondColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 12, 4, firstColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 13, 5 }, { buttonWidth - 14, 6 }, lastColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 10, 5 }, { buttonWidth - 12, 7 }, firstColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 13, 8 }, { buttonWidth - 14, 9 }, secondColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 8, 5 }, { buttonWidth - 10, 7 }, firstColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 11, 8, lastColor ); // Bottom left-side shine fheroes2::SetPixel( buttonImage, 11, buttonHeight - 6, lastColor ); fheroes2::DrawLine( buttonImage, { 12, buttonHeight - 7 }, { 13, buttonHeight - 8 }, firstColor ); fheroes2::SetPixel( buttonImage, 14, buttonHeight - 9, lastColor ); // This is mainly to decorate the space bar button if ( buttonWidth > 96 || buttonHeight > 25 ) { // Longer bottom left shine fheroes2::SetPixel( buttonImage, 10, buttonHeight - 5, lastColor ); // Center part shine fheroes2::SetPixel( buttonImage, 30, buttonHeight - 5, secondColor ); fheroes2::SetPixel( buttonImage, 31, buttonHeight - 6, lastColor ); fheroes2::DrawLine( buttonImage, { 32, buttonHeight - 5 }, { 34, buttonHeight - 7 }, firstColor ); fheroes2::SetPixel( buttonImage, 35, buttonHeight - 8, secondColor ); fheroes2::SetPixel( buttonImage, 36, buttonHeight - 9, lastColor ); fheroes2::SetPixel( buttonImage, 34, buttonHeight - 5, secondColor ); fheroes2::SetPixel( buttonImage, 35, buttonHeight - 6, lastColor ); } if ( buttonHeight > 25 ) { // Bottom right-side shine fheroes2::DrawLine( buttonImage, { buttonWidth - 20, buttonHeight - 5 }, { buttonWidth - 16, buttonHeight - 9 }, secondColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 15, buttonHeight - 10, lastColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 18, buttonHeight - 5 }, { buttonWidth - 14, buttonHeight - 9 }, firstColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 13, buttonHeight - 10 }, { buttonWidth - 12, buttonHeight - 11 }, secondColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 11, buttonHeight - 12 }, { buttonWidth - 10, buttonHeight - 13 }, lastColor ); fheroes2::DrawLine( buttonImage, { buttonWidth - 16, buttonHeight - 5 }, { buttonWidth - 12, buttonHeight - 9 }, secondColor ); fheroes2::SetPixel( buttonImage, buttonWidth - 11, buttonHeight - 10, lastColor ); } } } } void getButtonSpecificValues( const int emptyButtonIcnID, fheroes2::FontColor & font, fheroes2::Point & textAreaBorders, fheroes2::Size & minimumTextArea, fheroes2::Size & maximumTextArea, fheroes2::Size & backgroundBorders, fheroes2::Point & releasedOffset, fheroes2::Point & pressedOffset ) { switch ( emptyButtonIcnID ) { case ICN::EMPTY_GOOD_BUTTON: font = fheroes2::FontColor::WHITE; textAreaBorders.x = 4 + 4; textAreaBorders.y = 1 + 1; // The minimum text area width for Good campaign buttons is 86 judging from the shared widths of the // original OKAY and the CANCEL buttons even though OKAY is a shorter word minimumTextArea.width = 86; maximumTextArea.height = 50; backgroundBorders.width = 6 + 4; backgroundBorders.height = 4 + 4; releasedOffset = { 6, 4 }; pressedOffset = { 5, 5 }; break; case ICN::EMPTY_EVIL_BUTTON: font = fheroes2::FontColor::GRAY; textAreaBorders.x = 4 + 4; textAreaBorders.y = 1 + 1; minimumTextArea.width = 87; maximumTextArea.height = 50; backgroundBorders.width = 6 + 3; backgroundBorders.height = 4 + 4; releasedOffset = { 6, 4 }; pressedOffset = { 5, 5 }; break; // TODO: POL buttons are just EVIL campaign theme buttons. With some adjustments, the POL button code can be removed. case ICN::EMPTY_POL_BUTTON: font = fheroes2::FontColor::GRAY; textAreaBorders.x = 4 + 4; textAreaBorders.y = 2 + 1; minimumTextArea.width = 87; // The empty POL button is 24 pixels tall. This does not divide evenly by 5, so we force it to be 24 pixels tall. // (2 + 1) + 15 = 18 -> 18 + (3 + 3) = 24 minimumTextArea.height = 18; maximumTextArea.height = 18; backgroundBorders.width = 4 + 3; backgroundBorders.height = 3 + 3; releasedOffset = { 4, 4 }; pressedOffset = { 3, 5 }; break; case ICN::EMPTY_GUILDWELL_BUTTON: font = fheroes2::FontColor::WHITE; textAreaBorders.x = 2 + 2; textAreaBorders.y = 0 + 0; minimumTextArea.width = 53; minimumTextArea.height = 13; maximumTextArea.height = 14; backgroundBorders.width = 5 + 3; backgroundBorders.height = 2 + 3; releasedOffset = { 4, 2 }; pressedOffset = { 3, 3 }; break; case ICN::EMPTY_VERTICAL_GOOD_BUTTON: font = fheroes2::FontColor::WHITE; textAreaBorders.x = 0 + 0; textAreaBorders.y = 2 + 2; minimumTextArea.width = 19; minimumTextArea.height = 110; // TODO: Currently the empty vertical button has a width of 28 which is not evenly dividable by 3 in resizeButton(). // It should be widened by 1 px to allow for widening. maximumTextArea.width = 19; backgroundBorders.width = 5 + 4; backgroundBorders.height = 4 + 6; releasedOffset = { 5, 5 }; pressedOffset = { 4, 6 }; break; case ICN::EMPTY_MAP_SELECT_BUTTON: font = fheroes2::FontColor::WHITE; textAreaBorders.x = 2 + 2; textAreaBorders.y = 1 + 0; minimumTextArea.width = 60; minimumTextArea.height = 13; maximumTextArea.height = 14; backgroundBorders.width = 6 + 3; backgroundBorders.height = 2 + 3; releasedOffset = { 6, 3 }; pressedOffset = { 5, 4 }; break; default: // Was a new empty button template added? assert( 0 ); break; } } } namespace fheroes2 { bool ButtonBase::press() { if ( !isEnabled() ) { return false; } _isPressed = true; notifySubscriber(); return true; } bool ButtonBase::release() { if ( !isEnabled() ) { return false; } _isPressed = false; notifySubscriber(); return true; } void ButtonBase::enable() { _isEnabled = true; notifySubscriber(); _updateReleasedArea(); } void ButtonBase::disable() { _isEnabled = false; _isPressed = false; // button can't be disabled and pressed notifySubscriber(); _updateReleasedArea(); } void ButtonBase::show() { _isVisible = true; notifySubscriber(); } void ButtonBase::hide() { _isVisible = false; notifySubscriber(); } bool ButtonBase::draw( Image & output ) const { if ( !isVisible() ) { return false; } if ( isPressed() ) { // button can't be disabled and pressed const Sprite & sprite = _getPressed(); Blit( sprite, output, _areaPressed ); } else { const Sprite & sprite = isEnabled() ? _getReleased() : _getDisabled(); Blit( sprite, output, _areaReleased ); } return true; } bool ButtonBase::drawOnPress( Display & output /* = Display::instance() */ ) { if ( isPressed() ) { return false; } if ( !press() ) { return false; } if ( isVisible() ) { draw( output ); output.render( area() ); } return true; } bool ButtonBase::drawOnRelease( Display & output /* = Display::instance() */ ) { if ( !isPressed() ) { return false; } if ( !release() ) { return false; } if ( isVisible() ) { draw( output ); output.render( area() ); } return true; } const Sprite & ButtonBase::_getDisabled() const { const Sprite & sprite = _getReleased(); if ( !_disabledSprite || ( _releasedSprite != &sprite ) ) { _releasedSprite = &sprite; _disabledSprite.reset( new Sprite( sprite ) ); ApplyPalette( *_disabledSprite, PAL::GetPalette( PAL::PaletteType::DARKENING ) ); } return *_disabledSprite; } const Sprite & Button::_getPressed() const { return AGG::GetICN( _icnId, _pressedIndex ); } const Sprite & Button::_getReleased() const { return AGG::GetICN( _icnId, _releasedIndex ); } const Sprite & ButtonSprite::_getPressed() const { return _pressed; } const Sprite & ButtonSprite::_getReleased() const { return _released; } const Sprite & ButtonSprite::_getDisabled() const { if ( _disabled.empty() ) { return ButtonBase::_getDisabled(); } return _disabled; } ButtonGroup::ButtonGroup( const Rect & area /* = Rect() */, const int buttonTypes /* = 0 */ ) { const bool isEvilInterface = Settings::Get().isEvilInterfaceEnabled(); const int buttonYesIcnID = isEvilInterface ? ICN::BUTTON_SMALL_YES_EVIL : ICN::BUTTON_SMALL_YES_GOOD; const int buttonNoIcnID = isEvilInterface ? ICN::BUTTON_SMALL_NO_EVIL : ICN::BUTTON_SMALL_NO_GOOD; const int buttonOkayIcnID = isEvilInterface ? ICN::UNIFORM_EVIL_OKAY_BUTTON : ICN::UNIFORM_GOOD_OKAY_BUTTON; const int buttonCancelIcnID = isEvilInterface ? ICN::UNIFORM_EVIL_CANCEL_BUTTON : ICN::UNIFORM_GOOD_CANCEL_BUTTON; Point offset; switch ( buttonTypes ) { case Dialog::YES | Dialog::NO: { const Sprite & yesButtonSprite = AGG::GetICN( buttonYesIcnID, 0 ); const Sprite & noButtonSprite = AGG::GetICN( buttonNoIcnID, 0 ); const int32_t horizontalFreeSpace = area.width - yesButtonSprite.width() - noButtonSprite.width(); const int32_t padding = horizontalFreeSpace / 4; assert( horizontalFreeSpace > 0 ); offset.x = area.x + padding; offset.y = area.y + area.height - yesButtonSprite.height(); createButton( offset.x, offset.y, buttonYesIcnID, 0, 1, Dialog::YES ); offset.x = area.x + area.width - noButtonSprite.width() - padding; offset.y = area.y + area.height - noButtonSprite.height(); createButton( offset.x, offset.y, buttonNoIcnID, 0, 1, Dialog::NO ); break; } case Dialog::OK | Dialog::CANCEL: { const Sprite & okayButtonSprite = AGG::GetICN( buttonOkayIcnID, 0 ); const Sprite & cancelButtonSprite = AGG::GetICN( buttonCancelIcnID, 0 ); const int32_t horizontalFreeSpace = area.width - okayButtonSprite.width() - cancelButtonSprite.width(); const int32_t padding = horizontalFreeSpace / 4; assert( horizontalFreeSpace > 0 ); offset.x = area.x + padding; offset.y = area.y + area.height - okayButtonSprite.height(); createButton( offset.x, offset.y, buttonOkayIcnID, 0, 1, Dialog::OK ); offset.x = area.x + area.width - cancelButtonSprite.width() - padding; offset.y = area.y + area.height - cancelButtonSprite.height(); createButton( offset.x, offset.y, buttonCancelIcnID, 0, 1, Dialog::CANCEL ); break; } case Dialog::OK: { const Sprite & okayButtonSprite = AGG::GetICN( buttonOkayIcnID, 0 ); offset.x = area.x + ( area.width - okayButtonSprite.width() ) / 2; offset.y = area.y + area.height - okayButtonSprite.height(); createButton( offset.x, offset.y, buttonOkayIcnID, 0, 1, Dialog::OK ); break; } case Dialog::CANCEL: { const Sprite & cancelButtonSprite = AGG::GetICN( buttonCancelIcnID, 0 ); offset.x = area.x + ( area.width - cancelButtonSprite.width() ) / 2; offset.y = area.y + area.height - cancelButtonSprite.height(); createButton( offset.x, offset.y, buttonCancelIcnID, 0, 1, Dialog::CANCEL ); break; } default: break; } } void ButtonGroup::createButton( const int32_t offsetX, const int32_t offsetY, const int icnId, const uint32_t releasedIndex, const uint32_t pressedIndex, const int returnValue ) { _button.push_back( std::make_unique